Skip to content

Commit

Permalink
Update to version 1.3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
egor-dolzhenko committed Nov 19, 2024
1 parent 32e65e8 commit 881174c
Show file tree
Hide file tree
Showing 31 changed files with 1,855 additions and 1,686 deletions.
539 changes: 306 additions & 233 deletions Cargo.lock

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
[package]
name = "trgt"
version = "1.2.0"
version = "1.3.0"
edition = "2021"
build = "build.rs"

[workspace]
members = ["crates/pipeplot"]

[build-dependencies]
vergen = { version = "8.2", features = ["git", "gitcl"] }

Expand All @@ -20,11 +23,8 @@ kodama = "0.3"
rand = "0.8"
once_cell = "1.18"
flate2 = "1.0"
resvg = "0.36"
usvg = "0.36"
tiny-skia = "0.11"
svg2pdf = "0.9"
tempfile = "3"
rayon = "1.10"
crossbeam-channel = "0.5"
semver = "1.0"
pipeplot = { path = "crates/pipeplot" }
semver = "1.0"
tempfile = "3"
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,12 @@ tandem repeats at genome scale. 2024](https://www.nature.com/articles/s41587-023
- Merging now skips and logs problematic loci by default. Use the `--quit-on-errors` flag to terminate on errors. Statistics are logged post-merge, including counts of failed and skipped TRs.
- `trgt validate`
- Always outputs statistics directly to stdout and stderr instead of logging them.
- Bug fix:
- Bug fix:
- Resolved issue with handling bgzip-compressed BED files.
- 1.3.0
- Plotting code has been refactored as we prepare to revamp repeat visualizations
- The maximum number of reads per allele to plot can now be specified by `--max-allele-reads`
- bugfix: repeat identifiers are now permitted to contain commas

### DISCLAIMER

Expand Down
13 changes: 13 additions & 0 deletions crates/pipeplot/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "pipeplot"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
resvg = "0.36"
usvg = "0.36"
tiny-skia = "0.11"
svg2pdf = "0.9"
tempfile = "3"
46 changes: 46 additions & 0 deletions crates/pipeplot/src/image.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use crate::{pdf, png, svg, PipePlot};
use std::path::{Path, PathBuf};
use tempfile::NamedTempFile;

pub fn generate(plot: &PipePlot, path: &PathBuf) -> Result<(), String> {
let extension = Path::new(path)
.extension()
.and_then(|ext| ext.to_str())
.ok_or_else(|| format!("Failed to get extension from path: {path:?}"))?;
let file_type = FileType::from_extension(extension)
.ok_or_else(|| format!("Unsupported file extension: {extension:?}"))?;

let temp_dir = PathBuf::from(&path);
let temp_dir = temp_dir
.parent()
.ok_or_else(|| format!("Invalid path: {path:?}"))?;
let svg_temp_path = NamedTempFile::new_in(temp_dir)
.map_err(|e| format!("Failed to create temporary file: {e}"))?
.into_temp_path();

svg::generate(plot, &svg_temp_path.to_path_buf());
match file_type {
FileType::Svg => svg_temp_path.persist(path).map_err(|e| e.to_string())?,
FileType::Png => png::render(&svg_temp_path.to_path_buf(), path)?,
FileType::Pdf => pdf::render(&svg_temp_path.to_path_buf(), path)?,
}
Ok(())
}

#[derive(Debug, PartialEq)]
enum FileType {
Svg,
Png,
Pdf,
}

impl FileType {
fn from_extension(extension: &str) -> Option<Self> {
match extension.to_lowercase().as_str() {
"svg" => Some(FileType::Svg),
"png" => Some(FileType::Png),
"pdf" => Some(FileType::Pdf),
_ => None,
}
}
}
18 changes: 18 additions & 0 deletions crates/pipeplot/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*!
This crate provides functionality to generate the so-called "pipe plots"
consisting of stacked horizontal pipes (bars). Each pipe consists of segments of
specified width, shape, and color. Pipe plots can be annotated with scales,
labels, and legends. The crate supports rendering of pipe plots as SVG, PNG, and
PDF images.
Pipe plots are useful for representing pileups of sequenced reads.
*/

mod image;
mod pdf;
mod pipeplot;
mod png;
mod svg;

pub use image::generate as generate_image;
pub use pipeplot::{Band, Color, Legend, Pipe, PipePlot, Seg, Shape};
8 changes: 5 additions & 3 deletions src/trvz/pdf.rs → crates/pipeplot/src/pdf.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use std::path::PathBuf;
use usvg::{TreeParsing, TreeTextToPath};

pub fn render(svg_path: &str, pdf_path: &str) {
let svg = std::fs::read_to_string(svg_path).unwrap();
pub fn render(svg_path: &PathBuf, pdf_path: &PathBuf) -> Result<(), String> {
let svg = std::fs::read_to_string(svg_path).map_err(|e| e.to_string())?;
let options = usvg::Options::default();
let mut tree = usvg::Tree::from_str(&svg, &options).expect("Error parsing SVG");
let mut db = usvg::fontdb::Database::new();
db.load_system_fonts();
tree.convert_text(&db);
let pdf = svg2pdf::convert_tree(&tree, svg2pdf::Options::default());
std::fs::write(pdf_path, pdf).unwrap();
std::fs::write(pdf_path, pdf).map_err(|e| e.to_string())?;
Ok(())
}
48 changes: 48 additions & 0 deletions crates/pipeplot/src/pipeplot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#[derive(Debug, PartialEq)]
pub enum Shape {
Rect,
HLine,
VLine,
None,
Tick(Option<u32>),
}

pub type Color = String;

#[derive(Debug, PartialEq)]
pub struct Seg {
pub width: u32,
pub color: Color,
pub shape: Shape,
}

#[derive(Debug)]
pub struct Band {
pub pos: u32, // Position relative to pipe's start
pub width: u32,
pub color: Color,
}

#[derive(Debug)]
pub struct Pipe {
pub xpos: u32,
pub ypos: u32,
pub height: u32,
pub segs: Vec<Seg>,
pub bands: Vec<Band>,
pub outline: bool,
}

#[derive(Debug)]
pub struct Legend {
pub xpos: u32,
pub ypos: u32,
pub height: u32,
pub labels: Vec<(String, String)>,
}

#[derive(Debug)]
pub struct PipePlot {
pub pipes: Vec<Pipe>,
pub legend: Legend,
}
13 changes: 8 additions & 5 deletions src/trvz/png.rs → crates/pipeplot/src/png.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
use std::path::PathBuf;
use usvg::{TreeParsing, TreeTextToPath};

pub fn render(svg_path: &str, png_path: &str) {
let svg = std::fs::read(svg_path).unwrap();
pub fn render(svg_path: &PathBuf, png_path: &PathBuf) -> Result<(), String> {
let svg = std::fs::read(svg_path).map_err(|e| e.to_string())?;
let options = usvg::Options::default();
let mut tree = usvg::Tree::from_data(&svg, &options).unwrap();
let mut tree = usvg::Tree::from_data(&svg, &options).map_err(|e| e.to_string())?;
let mut db = usvg::fontdb::Database::new();
db.load_system_fonts();
tree.convert_text(&db);
let pixmap_size = tree.size.to_int_size();
let mut pixmap = tiny_skia::Pixmap::new(pixmap_size.width(), pixmap_size.height()).unwrap();
let mut pixmap = tiny_skia::Pixmap::new(pixmap_size.width(), pixmap_size.height())
.ok_or("Unable to init image".to_string())?;
let tree = resvg::Tree::from_usvg(&tree);
tree.render(resvg::usvg::Transform::identity(), &mut pixmap.as_mut());
pixmap.save_png(png_path).unwrap();
pixmap.save_png(png_path).map_err(|e| e.to_string())?;
Ok(())
}
Loading

0 comments on commit 881174c

Please sign in to comment.