Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parameter class #19

Merged
merged 13 commits into from
Jun 21, 2023
Merged

Parameter class #19

merged 13 commits into from
Jun 21, 2023

Conversation

hammannr
Copy link
Collaborator

This adds the Parameter and Parameters classes, which simplify the handling of our parameters. Closes #13 and #18.

Some example code to play around with the Parameter & Parameters classes:
Simple examples:

from alea.parameters import Parameter, Parameters

mu = Parameter(name="mu", nominal_value=1, fittable=True, uncertainty=0.1)
>>> mu
alea.parameters.Parameter(name=mu, nominal_value=1, fittable=True, _uncertainty=0.1)
>>> mu.uncertainty
0.1
>>> mu.uncertainty = .5
>>> mu.uncertainty
0.5
>>> parameters = Parameters()
>>> parameters.add_parameter(mu)
>>> parameters
alea.parameters.Parameters(mu)

load from config:

parameter_definition = {
    "wimp_mass": {
        "nominal_value": 50,
        "fittable": False,
    },
    "livetime_0": {
        "nominal_value": 0.2,
        "fittable": False,
        "description": "Livetime of SR0 in years",
    },
    "livetime_1": {
        "nominal_value": 1.,
        "fittable": False,
        "description": "Livetime of SR1 in years",
    },
    "signal_rate_multiplier": {
        "nominal_value": 1.,
        "ptype": "rate",
        "fittable": True,
        "fit_limits": (0, None),
    },
    "er_rate_multiplier": {
        "nominal_value": 1.,
        "ptype": "rate",
        "uncertainty": 0.2,
        "relative_uncertainty": True,
        "fittable": True,
        "fit_limits": (0, None),
        "fit_guess": 1.,
    },
    "par1": {
        "nominal_value": 0,
        "ptype": "shape",
        "uncertainty": "scipy.stats.uniform(loc=-1, scale=2)",
        "relative_uncertainty": False,
        "fittable": True,
        "blueice_anchors": [-1, 0, 1],
        "fit_limits": (-1, 1),
        "description": "ER PCA shape parameter 1",
    },
}
>>> parameters = Parameters.from_config(parameter_definition)
>>> parameters.wimp_mass.nominal_value = 100
>>> parameters()
{'wimp_mass': 100,
 'livetime_0': 0.2,
 'livetime_1': 1.0,
 'signal_rate_multiplier': 1.0,
 'er_rate_multiplier': 1.0,
 'par1': 0}
>>> parameters(signal_rate_multiplier=0.)
{'wimp_mass': 100,
 'livetime_0': 0.2,
 'livetime_1': 1.0,
 'signal_rate_multiplier': 0.0,
 'er_rate_multiplier': 1.0,
 'par1': 0}
>>> parameters.fittable
['signal_rate_multiplier', 'er_rate_multiplier', 'par1']

An updated example for the Gaussian model:

from alea.examples.gaussian_model import GaussianModel
import numpy as np
import matplotlib.pyplot as plt


model = GaussianModel()

# further define the parameters
model.parameters.sigma.fittable = False
model.parameters.sigma.nominal_value = .1
model.parameters.mu.nominal_value = 1.
model.parameters.mu.fit_limits = (-5, 5)

# toy generation
data = model.generate_data()
model.data = data

# Fit the data
best_fit, ll_val = model.fit(verbose=True)

@hammannr hammannr added the enhancement New feature or request label Jun 20, 2023
@hammannr hammannr requested review from kdund and dachengx June 20, 2023 18:46
…s a dict of all parameters with a nominal value, and a method to take that dict and update with any new values (useful to always pass entire dict of parameters to likelihood)
Copy link
Collaborator

@kdund kdund left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @hammannr looks good! Added a nominal values property + class to update parameter values, I think this is useful to always pass all args to likelihood etc. that way (we can add limit checking next pass I guess)

@hammannr
Copy link
Collaborator Author

@kdund if I understand correctly, your get_parameters_to_call method is essentially the same as the __call__ method. And I think we could do the clean version that you implemented in ll and generate_args also with the call one since it will set the default if None is parsed. I just missed doing this 😅 ..
Did I miss the point of get_parameters_to_call ? Otherwise, I'd revert to using the call function and write parameters = self.parameters(mu=mu, sigma=sigma) in the ll and generate_data methods.

@kdund
Copy link
Collaborator

kdund commented Jun 20, 2023

oops, sorry, @hammannr didn't realise I was duplicating. I do think it is neater to clean away Nones in the parameter call. feel free to remove what does not add anything

@hammannr
Copy link
Collaborator Author

@kdund I now went back to the call method, it should have all the functionality (in particular, if you parse Nones as kwargs they are just dropped).
Also, I took your nice idea of a method to check whether a value is within limit and implemented it already in the Parameter class as I think it already makes sense there. I also added an exception in case one tries to fix a value outside the fit params (I guess this was your intent, right?).
Let me know whether you think those changes fit your intended purpose! 😊

@kdund
Copy link
Collaborator

kdund commented Jun 20, 2023 via email

@hammannr
Copy link
Collaborator Author

Also solves #6 (forgot earlier).

@hammannr hammannr merged commit 93f61c7 into master Jun 21, 2023
@hammannr hammannr deleted the parameter_class branch June 21, 2023 19:36
@kdund kdund mentioned this pull request Jun 21, 2023
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
2 participants