use std::path::Path;
use anyhow::{Context, Result};
use igv_core::render_inputs::{
AnnotationTrackSnapshot, BamTrackSnapshot, LinkTrackSnapshot, RenderInputs, SignalTrackSnapshot,
};
use igv_render::{render_png, render_svg, SvgOptions};
use crate::app::action::SnapshotFormat;
use crate::app::state::AppState;
pub fn inputs_from_state(state: &AppState) -> RenderInputs {
let bams = state
.bams
.iter()
.enumerate()
.map(|(i, t)| BamTrackSnapshot {
display: t.display.clone(),
rows: state.bam_rows.get(i).cloned().unwrap_or_default(),
lanes: state.bam_lanes.get(i).cloned().unwrap_or_default(),
total_lanes: state.bam_total_lanes.get(i).copied().unwrap_or(0),
})
.collect();
let annotations = state
.annotations
.iter()
.enumerate()
.map(|(i, t)| AnnotationTrackSnapshot {
display: t.display.clone(),
transcripts: state.annotation_rows.get(i).cloned().unwrap_or_default(),
})
.collect();
let signals = state
.signals
.iter()
.enumerate()
.map(|(i, t)| SignalTrackSnapshot {
display: t.display.clone(),
bins: state.signal_bins.get(i).cloned().unwrap_or_default(),
})
.collect();
let links = state
.links
.iter()
.enumerate()
.map(|(i, t)| LinkTrackSnapshot {
display: t.display.clone(),
visible: state.link_records.get(i).cloned().unwrap_or_default(),
total_record_count: t.source.record_count(),
})
.collect();
RenderInputs {
region: state.region.clone(),
references: state.references.clone(),
reference_seq: state.reference_seq.clone(),
variants: state.variants.clone(),
bams,
annotations,
signals,
links,
render_mode: state.render_mode(),
}
}
fn signal_shared_max(state: &AppState) -> Option<f32> {
if !state.signal_shared_scale {
return None;
}
let m = state
.signal_bins
.iter()
.flatten()
.map(|b| b.value)
.fold(0.0_f32, f32::max);
Some(m)
}
pub fn write_snapshot(state: &AppState, path: &Path, format: SnapshotFormat) -> Result<()> {
let inputs = inputs_from_state(state);
let opts = SvgOptions {
signal_shared_max: signal_shared_max(state),
..Default::default()
};
match format {
SnapshotFormat::Svg => {
let svg = render_svg(&inputs, &opts);
std::fs::write(path, svg).with_context(|| format!("write {}", path.display()))?;
}
SnapshotFormat::Png => {
let bytes = render_png(&inputs, &opts).with_context(|| "render PNG")?;
std::fs::write(path, bytes).with_context(|| format!("write {}", path.display()))?;
}
}
Ok(())
}