7
7
from __future__ import with_statement
10
import pickle, warnings
8
12
from cogent.core.tree import TreeError
9
13
from cogent.evolve import likelihood_calculation
10
14
from cogent.align import dp_calculation
11
15
from cogent.evolve.likelihood_function import LikelihoodFunction as _LF
12
16
from cogent.recalculation.scope import _indexed
17
from cogent.maths.stats.information_criteria import aic, bic
17
20
from cogent.align.pairwise import AlignableSeq
21
from cogent.util.warning import discontinued
19
__author__ = "Andrew Butterfield"
23
__author__ = "Peter Maxwell"
20
24
__copyright__ = "Copyright 2007-2009, The Cogent Project"
21
25
__credits__ = ["Andrew Butterfield", "Peter Maxwell", "Gavin Huttley",
23
27
__license__ = "GPL"
25
29
__maintainer__ = "Gavin Huttley"
26
30
__email__ = "gavin.huttley@anu.ed.au"
27
31
__status__ = "Production"
64
68
self.motifs = self._motifs = model.getMotifs()
65
69
self._mprob_motifs = list(model.getMprobAlphabet())
66
70
defn = self.makeLikelihoodDefn(**kw)
67
self.real_par_controller = defn.makeParamController()
71
super(_LF, self).__init__(defn)
68
72
self.setDefaultParamRules()
69
73
self.setDefaultTreeParameterRules()
70
74
self.mprobs_from_alignment = motif_probs_from_align
76
80
f = open(filename, 'w')
79
for d in self.real_par_controller.defns:
80
84
temp[id(d)] = d.values
82
86
pickle.dump((1.0, None, self), f)
84
for d in self.real_par_controller.defns:
86
90
d.values = temp[id(d)]
88
def updateIntermediateValues(self):
89
self.real_par_controller.update()
91
def optimise(self, *args, **kw):
92
return_calculator = kw.pop('return_calculator', False)
93
lc = self.real_par_controller.makeCalculator()
94
lc.optimise(*args, **kw)
95
self.real_par_controller.updateFromCalculator(lc)
99
def graphviz(self, **kw):
100
lc = self.real_par_controller.makeCalculator()
101
return lc.graphviz(**kw)
104
return repr(self.real_par_controller)
106
92
def setDefaultTreeParameterRules(self):
107
93
"""Lengths are set to the values found in the tree (if any), and
108
94
free to be optimised independently.
109
95
Other parameters are scoped based on the unique values found in the
110
96
tree (if any) or default to having one value shared across the whole
112
with self.real_par_controller.updatesPostponed():
98
with self.updatesPostponed():
113
99
edges = self.tree.getEdgeVector()
114
100
for par_name in self.model.getParamList():
157
143
assert expm in ['pade', 'either', 'eigen', 'checked'], expm
158
144
self.setParamRule('expm', is_const=True, value=expm)
160
def makeCalculator(self, aligns):
162
self.setAlignment(aligns)
163
if getattr(self, 'used_as_calculator', False):
164
warnings.warn('PC used as two different calculators', stacklevel=2)
165
self.used_as_calculator = True
146
def makeCalculator(self, *args, **kw):
148
discontinued('method', "makeCalculator(aligns)", '1.6')
149
# and shadowing a quite different superclass method.
150
self.setAlignment(*args)
151
if getattr(self, 'used_as_calculator', False):
152
warnings.warn('PC used as two different calculators', stacklevel=2)
153
self.used_as_calculator = True
156
return super(_LF, self).makeCalculator(**kw)
168
158
def _process_scope_info(self, edge=None, tip_names=None, edges=None,
169
159
is_clade=None, is_stem=None, outgroup_name=None):
250
240
elif init is not None:
253
self.real_par_controller.assignAll(par_name, scopes, value, lower,
254
upper, is_const, is_independent)
243
self.assignAll(par_name, scopes, value, lower, upper, is_const,
256
246
def setLocalClock(self, tip1name, tip2name):
257
247
"""Constrain branch lengths for tip1name and tip2name to be equal.
278
with self.real_par_controller.updatesPostponed():
268
with self.updatesPostponed():
279
269
for edge in tree.getEdgeVector():
280
270
if edge.Length is None or edge.Name in exclude_list:
282
272
self.setParamRule("length", edge=edge.Name, is_const=1,
283
273
value=edge.Length)
275
def getAic(self, second_order=False):
276
"""returns Aikake Information Criteria
279
- second_order: if true, the second-order AIC is returned,
280
adjusted by the alignment length"""
282
sequence_length = sum(len(self.getParamValue('lht', locus=l).index)
283
for l in self.locus_names)
285
sequence_length = None
287
lnL = self.getLogLikelihood()
288
nfp = self.getNumFreeParams()
289
return aic(lnL, nfp, sequence_length)
292
"""returns the Bayesian Information Criteria"""
293
sequence_length = sum(len(self.getParamValue('lht', locus=l).index)
294
for l in self.locus_names)
295
lnL = self.getLogLikelihood()
296
nfp = self.getNumFreeParams()
297
return bic(lnL, nfp, sequence_length)
286
299
class AlignmentLikelihoodFunction(_LikelihoodParameterController):
288
301
def setDefaultParamRules(self):
290
self.real_par_controller.assignAll(
291
304
'fixed_motif', None, value=-1, const=True, independent=True)
295
def makeLikelihoodDefn(self, sites_independent=True):
296
defns = self.model.makeParamControllerDefns(
297
bin_names=self.bin_names)
308
def makeLikelihoodDefn(self, sites_independent=True, discrete_edges=None):
309
defns = self.model.makeParamControllerDefns(bin_names=self.bin_names)
310
if discrete_edges is not None:
311
from discrete_markov import PartialyDiscretePsubsDefn
312
defns['psubs'] = PartialyDiscretePsubsDefn(
313
self.motifs, defns['psubs'], discrete_edges)
298
314
return likelihood_calculation.makeTotalLogLikelihoodDefn(
299
315
self.tree, defns['align'], defns['psubs'], defns['word_probs'],
300
316
defns['bprobs'], self.bin_names, self.locus_names,
316
332
(self.tree.getTipNames(), aln.getSeqNames(),
318
334
assert not "root" in aln.getSeqNames(), "'root' is a reserved name."
319
with self.real_par_controller.updatesPostponed():
335
with self.updatesPostponed():
320
336
for (locus_name, align) in zip(self.locus_names, aligns):
321
self.real_par_controller.assignAll(
322
338
'alignment', {'locus':[locus_name]},
323
339
value=align, const=True)
324
340
if self.mprobs_from_alignment:
352
368
self.setPogs(leaves, locus=locus)
354
370
def setPogs(self, leaves, locus=None):
355
with self.real_par_controller.updatesPostponed():
371
with self.updatesPostponed():
356
372
for (name, pog) in leaves.items():
357
373
self.setParamRule('leaf', edge=name, value=pog, is_const=True)
358
374
if self.mprobs_from_alignment: