"""Base and child classes to handle orbital parameters
Author: Joe Filippazzo
Email: jfilippazzo@stsci.edu
"""
import os
import json
import numpy as np
[docs]class Parameter:
"""A generic parameter class"""
def __init__(self, name, value, ptype='free', mn=None, mx=None):
"""Instantiate a Parameter with a name and value at least
Parameters
----------
name: str
The name of the parameter
value: float, int, str, list, tuple
The value of the parameter
ptype: str
Parameter type, ['free','fixed','independent']
mn: float, int, str, list, tuple (optioal)
The minimum value
mx: float, int, str, list, tuple (optioal)
The maximim value
"""
# If value is a list, distribute the elements
if isinstance(value, tuple):
value, *other = value
if len(other) > 1:
ptype, *other = other
if len(other) > 0:
mn, mx = other
# Set the attributes
self.name = name
self.value = value
self.mn = mn
self.mx = mx
self.ptype = ptype
@property
def ptype(self):
"""Getter for the ptype"""
return self._ptype
@ptype.setter
def ptype(self, param_type):
"""Setter for ptype
Parameters
----------
param_type: str
Parameter type, ['free','fixed','independent']
"""
if param_type not in ['free', 'fixed', 'independent', True, False]:
raise ValueError("ptype must be 'free','fixed', or 'independent'")
if param_type is True:
param_type = 'free'
if param_type is False:
param_type = 'fixed'
self._ptype = param_type
@property
def values(self):
"""Return all values for this parameter"""
vals = self.name, self.value, self.ptype, self.mn, self.mx
return tuple(filter(lambda x: x is not None, vals))
[docs]class Parameters:
"""A class to hold the Parameter instances
"""
def __init__(self, param_file=None, **kwargs):
"""Initialize the parameter object
Parameters
----------
param_file: str
A text file of the parameters to parse
Example
-------
params = lightcurve.Parameters(a=20, ecc=0.1, inc=89,
limb_dark='quadratic')
"""
self.__dict__['list'] = []
self.__dict__['dict'] = {}
# Make an empty params dict
params = {}
# If a param_file is given, make sure it exists
if param_file is not None and os.path.exists(param_file):
# Parse the ASCII file
if param_file.endswith('.txt'):
# Add the params to a dict
data = np.genfromtxt(param_file)
params = {i: j for i, j in data}
# Parse the JSON file
elif param_file.endswith('.json'):
with open(param_file) as json_data:
params = json.load(json_data)
# Add any kwargs to the parameter dict
params.update(kwargs)
# Try to store each as an attribute
for param, value in params.items():
setattr(self, param, value)
def __add__(self, other):
"""Add parameters to make a combined model
Parameters
----------
other: ExoCTK.lightcurve_fitting.parameters.Parameters
The parameters to to multiply
Returns
-------
ExoCTK.lightcurve_fitting.parameters.Parameters
The combined model
"""
# Make sure it is the right type
if not type(self) == type(other):
raise TypeError('Only another Parameters instance may be multiplied.')
# Combine the model parameters too
kwargs = self.dict
kwargs.update(other.dict)
newParams = Parameters(**kwargs)
return newParams
def __setattr__(self, item, value):
"""Maps attributes to values
Parameters
----------
item: str
The name for the attribute
value: any
The attribute value
"""
# Convert single items to tuple
if isinstance(value, (str, float, int, bool)):
value = (value,)
# Convert list to tuple
if isinstance(value, list):
value = tuple(value)
if not isinstance(value, tuple):
raise TypeError("Cannot set {}={}.".format(item, value))
# Set the attribute
self.__dict__[item] = Parameter(item, *value)
# Add it to the list of parameters
self.__dict__['list'].append(self.__dict__[item].values)
self.__dict__['dict'][item] = self.__dict__[item].values[1:]