22
22
import warnings
23
23
24
24
import attr
25
+ import demes
25
26
import numpy as np
26
27
27
28
from deprecated import deprecated
28
29
30
+
29
31
from ._fwdpy11 import (
30
32
GeneticValueIsTrait ,
31
33
GeneticValueNoise ,
49
51
attr_class_to_from_dict_no_recurse ,
50
52
)
51
53
54
+ from ._types .forward_demes_graph import ForwardDemesGraph
55
+
56
+
57
+ class TimingError (Exception ):
58
+ pass
59
+
52
60
53
61
@attr_add_asblack
54
62
@attr_class_pickle_with_super
@@ -204,6 +212,20 @@ def asdict(self):
204
212
def fromdict (cls , data ):
205
213
return cls (** data )
206
214
215
+ def validate_timings (self , deme : int , demography : ForwardDemesGraph ) -> None :
216
+ graph = demography .demes_graph
217
+ deme_obj = graph .demes [deme ]
218
+ if deme_obj .start_time == float ("inf" ):
219
+ start_time = demography .to_backwards_time (0 )
220
+ else :
221
+ start_time = deme_obj .start_time
222
+ for i in self .optima [:1 ]:
223
+ btime = demography .to_backwards_time (i .when )
224
+ if btime < start_time :
225
+ msg = f"deme { deme_obj .name } , event { i } is at time { btime } in the past "
226
+ msg += f", but the deme starts at { int (start_time )} "
227
+ raise TimingError (msg )
228
+
207
229
208
230
@attr_add_asblack
209
231
@attr_class_to_from_dict_no_recurse
@@ -508,6 +530,11 @@ def __attrs_post_init__(self):
508
530
self .scaling , self .gvalue_to_fitness , self .noise , self .ndemes
509
531
)
510
532
533
+ def validate_timings (self , deme : int , demography : ForwardDemesGraph ) -> None :
534
+ if self .gvalue_to_fitness is None :
535
+ return
536
+ self .gvalue_to_fitness .validate_timings (deme , demography )
537
+
511
538
512
539
@attr_add_asblack
513
540
@attr_class_pickle_with_super
@@ -555,6 +582,11 @@ def __attrs_post_init__(self):
555
582
self .scaling , self .gvalue_to_fitness , self .noise , self .ndemes
556
583
)
557
584
585
+ def validate_timings (self , deme : int , demography : ForwardDemesGraph ) -> None :
586
+ if self .gvalue_to_fitness is None :
587
+ return
588
+ self .gvalue_to_fitness .validate_timings (deme , demography )
589
+
558
590
559
591
@attr_add_asblack
560
592
@attr_class_pickle_with_super
@@ -591,6 +623,11 @@ class GBR(_ll_GBR):
591
623
def __attrs_post_init__ (self ):
592
624
super (GBR , self ).__init__ (self .gvalue_to_fitness , self .noise )
593
625
626
+ def validate_timings (self , deme : int , demography : ForwardDemesGraph ) -> None :
627
+ if self .gvalue_to_fitness is None :
628
+ return
629
+ self .gvalue_to_fitness .validate_timings (deme , demography )
630
+
594
631
595
632
@attr_add_asblack
596
633
@attr_class_pickle_with_super
@@ -637,6 +674,11 @@ def __attrs_post_init__(self):
637
674
self .ndimensions , self .focal_trait , self .gvalue_to_fitness , self .noise
638
675
)
639
676
677
+ def validate_timings (self , deme : int , demography : ForwardDemesGraph ) -> None :
678
+ if self .gvalue_to_fitness is None :
679
+ return
680
+ self .gvalue_to_fitness .validate_timings (deme , demography )
681
+
640
682
641
683
@deprecated (reason = "Use AdditivePleiotropy instead." )
642
684
class StrictAdditiveMultivariateEffects (AdditivePleiotropy ):
@@ -652,3 +694,8 @@ def __init__(self, ndim: int, gvalue_to_fitness=None, noise=None):
652
694
gvalue_to_fitness ,
653
695
noise ,
654
696
)
697
+
698
+ def validate_timings (self , deme : int , demography : ForwardDemesGraph ) -> None :
699
+ if self .gvalue_to_fitness is None :
700
+ return
701
+ self .gvalue_to_fitness .validate_timings (deme , demography )
0 commit comments