def figure_final_before_s(self, data): self._figure.clf() ax = self._figure.add_subplot(111) cmap = mpl.cm.get_cmap('gray') # norm = mpl.colors.LogNorm() ax.set_title('Result image') ax.set_xlabel('X') ax.set_ylabel('Y') interval = PercentileInterval(50.) z1, z2 = interval.get_limits(data) norm = ImageNormalize(vmin=z1, vmax=z2, stretch=SqrtStretch()) ax.imshow(data, cmap=cmap, clim=(z1, z2), norm=norm) self._figure.canvas.draw()
def figure_image(self, thedata, image): ax = self._figure.gca() image_axes, = ax.get_images() image_axes.set_data(thedata) # Create normalizer object interval = PercentileInterval(50.) z1, z2 = interval.get_limits(thedata) norm = ImageNormalize(vmin=z1, vmax=z2, stretch=SqrtStretch()) image_axes.set_clim(z1, z2) image_axes.set_norm(norm) clim = image_axes.get_clim() ax.set_title('%s, bg=%g fg=%g, linscale' % (image.lastname, clim[0], clim[1])) self._figure.canvas.draw()
def percentile(img: np.ndarray, percentile: int) -> Tuple[float, float]: """Determine percentile range. Calculates the range (vmin, vmax) so that a percentile of the pixels is within those values. Parameters ---------- img image array percentile Percentile value Returns ------- percentile range """ p = PercentileInterval(percentile) vmin, vmax = p.get_limits(img.ravel()) return vmin, vmax
# CHANNEL MAPS: Setting all the needed variables image = fits.open('image/NGC5257_12CO21_pbcor_cube_masked.fits') image_mas = fits.open(outfolder + 'mask.fits') xmin, xmax = 345, 615 ymin, ymax = 347, 617 zmin, zmax = 0, 69 data = image[0].data[zmin:zmax + 1, ymin:ymax + 1, xmin:xmax + 1] data_mas = image_mas[0].data[zmin:zmax + 1, ymin:ymax + 1, xmin:xmax + 1] head = image[0].header zsize = data[:, 0, 0].size cdeltsp = 0.1 cont = 0.0182647 v = np.array([1, 2, 4, 8, 16, 32, 64]) * cont v_neg = [-cont] interval = PercentileInterval(99.5) vmax = interval.get_limits(data)[1] norm = ImageNormalize(vmin=cont, vmax=vmax, stretch=PowerStretch(0.5)) files_mod, typ = [], [] for thisFile in os.listdir(outfolder): if 'mod_azim.fits' in thisFile: files_mod.append(thisFile) if len(files_mod) == 1: typ.append('AZIM') for thisFile in os.listdir(outfolder): if 'mod_local.fits' in thisFile: files_mod.append(thisFile) if len(files_mod) == 2: typ.append('LOCAL') elif (len(files_mod) == 1 and len(typ) == 0): typ.append('LOCAL') elif (len(files_mod) == len(typ) == 0): exit()
def fit_model(data, model, sigma, fit_method='chisq', masking=None, mask_only=False, **kwargs): def chisq(x): return np.sum((data[mask] - x * model[mask])**2 / sigma[mask]**2) / (sum(mask) - 1) def difference(x): return np.sum(np.abs(data[mask] - x * model[mask])) mask = np.array([True for _ in data]) sigmalimit = None if masking is not None: for masktype in masking.split(';'): masktype = masktype.strip().lower() if masktype.startswith('middle'): perinterval = float(masktype[6:]) # Estimate model strength (source rate) by fitting middle % interval = PercentileInterval(perinterval) lim = interval.get_limits(data) mask = (mask & (data >= lim[0]) & (data <= lim[1])) elif (masktype.startswith('minalt')) and ('altitude' in kwargs): minalt = float(masktype[6:]) mask = mask & (kwargs['altitude'] >= minalt) elif masktype.startswith('minalt'): raise InputError('mathMB.fit_model', 'Altitude not supplied.') elif masktype.startswith('minsnr'): minSNR = float(masktype[6:]) snr = data / sigma mask = mask & (snr > minSNR) elif masktype.startswith('siglimit'): sigmalimit = masktype else: raise InputError('MESSENGERdata.fit_model', f'masking = {masktype} not defined.') else: pass if mask_only: return None, None, mask else: available_fitfunctions = ['chisq', 'difference', 'wls'] if np.any(mask) == False: # No data points are included - just do a simple fit for show mask_ = mask.copy() mask[:] = True model_strength = minimize_scalar(difference) mask = mask_ return model_strength.x, model_strength.fun, mask elif fit_method.lower() in available_fitfunctions: if fit_method == 'wls': # Weighted least squares fit wls_model = lm.WLS(model[mask], data[mask], 1. / sigma[mask]**2) result = wls_model.fit() if sigmalimit is not None: siglimit = float(sigmalimit[8:]) diff = (data - model / result.params[0]) / sigma mask = mask & (diff < siglimit * sigma) wls_model = lm.WLS(model[mask], data[mask], 1. / sigma[mask]**2) result = wls_model.fit() else: pass return 1. / result.params[0], result.rsquared, mask else: model_strength = minimize_scalar(eval(fit_method.lower())) if sigmalimit is not None: siglimit = float(sigmalimit[8:]) diff = (data - model_strength.x * model) / sigma mask = mask & (diff < siglimit * sigma) model_strength = minimize_scalar(eval(fit_method.lower())) else: pass return model_strength.x, model_strength.fun, mask else: raise InputError('mathMB.fit_model', f'fit_method = {fit_method} not defined.')
# CHANNEL MAPS: Setting all the needed variables image = fits.open('image/NGC5257_12CO21_pbcor_cube_masked.fits') image_mas = fits.open(outfolder+'mask.fits') xmin, xmax = 345, 615 ymin, ymax = 347, 617 zmin, zmax = 0, 69 data = image[0].data[zmin:zmax+1,ymin:ymax+1,xmin:xmax+1] data_mas = image_mas[0].data[zmin:zmax+1,ymin:ymax+1,xmin:xmax+1] head = image[0].header zsize=data[:,0,0].size cdeltsp=0.1 cont = 0.0182647 v = np.array([1,2,4,8,16,32,64])*cont v_neg = [-cont] interval = PercentileInterval(99.5) vmax = interval.get_limits(data)[1] norm = ImageNormalize(vmin=cont, vmax=vmax, stretch=PowerStretch(0.5)) files_mod, typ = [], [] for thisFile in os.listdir(outfolder): if 'mod_azim.fits' in thisFile: files_mod.append(thisFile) if len(files_mod)==1: typ.append('AZIM') for thisFile in os.listdir(outfolder): if 'mod_local.fits' in thisFile: files_mod.append(thisFile) if len(files_mod)==2: typ.append('LOCAL') elif (len(files_mod)==1 and len(typ)==0): typ.append('LOCAL') elif (len(files_mod)==len(typ)==0): exit()
def poly_plots(snrs): for snr in snrs: print "Fitting polygons and sources to " + snr.name white = fits.open("white/" + snr.name + ".fits") red = fits.open("red/rpj/" + snr.name + ".fits") green = fits.open("green/rpj/" + snr.name + ".fits") blue = fits.open("blue/rpj/" + snr.name + ".fits") white_data = white[0].data red_data = red[0].data green_data = green[0].data blue_data = blue[0].data # rgb = np.dstack([red_data,green_data,blue_data]) xmax = white[0].header["NAXIS1"] ymax = white[0].header["NAXIS2"] w = wcs.WCS(white[0].header) try: pix2deg = white[0].header["CD2_2"] except KeyError: pix2deg = white[0].header["CDELT2"] # Divide by maximum value to normalise # rgb = normalize(rgb, np.nanmin(rgb), np.nanmax(rgb)) # Percentile interval for image normalisation pct = 97.0 interval = PercentileInterval(pct) # vmin, vmax = interval.get_limits(data) # stretch = AsinhStretch(a=0.1) i = interval.get_limits(red_data) r = normalize(red_data, *i) i = interval.get_limits(green_data) g = normalize(green_data, *i) i = interval.get_limits(blue_data) b = normalize(blue_data, *i) rgb = np.dstack([r, g, b]) rgb[np.isnan(rgb)] = 0.0 def update(val): vmin = svmin.val vmax = svmax.val img_white.set_clim([svmin.val, svmax.val]) fig.canvas.draw() fig = newfigure(figsize=(10, 5)) ax_white = fig.add_axes([0.05, 0.15, 0.4, 0.8]) ax_rgb = fig.add_axes([0.55, 0.15, 0.4, 0.8]) img_rgb = ax_rgb.imshow(rgb) img_white = ax_white.imshow(white_data, cmap="gray") cbaxes = fig.add_axes([0.45, 0.1, 0.03, 0.85]) cb = plt.colorbar(img_white, cax=cbaxes, orientation="vertical") axcolor = 'white' axmin = fig.add_axes([0.05, 0.05, 0.1, 0.02], axisbg=axcolor) axmax = fig.add_axes([0.24, 0.05, 0.1, 0.02], axisbg=axcolor) # vmin0 = np.min(white_data) # vmax0 = np.max(white_data) vmin0, vmax0 = interval.get_limits(white_data) # include the slider: cribbed from https://stackoverflow.com/questions/5611805/using-matplotlib-slider-widget-to-change-clim-in-image svmin = Slider(axmin, "vmin", 2 * vmin0, -2 * vmin0, valinit=vmin0) svmax = Slider(axmax, "vmax", -2 * vmax0, 2 * vmax0, valinit=vmax0) svmin.on_changed(update) svmax.on_changed(update) fig.suptitle( 'Left-click = select source, middle-click = source subtract, right-click = select region to exclude from background calculation' ) centerx, centery = w.wcs_world2pix(snr.loc.fk5.ra.value, snr.loc.fk5.dec.value, 0) print centerx, centery major, minor = snr.maj / (2 * pix2deg), snr.min / (2 * pix2deg) for ax in ax_white, ax_rgb: # If you don't do this, it automatically zooms out when you first click on the plot ax.set_xlim(0, xmax) ax.set_ylim(0, ymax) # Plot rough size of SNR -- DAG doesn't include pa information so neither can I ax.plot([centerx, centerx], [centery - major, centery + major], **reticsnr) ax.plot([centerx - minor, centerx + minor], [centery, centery], **reticsnr) polypick = PolyPick(ax_white) rax = fig.add_axes([0.6, 0.0, 0.15, 0.10]) radio = RadioButtons(rax, ("white", "rgb"), active=0) def changeax(axl): if axl == "white": polypick.ax = ax_white plt.sca(ax_white) elif axl == "rgb": polypick.ax = ax_rgb plt.sca(ax_rgb) fig.canvas.draw_idle() radio.on_clicked(changeax) plt.show() # Export pixel co-ordinates as WCS co-ordinates in order to use on any arbitrary image, and save for later polygon = Coords() sources = Coords() exclude = Coords() if len(polypick.coords.x): polygon.x, polygon.y = w.wcs_pix2world( zip(polypick.coords.x, polypick.coords.y), 0).transpose() else: # User has got bored of picking polygons and wants to exit this loop print "No polygon detected; leaving polygon-drawing mode." break if len(polypick.points.x): sources.x, sources.y = w.wcs_pix2world( zip(polypick.points.x, polypick.points.y), 0).transpose() if len(polypick.exclude.x): exclude.x, exclude.y = w.wcs_pix2world( zip(polypick.exclude.x, polypick.exclude.y), 0).transpose() # NB: overwrites data for any old measurements for this live object snr.polygon = polygon snr.sources = sources snr.exclude = exclude return snrs
def make_plots(snrs): for snr in snrs: print "Making attractive FITS image plot for " + snr.name # Normalize and stretch images pct = 95.0 interval = PercentileInterval(pct) # framesize = 3*snr.maj*u.deg framesize = max(1.0, 3 * snr.maj) * u.deg # Load image data mask = fits.open("white/" + snr.name + "_mask.fits") white = fits.open("white/" + snr.name + ".fits") red = fits.open("red/rpj/" + snr.name + ".fits") green = fits.open("green/rpj/" + snr.name + ".fits") blue = fits.open("blue/rpj/" + snr.name + ".fits") # mask_data = mask[0].data # Set mask data to 1.0, NaNs will not be plotted # mask_data[np.where(np.logical_not(np.isnan(mask_data)))] = 1.0 # white_data = white[0].data # red_data = red[0].data # green_data = green[0].data # blue_data = blue[0].data # All GLEAM images and the ancillary image should be the same for all images thanks to regridding stage w_gleam = wcs.WCS(red[0].header) cutout_white = Cutout2D(white[0].data, snr.loc, framesize, wcs=w_gleam) cutout_mask = Cutout2D(mask[0].data, snr.loc, framesize, wcs=w_gleam) cutout_mask.data[np.where(np.logical_not(np.isnan( cutout_mask.data)))] = 1.0 vmin, vmax = interval.get_limits(cutout_white.data) cutout_red = Cutout2D(red[0].data, snr.loc, framesize, wcs=w_gleam) cutout_green = Cutout2D(green[0].data, snr.loc, framesize, wcs=w_gleam) cutout_blue = Cutout2D(blue[0].data, snr.loc, framesize, wcs=w_gleam) ir = interval.get_limits(cutout_red.data) r = normalize(cutout_red.data, *ir) ig = interval.get_limits(cutout_green.data) g = normalize(cutout_green.data, *ig) ib = interval.get_limits(cutout_blue.data) b = normalize(cutout_blue.data, *ib) rgb = np.dstack([r, g, b]) print( "The colour scales for the GLEAM 170--231MHz image and R, G, and B of the RGB cube are {0:2.1f}--{1:2.1f}, {2:2.1f}--{3:2.1f}, {4:2.1f}--{5:2.1f}, and {6:2.1f}--{7:2.1f}\,Jy\perbeam, respectively." .format(vmin, vmax, ir[0], ir[1], ig[0], ig[1], ib[0], ib[1])) # temporary: changing variable names white_data = cutout_white.data mask_data = cutout_mask.data w = cutout_white.wcs # rgb = np.dstack([red_data,green_data,blue_data]) # rgb = normalize(rgb, np.nanmin(rgb), np.nanmax(rgb)) ## Get relevant header info ## Later: add bmaj bmin as ellipse # xmax = white[0].header["NAXIS1"] # ymax = white[0].header["NAXIS2"] xmax, ymax = white_data.shape ## Transform snr polygons into local pixel co-ordinates ## All colours should be on the same projection thanks to Montage so we only have to do this once # w = wcs.WCS(white[0].header) local_polygon = Coords() if len(snr.polygon.x): local_polygon.x, local_polygon.y = w.wcs_world2pix( zip(snr.polygon.x, snr.polygon.y), 0).transpose() local_sources = Coords() if len(snr.sources.x): local_sources.x, local_sources.y = w.wcs_world2pix( zip(snr.sources.x, snr.sources.y), 0).transpose() local_exclude = Coords() if len(snr.exclude.x): local_exclude.x, local_exclude.y = w.wcs_world2pix( zip(snr.exclude.x, snr.exclude.y), 0).transpose() # Using http://docs.astropy.org/en/stable/visualization/wcsaxes/index.html fig = plt.figure(figsize=(6, 6)) fig.set_tight_layout(True) ax_white = fig.add_subplot(221, projection=w) ax_white_mask = fig.add_subplot(222, projection=w) ax_rgb = fig.add_subplot(223, projection=w) ax_rgb_mask = fig.add_subplot(224, projection=w) img_white = ax_white.imshow(white_data, cmap="gray", origin="lower", vmin=vmin, vmax=vmax) img_white_mask = ax_white_mask.imshow(white_data, cmap="gray", origin="lower", vmin=vmin, vmax=vmax) img_white_mask = ax_white_mask.imshow(mask_data, cmap="Blues", origin="lower", alpha=0.2) img_rgb = ax_rgb.imshow(rgb, origin="lower") img_rgb_mask = ax_rgb_mask.imshow(rgb, origin="lower") img_rgb_mask = ax_rgb_mask.imshow(mask_data, cmap="Blues", origin="lower", alpha=0.2) for ax in ax_white_mask, ax_rgb_mask: if len(local_polygon.x): ax.plot(local_polygon.x, local_polygon.y, **restsnr) if len(local_sources.x): ax.plot(local_sources.x, local_sources.y, **srcmark) if len(local_exclude.x): ax.plot(local_exclude.x, local_exclude.y, **restexc) # Tedious removal of axis labels axes = [ax_white, ax_white_mask, ax_rgb, ax_rgb_mask] latleft = [True, False, True, False] #lal latright = [False, True, False, True] #lar lonbottom = [False, False, True, True] #lob lontop = [True, True, False, False] #lot for ax, lal, lar, lob, lot in zip(axes, latleft, latright, lonbottom, lontop): ax.set_xlim(0, xmax) ax.set_ylim(0, ymax) lon = ax.coords['ra'] lat = ax.coords['dec'] if lob: lon.set_axislabel("Right Ascension (J2000)") lon.set_major_formatter('hh:mm') if lal: lat.set_axislabel("Declination (J2000)") lat.set_major_formatter('dd:mm') lon.set_ticklabel_visible(lob) lat.set_ticklabel_visible(lal) lon.set_ticks_visible(lob) lat.set_ticks_visible(lal) overlay = ax.get_coords_overlay("fk5") overlay.grid(axes=ax, color='white', ls='dotted') overlay["ra"].set_ticklabel_visible(lot) if lot: overlay["ra"].set_major_formatter('hh:mm') overlay["dec"].set_ticklabel_visible(lar) if lar: overlay["dec"].set_major_formatter('dd:mm') # output_file = "plots/"+snr.name+".eps" output_file = "plots/" + snr.name + ".png" if os.path.exists(output_file): renumber(output_file) fig.tight_layout(pad=1.0, w_pad=1.0, h_pad=1.0) # fig2.tight_layout(pad=0.4, w_pad=0.5, h_pad=1.0) # fig1.savefig("int_flux_ratio.png",pad_inches=0.1,bbox_inches="tight") # fig2.savefig("divergence.png",pad_inches=0.1,bbox_inches="tight") fig.savefig(output_file, pad_inches=0.1, bbox_inches="tight")
def identify_target(filter, imdrizzlepath): """ Identify target amoung sources catalogued by Source Extractor. INPUTS: -------- filter : string filter of the drizzled image imdrizzle path : string path where full frame drizzled image is located target_name : string optionally provide a target name, default is 'Target' the output catalog is saved using this name """ #open the drizzled image file for given filter imfile = os.path.join(imdrizzlepath, filter + "_drz.fits") try: hdu_list = fits.open(imfile) except IOError: print('The following file does not exist, or could not be opened: %s' ( imfile)) sys.exit() #pull image from hdu_list image_data = hdu_list['SCI'].data #2D numpy array #pull weights from hdu_list wht_data = hdu_list['WHT'].data #2D numpy array #close the fits file hdu_list.close() #where is the subarry data in the full frame? subarr = np.where(wht_data != 0) xmin, ymin = min(subarr[1]), min(subarr[0]) xmax, ymax = max(subarr[1]), max(subarr[0]) #scale the image for display interval = PercentileInterval(99.9) interval.get_limits(image_data) scl_image = interval(image_data) #open the catalog file catfile = os.path.join(imdrizzlepath, filter + '_prep.cat') cat = ascii.read(os.path.join(imdrizzlepath, catfile)) #get the source IDs, x-positions, and y-positions src_id = cat['NUMBER'] src_x = cat['X_IMAGE'] src_y = cat['Y_IMAGE'] #create a figure fig = plt.figure(1) #add a subplot in the bottom left sub = fig.add_subplot(1, 1, 1) #populate the subplot with our image sub.imshow(scl_image**2, cmap='gray_r') #limit the axes to the subarray data sub.set_ylim([ymin, ymax]) sub.set_xlim([xmin, xmax]) #circle the catalog sources on the plot sub.scatter(src_x, src_y, s=130, marker='o', edgecolors='blue', facecolors='none', lw=1.5) #Identify source by ID on plot for i, junk in enumerate(src_id): print(src_id[i], src_x[i], src_y[i]) sub.annotate('%d' % src_id[i], xy=(src_x[i], src_y[i]), xytext=(src_x[i] + 5., src_y[i] + 5.), color='blue', fontsize=14) #Save plot plt.title(filter) plt.savefig(os.path.join(imdrizzlepath, filter + ".pdf")) #Show plot plt.show() #Ask user to identify target target = float(raw_input("Identify the target by entering a number:")) #Create a new catalog file only containing the target for the aXe run: cat.meta = {} #scrub the empty lines of header discard = [i for i, junk in enumerate(src_id) if src_id[i] != target] cat.remove_rows(discard) ascii.write(cat, os.path.join(imdrizzlepath, filter + '_prep_target.cat'))
# CHANNEL MAPS: Setting all the needed variables image = fits.open('NGC5257_12CO21_combine.fits') image_mas = fits.open(outfolder + 'mask.fits') xmin, xmax = 320, 624 ymin, ymax = 336, 640 zmin, zmax = 0, 69 data = image[0].data[zmin:zmax + 1, ymin:ymax + 1, xmin:xmax + 1] data_mas = image_mas[0].data[zmin:zmax + 1, ymin:ymax + 1, xmin:xmax + 1] head = image[0].header zsize = data[:, 0, 0].size cdeltsp = 0.1 cont = 0.012 v = np.array([1, 2, 4, 8, 16, 32, 64]) * cont v_neg = [-cont] interval = PercentileInterval(99.5) vmax = interval.get_limits(data)[1] norm = ImageNormalize(vmin=cont, vmax=vmax, stretch=PowerStretch(0.5)) files_mod, typ = [], [] for thisFile in os.listdir(outfolder): if 'mod_azim.fits' in thisFile: files_mod.append(thisFile) if len(files_mod) == 1: typ.append('AZIM') for thisFile in os.listdir(outfolder): if 'mod_local.fits' in thisFile: files_mod.append(thisFile) if len(files_mod) == 2: typ.append('LOCAL') elif (len(files_mod) == 1 and len(typ) == 0): typ.append('LOCAL') elif (len(files_mod) == len(typ) == 0): exit()
# CHANNEL MAPS: Setting all the needed variables image = fits.open('ngc2403.fits') image_mas = fits.open(outfolder + 'mask.fits') xmin, xmax = 0, 149 ymin, ymax = 0, 149 zmin, zmax = 0, 61 data = image[0].data[zmin:zmax + 1, ymin:ymax + 1, xmin:xmax + 1] data_mas = image_mas[0].data[zmin:zmax + 1, ymin:ymax + 1, xmin:xmax + 1] head = image[0].header zsize = data[:, 0, 0].size cdeltsp = 16 cont = 0.0016617 v = np.array([1, 2, 4, 8, 16, 32, 64]) * cont v_neg = [-cont] interval = PercentileInterval(99.5) vmax = interval.get_limits(data)[1] norm = ImageNormalize(vmin=cont, vmax=vmax, stretch=PowerStretch(0.5)) files_mod, typ = [], [] for thisFile in os.listdir(outfolder): if 'mod_azim.fits' in thisFile: files_mod.append(thisFile) if len(files_mod) == 1: typ.append('AZIM') for thisFile in os.listdir(outfolder): if 'mod_local.fits' in thisFile: files_mod.append(thisFile) if len(files_mod) == 2: typ.append('LOCAL') elif (len(files_mod) == 1 and len(typ) == 0): typ.append('LOCAL') elif (len(files_mod) == len(typ) == 0): exit()
def display_interval(self, channel, percentile): zs = PercentileInterval(percentile) data = self.ds[8]["S001"].sel(channel=channel, z=0).values mask = data > 0 return zs.get_limits(data[mask])