@ohif/app 3.11.0-beta.99 → 3.12.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/{2676.bundle.7e194265450db9aa1e98.js → 1402.bundle.e5306db9171c6c9793a7.js} +1379 -857
  2. package/dist/{9625.bundle.88dafbecfb596dade1a7.js → 1447.bundle.78d3b8f02c28f8ad9924.js} +2401 -2422
  3. package/dist/{147.bundle.c27839e06e2e8cabf9e1.js → 147.bundle.e22bae08eb10c0a51314.js} +42 -122
  4. package/dist/{1919.bundle.c53e597a4d2109ef7c97.js → 1919.bundle.ca1ffebd2ee775dc2d82.js} +6 -4
  5. package/dist/{2011.bundle.c44c0094525a51b528f4.js → 2011.bundle.12539f6bbbfc20a372e9.js} +2726 -197
  6. package/dist/{6216.bundle.48ff7813b6b3b8aba5f0.js → 2345.bundle.1fedf5750caf46ce99d9.js} +1 -35
  7. package/dist/{2701.bundle.d5c7ef6ec8b6cd9c2dfa.js → 2701.bundle.f2c7a5ab4a8b49d73bff.js} +9 -9
  8. package/dist/{2974.bundle.54d5903a8b29f1b09299.js → 2974.bundle.ec95e58b346dbe30a362.js} +2 -0
  9. package/dist/{7750.bundle.216dafe3c87d611928da.js → 319.bundle.45c1c250b562a3feefa5.js} +296 -62
  10. package/dist/{3658.bundle.046b575faed9e6bf1915.js → 3658.bundle.4b03e3bc783328aab18f.js} +2 -2
  11. package/dist/{9594.bundle.e623f61b984d7ff3b4b6.js → 4019.bundle.e07cc2a71b6e189a706a.js} +31 -157
  12. package/dist/{4113.bundle.46086f61126bf7100c6b.js → 4113.bundle.3b3fed48ad784ccda1a1.js} +268 -67
  13. package/dist/{414.bundle.443f391e019ece702e08.js → 414.bundle.fac8463232edcfda0b6c.js} +15 -15
  14. package/dist/{4202.bundle.aa4161a7b8cb7c691072.js → 4202.bundle.f804c72fb887b9543506.js} +1 -1
  15. package/dist/{4759.bundle.4da90b9346bb5e377ac6.js → 4759.bundle.8686abdd7bcf4aa7d107.js} +2 -0
  16. package/dist/{5349.bundle.be4b2d9a58412788944e.js → 5349.bundle.c117cc60ab5ff40eed14.js} +2 -2
  17. package/dist/{6972.bundle.0992b530f9691709f6d8.js → 557.bundle.a0344a04ae7a43642402.js} +5541 -5283
  18. package/dist/{5674.bundle.6c0d445cbd151b6e7aa1.js → 5674.bundle.4e40a906351477a2a193.js} +2 -0
  19. package/dist/{6201.bundle.a43859b8c8d3c89d73fe.js → 6201.bundle.5d7b8937f331f965d1aa.js} +4 -4
  20. package/dist/{6376.bundle.de4abf332424cba7513e.js → 6376.bundle.24e14fa9bf28c7c86e7c.js} +1 -1
  21. package/dist/{1943.bundle.3cf999579ec18e369ae6.js → 6991.bundle.08967b6f5698660e3a19.js} +67 -51
  22. package/dist/{7190.bundle.a35063abb9cb95986e67.js → 7190.bundle.4448c5a66a997bea24ca.js} +45 -8
  23. package/dist/{7197.bundle.c43fa621a7f16a4ea598.js → 7197.bundle.b8ce1b612ab1eff5d3ee.js} +5 -5
  24. package/dist/{810.bundle.0012733e3c8a87684485.js → 810.bundle.84fc54342c180b8a3023.js} +6 -6
  25. package/dist/{8228.bundle.2df7b5c0e4e0fdbb3654.js → 8228.bundle.ec3557eae81cafaed8c9.js} +2 -2
  26. package/dist/{85.bundle.c2855f98bbc7af94324a.js → 85.bundle.f9908f1f7350e5027d37.js} +3 -2
  27. package/dist/{8558.bundle.b69313ff865d69505f3f.js → 8558.bundle.ead200c0f2518d73739f.js} +3 -1
  28. package/dist/{860.bundle.f0d3efcceec48a1147ee.js → 860.bundle.f90055bfb2088bf17617.js} +24 -1
  29. package/dist/{8740.bundle.d0f554795adaecf0292c.js → 8740.bundle.9e567165a05c863b9698.js} +18 -5
  30. package/dist/{8815.bundle.85f43d0109e9e8eb7d2f.js → 8815.bundle.9999a630034893a74508.js} +32 -10
  31. package/dist/{934.bundle.f60a5cfd492b9b2f80d7.js → 934.bundle.e620a43102a8abf8a1e3.js} +4 -2
  32. package/dist/{963.bundle.5a8404d29251b83344c9.js → 963.bundle.b2434897acfb3e8abee5.js} +29 -9
  33. package/dist/{1443.bundle.405ff549a88a585906f3.js → 9732.bundle.91cb05748bef4e4f67c2.js} +883 -1731
  34. package/dist/{9560.bundle.203976e64c9a0202e247.js → 9856.bundle.c34e4165e91ef095aa9f.js} +5853 -5649
  35. package/dist/{9862.bundle.11d2a0f6528e9e916e25.js → 9862.bundle.e404cb5f0e762fbf6a03.js} +2 -14
  36. package/dist/{5886.bundle.181e673d6d5a9333039a.js → 9892.bundle.364aba175ce50baeb46c.js} +35397 -32968
  37. package/dist/app-config.js +8 -0
  38. package/dist/{app.bundle.4c2206d03a480f25fa24.js → app.bundle.41ff3ab8824cbbe55246.js} +2239 -1468
  39. package/dist/{compute.bundle.06ee8311038e4ac2d34d.js → compute.bundle.a1c8365c4732e8b82ca3.js} +3 -3
  40. package/dist/index.html +1 -1
  41. package/dist/{interpolation.bundle.6b3b374f2888d3744e61.js → interpolation.bundle.488206d0a2c4fa1dd6c5.js} +1 -1
  42. package/dist/{polySeg.bundle.d8a36b40716862d016de.js → polySeg.bundle.02258624e0ec30e9934c.js} +3 -3
  43. package/dist/sw.js +1 -1
  44. package/package.json +22 -22
  45. /package/dist/{1459.bundle.ce20cf6141ce43861cb6.js → 1459.bundle.163c80965265cae11781.js} +0 -0
  46. /package/dist/{1807.bundle.b29feec5110c55747364.js → 1807.bundle.d79c83317de38e4cffbd.js} +0 -0
  47. /package/dist/{213.bundle.5f47c7726bac8015c955.js → 213.bundle.f8b1fd7851428f0fa02f.js} +0 -0
  48. /package/dist/{2424.bundle.efc13d194c408554908e.js → 2424.bundle.7469c5960e905196f646.js} +0 -0
  49. /package/dist/{6027.bundle.80487e243df9ca540b1e.js → 6027.bundle.ab73f6c39c04c7662744.js} +0 -0
  50. /package/dist/{7431.bundle.503dc3262479de76225b.js → 7431.bundle.494b080a8141ef60067a.js} +0 -0
  51. /package/dist/{7639.bundle.d266780fbc9fe5a0053f.js → 7639.bundle.664fc584f04ca34a4bf1.js} +0 -0
@@ -23,10 +23,10 @@ var react = __webpack_require__(86326);
23
23
  var src = __webpack_require__(15871);
24
24
  // EXTERNAL MODULE: ../../i18n/src/index.js + 197 modules
25
25
  var i18n_src = __webpack_require__(89806);
26
- // EXTERNAL MODULE: ../../../extensions/cornerstone/src/index.tsx + 177 modules
27
- var cornerstone_src = __webpack_require__(56972);
28
- // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/adapters/dist/esm/index.js + 66 modules
29
- var esm = __webpack_require__(34279);
26
+ // EXTERNAL MODULE: ../../../extensions/cornerstone/src/index.tsx + 184 modules
27
+ var cornerstone_src = __webpack_require__(20557);
28
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/adapters/dist/esm/index.js + 70 modules
29
+ var esm = __webpack_require__(92740);
30
30
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/index.js
31
31
  var dist_esm = __webpack_require__(4667);
32
32
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/index.js + 1 modules
@@ -84,6 +84,13 @@ function getRenderableData({
84
84
  ValueType,
85
85
  imageId
86
86
  });
87
+ if (!imageId) {
88
+ // without the image id it's not possible to perform the calculations below
89
+ // these calculations also do not seem to be needed, since everything works
90
+ // just fine when we skip them. At least for SCOORD3D annotations.
91
+ return pointsWorld;
92
+ }
93
+
87
94
  // We do not have an explicit draw circle svg helper in Cornerstone3D at
88
95
  // this time, but we can use the ellipse svg helper to draw a circle, so
89
96
  // here we reshape the data for that purpose.
@@ -123,6 +130,12 @@ function getRenderableData({
123
130
  ValueType,
124
131
  imageId
125
132
  });
133
+ if (!imageId) {
134
+ // without the image id it's not possible to perform the calculations below
135
+ // these calculations also do not seem to be needed, since everything works
136
+ // just fine when we skip them. At least for SCOORD3D annotations.
137
+ return pointsWorld;
138
+ }
126
139
  const majorAxisStart = gl_matrix_esm/* vec3.fromValues */.eR.fromValues(...pointsWorld[0]);
127
140
  const majorAxisEnd = gl_matrix_esm/* vec3.fromValues */.eR.fromValues(...pointsWorld[1]);
128
141
  const minorAxisStart = gl_matrix_esm/* vec3.fromValues */.eR.fromValues(...pointsWorld[2]);
@@ -185,6 +198,10 @@ const toolNames = {
185
198
 
186
199
 
187
200
 
201
+
202
+ const {
203
+ MeasurementReport
204
+ } = esm/* adaptersSR */.QX.Cornerstone3D;
188
205
  function addSRAnnotation(measurement, imageId, frameNumber) {
189
206
  let toolName = tools_toolNames.DICOMSRDisplay;
190
207
  const renderableData = measurement.coords.reduce((acc, coordProps) => {
@@ -211,7 +228,10 @@ function addSRAnnotation(measurement, imageId, frameNumber) {
211
228
  frameOfReferenceUID = imagePlaneModule?.frameOfReferenceUID;
212
229
  }
213
230
  if (valueType === 'SCOORD3D') {
214
- toolName = tools_toolNames.SRSCOORD3DPoint;
231
+ const adapter = MeasurementReport.getAdapterForTrackingIdentifier(measurement.TrackingIdentifier);
232
+ if (!adapter) {
233
+ toolName = tools_toolNames.SRSCOORD3DPoint;
234
+ }
215
235
 
216
236
  // get the ReferencedFrameOfReferenceUID from the measurement
217
237
  frameOfReferenceUID = measurement.coords[0].ReferencedFrameOfReferenceSequence;
@@ -252,7 +272,7 @@ function addSRAnnotation(measurement, imageId, frameNumber) {
252
272
  ;// ../../../extensions/cornerstone-dicom-sr/src/utils/isRehydratable.ts
253
273
 
254
274
  const {
255
- MeasurementReport
275
+ MeasurementReport: isRehydratable_MeasurementReport
256
276
  } = esm/* adaptersSR */.QX.Cornerstone3D;
257
277
 
258
278
  /**
@@ -274,15 +294,23 @@ function isRehydratable(displaySet, mappings) {
274
294
  measurements
275
295
  } = displaySet;
276
296
  for (let i = 0; i < measurements.length; i++) {
297
+ const measurement = measurements[i];
298
+ if (!measurement) {
299
+ continue;
300
+ }
277
301
  const {
278
- TrackingIdentifier
279
- } = measurements[i] || {};
280
- if (!TrackingIdentifier) {
281
- console.warn('No tracking identifier for measurement ', measurements[i]);
302
+ TrackingIdentifier = '',
303
+ graphicType,
304
+ graphicCode,
305
+ pointsLength
306
+ } = measurement;
307
+ if (!TrackingIdentifier && !graphicType) {
308
+ console.warn('No tracking identifier or graphicType for measurement ', measurement);
282
309
  continue;
283
310
  }
284
- const adapter = MeasurementReport.getAdapterForTrackingIdentifier(TrackingIdentifier);
285
- const hydratable = adapter && mappingDefinitions.has(adapter.toolType);
311
+ const adapter = isRehydratable_MeasurementReport.getAdapterForTrackingIdentifier(TrackingIdentifier);
312
+ const adapters = isRehydratable_MeasurementReport.getAdaptersForTypes(graphicCode, graphicType, pointsLength);
313
+ const hydratable = adapter && mappingDefinitions.has(adapter.toolType) || adapters && adapters.some(adapter => mappingDefinitions.has(adapter.toolType));
286
314
  if (hydratable) {
287
315
  return true;
288
316
  }
@@ -318,10 +346,11 @@ const {
318
346
  CORNERSTONE_3D_TOOLS_SOURCE_VERSION
319
347
  } = cornerstone_src.Enums;
320
348
  const {
321
- ImageSet,
322
349
  MetadataProvider: metadataProvider
323
350
  } = src/* classes */.Ly;
324
351
  const {
352
+ TEXT_ANNOTATION_POSITION,
353
+ COMMENT_CODE,
325
354
  CodeScheme: Cornerstone3DCodeScheme
326
355
  } = esm/* adaptersSR */.QX.Cornerstone3D;
327
356
  /**
@@ -487,6 +516,12 @@ async function _load(srDisplaySet, servicesManager, extensionManager) {
487
516
  });
488
517
  });
489
518
  }
519
+ function _measurementBelongsToDisplaySet({
520
+ measurement,
521
+ displaySet
522
+ }) {
523
+ return measurement.coords[0].ReferencedFrameOfReferenceSequence === displaySet.FrameOfReferenceUID;
524
+ }
490
525
 
491
526
  /**
492
527
  * Checks if measurements can be added to a display set.
@@ -501,14 +536,10 @@ function _checkIfCanAddMeasurementsToDisplaySet(srDisplaySet, newDisplaySet, dat
501
536
  customizationService
502
537
  } = servicesManager.services;
503
538
  const unloadedMeasurements = srDisplaySet.measurements.filter(measurement => measurement.loaded === false);
504
- if (unloadedMeasurements.length === 0 || !(newDisplaySet instanceof ImageSet) || newDisplaySet.unsupported) {
539
+ if (!unloadedMeasurements.length || newDisplaySet.unsupported) {
505
540
  return;
506
541
  }
507
542
 
508
- // const { sopClassUids } = newDisplaySet;
509
- // Create a Set for faster lookups
510
- // const sopClassUidSet = new Set(sopClassUids);
511
-
512
543
  // Create a Map to efficiently look up ImageIds by SOPInstanceUID and frame number
513
544
  const imageIdMap = new Map();
514
545
  const imageIds = dataSource.getImageIdsForDisplaySet(newDisplaySet);
@@ -526,6 +557,7 @@ function _checkIfCanAddMeasurementsToDisplaySet(srDisplaySet, newDisplaySet, dat
526
557
  const is3DSR = srDisplaySet.SOPClassUID === sopClassDictionary.Comprehensive3DSR;
527
558
  for (let j = unloadedMeasurements.length - 1; j >= 0; j--) {
528
559
  let measurement = unloadedMeasurements[j];
560
+ const is3DMeasurement = measurement.coords?.[0]?.ValueType === 'SCOORD3D';
529
561
  const onBeforeSRAddMeasurement = customizationService.getCustomization('onBeforeSRAddMeasurement');
530
562
  if (typeof onBeforeSRAddMeasurement === 'function') {
531
563
  measurement = onBeforeSRAddMeasurement({
@@ -536,9 +568,14 @@ function _checkIfCanAddMeasurementsToDisplaySet(srDisplaySet, newDisplaySet, dat
536
568
  }
537
569
 
538
570
  // if it is 3d SR we can just add the SR annotation
539
- if (is3DSR) {
571
+ if (is3DSR && is3DMeasurement && _measurementBelongsToDisplaySet({
572
+ measurement,
573
+ displaySet: newDisplaySet
574
+ })) {
540
575
  addSRAnnotation(measurement, null, null);
541
576
  measurement.loaded = true;
577
+ measurement.displaySetInstanceUID = newDisplaySet.displaySetInstanceUID;
578
+ unloadedMeasurements.splice(j, 1);
542
579
  continue;
543
580
  }
544
581
  const referencedSOPSequence = measurement.coords[0].ReferencedSOPSequence;
@@ -689,7 +726,7 @@ function _getMergedContentSequencesByTrackingUniqueIdentifiers(MeasurementGroups
689
726
  * @returns {any} - The processed measurement result.
690
727
  */
691
728
  function _processMeasurement(mergedContentSequence) {
692
- if (mergedContentSequence.some(group => group.ValueType === 'SCOORD' || group.ValueType === 'SCOORD3D')) {
729
+ if (mergedContentSequence.some(group => isScoordOr3d(group) && !isTextPosition(group))) {
693
730
  return _processTID1410Measurement(mergedContentSequence);
694
731
  }
695
732
  return _processNonGeometricallyDefinedMeasurement(mergedContentSequence);
@@ -715,12 +752,28 @@ function _processTID1410Measurement(mergedContentSequence) {
715
752
  return;
716
753
  }
717
754
  const NUMContentItems = mergedContentSequence.filter(group => group.ValueType === 'NUM');
755
+ const {
756
+ ConceptNameCodeSequence: conceptNameItem
757
+ } = graphicItem;
758
+ const {
759
+ CodeValue: graphicValue,
760
+ CodingSchemeDesignator: graphicDesignator
761
+ } = conceptNameItem;
762
+ const graphicCode = `${graphicDesignator}:${graphicValue}`;
763
+ const pointDataItem = _getCoordsFromSCOORDOrSCOORD3D(graphicItem);
764
+ const is3DMeasurement = pointDataItem.ValueType === 'SCOORD3D';
765
+ const pointLength = is3DMeasurement ? 3 : 2;
766
+ const pointsLength = pointDataItem.GraphicData.length / pointLength;
718
767
  const measurement = {
719
768
  loaded: false,
720
769
  labels: [],
721
- coords: [_getCoordsFromSCOORDOrSCOORD3D(graphicItem)],
770
+ coords: [pointDataItem],
722
771
  TrackingUniqueIdentifier: UIDREFContentItem.UID,
723
- TrackingIdentifier: TrackingIdentifierContentItem.TextValue
772
+ TrackingIdentifier: TrackingIdentifierContentItem.TextValue,
773
+ graphicCode,
774
+ is3DMeasurement,
775
+ pointsLength,
776
+ graphicType: pointDataItem.GraphicType
724
777
  };
725
778
  NUMContentItems.forEach(item => {
726
779
  const {
@@ -753,6 +806,7 @@ function _processNonGeometricallyDefinedMeasurement(mergedContentSequence) {
753
806
  const TrackingIdentifierContentItem = mergedContentSequence.find(item => item.ConceptNameCodeSequence.CodeValue === enums/* CodeNameCodeSequenceValues */.n7.TrackingIdentifier);
754
807
  const finding = mergedContentSequence.find(item => item.ConceptNameCodeSequence.CodeValue === enums/* CodeNameCodeSequenceValues */.n7.Finding);
755
808
  const findingSites = mergedContentSequence.filter(item => item.ConceptNameCodeSequence.CodingSchemeDesignator === enums/* CodingSchemeDesignators */.bY.SRT && item.ConceptNameCodeSequence.CodeValue === enums/* CodeNameCodeSequenceValues */.n7.FindingSite);
809
+ const commentSites = mergedContentSequence.filter(item => item.ConceptNameCodeSequence.CodingSchemeDesignator === COMMENT_CODE.schemeDesignator && item.ConceptNameCodeSequence.CodeValue === COMMENT_CODE.value);
756
810
  const measurement = {
757
811
  loaded: false,
758
812
  labels: [],
@@ -760,6 +814,16 @@ function _processNonGeometricallyDefinedMeasurement(mergedContentSequence) {
760
814
  TrackingUniqueIdentifier: UIDREFContentItem.UID,
761
815
  TrackingIdentifier: TrackingIdentifierContentItem.TextValue
762
816
  };
817
+ if (commentSites) {
818
+ for (const group of commentSites) {
819
+ if (group.TextValue) {
820
+ measurement.labels.push({
821
+ label: group.TextValue,
822
+ value: ''
823
+ });
824
+ }
825
+ }
826
+ }
763
827
  if (finding && enums/* CodingSchemeDesignators */.bY.CornerstoneCodeSchemes.includes(finding.ConceptCodeSequence.CodingSchemeDesignator) && finding.ConceptCodeSequence.CodeValue === Cornerstone3DCodeScheme.codeValues.CORNERSTONEFREETEXT) {
764
828
  measurement.labels.push({
765
829
  label: Cornerstone3DCodeScheme.codeValues.CORNERSTONEFREETEXT,
@@ -903,6 +967,13 @@ function _getSequenceAsArray(sequence) {
903
967
  }
904
968
  return Array.isArray(sequence) ? sequence : [sequence];
905
969
  }
970
+ function isScoordOr3d(group) {
971
+ return group.ValueType === 'SCOORD' || group.ValueType === 'SCOORD3D';
972
+ }
973
+ function isTextPosition(group) {
974
+ const concept = group.ConceptNameCodeSequence[0];
975
+ return concept && concept.CodeValue === TEXT_ANNOTATION_POSITION.value && concept.CodingSchemeDesignator === TEXT_ANNOTATION_POSITION.schemeDesignator;
976
+ }
906
977
  /* harmony default export */ const src_getSopClassHandlerModule = (getSopClassHandlerModule);
907
978
  ;// ../../../extensions/cornerstone-dicom-sr/src/getHangingProtocolModule.ts
908
979
  const srProtocol = {
@@ -988,17 +1059,10 @@ var dcmjs_es = __webpack_require__(5842);
988
1059
  ;// ../../../extensions/cornerstone-dicom-sr/src/utils/getFilteredCornerstoneToolState.ts
989
1060
 
990
1061
 
991
- const {
992
- log
993
- } = src/* default */.Ay;
994
1062
  function getFilteredCornerstoneToolState(measurementData, additionalFindingTypes) {
995
1063
  const filteredToolState = {};
996
1064
  function addToFilteredToolState(annotation, toolType) {
997
- if (!annotation.metadata?.referencedImageId) {
998
- log.warn(`[DICOMSR] No referencedImageId found for ${toolType} ${annotation.id}`);
999
- return;
1000
- }
1001
- const imageId = annotation.metadata.referencedImageId;
1065
+ const imageId = annotation.metadata?.referencedImageId ?? esm/* NO_IMAGE_ID */.W6;
1002
1066
  if (!filteredToolState[imageId]) {
1003
1067
  filteredToolState[imageId] = {};
1004
1068
  }
@@ -1087,8 +1151,12 @@ const {
1087
1151
  function getLabelFromDCMJSImportedToolData(toolData) {
1088
1152
  const {
1089
1153
  findingSites = [],
1090
- finding
1154
+ finding,
1155
+ annotation
1091
1156
  } = toolData;
1157
+ if (annotation.data.label) {
1158
+ return annotation.data.label;
1159
+ }
1092
1160
  let freeTextLabel = findingSites.find(fs => fs.CodeValue === getLabelFromDCMJSImportedToolData_Cornerstone3DCodeScheme.codeValues.CORNERSTONEFREETEXT);
1093
1161
  if (freeTextLabel) {
1094
1162
  return freeTextLabel.CodeMeaning;
@@ -1104,6 +1172,7 @@ function getLabelFromDCMJSImportedToolData(toolData) {
1104
1172
 
1105
1173
 
1106
1174
 
1175
+
1107
1176
  const {
1108
1177
  locking
1109
1178
  } = dist_esm.annotation;
@@ -1111,14 +1180,12 @@ const {
1111
1180
  guid
1112
1181
  } = src/* default.utils */.Ay.utils;
1113
1182
  const {
1114
- MeasurementReport: hydrateStructuredReport_MeasurementReport,
1115
- CORNERSTONE_3D_TAG
1183
+ MeasurementReport: hydrateStructuredReport_MeasurementReport
1116
1184
  } = esm/* adaptersSR */.QX.Cornerstone3D;
1117
1185
  const {
1118
1186
  CORNERSTONE_3D_TOOLS_SOURCE_NAME: hydrateStructuredReport_CORNERSTONE_3D_TOOLS_SOURCE_NAME,
1119
1187
  CORNERSTONE_3D_TOOLS_SOURCE_VERSION: hydrateStructuredReport_CORNERSTONE_3D_TOOLS_SOURCE_VERSION
1120
1188
  } = cornerstone_src.Enums;
1121
- const supportedLegacyCornerstoneTags = (/* unused pure expression or super */ null && (['cornerstoneTools@^4.0.0']));
1122
1189
  const convertCode = (codingValues, code) => {
1123
1190
  if (!code || code.CodingSchemeDesignator === 'CORNERSTONEJS') {
1124
1191
  return;
@@ -1149,8 +1216,10 @@ const convertSites = (codingValues, sites) => {
1149
1216
  };
1150
1217
 
1151
1218
  /**
1152
- * Hydrates a structured report, for default viewports.
1153
- *
1219
+ * Hydrates a structured report
1220
+ * Handles 2d and 3d hydration from SCOORD and SCOORD3D points
1221
+ * For 3D hydration, chooses a volume display set to display with
1222
+ * FOr 2D hydration, chooses the (first) display set containing the referenced image.
1154
1223
  */
1155
1224
  function hydrateStructuredReport({
1156
1225
  servicesManager,
@@ -1193,13 +1262,13 @@ function hydrateStructuredReport({
1193
1262
  // Mapping of legacy datasets is now directly handled by adapters module
1194
1263
  const datasetToUse = instance;
1195
1264
 
1196
- // Use dcmjs to generate toolState.
1265
+ // Use CS3D adapters to generate toolState.
1197
1266
  let storedMeasurementByAnnotationType = hydrateStructuredReport_MeasurementReport.generateToolState(datasetToUse,
1198
1267
  // NOTE: we need to pass in the imageIds to dcmjs since the we use them
1199
1268
  // for the imageToWorld transformation. The following assumes that the order
1200
1269
  // that measurements were added to the display set are the same order as
1201
1270
  // the measurementGroups in the instance.
1202
- sopInstanceUIDToImageId, core_dist_esm.utilities.imageToWorldCoords, core_dist_esm.metaData);
1271
+ sopInstanceUIDToImageId, core_dist_esm.metaData);
1203
1272
  const onBeforeSRHydration = customizationService.getCustomization('onBeforeSRHydration')?.value;
1204
1273
  if (typeof onBeforeSRHydration === 'function') {
1205
1274
  storedMeasurementByAnnotationType = onBeforeSRHydration({
@@ -1239,6 +1308,9 @@ function hydrateStructuredReport({
1239
1308
  const SeriesInstanceUIDs = [];
1240
1309
  for (let i = 0; i < imageIds.length; i++) {
1241
1310
  const imageId = imageIds[i];
1311
+ if (!imageId) {
1312
+ continue;
1313
+ }
1242
1314
  const {
1243
1315
  SeriesInstanceUID,
1244
1316
  StudyInstanceUID
@@ -1252,32 +1324,50 @@ function hydrateStructuredReport({
1252
1324
  console.warn('NO SUPPORT FOR SRs THAT HAVE MEASUREMENTS FROM MULTIPLE STUDIES.');
1253
1325
  }
1254
1326
  }
1327
+
1328
+ /**
1329
+ * Gets reference data for what frame of reference and the referenced
1330
+ * image id, or for 3d measurements, the volumeId to apply this annotation to.
1331
+ */
1332
+ function getReferenceData(toolData) {
1333
+ // Add the measurement to toolState
1334
+ // dcmjs and Cornerstone3D has structural defect in supporting multi-frame
1335
+ // files, and looking up the imageId from sopInstanceUIDToImageId results
1336
+ // in the wrong value.
1337
+ const frameNumber = toolData.annotation.data && toolData.annotation.data.frameNumber || 1;
1338
+ const imageId = imageIdsForToolState[toolData.sopInstanceUid][frameNumber] || sopInstanceUIDToImageId[toolData.sopInstanceUid];
1339
+ if (!imageId) {
1340
+ return getReferenceData3D(toolData, servicesManager);
1341
+ }
1342
+ const instance = core_dist_esm.metaData.get('instance', imageId);
1343
+ const {
1344
+ FrameOfReferenceUID
1345
+ // SOPInstanceUID,
1346
+ // SeriesInstanceUID,
1347
+ // StudyInstanceUID,
1348
+ } = instance;
1349
+ return {
1350
+ referencedImageId: imageId,
1351
+ FrameOfReferenceUID
1352
+ };
1353
+ }
1255
1354
  Object.keys(hydratableMeasurementsInSR).forEach(annotationType => {
1256
1355
  const toolDataForAnnotationType = hydratableMeasurementsInSR[annotationType];
1257
1356
  toolDataForAnnotationType.forEach(toolData => {
1258
- // Add the measurement to toolState
1259
- // dcmjs and Cornerstone3D has structural defect in supporting multi-frame
1260
- // files, and looking up the imageId from sopInstanceUIDToImageId results
1261
- // in the wrong value.
1262
- const frameNumber = toolData.annotation.data && toolData.annotation.data.frameNumber || 1;
1263
- const imageId = imageIdsForToolState[toolData.sopInstanceUid][frameNumber] || sopInstanceUIDToImageId[toolData.sopInstanceUid];
1264
1357
  toolData.uid = guid();
1265
- const instance = core_dist_esm.metaData.get('instance', imageId);
1358
+ const referenceData = getReferenceData(toolData);
1266
1359
  const {
1267
- FrameOfReferenceUID
1268
- // SOPInstanceUID,
1269
- // SeriesInstanceUID,
1270
- // StudyInstanceUID,
1271
- } = instance;
1360
+ imageId
1361
+ } = referenceData;
1272
1362
  const annotation = {
1273
1363
  annotationUID: toolData.annotation.annotationUID,
1274
1364
  data: toolData.annotation.data,
1275
1365
  metadata: {
1276
- toolName: annotationType,
1277
- referencedImageId: imageId,
1278
- FrameOfReferenceUID
1366
+ ...referenceData,
1367
+ toolName: annotationType
1279
1368
  }
1280
1369
  };
1370
+ core_dist_esm.utilities.updatePlaneRestriction(annotation.data.handles.points, annotation.metadata);
1281
1371
  const source = measurementService.getSource(hydrateStructuredReport_CORNERSTONE_3D_TOOLS_SOURCE_NAME, hydrateStructuredReport_CORNERSTONE_3D_TOOLS_SOURCE_VERSION);
1282
1372
  annotation.data.label = getLabelFromDCMJSImportedToolData(toolData);
1283
1373
  annotation.data.finding = convertCode(codingValues, toolData.finding?.[0]);
@@ -1298,7 +1388,7 @@ function hydrateStructuredReport({
1298
1388
  if (disableEditing) {
1299
1389
  locking.setAnnotationLocked(newAnnotationUID, true);
1300
1390
  }
1301
- if (!imageIds.includes(imageId)) {
1391
+ if (imageId && !imageIds.includes(imageId)) {
1302
1392
  imageIds.push(imageId);
1303
1393
  }
1304
1394
  });
@@ -1309,6 +1399,95 @@ function hydrateStructuredReport({
1309
1399
  SeriesInstanceUIDs
1310
1400
  };
1311
1401
  }
1402
+
1403
+ /**
1404
+ * For 3d annotations, there are often several display sets which could
1405
+ * be used to display the annotation. Choose the first annotation with the
1406
+ * same frame of reference that is reconstructable, or the first display set
1407
+ * otherwise.
1408
+ */
1409
+ function chooseDisplaySet(displaySets, annotation) {
1410
+ if (!displaySets?.length) {
1411
+ console.warn('No display set found for', annotation);
1412
+ return;
1413
+ }
1414
+ if (displaySets.length === 1) {
1415
+ return displaySets[0];
1416
+ }
1417
+ const volumeDs = displaySets.find(ds => ds.isReconstructable);
1418
+ if (volumeDs) {
1419
+ return volumeDs;
1420
+ }
1421
+ return displaySets[0];
1422
+ }
1423
+
1424
+ /**
1425
+ * Gets the additional reference data appropriate for a 3d reference.
1426
+ * This will choose a volume id, frame of reference and a plane restriction.
1427
+ */
1428
+ function getReferenceData3D(toolData, servicesManager) {
1429
+ const {
1430
+ FrameOfReferenceUID
1431
+ } = toolData.annotation.metadata;
1432
+ const {
1433
+ points
1434
+ } = toolData.annotation.data.handles;
1435
+ const {
1436
+ displaySetService
1437
+ } = servicesManager.services;
1438
+ const displaySetsFOR = displaySetService.getDisplaySetsBy(ds => ds.FrameOfReferenceUID === FrameOfReferenceUID);
1439
+ if (!displaySetsFOR.length || !points?.length) {
1440
+ return {
1441
+ FrameOfReferenceUID
1442
+ };
1443
+ }
1444
+ const ds = chooseDisplaySet(displaySetsFOR, toolData.annotation);
1445
+ const cameraView = chooseCameraView(ds, points);
1446
+ const viewReference = {
1447
+ ...cameraView,
1448
+ volumeId: ds.displaySetInstanceUID,
1449
+ FrameOfReferenceUID
1450
+ };
1451
+ core_dist_esm.utilities.updatePlaneRestriction(points, viewReference);
1452
+ return viewReference;
1453
+ }
1454
+
1455
+ /**
1456
+ * Chooses a possible camera view - right now this is fairly basic,
1457
+ * just setting the unknowns to null.
1458
+ */
1459
+ function chooseCameraView(_ds, points) {
1460
+ const selectedPoints = choosePoints(points);
1461
+ const cameraFocalPoint = centerOf(selectedPoints);
1462
+ // These are sufficient to be null for now and can be set on first view
1463
+ let viewPlaneNormal = null;
1464
+ let viewUp = null;
1465
+ return {
1466
+ cameraFocalPoint,
1467
+ viewPlaneNormal,
1468
+ viewUp
1469
+ };
1470
+ }
1471
+ function centerOf(points) {
1472
+ const scale = 1 / points.length;
1473
+ const center = gl_matrix_esm/* vec3.create */.eR.create();
1474
+ for (const point of points) {
1475
+ gl_matrix_esm/* vec3.scaleAndAdd */.eR.scaleAndAdd(center, center, point, scale);
1476
+ }
1477
+ return center;
1478
+ }
1479
+ function choosePoints(points) {
1480
+ if (points.length === 1 || points.length === 2) {
1481
+ return points;
1482
+ }
1483
+ const firstIndex = 0;
1484
+ const secondIndex = Math.ceil(points.length / 4);
1485
+ const thirdIndex = Math.ceil(points.length / 2);
1486
+ // TODO - check if colinear, if so try to find another 3 points.
1487
+
1488
+ const newPoints = [points[firstIndex], points[secondIndex], points[thirdIndex]];
1489
+ return newPoints;
1490
+ }
1312
1491
  ;// ../../../extensions/cornerstone-dicom-sr/src/commandsModule.ts
1313
1492
 
1314
1493
 
@@ -1320,7 +1499,7 @@ const {
1320
1499
  MeasurementReport: commandsModule_MeasurementReport
1321
1500
  } = esm/* adaptersSR */.QX.Cornerstone3D;
1322
1501
  const {
1323
- log: commandsModule_log
1502
+ log
1324
1503
  } = src/* default */.Ay;
1325
1504
  /**
1326
1505
  * @param measurementData An array of measurements from the measurements service
@@ -1331,7 +1510,7 @@ const {
1331
1510
  */
1332
1511
  const _generateReport = (measurementData, additionalFindingTypes, options = {}) => {
1333
1512
  const filteredToolState = utils_getFilteredCornerstoneToolState(measurementData, additionalFindingTypes);
1334
- const report = commandsModule_MeasurementReport.generateReport(filteredToolState, core_dist_esm.metaData, core_dist_esm.utilities.worldToImageCoords, options);
1513
+ const report = commandsModule_MeasurementReport.generateReport(filteredToolState, core_dist_esm.metaData, options);
1335
1514
  const {
1336
1515
  dataset
1337
1516
  } = report;
@@ -1351,9 +1530,7 @@ const commandsModule = props => {
1351
1530
  commandsManager
1352
1531
  } = props;
1353
1532
  const {
1354
- customizationService,
1355
- viewportGridService,
1356
- displaySetService
1533
+ customizationService
1357
1534
  } = servicesManager.services;
1358
1535
  const actions = {
1359
1536
  changeColorMeasurement: ({
@@ -1414,9 +1591,9 @@ const commandsModule = props => {
1414
1591
  }) => {
1415
1592
  // Use the @cornerstonejs adapter for converting to/from DICOM
1416
1593
  // But it is good enough for now whilst we only have cornerstone as a datasource.
1417
- commandsModule_log.info('[DICOMSR] storeMeasurements');
1594
+ log.info('[DICOMSR] storeMeasurements');
1418
1595
  if (!dataSource || !dataSource.store || !dataSource.store.dicom) {
1419
- commandsModule_log.error('[DICOMSR] datasource has no dataSource.store.dicom endpoint!');
1596
+ log.error('[DICOMSR] datasource has no dataSource.store.dicom endpoint!');
1420
1597
  return Promise.reject({});
1421
1598
  }
1422
1599
  try {
@@ -1432,6 +1609,9 @@ const commandsModule = props => {
1432
1609
  console.log('naturalizedReport missing imaging content', naturalizedReport);
1433
1610
  throw new Error('Invalid report, no content');
1434
1611
  }
1612
+ if (!naturalizedReport.SOPClassUID) {
1613
+ throw new Error('No sop class uid');
1614
+ }
1435
1615
  const onBeforeDicomStore = customizationService.getCustomization('onBeforeDicomStore');
1436
1616
  let dicomDict;
1437
1617
  if (typeof onBeforeDicomStore === 'function') {
@@ -1453,7 +1633,7 @@ const commandsModule = props => {
1453
1633
  return naturalizedReport;
1454
1634
  } catch (error) {
1455
1635
  console.warn(error);
1456
- commandsModule_log.error(`[DICOMSR] Error while saving the measurements: ${error.message}`);
1636
+ log.error(`[DICOMSR] Error while saving the measurements: ${error.message}`);
1457
1637
  throw new Error(error.message || 'Error while saving the measurements.');
1458
1638
  }
1459
1639
  },
@@ -1910,7 +2090,13 @@ const SRSCOOR3DProbe = {
1910
2090
  * @param {Object} cornerstone Cornerstone event data
1911
2091
  * @return {Measurement} Measurement instance
1912
2092
  */
1913
- toMeasurement: (csToolsEventDetail, displaySetService, CornerstoneViewportService, getValueTypeFromToolType, customizationService) => {
2093
+ toMeasurement: ({
2094
+ servicesManager,
2095
+ getValueTypeFromToolType
2096
+ }, csToolsEventDetail) => {
2097
+ const {
2098
+ displaySetService
2099
+ } = servicesManager.services;
1914
2100
  const {
1915
2101
  annotation
1916
2102
  } = csToolsEventDetail;
@@ -1924,16 +2110,26 @@ const SRSCOOR3DProbe = {
1924
2110
  return null;
1925
2111
  }
1926
2112
  const {
1927
- toolName
2113
+ toolName,
2114
+ FrameOfReferenceUID
1928
2115
  } = metadata;
1929
2116
  const {
1930
2117
  points
1931
2118
  } = data.handles;
2119
+ const displaySets = displaySetService.getActiveDisplaySets().filter(ds => ds.FrameOfReferenceUID === FrameOfReferenceUID);
2120
+ const displaySet = displaySets.filter(ds => ds.isReconstructable)[0] || displaySets[0];
2121
+ const {
2122
+ StudyInstanceUID: referenceStudyUID,
2123
+ SeriesInstanceUID: referenceSeriesUID
2124
+ } = displaySets[0] || {};
1932
2125
  const displayText = getDisplayText(annotation);
1933
2126
  return {
1934
2127
  uid: annotationUID,
1935
2128
  points,
1936
2129
  metadata,
2130
+ referenceStudyUID,
2131
+ referenceSeriesUID,
2132
+ displaySetInstanceUID: displaySet?.displaySetInstanceUID,
1937
2133
  toolName: metadata.toolName,
1938
2134
  label: data.label,
1939
2135
  displayText: displayText,
@@ -1959,7 +2155,10 @@ function getDisplayText(annotation) {
1959
2155
  displayText.push(`Finding Site: ${label.value}`);
1960
2156
  }
1961
2157
  }
1962
- return displayText;
2158
+ return {
2159
+ primary: displayText,
2160
+ secondary: []
2161
+ };
1963
2162
  }
1964
2163
  /* harmony default export */ const SRSCOOR3DProbeMapper = (SRSCOOR3DProbe);
1965
2164
  ;// ../../../extensions/cornerstone-dicom-sr/src/utils/addToolInstance.ts
@@ -2018,7 +2217,9 @@ function init({
2018
2217
  const {
2019
2218
  POINT
2020
2219
  } = measurementService.VALUE_TYPES;
2021
- measurementService.addMapping(csTools3DVer1MeasurementSource, 'SRSCOORD3DPoint', POINT, SRSCOOR3DProbeMapper.toAnnotation, SRSCOOR3DProbeMapper.toMeasurement);
2220
+ measurementService.addMapping(csTools3DVer1MeasurementSource, 'SRSCOORD3DPoint', POINT, SRSCOOR3DProbeMapper.toAnnotation, SRSCOOR3DProbeMapper.toMeasurement.bind(null, {
2221
+ servicesManager
2222
+ }));
2022
2223
 
2023
2224
  // Modify annotation tools to use dashed lines on SR
2024
2225
  const dashedLine = {
@@ -2124,7 +2325,7 @@ const dicomSRExtension = {
2124
2325
  /* harmony export */ sh: () => (/* binding */ SCOORDTypes)
2125
2326
  /* harmony export */ });
2126
2327
  /* unused harmony export RelationshipType */
2127
- /* harmony import */ var _cornerstonejs_adapters__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(34279);
2328
+ /* harmony import */ var _cornerstonejs_adapters__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(92740);
2128
2329
 
2129
2330
  const {
2130
2331
  CodeScheme: Cornerstone3DCodeScheme