react-cheminfo 0.23.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) hide show
  1. package/README.md +39 -26
  2. package/lib/chrome/ui/HeaderToggle.d.ts +52 -0
  3. package/lib/chrome/ui/HeaderToggle.d.ts.map +1 -0
  4. package/lib/chrome/ui/HeaderToggle.js +31 -0
  5. package/lib/chrome/ui/HeaderToggle.js.map +1 -0
  6. package/lib/chrome/ui/index.d.ts +2 -0
  7. package/lib/chrome/ui/index.d.ts.map +1 -1
  8. package/lib/chrome/ui/index.js +1 -0
  9. package/lib/chrome/ui/index.js.map +1 -1
  10. package/lib/citation/core/gfn2Paper.d.ts +10 -0
  11. package/lib/citation/core/gfn2Paper.d.ts.map +1 -0
  12. package/lib/citation/core/gfn2Paper.js +28 -0
  13. package/lib/citation/core/gfn2Paper.js.map +1 -0
  14. package/lib/citation/core/index.d.ts +1 -0
  15. package/lib/citation/core/index.d.ts.map +1 -1
  16. package/lib/citation/core/index.js +1 -0
  17. package/lib/citation/core/index.js.map +1 -1
  18. package/lib/clipboard/ui/ClickToCopy.d.ts +8 -7
  19. package/lib/clipboard/ui/ClickToCopy.d.ts.map +1 -1
  20. package/lib/clipboard/ui/ClickToCopy.js +3 -3
  21. package/lib/clipboard/ui/ClickToCopy.js.map +1 -1
  22. package/lib/conformers.d.ts +27 -0
  23. package/lib/conformers.d.ts.map +1 -0
  24. package/lib/conformers.js +19 -0
  25. package/lib/conformers.js.map +1 -0
  26. package/lib/core.d.ts +1 -0
  27. package/lib/core.d.ts.map +1 -1
  28. package/lib/core.js +1 -0
  29. package/lib/core.js.map +1 -1
  30. package/lib/credits/core/credits.d.ts +12 -0
  31. package/lib/credits/core/credits.d.ts.map +1 -1
  32. package/lib/credits/core/credits.js +14 -0
  33. package/lib/credits/core/credits.js.map +1 -1
  34. package/lib/ecosystem/core/index.d.ts +1 -1
  35. package/lib/ecosystem/core/index.d.ts.map +1 -1
  36. package/lib/ecosystem/core/index.js.map +1 -1
  37. package/lib/ecosystem/core/sites.d.ts +11 -1
  38. package/lib/ecosystem/core/sites.d.ts.map +1 -1
  39. package/lib/ecosystem/core/sites.js +7 -2
  40. package/lib/ecosystem/core/sites.js.map +1 -1
  41. package/lib/ecosystem/ui/EcosystemLinks.d.ts.map +1 -1
  42. package/lib/ecosystem/ui/EcosystemLinks.js +3 -1
  43. package/lib/ecosystem/ui/EcosystemLinks.js.map +1 -1
  44. package/lib/ecosystem/ui/SiteTile.d.ts.map +1 -1
  45. package/lib/ecosystem/ui/SiteTile.js +3 -1
  46. package/lib/ecosystem/ui/SiteTile.js.map +1 -1
  47. package/lib/format/core/index.d.ts +1 -1
  48. package/lib/format/core/index.d.ts.map +1 -1
  49. package/lib/format/core/index.js +1 -1
  50. package/lib/format/core/index.js.map +1 -1
  51. package/lib/format/core/words.d.ts +9 -0
  52. package/lib/format/core/words.d.ts.map +1 -1
  53. package/lib/format/core/words.js +16 -0
  54. package/lib/format/core/words.js.map +1 -1
  55. package/lib/language/core/index.d.ts +3 -0
  56. package/lib/language/core/index.d.ts.map +1 -0
  57. package/lib/language/core/index.js +3 -0
  58. package/lib/language/core/index.js.map +1 -0
  59. package/lib/language/core/languageName.d.ts +8 -0
  60. package/lib/language/core/languageName.d.ts.map +1 -0
  61. package/lib/language/core/languageName.js +16 -0
  62. package/lib/language/core/languageName.js.map +1 -0
  63. package/lib/language/core/languageParam.d.ts +35 -0
  64. package/lib/language/core/languageParam.d.ts.map +1 -0
  65. package/lib/language/core/languageParam.js +67 -0
  66. package/lib/language/core/languageParam.js.map +1 -0
  67. package/lib/language/ui/SiteLanguage.d.ts +20 -0
  68. package/lib/language/ui/SiteLanguage.d.ts.map +1 -0
  69. package/lib/language/ui/SiteLanguage.js +14 -0
  70. package/lib/language/ui/SiteLanguage.js.map +1 -0
  71. package/lib/language/ui/index.d.ts +4 -0
  72. package/lib/language/ui/index.d.ts.map +1 -0
  73. package/lib/language/ui/index.js +3 -0
  74. package/lib/language/ui/index.js.map +1 -0
  75. package/lib/language/ui/siteLanguageContext.d.ts +12 -0
  76. package/lib/language/ui/siteLanguageContext.d.ts.map +1 -0
  77. package/lib/language/ui/siteLanguageContext.js +19 -0
  78. package/lib/language/ui/siteLanguageContext.js.map +1 -0
  79. package/lib/orbital/core/atomicOrbitals.d.ts +9 -1
  80. package/lib/orbital/core/atomicOrbitals.d.ts.map +1 -1
  81. package/lib/orbital/core/atomicOrbitals.js +7 -0
  82. package/lib/orbital/core/atomicOrbitals.js.map +1 -1
  83. package/lib/orbital/core/hydrogenic.d.ts +2 -1
  84. package/lib/orbital/core/hydrogenic.d.ts.map +1 -1
  85. package/lib/orbital/core/hydrogenic.js +2 -1
  86. package/lib/orbital/core/hydrogenic.js.map +1 -1
  87. package/lib/orbital/core/index.d.ts +1 -0
  88. package/lib/orbital/core/index.d.ts.map +1 -1
  89. package/lib/orbital/core/index.js +1 -0
  90. package/lib/orbital/core/index.js.map +1 -1
  91. package/lib/orbital/core/slaterEnergy.d.ts +35 -0
  92. package/lib/orbital/core/slaterEnergy.d.ts.map +1 -0
  93. package/lib/orbital/core/slaterEnergy.js +66 -0
  94. package/lib/orbital/core/slaterEnergy.js.map +1 -0
  95. package/lib/shared/ui/MenuButton.d.ts +3 -2
  96. package/lib/shared/ui/MenuButton.d.ts.map +1 -1
  97. package/lib/shared/ui/MenuButton.js +1 -1
  98. package/lib/shared/ui/MenuButton.js.map +1 -1
  99. package/lib/structure/core/conformerMinimise.d.ts +36 -0
  100. package/lib/structure/core/conformerMinimise.d.ts.map +1 -0
  101. package/lib/structure/core/conformerMinimise.js +81 -0
  102. package/lib/structure/core/conformerMinimise.js.map +1 -0
  103. package/lib/structure/core/conformerMinimum.d.ts +62 -0
  104. package/lib/structure/core/conformerMinimum.d.ts.map +1 -0
  105. package/lib/structure/core/conformerMinimum.js +90 -0
  106. package/lib/structure/core/conformerMinimum.js.map +1 -0
  107. package/lib/structure/core/conformerOptions.d.ts +62 -0
  108. package/lib/structure/core/conformerOptions.d.ts.map +1 -0
  109. package/lib/structure/core/conformerOptions.js +83 -0
  110. package/lib/structure/core/conformerOptions.js.map +1 -0
  111. package/lib/structure/core/conformerRefine.d.ts +104 -0
  112. package/lib/structure/core/conformerRefine.d.ts.map +1 -0
  113. package/lib/structure/core/conformerRefine.js +130 -0
  114. package/lib/structure/core/conformerRefine.js.map +1 -0
  115. package/lib/structure/core/conformerRefineRank.d.ts +36 -0
  116. package/lib/structure/core/conformerRefineRank.d.ts.map +1 -0
  117. package/lib/structure/core/conformerRefineRank.js +69 -0
  118. package/lib/structure/core/conformerRefineRank.js.map +1 -0
  119. package/lib/structure/core/conformerSession.d.ts +50 -0
  120. package/lib/structure/core/conformerSession.d.ts.map +1 -0
  121. package/lib/structure/core/conformerSession.js +88 -0
  122. package/lib/structure/core/conformerSession.js.map +1 -0
  123. package/lib/structure/core/conformerShape.d.ts +36 -0
  124. package/lib/structure/core/conformerShape.d.ts.map +1 -0
  125. package/lib/structure/core/conformerShape.js +150 -0
  126. package/lib/structure/core/conformerShape.js.map +1 -0
  127. package/lib/structure/core/conformers.d.ts +107 -0
  128. package/lib/structure/core/conformers.d.ts.map +1 -0
  129. package/lib/structure/core/conformers.js +149 -0
  130. package/lib/structure/core/conformers.js.map +1 -0
  131. package/lib/structure/core/geometryRelaxer.d.ts +66 -0
  132. package/lib/structure/core/geometryRelaxer.d.ts.map +1 -0
  133. package/lib/structure/core/geometryRelaxer.js +2 -0
  134. package/lib/structure/core/geometryRelaxer.js.map +1 -0
  135. package/lib/structure/core/index.d.ts +4 -0
  136. package/lib/structure/core/index.d.ts.map +1 -1
  137. package/lib/structure/core/index.js +2 -0
  138. package/lib/structure/core/index.js.map +1 -1
  139. package/lib/structure/core/moleculeCoordinates.d.ts +31 -0
  140. package/lib/structure/core/moleculeCoordinates.d.ts.map +1 -0
  141. package/lib/structure/core/moleculeCoordinates.js +80 -0
  142. package/lib/structure/core/moleculeCoordinates.js.map +1 -0
  143. package/lib/structure/core/molfileExport.d.ts +42 -0
  144. package/lib/structure/core/molfileExport.d.ts.map +1 -0
  145. package/lib/structure/core/molfileExport.js +47 -0
  146. package/lib/structure/core/molfileExport.js.map +1 -0
  147. package/lib/structure/core/oclResources.d.ts +12 -0
  148. package/lib/structure/core/oclResources.d.ts.map +1 -0
  149. package/lib/structure/core/oclResources.js +35 -0
  150. package/lib/structure/core/oclResources.js.map +1 -0
  151. package/lib/translate/core/catalog.d.ts +61 -0
  152. package/lib/translate/core/catalog.d.ts.map +1 -0
  153. package/lib/translate/core/catalog.js +49 -0
  154. package/lib/translate/core/catalog.js.map +1 -0
  155. package/lib/translate/core/checkTranslation.d.ts +32 -0
  156. package/lib/translate/core/checkTranslation.d.ts.map +1 -0
  157. package/lib/translate/core/checkTranslation.js +98 -0
  158. package/lib/translate/core/checkTranslation.js.map +1 -0
  159. package/lib/translate/core/contribution.d.ts +88 -0
  160. package/lib/translate/core/contribution.d.ts.map +1 -0
  161. package/lib/translate/core/contribution.js +14 -0
  162. package/lib/translate/core/contribution.js.map +1 -0
  163. package/lib/translate/core/index.d.ts +19 -0
  164. package/lib/translate/core/index.d.ts.map +1 -0
  165. package/lib/translate/core/index.js +15 -0
  166. package/lib/translate/core/index.js.map +1 -0
  167. package/lib/translate/core/marker.d.ts +45 -0
  168. package/lib/translate/core/marker.d.ts.map +1 -0
  169. package/lib/translate/core/marker.js +79 -0
  170. package/lib/translate/core/marker.js.map +1 -0
  171. package/lib/translate/core/mergeMessages.d.ts +35 -0
  172. package/lib/translate/core/mergeMessages.d.ts.map +1 -0
  173. package/lib/translate/core/mergeMessages.js +69 -0
  174. package/lib/translate/core/mergeMessages.js.map +1 -0
  175. package/lib/translate/core/session.d.ts +102 -0
  176. package/lib/translate/core/session.d.ts.map +1 -0
  177. package/lib/translate/core/session.js +162 -0
  178. package/lib/translate/core/session.js.map +1 -0
  179. package/lib/translate/core/start.d.ts +70 -0
  180. package/lib/translate/core/start.d.ts.map +1 -0
  181. package/lib/translate/core/start.js +73 -0
  182. package/lib/translate/core/start.js.map +1 -0
  183. package/lib/translate/core/suggestions.d.ts +77 -0
  184. package/lib/translate/core/suggestions.d.ts.map +1 -0
  185. package/lib/translate/core/suggestions.js +143 -0
  186. package/lib/translate/core/suggestions.js.map +1 -0
  187. package/lib/translate/core/tables.d.ts +100 -0
  188. package/lib/translate/core/tables.d.ts.map +1 -0
  189. package/lib/translate/core/tables.js +51 -0
  190. package/lib/translate/core/tables.js.map +1 -0
  191. package/lib/translate.d.ts +2 -0
  192. package/lib/translate.d.ts.map +1 -0
  193. package/lib/translate.js +6 -0
  194. package/lib/translate.js.map +1 -0
  195. package/lib/ui.d.ts +1 -0
  196. package/lib/ui.d.ts.map +1 -1
  197. package/lib/ui.js +1 -0
  198. package/lib/ui.js.map +1 -1
  199. package/lib/xtb/core/xtbRelaxer.d.ts +61 -0
  200. package/lib/xtb/core/xtbRelaxer.d.ts.map +1 -0
  201. package/lib/xtb/core/xtbRelaxer.js +108 -0
  202. package/lib/xtb/core/xtbRelaxer.js.map +1 -0
  203. package/lib/xtb.d.ts +11 -0
  204. package/lib/xtb.d.ts.map +1 -0
  205. package/lib/xtb.js +10 -0
  206. package/lib/xtb.js.map +1 -0
  207. package/package.json +18 -11
  208. package/src/chrome/ui/HeaderToggle.tsx +100 -0
  209. package/src/chrome/ui/index.ts +2 -0
  210. package/src/citation/core/gfn2Paper.ts +32 -0
  211. package/src/citation/core/index.ts +1 -0
  212. package/src/clipboard/ui/ClickToCopy.tsx +8 -7
  213. package/src/conformers.ts +87 -0
  214. package/src/core.ts +1 -0
  215. package/src/credits/core/credits.ts +16 -0
  216. package/src/ecosystem/core/index.ts +1 -0
  217. package/src/ecosystem/core/sites.ts +20 -2
  218. package/src/ecosystem/ui/EcosystemLinks.tsx +3 -1
  219. package/src/ecosystem/ui/SiteTile.tsx +3 -1
  220. package/src/format/core/index.ts +1 -1
  221. package/src/format/core/words.ts +19 -0
  222. package/src/language/core/index.ts +7 -0
  223. package/src/language/core/languageName.ts +16 -0
  224. package/src/language/core/languageParam.ts +70 -0
  225. package/src/language/ui/SiteLanguage.tsx +26 -0
  226. package/src/language/ui/index.ts +3 -0
  227. package/src/language/ui/siteLanguageContext.ts +20 -0
  228. package/src/orbital/core/atomicOrbitals.ts +17 -1
  229. package/src/orbital/core/hydrogenic.ts +2 -1
  230. package/src/orbital/core/index.ts +1 -0
  231. package/src/orbital/core/slaterEnergy.ts +83 -0
  232. package/src/shared/ui/MenuButton.tsx +4 -3
  233. package/src/structure/core/conformerMinimise.ts +99 -0
  234. package/src/structure/core/conformerMinimum.ts +125 -0
  235. package/src/structure/core/conformerOptions.ts +125 -0
  236. package/src/structure/core/conformerRefine.ts +234 -0
  237. package/src/structure/core/conformerRefineRank.ts +89 -0
  238. package/src/structure/core/conformerSession.ts +123 -0
  239. package/src/structure/core/conformerShape.ts +181 -0
  240. package/src/structure/core/conformers.ts +282 -0
  241. package/src/structure/core/geometryRelaxer.ts +71 -0
  242. package/src/structure/core/index.ts +13 -0
  243. package/src/structure/core/moleculeCoordinates.ts +93 -0
  244. package/src/structure/core/molfileExport.ts +62 -0
  245. package/src/structure/core/oclResources.ts +41 -0
  246. package/src/translate/core/catalog.ts +83 -0
  247. package/src/translate/core/checkTranslation.ts +128 -0
  248. package/src/translate/core/contribution.ts +99 -0
  249. package/src/translate/core/index.ts +72 -0
  250. package/src/translate/core/marker.ts +85 -0
  251. package/src/translate/core/mergeMessages.ts +74 -0
  252. package/src/translate/core/session.ts +250 -0
  253. package/src/translate/core/start.ts +121 -0
  254. package/src/translate/core/suggestions.ts +211 -0
  255. package/src/translate/core/tables.ts +120 -0
  256. package/src/translate.ts +5 -0
  257. package/src/ui.ts +1 -0
  258. package/src/xtb/core/xtbRelaxer.ts +160 -0
  259. package/src/xtb.ts +16 -0
  260. package/styles/chrome.css +61 -30
@@ -0,0 +1,88 @@
1
+ import { ConformerGenerator } from 'openchemlib';
2
+ /**
3
+ * A generator for a prepared structure, positioned after `produced` conformers.
4
+ *
5
+ * The generator is seeded, so the same structure and options always hand back
6
+ * the same sequence. The last session is kept, and resumed when it is exactly
7
+ * where the caller left it; otherwise a fresh generator is initialised and the
8
+ * first `produced` conformers are drawn and discarded, which yields the same
9
+ * position without their minimisation.
10
+ * @param prepared - The hydrogen-saturated copy the run embeds.
11
+ * @param options - The options that fixed the sequence: strategy, seed, torsion sets.
12
+ * @param produced - How far into the sequence the caller already is.
13
+ * @returns The session, to be handed back through {@link keepConformerSession}.
14
+ * @throws {Error} When OpenChemLib refuses to initialise the structure.
15
+ */
16
+ export function openConformerSession(prepared, options, produced) {
17
+ const key = sessionKey(prepared, options);
18
+ if (produced > 0 && last?.key === key && last.session.produced === produced) {
19
+ const session = last.session;
20
+ last = null;
21
+ return session;
22
+ }
23
+ last = null;
24
+ const generator = new ConformerGenerator(options.seed);
25
+ const initialised = generator.initializeConformers(prepared, {
26
+ strategy: strategyConstant(options.strategy),
27
+ maxTorsionSets: options.maxTorsionSets,
28
+ use60degreeSteps: options.use60DegreeSteps,
29
+ });
30
+ if (!initialised) {
31
+ throw new Error(`OpenChemLib could not set up conformer generation for ${prepared.getMolecularFormula().formula}. The structure has a problem the generator cannot resolve, such as an impossible valence or an over-constrained ring.`);
32
+ }
33
+ let skipped = 0;
34
+ while (skipped < produced &&
35
+ generator.getNextConformerAsMolecule() !== null) {
36
+ skipped++;
37
+ }
38
+ return { generator, produced: skipped, pending: null };
39
+ }
40
+ /**
41
+ * Keep a session so the next continuation of the same run resumes it.
42
+ * @param prepared - The structure the session was opened on.
43
+ * @param options - The options it was opened with.
44
+ * @param session - The session, positioned where the run stopped.
45
+ */
46
+ export function keepConformerSession(prepared, options, session) {
47
+ last = { key: sessionKey(prepared, options), session };
48
+ }
49
+ /**
50
+ * OpenChemLib's estimate of the conformers a session can reach.
51
+ * @param session - A freshly opened session.
52
+ * @returns The estimate, or `-1` when the generator declines to make one.
53
+ */
54
+ export function readPotentialCount(session) {
55
+ try {
56
+ return session.generator.getPotentialConformerCount();
57
+ }
58
+ catch {
59
+ return -1;
60
+ }
61
+ }
62
+ /**
63
+ * Map one of our strategy ids onto the `ConformerGenerator` constant it stands
64
+ * for.
65
+ * @param strategy - The id stored in the preferences.
66
+ * @returns The numeric constant OpenChemLib expects.
67
+ */
68
+ export function strategyConstant(strategy) {
69
+ return STRATEGY_CONSTANTS[strategy];
70
+ }
71
+ const STRATEGY_CONSTANTS = {
72
+ 'adaptive-random': ConformerGenerator.STRATEGY_ADAPTIVE_RANDOM,
73
+ 'likely-random': ConformerGenerator.STRATEGY_LIKELY_RANDOM,
74
+ 'pure-random': ConformerGenerator.STRATEGY_PURE_RANDOM,
75
+ 'likely-systematic': ConformerGenerator.STRATEGY_LIKELY_SYSTEMATIC,
76
+ };
77
+ let last = null;
78
+ // The atom order matters as much as the structure, so the molfile is the key.
79
+ function sessionKey(prepared, options) {
80
+ return [
81
+ options.strategy,
82
+ options.seed,
83
+ options.maxTorsionSets,
84
+ options.use60DegreeSteps,
85
+ prepared.toMolfileV3(),
86
+ ].join('\n');
87
+ }
88
+ //# sourceMappingURL=conformerSession.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conformerSession.js","sourceRoot":"","sources":["../../../src/structure/core/conformerSession.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAmBjD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,oBAAoB,CAClC,QAAkB,EAClB,OAAyB,EACzB,QAAgB;IAEhB,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC1C,IAAI,QAAQ,GAAG,CAAC,IAAI,IAAI,EAAE,GAAG,KAAK,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC5E,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7B,IAAI,GAAG,IAAI,CAAC;QACZ,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,IAAI,GAAG,IAAI,CAAC;IACZ,MAAM,SAAS,GAAG,IAAI,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,MAAM,WAAW,GAAG,SAAS,CAAC,oBAAoB,CAAC,QAAQ,EAAE;QAC3D,QAAQ,EAAE,gBAAgB,CAAC,OAAO,CAAC,QAAQ,CAAC;QAC5C,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;KAC3C,CAAC,CAAC;IACH,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,yDAAyD,QAAQ,CAAC,mBAAmB,EAAE,CAAC,OAAO,wHAAwH,CACxN,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,OACE,OAAO,GAAG,QAAQ;QAClB,SAAS,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAC/C,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AACzD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAClC,QAAkB,EAClB,OAAyB,EACzB,OAAyB;IAEzB,IAAI,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;AACzD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAyB;IAC1D,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,SAAS,CAAC,0BAA0B,EAAE,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAA2B;IAC1D,OAAO,kBAAkB,CAAC,QAAQ,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,kBAAkB,GAAsC;IAC5D,iBAAiB,EAAE,kBAAkB,CAAC,wBAAwB;IAC9D,eAAe,EAAE,kBAAkB,CAAC,sBAAsB;IAC1D,aAAa,EAAE,kBAAkB,CAAC,oBAAoB;IACtD,mBAAmB,EAAE,kBAAkB,CAAC,0BAA0B;CACnE,CAAC;AAEF,IAAI,IAAI,GAAsD,IAAI,CAAC;AAEnE,8EAA8E;AAC9E,SAAS,UAAU,CAAC,QAAkB,EAAE,OAAyB;IAC/D,OAAO;QACL,OAAO,CAAC,QAAQ;QAChB,OAAO,CAAC,IAAI;QACZ,OAAO,CAAC,cAAc;QACtB,OAAO,CAAC,gBAAgB;QACxB,QAAQ,CAAC,WAAW,EAAE;KACvB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,36 @@
1
+ import type { Molecule } from 'openchemlib';
2
+ /** Principal second moments of a conformer's atoms, in increasing order. */
3
+ export type PrincipalMoments = readonly [number, number, number];
4
+ /** What tells two minimised conformers of one energy apart. */
5
+ export interface ConformerShape {
6
+ /** Principal second moments, smallest first. */
7
+ moments: PrincipalMoments;
8
+ /** Handedness in [-1, 1]: opposite for mirror images, 0 for a shape that is its own mirror image. */
9
+ chirality: number;
10
+ }
11
+ /**
12
+ * Shape of a conformer: the principal second moments of its atoms, weighted by
13
+ * atomic number, about their weighted centre, and the handedness of the atoms
14
+ * in that principal frame.
15
+ *
16
+ * Neither changes when the conformer is turned or has its symmetry-equivalent
17
+ * atoms numbered differently, which is how the generator hands back the same
18
+ * minimum twice, as with a cyclohexane chair and its flipped copy. A mirror
19
+ * image keeps the moments and flips the sign of the chirality, so gauche butane
20
+ * and its mirror image share the one and not the other.
21
+ *
22
+ * The chirality is Σ w·u₁u₂u₃ over Σ w·|u₁u₂u₃|, u being the coordinates along
23
+ * right-handed principal axes. A mirror plane or an inversion centre makes it
24
+ * vanish. It is 0 as well for a flat conformer, and when the principal axes
25
+ * cannot be drawn.
26
+ * @param molecule - A conformer with 3D coordinates.
27
+ * @returns Its moments, smallest first, and its chirality.
28
+ */
29
+ export declare function conformerShape(molecule: Molecule): ConformerShape;
30
+ /**
31
+ * Whether every atom of a conformer sits at finite coordinates.
32
+ * @param conformer - A conformer with 3D coordinates.
33
+ * @returns `false` as soon as one coordinate is `NaN` or infinite.
34
+ */
35
+ export declare function hasFiniteCoordinates(conformer: Molecule): boolean;
36
+ //# sourceMappingURL=conformerShape.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conformerShape.d.ts","sourceRoot":"","sources":["../../../src/structure/core/conformerShape.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,4EAA4E;AAC5E,MAAM,MAAM,gBAAgB,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAEjE,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC7B,gDAAgD;IAChD,OAAO,EAAE,gBAAgB,CAAC;IAC1B,qGAAqG;IACrG,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,cAAc,CAuDjE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,QAAQ,GAAG,OAAO,CAYjE"}
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Shape of a conformer: the principal second moments of its atoms, weighted by
3
+ * atomic number, about their weighted centre, and the handedness of the atoms
4
+ * in that principal frame.
5
+ *
6
+ * Neither changes when the conformer is turned or has its symmetry-equivalent
7
+ * atoms numbered differently, which is how the generator hands back the same
8
+ * minimum twice, as with a cyclohexane chair and its flipped copy. A mirror
9
+ * image keeps the moments and flips the sign of the chirality, so gauche butane
10
+ * and its mirror image share the one and not the other.
11
+ *
12
+ * The chirality is Σ w·u₁u₂u₃ over Σ w·|u₁u₂u₃|, u being the coordinates along
13
+ * right-handed principal axes. A mirror plane or an inversion centre makes it
14
+ * vanish. It is 0 as well for a flat conformer, and when the principal axes
15
+ * cannot be drawn.
16
+ * @param molecule - A conformer with 3D coordinates.
17
+ * @returns Its moments, smallest first, and its chirality.
18
+ */
19
+ export function conformerShape(molecule) {
20
+ const atomCount = molecule.getAllAtoms();
21
+ let total = 0;
22
+ let centreX = 0;
23
+ let centreY = 0;
24
+ let centreZ = 0;
25
+ for (let atom = 0; atom < atomCount; atom++) {
26
+ const weight = molecule.getAtomicNo(atom);
27
+ total += weight;
28
+ centreX += weight * molecule.getAtomX(atom);
29
+ centreY += weight * molecule.getAtomY(atom);
30
+ centreZ += weight * molecule.getAtomZ(atom);
31
+ }
32
+ if (total === 0)
33
+ return { moments: [0, 0, 0], chirality: 0 };
34
+ centreX /= total;
35
+ centreY /= total;
36
+ centreZ /= total;
37
+ const tensor = { xx: 0, yy: 0, zz: 0, xy: 0, xz: 0, yz: 0 };
38
+ for (let atom = 0; atom < atomCount; atom++) {
39
+ const weight = molecule.getAtomicNo(atom);
40
+ const x = molecule.getAtomX(atom) - centreX;
41
+ const y = molecule.getAtomY(atom) - centreY;
42
+ const z = molecule.getAtomZ(atom) - centreZ;
43
+ tensor.xx += weight * x * x;
44
+ tensor.yy += weight * y * y;
45
+ tensor.zz += weight * z * z;
46
+ tensor.xy += weight * x * y;
47
+ tensor.xz += weight * x * z;
48
+ tensor.yz += weight * y * z;
49
+ }
50
+ const moments = symmetricEigenvalues(tensor);
51
+ const first = principalAxis(tensor, moments[0]);
52
+ const third = principalAxis(tensor, moments[2]);
53
+ if (first === null || third === null)
54
+ return { moments, chirality: 0 };
55
+ const second = cross(third, first);
56
+ let signed = 0;
57
+ let absolute = 0;
58
+ for (let atom = 0; atom < atomCount; atom++) {
59
+ const weight = molecule.getAtomicNo(atom);
60
+ const x = molecule.getAtomX(atom) - centreX;
61
+ const y = molecule.getAtomY(atom) - centreY;
62
+ const z = molecule.getAtomZ(atom) - centreZ;
63
+ const product = (x * first[0] + y * first[1] + z * first[2]) *
64
+ (x * second[0] + y * second[1] + z * second[2]) *
65
+ (x * third[0] + y * third[1] + z * third[2]);
66
+ signed += weight * product;
67
+ absolute += weight * Math.abs(product);
68
+ }
69
+ const radius = Math.sqrt((moments[0] + moments[1] + moments[2]) / total);
70
+ if (absolute <= FLAT_TOLERANCE * total * radius * radius * radius) {
71
+ return { moments, chirality: 0 };
72
+ }
73
+ return { moments, chirality: signed / absolute };
74
+ }
75
+ /**
76
+ * Whether every atom of a conformer sits at finite coordinates.
77
+ * @param conformer - A conformer with 3D coordinates.
78
+ * @returns `false` as soon as one coordinate is `NaN` or infinite.
79
+ */
80
+ export function hasFiniteCoordinates(conformer) {
81
+ const atomCount = conformer.getAllAtoms();
82
+ for (let atom = 0; atom < atomCount; atom++) {
83
+ if (!Number.isFinite(conformer.getAtomX(atom)) ||
84
+ !Number.isFinite(conformer.getAtomY(atom)) ||
85
+ !Number.isFinite(conformer.getAtomZ(atom))) {
86
+ return false;
87
+ }
88
+ }
89
+ return true;
90
+ }
91
+ /**
92
+ * Σ w·|u₁u₂u₃|, relative to the total weight times the cubed radius of
93
+ * gyration, under which a conformer is flat: its handedness is rounding noise.
94
+ */
95
+ const FLAT_TOLERANCE = 1e-4;
96
+ // Unit eigenvector of `moment`: the longest cross product of two rows of the tensor minus `moment`.
97
+ function principalAxis(tensor, moment) {
98
+ const rows = [
99
+ [tensor.xx - moment, tensor.xy, tensor.xz],
100
+ [tensor.xy, tensor.yy - moment, tensor.yz],
101
+ [tensor.xz, tensor.yz, tensor.zz - moment],
102
+ ];
103
+ let best = [0, 0, 0];
104
+ let bestLength = 0;
105
+ for (let a = 0; a < 3; a++) {
106
+ for (let b = a + 1; b < 3; b++) {
107
+ const candidate = cross(rows[a], rows[b]);
108
+ const length = Math.hypot(candidate[0], candidate[1], candidate[2]);
109
+ if (length > bestLength) {
110
+ best = candidate;
111
+ bestLength = length;
112
+ }
113
+ }
114
+ }
115
+ if (bestLength === 0)
116
+ return null;
117
+ return [best[0] / bestLength, best[1] / bestLength, best[2] / bestLength];
118
+ }
119
+ function cross(a, b) {
120
+ return [
121
+ a[1] * b[2] - a[2] * b[1],
122
+ a[2] * b[0] - a[0] * b[2],
123
+ a[0] * b[1] - a[1] * b[0],
124
+ ];
125
+ }
126
+ // Closed-form eigenvalues of a symmetric 3×3 matrix (Smith, 1961).
127
+ function symmetricEigenvalues(tensor) {
128
+ const { xx, yy, zz, xy, xz, yz } = tensor;
129
+ const mean = (xx + yy + zz) / 3;
130
+ const offDiagonal = xy * xy + xz * xz + yz * yz;
131
+ const spread = (xx - mean) * (xx - mean) +
132
+ (yy - mean) * (yy - mean) +
133
+ (zz - mean) * (zz - mean) +
134
+ 2 * offDiagonal;
135
+ if (spread === 0)
136
+ return [mean, mean, mean];
137
+ const p = Math.sqrt(spread / 6);
138
+ const a = (xx - mean) / p;
139
+ const b = (yy - mean) / p;
140
+ const c = (zz - mean) / p;
141
+ const d = xy / p;
142
+ const e = xz / p;
143
+ const f = yz / p;
144
+ const halfDeterminant = (a * (b * c - f * f) - d * (d * c - f * e) + e * (d * f - b * e)) / 2;
145
+ const angle = Math.acos(Math.min(1, Math.max(-1, halfDeterminant))) / 3;
146
+ const largest = mean + 2 * p * Math.cos(angle);
147
+ const smallest = mean + 2 * p * Math.cos(angle + (2 * Math.PI) / 3);
148
+ return [smallest, 3 * mean - largest - smallest, largest];
149
+ }
150
+ //# sourceMappingURL=conformerShape.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conformerShape.js","sourceRoot":"","sources":["../../../src/structure/core/conformerShape.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,107 @@
1
+ import type { Molecule } from 'openchemlib';
2
+ import type { ConformerOptions, MinimisationAlgorithm } from './conformerOptions.ts';
3
+ import type { ConformerRefinement, ConformerSetRefinement } from './conformerRefine.ts';
4
+ import type { MolfileExport } from './molfileExport.ts';
5
+ export { strategyConstant } from './conformerSession.ts';
6
+ /** One conformer of the input structure, ready to display and to export. */
7
+ export interface Conformer {
8
+ /** 1-based position in {@link ConformerSet.conformers}. */
9
+ id: number;
10
+ /** The 3D structure, as a molfile the viewer can parse. */
11
+ molfile: MolfileExport;
12
+ /** Total force-field energy in kcal/mol, `null` when it was not computed. */
13
+ energy: number | null;
14
+ /** Energy above the lowest conformer of the set, `null` without an energy. */
15
+ relativeEnergy: number | null;
16
+ /**
17
+ * What a better method said about this conformer, once `refineConformers` has
18
+ * relaxed it. `null` until then, which is what a plain force-field run leaves.
19
+ * @default null
20
+ */
21
+ refinement: ConformerRefinement | null;
22
+ }
23
+ /**
24
+ * Which energies a set is ordered by: the force field's own, or the ones a
25
+ * refinement pass produced.
26
+ */
27
+ export type ConformerRanking = 'force-field' | 'refined';
28
+ /** Why {@link generateConformers} stopped asking for more conformers. */
29
+ export type StopReason = 'exhausted' | 'count' | 'timeout';
30
+ /** The complete outcome of one conformer run. */
31
+ export interface ConformerSet {
32
+ /** The conformers kept, most stable first; one without an energy follows every one that has one. */
33
+ conformers: Conformer[];
34
+ /** OpenChemLib's estimate of the reachable conformers, `-1` when unavailable. */
35
+ potentialConformerCount: number;
36
+ /** Which of the three limits ended the run. */
37
+ stoppedBy: StopReason;
38
+ /** Wall-clock duration of the run, initialisation and continuations included. */
39
+ elapsedMilliseconds: number;
40
+ /** Plain sentences about conformers that were dropped or left unminimised. */
41
+ warnings: string[];
42
+ /** The force field that was asked for, echoed so a reader knows what the energies mean. */
43
+ minimisation: MinimisationAlgorithm;
44
+ /** Conformers the generator handed back, dropped ones included: where a continuation resumes. */
45
+ produced: number;
46
+ /** The options of the run, so a continuation draws from the same sequence. */
47
+ options: ConformerOptions;
48
+ /** Which of the two energies {@link ConformerSet.conformers} is ordered by. */
49
+ rankedBy: ConformerRanking;
50
+ /**
51
+ * What the refinement pass did, `null` for a set no better method has seen.
52
+ * @default null
53
+ */
54
+ refinement: ConformerSetRefinement | null;
55
+ }
56
+ /** The two options a continuation takes from the caller rather than from the run. */
57
+ export type ConformerLimits = Pick<ConformerOptions, 'maxConformers' | 'timeoutSeconds'>;
58
+ /**
59
+ * Generate conformers of a structure, optionally relaxing each one with MMFF94.
60
+ *
61
+ * The caller's molecule is never touched: the run works on a compact copy that
62
+ * receives the explicit hydrogens the generator needs.
63
+ *
64
+ * The run ends on the first of three limits — the generator runs out of new
65
+ * torsion sets, `maxConformers` conformers are in hand, or the time budget is
66
+ * spent. **A timeout is not an error**: whatever was produced is returned, with
67
+ * `stoppedBy` saying why there is not more.
68
+ *
69
+ * The budget covers the whole call, initialisation included, and is read again
70
+ * once a conformer is in hand, so no further minimisation starts past the
71
+ * deadline. The one step already running cannot be cut short, so a caller
72
+ * waiting from another thread must allow one step on top of `timeoutSeconds`.
73
+ *
74
+ * Minimisation is best-effort: a conformer MMFF94 refuses is kept with a `null`
75
+ * energy and a warning rather than lost. A minimised conformer that lands in a
76
+ * minimum already kept, such as the flipped copy of a cyclohexane chair, is
77
+ * not kept a second time; the mirror image of a chiral minimum, such as the
78
+ * second gauche butane, is a minimum of its own.
79
+ * @param molecule - Structure to embed. Not mutated.
80
+ * @param options - Strategy, limits, seed and force field.
81
+ * @param now - Clock used for the time budget, injectable for tests.
82
+ * @returns Every conformer kept, most stable first, with relative energies and any warnings.
83
+ * @throws {Error} When the structure is empty or OpenChemLib refuses to initialise it.
84
+ */
85
+ export declare function generateConformers(molecule: Molecule, options: ConformerOptions, now?: () => number): ConformerSet;
86
+ /**
87
+ * Ask the run that produced `previous` for more conformers.
88
+ *
89
+ * The continuation draws from the same seeded sequence with the same force
90
+ * field, so the result is the set a single larger run would have produced:
91
+ * the new conformers are ranked among the previous ones, the ids follow that
92
+ * order, and every relative energy is measured again from the lowest of all.
93
+ * A refined set cannot be extended: its molfiles hold the relaxed geometries
94
+ * while its `energy` fields still hold the force field's numbers, so the two
95
+ * would no longer describe one conformer and the duplicate check would compare
96
+ * shapes against energies that do not belong to them. Generate a larger set and
97
+ * refine that instead.
98
+ * @param molecule - The structure `previous` was generated from. Not mutated.
99
+ * @param previous - The set to extend. Not mutated.
100
+ * @param limits - How many more conformers to find, and the time budget of this call.
101
+ * @param now - Clock used for the time budget, injectable for tests.
102
+ * @returns The extended set, its duration the sum of both runs.
103
+ * @throws {Error} When the structure is empty, when `previous` has been refined,
104
+ * or when OpenChemLib refuses to initialise it.
105
+ */
106
+ export declare function continueConformers(molecule: Molecule, previous: ConformerSet, limits: ConformerLimits, now?: () => number): ConformerSet;
107
+ //# sourceMappingURL=conformers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conformers.d.ts","sourceRoot":"","sources":["../../../src/structure/core/conformers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAM5C,OAAO,KAAK,EACV,gBAAgB,EAChB,qBAAqB,EACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EACV,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,sBAAsB,CAAC;AAS9B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,4EAA4E;AAC5E,MAAM,WAAW,SAAS;IACxB,2DAA2D;IAC3D,EAAE,EAAE,MAAM,CAAC;IACX,2DAA2D;IAC3D,OAAO,EAAE,aAAa,CAAC;IACvB,6EAA6E;IAC7E,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,8EAA8E;IAC9E,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B;;;;OAIG;IACH,UAAU,EAAE,mBAAmB,GAAG,IAAI,CAAC;CACxC;AAED;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,aAAa,GAAG,SAAS,CAAC;AAEzD,yEAAyE;AACzE,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,OAAO,GAAG,SAAS,CAAC;AAE3D,iDAAiD;AACjD,MAAM,WAAW,YAAY;IAC3B,oGAAoG;IACpG,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,iFAAiF;IACjF,uBAAuB,EAAE,MAAM,CAAC;IAChC,+CAA+C;IAC/C,SAAS,EAAE,UAAU,CAAC;IACtB,iFAAiF;IACjF,mBAAmB,EAAE,MAAM,CAAC;IAC5B,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,2FAA2F;IAC3F,YAAY,EAAE,qBAAqB,CAAC;IACpC,iGAAiG;IACjG,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,OAAO,EAAE,gBAAgB,CAAC;IAC1B,+EAA+E;IAC/E,QAAQ,EAAE,gBAAgB,CAAC;IAC3B;;;OAGG;IACH,UAAU,EAAE,sBAAsB,GAAG,IAAI,CAAC;CAC3C;AAED,qFAAqF;AACrF,MAAM,MAAM,eAAe,GAAG,IAAI,CAChC,gBAAgB,EAChB,eAAe,GAAG,gBAAgB,CACnC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,gBAAgB,EACzB,GAAG,GAAE,MAAM,MAAqB,GAC/B,YAAY,CAEd;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,YAAY,EACtB,MAAM,EAAE,eAAe,EACvB,GAAG,GAAE,MAAM,MAAqB,GAC/B,YAAY,CAOd"}
@@ -0,0 +1,149 @@
1
+ import { ordinal } from "../../format/core/words.js";
2
+ import { minimiseConformer, rankByEnergy } from "./conformerMinimise.js";
3
+ import { isKeptMinimum, minimisedShapes } from "./conformerMinimum.js";
4
+ import { keepConformerSession, openConformerSession, readPotentialCount, } from "./conformerSession.js";
5
+ import { conformerShape, hasFiniteCoordinates } from "./conformerShape.js";
6
+ import { toMolfileExport } from "./molfileExport.js";
7
+ export { strategyConstant } from "./conformerSession.js";
8
+ /**
9
+ * Generate conformers of a structure, optionally relaxing each one with MMFF94.
10
+ *
11
+ * The caller's molecule is never touched: the run works on a compact copy that
12
+ * receives the explicit hydrogens the generator needs.
13
+ *
14
+ * The run ends on the first of three limits — the generator runs out of new
15
+ * torsion sets, `maxConformers` conformers are in hand, or the time budget is
16
+ * spent. **A timeout is not an error**: whatever was produced is returned, with
17
+ * `stoppedBy` saying why there is not more.
18
+ *
19
+ * The budget covers the whole call, initialisation included, and is read again
20
+ * once a conformer is in hand, so no further minimisation starts past the
21
+ * deadline. The one step already running cannot be cut short, so a caller
22
+ * waiting from another thread must allow one step on top of `timeoutSeconds`.
23
+ *
24
+ * Minimisation is best-effort: a conformer MMFF94 refuses is kept with a `null`
25
+ * energy and a warning rather than lost. A minimised conformer that lands in a
26
+ * minimum already kept, such as the flipped copy of a cyclohexane chair, is
27
+ * not kept a second time; the mirror image of a chiral minimum, such as the
28
+ * second gauche butane, is a minimum of its own.
29
+ * @param molecule - Structure to embed. Not mutated.
30
+ * @param options - Strategy, limits, seed and force field.
31
+ * @param now - Clock used for the time budget, injectable for tests.
32
+ * @returns Every conformer kept, most stable first, with relative energies and any warnings.
33
+ * @throws {Error} When the structure is empty or OpenChemLib refuses to initialise it.
34
+ */
35
+ export function generateConformers(molecule, options, now = defaultClock) {
36
+ return runConformers(molecule, options, null, now);
37
+ }
38
+ /**
39
+ * Ask the run that produced `previous` for more conformers.
40
+ *
41
+ * The continuation draws from the same seeded sequence with the same force
42
+ * field, so the result is the set a single larger run would have produced:
43
+ * the new conformers are ranked among the previous ones, the ids follow that
44
+ * order, and every relative energy is measured again from the lowest of all.
45
+ * A refined set cannot be extended: its molfiles hold the relaxed geometries
46
+ * while its `energy` fields still hold the force field's numbers, so the two
47
+ * would no longer describe one conformer and the duplicate check would compare
48
+ * shapes against energies that do not belong to them. Generate a larger set and
49
+ * refine that instead.
50
+ * @param molecule - The structure `previous` was generated from. Not mutated.
51
+ * @param previous - The set to extend. Not mutated.
52
+ * @param limits - How many more conformers to find, and the time budget of this call.
53
+ * @param now - Clock used for the time budget, injectable for tests.
54
+ * @returns The extended set, its duration the sum of both runs.
55
+ * @throws {Error} When the structure is empty, when `previous` has been refined,
56
+ * or when OpenChemLib refuses to initialise it.
57
+ */
58
+ export function continueConformers(molecule, previous, limits, now = defaultClock) {
59
+ const options = {
60
+ ...previous.options,
61
+ maxConformers: limits.maxConformers,
62
+ timeoutSeconds: limits.timeoutSeconds,
63
+ };
64
+ return runConformers(molecule, options, previous, now);
65
+ }
66
+ function defaultClock() {
67
+ return performance.now();
68
+ }
69
+ function runConformers(molecule, options, previous, now) {
70
+ if (previous?.refinement != null) {
71
+ throw new Error(`This set was refined with ${previous.refinement.method}, so it cannot be extended. Generate a larger set, then refine it again.`);
72
+ }
73
+ const prepared = molecule.getCompactCopy();
74
+ prepared.addImplicitHydrogens();
75
+ if (prepared.getAllAtoms() === 0) {
76
+ throw new Error('The structure is empty: there is nothing to embed in 3D.');
77
+ }
78
+ // Setting up the torsion sets is the slow half of a flexible run — seconds on
79
+ // a long chain — so it is inside both the budget and the reported duration.
80
+ const start = now();
81
+ const session = openConformerSession(prepared, options, previous?.produced ?? 0);
82
+ const potentialConformerCount = previous?.potentialConformerCount ?? readPotentialCount(session);
83
+ const conformers = previous === null ? [] : copyConformers(previous.conformers);
84
+ const into = {
85
+ conformers,
86
+ shapes: minimisedShapes(conformers),
87
+ warnings: previous === null ? [] : [...previous.warnings],
88
+ };
89
+ const budget = Math.max(options.timeoutSeconds * 1000, 0);
90
+ const stoppedBy = collect(session, options, into.conformers.length + options.maxConformers, () => now() - start >= budget, into);
91
+ keepConformerSession(prepared, options, session);
92
+ return {
93
+ conformers: rankByEnergy(into.conformers),
94
+ potentialConformerCount,
95
+ stoppedBy,
96
+ elapsedMilliseconds: (previous?.elapsedMilliseconds ?? 0) + now() - start,
97
+ warnings: into.warnings,
98
+ minimisation: options.minimisation,
99
+ produced: session.produced,
100
+ options,
101
+ rankedBy: 'force-field',
102
+ refinement: null,
103
+ };
104
+ }
105
+ function collect(session, options, target, spent, into) {
106
+ while (true) {
107
+ if (into.conformers.length >= target)
108
+ return 'count';
109
+ if (spent())
110
+ return 'timeout';
111
+ const conformer = session.pending ?? session.generator.getNextConformerAsMolecule();
112
+ session.pending = null;
113
+ if (conformer === null)
114
+ return 'exhausted';
115
+ // Minimisation runs to completion once entered, so a conformer that arrives
116
+ // past the deadline is kept aside for a continuation rather than bought now.
117
+ if (spent()) {
118
+ session.pending = conformer;
119
+ return 'timeout';
120
+ }
121
+ session.produced++;
122
+ if (!hasFiniteCoordinates(conformer)) {
123
+ into.warnings.push(`The ${ordinal(session.produced)} conformer produced was dropped: the generator placed some of its atoms at non-finite coordinates.`);
124
+ continue;
125
+ }
126
+ const energy = minimiseConformer(conformer, options, session.produced, into.warnings);
127
+ const shape = energy === null ? null : conformerShape(conformer);
128
+ if (energy !== null &&
129
+ shape !== null &&
130
+ isKeptMinimum(energy, shape, into.conformers, into.shapes)) {
131
+ continue;
132
+ }
133
+ into.conformers.push({
134
+ id: into.conformers.length + 1,
135
+ molfile: toMolfileExport(conformer),
136
+ energy,
137
+ relativeEnergy: null,
138
+ refinement: null,
139
+ });
140
+ into.shapes.push(shape);
141
+ }
142
+ }
143
+ function copyConformers(conformers) {
144
+ const copies = [];
145
+ for (const conformer of conformers)
146
+ copies.push({ ...conformer });
147
+ return copies;
148
+ }
149
+ //# sourceMappingURL=conformers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conformers.js","sourceRoot":"","sources":["../../../src/structure/core/conformers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * A geometry a relaxer is handed: element symbols plus flat Cartesian
3
+ * coordinates in ångström, `x,y,z` per atom.
4
+ */
5
+ export interface RelaxableGeometry {
6
+ /** Element symbol per atom, explicit hydrogens included. */
7
+ elements: string[];
8
+ /** Flat `x,y,z` per atom in ångström, length `3 · elements.length`. */
9
+ coordinates: Float64Array;
10
+ }
11
+ /** What a relaxer reports for one structure. */
12
+ export interface RelaxedGeometry {
13
+ /**
14
+ * The relaxed coordinates, in the input's atom order. Translated freely;
15
+ * never rotated, which is what lets {@link RelaxedGeometry} be compared with
16
+ * the geometry it came from by removing both centroids.
17
+ */
18
+ coordinates: Float64Array;
19
+ /**
20
+ * Total energy at `coordinates`, **in kcal/mol**, so it can be read against a
21
+ * force-field energy without a second unit in the UI.
22
+ */
23
+ energy: number;
24
+ /**
25
+ * The dispersion term of `energy`, kcal/mol, or `null` from a method that has
26
+ * none. It is the part a force field of the MMFF94 era does not model at all,
27
+ * and a large part of why conformers re-rank.
28
+ * @default null
29
+ */
30
+ dispersionEnergy: number | null;
31
+ /** Optimizer cycles spent. `0` when there was nothing to relax. */
32
+ cycles: number;
33
+ /** Whether the optimizer met its convergence criteria. */
34
+ converged: boolean;
35
+ /** Plain sentences about anything the caller should know. */
36
+ warnings: string[];
37
+ }
38
+ /** How a relaxation run is watched and cancelled. */
39
+ export interface RelaxerOptions {
40
+ /**
41
+ * Called as each structure finishes, so a caller can show progress over a
42
+ * batch that runs for seconds.
43
+ * @default undefined
44
+ */
45
+ onSettled?: (done: number, total: number) => void;
46
+ /**
47
+ * Gives the run up. A relaxer is not obliged to be able to interrupt a
48
+ * structure already in flight.
49
+ * @default undefined
50
+ */
51
+ signal?: AbortSignal;
52
+ }
53
+ /**
54
+ * Something that relaxes geometries with a real electronic structure behind it,
55
+ * and reports the energy **at the geometry it returns**.
56
+ *
57
+ * This is the seam between a site and the semi-empirical engine: nothing in
58
+ * `react-cheminfo/core` imports one, so a site that never refines a geometry
59
+ * downloads no WebAssembly. `xtbRelaxer` from `react-cheminfo/xtb` is the
60
+ * implementation, GFN2-xTB through `xtb-wasm`.
61
+ *
62
+ * An implementation must return one result per request, in request order, and
63
+ * must keep each structure's atom order.
64
+ */
65
+ export type GeometryRelaxer = (geometries: readonly RelaxableGeometry[], options?: RelaxerOptions) => Promise<RelaxedGeometry[]>;
66
+ //# sourceMappingURL=geometryRelaxer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geometryRelaxer.d.ts","sourceRoot":"","sources":["../../../src/structure/core/geometryRelaxer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,uEAAuE;IACvE,WAAW,EAAE,YAAY,CAAC;CAC3B;AAED,gDAAgD;AAChD,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,WAAW,EAAE,YAAY,CAAC;IAC1B;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,SAAS,EAAE,OAAO,CAAC;IACnB,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,qDAAqD;AACrD,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD;;;;OAIG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,eAAe,GAAG,CAC5B,UAAU,EAAE,SAAS,iBAAiB,EAAE,EACxC,OAAO,CAAC,EAAE,cAAc,KACrB,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=geometryRelaxer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geometryRelaxer.js","sourceRoot":"","sources":["../../../src/structure/core/geometryRelaxer.ts"],"names":[],"mappings":""}