Skip to content

Commit a4a0a2e

Browse files
fix: Multiple Slim issues regarding ANN visualization (#185)
* Improve logging * CR Updates: Update scoord3d conditionals around first/last point * Bump dcmjs * Disable measurements fetching * Lint * Add zoom to roi * Address issue where icc profile failed request would block image rendering * Address icc profile issues with dcm4chee * Fix getExtendedROI for annotation groups * Improve tile error messag * Remove resolution so we can have full image even without thumbnails * Lint * Add check for overview map while disposing * Update zoom to roi to use scale
1 parent beca218 commit a4a0a2e

File tree

6 files changed

+311
-175
lines changed

6 files changed

+311
-175
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@
8383
"@cornerstonejs/codec-openjph": "^2.4.5",
8484
"dicomweb-client": "^0.10.3",
8585
"colormap": "^2.3",
86-
"dcmjs": "^0.38.1",
86+
"dcmjs": "^0.41.0",
8787
"dicomicc": "^0.1",
8888
"image-type": "^4.1",
8989
"mathjs": "^11.2",

src/bulkAnnotations/getExtendedROI.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@ import dcmjs from 'dcmjs'
66
* @param {Object} options.feature - The feature object.
77
* @param {Object} options.roi - The ROI object.
88
* @param {Object} options.metadata - The metadata object.
9+
* @param {Object} options.annotationGroup - The annotation group object.
910
* @returns {Object} The extended ROI.
1011
*/
11-
const getExtendedROI = ({ feature, roi, metadata }) => {
12+
const getExtendedROI = ({ feature, roi, metadata, annotationGroup }) => {
1213
const annotationGroupUID = feature.get('annotationGroupUID')
1314
const annotationGroupMetadata = metadata.AnnotationGroupSequence.find(
1415
(item) => item.AnnotationGroupUID === annotationGroupUID
15-
)
16+
) || annotationGroup
1617

1718
if (annotationGroupUID == null || annotationGroupMetadata == null) {
1819
throw new Error(

src/pyramid.js

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,50 @@ import { are1DArraysAlmostEqual, are2DArraysAlmostEqual, _fetchBulkdata } from '
1212
*
1313
* @param {Array<metadata.VLWholeSlideMicroscopyImage>} pyramid - Metadata of
1414
* VL Whole Slide Microscopy Image instances
15-
* @param {object} client - dicom web client
15+
* @param {object} options - options object
16+
* @param {object} options.metadata - metadata of VL Whole Slide Microscopy Image instances
17+
* @param {object} options.client - dicom web client
18+
* @param {function} options.onError - function to call when an error occurs
1619
*
17-
* @returns {Promise<Array<TypedArray>>} image array with ICC profiles
20+
* @returns {Promise<Array<TypedArray>>} image array with ICC profiles (only for images with SamplesPerPixel === 3 and ICCProfile present)
1821
*
1922
* @private
2023
*/
21-
async function _getIccProfiles (metadata, client) {
22-
const profiles = []
23-
for (let i = 0; i < metadata.length; i++) {
24-
const image = metadata[i]
24+
async function _getIccProfiles ({ metadata, client, onError }) {
25+
const fetchPromises = metadata.map(image => {
2526
if (image.SamplesPerPixel === 3) {
26-
if (image.bulkdataReferences.OpticalPathSequence == null) {
27-
console.warn(
28-
`no ICC Profile was not found for image "${image.SOPInstanceUID}"`
29-
)
30-
continue
27+
let iccProfile = false
28+
const metadataItem = image.OpticalPathSequence[0]
29+
if (metadataItem.ICCProfile == null) {
30+
if ('OpticalPathSequence' in image.bulkdataReferences) {
31+
const bulkdataItem = image.bulkdataReferences.OpticalPathSequence[0]
32+
if ('ICCProfile' in bulkdataItem) {
33+
iccProfile = bulkdataItem.ICCProfile
34+
}
35+
}
36+
} else {
37+
iccProfile = metadataItem.ICCProfile
38+
}
39+
if (!iccProfile) {
40+
console.warn(`ICC Profile was not found for image "${image.SOPInstanceUID}"`)
41+
return null
42+
} else if ('BulkDataURI' in iccProfile) {
43+
console.debug(`fetching ICC Profile for image "${image.SOPInstanceUID}"`, iccProfile)
44+
return _fetchBulkdata({
45+
client,
46+
reference: iccProfile
47+
}).catch(onError)
48+
} else {
49+
return iccProfile
3150
}
32-
const bulkdata = await _fetchBulkdata({
33-
client,
34-
reference: (
35-
image
36-
.bulkdataReferences
37-
.OpticalPathSequence[0]
38-
.ICCProfile
39-
)
40-
})
41-
profiles.push(bulkdata)
4251
}
43-
}
44-
return profiles
52+
return null
53+
})
54+
const validPromises = fetchPromises.filter(Boolean)
55+
const results = await Promise.allSettled(validPromises)
56+
return results
57+
.filter(result => result.status === 'fulfilled' && result.value != null)
58+
.map(result => result.value)
4559
}
4660

4761
/**

src/scoord3d.js

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,6 @@ class Polyline extends Scoord3D {
208208
/**
209209
* POLYGON graphic denoted by multiple, ordered, coplaner (x, y, z) coordinates
210210
* that represent vertices of connected line segments.
211-
* The first and last coordinate should be identical.
212211
*
213212
* @class
214213
* @extends scoord3d.Scoord3D
@@ -234,12 +233,17 @@ class Polygon extends Scoord3D {
234233
if (options.coordinates.find(c => c.some(item => item < 0))) {
235234
console.warn('coordinates of Polygon contain negative numbers')
236235
}
237-
const n = options.coordinates.length
238-
if ((options.coordinates[0][0] !== options.coordinates[n - 1][0]) ||
239-
(options.coordinates[0][1] !== options.coordinates[n - 1][1]) ||
240-
(options.coordinates[0][2] !== options.coordinates[n - 1][2])) {
241-
throw new Error('First and last coordinate of Polygon must be the same.')
242-
}
236+
// Note: the POLYGON GraphicType value for ANN specifies that the
237+
// first and last points are implicitly joined, so the first point
238+
// should not be repeated at the end (unlike other uses in other IODs).
239+
// Reference: https://github.com/ImagingDataCommons/slim/issues/298#issuecomment-2959241315
240+
//
241+
// const n = options.coordinates.length
242+
// if ((options.coordinates[0][0] !== options.coordinates[n - 1][0]) ||
243+
// (options.coordinates[0][1] !== options.coordinates[n - 1][1]) ||
244+
// (options.coordinates[0][2] !== options.coordinates[n - 1][2])) {
245+
// throw new Error('First and last coordinate of Polygon must be the same.')
246+
// }
243247
super({
244248
coordinates: options.coordinates,
245249
frameOfReferenceUID: options.frameOfReferenceUID,

0 commit comments

Comments
 (0)