react-cheminfo 0.22.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 (464) hide show
  1. package/README.md +51 -28
  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/overlay/core/index.d.ts +2 -2
  96. package/lib/overlay/core/index.d.ts.map +1 -1
  97. package/lib/overlay/core/index.js +1 -1
  98. package/lib/overlay/core/index.js.map +1 -1
  99. package/lib/overlay/core/overlayMarks.d.ts +20 -5
  100. package/lib/overlay/core/overlayMarks.d.ts.map +1 -1
  101. package/lib/overlay/core/overlayMarks.js +31 -5
  102. package/lib/overlay/core/overlayMarks.js.map +1 -1
  103. package/lib/overlay/ui/OverlayLegendMark.js +5 -0
  104. package/lib/overlay/ui/OverlayLegendMark.js.map +1 -1
  105. package/lib/projection/core/index.d.ts +4 -4
  106. package/lib/projection/core/index.d.ts.map +1 -1
  107. package/lib/projection/core/index.js +2 -2
  108. package/lib/projection/core/index.js.map +1 -1
  109. package/lib/projection/core/projectionCopy.d.ts +2 -0
  110. package/lib/projection/core/projectionCopy.d.ts.map +1 -1
  111. package/lib/projection/core/projectionCopy.js +1 -0
  112. package/lib/projection/core/projectionCopy.js.map +1 -1
  113. package/lib/projection/core/projectionGroupings.d.ts +44 -0
  114. package/lib/projection/core/projectionGroupings.d.ts.map +1 -0
  115. package/lib/projection/core/projectionGroupings.js +132 -0
  116. package/lib/projection/core/projectionGroupings.js.map +1 -0
  117. package/lib/projection/core/projectionOptions.d.ts +16 -6
  118. package/lib/projection/core/projectionOptions.d.ts.map +1 -1
  119. package/lib/projection/core/projectionOptions.js +7 -1
  120. package/lib/projection/core/projectionOptions.js.map +1 -1
  121. package/lib/projection/core/projectionPanelWords.d.ts +6 -0
  122. package/lib/projection/core/projectionPanelWords.d.ts.map +1 -1
  123. package/lib/projection/core/projectionPanelWords.js +4 -0
  124. package/lib/projection/core/projectionPanelWords.js.map +1 -1
  125. package/lib/projection/core/projectionSamples.d.ts +63 -32
  126. package/lib/projection/core/projectionSamples.d.ts.map +1 -1
  127. package/lib/projection/core/projectionSamples.js +1 -80
  128. package/lib/projection/core/projectionSamples.js.map +1 -1
  129. package/lib/projection/core/projectionStrings.d.ts +2 -0
  130. package/lib/projection/core/projectionStrings.d.ts.map +1 -1
  131. package/lib/projection/core/projectionStrings.js +10 -1
  132. package/lib/projection/core/projectionStrings.js.map +1 -1
  133. package/lib/projection/core/resolveProjectionOptions.d.ts +8 -3
  134. package/lib/projection/core/resolveProjectionOptions.d.ts.map +1 -1
  135. package/lib/projection/core/resolveProjectionOptions.js +58 -5
  136. package/lib/projection/core/resolveProjectionOptions.js.map +1 -1
  137. package/lib/projection/ui/ProjectionBar.d.ts +1 -1
  138. package/lib/projection/ui/ProjectionBar.d.ts.map +1 -1
  139. package/lib/projection/ui/ProjectionBar.js +3 -1
  140. package/lib/projection/ui/ProjectionBar.js.map +1 -1
  141. package/lib/projection/ui/ProjectionGroupingPickers.d.ts +38 -0
  142. package/lib/projection/ui/ProjectionGroupingPickers.d.ts.map +1 -0
  143. package/lib/projection/ui/ProjectionGroupingPickers.js +33 -0
  144. package/lib/projection/ui/ProjectionGroupingPickers.js.map +1 -0
  145. package/lib/projection/ui/ProjectionMapControls.d.ts +6 -7
  146. package/lib/projection/ui/ProjectionMapControls.d.ts.map +1 -1
  147. package/lib/projection/ui/ProjectionMapControls.js +11 -9
  148. package/lib/projection/ui/ProjectionMapControls.js.map +1 -1
  149. package/lib/projection/ui/ProjectionMapLegend.d.ts.map +1 -1
  150. package/lib/projection/ui/ProjectionMapLegend.js +1 -1
  151. package/lib/projection/ui/ProjectionMapLegend.js.map +1 -1
  152. package/lib/projection/ui/ProjectionMapMore.d.ts +2 -2
  153. package/lib/projection/ui/ProjectionMapMore.d.ts.map +1 -1
  154. package/lib/projection/ui/ProjectionMapMore.js +7 -5
  155. package/lib/projection/ui/ProjectionMapMore.js.map +1 -1
  156. package/lib/projection/ui/ProjectionMapTab.d.ts +15 -6
  157. package/lib/projection/ui/ProjectionMapTab.d.ts.map +1 -1
  158. package/lib/projection/ui/ProjectionMapTab.js +11 -7
  159. package/lib/projection/ui/ProjectionMapTab.js.map +1 -1
  160. package/lib/projection/ui/ProjectionPairsMore.d.ts +3 -7
  161. package/lib/projection/ui/ProjectionPairsMore.d.ts.map +1 -1
  162. package/lib/projection/ui/ProjectionPairsMore.js +4 -5
  163. package/lib/projection/ui/ProjectionPairsMore.js.map +1 -1
  164. package/lib/projection/ui/ProjectionPairsTab.d.ts.map +1 -1
  165. package/lib/projection/ui/ProjectionPairsTab.js +2 -2
  166. package/lib/projection/ui/ProjectionPairsTab.js.map +1 -1
  167. package/lib/projection/ui/ProjectionPanel.d.ts +1 -1
  168. package/lib/projection/ui/ProjectionPanel.d.ts.map +1 -1
  169. package/lib/projection/ui/ProjectionPanel.js +1 -1
  170. package/lib/projection/ui/ProjectionPanel.js.map +1 -1
  171. package/lib/projection/ui/ProjectionReadout.d.ts +7 -1
  172. package/lib/projection/ui/ProjectionReadout.d.ts.map +1 -1
  173. package/lib/projection/ui/ProjectionReadout.js +19 -7
  174. package/lib/projection/ui/ProjectionReadout.js.map +1 -1
  175. package/lib/projection/ui/ProjectionSpaceControls.d.ts +3 -5
  176. package/lib/projection/ui/ProjectionSpaceControls.d.ts.map +1 -1
  177. package/lib/projection/ui/ProjectionSpaceControls.js +9 -7
  178. package/lib/projection/ui/ProjectionSpaceControls.js.map +1 -1
  179. package/lib/projection/ui/ProjectionSpaceMore.d.ts +2 -2
  180. package/lib/projection/ui/ProjectionSpaceMore.d.ts.map +1 -1
  181. package/lib/projection/ui/ProjectionSpaceMore.js +5 -4
  182. package/lib/projection/ui/ProjectionSpaceMore.js.map +1 -1
  183. package/lib/projection/ui/ProjectionSpaceTab.d.ts +11 -3
  184. package/lib/projection/ui/ProjectionSpaceTab.d.ts.map +1 -1
  185. package/lib/projection/ui/ProjectionSpaceTab.js +7 -4
  186. package/lib/projection/ui/ProjectionSpaceTab.js.map +1 -1
  187. package/lib/projection/ui/ProjectionViewer.d.ts.map +1 -1
  188. package/lib/projection/ui/ProjectionViewer.js +1 -0
  189. package/lib/projection/ui/ProjectionViewer.js.map +1 -1
  190. package/lib/projection/ui/projectionBarReadings.d.ts +4 -1
  191. package/lib/projection/ui/projectionBarReadings.d.ts.map +1 -1
  192. package/lib/projection/ui/projectionBarReadings.js +14 -4
  193. package/lib/projection/ui/projectionBarReadings.js.map +1 -1
  194. package/lib/projection/ui/projectionBarSlots.d.ts +4 -2
  195. package/lib/projection/ui/projectionBarSlots.d.ts.map +1 -1
  196. package/lib/projection/ui/projectionBarSlots.js +3 -7
  197. package/lib/projection/ui/projectionBarSlots.js.map +1 -1
  198. package/lib/projection/ui/projectionMapChoices.d.ts +31 -6
  199. package/lib/projection/ui/projectionMapChoices.d.ts.map +1 -1
  200. package/lib/projection/ui/projectionMapChoices.js +58 -9
  201. package/lib/projection/ui/projectionMapChoices.js.map +1 -1
  202. package/lib/projection/ui/projectionMapChrome.d.ts +3 -9
  203. package/lib/projection/ui/projectionMapChrome.d.ts.map +1 -1
  204. package/lib/projection/ui/projectionMapChrome.js +41 -27
  205. package/lib/projection/ui/projectionMapChrome.js.map +1 -1
  206. package/lib/projection/ui/projectionMapCorner.d.ts +25 -0
  207. package/lib/projection/ui/projectionMapCorner.d.ts.map +1 -0
  208. package/lib/projection/ui/projectionMapCorner.js +46 -0
  209. package/lib/projection/ui/projectionMapCorner.js.map +1 -0
  210. package/lib/projection/ui/projectionMapModel.d.ts +9 -18
  211. package/lib/projection/ui/projectionMapModel.d.ts.map +1 -1
  212. package/lib/projection/ui/projectionMapModel.js +14 -39
  213. package/lib/projection/ui/projectionMapModel.js.map +1 -1
  214. package/lib/projection/ui/projectionMapView.d.ts +3 -1
  215. package/lib/projection/ui/projectionMapView.d.ts.map +1 -1
  216. package/lib/projection/ui/projectionMapView.js +9 -4
  217. package/lib/projection/ui/projectionMapView.js.map +1 -1
  218. package/lib/projection/ui/projectionSelectionSentence.d.ts +10 -0
  219. package/lib/projection/ui/projectionSelectionSentence.d.ts.map +1 -0
  220. package/lib/projection/ui/projectionSelectionSentence.js +18 -0
  221. package/lib/projection/ui/projectionSelectionSentence.js.map +1 -0
  222. package/lib/projection/ui/projectionStateApi.d.ts +47 -0
  223. package/lib/projection/ui/projectionStateApi.d.ts.map +1 -0
  224. package/lib/projection/ui/projectionStateApi.js +9 -0
  225. package/lib/projection/ui/projectionStateApi.js.map +1 -0
  226. package/lib/projection/ui/projectionTabModels.js +1 -1
  227. package/lib/projection/ui/projectionTabModels.js.map +1 -1
  228. package/lib/projection/ui/useProjectionState.d.ts +1 -29
  229. package/lib/projection/ui/useProjectionState.d.ts.map +1 -1
  230. package/lib/projection/ui/useProjectionState.js +13 -5
  231. package/lib/projection/ui/useProjectionState.js.map +1 -1
  232. package/lib/scatter/core/index.d.ts +1 -0
  233. package/lib/scatter/core/index.d.ts.map +1 -1
  234. package/lib/scatter/core/index.js +1 -0
  235. package/lib/scatter/core/index.js.map +1 -1
  236. package/lib/scatter/core/pointShape.d.ts +18 -0
  237. package/lib/scatter/core/pointShape.d.ts.map +1 -0
  238. package/lib/scatter/core/pointShape.js +70 -0
  239. package/lib/scatter/core/pointShape.js.map +1 -0
  240. package/lib/scatter/ui/ScatterPlot.d.ts.map +1 -1
  241. package/lib/scatter/ui/ScatterPlot.js +3 -2
  242. package/lib/scatter/ui/ScatterPlot.js.map +1 -1
  243. package/lib/scatter/ui/ScatterPointLayer.d.ts +14 -1
  244. package/lib/scatter/ui/ScatterPointLayer.d.ts.map +1 -1
  245. package/lib/scatter/ui/ScatterPointLayer.js +15 -3
  246. package/lib/scatter/ui/ScatterPointLayer.js.map +1 -1
  247. package/lib/scatter/ui/scatterFigureProps.d.ts +13 -0
  248. package/lib/scatter/ui/scatterFigureProps.d.ts.map +1 -1
  249. package/lib/scatter/ui/scatterMarkGlyph.d.ts +2 -1
  250. package/lib/scatter/ui/scatterMarkGlyph.d.ts.map +1 -1
  251. package/lib/scatter/ui/scatterMarkGlyph.js +7 -1
  252. package/lib/scatter/ui/scatterMarkGlyph.js.map +1 -1
  253. package/lib/scatter3d/ui/ScatterCloud.d.ts.map +1 -1
  254. package/lib/scatter3d/ui/ScatterCloud.js +2 -1
  255. package/lib/scatter3d/ui/ScatterCloud.js.map +1 -1
  256. package/lib/shared/ui/MenuButton.d.ts +3 -2
  257. package/lib/shared/ui/MenuButton.d.ts.map +1 -1
  258. package/lib/shared/ui/MenuButton.js +1 -1
  259. package/lib/shared/ui/MenuButton.js.map +1 -1
  260. package/lib/structure/core/conformerMinimise.d.ts +36 -0
  261. package/lib/structure/core/conformerMinimise.d.ts.map +1 -0
  262. package/lib/structure/core/conformerMinimise.js +81 -0
  263. package/lib/structure/core/conformerMinimise.js.map +1 -0
  264. package/lib/structure/core/conformerMinimum.d.ts +62 -0
  265. package/lib/structure/core/conformerMinimum.d.ts.map +1 -0
  266. package/lib/structure/core/conformerMinimum.js +90 -0
  267. package/lib/structure/core/conformerMinimum.js.map +1 -0
  268. package/lib/structure/core/conformerOptions.d.ts +62 -0
  269. package/lib/structure/core/conformerOptions.d.ts.map +1 -0
  270. package/lib/structure/core/conformerOptions.js +83 -0
  271. package/lib/structure/core/conformerOptions.js.map +1 -0
  272. package/lib/structure/core/conformerRefine.d.ts +104 -0
  273. package/lib/structure/core/conformerRefine.d.ts.map +1 -0
  274. package/lib/structure/core/conformerRefine.js +130 -0
  275. package/lib/structure/core/conformerRefine.js.map +1 -0
  276. package/lib/structure/core/conformerRefineRank.d.ts +36 -0
  277. package/lib/structure/core/conformerRefineRank.d.ts.map +1 -0
  278. package/lib/structure/core/conformerRefineRank.js +69 -0
  279. package/lib/structure/core/conformerRefineRank.js.map +1 -0
  280. package/lib/structure/core/conformerSession.d.ts +50 -0
  281. package/lib/structure/core/conformerSession.d.ts.map +1 -0
  282. package/lib/structure/core/conformerSession.js +88 -0
  283. package/lib/structure/core/conformerSession.js.map +1 -0
  284. package/lib/structure/core/conformerShape.d.ts +36 -0
  285. package/lib/structure/core/conformerShape.d.ts.map +1 -0
  286. package/lib/structure/core/conformerShape.js +150 -0
  287. package/lib/structure/core/conformerShape.js.map +1 -0
  288. package/lib/structure/core/conformers.d.ts +107 -0
  289. package/lib/structure/core/conformers.d.ts.map +1 -0
  290. package/lib/structure/core/conformers.js +149 -0
  291. package/lib/structure/core/conformers.js.map +1 -0
  292. package/lib/structure/core/geometryRelaxer.d.ts +66 -0
  293. package/lib/structure/core/geometryRelaxer.d.ts.map +1 -0
  294. package/lib/structure/core/geometryRelaxer.js +2 -0
  295. package/lib/structure/core/geometryRelaxer.js.map +1 -0
  296. package/lib/structure/core/index.d.ts +4 -0
  297. package/lib/structure/core/index.d.ts.map +1 -1
  298. package/lib/structure/core/index.js +2 -0
  299. package/lib/structure/core/index.js.map +1 -1
  300. package/lib/structure/core/moleculeCoordinates.d.ts +31 -0
  301. package/lib/structure/core/moleculeCoordinates.d.ts.map +1 -0
  302. package/lib/structure/core/moleculeCoordinates.js +80 -0
  303. package/lib/structure/core/moleculeCoordinates.js.map +1 -0
  304. package/lib/structure/core/molfileExport.d.ts +42 -0
  305. package/lib/structure/core/molfileExport.d.ts.map +1 -0
  306. package/lib/structure/core/molfileExport.js +47 -0
  307. package/lib/structure/core/molfileExport.js.map +1 -0
  308. package/lib/structure/core/oclResources.d.ts +12 -0
  309. package/lib/structure/core/oclResources.d.ts.map +1 -0
  310. package/lib/structure/core/oclResources.js +35 -0
  311. package/lib/structure/core/oclResources.js.map +1 -0
  312. package/lib/translate/core/catalog.d.ts +61 -0
  313. package/lib/translate/core/catalog.d.ts.map +1 -0
  314. package/lib/translate/core/catalog.js +49 -0
  315. package/lib/translate/core/catalog.js.map +1 -0
  316. package/lib/translate/core/checkTranslation.d.ts +32 -0
  317. package/lib/translate/core/checkTranslation.d.ts.map +1 -0
  318. package/lib/translate/core/checkTranslation.js +98 -0
  319. package/lib/translate/core/checkTranslation.js.map +1 -0
  320. package/lib/translate/core/contribution.d.ts +88 -0
  321. package/lib/translate/core/contribution.d.ts.map +1 -0
  322. package/lib/translate/core/contribution.js +14 -0
  323. package/lib/translate/core/contribution.js.map +1 -0
  324. package/lib/translate/core/index.d.ts +19 -0
  325. package/lib/translate/core/index.d.ts.map +1 -0
  326. package/lib/translate/core/index.js +15 -0
  327. package/lib/translate/core/index.js.map +1 -0
  328. package/lib/translate/core/marker.d.ts +45 -0
  329. package/lib/translate/core/marker.d.ts.map +1 -0
  330. package/lib/translate/core/marker.js +79 -0
  331. package/lib/translate/core/marker.js.map +1 -0
  332. package/lib/translate/core/mergeMessages.d.ts +35 -0
  333. package/lib/translate/core/mergeMessages.d.ts.map +1 -0
  334. package/lib/translate/core/mergeMessages.js +69 -0
  335. package/lib/translate/core/mergeMessages.js.map +1 -0
  336. package/lib/translate/core/session.d.ts +102 -0
  337. package/lib/translate/core/session.d.ts.map +1 -0
  338. package/lib/translate/core/session.js +162 -0
  339. package/lib/translate/core/session.js.map +1 -0
  340. package/lib/translate/core/start.d.ts +70 -0
  341. package/lib/translate/core/start.d.ts.map +1 -0
  342. package/lib/translate/core/start.js +73 -0
  343. package/lib/translate/core/start.js.map +1 -0
  344. package/lib/translate/core/suggestions.d.ts +77 -0
  345. package/lib/translate/core/suggestions.d.ts.map +1 -0
  346. package/lib/translate/core/suggestions.js +143 -0
  347. package/lib/translate/core/suggestions.js.map +1 -0
  348. package/lib/translate/core/tables.d.ts +100 -0
  349. package/lib/translate/core/tables.d.ts.map +1 -0
  350. package/lib/translate/core/tables.js +51 -0
  351. package/lib/translate/core/tables.js.map +1 -0
  352. package/lib/translate.d.ts +2 -0
  353. package/lib/translate.d.ts.map +1 -0
  354. package/lib/translate.js +6 -0
  355. package/lib/translate.js.map +1 -0
  356. package/lib/ui.d.ts +1 -0
  357. package/lib/ui.d.ts.map +1 -1
  358. package/lib/ui.js +1 -0
  359. package/lib/ui.js.map +1 -1
  360. package/lib/xtb/core/xtbRelaxer.d.ts +61 -0
  361. package/lib/xtb/core/xtbRelaxer.d.ts.map +1 -0
  362. package/lib/xtb/core/xtbRelaxer.js +108 -0
  363. package/lib/xtb/core/xtbRelaxer.js.map +1 -0
  364. package/lib/xtb.d.ts +11 -0
  365. package/lib/xtb.d.ts.map +1 -0
  366. package/lib/xtb.js +10 -0
  367. package/lib/xtb.js.map +1 -0
  368. package/package.json +18 -11
  369. package/src/chrome/ui/HeaderToggle.tsx +100 -0
  370. package/src/chrome/ui/index.ts +2 -0
  371. package/src/citation/core/gfn2Paper.ts +32 -0
  372. package/src/citation/core/index.ts +1 -0
  373. package/src/clipboard/ui/ClickToCopy.tsx +8 -7
  374. package/src/conformers.ts +87 -0
  375. package/src/core.ts +1 -0
  376. package/src/credits/core/credits.ts +16 -0
  377. package/src/ecosystem/core/index.ts +1 -0
  378. package/src/ecosystem/core/sites.ts +20 -2
  379. package/src/ecosystem/ui/EcosystemLinks.tsx +3 -1
  380. package/src/ecosystem/ui/SiteTile.tsx +3 -1
  381. package/src/format/core/index.ts +1 -1
  382. package/src/format/core/words.ts +19 -0
  383. package/src/language/core/index.ts +7 -0
  384. package/src/language/core/languageName.ts +16 -0
  385. package/src/language/core/languageParam.ts +70 -0
  386. package/src/language/ui/SiteLanguage.tsx +26 -0
  387. package/src/language/ui/index.ts +3 -0
  388. package/src/language/ui/siteLanguageContext.ts +20 -0
  389. package/src/orbital/core/atomicOrbitals.ts +17 -1
  390. package/src/orbital/core/hydrogenic.ts +2 -1
  391. package/src/orbital/core/index.ts +1 -0
  392. package/src/orbital/core/slaterEnergy.ts +83 -0
  393. package/src/overlay/core/index.ts +6 -2
  394. package/src/overlay/core/overlayMarks.ts +51 -6
  395. package/src/overlay/ui/OverlayLegendMark.tsx +5 -0
  396. package/src/projection/core/index.ts +11 -3
  397. package/src/projection/core/projectionCopy.ts +3 -0
  398. package/src/projection/core/projectionGroupings.ts +174 -0
  399. package/src/projection/core/projectionOptions.ts +18 -7
  400. package/src/projection/core/projectionPanelWords.ts +10 -0
  401. package/src/projection/core/projectionSamples.ts +62 -120
  402. package/src/projection/core/projectionStrings.ts +12 -1
  403. package/src/projection/core/resolveProjectionOptions.ts +66 -4
  404. package/src/projection/ui/ProjectionBar.tsx +4 -2
  405. package/src/projection/ui/ProjectionGroupingPickers.tsx +91 -0
  406. package/src/projection/ui/ProjectionMapControls.tsx +29 -32
  407. package/src/projection/ui/ProjectionMapLegend.tsx +1 -1
  408. package/src/projection/ui/ProjectionMapMore.tsx +14 -4
  409. package/src/projection/ui/ProjectionMapTab.tsx +27 -9
  410. package/src/projection/ui/ProjectionPairsMore.tsx +12 -21
  411. package/src/projection/ui/ProjectionPairsTab.tsx +5 -2
  412. package/src/projection/ui/ProjectionPanel.tsx +7 -3
  413. package/src/projection/ui/ProjectionReadout.tsx +28 -8
  414. package/src/projection/ui/ProjectionSpaceControls.tsx +20 -27
  415. package/src/projection/ui/ProjectionSpaceMore.tsx +12 -3
  416. package/src/projection/ui/ProjectionSpaceTab.tsx +23 -6
  417. package/src/projection/ui/ProjectionViewer.tsx +1 -0
  418. package/src/projection/ui/projectionBarReadings.ts +24 -8
  419. package/src/projection/ui/projectionBarSlots.tsx +10 -9
  420. package/src/projection/ui/projectionMapChoices.ts +71 -14
  421. package/src/projection/ui/projectionMapChrome.ts +55 -30
  422. package/src/projection/ui/projectionMapCorner.ts +67 -0
  423. package/src/projection/ui/projectionMapModel.ts +20 -59
  424. package/src/projection/ui/projectionMapView.ts +15 -8
  425. package/src/projection/ui/projectionSelectionSentence.ts +22 -0
  426. package/src/projection/ui/projectionStateApi.ts +57 -0
  427. package/src/projection/ui/projectionTabModels.ts +1 -1
  428. package/src/projection/ui/useProjectionState.ts +33 -37
  429. package/src/scatter/core/index.ts +1 -0
  430. package/src/scatter/core/pointShape.ts +80 -0
  431. package/src/scatter/ui/ScatterPlot.tsx +4 -1
  432. package/src/scatter/ui/ScatterPointLayer.tsx +39 -11
  433. package/src/scatter/ui/scatterFigureProps.ts +13 -0
  434. package/src/scatter/ui/scatterMarkGlyph.tsx +9 -1
  435. package/src/scatter3d/ui/ScatterCloud.tsx +3 -0
  436. package/src/shared/ui/MenuButton.tsx +4 -3
  437. package/src/structure/core/conformerMinimise.ts +99 -0
  438. package/src/structure/core/conformerMinimum.ts +125 -0
  439. package/src/structure/core/conformerOptions.ts +125 -0
  440. package/src/structure/core/conformerRefine.ts +234 -0
  441. package/src/structure/core/conformerRefineRank.ts +89 -0
  442. package/src/structure/core/conformerSession.ts +123 -0
  443. package/src/structure/core/conformerShape.ts +181 -0
  444. package/src/structure/core/conformers.ts +282 -0
  445. package/src/structure/core/geometryRelaxer.ts +71 -0
  446. package/src/structure/core/index.ts +13 -0
  447. package/src/structure/core/moleculeCoordinates.ts +93 -0
  448. package/src/structure/core/molfileExport.ts +62 -0
  449. package/src/structure/core/oclResources.ts +41 -0
  450. package/src/translate/core/catalog.ts +83 -0
  451. package/src/translate/core/checkTranslation.ts +128 -0
  452. package/src/translate/core/contribution.ts +99 -0
  453. package/src/translate/core/index.ts +72 -0
  454. package/src/translate/core/marker.ts +85 -0
  455. package/src/translate/core/mergeMessages.ts +74 -0
  456. package/src/translate/core/session.ts +250 -0
  457. package/src/translate/core/start.ts +121 -0
  458. package/src/translate/core/suggestions.ts +211 -0
  459. package/src/translate/core/tables.ts +120 -0
  460. package/src/translate.ts +5 -0
  461. package/src/ui.ts +1 -0
  462. package/src/xtb/core/xtbRelaxer.ts +160 -0
  463. package/src/xtb.ts +16 -0
  464. package/styles/chrome.css +61 -30
@@ -0,0 +1,80 @@
1
+ import { chartRoundPixel } from '../../chart/core/chartScale.ts';
2
+ import type { OverlayMarkShape } from '../../overlay/core/overlayMarks.ts';
3
+
4
+ /**
5
+ * The outline of a mark drawn as a filled polygon — a sample shaped by a
6
+ * second grouping, or a marker drawn in one of those shapes — as SVG path data.
7
+ *
8
+ * Every shape covers the area of the disc it stands in for. The eye weighs a
9
+ * mark by its ink, so a square drawn in the disc's own box would make its
10
+ * group read as the heavier one — which is a claim about the data that nothing
11
+ * in the data supports.
12
+ * @param shape - The shape.
13
+ * @param x - Horizontal centre, in pixels.
14
+ * @param y - Vertical centre, in pixels.
15
+ * @param radius - Radius of the disc the shape stands in for, in pixels.
16
+ * @returns The path data, or `null` for a disc, which is drawn as a circle,
17
+ * and for every mark that is not a filled polygon.
18
+ */
19
+ export function pointShapePath(
20
+ shape: OverlayMarkShape,
21
+ x: number,
22
+ y: number,
23
+ radius: number,
24
+ ): string | null {
25
+ if (shape === 'square') {
26
+ const half = SQUARE_HALF * radius;
27
+ return polygon([
28
+ [x - half, y - half],
29
+ [x + half, y - half],
30
+ [x + half, y + half],
31
+ [x - half, y + half],
32
+ ]);
33
+ }
34
+ if (shape === 'diamond') {
35
+ const reach = DIAMOND_REACH * radius;
36
+ return polygon([
37
+ [x, y - reach],
38
+ [x + reach, y],
39
+ [x, y + reach],
40
+ [x - reach, y],
41
+ ]);
42
+ }
43
+ if (shape === 'triangle' || shape === 'triangle-down') {
44
+ // The centroid sits on the point, so the triangle is balanced on the
45
+ // sample rather than hanging from it.
46
+ const tip = TRIANGLE_TIP * radius;
47
+ const half = TRIANGLE_HALF_BASE * radius;
48
+ const base = (TRIANGLE_TIP / 2) * radius;
49
+ const flip = shape === 'triangle' ? 1 : -1;
50
+ return polygon([
51
+ [x, y - flip * tip],
52
+ [x + half, y + flip * base],
53
+ [x - half, y + flip * base],
54
+ ]);
55
+ }
56
+ return null;
57
+ }
58
+
59
+ function polygon(corners: ReadonlyArray<readonly [number, number]>): string {
60
+ let path = '';
61
+ for (const [x, y] of corners) {
62
+ path += `${path === '' ? 'M' : 'L'}${chartRoundPixel(x)} ${chartRoundPixel(y)}`;
63
+ }
64
+ return `${path}Z`;
65
+ }
66
+
67
+ /** Half the side of a square as large as a disc of radius one: √π / 2. */
68
+ const SQUARE_HALF = Math.sqrt(Math.PI) / 2;
69
+
70
+ /** How far a diamond as large as that disc reaches from its centre: √(π / 2). */
71
+ const DIAMOND_REACH = Math.sqrt(Math.PI / 2);
72
+
73
+ /**
74
+ * The side of an equilateral triangle as large as that disc is √(4π / √3). Its
75
+ * tip stands side / √3 from the centroid, and its base half as far on the other
76
+ * side.
77
+ */
78
+ const TRIANGLE_SIDE = Math.sqrt((4 * Math.PI) / Math.sqrt(3));
79
+ const TRIANGLE_TIP = TRIANGLE_SIDE / Math.sqrt(3);
80
+ const TRIANGLE_HALF_BASE = TRIANGLE_SIDE / 2;
@@ -32,7 +32,8 @@ import { useScatterLabels } from './useScatterLabels.ts';
32
32
  */
33
33
  export function ScatterPlot(props: ScatterPlotProps): ReactElement {
34
34
  const { x, y, width, height, xAxis, yAxis, groupOf, groups } = props;
35
- const { mutedGroups, ellipse = null, ellipseMinimumPoints } = props;
35
+ const { mutedGroups, shapeOf, shapes } = props;
36
+ const { ellipse = null, ellipseMinimumPoints } = props;
36
37
  const { ellipseFillOpacity, showGroupMeans, markers } = props;
37
38
  const { pointRadius = 3.5, outlinedFrom, pointLabels } = props;
38
39
  const { showGroupLabels = false, selected, defaultSelected } = props;
@@ -127,6 +128,8 @@ export function ScatterPlot(props: ScatterPlotProps): ReactElement {
127
128
  groupOf={groupOf}
128
129
  colors={ink.colors}
129
130
  opacities={ink.opacities}
131
+ shapeOf={shapeOf}
132
+ shapes={shapes}
130
133
  radius={pointRadius}
131
134
  outlinedFrom={outlinedFrom}
132
135
  />
@@ -3,6 +3,8 @@ import { memo } from 'react';
3
3
 
4
4
  import { chartGroupIndex } from '../../chart/core/chartGroups.ts';
5
5
  import { chartRoundPixel } from '../../chart/core/chartScale.ts';
6
+ import type { OverlaySampleShape } from '../../overlay/core/overlayMarks.ts';
7
+ import { pointShapePath } from '../core/pointShape.ts';
6
8
  import type { ScreenPoints } from '../core/screenPoints.ts';
7
9
 
8
10
  /** What {@link ScatterPointLayer} draws. */
@@ -31,6 +33,17 @@ export interface ScatterPointLayerProps {
31
33
  * @default undefined — every group is drawn at full strength
32
34
  */
33
35
  opacities?: readonly number[];
36
+ /**
37
+ * Which shape each point takes, as an index into `shapes`. An entry of `-1`,
38
+ * or one outside the range, is a disc.
39
+ * @default undefined — every point is a disc
40
+ */
41
+ shapeOf?: ArrayLike<number>;
42
+ /**
43
+ * The shapes, in the order `shapeOf` names them.
44
+ * @default undefined
45
+ */
46
+ shapes?: readonly OverlaySampleShape[];
34
47
  /**
35
48
  * Colour of a point belonging to no group. It has to be the one ink on the
36
49
  * plot that names nothing, or a reader counts it as one more group.
@@ -77,7 +90,8 @@ export interface ScatterPointLayerProps {
77
90
  *
78
91
  * A hollow dot is the same dot at the same radius with its colour moved from
79
92
  * the fill to the stroke, so the two read as one kind of thing seen at two
80
- * levels of confidence rather than as two unrelated marks.
93
+ * levels of confidence rather than as two unrelated marks. A shaped point
94
+ * follows the same rule, and covers the area of the disc it stands in for.
81
95
  * @param props - See {@link ScatterPointLayerProps}.
82
96
  * @returns The cloud.
83
97
  */
@@ -89,6 +103,8 @@ export const ScatterPointLayer = memo(function ScatterPointLayer(
89
103
  groupOf,
90
104
  colors,
91
105
  opacities,
106
+ shapeOf,
107
+ shapes,
92
108
  fallbackColor = 'var(--text-faint)',
93
109
  radius = 3.5,
94
110
  radii,
@@ -102,6 +118,7 @@ export const ScatterPointLayer = memo(function ScatterPointLayer(
102
118
  const steps = order === undefined ? count : Math.min(count, order.length);
103
119
  const hollowFrom = outlineStart(outlinedFrom, count);
104
120
  const groups = colors?.length ?? 0;
121
+ const shapeCount = shapes?.length ?? 0;
105
122
  const ink = groupInk(colors, opacities, fallbackColor);
106
123
 
107
124
  const dots: ReactElement[] = [];
@@ -115,17 +132,28 @@ export const ScatterPointLayer = memo(function ScatterPointLayer(
115
132
  const color = ink.colors[slot] ?? fallbackColor;
116
133
  const hollow = index >= hollowFrom;
117
134
  const size = radii?.[index];
135
+ const reach = size === undefined ? radius : chartRoundPixel(size);
136
+ const shape = shapes?.[chartGroupIndex(shapeOf, index, shapeCount)];
137
+ const outline =
138
+ shape === undefined ? null : pointShapePath(shape, x, y, reach);
139
+ const paint = {
140
+ fill: hollow ? 'none' : color,
141
+ stroke: hollow ? color : undefined,
142
+ strokeWidth: hollow ? OUTLINE_WIDTH : undefined,
143
+ opacity: ink.opacities[slot],
144
+ };
118
145
  dots.push(
119
- <circle
120
- key={index}
121
- cx={chartRoundPixel(x)}
122
- cy={chartRoundPixel(y)}
123
- r={size === undefined ? radius : chartRoundPixel(size)}
124
- fill={hollow ? 'none' : color}
125
- stroke={hollow ? color : undefined}
126
- strokeWidth={hollow ? OUTLINE_WIDTH : undefined}
127
- opacity={ink.opacities[slot]}
128
- />,
146
+ outline === null ? (
147
+ <circle
148
+ key={index}
149
+ cx={chartRoundPixel(x)}
150
+ cy={chartRoundPixel(y)}
151
+ r={reach}
152
+ {...paint}
153
+ />
154
+ ) : (
155
+ <path key={index} d={outline} {...paint} />
156
+ ),
129
157
  );
130
158
  }
131
159
 
@@ -9,6 +9,7 @@
9
9
 
10
10
  import type { ReactNode } from 'react';
11
11
 
12
+ import type { OverlaySampleShape } from '../../overlay/core/overlayMarks.ts';
12
13
  import type { ScatterSelectionMode } from '../core/scatterSelection.ts';
13
14
 
14
15
  import type { SelectionChange } from './useScatterSelection.ts';
@@ -61,6 +62,18 @@ export interface ScatterGroupProps {
61
62
  * @default undefined — every group is drawn in full
62
63
  */
63
64
  mutedGroups?: ReadonlySet<string>;
65
+ /**
66
+ * Which shape each point takes, as an index into `shapes`: a second
67
+ * grouping of the same points, drawn while colour keeps the first. A point
68
+ * with `-1`, `NaN`, or an index outside the range, is a disc.
69
+ * @default undefined — every point is a disc
70
+ */
71
+ shapeOf?: ArrayLike<number>;
72
+ /**
73
+ * The shapes, in the order `shapeOf` names them.
74
+ * @default undefined
75
+ */
76
+ shapes?: readonly OverlaySampleShape[];
64
77
  /**
65
78
  * Radius of a dot, in pixels. A cloud draws the dot at the middle of its box
66
79
  * at this size, one at the front larger and one at the back smaller.
@@ -10,6 +10,7 @@ import type { ReactElement } from 'react';
10
10
 
11
11
  import { chartRoundPixel } from '../../chart/core/chartScale.ts';
12
12
  import type { OverlayMarkShape } from '../../overlay/core/overlayMarks.ts';
13
+ import { pointShapePath } from '../core/pointShape.ts';
13
14
 
14
15
  /** A point drawn over the cloud that is not a sample, already in pixels. */
15
16
  export interface ScatterPixelMark {
@@ -32,7 +33,8 @@ export interface ScatterPixelMark {
32
33
  * One mark, drawn as the glyph its shape asks for.
33
34
  *
34
35
  * A rule laid across the cloud names no point, so the two rule shapes are
35
- * drawn as the default cross.
36
+ * drawn as the default cross. The three filled polygons are the shapes a
37
+ * sample can take, drawn as large as the disc they stand in for.
36
38
  * @param mark - What to draw, already in the frame's pixels.
37
39
  * @param size - Side of the square the glyph is drawn in, in pixels.
38
40
  * @param key - What React reconciles the glyph by.
@@ -81,6 +83,12 @@ export function markGlyph(
81
83
  />
82
84
  );
83
85
  }
86
+ const polygon = pointShapePath(shape, x, y, half);
87
+ if (polygon !== null) {
88
+ return (
89
+ <path key={key} {...shared} d={polygon} fill={color} stroke="none" />
90
+ );
91
+ }
84
92
  return (
85
93
  <path
86
94
  key={key}
@@ -47,6 +47,7 @@ import { useOrbitDrag } from './useOrbitDrag.ts';
47
47
  export function ScatterCloud(props: ScatterCloudProps): ReactElement {
48
48
  const { x, y, z, width, height, xLabel, yLabel, zLabel } = props;
49
49
  const { groupOf, groups, mutedGroups, ellipsoid = null } = props;
50
+ const { shapeOf, shapes } = props;
50
51
  const { ellipsoidMinimumPoints, ellipsoidFillOpacity } = props;
51
52
  const { showGroupLabels = false, pointLabels, pointRadius = 3.5 } = props;
52
53
  const { outlinedFrom, selected, defaultSelected, onSelectionChange } = props;
@@ -198,6 +199,8 @@ export function ScatterCloud(props: ScatterCloudProps): ReactElement {
198
199
  groupOf={groupOf}
199
200
  colors={ink.colors}
200
201
  opacities={ink.opacities}
202
+ shapeOf={shapeOf}
203
+ shapes={shapes}
201
204
  radius={pointRadius}
202
205
  outlinedFrom={outlinedFrom}
203
206
  />
@@ -11,8 +11,9 @@ const HOLDER_STYLE: CSSProperties = {
11
11
  /** What every button of a site header takes, whatever its menu holds. */
12
12
  export interface HeaderButtonProps {
13
13
  /**
14
- * Whether the button is reduced to its icon — no text, no caret — for a
15
- * header that has run out of room. The icon still opens the same menu.
14
+ * Whether the text is left out of the button altogether, rather than only
15
+ * hidden: a bar that has run out of room drops the caret with it. The glyph
16
+ * names itself through its tooltip either way.
16
17
  * @default false
17
18
  */
18
19
  compact?: boolean;
@@ -60,7 +61,7 @@ export function MenuButton(props: MenuButtonProps): ReactElement {
60
61
  endIcon={compact ? undefined : 'caret-down'}
61
62
  text={compact ? undefined : label}
62
63
  aria-label={label}
63
- title={compact ? label : undefined}
64
+ title={label}
64
65
  />
65
66
  </PopoverNext>
66
67
  </span>
@@ -0,0 +1,99 @@
1
+ import type { Molecule } from 'openchemlib';
2
+ import { ForceFieldMMFF94 } from 'openchemlib';
3
+
4
+ import { ordinal } from '../../format/core/words.ts';
5
+
6
+ import type { ConformerOptions } from './conformerOptions.ts';
7
+
8
+ /**
9
+ * Relax one conformer in place and return its energy.
10
+ *
11
+ * Minimisation is best-effort. MMFF94 cannot type every element (boron, for
12
+ * one), so a conformer it refuses gets a `null` energy and a warning rather
13
+ * than an exception. A non-zero return code from `minimise()` is *not* a
14
+ * failure: ethyne returns 2 with a perfect geometry.
15
+ *
16
+ * Warnings count the conformers the generator handed back, kept or not, so one
17
+ * number never means two things — a row number would, once one is dropped.
18
+ * @param conformer - The conformer to relax. Mutated.
19
+ * @param options - Force field and iteration budget.
20
+ * @param produced - 1-based position of the conformer in the generator's output.
21
+ * @param warnings - Receives one sentence when the energy is unknown.
22
+ * @returns Total energy in kcal/mol, or `null` when none was computed.
23
+ */
24
+ export function minimiseConformer(
25
+ conformer: Molecule,
26
+ options: ConformerOptions,
27
+ produced: number,
28
+ warnings: string[],
29
+ ): number | null {
30
+ const algorithm = options.minimisation;
31
+ if (algorithm === 'none') return null;
32
+ let energy: number;
33
+ try {
34
+ const forceField = new ForceFieldMMFF94(conformer, algorithm, {});
35
+ forceField.minimise({ maxIts: options.maxIterations });
36
+ energy = forceField.getTotalEnergy();
37
+ } catch (error) {
38
+ warnings.push(
39
+ `The ${ordinal(produced)} conformer produced could not be minimised with ${algorithm} (${readable(error)}), so its energy is unknown.`,
40
+ );
41
+ return null;
42
+ }
43
+ if (!Number.isFinite(energy)) {
44
+ warnings.push(
45
+ `The ${ordinal(produced)} conformer produced minimised to a non-finite ${algorithm} energy, so its energy is unknown.`,
46
+ );
47
+ return null;
48
+ }
49
+ return energy;
50
+ }
51
+
52
+ /** What {@link rankByEnergy} reads and rewrites on a conformer. */
53
+ export interface RankedConformer {
54
+ id: number;
55
+ energy: number | null;
56
+ relativeEnergy: number | null;
57
+ }
58
+
59
+ /**
60
+ * Order a set from the most stable conformer down, number it from one in that
61
+ * order, and measure every known energy from the lowest.
62
+ *
63
+ * A conformer without an energy ranks after every one that has one; equal
64
+ * energies, and conformers without one, keep the order they came in.
65
+ * @param conformers - The set. Each `id` and `relativeEnergy` is rewritten in place.
66
+ * @returns The same conformers, most stable first.
67
+ */
68
+ export function rankByEnergy<T extends RankedConformer>(
69
+ conformers: readonly T[],
70
+ ): T[] {
71
+ assignRelativeEnergies(conformers);
72
+ const ranked = conformers.toSorted(compareEnergy);
73
+ for (const [index, conformer] of ranked.entries()) conformer.id = index + 1;
74
+ return ranked;
75
+ }
76
+
77
+ function compareEnergy(a: RankedConformer, b: RankedConformer): number {
78
+ if (a.energy === null) return b.energy === null ? 0 : 1;
79
+ if (b.energy === null) return -1;
80
+ return a.energy - b.energy;
81
+ }
82
+
83
+ function assignRelativeEnergies(conformers: readonly RankedConformer[]): void {
84
+ let lowest = Number.POSITIVE_INFINITY;
85
+ for (const conformer of conformers) {
86
+ const energy = conformer.energy;
87
+ if (energy !== null && energy < lowest) lowest = energy;
88
+ }
89
+ if (lowest === Number.POSITIVE_INFINITY) return;
90
+ for (const conformer of conformers) {
91
+ const energy = conformer.energy;
92
+ if (energy !== null) conformer.relativeEnergy = energy - lowest;
93
+ }
94
+ }
95
+
96
+ function readable(error: unknown): string {
97
+ const message = error instanceof Error ? error.message : String(error);
98
+ return message.replace(/^\w+\$\w+: /, '');
99
+ }
@@ -0,0 +1,125 @@
1
+ import { Molecule } from 'openchemlib';
2
+
3
+ import type { ConformerShape } from './conformerShape.ts';
4
+ import { conformerShape } from './conformerShape.ts';
5
+
6
+ /** What {@link isKeptMinimum} and {@link minimisedShapes} read of a conformer. */
7
+ export interface KeptConformer {
8
+ /** Total energy in kcal/mol, `null` when it was not computed. */
9
+ energy: number | null;
10
+ /** The 3D structure, as molfile text. */
11
+ molfile: { data: string };
12
+ }
13
+
14
+ /**
15
+ * Energy gap, in kcal/mol, under which two minimised conformers can be the
16
+ * same minimum. Copies of one minimum agree to about 1e-7; distinct minima
17
+ * that close in energy differ in shape by more than a percent.
18
+ */
19
+ export const SAME_ENERGY_TOLERANCE = 1e-3;
20
+
21
+ /** Gap between principal moments, relative to the largest, under which two shapes are one. */
22
+ export const SAME_SHAPE_TOLERANCE = 1e-3;
23
+
24
+ /**
25
+ * Gap in chirality under which two shapes are one. Copies of one minimum agree
26
+ * to about 1e-4 and a shape that is its own mirror image reads within 1e-3 of
27
+ * zero, while the mirror images of a chiral minimum usually sit tenths apart.
28
+ */
29
+ export const SAME_CHIRALITY_TOLERANCE = 1e-2;
30
+
31
+ /**
32
+ * Whether two minimised conformers are one energy minimum: the same energy,
33
+ * the same principal moments and the same chirality. The two mirror-image
34
+ * gauche butanes are two minima; the two chairs of cyclohexane, each its own
35
+ * mirror image, are one.
36
+ * @param energyA - Total energy of the first conformer, kcal/mol.
37
+ * @param shapeA - Shape of the first conformer.
38
+ * @param energyB - Total energy of the second conformer, kcal/mol.
39
+ * @param shapeB - Shape of the second conformer.
40
+ * @returns `true` when both agree within {@link SAME_ENERGY_TOLERANCE}, {@link SAME_SHAPE_TOLERANCE} and {@link SAME_CHIRALITY_TOLERANCE}.
41
+ */
42
+ export function isSameMinimum(
43
+ energyA: number,
44
+ shapeA: ConformerShape,
45
+ energyB: number,
46
+ shapeB: ConformerShape,
47
+ ): boolean {
48
+ if (Math.abs(energyA - energyB) > SAME_ENERGY_TOLERANCE) return false;
49
+ return isSameShape(shapeA, shapeB);
50
+ }
51
+
52
+ /**
53
+ * Whether two conformers have the same shape: the same principal moments and
54
+ * the same chirality, energies not consulted. Two mirror images share the
55
+ * moments and not the chirality, so they are two shapes.
56
+ * @param shapeA - Shape of one conformer.
57
+ * @param shapeB - Shape of the other.
58
+ * @returns `true` when both agree within {@link SAME_SHAPE_TOLERANCE} and {@link SAME_CHIRALITY_TOLERANCE}.
59
+ */
60
+ export function isSameShape(
61
+ shapeA: ConformerShape,
62
+ shapeB: ConformerShape,
63
+ ): boolean {
64
+ if (
65
+ Math.abs(shapeA.chirality - shapeB.chirality) > SAME_CHIRALITY_TOLERANCE
66
+ ) {
67
+ return false;
68
+ }
69
+ const momentsA = shapeA.moments;
70
+ const momentsB = shapeB.moments;
71
+ const scale = Math.max(momentsA[2], momentsB[2]);
72
+ for (let axis = 0; axis < 3; axis++) {
73
+ const gap = Math.abs((momentsA[axis] ?? 0) - (momentsB[axis] ?? 0));
74
+ if (gap > SAME_SHAPE_TOLERANCE * scale) return false;
75
+ }
76
+ return true;
77
+ }
78
+
79
+ /**
80
+ * Whether a minimised conformer lands in a minimum one of `kept` already holds.
81
+ * @param energy - Total energy of the candidate, kcal/mol.
82
+ * @param shape - Shape of the candidate.
83
+ * @param kept - The conformers kept so far.
84
+ * @param keptShapes - Their shapes, index for index; `null` where there is no energy.
85
+ * @returns `true` when one of them is the same minimum.
86
+ */
87
+ export function isKeptMinimum(
88
+ energy: number,
89
+ shape: ConformerShape,
90
+ kept: readonly KeptConformer[],
91
+ keptShapes: ReadonlyArray<ConformerShape | null>,
92
+ ): boolean {
93
+ for (let index = 0; index < kept.length; index++) {
94
+ const keptEnergy = kept[index]?.energy ?? null;
95
+ const keptShape = keptShapes[index] ?? null;
96
+ if (
97
+ keptEnergy !== null &&
98
+ keptShape !== null &&
99
+ isSameMinimum(energy, shape, keptEnergy, keptShape)
100
+ ) {
101
+ return true;
102
+ }
103
+ }
104
+ return false;
105
+ }
106
+
107
+ /**
108
+ * Shapes of conformers read back from their molfiles, so a continuation
109
+ * compares new conformers with the ones a previous run kept.
110
+ * @param conformers - Conformers of an earlier run.
111
+ * @returns Their shapes, index for index; `null` for one without an energy.
112
+ */
113
+ export function minimisedShapes(
114
+ conformers: readonly KeptConformer[],
115
+ ): Array<ConformerShape | null> {
116
+ const shapes: Array<ConformerShape | null> = [];
117
+ for (const conformer of conformers) {
118
+ shapes.push(
119
+ conformer.energy === null
120
+ ? null
121
+ : conformerShape(Molecule.fromMolfile(conformer.molfile.data)),
122
+ );
123
+ }
124
+ return shapes;
125
+ }
@@ -0,0 +1,125 @@
1
+ /** The four torsion-set strategies OpenChemLib's `ConformerGenerator` offers. */
2
+ export const CONFORMER_STRATEGIES = [
3
+ 'adaptive-random',
4
+ 'likely-random',
5
+ 'pure-random',
6
+ 'likely-systematic',
7
+ ] as const;
8
+
9
+ /** One of {@link CONFORMER_STRATEGIES}. */
10
+ export type ConformerStrategy = (typeof CONFORMER_STRATEGIES)[number];
11
+
12
+ /** Short names for the strategy picker. */
13
+ export const STRATEGY_LABELS: Record<ConformerStrategy, string> = {
14
+ 'adaptive-random': 'Adaptive random',
15
+ 'likely-random': 'Likely random',
16
+ 'pure-random': 'Pure random',
17
+ 'likely-systematic': 'Likely systematic',
18
+ };
19
+
20
+ /** One sentence per strategy, shown as help text next to the picker. */
21
+ export const STRATEGY_DETAILS: Record<ConformerStrategy, string> = {
22
+ 'adaptive-random':
23
+ 'Draws torsions at random but steers away from the combinations that already collided, which covers a flexible molecule fastest.',
24
+ 'likely-random':
25
+ 'Draws torsions at random from the torsion database, weighted by how often each angle is seen in crystal structures.',
26
+ 'pure-random':
27
+ 'Draws every torsion uniformly at random, ignoring how likely the angle is — the widest spread and the least realistic set.',
28
+ 'likely-systematic':
29
+ 'Walks the torsion combinations in decreasing likelihood, so the first conformers are the most probable ones and the set is reproducible.',
30
+ };
31
+
32
+ /** Force fields offered for the optional minimisation step. */
33
+ export const MINIMISATION_ALGORITHMS = [
34
+ 'none',
35
+ 'MMFF94',
36
+ 'MMFF94s',
37
+ 'MMFF94s+',
38
+ ] as const;
39
+
40
+ /** One of {@link MINIMISATION_ALGORITHMS}. */
41
+ export type MinimisationAlgorithm = (typeof MINIMISATION_ALGORITHMS)[number];
42
+
43
+ /** Short names for the minimisation picker. */
44
+ export const MINIMISATION_LABELS: Record<MinimisationAlgorithm, string> = {
45
+ none: 'None (no energies)',
46
+ MMFF94: 'MMFF94',
47
+ MMFF94s: 'MMFF94s',
48
+ 'MMFF94s+': 'MMFF94s+',
49
+ };
50
+
51
+ /** Everything a conformer run needs, in one serialisable object. */
52
+ export interface ConformerOptions {
53
+ /** Which torsion-set strategy the generator follows. */
54
+ strategy: ConformerStrategy;
55
+ /** Upper bound on the number of conformers kept. */
56
+ maxConformers: number;
57
+ /** Upper bound on the distinct torsion sets the strategy will try. */
58
+ maxTorsionSets: number;
59
+ /** Rotate every rotatable bond in 60° steps instead of using the torsion database. */
60
+ use60DegreeSteps: boolean;
61
+ /** Seed of the generator's random source, so a run is reproducible. */
62
+ seed: number;
63
+ /** Force field used to relax each conformer; `none` leaves the energies unknown. */
64
+ minimisation: MinimisationAlgorithm;
65
+ /** Iteration budget of a single minimisation. */
66
+ maxIterations: number;
67
+ /** Wall-clock budget of the whole run, in seconds. */
68
+ timeoutSeconds: number;
69
+ }
70
+
71
+ /** The settings a first-time visitor gets. */
72
+ export const DEFAULT_CONFORMER_OPTIONS: ConformerOptions = {
73
+ strategy: 'adaptive-random',
74
+ maxConformers: 10,
75
+ maxTorsionSets: 10_000,
76
+ use60DegreeSteps: false,
77
+ seed: 42,
78
+ minimisation: 'MMFF94s+',
79
+ maxIterations: 4000,
80
+ timeoutSeconds: 10,
81
+ };
82
+
83
+ /**
84
+ * Whether two option sets would run the same calculation.
85
+ * @param first - One option set.
86
+ * @param second - The other.
87
+ * @returns `true` when every option is equal.
88
+ */
89
+ export function sameConformerOptions(
90
+ first: ConformerOptions,
91
+ second: ConformerOptions,
92
+ ): boolean {
93
+ for (const key of Object.keys(first) as Array<keyof ConformerOptions>) {
94
+ if (first[key] !== second[key]) return false;
95
+ }
96
+ return true;
97
+ }
98
+
99
+ /**
100
+ * Rotatable-bond count above which the conformer space is large enough that the
101
+ * run is worth warning about before it starts.
102
+ */
103
+ export const ROTATABLE_BOND_WARNING = 12;
104
+
105
+ /**
106
+ * Narrow an arbitrary string, typically a URL parameter or a stored preference,
107
+ * to a strategy id.
108
+ * @param value - Text to test.
109
+ * @returns Whether `value` is one of {@link CONFORMER_STRATEGIES}.
110
+ */
111
+ export function isConformerStrategy(value: string): value is ConformerStrategy {
112
+ return (CONFORMER_STRATEGIES as readonly string[]).includes(value);
113
+ }
114
+
115
+ /**
116
+ * Narrow an arbitrary string, typically a stored preference, to a force-field
117
+ * id.
118
+ * @param value - Text to test.
119
+ * @returns Whether `value` is one of {@link MINIMISATION_ALGORITHMS}.
120
+ */
121
+ export function isMinimisationAlgorithm(
122
+ value: string,
123
+ ): value is MinimisationAlgorithm {
124
+ return (MINIMISATION_ALGORITHMS as readonly string[]).includes(value);
125
+ }