react-cheminfo 0.65.0 → 0.66.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 (237) hide show
  1. package/README.md +11 -6
  2. package/lib/i18n/core/chromeCatalog.d.ts +1 -1
  3. package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
  4. package/lib/ir/core/analysisSpectra.d.ts +23 -6
  5. package/lib/ir/core/analysisSpectra.d.ts.map +1 -1
  6. package/lib/ir/core/analysisSpectra.js.map +1 -1
  7. package/lib/ir/core/bandLabelPlan.d.ts.map +1 -1
  8. package/lib/ir/core/bandLabelPlan.js +11 -6
  9. package/lib/ir/core/bandLabelPlan.js.map +1 -1
  10. package/lib/ir/core/index.d.ts +13 -9
  11. package/lib/ir/core/index.d.ts.map +1 -1
  12. package/lib/ir/core/index.js +9 -6
  13. package/lib/ir/core/index.js.map +1 -1
  14. package/lib/ir/core/irBand.d.ts +45 -14
  15. package/lib/ir/core/irBand.d.ts.map +1 -1
  16. package/lib/ir/core/irBand.js +28 -6
  17. package/lib/ir/core/irBand.js.map +1 -1
  18. package/lib/ir/core/irCommands.d.ts +11 -0
  19. package/lib/ir/core/irCommands.d.ts.map +1 -1
  20. package/lib/ir/core/irCommands.js +11 -1
  21. package/lib/ir/core/irCommands.js.map +1 -1
  22. package/lib/ir/core/irDomain.d.ts +4 -3
  23. package/lib/ir/core/irDomain.d.ts.map +1 -1
  24. package/lib/ir/core/irDomain.js +10 -7
  25. package/lib/ir/core/irDomain.js.map +1 -1
  26. package/lib/ir/core/irFormat.d.ts +14 -2
  27. package/lib/ir/core/irFormat.d.ts.map +1 -1
  28. package/lib/ir/core/irFormat.js +33 -4
  29. package/lib/ir/core/irFormat.js.map +1 -1
  30. package/lib/ir/core/irMode.d.ts +35 -8
  31. package/lib/ir/core/irMode.d.ts.map +1 -1
  32. package/lib/ir/core/irMode.js +38 -10
  33. package/lib/ir/core/irMode.js.map +1 -1
  34. package/lib/ir/core/irReducer.d.ts +0 -28
  35. package/lib/ir/core/irReducer.d.ts.map +1 -1
  36. package/lib/ir/core/irReducer.js +1 -24
  37. package/lib/ir/core/irReducer.js.map +1 -1
  38. package/lib/ir/core/irSpectrum.d.ts +52 -26
  39. package/lib/ir/core/irSpectrum.d.ts.map +1 -1
  40. package/lib/ir/core/irSpectrum.js +21 -15
  41. package/lib/ir/core/irSpectrum.js.map +1 -1
  42. package/lib/ir/core/irState.d.ts +40 -2
  43. package/lib/ir/core/irState.d.ts.map +1 -1
  44. package/lib/ir/core/irState.js +38 -1
  45. package/lib/ir/core/irState.js.map +1 -1
  46. package/lib/ir/core/irTechnique.d.ts +94 -0
  47. package/lib/ir/core/irTechnique.d.ts.map +1 -0
  48. package/lib/ir/core/irTechnique.js +87 -0
  49. package/lib/ir/core/irTechnique.js.map +1 -0
  50. package/lib/ir/core/irTechniqueCommands.d.ts +26 -0
  51. package/lib/ir/core/irTechniqueCommands.d.ts.map +1 -0
  52. package/lib/ir/core/irTechniqueCommands.js +68 -0
  53. package/lib/ir/core/irTechniqueCommands.js.map +1 -0
  54. package/lib/ir/core/pickBands.d.ts +6 -5
  55. package/lib/ir/core/pickBands.d.ts.map +1 -1
  56. package/lib/ir/core/pickBands.js +49 -26
  57. package/lib/ir/core/pickBands.js.map +1 -1
  58. package/lib/ir/core/ramanBands.d.ts +30 -0
  59. package/lib/ir/core/ramanBands.d.ts.map +1 -0
  60. package/lib/ir/core/ramanBands.js +83 -0
  61. package/lib/ir/core/ramanBands.js.map +1 -0
  62. package/lib/ir/core/spectrumJcamp.d.ts +10 -5
  63. package/lib/ir/core/spectrumJcamp.d.ts.map +1 -1
  64. package/lib/ir/core/spectrumJcamp.js +63 -15
  65. package/lib/ir/core/spectrumJcamp.js.map +1 -1
  66. package/lib/ir/core/toIrSpectrum.d.ts.map +1 -1
  67. package/lib/ir/core/toIrSpectrum.js +17 -2
  68. package/lib/ir/core/toIrSpectrum.js.map +1 -1
  69. package/lib/ir/ui/BandRow.d.ts +30 -0
  70. package/lib/ir/ui/BandRow.d.ts.map +1 -0
  71. package/lib/ir/ui/BandRow.js +42 -0
  72. package/lib/ir/ui/BandRow.js.map +1 -0
  73. package/lib/ir/ui/BandsPanel.d.ts +4 -0
  74. package/lib/ir/ui/BandsPanel.d.ts.map +1 -1
  75. package/lib/ir/ui/BandsPanel.js +14 -59
  76. package/lib/ir/ui/BandsPanel.js.map +1 -1
  77. package/lib/ir/ui/IrAboutDialog.d.ts +7 -0
  78. package/lib/ir/ui/IrAboutDialog.d.ts.map +1 -1
  79. package/lib/ir/ui/IrAboutDialog.js +16 -3
  80. package/lib/ir/ui/IrAboutDialog.js.map +1 -1
  81. package/lib/ir/ui/IrCanvas.d.ts.map +1 -1
  82. package/lib/ir/ui/IrCanvas.js +2 -2
  83. package/lib/ir/ui/IrCanvas.js.map +1 -1
  84. package/lib/ir/ui/IrChart.d.ts +2 -1
  85. package/lib/ir/ui/IrChart.d.ts.map +1 -1
  86. package/lib/ir/ui/IrChart.js +18 -21
  87. package/lib/ir/ui/IrChart.js.map +1 -1
  88. package/lib/ir/ui/IrCommandProvider.d.ts +7 -0
  89. package/lib/ir/ui/IrCommandProvider.d.ts.map +1 -1
  90. package/lib/ir/ui/IrCommandProvider.js +2 -2
  91. package/lib/ir/ui/IrCommandProvider.js.map +1 -1
  92. package/lib/ir/ui/IrCommandTooltip.d.ts +7 -0
  93. package/lib/ir/ui/IrCommandTooltip.d.ts.map +1 -1
  94. package/lib/ir/ui/IrCommandTooltip.js +3 -2
  95. package/lib/ir/ui/IrCommandTooltip.js.map +1 -1
  96. package/lib/ir/ui/IrDocumentationDialog.d.ts +8 -1
  97. package/lib/ir/ui/IrDocumentationDialog.d.ts.map +1 -1
  98. package/lib/ir/ui/IrDocumentationDialog.js +30 -7
  99. package/lib/ir/ui/IrDocumentationDialog.js.map +1 -1
  100. package/lib/ir/ui/IrEditor.d.ts +3 -1
  101. package/lib/ir/ui/IrEditor.d.ts.map +1 -1
  102. package/lib/ir/ui/IrEditor.js +3 -20
  103. package/lib/ir/ui/IrEditor.js.map +1 -1
  104. package/lib/ir/ui/IrHeader.d.ts.map +1 -1
  105. package/lib/ir/ui/IrHeader.js +5 -1
  106. package/lib/ir/ui/IrHeader.js.map +1 -1
  107. package/lib/ir/ui/IrLogo.d.ts +11 -3
  108. package/lib/ir/ui/IrLogo.d.ts.map +1 -1
  109. package/lib/ir/ui/IrLogo.js +14 -5
  110. package/lib/ir/ui/IrLogo.js.map +1 -1
  111. package/lib/ir/ui/IrShell.d.ts.map +1 -1
  112. package/lib/ir/ui/IrShell.js +23 -56
  113. package/lib/ir/ui/IrShell.js.map +1 -1
  114. package/lib/ir/ui/IrStatusBar.d.ts +3 -2
  115. package/lib/ir/ui/IrStatusBar.d.ts.map +1 -1
  116. package/lib/ir/ui/IrStatusBar.js +14 -9
  117. package/lib/ir/ui/IrStatusBar.js.map +1 -1
  118. package/lib/ir/ui/IrToolbar.d.ts +3 -0
  119. package/lib/ir/ui/IrToolbar.d.ts.map +1 -1
  120. package/lib/ir/ui/IrToolbar.js +10 -3
  121. package/lib/ir/ui/IrToolbar.js.map +1 -1
  122. package/lib/ir/ui/IrTraces.d.ts +4 -1
  123. package/lib/ir/ui/IrTraces.d.ts.map +1 -1
  124. package/lib/ir/ui/IrTraces.js +2 -0
  125. package/lib/ir/ui/IrTraces.js.map +1 -1
  126. package/lib/ir/ui/RamanEditor.d.ts +46 -0
  127. package/lib/ir/ui/RamanEditor.d.ts.map +1 -0
  128. package/lib/ir/ui/RamanEditor.js +17 -0
  129. package/lib/ir/ui/RamanEditor.js.map +1 -0
  130. package/lib/ir/ui/SpectraPanel.d.ts.map +1 -1
  131. package/lib/ir/ui/SpectraPanel.js +2 -2
  132. package/lib/ir/ui/SpectraPanel.js.map +1 -1
  133. package/lib/ir/ui/SpectrumRow.d.ts +7 -0
  134. package/lib/ir/ui/SpectrumRow.d.ts.map +1 -1
  135. package/lib/ir/ui/SpectrumRow.js +4 -5
  136. package/lib/ir/ui/SpectrumRow.js.map +1 -1
  137. package/lib/ir/ui/VibrationalEditor.d.ts +48 -0
  138. package/lib/ir/ui/VibrationalEditor.d.ts.map +1 -0
  139. package/lib/ir/ui/VibrationalEditor.js +31 -0
  140. package/lib/ir/ui/VibrationalEditor.js.map +1 -0
  141. package/lib/ir/ui/bandsTsv.d.ts +19 -0
  142. package/lib/ir/ui/bandsTsv.d.ts.map +1 -0
  143. package/lib/ir/ui/bandsTsv.js +38 -0
  144. package/lib/ir/ui/bandsTsv.js.map +1 -0
  145. package/lib/ir/ui/irChartProps.d.ts +14 -4
  146. package/lib/ir/ui/irChartProps.d.ts.map +1 -1
  147. package/lib/ir/ui/irChartProps.js +3 -2
  148. package/lib/ir/ui/irChartProps.js.map +1 -1
  149. package/lib/ir/ui/irCommandContext.d.ts +8 -0
  150. package/lib/ir/ui/irCommandContext.d.ts.map +1 -1
  151. package/lib/ir/ui/irCommandContext.js +14 -3
  152. package/lib/ir/ui/irCommandContext.js.map +1 -1
  153. package/lib/ir/ui/useIrEditor.d.ts +3 -3
  154. package/lib/ir/ui/useIrEditor.d.ts.map +1 -1
  155. package/lib/ir/ui/useIrEditor.js +13 -4
  156. package/lib/ir/ui/useIrEditor.js.map +1 -1
  157. package/lib/ir/ui/useIrHandle.d.ts +14 -0
  158. package/lib/ir/ui/useIrHandle.d.ts.map +1 -0
  159. package/lib/ir/ui/useIrHandle.js +39 -0
  160. package/lib/ir/ui/useIrHandle.js.map +1 -0
  161. package/lib/ir/ui/useIrText.d.ts +40 -0
  162. package/lib/ir/ui/useIrText.d.ts.map +1 -0
  163. package/lib/ir/ui/useIrText.js +118 -0
  164. package/lib/ir/ui/useIrText.js.map +1 -0
  165. package/lib/ir/ui/useIrZoom.d.ts +7 -0
  166. package/lib/ir/ui/useIrZoom.d.ts.map +1 -1
  167. package/lib/ir/ui/useIrZoom.js +5 -4
  168. package/lib/ir/ui/useIrZoom.js.map +1 -1
  169. package/lib/ir/ui/useValueAxisZoom.d.ts +20 -0
  170. package/lib/ir/ui/useValueAxisZoom.d.ts.map +1 -0
  171. package/lib/ir/ui/useValueAxisZoom.js +54 -0
  172. package/lib/ir/ui/useValueAxisZoom.js.map +1 -0
  173. package/lib/ir.d.ts +3 -0
  174. package/lib/ir.d.ts.map +1 -1
  175. package/lib/ir.js +3 -0
  176. package/lib/ir.js.map +1 -1
  177. package/lib/locales/de.json +20 -1
  178. package/lib/locales/en.json +20 -1
  179. package/lib/locales/es.json +20 -1
  180. package/lib/locales/fr.json +20 -1
  181. package/lib/locales/it.json +20 -1
  182. package/lib/raman.d.ts +16 -0
  183. package/lib/raman.d.ts.map +1 -0
  184. package/lib/raman.js +12 -0
  185. package/lib/raman.js.map +1 -0
  186. package/package.json +2 -1
  187. package/src/ir/core/analysisSpectra.ts +26 -10
  188. package/src/ir/core/bandLabelPlan.ts +21 -10
  189. package/src/ir/core/index.ts +25 -5
  190. package/src/ir/core/irBand.ts +52 -14
  191. package/src/ir/core/irCommands.ts +15 -1
  192. package/src/ir/core/irDomain.ts +9 -7
  193. package/src/ir/core/irFormat.ts +39 -6
  194. package/src/ir/core/irMode.ts +42 -10
  195. package/src/ir/core/irReducer.ts +1 -49
  196. package/src/ir/core/irSpectrum.ts +59 -30
  197. package/src/ir/core/irState.ts +67 -2
  198. package/src/ir/core/irTechnique.ts +115 -0
  199. package/src/ir/core/irTechniqueCommands.ts +82 -0
  200. package/src/ir/core/pickBands.ts +63 -28
  201. package/src/ir/core/ramanBands.ts +105 -0
  202. package/src/ir/core/spectrumJcamp.ts +65 -16
  203. package/src/ir/core/toIrSpectrum.ts +20 -2
  204. package/src/ir/ui/BandRow.tsx +107 -0
  205. package/src/ir/ui/BandsPanel.tsx +32 -125
  206. package/src/ir/ui/IrAboutDialog.tsx +69 -28
  207. package/src/ir/ui/IrCanvas.tsx +2 -1
  208. package/src/ir/ui/IrChart.tsx +20 -24
  209. package/src/ir/ui/IrCommandProvider.tsx +10 -3
  210. package/src/ir/ui/IrCommandTooltip.tsx +11 -2
  211. package/src/ir/ui/IrDocumentationDialog.tsx +99 -55
  212. package/src/ir/ui/IrEditor.tsx +5 -36
  213. package/src/ir/ui/IrHeader.tsx +10 -3
  214. package/src/ir/ui/IrLogo.tsx +28 -9
  215. package/src/ir/ui/IrShell.tsx +27 -75
  216. package/src/ir/ui/IrStatusBar.tsx +17 -12
  217. package/src/ir/ui/IrToolbar.tsx +26 -15
  218. package/src/ir/ui/IrTraces.tsx +5 -1
  219. package/src/ir/ui/RamanEditor.tsx +53 -0
  220. package/src/ir/ui/SpectraPanel.tsx +2 -1
  221. package/src/ir/ui/SpectrumRow.tsx +14 -5
  222. package/src/ir/ui/VibrationalEditor.tsx +94 -0
  223. package/src/ir/ui/bandsTsv.ts +46 -0
  224. package/src/ir/ui/irChartProps.ts +14 -4
  225. package/src/ir/ui/irCommandContext.tsx +18 -3
  226. package/src/ir/ui/useIrEditor.ts +20 -8
  227. package/src/ir/ui/useIrHandle.ts +51 -0
  228. package/src/ir/ui/useIrText.ts +170 -0
  229. package/src/ir/ui/useIrZoom.ts +12 -3
  230. package/src/ir/ui/useValueAxisZoom.ts +67 -0
  231. package/src/ir.ts +3 -0
  232. package/src/locales/de.json +20 -1
  233. package/src/locales/en.json +20 -1
  234. package/src/locales/es.json +20 -1
  235. package/src/locales/fr.json +20 -1
  236. package/src/locales/it.json +20 -1
  237. package/src/raman.ts +19 -0
@@ -0,0 +1,46 @@
1
+ /**
2
+ * The band table as text, for pasting into a notebook.
3
+ */
4
+
5
+ import type { AssignedBand } from '../core/assignBands.ts';
6
+ import { bandValue } from '../core/irBand.ts';
7
+ import { formatIrValue, formatWavenumber } from '../core/irFormat.ts';
8
+ import type { IrMode } from '../core/irSpectrum.ts';
9
+
10
+ /**
11
+ * The table as tab separated text.
12
+ *
13
+ * Every candidate is on its band's row, because the reason to copy a band table
14
+ * is to put it beside a structure and argue about it — and the argument is over
15
+ * the candidates rather than over the wavenumbers. A technique the correlation
16
+ * table does not cover has no such column.
17
+ * @param rows - The bands, as they are shown.
18
+ * @param mode - Which value axis is being read.
19
+ * @param assignments - Whether the table has a column for the candidates.
20
+ * @returns The table, one line per band, with a heading.
21
+ */
22
+ export function bandsToTsv(
23
+ rows: readonly AssignedBand[],
24
+ mode: IrMode,
25
+ assignments: boolean,
26
+ ): string {
27
+ const heading = ['wavenumber', 'strength', mode];
28
+ if (assignments) heading.push('could be');
29
+ const lines = [heading.join('\t')];
30
+ for (const { band, candidates } of rows) {
31
+ const cells = [
32
+ formatWavenumber(band.wavenumber),
33
+ band.strength,
34
+ formatIrValue(bandValue(band, mode) ?? Number.NaN, mode),
35
+ ];
36
+ if (assignments) {
37
+ cells.push(
38
+ candidates
39
+ .map((candidate) => `${candidate.group} ${candidate.vibration}`)
40
+ .join('; '),
41
+ );
42
+ }
43
+ lines.push(cells.join('\t'));
44
+ }
45
+ return lines.join('\n');
46
+ }
@@ -7,8 +7,9 @@
7
7
  * of half a dozen layers nobody needs to read in order to mount one.
8
8
  *
9
9
  * Everything arrives as a prop and nothing is reached for: the chart reads no
10
- * context and no store, so the same component serves an editor, a report page
11
- * that only ever draws one spectrum, and a test.
10
+ * store and no context but the language the page is written in, so the same
11
+ * component serves an editor, a report page that only ever draws one spectrum,
12
+ * and a test.
12
13
  */
13
14
 
14
15
  import type { ReactNode } from 'react';
@@ -17,17 +18,26 @@ import type { ZoomDragMode } from '../../chart/core/chartDomain.ts';
17
18
  import type { AssignedBand } from '../core/assignBands.ts';
18
19
  import type { IrBand } from '../core/irBand.ts';
19
20
  import type { IrDomain, IrMode, IrSpectrum } from '../core/irSpectrum.ts';
21
+ import type { IrTechnique } from '../core/irTechnique.ts';
20
22
 
21
23
  export interface IrChartProps {
22
24
  /** The spectra to draw, each saying in itself whether it is drawn. */
23
25
  spectra: readonly IrSpectrum[];
24
26
  /**
25
- * Which value axis to draw them in.
27
+ * What the spectra were measured with, which names the wavenumber axis and
28
+ * decides which way it runs: high to low for infrared, low to high for Raman.
29
+ * @default 'infrared'
30
+ */
31
+ technique?: IrTechnique;
32
+ /**
33
+ * Which value axis to draw them in. One the technique does not offer draws
34
+ * its first instead.
26
35
  *
27
36
  * A prop rather than state, so the switch lives with whoever owns the toolbar
28
37
  * that flips it — and so two charts of the same spectra can be shown side by
29
38
  * side, one in each, which is the clearest way to see what the pair means.
30
- * @default 'transmittance'
39
+ * @default the technique's first: `'transmittance'` for infrared,
40
+ * `'intensity'` for Raman
31
41
  */
32
42
  mode?: IrMode;
33
43
  /**
@@ -12,14 +12,18 @@ import type {
12
12
  IrCommandId,
13
13
  RunIrCommand,
14
14
  } from '../core/irCommands.ts';
15
- import { irCommandLabel } from '../core/irCommands.ts';
15
+ import { irCommandEntryLabel, irCommands } from '../core/irCommands.ts';
16
+ import type { IrTechnique } from '../core/irTechnique.ts';
16
17
 
17
18
  import { IrCommandTooltip } from './IrCommandTooltip.tsx';
19
+ import { useIrText } from './useIrText.ts';
18
20
 
19
21
  /** What the provider holds. */
20
22
  export interface IrCommandContextValue {
21
23
  /** What each command does. */
22
24
  handlers: IrCommandHandlers;
25
+ /** What the spectra were measured with, which words the commands. */
26
+ technique: IrTechnique;
23
27
  /** Run one. */
24
28
  run: RunIrCommand;
25
29
  }
@@ -36,6 +40,14 @@ export function useIrCommand(): RunIrCommand {
36
40
  return value?.run ?? noRun;
37
41
  }
38
42
 
43
+ /**
44
+ * What the spectra were measured with, from anywhere inside the viewer.
45
+ * @returns The technique; infrared outside a provider.
46
+ */
47
+ export function useIrCommandTechnique(): IrTechnique {
48
+ return useContext(commandContext)?.technique ?? 'infrared';
49
+ }
50
+
39
51
  /**
40
52
  * Everything a toolbar item needs to be one command, in one spread.
41
53
  *
@@ -46,10 +58,13 @@ export function useIrCommand(): RunIrCommand {
46
58
  */
47
59
  export function useIrCommandProps() {
48
60
  const run = useIrCommand();
61
+ const technique = useIrCommandTechnique();
62
+ const text = useIrText(technique);
49
63
  return function command(id: IrCommandId) {
64
+ const entry = text.command(id) ?? irCommands[id];
50
65
  return {
51
- tooltip: <IrCommandTooltip id={id} />,
52
- 'aria-label': irCommandLabel(id),
66
+ tooltip: <IrCommandTooltip id={id} technique={technique} />,
67
+ 'aria-label': irCommandEntryLabel(entry),
53
68
  onClick: () => run(id),
54
69
  };
55
70
  };
@@ -17,10 +17,13 @@ import { useEffect, useMemo, useReducer, useRef } from 'react';
17
17
 
18
18
  import type { AssignedBand } from '../core/assignBands.ts';
19
19
  import { assignBands } from '../core/assignBands.ts';
20
- import type { CreateIrStateOptions } from '../core/irReducer.ts';
21
- import { createIrState, irReducer } from '../core/irReducer.ts';
20
+ import type { BandAssignment } from '../core/bandAssignments.ts';
21
+ import { BAND_ASSIGNMENTS } from '../core/bandAssignments.ts';
22
+ import { irReducer } from '../core/irReducer.ts';
22
23
  import type { IrSpectrum } from '../core/irSpectrum.ts';
23
- import type { IrState } from '../core/irState.ts';
24
+ import type { CreateIrStateOptions, IrState } from '../core/irState.ts';
25
+ import { createIrState } from '../core/irState.ts';
26
+ import { IR_TECHNIQUE_RULES } from '../core/irTechnique.ts';
24
27
  import { pickBands } from '../core/pickBands.ts';
25
28
 
26
29
  import type { IrEditorActions } from './irActions.ts';
@@ -46,7 +49,8 @@ export interface IrEditorApi {
46
49
  selectedSpectrum: IrSpectrum | null;
47
50
  /**
48
51
  * The bands of the selected spectrum, with everything each might be. Empty
49
- * while nothing is selected or while picking is switched off.
52
+ * while nothing is selected or while picking is switched off, and every band
53
+ * without a candidate for a technique the correlation table does not cover.
50
54
  */
51
55
  assigned: AssignedBand[];
52
56
  /** Everything to do. */
@@ -67,7 +71,7 @@ export function useIrEditor(options: UseIrEditorOptions = {}): IrEditorApi {
67
71
  const { spectra } = state.data;
68
72
  const { selectedId } = state.view;
69
73
  const { pickBands: picking, picking: pickingOptions } = state.settings;
70
- const { assignmentTolerance } = state.settings;
74
+ const { assignmentTolerance, technique } = state.settings;
71
75
 
72
76
  const visibleSpectra = useMemo(() => {
73
77
  const visible: IrSpectrum[] = [];
@@ -95,10 +99,15 @@ export function useIrEditor(options: UseIrEditorOptions = {}): IrEditorApi {
95
99
 
96
100
  // Assigning is a walk of thirty ranges per band, which is nothing beside the
97
101
  // picking — so it is a memo of its own, and moving the tolerance does not
98
- // re-pick.
102
+ // re-pick. A technique the table does not cover is matched against no table.
103
+ const { assignments } = IR_TECHNIQUE_RULES[technique];
99
104
  const assigned = useMemo(
100
- () => assignBands(bands, { tolerance: assignmentTolerance }),
101
- [bands, assignmentTolerance],
105
+ () =>
106
+ assignBands(bands, {
107
+ tolerance: assignmentTolerance,
108
+ assignments: assignments ? BAND_ASSIGNMENTS : NO_ASSIGNMENTS,
109
+ }),
110
+ [bands, assignmentTolerance, assignments],
102
111
  );
103
112
 
104
113
  // What was reported last, so a host passing a fresh callback on every render
@@ -118,6 +127,9 @@ export function useIrEditor(options: UseIrEditorOptions = {}): IrEditorApi {
118
127
  );
119
128
  }
120
129
 
130
+ /** The table a technique the correlation table does not cover is matched against. */
131
+ const NO_ASSIGNMENTS: readonly BandAssignment[] = [];
132
+
121
133
  /**
122
134
  * Whether two lists hold the same spectra, by identity and in order.
123
135
  * @param current - What was reported last.
@@ -0,0 +1,51 @@
1
+ /**
2
+ * The handle a host drives the viewer through, filled in from its state.
3
+ *
4
+ * A hook of its own beside the shell, because every gesture on the handle reads
5
+ * the state the shell already reads — and the shell is long enough without it.
6
+ */
7
+
8
+ import type { Ref } from 'react';
9
+ import { useImperativeHandle } from 'react';
10
+
11
+ import { fullDomain } from '../core/irDomain.ts';
12
+ import type { IrEditorHandle, ZoomToBandOptions } from '../core/irEditorApi.ts';
13
+ import type { IrDomain } from '../core/irSpectrum.ts';
14
+
15
+ import { useIrActions, useIrEditorState } from './irStateContext.ts';
16
+
17
+ /**
18
+ * Fill in a host's handle on the viewer this is called inside.
19
+ * @param handle - The handle to fill in, if the host asked for one.
20
+ */
21
+ export function useIrHandle(handle: Ref<IrEditorHandle> | undefined): void {
22
+ const { state, visibleSpectra } = useIrEditorState();
23
+ const actions = useIrActions();
24
+ const { domain } = state.view;
25
+ const { mode } = state.settings;
26
+
27
+ useImperativeHandle(
28
+ handle,
29
+ (): IrEditorHandle => ({
30
+ getSpectra: () => state.data.spectra,
31
+ setSpectra: (spectra) => actions.setSpectra(spectra),
32
+ addSpectra: (spectra) => actions.addSpectra(spectra),
33
+ clear: () => actions.clear(),
34
+ setDomain: (next) => actions.setDomain(next),
35
+ resetDomain: () => actions.resetDomain(),
36
+ zoomToWavenumber: (wavenumber, options: ZoomToBandOptions = {}) => {
37
+ const { width = DEFAULT_FRAME_WIDTH } = options;
38
+ const shown: IrDomain = domain ?? fullDomain(visibleSpectra, mode);
39
+ actions.setDomain({
40
+ x: [wavenumber - width / 2, wavenumber + width / 2],
41
+ y: shown.y,
42
+ });
43
+ },
44
+ selectSpectrum: (id) => actions.selectSpectrum(id),
45
+ }),
46
+ [state.data.spectra, actions, domain, visibleSpectra, mode],
47
+ );
48
+ }
49
+
50
+ /** How wide a window a host gets when it asks to frame a band without saying. */
51
+ const DEFAULT_FRAME_WIDTH = 200;
@@ -0,0 +1,170 @@
1
+ /**
2
+ * The words of the viewer that change with what was measured, in the language
3
+ * the page is written in.
4
+ *
5
+ * Infrared's are not in the chrome's catalog: they are read from the core
6
+ * records, so an infrared viewer reads the same in every language. Raman's are
7
+ * in the catalog, each key written out rather than built, so a key the catalog
8
+ * lacks fails the type check instead of rendering raw.
9
+ */
10
+
11
+ import type { ChromeKey } from '../../i18n/core/chromeCatalog.ts';
12
+ import type { Translate } from '../../i18n/ui/useT.ts';
13
+ import { useChromeT } from '../../i18n/ui/useT.ts';
14
+ import type { IrCommand, IrCommandId } from '../core/irCommands.ts';
15
+ import { boxZoomOnly, yAxisTitle } from '../core/irMode.ts';
16
+ import type { IrMode } from '../core/irSpectrum.ts';
17
+ import type { IrTechnique } from '../core/irTechnique.ts';
18
+ import { IR_TECHNIQUE_RULES } from '../core/irTechnique.ts';
19
+ import { irCommandsFor } from '../core/irTechniqueCommands.ts';
20
+
21
+ /** The words that change with what was measured. */
22
+ export interface IrText {
23
+ /** What the horizontal axis is called. */
24
+ xTitle: string;
25
+ /** What the value axis is called in a mode. */
26
+ yTitle: (mode: IrMode) => string;
27
+ /** What the chart is and what can be done to it, for whoever cannot see it. */
28
+ chart: (mode: IrMode) => string;
29
+ /** The accessible name of the tool rail. */
30
+ tools: string;
31
+ /** The accessible name of the header. */
32
+ viewer: string;
33
+ /** The accessible name of the header's help group. */
34
+ viewerHelp: string;
35
+ /** The accessible name of the mark. */
36
+ mark: string;
37
+ /** The title of the documentation dialog. */
38
+ documentation: string;
39
+ /** A command as the viewer words it, `undefined` for one it does not offer. */
40
+ command: (id: IrCommandId) => IrCommand | undefined;
41
+ }
42
+
43
+ /**
44
+ * The words of a viewer of one technique.
45
+ * @param technique - What was measured.
46
+ * @returns The words, in the language of the page where the catalog has them.
47
+ */
48
+ export function useIrText(technique: IrTechnique): IrText {
49
+ const t = useChromeT();
50
+ return technique === 'raman' ? ramanText(t) : infraredText(t);
51
+ }
52
+
53
+ /**
54
+ * The words of an infrared viewer, from the core records.
55
+ * @param t - The chrome's formatter, for a value axis the catalog names.
56
+ * @returns The words.
57
+ */
58
+ function infraredText(t: Translate<ChromeKey>): IrText {
59
+ const { name, xTitle } = IR_TECHNIQUE_RULES.infrared;
60
+ const opening = `${name.charAt(0).toUpperCase()}${name.slice(1)}`;
61
+ const commands = irCommandsFor('infrared');
62
+ return {
63
+ xTitle,
64
+ yTitle: (mode) => modeTitle(t, mode),
65
+ chart: (mode) => infraredChartLabel(opening, mode),
66
+ tools: `${opening} spectrum tools`,
67
+ viewer: `${opening} spectrum viewer`,
68
+ viewerHelp: `${opening} spectrum viewer help`,
69
+ mark: `${opening} viewer`,
70
+ documentation: `Using the ${name} viewer`,
71
+ command: (id) => commands[id],
72
+ };
73
+ }
74
+
75
+ /**
76
+ * The words of a Raman viewer, all of them from the catalog.
77
+ * @param t - The chrome's formatter.
78
+ * @returns The words.
79
+ */
80
+ function ramanText(t: Translate<ChromeKey>): IrText {
81
+ const commands = irCommandsFor('raman');
82
+ return {
83
+ xTitle: t('ir.raman.xTitle'),
84
+ yTitle: (mode) => modeTitle(t, mode),
85
+ chart: () => t('ir.raman.chart'),
86
+ tools: t('ir.raman.tools'),
87
+ viewer: t('ir.raman.viewer'),
88
+ viewerHelp: t('ir.raman.viewerHelp'),
89
+ mark: t('ir.raman.mark'),
90
+ documentation: t('ir.raman.documentation'),
91
+ command: (id) => translated(t, commands[id], RAMAN_COMMAND_KEYS[id]),
92
+ };
93
+ }
94
+
95
+ /**
96
+ * What the value axis is called, translated where the catalog has the axis.
97
+ * @param t - The chrome's formatter.
98
+ * @param mode - Which value axis.
99
+ * @returns The title.
100
+ */
101
+ function modeTitle(t: Translate<ChromeKey>, mode: IrMode): string {
102
+ const key = MODE_KEYS[mode];
103
+ return key === undefined ? yAxisTitle(mode) : t(key);
104
+ }
105
+
106
+ /**
107
+ * The infrared chart's accessible name. The gestures differ by mode, so the
108
+ * sentence does too — a label promising the wheel to a reader who cannot watch
109
+ * it fail to do anything is worse than no label at all.
110
+ * @param opening - The technique's name, as a sentence opens on it.
111
+ * @param mode - Which value axis is being drawn.
112
+ * @returns The label.
113
+ */
114
+ function infraredChartLabel(opening: string, mode: IrMode): string {
115
+ const axis = `${opening} spectrum read as ${yAxisTitle(mode)}, wavenumber running from high at the left to low at the right.`;
116
+ return boxZoomOnly(mode)
117
+ ? `${axis} Drag a rectangle over it to zoom to that rectangle, and double click to fit everything again.`
118
+ : `${axis} Drag across it to zoom the wavenumber axis, drag past the baseline to take the value axis with it, turn the wheel to scale the value axis, and double click to fit everything again.`;
119
+ }
120
+
121
+ /**
122
+ * A command with its words read from the catalog where it has them.
123
+ * @param t - The chrome's formatter.
124
+ * @param entry - The command as its table words it.
125
+ * @param keys - The catalog keys of its title and description, if any.
126
+ * @returns The command, translated.
127
+ */
128
+ function translated(
129
+ t: Translate<ChromeKey>,
130
+ entry: IrCommand | undefined,
131
+ keys: CommandKeys | undefined,
132
+ ): IrCommand | undefined {
133
+ if (entry === undefined || keys === undefined) return entry;
134
+ return {
135
+ ...entry,
136
+ ...(keys.title === undefined ? {} : { title: t(keys.title) }),
137
+ ...(keys.description === undefined
138
+ ? {}
139
+ : { description: t(keys.description) }),
140
+ };
141
+ }
142
+
143
+ /** Where a command's words are kept in the catalog. */
144
+ interface CommandKeys {
145
+ /**
146
+ * Its title's key.
147
+ * @default the table's title
148
+ */
149
+ title?: ChromeKey;
150
+ /**
151
+ * Its description's key.
152
+ * @default the table's description
153
+ */
154
+ description?: ChromeKey;
155
+ }
156
+
157
+ /** The value axes the catalog has a name for. */
158
+ const MODE_KEYS: Partial<Record<IrMode, ChromeKey>> = {
159
+ intensity: 'ir.mode.intensity',
160
+ };
161
+
162
+ /** The catalog keys of every command a Raman viewer words its own way. */
163
+ const RAMAN_COMMAND_KEYS: Partial<Record<IrCommandId, CommandKeys>> = {
164
+ about: { title: 'ir.raman.about' },
165
+ documentation: { description: 'ir.raman.command.documentation' },
166
+ readTool: { description: 'ir.raman.command.readTool' },
167
+ boxTool: { description: 'ir.raman.command.boxTool' },
168
+ zoomIn: { description: 'ir.raman.command.zoomIn' },
169
+ togglePicking: { description: 'ir.raman.command.togglePicking' },
170
+ };
@@ -21,10 +21,18 @@ import { useChartZoom } from '../../chart/ui/useChartZoom.ts';
21
21
  import { fittedTo, fullDomain } from '../core/irDomain.ts';
22
22
  import { yAxisRules, zoomGestures } from '../core/irMode.ts';
23
23
  import type { IrDomain, IrMode, IrSpectrum } from '../core/irSpectrum.ts';
24
+ import type { IrTechnique } from '../core/irTechnique.ts';
25
+ import { IR_TECHNIQUE_RULES } from '../core/irTechnique.ts';
24
26
 
25
27
  export interface IrZoomOptions {
26
28
  /** Everything the chart holds, which is what the window is fitted to. */
27
29
  spectra: readonly IrSpectrum[];
30
+ /**
31
+ * What the spectra were measured with, which decides which way the
32
+ * wavenumber axis runs.
33
+ * @default 'infrared'
34
+ */
35
+ technique?: IrTechnique;
28
36
  /** Which value axis is being drawn. */
29
37
  mode: IrMode;
30
38
  /** The SVG the gestures are made on, as it was handed to its `ref`. */
@@ -58,6 +66,7 @@ export interface IrZoomOptions {
58
66
  export function useIrZoom(options: IrZoomOptions): ChartZoom {
59
67
  const {
60
68
  spectra,
69
+ technique = 'infrared',
61
70
  mode,
62
71
  svgRef,
63
72
  plot,
@@ -71,8 +80,8 @@ export function useIrZoom(options: IrZoomOptions): ChartZoom {
71
80
  const gestures = useMemo(() => zoomGestures(mode, drag), [mode, drag]);
72
81
 
73
82
  // `reverseX` is not decoration: the hook measures every gesture by inverting a
74
- // pixel through the scale it builds, so it has to build the same reversed one
75
- // the chart draws with.
83
+ // pixel through the scale it builds, so it has to build the same scale the
84
+ // chart draws with — reversed for infrared, forward for Raman.
76
85
  return useChartZoom({
77
86
  fitted,
78
87
  fitKey,
@@ -81,6 +90,6 @@ export function useIrZoom(options: IrZoomOptions): ChartZoom {
81
90
  yAxis,
82
91
  domain,
83
92
  gestures,
84
- reverseX: true,
93
+ reverseX: IR_TECHNIQUE_RULES[technique].reverseX,
85
94
  });
86
95
  }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * The zoom in and zoom out commands, which scale the value axis alone.
3
+ *
4
+ * They scale it about the baseline the mode hangs from — 100 for percent
5
+ * transmittance, zero for absorbance and intensity — so a weak band comes up
6
+ * out of its baseline rather than the whole trace drifting off the plot.
7
+ */
8
+
9
+ import { useMemo } from 'react';
10
+
11
+ import { fullDomain } from '../core/irDomain.ts';
12
+ import { yAxisRules } from '../core/irMode.ts';
13
+
14
+ import { useIrActions, useIrEditorState } from './irStateContext.ts';
15
+
16
+ /** The two commands, ready to hand to a button or a key. */
17
+ export interface ValueAxisZoom {
18
+ /** Bring the bands up by one step. */
19
+ zoomIn: () => void;
20
+ /** Put the axis back out by one step. */
21
+ zoomOut: () => void;
22
+ }
23
+
24
+ /**
25
+ * Zoom the value axis of the viewer this is called inside.
26
+ * @returns The two commands.
27
+ */
28
+ export function useValueAxisZoom(): ValueAxisZoom {
29
+ const { state, visibleSpectra } = useIrEditorState();
30
+ const actions = useIrActions();
31
+ const { domain } = state.view;
32
+ const { mode } = state.settings;
33
+
34
+ return useMemo(() => {
35
+ /**
36
+ * Scale the value axis by a factor, about the baseline the mode hangs from.
37
+ * @param factor - Above one to zoom out.
38
+ */
39
+ function scale(factor: number): void {
40
+ const shown = domain ?? fullDomain(visibleSpectra, mode);
41
+ // Asked of the mode rather than written out again here: the baseline a
42
+ // value axis is scaled about is `irMode`'s to know, and a second copy of
43
+ // it is a second thing to get wrong.
44
+ const { baseline = 0 } = yAxisRules(mode);
45
+ actions.setDomain({
46
+ x: shown.x,
47
+ y: [
48
+ baseline + (shown.y[0] - baseline) * factor,
49
+ baseline + (shown.y[1] - baseline) * factor,
50
+ ],
51
+ });
52
+ }
53
+ return {
54
+ zoomIn: () => scale(1 / ZOOM_STEP),
55
+ zoomOut: () => scale(ZOOM_STEP),
56
+ };
57
+ }, [actions, domain, visibleSpectra, mode]);
58
+ }
59
+
60
+ /**
61
+ * What one press of zoom in or out is worth.
62
+ *
63
+ * A fifth, which is about what one notch of a mouse wheel does — so the button
64
+ * and the wheel feel like the same gesture at two speeds rather than two
65
+ * different ones.
66
+ */
67
+ const ZOOM_STEP = 1.2;
package/src/ir.ts CHANGED
@@ -7,6 +7,9 @@
7
7
  * arrive in — `ir-spectrum` for the band correlations, `convert-to-jcamp` for
8
8
  * writing them back out, and a JCAMP or SPC reader fetched only once the bytes
9
9
  * turn out to need it. A site with no spectra to look at installs none of it.
10
+ *
11
+ * Raman spectra are drawn by the same code, opened through
12
+ * `react-cheminfo/raman`.
10
13
  */
11
14
 
12
15
  export * from './ir/core/index.ts';
@@ -663,5 +663,24 @@
663
663
  "moleculesToken.fix.issueOnServer": "Oder auf dem Server von molecules.cheminfo.org:",
664
664
  "moleculesToken.fix.envOne": "Tragen Sie es in die .env des Servers dieser Website ein:",
665
665
  "moleculesToken.fix.envMany": "Tragen Sie sie in die .env des Servers dieser Website ein:",
666
- "moleculesToken.fix.restart": "Starten Sie die Dienste neu, da sie die .env nur beim Start lesen:"
666
+ "moleculesToken.fix.restart": "Starten Sie die Dienste neu, da sie die .env nur beim Start lesen:",
667
+ "ir.mode.intensity": "Intensität",
668
+ "ir.raman.xTitle": "Raman-Verschiebung (cm⁻¹)",
669
+ "ir.raman.chart": "Raman-Spektrum, als Intensität gelesen, die Raman-Verschiebung von links nach rechts steigend. Ziehen Sie darüber, um die Achse der Raman-Verschiebung zu zoomen, ziehen Sie über die Grundlinie hinaus, um die Intensitätsachse mitzunehmen, drehen Sie das Mausrad, um die Intensitätsachse zu skalieren, und doppelklicken Sie, um wieder alles einzupassen.",
670
+ "ir.raman.tools": "Werkzeuge für das Raman-Spektrum",
671
+ "ir.raman.viewer": "Raman-Spektrenbetrachter",
672
+ "ir.raman.viewerHelp": "Hilfe zum Raman-Spektrenbetrachter",
673
+ "ir.raman.mark": "Raman-Betrachter",
674
+ "ir.raman.about": "Über den Raman-Betrachter",
675
+ "ir.raman.documentation": "Den Raman-Betrachter verwenden",
676
+ "ir.raman.command.documentation": "Wie die Banden gelesen werden, und jede Geste.",
677
+ "ir.raman.command.readTool": "Ein Ziehen verengt die Achse der Raman-Verschiebung. Über die Grundlinie hinaus losgelassen, nimmt es die Intensitätsachse mit.",
678
+ "ir.raman.command.boxTool": "Ein Ziehen zoomt genau auf das Rechteck, das es aufspannt, beide Achsen zugleich — um in eine Grundlinie oder eine Schulter hineinzusehen statt über das ganze Spektrum.",
679
+ "ir.raman.command.zoomIn": "Hebt die schwachen Banden hervor, indem die Intensitätsachse um null skaliert wird.",
680
+ "ir.raman.command.togglePicking": "Findet die Banden des ausgewählten Spektrums, markiert sie im Diagramm und listet sie auf.",
681
+ "ir.raman.doc.bands": "Die Banden des *ausgewählten* Spektrums werden als Intensitätsmaxima gefunden, im Diagramm markiert und im Bandenbereich aufgelistet. Fahren Sie über eine Zeile, wird die Bande im Diagramm markiert; fahren Sie über das Diagramm, leuchtet die Zeile auf.",
682
+ "ir.raman.doc.sampled": "Eine Bande wird an dem abgetasteten Punkt angegeben, an dem sie ihr Maximum hat: Ihre Lage ist nur so genau wie das Raster, auf dem das Spektrum aufgenommen wurde.",
683
+ "ir.raman.aboutLead": "Zeichnet ein Raman-Spektrum, findet seine Banden und listet sie neben dem Diagramm auf.",
684
+ "ir.raman.credit.picking": "**ir-spectrum** (cheminfo, MIT) findet die Banden, mit dem Peakfinder von **common-spectrum** und **ml-gsd**.",
685
+ "ir.raman.credit.jcamp": "**convert-to-jcamp** (cheminfo, MIT) schreibt die heruntergeladene JCAMP-DX-Datei."
667
686
  }
@@ -663,5 +663,24 @@
663
663
  "moleculesToken.fix.issueOnServer": "Or, on the server of molecules.cheminfo.org:",
664
664
  "moleculesToken.fix.envOne": "Write it in the .env of this site's server:",
665
665
  "moleculesToken.fix.envMany": "Write them in the .env of this site's server:",
666
- "moleculesToken.fix.restart": "Restart the services, which read the .env only when they start:"
666
+ "moleculesToken.fix.restart": "Restart the services, which read the .env only when they start:",
667
+ "ir.mode.intensity": "intensity",
668
+ "ir.raman.xTitle": "Raman shift (cm⁻¹)",
669
+ "ir.raman.chart": "Raman spectrum read as intensity, Raman shift running from low at the left to high at the right. Drag across it to zoom the Raman shift axis, drag past the baseline to take the intensity axis with it, turn the wheel to scale the intensity axis, and double click to fit everything again.",
670
+ "ir.raman.tools": "Raman spectrum tools",
671
+ "ir.raman.viewer": "Raman spectrum viewer",
672
+ "ir.raman.viewerHelp": "Raman spectrum viewer help",
673
+ "ir.raman.mark": "Raman viewer",
674
+ "ir.raman.about": "About the Raman viewer",
675
+ "ir.raman.documentation": "Using the Raman viewer",
676
+ "ir.raman.command.documentation": "How the bands are read, and every gesture.",
677
+ "ir.raman.command.readTool": "A drag narrows the Raman shift axis. Released past the baseline, it takes the intensity axis with it.",
678
+ "ir.raman.command.boxTool": "A drag zooms to exactly the rectangle it sweeps out, both axes at once — for looking into a baseline or a shoulder rather than across the spectrum.",
679
+ "ir.raman.command.zoomIn": "Brings the weak bands up, scaling the intensity axis about zero.",
680
+ "ir.raman.command.togglePicking": "Finds the bands of the selected spectrum, marks them on the chart and lists them.",
681
+ "ir.raman.doc.bands": "The bands of the *selected* spectrum are picked as maxima of intensity, marked on the chart and listed in the bands panel. Hovering a row marks the band on the chart, and hovering the chart lights the row.",
682
+ "ir.raman.doc.sampled": "A band is reported at the sampled point it peaked on, so its position is only as precise as the grid the spectrum was recorded on.",
683
+ "ir.raman.aboutLead": "Draws a Raman spectrum, picks its bands and lists them beside the chart.",
684
+ "ir.raman.credit.picking": "**ir-spectrum** (cheminfo, MIT) picks the bands, with the peak picker of **common-spectrum** and **ml-gsd**.",
685
+ "ir.raman.credit.jcamp": "**convert-to-jcamp** (cheminfo, MIT) writes the JCAMP-DX download."
667
686
  }
@@ -663,5 +663,24 @@
663
663
  "moleculesToken.fix.issueOnServer": "O, en el servidor de molecules.cheminfo.org:",
664
664
  "moleculesToken.fix.envOne": "Escríbalo en el .env del servidor de este sitio:",
665
665
  "moleculesToken.fix.envMany": "Escríbalos en el .env del servidor de este sitio:",
666
- "moleculesToken.fix.restart": "Reinicie los servicios, que solo leen el .env al arrancar:"
666
+ "moleculesToken.fix.restart": "Reinicie los servicios, que solo leen el .env al arrancar:",
667
+ "ir.mode.intensity": "intensidad",
668
+ "ir.raman.xTitle": "desplazamiento Raman (cm⁻¹)",
669
+ "ir.raman.chart": "Espectro Raman leído como intensidad, con el desplazamiento Raman creciendo de izquierda a derecha. Arrastre sobre él para ampliar el eje del desplazamiento Raman, arrastre más allá de la línea de base para llevarse también el eje de intensidad, gire la rueda para escalar el eje de intensidad y haga doble clic para volver a ajustarlo todo.",
670
+ "ir.raman.tools": "Herramientas del espectro Raman",
671
+ "ir.raman.viewer": "Visor de espectros Raman",
672
+ "ir.raman.viewerHelp": "Ayuda del visor de espectros Raman",
673
+ "ir.raman.mark": "Visor Raman",
674
+ "ir.raman.about": "Acerca del visor Raman",
675
+ "ir.raman.documentation": "Uso del visor Raman",
676
+ "ir.raman.command.documentation": "Cómo se leen las bandas, y cada gesto.",
677
+ "ir.raman.command.readTool": "Un arrastre estrecha el eje del desplazamiento Raman. Soltado más allá de la línea de base, se lleva también el eje de intensidad.",
678
+ "ir.raman.command.boxTool": "Un arrastre amplía exactamente el rectángulo que traza, los dos ejes a la vez — para mirar dentro de una línea de base o de un hombro en lugar de a lo largo del espectro.",
679
+ "ir.raman.command.zoomIn": "Hace destacar las bandas débiles, escalando el eje de intensidad en torno a cero.",
680
+ "ir.raman.command.togglePicking": "Encuentra las bandas del espectro seleccionado, las marca en la gráfica y las enumera.",
681
+ "ir.raman.doc.bands": "Las bandas del espectro *seleccionado* se buscan como máximos de intensidad, se marcan en la gráfica y se enumeran en el panel de bandas. Pasar sobre una fila marca la banda en la gráfica, y pasar sobre la gráfica ilumina la fila.",
682
+ "ir.raman.doc.sampled": "Una banda se da en el punto muestreado donde alcanza su máximo: su posición no es más precisa que la rejilla en la que se registró el espectro.",
683
+ "ir.raman.aboutLead": "Dibuja un espectro Raman, encuentra sus bandas y las enumera junto a la gráfica.",
684
+ "ir.raman.credit.picking": "**ir-spectrum** (cheminfo, MIT) encuentra las bandas, con el detector de picos de **common-spectrum** y **ml-gsd**.",
685
+ "ir.raman.credit.jcamp": "**convert-to-jcamp** (cheminfo, MIT) escribe el archivo JCAMP-DX descargado."
667
686
  }
@@ -663,5 +663,24 @@
663
663
  "moleculesToken.fix.issueOnServer": "Ou, sur le serveur de molecules.cheminfo.org :",
664
664
  "moleculesToken.fix.envOne": "Écrivez-le dans le fichier .env du serveur de ce site :",
665
665
  "moleculesToken.fix.envMany": "Écrivez-les dans le fichier .env du serveur de ce site :",
666
- "moleculesToken.fix.restart": "Redémarrez les services, qui ne lisent le fichier .env qu'à leur démarrage :"
666
+ "moleculesToken.fix.restart": "Redémarrez les services, qui ne lisent le fichier .env qu'à leur démarrage :",
667
+ "ir.mode.intensity": "intensité",
668
+ "ir.raman.xTitle": "déplacement Raman (cm⁻¹)",
669
+ "ir.raman.chart": "Spectre Raman lu en intensité, le déplacement Raman croissant de gauche à droite. Glissez dessus pour zoomer sur l'axe du déplacement Raman, glissez au-delà de la ligne de base pour entraîner aussi l'axe des intensités, tournez la molette pour mettre l'axe des intensités à l'échelle, et double-cliquez pour tout réajuster.",
670
+ "ir.raman.tools": "Outils du spectre Raman",
671
+ "ir.raman.viewer": "Visionneuse de spectres Raman",
672
+ "ir.raman.viewerHelp": "Aide de la visionneuse de spectres Raman",
673
+ "ir.raman.mark": "Visionneuse Raman",
674
+ "ir.raman.about": "À propos de la visionneuse Raman",
675
+ "ir.raman.documentation": "Utiliser la visionneuse Raman",
676
+ "ir.raman.command.documentation": "Comment les bandes sont lues, et chaque geste.",
677
+ "ir.raman.command.readTool": "Un glissement resserre l'axe du déplacement Raman. Relâché au-delà de la ligne de base, il entraîne aussi l'axe des intensités.",
678
+ "ir.raman.command.boxTool": "Un glissement zoome exactement sur le rectangle qu'il trace, les deux axes à la fois — pour regarder dans une ligne de base ou un épaulement plutôt qu'à travers le spectre.",
679
+ "ir.raman.command.zoomIn": "Fait ressortir les bandes faibles, en mettant l'axe des intensités à l'échelle autour de zéro.",
680
+ "ir.raman.command.togglePicking": "Trouve les bandes du spectre sélectionné, les marque sur le graphique et les liste.",
681
+ "ir.raman.doc.bands": "Les bandes du spectre *sélectionné* sont repérées comme maxima d'intensité, marquées sur le graphique et listées dans le panneau des bandes. Survoler une ligne marque la bande sur le graphique, et survoler le graphique éclaire la ligne.",
682
+ "ir.raman.doc.sampled": "Une bande est donnée au point échantillonné où elle culmine : sa position n'est pas plus précise que la grille sur laquelle le spectre a été enregistré.",
683
+ "ir.raman.aboutLead": "Trace un spectre Raman, repère ses bandes et les liste à côté du graphique.",
684
+ "ir.raman.credit.picking": "**ir-spectrum** (cheminfo, MIT) repère les bandes, avec le détecteur de pics de **common-spectrum** et **ml-gsd**.",
685
+ "ir.raman.credit.jcamp": "**convert-to-jcamp** (cheminfo, MIT) écrit le fichier JCAMP-DX téléchargé."
667
686
  }