configuration files

delensalot is best used via configuration files, defining all analysis details in a structured, human-readable metamodel. This section describes the structure of configuration files, used for running delensalot jobs.

At the end of this section, you will understand example configuration files, and know how to modify parameters, and to write a configuration file to perfrom lensing reconstruction on your very own data.

Structure:

A complete delensalot model includes the following objects,

Type

Description

Job

jobs to run for this analysis

Analysis

Analysis settings

Data

Data/simulation settings

Noisemodel

A noisemodel to define the Wiener-filter

Qerec

Quadratic estimator lensing reconstruction settings

Itrec

Iterative lensing reconstruction settings

Mapdelensing

Delensing settings

Stepper

iterative reconstruction likelihood search settings

Chaindescriptor

Conjugate gradient solver settings

Config

General configuration

The following shows the delensalot metamodel and its attributes with the docstring describing the purpose of it. Defaults and valid values for each are defined via validators and may be found in the API.

  1#!/usr/bin/env python
  2
  3"""dlensalot_mm.py: Contains classes defining the metamodel of the Dlensalot formalism.
  4    The metamodel is a structured representation, with the `DLENSALOT_Model` as the main building block.
  5    We use the attr package. It provides handy ways of validation and defaulting.
  6"""
  7
  8import abc, attr, os, sys
  9from os.path import join as opj
 10from pathlib import Path
 11from attrs import validators
 12import numpy as np
 13
 14import logging
 15log = logging.getLogger(__name__)
 16log.setLevel(logging.INFO)
 17
 18from delensalot.config.metamodel import DEFAULT_NotAValue, DEFAULT_NotASTR
 19from delensalot.config.validator import analysis, chaindescriptor, computing, data, filter as v_filter, itrec, job, mapdelensing, meta, model, noisemodel, obd, qerec, stepper
 20
 21
 22import importlib.util
 23
 24
 25class DLENSALOT_Concept:
 26    """An abstract element base type for the Dlensalot formalism."""
 27    __metaclass__ = abc.ABCMeta
 28
 29
 30    def __str__(self):
 31        """ overwrites __str__ to summarize dlensalot model in a prettier way
 32
 33        Returns:
 34            str: A table with all attributes of the model
 35        """        
 36        ##
 37        _str = ''
 38        for key, val in self.__dict__.items():
 39            keylen = len(str(key))
 40            if type(val) in [list, np.ndarray, np.array, dict]:
 41                _str += '{}:'.format(key)+(20-keylen)*' '+'\t{}'.format(type(val))
 42            else:
 43                _str += '{}:'.format(key)+(20-keylen)*' '+'\t{}'.format(val)
 44            _str += '\n'
 45        return _str
 46
 47
 48@attr.s
 49class DLENSALOT_Chaindescriptor(DLENSALOT_Concept):
 50    """A root model element type of the Dlensalot formalism.
 51    This class collects all configurations related to conjugate gradient solver. There are currently not many options for this. Better don't touch it.
 52    
 53    Attributes:
 54        p0: 0
 55        p1: type of the conditioner. Can be in ["diag_cl"]
 56        p2: value of lm_max_ivf[0]
 57        p3: value of nside of the data
 58        p4: np.inf
 59        p5: value of cg_tol
 60        p6: `tr_cg`: value of cd_solve.tr_cg
 61        p7: cacher setting
 62    """
 63    # TODO change names after testing various chains - can we find better heuristics?
 64    p0 =                    attr.field(default=DEFAULT_NotAValue, validator=chaindescriptor.p0)
 65    p1 =                    attr.field(default=DEFAULT_NotAValue, validator=chaindescriptor.p1)
 66    p2 =                    attr.field(default=DEFAULT_NotAValue, validator=chaindescriptor.p2)
 67    p3 =                    attr.field(default=DEFAULT_NotAValue, validator=chaindescriptor.p3)
 68    p4 =                    attr.field(default=DEFAULT_NotAValue, validator=chaindescriptor.p4)
 69    p5 =                    attr.field(default=DEFAULT_NotAValue, validator=chaindescriptor.p5)
 70    p6 =                    attr.field(default=DEFAULT_NotAValue, validator=chaindescriptor.p6)
 71    p7 =                    attr.field(default=DEFAULT_NotAValue, validator=chaindescriptor.p7)
 72
 73@attr.s
 74class DLENSALOT_Stepper(DLENSALOT_Concept):
 75    """A root model element type of the Dlensalot formalism.
 76    Defines the stepper function. The stepper function controls how the increment in the likelihood search is added to the current solution.
 77    Currently, this is pretty much just the harmonicbump class.
 78    
 79    Attributes:
 80        typ (str): The name of the stepper function
 81        lmax_qlm (int): maximum `\ell` of the lensing potential reconstruction
 82        mmax_qlm (int): maximum `m` of the lensing potential reconstruction
 83        a: TBD
 84        b: TBD
 85        xa: TBD
 86        xb: TBD
 87    """
 88    # FIXME this is very 'harmonicbump'-specific.
 89    typ =                   attr.field(default=DEFAULT_NotAValue, validator=stepper.typ)
 90    lmax_qlm =              attr.field(default=DEFAULT_NotAValue, validator=stepper.lmax_qlm) # must match lm_max_qlm -> validator
 91    mmax_qlm =              attr.field(default=DEFAULT_NotAValue, validator=stepper.mmax_qlm) # must match lm_max_qlm -> validator
 92    a =                     attr.field(default=DEFAULT_NotAValue, validator=stepper.a)
 93    b =                     attr.field(default=DEFAULT_NotAValue, validator=stepper.b)
 94    xa =                    attr.field(default=DEFAULT_NotAValue, validator=stepper.xa)
 95    xb =                    attr.field(default=DEFAULT_NotAValue, validator=stepper.xb)
 96
 97
 98@attr.s
 99class DLENSALOT_Job(DLENSALOT_Concept):
100    """A root model element type of the Dlensalot formalism.
101    delensalot can executte different jobs (QE reconstruction, simulation generation, MAP reconstruction, delensing, ..) which is controlled here.
102
103    Attributes:
104        jobs (list[str]): Job identifier(s)
105    """
106    jobs =                  attr.field(default=DEFAULT_NotAValue, validator=job.jobs)
107
108@attr.s
109class DLENSALOT_Analysis(DLENSALOT_Concept):
110    """A root model element type of the Dlensalot formalism.
111    This class collects all configurations related to the specific analysis performed on the data.
112
113    Attributes:
114        key (str):                          reconstruction estimator key
115        version (str):                      specific configuration for the esimator (e.g. `noMF`, which turns off mean-field subtraction)
116        simidxs (np.array[int]):            simulation indices to use for the delensalot job
117        simidxs_mf (np.array[int]):         simulation indices to use for the calculation of the mean-field
118        TEMP_suffix (str):                  identifier to customize TEMP directory of the analysis
119        Lmin (int):                         minimum L for reconstructing the lensing potential
120        zbounds (tuple[int or str,float]):  latitudinal boundary (-1 to 1), or identifier together with noise level ratio treshold at which lensing reconstruction is perfromed.
121        zbounds_len (tuple[int]):           latitudinal extended boundary at which lensing reconstruction is performed, and used for iterative lensing reconstruction
122        lm_max_ivf (tuple[int]):            maximum `\ell` and m for which inverse variance filtering is done
123        lm_max_blt (tuple[int]):            maximum `\ell` and m for which B-lensing template is calculated
124        mask (list[str]):                   TBD
125        lmin_teb (int):                     minimum `\ell` and m of the data which the reconstruction uses, and is set to zero below via the transfer function
126        cls_unl (str):                      path to the fiducial unlensed CAMB-like CMB data
127        cls_len (str):                      path to the fiducial lensed CAMB-like CMB data
128        cpp (str):                          path to the power spectrum of the prior for the iterative reconstruction
129        beam (float):                       The beam used in the filters
130    """
131    key =                   attr.field(default=DEFAULT_NotAValue, validator=analysis.key)
132    version =               attr.field(default=DEFAULT_NotAValue, validator=analysis.version) # TODO either make it more useful, or remove
133    reconstruction_method = attr.field(default=DEFAULT_NotAValue, validator=analysis.reconstruction_method) # TODO implement if needed
134    simidxs =               attr.field(default=DEFAULT_NotAValue, validator=analysis.simidxs)
135    simidxs_mf =            attr.field(default=DEFAULT_NotAValue, validator=analysis.simidxs_mf)
136    TEMP_suffix =           attr.field(default=DEFAULT_NotAValue, validator=analysis.TEMP_suffix)
137    Lmin =                  attr.field(default=DEFAULT_NotAValue, validator=analysis.Lmin)
138    zbounds =               attr.field(default=DEFAULT_NotAValue, validator=analysis.zbounds)
139    zbounds_len =           attr.field(default=DEFAULT_NotAValue, validator=analysis.zbounds_len) # TODO rename
140    lm_max_ivf =            attr.field(default=DEFAULT_NotAValue, validator=v_filter.lm_max_ivf)
141    lm_max_blt =            attr.field(default=DEFAULT_NotAValue, validator=analysis.lm_max_blt)
142    mask =                  attr.field(default=DEFAULT_NotAValue, validator=analysis.mask) # TODO is this used? 
143    lmin_teb =              attr.field(default=DEFAULT_NotAValue, validator=analysis.lmin_teb)
144    cls_unl =               attr.field(default=DEFAULT_NotAValue, validator=analysis.cls_unl)
145    cls_len =               attr.field(default=DEFAULT_NotAValue, validator=analysis.cls_len)
146    cpp =                   attr.field(default=DEFAULT_NotAValue, validator=analysis.cpp)
147    beam =                  attr.field(default=DEFAULT_NotAValue, validator=analysis.beam)
148    transfunction_desc =    attr.field(default=DEFAULT_NotAValue, validator=analysis.transfunction)
149
150
151@attr.s
152class DLENSALOT_Simulation(DLENSALOT_Concept):
153    """A root model element type of the Dlensalot formalism.
154    This class collects all configurations related to the input maps, and values can differ from the noise model and analysis.
155
156    Attributes:
157        flavour      (str): Can be in ['obs', 'sky', 'unl'] and defines the type of data provided.
158        space        (str): Can be in ['map', 'alm', 'cl'] and defines the space of the data provided.
159        maps         (np.array, optional): These maps will be put into the cacher directly. They are used for settings in which no data is generated or accesed on disk, but directly provided (like in `delensalot.anafast()`) Defaults to DNaV.
160        geominfo     (tuple, optional): Lenspyx geominfo descriptor, describes the geominfo of the data provided (e.g. `('healpix', 'nside': 2048)). Defaults to DNaV.
161        field        (str, optional): the type of data provided, can be in ['temperature', 'polarization']. Defaults to DNaV.
162        libdir       (str, optional): directory of the data provided. Defaults to DNaV.
163        libdir_noise (str, optional): directory of the noise provided. Defaults to DNaV.
164        libdir_phi   (str, optional): directory of the lensing potential provided. Defaults to DNaV.
165        fns          (dict with str with formatter, optional): file names of the data provided. It expects `{'T': <filename{simidx}.something>, 'Q': <filename{simidx}.something>, 'U': <filename{simidx}.something>}`, where `{simidx}` is used by the libraries to format the simulation index into the name. Defaults to DNaV.
166        fnsnoise     (dict with str with formatter, optional): file names of the noise provided. It expects `{'T': <filename{simidx}.something>, 'Q': <filename{simidx}.something>, 'U': <filename{simidx}.something>}`, where `{simidx}` is used by the libraries to format the simulation index into the name. Defaults to DNaV.
167        fnsP         (str with formatter, optional): file names of the lensing potential provided. It expects `<filename{simidx}.something>, where `{simidx}` is used by the libraries to format the simulation index into the name. Defaults to DNaV.
168        lmax         (int, optional): Maximum l of the data provided. Defaults to DNaV.
169        transfunction(np.array, optional): transfer function. Defaults to DNaV.
170        nlev         (dict, optional): noise level of the individual fields. It expects `{'T': <value>, 'P': <value>}. Defaults to DNaV.
171        spin         (int, optional): the spin of the data provided. Defaults to 0. Always defaults to 0 for temperature.
172        CMB_fn       (str, optional): path+name of the file of the power spectra of the CMB. Defaults to DNaV.
173        phi_fn       (str, optional): path+name of the file of the power spectrum of the lensing potential. Defaults to DNaV.
174        phi_field    (str, optional): the type of potential provided, can be in ['potential', 'deflection', 'convergence']. This simulation library will automatically rescale the field, if needded. Defaults to DNaV.
175        phi_space    (str, optional): can be in ['map', 'alm', 'cl'] and defines the space of the lensing potential provided.. Defaults to DNaV.
176        phi_lmax     (_type_, optional): the maximum multipole of the lensing potential. if simulation library perfroms lensing, it is advisable that `phi_lmax` is somewhat larger than `lmax` (+ ~512-1024). Defaults to DNaV.
177        epsilon      (float, optional): Lenspyx lensing accuracy. Defaults to 1e-7.
178                                               
179    """
180
181    flavour =       attr.field(default=DEFAULT_NotAValue, validator=data.flavour)
182    space =         attr.field(default=DEFAULT_NotAValue, validator=data.space)
183    maps =          attr.field(default=DEFAULT_NotAValue, validator=data.maps)
184    geominfo =      attr.field(default=DEFAULT_NotAValue, validator=data.geominfo)
185    lenjob_geominfo=attr.field(default=DEFAULT_NotAValue, validator=data.geominfo)
186    field =         attr.field(default=DEFAULT_NotAValue, validator=data.field)
187    libdir =        attr.field(default=DEFAULT_NotAValue, validator=data.libdir)
188    libdir_noise =  attr.field(default=DEFAULT_NotAValue, validator=data.libdir_noise)
189    libdir_phi =    attr.field(default=DEFAULT_NotAValue, validator=data.libdir_phi)
190    fns =           attr.field(default=DEFAULT_NotAValue, validator=data.fns)
191    fnsnoise =      attr.field(default=DEFAULT_NotAValue, validator=data.fnsnoise)
192    fnsP =          attr.field(default=DEFAULT_NotAValue, validator=data.fnsP)
193    lmax =          attr.field(default=DEFAULT_NotAValue, validator=data.lmax)
194    transfunction = attr.field(default=DEFAULT_NotAValue, validator=data.transfunction)
195    nlev =          attr.field(default=DEFAULT_NotAValue, validator=data.nlev)
196    spin =          attr.field(default=DEFAULT_NotAValue, validator=data.spin)
197    CMB_fn =        attr.field(default=DEFAULT_NotAValue, validator=data.CMB_fn)
198    phi_fn =        attr.field(default=DEFAULT_NotAValue, validator=data.phi_fn)
199    phi_field =     attr.field(default=DEFAULT_NotAValue, validator=data.phi_field)
200    phi_space =     attr.field(default=DEFAULT_NotAValue, validator=data.phi_space)
201    phi_lmax =      attr.field(default=DEFAULT_NotAValue, validator=data.phi_lmax)
202    epsilon =       attr.field(default=DEFAULT_NotAValue, validator=data.epsilon)
203    libdir_suffix = attr.field(default='generic', validator=data.libdir_suffix)
204    
205@attr.s
206class DLENSALOT_Noisemodel(DLENSALOT_Concept):
207    """A root model element type of the Dlensalot formalism.
208    This class collects all configurations related to the noise model used for Wiener-filtering the data.
209
210    Attributes:
211        sky_coverage (str):     Can be either 'masked' or 'unmasked'
212        spectrum_type (str):    TBD
213        OBD (str):              OBD identifier. Can be 'OBD', 'trunc', or None. Defines how lowest B-modes will be handled.
214        nlev_t (float):         (central) noise level of temperature data in muK arcmin.
215        nlev_p (float):         (central) noise level of polarization data in muK arcmin.
216        rhits_normalised (str): path to the hits-count map, used to calculate the noise levels, and the mask tracing the noise level. Second entry in tuple is the <inverse hits-count multiplier>.
217        geominfo (tuple): geominfo of the noise map
218    """
219    sky_coverage =          attr.field(default=DEFAULT_NotAValue, validator=noisemodel.sky_coverage)
220    spectrum_type =         attr.field(default=DEFAULT_NotAValue, validator=noisemodel.spectrum_type)
221    OBD =                   attr.field(default=DEFAULT_NotAValue, validator=noisemodel.OBD)
222    nlev =                  attr.field(default=DEFAULT_NotAValue, validator=noisemodel.nlev_t)
223    geominfo =              attr.field(default=DEFAULT_NotAValue, validator=noisemodel.ninvjob_geominfo) # FIXME this must match the data geominfo.. validate accordingly
224    zbounds =               attr.field(default=DEFAULT_NotAValue, validator=noisemodel.ninvjob_geominfo) # FIXME is this used? How is it different to Analysis.zbounds?
225    rhits_normalised =      attr.field(default=DEFAULT_NotAValue, validator=noisemodel.rhits_normalised)
226    nivt_map =              attr.field(default=DEFAULT_NotAValue, validator=noisemodel.ninvjob_geominfo) # TODO test if it works
227    nivp_map =              attr.field(default=DEFAULT_NotAValue, validator=noisemodel.ninvjob_geominfo) # TODO test if it works
228
229@attr.s
230class DLENSALOT_Qerec(DLENSALOT_Concept):
231    """A root model element type of the Dlensalot formalism.
232    This class collects all configurations related to the quadratic estimator reconstruction job.
233
234    Attributes:
235        tasks (list[tuple]):        tasks to perfrom. Can be any combination of :code:`calc_phi`, :code:`calc_meanfield`, :code:`calc_blt`
236        qlm_type (str):             lensing potential estimator identifier. Can be 'sepTP' or 'jTP'
237        cg_tol (float):             tolerance of the conjugate gradient method
238        filter_directional (str):   can be either 'isotropic' (unmasked sky) or 'isotropic' (masked sky)
239        lm_max_qlm (type):          maximum multipole `\ell` and m to reconstruct the lensing potential
240        chain (DLENSALOT_Chaindescriptor): configuration of the conjugate gradient method. Configures the chain and preconditioner
241        cl_analysis (bool):         If tru, performs lensing power spectrum analysis
242        blt_pert (bool):            If True, delensing is performed perurbitivly (recommended)
243    
244    """
245
246    tasks =                 attr.field(default=DEFAULT_NotAValue, validator=qerec.tasks)
247    qlm_type =              attr.field(default=DEFAULT_NotAValue, validator=qerec.qlms)
248    cg_tol =                attr.field(default=DEFAULT_NotAValue, validator=qerec.cg_tol)
249    filter_directional =    attr.field(default=DEFAULT_NotAValue, validator=qerec.filter_directional)
250    lm_max_qlm =            attr.field(default=DEFAULT_NotAValue, validator=qerec.lm_max_qlm) # TODO move this to analysis, lmax must be same in qe and it
251    chain =                 attr.field(default=DLENSALOT_Chaindescriptor(), validator=qerec.chain)
252    cl_analysis =           attr.field(default=DEFAULT_NotAValue, validator=qerec.cl_analysis) # TODO make this useful or remove
253    blt_pert =              attr.field(default=DEFAULT_NotAValue, validator=qerec.btemplate_perturbative_lensremap)
254
255@attr.s
256class DLENSALOT_Itrec(DLENSALOT_Concept):
257    """A root model element type of the Dlensalot formalism.
258    This class collects all configurations related to the iterative reconstruction job.
259
260    Attributes:
261        tasks (list[str]):          tasks to perfrom. Can be any combination of :code:`calc_phi`, :code:`calc_meanfield`, :code:`calc_blt`
262        itmax (int):                maximum number of iterations
263        cg_tol (float):             tolerance of the conjugate gradient method
264        iterator_typ (str):         mean-field handling identifier. Can be either 'const_mf' or 'pert_mf'
265        chain (DLENSALOT_Chaindescriptor): configuration for the conjugate gradient solver
266        filter_directional (str):   can be either 'isotropic' (unmasked sky) or 'isotropic' (masked sky)
267        lenjob_geominfo (str):      can be 'healpix_geominfo', 'thin_gauss' or 'pbdGeometry'
268        lenjob_pbgeominfo (str):    can be 'healpix_geominfo', 'thin_gauss' or 'pbdGeometry'
269        lm_max_unl (tuple[int]):    maximum multipoles `\ell` and m for reconstruction the unlensed CMB
270        lm_max_qlm (tuple[int]):    maximum multipoles L and m for reconstruction the lensing potential
271        mfvar (str):                path to precalculated mean-field, to be used instead
272        soltn_cond (type):          TBD
273        stepper (DLENSALOT_STEPPER):configuration for updating the current likelihood iteration point with the likelihood gradient
274              
275    """
276    tasks =                 attr.field(default=DEFAULT_NotAValue, validator=itrec.tasks)
277    itmax =                 attr.field(default=DEFAULT_NotAValue, validator=itrec.itmax)
278    cg_tol =                attr.field(default=DEFAULT_NotAValue, validator=itrec.cg_tol)
279    iterator_typ =          attr.field(default=DEFAULT_NotAValue, validator=itrec.iterator_type) # TODO rename
280    chain =                 attr.field(default=DLENSALOT_Chaindescriptor(), validator=itrec.chain)
281    filter_directional =    attr.field(default=DEFAULT_NotAValue, validator=itrec.filter_directional)
282    lenjob_geominfo =       attr.field(default=DEFAULT_NotAValue, validator=itrec.lenjob_geominfo)
283    lenjob_pbdgeominfo =    attr.field(default=DEFAULT_NotAValue, validator=itrec.lenjob_pbgeominfo)
284    lm_max_unl =            attr.field(default=DEFAULT_NotAValue, validator=itrec.lm_max_unl)
285    lm_max_qlm =            attr.field(default=DEFAULT_NotAValue, validator=itrec.lm_max_qlm)
286    mfvar =                 attr.field(default=DEFAULT_NotAValue, validator=itrec.mfvar) # TODO rename and check if it still works 
287    soltn_cond =            attr.field(default=DEFAULT_NotAValue, validator=itrec.soltn_cond)
288    stepper =               attr.field(default=DLENSALOT_Stepper(), validator=itrec.stepper)
289    epsilon =               attr.field(default=DEFAULT_NotAValue, validator=data.epsilon)
290    
291@attr.s
292class DLENSALOT_Mapdelensing(DLENSALOT_Concept):
293    """A root model element type of the Dlensalot formalism.
294    This class collects all configurations related to the internal map delensing job.
295
296    Attributes:
297        data_from_CFS (bool):   if set, use B-lensing templates located at the $CFS directory instead of the $TEMP directory\n
298        edges (np.array):       binning to calculate the (delensed) power spectrum on\n
299        dlm_mod (bool):         if set, modfies the lensing potential before calculating the B-lensing template\n
300        iterations (list[int]): which iterations to calculate delensed power spectrum for\n
301        nlevels (list[float]):  noiselevel ratio treshold up to which the maps are delensed, uses the rhits_normalized map to generate masks.
302        lmax (int):             maximum multipole to calculate the (delensed) power spectrum\n
303        Cl_fid (type):          fiducial power spectrum, and needed for template calculation of the binned power spectrum package\n
304        libdir_it (type):       TBD\n
305        binning (type):         can be either 'binned' or 'unbinned'. If 'unbinned', overwrites :code:`edges` and calculates power spectrum for each multipole\n
306        spectrum_calculator (package): name of the package of the power spectrum calculator. Can be 'healpy' if :code:`binning=unbinned`\n
307        masks_fn (list[str]):   the sky patches to calculate the power spectra on. Note that this is different to using `nlevels`. Here, no tresholds are calculated, but masks are used 'as is' for delensing.\n
308        basemap (str):          the delensed map Bdel is calculated as Bdel = basemap - blt. Basemap can be two things: 'obs' or 'lens', where 'obs' will use the observed sky map, and lens will use the pure B-lensing map.
309    """
310
311    data_from_CFS =         attr.field(default=DEFAULT_NotAValue, validator=mapdelensing.data_from_CFS)
312    edges =                 attr.field(default=DEFAULT_NotAValue, validator=mapdelensing.edges)
313    dlm_mod =               attr.field(default=DEFAULT_NotAValue, validator=mapdelensing.dlm_mod)
314    iterations =            attr.field(default=DEFAULT_NotAValue, validator=mapdelensing.iterations)
315    nlevels =               attr.field(default=DEFAULT_NotAValue, validator=mapdelensing.nlevels)
316    lmax =                  attr.field(default=DEFAULT_NotAValue, validator=mapdelensing.lmax)
317    Cl_fid =                attr.field(default=DEFAULT_NotAValue, validator=mapdelensing.Cl_fid)
318    libdir_it =             attr.field(default=DEFAULT_NotAValue, validator=mapdelensing.libdir_it)
319    binning =               attr.field(default=DEFAULT_NotAValue, validator=mapdelensing.binning)
320    spectrum_calculator =   attr.field(default=DEFAULT_NotAValue, validator=mapdelensing.spectrum_calculator)
321    masks_fn =              attr.field(default=DEFAULT_NotAValue, validator=mapdelensing.masks)
322    basemap =               attr.field(default=DEFAULT_NotAValue, validator=mapdelensing.basemap)
323
324@attr.s
325class DLENSALOT_OBD(DLENSALOT_Concept):
326    """A root model element type of the Dlensalot formalism.
327    This class collects all configurations related to the overlapping B-mode deprojection.
328
329    Attributes:
330        libdir (str):       path to the OBD matrix
331        rescale (float):    rescaling of OBD matrix amplitude. Useful if matrix already calculated, but noiselevel changed
332        tpl (type):         function name for calculating OBD matrix
333        nlev_dep (float):   deprojection factor, or, strength of B-mode deprojection
334        lmax (int):         maximum multipole to deproject B-modes
335        beam (type):        TBD                         
336    """
337    libdir =                attr.field(default=DEFAULT_NotAValue, validator=obd.libdir)
338    rescale =               attr.field(default=DEFAULT_NotAValue, validator=obd.rescale) # TODO this is a very specific parameter.. keep?
339    tpl =                   attr.field(default=DEFAULT_NotAValue, validator=obd.tpl)
340    nlev_dep =              attr.field(default=DEFAULT_NotAValue, validator=obd.nlev_dep)
341    lmax =                  attr.field(default=DEFAULT_NotAValue, validator=obd.lmax)
342    beam =                  attr.field(default=DEFAULT_NotAValue, validator=obd.beam) # TODO why not use beam from analysis? or transfunction..
343
344@attr.s
345class DLENSALOT_Config(DLENSALOT_Concept):
346    """A root model element type of the Dlensalot formalism.
347    This class collects all configurations related to general behaviour to the operating system. 
348
349    Attributes:
350        outdir_plot_root (str): root path for the plots to be stored at
351        outdir_plot_rel (str):  relative path folder for the plots to be stored at
352    """
353    outdir_plot_root =      attr.field(default=opj(os.environ['HOME'], 'plots'))
354    outdir_plot_rel =       attr.field(default='')
355
356@attr.s
357# @add_defaults
358class DLENSALOT_Meta(DLENSALOT_Concept): # TODO do we really need a Meta?
359    """A root model element type of the Dlensalot formalism.
360    This class collects all configurations related to internal behaviour of delensalot.
361
362    Attributes:
363        version (str):  version control of the delensalot model
364    """
365    version =               attr.field(default=DEFAULT_NotAValue, validator=attr.validators.instance_of(int))
366
367
368@attr.s
369class DLENSALOT_Computing(DLENSALOT_Concept):
370    """A root model element type of the Dlensalot formalism.
371    This class collects all configurations related to the usage of computing resources.
372
373    Attributes:
374        OMP_NUM_THREADS (int):  number of threads used per Job
375    """
376    OMP_NUM_THREADS =       attr.field(default=DEFAULT_NotAValue, validator=computing.OMP_NUM_THREADS)
377
378
379@attr.s
380class DLENSALOT_Model(DLENSALOT_Concept):
381    """A root model element type of the Dlensalot formalism.
382
383    Attributes:
384        defaults_to (str):              Identifier for default-dictionary if user hasn't specified value in configuration file
385        meta (DLENSALOT_Meta):          configurations related to internal behaviour of delensalot
386        job (DLENSALOT_Job):            delensalot can executte different jobs (QE reconstruction, simulation generation, MAP reconstruction, delensing, ..) which is controlled here
387        analysis (DLENSALOT_Analysis):  configurations related to the specific analysis performed on the data
388        data (DLENSALOT_Data):          configurations related to the input CMB maps
389        noisemodel (DLENSALOT_Noisemodel):  configurations related to the noise model used for Wiener-filtering the data
390        qerec (DLENSALOT_Qerec):        configurations related to the quadratic estimator reconstruction job
391        itrec (DLENSALOT_Itrec):        configurations related to the iterative reconstruction job
392        madel (DLENSALOT_Mapdelensing): configurations related to the internal map delensing job
393        config (DLENSALOT_Config):      configurations related to general behaviour to the operating system
394        computing (DLENSALOT_Computing):    configurations related to the usage of computing resources
395        obd (DLENSALOT_OBD):            configurations related to the overlapping B-mode deprojection
396
397    """
398    
399    defaults_to =           attr.field(default='default_CMBS4_fullsky_polarization')
400    meta =                  attr.field(default=DLENSALOT_Meta(), validator=model.meta)
401    job =                   attr.field(default=DLENSALOT_Job(), validator=model.job)
402    analysis =              attr.field(default=DLENSALOT_Analysis(), validator=model.analysis)
403    simulationdata =        attr.field(default=DLENSALOT_Simulation(), validator=model.data)
404    noisemodel =            attr.field(default=DLENSALOT_Noisemodel(), validator=model.noisemodel)
405    qerec =                 attr.field(default=DLENSALOT_Qerec(), validator=model.qerec)
406    itrec =                 attr.field(default=DLENSALOT_Itrec(), validator=model.itrec)
407    madel =                 attr.field(default=DLENSALOT_Mapdelensing(), validator=model.madel)
408    config =                attr.field(default=DLENSALOT_Config(), validator=model.config)
409    computing =             attr.field(default=DLENSALOT_Computing(), validator=model.computing)
410    obd =                   attr.field(default=DLENSALOT_OBD(), validator=model.obd)
411    
412
413    def __attrs_post_init__(self):
414        """
415        The logic is as follow:
416         * All variables default to 'DEFAULT_NotAValue' upon start - validator checks and passes due to 'DEFAULT_NotAValue' being allowed
417         * Upon loading config file:
418            * 1st init: all user-variables are set, validator checks
419            * 2nd init (this function here): remaining variables with value 'DEFAULT_NotAValue' are set to user-specified 'default_to'-dictionary
420         * 'validator' takes care of validating post-init, thus all default-dict keys are validated
421         comment: __attrs_post_init must be in DLENSALOT_Model, as this is the only one who knows of the default dictionary (defaults_to), and cannot simply be passed along to sub-classes.
422
423        """
424        # log.info("Setting default, using {}:\n\t{}".format(self.defaults_to, default_dict))
425
426        spec = importlib.util.spec_from_file_location("default", opj(Path(__file__).parent.parent, "default/{}.py".format(self.defaults_to.replace('.py', ''))))
427        default_module = importlib.util.module_from_spec(spec)
428        sys.modules["default"] = default_module
429        spec.loader.exec_module(default_module)
430        default_dict = default_module.DL_DEFAULT
431        for key, val in list(filter(lambda x: '__' not in x[0] and x[0] != 'defaults_to', self.__dict__.items())):
432            for k, v in val.__dict__.items():
433                if k in ['chain', 'stepper']:
434                    for ke, va in v.__dict__.items():
435                        if np.all(va == DEFAULT_NotAValue):
436                            if key in default_dict:
437                                if k in default_dict[key]:
438                                    if ke in default_dict[key][k]:
439                                        self.__dict__[key].__dict__[k].__dict__.update({ke: default_dict[key][k][ke]})
440                elif np.all(v == DEFAULT_NotAValue):
441                    if key in default_dict:
442                        if k in default_dict[key]:
443                            # log.info('\t\t{}: Found default for k {}: {}'. format(key, k, default_dict[key][k]))
444                            self.__dict__[key].__dict__.update({k: default_dict[key][k]})
445                        else:
446                            if key not in ['simulationdata']:
447                                # It is ok to not have defaults for simulationdata, as the simlib will handle it
448                                log.info('{}: couldnt find matching default value for {}'.format(key, k))
449                    else:
450                        log.info('couldnt find matching default value for key {}'.format(key))
451                elif callable(v):
452                    # Cannot evaluate functions, so hopefully they didn't change..
453                    pass

example models are provided for different use cases, among them,

  • cmbs4-like setting with no foregrounds and no masking

  • cmbs4-like setting with no foreground and masking

  • cmbs4-like setting with foregrounds and no masking