1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum EmbedAlgorithm {
9 FragmentRules,
13 DistanceGeometry,
15}
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum ForceFieldKind {
20 MMFF94,
22 Uff,
24 Auto,
26}
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub enum Gen3DSpeed {
31 Fast,
33 Medium,
35 Better,
37}
38
39#[derive(Debug, Clone)]
41pub struct Gen3DOptions {
42 pub embed_algorithm: EmbedAlgorithm,
44 pub forcefield: ForceFieldKind,
46 pub speed: Gen3DSpeed,
48 pub add_hydrogens: bool,
50 pub max_steps: usize,
52 pub rng_seed: Option<u64>,
54}
55
56impl Default for Gen3DOptions {
57 fn default() -> Self {
58 Self {
59 embed_algorithm: EmbedAlgorithm::FragmentRules,
60 forcefield: ForceFieldKind::Auto,
61 speed: Gen3DSpeed::Medium,
62 add_hydrogens: true,
63 max_steps: 0,
64 rng_seed: None,
65 }
66 }
67}
68
69impl Gen3DOptions {
70 pub(crate) fn effective_max_steps(&self) -> usize {
72 if self.max_steps > 0 {
73 return self.max_steps;
74 }
75 match self.speed {
76 Gen3DSpeed::Fast => 120,
77 Gen3DSpeed::Medium => 260,
78 Gen3DSpeed::Better => 520,
79 }
80 }
81
82 pub(crate) fn coarse_steps(&self) -> usize {
84 (self.effective_max_steps() * 35 / 100).max(20)
85 }
86
87 pub(crate) fn final_steps(&self) -> usize {
89 (self.effective_max_steps() * 50 / 100).max(20)
90 }
91
92 pub(crate) fn rotor_attempts(&self, n_rot_bonds: usize) -> usize {
94 if n_rot_bonds == 0 {
95 return 0;
96 }
97 match self.speed {
98 Gen3DSpeed::Fast => (n_rot_bonds * 4).max(8),
99 Gen3DSpeed::Medium => (n_rot_bonds * 8).max(20),
100 Gen3DSpeed::Better => (n_rot_bonds * 16).max(40),
101 }
102 }
103
104 pub(crate) fn rotor_max_delta(&self) -> f64 {
106 match self.speed {
107 Gen3DSpeed::Fast => std::f64::consts::PI / 5.0,
108 Gen3DSpeed::Medium => std::f64::consts::PI / 3.0,
109 Gen3DSpeed::Better => std::f64::consts::PI / 2.0,
110 }
111 }
112}