@tetrascience-npm/tetrascience-react-ui 0.7.0-beta.106.1 → 0.7.0-beta.108.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 +1 -1
- package/dist/components/charts/ChromatogramChart/ChromatogramChart.cjs +1 -1
- package/dist/components/charts/ChromatogramChart/ChromatogramChart.cjs.map +1 -1
- package/dist/components/charts/ChromatogramChart/ChromatogramChart.js +221 -207
- package/dist/components/charts/ChromatogramChart/ChromatogramChart.js.map +1 -1
- package/dist/components/charts/ChromatogramChart/annotations.cjs +1 -1
- package/dist/components/charts/ChromatogramChart/annotations.cjs.map +1 -1
- package/dist/components/charts/ChromatogramChart/annotations.js +99 -36
- package/dist/components/charts/ChromatogramChart/annotations.js.map +1 -1
- package/dist/components/charts/ChromatogramChart/boundaryMarkers.cjs +1 -1
- package/dist/components/charts/ChromatogramChart/boundaryMarkers.cjs.map +1 -1
- package/dist/components/charts/ChromatogramChart/boundaryMarkers.js +12 -12
- package/dist/components/charts/ChromatogramChart/boundaryMarkers.js.map +1 -1
- package/dist/components/charts/ChromatogramChart/constants.cjs +1 -1
- package/dist/components/charts/ChromatogramChart/constants.cjs.map +1 -1
- package/dist/components/charts/ChromatogramChart/constants.js +11 -5
- package/dist/components/charts/ChromatogramChart/constants.js.map +1 -1
- package/dist/components/charts/ChromatogramChart/dataProcessing.cjs +1 -1
- package/dist/components/charts/ChromatogramChart/dataProcessing.cjs.map +1 -1
- package/dist/components/charts/ChromatogramChart/dataProcessing.js +49 -38
- package/dist/components/charts/ChromatogramChart/dataProcessing.js.map +1 -1
- package/dist/components/charts/ChromatogramChart/plotBuilder.cjs +2 -0
- package/dist/components/charts/ChromatogramChart/plotBuilder.cjs.map +1 -0
- package/dist/components/charts/ChromatogramChart/plotBuilder.js +207 -0
- package/dist/components/charts/ChromatogramChart/plotBuilder.js.map +1 -0
- package/dist/components/charts/ChromatogramChart/regionOverlays.cjs +2 -0
- package/dist/components/charts/ChromatogramChart/regionOverlays.cjs.map +1 -0
- package/dist/components/charts/ChromatogramChart/regionOverlays.js +26 -0
- package/dist/components/charts/ChromatogramChart/regionOverlays.js.map +1 -0
- package/dist/components/charts/StackedChromatogramChart/StackedChromatogramChart.cjs +2 -0
- package/dist/components/charts/StackedChromatogramChart/StackedChromatogramChart.cjs.map +1 -0
- package/dist/components/charts/StackedChromatogramChart/StackedChromatogramChart.js +40 -0
- package/dist/components/charts/StackedChromatogramChart/StackedChromatogramChart.js.map +1 -0
- package/dist/components/charts/StackedChromatogramChart/transforms.cjs +2 -0
- package/dist/components/charts/StackedChromatogramChart/transforms.cjs.map +1 -0
- package/dist/components/charts/StackedChromatogramChart/transforms.js +31 -0
- package/dist/components/charts/StackedChromatogramChart/transforms.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +141 -34
- package/dist/index.js +570 -582
- package/dist/index.tailwind.css +1 -1
- package/package.json +2 -4
- package/dist/components/ui/drawer.cjs +0 -2
- package/dist/components/ui/drawer.cjs.map +0 -1
- package/dist/components/ui/drawer.js +0 -125
- package/dist/components/ui/drawer.js.map +0 -1
- package/dist/components/ui/input-otp.cjs +0 -2
- package/dist/components/ui/input-otp.cjs.map +0 -1
- package/dist/components/ui/input-otp.js +0 -82
- package/dist/components/ui/input-otp.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataProcessing.cjs","sources":["../../../../src/components/charts/ChromatogramChart/dataProcessing.ts"],"sourcesContent":["/**\n * Data processing utilities for ChromatogramChart\n */\n\nimport { calculatePeakArea } from \"./peakDetection\";\n\nimport type { BaselineCorrectionMethod, PeakAnnotation } from \"./types\";\n\n/**\n * Data structure for peaks with their associated series data\n */\nexport type PeakDataWithSeries = {\n peaks: PeakAnnotation[];\n seriesIndex: number;\n x: number[];\n y: number[];\n};\n\n/**\n * Find the closest index in an array for a given target value.\n * Uses binary search for efficiency.\n */\nexport function findClosestIndex(arr: number[], target: number): number {\n if (arr.length === 0) return 0;\n if (arr.length === 1) return 0;\n\n let left = 0;\n let right = arr.length - 1;\n\n while (left < right) {\n const mid = Math.floor((left + right) / 2);\n if (arr[mid] < target) {\n left = mid + 1;\n } else {\n right = mid;\n }\n }\n\n // Check if left-1 is closer\n if (left > 0 && Math.abs(arr[left - 1] - target) < Math.abs(arr[left] - target)) {\n return left - 1;\n }\n return left;\n}\n\n/**\n * Process user annotations to convert startX/endX to startIndex/endIndex\n * and compute area if boundaries are provided.\n */\nexport function processUserAnnotations(\n annotations: PeakAnnotation[],\n xArray: number[],\n yArray: number[]\n): PeakAnnotation[] {\n return annotations.map((ann) => {\n // If startX/endX are provided, convert to indices\n if (ann.startX !== undefined && ann.endX !== undefined) {\n const startIndex = findClosestIndex(xArray, ann.startX);\n const endIndex = findClosestIndex(xArray, ann.endX);\n const index = findClosestIndex(xArray, ann.x);\n\n // Calculate area if not provided\n const area = ann._computed?.area ?? calculatePeakArea(xArray, yArray, startIndex, endIndex);\n\n return {\n ...ann,\n _computed: {\n ...ann._computed,\n index,\n startIndex,\n endIndex,\n area,\n },\n };\n }\n return ann;\n });\n}\n\n/**\n * Collect peaks with boundary information from both auto-detected peaks and user-provided annotations.\n * User-provided annotations with startIndex/endIndex or startX/endX are included for boundary marker rendering.\n */\nexport function collectPeaksWithBoundaryData(\n allDetectedPeaks: { peaks: PeakAnnotation[]; seriesIndex: number }[],\n annotations: PeakAnnotation[],\n processedSeries: { x: number[]; y: number[] }[]\n): PeakDataWithSeries[] {\n const peaksWithData: PeakDataWithSeries[] = [];\n\n // Add auto-detected peaks\n allDetectedPeaks.forEach(({ peaks, seriesIndex }) => {\n peaksWithData.push({\n peaks,\n seriesIndex,\n x: processedSeries[seriesIndex].x,\n y: processedSeries[seriesIndex].y,\n });\n });\n\n // Add user-provided annotations that have boundary info (_computed.startIndex and _computed.endIndex)\n // Note: annotations with startX/endX should already be processed to have _computed fields\n const annotationsWithBoundaries = annotations.filter(\n (ann) => ann._computed?.startIndex !== undefined && ann._computed?.endIndex !== undefined\n );\n if (annotationsWithBoundaries.length > 0 && processedSeries.length > 0) {\n peaksWithData.push({\n peaks: annotationsWithBoundaries,\n seriesIndex: 0, // User annotations apply to first series by default\n x: processedSeries[0].x,\n y: processedSeries[0].y,\n });\n }\n\n return peaksWithData;\n}\n\n/**\n * Build the extra content for Plotly hovertemplate from series metadata.\n * Displays all metadata fields as key: value pairs.\n */\nexport function buildHoverExtraContent(\n seriesName: string,\n metadata?: Record<string, unknown>\n): string {\n if (!metadata) return seriesName;\n\n const metaLines: string[] = [];\n for (const [key, value] of Object.entries(metadata)) {\n if (value !== undefined && value !== null && value !== \"\") {\n // Format the key as Title Case (e.g., \"sampleName\" -> \"Sample Name\")\n const formattedKey = key\n .replace(/([A-Z])/g, \" $1\")\n .replace(/^./, (s) => s.toUpperCase())\n .trim();\n metaLines.push(`${formattedKey}: ${String(value)}`);\n }\n }\n\n if (metaLines.length > 0) {\n return `${seriesName}<br>${metaLines.join(\"<br>\")}`;\n }\n return seriesName;\n}\n\n/**\n * Validate and sanitize series data.\n * - Ensures x and y arrays have the same length (truncates to shorter)\n * - Replaces NaN and Infinity values with 0\n */\nexport function validateSeriesData(\n x: number[],\n y: number[]\n): { x: number[]; y: number[] } {\n // Ensure arrays have same length\n const length = Math.min(x.length, y.length);\n const validX = x.slice(0, length);\n const validY = y.slice(0, length);\n\n // Sanitize NaN and Infinity values\n const sanitizedY = validY.map((val) => (Number.isFinite(val) ? val : 0));\n const sanitizedX = validX.map((val) => (Number.isFinite(val) ? val : 0));\n\n return { x: sanitizedX, y: sanitizedY };\n}\n\n/**\n * Apply baseline correction to signal data\n */\nexport function applyBaselineCorrection(\n y: number[],\n method: BaselineCorrectionMethod,\n windowSize: number = 50\n): number[] {\n if (method === \"none\" || y.length === 0) return y;\n\n if (method === \"linear\") {\n // Linear baseline from first to last point\n // Handle single-point case to avoid division by zero\n if (y.length === 1) {\n return [0]; // Single point baseline-corrected to zero\n }\n const slope = (y[y.length - 1] - y[0]) / (y.length - 1);\n return y.map((val, i) => val - (y[0] + slope * i));\n }\n\n if (method === \"rolling\") {\n // Rolling minimum baseline\n const baseline: number[] = [];\n const halfWindow = Math.floor(windowSize / 2);\n\n for (let i = 0; i < y.length; i++) {\n const start = Math.max(0, i - halfWindow);\n const end = Math.min(y.length, i + halfWindow + 1);\n const windowSlice = y.slice(start, end);\n baseline.push(Math.min(...windowSlice));\n }\n\n return y.map((val, i) => val - baseline[i]);\n }\n\n return y;\n}\n\n"],"names":["findClosestIndex","arr","target","left","right","mid","processUserAnnotations","annotations","xArray","yArray","ann","startIndex","endIndex","index","area","calculatePeakArea","collectPeaksWithBoundaryData","allDetectedPeaks","processedSeries","peaksWithData","peaks","seriesIndex","annotationsWithBoundaries","validateSeriesData","x","y","length","validX","sanitizedY","val","applyBaselineCorrection","method","windowSize","slope","baseline","halfWindow","start","end","windowSlice"
|
|
1
|
+
{"version":3,"file":"dataProcessing.cjs","sources":["../../../../src/components/charts/ChromatogramChart/dataProcessing.ts"],"sourcesContent":["/**\n * Data processing utilities for ChromatogramChart\n */\n\nimport { calculatePeakArea } from \"./peakDetection\";\n\nimport type { BaselineCorrectionMethod, PeakAnnotation } from \"./types\";\n\n/**\n * Data structure for peaks with their associated series data\n */\nexport type PeakDataWithSeries = {\n peaks: PeakAnnotation[];\n seriesIndex: number;\n x: number[];\n y: number[];\n};\n\n/**\n * Find the closest index in an array for a given target value.\n * Uses binary search for efficiency.\n */\nexport function findClosestIndex(arr: number[], target: number): number {\n if (arr.length === 0) return 0;\n if (arr.length === 1) return 0;\n\n let left = 0;\n let right = arr.length - 1;\n\n while (left < right) {\n const mid = Math.floor((left + right) / 2);\n if (arr[mid] < target) {\n left = mid + 1;\n } else {\n right = mid;\n }\n }\n\n // Check if left-1 is closer\n if (left > 0 && Math.abs(arr[left - 1] - target) < Math.abs(arr[left] - target)) {\n return left - 1;\n }\n return left;\n}\n\n/**\n * Process user annotations to convert startX/endX to startIndex/endIndex\n * and compute area if boundaries are provided.\n */\nexport function processUserAnnotations(\n annotations: PeakAnnotation[],\n xArray: number[],\n yArray: number[]\n): PeakAnnotation[] {\n return annotations.map((ann) => {\n // If startX/endX are provided, convert to indices\n if (ann.startX !== undefined && ann.endX !== undefined) {\n const startIndex = findClosestIndex(xArray, ann.startX);\n const endIndex = findClosestIndex(xArray, ann.endX);\n const index = findClosestIndex(xArray, ann.x);\n\n // Calculate area if not provided\n const area = ann._computed?.area ?? calculatePeakArea(xArray, yArray, startIndex, endIndex);\n\n return {\n ...ann,\n _computed: {\n ...ann._computed,\n index,\n startIndex,\n endIndex,\n area,\n },\n };\n }\n return ann;\n });\n}\n\n/**\n * Collect peaks with boundary information from both auto-detected peaks and user-provided annotations.\n * User-provided annotations with startIndex/endIndex or startX/endX are included for boundary marker rendering.\n */\nexport function collectPeaksWithBoundaryData(\n allDetectedPeaks: { peaks: PeakAnnotation[]; seriesIndex: number }[],\n annotations: PeakAnnotation[],\n processedSeries: { x: number[]; y: number[] }[]\n): PeakDataWithSeries[] {\n const peaksWithData: PeakDataWithSeries[] = [];\n\n // Add auto-detected peaks\n allDetectedPeaks.forEach(({ peaks, seriesIndex }) => {\n peaksWithData.push({\n peaks,\n seriesIndex,\n x: processedSeries[seriesIndex].x,\n y: processedSeries[seriesIndex].y,\n });\n });\n\n // Add user-provided annotations that have boundary info (_computed.startIndex and _computed.endIndex)\n // Note: annotations with startX/endX should already be processed to have _computed fields\n const annotationsWithBoundaries = annotations.filter(\n (ann) => ann._computed?.startIndex !== undefined && ann._computed?.endIndex !== undefined\n );\n if (annotationsWithBoundaries.length > 0 && processedSeries.length > 0) {\n peaksWithData.push({\n peaks: annotationsWithBoundaries,\n seriesIndex: 0, // User annotations apply to first series by default\n x: processedSeries[0].x,\n y: processedSeries[0].y,\n });\n }\n\n return peaksWithData;\n}\n\n/**\n * Build the extra content for Plotly hovertemplate from series metadata.\n * Displays all metadata fields as key: value pairs.\n */\nexport function buildHoverExtraContent(\n seriesName: string,\n metadata?: Record<string, unknown>\n): string {\n if (!metadata) return seriesName;\n\n const metaLines: string[] = [];\n for (const [key, value] of Object.entries(metadata)) {\n if (value !== undefined && value !== null && value !== \"\") {\n // Format the key as Title Case (e.g., \"sampleName\" -> \"Sample Name\")\n const formattedKey = key\n .replace(/([A-Z])/g, \" $1\")\n .replace(/^./, (s) => s.toUpperCase())\n .trim();\n metaLines.push(`${formattedKey}: ${String(value)}`);\n }\n }\n\n if (metaLines.length > 0) {\n return `${seriesName}<br>${metaLines.join(\"<br>\")}`;\n }\n return seriesName;\n}\n\n/**\n * Validate and sanitize series data.\n * - Ensures x and y arrays have the same length (truncates to shorter)\n * - Replaces NaN and Infinity values with 0\n */\nexport function validateSeriesData(\n x: number[],\n y: number[]\n): { x: number[]; y: number[] } {\n // Ensure arrays have same length\n const length = Math.min(x.length, y.length);\n const validX = x.slice(0, length);\n const validY = y.slice(0, length);\n\n // Sanitize NaN and Infinity values\n const sanitizedY = validY.map((val) => (Number.isFinite(val) ? val : 0));\n const sanitizedX = validX.map((val) => (Number.isFinite(val) ? val : 0));\n\n return { x: sanitizedX, y: sanitizedY };\n}\n\n/**\n * Apply baseline correction to signal data\n */\nexport function applyBaselineCorrection(\n y: number[],\n method: BaselineCorrectionMethod,\n windowSize: number = 50\n): number[] {\n if (method === \"none\" || y.length === 0) return y;\n\n if (method === \"linear\") {\n // Linear baseline from first to last point\n // Handle single-point case to avoid division by zero\n if (y.length === 1) {\n return [0]; // Single point baseline-corrected to zero\n }\n const slope = (y[y.length - 1] - y[0]) / (y.length - 1);\n return y.map((val, i) => val - (y[0] + slope * i));\n }\n\n if (method === \"rolling\") {\n // Rolling minimum baseline\n const baseline: number[] = [];\n const halfWindow = Math.floor(windowSize / 2);\n\n for (let i = 0; i < y.length; i++) {\n const start = Math.max(0, i - halfWindow);\n const end = Math.min(y.length, i + halfWindow + 1);\n const windowSlice = y.slice(start, end);\n baseline.push(Math.min(...windowSlice));\n }\n\n return y.map((val, i) => val - baseline[i]);\n }\n\n return y;\n}\n\n"],"names":["findClosestIndex","arr","target","left","right","mid","processUserAnnotations","annotations","xArray","yArray","ann","startIndex","endIndex","index","area","calculatePeakArea","collectPeaksWithBoundaryData","allDetectedPeaks","processedSeries","peaksWithData","peaks","seriesIndex","annotationsWithBoundaries","buildHoverExtraContent","seriesName","metadata","metaLines","key","value","formattedKey","s","validateSeriesData","x","y","length","validX","sanitizedY","val","applyBaselineCorrection","method","windowSize","slope","i","baseline","halfWindow","start","end","windowSlice"],"mappings":"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"}
|
|
@@ -1,79 +1,90 @@
|
|
|
1
|
-
import { calculatePeakArea as
|
|
2
|
-
function
|
|
1
|
+
import { calculatePeakArea as a } from "./peakDetection.js";
|
|
2
|
+
function s(t, i) {
|
|
3
3
|
if (t.length === 0 || t.length === 1) return 0;
|
|
4
4
|
let e = 0, n = t.length - 1;
|
|
5
5
|
for (; e < n; ) {
|
|
6
|
-
const
|
|
7
|
-
t[
|
|
6
|
+
const o = Math.floor((e + n) / 2);
|
|
7
|
+
t[o] < i ? e = o + 1 : n = o;
|
|
8
8
|
}
|
|
9
|
-
return e > 0 && Math.abs(t[e - 1] -
|
|
9
|
+
return e > 0 && Math.abs(t[e - 1] - i) < Math.abs(t[e] - i) ? e - 1 : e;
|
|
10
10
|
}
|
|
11
|
-
function
|
|
11
|
+
function f(t, i, e) {
|
|
12
12
|
return t.map((n) => {
|
|
13
13
|
if (n.startX !== void 0 && n.endX !== void 0) {
|
|
14
|
-
const
|
|
14
|
+
const o = s(i, n.startX), l = s(i, n.endX), r = s(i, n.x), c = n._computed?.area ?? a(i, e, o, l);
|
|
15
15
|
return {
|
|
16
16
|
...n,
|
|
17
17
|
_computed: {
|
|
18
18
|
...n._computed,
|
|
19
|
-
index:
|
|
20
|
-
startIndex:
|
|
21
|
-
endIndex:
|
|
22
|
-
area:
|
|
19
|
+
index: r,
|
|
20
|
+
startIndex: o,
|
|
21
|
+
endIndex: l,
|
|
22
|
+
area: c
|
|
23
23
|
}
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
return n;
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
|
-
function
|
|
29
|
+
function d(t, i, e) {
|
|
30
30
|
const n = [];
|
|
31
|
-
t.forEach(({ peaks:
|
|
31
|
+
t.forEach(({ peaks: l, seriesIndex: r }) => {
|
|
32
32
|
n.push({
|
|
33
|
-
peaks:
|
|
34
|
-
seriesIndex:
|
|
35
|
-
x: e[
|
|
36
|
-
y: e[
|
|
33
|
+
peaks: l,
|
|
34
|
+
seriesIndex: r,
|
|
35
|
+
x: e[r].x,
|
|
36
|
+
y: e[r].y
|
|
37
37
|
});
|
|
38
38
|
});
|
|
39
|
-
const
|
|
40
|
-
(
|
|
39
|
+
const o = i.filter(
|
|
40
|
+
(l) => l._computed?.startIndex !== void 0 && l._computed?.endIndex !== void 0
|
|
41
41
|
);
|
|
42
|
-
return
|
|
43
|
-
peaks:
|
|
42
|
+
return o.length > 0 && e.length > 0 && n.push({
|
|
43
|
+
peaks: o,
|
|
44
44
|
seriesIndex: 0,
|
|
45
45
|
// User annotations apply to first series by default
|
|
46
46
|
x: e[0].x,
|
|
47
47
|
y: e[0].y
|
|
48
48
|
}), n;
|
|
49
49
|
}
|
|
50
|
-
function
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
function p(t, i) {
|
|
51
|
+
if (!i) return t;
|
|
52
|
+
const e = [];
|
|
53
|
+
for (const [n, o] of Object.entries(i))
|
|
54
|
+
if (o != null && o !== "") {
|
|
55
|
+
const l = n.replace(/([A-Z])/g, " $1").replace(/^./, (r) => r.toUpperCase()).trim();
|
|
56
|
+
e.push(`${l}: ${String(o)}`);
|
|
57
|
+
}
|
|
58
|
+
return e.length > 0 ? `${t}<br>${e.join("<br>")}` : t;
|
|
59
|
+
}
|
|
60
|
+
function g(t, i) {
|
|
61
|
+
const e = Math.min(t.length, i.length), n = t.slice(0, e), l = i.slice(0, e).map((c) => Number.isFinite(c) ? c : 0);
|
|
62
|
+
return { x: n.map((c) => Number.isFinite(c) ? c : 0), y: l };
|
|
53
63
|
}
|
|
54
|
-
function
|
|
55
|
-
if (
|
|
56
|
-
if (
|
|
64
|
+
function m(t, i, e = 50) {
|
|
65
|
+
if (i === "none" || t.length === 0) return t;
|
|
66
|
+
if (i === "linear") {
|
|
57
67
|
if (t.length === 1)
|
|
58
68
|
return [0];
|
|
59
69
|
const n = (t[t.length - 1] - t[0]) / (t.length - 1);
|
|
60
|
-
return t.map((
|
|
70
|
+
return t.map((o, l) => o - (t[0] + n * l));
|
|
61
71
|
}
|
|
62
|
-
if (
|
|
63
|
-
const n = [],
|
|
64
|
-
for (let
|
|
65
|
-
const
|
|
72
|
+
if (i === "rolling") {
|
|
73
|
+
const n = [], o = Math.floor(e / 2);
|
|
74
|
+
for (let l = 0; l < t.length; l++) {
|
|
75
|
+
const r = Math.max(0, l - o), c = Math.min(t.length, l + o + 1), u = t.slice(r, c);
|
|
66
76
|
n.push(Math.min(...u));
|
|
67
77
|
}
|
|
68
|
-
return t.map((
|
|
78
|
+
return t.map((l, r) => l - n[r]);
|
|
69
79
|
}
|
|
70
80
|
return t;
|
|
71
81
|
}
|
|
72
82
|
export {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
83
|
+
m as applyBaselineCorrection,
|
|
84
|
+
p as buildHoverExtraContent,
|
|
85
|
+
d as collectPeaksWithBoundaryData,
|
|
86
|
+
s as findClosestIndex,
|
|
87
|
+
f as processUserAnnotations,
|
|
88
|
+
g as validateSeriesData
|
|
78
89
|
};
|
|
79
90
|
//# sourceMappingURL=dataProcessing.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataProcessing.js","sources":["../../../../src/components/charts/ChromatogramChart/dataProcessing.ts"],"sourcesContent":["/**\n * Data processing utilities for ChromatogramChart\n */\n\nimport { calculatePeakArea } from \"./peakDetection\";\n\nimport type { BaselineCorrectionMethod, PeakAnnotation } from \"./types\";\n\n/**\n * Data structure for peaks with their associated series data\n */\nexport type PeakDataWithSeries = {\n peaks: PeakAnnotation[];\n seriesIndex: number;\n x: number[];\n y: number[];\n};\n\n/**\n * Find the closest index in an array for a given target value.\n * Uses binary search for efficiency.\n */\nexport function findClosestIndex(arr: number[], target: number): number {\n if (arr.length === 0) return 0;\n if (arr.length === 1) return 0;\n\n let left = 0;\n let right = arr.length - 1;\n\n while (left < right) {\n const mid = Math.floor((left + right) / 2);\n if (arr[mid] < target) {\n left = mid + 1;\n } else {\n right = mid;\n }\n }\n\n // Check if left-1 is closer\n if (left > 0 && Math.abs(arr[left - 1] - target) < Math.abs(arr[left] - target)) {\n return left - 1;\n }\n return left;\n}\n\n/**\n * Process user annotations to convert startX/endX to startIndex/endIndex\n * and compute area if boundaries are provided.\n */\nexport function processUserAnnotations(\n annotations: PeakAnnotation[],\n xArray: number[],\n yArray: number[]\n): PeakAnnotation[] {\n return annotations.map((ann) => {\n // If startX/endX are provided, convert to indices\n if (ann.startX !== undefined && ann.endX !== undefined) {\n const startIndex = findClosestIndex(xArray, ann.startX);\n const endIndex = findClosestIndex(xArray, ann.endX);\n const index = findClosestIndex(xArray, ann.x);\n\n // Calculate area if not provided\n const area = ann._computed?.area ?? calculatePeakArea(xArray, yArray, startIndex, endIndex);\n\n return {\n ...ann,\n _computed: {\n ...ann._computed,\n index,\n startIndex,\n endIndex,\n area,\n },\n };\n }\n return ann;\n });\n}\n\n/**\n * Collect peaks with boundary information from both auto-detected peaks and user-provided annotations.\n * User-provided annotations with startIndex/endIndex or startX/endX are included for boundary marker rendering.\n */\nexport function collectPeaksWithBoundaryData(\n allDetectedPeaks: { peaks: PeakAnnotation[]; seriesIndex: number }[],\n annotations: PeakAnnotation[],\n processedSeries: { x: number[]; y: number[] }[]\n): PeakDataWithSeries[] {\n const peaksWithData: PeakDataWithSeries[] = [];\n\n // Add auto-detected peaks\n allDetectedPeaks.forEach(({ peaks, seriesIndex }) => {\n peaksWithData.push({\n peaks,\n seriesIndex,\n x: processedSeries[seriesIndex].x,\n y: processedSeries[seriesIndex].y,\n });\n });\n\n // Add user-provided annotations that have boundary info (_computed.startIndex and _computed.endIndex)\n // Note: annotations with startX/endX should already be processed to have _computed fields\n const annotationsWithBoundaries = annotations.filter(\n (ann) => ann._computed?.startIndex !== undefined && ann._computed?.endIndex !== undefined\n );\n if (annotationsWithBoundaries.length > 0 && processedSeries.length > 0) {\n peaksWithData.push({\n peaks: annotationsWithBoundaries,\n seriesIndex: 0, // User annotations apply to first series by default\n x: processedSeries[0].x,\n y: processedSeries[0].y,\n });\n }\n\n return peaksWithData;\n}\n\n/**\n * Build the extra content for Plotly hovertemplate from series metadata.\n * Displays all metadata fields as key: value pairs.\n */\nexport function buildHoverExtraContent(\n seriesName: string,\n metadata?: Record<string, unknown>\n): string {\n if (!metadata) return seriesName;\n\n const metaLines: string[] = [];\n for (const [key, value] of Object.entries(metadata)) {\n if (value !== undefined && value !== null && value !== \"\") {\n // Format the key as Title Case (e.g., \"sampleName\" -> \"Sample Name\")\n const formattedKey = key\n .replace(/([A-Z])/g, \" $1\")\n .replace(/^./, (s) => s.toUpperCase())\n .trim();\n metaLines.push(`${formattedKey}: ${String(value)}`);\n }\n }\n\n if (metaLines.length > 0) {\n return `${seriesName}<br>${metaLines.join(\"<br>\")}`;\n }\n return seriesName;\n}\n\n/**\n * Validate and sanitize series data.\n * - Ensures x and y arrays have the same length (truncates to shorter)\n * - Replaces NaN and Infinity values with 0\n */\nexport function validateSeriesData(\n x: number[],\n y: number[]\n): { x: number[]; y: number[] } {\n // Ensure arrays have same length\n const length = Math.min(x.length, y.length);\n const validX = x.slice(0, length);\n const validY = y.slice(0, length);\n\n // Sanitize NaN and Infinity values\n const sanitizedY = validY.map((val) => (Number.isFinite(val) ? val : 0));\n const sanitizedX = validX.map((val) => (Number.isFinite(val) ? val : 0));\n\n return { x: sanitizedX, y: sanitizedY };\n}\n\n/**\n * Apply baseline correction to signal data\n */\nexport function applyBaselineCorrection(\n y: number[],\n method: BaselineCorrectionMethod,\n windowSize: number = 50\n): number[] {\n if (method === \"none\" || y.length === 0) return y;\n\n if (method === \"linear\") {\n // Linear baseline from first to last point\n // Handle single-point case to avoid division by zero\n if (y.length === 1) {\n return [0]; // Single point baseline-corrected to zero\n }\n const slope = (y[y.length - 1] - y[0]) / (y.length - 1);\n return y.map((val, i) => val - (y[0] + slope * i));\n }\n\n if (method === \"rolling\") {\n // Rolling minimum baseline\n const baseline: number[] = [];\n const halfWindow = Math.floor(windowSize / 2);\n\n for (let i = 0; i < y.length; i++) {\n const start = Math.max(0, i - halfWindow);\n const end = Math.min(y.length, i + halfWindow + 1);\n const windowSlice = y.slice(start, end);\n baseline.push(Math.min(...windowSlice));\n }\n\n return y.map((val, i) => val - baseline[i]);\n }\n\n return y;\n}\n\n"],"names":["findClosestIndex","arr","target","left","right","mid","processUserAnnotations","annotations","xArray","yArray","ann","startIndex","endIndex","index","area","calculatePeakArea","collectPeaksWithBoundaryData","allDetectedPeaks","processedSeries","peaksWithData","peaks","seriesIndex","annotationsWithBoundaries","validateSeriesData","x","y","length","validX","sanitizedY","val","applyBaselineCorrection","method","windowSize","slope","baseline","halfWindow","start","end","windowSlice"
|
|
1
|
+
{"version":3,"file":"dataProcessing.js","sources":["../../../../src/components/charts/ChromatogramChart/dataProcessing.ts"],"sourcesContent":["/**\n * Data processing utilities for ChromatogramChart\n */\n\nimport { calculatePeakArea } from \"./peakDetection\";\n\nimport type { BaselineCorrectionMethod, PeakAnnotation } from \"./types\";\n\n/**\n * Data structure for peaks with their associated series data\n */\nexport type PeakDataWithSeries = {\n peaks: PeakAnnotation[];\n seriesIndex: number;\n x: number[];\n y: number[];\n};\n\n/**\n * Find the closest index in an array for a given target value.\n * Uses binary search for efficiency.\n */\nexport function findClosestIndex(arr: number[], target: number): number {\n if (arr.length === 0) return 0;\n if (arr.length === 1) return 0;\n\n let left = 0;\n let right = arr.length - 1;\n\n while (left < right) {\n const mid = Math.floor((left + right) / 2);\n if (arr[mid] < target) {\n left = mid + 1;\n } else {\n right = mid;\n }\n }\n\n // Check if left-1 is closer\n if (left > 0 && Math.abs(arr[left - 1] - target) < Math.abs(arr[left] - target)) {\n return left - 1;\n }\n return left;\n}\n\n/**\n * Process user annotations to convert startX/endX to startIndex/endIndex\n * and compute area if boundaries are provided.\n */\nexport function processUserAnnotations(\n annotations: PeakAnnotation[],\n xArray: number[],\n yArray: number[]\n): PeakAnnotation[] {\n return annotations.map((ann) => {\n // If startX/endX are provided, convert to indices\n if (ann.startX !== undefined && ann.endX !== undefined) {\n const startIndex = findClosestIndex(xArray, ann.startX);\n const endIndex = findClosestIndex(xArray, ann.endX);\n const index = findClosestIndex(xArray, ann.x);\n\n // Calculate area if not provided\n const area = ann._computed?.area ?? calculatePeakArea(xArray, yArray, startIndex, endIndex);\n\n return {\n ...ann,\n _computed: {\n ...ann._computed,\n index,\n startIndex,\n endIndex,\n area,\n },\n };\n }\n return ann;\n });\n}\n\n/**\n * Collect peaks with boundary information from both auto-detected peaks and user-provided annotations.\n * User-provided annotations with startIndex/endIndex or startX/endX are included for boundary marker rendering.\n */\nexport function collectPeaksWithBoundaryData(\n allDetectedPeaks: { peaks: PeakAnnotation[]; seriesIndex: number }[],\n annotations: PeakAnnotation[],\n processedSeries: { x: number[]; y: number[] }[]\n): PeakDataWithSeries[] {\n const peaksWithData: PeakDataWithSeries[] = [];\n\n // Add auto-detected peaks\n allDetectedPeaks.forEach(({ peaks, seriesIndex }) => {\n peaksWithData.push({\n peaks,\n seriesIndex,\n x: processedSeries[seriesIndex].x,\n y: processedSeries[seriesIndex].y,\n });\n });\n\n // Add user-provided annotations that have boundary info (_computed.startIndex and _computed.endIndex)\n // Note: annotations with startX/endX should already be processed to have _computed fields\n const annotationsWithBoundaries = annotations.filter(\n (ann) => ann._computed?.startIndex !== undefined && ann._computed?.endIndex !== undefined\n );\n if (annotationsWithBoundaries.length > 0 && processedSeries.length > 0) {\n peaksWithData.push({\n peaks: annotationsWithBoundaries,\n seriesIndex: 0, // User annotations apply to first series by default\n x: processedSeries[0].x,\n y: processedSeries[0].y,\n });\n }\n\n return peaksWithData;\n}\n\n/**\n * Build the extra content for Plotly hovertemplate from series metadata.\n * Displays all metadata fields as key: value pairs.\n */\nexport function buildHoverExtraContent(\n seriesName: string,\n metadata?: Record<string, unknown>\n): string {\n if (!metadata) return seriesName;\n\n const metaLines: string[] = [];\n for (const [key, value] of Object.entries(metadata)) {\n if (value !== undefined && value !== null && value !== \"\") {\n // Format the key as Title Case (e.g., \"sampleName\" -> \"Sample Name\")\n const formattedKey = key\n .replace(/([A-Z])/g, \" $1\")\n .replace(/^./, (s) => s.toUpperCase())\n .trim();\n metaLines.push(`${formattedKey}: ${String(value)}`);\n }\n }\n\n if (metaLines.length > 0) {\n return `${seriesName}<br>${metaLines.join(\"<br>\")}`;\n }\n return seriesName;\n}\n\n/**\n * Validate and sanitize series data.\n * - Ensures x and y arrays have the same length (truncates to shorter)\n * - Replaces NaN and Infinity values with 0\n */\nexport function validateSeriesData(\n x: number[],\n y: number[]\n): { x: number[]; y: number[] } {\n // Ensure arrays have same length\n const length = Math.min(x.length, y.length);\n const validX = x.slice(0, length);\n const validY = y.slice(0, length);\n\n // Sanitize NaN and Infinity values\n const sanitizedY = validY.map((val) => (Number.isFinite(val) ? val : 0));\n const sanitizedX = validX.map((val) => (Number.isFinite(val) ? val : 0));\n\n return { x: sanitizedX, y: sanitizedY };\n}\n\n/**\n * Apply baseline correction to signal data\n */\nexport function applyBaselineCorrection(\n y: number[],\n method: BaselineCorrectionMethod,\n windowSize: number = 50\n): number[] {\n if (method === \"none\" || y.length === 0) return y;\n\n if (method === \"linear\") {\n // Linear baseline from first to last point\n // Handle single-point case to avoid division by zero\n if (y.length === 1) {\n return [0]; // Single point baseline-corrected to zero\n }\n const slope = (y[y.length - 1] - y[0]) / (y.length - 1);\n return y.map((val, i) => val - (y[0] + slope * i));\n }\n\n if (method === \"rolling\") {\n // Rolling minimum baseline\n const baseline: number[] = [];\n const halfWindow = Math.floor(windowSize / 2);\n\n for (let i = 0; i < y.length; i++) {\n const start = Math.max(0, i - halfWindow);\n const end = Math.min(y.length, i + halfWindow + 1);\n const windowSlice = y.slice(start, end);\n baseline.push(Math.min(...windowSlice));\n }\n\n return y.map((val, i) => val - baseline[i]);\n }\n\n return y;\n}\n\n"],"names":["findClosestIndex","arr","target","left","right","mid","processUserAnnotations","annotations","xArray","yArray","ann","startIndex","endIndex","index","area","calculatePeakArea","collectPeaksWithBoundaryData","allDetectedPeaks","processedSeries","peaksWithData","peaks","seriesIndex","annotationsWithBoundaries","buildHoverExtraContent","seriesName","metadata","metaLines","key","value","formattedKey","s","validateSeriesData","x","y","length","validX","sanitizedY","val","applyBaselineCorrection","method","windowSize","slope","i","baseline","halfWindow","start","end","windowSlice"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const m=require("plotly.js-dist"),g=require("../../../utils/colors.cjs"),k=require("./boundaryMarkers.cjs"),l=require("./constants.cjs"),x=require("./dataProcessing.cjs"),y=require("./regionOverlays.cjs");function C(n){const{processedSeries:r,processedAnnotations:a,allDetectedPeaks:u,allPeaksForInteraction:s,showMarkers:d,markerSize:p,xAxisTitle:A,yAxisTitle:i,boundaryMarkers:h}=n,T=r.map((t,c)=>{const e=t.color||g.CHART_COLORS[c%g.CHART_COLORS.length],f=x.buildHoverExtraContent(t.name,t.metadata),o={x:t.x,y:t.y,type:"scatter",mode:d?"lines+markers":"lines",name:t.name,line:{color:e,width:l.CHROMATOGRAM_TRACE.BASE_LINE_WIDTH},hovertemplate:`%{x:.2f} ${A}<br>%{y:.2f} ${i}<extra>${f}</extra>`};return d&&(o.marker={size:p,color:e}),o});if(h!=="none"){const t=x.collectPeaksWithBoundaryData(u,a,r);t.length>0&&T.push(...k.createBoundaryMarkerTraces(t))}if(a.forEach(t=>{t.regionOverlay&&r[0]&&T.push(...y.createRegionOverlayTraces([t],0,r[0]))}),u.forEach(({peaks:t,seriesIndex:c})=>{t.some(e=>e.regionOverlay)&&r[c]&&T.push(...y.createRegionOverlayTraces(t,c,r[c]))}),s.length>0){const t=s.some(e=>e.peak.hoverText),c={x:s.map(e=>e.peak.x),y:s.map(e=>e.peak.y),type:"scatter",mode:"markers",marker:{size:14,opacity:0},showlegend:!1,name:"",customdata:s.map(e=>({id:e.peak.id,peak:e.peak,seriesIndex:e.seriesIndex,seriesName:e.seriesName,isAutoDetected:e.isAutoDetected})),...t?{hovertemplate:s.map(e=>e.peak.hoverText?`${e.peak.hoverText}<extra></extra>`:"<extra></extra>")}:{hovertemplate:"<extra></extra>"}};T.push(c)}return T}function M(n){const{title:r,titleFontSize:a,titleTopMargin:u,width:s,height:d,xAxisTitle:p,yAxisTitle:A,xRange:i,yRange:h,showLegend:T,seriesCount:t,showGridX:c,showGridY:e,showCrosshairs:f,theme:o,peakAnnotations:O}=n;return{title:r?{text:r,font:{size:a,family:"Inter, sans-serif",color:o.textColor}}:void 0,width:s,height:d,margin:{l:l.CHROMATOGRAM_LAYOUT.MARGIN_LEFT,r:l.CHROMATOGRAM_LAYOUT.MARGIN_RIGHT,b:l.CHROMATOGRAM_LAYOUT.MARGIN_BOTTOM,t:r?u??l.CHROMATOGRAM_LAYOUT.MARGIN_TOP_WITH_TITLE:l.CHROMATOGRAM_LAYOUT.MARGIN_TOP_NO_TITLE,pad:l.CHROMATOGRAM_LAYOUT.MARGIN_PAD},paper_bgcolor:o.paperBg,plot_bgcolor:o.plotBg,font:{family:"Inter, sans-serif"},hovermode:f?"x":"x unified",dragmode:"zoom",xaxis:{title:{text:p,font:{size:14,color:o.textSecondary,family:"Inter, sans-serif"},standoff:15},showgrid:c,gridcolor:o.gridColor,linecolor:o.lineColor,linewidth:1,range:i,autorange:!i,zeroline:!1,tickfont:{size:12,color:o.textColor,family:"Inter, sans-serif"},showspikes:f,spikemode:"across",spikesnap:"cursor",spikecolor:o.spikeColor,spikethickness:1,spikedash:"dot"},yaxis:{title:{text:A,font:{size:14,color:o.textSecondary,family:"Inter, sans-serif"},standoff:10},showgrid:e,gridcolor:o.gridColor,linecolor:o.lineColor,linewidth:1,range:h,autorange:!h,zeroline:!1,tickfont:{size:12,color:o.textColor,family:"Inter, sans-serif"},showspikes:f,spikemode:"across",spikesnap:"cursor",spikecolor:o.spikeColor,spikethickness:1,spikedash:"dot"},legend:{x:.5,y:-.15,xanchor:"center",yanchor:"top",orientation:"h",font:{size:12,color:o.textColor,family:"Inter, sans-serif"}},showlegend:T&&t>1,annotations:O}}function R(n){const{showExportButton:r,width:a,height:u}=n;return{responsive:!0,displayModeBar:!0,displaylogo:!1,modeBarButtonsToRemove:["lasso2d","select2d",...r?[]:["toImage"]],...r&&{toImageButtonOptions:{format:"png",filename:"chromatogram",width:a,height:u}}}}function _(n,r,a,u,s){return d=>{const p=d.points[0];if(p&&p.curveNumber<r){const i=p.curveNumber;a.current!==i&&(a.current!==null&&m.restyle(n,{"line.width":l.CHROMATOGRAM_TRACE.BASE_LINE_WIDTH},[a.current]),m.restyle(n,{"line.width":l.CHROMATOGRAM_TRACE.BASE_LINE_WIDTH*s},[i]),a.current=i)}const A=d.points.find(i=>i.customdata!=null);A&&u.current?.(A.customdata)}}function I(n,r,a){return()=>{a.current?.(null),r.current!==null&&(m.restyle(n,{"line.width":l.CHROMATOGRAM_TRACE.BASE_LINE_WIDTH},[r.current]),r.current=null)}}exports.buildConfig=R;exports.buildLayout=M;exports.buildTraceData=C;exports.createHoverHandler=_;exports.createUnhoverHandler=I;
|
|
2
|
+
//# sourceMappingURL=plotBuilder.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plotBuilder.cjs","sources":["../../../../src/components/charts/ChromatogramChart/plotBuilder.ts"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\n\nimport { CHART_COLORS } from \"../../../utils/colors\";\n\nimport { createBoundaryMarkerTraces } from \"./boundaryMarkers\";\nimport { CHROMATOGRAM_LAYOUT, CHROMATOGRAM_TRACE } from \"./constants\";\nimport { buildHoverExtraContent, collectPeaksWithBoundaryData } from \"./dataProcessing\";\nimport { createRegionOverlayTraces } from \"./regionOverlays\";\n\nimport type { ChromatogramSeries, PeakAnnotation, BoundaryMarkerStyle, PeakSelectEvent } from \"./types\";\nimport type { PlotlyThemeColors } from \"@/hooks/use-plotly-theme\";\n\ntype PeakForInteraction = {\n peak: PeakAnnotation & { id: string };\n seriesIndex: number;\n seriesName: string;\n isAutoDetected: boolean;\n};\n\ntype BuildTraceDataParams = {\n processedSeries: ChromatogramSeries[];\n processedAnnotations: PeakAnnotation[];\n allDetectedPeaks: { peaks: PeakAnnotation[]; seriesIndex: number }[];\n allPeaksForInteraction: PeakForInteraction[];\n showMarkers: boolean;\n markerSize: number;\n xAxisTitle: string;\n yAxisTitle: string;\n boundaryMarkers: BoundaryMarkerStyle;\n};\n\ntype BuildLayoutParams = {\n title?: string;\n titleFontSize: number;\n titleTopMargin?: number;\n width: number;\n height: number;\n xAxisTitle: string;\n yAxisTitle: string;\n xRange?: [number, number];\n yRange?: [number, number];\n showLegend: boolean;\n seriesCount: number;\n showGridX: boolean;\n showGridY: boolean;\n showCrosshairs: boolean;\n theme: PlotlyThemeColors;\n peakAnnotations: Partial<Plotly.Annotations>[];\n};\n\ntype BuildConfigParams = {\n showExportButton: boolean;\n width: number;\n height: number;\n};\n\nexport type { PeakForInteraction, BuildTraceDataParams, BuildLayoutParams, BuildConfigParams };\n\nexport function buildTraceData(params: BuildTraceDataParams): Plotly.Data[] {\n const {\n processedSeries,\n processedAnnotations,\n allDetectedPeaks,\n allPeaksForInteraction,\n showMarkers,\n markerSize,\n xAxisTitle,\n yAxisTitle,\n boundaryMarkers,\n } = params;\n\n const plotData: Plotly.Data[] = processedSeries.map((s, index) => {\n const traceColor = s.color || CHART_COLORS[index % CHART_COLORS.length];\n const extraContent = buildHoverExtraContent(s.name, s.metadata);\n\n const trace: Plotly.Data = {\n x: s.x,\n y: s.y,\n type: \"scatter\" as const,\n mode: showMarkers ? (\"lines+markers\" as const) : (\"lines\" as const),\n name: s.name,\n line: {\n color: traceColor,\n width: CHROMATOGRAM_TRACE.BASE_LINE_WIDTH,\n },\n hovertemplate: `%{x:.2f} ${xAxisTitle}<br>%{y:.2f} ${yAxisTitle}<extra>${extraContent}</extra>`,\n };\n if (showMarkers) {\n trace.marker = { size: markerSize, color: traceColor };\n }\n return trace;\n });\n\n if (boundaryMarkers !== \"none\") {\n const peaksWithData = collectPeaksWithBoundaryData(\n allDetectedPeaks,\n processedAnnotations,\n processedSeries\n );\n if (peaksWithData.length > 0) {\n plotData.push(...createBoundaryMarkerTraces(peaksWithData));\n }\n }\n\n processedAnnotations.forEach((ann) => {\n if (ann.regionOverlay && processedSeries[0]) {\n plotData.push(...createRegionOverlayTraces([ann], 0, processedSeries[0]));\n }\n });\n allDetectedPeaks.forEach(({ peaks, seriesIndex }) => {\n if (peaks.some((p) => p.regionOverlay) && processedSeries[seriesIndex]) {\n plotData.push(...createRegionOverlayTraces(peaks, seriesIndex, processedSeries[seriesIndex]));\n }\n });\n\n if (allPeaksForInteraction.length > 0) {\n const anyHoverText = allPeaksForInteraction.some((p) => p.peak.hoverText);\n const hitAreaTrace: Plotly.Data = {\n x: allPeaksForInteraction.map((p) => p.peak.x),\n y: allPeaksForInteraction.map((p) => p.peak.y),\n type: \"scatter\" as const,\n mode: \"markers\" as const,\n marker: { size: 14, opacity: 0 },\n showlegend: false,\n name: \"\",\n customdata: allPeaksForInteraction.map((p) => ({\n id: p.peak.id,\n peak: p.peak,\n seriesIndex: p.seriesIndex,\n seriesName: p.seriesName,\n isAutoDetected: p.isAutoDetected,\n })) as unknown as Plotly.Datum[],\n ...(anyHoverText\n ? {\n hovertemplate: allPeaksForInteraction.map((p) =>\n p.peak.hoverText ? `${p.peak.hoverText}<extra></extra>` : \"<extra></extra>\"\n ),\n }\n : { hovertemplate: \"<extra></extra>\" }),\n };\n plotData.push(hitAreaTrace);\n }\n\n return plotData;\n}\n\nexport function buildLayout(params: BuildLayoutParams): Partial<Plotly.Layout> {\n const {\n title,\n titleFontSize,\n titleTopMargin,\n width,\n height,\n xAxisTitle,\n yAxisTitle,\n xRange,\n yRange,\n showLegend,\n seriesCount,\n showGridX,\n showGridY,\n showCrosshairs,\n theme,\n peakAnnotations,\n } = params;\n\n return {\n title: title\n ? {\n text: title,\n font: { size: titleFontSize, family: \"Inter, sans-serif\", color: theme.textColor },\n }\n : undefined,\n width,\n height,\n margin: {\n l: CHROMATOGRAM_LAYOUT.MARGIN_LEFT,\n r: CHROMATOGRAM_LAYOUT.MARGIN_RIGHT,\n b: CHROMATOGRAM_LAYOUT.MARGIN_BOTTOM,\n t: title\n ? (titleTopMargin ?? CHROMATOGRAM_LAYOUT.MARGIN_TOP_WITH_TITLE)\n : CHROMATOGRAM_LAYOUT.MARGIN_TOP_NO_TITLE,\n pad: CHROMATOGRAM_LAYOUT.MARGIN_PAD,\n },\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n font: { family: \"Inter, sans-serif\" },\n hovermode: showCrosshairs ? (\"x\" as const) : (\"x unified\" as const),\n dragmode: \"zoom\" as const,\n xaxis: {\n title: {\n text: xAxisTitle,\n font: { size: 14, color: theme.textSecondary, family: \"Inter, sans-serif\" },\n standoff: 15,\n },\n showgrid: showGridX,\n gridcolor: theme.gridColor,\n linecolor: theme.lineColor,\n linewidth: 1,\n range: xRange,\n autorange: !xRange,\n zeroline: false,\n tickfont: { size: 12, color: theme.textColor, family: \"Inter, sans-serif\" },\n showspikes: showCrosshairs,\n spikemode: \"across\" as const,\n spikesnap: \"cursor\" as const,\n spikecolor: theme.spikeColor,\n spikethickness: 1,\n spikedash: \"dot\" as const,\n },\n yaxis: {\n title: {\n text: yAxisTitle,\n font: { size: 14, color: theme.textSecondary, family: \"Inter, sans-serif\" },\n standoff: 10,\n },\n showgrid: showGridY,\n gridcolor: theme.gridColor,\n linecolor: theme.lineColor,\n linewidth: 1,\n range: yRange,\n autorange: !yRange,\n zeroline: false,\n tickfont: { size: 12, color: theme.textColor, family: \"Inter, sans-serif\" },\n showspikes: showCrosshairs,\n spikemode: \"across\" as const,\n spikesnap: \"cursor\" as const,\n spikecolor: theme.spikeColor,\n spikethickness: 1,\n spikedash: \"dot\" as const,\n },\n legend: {\n x: 0.5,\n y: -0.15,\n xanchor: \"center\" as const,\n yanchor: \"top\" as const,\n orientation: \"h\" as const,\n font: { size: 12, color: theme.textColor, family: \"Inter, sans-serif\" },\n },\n showlegend: showLegend && seriesCount > 1,\n annotations: peakAnnotations,\n };\n}\n\nexport function buildConfig(params: BuildConfigParams): Partial<Plotly.Config> {\n const { showExportButton, width, height } = params;\n return {\n responsive: true,\n displayModeBar: true,\n displaylogo: false,\n modeBarButtonsToRemove: [\n \"lasso2d\",\n \"select2d\",\n ...(showExportButton ? [] : ([\"toImage\"] as Plotly.ModeBarDefaultButtons[])),\n ] as Plotly.ModeBarDefaultButtons[],\n ...(showExportButton && {\n toImageButtonOptions: {\n format: \"png\",\n filename: \"chromatogram\",\n width,\n height,\n },\n }),\n };\n}\n\ntype MutableRef<T> = { current: T };\n\nexport function createHoverHandler(\n domElement: HTMLElement,\n processedSeriesLength: number,\n thickenedSeriesRef: MutableRef<number | null>,\n onPeakHoverRef: MutableRef<((event: PeakSelectEvent | null) => void) | undefined>,\n hoverLineWidthMultiplier: number\n): (eventData: Plotly.PlotHoverEvent) => void {\n return (eventData) => {\n const pt = eventData.points[0];\n if (pt && pt.curveNumber < processedSeriesLength) {\n const targetIdx = pt.curveNumber;\n if (thickenedSeriesRef.current !== targetIdx) {\n if (thickenedSeriesRef.current !== null) {\n Plotly.restyle(domElement, { \"line.width\": CHROMATOGRAM_TRACE.BASE_LINE_WIDTH } as Plotly.Data, [thickenedSeriesRef.current]);\n }\n Plotly.restyle(domElement, { \"line.width\": CHROMATOGRAM_TRACE.BASE_LINE_WIDTH * hoverLineWidthMultiplier } as Plotly.Data, [targetIdx]);\n thickenedSeriesRef.current = targetIdx;\n }\n }\n const peakPoint = eventData.points.find((p) => p.customdata != null);\n if (peakPoint) {\n onPeakHoverRef.current?.(peakPoint.customdata as unknown as PeakSelectEvent);\n }\n };\n}\n\nexport function createUnhoverHandler(\n domElement: HTMLElement,\n thickenedSeriesRef: MutableRef<number | null>,\n onPeakHoverRef: MutableRef<((event: PeakSelectEvent | null) => void) | undefined>\n): () => void {\n return () => {\n onPeakHoverRef.current?.(null);\n if (thickenedSeriesRef.current !== null) {\n Plotly.restyle(domElement, { \"line.width\": CHROMATOGRAM_TRACE.BASE_LINE_WIDTH } as Plotly.Data, [thickenedSeriesRef.current]);\n thickenedSeriesRef.current = null;\n }\n };\n}\n"],"names":["buildTraceData","params","processedSeries","processedAnnotations","allDetectedPeaks","allPeaksForInteraction","showMarkers","markerSize","xAxisTitle","yAxisTitle","boundaryMarkers","plotData","s","index","traceColor","CHART_COLORS","extraContent","buildHoverExtraContent","trace","CHROMATOGRAM_TRACE","peaksWithData","collectPeaksWithBoundaryData","createBoundaryMarkerTraces","ann","createRegionOverlayTraces","peaks","seriesIndex","p","anyHoverText","hitAreaTrace","buildLayout","title","titleFontSize","titleTopMargin","width","height","xRange","yRange","showLegend","seriesCount","showGridX","showGridY","showCrosshairs","theme","peakAnnotations","CHROMATOGRAM_LAYOUT","buildConfig","showExportButton","createHoverHandler","domElement","processedSeriesLength","thickenedSeriesRef","onPeakHoverRef","hoverLineWidthMultiplier","eventData","pt","targetIdx","Plotly","peakPoint","createUnhoverHandler"],"mappings":"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"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import y from "plotly.js-dist";
|
|
2
|
+
import { CHART_COLORS as k } from "../../../utils/colors.js";
|
|
3
|
+
import { createBoundaryMarkerTraces as A } from "./boundaryMarkers.js";
|
|
4
|
+
import { CHROMATOGRAM_TRACE as g, CHROMATOGRAM_LAYOUT as f } from "./constants.js";
|
|
5
|
+
import { buildHoverExtraContent as _, collectPeaksWithBoundaryData as C } from "./dataProcessing.js";
|
|
6
|
+
import { createRegionOverlayTraces as T } from "./regionOverlays.js";
|
|
7
|
+
function B(i) {
|
|
8
|
+
const {
|
|
9
|
+
processedSeries: t,
|
|
10
|
+
processedAnnotations: a,
|
|
11
|
+
allDetectedPeaks: c,
|
|
12
|
+
allPeaksForInteraction: n,
|
|
13
|
+
showMarkers: p,
|
|
14
|
+
markerSize: m,
|
|
15
|
+
xAxisTitle: u,
|
|
16
|
+
yAxisTitle: s,
|
|
17
|
+
boundaryMarkers: x
|
|
18
|
+
} = i, d = t.map((o, l) => {
|
|
19
|
+
const e = o.color || k[l % k.length], h = _(o.name, o.metadata), r = {
|
|
20
|
+
x: o.x,
|
|
21
|
+
y: o.y,
|
|
22
|
+
type: "scatter",
|
|
23
|
+
mode: p ? "lines+markers" : "lines",
|
|
24
|
+
name: o.name,
|
|
25
|
+
line: {
|
|
26
|
+
color: e,
|
|
27
|
+
width: g.BASE_LINE_WIDTH
|
|
28
|
+
},
|
|
29
|
+
hovertemplate: `%{x:.2f} ${u}<br>%{y:.2f} ${s}<extra>${h}</extra>`
|
|
30
|
+
};
|
|
31
|
+
return p && (r.marker = { size: m, color: e }), r;
|
|
32
|
+
});
|
|
33
|
+
if (x !== "none") {
|
|
34
|
+
const o = C(
|
|
35
|
+
c,
|
|
36
|
+
a,
|
|
37
|
+
t
|
|
38
|
+
);
|
|
39
|
+
o.length > 0 && d.push(...A(o));
|
|
40
|
+
}
|
|
41
|
+
if (a.forEach((o) => {
|
|
42
|
+
o.regionOverlay && t[0] && d.push(...T([o], 0, t[0]));
|
|
43
|
+
}), c.forEach(({ peaks: o, seriesIndex: l }) => {
|
|
44
|
+
o.some((e) => e.regionOverlay) && t[l] && d.push(...T(o, l, t[l]));
|
|
45
|
+
}), n.length > 0) {
|
|
46
|
+
const o = n.some((e) => e.peak.hoverText), l = {
|
|
47
|
+
x: n.map((e) => e.peak.x),
|
|
48
|
+
y: n.map((e) => e.peak.y),
|
|
49
|
+
type: "scatter",
|
|
50
|
+
mode: "markers",
|
|
51
|
+
marker: { size: 14, opacity: 0 },
|
|
52
|
+
showlegend: !1,
|
|
53
|
+
name: "",
|
|
54
|
+
customdata: n.map((e) => ({
|
|
55
|
+
id: e.peak.id,
|
|
56
|
+
peak: e.peak,
|
|
57
|
+
seriesIndex: e.seriesIndex,
|
|
58
|
+
seriesName: e.seriesName,
|
|
59
|
+
isAutoDetected: e.isAutoDetected
|
|
60
|
+
})),
|
|
61
|
+
...o ? {
|
|
62
|
+
hovertemplate: n.map(
|
|
63
|
+
(e) => e.peak.hoverText ? `${e.peak.hoverText}<extra></extra>` : "<extra></extra>"
|
|
64
|
+
)
|
|
65
|
+
} : { hovertemplate: "<extra></extra>" }
|
|
66
|
+
};
|
|
67
|
+
d.push(l);
|
|
68
|
+
}
|
|
69
|
+
return d;
|
|
70
|
+
}
|
|
71
|
+
function H(i) {
|
|
72
|
+
const {
|
|
73
|
+
title: t,
|
|
74
|
+
titleFontSize: a,
|
|
75
|
+
titleTopMargin: c,
|
|
76
|
+
width: n,
|
|
77
|
+
height: p,
|
|
78
|
+
xAxisTitle: m,
|
|
79
|
+
yAxisTitle: u,
|
|
80
|
+
xRange: s,
|
|
81
|
+
yRange: x,
|
|
82
|
+
showLegend: d,
|
|
83
|
+
seriesCount: o,
|
|
84
|
+
showGridX: l,
|
|
85
|
+
showGridY: e,
|
|
86
|
+
showCrosshairs: h,
|
|
87
|
+
theme: r,
|
|
88
|
+
peakAnnotations: I
|
|
89
|
+
} = i;
|
|
90
|
+
return {
|
|
91
|
+
title: t ? {
|
|
92
|
+
text: t,
|
|
93
|
+
font: { size: a, family: "Inter, sans-serif", color: r.textColor }
|
|
94
|
+
} : void 0,
|
|
95
|
+
width: n,
|
|
96
|
+
height: p,
|
|
97
|
+
margin: {
|
|
98
|
+
l: f.MARGIN_LEFT,
|
|
99
|
+
r: f.MARGIN_RIGHT,
|
|
100
|
+
b: f.MARGIN_BOTTOM,
|
|
101
|
+
t: t ? c ?? f.MARGIN_TOP_WITH_TITLE : f.MARGIN_TOP_NO_TITLE,
|
|
102
|
+
pad: f.MARGIN_PAD
|
|
103
|
+
},
|
|
104
|
+
paper_bgcolor: r.paperBg,
|
|
105
|
+
plot_bgcolor: r.plotBg,
|
|
106
|
+
font: { family: "Inter, sans-serif" },
|
|
107
|
+
hovermode: h ? "x" : "x unified",
|
|
108
|
+
dragmode: "zoom",
|
|
109
|
+
xaxis: {
|
|
110
|
+
title: {
|
|
111
|
+
text: m,
|
|
112
|
+
font: { size: 14, color: r.textSecondary, family: "Inter, sans-serif" },
|
|
113
|
+
standoff: 15
|
|
114
|
+
},
|
|
115
|
+
showgrid: l,
|
|
116
|
+
gridcolor: r.gridColor,
|
|
117
|
+
linecolor: r.lineColor,
|
|
118
|
+
linewidth: 1,
|
|
119
|
+
range: s,
|
|
120
|
+
autorange: !s,
|
|
121
|
+
zeroline: !1,
|
|
122
|
+
tickfont: { size: 12, color: r.textColor, family: "Inter, sans-serif" },
|
|
123
|
+
showspikes: h,
|
|
124
|
+
spikemode: "across",
|
|
125
|
+
spikesnap: "cursor",
|
|
126
|
+
spikecolor: r.spikeColor,
|
|
127
|
+
spikethickness: 1,
|
|
128
|
+
spikedash: "dot"
|
|
129
|
+
},
|
|
130
|
+
yaxis: {
|
|
131
|
+
title: {
|
|
132
|
+
text: u,
|
|
133
|
+
font: { size: 14, color: r.textSecondary, family: "Inter, sans-serif" },
|
|
134
|
+
standoff: 10
|
|
135
|
+
},
|
|
136
|
+
showgrid: e,
|
|
137
|
+
gridcolor: r.gridColor,
|
|
138
|
+
linecolor: r.lineColor,
|
|
139
|
+
linewidth: 1,
|
|
140
|
+
range: x,
|
|
141
|
+
autorange: !x,
|
|
142
|
+
zeroline: !1,
|
|
143
|
+
tickfont: { size: 12, color: r.textColor, family: "Inter, sans-serif" },
|
|
144
|
+
showspikes: h,
|
|
145
|
+
spikemode: "across",
|
|
146
|
+
spikesnap: "cursor",
|
|
147
|
+
spikecolor: r.spikeColor,
|
|
148
|
+
spikethickness: 1,
|
|
149
|
+
spikedash: "dot"
|
|
150
|
+
},
|
|
151
|
+
legend: {
|
|
152
|
+
x: 0.5,
|
|
153
|
+
y: -0.15,
|
|
154
|
+
xanchor: "center",
|
|
155
|
+
yanchor: "top",
|
|
156
|
+
orientation: "h",
|
|
157
|
+
font: { size: 12, color: r.textColor, family: "Inter, sans-serif" }
|
|
158
|
+
},
|
|
159
|
+
showlegend: d && o > 1,
|
|
160
|
+
annotations: I
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function z(i) {
|
|
164
|
+
const { showExportButton: t, width: a, height: c } = i;
|
|
165
|
+
return {
|
|
166
|
+
responsive: !0,
|
|
167
|
+
displayModeBar: !0,
|
|
168
|
+
displaylogo: !1,
|
|
169
|
+
modeBarButtonsToRemove: [
|
|
170
|
+
"lasso2d",
|
|
171
|
+
"select2d",
|
|
172
|
+
...t ? [] : ["toImage"]
|
|
173
|
+
],
|
|
174
|
+
...t && {
|
|
175
|
+
toImageButtonOptions: {
|
|
176
|
+
format: "png",
|
|
177
|
+
filename: "chromatogram",
|
|
178
|
+
width: a,
|
|
179
|
+
height: c
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
function R(i, t, a, c, n) {
|
|
185
|
+
return (p) => {
|
|
186
|
+
const m = p.points[0];
|
|
187
|
+
if (m && m.curveNumber < t) {
|
|
188
|
+
const s = m.curveNumber;
|
|
189
|
+
a.current !== s && (a.current !== null && y.restyle(i, { "line.width": g.BASE_LINE_WIDTH }, [a.current]), y.restyle(i, { "line.width": g.BASE_LINE_WIDTH * n }, [s]), a.current = s);
|
|
190
|
+
}
|
|
191
|
+
const u = p.points.find((s) => s.customdata != null);
|
|
192
|
+
u && c.current?.(u.customdata);
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function b(i, t, a) {
|
|
196
|
+
return () => {
|
|
197
|
+
a.current?.(null), t.current !== null && (y.restyle(i, { "line.width": g.BASE_LINE_WIDTH }, [t.current]), t.current = null);
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
export {
|
|
201
|
+
z as buildConfig,
|
|
202
|
+
H as buildLayout,
|
|
203
|
+
B as buildTraceData,
|
|
204
|
+
R as createHoverHandler,
|
|
205
|
+
b as createUnhoverHandler
|
|
206
|
+
};
|
|
207
|
+
//# sourceMappingURL=plotBuilder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plotBuilder.js","sources":["../../../../src/components/charts/ChromatogramChart/plotBuilder.ts"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\n\nimport { CHART_COLORS } from \"../../../utils/colors\";\n\nimport { createBoundaryMarkerTraces } from \"./boundaryMarkers\";\nimport { CHROMATOGRAM_LAYOUT, CHROMATOGRAM_TRACE } from \"./constants\";\nimport { buildHoverExtraContent, collectPeaksWithBoundaryData } from \"./dataProcessing\";\nimport { createRegionOverlayTraces } from \"./regionOverlays\";\n\nimport type { ChromatogramSeries, PeakAnnotation, BoundaryMarkerStyle, PeakSelectEvent } from \"./types\";\nimport type { PlotlyThemeColors } from \"@/hooks/use-plotly-theme\";\n\ntype PeakForInteraction = {\n peak: PeakAnnotation & { id: string };\n seriesIndex: number;\n seriesName: string;\n isAutoDetected: boolean;\n};\n\ntype BuildTraceDataParams = {\n processedSeries: ChromatogramSeries[];\n processedAnnotations: PeakAnnotation[];\n allDetectedPeaks: { peaks: PeakAnnotation[]; seriesIndex: number }[];\n allPeaksForInteraction: PeakForInteraction[];\n showMarkers: boolean;\n markerSize: number;\n xAxisTitle: string;\n yAxisTitle: string;\n boundaryMarkers: BoundaryMarkerStyle;\n};\n\ntype BuildLayoutParams = {\n title?: string;\n titleFontSize: number;\n titleTopMargin?: number;\n width: number;\n height: number;\n xAxisTitle: string;\n yAxisTitle: string;\n xRange?: [number, number];\n yRange?: [number, number];\n showLegend: boolean;\n seriesCount: number;\n showGridX: boolean;\n showGridY: boolean;\n showCrosshairs: boolean;\n theme: PlotlyThemeColors;\n peakAnnotations: Partial<Plotly.Annotations>[];\n};\n\ntype BuildConfigParams = {\n showExportButton: boolean;\n width: number;\n height: number;\n};\n\nexport type { PeakForInteraction, BuildTraceDataParams, BuildLayoutParams, BuildConfigParams };\n\nexport function buildTraceData(params: BuildTraceDataParams): Plotly.Data[] {\n const {\n processedSeries,\n processedAnnotations,\n allDetectedPeaks,\n allPeaksForInteraction,\n showMarkers,\n markerSize,\n xAxisTitle,\n yAxisTitle,\n boundaryMarkers,\n } = params;\n\n const plotData: Plotly.Data[] = processedSeries.map((s, index) => {\n const traceColor = s.color || CHART_COLORS[index % CHART_COLORS.length];\n const extraContent = buildHoverExtraContent(s.name, s.metadata);\n\n const trace: Plotly.Data = {\n x: s.x,\n y: s.y,\n type: \"scatter\" as const,\n mode: showMarkers ? (\"lines+markers\" as const) : (\"lines\" as const),\n name: s.name,\n line: {\n color: traceColor,\n width: CHROMATOGRAM_TRACE.BASE_LINE_WIDTH,\n },\n hovertemplate: `%{x:.2f} ${xAxisTitle}<br>%{y:.2f} ${yAxisTitle}<extra>${extraContent}</extra>`,\n };\n if (showMarkers) {\n trace.marker = { size: markerSize, color: traceColor };\n }\n return trace;\n });\n\n if (boundaryMarkers !== \"none\") {\n const peaksWithData = collectPeaksWithBoundaryData(\n allDetectedPeaks,\n processedAnnotations,\n processedSeries\n );\n if (peaksWithData.length > 0) {\n plotData.push(...createBoundaryMarkerTraces(peaksWithData));\n }\n }\n\n processedAnnotations.forEach((ann) => {\n if (ann.regionOverlay && processedSeries[0]) {\n plotData.push(...createRegionOverlayTraces([ann], 0, processedSeries[0]));\n }\n });\n allDetectedPeaks.forEach(({ peaks, seriesIndex }) => {\n if (peaks.some((p) => p.regionOverlay) && processedSeries[seriesIndex]) {\n plotData.push(...createRegionOverlayTraces(peaks, seriesIndex, processedSeries[seriesIndex]));\n }\n });\n\n if (allPeaksForInteraction.length > 0) {\n const anyHoverText = allPeaksForInteraction.some((p) => p.peak.hoverText);\n const hitAreaTrace: Plotly.Data = {\n x: allPeaksForInteraction.map((p) => p.peak.x),\n y: allPeaksForInteraction.map((p) => p.peak.y),\n type: \"scatter\" as const,\n mode: \"markers\" as const,\n marker: { size: 14, opacity: 0 },\n showlegend: false,\n name: \"\",\n customdata: allPeaksForInteraction.map((p) => ({\n id: p.peak.id,\n peak: p.peak,\n seriesIndex: p.seriesIndex,\n seriesName: p.seriesName,\n isAutoDetected: p.isAutoDetected,\n })) as unknown as Plotly.Datum[],\n ...(anyHoverText\n ? {\n hovertemplate: allPeaksForInteraction.map((p) =>\n p.peak.hoverText ? `${p.peak.hoverText}<extra></extra>` : \"<extra></extra>\"\n ),\n }\n : { hovertemplate: \"<extra></extra>\" }),\n };\n plotData.push(hitAreaTrace);\n }\n\n return plotData;\n}\n\nexport function buildLayout(params: BuildLayoutParams): Partial<Plotly.Layout> {\n const {\n title,\n titleFontSize,\n titleTopMargin,\n width,\n height,\n xAxisTitle,\n yAxisTitle,\n xRange,\n yRange,\n showLegend,\n seriesCount,\n showGridX,\n showGridY,\n showCrosshairs,\n theme,\n peakAnnotations,\n } = params;\n\n return {\n title: title\n ? {\n text: title,\n font: { size: titleFontSize, family: \"Inter, sans-serif\", color: theme.textColor },\n }\n : undefined,\n width,\n height,\n margin: {\n l: CHROMATOGRAM_LAYOUT.MARGIN_LEFT,\n r: CHROMATOGRAM_LAYOUT.MARGIN_RIGHT,\n b: CHROMATOGRAM_LAYOUT.MARGIN_BOTTOM,\n t: title\n ? (titleTopMargin ?? CHROMATOGRAM_LAYOUT.MARGIN_TOP_WITH_TITLE)\n : CHROMATOGRAM_LAYOUT.MARGIN_TOP_NO_TITLE,\n pad: CHROMATOGRAM_LAYOUT.MARGIN_PAD,\n },\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n font: { family: \"Inter, sans-serif\" },\n hovermode: showCrosshairs ? (\"x\" as const) : (\"x unified\" as const),\n dragmode: \"zoom\" as const,\n xaxis: {\n title: {\n text: xAxisTitle,\n font: { size: 14, color: theme.textSecondary, family: \"Inter, sans-serif\" },\n standoff: 15,\n },\n showgrid: showGridX,\n gridcolor: theme.gridColor,\n linecolor: theme.lineColor,\n linewidth: 1,\n range: xRange,\n autorange: !xRange,\n zeroline: false,\n tickfont: { size: 12, color: theme.textColor, family: \"Inter, sans-serif\" },\n showspikes: showCrosshairs,\n spikemode: \"across\" as const,\n spikesnap: \"cursor\" as const,\n spikecolor: theme.spikeColor,\n spikethickness: 1,\n spikedash: \"dot\" as const,\n },\n yaxis: {\n title: {\n text: yAxisTitle,\n font: { size: 14, color: theme.textSecondary, family: \"Inter, sans-serif\" },\n standoff: 10,\n },\n showgrid: showGridY,\n gridcolor: theme.gridColor,\n linecolor: theme.lineColor,\n linewidth: 1,\n range: yRange,\n autorange: !yRange,\n zeroline: false,\n tickfont: { size: 12, color: theme.textColor, family: \"Inter, sans-serif\" },\n showspikes: showCrosshairs,\n spikemode: \"across\" as const,\n spikesnap: \"cursor\" as const,\n spikecolor: theme.spikeColor,\n spikethickness: 1,\n spikedash: \"dot\" as const,\n },\n legend: {\n x: 0.5,\n y: -0.15,\n xanchor: \"center\" as const,\n yanchor: \"top\" as const,\n orientation: \"h\" as const,\n font: { size: 12, color: theme.textColor, family: \"Inter, sans-serif\" },\n },\n showlegend: showLegend && seriesCount > 1,\n annotations: peakAnnotations,\n };\n}\n\nexport function buildConfig(params: BuildConfigParams): Partial<Plotly.Config> {\n const { showExportButton, width, height } = params;\n return {\n responsive: true,\n displayModeBar: true,\n displaylogo: false,\n modeBarButtonsToRemove: [\n \"lasso2d\",\n \"select2d\",\n ...(showExportButton ? [] : ([\"toImage\"] as Plotly.ModeBarDefaultButtons[])),\n ] as Plotly.ModeBarDefaultButtons[],\n ...(showExportButton && {\n toImageButtonOptions: {\n format: \"png\",\n filename: \"chromatogram\",\n width,\n height,\n },\n }),\n };\n}\n\ntype MutableRef<T> = { current: T };\n\nexport function createHoverHandler(\n domElement: HTMLElement,\n processedSeriesLength: number,\n thickenedSeriesRef: MutableRef<number | null>,\n onPeakHoverRef: MutableRef<((event: PeakSelectEvent | null) => void) | undefined>,\n hoverLineWidthMultiplier: number\n): (eventData: Plotly.PlotHoverEvent) => void {\n return (eventData) => {\n const pt = eventData.points[0];\n if (pt && pt.curveNumber < processedSeriesLength) {\n const targetIdx = pt.curveNumber;\n if (thickenedSeriesRef.current !== targetIdx) {\n if (thickenedSeriesRef.current !== null) {\n Plotly.restyle(domElement, { \"line.width\": CHROMATOGRAM_TRACE.BASE_LINE_WIDTH } as Plotly.Data, [thickenedSeriesRef.current]);\n }\n Plotly.restyle(domElement, { \"line.width\": CHROMATOGRAM_TRACE.BASE_LINE_WIDTH * hoverLineWidthMultiplier } as Plotly.Data, [targetIdx]);\n thickenedSeriesRef.current = targetIdx;\n }\n }\n const peakPoint = eventData.points.find((p) => p.customdata != null);\n if (peakPoint) {\n onPeakHoverRef.current?.(peakPoint.customdata as unknown as PeakSelectEvent);\n }\n };\n}\n\nexport function createUnhoverHandler(\n domElement: HTMLElement,\n thickenedSeriesRef: MutableRef<number | null>,\n onPeakHoverRef: MutableRef<((event: PeakSelectEvent | null) => void) | undefined>\n): () => void {\n return () => {\n onPeakHoverRef.current?.(null);\n if (thickenedSeriesRef.current !== null) {\n Plotly.restyle(domElement, { \"line.width\": CHROMATOGRAM_TRACE.BASE_LINE_WIDTH } as Plotly.Data, [thickenedSeriesRef.current]);\n thickenedSeriesRef.current = null;\n }\n };\n}\n"],"names":["buildTraceData","params","processedSeries","processedAnnotations","allDetectedPeaks","allPeaksForInteraction","showMarkers","markerSize","xAxisTitle","yAxisTitle","boundaryMarkers","plotData","s","index","traceColor","CHART_COLORS","extraContent","buildHoverExtraContent","trace","CHROMATOGRAM_TRACE","peaksWithData","collectPeaksWithBoundaryData","createBoundaryMarkerTraces","ann","createRegionOverlayTraces","peaks","seriesIndex","p","anyHoverText","hitAreaTrace","buildLayout","title","titleFontSize","titleTopMargin","width","height","xRange","yRange","showLegend","seriesCount","showGridX","showGridY","showCrosshairs","theme","peakAnnotations","CHROMATOGRAM_LAYOUT","buildConfig","showExportButton","createHoverHandler","domElement","processedSeriesLength","thickenedSeriesRef","onPeakHoverRef","hoverLineWidthMultiplier","eventData","pt","targetIdx","Plotly","peakPoint","createUnhoverHandler"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("../../../utils/colors.cjs"),h=3.5;function u(s,i,o){const l=o.color??c.CHART_COLORS[i%c.CHART_COLORS.length],n=[];for(const e of s){if(!e.regionOverlay)continue;const t=e._computed?.startIndex,r=e._computed?.endIndex;if(t===void 0||r===void 0)continue;const a=e.color??l,d=e.regionOverlayWidth??h,v=e.hoverText?{hovertemplate:`${e.hoverText}<extra></extra>`}:{hoverinfo:"skip"};n.push({x:o.x.slice(t,r+1),y:o.y.slice(t,r+1),type:"scatter",mode:"lines",line:{color:a,width:d},showlegend:!1,name:"",...v})}return n}exports.createRegionOverlayTraces=u;
|
|
2
|
+
//# sourceMappingURL=regionOverlays.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regionOverlays.cjs","sources":["../../../../src/components/charts/ChromatogramChart/regionOverlays.ts"],"sourcesContent":["import { CHART_COLORS } from \"../../../utils/colors\";\n\nimport type { PeakAnnotation, ChromatogramSeries } from \"./types\";\nimport type Plotly from \"plotly.js-dist\";\n\nconst DEFAULT_REGION_OVERLAY_WIDTH = 3.5;\n\n/**\n * Build one scatter trace per peak that has regionOverlay:true, slicing the\n * underlying series data between the peak's startIndex and endIndex.\n * Traces are pushed BEFORE the invisible hit-area trace so peak click/hover\n * still resolves to the hit-area marker, not the overlay.\n */\nexport function createRegionOverlayTraces(\n peaks: PeakAnnotation[],\n seriesIndex: number,\n series: ChromatogramSeries\n): Plotly.Data[] {\n const seriesColor = series.color ?? CHART_COLORS[seriesIndex % CHART_COLORS.length];\n const traces: Plotly.Data[] = [];\n\n for (const peak of peaks) {\n if (!peak.regionOverlay) continue;\n const startIdx = peak._computed?.startIndex;\n const endIdx = peak._computed?.endIndex;\n if (startIdx === undefined || endIdx === undefined) continue;\n\n const color = peak.color ?? seriesColor;\n const lineWidth = peak.regionOverlayWidth ?? DEFAULT_REGION_OVERLAY_WIDTH;\n const hoverProps = peak.hoverText\n ? { hovertemplate: `${peak.hoverText}<extra></extra>` }\n : { hoverinfo: \"skip\" as const };\n\n traces.push({\n x: series.x.slice(startIdx, endIdx + 1),\n y: series.y.slice(startIdx, endIdx + 1),\n type: \"scatter\" as const,\n mode: \"lines\" as const,\n line: { color, width: lineWidth },\n showlegend: false,\n name: \"\",\n ...hoverProps,\n });\n }\n\n return traces;\n}\n"],"names":["DEFAULT_REGION_OVERLAY_WIDTH","createRegionOverlayTraces","peaks","seriesIndex","series","seriesColor","CHART_COLORS","traces","peak","startIdx","endIdx","color","lineWidth","hoverProps"],"mappings":"6HAKMA,EAA+B,IAQ9B,SAASC,EACdC,EACAC,EACAC,EACe,CACf,MAAMC,EAAcD,EAAO,OAASE,EAAAA,aAAaH,EAAcG,EAAAA,aAAa,MAAM,EAC5EC,EAAwB,CAAA,EAE9B,UAAWC,KAAQN,EAAO,CACxB,GAAI,CAACM,EAAK,cAAe,SACzB,MAAMC,EAAWD,EAAK,WAAW,WAC3BE,EAASF,EAAK,WAAW,SAC/B,GAAIC,IAAa,QAAaC,IAAW,OAAW,SAEpD,MAAMC,EAAQH,EAAK,OAASH,EACtBO,EAAYJ,EAAK,oBAAsBR,EACvCa,EAAaL,EAAK,UACpB,CAAE,cAAe,GAAGA,EAAK,SAAS,iBAAA,EAClC,CAAE,UAAW,MAAA,EAEjBD,EAAO,KAAK,CACV,EAAGH,EAAO,EAAE,MAAMK,EAAUC,EAAS,CAAC,EACtC,EAAGN,EAAO,EAAE,MAAMK,EAAUC,EAAS,CAAC,EACtC,KAAM,UACN,KAAM,QACN,KAAM,CAAE,MAAAC,EAAO,MAAOC,CAAA,EACtB,WAAY,GACZ,KAAM,GACN,GAAGC,CAAA,CACJ,CACH,CAEA,OAAON,CACT"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { CHART_COLORS as c } from "../../../utils/colors.js";
|
|
2
|
+
const x = 3.5;
|
|
3
|
+
function v(i, s, o) {
|
|
4
|
+
const l = o.color ?? c[s % c.length], r = [];
|
|
5
|
+
for (const e of i) {
|
|
6
|
+
if (!e.regionOverlay) continue;
|
|
7
|
+
const t = e._computed?.startIndex, n = e._computed?.endIndex;
|
|
8
|
+
if (t === void 0 || n === void 0) continue;
|
|
9
|
+
const a = e.color ?? l, d = e.regionOverlayWidth ?? x, h = e.hoverText ? { hovertemplate: `${e.hoverText}<extra></extra>` } : { hoverinfo: "skip" };
|
|
10
|
+
r.push({
|
|
11
|
+
x: o.x.slice(t, n + 1),
|
|
12
|
+
y: o.y.slice(t, n + 1),
|
|
13
|
+
type: "scatter",
|
|
14
|
+
mode: "lines",
|
|
15
|
+
line: { color: a, width: d },
|
|
16
|
+
showlegend: !1,
|
|
17
|
+
name: "",
|
|
18
|
+
...h
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
return r;
|
|
22
|
+
}
|
|
23
|
+
export {
|
|
24
|
+
v as createRegionOverlayTraces
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=regionOverlays.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regionOverlays.js","sources":["../../../../src/components/charts/ChromatogramChart/regionOverlays.ts"],"sourcesContent":["import { CHART_COLORS } from \"../../../utils/colors\";\n\nimport type { PeakAnnotation, ChromatogramSeries } from \"./types\";\nimport type Plotly from \"plotly.js-dist\";\n\nconst DEFAULT_REGION_OVERLAY_WIDTH = 3.5;\n\n/**\n * Build one scatter trace per peak that has regionOverlay:true, slicing the\n * underlying series data between the peak's startIndex and endIndex.\n * Traces are pushed BEFORE the invisible hit-area trace so peak click/hover\n * still resolves to the hit-area marker, not the overlay.\n */\nexport function createRegionOverlayTraces(\n peaks: PeakAnnotation[],\n seriesIndex: number,\n series: ChromatogramSeries\n): Plotly.Data[] {\n const seriesColor = series.color ?? CHART_COLORS[seriesIndex % CHART_COLORS.length];\n const traces: Plotly.Data[] = [];\n\n for (const peak of peaks) {\n if (!peak.regionOverlay) continue;\n const startIdx = peak._computed?.startIndex;\n const endIdx = peak._computed?.endIndex;\n if (startIdx === undefined || endIdx === undefined) continue;\n\n const color = peak.color ?? seriesColor;\n const lineWidth = peak.regionOverlayWidth ?? DEFAULT_REGION_OVERLAY_WIDTH;\n const hoverProps = peak.hoverText\n ? { hovertemplate: `${peak.hoverText}<extra></extra>` }\n : { hoverinfo: \"skip\" as const };\n\n traces.push({\n x: series.x.slice(startIdx, endIdx + 1),\n y: series.y.slice(startIdx, endIdx + 1),\n type: \"scatter\" as const,\n mode: \"lines\" as const,\n line: { color, width: lineWidth },\n showlegend: false,\n name: \"\",\n ...hoverProps,\n });\n }\n\n return traces;\n}\n"],"names":["DEFAULT_REGION_OVERLAY_WIDTH","createRegionOverlayTraces","peaks","seriesIndex","series","seriesColor","CHART_COLORS","traces","peak","startIdx","endIdx","color","lineWidth","hoverProps"],"mappings":";AAKA,MAAMA,IAA+B;AAQ9B,SAASC,EACdC,GACAC,GACAC,GACe;AACf,QAAMC,IAAcD,EAAO,SAASE,EAAaH,IAAcG,EAAa,MAAM,GAC5EC,IAAwB,CAAA;AAE9B,aAAWC,KAAQN,GAAO;AACxB,QAAI,CAACM,EAAK,cAAe;AACzB,UAAMC,IAAWD,EAAK,WAAW,YAC3BE,IAASF,EAAK,WAAW;AAC/B,QAAIC,MAAa,UAAaC,MAAW,OAAW;AAEpD,UAAMC,IAAQH,EAAK,SAASH,GACtBO,IAAYJ,EAAK,sBAAsBR,GACvCa,IAAaL,EAAK,YACpB,EAAE,eAAe,GAAGA,EAAK,SAAS,kBAAA,IAClC,EAAE,WAAW,OAAA;AAEjB,IAAAD,EAAO,KAAK;AAAA,MACV,GAAGH,EAAO,EAAE,MAAMK,GAAUC,IAAS,CAAC;AAAA,MACtC,GAAGN,EAAO,EAAE,MAAMK,GAAUC,IAAS,CAAC;AAAA,MACtC,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM,EAAE,OAAAC,GAAO,OAAOC,EAAA;AAAA,MACtB,YAAY;AAAA,MACZ,MAAM;AAAA,MACN,GAAGC;AAAA,IAAA,CACJ;AAAA,EACH;AAEA,SAAON;AACT;"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("react/jsx-runtime"),c=require("react"),h=require("../ChromatogramChart/ChromatogramChart.cjs"),C=require("./transforms.cjs");function g({series:r,stackingMode:t="overlay",stackOffset:o=0,stackingOrder:e="first-on-bottom",annotations:a,...n}){const{series:s,annotations:m,yRange:i}=c.useMemo(()=>C.applyStackingTransform(r,a,t,o,e),[r,a,t,o,e]);return u.jsx(h.ChromatogramChart,{...n,series:s,annotations:m,yRange:i})}exports.StackedChromatogramChart=g;
|
|
2
|
+
//# sourceMappingURL=StackedChromatogramChart.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StackedChromatogramChart.cjs","sources":["../../../../src/components/charts/StackedChromatogramChart/StackedChromatogramChart.tsx"],"sourcesContent":["import { useMemo } from \"react\";\n\nimport { ChromatogramChart } from \"../ChromatogramChart\";\n\nimport { applyStackingTransform } from \"./transforms\";\n\nimport type { StackedChromatogramChartProps } from \"./types\";\n\nexport function StackedChromatogramChart({\n series,\n stackingMode = \"overlay\",\n stackOffset = 0,\n stackingOrder = \"first-on-bottom\",\n annotations,\n ...restProps\n}: StackedChromatogramChartProps) {\n const {\n series: transformedSeries,\n annotations: transformedAnnotations,\n yRange,\n } = useMemo(\n () =>\n applyStackingTransform(\n series,\n annotations,\n stackingMode,\n stackOffset,\n stackingOrder\n ),\n [series, annotations, stackingMode, stackOffset, stackingOrder]\n );\n\n return (\n <ChromatogramChart\n {...restProps}\n series={transformedSeries}\n annotations={transformedAnnotations}\n yRange={yRange}\n />\n );\n}\n\nexport default StackedChromatogramChart;\n"],"names":["StackedChromatogramChart","series","stackingMode","stackOffset","stackingOrder","annotations","restProps","transformedSeries","transformedAnnotations","yRange","useMemo","applyStackingTransform","jsx","ChromatogramChart"],"mappings":"8NAQO,SAASA,EAAyB,CACvC,OAAAC,EACA,aAAAC,EAAe,UACf,YAAAC,EAAc,EACd,cAAAC,EAAgB,kBAChB,YAAAC,EACA,GAAGC,CACL,EAAkC,CAChC,KAAM,CACJ,OAAQC,EACR,YAAaC,EACb,OAAAC,CAAA,EACEC,EAAAA,QACF,IACEC,EAAAA,uBACEV,EACAI,EACAH,EACAC,EACAC,CAAA,EAEJ,CAACH,EAAQI,EAAaH,EAAcC,EAAaC,CAAa,CAAA,EAGhE,OACEQ,EAAAA,IAACC,EAAAA,kBAAA,CACE,GAAGP,EACJ,OAAQC,EACR,YAAaC,EACb,OAAAC,CAAA,CAAA,CAGN"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { jsx as f } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo as p } from "react";
|
|
3
|
+
import { ChromatogramChart as h } from "../ChromatogramChart/ChromatogramChart.js";
|
|
4
|
+
import { applyStackingTransform as C } from "./transforms.js";
|
|
5
|
+
function l({
|
|
6
|
+
series: o,
|
|
7
|
+
stackingMode: r = "overlay",
|
|
8
|
+
stackOffset: t = 0,
|
|
9
|
+
stackingOrder: m = "first-on-bottom",
|
|
10
|
+
annotations: a,
|
|
11
|
+
...n
|
|
12
|
+
}) {
|
|
13
|
+
const {
|
|
14
|
+
series: e,
|
|
15
|
+
annotations: i,
|
|
16
|
+
yRange: s
|
|
17
|
+
} = p(
|
|
18
|
+
() => C(
|
|
19
|
+
o,
|
|
20
|
+
a,
|
|
21
|
+
r,
|
|
22
|
+
t,
|
|
23
|
+
m
|
|
24
|
+
),
|
|
25
|
+
[o, a, r, t, m]
|
|
26
|
+
);
|
|
27
|
+
return /* @__PURE__ */ f(
|
|
28
|
+
h,
|
|
29
|
+
{
|
|
30
|
+
...n,
|
|
31
|
+
series: e,
|
|
32
|
+
annotations: i,
|
|
33
|
+
yRange: s
|
|
34
|
+
}
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
export {
|
|
38
|
+
l as StackedChromatogramChart
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=StackedChromatogramChart.js.map
|