def __parse_config(self, config):
        """Parse the configuration options

        Arguments
        ---------
        config: configparser.SectionProxy
        Parsed options to initialize class

        Raises
        ------
        ExpectedFluxError if iter out prefix is not valid
        """
        self.eta_value = config.get("eta value")
        if self.eta_value is None:
            raise ExpectedFluxError("Missing argument 'eta value' required "
                                    "by Dr16FixEtaExpectedFlux")
        if not (self.eta_value.endswith(".fits")
                or self.eta_value.endswith(".fits.gz")):
            try:
                _ = float(self.eta_value)
            except ValueError as error:
                raise ExpectedFluxError(
                    "Wrong argument 'eta value' passed to "
                    "Dr16FixEtaExpectedFlux. Expected a fits file or "
                    f"a float. Found {self.eta_value}") from error
Exemple #2
0
    def __init__(self, config):
        """Initialize class instance"""
        self.los_ids = {}

        self.iter_out_prefix = None
        self.out_dir = None
        self.num_bins_variance = None
        self.num_processors = None
        self.__parse_config(config)

        # check that Forest class variables are set
        # these are required in order to initialize the arrays
        try:
            Forest.class_variable_check()
        except AstronomicalObjectError as error:
            raise ExpectedFluxError(
                "Forest class variables need to be set "
                "before initializing variables here.") from error

        # initialize wavelength array for variance functions
        self.log_lambda_var_func_grid = None
        self._initialize_variance_wavelength_array()
        # variance functions are initialized by the child classes

        # initialize mean continuum
        self.get_mean_cont = None
        self.get_mean_cont_weight = None
        self._initialize_mean_continuum_arrays()

        # to store the stack of deltas
        self.get_stack_delta = None
        self.get_stack_delta_weights = None
Exemple #3
0
    def __parse_config(self, config):
        """Parse the configuration options

        Arguments
        ---------
        config: configparser.SectionProxy
        Parsed options to initialize class

        Raises
        ------
        ExpectedFluxError if variables are not valid
        """
        self.iter_out_prefix = config.get("iter out prefix")
        if self.iter_out_prefix is None:
            raise ExpectedFluxError(
                "Missing argument 'iter out prefix' required "
                "by ExpectedFlux")
        if "/" in self.iter_out_prefix:
            raise ExpectedFluxError(
                "Error constructing ExpectedFlux. "
                "'iter out prefix' should not incude folders. "
                f"Found: {self.iter_out_prefix}")

        self.num_bins_variance = config.getint("num bins variance")
        if self.num_bins_variance is None:
            raise ExpectedFluxError(
                "Missing argument 'num bins variance' required by ExpectedFlux"
            )

        self.num_processors = config.getint("num processors")
        if self.num_processors is None:
            raise ExpectedFluxError(
                "Missing argument 'num processors' required by ExpectedFlux")
        if self.num_processors == 0:
            self.num_processors = (multiprocessing.cpu_count() // 2)

        self.out_dir = config.get("out dir")
        if self.out_dir is None:
            raise ExpectedFluxError(
                "Missing argument 'out dir' required by ExpectedFlux")
        self.out_dir += "Log/"
Exemple #4
0
    def read_true_continuum_one_healpix(self, forests, healpix=None):
        """Read the forest continuum from one healpix and insert it into

        Arguments
        ---------
        forests: List of Forest
        A list of forest instances where the continuum will be computed

        healpix: int (Optional)
        Healpix number that forests belong to

        Return
        ------
        forests: List of Forest
        The modified forest instances

        Raise
        -----
        ExpectedFluxError if Forest.wave_solution is not 'lin' or 'log'
        """
        if healpix is None:
            healpix = healpy.ang2pix(IN_NSIDE,
                                 np.pi / 2 - forests[0].dec,
                                 forests[0].ra,
                                 nest=True)

        filename_truth = (
            f"{self.input_directory}/{healpix//100}/{healpix}/truth-{IN_NSIDE}-"
            f"{healpix}.fits")
        hdul = fitsio.FITS(filename_truth)
        header = hdul["TRUE_CONT"].read_header()
        lambda_min = header["WMIN"]
        lambda_max = header["WMAX"]
        delta_lambda = header["DWAVE"]
        lambda_ = np.arange(lambda_min, lambda_max + delta_lambda, delta_lambda)
        true_cont = hdul["TRUE_CONT"].read()
        for forest in forests:
            indx = np.nonzero(true_cont["TARGETID"] == forest.targetid)[0]
            if indx.size == 0:
                raise ExpectedFluxError("Forest target id was not found in "
                    "the truth file.")
            indx = indx[0]

            # Should we also check for healpix consistency here?
            true_continuum = interp1d(lambda_, true_cont["TRUE_CONT"][indx])

            forest.continuum = true_continuum(10**forest.log_lambda)
            forest.continuum *= self.get_mean_flux(forest.log_lambda)

        hdul.close()
        return forests
Exemple #5
0
    def compute_forest_variance(self, forest, continuum):  # pylint: disable=no-self-use
        """Compute the forest variance

        Arguments
        ---------
        forest: Forest
        A forest instance where the variance will be computed

        continuum: array of float
        Quasar continuum associated with the forest

        Raise
        -----
        MeanExpectedFluxError if function was not overloaded by child class
        """
        raise ExpectedFluxError("Function 'compute_forest_variance' was not "
                                "overloaded by child class")
Exemple #6
0
    def compute_expected_flux(self, forests):  # pylint: disable=no-self-use
        """Compute the mean expected flux of the forests.
        This includes the quasar continua and the mean transimission. It is
        computed iteratively following as explained in du Mas des Bourboux et
        al. (2020)

        Arguments
        ---------
        forests: List of Forest
        A list of Forest from which to compute the deltas.

        Raise
        -----
        MeanExpectedFluxError if function was not overloaded by child class
        """
        raise ExpectedFluxError("Function 'compute_expected_flux' was not "
                                "overloaded by child class")
Exemple #7
0
    def __parse_config(self, config):
        """Parse the configuration options

        Arguments
        ---------
        config: configparser.SectionProxy
        Parsed options to initialize class

        Raises
        ------
        ExpectedFluxError if variables are not valid
        """
        self.input_directory = config.get("input directory")
        if self.input_directory is None:
            raise ExpectedFluxError(
                "Missing argument 'input directory' required "
                "by TrueContinuum")

        self.use_constant_weight = config.getboolean("use constant weight")
        self.raw_statistics_filename = config.get("raw statistics file")
Exemple #8
0
    def __parse_config(self, config):
        """Parse the configuration options

        Arguments
        ---------
        config: configparser.SectionProxy
        Parsed options to initialize class

        Raises
        ------
        ExpectedFluxError if variables are not valid
        """
        self.force_stack_delta_to_zero = config.getboolean(
            "force stack delta to zero")
        if self.force_stack_delta_to_zero is None:
            raise ExpectedFluxError(
                "Missing argument 'force stack delta to zero' required by Dr16ExpectedFlux"
            )

        limit_eta_string = config.get("limit eta")
        if limit_eta_string is None:
            raise ExpectedFluxError(
                "Missing argument 'limit eta' required by Dr16ExpectedFlux")
        limit_eta = limit_eta_string.split(",")
        if limit_eta[0].startswith("(") or limit_eta[0].startswith("["):
            eta_min = float(limit_eta[0][1:])
        else:
            eta_min = float(limit_eta[0])
        if limit_eta[1].endswith(")") or limit_eta[1].endswith("]"):
            eta_max = float(limit_eta[1][:-1])
        else:
            eta_max = float(limit_eta[1])
        self.limit_eta = (eta_min, eta_max)

        limit_var_lss_string = config.get("limit var lss")
        if limit_var_lss_string is None:
            raise ExpectedFluxError(
                "Missing argument 'limit var lss' required by Dr16ExpectedFlux"
            )
        limit_var_lss = limit_var_lss_string.split(",")
        if limit_var_lss[0].startswith("(") or limit_var_lss[0].startswith(
                "["):
            var_lss_min = float(limit_var_lss[0][1:])
        else:
            var_lss_min = float(limit_var_lss[0])
        if limit_var_lss[1].endswith(")") or limit_var_lss[1].endswith("]"):
            var_lss_max = float(limit_var_lss[1][:-1])
        else:
            var_lss_max = float(limit_var_lss[1])
        self.limit_var_lss = (var_lss_min, var_lss_max)

        self.min_num_qso_in_fit = config.getint("min num qso in fit")
        if self.min_num_qso_in_fit is None:
            raise ExpectedFluxError(
                "Missing argument 'min qso in fit' required by Dr16ExpectedFlux"
            )

        self.num_iterations = config.getint("num iterations")
        if self.num_iterations is None:
            raise ExpectedFluxError(
                "Missing argument 'num iterations' required by Dr16ExpectedFlux"
            )

        self.order = config.getint("order")
        if self.order is None:
            raise ExpectedFluxError(
                "Missing argument 'order' required by Dr16ExpectedFlux")

        self.use_constant_weight = config.getboolean("use constant weight")
        if self.use_constant_weight is None:
            raise ExpectedFluxError(
                "Missing argument 'use constant weight' required by Dr16ExpectedFlux"
            )
        if self.use_constant_weight:
            self.logger.warning(
                "Deprecation Warning: option 'use constant weight' is now deprecated "
                "and will be removed in future versions. Consider using class "
                "Dr16FixedEtaVarlssFudgeExpectedFlux with options 'eta = 0', "
                "'var lss = 1' and 'fudge = 0'")
            # if use_ivar_as_weight is set, we fix eta=1, var_lss=0 and fudge=0
            # if use_constant_weight is set, we fix eta=0, var_lss=1, and fudge=0

        self.use_ivar_as_weight = config.getboolean("use ivar as weight")
        if self.use_ivar_as_weight is None:
            raise ExpectedFluxError(
                "Missing argument 'use ivar as weight' required by Dr16ExpectedFlux"
            )
        if self.use_ivar_as_weight:
            self.logger.warning(
                "Deprecation Warning: option 'use ivar as weight' is now deprecated "
                "and will be removed in future versions. Consider using class "
                "Dr16FixedEtaVarlssFudgeExpectedFlux with options 'eta = 1', "
                "'var lss = 0' and 'fudge = 0'")
Exemple #9
0
    def read_raw_statistics(self):
        """Read the LSS delta variance and mean transmitted flux from files
        written by the raw analysis
        """
        # files are only for lya so far, this will need to be updated so that
        # regions other than Lya are available

        if self.raw_statistics_filename != "":
            filename = self.raw_statistics_filename
        else:
            filename = resource_filename(
                'picca', 'delta_extraction') + '/expected_fluxes/raw_stats/'
            if Forest.wave_solution == "log":
                filename += 'colore_v9_lya_log.fits.gz'
            elif Forest.wave_solution == "lin" and np.isclose(
                    10**Forest.log_lambda_grid[1] -
                    10**Forest.log_lambda_grid[0],
                    2.4,
                    rtol=0.1):
                filename += 'colore_v9_lya_lin_2.4.fits.gz'
            elif Forest.wave_solution == "lin" and np.isclose(
                    10**Forest.log_lambda_grid[1] -
                    10**Forest.log_lambda_grid[0],
                    3.2,
                    rtol=0.1):
                filename += 'colore_v9_lya_lin_3.2.fits.gz'
            else:
                raise ExpectedFluxError(
                    "Couldn't find compatible raw satistics file. Provide a "
                    "custom one using 'raw statistics file' field.")
        self.logger.info(
            f'Reading raw statistics var_lss and mean_flux from file: {filename}'
        )

        try:
            hdul = fitsio.FITS(filename)
        except IOError as error:
            raise ExpectedFluxError(
                f"raw statistics file {filename} couldn't be loaded") from error

        header = hdul[1].read_header()
        if Forest.wave_solution == "log":
            pixel_step = Forest.log_lambda_grid[1] - Forest.log_lambda_grid[0]
            log_lambda_min = Forest.log_lambda_grid[0]
            log_lambda_max = Forest.log_lambda_grid[-1] - pixel_step / 2
            log_lambda_rest_min = Forest.log_lambda_rest_frame_grid[
                0] - pixel_step / 2
            log_lambda_rest_max = Forest.log_lambda_rest_frame_grid[-1]
            if (header['LINEAR'] or not np.isclose(
                    header['L_MIN'], 10**log_lambda_min, rtol=1e-3) or
                    not np.isclose(
                        header['L_MAX'], 10**log_lambda_max, rtol=1e-3) or
                    not np.isclose(
                        header['LR_MIN'], 10**log_lambda_rest_min, rtol=1e-3) or
                    not np.isclose(
                        header['LR_MAX'], 10**log_lambda_rest_max, rtol=1e-3) or
                    not np.isclose(header['DEL_LL'], pixel_step, rtol=1e-3)):
                raise ExpectedFluxError(
                    "raw statistics file pixelization scheme does not match "
                    "input pixelization scheme. "
                    "\t\tL_MIN\tL_MAX\tLR_MIN\tLR_MAX\tDEL_LL"
                    f"raw\t{header['L_MIN']}\t{header['L_MAX']}\t"
                    f"{header['LR_MIN']}\t{header['LR_MAX']}\t{header['DEL_LL']}"
                    f"input\t{log_lambda_min}\t{log_lambda_max}\t"
                    f"{log_lambda_rest_min}\t{log_lambda_rest_max}"
                    "provide a custom file in 'raw statistics file' field "
                    "matching input pixelization scheme")
            log_lambda = hdul[1]['LAMBDA'][:]
        elif Forest.wave_solution == "lin":
            pixel_step = 10**Forest.log_lambda_grid[
                1] - 10**Forest.log_lambda_grid[0]
            lambda_min = 10**Forest.log_lambda_grid[0]
            lambda_max = 10**Forest.log_lambda_grid[-1] - pixel_step / 2
            lambda_rest_min = 10**Forest.log_lambda_rest_frame_grid[
                0] - pixel_step / 2
            lambda_rest_max = 10**Forest.log_lambda_rest_frame_grid[-1]
            if (not header['LINEAR'] or
                    not np.isclose(header['L_MIN'], lambda_min, rtol=1e-3) or
                    not np.isclose(header['L_MAX'], lambda_max, rtol=1e-3) or
                    not np.isclose(header['LR_MIN'], lambda_rest_min, rtol=1e-3)
                    or
                    not np.isclose(header['LR_MAX'], lambda_rest_max, rtol=1e-3)
                    or not np.isclose(header['DEL_L'],
                                      10**Forest.log_lambda_grid[1] -
                                      10**Forest.log_lambda_grid[0],
                                      rtol=1e-3)):
                raise ExpectedFluxError(
                    "raw statistics file pixelization scheme does not match "
                    "input pixelization scheme. "
                    "\t\tL_MIN\tL_MAX\tLR_MIN\tLR_MAX\tDEL_L"
                    f"raw\t{header['L_MIN']}\t{header['L_MAX']}\t"
                    f"{header['LR_MIN']}\t{header['LR_MAX']}\t{header['DEL_L']}"
                    f"input\t{lambda_min}\t{lambda_max}\t{lambda_rest_min}\t"
                    f"{lambda_rest_max} provide a custom file in 'raw "
                    "statistics file' field matching input pixelization scheme")
            log_lambda = np.log10(hdul[1]['LAMBDA'][:])

        flux_variance = hdul[1]['VAR'][:]
        mean_flux = hdul[1]['MEANFLUX'][:]
        hdul.close()

        var_lss = flux_variance / mean_flux**2

        self.get_var_lss = interp1d(log_lambda,
                                    var_lss,
                                    fill_value='extrapolate',
                                    kind='nearest')

        self.get_mean_flux = interp1d(log_lambda,
                                      mean_flux,
                                      fill_value='extrapolate',
                                      kind='nearest')