@cornerstonejs/adapters 2.0.0-beta.2 → 2.0.0-beta.3

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