def __init__(self, env, x_init, min_dist=.3, nfourier=20, t_horizon=2, t_history=0, mode='mi', gui=True): self.x = x_init self.bounds = env.bounds self.u_max = env.get_u_max() self.min_dist = min_dist self.nfourier = nfourier self.t_horizon = t_horizon self.nagents = x_init.shape[0] self.tp_rate = env.tp_rate self.fp_rate = env.fp_rate self.u = [np.zeros((2, t_horizon)) for i in range(self.nagents)] K1, K2 = np.meshgrid(np.arange(nfourier), np.arange(nfourier), indexing='ij') self.k1 = K1.flatten() * np.pi self.k2 = K2.flatten() * np.pi self.hk = np.ones(self.k1.shape[0]) self.hk[self.k1 != 0] *= np.sqrt(.5) self.hk[self.k2 != 0] *= np.sqrt(.5) s = (2 + 1) / 2 self.Lambdak = (1 + np.square(self.k1) + np.square(self.k2))**(-s) self.t_history = t_history self.ck_history_cum = [] r = env.target_r + env.view_r npix = int(np.ceil(r / env.grid_dx) * 2 + 1) reg = CirclePixelRegion(center=PixCoord(npix, npix), radius=r / env.grid_dx) self.footprint_mask = reg.to_mask(mode='exact').data self.image1 = None self.image2 = None self.lines = None # self.change_paramt0 = 5 # self.change_param = .01 self.change_paramt0 = .1 self.change_param = .01 self.mode = mode self.gui = gui
def makeMask(xs, ys, radius, cenx, ceny): shape = (xs, ys) fin_mask = np.zeros(shape) print(radius) for i in np.arange(len(cenx)): if radius[i] > 5: radius[i] = 6 center = PixCoord(cenx[i], ceny[i]) circle = CirclePixelRegion(center, radius[i] - 1) mask = circle.to_mask() newmask = mask.to_image(shape) fin_mask += newmask fin_mask[fin_mask > 1] = 1 return fin_mask
def fftMask(sciImg, wavel_lambda, plateScale): # sciImg: this is actually the FFT image, not the science detector image # wavel_lambda: wavelenth of the observation # plateScale: plate scale of the detector (asec/pixel) # make division lines separating different parts of the PSF line_M1diam_pixOnFFT = findFFTloc(8.25, np.shape(sciImg)[0], wavel_lambda, plateScale) line_center2center_pixOnFFT = findFFTloc(14.4, np.shape(sciImg)[0], wavel_lambda, plateScale) line_edge2edge_pixOnFFT = findFFTloc(22.65, np.shape(sciImg)[0], wavel_lambda, plateScale) # define circles circRad = 60 # pixels in FFT space circle_highFreqPerfect_L = CirclePixelRegion(center=PixCoord( x=line_center2center_pixOnFFT[0], y=0.5 * np.shape(sciImg)[0]), radius=circRad) circle_highFreqPerfect_R = CirclePixelRegion(center=PixCoord( x=line_center2center_pixOnFFT[1], y=0.5 * np.shape(sciImg)[0]), radius=circRad) circle_lowFreqPerfect = CirclePixelRegion(center=PixCoord( x=0.5 * np.shape(sciImg)[1], y=0.5 * np.shape(sciImg)[0]), radius=circRad) # define central rectangular region that includes all three nodes rect_pix = PolygonPixelRegion( vertices=PixCoord(x=[ line_edge2edge_pixOnFFT[0], line_edge2edge_pixOnFFT[1], line_edge2edge_pixOnFFT[1], line_edge2edge_pixOnFFT[0] ], y=[ line_M1diam_pixOnFFT[1], line_M1diam_pixOnFFT[1], line_M1diam_pixOnFFT[0], line_M1diam_pixOnFFT[0] ])) # make the masks mask_circHighFreq_L = circle_highFreqPerfect_L.to_mask() mask_circHighFreq_R = circle_highFreqPerfect_R.to_mask() mask_circLowFreq = circle_lowFreqPerfect.to_mask() mask_rect = rect_pix.to_mask() # apply the masks sciImg1 = np.copy( sciImg) # initialize arrays of same size as science image sciImg2 = np.copy(sciImg) sciImg3 = np.copy(sciImg) sciImg4 = np.copy(sciImg) # region 1 sciImg1.fill(np.nan) # initialize arrays of nans mask_circHighFreq_L.data[ mask_circHighFreq_L.data == 0] = np.nan # make zeros within mask cutout (but not in the mask itself) nans sciImg1[ mask_circHighFreq_L.bbox. slices] = mask_circHighFreq_L.data # place the mask cutout (consisting only of 1s) onto the array of nans sciImg1 = np.multiply( sciImg1, sciImg) # 'transmit' the original science image through the mask # region 2 sciImg2.fill(np.nan) # initialize arrays of nans mask_circHighFreq_R.data[ mask_circHighFreq_R.data == 0] = np.nan # make zeros within mask cutout (but not in the mask itself) nans sciImg2[ mask_circHighFreq_R.bbox. slices] = mask_circHighFreq_R.data # place the mask cutout (consisting only of 1s) onto the array of nans sciImg2 = np.multiply( sciImg2, sciImg) # 'transmit' the original science image through the mask # region 3 sciImg3.fill(np.nan) # initialize arrays of nans mask_circLowFreq.data[ mask_circLowFreq.data == 0] = np.nan # make zeros within mask cutout (but not in the mask itself) nans sciImg3[ mask_circLowFreq.bbox. slices] = mask_circLowFreq.data # place the mask cutout (consisting only of 1s) onto the array of nans sciImg3 = np.multiply( sciImg3, sciImg) # 'transmit' the original science image through the mask # region 4 sciImg4.fill(np.nan) # initialize arrays of nans mask_rect.data[ mask_rect.data == 0] = np.nan # make zeros within mask cutout (but not in the mask itself) nans sciImg4[ mask_rect.bbox. slices] = mask_rect.data # place the mask cutout (consisting only of 1s) onto the array of nans sciImg4 = np.multiply( sciImg4, sciImg) # 'transmit' the original science image through the mask # return medians of regions under masks med_highFreqPerfect_L = np.nanmedian(sciImg1) med_highFreqPerfect_R = np.nanmedian(sciImg2) med_lowFreqPerfect = np.nanmedian(sciImg3) med_rect = np.nanmedian(sciImg4) # return normal vectors corresponding to [x,y,z] to surfaces (x- and y- components are of interest) normVec_highFreqPerfect_L = normalVector(sciImg1) normVec_highFreqPerfect_R = normalVector(sciImg2) normVec_lowFreqPerfect = normalVector(sciImg3) normVec_rect = normalVector(sciImg4) # generate images showing footprints of regions of interest # (comment this bit in/out as desired) ''' plt.imshow(sciImg1, origin='lower') plt.show() plt.imshow(sciImg2, origin='lower') plt.show() plt.imshow(sciImg3, origin='lower') plt.show() plt.imshow(sciImg4, origin='lower') plt.show() plt.clf() fig = plt.figure() ax = fig.add_subplot(1, 1, 1) cax = ax.imshow(sciImg, origin="lower") ax.axhline(line_M1diam_pixOnFFT[0]) ax.axhline(line_M1diam_pixOnFFT[1]) ax.axvline(line_M1diam_pixOnFFT[0]) ax.axvline(line_M1diam_pixOnFFT[1]) ax.axvline(line_center2center_pixOnFFT[0]) ax.axvline(line_center2center_pixOnFFT[1]) ax.axvline(line_edge2edge_pixOnFFT[0]) ax.axvline(line_edge2edge_pixOnFFT[1]) ax.add_patch(circle_highFreqPerfect_L.as_patch(facecolor='none', edgecolor='blue')) ax.add_patch(circle_highFreqPerfect_R.as_patch(facecolor='none', edgecolor='blue')) ax.add_patch(circle_lowFreqPerfect.as_patch(facecolor='none', edgecolor='blue')) ax.add_patch(rect_pix.as_patch(facecolor='none', edgecolor='red')) cbar = fig.colorbar(cax) plt.savefig("junk.pdf") ''' dictFFTstuff = {} dictFFTstuff["med_highFreqPerfect_L"] = med_highFreqPerfect_L dictFFTstuff["med_highFreqPerfect_R"] = med_highFreqPerfect_R dictFFTstuff["med_lowFreqPerfect"] = med_lowFreqPerfect dictFFTstuff["med_rect"] = med_rect # note vectors are [a,b,c] corresponding to the eqn Z = a*X + b*Y + c dictFFTstuff["normVec_highFreqPerfect_L"] = normVec_highFreqPerfect_L dictFFTstuff["normVec_highFreqPerfect_R"] = normVec_highFreqPerfect_R dictFFTstuff["normVec_lowFreqPerfect"] = normVec_lowFreqPerfect dictFFTstuff["normVec_rect"] = normVec_rect return dictFFTstuff
def __call__(self, abs_sci_name): ''' PCA-based background subtraction, for a single frame so as to parallelize job INPUTS: abs_sci_name: science array filename ''' # start the timer start_time = time.time() # read in the science frame from raw data directory sciImg, header_sci = fits.getdata(abs_sci_name, 0, header=True) # apply mask over weird detector regions to science image sciImg = np.multiply(sciImg, make_first_pass_mask(self.quad_choice)) ## mask the PSF # define region psf_loc = find_airy_psf(sciImg) # center of science PSF print("PSF location in " + os.path.basename(abs_sci_name) + ": [" + str(psf_loc[0]) + ", " + str(psf_loc[1]) + "]") radius = 30. # radius around PSF that will be masked center = PixCoord(x=psf_loc[1], y=psf_loc[0]) region = CirclePixelRegion(center, radius) mask_psf_region = region.to_mask() # apply the mask to science array psf_mask = np.ones(np.shape( sciImg)) # initialize arrays of same size as science image mask_psf_region.data[ mask_psf_region.data == 1] = np.nan # make zeros within mask cutout (but not in the mask itself) nans mask_psf_region.data[mask_psf_region.data == 0] = 1 ##mask_psf_region.data[mask_psf_region.data == -99999] = 0 # have to avoid nans in the linear algebra psf_mask[ mask_psf_region.bbox. slices] = mask_psf_region.data # place the mask cutout (consisting only of 1s) onto the array of nans # I don't know why, but the sciImg nans in weird detector regions become zeros by this point, and I want them to stay nans # so, re-apply the mask over the bad regions of the detector sciImg = np.multiply(sciImg, make_first_pass_mask(self.quad_choice)) sciImg_masked = np.multiply( sciImg, psf_mask) # this is now the masked science frame # subtract the median (just a constant) from the remaining science image sciImg_psf_masked = np.subtract( sciImg_masked, np.nanmedian(sciImg_masked)) # where PSF is masked sciImg_psf_not_masked = np.subtract( sciImg, np.nanmedian(sciImg_masked)) # where PSF is not masked # apply the PSF mask to PCA slices, with which we will do the fitting pca_cube_masked = np.multiply(self.pca_cube, psf_mask) ## PCA-decompose # flatten the science array and PCA cube pca_not_masked_1ds = np.reshape( self.pca_cube, (np.shape(self.pca_cube)[0], np.shape(self.pca_cube)[1] * np.shape(self.pca_cube)[2])) sci_masked_1d = np.reshape( sciImg_psf_masked, (np.shape(sciImg_masked)[0] * np.shape(sciImg_masked)[1])) pca_masked_1ds = np.reshape( pca_cube_masked, (np.shape(pca_cube_masked)[0], np.shape(pca_cube_masked)[1] * np.shape(pca_cube_masked)[2])) ## remove nans from the linear algebra # indices of finite elements over a single flattened frame idx = np.logical_and(np.isfinite(pca_masked_1ds[0, :]), np.isfinite(sci_masked_1d)) # reconstitute only the finite elements together in another PCA cube and a science image pca_masked_1ds_noNaN = np.nan * np.ones( (len(pca_masked_1ds[:, 0]), np.sum(idx)) ) # initialize array with slices the length of number of finite elements for t in range( 0, len(pca_masked_1ds[:, 0]) ): # for each PCA component, populate the arrays without nans with the finite elements pca_masked_1ds_noNaN[t, :] = pca_masked_1ds[t, idx] sci_masked_1d_noNaN = np.array(1, np.sum(idx)) # science frame sci_masked_1d_noNaN = sci_masked_1d[idx] # the vector of component amplitudes soln_vector = np.linalg.lstsq(pca_masked_1ds_noNaN[0:self.n_PCA, :].T, sci_masked_1d_noNaN) # reconstruct the background based on that vector # note that the PCA components WITHOUT masking of the PSF location is being # used to reconstruct the background recon_backgrnd_2d = np.dot(self.pca_cube[0:self.n_PCA, :, :].T, soln_vector[0]).T # now do the same, but for the channel bias variation contributions only (assumes 32 elements only) recon_backgrnd_2d_channels_only_no_psf_masking = np.dot( self.pca_cube[0:32, :, :].T, soln_vector[0][0:32]).T # without PSF masking recon_backgrnd_2d_channels_only_psf_masked = np.dot( self.pca_cube[0:32, :, :].T, soln_vector[0][0:32]).T # with PSF masking # do the actual subtraction: # all-background subtraction sciImg_subtracted = np.subtract(sciImg_psf_not_masked, recon_backgrnd_2d) # background subtraction of channels only: # without PSF masking #sciImg_subtracted_channels_only_no_psf_masking = np.subtract(sciImg_psf_not_masked,recon_backgrnd_2d_channels_only) # with PSF masking sciImg_subtracted_channels_only_psf_masked = np.subtract( sciImg_psf_masked, np.multiply(recon_backgrnd_2d_channels_only_psf_masked, np.multiply(self.pca_cube, psf_mask))) # add last reduction step to header header_sci["RED_STEP"] = "pca_background_subtracted" # save reconstructed background for checking abs_recon_bkgd = str(self.config_data["data_dirs"]["DIR_OTHER_FITS"] + 'recon_bkgd_quad_' + str("{:0>2d}".format(self.quad_choice)) + '_PCAseqStart_' + str("{:0>6d}".format(self.cube_start_framenum)) + '_PCAseqStop_' + str("{:0>6d}".format(self.cube_stop_framenum)) + '_' + os.path.basename(abs_sci_name)) fits.writeto(filename=abs_recon_bkgd, data=recon_backgrnd_2d, overwrite=True) # save masked science frame BEFORE background-subtraction abs_masked_sci_before_bkd_subt = str( self.config_data["data_dirs"]["DIR_OTHER_FITS"] + 'masked_sci_before_bkd_subt_quad_' + str("{:0>2d}".format(self.quad_choice)) + '_PCAseqStart_' + str("{:0>6d}".format(self.cube_start_framenum)) + '_PCAseqStop_' + str("{:0>6d}".format(self.cube_stop_framenum)) + os.path.basename(abs_sci_name)) fits.writeto(filename=abs_masked_sci_before_bkd_subt, data=sciImg_psf_masked, overwrite=True) # save masked, background-subtracted science frame background_subtracted_masked = np.multiply( sciImg_subtracted, make_first_pass_mask(self.quad_choice)) background_subtracted_masked = np.multiply( background_subtracted_masked, psf_mask) abs_masked_sci_after_bkd_subt = str( self.config_data["data_dirs"]["DIR_OTHER_FITS"] + 'masked_sci_after_bkd_subt_quad_' + str("{:0>2d}".format(self.quad_choice)) + '_PCAseqStart_' + str("{:0>6d}".format(self.cube_start_framenum)) + '_PCAseqStop_' + str("{:0>6d}".format(self.cube_stop_framenum)) + os.path.basename(abs_sci_name)) fits.writeto(filename=abs_masked_sci_after_bkd_subt, data=background_subtracted_masked, overwrite=True) # save background-subtracted science frame sciImg_subtracted_name = str( self.config_data["data_dirs"]["DIR_PCAB_SUBTED"] + os.path.basename(abs_sci_name)) fits.writeto(filename=sciImg_subtracted_name, data=sciImg_subtracted, header=header_sci, overwrite=True) print('Background-subtracted frame ' + os.path.basename(abs_sci_name) + ' written out. PCA = ' + str(self.n_PCA)) ## make FYI plots of the effectiveness of the background subtraction # (N.b. the PSF and weird detector regions are masked here) self.vital_stats(file_base_name=str(os.path.basename(abs_sci_name)), sci_img_pre=sciImg_masked, sci_img_post_channel_subt= sciImg_subtracted_channels_only_psf_masked, sci_img_post_all_subt=background_subtracted_masked, pca_spec=soln_vector[0]) print('Elapsed time:') elapsed_time = time.time() - start_time print('--------------------------------------------------------------') print(elapsed_time)
def fftMask(sciImg,wavel_lambda,plateScale,fyi_string=''): ''' Take a FFT image, generate masks to select interesting areas of the FFT, and return data about those areas (amplitudes, normal vectors, etc.) INPUTS: sciImg: this is actually the FFT image, not the science detector image wavel_lambda: wavelength of the observation plateScale: plate scale of the detector (asec/pixel) fyi_string: an FYI string that could be used for plots OUTPUTS: dictFFTstuff: dictionary with keys corresponding to different parts of the FFT ''' # make division lines separating different parts of the PSF line_M1diam_pixOnFFT = findFFTloc(D,np.shape(sciImg)[0],wavel_lambda,plateScale) line_center2center_pixOnFFT = findFFTloc(B_c2c,np.shape(sciImg)[0],wavel_lambda,plateScale) line_edge2edge_pixOnFFT = findFFTloc(B_e2e,np.shape(sciImg)[0],wavel_lambda,plateScale) # define circles circRad = 60 # pixels in FFT space circle_highFreqPerfect_L = CirclePixelRegion(center=PixCoord(x=line_center2center_pixOnFFT[0], y=0.5*np.shape(sciImg)[0]), radius=circRad) circle_highFreqPerfect_R = CirclePixelRegion(center=PixCoord(x=line_center2center_pixOnFFT[1], y=0.5*np.shape(sciImg)[0]), radius=circRad) circle_lowFreqPerfect = CirclePixelRegion(center=PixCoord(x=0.5*np.shape(sciImg)[1], y=0.5*np.shape(sciImg)[0]), radius=circRad) # define central rectangular region that includes all three nodes rect_pix = PolygonPixelRegion(vertices=PixCoord(x=[line_edge2edge_pixOnFFT[0],line_edge2edge_pixOnFFT[1],line_edge2edge_pixOnFFT[1],line_edge2edge_pixOnFFT[0]], y=[line_M1diam_pixOnFFT[1],line_M1diam_pixOnFFT[1],line_M1diam_pixOnFFT[0],line_M1diam_pixOnFFT[0]])) # make the masks mask_circHighFreq_L = circle_highFreqPerfect_L.to_mask() mask_circHighFreq_R = circle_highFreqPerfect_R.to_mask() mask_circLowFreq = circle_lowFreqPerfect.to_mask() mask_rect = rect_pix.to_mask() ## apply the masks # initialize arrays of same size as science image sciImg1 = np.copy(sciImg) sciImg2 = np.copy(sciImg) sciImg3 = np.copy(sciImg) sciImg4 = np.copy(sciImg) # region 1: high-freq lobe, left sciImg1.fill(np.nan) # initialize arrays of nans mask_circHighFreq_L.data[mask_circHighFreq_L.data == 0] = np.nan # make zeros within mask cutout (but not in the mask itself) nans sciImg1[mask_circHighFreq_L.bbox.slices] = mask_circHighFreq_L.data # place the mask cutout (consisting only of 1s) onto the array of nans sciImg1 = np.multiply(sciImg1,sciImg) # 'transmit' the original science image through the mask sciImg1 = sciImg1.filled(fill_value=np.nan) # turn all masked '--' elements to nans # region 2: high-freq lobe, right sciImg2.fill(np.nan) # initialize arrays of nans mask_circHighFreq_R.data[mask_circHighFreq_R.data == 0] = np.nan # make zeros within mask cutout (but not in the mask itself) nans sciImg2[mask_circHighFreq_R.bbox.slices] = mask_circHighFreq_R.data # place the mask cutout (consisting only of 1s) onto the array of nans sciImg2 = np.multiply(sciImg2,sciImg) # 'transmit' the original science image through the mask sciImg2 = sciImg2.filled(fill_value=np.nan) # turn all masked '--' elements to nans # region 3: low-freq lobe sciImg3.fill(np.nan) # initialize arrays of nans mask_circLowFreq.data[mask_circLowFreq.data == 0] = np.nan # make zeros within mask cutout (but not in the mask itself) nans sciImg3[mask_circLowFreq.bbox.slices] = mask_circLowFreq.data # place the mask cutout (consisting only of 1s) onto the array of nans sciImg3 = np.multiply(sciImg3,sciImg) # 'transmit' the original science image through the mask sciImg3 = sciImg3.filled(fill_value=np.nan) # turn all masked '--' elements to nans # region 4: rectangular region containing parts of all lobes sciImg4.fill(np.nan) # initialize arrays of nans mask_rect.data[mask_rect.data == 0] = np.nan # make zeros within mask cutout (but not in the mask itself) nans sciImg4[mask_rect.bbox.slices] = mask_rect.data # place the mask cutout (consisting only of 1s) onto the array of nans sciImg4 = np.multiply(sciImg4,sciImg) # 'transmit' the original science image through the mask sciImg4 = sciImg4.filled(fill_value=np.nan) # turn all masked '--' elements to nans # return medians of regions under masks med_highFreqPerfect_L = np.nanmedian(sciImg1) med_highFreqPerfect_R = np.nanmedian(sciImg2) med_lowFreqPerfect = np.nanmedian(sciImg3) med_rect = np.nanmedian(sciImg4) # return normal vectors corresponding to [x,y,z] to surfaces (x- and y- components are of interest) normVec_highFreqPerfect_L = normalVector(sciImg1) normVec_highFreqPerfect_R = normalVector(sciImg2) normVec_lowFreqPerfect = normalVector(sciImg3) normVec_rect = normalVector(sciImg4) # return stdev in each region std_highFreqPerfect_L = np.nanstd(sciImg1) std_highFreqPerfect_R = np.nanstd(sciImg2) std_lowFreqPerfect = np.nanstd(sciImg3) std_rect = np.nanstd(sciImg4) # generate images showing footprints of regions of interest # (comment this bit in/out as desired) # initialize dictionary to contain FFT data # N.b. all the info in this dictionary is EITHER for # the FFT amplitude OR the FFT phase, depending on what # the 'sciImg' is dictFFTstuff = {} # median of high-freq lobe on left side, within circular region centered around # where a perfect high-freq lobe would be dictFFTstuff["med_highFreqPerfect_L"] = med_highFreqPerfect_L # median of right-side high-freq lobe dictFFTstuff["med_highFreqPerfect_R"] = med_highFreqPerfect_R # median of low-frequency lobe dictFFTstuff["med_lowFreqPerfect"] = med_lowFreqPerfect # median of rectangle that is drawn to contain both high- and low-freq lobes dictFFTstuff["med_rect"] = med_rect # stdev of the same regions dictFFTstuff["std_highFreqPerfect_L"] = std_highFreqPerfect_L # median of right-side high-freq lobe dictFFTstuff["std_highFreqPerfect_R"] = std_highFreqPerfect_R # median of low-frequency lobe dictFFTstuff["std_lowFreqPerfect"] = std_lowFreqPerfect # median of rectangle that is drawn to contain both high- and low-freq lobes dictFFTstuff["std_rect"] = std_rect # normal vectors to the high- and low- frequency # note vectors are [a,b,c] corresponding to the eqn Z = a*X + b*Y + c dictFFTstuff["normVec_highFreqPerfect_L"] = normVec_highFreqPerfect_L dictFFTstuff["normVec_highFreqPerfect_R"] = normVec_highFreqPerfect_R dictFFTstuff["normVec_lowFreqPerfect"] = normVec_lowFreqPerfect dictFFTstuff["normVec_rect"] = normVec_rect return dictFFTstuff