Skip to content

Commit e6e2928

Browse files
Fix non-pangenomic x-axis
1 parent 9da5626 commit e6e2928

File tree

1 file changed

+97
-55
lines changed

1 file changed

+97
-55
lines changed

src/main.rs

Lines changed: 97 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3557,17 +3557,6 @@ fn render(args: &Args, graph: &Graph) -> Vec<u8> {
35573557
}
35583558
}
35593559

3560-
// Draw horizontal axis line (PNG)
3561-
for x in path_names_width..total_width {
3562-
let idx = ((axis_y * total_width + x) * 4) as usize;
3563-
if idx + 3 < buffer.len() {
3564-
buffer[idx] = 0;
3565-
buffer[idx + 1] = 0;
3566-
buffer[idx + 2] = 0;
3567-
buffer[idx + 3] = 255;
3568-
}
3569-
}
3570-
35713560
// Calculate tick positions and labels
35723561
let num_ticks = args.x_ticks.max(2) as usize;
35733562
let is_pangenomic = coord_system.to_lowercase() == "pangenomic";
@@ -3579,40 +3568,73 @@ fn render(args: &Args, graph: &Graph) -> Vec<u8> {
35793568

35803569
// For pangenomic coordinates, use total graph length
35813570
// For path-based coordinates, find the path and use its length
3582-
let (coord_start, coord_end) = if is_pangenomic {
3583-
(0u64, len_to_visualize)
3571+
// Also calculate pixel range where the path actually appears
3572+
let (coord_start, coord_end, pixel_start, pixel_end) = if is_pangenomic {
3573+
(0u64, len_to_visualize, 0u32, viz_width)
35843574
} else if let Some(path) = graph.paths.iter().find(|p| p.name == *coord_system) {
3585-
let path_len: u64 = path
3586-
.steps
3587-
.iter()
3588-
.map(|step| {
3589-
let seg_id = step.segment_id as usize;
3590-
if seg_id < graph.segments.len() {
3591-
graph.segments[seg_id].sequence_len
3592-
} else {
3593-
0
3575+
// Calculate path length and pangenomic positions from its steps
3576+
let mut path_len: u64 = 0;
3577+
let mut pangenomic_start: Option<u64> = None;
3578+
let mut pangenomic_end: u64 = 0;
3579+
3580+
for step in &path.steps {
3581+
let seg_id = step.segment_id as usize;
3582+
if seg_id < graph.segments.len() {
3583+
let seg_len = graph.segments[seg_id].sequence_len;
3584+
let seg_offset = graph.segment_offsets[seg_id];
3585+
3586+
// Track first segment's pangenomic position
3587+
if pangenomic_start.is_none() {
3588+
pangenomic_start = Some(seg_offset);
35943589
}
3595-
})
3596-
.sum();
3590+
// Track last segment's end position
3591+
pangenomic_end = seg_offset + seg_len;
3592+
path_len += seg_len;
3593+
}
3594+
}
3595+
3596+
let pangenomic_start = pangenomic_start.unwrap_or(0);
3597+
3598+
// Convert pangenomic positions to pixel positions
3599+
let pix_start = ((pangenomic_start as f64 / bin_width) as u32).min(viz_width);
3600+
let pix_end = ((pangenomic_end as f64 / bin_width) as u32).min(viz_width);
3601+
35973602
// Add subpath start offset if --x-axis-absolute is enabled
35983603
let offset = if args.x_axis_absolute {
35993604
parse_subpath_start(coord_system)
36003605
} else {
36013606
0
36023607
};
3603-
(offset, offset + path_len)
3608+
(offset, offset + path_len, pix_start, pix_end)
36043609
} else {
36053610
debug!(
36063611
"Path '{}' not found, using pangenomic coordinates",
36073612
coord_system
36083613
);
3609-
(0u64, len_to_visualize)
3614+
(0u64, len_to_visualize, 0u32, viz_width)
36103615
};
36113616

3612-
// Draw ticks and labels
3617+
// Calculate the pixel width of the path's range
3618+
let path_pixel_width = pixel_end.saturating_sub(pixel_start);
3619+
3620+
// Draw horizontal axis line only where the path exists (PNG)
3621+
let axis_line_start = path_names_width + pixel_start;
3622+
let axis_line_end = path_names_width + pixel_end;
3623+
for x in axis_line_start..axis_line_end {
3624+
let idx = ((axis_y * total_width + x) * 4) as usize;
3625+
if idx + 3 < buffer.len() {
3626+
buffer[idx] = 0;
3627+
buffer[idx + 1] = 0;
3628+
buffer[idx + 2] = 0;
3629+
buffer[idx + 3] = 255;
3630+
}
3631+
}
3632+
3633+
// Draw ticks and labels only where the path exists
36133634
for i in 0..num_ticks {
36143635
let t = i as f64 / (num_ticks - 1) as f64;
3615-
let x_pos = path_names_width + (t * (viz_width as f64 - 1.0)) as u32;
3636+
// Map tick position to the path's pixel range
3637+
let x_pos = path_names_width + pixel_start + (t * (path_pixel_width as f64 - 1.0).max(0.0)) as u32;
36163638
let coord_value = coord_start as f64 + t * (coord_end - coord_start) as f64;
36173639

36183640
// Draw tick mark
@@ -4956,9 +4978,8 @@ fn render_svg(args: &Args, graph: &Graph) -> String {
49564978
// Y position for the axis line (at the bottom of paths)
49574979
let axis_y = path_space_with_gap + axis_padding;
49584980

4959-
// X start and end of the axis line
4981+
// X start of the axis line (end will be calculated based on path's pangenomic extent)
49604982
let axis_x_start = dendrogram_width + cluster_bar_width + text_width;
4961-
let axis_x_end = total_width;
49624983

49634984
// Draw axis label on the left
49644985
// Strip the :start-end range from the label when showing absolute coordinates
@@ -4988,13 +5009,6 @@ fn render_svg(args: &Args, graph: &Graph) -> String {
49885009
));
49895010
svg.push('\n');
49905011

4991-
// Draw horizontal axis line
4992-
svg.push_str(&format!(
4993-
r#"<line x1="{}" y1="{}" x2="{}" y2="{}" stroke="black" stroke-width="1"/>"#,
4994-
axis_x_start, axis_y, axis_x_end, axis_y
4995-
));
4996-
svg.push('\n');
4997-
49985012
// Calculate tick positions and labels
49995013
let num_ticks = args.x_ticks.max(2) as usize;
50005014
let is_pangenomic = coord_system.to_lowercase() == "pangenomic";
@@ -5006,45 +5020,73 @@ fn render_svg(args: &Args, graph: &Graph) -> String {
50065020

50075021
// For pangenomic coordinates, use total graph length
50085022
// For path-based coordinates, find the path and use its length
5009-
let (coord_start, coord_end) = if is_pangenomic {
5010-
(0u64, len_to_visualize)
5023+
// Also calculate pixel range where the path actually appears
5024+
let (coord_start, coord_end, pixel_start, pixel_end) = if is_pangenomic {
5025+
(0u64, len_to_visualize, 0.0f64, viz_width as f64)
50115026
} else {
50125027
// Find the path with the specified name
50135028
if let Some(path) = graph.paths.iter().find(|p| p.name == *coord_system) {
5014-
// Calculate path length from its steps
5015-
let path_len: u64 = path
5016-
.steps
5017-
.iter()
5018-
.map(|step| {
5019-
let seg_id = step.segment_id as usize;
5020-
if seg_id < graph.segments.len() {
5021-
graph.segments[seg_id].sequence_len
5022-
} else {
5023-
0
5029+
// Calculate path length and pangenomic positions from its steps
5030+
let mut path_len: u64 = 0;
5031+
let mut pangenomic_start: Option<u64> = None;
5032+
let mut pangenomic_end: u64 = 0;
5033+
5034+
for step in &path.steps {
5035+
let seg_id = step.segment_id as usize;
5036+
if seg_id < graph.segments.len() {
5037+
let seg_len = graph.segments[seg_id].sequence_len;
5038+
let seg_offset = graph.segment_offsets[seg_id];
5039+
5040+
// Track first segment's pangenomic position
5041+
if pangenomic_start.is_none() {
5042+
pangenomic_start = Some(seg_offset);
50245043
}
5025-
})
5026-
.sum();
5044+
// Track last segment's end position
5045+
pangenomic_end = seg_offset + seg_len;
5046+
path_len += seg_len;
5047+
}
5048+
}
5049+
5050+
let pangenomic_start = pangenomic_start.unwrap_or(0);
5051+
5052+
// Convert pangenomic positions to pixel positions
5053+
let pix_start = (pangenomic_start as f64 / bin_width).min(viz_width as f64);
5054+
let pix_end = (pangenomic_end as f64 / bin_width).min(viz_width as f64);
5055+
50275056
// Add subpath start offset if --x-axis-absolute is enabled
50285057
let offset = if args.x_axis_absolute {
50295058
parse_subpath_start(coord_system)
50305059
} else {
50315060
0
50325061
};
5033-
(offset, offset + path_len)
5062+
(offset, offset + path_len, pix_start, pix_end)
50345063
} else {
50355064
// Path not found, fall back to pangenomic
50365065
debug!(
50375066
"Path '{}' not found, using pangenomic coordinates",
50385067
coord_system
50395068
);
5040-
(0u64, len_to_visualize)
5069+
(0u64, len_to_visualize, 0.0f64, viz_width as f64)
50415070
}
50425071
};
50435072

5044-
// Draw ticks
5073+
// Calculate the pixel width of the path's range
5074+
let path_pixel_width = pixel_end - pixel_start;
5075+
5076+
// Draw horizontal axis line only where the path exists
5077+
let axis_line_x_start = axis_x_start as f64 + pixel_start;
5078+
let axis_line_x_end = axis_x_start as f64 + pixel_end;
5079+
svg.push_str(&format!(
5080+
r#"<line x1="{:.1}" y1="{}" x2="{:.1}" y2="{}" stroke="black" stroke-width="1"/>"#,
5081+
axis_line_x_start, axis_y, axis_line_x_end, axis_y
5082+
));
5083+
svg.push('\n');
5084+
5085+
// Draw ticks only where the path exists
50455086
for i in 0..num_ticks {
50465087
let t = i as f64 / (num_ticks - 1) as f64;
5047-
let x_pos = axis_x_start as f64 + t * (viz_width as f64 - 1.0);
5088+
// Map tick position to the path's pixel range
5089+
let x_pos = axis_x_start as f64 + pixel_start + t * (path_pixel_width - 1.0).max(0.0);
50485090
let coord_value = coord_start as f64 + t * (coord_end - coord_start) as f64;
50495091

50505092
// Draw tick mark

0 commit comments

Comments
 (0)