readcon_core/
chemfiles_selection.rs1#[cfg(not(feature = "chemfiles"))]
7use crate::chemfiles_import::ChemfilesImportError;
8#[cfg(not(feature = "chemfiles"))]
9use crate::types::ConFrame;
10
11#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct SelectionMatch {
14 pub size: usize,
16 pub atoms: [usize; 4],
18}
19
20impl SelectionMatch {
21 pub fn indices(&self) -> &[usize] {
23 &self.atoms[..self.size.min(4)]
24 }
25}
26
27#[derive(Debug, Clone)]
29pub struct SelectionResult {
30 pub selection: String,
32 pub context_size: usize,
34 pub matches: Vec<SelectionMatch>,
36}
37
38impl SelectionResult {
39 pub fn primary_indices(&self) -> Vec<usize> {
41 self.matches
42 .iter()
43 .filter_map(|m| m.indices().first().copied())
44 .collect()
45 }
46}
47
48#[derive(Debug, Clone)]
50pub struct FrameSelectionSlice {
51 pub frame_index: usize,
53 pub result: SelectionResult,
55 pub positions: Vec<[f64; 3]>,
59 pub atom_indices: Vec<usize>,
61}
62
63#[derive(Debug, Clone)]
65pub struct MultiFrameSelectionResult {
66 pub selection: String,
68 pub frames: Vec<FrameSelectionSlice>,
70}
71
72impl MultiFrameSelectionResult {
73 pub fn positions_per_frame(&self) -> impl Iterator<Item = &Vec<[f64; 3]>> {
76 self.frames.iter().map(|f| &f.positions)
77 }
78}
79
80#[cfg(feature = "chemfiles")]
81#[path = "chemfiles_selection_imp.rs"]
82mod imp;
83
84#[cfg(feature = "chemfiles")]
85pub use imp::{
86 apply_con_bonds_to_chemfiles_frame, chemfiles_frame_from_con_frame,
87 evaluate_selection_on_chemfiles_frame, evaluate_selection_on_con_frame,
88 evaluate_selection_on_frames, parse_selection_string, select_atom_indices,
89 select_atom_positions_on_frames,
90};
91
92#[cfg(not(feature = "chemfiles"))]
93pub fn evaluate_selection_on_con_frame(
97 _selection: &str,
98 _frame: &ConFrame,
99) -> Result<SelectionResult, ChemfilesImportError> {
100 Err(ChemfilesImportError::FeatureDisabled)
101}
102
103#[cfg(not(feature = "chemfiles"))]
104pub fn select_atom_indices(
108 _selection: &str,
109 _frame: &ConFrame,
110) -> Result<Vec<usize>, ChemfilesImportError> {
111 Err(ChemfilesImportError::FeatureDisabled)
112}
113
114#[cfg(not(feature = "chemfiles"))]
115pub fn parse_selection_string(_selection: &str) -> Result<usize, ChemfilesImportError> {
119 Err(ChemfilesImportError::FeatureDisabled)
120}
121
122#[cfg(not(feature = "chemfiles"))]
123pub fn evaluate_selection_on_frames(
125 _selection: &str,
126 _frames: &[ConFrame],
127) -> Result<MultiFrameSelectionResult, ChemfilesImportError> {
128 Err(ChemfilesImportError::FeatureDisabled)
129}
130
131#[cfg(not(feature = "chemfiles"))]
132pub fn select_atom_positions_on_frames(
134 _selection: &str,
135 _frames: &[ConFrame],
136) -> Result<MultiFrameSelectionResult, ChemfilesImportError> {
137 Err(ChemfilesImportError::FeatureDisabled)
138}
139
140#[cfg(all(test, not(feature = "chemfiles")))]
141mod stub_tests {
142 use super::*;
143 use crate::chemfiles_import::ChemfilesImportError;
144 use crate::types::ConFrameBuilder;
145
146 #[test]
147 fn selection_stub_is_feature_disabled() {
148 let frame = ConFrameBuilder::new([10.0; 3], [90.0; 3]).build();
149 let err = evaluate_selection_on_con_frame("name O", &frame).unwrap_err();
150 assert!(matches!(err, ChemfilesImportError::FeatureDisabled));
151 }
152
153 #[test]
154 fn multi_frame_selection_stub_is_feature_disabled() {
155 let frame = ConFrameBuilder::new([10.0; 3], [90.0; 3]).build();
156 let err = evaluate_selection_on_frames("name H", &[frame]).unwrap_err();
157 assert!(matches!(err, ChemfilesImportError::FeatureDisabled));
158 let frame2 = ConFrameBuilder::new([10.0; 3], [90.0; 3]).build();
159 let err2 = select_atom_positions_on_frames("name H", &[frame2]).unwrap_err();
160 assert!(matches!(err2, ChemfilesImportError::FeatureDisabled));
161 }
162}