Source code for exoctk.lightcurve_fitting.fitters

"""Functions used to fit models to light curve data

Author: Joe Filippazzo
Email: jfilippazzo@stsci.edu
"""
import numpy as np
import lmfit
import copy

from .parameters import Parameters


[docs]def lmfitter(time, data, model, uncertainty=None, verbose=True, **kwargs): """Use lmfit Parameters ---------- data: sequence The observational data model: ExoCTK.lightcurve_fitting.models.Model The model to fit uncertainty: np.ndarray (optional) The uncertainty on the (same shape) data method: str The name of the method to use name: str A name for the best fit model verbose: bool Print some stuff Returns ------- lmfit.Model.fit.fit_report The results of the fit """ # Initialize lmfit Params object initialParams = lmfit.Parameters() #TODO: Do something so that duplicate param names can all be handled (e.g. two Polynomail models with c0). Perhaps append something to the parameter name like c0_1 and c0_2?) # Concatenate the lists of parameters all_params = [i for j in [model.components[n].parameters.list for n in range(len(model.components))] for i in j] # Group the different variable types param_list = [] indep_vars = {} for param in all_params: param = list(param) if param[2] == 'free': param[2] = True param_list.append(tuple(param)) elif param[2] == 'fixed': param[2] = False param_list.append(tuple(param)) else: indep_vars[param[0]] = param[1] # Add the time as an independent variable indep_vars['time'] = time # Get values from input parameters.Parameters instances initialParams.add_many(*param_list) # Create the lightcurve model lcmodel = lmfit.Model(model.eval) lcmodel.independent_vars = indep_vars.keys() # Set the uncertainty if uncertainty is None: uncertainty = np.ones(len(data)) # Fit light curve model to the simulated data result = lcmodel.fit(data, weights=1/uncertainty, params=initialParams, **indep_vars, **kwargs) if verbose: print(result.fit_report()) # Get the best fit params fit_params = result.__dict__['params'] new_params = [(fit_params.get(i).name, fit_params.get(i).value, fit_params.get(i).vary, fit_params.get(i).min, fit_params.get(i).max) for i in fit_params] # Create new model with best fit parameters params = Parameters() # Try to store each as an attribute for param in new_params: setattr(params, param[0], param[1:]) # Make a new model instance best_model = copy.copy(model) best_model.parameters = params best_model.name = ', '.join(['{}:{}'.format(k, round(v[0], 2)) for k, v in params.dict.items()]) return best_model