Skip to main content

ferritin_core/io/
io.rs

1use crate::trajectory::ArrayTrajectory;
2use crate::AtomCollection;
3use crate::io::cif;
4use crate::io::pdb;
5use anyhow::{Context, Result};
6use std::path::Path;
7
8//
9pub fn load_structure<P: AsRef<Path>>(file_path: P) -> Result<AtomCollection> {
10    let path = file_path.as_ref();
11    let extension = path
12        .extension()
13        .and_then(|ext| ext.to_str())
14        .ok_or_else(|| anyhow::anyhow!("File has no extension"))?
15        .to_lowercase();
16
17    let mut ac = match extension.as_str() {
18        "pdb" => pdb::PDBFile::read(path)
19            .context("Failed to read PDB file")?
20            .parse_to_atom_collection()
21            .context("Failed to parse PDB file to atom collection")?,
22        "cif" => cif::CIFFile::read(path)?.parse_to_atom_collection()?,
23        _ => return Err(anyhow::anyhow!("Unsupported file extension: {}", extension)),
24    };
25
26    ac.connect_via_residue_names();
27    Ok(ac)
28}
29
30/// Load all models from a structure file as a trajectory.
31///
32/// For single-model files, returns a trajectory with one frame.
33/// For multi-model NMR/MD files, returns all frames sharing one `Arc<AtomicHierarchy>`.
34pub fn load_trajectory<P: AsRef<Path>>(file_path: P) -> Result<ArrayTrajectory> {
35    let path = file_path.as_ref();
36    let extension = path
37        .extension()
38        .and_then(|ext| ext.to_str())
39        .ok_or_else(|| anyhow::anyhow!("File has no extension"))?
40        .to_lowercase();
41
42    match extension.as_str() {
43        "cif" => cif::CIFFile::read(path)?
44            .parse_to_trajectory()
45            .context("Failed to parse CIF file to trajectory"),
46        "pdb" => Err(anyhow::anyhow!("PDB multi-model trajectory not yet implemented")),
47        _ => Err(anyhow::anyhow!("Unsupported file extension: {}", extension)),
48    }
49}
50
51pub fn load_structure_from_string(content: &str, filetype: &str) -> Result<AtomCollection> {
52    let filetype = filetype.to_lowercase();
53
54    let mut ac = match filetype.as_str() {
55        "pdb" => pdb::PDBFile::new_from_string(content.to_string())
56            .context("Failed to read PDB from string")?
57            .parse_to_atom_collection()
58            .context("Failed to parse PDB string to atom collection")?,
59        "cif" => cif::CIFFile::new(content.to_string())
60            .context("Failed to read CIF from string")?
61            .parse_to_atom_collection()
62            .context("Failed to parse CIF string to atom collection")?,
63        _ => return Err(anyhow::anyhow!("Unsupported file type: {}", filetype)),
64    };
65
66    ac.connect_via_residue_names();
67    Ok(ac)
68}