コード例 #1
0
ファイル: residuals.py プロジェクト: SKIRT/PTS
    def old(self):

        """
        This function ...
        :return:
        """

        exit()

        # FWHM of all the images
        fwhm = 11.18 * u("arcsec")
        fwhm_pix = (fwhm / frame.average_pixelscale).to("pix").value
        sigma = fwhm_pix * statistics.fwhm_to_sigma

        # Get the center pixel of the galaxy
        parameters_path = fs.join(components_path, "parameters.dat")
        parameters = load_parameters(parameters_path)
        center = parameters.center.to_pixel(frame.wcs)

        # Create a source around the galaxy center
        ellipse = PixelEllipseRegion(center, 20.0*sigma)
        source = Source.from_ellipse(model_residual, ellipse, 1.5)

        source.estimate_background("polynomial")

        source.plot()

        position = source.center
        model = source.subtracted.fit_model(position, "Gaussian")

        rel_center = center - Extent(source.x_min, source.y_min)
        rel_model = fitting.shifted_model(model, -source.cutout.x_min, -source.cutout.y_min)
        plotting.plot_peak_model(source.cutout, rel_center.x, rel_center.y, rel_model)

        model_fwhm_pix = fitting.fwhm(model)
        model_fwhm = (model_fwhm_pix * frame.average_pixelscale).to("arcsec")

        print("Model FWHM: ", model_fwhm)

        evaluated_model = source.cutout.evaluate_model(model)

        all_residual = Frame(np.copy(model_residual))
        all_residual[source.y_slice, source.x_slice] -= evaluated_model
        all_residual.saveto(fs.join(residuals_path, "all_residual.fits"))

        model = Gaussian2D(amplitude=0.0087509425805, x_mean=center.x, y_mean=center.y, x_stddev=sigma, y_stddev=sigma)
        rel_model = fitting.shifted_model(model, -source.cutout.x_min, -source.cutout.y_min)
        plotting.plot_peak_model(source.cutout, rel_center.x, rel_center.y, rel_model)

        evaluated_model = source.cutout.evaluate_model(model)

        all_residual2 = Frame(np.copy(model_residual))
        all_residual2[source.y_slice, source.x_slice] -= evaluated_model
        all_residual2.saveto(fs.join(residuals_path, "all_residual2.fits"))
コード例 #2
0
ファイル: test.py プロジェクト: rag9704/PTS
class SkyTest(TestImplementation):
    """
    This class ...
    """
    def __init__(self, *args, **kwargs):
        """
        The constructor ...
        :param kwargs:
        """

        # Call the constructor of the base class
        super(SkyTest, self).__init__(*args, **kwargs)

        # FRAME COMPONENTS

        # The sources map
        self.sources = None

        # The noise map
        self.noise = None

        # The galaxy
        self.galaxy = None

        # Real sky frames
        self.constant_sky = None
        self.gradient_sky = None

        # TABLES
        self.source_table = None

        # MASKS

        # The sources mask
        self.sources_mask = None

        # The rotation mask
        self.rotation_mask = None

        # The galaxy
        self.galaxy_region = None

        # SKY ESTIMATION

        # Photutils Background2D object
        self.photutils_bkg = None

        # Sky reference estimation
        self.reference_sky = None

        # Path
        self.subtraction_path = None

        # The sky subtractor
        self.subtractor = None

        # STATISTICS

        # The statistics
        self.statistics = Map()

    # -----------------------------------------------------------------

    def run(self, **kwargs):
        """
        This function ...
        :param kwargs:
        :return:
        """

        # 1. Call the setup function
        self.setup(**kwargs)

        # 2. Make rotation mask
        self.make_rotation_mask()

        # 3. Generate the sources
        self.make_sources()

        # 4. Make noise
        self.make_noise()

        # 5. Make galaxy
        self.make_galaxy()

        # 6. Make sky
        self.make_sky()

        # 7. Mask sources
        self.mask_sources()

        # 8. Statistics
        self.calculate_statistics()

        # 9. Reference
        self.reference()

        # 10. Subtract
        self.subtract()

        # 11. Write
        self.write()

        # 12. Plot
        self.plot()

    # -----------------------------------------------------------------

    def setup(self, **kwargs):
        """
        This function ...
        :param kwargs:
        :return:
        """

        # Call the setup function of the base class
        super(SkyTest, self).setup(**kwargs)

        # Set the subtraction path
        self.subtraction_path = fs.create_directory_in(self.path,
                                                       "subtraction")

    # -----------------------------------------------------------------

    def make_rotation_mask(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Making rotation mask ...")

        # Rotate
        if self.config.rotate:

            frame = Frame.zeros(self.config.shape)
            self.rotation_mask = frame.rotate(self.config.rotation_angle)

        else:
            self.rotation_mask = Mask.empty(self.config.shape[1],
                                            self.config.shape[0])

    # -----------------------------------------------------------------

    @property
    def effective_rotation_angle(self):
        """
        THis function ...
        :return:
        """

        if self.config.rotate: return self.config.rotation_angle
        else: return Angle(0.0, "deg")

    # -----------------------------------------------------------------

    @property
    def shape(self):
        """
        THis function ...
        :return:
        """

        return self.rotation_mask.shape

    # -----------------------------------------------------------------

    @property
    def xsize(self):
        """
        This function ...
        :return:
        """

        return self.rotation_mask.xsize

    # -----------------------------------------------------------------

    @property
    def ysize(self):
        """
        This function ...
        :return:
        """

        return self.rotation_mask.ysize

    # -----------------------------------------------------------------

    @property
    def sources_sigma(self):
        """
        This function ...
        :return:
        """

        return self.config.fwhm * statistics.fwhm_to_sigma

    # -----------------------------------------------------------------

    def make_sources(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Making the sources ...")

        flux_range = [self.config.flux_range.min, self.config.flux_range.max]
        xmean_range = [0, self.config.shape[1]]
        ymean_range = [0, self.config.shape[0]]

        # Ranges of sigma
        xstddev_range = [self.sources_sigma, self.sources_sigma]
        ystddev_range = [self.sources_sigma, self.sources_sigma]

        table = make_random_gaussians(self.config.nsources,
                                      flux_range,
                                      xmean_range,
                                      ymean_range,
                                      xstddev_range,
                                      ystddev_range,
                                      random_state=12345)
        self.source_table = table

        data = make_gaussian_sources(self.config.shape, table)
        self.sources = Frame(data)

        # mask
        self.sources[self.rotation_mask] = 0.0

        if self.config.plot: plotting.plot_box(self.sources, title="sources")

    # -----------------------------------------------------------------

    def make_noise(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Making noise map ...")

        # Make noise
        data = make_noise_image(self.config.shape,
                                type='gaussian',
                                mean=0.,
                                stddev=self.config.noise_stddev,
                                random_state=12345)
        self.noise = Frame(data)

        # Mask
        self.noise[self.rotation_mask] = 0.0

        # Plot
        #if self.config.plot: plotting.plot_difference(self.frame, self.real_sky, title="original")
        if self.config.plot: plotting.plot_box(self.noise, title="noise")

    # -----------------------------------------------------------------

    def make_galaxy(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Adding smooth galaxy source ...")

        effective_radius = self.config.galaxy_effective_radius
        effective_galaxy_angle = self.config.galaxy_angle + self.effective_rotation_angle

        axial_ratio = self.config.galaxy_axial_ratio
        angle_deg = effective_galaxy_angle.to("deg").value

        # Produce guess values
        initial_sersic_amplitude = self.config.galaxy_central_flux
        initial_sersic_r_eff = effective_radius
        initial_sersic_n = self.config.galaxy_sersic_index
        initial_sersic_x_0 = self.config.galaxy_position.x
        initial_sersic_y_0 = self.config.galaxy_position.y
        initial_sersic_ellip = (axial_ratio - 1.0) / axial_ratio
        initial_sersic_theta = np.deg2rad(angle_deg)

        # Produce sersic model from guess parameters, for time trials
        sersic_x, sersic_y = np.meshgrid(np.arange(self.xsize),
                                         np.arange(self.ysize))
        sersic_model = Sersic2D(amplitude=initial_sersic_amplitude,
                                r_eff=initial_sersic_r_eff,
                                n=initial_sersic_n,
                                x_0=initial_sersic_x_0,
                                y_0=initial_sersic_y_0,
                                ellip=initial_sersic_ellip,
                                theta=initial_sersic_theta)
        sersic_map = sersic_model(sersic_x, sersic_y)

        # Set the galaxy frame
        self.galaxy = Frame(sersic_map)

        # Mask
        self.galaxy[self.rotation_mask] = 0.0

        limit_radius = self.config.galaxy_relative_asymptotic_radius * effective_radius

        # Create galaxy region
        galaxy_center = PixelCoordinate(initial_sersic_x_0, initial_sersic_y_0)
        galaxy_radius = PixelStretch(limit_radius, limit_radius / axial_ratio)
        self.galaxy_region = PixelEllipseRegion(galaxy_center, galaxy_radius,
                                                effective_galaxy_angle)

        # Set galaxy map zero outside certain radius
        self.galaxy[self.galaxy_mask.inverse()] = 0.0

        # Plot
        if self.config.plot: plotting.plot_box(self.galaxy, title="galaxy")

    # -----------------------------------------------------------------

    def make_sky(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Making sky ...")

        # make constant sky
        self.make_constant_sky()

        # Make gradient sky
        self.make_gradient_sky()

    # -----------------------------------------------------------------

    def make_constant_sky(self):
        """
        This function ..
        :return:
        """

        # Inform the user
        log.info("Making constant sky ...")

        self.constant_sky = Frame.filled_like(self.sources,
                                              self.config.constant_sky)

        # Mask
        self.constant_sky[self.rotation_mask] = 0.0

        # Plot

    # -----------------------------------------------------------------

    def make_gradient_sky(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Making gradient sky ...")

        y, x = np.mgrid[:self.ysize, :self.xsize]

        # Create gradient sky
        self.gradient_sky = Frame(x * y / 5000.)

        # Mask padded
        self.gradient_sky[self.rotation_mask] = 0.0

        # Plot
        #if self.config.plot: plotting.plot_difference(self.frame, self.real_sky, title="frame with background")
        if self.config.plot:
            plotting.plot_box(self.gradient_sky, title="gradient sky")

    # -----------------------------------------------------------------

    @lazyproperty
    def sky(self):
        """
        This function ...
        :return:
        """

        return self.constant_sky + self.gradient_sky

    # -----------------------------------------------------------------

    @lazyproperty
    def frame(self):
        """
        This fucntion ...
        :return:
        """

        return self.sources_with_galaxy_and_noise + self.sky

    # -----------------------------------------------------------------

    @lazyproperty
    def sources_with_noise(self):
        """
        This function ...
        :return:
        """

        return self.noise + self.sources

    # -----------------------------------------------------------------

    @lazyproperty
    def sources_with_galaxy_and_noise(self):
        """
        This function ...
        :return:
        """

        return self.sources_with_noise + self.galaxy

    # -----------------------------------------------------------------

    def mask_sources(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Masking sources ...")

        # Create sources mask
        mask = make_source_mask(self.sources_with_noise.data,
                                snr=2,
                                npixels=5,
                                dilate_size=11,
                                mask=self.rotation_mask)
        self.sources_mask = Mask(mask)

        # Plot
        if self.config.plot:
            plotting.plot_mask(self.sources_mask, title="sources mask")

    # -----------------------------------------------------------------

    def calculate_statistics(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Calculating statistics ...")

        # Calculate statistics no sigma clipping
        self.calculate_statistics_no_clipping()

        # Calculate statistics clipping
        self.calculate_statistics_clipping()

        # Calculate statistics masked sources
        self.calculate_statistics_masked()

    # -----------------------------------------------------------------

    def calculate_statistics_no_clipping(self):
        """
        This function ...
        :return:
        """

        # Compress (remove masked values)
        flattened = np.ma.array(self.sources_with_noise.data,
                                mask=self.rotation_mask.data).compressed()

        median = np.median(flattened)
        biweight_loc = biweight_location(flattened)

        biweight_midvar = biweight_midvariance(flattened)
        median_absolute_deviation = mad_std(flattened)

        #print("median", median)
        #print("biweigth_loc", biweight_loc)
        #print("biweight_midvar", biweight_midvar)
        #print("median_absolute_deviation", median_absolute_deviation)

        self.statistics.no_clipping = Map()
        self.statistics.no_clipping.median = median
        self.statistics.no_clipping.biweight_loc = biweight_loc
        self.statistics.no_clipping.biweight_midvar = biweight_midvar
        self.statistics.no_clipping.median_absolute_deviation = median_absolute_deviation

        # SAME RESULTS:

        # median = np.median(self.original_frame)
        # biweight_loc = biweight_location(self.original_frame)
        # biweight_midvar = biweight_midvariance(self.original_frame)
        # median_absolute_deviation = mad_std(self.original_frame)

        # print("median", median)
        # print("biweigth_loc", biweight_loc)
        # print("biweight_midvar", biweight_midvar)
        # print("median_absolute_deviation", median_absolute_deviation)

    # -----------------------------------------------------------------

    def calculate_statistics_clipping(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Sigma-clipping ...")

        # Sigma clip
        mean, median, std = sigma_clipped_stats(self.sources_with_noise.data,
                                                sigma=3.0,
                                                iters=5,
                                                mask=self.rotation_mask)

        #print("sigma-clip mean:", mean)
        #print("sigma-clip median:", median)
        #print("sigma-clip std:", std)

        self.statistics.clipping = Map()
        self.statistics.clipping.mean = mean
        self.statistics.clipping.median = median
        self.statistics.clipping.std = std

    # -----------------------------------------------------------------

    def calculate_statistics_masked(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Calculating statistics with sources masked ...")

        # Statistics
        mean, median, std = sigma_clipped_stats(self.sources_with_noise.data,
                                                sigma=3.0,
                                                mask=self.total_mask.data,
                                                iters=5)

        #print("sigma-clip mean after source masking:", mean)
        #print("sigma-clip median after source masking:", median)
        #print("sigma_clip std after source masking:", std)

        # Set the statistics
        self.statistics.masked = Map()
        self.statistics.masked.mean = mean
        self.statistics.masked.median = median
        self.statistics.masked.std = std

    # -----------------------------------------------------------------

    @lazyproperty
    def total_mask(self):
        """
        This function ...
        :return:
        """

        return self.sources_and_rotation_mask + self.galaxy_mask

    # -----------------------------------------------------------------

    @lazyproperty
    def sources_and_rotation_mask(self):
        """
        This function ...
        :return:
        """

        return self.sources_mask + self.rotation_mask

    # -----------------------------------------------------------------

    @lazyproperty
    def galaxy_mask(self):
        """
        This function ...
        :return:
        """

        # Make mask
        return self.galaxy_region.to_mask(self.xsize, self.ysize)

    # -----------------------------------------------------------------

    @lazyproperty
    def reference_subtracted(self):
        """
        This function ...
        :return:
        """

        return self.frame - self.reference_sky

    # -----------------------------------------------------------------

    @lazyproperty
    def subtracted(self):
        """
        This function ...
        :return:
        """

        return self.frame - self.estimated_sky

    # -----------------------------------------------------------------

    @property
    def aperture_radius(self):
        """
        This function ...
        :return:
        """

        return self.config.fwhm * self.config.aperture_fwhm_factor

    # -----------------------------------------------------------------

    @property
    def aperture_diameter(self):
        """
        This function ...
        :return:
        """

        return 2.0 * self.aperture_radius

    # -----------------------------------------------------------------

    def reference(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Estimating background with photutils ...")

        # Plot total mask
        if self.config.plot:
            plotting.plot_mask(self.total_mask, title="total mask")

        integer_aperture_radius = int(math.ceil(self.aperture_radius))
        box_shape = (integer_aperture_radius, integer_aperture_radius)
        filter_size = (3, 3)

        # Estimate the background
        sigma_clip = SigmaClip(sigma=3., iters=10)
        #bkg_estimator = MedianBackground()
        bkg_estimator = SExtractorBackground()

        bkg = Background2D(self.frame.data,
                           box_shape,
                           filter_size=filter_size,
                           sigma_clip=sigma_clip,
                           bkg_estimator=bkg_estimator,
                           mask=self.total_mask.data)

        # Statistics
        #print("median background", bkg.background_median)
        #print("rms background", bkg.background_rms_median)

        self.statistics.reference = Map()
        self.statistics.reference.median = bkg.background_median
        self.statistics.reference.rms = bkg.background_rms_median

        # Plot
        if self.config.plot:
            plotting.plot_box(bkg.background,
                              title="background from photutils")

        # Set the sky
        self.reference_sky = Frame(bkg.background)

        # Set bkg object
        self.photutils_bkg = bkg

        # Plot
        if self.config.plot:
            plotting.plot_box(self.reference_sky, title="reference sky")

    # -----------------------------------------------------------------

    def subtract(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Subtracting the sky ...")

        # Settings
        settings = dict()
        settings["estimation"] = dict()
        settings["estimation"]["method"] = "photutils"
        settings["estimation"]["aperture_radius"] = self.aperture_radius
        settings["write"] = True
        #settings["estimation"]["finishing_step"] = "polynomial"
        #settings["estimation"]["polynomial_degree"] = self.config.polynomial_degree
        #settings["estimation"]["fill_method"] = "cubic"

        settings["plot"] = True

        # Input
        input_dict = dict()

        # Set input
        input_dict["frame"] = self.frame
        input_dict["principal_shape"] = self.galaxy_region
        input_dict["sources_mask"] = self.sources_mask
        input_dict["extra_mask"] = self.rotation_mask

        # Create command
        command = Command(
            "subtract_sky",
            "subtract the sky from an artificially created image",
            settings,
            input_dict,
            cwd=self.subtraction_path)

        # Run the subtraction
        self.subtractor = self.run_command(command)

    # -----------------------------------------------------------------

    @property
    def estimated_sky(self):
        """
        This function ...
        :return:
        """

        return self.subtractor.sky_frame

    # -----------------------------------------------------------------

    @lazyproperty
    def subtracted(self):
        """
        This function ...
        :return:
        """

        return self.frame - self.estimated_sky

    # -----------------------------------------------------------------

    @lazyproperty
    def sky_residual(self):
        """
        This function ...
        :return:
        """

        return self.estimated_sky - self.sky

    # -----------------------------------------------------------------

    def write(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing ...")

        # Write the sources with noise
        self.write_sources()

        # Write the frame
        self.write_frame()

        # Write real sky map
        self.write_real_sky()

        # Write sources mask
        self.write_sources_mask()

        # Write galaxy mask
        self.write_galaxy_mask()

        # Write reference sky
        self.write_reference_sky()

        # Write estiamted sky
        self.write_estimated_sky()

        # Write residuals
        self.write_residual()

        # Write the statistics
        self.write_statistics()

    # -----------------------------------------------------------------

    def write_sources(self):
        """
        THis function ...
        :return:
        """

        # Inform the user
        log.info("Writing the sources frame with noise ...")

        # Determine the path
        path = fs.join(self.path, "sources_noise.fits")

        # Save the frame
        self.sources_with_noise.saveto(path)

    # -----------------------------------------------------------------

    def write_frame(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing the frame ...")

        # Determine the path
        path = fs.join(self.path, "frame.fits")

        # SAve the frame
        self.frame.saveto(path)

    # -----------------------------------------------------------------

    def write_real_sky(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing the real sky map ...")

        # Determine the path
        path = fs.join(self.path, "real_sky.fits")

        # Save the map
        self.sky.saveto(path)

    # -----------------------------------------------------------------

    def write_sources_mask(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing the sources mask ...")

        # Determine the path
        path = fs.join(self.path, "sources_mask.fits")

        # Save
        self.sources_mask.saveto(path)

    # -----------------------------------------------------------------

    def write_galaxy_mask(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing the galaxy mask ...")

        # Determine the path
        path = fs.join(self.path, "galaxy_mask.fits")

        # Save
        self.galaxy_mask.saveto(path)

    # -----------------------------------------------------------------

    def write_reference_sky(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing the reference sky map ...")

        # Determine the path
        path = fs.join(self.path, "reference_sky.fits")

        # Save
        self.reference_sky.saveto(path)

    # -----------------------------------------------------------------

    def write_estimated_sky(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing the estimated sky map ...")

        # Determine the path
        path = fs.join(self.path, "estimated_sky.fits")

        # Save
        self.estimated_sky.saveto(path)

    # -----------------------------------------------------------------

    def write_subtracted(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing the sky-subtracted frame ...")

        # Determine the path
        path = fs.join(self.path, "subtracted.fits")

        # Save
        self.subtracted.saveto(path)

    # -----------------------------------------------------------------

    def write_residual(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing the residual map ...")

        # Determine the path
        path = fs.join(self.path, "residual.fits")

        # Save
        self.sky_residual.saveto(path)

    # -----------------------------------------------------------------

    def write_statistics(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing the statistics ...")

        # Determine the path
        path = fs.join(self.path, "statistics.dat")

        # Write
        save_mapping(path, self.statistics)

    # -----------------------------------------------------------------

    def plot(self):
        """
        This function ...
        :return:
        """

        # Inofmrthe user
        log.info("Plotting ...")

        # Plot meshes
        if self.config.plotting.meshes: self.plot_meshes()

    # -----------------------------------------------------------------

    def plot_meshes(self):
        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Plotting the meshes ...")

        # Plot meshes
        plt.figure()
        norm = ImageNormalize(stretch=SqrtStretch())
        plt.imshow(self.frame, origin='lower', cmap='Greys_r', norm=norm)
        self.photutils_bkg.plot_meshes(outlines=True, color='#1f77b4')
        plt.show()
コード例 #3
0
ファイル: create_mask.py プロジェクト: SKIRT/PTS
# -----------------------------------------------------------------

# Load the image
frame = Frame.from_file(arguments.image)

# Load the region
region_name = os.path.splitext(os.path.basename(arguments.region))[0]
region = load_as_pixel_region_list(arguments.region, frame.wcs)

# Create the mask
mask = region.to_mask(x_size=frame.xsize, y_size=frame.ysize)

# Calculate the inverse, if requested
if arguments.invert: mask = mask.inverse()

# -----------------------------------------------------------------

if arguments.data:
    
    new_frame = frame
    frame[mask] = arguments.value
    
# Create a frame for the total mask
else: new_frame = Frame(mask.astype(int))

# Write out the new frame
new_frame.saveto(region_name + ".fits")

# -----------------------------------------------------------------
コード例 #4
0
ファイル: test.py プロジェクト: SKIRT/PTS
class SkyTest(TestImplementation):

    """
    This class ...
    """

    def __init__(self, *args, **kwargs):

        """
        The constructor ...
        :param kwargs:
        """

        # Call the constructor of the base class
        super(SkyTest, self).__init__(*args, **kwargs)

        # FRAME COMPONENTS

        # The sources map
        self.sources = None

        # The noise map
        self.noise = None

        # The galaxy
        self.galaxy = None

        # Real sky frames
        self.constant_sky = None
        self.gradient_sky = None

        # TABLES
        self.source_table = None

        # MASKS

        # The sources mask
        self.sources_mask = None

        # The rotation mask
        self.rotation_mask = None

        # The galaxy
        self.galaxy_region = None

        # SKY ESTIMATION

        # Photutils Background2D object
        self.photutils_bkg = None

        # Sky reference estimation
        self.reference_sky = None

        # Path
        self.subtraction_path = None

        # The sky subtractor
        self.subtractor = None

        # STATISTICS

        # The statistics
        self.statistics = Map()

    # -----------------------------------------------------------------

    def _run(self, **kwargs):

        """
        This function ...
        :param kwargs:
        :return:
        """

        # 2. Make rotation mask
        self.make_rotation_mask()

        # 3. Generate the sources
        self.make_sources()

        # 4. Make noise
        self.make_noise()

        # 5. Make galaxy
        self.make_galaxy()

        # 6. Make sky
        self.make_sky()

        # 7. Mask sources
        self.mask_sources()

        # 8. Statistics
        self.calculate_statistics()

        # 9. Reference
        self.reference()

        # 10. Subtract
        self.subtract()

        # 11. Write
        self.write()

        # 12. Plot
        self.plot()

    # -----------------------------------------------------------------

    def setup(self, **kwargs):

        """
        This function ...
        :param kwargs:
        :return:
        """

        # Call the setup function of the base class
        super(SkyTest, self).setup(**kwargs)

        # Set the subtraction path
        self.subtraction_path = fs.create_directory_in(self.path, "subtraction")

    # -----------------------------------------------------------------

    def make_rotation_mask(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Making rotation mask ...")

        # Rotate
        if self.config.rotate:

            frame = Frame.zeros(self.config.shape)
            self.rotation_mask = frame.rotate(self.config.rotation_angle)

        else: self.rotation_mask = Mask.empty(self.config.shape[1], self.config.shape[0])

    # -----------------------------------------------------------------

    @property
    def effective_rotation_angle(self):

        """
        THis function ...
        :return:
        """

        if self.config.rotate: return self.config.rotation_angle
        else: return Angle(0.0, "deg")

    # -----------------------------------------------------------------

    @property
    def shape(self):

        """
        THis function ...
        :return:
        """

        return self.rotation_mask.shape

    # -----------------------------------------------------------------

    @property
    def xsize(self):

        """
        This function ...
        :return:
        """

        return self.rotation_mask.xsize

    # -----------------------------------------------------------------

    @property
    def ysize(self):

        """
        This function ...
        :return:
        """

        return self.rotation_mask.ysize

    # -----------------------------------------------------------------

    @property
    def sources_sigma(self):

        """
        This function ...
        :return:
        """

        return self.config.fwhm * statistics.fwhm_to_sigma

    # -----------------------------------------------------------------

    def make_sources(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Making the sources ...")

        flux_range = [self.config.flux_range.min, self.config.flux_range.max]
        xmean_range = [0, self.config.shape[1]]
        ymean_range = [0, self.config.shape[0]]

        # Ranges of sigma
        xstddev_range = [self.sources_sigma, self.sources_sigma]
        ystddev_range = [self.sources_sigma, self.sources_sigma]

        table = make_random_gaussians(self.config.nsources, flux_range, xmean_range,
                                      ymean_range, xstddev_range,
                                      ystddev_range, random_state=12345)
        self.source_table = table

        data = make_gaussian_sources(self.config.shape, table)
        self.sources = Frame(data)

        # mask
        self.sources[self.rotation_mask] = 0.0

        if self.config.plot: plotting.plot_box(self.sources, title="sources")

    # -----------------------------------------------------------------

    def make_noise(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Making noise map ...")

        # Make noise
        data = make_noise_image(self.config.shape, type='gaussian', mean=0., stddev=self.config.noise_stddev, random_state=12345)
        self.noise = Frame(data)

        # Mask
        self.noise[self.rotation_mask] = 0.0

        # Plot
        #if self.config.plot: plotting.plot_difference(self.frame, self.real_sky, title="original")
        if self.config.plot: plotting.plot_box(self.noise, title="noise")

    # -----------------------------------------------------------------

    def make_galaxy(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Adding smooth galaxy source ...")

        effective_radius = self.config.galaxy_effective_radius
        effective_galaxy_angle = self.config.galaxy_angle + self.effective_rotation_angle

        axial_ratio = self.config.galaxy_axial_ratio
        angle_deg = effective_galaxy_angle.to("deg").value

        # Produce guess values
        initial_sersic_amplitude = self.config.galaxy_central_flux
        initial_sersic_r_eff = effective_radius
        initial_sersic_n = self.config.galaxy_sersic_index
        initial_sersic_x_0 = self.config.galaxy_position.x
        initial_sersic_y_0 = self.config.galaxy_position.y
        initial_sersic_ellip = (axial_ratio - 1.0) / axial_ratio
        initial_sersic_theta = np.deg2rad(angle_deg)

        # Produce sersic model from guess parameters, for time trials
        sersic_x, sersic_y = np.meshgrid(np.arange(self.xsize), np.arange(self.ysize))
        sersic_model = Sersic2D(amplitude=initial_sersic_amplitude, r_eff=initial_sersic_r_eff,
                                                        n=initial_sersic_n, x_0=initial_sersic_x_0,
                                                        y_0=initial_sersic_y_0, ellip=initial_sersic_ellip,
                                                        theta=initial_sersic_theta)
        sersic_map = sersic_model(sersic_x, sersic_y)

        # Set the galaxy frame
        self.galaxy = Frame(sersic_map)

        # Mask
        self.galaxy[self.rotation_mask] = 0.0

        limit_radius = self.config.galaxy_relative_asymptotic_radius * effective_radius

        # Create galaxy region
        galaxy_center = PixelCoordinate(initial_sersic_x_0, initial_sersic_y_0)
        galaxy_radius = PixelStretch(limit_radius, limit_radius / axial_ratio)
        self.galaxy_region = PixelEllipseRegion(galaxy_center, galaxy_radius, effective_galaxy_angle)

        # Set galaxy map zero outside certain radius
        self.galaxy[self.galaxy_mask.inverse()] = 0.0

        # Plot
        if self.config.plot: plotting.plot_box(self.galaxy, title="galaxy")

    # -----------------------------------------------------------------

    def make_sky(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Making sky ...")

        # make constant sky
        self.make_constant_sky()

        # Make gradient sky
        self.make_gradient_sky()

    # -----------------------------------------------------------------

    def make_constant_sky(self):

        """
        This function ..
        :return:
        """

        # Inform the user
        log.info("Making constant sky ...")

        self.constant_sky = Frame.filled_like(self.sources, self.config.constant_sky)

        # Mask
        self.constant_sky[self.rotation_mask] = 0.0

        # Plot

    # -----------------------------------------------------------------

    def make_gradient_sky(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Making gradient sky ...")

        y, x = np.mgrid[:self.ysize, :self.xsize]

        # Create gradient sky
        self.gradient_sky = Frame(x * y / 5000.)

        # Mask padded
        self.gradient_sky[self.rotation_mask] = 0.0

        # Plot
        #if self.config.plot: plotting.plot_difference(self.frame, self.real_sky, title="frame with background")
        if self.config.plot: plotting.plot_box(self.gradient_sky, title="gradient sky")

    # -----------------------------------------------------------------

    @lazyproperty
    def sky(self):

        """
        This function ...
        :return:
        """

        return self.constant_sky + self.gradient_sky

    # -----------------------------------------------------------------

    @lazyproperty
    def frame(self):

        """
        This fucntion ...
        :return:
        """

        return self.sources_with_galaxy_and_noise + self.sky

    # -----------------------------------------------------------------

    @lazyproperty
    def sources_with_noise(self):

        """
        This function ...
        :return:
        """

        return self.noise + self.sources

    # -----------------------------------------------------------------

    @lazyproperty
    def sources_with_galaxy_and_noise(self):

        """
        This function ...
        :return:
        """

        return self.sources_with_noise + self.galaxy

    # -----------------------------------------------------------------

    def mask_sources(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Masking sources ...")

        # Create sources mask
        mask = make_source_mask(self.sources_with_noise.data, snr=2, npixels=5, dilate_size=11, mask=self.rotation_mask)
        self.sources_mask = Mask(mask)

        # Plot
        if self.config.plot: plotting.plot_mask(self.sources_mask, title="sources mask")

    # -----------------------------------------------------------------

    def calculate_statistics(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Calculating statistics ...")

        # Calculate statistics no sigma clipping
        self.calculate_statistics_no_clipping()

        # Calculate statistics clipping
        self.calculate_statistics_clipping()

        # Calculate statistics masked sources
        self.calculate_statistics_masked()

    # -----------------------------------------------------------------

    def calculate_statistics_no_clipping(self):

        """
        This function ...
        :return:
        """

        # Compress (remove masked values)
        flattened = np.ma.array(self.sources_with_noise.data, mask=self.rotation_mask.data).compressed()

        median = np.median(flattened)
        biweight_loc = biweight_location(flattened)

        biweight_midvar = biweight_midvariance(flattened)
        median_absolute_deviation = mad_std(flattened)

        #print("median", median)
        #print("biweigth_loc", biweight_loc)
        #print("biweight_midvar", biweight_midvar)
        #print("median_absolute_deviation", median_absolute_deviation)

        self.statistics.no_clipping = Map()
        self.statistics.no_clipping.median = median
        self.statistics.no_clipping.biweight_loc = biweight_loc
        self.statistics.no_clipping.biweight_midvar = biweight_midvar
        self.statistics.no_clipping.median_absolute_deviation = median_absolute_deviation

        # SAME RESULTS:

        # median = np.median(self.original_frame)
        # biweight_loc = biweight_location(self.original_frame)
        # biweight_midvar = biweight_midvariance(self.original_frame)
        # median_absolute_deviation = mad_std(self.original_frame)

        # print("median", median)
        # print("biweigth_loc", biweight_loc)
        # print("biweight_midvar", biweight_midvar)
        # print("median_absolute_deviation", median_absolute_deviation)

    # -----------------------------------------------------------------

    def calculate_statistics_clipping(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Sigma-clipping ...")

        # Sigma clip
        mean, median, std = sigma_clipped_stats(self.sources_with_noise.data, sigma=3.0, iters=5,
                                                mask=self.rotation_mask)

        #print("sigma-clip mean:", mean)
        #print("sigma-clip median:", median)
        #print("sigma-clip std:", std)

        self.statistics.clipping = Map()
        self.statistics.clipping.mean = mean
        self.statistics.clipping.median = median
        self.statistics.clipping.std = std

    # -----------------------------------------------------------------

    def calculate_statistics_masked(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Calculating statistics with sources masked ...")

        # Statistics
        mean, median, std = sigma_clipped_stats(self.sources_with_noise.data, sigma=3.0, mask=self.total_mask.data, iters=5)

        #print("sigma-clip mean after source masking:", mean)
        #print("sigma-clip median after source masking:", median)
        #print("sigma_clip std after source masking:", std)

        # Set the statistics
        self.statistics.masked = Map()
        self.statistics.masked.mean = mean
        self.statistics.masked.median = median
        self.statistics.masked.std = std

    # -----------------------------------------------------------------

    @lazyproperty
    def total_mask(self):

        """
        This function ...
        :return:
        """

        return self.sources_and_rotation_mask + self.galaxy_mask

    # -----------------------------------------------------------------

    @lazyproperty
    def sources_and_rotation_mask(self):

        """
        This function ...
        :return:
        """

        return self.sources_mask + self.rotation_mask

    # -----------------------------------------------------------------

    @lazyproperty
    def galaxy_mask(self):

        """
        This function ...
        :return:
        """

        # Make mask
        return self.galaxy_region.to_mask(self.xsize, self.ysize)

    # -----------------------------------------------------------------

    @lazyproperty
    def reference_subtracted(self):

        """
        This function ...
        :return:
        """

        return self.frame - self.reference_sky

    # -----------------------------------------------------------------

    @lazyproperty
    def subtracted(self):

        """
        This function ...
        :return:
        """

        return self.frame - self.estimated_sky

    # -----------------------------------------------------------------

    @property
    def aperture_radius(self):

        """
        This function ...
        :return:
        """

        return self.config.fwhm * self.config.aperture_fwhm_factor

    # -----------------------------------------------------------------

    @property
    def aperture_diameter(self):

        """
        This function ...
        :return:
        """

        return 2.0 * self.aperture_radius

    # -----------------------------------------------------------------

    def reference(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Estimating background with photutils ...")

        # Plot total mask
        if self.config.plot: plotting.plot_mask(self.total_mask, title="total mask")

        integer_aperture_radius = int(math.ceil(self.aperture_radius))
        box_shape = (integer_aperture_radius, integer_aperture_radius)
        filter_size = (3, 3)

        # Estimate the background
        sigma_clip = SigmaClip(sigma=3., iters=10)
        #bkg_estimator = MedianBackground()
        bkg_estimator = SExtractorBackground()

        bkg = Background2D(self.frame.data, box_shape, filter_size=filter_size, sigma_clip=sigma_clip,
                           bkg_estimator=bkg_estimator, mask=self.total_mask.data)

        # Statistics
        #print("median background", bkg.background_median)
        #print("rms background", bkg.background_rms_median)

        self.statistics.reference = Map()
        self.statistics.reference.median = bkg.background_median
        self.statistics.reference.rms = bkg.background_rms_median

        # Plot
        if self.config.plot: plotting.plot_box(bkg.background, title="background from photutils")

        # Set the sky
        self.reference_sky = Frame(bkg.background)

        # Set bkg object
        self.photutils_bkg = bkg

        # Plot
        if self.config.plot: plotting.plot_box(self.reference_sky, title="reference sky")

    # -----------------------------------------------------------------

    def subtract(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Subtracting the sky ...")

        # Settings
        settings = dict()
        settings["estimation"] = dict()
        settings["estimation"]["method"] = "photutils"
        settings["estimation"]["aperture_radius"] = self.aperture_radius
        settings["write"] = True
        #settings["estimation"]["finishing_step"] = "polynomial"
        #settings["estimation"]["polynomial_degree"] = self.config.polynomial_degree
        #settings["estimation"]["fill_method"] = "cubic"

        settings["plot"] = True

        # Input
        input_dict = dict()

        # Set input
        input_dict["frame"] = self.frame
        input_dict["principal_shape"] = self.galaxy_region
        input_dict["sources_mask"] = self.sources_mask
        input_dict["extra_mask"] = self.rotation_mask

        # Create command
        command = Command("subtract_sky", "subtract the sky from an artificially created image", settings, input_dict, cwd=self.subtraction_path)

        # Run the subtraction
        self.subtractor = self.run_command(command)

    # -----------------------------------------------------------------

    @property
    def estimated_sky(self):

        """
        This function ...
        :return:
        """

        return self.subtractor.sky_frame

    # -----------------------------------------------------------------

    @lazyproperty
    def subtracted(self):

        """
        This function ...
        :return:
        """

        return self.frame - self.estimated_sky

    # -----------------------------------------------------------------

    @lazyproperty
    def sky_residual(self):

        """
        This function ...
        :return:
        """

        return self.estimated_sky - self.sky

    # -----------------------------------------------------------------

    def write(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing ...")

        # Write the sources with noise
        self.write_sources()

        # Write the frame
        self.write_frame()

        # Write real sky map
        self.write_real_sky()

        # Write sources mask
        self.write_sources_mask()

        # Write galaxy mask
        self.write_galaxy_mask()

        # Write reference sky
        self.write_reference_sky()

        # Write estiamted sky
        self.write_estimated_sky()

        # Write residuals
        self.write_residual()

        # Write the statistics
        self.write_statistics()

    # -----------------------------------------------------------------

    def write_sources(self):

        """
        THis function ...
        :return:
        """

        # Inform the user
        log.info("Writing the sources frame with noise ...")

        # Determine the path
        path = fs.join(self.path, "sources_noise.fits")

        # Save the frame
        self.sources_with_noise.saveto(path)

    # -----------------------------------------------------------------

    def write_frame(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing the frame ...")

        # Determine the path
        path = fs.join(self.path, "frame.fits")

        # SAve the frame
        self.frame.saveto(path)

    # -----------------------------------------------------------------

    def write_real_sky(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing the real sky map ...")

        # Determine the path
        path = fs.join(self.path, "real_sky.fits")

        # Save the map
        self.sky.saveto(path)

    # -----------------------------------------------------------------

    def write_sources_mask(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing the sources mask ...")

        # Determine the path
        path = fs.join(self.path, "sources_mask.fits")

        # Save
        self.sources_mask.saveto(path)

    # -----------------------------------------------------------------

    def write_galaxy_mask(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing the galaxy mask ...")

        # Determine the path
        path = fs.join(self.path, "galaxy_mask.fits")

        # Save
        self.galaxy_mask.saveto(path)

    # -----------------------------------------------------------------

    def write_reference_sky(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing the reference sky map ...")

        # Determine the path
        path = fs.join(self.path, "reference_sky.fits")

        # Save
        self.reference_sky.saveto(path)

    # -----------------------------------------------------------------

    def write_estimated_sky(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing the estimated sky map ...")

        # Determine the path
        path = fs.join(self.path, "estimated_sky.fits")

        # Save
        self.estimated_sky.saveto(path)

    # -----------------------------------------------------------------

    def write_subtracted(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing the sky-subtracted frame ...")

        # Determine the path
        path = fs.join(self.path, "subtracted.fits")

        # Save
        self.subtracted.saveto(path)

    # -----------------------------------------------------------------

    def write_residual(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing the residual map ...")

        # Determine the path
        path = fs.join(self.path, "residual.fits")

        # Save
        self.sky_residual.saveto(path)

    # -----------------------------------------------------------------

    def write_statistics(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Writing the statistics ...")

        # Determine the path
        path = fs.join(self.path, "statistics.dat")

        # Write
        save_mapping(path, self.statistics)

    # -----------------------------------------------------------------

    def plot(self):

        """
        This function ...
        :return:
        """

        # Inofmrthe user
        log.info("Plotting ...")

        # Plot meshes
        if self.config.plotting.meshes: self.plot_meshes()

    # -----------------------------------------------------------------

    def plot_meshes(self):

        """
        This function ...
        :return:
        """

        # Inform the user
        log.info("Plotting the meshes ...")

        # Plot meshes
        plt.figure()
        norm = ImageNormalize(stretch=SqrtStretch())
        plt.imshow(self.frame, origin='lower', cmap='Greys_r', norm=norm)
        self.photutils_bkg.plot_meshes(outlines=True, color='#1f77b4')
        plt.show()
コード例 #5
0
    def old(self):
        """
        This function ...
        :return:
        """

        exit()

        # FWHM of all the images
        fwhm = 11.18 * u("arcsec")
        fwhm_pix = (fwhm / frame.average_pixelscale).to("pix").value
        sigma = fwhm_pix * statistics.fwhm_to_sigma

        # Get the center pixel of the galaxy
        parameters_path = fs.join(components_path, "parameters.dat")
        parameters = load_parameters(parameters_path)
        center = parameters.center.to_pixel(frame.wcs)

        # Create a source around the galaxy center
        ellipse = PixelEllipseRegion(center, 20.0 * sigma)
        source = Source.from_ellipse(model_residual, ellipse, 1.5)

        source.estimate_background("polynomial")

        source.plot()

        position = source.center
        model = source.subtracted.fit_model(position, "Gaussian")

        rel_center = center - Extent(source.x_min, source.y_min)
        rel_model = fitting.shifted_model(model, -source.cutout.x_min,
                                          -source.cutout.y_min)
        plotting.plot_peak_model(source.cutout, rel_center.x, rel_center.y,
                                 rel_model)

        model_fwhm_pix = fitting.fwhm(model)
        model_fwhm = (model_fwhm_pix * frame.average_pixelscale).to("arcsec")

        print("Model FWHM: ", model_fwhm)

        evaluated_model = source.cutout.evaluate_model(model)

        all_residual = Frame(np.copy(model_residual))
        all_residual[source.y_slice, source.x_slice] -= evaluated_model
        all_residual.saveto(fs.join(residuals_path, "all_residual.fits"))

        model = Gaussian2D(amplitude=0.0087509425805,
                           x_mean=center.x,
                           y_mean=center.y,
                           x_stddev=sigma,
                           y_stddev=sigma)
        rel_model = fitting.shifted_model(model, -source.cutout.x_min,
                                          -source.cutout.y_min)
        plotting.plot_peak_model(source.cutout, rel_center.x, rel_center.y,
                                 rel_model)

        evaluated_model = source.cutout.evaluate_model(model)

        all_residual2 = Frame(np.copy(model_residual))
        all_residual2[source.y_slice, source.x_slice] -= evaluated_model
        all_residual2.saveto(fs.join(residuals_path, "all_residual2.fits"))
コード例 #6
0
# -----------------------------------------------------------------

# Load the image
frame = Frame.from_file(arguments.image)

# Load the region
region_name = os.path.splitext(os.path.basename(arguments.region))[0]
region = load_as_pixel_region_list(arguments.region, frame.wcs)

# Create the mask
mask = region.to_mask(x_size=frame.xsize, y_size=frame.ysize)

# Calculate the inverse, if requested
if arguments.invert: mask = mask.inverse()

# -----------------------------------------------------------------

if arguments.data:

    new_frame = frame
    frame[mask] = arguments.value

# Create a frame for the total mask
else:
    new_frame = Frame(mask.astype(int))

# Write out the new frame
new_frame.saveto(region_name + ".fits")

# -----------------------------------------------------------------