Beispiel #1
0
 def class_variable_check(cls):
     """Check that class variables have been correctly initialized"""
     if cls.log_lambda_grid.size == 0:  # is None:
         raise AstronomicalObjectError(
             "Error constructing Forest. Class variable 'log_lambda_grid' "
             "must be set prior to initialize instances of this type. This "
             "probably means you did not run Forest.set_class_variables")
     if cls.log_lambda_rest_frame_grid.size == 0:  # is None:
         raise AstronomicalObjectError(
             "Error constructing Forest. Class variable "
             "'log_lambda_rest_frame_grid' must be set prior to initialize "
             "instances of this type. This probably means you did not run "
             "Forest.set_class_variables")
     if len(cls.mask_fields) == 0:  #cls.mask_fields is None:
         raise AstronomicalObjectError(
             "Error constructing Forest. Class variable "
             "'mask_fields' must be set prior to initialize "
             "instances of this type. This probably means you did not run "
             "Forest.set_class_variables")
     if not isinstance(cls.mask_fields, list):
         raise AstronomicalObjectError(
             "Error constructing Forest. "
             "Expected list in class variable 'mask fields'. "
             f"Found '{cls.mask_fields}'.")
     if cls.wave_solution is None:
         raise AstronomicalObjectError(
             "Error constructing Forest. Class variable 'wave_solution' "
             "must be set prior to initialize instances of this type. This "
             "probably means you did not run Forest.set_class_variables")
Beispiel #2
0
 def consistency_check(self):
     """Consistency checks after __init__"""
     if self.flux.size != self.ivar.size:
         raise AstronomicalObjectError("Error constructing Forest. 'flux' "
                                       "and 'ivar' don't have the same size")
     if self.log_lambda.size != self.flux.size:
         raise AstronomicalObjectError("Error constructing Forest. "
                                       "'flux' and 'log_lambda' don't "
                                       "have the same size")
Beispiel #3
0
    def __init__(self, **kwargs):
        """Initialize instance

        Arguments
        ---------
        **kwargs: dict
        Dictionary contiaing the information

        Raise
        -----
        AstronomicalObjectError if there are missing variables
        """
        self.logger = logging.getLogger(__name__)

        Forest.class_variable_check()

        self.log_lambda = kwargs.get("log_lambda")
        if self.log_lambda is None:
            raise AstronomicalObjectError("Error constructing Forest. "
                                          "Missing variable 'log_lambda'")
        del kwargs["log_lambda"]

        self.bad_continuum_reason = None
        self.continuum = kwargs.get("continuum")
        if kwargs.get("continuum") is not None:
            del kwargs["continuum"]

        self.deltas = kwargs.get("deltas")
        if kwargs.get("deltas") is not None:
            del kwargs["deltas"]

        self.flux = kwargs.get("flux")
        if self.flux is None:
            raise AstronomicalObjectError("Error constructing Forest. "
                                          "Missing variable 'flux'")
        del kwargs["flux"]

        self.ivar = kwargs.get("ivar")
        if self.ivar is None:
            raise AstronomicalObjectError("Error constructing Forest. "
                                          "Missing variable 'ivar'")
        del kwargs["ivar"]

        self.transmission_correction = np.ones_like(self.flux)

        self.weights = kwargs.get("weights")
        if kwargs.get("weights") is not None:
            del kwargs["weights"]

        # call parent constructor
        super().__init__(**kwargs)

        self.consistency_check()

        # compute mean quality variables
        snr = self.flux * np.sqrt(self.ivar)
        self.mean_snr = np.mean(snr)
Beispiel #4
0
    def coadd(self, other):
        """Coadd the information of another forest.

        Extends the coadd method of Forest to also include information
        about the exposures_diff and reso arrays

        Arguments
        ---------
        other: Pk1dForest
        The forest instance to be coadded.

        Raise
        -----
        AstronomicalObjectError if other is not a Pk1dForest instance
        """
        if not isinstance(other, Pk1dForest):
            raise AstronomicalObjectError(
                "Error coadding Pk1dForest. Expected "
                "Pk1dForest instance in other. Found: "
                f"{type(other).__name__}")
        self.exposures_diff = np.append(self.exposures_diff,
                                        other.exposures_diff)
        self.reso = np.append(self.reso, other.reso)
        self.reso_pix = np.append(self.reso_pix, other.reso_pix)
        # coadd the deltas by rebinning
        super().coadd(other)
Beispiel #5
0
    def get_header(self):
        """Return line-of-sight data to be saved as a fits file header

        Adds to specific Forest keys to general header (defined in class
        AstronomicalObject)

        Return
        ------
        header : list of dict
        A list of dictionaries containing 'name', 'value' and 'comment' fields
        """
        header = super().get_header()
        header += [
            {
                'name': 'MEANSNR',
                'value': self.mean_snr,
                'comment': 'Mean SNR'
            },
            {
                'name': 'BLINDING',
                'value': Forest.blinding,
                'comment': "String specifying the blinding strategy"
            },
            {
                'name': 'WAVE_SOLUTION',
                'value': Forest.wave_solution,
                'comment': "Chosen wavelength solution (linnear or logarithmic)"
            },
        ]

        if Forest.wave_solution == "log":
            header += [
                {
                    'name':
                        'DELTA_LOG_LAMBDA',
                    'value':
                        Forest.log_lambda_grid[1] - Forest.log_lambda_grid[0],
                    'comment':
                        "Pixel step in log lambda [log(Angstrom)]"
                },
            ]
        elif Forest.wave_solution == "lin":
            header += [
                {
                    'name':
                        'DELTA_LAMBDA',
                    'value':
                        10**Forest.log_lambda_grid[1] -
                        10**Forest.log_lambda_grid[0],
                    'comment':
                        "Pixel step in lambda [Angstrom]"
                },
            ]
        else:
            raise AstronomicalObjectError("Error in Forest.get_header(). "
                                          "Class variable 'wave_solution' "
                                          "must be either 'lin' or 'log'. "
                                          f"Found: '{Forest.wave_solution}'")

        return header
Beispiel #6
0
    def __init__(self, **kwargs):
        """Initialize instance

        Arguments
        ---------
        **kwargs: dict
        Dictionary containing the information

        Raise
        -----
        AstronomicalObjectError if there are missing variables
        """

        self.resolution_matrix = kwargs.get("resolution_matrix")
        #potentially change this in case we ever want log-binning with DESI Pk1d data
        #then would need a check of self.wave_solution
        if self.resolution_matrix is None:
            raise AstronomicalObjectError(
                "Error constructing DesiPk1dForest. "
                "Missing variable 'resolution_matrix'")
        del kwargs["resolution_matrix"]

        # call parent constructors
        super().__init__(**kwargs)
        self.consistency_check()
Beispiel #7
0
    def __init__(self, **kwargs):
        """Initialize instance

        Arguments
        ---------
        **kwargs: dict
        Dictionary contiaing the information

        Raise
        -----
        AstronomicalObjectError if there are missing variables
        """
        Pk1dForest.class_variable_check()

        self.exposures_diff = kwargs.get("exposures_diff")
        if self.exposures_diff is None:
            raise AstronomicalObjectError("Error constructing Pk1dForest. "
                                          "Missing variable 'exposures_diff'")
        del kwargs["exposures_diff"]

        self.reso = kwargs.get("reso")
        if self.reso is None:
            raise AstronomicalObjectError("Error constructing Pk1dForest. "
                                          "Missing variable 'reso'")
        del kwargs["reso"]

        self.reso_pix = kwargs.get("reso_pix")
        if self.reso_pix is None:
            raise AstronomicalObjectError("Error constructing Pk1dForest. "
                                          "Missing variable 'reso_pix'")
        del kwargs["reso_pix"]

        # call parent constructor
        super().__init__(**kwargs)

        # compute mean quality variables
        self.mean_reso = self.reso.mean()
        self.mean_z = (
            (np.power(10., self.log_lambda[len(self.log_lambda) - 1]) +
             np.power(10., self.log_lambda[0])) / 2. /
            Pk1dForest.lambda_abs_igm - 1.0)
        self.mean_reso_pix = self.reso_pix.mean()

        self.consistency_check()
Beispiel #8
0
 def consistency_check(self):
     """Consistency checks after __init__"""
     super().consistency_check()
     if self.resolution_matrix.shape[1] != self.flux.shape[0]:
         raise AstronomicalObjectError(
             "Error constructing DesiPk1dForest. 'resolution_matrix' "
             "and 'flux' don't have the "
             "same size")
     if "resolution_matrix" not in Forest.mask_fields:
         Forest.mask_fields += ["resolution_matrix"]
Beispiel #9
0
    def __init__(self, **kwargs):
        """Initialize instance

        Arguments
        ---------
        **kwargs: dict
        Dictionary contiaing the information

        Raise
        -----
        AstronomicalObjectError if there are missing variables
        """
        if kwargs.get("fiberid") is None:
            raise AstronomicalObjectError("Error constructing SdssForest. "
                                          "Missing variable 'fiberid'")
        self.fiberid = [kwargs.get("fiberid")]
        del kwargs["fiberid"]

        if kwargs.get("mjd") is None:
            raise AstronomicalObjectError("Error constructing SdssForest. "
                                          "Missing variable 'mjd'")
        self.mjd = [kwargs.get("mjd")]
        del kwargs["mjd"]

        if kwargs.get("plate") is None:
            raise AstronomicalObjectError("Error constructing SdssForest. "
                                          "Missing variable 'plate'")
        self.plate = [kwargs.get("plate")]
        del kwargs["plate"]

        self.thingid = kwargs.get("thingid")
        if self.thingid is None:
            raise AstronomicalObjectError("Error constructing SdssForest. "
                                          "Missing variable 'thingid'")
        del kwargs["thingid"]

        # call parent constructor
        kwargs["los_id"] = self.thingid
        super().__init__(**kwargs)
Beispiel #10
0
    def set_class_variables(cls, lambda_min, lambda_max, lambda_min_rest_frame,
                            lambda_max_rest_frame, pixel_step,
                            pixel_step_rest_frame, wave_solution):
        """Set class variables

        Arguments
        ---------
        lambda_min: float
        Logarithm of the minimum wavelength (in Angs) to be considered in a forest.

        lambda_max: float
        Logarithm of the maximum wavelength (in Angs) to be considered in a forest.

        lambda_min_rest_frame: float or None
        As lambda_min but for rest-frame wavelength.

        lambda_max_rest_frame: float
        As lambda_max but for rest-frame wavelength.

        pixel_step: float
        Wavelength cahnge between two pixels. If pixel_step is "log" this is in
        units of the logarithm of the wavelength (in Angs). If pixel_step is "lin"
        this is in units of the wavelength (in Angs).

        wave_solution: "log" or "lin"
        Specifies whether we want to construct a wavelength grid that is evenly
        spaced on wavelength (lin) or on the logarithm of the wavelength (log)
        """
        if wave_solution == "log":
            cls.log_lambda_grid = np.arange(
                np.log10(lambda_min),
                np.log10(lambda_max) + pixel_step / 2, pixel_step)
            cls.log_lambda_rest_frame_grid = np.arange(
                np.log10(lambda_min_rest_frame) + pixel_step_rest_frame / 2,
                np.log10(lambda_max_rest_frame), pixel_step_rest_frame)
        elif wave_solution == "lin":
            cls.log_lambda_grid = np.log10(
                np.arange(lambda_min, lambda_max + pixel_step / 2, pixel_step))
            cls.log_lambda_rest_frame_grid = np.log10(
                np.arange(lambda_min_rest_frame + pixel_step_rest_frame / 2,
                          lambda_max_rest_frame, pixel_step_rest_frame))
        else:
            raise AstronomicalObjectError("Error in setting Forest class "
                                          "variables. 'wave_solution' "
                                          "must be either 'lin' or 'log'. "
                                          f"Found: {wave_solution}")

        cls.wave_solution = wave_solution

        cls.mask_fields = defaults.get("mask fields").copy()
Beispiel #11
0
 def consistency_check(self):
     """Consistency checks after __init__"""
     super().consistency_check()
     if self.flux.size != self.exposures_diff.size:
         raise AstronomicalObjectError(
             "Error constructing Pk1dForest. 'flux' "
             "and 'exposures_diff' don't have the "
             "same size")
     if "exposures_diff" not in Forest.mask_fields:
         Forest.mask_fields += ["exposures_diff"]
     if "reso" not in Forest.mask_fields:
         Forest.mask_fields += ["reso"]
     if "reso_pix" not in Forest.mask_fields:
         Forest.mask_fields += ["reso_pix"]
Beispiel #12
0
    def __init__(self, **kwargs):
        """Initialize instance

        Arguments
        ---------
        **kwargs: dict
        Dictionary contiaing the information

        Raise
        -----
        AstronomicalObjectError if there are missing variables
        """
        self.dec = kwargs.get("dec")
        if self.dec is None:
            raise AstronomicalObjectError(
                "Error constructing AstronomicalObject. "
                "Missing variable 'dec'")

        self.los_id = kwargs.get("los_id")
        if self.los_id is None:
            raise AstronomicalObjectError(
                "Error constructing AstronomicalObject. "
                "Missing variable 'los_id'")

        self.ra = kwargs.get("ra")
        if self.ra is None:
            raise AstronomicalObjectError(
                "Error constructing AstronomicalObject. "
                "Missing variable 'ra'")

        self.z = kwargs.get("z")
        if self.z is None:
            raise AstronomicalObjectError(
                "Error constructing AstronomicalObject. "
                "Missing variable 'z'")

        self.healpix = healpy.ang2pix(16, np.pi / 2 - self.dec, self.ra)
Beispiel #13
0
    def coadd(self, other):
        """Coadd the information of another forest.

        Forests are coadded by rebinning

        Arguments
        ---------
        other: Forest
        The forest instance to be coadded.

        Raise
        -----
        AstronomicalObjectError if other is not an instance of Forest
        AstronomicalObjectError if other has a different los_id
        AstronomicalObjectError if Forest.wave_solution is not 'lin' or 'log'
        """
        if not isinstance(other, Forest):
            raise AstronomicalObjectError("Error coadding Forest. Expected "
                                          "Forest instance in other. Found: "
                                          f"{type(other).__name__}")

        if self.los_id != other.los_id:
            raise AstronomicalObjectError(
                "Attempting to coadd two Forests "
                "with different los_id. This should "
                f"not happen. this.los_id={self.los_id}, "
                f"other.los_id={other.los_id}.")

        self.log_lambda = np.append(self.log_lambda, other.log_lambda)
        self.flux = np.append(self.flux, other.flux)
        self.ivar = np.append(self.ivar, other.ivar)
        self.transmission_correction = np.append(self.transmission_correction,
                                                 other.transmission_correction)

        # coadd the deltas by rebinning
        self.rebin()
Beispiel #14
0
    def coadd(self, other):
        """Coadd the information of another forest.

        Forests are coadded by calling the coadd function from Forest.
        SDSS fiberid, mjd and plate from other are added to the current list

        Arguments
        ---------
        other: Forest
        The forest instance to be coadded.

        Raise
        -----
        AstronomicalObjectError if other is not a DesiForest instance
        """
        if not isinstance(other, SdssForest):
            raise AstronomicalObjectError("Error coadding SdssForest. Expected "
                                          "SdssForest instance in other. Found: "
                                          f"{type(other).__name__}")

        self.fiberid += other.fiberid
        self.mjd += other.mjd
        self.plate += other.plate
        super().coadd(other)
Beispiel #15
0
    def coadd(self, other):
        """Coadd the information of another forest.

        Forests are coadded by calling the coadd function from Forest.
        DESI night, petal and night from other are added to the current list

        Arguments
        ---------
        other: DesiForest
        The forest instance to be coadded.

        Raise
        -----
        AstronomicalObjectError if other is not a DesiForest instance
        """
        if not isinstance(other, DesiForest):
            raise AstronomicalObjectError(
                "Error coadding DesiForest. Expected "
                "DesiForest instance in other. Found: "
                f"{type(other).__name__}")
        self.night += other.night
        self.petal += other.petal
        self.tile += other.tile
        super().coadd(other)
Beispiel #16
0
    def __init__(self, **kwargs):
        """Initialize instance

        Arguments
        ---------
        **kwargs: dict
        Dictionary contiaing the information

        Raise
        -----
        AstronomicalObjectError if there are missing variables
        """
        self.night = []
        if kwargs.get("night") is not None:
            self.night.append(kwargs.get("night"))
            del kwargs["night"]

        self.petal = []
        if kwargs.get("petal") is not None:
            self.petal.append(kwargs.get("petal"))
            del kwargs["petal"]

        self.targetid = kwargs.get("targetid")
        if self.targetid is None:
            raise AstronomicalObjectError("Error constructing DesiForest. "
                                          "Missing variable 'targetid'")
        del kwargs["targetid"]

        self.tile = []
        if kwargs.get("tile") is not None:
            self.tile.append(kwargs.get("tile"))
            del kwargs["tile"]

        # call parent constructor
        kwargs["los_id"] = self.targetid
        super().__init__(**kwargs)
Beispiel #17
0
    def coadd(self, other):
        """Coadd the information of another forest.

        Extends the coadd method of Forest to also include information
        about the exposures_diff and reso arrays

        Arguments
        ---------
        other: Pk1dForest
        The forest instance to be coadded.

        Raise
        -----
        AstronomicalObjectError if other is not a DesiPk1dForest instance
        """
        if not isinstance(other, DesiPk1dForest):
            raise AstronomicalObjectError(
                "Error coadding DesiPk1dForest. Expected "
                "DesiPk1dForest instance in other. Found: "
                f"{type(other).__name__}")

        if other.resolution_matrix.size > 0 and self.resolution_matrix.size > 0:
            if self.resolution_matrix.shape[
                    0] != other.resolution_matrix.shape[0]:
                largershape = np.max([
                    self.resolution_matrix.shape[0],
                    other.resolution_matrix.shape[0]
                ])
                smallershape = np.min([
                    self.resolution_matrix.shape[0],
                    other.resolution_matrix.shape[0]
                ])
                shapediff = largershape - smallershape
                if self.resolution_matrix.shape[0] == smallershape:
                    self.resolution_matrix = np.append(np.zeros(
                        [shapediff // 2, self.resolution_matrix.shape[1]]),
                                                       self.resolution_matrix,
                                                       axis=0)
                    self.resolution_matrix = np.append(
                        self.resolution_matrix,
                        np.zeros(
                            [shapediff // 2, self.resolution_matrix.shape[1]]),
                        axis=0)
                if other.resolution_matrix.shape[0] == smallershape:
                    other.resolution_matrix = np.append(
                        np.zeros(
                            [shapediff // 2,
                             other.resolution_matrix.shape[1]]),
                        other.resolution_matrix,
                        axis=0)
                    other.resolution_matrix = np.append(
                        other.resolution_matrix,
                        np.zeros(
                            [shapediff // 2,
                             other.resolution_matrix.shape[1]]),
                        axis=0)

            self.resolution_matrix = np.append(self.resolution_matrix,
                                               other.resolution_matrix,
                                               axis=1)
        elif self.resolution_matrix.size == 0:
            self.resolution_matrix = other.resolution_matrix

        # coadd the deltas by rebinning
        super().coadd(other)
Beispiel #18
0
 def class_variable_check(cls):
     """Check that class variables have been correctly initialized"""
     if cls.lambda_abs_igm is None:
         raise AstronomicalObjectError(
             "Error constructing Pk1dForest. Class variable 'lambda_abs_igm' "
             "must be set prior to initialize instances of this type")
Beispiel #19
0
def rebin(log_lambda, flux, ivar, transmission_correction, z, wave_solution,
          log_lambda_grid, log_lambda_rest_frame_grid):
    """Rebin the arrays and update control variables
    Rebinned arrays are flux, ivar, lambda_ or log_lambda, and
    transmission_correction. Control variables are mean_snr

    Arguments
    ---------
    log_lambda: array of float
    Logarithm of the wavelength (in Angstroms). Differs from log_lambda_grid
    as the particular instance might not have full wavelength coverage or
    might have some missing pixels (because they are masked)

    flux: array of float
    Flux

    ivar: array of float
    Inverse variance

    transmission_correction: array of float
    Transmission correction.

    z: float
    Quasar redshift

    wave_solution: "lin" or "log"
    Determines whether the wavelength solution has linear spacing ("lin") or
    logarithmic spacing ("log").

    log_lambda_grid: array of float or None
    Common grid in log_lambda based on the specified minimum and maximum
    wavelengths, and pixelisation.

    log_lambda_rest_frame_grid: array of float or None
    Same as log_lambda_grid but for rest-frame wavelengths.

    Return
    ------
    log_lambda: array of float
    Rebinned version of input log_lambda

    flux: array of float
    Rebinned version of input flux

    ivar: array of float
    Rebinned version of input ivar

    transmission_correction: array of float
    Rebinned version of input transmission_correction

    mean_snr: float
    Mean signal-to-noise of the forest

    bins: array of float
    Binning solution to be used for the rebinning

    rebin_ivar: array of float
    Rebinned version of ivar

    orig_ivar: array of float
    Original version of ivar (before applying the function)

    w1: array of bool
    Masking array for the bins solution

    w2: array of bool
    Masking array for the rebinned ivar solution

    Raise
    -----
    AstronomicalObjectError if Forest.wave_solution is not 'lin' or 'log'
    AstronomicalObjectError if ivar only has zeros
    """
    orig_ivar = ivar.copy()
    w1 = np.ones(log_lambda.size, dtype=bool_)
    pixel_step = np.nan

    # compute bins
    if wave_solution == "log":
        pixel_step = log_lambda_grid[1] - log_lambda_grid[0]
        half_pixel_step = pixel_step / 2.

        half_pixel_step_rest_frame = (log_lambda_rest_frame_grid[1] -
                                      log_lambda_rest_frame_grid[0]) / 2.

        w1 &= log_lambda >= log_lambda_grid[0] - half_pixel_step
        w1 &= log_lambda < log_lambda_grid[-1] + half_pixel_step
        w1 &= (log_lambda - np.log10(1. + z) >=
               log_lambda_rest_frame_grid[0] - half_pixel_step_rest_frame)
        w1 &= (log_lambda - np.log10(1. + z) <
               log_lambda_rest_frame_grid[-1] + half_pixel_step_rest_frame)
        w1 &= (ivar > 0.)

    elif wave_solution == "lin":
        pixel_step = 10**log_lambda_grid[1] - 10**log_lambda_grid[0]
        half_pixel_step = pixel_step / 2.

        half_pixel_step_rest_frame = (10**log_lambda_rest_frame_grid[1] -
                                      10**log_lambda_rest_frame_grid[0]) / 2.
        lambda_ = 10**log_lambda
        w1 &= (lambda_ >= 10**log_lambda_grid[0] - half_pixel_step)
        w1 &= (lambda_ < 10**log_lambda_grid[-1] + half_pixel_step)
        w1 &= (lambda_ / (1. + z) >=
               10**log_lambda_rest_frame_grid[0] - half_pixel_step_rest_frame)
        w1 &= (lambda_ / (1. + z) <
               10**log_lambda_rest_frame_grid[-1] + half_pixel_step_rest_frame)
        w1 &= (ivar > 0.)
    else:
        raise AstronomicalObjectError("Error in Forest.rebin(). "
                                      "Class variable 'wave_solution' "
                                      "must be either 'lin' or 'log'.")

    log_lambda = log_lambda[w1]
    flux = flux[w1]
    ivar = ivar[w1]
    transmission_correction = transmission_correction[w1]
    if w1.sum() == 0:
        log_lambda = np.zeros(log_lambda.size)
        flux = np.zeros(log_lambda.size)
        ivar = np.zeros(log_lambda.size)
        transmission_correction = np.zeros(log_lambda.size)
        mean_snr = 0.0
        bins = np.zeros(log_lambda.size, dtype=np.int64)
        rebin_ivar = np.zeros(log_lambda.size)
        w1 = np.zeros(log_lambda.size, dtype=bool_)
        w2 = np.zeros(log_lambda.size, dtype=bool_)
        return (log_lambda, flux, ivar, transmission_correction, mean_snr, bins,
                rebin_ivar, orig_ivar, w1, w2)

    bins = find_bins(log_lambda, log_lambda_grid, wave_solution)
    log_lambda = log_lambda_grid[0] + bins * pixel_step

    # rebin flux, ivar and transmission_correction
    rebin_flux = np.zeros(bins.max() + 1)
    rebin_transmission_correction = np.zeros(bins.max() + 1)
    rebin_ivar = np.zeros(bins.max() + 1)
    rebin_flux_aux = np.bincount(bins, weights=ivar * flux)
    rebin_transmission_correction_aux = np.bincount(
        bins, weights=(ivar * transmission_correction))
    rebin_ivar_aux = np.bincount(bins, weights=ivar)
    rebin_flux[:len(rebin_flux_aux)] += rebin_flux_aux
    rebin_transmission_correction[:len(rebin_transmission_correction_aux
                                      )] += rebin_transmission_correction_aux
    rebin_ivar[:len(rebin_ivar_aux)] += rebin_ivar_aux

    # this condition should always be non-zero for at least one pixel
    # this does not mean that all rebin_ivar pixels will be non-zero,
    # as we could have a masked region of the spectra
    w2 = (rebin_ivar > 0.)
    flux = rebin_flux[w2] / rebin_ivar[w2]
    transmission_correction = rebin_transmission_correction[w2] / rebin_ivar[w2]
    ivar = rebin_ivar[w2]

    # then rebin wavelength
    if wave_solution == "log":
        rebin_log_lambda = (log_lambda_grid[0] +
                            np.arange(bins.max() + 1) * pixel_step)
        log_lambda = rebin_log_lambda[w2]
    else:  # we have already checked that it will always be "lin" at this point
        rebin_lambda = (10**log_lambda_grid[0] +
                        np.arange(bins.max() + 1) * pixel_step)
        log_lambda = np.log10(rebin_lambda[w2])

    # finally update control variables
    snr = flux * np.sqrt(ivar)
    mean_snr = np.sum(snr) / float(snr.size)

    # return weights and binning solution to be used by child classes if
    # required
    return (log_lambda, flux, ivar, transmission_correction, mean_snr, bins,
            rebin_ivar, orig_ivar, w1, w2)
Beispiel #20
0
    def get_data(self):
        """Get the data to be saved in a fits file.

        Data contains lambda_ or log_lambda depending on whether
        wave_solution is "lin" or "log"
        Data also contains the delta field, the weights and the quasar
        continuum.

        Return
        ------
        cols: list of arrays
        Data of the different variables

        names: list of str
        Names of the different variables

        units: list of str
        Units of the different variables

        comments: list of str
        Comments attached to the different variables

        Raise
        -----
        AstronomicalObjectError if Forest.wave_solution is not 'lin' or 'log'
        """
        cols = []
        names = []
        comments = []
        units = []
        if Forest.wave_solution == "log":
            cols += [self.log_lambda]
            names += ["LOGLAM"]
            comments += ["Log lambda"]
            units += ["log Angstrom"]
            array_size = self.log_lambda.size
        elif Forest.wave_solution == "lin":
            cols += [10**self.log_lambda]
            names += ["LAMBDA"]
            comments += ["Lambda"]
            units += ["Angstrom"]
            array_size = self.log_lambda.size
        else:
            raise AstronomicalObjectError("Error in Forest.get_data(). "
                                          "Class variable 'wave_solution' "
                                          "must be either 'lin' or 'log'. "
                                          f"Found: '{Forest.wave_solution}'")

        if self.deltas is None:
            cols += [np.zeros(array_size, dtype=float)]
        else:
            cols += [self.deltas]
        if Forest.blinding == "none":
            names += ["DELTA"]
        else:
            names += ["DELTA_BLIND"]
        comments += ["Delta field"]
        units += [""]

        if self.weights is None:
            cols += [np.zeros(array_size, dtype=float)]
        else:
            cols += [self.weights]
        names += ["WEIGHT"]
        comments += ["Pixel weights"]
        units += [""]

        if self.continuum is None:
            cols += [np.zeros(array_size, dtype=float)]
        else:
            cols += [self.continuum]
        names += ["CONT"]
        comments += ["Quasar continuum. Check input "
                     "spectra for units"]
        units += ["Flux units"]

        return cols, names, units, comments