ir-spectrum 4.2.0 → 4.2.1

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.
package/README.md CHANGED
@@ -12,21 +12,26 @@
12
12
  ## Usage
13
13
 
14
14
  ```js
15
- import IRSpectrum from 'ir-spectrum';
15
+ import { readFileSync } from 'node:fs';
16
16
 
17
- let analysis = IRSpectrum.fromJcamp(jcamp);
17
+ import { fromJcamp } from 'ir-spectrum';
18
+
19
+ const analysis = fromJcamp(readFileSync('absorbance.jdx', 'utf8'));
20
+ const spectrum = analysis.getSpectrum();
18
21
  ```
19
22
 
23
+ Other loaders are `fromSPC` (SPC files) and `fromText` (CSV, TSV and other x,y text). `peakPicking` and `autoPeakPicking` return peaks with their wavenumber, absorbance and transmittance.
24
+
20
25
  When loading an IR spectrum from JCAMP or SPC, two additional variables are systematically added:
21
26
 
22
- | Key | Label | Units | Description | Always present |
23
- | --- | ------------------ | ----- | -------------------------------- | -------------- |
24
- | x | Wavenumber | cm⁻¹ | Infrared wavenumber | Yes |
25
- | y | (from source file) | | Original y-axis data | Yes |
26
- | a | Absorbance | | Absorbance values | Yes |
27
- | t | Transmittance | % | Percent transmittance values | Yes |
27
+ | Key | Label | Units | Description | Always present |
28
+ | --- | ------------------ | ----- | ---------------------------- | -------------- |
29
+ | x | Wavenumber | cm⁻¹ | Infrared wavenumber | Yes |
30
+ | y | (from source file) | | Original y-axis data | Yes |
31
+ | a | Absorbance | | Absorbance values | Yes |
32
+ | t | Transmittance | % | Percent transmittance values | Yes |
28
33
 
29
- The conversion is automatic: if the original y label contains "transmittance", absorbance is calculated; if it contains "absorbance", transmittance is calculated. For transmittance, the presence of '%' or 'percent' in the label is used to determine the scaling factor.
34
+ The conversion is automatic: if the y label or units name a transmittance ("Transmittance", "Transmission", "%T", "T"), absorbance is calculated; otherwise y is taken as an absorbance and transmittance is calculated. A transmittance is read as a percentage when its label or units contain '%' or 'percent', or, failing that, when its values go above 2.
30
35
 
31
36
  ### Selector for visualization
32
37
 
@@ -1 +1 @@
1
- {"version":3,"file":"fromSPC.d.ts","sourceRoot":"","sources":["../../src/from/fromSPC.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAK5C,UAAU,cAAc;IACtB,0CAA0C;IAC1C,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6HAA6H;IAC7H,gBAAgB,CAAC,EAAE,CACjB,SAAS,EAAE,sBAAsB,KAC9B,sBAAsB,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CACrB,MAAM,EAAE,SAAS,EACjB,OAAO,GAAE,cAAmB,GAC3B,QAAQ,CAiBV"}
1
+ {"version":3,"file":"fromSPC.d.ts","sourceRoot":"","sources":["../../src/from/fromSPC.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAK5C,UAAU,cAAc;IACtB,0CAA0C;IAC1C,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6HAA6H;IAC7H,gBAAgB,CAAC,EAAE,CACjB,SAAS,EAAE,sBAAsB,KAC9B,sBAAsB,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CACrB,MAAM,EAAE,SAAS,EACjB,OAAO,GAAE,cAAmB,GAC3B,QAAQ,CAkBV"}
@@ -11,7 +11,8 @@ export function fromSPC(buffer, options = {}) {
11
11
  const { spectrumCallback = defaultSpectrumCallback, ...rest } = options;
12
12
  const analysis = new Analysis({ ...rest, spectrumCallback });
13
13
  const result = parse(buffer);
14
- const { parameters: _resultParameters, ...resultMeta } = result.meta;
14
+ const resultMeta = { ...result.meta };
15
+ delete resultMeta.parameters;
15
16
  for (const spectrum of result.spectra) {
16
17
  const { parameters: _spectrumParameters, ...spectrumMeta } = spectrum.meta ?? {};
17
18
  analysis.pushSpectrum(spectrum.variables, {
@@ -1 +1 @@
1
- {"version":3,"file":"fromSPC.js","sourceRoot":"","sources":["../../src/from/fromSPC.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,gBAAgB,IAAI,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAa1F;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CACrB,MAAiB,EACjB,UAA0B,EAAE;IAE5B,MAAM,EAAE,gBAAgB,GAAG,uBAAuB,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IACxE,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,EAAE,GAAG,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IAE7B,MAAM,EAAE,UAAU,EAAE,iBAAiB,EAAE,GAAG,UAAU,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC;IAErE,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACtC,MAAM,EAAE,UAAU,EAAE,mBAAmB,EAAE,GAAG,YAAY,EAAE,GACxD,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC;QACtB,QAAQ,CAAC,YAAY,CAAC,QAAQ,CAAC,SAAS,EAAE;YACxC,QAAQ,EAAE,aAAa;YACvB,KAAK,EAAE,EAAE;YACT,IAAI,EAAE,EAAE,GAAG,UAAU,EAAE,GAAG,YAAY,EAAE;SACzC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"fromSPC.js","sourceRoot":"","sources":["../../src/from/fromSPC.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,gBAAgB,IAAI,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAa1F;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CACrB,MAAiB,EACjB,UAA0B,EAAE;IAE5B,MAAM,EAAE,gBAAgB,GAAG,uBAAuB,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IACxE,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,EAAE,GAAG,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IAE7B,MAAM,UAAU,GAA4B,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC/D,OAAO,UAAU,CAAC,UAAU,CAAC;IAE7B,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACtC,MAAM,EAAE,UAAU,EAAE,mBAAmB,EAAE,GAAG,YAAY,EAAE,GACxD,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC;QACtB,QAAQ,CAAC,YAAY,CAAC,QAAQ,CAAC,SAAS,EAAE;YACxC,QAAQ,EAAE,aAAa;YACvB,KAAK,EAAE,EAAE;YACT,IAAI,EAAE,EAAE,GAAG,UAAU,EAAE,GAAG,YAAY,EAAE;SACzC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { MeasurementVariable, NumberArray } from 'cheminfo-types';
2
+ /**
3
+ * Checks whether a variable holds a transmittance rather than an absorbance.
4
+ * Spectrometers spell the unit in many ways and `%T` is as common as
5
+ * `TRANSMITTANCE`, so both the label and the units are tested.
6
+ * @param variable - Variable to inspect, usually the y of an IR spectrum.
7
+ * @returns True when the data is a transmittance.
8
+ */
9
+ export declare function isTransmittance(variable: Pick<MeasurementVariable, 'label' | 'units'>): boolean;
10
+ /**
11
+ * Checks whether a transmittance is expressed as a percentage rather than as a
12
+ * fraction of 1. The label and the units are tested first; when neither says
13
+ * so, the data decides, since a fraction never goes much above 1.
14
+ * @param variable - Variable known to hold a transmittance.
15
+ * @returns True when the data runs from 0 to 100.
16
+ */
17
+ export declare function isPercent(variable: Pick<MeasurementVariable, 'label' | 'units'> & {
18
+ data?: NumberArray;
19
+ }): boolean;
20
+ //# sourceMappingURL=isTransmittance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isTransmittance.d.ts","sourceRoot":"","sources":["../../../src/from/utils/isTransmittance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAQvE;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,IAAI,CAAC,mBAAmB,EAAE,OAAO,GAAG,OAAO,CAAC,GACrD,OAAO,CAOT;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CACvB,QAAQ,EAAE,IAAI,CAAC,mBAAmB,EAAE,OAAO,GAAG,OAAO,CAAC,GAAG;IACvD,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB,GACA,OAAO,CAST"}
@@ -0,0 +1,41 @@
1
+ import { xMaxValue } from 'ml-spectra-processing';
2
+ /** Any spelling built on the word itself: `TRANSMITTANCE`, `%Transmission`. */
3
+ const spelledOut = /trans/i;
4
+ /** The abbreviated forms, which share no substring with `transmittance`. */
5
+ const abbreviated = /^\s*%?\s*t\s*%?\s*$/i;
6
+ /**
7
+ * Checks whether a variable holds a transmittance rather than an absorbance.
8
+ * Spectrometers spell the unit in many ways and `%T` is as common as
9
+ * `TRANSMITTANCE`, so both the label and the units are tested.
10
+ * @param variable - Variable to inspect, usually the y of an IR spectrum.
11
+ * @returns True when the data is a transmittance.
12
+ */
13
+ export function isTransmittance(variable) {
14
+ const { label, units } = variable;
15
+ for (const value of [label, units]) {
16
+ if (!value)
17
+ continue;
18
+ if (spelledOut.test(value) || abbreviated.test(value))
19
+ return true;
20
+ }
21
+ return false;
22
+ }
23
+ /**
24
+ * Checks whether a transmittance is expressed as a percentage rather than as a
25
+ * fraction of 1. The label and the units are tested first; when neither says
26
+ * so, the data decides, since a fraction never goes much above 1.
27
+ * @param variable - Variable known to hold a transmittance.
28
+ * @returns True when the data runs from 0 to 100.
29
+ */
30
+ export function isPercent(variable) {
31
+ const { label, units, data } = variable;
32
+ for (const value of [label, units]) {
33
+ if (!value)
34
+ continue;
35
+ if (value.includes('%') || value.toLowerCase().includes('percent')) {
36
+ return true;
37
+ }
38
+ }
39
+ return data !== undefined && data.length > 0 && xMaxValue(data) > 2;
40
+ }
41
+ //# sourceMappingURL=isTransmittance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isTransmittance.js","sourceRoot":"","sources":["../../../src/from/utils/isTransmittance.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD,+EAA+E;AAC/E,MAAM,UAAU,GAAG,QAAQ,CAAC;AAC5B,4EAA4E;AAC5E,MAAM,WAAW,GAAG,sBAAsB,CAAC;AAE3C;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAsD;IAEtD,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC;IAClC,KAAK,MAAM,KAAK,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;QACnC,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;IACrE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CACvB,QAEC;IAED,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC;IACxC,KAAK,MAAM,KAAK,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;QACnC,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YACnE,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACtE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"spectrumCallback.d.ts","sourceRoot":"","sources":["../../../src/from/utils/spectrumCallback.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAE7D;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,sBAAsB,GAChC,sBAAsB,CAqDxB"}
1
+ {"version":3,"file":"spectrumCallback.d.ts","sourceRoot":"","sources":["../../../src/from/utils/spectrumCallback.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAI7D;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,sBAAsB,GAChC,sBAAsB,CAgDxB"}
@@ -1,3 +1,4 @@
1
+ import { isPercent, isTransmittance } from "./isTransmittance.js";
1
2
  /**
2
3
  * Callback that adds absorbance (a) and transmittance (t) variables to the spectrum.
3
4
  * If the y variable is absorbance, transmittance is computed and vice versa.
@@ -9,11 +10,7 @@ export function spectrumCallback(variables) {
9
10
  // variable a = absorbance
10
11
  // variable t = transmittance
11
12
  const yVariable = variables.y;
12
- let isAbsorbance = true;
13
- if (yVariable.label.toLowerCase().includes('trans')) {
14
- isAbsorbance = false;
15
- }
16
- if (isAbsorbance) {
13
+ if (!isTransmittance(yVariable)) {
17
14
  variables.a = {
18
15
  ...yVariable,
19
16
  symbol: 'a',
@@ -27,26 +24,25 @@ export function spectrumCallback(variables) {
27
24
  };
28
25
  }
29
26
  else {
30
- const factor = yVariable.label.includes('%') ||
31
- yVariable.label.toLowerCase().includes('percent')
32
- ? 100
33
- : 1;
27
+ const factor = isPercent(yVariable) ? 100 : 1;
34
28
  variables.a = {
35
29
  data: yVariable.data.map((transmittance) => -Math.log10(transmittance / factor)),
36
30
  symbol: 'a',
37
31
  label: 'Absorbance',
38
32
  units: '',
39
33
  };
40
- if (factor === 100) {
41
- variables.t = { ...yVariable, symbol: 't' };
42
- variables.t.data = variables.t.data.slice();
34
+ const { label, units, data } = yVariable;
35
+ if (isPercent({ label, units })) {
36
+ variables.t = { ...yVariable, symbol: 't', data: data.slice() };
43
37
  }
44
38
  else {
45
39
  variables.t = {
46
40
  units: '',
47
41
  label: 'Transmittance (%)',
48
42
  symbol: 't',
49
- data: yVariable.data.map((transmittance) => transmittance * 100),
43
+ data: factor === 100
44
+ ? data.slice()
45
+ : data.map((transmittance) => transmittance * 100),
50
46
  };
51
47
  }
52
48
  }
@@ -1 +1 @@
1
- {"version":3,"file":"spectrumCallback.js","sourceRoot":"","sources":["../../../src/from/utils/spectrumCallback.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAC9B,SAAiC;IAEjC,4CAA4C;IAC5C,0BAA0B;IAC1B,6BAA6B;IAC7B,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC;IAC9B,IAAI,YAAY,GAAG,IAAI,CAAC;IACxB,IAAI,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACpD,YAAY,GAAG,KAAK,CAAC;IACvB,CAAC;IACD,IAAI,YAAY,EAAE,CAAC;QACjB,SAAS,CAAC,CAAC,GAAG;YACZ,GAAG,SAAS;YACZ,MAAM,EAAE,GAAG;YACX,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,KAAK,EAAc;SACzC,CAAC;QACF,SAAS,CAAC,CAAC,GAAG;YACZ,IAAI,EAAG,SAAS,CAAC,IAAiB,CAAC,GAAG,CACpC,CAAC,UAAkB,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,UAAU,GAAG,GAAG,CAChD;YACD,KAAK,EAAE,mBAAmB;YAC1B,MAAM,EAAE,GAAG;YACX,KAAK,EAAE,EAAE;SACV,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,MAAM,MAAM,GACV,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;YAC7B,SAAS,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC;YAC/C,CAAC,CAAC,GAAG;YACL,CAAC,CAAC,CAAC,CAAC;QAER,SAAS,CAAC,CAAC,GAAG;YACZ,IAAI,EAAG,SAAS,CAAC,IAAiB,CAAC,GAAG,CACpC,CAAC,aAAqB,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,MAAM,CAAC,CAC/D;YACD,MAAM,EAAE,GAAG;YACX,KAAK,EAAE,YAAY;YACnB,KAAK,EAAE,EAAE;SACV,CAAC;QACF,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACnB,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;YAC5C,SAAS,CAAC,CAAC,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAC9C,CAAC;aAAM,CAAC;YACN,SAAS,CAAC,CAAC,GAAG;gBACZ,KAAK,EAAE,EAAE;gBACT,KAAK,EAAE,mBAAmB;gBAC1B,MAAM,EAAE,GAAG;gBACX,IAAI,EAAG,SAAS,CAAC,IAAiB,CAAC,GAAG,CACpC,CAAC,aAAqB,EAAE,EAAE,CAAC,aAAa,GAAG,GAAG,CAC/C;aACF,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
1
+ {"version":3,"file":"spectrumCallback.js","sourceRoot":"","sources":["../../../src/from/utils/spectrumCallback.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAElE;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAC9B,SAAiC;IAEjC,4CAA4C;IAC5C,0BAA0B;IAC1B,6BAA6B;IAC7B,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC;IAC9B,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,EAAE,CAAC;QAChC,SAAS,CAAC,CAAC,GAAG;YACZ,GAAG,SAAS;YACZ,MAAM,EAAE,GAAG;YACX,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,KAAK,EAAc;SACzC,CAAC;QACF,SAAS,CAAC,CAAC,GAAG;YACZ,IAAI,EAAG,SAAS,CAAC,IAAiB,CAAC,GAAG,CACpC,CAAC,UAAkB,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,UAAU,GAAG,GAAG,CAChD;YACD,KAAK,EAAE,mBAAmB;YAC1B,MAAM,EAAE,GAAG;YACX,KAAK,EAAE,EAAE;SACV,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAE9C,SAAS,CAAC,CAAC,GAAG;YACZ,IAAI,EAAG,SAAS,CAAC,IAAiB,CAAC,GAAG,CACpC,CAAC,aAAqB,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,MAAM,CAAC,CAC/D;YACD,MAAM,EAAE,GAAG;YACX,KAAK,EAAE,YAAY;YACnB,KAAK,EAAE,EAAE;SACV,CAAC;QACF,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,SAAS,CAAC;QACzC,IAAI,SAAS,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;YAChC,SAAS,CAAC,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;QAClE,CAAC;aAAM,CAAC;YACN,SAAS,CAAC,CAAC,GAAG;gBACZ,KAAK,EAAE,EAAE;gBACT,KAAK,EAAE,mBAAmB;gBAC1B,MAAM,EAAE,GAAG;gBACX,IAAI,EACF,MAAM,KAAK,GAAG;oBACZ,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE;oBACd,CAAC,CAAE,IAAiB,CAAC,GAAG,CACpB,CAAC,aAAqB,EAAE,EAAE,CAAC,aAAa,GAAG,GAAG,CAC/C;aACR,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ir-spectrum",
3
- "version": "4.2.0",
3
+ "version": "4.2.1",
4
4
  "description": "Package used to handle IR spectra in SciPeaks.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -14,11 +14,11 @@
14
14
  "build": "npm run tsc && cheminfo-build --entry lib/index.js --root IRSpectrum",
15
15
  "check-types": "tsc --noEmit",
16
16
  "clean": "rimraf coverage lib",
17
- "eslint": "eslint src",
18
- "eslint-fix": "eslint src --fix",
17
+ "eslint": "eslint .",
18
+ "eslint-fix": "eslint . --fix",
19
19
  "prepack": "npm run tsc",
20
- "prettier": "prettier --check src",
21
- "prettier-write": "prettier --write src",
20
+ "prettier": "prettier --check .",
21
+ "prettier-write": "prettier --write .",
22
22
  "test": "npm run test-only && npm run check-types && npm run eslint && npm run prettier",
23
23
  "test-only": "vitest run --coverage",
24
24
  "tsc": "npm run clean && npm run tsc-build",
@@ -36,26 +36,27 @@
36
36
  },
37
37
  "homepage": "https://github.com/cheminfo/ir-spectrum#readme",
38
38
  "dependencies": {
39
- "common-spectrum": "3.2.0",
40
- "ml-gsd": "^13.1.1",
41
- "spc-parser": "^2.0.0",
39
+ "common-spectrum": "4.0.1",
40
+ "ml-gsd": "^14.3.0",
41
+ "ml-spectra-processing": "^14.35.1",
42
+ "spc-parser": "^2.1.1",
42
43
  "xy-parser": "^6.0.1"
43
44
  },
44
45
  "devDependencies": {
45
- "@types/node": "^25.6.0",
46
- "@vitest/coverage-v8": "^4.1.5",
46
+ "@types/node": "^26.6.1",
47
+ "@vitest/coverage-v8": "^4.1.11",
47
48
  "@zakodium/tsconfig": "^1.0.5",
48
- "cheminfo-build": "^1.3.2",
49
+ "cheminfo-build": "^1.4.0",
49
50
  "eslint": "^9.39.2",
50
51
  "eslint-config-cheminfo-typescript": "^22.0.0",
51
52
  "jest-matcher-deep-close-to": "^3.0.2",
52
- "prettier": "^3.8.3",
53
+ "prettier": "^3.9.8",
53
54
  "rimraf": "^6.1.3",
54
55
  "typescript": "^6.0.3",
55
- "vitest": "^4.1.5"
56
+ "vitest": "^4.1.11"
56
57
  },
57
58
  "info": {
58
- "logo": "https://raw.githubusercontent.com/cheminfo/font/master/src/ir/assignment.svg",
59
+ "logo": "https://raw.githubusercontent.com/cheminfo/font/main/src/ir/assignment.svg",
59
60
  "domain": [
60
61
  "Physical Chemistry",
61
62
  "Materials Science",
@@ -71,7 +72,7 @@
71
72
  {
72
73
  "extension": "jdx",
73
74
  "manufacturer": "IUPAC",
74
- "example": "https://raw.githubusercontent.com/cheminfo/ir-spectrum/master/testFiles/absorbance.jdx"
75
+ "example": "https://raw.githubusercontent.com/cheminfo/ir-spectrum/main/src/from/__tests__/data/absorbance.jdx"
75
76
  }
76
77
  ]
77
78
  }
@@ -30,7 +30,8 @@ export function fromSPC(
30
30
  const analysis = new Analysis({ ...rest, spectrumCallback });
31
31
  const result = parse(buffer);
32
32
 
33
- const { parameters: _resultParameters, ...resultMeta } = result.meta;
33
+ const resultMeta: Record<string, unknown> = { ...result.meta };
34
+ delete resultMeta.parameters;
34
35
 
35
36
  for (const spectrum of result.spectra) {
36
37
  const { parameters: _spectrumParameters, ...spectrumMeta } =
@@ -0,0 +1,47 @@
1
+ import type { MeasurementVariable, NumberArray } from 'cheminfo-types';
2
+ import { xMaxValue } from 'ml-spectra-processing';
3
+
4
+ /** Any spelling built on the word itself: `TRANSMITTANCE`, `%Transmission`. */
5
+ const spelledOut = /trans/i;
6
+ /** The abbreviated forms, which share no substring with `transmittance`. */
7
+ const abbreviated = /^\s*%?\s*t\s*%?\s*$/i;
8
+
9
+ /**
10
+ * Checks whether a variable holds a transmittance rather than an absorbance.
11
+ * Spectrometers spell the unit in many ways and `%T` is as common as
12
+ * `TRANSMITTANCE`, so both the label and the units are tested.
13
+ * @param variable - Variable to inspect, usually the y of an IR spectrum.
14
+ * @returns True when the data is a transmittance.
15
+ */
16
+ export function isTransmittance(
17
+ variable: Pick<MeasurementVariable, 'label' | 'units'>,
18
+ ): boolean {
19
+ const { label, units } = variable;
20
+ for (const value of [label, units]) {
21
+ if (!value) continue;
22
+ if (spelledOut.test(value) || abbreviated.test(value)) return true;
23
+ }
24
+ return false;
25
+ }
26
+
27
+ /**
28
+ * Checks whether a transmittance is expressed as a percentage rather than as a
29
+ * fraction of 1. The label and the units are tested first; when neither says
30
+ * so, the data decides, since a fraction never goes much above 1.
31
+ * @param variable - Variable known to hold a transmittance.
32
+ * @returns True when the data runs from 0 to 100.
33
+ */
34
+ export function isPercent(
35
+ variable: Pick<MeasurementVariable, 'label' | 'units'> & {
36
+ data?: NumberArray;
37
+ },
38
+ ): boolean {
39
+ const { label, units, data } = variable;
40
+ for (const value of [label, units]) {
41
+ if (!value) continue;
42
+ if (value.includes('%') || value.toLowerCase().includes('percent')) {
43
+ return true;
44
+ }
45
+ }
46
+ return data !== undefined && data.length > 0 && xMaxValue(data) > 2;
47
+ }
@@ -1,5 +1,7 @@
1
1
  import type { MeasurementXYVariables } from 'cheminfo-types';
2
2
 
3
+ import { isPercent, isTransmittance } from './isTransmittance.ts';
4
+
3
5
  /**
4
6
  * Callback that adds absorbance (a) and transmittance (t) variables to the spectrum.
5
7
  * If the y variable is absorbance, transmittance is computed and vice versa.
@@ -13,11 +15,7 @@ export function spectrumCallback(
13
15
  // variable a = absorbance
14
16
  // variable t = transmittance
15
17
  const yVariable = variables.y;
16
- let isAbsorbance = true;
17
- if (yVariable.label.toLowerCase().includes('trans')) {
18
- isAbsorbance = false;
19
- }
20
- if (isAbsorbance) {
18
+ if (!isTransmittance(yVariable)) {
21
19
  variables.a = {
22
20
  ...yVariable,
23
21
  symbol: 'a',
@@ -32,11 +30,7 @@ export function spectrumCallback(
32
30
  units: '',
33
31
  };
34
32
  } else {
35
- const factor =
36
- yVariable.label.includes('%') ||
37
- yVariable.label.toLowerCase().includes('percent')
38
- ? 100
39
- : 1;
33
+ const factor = isPercent(yVariable) ? 100 : 1;
40
34
 
41
35
  variables.a = {
42
36
  data: (yVariable.data as number[]).map(
@@ -46,17 +40,20 @@ export function spectrumCallback(
46
40
  label: 'Absorbance',
47
41
  units: '',
48
42
  };
49
- if (factor === 100) {
50
- variables.t = { ...yVariable, symbol: 't' };
51
- variables.t.data = variables.t.data.slice();
43
+ const { label, units, data } = yVariable;
44
+ if (isPercent({ label, units })) {
45
+ variables.t = { ...yVariable, symbol: 't', data: data.slice() };
52
46
  } else {
53
47
  variables.t = {
54
48
  units: '',
55
49
  label: 'Transmittance (%)',
56
50
  symbol: 't',
57
- data: (yVariable.data as number[]).map(
58
- (transmittance: number) => transmittance * 100,
59
- ),
51
+ data:
52
+ factor === 100
53
+ ? data.slice()
54
+ : (data as number[]).map(
55
+ (transmittance: number) => transmittance * 100,
56
+ ),
60
57
  };
61
58
  }
62
59
  }