-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathmodel.py
More file actions
103 lines (83 loc) · 2.93 KB
/
model.py
File metadata and controls
103 lines (83 loc) · 2.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
from abc import ABCMeta, abstractmethod
import numpy as np
import copy
class Model():
"""Base (abstract) class for complex models to be fit with emcee.
Attributes:
attr1 (type): description, fill these in when we know what they are"""
__metaclass__ = ABCMeta
def __init__(self,plist):
"""Initialise model.
Args:
plist (list): List of mcmc_utils.Param objects"""
self.plist = copy.copy(plist)
@property
def lookuptable(self):
"""Get lookup table for model
A lookup table maps between the model VARIABLE parameters and their names"""
return [p.name for p in self.plist if p.isVar]
@property
def npars(self):
"""Number of parameters"""
return len(self.pars)
@property
def pars(self):
"""Model parameters.
This is a list of the Param objects of all the model's variable parameters.
The setter will update the *current values* of all variable parameters from
a list of new values."""
return [p for p in self.plist if p.isVar]
@pars.setter
def pars(self,value_list):
"""Gets list of all variable parameters and updates current values.
The current values of the variable parameters obtained from the list are
updated with those from a new list of variable parameters."""
variable_params = [p for p in self.plist if p.isVar]
for i, val in enumerate(value_list):
variable_params[i].currVal = val
def ln_prior(self):
"""Return the natural log of the prior probability of this model.
If model has more prior information not captured in the priors of
the parameters, the details of such additional prior information must
also be included here."""
lnp = 0.0
for param in self.pars:
lnp += param.prior.ln_prob(param.currVal)
return lnp
@abstractmethod
def ln_like(self):
"""Calculate the natural log of the likelihood"""
pass
@abstractmethod
def ln_prob(self):
"""Calculate the natural log of the posterior probability"""
pass
def getIndex(self,name):
"""Gets index (e.g. position in list) of a parameter"""
names = [p.name for p in self.plist]
return names.index(name)
def getValue(self,name):
"""Gets current value of a parameter"""
return self.plist[self.getIndex(name)].currVal
def getParam(self,name):
"""Gets object(?) of a parameter"""
return self.plist[self.getIndex(name)]
class CrapCV(Model):
"""A totally useless model just for illustration purposes"""
def __init__(self,plist,complex):
"""CVs need to know whether or not to use a complex BS"""
#Model.__init__(plist) # this works poorly with multiple inheritance apparently
super(CrapCV,self).__init__(plist)
self.complex = True
def ln_like(self,pars):
return 100
def ln_prob(self,pars):
return self.ln_like(pars)+self.ln_prior(pars)
def ln_prior(self):
"""This is how you would implement a custom ln_prior"""
lnp = 0.0
lnp += super(CrapCV,self).ln_prior()
# cases where az > q are not allowed
if self.getValue('az') > self.getValue('q'):
lnp += -np.inf
return lnp