Ejemplo n.º 1
0
    def plot_sources(self,
                     data,
                     centroids,
                     vmin=0,
                     vmax=1000,
                     radius=3,
                     color='red',
                     ax=None):
        """Draw apertures at each position (x_pos[i], y_pos[i])

        Parameters
        ----------
        data
        centroid
        radius
        color
        ax

        Returns
        -------

        """
        m_interval = ManualInterval(vmin=vmin, vmax=vmax)
        norm = ImageNormalize(data, stretch=LogStretch(), interval=m_interval)
        if ax is None:
            fig, ax = plt.subplots(nrows=1, ncols=1)

        ax.grid(False)
        ax.imshow(data, norm=norm, cmap='gray', origin='lower')

        for xy in centroids:
            aperture = self.mk_aperture(xy, radius, color)
            ax.add_patch(aperture)
        return ax
Ejemplo n.º 2
0
def convert_to_valid_color(
    image_color: np.ndarray,
    clip: bool = False,
    lower_clip: float = 0.0,
    upper_clip: float = 1.0,
    normalize: bool = False,
    scaling: Optional[str] = None,
    simple_norm: bool = False,
) -> np.ndarray:
    """
    Convert the channel to a valid 0-1 range for RGB images
    """

    if simple_norm:
        interval = MinMaxInterval()
        norm = ImageNormalize()
        return norm(interval(image_color))

    if clip:
        image_color = np.clip(image_color, lower_clip, upper_clip)
    if normalize:
        interval = ManualInterval(lower_clip, upper_clip)
    else:
        interval = MinMaxInterval()
    if scaling == "sqrt":
        stretch = SqrtStretch()
        image_color = stretch(interval(image_color))
    else:
        norm = ImageNormalize()
        image_color = norm(interval(image_color))

    return image_color
Ejemplo n.º 3
0
 def _plotbutton_inverted_individual_fired(self):
     try:
         self.data
     except:
         self.status_string_right = "No fits file loaded yet!"
         return
     self.data_scaled = (
         scaling_fns[self.image_scale]() +
         ManualInterval(vmin=self.datamin, vmax=self.datamax))(self.data)
     self.image_greyRGB = ski_color.gray2rgb(
         adjust_gamma(self.data_scaled, self.gamma))
     self.image_colorRGB = colorize_image(self.image_greyRGB,
                                          hexinv(self.imagecolor),
                                          colorintype='hex',
                                          gammacorr_color=self.gamma)
     #self.image_axesimage.set_data(1.-self.image_colorRGB**(1./self.gamma))
     self.image_axesimage.set_data(
         combine_multicolor([
             self.image_colorRGB,
         ],
                            gamma=self.gamma,
                            inverse=True))
     self.percent_min = np.round(
         percentileofscore(self.data.ravel(), self.datamin, kind='strict'),
         2)
     self.percent_max = np.round(
         percentileofscore(self.data.ravel(), self.datamax, kind='strict'),
         2)
     self.in_use = True
     self.image_figure.canvas.draw()
     self.status_string_right = "Plot updated"
Ejemplo n.º 4
0
    def plot_segmap(self,
                    img_data,
                    segmap,
                    centroids=None,
                    ax1=None,
                    ax2=None,
                    vmin=None,
                    vmax=None,
                    units=None,
                    fs=10):
        """ Plot segmentation map returned by SExtractor

        Parameters
        ----------
        img_data
        segmap
        centroids
        ax1
        ax2
        vmin
        vmax
        units
        fs

        Returns
        -------

        """
        if vmin is not None and vmax is not None:
            interval = ManualInterval(vmin=vmin, vmax=vmax)
        else:
            interval = ZScaleInterval()

        norm = ImageNormalize(img_data,
                              stretch=LinearStretch(),
                              interval=interval)

        segm_cmap = self.rand_cmap(np.max(segmap))
        self._segm_cmap = segm_cmap
        if ax1 is None or ax2 is None:
            fig, (ax1, ax2) = plt.subplots(nrows=2,
                                           ncols=1,
                                           sharex=True,
                                           sharey=True)
        else:
            fig = ax1.get_figure()

        im1 = ax1.imshow(img_data, norm=norm, cmap='gray', origin='lower')
        divider = make_axes_locatable(ax1)
        cax = divider.append_axes('right', size='5%', pad=0.05)
        cbar = fig.colorbar(im1, cax=cax, orientation='vertical')
        cbar.set_label(units, fontsize=fs)
        im2 = ax2.imshow(segmap, cmap=self.segm_cmap, origin='lower')

        if centroids is not None:
            for xy in centroids:
                aperture = self.mk_aperture(xy, r=3, c='red')
                ax1.add_patch(aperture)

        return fig, ax1, ax2
Ejemplo n.º 5
0
 def manual_int(self):
     self.interval = ManualInterval(self.v_min, self.v_max)
     self.rbtn5.setChecked(True)
     self.rbtn6.setChecked(False)
     self.rbtn7.setChecked(False)
     self.rbtn8.setChecked(False)
     self.rbtn9.setChecked(False)
     main.refresh_norm()
     print('v_min, v_max = ' + str(self.v_min) + ', ' + str(self.v_max))
Ejemplo n.º 6
0
 def _percent_max_changed(self):
     self.datamax = np.nanpercentile(self.data, self.percent_max)
     self.data_scaled = (
         scaling_fns[self.image_scale]() +
         ManualInterval(vmin=self.datamin, vmax=self.datamax))(self.data)
     self.image_greyRGB = ski_color.gray2rgb(
         adjust_gamma(self.data_scaled, self.gamma))
     self.image_colorRGB = colorize_image(self.image_greyRGB,
                                          self.imagecolor,
                                          colorintype='hex',
                                          gammacorr_color=self.gamma)
     self.image_axesimage.set_data(self.image_colorRGB**(1. / self.gamma))
     self.image_figure.canvas.draw()
     self.status_string_right = "Updated scale using percentiles"
Ejemplo n.º 7
0
    def _scale_dropdown_changed(self):
        self.image_scale = self.scale_dropdown
        #self.norm=ImageNormalize(self.sregion,stretch=scaling_fns[self.image_scale]() )
        self.data_scaled = (
            scaling_fns[self.image_scale]() +
            ManualInterval(vmin=self.datamin, vmax=self.datamax))(self.data)
        #*** Instead, should I just integrate my imscale class here instead of astropy? ...
        self.image_greyRGB = ski_color.gray2rgb(
            adjust_gamma(self.data_scaled, self.gamma))
        self.image_colorRGB = colorize_image(self.image_greyRGB,
                                             self.imagecolor,
                                             colorintype='hex',
                                             gammacorr_color=self.gamma)

        self.image_axesimage.set_data(self.image_colorRGB**(1. / self.gamma))

        self.in_use = True

        self.image_figure.canvas.draw()
        self.status_string_right = 'Image scale function changed to ' + self.image_scale
Ejemplo n.º 8
0
    def _plotbutton_individual_fired(self):
        try:
            self.data
        except:
            self.status_string_right = "No fits file loaded yet!"
            return
        #self.image=self.data
        ###Using this command is preferable, as long as the projection doesn't need to be updated...
        #  The home zoom button will work, but no WCS labels because projection wasn't set during init.
        #Scale the data to [0,1] range
        self.data_scaled = (
            scaling_fns[self.image_scale]() +
            ManualInterval(vmin=self.datamin, vmax=self.datamax))(self.data)
        #Convert scale[0,1] image to greyscale RGB image
        self.image_greyRGB = ski_color.gray2rgb(
            adjust_gamma(self.data_scaled, self.gamma))
        self.image_colorRGB = colorize_image(self.image_greyRGB,
                                             self.imagecolor,
                                             colorintype='hex',
                                             gammacorr_color=self.gamma)
        self.image_axesimage.set_data(self.image_colorRGB**(1. / self.gamma))
        ###Using this set instead properly updates the axes labels to WCS, but the home zoom button won't work
        #self.image_figure.clf()
        #self.image_axes = self.image_figure.add_subplot(111,aspect=1)#,projection=self.wcs)
        #self.image_axesimage = self.image_axes.imshow(self.image, cmap=self.image_cmap,origin='lower',interpolation='nearest', norm=self.norm)

        self.percent_min = np.round(
            percentileofscore(self.data.ravel(), self.datamin, kind='strict'),
            2)
        self.percent_max = np.round(
            percentileofscore(self.data.ravel(), self.datamax, kind='strict'),
            2)

        self.in_use = True

        #self.update_radecpars()
        self.image_figure.canvas.draw()
        self.status_string_right = "Plot updated"
print("Input has {0} out of {1} matches to the observed leaves within 1 arcsec"
      .format((orig_to_obs['sep'] < 1*u.arcsec).sum(), len(pruned_orig_ppcat)))

pruned_ppcat.add_column(Column(data=orig_to_obs['inds'],
                               name='match_inds'))
pruned_ppcat.add_column(Column(data=orig_to_obs['sep'],
                               name='match_separation'))
temporary = pruned_orig_ppcat[pruned_ppcat['match_inds']]
merged_orig_onto_obs = table.hstack([pruned_ppcat, temporary])

# ds9 -multiframe ../analysis/*perseus*.fits ../perseus_synth/perseus_250_2_model_tclean_clean_noise.fits -lock frames image -frame 2 -scale minmax -cmap sls -frame 3 -frame delete -frame 7 -frame delete -frame 6 -cmap sls -frame 8 -cmap sls -frame 4 -cmap sls -frame 5 -cmap value 8.5 0.05 -frame 9 -cmap value 12 0.03 -frame 1 -cmap value 8.5 0.05 -lock crosshairs image  &
import pylab as pl
from astropy.visualization import (MinMaxInterval, ManualInterval, AsinhStretch,
                                   ImageNormalize)

norm = ImageNormalize(data_original, interval=ManualInterval(-0.002,0.03),
                      stretch=AsinhStretch())

fig = pl.figure(1)
fig.clf()
ax = fig.add_axes([0.15, 0.1, 0.8, 0.8], projection=mywcs)
ax.imshow(data_original, cmap='gray_r', origin='lower', interpolation='none', norm=norm)
ax.plot(orig_ppcat['x_cen'], orig_ppcat['y_cen'], 'o', markeredgecolor='r', markerfacecolor='none', transform=ax.get_transform('world'))

ra = ax.coords['ra']
ra.set_major_formatter('hh:mm:ss.s')
dec = ax.coords['dec']
ra.set_axislabel("RA (J2000)", fontsize=pl.rcParams['axes.labelsize'])
dec.set_axislabel("Dec (J2000)", fontsize=pl.rcParams['axes.labelsize'], minpad=0.0)
ra.set_ticks(exclude_overlapping=True)
dec.set_ticks(exclude_overlapping=True)
Ejemplo n.º 10
0
    def kde2D_plot(self,
                   parameter1,
                   parameter2,
                   normtype='log',
                   interval=None,
                   xlim=None,
                   ylim=None,
                   gridsize=100):
        """Generate a 2D KDE for the given parameters.

        Parameters
        ----------
        parameter1 : `numpy.array`
            X-axis variable

        parameter2 : `numpy.array`
            Y-axis variable

        normtype : {'log', 'linear', 'sqrt'}
            Normalization type to apply to the data

        interval : tuple
            Limits of the interval to use when computing the image scaling

        xlim : tuple
            X-limits to use for the plot and the KDE grid

        ylim : tuple
            Y-limits to use for the plot and the KDE grid

        gridsize : int
            Step-size for the grid

        Returns
        -------
        fig : :py:class:`matplotlib.figure.Figure`

        ax : :py:class:`matplotlib.axes.Axes`

        surface : numpy.array
            The KDE surface plot
        """

        data = np.vstack([parameter1, parameter2])

        if xlim is None:
            xlim = (np.min(parameter1), np.max(parameter1))

        if ylim is None:
            ylim = (np.min(parameter2), np.max(parameter2))

        # Generate a grid to compute the KDE over
        xgrid = np.linspace(xlim[0], xlim[1], gridsize)
        ygrid = np.linspace(ylim[0], ylim[1], gridsize)

        kde = gaussian_kde(data)
        Xgrid, Ygrid = np.meshgrid(xgrid, ygrid)
        surface = kde.evaluate(np.vstack([Xgrid.ravel(), Ygrid.ravel()]))

        if isinstance(interval, tuple):
            Interval = ManualInterval(vmin=interval[0], vmax=interval[1])
        else:
            Interval = ZScaleInterval()

        norm = ImageNormalize(surface,
                              stretch=self.image_norms[normtype],
                              interval=Interval)

        fig, ax = self.mk_fig(nrows=1, ncols=1)
        ax.imshow(surface.reshape(Xgrid.shape),
                  norm=norm,
                  cmap='gray',
                  origin='lower',
                  aspect='auto',
                  extent=[xgrid.min(),
                          xgrid.max(),
                          ygrid.min(),
                          ygrid.max()])

        return fig, ax, surface
    def _plot_fits(self):
        """Plot all the fits.
        """

        # Make axis box stand out as viridis can be dark.
        matplotlib.rc('axes', edgecolor='r')

        # Hand-tuning suggests a linear scale between the
        # min max of these stars is the best. Global limits or
        # percentile limits tend to saturate out the stars.
        ##pct_interval = AsymmetricPercentileInterval(0.10, 99.9)
        valmin = self._init_bglvl
        valmax = np.amax(self._fit_table['peak_adu'])
        minmax_interval = ManualInterval(vmin=valmin, vmax=valmax)

        norm_func = ImageNormalize(self._img_data,
                                   interval=minmax_interval,
                                   stretch=AsinhStretch())
        ##norm_func    = ImageNormalize(self._img_data,
        ##    interval=pct_interval,
        ##    stretch=SqrtStretch())

        # May be overly agressive for subplots
        ##norm_func   = ImageNormalize(self._img_data,
        ##    interval=pct_interval,
        ##    stretch=AsinhStretch())

        # Location of text label added internal to subplots, in
        # normalized 0:1 coordinate. This is where the bottom left
        # the text box will appear.
        text_x = 0.2
        text_y = 0.8

        region_list = ['TL', 'TR', 'CN', 'BR', 'BL']
        region_row_dict = {'TL': 0, 'TR': 1, 'CN': 2, 'BR': 3, 'BL': 4}

        # Create a dictionary that has keys of the row index within
        # _fit_table (also the first index of the _pixel_array)
        # and the column index within the 2-D plotting array.
        #
        # This is necessary because there may be less that _num_per_reg
        # stars per region.
        #
        # This is inelegant but should work.
        num_stars = len(self._fit_table)
        star_col_dict = {}  # To fill
        col_idx_dict = {
            'CN': 0,  # working memory
            'TL': 0,
            'TR': 0,
            'BL': 0,
            'BR': 0
        }
        for idx in range(num_stars):
            this_reg = self._fit_table['region'][idx]
            this_col_idx = col_idx_dict[this_reg]
            star_col_dict[idx] = this_col_idx
            new_col_idx = this_col_idx + 1
            col_idx_dict[this_reg] = new_col_idx

        # Create figure for plot
        fig_rows = len(region_list)
        fig_cols = self._num_per_reg

        # List of handles to the images
        plt_imgs = []

        fig, ax_arr = plt.subplots(nrows=fig_rows,
                                   ncols=fig_cols,
                                   sharex=True,
                                   sharey=True)

        (median_fwhm, madstd_fwhm, npts) = self.median_fwhm('both')

        title = 'Star PSF measurements using 2-D Gaussian fits'
        if self._plot_title is not None:
            title = self._plot_title
        title += f'\nMedian FWHM={median_fwhm:.2f} +/- {madstd_fwhm:.2f} (MAD stddev) pixels'
        fig.suptitle(title, fontsize=7)

        for idx in range(num_stars):
            this_reg = self._fit_table['region'][idx]
            row_idx = region_row_dict[this_reg]
            col_idx = star_col_dict[idx]

            # Plot the cutout image.
            cut_out = self._pixel_array[idx]
            plt_imgs.append(ax_arr[row_idx, col_idx].imshow(cut_out,
                                                            origin='lower',
                                                            norm=norm_func))

            # Titles, fit info etc
            title_str = self._get_subplot_title(idx)
            fitinfo_str = self._get_subplot_fitinfo(idx)
            ax_arr[row_idx, col_idx].set_title(title_str, fontsize=4, pad=3)
            ax_arr[row_idx, col_idx].text(text_x,
                                          text_y,
                                          fitinfo_str,
                                          fontsize=3,
                                          color='w')
            #ax_arr[row_idx, col_idx].set_xlabel('X-axis (pixels)', fontsize=6)
            ax_arr[row_idx, col_idx].set_ylabel(this_reg, fontsize=6)

            # Get artists related to best-fit parameters
            artist_list = self._get_fit_artists(idx)
            if len(artist_list) > 0:
                for art in artist_list:
                    ax_arr[row_idx, col_idx].add_artist(art)

        # Only show tick values on outer edge of grid.
        for ax in ax_arr.flat:
            ax.tick_params(axis='both',
                           labelsize=4,
                           direction='in',
                           color='r',
                           length=3)
            ax.label_outer()

        plt.savefig(self._fwhm_plot,
                    dpi=200,
                    quality=95,
                    optimize=True,
                    bbox_inches='tight')
        self._logger.info(
            f'Plotted star FWHM fit cut-outs to {self._fwhm_plot}')
        return
Ejemplo n.º 12
0
beam_pix = hdr['BMAJ']/hdr['CDELT2']

# crop the plotted PSF region in offset from center
if args.crop_offset:
	crop_arcsec = args.crop_offset
	crop_pix = crop_arcsec/3600/hdr['CDELT2']
else:
	crop_arcsec= np.max([x_off_arcsec,y_off_arcsec])
	crop_pix = np.max([x_off,y_off])
crop_suff = '_'+str(np.round(crop_arcsec,1))+'arcsec'


# plot the PSF image
plt.figure(1)
plt.clf()
norm=ImageNormalize(psf,stretch=LogStretch(),interval=ManualInterval(vmin=0,vmax=1))
plt.imshow(psf,origin='lower',norm=norm,cmap='gray_r')
plt.colorbar()
plt.xlim(left=xcen-crop_pix,right=xcen+crop_pix)
plt.ylim(bottom=ycen-crop_pix,top=ycen+crop_pix)
plt.savefig(save_path+crop_suff+'_image.pdf',bbox_inches='tight',metadata={'Creator':this_script})
plt.plot([xcen-crop_pix,xcen+crop_pix],[ycen,ycen],linestyle='-',lw=1.0)
plt.plot([xcen,xcen],[ycen-crop_pix,ycen+crop_pix],linestyle='--',lw=1.0)
plt.plot([xcen-crop_pix,xcen+crop_pix],[ycen-crop_pix,ycen+crop_pix],linestyle='-.',lw=1.0)
plt.plot([xcen-crop_pix,xcen+crop_pix],[ycen+crop_pix,ycen-crop_pix],linestyle=':',lw=1.0)
plt.savefig(save_path+crop_suff+'_image_slices.pdf',bbox_inches='tight',metadata={'Creator':this_script})
plt.close()

#make a second x-axis on the top in pix
def arcsec2pix(x):
	return x/3600/hdr['CDELT2']
Ejemplo n.º 13
0
    def __call__(self, bounds=None):

        img = None
        visible_layers = 0

        for uuid in sorted(self.layers,
                           key=lambda x: self.layers[x]['zorder']):

            layer = self.layers[uuid]

            if not layer['visible']:
                continue

            interval = ManualInterval(*layer['clim'])
            contrast_bias = ContrastBiasStretch(layer['contrast'],
                                                layer['bias'])

            if callable(layer['array']):
                array = layer['array'](bounds=bounds)
            else:
                array = layer['array']

            if array is None:
                continue

            if np.isscalar(array):
                scalar = True
                array = np.atleast_2d(array)
            else:
                scalar = False

            data = STRETCHES[layer['stretch']]()(contrast_bias(
                interval(array)))

            if isinstance(layer['color'], Colormap):

                if img is None:
                    img = np.ones(data.shape + (4, ))

                # Compute colormapped image
                plane = layer['color'](data)

                alpha_plane = layer['alpha'] * plane[:, :, 3]

                # Use traditional alpha compositing
                plane[:, :, 0] = plane[:, :, 0] * alpha_plane
                plane[:, :, 1] = plane[:, :, 1] * alpha_plane
                plane[:, :, 2] = plane[:, :, 2] * alpha_plane

                img[:, :, 0] *= (1 - alpha_plane)
                img[:, :, 1] *= (1 - alpha_plane)
                img[:, :, 2] *= (1 - alpha_plane)
                img[:, :, 3] = 1

            else:

                if img is None:
                    img = np.zeros(data.shape + (4, ))

                # Get color and pre-multiply by alpha values
                color = COLOR_CONVERTER.to_rgba_array(layer['color'])[0]
                color *= layer['alpha']

                # We should treat NaN values as zero (post-stretch), which means
                # that those pixels don't contribute towards the final image.
                reset = np.isnan(data)
                if np.any(reset):
                    data[reset] = 0.

                plane = data[:, :, np.newaxis] * color
                plane[:, :, 3] = 1

                visible_layers += 1

            if scalar:
                plane = plane[0, 0]

            img += plane

        if img is None:
            return None
        else:
            img = np.clip(img, 0, 1)

        return img
Ejemplo n.º 14
0
            # if not os.path.isfile('{}/images/image_filtered_low_clean.fits'.format(odf_dir)):
            #     fits_image = '{}/images/image_filtered_low.fits'.format(odf_dir)
            # else:
            #     fits_image = '{}/images/image_filtered_low_clean.fits'.format(odf_dir)

            hdu = fits.open(fits_image)
            wcs = WCS(hdu[0].header)
            g2_kernel = Gaussian2DKernel(2)
            smoothed_data_g2 = convolve(hdu[0].data, g2_kernel, mask=np.logical_not(detmask.data)) * detmask.data

            fig = plt.figure(figsize=(10, 10), dpi=100)
            pp = 99.9  # colour cut percentage

            ax = fig.add_subplot(111, projection=wcs)
            #ax.set_title("Gaussian smoothed image")
            norm_xmm = ImageNormalize(smoothed_data_g2, interval=ManualInterval(vmin=0.01, vmax=100.0),
                                      stretch=LogStretch())
            # norm_xmm = ImageNormalize(smoothed_data_g2,interval=PercentileInterval(pp), stretch=AsinhStretch())
            ax.imshow(smoothed_data_g2, cmap=plt.cm.hot, norm=norm_xmm, origin='lower', interpolation='nearest')
            ax.xlabel = 'RA'
            ax.ylabel = 'Dec'
            ax.set_xlabel('RA')
            ax.set_ylabel('DEC')
            #
            # only show the last aperture
            #
            circle_sky = CircleSkyRegion(center=center, radius=r_end)
            pix_reg = circle_sky.to_pixel(wcs)
            pix_reg.plot(ax=ax, edgecolor='yellow')
            plt.savefig('/home/aaranda/tfm/results_v2/{}/{}/smoothed_g2_image_low.png'.format(target, obsid))
            plt.close(fig)
Ejemplo n.º 15
0
            wcs_det = WCS(detmask.header)
            fits_image = '{}/images/image_filtered_high.fits'.format(odf_dir)
            hdu = fits.open(fits_image)
            wcs = WCS(hdu[0].header)
            g2_kernel = Gaussian2DKernel(2)
            smoothed_data_g2 = convolve(
                hdu[0].data, g2_kernel, mask=np.logical_not(
                    detmask.data)) * detmask.data

            fig = plt.figure(figsize=(10, 10), dpi=100)
            pp = 99.9  # colour cut percentage

            ax = fig.add_subplot(111, projection=wcs)
            #ax.set_title("Gaussian smoothed image")
            norm_xmm = ImageNormalize(smoothed_data_g2,
                                      interval=ManualInterval(vmin=0.01,
                                                              vmax=100.0),
                                      stretch=LogStretch())
            # norm_xmm = ImageNormalize(smoothed_data_g2,interval=PercentileInterval(pp), stretch=AsinhStretch())
            ax.imshow(smoothed_data_g2,
                      cmap=plt.cm.hot,
                      norm=norm_xmm,
                      origin='lower',
                      interpolation='nearest')
            ax.xlabel = 'RA'
            ax.ylabel = 'Dec'
            ax.set_xlabel('RA')
            ax.set_ylabel('DEC')
            #
            # only show the last aperture
            #
            circle_sky = CircleSkyRegion(center=center, radius=r_end)
Ejemplo n.º 16
0
    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)
Ejemplo n.º 17
0
    def __getitem__(self, view):

        img = None
        visible_layers = 0

        for uuid in sorted(self.layers, key=lambda x: self.layers[x]['zorder']):

            layer = self.layers[uuid]

            if not layer['visible']:
                continue

            interval = ManualInterval(*layer['clim'])
            contrast_bias = ContrastBiasStretch(layer['contrast'], layer['bias'])

            if callable(layer['array']):
                array = layer['array'](view=view)
            else:
                array = layer['array']

            if array is None:
                continue

            if not callable(layer['array']):
                array = array[view]

            if np.isscalar(array):
                scalar = True
                array = np.atleast_2d(array)
            else:
                scalar = False

            data = STRETCHES[layer['stretch']]()(contrast_bias(interval(array)))

            if isinstance(layer['color'], Colormap):

                if img is None:
                    img = np.ones(data.shape + (4,))

                # Compute colormapped image
                plane = layer['color'](data)

                alpha_plane = layer['alpha'] * plane[:, :, 3]

                # Use traditional alpha compositing
                plane[:, :, 0] = plane[:, :, 0] * alpha_plane
                plane[:, :, 1] = plane[:, :, 1] * alpha_plane
                plane[:, :, 2] = plane[:, :, 2] * alpha_plane

                img[:, :, 0] *= (1 - alpha_plane)
                img[:, :, 1] *= (1 - alpha_plane)
                img[:, :, 2] *= (1 - alpha_plane)
                img[:, :, 3] = 1

            else:

                if img is None:
                    img = np.zeros(data.shape + (4,))

                # Get color and pre-multiply by alpha values
                color = COLOR_CONVERTER.to_rgba_array(layer['color'])[0]
                color *= layer['alpha']

                plane = data[:, :, np.newaxis] * color
                plane[:, :, 3] = 1

                visible_layers += 1

            if scalar:
                plane = plane[0, 0]

            img += plane

        if img is None:
            if self.shape is None:
                return None
            else:
                img = np.zeros(self.shape + (4,))

        img = np.clip(img, 0, 1)

        return img
Ejemplo n.º 18
0
def data_to_pitch(data_array, pitch_range=[100, 10000], center_pitch=440, zero_point="median",
                  stretch='linear', minmax_percent=None, minmax_value=None, invert=False):
    """
    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 specified 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.
    invert : bool
        Optional, default False.  If True the pitch array is inverted (low pitches become high
        and vice versa).

    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)

    # The center pitch cannot be >= max() pitch range, or <= min() of pitch range.
    # If it is, fall back to using the mean of the pitch range provided.
    if center_pitch <= pitch_range[0] or center_pitch >= pitch_range[1]:
        warnings.warn("Given center pitch is outside the pitch range, defaulting to the mean.",
                      InputWarning)
        center_pitch = np.mean(pitch_range)

    if (data_array == zero_point).all():  # All values are the same, no more calculation needed
        return np.full(len(data_array), center_pitch)

    # 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)

    if invert:
        pitch_array = 1 - pitch_array

    zero_point = pitch_array[-1]
    pitch_array = pitch_array[:-1]

    # In rare cases, the zero-point at this stage might be 0.0.
    # One example is an input array of two values where the median() is the same as the
    # lowest of the two values. In this case, the zero-point is 0.0 and will lead to error
    # (divide by zero). Change to small value to avoid dividing by zero (in reality the choice
    # of zero-point calculation by the user was probably poor, but not in purview to mandate or
    # change user's choice here.  May want to consider providing info back to the user about the
    # distribution of pitches actually used based on their sonification options in some way.
    if zero_point == 0.0:
        zero_point = 1E-6

    if ((1/zero_point)*(center_pitch - pitch_range[0]) + pitch_range[0]) <= pitch_range[1]:
        pitch_array = (pitch_array/zero_point)*(center_pitch - pitch_range[0]) + pitch_range[0]
    else:
        pitch_array = (((pitch_array-zero_point)/(1-zero_point))*(pitch_range[1] - center_pitch) +
                       center_pitch)

    return pitch_array
Ejemplo n.º 19
0
hdu = fits.open(filename)[0]
wcs = WCS(hdu.header)

TICK_FONTSIZE = 8
AXIS_FONTSIZE = 10
AXIS_WEIGHT = 'bold'

import matplotlib.pyplot as plt

plt.rc('font', family='serif')
plt.rc('text', usetex=True)

ax = plt.axes([0.1, 0.1, 0.8, 0.8], projection=wcs, adjustable='datalim')

norm = ImageNormalize(hdu.data,
                      interval=ManualInterval(22, 140),
                      stretch=SqrtStretch())

image = ax.imshow(hdu.data,
                  origin='lower',
                  cmap=plt.cm.plasma,
                  norm=norm,
                  aspect='equal')

ax.set_xlim(1700, 8200)
ax.set_ylim(3300, 8500)

ax.coords['ra'].set_ticks(color='black')
ax.coords['dec'].set_ticks(color='black')

ax.coords['ra'].set_ticklabel(size=TICK_FONTSIZE)
Ejemplo n.º 20
0
def data_to_pitch(data_array,
                  pitch_range=[100, 10000],
                  center_pitch=440,
                  zero_point="median",
                  stretch='linear',
                  minmax_percent=None,
                  minmax_value=None,
                  invert=False):
    """
    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 specified 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.
    invert : bool
        Optional, default False.  If True the pitch array is inverted (low pitches become high 
        and vice versa).

    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)

    if (data_array == zero_point
        ).all():  # All values are the same, no more calculation needed
        return np.full(len(data_array), zero_point)

    # 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)

    if invert:
        pitch_array = 1 - pitch_array

    zero_point = pitch_array[-1]
    pitch_array = pitch_array[:-1]

    if ((1 / zero_point) *
        (center_pitch - pitch_range[0]) + pitch_range[0]) <= pitch_range[1]:
        pitch_array = (pitch_array / zero_point) * (
            center_pitch - pitch_range[0]) + pitch_range[0]
    else:
        pitch_array = (
            (pitch_array - zero_point) /
            (1 - zero_point)) * (pitch_range[1] - center_pitch) + center_pitch

    return pitch_array
Ejemplo n.º 21
0
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
Ejemplo n.º 22
0
def greyRGBize_image(datin,
                     rescalefn='linear',
                     scaletype='abs',
                     min_max=[None, None],
                     gamma=2.2,
                     checkscale=False):
    """
    ### Takes an image and returns 3-frame [R,G,B] (vals from 0...1)

    Parameters
    ----------
    datin : array 
        Input 2D image data array
    rescalefn : func 
        Function to use for rescaling intensity.  imscale.linear/sqrt/squared/log/power/sinh/asinh
    scaletype : str 
        'abs' for absolute values, 'perc' for percentiles
    min_max : list
        [min,max] vals to use in rescale.  if scaletype='perc', list the percentiles to use, e.g. [1.,95.]
    gamma : float 
        Value for gamma correction.  For combining colorized frames, use default gamma=2.2.  For inverse, use gamma=(1./2.2)
    checkscale : bool  
        True to bring up plot to check the new image scale.

    Returns
    -------
    array
        Greyscale RGB image, shape=[ypixels,xpixels,3]
    """
    if 'per' in scaletype.lower():
        if min_max == [None, None]:
            min_max = [0., 100.]
        minval, maxval = np.percentile(
            np.ma.masked_invalid(datin).compressed(), min_max)
    else:
        minval = [np.nanmin(datin) if min_max[0] is None else min_max[0]][0]
        maxval = [np.nanmax(datin) if min_max[1] is None else min_max[1]][0]
    # Used specified rescaling function
    datscaled = (scaling_fns[rescalefn]() +
                 ManualInterval(vmin=minval, vmax=maxval))(datin)
    # datscaled=rescalefn(datin,vmin=minval,vmax=maxval)
    if gamma != 1:
        datscaled = adjust_gamma(datscaled, gamma)
    # Need to scale image between -1 and 1 if data type is float...
    datlinear = LinearStretch()(datscaled)
    # datlinear=imscale.linear(np.nan_to_num(datscaled))
    # Convert to RGB
    dat_greyRGB = ski_color.gray2rgb(datlinear)

    if checkscale is not False:
        plt.clf()
        plt.close('all')
        fig0 = plt.figure(0)
        ax1 = fig0.add_subplot(121)
        plt.imshow(datin,
                   interpolation='nearest',
                   origin='lower',
                   cmap='gist_gray')
        plt.title('Input Image')
        ax2 = fig0.add_subplot(122)
        plt.imshow(dat_greyRGB**(1. / gamma),
                   interpolation='nearest',
                   origin='lower')
        plt.title('Scaled Image')
        plt.show()  # plt.clf(); plt.close('all')

    return dat_greyRGB
Ejemplo n.º 23
0
# yaxis.set_minor_frequency(ymi_num)
""" scaling and imaging """
interp = 'none'
# interpolation of the datacube, e.g., 'none'/'nearest'/'bilinear'/'bicubic', defaut is 'none'

scaling = 'linear'
# scaling of the datacube, e.g., 'linear'/'log'/'power'/'sqrt'/'squared', defaut is 'linear'
index = 1e3
# index of log and power scaling, default is 1e3
if scaling == 'linear': stretch = LinearStretch()
elif scaling == 'log': stretch = LogStretch(index)
elif scaling == 'power': stretch = PowerStretch(index)
elif scaling == 'sqrt': stretch = SqrtStretch()
elif scaling == 'squared': stretch = SquaredStretch()
if scale is None:
    interval = ManualInterval(vmin=np.nanmin(dat), vmax=np.nanmax(dat))
else:
    interval = ManualInterval(vmin=scale[0], vmax=scale[1])
# norm=ImageNormalize(dat, interval=interval, stretch=stretch)

if scale is None:
    norm = colors.Normalize(vmin=np.nanmin(dat), vmax=np.nanmax(dat))
else:
    norm = colors.Normalize(vmin=scale[0], vmax=scale[1])

# ax.set_xlim(-0.5, dat.shape[1]-0.5)
# ax.set_ylim(-0.5, dat.shape[0]-0.5)
if colormap is not None: plt.set_cmap(colormap)
cmap = mpl.cm.get_cmap()
cmap.set_bad(color='white')
im = ax.imshow(dat, norm=norm, interpolation=interp, cmap=cmap, origin='lower')
Ejemplo n.º 24
0
    # yaxis.set_minor_frequency(ymi_num)

    """ scaling and imaging """
    interp='none'
    # interpolation of the datacube, e.g., 'none'/'nearest'/'bilinear'/'bicubic', defaut is 'none'

    scaling='linear'
    # scaling of the datacube, e.g., 'linear'/'log'/'power'/'sqrt'/'squared', defaut is 'linear'
    index=1e3
    # index of log and power scaling, default is 1e3
    if scaling=='linear': stretch=LinearStretch()
    elif scaling=='log': stretch=LogStretch(index)
    elif scaling=='power': stretch=PowerStretch(index)
    elif scaling=='sqrt': stretch=SqrtStretch()
    elif scaling=='squared': stretch=SquaredStretch()
    if scale is None: interval=ManualInterval(vmin=np.nanmin(dat), vmax=np.nanmax(dat))
    else: interval=ManualInterval(vmin=scale[0], vmax=scale[1])
    # norm=ImageNormalize(dat, interval=interval, stretch=stretch)
    
    if scale is None: norm=colors.Normalize(vmin=np.nanmin(dat), vmax=np.nanmax(dat))
    else: norm=colors.Normalize(vmin=scale[0], vmax=scale[1])

    # ax.set_xlim(-0.5, dat.shape[1]-0.5)
    # ax.set_ylim(-0.5, dat.shape[0]-0.5)
    if colormap is not None: plt.set_cmap(colormap)
    cmap=mpl.cm.get_cmap()
    cmap.set_bad(color='white')
    im=ax.imshow(dat, norm=norm, interpolation=interp, cmap=cmap, origin='lower')

    """
    The following arguments need to be set in the command.
def plot_inset(data,
               ax,
               centroids=None,
               cmap=None,
               vmin=None,
               vmax=None,
               w=100,
               h=100):
    """Plot an inset in the image plot

    Parameters
    ----------
    data
    norm
    ax
    w
    h

    Returns
    -------

    """
    ax_inset = inset_axes(ax, width="30%", height="30%")
    ax_inset.grid(False)
    mark_inset(ax, ax_inset, loc1=2, loc2=4, fc="none", ec='r', lw=1.25)

    for label in ['bottom', 'top', 'left', 'right']:
        ax_inset.spines[label].set_color('r')

    ax_inset.tick_params(axis='both',
                         which='major',
                         bottom=False,
                         top=False,
                         right=False,
                         left=False,
                         labelleft=False,
                         labelbottom=False)

    ymax, xmax = data.shape

    xlim = (xmax // 5 - w, xmax // 5 + w)
    ylim = (ymax // 3 - h, ymax // 3 + h)
    if cmap is not None:
        ax_inset.imshow(
            data,
            cmap=cmap,
            origin='lower',
        )
    else:
        if vmin is not None and vmax is not None:
            interval = ManualInterval(vmin=vmin, vmax=vmax)
        else:
            interval = ZScaleInterval()
        norm = ImageNormalize(data, stretch=LinearStretch(), interval=interval)
        ax_inset.imshow(data, norm=norm, origin='lower', cmap='gray')

    if centroids is not None:
        for xy in centroids:
            aperture = Circle(xy=xy,
                              radius=3,
                              color='red',
                              fill=False,
                              lw=0.75)
            ax_inset.add_patch(aperture)
    ax_inset.set_xlim(xlim)
    ax_inset.set_ylim(ylim)
    return ax_inset