@complat/react-spectra-editor 1.7.0 → 1.8.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.
- package/CHANGELOG.md +28 -0
- package/LICENSE +21 -662
- package/README.md +5 -0
- package/dist/__tests__/fixtures/lc_ms_jcamp.js +2329 -0
- package/dist/__tests__/fixtures/lc_ms_jcamp_2.js +2874 -0
- package/dist/__tests__/fixtures/lc_ms_jcamp_mz_chemstation.js +3242 -0
- package/dist/__tests__/fixtures/lc_ms_jcamp_tic_chemstation.js +854 -0
- package/dist/__tests__/fixtures/lc_ms_jcamp_tic_neg.js +1233 -0
- package/dist/__tests__/fixtures/lc_ms_jcamp_tic_pos.js +1233 -0
- package/dist/__tests__/fixtures/lc_ms_jcamp_uvvis.js +48908 -0
- package/dist/__tests__/fixtures/lc_ms_jcamp_uvvis_chemstation.js +15424 -0
- package/dist/__tests__/units/components/cmd_bar/r05_submit_btn.test.js +158 -3
- package/dist/__tests__/units/components/d3_line_rect.test.js +85 -0
- package/dist/__tests__/units/components/d3_multi/multi_focus.test.js +43 -0
- package/dist/__tests__/units/components/hplc_viewer.test.js +123 -0
- package/dist/__tests__/units/components/panel/info.test.js +55 -15
- package/dist/__tests__/units/features/lc-ms/parsing/lcmsCategory.test.js +73 -0
- package/dist/__tests__/units/features/lc-ms/submit/peaks.test.js +310 -0
- package/dist/actions/curve.js +5 -2
- package/dist/actions/hplc_ms.js +66 -0
- package/dist/actions/integration.js +17 -2
- package/dist/actions/ui.js +39 -11
- package/dist/app.js +21 -8
- package/dist/components/cmd_bar/01_viewer.js +15 -11
- package/dist/components/cmd_bar/03_peak.js +25 -16
- package/dist/components/cmd_bar/04_integration.js +116 -17
- package/dist/components/cmd_bar/08_peak_group.js +83 -0
- package/dist/components/cmd_bar/collapsible_toolbar_group.js +101 -0
- package/dist/components/cmd_bar/common.js +4 -3
- package/dist/components/cmd_bar/index.js +76 -18
- package/dist/components/cmd_bar/r01_layout.js +6 -0
- package/dist/components/cmd_bar/r02_scan.js +15 -11
- package/dist/components/cmd_bar/r03_threshold.js +19 -3
- package/dist/components/cmd_bar/r04_submit.js +61 -6
- package/dist/components/cmd_bar/r05_submit_btn.js +60 -13
- package/dist/components/cmd_bar/r06_predict_btn.js +4 -4
- package/dist/components/cmd_bar/r07_wavelength_btn.js +10 -9
- package/dist/components/cmd_bar/r09_detector.js +2 -2
- package/dist/components/cmd_bar/tri_btn.js +4 -1
- package/dist/components/common/draw.js +6 -5
- package/dist/components/d3_line/index.js +70 -15
- package/dist/components/d3_line/line_focus.js +104 -67
- package/dist/components/d3_line_rect/index.js +836 -0
- package/dist/components/d3_line_rect/line_focus.js +526 -0
- package/dist/components/d3_line_rect/multi_focus.js +433 -0
- package/dist/components/d3_line_rect/rect_focus.js +247 -0
- package/dist/components/d3_multi/index.js +154 -163
- package/dist/components/d3_multi/multi_focus.js +117 -68
- package/dist/components/d3_rect/index.js +6 -0
- package/dist/components/d3_rect/rect_focus.js +17 -5
- package/dist/components/hplc_viewer.js +169 -0
- package/dist/components/lc_ms_uv_tools_bar.js +175 -0
- package/dist/components/multi_jcamps_viewer.js +17 -5
- package/dist/components/panel/compare.js +84 -62
- package/dist/components/panel/cyclic_voltamery_data.js +15 -14
- package/dist/components/panel/graph_selection.js +32 -30
- package/dist/components/panel/index.js +28 -22
- package/dist/components/panel/info.js +90 -31
- package/dist/constants/action_type.js +23 -2
- package/dist/constants/list_graph.js +16 -0
- package/dist/constants/list_layout.js +2 -1
- package/dist/constants/list_ui.js +5 -2
- package/dist/features/lc-ms/entities/extractEntityLCMS.js +187 -0
- package/dist/features/lc-ms/parsing/chemstation.js +108 -0
- package/dist/features/lc-ms/parsing/index.js +46 -0
- package/dist/features/lc-ms/parsing/lcmsCategory.js +44 -0
- package/dist/features/lc-ms/parsing/lcmsJcampInfo.js +18 -0
- package/dist/features/lc-ms/parsing/lcmsMsPage.js +241 -0
- package/dist/features/lc-ms/parsing/pageValue.js +27 -0
- package/dist/features/lc-ms/submit/index.js +24 -0
- package/dist/features/lc-ms/submit/peaks.js +66 -0
- package/dist/features/lc-ms/ui/wavelengthSelect.js +54 -0
- package/dist/fn.js +4 -1
- package/dist/helpers/brush.js +74 -19
- package/dist/helpers/calc.js +4 -2
- package/dist/helpers/cfg.js +5 -4
- package/dist/helpers/chem.js +449 -71
- package/dist/helpers/compass.js +181 -17
- package/dist/helpers/extractEntityLCMS.js +24 -0
- package/dist/helpers/extractParams.js +118 -33
- package/dist/helpers/extractPeaksEdit.js +29 -9
- package/dist/helpers/format.js +189 -4
- package/dist/helpers/init.js +25 -5
- package/dist/helpers/integration.js +130 -17
- package/dist/helpers/integration_draft.js +43 -0
- package/dist/helpers/integration_focus.js +155 -0
- package/dist/helpers/integration_jcamp.js +68 -0
- package/dist/helpers/integration_split.js +202 -0
- package/dist/helpers/mount.js +8 -1
- package/dist/helpers/sweep.js +39 -0
- package/dist/index.js +284 -26
- package/dist/layer_content.js +17 -3
- package/dist/layer_init.js +124 -14
- package/dist/layer_prism.js +31 -5
- package/dist/reducers/index.js +3 -1
- package/dist/reducers/reducer_curve.js +54 -36
- package/dist/reducers/reducer_hplc_ms/hydrate.js +289 -0
- package/dist/reducers/reducer_hplc_ms/index.js +122 -0
- package/dist/reducers/reducer_hplc_ms/persistence.js +74 -0
- package/dist/reducers/reducer_hplc_ms/tic.js +70 -0
- package/dist/reducers/reducer_hplc_ms/utils.js +70 -0
- package/dist/reducers/reducer_hplc_ms/uvvis.js +377 -0
- package/dist/reducers/reducer_integration.js +265 -7
- package/dist/reducers/reducer_layout.js +1 -1
- package/dist/reducers/reducer_submit.js +2 -1
- package/dist/reducers/reducer_ui.js +149 -13
- package/dist/reducers/undo_redo_config.js +2 -2
- package/dist/sagas/saga_lcms_ui.js +85 -0
- package/dist/sagas/saga_ui.js +177 -74
- package/dist/setupTests.js +5 -5
- package/package.json +10 -7
package/dist/helpers/format.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
3
|
Object.defineProperty(exports, "__esModule", {
|
|
5
4
|
value: true
|
|
6
5
|
});
|
|
7
6
|
exports.default = void 0;
|
|
8
|
-
var _jcampconverter = _interopRequireDefault(require("jcampconverter"));
|
|
9
7
|
var _converter = require("./converter");
|
|
10
8
|
var _list_layout = require("../constants/list_layout");
|
|
11
9
|
var _multiplicity_calc = require("./multiplicity_calc");
|
|
@@ -25,6 +23,7 @@ const spectraDigit = layout => {
|
|
|
25
23
|
case _list_layout.LIST_LAYOUT.CDS:
|
|
26
24
|
case _list_layout.LIST_LAYOUT.SEC:
|
|
27
25
|
case _list_layout.LIST_LAYOUT.GC:
|
|
26
|
+
case _list_layout.LIST_LAYOUT.LC_MS:
|
|
28
27
|
case _list_layout.LIST_LAYOUT.MS:
|
|
29
28
|
return 0;
|
|
30
29
|
case _list_layout.LIST_LAYOUT.C13:
|
|
@@ -44,6 +43,16 @@ const fixDigit = (input, precision) => {
|
|
|
44
43
|
const output = input || 0.0;
|
|
45
44
|
return output.toFixed(precision);
|
|
46
45
|
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Integer 0–20 for toFixed; invalid input uses fallback.
|
|
49
|
+
* Default 3 preserves legacy cursor precision.
|
|
50
|
+
*/
|
|
51
|
+
const clampDecimalPlaces = (value, fallback = 3) => {
|
|
52
|
+
const n = Number(value);
|
|
53
|
+
if (!Number.isFinite(n)) return fallback;
|
|
54
|
+
return Math.max(0, Math.min(20, Math.trunc(n)));
|
|
55
|
+
};
|
|
47
56
|
const buildData = entity => {
|
|
48
57
|
if (!entity) return {
|
|
49
58
|
isExist: false
|
|
@@ -63,6 +72,28 @@ const toPeakStr = peaks => {
|
|
|
63
72
|
const str = arr.join('#');
|
|
64
73
|
return str;
|
|
65
74
|
};
|
|
75
|
+
const extractUvvisLcmsPeaks = hplcMsSt => {
|
|
76
|
+
if (!hplcMsSt?.uvvis) {
|
|
77
|
+
return '{}';
|
|
78
|
+
}
|
|
79
|
+
const {
|
|
80
|
+
listWaveLength = [],
|
|
81
|
+
spectraList = []
|
|
82
|
+
} = hplcMsSt.uvvis;
|
|
83
|
+
const byWavelength = {};
|
|
84
|
+
spectraList.forEach((spectrum, idx) => {
|
|
85
|
+
const wl = listWaveLength[idx];
|
|
86
|
+
const wlKey = String(Math.round(wl));
|
|
87
|
+
(spectrum.peaks || []).forEach((p, n) => {
|
|
88
|
+
if (!byWavelength[wlKey]) byWavelength[wlKey] = [];
|
|
89
|
+
byWavelength[wlKey].push({
|
|
90
|
+
x: p.x,
|
|
91
|
+
y: p.y
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
return JSON.stringify(byWavelength);
|
|
96
|
+
};
|
|
66
97
|
const spectraOps = {
|
|
67
98
|
[_list_layout.LIST_LAYOUT.PLAIN]: {
|
|
68
99
|
head: '',
|
|
@@ -147,6 +178,10 @@ const spectraOps = {
|
|
|
147
178
|
[_list_layout.LIST_LAYOUT.DLS_INTENSITY]: {
|
|
148
179
|
head: 'DLS',
|
|
149
180
|
tail: '.'
|
|
181
|
+
},
|
|
182
|
+
[_list_layout.LIST_LAYOUT.LC_MS]: {
|
|
183
|
+
head: 'HPLC UV/VIS',
|
|
184
|
+
tail: ''
|
|
150
185
|
}
|
|
151
186
|
};
|
|
152
187
|
const rmRef = (peaks, shift, atIndex = 0) => {
|
|
@@ -158,6 +193,147 @@ const rmRef = (peaks, shift, atIndex = 0) => {
|
|
|
158
193
|
const refValue = selectedShift.ref.value || selectedShift.peak.x;
|
|
159
194
|
return peaks.map(p => (0, _converter.IsSame)(p.x, refValue) ? null : p).filter(r => r != null);
|
|
160
195
|
};
|
|
196
|
+
const isValidLcmsWavelengthLabel = wl => Number.isFinite(wl) && wl > 0;
|
|
197
|
+
const LCMS_INTEGRATION_EXPORT_MODES = ['percent', 'area', 'both'];
|
|
198
|
+
const isLcmsIntegrationExportMode = v => LCMS_INTEGRATION_EXPORT_MODES.includes(v);
|
|
199
|
+
const formatedLCMS = (hplcMsSt, isAscend, decimal, options = {}) => {
|
|
200
|
+
if (!hplcMsSt?.uvvis) {
|
|
201
|
+
return '';
|
|
202
|
+
}
|
|
203
|
+
const {
|
|
204
|
+
lcmsIntegrationsExport: modeOpt,
|
|
205
|
+
includeIntegrationArea = false
|
|
206
|
+
} = options;
|
|
207
|
+
let lcmsIntegrationsExport = modeOpt;
|
|
208
|
+
if (!isLcmsIntegrationExportMode(lcmsIntegrationsExport)) {
|
|
209
|
+
lcmsIntegrationsExport = hplcMsSt?.lcmsIntegrationsExport;
|
|
210
|
+
}
|
|
211
|
+
if (!isLcmsIntegrationExportMode(lcmsIntegrationsExport)) {
|
|
212
|
+
lcmsIntegrationsExport = includeIntegrationArea ? 'both' : 'percent';
|
|
213
|
+
}
|
|
214
|
+
let result = '\n';
|
|
215
|
+
const sections = [];
|
|
216
|
+
const parsedDecimal = Number.isFinite(decimal) ? decimal : Number.parseInt(decimal, 10);
|
|
217
|
+
const resolvedDecimal = Number.isFinite(parsedDecimal) ? parsedDecimal : 3;
|
|
218
|
+
const {
|
|
219
|
+
listWaveLength = [],
|
|
220
|
+
spectraList = []
|
|
221
|
+
} = hplcMsSt.uvvis || {};
|
|
222
|
+
const ms = hplcMsSt.ms || {};
|
|
223
|
+
const tic = hplcMsSt.tic;
|
|
224
|
+
const threshold = hplcMsSt.threshold;
|
|
225
|
+
listWaveLength.forEach((wavelength, idx) => {
|
|
226
|
+
const spectrum = spectraList[idx];
|
|
227
|
+
if (!spectrum) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
const peaks = spectrum.peaks || [];
|
|
231
|
+
const integrations = spectrum.integrations || [];
|
|
232
|
+
const stack = integrations?.[0]?.stack;
|
|
233
|
+
const hasStack = Array.isArray(stack) && stack.length > 0;
|
|
234
|
+
const hasList = !hasStack && Array.isArray(integrations) && integrations.length > 0;
|
|
235
|
+
const hasIntegrations = hasStack || hasList;
|
|
236
|
+
const hasPeaks = peaks.length > 0;
|
|
237
|
+
if (!hasPeaks && !hasIntegrations) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
const lines = [];
|
|
241
|
+
if (isValidLcmsWavelengthLabel(wavelength)) {
|
|
242
|
+
lines.push(`Wavelength ${wavelength} nm:`);
|
|
243
|
+
}
|
|
244
|
+
if (hasPeaks) {
|
|
245
|
+
const sortedPeaks = [...peaks].sort((a, b) => b.y - a.y);
|
|
246
|
+
const maxIntensity = sortedPeaks[0].y || 1;
|
|
247
|
+
const peakLines = sortedPeaks.map(peak => {
|
|
248
|
+
const rt = peak.x.toFixed(resolvedDecimal);
|
|
249
|
+
const percent = (peak.y / maxIntensity * 100).toFixed(1);
|
|
250
|
+
return `${rt} min (${percent}%)`;
|
|
251
|
+
});
|
|
252
|
+
lines.push(`Peaks: ${peakLines.join(', ')}`);
|
|
253
|
+
}
|
|
254
|
+
if (hasIntegrations) {
|
|
255
|
+
const entries = hasStack ? stack : integrations;
|
|
256
|
+
const refAreaCandidate = hasStack ? integrations?.[0]?.refArea : integrations?.[0]?.refArea ?? integrations?.[0]?.area;
|
|
257
|
+
const refArea = refAreaCandidate && refAreaCandidate > 0 ? refAreaCandidate : 1;
|
|
258
|
+
const sortedIntegrations = [...entries].sort((a, b) => a.xL - b.xL);
|
|
259
|
+
const integrationLines = sortedIntegrations.map(integ => {
|
|
260
|
+
const rt = integ.xL.toFixed(resolvedDecimal);
|
|
261
|
+
const area = integ.area || integ.absoluteArea || 0;
|
|
262
|
+
const percent = (area / refArea * 100).toFixed(1);
|
|
263
|
+
const areaStr = Number.isFinite(area) ? area.toExponential(3) : String(area);
|
|
264
|
+
if (lcmsIntegrationsExport === 'area') {
|
|
265
|
+
return `${rt} min (A=${areaStr})`;
|
|
266
|
+
}
|
|
267
|
+
if (lcmsIntegrationsExport === 'both') {
|
|
268
|
+
return `${rt} min (${percent}%, A=${areaStr})`;
|
|
269
|
+
}
|
|
270
|
+
return `${rt} min (${percent}%)`;
|
|
271
|
+
});
|
|
272
|
+
lines.push(`Integrations: ${integrationLines.join(', ')}`);
|
|
273
|
+
}
|
|
274
|
+
sections.push(lines.join('\n'));
|
|
275
|
+
});
|
|
276
|
+
if (sections.length > 0) {
|
|
277
|
+
result = `\n${sections.join('\n\n')}`;
|
|
278
|
+
}
|
|
279
|
+
const polarity = tic?.polarity || 'positive';
|
|
280
|
+
let polarityKey = 'neutral';
|
|
281
|
+
if (polarity === 'negative') {
|
|
282
|
+
polarityKey = 'negative';
|
|
283
|
+
} else if (polarity === 'positive') {
|
|
284
|
+
polarityKey = 'positive';
|
|
285
|
+
}
|
|
286
|
+
let polarityLabel = '';
|
|
287
|
+
if (polarity === 'negative') {
|
|
288
|
+
polarityLabel = '−';
|
|
289
|
+
} else if (polarity === 'positive') {
|
|
290
|
+
polarityLabel = '+';
|
|
291
|
+
}
|
|
292
|
+
if (tic && ms[polarityKey]) {
|
|
293
|
+
const pageValues = Array.isArray(ms[polarityKey].pageValues) ? ms[polarityKey].pageValues : [];
|
|
294
|
+
const peaksByPage = Array.isArray(ms[polarityKey].peaks) ? ms[polarityKey].peaks : [];
|
|
295
|
+
let currentIndex = -1;
|
|
296
|
+
if (Number.isFinite(tic.currentPageValue) && pageValues.length > 0) {
|
|
297
|
+
currentIndex = pageValues.findIndex(value => Number.isFinite(value) && Math.abs(value - tic.currentPageValue) < 1e-6);
|
|
298
|
+
}
|
|
299
|
+
if (Array.isArray(tic[polarityKey]?.data?.x)) {
|
|
300
|
+
const fallbackIndex = tic[polarityKey].data.x.findIndex(x => Math.abs(x - tic.currentPageValue) < 1e-6);
|
|
301
|
+
if (currentIndex < 0) currentIndex = fallbackIndex;
|
|
302
|
+
}
|
|
303
|
+
if (currentIndex >= 0 && peaksByPage[currentIndex]) {
|
|
304
|
+
const peaks = peaksByPage[currentIndex];
|
|
305
|
+
const maxIntensity = Math.max(...peaks.map(p => p.y)) || 1;
|
|
306
|
+
const thresholdValue = threshold?.value != null ? threshold.value : 5;
|
|
307
|
+
const filtered = peaks.filter(peak => peak.y / maxIntensity * 100 >= thresholdValue);
|
|
308
|
+
const sortedPeaks = [...filtered].sort((a, b) => {
|
|
309
|
+
if (isAscend) {
|
|
310
|
+
return parseFloat(a.x) - parseFloat(b.x);
|
|
311
|
+
}
|
|
312
|
+
return parseFloat(b.x) - parseFloat(a.x);
|
|
313
|
+
});
|
|
314
|
+
const label = polarityLabel ? `${polarityLabel}ESI` : 'ESI';
|
|
315
|
+
if (result) {
|
|
316
|
+
result += '\n\n';
|
|
317
|
+
}
|
|
318
|
+
const rtPage = tic?.currentPageValue;
|
|
319
|
+
const rtDecimal = Math.max(resolvedDecimal, 3);
|
|
320
|
+
const rtPart = Number.isFinite(rtPage) ? `RT ${fixDigit(rtPage, rtDecimal)} min, ` : '';
|
|
321
|
+
result += `MS (${label}), ${rtPart}m/z (≥${thresholdValue}%):\n`;
|
|
322
|
+
const lines = sortedPeaks.map(peak => {
|
|
323
|
+
const mass = fixDigit(peak.x, resolvedDecimal);
|
|
324
|
+
const percent = Math.round(peak.y / maxIntensity * 100);
|
|
325
|
+
return `${mass} (${percent}%)`;
|
|
326
|
+
});
|
|
327
|
+
result += ` ${lines.join(', ')}`;
|
|
328
|
+
} else {
|
|
329
|
+
if (result) {
|
|
330
|
+
result += '\n\n';
|
|
331
|
+
}
|
|
332
|
+
result += 'MS: No data for current retention time.\n';
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return result;
|
|
336
|
+
};
|
|
161
337
|
const formatedMS = (peaks, maxY, decimal = 2, isAscend = true) => {
|
|
162
338
|
const ascendFunc = (a, b) => parseFloat(a) - parseFloat(b);
|
|
163
339
|
const descendFunc = (a, b) => parseFloat(b) - parseFloat(a);
|
|
@@ -365,7 +541,8 @@ const peaksBody = ({
|
|
|
365
541
|
integration,
|
|
366
542
|
atIndex = 0,
|
|
367
543
|
waveLength,
|
|
368
|
-
temperature
|
|
544
|
+
temperature,
|
|
545
|
+
hplcMsSt = null
|
|
369
546
|
}) => {
|
|
370
547
|
const result = rmShiftFromPeaks(peaks, shift, atIndex);
|
|
371
548
|
const ascendFunc = (a, b) => parseFloat(a.x) - parseFloat(b.x);
|
|
@@ -373,6 +550,9 @@ const peaksBody = ({
|
|
|
373
550
|
const sortFunc = isAscend ? ascendFunc : descendFunc;
|
|
374
551
|
const ordered = result.sort(sortFunc);
|
|
375
552
|
const maxY = Math.max(...ordered.map(o => o.y));
|
|
553
|
+
if (layout === _list_layout.LIST_LAYOUT.LC_MS) {
|
|
554
|
+
return formatedLCMS(hplcMsSt, isAscend, decimal);
|
|
555
|
+
}
|
|
376
556
|
if (layout === _list_layout.LIST_LAYOUT.MS) {
|
|
377
557
|
return formatedMS(ordered, maxY, decimal, isAscend);
|
|
378
558
|
}
|
|
@@ -445,6 +625,7 @@ const isCyclicVoltaLayout = layoutSt => _list_layout.LIST_LAYOUT.CYCLIC_VOLTAMME
|
|
|
445
625
|
const isCDSLayout = layoutSt => _list_layout.LIST_LAYOUT.CDS === layoutSt;
|
|
446
626
|
const isSECLayout = layoutSt => _list_layout.LIST_LAYOUT.SEC === layoutSt;
|
|
447
627
|
const isGCLayout = layoutSt => _list_layout.LIST_LAYOUT.GC === layoutSt;
|
|
628
|
+
const isLCMsLayout = layoutSt => _list_layout.LIST_LAYOUT.LC_MS === layoutSt;
|
|
448
629
|
const isEmWaveLayout = layoutSt => [_list_layout.LIST_LAYOUT.IR, _list_layout.LIST_LAYOUT.RAMAN, _list_layout.LIST_LAYOUT.UVVIS, _list_layout.LIST_LAYOUT.HPLC_UVVIS].indexOf(layoutSt) >= 0;
|
|
449
630
|
const hasMultiCurves = layoutSt => [_list_layout.LIST_LAYOUT.CYCLIC_VOLTAMMETRY, _list_layout.LIST_LAYOUT.SEC, _list_layout.LIST_LAYOUT.GC, _list_layout.LIST_LAYOUT.AIF].indexOf(layoutSt) >= 0;
|
|
450
631
|
const isAIFLayout = layoutSt => _list_layout.LIST_LAYOUT.AIF === layoutSt;
|
|
@@ -609,6 +790,7 @@ const inlineNotation = (layout, data, sampleName = '') => {
|
|
|
609
790
|
};
|
|
610
791
|
const Format = {
|
|
611
792
|
toPeakStr,
|
|
793
|
+
extractUvvisLcmsPeaks,
|
|
612
794
|
buildData,
|
|
613
795
|
spectraDigit,
|
|
614
796
|
spectraOps,
|
|
@@ -638,7 +820,9 @@ const Format = {
|
|
|
638
820
|
isDLSIntensityLayout,
|
|
639
821
|
isEmWaveLayout,
|
|
640
822
|
isGCLayout,
|
|
823
|
+
isLCMsLayout,
|
|
641
824
|
fixDigit,
|
|
825
|
+
clampDecimalPlaces,
|
|
642
826
|
formatPeaksByPrediction,
|
|
643
827
|
formatedMS,
|
|
644
828
|
formatedEm,
|
|
@@ -651,6 +835,7 @@ const Format = {
|
|
|
651
835
|
strNumberFixedDecimal,
|
|
652
836
|
formatedXRD,
|
|
653
837
|
strNumberFixedLength,
|
|
654
|
-
inlineNotation
|
|
838
|
+
inlineNotation,
|
|
839
|
+
formatedLCMS
|
|
655
840
|
};
|
|
656
841
|
var _default = exports.default = Format;
|
package/dist/helpers/init.js
CHANGED
|
@@ -55,13 +55,33 @@ const tpDiv = (d, digits, yFactor = 1) => `
|
|
|
55
55
|
<span> y: ${d3.format('.2~e')(d.y * (yFactor || 1))}</span>
|
|
56
56
|
<div>
|
|
57
57
|
`;
|
|
58
|
+
const msPeakTpDiv = (d, relInt, digits) => `
|
|
59
|
+
<div
|
|
60
|
+
class="peak-tp"
|
|
61
|
+
style="${tpStyle()}"
|
|
62
|
+
>
|
|
63
|
+
<span>${_format.default.fixDigit(d.x, digits)} (${relInt})</span>
|
|
64
|
+
<div>
|
|
65
|
+
`;
|
|
66
|
+
const resolveDigits = (layout, xDigits) => xDigits != null && xDigits !== '' ? _format.default.clampDecimalPlaces(xDigits, _format.default.spectraDigit(layout)) : _format.default.spectraDigit(layout);
|
|
67
|
+
const peakTipHtml = ({
|
|
68
|
+
d,
|
|
69
|
+
layout,
|
|
70
|
+
yFactor,
|
|
71
|
+
xDigits,
|
|
72
|
+
msMaxY
|
|
73
|
+
}) => {
|
|
74
|
+
const digits = resolveDigits(layout, xDigits);
|
|
75
|
+
if (_format.default.isMsLayout(layout) && msMaxY > 0) {
|
|
76
|
+
const relPct = 100 * d.y / msMaxY;
|
|
77
|
+
const rel = parseInt(relPct, 10);
|
|
78
|
+
return msPeakTpDiv(d, rel, digits);
|
|
79
|
+
}
|
|
80
|
+
return tpDiv(d, digits, yFactor || 1);
|
|
81
|
+
};
|
|
58
82
|
const InitTip = () => {
|
|
59
83
|
d3.select('.peak-tp').remove();
|
|
60
|
-
const tip = (0, _d3Tip.default)().attr('class', 'd3-tip').html(
|
|
61
|
-
d,
|
|
62
|
-
layout,
|
|
63
|
-
yFactor
|
|
64
|
-
}) => tpDiv(d, _format.default.spectraDigit(layout), yFactor || 1));
|
|
84
|
+
const tip = (0, _d3Tip.default)().attr('class', 'd3-tip').html(peakTipHtml);
|
|
65
85
|
return tip;
|
|
66
86
|
};
|
|
67
87
|
exports.InitTip = InitTip;
|
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.getArea = exports.getAbsoluteArea = exports.calcArea = void 0;
|
|
6
|
+
exports.splitAreaProportionally = exports.normalizeSplitLines = exports.getVisualSplitGroups = exports.getVisualSplitGroupBoundaries = exports.getSplitAreas = exports.getLinearBaseline = exports.getIntegrationPoints = exports.getArea = exports.getAbsoluteAreaWithBaseline = exports.getAbsoluteArea = exports.generateVisualSplitGroupId = exports.calcArea = exports.buildSplitIntervals = void 0;
|
|
7
7
|
var _calc = require("./calc");
|
|
8
8
|
/* eslint-disable no-mixed-operators */
|
|
9
9
|
|
|
10
10
|
const getArea = (xL, xU, data) => {
|
|
11
|
+
if (!Array.isArray(data) || data.length === 0) return NaN;
|
|
11
12
|
let [iL, iU] = [data.length - 1, 0];
|
|
12
13
|
for (let i = 0; i < data.length; i += 1) {
|
|
13
14
|
const pt = data[i];
|
|
@@ -23,27 +24,68 @@ const getArea = (xL, xU, data) => {
|
|
|
23
24
|
return Math.abs(data[iU].k - data[iL].k);
|
|
24
25
|
};
|
|
25
26
|
exports.getArea = getArea;
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
const getIntegrationPoints = (xL, xU, data) => {
|
|
28
|
+
if (!Array.isArray(data)) return [];
|
|
29
|
+
return data.filter(d => d && Number.isFinite(d.x) && Number.isFinite(d.y) && d.x > xL && d.x < xU);
|
|
30
|
+
};
|
|
31
|
+
exports.getIntegrationPoints = getIntegrationPoints;
|
|
32
|
+
const getLinearBaseline = points => {
|
|
33
|
+
if (!points || !points[0]) return () => 0;
|
|
34
|
+
const point1 = points[0];
|
|
35
|
+
const point2 = points[points.length - 1];
|
|
32
36
|
const slope = (0, _calc.calcSlope)(point1.x, point1.y, point2.x, point2.y);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
return point => point1.y + slope * (point.x - point1.x);
|
|
38
|
+
};
|
|
39
|
+
exports.getLinearBaseline = getLinearBaseline;
|
|
40
|
+
const normalizeSplitLines = splitLines => {
|
|
41
|
+
if (!Array.isArray(splitLines)) return [];
|
|
42
|
+
const finiteValues = splitLines.map(value => parseFloat(value)).filter(value => Number.isFinite(value));
|
|
43
|
+
return [...new Set(finiteValues)].sort((a, b) => a - b);
|
|
44
|
+
};
|
|
45
|
+
exports.normalizeSplitLines = normalizeSplitLines;
|
|
46
|
+
const buildSplitIntervals = (xL, xU, splitLines = []) => {
|
|
47
|
+
if (!Number.isFinite(xL) || !Number.isFinite(xU)) return [];
|
|
48
|
+
const [lower, upper] = [xL, xU].sort((a, b) => a - b);
|
|
49
|
+
if (lower === upper) return [];
|
|
50
|
+
const sortedSplitLines = normalizeSplitLines(splitLines).filter(splitX => splitX > lower && splitX < upper);
|
|
51
|
+
return [lower, ...sortedSplitLines, upper].slice(1).map((right, index, bounds) => ({
|
|
52
|
+
xL: index === 0 ? lower : bounds[index - 1],
|
|
53
|
+
xU: right
|
|
54
|
+
}));
|
|
55
|
+
};
|
|
56
|
+
exports.buildSplitIntervals = buildSplitIntervals;
|
|
57
|
+
const getAbsoluteAreaWithBaseline = (xL, xU, data, baselineY) => {
|
|
58
|
+
const ps = getIntegrationPoints(xL, xU, data);
|
|
59
|
+
if (ps.length < 2 || typeof baselineY !== 'function') return 0;
|
|
60
|
+
let area = 0;
|
|
61
|
+
for (let i = 1; i < ps.length; i += 1) {
|
|
62
|
+
const pt = ps[i];
|
|
63
|
+
const baselineValue = baselineY(pt);
|
|
64
|
+
if (Number.isFinite(baselineValue)) {
|
|
65
|
+
area += Math.abs(pt.y - baselineValue);
|
|
42
66
|
}
|
|
43
67
|
}
|
|
44
68
|
return area;
|
|
45
69
|
};
|
|
70
|
+
exports.getAbsoluteAreaWithBaseline = getAbsoluteAreaWithBaseline;
|
|
71
|
+
const getAbsoluteArea = (xL, xU, data) => {
|
|
72
|
+
const points = getIntegrationPoints(xL, xU, data);
|
|
73
|
+
const baselineY = getLinearBaseline(points);
|
|
74
|
+
return getAbsoluteAreaWithBaseline(xL, xU, data, baselineY);
|
|
75
|
+
};
|
|
46
76
|
exports.getAbsoluteArea = getAbsoluteArea;
|
|
77
|
+
const getSplitAreas = (xL, xU, splitLines, data) => {
|
|
78
|
+
const intervals = buildSplitIntervals(xL, xU, splitLines);
|
|
79
|
+
const mainPoints = getIntegrationPoints(xL, xU, data);
|
|
80
|
+
const baselineY = getLinearBaseline(mainPoints);
|
|
81
|
+
return intervals.map(interval => ({
|
|
82
|
+
xL: interval.xL,
|
|
83
|
+
xU: interval.xU,
|
|
84
|
+
area: getArea(interval.xL, interval.xU, data),
|
|
85
|
+
absoluteArea: getAbsoluteAreaWithBaseline(interval.xL, interval.xU, data, baselineY)
|
|
86
|
+
}));
|
|
87
|
+
};
|
|
88
|
+
exports.getSplitAreas = getSplitAreas;
|
|
47
89
|
const calcArea = (d, refArea, refFactor, ignoreRef = false) => {
|
|
48
90
|
if (ignoreRef) {
|
|
49
91
|
const {
|
|
@@ -53,6 +95,77 @@ const calcArea = (d, refArea, refFactor, ignoreRef = false) => {
|
|
|
53
95
|
}
|
|
54
96
|
return (d.area * refFactor / refArea).toFixed(2);
|
|
55
97
|
};
|
|
98
|
+
exports.calcArea = calcArea;
|
|
99
|
+
const splitAreaProportionally = (totalArea, leftRaw, rightRaw) => {
|
|
100
|
+
const safeTotal = Number.isFinite(totalArea) ? totalArea : 0;
|
|
101
|
+
if (safeTotal === 0) return {
|
|
102
|
+
left: 0,
|
|
103
|
+
right: 0
|
|
104
|
+
};
|
|
105
|
+
const safeLeft = Number.isFinite(leftRaw) ? Math.max(leftRaw, 0) : 0;
|
|
106
|
+
const safeRight = Number.isFinite(rightRaw) ? Math.max(rightRaw, 0) : 0;
|
|
107
|
+
const rawSum = safeLeft + safeRight;
|
|
108
|
+
if (rawSum <= 0) {
|
|
109
|
+
const half = safeTotal / 2;
|
|
110
|
+
return {
|
|
111
|
+
left: half,
|
|
112
|
+
right: half
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
const ratio = safeTotal / rawSum;
|
|
116
|
+
return {
|
|
117
|
+
left: safeLeft * ratio,
|
|
118
|
+
right: safeRight * ratio
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
exports.splitAreaProportionally = splitAreaProportionally;
|
|
122
|
+
let visualSplitGroupCounter = 0;
|
|
123
|
+
const generateVisualSplitGroupId = () => {
|
|
124
|
+
visualSplitGroupCounter += 1;
|
|
125
|
+
const seed = typeof Date !== 'undefined' && Date.now ? Date.now().toString(36) : Math.random().toString(36).slice(2);
|
|
126
|
+
return `vsg-${seed}-${visualSplitGroupCounter}`;
|
|
127
|
+
};
|
|
128
|
+
exports.generateVisualSplitGroupId = generateVisualSplitGroupId;
|
|
129
|
+
const getVisualSplitGroups = (stack = []) => {
|
|
130
|
+
if (!Array.isArray(stack) || stack.length === 0) return [];
|
|
131
|
+
const groups = [];
|
|
132
|
+
let current = null;
|
|
133
|
+
stack.forEach(item => {
|
|
134
|
+
const groupId = item && item.visualSplitGroupId;
|
|
135
|
+
if (groupId && current && current.groupId === groupId) {
|
|
136
|
+
current.items.push(item);
|
|
137
|
+
current.xL = Math.min(current.xL, item.xL);
|
|
138
|
+
current.xU = Math.max(current.xU, item.xU);
|
|
139
|
+
} else {
|
|
140
|
+
current = {
|
|
141
|
+
groupId: groupId || null,
|
|
142
|
+
items: [item],
|
|
143
|
+
xL: item.xL,
|
|
144
|
+
xU: item.xU,
|
|
145
|
+
isMerged: false
|
|
146
|
+
};
|
|
147
|
+
groups.push(current);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
groups.forEach(group => {
|
|
151
|
+
// eslint-disable-next-line no-param-reassign
|
|
152
|
+
group.isMerged = !!group.groupId && group.items.length > 1;
|
|
153
|
+
});
|
|
154
|
+
return groups;
|
|
155
|
+
};
|
|
156
|
+
exports.getVisualSplitGroups = getVisualSplitGroups;
|
|
157
|
+
const getVisualSplitGroupBoundaries = group => {
|
|
158
|
+
if (!group || !group.isMerged) return [];
|
|
159
|
+
const sortedItems = [...group.items].sort((a, b) => a.xL - b.xL);
|
|
160
|
+
const boundaries = [];
|
|
161
|
+
for (let i = 0; i < sortedItems.length - 1; i += 1) {
|
|
162
|
+
const current = sortedItems[i];
|
|
163
|
+
const next = sortedItems[i + 1];
|
|
164
|
+
const boundary = (current.xU + next.xL) / 2;
|
|
165
|
+
if (Number.isFinite(boundary)) boundaries.push(boundary);
|
|
166
|
+
}
|
|
167
|
+
return boundaries;
|
|
168
|
+
};
|
|
56
169
|
|
|
57
170
|
// eslint-disable-line
|
|
58
|
-
exports.
|
|
171
|
+
exports.getVisualSplitGroupBoundaries = getVisualSplitGroupBoundaries;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.setPendingIntegrationDraft = exports.isDraftForCurve = exports.hasPendingIntegrationDraft = exports.forgetPendingIntegrationDraft = exports.confirmCancelPendingIntegration = exports.clearPendingIntegrationDraft = void 0;
|
|
7
|
+
let pendingIntegrationDraft = null;
|
|
8
|
+
const cancelMessage = 'You are currently creating an integration. Are you sure you want to cancel it?';
|
|
9
|
+
const hasPendingIntegrationDraft = () => !!pendingIntegrationDraft;
|
|
10
|
+
exports.hasPendingIntegrationDraft = hasPendingIntegrationDraft;
|
|
11
|
+
const setPendingIntegrationDraft = draft => {
|
|
12
|
+
pendingIntegrationDraft = draft;
|
|
13
|
+
};
|
|
14
|
+
exports.setPendingIntegrationDraft = setPendingIntegrationDraft;
|
|
15
|
+
const forgetPendingIntegrationDraft = () => {
|
|
16
|
+
pendingIntegrationDraft = null;
|
|
17
|
+
};
|
|
18
|
+
exports.forgetPendingIntegrationDraft = forgetPendingIntegrationDraft;
|
|
19
|
+
const clearPendingIntegrationDraft = () => {
|
|
20
|
+
const draft = pendingIntegrationDraft;
|
|
21
|
+
pendingIntegrationDraft = null;
|
|
22
|
+
if (draft && typeof draft.cancel === 'function') {
|
|
23
|
+
draft.cancel();
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
exports.clearPendingIntegrationDraft = clearPendingIntegrationDraft;
|
|
27
|
+
const confirmCancelPendingIntegration = () => {
|
|
28
|
+
if (!hasPendingIntegrationDraft()) return true;
|
|
29
|
+
const shouldCancel = typeof window === 'undefined' || typeof window.confirm !== 'function'
|
|
30
|
+
// This confirmation intentionally protects an in-progress two-click integration.
|
|
31
|
+
// eslint-disable-next-line no-alert
|
|
32
|
+
|| window.confirm(cancelMessage);
|
|
33
|
+
if (shouldCancel) {
|
|
34
|
+
clearPendingIntegrationDraft();
|
|
35
|
+
}
|
|
36
|
+
return shouldCancel;
|
|
37
|
+
};
|
|
38
|
+
exports.confirmCancelPendingIntegration = confirmCancelPendingIntegration;
|
|
39
|
+
const isDraftForCurve = (jcampIdx, dataLength) => {
|
|
40
|
+
if (!pendingIntegrationDraft) return false;
|
|
41
|
+
return pendingIntegrationDraft.jcampIdx === jcampIdx && pendingIntegrationDraft.dataLength === dataLength;
|
|
42
|
+
};
|
|
43
|
+
exports.isDraftForCurve = isDraftForCurve;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.handleVisualSplitLineClick = exports.handleIntegrationMouseMove = exports.handleIntegrationClick = exports.drawVisualSplitLinesForFocus = exports.drawIntegrationAUC = exports.buildIntegrationGroups = exports.buildIntegrationBarData = exports.bindSplitMouseHandlers = void 0;
|
|
8
|
+
var _integration = require("./integration");
|
|
9
|
+
var _focus = require("./focus");
|
|
10
|
+
var _compass = require("./compass");
|
|
11
|
+
var _cfg = _interopRequireDefault(require("./cfg"));
|
|
12
|
+
var _integration_split = require("./integration_split");
|
|
13
|
+
const d3 = require('d3');
|
|
14
|
+
const buildIntegrationGroups = (stack = []) => (0, _integration.getVisualSplitGroups)(stack).map(group => ({
|
|
15
|
+
xL: group.xL,
|
|
16
|
+
xU: group.xU,
|
|
17
|
+
isMerged: group.isMerged,
|
|
18
|
+
groupId: group.groupId,
|
|
19
|
+
target: group.items[0]
|
|
20
|
+
}));
|
|
21
|
+
exports.buildIntegrationGroups = buildIntegrationGroups;
|
|
22
|
+
const buildIntegrationBarData = (layout, stack = []) => {
|
|
23
|
+
const showIntegSplit = _cfg.default.showIntegSplitTools(layout);
|
|
24
|
+
const igGroups = buildIntegrationGroups(stack);
|
|
25
|
+
return {
|
|
26
|
+
showIntegSplit,
|
|
27
|
+
igGroups,
|
|
28
|
+
igBarData: showIntegSplit ? igGroups : stack
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
exports.buildIntegrationBarData = buildIntegrationBarData;
|
|
32
|
+
const handleIntegrationMouseMove = (focus, event, data, shift, ignoreRef) => {
|
|
33
|
+
if (!focus.isUiSplitIntgSt && !focus.isUiVisualSplitIntgSt) return;
|
|
34
|
+
if (focus.isUiVisualSplitIntgSt && (0, _integration_split.isAlreadyVisuallySplit)(data)) {
|
|
35
|
+
(0, _integration_split.clearIntegrationSplitPreview)(focus);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (focus.isUiSplitIntgSt && (0, _integration_split.isMergedVisualSplitGroup)(data)) {
|
|
39
|
+
(0, _integration_split.clearIntegrationSplitPreview)(focus);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const splitX = (0, _integration_split.getSplitXFromEvent)(event, focus);
|
|
43
|
+
const previewTarget = (0, _integration_split.resolveSplitTarget)(focus, data, splitX) || data;
|
|
44
|
+
(0, _integration_split.drawIntegrationSplitPreview)(focus, previewTarget, splitX, shift, ignoreRef);
|
|
45
|
+
};
|
|
46
|
+
exports.handleIntegrationMouseMove = handleIntegrationMouseMove;
|
|
47
|
+
const handleIntegrationClick = (focus, event, data, fallbackClick) => {
|
|
48
|
+
if (!focus.isUiSplitIntgSt && !focus.isUiVisualSplitIntgSt) {
|
|
49
|
+
if (typeof fallbackClick === 'function') fallbackClick(event, data);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
event.stopPropagation();
|
|
53
|
+
event.preventDefault();
|
|
54
|
+
const splitX = (0, _integration_split.getSplitXFromEvent)(event, focus);
|
|
55
|
+
(0, _integration_split.clearIntegrationSplitPreview)(focus);
|
|
56
|
+
const target = (0, _integration_split.resolveSplitTarget)(focus, data, splitX);
|
|
57
|
+
if (!target) return;
|
|
58
|
+
if (focus.isUiVisualSplitIntgSt) {
|
|
59
|
+
const {
|
|
60
|
+
stack = [],
|
|
61
|
+
shift = 0
|
|
62
|
+
} = focus.integrationSplitTargets || {};
|
|
63
|
+
const existingSplitX = (0, _integration_split.getVisualSplitLineAtX)(focus, stack, splitX, shift);
|
|
64
|
+
if (Number.isFinite(existingSplitX)) {
|
|
65
|
+
if (typeof focus.removeVisualSplitLineAct !== 'function') return;
|
|
66
|
+
focus.removeVisualSplitLineAct({
|
|
67
|
+
curveIdx: focus.jcampIdx,
|
|
68
|
+
splitX: existingSplitX,
|
|
69
|
+
data: focus.data
|
|
70
|
+
});
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if ((0, _integration_split.isAlreadyVisuallySplit)(target)) return;
|
|
74
|
+
if (typeof focus.addVisualSplitLineAct !== 'function') return;
|
|
75
|
+
focus.addVisualSplitLineAct({
|
|
76
|
+
curveIdx: focus.jcampIdx,
|
|
77
|
+
target,
|
|
78
|
+
splitX,
|
|
79
|
+
data: focus.data
|
|
80
|
+
});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if ((0, _integration_split.isMergedVisualSplitGroup)(data)) return;
|
|
84
|
+
if (typeof focus.splitIntegrationAct !== 'function') return;
|
|
85
|
+
focus.splitIntegrationAct({
|
|
86
|
+
curveIdx: focus.jcampIdx,
|
|
87
|
+
target,
|
|
88
|
+
splitX,
|
|
89
|
+
data: focus.data
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
exports.handleIntegrationClick = handleIntegrationClick;
|
|
93
|
+
const handleVisualSplitLineClick = (focus, event, splitX) => {
|
|
94
|
+
event.stopPropagation();
|
|
95
|
+
event.preventDefault();
|
|
96
|
+
(0, _integration_split.clearIntegrationSplitPreview)(focus);
|
|
97
|
+
if (typeof focus.removeVisualSplitLineAct !== 'function') return;
|
|
98
|
+
focus.removeVisualSplitLineAct({
|
|
99
|
+
curveIdx: focus.jcampIdx,
|
|
100
|
+
splitX,
|
|
101
|
+
data: focus.data
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
exports.handleVisualSplitLineClick = handleVisualSplitLineClick;
|
|
105
|
+
const drawVisualSplitLinesForFocus = (focus, stack, shift, ignoreRef) => {
|
|
106
|
+
(0, _integration_split.drawIntegrationVisualSplitLines)(focus, stack, shift, ignoreRef, focus.isUiVisualSplitIntgSt, (event, splitX) => handleVisualSplitLineClick(focus, event, splitX));
|
|
107
|
+
};
|
|
108
|
+
exports.drawVisualSplitLinesForFocus = drawVisualSplitLinesForFocus;
|
|
109
|
+
const drawIntegrationAUC = (focus, stack, shift = 0) => {
|
|
110
|
+
const {
|
|
111
|
+
xt,
|
|
112
|
+
yt
|
|
113
|
+
} = (0, _compass.TfRescale)(focus);
|
|
114
|
+
const groups = buildIntegrationGroups(stack);
|
|
115
|
+
const auc = focus.tags.aucPath.selectAll('path').data(groups);
|
|
116
|
+
auc.exit().attr('class', 'exit').remove();
|
|
117
|
+
const integCurve = border => {
|
|
118
|
+
const {
|
|
119
|
+
xL,
|
|
120
|
+
xU
|
|
121
|
+
} = border;
|
|
122
|
+
const ps = (0, _integration.getIntegrationPoints)(xL - shift, xU - shift, focus.data);
|
|
123
|
+
if (!ps[0]) return null;
|
|
124
|
+
const baselineY = (0, _integration.getLinearBaseline)(ps);
|
|
125
|
+
return d3.area().x(d => xt(d.x)).y0(d => yt(baselineY(d))).y1(d => yt(d.y))(ps);
|
|
126
|
+
};
|
|
127
|
+
const showIntegSplit = _cfg.default.showIntegSplitTools(focus.layout);
|
|
128
|
+
auc.enter().append('path').attr('class', 'auc').attr('fill', 'red').attr('stroke', 'none').attr('fill-opacity', 0.2).attr('stroke-width', 2).merge(auc).attr('d', d => integCurve(d)).attr('id', d => `auc${(0, _focus.itgIdTag)(d)}`).on('mouseover', (event, d) => {
|
|
129
|
+
d3.select(`#auc${(0, _focus.itgIdTag)(d)}`).attr('stroke', 'blue');
|
|
130
|
+
d3.select(`#auc${(0, _focus.itgIdTag)(d)}`).style('fill', 'blue');
|
|
131
|
+
}).on('mouseout', (event, d) => {
|
|
132
|
+
d3.select(`#auc${(0, _focus.itgIdTag)(d)}`).attr('stroke', 'none');
|
|
133
|
+
d3.select(`#auc${(0, _focus.itgIdTag)(d)}`).style('fill', 'red');
|
|
134
|
+
d3.select(`#auc${(0, _focus.itgIdTag)(d)}`).style('fill-opacity', 0.2);
|
|
135
|
+
if (showIntegSplit) (0, _integration_split.clearIntegrationSplitPreview)(focus);
|
|
136
|
+
}).on('mousemove', showIntegSplit ? (event, d) => handleIntegrationMouseMove(focus, event, d, shift, true) : null).on('click', (event, d) => handleIntegrationClick(focus, event, d, (clickEvent, clickData) => focus.onClickTarget(clickEvent, clickData)));
|
|
137
|
+
};
|
|
138
|
+
exports.drawIntegrationAUC = drawIntegrationAUC;
|
|
139
|
+
const bindSplitMouseHandlers = ({
|
|
140
|
+
focus,
|
|
141
|
+
shift,
|
|
142
|
+
ignoreRef,
|
|
143
|
+
showIntegSplit,
|
|
144
|
+
fallbackClick
|
|
145
|
+
}) => ({
|
|
146
|
+
mouseout: (event, d) => {
|
|
147
|
+
d3.select(`#igbp${(0, _focus.itgIdTag)(d)}`).attr('stroke', '#228B22');
|
|
148
|
+
d3.select(`#igbc${(0, _focus.itgIdTag)(d)}`).attr('stroke', '#228B22');
|
|
149
|
+
d3.select(`#igtp${(0, _focus.itgIdTag)(d)}`).style('fill', '#228B22');
|
|
150
|
+
if (showIntegSplit) (0, _integration_split.clearIntegrationSplitPreview)(focus);
|
|
151
|
+
},
|
|
152
|
+
mousemove: showIntegSplit ? (event, d) => handleIntegrationMouseMove(focus, event, d, shift, ignoreRef) : null,
|
|
153
|
+
click: (event, d) => handleIntegrationClick(focus, event, d, fallbackClick)
|
|
154
|
+
});
|
|
155
|
+
exports.bindSplitMouseHandlers = bindSplitMouseHandlers;
|