def new_plots(pos, data, layer=None, plot_type='blazar', vmax=1, levels=[]): ax0 = plt.subplot(1, 2, pos) ax0.get_xaxis().set_ticks([]) ax0.get_yaxis().set_ticks([]) image_size = 60 * 2 # image is 2 * 2 arcminutes len_x, len_y = data.shape x0, x1 = len_x * (0.65 + 0.125), len_x * 0.9 y = len_y * 0.1 plt.text((x0 + x1) / 2, y * (0.7), str(int(image_size * 0.25 * 0.5)) + '"', horizontalalignment='center', verticalalignment='center', fontsize=15, color='w') plt.plot([x0, x1], [y, y], 'w-', lw=1.5) image = ax0.imshow(data, origin='lower', cmap='viridis', vmax=vmax, vmin=0, norm=DS9Normalize(stretch='arcsinh')) circle1 = plt.Circle([8, 8], (x1 - x0) * (6 / 15) / 2, ls='--', fc='None', ec='w') ax0.add_artist(circle1) divider = make_axes_locatable(ax0) cax0 = divider.append_axes('bottom', size='5%', pad=0.05) cbar = plt.colorbar(image, cax=cax0, orientation='horizontal') cbar.ax.tick_params(labelsize=15) cbar.ax.set_xlabel(r'Jy beam$^{-1}$', fontsize=15) if plot_type is 'blazar': ax0.contour(data, levels=levels, origin='lower', colors='white', alpha=0.67) elif plot_type is 'diffuse': ax0.contour(layer, levels=levels, origin='lower', colors='white', alpha=0.67) ax0.contour(data, levels=levels, origin='lower', colors='magenta' ) # in this case, data is the core subtracted array
x1s.append(x1) x2s.append(x2) y1s.append(y1) y2s.append(y2) distances = np.array(distances) my_max = np.max(distances) max_x1 = x1s[distances.argmax()] max_x2 = x2s[distances.argmax()] max_y1 = y1s[distances.argmax()] max_y2 = y2s[distances.argmax()] asec_max = my_max * 1.5 # 1.5" per pixel centre = ((max_y1 + max_y2) / 2, (max_x1 + max_x2) / 2) fig = plt.imshow(d, vmin=0, vmax=np.nanmax(d), origin='lower', norm=DS9Normalize(stretch='arcsinh')) plt.colorbar() fig.axes.get_xaxis().set_visible(False) fig.axes.get_yaxis().set_visible(False) circle = plt.Circle(centre, my_max / 2, color='r', fill=False, alpha=0.5, lw=2) fig = plt.gcf() ax = fig.gca() ax.add_artist(circle) plt.plot([max_y1, max_y2], [max_x1, max_x2], color='red', alpha=0.5, lw=2) plt.plot([(max_y1 + max_y2) / 2], [(max_x1 + max_x2) / 2], marker='o', color='red', alpha=0.5) plt.title(f'{source_name}\n5\u03C3 = {threshold * 1000:.3f} mJy; d = ' + f'{asec_max:.1f}"') # plt.show()
def optical(sigma=4, my_directory='/data5/sean/ldr2'): """Plot Pan-STARRS data. Parameters ---------- sigma : float or int The threshold of the significance to set the mask, as a factor of the local RMS. The default is 4. my_directory : string Working directory. """ df = pd.read_csv(f'{my_directory}/catalogues/final.csv') plt.figure(figsize=(13.92, 8.60)).patch.set_facecolor('white') plt.rcParams['font.family'] = 'serif' plt.rcParams['mathtext.fontset'] = 'dejavuserif' mpl.rcParams['xtick.major.size'] = 10 mpl.rcParams['xtick.major.width'] = 2 mpl.rcParams['xtick.minor.size'] = 5 mpl.rcParams['xtick.minor.width'] = 2 mpl.rcParams['ytick.major.size'] = 10 mpl.rcParams['ytick.major.width'] = 2 mpl.rcParams['ytick.minor.size'] = 5 mpl.rcParams['ytick.minor.width'] = 2 mpl.rcParams['axes.linewidth'] = 2 colors = ['#118ab2', '#06d6a0', '#ffd166', '#ef476f'] sbar_asec = 30 # desired length of scalebar in arcseconds pix = 0.25 # arcseconds per pixel for source_name, ra, dec, mosaic, rms, z, pf in zip(df['Name'], df['BZCAT RA'], df['BZCAT Dec'], df['Mosaic_ID'], df['Isl_rms'], df['redshift'], df['Peak_flux']): source_name = '5BZB' + source_name sky_position = SkyCoord(ra, dec, unit='deg') if source_name == '5BZBJ1202+4444' or source_name == '5BZBJ1325+4115': size = [3, 3] * u.arcmin p = 54 elif (source_name == '5BZBJ1419+5423' or source_name == '5BZBJ0945+5757'): size = [4, 4] * u.arcmin p = 72 else: size = [2, 2] * u.arcmin p = 36 print(source_name) p_hdu = fits.open(f'{my_directory}/panstarrs/{source_name}.i.' 'fits')[0] p_wcs = WCS(p_hdu.header) p_cutout = Cutout2D(p_hdu.data, sky_position, size=size, wcs=p_wcs) l_hdu = fits.open(f'{my_directory}/mosaics/{mosaic}-mosaic.fits')[0] l_wcs = WCS(l_hdu.header, naxis=2) l_cutout = Cutout2D(np.squeeze(l_hdu.data), sky_position, size=size, wcs=l_wcs) if 4 * rms < (pf / 50): # see 2.2 of https://arxiv.org/pdf/1907.03726.pdf levels = [level * (pf / 50) / 1000 for level in [1, 2, 4, 8]] else: levels = [level * rms / 1000 for level in [4, 8, 16, 32]] ax = plt.subplot(projection=p_cutout.wcs) im = ax.imshow(p_cutout.data, vmin=0, vmax=8000, cmap='cubehelix_r', origin='lower', norm=DS9Normalize(stretch='arcsinh'), interpolation='gaussian') cbar = plt.colorbar(im) cbar.set_label('Excess counts', size=20) cbar.ax.tick_params(labelsize=20) ax.contour(l_cutout.data, transform=ax.get_transform(l_cutout.wcs), levels=levels, origin='lower', colors=colors) plt.xlabel('Right ascension', fontsize=20, color='black') plt.ylabel('Declination', fontsize=20, color='black') ax.tick_params(axis='both', which='major', labelsize=20) plt.minorticks_on() ax.tick_params(which='minor', length=0) kpc_per_asec = get_kpc_per_asec(z=z) sbar = sbar_asec / pix # length of scalebar in pixels kpc_per_pixel = kpc_per_asec * pix s = p_cutout.data.shape[1] # plot scalebar plt.plot([p, p + sbar], [s - p, s - p], marker='None', lw=2, color='b') plt.text(p, s - p + 10 * (p / 36), f'{sbar_asec:.0f}" = ' f'{kpc_per_pixel * sbar:.0f} kpc', fontsize=20, color='b') plt.savefig(f'{my_directory}/images/panstarrs-{source_name}.png') plt.clf()
def __init__(self,filelist, step=1.0,outdir='./nudged/',ext='',clobber=False): self.filelist = filelist # datalist holds current state of arrays self.datalist = map(pyfits.getdata,filelist) self.step = step self.outdir = outdir self.ext = ext self.clobber = clobber self.current = 0 self.orig_data = pyfits.getdata(filelist[0]) self.active_data = self.datalist[0] # store total offsets self.offsets = np.zeros((len(filelist),2)) # initialize norm self.norm = DS9Normalize(stretch='linear') # set up subparser self.subparser=argparse.ArgumentParser(description='Parse window text.',prog='') self.subparser.add_argument('-s',type=float,help='Step size (default=%.1f)' % self.step) self.subparser.add_argument('--stretch',choices=['linear','sqrt','arcsinh','log','power','squared'],help='Choose image stretch (default = stretch)') self.subparser.add_argument('--clip_lo',type=float,help='Clip minimum intensity percentile') self.subparser.add_argument('--clip_hi',type=float,help='Clip maximum intensity percentile') self.subparser.add_argument('-w',action='store_true',help="Write current frame to output directory (outdir=%s)"%self.outdir) self.subparser.add_argument('-wa',action='store_true',help="Write all frames to output directory (outdir=%s)"%self.outdir) self.subparser.add_argument('-wq',action='store_true',help="Write all frames to output directory and quit (outdir=%s)"%self.outdir) self.subparser.add_argument('-r',action='store_true',help='Restore original') self.subparser.add_argument('--c',action='store_true',help='Force clobber status to True on write') self.subparser.add_argument('--q',action='store_true',help='Quit') self.fig = plt.figure() self.fig.canvas.mpl_disconnect(self.fig.canvas.manager.key_press_handler_id) self.keycid = self.fig.canvas.mpl_connect('key_press_event',self.onkey) self.fig.canvas.mpl_connect('button_press_event', self.onclick) self.fig.canvas.mpl_connect('button_release_event', self.onrelease) # Hold x,y drag coords self.dragfrom = None self.pausetext = '-' self.pid = None # Make directory if doesn't exist try: mkdir(self.outdir) except OSError: #directory exists. no big deal. pass print "Type directly into figure" print "'left/right/up/down' to translate image" print "'</>' to choose previous/next image in input list" print "'-h' to see additional options" print "'--q' to quit" print #Show initial self.display(self.active_data) self.displaytext('[0, 0], s=%.2f'%self.step,x=0.60) plt.show()
def parsetext(self,text): args = None try: # catch -h, or error exit args = self.subparser.parse_args(text.split()) except SystemExit: return if not args: return if args.c: self.clobber = True print 'Force clobber on write' if args.s: self.step = args.s print 'Step size changed to %.2f' % self.step if args.stretch: print 'Changed stretch to %s' % args.stretch self.norm.stretch = args.stretch self.display(self.active_data) if args.clip_lo: print 'Clip lo changed to %.2f' % args.clip_lo self.norm.clip_lo = args.clip_lo self.display(self.active_data) if args.clip_hi: print 'Clip hi changed to %.2f' % args.clip_hi self.norm.clip_hi = args.clip_hi self.display(self.active_data) if args.r: self.active_data = self.orig_data.copy() self.offsets[self.current][0] = 0.0 self.offsets[self.current][1] = 0.0 self.norm = DS9Normalize(stretch='linear') self.display(self.active_data) print 'Restored image from %s' % self.filelist[self.current] if args.w: h = pyfits.getheader(self.filelist[self.current]) h['N_ORIG_F'] = (self.filelist[self.current],'Original file before nudge') h['N_XS'] = (self.offsets[self.current][0],'Xshift of nudge') h['N_YS'] = (self.offsets[self.current][1],'Yshift of nudge') outfile = os.path.basename(self.filelist[self.current]) outfile = os.path.splitext(outfile) outfile = ''.join([outfile[0],self.ext,outfile[1]]) outfile = os.path.join(self.outdir,outfile) try: pyfits.writeto(outfile,data=self.active_data,header=h,clobber=self.clobber) except IOError as e: print e, "'--c' to force overwrite" else: print '%s: written to disk, s = [%.2f, %.2f]' % (outfile,self.offsets[self.current][0],self.offsets[self.current][1]) if args.wq: args.wa = True args.q = True if args.wa: for idx in range(0,len(self.filelist)): h = pyfits.getheader(self.filelist[idx]) h['N_ORIG_F'] = (self.filelist[idx],'Original file before nudge') h['N_XS'] = (self.offsets[idx][0],'Xshift of nudge') h['N_YS'] = (self.offsets[idx][1],'Yshift of nudge') outfile = os.path.basename(self.filelist[idx]) outfile = os.path.splitext(outfile) outfile = ''.join([outfile[0],self.ext,outfile[1]]) outfile = os.path.join(self.outdir,outfile) try: if idx == self.current: pyfits.writeto(outfile,data=self.active_data,header=h,clobber=self.clobber) else: pyfits.writeto(outfile,data=self.datalist[idx],header=h,clobber=self.clobber) except IOError as e: print e, "'--c' to force overwrite" args.q = False #don't quit if file fails to write else: print '%s: written to disk, s = [%.2f, %.2f]' % (outfile,self.offsets[idx][0],self.offsets[idx][1]) if args.q: plt.close() exit()
def loop_through_sources(sigma=4, my_directory='/data5/sean/ldr2'): """Plot postage stamp images of LDR2 BL Lacs. Parameters ---------- sigma : float or integer The threshold of the significance to set the mask, as a factor of the local RMS. The default is 4. my_directory : string Working directory. Returns ------- string The name of the CSV containing the results. """ df = pd.read_csv(f'{my_directory}/catalogues/pulsars-10asec-match.csv') plt.figure(figsize=(13.92, 8.60)).patch.set_facecolor('white') plt.rcParams['font.family'] = 'serif' plt.rcParams['mathtext.fontset'] = 'dejavuserif' mpl.rcParams['xtick.major.size'] = 10 mpl.rcParams['xtick.major.width'] = 2 mpl.rcParams['xtick.minor.size'] = 5 mpl.rcParams['xtick.minor.width'] = 2 mpl.rcParams['ytick.major.size'] = 10 mpl.rcParams['ytick.major.width'] = 2 mpl.rcParams['ytick.minor.size'] = 5 mpl.rcParams['ytick.minor.width'] = 2 mpl.rcParams['axes.linewidth'] = 2 dummy = 123456 sbar_asec = 30 # desired length of scalebar in arcseconds pix = 1.5 # arcseconds per pixel for source_name, ra, dec, mosaic, rms in zip(df['NAME'], df['RAJD'], df['DECJD'], df['Mosaic_ID'], df['Isl_rms']): threshold = sigma * rms / 1000 # jansky hdu = fits.open(f'{my_directory}/mosaics/{mosaic}-mosaic.fits')[0] wcs = WCS(hdu.header, naxis=2) sky_position = SkyCoord(ra, dec, unit='deg') size = [2, 2] * u.arcmin p = 6 cutout = Cutout2D(np.squeeze(hdu.data), sky_position, size=size, wcs=wcs) d = cutout.data copy_d = np.copy(d) another_copy_d = np.copy(d) d[d < threshold] = 0 d[d >= threshold] = 1 rows, cols = d.shape d = label(d) # label islands of emission source_islands = nearest_to_centre(d, percent=0.1) for source_island in source_islands: d[d == source_island] = dummy d[d != dummy] = 0 copy_d[d != dummy] = 0 set_to_nil = [] # identify values we can set to zero for being inside for r in range(rows): # set to 0 if surrounded by non nans for c in range(cols): try: if (d[r - 1, c - 1] != 0 and d[r - 1, c] != 0 and d[r - 1, c + 1] != 0 and d[r, c - 1] != 0 and d[r, c + 1] != 0 and d[r + 1, c - 1] != 0 and d[r + 1, c] != 0 and d[r + 1, c + 1] != 0): set_to_nil.append((r, c)) except IndexError: print(f'Index error for {source_name}.') continue for r, c in set_to_nil: d[r, c] = 0 # needs separate loop to avoid checkered pattern # d is an outline of the source (one) and everything else is zero # copy_d is the source with flux values and everything else is zero # another_copy_d has flux values throughout good_cells = [] for r in range(rows): for c in range(cols): if d[r, c] != 0: good_cells.append([r, c]) x, y, r = smallestenclosingcircle.make_circle(good_cells) ax = plt.subplot(projection=cutout.wcs) plt.xlabel('Right ascension', fontsize=20, color='black') plt.ylabel('Declination', fontsize=20, color='black') ax.tick_params(axis='both', which='major', labelsize=20) plt.imshow(another_copy_d, vmin=0, vmax=np.nanmax(another_copy_d), origin='lower', norm=DS9Normalize(stretch='arcsinh'), cmap='plasma_r') # interpolation='gaussian' beam = Circle((6, 6), radius=2, linestyle='dashed', lw=2, fc='none', edgecolor='blue') diffuse = Circle((y + 0.5, x + 0.5), radius=r, fc='none', edgecolor='k', lw=2) ax.add_patch(beam) ax.add_patch(diffuse) sbar = sbar_asec / pix # length of scalebar in pixels s = cutout.data.shape[1] # plot scalebar plt.plot([p, p + sbar], [s - p, s - p], marker='None', lw=2, color='b') plt.text(p, s - (5 * p / 6), f'{sbar_asec:.0f}"', fontsize=20, color='b') cbar = plt.colorbar() cbar.set_label(r'Jy beam$^{-1}$', size=20) cbar.ax.tick_params(labelsize=20) plt.minorticks_on() plt.tick_params(which='minor', length=0) plt.contour(another_copy_d, levels=[threshold], origin='lower', colors='w') plt.contour(another_copy_d - copy_d, levels=[threshold], colors='grey', origin='lower') plt.savefig(f'{my_directory}/images/pulsar-{source_name}.png') plt.clf() print(f'{source_name}: {r * 1.5 * 2:.1f}"')
def measure_extent_radio_galaxies(my_dir='/data5/sean/deep-fields/catalogues/', nah=False): """Measure the size of radio galaxies. """ results_csv = f'{my_dir}../results/extention-radio-galaxies.csv' if nah: return results_csv # do not do anything df = pd.read_csv(f'{my_dir}radio.galaxies.ldr1.csv') # load data fields = [f'/data1/lotss-data/{m}-mosaic.fits' for m in df['Mosaic_ID']] thresholds = 5 * df['Isl_rms'] / 1000 # converting to jansky plt.figure(figsize=(8, 8)) result_header = ('Name,Class,LM flux (mJy),LM size ("),Width ("),Width' + ' (kpc),5 * rms (mJy),Redshift,NAT,WAT,D-D\n') if not os.path.exists(results_csv): with open(results_csv, 'a') as f: f.write(result_header) # skipping these sources as they are too complicated skip_list = ['ILTJ105155.09+552329.0', 'ILTJ104703.03+523023.4'] i = 0 for (source_name, ra, dec, field, threshold, fri, frii, redshift, nat, wat, dd, lm_size, lm_flux) in zip(df['Source_Name_1'], df['RA_1'], df['DEC_1'], fields, thresholds, df['FR1'], df['FR2'], df['z_best'], df['NAT'], df['WAT'], df['D-D'], df['LM_dec_size'], df['LM_Flux']): save = f'{my_dir}../images/extention-radio-galaxies/{source_name}.png' if os.path.exists(save): print(f'{save} already exists so it is being skipped.') continue if source_name in skip_list: print(f'{source_name} is too complicated so it is being skipped.') continue # already removed small sources and ambiguous sources from the sample source_type = 'FR-I' if fri else 'FR-II' # if source_name != 'ILTJ130804.04+550835.4': # for testing one source # continue # try: hdu = fits.open(field)[0] # except FileNotFoundError: # fits might have different name # print(f'{field} does not exist.') # continue wcs = WCS(hdu.header, naxis=2) sky_position = SkyCoord(ra, dec, unit='deg') s = math.ceil((lm_size * 2) / 60) # already have adhoc masks for P196+55 field at [3, 3] arcmin but for # the rest we take the size of the source from lomorph size = [3, 3] if field[-19:-5] == 'P196+55-mosaic' else [s, s] # some sources need a bigger cutout if source_name == 'ILTJ130140.02+540825.9': size = [4, 4] elif source_name == 'ILTJ130331.30+540024.1': size = [6, 6] cutout = Cutout2D(np.squeeze(hdu.data), sky_position, size=size * u.arcmin, wcs=wcs) d = cutout.data d[d < threshold] = np.nan d = manual_mask(name=source_name, data=d) rows, cols = d.shape good_cells = [] for r in range(rows): for c in range(cols): if not np.isnan(d[r, c]): good_cells.append([r, c]) # find distance between good_cell and all other good_cells distances, x1s, x2s, y1s, y2s = [], [], [], [], [] for (x1, y1) in good_cells: for (x2, y2) in good_cells: distances.append(np.sqrt((x1 - x2)**2 + (y1 - y2)**2)) x1s.append(x1) x2s.append(x2) y1s.append(y1) y2s.append(y2) distances = np.array(distances) # try: # my_max = np.max(distances) # except ValueError: # print(f'Failed for {source_name}.') # continue max_x1 = x1s[distances.argmax()] max_x2 = x2s[distances.argmax()] max_y1 = y1s[distances.argmax()] max_y2 = y2s[distances.argmax()] # asec_max = my_max * 1.5 # 1.5" per pixel # this removes highly curved sources # if lm_size / asec_max > 1.75 or asec_max / lm_size > 1.75: # print(f'{source_name} is too curved so it is being skipped.') # continue # for good cells find the distance from it to the point on the line, we # assume we look down the longest line and the source is flat in the # plane of the sky (https://stackoverflow.com/a/52756183/6386612) p1 = np.array([max_x1, max_y1]) p2 = np.array([max_x2, max_y2]) widths = [] width_x, width_y = [], [] for (x, y) in good_cells: p3 = np.array([x, y]) widths.append(np.cross(p2 - p1, p3 - p1) / np.linalg.norm(p2 - p1)) width_x.append(x) width_y.append(y) widths = np.array(widths) my_max_width = np.max(widths) my_min_width = np.min(widths) width_x_max = width_x[widths.argmax()] width_y_max = width_y[widths.argmax()] width_x_min = width_x[widths.argmin()] width_y_min = width_y[widths.argmin()] asec_width = (my_max_width + np.abs(my_min_width)) * 1.5 # 1.5"/pixel plt.imshow(d, vmin=0, vmax=np.nanmax(d), origin='lower', norm=DS9Normalize(stretch='arcsinh')) plt.colorbar() plt.plot([max_y1, max_y2], [max_x1, max_x2], color='red', alpha=0.5, lw=2) plt.plot([width_y_max], [width_x_max], marker='o', markersize=10, color='red', alpha=0.5) plt.plot([width_y_min], [width_x_min], marker='o', markersize=10, color='red', alpha=0.5) plt.minorticks_on() plt.grid(which="both", linewidth=0.72, color="k") plt.tick_params(which="minor", length=0) my_string = '' if nat: my_string += 'NAT ' elif wat: my_string += 'WAT ' if dd: my_string += 'D-D ' plt.title(f'{source_name}\n{source_type}; {my_string}5\u03C3 = ' + f'{threshold * 1000:.3f} mJy; width = {asec_width:.1f}"') # plt.show() plt.savefig(save) plt.clf() _, kpc = get_dl_and_kpc_per_asec(z=redshift) kpc_width = kpc * asec_width results = (f'{source_name},{source_type},{lm_flux},{lm_size},' + f'{asec_width},{kpc_width},{threshold * 1000},{redshift},' + f'{nat},{wat},{dd}\n') with open(results_csv, 'a') as f: f.write(results) # build clean sample on visual inspection i += 1 if i > 100: return
def ghz(sigma=4, my_directory='/data5/sean/ldr2'): """Plot FIRST data. Parameters ---------- sigma : float or int The threshold of the significance to set the mask, as a factor of the local RMS. The default is 4. my_directory : string Working directory. """ df = pd.read_csv(f'{my_directory}/catalogues/final.csv') plt.figure(figsize=(13.92, 8.60)).patch.set_facecolor('white') plt.rcParams['font.family'] = 'serif' plt.rcParams['mathtext.fontset'] = 'dejavuserif' mpl.rcParams['xtick.major.size'] = 10 mpl.rcParams['xtick.major.width'] = 2 mpl.rcParams['xtick.minor.size'] = 5 mpl.rcParams['xtick.minor.width'] = 2 mpl.rcParams['ytick.major.size'] = 10 mpl.rcParams['ytick.major.width'] = 2 mpl.rcParams['ytick.minor.size'] = 5 mpl.rcParams['ytick.minor.width'] = 2 mpl.rcParams['axes.linewidth'] = 2 colors = ['#118ab2', '#06d6a0', '#ffd166', '#ef476f'] sbar_asec = 30 # desired length of scalebar in arcseconds pix = 1.8 # arcseconds per pixel for source_name, ra, dec, mosaic, rms, z, f_rms, pf in zip( df['Name'], df['BZCAT RA'], df['BZCAT Dec'], df['Mosaic_ID'], df['Isl_rms'], df['redshift'], df['RMS'], df['Peak_flux']): source_name = '5BZB' + source_name sky_position = SkyCoord(ra, dec, unit='deg') if source_name == '5BZBJ1202+4444' or source_name == '5BZBJ1325+4115': size = [3, 3] * u.arcmin x = 9 * (1.5 / pix) # to get the scalebar in the same place elif (source_name == '5BZBJ1419+5423' or source_name == '5BZBJ0945+5757'): size = [4, 4] * u.arcmin x = 12 * (1.5 / pix) else: size = [2, 2] * u.arcmin x = 6 * (1.5 / pix) f_hdu = fits.open(f'{my_directory}/first/{source_name}.fits')[0] f_wcs = WCS(f_hdu.header, naxis=2) print(f'{source_name}') f_cutout = Cutout2D(np.squeeze(f_hdu.data), sky_position, size=size, wcs=f_wcs) l_hdu = fits.open(f'{my_directory}/mosaics/{mosaic}-mosaic.fits')[0] l_wcs = WCS(l_hdu.header, naxis=2) l_cutout = Cutout2D(np.squeeze(l_hdu.data), sky_position, size=size, wcs=l_wcs) if 4 * rms < (pf / 50): # see 2.2 of https://arxiv.org/pdf/1907.03726.pdf levels = [level * (pf / 50) / 1000 for level in [1, 2, 4, 8]] else: levels = [level * rms / 1000 for level in [4, 8, 16, 32]] f_level = f_rms * 4 / 1000 ax = plt.subplot(projection=f_cutout.wcs) im = ax.imshow(f_cutout.data, vmin=0, vmax=np.max(f_cutout.data), cmap='cubehelix_r', origin='lower', interpolation='gaussian', norm=DS9Normalize(stretch='arcsinh')) ax.contour(f_cutout.data, levels=[f_level], origin='lower', colors=['k']) cbar = plt.colorbar(im) cbar.set_label(r'Jy beam$^{-1}$', size=20) cbar.ax.tick_params(labelsize=20) ax.contour(l_cutout.data, transform=ax.get_transform(l_cutout.wcs), levels=levels, origin='lower', colors=colors) beam = Circle((6, 6), radius=1.5, linestyle='dashed', lw=2, fc='none', edgecolor='blue') # beam = 5.4" diameter, 1 pixel = 1.8" ax.add_patch(beam) plt.xlabel('Right ascension', fontsize=20, color='black') plt.ylabel('Declination', fontsize=20, color='black') ax.tick_params(axis='both', which='major', labelsize=20) plt.minorticks_on() ax.tick_params(which='minor', length=0) plt.xlim(0, f_cutout.data.shape[0]) plt.ylim(0, f_cutout.data.shape[1]) kpc_per_asec = get_kpc_per_asec(z=z) sbar = sbar_asec / pix # length of scalebar in pixels kpc_per_pixel = kpc_per_asec * pix s = f_cutout.data.shape[1] plt.plot([x, x + sbar], [s - x, s - x], marker='None', lw=2, color='b') plt.text(x, s - (4.167 * x / 5), f'{sbar_asec:.0f}" = ' f'{kpc_per_pixel * sbar:.0f} kpc', fontsize=20, color='b') plt.savefig(f'{my_directory}/images/first-{source_name}.png') plt.clf()
def loop_through_sources(sigma=5, my_directory='/data5/sean/ldr2'): """Plot postage stamp images of LDR2 BL Lacs. Parameters ---------- sigma : float or integer The threshold of the significance to set the mask, as a factor of the local RMS. The default is 5. my_directory : string Working directory. Returns ------- string The name of the CSV containing the results. """ results_path = f'{my_directory}/measure_point_sources/' if Path(results_path).exists() and Path(results_path).is_dir(): shutil.rmtree(results_path) os.mkdir(results_path, 0o755) results_csv = (f'{results_path}/measure_point_sources.csv') result_header = ('BZB,Name,RA,Dec,S_peak (mJy),RMS (mJy/beam),D (asec)') print(result_header) with open(results_csv, 'a') as f: f.write(f'{result_header}\n') df = pd.read_csv(f'{my_directory}/S_Code=S,DC_Maj=0,_1deg - S_Code=S,' 'DC_Maj=0,_1deg.csv') df = df[(df['PS SNR'] > 10) & (df['Degree separation'] < 0.5)] df = df[(df['DC_Maj'] == 0) & (df['DC_Min'] == 0) & (df['S_Code'] == 'S')] plt.figure(figsize=(13.92, 8.60)).patch.set_facecolor('white') plt.rcParams['font.family'] = 'serif' plt.rcParams['mathtext.fontset'] = 'dejavuserif' mpl.rcParams['xtick.major.size'] = 10 mpl.rcParams['xtick.major.width'] = 2 mpl.rcParams['xtick.minor.size'] = 5 mpl.rcParams['xtick.minor.width'] = 2 mpl.rcParams['ytick.major.size'] = 10 mpl.rcParams['ytick.major.width'] = 2 mpl.rcParams['ytick.minor.size'] = 5 mpl.rcParams['ytick.minor.width'] = 2 mpl.rcParams['axes.linewidth'] = 2 dummy = 123456 pix = 1.5 # arcseconds per pixel colors = ['#118ab2', '#06d6a0', '#ffd166', '#ef476f'] for bzb, bzb_mosaic, source_name, ra, dec, mosaic, rms, pf in zip( df['BZB name'], df['BZB mosaic'], df['Source_Name'], df['RA'], df['DEC'], df['Mosaic_ID'], df['Isl_rms'], df['Peak_flux']): if not bzb_mosaic: continue # don't use the source if it is from a different pointing threshold = sigma * rms / 1000 # jansky hdu = fits.open(f'{my_directory}/mosaics/{mosaic}-mosaic.fits')[0] wcs = WCS(hdu.header, naxis=2) sky_position = SkyCoord(ra, dec, unit='deg') size = [1, 1] * u.arcmin cutout = Cutout2D(np.squeeze(hdu.data), sky_position, size=size, wcs=wcs) d = cutout.data copy_d = np.copy(d) last_copy = np.copy(d) another_copy_d = np.copy(d) d[d < threshold] = 0 d[d >= threshold] = 1 rows, cols = d.shape d = label(d) source_islands = nearest_to_centre(d, percent=0.1) for source_island in source_islands: d[d == source_island] = dummy d[d != dummy] = 0 copy_d[d != dummy] = 0 set_to_nil = [] # identify values we can set to zero for being inside for r in range(rows): # set to 0 if surrounded by non nans for c in range(cols): try: if (d[r - 1, c - 1] != 0 and d[r - 1, c] != 0 and d[r - 1, c + 1] != 0 and d[r, c - 1] != 0 and d[r, c + 1] != 0 and d[r + 1, c - 1] != 0 and d[r + 1, c] != 0 and d[r + 1, c + 1] != 0): set_to_nil.append((r, c)) except IndexError: print(f'Index error for {source_name}.') continue for r, c in set_to_nil: d[r, c] = 0 # needs separate loop to avoid checkered pattern # d is an outline of the source (one) and everything else is zero # copy_d is the source with flux values and everything else is zero # another_copy_d has flux values throughout good_cells = [] for r in range(rows): for c in range(cols): if d[r, c] != 0: good_cells.append([r, c]) x, y, r = smallestenclosingcircle.make_circle(good_cells) ax = plt.subplot(projection=cutout.wcs) plt.xlabel('Right ascension', fontsize=20, color='black') plt.ylabel('Declination', fontsize=20, color='black') ax.tick_params(axis='both', which='major', labelsize=20) plt.imshow(another_copy_d, vmin=0, vmax=np.nanmax(another_copy_d), origin='lower', norm=DS9Normalize(stretch='arcsinh'), cmap='cubehelix_r', interpolation='gaussian') beam = Circle((6, 6), radius=2, linestyle='dashed', lw=2, fc='none', edgecolor='blue') # radius=2 pixels -> 3" -> diameter=6" diffuse = Circle((y + 0.5, x + 0.5), radius=r, fc='none', edgecolor='k', lw=2) ax.add_patch(beam) ax.add_patch(diffuse) cbar = plt.colorbar() cbar.set_label(r'Jy beam$^{-1}$', size=20) cbar.ax.tick_params(labelsize=20) plt.minorticks_on() plt.tick_params(which='minor', length=0) levels = [level * threshold for level in [1, 2, 4, 8]] plt.contour(another_copy_d, levels=levels, origin='lower', colors=colors) plt.contour(last_copy, levels=[-threshold * (3 / 5)], colors='grey', origin='lower', linestyles='dashed') saved = f'{results_path}/{source_name}.png' plt.savefig(saved) plt.clf() # os.system(f'convert {saved} -trim {saved}') # removes whitespace result = (f'{bzb},{source_name},{ra},{dec},{pf},{rms},' f'{r * pix * 2:.1f}') print(result) with open(results_csv, 'a') as f: f.write(f'{result}\n') return results_csv
def loop_through_sources(sigma=5, my_directory='/data5/sean/ldr2'): """Plot postage stamp images of LDR2 BL Lacs. Parameters ---------- sigma : float or integer The threshold of the significance to set the mask, as a factor of the local RMS. The default is 4. my_directory : string Working directory. Returns ------- string The name of the CSV containing the results. """ results_csv = f'{my_directory}/images/ldr2.csv' try: os.remove(results_csv) except OSError: pass df = pd.read_csv(f'{my_directory}/catalogues/final.csv') result_header = ('Name,RA,Dec,RMS (uJy),Redshift,Width ("),Width (kpc),' 'Peak flux (mJy)\n') with open(results_csv, 'a') as f: f.write(result_header) plt.figure(figsize=(13.92, 8.60)).patch.set_facecolor('white') plt.rcParams['font.family'] = 'serif' plt.rcParams['mathtext.fontset'] = 'dejavuserif' mpl.rcParams['xtick.major.size'] = 10 mpl.rcParams['xtick.major.width'] = 2 mpl.rcParams['xtick.minor.size'] = 5 mpl.rcParams['xtick.minor.width'] = 2 mpl.rcParams['ytick.major.size'] = 10 mpl.rcParams['ytick.major.width'] = 2 mpl.rcParams['ytick.minor.size'] = 5 mpl.rcParams['ytick.minor.width'] = 2 mpl.rcParams['axes.linewidth'] = 2 dummy = 123456 sbar_asec = 30 # desired length of scalebar in arcseconds pix = 1.5 # arcseconds per pixel colors = ['#118ab2', '#06d6a0', '#ffd166', '#ef476f'] print('Name, asec, kpc, threshold, UL?') for source_name, ra, dec, mosaic, rms, z, pf, comp in zip( df['Name'], df['BZCAT RA'], df['BZCAT Dec'], df['Mosaic_ID'], df['Isl_rms'], df['redshift'], df['Peak_flux'], df['Compact']): source_name = '5BZB' + source_name source_name = source_name.replace(' ', '') threshold = sigma * rms / 1000 # jansky thresh_ans = f'{sigma}sigma' # if threshold < (pf / 50) / 1000: # # see 2.2 of https://arxiv.org/pdf/1907.03726.pdf # four_sigma = threshold # threshold = (pf / 50) / 1000 # thresh_ans = '1/50 S_peak' hdu = fits.open(f'{my_directory}/mosaics/{mosaic}-mosaic.fits')[0] wcs = WCS(hdu.header, naxis=2) sky_position = SkyCoord(ra, dec, unit='deg') if source_name == '5BZBJ1202+4444' or source_name == '5BZBJ1325+4115': size = [3, 3] * u.arcmin p = 9 elif (source_name == '5BZBJ1419+5423' or source_name == '5BZBJ0945+5757'): size = [4, 4] * u.arcmin p = 12 else: size = [2, 2] * u.arcmin p = 6 cutout = Cutout2D(np.squeeze(hdu.data), sky_position, size=size, wcs=wcs) d = cutout.data copy_d = np.copy(d) last_copy = np.copy(d) another_copy_d = np.copy(d) d[d < threshold] = 0 d[d >= threshold] = 1 rows, cols = d.shape d = label(d) # label islands of emission source_islands = nearest_to_centre(d, percent=0.1) if source_name == '5BZBJ1000+5746': source_islands = [1, 2, 3, 4] elif source_name == '5BZBJ1202+4444': source_islands = [1, 2, 3] elif (source_name == '5BZBJ1203+5430' or source_name == '5BZBJ1419+5423'): source_islands = [1, 2] elif source_name == '5BZBJ1409+5939': source_islands = [2, 3] elif source_name == '5BZBJ1203+5430': source_islands = [1, 2] for source_island in source_islands: d[d == source_island] = dummy d[d != dummy] = 0 copy_d[d != dummy] = 0 set_to_nil = [] # identify values we can set to zero for being inside for r in range(rows): # set to 0 if surrounded by non nans for c in range(cols): try: if (d[r - 1, c - 1] != 0 and d[r - 1, c] != 0 and d[r - 1, c + 1] != 0 and d[r, c - 1] != 0 and d[r, c + 1] != 0 and d[r + 1, c - 1] != 0 and d[r + 1, c] != 0 and d[r + 1, c + 1] != 0): set_to_nil.append((r, c)) except IndexError: print(f'Index error for {source_name}.') continue for r, c in set_to_nil: d[r, c] = 0 # needs separate loop to avoid checkered pattern # d is an outline of the source (one) and everything else is zero # copy_d is the source with flux values and everything else is zero # another_copy_d has flux values throughout good_cells = [] for r in range(rows): for c in range(cols): if d[r, c] != 0: good_cells.append([r, c]) x, y, r = smallestenclosingcircle.make_circle(good_cells) ax = plt.subplot(projection=cutout.wcs) plt.xlabel('Right ascension', fontsize=20, color='black') plt.ylabel('Declination', fontsize=20, color='black') ax.tick_params(axis='both', which='major', labelsize=20) plt.imshow(another_copy_d, vmin=0, vmax=np.nanmax(another_copy_d), origin='lower', norm=DS9Normalize(stretch='arcsinh'), cmap='cubehelix_r', interpolation='gaussian') beam = Circle((6, 6), radius=2, linestyle='dashed', lw=2, fc='none', edgecolor='blue') # radius=2 pixels -> 3" -> diameter=6" # diffuse = Circle((y + 0.5, x + 0.5), radius=r, fc='none', # edgecolor='k', lw=2) ax.add_patch(beam) # if comp == False: # noqa # ax.add_patch(diffuse) kpc_per_asec = get_kpc_per_asec(z=z) sbar = sbar_asec / pix # length of scalebar in pixels kpc_per_pixel = kpc_per_asec * pix s = cutout.data.shape[1] # plot scalebar plt.plot([p, p + sbar], [s - p, s - p], marker='None', lw=2, color='b') plt.text(p, s - (5 * p / 6), f'{sbar_asec:.0f}" = ' f'{kpc_per_pixel * sbar:.0f} kpc', fontsize=20, color='b') cbar = plt.colorbar() cbar.set_label(r'Jy beam$^{-1}$', size=20) cbar.ax.tick_params(labelsize=20) plt.minorticks_on() plt.tick_params(which='minor', length=0) # levels = [level * threshold for level in [1, 2, 4, 8]] levels = [level * threshold for level in [1, 2, 4, 8]] plt.contour(another_copy_d, levels=levels, origin='lower', colors=colors) plt.contour(last_copy, levels=[-threshold * (3 / 5)], colors='grey', origin='lower', linestyles='dashed') # plt.contour(another_copy_d - copy_d, levels=[threshold], # colors='grey', origin='lower') saved = f'{my_directory}/images/ldr2-{source_name}.png' # if thresh_ans == '1/50 S_peak': # plt.contour(last_copy, levels=[-four_sigma], colors='grey', # origin='lower', linestyles='dashed') # plt.contour(last_copy, levels=[four_sigma], colors='grey', # origin='lower', linestyles='solid') print('view me: gpicview ' + saved) plt.savefig(saved) plt.clf() os.system(f'convert {saved} -trim {saved}') # removes whitespace width = r * kpc_per_pixel * 2 # radius to diameter result = (f'{source_name},{ra},{dec},{rms * 1e3},{z},' f'{r * pix * 2:.1f}, {width:.1f}, {pf}\n') print(f'{source_name[4:]}, {r * pix * 2:.4f}, {width:.4f}, ' f'{thresh_ans}, {comp}') with open(results_csv, 'a') as f: f.write(result) return results_csv