1 package org
.modiphy
.math
2 import EnhancedMatrix
._
3 import org
.modiphy
.tree
._
4 import org
.modiphy
.tree
.DataParse
.Tree
5 import org
.modiphy
.sequence
._
6 import scala
.collection
.immutable
.{Map
,IntMap
}
7 import scala
.actors
.Actor
8 import scala
.actors
.Actor
._
9 import scala
.actors
.OutputChannel
12 object ParamScheduler
extends scala
.actors
.scheduler
.ForkJoinScheduler(10,400,true,false)
14 trait ParamActor
extends Actor
{
15 override def scheduler
= ParamScheduler
17 abstract class ActorModelComponent
extends ParamActor
with Logging
19 trait SimpleActorModelComponent
extends ActorModelComponent
{
20 def params
:List
[ActorParamComponent
]
21 def rec1
:Option
[Actor
]
22 lazy val numParams
= params
.length
23 lazy val paramNames
=params
.map
{_
.name
}
24 lazy val pActorMap
=paramNames
.zip(params
).foldLeft(Map
[ParamName
,ActorParamComponent
]()){_
+_
}
25 var pMap
:Map
[ParamName
,ParamChanged
[_
]]=null
27 debug
{"Setup start" + this}
32 var x
= (p
!?
(4000,RequestParam
))
35 x
= (p
!?
(4000,RequestParam
))
38 }.map
{_
.asInstanceOf
[ParamChanged
[_
]]}.map
{p
=>(p
.name
,p
)}.foldLeft(Map
[ParamName
,ParamChanged
[_
]]()){_
+_
}
39 pMap
.map
{_
._2
}.foreach
{updateParam
}
40 if (rec1
.isDefined
){rec1
.get
.start
}
41 debug
{"Setup " + this}
46 react
{myHandler
.orElse
{
51 println(self
+ " received unexpected message" + a
)
57 def matReq
[A
<: BioEnum
](m
:MatReq
[A
]):MatReq
[A
]
58 def updateParam(p
:ParamChanged
[_
])
60 def sendUnclean(p
:ParamName
)={
61 if (rec1
.isDefined
){ rec1
.get forward
Unclean(pActorMap(p
))}
62 else {reply(Unclean(pActorMap(p
)))}
65 called when a downstream component has a parameter changed
68 def myHandler
= handlers
71 val mainHandler
:PartialFunction
[Any
,Unit
]={
72 case m
:QMatReq
[BioEnum
]=>
73 val ans
= matReq(m
.toMatReq
).toQMatReq
78 case m
:MatReq
[BioEnum
]=>
80 if (rec1
.isDefined
){rec1
.get forward ans
}
84 if (rec1
.isDefined
){rec1
.get forward
Unclean(a
)}
85 else {reply(Unclean(a
))}
89 case ParamChanged(`p`
,param
)=>
91 updateParam(ParamChanged(`p`
,param
))
92 }:PartialFunction
[Any
,Unit
]
93 }.foldLeft(mainHandler
){_ orElse _
}
96 def problem(s
:String
)={
103 sealed trait NMessage
{
107 case class SwitchingRate(val n
:Int
) extends NMessage
111 case class Params(list
:List
[ActorParamComponent
])
112 object GetParams
extends Params(Nil
)
113 class MatBuilder(m
:Option
[Map
[Node
[_
],Matrix
]])
114 case class Unclean(sender
:Actor
)
115 case object RequestOpt
117 sealed trait ParamName
118 trait ConcreteParamName
extends ParamName
{
121 case class Pi(i
:Int
) extends ConcreteParamName
122 case class S(i
:Int
) extends ConcreteParamName
123 case class BranchLengths(i
:Int
) extends ConcreteParamName
124 case class Alpha(i
:Int
) extends ConcreteParamName
125 case class InvarPrior(i
:Int
) extends ConcreteParamName
126 case class Sigma(i
:Int
) extends ConcreteParamName
127 case class SingleParam(p
:ParamName
) extends ParamName
128 case class JoinedParam(p
:List
[ParamName
]) extends ParamName
131 trait ParamMatcher
extends ParamName
{
132 def matches(p2
:ParamName
):Boolean
134 case class All(p
:ConcreteParamName
) extends ParamMatcher
{
135 def matches(p2
:ParamName
)={
136 p2
!=null && (p2
.getClass
==p
.getClass
)
139 case class AllMatches(p
:ConcreteParamName
,f
:Int
=>Boolean
) extends ParamMatcher
{
140 def matches(p2
:ParamName
)={
141 p2
!=null && (p2
.getClass
==p
.getClass
) && f(p2
.asInstanceOf
[ConcreteParamName
].i
)
144 //This doesn't seem ideal and may be improved...
145 case class AllSingle(p
:ConcreteParamName
) extends ParamMatcher
{
146 def matches(p2
:ParamName
)={
147 p2
!=null && (p2
.getClass
==p
.getClass
)
152 type PFact
={def apply(i
:Int
):ConcreteParamName
}
153 implicit def lazymaker(p
:PFact
)=p(0)
156 case class ParamUpdate
[A
](d
:A
)
157 case class ParamChanged
[A
](name
:ParamName
,param
:A
){
158 def toParamUpdate
= ParamUpdate(param
)
166 Optimiser may have different view of params (log of real params, for example)
168 case class OptUpdate(d
:Array
[Double
])
170 class BasicActorModel(piParam
:ActorPiComponent
,sParam
:ActorSComponent
,rec
:Actor
) extends ActorModelComponent
with SimpleActorModelComponent
{
171 val params
= piParam
:: sParam
:: Nil
172 val piName
= piParam
.name
173 val sName
= sParam
.name
176 var sMat
:Matrix
= null
177 var mat
:Option
[Matrix
]=None
178 def updateParam(p
:ParamChanged
[_
]){
180 case ParamChanged(`piName`
,v
:Vector
)=>
183 case ParamChanged(`sName`
,m
:Matrix
) =>
188 def unclean
{mat
=None
}
189 def matReq
[A
<: BioEnum
](m
:MatReq
[A
])={
190 val myMat
= if (mat
.isDefined
){
193 mat
= Some(sMat
.sToQ(pi
))
196 MatReq(m
.n
,Some(myMat
),Some(pi
))
199 class NormaliserActorModel(rec
:Actor
) extends SimpleActorModelComponent
{
202 var mat
:Option
[Matrix
]=None
203 def updateParam(p
:ParamChanged
[_
]){
205 def unclean
{mat
=None
}
206 def matReq
[A
<: BioEnum
](m
:MatReq
[A
])={
210 mat
= Some(m
.m
.get
.normalize(m
.pi
.get
))
216 class THMMActorModel(sigmaParam
:ActorFullSComponent
,numClasses
:Int
,rec
:Actor
) extends SimpleActorModelComponent
{
217 val sigmaName
= sigmaParam
.name
218 val params
= sigmaParam
:: Nil
220 var mat
:Option
[Matrix
]=None
221 var switchingRate
:Option
[Double
]=None
222 var sigma
:Matrix
= null
223 def updateParam(p
:ParamChanged
[_
]){
225 case ParamChanged(`sigmaName`
,m
:Matrix
)=>
230 def unclean
{ mat
=None
}
232 pi must be the new length, m is pi.length - numAA
234 def applyMat(m
:Matrix
,pi
:Vector
,sigma
:Matrix
):(Matrix
,Double
)={
236 val numAlpha
= m
.rows
/ numClasses
238 for (i
<- 0 until numClasses
){
239 for (j
<- i
+1 until numClasses
){
240 for (x
<- 0 until numAlpha
){
241 qStart(i
* numAlpha
+ x
, j
* numAlpha
+ x
) = sigma(i
,j
) * pi(j
* numAlpha
+ x
) // i->j transition
242 qStart(j
* numAlpha
+ x
, i
* numAlpha
+ x
) = sigma(i
,j
) * pi(i
* numAlpha
+ x
) // j->i transition
243 switching
= switching
+ sigma(i
,j
) * pi(j
* numAlpha
+ x
) * pi(i
* numAlpha
+ x
) * 2
251 def matReq
[A
<: BioEnum
](m
:MatReq
[A
])={
253 case MatReq(n
,Some(m
),Some(pi
))=>
254 if (mat
.isDefined
){mat
}
256 val (myMat
,switch) = applyMat(m
,pi
,sigma
)
258 switchingRate
=Some(switch)
260 MatReq(n
,mat
,Some(pi
))
262 problem(m
+ " is not defined")
266 override def myHandler
= {
267 val h
:PartialFunction
[Any
,Unit
]={
268 case SwitchingRate(n
) =>
271 h
orElse (super.myHandler
)
279 class InvarActorModel(priorParam
:ActorProbComponent
,piParam
:ActorPiComponent
,numClasses
:Int
,rec
:Actor
) extends SimpleActorModelComponent
{
280 val priorName
=priorParam
.name
281 val piName
= piParam
.name
282 val params
= priorParam
:: piParam
:: Nil
284 var processedPi
:Option
[Vector
]=None
285 var mat
:Option
[Matrix
]=None
286 var prior
:Double
= 0.0D
289 def updateParam(p
:ParamChanged
[_
]){
291 case ParamChanged(`priorName`
,d
:Double
)=>
294 case ParamChanged(`piName`
,v
:Vector
)=>
304 pi must be the new length, m is pi.length - numAA
306 def applyMat(m
:Matrix
,pi
:Vector
):Matrix
={
307 val newMatSize
= pi
.size
308 val mat
= Matrix(newMatSize
,newMatSize
)
309 mat
.viewPart(0,0,m
.rows
,m
.rows
).assign(m
)
312 def applyPi(oldPi
:Vector
):Vector
={
313 val newPi
= Vector(oldPi
.size
+ pi
.size
)
314 newPi
.viewPart(0,oldPi
.size
).assign(oldPi
* (1.0D
-prior
))
315 newPi
.viewPart(oldPi
.size
,pi
.size
).assign(pi
* prior
)
319 def matReq
[A
<: BioEnum
](m
:MatReq
[A
])={
321 case MatReq(n
,Some(m
),Some(p
))=>
322 val myPi
= if (processedPi
.isDefined
){
325 processedPi
=Some(applyPi(p
))
328 val myMat
= if (mat
.isDefined
){
331 mat
= Some(applyMat(m
,myPi
))
334 MatReq(n
,mat
,processedPi
)
336 problem(m
+ " not completely defined")
342 class GammaActorModel(shape
:ActorGammaComponent
,numClasses
:Int
,rec
:Actor
) extends SimpleActorModelComponent
{
344 val shapeName
= shape
.name
345 val params
= shape
:: Nil
346 val gamma
= new Gamma(numClasses
)
348 var mat
:Option
[Matrix
] = None
349 var processedPi
:Option
[Vector
] = None
351 def applyMat(m
:Matrix
,alpha
:Double
,pi
:Vector
):Matrix
={
353 debug
{"GAMMA " + alpha
+ " " + r
.mkString(" ")}
354 val myMat
= Matrix(m
.rows
*numClasses
,m
.columns
* numClasses
)
355 val numAlpha
= m
.rows
356 (0 until numClasses
).foreach
{i
=>
357 myMat
.viewPart(i
* numAlpha
,i
* numAlpha
,numAlpha
,numAlpha
).assign(m
) * r(i
)
362 def matReq
[A
<: BioEnum
](m
:MatReq
[A
])=m
match{
363 case MatReq(n
,Some(m
),Some(p
)) =>
365 mat
= Some(applyMat(m
,alpha
,p
))
367 if (processedPi
.isEmpty
){
368 processedPi
= Some(applyPi(p
))
370 MatReq(n
,mat
,processedPi
)
372 problem("Unfilled " + m
)
380 def updateParam(p
:ParamChanged
[_
]){
382 case ParamChanged(`shapeName`
,d
:Double
) =>
388 def applyPi(pi
:Vector
):Vector
={
389 val numAlpha
= pi
.size
390 val myPi
= Vector(numAlpha
* numClasses
)
391 val postVals
= pi
/ numClasses
.toDouble
392 (0 until numClasses
).foreach
{i
=>
393 myPi
.viewPart(i
*numAlpha
,numAlpha
).assign(postVals
)
399 class ForkActor
[A
<: BioEnum
](tree
:Tree
[A
],rec1Map
:Map
[Int
,Actor
]) extends ActorModelComponent
{
400 val rec
= rec1Map
.values
.toList
.removeDuplicates
401 val numRec
= rec
.length
403 rec1Map
.values
.foreach
{v
=>
416 getListReplies(sender
,numRec
,Nil
)
417 case Unclean(a
:ActorParamComponent
) =>
422 case QMatReq(n
,m
,p
)=>
423 if (rec1Map contains n
.id
){
424 rec1Map(n
.id
) forward
QMatReq(n
,m
,p
)
426 warning
{"Map does not contain " + n
.id
+ " " + n
}
427 sender
! QMatReq(n
,m
,p
)
430 if(rec1Map contains n
.id
){
431 rec1Map(n
.id
) forward
MatReq(n
,m
,p
)
433 if (! n
.isRoot
){warning
{"Map does not contain " + n
.id
+ " " + n
}}
434 sender
! MatReq(n
,m
,p
)
437 if (rec1Map contains m
.n
){
438 rec1Map(m
.n
) forward m
440 println(self
+ " received unexpected message " + m
)
443 println(self
+ " received unexpected message " + a
)
448 def getListReplies(output
:OutputChannel
[Any
],toDo
:Int
,l
:List
[ActorParamComponent
]){
455 getListReplies(output
,toDo
-1,l2
++l
)
459 def getCleanReplies(output:Actor,toDo:Int,me:Actor){
461 output ! Unclean(output)
465 case Unclean(`me`) =>
466 getCleanReplies(output,toDo-1,me)
473 class BasicSingleExpActorModel
[A
<: BioEnum
](tree
:Tree
[A
],branchLengthParams
:ActorTreeComponent
[A
],rec1
:Option
[Actor
]) extends ActorModelComponent
{
474 val blName
= branchLengthParams
.name
475 val nodes
= tree
.descendentNodes
.toArray
//root has no length
478 branchLengthParams addActor
this
479 if (rec1
.isDefined
){rec1
.get
.start
}
482 var eigen
:MatrixExponential
=null
485 main(None
,nodes
.foldLeft(Map
[Int
,Double
]()){(m
,n
)=>m
+((n
.id
,n
.lengthTo
))})
487 def main(eigen
:Option
[MatrixExponential
],lengths
:Map
[Int
,Double
]){
488 case class ExpReq
[A
<: BioEnum
](n
:Node
[A
],e
:MatrixExponential
,lengthTo
:Double
,pi
:Vector
)
493 case MatReq(n
,Some(m
),Some(pi
)) =>
494 if (n
.isRoot
){//don't need exp(qt)
495 if (rec1
.isDefined
){rec1
.get forward
MatReq(n
,None
,Some(pi
))}
496 else { sender
! MatReq(n
,None
,Some(pi
))}
499 val myEigen
= if (eigen
.isEmpty
){
500 val ans
= new MatExpNormal(m
,pi
,None
)
508 case ExpReq(n
,e
,lengthTo
,pi
)=>
509 val ans
= e
.exp(lengthTo
)
510 if (rec1
.isDefined
){rec1
.get forward
MatReq(n
,Some(ans
),Some(pi
))}
511 else { sender
! MatReq(n
,Some(ans
),Some(pi
)) }
515 }.start forward
ExpReq(n
,myEigen
,lengths(n
.id
),pi
)
516 main(Some(myEigen
),lengths
)
518 if (rec1
.isDefined
){rec1
.get forward
Unclean(a
)} else {
522 case ParamChanged(`blName`
,a
:Array
[Double
])=>
523 if (rec1
.isDefined
){rec1
.get forward
Unclean(branchLengthParams
)} else {reply(Unclean(branchLengthParams
))}
524 val nodeMap
= nodes
.zip(a
).foldLeft(Map
[Int
,Double
]()){(m
,t
)=>m
+ ((t
._1
.id
,t
._2
))}
530 trait ActorParamComponent
extends ParamActor
{
532 var modelComp
:List
[Actor
]=Nil
533 def addActor(l
:Actor
){
534 modelComp
= l
::modelComp
539 case class SingleParamWrapper(p
:ActorParamComponent
) extends ActorParamComponent
{
541 val name
= SingleParam(p
.name
)
543 val mainParam
= (p
!? RequestOpt
).asInstanceOf
[Array
[Double
]]
544 main(Array
.make(mainParam
.length
,mainParam(0)))
546 def lower
= (p
!? Lower
).asInstanceOf
[Array
[Double
]](0)
547 def upper
= (p
!? Upper
).asInstanceOf
[Array
[Double
]](0)
549 def main(param
:Array
[Double
]){
552 reply(ParamChanged(name
,param(0)))
554 case ParamUpdate(x
:Array
[Double
])=>
555 val newParam
= Array
.make(param
.length
,x(0))
556 p forward
OptUpdate(newParam
)
558 case OptUpdate(x
:Array
[Double
]) =>
559 val newParam
= Array
.make(param
.length
,x(0))
560 p forward
OptUpdate(newParam
)
563 reply(Array(param(0)))
576 object JoinedParamWrapper
{
577 def apply(pList
:List
[ActorParamComponent
])={
578 val x
= new JoinedParamWrapper(pList
)
583 class JoinedParamWrapper
private(pList
:List
[ActorParamComponent
]) extends ActorParamComponent
{
584 override def start
={
587 val name
= JoinedParam(pList
.map
{_
.name
})
588 lazy val paramArray
=getParam2D
.toArray
589 lazy val numParams
=paramArray
.map
{_
.size
}
590 def getParam2D
= pList
.map
{p
=>(p
!? RequestOpt
).asInstanceOf
[Array
[Double
]]}
591 def flatten(a
:Array
[Array
[Double
]]):Array
[Double
]={
594 def flatten(a
:List
[Array
[Double
]]):Array
[Double
]={
595 //jeez this is lazy - but it probably isn't going to slow things down too much
596 a
.map
{_
.toList
}.flatten
[Double
].toArray
598 def setParam(from
:Array
[Double
],to
:Array
[Array
[Double
]])={
599 val iter
= from
.elements
600 for (i
<-0 until to
.length
){
601 for (j
<-0 until
to(i
).length
){
606 lazy val lower
= pList
.map
{p
=>(p
!? Lower
).asInstanceOf
[Array
[Double
]].toList
}.flatten
[Double
].toArray
607 lazy val upper
= pList
.map
{p
=>(p
!? Upper
).asInstanceOf
[Array
[Double
]].toList
}.flatten
[Double
].toArray
612 reply(ParamChanged(name
,flatten(getParam2D
)))
613 case ParamUpdate(x
:Array
[Double
])=>
614 val to
= paramArray
.map
{i
=>new Array
[Double
](i
.size
)}.toArray
616 pList
.elements
.zip(to
.elements
).foreach
{t
=>
617 val (pActor
,pArray
)=t
618 pActor forward
OptUpdate(pArray
)
620 case OptUpdate(x
:Array
[Double
]) =>
621 val to
= paramArray
.map
{i
=>new Array
[Double
](i
.size
)}
623 pList
.elements
.zip(to
.elements
).foreach
{t
=>
624 val (pActor
,pArray
)=t
625 pActor forward
OptUpdate(pArray
)
628 reply(flatten(getParam2D
))
637 case class JoinedParamWrapper(p:List[ActorParamComponent]) extends ActorParamComponent{
639 val name = JoinedParam(p)
641 val current = p.map{p2 => (p2 !? RequestOpt).asInstanceOf[Array[Double]].toList}.flatten[Double].toArray
646 case class ReadSerial(x
:Seq
[Double
])
647 case object WriteSerial
649 abstract class AbstractActorParam
[A
] extends ActorParamComponent
with Logging
{
650 override def !?
(msg
:Any
)={
651 debug
{this + " !? "+ msg
}
652 val ans
= super.!?
(msg
)
653 debug
{this + " finished" }
658 def getParams
:Array
[Double
]
659 def setParams(a
:Array
[Double
]):Unit
663 override def toString
={
664 name
.toString
+ " = " + internal
.getParams
.toList
.mkString(",")
667 def readSerial(x
:Seq
[Double
])=internal setParams x
.toArray
668 def writeSerial
:Seq
[Double
]=internal
.getParams
672 def lowerArray
= Array
.make(internal
.getParams
.length
,lower
)
673 def upperArray
= Array
.make(internal
.getParams
.length
,upper
)
674 //override this if raw params are different!
675 def setRaw(p
:Array
[Double
]){internal setParams p
}
676 /*def waitOn(i:Int,o:OutputChannel[Any]){
677 finest{super.toString + " WAITING ON " + i + ":::" + this}
689 private val myHandler
:PartialFunction
[Any
,Unit
] = {
691 reply(ParamChanged(name
,myParam
))
692 case ParamUpdate(x
:Array
[Double
])=>
694 modelComp
.foreach
{c
=>
695 c
!?
ParamChanged(name
,myParam
)
698 // waitOn(modelComp.length,sender)
699 case ParamUpdate(v:Vector)=>
700 debug{"ParamUpdate 1"}
702 debug{"ParamUpdate 2"}
703 modelComp.foreach{c=>
704 debug{"ParamUpdate c"}
705 c !? ParamChanged(name,myParam)
707 debug{"ParamUpdate 3"}
711 modelComp
.foreach
{c
=>
712 c
!?
ParamChanged(name
,myParam
)
716 reply(internal.getParams)
721 case ReadSerial(s) =>
727 def handler
:PartialFunction
[Any
,Unit
]= {
737 class ActorPiComponent(pi
:Vector
,val name
:ParamName
) extends AbstractActorParam
[Vector
]{
739 override def handler
:PartialFunction
[Any
,Unit
]={
744 class PiParam(pi
:Vector
){
747 def fromFit(array
:Array
[Double
],medianIndex
:Int
)={
748 val exponentiated
= array
.map
{i
=>Math
.exp(i
)}
749 val total
= (0.0D
/: exponentiated
){_
+_
} + Math
.exp(0.0D
)
750 ((0 to medianIndex
-1 ).map
{i
=> exponentiated(i
)/total
}.toList
++ List(Math
.exp(0.0D
)/total
) ++ (medianIndex to array
.length
-1).map
{i
=> exponentiated(i
)/total
}).toArray
753 def toFit(pi
:Vector
):(List
[Double
],Int
)={
754 val t
= (pi
.toList
.zipWithIndex
.toList
.sort
{_
._1
<_
._1
})(pi
.size
/2)
756 def toFitness
={i
:Int
=>Math
.log(pi(i
)/pi(medianIndex
))}
757 ((0 to medianIndex
-1).map
{toFitness
}.toList
++ (medianIndex
+1 to pi
.size
-1).map
{toFitness
}.toList
,
761 def setParams(a
:Array
[Double
]){pi assign
fromFit(a
,medianIndex
)}
768 def setPi(p
:Array
[Double
]){pi assign p
}
772 val internal
= new PiParam(pi
)
774 def lower
= -10 // this is log-odds scaled prob
777 override def setRaw(p
:Array
[Double
]){
780 override def toString
=name
.toString
+ " = " + internal
.view
.toArray
.mkString(",")
781 override def writeSerial
= internal
.view
.toList
782 override def readSerial(x
:Seq
[Double
])=internal
.setPi(x
.toArray
)
784 class ActorSComponent(s
:Matrix
,val name
:ParamName
) extends AbstractActorParam
[Matrix
] with SMatUtil
{
785 class SMatParam(s
:Matrix
) extends SMatUtil
{
786 var cache
:Option
[Array
[Double
]]=None
787 def getParams
={ if (cache
.isEmpty
){cache
= Some(linearSMat(s
).toArray
)}; cache
.get
}
788 def setParams(a
:Array
[Double
]) = setSMat(a
,s
)
790 val internal
= new SMatParam(s
)
794 private val myHandler
:PartialFunction
[Any
,Unit
]={
795 case ParamUpdate(m
:Matrix
)=>
796 setRaw(linearSMatFull(m
).toArray
)
797 modelComp
.foreach
{c
=>
798 c
!?
ParamChanged(name
,myParam
)
800 //waitOn(modelComp.length,sender)
803 override def handler={
804 myHandler orElse (super.handler)
808 class ActorFullSComponent(s:Matrix,val name:ParamName) extends AbstractActorParam[Matrix] with SMatUtil{
809 class FullSMatParam(s:Matrix) extends SMatUtil{
810 var cache:Option[Array[Double]]=None
811 def getParams={ if (cache.isEmpty){cache = Some(linearSMatFull(s).toArray)}; cache.get}
812 def setParams(a:Array[Double]) = {setSMat(a,s);cache=None}
814 val internal = new FullSMatParam(s)
818 private val myHandler:PartialFunction[Any,Unit]={
820 reply(ParamChanged(name,myParam))
821 case ParamUpdate(m:Matrix)=>
822 setRaw(linearSMatFull(m).toArray)
823 modelComp.foreach{c=>
824 c !? ParamChanged(name,myParam)
826 //waitOn(modelComp.length,sender)
829 override def handler
={
830 myHandler
orElse (super.handler
)
835 class ActorTreeComponent
[B
<: BioEnum
](tree
:Tree
[B
],name
:ParamName
) extends ActorArrayComponent(tree
.getBranchLengths
.toArray
,name
,0.0,100.0)
836 class ActorDoubleComponent(param
:Double
,val name
:ParamName
,val lower
:Double
,val upper
:Double
) extends AbstractActorParam
[Double
]{
839 def getParams
=Array(myP
)
840 def setParams(a
:Array
[Double
]){myP
=a(0)}
842 val internal
= new DoubleParam
843 def myParam
= internal
.getParams(0)
845 private val myHandler
:PartialFunction
[Any
,Unit
]={
846 case ParamUpdate(x
:Double
)=>
848 modelComp
.foreach
{c
=>
849 c
!?
ParamChanged(name
,myParam
)
851 // waitOn(modelComp.length,sender)
854 override def handler={
855 myHandler orElse (super.handler)
858 class ActorArrayComponent(param:Array[Double],val name:ParamName,val lower:Double, val upper:Double) extends AbstractActorParam[Array[Double]]{
861 def getParams = myP.toArray
862 def setParams(a:Array[Double]){Array.copy(a,0,myP,0,Math.min(a.length,myP.length))}
864 val internal = new ArrayParam
865 def myParam = internal.getParams
867 class ActorProbComponent(prob:Double,name:ParamName,min:Double,max:Double) extends ActorDoubleComponent(prob,name,min,max){
868 def this(prob:Double,name:ParamName)=this(prob,name,0,0.9)
870 class ActorGammaComponent(alpha:Double,name:ParamName) extends ActorDoubleComponent(alpha,name,0.01,1000)
872 def apply[A <: BioEnum](tree:Tree[A])={
873 val pi = new ActorPiComponent(WAG.pi,Pi(0))
874 val s = new ActorSComponent(WAG.S,S(0))
875 val branchLength = new ActorTreeComponent(tree,BranchLengths(0))
876 val components = new BasicActorModel(pi,s, new NormaliserActorModel(new BasicSingleExpActorModel(tree,branchLength,None)))
877 val pList = List(pi,s,branchLength)
878 val pMap = pList.map{p => (p.name,p)}.foldLeft(Map[ParamName,ActorParamComponent]()){_+_}
879 new ActorModel(tree,components,pMap)
883 def apply[A <: BioEnum](tree:Tree[A])={
884 val pi = new ActorPiComponent(WAG.pi,Pi(0))
885 val s = new ActorSComponent(WAG.S,S(0))
886 val branchLength = new ActorTreeComponent(tree,BranchLengths(0))
887 val alpha = new ActorGammaComponent(0.5D,Alpha(0))
888 val components = new BasicActorModel(pi,s,
889 new GammaActorModel(alpha,tree.alphabet.numClasses,
890 new NormaliserActorModel(
891 new BasicSingleExpActorModel(tree,branchLength,None))))
892 val pList = List(pi,s,branchLength,alpha)
893 val pMap = pList.map{p => (p.name,p)}.foldLeft(Map[ParamName,ActorParamComponent]()){_+_}
894 new ActorModel(tree,components,pMap)
897 object InvarGammaModel{
898 def apply[A <: BioEnum](tree:Tree[A])={
899 val pi = new ActorPiComponent(WAG.pi,Pi(0))
900 val s = new ActorSComponent(WAG.S,S(0))
901 val branchLength = new ActorTreeComponent(tree,BranchLengths(0))
902 val alpha = new ActorGammaComponent(0.5D,Alpha(0))
903 val invarPrior = new ActorProbComponent(0.2D,InvarPrior(0))
904 val components = new BasicActorModel(pi,s,
905 new GammaActorModel(alpha,tree.alphabet.numClasses-1,
906 new InvarActorModel(invarPrior,pi,tree.alphabet.numClasses,
907 new NormaliserActorModel(
908 new BasicSingleExpActorModel(tree,branchLength,None)))))
909 val pList = List(pi,s,branchLength,alpha,invarPrior)
910 val pMap = pList.map{p => (p.name,p)}.foldLeft(Map[ParamName,ActorParamComponent]()){_+_}
911 new ActorModel(tree,components,pMap)
915 object InvarThmmModel{
916 def apply[A <: BioEnum](tree:Tree[A])={
917 val numClasses = tree.alphabet.numClasses
918 val pi = new ActorPiComponent(WAG.pi,Pi(0))
919 val s = new ActorSComponent(WAG.S,S(0))
920 val branchLength = new ActorTreeComponent(tree,BranchLengths(0))
921 val alpha = new ActorGammaComponent(0.5D,Alpha(0))
922 val invarPrior = new ActorProbComponent(0.2D,InvarPrior(0))
923 val sigma = new ActorFullSComponent(Matrix(numClasses,numClasses),Sigma(0))
924 val components = new BasicActorModel(pi,s,
925 new GammaActorModel(alpha,numClasses-1,
926 new InvarActorModel(invarPrior,pi,numClasses,
927 new NormaliserActorModel(
928 new THMMActorModel(sigma,numClasses,
929 new BasicSingleExpActorModel(tree,branchLength,None))))))
930 val pList = List(pi,s,branchLength,alpha,invarPrior,sigma)
931 val pMap = pList.map{p => (p.name,p)}.foldLeft(Map[ParamName,ActorParamComponent]()){_+_}
932 new ActorModel(tree,components,pMap)
936 object BranchSpecificThmmModel{
937 def apply[A <: BioEnum](tree:Tree[A]):ActorModel[A]={
938 val nodeMap=tree.descendentNodes.foldLeft[Map[Int,Int]](IntMap[Int]()){(m,n)=>
943 def apply[A <: BioEnum](tree:Tree[A],map:Map[Int,Int]):ActorModel[A]={
944 val numClasses = tree.alphabet.numClasses
945 val pi = new ActorPiComponent(WAG.pi,Pi(0))
946 val s = new ActorSComponent(WAG.S,S(0))
947 val branchLength = new ActorTreeComponent(tree,BranchLengths(0))
948 val alpha = new ActorGammaComponent(0.5D,Alpha(0))
949 val invarPrior = new ActorProbComponent(0.2D,InvarPrior(0))
950 var pList:List[ActorParamComponent] = List(pi,s,branchLength,alpha,invarPrior)
951 val modelNums = map.values.toList.removeDuplicates
952 val modelMapTmp = modelNums.map{a=>
953 val sigma = new ActorFullSComponent(Matrix(numClasses,numClasses),Sigma(a))
954 pList = sigma :: pList
955 val ans = new THMMActorModel(sigma,numClasses, new BasicSingleExpActorModel(tree,branchLength,None))
957 }.foldLeft[Map[Int,Actor]](IntMap[Actor]()){_+_}
959 val pMap = pList.map{p => (p.name,p)}.foldLeft(Map[ParamName,ActorParamComponent]()){_+_}
961 val modelMap = (map.keys).map{id=> (id,modelMapTmp(map(id)))}.foldLeft[Map[Int,Actor]](IntMap[Actor]()){_+_}
962 val components = new BasicActorModel(pi,s,
963 new GammaActorModel(alpha,numClasses-1,
964 new InvarActorModel(invarPrior,pi,numClasses,
965 new NormaliserActorModel(
966 new ForkActor(tree,modelMap)))))
970 new ActorModel(tree,components,pMap)
974 def apply[A <: BioEnum](tree:Tree[A],l:List[Int]):ActorModel[A]={
975 apply(tree,(tree::tree.descendentNodes).map{n => (n.id,if (l contains n.id){1}else{0})}.foldLeft(Map[Int,Int]()){_+_})
978 class BadParameterException(s:String) extends Exception(s)
981 def internal:ActorParamComponent
982 def update(x:Seq[Double]){
983 x.elements.zipWithIndex.foreach{t=>
988 def readSerial(x:Seq[Double]){internal !? ReadSerial(x)}
989 def writeSerial = {internal !? WriteSerial}.asInstanceOf[Seq[Double]]
990 def update(i:Int,x:Double) { throw new BadParameterException("Can't accept
1D parameter location
")}
991 def update(i:Int,j:Int,x:Double) { throw new BadParameterException("Can
't accept 2D parameter location")}
992 def apply(i:Int):Double = throw new BadParameterException("Can't accept
1D parameter location
")
993 def apply(i:Int,j:Int):Double = throw new BadParameterException("Can
't accept 2D parameter location")
994 def apply():Double = throw new BadParameterException("Can't accept
0D parameter location
")
995 def toList:List[Double]
996 def update(x:Double) { throw new BadParameterException("Can
't accept 0D parameter location")}
997 def <<[B](other:PSetter[B]){apply[B](other.getP)}
998 def apply[B](a:B)={internal !? ParamUpdate(a)}
1001 override def toString = name + " : " + paramString
1002 def paramString:String
1005 def lower:Array[Double]
1006 def upper:Array[Double]
1007 def numArguments:Int
1008 def length = numArguments
1009 def apply(d:Array[Double])
1010 def currentArgs:Array[Double]
1011 def latestArgs:Array[Double]
1012 lazy val random = new org.apache.commons.math.random.MersenneTwister
1015 lower.zip(upper).map{t=>
1016 random.nextDouble * (t._2-t._1) + t._1
1020 def randomise(lowerX:Double,upperX:Double){
1022 lower.zip(upper).map{t=> ((t._1 max lowerX),(t._2 min upperX))}.map{t=>
1023 random.nextDouble * (t._2-t._1) + t._1
1029 val prevArgs = currentArgs
1030 val newArgs = prevArgs.map{i=>
1031 prevArgs(random nextInt currentArgs.length)
1039 class ActorModel[A <: BioEnum](t:Tree[A],components:ActorModelComponent,val paramMap:Map[ParamName,ActorParamComponent]) extends Logging{
1041 val tree = t.splitAln(6)
1042 tree.foreach{_.start}
1043 val params = paramMap.keys.toList
1044 paramMap.values.foreach{_.start}
1065 case class GetQ(i:Int)
1068 val actor = Actor.actor{
1071 val baseTree = tree(0)
1072 components ! QMatReq(baseTree(i),None,None)
1073 var matrix:Matrix=null
1075 case QMatReq(node,Some(m),Some(pi))=>
1082 (actor !? GetQ(i)).asInstanceOf[Matrix]
1086 case class GetQ(i:Int)
1089 val actor = Actor.actor{
1092 val baseTree = tree(0)
1093 components ! MatReq(baseTree(i),None,None)
1094 var matrix:Matrix=null
1096 case MatReq(node,Some(m),Some(pi))=>
1103 (actor !? GetQ(i)).asInstanceOf[Matrix]
1106 debug{"Param Map " + paramMap}
1107 def getParam(p:ParamName):ActorParamComponent={
1109 case SingleParam(p2)=>SingleParamWrapper(getParam(p2))
1110 case JoinedParam(p2)=>JoinedParamWrapper(p2.map{getParam})
1111 case m:AllSingle => {
1112 JoinedParamWrapper( paramMap.filter{m matches _._1}.map{t=>SingleParamWrapper(t._2)}.toList)
1114 case m:ParamMatcher => {
1115 JoinedParamWrapper( paramMap.filter{m matches _._1}.map{_._2}.toList)
1117 case p => paramMap(p)
1122 def setParamsFrom(other:ActorModel[A]){
1123 other.paramMap.foreach{t=> val (k,v)=t
1124 if (paramMap.contains(k) && !k.isInstanceOf[BranchLengths]){
1125 debug{"Setting " + k + " " + v}
1126 val p = (v !? RequestParam).asInstanceOf[ParamChanged[_]]
1133 def from(other:ActorModel[A])={
1135 apply(BranchLengths(0)) << other(BranchLengths(0))
1140 def from(other:String)={
1141 val pLookup = paramMap.map{t=>(t._1.toString,t._1)}.foldLeft(Map[String,ParamName]()){_+_}
1142 other.lines.foreach{s=>
1143 val p = s.split("=").map{_.trim}
1144 val name=pLookup.get(p(0))
1145 if (name.isDefined){
1146 apply(name.get) readSerial p(1).split(",").map(_.toDouble)
1148 warning{"Ignoring apparent Parameter " + p(0)}
1154 def <<(other:ActorModel[A]){setParamsFrom(other)}
1156 val paramLengthMap = paramMap.keys.map{t=>(t,optGet(t).length)}.foldLeft(Map[ParamName,Int]()){(m,p)=>m+((p._1,p._2))}
1158 def update(p:ParamName,x:Array[Double]) {
1159 getParam(p) !? ParamUpdate[Array[Double]](x)
1161 def update(p:ParamName,x:Double) {
1162 getParam(p) !? ParamUpdate(Array(x))
1164 def update(p:ParamName,x:Vector) {
1165 getParam(p) !? ParamUpdate(x.toArray)
1167 def update(p:ParamName,x:Matrix) {
1168 getParam(p) !? ParamUpdate(x)
1170 def update[B](p:ParamName,pc:ParamChanged[B]){
1171 getParam(p) !? pc.toParamUpdate
1173 def optUpdate(p:ParamName,x:Array[Double]){getParam(p) !? OptUpdate(x)}
1174 def optGet(p:ParamName):Array[Double]={getParam(p) !? RequestOpt}.asInstanceOf[Array[Double]]
1175 def optUpdate(pList:List[ParamName])(x:Array[Double]){
1176 val iter = x.elements
1178 optUpdate(p,iter.take(paramLengthMap(p)).toList.toArray)
1181 def optGet(p:List[ParamName]):Array[Double]={
1182 //this is a crappy implementation
1183 //but how often is this really going to be called?
1184 p.map{optGet(_).toList}.flatten[Double].toArray
1186 def optSetter(p:ParamName):OptPSetter={
1188 val param = getParam(p)
1189 lazy val lower = (param !? Lower).asInstanceOf[Array[Double]]
1190 lazy val upper = (param !? Upper).asInstanceOf[Array[Double]]
1191 lazy val numArguments=lower.length
1192 lazy val currentArgs=(param !? RequestOpt).asInstanceOf[Array[Double]]
1194 val latestArgs=(param !? RequestOpt).asInstanceOf[Array[Double]]
1195 Array.copy(latestArgs,0,currentArgs,0,currentArgs.length)
1198 def apply(d:Array[Double])={
1199 if (d.zip(currentArgs).foldLeft(false){(bool,t)=> bool || t._1!=t._2}){
1200 Array.copy(d,0,currentArgs,0,d.length)
1201 param !? OptUpdate(d)
1204 def paramString=latestArgs.mkString(" ")
1205 override def toString = p + " : (" +paramString+")"
1208 def optSetter(p:List[ParamName]):OptPSetter={
1211 val sub = p.map{optSetter}
1212 val lower = sub.map{_.lower.toList}.flatten[Double].toArray
1213 val upper = sub.map{_.upper.toList}.flatten[Double].toArray
1214 val subLengths = sub.map{_.numArguments}
1215 val numArguments=subLengths.foldLeft(0){_+_}
1217 val currentArgs = sub.map{_.currentArgs.toList}.flatten[Double].toArray
1219 val latestArgs = sub.map{_.latestArgs.toList}.flatten[Double].toArray
1220 Array.copy(latestArgs,0,currentArgs,0,currentArgs.length)
1224 def apply(d:Array[Double])={
1226 val subIter = sub.elements
1227 val lenIter=subLengths.elements
1228 for (i<- 0 until numSub){
1229 val len = lenIter.next
1230 val s = subIter.next
1231 s(d.slice(pointer,pointer + len).toArray)
1232 pointer = pointer + len
1235 override def toString = sub.map{_.toString}.mkString(" ")
1240 def paramSetterVector(p:ActorParamComponent)(startParam:Vector)={
1241 class APSetter extends PSetter[Vector]{
1243 def getP={(p !? RequestParam).asInstanceOf[ParamChanged[Vector]].param}
1244 override def update(i:Int,x:Double){
1247 p !? ParamUpdate(array)
1249 override def apply(i:Int):Double={
1253 def toList = getP.toList
1255 def paramString = getP.toString
1260 //Separate array type necessary otherwise casting back to [A] seems to give a
1261 //java array rather than scala array - maybe this is something that changes
1263 def paramSetterArray(p:ActorParamComponent)(startParam:Array[Double])={
1264 class APSetter extends PSetter[Array[Double]]{
1265 def getP={(p !? RequestParam).asInstanceOf[ParamChanged[Array[Double]]].param}
1267 override def update(i:Int,x:Double){
1270 p !? ParamUpdate(array)
1272 override def apply(i:Int):Double={
1276 def toList = getP.toList
1278 def paramString = getP.mkString(" ")
1284 def paramSetterMatrix(p:ActorParamComponent)(startParam:Matrix)={
1285 class APSetter extends PSetter[Matrix]{
1287 def getP=(p !? RequestParam).asInstanceOf[ParamChanged[Matrix]].param
1288 override def update(i:Int,j:Int,x:Double){
1291 p !? ParamUpdate(array)
1293 override def apply(i:Int,j:Int):Double={
1297 def toList = getP.toList
1299 def paramString = getP.toString
1303 def paramSetterDouble(p:ActorParamComponent)(startParam:Double)={
1304 class APSetter extends PSetter[Double]{
1306 def getP=(p !? RequestParam).asInstanceOf[ParamChanged[Double]].param
1307 override def update(x:Double){
1310 override def apply():Double={
1314 override def update(i:Int,x:Double)={
1318 def toList = getP :: Nil
1320 def paramString = getP.toString
1326 //model(Pi(0))(S)=0.03
1327 def apply(p:ParamName)={
1328 val param = getParam(p)
1329 val start = param !? RequestParam
1331 case ParamChanged(_,a:Array[Double])=>paramSetterArray(param)(a)
1332 case ParamChanged(_,a:Vector)=>paramSetterVector(param)(a)
1333 case ParamChanged(_,a:Matrix)=>paramSetterMatrix(param)(a)
1334 case ParamChanged(_,a:Double)=>paramSetterDouble(param)(a)
1335 case _ => null//TODO error handling
1340 def logLikelihood = {val ans =
1347 t ! LogLikelihoodCalc(components,self)
1351 while (returned < tree.length){
1353 case LogLikelihood(d) =>
1362 }.asInstanceOf[Double]
1363 if (ans.isNaN){-1E100}else{ans}
1366 def paramString=paramMap.map{t=> t._2.name + " = " + (t._2 !? WriteSerial).asInstanceOf[Seq[Double]].mkString(",")}.mkString("\n")
1368 override def toString = paramString + "\nlog-likelihood: " + logLikelihood
1370 def optimise(params:ParamName*):Double={
1371 optimise(params.toList)
1373 def optimise(params:List[ParamName],tolfx:Double,tolx:Double):Double={
1374 import ModelOptimiser._
1375 ModelOptimiser.optimise(getConjugateDirection,params,this,tolfx,tolx)
1377 def optimiseQuick(params:List[ParamName]):Double=optimise(params,1E-1,1E-1)
1378 def optimise(params:List[ParamName]):Double={
1379 import ModelOptimiser._
1380 ModelOptimiser.optimise(getConjugateDirection,params,this)
1382 def optimise(params:List[List[ParamName]])(implicit m:Manifest[List[List[ParamName]]]):Double={
1383 var end = logLikelihood
1387 params.foreach{pset=>
1391 } while (end - start > 0.001)
1394 def optimiseCustom(params:List[List[ParamName]],tolfx:Double,tolx:Double)(implicit m:Manifest[List[List[ParamName]]]):Double={
1395 var end = logLikelihood
1399 params.foreach{pset=>
1400 optimise(pset,tolfx,tolx)
1403 } while (end - start > 0.001)
1406 def optimiseQuick(params:List[List[ParamName]])(implicit m:Manifest[List[List[ParamName]]]):Double={
1407 var end = logLikelihood
1411 params.foreach{pset=>
1415 } while (end - start > 0.001)
1420 // def switchingRate(nodeID:Int)={
1421 // logLikelihood //make sure parameters are set
1422 // (components !? SwitchingRate(nodeID)).asInstanceOf[Option[Double]].get
1425 def switchingRate(nodeID:Int)={
1427 val ans = rawReq(QMatReq(myTree(nodeID),None,None)).asInstanceOf[QMatReq[_]]
1428 val qMat = ans.m.get
1430 Math.max(qMat.rate(pi),1.0)-1.0
1433 def switchingBranchLengths={
1434 val myTree = currentTree
1435 val branchLengths=apply(BranchLengths(0)).toList
1436 myTree.descendentNodes.map{i:Node[_]=>i.id}.map{i=> (i,switchingRate(i) * myTree(i).lengthTo)}.foldLeft(Map[Int,Double]()){_+_}
1439 t setBranchLengths switchingBranchLengths
1442 t setBranchLengths (apply(BranchLengths(0)).toList)
1446 case class MatReq[A <: BioEnum](n:Node[A],m:Option[Matrix],pi:Option[Vector]){
1447 def toQMatReq=QMatReq(n,m,pi)
1449 case class QMatReq[A <: BioEnum](n:Node[A],m:Option[Matrix],pi:Option[Vector]){// extends MatReq(n2,m2,pi2) //used for skipping exponentiation
1450 def toMatReq=MatReq(n,m,pi)
1453 def apply[A <: BioEnum](n:Node[A])=MatReq(n,None,None)