Exemple #1
0
def test_gaussian1d_fit():
    """Test histogram fitting function"""

    mean_value = 0.5
    sigma_value = 0.05
    image = np.random.normal(loc=mean_value, scale=sigma_value, size=(100, 100))
    hist, bin_edges = np.histogram(image, bins='auto')
    bin_centers = (bin_edges[1:] + bin_edges[0: -1]) / 2.
    initial_params = [np.max(hist), 0.55, 0.1]
    amplitude, peak, width = calculations.gaussian1d_fit(bin_centers, hist, initial_params)

    assert np.isclose(peak[0], mean_value, atol=0.0015, rtol=0.)
    assert np.isclose(width[0], sigma_value, atol=0.0015, rtol=0.)
    assert ((mean_value <= peak[0]+3*peak[1]) & (mean_value >= peak[0]-3*peak[1]))
    assert ((sigma_value <= width[0]+3*width[1]) & (sigma_value >= width[0]-3*width[1]))
Exemple #2
0
    def stats_by_amp(self, image, amps):
        """Calculate statistics in the input image for each amplifier as
        well as the full image

        Parameters
        ----------
        image : numpy.ndarray
            2D array on which to calculate statistics

        amps : dict
            Dictionary containing amp boundary coordinates (output from
            ``amplifier_info`` function)
            ``amps[key] = [(xmin, xmax, xstep), (ymin, ymax, ystep)]``

        Returns
        -------
        amp_means : dict
            Sigma-clipped mean value for each amp. Keys are amp numbers
            as strings (e.g. ``'1'``)

        amp_stdevs : dict
            Sigma-clipped standard deviation for each amp. Keys are amp
            numbers as strings (e.g. ``'1'``)

        gaussian_params : dict
            Best-fit Gaussian parameters to the dark current histogram.
            Keys are amp numbers as strings. Values are three-element
            lists ``[amplitude, peak, width]``. Each element in the list
            is a tuple of the best-fit value and the associated
            uncertainty.

        gaussian_chi_squared : dict
            Reduced chi-squared for the best-fit parameters. Keys are
            amp numbers as strings

        double_gaussian_params : dict
            Best-fit double Gaussian parameters to the dark current
            histogram. Keys are amp numbers as strings. Values are six-
            element lists. (3-elements * 2 Gaussians).
            ``[amplitude1, peak1, stdev1, amplitude2, peak2, stdev2]``
            Each element of the list is a tuple containing the best-fit
            value and associated uncertainty.

        double_gaussian_chi_squared : dict
            Reduced chi-squared for the best-fit parameters. Keys are
            amp numbers as strings

        hist : numpy.ndarray
            1D array of histogram values

        bin_centers : numpy.ndarray
            1D array of bin centers that match the ``hist`` values.
        """

        amp_means = {}
        amp_stdevs = {}
        gaussian_params = {}
        gaussian_chi_squared = {}
        double_gaussian_params = {}
        double_gaussian_chi_squared = {}

        # Add full image coords to the list of amp_boundaries, so that full
        # frame stats are also calculated.
        if 'FULL' in self.aperture:
            maxx = 0
            maxy = 0
            for amp in amps:
                mxx = amps[amp][0][1]
                mxy = amps[amp][1][1]
                if mxx > maxx:
                    maxx = copy(mxx)
                if mxy > maxy:
                    maxy = copy(mxy)
            amps['5'] = [(0, maxx, 1), (0, maxy, 1)]
            logging.info((
                '\tFull frame exposure detected. Adding the full frame to the list '
                'of amplifiers upon which to calculate statistics.'))

        for key in amps:
            x_start, x_end, x_step = amps[key][0]
            y_start, y_end, y_step = amps[key][1]
            indexes = np.mgrid[y_start:y_end:y_step, x_start:x_end:x_step]

            # Basic statistics, sigma clipped areal mean and stdev
            amp_mean, amp_stdev = calculations.mean_stdev(image[indexes[0],
                                                                indexes[1]])
            amp_means[key] = amp_mean
            amp_stdevs[key] = amp_stdev

            # Create a histogram
            lower_bound = (amp_mean - 7 * amp_stdev)
            upper_bound = (amp_mean + 7 * amp_stdev)

            hist, bin_edges = np.histogram(image[indexes[0], indexes[1]],
                                           bins='auto',
                                           range=(lower_bound, upper_bound))
            bin_centers = (bin_edges[1:] + bin_edges[0:-1]) / 2.
            initial_params = [np.max(hist), amp_mean, amp_stdev]

            # Fit a Gaussian to the histogram. Save best-fit params and
            # uncertainties, as well as reduced chi squared
            amplitude, peak, width = calculations.gaussian1d_fit(
                bin_centers, hist, initial_params)
            gaussian_params[key] = [amplitude, peak, width]

            gauss_fit_model = models.Gaussian1D(amplitude=amplitude[0],
                                                mean=peak[0],
                                                stddev=width[0])
            gauss_fit = gauss_fit_model(bin_centers)

            positive = hist > 0
            degrees_of_freedom = len(hist) - 3.
            total_pix = np.sum(hist[positive])
            p_i = gauss_fit[positive] / total_pix
            gaussian_chi_squared[key] = (np.sum(
                (hist[positive] - (total_pix * p_i)**2) / (total_pix * p_i)) /
                                         degrees_of_freedom)

            # Double Gaussian fit only for full frame data (and only for
            # NIRISS, NIRCam at the moment.)
            if key == '5':
                if self.instrument.upper() in ['NIRISS', 'NIRCAM']:
                    initial_params = (np.max(hist), amp_mean, amp_stdev * 0.8,
                                      np.max(hist) / 7., amp_mean / 2.,
                                      amp_stdev * 0.9)
                    double_gauss_params, double_gauss_sigma = calculations.double_gaussian_fit(
                        bin_centers, hist, initial_params)
                    double_gaussian_params[key] = [
                        [param, sig] for param, sig in zip(
                            double_gauss_params, double_gauss_sigma)
                    ]
                    double_gauss_fit = calculations.double_gaussian(
                        bin_centers, *double_gauss_params)
                    degrees_of_freedom = len(bin_centers) - 6.
                    dp_i = double_gauss_fit[positive] / total_pix
                    double_gaussian_chi_squared[key] = np.sum(
                        (hist[positive] - (total_pix * dp_i)**2) /
                        (total_pix * dp_i)) / degrees_of_freedom

                else:
                    double_gaussian_params[key] = [[0., 0.] for i in range(6)]
                    double_gaussian_chi_squared[key] = 0.
            else:
                double_gaussian_params[key] = [[0., 0.] for i in range(6)]
                double_gaussian_chi_squared[key] = 0.

        logging.info('\tMean dark rate by amplifier: {}'.format(amp_means))
        logging.info(
            '\tStandard deviation of dark rate by amplifier: {}'.format(
                amp_means))
        logging.info(
            '\tBest-fit Gaussian parameters [amplitude, peak, width]'.format(
                gaussian_params))
        logging.info(
            '\tReduced chi-squared associated with Gaussian fit: {}'.format(
                gaussian_chi_squared))
        logging.info(
            '\tBest-fit double Gaussian parameters [amplitude1, peak1, width1, amplitude2, peak2, '
            'width2]'.format(double_gaussian_params))
        logging.info(
            '\tReduced chi-squared associated with double Gaussian fit: {}'.
            format(double_gaussian_chi_squared))

        return (amp_means, amp_stdevs, gaussian_params, gaussian_chi_squared,
                double_gaussian_params, double_gaussian_chi_squared,
                hist.astype(np.float), bin_centers)