larvitar 1.5.14 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/settings.json +4 -0
- package/README.md +78 -48
- package/bundler/webpack.common.js +27 -0
- package/bundler/webpack.dev.js +23 -0
- package/bundler/webpack.prod.js +19 -0
- package/decs.d.ts +12 -0
- package/dist/imaging/MetaDataReadable.d.ts +40 -0
- package/dist/imaging/MetaDataTypes.d.ts +3489 -0
- package/dist/imaging/imageAnonymization.d.ts +12 -0
- package/dist/imaging/imageColormaps.d.ts +47 -0
- package/dist/imaging/imageContours.d.ts +18 -0
- package/dist/imaging/imageIo.d.ts +42 -0
- package/dist/imaging/imageLayers.d.ts +56 -0
- package/dist/imaging/imageLoading.d.ts +65 -0
- package/dist/imaging/imageParsing.d.ts +46 -0
- package/dist/imaging/imagePresets.d.ts +43 -0
- package/dist/imaging/imageRendering.d.ts +238 -0
- package/dist/imaging/imageReslice.d.ts +14 -0
- package/dist/imaging/imageStore.d.ts +121 -0
- package/dist/imaging/imageTags.d.ts +22 -0
- package/dist/imaging/imageTools.d.ts +20 -0
- package/dist/imaging/imageUtils.d.ts +165 -0
- package/dist/imaging/loaders/commonLoader.d.ts +103 -0
- package/dist/imaging/loaders/dicomLoader.d.ts +29 -0
- package/dist/imaging/loaders/fileLoader.d.ts +33 -0
- package/dist/imaging/loaders/multiframeLoader.d.ts +37 -0
- package/dist/imaging/loaders/nrrdLoader.d.ts +113 -0
- package/dist/imaging/loaders/resliceLoader.d.ts +15 -0
- package/dist/imaging/monitors/memory.d.ts +41 -0
- package/dist/imaging/monitors/performance.d.ts +23 -0
- package/dist/imaging/parsers/ecg.d.ts +15 -0
- package/dist/imaging/parsers/nrrd.d.ts +3 -0
- package/dist/imaging/tools/custom/4dSliceScrollTool.d.ts +12 -0
- package/dist/imaging/tools/custom/BorderMagnifyTool.d.ts +18 -0
- package/dist/imaging/tools/custom/contourTool.d.ts +409 -0
- package/dist/imaging/tools/custom/diameterTool.d.ts +18 -0
- package/dist/imaging/tools/custom/editMaskTool.d.ts +22 -0
- package/dist/imaging/tools/custom/ellipticalRoiOverlayTool.d.ts +45 -0
- package/dist/imaging/tools/custom/polygonSegmentationMixin.d.ts +54 -0
- package/dist/imaging/tools/custom/polylineScissorsTool.d.ts +11 -0
- package/dist/imaging/tools/custom/rectangleRoiOverlayTool.d.ts +45 -0
- package/dist/imaging/tools/custom/seedTool.d.ts +0 -0
- package/dist/imaging/tools/custom/setLabelMap3D.d.ts +39 -0
- package/dist/imaging/tools/custom/thresholdsBrushTool.d.ts +19 -0
- package/dist/imaging/tools/default.d.ts +53 -0
- package/dist/imaging/tools/interaction.d.ts +30 -0
- package/dist/imaging/tools/io.d.ts +38 -0
- package/dist/imaging/tools/main.d.ts +81 -0
- package/dist/imaging/tools/segmentation.d.ts +125 -0
- package/dist/imaging/tools/state.d.ts +17 -0
- package/dist/imaging/tools/strategies/eraseFreehand.d.ts +16 -0
- package/dist/imaging/tools/strategies/fillFreehand.d.ts +16 -0
- package/dist/imaging/tools/strategies/index.d.ts +2 -0
- package/dist/imaging/waveforms/ecg.d.ts +39 -0
- package/dist/index.d.ts +35 -0
- package/dist/larvitar.js +90104 -0
- package/dist/larvitar.js.map +1 -0
- package/imaging/MetaDataReadable.ts +41 -0
- package/imaging/MetaDataTypes.ts +3491 -0
- package/imaging/dataDictionary.json +5328 -5328
- package/imaging/{imageAnonymization.js → imageAnonymization.ts} +41 -13
- package/imaging/{imageColormaps.js → imageColormaps.ts} +48 -30
- package/imaging/{imageContours.js → imageContours.ts} +24 -22
- package/imaging/{imageIo.js → imageIo.ts} +89 -52
- package/imaging/{imageLayers.js → imageLayers.ts} +31 -14
- package/imaging/{imageLoading.js → imageLoading.ts} +107 -43
- package/imaging/{imageParsing.js → imageParsing.ts} +160 -80
- package/imaging/{imagePresets.js → imagePresets.ts} +44 -11
- package/imaging/imageRendering.ts +1091 -0
- package/imaging/{imageReslice.js → imageReslice.ts} +18 -9
- package/imaging/imageStore.ts +487 -0
- package/imaging/imageTags.ts +609 -0
- package/imaging/imageTools.js +2 -1
- package/imaging/{imageUtils.js → imageUtils.ts} +211 -701
- package/imaging/loaders/{commonLoader.js → commonLoader.ts} +73 -24
- package/imaging/loaders/{dicomLoader.js → dicomLoader.ts} +25 -5
- package/imaging/loaders/{fileLoader.js → fileLoader.ts} +5 -5
- package/imaging/loaders/{multiframeLoader.js → multiframeLoader.ts} +145 -90
- package/imaging/loaders/{nrrdLoader.js → nrrdLoader.ts} +231 -64
- package/imaging/loaders/{resliceLoader.js → resliceLoader.ts} +51 -20
- package/imaging/monitors/{memory.js → memory.ts} +54 -8
- package/imaging/monitors/performance.ts +34 -0
- package/imaging/parsers/ecg.ts +54 -0
- package/imaging/tools/README.md +27 -0
- package/imaging/tools/custom/4dSliceScrollTool.js +47 -46
- package/imaging/tools/custom/BorderMagnifyTool.js +99 -0
- package/imaging/tools/custom/ellipticalRoiOverlayTool.js +534 -0
- package/imaging/tools/custom/polylineScissorsTool.js +1 -1
- package/imaging/tools/custom/rectangleRoiOverlayTool.js +564 -0
- package/imaging/tools/{setLabelMap3D.js → custom/setLabelMap3D.ts} +19 -25
- package/imaging/tools/{default.js → default.ts} +119 -33
- package/imaging/tools/{interaction.js → interaction.ts} +42 -23
- package/imaging/tools/{io.js → io.ts} +47 -31
- package/imaging/tools/{main.js → main.ts} +105 -40
- package/imaging/tools/{segmentation.js → segmentation.ts} +95 -68
- package/imaging/tools/{state.js → state.ts} +7 -12
- package/imaging/tools/types.d.ts +243 -0
- package/imaging/types.d.ts +200 -0
- package/imaging/waveforms/ecg.ts +191 -0
- package/{index.js → index.ts} +53 -14
- package/jsdoc.json +1 -1
- package/package.json +35 -14
- package/tsconfig.json +102 -0
- package/imaging/imageRendering.js +0 -860
- package/imaging/imageStore.js +0 -322
- package/modules/vuex/larvitar.js +0 -187
- /package/imaging/tools/{polygonSegmentationMixin.js → custom/polygonSegmentationMixin.js} +0 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { vec2 } from "cornerstone-core";
|
|
2
|
+
import { DataSet } from "dicom-parser";
|
|
3
|
+
import { DEFAULT_VIEWPORT } from "./imageStore";
|
|
4
|
+
import { NrrdSeries } from "./loaders/nrrdLoader";
|
|
5
|
+
import { MetaDataTypes } from "./MetaDataTypes";
|
|
6
|
+
import { MetaDataReadable } from "./MetaDataReadable";
|
|
7
|
+
|
|
8
|
+
// TODO-ts: differentiate each single metadata @szanchi
|
|
9
|
+
/*export type MetadataValue =
|
|
10
|
+
| string
|
|
11
|
+
| number
|
|
12
|
+
| string[]
|
|
13
|
+
| number[]
|
|
14
|
+
| boolean
|
|
15
|
+
| null
|
|
16
|
+
| Array
|
|
17
|
+
| undefined; // null or undefined is only for nrrd*/
|
|
18
|
+
|
|
19
|
+
export type MetaData = MetaDataTypes & MetaDataReadable;
|
|
20
|
+
export interface Image extends cornerstone.Image {
|
|
21
|
+
render?: Function;
|
|
22
|
+
decodeTimeInMS?: number;
|
|
23
|
+
loadTimeInMS?: number;
|
|
24
|
+
webWorkerTimeInMS?: number;
|
|
25
|
+
metadata: MetaData;
|
|
26
|
+
data?: DataSet;
|
|
27
|
+
floatPixelData?: Float32Array;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type Instance = {
|
|
31
|
+
metadata: MetaData;
|
|
32
|
+
pixelData?: TypedArray | null;
|
|
33
|
+
dataSet?: DataSet | null;
|
|
34
|
+
file?: File | null;
|
|
35
|
+
instanceId?: string;
|
|
36
|
+
frame?: number;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export type ReslicedInstance = {
|
|
40
|
+
metadata: MetaData;
|
|
41
|
+
instanceId?: string;
|
|
42
|
+
permuteTable?: [number, number, number];
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export type StagedProtocol = {
|
|
46
|
+
numberOfStages: number; // Number of stages
|
|
47
|
+
numberOfViews: number; // Number of views in stage
|
|
48
|
+
stageName?: string; // Name of the stage
|
|
49
|
+
stageNumber?: number; // Number of the stage
|
|
50
|
+
viewName?: string; // Name of the view
|
|
51
|
+
viewNumber?: number; // Number of the view
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type Series = {
|
|
55
|
+
imageIds: string[];
|
|
56
|
+
instances: { [key: string]: Instance };
|
|
57
|
+
seriesDescription?: string;
|
|
58
|
+
anonymized?: boolean;
|
|
59
|
+
bytes: number;
|
|
60
|
+
seriesUID: string;
|
|
61
|
+
currentImageIdIndex: number;
|
|
62
|
+
numberOfImages?: number;
|
|
63
|
+
isMultiframe: boolean;
|
|
64
|
+
color?: boolean;
|
|
65
|
+
dataSet: DataSet | null;
|
|
66
|
+
metadata?: MetaData;
|
|
67
|
+
frameDelay?: number;
|
|
68
|
+
frameTime?: number;
|
|
69
|
+
rWaveTimeVector?: number[];
|
|
70
|
+
instanceUIDs: { [key: string]: string };
|
|
71
|
+
is4D: boolean;
|
|
72
|
+
waveform: boolean;
|
|
73
|
+
ecgData?: number[];
|
|
74
|
+
traceData?: Partial<Plotly.PlotData>[];
|
|
75
|
+
isPDF: boolean;
|
|
76
|
+
stagedProtocol?: StagedProtocol;
|
|
77
|
+
modality: string;
|
|
78
|
+
numberOfFrames: number;
|
|
79
|
+
numberOfSlices: number;
|
|
80
|
+
numberOfTemporalPositions: number;
|
|
81
|
+
studyUID: string;
|
|
82
|
+
larvitarSeriesInstanceUID: string;
|
|
83
|
+
elements?: { [key: string]: any } | null;
|
|
84
|
+
layer: Layer;
|
|
85
|
+
orientation?: "axial" | "coronal" | "sagittal"; // this is needed for legacy reslice
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export interface Layer extends cornerstone.EnabledElementLayer {
|
|
89
|
+
id: string;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface Viewport extends cornerstone.Viewport {
|
|
93
|
+
newImageIdIndex: number;
|
|
94
|
+
displayedArea: {
|
|
95
|
+
brhc: {
|
|
96
|
+
x: number;
|
|
97
|
+
y: number;
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export type Contours = {
|
|
103
|
+
[key: string]: {
|
|
104
|
+
[key: string]: Array<{
|
|
105
|
+
x?: number;
|
|
106
|
+
y?: number;
|
|
107
|
+
lines: vec2[][];
|
|
108
|
+
}>;
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export type Header = {
|
|
113
|
+
volume: Volume;
|
|
114
|
+
[imageId: string]: Instance.metadata;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export type Volume = {
|
|
118
|
+
imageIds: string[];
|
|
119
|
+
seriesId: string;
|
|
120
|
+
rows: number;
|
|
121
|
+
cols: number;
|
|
122
|
+
slope: number;
|
|
123
|
+
repr: string;
|
|
124
|
+
intercept: number;
|
|
125
|
+
imagePosition: [number, number];
|
|
126
|
+
numberOfSlices: number;
|
|
127
|
+
imageOrientation: [number, number, number];
|
|
128
|
+
pixelSpacing: [number, number];
|
|
129
|
+
sliceThickness: number;
|
|
130
|
+
phase?: string;
|
|
131
|
+
study_description?: string;
|
|
132
|
+
series_description?: string;
|
|
133
|
+
acquisition_date?: string;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export type LarvitarManager = {
|
|
137
|
+
[key: string]: NrrdSeries | Series;
|
|
138
|
+
} | null;
|
|
139
|
+
|
|
140
|
+
export type ImageFrame = {
|
|
141
|
+
pixelData?: Uint8ClampedArray | Uint16Array | Int16Array | Uint8Array;
|
|
142
|
+
bitsAllocated: number;
|
|
143
|
+
rows: number;
|
|
144
|
+
columns: number;
|
|
145
|
+
photometricInterpretation: string;
|
|
146
|
+
samplesPerPixel: number;
|
|
147
|
+
smallestPixelValue: number;
|
|
148
|
+
largestPixelValue: number;
|
|
149
|
+
imageData?: ImageData;
|
|
150
|
+
pixelRepresentation: number;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
export type ImageTracker = {
|
|
154
|
+
[key: string]: string;
|
|
155
|
+
} | null;
|
|
156
|
+
|
|
157
|
+
// the result of readFile
|
|
158
|
+
export type ImageObject = {
|
|
159
|
+
file: File;
|
|
160
|
+
instanceUID: string;
|
|
161
|
+
metadata: MetaData;
|
|
162
|
+
dataSet: DataSet;
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
export type CachingResponse = {
|
|
166
|
+
seriesId: string;
|
|
167
|
+
loading: number;
|
|
168
|
+
series: Partial<Series>;
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
export interface CustomDataSet extends DataSet {
|
|
172
|
+
repr?: string;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
type Orientation = "axial" | "coronal" | "sagittal";
|
|
176
|
+
|
|
177
|
+
type TypedArray =
|
|
178
|
+
| Float64Array
|
|
179
|
+
| Uint8Array
|
|
180
|
+
| Int8Array
|
|
181
|
+
| Uint16Array
|
|
182
|
+
| Int16Array
|
|
183
|
+
| Int32Array
|
|
184
|
+
| Uint32Array
|
|
185
|
+
| Float32Array;
|
|
186
|
+
|
|
187
|
+
type StoreViewport = typeof DEFAULT_VIEWPORT;
|
|
188
|
+
|
|
189
|
+
type StoreViewportOptions = {
|
|
190
|
+
numberOfSlices?: number;
|
|
191
|
+
sliceNumber?: number;
|
|
192
|
+
wc?: number;
|
|
193
|
+
ww?: number;
|
|
194
|
+
defaultWC?: number;
|
|
195
|
+
defaultWW?: number;
|
|
196
|
+
scale?: number;
|
|
197
|
+
colormap?: string;
|
|
198
|
+
tr_x?: number;
|
|
199
|
+
tr_y?: number;
|
|
200
|
+
};
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/** @module waveforms/ecg
|
|
2
|
+
* @desc This file provides utility functions for
|
|
3
|
+
* rendering ecg waveforms using plotly.js
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// external libraries
|
|
7
|
+
import Plotly, { Datum } from "plotly.js-dist-min";
|
|
8
|
+
|
|
9
|
+
// internal libraries
|
|
10
|
+
import { Series } from "../types";
|
|
11
|
+
import { NrrdSeries } from "../loaders/nrrdLoader";
|
|
12
|
+
import { updateImage } from "../imageRendering";
|
|
13
|
+
import store from "../imageStore";
|
|
14
|
+
import { getSeriesDataFromLarvitarManager } from "../loaders/commonLoader";
|
|
15
|
+
import { updateStackToolState } from "../imageTools";
|
|
16
|
+
|
|
17
|
+
/*
|
|
18
|
+
* This module provides the following functions to be exported:
|
|
19
|
+
* renderECG(data, divId, colorMarker, numberOfFrames, frameTime, frameId)
|
|
20
|
+
* syncECGFrame(traceData, seriesId, canvasId, numberOfFrames, divId)
|
|
21
|
+
* updateECGFrame(traceData, frameId, numberOfFrames, divId)
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
const LAYOUT: Partial<Plotly.Layout> = {
|
|
25
|
+
xaxis: {
|
|
26
|
+
rangemode: "tozero",
|
|
27
|
+
showgrid: true,
|
|
28
|
+
gridcolor: "rgba(238,135,51,0.5)",
|
|
29
|
+
dtick: 1,
|
|
30
|
+
tickwidth: 2,
|
|
31
|
+
tickcolor: "#f5f5f5",
|
|
32
|
+
tickformat: ".2f",
|
|
33
|
+
tickfont: {
|
|
34
|
+
color: "#f5f5f5"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
yaxis: {
|
|
38
|
+
rangemode: "nonnegative",
|
|
39
|
+
showgrid: true,
|
|
40
|
+
gridcolor: "rgba(238,135,51,0.5)",
|
|
41
|
+
dtick: 20,
|
|
42
|
+
tick0: 0,
|
|
43
|
+
tickwidth: 2,
|
|
44
|
+
tickcolor: "#f5f5f5",
|
|
45
|
+
tickfont: {
|
|
46
|
+
color: "#f5f5f5"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
showlegend: false,
|
|
50
|
+
paper_bgcolor: "#000000",
|
|
51
|
+
plot_bgcolor: "#000000"
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Render ECG waveform in a div
|
|
56
|
+
* @instance
|
|
57
|
+
* @function renderECG
|
|
58
|
+
* @param {number[]} data - ECG waveform data
|
|
59
|
+
* @param {string} divId - DivId to render waveform in
|
|
60
|
+
* @param {string} colorMarker - Color of the marker
|
|
61
|
+
* @param {number} numberOfframes - Number of frames in the image
|
|
62
|
+
* @param {number} frameTime - Time interval of each frame in the image
|
|
63
|
+
* @param {number} frameId - FrameId of the image to be rendered
|
|
64
|
+
* @returns {Object} traceData - Plotly trace data
|
|
65
|
+
*/
|
|
66
|
+
export const renderECG = function (
|
|
67
|
+
data: number[],
|
|
68
|
+
divId: string,
|
|
69
|
+
colorMarker: string,
|
|
70
|
+
numberOfFrames: number,
|
|
71
|
+
frameTime: number,
|
|
72
|
+
frameId: number = 0
|
|
73
|
+
): Partial<Plotly.PlotData>[] {
|
|
74
|
+
// convert info using frameTime and numberOfFrames
|
|
75
|
+
const totalTime = (numberOfFrames - 1) * (frameTime * 1e-3);
|
|
76
|
+
const dotX: number = Math.floor((frameId * data.length) / numberOfFrames);
|
|
77
|
+
// build the trace data
|
|
78
|
+
const trace: Partial<Plotly.PlotData> = {
|
|
79
|
+
x: data.map((_, i) => (i * totalTime) / data.length),
|
|
80
|
+
y: data,
|
|
81
|
+
mode: "lines",
|
|
82
|
+
type: "scattergl",
|
|
83
|
+
line: {
|
|
84
|
+
width: 1.5,
|
|
85
|
+
shape: "linear"
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// build the marker data
|
|
90
|
+
const marker: Partial<Plotly.PlotData> = {
|
|
91
|
+
x: [dotX],
|
|
92
|
+
y: [data[dotX]],
|
|
93
|
+
mode: "markers",
|
|
94
|
+
type: "scattergl",
|
|
95
|
+
marker: {
|
|
96
|
+
size: 12,
|
|
97
|
+
color: colorMarker,
|
|
98
|
+
symbol: "line-ns-open",
|
|
99
|
+
line: {
|
|
100
|
+
width: 3
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
// render data and update ranges
|
|
105
|
+
const traceData: Partial<Plotly.PlotData>[] = [trace, marker];
|
|
106
|
+
// fix the range of the x-axis
|
|
107
|
+
LAYOUT.xaxis!.range = [0, totalTime];
|
|
108
|
+
// fix the grid of x-axis using a line for each frame
|
|
109
|
+
LAYOUT.xaxis!.dtick = LAYOUT.xaxis!.dtick = totalTime / (numberOfFrames - 1);
|
|
110
|
+
Plotly.newPlot(divId, traceData, LAYOUT, {
|
|
111
|
+
responsive: true,
|
|
112
|
+
displayModeBar: false
|
|
113
|
+
});
|
|
114
|
+
return traceData;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Sync ECG waveform with rendered image on click
|
|
119
|
+
* @instance
|
|
120
|
+
* @function syncECGFrame
|
|
121
|
+
* @param {Object} traceData - Plotly trace data
|
|
122
|
+
* @param {string} seriesId - SeriesId of the image
|
|
123
|
+
* @param {string} canvasId - CanvasId of the image
|
|
124
|
+
* @param {number} numberOfFrames - Number of frames in the image
|
|
125
|
+
* @param {string} divId - DivId to render waveform in
|
|
126
|
+
*/
|
|
127
|
+
export const syncECGFrame = function (
|
|
128
|
+
traceData: Partial<Plotly.PlotData>[],
|
|
129
|
+
seriesId: string,
|
|
130
|
+
canvasId: string,
|
|
131
|
+
numberOfFrames: number,
|
|
132
|
+
divId: string
|
|
133
|
+
) {
|
|
134
|
+
// document.getElementById('myDiv') return HTMLElement. This type doesn't
|
|
135
|
+
// contain method 'on' because this method is added within plotly-latest.min.js.
|
|
136
|
+
const domElement: any = document.getElementById(divId);
|
|
137
|
+
if (domElement) {
|
|
138
|
+
domElement.on("plotly_click", function (data: Plotly.PlotMouseEvent) {
|
|
139
|
+
traceData[1].x = [data.points[0].x];
|
|
140
|
+
traceData[1].y = [data.points[0].y];
|
|
141
|
+
Plotly.extendTraces(divId, {}, [0]);
|
|
142
|
+
const totalTime: number = (traceData[0].x as number[])[
|
|
143
|
+
(traceData[0].x as number[]).length - 1
|
|
144
|
+
];
|
|
145
|
+
const frameId: number = Math.floor(
|
|
146
|
+
((data.points[0].x as number) * numberOfFrames - 1) / totalTime
|
|
147
|
+
);
|
|
148
|
+
const series: Series | NrrdSeries | null =
|
|
149
|
+
getSeriesDataFromLarvitarManager(seriesId);
|
|
150
|
+
if (series) {
|
|
151
|
+
updateImage(series as Series, canvasId, frameId, false);
|
|
152
|
+
updateStackToolState(canvasId, frameId);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const canvasElement: any = document.getElementById(canvasId);
|
|
158
|
+
canvasElement.addEventListener("wheel", function (e: WheelEvent) {
|
|
159
|
+
const viewport = store.get(["viewports", canvasId]);
|
|
160
|
+
updateECGFrame(traceData, viewport.sliceId, numberOfFrames, divId);
|
|
161
|
+
updateStackToolState(canvasId, viewport.sliceId);
|
|
162
|
+
});
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Sync ECG waveform with rendered image on click
|
|
167
|
+
* @instance
|
|
168
|
+
* @function updateECGFrame
|
|
169
|
+
* @param {Object} traceData - Plotly trace data
|
|
170
|
+
* @param {number} frameId - FrameId of the image
|
|
171
|
+
* @param {number} numberOfFrames - Number of frames in the image
|
|
172
|
+
* @param {string} divId - DivId to render waveform in
|
|
173
|
+
*/
|
|
174
|
+
export const updateECGFrame = function (
|
|
175
|
+
traceData: Partial<Plotly.PlotData>[],
|
|
176
|
+
frameId: number,
|
|
177
|
+
numberOfFrames: number,
|
|
178
|
+
divId: string
|
|
179
|
+
) {
|
|
180
|
+
const totalTime: number = (traceData[0].x as number[])[
|
|
181
|
+
(traceData[0].x as number[]).length - 1
|
|
182
|
+
];
|
|
183
|
+
const dotX: number = (frameId * totalTime) / (numberOfFrames - 1);
|
|
184
|
+
const index: number = (traceData[0].x as number[]).findIndex(
|
|
185
|
+
(x: number) => x >= dotX
|
|
186
|
+
);
|
|
187
|
+
const dotY: Datum | Datum[] = traceData[0].y![index];
|
|
188
|
+
traceData[1].x = [dotX];
|
|
189
|
+
traceData[1].y = Array.isArray(dotY) ? dotY : [dotY];
|
|
190
|
+
Plotly.extendTraces(divId, {}, [0]);
|
|
191
|
+
};
|
package/{index.js → index.ts}
RENAMED
|
@@ -1,24 +1,45 @@
|
|
|
1
1
|
import pkg from "./package.json";
|
|
2
|
-
const VERSION = pkg.version;
|
|
3
|
-
console.
|
|
2
|
+
const VERSION: string = pkg.version;
|
|
3
|
+
console.groupCollapsed(
|
|
4
|
+
`%cLARVITAR %cv${VERSION}`,
|
|
5
|
+
"color: #404888; background: #209A71; font-weight: 900;",
|
|
6
|
+
"color: #BED730; background: #209A71; font-weight: 900;"
|
|
7
|
+
);
|
|
4
8
|
|
|
5
9
|
import cornerstone from "cornerstone-core";
|
|
6
10
|
import cornerstoneTools from "cornerstone-tools";
|
|
11
|
+
import { parseDicom } from "dicom-parser";
|
|
12
|
+
|
|
7
13
|
import { default as cornerstoneDICOMImageLoader } from "cornerstone-wado-image-loader";
|
|
8
14
|
const segModule = cornerstoneTools.getModule("segmentation");
|
|
9
15
|
|
|
10
|
-
import larvitarModule from "./modules/vuex/larvitar";
|
|
11
|
-
|
|
12
16
|
import {
|
|
17
|
+
checkAndClearMemory,
|
|
13
18
|
checkMemoryAllocation,
|
|
14
19
|
getUsedMemory,
|
|
15
20
|
getAvailableMemory
|
|
16
21
|
} from "./imaging/monitors/memory";
|
|
17
22
|
|
|
18
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
getPerformanceMonitor,
|
|
25
|
+
activatePerformanceMonitor,
|
|
26
|
+
deactivatePerformanceMonitor
|
|
27
|
+
} from "./imaging/monitors/performance";
|
|
28
|
+
|
|
29
|
+
import store from "./imaging/imageStore";
|
|
30
|
+
console.log(store);
|
|
31
|
+
console.groupEnd();
|
|
19
32
|
|
|
20
33
|
import { parseContours } from "./imaging/imageContours";
|
|
21
34
|
|
|
35
|
+
import { parseECG } from "./imaging/parsers/ecg";
|
|
36
|
+
|
|
37
|
+
import {
|
|
38
|
+
renderECG,
|
|
39
|
+
syncECGFrame,
|
|
40
|
+
updateECGFrame
|
|
41
|
+
} from "./imaging/waveforms/ecg";
|
|
42
|
+
|
|
22
43
|
import {
|
|
23
44
|
getImagePresets,
|
|
24
45
|
setImagePreset,
|
|
@@ -31,7 +52,6 @@ import {
|
|
|
31
52
|
getMaxPixelValue,
|
|
32
53
|
getPixelRepresentation,
|
|
33
54
|
getTypedArrayFromDataType,
|
|
34
|
-
getPixelTypedArray,
|
|
35
55
|
getSortedStack,
|
|
36
56
|
randomId,
|
|
37
57
|
getMeanValue,
|
|
@@ -133,8 +153,10 @@ import {
|
|
|
133
153
|
|
|
134
154
|
import {
|
|
135
155
|
DEFAULT_TOOLS,
|
|
156
|
+
dvTools,
|
|
136
157
|
getDefaultToolsByType,
|
|
137
|
-
setDefaultToolsProps
|
|
158
|
+
setDefaultToolsProps,
|
|
159
|
+
registerExternalTool
|
|
138
160
|
} from "./imaging/tools/default";
|
|
139
161
|
|
|
140
162
|
import {
|
|
@@ -164,7 +186,8 @@ import {
|
|
|
164
186
|
resetLarvitarManager,
|
|
165
187
|
removeSeriesFromLarvitarManager,
|
|
166
188
|
getSeriesDataFromLarvitarManager,
|
|
167
|
-
getImageFrame
|
|
189
|
+
getImageFrame,
|
|
190
|
+
getSopInstanceUIDFromLarvitarManager
|
|
168
191
|
} from "./imaging/loaders/commonLoader";
|
|
169
192
|
|
|
170
193
|
import {
|
|
@@ -176,7 +199,11 @@ import {
|
|
|
176
199
|
getNrrdSerieDimensions
|
|
177
200
|
} from "./imaging/loaders/nrrdLoader";
|
|
178
201
|
|
|
179
|
-
import {
|
|
202
|
+
import {
|
|
203
|
+
getDicomImageId,
|
|
204
|
+
cacheImage,
|
|
205
|
+
cacheImages
|
|
206
|
+
} from "./imaging/loaders/dicomLoader";
|
|
180
207
|
|
|
181
208
|
import { loadReslicedImage } from "./imaging/loaders/resliceLoader";
|
|
182
209
|
|
|
@@ -216,17 +243,26 @@ export {
|
|
|
216
243
|
// global cornerstone variables
|
|
217
244
|
cornerstone,
|
|
218
245
|
cornerstoneTools,
|
|
246
|
+
parseDicom,
|
|
219
247
|
segModule,
|
|
220
248
|
cornerstoneDICOMImageLoader,
|
|
221
|
-
// vuex module
|
|
222
|
-
larvitarModule,
|
|
223
249
|
// memory module
|
|
250
|
+
checkAndClearMemory,
|
|
224
251
|
checkMemoryAllocation,
|
|
225
252
|
getUsedMemory,
|
|
226
253
|
getAvailableMemory,
|
|
254
|
+
// performance module
|
|
255
|
+
getPerformanceMonitor,
|
|
256
|
+
activatePerformanceMonitor,
|
|
257
|
+
deactivatePerformanceMonitor,
|
|
227
258
|
// larvitarStore
|
|
228
|
-
|
|
229
|
-
|
|
259
|
+
store,
|
|
260
|
+
// parsers
|
|
261
|
+
parseECG,
|
|
262
|
+
syncECGFrame,
|
|
263
|
+
updateECGFrame,
|
|
264
|
+
// waveforms
|
|
265
|
+
renderECG,
|
|
230
266
|
// imagePresets
|
|
231
267
|
getImagePresets,
|
|
232
268
|
setImagePreset,
|
|
@@ -237,7 +273,6 @@ export {
|
|
|
237
273
|
getMaxPixelValue,
|
|
238
274
|
getPixelRepresentation,
|
|
239
275
|
getTypedArrayFromDataType,
|
|
240
|
-
getPixelTypedArray,
|
|
241
276
|
getSortedStack,
|
|
242
277
|
randomId,
|
|
243
278
|
getMeanValue,
|
|
@@ -310,6 +345,7 @@ export {
|
|
|
310
345
|
removeSeriesFromLarvitarManager,
|
|
311
346
|
getSeriesDataFromLarvitarManager,
|
|
312
347
|
getImageFrame,
|
|
348
|
+
getSopInstanceUIDFromLarvitarManager,
|
|
313
349
|
// loaders/nrrdLoader
|
|
314
350
|
buildNrrdImage,
|
|
315
351
|
getNrrdImageId,
|
|
@@ -321,6 +357,7 @@ export {
|
|
|
321
357
|
loadReslicedImage,
|
|
322
358
|
// loaders/dicomLoader
|
|
323
359
|
getDicomImageId,
|
|
360
|
+
cacheImage,
|
|
324
361
|
cacheImages,
|
|
325
362
|
// loaders/multiframeLoader
|
|
326
363
|
loadMultiFrameImage,
|
|
@@ -364,8 +401,10 @@ export {
|
|
|
364
401
|
exportAnnotations,
|
|
365
402
|
// tools/default
|
|
366
403
|
DEFAULT_TOOLS,
|
|
404
|
+
dvTools,
|
|
367
405
|
getDefaultToolsByType,
|
|
368
406
|
setDefaultToolsProps,
|
|
407
|
+
registerExternalTool,
|
|
369
408
|
// tools/io
|
|
370
409
|
saveAnnotations,
|
|
371
410
|
loadAnnotations,
|
package/jsdoc.json
CHANGED
package/package.json
CHANGED
|
@@ -6,22 +6,26 @@
|
|
|
6
6
|
"medical",
|
|
7
7
|
"cornerstone"
|
|
8
8
|
],
|
|
9
|
-
"version": "
|
|
10
|
-
"description": "
|
|
9
|
+
"version": "2.0.2",
|
|
10
|
+
"description": "typescript library for parsing, loading, rendering and interacting with DICOM images",
|
|
11
11
|
"repository": {
|
|
12
12
|
"url": "https://github.com/dvisionlab/Larvitar.git",
|
|
13
13
|
"type": "git"
|
|
14
14
|
},
|
|
15
|
+
"main": "index.ts",
|
|
15
16
|
"scripts": {
|
|
17
|
+
"coverage": "typescript-coverage-report",
|
|
16
18
|
"generate-docs": "node_modules/.bin/jsdoc -c jsdoc.json",
|
|
17
|
-
"build
|
|
18
|
-
"dev
|
|
19
|
+
"build": "webpack --config ./bundler/webpack.prod.js && cp ./dist/larvitar.js ./docs/examples/larvitar.js",
|
|
20
|
+
"dev": "webpack --progress --config ./bundler/webpack.dev.js && cp ./dist/larvitar.js ./docs/examples/larvitar.js",
|
|
21
|
+
"dev-wip": "webpack serve --config ./bundler/webpack.dev-wip.js"
|
|
19
22
|
},
|
|
20
23
|
"author": "Simone Manini <simone.manini@dvisionlab.com> (https://www.dvisionlab.com)",
|
|
21
24
|
"contributors": [
|
|
22
25
|
"Mattia Ronzoni <mattia.ronzoni@dvisionlab.com> (https://www.dvisionlab.com)",
|
|
23
26
|
"Sara Zanchi <sara.zanchi@dvisionlab.com> (https://www.dvisionlab.com)",
|
|
24
|
-
"Ale Re <ale.re@dvisionlab.com> (https://www.dvisionlab.com)"
|
|
27
|
+
"Ale Re <ale.re@dvisionlab.com> (https://www.dvisionlab.com)",
|
|
28
|
+
"Laura Borghesi Re <laura.borghesi@dvisionlab.com> (https://www.dvisionlab.com)"
|
|
25
29
|
],
|
|
26
30
|
"license": "MIT",
|
|
27
31
|
"dependencies": {
|
|
@@ -36,22 +40,39 @@
|
|
|
36
40
|
"dicom-parser": "^1.8.13",
|
|
37
41
|
"docdash": "^1.2.0",
|
|
38
42
|
"hammerjs": "^2.0.8",
|
|
43
|
+
"jpeg-lossless-decoder-js": "^2.0.7",
|
|
39
44
|
"keycode-js": "^3.1.0",
|
|
40
45
|
"lodash": "^4.17.15",
|
|
41
46
|
"pako": "^1.0.10",
|
|
42
47
|
"papaparse": "^5.3.0",
|
|
48
|
+
"plotly.js-dist-min": "^2.27.1",
|
|
43
49
|
"uuid": "^8.3.2"
|
|
44
50
|
},
|
|
45
51
|
"devDependencies": {
|
|
46
|
-
"@
|
|
47
|
-
"@
|
|
52
|
+
"@babel/core": "^7.21.8",
|
|
53
|
+
"@types/cornerstone-core": "^2.3.0",
|
|
54
|
+
"@types/crypto-js": "^4.1.1",
|
|
55
|
+
"@types/hammerjs": "^2.0.41",
|
|
56
|
+
"@types/lodash": "^4.14.192",
|
|
57
|
+
"@types/papaparse": "^5.3.7",
|
|
58
|
+
"@types/plotly.js": "^2.12.30",
|
|
59
|
+
"@types/plotly.js-dist-min": "^2.3.4",
|
|
60
|
+
"@types/uuid": "^9.0.1",
|
|
61
|
+
"babel-loader": "^9.1.2",
|
|
62
|
+
"clean-webpack-plugin": "^4.0.0",
|
|
63
|
+
"copy-webpack-plugin": "^11.0.0",
|
|
48
64
|
"fs": "^0.0.1-security",
|
|
65
|
+
"html-loader": "^4.2.0",
|
|
66
|
+
"html-webpack-plugin": "^5.5.0",
|
|
67
|
+
"ip": "^1.1.8",
|
|
49
68
|
"jsdoc": "^3.6.4",
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
69
|
+
"portfinder-sync": "^0.0.2",
|
|
70
|
+
"ts-loader": "^9.4.2",
|
|
71
|
+
"typescript": "^5.0.2",
|
|
72
|
+
"typescript-coverage-report": "^0.7.0",
|
|
73
|
+
"webpack": "^5.76.3",
|
|
74
|
+
"webpack-bundle-analyzer": "^4.8.0",
|
|
75
|
+
"webpack-cli": "^5.0.1",
|
|
76
|
+
"webpack-dev-server": "^4.13.1"
|
|
77
|
+
}
|
|
57
78
|
}
|