1414logger = logging .getLogger (__name__ )
1515
1616
17+ def _uniform_rate_map (left , right , length , rate ):
18+ """
19+ Makes a RateMap that is
20+ """
21+ pos = [
22+ 0.0 ,
23+ ]
24+ x = []
25+ if left > 0 :
26+ pos .append (left )
27+ x .append (np .nan )
28+ pos .append (right )
29+ x .append (rate )
30+ if right < length :
31+ pos .append (length )
32+ x .append (np .nan )
33+ return msprime .RateMap (position = pos , rate = x )
34+
35+
1736@attr .s
1837class Genome :
1938 """
@@ -225,9 +244,6 @@ class Contig:
225244 and ``interval_list``. These must be of the same length, and the k-th DFE
226245 applies to the k-th interval; see :meth:`.add_dfe` for more information.
227246
228- The contig may be a segment of a named chromosome. If so, the original
229- coordinate system is used for :meth:`.add_dfe` and :meth:`add_single_site`.
230-
231247 :ivar mutation_rate: The rate of mutation per base per generation.
232248 :vartype mutation_rate: float
233249 :ivar ploidy: The ploidy of the contig. Defaults to 2 (diploid).
@@ -267,11 +283,11 @@ class Contig:
267283 :ivar interval_list: A list of :class:`np.array` objects containing integers.
268284 By default, the inital interval list spans the whole chromosome with the
269285 neutral DFE.
270- :ivar original_coordinates : The location of the contig on a named chromosome,
286+ :ivar coordinates : The location of the contig on a named chromosome,
271287 as a tuple of the form `(chromosome, left, right)`. If `None`, the contig
272288 is assumed to be generic (i.e. it does not inherit a coordinate system
273289 from a larger chromosome).
274- :vartype original_coordinates : tuple
290+ :vartype coordinates : tuple
275291
276292 .. note::
277293 To run stdpopsim simulations with alternative, user-specified mutation,
@@ -300,14 +316,14 @@ class Contig:
300316 exclusion_mask = attr .ib (default = None )
301317 dfe_list = attr .ib (factory = list )
302318 interval_list = attr .ib (factory = list )
303- original_coordinates = attr .ib (default = None , type = tuple )
319+ coordinates = attr .ib (default = None , type = tuple )
304320
305321 def __attrs_post_init__ (self ):
306- if self .original_coordinates is None :
307- self .original_coordinates = (None , 0 , int (self .length ))
308- _ , left , right = self .original_coordinates
322+ if self .coordinates is None :
323+ self .coordinates = (None , 0 , int (self .length ))
324+ _ , left , right = self .coordinates
309325 self .add_dfe (
310- [[left , right ]],
326+ np . array ( [[left , right ]]) ,
311327 stdpopsim .dfe .neutral_dfe (),
312328 )
313329
@@ -491,20 +507,24 @@ def species_contig(
491507 logger .debug (
492508 f"Making flat chromosome { length_multiplier } * { chrom .id } "
493509 )
510+ recomb_map = msprime .RateMap .uniform (
511+ round (length_multiplier * chrom .length ),
512+ chrom .recombination_rate ,
513+ )
494514 else :
495515 logger .debug (
496- f"Making flat contig of length { right - left } from { chrom .id } "
516+ f"Making flat contig from { left } to { right } for { chrom .id } "
517+ )
518+ recomb_map = _uniform_rate_map (
519+ left , right , chrom .length , chrom .recombination_rate
497520 )
498- recomb_map = msprime .RateMap .uniform (
499- right - left , chrom .recombination_rate
500- )
501521 else :
502522 if length_multiplier != 1 :
503523 raise ValueError ("Cannot use length multiplier with empirical maps" )
504524 logger .debug (f"Getting map for { chrom .id } from { genetic_map } " )
505525 gm = species .get_genetic_map (genetic_map )
506526 recomb_map = gm .get_chromosome_map (chrom .id )
507- recomb_map = recomb_map .slice (left = left , right = right , trim = True )
527+ recomb_map = recomb_map .slice (left = left , right = right )
508528
509529 inclusion_intervals = None
510530 exclusion_intervals = None
@@ -517,7 +537,7 @@ def species_contig(
517537 )
518538 else :
519539 inclusion_intervals = inclusion_mask
520- inclusion_intervals = stdpopsim .utils .clip_and_shift_intervals (
540+ inclusion_intervals = stdpopsim .utils .clip_intervals (
521541 inclusion_intervals , left , right
522542 )
523543 if exclusion_mask is not None :
@@ -529,7 +549,7 @@ def species_contig(
529549 )
530550 else :
531551 exclusion_intervals = exclusion_mask
532- exclusion_intervals = stdpopsim .utils .clip_and_shift_intervals (
552+ exclusion_intervals = stdpopsim .utils .clip_intervals (
533553 exclusion_intervals , left , right
534554 )
535555
@@ -562,7 +582,7 @@ def species_contig(
562582 gene_conversion_length = gene_conversion_length ,
563583 inclusion_mask = inclusion_intervals ,
564584 exclusion_mask = exclusion_intervals ,
565- original_coordinates = (chromosome , left , right ),
585+ coordinates = (chromosome , left , right ),
566586 ploidy = ploidy ,
567587 )
568588
@@ -572,19 +592,30 @@ def species_contig(
572592 def length (self ):
573593 return self .recombination_map .sequence_length
574594
595+ @property
596+ def original_coordinates (self ):
597+ warnings .warn (
598+ stdpopsim .DeprecatedFeatureWarning (
599+ "The original_coordinates property is deprecated, "
600+ "since contigs are no longer shifted to be relative to their "
601+ "left endpoint: use Contig.coordinates instead."
602+ )
603+ )
604+ return self .coordinates
605+
575606 @property
576607 def origin (self ):
577608 """
578609 The location of the contig on a named chromosome as a string with format,
579610 "chromosome:left-right"; or None if a generic contig.
580611 """
581- chromosome , left , right = self .original_coordinates
612+ chromosome , left , right = self .coordinates
582613 if chromosome is None :
583614 return None
584615 else :
585616 return f"{ chromosome } :{ left } -{ right } "
586617
587- def dfe_breakpoints (self , relative_coordinates = True ):
618+ def dfe_breakpoints (self , * , relative_coordinates = None ):
588619 """
589620 Returns two things: the sorted vector of endpoints of all intervals across
590621 all DFEs in the contig, and a vector of integer labels for these intervals,
@@ -607,21 +638,23 @@ def dfe_breakpoints(self, relative_coordinates=True):
607638 ``breaks[k]``. Some intervals may not be covered by a DFE, in which
608639 case they will have the label ``-1`` (beware of python indexing!).
609640
610- :param bool relative_coordinates: If True, the returned breakpoints
611- will be relative to the start of the contig, rather than to the
612- start of the chromosome to which to contig belongs.
613-
614641 :return: A tuple (breaks, dfe_labels).
615642 """
643+ if relative_coordinates is not None :
644+ warnings .warn (
645+ stdpopsim .DeprecatedFeatureWarning (
646+ "The relative_coordinates argument is deprecated "
647+ "(and no longer needed),"
648+ "because contigs are no longer shifted to be relative to their "
649+ "left endpoint."
650+ )
651+ )
616652 breaks = np .unique (
617653 np .vstack (self .interval_list + [[[0 , int (self .length )]]]) # also sorted
618654 )
619655 dfe_labels = np .full (len (breaks ) - 1 , - 1 , dtype = "int" )
620656 for j , intervals in enumerate (self .interval_list ):
621657 dfe_labels [np .isin (breaks [:- 1 ], intervals [:, 0 ], assume_unique = True )] = j
622- if not relative_coordinates :
623- _ , left , _ = self .original_coordinates
624- breaks += left
625658 return breaks , dfe_labels
626659
627660 def clear_dfes (self ):
@@ -659,9 +692,9 @@ def add_dfe(self, intervals, DFE):
659692 :param array intervals: A valid set of intervals.
660693 :param DFE dfe: A DFE object.
661694 """
662- _ , left , right = self .original_coordinates
663- intervals = stdpopsim .utils .clip_and_shift_intervals (intervals , left , right )
664- stdpopsim .utils ._check_intervals_validity (intervals , start = 0 , end = self . length )
695+ _ , left , right = self .coordinates
696+ intervals = stdpopsim .utils .clip_intervals (intervals , left , right )
697+ stdpopsim .utils ._check_intervals_validity (intervals , start = left , end = right )
665698 for j , ints in enumerate (self .interval_list ):
666699 self .interval_list [j ] = stdpopsim .utils .mask_intervals (ints , intervals )
667700 self .dfe_list .append (DFE )
0 commit comments