Skip to content

Commit

Permalink
Merge pull request #1 from cvhammond/remove-file
Browse files Browse the repository at this point in the history
Remove file
  • Loading branch information
cvhammond authored Aug 9, 2023
2 parents c570c58 + 415743f commit 23b52ea
Show file tree
Hide file tree
Showing 7 changed files with 416 additions and 321 deletions.
145 changes: 76 additions & 69 deletions src/c3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,40 +20,42 @@ impl PartialEq for C3d {

impl C3d {
pub fn load(file_name: &str) -> Result<C3d, C3dParseError> {
let c3d = C3d::new()?;
let (c3d, mut file) = c3d.open_file(file_name)?;
Ok(c3d
.parse_basic_info(&mut file)?
.parse_header()?
.parse_parameters()?
.parse_data(file)?)
}

pub fn from_bytes(bytes: &[u8]) -> Result<C3d, C3dParseError> {
let c3d = C3d::new()?
.open_file(file_name)?
.parse_basic_info()?
.parse_basic_info_from_bytes(bytes)?
.parse_header()?
.parse_parameters()?
.parse_data()?;
.parse_data_from_bytes(bytes)?;

Ok(c3d)
}

pub fn load_header(file_name: &str) -> Result<C3d, C3dParseError> {
let c3d = C3d::new()?
.open_file(file_name)?
.parse_basic_info()?
.parse_header()?;

Ok(c3d)
let c3d = C3d::new()?;
let (c3d, mut file) = c3d.open_file(file_name)?;
Ok(c3d.parse_basic_info(&mut file)?.parse_header()?)
}

pub fn load_parameters(file_name: &str) -> Result<C3d, C3dParseError> {
let c3d = C3d::new()?
.open_file(file_name)?
.parse_basic_info()?
let c3d = C3d::new()?;
let (c3d, mut file) = c3d.open_file(file_name)?;
Ok(c3d.parse_basic_info(&mut file)?
.parse_header()?
.parse_parameters()?;

Ok(c3d)
.parse_parameters()?)
}

pub fn new() -> Result<C3d, C3dParseError> {
let path = PathBuf::from("");
Ok(C3d {
file_path: path,
file: None,
file_path: None,
bytes: Bytes::new(),
parameters: Parameters::new(),
processor: Processor::new(),
Expand All @@ -62,33 +64,22 @@ impl C3d {
})
}

fn open_file(mut self, file_name: &str) -> Result<C3d, C3dParseError> {
self.file_path = PathBuf::from(file_name);
self.file = Some(File::open(&self.file_path).map_err(|e| C3dParseError::ReadError(e))?);
Ok(self)
fn open_file(mut self, file_name: &str) -> Result<(C3d, File), C3dParseError> {
self.file_path = Some(PathBuf::from(file_name));
let file = File::open(self.file_path.clone().unwrap()).map_err(|e| C3dParseError::ReadError(e))?;
Ok((self, file))
}

fn read_header_bytes(mut self) -> Result<C3d, C3dParseError> {
fn read_header_bytes(mut self, file: &mut File) -> Result<C3d, C3dParseError> {
self.bytes.header = [0u8; 512];

if self.file.is_none() {
return Err(C3dParseError::FileNotOpen);
}

let file = self.file.as_mut().unwrap();
file.read_exact(&mut self.bytes.header)
.map_err(|e| C3dParseError::ReadError(e))?;
Ok(self)
}

fn read_parameter_bytes(mut self) -> Result<C3d, C3dParseError> {
fn read_parameter_bytes(mut self, file: &mut File) -> Result<C3d, C3dParseError> {
self.bytes.parameter_start_block_index = self.bytes.header[0] as usize;

if self.file.is_none() {
return Err(C3dParseError::FileNotOpen);
}

let file = self.file.as_mut().unwrap();
let blocks_to_skip = self.bytes.parameter_start_block_index - 2;
file.seek(SeekFrom::Current((512 * blocks_to_skip) as i64))
.map_err(|e| C3dParseError::ReadError(e))?;
Expand Down Expand Up @@ -123,8 +114,38 @@ impl C3d {
Ok(self)
}

fn parse_basic_info(self) -> Result<C3d, C3dParseError> {
self.read_header_bytes()?.read_parameter_bytes()
fn parse_basic_info(self, file: &mut File) -> Result<C3d, C3dParseError> {
self.read_header_bytes(file)?.read_parameter_bytes(file)
}

fn parse_basic_info_from_bytes(mut self, bytes: &[u8]) -> Result<C3d, C3dParseError> {
if bytes.len() < 512 {
return Err(C3dParseError::InsufficientBlocks("header".to_string()));
}
self.bytes.header = bytes[0..512].try_into().unwrap();

self.bytes.parameter_start_block_index = self.bytes.header[0] as usize;

if bytes.len() < 512 * (self.bytes.parameter_start_block_index + 1) {
return Err(C3dParseError::InsufficientBlocks("parameter".to_string()));
}
let parameter_start_block = &bytes[512..1024];

self.processor =
Processor::from_parameter_start_block(parameter_start_block.try_into().unwrap())?;
self.bytes.data_start_block_index =
self.processor
.u16([self.bytes.header[16], self.bytes.header[17]]) as usize;

if bytes.len() < 512 * (self.bytes.data_start_block_index + 1) {
return Err(C3dParseError::InsufficientBlocks("data".to_string()));
}

self.bytes.parameter = bytes[512..(512 * (self.bytes.data_start_block_index + 1))]
.try_into()
.unwrap();

Ok(self)
}

fn parse_header(mut self) -> Result<C3d, C3dParseError> {
Expand Down Expand Up @@ -162,21 +183,25 @@ impl C3d {
Ok(self)
}

fn read_data_bytes(mut self) -> Result<C3d, C3dParseError> {
fn read_data_bytes(mut self, mut file: File) -> Result<C3d, C3dParseError> {
self.bytes.data = Vec::new();

if self.file.is_none() {
return Err(C3dParseError::FileNotOpen);
}

let file = self.file.as_mut().unwrap();
file.read_to_end(&mut self.bytes.data)
.map_err(|e| C3dParseError::ReadError(e))?;
Ok(self)
}

fn parse_data(self) -> Result<C3d, C3dParseError> {
self.read_data_bytes()?.parse_data_bytes()
fn parse_data(self, file: File) -> Result<C3d, C3dParseError> {
self.read_data_bytes(file)?.parse_data_bytes()
}

fn parse_data_from_bytes(mut self, bytes: &[u8]) -> Result<C3d, C3dParseError> {
let data_start_byte = 512 * (self.bytes.data_start_block_index + 1);
if bytes.len() < data_start_byte {
return Err(C3dParseError::InsufficientBlocks("data".to_string()));
}
self.bytes.data = bytes[data_start_byte..].to_vec();
self.parse_data_bytes()
}

fn parse_data_bytes(mut self) -> Result<C3d, C3dParseError> {
Expand All @@ -199,27 +224,9 @@ impl C3d {
}
_ => 0,
};
let start_field_parameter = self.parameters.get_int_vec("TRIAL", "ACTUAL_START_FIELD");
let end_field_parameter = self.parameters.get_int_vec("TRIAL", "ACTUAL_END_FIELD");

if start_field_parameter.is_some() && end_field_parameter.is_some() {
let start_field_parameter = start_field_parameter.unwrap();
let end_field_parameter = end_field_parameter.unwrap();

if start_field_parameter.len() == 2 && end_field_parameter.len() == 2 {
let start_one = start_field_parameter.first().unwrap();
let start_two = start_field_parameter.last().unwrap();
let end_one = end_field_parameter.first().unwrap();
let end_two = end_field_parameter.last().unwrap();

self.data.trial_start_frame =
*start_one as u16 as usize + (*start_two as u16 * 65535) as usize;
self.data.trial_end_frame =
*end_one as u16 as usize + (*end_two as u16 * 65535) as usize;
//self.data.num_frames = end_field - start_field + 1;
}
}
self.data.parse(&self.bytes.data, &self.parameters, &self.processor)?;

self.data
.parse(&self.bytes.data, &self.parameters, &self.processor)?;
Ok(self)
}
}
Expand All @@ -240,11 +247,11 @@ pub fn test_load_file(file_name: &str) -> ProcessStep {
Ok(c3d) => c3d,
Err(_) => return ProcessStep::MakeEmpty,
};
let c3d = match c3d.open_file(file_name) {
let (c3d, mut file) = match c3d.open_file(file_name) {
Ok(c3d) => c3d,
Err(_) => return ProcessStep::LoadFile,
};
let c3d = match c3d.parse_basic_info() {
let c3d = match c3d.parse_basic_info(&mut file) {
Ok(c3d) => c3d,
Err(_) => return ProcessStep::ParseBasicInfo,
};
Expand All @@ -256,7 +263,7 @@ pub fn test_load_file(file_name: &str) -> ProcessStep {
Ok(c3d) => c3d,
Err(_) => return ProcessStep::ParseParameters,
};
match c3d.parse_data() {
match c3d.parse_data(file) {
Ok(c3d) => c3d,
Err(_) => return ProcessStep::ParseData,
};
Expand Down
47 changes: 26 additions & 21 deletions src/data.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::ops::{MulAssign, SubAssign, DivAssign};
use std::ops::{DivAssign, MulAssign, SubAssign};

use crate::processor::Processor;
use crate::{
Expand All @@ -13,13 +13,10 @@ use ndarray::{Array, Array2, Array3};
#[derive(Debug, Clone)]
pub struct Data {
pub points: Array3<f32>,
pub point_labels: Vec<String>,
pub cameras: Array3<bool>,
pub residuals: Array2<f32>,
pub num_frames: usize,
pub point_frames: usize,
pub trial_start_frame: usize,
pub trial_end_frame: usize,
pub frame_rate: f32,
pub scale_factor: f32,
pub max_interpolation_gap: u16,
Expand All @@ -38,7 +35,6 @@ pub struct Data {
impl PartialEq for Data {
fn eq(&self, other: &Self) -> bool {
self.points == other.points
&& self.point_labels == other.point_labels
&& self.cameras == other.cameras
&& self.residuals == other.residuals
&& self.num_frames == other.num_frames
Expand Down Expand Up @@ -66,13 +62,10 @@ impl Data {
pub fn new() -> Data {
Data {
points: Array3::zeros((0, 0, 0)),
point_labels: Vec::new(),
cameras: Array3::from_elem((0, 0, 0), false),
residuals: Array2::zeros((0, 0)),
num_frames: 0,
point_frames: 0,
trial_start_frame: 0,
trial_end_frame: 0,
frame_rate: 0.0,
scale_factor: 0.0,
max_interpolation_gap: 0,
Expand All @@ -89,7 +82,11 @@ impl Data {
}
}

fn calc_num_frames(&mut self, data_bytes: &[u8]) -> Result<&mut Self, C3dParseError> {
fn calc_num_frames(
&mut self,
data_bytes: &[u8],
parameters: &Parameters,
) -> Result<&mut Self, C3dParseError> {
self.num_frames = (self.last_frame as usize - self.first_frame as usize) + 1;
if self.num_frames != self.point_frames {
self.num_frames = self.point_frames;
Expand All @@ -98,8 +95,18 @@ impl Data {
// self.num_frames,
// ));
}
if self.trial_end_frame - self.trial_start_frame + 1 != self.num_frames {
self.num_frames = self.trial_end_frame - self.trial_start_frame + 1;
if parameters.trial.actual_start_field.is_some()
&& parameters.trial.actual_end_field.is_some()
{
if (parameters.trial.actual_end_field.unwrap()
- parameters.trial.actual_start_field.unwrap()
+ 1) as usize
!= self.num_frames
{
self.num_frames = (parameters.trial.actual_end_field.unwrap()
- parameters.trial.actual_start_field.unwrap()
+ 1) as usize;
}
}

if DataFormat::Unknown == self.format {
Expand Down Expand Up @@ -227,8 +234,8 @@ impl Data {
0
};
let mut analog_data: Array2<f32> = Array::zeros((
self.num_frames * self.analog_channels as usize,
analog_samples_per_channel_per_frame,
self.num_frames * analog_samples_per_channel_per_frame,
self.analog_channels as usize,
));
let mut analog_iter = analog_data.iter_mut();

Expand Down Expand Up @@ -271,25 +278,23 @@ impl Data {
}
}
}
let offset_len = match &parameters.required_parameters.analog.offset {
let offset_len = match &parameters.analog.offset {
Signed(offset) => offset.len(),
Unsigned(offset) => offset.len(),
};
if offset_len == parameters.required_parameters.analog.scale.len()
&& offset_len == analog_data.shape()[1]
{
if offset_len == parameters.analog.scale.len() && offset_len == analog_data.shape()[1] {
analog_data
.columns_mut()
.into_iter()
.enumerate()
.for_each(|(i, mut column)| {
match &parameters.required_parameters.analog.offset {
match &parameters.analog.offset {
Signed(offset) => column.sub_assign(offset[i] as f32),
Unsigned(offset) => column.sub_assign(offset[i] as f32),
}
column.mul_assign(parameters.required_parameters.analog.scale[i]);
column.mul_assign(parameters.analog.scale[i]);
});
analog_data.div_assign(parameters.required_parameters.analog.gen_scale);
analog_data.div_assign(parameters.analog.gen_scale);
}
self.analog = analog_data;
Ok(self)
Expand All @@ -301,7 +306,7 @@ impl Data {
parameters: &Parameters,
processor: &Processor,
) -> Result<(), C3dParseError> {
self.calc_num_frames(data_bytes)?
self.calc_num_frames(data_bytes, parameters)?
.parse_points(data_bytes, processor)?
.parse_analog(data_bytes, parameters, processor)?;
Ok(())
Expand Down
4 changes: 1 addition & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::fs::File;
use std::path::PathBuf;
use std::{error::Error, fmt};

Expand Down Expand Up @@ -58,8 +57,7 @@ impl fmt::Display for C3dParseError {

#[derive(Debug)]
pub struct C3d {
pub file_path: PathBuf,
pub file: Option<File>,
pub file_path: Option<PathBuf>,
pub bytes: Bytes,
pub parameters: Parameters,
pub processor: Processor,
Expand Down
10 changes: 6 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use c3dio::parameters::AnalogOffset::{Signed, Unsigned};
use std::ops::{MulAssign, SubAssign};

use c3dio::C3d;
fn main() {
let dec_int = C3d::load("tests/c3d.org-sample-files/Sample19/sample19.c3d").unwrap();
let sample19 = C3d::load("tests/c3d.org-sample-files/Sample07/16bitanalog.c3d").unwrap();

dbg!(sample19.data.num_frames);
dbg!(sample19.data.analog_channels);
dbg!(sample19.data.analog_samples_per_frame);
dbg!(sample19.data.analog_samples_per_frame as usize * sample19.data.num_frames);
}
Loading

0 comments on commit 23b52ea

Please sign in to comment.