From 859c49d5336284dc99c5414b8e2a4f6a0c0e3ce2 Mon Sep 17 00:00:00 2001 From: Arthur Loureiro Date: Wed, 13 Dec 2023 18:03:50 +0100 Subject: [PATCH] started smokescreen class --- README.md | 18 +++++++++ src/blinding/__main__.py | 0 src/blinding/smokescreen.py | 76 +++++++++++++++++++++++++++++++++++++ tests/test_smokescreen.py | 47 +++++++++++++++++++++++ 4 files changed, 141 insertions(+) create mode 100644 src/blinding/__main__.py create mode 100644 tests/test_smokescreen.py diff --git a/README.md b/README.md index 5fcff2f..64bcd72 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,24 @@ This repostory (under development) contains the blinding modules for blinding at Other info: the previous README can be found [here](bckp_README.md) +## Data-vector Blinding +### Likelihood Requirements +The blinding module requires the Firecrown likelihoods to be built with certain requirements. First we bust be able to build the likelihoods providing a [sacc](https://github.com/LSSTDESC/sacc/tree/master) object with the measurements for the data-vector: +```python +def build_likelihood(build_parameters): + """ + This is a generic 3x2pt theory model, but with only + bias as a systematic. + + """ + sacc_data = build_parameters['sacc_data'] +``` +(This is simular to what is currently done in [TXPipe](https://github.com/LSSTDESC/TXPipe/blob/df0dcc8c1e974576dd1942624ab5ff7bd0fbbaa0/txpipe/utils/theory_model.py#L19)). + +The likelihood module also must have a method `.compute_theory_vector(ModellingTools)` which calls for the calculation of the theory vector inside the likelihood object. + +The likelihood can be provided either as a path to the python file containing the `build_likelihood` function or as a python module. In the latter case, the module must be imported. + ## Legacy Blinding Legacy Blinding scripts for 2pt data vector blinding with Cosmosis moved to a [new repository](https://github.com/LSSTDESC/legacy_blinding). diff --git a/src/blinding/__main__.py b/src/blinding/__main__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/blinding/smokescreen.py b/src/blinding/smokescreen.py index a22b22b..2c9a664 100644 --- a/src/blinding/smokescreen.py +++ b/src/blinding/smokescreen.py @@ -1 +1,77 @@ import numpy as np +import os +import types +import pyccl as ccl +from firecrown.likelihood.likelihood import load_likelihood +from firecrown.likelihood.likelihood import load_likelihood_from_module_type +from firecrown.parameters import ParamsMap + + +# creates the smokescreen object +class Smokescreen(): + """ + Class for calling a smokescreen on the measured data-vector. + """ + def __init__(self, cosmo, sacc_data, likelihood, systematics_dict, shifts_dict, **kwargs): + """ + Parameters + ---------- + cosmo : pyccl.Cosmology + Cosmology object from CCL with a fiducial cosmology. + sacc_data : sacc.sacc.Sacc + Data-vector to be blinded. + likelihood : str or module + path to the likelihood or a module containing the likelihood + must contain both `build_likelihood` and `compute_theory_vector` methods + systematics_dict : dict + Dictionary of systematics names and corresponding fiducial values. + shifts_dict : dict + Dictionary of parameter names and corresponding shift widths. If the + shifts are single values, the dictionary values should be the shift + widths. If the shifts are tuples of values, the dictionary values + should be the (lower, upper) bounds of the shift widths. + """ + # save the cosmology + self.cosmo = cosmo + # save the data-vector + self.sacc_data = sacc_data + # load the likelihood + self.likelihood, self.tools = self.load_likelihood(likelihood, **kwargs) + + # # load the systematics + # self.systematics = self.load_systematics(systematics_dict) + # # load the shifts + # self.shifts = self.load_shifts(shifts_dict) + # # create the smokescreen data-vector + # self.smokescreen_data = self.create_smokescreen_data() + + def load_likelihood(self, likelihood): + """ + Loads the likelihood either from a python module or from a file. + + Parameters + ---------- + likelihood : str or module + path to the likelihood or a module containing the likelihood + must contain both `build_likelihood` and `compute_theory_vector` methods + """ + if type(likelihood) == str: + # check if the file can be found + if not os.path.isfile(likelihood): + raise FileNotFoundError(f'Could not find file {likelihood}') + # load the likelihood from the file + likelihood, tools = load_likelihood(likelihood, None) + # check if the likehood has a compute_vector method + if not hasattr(likelihood, 'compute_theory_vector'): + raise AttributeError('Likelihood does not have a compute_vector method') + return likelihood, tools + elif isinstance(likelihood, types.ModuleType): + # check if the module has a build_likelihood method + if not hasattr(likelihood, 'build_likelihood'): + raise AttributeError('Likelihood does not have a build_likelihood method') + # tries to load the likelihood from the module + likelihood, tools = load_likelihood_from_module_type(likelihood, None) + # check if the likehood has a compute_vector method + if not hasattr(likelihood, 'compute_theory_vector'): + raise AttributeError('Likelihood does not have a compute_vector method') + return likelihood, tools diff --git a/tests/test_smokescreen.py b/tests/test_smokescreen.py new file mode 100644 index 0000000..a6a215d --- /dev/null +++ b/tests/test_smokescreen.py @@ -0,0 +1,47 @@ +import pytest +import types +import sacc +from firecrown.likelihood.likelihood import Likelihood +from firecrown.modeling_tools import ModelingTools +from blinding.smokescreen import Smokescreen + +class EmptyLikelihood(Likelihood): + """ + empty mock likelihood based on: + https://github.com/LSSTDESC/firecrown/blob/master/tests/likelihood/lkdir/lkmodule.py + """ + def __init__(self): + self.nothing = 1.0 + super().__init__() + def read(self, sacc_data: sacc.Sacc): + pass + def compute_loglike(self, ModellingTools): + return -self.nothing*2.0 + def compute_theory_vector(self): + return self.nothing + +class MockLikelihoodModule(types.ModuleType): + def build_likelihood(self, *args, **kwargs): + mocktools = ModelingTools() + mocklike = EmptyLikelihood() + return mocklike, mocktools + + def compute_theory_vector(self): + return None + +def test_smokescreen_init(): + # Create mock inputs + cosmo = "cosmo" + sacc_data = "sacc_data" + likelihood = MockLikelihoodModule("mock_likelihood") + systematics_dict = {"systematic1": 0.1} + shifts_dict = {"param1": 1} + + # Check that Smokescreen can be instantiated with valid inputs + smokescreen = Smokescreen(cosmo, sacc_data, likelihood, systematics_dict, shifts_dict) + assert isinstance(smokescreen, Smokescreen) + + # Check that Smokescreen raises an error when given an invalid likelihood + with pytest.raises(AttributeError): + invalid_likelihood = types.ModuleType("invalid_likelihood") + Smokescreen(cosmo, sacc_data, invalid_likelihood, systematics_dict, shifts_dict) \ No newline at end of file