Skip to content

Commit

Permalink
chore: add scaffold
Browse files Browse the repository at this point in the history
  • Loading branch information
lhao03 committed Aug 9, 2024
1 parent 7132073 commit 21c72c4
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 151 deletions.
136 changes: 8 additions & 128 deletions src-tauri/src/blocker.rs
Original file line number Diff line number Diff line change
@@ -1,139 +1,19 @@
use std::{cmp, f64::INFINITY};
use bitvec::{order::Msb0, vec::BitVec};

use crate::primer::Base;

#[derive(Clone)]
pub enum DataType {
Base(Base),
Bit(bool),
}

pub trait Blocker {
fn block(
&self,
sequence: Vec<DataType>,
per_segment: usize,
per_overlap: usize,
) -> Vec<Vec<DataType>>;
fn deblock(&self, blocks: Vec<Vec<DataType>>) -> Vec<DataType>;
}
use crate::metadata::MetaData;

pub struct BitBlocker {}
impl Blocker for BitBlocker {
fn block(
impl BitBlocker {
pub fn block(
&self,
sequence: Vec<DataType>,
mut metadata: MetaData,
sequence: BitVec<u8, Msb0>,
per_segment: usize,
per_overlap: usize,
) -> Vec<Vec<DataType>> {
) -> Vec<BitVec<u8, Msb0>> {
todo!()
}

fn deblock(&self, blocks: Vec<Vec<DataType>>) -> Vec<DataType> {
todo!()
}
}

pub struct DNABlocker {}
impl Blocker for DNABlocker {
fn block(
&self,
sequence: Vec<DataType>,
per_segment: usize,
per_overlap: usize,
) -> Vec<Vec<DataType>> {
let mut iter = sequence.windows(per_segment);
let mut dna_sequences = Vec::new();
while let Some(next_segment) = iter.next() {
dna_sequences.push(next_segment.to_vec());
}
dna_sequences
}

fn deblock(&self, dna_blocks: Vec<Vec<DataType>>) -> Vec<DataType> {
// 1. find overlaps with dynamic programming
for first_dna_seg in &dna_blocks {
for second_dna_seg in &dna_blocks {
// TODO: fill_in_overlap_matrix(first_dna_seg, second_dna_seg);
}
}
pub fn deblock(&self, sequences: Vec<BitVec<u8, Msb0>>) -> BitVec<u8, Msb0> {
todo!()
// 2.
// 3.
}
}

fn init_overlap_matrix(overlap_matrix: &mut [&mut [f64]]) {
// first column gets 0s
let dimension = overlap_matrix.len();
for j in 0..dimension {
overlap_matrix[j][0] = 0 as f64;
}
// first row get infinity
for i in 0..dimension {
overlap_matrix[0][i] = INFINITY;
}
}

fn min_dist(
overlap_matrix: &mut [&mut [f64]],
first_dna_seg: &Vec<Base>,
second_dna_seg: &Vec<Base>,
i: f64,
j: f64,
) -> usize {
let s = vec![
vec![0, 4, 2, 4, 8],
vec![4, 0, 4, 2, 8],
vec![2, 4, 0, 4, 8],
vec![4, 2, 4, 0, 8],
vec![8, 8, 8, 8, 8],
];

let i_minus_1_s_index = match first_dna_seg[i as usize - 1] {
Base::A => 0,
Base::T => 3,
Base::G => 2,
Base::C => 1,
};

let j_minus_1_s_index = match second_dna_seg[j as usize - 1] {
Base::A => 0,
Base::T => 3,
Base::G => 2,
Base::C => 1,
};

let i_minus_1 = overlap_matrix[i as usize - 1][j as usize] + s[i_minus_1_s_index][4] as f64;
let j_minus_1 = overlap_matrix[i as usize][j as usize - 1] + s[4][j_minus_1_s_index] as f64;
let i_minus_1_j_minus_1 = overlap_matrix[i as usize - 1][j as usize - 1]
+ s[i_minus_1_s_index][j_minus_1_s_index] as f64;

cmp::min(
i_minus_1 as usize,
cmp::min(j_minus_1 as usize, i_minus_1_j_minus_1 as usize),
)
}

fn fill_in_overlap_matrix(first_dna_seg: &Vec<Base>, second_dna_seg: &Vec<Base>) {
let dimension = first_dna_seg.len();
let mut grid_raw = vec![0 as f64; dimension];
let mut grid_base: Vec<_> = grid_raw.as_mut_slice().chunks_mut(dimension).collect();

let mut overlap_matrix = grid_base.as_mut_slice();

init_overlap_matrix(overlap_matrix);

for i in 0..dimension {
for j in 0..dimension {
overlap_matrix[i][j] = min_dist(
overlap_matrix,
&first_dna_seg,
&second_dna_seg,
i as f64,
j as f64,
) as f64;
}
}
todo!()
}
69 changes: 46 additions & 23 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
#![feature(iter_map_windows)]
#![feature(iter_array_chunks)]

use blocker::BitBlocker;
use fasta::{FastaBase, FastaParser, Parser};
use metadata::MetaData;
use primer::{Base, MeltingTemperature, Primer, PrimerInfo};
use scaffolder::Scaffolder;
#[cfg(test)]
extern crate quickcheck;
#[cfg(test)]
Expand All @@ -28,6 +30,7 @@ mod encoder;
mod fasta;
mod metadata;
mod primer;
mod scaffolder;

// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
#[tauri::command]
Expand All @@ -40,50 +43,70 @@ fn generate_primers(
}

#[tauri::command]
fn encode_sequence(encoder_type: &str, file_path: &str) -> Result<Vec<Base>, String> {
fn encode_sequence(encoder_type: &str, file_path: &str) -> Result<Vec<Vec<Base>>, String> {
let mut metadata = MetaData {
file_path: file_path,
encoder_type: encoder_type,
num_bit_sequences: 0,
bit_sequence_length: 0,
compression_type: "lz4",
};

let path = PathBuf::from(file_path);

let compressor = VoidCompressor {};
let compressed = compressor
.compress(path.clone())
.map_err(|err| err.to_string())?;

let bytes = fs::read(compressed).map_err(|err| err.to_string())?;
let bits = BitVec::<_, Msb0>::from_slice(&bytes);
let bit_blocks = 0;

let blocker = BitBlocker {};
let bit_blocks = blocker.block(metadata, bits, 20, 19);
let encoder: Box<dyn Encoder> = match encoder_type {
"quaternary" => Box::new(QuaternaryEncoder {}),
"rotation" => Box::new(RotationEncoder {}),
"church" => Box::new(ChurchEncoder {}),
_ => return Err("Selected encoder does not exist.".to_string()),
};

let metadata = MetaData {
file_path: file_path,
encoder_type: encoder_type,
num_bit_sequences: 0,
bit_sequence_length: 0,
compression_type: "lz4",
};
let encoded_dna_blocks = bit_blocks
.iter()
.map(|bit_block| encoder.encode(bit_block))
.collect();

let scaffolder = Scaffolder {};
let scaffolded_dna_blocks = scaffolder.add_scaffold(metadata, encoded_dna_blocks);

let out_dir = "metadata";
fs::create_dir_all(out_dir);
fs::create_dir_all(out_dir).unwrap();

Ok(encoder.encode(&bits).into())
Ok(scaffolded_dna_blocks)
}

#[tauri::command]
fn decode_sequence(file_path: &str) -> Result<String, String> {
let fasta_file_content = fs::read_to_string(PathBuf::from(file_path)).unwrap();
let fasta_bases = FastaParser::parse_into(&fasta_file_content);
let decoder = QuaternaryDecoder {};
let bases = fasta_bases
.into_iter()
.flatten()
.map(|base| match base {
FastaBase::Base(b) => Base::try_from(b).unwrap(),
FastaBase::NotBase(b) => Base::A, // TODO: this is just for now since the error correction will deal with the NotBase
fn decode_sequence(file_paths: Vec<&str>) -> Result<String, String> {
let decoded_sequences: Vec<BitVec<u8, Msb0>> = file_paths
.iter()
.map(|file_path| {
let fasta_file_content = fs::read_to_string(PathBuf::from(file_path)).unwrap();
let fasta_bases = FastaParser::parse_into(&fasta_file_content);
let decoder = QuaternaryDecoder {};
let bases = fasta_bases
.into_iter()
.flatten()
.map(|base| match base {
FastaBase::Base(b) => Base::try_from(b).unwrap(),
FastaBase::NotBase(b) => Base::A, // TODO: this is just for now since the error correction will deal with the NotBase
})
.collect::<Vec<Base>>();
decoder.decode(&bases)
})
.collect::<Vec<Base>>();
Ok(decoder.decode(&bases).to_string())
.collect();
let blocker = BitBlocker {};
let decoded_file = blocker.deblock(decoded_sequences);
Ok(decoded_file.to_string())
}

fn main() {
Expand Down
1 change: 1 addition & 0 deletions src-tauri/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::{compressor::Compressor, encoder::Encoder};

// TODO: don't know if lifetimes are neccesarry

#[derive(Clone, Copy)]
pub struct MetaData<'a> {
pub file_path: &'a str,
pub encoder_type: &'a str,
Expand Down
12 changes: 12 additions & 0 deletions src-tauri/src/scaffolder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use crate::{metadata::MetaData, primer::Base};

pub struct Scaffolder {}
impl Scaffolder {
pub fn add_scaffold(
&self,
metadata: MetaData,
encoded_dna_sequences: Vec<Vec<Base>>,
) -> Vec<Vec<Base>> {
todo!()
}
}

0 comments on commit 21c72c4

Please sign in to comment.