def polygon_pix_pts2polygon_sky_reg(polygon_points, wcs): x_coord = polygon_points[:, 0] y_coord = polygon_points[:, 1] polygon_pix_reg = PolygonPixelRegion( vertices=PixCoord(x=x_coord, y=y_coord)) polygon_sky_reg = polygon_pix_reg.to_sky(wcs) return polygon_sky_reg
def find_sky_region(mask, wcs): '''create a region object from a mask and wcs Returns: reg_pix : PixelRegion reg_sky : SkyRegion ''' mask[:, [0, -1]] = 1 mask[[0, -1], :] = 1 # find the contours around the image to use as vertices for the PixelRegion contours = find_contours( mask, 0.5, ) # we use the region with the most vertices coords = max(contours, key=len) #coords = np.concatenate(contours) # the coordinates from find_counters are switched compared to astropy reg_pix = PolygonPixelRegion(vertices=PixCoord(*coords.T[::-1])) reg_sky = reg_pix.to_sky(wcs) return reg_pix, reg_sky
def to_object(self, subset): data = subset.data if data.ndim != 2: raise NotImplementedError("Can only handle 2-d datasets at this time") subset_state = subset.subset_state if isinstance(subset_state, RoiSubsetState): if subset_state.xatt != data.pixel_component_ids[1]: raise ValueError('subset state xatt should be x pixel coordinate') if subset_state.yatt != data.pixel_component_ids[0]: raise ValueError('subset state yatt should be y pixel coordinate') roi = subset_state.roi if isinstance(roi, RectangularROI): xcen = 0.5 * (roi.xmin + roi.xmax) ycen = 0.5 * (roi.ymin + roi.ymax) width = roi.xmax - roi.xmin height = roi.ymax - roi.ymin return RectanglePixelRegion(PixCoord(xcen, ycen), width, height) elif isinstance(roi, PolygonalROI): return PolygonPixelRegion(PixCoord(roi.vx, roi.vy)) else: raise NotImplementedError("ROIs of type {0} are not yet supported".format(roi.__class__.__name__)) else: raise NotImplementedError("Subset states of type {0} are not supported".format(subset_state.__class__.__name__))
def dagga(field): "function to tag sources for dd calibration, very smoky" key = 'calibrate_dd' #make a skymodel with only dE taggable sources. #de_only_model = 'de-only-model.txt' de_sources_mode = config[key]['de_sources_mode'] print("de_sources_mode:", de_sources_mode) # if usepb: # model_cube = prefix+"-DD-precal.cube.int.model.fits" # else: # model_cube = prefix+"-DD-precal.cube.app.model.fits" outdir = field+"_ddcal" if de_sources_mode == 'auto': print("Carrying out automatic source taggig for direction dependent calibration") caracal.log.info('Carrying out automatic dE tagging') catdagger_opts = { "ds9-reg-file": "de-{0:s}.reg:output".format(field), "ds9-tag-reg-file" : "de-clusterleads-{0:s}.reg:output".format(field), "noise-map" : prefix+"_"+field+"-DD-precal.app.residual.fits", "sigma" : config[key]['sigma'], "min-distance-from-tracking-centre" : config[key]['min_dist_from_phcentre'], } recipe.add('cab/catdagger', 'tag_sources-auto_mode', catdagger_opts,input=INPUT, output=OUTPUT+"/"+outdir,label='tag_sources-auto_mode::Tag dE sources with CatDagger',shared_memory=shared_mem) if de_sources_mode == 'manual': img = prefix+"_"+field+"-DD-precal.app.restored.fits" imagefile = os.path.join(pipeline.output,DD_DIR,outdir,img) #print("Imagefile",imagefile) #print("Pipeline output", pipeline.output) w = WCS(imagefile) #coords = config[key]['de_sources_manual'] print(de_dict) sources_to_tag = de_dict[field.replace("_","-")] reg = [] for j in range(len(sources_to_tag.split(";"))): coords = sources_to_tag.split(";")[j] size = coords.split(",")[2] coords_str = coords.split(",")[0]+" "+coords.split(",")[1] #print("Coordinate String", coords_str) centre = SkyCoord(coords_str, unit='deg') separation = int(size) * u.arcsec #print("Size",separation) xlist = [] ylist = [] for i in range(5): ang_sep = (306/5)*i*u.deg p = centre.directional_offset_by(ang_sep,separation) pix = PixCoord.from_sky(p,w) xlist.append(pix.x) ylist.append(pix.y) vertices = PixCoord(x=xlist, y=ylist) region_dd = PolygonPixelRegion(vertices=vertices) reg.append(region_dd) regfile = "de-{0:s}.reg".format(field) ds9_file = os.path.join(OUTPUT,outdir,regfile) write_ds9(reg,ds9_file,coordsys='physical')
def region_from_mask(mask): '''take a bool mask as input and return outline of regions as PixelRegion''' # otherwiese we have problems with the edge of the image mask[:, 0] = False mask[:, -1] = False mask[0, :] = False mask[-1, :] = False contours = find_contours(mask.astype(float), level=0.5) regs = [] for contour in contours: regs.append(PolygonPixelRegion(PixCoord(*contour.T[::-1]))) return regs
def clean_up_results(t_init, obj_name, id_type='smallbody', location=None, radius=0.0083): """ Function to clean up results. Will check if the target is inside the observation footprint. If a radius is provided, will also construct a circle and check if the observation center is in the target circle. Parameters ---------- t_init: atropy Table Initial astropy Table obj_name: str Object name. May require specific formatting (i.e. selecting between the codes for Jupiter and Jupiter barycenter). See JPL Horizons documentation id_type: str Object ID type for JPL Horizons. Defaults to smallbody (an asteroid or comet). Best to be as specific as possible to find the correct body. majorbody: planets and satellites smallbody: asteroids and comets asteroid_name: name of asteroid comet_name: name of comet name: any target name designation: any asteroid or comet designation location: str Default of None uses a geocentric location for queries. For specific spacecrafts, insert location Examples: TESS: @TESS Hubble: @hst Kepler: 500@-227 radius : float Size of target for intersection calculations Returns ------- t: astropy Table Astropy Table with only those where the moving target was in the footprint """ t = t_init.copy() # Add mid-point time and sort by that first t['t_mid'] = (t['t_max'] + t['t_min'])/2 + 2400000.5 t.sort('t_mid') # Ephemerides results are sorted by time, hence the initial sort print('Verifying footprints...') eph = Horizons(id=obj_name, location=location, id_type=id_type, epochs=t['t_mid']).ephemerides() # For each row in table, check s_region versus target position at mid-time check_list = [] for i, row in enumerate(t): # print(row['t_mid'], eph['datetime_jd'][i], eph['RA'][i], eph['DEC'][i]) # Create a polygon for the footprint and check if target is inside polygon try: stcs = parse_s_region(row['s_region']) xs = stcs['ra'] ys = stcs['dec'] polygon_pix = PolygonPixelRegion(vertices=PixCoord(x=xs, y=ys)) target_coords = PixCoord(eph['RA'][i], eph['DEC'][i]) if radius is None or radius <= 0: flag = target_coords in polygon_pix else: target_circle = CirclePixelRegion(center=target_coords, radius=radius) observation_coords = PixCoord(row['s_ra'], row['s_dec']) flag = (target_coords in polygon_pix) or (observation_coords in target_circle) # print(stcs, flag) except Exception as e: print(f"ERROR checking footprint for {row['obs_id']} with: {e}" f"\nAssuming False") flag = False check_list.append(flag) # Set the flags t['in_footprint'] = check_list return t[t['in_footprint']]
def clean_up_results(t_init, obj_name, orig_eph=None, id_type='smallbody', location=None, radius=0.0083, aggressive_check=False): """ Function to clean up results. Will check if the target is inside the observation footprint. If a radius is provided, will also construct a circle and check if the observation center is in the target circle. TODO: This is a buggy for several reasons: 1- regions doesn't have intersection of polygons yet so valid observations are missed 2- the mid point for observations like TESS can be days away from the target location 3- the _detail_check function is effectively re-adding most of what it clears Parameters ---------- t_init: atropy Table Initial astropy Table obj_name: str Object name. May require specific formatting (i.e. selecting between the codes for Jupiter and Jupiter barycenter). See JPL Horizons documentation orig_eph: astropy Table Original ephemerides table id_type: str Object ID type for JPL Horizons. Defaults to smallbody (an asteroid or comet). Best to be as specific as possible to find the correct body. majorbody: planets and satellites smallbody: asteroids and comets asteroid_name: name of asteroid comet_name: name of comet name: any target name designation: any asteroid or comet designation location: str Default of None uses a geocentric location for queries. For specific spacecrafts, insert location Examples: TESS: @TESS Hubble: @hst Kepler: 500@-227 radius: float Size of target for intersection calculations aggressive_check: bool Perform additional time checks; can remove valid observations (Default: False) Returns ------- t: astropy Table Astropy Table with only those where the moving target was in the footprint """ if len(t_init) == 0: return None if radius is not None and not isinstance(radius, float): radius = float(radius) t = t_init.copy() # Sort by mid point time t['t_mid'] = (t['t_max'] + t['t_min']) / 2 + 2400000.5 t.sort('t_mid') # Ephemerides results are sorted by time, hence the initial sort print('Verifying footprints...') # Fix for TESS if location is not None and location.upper() == '@TESS': print('Restriction for TESS observations') threshold = 2456778.50000 # 2018-05-01 ind = t['t_mid'] > threshold t = t[ind] eph = Horizons(id=obj_name, location=location, id_type=id_type, epochs=t['t_mid']).ephemerides() # For each row in table, check s_region versus target position at mid-time check_list = [] for i, row in enumerate(t): # print(row['t_mid'], eph['datetime_jd'][i], eph['RA'][i], eph['DEC'][i]) # Create a polygon for the footprint and check if target is inside polygon try: stcs = parse_s_region(row['s_region']) xs = stcs['ra'] ys = stcs['dec'] polygon_pix = PolygonPixelRegion(vertices=PixCoord(x=xs, y=ys)) target_coords = PixCoord(eph['RA'][i], eph['DEC'][i]) observation_coords = PixCoord(row['s_ra'], row['s_dec']) if radius is None or radius < 0: flag = target_coords in polygon_pix else: target_circle = CirclePixelRegion(center=target_coords, radius=radius) flag = (target_coords in polygon_pix) or (observation_coords in target_circle) if orig_eph is not None and not flag: flag = _detail_check(orig_eph, polygon_pix, observation_coords, start_date=row['t_min'], end_date=row['t_max'], radius=radius, aggressive_check=aggressive_check) # print(row['obs_id'], flag) except Exception as e: print(f"ERROR checking footprint for {row['obs_id']} with: {e}" f"\nAssuming False") flag = False check_list.append(flag) # Set the flags t['in_footprint'] = check_list return t[t['in_footprint']]
obj_name=obj_name, id_type=id_type, location=location) print(filtered_results) # Using regions import matplotlib.pyplot as plt from astropy.coordinates import SkyCoord from regions import PixCoord, PolygonSkyRegion, PolygonPixelRegion, CirclePixelRegion patch_xs = parse_s_region(stcs)['ra'] patch_ys = parse_s_region(stcs)['dec'] polygon_sky = PolygonSkyRegion( vertices=SkyCoord(patch_xs, patch_ys, unit='deg', frame='icrs')) # Treating as pixels for simplicity (and since I have no WCS) polygon_pix = PolygonPixelRegion(vertices=PixCoord(x=patch_xs, y=patch_ys)) PixCoord(eph['RA'][1], eph['DEC'][1]) in polygon_pix radius = 0.0083 target_coords = PixCoord(eph['RA'][0], eph['DEC'][0]) target_circle = CirclePixelRegion(center=target_coords, radius=radius) intersection = target_circle & polygon_pix # intersection.area # not implemented yet fig, ax = plt.subplots(figsize=(8, 4)) patch = polygon_pix.as_artist(facecolor='none', edgecolor='red', lw=2) ax.add_patch(patch) plt.plot([eph['RA'][1]], [eph['DEC'][1]], 'ko') plt.xlim(84.2, 81.4) plt.ylim(41.2, 41.5)
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 to_object(self, subset): """ Convert a glue Subset object to a astropy regions Region object. Parameters ---------- subset : `glue.core.subset.Subset` The subset to convert to a Region object """ data = subset.data if data.pixel_component_ids[0].axis == 0: x_pix_att = data.pixel_component_ids[1] y_pix_att = data.pixel_component_ids[0] else: x_pix_att = data.pixel_component_ids[0] y_pix_att = data.pixel_component_ids[1] subset_state = subset.subset_state if isinstance(subset_state, RoiSubsetState): roi = subset_state.roi if isinstance(roi, RectangularROI): xcen = 0.5 * (roi.xmin + roi.xmax) ycen = 0.5 * (roi.ymin + roi.ymax) width = roi.xmax - roi.xmin height = roi.ymax - roi.ymin return RectanglePixelRegion(PixCoord(xcen, ycen), width, height) elif isinstance(roi, PolygonalROI): return PolygonPixelRegion(PixCoord(roi.vx, roi.vy)) elif isinstance(roi, CircularROI): return CirclePixelRegion(PixCoord(*roi.get_center()), roi.get_radius()) elif isinstance(roi, EllipticalROI): return EllipsePixelRegion(PixCoord(roi.xc, roi.yc), roi.radius_x, roi.radius_y) elif isinstance(roi, PointROI): return PointPixelRegion(PixCoord(*roi.center())) elif isinstance(roi, RangeROI): return range_to_rect(data, roi.ori, roi.min, roi.max) elif isinstance(roi, AbstractMplRoi): temp_sub = Subset(data) temp_sub.subset_state = RoiSubsetState(x_pix_att, y_pix_att, roi.roi()) try: return self.to_object(temp_sub) except NotImplementedError: raise NotImplementedError( "ROIs of type {0} are not yet supported".format( roi.__class__.__name__)) else: raise NotImplementedError( "ROIs of type {0} are not yet supported".format( roi.__class__.__name__)) elif isinstance(subset_state, RangeSubsetState): if subset_state.att == x_pix_att: return range_to_rect(data, 'x', subset_state.lo, subset_state.hi) elif subset_state.att == y_pix_att: return range_to_rect(data, 'y', subset_state.lo, subset_state.hi) else: raise ValueError( 'Range subset state att should be either x or y pixel coordinate' ) elif isinstance(subset_state, MultiRangeSubsetState): if subset_state.att == x_pix_att: ori = 'x' elif subset_state.att == y_pix_att: ori = 'y' else: message = 'Multirange subset state att should be either x or y pixel coordinate' raise ValueError(message) if len(subset_state.pairs) == 0: message = 'Multirange subset state should contain at least one range' raise ValueError(message) region = range_to_rect(data, ori, subset_state.pairs[0][0], subset_state.pairs[0][1]) for pair in subset_state.pairs[1:]: region = region | range_to_rect(data, ori, pair[0], pair[1]) return region elif isinstance(subset_state, PixelSubsetState): return PointPixelRegion(PixCoord(*subset_state.get_xy(data, 1, 0))) elif isinstance(subset_state, AndState): temp_sub1 = Subset(data=data) temp_sub1.subset_state = subset_state.state1 temp_sub2 = Subset(data=data) temp_sub2.subset_state = subset_state.state2 return self.to_object(temp_sub1) & self.to_object(temp_sub2) elif isinstance(subset_state, OrState): temp_sub1 = Subset(data=data) temp_sub1.subset_state = subset_state.state1 temp_sub2 = Subset(data=data) temp_sub2.subset_state = subset_state.state2 return self.to_object(temp_sub1) | self.to_object(temp_sub2) elif isinstance(subset_state, XorState): temp_sub1 = Subset(data=data) temp_sub1.subset_state = subset_state.state1 temp_sub2 = Subset(data=data) temp_sub2.subset_state = subset_state.state2 return self.to_object(temp_sub1) ^ self.to_object(temp_sub2) elif isinstance(subset_state, MultiOrState): temp_sub = Subset(data=data) temp_sub.subset_state = subset_state.states[0] region = self.to_object(temp_sub) for state in subset_state.states[1:]: temp_sub.subset_state = state region = region | self.to_object(temp_sub) return region else: raise NotImplementedError( "Subset states of type {0} are not supported".format( subset_state.__class__.__name__))
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