Display all transfers in a well with fill as pie piece

This commit is contained in:
Emilia Allison 2025-11-26 21:39:23 -05:00
parent 7470fea541
commit 60bfd39dc9
Signed by: emilia
GPG Key ID: FEC1CE6360EEC9A8
2 changed files with 73 additions and 14 deletions

View File

@ -35,16 +35,16 @@ impl Default for PlateUiState {
} }
} }
#[derive(Clone, Copy, Debug)] #[derive(Clone, Debug)]
struct WellInfo { struct WellInfo {
volume: f32, volume: f32,
color: [f64; 3], color: Vec<[f64; 3]>,
highlight: bool, highlight: bool,
fill: bool, fill: bool,
} }
impl WellInfo { impl WellInfo {
fn new(volume: f32, color: [f64; 3]) -> Self { fn new(volume: f32, color: Vec<[f64; 3]>) -> Self {
WellInfo { WellInfo {
volume, volume,
color, color,
@ -61,6 +61,7 @@ pub struct PlateDisplayOptions {
pub show_well_volumes: bool, pub show_well_volumes: bool,
pub show_volume_heatmap: bool, pub show_volume_heatmap: bool,
pub show_coordinates: bool, pub show_coordinates: bool,
pub show_pie_piece_shading: bool,
} }
impl Default for PlateDisplayOptions { impl Default for PlateDisplayOptions {
fn default() -> Self { fn default() -> Self {
@ -69,6 +70,7 @@ impl Default for PlateDisplayOptions {
show_well_volumes: true, show_well_volumes: true,
show_volume_heatmap: false, show_volume_heatmap: false,
show_coordinates: true, show_coordinates: true,
show_pie_piece_shading: true,
} }
} }
} }
@ -202,10 +204,10 @@ fn calculate_shading_for_wells(
// Well info already existed. // Well info already existed.
x.volume += volume; x.volume += volume;
x.color = if display_options.show_volume_heatmap { if display_options.show_volume_heatmap {
PALETTE.get_linear(x.volume.into(), max_volume.into()) x.color = vec![PALETTE.get_linear(x.volume.into(), max_volume.into())];
} else { } else {
PALETTE.get_ordered(transfer.id, ordered_ids) x.color.push(PALETTE.get_ordered(transfer.id, ordered_ids));
}; };
} else { } else {
// Well info does not already exist, we need to make it. // Well info does not already exist, we need to make it.
@ -216,9 +218,9 @@ fn calculate_shading_for_wells(
*wi = Some(WellInfo::new( *wi = Some(WellInfo::new(
volume, volume,
if display_options.show_volume_heatmap { if display_options.show_volume_heatmap {
PALETTE.get_linear(volume.into(), max_volume.into()) vec![PALETTE.get_linear(volume.into(), max_volume.into())]
} else { } else {
PALETTE.get_ordered(transfer.id, ordered_ids) vec![PALETTE.get_ordered(transfer.id, ordered_ids)]
}, },
)); ));
} }
@ -253,6 +255,45 @@ fn draw_cross(painter: &egui::Painter, center: egui::Pos2, radius: f32, stroke:
painter.line_segment([pts[1], pts[3]], stroke); painter.line_segment([pts[1], pts[3]], stroke);
} }
fn draw_multicolor_circle(
painter: &egui::Painter,
center: egui::Pos2,
radius: f32,
colors: &[[f64; 3]],
) {
if colors.is_empty() {
return;
}
let adjusted_radius = radius * 0.80f32;
let angle_per_slice_rad = std::f32::consts::TAU / colors.len() as f32;
for (index, color) in colors.iter().enumerate() {
let start_angle = index as f32 * angle_per_slice_rad;
let stop_angle = (index + 1) as f32 * angle_per_slice_rad;
let mut points = vec![center];
const NUM_POINTS: u8 = 32;
for j in 0..=NUM_POINTS {
let t = j as f32 / NUM_POINTS as f32;
let angle = start_angle + t * angle_per_slice_rad;
let x = center.x + adjusted_radius * angle.cos();
let y = center.y + adjusted_radius * angle.sin();
points.push(egui::pos2(x, y));
}
points.push(center);
painter.add(egui::Shape::convex_polygon(
points,
f64_to_color32(*color),
egui::Stroke::NONE,
));
}
}
fn add_plate_sub( fn add_plate_sub(
size: egui::Vec2, size: egui::Vec2,
rows: u8, rows: u8,
@ -371,9 +412,11 @@ fn add_plate_sub(
if let Some(mut well_info) = if let Some(mut well_info) =
well_infos.get_mut((w.0 - 1) * columns as usize + (w.1 - 1)) well_infos.get_mut((w.0 - 1) * columns as usize + (w.1 - 1))
{ {
let volume = well_info.map(|x| x.volume).unwrap_or(0.0); let (volume, color, fill) = if let Some(ref info) = well_info {
let color = well_info.map(|x| x.color).unwrap_or([255.0, 255.0, 255.0]); (info.volume, info.color.clone(), info.fill)
let fill = well_info.map(|x| x.color).is_some(); } else {
(0.0, vec![[255.0, 255.0, 255.0]], false)
};
*well_info = Some(WellInfo { *well_info = Some(WellInfo {
color, color,
@ -414,10 +457,20 @@ fn add_plate_sub(
// //
if let Some(well_info) = if let Some(well_info) =
well_infos[(c_row - 1) as usize * columns as usize + (c_column - 1) as usize] &well_infos[(c_row - 1) as usize * columns as usize + (c_column - 1) as usize]
{ {
if well_info.fill { if well_info.fill {
painter.circle_filled(center, radius * 0.80, f64_to_color32(well_info.color)); if display_options.show_pie_piece_shading && !display_options.show_volume_heatmap {
draw_multicolor_circle(&painter, center, radius, &well_info.color);
} else {
painter.circle_filled(
center,
radius * 0.80,
f64_to_color32(
*well_info.color.first().unwrap_or(&[255.0, 255.0, 255.0]),
),
);
}
} }
if well_info.highlight && display_options.show_transfer_hashes { if well_info.highlight && display_options.show_transfer_hashes {
draw_cross(&painter, center, radius * 0.80, *STROKE_CURRENT); draw_cross(&painter, center, radius * 0.80, *STROKE_CURRENT);
@ -428,7 +481,7 @@ fn add_plate_sub(
if display_options.show_well_volumes { if display_options.show_well_volumes {
if let Some(well_info) = if let Some(well_info) =
well_infos[(c_row - 1) as usize * columns as usize + (c_column - 1) as usize] &well_infos[(c_row - 1) as usize * columns as usize + (c_column - 1) as usize]
{ {
painter.text( painter.text(
center, center,

View File

@ -206,6 +206,12 @@ fn render_options_menu(
&mut main_window_state.plate_display_options.show_well_volumes, &mut main_window_state.plate_display_options.show_well_volumes,
"Show volumes in wells", "Show volumes in wells",
); );
ui.toggle_value(
&mut main_window_state
.plate_display_options
.show_pie_piece_shading,
"Show well shading as pie pieces",
);
ui.toggle_value( ui.toggle_value(
&mut main_window_state.plate_display_options.show_volume_heatmap, &mut main_window_state.plate_display_options.show_volume_heatmap,
"Toggle volume heatmap", "Toggle volume heatmap",