jcampconverter 9.2.0 → 9.2.2
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/jcampconverter.cjs +8 -0
- package/{lib/convert.d.ts → jcampconverter.d.ts} +222 -182
- package/jcampconverter.mjs +8 -0
- package/package.json +27 -19
- package/lib/2d/add2D.d.ts +0 -2
- package/lib/2d/add2D.d.ts.map +0 -1
- package/lib/2d/add2D.js +0 -17
- package/lib/2d/add2D.js.map +0 -1
- package/lib/2d/convertTo3DZ.d.ts +0 -11
- package/lib/2d/convertTo3DZ.d.ts.map +0 -1
- package/lib/2d/convertTo3DZ.js +0 -59
- package/lib/2d/convertTo3DZ.js.map +0 -1
- package/lib/2d/generateContourLines.d.ts +0 -8
- package/lib/2d/generateContourLines.d.ts.map +0 -1
- package/lib/2d/generateContourLines.js +0 -163
- package/lib/2d/generateContourLines.js.map +0 -1
- package/lib/complexChromatogram.d.ts +0 -4
- package/lib/complexChromatogram.d.ts.map +0 -1
- package/lib/complexChromatogram.js +0 -49
- package/lib/complexChromatogram.js.map +0 -1
- package/lib/convert.d.ts.map +0 -1
- package/lib/convert.js +0 -412
- package/lib/convert.js.map +0 -1
- package/lib/convertToFloatArray.d.ts +0 -2
- package/lib/convertToFloatArray.d.ts.map +0 -1
- package/lib/convertToFloatArray.js +0 -11
- package/lib/convertToFloatArray.js.map +0 -1
- package/lib/createTree.d.ts +0 -29
- package/lib/createTree.d.ts.map +0 -1
- package/lib/createTree.js +0 -101
- package/lib/createTree.js.map +0 -1
- package/lib/index.d.ts +0 -3
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js +0 -8
- package/lib/index.js.map +0 -1
- package/lib/parse/fastParseXYData.d.ts +0 -2
- package/lib/parse/fastParseXYData.d.ts.map +0 -1
- package/lib/parse/fastParseXYData.js +0 -193
- package/lib/parse/fastParseXYData.js.map +0 -1
- package/lib/parse/parsePeakTable.d.ts +0 -2
- package/lib/parse/parsePeakTable.d.ts.map +0 -1
- package/lib/parse/parsePeakTable.js +0 -67
- package/lib/parse/parsePeakTable.js.map +0 -1
- package/lib/parse/parseXYA.d.ts +0 -2
- package/lib/parse/parseXYA.d.ts.map +0 -1
- package/lib/parse/parseXYA.js +0 -51
- package/lib/parse/parseXYA.js.map +0 -1
- package/lib/postProcessing.d.ts +0 -2
- package/lib/postProcessing.d.ts.map +0 -1
- package/lib/postProcessing.js +0 -93
- package/lib/postProcessing.js.map +0 -1
- package/lib/postProcessingNMR.d.ts +0 -2
- package/lib/postProcessingNMR.d.ts.map +0 -1
- package/lib/postProcessingNMR.js +0 -95
- package/lib/postProcessingNMR.js.map +0 -1
- package/lib/prepareNtuplesDatatable.d.ts +0 -2
- package/lib/prepareNtuplesDatatable.d.ts.map +0 -1
- package/lib/prepareNtuplesDatatable.js +0 -87
- package/lib/prepareNtuplesDatatable.js.map +0 -1
- package/lib/prepareSpectrum.d.ts +0 -2
- package/lib/prepareSpectrum.d.ts.map +0 -1
- package/lib/prepareSpectrum.js +0 -10
- package/lib/prepareSpectrum.js.map +0 -1
- package/lib/profiling.d.ts +0 -2
- package/lib/profiling.d.ts.map +0 -1
- package/lib/profiling.js +0 -13
- package/lib/profiling.js.map +0 -1
- package/lib/simpleChromatogram.d.ts +0 -2
- package/lib/simpleChromatogram.d.ts.map +0 -1
- package/lib/simpleChromatogram.js +0 -16
- package/lib/simpleChromatogram.js.map +0 -1
- package/lib-esm/2d/add2D.d.ts +0 -2
- package/lib-esm/2d/add2D.d.ts.map +0 -1
- package/lib-esm/2d/add2D.js +0 -11
- package/lib-esm/2d/add2D.js.map +0 -1
- package/lib-esm/2d/convertTo3DZ.d.ts +0 -11
- package/lib-esm/2d/convertTo3DZ.d.ts.map +0 -1
- package/lib-esm/2d/convertTo3DZ.js +0 -53
- package/lib-esm/2d/convertTo3DZ.js.map +0 -1
- package/lib-esm/2d/generateContourLines.d.ts +0 -8
- package/lib-esm/2d/generateContourLines.d.ts.map +0 -1
- package/lib-esm/2d/generateContourLines.js +0 -160
- package/lib-esm/2d/generateContourLines.js.map +0 -1
- package/lib-esm/complexChromatogram.d.ts +0 -4
- package/lib-esm/complexChromatogram.d.ts.map +0 -1
- package/lib-esm/complexChromatogram.js +0 -43
- package/lib-esm/complexChromatogram.js.map +0 -1
- package/lib-esm/convert.d.ts +0 -182
- package/lib-esm/convert.d.ts.map +0 -1
- package/lib-esm/convert.js +0 -405
- package/lib-esm/convert.js.map +0 -1
- package/lib-esm/convertToFloatArray.d.ts +0 -2
- package/lib-esm/convertToFloatArray.d.ts.map +0 -1
- package/lib-esm/convertToFloatArray.js +0 -8
- package/lib-esm/convertToFloatArray.js.map +0 -1
- package/lib-esm/createTree.d.ts +0 -29
- package/lib-esm/createTree.d.ts.map +0 -1
- package/lib-esm/createTree.js +0 -97
- package/lib-esm/createTree.js.map +0 -1
- package/lib-esm/index.d.ts +0 -3
- package/lib-esm/index.d.ts.map +0 -1
- package/lib-esm/index.js +0 -3
- package/lib-esm/index.js.map +0 -1
- package/lib-esm/parse/fastParseXYData.d.ts +0 -2
- package/lib-esm/parse/fastParseXYData.d.ts.map +0 -1
- package/lib-esm/parse/fastParseXYData.js +0 -190
- package/lib-esm/parse/fastParseXYData.js.map +0 -1
- package/lib-esm/parse/parsePeakTable.d.ts +0 -2
- package/lib-esm/parse/parsePeakTable.d.ts.map +0 -1
- package/lib-esm/parse/parsePeakTable.js +0 -64
- package/lib-esm/parse/parsePeakTable.js.map +0 -1
- package/lib-esm/parse/parseXYA.d.ts +0 -2
- package/lib-esm/parse/parseXYA.d.ts.map +0 -1
- package/lib-esm/parse/parseXYA.js +0 -48
- package/lib-esm/parse/parseXYA.js.map +0 -1
- package/lib-esm/postProcessing.d.ts +0 -2
- package/lib-esm/postProcessing.d.ts.map +0 -1
- package/lib-esm/postProcessing.js +0 -87
- package/lib-esm/postProcessing.js.map +0 -1
- package/lib-esm/postProcessingNMR.d.ts +0 -2
- package/lib-esm/postProcessingNMR.d.ts.map +0 -1
- package/lib-esm/postProcessingNMR.js +0 -92
- package/lib-esm/postProcessingNMR.js.map +0 -1
- package/lib-esm/prepareNtuplesDatatable.d.ts +0 -2
- package/lib-esm/prepareNtuplesDatatable.d.ts.map +0 -1
- package/lib-esm/prepareNtuplesDatatable.js +0 -84
- package/lib-esm/prepareNtuplesDatatable.js.map +0 -1
- package/lib-esm/prepareSpectrum.d.ts +0 -2
- package/lib-esm/prepareSpectrum.d.ts.map +0 -1
- package/lib-esm/prepareSpectrum.js +0 -7
- package/lib-esm/prepareSpectrum.js.map +0 -1
- package/lib-esm/profiling.d.ts +0 -2
- package/lib-esm/profiling.d.ts.map +0 -1
- package/lib-esm/profiling.js +0 -10
- package/lib-esm/profiling.js.map +0 -1
- package/lib-esm/simpleChromatogram.d.ts +0 -2
- package/lib-esm/simpleChromatogram.d.ts.map +0 -1
- package/lib-esm/simpleChromatogram.js +0 -13
- package/lib-esm/simpleChromatogram.js.map +0 -1
- package/src/2d/add2D.js +0 -11
- package/src/2d/convertTo3DZ.js +0 -55
- package/src/2d/generateContourLines.js +0 -166
- package/src/complexChromatogram.js +0 -49
- package/src/convert.js +0 -412
- package/src/convertToFloatArray.js +0 -7
- package/src/createTree.js +0 -100
- package/src/index.js +0 -2
- package/src/parse/fastParseXYData.js +0 -175
- package/src/parse/parsePeakTable.js +0 -69
- package/src/parse/parseXYA.js +0 -50
- package/src/postProcessing.js +0 -93
- package/src/postProcessingNMR.js +0 -99
- package/src/prepareNtuplesDatatable.js +0 -85
- package/src/prepareSpectrum.js +0 -4
- package/src/profiling.js +0 -9
- package/src/simpleChromatogram.js +0 -12
package/src/convert.js
DELETED
|
@@ -1,412 +0,0 @@
|
|
|
1
|
-
import { parseString } from 'dynamic-typing';
|
|
2
|
-
import { ensureString } from 'ensure-string';
|
|
3
|
-
|
|
4
|
-
import { isMSField, convertMSFieldToLabel } from './complexChromatogram';
|
|
5
|
-
import convertToFloatArray from './convertToFloatArray';
|
|
6
|
-
import fastParseXYData from './parse/fastParseXYData';
|
|
7
|
-
import parsePeakTable from './parse/parsePeakTable';
|
|
8
|
-
import parseXYA from './parse/parseXYA';
|
|
9
|
-
import postProcessing from './postProcessing';
|
|
10
|
-
import prepareNtuplesDatatable from './prepareNtuplesDatatable';
|
|
11
|
-
import prepareSpectrum from './prepareSpectrum';
|
|
12
|
-
import profiling from './profiling';
|
|
13
|
-
|
|
14
|
-
// the following RegExp can only be used for XYdata, some peakTables have values with a "E-5" ...
|
|
15
|
-
const ntuplesSeparatorRegExp = /[ \t]*,[ \t]*/;
|
|
16
|
-
|
|
17
|
-
const defaultOptions = {
|
|
18
|
-
keepRecordsRegExp: /^$/,
|
|
19
|
-
canonicDataLabels: true,
|
|
20
|
-
canonicMetadataLabels: false,
|
|
21
|
-
dynamicTyping: true,
|
|
22
|
-
withoutXY: false,
|
|
23
|
-
chromatogram: false,
|
|
24
|
-
keepSpectra: false,
|
|
25
|
-
noContour: false,
|
|
26
|
-
nbContourLevels: 7,
|
|
27
|
-
noiseMultiplier: 5,
|
|
28
|
-
profiling: false,
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Conversion options
|
|
33
|
-
* @typedef {object} ConvertOptions
|
|
34
|
-
* @property {RegExp} [keepRecordsRegExp=/^$/] - By default we don't keep meta information.
|
|
35
|
-
* @property {boolean} [canonicDataLabels=true] - Canonize the Labels (uppercase without symbol).
|
|
36
|
-
* @property {boolean} [canonicMetadataLabels=false] - Canonize the metadata Labels (uppercase without symbol).
|
|
37
|
-
* @property {boolean} [dynamicTyping=false] - Convert numbers to Number.
|
|
38
|
-
* @property {boolean} [withoutXY=false] - Remove the XY data.
|
|
39
|
-
* @property {boolean} [chromatogram=false] - Special post-processing for GC / HPLC / MS.
|
|
40
|
-
* @property {boolean} [keepSpectra=false] - Force to keep the spectra in case of 2D.
|
|
41
|
-
* @property {boolean} [noContour=false] - Don't calculate countour in case of 2D.
|
|
42
|
-
* @property {number} [nbContourLevels=7] - Number of positive / negative contour levels to calculate.
|
|
43
|
-
* @property {number} [noiseMultiplier=5] - Define for 2D the level as 5 times the median as default.
|
|
44
|
-
* @property {import('cheminfo-types').Logger} [logger] - A logger like 'pino'
|
|
45
|
-
* @property {boolean} [profiling=false] - Add profiling information.
|
|
46
|
-
*/
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
*
|
|
50
|
-
* @typedef {object} Ntuples
|
|
51
|
-
* @property {string[]} [varname]
|
|
52
|
-
* @property {string[]} [symbol]
|
|
53
|
-
* @property {string[]} [vartype]
|
|
54
|
-
* @property {string[]} [varform]
|
|
55
|
-
* @property {number[]} [vardim]
|
|
56
|
-
* @property {string[]} [units]
|
|
57
|
-
* @property {number[]} [factor]
|
|
58
|
-
* @property {number[]} [first]
|
|
59
|
-
* @property {number[]} [last]
|
|
60
|
-
* @property {number[]} [min]
|
|
61
|
-
* @property {number[]} [max]
|
|
62
|
-
* @property {string[]} [nucleus]
|
|
63
|
-
*/
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* @typedef { Record<string, any> } Spectrum
|
|
67
|
-
* @property {Record<string, number[]>} [data]
|
|
68
|
-
* @property {number} [firstX] - first X value
|
|
69
|
-
* @property {number} [lastX] - last X value
|
|
70
|
-
* @property {number} [deltaX] - distance between 2 consecutive x axis values
|
|
71
|
-
* @property {number} [yFactor] - y axis scaling factor
|
|
72
|
-
* @property {number} [xFactor] - x axis scaling factor
|
|
73
|
-
* @property {number} [nbPoints] - Number of points
|
|
74
|
-
*/
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
*
|
|
78
|
-
* @typedef {object} MinMax
|
|
79
|
-
* @property {number[][]} [z]
|
|
80
|
-
* @property {number} minX
|
|
81
|
-
* @property {number} maxX
|
|
82
|
-
* @property {number} minY
|
|
83
|
-
* @property {number} maxY
|
|
84
|
-
* @property {number} minZ
|
|
85
|
-
* @property {number} maxZ
|
|
86
|
-
* @property {number} median
|
|
87
|
-
*/
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
*
|
|
91
|
-
* @typedef {object} Entry
|
|
92
|
-
* @property {Spectrum[]} spectra
|
|
93
|
-
* @property {Ntuples} ntuples
|
|
94
|
-
* @property {object} meta
|
|
95
|
-
* @property {object} info
|
|
96
|
-
* @property {object} tmp
|
|
97
|
-
* @property {string} [title]
|
|
98
|
-
* @property {string} [dataType]
|
|
99
|
-
* @property {string} [dataClass]
|
|
100
|
-
* @property {boolean} [twoD]
|
|
101
|
-
* @property {MinMax} [minMax]
|
|
102
|
-
*/
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
*
|
|
106
|
-
* @typedef { object } ConvertResult
|
|
107
|
-
* @property { object[] | boolean } profiling
|
|
108
|
-
* @property { string[] } logs
|
|
109
|
-
* @property { object[] } entries
|
|
110
|
-
* @property { Entry[] } flatten
|
|
111
|
-
*/
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Parse a jcamp.
|
|
115
|
-
* The data can be provide as a string or array buffer. In this later case
|
|
116
|
-
* we will convert it first to a string before parsing.
|
|
117
|
-
* @param {string|ArrayBuffer|Uint8Array} jcamp
|
|
118
|
-
* @param {ConvertOptions} [options]
|
|
119
|
-
* @returns {ConvertResult}
|
|
120
|
-
*/
|
|
121
|
-
export function convert(jcamp, options = {}) {
|
|
122
|
-
jcamp = ensureString(jcamp);
|
|
123
|
-
options = { ...defaultOptions, ...options };
|
|
124
|
-
|
|
125
|
-
options.logger?.debug('Starting jcamp conversion');
|
|
126
|
-
|
|
127
|
-
options.wantXY = !options.withoutXY;
|
|
128
|
-
options.start = Date.now();
|
|
129
|
-
|
|
130
|
-
let entriesFlat = [];
|
|
131
|
-
|
|
132
|
-
let result = {
|
|
133
|
-
profiling: options.profiling ? [] : false,
|
|
134
|
-
logs: [],
|
|
135
|
-
entries: [],
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
let tmpResult = { children: [] };
|
|
139
|
-
let currentEntry = tmpResult;
|
|
140
|
-
let parentsStack = [];
|
|
141
|
-
|
|
142
|
-
let spectrum = {};
|
|
143
|
-
|
|
144
|
-
if (typeof jcamp !== 'string') {
|
|
145
|
-
throw new TypeError('the JCAMP should be a string');
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
profiling(result, 'Before split to LDRS', options);
|
|
149
|
-
|
|
150
|
-
let ldrs = jcamp.replace(/[\r\n]+##/g, '\n##').split('\n##');
|
|
151
|
-
|
|
152
|
-
profiling(result, 'Split to LDRS', options);
|
|
153
|
-
|
|
154
|
-
if (ldrs[0]) ldrs[0] = ldrs[0].replace(/^[\r\n ]*##/, '');
|
|
155
|
-
|
|
156
|
-
for (let ldr of ldrs) {
|
|
157
|
-
// This is a new LDR
|
|
158
|
-
let position = ldr.indexOf('=');
|
|
159
|
-
let dataLabel = position > 0 ? ldr.substring(0, position) : ldr;
|
|
160
|
-
let dataValue = position > 0 ? ldr.substring(position + 1).trim() : '';
|
|
161
|
-
|
|
162
|
-
let canonicDataLabel = dataLabel.replace(/[_ -]/g, '').toUpperCase();
|
|
163
|
-
|
|
164
|
-
if (canonicDataLabel === 'DATATABLE') {
|
|
165
|
-
let endLine = dataValue.indexOf('\n');
|
|
166
|
-
if (endLine === -1) endLine = dataValue.indexOf('\r');
|
|
167
|
-
if (endLine > 0) {
|
|
168
|
-
// ##DATA TABLE= (X++(I..I)), XYDATA
|
|
169
|
-
// We need to find the variables
|
|
170
|
-
|
|
171
|
-
let infos = dataValue.substring(0, endLine).split(/[ ,;\t]+/);
|
|
172
|
-
prepareNtuplesDatatable(currentEntry, spectrum, infos[0]);
|
|
173
|
-
|
|
174
|
-
spectrum.datatable = infos[0];
|
|
175
|
-
if (infos[1] && infos[1].indexOf('PEAKS') > -1) {
|
|
176
|
-
canonicDataLabel = 'PEAKTABLE';
|
|
177
|
-
} else if (
|
|
178
|
-
infos[1] &&
|
|
179
|
-
(infos[1].indexOf('XYDATA') || infos[0].indexOf('++') > 0)
|
|
180
|
-
) {
|
|
181
|
-
canonicDataLabel = 'XYDATA';
|
|
182
|
-
if (spectrum.nbPoints) {
|
|
183
|
-
spectrum.deltaX =
|
|
184
|
-
(spectrum.lastX - spectrum.firstX) / (spectrum.nbPoints - 1);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
if (canonicDataLabel === 'XYDATA') {
|
|
191
|
-
if (options.wantXY) {
|
|
192
|
-
prepareSpectrum(spectrum);
|
|
193
|
-
// well apparently we should still consider it is a PEAK TABLE if there are no '++' after
|
|
194
|
-
if (dataValue.match(/.*\+\+.*/)) {
|
|
195
|
-
// ex: (X++(Y..Y))
|
|
196
|
-
if (spectrum.nbPoints) {
|
|
197
|
-
spectrum.deltaX =
|
|
198
|
-
(spectrum.lastX - spectrum.firstX) / (spectrum.nbPoints - 1);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
fastParseXYData(spectrum, dataValue, result);
|
|
202
|
-
} else {
|
|
203
|
-
parsePeakTable(spectrum, dataValue, result);
|
|
204
|
-
}
|
|
205
|
-
currentEntry.spectra.push(spectrum);
|
|
206
|
-
spectrum = {};
|
|
207
|
-
}
|
|
208
|
-
continue;
|
|
209
|
-
} else if (canonicDataLabel === 'PEAKTABLE') {
|
|
210
|
-
if (options.wantXY) {
|
|
211
|
-
prepareSpectrum(spectrum);
|
|
212
|
-
parsePeakTable(spectrum, dataValue, result);
|
|
213
|
-
currentEntry.spectra.push(spectrum);
|
|
214
|
-
spectrum = {};
|
|
215
|
-
}
|
|
216
|
-
continue;
|
|
217
|
-
}
|
|
218
|
-
if (canonicDataLabel === 'PEAKASSIGNMENTS') {
|
|
219
|
-
if (options.wantXY) {
|
|
220
|
-
if (dataValue.match(/.*([^A-Z]*).*/)) {
|
|
221
|
-
// ex: (XYA)
|
|
222
|
-
parseXYA(spectrum, dataValue);
|
|
223
|
-
}
|
|
224
|
-
currentEntry.spectra.push(spectrum);
|
|
225
|
-
spectrum = {};
|
|
226
|
-
}
|
|
227
|
-
continue;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
if (canonicDataLabel === 'TITLE') {
|
|
231
|
-
let parentEntry = currentEntry;
|
|
232
|
-
if (!parentEntry.children) {
|
|
233
|
-
parentEntry.children = [];
|
|
234
|
-
}
|
|
235
|
-
currentEntry = {
|
|
236
|
-
spectra: [],
|
|
237
|
-
ntuples: {},
|
|
238
|
-
info: {},
|
|
239
|
-
meta: {},
|
|
240
|
-
tmp: {}, // tmp information we need to keep for postprocessing
|
|
241
|
-
};
|
|
242
|
-
parentEntry.children.push(currentEntry);
|
|
243
|
-
parentsStack.push(parentEntry);
|
|
244
|
-
entriesFlat.push(currentEntry);
|
|
245
|
-
currentEntry.title = dataValue;
|
|
246
|
-
} else if (canonicDataLabel === 'DATATYPE') {
|
|
247
|
-
currentEntry.dataType = dataValue;
|
|
248
|
-
if (dataValue.match(/(^nd|\snd\s)/i)) {
|
|
249
|
-
currentEntry.twoD = true;
|
|
250
|
-
}
|
|
251
|
-
} else if (canonicDataLabel === 'NTUPLES') {
|
|
252
|
-
if (dataValue.match(/(^nd|\snd\s)/i)) {
|
|
253
|
-
currentEntry.twoD = true;
|
|
254
|
-
}
|
|
255
|
-
} else if (canonicDataLabel === 'DATACLASS') {
|
|
256
|
-
currentEntry.dataClass = dataValue;
|
|
257
|
-
} else if (canonicDataLabel === 'XUNITS') {
|
|
258
|
-
spectrum.xUnits = dataValue;
|
|
259
|
-
} else if (canonicDataLabel === 'YUNITS') {
|
|
260
|
-
spectrum.yUnits = dataValue;
|
|
261
|
-
} else if (canonicDataLabel === 'FIRSTX') {
|
|
262
|
-
spectrum.firstX = Number(dataValue);
|
|
263
|
-
} else if (canonicDataLabel === 'LASTX') {
|
|
264
|
-
spectrum.lastX = Number(dataValue);
|
|
265
|
-
} else if (canonicDataLabel === 'FIRSTY') {
|
|
266
|
-
spectrum.firstY = Number(dataValue);
|
|
267
|
-
} else if (canonicDataLabel === 'LASTY') {
|
|
268
|
-
spectrum.lastY = Number(dataValue);
|
|
269
|
-
} else if (canonicDataLabel === 'NPOINTS') {
|
|
270
|
-
spectrum.nbPoints = Number(dataValue);
|
|
271
|
-
} else if (canonicDataLabel === 'XFACTOR') {
|
|
272
|
-
spectrum.xFactor = Number(dataValue);
|
|
273
|
-
} else if (canonicDataLabel === 'YFACTOR') {
|
|
274
|
-
spectrum.yFactor = Number(dataValue);
|
|
275
|
-
} else if (canonicDataLabel === 'MAXX') {
|
|
276
|
-
spectrum.maxX = Number(dataValue);
|
|
277
|
-
} else if (canonicDataLabel === 'MINX') {
|
|
278
|
-
spectrum.minX = Number(dataValue);
|
|
279
|
-
} else if (canonicDataLabel === 'MAXY') {
|
|
280
|
-
spectrum.maxY = Number(dataValue);
|
|
281
|
-
} else if (canonicDataLabel === 'MINY') {
|
|
282
|
-
spectrum.minY = Number(dataValue);
|
|
283
|
-
} else if (canonicDataLabel === 'DELTAX') {
|
|
284
|
-
spectrum.deltaX = Number(dataValue);
|
|
285
|
-
} else if (
|
|
286
|
-
canonicDataLabel === '.OBSERVEFREQUENCY' ||
|
|
287
|
-
canonicDataLabel === '$SFO1'
|
|
288
|
-
) {
|
|
289
|
-
if (!spectrum.observeFrequency) {
|
|
290
|
-
spectrum.observeFrequency = Number(dataValue);
|
|
291
|
-
}
|
|
292
|
-
} else if (canonicDataLabel === '.OBSERVENUCLEUS') {
|
|
293
|
-
if (!spectrum.xType) {
|
|
294
|
-
currentEntry.xType = dataValue.replace(/[^a-zA-Z0-9]/g, '');
|
|
295
|
-
}
|
|
296
|
-
} else if (canonicDataLabel === '$OFFSET') {
|
|
297
|
-
// OFFSET for Bruker spectra
|
|
298
|
-
currentEntry.shiftOffsetNum = 0;
|
|
299
|
-
if (!spectrum.shiftOffsetVal) {
|
|
300
|
-
spectrum.shiftOffsetVal = Number(dataValue);
|
|
301
|
-
}
|
|
302
|
-
} else if (canonicDataLabel === '$REFERENCEPOINT') {
|
|
303
|
-
// OFFSET for Varian spectra
|
|
304
|
-
// if we activate this part it does not work for ACD specmanager
|
|
305
|
-
// } else if (canonicDataLabel=='.SHIFTREFERENCE') { // OFFSET FOR Bruker Spectra
|
|
306
|
-
// var parts = dataValue.split(/ *, */);
|
|
307
|
-
// currentEntry.shiftOffsetNum = parseInt(parts[2].trim());
|
|
308
|
-
// spectrum.shiftOffsetVal = Number(parts[3].trim());
|
|
309
|
-
} else if (canonicDataLabel === 'VARNAME') {
|
|
310
|
-
currentEntry.ntuples.varname = dataValue.split(ntuplesSeparatorRegExp);
|
|
311
|
-
} else if (canonicDataLabel === 'SYMBOL') {
|
|
312
|
-
currentEntry.ntuples.symbol = dataValue.split(ntuplesSeparatorRegExp);
|
|
313
|
-
} else if (canonicDataLabel === 'VARTYPE') {
|
|
314
|
-
currentEntry.ntuples.vartype = dataValue.split(ntuplesSeparatorRegExp);
|
|
315
|
-
} else if (canonicDataLabel === 'VARFORM') {
|
|
316
|
-
currentEntry.ntuples.varform = dataValue.split(ntuplesSeparatorRegExp);
|
|
317
|
-
} else if (canonicDataLabel === 'VARDIM') {
|
|
318
|
-
currentEntry.ntuples.vardim = convertToFloatArray(
|
|
319
|
-
dataValue.split(ntuplesSeparatorRegExp),
|
|
320
|
-
);
|
|
321
|
-
} else if (canonicDataLabel === 'UNITS') {
|
|
322
|
-
currentEntry.ntuples.units = dataValue.split(ntuplesSeparatorRegExp);
|
|
323
|
-
} else if (canonicDataLabel === 'FACTOR') {
|
|
324
|
-
currentEntry.ntuples.factor = convertToFloatArray(
|
|
325
|
-
dataValue.split(ntuplesSeparatorRegExp),
|
|
326
|
-
);
|
|
327
|
-
} else if (canonicDataLabel === 'FIRST') {
|
|
328
|
-
currentEntry.ntuples.first = convertToFloatArray(
|
|
329
|
-
dataValue.split(ntuplesSeparatorRegExp),
|
|
330
|
-
);
|
|
331
|
-
} else if (canonicDataLabel === 'LAST') {
|
|
332
|
-
currentEntry.ntuples.last = convertToFloatArray(
|
|
333
|
-
dataValue.split(ntuplesSeparatorRegExp),
|
|
334
|
-
);
|
|
335
|
-
} else if (canonicDataLabel === 'MIN') {
|
|
336
|
-
currentEntry.ntuples.min = convertToFloatArray(
|
|
337
|
-
dataValue.split(ntuplesSeparatorRegExp),
|
|
338
|
-
);
|
|
339
|
-
} else if (canonicDataLabel === 'MAX') {
|
|
340
|
-
currentEntry.ntuples.max = convertToFloatArray(
|
|
341
|
-
dataValue.split(ntuplesSeparatorRegExp),
|
|
342
|
-
);
|
|
343
|
-
} else if (canonicDataLabel === '.NUCLEUS') {
|
|
344
|
-
if (currentEntry.ntuples) {
|
|
345
|
-
currentEntry.ntuples.nucleus = dataValue.split(ntuplesSeparatorRegExp);
|
|
346
|
-
}
|
|
347
|
-
} else if (canonicDataLabel === 'PAGE') {
|
|
348
|
-
spectrum.page = dataValue.trim();
|
|
349
|
-
spectrum.pageValue = Number(dataValue.replace(/^.*=/, ''));
|
|
350
|
-
spectrum.pageSymbol = spectrum.page.replace(/[=].*/, '');
|
|
351
|
-
} else if (canonicDataLabel === 'RETENTIONTIME') {
|
|
352
|
-
spectrum.pageValue = Number(dataValue);
|
|
353
|
-
} else if (isMSField(canonicDataLabel)) {
|
|
354
|
-
spectrum[convertMSFieldToLabel(canonicDataLabel)] = dataValue;
|
|
355
|
-
} else if (canonicDataLabel === 'SAMPLEDESCRIPTION') {
|
|
356
|
-
spectrum.sampleDescription = dataValue;
|
|
357
|
-
} else if (canonicDataLabel.startsWith('$NUC')) {
|
|
358
|
-
if (!currentEntry.tmp[canonicDataLabel] && !dataValue.includes('off')) {
|
|
359
|
-
currentEntry.tmp[canonicDataLabel] = dataValue.replace(/[<>]/g, '');
|
|
360
|
-
}
|
|
361
|
-
} else if (canonicDataLabel === 'END') {
|
|
362
|
-
currentEntry = parentsStack.pop();
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
if (
|
|
366
|
-
currentEntry &&
|
|
367
|
-
currentEntry.info &&
|
|
368
|
-
currentEntry.meta &&
|
|
369
|
-
canonicDataLabel.match(options.keepRecordsRegExp)
|
|
370
|
-
) {
|
|
371
|
-
let value = dataValue.trim();
|
|
372
|
-
let target, label;
|
|
373
|
-
if (dataLabel.startsWith('$')) {
|
|
374
|
-
label = options.canonicMetadataLabels
|
|
375
|
-
? canonicDataLabel.substring(1)
|
|
376
|
-
: dataLabel.substring(1);
|
|
377
|
-
target = currentEntry.meta;
|
|
378
|
-
} else {
|
|
379
|
-
label = options.canonicDataLabels ? canonicDataLabel : dataLabel;
|
|
380
|
-
target = currentEntry.info;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
if (options.dynamicTyping) {
|
|
384
|
-
value = parseString(value);
|
|
385
|
-
}
|
|
386
|
-
if (target[label]) {
|
|
387
|
-
if (!Array.isArray(target[label])) {
|
|
388
|
-
target[label] = [target[label]];
|
|
389
|
-
}
|
|
390
|
-
target[label].push(value);
|
|
391
|
-
} else {
|
|
392
|
-
target[label] = value;
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
profiling(result, 'Finished parsing', options);
|
|
398
|
-
|
|
399
|
-
postProcessing(entriesFlat, result, options);
|
|
400
|
-
|
|
401
|
-
profiling(result, 'Total time', options);
|
|
402
|
-
|
|
403
|
-
/*
|
|
404
|
-
if (result.children && result.children.length>0) {
|
|
405
|
-
result = { ...result, ...result.children[0] };
|
|
406
|
-
}
|
|
407
|
-
*/
|
|
408
|
-
result.entries = tmpResult.children;
|
|
409
|
-
result.flatten = entriesFlat;
|
|
410
|
-
|
|
411
|
-
return result;
|
|
412
|
-
}
|
package/src/createTree.js
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { ensureString } from 'ensure-string';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
*
|
|
5
|
-
* @typedef {object} CreateTreeOptions
|
|
6
|
-
* @property {boolean} [flatten=false]
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
*
|
|
11
|
-
* @typedef {object} Tree
|
|
12
|
-
* @property {string} title
|
|
13
|
-
* @property {string} jcamp
|
|
14
|
-
* @property {Tree[]} [children]
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Parse the jcamp to extract the structure as a tree.
|
|
19
|
-
*
|
|
20
|
-
* @param {string|ArrayBuffer|Uint8Array} jcamp
|
|
21
|
-
* @param {CreateTreeOptions} [options={}]
|
|
22
|
-
* @returns {Tree[]}
|
|
23
|
-
*/
|
|
24
|
-
export function createTree(jcamp, options = {}) {
|
|
25
|
-
jcamp = ensureString(jcamp);
|
|
26
|
-
const { flatten = false } = options;
|
|
27
|
-
if (typeof jcamp !== 'string') {
|
|
28
|
-
throw new TypeError('the JCAMP should be a string');
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
let lines = jcamp.split(/[\r\n]+/);
|
|
32
|
-
let flat = [];
|
|
33
|
-
let stack = [];
|
|
34
|
-
let result = [];
|
|
35
|
-
let current;
|
|
36
|
-
let ntupleLevel = 0;
|
|
37
|
-
|
|
38
|
-
let spaces = jcamp.includes('## ');
|
|
39
|
-
|
|
40
|
-
for (let i = 0; i < lines.length; i++) {
|
|
41
|
-
let line = lines[i];
|
|
42
|
-
let labelLine = spaces ? line.replace(/ /g, '') : line;
|
|
43
|
-
|
|
44
|
-
if (labelLine.substring(0, 9) === '##NTUPLES') {
|
|
45
|
-
ntupleLevel++;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (labelLine.substring(0, 7) === '##TITLE') {
|
|
49
|
-
let title = [labelLine.substring(8).trim()];
|
|
50
|
-
for (let j = i + 1; j < lines.length; j++) {
|
|
51
|
-
if (lines[j].startsWith('##')) {
|
|
52
|
-
break;
|
|
53
|
-
} else {
|
|
54
|
-
title.push(lines[j].trim());
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
stack.push({
|
|
58
|
-
title: title.join('\n'),
|
|
59
|
-
jcamp: `${line}\n`,
|
|
60
|
-
children: [],
|
|
61
|
-
});
|
|
62
|
-
current = stack[stack.length - 1];
|
|
63
|
-
flat.push(current);
|
|
64
|
-
} else if (labelLine.substring(0, 5) === '##END' && ntupleLevel === 0) {
|
|
65
|
-
current.jcamp += `${line}\n`;
|
|
66
|
-
let finished = stack.pop();
|
|
67
|
-
if (stack.length !== 0) {
|
|
68
|
-
current = stack[stack.length - 1];
|
|
69
|
-
current.children.push(finished);
|
|
70
|
-
} else {
|
|
71
|
-
current = undefined;
|
|
72
|
-
result.push(finished);
|
|
73
|
-
}
|
|
74
|
-
} else if (current && current.jcamp) {
|
|
75
|
-
current.jcamp += `${line}\n`;
|
|
76
|
-
let match = labelLine.match(/^##(.*?)=(.+)/);
|
|
77
|
-
if (match) {
|
|
78
|
-
let canonicDataLabel = match[1].replace(/[ _-]/g, '').toUpperCase();
|
|
79
|
-
if (canonicDataLabel === 'DATATYPE') {
|
|
80
|
-
current.dataType = match[2].trim();
|
|
81
|
-
}
|
|
82
|
-
if (canonicDataLabel === 'DATACLASS') {
|
|
83
|
-
current.dataClass = match[2].trim();
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (labelLine.substring(0, 5) === '##END' && ntupleLevel > 0) {
|
|
89
|
-
ntupleLevel--;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
if (flatten) {
|
|
93
|
-
flat.forEach((entry) => {
|
|
94
|
-
entry.children = undefined;
|
|
95
|
-
});
|
|
96
|
-
return flat;
|
|
97
|
-
} else {
|
|
98
|
-
return result;
|
|
99
|
-
}
|
|
100
|
-
}
|
package/src/index.js
DELETED
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
export default function fastParseXYData(spectrum, value) {
|
|
2
|
-
// TODO need to deal with result
|
|
3
|
-
// console.log(value);
|
|
4
|
-
// we check if deltaX is defined otherwise we calculate it
|
|
5
|
-
|
|
6
|
-
let yFactor = spectrum.yFactor;
|
|
7
|
-
let deltaX = spectrum.deltaX;
|
|
8
|
-
|
|
9
|
-
spectrum.isXYdata = true;
|
|
10
|
-
let currentData = { x: [], y: [] };
|
|
11
|
-
spectrum.data = currentData;
|
|
12
|
-
|
|
13
|
-
let currentX = spectrum.firstX;
|
|
14
|
-
let currentY = spectrum.firstY;
|
|
15
|
-
|
|
16
|
-
// we skip the first line
|
|
17
|
-
//
|
|
18
|
-
let endLine = false;
|
|
19
|
-
let ascii;
|
|
20
|
-
let i = 0;
|
|
21
|
-
for (; i < value.length; i++) {
|
|
22
|
-
ascii = value.charCodeAt(i);
|
|
23
|
-
if (ascii === 13 || ascii === 10) {
|
|
24
|
-
endLine = true;
|
|
25
|
-
} else if (endLine) {
|
|
26
|
-
break;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// we proceed taking the i after the first line
|
|
31
|
-
let newLine = true;
|
|
32
|
-
let isDifference = false;
|
|
33
|
-
let isLastDifference = false;
|
|
34
|
-
let lastDifference = 0;
|
|
35
|
-
let isDuplicate = false;
|
|
36
|
-
let inComment = false;
|
|
37
|
-
let currentValue = 0; // can be a difference or a duplicate
|
|
38
|
-
let lastValue = 0; // must be the real last value
|
|
39
|
-
let isNegative = false;
|
|
40
|
-
let inValue = false;
|
|
41
|
-
let skipFirstValue = false;
|
|
42
|
-
let decimalPosition = 0;
|
|
43
|
-
for (; i <= value.length; i++) {
|
|
44
|
-
if (i === value.length) ascii = 13;
|
|
45
|
-
else ascii = value.charCodeAt(i);
|
|
46
|
-
if (inComment) {
|
|
47
|
-
// we should ignore the text if we are after $$
|
|
48
|
-
if (ascii === 13 || ascii === 10) {
|
|
49
|
-
newLine = true;
|
|
50
|
-
inComment = false;
|
|
51
|
-
}
|
|
52
|
-
} else {
|
|
53
|
-
// when is it a new value ?
|
|
54
|
-
// when it is not a digit, . or comma
|
|
55
|
-
// it is a number that is either new or we continue
|
|
56
|
-
// eslint-disable-next-line no-lonely-if
|
|
57
|
-
if (ascii <= 57 && ascii >= 48) {
|
|
58
|
-
// a number
|
|
59
|
-
inValue = true;
|
|
60
|
-
if (decimalPosition > 0) {
|
|
61
|
-
currentValue += (ascii - 48) / Math.pow(10, decimalPosition++);
|
|
62
|
-
} else {
|
|
63
|
-
currentValue *= 10;
|
|
64
|
-
currentValue += ascii - 48;
|
|
65
|
-
}
|
|
66
|
-
} else if (ascii === 44 || ascii === 46) {
|
|
67
|
-
// a "," or "."
|
|
68
|
-
inValue = true;
|
|
69
|
-
decimalPosition++;
|
|
70
|
-
} else {
|
|
71
|
-
if (inValue) {
|
|
72
|
-
// need to process the previous value
|
|
73
|
-
if (newLine) {
|
|
74
|
-
newLine = false; // we don't check the X value
|
|
75
|
-
// console.log("NEW LINE",isDifference, lastDifference);
|
|
76
|
-
// if new line and lastDifference, the first value is just a check !
|
|
77
|
-
// that we don't check ...
|
|
78
|
-
if (isLastDifference) skipFirstValue = true;
|
|
79
|
-
} else {
|
|
80
|
-
// need to deal with duplicate and differences
|
|
81
|
-
// eslint-disable-next-line no-lonely-if
|
|
82
|
-
if (skipFirstValue) {
|
|
83
|
-
skipFirstValue = false;
|
|
84
|
-
} else {
|
|
85
|
-
if (isDifference) {
|
|
86
|
-
lastDifference = isNegative ? 0 - currentValue : currentValue;
|
|
87
|
-
isLastDifference = true;
|
|
88
|
-
isDifference = false;
|
|
89
|
-
} else if (!isDuplicate) {
|
|
90
|
-
lastValue = isNegative ? 0 - currentValue : currentValue;
|
|
91
|
-
}
|
|
92
|
-
let duplicate = isDuplicate ? currentValue - 1 : 1;
|
|
93
|
-
for (let j = 0; j < duplicate; j++) {
|
|
94
|
-
if (isLastDifference) {
|
|
95
|
-
currentY += lastDifference;
|
|
96
|
-
} else {
|
|
97
|
-
currentY = lastValue;
|
|
98
|
-
}
|
|
99
|
-
currentData.x.push(currentX);
|
|
100
|
-
currentData.y.push(currentY * yFactor);
|
|
101
|
-
currentX += deltaX;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
isNegative = false;
|
|
106
|
-
currentValue = 0;
|
|
107
|
-
decimalPosition = 0;
|
|
108
|
-
inValue = false;
|
|
109
|
-
isDuplicate = false;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// positive SQZ digits @ A B C D E F G H I (ascii 64-73)
|
|
113
|
-
if (ascii < 74 && ascii > 63) {
|
|
114
|
-
inValue = true;
|
|
115
|
-
isLastDifference = false;
|
|
116
|
-
currentValue = ascii - 64;
|
|
117
|
-
} else if (ascii > 96 && ascii < 106) {
|
|
118
|
-
// negative SQZ digits a b c d e f g h i (ascii 97-105)
|
|
119
|
-
inValue = true;
|
|
120
|
-
isLastDifference = false;
|
|
121
|
-
currentValue = ascii - 96;
|
|
122
|
-
isNegative = true;
|
|
123
|
-
} else if (ascii === 115) {
|
|
124
|
-
// DUP digits S T U V W X Y Z s (ascii 83-90, 115)
|
|
125
|
-
inValue = true;
|
|
126
|
-
isDuplicate = true;
|
|
127
|
-
currentValue = 9;
|
|
128
|
-
} else if (ascii > 82 && ascii < 91) {
|
|
129
|
-
inValue = true;
|
|
130
|
-
isDuplicate = true;
|
|
131
|
-
currentValue = ascii - 82;
|
|
132
|
-
} else if (ascii > 73 && ascii < 83) {
|
|
133
|
-
// positive DIF digits % J K L M N O P Q R (ascii 37, 74-82)
|
|
134
|
-
inValue = true;
|
|
135
|
-
isDifference = true;
|
|
136
|
-
currentValue = ascii - 73;
|
|
137
|
-
} else if (ascii > 105 && ascii < 115) {
|
|
138
|
-
// negative DIF digits j k l m n o p q r (ascii 106-114)
|
|
139
|
-
inValue = true;
|
|
140
|
-
isDifference = true;
|
|
141
|
-
currentValue = ascii - 105;
|
|
142
|
-
isNegative = true;
|
|
143
|
-
} else if (ascii === 36 && value.charCodeAt(i + 1) === 36) {
|
|
144
|
-
// $ sign, we need to check the next one
|
|
145
|
-
inValue = true;
|
|
146
|
-
inComment = true;
|
|
147
|
-
} else if (ascii === 37) {
|
|
148
|
-
// positive DIF digits % J K L M N O P Q R (ascii 37, 74-82)
|
|
149
|
-
inValue = true;
|
|
150
|
-
isDifference = true;
|
|
151
|
-
currentValue = 0;
|
|
152
|
-
isNegative = false;
|
|
153
|
-
} else if (ascii === 45) {
|
|
154
|
-
// a "-"
|
|
155
|
-
// check if after there is a number, decimal or comma
|
|
156
|
-
let ascii2 = value.charCodeAt(i + 1);
|
|
157
|
-
if (
|
|
158
|
-
(ascii2 >= 48 && ascii2 <= 57) ||
|
|
159
|
-
ascii2 === 44 ||
|
|
160
|
-
ascii2 === 46
|
|
161
|
-
) {
|
|
162
|
-
inValue = true;
|
|
163
|
-
if (!newLine) isLastDifference = false;
|
|
164
|
-
isNegative = true;
|
|
165
|
-
}
|
|
166
|
-
} else if (ascii === 13 || ascii === 10) {
|
|
167
|
-
newLine = true;
|
|
168
|
-
inComment = false;
|
|
169
|
-
}
|
|
170
|
-
// and now analyse the details ... space or tabulation
|
|
171
|
-
// if "+" we just don't care
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|