# Copyright (C) 2019 ETH Zurich, Institute for Particle and Astrophysics"""Created on Feb 5, 2019author: Joerg Herbel"""importnumbaasnbimportnumpyasnp
[docs]defdecimal_integer_to_binary(n_bits,arr_decimal,dtype_out):""" Transform a one-dimensional array of decimal integers into its binary representation. Returns an array with the shape (len(arr_decimal), n_bits). To reconstruct arr_decimal[i], one would perform the operation arr_decimal[i] = np.sum(2**np.arange(n_bits) * arr_binary[i]) This means that this binary representation is reversed with respect to what is normally used. For example, normally, 1100 = 1 * 2**3 + 1 * 2**2 + 0 * 2**1 + 0 * 2**0. However, here we have 1100 = 1 * 2**0 + 1 * 2**1 + 0 * 2**2 + 0 * 2**3. ATTENTION: THIS FUNCTION MODIFIES ARR_DECIMAL IN PLACE! """arr_binary=np.zeros((len(arr_decimal),n_bits),dtype=dtype_out)arr_decimal=arr_decimal.astype(dtype_out)foriinrange(n_bits):arr_binary[:,i]=arr_decimal%np.uint(2)arr_decimal//=np.uint(2)returnarr_binary
[docs]defget_binary_mask_dtype(n_bits):fordtypein[np.uint8,np.uint16,np.uint32,np.uint64]:ifnp.iinfo(dtype).max>=n_bits:returndtyperaiseValueError(f"Number of bits {n_bits} exceeding maximum possible value such that np.uint"" dtype can be used")
[docs]defset_masked_pixels(pixel_mask,maskbits_keep,n_bits):""" Set pixels which are masked according to input bits. This function modifies pixel_mask in-place. :param pixel_mask: mask :param maskbits_keep: mask bits to keep :param n_bits: ... :return: mask with only bits to keep switched on (same shape as input mask) """pixel_mask=pixel_mask.copy()# special case of no maskingiflen(maskbits_keep)==0:returnpixel_mask*0# transform to binary representationpixel_mask_bin=decimal_integer_to_binary(n_bits,np.ravel(pixel_mask),dtype_out=get_binary_mask_dtype(n_bits))# select bits to keeppixel_mask_bin=pixel_mask_bin[:,maskbits_keep]# transform back to original shapepixel_mask_keep=np.sum(pixel_mask_bin,axis=1).reshape(pixel_mask.shape)returnpixel_mask_keep
[docs]@nb.jit(nopython=True)defselect_off_mask(xs,ys,rs,mask):# Array holding resultsselect_off=np.ones(len(xs),dtype=np.int8)# Compute coordinates to be checkedx_min=np.floor(xs-rs).astype(np.int32)y_min=np.floor(ys-rs).astype(np.int32)x_max=np.ceil(xs+rs).astype(np.int32)y_max=np.ceil(ys+rs).astype(np.int32)x_min=np.maximum(x_min,0)y_min=np.maximum(y_min,0)x_max=np.minimum(x_max,mask.shape[1])y_max=np.minimum(y_max,mask.shape[0])rs_sq=rs**2foriinrange(len(xs)):x=xs[i]y=ys[i]r_sq=rs_sq[i]forxiinrange(x_min[i],x_max[i]):foryiinrange(y_min[i],y_max[i]):delta=(xi-x)**2+(yi-y)**2ifdelta<r_sqandmask[int(yi),int(xi)]>0:select_off[i]=0breakifselect_off[i]==0:breakreturnselect_off