@cornerstonejs/adapters 3.31.3 → 3.31.5

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,6 +1,6 @@
1
1
  import BaseAdapter3D from "./BaseAdapter3D";
2
2
  declare class Angle extends BaseAdapter3D {
3
- static getMeasurementData(MeasurementGroup: any, sopInstanceUIDToImageIdMap: any, imageToWorldCoords: any, metadata: any): {
3
+ static getMeasurementData(MeasurementGroup: any, sopInstanceUIDToImageIdMap: any, metadata: any): {
4
4
  description?: string;
5
5
  sopInstanceUid?: string;
6
6
  annotation: import("packages/tools/dist/esm/types").Annotation;
@@ -10,12 +10,10 @@ const {
10
10
  CobbAngle: TID300CobbAngle
11
11
  } = utilities.TID300;
12
12
  class Angle extends BaseAdapter3D {
13
- static getMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, imageToWorldCoords, metadata) {
13
+ static getMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata) {
14
14
  const {
15
15
  state,
16
16
  NUMGroup,
17
- scoord,
18
- scoordArgs,
19
17
  worldCoords,
20
18
  referencedImageId,
21
19
  ReferencedFrameNumber
@@ -1,6 +1,6 @@
1
1
  import BaseAdapter3D from "./BaseAdapter3D";
2
2
  declare class ArrowAnnotate extends BaseAdapter3D {
3
- static getMeasurementData(MeasurementGroup: any, sopInstanceUIDToImageIdMap: any, imageToWorldCoords: any, metadata: any, _trackingIdentifier: any): {
3
+ static getMeasurementData(MeasurementGroup: any, sopInstanceUIDToImageIdMap: any, metadata: any, _trackingIdentifier: any): {
4
4
  description?: string;
5
5
  sopInstanceUid?: string;
6
6
  annotation: import("packages/tools/dist/esm/types").Annotation;
@@ -1,20 +1,23 @@
1
- import MeasurementReport from './MeasurementReport.js';
2
1
  import { utilities } from 'dcmjs';
2
+ import { utilities as utilities$1 } from '@cornerstonejs/core';
3
+ import MeasurementReport from './MeasurementReport.js';
3
4
  import BaseAdapter3D from './BaseAdapter3D.js';
4
5
  import CodingScheme from './CodingScheme.js';
5
6
  import 'buffer';
6
7
  import { toScoord } from '../helpers/toScoordType.js';
7
- import '@cornerstonejs/core';
8
8
 
9
9
  var _ArrowAnnotate;
10
10
  const {
11
11
  Point: TID300Point
12
12
  } = utilities.TID300;
13
+ const {
14
+ imageToWorldCoords
15
+ } = utilities$1;
13
16
  const {
14
17
  codeValues
15
18
  } = CodingScheme;
16
19
  class ArrowAnnotate extends BaseAdapter3D {
17
- static getMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, imageToWorldCoords, metadata, _trackingIdentifier) {
20
+ static getMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata, _trackingIdentifier) {
18
21
  const {
19
22
  state,
20
23
  SCOORDGroup,
@@ -19,11 +19,18 @@ export default class BaseAdapter3D {
19
19
  static trackingIdentifierTextValue: string;
20
20
  static trackingIdentifiers: Set<string>;
21
21
  static parentType: string;
22
+ static registerType(code?: string, type?: string, count?: number): void;
23
+ static getPointsCount(graphicItem: any): number;
24
+ static getGraphicItems(measurementGroup: any, filter: any): any;
25
+ static getGraphicItem(measurementGroup: any, offset?: number, type?: any): any;
26
+ static getGraphicCode(graphicItem: any): string;
27
+ static getGraphicType(graphicItem: any): any;
28
+ static isValidMeasurement(_measurementGroup: any): boolean;
22
29
  static init(toolType: string, representation: any, options?: AdapterOptions): void;
23
30
  static registerLegacy(): void;
24
31
  static registerSubType(adapter: MeasurementAdapter, toolType: string, replace?: any): any;
25
32
  static isValidCornerstoneTrackingIdentifier(trackingIdentifier: string): boolean;
26
- static getMeasurementData(MeasurementGroup: any, sopInstanceUIDToImageIdMap: any, _imageToWorldCoords: any, metadata: any, trackingIdentifier?: string): {
33
+ static getMeasurementData(MeasurementGroup: any, sopInstanceUIDToImageIdMap: any, metadata: any, trackingIdentifier?: string): {
27
34
  description?: string;
28
35
  sopInstanceUid?: string;
29
36
  annotation: import("packages/tools/dist/esm/types").Annotation;
@@ -6,6 +6,50 @@ import { toScoords } from '../helpers/toScoordType.js';
6
6
  import '@cornerstonejs/core';
7
7
 
8
8
  class BaseAdapter3D {
9
+ static registerType() {
10
+ let code = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
11
+ let type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "";
12
+ let count = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
13
+ let key = code;
14
+ if (type) {
15
+ key = `${key}${key.length ? "-" : ""}${type}`;
16
+ }
17
+ if (count) {
18
+ key = `${key}${key.length ? "-" : ""}${count}`;
19
+ }
20
+ MeasurementReport.registerAdapterTypes(this, key);
21
+ }
22
+ static getPointsCount(graphicItem) {
23
+ const is3DMeasurement = graphicItem.ValueType === "SCOORD3D";
24
+ const pointSize = is3DMeasurement ? 3 : 2;
25
+ return graphicItem.GraphicData.length / pointSize;
26
+ }
27
+ static getGraphicItems(measurementGroup, filter) {
28
+ const items = measurementGroup.ContentSequence.filter(group => group.ValueType === "SCOORD" || group.ValueType === "SCOORD3D");
29
+ return filter ? items.filter(filter) : items;
30
+ }
31
+ static getGraphicItem(measurementGroup) {
32
+ let offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
33
+ let type = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
34
+ const items = this.getGraphicItems(measurementGroup, type && (group => group.ValueType === type));
35
+ return items[offset];
36
+ }
37
+ static getGraphicCode(graphicItem) {
38
+ const {
39
+ ConceptNameCodeSequence: conceptNameItem
40
+ } = graphicItem;
41
+ const {
42
+ CodeValue: graphicValue,
43
+ CodingSchemeDesignator: graphicDesignator
44
+ } = conceptNameItem;
45
+ return `${graphicDesignator}:${graphicValue}`;
46
+ }
47
+ static getGraphicType(graphicItem) {
48
+ return graphicItem.GraphicType;
49
+ }
50
+ static isValidMeasurement(_measurementGroup) {
51
+ return false;
52
+ }
9
53
  static init(toolType, representation, options) {
10
54
  this.toolType = toolType;
11
55
  if (BaseAdapter3D.toolType) {
@@ -44,7 +88,7 @@ class BaseAdapter3D {
44
88
  }
45
89
  return trackingIdentifier.startsWith(this.trackingIdentifierTextValue);
46
90
  }
47
- static getMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, _imageToWorldCoords, metadata, trackingIdentifier) {
91
+ static getMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata, trackingIdentifier) {
48
92
  const {
49
93
  defaultState: state,
50
94
  ReferencedFrameNumber
@@ -16,10 +16,12 @@ class Bidirectional extends BaseAdapter3D {
16
16
  static getMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata) {
17
17
  const {
18
18
  state,
19
+ NUMGroup,
20
+ scoord,
19
21
  scoordArgs,
20
22
  referencedImageId,
21
23
  ReferencedFrameNumber
22
- } = MeasurementReport.getSetupMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata, Bidirectional.toolType);
24
+ } = MeasurementReport.getSetupMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata, this.toolType);
23
25
  const {
24
26
  ContentSequence
25
27
  } = MeasurementGroup;
@@ -28,8 +30,8 @@ class Bidirectional extends BaseAdapter3D {
28
30
  const longAxisScoordGroup = toArray(longAxisNUMGroup.ContentSequence).find(group => group.ValueType === "SCOORD3D" || group.ValueType === "SCOORD");
29
31
  const shortAxisScoordGroup = toArray(shortAxisNUMGroup.ContentSequence).find(group => group.ValueType === "SCOORD3D" || group.ValueType === "SCOORD");
30
32
  const worldCoords = [];
31
- worldCoords.push(...scoordToWorld(scoordArgs, longAxisScoordGroup.GraphicData));
32
- worldCoords.push(...scoordToWorld(scoordArgs, shortAxisScoordGroup.GraphicData));
33
+ worldCoords.push(...scoordToWorld(scoordArgs, longAxisScoordGroup));
34
+ worldCoords.push(...scoordToWorld(scoordArgs, shortAxisScoordGroup));
33
35
  state.annotation.data = {
34
36
  ...state.annotation.data,
35
37
  handles: {
@@ -1,6 +1,6 @@
1
1
  import BaseAdapter3D from "./BaseAdapter3D";
2
2
  declare class EllipticalROI extends BaseAdapter3D {
3
- static getMeasurementData(MeasurementGroup: any, sopInstanceUIDToImageIdMap: any, imageToWorldCoords: any, metadata: any): {
3
+ static getMeasurementData(MeasurementGroup: any, sopInstanceUIDToImageIdMap: any, metadata: any): {
4
4
  description?: string;
5
5
  sopInstanceUid?: string;
6
6
  annotation: import("packages/tools/dist/esm/types").Annotation;
@@ -9,7 +9,15 @@ declare class EllipticalROI extends BaseAdapter3D {
9
9
  };
10
10
  static getTID300RepresentationArguments(tool: any, is3DMeasurement?: boolean): {
11
11
  area: any;
12
- points: any[];
12
+ points: ({
13
+ x: any;
14
+ y: any;
15
+ z: any;
16
+ } | {
17
+ x: number;
18
+ y: number;
19
+ z?: undefined;
20
+ })[];
13
21
  trackingIdentifierTextValue: string;
14
22
  finding: any;
15
23
  findingSites: any;
@@ -1,60 +1,27 @@
1
- import { vec3 } from 'gl-matrix';
2
1
  import { utilities } from 'dcmjs';
3
- import { utilities as utilities$1 } from '@cornerstonejs/core';
4
2
  import MeasurementReport from './MeasurementReport.js';
5
3
  import BaseAdapter3D from './BaseAdapter3D.js';
4
+ import 'buffer';
5
+ import { toScoord } from '../helpers/toScoordType.js';
6
+ import '@cornerstonejs/core';
6
7
 
7
8
  var _EllipticalROI;
8
9
  const {
9
10
  Ellipse: TID300Ellipse
10
11
  } = utilities.TID300;
11
- const {
12
- worldToImageCoords
13
- } = utilities$1;
14
- const EPSILON = 1e-4;
15
12
  class EllipticalROI extends BaseAdapter3D {
16
- static getMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, imageToWorldCoords, metadata) {
13
+ static getMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata) {
17
14
  const {
18
15
  state,
19
16
  NUMGroup,
20
- scoord,
21
- scoordArgs,
22
17
  worldCoords,
23
18
  referencedImageId,
24
19
  ReferencedFrameNumber
25
20
  } = MeasurementReport.getSetupMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata, EllipticalROI.toolType);
26
- const [majorAxisStart, majorAxisEnd, minorAxisStart, minorAxisEnd] = worldCoords;
27
- const majorAxisVec = vec3.create();
28
- vec3.sub(majorAxisVec, majorAxisEnd, majorAxisStart);
29
- vec3.normalize(majorAxisVec, majorAxisVec);
30
- const minorAxisVec = vec3.create();
31
- vec3.sub(minorAxisVec, minorAxisEnd, minorAxisStart);
32
- vec3.normalize(minorAxisVec, minorAxisVec);
33
- const imagePlaneModule = metadata.get("imagePlaneModule", referencedImageId);
34
- if (!imagePlaneModule) {
35
- throw new Error("imageId does not have imagePlaneModule metadata");
36
- }
37
- const {
38
- columnCosines
39
- } = imagePlaneModule;
40
- const columnCosinesVec = vec3.fromValues(columnCosines[0], columnCosines[1], columnCosines[2]);
41
- const projectedMajorAxisOnColVec = vec3.dot(columnCosinesVec, majorAxisVec);
42
- const projectedMinorAxisOnColVec = vec3.dot(columnCosinesVec, minorAxisVec);
43
- const absoluteOfMajorDotProduct = Math.abs(projectedMajorAxisOnColVec);
44
- const absoluteOfMinorDotProduct = Math.abs(projectedMinorAxisOnColVec);
45
- let ellipsePoints = [];
46
- if (Math.abs(absoluteOfMajorDotProduct - 1) < EPSILON) {
47
- ellipsePoints = worldCoords;
48
- } else if (Math.abs(absoluteOfMinorDotProduct - 1) < EPSILON) {
49
- ellipsePoints = [worldCoords[2], worldCoords[3], worldCoords[0], worldCoords[1]];
50
- } else {
51
- console.warn("OBLIQUE ELLIPSE NOT YET SUPPORTED");
52
- return null;
53
- }
54
21
  state.annotation.data = {
55
22
  ...state.annotation.data,
56
23
  handles: {
57
- points: [...ellipsePoints],
24
+ points: worldCoords,
58
25
  activeHandleIndex: 0,
59
26
  textBox: {
60
27
  hasMoved: false
@@ -62,13 +29,11 @@ class EllipticalROI extends BaseAdapter3D {
62
29
  },
63
30
  frameNumber: ReferencedFrameNumber
64
31
  };
65
- if (referencedImageId) {
66
- state.annotation.data.cachedStats = {
67
- [`imageId:${referencedImageId}`]: {
68
- area: NUMGroup ? NUMGroup.MeasuredValueSequence.NumericValue : 0
69
- }
70
- };
71
- }
32
+ state.annotation.data.cachedStats = referencedImageId ? {
33
+ [`imageId:${referencedImageId}`]: {
34
+ area: NUMGroup ? NUMGroup.MeasuredValueSequence.NumericValue : 0
35
+ }
36
+ } : {};
72
37
  return state;
73
38
  }
74
39
  static getTID300RepresentationArguments(tool) {
@@ -87,62 +52,37 @@ class EllipticalROI extends BaseAdapter3D {
87
52
  const {
88
53
  referencedImageId
89
54
  } = metadata;
55
+ const scoordProps = {
56
+ is3DMeasurement,
57
+ referencedImageId
58
+ };
90
59
  let top, bottom, left, right;
91
60
  if (rotation == 90 || rotation == 270) {
92
- bottom = worldToImageCoords(referencedImageId, handles.points[2]);
93
- top = worldToImageCoords(referencedImageId, handles.points[3]);
94
- left = worldToImageCoords(referencedImageId, handles.points[0]);
95
- right = worldToImageCoords(referencedImageId, handles.points[1]);
61
+ bottom = handles.points[2];
62
+ top = handles.points[3];
63
+ left = handles.points[0];
64
+ right = handles.points[1];
96
65
  } else {
97
- top = worldToImageCoords(referencedImageId, handles.points[0]);
98
- bottom = worldToImageCoords(referencedImageId, handles.points[1]);
99
- left = worldToImageCoords(referencedImageId, handles.points[2]);
100
- right = worldToImageCoords(referencedImageId, handles.points[3]);
66
+ top = handles.points[0];
67
+ bottom = handles.points[1];
68
+ left = handles.points[2];
69
+ right = handles.points[3];
101
70
  }
102
- const topBottomLength = Math.abs(top.y - bottom.y);
103
- const leftRightLength = Math.abs(left.x - right.x);
71
+ const topBottomLength = Math.sqrt((top[0] - bottom[0]) ** 2 + (top[1] - bottom[1]) ** 2 + (top[2] - bottom[2]) ** 2);
72
+ const leftRightLength = Math.sqrt((left[0] - right[0]) ** 2 + (left[1] - right[1]) ** 2 + (left[2] - right[2]) ** 2);
104
73
  const points = [];
105
74
  if (topBottomLength > leftRightLength) {
106
- points.push({
107
- x: top[0],
108
- y: top[1]
109
- });
110
- points.push({
111
- x: bottom[0],
112
- y: bottom[1]
113
- });
114
- points.push({
115
- x: left[0],
116
- y: left[1]
117
- });
118
- points.push({
119
- x: right[0],
120
- y: right[1]
121
- });
75
+ points.push(top, bottom, left, right);
122
76
  } else {
123
- points.push({
124
- x: left[0],
125
- y: left[1]
126
- });
127
- points.push({
128
- x: right[0],
129
- y: right[1]
130
- });
131
- points.push({
132
- x: top[0],
133
- y: top[1]
134
- });
135
- points.push({
136
- x: bottom[0],
137
- y: bottom[1]
138
- });
77
+ points.push(left, right, top, bottom);
139
78
  }
140
79
  const {
141
80
  area
142
81
  } = cachedStats[`imageId:${referencedImageId}`] || {};
82
+ const convertedPoints = points.map(point => toScoord(scoordProps, point));
143
83
  return {
144
84
  area,
145
- points,
85
+ points: convertedPoints,
146
86
  trackingIdentifierTextValue: this.trackingIdentifierTextValue,
147
87
  finding,
148
88
  findingSites: findingSites || [],
@@ -3,7 +3,13 @@ export default class KeyImage extends Probe {
3
3
  static trackingSeriesIdentifier: string;
4
4
  static trackingPointIdentifier: string;
5
5
  static trackingSeriesPointIdentifier: string;
6
- static getMeasurementData(measurementGroup: any, sopInstanceUIDToImageIdMap: any, imageToWorldCoords: any, metadata: any, trackingIdentifier: any): any;
6
+ static getMeasurementData(measurementGroup: any, sopInstanceUIDToImageIdMap: any, metadata: any, trackingIdentifier: any): {
7
+ description?: string;
8
+ sopInstanceUid?: string;
9
+ annotation: import("packages/tools/dist/esm/types").Annotation;
10
+ finding?: unknown;
11
+ findingSites?: unknown;
12
+ };
7
13
  static getTID300RepresentationArguments(tool: any): {
8
14
  points: ({
9
15
  x: any;
@@ -6,8 +6,8 @@ const {
6
6
  Point: TID300Point
7
7
  } = utilities.TID300;
8
8
  class KeyImage extends Probe {
9
- static getMeasurementData(measurementGroup, sopInstanceUIDToImageIdMap, imageToWorldCoords, metadata, trackingIdentifier) {
10
- const baseData = super.getMeasurementData(measurementGroup, sopInstanceUIDToImageIdMap, imageToWorldCoords, metadata, trackingIdentifier);
9
+ static getMeasurementData(measurementGroup, sopInstanceUIDToImageIdMap, metadata, trackingIdentifier) {
10
+ const baseData = super.getMeasurementData(measurementGroup, sopInstanceUIDToImageIdMap, metadata, trackingIdentifier);
11
11
  const {
12
12
  data
13
13
  } = baseData.annotation;
@@ -50,11 +50,13 @@ export interface MeasurementAdapter {
50
50
  init(toolType: string, representation: any, options?: AdapterOptions): any;
51
51
  getMeasurementData(measurementGroup: any, sopInstanceUIDToImageIdMap: any, metadata: any, trackingIdentifier: string): any;
52
52
  isValidCornerstoneTrackingIdentifier(trackingIdentifier: string): boolean;
53
+ isValidMeasurement(measurementGroup: any): boolean;
53
54
  getTID300RepresentationArguments(tool: any, is3DMeasurement: any): Record<string, unknown>;
54
55
  }
55
56
  export default class MeasurementReport {
56
57
  static CORNERSTONE_3D_TAG: string;
57
58
  static measurementAdapterByToolType: Map<string, MeasurementAdapter>;
59
+ static measurementAdaptersByType: Map<string, MeasurementAdapter[]>;
58
60
  static measurementAdapterByTrackingIdentifier: Map<string, MeasurementAdapter>;
59
61
  static getTID300ContentItem(tool: any, ReferencedSOPSequence: any, toolClass: any, is3DMeasurement: any): any;
60
62
  static codeValueMatch: (group: any, code: any, oldCode?: any) => boolean;
@@ -161,5 +163,8 @@ export default class MeasurementReport {
161
163
  static registerTool(toolAdapter: MeasurementAdapter, replace?: boolean | ((original: any) => void)): void;
162
164
  static registerTrackingIdentifier(toolClass: any, ...trackingIdentifiers: string[]): void;
163
165
  static getAdapterForTrackingIdentifier(trackingIdentifier: string): MeasurementAdapter;
166
+ static getAdapterForCodeType(measurementGroup: any): MeasurementAdapter;
167
+ static registerAdapterTypes(adapter: any, ...types: any[]): void;
168
+ static getAdaptersForTypes(graphicCode: string, graphicType: string, pointCount: number): any[];
164
169
  }
165
170
  export {};
@@ -242,7 +242,9 @@ class MeasurementReport {
242
242
  const contentSequenceArr = toArray(ContentSequence);
243
243
  const findingGroup = contentSequenceArr.find(group => this.codeValueMatch(group, FINDING));
244
244
  const findingSiteGroups = contentSequenceArr.filter(group => this.codeValueMatch(group, FINDING_SITE, FINDING_SITE_OLD)) || [];
245
- const NUMGroup = contentSequenceArr.find(group => group.ValueType === "NUM");
245
+ const NUMGroup = contentSequenceArr.find(group => group.ValueType === "NUM") || {
246
+ ContentSequence: contentSequenceArr.filter(group => group.ValueType === "SCOORD" || group.ValueType === "SCOORD3D")
247
+ };
246
248
  const spatialGroup = this.processSpatialCoordinatesGroup({
247
249
  NUMGroup,
248
250
  sopInstanceUIDToImageIdMap,
@@ -390,7 +392,7 @@ class MeasurementReport {
390
392
  } = trackingIdentifierGroup;
391
393
  const trackingUniqueIdentifierGroup = measurementGroupContentSequence.find(contentItem => contentItem.ConceptNameCodeSequence.CodeMeaning === TRACKING_UNIQUE_IDENTIFIER);
392
394
  const trackingUniqueIdentifierValue = trackingUniqueIdentifierGroup?.UID;
393
- const toolAdapter = hooks?.getToolClass?.(measurementGroup, dataset, this.measurementAdapterByToolType) || this.getAdapterForTrackingIdentifier(trackingIdentifierValue);
395
+ const toolAdapter = hooks?.getToolClass?.(measurementGroup, dataset, this.measurementAdapterByToolType) || this.getAdapterForTrackingIdentifier(trackingIdentifierValue) || this.getAdapterForCodeType(measurementGroup);
394
396
  if (toolAdapter) {
395
397
  const measurement = toolAdapter.getMeasurementData(measurementGroup, sopInstanceUIDToImageIdMap, metadata, trackingIdentifierValue);
396
398
  measurement.TrackingUniqueIdentifier = trackingUniqueIdentifierValue;
@@ -439,10 +441,40 @@ class MeasurementReport {
439
441
  }
440
442
  }
441
443
  }
444
+ static getAdapterForCodeType(measurementGroup) {
445
+ for (const adapter of this.measurementAdapterByTrackingIdentifier.values()) {
446
+ if (adapter.isValidMeasurement(measurementGroup)) {
447
+ return adapter;
448
+ }
449
+ }
450
+ }
451
+ static registerAdapterTypes(adapter) {
452
+ for (var _len2 = arguments.length, types = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
453
+ types[_key2 - 1] = arguments[_key2];
454
+ }
455
+ for (const type of types) {
456
+ if (!this.measurementAdaptersByType.has(type)) {
457
+ this.measurementAdaptersByType.set(type, []);
458
+ }
459
+ const adapters = this.measurementAdaptersByType.get(type);
460
+ if (adapters.indexOf(adapter) === -1) {
461
+ adapters.push(adapter);
462
+ }
463
+ }
464
+ }
465
+ static getAdaptersForTypes(graphicCode, graphicType, pointCount) {
466
+ const adapters = [];
467
+ appendList(adapters, this.measurementAdaptersByType.get(`${graphicCode}-${graphicType}-${pointCount}`));
468
+ appendList(adapters, this.measurementAdaptersByType.get(`${graphicCode}-${graphicType}`));
469
+ appendList(adapters, this.measurementAdaptersByType.get(graphicCode));
470
+ appendList(adapters, this.measurementAdaptersByType.get(graphicType));
471
+ return adapters;
472
+ }
442
473
  }
443
474
  _MeasurementReport = MeasurementReport;
444
475
  _MeasurementReport.CORNERSTONE_3D_TAG = CORNERSTONE_3D_TAG;
445
476
  _MeasurementReport.measurementAdapterByToolType = new Map();
477
+ _MeasurementReport.measurementAdaptersByType = new Map();
446
478
  _MeasurementReport.measurementAdapterByTrackingIdentifier = new Map();
447
479
  _MeasurementReport.codeValueMatch = (group, code, oldCode) => {
448
480
  const {
@@ -465,5 +497,11 @@ _MeasurementReport.generateDerivationSourceDataset = instance => {
465
497
  ...seriesTags
466
498
  };
467
499
  };
500
+ function appendList(list, appendList) {
501
+ if (!appendList?.length) {
502
+ return;
503
+ }
504
+ list.push(...appendList);
505
+ }
468
506
 
469
507
  export { MeasurementReport as default };
@@ -1,16 +1,13 @@
1
1
  import BaseAdapter3D from "./BaseAdapter3D";
2
2
  declare class Probe extends BaseAdapter3D {
3
- static getMeasurementData(MeasurementGroup: any, sopInstanceUIDToImageIdMap: any, imageToWorldCoords: any, metadata: any, trackingIdentifier: any): any;
4
- static getMeasurementDataFromScoord({ state, defaultState, SCOORDGroup, imageToWorldCoords }: {
5
- state: any;
6
- defaultState: any;
7
- SCOORDGroup: any;
8
- imageToWorldCoords: any;
9
- }): any;
10
- static getMeasurementDataFromScoord3D({ state, SCOORD3DGroup }: {
11
- state: any;
12
- SCOORD3DGroup: any;
13
- }): any;
3
+ static isValidMeasurement(measurement: any): boolean;
4
+ static getMeasurementData(MeasurementGroup: any, sopInstanceUIDToImageIdMap: any, metadata: any, _trackingIdentifier: any): {
5
+ description?: string;
6
+ sopInstanceUid?: string;
7
+ annotation: import("packages/tools/dist/esm/types").Annotation;
8
+ finding?: unknown;
9
+ findingSites?: unknown;
10
+ };
14
11
  static getTID300RepresentationArguments(tool: any, is3DMeasurement?: boolean): {
15
12
  points: ({
16
13
  x: any;
@@ -10,79 +10,36 @@ const {
10
10
  Point: TID300Point
11
11
  } = utilities.TID300;
12
12
  class Probe extends BaseAdapter3D {
13
- static getMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, imageToWorldCoords, metadata, trackingIdentifier) {
14
- const state = super.getMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, imageToWorldCoords, metadata, trackingIdentifier);
15
- const {
16
- defaultState,
17
- SCOORDGroup,
18
- SCOORD3DGroup
19
- } = MeasurementReport.getSetupMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata, Probe.toolType);
20
- if (SCOORDGroup) {
21
- return this.getMeasurementDataFromScoord({
22
- state,
23
- defaultState,
24
- SCOORDGroup,
25
- imageToWorldCoords
26
- });
27
- } else if (SCOORD3DGroup) {
28
- return this.getMeasurementDataFromScoord3D({
29
- state,
30
- SCOORD3DGroup
31
- });
32
- } else {
33
- throw new Error("Can't get measurement data with missing SCOORD and SCOORD3D groups.");
34
- }
13
+ static isValidMeasurement(measurement) {
14
+ const graphicItem = this.getGraphicItem(measurement);
15
+ return this.getGraphicType(graphicItem) === "POINT" && this.getPointsCount(graphicItem) <= 2;
35
16
  }
36
- static getMeasurementDataFromScoord(_ref) {
37
- let {
38
- state,
39
- defaultState,
40
- SCOORDGroup,
41
- imageToWorldCoords
42
- } = _ref;
43
- const referencedImageId = defaultState.annotation.metadata.referencedImageId;
17
+ static getMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata, _trackingIdentifier) {
44
18
  const {
45
- GraphicData
46
- } = SCOORDGroup;
47
- const worldCoords = [];
48
- for (let i = 0; i < GraphicData.length; i += 2) {
49
- const point = imageToWorldCoords(referencedImageId, [GraphicData[i], GraphicData[i + 1]]);
50
- worldCoords.push(point);
51
- }
52
- state.annotation.data = {
53
- ...state.annotation.data,
54
- handles: {
55
- points: worldCoords,
56
- activeHandleIndex: null,
57
- textBox: {
58
- hasMoved: false
59
- }
60
- }
61
- };
62
- return state;
63
- }
64
- static getMeasurementDataFromScoord3D(_ref2) {
65
- let {
66
19
  state,
67
- SCOORD3DGroup
68
- } = _ref2;
69
- const {
70
- GraphicData
71
- } = SCOORD3DGroup;
72
- const worldCoords = [];
73
- for (let i = 0; i < GraphicData.length; i += 3) {
74
- const point = [GraphicData[i], GraphicData[i + 1], GraphicData[i + 2]];
75
- worldCoords.push(point);
76
- }
20
+ NUMGroup,
21
+ scoord,
22
+ scoordArgs,
23
+ worldCoords,
24
+ referencedImageId,
25
+ ReferencedFrameNumber
26
+ } = MeasurementReport.getSetupMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata, this.toolType);
27
+ const cachedStats = referencedImageId ? {
28
+ [`imageId:${referencedImageId}`]: {
29
+ length: NUMGroup ? NUMGroup.MeasuredValueSequence.NumericValue : 0
30
+ }
31
+ } : {};
77
32
  state.annotation.data = {
78
33
  ...state.annotation.data,
79
34
  handles: {
80
35
  points: worldCoords,
81
- activeHandleIndex: null,
36
+ activeHandleIndex: 0,
82
37
  textBox: {
83
38
  hasMoved: false
84
39
  }
85
- }
40
+ },
41
+ cachedStats,
42
+ frameNumber: ReferencedFrameNumber
86
43
  };
87
44
  return state;
88
45
  }
@@ -123,6 +80,8 @@ _Probe = Probe;
123
80
  (() => {
124
81
  _Probe.init("Probe", TID300Point);
125
82
  _Probe.registerLegacy();
83
+ _Probe.registerType("DCM:111030", "POINT", 1);
84
+ _Probe.registerType("DCM:111030", "POINT", 2);
126
85
  })();
127
86
 
128
87
  export { Probe as default };
@@ -1,43 +1,27 @@
1
1
  import BaseAdapter3D from "./BaseAdapter3D";
2
- declare class RectangleROI extends BaseAdapter3D {
3
- static getMeasurementData(MeasurementGroup: any, sopInstanceUIDToImageIdMap: any, imageToWorldCoords: any, metadata: any): any;
4
- static getMeasurementDataFromScoord({ defaultState, SCOORDGroup, imageToWorldCoords, NUMGroup, ReferencedFrameNumber }: {
5
- defaultState: any;
6
- SCOORDGroup: any;
7
- imageToWorldCoords: any;
8
- NUMGroup: any;
9
- ReferencedFrameNumber: any;
10
- }): any;
11
- static getMeasurementDataFromScoord3D({ SCOORD3DGroup, defaultState }: {
12
- SCOORD3DGroup: any;
13
- defaultState: any;
14
- }): any;
15
- static getTID300RepresentationArguments(tool: any, is3DMeasurement?: boolean): {
16
- points: any[];
17
- area: any;
18
- perimeter: any;
19
- trackingIdentifierTextValue: string;
20
- finding: any;
21
- findingSites: any;
22
- ReferencedFrameOfReferenceUID: any;
23
- use3DSpatialCoordinates: boolean;
24
- } | {
25
- points: any[];
26
- area: any;
27
- perimeter: any;
28
- trackingIdentifierTextValue: string;
29
- finding: any;
30
- findingSites: any;
31
- use3DSpatialCoordinates: boolean;
2
+ export declare class RectangleROI extends BaseAdapter3D {
3
+ static getMeasurementData(MeasurementGroup: any, sopInstanceUIDToImageIdMap: any, metadata: any): {
4
+ description?: string;
5
+ sopInstanceUid?: string;
6
+ annotation: import("packages/tools/dist/esm/types").Annotation;
7
+ finding?: unknown;
8
+ findingSites?: unknown;
32
9
  };
33
- static getTID300RepresentationArgumentsSCOORD3D(tool: any): {
34
- points: any[];
10
+ static getTID300RepresentationArguments(tool: any, is3DMeasurement?: boolean): {
11
+ points: ({
12
+ x: any;
13
+ y: any;
14
+ z: any;
15
+ } | {
16
+ x: number;
17
+ y: number;
18
+ z?: undefined;
19
+ })[];
35
20
  area: any;
36
21
  perimeter: any;
37
22
  trackingIdentifierTextValue: string;
38
23
  finding: any;
39
24
  findingSites: any;
40
- ReferencedFrameOfReferenceUID: any;
41
25
  use3DSpatialCoordinates: boolean;
42
26
  };
43
27
  }
@@ -1,5 +1,7 @@
1
1
  import { utilities } from 'dcmjs';
2
- import { utilities as utilities$1 } from '@cornerstonejs/core';
2
+ import 'buffer';
3
+ import { toScoords } from '../helpers/toScoordType.js';
4
+ import '@cornerstonejs/core';
3
5
  import MeasurementReport from './MeasurementReport.js';
4
6
  import BaseAdapter3D from './BaseAdapter3D.js';
5
7
 
@@ -7,96 +9,36 @@ var _RectangleROI;
7
9
  const {
8
10
  Polyline: TID300Polyline
9
11
  } = utilities.TID300;
10
- const {
11
- worldToImageCoords
12
- } = utilities$1;
13
12
  class RectangleROI extends BaseAdapter3D {
14
- static getMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, imageToWorldCoords, metadata) {
13
+ static getMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata) {
15
14
  const {
16
- defaultState,
15
+ state,
17
16
  NUMGroup,
18
- SCOORDGroup,
19
- SCOORD3DGroup,
17
+ scoord,
18
+ scoordArgs,
19
+ worldCoords,
20
+ referencedImageId,
20
21
  ReferencedFrameNumber
21
- } = MeasurementReport.getSetupMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata, RectangleROI.toolType);
22
- if (SCOORDGroup) {
23
- return this.getMeasurementDataFromScoord({
24
- defaultState,
25
- SCOORDGroup,
26
- imageToWorldCoords,
27
- NUMGroup,
28
- ReferencedFrameNumber
29
- });
30
- } else if (SCOORD3DGroup) {
31
- return this.getMeasurementDataFromScoord3D({
32
- SCOORD3DGroup,
33
- defaultState
34
- });
35
- } else {
36
- throw new Error("Can't get measurement data with missing SCOORD and SCOORD3D groups.");
37
- }
38
- }
39
- static getMeasurementDataFromScoord(_ref) {
40
- let {
41
- defaultState,
42
- SCOORDGroup,
43
- imageToWorldCoords,
44
- NUMGroup,
45
- ReferencedFrameNumber
46
- } = _ref;
47
- const referencedImageId = defaultState.annotation.metadata.referencedImageId;
48
- const {
49
- GraphicData
50
- } = SCOORDGroup;
51
- const worldCoords = [];
52
- for (let i = 0; i < GraphicData.length; i += 2) {
53
- const point = imageToWorldCoords(referencedImageId, [GraphicData[i], GraphicData[i + 1]]);
54
- worldCoords.push(point);
55
- }
56
- const state = defaultState;
22
+ } = MeasurementReport.getSetupMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata, this.toolType);
23
+ const cachedStats = referencedImageId ? {
24
+ [`imageId:${referencedImageId}`]: {
25
+ area: NUMGroup ? NUMGroup.MeasuredValueSequence.NumericValue : 0
26
+ }
27
+ } : {};
57
28
  state.annotation.data = {
29
+ ...state.annotation.data,
58
30
  handles: {
59
- points: [worldCoords[0], worldCoords[1], worldCoords[3], worldCoords[2]],
31
+ points: worldCoords,
60
32
  activeHandleIndex: 0,
61
33
  textBox: {
62
34
  hasMoved: false
63
35
  }
64
36
  },
65
- cachedStats: {
66
- [`imageId:${referencedImageId}`]: {
67
- area: NUMGroup ? NUMGroup.MeasuredValueSequence.NumericValue : null
68
- }
69
- },
37
+ cachedStats,
70
38
  frameNumber: ReferencedFrameNumber
71
39
  };
72
40
  return state;
73
41
  }
74
- static getMeasurementDataFromScoord3D(_ref2) {
75
- let {
76
- SCOORD3DGroup,
77
- defaultState
78
- } = _ref2;
79
- const {
80
- GraphicData
81
- } = SCOORD3DGroup;
82
- const worldCoords = [];
83
- for (let i = 0; i < GraphicData.length; i += 3) {
84
- const point = [GraphicData[i], GraphicData[i + 1], GraphicData[i + 2]];
85
- worldCoords.push(point);
86
- }
87
- const state = defaultState;
88
- state.annotation.data = {
89
- handles: {
90
- points: [worldCoords[0], worldCoords[1], worldCoords[3], worldCoords[2]],
91
- activeHandleIndex: 0,
92
- textBox: {
93
- hasMoved: false
94
- }
95
- },
96
- cachedStats: {}
97
- };
98
- return state;
99
- }
100
42
  static getTID300RepresentationArguments(tool) {
101
43
  let is3DMeasurement = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
102
44
  const {
@@ -106,46 +48,21 @@ class RectangleROI extends BaseAdapter3D {
106
48
  metadata
107
49
  } = tool;
108
50
  const {
109
- cachedStats = {},
110
- handles
111
- } = data;
51
+ polyline,
52
+ closed
53
+ } = data.contour;
112
54
  const {
113
55
  referencedImageId
114
56
  } = metadata;
115
- if (is3DMeasurement) {
116
- return this.getTID300RepresentationArgumentsSCOORD3D(tool);
117
- }
118
- const corners = handles.points.map(point => worldToImageCoords(referencedImageId, point));
119
- const {
120
- area,
121
- perimeter
122
- } = cachedStats;
123
- return {
124
- points: [corners[0], corners[1], corners[3], corners[2], corners[0]],
125
- area,
126
- perimeter,
127
- trackingIdentifierTextValue: this.trackingIdentifierTextValue,
128
- finding,
129
- findingSites: findingSites || [],
130
- use3DSpatialCoordinates: false
57
+ const scoordProps = {
58
+ is3DMeasurement,
59
+ referencedImageId
131
60
  };
132
- }
133
- static getTID300RepresentationArgumentsSCOORD3D(tool) {
134
- const {
135
- data,
136
- finding,
137
- findingSites,
138
- metadata
139
- } = tool;
140
- const {
141
- cachedStats = {},
142
- handles
143
- } = data;
144
- const corners = handles.points;
61
+ const corners = toScoords(scoordProps, polyline);
145
62
  const {
146
63
  area,
147
64
  perimeter
148
- } = cachedStats;
65
+ } = data.cachedStats[`imageId:${referencedImageId}`] || {};
149
66
  return {
150
67
  points: [corners[0], corners[1], corners[3], corners[2], corners[0]],
151
68
  area,
@@ -153,8 +70,7 @@ class RectangleROI extends BaseAdapter3D {
153
70
  trackingIdentifierTextValue: this.trackingIdentifierTextValue,
154
71
  finding,
155
72
  findingSites: findingSites || [],
156
- ReferencedFrameOfReferenceUID: metadata.FrameOfReferenceUID,
157
- use3DSpatialCoordinates: true
73
+ use3DSpatialCoordinates: false
158
74
  };
159
75
  }
160
76
  }
@@ -164,4 +80,4 @@ _RectangleROI = RectangleROI;
164
80
  _RectangleROI.registerLegacy();
165
81
  })();
166
82
 
167
- export { RectangleROI as default };
83
+ export { RectangleROI, RectangleROI as default };
@@ -1,6 +1,6 @@
1
1
  import BaseAdapter3D from "./BaseAdapter3D";
2
2
  declare class UltrasoundDirectional extends BaseAdapter3D {
3
- static getMeasurementData(MeasurementGroup: any, sopInstanceUIDToImageIdMap: any, imageToWorldCoords: any, metadata: any): {
3
+ static getMeasurementData(measurementGroup: any, sopInstanceUIDToImageIdMap: any, metadata: any): {
4
4
  description?: string;
5
5
  sopInstanceUid?: string;
6
6
  annotation: import("packages/tools/dist/esm/types").Annotation;
@@ -11,26 +11,16 @@ const {
11
11
  worldToImageCoords
12
12
  } = utilities$1;
13
13
  class UltrasoundDirectional extends BaseAdapter3D {
14
- static getMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, imageToWorldCoords, metadata) {
14
+ static getMeasurementData(measurementGroup, sopInstanceUIDToImageIdMap, metadata) {
15
15
  const {
16
- defaultState,
17
- SCOORDGroup,
16
+ state,
17
+ worldCoords,
18
18
  ReferencedFrameNumber
19
- } = MeasurementReport.getSetupMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata, UltrasoundDirectional.toolType);
20
- const referencedImageId = defaultState.annotation.metadata.referencedImageId;
21
- const {
22
- GraphicData
23
- } = SCOORDGroup;
24
- const worldCoords = [];
25
- for (let i = 0; i < GraphicData.length; i += 2) {
26
- const point = imageToWorldCoords(referencedImageId, [GraphicData[i], GraphicData[i + 1]]);
27
- worldCoords.push(point);
28
- }
29
- const state = defaultState;
19
+ } = MeasurementReport.getSetupMeasurementData(measurementGroup, sopInstanceUIDToImageIdMap, metadata, this.toolType);
30
20
  state.annotation.data = {
31
21
  ...state.annotation.data,
32
22
  handles: {
33
- points: [worldCoords[0], worldCoords[1]],
23
+ points: worldCoords,
34
24
  activeHandleIndex: 0,
35
25
  textBox: {
36
26
  hasMoved: false
@@ -7,7 +7,7 @@ import Angle from './Angle.js';
7
7
  import CobbAngle from './CobbAngle.js';
8
8
  import CircleROI from './CircleROI.js';
9
9
  import EllipticalROI from './EllipticalROI.js';
10
- import RectangleROI from './RectangleROI.js';
10
+ import { RectangleROI } from './RectangleROI.js';
11
11
  import Length from './Length.js';
12
12
  import PlanarFreehandROI from './PlanarFreehandROI.js';
13
13
  import Probe from './Probe.js';
@@ -1,3 +1,3 @@
1
- const toArray = x => Array.isArray(x) ? x : [x];
1
+ const toArray = x => Array.isArray(x) ? x : x !== undefined ? [x] : [];
2
2
 
3
3
  export { toArray };
@@ -22,7 +22,7 @@ declare const adaptersSR: {
22
22
  Length: typeof import("./Cornerstone3D/Length").default;
23
23
  CircleROI: typeof import("./Cornerstone3D/CircleROI").default;
24
24
  EllipticalROI: typeof import("./Cornerstone3D/EllipticalROI").default;
25
- RectangleROI: typeof import("./Cornerstone3D/RectangleROI").default;
25
+ RectangleROI: typeof import("./Cornerstone3D/RectangleROI").RectangleROI;
26
26
  ArrowAnnotate: typeof import("./Cornerstone3D/ArrowAnnotate").default;
27
27
  Probe: typeof import("./Cornerstone3D/Probe").default;
28
28
  PlanarFreehandROI: typeof import("./Cornerstone3D/PlanarFreehandROI").default;
@@ -1 +1 @@
1
- export declare const version = "3.31.3";
1
+ export declare const version = "3.31.5";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cornerstonejs/adapters",
3
- "version": "3.31.3",
3
+ "version": "3.31.5",
4
4
  "description": "Adapters for Cornerstone3D to/from formats including DICOM SR and others",
5
5
  "module": "./dist/esm/index.js",
6
6
  "types": "./dist/esm/index.d.ts",
@@ -90,8 +90,8 @@
90
90
  "ndarray": "^1.0.19"
91
91
  },
92
92
  "peerDependencies": {
93
- "@cornerstonejs/core": "^3.31.3",
94
- "@cornerstonejs/tools": "^3.31.3"
93
+ "@cornerstonejs/core": "^3.31.5",
94
+ "@cornerstonejs/tools": "^3.31.5"
95
95
  },
96
- "gitHead": "f68f1d6e2f9c4e18f81c51d5d728d8560d6f56cb"
96
+ "gitHead": "014f4c4cc2b973b200ec9af2e16783464b9a2a0d"
97
97
  }