Пример #1
0
def source_morphology(in_image, ext_name, **kwargs):
    fo = fits.open(in_image, "append")
    hdu = fo[ext_name]

    segm_obj = SegmentationImage(fo["DEBLEND"].data)
    errmap = fo["WEIGHT_MAP"].data
    seg_props = fo["DEBLEND_PROPS"].data
    im = hdu.data

    bkg_estimator = photutils.MedianBackground()
    bkg = photutils.Background2D(hdu.data, (50, 50),
                                 bkg_estimator=bkg_estimator)
    im -= bkg.background

    npix = im.shape[0]
    center_slice = segm_obj.data[int(npix / 2) - 2:int(npix / 2) + 2,
                                 int(npix / 2) - 2:int(npix / 2) + 2]

    central_index = np.where(seg_props["id"] == center_slice[0, 0])[0][0]

    fo.flush()
    fo.close()
    source_morph = statmorph.SourceMorphology(im,
                                              segm_obj,
                                              central_index,
                                              weightmap=errmap,
                                              **kwargs)
    return source_morph
Пример #2
0
    def threshold(self, nsig=1.5, box_size=(50, 50), filter_size=(3, 3)):
        """
        Generate threshold image

        self.thresh_img is set in place

        Args:
            nsig (float, optional):
                Primary threshold parameter
            box_size (tuple):
                Primary Background2D parameter
            filter_size (tuple):
                Primary Background2D parameter
        Returns:

        """

        if self.hdu is None:
            self.load_image()

        # Background
        bkg_estimator = photutils.MedianBackground()
        self.bkg = photutils.Background2D(self.hdu.data,
                                          box_size,
                                          filter_size=filter_size,
                                          bkg_estimator=bkg_estimator,
                                          exclude_percentile=self.exc_per)

        # Threshold
        self.thresh_img = self.bkg.background + (nsig *
                                                 self.bkg.background_rms)
Пример #3
0
    def subtract_background(self,
                            subtract_min_value=True,
                            plot_background=False,
                            ax=None):
        """
        A function to subtract the background for the FRD tests

        INPUT:
        subtract_min_value - subtracts the .min value (no negative numbers)
        plot_background    - if True, plots the estimated background with the meshes it used.
        """
        self.aper = photutils.CircularAperture(positions=(self.x, self.y),
                                               r=self.r)

        # get the mask from the aperture
        # hack
        mask = self.aper.to_mask()[0].to_image(self.data.shape)

        # use sigma clipping
        sigma_clip = SigmaClip(sigma=3., iters=10)

        bkg_estimator = photutils.MedianBackground()
        self.bkg = photutils.Background2D(self.data,
                                          self.box_size,
                                          filter_size=(3, 3),
                                          sigma_clip=sigma_clip,
                                          bkg_estimator=bkg_estimator,
                                          mask=mask,
                                          edge_method="crop")

        self.data_background = self.data - self.bkg.background

        if subtract_min_value:
            self.subtracted_value = self.data_background.min()
            print("Subtracted min value:", self.subtracted_value)
            self.data_background -= self.subtracted_value

        if plot_background:
            if ax == None:
                self.fig, self.ax = plt.subplots()
            else:
                self.ax = ax
            im = self.ax.imshow(self.bkg.background,
                                origin='lower',
                                cmap='Greys_r')
            self.ax.set_xlim(0, self.bkg.background.shape[1])
            self.ax.set_ylim(0, self.bkg.background.shape[0])
            self.ax.set_title("Estimated Background", y=1.02)
            self.ax.set_xlabel("X pixels")
            self.ax.set_ylabel("Y pixels")
            if ax == None:
                # Only do this if ax is not supplied
                # Don't know how to deal with this without passing the figure explicitly
                self.fig.colorbar(im)
            self.bkg.plot_meshes(outlines=True, color='#1f77b4', ax=self.ax)

        return self.data_background
Пример #4
0
def sub_background(image: CCDData, filter_size: int = 27, box_size: int = 150):
    """
    Perform background subtraction using photutils' median background estimator over a 2D mesh.
    """
    binning = image.header['BINNING']
    filter_size = int(filter_size / binning)
    box_size = int(box_size / binning)
    bkg_estimator = photutils.MedianBackground()
    bkg = photutils.Background2D(image, (box_size, box_size),
                                 filter_size=(filter_size, filter_size),
                                 bkg_estimator=bkg_estimator)
    sub = image.data - bkg.background
    return sub
Пример #5
0
def detect_sources(in_image, ext_name, filt_wheel, **kwargs):
    fo = fits.open(in_image, "append")
    hdu = fo[ext_name]

    # build kernel for pre-filtering.  How big?
    # don't assume redshift knowledge here
    typical_kpc_per_arcsec = 8.0

    kernel_kpc_fwhm = 5.0
    kernel_arcsec_fwhm = kernel_kpc_fwhm / typical_kpc_per_arcsec
    kernel_pixel_fwhm = kernel_arcsec_fwhm / hdu.header["PIXSIZE"]

    sigma = kernel_pixel_fwhm * gaussian_fwhm_to_sigma
    nsize = int(5 * kernel_pixel_fwhm)
    kernel = Gaussian2DKernel(sigma, x_size=nsize, y_size=nsize)

    bkg_estimator = photutils.MedianBackground()
    bkg = photutils.Background2D(hdu.data, (50, 50),
                                 bkg_estimator=bkg_estimator)
    thresh = bkg.background + (5.0 * bkg.background_rms)
    segmap_obj = photutils.detect_sources(hdu.data,
                                          thresh,
                                          npixels=5,
                                          filter_kernel=kernel,
                                          **kwargs)

    if segmap_obj is None:
        nhdu = fits.ImageHDU()
        nhdu.header["EXTNAME"] = "SEGMAP"
        fo.append(nhdu)

        thdu = fits.BinTableHDU()
        thdu.header["EXTNAME"] = "SEGMAP_PROPS"
        fo.append(thdu)

        fo.flush()
        fo.close()
        return None, None, None
    else:
        # Error image can be computed with photutils plus a GAIN keyword -- ratio of flux units to counts
        gain = filt_wheel[hdu.header["FILTER"]][2]
        errmap = calc_total_error(hdu.data,
                                  bkg.background_rms,
                                  effective_gain=gain)

        segmap = segmap_obj.data
        props = photutils.source_properties(hdu.data, segmap, errmap)
        props_table = astropy.table.Table(props.to_table())
        # these give problems given their format/NoneType objects
        props_table.remove_columns([
            "sky_centroid",
            "sky_centroid_icrs",
            "source_sum_err",
            "background_sum",
            "background_mean",
            "background_at_centroid",
        ])
        nhdu = fits.ImageHDU(segmap)

        # save segmap and info
        nhdu.header["EXTNAME"] = "SEGMAP"
        fo.append(nhdu)

        thdu = fits.BinTableHDU(props_table)
        thdu.header["EXTNAME"] = "SEGMAP_PROPS"
        fo.append(thdu)

        fo.flush()

        nhdu = fits.ImageHDU(errmap)

        # save errmap
        nhdu.header["EXTNAME"] = "WEIGHT_MAP"
        fo.append(nhdu)

        fo.flush()
        fo.close()
    return segmap_obj, kernel, errmap
Пример #6
0
def forced_phot(image,
                wcs,
                zp,
                catalog_alt,
                catalog_az,
                catalog_mag,
                catalog_id,
                nside=8,
                phot_params=None,
                do_background=False,
                return_table=False,
                mjd=0.):
    """
    Generate a map of the extinction on the sky

    Parameters
    ----------
    image : array
        The image to find the extinction map from
    wcs : wcs-like object
        WCS describing the image. Note WCS RA,Dec will be interpreted as Az,Alt.
    zp : float
        The zeropoint of the image
    catalog_alt : array
        Altitude of stars expected to be in the image (degrees)
    catalog_az : array
        Azimuth of stars expected in the image (degrees)
    catalog_mag : array
        Magnitudes of stars expected in the image
    nside : int
        Healpixel nside to set resoltion of output map
    phot_params : dict (None)
        Dictionary holding common photometry kwargs. Loads defaults from default_phot_params
        if None.
    do_background : bool (False)
        Do a 2D background model subtraction. Skipped by default because astropy is really slow.
    return_table : bool (False)
        If True, return the astropy table with the photometry, otherwise, return the extinction map.

    Output
    ------
    extinction : array
        A healpixel array (where latitude and longitude are altitude and azimuth). Pixels
        with no stars are filled with the healpixel mask value. Non-masked pixels have the
        measured extinction in magnitudes.
    """

    if phot_params is None:
        phot_params = default_phot_params()

    # Find the healpixel for each catalog star
    lat = np.radians(90. - catalog_alt)
    catalog_hp = hp.ang2pix(nside, lat, np.radians(catalog_az))

    order = np.argsort(catalog_hp)
    catalog_alt = catalog_alt[order]
    catalog_az = catalog_az[order]
    catalog_mag = catalog_mag[order]
    catalog_id = catalog_id[order]
    catalog_hp = catalog_hp[order]
    catalog_x, catalog_y = wcs.all_world2pix(catalog_az, catalog_alt, 0)

    good_transform = ~np.isnan(catalog_x)

    # Find the x,y positions of helpix centers
    lat, lon = hp.pix2ang(nside, np.arange(hp.nside2npix(nside)))
    hp_alt = np.degrees(np.pi / 2. - lat)
    hp_az = np.degrees(lon)
    hp_x, hp_y = wcs.all_world2pix(hp_az, hp_alt, 0)

    # Run the photometry at the expected catalog positions
    if do_background:
        sigma_clip = phu.SigmaClip(sigma=phot_params['bk_clip_sigma'],
                                   iters=phot_params['bk_iter'])
        bkg_estimator = phu.MedianBackground()
        bkg = phu.Background2D(
            image,
            (phot_params['background_size'], phot_params['background_size']),
            filter_size=(phot_params['bk_filter_size'],
                         phot_params['bk_filter_size']),
            sigma_clip=sigma_clip,
            bkg_estimator=bkg_estimator)
        bk_img = image - bkg.background
    else:
        bk_img = image

    positions = list(zip(catalog_x[good_transform], catalog_y[good_transform]))
    apertures = phu.CircularAperture(positions, r=phot_params['apper_r'])
    annulus_apertures = phu.CircularAnnulus(positions,
                                            r_in=phot_params['ann_r_in'],
                                            r_out=phot_params['ann_r_out'])

    apers = [apertures, annulus_apertures]
    phot_table = phu.aperture_photometry(bk_img, apers)

    bkg_mean = phot_table['aperture_sum_1'] / annulus_apertures.area()
    bkg_sum = bkg_mean * apertures.area()
    final_sum = phot_table['aperture_sum_0'] - bkg_sum
    phot_table['residual_aperture_sum'] = final_sum
    phot_table['catalog_id'] = catalog_id[good_transform]

    phot_table['residual_aperture_mag'] = -2.5 * np.log10(final_sum) + zp
    detected = np.where(final_sum > 0)

    mag_difference = phot_table['residual_aperture_mag'][
        detected] - catalog_mag[good_transform][detected]
    phot_table['mag_difference'] = np.zeros(
        phot_table['residual_aperture_mag'].data.size, dtype=float)
    phot_table['mjd'] = np.zeros(phot_table['residual_aperture_mag'].data.size,
                                 dtype=float)
    phot_table['mag_difference'][detected] = mag_difference
    phot_table['mjd'] = mjd

    bins = np.arange(hp.nside2npix(nside) + 1) - 0.5
    result, be, bn = binned_statistic(catalog_hp[good_transform][detected],
                                      mag_difference,
                                      bins=bins)

    if return_table:
        return phot_table, result
    else:
        return result
Пример #7
0
def getBackground(data,
                  fitsfilename,
                  bkg_method='2d',
                  box_size=128,
                  params=None,
                  locs=None):
    if bkg_method == '2d':
        bkg_estimator = pt.MedianBackground()
        data_mask = (data < 1.1 * np.median(data))
        bkg_maskarr = np.ma.array(data, mask=~data_mask)
        bkg = pt.Background2D(bkg_maskarr, (box_size, box_size),
                              filter_size=(3, 3),
                              sigma_clip=None,
                              bkg_estimator=bkg_estimator)
        bkg_median = bkg.background_median
        plt.imshow(bkg.background,
                   origin='lower',
                   vmin=bkg_median - 100,
                   vmax=bkg_median + 100,
                   cmap='Greys')
        plt.colorbar(orientation='horizontal')
        if not os.path.exists(
                os.path.join(os.path.dirname(fitsfilename), 'background')):
            os.makedirs(
                os.path.join(os.path.dirname(fitsfilename), 'background'))
        savepath = os.path.join(
            os.path.join(os.path.dirname(fitsfilename), 'background'),
            'bkg_' + os.path.split(fitsfilename[:-5])[-1] + '.png')
        plt.savefig(savepath)
        plt.clf()
        plt.close()
    elif bkg_method == 'aperture':
        bkg_arr = data.copy()
        bkg = []
        for loc in locs:
            bkg_arr[loc[0] - params['sky_rad_in']:loc[0] +
                    params['sky_rad_in'],
                    loc[1] - params['sky_rad_in']:loc[1] +
                    params['sky_rad_in']] = np.nan
            bkg.append(
                np.nanmedian(bkg_arr[loc[0] - params['sky_rad_out']:loc[0] +
                                     params['sky_rad_out'],
                                     loc[1] - params['sky_rad_out']:loc[1] +
                                     params['sky_rad_out']].flatten()))

        plt.imshow(bkg_arr,
                   origin='lower',
                   vmin=np.nanmedian(bkg_arr) - 100,
                   vmax=np.nanmedian(bkg_arr) + 100)
        plt.colorbar()
        for loc in locs:
            plt.gca().add_patch(
                patch.Rectangle((loc[1] - params['sky_rad_out'],
                                 loc[0] - params['sky_rad_out']),
                                2 * params['sky_rad_out'],
                                2 * params['sky_rad_out'],
                                color='k',
                                alpha=0.5))
        if not os.path.exists(
                os.path.join(os.path.dirname(fitsfilename), 'background')):
            os.makedirs(
                os.path.join(os.path.dirname(fitsfilename), 'background'))
        savepath = os.path.join(
            os.path.join(os.path.dirname(fitsfilename), 'background'),
            'bkg_' + os.path.split(fitsfilename[:-5])[-1] + '.png')
        plt.savefig(savepath)
        plt.clf()
        plt.close()
        bkg = np.array(bkg)
        bkg = BkgWrapper(bkg)
    elif bkg_method == 'median':
        return BkgWrapper(np.median(data.flatten()))
    elif bkg_method == 'None':
        return None
    else:
        raise ValueError('Method %s not supported.' % bkg_method)

    return bkg