react-cheminfo 0.69.0 → 0.71.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 (616) hide show
  1. package/README.md +70 -2
  2. package/lib/about/core/providers.d.ts +6 -0
  3. package/lib/about/core/providers.d.ts.map +1 -1
  4. package/lib/about/core/providers.js +7 -0
  5. package/lib/about/core/providers.js.map +1 -1
  6. package/lib/about/ui/AboutProvidedBy.js +34 -0
  7. package/lib/about/ui/AboutProvidedBy.js.map +1 -1
  8. package/lib/chart/ui/useChartPointer.d.ts +9 -1
  9. package/lib/chart/ui/useChartPointer.d.ts.map +1 -1
  10. package/lib/chart/ui/useChartPointer.js +11 -3
  11. package/lib/chart/ui/useChartPointer.js.map +1 -1
  12. package/lib/credits/core/credits.d.ts +41 -0
  13. package/lib/credits/core/credits.d.ts.map +1 -1
  14. package/lib/credits/core/credits.js +50 -0
  15. package/lib/credits/core/credits.js.map +1 -1
  16. package/lib/download/core/drawingMarkup.d.ts +8 -1
  17. package/lib/download/core/drawingMarkup.d.ts.map +1 -1
  18. package/lib/download/core/drawingMarkup.js +13 -1
  19. package/lib/download/core/drawingMarkup.js.map +1 -1
  20. package/lib/download/core/figurePng.d.ts +14 -0
  21. package/lib/download/core/figurePng.d.ts.map +1 -1
  22. package/lib/download/core/figurePng.js +21 -6
  23. package/lib/download/core/figurePng.js.map +1 -1
  24. package/lib/download/core/figureSvg.d.ts.map +1 -1
  25. package/lib/download/core/figureSvg.js +5 -3
  26. package/lib/download/core/figureSvg.js.map +1 -1
  27. package/lib/download/core/figureTarget.d.ts +13 -0
  28. package/lib/download/core/figureTarget.d.ts.map +1 -1
  29. package/lib/download/core/figureTarget.js +25 -5
  30. package/lib/download/core/figureTarget.js.map +1 -1
  31. package/lib/download/core/svgBounds.d.ts +15 -0
  32. package/lib/download/core/svgBounds.d.ts.map +1 -1
  33. package/lib/download/core/svgBounds.js +20 -0
  34. package/lib/download/core/svgBounds.js.map +1 -1
  35. package/lib/download/core/svgToPng.d.ts.map +1 -1
  36. package/lib/download/core/svgToPng.js +4 -2
  37. package/lib/download/core/svgToPng.js.map +1 -1
  38. package/lib/format/core/relativeTime.d.ts +8 -3
  39. package/lib/format/core/relativeTime.d.ts.map +1 -1
  40. package/lib/format/core/relativeTime.js +19 -7
  41. package/lib/format/core/relativeTime.js.map +1 -1
  42. package/lib/host/core/connectHost.d.ts +25 -34
  43. package/lib/host/core/connectHost.d.ts.map +1 -1
  44. package/lib/host/core/connectHost.js +43 -89
  45. package/lib/host/core/connectHost.js.map +1 -1
  46. package/lib/host/core/hostOutputs.d.ts +58 -0
  47. package/lib/host/core/hostOutputs.d.ts.map +1 -0
  48. package/lib/host/core/hostOutputs.js +151 -0
  49. package/lib/host/core/hostOutputs.js.map +1 -0
  50. package/lib/host/core/index.d.ts +9 -3
  51. package/lib/host/core/index.d.ts.map +1 -1
  52. package/lib/host/core/index.js +4 -1
  53. package/lib/host/core/index.js.map +1 -1
  54. package/lib/host/core/irKinds.d.ts +124 -0
  55. package/lib/host/core/irKinds.d.ts.map +1 -0
  56. package/lib/host/core/irKinds.js +46 -0
  57. package/lib/host/core/irKinds.js.map +1 -0
  58. package/lib/host/core/kinds.d.ts +13 -5
  59. package/lib/host/core/kinds.d.ts.map +1 -1
  60. package/lib/host/core/kinds.js +11 -5
  61. package/lib/host/core/kinds.js.map +1 -1
  62. package/lib/host/core/protocol.d.ts +50 -7
  63. package/lib/host/core/protocol.d.ts.map +1 -1
  64. package/lib/host/core/protocol.js +10 -6
  65. package/lib/host/core/protocol.js.map +1 -1
  66. package/lib/host/core/selectInputs.d.ts +37 -0
  67. package/lib/host/core/selectInputs.d.ts.map +1 -0
  68. package/lib/host/core/selectInputs.js +110 -0
  69. package/lib/host/core/selectInputs.js.map +1 -0
  70. package/lib/host/testing/sciPeaks.d.ts +31 -0
  71. package/lib/host/testing/sciPeaks.d.ts.map +1 -1
  72. package/lib/host/testing/sciPeaks.js +73 -0
  73. package/lib/host/testing/sciPeaks.js.map +1 -1
  74. package/lib/host/testing/standInHost.d.ts +9 -1
  75. package/lib/host/testing/standInHost.d.ts.map +1 -1
  76. package/lib/host/testing/standInHost.js +19 -1
  77. package/lib/host/testing/standInHost.js.map +1 -1
  78. package/lib/host/ui/useHostConnection.d.ts +13 -5
  79. package/lib/host/ui/useHostConnection.d.ts.map +1 -1
  80. package/lib/host/ui/useHostConnection.js +4 -3
  81. package/lib/host/ui/useHostConnection.js.map +1 -1
  82. package/lib/host-testing.d.ts +2 -2
  83. package/lib/host-testing.d.ts.map +1 -1
  84. package/lib/host-testing.js +2 -2
  85. package/lib/host-testing.js.map +1 -1
  86. package/lib/i18n/core/chromeCatalog.d.ts +1 -1
  87. package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
  88. package/lib/ir/core/handPicking.d.ts +58 -0
  89. package/lib/ir/core/handPicking.d.ts.map +1 -0
  90. package/lib/ir/core/handPicking.js +130 -0
  91. package/lib/ir/core/handPicking.js.map +1 -0
  92. package/lib/ir/core/index.d.ts +3 -0
  93. package/lib/ir/core/index.d.ts.map +1 -1
  94. package/lib/ir/core/index.js +3 -0
  95. package/lib/ir/core/index.js.map +1 -1
  96. package/lib/ir/core/irBandState.d.ts +57 -0
  97. package/lib/ir/core/irBandState.d.ts.map +1 -0
  98. package/lib/ir/core/irBandState.js +119 -0
  99. package/lib/ir/core/irBandState.js.map +1 -0
  100. package/lib/ir/core/irCommands.d.ts +11 -0
  101. package/lib/ir/core/irCommands.d.ts.map +1 -1
  102. package/lib/ir/core/irCommands.js +6 -0
  103. package/lib/ir/core/irCommands.js.map +1 -1
  104. package/lib/ir/core/irPeaks.d.ts +28 -0
  105. package/lib/ir/core/irPeaks.d.ts.map +1 -0
  106. package/lib/ir/core/irPeaks.js +66 -0
  107. package/lib/ir/core/irPeaks.js.map +1 -0
  108. package/lib/ir/core/irReducer.d.ts +8 -0
  109. package/lib/ir/core/irReducer.d.ts.map +1 -1
  110. package/lib/ir/core/irReducer.js +15 -32
  111. package/lib/ir/core/irReducer.js.map +1 -1
  112. package/lib/ir/core/irSpectrum.d.ts +15 -0
  113. package/lib/ir/core/irSpectrum.d.ts.map +1 -1
  114. package/lib/ir/core/irSpectrum.js.map +1 -1
  115. package/lib/ir/core/irState.d.ts +9 -6
  116. package/lib/ir/core/irState.d.ts.map +1 -1
  117. package/lib/ir/core/irState.js +10 -6
  118. package/lib/ir/core/irState.js.map +1 -1
  119. package/lib/ir/core/pickBands.d.ts +14 -0
  120. package/lib/ir/core/pickBands.d.ts.map +1 -1
  121. package/lib/ir/core/pickBands.js +39 -33
  122. package/lib/ir/core/pickBands.js.map +1 -1
  123. package/lib/ir/core/ramanBands.d.ts +9 -1
  124. package/lib/ir/core/ramanBands.d.ts.map +1 -1
  125. package/lib/ir/core/ramanBands.js +2 -2
  126. package/lib/ir/core/ramanBands.js.map +1 -1
  127. package/lib/ir/core/spectrumBands.d.ts +46 -0
  128. package/lib/ir/core/spectrumBands.d.ts.map +1 -0
  129. package/lib/ir/core/spectrumBands.js +98 -0
  130. package/lib/ir/core/spectrumBands.js.map +1 -0
  131. package/lib/ir/ui/BandRow.d.ts +5 -0
  132. package/lib/ir/ui/BandRow.d.ts.map +1 -1
  133. package/lib/ir/ui/BandRow.js +4 -3
  134. package/lib/ir/ui/BandRow.js.map +1 -1
  135. package/lib/ir/ui/BandsPanel.d.ts +5 -0
  136. package/lib/ir/ui/BandsPanel.d.ts.map +1 -1
  137. package/lib/ir/ui/BandsPanel.js +36 -16
  138. package/lib/ir/ui/BandsPanel.js.map +1 -1
  139. package/lib/ir/ui/BandsToolbar.d.ts +9 -0
  140. package/lib/ir/ui/BandsToolbar.d.ts.map +1 -0
  141. package/lib/ir/ui/BandsToolbar.js +61 -0
  142. package/lib/ir/ui/BandsToolbar.js.map +1 -0
  143. package/lib/ir/ui/IrCanvas.d.ts +2 -1
  144. package/lib/ir/ui/IrCanvas.d.ts.map +1 -1
  145. package/lib/ir/ui/IrCanvas.js +19 -5
  146. package/lib/ir/ui/IrCanvas.js.map +1 -1
  147. package/lib/ir/ui/IrChart.d.ts.map +1 -1
  148. package/lib/ir/ui/IrChart.js +8 -1
  149. package/lib/ir/ui/IrChart.js.map +1 -1
  150. package/lib/ir/ui/IrDocumentationDialog.js +1 -1
  151. package/lib/ir/ui/IrDocumentationDialog.js.map +1 -1
  152. package/lib/ir/ui/IrEditor.d.ts +4 -2
  153. package/lib/ir/ui/IrEditor.d.ts.map +1 -1
  154. package/lib/ir/ui/IrEditor.js.map +1 -1
  155. package/lib/ir/ui/IrShell.d.ts.map +1 -1
  156. package/lib/ir/ui/IrShell.js +6 -0
  157. package/lib/ir/ui/IrShell.js.map +1 -1
  158. package/lib/ir/ui/IrStatusBar.d.ts.map +1 -1
  159. package/lib/ir/ui/IrStatusBar.js +1 -1
  160. package/lib/ir/ui/IrStatusBar.js.map +1 -1
  161. package/lib/ir/ui/IrToolbar.d.ts +4 -3
  162. package/lib/ir/ui/IrToolbar.d.ts.map +1 -1
  163. package/lib/ir/ui/IrToolbar.js +5 -4
  164. package/lib/ir/ui/IrToolbar.js.map +1 -1
  165. package/lib/ir/ui/VibrationalEditor.d.ts +2 -1
  166. package/lib/ir/ui/VibrationalEditor.d.ts.map +1 -1
  167. package/lib/ir/ui/VibrationalEditor.js.map +1 -1
  168. package/lib/ir/ui/irActions.d.ts +5 -0
  169. package/lib/ir/ui/irActions.d.ts.map +1 -1
  170. package/lib/ir/ui/irActions.js +6 -0
  171. package/lib/ir/ui/irActions.js.map +1 -1
  172. package/lib/ir/ui/irChartProps.d.ts +4 -1
  173. package/lib/ir/ui/irChartProps.d.ts.map +1 -1
  174. package/lib/ir/ui/useIrEditor.d.ts +5 -11
  175. package/lib/ir/ui/useIrEditor.d.ts.map +1 -1
  176. package/lib/ir/ui/useIrEditor.js +17 -18
  177. package/lib/ir/ui/useIrEditor.js.map +1 -1
  178. package/lib/locales/de.json +63 -0
  179. package/lib/locales/en.json +63 -0
  180. package/lib/locales/es.json +63 -0
  181. package/lib/locales/fr.json +63 -0
  182. package/lib/locales/it.json +63 -0
  183. package/lib/mass/core/analyseSpectrum.d.ts +85 -0
  184. package/lib/mass/core/analyseSpectrum.d.ts.map +1 -0
  185. package/lib/mass/core/analyseSpectrum.js +101 -0
  186. package/lib/mass/core/analyseSpectrum.js.map +1 -0
  187. package/lib/mass/core/ascendingTrace.d.ts +24 -0
  188. package/lib/mass/core/ascendingTrace.d.ts.map +1 -0
  189. package/lib/mass/core/ascendingTrace.js +57 -0
  190. package/lib/mass/core/ascendingTrace.js.map +1 -0
  191. package/lib/mass/core/centroidPeaks.d.ts +77 -0
  192. package/lib/mass/core/centroidPeaks.d.ts.map +1 -0
  193. package/lib/mass/core/centroidPeaks.js +62 -0
  194. package/lib/mass/core/centroidPeaks.js.map +1 -0
  195. package/lib/mass/core/detectMassFormat.d.ts +24 -0
  196. package/lib/mass/core/detectMassFormat.d.ts.map +1 -0
  197. package/lib/mass/core/detectMassFormat.js +105 -0
  198. package/lib/mass/core/detectMassFormat.js.map +1 -0
  199. package/lib/mass/core/downloadSpectra.d.ts +24 -0
  200. package/lib/mass/core/downloadSpectra.d.ts.map +1 -0
  201. package/lib/mass/core/downloadSpectra.js +35 -0
  202. package/lib/mass/core/downloadSpectra.js.map +1 -0
  203. package/lib/mass/core/fromJcamp.d.ts +46 -0
  204. package/lib/mass/core/fromJcamp.d.ts.map +1 -0
  205. package/lib/mass/core/fromJcamp.js +123 -0
  206. package/lib/mass/core/fromJcamp.js.map +1 -0
  207. package/lib/mass/core/fromText.d.ts +30 -0
  208. package/lib/mass/core/fromText.d.ts.map +1 -0
  209. package/lib/mass/core/fromText.js +39 -0
  210. package/lib/mass/core/fromText.js.map +1 -0
  211. package/lib/mass/core/index.d.ts +70 -0
  212. package/lib/mass/core/index.d.ts.map +1 -0
  213. package/lib/mass/core/index.js +42 -0
  214. package/lib/mass/core/index.js.map +1 -0
  215. package/lib/mass/core/jcampTechnique.d.ts +38 -0
  216. package/lib/mass/core/jcampTechnique.d.ts.map +1 -0
  217. package/lib/mass/core/jcampTechnique.js +70 -0
  218. package/lib/mass/core/jcampTechnique.js.map +1 -0
  219. package/lib/mass/core/labelStackBox.d.ts +49 -0
  220. package/lib/mass/core/labelStackBox.d.ts.map +1 -0
  221. package/lib/mass/core/labelStackBox.js +44 -0
  222. package/lib/mass/core/labelStackBox.js.map +1 -0
  223. package/lib/mass/core/labelledPeaks.d.ts +79 -0
  224. package/lib/mass/core/labelledPeaks.d.ts.map +1 -0
  225. package/lib/mass/core/labelledPeaks.js +74 -0
  226. package/lib/mass/core/labelledPeaks.js.map +1 -0
  227. package/lib/mass/core/loadMassSpectra.d.ts +57 -0
  228. package/lib/mass/core/loadMassSpectra.d.ts.map +1 -0
  229. package/lib/mass/core/loadMassSpectra.js +45 -0
  230. package/lib/mass/core/loadMassSpectra.js.map +1 -0
  231. package/lib/mass/core/loadedMassSpectrum.d.ts +42 -0
  232. package/lib/mass/core/loadedMassSpectrum.d.ts.map +1 -0
  233. package/lib/mass/core/loadedMassSpectrum.js +15 -0
  234. package/lib/mass/core/loadedMassSpectrum.js.map +1 -0
  235. package/lib/mass/core/massCommands.d.ts +170 -0
  236. package/lib/mass/core/massCommands.d.ts.map +1 -0
  237. package/lib/mass/core/massCommands.js +95 -0
  238. package/lib/mass/core/massCommands.js.map +1 -0
  239. package/lib/mass/core/massDomain.d.ts +121 -0
  240. package/lib/mass/core/massDomain.d.ts.map +1 -0
  241. package/lib/mass/core/massDomain.js +179 -0
  242. package/lib/mass/core/massDomain.js.map +1 -0
  243. package/lib/mass/core/massEditorApi.d.ts +65 -0
  244. package/lib/mass/core/massEditorApi.d.ts.map +1 -0
  245. package/lib/mass/core/massEditorApi.js +10 -0
  246. package/lib/mass/core/massEditorApi.js.map +1 -0
  247. package/lib/mass/core/massFormat.d.ts +78 -0
  248. package/lib/mass/core/massFormat.d.ts.map +1 -0
  249. package/lib/mass/core/massFormat.js +168 -0
  250. package/lib/mass/core/massFormat.js.map +1 -0
  251. package/lib/mass/core/massMeta.d.ts +85 -0
  252. package/lib/mass/core/massMeta.d.ts.map +1 -0
  253. package/lib/mass/core/massMeta.js +182 -0
  254. package/lib/mass/core/massMeta.js.map +1 -0
  255. package/lib/mass/core/massReducer.d.ts +82 -0
  256. package/lib/mass/core/massReducer.d.ts.map +1 -0
  257. package/lib/mass/core/massReducer.js +163 -0
  258. package/lib/mass/core/massReducer.js.map +1 -0
  259. package/lib/mass/core/massResolution.d.ts +92 -0
  260. package/lib/mass/core/massResolution.d.ts.map +1 -0
  261. package/lib/mass/core/massResolution.js +126 -0
  262. package/lib/mass/core/massResolution.js.map +1 -0
  263. package/lib/mass/core/massSidePanels.d.ts +28 -0
  264. package/lib/mass/core/massSidePanels.d.ts.map +1 -0
  265. package/lib/mass/core/massSidePanels.js +12 -0
  266. package/lib/mass/core/massSidePanels.js.map +1 -0
  267. package/lib/mass/core/massSpectrum.d.ts +206 -0
  268. package/lib/mass/core/massSpectrum.d.ts.map +1 -0
  269. package/lib/mass/core/massSpectrum.js +41 -0
  270. package/lib/mass/core/massSpectrum.js.map +1 -0
  271. package/lib/mass/core/massState.d.ts +145 -0
  272. package/lib/mass/core/massState.d.ts.map +1 -0
  273. package/lib/mass/core/massState.js +102 -0
  274. package/lib/mass/core/massState.js.map +1 -0
  275. package/lib/mass/core/massStateEdits.d.ts +51 -0
  276. package/lib/mass/core/massStateEdits.d.ts.map +1 -0
  277. package/lib/mass/core/massStateEdits.js +90 -0
  278. package/lib/mass/core/massStateEdits.js.map +1 -0
  279. package/lib/mass/core/massSummary.d.ts +77 -0
  280. package/lib/mass/core/massSummary.d.ts.map +1 -0
  281. package/lib/mass/core/massSummary.js +174 -0
  282. package/lib/mass/core/massSummary.js.map +1 -0
  283. package/lib/mass/core/mzDecimalsSetting.d.ts +36 -0
  284. package/lib/mass/core/mzDecimalsSetting.d.ts.map +1 -0
  285. package/lib/mass/core/mzDecimalsSetting.js +42 -0
  286. package/lib/mass/core/mzDecimalsSetting.js.map +1 -0
  287. package/lib/mass/core/nearestPeak.d.ts +75 -0
  288. package/lib/mass/core/nearestPeak.d.ts.map +1 -0
  289. package/lib/mass/core/nearestPeak.js +99 -0
  290. package/lib/mass/core/nearestPeak.js.map +1 -0
  291. package/lib/mass/core/peakLabelLines.d.ts +77 -0
  292. package/lib/mass/core/peakLabelLines.d.ts.map +1 -0
  293. package/lib/mass/core/peakLabelLines.js +54 -0
  294. package/lib/mass/core/peakLabelLines.js.map +1 -0
  295. package/lib/mass/core/peakLabelPlan.d.ts +109 -0
  296. package/lib/mass/core/peakLabelPlan.d.ts.map +1 -0
  297. package/lib/mass/core/peakLabelPlan.js +143 -0
  298. package/lib/mass/core/peakLabelPlan.js.map +1 -0
  299. package/lib/mass/core/peakTable.d.ts +54 -0
  300. package/lib/mass/core/peakTable.d.ts.map +1 -0
  301. package/lib/mass/core/peakTable.js +53 -0
  302. package/lib/mass/core/peakTable.js.map +1 -0
  303. package/lib/mass/core/resolutionOf.d.ts +60 -0
  304. package/lib/mass/core/resolutionOf.d.ts.map +1 -0
  305. package/lib/mass/core/resolutionOf.js +84 -0
  306. package/lib/mass/core/resolutionOf.js.map +1 -0
  307. package/lib/mass/core/scanFilter.d.ts +25 -0
  308. package/lib/mass/core/scanFilter.d.ts.map +1 -0
  309. package/lib/mass/core/scanFilter.js +107 -0
  310. package/lib/mass/core/scanFilter.js.map +1 -0
  311. package/lib/mass/core/spectrumJcamp.d.ts +47 -0
  312. package/lib/mass/core/spectrumJcamp.d.ts.map +1 -0
  313. package/lib/mass/core/spectrumJcamp.js +167 -0
  314. package/lib/mass/core/spectrumJcamp.js.map +1 -0
  315. package/lib/mass/core/toMassSpectrum.d.ts +67 -0
  316. package/lib/mass/core/toMassSpectrum.d.ts.map +1 -0
  317. package/lib/mass/core/toMassSpectrum.js +78 -0
  318. package/lib/mass/core/toMassSpectrum.js.map +1 -0
  319. package/lib/mass/core/traceIcon.d.ts +82 -0
  320. package/lib/mass/core/traceIcon.d.ts.map +1 -0
  321. package/lib/mass/core/traceIcon.js +66 -0
  322. package/lib/mass/core/traceIcon.js.map +1 -0
  323. package/lib/mass/core/writtenResolution.d.ts +40 -0
  324. package/lib/mass/core/writtenResolution.d.ts.map +1 -0
  325. package/lib/mass/core/writtenResolution.js +77 -0
  326. package/lib/mass/core/writtenResolution.js.map +1 -0
  327. package/lib/mass/ui/MassAboutDialog.d.ts +16 -0
  328. package/lib/mass/ui/MassAboutDialog.d.ts.map +1 -0
  329. package/lib/mass/ui/MassAboutDialog.js +44 -0
  330. package/lib/mass/ui/MassAboutDialog.js.map +1 -0
  331. package/lib/mass/ui/MassCanvas.d.ts +46 -0
  332. package/lib/mass/ui/MassCanvas.d.ts.map +1 -0
  333. package/lib/mass/ui/MassCanvas.js +84 -0
  334. package/lib/mass/ui/MassCanvas.js.map +1 -0
  335. package/lib/mass/ui/MassChart.d.ts +21 -0
  336. package/lib/mass/ui/MassChart.d.ts.map +1 -0
  337. package/lib/mass/ui/MassChart.js +139 -0
  338. package/lib/mass/ui/MassChart.js.map +1 -0
  339. package/lib/mass/ui/MassCommandProvider.d.ts +15 -0
  340. package/lib/mass/ui/MassCommandProvider.d.ts.map +1 -0
  341. package/lib/mass/ui/MassCommandProvider.js +14 -0
  342. package/lib/mass/ui/MassCommandProvider.js.map +1 -0
  343. package/lib/mass/ui/MassCommandTooltip.d.ts +16 -0
  344. package/lib/mass/ui/MassCommandTooltip.d.ts.map +1 -0
  345. package/lib/mass/ui/MassCommandTooltip.js +22 -0
  346. package/lib/mass/ui/MassCommandTooltip.js.map +1 -0
  347. package/lib/mass/ui/MassDocumentationDialog.d.ts +18 -0
  348. package/lib/mass/ui/MassDocumentationDialog.d.ts.map +1 -0
  349. package/lib/mass/ui/MassDocumentationDialog.js +70 -0
  350. package/lib/mass/ui/MassDocumentationDialog.js.map +1 -0
  351. package/lib/mass/ui/MassEditor.d.ts +78 -0
  352. package/lib/mass/ui/MassEditor.d.ts.map +1 -0
  353. package/lib/mass/ui/MassEditor.js +42 -0
  354. package/lib/mass/ui/MassEditor.js.map +1 -0
  355. package/lib/mass/ui/MassHeader.d.ts +12 -0
  356. package/lib/mass/ui/MassHeader.d.ts.map +1 -0
  357. package/lib/mass/ui/MassHeader.js +20 -0
  358. package/lib/mass/ui/MassHeader.js.map +1 -0
  359. package/lib/mass/ui/MassLogo.d.ts +21 -0
  360. package/lib/mass/ui/MassLogo.d.ts.map +1 -0
  361. package/lib/mass/ui/MassLogo.js +36 -0
  362. package/lib/mass/ui/MassLogo.js.map +1 -0
  363. package/lib/mass/ui/MassPointerTracker.d.ts +44 -0
  364. package/lib/mass/ui/MassPointerTracker.d.ts.map +1 -0
  365. package/lib/mass/ui/MassPointerTracker.js +29 -0
  366. package/lib/mass/ui/MassPointerTracker.js.map +1 -0
  367. package/lib/mass/ui/MassShell.d.ts +29 -0
  368. package/lib/mass/ui/MassShell.d.ts.map +1 -0
  369. package/lib/mass/ui/MassShell.js +133 -0
  370. package/lib/mass/ui/MassShell.js.map +1 -0
  371. package/lib/mass/ui/MassSidePanel.d.ts +32 -0
  372. package/lib/mass/ui/MassSidePanel.d.ts.map +1 -0
  373. package/lib/mass/ui/MassSidePanel.js +44 -0
  374. package/lib/mass/ui/MassSidePanel.js.map +1 -0
  375. package/lib/mass/ui/MassStateProvider.d.ts +19 -0
  376. package/lib/mass/ui/MassStateProvider.d.ts.map +1 -0
  377. package/lib/mass/ui/MassStateProvider.js +16 -0
  378. package/lib/mass/ui/MassStateProvider.js.map +1 -0
  379. package/lib/mass/ui/MassStatusBar.d.ts +15 -0
  380. package/lib/mass/ui/MassStatusBar.d.ts.map +1 -0
  381. package/lib/mass/ui/MassStatusBar.js +50 -0
  382. package/lib/mass/ui/MassStatusBar.js.map +1 -0
  383. package/lib/mass/ui/MassToolbar.d.ts +24 -0
  384. package/lib/mass/ui/MassToolbar.d.ts.map +1 -0
  385. package/lib/mass/ui/MassToolbar.js +36 -0
  386. package/lib/mass/ui/MassToolbar.js.map +1 -0
  387. package/lib/mass/ui/MetadataPanel.d.ts +35 -0
  388. package/lib/mass/ui/MetadataPanel.d.ts.map +1 -0
  389. package/lib/mass/ui/MetadataPanel.js +100 -0
  390. package/lib/mass/ui/MetadataPanel.js.map +1 -0
  391. package/lib/mass/ui/MzDecimalsMenu.d.ts +28 -0
  392. package/lib/mass/ui/MzDecimalsMenu.d.ts.map +1 -0
  393. package/lib/mass/ui/MzDecimalsMenu.js +40 -0
  394. package/lib/mass/ui/MzDecimalsMenu.js.map +1 -0
  395. package/lib/mass/ui/PeakLabels.d.ts +93 -0
  396. package/lib/mass/ui/PeakLabels.d.ts.map +1 -0
  397. package/lib/mass/ui/PeakLabels.js +91 -0
  398. package/lib/mass/ui/PeakLabels.js.map +1 -0
  399. package/lib/mass/ui/PeakTable.d.ts +34 -0
  400. package/lib/mass/ui/PeakTable.d.ts.map +1 -0
  401. package/lib/mass/ui/PeakTable.js +49 -0
  402. package/lib/mass/ui/PeakTable.js.map +1 -0
  403. package/lib/mass/ui/PeaksPanel.d.ts +31 -0
  404. package/lib/mass/ui/PeaksPanel.d.ts.map +1 -0
  405. package/lib/mass/ui/PeaksPanel.js +53 -0
  406. package/lib/mass/ui/PeaksPanel.js.map +1 -0
  407. package/lib/mass/ui/SpectraPanel.d.ts +17 -0
  408. package/lib/mass/ui/SpectraPanel.d.ts.map +1 -0
  409. package/lib/mass/ui/SpectraPanel.js +76 -0
  410. package/lib/mass/ui/SpectraPanel.js.map +1 -0
  411. package/lib/mass/ui/SpectrumRow.d.ts +26 -0
  412. package/lib/mass/ui/SpectrumRow.d.ts.map +1 -0
  413. package/lib/mass/ui/SpectrumRow.js +141 -0
  414. package/lib/mass/ui/SpectrumRow.js.map +1 -0
  415. package/lib/mass/ui/SpectrumTrace.d.ts +46 -0
  416. package/lib/mass/ui/SpectrumTrace.d.ts.map +1 -0
  417. package/lib/mass/ui/SpectrumTrace.js +68 -0
  418. package/lib/mass/ui/SpectrumTrace.js.map +1 -0
  419. package/lib/mass/ui/index.d.ts +69 -0
  420. package/lib/mass/ui/index.d.ts.map +1 -0
  421. package/lib/mass/ui/index.js +42 -0
  422. package/lib/mass/ui/index.js.map +1 -0
  423. package/lib/mass/ui/massActions.d.ts +52 -0
  424. package/lib/mass/ui/massActions.d.ts.map +1 -0
  425. package/lib/mass/ui/massActions.js +62 -0
  426. package/lib/mass/ui/massActions.js.map +1 -0
  427. package/lib/mass/ui/massChartProps.d.ts +128 -0
  428. package/lib/mass/ui/massChartProps.d.ts.map +1 -0
  429. package/lib/mass/ui/massChartProps.js +14 -0
  430. package/lib/mass/ui/massChartProps.js.map +1 -0
  431. package/lib/mass/ui/massCommandContext.d.ts +36 -0
  432. package/lib/mass/ui/massCommandContext.d.ts.map +1 -0
  433. package/lib/mass/ui/massCommandContext.js +45 -0
  434. package/lib/mass/ui/massCommandContext.js.map +1 -0
  435. package/lib/mass/ui/massHostPanels.d.ts +48 -0
  436. package/lib/mass/ui/massHostPanels.d.ts.map +1 -0
  437. package/lib/mass/ui/massHostPanels.js +41 -0
  438. package/lib/mass/ui/massHostPanels.js.map +1 -0
  439. package/lib/mass/ui/massStateContext.d.ts +26 -0
  440. package/lib/mass/ui/massStateContext.d.ts.map +1 -0
  441. package/lib/mass/ui/massStateContext.js +37 -0
  442. package/lib/mass/ui/massStateContext.js.map +1 -0
  443. package/lib/mass/ui/useIntensityZoom.d.ts +20 -0
  444. package/lib/mass/ui/useIntensityZoom.d.ts.map +1 -0
  445. package/lib/mass/ui/useIntensityZoom.js +42 -0
  446. package/lib/mass/ui/useIntensityZoom.js.map +1 -0
  447. package/lib/mass/ui/useMassEditor.d.ts +52 -0
  448. package/lib/mass/ui/useMassEditor.d.ts.map +1 -0
  449. package/lib/mass/ui/useMassEditor.js +93 -0
  450. package/lib/mass/ui/useMassEditor.js.map +1 -0
  451. package/lib/mass/ui/useMassFiles.d.ts +22 -0
  452. package/lib/mass/ui/useMassFiles.d.ts.map +1 -0
  453. package/lib/mass/ui/useMassFiles.js +71 -0
  454. package/lib/mass/ui/useMassFiles.js.map +1 -0
  455. package/lib/mass/ui/useMassHandle.d.ts +15 -0
  456. package/lib/mass/ui/useMassHandle.d.ts.map +1 -0
  457. package/lib/mass/ui/useMassHandle.js +35 -0
  458. package/lib/mass/ui/useMassHandle.js.map +1 -0
  459. package/lib/mass/ui/useMassPointer.d.ts +70 -0
  460. package/lib/mass/ui/useMassPointer.d.ts.map +1 -0
  461. package/lib/mass/ui/useMassPointer.js +57 -0
  462. package/lib/mass/ui/useMassPointer.js.map +1 -0
  463. package/lib/mass/ui/useMassShortcuts.d.ts +21 -0
  464. package/lib/mass/ui/useMassShortcuts.d.ts.map +1 -0
  465. package/lib/mass/ui/useMassShortcuts.js +66 -0
  466. package/lib/mass/ui/useMassShortcuts.js.map +1 -0
  467. package/lib/mass/ui/useMassSide.d.ts +27 -0
  468. package/lib/mass/ui/useMassSide.d.ts.map +1 -0
  469. package/lib/mass/ui/useMassSide.js +45 -0
  470. package/lib/mass/ui/useMassSide.js.map +1 -0
  471. package/lib/mass/ui/useMassZoom.d.ts +92 -0
  472. package/lib/mass/ui/useMassZoom.d.ts.map +1 -0
  473. package/lib/mass/ui/useMassZoom.js +65 -0
  474. package/lib/mass/ui/useMassZoom.js.map +1 -0
  475. package/lib/mass.d.ts +16 -0
  476. package/lib/mass.d.ts.map +1 -0
  477. package/lib/mass.js +16 -0
  478. package/lib/mass.js.map +1 -0
  479. package/lib/panel/ui/PanelRail.d.ts.map +1 -1
  480. package/lib/panel/ui/PanelRail.js +6 -1
  481. package/lib/panel/ui/PanelRail.js.map +1 -1
  482. package/lib/slides/ui/slideSanitizeSchema.d.ts +3 -2
  483. package/lib/slides/ui/slideSanitizeSchema.d.ts.map +1 -1
  484. package/lib/slides/ui/slideSanitizeSchema.js +82 -2
  485. package/lib/slides/ui/slideSanitizeSchema.js.map +1 -1
  486. package/package.json +6 -1
  487. package/src/about/core/providers.ts +7 -0
  488. package/src/about/ui/AboutProvidedBy.tsx +49 -0
  489. package/src/chart/ui/useChartPointer.ts +18 -4
  490. package/src/credits/core/credits.ts +53 -0
  491. package/src/download/core/drawingMarkup.ts +18 -1
  492. package/src/download/core/figurePng.ts +21 -8
  493. package/src/download/core/figureSvg.ts +5 -2
  494. package/src/download/core/figureTarget.ts +28 -3
  495. package/src/download/core/svgBounds.ts +21 -0
  496. package/src/download/core/svgToPng.ts +3 -4
  497. package/src/format/core/relativeTime.ts +29 -7
  498. package/src/host/core/connectHost.ts +77 -120
  499. package/src/host/core/hostOutputs.ts +197 -0
  500. package/src/host/core/index.ts +13 -7
  501. package/src/host/core/irKinds.ts +92 -0
  502. package/src/host/core/kinds.ts +16 -6
  503. package/src/host/core/protocol.ts +50 -8
  504. package/src/host/core/selectInputs.ts +145 -0
  505. package/src/host/testing/sciPeaks.ts +140 -0
  506. package/src/host/testing/standInHost.ts +30 -5
  507. package/src/host/ui/useHostConnection.ts +17 -8
  508. package/src/host-testing.ts +4 -0
  509. package/src/ir/core/handPicking.ts +154 -0
  510. package/src/ir/core/index.ts +14 -0
  511. package/src/ir/core/irBandState.ts +155 -0
  512. package/src/ir/core/irCommands.ts +7 -0
  513. package/src/ir/core/irPeaks.ts +79 -0
  514. package/src/ir/core/irReducer.ts +27 -34
  515. package/src/ir/core/irSpectrum.ts +16 -0
  516. package/src/ir/core/irState.ts +15 -8
  517. package/src/ir/core/pickBands.ts +46 -39
  518. package/src/ir/core/ramanBands.ts +2 -2
  519. package/src/ir/core/spectrumBands.ts +113 -0
  520. package/src/ir/ui/BandRow.tsx +20 -2
  521. package/src/ir/ui/BandsPanel.tsx +46 -88
  522. package/src/ir/ui/BandsToolbar.tsx +152 -0
  523. package/src/ir/ui/IrCanvas.tsx +22 -11
  524. package/src/ir/ui/IrChart.tsx +10 -1
  525. package/src/ir/ui/IrDocumentationDialog.tsx +7 -0
  526. package/src/ir/ui/IrEditor.tsx +4 -2
  527. package/src/ir/ui/IrShell.tsx +5 -0
  528. package/src/ir/ui/IrStatusBar.tsx +4 -1
  529. package/src/ir/ui/IrToolbar.tsx +14 -5
  530. package/src/ir/ui/VibrationalEditor.tsx +2 -1
  531. package/src/ir/ui/irActions.ts +11 -0
  532. package/src/ir/ui/irChartProps.ts +4 -1
  533. package/src/ir/ui/useIrEditor.ts +21 -21
  534. package/src/locales/de.json +63 -0
  535. package/src/locales/en.json +63 -0
  536. package/src/locales/es.json +63 -0
  537. package/src/locales/fr.json +63 -0
  538. package/src/locales/it.json +63 -0
  539. package/src/mass/core/analyseSpectrum.ts +191 -0
  540. package/src/mass/core/ascendingTrace.ts +62 -0
  541. package/src/mass/core/centroidPeaks.ts +114 -0
  542. package/src/mass/core/detectMassFormat.ts +113 -0
  543. package/src/mass/core/downloadSpectra.ts +52 -0
  544. package/src/mass/core/fromJcamp.ts +151 -0
  545. package/src/mass/core/fromText.ts +58 -0
  546. package/src/mass/core/index.ts +194 -0
  547. package/src/mass/core/jcampTechnique.ts +87 -0
  548. package/src/mass/core/labelStackBox.ts +75 -0
  549. package/src/mass/core/labelledPeaks.ts +135 -0
  550. package/src/mass/core/loadMassSpectra.ts +86 -0
  551. package/src/mass/core/loadedMassSpectrum.ts +43 -0
  552. package/src/mass/core/massCommands.ts +156 -0
  553. package/src/mass/core/massDomain.ts +229 -0
  554. package/src/mass/core/massEditorApi.ts +68 -0
  555. package/src/mass/core/massFormat.ts +187 -0
  556. package/src/mass/core/massMeta.ts +239 -0
  557. package/src/mass/core/massReducer.ts +232 -0
  558. package/src/mass/core/massResolution.ts +169 -0
  559. package/src/mass/core/massSidePanels.ts +27 -0
  560. package/src/mass/core/massSpectrum.ts +220 -0
  561. package/src/mass/core/massState.ts +206 -0
  562. package/src/mass/core/massStateEdits.ts +104 -0
  563. package/src/mass/core/massSummary.ts +213 -0
  564. package/src/mass/core/mzDecimalsSetting.ts +52 -0
  565. package/src/mass/core/nearestPeak.ts +130 -0
  566. package/src/mass/core/peakLabelLines.ts +112 -0
  567. package/src/mass/core/peakLabelPlan.ts +246 -0
  568. package/src/mass/core/peakTable.ts +82 -0
  569. package/src/mass/core/resolutionOf.ts +100 -0
  570. package/src/mass/core/scanFilter.ts +119 -0
  571. package/src/mass/core/spectrumJcamp.ts +186 -0
  572. package/src/mass/core/toMassSpectrum.ts +126 -0
  573. package/src/mass/core/traceIcon.ts +105 -0
  574. package/src/mass/core/writtenResolution.ts +81 -0
  575. package/src/mass/ui/MassAboutDialog.tsx +89 -0
  576. package/src/mass/ui/MassCanvas.tsx +170 -0
  577. package/src/mass/ui/MassChart.tsx +266 -0
  578. package/src/mass/ui/MassCommandProvider.tsx +34 -0
  579. package/src/mass/ui/MassCommandTooltip.tsx +36 -0
  580. package/src/mass/ui/MassDocumentationDialog.tsx +136 -0
  581. package/src/mass/ui/MassEditor.tsx +130 -0
  582. package/src/mass/ui/MassHeader.tsx +38 -0
  583. package/src/mass/ui/MassLogo.tsx +84 -0
  584. package/src/mass/ui/MassPointerTracker.tsx +72 -0
  585. package/src/mass/ui/MassShell.tsx +237 -0
  586. package/src/mass/ui/MassSidePanel.tsx +107 -0
  587. package/src/mass/ui/MassStateProvider.tsx +32 -0
  588. package/src/mass/ui/MassStatusBar.tsx +108 -0
  589. package/src/mass/ui/MassToolbar.tsx +120 -0
  590. package/src/mass/ui/MetadataPanel.tsx +201 -0
  591. package/src/mass/ui/MzDecimalsMenu.tsx +86 -0
  592. package/src/mass/ui/PeakLabels.tsx +242 -0
  593. package/src/mass/ui/PeakTable.tsx +199 -0
  594. package/src/mass/ui/PeaksPanel.tsx +182 -0
  595. package/src/mass/ui/SpectraPanel.tsx +153 -0
  596. package/src/mass/ui/SpectrumRow.tsx +246 -0
  597. package/src/mass/ui/SpectrumTrace.tsx +119 -0
  598. package/src/mass/ui/index.ts +69 -0
  599. package/src/mass/ui/massActions.ts +109 -0
  600. package/src/mass/ui/massChartProps.ts +130 -0
  601. package/src/mass/ui/massCommandContext.tsx +65 -0
  602. package/src/mass/ui/massHostPanels.ts +71 -0
  603. package/src/mass/ui/massStateContext.ts +48 -0
  604. package/src/mass/ui/useIntensityZoom.ts +55 -0
  605. package/src/mass/ui/useMassEditor.ts +156 -0
  606. package/src/mass/ui/useMassFiles.ts +91 -0
  607. package/src/mass/ui/useMassHandle.ts +58 -0
  608. package/src/mass/ui/useMassPointer.ts +120 -0
  609. package/src/mass/ui/useMassShortcuts.ts +85 -0
  610. package/src/mass/ui/useMassSide.ts +63 -0
  611. package/src/mass/ui/useMassZoom.ts +157 -0
  612. package/src/mass.ts +16 -0
  613. package/src/panel/ui/PanelRail.tsx +5 -1
  614. package/src/slides/ui/slideSanitizeSchema.ts +86 -2
  615. package/styles/chrome.css +7 -0
  616. package/styles/slides.css +47 -0
@@ -0,0 +1,239 @@
1
+ /**
2
+ * What the file says about how the spectrum was acquired, made displayable.
3
+ *
4
+ * A JCAMP written by a Thermo instrument carries the answer to every question a
5
+ * chemist asks of a spectrum — which analyser, which polarity, which collision
6
+ * energy — but carries it in whichever of two record bags the exporting
7
+ * software felt like using, and leaves half of them blank. A JCAMP of the older
8
+ * MS dialect states the same facts under standard records of its own,
9
+ * `##.SPECTROMETER TYPE=` and `##.IONIZATION MODE=`. So each field names the
10
+ * records it may live in, in the order they are worth trying, and anything
11
+ * still blank falls back to the instrument's own scan description.
12
+ *
13
+ * A field that is absent or empty is left out entirely rather than shown as a
14
+ * dash, which is what keeps the table short enough to read at a glance: every
15
+ * line in it is a fact the file actually stated.
16
+ */
17
+
18
+ import type { MassMeta, MassMetaField } from './massSpectrum.ts';
19
+ import { parseScanFilter } from './scanFilter.ts';
20
+
21
+ /**
22
+ * The two record bags a JCAMP reader offers.
23
+ *
24
+ * `jcampconverter` splits the records in two — `##ORIGIN=` and the other
25
+ * standard labels into `info`, keyed without their spaces, and the
26
+ * `$`-prefixed user-defined ones into `meta` with the `$` stripped — and a
27
+ * record belongs to one bag or the other, never both.
28
+ */
29
+ export interface MassMetaSource {
30
+ /**
31
+ * The standard records, keyed without their `##` and without spaces.
32
+ * @default undefined
33
+ */
34
+ info?: Record<string, unknown>;
35
+ /**
36
+ * The `$`-prefixed user-defined records, keyed without their `##$`.
37
+ * @default undefined
38
+ */
39
+ meta?: Record<string, unknown>;
40
+ /**
41
+ * The title, when the reader kept it apart from the records.
42
+ * @default undefined
43
+ */
44
+ title?: string;
45
+ }
46
+
47
+ /** One record a row of the table can be read from, and written back to. */
48
+ export interface MassMetaRecord {
49
+ /** The record's label as the reader keys it, without its `##` or its `$`. */
50
+ key: string;
51
+ /** Whether it is a standard record rather than a `$`-prefixed one. */
52
+ info: boolean;
53
+ }
54
+
55
+ /**
56
+ * Read the acquisition metadata a file carries.
57
+ *
58
+ * Returns `null` rather than an empty table when the file said nothing at all,
59
+ * so the panel can leave the section out instead of drawing a heading over
60
+ * nothing — the normal outcome for a pasted peak list.
61
+ * @param source - The record bags the reader recovered.
62
+ * @returns The metadata, or `null` when the file carries none.
63
+ */
64
+ export function buildMassMeta(source: MassMetaSource): MassMeta | null {
65
+ const bags: Bags = { info: source.info ?? {}, meta: source.meta ?? {} };
66
+ const conditions = recordText(bags.meta.CONDITIONS);
67
+ const derived = parseScanFilter(conditions);
68
+
69
+ const fields: MassMetaField[] = [];
70
+ for (const field of FIELDS) {
71
+ const value =
72
+ firstValue(bags, field.records) || (derived[field.label] ?? '');
73
+ if (value) fields.push({ label: field.label, value });
74
+ }
75
+
76
+ const title = recordText(source.title) || recordText(bags.info.TITLE) || null;
77
+ const molecularFormula = firstValue(bags, MOLECULAR_FORMULA_RECORDS) || null;
78
+ if (fields.length === 0 && !title && !conditions && !molecularFormula) {
79
+ return null;
80
+ }
81
+ return { title, molecularFormula, fields, conditions: conditions || null };
82
+ }
83
+
84
+ /**
85
+ * The record a row of the table is written back to.
86
+ *
87
+ * The inverse of the table below, and it lives beside it for that reason: a
88
+ * writer holding a second list of record names is a writer whose `MSLEVEL`
89
+ * becomes `MS_LEVEL` the day a spelling is added here, and the round trip then
90
+ * loses the field without anything going wrong loudly. Only the first of each
91
+ * row's records is offered — the others exist to read what other exporters
92
+ * wrote, and writing our own file is not the place to imitate them.
93
+ * @param label - The row's label, as the table displays it.
94
+ * @returns The record, or `null` when the label is not one of the table's rows.
95
+ */
96
+ export function metaRecord(label: string): MassMetaRecord | null {
97
+ for (const field of FIELDS) {
98
+ if (field.label === label) return field.records[0] ?? null;
99
+ }
100
+ return null;
101
+ }
102
+
103
+ /** Both bags, as the reader handed them over. */
104
+ interface Bags {
105
+ /** The standard records. */
106
+ info: Record<string, unknown>;
107
+ /** The `$`-prefixed ones. */
108
+ meta: Record<string, unknown>;
109
+ }
110
+
111
+ /** One row of the table: how it is named, and where its value may live. */
112
+ interface FieldSpec {
113
+ /** The label, which is also the key `parseScanFilter` derives it under. */
114
+ label: string;
115
+ /** The records to try, in the order they are worth trying. */
116
+ records: readonly MassMetaRecord[];
117
+ }
118
+
119
+ /**
120
+ * A standard record.
121
+ * @param key - Its label without spaces.
122
+ * @returns The record.
123
+ */
124
+ function standard(key: string): MassMetaRecord {
125
+ return { key, info: true };
126
+ }
127
+
128
+ /**
129
+ * A `$`-prefixed record.
130
+ * @param key - Its label without the `$`.
131
+ * @returns The record.
132
+ */
133
+ function custom(key: string): MassMetaRecord {
134
+ return { key, info: false };
135
+ }
136
+
137
+ /**
138
+ * Every row the table can show, in the order it shows them.
139
+ *
140
+ * The order runs from what the sample was measured on down to who measured it,
141
+ * because that is the order a chemist reads a method in. The alternatives on
142
+ * each row are the records real exporters were observed to write: `IONISATION`
143
+ * and `IONIZATION` are the same field spelled by two vendors.
144
+ *
145
+ * `EXPERIMENT` is deliberately not a fallback for the collision energy, however
146
+ * tempting the name is: on real Orbitrap exports it holds what kind of run this
147
+ * was — `MS/MS`, `Accurate mass` — while the energy is in `REPORT` or in the
148
+ * instrument's own scan filter.
149
+ */
150
+ const FIELDS: readonly FieldSpec[] = [
151
+ { label: 'Source', records: [standard('ORIGIN')] },
152
+ {
153
+ label: 'Instrument',
154
+ records: [custom('INSTRUMENT'), standard('SPECTROMETER/DATASYSTEM')],
155
+ },
156
+ {
157
+ label: 'Analyser',
158
+ records: [
159
+ custom('ANALYZER'),
160
+ custom('ANALYSER'),
161
+ standard('.SPECTROMETERTYPE'),
162
+ ],
163
+ },
164
+ {
165
+ label: 'Instrument parameters',
166
+ records: [standard('.INSTRUMENTPARAMETERS')],
167
+ },
168
+ {
169
+ label: 'Ionization',
170
+ records: [
171
+ custom('IONISATION'),
172
+ custom('IONIZATION'),
173
+ standard('.IONIZATIONMODE'),
174
+ ],
175
+ },
176
+ { label: 'Inlet', records: [custom('INJECTION'), standard('.INLET')] },
177
+ { label: 'Polarity', records: [custom('MODE'), custom('POLARITY')] },
178
+ { label: 'Experiment', records: [custom('EXPERIMENT')] },
179
+ { label: 'MS level', records: [custom('MSLEVEL')] },
180
+ { label: 'Isolation m/z', records: [custom('ISOLATION')] },
181
+ {
182
+ label: 'Collision energy',
183
+ records: [custom('COLLISIONENERGY'), custom('REPORT')],
184
+ },
185
+ { label: 'Scan range', records: [custom('SCANRANGE')] },
186
+ { label: 'Retention time', records: [custom('RETENTIONTIME')] },
187
+ { label: 'Scans', records: [custom('SCANS')] },
188
+ { label: 'Averaged scans', records: [custom('AVERAGEDSCANS')] },
189
+ { label: 'Raw file', records: [custom('RAWFILE')] },
190
+ {
191
+ label: 'Operator',
192
+ records: [custom('USER'), custom('OWNER'), standard('OWNER')],
193
+ },
194
+ { label: 'Note', records: [custom('NOTE')] },
195
+ ];
196
+
197
+ /**
198
+ * Where the formula the file was measured for may be stated: the standard
199
+ * record first, then the one an accurate-mass tool writes its answer into.
200
+ */
201
+ const MOLECULAR_FORMULA_RECORDS: readonly MassMetaRecord[] = [
202
+ standard('MOLFORM'),
203
+ standard('MOLFORMULA'),
204
+ custom('ACCURATE_MF'),
205
+ ];
206
+
207
+ /**
208
+ * The first record that holds anything.
209
+ * @param bags - The records to look in.
210
+ * @param records - The records to try, in order.
211
+ * @returns The value as the file states it, or `''` when none is populated.
212
+ */
213
+ function firstValue(bags: Bags, records: readonly MassMetaRecord[]): string {
214
+ for (const record of records) {
215
+ const value = recordText((record.info ? bags.info : bags.meta)[record.key]);
216
+ if (value) return value;
217
+ }
218
+ return '';
219
+ }
220
+
221
+ /**
222
+ * A record's value as a trimmed string, whatever dynamic typing made of it.
223
+ *
224
+ * `jcampconverter` reads `##$SCANS=1` as the number `1` and a record written
225
+ * twice as an array of both values, so a row that is only ever shown has to
226
+ * accept all three shapes. A repeated record shows its first occurrence, which
227
+ * is the one the exporter wrote for the acquisition rather than for a later
228
+ * reprocessing of it.
229
+ * @param value - The record, as dynamic typing left it.
230
+ * @returns The value as text, `''` when there is none.
231
+ */
232
+ export function recordText(value: unknown): string {
233
+ if (typeof value === 'string') return value.trim();
234
+ if (typeof value === 'number' || typeof value === 'boolean') {
235
+ return String(value);
236
+ }
237
+ if (Array.isArray(value)) return recordText(value[0]);
238
+ return '';
239
+ }
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Every change the viewer can undergo, as one function over one object.
3
+ *
4
+ * A reducer rather than a graph of signals: a published component must not
5
+ * impose a state library on the page that mounts it, and two viewers on one
6
+ * page must not share a module-level singleton. The state is a plain object, so
7
+ * a host can save it, restore it and compare it.
8
+ *
9
+ * Every case returns the state **itself** when it has nothing to do, so a render
10
+ * memoised on the state is not defeated by an action that changed nothing —
11
+ * selecting the spectrum already selected, closing an error already closed.
12
+ */
13
+
14
+ import type { MassPanelId } from './massSidePanels.ts';
15
+ import type { MassDomain, MassSpectrum } from './massSpectrum.ts';
16
+ import type {
17
+ MassSettings,
18
+ MassState,
19
+ MassTool,
20
+ PartialMassState,
21
+ } from './massState.ts';
22
+ import { isMassWindow, mergeMassSettings } from './massState.ts';
23
+ import {
24
+ arriving,
25
+ mapSpectrum,
26
+ restoreState,
27
+ withError,
28
+ } from './massStateEdits.ts';
29
+
30
+ /**
31
+ * Which of a spectrum's two traces are drawn. Both are named every time,
32
+ * because they are an either/or: drawing one is also the gesture that puts the
33
+ * other away.
34
+ */
35
+ export interface SpectrumVisibility {
36
+ /** Whether the continuous trace is drawn. */
37
+ showProfile: boolean;
38
+ /** Whether the centroid sticks are drawn. */
39
+ showCentroid: boolean;
40
+ }
41
+
42
+ /** Everything that can be asked of the viewer. */
43
+ export type MassAction =
44
+ | { type: 'addSpectra'; spectra: MassSpectrum[] }
45
+ | { type: 'setSpectra'; spectra: MassSpectrum[] }
46
+ | { type: 'removeSpectrum'; id: string }
47
+ | { type: 'renameSpectrum'; id: string; name: string }
48
+ | { type: 'setSpectrumColor'; id: string; color: string }
49
+ | {
50
+ type: 'setSpectrumVisibility';
51
+ id: string;
52
+ visibility: SpectrumVisibility;
53
+ }
54
+ | { type: 'selectSpectrum'; id: string | null }
55
+ | { type: 'setDomain'; domain: MassDomain }
56
+ | { type: 'resetDomain' }
57
+ | { type: 'setTool'; tool: MassTool }
58
+ | { type: 'togglePanel'; panelId: MassPanelId }
59
+ | { type: 'setError'; error: string | null }
60
+ | { type: 'setSettings'; settings: Partial<MassSettings> }
61
+ | { type: 'loadState'; state: PartialMassState }
62
+ | { type: 'clear' };
63
+
64
+ /**
65
+ * Fold one action into the state.
66
+ * @param state - The state in force.
67
+ * @param action - What is being asked.
68
+ * @returns The new state, or the old one when nothing changed.
69
+ */
70
+ export function massReducer(state: MassState, action: MassAction): MassState {
71
+ switch (action.type) {
72
+ case 'addSpectra': {
73
+ const added = arriving(state, action.spectra);
74
+ if (added.length === 0) return state;
75
+ return {
76
+ ...state,
77
+ data: { spectra: [...state.data.spectra, ...added] },
78
+ view: {
79
+ ...state.view,
80
+ // Whatever arrived is what somebody wants to look at, so it takes the
81
+ // selection — but only when nothing was selected, since a spectrum
82
+ // added for comparison must not steal the panels from the one being
83
+ // read.
84
+ selectedId: state.view.selectedId ?? added[0]?.id ?? null,
85
+ error: null,
86
+ },
87
+ };
88
+ }
89
+
90
+ case 'setSpectra': {
91
+ const spectra = arriving(
92
+ { ...state, data: { spectra: [] } },
93
+ action.spectra,
94
+ );
95
+ return {
96
+ ...state,
97
+ data: { spectra },
98
+ view: {
99
+ ...state.view,
100
+ selectedId: spectra[0]?.id ?? null,
101
+ // Replacing what is drawn is the one change that throws the window
102
+ // away: a window over one spectrum's masses means nothing over
103
+ // another's, and the chart refits when it is handed `null`.
104
+ domain: null,
105
+ error: null,
106
+ },
107
+ };
108
+ }
109
+
110
+ case 'removeSpectrum': {
111
+ const spectra = state.data.spectra.filter(
112
+ (spectrum) => spectrum.id !== action.id,
113
+ );
114
+ if (spectra.length === state.data.spectra.length) return state;
115
+ return {
116
+ ...state,
117
+ data: { spectra },
118
+ view: {
119
+ ...state.view,
120
+ selectedId:
121
+ state.view.selectedId === action.id
122
+ ? (spectra[0]?.id ?? null)
123
+ : state.view.selectedId,
124
+ },
125
+ };
126
+ }
127
+
128
+ case 'renameSpectrum': {
129
+ const name = action.name.trim();
130
+ if (name === '') {
131
+ return withError(state, 'A spectrum needs a name to be called by.');
132
+ }
133
+ return mapSpectrum(state, action.id, (spectrum) =>
134
+ spectrum.name === name ? spectrum : { ...spectrum, name },
135
+ );
136
+ }
137
+
138
+ case 'setSpectrumColor': {
139
+ return mapSpectrum(state, action.id, (spectrum) =>
140
+ spectrum.color === action.color
141
+ ? spectrum
142
+ : { ...spectrum, color: action.color },
143
+ );
144
+ }
145
+
146
+ case 'setSpectrumVisibility': {
147
+ return mapSpectrum(state, action.id, (spectrum) => {
148
+ // A spectrum read from a peak table has no profile to draw, and asking
149
+ // for one must not leave it drawn as nothing at all.
150
+ const showProfile =
151
+ action.visibility.showProfile && spectrum.profile !== null;
152
+ const { showCentroid } = action.visibility;
153
+ return spectrum.showProfile === showProfile &&
154
+ spectrum.showCentroid === showCentroid
155
+ ? spectrum
156
+ : { ...spectrum, showProfile, showCentroid };
157
+ });
158
+ }
159
+
160
+ case 'selectSpectrum': {
161
+ if (state.view.selectedId === action.id) return state;
162
+ return { ...state, view: { ...state.view, selectedId: action.id } };
163
+ }
164
+
165
+ case 'setDomain': {
166
+ if (!isMassWindow(action.domain)) return state;
167
+ return { ...state, view: { ...state.view, domain: action.domain } };
168
+ }
169
+
170
+ case 'resetDomain': {
171
+ if (state.view.domain === null) return state;
172
+ return { ...state, view: { ...state.view, domain: null } };
173
+ }
174
+
175
+ case 'setTool': {
176
+ if (state.view.tool === action.tool) return state;
177
+ return { ...state, view: { ...state.view, tool: action.tool } };
178
+ }
179
+
180
+ case 'togglePanel': {
181
+ const { openPanelIds } = state.view;
182
+ const open = openPanelIds.includes(action.panelId);
183
+ return {
184
+ ...state,
185
+ view: {
186
+ ...state.view,
187
+ openPanelIds: open
188
+ ? openPanelIds.filter((id) => id !== action.panelId)
189
+ : [...openPanelIds, action.panelId],
190
+ },
191
+ };
192
+ }
193
+
194
+ case 'setError': {
195
+ if (state.view.error === action.error) return state;
196
+ return { ...state, view: { ...state.view, error: action.error } };
197
+ }
198
+
199
+ case 'setSettings': {
200
+ const settings = mergeMassSettings(state.settings, action.settings);
201
+ const { showLabels, labelLimit, showCharges, mzDecimals } =
202
+ state.settings;
203
+ if (
204
+ settings.showLabels === showLabels &&
205
+ settings.labelLimit === labelLimit &&
206
+ settings.showCharges === showCharges &&
207
+ settings.mzDecimals === mzDecimals
208
+ ) {
209
+ return state;
210
+ }
211
+ return { ...state, settings };
212
+ }
213
+
214
+ case 'loadState': {
215
+ return restoreState(state, action.state);
216
+ }
217
+
218
+ case 'clear': {
219
+ if (state.data.spectra.length === 0 && state.view.error === null) {
220
+ return state;
221
+ }
222
+ return {
223
+ ...state,
224
+ data: { spectra: [] },
225
+ view: { ...state.view, selectedId: null, domain: null, error: null },
226
+ };
227
+ }
228
+ /* Every action is handled above, and TypeScript is what keeps that true
229
+ when one is added — so there is nothing for a fallback to do. */
230
+ // no default
231
+ }
232
+ }
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Whether a spectrum resolves masses finely enough for their decimals to mean
3
+ * anything.
4
+ *
5
+ * A peak table typed out of a low-resolution instrument report holds whole
6
+ * numbers — `163`, `325`, `487` — and writing them as `163.0000` claims four
7
+ * digits of accuracy nobody measured. A high-resolution measurement is the
8
+ * opposite case: `325.1129` and `325.1503` are different ions, and rounding them
9
+ * together loses the whole point of having measured them. Nothing about a single
10
+ * number says which of the two it is, so the answer is read off the spectrum.
11
+ *
12
+ * Three kinds of evidence are read, and the strongest one present decides —
13
+ * `decideResolution` is where they are weighed:
14
+ *
15
+ * 1. **The peaks themselves.** A profile carries the width of every peak, and
16
+ * the resolving power `m / Δm` at half height is what "high resolution" is
17
+ * defined by. This is a measurement, so it is believed over anything a file
18
+ * says about itself.
19
+ * 2. **What the file says the instrument was.** A Thermo scan filter starting
20
+ * `FTMS` is an Orbitrap, one starting `ITMS` an ion trap, and a JCAMP of the
21
+ * old MS dialect writes `##.INSTRUMENT PARAMETERS= LOW RESOLUTION` outright.
22
+ * 3. **How many decimals the masses were written with**, which is all a bare
23
+ * peak table has to say — `writtenResolution.ts`.
24
+ */
25
+
26
+ import { gaussianWidthToFWHM } from 'ml-peak-shape-generator';
27
+ import { xMedian } from 'ml-spectra-processing';
28
+
29
+ import type { MassMeta } from './massSpectrum.ts';
30
+
31
+ /** How finely a spectrum resolves masses. */
32
+ export type MassResolutionKind = 'high' | 'low' | 'nominal';
33
+
34
+ /** Which evidence the verdict was read from, the strongest first. */
35
+ export type MassResolutionBasis = 'peakWidth' | 'instrument' | 'decimals';
36
+
37
+ /** The verdict on one spectrum, and what it rests on. */
38
+ export interface MassResolution {
39
+ /** Whether the masses are resolved, resolved coarsely, or written whole. */
40
+ kind: MassResolutionKind;
41
+ /**
42
+ * The resolving power `m / Δm` at half height, the median over the tallest
43
+ * peaks — `null` unless it was measured, which needs a profile.
44
+ */
45
+ resolvingPower: number | null;
46
+ /** What the verdict was read from. */
47
+ basis: MassResolutionBasis;
48
+ /** How many decimals an m/z of this spectrum is written with. */
49
+ decimals: number;
50
+ }
51
+
52
+ /** A picked peak with the width the peak picking measured for it. */
53
+ export interface WidthPeak {
54
+ /** Where it sits, in m/z. */
55
+ x: number;
56
+ /** How tall it is. */
57
+ y: number;
58
+ /** Its width between inflection points, in m/z, as `ml-gsd` reports it. */
59
+ width: number;
60
+ }
61
+
62
+ /**
63
+ * The resolving power from which a spectrum counts as high resolution.
64
+ *
65
+ * Ten thousand at half height is the conventional threshold, and it falls in
66
+ * the gap between the two families of instrument rather than inside either:
67
+ * quadrupoles, ion traps and linear time-of-flights work at a few thousand at
68
+ * most, while reflectron time-of-flights, Orbitraps and FT-ICRs start above it.
69
+ */
70
+ export const HIGH_RESOLVING_POWER = 10_000;
71
+
72
+ /** How many of the tallest peaks the resolving power is the median of. */
73
+ export const MEASURED_PEAKS = 20;
74
+
75
+ /** How many decimals an m/z is written with, for each kind of spectrum. */
76
+ export const MZ_DECIMALS: Readonly<Record<MassResolutionKind, number>> = {
77
+ high: 4,
78
+ low: 1,
79
+ nominal: 0,
80
+ };
81
+
82
+ /**
83
+ * The resolving power measured on the peaks of a profile.
84
+ *
85
+ * The median over the tallest peaks rather than over all of them, because a
86
+ * peak a few counts above the noise has a width the noise decided, and rather
87
+ * than the base peak alone, because one peak sitting on an unresolved shoulder
88
+ * would decide the whole spectrum. The width `ml-gsd` reports is the distance
89
+ * between the inflection points, which is converted to the width at half height
90
+ * as a gaussian's is: what a resolving power is quoted against.
91
+ * @param peaks - The peaks the profile was picked into, each with its width.
92
+ * @returns The verdict, `null` when no peak carries a usable width.
93
+ */
94
+ export function measuredResolution(
95
+ peaks: readonly WidthPeak[],
96
+ ): MassResolution | null {
97
+ const usable: WidthPeak[] = [];
98
+ for (const peak of peaks) {
99
+ if (peak.x > 0 && peak.width > 0 && Number.isFinite(peak.width)) {
100
+ usable.push(peak);
101
+ }
102
+ }
103
+ if (usable.length === 0) return null;
104
+
105
+ const tallest = usable
106
+ .toSorted((first, second) => second.y - first.y)
107
+ .slice(0, MEASURED_PEAKS);
108
+ const powers = new Float64Array(tallest.length);
109
+ for (let index = 0; index < tallest.length; index++) {
110
+ const peak = tallest[index] as WidthPeak;
111
+ powers[index] = peak.x / gaussianWidthToFWHM(peak.width);
112
+ }
113
+ const resolvingPower = xMedian(powers);
114
+ const kind = resolvingPower >= HIGH_RESOLVING_POWER ? 'high' : 'low';
115
+ return {
116
+ kind,
117
+ resolvingPower,
118
+ basis: 'peakWidth',
119
+ decimals: MZ_DECIMALS[kind],
120
+ };
121
+ }
122
+
123
+ /**
124
+ * The resolution the file says the instrument worked at, when it says so.
125
+ *
126
+ * Only the rows that name an instrument are read, and a high verdict is looked
127
+ * for first: an `LTQ-Orbitrap` names an ion trap and an Orbitrap, and the
128
+ * spectrum came out of the Orbitrap. A time-of-flight is deliberately left
129
+ * undecided — a reflectron one is high resolution and a linear one is not, and
130
+ * the name is the same.
131
+ * @param meta - What the file said about the acquisition.
132
+ * @returns The verdict, `null` when the file names no instrument it can be
133
+ * read off.
134
+ */
135
+ export function statedResolution(meta: MassMeta | null): MassResolution | null {
136
+ if (meta === null) return null;
137
+ for (const field of meta.fields) {
138
+ if (!INSTRUMENT_FIELDS.has(field.label)) continue;
139
+ const kind = HIGH_INSTRUMENT.test(field.value)
140
+ ? 'high'
141
+ : LOW_INSTRUMENT.test(field.value)
142
+ ? 'low'
143
+ : null;
144
+ if (kind !== null) {
145
+ return {
146
+ kind,
147
+ resolvingPower: null,
148
+ basis: 'instrument',
149
+ decimals: MZ_DECIMALS[kind],
150
+ };
151
+ }
152
+ }
153
+ return null;
154
+ }
155
+
156
+ /** The acquisition rows that name the instrument, and so its resolution. */
157
+ const INSTRUMENT_FIELDS = new Set([
158
+ 'Analyser',
159
+ 'Instrument',
160
+ 'Instrument parameters',
161
+ ]);
162
+
163
+ /** The instruments, and the words, that say high resolution. */
164
+ const HIGH_INSTRUMENT =
165
+ /\bHIGH[\s-]RESOLUTION\b|\bHRMS\b|\bFTMS\b|ORBITRAP|\bFT-?ICR\b|\bEXACTIVE\b|\bEXPLORIS\b/i;
166
+
167
+ /** The instruments, and the words, that say a unit-resolution measurement. */
168
+ const LOW_INSTRUMENT =
169
+ /\bLOW[\s-]RESOLUTION\b|\bITMS\b|\bION[\s-]TRAP\b|\bTRAP\b|QUADRUPOLE/i;
@@ -0,0 +1,27 @@
1
+ import type { ActivityBarItemProps } from 'react-science/ui';
2
+
3
+ /**
4
+ * The panels the side of the viewer can hold, in the order their icons stack.
5
+ *
6
+ * One frozen list read by both the activity bar and the panel stack, so a panel
7
+ * switched off and on again comes back where it was rather than at the end.
8
+ */
9
+ export const massSidePanels = [
10
+ { id: 'spectra', title: 'Spectra', icon: 'timeline-line-chart' },
11
+ { id: 'peaks', title: 'Peaks', icon: 'th-list' },
12
+ { id: 'metadata', title: 'Acquisition', icon: 'properties' },
13
+ ] as const satisfies ReadonlyArray<{
14
+ id: string;
15
+ title: string;
16
+ icon: ActivityBarItemProps['icon'];
17
+ }>;
18
+
19
+ /** Identity of one of the panels the viewer offers of its own. */
20
+ export type MassSidePanelId = (typeof massSidePanels)[number]['id'];
21
+
22
+ /**
23
+ * Identity of any panel the side can hold: one of the viewer's own, or one a
24
+ * host added to them. Still a union with the viewer's own ids, so those keep
25
+ * autocompleting where a plain `string` would swallow them.
26
+ */
27
+ export type MassPanelId = MassSidePanelId | (string & Record<never, never>);