@@ -170,6 +170,12 @@ void Chromosome::InitializeDraws(void)
170170 if (genomic_elements_.size () == 0 )
171171 EIDOS_TERMINATION << " ERROR (Chromosome::InitializeDraws): empty chromosome." << EidosTerminate ();
172172
173+ // BCH 8/28/2024: we now sort the genomic elements here; we need them to be sorted later on anyway
174+ // I avoided doing this before because it changed the behavior, but it is hard to imagine anybody caring
175+ // Since elements must be non-overlapping, we only need to sort by start position
176+ std::sort (genomic_elements_.begin (), genomic_elements_.end (),
177+ [](GenomicElement *e1 , GenomicElement *e2 ) { return e1 ->start_position_ < e2 ->start_position_ ; });
178+
173179 // determine which case we are working with: separate recombination maps for the sexes, or one map
174180 auto rec_rates_H_size = recombination_rates_H_.size ();
175181 auto rec_rates_M_size = recombination_rates_M_.size ();
@@ -614,12 +620,7 @@ void Chromosome::_InitializeOneMutationMap(gsl_ran_discrete_t *&p_lookup, std::v
614620 // The class we use to represent these constant-rate subregions is GESubrange, declared in chromosome.h.
615621 p_subranges.clear ();
616622
617- // We need to work with a *sorted* genomic elements vector here. We sort it internally here, rather than in
618- // genomic_elements_, so that genomic_elements_ reflects exactly what they user gave us (mostly for backward
619- // compatibility).
620- std::vector<GenomicElement *> sorted_ge_vec = genomic_elements_;
621-
622- std::sort (sorted_ge_vec.begin (), sorted_ge_vec.end (), [](GenomicElement *ge1, GenomicElement *ge2) {return ge1->start_position_ < ge2->start_position_ ;});
623+ // We need to work with a *sorted* genomic elements vector here. BCH 8/28/2024: That is now guaranteed.
623624
624625 // This code deals in two different currencies: *requested* mutation rates and *adjusted* mutation rates.
625626 // This stems from the fact that, beginning in SLiM 3.5, we unique mutation positions as we're generating
@@ -638,7 +639,7 @@ void Chromosome::_InitializeOneMutationMap(gsl_ran_discrete_t *&p_lookup, std::v
638639 unsigned int mutrange_index = 0 ;
639640 slim_position_t end_of_previous_mutrange = -1 ;
640641
641- for (GenomicElement *ge_ptr : sorted_ge_vec )
642+ for (GenomicElement *ge_ptr : genomic_elements_ )
642643 {
643644 GenomicElement &ge = *ge_ptr;
644645
@@ -1858,14 +1859,16 @@ EidosValue_SP Chromosome::ExecuteInstanceMethod(EidosGlobalStringID p_method_id,
18581859{
18591860 switch (p_method_id)
18601861 {
1861- case gID_ancestralNucleotides : return ExecuteMethod_ancestralNucleotides (p_method_id, p_arguments, p_interpreter);
1862- case gID_setAncestralNucleotides : return ExecuteMethod_setAncestralNucleotides (p_method_id, p_arguments, p_interpreter);
1863- case gID_setGeneConversion : return ExecuteMethod_setGeneConversion (p_method_id, p_arguments, p_interpreter);
1864- case gID_setHotspotMap : return ExecuteMethod_setHotspotMap (p_method_id, p_arguments, p_interpreter);
1865- case gID_setMutationRate : return ExecuteMethod_setMutationRate (p_method_id, p_arguments, p_interpreter);
1866- case gID_setRecombinationRate : return ExecuteMethod_setRecombinationRate (p_method_id, p_arguments, p_interpreter);
1867- case gID_drawBreakpoints : return ExecuteMethod_drawBreakpoints (p_method_id, p_arguments, p_interpreter);
1868- default : return super::ExecuteInstanceMethod (p_method_id, p_arguments, p_interpreter);
1862+ case gID_ancestralNucleotides : return ExecuteMethod_ancestralNucleotides (p_method_id, p_arguments, p_interpreter);
1863+ case gID_genomicElementForPosition : return ExecuteMethod_genomicElementForPosition (p_method_id, p_arguments, p_interpreter);
1864+ case gID_hasGenomicElementForPosition : return ExecuteMethod_hasGenomicElementForPosition (p_method_id, p_arguments, p_interpreter);
1865+ case gID_setAncestralNucleotides : return ExecuteMethod_setAncestralNucleotides (p_method_id, p_arguments, p_interpreter);
1866+ case gID_setGeneConversion : return ExecuteMethod_setGeneConversion (p_method_id, p_arguments, p_interpreter);
1867+ case gID_setHotspotMap : return ExecuteMethod_setHotspotMap (p_method_id, p_arguments, p_interpreter);
1868+ case gID_setMutationRate : return ExecuteMethod_setMutationRate (p_method_id, p_arguments, p_interpreter);
1869+ case gID_setRecombinationRate : return ExecuteMethod_setRecombinationRate (p_method_id, p_arguments, p_interpreter);
1870+ case gID_drawBreakpoints : return ExecuteMethod_drawBreakpoints (p_method_id, p_arguments, p_interpreter);
1871+ default : return super::ExecuteInstanceMethod (p_method_id, p_arguments, p_interpreter);
18691872 }
18701873}
18711874
@@ -2017,6 +2020,65 @@ EidosValue_SP Chromosome::ExecuteMethod_drawBreakpoints(EidosGlobalStringID p_me
20172020 return EidosValue_SP (new (gEidosValuePool ->AllocateChunk ()) EidosValue_Int (all_breakpoints));
20182021}
20192022
2023+ GenomicElement *Chromosome::ElementForPosition (slim_position_t pos)
2024+ {
2025+ auto element_iter = std::lower_bound (genomic_elements_.begin (), genomic_elements_.end (), pos,
2026+ [](const GenomicElement *e, slim_position_t position) { return e->end_position_ < position; });
2027+
2028+ if (element_iter == genomic_elements_.end ())
2029+ return nullptr ;
2030+
2031+ GenomicElement *element = *element_iter;
2032+
2033+ if (element->start_position_ > pos)
2034+ return nullptr ;
2035+
2036+ return element;
2037+ }
2038+
2039+ // ********************* (object<GenomicElement>)genomicElementForPosition(integer positions)
2040+ //
2041+ EidosValue_SP Chromosome::ExecuteMethod_genomicElementForPosition (EidosGlobalStringID p_method_id, const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter)
2042+ {
2043+ #pragma unused (p_method_id, p_arguments, p_interpreter)
2044+ EidosValue *positions_value = p_arguments[0 ].get ();
2045+ int positions_count = positions_value->Count ();
2046+ EidosValue_Object_SP obj_result_SP = EidosValue_Object_SP (new (gEidosValuePool ->AllocateChunk ()) EidosValue_Object (gSLiM_GenomicElement_Class ));
2047+ EidosValue_Object *obj_result = obj_result_SP->reserve (positions_count);
2048+ const int64_t *positions_data = positions_value->IntData ();
2049+
2050+ for (int pos_index = 0 ; pos_index < positions_count; ++pos_index)
2051+ {
2052+ int64_t pos = positions_data[pos_index];
2053+ GenomicElement *element = ElementForPosition (pos);
2054+
2055+ if (element)
2056+ obj_result->push_object_element_no_check_NORR (element);
2057+ }
2058+
2059+ return obj_result_SP;
2060+ }
2061+
2062+ // ********************* (logical)hasGenomicElementForPosition(integer positions)
2063+ //
2064+ EidosValue_SP Chromosome::ExecuteMethod_hasGenomicElementForPosition (EidosGlobalStringID p_method_id, const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter)
2065+ {
2066+ #pragma unused (p_method_id, p_arguments, p_interpreter)
2067+ EidosValue *positions_value = p_arguments[0 ].get ();
2068+ int positions_count = positions_value->Count ();
2069+ EidosValue_Logical_SP logical_result_SP = EidosValue_Logical_SP (new (gEidosValuePool ->AllocateChunk ()) EidosValue_Logical ());
2070+ EidosValue_Logical *logical_result = logical_result_SP->reserve (positions_count);
2071+ const int64_t *positions_data = positions_value->IntData ();
2072+
2073+ for (int pos_index = 0 ; pos_index < positions_count; ++pos_index)
2074+ {
2075+ int64_t pos = positions_data[pos_index];
2076+ logical_result->push_logical_no_check (ElementForPosition (pos) ? true : false );
2077+ }
2078+
2079+ return logical_result_SP;
2080+ }
2081+
20202082// ********************* (integer$)setAncestralNucleotides(is sequence)
20212083//
20222084EidosValue_SP Chromosome::ExecuteMethod_setAncestralNucleotides (EidosGlobalStringID p_method_id, const std::vector<EidosValue_SP> &p_arguments, EidosInterpreter &p_interpreter)
@@ -2577,6 +2639,8 @@ const std::vector<EidosMethodSignature_CSP> *Chromosome_Class::Methods(void) con
25772639
25782640 methods->emplace_back ((EidosInstanceMethodSignature *)(new EidosInstanceMethodSignature (gStr_ancestralNucleotides , kEidosValueMaskInt | kEidosValueMaskString ))->AddInt_OSN (gEidosStr_start , gStaticEidosValueNULL )->AddInt_OSN (gEidosStr_end , gStaticEidosValueNULL )->AddString_OS (" format" , EidosValue_String_SP (new (gEidosValuePool ->AllocateChunk ()) EidosValue_String (" string" ))));
25792641 methods->emplace_back ((EidosInstanceMethodSignature *)(new EidosInstanceMethodSignature (gStr_drawBreakpoints , kEidosValueMaskInt ))->AddObject_OSN (" parent" , gSLiM_Individual_Class , gStaticEidosValueNULL )->AddInt_OSN (" n" , gStaticEidosValueNULL ));
2642+ methods->emplace_back ((EidosInstanceMethodSignature *)(new EidosInstanceMethodSignature (gStr_genomicElementForPosition , kEidosValueMaskObject , gSLiM_GenomicElement_Class ))->AddInt (" positions" ));
2643+ methods->emplace_back ((EidosInstanceMethodSignature *)(new EidosInstanceMethodSignature (gStr_hasGenomicElementForPosition , kEidosValueMaskLogical ))->AddInt (" positions" ));
25802644 methods->emplace_back ((EidosInstanceMethodSignature *)(new EidosInstanceMethodSignature (gStr_setAncestralNucleotides , kEidosValueMaskInt | kEidosValueMaskSingleton ))->AddIntString (" sequence" ));
25812645 methods->emplace_back ((EidosInstanceMethodSignature *)(new EidosInstanceMethodSignature (gStr_setGeneConversion , kEidosValueMaskVOID ))->AddNumeric_S (" nonCrossoverFraction" )->AddNumeric_S (" meanLength" )->AddNumeric_S (" simpleConversionFraction" )->AddNumeric_OS (" bias" , gStaticEidosValue_Integer0 ));
25822646 methods->emplace_back ((EidosInstanceMethodSignature *)(new EidosInstanceMethodSignature (gStr_setHotspotMap , kEidosValueMaskVOID ))->AddNumeric (" multipliers" )->AddInt_ON (" ends" , gStaticEidosValueNULL )->AddString_OS (" sex" , gStaticEidosValue_StringAsterisk ));
0 commit comments