@@ -13,6 +13,9 @@ use crate::{
1313 context:: DynamicStrategies ,
1414 strategies:: {
1515 AlignmentStrategySelection ,
16+ allow_ts_14_out_of_range:: {
17+ AdditionalExplicitTSMStartsAndEnds , Ts14OutOfRangeStrategy ,
18+ } ,
1619 descendant:: {
1720 AnyTemplateSwitchDescendantStrategy , OnlyEqualTemplateSwitchDescendantStrategy ,
1821 TemplateSwitchDescendantStrategy ,
@@ -112,6 +115,7 @@ struct QueryData<'a> {
112115 query_name : & ' a str ,
113116 query : & ' a [ u8 ] ,
114117 ranges : Option < AlignmentRange > ,
118+ gap_characters : & ' a [ u8 ] ,
115119 cost_limit : Option < u64 > ,
116120 memory_limit : Option < usize > ,
117121 extend_beyond_range : bool ,
@@ -127,6 +131,7 @@ pub struct Aligner<AlphabetType: Alphabet = DnaAlphabetOrN> {
127131 chaining_strategy : ChainingStrategySelector ,
128132 total_length_strategy : TotalLengthStrategySelector ,
129133 descendant_strategy : DescendantStrategySelector ,
134+ ts_14_out_of_range_strategy : Ts14OutOfRangeStrategy ,
130135 no_ts : bool ,
131136}
132137
@@ -143,10 +148,11 @@ impl<AlphabetType: Alphabet> Default for Aligner<AlphabetType> {
143148 fn default ( ) -> Self {
144149 Self {
145150 costs : TemplateSwitchConfig :: < AlphabetType , U64Cost > :: default ( ) ,
146- min_length_strategy : MinLengthStrategySelector :: default ( ) ,
147- chaining_strategy : ChainingStrategySelector :: default ( ) ,
148- total_length_strategy : TotalLengthStrategySelector :: default ( ) ,
149- descendant_strategy : DescendantStrategySelector :: default ( ) ,
151+ min_length_strategy : Default :: default ( ) ,
152+ chaining_strategy : Default :: default ( ) ,
153+ total_length_strategy : Default :: default ( ) ,
154+ descendant_strategy : Default :: default ( ) ,
155+ ts_14_out_of_range_strategy : Default :: default ( ) ,
150156 no_ts : false ,
151157 }
152158 }
@@ -204,7 +210,20 @@ impl<AlphabetType: Alphabet> Aligner<AlphabetType> {
204210 self
205211 }
206212
207- /// This performs the actual alignment and is, depending on the inputs, potentially taking quite long.
213+ pub fn set_ts_14_out_of_range_strategy (
214+ & mut self ,
215+ ts_14_out_of_range_strategy : Ts14OutOfRangeStrategy ,
216+ ) -> & mut Self {
217+ self . ts_14_out_of_range_strategy = ts_14_out_of_range_strategy;
218+ self
219+ }
220+
221+ /// Perform the actual alignment.
222+ ///
223+ /// Special gap characters can be specified in order to interpret the given sequences as an alignment with gaps instead of raw sequences.
224+ /// In this case, the range coordinates must refer to the ungapped sequences.
225+ ///
226+ /// Depending on the inputs, this takes quite long.
208227 /// Consider spawning tasks to not block the user application.
209228 #[ allow(
210229 clippy:: too_many_arguments,
@@ -218,6 +237,7 @@ impl<AlphabetType: Alphabet> Aligner<AlphabetType> {
218237 query_name : & str ,
219238 query : & [ u8 ] ,
220239 ranges : Option < AlignmentRange > ,
240+ gap_characters : & [ u8 ] ,
221241 cost_limit : Option < u64 > ,
222242 memory_limit : Option < usize > ,
223243 extend_beyond_range : bool ,
@@ -228,6 +248,7 @@ impl<AlphabetType: Alphabet> Aligner<AlphabetType> {
228248 query_name,
229249 query,
230250 ranges,
251+ gap_characters,
231252 cost_limit,
232253 memory_limit,
233254 extend_beyond_range,
@@ -336,9 +357,48 @@ impl<AlphabetType: Alphabet> Aligner<AlphabetType> {
336357 count_strategy_memory : TC :: Memory ,
337358 ) -> AlignmentResult < AlignmentType , U64Cost > {
338359 // TODO error handling
339- let reference = VectorGenome :: < AlphabetType > :: from_slice_u8 ( data. reference ) . unwrap ( ) ;
340- let query = VectorGenome :: from_slice_u8 ( data. query ) . unwrap ( ) ;
360+ let reference = VectorGenome :: < AlphabetType > :: from_iter_u8 (
361+ data. reference
362+ . iter ( )
363+ . copied ( )
364+ . filter ( |c| !data. gap_characters . contains ( c) ) ,
365+ )
366+ . unwrap ( ) ;
367+ let query = VectorGenome :: from_iter_u8 (
368+ data. query
369+ . iter ( )
370+ . copied ( )
371+ . filter ( |c| !data. gap_characters . contains ( c) ) ,
372+ )
373+ . unwrap ( ) ;
374+
375+ let range = data
376+ . ranges
377+ . unwrap_or_else ( || AlignmentRange :: new_complete ( reference. len ( ) , query. len ( ) ) ) ;
378+ let additional_tsm_starts_and_ends =
379+ if self . ts_14_out_of_range_strategy == Ts14OutOfRangeStrategy :: Allow {
380+ AdditionalExplicitTSMStartsAndEnds :: new (
381+ & data
382+ . reference
383+ . iter ( )
384+ . map ( |c| * c as char )
385+ . collect :: < String > ( ) ,
386+ & data. query . iter ( ) . map ( |c| * c as char ) . collect :: < String > ( ) ,
387+ & range,
388+ & data
389+ . gap_characters
390+ . iter ( )
391+ . map ( |c| * c as char )
392+ . collect :: < Vec < _ > > ( ) ,
393+ false ,
394+ )
395+ . unwrap ( )
396+ } else {
397+ AdditionalExplicitTSMStartsAndEnds :: default ( )
398+ } ;
399+
341400 let cost_limit = data. cost_limit . map ( U64Cost :: from) ;
401+
342402 template_switch_distance_a_star_align :: <
343403 AlignmentStrategySelection <
344404 AlphabetType ,
@@ -360,8 +420,8 @@ impl<AlphabetType: Alphabet> Aligner<AlphabetType> {
360420 query. as_genome_subsequence ( ) ,
361421 data. reference_name ,
362422 data. query_name ,
363- data . ranges
364- . unwrap_or_else ( || AlignmentRange :: new_complete ( reference . len ( ) , query . len ( ) ) ) ,
423+ range ,
424+ additional_tsm_starts_and_ends ,
365425 & self . costs ,
366426 DynamicStrategies { } ,
367427 cost_limit,
@@ -395,6 +455,7 @@ mod tests {
395455 AlignmentCoordinates :: new ( 27 , 200 ) ,
396456 AlignmentCoordinates :: new ( 33 , 214 )
397457 ) . into ( ) ,
458+ & [ ] ,
398459 None ,
399460 None ,
400461 true ) ;
0 commit comments