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
76 changes: 65 additions & 11 deletions lib_tsshow/src/svg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ mod numbers;

const SVG_PADDING: f32 = 10.0;
const COPY_COLORS: &[&str] = &["#00CC00", "#009900", "#006600", "#003300"];
const OPTIONAL_COPY_COLORS: &[&str] = &["#88CC88", "#669966", "#446644", "#223322"];
const OPTIONAL_SOURCE_COLOR: &str = "blue";
Comment thread
sebschmi marked this conversation as resolved.
const COMPLEMENT_SOURCE_HIDDEN_COLOR: &str = "grey";
const TS_RUNNING_NUMBER: &str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

Expand All @@ -61,6 +63,7 @@ pub struct SvgConfig {
/// Restrict the context around the template switches to this many characters on each side.
/// If `None`, the full sequences will be rendered.
pub restrict_context: Option<usize>,
pub visualise_equal_cost_ranges: bool,
}

pub fn create_ts_svg(
Expand Down Expand Up @@ -92,6 +95,7 @@ pub fn create_ts_svg(
reference.len(),
query.len(),
alignment.iter_flat_cloned(),
config.visualise_equal_cost_ranges,
)?;

if config.render_more_complement {
Expand Down Expand Up @@ -274,8 +278,8 @@ pub fn create_ts_svg(
)
.skip(primary_sp4_minus_one.unwrap_or(0.into()).into())
.find(|(_, c)| !c.is_blank())
.unwrap()
.0,
.map(|(column, _)| column)
.unwrap_or(ts_arrangement.query().len().into()),
TsArrangementRow::Query,
),
};
Expand Down Expand Up @@ -801,11 +805,12 @@ fn render_source_char(
c
};

Character::new_char(c, CharacterData::new_colored(copy_color(copy_depth)))
}
SourceChar::Gap { copy_depth } => {
Character::new_char('-', CharacterData::new_colored(copy_color(copy_depth)))
Character::new_char(c, CharacterData::new_colored(copy_color(copy_depth, false)))
}
SourceChar::Gap { copy_depth } => Character::new_char(
'-',
CharacterData::new_colored(copy_color(copy_depth, false)),
),
SourceChar::Separator => Character::new_char_with_default('|'),
SourceChar::Hidden { .. } | SourceChar::Spacer | SourceChar::Blank => {
Character::new_char_with_default(' ')
Expand Down Expand Up @@ -867,11 +872,25 @@ fn render_inner_char(
} else {
c
};
Character::new_char(c, CharacterData::new_colored(copy_color(copy_depth)))
Character::new_char(c, CharacterData::new_colored(copy_color(copy_depth, false)))
}
InnerChar::Gap { copy_depth } => {
Character::new_char('-', CharacterData::new_colored(copy_color(copy_depth)))
InnerChar::OptionalInner {
column,
lower_case,
copy_depth,
} => {
let c = source_sequence.char_at(column.into());
let c = if *lower_case {
c.to_ascii_lowercase()
} else {
c
};
Character::new_char(c, CharacterData::new_colored(copy_color(copy_depth, true)))
}
InnerChar::Gap { copy_depth } => Character::new_char(
'-',
CharacterData::new_colored(copy_color(copy_depth, false)),
),
InnerChar::Blank => Character::new_char(' ', Default::default()),
}
}
Expand All @@ -880,9 +899,15 @@ fn render_label_char(c: char) -> Character<CharacterData> {
Character::new_char(c, CharacterData::new_colored("#555555"))
}

fn copy_color(copy_depth: &Option<usize>) -> impl ToString {
fn copy_color(copy_depth: &Option<usize>, is_optional: bool) -> impl ToString {
if let Some(copy_depth) = copy_depth {
COPY_COLORS[copy_depth % COPY_COLORS.len()]
if is_optional {
OPTIONAL_COPY_COLORS[copy_depth % OPTIONAL_COPY_COLORS.len()]
} else {
COPY_COLORS[copy_depth % COPY_COLORS.len()]
}
} else if is_optional {
OPTIONAL_SOURCE_COLOR
} else {
"black"
}
Expand Down Expand Up @@ -946,6 +971,20 @@ fn legend(reference_name: &str, query_name: &str, scale: f32) -> (Group, f32, f3
));
label_width =
label_width.max(copy_label.chars().count() as f32 * typewriter::FONT.character_width);
y += typewriter::FONT
.character_height
.max(sans_serif_mono::FONT.character_height);

let uncertainty_label = "BLUE CHARACTERS";
result = result.add(svg_string(
uncertainty_label
.chars()
.map(|c| Character::new_char(c, CharacterData::new_colored(OPTIONAL_SOURCE_COLOR))),
&SvgLocation { x: 0.0, y },
&typewriter::FONT,
));
label_width = label_width
.max(uncertainty_label.chars().count() as f32 * typewriter::FONT.character_width);

// Explanations.
let label_width = label_width + typewriter::FONT.character_width;
Expand Down Expand Up @@ -979,6 +1018,21 @@ fn legend(reference_name: &str, query_name: &str, scale: f32) -> (Group, f32, f3
.character_height
.max(sans_serif_mono::FONT.character_height);

let uncertainty_explanation = "Equal-cost range of the TSM";
result = result.add(svg_string(
uncertainty_explanation
.chars()
.map(Character::<CharacterData>::new_char_with_default),
&SvgLocation { x: label_width, y },
&sans_serif_mono::FONT,
));
explanation_width = explanation_width.max(
uncertainty_explanation.chars().count() as f32 * sans_serif_mono::FONT.character_width,
);
y += typewriter::FONT
.character_height
.max(sans_serif_mono::FONT.character_height);

result = result.set("transform", format!("scale({scale})"));
let legend_width = headline_width.max(label_width + explanation_width) * scale;
let legend_height = y * scale;
Expand Down
50 changes: 42 additions & 8 deletions lib_tsshow/src/ts_arrangement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ impl TsArrangement {
reference_length: usize,
query_length: usize,
alignment: impl IntoIterator<Item = AlignmentType>,
visualise_equal_cost_ranges: bool,
) -> Result<Self> {
let mut template_switches = Vec::new();
let mut source = TsSourceArrangement::new(
Expand All @@ -49,7 +50,12 @@ impl TsArrangement {
&mut template_switches,
)?;
let mut complement = TsComplementArrangement::new(&source);
let inner = TsInnerArrangement::new(&mut source, &mut complement, template_switches);
let inner = TsInnerArrangement::new(
&mut source,
&mut complement,
template_switches,
visualise_equal_cost_ranges,
);

Ok(Self {
source,
Expand Down Expand Up @@ -333,6 +339,18 @@ impl TsArrangement {
inner.template_switch().sp4_reference,
),
self.query_arrangement_char_to_source_column(inner.template_switch().sp4_query),
inner
.sequence()
.iter_values()
.filter_map(|c| {
if c.is_gap_or_blank() {
None
} else {
Some(c.source_column())
}
})
.next()
.unwrap(),
Comment thread
sebschmi marked this conversation as resolved.
]
.into_iter()
.min()
Expand All @@ -350,14 +368,31 @@ impl TsArrangement {
[
self.reference_arrangement_char_to_source_column(
inner.template_switch().sp1_reference,
),
self.query_arrangement_char_to_source_column(inner.template_switch().sp1_query),
inner.template_switch().sp2_secondary,
inner.template_switch().sp3_secondary,
)
.saturating_sub(1),
self.query_arrangement_char_to_source_column(inner.template_switch().sp1_query)
.saturating_sub(1),
inner.template_switch().sp2_secondary.saturating_sub(1),
inner.template_switch().sp3_secondary.saturating_sub(1),
self.reference_arrangement_char_to_source_column(
inner.template_switch().sp4_reference,
),
self.query_arrangement_char_to_source_column(inner.template_switch().sp4_query),
)
.saturating_sub(1),
self.query_arrangement_char_to_source_column(inner.template_switch().sp4_query)
.saturating_sub(1),
inner
.sequence()
.iter_values()
.rev()
.filter_map(|c| {
if c.is_gap_or_blank() {
None
} else {
Some(c.source_column())
}
})
.next()
.unwrap(),
]
Comment thread
sebschmi marked this conversation as resolved.
.into_iter()
.max()
Expand All @@ -370,6 +405,5 @@ impl TsArrangement {
.max(self.source.query_length())
.into(),
)
.saturating_sub(1)
}
}
10 changes: 10 additions & 0 deletions lib_tsshow/src/ts_arrangement/index_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,16 @@ macro_rules! index_type_ops {
}
}

impl std::ops::Sub<$signed_inner> for $name {
type Output = Self;

fn sub(self, other: $signed_inner) -> Self::Output {
Self(
<$inner>::try_from(<$signed_inner>::try_from(self.0).unwrap() - other).unwrap(),
)
}
}

impl std::ops::AddAssign<$inner> for $name {
fn add_assign(&mut self, other: $inner) {
self.0 += other
Expand Down
Loading
Loading