Compare commits
224
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
79d5c36bda | ||
|
|
f47a94317d | ||
|
|
45b68e841d | ||
|
|
d70aae3233 | ||
|
|
345b137bec | ||
|
|
9bcd1ae6f5 | ||
|
|
6b79dff5c1 | ||
|
|
88859f75d5 | ||
|
|
feed2304c1 | ||
|
|
08815909c7 | ||
|
|
ed2234a67c | ||
|
|
f7fe91c5f6 | ||
|
|
21ec6860f2 | ||
|
|
ac474b7f8f | ||
|
|
e485d68fd4 | ||
|
|
5089229ff9 | ||
|
|
df09176d63 | ||
|
|
bb603bd1f8 | ||
|
|
82a4a7d377 | ||
|
|
c27fa9c802 | ||
|
|
4cdfdae814 | ||
|
|
596340803a | ||
|
|
ff4e17f5c2 | ||
|
|
21e8a2bd0b | ||
|
|
2a442e30eb | ||
|
|
8e8a66bd29 | ||
|
|
b3a0faf5f5 | ||
|
|
a2a0090eeb | ||
|
|
ea552027c5 | ||
|
|
0eac386a31 | ||
|
|
40b590d75a | ||
|
|
01df1763ce | ||
|
|
5bba98ed84 | ||
|
|
16785936d9 | ||
|
|
3deb73d642 | ||
|
|
ef46b5a704 | ||
|
|
ed2bf23cd2 | ||
|
|
2ff2f3f34d | ||
|
|
a47aeb8bd7 | ||
|
|
94f40192f5 | ||
|
|
1c43aa791a | ||
|
|
e4a116b074 | ||
|
|
2460d28afc | ||
|
|
4a958b8989 | ||
|
|
31b837fa90 | ||
|
|
9bb00d71fa | ||
|
|
40bbe33a9d | ||
|
|
911d672835 | ||
|
|
9c553fded4 | ||
|
|
144dd39393 | ||
|
|
df2f50748e | ||
|
|
83a1523408 | ||
|
|
5a62a983e5 | ||
|
|
d00a86b022 | ||
|
|
710a2dca72 | ||
|
|
9100b1f02e | ||
|
|
0049f4c030 | ||
|
|
b5cdf88a57 | ||
|
|
c793df727b | ||
|
|
1456a493d6 | ||
|
|
7c551f5043 | ||
|
|
0b2c2a235f | ||
|
|
b1efe40aa1 | ||
|
|
a8a0bdb2df | ||
|
|
6878c1a264 | ||
|
|
d181eb4fdc | ||
|
|
fd809e4a0b | ||
|
|
4c29670d76 | ||
|
|
f58725ce40 | ||
|
|
5a1cb842f0 | ||
|
|
c5bd79552a | ||
|
|
61bf22c6f8 | ||
|
|
3d98548072 | ||
|
|
bf9770a55c | ||
|
|
2049c0936c | ||
|
|
7d5607073d | ||
|
|
1b6910bf76 | ||
|
|
98650302c7 | ||
|
|
bf846c94c3 | ||
|
|
b5dc9047ba | ||
|
|
636d8b0458 | ||
|
|
e8858f3eb5 | ||
|
|
eb7c950d7e | ||
|
|
c6214d66b9 | ||
|
|
0eb502aaf0 | ||
|
|
44a5a24d4f | ||
|
|
b0bf5dc780 | ||
|
|
5915fada83 | ||
|
|
2fa335c6d9 | ||
|
|
de4ad88a09 | ||
|
|
6ca13c0a4c | ||
|
|
0177b625ba | ||
|
|
c4064acfbc | ||
|
|
7a05d169ef | ||
|
|
13d0c883f8 | ||
|
|
c45f60dce2 | ||
|
|
7bb2713c5c | ||
|
|
97cb1f94e1 | ||
|
|
f99645f3a1 | ||
|
|
ae16c7f972 | ||
|
|
9c6e1cd305 | ||
|
|
7f0ca857fa | ||
|
|
920256d3a4 | ||
|
|
e1f55e65f2 | ||
|
|
d1c07d90f0 | ||
|
|
b1a04ecac3 | ||
|
|
f707b4ebc9 | ||
|
|
805c53270f | ||
|
|
d14a8f0199 | ||
|
|
5a5c4f58af | ||
|
|
6e5d8b691e | ||
|
|
59576d695d | ||
|
|
78d4bea04d | ||
|
|
806c2f4b36 | ||
|
|
6651008fbb | ||
|
|
74c98b6e9f | ||
|
|
ecee25b1d5 | ||
|
|
f1a67647ae | ||
|
|
4f9a00f872 | ||
|
|
7673a887e4 | ||
|
|
924affa7b5 | ||
|
|
abac6f583e | ||
|
|
36ba20d6e8 | ||
|
|
9d1884d7d8 | ||
|
|
622f18bd3e | ||
|
|
8b6256e76f | ||
|
|
c4ff2c2f09 | ||
|
|
1be5613946 | ||
|
|
6edb1c1e4c | ||
|
|
404b0a5d53 | ||
|
|
786898fd63 | ||
|
|
dfa851600c | ||
|
|
00e751933a | ||
|
|
c4e22c251f | ||
|
|
3cf4b6dea5 | ||
|
|
8c8924af37 | ||
|
|
04121e3713 | ||
|
|
d1eef6dbdb | ||
|
|
d83beb7c62 | ||
|
|
7867b29742 | ||
|
|
4a6f1bd407 | ||
|
|
b694228dd5 | ||
|
|
013068bcb0 | ||
|
|
3fbc23b04c | ||
|
|
323401418e | ||
|
|
fc438e90ae | ||
|
|
9b7f38467b | ||
|
|
fd1251f751 | ||
|
|
14793493a4 | ||
|
|
73d8848707 | ||
|
|
43b1c17209 | ||
|
|
5b513fd30e | ||
|
|
26c9567c38 | ||
|
|
8bbcd0e692 | ||
|
|
8c2f495405 | ||
|
|
e1e1e60b7d | ||
|
|
8af1046803 | ||
|
|
4bbba871f5 | ||
|
|
73e804c311 | ||
|
|
442f99d5eb | ||
|
|
9575a6f54c | ||
|
|
dc345d1875 | ||
|
|
bf252bcec2 | ||
|
|
1a68c06c3b | ||
|
|
a2361fa615 | ||
|
|
ee67bcc0f5 | ||
|
|
f9f16bc69f | ||
|
|
a29f5bc9d3 | ||
|
|
b23eeff937 | ||
|
|
09ff293f5f | ||
|
|
71a30dc9f2 | ||
|
|
330e11c7ff | ||
|
|
c73a403cdc | ||
|
|
5b3b6eed16 | ||
|
|
2a15ef0e44 | ||
|
|
db395852b6 | ||
|
|
423ba7c269 | ||
|
|
cafba997bf | ||
|
|
dd6d9768bb | ||
|
|
2145b42920 | ||
|
|
a5ad1cc02a | ||
|
|
d98439fe7f | ||
|
|
3bbbcea0d7 | ||
|
|
6e993511b7 | ||
|
|
eec9c33b76 | ||
|
|
c31c7f8e79 | ||
|
|
a7125f9385 | ||
|
|
49514aedfe | ||
|
|
43c882ac87 | ||
|
|
912b3c7c53 | ||
|
|
d9258eca70 | ||
|
|
fa599d05fb | ||
|
|
5f8325e338 | ||
|
|
93d798db99 | ||
|
|
33f1259408 | ||
|
|
c54658a320 | ||
|
|
55002fbd71 | ||
|
|
3f9ee1451b | ||
|
|
70ea13ec1f | ||
|
|
157b88c909 | ||
|
|
75c3f94177 | ||
|
|
6874d5f0b9 | ||
|
|
a3f2a1a7b0 | ||
|
|
8067f0c62c | ||
|
|
a894b6ffc5 | ||
|
|
c3a5847dcd | ||
|
|
132938bbe0 | ||
|
|
5ba63bd010 | ||
|
|
7c57f67844 | ||
|
|
dc929d3df5 | ||
|
|
5a3af83168 | ||
|
|
a9a6ad50ea | ||
|
|
f8455056cd | ||
|
|
f9c3d510d3 | ||
|
|
52f34c64d0 | ||
|
|
7d87766ac4 | ||
|
|
820bb83b70 | ||
|
|
0a42d573bb | ||
|
|
f9f33f74c1 | ||
|
|
6a5fe59136 | ||
|
|
4911e4796c | ||
|
|
349c503f04 | ||
|
|
a6a6aed361 | ||
|
|
40673f64b3 |
No files matched your search
@@ -13,7 +13,7 @@ version: 2.1
|
||||
##
|
||||
orbs:
|
||||
codecov: codecov/codecov@1.0.5
|
||||
cypress: cypress-io/cypress@3.1.4
|
||||
cypress: cypress-io/cypress@3.2.1
|
||||
|
||||
executors:
|
||||
cypress-custom:
|
||||
|
||||
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* This script uses nodejs to generate a JSON file from a DICOM study folder.
|
||||
* You need to have dcmjs installed in your project.
|
||||
* The JSON file can be used to load the study into the OHIF Viewer. You can get more detail
|
||||
* in the DICOM JSON Data source on docs.ohif.org
|
||||
*
|
||||
* Usage: node dicomStudyToJSONLaunch.js <studyFolder> <urlPrefix> <outputJSONPath>
|
||||
*
|
||||
* params:
|
||||
* - studyFolder: path to the study folder
|
||||
* - urlPrefix: prefix to the url that will be used to load the study into the viewer. For instance
|
||||
* we use https://ohif-assets.s3.us-east-2.amazonaws.com/dicom-json/data as the urlPrefix for the
|
||||
* example since the data is hosted on S3 and each study is in a folder. So the url in the generated
|
||||
* json file for the first instance of the first series of the first study will be
|
||||
* dicomweb:https://ohif-assets.s3.us-east-2.amazonaws.com/dicom-json/data/Series1/Instance1
|
||||
* - outputJSONPath: path to the output JSON file
|
||||
*/
|
||||
const dcmjs = require('dcmjs');
|
||||
const path = require('path');
|
||||
const fs = require('fs').promises;
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
const [studyDirectory, urlPrefix, outputPath] = args;
|
||||
|
||||
if (args.length !== 3) {
|
||||
console.error('Usage: node dicomStudyToJSONLaunch.js <studyFolder> <urlPrefix> <outputJSONPath>');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const model = {
|
||||
studies: [],
|
||||
};
|
||||
|
||||
async function convertDICOMToJSON(studyDirectory, urlPrefix, outputPath) {
|
||||
try {
|
||||
const files = await recursiveReadDir(studyDirectory);
|
||||
console.debug('Processing...');
|
||||
|
||||
for (const file of files) {
|
||||
if (!file.includes('.DS_Store') && !file.includes('.xml')) {
|
||||
const arrayBuffer = await fs.readFile(file);
|
||||
const dicomDict = dcmjs.data.DicomMessage.readFile(arrayBuffer.buffer);
|
||||
const instance = dcmjs.data.DicomMetaDictionary.naturalizeDataset(dicomDict.dict);
|
||||
|
||||
instance.fileLocation = createImageId(file, urlPrefix, studyDirectory);
|
||||
processInstance(instance);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Successfully loaded data');
|
||||
|
||||
model.studies.forEach(study => {
|
||||
study.NumInstances = findInstancesNumber(study);
|
||||
study.Modalities = findModalities(study).join('/');
|
||||
});
|
||||
|
||||
await fs.writeFile(outputPath, JSON.stringify(model, null, 2));
|
||||
console.log('JSON saved');
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function recursiveReadDir(dir) {
|
||||
let results = [];
|
||||
const list = await fs.readdir(dir);
|
||||
for (const file of list) {
|
||||
const filePath = path.resolve(dir, file);
|
||||
const stat = await fs.stat(filePath);
|
||||
if (stat.isDirectory()) {
|
||||
const res = await recursiveReadDir(filePath);
|
||||
results = results.concat(res);
|
||||
} else {
|
||||
results.push(filePath);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
function createImageId(fileLocation, urlPrefix, studyDirectory) {
|
||||
const relativePath = path.relative(studyDirectory, fileLocation);
|
||||
const normalizedPath = path.normalize(relativePath).replace(/\\/g, '/');
|
||||
return `dicomweb:${urlPrefix}${normalizedPath}`;
|
||||
}
|
||||
|
||||
function processInstance(instance) {
|
||||
const { StudyInstanceUID, SeriesInstanceUID } = instance;
|
||||
let study = getStudy(StudyInstanceUID);
|
||||
|
||||
if (!study) {
|
||||
study = createStudyMetadata(StudyInstanceUID, instance);
|
||||
model.studies.push(study);
|
||||
}
|
||||
|
||||
let series = getSeries(StudyInstanceUID, SeriesInstanceUID);
|
||||
|
||||
if (!series) {
|
||||
series = createSeriesMetadata(instance);
|
||||
study.series.push(series);
|
||||
}
|
||||
|
||||
const instanceMetaData =
|
||||
instance.NumberOfFrames > 1
|
||||
? createInstanceMetaDataMultiFrame(instance)
|
||||
: createInstanceMetaData(instance);
|
||||
|
||||
series.instances.push(...[].concat(instanceMetaData));
|
||||
}
|
||||
|
||||
function getStudy(StudyInstanceUID) {
|
||||
return model.studies.find(study => study.StudyInstanceUID === StudyInstanceUID);
|
||||
}
|
||||
|
||||
function getSeries(StudyInstanceUID, SeriesInstanceUID) {
|
||||
const study = getStudy(StudyInstanceUID);
|
||||
return study
|
||||
? study.series.find(series => series.SeriesInstanceUID === SeriesInstanceUID)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
const findInstancesNumber = study => {
|
||||
let numInstances = 0;
|
||||
study.series.forEach(aSeries => {
|
||||
numInstances = numInstances + aSeries.instances.length;
|
||||
});
|
||||
return numInstances;
|
||||
};
|
||||
|
||||
const findModalities = study => {
|
||||
let modalities = new Set();
|
||||
study.series.forEach(aSeries => {
|
||||
modalities.add(aSeries.Modality);
|
||||
});
|
||||
return Array.from(modalities);
|
||||
};
|
||||
|
||||
function createStudyMetadata(StudyInstanceUID, instance) {
|
||||
return {
|
||||
StudyInstanceUID,
|
||||
StudyDescription: instance.StudyDescription,
|
||||
StudyDate: instance.StudyDate,
|
||||
StudyTime: instance.StudyTime,
|
||||
PatientName: instance.PatientName,
|
||||
PatientID: instance.PatientID || '1234', // this is critical to have
|
||||
AccessionNumber: instance.AccessionNumber,
|
||||
PatientAge: instance.PatientAge,
|
||||
PatientSex: instance.PatientSex,
|
||||
PatientWeight: instance.PatientWeight,
|
||||
series: [],
|
||||
};
|
||||
}
|
||||
function createSeriesMetadata(instance) {
|
||||
return {
|
||||
SeriesInstanceUID: instance.SeriesInstanceUID,
|
||||
SeriesDescription: instance.SeriesDescription,
|
||||
SeriesNumber: instance.SeriesNumber,
|
||||
SeriesTime: instance.SeriesTime,
|
||||
Modality: instance.Modality,
|
||||
SliceThickness: instance.SliceThickness,
|
||||
instances: [],
|
||||
};
|
||||
}
|
||||
function commonMetaData(instance) {
|
||||
return {
|
||||
Columns: instance.Columns,
|
||||
Rows: instance.Rows,
|
||||
InstanceNumber: instance.InstanceNumber,
|
||||
SOPClassUID: instance.SOPClassUID,
|
||||
AcquisitionNumber: instance.AcquisitionNumber,
|
||||
PhotometricInterpretation: instance.PhotometricInterpretation,
|
||||
BitsAllocated: instance.BitsAllocated,
|
||||
BitsStored: instance.BitsStored,
|
||||
PixelRepresentation: instance.PixelRepresentation,
|
||||
SamplesPerPixel: instance.SamplesPerPixel,
|
||||
PixelSpacing: instance.PixelSpacing,
|
||||
HighBit: instance.HighBit,
|
||||
ImageOrientationPatient: instance.ImageOrientationPatient,
|
||||
ImagePositionPatient: instance.ImagePositionPatient,
|
||||
FrameOfReferenceUID: instance.FrameOfReferenceUID,
|
||||
ImageType: instance.ImageType,
|
||||
Modality: instance.Modality,
|
||||
SOPInstanceUID: instance.SOPInstanceUID,
|
||||
SeriesInstanceUID: instance.SeriesInstanceUID,
|
||||
StudyInstanceUID: instance.StudyInstanceUID,
|
||||
WindowCenter: instance.WindowCenter,
|
||||
WindowWidth: instance.WindowWidth,
|
||||
RescaleIntercept: instance.RescaleIntercept,
|
||||
RescaleSlope: instance.RescaleSlope,
|
||||
};
|
||||
}
|
||||
|
||||
function conditionalMetaData(instance) {
|
||||
return {
|
||||
...(instance.ConceptNameCodeSequence && {
|
||||
ConceptNameCodeSequence: instance.ConceptNameCodeSequence,
|
||||
}),
|
||||
...(instance.SeriesDate && { SeriesDate: instance.SeriesDate }),
|
||||
...(instance.ReferencedSeriesSequence && {
|
||||
ReferencedSeriesSequence: instance.ReferencedSeriesSequence,
|
||||
}),
|
||||
...(instance.SharedFunctionalGroupsSequence && {
|
||||
SharedFunctionalGroupsSequence: instance.SharedFunctionalGroupsSequence,
|
||||
}),
|
||||
...(instance.PerFrameFunctionalGroupsSequence && {
|
||||
PerFrameFunctionalGroupsSequence: instance.PerFrameFunctionalGroupsSequence,
|
||||
}),
|
||||
...(instance.ContentSequence && { ContentSequence: instance.ContentSequence }),
|
||||
...(instance.ContentTemplateSequence && {
|
||||
ContentTemplateSequence: instance.ContentTemplateSequence,
|
||||
}),
|
||||
...(instance.CurrentRequestedProcedureEvidenceSequence && {
|
||||
CurrentRequestedProcedureEvidenceSequence: instance.CurrentRequestedProcedureEvidenceSequence,
|
||||
}),
|
||||
...(instance.CodingSchemeIdentificationSequence && {
|
||||
CodingSchemeIdentificationSequence: instance.CodingSchemeIdentificationSequence,
|
||||
}),
|
||||
...(instance.RadiopharmaceuticalInformationSequence && {
|
||||
RadiopharmaceuticalInformationSequence: instance.RadiopharmaceuticalInformationSequence,
|
||||
}),
|
||||
...(instance.ROIContourSequence && {
|
||||
ROIContourSequence: instance.ROIContourSequence,
|
||||
}),
|
||||
...(instance.StructureSetROISequence && {
|
||||
StructureSetROISequence: instance.StructureSetROISequence,
|
||||
}),
|
||||
...(instance.ReferencedFrameOfReferenceSequence && {
|
||||
ReferencedFrameOfReferenceSequence: instance.ReferencedFrameOfReferenceSequence,
|
||||
}),
|
||||
...(instance.CorrectedImage && { CorrectedImage: instance.CorrectedImage }),
|
||||
...(instance.Units && { Units: instance.Units }),
|
||||
...(instance.DecayCorrection && { DecayCorrection: instance.DecayCorrection }),
|
||||
...(instance.AcquisitionDate && { AcquisitionDate: instance.AcquisitionDate }),
|
||||
...(instance.AcquisitionTime && { AcquisitionTime: instance.AcquisitionTime }),
|
||||
...(instance.PatientWeight && { PatientWeight: instance.PatientWeight }),
|
||||
...(instance.NumberOfFrames && { NumberOfFrames: instance.NumberOfFrames }),
|
||||
...(instance.FrameTime && { FrameTime: instance.FrameTime }),
|
||||
...(instance.EncapsulatedDocument && { EncapsulatedDocument: instance.EncapsulatedDocument }),
|
||||
...(instance.SequenceOfUltrasoundRegions && {
|
||||
SequenceOfUltrasoundRegions: instance.SequenceOfUltrasoundRegions,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
function createInstanceMetaData(instance) {
|
||||
const metadata = {
|
||||
...commonMetaData(instance),
|
||||
...conditionalMetaData(instance),
|
||||
};
|
||||
return { metadata, url: instance.fileLocation };
|
||||
}
|
||||
|
||||
function createInstanceMetaDataMultiFrame(instance) {
|
||||
const instances = [];
|
||||
const commonData = commonMetaData(instance);
|
||||
const conditionalData = conditionalMetaData(instance);
|
||||
|
||||
for (let i = 1; i <= instance.NumberOfFrames; i++) {
|
||||
const metadata = { ...commonData, ...conditionalData };
|
||||
const result = { metadata, url: instance.fileLocation + `?frame=${i}` };
|
||||
instances.push(result);
|
||||
}
|
||||
return instances;
|
||||
}
|
||||
|
||||
convertDICOMToJSON(studyDirectory, urlPrefix, outputPath);
|
||||
Vendored
+1
-1
@@ -31,6 +31,6 @@
|
||||
"prettier.endOfLine": "lf",
|
||||
"workbench.colorCustomizations": {},
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
"source.fixAll.eslint": "explicit"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
const stylusToJavaScript = {
|
||||
test: /\.styl$/,
|
||||
use: [
|
||||
{ loader: 'style-loader' }, // 3. Style nodes from JS Strings
|
||||
{ loader: 'css-loader' }, // 2. CSS to CommonJS
|
||||
{ loader: 'stylus-loader' }, // 1. Stylus to CSS
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = stylusToJavaScript;
|
||||
@@ -18,6 +18,7 @@ const loadShadersRule = require('./rules/loadShaders.js');
|
||||
const loadWebWorkersRule = require('./rules/loadWebWorkers.js');
|
||||
const transpileJavaScriptRule = require('./rules/transpileJavaScript.js');
|
||||
const cssToJavaScript = require('./rules/cssToJavaScript.js');
|
||||
const stylusToJavaScript = require('./rules/stylusToJavaScript.js');
|
||||
|
||||
// ~~ ENV VARS
|
||||
const NODE_ENV = process.env.NODE_ENV;
|
||||
@@ -112,6 +113,9 @@ module.exports = (env, argv, { SRC_DIR, ENTRY }) => {
|
||||
},
|
||||
},
|
||||
cssToJavaScript,
|
||||
// Note: Only uncomment the following if you are using the old style of stylus in v2
|
||||
// Also you need to uncomment this platform/app/.webpack/rules/extractStyleChunks.js
|
||||
// stylusToJavaScript,
|
||||
{
|
||||
test: /\.wasm/,
|
||||
type: 'asset/resource',
|
||||
|
||||
+784
@@ -3,6 +3,790 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.8.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.62...v3.8.0-beta.63) (2024-03-25)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **worklist:** new investigational use text ([#3999](https://github.com/OHIF/Viewers/issues/3999)) ([45b68e8](https://github.com/OHIF/Viewers/commit/45b68e841dcb9e28a2ea991c37ee7ac4a8c5b71e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.61...v3.8.0-beta.62) (2024-03-19)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **worklist:** New worklist buttons and tooltips ([#3989](https://github.com/OHIF/Viewers/issues/3989)) ([9bcd1ae](https://github.com/OHIF/Viewers/commit/9bcd1ae6f51d61786cc1e99624f396b56a47cd69))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.60...v3.8.0-beta.61) (2024-03-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **SR display:** and the token based navigation ([#3995](https://github.com/OHIF/Viewers/issues/3995)) ([feed230](https://github.com/OHIF/Viewers/commit/feed2304c124dc2facc7a7371ed9851548c223c5))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.59...v3.8.0-beta.60) (2024-03-15)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **delete measurement:** icon for measurement table ([#3775](https://github.com/OHIF/Viewers/issues/3775)) ([f7fe91c](https://github.com/OHIF/Viewers/commit/f7fe91c5f6c4f05f3f3f5f640d3a119bd40a5870))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.58...v3.8.0-beta.59) (2024-03-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cli:** mode creation template ([#3876](https://github.com/OHIF/Viewers/issues/3876)) ([#3981](https://github.com/OHIF/Viewers/issues/3981)) ([e485d68](https://github.com/OHIF/Viewers/commit/e485d68fd4619ce7187113cbe59e47f9523dbcc8))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.57...v3.8.0-beta.58) (2024-03-05)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.56...v3.8.0-beta.57) (2024-02-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **docs:** Minor typos in hpModule.md ([#3962](https://github.com/OHIF/Viewers/issues/3962)) ([4cdfdae](https://github.com/OHIF/Viewers/commit/4cdfdae8149166cf9dc91a55c0d7f2a224e55d8f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.55...v3.8.0-beta.56) (2024-02-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **demo:** Deploy issue ([#3951](https://github.com/OHIF/Viewers/issues/3951)) ([21e8a2b](https://github.com/OHIF/Viewers/commit/21e8a2bd0b7cc72f90a31e472d285d761be15d30))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.54...v3.8.0-beta.55) (2024-02-21)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **resize:** Optimize resizing process and maintain zoom level ([#3889](https://github.com/OHIF/Viewers/issues/3889)) ([b3a0faf](https://github.com/OHIF/Viewers/commit/b3a0faf5f5f0a1993b2b017eb4cc1216164ea2c6))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.53...v3.8.0-beta.54) (2024-02-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **errorboundary:** format stack trace properly ([#3931](https://github.com/OHIF/Viewers/issues/3931)) ([0eac386](https://github.com/OHIF/Viewers/commit/0eac386a31a5d6965536360aa65a44769c1a5740))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.52...v3.8.0-beta.53) (2024-02-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 🐛 Sort merge results based on default data source (input) ([#3903](https://github.com/OHIF/Viewers/issues/3903)) ([5bba98e](https://github.com/OHIF/Viewers/commit/5bba98ed848bdf46b5ba4fc4708527cced3308b5))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.51...v3.8.0-beta.52) (2024-01-22)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.50...v3.8.0-beta.51) (2024-01-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* catch errors in getPTImageIdInstanceMetadata ([#3897](https://github.com/OHIF/Viewers/issues/3897)) ([a47aeb8](https://github.com/OHIF/Viewers/commit/a47aeb8bd729dcb8d2cfc13b27a31b0dd88f11ad))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.49...v3.8.0-beta.50) (2024-01-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **viewport-sync:** remember synced viewports bw stack and volume and RENAME StackImageSync to ImageSliceSync ([#3849](https://github.com/OHIF/Viewers/issues/3849)) ([e4a116b](https://github.com/OHIF/Viewers/commit/e4a116b074fcb85c8cbcc9db44fdec565f3386db))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.48...v3.8.0-beta.49) (2024-01-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* is same orientaiton ([#3905](https://github.com/OHIF/Viewers/issues/3905)) ([31b837f](https://github.com/OHIF/Viewers/commit/31b837fa90f631d4984482c6e952373fbb8bdbfc))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.47...v3.8.0-beta.48) (2024-01-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 🐛 Check merge key for merge data source ([#3901](https://github.com/OHIF/Viewers/issues/3901)) ([911d672](https://github.com/OHIF/Viewers/commit/911d67283536b2fe7930948f2819ea0ad66e2a32))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.46...v3.8.0-beta.47) (2024-01-12)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.45...v3.8.0-beta.46) (2024-01-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Update CS3D to fix second render ([#3892](https://github.com/OHIF/Viewers/issues/3892)) ([d00a86b](https://github.com/OHIF/Viewers/commit/d00a86b022742ea089d246d06cfd691f43b64412))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.44...v3.8.0-beta.45) (2024-01-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **hp:** enable OHIF to run with partial metadata for large studies at the cost of less effective hanging protocol ([#3804](https://github.com/OHIF/Viewers/issues/3804)) ([0049f4c](https://github.com/OHIF/Viewers/commit/0049f4c0303f0b6ea995972326fc8784259f5a47))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.43...v3.8.0-beta.44) (2024-01-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **transferSyntax:** prefer server transcoded transfer syntax for all images ([#3883](https://github.com/OHIF/Viewers/issues/3883)) ([1456a49](https://github.com/OHIF/Viewers/commit/1456a493d66c90c787b022256c9f2846afb115fc))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.42...v3.8.0-beta.43) (2024-01-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** upgrade cs3d to fix various segmentation bugs ([#3885](https://github.com/OHIF/Viewers/issues/3885)) ([b1efe40](https://github.com/OHIF/Viewers/commit/b1efe40aa146e4052cc47b3f774cabbb47a8d1a6))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.41...v3.8.0-beta.42) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.40...v3.8.0-beta.41) (2024-01-08)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add on mode init hook ([#3882](https://github.com/OHIF/Viewers/issues/3882)) ([f58725c](https://github.com/OHIF/Viewers/commit/f58725ce40685f7297181ef98d81bc28420c8291))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.39...v3.8.0-beta.40) (2024-01-08)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **ui:** sidePanel expandedWidth ([#3728](https://github.com/OHIF/Viewers/issues/3728)) ([61bf22c](https://github.com/OHIF/Viewers/commit/61bf22c6f80e764bdf5c3b56bb0124a95aa0f793))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.38...v3.8.0-beta.39) (2024-01-08)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* improve disableEditing flag ([#3875](https://github.com/OHIF/Viewers/issues/3875)) ([2049c09](https://github.com/OHIF/Viewers/commit/2049c0936c86f819604c243d3dc7b3fe971b5b2c))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.37...v3.8.0-beta.38) (2024-01-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* convert radian to degree value for mip rotation ([#3881](https://github.com/OHIF/Viewers/issues/3881)) ([bf846c9](https://github.com/OHIF/Viewers/commit/bf846c94c378f04b9f44dcd71be3f056dbcfe0b5))
|
||||
* PDF display request in v3 ([#3878](https://github.com/OHIF/Viewers/issues/3878)) ([9865030](https://github.com/OHIF/Viewers/commit/98650302c7575f0aea386e32cfc4112c378035e6))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.36...v3.8.0-beta.37) (2024-01-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* colormap for stack viewports via HangingProtocol ([#3866](https://github.com/OHIF/Viewers/issues/3866)) ([e8858f3](https://github.com/OHIF/Viewers/commit/e8858f3eb55552f695af4a55980f9ae2e9af7291))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.35...v3.8.0-beta.36) (2023-12-15)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.34...v3.8.0-beta.35) (2023-12-14)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.33...v3.8.0-beta.34) (2023-12-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **icon-style:** Ensure consistent icon dimensions ([#3727](https://github.com/OHIF/Viewers/issues/3727)) ([6ca13c0](https://github.com/OHIF/Viewers/commit/6ca13c0a4cb5a95bbb52b0db902b5dbf72f8aa6e))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **overlay:** add inline binary overlays ([#3852](https://github.com/OHIF/Viewers/issues/3852)) ([0177b62](https://github.com/OHIF/Viewers/commit/0177b625ba86760168bc4db58c8a109aa9ee83cb))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.32...v3.8.0-beta.33) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.31...v3.8.0-beta.32) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.30...v3.8.0-beta.31) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.29...v3.8.0-beta.30) (2023-12-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **customizationService:** Enable saving and loading of private tags in SRs ([#3842](https://github.com/OHIF/Viewers/issues/3842)) ([e1f55e6](https://github.com/OHIF/Viewers/commit/e1f55e65f2d2a34136ad5d0b1ada77d337a0ea23))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.28...v3.8.0-beta.29) (2023-12-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* address and improve system vulnerabilities ([#3851](https://github.com/OHIF/Viewers/issues/3851)) ([805c532](https://github.com/OHIF/Viewers/commit/805c53270f243ec61f142a3ffa0af500021cd5ec))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **config:** Add activateViewportBeforeInteraction parameter for viewport interaction customization ([#3847](https://github.com/OHIF/Viewers/issues/3847)) ([f707b4e](https://github.com/OHIF/Viewers/commit/f707b4ebc996f379cd30337badc06b07e6e35ac5))
|
||||
* **i18n:** enhanced i18n support ([#3761](https://github.com/OHIF/Viewers/issues/3761)) ([d14a8f0](https://github.com/OHIF/Viewers/commit/d14a8f0199db95cd9e85866a011b64d6bf830d57))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.27...v3.8.0-beta.28) (2023-12-08)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **HP:** Added new 3D hanging protocols to be used in the new layout selector ([#3844](https://github.com/OHIF/Viewers/issues/3844)) ([59576d6](https://github.com/OHIF/Viewers/commit/59576d695d4d26601d35c43f73d602f0b12d72bf))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.26...v3.8.0-beta.27) (2023-12-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **auth:** fix the issue with oauth at a non root path ([#3840](https://github.com/OHIF/Viewers/issues/3840)) ([6651008](https://github.com/OHIF/Viewers/commit/6651008fbb35dabd5991c7f61128e6ef324012df))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.25...v3.8.0-beta.26) (2023-11-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **SM:** drag and drop is now fixed for SM ([#3813](https://github.com/OHIF/Viewers/issues/3813)) ([f1a6764](https://github.com/OHIF/Viewers/commit/f1a67647aed635437b188cea7cf5d5a8fb974bbe))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.24...v3.8.0-beta.25) (2023-11-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cine:** Set cine disabled on mode exit. ([#3812](https://github.com/OHIF/Viewers/issues/3812)) ([924affa](https://github.com/OHIF/Viewers/commit/924affa7b5d420c2f91522a075cecbb3c78e8f52))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.23...v3.8.0-beta.24) (2023-11-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Update the CS3D packages to add the most recent HTJ2K TSUIDS ([#3806](https://github.com/OHIF/Viewers/issues/3806)) ([9d1884d](https://github.com/OHIF/Viewers/commit/9d1884d7d8b6b2a1cdc26965a96995838aa72682))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.22...v3.8.0-beta.23) (2023-11-24)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Merge Data Source ([#3788](https://github.com/OHIF/Viewers/issues/3788)) ([c4ff2c2](https://github.com/OHIF/Viewers/commit/c4ff2c2f09546ce8b72eab9c5e7beed611e3cab0))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.21...v3.8.0-beta.22) (2023-11-21)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **events:** broadcast series summary metadata ([#3798](https://github.com/OHIF/Viewers/issues/3798)) ([404b0a5](https://github.com/OHIF/Viewers/commit/404b0a5d535182d1ae44e33f7232db500a7b2c16))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.20...v3.8.0-beta.21) (2023-11-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **DICOM Overlay:** The overlay data wasn't being refreshed on change ([#3793](https://github.com/OHIF/Viewers/issues/3793)) ([00e7519](https://github.com/OHIF/Viewers/commit/00e751933ac6d611a34773fa69594243f1b99082))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.19...v3.8.0-beta.20) (2023-11-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **metadata:** to handle cornerstone3D update for htj2k ([#3783](https://github.com/OHIF/Viewers/issues/3783)) ([8c8924a](https://github.com/OHIF/Viewers/commit/8c8924af373d906773f5db20defe38628cacd4a0))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.18...v3.8.0-beta.19) (2023-11-18)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **docs:** Added various training videos to support the OHIF CLI tools ([#3794](https://github.com/OHIF/Viewers/issues/3794)) ([d83beb7](https://github.com/OHIF/Viewers/commit/d83beb7c62c1d5be19c54e08d23883f112147fe1))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.17...v3.8.0-beta.18) (2023-11-15)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **url:** Add SeriesInstanceUIDs wado query param ([#3746](https://github.com/OHIF/Viewers/issues/3746)) ([b694228](https://github.com/OHIF/Viewers/commit/b694228dd535e4b97cb86a1dc085b6e8716bdaf3))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.16...v3.8.0-beta.17) (2023-11-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 🐛 Run error handler for failed image requests ([#3773](https://github.com/OHIF/Viewers/issues/3773)) ([3234014](https://github.com/OHIF/Viewers/commit/323401418e7ccab74655ba02f990bbe0ed4e523b))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.15...v3.8.0-beta.16) (2023-11-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **overlay:** Overlays aren't shown on undefined origin ([#3781](https://github.com/OHIF/Viewers/issues/3781)) ([fd1251f](https://github.com/OHIF/Viewers/commit/fd1251f751d8147b8a78c7f4d81c67ba69769afa))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.14...v3.8.0-beta.15) (2023-11-10)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **dicomJSON:** Add Loading Other Display Sets and JSON Metadata Generation script ([#3777](https://github.com/OHIF/Viewers/issues/3777)) ([43b1c17](https://github.com/OHIF/Viewers/commit/43b1c17209502e4876ad59bae09ed9442eda8024))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.13...v3.8.0-beta.14) (2023-11-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **path:** upgrade docusaurus for security ([#3780](https://github.com/OHIF/Viewers/issues/3780)) ([8bbcd0e](https://github.com/OHIF/Viewers/commit/8bbcd0e692e25917c1b6dd94a39fac834c812fca))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.12...v3.8.0-beta.13) (2023-11-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **arrow:** ArrowAnnotate text key cause validation error ([#3771](https://github.com/OHIF/Viewers/issues/3771)) ([8af1046](https://github.com/OHIF/Viewers/commit/8af10468035f1f59e0a21e579d50ad63c8cbf7ad))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.11...v3.8.0-beta.12) (2023-11-08)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add VolumeViewport rotation ([#3776](https://github.com/OHIF/Viewers/issues/3776)) ([442f99d](https://github.com/OHIF/Viewers/commit/442f99d5eb2ceece7def20e14da59af1dd7d8442))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.10...v3.8.0-beta.11) (2023-11-08)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **hp callback:** Add viewport ready callback ([#3772](https://github.com/OHIF/Viewers/issues/3772)) ([bf252bc](https://github.com/OHIF/Viewers/commit/bf252bcec2aae3a00479fdcb732110b344bcf2c0))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.9...v3.8.0-beta.10) (2023-11-03)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.8...v3.8.0-beta.9) (2023-11-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **thumbnail:** Avoid multiple promise creations for thumbnails ([#3756](https://github.com/OHIF/Viewers/issues/3756)) ([b23eeff](https://github.com/OHIF/Viewers/commit/b23eeff93745769e67e60c33d75293d6242c5ec9))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.7...v3.8.0-beta.8) (2023-10-31)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **i18n:** enhanced i18n support ([#3730](https://github.com/OHIF/Viewers/issues/3730)) ([330e11c](https://github.com/OHIF/Viewers/commit/330e11c7ff0151e1096e19b8ffdae7d64cae280e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.6...v3.8.0-beta.7) (2023-10-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **measurement service:** Implemented correct check of schema keys in _isValidMeasurment. ([#3750](https://github.com/OHIF/Viewers/issues/3750)) ([db39585](https://github.com/OHIF/Viewers/commit/db395852b6fc6cd5c265a9282e5eee5bd6f951b7))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **filters:** save worklist query filters to session storage so that they persist between navigation to the viewer and back ([#3749](https://github.com/OHIF/Viewers/issues/3749)) ([2a15ef0](https://github.com/OHIF/Viewers/commit/2a15ef0e44b7b4d8bbf5cb9363db6e523201c681))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.5...v3.8.0-beta.6) (2023-10-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **toolbar:** allow customizable toolbar for active viewport and allow active tool to be deactivated via a click ([#3608](https://github.com/OHIF/Viewers/issues/3608)) ([dd6d976](https://github.com/OHIF/Viewers/commit/dd6d9768bbca1d3cc472e8c1e6d85822500b96ef))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.4...v3.8.0-beta.5) (2023-10-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **sr:** dcm4chee requires the patient name for an SR to match what is in the original study ([#3739](https://github.com/OHIF/Viewers/issues/3739)) ([d98439f](https://github.com/OHIF/Viewers/commit/d98439fe7f3825076dbc87b664a1d1480ff414d3))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.3...v3.8.0-beta.4) (2023-10-23)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.2...v3.8.0-beta.3) (2023-10-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **recipes:** package.json script orthanc:up docker-compose path ([#3741](https://github.com/OHIF/Viewers/issues/3741)) ([49514ae](https://github.com/OHIF/Viewers/commit/49514aedfe0498b5bd505193106a9745a6a5b5e6))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.1...v3.8.0-beta.2) (2023-10-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cine:** Use the frame rate specified in DICOM and optionally auto play cine ([#3735](https://github.com/OHIF/Viewers/issues/3735)) ([d9258ec](https://github.com/OHIF/Viewers/commit/d9258eca70587cf4dc18be4e56c79b16bae73d6d))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.0...v3.8.0-beta.1) (2023-10-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **calibration:** No calibration popup caused by perhaps an unused code optimization for production builds ([#3736](https://github.com/OHIF/Viewers/issues/3736)) ([93d798d](https://github.com/OHIF/Viewers/commit/93d798db99c0dee53ef73c376f8a74ac3049cf3f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.110...v3.8.0-beta.0) (2023-10-12)
|
||||
|
||||
**Note:** Version bump only for package ohif-monorepo-root
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.109...v3.7.0-beta.110) (2023-10-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **display messages:** broken after timings ([#3719](https://github.com/OHIF/Viewers/issues/3719)) ([157b88c](https://github.com/OHIF/Viewers/commit/157b88c909d3289cb89ace731c1f9a19d40797ac))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.108...v3.7.0-beta.109) (2023-10-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **export:** wrong export for the tmtv RT function ([#3715](https://github.com/OHIF/Viewers/issues/3715)) ([a3f2a1a](https://github.com/OHIF/Viewers/commit/a3f2a1a7b0d16bfcc0ecddc2ab731e54c5e377c8))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.107...v3.7.0-beta.108) (2023-10-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **i18n:** display set(s) are two words for English messages ([#3711](https://github.com/OHIF/Viewers/issues/3711)) ([c3a5847](https://github.com/OHIF/Viewers/commit/c3a5847dcd3dce4f1c8d8b11af95f79e3f93f70d))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.106...v3.7.0-beta.107) (2023-10-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **modules:** add stylus loader as an option to be uncommented ([#3710](https://github.com/OHIF/Viewers/issues/3710)) ([7c57f67](https://github.com/OHIF/Viewers/commit/7c57f67844b790fc6e47ac3f9708bf9d576389c8))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.105...v3.7.0-beta.106) (2023-10-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** Various fixes for segmentation mode and other ([#3709](https://github.com/OHIF/Viewers/issues/3709)) ([a9a6ad5](https://github.com/OHIF/Viewers/commit/a9a6ad50eae67b43b8b34efc07182d788cacdcfe))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.104...v3.7.0-beta.105) (2023-10-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **voi:** should publish voi change event on reset ([#3707](https://github.com/OHIF/Viewers/issues/3707)) ([52f34c6](https://github.com/OHIF/Viewers/commit/52f34c64d014f433ec1661a39b47e7fb27f15332))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.103...v3.7.0-beta.104) (2023-10-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **modality unit:** fix the modality unit per target via upgrade of cs3d ([#3706](https://github.com/OHIF/Viewers/issues/3706)) ([0a42d57](https://github.com/OHIF/Viewers/commit/0a42d573bbca7f2551a831a46d3aa6b56674a580))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.102...v3.7.0-beta.103) (2023-10-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** do not use SAB if not specified ([#3705](https://github.com/OHIF/Viewers/issues/3705)) ([4911e47](https://github.com/OHIF/Viewers/commit/4911e4796cef5e22cb7cc0ca73dc5c956bc75339))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.101...v3.7.0-beta.102) (2023-10-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Segmentation:** download RTSS from Labelmap([#3692](https://github.com/OHIF/Viewers/issues/3692)) ([40673f6](https://github.com/OHIF/Viewers/commit/40673f64b36b1150149c55632aa1825178a39e65))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.100...v3.7.0-beta.101) (2023-10-06)
|
||||
|
||||
|
||||
|
||||
@@ -17,6 +17,10 @@ provided by the <a href="https://ohif.org/">Open Health Imaging Foundation (OHIF
|
||||
<div align="center">
|
||||
📰 <a href="https://ohif.org/news/"><strong>Join OHIF Newsletter</strong></a> 📰
|
||||
</div>
|
||||
<div align="center">
|
||||
📰 <a href="https://ohif.org/news/"><strong>Join OHIF Newsletter</strong></a> 📰
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
@@ -26,6 +26,7 @@ module.exports = {
|
||||
'@babel/plugin-transform-typescript',
|
||||
['@babel/plugin-proposal-private-property-in-object', { loose: true }],
|
||||
['@babel/plugin-proposal-private-methods', { loose: true }],
|
||||
'@babel/plugin-transform-class-static-block',
|
||||
],
|
||||
env: {
|
||||
test: {
|
||||
@@ -45,6 +46,7 @@ module.exports = {
|
||||
'@babel/plugin-proposal-object-rest-spread',
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
'@babel/plugin-transform-regenerator',
|
||||
'@babel/transform-destructuring',
|
||||
'@babel/plugin-transform-runtime',
|
||||
'@babel/plugin-transform-typescript',
|
||||
],
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
8bc12a37d0353160ae5ea4624dc0b244b7d59c07
|
||||
45b68e841dcb9e28a2ea991c37ee7ac4a8c5b71e
|
||||
@@ -3,6 +3,599 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.8.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.62...v3.8.0-beta.63) (2024-03-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.61...v3.8.0-beta.62) (2024-03-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.60...v3.8.0-beta.61) (2024-03-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.59...v3.8.0-beta.60) (2024-03-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.58...v3.8.0-beta.59) (2024-03-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.57...v3.8.0-beta.58) (2024-03-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.56...v3.8.0-beta.57) (2024-02-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.55...v3.8.0-beta.56) (2024-02-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.54...v3.8.0-beta.55) (2024-02-21)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **resize:** Optimize resizing process and maintain zoom level ([#3889](https://github.com/OHIF/Viewers/issues/3889)) ([b3a0faf](https://github.com/OHIF/Viewers/commit/b3a0faf5f5f0a1993b2b017eb4cc1216164ea2c6))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.53...v3.8.0-beta.54) (2024-02-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.52...v3.8.0-beta.53) (2024-02-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.51...v3.8.0-beta.52) (2024-01-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.50...v3.8.0-beta.51) (2024-01-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.49...v3.8.0-beta.50) (2024-01-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **viewport-sync:** remember synced viewports bw stack and volume and RENAME StackImageSync to ImageSliceSync ([#3849](https://github.com/OHIF/Viewers/issues/3849)) ([e4a116b](https://github.com/OHIF/Viewers/commit/e4a116b074fcb85c8cbcc9db44fdec565f3386db))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.48...v3.8.0-beta.49) (2024-01-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.47...v3.8.0-beta.48) (2024-01-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.46...v3.8.0-beta.47) (2024-01-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.45...v3.8.0-beta.46) (2024-01-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.44...v3.8.0-beta.45) (2024-01-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.43...v3.8.0-beta.44) (2024-01-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.42...v3.8.0-beta.43) (2024-01-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** upgrade cs3d to fix various segmentation bugs ([#3885](https://github.com/OHIF/Viewers/issues/3885)) ([b1efe40](https://github.com/OHIF/Viewers/commit/b1efe40aa146e4052cc47b3f774cabbb47a8d1a6))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.41...v3.8.0-beta.42) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.40...v3.8.0-beta.41) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.39...v3.8.0-beta.40) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.38...v3.8.0-beta.39) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.37...v3.8.0-beta.38) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.36...v3.8.0-beta.37) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.35...v3.8.0-beta.36) (2023-12-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.34...v3.8.0-beta.35) (2023-12-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.33...v3.8.0-beta.34) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.32...v3.8.0-beta.33) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.31...v3.8.0-beta.32) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.30...v3.8.0-beta.31) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.29...v3.8.0-beta.30) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.28...v3.8.0-beta.29) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.27...v3.8.0-beta.28) (2023-12-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.26...v3.8.0-beta.27) (2023-12-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.25...v3.8.0-beta.26) (2023-11-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.24...v3.8.0-beta.25) (2023-11-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.23...v3.8.0-beta.24) (2023-11-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.22...v3.8.0-beta.23) (2023-11-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.21...v3.8.0-beta.22) (2023-11-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.20...v3.8.0-beta.21) (2023-11-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.19...v3.8.0-beta.20) (2023-11-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.18...v3.8.0-beta.19) (2023-11-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.17...v3.8.0-beta.18) (2023-11-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.16...v3.8.0-beta.17) (2023-11-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.15...v3.8.0-beta.16) (2023-11-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.14...v3.8.0-beta.15) (2023-11-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.13...v3.8.0-beta.14) (2023-11-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.12...v3.8.0-beta.13) (2023-11-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.11...v3.8.0-beta.12) (2023-11-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.10...v3.8.0-beta.11) (2023-11-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.9...v3.8.0-beta.10) (2023-11-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.8...v3.8.0-beta.9) (2023-11-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.7...v3.8.0-beta.8) (2023-10-31)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.6...v3.8.0-beta.7) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.5...v3.8.0-beta.6) (2023-10-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.4...v3.8.0-beta.5) (2023-10-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.3...v3.8.0-beta.4) (2023-10-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.2...v3.8.0-beta.3) (2023-10-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.1...v3.8.0-beta.2) (2023-10-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.0...v3.8.0-beta.1) (2023-10-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.110...v3.8.0-beta.0) (2023-10-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.109...v3.7.0-beta.110) (2023-10-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.108...v3.7.0-beta.109) (2023-10-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.107...v3.7.0-beta.108) (2023-10-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.106...v3.7.0-beta.107) (2023-10-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.105...v3.7.0-beta.106) (2023-10-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.104...v3.7.0-beta.105) (2023-10-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.103...v3.7.0-beta.104) (2023-10-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.102...v3.7.0-beta.103) (2023-10-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.101...v3.7.0-beta.102) (2023-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.100...v3.7.0-beta.101) (2023-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-rt
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dicom-rt",
|
||||
"version": "3.7.0-beta.101",
|
||||
"version": "3.8.0-beta.63",
|
||||
"description": "DICOM RT read workflow",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -24,6 +24,8 @@
|
||||
"yarn": ">=1.18.0"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "shx rm -rf dist",
|
||||
"clean:deep": "yarn run clean && shx rm -rf node_modules",
|
||||
"dev": "cross-env NODE_ENV=development webpack --config .webpack/webpack.dev.js --watch --output-pathinfo",
|
||||
"dev:dicom-seg": "yarn run dev",
|
||||
"build": "cross-env NODE_ENV=production webpack --config .webpack/webpack.prod.js",
|
||||
@@ -31,10 +33,10 @@
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.7.0-beta.101",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.101",
|
||||
"@ohif/extension-default": "3.7.0-beta.101",
|
||||
"@ohif/i18n": "3.7.0-beta.101",
|
||||
"@ohif/core": "3.8.0-beta.63",
|
||||
"@ohif/extension-cornerstone": "3.8.0-beta.63",
|
||||
"@ohif/extension-default": "3.8.0-beta.63",
|
||||
"@ohif/i18n": "3.8.0-beta.63",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
|
||||
@@ -168,6 +168,8 @@ function OHIFCornerstoneRTViewport(props) {
|
||||
}, [servicesManager, viewportId, rtDisplaySet, rtIsLoading]);
|
||||
|
||||
useEffect(() => {
|
||||
// I'm not sure what is this, since in RT we support Overlapping segments
|
||||
// via contours
|
||||
const { unsubscribe } = segmentationService.subscribe(
|
||||
segmentationService.EVENTS.SEGMENTATION_LOADING_COMPLETE,
|
||||
evt => {
|
||||
|
||||
@@ -3,6 +3,620 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.8.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.62...v3.8.0-beta.63) (2024-03-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.61...v3.8.0-beta.62) (2024-03-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.60...v3.8.0-beta.61) (2024-03-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **SR display:** and the token based navigation ([#3995](https://github.com/OHIF/Viewers/issues/3995)) ([feed230](https://github.com/OHIF/Viewers/commit/feed2304c124dc2facc7a7371ed9851548c223c5))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.59...v3.8.0-beta.60) (2024-03-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.58...v3.8.0-beta.59) (2024-03-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.57...v3.8.0-beta.58) (2024-03-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.56...v3.8.0-beta.57) (2024-02-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.55...v3.8.0-beta.56) (2024-02-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **demo:** Deploy issue ([#3951](https://github.com/OHIF/Viewers/issues/3951)) ([21e8a2b](https://github.com/OHIF/Viewers/commit/21e8a2bd0b7cc72f90a31e472d285d761be15d30))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.54...v3.8.0-beta.55) (2024-02-21)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **resize:** Optimize resizing process and maintain zoom level ([#3889](https://github.com/OHIF/Viewers/issues/3889)) ([b3a0faf](https://github.com/OHIF/Viewers/commit/b3a0faf5f5f0a1993b2b017eb4cc1216164ea2c6))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.53...v3.8.0-beta.54) (2024-02-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.52...v3.8.0-beta.53) (2024-02-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.51...v3.8.0-beta.52) (2024-01-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.50...v3.8.0-beta.51) (2024-01-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.49...v3.8.0-beta.50) (2024-01-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.48...v3.8.0-beta.49) (2024-01-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.47...v3.8.0-beta.48) (2024-01-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.46...v3.8.0-beta.47) (2024-01-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.45...v3.8.0-beta.46) (2024-01-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Update CS3D to fix second render ([#3892](https://github.com/OHIF/Viewers/issues/3892)) ([d00a86b](https://github.com/OHIF/Viewers/commit/d00a86b022742ea089d246d06cfd691f43b64412))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.44...v3.8.0-beta.45) (2024-01-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.43...v3.8.0-beta.44) (2024-01-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.42...v3.8.0-beta.43) (2024-01-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** upgrade cs3d to fix various segmentation bugs ([#3885](https://github.com/OHIF/Viewers/issues/3885)) ([b1efe40](https://github.com/OHIF/Viewers/commit/b1efe40aa146e4052cc47b3f774cabbb47a8d1a6))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.41...v3.8.0-beta.42) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.40...v3.8.0-beta.41) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.39...v3.8.0-beta.40) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.38...v3.8.0-beta.39) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.37...v3.8.0-beta.38) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.36...v3.8.0-beta.37) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.35...v3.8.0-beta.36) (2023-12-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.34...v3.8.0-beta.35) (2023-12-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.33...v3.8.0-beta.34) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.32...v3.8.0-beta.33) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.31...v3.8.0-beta.32) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.30...v3.8.0-beta.31) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.29...v3.8.0-beta.30) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.28...v3.8.0-beta.29) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.27...v3.8.0-beta.28) (2023-12-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.26...v3.8.0-beta.27) (2023-12-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **auth:** fix the issue with oauth at a non root path ([#3840](https://github.com/OHIF/Viewers/issues/3840)) ([6651008](https://github.com/OHIF/Viewers/commit/6651008fbb35dabd5991c7f61128e6ef324012df))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.25...v3.8.0-beta.26) (2023-11-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.24...v3.8.0-beta.25) (2023-11-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.23...v3.8.0-beta.24) (2023-11-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Update the CS3D packages to add the most recent HTJ2K TSUIDS ([#3806](https://github.com/OHIF/Viewers/issues/3806)) ([9d1884d](https://github.com/OHIF/Viewers/commit/9d1884d7d8b6b2a1cdc26965a96995838aa72682))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.22...v3.8.0-beta.23) (2023-11-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.21...v3.8.0-beta.22) (2023-11-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.20...v3.8.0-beta.21) (2023-11-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.19...v3.8.0-beta.20) (2023-11-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.18...v3.8.0-beta.19) (2023-11-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.17...v3.8.0-beta.18) (2023-11-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.16...v3.8.0-beta.17) (2023-11-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.15...v3.8.0-beta.16) (2023-11-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.14...v3.8.0-beta.15) (2023-11-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.13...v3.8.0-beta.14) (2023-11-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.12...v3.8.0-beta.13) (2023-11-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.11...v3.8.0-beta.12) (2023-11-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.10...v3.8.0-beta.11) (2023-11-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.9...v3.8.0-beta.10) (2023-11-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.8...v3.8.0-beta.9) (2023-11-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.7...v3.8.0-beta.8) (2023-10-31)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.6...v3.8.0-beta.7) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.5...v3.8.0-beta.6) (2023-10-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.4...v3.8.0-beta.5) (2023-10-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.3...v3.8.0-beta.4) (2023-10-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.2...v3.8.0-beta.3) (2023-10-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.1...v3.8.0-beta.2) (2023-10-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.0...v3.8.0-beta.1) (2023-10-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.110...v3.8.0-beta.0) (2023-10-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.109...v3.7.0-beta.110) (2023-10-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.108...v3.7.0-beta.109) (2023-10-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.107...v3.7.0-beta.108) (2023-10-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.106...v3.7.0-beta.107) (2023-10-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.105...v3.7.0-beta.106) (2023-10-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.104...v3.7.0-beta.105) (2023-10-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **voi:** should publish voi change event on reset ([#3707](https://github.com/OHIF/Viewers/issues/3707)) ([52f34c6](https://github.com/OHIF/Viewers/commit/52f34c64d014f433ec1661a39b47e7fb27f15332))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.103...v3.7.0-beta.104) (2023-10-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **modality unit:** fix the modality unit per target via upgrade of cs3d ([#3706](https://github.com/OHIF/Viewers/issues/3706)) ([0a42d57](https://github.com/OHIF/Viewers/commit/0a42d573bbca7f2551a831a46d3aa6b56674a580))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.102...v3.7.0-beta.103) (2023-10-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.101...v3.7.0-beta.102) (2023-10-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Segmentation:** download RTSS from Labelmap([#3692](https://github.com/OHIF/Viewers/issues/3692)) ([40673f6](https://github.com/OHIF/Viewers/commit/40673f64b36b1150149c55632aa1825178a39e65))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.100...v3.7.0-beta.101) (2023-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-seg
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dicom-seg",
|
||||
"version": "3.7.0-beta.101",
|
||||
"version": "3.8.0-beta.63",
|
||||
"description": "DICOM SEG read workflow",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -24,6 +24,8 @@
|
||||
"yarn": ">=1.18.0"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "shx rm -rf dist",
|
||||
"clean:deep": "yarn run clean && shx rm -rf node_modules",
|
||||
"dev": "cross-env NODE_ENV=development webpack --config .webpack/webpack.dev.js --watch --output-pathinfo",
|
||||
"dev:dicom-seg": "yarn run dev",
|
||||
"build": "cross-env NODE_ENV=production webpack --config .webpack/webpack.prod.js",
|
||||
@@ -31,10 +33,10 @@
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.7.0-beta.101",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.101",
|
||||
"@ohif/extension-default": "3.7.0-beta.101",
|
||||
"@ohif/i18n": "3.7.0-beta.101",
|
||||
"@ohif/core": "3.8.0-beta.63",
|
||||
"@ohif/extension-cornerstone": "3.8.0-beta.63",
|
||||
"@ohif/extension-default": "3.8.0-beta.63",
|
||||
"@ohif/i18n": "3.8.0-beta.63",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
@@ -44,7 +46,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/tools": "^1.19.4",
|
||||
"@cornerstonejs/adapters": "^1.66.7",
|
||||
"@cornerstonejs/core": "^1.66.7",
|
||||
"@kitware/vtk.js": "29.7.0",
|
||||
"react-color": "^2.19.3"
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,16 @@ import dcmjs from 'dcmjs';
|
||||
import { createReportDialogPrompt } from '@ohif/extension-default';
|
||||
import { ServicesManager, Types } from '@ohif/core';
|
||||
import { cache, metaData } from '@cornerstonejs/core';
|
||||
import { segmentation as cornerstoneToolsSegmentation } from '@cornerstonejs/tools';
|
||||
import { adaptersSEG, helpers } from '@cornerstonejs/adapters';
|
||||
import { DicomMetadataStore } from '@ohif/core';
|
||||
import {
|
||||
segmentation as cornerstoneToolsSegmentation,
|
||||
Enums as cornerstoneToolsEnums,
|
||||
} from '@cornerstonejs/tools';
|
||||
import { adaptersRT, helpers, adaptersSEG } from '@cornerstonejs/adapters';
|
||||
import { classes, DicomMetadataStore } from '@ohif/core';
|
||||
|
||||
import vtkImageMarchingSquares from '@kitware/vtk.js/Filters/General/ImageMarchingSquares';
|
||||
import vtkDataArray from '@kitware/vtk.js/Common/Core/DataArray';
|
||||
import vtkImageData from '@kitware/vtk.js/Common/DataModel/ImageData';
|
||||
|
||||
import {
|
||||
updateViewportsForSegmentationRendering,
|
||||
@@ -12,12 +19,20 @@ import {
|
||||
getTargetViewport,
|
||||
} from './utils/hydrationUtils';
|
||||
|
||||
const { datasetToBlob } = dcmjs.data;
|
||||
|
||||
const {
|
||||
Cornerstone3D: {
|
||||
Segmentation: { generateLabelMaps2DFrom3D, generateSegmentation },
|
||||
},
|
||||
} = adaptersSEG;
|
||||
|
||||
const {
|
||||
Cornerstone3D: {
|
||||
RTSS: { generateRTSSFromSegmentations },
|
||||
},
|
||||
} = adaptersRT;
|
||||
|
||||
const { downloadDICOMData } = helpers;
|
||||
|
||||
const commandsModule = ({
|
||||
@@ -348,6 +363,40 @@ const commandsModule = ({
|
||||
|
||||
return naturalizedReport;
|
||||
},
|
||||
/**
|
||||
* Converts segmentations into RTSS for download.
|
||||
* This sample function retrieves all segentations and passes to
|
||||
* cornerstone tool adapter to convert to DICOM RTSS format. It then
|
||||
* converts dataset to downloadable blob.
|
||||
*
|
||||
*/
|
||||
downloadRTSS: ({ segmentationId }) => {
|
||||
const segmentations = segmentationService.getSegmentation(segmentationId);
|
||||
const vtkUtils = {
|
||||
vtkImageMarchingSquares,
|
||||
vtkDataArray,
|
||||
vtkImageData,
|
||||
};
|
||||
|
||||
const RTSS = generateRTSSFromSegmentations(
|
||||
segmentations,
|
||||
classes.MetadataProvider,
|
||||
DicomMetadataStore,
|
||||
cache,
|
||||
cornerstoneToolsEnums,
|
||||
vtkUtils
|
||||
);
|
||||
|
||||
try {
|
||||
const reportBlob = datasetToBlob(RTSS);
|
||||
|
||||
//Create a URL for the binary.
|
||||
const objectUrl = URL.createObjectURL(reportBlob);
|
||||
window.location.assign(objectUrl);
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const definitions = {
|
||||
@@ -372,6 +421,9 @@ const commandsModule = ({
|
||||
storeSegmentation: {
|
||||
commandFn: actions.storeSegmentation,
|
||||
},
|
||||
downloadRTSS: {
|
||||
commandFn: actions.downloadRTSS,
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { utils } from '@ohif/core';
|
||||
import { metaData, cache, triggerEvent, eventTarget } from '@cornerstonejs/core';
|
||||
import { CONSTANTS } from '@cornerstonejs/tools';
|
||||
import { adaptersSEG, Enums } from '@cornerstonejs/adapters';
|
||||
|
||||
import { SOPClassHandlerId } from './id';
|
||||
@@ -141,7 +142,7 @@ async function _loadSegments({ extensionManager, servicesManager, segDisplaySet,
|
||||
'@ohif/extension-cornerstone.utilityModule.common'
|
||||
);
|
||||
|
||||
const { segmentationService } = servicesManager.services;
|
||||
const { segmentationService, uiNotificationService } = servicesManager.services;
|
||||
|
||||
const { dicomLoaderService } = utilityModule.exports;
|
||||
const arrayBuffer = await dicomLoaderService.findDicomDataPromise(segDisplaySet, null, headers);
|
||||
@@ -174,12 +175,40 @@ async function _loadSegments({ extensionManager, servicesManager, segDisplaySet,
|
||||
{ skipOverlapping, tolerance, eventTarget, triggerEvent }
|
||||
);
|
||||
|
||||
let usedRecommendedDisplayCIELabValue = true;
|
||||
results.segMetadata.data.forEach((data, i) => {
|
||||
if (i > 0) {
|
||||
data.rgba = dicomlabToRGB(data.RecommendedDisplayCIELabValue);
|
||||
data.rgba = data.RecommendedDisplayCIELabValue;
|
||||
|
||||
if (data.rgba) {
|
||||
data.rgba = dicomlabToRGB(data.rgba);
|
||||
} else {
|
||||
usedRecommendedDisplayCIELabValue = false;
|
||||
data.rgba = CONSTANTS.COLOR_LUT[i % CONSTANTS.COLOR_LUT.length];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (results.overlappingSegments) {
|
||||
uiNotificationService.show({
|
||||
title: 'Overlapping Segments',
|
||||
message:
|
||||
'Unsupported overlapping segments detected, segmentation rendering results may be incorrect.',
|
||||
type: 'warning',
|
||||
});
|
||||
}
|
||||
|
||||
if (!usedRecommendedDisplayCIELabValue) {
|
||||
// Display a notification about the non-utilization of RecommendedDisplayCIELabValue
|
||||
uiNotificationService.show({
|
||||
title: 'DICOM SEG import',
|
||||
message:
|
||||
'RecommendedDisplayCIELabValue not found for one or more segments. The default color was used instead.',
|
||||
type: 'warning',
|
||||
duration: 5000,
|
||||
});
|
||||
}
|
||||
|
||||
Object.assign(segDisplaySet, results);
|
||||
}
|
||||
|
||||
|
||||
@@ -215,6 +215,12 @@ export default function PanelSegmentation({
|
||||
}
|
||||
};
|
||||
|
||||
const onSegmentationDownloadRTSS = segmentationId => {
|
||||
commandsManager.runCommand('downloadRTSS', {
|
||||
segmentationId,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="ohif-scrollbar flex min-h-0 flex-auto select-none flex-col justify-between overflow-auto">
|
||||
@@ -227,6 +233,7 @@ export default function PanelSegmentation({
|
||||
onSegmentationClick={onSegmentationClick}
|
||||
onSegmentationDelete={onSegmentationDelete}
|
||||
onSegmentationDownload={onSegmentationDownload}
|
||||
onSegmentationDownloadRTSS={onSegmentationDownloadRTSS}
|
||||
storeSegmentation={storeSegmentation}
|
||||
onSegmentationEdit={onSegmentationEdit}
|
||||
onSegmentClick={onSegmentClick}
|
||||
|
||||
@@ -10,9 +10,9 @@ const TOOL_TYPES = {
|
||||
SPHERE_BRUSH: 'SphereBrush',
|
||||
CIRCULAR_ERASER: 'CircularEraser',
|
||||
SPHERE_ERASER: 'SphereEraser',
|
||||
CIRCLE_SCISSOR: 'CircleScissor',
|
||||
RECTANGLE_SCISSOR: 'RectangleScissor',
|
||||
SPHERE_SCISSOR: 'SphereScissor',
|
||||
CIRCLE_SHAPE: 'CircleScissor',
|
||||
RECTANGLE_SHAPE: 'RectangleScissor',
|
||||
SPHERE_SHAPE: 'SphereScissor',
|
||||
THRESHOLD_CIRCULAR_BRUSH: 'ThresholdCircularBrush',
|
||||
THRESHOLD_SPHERE_BRUSH: 'ThresholdSphereBrush',
|
||||
};
|
||||
@@ -31,13 +31,13 @@ const initialState = {
|
||||
brushSize: 15,
|
||||
mode: 'CircularEraser', // Can be 'CircularEraser' or 'SphereEraser'
|
||||
},
|
||||
Scissors: {
|
||||
Shapes: {
|
||||
brushSize: 15,
|
||||
mode: 'CircleScissor', // E.g., 'CircleScissor', 'RectangleScissor', or 'SphereScissor'
|
||||
},
|
||||
ThresholdBrush: {
|
||||
brushSize: 15,
|
||||
thresholdRange: [-500, 500],
|
||||
thresholdRange: null,
|
||||
},
|
||||
activeTool: null,
|
||||
};
|
||||
@@ -88,6 +88,8 @@ function SegmentationToolbox({ servicesManager, extensionManager }) {
|
||||
|
||||
const setToolActive = useCallback(
|
||||
toolName => {
|
||||
initializeThresholdValue(toolName);
|
||||
|
||||
toolbarService.recordInteraction({
|
||||
interactionType: 'tool',
|
||||
commands: [
|
||||
@@ -178,6 +180,24 @@ function SegmentationToolbox({ servicesManager, extensionManager }) {
|
||||
[toolGroupService]
|
||||
);
|
||||
|
||||
function initializeThresholdValue(toolName: any) {
|
||||
if (state.ThresholdBrush.thresholdRange === null) {
|
||||
// set the default threshold range from the tool configuration
|
||||
const toolGroupIds = toolGroupService.getToolGroupIds();
|
||||
const toolGroupId = toolGroupIds[0];
|
||||
const toolGroup = toolGroupService.getToolGroup(toolGroupId);
|
||||
const toolConfig = toolGroup.getToolConfiguration(toolName);
|
||||
const defaultThresholdRange = toolConfig?.strategySpecificConfiguration?.THRESHOLD?.threshold;
|
||||
dispatch({
|
||||
type: ACTIONS.SET_TOOL_CONFIG,
|
||||
payload: {
|
||||
tool: 'ThresholdBrush',
|
||||
config: { thresholdRange: defaultThresholdRange },
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const onBrushSizeChange = useCallback(
|
||||
(valueAsStringOrNumber, toolCategory) => {
|
||||
const value = Number(valueAsStringOrNumber);
|
||||
@@ -200,8 +220,8 @@ function SegmentationToolbox({ servicesManager, extensionManager }) {
|
||||
const handleRangeChange = useCallback(
|
||||
newRange => {
|
||||
if (
|
||||
newRange[0] === state.ThresholdBrush.thresholdRange[0] &&
|
||||
newRange[1] === state.ThresholdBrush.thresholdRange[1]
|
||||
newRange[0] === state.ThresholdBrush.thresholdRange?.[0] &&
|
||||
newRange[1] === state.ThresholdBrush.thresholdRange?.[1]
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -213,7 +233,7 @@ function SegmentationToolbox({ servicesManager, extensionManager }) {
|
||||
const toolGroup = toolGroupService.getToolGroup(toolGroupId);
|
||||
toolGroup.setToolConfiguration(toolName, {
|
||||
strategySpecificConfiguration: {
|
||||
THRESHOLD_INSIDE_CIRCLE: {
|
||||
THRESHOLD: {
|
||||
threshold: newRange,
|
||||
},
|
||||
},
|
||||
@@ -301,24 +321,24 @@ function SegmentationToolbox({ servicesManager, extensionManager }) {
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Scissor',
|
||||
icon: 'icon-tool-scissor',
|
||||
name: 'Shapes',
|
||||
icon: 'icon-tool-shape',
|
||||
disabled: !toolsEnabled,
|
||||
active:
|
||||
state.activeTool === TOOL_TYPES.CIRCLE_SCISSOR ||
|
||||
state.activeTool === TOOL_TYPES.RECTANGLE_SCISSOR ||
|
||||
state.activeTool === TOOL_TYPES.SPHERE_SCISSOR,
|
||||
onClick: () => setToolActive(TOOL_TYPES.CIRCLE_SCISSOR),
|
||||
state.activeTool === TOOL_TYPES.CIRCLE_SHAPE ||
|
||||
state.activeTool === TOOL_TYPES.RECTANGLE_SHAPE ||
|
||||
state.activeTool === TOOL_TYPES.SPHERE_SHAPE,
|
||||
onClick: () => setToolActive(TOOL_TYPES.CIRCLE_SHAPE),
|
||||
options: [
|
||||
{
|
||||
name: 'Mode',
|
||||
type: 'radio',
|
||||
value: state.Scissors.mode,
|
||||
id: 'scissor-mode',
|
||||
value: state.Shapes.mode,
|
||||
id: 'shape-mode',
|
||||
values: [
|
||||
{ value: TOOL_TYPES.CIRCLE_SCISSOR, label: 'Circle' },
|
||||
{ value: TOOL_TYPES.RECTANGLE_SCISSOR, label: 'Rectangle' },
|
||||
{ value: TOOL_TYPES.SPHERE_SCISSOR, label: 'Sphere' },
|
||||
{ value: TOOL_TYPES.CIRCLE_SHAPE, label: 'Circle' },
|
||||
{ value: TOOL_TYPES.RECTANGLE_SHAPE, label: 'Rectangle' },
|
||||
{ value: TOOL_TYPES.SPHERE_SHAPE, label: 'Sphere' },
|
||||
],
|
||||
onChange: value => setToolActive(value),
|
||||
},
|
||||
@@ -365,7 +385,7 @@ function SegmentationToolbox({ servicesManager, extensionManager }) {
|
||||
<InputDoubleRange
|
||||
values={state.ThresholdBrush.thresholdRange}
|
||||
onChange={handleRangeChange}
|
||||
minValue={-1000}
|
||||
minValue={-1000} // Todo: these should be configurable
|
||||
maxValue={1000}
|
||||
step={1}
|
||||
showLabel={true}
|
||||
|
||||
@@ -116,7 +116,6 @@ function OHIFCornerstoneSEGViewport(props) {
|
||||
}}
|
||||
onElementEnabled={onElementEnabled}
|
||||
onElementDisabled={onElementDisabled}
|
||||
// initialImageIndex={initialImageIndex}
|
||||
></Component>
|
||||
);
|
||||
}, [viewportId, segDisplaySet, toolGroupId]);
|
||||
@@ -172,14 +171,6 @@ function OHIFCornerstoneSEGViewport(props) {
|
||||
if (evt.segDisplaySet.displaySetInstanceUID === segDisplaySet.displaySetInstanceUID) {
|
||||
setSegIsLoading(false);
|
||||
}
|
||||
|
||||
if (evt.overlappingSegments) {
|
||||
uiNotificationService.show({
|
||||
title: 'Overlapping Segments',
|
||||
message: 'Overlapping segments detected which is not currently supported',
|
||||
type: 'warning',
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -3,6 +3,629 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.8.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.62...v3.8.0-beta.63) (2024-03-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.61...v3.8.0-beta.62) (2024-03-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.60...v3.8.0-beta.61) (2024-03-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **SR display:** and the token based navigation ([#3995](https://github.com/OHIF/Viewers/issues/3995)) ([feed230](https://github.com/OHIF/Viewers/commit/feed2304c124dc2facc7a7371ed9851548c223c5))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.59...v3.8.0-beta.60) (2024-03-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.58...v3.8.0-beta.59) (2024-03-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.57...v3.8.0-beta.58) (2024-03-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.56...v3.8.0-beta.57) (2024-02-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.55...v3.8.0-beta.56) (2024-02-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **demo:** Deploy issue ([#3951](https://github.com/OHIF/Viewers/issues/3951)) ([21e8a2b](https://github.com/OHIF/Viewers/commit/21e8a2bd0b7cc72f90a31e472d285d761be15d30))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.54...v3.8.0-beta.55) (2024-02-21)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **resize:** Optimize resizing process and maintain zoom level ([#3889](https://github.com/OHIF/Viewers/issues/3889)) ([b3a0faf](https://github.com/OHIF/Viewers/commit/b3a0faf5f5f0a1993b2b017eb4cc1216164ea2c6))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.53...v3.8.0-beta.54) (2024-02-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.52...v3.8.0-beta.53) (2024-02-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.51...v3.8.0-beta.52) (2024-01-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.50...v3.8.0-beta.51) (2024-01-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.49...v3.8.0-beta.50) (2024-01-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.48...v3.8.0-beta.49) (2024-01-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.47...v3.8.0-beta.48) (2024-01-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.46...v3.8.0-beta.47) (2024-01-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.45...v3.8.0-beta.46) (2024-01-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Update CS3D to fix second render ([#3892](https://github.com/OHIF/Viewers/issues/3892)) ([d00a86b](https://github.com/OHIF/Viewers/commit/d00a86b022742ea089d246d06cfd691f43b64412))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.44...v3.8.0-beta.45) (2024-01-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.43...v3.8.0-beta.44) (2024-01-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.42...v3.8.0-beta.43) (2024-01-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** upgrade cs3d to fix various segmentation bugs ([#3885](https://github.com/OHIF/Viewers/issues/3885)) ([b1efe40](https://github.com/OHIF/Viewers/commit/b1efe40aa146e4052cc47b3f774cabbb47a8d1a6))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.41...v3.8.0-beta.42) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.40...v3.8.0-beta.41) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.39...v3.8.0-beta.40) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.38...v3.8.0-beta.39) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.37...v3.8.0-beta.38) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.36...v3.8.0-beta.37) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.35...v3.8.0-beta.36) (2023-12-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.34...v3.8.0-beta.35) (2023-12-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.33...v3.8.0-beta.34) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.32...v3.8.0-beta.33) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.31...v3.8.0-beta.32) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.30...v3.8.0-beta.31) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.29...v3.8.0-beta.30) (2023-12-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **customizationService:** Enable saving and loading of private tags in SRs ([#3842](https://github.com/OHIF/Viewers/issues/3842)) ([e1f55e6](https://github.com/OHIF/Viewers/commit/e1f55e65f2d2a34136ad5d0b1ada77d337a0ea23))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.28...v3.8.0-beta.29) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.27...v3.8.0-beta.28) (2023-12-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.26...v3.8.0-beta.27) (2023-12-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **auth:** fix the issue with oauth at a non root path ([#3840](https://github.com/OHIF/Viewers/issues/3840)) ([6651008](https://github.com/OHIF/Viewers/commit/6651008fbb35dabd5991c7f61128e6ef324012df))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.25...v3.8.0-beta.26) (2023-11-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.24...v3.8.0-beta.25) (2023-11-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.23...v3.8.0-beta.24) (2023-11-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Update the CS3D packages to add the most recent HTJ2K TSUIDS ([#3806](https://github.com/OHIF/Viewers/issues/3806)) ([9d1884d](https://github.com/OHIF/Viewers/commit/9d1884d7d8b6b2a1cdc26965a96995838aa72682))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.22...v3.8.0-beta.23) (2023-11-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.21...v3.8.0-beta.22) (2023-11-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.20...v3.8.0-beta.21) (2023-11-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.19...v3.8.0-beta.20) (2023-11-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.18...v3.8.0-beta.19) (2023-11-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.17...v3.8.0-beta.18) (2023-11-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.16...v3.8.0-beta.17) (2023-11-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.15...v3.8.0-beta.16) (2023-11-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.14...v3.8.0-beta.15) (2023-11-10)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **dicomJSON:** Add Loading Other Display Sets and JSON Metadata Generation script ([#3777](https://github.com/OHIF/Viewers/issues/3777)) ([43b1c17](https://github.com/OHIF/Viewers/commit/43b1c17209502e4876ad59bae09ed9442eda8024))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.13...v3.8.0-beta.14) (2023-11-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.12...v3.8.0-beta.13) (2023-11-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.11...v3.8.0-beta.12) (2023-11-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.10...v3.8.0-beta.11) (2023-11-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.9...v3.8.0-beta.10) (2023-11-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.8...v3.8.0-beta.9) (2023-11-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.7...v3.8.0-beta.8) (2023-10-31)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.6...v3.8.0-beta.7) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.5...v3.8.0-beta.6) (2023-10-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.4...v3.8.0-beta.5) (2023-10-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **sr:** dcm4chee requires the patient name for an SR to match what is in the original study ([#3739](https://github.com/OHIF/Viewers/issues/3739)) ([d98439f](https://github.com/OHIF/Viewers/commit/d98439fe7f3825076dbc87b664a1d1480ff414d3))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.3...v3.8.0-beta.4) (2023-10-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.2...v3.8.0-beta.3) (2023-10-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.1...v3.8.0-beta.2) (2023-10-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.0...v3.8.0-beta.1) (2023-10-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.110...v3.8.0-beta.0) (2023-10-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.109...v3.7.0-beta.110) (2023-10-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.108...v3.7.0-beta.109) (2023-10-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.107...v3.7.0-beta.108) (2023-10-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.106...v3.7.0-beta.107) (2023-10-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.105...v3.7.0-beta.106) (2023-10-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.104...v3.7.0-beta.105) (2023-10-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **voi:** should publish voi change event on reset ([#3707](https://github.com/OHIF/Viewers/issues/3707)) ([52f34c6](https://github.com/OHIF/Viewers/commit/52f34c64d014f433ec1661a39b47e7fb27f15332))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.103...v3.7.0-beta.104) (2023-10-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **modality unit:** fix the modality unit per target via upgrade of cs3d ([#3706](https://github.com/OHIF/Viewers/issues/3706)) ([0a42d57](https://github.com/OHIF/Viewers/commit/0a42d573bbca7f2551a831a46d3aa6b56674a580))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.102...v3.7.0-beta.103) (2023-10-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.101...v3.7.0-beta.102) (2023-10-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Segmentation:** download RTSS from Labelmap([#3692](https://github.com/OHIF/Viewers/issues/3692)) ([40673f6](https://github.com/OHIF/Viewers/commit/40673f64b36b1150149c55632aa1825178a39e65))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.100...v3.7.0-beta.101) (2023-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone-dicom-sr
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone-dicom-sr",
|
||||
"version": "3.7.0-beta.101",
|
||||
"version": "3.8.0-beta.63",
|
||||
"description": "OHIF extension for an SR Cornerstone Viewport",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -23,6 +23,8 @@
|
||||
"ohif-extension"
|
||||
],
|
||||
"scripts": {
|
||||
"clean": "shx rm -rf dist",
|
||||
"clean:deep": "yarn run clean && shx rm -rf node_modules",
|
||||
"dev": "cross-env NODE_ENV=development webpack --config .webpack/webpack.dev.js --watch --output-pathinfo",
|
||||
"dev:cornerstone": "yarn run dev",
|
||||
"build": "cross-env NODE_ENV=production webpack --config .webpack/webpack.prod.js",
|
||||
@@ -32,11 +34,11 @@
|
||||
"test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.7.0-beta.101",
|
||||
"@ohif/extension-cornerstone": "3.7.0-beta.101",
|
||||
"@ohif/extension-measurement-tracking": "3.7.0-beta.101",
|
||||
"@ohif/ui": "3.7.0-beta.101",
|
||||
"dcmjs": "^0.29.5",
|
||||
"@ohif/core": "3.8.0-beta.63",
|
||||
"@ohif/extension-cornerstone": "3.8.0-beta.63",
|
||||
"@ohif/extension-measurement-tracking": "3.8.0-beta.63",
|
||||
"@ohif/ui": "3.8.0-beta.63",
|
||||
"dcmjs": "^0.29.12",
|
||||
"dicom-parser": "^1.8.9",
|
||||
"hammerjs": "^2.0.8",
|
||||
"prop-types": "^15.6.2",
|
||||
@@ -44,9 +46,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/adapters": "^1.19.4",
|
||||
"@cornerstonejs/core": "^1.19.4",
|
||||
"@cornerstonejs/tools": "^1.19.4",
|
||||
"@cornerstonejs/adapters": "^1.66.7",
|
||||
"@cornerstonejs/core": "^1.66.7",
|
||||
"@cornerstonejs/tools": "^1.66.7",
|
||||
"classnames": "^2.3.2"
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,9 @@ const _generateReport = (measurementData, additionalFindingTypes, options = {})
|
||||
return dataset;
|
||||
};
|
||||
|
||||
const commandsModule = ({}) => {
|
||||
const commandsModule = props => {
|
||||
const { servicesManager } = props;
|
||||
const { customizationService } = servicesManager.services;
|
||||
const actions = {
|
||||
/**
|
||||
*
|
||||
@@ -95,7 +97,15 @@ const commandsModule = ({}) => {
|
||||
throw new Error('Invalid report, no content');
|
||||
}
|
||||
|
||||
await dataSource.store.dicom(naturalizedReport);
|
||||
const onBeforeDicomStore =
|
||||
customizationService.getModeCustomization('onBeforeDicomStore')?.value;
|
||||
|
||||
let dicomDict;
|
||||
if (typeof onBeforeDicomStore === 'function') {
|
||||
dicomDict = onBeforeDicomStore({ measurementData, naturalizedReport });
|
||||
}
|
||||
|
||||
await dataSource.store.dicom(naturalizedReport, null, dicomDict);
|
||||
|
||||
if (StudyInstanceUID) {
|
||||
dataSource.deleteStudyMetadataPromise(StudyInstanceUID);
|
||||
|
||||
@@ -171,7 +171,12 @@ function _load(displaySet, servicesManager, extensionManager) {
|
||||
|
||||
// Check currently added displaySets and add measurements if the sources exist.
|
||||
displaySetService.activeDisplaySets.forEach(activeDisplaySet => {
|
||||
_checkIfCanAddMeasurementsToDisplaySet(displaySet, activeDisplaySet, dataSource);
|
||||
_checkIfCanAddMeasurementsToDisplaySet(
|
||||
displaySet,
|
||||
activeDisplaySet,
|
||||
dataSource,
|
||||
servicesManager
|
||||
);
|
||||
});
|
||||
|
||||
// Subscribe to new displaySets as the source may come in after.
|
||||
@@ -180,12 +185,23 @@ function _load(displaySet, servicesManager, extensionManager) {
|
||||
// If there are still some measurements that have not yet been loaded into cornerstone,
|
||||
// See if we can load them onto any of the new displaySets.
|
||||
displaySetsAdded.forEach(newDisplaySet => {
|
||||
_checkIfCanAddMeasurementsToDisplaySet(displaySet, newDisplaySet, dataSource);
|
||||
_checkIfCanAddMeasurementsToDisplaySet(
|
||||
displaySet,
|
||||
newDisplaySet,
|
||||
dataSource,
|
||||
servicesManager
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function _checkIfCanAddMeasurementsToDisplaySet(srDisplaySet, newDisplaySet, dataSource) {
|
||||
function _checkIfCanAddMeasurementsToDisplaySet(
|
||||
srDisplaySet,
|
||||
newDisplaySet,
|
||||
dataSource,
|
||||
servicesManager
|
||||
) {
|
||||
const { customizationService } = servicesManager.services;
|
||||
let unloadedMeasurements = srDisplaySet.measurements.filter(
|
||||
measurement => measurement.loaded === false
|
||||
);
|
||||
@@ -200,7 +216,11 @@ function _checkIfCanAddMeasurementsToDisplaySet(srDisplaySet, newDisplaySet, dat
|
||||
return;
|
||||
}
|
||||
|
||||
const { sopClassUids, images } = newDisplaySet;
|
||||
if (newDisplaySet.unsupported) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { sopClassUids } = newDisplaySet;
|
||||
|
||||
// Check if any have the newDisplaySet is the correct SOPClass.
|
||||
unloadedMeasurements = unloadedMeasurements.filter(measurement =>
|
||||
@@ -240,7 +260,20 @@ function _checkIfCanAddMeasurementsToDisplaySet(srDisplaySet, newDisplaySet, dat
|
||||
|
||||
if (SOPInstanceUIDs.includes(SOPInstanceUID)) {
|
||||
for (let j = unloadedMeasurements.length - 1; j >= 0; j--) {
|
||||
const measurement = unloadedMeasurements[j];
|
||||
let measurement = unloadedMeasurements[j];
|
||||
|
||||
const onBeforeSRAddMeasurement = customizationService.getModeCustomization(
|
||||
'onBeforeSRAddMeasurement'
|
||||
)?.value;
|
||||
|
||||
if (typeof onBeforeSRAddMeasurement === 'function') {
|
||||
measurement = onBeforeSRAddMeasurement({
|
||||
measurement,
|
||||
StudyInstanceUID: srDisplaySet.StudyInstanceUID,
|
||||
SeriesInstanceUID: srDisplaySet.SeriesInstanceUID,
|
||||
});
|
||||
}
|
||||
|
||||
if (_measurementReferencesSOPInstanceUID(measurement, SOPInstanceUID, frameNumber)) {
|
||||
addMeasurement(measurement, imageId, newDisplaySet.displaySetInstanceUID);
|
||||
|
||||
|
||||
@@ -339,7 +339,9 @@ export default class DICOMSRDisplayTool extends AnnotationTool {
|
||||
const textLines = this._getTextBoxLinesFromLabels(label);
|
||||
const canvasTextBoxCoords = utilities.drawing.getTextBoxCoordsCanvas(adaptedCanvasCoordinates);
|
||||
|
||||
annotation.data.handles.textBox.worldPosition = viewport.canvasToWorld(canvasTextBoxCoords);
|
||||
if (!annotation.data?.handles?.textBox?.worldPosition) {
|
||||
annotation.data.handles.textBox.worldPosition = viewport.canvasToWorld(canvasTextBoxCoords);
|
||||
}
|
||||
|
||||
const textBoxPosition = viewport.worldToCanvas(annotation.data.handles.textBox.worldPosition);
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ export default function addMeasurement(measurement, imageId, displaySetInstanceU
|
||||
data: {
|
||||
label: measurement.labels,
|
||||
handles: {
|
||||
textBox: {},
|
||||
textBox: measurement.textBox ?? {},
|
||||
},
|
||||
cachedStats: {
|
||||
TrackingUniqueIdentifier: measurementData.TrackingUniqueIdentifier,
|
||||
|
||||
@@ -90,7 +90,7 @@ export default function hydrateStructuredReport(
|
||||
const datasetToUse = _mapLegacyDataSet(instance);
|
||||
|
||||
// Use dcmjs to generate toolState.
|
||||
const storedMeasurementByAnnotationType = MeasurementReport.generateToolState(
|
||||
let storedMeasurementByAnnotationType = MeasurementReport.generateToolState(
|
||||
datasetToUse,
|
||||
// NOTE: we need to pass in the imageIds to dcmjs since the we use them
|
||||
// for the imageToWorld transformation. The following assumes that the order
|
||||
@@ -101,6 +101,16 @@ export default function hydrateStructuredReport(
|
||||
metaData
|
||||
);
|
||||
|
||||
const onBeforeSRHydration =
|
||||
customizationService.getModeCustomization('onBeforeSRHydration')?.value;
|
||||
|
||||
if (typeof onBeforeSRHydration === 'function') {
|
||||
storedMeasurementByAnnotationType = onBeforeSRHydration({
|
||||
storedMeasurementByAnnotationType,
|
||||
displaySet,
|
||||
});
|
||||
}
|
||||
|
||||
// Filter what is found by DICOM SR to measurements we support.
|
||||
const mappingDefinitions = mappings.map(m => m.annotationType);
|
||||
const hydratableMeasurementsInSR = {};
|
||||
|
||||
@@ -360,7 +360,7 @@ function OHIFCornerstoneSRViewport(props) {
|
||||
patientSex: PatientSex || '',
|
||||
patientAge: PatientAge || '',
|
||||
MRN: PatientID || '',
|
||||
thickness: SliceThickness ? `${SliceThickness.toFixed(2)}mm` : '',
|
||||
thickness: SliceThickness ? `${parseFloat(SliceThickness).toFixed(2)}mm` : '',
|
||||
spacing:
|
||||
SpacingBetweenSlices !== undefined ? `${SpacingBetweenSlices.toFixed(2)}mm` : '',
|
||||
scanner: ManufacturerModelName || '',
|
||||
|
||||
@@ -3,6 +3,677 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.8.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.62...v3.8.0-beta.63) (2024-03-25)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.61...v3.8.0-beta.62) (2024-03-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.60...v3.8.0-beta.61) (2024-03-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **SR display:** and the token based navigation ([#3995](https://github.com/OHIF/Viewers/issues/3995)) ([feed230](https://github.com/OHIF/Viewers/commit/feed2304c124dc2facc7a7371ed9851548c223c5))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.59...v3.8.0-beta.60) (2024-03-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.58...v3.8.0-beta.59) (2024-03-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.57...v3.8.0-beta.58) (2024-03-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.56...v3.8.0-beta.57) (2024-02-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.55...v3.8.0-beta.56) (2024-02-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **demo:** Deploy issue ([#3951](https://github.com/OHIF/Viewers/issues/3951)) ([21e8a2b](https://github.com/OHIF/Viewers/commit/21e8a2bd0b7cc72f90a31e472d285d761be15d30))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.54...v3.8.0-beta.55) (2024-02-21)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **resize:** Optimize resizing process and maintain zoom level ([#3889](https://github.com/OHIF/Viewers/issues/3889)) ([b3a0faf](https://github.com/OHIF/Viewers/commit/b3a0faf5f5f0a1993b2b017eb4cc1216164ea2c6))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.53...v3.8.0-beta.54) (2024-02-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.52...v3.8.0-beta.53) (2024-02-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.51...v3.8.0-beta.52) (2024-01-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.50...v3.8.0-beta.51) (2024-01-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.49...v3.8.0-beta.50) (2024-01-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **viewport-sync:** remember synced viewports bw stack and volume and RENAME StackImageSync to ImageSliceSync ([#3849](https://github.com/OHIF/Viewers/issues/3849)) ([e4a116b](https://github.com/OHIF/Viewers/commit/e4a116b074fcb85c8cbcc9db44fdec565f3386db))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.48...v3.8.0-beta.49) (2024-01-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.47...v3.8.0-beta.48) (2024-01-17)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.46...v3.8.0-beta.47) (2024-01-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.45...v3.8.0-beta.46) (2024-01-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Update CS3D to fix second render ([#3892](https://github.com/OHIF/Viewers/issues/3892)) ([d00a86b](https://github.com/OHIF/Viewers/commit/d00a86b022742ea089d246d06cfd691f43b64412))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.44...v3.8.0-beta.45) (2024-01-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.43...v3.8.0-beta.44) (2024-01-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.42...v3.8.0-beta.43) (2024-01-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** upgrade cs3d to fix various segmentation bugs ([#3885](https://github.com/OHIF/Viewers/issues/3885)) ([b1efe40](https://github.com/OHIF/Viewers/commit/b1efe40aa146e4052cc47b3f774cabbb47a8d1a6))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.41...v3.8.0-beta.42) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.40...v3.8.0-beta.41) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.39...v3.8.0-beta.40) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.38...v3.8.0-beta.39) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.37...v3.8.0-beta.38) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.36...v3.8.0-beta.37) (2024-01-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* colormap for stack viewports via HangingProtocol ([#3866](https://github.com/OHIF/Viewers/issues/3866)) ([e8858f3](https://github.com/OHIF/Viewers/commit/e8858f3eb55552f695af4a55980f9ae2e9af7291))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.35...v3.8.0-beta.36) (2023-12-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.34...v3.8.0-beta.35) (2023-12-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.33...v3.8.0-beta.34) (2023-12-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **overlay:** add inline binary overlays ([#3852](https://github.com/OHIF/Viewers/issues/3852)) ([0177b62](https://github.com/OHIF/Viewers/commit/0177b625ba86760168bc4db58c8a109aa9ee83cb))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.32...v3.8.0-beta.33) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.31...v3.8.0-beta.32) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.30...v3.8.0-beta.31) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.29...v3.8.0-beta.30) (2023-12-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **customizationService:** Enable saving and loading of private tags in SRs ([#3842](https://github.com/OHIF/Viewers/issues/3842)) ([e1f55e6](https://github.com/OHIF/Viewers/commit/e1f55e65f2d2a34136ad5d0b1ada77d337a0ea23))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.28...v3.8.0-beta.29) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.27...v3.8.0-beta.28) (2023-12-08)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **HP:** Added new 3D hanging protocols to be used in the new layout selector ([#3844](https://github.com/OHIF/Viewers/issues/3844)) ([59576d6](https://github.com/OHIF/Viewers/commit/59576d695d4d26601d35c43f73d602f0b12d72bf))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.26...v3.8.0-beta.27) (2023-12-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **auth:** fix the issue with oauth at a non root path ([#3840](https://github.com/OHIF/Viewers/issues/3840)) ([6651008](https://github.com/OHIF/Viewers/commit/6651008fbb35dabd5991c7f61128e6ef324012df))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.25...v3.8.0-beta.26) (2023-11-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.24...v3.8.0-beta.25) (2023-11-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.23...v3.8.0-beta.24) (2023-11-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Update the CS3D packages to add the most recent HTJ2K TSUIDS ([#3806](https://github.com/OHIF/Viewers/issues/3806)) ([9d1884d](https://github.com/OHIF/Viewers/commit/9d1884d7d8b6b2a1cdc26965a96995838aa72682))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.22...v3.8.0-beta.23) (2023-11-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.21...v3.8.0-beta.22) (2023-11-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.20...v3.8.0-beta.21) (2023-11-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **DICOM Overlay:** The overlay data wasn't being refreshed on change ([#3793](https://github.com/OHIF/Viewers/issues/3793)) ([00e7519](https://github.com/OHIF/Viewers/commit/00e751933ac6d611a34773fa69594243f1b99082))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.19...v3.8.0-beta.20) (2023-11-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.18...v3.8.0-beta.19) (2023-11-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.17...v3.8.0-beta.18) (2023-11-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.16...v3.8.0-beta.17) (2023-11-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 🐛 Run error handler for failed image requests ([#3773](https://github.com/OHIF/Viewers/issues/3773)) ([3234014](https://github.com/OHIF/Viewers/commit/323401418e7ccab74655ba02f990bbe0ed4e523b))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.15...v3.8.0-beta.16) (2023-11-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **overlay:** Overlays aren't shown on undefined origin ([#3781](https://github.com/OHIF/Viewers/issues/3781)) ([fd1251f](https://github.com/OHIF/Viewers/commit/fd1251f751d8147b8a78c7f4d81c67ba69769afa))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.14...v3.8.0-beta.15) (2023-11-10)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **dicomJSON:** Add Loading Other Display Sets and JSON Metadata Generation script ([#3777](https://github.com/OHIF/Viewers/issues/3777)) ([43b1c17](https://github.com/OHIF/Viewers/commit/43b1c17209502e4876ad59bae09ed9442eda8024))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.13...v3.8.0-beta.14) (2023-11-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.12...v3.8.0-beta.13) (2023-11-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **arrow:** ArrowAnnotate text key cause validation error ([#3771](https://github.com/OHIF/Viewers/issues/3771)) ([8af1046](https://github.com/OHIF/Viewers/commit/8af10468035f1f59e0a21e579d50ad63c8cbf7ad))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.11...v3.8.0-beta.12) (2023-11-08)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add VolumeViewport rotation ([#3776](https://github.com/OHIF/Viewers/issues/3776)) ([442f99d](https://github.com/OHIF/Viewers/commit/442f99d5eb2ceece7def20e14da59af1dd7d8442))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.10...v3.8.0-beta.11) (2023-11-08)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **hp callback:** Add viewport ready callback ([#3772](https://github.com/OHIF/Viewers/issues/3772)) ([bf252bc](https://github.com/OHIF/Viewers/commit/bf252bcec2aae3a00479fdcb732110b344bcf2c0))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.9...v3.8.0-beta.10) (2023-11-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.8...v3.8.0-beta.9) (2023-11-02)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.7...v3.8.0-beta.8) (2023-10-31)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.6...v3.8.0-beta.7) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.5...v3.8.0-beta.6) (2023-10-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **toolbar:** allow customizable toolbar for active viewport and allow active tool to be deactivated via a click ([#3608](https://github.com/OHIF/Viewers/issues/3608)) ([dd6d976](https://github.com/OHIF/Viewers/commit/dd6d9768bbca1d3cc472e8c1e6d85822500b96ef))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.4...v3.8.0-beta.5) (2023-10-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **sr:** dcm4chee requires the patient name for an SR to match what is in the original study ([#3739](https://github.com/OHIF/Viewers/issues/3739)) ([d98439f](https://github.com/OHIF/Viewers/commit/d98439fe7f3825076dbc87b664a1d1480ff414d3))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.3...v3.8.0-beta.4) (2023-10-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.2...v3.8.0-beta.3) (2023-10-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.1...v3.8.0-beta.2) (2023-10-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cine:** Use the frame rate specified in DICOM and optionally auto play cine ([#3735](https://github.com/OHIF/Viewers/issues/3735)) ([d9258ec](https://github.com/OHIF/Viewers/commit/d9258eca70587cf4dc18be4e56c79b16bae73d6d))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.0...v3.8.0-beta.1) (2023-10-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **calibration:** No calibration popup caused by perhaps an unused code optimization for production builds ([#3736](https://github.com/OHIF/Viewers/issues/3736)) ([93d798d](https://github.com/OHIF/Viewers/commit/93d798db99c0dee53ef73c376f8a74ac3049cf3f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.110...v3.8.0-beta.0) (2023-10-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.109...v3.7.0-beta.110) (2023-10-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.108...v3.7.0-beta.109) (2023-10-11)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.107...v3.7.0-beta.108) (2023-10-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-cornerstone
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.106...v3.7.0-beta.107) (2023-10-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **modules:** add stylus loader as an option to be uncommented ([#3710](https://github.com/OHIF/Viewers/issues/3710)) ([7c57f67](https://github.com/OHIF/Viewers/commit/7c57f67844b790fc6e47ac3f9708bf9d576389c8))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.105...v3.7.0-beta.106) (2023-10-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** Various fixes for segmentation mode and other ([#3709](https://github.com/OHIF/Viewers/issues/3709)) ([a9a6ad5](https://github.com/OHIF/Viewers/commit/a9a6ad50eae67b43b8b34efc07182d788cacdcfe))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.104...v3.7.0-beta.105) (2023-10-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **voi:** should publish voi change event on reset ([#3707](https://github.com/OHIF/Viewers/issues/3707)) ([52f34c6](https://github.com/OHIF/Viewers/commit/52f34c64d014f433ec1661a39b47e7fb27f15332))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.103...v3.7.0-beta.104) (2023-10-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **modality unit:** fix the modality unit per target via upgrade of cs3d ([#3706](https://github.com/OHIF/Viewers/issues/3706)) ([0a42d57](https://github.com/OHIF/Viewers/commit/0a42d573bbca7f2551a831a46d3aa6b56674a580))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.102...v3.7.0-beta.103) (2023-10-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **segmentation:** do not use SAB if not specified ([#3705](https://github.com/OHIF/Viewers/issues/3705)) ([4911e47](https://github.com/OHIF/Viewers/commit/4911e4796cef5e22cb7cc0ca73dc5c956bc75339))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.101...v3.7.0-beta.102) (2023-10-06)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Segmentation:** download RTSS from Labelmap([#3692](https://github.com/OHIF/Viewers/issues/3692)) ([40673f6](https://github.com/OHIF/Viewers/commit/40673f64b36b1150149c55632aa1825178a39e65))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.100...v3.7.0-beta.101) (2023-10-06)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-cornerstone",
|
||||
"version": "3.7.0-beta.101",
|
||||
"version": "3.8.0-beta.63",
|
||||
"description": "OHIF extension for Cornerstone",
|
||||
"author": "OHIF",
|
||||
"license": "MIT",
|
||||
@@ -25,6 +25,8 @@
|
||||
"access": "public"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "shx rm -rf dist",
|
||||
"clean:deep": "yarn run clean && shx rm -rf node_modules",
|
||||
"dev": "cross-env NODE_ENV=development webpack --config .webpack/webpack.dev.js --watch --output-pathinfo",
|
||||
"dev:cornerstone": "yarn run dev",
|
||||
"build": "cross-env NODE_ENV=production webpack --progress --config .webpack/webpack.prod.js",
|
||||
@@ -36,10 +38,10 @@
|
||||
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
|
||||
"@cornerstonejs/codec-openjpeg": "^1.2.2",
|
||||
"@cornerstonejs/codec-openjph": "^2.4.2",
|
||||
"@cornerstonejs/dicom-image-loader": "^1.19.4",
|
||||
"@ohif/core": "3.7.0-beta.101",
|
||||
"@ohif/ui": "3.7.0-beta.101",
|
||||
"dcmjs": "^0.29.6",
|
||||
"@cornerstonejs/dicom-image-loader": "^1.66.7",
|
||||
"@ohif/core": "3.8.0-beta.63",
|
||||
"@ohif/ui": "3.8.0-beta.63",
|
||||
"dcmjs": "^0.29.12",
|
||||
"dicom-parser": "^1.8.21",
|
||||
"hammerjs": "^2.0.8",
|
||||
"prop-types": "^15.6.2",
|
||||
@@ -52,11 +54,11 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@cornerstonejs/adapters": "^1.19.4",
|
||||
"@cornerstonejs/core": "^1.19.4",
|
||||
"@cornerstonejs/streaming-image-volume-loader": "^1.19.4",
|
||||
"@cornerstonejs/tools": "^1.19.4",
|
||||
"@kitware/vtk.js": "27.3.1",
|
||||
"@cornerstonejs/adapters": "^1.66.7",
|
||||
"@cornerstonejs/core": "^1.66.7",
|
||||
"@cornerstonejs/streaming-image-volume-loader": "^1.66.7",
|
||||
"@cornerstonejs/tools": "^1.66.7",
|
||||
"@kitware/vtk.js": "29.7.0",
|
||||
"html2canvas": "^1.4.1",
|
||||
"lodash.debounce": "4.0.8",
|
||||
"lodash.merge": "^4.6.2",
|
||||
|
||||
@@ -21,6 +21,7 @@ import getSOPInstanceAttributes from '../utils/measurementServiceMappings/utils/
|
||||
import CornerstoneServices from '../types/CornerstoneServices';
|
||||
import CinePlayer from '../components/CinePlayer';
|
||||
import { Types } from '@ohif/core';
|
||||
import { LutPresentation, PositionPresentation } from '../types/Presentation';
|
||||
|
||||
const STACK = 'stack';
|
||||
|
||||
@@ -101,7 +102,6 @@ const OHIFCornerstoneViewport = React.memo(props => {
|
||||
viewportOptions,
|
||||
displaySetOptions,
|
||||
servicesManager,
|
||||
commandsManager,
|
||||
onElementEnabled,
|
||||
onElementDisabled,
|
||||
isJumpToMeasurementDisabled,
|
||||
@@ -175,6 +175,13 @@ const OHIFCornerstoneViewport = React.memo(props => {
|
||||
|
||||
syncGroupService.addViewportToSyncGroup(viewportId, renderingEngineId, syncGroups);
|
||||
|
||||
const synchronizersStore = stateSyncService.getState().synchronizersStore;
|
||||
|
||||
if (synchronizersStore?.[viewportId]?.length) {
|
||||
// If the viewport used to have a synchronizer, re apply it again
|
||||
_rehydrateSynchronizers(synchronizersStore, viewportId, syncGroupService);
|
||||
}
|
||||
|
||||
if (onElementEnabled) {
|
||||
onElementEnabled(evt);
|
||||
}
|
||||
@@ -197,13 +204,18 @@ const OHIFCornerstoneViewport = React.memo(props => {
|
||||
return;
|
||||
}
|
||||
|
||||
cleanUpServices(viewportInfo);
|
||||
cornerstoneViewportService.storePresentation({ viewportId });
|
||||
|
||||
// This should be done after the store presentation since synchronizers
|
||||
// will get cleaned up and they need the viewportInfo to be present
|
||||
cleanUpServices(viewportInfo);
|
||||
|
||||
if (onElementDisabled) {
|
||||
onElementDisabled(viewportInfo);
|
||||
}
|
||||
|
||||
cornerstoneViewportService.disableElement(viewportId);
|
||||
|
||||
eventTarget.removeEventListener(Enums.Events.ELEMENT_ENABLED, elementEnabledHandler);
|
||||
};
|
||||
}, []);
|
||||
@@ -265,7 +277,10 @@ const OHIFCornerstoneViewport = React.memo(props => {
|
||||
// The presentation state will have been stored previously by closing
|
||||
// a viewport. Otherwise, this viewport will be unchanged and the
|
||||
// presentation information will be directly carried over.
|
||||
const { lutPresentationStore, positionPresentationStore } = stateSyncService.getState();
|
||||
const state = stateSyncService.getState();
|
||||
const lutPresentationStore = state.lutPresentationStore as LutPresentation;
|
||||
const positionPresentationStore = state.positionPresentationStore as PositionPresentation;
|
||||
|
||||
const { presentationIds } = viewportOptions;
|
||||
const presentations = {
|
||||
positionPresentation: positionPresentationStore[presentationIds?.positionPresentationId],
|
||||
@@ -348,8 +363,6 @@ const OHIFCornerstoneViewport = React.memo(props => {
|
||||
<React.Fragment>
|
||||
<div className="viewport-wrapper">
|
||||
<ReactResizeDetector
|
||||
refreshMode="debounce"
|
||||
refreshRate={50} // Wait 50 ms after last move to render
|
||||
onResize={onResize}
|
||||
targetRef={elementRef.current}
|
||||
/>
|
||||
@@ -547,6 +560,58 @@ function _jumpToMeasurement(
|
||||
}
|
||||
}
|
||||
|
||||
function _rehydrateSynchronizers(
|
||||
synchronizersStore: { [key: string]: unknown },
|
||||
viewportId: string,
|
||||
syncGroupService: any
|
||||
) {
|
||||
synchronizersStore[viewportId].forEach(synchronizerObj => {
|
||||
if (!synchronizerObj.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { id, sourceViewports, targetViewports } = synchronizerObj;
|
||||
|
||||
const synchronizer = syncGroupService.getSynchronizer(id);
|
||||
|
||||
if (!synchronizer) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sourceViewportInfo = sourceViewports.find(
|
||||
sourceViewport => sourceViewport.viewportId === viewportId
|
||||
);
|
||||
|
||||
const targetViewportInfo = targetViewports.find(
|
||||
targetViewport => targetViewport.viewportId === viewportId
|
||||
);
|
||||
|
||||
const isSourceViewportInSynchronizer = synchronizer
|
||||
.getSourceViewports()
|
||||
.find(sourceViewport => sourceViewport.viewportId === viewportId);
|
||||
|
||||
const isTargetViewportInSynchronizer = synchronizer
|
||||
.getTargetViewports()
|
||||
.find(targetViewport => targetViewport.viewportId === viewportId);
|
||||
|
||||
// if the viewport was previously a source viewport, add it again
|
||||
if (sourceViewportInfo && !isSourceViewportInSynchronizer) {
|
||||
synchronizer.addSource({
|
||||
viewportId: sourceViewportInfo.viewportId,
|
||||
renderingEngineId: sourceViewportInfo.renderingEngineId,
|
||||
});
|
||||
}
|
||||
|
||||
// if the viewport was previously a target viewport, add it again
|
||||
if (targetViewportInfo && !isTargetViewportInSynchronizer) {
|
||||
synchronizer.addTarget({
|
||||
viewportId: targetViewportInfo.viewportId,
|
||||
renderingEngineId: targetViewportInfo.renderingEngineId,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Component displayName
|
||||
OHIFCornerstoneViewport.displayName = 'OHIFCornerstoneViewport';
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ import {
|
||||
StackViewport,
|
||||
VolumeViewport,
|
||||
utilities as csUtils,
|
||||
Types as CoreTypes,
|
||||
BaseVolumeViewport,
|
||||
} from '@cornerstonejs/core';
|
||||
import {
|
||||
ToolGroupManager,
|
||||
@@ -11,10 +13,11 @@ import {
|
||||
ReferenceLinesTool,
|
||||
} from '@cornerstonejs/tools';
|
||||
import { Types as OhifTypes } from '@ohif/core';
|
||||
import { vec3, mat4 } from 'gl-matrix';
|
||||
|
||||
import CornerstoneViewportDownloadForm from './utils/CornerstoneViewportDownloadForm';
|
||||
import callInputDialog from './utils/callInputDialog';
|
||||
import toggleStackImageSync from './utils/stackSync/toggleStackImageSync';
|
||||
import toggleImageSliceSync from './utils/imageSliceSync/toggleImageSliceSync';
|
||||
import { getFirstAnnotationSelected } from './utils/measurementServiceMappings/utils/selection';
|
||||
import getActiveViewportEnabledElement from './utils/getActiveViewportEnabledElement';
|
||||
import { CornerstoneServices } from './types';
|
||||
@@ -391,8 +394,16 @@ function commandsModule({
|
||||
|
||||
const { viewport } = enabledElement;
|
||||
|
||||
if (viewport instanceof StackViewport) {
|
||||
const { rotation: currentRotation } = viewport.getProperties();
|
||||
if (viewport instanceof BaseVolumeViewport) {
|
||||
const camera = viewport.getCamera();
|
||||
const rotAngle = (rotation * Math.PI) / 180;
|
||||
const rotMat = mat4.identity(new Float32Array(16));
|
||||
mat4.rotate(rotMat, rotMat, rotAngle, camera.viewPlaneNormal);
|
||||
const rotatedViewUp = vec3.transformMat4(vec3.create(), camera.viewUp, rotMat);
|
||||
viewport.setCamera({ viewUp: rotatedViewUp as CoreTypes.Point3 });
|
||||
viewport.render();
|
||||
} else if (viewport.getRotation !== undefined) {
|
||||
const currentRotation = viewport.getRotation();
|
||||
const newRotation = (currentRotation + rotation) % 360;
|
||||
viewport.setProperties({ rotation: newRotation });
|
||||
viewport.render();
|
||||
@@ -456,13 +467,8 @@ function commandsModule({
|
||||
|
||||
const { viewport } = enabledElement;
|
||||
|
||||
if (viewport instanceof StackViewport) {
|
||||
viewport.resetProperties();
|
||||
viewport.resetCamera();
|
||||
} else {
|
||||
// Todo: add reset properties for volume viewport
|
||||
viewport.resetCamera();
|
||||
}
|
||||
viewport.resetProperties?.();
|
||||
viewport.resetCamera();
|
||||
|
||||
viewport.render();
|
||||
},
|
||||
@@ -560,8 +566,8 @@ function commandsModule({
|
||||
viewportGridService.setActiveViewportId(viewportIds[nextViewportIndex] as string);
|
||||
},
|
||||
|
||||
toggleStackImageSync: ({ toggledState }) => {
|
||||
toggleStackImageSync({
|
||||
toggleImageSliceSync: ({ toggledState }) => {
|
||||
toggleImageSliceSync({
|
||||
servicesManager,
|
||||
toggledState,
|
||||
});
|
||||
@@ -585,6 +591,23 @@ function commandsModule({
|
||||
storePresentation: ({ viewportId }) => {
|
||||
cornerstoneViewportService.storePresentation({ viewportId });
|
||||
},
|
||||
|
||||
attachProtocolViewportDataListener: ({ protocol, stageIndex }) => {
|
||||
const EVENT = cornerstoneViewportService.EVENTS.VIEWPORT_DATA_CHANGED;
|
||||
const command = protocol.callbacks.onViewportDataInitialized;
|
||||
const numPanes = protocol.stages?.[stageIndex]?.viewports.length ?? 1;
|
||||
let numPanesWithData = 0;
|
||||
const { unsubscribe } = cornerstoneViewportService.subscribe(EVENT, evt => {
|
||||
numPanesWithData++;
|
||||
|
||||
if (numPanesWithData === numPanes) {
|
||||
commandsManager.run(...command);
|
||||
|
||||
// Unsubscribe from the event
|
||||
unsubscribe(EVENT);
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
const definitions = {
|
||||
@@ -611,7 +634,6 @@ function commandsModule({
|
||||
storeContexts: [],
|
||||
options: {},
|
||||
},
|
||||
|
||||
deleteMeasurement: {
|
||||
commandFn: actions.deleteMeasurement,
|
||||
},
|
||||
@@ -704,8 +726,8 @@ function commandsModule({
|
||||
setViewportColormap: {
|
||||
commandFn: actions.setViewportColormap,
|
||||
},
|
||||
toggleStackImageSync: {
|
||||
commandFn: actions.toggleStackImageSync,
|
||||
toggleImageSliceSync: {
|
||||
commandFn: actions.toggleImageSliceSync,
|
||||
},
|
||||
setSourceViewportForReferenceLinesTool: {
|
||||
commandFn: actions.setSourceViewportForReferenceLinesTool,
|
||||
@@ -719,6 +741,9 @@ function commandsModule({
|
||||
cleanUpCrosshairs: {
|
||||
commandFn: actions.cleanUpCrosshairs,
|
||||
},
|
||||
attachProtocolViewportDataListener: {
|
||||
commandFn: actions.attachProtocolViewportDataListener,
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { CinePlayer, useCine, useViewportGrid } from '@ohif/ui';
|
||||
import { Enums, eventTarget } from '@cornerstonejs/core';
|
||||
import { useAppConfig } from '@state';
|
||||
|
||||
function WrappedCinePlayer({ enabledVPElement, viewportId, servicesManager }) {
|
||||
const { toolbarService, customizationService } = servicesManager.services;
|
||||
const [{ isCineEnabled, cines }, cineService] = useCine();
|
||||
const [{ activeViewportId }] = useViewportGrid();
|
||||
const {
|
||||
toolbarService,
|
||||
customizationService,
|
||||
displaySetService,
|
||||
viewportGridService,
|
||||
cineService,
|
||||
} = servicesManager.services;
|
||||
const [{ isCineEnabled, cines }] = useCine();
|
||||
const [newStackFrameRate, setNewStackFrameRate] = useState(24);
|
||||
const [appConfig] = useAppConfig();
|
||||
|
||||
const { component: CinePlayerComponent = CinePlayer } =
|
||||
customizationService.get('cinePlayer') ?? {};
|
||||
@@ -45,14 +53,37 @@ function WrappedCinePlayer({ enabledVPElement, viewportId, servicesManager }) {
|
||||
}
|
||||
};
|
||||
|
||||
const newStackCineHandler = useCallback(() => {
|
||||
const { viewports } = viewportGridService.getState();
|
||||
const { displaySetInstanceUIDs } = viewports.get(viewportId);
|
||||
|
||||
let frameRate = 24;
|
||||
let isPlaying = cines[viewportId].isPlaying;
|
||||
displaySetInstanceUIDs.forEach(displaySetInstanceUID => {
|
||||
const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
|
||||
if (displaySet.FrameRate) {
|
||||
// displaySet.FrameRate corresponds to DICOM tag (0018,1063) which is defined as the the frame time in milliseconds
|
||||
// So a bit of math to get the actual frame rate.
|
||||
frameRate = Math.round(1000 / displaySet.FrameRate);
|
||||
isPlaying ||= !!appConfig.autoPlayCine;
|
||||
}
|
||||
});
|
||||
|
||||
if (isPlaying) {
|
||||
cineService.setIsCineEnabled(isPlaying);
|
||||
}
|
||||
cineService.setCine({ id: viewportId, isPlaying, frameRate });
|
||||
setNewStackFrameRate(frameRate);
|
||||
}, [cineService, displaySetService, viewportId, viewportGridService, cines]);
|
||||
|
||||
useEffect(() => {
|
||||
eventTarget.addEventListener(Enums.Events.STACK_VIEWPORT_NEW_STACK, cineHandler);
|
||||
eventTarget.addEventListener(Enums.Events.STACK_VIEWPORT_NEW_STACK, newStackCineHandler);
|
||||
|
||||
return () => {
|
||||
cineService.setCine({ id: viewportId, isPlaying: false });
|
||||
eventTarget.removeEventListener(Enums.Events.STACK_VIEWPORT_NEW_STACK, cineHandler);
|
||||
eventTarget.removeEventListener(Enums.Events.STACK_VIEWPORT_NEW_STACK, newStackCineHandler);
|
||||
};
|
||||
}, [enabledVPElement]);
|
||||
}, [enabledVPElement, newStackCineHandler]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!cines || !cines[viewportId] || !enabledVPElement) {
|
||||
@@ -75,17 +106,18 @@ function WrappedCinePlayer({ enabledVPElement, viewportId, servicesManager }) {
|
||||
isCineEnabled && (
|
||||
<CinePlayerComponent
|
||||
className="absolute left-1/2 bottom-3 -translate-x-1/2"
|
||||
frameRate={newStackFrameRate}
|
||||
isPlaying={isPlaying}
|
||||
onClose={handleCineClose}
|
||||
onPlayPauseChange={isPlaying =>
|
||||
cineService.setCine({
|
||||
id: activeViewportId,
|
||||
id: viewportId,
|
||||
isPlaying,
|
||||
})
|
||||
}
|
||||
onFrameRateChange={frameRate =>
|
||||
cineService.setCine({
|
||||
id: activeViewportId,
|
||||
id: viewportId,
|
||||
frameRate,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,295 +1,10 @@
|
||||
import { Types } from '@ohif/core';
|
||||
|
||||
const mpr: Types.HangingProtocol.Protocol = {
|
||||
id: 'mpr',
|
||||
name: 'Multi-Planar Reconstruction',
|
||||
locked: true,
|
||||
createdDate: '2021-02-23',
|
||||
modifiedDate: '2023-08-15',
|
||||
availableTo: {},
|
||||
editableBy: {},
|
||||
// Unknown number of priors referenced - so just match any study
|
||||
numberOfPriorsReferenced: 0,
|
||||
protocolMatchingRules: [],
|
||||
imageLoadStrategy: 'nth',
|
||||
callbacks: {
|
||||
// Switches out of MPR mode when the layout change button is used
|
||||
onLayoutChange: [
|
||||
{
|
||||
commandName: 'toggleHangingProtocol',
|
||||
commandOptions: { protocolId: 'mpr' },
|
||||
context: 'DEFAULT',
|
||||
},
|
||||
],
|
||||
// Turns off crosshairs when switching out of MPR mode
|
||||
onProtocolExit: [
|
||||
{
|
||||
commandName: 'cleanUpCrosshairs',
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySetSelectors: {
|
||||
activeDisplaySet: {
|
||||
seriesMatchingRules: [
|
||||
{
|
||||
weight: 1,
|
||||
attribute: 'isReconstructable',
|
||||
constraint: {
|
||||
equals: {
|
||||
value: true,
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
stages: [
|
||||
{
|
||||
name: 'MPR 1x3',
|
||||
viewportStructure: {
|
||||
layoutType: 'grid',
|
||||
properties: {
|
||||
rows: 1,
|
||||
columns: 3,
|
||||
layoutOptions: [
|
||||
{
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 1 / 3,
|
||||
height: 1,
|
||||
},
|
||||
{
|
||||
x: 1 / 3,
|
||||
y: 0,
|
||||
width: 1 / 3,
|
||||
height: 1,
|
||||
},
|
||||
{
|
||||
x: 2 / 3,
|
||||
y: 0,
|
||||
width: 1 / 3,
|
||||
height: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
viewports: [
|
||||
{
|
||||
viewportOptions: {
|
||||
viewportId: 'mpr-axial',
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'axial',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'activeDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
viewportId: 'mpr-sagittal',
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'sagittal',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'activeDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
viewportId: 'mpr-coronal',
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'coronal',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'activeDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const mprAnd3DVolumeViewport = {
|
||||
id: 'mprAnd3DVolumeViewport',
|
||||
locked: true,
|
||||
name: 'mpr',
|
||||
createdDate: '2023-03-15T10:29:44.894Z',
|
||||
modifiedDate: '2023-03-15T10:29:44.894Z',
|
||||
availableTo: {},
|
||||
editableBy: {},
|
||||
protocolMatchingRules: [],
|
||||
imageLoadStrategy: 'interleaveCenter',
|
||||
displaySetSelectors: {
|
||||
mprDisplaySet: {
|
||||
seriesMatchingRules: [
|
||||
{
|
||||
weight: 1,
|
||||
attribute: 'isReconstructable',
|
||||
constraint: {
|
||||
equals: {
|
||||
value: true,
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
attribute: 'Modality',
|
||||
constraint: {
|
||||
equals: {
|
||||
value: 'CT',
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
stages: [
|
||||
{
|
||||
id: 'mpr3Stage',
|
||||
name: 'mpr',
|
||||
viewportStructure: {
|
||||
layoutType: 'grid',
|
||||
properties: {
|
||||
rows: 2,
|
||||
columns: 2,
|
||||
},
|
||||
},
|
||||
viewports: [
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'axial',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'volume3d',
|
||||
viewportType: 'volume3d',
|
||||
orientation: 'coronal',
|
||||
customViewportProps: {
|
||||
hideOverlays: true,
|
||||
},
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
options: {
|
||||
displayPreset: 'CT-Bone',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'coronal',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'sagittal',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
import { fourUp } from './hps/fourUp';
|
||||
import { main3D } from './hps/main3D';
|
||||
import { mpr } from './hps/mpr';
|
||||
import { mprAnd3DVolumeViewport } from './hps/mprAnd3DVolumeViewport';
|
||||
import { only3D } from './hps/only3D';
|
||||
import { primary3D } from './hps/primary3D';
|
||||
import { primaryAxial } from './hps/primaryAxial';
|
||||
|
||||
function getHangingProtocolModule() {
|
||||
return [
|
||||
@@ -301,6 +16,26 @@ function getHangingProtocolModule() {
|
||||
name: mprAnd3DVolumeViewport.id,
|
||||
protocol: mprAnd3DVolumeViewport,
|
||||
},
|
||||
{
|
||||
name: fourUp.id,
|
||||
protocol: fourUp,
|
||||
},
|
||||
{
|
||||
name: main3D.id,
|
||||
protocol: main3D,
|
||||
},
|
||||
{
|
||||
name: primaryAxial.id,
|
||||
protocol: primaryAxial,
|
||||
},
|
||||
{
|
||||
name: only3D.id,
|
||||
protocol: only3D,
|
||||
},
|
||||
{
|
||||
name: primary3D.id,
|
||||
protocol: primary3D,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
export const fourUp = {
|
||||
id: 'fourUp',
|
||||
locked: true,
|
||||
name: 'fourUp',
|
||||
createdDate: '2023-03-15T10:29:44.894Z',
|
||||
modifiedDate: '2023-03-15T10:29:44.894Z',
|
||||
availableTo: {},
|
||||
editableBy: {},
|
||||
protocolMatchingRules: [],
|
||||
imageLoadStrategy: 'interleaveCenter',
|
||||
displaySetSelectors: {
|
||||
mprDisplaySet: {
|
||||
seriesMatchingRules: [
|
||||
{
|
||||
weight: 1,
|
||||
attribute: 'isReconstructable',
|
||||
constraint: {
|
||||
equals: {
|
||||
value: true,
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
stages: [
|
||||
{
|
||||
id: 'fourUpStage',
|
||||
name: 'fourUp',
|
||||
viewportStructure: {
|
||||
layoutType: 'grid',
|
||||
properties: {
|
||||
rows: 2,
|
||||
columns: 2,
|
||||
},
|
||||
},
|
||||
viewports: [
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'axial',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'volume3d',
|
||||
viewportType: 'volume3d',
|
||||
orientation: 'coronal',
|
||||
customViewportProps: {
|
||||
hideOverlays: true,
|
||||
},
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
options: {
|
||||
// ToDo: choose appropriate preset
|
||||
displayPreset: 'CT-Bone',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'coronal',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'sagittal',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,156 @@
|
||||
export const main3D = {
|
||||
id: 'main3D',
|
||||
locked: true,
|
||||
name: 'main3D',
|
||||
createdDate: '2023-03-15T10:29:44.894Z',
|
||||
modifiedDate: '2023-03-15T10:29:44.894Z',
|
||||
availableTo: {},
|
||||
editableBy: {},
|
||||
protocolMatchingRules: [],
|
||||
imageLoadStrategy: 'interleaveCenter',
|
||||
displaySetSelectors: {
|
||||
mprDisplaySet: {
|
||||
seriesMatchingRules: [
|
||||
{
|
||||
weight: 1,
|
||||
attribute: 'isReconstructable',
|
||||
constraint: {
|
||||
equals: {
|
||||
value: true,
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
stages: [
|
||||
{
|
||||
id: 'main3DStage',
|
||||
name: 'main3D',
|
||||
viewportStructure: {
|
||||
layoutType: 'grid',
|
||||
properties: {
|
||||
rows: 2,
|
||||
columns: 3,
|
||||
layoutOptions: [
|
||||
{
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 1,
|
||||
height: 1 / 2,
|
||||
},
|
||||
{
|
||||
x: 0,
|
||||
y: 1 / 2,
|
||||
width: 1 / 3,
|
||||
height: 1 / 2,
|
||||
},
|
||||
{
|
||||
x: 1 / 3,
|
||||
y: 1 / 2,
|
||||
width: 1 / 3,
|
||||
height: 1 / 2,
|
||||
},
|
||||
{
|
||||
x: 2 / 3,
|
||||
y: 1 / 2,
|
||||
width: 1 / 3,
|
||||
height: 1 / 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
viewports: [
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'volume3d',
|
||||
viewportType: 'volume3d',
|
||||
orientation: 'coronal',
|
||||
customViewportProps: {
|
||||
hideOverlays: true,
|
||||
},
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
options: {
|
||||
// ToDo: choose appropriate preset
|
||||
displayPreset: 'CT-Bone',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'axial',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'coronal',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'sagittal',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,153 @@
|
||||
import { Types } from '@ohif/core';
|
||||
|
||||
export const mpr: Types.HangingProtocol.Protocol = {
|
||||
id: 'mpr',
|
||||
name: 'Multi-Planar Reconstruction',
|
||||
locked: true,
|
||||
createdDate: '2021-02-23',
|
||||
modifiedDate: '2023-08-15',
|
||||
availableTo: {},
|
||||
editableBy: {},
|
||||
// Unknown number of priors referenced - so just match any study
|
||||
numberOfPriorsReferenced: 0,
|
||||
protocolMatchingRules: [],
|
||||
imageLoadStrategy: 'nth',
|
||||
callbacks: {
|
||||
// Switches out of MPR mode when the layout change button is used
|
||||
onLayoutChange: [
|
||||
{
|
||||
commandName: 'toggleHangingProtocol',
|
||||
commandOptions: { protocolId: 'mpr' },
|
||||
context: 'DEFAULT',
|
||||
},
|
||||
],
|
||||
// Turns off crosshairs when switching out of MPR mode
|
||||
onProtocolExit: [
|
||||
{
|
||||
commandName: 'cleanUpCrosshairs',
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySetSelectors: {
|
||||
activeDisplaySet: {
|
||||
seriesMatchingRules: [
|
||||
{
|
||||
weight: 1,
|
||||
attribute: 'isReconstructable',
|
||||
constraint: {
|
||||
equals: {
|
||||
value: true,
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
stages: [
|
||||
{
|
||||
name: 'MPR 1x3',
|
||||
viewportStructure: {
|
||||
layoutType: 'grid',
|
||||
properties: {
|
||||
rows: 1,
|
||||
columns: 3,
|
||||
layoutOptions: [
|
||||
{
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 1 / 3,
|
||||
height: 1,
|
||||
},
|
||||
{
|
||||
x: 1 / 3,
|
||||
y: 0,
|
||||
width: 1 / 3,
|
||||
height: 1,
|
||||
},
|
||||
{
|
||||
x: 2 / 3,
|
||||
y: 0,
|
||||
width: 1 / 3,
|
||||
height: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
viewports: [
|
||||
{
|
||||
viewportOptions: {
|
||||
viewportId: 'mpr-axial',
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'axial',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'activeDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
viewportId: 'mpr-sagittal',
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'sagittal',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'activeDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
viewportId: 'mpr-coronal',
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'coronal',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'activeDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,138 @@
|
||||
export const mprAnd3DVolumeViewport = {
|
||||
id: 'mprAnd3DVolumeViewport',
|
||||
locked: true,
|
||||
name: 'mpr',
|
||||
createdDate: '2023-03-15T10:29:44.894Z',
|
||||
modifiedDate: '2023-03-15T10:29:44.894Z',
|
||||
availableTo: {},
|
||||
editableBy: {},
|
||||
protocolMatchingRules: [],
|
||||
imageLoadStrategy: 'interleaveCenter',
|
||||
displaySetSelectors: {
|
||||
mprDisplaySet: {
|
||||
seriesMatchingRules: [
|
||||
{
|
||||
weight: 1,
|
||||
attribute: 'isReconstructable',
|
||||
constraint: {
|
||||
equals: {
|
||||
value: true,
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
attribute: 'Modality',
|
||||
constraint: {
|
||||
equals: {
|
||||
value: 'CT',
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
stages: [
|
||||
{
|
||||
id: 'mpr3Stage',
|
||||
name: 'mpr',
|
||||
viewportStructure: {
|
||||
layoutType: 'grid',
|
||||
properties: {
|
||||
rows: 2,
|
||||
columns: 2,
|
||||
},
|
||||
},
|
||||
viewports: [
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'axial',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'volume3d',
|
||||
viewportType: 'volume3d',
|
||||
orientation: 'coronal',
|
||||
customViewportProps: {
|
||||
hideOverlays: true,
|
||||
},
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
options: {
|
||||
displayPreset: 'CT-Bone',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'coronal',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'sagittal',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
export const only3D = {
|
||||
id: 'only3D',
|
||||
locked: true,
|
||||
name: 'only3D',
|
||||
createdDate: '2023-03-15T10:29:44.894Z',
|
||||
modifiedDate: '2023-03-15T10:29:44.894Z',
|
||||
availableTo: {},
|
||||
editableBy: {},
|
||||
protocolMatchingRules: [],
|
||||
imageLoadStrategy: 'interleaveCenter',
|
||||
displaySetSelectors: {
|
||||
mprDisplaySet: {
|
||||
seriesMatchingRules: [
|
||||
{
|
||||
weight: 1,
|
||||
attribute: 'isReconstructable',
|
||||
constraint: {
|
||||
equals: {
|
||||
value: true,
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
stages: [
|
||||
{
|
||||
id: 'only3DStage',
|
||||
name: 'only3D',
|
||||
viewportStructure: {
|
||||
layoutType: 'grid',
|
||||
properties: {
|
||||
rows: 1,
|
||||
columns: 1,
|
||||
},
|
||||
},
|
||||
viewports: [
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'volume3d',
|
||||
viewportType: 'volume3d',
|
||||
orientation: 'coronal',
|
||||
customViewportProps: {
|
||||
hideOverlays: true,
|
||||
},
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
options: {
|
||||
// ToDo: choose appropriate preset
|
||||
displayPreset: 'CT-Bone',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,156 @@
|
||||
export const primary3D = {
|
||||
id: 'primary3D',
|
||||
locked: true,
|
||||
name: 'primary3D',
|
||||
createdDate: '2023-03-15T10:29:44.894Z',
|
||||
modifiedDate: '2023-03-15T10:29:44.894Z',
|
||||
availableTo: {},
|
||||
editableBy: {},
|
||||
protocolMatchingRules: [],
|
||||
imageLoadStrategy: 'interleaveCenter',
|
||||
displaySetSelectors: {
|
||||
mprDisplaySet: {
|
||||
seriesMatchingRules: [
|
||||
{
|
||||
weight: 1,
|
||||
attribute: 'isReconstructable',
|
||||
constraint: {
|
||||
equals: {
|
||||
value: true,
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
stages: [
|
||||
{
|
||||
id: 'primary3DStage',
|
||||
name: 'primary3D',
|
||||
viewportStructure: {
|
||||
layoutType: 'grid',
|
||||
properties: {
|
||||
rows: 3,
|
||||
columns: 3,
|
||||
layoutOptions: [
|
||||
{
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 2 / 3,
|
||||
height: 1,
|
||||
},
|
||||
{
|
||||
x: 2 / 3,
|
||||
y: 0,
|
||||
width: 1 / 3,
|
||||
height: 1 / 3,
|
||||
},
|
||||
{
|
||||
x: 2 / 3,
|
||||
y: 1 / 3,
|
||||
width: 1 / 3,
|
||||
height: 1 / 3,
|
||||
},
|
||||
{
|
||||
x: 2 / 3,
|
||||
y: 2 / 3,
|
||||
width: 1 / 3,
|
||||
height: 1 / 3,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
viewports: [
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'volume3d',
|
||||
viewportType: 'volume3d',
|
||||
orientation: 'coronal',
|
||||
customViewportProps: {
|
||||
hideOverlays: true,
|
||||
},
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
options: {
|
||||
// ToDo: choose appropriate preset
|
||||
displayPreset: 'CT-Bone',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'axial',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'coronal',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'sagittal',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,131 @@
|
||||
export const primaryAxial = {
|
||||
id: 'primaryAxial',
|
||||
locked: true,
|
||||
name: 'primaryAxial',
|
||||
createdDate: '2023-03-15T10:29:44.894Z',
|
||||
modifiedDate: '2023-03-15T10:29:44.894Z',
|
||||
availableTo: {},
|
||||
editableBy: {},
|
||||
protocolMatchingRules: [],
|
||||
imageLoadStrategy: 'interleaveCenter',
|
||||
displaySetSelectors: {
|
||||
mprDisplaySet: {
|
||||
seriesMatchingRules: [
|
||||
{
|
||||
weight: 1,
|
||||
attribute: 'isReconstructable',
|
||||
constraint: {
|
||||
equals: {
|
||||
value: true,
|
||||
},
|
||||
},
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
stages: [
|
||||
{
|
||||
id: 'primaryAxialStage',
|
||||
name: 'primaryAxial',
|
||||
viewportStructure: {
|
||||
layoutType: 'grid',
|
||||
properties: {
|
||||
rows: 2,
|
||||
columns: 3,
|
||||
layoutOptions: [
|
||||
{
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 2 / 3,
|
||||
height: 1,
|
||||
},
|
||||
{
|
||||
x: 2 / 3,
|
||||
y: 0,
|
||||
width: 1 / 3,
|
||||
height: 1 / 2,
|
||||
},
|
||||
{
|
||||
x: 2 / 3,
|
||||
y: 1 / 2,
|
||||
width: 1 / 3,
|
||||
height: 1 / 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
viewports: [
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'axial',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'sagittal',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
viewportOptions: {
|
||||
toolGroupId: 'mpr',
|
||||
viewportType: 'volume',
|
||||
orientation: 'coronal',
|
||||
initialImageOptions: {
|
||||
preset: 'middle',
|
||||
},
|
||||
syncGroups: [
|
||||
{
|
||||
type: 'voi',
|
||||
id: 'mpr',
|
||||
source: true,
|
||||
target: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
displaySets: [
|
||||
{
|
||||
id: 'mprDisplaySet',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -29,6 +29,7 @@ import { id } from './id';
|
||||
import * as csWADOImageLoader from './initWADOImageLoader.js';
|
||||
import { measurementMappingUtils } from './utils/measurementServiceMappings';
|
||||
import type { PublicViewportOptions } from './services/ViewportService/Viewport';
|
||||
import ImageOverlayViewerTool from './tools/ImageOverlayViewerTool';
|
||||
|
||||
const Component = React.lazy(() => {
|
||||
return import(/* webpackPrefetch: true */ './Viewport/OHIFCornerstoneViewport');
|
||||
@@ -140,5 +141,6 @@ export {
|
||||
CornerstoneExtensionTypes as Types,
|
||||
toolNames,
|
||||
getActiveViewportEnabledElement,
|
||||
ImageOverlayViewerTool,
|
||||
};
|
||||
export default cornerstoneExtension;
|
||||
@@ -1,4 +1,4 @@
|
||||
import OHIF, { Types } from '@ohif/core';
|
||||
import OHIF, { Types, errorHandler } from '@ohif/core';
|
||||
import React from 'react';
|
||||
|
||||
import * as cornerstone from '@cornerstonejs/core';
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
metaData,
|
||||
volumeLoader,
|
||||
imageLoadPoolManager,
|
||||
getEnabledElement,
|
||||
Settings,
|
||||
utilities as csUtilities,
|
||||
Enums as csEnums,
|
||||
@@ -59,8 +60,8 @@ export default async function init({
|
||||
|
||||
await cs3DInit({
|
||||
rendering: {
|
||||
preferSizeOverAccuracy: Boolean(appConfig.use16BitDataType),
|
||||
useNorm16Texture: Boolean(appConfig.use16BitDataType),
|
||||
preferSizeOverAccuracy: Boolean(appConfig.preferSizeOverAccuracy),
|
||||
useNorm16Texture: Boolean(appConfig.useNorm16Texture),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -97,6 +98,7 @@ export default async function init({
|
||||
toolbarService,
|
||||
viewportGridService,
|
||||
stateSyncService,
|
||||
syncGroupService,
|
||||
} = servicesManager.services as CornerstoneServices;
|
||||
|
||||
window.services = servicesManager.services;
|
||||
@@ -124,6 +126,9 @@ export default async function init({
|
||||
// an OHIFCornerstoneViewport can be redisplayed with the same LUT
|
||||
stateSyncService.register('lutPresentationStore', { clearOnModeExit: true });
|
||||
|
||||
// Stores synchronizers state to be restored
|
||||
stateSyncService.register('synchronizersStore', { clearOnModeExit: true });
|
||||
|
||||
// Stores a map from `positionPresentationId` to a Presentation object so that
|
||||
// an OHIFCornerstoneViewport can be redisplayed with the same position
|
||||
stateSyncService.register('positionPresentationStore', {
|
||||
@@ -199,6 +204,16 @@ export default async function init({
|
||||
}
|
||||
);
|
||||
|
||||
// resize the cornerstone viewport service when the grid size changes
|
||||
// IMPORTANT: this should happen outside of the OHIFCornerstoneViewport
|
||||
// since it will trigger a rerender of each viewport and each resizing
|
||||
// the offscreen canvas which would result in a performance hit, this should
|
||||
// done only once per grid resize here. Doing it once here, allows us to reduce
|
||||
// the refreshRage(in ms) to 10 from 50. I tried with even 1 or 5 ms it worked fine
|
||||
viewportGridService.subscribe(viewportGridService.EVENTS.GRID_SIZE_CHANGED, () => {
|
||||
cornerstoneViewportService.resize(true);
|
||||
});
|
||||
|
||||
initContextMenu({
|
||||
cornerstoneViewportService,
|
||||
customizationService,
|
||||
@@ -251,6 +266,15 @@ export default async function init({
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Runs error handler for failed requests.
|
||||
* @param event
|
||||
*/
|
||||
const imageLoadFailedHandler = ({ detail }) => {
|
||||
const handler = errorHandler.getHTTPErrorHandler();
|
||||
handler(detail.error);
|
||||
};
|
||||
|
||||
const resetCrosshairs = evt => {
|
||||
const { element } = evt.detail;
|
||||
const { viewportId, renderingEngineId } = cornerstone.getEnabledElement(element);
|
||||
@@ -279,9 +303,12 @@ export default async function init({
|
||||
const { element } = evt.detail;
|
||||
cornerstoneTools.utilities.stackContextPrefetch.enable(element);
|
||||
});
|
||||
eventTarget.addEventListener(EVENTS.IMAGE_LOAD_FAILED, imageLoadFailedHandler);
|
||||
eventTarget.addEventListener(EVENTS.IMAGE_LOAD_ERROR, imageLoadFailedHandler);
|
||||
|
||||
function elementEnabledHandler(evt) {
|
||||
const { element } = evt.detail;
|
||||
|
||||
element.addEventListener(EVENTS.CAMERA_RESET, resetCrosshairs);
|
||||
|
||||
eventTarget.addEventListener(EVENTS.STACK_VIEWPORT_NEW_STACK, toolbarEventListener);
|
||||
@@ -308,8 +335,8 @@ export default async function init({
|
||||
viewportGridService.subscribe(
|
||||
viewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED,
|
||||
activeViewportEventListener
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function CPUModal() {
|
||||
return (
|
||||
|
||||
@@ -49,7 +49,8 @@ export default function initWADOImageLoader(
|
||||
// Until the default is set to true (which is the case for cornerstone3D),
|
||||
// we should set this flag to false.
|
||||
convertFloatPixelDataToInt: false,
|
||||
use16BitDataType: Boolean(appConfig.use16BitDataType),
|
||||
use16BitDataType:
|
||||
Boolean(appConfig.useNorm16Texture) || Boolean(appConfig.preferSizeOverAccuracy),
|
||||
},
|
||||
beforeSend: function (xhr) {
|
||||
//TODO should be removed in the future and request emitted by DicomWebDataSource
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import cloneDeep from 'lodash.clonedeep';
|
||||
|
||||
import { Types as OhifTypes, ServicesManager, PubSubService } from '@ohif/core';
|
||||
import {
|
||||
cache,
|
||||
@@ -7,12 +5,10 @@ import {
|
||||
geometryLoader,
|
||||
eventTarget,
|
||||
getEnabledElementByIds,
|
||||
metaData,
|
||||
utilities as csUtils,
|
||||
volumeLoader,
|
||||
} from '@cornerstonejs/core';
|
||||
import {
|
||||
CONSTANTS as cstConstants,
|
||||
Enums as csToolsEnums,
|
||||
segmentation as cstSegmentation,
|
||||
Types as cstTypes,
|
||||
@@ -24,7 +20,6 @@ import { easeInOutBell, reverseEaseInOutBell } from '../../utils/transitions';
|
||||
import { Segment, Segmentation, SegmentationConfig } from './SegmentationServiceTypes';
|
||||
import { mapROIContoursToRTStructData } from './RTSTRUCT/mapROIContoursToRTStructData';
|
||||
|
||||
const { COLOR_LUT } = cstConstants;
|
||||
const LABELMAP = csToolsEnums.SegmentationRepresentations.Labelmap;
|
||||
const CONTOUR = csToolsEnums.SegmentationRepresentations.Contour;
|
||||
|
||||
@@ -41,7 +36,7 @@ const EVENTS = {
|
||||
SEGMENTATION_CONFIGURATION_CHANGED: 'event::segmentation_configuration_changed',
|
||||
// fired when the active segment is loaded in SEG or RTSTRUCT
|
||||
SEGMENT_LOADING_COMPLETE: 'event::segment_loading_complete',
|
||||
// for all segments
|
||||
// loading completed for all segments
|
||||
SEGMENTATION_LOADING_COMPLETE: 'event::segmentation_loading_complete',
|
||||
};
|
||||
|
||||
@@ -131,7 +126,7 @@ class SegmentationService extends PubSubService {
|
||||
throw new Error('Segment index 0 is reserved for "no label"');
|
||||
}
|
||||
|
||||
const toolGroupId = config.toolGroupId ?? this._getFirstToolGroupId();
|
||||
const toolGroupId = config.toolGroupId ?? this._getApplicableToolGroupId();
|
||||
|
||||
const { segmentationRepresentationUID, segmentation } = this._getSegmentationInfo(
|
||||
segmentationId,
|
||||
@@ -190,7 +185,7 @@ class SegmentationService extends PubSubService {
|
||||
);
|
||||
}
|
||||
|
||||
if (active !== undefined) {
|
||||
if (active === true) {
|
||||
this._setActiveSegment(segmentationId, segmentIndex, suppressEvents);
|
||||
}
|
||||
|
||||
@@ -362,7 +357,7 @@ class SegmentationService extends PubSubService {
|
||||
}
|
||||
|
||||
public setActiveSegmentationForToolGroup(segmentationId: string, toolGroupId?: string): void {
|
||||
toolGroupId = toolGroupId ?? this._getFirstToolGroupId();
|
||||
toolGroupId = toolGroupId ?? this._getApplicableToolGroupId();
|
||||
|
||||
const suppressEvents = false;
|
||||
this._setActiveSegmentationForToolGroup(segmentationId, toolGroupId, suppressEvents);
|
||||
@@ -400,6 +395,23 @@ class SegmentationService extends PubSubService {
|
||||
return segmentations && segmentations.map(m => this.segmentations[Object.keys(m)[0]]);
|
||||
}
|
||||
|
||||
public getActiveSegmentation(): Segmentation {
|
||||
const segmentations = this.getSegmentations();
|
||||
|
||||
return segmentations.find(segmentation => segmentation.isActive);
|
||||
}
|
||||
|
||||
public getActiveSegment() {
|
||||
const activeSegmentation = this.getActiveSegmentation();
|
||||
const { activeSegmentIndex, segments } = activeSegmentation;
|
||||
|
||||
if (activeSegmentIndex === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
return segments[activeSegmentIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get specific segmentation by its id.
|
||||
*
|
||||
@@ -449,15 +461,6 @@ class SegmentationService extends PubSubService {
|
||||
},
|
||||
]);
|
||||
|
||||
// if first segmentation, we can use the default colorLUT, otherwise
|
||||
// we need to generate a new one and use a new colorLUT
|
||||
const colorLUTIndex = 0;
|
||||
if (Object.keys(this.segmentations).length !== 0) {
|
||||
const newColorLUT = this.generateNewColorLUT();
|
||||
const colorLUTIndex = this.getNextColorLUTIndex();
|
||||
cstSegmentation.config.color.addColorLUT(newColorLUT, colorLUTIndex);
|
||||
}
|
||||
|
||||
this.segmentations[segmentationId] = {
|
||||
...segmentation,
|
||||
label: segmentation.label || '',
|
||||
@@ -466,7 +469,6 @@ class SegmentationService extends PubSubService {
|
||||
segmentCount: segmentation.segmentCount ?? 0,
|
||||
isActive: false,
|
||||
isVisible: true,
|
||||
colorLUTIndex,
|
||||
};
|
||||
|
||||
cachedSegmentation = this.segmentations[segmentationId];
|
||||
@@ -543,7 +545,7 @@ class SegmentationService extends PubSubService {
|
||||
volumeId: segmentationId,
|
||||
targetBuffer: {
|
||||
type: 'Uint8Array',
|
||||
sharedArrayBuffer: true,
|
||||
sharedArrayBuffer: window.SharedArrayBuffer,
|
||||
},
|
||||
});
|
||||
const derivedVolumeScalarData = derivedVolume.getScalarData();
|
||||
@@ -913,7 +915,7 @@ class SegmentationService extends PubSubService {
|
||||
}
|
||||
|
||||
const segmentation = this.getSegmentation(segmentationId);
|
||||
toolGroupId = toolGroupId ?? this._getFirstToolGroupId();
|
||||
toolGroupId = toolGroupId ?? this._getApplicableToolGroupId();
|
||||
|
||||
const segmentationRepresentation = this._getSegmentationRepresentation(
|
||||
segmentationId,
|
||||
@@ -964,7 +966,7 @@ class SegmentationService extends PubSubService {
|
||||
volumeId: segmentationId,
|
||||
targetBuffer: {
|
||||
type: 'Uint8Array',
|
||||
sharedArrayBuffer: true,
|
||||
sharedArrayBuffer: window.SharedArrayBuffer,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1021,8 +1023,6 @@ class SegmentationService extends PubSubService {
|
||||
segmentation.hydrated = true;
|
||||
}
|
||||
|
||||
const { colorLUTIndex } = segmentation;
|
||||
|
||||
// Based on the segmentationId, set the colorLUTIndex.
|
||||
const segmentationRepresentationUIDs = await cstSegmentation.addSegmentationRepresentations(
|
||||
toolGroupId,
|
||||
@@ -1041,12 +1041,6 @@ class SegmentationService extends PubSubService {
|
||||
segmentationRepresentationUIDs[0]
|
||||
);
|
||||
|
||||
cstSegmentation.config.color.setColorLUT(
|
||||
toolGroupId,
|
||||
segmentationRepresentationUIDs[0],
|
||||
colorLUTIndex
|
||||
);
|
||||
|
||||
// add the segmentation segments properly
|
||||
for (const segment of segmentation.segments) {
|
||||
if (segment === null || segment === undefined) {
|
||||
@@ -1314,7 +1308,7 @@ class SegmentationService extends PubSubService {
|
||||
if (remainingHydratedSegmentations.length) {
|
||||
const { id } = remainingHydratedSegmentations[0];
|
||||
|
||||
this._setActiveSegmentationForToolGroup(id, this._getFirstToolGroupId(), false);
|
||||
this._setActiveSegmentationForToolGroup(id, this._getApplicableToolGroupId(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1326,7 +1320,7 @@ class SegmentationService extends PubSubService {
|
||||
}
|
||||
|
||||
public getConfiguration = (toolGroupId?: string): SegmentationConfig => {
|
||||
toolGroupId = toolGroupId ?? this._getFirstToolGroupId();
|
||||
toolGroupId = toolGroupId ?? this._getApplicableToolGroupId();
|
||||
|
||||
const brushSize = 1;
|
||||
// const brushSize = cstUtils.segmentation.getBrushSizeForToolGroup(
|
||||
@@ -1514,7 +1508,6 @@ class SegmentationService extends PubSubService {
|
||||
segments: [],
|
||||
isVisible: true,
|
||||
isActive: false,
|
||||
colorLUTIndex: 0,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1621,7 +1614,7 @@ class SegmentationService extends PubSubService {
|
||||
throw new Error(`Segment ${segmentIndex} not yet added to segmentation: ${segmentationId}`);
|
||||
}
|
||||
|
||||
toolGroupId = toolGroupId ?? this._getFirstToolGroupId();
|
||||
toolGroupId = toolGroupId ?? this._getApplicableToolGroupId();
|
||||
|
||||
const segmentationRepresentation = this._getSegmentationRepresentation(
|
||||
segmentationId,
|
||||
@@ -1715,7 +1708,7 @@ class SegmentationService extends PubSubService {
|
||||
toolGroupId?: string,
|
||||
suppressEvents = false
|
||||
) {
|
||||
toolGroupId = toolGroupId ?? this._getFirstToolGroupId();
|
||||
toolGroupId = toolGroupId ?? this._getApplicableToolGroupId();
|
||||
|
||||
const { segmentationRepresentationUID, segmentation } = this._getSegmentationInfo(
|
||||
segmentationId,
|
||||
@@ -1774,7 +1767,7 @@ class SegmentationService extends PubSubService {
|
||||
throw new Error(`Segment ${segmentIndex} not yet added to segmentation: ${segmentationId}`);
|
||||
}
|
||||
|
||||
toolGroupId = toolGroupId ?? this._getFirstToolGroupId();
|
||||
toolGroupId = toolGroupId ?? this._getApplicableToolGroupId();
|
||||
|
||||
const segmentationRepresentation = this._getSegmentationRepresentation(
|
||||
segmentationId,
|
||||
@@ -2091,30 +2084,23 @@ class SegmentationService extends PubSubService {
|
||||
}
|
||||
}
|
||||
|
||||
private _getFirstToolGroupId = () => {
|
||||
const { toolGroupService } = this.servicesManager.services;
|
||||
const toolGroupIds = toolGroupService.getToolGroupIds();
|
||||
private _getApplicableToolGroupId = () => {
|
||||
const { toolGroupService, viewportGridService, cornerstoneViewportService } =
|
||||
this.servicesManager.services;
|
||||
|
||||
return toolGroupIds[0];
|
||||
};
|
||||
const viewportInfo = cornerstoneViewportService.getViewportInfo(
|
||||
viewportGridService.getActiveViewportId()
|
||||
);
|
||||
|
||||
private getNextColorLUTIndex = (): number => {
|
||||
let i = 0;
|
||||
while (true) {
|
||||
if (cstSegmentation.state.getColorLUT(i) === undefined) {
|
||||
return i;
|
||||
}
|
||||
if (!viewportInfo) {
|
||||
const toolGroupIds = toolGroupService.getToolGroupIds();
|
||||
|
||||
i++;
|
||||
return toolGroupIds[0];
|
||||
}
|
||||
|
||||
return viewportInfo.getToolGroupId();
|
||||
};
|
||||
|
||||
private generateNewColorLUT() {
|
||||
const newColorLUT = cloneDeep(COLOR_LUT);
|
||||
|
||||
return newColorLUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts object of objects to array.
|
||||
*
|
||||
|
||||
@@ -67,4 +67,4 @@ type SegmentationRepresentationData = {
|
||||
LABELMAP?: LabelmapSegmentationData;
|
||||
};
|
||||
|
||||
export { SegmentationConfig, Segment, Segmentation };
|
||||
export type { SegmentationConfig, Segment, Segmentation };
|
||||
@@ -45,7 +45,7 @@ export default class SyncGroupService {
|
||||
[POSITION]: synchronizers.createCameraPositionSynchronizer,
|
||||
[VOI]: synchronizers.createVOISynchronizer,
|
||||
[ZOOMPAN]: synchronizers.createZoomPanSynchronizer,
|
||||
[STACKIMAGE]: synchronizers.createStackImageSynchronizer,
|
||||
[STACKIMAGE]: synchronizers.createImageSliceSynchronizer,
|
||||
};
|
||||
|
||||
constructor(serviceManager: ServicesManager) {
|
||||
@@ -74,6 +74,10 @@ export default class SyncGroupService {
|
||||
this.synchronizerCreators[type.toLowerCase()] = creator;
|
||||
}
|
||||
|
||||
public getSynchronizer(id: string): Synchronizer | void {
|
||||
return SynchronizerManager.getSynchronizer(id);
|
||||
}
|
||||
|
||||
protected _getOrCreateSynchronizer(
|
||||
type: string,
|
||||
id: string,
|
||||
@@ -121,6 +125,17 @@ export default class SyncGroupService {
|
||||
SynchronizerManager.destroy();
|
||||
}
|
||||
|
||||
public getSynchronizersForViewport(
|
||||
viewportId: string,
|
||||
renderingEngineId: string
|
||||
): Synchronizer[] {
|
||||
return SynchronizerManager.getAllSynchronizers().filter(
|
||||
s =>
|
||||
s.hasSourceViewport(renderingEngineId, viewportId) ||
|
||||
s.hasTargetViewport(renderingEngineId, viewportId)
|
||||
);
|
||||
}
|
||||
|
||||
public removeViewportFromSyncGroup(
|
||||
viewportId: string,
|
||||
renderingEngineId: string,
|
||||
|
||||
+373
-106
@@ -10,6 +10,7 @@ import {
|
||||
VolumeViewport3D,
|
||||
cache,
|
||||
Enums as csEnums,
|
||||
BaseVolumeViewport,
|
||||
} from '@cornerstonejs/core';
|
||||
|
||||
import { utilities as csToolsUtils, Enums as csToolsEnums } from '@cornerstonejs/tools';
|
||||
@@ -17,7 +18,7 @@ import { IViewportService } from './IViewportService';
|
||||
import { RENDERING_ENGINE_ID } from './constants';
|
||||
import ViewportInfo, { DisplaySetOptions, PublicViewportOptions } from './Viewport';
|
||||
import { StackViewportData, VolumeViewportData } from '../../types/CornerstoneCacheService';
|
||||
import { Presentation, Presentations } from '../../types/Presentation';
|
||||
import { LutPresentation, PositionPresentation, Presentations } from '../../types/Presentation';
|
||||
|
||||
import JumpPresets from '../../utils/JumpPresets';
|
||||
|
||||
@@ -44,6 +45,7 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
viewportsById: Map<string, ViewportInfo> = new Map();
|
||||
viewportGridResizeObserver: ResizeObserver | null;
|
||||
viewportsDisplaySets: Map<string, string[]> = new Map();
|
||||
beforeResizePositionPresentations: Map<string, PositionPresentation> = new Map();
|
||||
|
||||
// Some configs
|
||||
enableResizeDetector: true;
|
||||
@@ -51,6 +53,11 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
resizeRefreshMode: 'debounce';
|
||||
servicesManager = null;
|
||||
|
||||
resizeQueue = [];
|
||||
viewportResizeTimer = null;
|
||||
gridResizeDelay = 50;
|
||||
gridResizeTimeOut = null;
|
||||
|
||||
constructor(servicesManager: ServicesManager) {
|
||||
super(EVENTS);
|
||||
this.renderingEngine = null;
|
||||
@@ -94,14 +101,28 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
}
|
||||
|
||||
/**
|
||||
* It triggers the resize on the rendering engine.
|
||||
* It triggers the resize on the rendering engine, and renders the viewports
|
||||
*
|
||||
* @param isGridResize - if the resize is triggered by a grid resize
|
||||
* this is used to avoid double resize of the viewports since if the
|
||||
* grid is resized, all viewports will be resized so there is no need
|
||||
* to resize them individually which will get triggered by their
|
||||
* individual resize observers
|
||||
*/
|
||||
public resize() {
|
||||
const immediate = true;
|
||||
const keepCamera = true;
|
||||
|
||||
this.renderingEngine.resize(immediate, keepCamera);
|
||||
this.renderingEngine.render();
|
||||
public resize(isGridResize = false) {
|
||||
// if there is a grid resize happening, it means the viewport grid
|
||||
// has been manipulated (e.g., panels closed, added, etc.) and we need
|
||||
// to resize all viewports, so we will add a timeout here to make sure
|
||||
// we don't double resize the viewports when viewports in the grid are
|
||||
// resized individually
|
||||
if (isGridResize) {
|
||||
this.performResize();
|
||||
this.resetGridResizeTimeout();
|
||||
this.resizeQueue = [];
|
||||
clearTimeout(this.viewportResizeTimer);
|
||||
} else {
|
||||
this.enqueueViewportResizeRequest();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,74 +159,239 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
this.viewportsDisplaySets.delete(viewportId);
|
||||
}
|
||||
|
||||
public setPresentations(viewport, presentations?: Presentations): void {
|
||||
const properties = presentations?.lutPresentation?.properties;
|
||||
if (properties) {
|
||||
viewport.setProperties(properties);
|
||||
/**
|
||||
* Sets the presentations for a given viewport. Presentations is an object
|
||||
* that can define the lut or position for a viewport.
|
||||
*
|
||||
* @param viewportId - The ID of the viewport.
|
||||
* @param presentations - The presentations to apply to the viewport.
|
||||
*/
|
||||
public setPresentations(viewportId: string, presentations?: Presentations): void {
|
||||
const viewport = this.getCornerstoneViewport(viewportId) as
|
||||
| Types.IStackViewport
|
||||
| Types.IVolumeViewport;
|
||||
|
||||
if (!viewport) {
|
||||
return;
|
||||
}
|
||||
const camera = presentations?.positionPresentation?.camera;
|
||||
if (camera) {
|
||||
viewport.setCamera(camera);
|
||||
|
||||
if (!presentations) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { lutPresentation, positionPresentation } = presentations;
|
||||
if (lutPresentation) {
|
||||
const { presentation } = lutPresentation;
|
||||
|
||||
if (viewport instanceof BaseVolumeViewport) {
|
||||
Object.entries(presentation).forEach(
|
||||
([volumeId, properties]: [string, Types.ViewportProperties]) => {
|
||||
viewport.setProperties(properties, volumeId);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
viewport.setProperties(presentation);
|
||||
}
|
||||
}
|
||||
|
||||
if (positionPresentation) {
|
||||
const { viewPlaneNormal, viewUp, zoom, pan } = positionPresentation.presentation;
|
||||
viewport.setCamera({ viewPlaneNormal, viewUp });
|
||||
|
||||
if (zoom !== undefined) {
|
||||
viewport.setZoom(zoom);
|
||||
}
|
||||
|
||||
if (pan !== undefined) {
|
||||
viewport.setPan(pan);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public getPresentation(viewportId: string): Presentation {
|
||||
/**
|
||||
* Retrieves the position presentation information for a given viewport.
|
||||
* @param viewportId The ID of the viewport.
|
||||
* @returns The position presentation object containing various properties
|
||||
* such as ID, viewport type, initial image index, view plane normal, view up, zoom, and pan.
|
||||
*/
|
||||
public getPositionPresentation(viewportId: string): PositionPresentation {
|
||||
const viewportInfo = this.viewportsById.get(viewportId);
|
||||
if (!viewportInfo) {
|
||||
return;
|
||||
}
|
||||
const { viewportType, presentationIds } = viewportInfo.getViewportOptions();
|
||||
|
||||
const presentationIds = viewportInfo.getPresentationIds();
|
||||
|
||||
if (!presentationIds) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { positionPresentationId } = presentationIds;
|
||||
|
||||
const csViewport = this.getCornerstoneViewport(viewportId);
|
||||
if (!csViewport) {
|
||||
return;
|
||||
}
|
||||
|
||||
const properties = csViewport.getProperties();
|
||||
if (properties.isComputedVOI) {
|
||||
delete properties.voiRange;
|
||||
delete properties.VOILUTFunction;
|
||||
}
|
||||
const { viewPlaneNormal, viewUp } = csViewport.getCamera();
|
||||
const initialImageIndex = csViewport.getCurrentImageIdIndex();
|
||||
const camera = csViewport.getCamera();
|
||||
const zoom = csViewport.getZoom();
|
||||
const pan = csViewport.getPan();
|
||||
|
||||
return {
|
||||
presentationIds,
|
||||
viewportType: !viewportType || viewportType === 'stack' ? 'stack' : 'volume',
|
||||
properties,
|
||||
initialImageIndex,
|
||||
camera,
|
||||
id: positionPresentationId,
|
||||
viewportType: viewportInfo.getViewportType(),
|
||||
presentation: {
|
||||
initialImageIndex,
|
||||
viewUp,
|
||||
viewPlaneNormal,
|
||||
zoom,
|
||||
pan,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public storePresentation({ viewportId }) {
|
||||
const stateSyncService = this.servicesManager.services.stateSyncService;
|
||||
let presentation;
|
||||
try {
|
||||
presentation = this.getPresentation(viewportId);
|
||||
} catch (error) {
|
||||
console.warn(error);
|
||||
}
|
||||
|
||||
if (!presentation || !presentation.presentationIds) {
|
||||
/**
|
||||
* Retrieves the LUT (Lookup Table) presentation for a given viewport.
|
||||
* @param viewportId The ID of the viewport.
|
||||
* @returns The LUT presentation object, or undefined if the viewport does not exist.
|
||||
*/
|
||||
public getLutPresentation(viewportId: string): LutPresentation {
|
||||
const viewportInfo = this.viewportsById.get(viewportId);
|
||||
if (!viewportInfo) {
|
||||
return;
|
||||
}
|
||||
const { lutPresentationStore, positionPresentationStore } = stateSyncService.getState();
|
||||
const { presentationIds } = presentation;
|
||||
const { lutPresentationId, positionPresentationId } = presentationIds || {};
|
||||
const storeState = {};
|
||||
|
||||
const presentationIds = viewportInfo.getPresentationIds();
|
||||
|
||||
if (!presentationIds) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { lutPresentationId } = presentationIds;
|
||||
|
||||
const csViewport = this.getCornerstoneViewport(viewportId) as
|
||||
| Types.IStackViewport
|
||||
| Types.IVolumeViewport;
|
||||
|
||||
if (!csViewport) {
|
||||
return;
|
||||
}
|
||||
|
||||
const cleanProperties = properties => {
|
||||
if (properties.isComputedVOI) {
|
||||
delete properties.voiRange;
|
||||
delete properties.VOILUTFunction;
|
||||
}
|
||||
return properties;
|
||||
};
|
||||
|
||||
const presentation =
|
||||
csViewport instanceof BaseVolumeViewport
|
||||
? new Map()
|
||||
: cleanProperties(csViewport.getProperties());
|
||||
|
||||
if (presentation instanceof Map) {
|
||||
csViewport.getActors().forEach(({ uid: volumeId }) => {
|
||||
const properties = cleanProperties(csViewport.getProperties(volumeId));
|
||||
presentation.set(volumeId, properties);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
id: lutPresentationId,
|
||||
viewportType: viewportInfo.getViewportType(),
|
||||
presentation,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the presentations for a given viewport.
|
||||
* @param viewportId - The ID of the viewport.
|
||||
* @returns The presentations for the viewport.
|
||||
*/
|
||||
public getPresentations(viewportId: string): Presentations {
|
||||
const viewportInfo = this.viewportsById.get(viewportId);
|
||||
if (!viewportInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
const positionPresentation = this.getPositionPresentation(viewportId);
|
||||
const lutPresentation = this.getLutPresentation(viewportId);
|
||||
|
||||
return {
|
||||
positionPresentation,
|
||||
lutPresentation,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the presentation state for a given viewport inside the
|
||||
* stateSyncService. This is used to persist the presentation state
|
||||
* across different scenarios e.g., when the viewport is changing the
|
||||
* display set, or when the viewport is moving to a different layout.
|
||||
*
|
||||
* @param viewportId The ID of the viewport.
|
||||
*/
|
||||
public storePresentation({ viewportId }) {
|
||||
let presentations = null as Presentations;
|
||||
try {
|
||||
presentations = this.getPresentations(viewportId);
|
||||
if (!presentations?.positionPresentation && !presentations?.lutPresentation) {
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(error);
|
||||
return;
|
||||
}
|
||||
|
||||
const { stateSyncService, syncGroupService } = this.servicesManager.services;
|
||||
|
||||
const synchronizers = syncGroupService.getSynchronizersForViewport(
|
||||
viewportId,
|
||||
this.renderingEngine.id
|
||||
);
|
||||
|
||||
const { positionPresentationStore, synchronizersStore, lutPresentationStore } =
|
||||
stateSyncService.getState();
|
||||
|
||||
const { lutPresentation, positionPresentation } = presentations;
|
||||
const { id: positionPresentationId } = positionPresentation;
|
||||
const { id: lutPresentationId } = lutPresentation;
|
||||
|
||||
const updateStore = (store, id, value) => ({ ...store, [id]: value });
|
||||
|
||||
const newState = {} as { [key: string]: any };
|
||||
|
||||
if (lutPresentationId) {
|
||||
storeState.lutPresentationStore = {
|
||||
...lutPresentationStore,
|
||||
[lutPresentationId]: presentation,
|
||||
};
|
||||
newState.lutPresentationStore = updateStore(
|
||||
lutPresentationStore,
|
||||
lutPresentationId,
|
||||
lutPresentation
|
||||
);
|
||||
}
|
||||
|
||||
if (positionPresentationId) {
|
||||
storeState.positionPresentationStore = {
|
||||
...positionPresentationStore,
|
||||
[positionPresentationId]: presentation,
|
||||
};
|
||||
newState.positionPresentationStore = updateStore(
|
||||
positionPresentationStore,
|
||||
positionPresentationId,
|
||||
positionPresentation
|
||||
);
|
||||
}
|
||||
stateSyncService.store(storeState);
|
||||
|
||||
if (synchronizers?.length) {
|
||||
newState.synchronizersStore = updateStore(
|
||||
synchronizersStore,
|
||||
viewportId,
|
||||
synchronizers.map(synchronizer => ({
|
||||
id: synchronizer.id,
|
||||
sourceViewports: [...synchronizer.getSourceViewports()],
|
||||
targetViewports: [...synchronizer.getTargetViewports()],
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
stateSyncService.store(newState);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -283,20 +469,31 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
this.viewportsById.set(viewportId, viewportInfo);
|
||||
|
||||
const viewport = renderingEngine.getViewport(viewportId);
|
||||
this._setDisplaySets(viewport, viewportData, viewportInfo, presentations);
|
||||
const displaySetPromise = this._setDisplaySets(
|
||||
viewport,
|
||||
viewportData,
|
||||
viewportInfo,
|
||||
presentations
|
||||
);
|
||||
|
||||
// The broadcast event here ensures that listeners have a valid, up to date
|
||||
// viewport to access. Doing it too early can result in exceptions or
|
||||
// invalid data.
|
||||
this._broadcastEvent(this.EVENTS.VIEWPORT_DATA_CHANGED, {
|
||||
viewportData,
|
||||
viewportId,
|
||||
displaySetPromise.then(() => {
|
||||
this._broadcastEvent(this.EVENTS.VIEWPORT_DATA_CHANGED, {
|
||||
viewportData,
|
||||
viewportId,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public getCornerstoneViewport(
|
||||
viewportId: string
|
||||
): Types.IStackViewport | Types.IVolumeViewport | null {
|
||||
/**
|
||||
* Retrieves the Cornerstone viewport with the specified ID.
|
||||
*
|
||||
* @param viewportId - The ID of the viewport.
|
||||
* @returns The Cornerstone viewport object if found, otherwise null.
|
||||
*/
|
||||
public getCornerstoneViewport(viewportId: string): Types.IViewport | null {
|
||||
const viewportInfo = this.getViewportInfo(viewportId);
|
||||
|
||||
if (!viewportInfo || !this.renderingEngine || this.renderingEngine.hasBeenDestroyed) {
|
||||
@@ -308,16 +505,52 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
return viewport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the viewport information for a given viewport ID. The viewport information
|
||||
* is the OHIF construct that holds different options and data for a given viewport and
|
||||
* is different from the cornerstone viewport.
|
||||
*
|
||||
* @param viewportId The ID of the viewport.
|
||||
* @returns The viewport information.
|
||||
*/
|
||||
public getViewportInfo(viewportId: string): ViewportInfo {
|
||||
return this.viewportsById.get(viewportId);
|
||||
}
|
||||
|
||||
_setStackViewport(
|
||||
/**
|
||||
* Looks through the viewports to see if the specified measurement can be
|
||||
* displayed in one of the viewports.
|
||||
*
|
||||
* @param measurement
|
||||
* The measurement that is desired to view.
|
||||
* @param activeViewportId - the index that was active at the time the jump
|
||||
* was initiated.
|
||||
* @return the viewportId that the measurement should be displayed in.
|
||||
*/
|
||||
public getViewportIdToJump(
|
||||
activeViewportId: string,
|
||||
displaySetInstanceUID: string,
|
||||
cameraProps: unknown
|
||||
): string {
|
||||
const viewportInfo = this.getViewportInfo(activeViewportId);
|
||||
const { referencedImageId } = cameraProps;
|
||||
if (viewportInfo?.contains(displaySetInstanceUID, referencedImageId)) {
|
||||
return activeViewportId;
|
||||
}
|
||||
|
||||
return (
|
||||
[...this.viewportsById.values()].find(viewportInfo =>
|
||||
viewportInfo.contains(displaySetInstanceUID, referencedImageId)
|
||||
)?.viewportId ?? null
|
||||
);
|
||||
}
|
||||
|
||||
private async _setStackViewport(
|
||||
viewport: Types.IStackViewport,
|
||||
viewportData: StackViewportData,
|
||||
viewportInfo: ViewportInfo,
|
||||
presentations: Presentations
|
||||
): void {
|
||||
presentations: Presentations = {}
|
||||
): Promise<void> {
|
||||
const displaySetOptions = viewportInfo.getDisplaySetOptions();
|
||||
|
||||
const { imageIds, initialImageIndex, displaySetInstanceUID } = viewportData.data;
|
||||
@@ -333,7 +566,7 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
|
||||
const properties = { ...presentations.lutPresentation?.properties };
|
||||
if (!presentations.lutPresentation?.properties) {
|
||||
const { voi, voiInverted } = displaySetOptions[0];
|
||||
const { voi, voiInverted, colormap } = displaySetOptions[0];
|
||||
if (voi && (voi.windowWidth || voi.windowCenter)) {
|
||||
const { lower, upper } = csUtils.windowLevel.toLowHighRange(
|
||||
voi.windowWidth,
|
||||
@@ -345,14 +578,15 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
if (voiInverted !== undefined) {
|
||||
properties.invert = voiInverted;
|
||||
}
|
||||
|
||||
if (colormap !== undefined) {
|
||||
properties.colormap = colormap;
|
||||
}
|
||||
}
|
||||
|
||||
viewport.setStack(imageIds, initialImageIndexToUse).then(() => {
|
||||
return viewport.setStack(imageIds, initialImageIndexToUse).then(() => {
|
||||
viewport.setProperties({ ...properties });
|
||||
const camera = presentations.positionPresentation?.camera;
|
||||
if (camera) {
|
||||
viewport.setCamera(camera);
|
||||
}
|
||||
this.setPresentations(viewport.id, presentations);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -420,7 +654,7 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
viewport: Types.IVolumeViewport,
|
||||
viewportData: VolumeViewportData,
|
||||
viewportInfo: ViewportInfo,
|
||||
presentations: Presentations
|
||||
presentations: Presentations = {}
|
||||
): Promise<void> {
|
||||
// TODO: We need to overhaul the way data sources work so requests can be made
|
||||
// async. I think we should follow the image loader pattern which is async and
|
||||
@@ -524,7 +758,7 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
viewport.setProperties(properties, volumeId);
|
||||
});
|
||||
|
||||
this.setPresentations(viewport, presentations);
|
||||
this.setPresentations(viewport.id, presentations);
|
||||
|
||||
// load any secondary displaySets
|
||||
const displaySetInstanceUIDs = this.viewportsDisplaySets.get(viewport.id);
|
||||
@@ -654,46 +888,54 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
const viewport = this.getCornerstoneViewport(viewportId);
|
||||
const viewportCamera = viewport.getCamera();
|
||||
|
||||
let displaySetPromise;
|
||||
|
||||
if (viewport instanceof VolumeViewport || viewport instanceof VolumeViewport3D) {
|
||||
this._setVolumeViewport(viewport, viewportData, viewportInfo).then(() => {
|
||||
displaySetPromise = this._setVolumeViewport(viewport, viewportData, viewportInfo).then(() => {
|
||||
if (keepCamera) {
|
||||
viewport.setCamera(viewportCamera);
|
||||
viewport.render();
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (viewport instanceof StackViewport) {
|
||||
this._setStackViewport(viewport, viewportData, viewportInfo);
|
||||
return;
|
||||
displaySetPromise = this._setStackViewport(viewport, viewportData, viewportInfo);
|
||||
}
|
||||
|
||||
displaySetPromise.then(() => {
|
||||
this._broadcastEvent(this.EVENTS.VIEWPORT_DATA_CHANGED, {
|
||||
viewportData,
|
||||
viewportId,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
_setDisplaySets(
|
||||
viewport: StackViewport | VolumeViewport,
|
||||
viewport: Types.IViewport,
|
||||
viewportData: StackViewportData | VolumeViewportData,
|
||||
viewportInfo: ViewportInfo,
|
||||
presentations: Presentations = {}
|
||||
): void {
|
||||
): Promise<void> {
|
||||
if (viewport instanceof StackViewport) {
|
||||
this._setStackViewport(
|
||||
return this._setStackViewport(
|
||||
viewport,
|
||||
viewportData as StackViewportData,
|
||||
viewportInfo,
|
||||
presentations
|
||||
);
|
||||
} else if (viewport instanceof VolumeViewport || viewport instanceof VolumeViewport3D) {
|
||||
this._setVolumeViewport(
|
||||
viewport,
|
||||
}
|
||||
|
||||
if ([VolumeViewport, VolumeViewport3D].some(type => viewport instanceof type)) {
|
||||
return this._setVolumeViewport(
|
||||
viewport as Types.IVolumeViewport,
|
||||
viewportData as VolumeViewportData,
|
||||
viewportInfo,
|
||||
presentations
|
||||
);
|
||||
} else {
|
||||
throw new Error('Unknown viewport type');
|
||||
}
|
||||
|
||||
throw new Error('Unknown viewport type');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -759,32 +1001,57 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks through the viewports to see if the specified measurement can be
|
||||
* displayed in one of the viewports.
|
||||
*
|
||||
* @param measurement
|
||||
* The measurement that is desired to view.
|
||||
* @param activeViewportId - the index that was active at the time the jump
|
||||
* was initiated.
|
||||
* @return the viewportId that the measurement should be displayed in.
|
||||
*/
|
||||
public getViewportIdToJump(
|
||||
activeViewportId: string,
|
||||
displaySetInstanceUID: string,
|
||||
cameraProps: unknown
|
||||
): string {
|
||||
const viewportInfo = this.getViewportInfo(activeViewportId);
|
||||
const { referencedImageId } = cameraProps;
|
||||
if (viewportInfo?.contains(displaySetInstanceUID, referencedImageId)) {
|
||||
return activeViewportId;
|
||||
private enqueueViewportResizeRequest() {
|
||||
this.resizeQueue.push(false); // false indicates viewport resize
|
||||
|
||||
clearTimeout(this.viewportResizeTimer);
|
||||
this.viewportResizeTimer = setTimeout(() => {
|
||||
this.processViewportResizeQueue();
|
||||
}, this.gridResizeDelay);
|
||||
}
|
||||
|
||||
private processViewportResizeQueue() {
|
||||
const isGridResizeInQueue = this.resizeQueue.some(isGridResize => isGridResize);
|
||||
if (this.resizeQueue.length > 0 && !isGridResizeInQueue && !this.gridResizeTimeOut) {
|
||||
this.performResize();
|
||||
}
|
||||
|
||||
return (
|
||||
[...this.viewportsById.values()].find(viewportInfo =>
|
||||
viewportInfo.contains(displaySetInstanceUID, referencedImageId)
|
||||
)?.viewportId ?? null
|
||||
);
|
||||
// Clear the queue after processing viewport resizes
|
||||
this.resizeQueue = [];
|
||||
}
|
||||
|
||||
private performResize() {
|
||||
const isImmediate = false;
|
||||
|
||||
const viewports = this.getRenderingEngine().getViewports();
|
||||
|
||||
// Store the current position presentations for each viewport.
|
||||
viewports.forEach(({ id }) => {
|
||||
const presentation = this.getPositionPresentation(id);
|
||||
this.beforeResizePositionPresentations.set(id, presentation);
|
||||
});
|
||||
|
||||
// Resize the rendering engine and render.
|
||||
const renderingEngine = this.renderingEngine;
|
||||
renderingEngine.resize(isImmediate);
|
||||
renderingEngine.render();
|
||||
|
||||
// Reset the camera for viewports that should reset their camera on resize,
|
||||
// which means only those viewports that have a zoom level of 1.
|
||||
this.beforeResizePositionPresentations.forEach((positionPresentation, viewportId) => {
|
||||
this.setPresentations(viewportId, { positionPresentation });
|
||||
});
|
||||
|
||||
// Resize and render the rendering engine again.
|
||||
renderingEngine.resize(isImmediate);
|
||||
renderingEngine.render();
|
||||
}
|
||||
|
||||
private resetGridResizeTimeout() {
|
||||
clearTimeout(this.gridResizeTimeOut);
|
||||
this.gridResizeTimeOut = setTimeout(() => {
|
||||
this.gridResizeTimeOut = null;
|
||||
}, this.gridResizeDelay);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Types } from '@cornerstonejs/core';
|
||||
import { StackData, VolumeData } from '../../types/CornerstoneCacheService';
|
||||
import { DisplaySetOptions, PublicViewportOptions, ViewportOptions } from './Viewport';
|
||||
import { StackViewportData, VolumeViewportData } from '../../types/CornerstoneCacheService';
|
||||
import { DisplaySetOptions, PublicViewportOptions } from './Viewport';
|
||||
import { Presentations } from '../../types/Presentation';
|
||||
|
||||
/**
|
||||
* Handles cornerstone viewport logic including enabling, disabling, and
|
||||
@@ -36,7 +37,7 @@ export interface IViewportService {
|
||||
* the element for resizing events
|
||||
* @param {*} elementRef
|
||||
*/
|
||||
resize(element: HTMLDivElement): void;
|
||||
resize(isGridResize: boolean): void;
|
||||
/**
|
||||
* Removes the viewport from cornerstone, and destroys the rendering engine
|
||||
*/
|
||||
@@ -55,8 +56,10 @@ export interface IViewportService {
|
||||
* @returns
|
||||
*/
|
||||
setViewportData(
|
||||
viewportData: StackData | VolumeData,
|
||||
viewportId: string,
|
||||
viewportData: StackViewportData | VolumeViewportData,
|
||||
publicViewportOptions: PublicViewportOptions,
|
||||
publicDisplaySetOptions: DisplaySetOptions[]
|
||||
publicDisplaySetOptions: DisplaySetOptions[],
|
||||
presentations?: Presentations
|
||||
): void;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Types, Enums } from '@cornerstonejs/core';
|
||||
import { Types as UITypes } from '@ohif/ui';
|
||||
import { Types as CoreTypes } from '@ohif/core';
|
||||
import { StackViewportData, VolumeViewportData } from '../../types/CornerstoneCacheService';
|
||||
import getCornerstoneBlendMode from '../../utils/getCornerstoneBlendMode';
|
||||
import getCornerstoneOrientation from '../../utils/getCornerstoneOrientation';
|
||||
@@ -18,7 +18,7 @@ export type ViewportOptions = {
|
||||
toolGroupId: string;
|
||||
viewportId: string;
|
||||
// Presentation ID to store/load presentation state from
|
||||
presentationIds?: UITypes.PresentationIds;
|
||||
presentationIds?: CoreTypes.PresentationIds;
|
||||
orientation?: Enums.OrientationAxis;
|
||||
background?: Types.Point3;
|
||||
displayArea?: Types.DisplayArea;
|
||||
@@ -36,7 +36,7 @@ export type PublicViewportOptions = {
|
||||
id?: string;
|
||||
viewportType?: string;
|
||||
toolGroupId?: string;
|
||||
presentationIds?: UITypes.PresentationIds;
|
||||
presentationIds?: CoreTypes.PresentationIds;
|
||||
viewportId?: string;
|
||||
orientation?: Enums.OrientationAxis;
|
||||
background?: Types.Point3;
|
||||
@@ -71,7 +71,7 @@ export type DisplaySetOptions = {
|
||||
voiInverted: boolean;
|
||||
blendMode?: Enums.BlendModes;
|
||||
slabThickness?: number;
|
||||
colormap?: string;
|
||||
colormap?: { name: string; opacity?: number };
|
||||
displayPreset?: string;
|
||||
};
|
||||
|
||||
@@ -238,6 +238,11 @@ class ViewportInfo {
|
||||
return this.viewportOptions;
|
||||
}
|
||||
|
||||
public getPresentationIds(): CoreTypes.PresentationIds {
|
||||
const { presentationIds } = this.viewportOptions;
|
||||
return presentationIds;
|
||||
}
|
||||
|
||||
public setDisplaySetOptions(displaySetOptions: Array<DisplaySetOptions>): void {
|
||||
this.displaySetOptions = displaySetOptions;
|
||||
}
|
||||
|
||||
@@ -66,14 +66,6 @@ export function onCompletedCalibrationLine(servicesManager, csToolsEvent) {
|
||||
calculateLength3(annotationData.handles.points[0], annotationData.handles.points[1]) * 100
|
||||
) / 100;
|
||||
|
||||
// calculate the currently applied pixel spacing on the viewport
|
||||
const calibratedPixelSpacing = metaData.get('calibratedPixelSpacing', imageId);
|
||||
const imagePlaneModule = metaData.get('imagePlaneModule', imageId);
|
||||
const currentRowPixelSpacing =
|
||||
calibratedPixelSpacing?.[0] || imagePlaneModule?.rowPixelSpacing || 1;
|
||||
const currentColumnPixelSpacing =
|
||||
calibratedPixelSpacing?.[1] || imagePlaneModule?.columnPixelSpacing || 1;
|
||||
|
||||
const adjustCalibration = newLength => {
|
||||
const spacingScale = newLength / length;
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { VolumeViewport, metaData } from '@cornerstonejs/core';
|
||||
import { utilities } from '@cornerstonejs/core';
|
||||
import { VolumeViewport, metaData, utilities } from '@cornerstonejs/core';
|
||||
import { IStackViewport, IVolumeViewport, Point3 } from '@cornerstonejs/core/dist/esm/types';
|
||||
import { AnnotationDisplayTool, drawing } from '@cornerstonejs/tools';
|
||||
import { guid } from '@ohif/core/src/utils';
|
||||
import { guid, b64toBlob } from '@ohif/core/src/utils';
|
||||
import OverlayPlaneModuleProvider from './OverlayPlaneModuleProvider';
|
||||
|
||||
interface CachedStat {
|
||||
color: number[]; // [r, g, b, a]
|
||||
@@ -27,8 +27,12 @@ interface CachedStat {
|
||||
*/
|
||||
class ImageOverlayViewerTool extends AnnotationDisplayTool {
|
||||
static toolName = 'ImageOverlayViewer';
|
||||
private _cachedOverlayMetadata: Map<string, any[]> = new Map();
|
||||
private _cachedStats: { [key: string]: CachedStat } = {};
|
||||
|
||||
/**
|
||||
* The overlay plane module provider add method is exposed here to be used
|
||||
* when updating the overlay for this tool to use for displaying data.
|
||||
*/
|
||||
public static addOverlayPlaneModule = OverlayPlaneModuleProvider.add;
|
||||
|
||||
constructor(
|
||||
toolProps = {},
|
||||
@@ -42,10 +46,7 @@ class ImageOverlayViewerTool extends AnnotationDisplayTool {
|
||||
super(toolProps, defaultToolProps);
|
||||
}
|
||||
|
||||
onSetToolDisabled = (): void => {
|
||||
this._cachedStats = {};
|
||||
this._cachedOverlayMetadata = new Map();
|
||||
};
|
||||
onSetToolDisabled = (): void => {};
|
||||
|
||||
protected getReferencedImageId(viewport: IStackViewport | IVolumeViewport): string {
|
||||
if (viewport instanceof VolumeViewport) {
|
||||
@@ -64,18 +65,24 @@ class ImageOverlayViewerTool extends AnnotationDisplayTool {
|
||||
return;
|
||||
}
|
||||
|
||||
const overlays =
|
||||
this._cachedOverlayMetadata.get(imageId) ??
|
||||
metaData.get('overlayPlaneModule', imageId)?.overlays;
|
||||
const overlayMetadata = metaData.get('overlayPlaneModule', imageId);
|
||||
const overlays = overlayMetadata?.overlays;
|
||||
|
||||
// no overlays
|
||||
if (!overlays?.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._cachedOverlayMetadata.set(imageId, overlays);
|
||||
// Fix the x, y positions
|
||||
overlays.forEach(overlay => {
|
||||
overlay.x ||= 0;
|
||||
overlay.y ||= 0;
|
||||
});
|
||||
|
||||
this._getCachedStat(imageId, overlays, this.configuration.fillColor).then(cachedStat => {
|
||||
// Will clear cached stat data when the overlay data changes
|
||||
ImageOverlayViewerTool.addOverlayPlaneModule(imageId, overlayMetadata);
|
||||
|
||||
this._getCachedStat(imageId, overlayMetadata, this.configuration.fillColor).then(cachedStat => {
|
||||
cachedStat.overlays.forEach(overlay => {
|
||||
this._renderOverlay(enabledElement, svgDrawingHelper, overlay);
|
||||
});
|
||||
@@ -146,15 +153,18 @@ class ImageOverlayViewerTool extends AnnotationDisplayTool {
|
||||
|
||||
private async _getCachedStat(
|
||||
imageId: string,
|
||||
overlayMetadata: any[],
|
||||
overlayMetadata,
|
||||
color: number[]
|
||||
): Promise<CachedStat> {
|
||||
if (this._cachedStats[imageId] && this._isSameColor(this._cachedStats[imageId].color, color)) {
|
||||
return this._cachedStats[imageId];
|
||||
const missingOverlay = overlayMetadata.overlays.filter(
|
||||
overlay => overlay.pixelData && !overlay.dataUrl
|
||||
);
|
||||
if (missingOverlay.length === 0) {
|
||||
return overlayMetadata;
|
||||
}
|
||||
|
||||
const overlays = await Promise.all(
|
||||
overlayMetadata
|
||||
overlayMetadata.overlays
|
||||
.filter(overlay => overlay.pixelData)
|
||||
.map(async (overlay, idx) => {
|
||||
let pixelData = null;
|
||||
@@ -164,6 +174,10 @@ class ImageOverlayViewerTool extends AnnotationDisplayTool {
|
||||
pixelData = overlay.pixelData[0];
|
||||
} else if (overlay.pixelData.retrieveBulkData) {
|
||||
pixelData = await overlay.pixelData.retrieveBulkData();
|
||||
} else if (overlay.pixelData.InlineBinary) {
|
||||
const blob = b64toBlob(overlay.pixelData.InlineBinary);
|
||||
const arrayBuffer = await blob.arrayBuffer();
|
||||
pixelData = arrayBuffer;
|
||||
}
|
||||
|
||||
if (!pixelData) {
|
||||
@@ -172,7 +186,7 @@ class ImageOverlayViewerTool extends AnnotationDisplayTool {
|
||||
|
||||
const dataUrl = this._renderOverlayToDataUrl(
|
||||
{ width: overlay.columns, height: overlay.rows },
|
||||
color,
|
||||
overlay.color || color,
|
||||
pixelData
|
||||
);
|
||||
|
||||
@@ -184,13 +198,9 @@ class ImageOverlayViewerTool extends AnnotationDisplayTool {
|
||||
};
|
||||
})
|
||||
);
|
||||
overlayMetadata.overlays = overlays;
|
||||
|
||||
this._cachedStats[imageId] = {
|
||||
color: color,
|
||||
overlays: overlays.filter(overlay => overlay),
|
||||
};
|
||||
|
||||
return this._cachedStats[imageId];
|
||||
return overlayMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import { metaData } from '@cornerstonejs/core';
|
||||
|
||||
const _cachedOverlayMetadata: Map<string, any[]> = new Map();
|
||||
|
||||
/**
|
||||
* Image Overlay Viewer tool is not a traditional tool that requires user interactin.
|
||||
* But it is used to display Pixel Overlays. And it will provide toggling capability.
|
||||
*
|
||||
* The documentation for Overlay Plane Module of DICOM can be found in [C.9.2 of
|
||||
* Part-3 of DICOM standard](https://dicom.nema.org/medical/dicom/2018b/output/chtml/part03/sect_C.9.2.html)
|
||||
*
|
||||
* Image Overlay rendered by this tool can be toggled on and off using
|
||||
* toolGroup.setToolEnabled() and toolGroup.setToolDisabled()
|
||||
*/
|
||||
const OverlayPlaneModuleProvider = {
|
||||
/** Adds the metadata for overlayPlaneModule */
|
||||
add: (imageId, metadata) => {
|
||||
if (_cachedOverlayMetadata.get(imageId) === metadata) {
|
||||
// This is a no-op here as the tool re-caches the data
|
||||
return;
|
||||
}
|
||||
_cachedOverlayMetadata.set(imageId, metadata);
|
||||
},
|
||||
|
||||
/** Standard getter for metadata */
|
||||
get: (type: string, query: string | string[]) => {
|
||||
if (Array.isArray(query)) {
|
||||
return;
|
||||
}
|
||||
if (type !== 'overlayPlaneModule') {
|
||||
return;
|
||||
}
|
||||
return _cachedOverlayMetadata.get(query);
|
||||
},
|
||||
};
|
||||
|
||||
// Needs to be higher priority than default provider
|
||||
metaData.addProvider(OverlayPlaneModuleProvider.get, 10_000);
|
||||
|
||||
export default OverlayPlaneModuleProvider;
|
||||
@@ -1,23 +1,45 @@
|
||||
/** Store presentation data for either stack viewports or volume viewports */
|
||||
import { Types } from '@cornerstonejs/core';
|
||||
import { Types as UITypes } from '@ohif/ui';
|
||||
import type { Types } from '@cornerstonejs/core';
|
||||
|
||||
/**
|
||||
* Has information on the presentation of the viewport.
|
||||
* Represents a position presentation in a viewport. This is basically
|
||||
* viewport specific camera position and zoom, and not the display set
|
||||
*/
|
||||
export interface Presentation extends Types.StackViewportProperties {
|
||||
presentationIds: UITypes.PresentationIds;
|
||||
export type PositionPresentation = {
|
||||
id: string;
|
||||
viewportType: string;
|
||||
initialImageIndex: number;
|
||||
camera: Types.ICamera;
|
||||
properties: Types.StackViewportProperties | Types.VolumeViewportProperties;
|
||||
zoom?: number;
|
||||
pan?: [number, number];
|
||||
presentation: {
|
||||
initialImageIndex: number;
|
||||
viewUp: Types.Point3;
|
||||
viewPlaneNormal: Types.Point3;
|
||||
zoom?: number;
|
||||
pan?: Types.Point2;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a LUT presentation in a viewport, and is really related
|
||||
* to displaySets and not the viewport itself. So that is why it can
|
||||
* be an object with volumeId keys, or a single object with the properties
|
||||
* itself
|
||||
*/
|
||||
export interface LutPresentation {
|
||||
id: string;
|
||||
viewportType: string;
|
||||
presentation: Record<string, Types.ViewportProperties> | Types.ViewportProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Presentation can be a PositionPresentation or a LutPresentation.
|
||||
*/
|
||||
type Presentation = PositionPresentation | LutPresentation;
|
||||
|
||||
/**
|
||||
* Viewport presentations object that can contain a positionPresentation
|
||||
* and or a lutPresentation.
|
||||
*/
|
||||
export type Presentations = {
|
||||
positionPresentation?: Presentation;
|
||||
lutPresentation?: Presentation;
|
||||
positionPresentation?: PositionPresentation;
|
||||
lutPresentation?: LutPresentation;
|
||||
};
|
||||
|
||||
export default Presentation;
|
||||
@@ -93,6 +93,7 @@ const CornerstoneViewportDownloadForm = ({
|
||||
renderingEngine.resize();
|
||||
|
||||
// Trigger the render on the viewport to update the on screen
|
||||
downloadViewport.resetCamera();
|
||||
downloadViewport.render();
|
||||
|
||||
downloadViewportElement.addEventListener(
|
||||
@@ -223,7 +224,6 @@ const CornerstoneViewportDownloadForm = ({
|
||||
minimumSize={MINIMUM_SIZE}
|
||||
maximumSize={MAX_TEXTURE_SIZE}
|
||||
defaultSize={DEFAULT_SIZE}
|
||||
canvasClass={'cornerstone-canvas'}
|
||||
activeViewportElement={activeViewportElement}
|
||||
enableViewport={enableViewport}
|
||||
disableViewport={disableViewport}
|
||||
|
||||
@@ -176,6 +176,7 @@ class DicomLoaderService {
|
||||
authorizationHeaders,
|
||||
wadoRoot,
|
||||
wadoUri,
|
||||
instance,
|
||||
} = dataset;
|
||||
// Retrieve wadors or just try to fetch wadouri
|
||||
if (!someInvalidStrings(wadoRoot)) {
|
||||
@@ -188,6 +189,13 @@ class DicomLoaderService {
|
||||
);
|
||||
} else if (!someInvalidStrings(wadoUri)) {
|
||||
return fetchIt(wadoUri, { headers: authorizationHeaders });
|
||||
} else if (!someInvalidStrings(instance?.url)) {
|
||||
// make sure the url is absolute, remove the scope
|
||||
// from it if it is not absolute. For instance it might be dicomweb:http://....
|
||||
// and we need to remove the dicomweb: part
|
||||
const url = instance.url;
|
||||
const absoluteUrl = url.startsWith('http') ? url : url.substring(url.indexOf(':') + 1);
|
||||
return fetchIt(absoluteUrl, { headers: authorizationHeaders });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File renamed without changes.
+8
-7
@@ -1,18 +1,19 @@
|
||||
const STACK_SYNC_NAME = 'stackImageSync';
|
||||
const IMAGE_SLICE_SYNC_NAME = 'IMAGE_SLICE_SYNC';
|
||||
|
||||
export default function toggleStackImageSync({
|
||||
export default function toggleImageSliceSync({
|
||||
toggledState,
|
||||
servicesManager,
|
||||
viewports: providedViewports,
|
||||
}) {
|
||||
if (!toggledState) {
|
||||
return disableSync(STACK_SYNC_NAME, servicesManager);
|
||||
return disableSync(IMAGE_SLICE_SYNC_NAME, servicesManager);
|
||||
}
|
||||
|
||||
const { syncGroupService, viewportGridService, displaySetService, cornerstoneViewportService } =
|
||||
servicesManager.services;
|
||||
|
||||
const viewports = providedViewports || getReconstructableStackViewports(viewportGridService, displaySetService);
|
||||
const viewports =
|
||||
providedViewports || getReconstructableStackViewports(viewportGridService, displaySetService);
|
||||
|
||||
// create synchronization group and add the viewports to it.
|
||||
viewports.forEach(gridViewport => {
|
||||
@@ -23,7 +24,7 @@ export default function toggleStackImageSync({
|
||||
}
|
||||
syncGroupService.addViewportToSyncGroup(viewportId, viewport.getRenderingEngine().id, {
|
||||
type: 'stackimage',
|
||||
id: STACK_SYNC_NAME,
|
||||
id: IMAGE_SLICE_SYNC_NAME,
|
||||
source: true,
|
||||
target: true,
|
||||
});
|
||||
@@ -46,7 +47,7 @@ function disableSync(syncName, servicesManager) {
|
||||
syncName
|
||||
);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the consistent spacing stack viewport types, which are the ones which
|
||||
@@ -77,4 +78,4 @@ function getReconstructableStackViewports(viewportGridService, displaySetService
|
||||
}
|
||||
});
|
||||
return viewports;
|
||||
};
|
||||
}
|
||||
@@ -1,13 +1,7 @@
|
||||
import { log, Types } from '@ohif/core';
|
||||
import { log, Enums } from '@ohif/core';
|
||||
import { EVENTS } from '@cornerstonejs/core';
|
||||
|
||||
const { TimingEnum } = Types;
|
||||
|
||||
const IMAGE_TIMING_KEYS = [
|
||||
TimingEnum.DISPLAY_SETS_TO_ALL_IMAGES,
|
||||
TimingEnum.DISPLAY_SETS_TO_FIRST_IMAGE,
|
||||
TimingEnum.STUDY_TO_FIRST_IMAGE,
|
||||
];
|
||||
const IMAGE_TIMING_KEYS = [];
|
||||
|
||||
const imageTiming = {
|
||||
viewportsWaiting: 0,
|
||||
@@ -23,6 +17,18 @@ const imageTiming = {
|
||||
*/
|
||||
|
||||
export default function initViewTiming({ element }) {
|
||||
if (!IMAGE_TIMING_KEYS.length) {
|
||||
// Work around a bug in WebPack that doesn't getting the enums initialized
|
||||
// quite fast enough to be declared statically.
|
||||
const { TimingEnum } = Enums;
|
||||
|
||||
IMAGE_TIMING_KEYS.push(
|
||||
TimingEnum.DISPLAY_SETS_TO_ALL_IMAGES,
|
||||
TimingEnum.DISPLAY_SETS_TO_FIRST_IMAGE,
|
||||
TimingEnum.STUDY_TO_FIRST_IMAGE,
|
||||
);
|
||||
}
|
||||
|
||||
if (!IMAGE_TIMING_KEYS.find(key => log.timingKeys[key])) {
|
||||
return;
|
||||
}
|
||||
@@ -34,6 +40,7 @@ function imageRenderedListener(evt) {
|
||||
if (evt.detail.viewportStatus === 'preRender') {
|
||||
return;
|
||||
}
|
||||
const { TimingEnum } = Enums;
|
||||
log.timeEnd(TimingEnum.DISPLAY_SETS_TO_FIRST_IMAGE);
|
||||
log.timeEnd(TimingEnum.STUDY_TO_FIRST_IMAGE);
|
||||
log.timeEnd(TimingEnum.SCRIPT_TO_VIEW);
|
||||
|
||||
@@ -50,7 +50,7 @@ const Angle = {
|
||||
displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
|
||||
}
|
||||
|
||||
const { points } = data.handles;
|
||||
const { points, textBox } = data.handles;
|
||||
|
||||
const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);
|
||||
|
||||
@@ -62,6 +62,7 @@ const Angle = {
|
||||
SOPInstanceUID,
|
||||
FrameOfReferenceUID,
|
||||
points,
|
||||
textBox,
|
||||
metadata,
|
||||
referenceSeriesUID: SeriesInstanceUID,
|
||||
referenceStudyUID: StudyInstanceUID,
|
||||
|
||||
@@ -48,7 +48,7 @@ const Length = {
|
||||
displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
|
||||
}
|
||||
|
||||
const { points } = data.handles;
|
||||
const { points, textBox } = data.handles;
|
||||
|
||||
const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);
|
||||
|
||||
@@ -59,6 +59,7 @@ const Length = {
|
||||
SOPInstanceUID,
|
||||
FrameOfReferenceUID,
|
||||
points,
|
||||
textBox,
|
||||
metadata,
|
||||
referenceSeriesUID: SeriesInstanceUID,
|
||||
referenceStudyUID: StudyInstanceUID,
|
||||
@@ -66,7 +67,6 @@ const Length = {
|
||||
toolName: metadata.toolName,
|
||||
displaySetInstanceUID: displaySet.displaySetInstanceUID,
|
||||
label: data.text,
|
||||
text: data.text,
|
||||
displayText: displayText,
|
||||
data: data.cachedStats,
|
||||
type: getValueTypeFromToolType(toolName),
|
||||
|
||||
@@ -45,7 +45,7 @@ const Bidirectional = {
|
||||
displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
|
||||
}
|
||||
|
||||
const { points } = data.handles;
|
||||
const { points, textBox } = data.handles;
|
||||
|
||||
const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);
|
||||
|
||||
@@ -57,6 +57,7 @@ const Bidirectional = {
|
||||
SOPInstanceUID,
|
||||
FrameOfReferenceUID,
|
||||
points,
|
||||
textBox,
|
||||
metadata,
|
||||
referenceSeriesUID: SeriesInstanceUID,
|
||||
referenceStudyUID: StudyInstanceUID,
|
||||
|
||||
@@ -43,7 +43,7 @@ const CircleROI = {
|
||||
displaySet = DisplaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
|
||||
}
|
||||
|
||||
const { points } = data.handles;
|
||||
const { points, textBox } = data.handles;
|
||||
|
||||
const mappedAnnotations = getMappedAnnotations(annotation, DisplaySetService);
|
||||
|
||||
@@ -55,6 +55,7 @@ const CircleROI = {
|
||||
SOPInstanceUID,
|
||||
FrameOfReferenceUID,
|
||||
points,
|
||||
textBox,
|
||||
metadata,
|
||||
referenceSeriesUID: SeriesInstanceUID,
|
||||
referenceStudyUID: StudyInstanceUID,
|
||||
|
||||
@@ -50,7 +50,7 @@ const CobbAngle = {
|
||||
displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
|
||||
}
|
||||
|
||||
const { points } = data.handles;
|
||||
const { points, textBox } = data.handles;
|
||||
|
||||
const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);
|
||||
|
||||
@@ -62,6 +62,7 @@ const CobbAngle = {
|
||||
SOPInstanceUID,
|
||||
FrameOfReferenceUID,
|
||||
points,
|
||||
textBox,
|
||||
metadata,
|
||||
referenceSeriesUID: SeriesInstanceUID,
|
||||
referenceStudyUID: StudyInstanceUID,
|
||||
|
||||
@@ -43,7 +43,7 @@ const EllipticalROI = {
|
||||
displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
|
||||
}
|
||||
|
||||
const { points } = data.handles;
|
||||
const { points, textBox } = data.handles;
|
||||
|
||||
const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);
|
||||
|
||||
@@ -55,6 +55,7 @@ const EllipticalROI = {
|
||||
SOPInstanceUID,
|
||||
FrameOfReferenceUID,
|
||||
points,
|
||||
textBox,
|
||||
metadata,
|
||||
referenceSeriesUID: SeriesInstanceUID,
|
||||
referenceStudyUID: StudyInstanceUID,
|
||||
|
||||
@@ -53,7 +53,7 @@ const Length = {
|
||||
displaySet = displaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
|
||||
}
|
||||
|
||||
const { points } = data.handles;
|
||||
const { points, textBox } = data.handles;
|
||||
|
||||
const mappedAnnotations = getMappedAnnotations(annotation, displaySetService);
|
||||
|
||||
@@ -65,6 +65,7 @@ const Length = {
|
||||
SOPInstanceUID,
|
||||
FrameOfReferenceUID,
|
||||
points,
|
||||
textBox,
|
||||
metadata,
|
||||
referenceSeriesUID: SeriesInstanceUID,
|
||||
referenceStudyUID: StudyInstanceUID,
|
||||
|
||||
@@ -48,7 +48,7 @@ const PlanarFreehandROI = {
|
||||
displaySet = DisplaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
|
||||
}
|
||||
|
||||
const { points } = data.handles;
|
||||
const { points, textBox } = data.handles;
|
||||
|
||||
const mappedAnnotations = getMappedAnnotations(annotation, DisplaySetService);
|
||||
|
||||
@@ -60,6 +60,7 @@ const PlanarFreehandROI = {
|
||||
SOPInstanceUID,
|
||||
FrameOfReferenceUID,
|
||||
points,
|
||||
textBox,
|
||||
metadata,
|
||||
referenceSeriesUID: SeriesInstanceUID,
|
||||
referenceStudyUID: StudyInstanceUID,
|
||||
|
||||
@@ -43,7 +43,7 @@ const RectangleROI = {
|
||||
displaySet = DisplaySetService.getDisplaySetsForSeries(SeriesInstanceUID);
|
||||
}
|
||||
|
||||
const { points } = data.handles;
|
||||
const { points, textBox } = data.handles;
|
||||
|
||||
const mappedAnnotations = getMappedAnnotations(annotation, DisplaySetService);
|
||||
|
||||
@@ -55,6 +55,7 @@ const RectangleROI = {
|
||||
SOPInstanceUID,
|
||||
FrameOfReferenceUID,
|
||||
points,
|
||||
textBox,
|
||||
metadata,
|
||||
referenceSeriesUID: SeriesInstanceUID,
|
||||
referenceStudyUID: StudyInstanceUID,
|
||||
|
||||
@@ -3,6 +3,659 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [3.8.0-beta.63](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.62...v3.8.0-beta.63) (2024-03-25)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **worklist:** new investigational use text ([#3999](https://github.com/OHIF/Viewers/issues/3999)) ([45b68e8](https://github.com/OHIF/Viewers/commit/45b68e841dcb9e28a2ea991c37ee7ac4a8c5b71e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.62](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.61...v3.8.0-beta.62) (2024-03-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.61](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.60...v3.8.0-beta.61) (2024-03-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.60](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.59...v3.8.0-beta.60) (2024-03-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.59](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.58...v3.8.0-beta.59) (2024-03-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.58](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.57...v3.8.0-beta.58) (2024-03-05)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.57](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.56...v3.8.0-beta.57) (2024-02-28)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.56](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.55...v3.8.0-beta.56) (2024-02-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **demo:** Deploy issue ([#3951](https://github.com/OHIF/Viewers/issues/3951)) ([21e8a2b](https://github.com/OHIF/Viewers/commit/21e8a2bd0b7cc72f90a31e472d285d761be15d30))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.55](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.54...v3.8.0-beta.55) (2024-02-21)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **resize:** Optimize resizing process and maintain zoom level ([#3889](https://github.com/OHIF/Viewers/issues/3889)) ([b3a0faf](https://github.com/OHIF/Viewers/commit/b3a0faf5f5f0a1993b2b017eb4cc1216164ea2c6))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.54](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.53...v3.8.0-beta.54) (2024-02-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.53](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.52...v3.8.0-beta.53) (2024-02-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 🐛 Sort merge results based on default data source (input) ([#3903](https://github.com/OHIF/Viewers/issues/3903)) ([5bba98e](https://github.com/OHIF/Viewers/commit/5bba98ed848bdf46b5ba4fc4708527cced3308b5))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.52](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.51...v3.8.0-beta.52) (2024-01-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.51](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.50...v3.8.0-beta.51) (2024-01-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* catch errors in getPTImageIdInstanceMetadata ([#3897](https://github.com/OHIF/Viewers/issues/3897)) ([a47aeb8](https://github.com/OHIF/Viewers/commit/a47aeb8bd729dcb8d2cfc13b27a31b0dd88f11ad))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.50](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.49...v3.8.0-beta.50) (2024-01-22)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.49](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.48...v3.8.0-beta.49) (2024-01-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.48](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.47...v3.8.0-beta.48) (2024-01-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 🐛 Check merge key for merge data source ([#3901](https://github.com/OHIF/Viewers/issues/3901)) ([911d672](https://github.com/OHIF/Viewers/commit/911d67283536b2fe7930948f2819ea0ad66e2a32))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.47](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.46...v3.8.0-beta.47) (2024-01-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.46](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.45...v3.8.0-beta.46) (2024-01-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.45](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.44...v3.8.0-beta.45) (2024-01-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **hp:** enable OHIF to run with partial metadata for large studies at the cost of less effective hanging protocol ([#3804](https://github.com/OHIF/Viewers/issues/3804)) ([0049f4c](https://github.com/OHIF/Viewers/commit/0049f4c0303f0b6ea995972326fc8784259f5a47))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.44](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.43...v3.8.0-beta.44) (2024-01-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.43](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.42...v3.8.0-beta.43) (2024-01-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.42](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.41...v3.8.0-beta.42) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.41](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.40...v3.8.0-beta.41) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.40](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.39...v3.8.0-beta.40) (2024-01-08)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **ui:** sidePanel expandedWidth ([#3728](https://github.com/OHIF/Viewers/issues/3728)) ([61bf22c](https://github.com/OHIF/Viewers/commit/61bf22c6f80e764bdf5c3b56bb0124a95aa0f793))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.39](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.38...v3.8.0-beta.39) (2024-01-08)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* improve disableEditing flag ([#3875](https://github.com/OHIF/Viewers/issues/3875)) ([2049c09](https://github.com/OHIF/Viewers/commit/2049c0936c86f819604c243d3dc7b3fe971b5b2c))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.38](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.37...v3.8.0-beta.38) (2024-01-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* PDF display request in v3 ([#3878](https://github.com/OHIF/Viewers/issues/3878)) ([9865030](https://github.com/OHIF/Viewers/commit/98650302c7575f0aea386e32cfc4112c378035e6))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.37](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.36...v3.8.0-beta.37) (2024-01-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.36](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.35...v3.8.0-beta.36) (2023-12-15)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.35](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.34...v3.8.0-beta.35) (2023-12-14)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.34](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.33...v3.8.0-beta.34) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.33](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.32...v3.8.0-beta.33) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.32](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.31...v3.8.0-beta.32) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.31](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.30...v3.8.0-beta.31) (2023-12-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.30](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.29...v3.8.0-beta.30) (2023-12-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **customizationService:** Enable saving and loading of private tags in SRs ([#3842](https://github.com/OHIF/Viewers/issues/3842)) ([e1f55e6](https://github.com/OHIF/Viewers/commit/e1f55e65f2d2a34136ad5d0b1ada77d337a0ea23))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.29](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.28...v3.8.0-beta.29) (2023-12-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **i18n:** enhanced i18n support ([#3761](https://github.com/OHIF/Viewers/issues/3761)) ([d14a8f0](https://github.com/OHIF/Viewers/commit/d14a8f0199db95cd9e85866a011b64d6bf830d57))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.28](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.27...v3.8.0-beta.28) (2023-12-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.27](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.26...v3.8.0-beta.27) (2023-12-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.26](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.25...v3.8.0-beta.26) (2023-11-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **SM:** drag and drop is now fixed for SM ([#3813](https://github.com/OHIF/Viewers/issues/3813)) ([f1a6764](https://github.com/OHIF/Viewers/commit/f1a67647aed635437b188cea7cf5d5a8fb974bbe))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.25](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.24...v3.8.0-beta.25) (2023-11-27)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.24](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.23...v3.8.0-beta.24) (2023-11-24)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.23](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.22...v3.8.0-beta.23) (2023-11-24)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Merge Data Source ([#3788](https://github.com/OHIF/Viewers/issues/3788)) ([c4ff2c2](https://github.com/OHIF/Viewers/commit/c4ff2c2f09546ce8b72eab9c5e7beed611e3cab0))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.22](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.21...v3.8.0-beta.22) (2023-11-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.21](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.20...v3.8.0-beta.21) (2023-11-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.20](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.19...v3.8.0-beta.20) (2023-11-21)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.19](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.18...v3.8.0-beta.19) (2023-11-18)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.18](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.17...v3.8.0-beta.18) (2023-11-15)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **url:** Add SeriesInstanceUIDs wado query param ([#3746](https://github.com/OHIF/Viewers/issues/3746)) ([b694228](https://github.com/OHIF/Viewers/commit/b694228dd535e4b97cb86a1dc085b6e8716bdaf3))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.17](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.16...v3.8.0-beta.17) (2023-11-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.16](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.15...v3.8.0-beta.16) (2023-11-13)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.15](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.14...v3.8.0-beta.15) (2023-11-10)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **dicomJSON:** Add Loading Other Display Sets and JSON Metadata Generation script ([#3777](https://github.com/OHIF/Viewers/issues/3777)) ([43b1c17](https://github.com/OHIF/Viewers/commit/43b1c17209502e4876ad59bae09ed9442eda8024))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.14](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.13...v3.8.0-beta.14) (2023-11-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.13](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.12...v3.8.0-beta.13) (2023-11-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.12](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.11...v3.8.0-beta.12) (2023-11-08)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.11](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.10...v3.8.0-beta.11) (2023-11-08)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **hp callback:** Add viewport ready callback ([#3772](https://github.com/OHIF/Viewers/issues/3772)) ([bf252bc](https://github.com/OHIF/Viewers/commit/bf252bcec2aae3a00479fdcb732110b344bcf2c0))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.10](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.9...v3.8.0-beta.10) (2023-11-03)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.9](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.8...v3.8.0-beta.9) (2023-11-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **thumbnail:** Avoid multiple promise creations for thumbnails ([#3756](https://github.com/OHIF/Viewers/issues/3756)) ([b23eeff](https://github.com/OHIF/Viewers/commit/b23eeff93745769e67e60c33d75293d6242c5ec9))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.8](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.7...v3.8.0-beta.8) (2023-10-31)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **i18n:** enhanced i18n support ([#3730](https://github.com/OHIF/Viewers/issues/3730)) ([330e11c](https://github.com/OHIF/Viewers/commit/330e11c7ff0151e1096e19b8ffdae7d64cae280e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.7](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.6...v3.8.0-beta.7) (2023-10-30)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.6](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.5...v3.8.0-beta.6) (2023-10-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **toolbar:** allow customizable toolbar for active viewport and allow active tool to be deactivated via a click ([#3608](https://github.com/OHIF/Viewers/issues/3608)) ([dd6d976](https://github.com/OHIF/Viewers/commit/dd6d9768bbca1d3cc472e8c1e6d85822500b96ef))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.5](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.4...v3.8.0-beta.5) (2023-10-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **sr:** dcm4chee requires the patient name for an SR to match what is in the original study ([#3739](https://github.com/OHIF/Viewers/issues/3739)) ([d98439f](https://github.com/OHIF/Viewers/commit/d98439fe7f3825076dbc87b664a1d1480ff414d3))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.4](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.3...v3.8.0-beta.4) (2023-10-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.3](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.2...v3.8.0-beta.3) (2023-10-23)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.2](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.1...v3.8.0-beta.2) (2023-10-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.1](https://github.com/OHIF/Viewers/compare/v3.8.0-beta.0...v3.8.0-beta.1) (2023-10-19)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.8.0-beta.0](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.110...v3.8.0-beta.0) (2023-10-12)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.110](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.109...v3.7.0-beta.110) (2023-10-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **display messages:** broken after timings ([#3719](https://github.com/OHIF/Viewers/issues/3719)) ([157b88c](https://github.com/OHIF/Viewers/commit/157b88c909d3289cb89ace731c1f9a19d40797ac))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.109](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.108...v3.7.0-beta.109) (2023-10-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **export:** wrong export for the tmtv RT function ([#3715](https://github.com/OHIF/Viewers/issues/3715)) ([a3f2a1a](https://github.com/OHIF/Viewers/commit/a3f2a1a7b0d16bfcc0ecddc2ab731e54c5e377c8))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.108](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.107...v3.7.0-beta.108) (2023-10-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.107](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.106...v3.7.0-beta.107) (2023-10-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.106](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.105...v3.7.0-beta.106) (2023-10-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.105](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.104...v3.7.0-beta.105) (2023-10-10)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.104](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.103...v3.7.0-beta.104) (2023-10-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.103](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.102...v3.7.0-beta.103) (2023-10-09)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.102](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.101...v3.7.0-beta.102) (2023-10-06)
|
||||
|
||||
**Note:** Version bump only for package @ohif/extension-default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.7.0-beta.101](https://github.com/OHIF/Viewers/compare/v3.7.0-beta.100...v3.7.0-beta.101) (2023-10-06)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = require('../../babel.config.js');
|
||||
@@ -0,0 +1,17 @@
|
||||
const base = require('../../jest.config.base.js');
|
||||
const pkg = require('./package');
|
||||
|
||||
module.exports = {
|
||||
...base,
|
||||
name: pkg.name,
|
||||
displayName: pkg.name,
|
||||
moduleNameMapper: {
|
||||
...base.moduleNameMapper,
|
||||
'@ohif/(.*)': '<rootDir>/../../platform/$1/src',
|
||||
},
|
||||
// rootDir: "../.."
|
||||
// testMatch: [
|
||||
// //`<rootDir>/platform/${pack.name}/**/*.spec.js`
|
||||
// "<rootDir>/platform/app/**/*.test.js"
|
||||
// ]
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ohif/extension-default",
|
||||
"version": "3.7.0-beta.101",
|
||||
"version": "3.8.0-beta.63",
|
||||
"description": "Common/default features and functionality for basic image viewing",
|
||||
"author": "OHIF Core Team",
|
||||
"license": "MIT",
|
||||
@@ -23,6 +23,8 @@
|
||||
"ohif-extension"
|
||||
],
|
||||
"scripts": {
|
||||
"clean": "shx rm -rf dist",
|
||||
"clean:deep": "yarn run clean && shx rm -rf node_modules",
|
||||
"dev": "cross-env NODE_ENV=development webpack --config .webpack/webpack.dev.js --watch --output-pathinfo",
|
||||
"dev:dicom-pdf": "yarn run dev",
|
||||
"build": "cross-env NODE_ENV=production webpack --config .webpack/webpack.prod.js",
|
||||
@@ -30,10 +32,10 @@
|
||||
"start": "yarn run dev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ohif/core": "3.7.0-beta.101",
|
||||
"@ohif/i18n": "3.7.0-beta.101",
|
||||
"dcmjs": "^0.29.5",
|
||||
"dicomweb-client": "^0.10.2",
|
||||
"@ohif/core": "3.8.0-beta.63",
|
||||
"@ohif/i18n": "3.8.0-beta.63",
|
||||
"dcmjs": "^0.29.12",
|
||||
"dicomweb-client": "^0.10.4",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
|
||||
@@ -8,6 +8,7 @@ export type SidePanelWithServicesProps = {
|
||||
className: string;
|
||||
activeTabIndex: number;
|
||||
tabs: any;
|
||||
expandedWidth?: number;
|
||||
};
|
||||
|
||||
const SidePanelWithServices = ({
|
||||
@@ -16,7 +17,8 @@ const SidePanelWithServices = ({
|
||||
className,
|
||||
activeTabIndex: activeTabIndexProp,
|
||||
tabs,
|
||||
}) => {
|
||||
expandedWidth,
|
||||
}: SidePanelWithServicesProps) => {
|
||||
const panelService: PanelService = servicesManager?.services?.panelService;
|
||||
|
||||
// Tracks whether this SidePanel has been opened at least once since this SidePanel was inserted into the DOM.
|
||||
@@ -53,6 +55,7 @@ const SidePanelWithServices = ({
|
||||
onOpen={() => {
|
||||
setHasBeenOpened(true);
|
||||
}}
|
||||
expandedWidth={expandedWidth}
|
||||
></SidePanel>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as ContextMenuItemsBuilder from './ContextMenuItemsBuilder';
|
||||
import ContextMenu from '../../../../platform/ui/src/components/ContextMenu/ContextMenu';
|
||||
import { CommandsManager, ServicesManager, Types } from '@ohif/core';
|
||||
import { annotation as CsAnnotation } from '@cornerstonejs/tools';
|
||||
import { Menu, MenuItem, Point, ContextMenuProps } from './types';
|
||||
|
||||
/**
|
||||
@@ -47,6 +48,18 @@ export default class ContextMenuController {
|
||||
|
||||
const { event, subMenu, menuId, menus, selectorProps } = contextMenuProps;
|
||||
|
||||
const annotationManager = CsAnnotation.state.getAnnotationManager();
|
||||
const { locking } = CsAnnotation;
|
||||
const targetAnnotationId = selectorProps?.nearbyToolData?.annotationUID as string;
|
||||
const isLocked = locking.isAnnotationLocked(
|
||||
annotationManager.getAnnotation(targetAnnotationId)
|
||||
);
|
||||
|
||||
if (isLocked) {
|
||||
console.warn('Annotation is locked.');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Getting items from', menus);
|
||||
const items = ContextMenuItemsBuilder.getMenuItems(
|
||||
selectorProps || contextMenuProps,
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import ContextMenuItemsBuilder from './ContextMenuItemsBuilder';
|
||||
import * as ContextMenuItemsBuilder from './ContextMenuItemsBuilder';
|
||||
|
||||
const menus = [
|
||||
{
|
||||
id: 'one',
|
||||
selector: ({ value }) => value === 'one',
|
||||
selector: ({ value } = {}) => value === 'one',
|
||||
items: [],
|
||||
},
|
||||
{
|
||||
id: 'two',
|
||||
selector: ({ value }) => value === 'two',
|
||||
selector: ({ value } = {}) => value === 'two',
|
||||
items: [],
|
||||
},
|
||||
{
|
||||
@@ -17,13 +17,13 @@ const menus = [
|
||||
},
|
||||
];
|
||||
|
||||
const menuBuilder = new ContextMenuItemsBuilder();
|
||||
|
||||
describe('ContextMenuItemsBuilder', () => {
|
||||
test('findMenuDefault', () => {
|
||||
expect(menuBuilder.findMenuDefault(menus, {})).toBe(menus[2]);
|
||||
expect(menuBuilder.findMenuDefault(menus, { value: 'two' })).toBe(menus[1]);
|
||||
expect(menuBuilder.findMenuDefault([], {})).toBeUndefined();
|
||||
expect(menuBuilder.findMenuDefault(undefined, undefined)).toBeNull();
|
||||
expect(ContextMenuItemsBuilder.findMenuDefault(menus, {})).toBe(menus[2]);
|
||||
expect(
|
||||
ContextMenuItemsBuilder.findMenuDefault(menus, { selectorProps: { value: 'two' } })
|
||||
).toBe(menus[1]);
|
||||
expect(ContextMenuItemsBuilder.findMenuDefault([], {})).toBeUndefined();
|
||||
expect(ContextMenuItemsBuilder.findMenuDefault(undefined, undefined)).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -25,6 +25,23 @@ let _store = {
|
||||
// }
|
||||
};
|
||||
|
||||
function wrapSequences(obj) {
|
||||
return Object.keys(obj).reduce(
|
||||
(acc, key) => {
|
||||
if (typeof obj[key] === 'object' && obj[key] !== null) {
|
||||
// Recursively wrap sequences for nested objects
|
||||
acc[key] = wrapSequences(obj[key]);
|
||||
} else {
|
||||
acc[key] = obj[key];
|
||||
}
|
||||
if (key.endsWith('Sequence')) {
|
||||
acc[key] = OHIF.utils.addAccessors(acc[key]);
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
Array.isArray(obj) ? [] : {}
|
||||
);
|
||||
}
|
||||
const getMetaDataByURL = url => {
|
||||
return _store.urls.find(metaData => metaData.url === url);
|
||||
};
|
||||
@@ -190,8 +207,14 @@ function createDicomJSONApi(dicomJsonConfig) {
|
||||
const numberOfSeries = series.length;
|
||||
series.forEach((series, index) => {
|
||||
const instances = series.instances.map(instance => {
|
||||
// for instance.metadata if the key ends with sequence then
|
||||
// we need to add a proxy to the first item in the sequence
|
||||
// so that we can access the value of the sequence
|
||||
// by using sequenceName.value
|
||||
const modifiedMetadata = wrapSequences(instance.metadata);
|
||||
|
||||
const obj = {
|
||||
...instance.metadata,
|
||||
...modifiedMetadata,
|
||||
url: instance.url,
|
||||
imageId: instance.url,
|
||||
...series,
|
||||
|
||||
@@ -28,19 +28,38 @@ const EXPLICIT_VR_LITTLE_ENDIAN = '1.2.840.10008.1.2.1';
|
||||
const metadataProvider = classes.MetadataProvider;
|
||||
|
||||
/**
|
||||
* Creates a DICOM Web API based on the provided configuration.
|
||||
*
|
||||
* @param {string} name - Data source name
|
||||
* @param {string} wadoUriRoot - Legacy? (potentially unused/replaced)
|
||||
* @param {string} qidoRoot - Base URL to use for QIDO requests
|
||||
* @param {string} wadoRoot - Base URL to use for WADO requests
|
||||
* @param {boolean} qidoSupportsIncludeField - Whether QIDO supports the "Include" option to request additional fields in response
|
||||
* @param {string} imageRengering - wadors | ? (unsure of where/how this is used)
|
||||
* @param {string} thumbnailRendering - wadors | ? (unsure of where/how this is used)
|
||||
* @param {bool} supportsReject - Whether the server supports reject calls (i.e. DCM4CHEE)
|
||||
* @param {bool} lazyLoadStudy - "enableStudyLazyLoad"; Request series meta async instead of blocking
|
||||
* @param {string|bool} singlepart - indicates of the retrieves can fetch singlepart. Options are bulkdata, video, image or boolean true
|
||||
* @param {object} dicomWebConfig - Configuration for the DICOM Web API
|
||||
* @param {string} dicomWebConfig.name - Data source name
|
||||
* @param {string} dicomWebConfig.wadoUriRoot - Legacy? (potentially unused/replaced)
|
||||
* @param {string} dicomWebConfig.qidoRoot - Base URL to use for QIDO requests
|
||||
* @param {string} dicomWebConfig.wadoRoot - Base URL to use for WADO requests
|
||||
* @param {string} dicomWebConfig.wadoUri - Base URL to use for WADO URI requests
|
||||
* @param {boolean} dicomWebConfig.qidoSupportsIncludeField - Whether QIDO supports the "Include" option to request additional fields in response
|
||||
* @param {string} dicomWebConfig.imageRendering - wadors | ? (unsure of where/how this is used)
|
||||
* @param {string} dicomWebConfig.thumbnailRendering - wadors | ? (unsure of where/how this is used)
|
||||
* @param {boolean} dicomWebConfig.supportsReject - Whether the server supports reject calls (i.e. DCM4CHEE)
|
||||
* @param {boolean} dicomWebConfig.lazyLoadStudy - "enableStudyLazyLoad"; Request series meta async instead of blocking
|
||||
* @param {string|boolean} dicomWebConfig.singlepart - indicates if the retrieves can fetch singlepart. Options are bulkdata, video, image, or boolean true
|
||||
* @param {string} dicomWebConfig.requestTransferSyntaxUID - Transfer syntax to request from the server
|
||||
* @param {object} dicomWebConfig.acceptHeader - Accept header to use for requests
|
||||
* @param {boolean} dicomWebConfig.omitQuotationForMultipartRequest - Whether to omit quotation marks for multipart requests
|
||||
* @param {boolean} dicomWebConfig.supportsFuzzyMatching - Whether the server supports fuzzy matching
|
||||
* @param {boolean} dicomWebConfig.supportsWildcard - Whether the server supports wildcard matching
|
||||
* @param {boolean} dicomWebConfig.supportsNativeDICOMModel - Whether the server supports the native DICOM model
|
||||
* @param {boolean} dicomWebConfig.enableStudyLazyLoad - Whether to enable study lazy loading
|
||||
* @param {boolean} dicomWebConfig.enableRequestTag - Whether to enable request tag
|
||||
* @param {boolean} dicomWebConfig.enableStudyLazyLoad - Whether to enable study lazy loading
|
||||
* @param {boolean} dicomWebConfig.bulkDataURI - Whether to enable bulkDataURI
|
||||
* @param {function} dicomWebConfig.onConfiguration - Function that is called after the configuration is initialized
|
||||
* @param {boolean} dicomWebConfig.staticWado - Whether to use the static WADO client
|
||||
* @param {object} userAuthenticationService - User authentication service
|
||||
* @param {object} userAuthenticationService.getAuthorizationHeader - Function that returns the authorization header
|
||||
* @returns {object} - DICOM Web API object
|
||||
*/
|
||||
function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
function createDicomWebApi(dicomWebConfig, servicesManager) {
|
||||
const { userAuthenticationService, customizationService } = servicesManager.services;
|
||||
let dicomWebConfigCopy,
|
||||
qidoConfig,
|
||||
wadoConfig,
|
||||
@@ -140,7 +159,13 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
instances: {
|
||||
search: (studyInstanceUid, queryParameters) => {
|
||||
qidoDicomWebClient.headers = getAuthrorizationHeader();
|
||||
qidoSearch.call(undefined, qidoDicomWebClient, studyInstanceUid, null, queryParameters);
|
||||
return qidoSearch.call(
|
||||
undefined,
|
||||
qidoDicomWebClient,
|
||||
studyInstanceUid,
|
||||
null,
|
||||
queryParameters
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -184,6 +209,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
sortCriteria,
|
||||
sortFunction,
|
||||
madeInClient = false,
|
||||
returnPromises = false,
|
||||
} = {}) => {
|
||||
if (!StudyInstanceUID) {
|
||||
throw new Error('Unable to query for SeriesMetadata without StudyInstanceUID');
|
||||
@@ -195,7 +221,8 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
filters,
|
||||
sortCriteria,
|
||||
sortFunction,
|
||||
madeInClient
|
||||
madeInClient,
|
||||
returnPromises
|
||||
);
|
||||
}
|
||||
|
||||
@@ -211,7 +238,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
},
|
||||
|
||||
store: {
|
||||
dicom: async (dataset, request) => {
|
||||
dicom: async (dataset, request, dicomDict) => {
|
||||
wadoDicomWebClient.headers = getAuthrorizationHeader();
|
||||
if (dataset instanceof ArrayBuffer) {
|
||||
const options = {
|
||||
@@ -220,21 +247,26 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
};
|
||||
await wadoDicomWebClient.storeInstances(options);
|
||||
} else {
|
||||
const meta = {
|
||||
FileMetaInformationVersion: dataset._meta?.FileMetaInformationVersion?.Value,
|
||||
MediaStorageSOPClassUID: dataset.SOPClassUID,
|
||||
MediaStorageSOPInstanceUID: dataset.SOPInstanceUID,
|
||||
TransferSyntaxUID: EXPLICIT_VR_LITTLE_ENDIAN,
|
||||
ImplementationClassUID,
|
||||
ImplementationVersionName,
|
||||
};
|
||||
let effectiveDicomDict = dicomDict;
|
||||
|
||||
const denaturalized = denaturalizeDataset(meta);
|
||||
const dicomDict = new DicomDict(denaturalized);
|
||||
if (!dicomDict) {
|
||||
const meta = {
|
||||
FileMetaInformationVersion: dataset._meta?.FileMetaInformationVersion?.Value,
|
||||
MediaStorageSOPClassUID: dataset.SOPClassUID,
|
||||
MediaStorageSOPInstanceUID: dataset.SOPInstanceUID,
|
||||
TransferSyntaxUID: EXPLICIT_VR_LITTLE_ENDIAN,
|
||||
ImplementationClassUID,
|
||||
ImplementationVersionName,
|
||||
};
|
||||
|
||||
dicomDict.dict = denaturalizeDataset(dataset);
|
||||
const denaturalized = denaturalizeDataset(meta);
|
||||
const defaultDicomDict = new DicomDict(denaturalized);
|
||||
defaultDicomDict.dict = denaturalizeDataset(dataset);
|
||||
|
||||
const part10Buffer = dicomDict.write();
|
||||
effectiveDicomDict = defaultDicomDict;
|
||||
}
|
||||
|
||||
const part10Buffer = effectiveDicomDict.write();
|
||||
|
||||
const options = {
|
||||
datasets: [part10Buffer],
|
||||
@@ -262,7 +294,8 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
enableStudyLazyLoad,
|
||||
filters,
|
||||
sortCriteria,
|
||||
sortFunction
|
||||
sortFunction,
|
||||
dicomWebConfig
|
||||
);
|
||||
|
||||
// first naturalize the data
|
||||
@@ -314,6 +347,8 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
Object.keys(instancesPerSeries).forEach(seriesInstanceUID =>
|
||||
DicomMetadataStore.addInstances(instancesPerSeries[seriesInstanceUID], madeInClient)
|
||||
);
|
||||
|
||||
return seriesSummaryMetadata;
|
||||
},
|
||||
|
||||
_retrieveSeriesMetadataAsync: async (
|
||||
@@ -321,7 +356,8 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
filters,
|
||||
sortCriteria,
|
||||
sortFunction,
|
||||
madeInClient = false
|
||||
madeInClient = false,
|
||||
returnPromises = false
|
||||
) => {
|
||||
const enableStudyLazyLoad = true;
|
||||
wadoDicomWebClient.headers = generateWadoHeader();
|
||||
@@ -333,7 +369,8 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
enableStudyLazyLoad,
|
||||
filters,
|
||||
sortCriteria,
|
||||
sortFunction
|
||||
sortFunction,
|
||||
dicomWebConfig
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -357,11 +394,12 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
// in which case it isn't necessary to re-read this.
|
||||
if (value && value.BulkDataURI && !value.Value) {
|
||||
// Provide a method to fetch bulkdata
|
||||
value.retrieveBulkData = () => {
|
||||
value.retrieveBulkData = (options = {}) => {
|
||||
// handle the scenarios where bulkDataURI is relative path
|
||||
fixBulkDataURI(value, naturalized, dicomWebConfig);
|
||||
|
||||
const options = {
|
||||
const { mediaType } = options;
|
||||
const useOptions = {
|
||||
// The bulkdata fetches work with either multipart or
|
||||
// singlepart, so set multipart to false to let the server
|
||||
// decide which type to respond with.
|
||||
@@ -372,9 +410,13 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
// isn't well specified in the standard, but is needed in
|
||||
// any implementation that stores static copies of the metadata
|
||||
StudyInstanceUID: naturalized.StudyInstanceUID,
|
||||
mediaTypes: mediaType
|
||||
? [{ mediaType }, { mediaType: 'application/octet-stream' }]
|
||||
: undefined,
|
||||
...options,
|
||||
};
|
||||
// Todo: this needs to be from wado dicom web client
|
||||
return qidoDicomWebClient.retrieveBulkData(options).then(val => {
|
||||
return qidoDicomWebClient.retrieveBulkData(useOptions).then(val => {
|
||||
// There are DICOM PDF cases where the first ArrayBuffer in the array is
|
||||
// the bulk data and DICOM video cases where the second ArrayBuffer is
|
||||
// the bulk data. Here we play it safe and do a find.
|
||||
@@ -395,7 +437,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
const naturalizedInstances = instances.map(addRetrieveBulkData);
|
||||
|
||||
// Adding instanceMetadata to OHIF MetadataProvider
|
||||
naturalizedInstances.forEach((instance, index) => {
|
||||
naturalizedInstances.forEach(instance => {
|
||||
instance.wadoRoot = dicomWebConfig.wadoRoot;
|
||||
instance.wadoUri = dicomWebConfig.wadoUri;
|
||||
|
||||
@@ -422,7 +464,10 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
}
|
||||
|
||||
function setSuccessFlag() {
|
||||
const study = DicomMetadataStore.getStudy(StudyInstanceUID, madeInClient);
|
||||
const study = DicomMetadataStore.getStudy(StudyInstanceUID);
|
||||
if (!study) {
|
||||
return;
|
||||
}
|
||||
study.isLoaded = true;
|
||||
}
|
||||
|
||||
@@ -434,13 +479,24 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
|
||||
DicomMetadataStore.addSeriesMetadata(seriesSummaryMetadata, madeInClient);
|
||||
|
||||
const seriesDeliveredPromises = seriesPromises.map(promise =>
|
||||
promise.then(instances => {
|
||||
const seriesDeliveredPromises = seriesPromises.map(promise => {
|
||||
if (!returnPromises) {
|
||||
promise?.start();
|
||||
}
|
||||
return promise.then(instances => {
|
||||
storeInstances(instances);
|
||||
})
|
||||
);
|
||||
await Promise.all(seriesDeliveredPromises);
|
||||
setSuccessFlag();
|
||||
});
|
||||
});
|
||||
|
||||
if (returnPromises) {
|
||||
Promise.all(seriesDeliveredPromises).then(() => setSuccessFlag());
|
||||
return seriesPromises;
|
||||
} else {
|
||||
await Promise.all(seriesDeliveredPromises);
|
||||
setSuccessFlag();
|
||||
}
|
||||
|
||||
return seriesSummaryMetadata;
|
||||
},
|
||||
deleteStudyMetadataPromise,
|
||||
getImageIdsForDisplaySet(displaySet) {
|
||||
@@ -470,7 +526,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
||||
|
||||
return imageIds;
|
||||
},
|
||||
getImageIdsForInstance({ instance, frame }) {
|
||||
getImageIdsForInstance({ instance, frame = undefined }) {
|
||||
const imageIds = getImageId({
|
||||
instance,
|
||||
frame,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import retrieveMetadataFiltered from './utils/retrieveMetadataFiltered.js';
|
||||
import RetrieveMetadata from './wado/retrieveMetadata.js';
|
||||
|
||||
const moduleName = 'RetrieveStudyMetadata';
|
||||
@@ -5,14 +6,17 @@ const moduleName = 'RetrieveStudyMetadata';
|
||||
const StudyMetaDataPromises = new Map();
|
||||
|
||||
/**
|
||||
* Retrieves study metadata
|
||||
* Retrieves study metadata.
|
||||
*
|
||||
* @param {Object} server Object with server configuration parameters
|
||||
* @param {Object} dicomWebClient The DICOMWebClient instance to be used for series load
|
||||
* @param {string} StudyInstanceUID The UID of the Study to be retrieved
|
||||
* @param {boolean} enabledStudyLazyLoad Whether the study metadata should be loaded asynchronously.
|
||||
* @param {function} storeInstancesCallback A callback used to store the retrieved instance metadata.
|
||||
* @param {Object} [filters] - Object containing filters to be applied on retrieve metadata process
|
||||
* @param {string} [filter.seriesInstanceUID] - series instance uid to filter results against
|
||||
* @param {boolean} enableStudyLazyLoad Whether the study metadata should be loaded asynchronously.
|
||||
* @param {Object} [filters] Object containing filters to be applied on retrieve metadata process
|
||||
* @param {string} [filters.seriesInstanceUID] Series instance uid to filter results against
|
||||
* @param {array} [filters.SeriesInstanceUIDs] Series instance uids to filter results against
|
||||
* @param {function} [sortCriteria] Sort criteria function
|
||||
* @param {function} [sortFunction] Sort function
|
||||
*
|
||||
* @returns {Promise} that will be resolved with the metadata or rejected with the error
|
||||
*/
|
||||
export function retrieveStudyMetadata(
|
||||
@@ -21,7 +25,8 @@ export function retrieveStudyMetadata(
|
||||
enableStudyLazyLoad,
|
||||
filters,
|
||||
sortCriteria,
|
||||
sortFunction
|
||||
sortFunction,
|
||||
dicomWebConfig = {}
|
||||
) {
|
||||
// @TODO: Whenever a study metadata request has failed, its related promise will be rejected once and for all
|
||||
// and further requests for that metadata will always fail. On failure, we probably need to remove the
|
||||
@@ -34,37 +39,51 @@ export function retrieveStudyMetadata(
|
||||
throw new Error(`${moduleName}: Required 'StudyInstanceUID' parameter not provided.`);
|
||||
}
|
||||
|
||||
const promiseId = `${dicomWebConfig.name}:${StudyInstanceUID}`;
|
||||
|
||||
// Already waiting on result? Return cached promise
|
||||
if (StudyMetaDataPromises.has(StudyInstanceUID)) {
|
||||
return StudyMetaDataPromises.get(StudyInstanceUID);
|
||||
if (StudyMetaDataPromises.has(promiseId)) {
|
||||
return StudyMetaDataPromises.get(promiseId);
|
||||
}
|
||||
|
||||
// Create a promise to handle the data retrieval
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
RetrieveMetadata(
|
||||
let promise;
|
||||
|
||||
if (filters && filters.SeriesInstanceUIDs) {
|
||||
promise = retrieveMetadataFiltered(
|
||||
dicomWebClient,
|
||||
StudyInstanceUID,
|
||||
enableStudyLazyLoad,
|
||||
filters,
|
||||
sortCriteria,
|
||||
sortFunction
|
||||
).then(function (data) {
|
||||
resolve(data);
|
||||
}, reject);
|
||||
});
|
||||
);
|
||||
} else {
|
||||
// Create a promise to handle the data retrieval
|
||||
promise = new Promise((resolve, reject) => {
|
||||
RetrieveMetadata(
|
||||
dicomWebClient,
|
||||
StudyInstanceUID,
|
||||
enableStudyLazyLoad,
|
||||
filters,
|
||||
sortCriteria,
|
||||
sortFunction
|
||||
).then(function (data) {
|
||||
resolve(data);
|
||||
}, reject);
|
||||
});
|
||||
}
|
||||
|
||||
// Store the promise in cache
|
||||
StudyMetaDataPromises.set(StudyInstanceUID, promise);
|
||||
StudyMetaDataPromises.set(promiseId, promise);
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the cached study metadata retrieval promise to ensure that the browser will
|
||||
* re-retrieve the study metadata when it is next requested
|
||||
* re-retrieve the study metadata when it is next requested.
|
||||
*
|
||||
* @param {String} StudyInstanceUID The UID of the Study to be removed from cache
|
||||
*
|
||||
*/
|
||||
export function deleteStudyMetadataPromise(StudyInstanceUID) {
|
||||
if (StudyMetaDataPromises.has(StudyInstanceUID)) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import { api } from 'dicomweb-client';
|
||||
* performing searches doesn't work. This version fixes the query issue
|
||||
* by manually implementing a query option.
|
||||
*/
|
||||
|
||||
export default class StaticWadoClient extends api.DICOMwebClient {
|
||||
static studyFilterKeys = {
|
||||
studyinstanceuid: '0020000D',
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import RetrieveMetadata from '../wado/retrieveMetadata';
|
||||
|
||||
/**
|
||||
* Retrieve metadata filtered.
|
||||
*
|
||||
* @param {*} dicomWebClient The DICOMWebClient instance to be used for series load
|
||||
* @param {*} StudyInstanceUID The UID of the Study to be retrieved
|
||||
* @param {*} enableStudyLazyLoad Whether the study metadata should be loaded asynchronously
|
||||
* @param {object} filters Object containing filters to be applied on retrieve metadata process
|
||||
* @param {string} [filters.seriesInstanceUID] Series instance uid to filter results against
|
||||
* @param {array} [filters.SeriesInstanceUIDs] Series instance uids to filter results against
|
||||
* @param {function} [sortCriteria] Sort criteria function
|
||||
* @param {function} [sortFunction] Sort function
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
function retrieveMetadataFiltered(
|
||||
dicomWebClient,
|
||||
StudyInstanceUID,
|
||||
enableStudyLazyLoad,
|
||||
filters,
|
||||
sortCriteria,
|
||||
sortFunction
|
||||
) {
|
||||
const { SeriesInstanceUIDs } = filters;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const promises = SeriesInstanceUIDs.map(uid => {
|
||||
const seriesSpecificFilters = Object.assign({}, filters, {
|
||||
seriesInstanceUID: uid,
|
||||
});
|
||||
|
||||
return RetrieveMetadata(
|
||||
dicomWebClient,
|
||||
StudyInstanceUID,
|
||||
enableStudyLazyLoad,
|
||||
seriesSpecificFilters,
|
||||
sortCriteria,
|
||||
sortFunction
|
||||
);
|
||||
});
|
||||
|
||||
Promise.all(promises).then(results => {
|
||||
const aggregatedResult = { preLoadData: [], promises: [] };
|
||||
|
||||
results.forEach(({ preLoadData, promises }) => {
|
||||
aggregatedResult.preLoadData = aggregatedResult.preLoadData.concat(preLoadData);
|
||||
aggregatedResult.promises = aggregatedResult.promises.concat(promises);
|
||||
});
|
||||
|
||||
resolve(aggregatedResult);
|
||||
}, reject);
|
||||
});
|
||||
}
|
||||
|
||||
export default retrieveMetadataFiltered;
|
||||
@@ -5,15 +5,20 @@ import RetrieveMetadataLoaderAsync from './retrieveMetadataLoaderAsync';
|
||||
* Retrieve Study metadata from a DICOM server. If the server is configured to use lazy load, only the first series
|
||||
* will be loaded and the property "studyLoader" will be set to let consumer load remaining series as needed.
|
||||
*
|
||||
* @param {Object} dicomWebClient The dicomweb-client.
|
||||
* @param {string} studyInstanceUid The Study Instance UID of the study which needs to be loaded
|
||||
* @param {Object} [filters] - Object containing filters to be applied on retrieve metadata process
|
||||
* @param {string} [filter.seriesInstanceUID] - series instance uid to filter results against
|
||||
* @returns {Object} A study descriptor object
|
||||
* @param {*} dicomWebClient The DICOMWebClient instance to be used for series load
|
||||
* @param {*} StudyInstanceUID The UID of the Study to be retrieved
|
||||
* @param {*} enableStudyLazyLoad Whether the study metadata should be loaded asynchronously
|
||||
* @param {object} filters Object containing filters to be applied on retrieve metadata process
|
||||
* @param {string} [filters.seriesInstanceUID] Series instance uid to filter results against
|
||||
* @param {array} [filters.SeriesInstanceUIDs] Series instance uids to filter results against
|
||||
* @param {function} [sortCriteria] Sort criteria function
|
||||
* @param {function} [sortFunction] Sort function
|
||||
*
|
||||
* @returns {Promise} A promises that resolves the study descriptor object
|
||||
*/
|
||||
async function RetrieveMetadata(
|
||||
dicomWebClient,
|
||||
studyInstanceUid,
|
||||
StudyInstanceUID,
|
||||
enableStudyLazyLoad,
|
||||
filters = {},
|
||||
sortCriteria,
|
||||
@@ -24,7 +29,7 @@ async function RetrieveMetadata(
|
||||
|
||||
const retrieveMetadataLoader = new RetrieveMetadataLoader(
|
||||
dicomWebClient,
|
||||
studyInstanceUid,
|
||||
StudyInstanceUID,
|
||||
filters,
|
||||
sortCriteria,
|
||||
sortFunction
|
||||
|
||||
@@ -11,10 +11,17 @@ export default class RetrieveMetadataLoader {
|
||||
* @param {Object} client The dicomweb-client.
|
||||
* @param {Array} studyInstanceUID Study instance ui to be retrieved
|
||||
* @param {Object} [filters] - Object containing filters to be applied on retrieve metadata process
|
||||
* @param {string} [filter.seriesInstanceUID] - series instance uid to filter results against
|
||||
* @param {Function} [sortSeries] - Custom sort function for series
|
||||
* @param {string} [filters.seriesInstanceUID] - series instance uid to filter results against
|
||||
* @param {Object} [sortCriteria] - Custom sort criteria used for series
|
||||
* @param {Function} [sortFunction] - Custom sort function for series
|
||||
*/
|
||||
constructor(client, studyInstanceUID, filters = {}, sortCriteria, sortFunction) {
|
||||
constructor(
|
||||
client,
|
||||
studyInstanceUID,
|
||||
filters = {},
|
||||
sortCriteria = undefined,
|
||||
sortFunction = undefined
|
||||
) {
|
||||
this.client = client;
|
||||
this.studyInstanceUID = studyInstanceUID;
|
||||
this.filters = filters;
|
||||
@@ -26,7 +33,6 @@ export default class RetrieveMetadataLoader {
|
||||
const preLoadData = await this.preLoad();
|
||||
const loadData = await this.load(preLoadData);
|
||||
const postLoadData = await this.posLoad(loadData);
|
||||
|
||||
return postLoadData;
|
||||
}
|
||||
|
||||
@@ -37,13 +43,9 @@ export default class RetrieveMetadataLoader {
|
||||
async runLoaders(loaders) {
|
||||
let result;
|
||||
for (const loader of loaders) {
|
||||
try {
|
||||
result = await loader();
|
||||
if (result && result.length) {
|
||||
break; // closes iterator in case data is retrieved successfully
|
||||
}
|
||||
} catch (e) {
|
||||
throw e;
|
||||
result = await loader();
|
||||
if (result && result.length) {
|
||||
break; // closes iterator in case data is retrieved successfully
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,65 @@
|
||||
import dcmjs from 'dcmjs';
|
||||
import { sortStudySeries, sortingCriteria } from '@ohif/core/src/utils/sortStudy';
|
||||
import { sortStudySeries } from '@ohif/core/src/utils/sortStudy';
|
||||
import RetrieveMetadataLoader from './retrieveMetadataLoader';
|
||||
|
||||
// Series Date, Series Time, Series Description and Series Number to be included
|
||||
// in the series metadata query result
|
||||
const includeField = ['00080021', '00080031', '0008103E', '00200011'].join(',');
|
||||
|
||||
export class DeferredPromise {
|
||||
metadata = undefined;
|
||||
processFunction = undefined;
|
||||
internalPromise = undefined;
|
||||
thenFunction = undefined;
|
||||
rejectFunction = undefined;
|
||||
|
||||
setMetadata(metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
setProcessFunction(func) {
|
||||
this.processFunction = func;
|
||||
}
|
||||
getPromise() {
|
||||
return this.start();
|
||||
}
|
||||
start() {
|
||||
if (this.internalPromise) {
|
||||
return this.internalPromise;
|
||||
}
|
||||
this.internalPromise = this.processFunction();
|
||||
// in case then and reject functions called before start
|
||||
if (this.thenFunction) {
|
||||
this.then(this.thenFunction);
|
||||
this.thenFunction = undefined;
|
||||
}
|
||||
if (this.rejectFunction) {
|
||||
this.reject(this.rejectFunction);
|
||||
this.rejectFunction = undefined;
|
||||
}
|
||||
return this.internalPromise;
|
||||
}
|
||||
then(func) {
|
||||
if (this.internalPromise) {
|
||||
return this.internalPromise.then(func);
|
||||
} else {
|
||||
this.thenFunction = func;
|
||||
}
|
||||
}
|
||||
reject(func) {
|
||||
if (this.internalPromise) {
|
||||
return this.internalPromise.reject(func);
|
||||
} else {
|
||||
this.rejectFunction = func;
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Creates an immutable series loader object which loads each series sequentially using the iterator interface
|
||||
* Creates an immutable series loader object which loads each series sequentially using the iterator interface.
|
||||
*
|
||||
* @param {DICOMWebClient} dicomWebClient The DICOMWebClient instance to be used for series load
|
||||
* @param {string} studyInstanceUID The Study Instance UID from which series will be loaded
|
||||
* @param {Array} seriesInstanceUIDList A list of Series Instance UIDs
|
||||
*
|
||||
* @returns {Object} Returns an object which supports loading of instances from each of given Series Instance UID
|
||||
*/
|
||||
function makeSeriesAsyncLoader(client, studyInstanceUID, seriesInstanceUIDList) {
|
||||
@@ -14,12 +67,17 @@ function makeSeriesAsyncLoader(client, studyInstanceUID, seriesInstanceUIDList)
|
||||
hasNext() {
|
||||
return seriesInstanceUIDList.length > 0;
|
||||
},
|
||||
async next() {
|
||||
const seriesInstanceUID = seriesInstanceUIDList.shift();
|
||||
return client.retrieveSeriesMetadata({
|
||||
studyInstanceUID,
|
||||
seriesInstanceUID,
|
||||
next() {
|
||||
const { seriesInstanceUID, metadata } = seriesInstanceUIDList.shift();
|
||||
const promise = new DeferredPromise();
|
||||
promise.setMetadata(metadata);
|
||||
promise.setProcessFunction(() => {
|
||||
return client.retrieveSeriesMetadata({
|
||||
studyInstanceUID,
|
||||
seriesInstanceUID,
|
||||
});
|
||||
});
|
||||
return promise;
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -38,15 +96,22 @@ export default class RetrieveMetadataLoaderAsync extends RetrieveMetadataLoader
|
||||
const preLoaders = [];
|
||||
const { studyInstanceUID, filters: { seriesInstanceUID } = {}, client } = this;
|
||||
|
||||
// asking to include Series Date, Series Time, Series Description
|
||||
// and Series Number in the series metadata returned to better sort series
|
||||
// in preLoad function
|
||||
let options = {
|
||||
studyInstanceUID,
|
||||
queryParams: {
|
||||
includefield: includeField,
|
||||
},
|
||||
};
|
||||
|
||||
if (seriesInstanceUID) {
|
||||
const options = {
|
||||
studyInstanceUID,
|
||||
queryParams: { SeriesInstanceUID: seriesInstanceUID },
|
||||
};
|
||||
options.queryParams.SeriesInstanceUID = seriesInstanceUID;
|
||||
preLoaders.push(client.searchForSeries.bind(client, options));
|
||||
}
|
||||
// Fallback preloader
|
||||
preLoaders.push(client.searchForSeries.bind(client, { studyInstanceUID }));
|
||||
preLoaders.push(client.searchForSeries.bind(client, options));
|
||||
|
||||
yield* preLoaders;
|
||||
}
|
||||
@@ -60,24 +125,23 @@ export default class RetrieveMetadataLoaderAsync extends RetrieveMetadataLoader
|
||||
const { naturalizeDataset } = dcmjs.data.DicomMetaDictionary;
|
||||
const naturalized = result.map(naturalizeDataset);
|
||||
|
||||
return sortStudySeries(
|
||||
naturalized,
|
||||
sortCriteria || sortingCriteria.seriesSortCriteria.seriesInfoSortingCriteria,
|
||||
sortFunction
|
||||
);
|
||||
return sortStudySeries(naturalized, sortCriteria, sortFunction);
|
||||
}
|
||||
|
||||
async load(preLoadData) {
|
||||
const { client, studyInstanceUID } = this;
|
||||
|
||||
const seriesInstanceUIDs = preLoadData.map(s => s.SeriesInstanceUID);
|
||||
const seriesInstanceUIDs = preLoadData.map(seriesMetadata => {
|
||||
return { seriesInstanceUID: seriesMetadata.SeriesInstanceUID, metadata: seriesMetadata };
|
||||
});
|
||||
|
||||
const seriesAsyncLoader = makeSeriesAsyncLoader(client, studyInstanceUID, seriesInstanceUIDs);
|
||||
|
||||
const promises = [];
|
||||
|
||||
while (seriesAsyncLoader.hasNext()) {
|
||||
promises.push(seriesAsyncLoader.next());
|
||||
const promise = seriesAsyncLoader.next();
|
||||
promises.push(promise);
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -9,7 +9,7 @@ import { createDicomWebApi } from '../DicomWebDataSource/index';
|
||||
* dicomWeb configuration array
|
||||
*
|
||||
*/
|
||||
function createDicomWebProxyApi(dicomWebProxyConfig, UserAuthenticationService) {
|
||||
function createDicomWebProxyApi(dicomWebProxyConfig, servicesManager) {
|
||||
const { name } = dicomWebProxyConfig;
|
||||
let dicomWebDelegate = undefined;
|
||||
|
||||
@@ -28,7 +28,7 @@ function createDicomWebProxyApi(dicomWebProxyConfig, UserAuthenticationService)
|
||||
|
||||
dicomWebDelegate = createDicomWebApi(
|
||||
data.servers.dicomWeb[0].configuration,
|
||||
UserAuthenticationService
|
||||
servicesManager
|
||||
);
|
||||
dicomWebDelegate.initialize({ params, query });
|
||||
}
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
import { DicomMetadataStore, IWebApiDataSource } from '@ohif/core';
|
||||
import {
|
||||
mergeMap,
|
||||
callForAllDataSourcesAsync,
|
||||
callForAllDataSources,
|
||||
callForDefaultDataSource,
|
||||
callByRetrieveAETitle,
|
||||
createMergeDataSourceApi,
|
||||
} from './index';
|
||||
|
||||
jest.mock('@ohif/core');
|
||||
|
||||
describe('MergeDataSource', () => {
|
||||
let path,
|
||||
sourceName,
|
||||
mergeConfig,
|
||||
extensionManager,
|
||||
series1,
|
||||
series2,
|
||||
series3,
|
||||
series4,
|
||||
mergeKey,
|
||||
tagFunc,
|
||||
dataSourceAndSeriesMap,
|
||||
dataSourceAndUIDsMap,
|
||||
dataSourceAndDSMap,
|
||||
pathSync;
|
||||
|
||||
beforeAll(() => {
|
||||
path = 'query.series.search';
|
||||
pathSync = 'getImageIdsForInstance';
|
||||
tagFunc = jest.fn((data, sourceName) =>
|
||||
data.map(item => ({ ...item, RetrieveAETitle: sourceName }))
|
||||
);
|
||||
sourceName = 'dicomweb1';
|
||||
mergeKey = 'seriesInstanceUid';
|
||||
series1 = { [mergeKey]: '123' };
|
||||
series2 = { [mergeKey]: '234' };
|
||||
series3 = { [mergeKey]: '345' };
|
||||
series4 = { [mergeKey]: '456' };
|
||||
mergeConfig = {
|
||||
seriesMerge: {
|
||||
dataSourceNames: ['dicomweb1', 'dicomweb2'],
|
||||
defaultDataSourceName: 'dicomweb1',
|
||||
},
|
||||
};
|
||||
dataSourceAndSeriesMap = {
|
||||
dataSource1: series1,
|
||||
dataSource2: series2,
|
||||
dataSource3: series3,
|
||||
};
|
||||
dataSourceAndUIDsMap = {
|
||||
dataSource1: ['123'],
|
||||
dataSource2: ['234'],
|
||||
dataSource3: ['345'],
|
||||
};
|
||||
dataSourceAndDSMap = {
|
||||
dataSource1: {
|
||||
displaySet: {
|
||||
StudyInstanceUID: '123',
|
||||
SeriesInstanceUID: '123',
|
||||
},
|
||||
},
|
||||
dataSource2: {
|
||||
displaySet: {
|
||||
StudyInstanceUID: '234',
|
||||
SeriesInstanceUID: '234',
|
||||
},
|
||||
},
|
||||
dataSource3: {
|
||||
displaySet: {
|
||||
StudyInstanceUID: '345',
|
||||
SeriesInstanceUID: '345',
|
||||
},
|
||||
},
|
||||
};
|
||||
extensionManager = {
|
||||
dataSourceDefs: {
|
||||
dataSource1: {
|
||||
sourceName: 'dataSource1',
|
||||
configuration: {},
|
||||
},
|
||||
dataSource2: {
|
||||
sourceName: 'dataSource2',
|
||||
configuration: {},
|
||||
},
|
||||
dataSource3: {
|
||||
sourceName: 'dataSource3',
|
||||
configuration: {},
|
||||
},
|
||||
},
|
||||
getDataSources: jest.fn(dataSourceName => [
|
||||
{
|
||||
[path]: jest.fn().mockResolvedValue([dataSourceAndSeriesMap[dataSourceName]]),
|
||||
},
|
||||
]),
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('callForAllDataSourcesAsync', () => {
|
||||
it('should call the correct functions and return the merged data', async () => {
|
||||
/** Arrange */
|
||||
extensionManager.getDataSources = jest.fn(dataSourceName => [
|
||||
{
|
||||
[path]: jest.fn().mockResolvedValue([dataSourceAndSeriesMap[dataSourceName]]),
|
||||
},
|
||||
]);
|
||||
|
||||
/** Act */
|
||||
const data = await callForAllDataSourcesAsync({
|
||||
mergeMap,
|
||||
path,
|
||||
args: [],
|
||||
extensionManager,
|
||||
dataSourceNames: ['dataSource1', 'dataSource2'],
|
||||
});
|
||||
|
||||
/** Assert */
|
||||
expect(extensionManager.getDataSources).toHaveBeenCalledTimes(2);
|
||||
expect(extensionManager.getDataSources).toHaveBeenCalledWith('dataSource1');
|
||||
expect(extensionManager.getDataSources).toHaveBeenCalledWith('dataSource2');
|
||||
expect(data).toEqual([series1, series2]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('callForAllDataSources', () => {
|
||||
it('should call the correct functions and return the merged data', () => {
|
||||
/** Arrange */
|
||||
extensionManager.getDataSources = jest.fn(dataSourceName => [
|
||||
{
|
||||
[pathSync]: () => dataSourceAndUIDsMap[dataSourceName],
|
||||
},
|
||||
]);
|
||||
|
||||
/** Act */
|
||||
const data = callForAllDataSources({
|
||||
path: pathSync,
|
||||
args: [],
|
||||
extensionManager,
|
||||
dataSourceNames: ['dataSource2', 'dataSource3'],
|
||||
});
|
||||
|
||||
/** Assert */
|
||||
expect(extensionManager.getDataSources).toHaveBeenCalledTimes(2);
|
||||
expect(extensionManager.getDataSources).toHaveBeenCalledWith('dataSource2');
|
||||
expect(extensionManager.getDataSources).toHaveBeenCalledWith('dataSource3');
|
||||
expect(data).toEqual(['234', '345']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('callForDefaultDataSource', () => {
|
||||
it('should call the correct function and return the data', () => {
|
||||
/** Arrange */
|
||||
extensionManager.getDataSources = jest.fn(dataSourceName => [
|
||||
{
|
||||
[pathSync]: () => dataSourceAndUIDsMap[dataSourceName],
|
||||
},
|
||||
]);
|
||||
|
||||
/** Act */
|
||||
const data = callForDefaultDataSource({
|
||||
path: pathSync,
|
||||
args: [],
|
||||
extensionManager,
|
||||
defaultDataSourceName: 'dataSource2',
|
||||
});
|
||||
|
||||
/** Assert */
|
||||
expect(extensionManager.getDataSources).toHaveBeenCalledTimes(1);
|
||||
expect(extensionManager.getDataSources).toHaveBeenCalledWith('dataSource2');
|
||||
expect(data).toEqual(['234']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('callByRetrieveAETitle', () => {
|
||||
it('should call the correct function and return the data', () => {
|
||||
/** Arrange */
|
||||
DicomMetadataStore.getSeries.mockImplementationOnce(() => [series2]);
|
||||
extensionManager.getDataSources = jest.fn(dataSourceName => [
|
||||
{
|
||||
[pathSync]: () => dataSourceAndUIDsMap[dataSourceName],
|
||||
},
|
||||
]);
|
||||
|
||||
/** Act */
|
||||
const data = callByRetrieveAETitle({
|
||||
path: pathSync,
|
||||
args: [dataSourceAndDSMap['dataSource2']],
|
||||
extensionManager,
|
||||
defaultDataSourceName: 'dataSource2',
|
||||
});
|
||||
|
||||
/** Assert */
|
||||
expect(extensionManager.getDataSources).toHaveBeenCalledTimes(1);
|
||||
expect(extensionManager.getDataSources).toHaveBeenCalledWith('dataSource2');
|
||||
expect(data).toEqual(['234']);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,293 @@
|
||||
import { DicomMetadataStore, IWebApiDataSource } from '@ohif/core';
|
||||
import { get, uniqBy } from 'lodash';
|
||||
import {
|
||||
MergeConfig,
|
||||
CallForAllDataSourcesAsyncOptions,
|
||||
CallForAllDataSourcesOptions,
|
||||
CallForDefaultDataSourceOptions,
|
||||
CallByRetrieveAETitleOptions,
|
||||
MergeMap,
|
||||
} from './types';
|
||||
|
||||
export const mergeMap: MergeMap = {
|
||||
'query.studies.search': {
|
||||
mergeKey: 'studyInstanceUid',
|
||||
tagFunc: x => x,
|
||||
},
|
||||
'query.series.search': {
|
||||
mergeKey: 'seriesInstanceUid',
|
||||
tagFunc: (series, sourceName) => {
|
||||
series.forEach(series => {
|
||||
series.RetrieveAETitle = sourceName;
|
||||
DicomMetadataStore.updateSeriesMetadata(series);
|
||||
});
|
||||
return series;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Calls all data sources asynchronously and merges the results.
|
||||
* @param {CallForAllDataSourcesAsyncOptions} options - The options for calling all data sources.
|
||||
* @param {string} options.path - The path to the function to be called on each data source.
|
||||
* @param {unknown[]} options.args - The arguments to be passed to the function.
|
||||
* @param {ExtensionManager} options.extensionManager - The extension manager.
|
||||
* @param {string[]} options.dataSourceNames - The names of the data sources to be called.
|
||||
* @param {string} options.defaultDataSourceName - The name of the default data source.
|
||||
* @returns {Promise<unknown[]>} - A promise that resolves to the merged data from all data sources.
|
||||
*/
|
||||
export const callForAllDataSourcesAsync = async ({
|
||||
mergeMap,
|
||||
path,
|
||||
args,
|
||||
extensionManager,
|
||||
dataSourceNames,
|
||||
defaultDataSourceName,
|
||||
}: CallForAllDataSourcesAsyncOptions) => {
|
||||
const { mergeKey, tagFunc } = mergeMap[path] || { tagFunc: x => x };
|
||||
|
||||
/** Sort by default data source */
|
||||
const defs = Object.values(extensionManager.dataSourceDefs);
|
||||
const defaultDataSourceDef = defs.find(def => def.sourceName === defaultDataSourceName);
|
||||
const dataSourceDefs = defs.filter(def => def.sourceName !== defaultDataSourceName);
|
||||
if (defaultDataSourceDef) {
|
||||
dataSourceDefs.unshift(defaultDataSourceDef);
|
||||
}
|
||||
|
||||
const promises = [];
|
||||
const sourceNames = [];
|
||||
|
||||
for (const dataSourceDef of dataSourceDefs) {
|
||||
const { configuration, sourceName } = dataSourceDef;
|
||||
if (!!configuration && dataSourceNames.includes(sourceName)) {
|
||||
const [dataSource] = extensionManager.getDataSources(sourceName);
|
||||
const func = get(dataSource, path);
|
||||
const promise = func.apply(dataSource, args);
|
||||
promises.push(promise);
|
||||
sourceNames.push(sourceName);
|
||||
}
|
||||
}
|
||||
|
||||
const data = await Promise.allSettled(promises);
|
||||
const mergedData = data.map((data, i) => tagFunc(data.value, sourceNames[i]));
|
||||
|
||||
let results = [];
|
||||
if (mergeKey) {
|
||||
results = uniqBy(mergedData.flat(), obj => get(obj, mergeKey));
|
||||
} else {
|
||||
results = mergedData.flat();
|
||||
}
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calls all data sources that match the provided names and merges their data.
|
||||
* @param options - The options for calling all data sources.
|
||||
* @param options.path - The path to the function to be called on each data source.
|
||||
* @param options.args - The arguments to be passed to the function.
|
||||
* @param options.extensionManager - The extension manager instance.
|
||||
* @param options.dataSourceNames - The names of the data sources to be called.
|
||||
* @param options.defaultDataSourceName - The name of the default data source.
|
||||
* @returns The merged data from all the matching data sources.
|
||||
*/
|
||||
export const callForAllDataSources = ({
|
||||
path,
|
||||
args,
|
||||
extensionManager,
|
||||
dataSourceNames,
|
||||
defaultDataSourceName,
|
||||
}: CallForAllDataSourcesOptions) => {
|
||||
/** Sort by default data source */
|
||||
const defs = Object.values(extensionManager.dataSourceDefs);
|
||||
const defaultDataSourceDef = defs.find(def => def.sourceName === defaultDataSourceName);
|
||||
const dataSourceDefs = defs.filter(def => def.sourceName !== defaultDataSourceName);
|
||||
if (defaultDataSourceDef) {
|
||||
dataSourceDefs.unshift(defaultDataSourceDef);
|
||||
}
|
||||
|
||||
const mergedData = [];
|
||||
for (const dataSourceDef of dataSourceDefs) {
|
||||
const { configuration, sourceName } = dataSourceDef;
|
||||
if (!!configuration && dataSourceNames.includes(sourceName)) {
|
||||
const [dataSource] = extensionManager.getDataSources(sourceName);
|
||||
const func = get(dataSource, path);
|
||||
const data = func.apply(dataSource, args);
|
||||
mergedData.push(data);
|
||||
}
|
||||
}
|
||||
|
||||
return mergedData.flat();
|
||||
};
|
||||
|
||||
/**
|
||||
* Calls the default data source function specified by the given path with the provided arguments.
|
||||
* @param {CallForDefaultDataSourceOptions} options - The options for calling the default data source.
|
||||
* @param {string} options.path - The path to the function within the default data source.
|
||||
* @param {unknown[]} options.args - The arguments to pass to the function.
|
||||
* @param {string} options.defaultDataSourceName - The name of the default data source.
|
||||
* @param {ExtensionManager} options.extensionManager - The extension manager instance.
|
||||
* @returns {unknown} - The result of calling the default data source function.
|
||||
*/
|
||||
export const callForDefaultDataSource = ({
|
||||
path,
|
||||
args,
|
||||
defaultDataSourceName,
|
||||
extensionManager,
|
||||
}: CallForDefaultDataSourceOptions) => {
|
||||
const [dataSource] = extensionManager.getDataSources(defaultDataSourceName);
|
||||
const func = get(dataSource, path);
|
||||
return func.apply(dataSource, args);
|
||||
};
|
||||
|
||||
/**
|
||||
* Calls the data source specified by the RetrieveAETitle of the given display set.
|
||||
* @typedef {Object} CallByRetrieveAETitleOptions
|
||||
* @property {string} path - The path of the method to call on the data source.
|
||||
* @property {any[]} args - The arguments to pass to the method.
|
||||
* @property {string} defaultDataSourceName - The name of the default data source.
|
||||
* @property {ExtensionManager} extensionManager - The extension manager.
|
||||
*/
|
||||
export const callByRetrieveAETitle = ({
|
||||
path,
|
||||
args,
|
||||
defaultDataSourceName,
|
||||
extensionManager,
|
||||
}: CallByRetrieveAETitleOptions) => {
|
||||
const [displaySet] = args;
|
||||
const seriesMetadata = DicomMetadataStore.getSeries(
|
||||
displaySet.StudyInstanceUID,
|
||||
displaySet.SeriesInstanceUID
|
||||
);
|
||||
const [dataSource] = extensionManager.getDataSources(
|
||||
seriesMetadata.RetrieveAETitle || defaultDataSourceName
|
||||
);
|
||||
return dataSource[path](...args);
|
||||
};
|
||||
|
||||
function createMergeDataSourceApi(
|
||||
mergeConfig: MergeConfig,
|
||||
servicesManager: unknown,
|
||||
extensionManager
|
||||
) {
|
||||
const { seriesMerge } = mergeConfig;
|
||||
const { dataSourceNames, defaultDataSourceName } = seriesMerge;
|
||||
|
||||
const implementation = {
|
||||
initialize: (...args: unknown[]) =>
|
||||
callForAllDataSources({
|
||||
path: 'initialize',
|
||||
args,
|
||||
extensionManager,
|
||||
dataSourceNames,
|
||||
defaultDataSourceName,
|
||||
}),
|
||||
query: {
|
||||
studies: {
|
||||
search: (...args: unknown[]) =>
|
||||
callForAllDataSourcesAsync({
|
||||
mergeMap,
|
||||
path: 'query.studies.search',
|
||||
args,
|
||||
extensionManager,
|
||||
dataSourceNames,
|
||||
defaultDataSourceName,
|
||||
}),
|
||||
},
|
||||
series: {
|
||||
search: (...args: unknown[]) =>
|
||||
callForAllDataSourcesAsync({
|
||||
mergeMap,
|
||||
path: 'query.series.search',
|
||||
args,
|
||||
extensionManager,
|
||||
dataSourceNames,
|
||||
defaultDataSourceName,
|
||||
}),
|
||||
},
|
||||
instances: {
|
||||
search: (...args: unknown[]) =>
|
||||
callForAllDataSourcesAsync({
|
||||
mergeMap,
|
||||
path: 'query.instances.search',
|
||||
args,
|
||||
extensionManager,
|
||||
dataSourceNames,
|
||||
defaultDataSourceName,
|
||||
}),
|
||||
},
|
||||
},
|
||||
retrieve: {
|
||||
bulkDataURI: (...args: unknown[]) =>
|
||||
callForAllDataSourcesAsync({
|
||||
mergeMap,
|
||||
path: 'retrieve.bulkDataURI',
|
||||
args,
|
||||
extensionManager,
|
||||
dataSourceNames,
|
||||
defaultDataSourceName,
|
||||
}),
|
||||
directURL: (...args: unknown[]) =>
|
||||
callForDefaultDataSource({
|
||||
path: 'retrieve.directURL',
|
||||
args,
|
||||
defaultDataSourceName,
|
||||
extensionManager,
|
||||
}),
|
||||
series: {
|
||||
metadata: (...args: unknown[]) =>
|
||||
callForAllDataSourcesAsync({
|
||||
mergeMap,
|
||||
path: 'retrieve.series.metadata',
|
||||
args,
|
||||
extensionManager,
|
||||
dataSourceNames,
|
||||
defaultDataSourceName,
|
||||
}),
|
||||
},
|
||||
},
|
||||
store: {
|
||||
dicom: (...args: unknown[]) =>
|
||||
callForDefaultDataSource({
|
||||
path: 'store.dicom',
|
||||
args,
|
||||
defaultDataSourceName,
|
||||
extensionManager,
|
||||
}),
|
||||
},
|
||||
deleteStudyMetadataPromise: (...args: unknown[]) =>
|
||||
callForAllDataSources({
|
||||
path: 'deleteStudyMetadataPromise',
|
||||
args,
|
||||
extensionManager,
|
||||
dataSourceNames,
|
||||
defaultDataSourceName,
|
||||
}),
|
||||
getImageIdsForDisplaySet: (...args: unknown[]) =>
|
||||
callByRetrieveAETitle({
|
||||
path: 'getImageIdsForDisplaySet',
|
||||
args,
|
||||
defaultDataSourceName,
|
||||
extensionManager,
|
||||
}),
|
||||
getImageIdsForInstance: (...args: unknown[]) =>
|
||||
callByRetrieveAETitle({
|
||||
path: 'getImageIdsForDisplaySet',
|
||||
args,
|
||||
defaultDataSourceName,
|
||||
extensionManager,
|
||||
}),
|
||||
getStudyInstanceUIDs: (...args: unknown[]) =>
|
||||
callForAllDataSources({
|
||||
path: 'getStudyInstanceUIDs',
|
||||
args,
|
||||
extensionManager,
|
||||
dataSourceNames,
|
||||
defaultDataSourceName,
|
||||
}),
|
||||
};
|
||||
|
||||
return IWebApiDataSource.create(implementation);
|
||||
}
|
||||
|
||||
export { createMergeDataSourceApi };
|
||||
@@ -0,0 +1,46 @@
|
||||
import { ExtensionManager } from '@ohif/core';
|
||||
|
||||
export type MergeMap = {
|
||||
[key: string]: {
|
||||
mergeKey: string;
|
||||
tagFunc: (data: unknown[], sourceName: string) => unknown[];
|
||||
};
|
||||
};
|
||||
|
||||
export type CallForAllDataSourcesAsyncOptions = {
|
||||
mergeMap: object;
|
||||
path: string;
|
||||
args: unknown[];
|
||||
dataSourceNames: string[];
|
||||
extensionManager: ExtensionManager;
|
||||
defaultDataSourceName: string;
|
||||
};
|
||||
|
||||
export type CallForAllDataSourcesOptions = {
|
||||
path: string;
|
||||
args: unknown[];
|
||||
dataSourceNames: string[];
|
||||
extensionManager: ExtensionManager;
|
||||
defaultDataSourceName: string;
|
||||
};
|
||||
|
||||
export type CallForDefaultDataSourceOptions = {
|
||||
path: string;
|
||||
args: unknown[];
|
||||
defaultDataSourceName: string;
|
||||
extensionManager: ExtensionManager;
|
||||
};
|
||||
|
||||
export type CallByRetrieveAETitleOptions = {
|
||||
path: string;
|
||||
args: unknown[];
|
||||
defaultDataSourceName: string;
|
||||
extensionManager: ExtensionManager;
|
||||
};
|
||||
|
||||
export type MergeConfig = {
|
||||
seriesMerge: {
|
||||
dataSourceNames: string[];
|
||||
defaultDataSourceName: string;
|
||||
};
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { utils, ServicesManager } from '@ohif/core';
|
||||
import { MeasurementTable, Dialog, Input, useViewportGrid, ButtonEnums } from '@ohif/ui';
|
||||
import ActionButtons from './ActionButtons';
|
||||
@@ -18,6 +19,8 @@ export default function PanelMeasurementTable({
|
||||
commandsManager,
|
||||
extensionManager,
|
||||
}): React.FunctionComponent {
|
||||
const { t } = useTranslation('MeasurementTable');
|
||||
|
||||
const [viewportGrid, viewportGridService] = useViewportGrid();
|
||||
const { activeViewportId, viewports } = viewportGrid;
|
||||
const { measurementService, uiDialogService, uiNotificationService, displaySetService } = (
|
||||
@@ -209,7 +212,7 @@ export default function PanelMeasurementTable({
|
||||
data-cy={'measurements-panel'}
|
||||
>
|
||||
<MeasurementTable
|
||||
title="Measurements"
|
||||
title={t("Measurements")}
|
||||
servicesManager={servicesManager}
|
||||
data={displayMeasurements}
|
||||
onClick={jumpToImage}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
//
|
||||
import PanelStudyBrowser from './PanelStudyBrowser';
|
||||
@@ -18,7 +18,10 @@ function WrappedPanelStudyBrowser({ commandsManager, extensionManager, servicesM
|
||||
// already determined our datasource
|
||||
const dataSource = extensionManager.getDataSources()[0];
|
||||
const _getStudiesForPatientByMRN = getStudiesForPatientByMRN.bind(null, dataSource);
|
||||
const _getImageSrcFromImageId = _createGetImageSrcFromImageIdFn(extensionManager);
|
||||
const _getImageSrcFromImageId = useCallback(
|
||||
_createGetImageSrcFromImageIdFn(extensionManager),
|
||||
[]
|
||||
);
|
||||
const _requestDisplaySetCreationForStudy = requestDisplaySetCreationForStudy.bind(
|
||||
null,
|
||||
dataSource
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable react/display-name */
|
||||
import React from 'react';
|
||||
|
||||
import { ButtonEnums, Dialog, Input, Select } from '@ohif/ui';
|
||||
|
||||
export const CREATE_REPORT_DIALOG_RESPONSE = {
|
||||
@@ -7,7 +7,7 @@ export const CREATE_REPORT_DIALOG_RESPONSE = {
|
||||
CREATE_REPORT: 1,
|
||||
};
|
||||
|
||||
export default function createReportDialogPrompt(uiDialogService, { extensionManager }) {
|
||||
export default function CreateReportDialogPrompt(uiDialogService, { extensionManager }) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
let dialogId = undefined;
|
||||
|
||||
@@ -97,33 +97,38 @@ export default function createReportDialogPrompt(uiDialogService, { extensionMan
|
||||
};
|
||||
return (
|
||||
<>
|
||||
{dataSourcesOpts.length > 1 && (
|
||||
<Select
|
||||
closeMenuOnSelect={true}
|
||||
className="border-primary-main mr-2 bg-black"
|
||||
options={dataSourcesOpts}
|
||||
placeholder={
|
||||
dataSourcesOpts.find(option => option.value === value.dataSourceName)
|
||||
.placeHolder
|
||||
}
|
||||
value={value.dataSourceName}
|
||||
onChange={evt => {
|
||||
setValue(v => ({ ...v, dataSourceName: evt.value }));
|
||||
}}
|
||||
isClearable={false}
|
||||
/>
|
||||
{dataSourcesOpts.length > 1 && window.config?.allowMultiSelectExport && (
|
||||
<div>
|
||||
<label className="text-[14px] leading-[1.2] text-white">Data Source</label>
|
||||
<Select
|
||||
closeMenuOnSelect={true}
|
||||
className="border-primary-main mt-2 bg-black"
|
||||
options={dataSourcesOpts}
|
||||
placeholder={
|
||||
dataSourcesOpts.find(option => option.value === value.dataSourceName)
|
||||
.placeHolder
|
||||
}
|
||||
value={value.dataSourceName}
|
||||
onChange={evt => {
|
||||
setValue(v => ({ ...v, dataSourceName: evt.value }));
|
||||
}}
|
||||
isClearable={false}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<Input
|
||||
autoFocus
|
||||
label="Enter the report name"
|
||||
labelClassName="text-white text-[14px] leading-[1.2]"
|
||||
className="border-primary-main bg-black"
|
||||
type="text"
|
||||
value={value.label}
|
||||
onChange={onChangeHandler}
|
||||
onKeyPress={onKeyPressHandler}
|
||||
required
|
||||
/>
|
||||
<div className="mt-3">
|
||||
<Input
|
||||
autoFocus
|
||||
label="Enter the report name"
|
||||
labelClassName="text-white text-[14px] leading-[1.2]"
|
||||
className="border-primary-main bg-black"
|
||||
type="text"
|
||||
value={value.label}
|
||||
onChange={onChangeHandler}
|
||||
onKeyPress={onKeyPressHandler}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
},
|
||||
|
||||
@@ -1,19 +1,34 @@
|
||||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import { useViewportGrid } from '@ohif/ui';
|
||||
|
||||
export default function Toolbar({ servicesManager }) {
|
||||
export default function Toolbar({
|
||||
servicesManager,
|
||||
}: Types.Extensions.ExtensionParams): React.ReactElement {
|
||||
const { toolbarService } = servicesManager.services;
|
||||
|
||||
const [viewportGrid, viewportGridService] = useViewportGrid();
|
||||
|
||||
const [toolbarButtons, setToolbarButtons] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
const { unsubscribe } = toolbarService.subscribe(toolbarService.EVENTS.TOOL_BAR_MODIFIED, () =>
|
||||
setToolbarButtons(toolbarService.getButtonSection('primary'))
|
||||
const updateToolbar = () => {
|
||||
const toolGroupId =
|
||||
viewportGridService.getActiveViewportOptionByKey('toolGroupId') ?? 'default';
|
||||
setToolbarButtons(toolbarService.getButtonSection(toolGroupId));
|
||||
};
|
||||
|
||||
const { unsubscribe } = toolbarService.subscribe(
|
||||
toolbarService.EVENTS.TOOL_BAR_MODIFIED,
|
||||
updateToolbar
|
||||
);
|
||||
|
||||
updateToolbar();
|
||||
|
||||
return () => {
|
||||
unsubscribe();
|
||||
};
|
||||
}, [toolbarService]);
|
||||
}, [toolbarService, viewportGrid]);
|
||||
|
||||
const onInteraction = useCallback(
|
||||
args => toolbarService.recordInteraction(args),
|
||||
|
||||
@@ -65,7 +65,7 @@ ToolbarButtonWithServices.propTypes = {
|
||||
state: PropTypes.shape({
|
||||
primaryToolId: PropTypes.string,
|
||||
toggles: PropTypes.objectOf(PropTypes.bool),
|
||||
groups: PropTypes.objectOf(PropTypes.object),
|
||||
groups: PropTypes.objectOf(PropTypes.any),
|
||||
}).isRequired,
|
||||
}).isRequired,
|
||||
}).isRequired,
|
||||
|
||||
@@ -53,7 +53,7 @@ function ViewerHeader({ hotkeysManager, extensionManager, servicesManager }) {
|
||||
onClick: () =>
|
||||
show({
|
||||
content: AboutModal,
|
||||
title: 'About OHIF Viewer',
|
||||
title: t('AboutModal:About OHIF Viewer'),
|
||||
contentProps: { versionNumber, commitHash },
|
||||
}),
|
||||
},
|
||||
@@ -62,7 +62,7 @@ function ViewerHeader({ hotkeysManager, extensionManager, servicesManager }) {
|
||||
icon: 'settings',
|
||||
onClick: () =>
|
||||
show({
|
||||
title: t('UserPreferencesModal:User Preferences'),
|
||||
title: t('UserPreferencesModal:User preferences'),
|
||||
content: UserPreferences,
|
||||
contentProps: {
|
||||
hotkeyDefaults: hotkeysManager.getValidHotkeyDefinitions(hotkeyDefaults),
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { SidePanel, ErrorBoundary, LoadingIndicatorProgress } from '@ohif/ui';
|
||||
import {
|
||||
SidePanel,
|
||||
ErrorBoundary,
|
||||
LoadingIndicatorProgress,
|
||||
InvestigationalUseDialog,
|
||||
} from '@ohif/ui';
|
||||
import { ServicesManager, HangingProtocolService, CommandsManager } from '@ohif/core';
|
||||
import { useAppConfig } from '@state';
|
||||
import ViewerHeader from './ViewerHeader';
|
||||
@@ -152,6 +157,8 @@ function ViewerLayout({
|
||||
) : null}
|
||||
</React.Fragment>
|
||||
</div>
|
||||
|
||||
<InvestigationalUseDialog dialogConfiguration={appConfig?.investigationalUseDialog} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -121,7 +121,10 @@ const commandsModule = ({
|
||||
if (!button.id) {
|
||||
return;
|
||||
}
|
||||
const { commands, items } = button.props || button;
|
||||
const { commands, items, primary } = button.props || button;
|
||||
if (primary) {
|
||||
enableListener(primary);
|
||||
}
|
||||
if (items) {
|
||||
items.forEach(enableListener);
|
||||
}
|
||||
@@ -241,7 +244,6 @@ const commandsModule = ({
|
||||
];
|
||||
stateSyncService.store(stateSyncReduce);
|
||||
// This is a default action applied
|
||||
const { protocol } = hangingProtocolService.getActiveProtocol();
|
||||
actions.toggleHpTools();
|
||||
|
||||
// try to use the same tool in the new hanging protocol stage
|
||||
@@ -264,16 +266,6 @@ const commandsModule = ({
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Send the notification about updating the state
|
||||
if (protocolId !== hpInfo.protocolId) {
|
||||
// The old protocol callbacks are used for turning off things
|
||||
// like crosshairs when moving to the new HP
|
||||
commandsManager.run(oldProtocol.callbacks?.onProtocolExit);
|
||||
// The new protocol callback is used for things like
|
||||
// activating modes etc.
|
||||
}
|
||||
commandsManager.run(protocol.callbacks?.onProtocolEnter);
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
||||
@@ -6,6 +6,7 @@ import { createDicomWebApi } from './DicomWebDataSource/index.js';
|
||||
import { createDicomJSONApi } from './DicomJSONDataSource/index.js';
|
||||
import { createDicomLocalApi } from './DicomLocalDataSource/index.js';
|
||||
import { createDicomWebProxyApi } from './DicomWebProxyDataSource/index.js';
|
||||
import { createMergeDataSourceApi } from './MergeDataSource/index';
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -32,6 +33,11 @@ function getDataSourcesModule() {
|
||||
type: 'localApi',
|
||||
createDataSource: createDicomLocalApi,
|
||||
},
|
||||
{
|
||||
name: 'merge',
|
||||
type: 'mergeApi',
|
||||
createDataSource: createMergeDataSourceApi,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -13,12 +13,12 @@ export default function getDisplaySetMessages(
|
||||
isReconstructable: boolean
|
||||
): DisplaySetMessageList {
|
||||
const messages = new DisplaySetMessageList();
|
||||
const firstInstance = instances[0];
|
||||
if (!instances.length || firstInstance) {
|
||||
if (!instances.length) {
|
||||
messages.addMessage(DisplaySetMessage.CODES.NO_VALID_INSTANCES);
|
||||
return;
|
||||
}
|
||||
|
||||
const firstInstance = instances[0];
|
||||
const { Modality, ImageType, NumberOfFrames } = firstInstance;
|
||||
// Due to current requirements, LOCALIZER series doesn't have any messages
|
||||
if (ImageType?.includes('LOCALIZER')) {
|
||||
|
||||
@@ -14,6 +14,7 @@ const defaultProtocol = {
|
||||
editableBy: {},
|
||||
protocolMatchingRules: [],
|
||||
toolGroupIds: ['default'],
|
||||
hpInitiationCriteria: { minSeriesLoaded: 1 },
|
||||
// -1 would be used to indicate active only, whereas other values are
|
||||
// the number of required priors referenced - so 0 means active with
|
||||
// 0 or more priors.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { WrappedPanelStudyBrowser, PanelMeasurementTable } from './Panels';
|
||||
import i18n from 'i18next';
|
||||
|
||||
// TODO:
|
||||
// - No loading UI exists yet
|
||||
@@ -22,7 +23,7 @@ function getPanelModule({ commandsManager, extensionManager, servicesManager })
|
||||
name: 'seriesList',
|
||||
iconName: 'tab-studies',
|
||||
iconLabel: 'Studies',
|
||||
label: 'Studies',
|
||||
label: i18n.t('SidePanel:Studies'),
|
||||
component: WrappedPanelStudyBrowser.bind(null, {
|
||||
commandsManager,
|
||||
extensionManager,
|
||||
@@ -33,8 +34,8 @@ function getPanelModule({ commandsManager, extensionManager, servicesManager })
|
||||
name: 'measure',
|
||||
iconName: 'tab-linear',
|
||||
iconLabel: 'Measure',
|
||||
label: 'Measurements',
|
||||
secondaryLabel: 'Measurements',
|
||||
label: i18n.t('SidePanel:Measurements'),
|
||||
secondaryLabel: i18n.t('SidePanel:Measurements'),
|
||||
component: wrappedMeasurementPanel,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -51,36 +51,41 @@ export default function init({ servicesManager, configuration = {} }): void {
|
||||
const handlePETImageMetadata = ({ SeriesInstanceUID, StudyInstanceUID }) => {
|
||||
const { instances } = DicomMetadataStore.getSeries(StudyInstanceUID, SeriesInstanceUID);
|
||||
|
||||
const modality = instances[0].Modality;
|
||||
if (modality !== 'PT') {
|
||||
if (!instances?.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const modality = instances[0].Modality;
|
||||
|
||||
if (!modality || modality !== 'PT') {
|
||||
return;
|
||||
}
|
||||
|
||||
const imageIds = instances.map(instance => instance.imageId);
|
||||
const instanceMetadataArray = [];
|
||||
imageIds.forEach(imageId => {
|
||||
const instanceMetadata = getPTImageIdInstanceMetadata(imageId);
|
||||
if (instanceMetadata) {
|
||||
instanceMetadataArray.push(instanceMetadata);
|
||||
}
|
||||
});
|
||||
|
||||
if (!instanceMetadataArray.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// try except block to prevent errors when the metadata is not correct
|
||||
let suvScalingFactors;
|
||||
try {
|
||||
suvScalingFactors = calculateSUVScalingFactors(instanceMetadataArray);
|
||||
imageIds.forEach(imageId => {
|
||||
const instanceMetadata = getPTImageIdInstanceMetadata(imageId);
|
||||
if (instanceMetadata) {
|
||||
instanceMetadataArray.push(instanceMetadata);
|
||||
}
|
||||
});
|
||||
|
||||
if (!instanceMetadataArray.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const suvScalingFactors = calculateSUVScalingFactors(instanceMetadataArray);
|
||||
instanceMetadataArray.forEach((instanceMetadata, index) => {
|
||||
metadataProvider.addCustomMetadata(
|
||||
imageIds[index],
|
||||
'scalingModule',
|
||||
suvScalingFactors[index]
|
||||
);
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
if (!suvScalingFactors) {
|
||||
return;
|
||||
}
|
||||
|
||||
instanceMetadataArray.forEach((instanceMetadata, index) => {
|
||||
metadataProvider.addCustomMetadata(imageIds[index], 'scalingModule', suvScalingFactors[index]);
|
||||
});
|
||||
};
|
||||
@@ -37,7 +37,11 @@ const getDirectURL = (config, params) => {
|
||||
}
|
||||
if (!singlepart || (singlepart !== true && singlepart.indexOf(fetchPart) === -1)) {
|
||||
if (value.retrieveBulkData) {
|
||||
return value.retrieveBulkData().then(arr => {
|
||||
// Try the specified retrieve type.
|
||||
const options = {
|
||||
mediaType: defaultType,
|
||||
};
|
||||
return value.retrieveBulkData(options).then(arr => {
|
||||
value.DirectRetrieveURL = URL.createObjectURL(new Blob([arr], { type: defaultType }));
|
||||
return value.DirectRetrieveURL;
|
||||
});
|
||||
|
||||
Loaded 100 of 373 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user