@cornerstonejs/adapters 2.0.0-beta.2 → 2.0.0-beta.4
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/dist/adapters.es.js +751 -26
- package/dist/adapters.es.js.map +1 -1
- package/dist/types/adapters/Cornerstone3D/RTStruct/RTSS.d.ts +27 -0
- package/dist/types/adapters/Cornerstone3D/RTStruct/index.d.ts +3 -0
- package/dist/types/adapters/Cornerstone3D/index.d.ts +5 -1
- package/dist/types/adapters/index.d.ts +6 -1
- package/dist/types/index.d.ts +2 -2
- package/package.json +5 -6
package/dist/adapters.es.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { data, utilities, derivations, normalizers, log } from 'dcmjs';
|
|
1
|
+
import dcmjs, { data, utilities, derivations, normalizers, log } from 'dcmjs';
|
|
2
2
|
import { Buffer } from 'buffer';
|
|
3
3
|
import ndarray from 'ndarray';
|
|
4
|
-
import cloneDeep from 'lodash.clonedeep';
|
|
5
4
|
import { vec3 } from 'gl-matrix';
|
|
6
5
|
|
|
7
6
|
function _iterableToArrayLimit(arr, i) {
|
|
@@ -583,7 +582,7 @@ var StructuredReport$1 = derivations.StructuredReport;
|
|
|
583
582
|
var Normalizer$4 = normalizers.Normalizer;
|
|
584
583
|
var TID1500MeasurementReport$1 = TID1500$1.TID1500MeasurementReport,
|
|
585
584
|
TID1501MeasurementGroup$1 = TID1500$1.TID1501MeasurementGroup;
|
|
586
|
-
var DicomMetaDictionary$
|
|
585
|
+
var DicomMetaDictionary$4 = data.DicomMetaDictionary;
|
|
587
586
|
var FINDING$2 = {
|
|
588
587
|
CodingSchemeDesignator: "DCM",
|
|
589
588
|
CodeValue: "121071"
|
|
@@ -754,7 +753,7 @@ var MeasurementReport$1 = /*#__PURE__*/function () {
|
|
|
754
753
|
vr: "UI"
|
|
755
754
|
},
|
|
756
755
|
ImplementationClassUID: {
|
|
757
|
-
Value: [DicomMetaDictionary$
|
|
756
|
+
Value: [DicomMetaDictionary$4.uid()],
|
|
758
757
|
// TODO: could be git hash or other valid id
|
|
759
758
|
vr: "UI"
|
|
760
759
|
},
|
|
@@ -1827,7 +1826,7 @@ var _utilities$orientatio$1 = utilities.orientation,
|
|
|
1827
1826
|
var datasetToBlob = utilities.datasetToBlob,
|
|
1828
1827
|
BitArray$2 = utilities.BitArray,
|
|
1829
1828
|
DicomMessage$1 = utilities.DicomMessage,
|
|
1830
|
-
DicomMetaDictionary$
|
|
1829
|
+
DicomMetaDictionary$3 = utilities.DicomMetaDictionary;
|
|
1831
1830
|
var Normalizer$3 = normalizers.Normalizer;
|
|
1832
1831
|
var SegmentationDerivation$2 = derivations.Segmentation;
|
|
1833
1832
|
var Segmentation$5 = {
|
|
@@ -1957,16 +1956,16 @@ function _createSegFromImages$1(images, isMultiframe, options) {
|
|
|
1957
1956
|
var image = images[0];
|
|
1958
1957
|
var arrayBuffer = image.data.byteArray.buffer;
|
|
1959
1958
|
var dicomData = DicomMessage$1.readFile(arrayBuffer);
|
|
1960
|
-
var dataset = DicomMetaDictionary$
|
|
1961
|
-
dataset._meta = DicomMetaDictionary$
|
|
1959
|
+
var dataset = DicomMetaDictionary$3.naturalizeDataset(dicomData.dict);
|
|
1960
|
+
dataset._meta = DicomMetaDictionary$3.namifyDataset(dicomData.meta);
|
|
1962
1961
|
datasets.push(dataset);
|
|
1963
1962
|
} else {
|
|
1964
1963
|
for (var i = 0; i < images.length; i++) {
|
|
1965
1964
|
var _image = images[i];
|
|
1966
1965
|
var _arrayBuffer = _image.data.byteArray.buffer;
|
|
1967
1966
|
var _dicomData = DicomMessage$1.readFile(_arrayBuffer);
|
|
1968
|
-
var _dataset = DicomMetaDictionary$
|
|
1969
|
-
_dataset._meta = DicomMetaDictionary$
|
|
1967
|
+
var _dataset = DicomMetaDictionary$3.naturalizeDataset(_dicomData.dict);
|
|
1968
|
+
_dataset._meta = DicomMetaDictionary$3.namifyDataset(_dicomData.meta);
|
|
1970
1969
|
datasets.push(_dataset);
|
|
1971
1970
|
}
|
|
1972
1971
|
}
|
|
@@ -1986,8 +1985,8 @@ function _createSegFromImages$1(images, isMultiframe, options) {
|
|
|
1986
1985
|
*/
|
|
1987
1986
|
function generateToolState$3(imageIds, arrayBuffer, metadataProvider) {
|
|
1988
1987
|
var dicomData = DicomMessage$1.readFile(arrayBuffer);
|
|
1989
|
-
var dataset = DicomMetaDictionary$
|
|
1990
|
-
dataset._meta = DicomMetaDictionary$
|
|
1988
|
+
var dataset = DicomMetaDictionary$3.naturalizeDataset(dicomData.dict);
|
|
1989
|
+
dataset._meta = DicomMetaDictionary$3.namifyDataset(dicomData.meta);
|
|
1991
1990
|
var multiframe = Normalizer$3.normalizeToDataset([dataset]);
|
|
1992
1991
|
var imagePlaneModule = metadataProvider.get("imagePlaneModule", imageIds[0]);
|
|
1993
1992
|
if (!imagePlaneModule) {
|
|
@@ -2267,7 +2266,7 @@ var _utilities$orientatio = utilities.orientation,
|
|
|
2267
2266
|
nearlyEqual = _utilities$orientatio.nearlyEqual;
|
|
2268
2267
|
var BitArray$1 = data.BitArray,
|
|
2269
2268
|
DicomMessage = data.DicomMessage,
|
|
2270
|
-
DicomMetaDictionary$
|
|
2269
|
+
DicomMetaDictionary$2 = data.DicomMetaDictionary;
|
|
2271
2270
|
var Normalizer$2 = normalizers.Normalizer;
|
|
2272
2271
|
var SegmentationDerivation$1 = derivations.Segmentation;
|
|
2273
2272
|
var _utilities$compressio = utilities.compression,
|
|
@@ -2417,16 +2416,16 @@ function _createSegFromImages(images, isMultiframe, options) {
|
|
|
2417
2416
|
var image = images[0];
|
|
2418
2417
|
var arrayBuffer = image.data.byteArray.buffer;
|
|
2419
2418
|
var dicomData = DicomMessage.readFile(arrayBuffer);
|
|
2420
|
-
var dataset = DicomMetaDictionary$
|
|
2421
|
-
dataset._meta = DicomMetaDictionary$
|
|
2419
|
+
var dataset = DicomMetaDictionary$2.naturalizeDataset(dicomData.dict);
|
|
2420
|
+
dataset._meta = DicomMetaDictionary$2.namifyDataset(dicomData.meta);
|
|
2422
2421
|
datasets.push(dataset);
|
|
2423
2422
|
} else {
|
|
2424
2423
|
for (var i = 0; i < images.length; i++) {
|
|
2425
2424
|
var _image = images[i];
|
|
2426
2425
|
var _arrayBuffer = _image.data.byteArray.buffer;
|
|
2427
2426
|
var _dicomData = DicomMessage.readFile(_arrayBuffer);
|
|
2428
|
-
var _dataset = DicomMetaDictionary$
|
|
2429
|
-
_dataset._meta = DicomMetaDictionary$
|
|
2427
|
+
var _dataset = DicomMetaDictionary$2.naturalizeDataset(_dicomData.dict);
|
|
2428
|
+
_dataset._meta = DicomMetaDictionary$2.namifyDataset(_dicomData.meta);
|
|
2430
2429
|
datasets.push(_dataset);
|
|
2431
2430
|
}
|
|
2432
2431
|
}
|
|
@@ -2610,8 +2609,8 @@ function _generateToolState() {
|
|
|
2610
2609
|
case 0:
|
|
2611
2610
|
_options$skipOverlapp = options.skipOverlapping, skipOverlapping = _options$skipOverlapp === void 0 ? false : _options$skipOverlapp, _options$tolerance = options.tolerance, tolerance = _options$tolerance === void 0 ? 1e-3 : _options$tolerance, _options$TypedArrayCo = options.TypedArrayConstructor, TypedArrayConstructor = _options$TypedArrayCo === void 0 ? Uint8Array : _options$TypedArrayCo, _options$maxBytesPerC = options.maxBytesPerChunk, maxBytesPerChunk = _options$maxBytesPerC === void 0 ? 199000000 : _options$maxBytesPerC, eventTarget = options.eventTarget, triggerEvent = options.triggerEvent;
|
|
2612
2611
|
dicomData = DicomMessage.readFile(arrayBuffer);
|
|
2613
|
-
dataset = DicomMetaDictionary$
|
|
2614
|
-
dataset._meta = DicomMetaDictionary$
|
|
2612
|
+
dataset = DicomMetaDictionary$2.naturalizeDataset(dicomData.dict);
|
|
2613
|
+
dataset._meta = DicomMetaDictionary$2.namifyDataset(dicomData.meta);
|
|
2615
2614
|
multiframe = Normalizer$2.normalizeToDataset([dataset]);
|
|
2616
2615
|
imagePlaneModule = metadataProvider.get("imagePlaneModule", imageIds[0]);
|
|
2617
2616
|
generalSeriesModule = metadataProvider.get("generalSeriesModule", imageIds[0]);
|
|
@@ -2895,7 +2894,7 @@ function insertOverlappingPixelDataPlanar(segmentsOnFrame, segmentsOnFrameArray,
|
|
|
2895
2894
|
var tempBuffer = labelmapBufferArray[m].slice(0);
|
|
2896
2895
|
|
|
2897
2896
|
// temp list for checking overlaps
|
|
2898
|
-
var tempSegmentsOnFrame =
|
|
2897
|
+
var tempSegmentsOnFrame = structuredClone(segmentsOnFrameArray[m]);
|
|
2899
2898
|
|
|
2900
2899
|
/** split overlapping SEGs algorithm for each segment:
|
|
2901
2900
|
* A) copy the labelmapBuffer in the array with index 0
|
|
@@ -2954,7 +2953,7 @@ function insertOverlappingPixelDataPlanar(segmentsOnFrame, segmentsOnFrameArray,
|
|
|
2954
2953
|
M++;
|
|
2955
2954
|
}
|
|
2956
2955
|
tempBuffer = labelmapBufferArray[m].slice(0);
|
|
2957
|
-
tempSegmentsOnFrame =
|
|
2956
|
+
tempSegmentsOnFrame = structuredClone(segmentsOnFrameArray[m]);
|
|
2958
2957
|
_i2 = 0;
|
|
2959
2958
|
break;
|
|
2960
2959
|
} else {
|
|
@@ -2980,12 +2979,12 @@ function insertOverlappingPixelDataPlanar(segmentsOnFrame, segmentsOnFrameArray,
|
|
|
2980
2979
|
if (_ret2 === "continue") continue;
|
|
2981
2980
|
}
|
|
2982
2981
|
labelmapBufferArray[m] = tempBuffer.slice(0);
|
|
2983
|
-
segmentsOnFrameArray[m] =
|
|
2982
|
+
segmentsOnFrameArray[m] = structuredClone(tempSegmentsOnFrame);
|
|
2984
2983
|
|
|
2985
2984
|
// reset temp variables/buffers for new segment
|
|
2986
2985
|
m = 0;
|
|
2987
2986
|
tempBuffer = labelmapBufferArray[m].slice(0);
|
|
2988
|
-
tempSegmentsOnFrame =
|
|
2987
|
+
tempSegmentsOnFrame = structuredClone(segmentsOnFrameArray[m]);
|
|
2989
2988
|
}
|
|
2990
2989
|
}
|
|
2991
2990
|
var getSegmentIndex = function getSegmentIndex(multiframe, frame) {
|
|
@@ -3587,7 +3586,7 @@ var TID1500 = utilities.TID1500, addAccessors = utilities.addAccessors;
|
|
|
3587
3586
|
var StructuredReport = derivations.StructuredReport;
|
|
3588
3587
|
var Normalizer$1 = normalizers.Normalizer;
|
|
3589
3588
|
var TID1500MeasurementReport = TID1500.TID1500MeasurementReport, TID1501MeasurementGroup = TID1500.TID1501MeasurementGroup;
|
|
3590
|
-
var DicomMetaDictionary = data.DicomMetaDictionary;
|
|
3589
|
+
var DicomMetaDictionary$1 = data.DicomMetaDictionary;
|
|
3591
3590
|
var FINDING = { CodingSchemeDesignator: "DCM", CodeValue: "121071" };
|
|
3592
3591
|
var FINDING_SITE = { CodingSchemeDesignator: "SCT", CodeValue: "363698007" };
|
|
3593
3592
|
var FINDING_SITE_OLD = { CodingSchemeDesignator: "SRT", CodeValue: "G-C0E3" };
|
|
@@ -3656,7 +3655,7 @@ var MeasurementReport = /** @class */ (function () {
|
|
|
3656
3655
|
vr: "UI"
|
|
3657
3656
|
},
|
|
3658
3657
|
ImplementationClassUID: {
|
|
3659
|
-
Value: [DicomMetaDictionary.uid()],
|
|
3658
|
+
Value: [DicomMetaDictionary$1.uid()],
|
|
3660
3659
|
vr: "UI"
|
|
3661
3660
|
},
|
|
3662
3661
|
ImplementationVersionName: {
|
|
@@ -3691,7 +3690,7 @@ var MeasurementReport = /** @class */ (function () {
|
|
|
3691
3690
|
description: undefined,
|
|
3692
3691
|
sopInstanceUid: ReferencedSOPInstanceUID,
|
|
3693
3692
|
annotation: {
|
|
3694
|
-
annotationUID: DicomMetaDictionary.uid(),
|
|
3693
|
+
annotationUID: DicomMetaDictionary$1.uid(),
|
|
3695
3694
|
metadata: {
|
|
3696
3695
|
toolName: toolType,
|
|
3697
3696
|
referencedImageId: referencedImageId,
|
|
@@ -4974,6 +4973,726 @@ var Segmentation$1 = /*#__PURE__*/Object.freeze({
|
|
|
4974
4973
|
generateToolState: generateToolState
|
|
4975
4974
|
});
|
|
4976
4975
|
|
|
4976
|
+
/**
|
|
4977
|
+
* Checks if point is within array
|
|
4978
|
+
* @param {*} array
|
|
4979
|
+
* @param {*} pt
|
|
4980
|
+
* @returns
|
|
4981
|
+
*/
|
|
4982
|
+
function ptInArray(array, pt) {
|
|
4983
|
+
var index = -1;
|
|
4984
|
+
for (var i = 0; i < array.length; i++) {
|
|
4985
|
+
if (isSamePoint(pt, array[i])) {
|
|
4986
|
+
index = i;
|
|
4987
|
+
}
|
|
4988
|
+
}
|
|
4989
|
+
return index;
|
|
4990
|
+
}
|
|
4991
|
+
|
|
4992
|
+
/**
|
|
4993
|
+
* Checks if point A and point B contain same values
|
|
4994
|
+
* @param {*} ptA
|
|
4995
|
+
* @param {*} ptB
|
|
4996
|
+
* @returns
|
|
4997
|
+
*/
|
|
4998
|
+
function isSamePoint(ptA, ptB) {
|
|
4999
|
+
if (ptA[0] == ptB[0] && ptA[1] == ptB[1] && ptA[2] == ptB[2]) {
|
|
5000
|
+
return true;
|
|
5001
|
+
} else {
|
|
5002
|
+
return false;
|
|
5003
|
+
}
|
|
5004
|
+
}
|
|
5005
|
+
|
|
5006
|
+
/**
|
|
5007
|
+
* Goes through linesArray and replaces all references of old index with new index
|
|
5008
|
+
* @param {*} linesArray
|
|
5009
|
+
* @param {*} oldIndex
|
|
5010
|
+
* @param {*} newIndex
|
|
5011
|
+
*/
|
|
5012
|
+
function replacePointIndexReferences(linesArray, oldIndex, newIndex) {
|
|
5013
|
+
for (var i = 0; i < linesArray.length; i++) {
|
|
5014
|
+
var line = linesArray[i];
|
|
5015
|
+
if (line.a == oldIndex) {
|
|
5016
|
+
line.a = newIndex;
|
|
5017
|
+
} else if (line.b == oldIndex) {
|
|
5018
|
+
line.b = newIndex;
|
|
5019
|
+
}
|
|
5020
|
+
}
|
|
5021
|
+
}
|
|
5022
|
+
|
|
5023
|
+
/**
|
|
5024
|
+
* Iterate through polyData from vtkjs and merge any points that are the same
|
|
5025
|
+
* then update merged point references within lines array
|
|
5026
|
+
* @param {*} polyData
|
|
5027
|
+
* @param {*} bypass
|
|
5028
|
+
* @returns
|
|
5029
|
+
*/
|
|
5030
|
+
function removeDuplicatePoints(polyData, bypass) {
|
|
5031
|
+
var points = polyData.getPoints();
|
|
5032
|
+
var lines = polyData.getLines();
|
|
5033
|
+
var pointsArray = [];
|
|
5034
|
+
for (var i = 0; i < points.getNumberOfPoints(); i++) {
|
|
5035
|
+
var pt = points.getPoint(i).slice();
|
|
5036
|
+
pointsArray.push(pt);
|
|
5037
|
+
}
|
|
5038
|
+
var linesArray = [];
|
|
5039
|
+
for (var _i = 0; _i < lines.getNumberOfCells(); _i++) {
|
|
5040
|
+
var cell = lines.getCell(_i * 3).slice();
|
|
5041
|
+
//console.log(JSON.stringify(cell));
|
|
5042
|
+
var a = cell[0];
|
|
5043
|
+
var b = cell[1];
|
|
5044
|
+
var line = {
|
|
5045
|
+
a: a,
|
|
5046
|
+
b: b
|
|
5047
|
+
};
|
|
5048
|
+
linesArray.push(line);
|
|
5049
|
+
}
|
|
5050
|
+
if (bypass) {
|
|
5051
|
+
return {
|
|
5052
|
+
points: pointsArray,
|
|
5053
|
+
lines: linesArray
|
|
5054
|
+
};
|
|
5055
|
+
}
|
|
5056
|
+
|
|
5057
|
+
// Iterate through points and replace any duplicates
|
|
5058
|
+
var newPoints = [];
|
|
5059
|
+
for (var _i2 = 0; _i2 < pointsArray.length; _i2++) {
|
|
5060
|
+
var _pt = pointsArray[_i2];
|
|
5061
|
+
var index = ptInArray(newPoints, _pt);
|
|
5062
|
+
if (index >= 0) {
|
|
5063
|
+
// Duplicate Point -> replace references in lines
|
|
5064
|
+
replacePointIndexReferences(linesArray, _i2, index);
|
|
5065
|
+
} else {
|
|
5066
|
+
index = newPoints.length;
|
|
5067
|
+
newPoints.push(_pt);
|
|
5068
|
+
replacePointIndexReferences(linesArray, _i2, index);
|
|
5069
|
+
}
|
|
5070
|
+
}
|
|
5071
|
+
|
|
5072
|
+
// Final pass through lines, remove any that refer to exact same point
|
|
5073
|
+
var newLines = [];
|
|
5074
|
+
linesArray.forEach(function (line) {
|
|
5075
|
+
if (line.a != line.b) {
|
|
5076
|
+
newLines.push(line);
|
|
5077
|
+
}
|
|
5078
|
+
});
|
|
5079
|
+
return {
|
|
5080
|
+
points: newPoints,
|
|
5081
|
+
lines: newLines
|
|
5082
|
+
};
|
|
5083
|
+
}
|
|
5084
|
+
|
|
5085
|
+
function findNextLink(line, lines, contourPoints) {
|
|
5086
|
+
var index = -1;
|
|
5087
|
+
lines.forEach(function (cell, i) {
|
|
5088
|
+
if (index >= 0) {
|
|
5089
|
+
return;
|
|
5090
|
+
}
|
|
5091
|
+
if (cell.a == line.b) {
|
|
5092
|
+
index = i;
|
|
5093
|
+
}
|
|
5094
|
+
});
|
|
5095
|
+
if (index >= 0) {
|
|
5096
|
+
var nextLine = lines[index];
|
|
5097
|
+
lines.splice(index, 1);
|
|
5098
|
+
contourPoints.push(nextLine.b);
|
|
5099
|
+
if (contourPoints[0] == nextLine.b) {
|
|
5100
|
+
return {
|
|
5101
|
+
remainingLines: lines,
|
|
5102
|
+
contourPoints: contourPoints,
|
|
5103
|
+
type: "CLOSED_PLANAR"
|
|
5104
|
+
//type: 'CLOSEDPLANAR_XOR',
|
|
5105
|
+
};
|
|
5106
|
+
}
|
|
5107
|
+
|
|
5108
|
+
return findNextLink(nextLine, lines, contourPoints);
|
|
5109
|
+
}
|
|
5110
|
+
return {
|
|
5111
|
+
remainingLines: lines,
|
|
5112
|
+
contourPoints: contourPoints,
|
|
5113
|
+
type: "OPEN_PLANAR"
|
|
5114
|
+
};
|
|
5115
|
+
}
|
|
5116
|
+
|
|
5117
|
+
/**
|
|
5118
|
+
*
|
|
5119
|
+
* @param {*} lines
|
|
5120
|
+
*/
|
|
5121
|
+
function findContours(lines) {
|
|
5122
|
+
if (lines.length == 0) {
|
|
5123
|
+
return [];
|
|
5124
|
+
}
|
|
5125
|
+
var contourPoints = [];
|
|
5126
|
+
var firstCell = lines.shift();
|
|
5127
|
+
contourPoints.push(firstCell.a);
|
|
5128
|
+
contourPoints.push(firstCell.b);
|
|
5129
|
+
var result = findNextLink(firstCell, lines, contourPoints);
|
|
5130
|
+
if (result.remainingLines.length == 0) {
|
|
5131
|
+
return [{
|
|
5132
|
+
type: result.type,
|
|
5133
|
+
contourPoints: result.contourPoints
|
|
5134
|
+
}];
|
|
5135
|
+
} else {
|
|
5136
|
+
var extraContours = findContours(result.remainingLines);
|
|
5137
|
+
extraContours.push({
|
|
5138
|
+
type: result.type,
|
|
5139
|
+
contourPoints: result.contourPoints
|
|
5140
|
+
});
|
|
5141
|
+
return extraContours;
|
|
5142
|
+
}
|
|
5143
|
+
}
|
|
5144
|
+
function findContoursFromReducedSet(lines, points) {
|
|
5145
|
+
return findContours(lines);
|
|
5146
|
+
}
|
|
5147
|
+
|
|
5148
|
+
function generateContourSetsFromLabelmap(_ref) {
|
|
5149
|
+
var segmentations = _ref.segmentations,
|
|
5150
|
+
cornerstoneCache = _ref.cornerstoneCache,
|
|
5151
|
+
cornerstoneToolsEnums = _ref.cornerstoneToolsEnums,
|
|
5152
|
+
vtkUtils = _ref.vtkUtils;
|
|
5153
|
+
var LABELMAP = cornerstoneToolsEnums.SegmentationRepresentations.Labelmap;
|
|
5154
|
+
var representationData = segmentations.representationData,
|
|
5155
|
+
segments = segmentations.segments;
|
|
5156
|
+
var segVolumeId = representationData[LABELMAP].volumeId;
|
|
5157
|
+
|
|
5158
|
+
// Get segmentation volume
|
|
5159
|
+
var vol = cornerstoneCache.getVolume(segVolumeId);
|
|
5160
|
+
if (!vol) {
|
|
5161
|
+
console.warn("No volume found for ".concat(segVolumeId));
|
|
5162
|
+
return;
|
|
5163
|
+
}
|
|
5164
|
+
var numSlices = vol.dimensions[2];
|
|
5165
|
+
|
|
5166
|
+
// Get image volume segmentation references
|
|
5167
|
+
var imageVol = cornerstoneCache.getVolume(vol.referencedVolumeId);
|
|
5168
|
+
if (!imageVol) {
|
|
5169
|
+
console.warn("No volume found for ".concat(vol.referencedVolumeId));
|
|
5170
|
+
return;
|
|
5171
|
+
}
|
|
5172
|
+
|
|
5173
|
+
// NOTE: Workaround for marching squares not finding closed contours at
|
|
5174
|
+
// boundary of image volume, clear pixels along x-y border of volume
|
|
5175
|
+
var segData = vol.imageData.getPointData().getScalars().getData();
|
|
5176
|
+
var pixelsPerSlice = vol.dimensions[0] * vol.dimensions[1];
|
|
5177
|
+
for (var z = 0; z < numSlices; z++) {
|
|
5178
|
+
for (var y = 0; y < vol.dimensions[1]; y++) {
|
|
5179
|
+
for (var x = 0; x < vol.dimensions[0]; x++) {
|
|
5180
|
+
var index = x + y * vol.dimensions[0] + z * pixelsPerSlice;
|
|
5181
|
+
if (x === 0 || y === 0 || x === vol.dimensions[0] - 1 || y === vol.dimensions[1] - 1) {
|
|
5182
|
+
segData[index] = 0;
|
|
5183
|
+
}
|
|
5184
|
+
}
|
|
5185
|
+
}
|
|
5186
|
+
}
|
|
5187
|
+
|
|
5188
|
+
// end workaround
|
|
5189
|
+
//
|
|
5190
|
+
//
|
|
5191
|
+
var ContourSets = [];
|
|
5192
|
+
|
|
5193
|
+
// Iterate through all segments in current segmentation set
|
|
5194
|
+
var numSegments = segments.length;
|
|
5195
|
+
for (var segIndex = 0; segIndex < numSegments; segIndex++) {
|
|
5196
|
+
var segment = segments[segIndex];
|
|
5197
|
+
|
|
5198
|
+
// Skip empty segments
|
|
5199
|
+
if (!segment) {
|
|
5200
|
+
continue;
|
|
5201
|
+
}
|
|
5202
|
+
var contourSequence = [];
|
|
5203
|
+
for (var sliceIndex = 0; sliceIndex < numSlices; sliceIndex++) {
|
|
5204
|
+
// Check if the slice is empty before running marching cube
|
|
5205
|
+
if (isSliceEmptyForSegment(sliceIndex, segData, pixelsPerSlice, segIndex)) {
|
|
5206
|
+
continue;
|
|
5207
|
+
}
|
|
5208
|
+
try {
|
|
5209
|
+
var _reducedSet$points;
|
|
5210
|
+
var scalars = vtkUtils.vtkDataArray.newInstance({
|
|
5211
|
+
name: "Scalars",
|
|
5212
|
+
values: Array.from(segData),
|
|
5213
|
+
numberOfComponents: 1
|
|
5214
|
+
});
|
|
5215
|
+
|
|
5216
|
+
// Modify segData for this specific segment directly
|
|
5217
|
+
var segmentIndexFound = false;
|
|
5218
|
+
for (var i = 0; i < segData.length; i++) {
|
|
5219
|
+
var value = segData[i];
|
|
5220
|
+
if (value === segIndex) {
|
|
5221
|
+
segmentIndexFound = true;
|
|
5222
|
+
scalars.setValue(i, 1);
|
|
5223
|
+
} else {
|
|
5224
|
+
scalars.setValue(i, 0);
|
|
5225
|
+
}
|
|
5226
|
+
}
|
|
5227
|
+
if (!segmentIndexFound) {
|
|
5228
|
+
continue;
|
|
5229
|
+
}
|
|
5230
|
+
var mSquares = vtkUtils.vtkImageMarchingSquares.newInstance({
|
|
5231
|
+
slice: sliceIndex
|
|
5232
|
+
});
|
|
5233
|
+
|
|
5234
|
+
// filter out the scalar data so that only it has background and
|
|
5235
|
+
// the current segment index
|
|
5236
|
+
var imageDataCopy = vtkUtils.vtkImageData.newInstance();
|
|
5237
|
+
imageDataCopy.shallowCopy(vol.imageData);
|
|
5238
|
+
imageDataCopy.getPointData().setScalars(scalars);
|
|
5239
|
+
|
|
5240
|
+
// Connect pipeline
|
|
5241
|
+
mSquares.setInputData(imageDataCopy);
|
|
5242
|
+
var cValues = [];
|
|
5243
|
+
cValues[0] = 1;
|
|
5244
|
+
mSquares.setContourValues(cValues);
|
|
5245
|
+
mSquares.setMergePoints(false);
|
|
5246
|
+
|
|
5247
|
+
// Perform marching squares
|
|
5248
|
+
var msOutput = mSquares.getOutputData();
|
|
5249
|
+
|
|
5250
|
+
// Clean up output from marching squares
|
|
5251
|
+
var reducedSet = removeDuplicatePoints(msOutput);
|
|
5252
|
+
if ((_reducedSet$points = reducedSet.points) !== null && _reducedSet$points !== void 0 && _reducedSet$points.length) {
|
|
5253
|
+
var contours = findContoursFromReducedSet(reducedSet.lines, reducedSet.points);
|
|
5254
|
+
contourSequence.push({
|
|
5255
|
+
referencedImageId: imageVol.imageIds[sliceIndex],
|
|
5256
|
+
contours: contours,
|
|
5257
|
+
polyData: reducedSet
|
|
5258
|
+
});
|
|
5259
|
+
}
|
|
5260
|
+
} catch (e) {
|
|
5261
|
+
console.warn(sliceIndex);
|
|
5262
|
+
console.warn(e);
|
|
5263
|
+
}
|
|
5264
|
+
}
|
|
5265
|
+
var metadata = {
|
|
5266
|
+
referencedImageId: imageVol.imageIds[0],
|
|
5267
|
+
// just use 0
|
|
5268
|
+
FrameOfReferenceUID: imageVol.metadata.FrameOfReferenceUID
|
|
5269
|
+
};
|
|
5270
|
+
var ContourSet = {
|
|
5271
|
+
label: segment.label,
|
|
5272
|
+
color: segment.color,
|
|
5273
|
+
metadata: metadata,
|
|
5274
|
+
sliceContours: contourSequence
|
|
5275
|
+
};
|
|
5276
|
+
ContourSets.push(ContourSet);
|
|
5277
|
+
}
|
|
5278
|
+
return ContourSets;
|
|
5279
|
+
}
|
|
5280
|
+
function isSliceEmptyForSegment(sliceIndex, segData, pixelsPerSlice, segIndex) {
|
|
5281
|
+
var startIdx = sliceIndex * pixelsPerSlice;
|
|
5282
|
+
var endIdx = startIdx + pixelsPerSlice;
|
|
5283
|
+
for (var i = startIdx; i < endIdx; i++) {
|
|
5284
|
+
if (segData[i] === segIndex) {
|
|
5285
|
+
return false;
|
|
5286
|
+
}
|
|
5287
|
+
}
|
|
5288
|
+
return true;
|
|
5289
|
+
}
|
|
5290
|
+
|
|
5291
|
+
// comment
|
|
5292
|
+
var RectangleROIStartEndThreshold = /*#__PURE__*/function () {
|
|
5293
|
+
function RectangleROIStartEndThreshold() {
|
|
5294
|
+
_classCallCheck(this, RectangleROIStartEndThreshold);
|
|
5295
|
+
} // empty
|
|
5296
|
+
_createClass(RectangleROIStartEndThreshold, null, [{
|
|
5297
|
+
key: "getContourSequence",
|
|
5298
|
+
value: function getContourSequence(toolData, metadataProvider) {
|
|
5299
|
+
var data = toolData.data;
|
|
5300
|
+
var _data$cachedStats = data.cachedStats,
|
|
5301
|
+
projectionPoints = _data$cachedStats.projectionPoints,
|
|
5302
|
+
projectionPointsImageIds = _data$cachedStats.projectionPointsImageIds;
|
|
5303
|
+
return projectionPoints.map(function (point, index) {
|
|
5304
|
+
var ContourData = getPointData(point);
|
|
5305
|
+
var ContourImageSequence = getContourImageSequence(projectionPointsImageIds[index], metadataProvider);
|
|
5306
|
+
return {
|
|
5307
|
+
NumberOfContourPoints: ContourData.length / 3,
|
|
5308
|
+
ContourImageSequence: ContourImageSequence,
|
|
5309
|
+
ContourGeometricType: "CLOSED_PLANAR",
|
|
5310
|
+
ContourData: ContourData
|
|
5311
|
+
};
|
|
5312
|
+
});
|
|
5313
|
+
}
|
|
5314
|
+
}]);
|
|
5315
|
+
return RectangleROIStartEndThreshold;
|
|
5316
|
+
}();
|
|
5317
|
+
RectangleROIStartEndThreshold.toolName = "RectangleROIStartEndThreshold";
|
|
5318
|
+
function getPointData(points) {
|
|
5319
|
+
// Since this is a closed contour, the order of the points is important.
|
|
5320
|
+
// re-order the points to be in the correct order clockwise
|
|
5321
|
+
// Spread to make sure Float32Arrays are converted to arrays
|
|
5322
|
+
var orderedPoints = [].concat(_toConsumableArray(points[0]), _toConsumableArray(points[1]), _toConsumableArray(points[3]), _toConsumableArray(points[2]));
|
|
5323
|
+
var pointsArray = orderedPoints.flat();
|
|
5324
|
+
|
|
5325
|
+
// reduce the precision of the points to 2 decimal places
|
|
5326
|
+
var pointsArrayWithPrecision = pointsArray.map(function (point) {
|
|
5327
|
+
return point.toFixed(2);
|
|
5328
|
+
});
|
|
5329
|
+
return pointsArrayWithPrecision;
|
|
5330
|
+
}
|
|
5331
|
+
function getContourImageSequence(imageId, metadataProvider) {
|
|
5332
|
+
var sopCommon = metadataProvider.get("sopCommonModule", imageId);
|
|
5333
|
+
return {
|
|
5334
|
+
ReferencedSOPClassUID: sopCommon.sopClassUID,
|
|
5335
|
+
ReferencedSOPInstanceUID: sopCommon.sopInstanceUID
|
|
5336
|
+
};
|
|
5337
|
+
}
|
|
5338
|
+
|
|
5339
|
+
function validateAnnotation(annotation) {
|
|
5340
|
+
if (!(annotation !== null && annotation !== void 0 && annotation.data)) {
|
|
5341
|
+
throw new Error("Tool data is empty");
|
|
5342
|
+
}
|
|
5343
|
+
if (!annotation.metadata || annotation.metadata.referenceImageId) {
|
|
5344
|
+
throw new Error("Tool data is not associated with any imageId");
|
|
5345
|
+
}
|
|
5346
|
+
}
|
|
5347
|
+
var AnnotationToPointData = /*#__PURE__*/function () {
|
|
5348
|
+
function AnnotationToPointData() {
|
|
5349
|
+
_classCallCheck(this, AnnotationToPointData);
|
|
5350
|
+
} // empty
|
|
5351
|
+
_createClass(AnnotationToPointData, null, [{
|
|
5352
|
+
key: "convert",
|
|
5353
|
+
value: function convert(annotation, index, metadataProvider) {
|
|
5354
|
+
validateAnnotation(annotation);
|
|
5355
|
+
var toolName = annotation.metadata.toolName;
|
|
5356
|
+
var toolClass = AnnotationToPointData.TOOL_NAMES[toolName];
|
|
5357
|
+
if (!toolClass) {
|
|
5358
|
+
throw new Error("Unknown tool type: ".concat(toolName, ", cannot convert to RTSSReport"));
|
|
5359
|
+
}
|
|
5360
|
+
|
|
5361
|
+
// Each toolData should become a list of contours, ContourSequence
|
|
5362
|
+
// contains a list of contours with their pointData, their geometry
|
|
5363
|
+
// type and their length.
|
|
5364
|
+
var ContourSequence = toolClass.getContourSequence(annotation, metadataProvider);
|
|
5365
|
+
|
|
5366
|
+
// Todo: random rgb color for now, options should be passed in
|
|
5367
|
+
var color = [Math.floor(Math.random() * 255), Math.floor(Math.random() * 255), Math.floor(Math.random() * 255)];
|
|
5368
|
+
return {
|
|
5369
|
+
ReferencedROINumber: index + 1,
|
|
5370
|
+
ROIDisplayColor: color,
|
|
5371
|
+
ContourSequence: ContourSequence
|
|
5372
|
+
};
|
|
5373
|
+
}
|
|
5374
|
+
}, {
|
|
5375
|
+
key: "register",
|
|
5376
|
+
value: function register(toolClass) {
|
|
5377
|
+
AnnotationToPointData.TOOL_NAMES[toolClass.toolName] = toolClass;
|
|
5378
|
+
}
|
|
5379
|
+
}]);
|
|
5380
|
+
return AnnotationToPointData;
|
|
5381
|
+
}();
|
|
5382
|
+
AnnotationToPointData.TOOL_NAMES = {};
|
|
5383
|
+
AnnotationToPointData.register(RectangleROIStartEndThreshold);
|
|
5384
|
+
|
|
5385
|
+
function getPatientModule(imageId, metadataProvider) {
|
|
5386
|
+
var generalSeriesModule = metadataProvider.get("generalSeriesModule", imageId);
|
|
5387
|
+
var generalStudyModule = metadataProvider.get("generalStudyModule", imageId);
|
|
5388
|
+
var patientStudyModule = metadataProvider.get("patientStudyModule", imageId);
|
|
5389
|
+
var patientModule = metadataProvider.get("patientModule", imageId);
|
|
5390
|
+
var patientDemographicModule = metadataProvider.get("patientDemographicModule", imageId);
|
|
5391
|
+
return {
|
|
5392
|
+
Modality: generalSeriesModule.modality,
|
|
5393
|
+
PatientID: patientModule.patientId,
|
|
5394
|
+
PatientName: patientModule.patientName,
|
|
5395
|
+
PatientBirthDate: "",
|
|
5396
|
+
PatientAge: patientStudyModule.patientAge,
|
|
5397
|
+
PatientSex: patientDemographicModule.patientSex,
|
|
5398
|
+
PatientWeight: patientStudyModule.patientWeight,
|
|
5399
|
+
StudyDate: generalStudyModule.studyDate,
|
|
5400
|
+
StudyTime: generalStudyModule.studyTime,
|
|
5401
|
+
StudyID: "ToDo",
|
|
5402
|
+
AccessionNumber: generalStudyModule.accessionNumber
|
|
5403
|
+
};
|
|
5404
|
+
}
|
|
5405
|
+
|
|
5406
|
+
function getReferencedFrameOfReferenceSequence(metadata, metadataProvider, dataset) {
|
|
5407
|
+
var imageId = metadata.referencedImageId,
|
|
5408
|
+
FrameOfReferenceUID = metadata.FrameOfReferenceUID;
|
|
5409
|
+
var instance = metadataProvider.get("instance", imageId);
|
|
5410
|
+
var SeriesInstanceUID = instance.SeriesInstanceUID;
|
|
5411
|
+
var ReferencedSeriesSequence = dataset.ReferencedSeriesSequence;
|
|
5412
|
+
return [{
|
|
5413
|
+
FrameOfReferenceUID: FrameOfReferenceUID,
|
|
5414
|
+
RTReferencedStudySequence: [{
|
|
5415
|
+
ReferencedSOPClassUID: dataset.SOPClassUID,
|
|
5416
|
+
ReferencedSOPInstanceUID: dataset.SOPInstanceUID,
|
|
5417
|
+
RTReferencedSeriesSequence: [{
|
|
5418
|
+
SeriesInstanceUID: SeriesInstanceUID,
|
|
5419
|
+
ContourImageSequence: _toConsumableArray(ReferencedSeriesSequence[0].ReferencedInstanceSequence)
|
|
5420
|
+
}]
|
|
5421
|
+
}]
|
|
5422
|
+
}];
|
|
5423
|
+
}
|
|
5424
|
+
|
|
5425
|
+
function getReferencedSeriesSequence(metadata, _index, metadataProvider, DicomMetadataStore) {
|
|
5426
|
+
// grab imageId from toolData
|
|
5427
|
+
var imageId = metadata.referencedImageId;
|
|
5428
|
+
var instance = metadataProvider.get("instance", imageId);
|
|
5429
|
+
var SeriesInstanceUID = instance.SeriesInstanceUID,
|
|
5430
|
+
StudyInstanceUID = instance.StudyInstanceUID;
|
|
5431
|
+
var ReferencedSeriesSequence = [];
|
|
5432
|
+
if (SeriesInstanceUID) {
|
|
5433
|
+
var series = DicomMetadataStore.getSeries(StudyInstanceUID, SeriesInstanceUID);
|
|
5434
|
+
var ReferencedSeries = {
|
|
5435
|
+
SeriesInstanceUID: SeriesInstanceUID,
|
|
5436
|
+
ReferencedInstanceSequence: []
|
|
5437
|
+
};
|
|
5438
|
+
series.instances.forEach(function (instance) {
|
|
5439
|
+
var SOPInstanceUID = instance.SOPInstanceUID,
|
|
5440
|
+
SOPClassUID = instance.SOPClassUID;
|
|
5441
|
+
ReferencedSeries.ReferencedInstanceSequence.push({
|
|
5442
|
+
ReferencedSOPClassUID: SOPClassUID,
|
|
5443
|
+
ReferencedSOPInstanceUID: SOPInstanceUID
|
|
5444
|
+
});
|
|
5445
|
+
});
|
|
5446
|
+
ReferencedSeriesSequence.push(ReferencedSeries);
|
|
5447
|
+
}
|
|
5448
|
+
return ReferencedSeriesSequence;
|
|
5449
|
+
}
|
|
5450
|
+
|
|
5451
|
+
function getRTROIObservationsSequence(toolData, index) {
|
|
5452
|
+
return {
|
|
5453
|
+
ObservationNumber: index + 1,
|
|
5454
|
+
ReferencedROINumber: index + 1,
|
|
5455
|
+
RTROIInterpretedType: "Todo: type",
|
|
5456
|
+
ROIInterpreter: "Todo: interpreter"
|
|
5457
|
+
};
|
|
5458
|
+
}
|
|
5459
|
+
|
|
5460
|
+
function getRTSeriesModule(DicomMetaDictionary) {
|
|
5461
|
+
return {
|
|
5462
|
+
SeriesInstanceUID: DicomMetaDictionary.uid(),
|
|
5463
|
+
// generate a new series instance uid
|
|
5464
|
+
SeriesNumber: "99" // Todo:: what should be the series number?
|
|
5465
|
+
};
|
|
5466
|
+
}
|
|
5467
|
+
|
|
5468
|
+
function getStructureSetModule(contour, index) {
|
|
5469
|
+
var FrameOfReferenceUID = contour.metadata.FrameOfReferenceUID;
|
|
5470
|
+
return {
|
|
5471
|
+
ROINumber: index + 1,
|
|
5472
|
+
ROIName: contour.name || "Todo: name ".concat(index + 1),
|
|
5473
|
+
ROIDescription: "Todo: description ".concat(index + 1),
|
|
5474
|
+
ROIGenerationAlgorithm: "Todo: algorithm",
|
|
5475
|
+
ReferencedFrameOfReferenceUID: FrameOfReferenceUID
|
|
5476
|
+
};
|
|
5477
|
+
}
|
|
5478
|
+
|
|
5479
|
+
var DicomMetaDictionary = dcmjs.data.DicomMetaDictionary;
|
|
5480
|
+
/**
|
|
5481
|
+
* Convert handles to RTSS report containing the dcmjs dicom dataset.
|
|
5482
|
+
*
|
|
5483
|
+
* Note: current WIP and using segmentation to contour conversion,
|
|
5484
|
+
* routine that is not fully tested
|
|
5485
|
+
*
|
|
5486
|
+
* @param segmentations - Cornerstone tool segmentations data
|
|
5487
|
+
* @param metadataProvider - Metadata provider
|
|
5488
|
+
* @param DicomMetadataStore - metadata store instance
|
|
5489
|
+
* @param cs - cornerstone instance
|
|
5490
|
+
* @param csTools - cornerstone tool instance
|
|
5491
|
+
* @returns Report object containing the dataset
|
|
5492
|
+
*/
|
|
5493
|
+
function generateRTSSFromSegmentations(segmentations, metadataProvider, DicomMetadataStore, cornerstoneCache, cornerstoneToolsEnums, vtkUtils) {
|
|
5494
|
+
// Convert segmentations to ROIContours
|
|
5495
|
+
var roiContours = [];
|
|
5496
|
+
var contourSets = generateContourSetsFromLabelmap({
|
|
5497
|
+
segmentations: segmentations,
|
|
5498
|
+
cornerstoneCache: cornerstoneCache,
|
|
5499
|
+
cornerstoneToolsEnums: cornerstoneToolsEnums,
|
|
5500
|
+
vtkUtils: vtkUtils
|
|
5501
|
+
});
|
|
5502
|
+
contourSets.forEach(function (contourSet, segIndex) {
|
|
5503
|
+
// Check contour set isn't undefined
|
|
5504
|
+
if (contourSet) {
|
|
5505
|
+
var contourSequence_1 = [];
|
|
5506
|
+
contourSet.sliceContours.forEach(function (sliceContour) {
|
|
5507
|
+
/**
|
|
5508
|
+
* addContour - Adds a new ROI with related contours to ROIContourSequence
|
|
5509
|
+
*
|
|
5510
|
+
* @param newContour - cornerstoneTools `ROIContour` object
|
|
5511
|
+
*
|
|
5512
|
+
* newContour = {
|
|
5513
|
+
* name: string,
|
|
5514
|
+
* description: string,
|
|
5515
|
+
* contourSequence: array[contour]
|
|
5516
|
+
* color: array[number],
|
|
5517
|
+
* metadata: {
|
|
5518
|
+
* referencedImageId: string,
|
|
5519
|
+
* FrameOfReferenceUID: string
|
|
5520
|
+
* }
|
|
5521
|
+
* }
|
|
5522
|
+
*
|
|
5523
|
+
* contour = {
|
|
5524
|
+
* ContourImageSequence: array[
|
|
5525
|
+
* { ReferencedSOPClassUID: string, ReferencedSOPInstanceUID: string}
|
|
5526
|
+
* ]
|
|
5527
|
+
* ContourGeometricType: string,
|
|
5528
|
+
* NumberOfContourPoints: number,
|
|
5529
|
+
* ContourData: array[number]
|
|
5530
|
+
* }
|
|
5531
|
+
*/
|
|
5532
|
+
// Note: change needed if support non-planar contour representation is needed
|
|
5533
|
+
var sopCommon = metadataProvider.get("sopCommonModule", sliceContour.referencedImageId);
|
|
5534
|
+
var ReferencedSOPClassUID = sopCommon.sopClassUID;
|
|
5535
|
+
var ReferencedSOPInstanceUID = sopCommon.sopInstanceUID;
|
|
5536
|
+
var ContourImageSequence = [
|
|
5537
|
+
{ ReferencedSOPClassUID: ReferencedSOPClassUID, ReferencedSOPInstanceUID: ReferencedSOPInstanceUID } // NOTE: replace in dcmjs?
|
|
5538
|
+
];
|
|
5539
|
+
var sliceContourPolyData = sliceContour.polyData;
|
|
5540
|
+
sliceContour.contours.forEach(function (contour, index) {
|
|
5541
|
+
var ContourGeometricType = contour.type;
|
|
5542
|
+
var NumberOfContourPoints = contour.contourPoints.length;
|
|
5543
|
+
var ContourData = [];
|
|
5544
|
+
contour.contourPoints.forEach(function (point) {
|
|
5545
|
+
var pointData = sliceContourPolyData.points[point];
|
|
5546
|
+
pointData[0] = +pointData[0].toFixed(2);
|
|
5547
|
+
pointData[1] = +pointData[1].toFixed(2);
|
|
5548
|
+
pointData[2] = +pointData[2].toFixed(2);
|
|
5549
|
+
ContourData.push(pointData[0]);
|
|
5550
|
+
ContourData.push(pointData[1]);
|
|
5551
|
+
ContourData.push(pointData[2]);
|
|
5552
|
+
});
|
|
5553
|
+
contourSequence_1.push({
|
|
5554
|
+
ContourImageSequence: ContourImageSequence,
|
|
5555
|
+
ContourGeometricType: ContourGeometricType,
|
|
5556
|
+
NumberOfContourPoints: NumberOfContourPoints,
|
|
5557
|
+
ContourNumber: index + 1,
|
|
5558
|
+
ContourData: ContourData
|
|
5559
|
+
});
|
|
5560
|
+
});
|
|
5561
|
+
});
|
|
5562
|
+
var segLabel = contourSet.label || "Segment ".concat(segIndex + 1);
|
|
5563
|
+
var ROIContour = {
|
|
5564
|
+
name: segLabel,
|
|
5565
|
+
description: segLabel,
|
|
5566
|
+
contourSequence: contourSequence_1,
|
|
5567
|
+
color: contourSet.color,
|
|
5568
|
+
metadata: contourSet.metadata
|
|
5569
|
+
};
|
|
5570
|
+
roiContours.push(ROIContour);
|
|
5571
|
+
}
|
|
5572
|
+
});
|
|
5573
|
+
var rtMetadata = {
|
|
5574
|
+
name: segmentations.label,
|
|
5575
|
+
label: segmentations.label
|
|
5576
|
+
};
|
|
5577
|
+
var dataset = _initializeDataset(rtMetadata, roiContours[0].metadata, metadataProvider);
|
|
5578
|
+
roiContours.forEach(function (contour, index) {
|
|
5579
|
+
var roiContour = {
|
|
5580
|
+
ROIDisplayColor: contour.color || [255, 0, 0],
|
|
5581
|
+
ContourSequence: contour.contourSequence,
|
|
5582
|
+
ReferencedROINumber: index + 1
|
|
5583
|
+
};
|
|
5584
|
+
dataset.StructureSetROISequence.push(getStructureSetModule(contour, index));
|
|
5585
|
+
dataset.ROIContourSequence.push(roiContour);
|
|
5586
|
+
// ReferencedSeriesSequence
|
|
5587
|
+
dataset.ReferencedSeriesSequence = getReferencedSeriesSequence(contour.metadata, index, metadataProvider, DicomMetadataStore);
|
|
5588
|
+
// ReferencedFrameOfReferenceSequence
|
|
5589
|
+
dataset.ReferencedFrameOfReferenceSequence =
|
|
5590
|
+
getReferencedFrameOfReferenceSequence(contour.metadata, metadataProvider, dataset);
|
|
5591
|
+
});
|
|
5592
|
+
var fileMetaInformationVersionArray = new Uint8Array(2);
|
|
5593
|
+
fileMetaInformationVersionArray[1] = 1;
|
|
5594
|
+
var _meta = {
|
|
5595
|
+
FileMetaInformationVersion: {
|
|
5596
|
+
Value: [fileMetaInformationVersionArray.buffer],
|
|
5597
|
+
vr: "OB"
|
|
5598
|
+
},
|
|
5599
|
+
TransferSyntaxUID: {
|
|
5600
|
+
Value: ["1.2.840.10008.1.2.1"],
|
|
5601
|
+
vr: "UI"
|
|
5602
|
+
},
|
|
5603
|
+
ImplementationClassUID: {
|
|
5604
|
+
Value: [DicomMetaDictionary.uid()],
|
|
5605
|
+
vr: "UI"
|
|
5606
|
+
},
|
|
5607
|
+
ImplementationVersionName: {
|
|
5608
|
+
Value: ["dcmjs"],
|
|
5609
|
+
vr: "SH"
|
|
5610
|
+
}
|
|
5611
|
+
};
|
|
5612
|
+
dataset._meta = _meta;
|
|
5613
|
+
return dataset;
|
|
5614
|
+
}
|
|
5615
|
+
/**
|
|
5616
|
+
* Convert handles to RTSSReport report object containing the dcmjs dicom dataset.
|
|
5617
|
+
*
|
|
5618
|
+
* Note: The tool data needs to be formatted in a specific way, and currently
|
|
5619
|
+
* it is limited to the RectangleROIStartEndTool in the Cornerstone.
|
|
5620
|
+
*
|
|
5621
|
+
* @param annotations Array of Cornerstone tool annotation data
|
|
5622
|
+
* @param metadataProvider Metadata provider
|
|
5623
|
+
* @param options report generation options
|
|
5624
|
+
* @returns Report object containing the dataset
|
|
5625
|
+
*/
|
|
5626
|
+
function generateRTSSFromAnnotations(annotations, metadataProvider, DicomMetadataStore, options) {
|
|
5627
|
+
var rtMetadata = {
|
|
5628
|
+
name: "RTSS from Annotations",
|
|
5629
|
+
label: "RTSS from Annotations"
|
|
5630
|
+
};
|
|
5631
|
+
var dataset = _initializeDataset(rtMetadata, annotations[0].metadata, metadataProvider);
|
|
5632
|
+
annotations.forEach(function (annotation, index) {
|
|
5633
|
+
var ContourSequence = AnnotationToPointData.convert(annotation, index, metadataProvider, options);
|
|
5634
|
+
dataset.StructureSetROISequence.push(getStructureSetModule(annotation, index));
|
|
5635
|
+
dataset.ROIContourSequence.push(ContourSequence);
|
|
5636
|
+
dataset.RTROIObservationsSequence.push(getRTROIObservationsSequence(annotation, index));
|
|
5637
|
+
// ReferencedSeriesSequence
|
|
5638
|
+
// Todo: handle more than one series
|
|
5639
|
+
dataset.ReferencedSeriesSequence = getReferencedSeriesSequence(annotation.metadata, index, metadataProvider, DicomMetadataStore);
|
|
5640
|
+
// ReferencedFrameOfReferenceSequence
|
|
5641
|
+
dataset.ReferencedFrameOfReferenceSequence =
|
|
5642
|
+
getReferencedFrameOfReferenceSequence(annotation.metadata, metadataProvider, dataset);
|
|
5643
|
+
});
|
|
5644
|
+
var fileMetaInformationVersionArray = new Uint8Array(2);
|
|
5645
|
+
fileMetaInformationVersionArray[1] = 1;
|
|
5646
|
+
var _meta = {
|
|
5647
|
+
FileMetaInformationVersion: {
|
|
5648
|
+
Value: [fileMetaInformationVersionArray.buffer],
|
|
5649
|
+
vr: "OB"
|
|
5650
|
+
},
|
|
5651
|
+
TransferSyntaxUID: {
|
|
5652
|
+
Value: ["1.2.840.10008.1.2.1"],
|
|
5653
|
+
vr: "UI"
|
|
5654
|
+
},
|
|
5655
|
+
ImplementationClassUID: {
|
|
5656
|
+
Value: [DicomMetaDictionary.uid()],
|
|
5657
|
+
vr: "UI"
|
|
5658
|
+
},
|
|
5659
|
+
ImplementationVersionName: {
|
|
5660
|
+
Value: ["dcmjs"],
|
|
5661
|
+
vr: "SH"
|
|
5662
|
+
}
|
|
5663
|
+
};
|
|
5664
|
+
dataset._meta = _meta;
|
|
5665
|
+
return dataset;
|
|
5666
|
+
}
|
|
5667
|
+
// /**
|
|
5668
|
+
// * Generate Cornerstone tool state from dataset
|
|
5669
|
+
// * @param {object} dataset dataset
|
|
5670
|
+
// * @param {object} hooks
|
|
5671
|
+
// * @param {function} hooks.getToolClass Function to map dataset to a tool class
|
|
5672
|
+
// * @returns
|
|
5673
|
+
// */
|
|
5674
|
+
// //static generateToolState(_dataset, _hooks = {}) {
|
|
5675
|
+
// function generateToolState() {
|
|
5676
|
+
// // Todo
|
|
5677
|
+
// console.warn("RTSS.generateToolState not implemented");
|
|
5678
|
+
// }
|
|
5679
|
+
function _initializeDataset(rtMetadata, imgMetadata, metadataProvider) {
|
|
5680
|
+
var rtSOPInstanceUID = DicomMetaDictionary.uid();
|
|
5681
|
+
// get the first annotation data
|
|
5682
|
+
var imageId = imgMetadata.referencedImageId, FrameOfReferenceUID = imgMetadata.FrameOfReferenceUID;
|
|
5683
|
+
var studyInstanceUID = metadataProvider.get("generalSeriesModule", imageId).studyInstanceUID;
|
|
5684
|
+
var patientModule = getPatientModule(imageId, metadataProvider);
|
|
5685
|
+
var rtSeriesModule = getRTSeriesModule(DicomMetaDictionary);
|
|
5686
|
+
return __assign(__assign(__assign({ StructureSetROISequence: [], ROIContourSequence: [], RTROIObservationsSequence: [], ReferencedSeriesSequence: [], ReferencedFrameOfReferenceSequence: [] }, patientModule), rtSeriesModule), { StudyInstanceUID: studyInstanceUID, SOPClassUID: "1.2.840.10008.5.1.4.1.1.481.3", SOPInstanceUID: rtSOPInstanceUID, Manufacturer: "dcmjs", Modality: "RTSTRUCT", FrameOfReferenceUID: FrameOfReferenceUID, PositionReferenceIndicator: "", StructureSetLabel: rtMetadata.label || "", StructureSetName: rtMetadata.name || "", ReferringPhysicianName: "", OperatorsName: "", StructureSetDate: DicomMetaDictionary.date(), StructureSetTime: DicomMetaDictionary.time() });
|
|
5687
|
+
}
|
|
5688
|
+
|
|
5689
|
+
var RTSS = /*#__PURE__*/Object.freeze({
|
|
5690
|
+
__proto__: null,
|
|
5691
|
+
generateContourSetsFromLabelmap: generateContourSetsFromLabelmap,
|
|
5692
|
+
generateRTSSFromAnnotations: generateRTSSFromAnnotations,
|
|
5693
|
+
generateRTSSFromSegmentations: generateRTSSFromSegmentations
|
|
5694
|
+
});
|
|
5695
|
+
|
|
4977
5696
|
var Cornerstone3DSR = {
|
|
4978
5697
|
Bidirectional: Bidirectional,
|
|
4979
5698
|
CobbAngle: CobbAngle,
|
|
@@ -4992,6 +5711,9 @@ var Cornerstone3DSR = {
|
|
|
4992
5711
|
var Cornerstone3DSEG = {
|
|
4993
5712
|
Segmentation: Segmentation$1
|
|
4994
5713
|
};
|
|
5714
|
+
var Cornerstone3DRT = {
|
|
5715
|
+
RTSS: RTSS
|
|
5716
|
+
};
|
|
4995
5717
|
|
|
4996
5718
|
var Colors = data.Colors,
|
|
4997
5719
|
BitArray = data.BitArray;
|
|
@@ -5189,6 +5911,9 @@ var adaptersSEG = {
|
|
|
5189
5911
|
Cornerstone3D: Cornerstone3DSEG,
|
|
5190
5912
|
VTKjs: VTKjsSEG
|
|
5191
5913
|
};
|
|
5914
|
+
var adaptersRT = {
|
|
5915
|
+
Cornerstone3D: Cornerstone3DRT
|
|
5916
|
+
};
|
|
5192
5917
|
|
|
5193
|
-
export { index as Enums, adaptersSEG, adaptersSR, index$1 as helpers };
|
|
5918
|
+
export { index as Enums, adaptersRT, adaptersSEG, adaptersSR, index$1 as helpers };
|
|
5194
5919
|
//# sourceMappingURL=adapters.es.js.map
|