grale.paramdesc
This module contains tools for parametric inversion: something to analyze a description of a lens model that can be optimized parametrically, and a routine to start such a description based on an existing lens model.
- grale.paramdesc.getSupportedLensTypes()
List which gravitational lens types are recognized in the parametric description.
- grale.paramdesc.createParametricDescription(lens, massUnitString='MASS_SUN', angularUnitString='ANGLE_ARCSEC', asString=True, convertValueFunction=None, objectStore=None, objectStoreName=None)
Create a basic representation of a parametric lens model, based on the
lens model
in lens. The result is a string which represents python code and can be saved to a file for further editing. By default this result has no parameters that can change and will need to be adjusted, but this behaviour can be changed using the convertValueFunction parameter (see below).To make the description more readable, values for masses will be represented as a value times the mass unit, which needs to be represented as string in massUnitString. Similarly, angular values will be represented using angularUnitString.
By default a single large string is returned, if a list of separate lines is more covenient, the asString parameter can be set to
False
.The convertValueFunction is a callback that can be used to convert a fixed value to a variable one. The parameters are:
value: the value itself
lensName: this is a list, of which the last entry specifies the name of the current (sub) model. This list could simply be
[ "NSIELens" ]
for a simple lens, or e.g.[ "CompositeLens", "lens_0", "NSIELens" ]
for a more complex model.paramName: the name of the parameter, for example
"mass"
uniqueParamName: internal name of the parameter, which is unique. This is similar to the parameter names in
variablefloatparams
from theanalyzeParametricLensDescription()
function.fullParams: the full lens model parameters of the current (sub) model. This could be helpful if you need more information about which submodel is being considered.
The return value can be:
a value: in that case this is a fixed parameter
a list
[ value, fraction ]
to initialize the parameter to vary between bounds specified by the fraction, or just[ value ]
if the default fraction is to be used when callinganalyzeParametricLensDescription()
. If a third fraction is specified, e.g.[ value, fraction, hardfraction ]
, then that will be used for the hard bounds.a dictionary containing entries for
"initmin"
and"initmax"
, and optionally"hardmin"
and"hardmax"
. Entries for"cname"
and"tag"
are also allowed - seeanalyzeParametricLensDescription()
for their meaning.
For some lenses (for now only a
DeflectionGridLens
) it may be nessary to store a large amount of data somewhere (e.g. the deflection angles on a grid). In this case you can specify a dictionary for objectStore where this data will be stored with a unique key. In the final output of this function (which is a string), the name objectStoreName will be used as the name of this dictionary.
- grale.paramdesc.analyzeParametricLensDescription(parametricLens, Dd, defaultFraction, clampToHardLimits=False, allowSameInitialMinMax=False, forceScales=None)
Analyze the parametric lens description in parametricLens, which should be a dictionary, for a lens at angular diameter distance Dd. In case a parameter is set to change with some fraction about a value, defaultFraction is used if no specific fraction is specified. By default, an error will be generated if some initial value bounds exceed the hard bounds, but if clampToHardLimits is set to
True
, the hard limit will be used as bound for the initial value.Returns a dictionary with the following entries:
templatelens
: a lens model constructed from the descriptionfloatparams
: the floating point parameters for the model, some of which can be changed.scales
: itself a dictionary with entries for the angular and potential scales that are used.variablefloatparams
: describes which of the floating point parameters can be changed, and within which boundaries.
An example parametricLens object:
parametricLens = { "type": "MultiplePlummerLens", "params": [ { # This represents a fixed value "x": 2*ANGLE_ARCSEC, # This specifies an initial value that can change within 20% of the specified one. # During optimization these bounds can be exceeded "y": [ 1*ANGLE_ARCSEC, 0.20 ] # Also a variable that can change, the amount determined by `defaultFraction` "mass": [ 1e13*MASS_SUN ], # When three entries are specified, the second is again to determine the # range of initial values, the last one is a fraction to fix hard limits. "width": [ 3*ANGLE_ARCSEC, 0.1, 0.5 ] }, { # Here the initial values will be chosen in the specified interval "x": { "initmin": -2*ANGLE_ARCSEC, "initmax": 2*ANGLE_ARCSEC }, # Similar, but hard bounds for the parameter are specified as well # In case none are specified, default values are used for these, # depending on the parameter type. Specifying them overrides the # defaults. "y": { "initmin": -2*ANGLE_ARCSEC, "initmax": 2*ANGLE_ARCSEC, "hardmin": -3*ANGLE_ARCSEC, "hardmax": 3*ANGLE_ARCSEC }, # And some fixed values "mass": 1e13*MASS_SUN, "width": 2*ANGLE_ARCSEC } ] }
When a dictionary is used to specify the initial range, you can also specify a special entry
"cname"
, with which parameters can be coupled to each other. For example, if two variables both have"cname": "SomeName"
, then only one of them will be changed, and the other will always have the same value. This can come in handy if you’d like to optimize two models, say one for the visible matter and one for dark matter, and you’d like both to be centered on the exact same position even though this position might need to be determined. Perhaps even the orientation could be forced to be the same this way.In such a case, it’s even possible to perform some operations on the variables: if
"cname": "SomeName ; x*2"
is specified, then this parameter’s value will be set to twice the reference value. There should always be one without any extra operations, so that a reference value can be determined.If a dictionary is used, you can also specify some
"tag"
value. This will be interpreted as a string, but will mostly be ignored. You can use this to name some variables yourself, perhaps to make post-processing lens inversion results easier to interpret.
- grale.paramdesc.refineParametricDescription(initialParamDesc, lens, fraction, createParamDescArgs={})
This is a helper function to adjust an earlier parametric lens description based on an estimate of the solution. The envisioned usage is to first do a general parametric lens inversion based on initialParamDesc, which leads to a lens model lens. Then you adjust the initial parameter ranges to a narrow range around the values from this model, so that a following MCMC exploration can look in the most interesting region of the parameter space.
Arguments:
initialParamDesc: the parametric model description (see e.g.
analyzeParametricLensDescription()
) that is used to obtain an initial lens model, which is then passed as the following argument.lens: this should be the lens model that results from the parametric optimization that was performed with the previous lens description. The initial bounds on the parameters that are allowed to change are set to a small range around the corresponding value from this model.
fraction: for the parameters that are not fixed, the initial values will be based on this fraction. For example, if this is 0.05, or 5%, the initial value range will be set to 95% and 105% of the value of the lens model. Alternatively, this can also be a callback function that should return the new initial value range. It is called with three arguments, the value itself, the type of the lens and the name of the parameter.
createParamDescArgs: dictionary for arguments that will be passed on to the call to
createParametricDescription()
.