1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//! Enhanced stereochemistry types for SDF V3000 format.
/// Stereo group types as defined in V3000 format.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum StereoGroupType {
/// Absolute stereochemistry - the depicted configuration is the actual configuration.
Absolute,
/// OR group - one of the depicted configurations exists, but which one is unknown.
Or,
/// AND group - a mixture of both configurations exists.
And,
}
impl StereoGroupType {
/// Creates a StereoGroupType from a V3000 string.
pub fn parse(s: &str) -> Option<Self> {
match s.to_uppercase().as_str() {
"ABS" | "ABSOLUTE" => Some(StereoGroupType::Absolute),
"OR" => Some(StereoGroupType::Or),
"AND" | "&" => Some(StereoGroupType::And),
_ => None,
}
}
/// Converts to V3000 format string.
pub fn to_v3000_str(&self) -> &'static str {
match self {
StereoGroupType::Absolute => "ABS",
StereoGroupType::Or => "OR",
StereoGroupType::And => "AND",
}
}
}
/// Represents an enhanced stereochemistry group in V3000 format.
#[derive(Debug, Clone, PartialEq)]
pub struct StereoGroup {
/// The type of stereo group.
pub group_type: StereoGroupType,
/// Group number (for distinguishing multiple OR or AND groups).
pub group_number: u32,
/// Indices of atoms in this stereo group (0-based).
pub atoms: Vec<usize>,
}
impl StereoGroup {
/// Creates a new stereo group.
pub fn new(group_type: StereoGroupType, group_number: u32, atoms: Vec<usize>) -> Self {
Self {
group_type,
group_number,
atoms,
}
}
/// Creates an absolute stereo group.
pub fn absolute(atoms: Vec<usize>) -> Self {
Self::new(StereoGroupType::Absolute, 0, atoms)
}
/// Creates an OR stereo group.
pub fn or_group(group_number: u32, atoms: Vec<usize>) -> Self {
Self::new(StereoGroupType::Or, group_number, atoms)
}
/// Creates an AND stereo group.
pub fn and_group(group_number: u32, atoms: Vec<usize>) -> Self {
Self::new(StereoGroupType::And, group_number, atoms)
}
/// Returns true if this group contains the given atom index.
pub fn contains_atom(&self, atom_index: usize) -> bool {
self.atoms.contains(&atom_index)
}
/// Returns the number of atoms in this group.
pub fn atom_count(&self) -> usize {
self.atoms.len()
}
}
impl Default for StereoGroup {
fn default() -> Self {
Self {
group_type: StereoGroupType::Absolute,
group_number: 0,
atoms: Vec::new(),
}
}
}