Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib_tsshow/src/svg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,7 @@ fn render_source_char(
SourceChar::Gap { copy_depth } => {
Character::new_char('-', CharacterData::new_colored(copy_color(copy_depth)))
}
SourceChar::Separator => Character::new_char_with_default('|'),
SourceChar::Hidden { .. } | SourceChar::Spacer | SourceChar::Blank => {
Character::new_char_with_default(' ')
}
Expand Down
1 change: 1 addition & 0 deletions lib_tsshow/src/svg/font/sans_serif_mono.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::sync::LazyLock;

use super::Font;

/// Font: monospace
pub static FONT: LazyLock<Font> = LazyLock::new(|| {
Font::new(
[
Expand Down
2 changes: 2 additions & 0 deletions lib_tsshow/src/svg/font/typewriter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::sync::LazyLock;

use super::Font;

/// Font: Courier New
pub static FONT: LazyLock<Font> = LazyLock::new(|| {
Font::new(
[
Expand Down Expand Up @@ -68,6 +69,7 @@ pub static FONT: LazyLock<Font> = LazyLock::new(|| {
('8', "m 0.86196288,-1.0557495 q 0.16278072,0.0790649 0.24494632,0.20928955 0.083716,0.12867432 0.083716,0.27750244 0,0.23099365 -0.1736328,0.39997558 Q 0.84335936,0 0.59531249,0 0.34726562,0 0.17363281,-0.16898193 0,-0.33796386 0,-0.56895751 0,-0.71623534 0.08216553,-0.84490966 0.16588135,-0.97513426 0.3302124,-1.0557495 0.18758545,-1.137915 0.12247314,-1.2262817 0.03255615,-1.3518554 0.03255615,-1.5037842 q 0,-0.2139404 0.16433105,-0.3736206 0.16588135,-0.1612304 0.39842529,-0.1612304 0.23409424,0 0.39842529,0.1612304 0.16433102,0.1596802 0.16433102,0.3736206 0,0.1519288 -0.089917,0.2759522 -0.063562,0.089917 -0.20618892,0.1720825 z M 1.0247436,-1.4991333 q 0,-0.1674316 -0.12557369,-0.2868042 -0.12402344,-0.1209228 -0.30540771,-0.1209228 -0.17983398,0 -0.30540771,0.1209228 -0.12402344,0.1209229 -0.12402344,0.2852539 0,0.1519287 0.12247315,0.2666504 0.12402343,0.1131714 0.306958,0.1131714 0.18448486,0 0.306958,-0.1131714 0.1240234,-0.1147217 0.1240234,-0.2651001 z m 0.035657,0.93327637 q 0,-0.17208251 -0.13332522,-0.29920653 -0.13332519,-0.12712403 -0.33176269,-0.12712403 -0.1984375,0 -0.33176269,0.12712403 -0.13332519,0.12712402 -0.13332519,0.29765624 0,0.1767334 0.13332519,0.306958 0.13487549,0.13022461 0.33176269,0.13022461 0.19688721,0 0.3302124,-0.13022461 0.13487551,-0.1302246 0.13487551,-0.30540771 z"),
('9', "m 1.0604004,-1.1472168 q -0.10076907,0.17828371 -0.24029544,0.2682007 -0.13797607,0.089917 -0.28370361,0.089917 -0.13487548,0 -0.26199951,-0.0775147 Q 0.14882812,-0.9441284 0.07441405,-1.0929565 0,-1.2433349 0,-1.407666 q 0,-0.2387451 0.14727782,-0.434082 0.14882813,-0.1968872 0.396875,-0.1968872 0.17673339,0 0.32246093,0.1100708 0.14572755,0.1100708 0.22634275,0.3193603 0.1038696,0.2682007 0.1038696,0.62321779 0,0.27595214 -0.088367,0.45888671 -0.058911,0.12402343 -0.17363276,0.2402954 Q 0.82165525,-0.17053222 0.6790283,-0.09766846 0.48369139,0 0.27285155,0 0.13332519,0 0.04495849,-0.05270996 0.00465087,-0.07751465 0.00465087,-0.11472168 q 0,-0.026355 0.01860352,-0.0434082 0.01860351,-0.0186035 0.04495849,-0.0186035 0.01860352,0 0.05426026,0.0170532 0.0604614,0.0294556 0.13952636,0.0294556 0.3302124,0 0.56740722,-0.23719482 0.23719478,-0.23874511 0.23719478,-0.59686278 0,-0.0651123 -0.0062,-0.18293459 z m -0.024805,-0.217041 Q 0.95343016,-1.6789673 0.83095701,-1.7921386 0.71003416,-1.9068603 0.5472534,-1.9068603 q -0.16588134,0 -0.29145507,0.1395263 -0.12557373,0.1395264 -0.12557373,0.3581177 0,0.2123901 0.12557373,0.3519165 0.12557373,0.13797608 0.28370361,0.13797608 0.0914673,0 0.17983398,-0.0496094 0.089917,-0.0496094 0.16898193,-0.14882811 0.0511597,-0.066663 0.14727785,-0.2464966 z"),
('-', "m 1.6169555,-0.99063719 v 0.18603515 H 0.28835449 v -0.18603515 z"),
('|', "m 1.0185425,-1.8572509 -0.00155,2.17196037 q 0,0.0465088 -0.0186035,0.0666626 -0.0170532,0.0201538 -0.0465088,0.0201538 -0.0279053,0 -0.0465088,-0.0201538 -0.0186035,-0.0201538 -0.0186035,-0.0666626 V -1.8572509 q 0,-0.048059 0.0186035,-0.068213 0.0186035,-0.020154 0.0465088,-0.020154 0.0294556,0 0.0480591,0.020154 0.0186035,0.020154 0.0186035,0.068213 z"),
(' ', ""),
].into_iter().map(|(c, value)| (c, value.to_string())).collect(),
2.0,
Expand Down
6 changes: 6 additions & 0 deletions lib_tsshow/src/ts_arrangement/complement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ impl TsComplementArrangement {
..
}
| SourceChar::Gap { .. }
| SourceChar::Separator
| SourceChar::Spacer
| SourceChar::Blank => {
sequence_c.push(ComplementChar::Blank);
Expand All @@ -75,6 +76,11 @@ impl TsComplementArrangement {
result
}

pub fn width(&self) -> usize {
debug_assert_eq!(self.reference_c.len(), self.query_c.len());
self.reference_c.len()
}

pub fn secondary_complement(
&self,
secondary: TemplateSwitchSecondary,
Expand Down
14 changes: 13 additions & 1 deletion lib_tsshow/src/ts_arrangement/inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ impl TsInnerArrangement {
inners: Default::default(),
};

trace!(
"source width: {}; complement width: {}",
source_arrangement.width(),
complement_arrangement.width(),
);

for ts in template_switches {
trace!("source_inner: {:?}", ts.inner);

Expand All @@ -63,6 +69,12 @@ impl TsInnerArrangement {
),
};
let forward = sp2_secondary < sp3_secondary;
trace!(
"sp2_secondary: {} -> {sp2_secondary}; sp3_secondary: {} -> {sp3_secondary}; {}",
ts.sp2_secondary,
ts.sp3_secondary,
if forward { "forward" } else { "reverse" }
);

let mut source_inner = ts.inner.iter().copied();
let mut inner = TaggedVec::<ArrangementColumn, _>::default();
Expand Down Expand Up @@ -395,7 +407,7 @@ impl From<SourceChar> for InnerChar {
panic!("Cannot be translated into InnerChar")
}
SourceChar::Gap { copy_depth } => Self::Gap { copy_depth },
SourceChar::Spacer | SourceChar::Blank => Self::Blank,
SourceChar::Separator | SourceChar::Spacer | SourceChar::Blank => Self::Blank,
}
}
}
Expand Down
110 changes: 97 additions & 13 deletions lib_tsshow/src/ts_arrangement/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ pub enum SourceChar {
Gap {
copy_depth: Option<usize>,
},
/// Separates the aligned section of the sequences from the unaligned section.
///
/// This is used when the alignment is only computed on a substring of the reference and the query.
Separator,
/// Like a blank, but not treated as an empty column.
Spacer,
Blank,
Expand All @@ -56,13 +60,42 @@ impl TsSourceArrangement {
) -> Result<Self> {
let mut ts_index = 0;
let mut alignment = alignment.into_iter();

// Insert the source sequences with blanks to the left to make sure their alignments start at the same arrangement column.
let reference_left_blank_count =
query_alignment_offset.saturating_sub(reference_alignment_offset);
let query_left_blank_count =
reference_alignment_offset.saturating_sub(query_alignment_offset);
let mut result = Self {
reference: FromIterator::from_iter((0..reference_length).map(SourceChar::new_source)),
query: FromIterator::from_iter((0..query_length).map(SourceChar::new_source)),
reference: FromIterator::from_iter(
iter::repeat_n(SourceChar::Blank, reference_left_blank_count)
.chain((0..reference_length).map(SourceChar::new_source)),
),
query: FromIterator::from_iter(
iter::repeat_n(SourceChar::Blank, query_left_blank_count)
.chain((0..query_length).map(SourceChar::new_source)),
),
};

let mut current_reference_index = ArrangementColumn::from(reference_alignment_offset);
let mut current_query_index = ArrangementColumn::from(query_alignment_offset);
let mut current_reference_index =
ArrangementColumn::from(reference_left_blank_count + reference_alignment_offset);
let mut current_query_index =
ArrangementColumn::from(query_left_blank_count + query_alignment_offset);
debug_assert_eq!(current_reference_index, current_query_index);

// If there are further characters to the left of the alignment, we insert a separator into both sequences.
if reference_alignment_offset > 0 || query_alignment_offset > 0 {
result
.reference
.insert(current_reference_index, SourceChar::Separator);
current_reference_index += 1;

result
.query
.insert(current_query_index, SourceChar::Separator);
current_query_index += 1;
}
debug_assert_eq!(current_reference_index, current_query_index);

while let Some(alignment_type) = alignment.next() {
match alignment_type {
Expand Down Expand Up @@ -127,6 +160,36 @@ impl TsSourceArrangement {
}
}

debug_assert_eq!(current_reference_index, current_query_index);

// If there are further source chars right of the alignment, we insert a separator into both sequences.
if result.reference_arrangement_to_source_column(current_reference_index)
< SourceColumn::new(reference_length - 1)
|| result.query_arrangement_to_source_column(current_query_index)
< SourceColumn::new(query_length - 1)
{
result
.reference
.insert(current_reference_index, SourceChar::Separator);
current_reference_index += 1;

result
.query
.insert(current_query_index, SourceChar::Separator);
current_query_index += 1;
}

debug_assert_eq!(current_reference_index, current_query_index);

// Fill the back with blanks to ensure equal length.
while result.reference.len() < result.query.len() {
result.reference.push(SourceChar::Blank);
}
while result.query.len() < result.reference.len() {
result.query.push(SourceChar::Blank);
}

debug_assert_eq!(result.reference.len(), result.query.len());
Ok(result)
}

Expand All @@ -147,12 +210,24 @@ impl TsSourceArrangement {
let sp1_query = self.query_arrangement_to_arrangement_char_column(*current_query_index);
let sp2_secondary = match ts_secondary {
TemplateSwitchSecondary::Reference => {
self.reference_arrangement_to_source_column(*current_reference_index)
let source_current_reference_index =
self.reference_arrangement_to_source_column(*current_reference_index);
trace!(
"current_reference_index: {current_reference_index} -> {source_current_reference_index}"
);
source_current_reference_index
}
TemplateSwitchSecondary::Query => {
self.query_arrangement_to_source_column(*current_query_index)
let source_current_query_index =
self.query_arrangement_to_source_column(*current_query_index);
trace!(
"current_query_index: {current_query_index} -> {source_current_query_index}"
);
source_current_query_index
}
} + first_offset;
trace!("first_offset: {first_offset}");
trace!("sp2_secondary: {sp2_secondary}");

let mut sp3_secondary = sp2_secondary;
let mut primary_inner_length = 0;
Expand Down Expand Up @@ -333,6 +408,7 @@ impl TsSourceArrangement {
}

pub fn width(&self) -> usize {
debug_assert_eq!(self.reference.len(), self.query.len());
self.reference.len()
}

Expand Down Expand Up @@ -574,22 +650,26 @@ impl SourceChar {
Self::Source { copy_depth, .. }
| Self::Hidden { copy_depth, .. }
| Self::Gap { copy_depth } => copy_depth.is_some(),
Self::Spacer | Self::Blank => panic!("Blank has no copy property"),
Self::Separator | Self::Spacer | Self::Blank => panic!("Blank has no copy property"),
}
}

pub fn copy_depth(&self) -> Option<usize> {
match self {
Self::Source { copy_depth, .. } | Self::Hidden { copy_depth, .. } => *copy_depth,
Self::Gap { copy_depth } => *copy_depth,
Self::Spacer | Self::Blank => panic!("Blank has no copy property"),
Self::Separator | Self::Spacer | Self::Blank => panic!("Blank has no copy property"),
}
}

pub fn to_lower_case(&mut self) {
match self {
Self::Source { lower_case, .. } => *lower_case = true,
Self::Hidden { .. } | Self::Gap { .. } | Self::Spacer | Self::Blank => {
Self::Hidden { .. }
| Self::Gap { .. }
| Self::Separator
| Self::Spacer
| Self::Blank => {
panic!("Not lowercasable: {self:?}")
}
}
Expand All @@ -598,7 +678,11 @@ impl SourceChar {
pub fn to_upper_case(&mut self) {
match self {
Self::Source { lower_case, .. } => *lower_case = false,
Self::Hidden { .. } | Self::Gap { .. } | Self::Spacer | Self::Blank => {
Self::Hidden { .. }
| Self::Gap { .. }
| Self::Separator
| Self::Spacer
| Self::Blank => {
panic!("Not uppercasable: {self:?}")
}
}
Expand All @@ -618,7 +702,7 @@ impl SourceChar {
};
}
Self::Hidden { .. } => unreachable!("Already hidden"),
Self::Gap { .. } | Self::Spacer | Self::Blank => {
Self::Gap { .. } | Self::Separator | Self::Spacer | Self::Blank => {
unreachable!("Cannot be hidden: {self:?}")
}
}
Expand All @@ -637,7 +721,7 @@ impl SourceChar {
column: *column,
copy_depth: Some(copy_depth.map(|copy_depth| copy_depth + 1).unwrap_or(0)),
},
Self::Gap { .. } | Self::Spacer | Self::Blank => {
Self::Gap { .. } | Self::Separator | Self::Spacer | Self::Blank => {
panic!("Should never be copied: {self:?}")
}
}
Expand All @@ -648,7 +732,7 @@ impl Char for SourceChar {
fn source_column(&self) -> SourceColumn {
match self {
Self::Source { column, .. } | Self::Hidden { column, .. } => *column,
Self::Gap { .. } | Self::Spacer | Self::Blank => panic!("Not a char"),
Self::Gap { .. } | Self::Separator | Self::Spacer | Self::Blank => panic!("Not a char"),
}
}

Expand Down
11 changes: 6 additions & 5 deletions raw_svg/font.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions raw_svg/label_font.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 26 additions & 0 deletions test_files/twin_heli_MDC1-AS1_10.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
type = "WithTarget"
alignment = [[1, "PrimarySubstitution"], [1, "PrimaryMatch"], [152, { TemplateSwitchEntrance = { first_offset = -151, equal_cost_range = { min_start = 0, max_start = 0, min_end = 0, max_end = 0 }, primary = "Reference", secondary = "Reference", direction = "Reverse" } }], [7, "SecondaryMatch"], [1, "SecondarySubstitution"], [2, "SecondaryMatch"], [69, { TemplateSwitchExit = { anti_primary_gap = 78 } }], [273, { TemplateSwitchEntrance = { first_offset = 272, equal_cost_range = { min_start = 0, max_start = 0, min_end = 0, max_end = 0 }, primary = "Query", secondary = "Reference", direction = "Reverse" } }], [5, "SecondaryMatch"], [1, "SecondaryInsertion"], [4, "SecondaryMatch"], [85, { TemplateSwitchExit = { anti_primary_gap = 94 } }], [2, "PrimaryMatch"], [1, "PrimarySubstitution"], [1, "PrimaryMatch"]]
reference_offset = 200
query_offset = 164
cost = 24.0
cost_per_base = 0.05263157894736842
duration_seconds = 69.622919049
opened_nodes = 50127278.0
closed_nodes = 22733640.0
suboptimal_opened_nodes = 4326095.0
suboptimal_opened_nodes_ratio = 0.09445378299508116
template_switch_amount = 2.0
runtime = 0.0
memory = 0.0

[result]
astar_result_type = "FoundTarget"
cost = 24

[sequences]
reference_name = "Homo_sapiens "
reference = "TCTTTACGGTGAACATCAGAGAAAACCCCCTCCTGTTGCAGTAACAGTTTTGAAATACACCAAGGGTGTTCCGGTCTCCCTAACAAAAACTTGCCTTCTCAGGGAAAATGCTTTGACAAAGTCTTCTCTGACCTAGGGGAAAAGCAGACACTCAACTCTGGCTGTATCTATCTGTCCTGTCTCCTTTGAAAGAGAAAGAAAAAAAACTGCTATGAAACAATTCTGGTCACAGGCCAGAAATTCAGCCTTATTTTAAAAATAGGACCTTACCAACATTCATCAACAGGGCTTCCATATAGTAAGAGTGGATTACAACTGAGAGAGCAGTAAGCCACAGACTCTATTTAGGAAATAGTTCTCAAGGAATCCCAGACAAGAGAGTGAAGAAACAACATCACAAGTCAACTACGGAAAACTAAAACCTGTGGCACTTACAGCTATAGCAAATACTAAACAAAACCCAGCTCATAGTCAGATTAACATAAAACCTCAC"
reference_rc = "GTGAGGTTTTATGTTAATCTGACTATGAGCTGGGTTTTGTTTAGTATTTGCTATAGCTGTAAGTGCCACAGGTTTTAGTTTTCCGTAGTTGACTTGTGATGTTGTTTCTTCACTCTCTTGTCTGGGATTCCTTGAGAACTATTTCCTAAATAGAGTCTGTGGCTTACTGCTCTCTCAGTTGTAATCCACTCTTACTATATGGAAGCCCTGTTGATGAATGTTGGTAAGGTCCTATTTTTAAAATAAGGCTGAATTTCTGGCCTGTGACCAGAATTGTTTCATAGCAGTTTTTTTTCTTTCTCTTTCAAAGGAGACAGGACAGATAGATACAGCCAGAGTTGAGTGTCTGCTTTTCCCCTAGGTCAGAGAAGACTTTGTCAAAGCATTTTCCCTGAGAAGGCAAGTTTTTGTTAGGGAGACCGGAACACCCTTGGTGTATTTCAAAACTGTTACTGCAACAGGAGGGGGTTTTCTCTGATGTTCACCGTAAAGA"
query_name = "PrimatesAnc069 "
query = "CTCTCCTGCTTAAGAACAGCTGCAGCCCACTCTGCCCCAGCATCCCCTTCTGCTGGAAGCTGGCTCTTTCTTACATCTGCAACTACTGAGGCTGTTAGGGAGGTGCCCTCCTCTGCATCTGTTTCACAGTCCCCATGCAGAGGCCAGGCTTCCTCTAGAGATACCACAAGCAGCTTTGCTGGTCCCCCAACTGCTTTCACATCTGTTTGATTTGTCCCCTCCACAGACACCTGATGCTTCTTTATATGTATAATGGCTGACCCTGGCGGGACTTCCTTCTCCACTTGTGTGTTGATGTCCACTGTGGTGGAGGCTTGGCTTCTCTCCAGGTGGATCCCAGGTGAGCTCTTATCTGCTTCCACACTGTCATCACTGTCCCCAAAAGGAGGTTGGTCCTTTTCTGAATGTGCTCTAACAAG"
query_rc = "CTTGTTAGAGCACATTCAGAAAAGGACCAACCTCCTTTTGGGGACAGTGATGACAGTGTGGAAGCAGATAAGAGCTCACCTGGGATCCACCTGGAGAGAAGCCAAGCCTCCACCACAGTGGACATCAACACACAAGTGGAGAAGGAAGTCCCGCCAGGGTCAGCCATTATACATATAAAGAAGCATCAGGTGTCTGTGGAGGGGACAAATCAAACAGATGTGAAAGCAGTTGGGGGACCAGCAAAGCTGCTTGTGGTATCTCTAGAGGAAGCCTGGCCTCTGCATGGGGACTGTGAAACAGATGCAGAGGAGGGCACCTCCCTAACAGCCTCAGTAGTTGCAGATGTAAGAAAGAGCCAGCTTCCAGCAGAAGGGGATGCTGGGGCAGAGTGGGCTGCAGCTGTTCTTAAGCAGGAGAG"
Loading
Loading