Refactor frame to have desired semantics

This commit is contained in:
Josh Mitchell
2020-11-10 20:38:24 +11:00
committed by daniel
parent d559f9e6df
commit 734048d572
6 changed files with 36 additions and 53 deletions

View File

@@ -17,17 +17,17 @@ fn main() -> Result<()> {
let mut trj = XTCTrajectory::open_read("tests/1l2y.xtc")?;
// find number of atoms in the file
let num_atoms = trj.get_num_atoms()?;
let num_atoms = trj.get_num_atoms()? as usize;
// a frame object is used to get to read or write from a trajectory
// without instantiating data arrays for every step
let mut frame = Frame::with_capacity(num_atoms);
let mut frame = Frame::with_len(num_atoms);
// read the first frame of the trajectory
trj.read(&mut frame)?;
assert_eq!(frame.step, 1);
assert_eq!(frame.num_atoms, num_atoms);
assert_eq!(frame.len(), num_atoms);
let first_atom_coords = frame.coords[0];
assert_eq!(first_atom_coords, [-0.8901, 0.4127, -0.055499997]);

View File

@@ -304,7 +304,7 @@ mod tests {
let err = Error::from((path, mode));
assert_eq!(expected, err);
let frame = Frame::with_capacity(0);
let frame = Frame::with_len(0);
let expected = Error::WrongSizeFrame {
expected: 10,
found: 0,

View File

@@ -1,11 +1,6 @@
use std::fmt;
/// A frame represents a single step in a trajectory.
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct Frame {
/// Number of atoms in the frame
pub num_atoms: u32,
/// Trajectory step
pub step: u32,
@@ -13,16 +8,15 @@ pub struct Frame {
pub time: f32,
/// 3x3 box vector
pub box_vector: [[f32; 3usize]; 3usize],
pub box_vector: [[f32; 3]; 3],
/// 3D coordinates for N atoms where N is num_atoms
pub coords: Vec<[f32; 3usize]>,
pub coords: Vec<[f32; 3]>,
}
impl Default for Frame {
fn default() -> Frame {
Frame {
num_atoms: 0,
step: 0,
time: 0.0,
box_vector: [[0.0; 3]; 3],
@@ -31,17 +25,6 @@ impl Default for Frame {
}
}
impl fmt::Debug for Frame {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Frame {{ atoms: {}, step: {}, time: {}, \
box: {:?}, coords: {:?} }}",
self.num_atoms, self.step, self.time, self.box_vector, self.coords
)
}
}
impl Frame {
/// Creates an empty frame with a capacity of 0
pub fn new() -> Frame {
@@ -51,10 +34,9 @@ impl Frame {
}
/// Creates a frame with the given capacity
pub fn with_capacity(num_atoms: u32) -> Frame {
pub fn with_len(num_atoms: usize) -> Frame {
Frame {
num_atoms,
coords: vec![[0.0, 0.0, 0.0]; num_atoms as usize],
coords: vec![[0.0, 0.0, 0.0]; num_atoms],
..Default::default()
}
}
@@ -69,12 +51,16 @@ impl Frame {
.filter(|&(i, _)| indeces.contains(&i))
.map(|(_, elem)| elem)
.collect();
self.num_atoms = self.coords.len() as u32;
}
/// Length of the frame (number of atoms)
pub fn len(self: &Frame) -> usize {
self.num_atoms as usize
self.coords.len()
}
/// Resize the frame to have exactly `num_atoms` atoms, filling coords with zeros if necessary
pub fn resize(&mut self, num_atoms: usize) {
self.coords.resize(num_atoms, [0.0; 3])
}
}
@@ -84,28 +70,28 @@ mod tests {
#[test]
fn test_frame_with_capacity() {
let frame = Frame::with_capacity(10);
let frame = Frame::with_len(10);
println!("{:?}", frame.coords);
assert_eq!(frame.coords.len(), 10);
}
#[test]
fn test_frame_filter_atoms() {
let mut frame = Frame::with_capacity(3);
let mut frame = Frame::with_len(3);
frame.coords[0] = [1.0, 2.0, 3.0];
frame.coords[1] = [4.0, 5.0, 6.0];
frame.coords[2] = [7.0, 8.0, 9.0];
let filter: Vec<usize> = vec![1, 2];
let mut frame_new = frame.clone();
frame_new.filter_coords(&filter);
assert!(frame_new.num_atoms as usize == filter.len());
assert!(frame_new.len() == filter.len());
assert!(frame_new.coords[0] == frame.coords[1]);
assert!(frame_new.coords[1] == frame.coords[2]);
}
#[test]
fn test_frame_len() {
let frame = Frame::with_capacity(10);
let frame = Frame::with_len(10);
assert_eq!(frame.len(), 10);
}
}

View File

@@ -2,9 +2,9 @@ use crate::*;
use std::rc::Rc;
fn into_iter_inner<T: Trajectory>(mut traj: T) -> TrajectoryIterator<T> {
let num_atoms = traj.get_num_atoms();
let num_atoms = traj.get_num_atoms().map(|n| n as usize);
let frame = match &num_atoms {
Ok(num_atoms) => Frame::with_capacity(*num_atoms),
Ok(num_atoms) => Frame::with_len(*num_atoms),
Err(_) => Frame::new(),
};
TrajectoryIterator {
@@ -58,7 +58,7 @@ impl<T: Trajectory> TrajectoryIterator<T> {
Some(item) => item,
None => {
// caller kept frame. Create new one
self.item = Rc::new(Frame::with_capacity(num_atoms));
self.item = Rc::new(Frame::with_len(num_atoms as usize));
Rc::get_mut(&mut self.item).expect("Could not get mutable access to new Rc")
}
};

View File

@@ -14,17 +14,17 @@
//! let mut trj = XTCTrajectory::open_read("tests/1l2y.xtc")?;
//!
//! // find number of atoms in the file
//! let num_atoms = trj.get_num_atoms()?;
//! let num_atoms = trj.get_num_atoms()? as usize;
//!
//! // a frame object is used to get to read or write from a trajectory
//! // without instantiating data arrays for every step
//! let mut frame = Frame::with_capacity(num_atoms);
//! let mut frame = Frame::with_len(num_atoms);
//!
//! // read the first frame of the trajectory
//! trj.read(&mut frame)?;
//!
//! assert_eq!(frame.step, 1);
//! assert_eq!(frame.num_atoms, num_atoms);
//! assert_eq!(frame.len(), num_atoms);
//!
//! let first_atom_coords = frame.coords[0];
//! assert_eq!(first_atom_coords, [-0.8901, 0.4127, -0.055499997]);
@@ -278,7 +278,7 @@ impl Trajectory for XTCTrajectory {
unsafe {
let code = xdrfile_xtc::write_xtc(
self.handle.xdrfile,
frame.num_atoms as i32,
frame.len() as i32,
frame.step as i32,
frame.time,
frame.box_vector.as_ptr() as *mut [[f32; 3]; 3],
@@ -413,7 +413,7 @@ impl Trajectory for TRRTrajectory {
unsafe {
let code = xdrfile_trr::write_trr(
self.handle.xdrfile,
frame.num_atoms as i32,
frame.len() as i32,
frame.step as i32,
frame.time,
0.0,
@@ -492,7 +492,6 @@ mod tests {
let natoms: u32 = 2;
let frame = Frame {
num_atoms: natoms,
step: 5,
time: 2.0,
box_vector: [[1.0, 2.0, 3.0], [2.0, 1.0, 3.0], [3.0, 2.0, 1.0]],
@@ -506,7 +505,7 @@ mod tests {
}
f.flush()?;
let mut new_frame = Frame::with_capacity(natoms);
let mut new_frame = Frame::with_len(natoms as usize);
let mut f = XTCTrajectory::open_read(tmp_path)?;
let num_atoms = f.get_num_atoms()?;
assert_eq!(num_atoms, natoms);
@@ -517,7 +516,7 @@ mod tests {
Ok(()) => {}
}
assert_eq!(new_frame.num_atoms, frame.num_atoms);
assert_eq!(new_frame.len(), frame.len());
assert_eq!(new_frame.step, frame.step);
assert_approx_eq!(new_frame.time, frame.time);
assert_eq!(new_frame.box_vector, frame.box_vector);
@@ -532,7 +531,6 @@ mod tests {
let natoms: u32 = 2;
let frame = Frame {
num_atoms: natoms,
step: 5,
time: 2.0,
box_vector: [[1.0, 2.0, 3.0], [2.0, 1.0, 3.0], [3.0, 2.0, 1.0]],
@@ -546,7 +544,7 @@ mod tests {
}
f.flush()?;
let mut new_frame = Frame::with_capacity(natoms);
let mut new_frame = Frame::with_len(natoms as usize);
let mut f = TRRTrajectory::open_read(tmp_path)?;
// let num_atoms = f.get_num_atoms()?;
// assert_eq!(num_atoms, natoms);
@@ -557,7 +555,7 @@ mod tests {
Ok(()) => {}
}
assert_eq!(new_frame.num_atoms, frame.num_atoms);
assert_eq!(new_frame.len(), frame.len());
assert_eq!(new_frame.step, frame.step);
assert_eq!(new_frame.time, frame.time);
assert_eq!(new_frame.box_vector, frame.box_vector);
@@ -569,7 +567,7 @@ mod tests {
pub fn test_manual_loop() -> Result<(), Box<dyn std::error::Error>> {
let mut xtc_frames = Vec::new();
let mut xtc_traj = XTCTrajectory::open_read("tests/1l2y.xtc")?;
let mut frame = Frame::with_capacity(xtc_traj.get_num_atoms()?);
let mut frame = Frame::with_len(xtc_traj.get_num_atoms()? as usize);
while let Ok(()) = xtc_traj.read(&mut frame) {
xtc_frames.push(frame.clone());
@@ -583,7 +581,7 @@ mod tests {
}
for (xtc, trr) in xtc_frames.into_iter().zip(trr_frames) {
assert_eq!(xtc.num_atoms, trr.num_atoms);
assert_eq!(xtc.len(), trr.len());
assert_eq!(xtc.step, trr.step);
assert_eq!(xtc.time, trr.time);
assert_eq!(xtc.box_vector, trr.box_vector);
@@ -732,7 +730,7 @@ mod tests {
#[test]
fn test_err_could_not_read() -> Result<()> {
let file_name = "README.md"; // not a trajectory
let mut frame = Frame::with_capacity(1);
let mut frame = Frame::with_len(1);
let mut trr = TRRTrajectory::open_read(file_name)?;
if let Err(e) = trr.read(&mut frame) {
assert_eq!(Some(ErrorCode::ExdrMagic), e.code());
@@ -749,7 +747,6 @@ mod tests {
let natoms: u32 = 2;
let frame = Frame {
num_atoms: natoms,
step: 5,
time: 2.0,
box_vector: [[1.0, 2.0, 3.0], [2.0, 1.0, 3.0], [3.0, 2.0, 1.0]],
@@ -759,7 +756,7 @@ mod tests {
f.write(&frame)?;
f.flush()?;
let mut new_frame = Frame::with_capacity(natoms);
let mut new_frame = Frame::with_len(natoms as usize);
let mut f = XTCTrajectory::open_read(tmp_path)?;
f.read(&mut new_frame)?;

View File

@@ -8,7 +8,7 @@ mod integration {
fn test_use_library() -> Result<()> {
let mut trj = XTCTrajectory::open_read("tests/1l2y.xtc")?;
let num_atoms = trj.get_num_atoms()?;
let mut frame = Frame::with_capacity(num_atoms);
let mut frame = Frame::with_len(num_atoms as usize);
trj.read(&mut frame)?;
trj.read(&mut frame)?;