def _data_stretch(image, vmin=None, vmax=None, pmin=0.25, pmax=99.75, stretch='linear', vmid=None, exponent=2): if vmin is None or vmax is None: interval = AsymmetricPercentileInterval(pmin, pmax, n_samples=10000) try: vmin_auto, vmax_auto = interval.get_limits(image) except IndexError: # no valid values vmin_auto = vmax_auto = 0 if vmin is None: log.info("vmin = %10.3e (auto)" % vmin_auto) vmin = vmin_auto else: log.info("vmin = %10.3e" % vmin) if vmax is None: log.info("vmax = %10.3e (auto)" % vmax_auto) vmax = vmax_auto else: log.info("vmax = %10.3e" % vmax) if stretch == 'arcsinh': stretch = 'asinh' normalizer = simple_norm(image, stretch=stretch, power=exponent, asinh_a=vmid, min_cut=vmin, max_cut=vmax, clip=False) data = normalizer(image, clip=True).filled(0) data = np.nan_to_num(data) data = np.clip(data * 255., 0., 255.) return data.astype(np.uint8)
def starfind(setup, path_to_image, reduction_metadata, plot_it=False, log=None): """ The routine will quickly identify stars in a given image and return a star list and image quality parameters. The output is to be used to select suitable candidate images for constructing a template reference image. :param object setup: this is an instance of the ReductionSetup class. See reduction_control.py :param string path_to_image: The full path to the image to be processed. :param object reduction_metadata: The reduction metadata object from which to extract the saturation value. :param boolean plot_it: Do you want to plot the selected stars? :param string log: Full The full path to the log file. :return status, report, params: the first two are strings reporting whether the stage was completed successfully. params is a dictionary with the image quality parameters. :rtype string, string, dictionary """ imname = path_to_image.split('/')[-1] if log != None: log.info('Starting starfind') params = { 'sky': 0.0, 'fwhm_y': 0.0, 'fwhm_x': 0.0, 'corr_xy': 0.0, 'nstars': 0, 'sat_frac': 0.0, 'symmetry': 1. } t0 = time.time() im = fits.open(path_to_image) header = im[0].header scidata = im[0].data # Get size of image ymax, xmax = scidata.shape # If it is a large image, consider 250x250 pixel subregions and # choose the one with the fewest saturated pixels to evaluate stats try: saturation = reduction_metadata.reduction_parameters[1]['MAXVAL'] except: if log != None: status = 'ERROR' report = ('Could not extract the saturation parameter ' 'from the configuration file.') log.info(report) return status, report, params nr_sat_pix = 100000 bestx1 = -1 bestx2 = -1 besty1 = -1 besty2 = -1 regionsx = np.arange(0, xmax, 250) regionsy = np.arange(0, ymax, 250) for i in regionsx[0:-1]: x1 = i x2 = i + 250 for j in regionsy[0:-1]: y1 = j y2 = j + 250 nr_pix = len( scidata[y1:y2, x1:x2][np.where(scidata[y1:y2, x1:x2] > saturation)]) #print x1, x2, y1, y2, nr_pix if nr_pix < nr_sat_pix: nr_sat_pix = nr_pix bestx1 = x1 bestx2 = x2 besty1 = y1 besty2 = y2 #mean, median, std = sigma_clipped_stats(scidata[1:ymax, 1:xmax], sigma=3.0, iters=5) # Evaluate mean, median and standard deviation for the selected subregion mean, median, std = sigma_clipped_stats(scidata[besty1:besty2, bestx1:bestx2], sigma=3.0, iters=5) # Identify stars daofind = DAOStarFinder(fwhm=3.0, threshold=5. * std) sources = daofind(scidata[besty1:besty2, bestx1:bestx2] - median) # Write steps to a log file if log != None: log.info("Identifying sources on image %s ...\n" % path_to_image.split('/')[-1]) log.info("Found %s sources.\n" % str(len(sources))) if len(sources) == 0: status = 'ERROR' report = 'Insufficient number of sources found. Stopping execution.' log.info(report) return status, report, params elif (len(sources) > 0 and len(sources) <= 5): log.info('WARNING: Too few sources detected on image.') else: log.info('Using best sources to determine FWHM (up to 30).') # Discount saturated stars sources = sources[np.where(sources['peak'] < saturation)] sources.sort('peak') sources.reverse() # Store the number of identified sources and fraction of saturated pixels nstars = len(sources) sat_frac = nr_sat_pix / (250. * 250.) # Discount stars too close to the edges of the image sources = sources[np.where((sources['xcentroid'] > 10) & (sources['xcentroid'] < 240) & (sources['ycentroid'] < 240) & (sources['ycentroid'] > 30))] # Keep only up to 100 stars sources = sources[0:100] sources_with_close_stars_ids = [] # Discount stars with close neighbours (within r=10 pix) for i in np.arange(len(sources)): source_i = sources[i] for other_source in sources[i + 1:]: if (np.sqrt( (source_i['xcentroid'] - other_source['xcentroid'])**2 + (source_i['ycentroid'] - other_source['ycentroid'])**2) <= 10): sources_with_close_stars_ids.append(i) #print source_i, other_source continue # Keep up to 30 isolated sources only (may be fewer) sources.remove_rows(sources_with_close_stars_ids) sources = sources[0:30] if log != None: log.info("Kept %s sources.\n" % str(len(sources))) #return sources # Uncomment the following line to display source list in browser window: #sources.show_in_browser() # Fit a model to identified sources and estimate PSF shape parameters sky_arr = [] fwhm_x_arr = [] fwhm_y_arr = [] corr_xy_arr = [] i = 0 while (i <= len(sources) - 1): try: i_peak = sources[i]['peak'] position = [sources[i]['xcentroid'], sources[i]['ycentroid']] #print position stamp_size = (20, 20) cutout = Cutout2D(scidata[besty1:besty2, bestx1:bestx2], position, stamp_size) # in pixels yc, xc = cutout.position_cutout yy, xx = np.indices(cutout.data.shape) fit = psf.fit_star(cutout.data, yy, xx, psf_model='BivariateNormal') fit_params = fit[0] fit_errors = fit[1].diagonal()**0.5 biv = psf.BivariateNormal() background = psf.ConstantBackground() fit_residuals = psf.error_star_fit_function( fit_params, cutout.data, biv, background, yy, xx) fit_residuals = fit_residuals.reshape(cutout.data.shape) cov = fit[1] * np.sum(fit_residuals**2) / ((stamp_size[0])**2 - 6) fit_errors = cov.diagonal()**0.5 #print fit_params model = biv.psf_model(yy, xx, fit_params) fwhm_y_arr.append(fit_params[3]) fwhm_x_arr.append(fit_params[4]) corr_xy_arr.append(fit_params[5]) sky_arr.append(fit_params[6]) if plot_it == True: plt.figure(figsize=(3, 8)) plt.subplot(3, 1, 1) plt.imshow(cutout.data, cmap='gray', origin='lower') plt.colorbar() plt.title("Data") plt.subplot(3, 1, 2) plt.imshow(model, cmap='gray', origin='lower') plt.colorbar() plt.title("Model") plt.subplot(3, 1, 3) plt.imshow(fit_residuals, cmap='gray', origin='lower') plt.title("Residual") plt.colorbar() plt.savefig(path.join(setup.red_dir, 'starfind_model.png')) except: if log != None: log.info("Could not fit source: %s." % str(i)) i = i + 1 # Estimate the median values for the parameters over the stars identified params['sky'] = np.median(sky_arr) params['fwhm_y'] = np.median(fwhm_y_arr) params['fwhm_x'] = np.median(fwhm_x_arr) params['corr_xy'] = np.median(corr_xy_arr) params['nstars'] = nstars params['sat_frac'] = sat_frac try: if xmax > 200 and ymax > 200: psf_emp, psf_error_emp = empirical_psf_simple.empirical_psf_median( np.copy(scidata)[:200, :200], 20, saturation) else: psf_emp, psf_error_emp = empirical_psf_simple.empirical_psf_median( np.copy(scidata), 20, saturation) #imgname = os.path.basename(path_to_image) #hduout=fits.PrimaryHDU(psf_emp) #hduout.writeto('psf_'+imgname,overwrite = True) symmetry_metric = empirical_psf_simple.symmetry_check(psf_emp) params['symmetry'] = symmetry_metric except Exception as e: if log != None: report = ('Could not extract the symmetry based on the PSF ') log.info(report) if log != None: log.info('Measured median values:') log.info('Sky background = ' + str(params['sky'])) log.info('FWHM X = ' + str(params['fwhm_x'])) log.info('FWHM Y = ' + str(params['fwhm_y'])) log.info('Corr XY = ' + str(params['corr_xy'])) log.info('Nstars = ' + str(params['nstars'])) log.info('Saturation fraction = ' + str(params['sat_frac'])) log.info('symmetry = ' + str(params['symmetry'])) # If plot_it is True, plot the sources found if plot_it == True: temp = np.copy(scidata[besty1:besty2, bestx1:bestx2]) temp[np.where(temp < median)] = median temp[np.where(temp > 25000)] = 25000 positions = (sources['xcentroid'], sources['ycentroid']) apertures = CircularAperture(positions, r=4.) norm = ImageNormalize(interval=AsymmetricPercentileInterval(10, 40), stretch=SqrtStretch()) plt.imshow(temp, cmap='gray', origin='lower', norm=norm) plt.title("Data") #plt.colorbar() apertures.plot(color='red', lw=1.2, alpha=0.5) plt.savefig(path.join(setup.red_dir, 'stars250x250.png')) im.close() if log != None: log.info("Finished processing image %s in %.3f seconds.\n" % (str(imname), (time.time() - t0))) status = 'OK' report = 'Completed successfully' return status, report, params
async def get(self, object_id: str = None): """ --- summary: Serve alert cutout as fits or png tags: - alerts - kowalski parameters: - in: query name: instrument required: false schema: type: str - in: query name: candid description: "ZTF alert candid" required: true schema: type: integer - in: query name: cutout description: "retrieve science, template, or difference cutout image?" required: true schema: type: string enum: [science, template, difference] - in: query name: file_format description: "response file format: original loss-less FITS or rendered png" required: true default: png schema: type: string enum: [fits, png] - in: query name: interval description: "Interval to use when rendering png" required: false schema: type: string enum: [min_max, zscale] - in: query name: stretch description: "Stretch to use when rendering png" required: false schema: type: string enum: [linear, log, asinh, sqrt] - in: query name: cmap description: "Color map to use when rendering png" required: false schema: type: string enum: [bone, gray, cividis, viridis, magma] responses: '200': description: retrieved cutout content: image/fits: schema: type: string format: binary image/png: schema: type: string format: binary '400': description: retrieval failed content: application/json: schema: Error """ instrument = self.get_query_argument("instrument", "ZTF").upper() if instrument not in INSTRUMENTS: raise ValueError("Instrument name not recognised") # allow access to public data only by default selector = {1} for stream in self.associated_user_object.streams: if "ztf" in stream.name.lower(): selector.update(set(stream.altdata.get("selector", []))) selector = list(selector) try: candid = int(self.get_argument("candid")) cutout = self.get_argument("cutout").capitalize() file_format = self.get_argument("file_format", "png").lower() interval = self.get_argument("interval", default=None) stretch = self.get_argument("stretch", default=None) cmap = self.get_argument("cmap", default=None) known_cutouts = ["Science", "Template", "Difference"] if cutout not in known_cutouts: return self.error( f"Cutout {cutout} of {object_id}/{candid} not in {str(known_cutouts)}" ) known_file_formats = ["fits", "png"] if file_format not in known_file_formats: return self.error( f"File format {file_format} of {object_id}/{candid}/{cutout} not in {str(known_file_formats)}" ) normalization_methods = { "asymmetric_percentile": AsymmetricPercentileInterval( lower_percentile=1, upper_percentile=100 ), "min_max": MinMaxInterval(), "zscale": ZScaleInterval(nsamples=600, contrast=0.045, krej=2.5), } if interval is None: interval = "asymmetric_percentile" normalizer = normalization_methods.get( interval.lower(), AsymmetricPercentileInterval(lower_percentile=1, upper_percentile=100), ) stretching_methods = { "linear": LinearStretch, "log": LogStretch, "asinh": AsinhStretch, "sqrt": SqrtStretch, } if stretch is None: stretch = "log" if cutout != "Difference" else "linear" stretcher = stretching_methods.get(stretch.lower(), LogStretch)() if (cmap is None) or ( cmap.lower() not in ["bone", "gray", "cividis", "viridis", "magma"] ): cmap = "bone" else: cmap = cmap.lower() query = { "query_type": "find", "query": { "catalog": "ZTF_alerts", "filter": { "candid": candid, "candidate.programid": {"$in": selector}, }, "projection": {"_id": 0, f"cutout{cutout}": 1}, }, "kwargs": {"limit": 1, "max_time_ms": 5000}, } response = kowalski.query(query=query) if response.get("status", "error") == "success": alert = response.get("data", [dict()])[0] else: return self.error("No cutout found.") cutout_data = bj.loads(bj.dumps([alert[f"cutout{cutout}"]["stampData"]]))[0] # unzipped fits name fits_name = pathlib.Path(alert[f"cutout{cutout}"]["fileName"]).with_suffix( "" ) # unzip and flip about y axis on the server side with gzip.open(io.BytesIO(cutout_data), "rb") as f: with fits.open(io.BytesIO(f.read())) as hdu: header = hdu[0].header data_flipped_y = np.flipud(hdu[0].data) if file_format == "fits": hdu = fits.PrimaryHDU(data_flipped_y, header=header) hdul = fits.HDUList([hdu]) stamp_fits = io.BytesIO() hdul.writeto(fileobj=stamp_fits) self.set_header("Content-Type", "image/fits") self.set_header( "Content-Disposition", f"Attachment;filename={fits_name}" ) self.write(stamp_fits.getvalue()) if file_format == "png": buff = io.BytesIO() plt.close("all") fig, ax = plt.subplots(figsize=(4, 4)) fig.subplots_adjust(0, 0, 1, 1) ax.set_axis_off() # replace nans with median: img = np.array(data_flipped_y) # replace dubiously large values xl = np.greater(np.abs(img), 1e20, where=~np.isnan(img)) if img[xl].any(): img[xl] = np.nan if np.isnan(img).any(): median = float(np.nanmean(img.flatten())) img = np.nan_to_num(img, nan=median) norm = ImageNormalize(img, stretch=stretcher) img_norm = norm(img) vmin, vmax = normalizer.get_limits(img_norm) ax.imshow(img_norm, cmap=cmap, origin="lower", vmin=vmin, vmax=vmax) plt.savefig(buff, dpi=42) buff.seek(0) plt.close("all") self.set_header("Content-Type", "image/png") self.write(buff.getvalue()) except Exception: _err = traceback.format_exc() return self.error(f"failure: {_err}")
def display_single(img, pixel_scale=0.168, physical_scale=None, xsize=8, ysize=8, ax=None, alpha=1.0, stretch='arcsinh', scale='zscale', zmin=None, zmax=None, contrast=0.25, no_negative=False, lower_percentile=1.0, upper_percentile=99.0, cmap=IMG_CMAP, scale_bar=True, scale_bar_length=5.0, scale_bar_fontsize=20, scale_bar_y_offset=0.5, scale_bar_color='w', scale_bar_loc='left', color_bar=False, color_bar_loc=1, color_bar_width='75%', color_bar_height='5%', color_bar_fontsize=18, color_bar_color='w', add_text=None, text_fontsize=30, text_color='w'): """Display single image. Parameters ---------- img: np 2-D array for image xsize: int, default = 8 Width of the image. ysize: int, default = 8 Height of the image. """ if ax is None: fig = plt.figure(figsize=(xsize, ysize)) ax1 = fig.add_subplot(111) else: ax1 = ax # Stretch option if stretch.strip() == 'arcsinh': img_scale = np.arcsinh(img) if zmin is not None: zmin = np.arcsinh(zmin) if zmax is not None: zmax = np.arcsinh(zmax) elif stretch.strip() == 'log': if no_negative: img[img <= 0.0] = 1.0E-10 img_scale = np.log(img) if zmin is not None: zmin = np.log(zmin) if zmax is not None: zmax = np.log(zmax) elif stretch.strip() == 'log10': if no_negative: img[img <= 0.0] = 1.0E-10 img_scale = np.log10(img) if zmin is not None: zmin = np.log10(zmin) if zmax is not None: zmax = np.log10(zmax) elif stretch.strip() == 'linear': img_scale = img else: raise Exception("# Wrong stretch option.") # Scale option if scale.strip() == 'zscale': try: vmin, vmax = ZScaleInterval( contrast=contrast).get_limits(img_scale) except IndexError: # TODO: Deal with problematic image vmin, vmax = -1.0, 1.0 elif scale.strip() == 'percentile': try: vmin, vmax = AsymmetricPercentileInterval( lower_percentile=lower_percentile, upper_percentile=upper_percentile).get_limits(img_scale) except IndexError: # TODO: Deal with problematic image vmin, vmax = -1.0, 1.0 elif scale.strip() == 'minmax': vmin, vmax = np.nanmin(img_scale), np.nanmax(img_scale) else: vmin, vmax = np.nanmin(img_scale), np.nanmax(img_scale) if zmin is not None: vmin = zmin if zmax is not None: vmax = zmax show = ax1.imshow(img_scale, origin='lower', cmap=cmap, interpolation='none', vmin=vmin, vmax=vmax, alpha=alpha) # Hide ticks and tick labels ax1.tick_params(labelbottom=False, labelleft=False, axis=u'both', which=u'both', length=0) # Put scale bar on the image (img_size_x, img_size_y) = img.shape if physical_scale is not None: pixel_scale *= physical_scale if scale_bar: if scale_bar_loc == 'left': scale_bar_x_0 = int(img_size_x * 0.04) scale_bar_x_1 = int(img_size_x * 0.04 + (scale_bar_length / pixel_scale)) else: scale_bar_x_0 = int(img_size_x * 0.95 - (scale_bar_length / pixel_scale)) scale_bar_x_1 = int(img_size_x * 0.95) scale_bar_y = int(img_size_y * 0.10) scale_bar_text_x = (scale_bar_x_0 + scale_bar_x_1) / 2 scale_bar_text_y = (scale_bar_y * scale_bar_y_offset) if physical_scale is not None: scale_bar_text = r'$%d\ \mathrm{kpc}$' % int(scale_bar_length) else: scale_bar_text = r'$%d^{\prime\prime}$' % int(scale_bar_length) scale_bar_text_size = scale_bar_fontsize ax1.plot([scale_bar_x_0, scale_bar_x_1], [scale_bar_y, scale_bar_y], linewidth=3, c=scale_bar_color, alpha=1.0) ax1.text(scale_bar_text_x, scale_bar_text_y, scale_bar_text, fontsize=scale_bar_text_size, horizontalalignment='center', color=scale_bar_color) if add_text is not None: text_x_0 = int(img_size_x * 0.08) text_y_0 = int(img_size_y * 0.80) ax1.text(text_x_0, text_y_0, r'$\mathrm{' + add_text + '}$', fontsize=text_fontsize, color=text_color) # Put a color bar on the image if color_bar: ax_cbar = inset_axes(ax1, width=color_bar_width, height=color_bar_height, loc=color_bar_loc) if ax is None: cbar = plt.colorbar(show, ax=ax1, cax=ax_cbar, orientation='horizontal') else: cbar = plt.colorbar(show, ax=ax, cax=ax_cbar, orientation='horizontal') cbar.ax.xaxis.set_tick_params(color=color_bar_color) cbar.ax.yaxis.set_tick_params(color=color_bar_color) cbar.outline.set_edgecolor(color_bar_color) plt.setp(plt.getp(cbar.ax.axes, 'xticklabels'), color=color_bar_color, fontsize=color_bar_fontsize) plt.setp(plt.getp(cbar.ax.axes, 'yticklabels'), color=color_bar_color, fontsize=color_bar_fontsize) if ax is None: return fig return ax1
#kde = stats.gaussian_kde(imx) #density = kde(imx) #peak = max(peak,0.01) #low_perc = max(low_perc,0.01) # set 1% as the minimum cut #print ("Histo Peak at %f, will use it as lower percentile (i.e. remove everything below)"%(h_peak)) # #peak_norm = (peak - np.min(bins1))/(np.max(bins1) - np.min(bins1)) #print ("Normalized peak is at %f"%(peak_norm)) #n1, bins1, patches1 = plt.hist(image[~np.isnan(image)], 50, normed=1, facecolor='green', histtype='step',alpha=0.75) # #%% fig = plt.figure(figsize=(10, 10)) norm = ImageNormalize(image, interval=AsymmetricPercentileInterval( mode_x * 100, 99.5), stretch=AsinhStretch()) #norm = ImageNormalize(image,interval=PercentileInterval(98),stretch=SqrtStretch()) #norm = ImageNormalize(image,interval=PercentileInterval(99.5),stretch=LogStretch()) ax = fig.add_subplot(111) ax.imshow(image, cmap=cm.gray, norm=norm, origin="lower", interpolation="nearest") ax.get_xaxis().set_ticks([]) ax.get_yaxis().set_ticks([]) ax.annotate("%s, %i %s" % (target, myObsid, band), textcoords='axes fraction', fontsize=10, xy=(0.05, 0.95),
def display_single(img, pixel_scale=0.168, physical_scale=None, xsize=8, ysize=8, ax=None, stretch='arcsinh', scale='zscale', scale_manual=None, contrast=0.25, no_negative=False, lower_percentile=1.0, upper_percentile=99.0, cmap=IMG_CMAP, scale_bar=True, scale_bar_length=5.0, scale_bar_fontsize=20, scale_bar_y_offset=0.5, scale_bar_color='w', scale_bar_alpha=1.0, scale_bar_loc='left', color_bar=False, color_bar_loc=1, color_bar_width='75%', color_bar_height='5%', color_bar_fontsize=18, color_bar_color='w', add_text=None, text_fontsize=30, text_box=None, text_facecolor='gray', text_x_offset=0.08, text_y_offset=0.80, text_color='w', text_fontweight='normal'): """ Display single image using ``arcsinh`` stretching, "zscale" scaling and ``viridis`` colormap as default. This function is from ``kungpao`` https://github.com/dr-guangtou/kungpao. Parameters: img (numpy 2-D array): The image array. pixel_scale (float): The pixel size, in unit of "arcsec/pixel". physical_scale (bool): Whether show the image in physical scale. xsize (int): Width of the image, default = 8. ysize (int): Height of the image, default = 8. ax (``matplotlib.pyplot.axes`` object): The user could provide axes on which the figure will be drawn. stretch (str): Stretching schemes. Options are "arcsinh", "log", "log10" and "linear". scale (str): Scaling schemes. Options are "zscale" and "percentile". contrast (float): Contrast of figure. no_negative (bool): If true, all negative pixels will be set to zero. lower_percentile (float): Lower percentile, if using ``scale="percentile"``. upper_percentile (float): Upper percentile, if using ``scale="percentile"``. cmap (str): Colormap. scale_bar (bool): Whether show scale bar or not. scale_bar_length (float): The length of scale bar. scale_bar_y_offset (float): Offset of scale bar on y-axis. scale_bar_fontsize (float): Fontsize of scale bar ticks. scale_bar_color (str): Color of scale bar. scale_bar_alpha (float): alpha of scale bar. scale_bar_loc (str): Scale bar position, options are "left" and "right". color_bar (bool): Whether show colorbar or not. add_text (str): The text you want to add to the figure. Note that it is wrapped within ``$\mathrm{}$``. text_fontsize (float): Fontsize of text. text_y_offset (float): Offset of text on y-axis. text_color (str): Color of text. text_box (dict): dictionary for box. Such as `dict(boxstyle='round', facecolor='wheat', alpha=0.5)`. Returns: ax: If the input ``ax`` is not ``None``. """ from PIL import Image, ImageOps if ax is None: fig = plt.figure(figsize=(xsize, ysize)) ax1 = fig.add_subplot(111) else: ax1 = ax if isinstance(img, Image.Image): img = ImageOps.flip(img) show = ax1.imshow( img, origin='lower', cmap=cmap, ) (img_size_x, img_size_y) = img.size else: (img_size_x, img_size_y) = img.shape # Stretch option if stretch.strip() == 'arcsinh': img_scale = np.arcsinh(img) elif stretch.strip() == 'log': if no_negative: img[img <= 0.0] = 1.0E-10 img_scale = np.log(img) elif stretch.strip() == 'log10': if no_negative: img[img <= 0.0] = 1.0E-10 img_scale = np.log10(img) elif stretch.strip() == 'linear': img_scale = img else: raise Exception("# Wrong stretch option.") # Scale option if scale.strip() == 'zscale': try: zmin, zmax = ZScaleInterval( contrast=contrast).get_limits(img_scale) except IndexError: # TODO: Deal with problematic image zmin, zmax = -1.0, 1.0 elif scale.strip() == 'percentile': try: zmin, zmax = AsymmetricPercentileInterval( lower_percentile=lower_percentile, upper_percentile=upper_percentile).get_limits(img_scale) except IndexError: # TODO: Deal with problematic image zmin, zmax = -1.0, 1.0 else: zmin, zmax = np.nanmin(img_scale), np.nanmax(img_scale) if scale_manual is not None: assert len( scale_manual) == 2, '# length of manual scale must be two!' zmin, zmax = scale_manual show = ax1.imshow(img_scale, origin='lower', cmap=cmap, vmin=zmin, vmax=zmax) # Hide ticks and tick labels ax1.tick_params(labelbottom=False, labelleft=False, axis=u'both', which=u'both', length=0) #ax1.axis('off') # Put scale bar on the image if physical_scale is not None: pixel_scale *= physical_scale if scale_bar: if scale_bar_loc == 'left': scale_bar_x_0 = int(img_size_x * 0.04) scale_bar_x_1 = int(img_size_x * 0.04 + (scale_bar_length / pixel_scale)) else: scale_bar_x_0 = int(img_size_x * 0.95 - (scale_bar_length / pixel_scale)) scale_bar_x_1 = int(img_size_x * 0.95) scale_bar_y = int(img_size_y * 0.10) scale_bar_text_x = (scale_bar_x_0 + scale_bar_x_1) / 2 scale_bar_text_y = (scale_bar_y * scale_bar_y_offset) if physical_scale is not None: if scale_bar_length > 1000: scale_bar_text = r'$%d\ \mathrm{Mpc}$' % int( scale_bar_length / 1000) else: scale_bar_text = r'$%d\ \mathrm{kpc}$' % int(scale_bar_length) else: if scale_bar_length < 60: scale_bar_text = r'$%d^{\prime\prime}$' % int(scale_bar_length) elif 60 < scale_bar_length < 3600: scale_bar_text = r"%d arcmin" % int( scale_bar_length / 60) # r'$%d^{\prime}$' else: scale_bar_text = r'$%d^{\circ}$' % int(scale_bar_length / 3600) scale_bar_text_size = scale_bar_fontsize ax1.plot([scale_bar_x_0, scale_bar_x_1], [scale_bar_y, scale_bar_y], linewidth=5, c=scale_bar_color, alpha=scale_bar_alpha) ax1.text(scale_bar_text_x, scale_bar_text_y, scale_bar_text, fontsize=scale_bar_text_size, fontweight=text_fontweight, horizontalalignment='center', color=scale_bar_color, alpha=scale_bar_alpha) if add_text is not None: text_x_0 = int(img_size_x * text_x_offset) text_y_0 = int(img_size_y * text_y_offset) ax1.text(text_x_0, text_y_0, add_text, horizontalalignment='left', verticalalignment='top', fontsize=text_fontsize, color=text_color, bbox=text_box, fontweight=text_fontweight) # Put a color bar on the image if color_bar: ax_cbar = inset_axes(ax1, width=color_bar_width, height=color_bar_height, loc=color_bar_loc) if ax is None: cbar = plt.colorbar(show, ax=ax1, cax=ax_cbar, orientation='horizontal') else: cbar = plt.colorbar(show, ax=ax, cax=ax_cbar, orientation='horizontal') cbar.ax.xaxis.set_tick_params(color=color_bar_color) cbar.ax.yaxis.set_tick_params(color=color_bar_color) cbar.outline.set_edgecolor(color_bar_color) plt.setp(plt.getp(cbar.ax.axes, 'xticklabels'), color=color_bar_color, fontsize=color_bar_fontsize) plt.setp(plt.getp(cbar.ax.axes, 'yticklabels'), color=color_bar_color, fontsize=color_bar_fontsize) if ax is None: return fig return ax1
#pl.subplots_adjust(left=panel_rect[0], bottom=panel_rect[1], right=panel_rect[0]+panel_rect[2], top=panel_rect[1]+panel_rect[3]) pl.imshow(FitsImage, cmap='gray', origin='lower', aspect='equal', norm=LogNorm()) #cb = pl.colorbar() # # Save eps # fig.savefig('%s.scale.log.jpg'%(FitsFile), format='jpg') print('Output to %s'%('%s.scale.log.jpg'%(FitsFile))) # # Plot the fits image in 99.5 percentile # if [[ 1 == 0 ]]; then pl.cla() #fig.delaxes(fig.axes[-1]) # remove previous colorbar #pl.subplots_adjust(left=panel_rect[0], bottom=panel_rect[1], right=panel_rect[0]+panel_rect[2], top=panel_rect[1]+panel_rect[3]) normfun = ImageNormalize(FitsImage, interval=AsymmetricPercentileInterval(19.5,99.5)) pl.imshow(FitsImage, cmap='gray', origin='lower', aspect='equal', norm=normfun) #cb = pl.colorbar() # # Save eps # fig.savefig('%s.scale.995.jpg'%(FitsFile), format='jpg') print('Output to %s'%('%s.scale.995.jpg'%(FitsFile))) print('Done!')
def plot_rgb(self, filters, ax=None, ra=None, dec=None, radius=None, north=True, rscale=2, upper_scale=99.7, lower_scale=1, asinh_factor=0.7): """ Given a filter, makes a normalized, asinh-stretched plot of a galaxy. INPUTS: filters: list of filter names [red, green, blue] e.g. ["i", "r", "g"] ax: axis to plot on. If None, create a new plot north: align the data North? Default: True rpet: radius of the galaxy. If None, use "size" from the Galaxy object xc, yc: pixel coordinates of image center. If None, use ra, dec of Galaxy rpet_scale: image scale in terms of galaxy radii upper_scale, lower_scale: scales used in normalization. By default, upper_scale is given in metadata or 99.7; lower_scale is 1 """ # Load the images for each filter data = {"r": {}, "g": {}, "b": {}} for filt, key in zip(filters, data): node = self.data[filt] data[key]["img"] = node["img"][()] data[key]["wcs"] = attr_to_wcs(node.attrs) data[key]["pxscale"] = node.attrs["pxscale"] # If ra, dec and rpet are not passed, populate them using galaxy properties if ra is None or dec is None or radius is None: ra, dec, radius = self.ra, self.dec, self.size # Resize all images for k, v in data.items(): v["img"], v["wcs"] = _resize(v["img"], v["wcs"], ra, dec, v["pxscale"], radius, scale=rscale) # Create a WCS to reproject the images to using blue WCS (north-aligned?) rgb_wcs = data["b"]["wcs"].deepcopy() if north: rgb_pxscale = data["b"]["pxscale"] rgb_wcs = _rotate_wcs(rgb_wcs, ra, dec, rgb_pxscale) # Define stretch and norm try: upper_scale = self.data.attrs["uscale"] except: pass stretch = AsinhStretch(asinh_factor) norm = AsymmetricPercentileInterval(lower_scale, upper_scale) norm_r = AsymmetricPercentileInterval(lower_scale, upper_scale - 0.1) # Reproject all data onto this new WCS, apply norm and stretch for k, v in data.items(): img = reproject_interp((v["img"], v["wcs"]), rgb_wcs, shape_out=data["b"]["img"].shape)[ 0] #data["b"]["img"].shape)[0] img = stretch(norm_r(img)) if k == "r" else stretch(norm(img)) v["plot_img"] = img # Make a data cube rgb = np.dstack([val["plot_img"] for key, val in data.items()]) # If ax=None, create figure if ax is None: fig = plt.figure(figsize=(6, 6)) ax = plt.axes() ax.axis('off') ax.imshow(rgb, origin="lower")
def normalize_img(img_arr, stretch='asinh', minmax_percent=None, minmax_value=None, invert=False): """ Apply given stretch and scaling to an image array. Parameters ---------- img_arr : array The input image array. stretch : str Optional, default 'asinh'. The stretch to apply to the image array. Valid values are: asinh, sinh, sqrt, log, linear minmax_percent : array Optional. Interval based on a keeping a specified fraction of pixels (can be asymmetric) when scaling the image. The format is [lower percentile, upper percentile], where pixel values below the lower percentile and above the upper percentile are clipped. Only one of minmax_percent and minmax_value shoul be specified. minmax_value : array Optional. Interval based on user-specified pixel values when scaling the image. The format is [min value, max value], where pixel values below the min value and above the max value are clipped. Only one of minmax_percent and minmax_value should be specified. invert : bool Optional, default False. If True the image is inverted (light pixels become dark and vice versa). Returns ------- response : array The normalized image array, in the form in an integer arrays with values in the range 0-255. """ # Setting up the transform with the stretch if stretch == 'asinh': transform = AsinhStretch() elif stretch == 'sinh': transform = SinhStretch() elif stretch == 'sqrt': transform = SqrtStretch() elif stretch == 'log': transform = LogStretch() elif stretch == 'linear': transform = LinearStretch() else: raise InvalidInputError("Stretch {} is not supported!".format(stretch)) # Adding the scaling to the transform if minmax_percent is not None: transform += AsymmetricPercentileInterval(*minmax_percent) if minmax_value is not None: warnings.warn("Both minmax_percent and minmax_value are set, minmax_value will be ignored.", InputWarning) elif minmax_value is not None: transform += ManualInterval(*minmax_value) else: # Default, scale the entire image range to [0,1] transform += MinMaxInterval() # Performing the transform and then putting it into the integer range 0-255 norm_img = transform(img_arr) norm_img = np.multiply(255, norm_img, out=norm_img) norm_img = norm_img.astype(np.uint8) # Applying invert if requested if invert: norm_img = 255 - norm_img return norm_img
imdss = sax.imshow(dssdata, transform=sax.get_transform(dssw), cmap='bone', vmin=vmin+dmad) textent = None talpha = .66 else: sax = plt.subplot() textent = [column, column+args.size, row, row+args.size] talpha = 1 lcmap = cmap_map(lambda x: 0.6*x, cm.get_cmap(args.cmap)) #stamp = sax.imshow(np.log10(np.nanmedian(flux[::10], axis=0)), # cmap=lcmap, origin='lower', aspect='equal', alpha=talpha, # extent=textent) mstamp = np.nanmedian(flux[::10], axis=0) norm = ImageNormalize(mstamp, interval=AsymmetricPercentileInterval(0,100), stretch=LogStretch(a=250)) stamp = sax.imshow(mstamp, cmap=lcmap, origin='lower', aspect='equal', alpha=talpha, extent=textent, norm=norm) xm, ym = pixel_border(dap[bidx]) for xi,yi in zip(xm, ym): if args.pngdss: sax.plot(xi, yi, color='#FF0043', lw=1.5, transform=sax.get_transform('pixel')) else: sax.plot(column+xi, row+yi, color='#FF0043', lw=1.5) #sax.grid(which='minor', zorder=99) #sax.grid(color='white')
def get_regstat(fixed_image, moving_image, out_stats, out_tm, out_qc, tm): x = [[]] time1 = time.time() # loading images target = plt.imread(fixed_image) #tar=cv2.imread(fixed_image) target_name = os.path.split(fixed_image)[1] # print(target_name) # target=cv2.resize(target,(5705,5705)) # tar=cv2.resize(tar,(5705,5705)) moving = plt.imread(moving_image) #mov=cv2.imread(moving_image) # moving=cv2.resize(moving,(5705,5705)) # mov=cv2.resize(mov,(5705,5705)) moving_name = os.path.split(moving_image)[-1] # print(moving_name) # registration #a=target.shape[0] b=target.shape[1] #moving=cv2.resize(moving,(b,b)) mov_avg=np.mean(moving.astype("float")) print(target.shape) print(moving.shape) res=ird.similarity(target,moving) def_moving=res['timg'] scale=res['scale'] angle=res['angle'] (t0,t1)=res['tvec'] #def_moving, scale, angle, (t0, t1) = imreg.similarity(target, moving) def_mov_array=imreg.similarity_matrix(scale,angle,(t0,t1)) np.save(out_tm, def_mov_array) def_avg=np.mean(def_moving.astype("float")) # def_moving=cv2.resize(def_moving,(5705,5705)) time2 = time.time() ti = time2-time1 # statistical results cc = np.corrcoef(moving.flat, target.flat) r1 = cc[0, 1] score1, diff = compare_ssim(target, moving, full=True, multichannel=True) loss_before = 0.5*(1-r1) + 0.5*(1-score1) cc = np.corrcoef(def_moving.flat, target.flat) r2 = cc[0, 1] score2, diff = compare_ssim(def_moving, target, full=True) loss_after = 0.5*(1-r2) + 0.5*(1-score2) mi_bef = mutual_info_score(moving.ravel(), target.ravel()) mi_aft = mutual_info_score(target.ravel(), def_moving.ravel()) mae = np.sum(np.absolute(target.astype("float") - moving.astype("float"))) u1 = np.sum(target.astype("float") + moving.astype("float")) mean_before = np.divide(mae, u1) u2 = np.sum(target.astype("float") + def_moving.astype("float")) mae = np.sum(np.absolute(target.astype( "float") - def_moving.astype("float"))) mean_after = np.divide(mae, u2) t = Texttable() #print(def_moving.shape) if mi_aft > mi_bef: plt.imsave(tm, def_moving,cmap='gray') else: plt.imsave(tm, moving,cmap='gray') # plt.imsave(tm,def_moving,cmap='gray') x.append([target_name, moving_name, r1, r2, score1, score2, loss_before, loss_after, mi_bef, mi_aft, mean_before, mean_after,mov_avg,def_avg, ti]) t.add_rows(x) t.set_cols_align(['r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r','r', 'r']) t.header(['TARGET', 'MOVING', 'PCC_BEFORE', 'PCC_AFTER', 'SSIM_BEFORE', 'SSIM_AFTER', 'loss_BEFORE', 'loss_AFTER', 'MI_BEFORE', 'MI_AFTER', 'MEAN_BEFORE', 'MEAN_AFTER', 'AVERAGE_INTENSITY_BEFORE', 'AVERAGE_INTENSITY_AFTER','TIME']) def_mov1 = cv2.imread(tm,0) # plotting the results transform = AsinhStretch() + AsymmetricPercentileInterval(0.1, 99.99) targ= transform(target) #targ=cv2.cvtColor(targ.astype(np.uint8),cv2.COLOR_GRAY2RGB) #targ_im=Image.fromarray(targ) plt.imsave('target.tiff', targ, cmap='gray') #plt.imsave(r'/media/u0132399/L-drive/GBW-0075_MILAN_Multiplex/u0140317/registration_comparison/imreg/output_images/target.tiff', targ, cmap='gray') movi = transform(moving) #movi=cv2.cvtColor(movi.astype(np.uint8),cv2.COLOR_GRAY2BGR) plt.imsave('moving.tiff', movi, cmap='gray') #movi_im=Image.fromarray(movi) #plt.imsave(r'/media/u0132399/L-drive/GBW-0075_MILAN_Multiplex/u0140317/registration_comparison/imreg/output_images/moving.tiff', movi, cmap='gray') targ = cv2.imread('target.tiff') #targ=Image.open(targ_im) movi= cv2.imread('moving.tiff') #movi=Image.open(movi_im) #targ = cv2.imread( r'/media/u0132399/L-drive/GBW-0075_MILAN_Multiplex/u0140317/registration_comparison/imreg/output_images/target.tiff') #movi = cv2.imread(r'/media/u0132399/L-drive/GBW-0075_MILAN_Multiplex/u0140317/registration_comparison/imreg/output_images/moving.tiff') # def_mov1=cv2.resize(def_mov1,(5705,5705)) def_mov1 = transform(def_mov1) #print(def_mov2.shape) #def_mov1=cv2.cvtColor(def_mov1.astype(np.uint8),cv2.COLOR_GRAY2BGR) plt.imsave('def_moving.tiff', def_mov1, cmap='gray') #def_mov1=Image.fromarray(def_mov1) #plt.imsave('/media/u0132399/L-drive/GBW-0075_MILAN_Multiplex/u0140317/registration_comparison/imreg/output_images/def_moving.tiff', def_mov1, cmap='gray') def_mov1 = cv2.imread('def_moving.tiff') #def_mov1=Image.open(def_mov1) #def_mov1 = cv2.imread(r'/media/u0132399/L-drive/GBW-0075_MILAN_Multiplex/u0140317/registration_comparison/imreg/output_images/def_moving.tiff') #targ = targ.astype(np.uint8) #movi = movi.astype(np.uint8) #def_mov1 = def_mov1.astype(np.uint8) tar1 = np.zeros(targ.shape) mov1 = np.zeros(movi.shape) def_mov = np.zeros(def_mov1.shape) tar1[:, :, 0] = targ[:, :, 0] mov1[:, :, 2] = movi[:, :, 2] def_mov[:, :, 2] = def_mov1[:, :, 2] tar1 = tar1.astype(np.uint8) mov1 = mov1.astype(np.uint8) def_mov = def_mov.astype(np.uint8) # mov[np.where((mov>[15]).all(axis=2))]=[255,0,0] # def_mov1[np.where((def_mov1>[15]).all(axis=2))]=[255,0,0] alpha = 1 beta = 1 gamma = 0 t1 = cv2.addWeighted(tar1, alpha, mov1, beta, gamma) # filename=target_name+moving_name+'unreg_imreg.tif' # cv2.imwrite(,t1) t2 = cv2.addWeighted(tar1, alpha, def_mov, beta, gamma) # filename=target_name+moving_name+'reg_imreg.tif' # cv2.imwrite(filename,t2) if mi_aft > mi_bef: cv2.imwrite(out_qc, t2) else: cv2.imwrite(out_qc, t1) # plt.figure(figsize=(10,10)) # plt.axis('off') # plt.imshow(t1,cmap='gray') # plt.show(block=False) # plt.pause(5) # plt.close() # plt.figure(figsize=(10,10)) # plt.axis('off') # plt.imshow(t2,cmap='gray') # plt.show(block=False) # plt.pause(5) # plt.close() df = pd.DataFrame(x, columns=['TARGET', 'MOVING', 'PCC_BEFORE', 'PCC_AFTER', 'SSIM_BEFORE', 'SSIM_AFTER', 'loss_BEFORE', 'loss_AFTER', 'MI_BEFORE', 'MI_AFTER', 'MEAN_BEFORE', 'MEAN_AFTER','AVERAGE_INTENSITY_BEFORE', 'AVERAGE_INTENSITY_AFTER', 'TIME']) #df[columns]= ['PCC_BEFORE','PCC_AFTER','SSIM_BEFORE' ,'SSIM_AFTER','loss_BEFORE','loss_AFTER','MI_BEFORE','MI_AFTER','MEAN_BEFORE','MEAN_AFTER'] #writer = pd.ExcelWriter(out_stats) df.to_csv(out_stats, index=None, header=True) # writer.save() #print(t.draw()) return t
def as_array(self, interval_r=AsymmetricPercentileInterval(2.5, 99.0), interval_g=AsymmetricPercentileInterval(5., 99.2), interval_b=AsymmetricPercentileInterval(10., 99.2)): """Returns the colour image as a MxNx3 (RGB) array.""" # First we determine the shifts cx, cy = 2050, 1024 # central coordinates of the image maxshiftx, maxshifty = 0, 0 aligned_imgs = {} for idx, band in enumerate(self.filenames.keys()): fn = self.filenames[band] hdu = fits.open(os.path.join(VPHAS_DATA_PATH, fn))[self.ccd] wcs = WCS(hdu.header) img = hdu.data if idx == 0: # The first image acts as reference cra, cdec = wcs.wcs_pix2world(cx, cy, 1) else: # For all subsequent images, compute the shift using the WCS refx, refy = wcs.wcs_world2pix(cra, cdec, 1) shiftx = int(refx - cx) shifty = int(refy - cy) # Now apply the required shift to the image if shiftx > 0: img = np.pad(img, ((0, 0), (0, shiftx)), mode=str('constant'))[:, shiftx:] elif shiftx < 0: img = np.pad(img, ((0, 0), (-shiftx, 0)), mode=str('constant'))[:, :shiftx] if shifty > 0: img = np.pad(img, ((0, shifty), (0, 0)), mode=str('constant'))[shifty:, :] elif shifty < 0: img = np.pad(img, ((-shifty, 0), (0, 0)), mode=str('constant'))[:shifty, :] # The maximum shift applied will determine the final img shape maxshiftx = max(abs(shiftx), maxshiftx) maxshifty = max(abs(shifty), maxshifty) aligned_imgs[band] = img if maxshiftx > cx or maxshifty > cy: raise VphasDataException('{0}-{1}: bands do not overlap'.format( self.offset, self.ccd)) # New stretch, scale, and stack the data into an MxNx3 array r = aligned_imgs['i'] + aligned_imgs['ha'] g = aligned_imgs['g'] + aligned_imgs['r'] + aligned_imgs['r2'] b = aligned_imgs['u'] + 2 * aligned_imgs['g'] r, g, b = 1.5 * r, 0.8 * g, 2.2 * b vmin_r, vmax_r = np.percentile(r, [1., 99.5]) vmin_g, vmax_g = np.percentile(g, [5., 99.5]) vmin_b, vmax_b = np.percentile(b, [10., 99.5]) #log.info((vmin_r, vmin_g, vmin_b)) #log.info((vmax_r, vmax_g, vmax_b)) #if vmin_b < 100: # vmin_b = 100 minrange = np.max( (1250., vmax_g - vmin_g, vmax_g - vmin_g, vmax_b - vmin_b)) if (vmax_r - vmin_r) < minrange: vmax_r = vmin_r + minrange if (vmax_g - vmin_g) < minrange: vmax_g = vmin_g + minrange if (vmax_b - vmin_b) < minrange: vmax_b = vmin_b + minrange interval_r = ManualInterval(vmin_r, vmax_r) interval_g = ManualInterval(vmin_g, vmax_g) interval_b = ManualInterval(vmin_b, vmax_b) r = interval_r(r) g = interval_g(g) b = interval_b(b) stacked = np.dstack((r[maxshifty:-maxshifty, maxshiftx:-maxshiftx], g[maxshifty:-maxshifty, maxshiftx:-maxshiftx], b[maxshifty:-maxshifty, maxshiftx:-maxshiftx])) return LuptonColorStretch()(stacked)
def data_to_pitch(data_array, pitch_range=[100, 10000], center_pitch=440, zero_point="median", stretch='linear', minmax_percent=None, minmax_value=None): """ Map data array to audible pitches in the given range, and apply stretch and scaling as required. Parameters ---------- data_array : array-like Data to map to pitch values. Individual data values should be floats. pitch_range : array Optional, default [100,10000]. Range of acceptable pitches in Hz. center_pitch : float Optional, default 440. The pitch in Hz where that the the zero point of the data will be mapped to. zero_point : str or float Optional, default "median". The data value that will be mapped to the center pitch. Options are mean, median, or a specifical data value (float). stretch : str Optional, default 'linear'. The stretch to apply to the data array. Valid values are: asinh, sinh, sqrt, log, linear minmax_percent : array Optional. Interval based on a keeping a specified fraction of data values (can be asymmetric) when scaling the data. The format is [lower percentile, upper percentile], where data values below the lower percentile and above the upper percentile are clipped. Only one of minmax_percent and minmax_value should be specified. minmax_value : array Optional. Interval based on user-specified data values when scaling the data array. The format is [min value, max value], where data values below the min value and above the max value are clipped. Only one of minmax_percent and minmax_value should be specified. Returns ------- response : array The normalized data array, with values in given pitch range. """ # Parsing the zero point if zero_point in ("med", "median"): zero_point = np.median(data_array) if zero_point in ("ave", "mean", "average"): zero_point = np.mean(data_array) # Normalizing the data_array and adding the zero point (so it can go through the same transform) data_array = np.append(np.array(data_array), zero_point) # Setting up the transform with the stretch if stretch == 'asinh': transform = AsinhStretch() elif stretch == 'sinh': transform = SinhStretch() elif stretch == 'sqrt': transform = SqrtStretch() elif stretch == 'log': transform = LogStretch() elif stretch == 'linear': transform = LinearStretch() else: raise InvalidInputError("Stretch {} is not supported!".format(stretch)) # Adding the scaling to the transform if minmax_percent is not None: transform += AsymmetricPercentileInterval(*minmax_percent) if minmax_value is not None: warnings.warn( "Both minmax_percent and minmax_value are set, minmax_value will be ignored.", InputWarning) elif minmax_value is not None: transform += ManualInterval(*minmax_value) else: # Default, scale the entire image range to [0,1] transform += MinMaxInterval() # Performing the transform and then putting it into the pich range pitch_array = transform(data_array) zero_point = pitch_array[-1] pitch_array = pitch_array[:-1] pitch_array = np.multiply((center_pitch - pitch_range[0]) / zero_point, pitch_array, out=pitch_array) + pitch_range[0] return pitch_array