Skip to content

Commit

Permalink
feat: cornerstone3D stack and volume viewports (#2787)
Browse files Browse the repository at this point in the history
* feat: cs3d working stack viewport and tools (#19)

* Squashed everything

* fix weird react issue

* fix eslint / prettier stuff

* thumbnails work now with cpu rendering

* feat: use new loadImageToCanvas in cs3d

* make jump to measurement work

* fix active thumbnail

* fix measurement delete

* fix window level presets

* remove segmentation and sync groups for now

* fix the dicom pdf and dicom video

* fix cornerstone window assignment for cypress

* apply review comments

Co-authored-by: Erik <[email protected]>

* feat: cs3d tools and toolGroups (#20)

* add more tools to work with cs3d mode

* fix hotkeys

* add stack manager usage for stach viewports

* add image scrollbar

* wip viewport overlay

* fix toAnnotation schema for tools

* fix the unnecessary size change that triggered resize

* hanging protocol improvement to allow unmatched errors

* study description matching for hanging protocol

* fix the displaysetOptions to work

* fix handle the active tool when a new viewport is added

* fix separate toolGroups for mode

* apply review comments

* apply review comments

* yarn lock

* feat: overlay component (#21)

* fix default displayset options

* add viewport overlay

* apply review comments

* feat: loading and orientation indicators (#22)

* add loading indicator

* add orientation marker initial work

* apply review comments

* fix: orientation markers (#23)

* finished the orientation markers

* fix various broken cypress tests

* apply review comments

* update yarn lock

* feat: re-working measurement tracking mode with cornerstone3d (#2805)

* feat: cs3d working stack viewport and tools (#19)

* Squashed everything

* fix weird react issue

* fix eslint / prettier stuff

* thumbnails work now with cpu rendering

* feat: use new loadImageToCanvas in cs3d

* make jump to measurement work

* fix active thumbnail

* fix measurement delete

* fix window level presets

* remove segmentation and sync groups for now

* fix the dicom pdf and dicom video

* fix cornerstone window assignment for cypress

* apply review comments

Co-authored-by: Erik <[email protected]>

* feat: Add Measurement tracking mode with cs3D (#2789)

* feat: first render for cornerstone3d tracked viewport

* make tool active work

* wip for SR extension

* renamed dicom sr to cornerstone dicom sr

* remove cornerstone from dicom pdf and video

* move dicom sr logic to sr extension

* feat: Add hydration for the length tool

* fix SR display tool for length using cs3d

* fix default config

* fix: various bugs with sr viewport and tracking

* fix promptying to continue tracking for when SR is created

* feat: add keep trackign of unique identifiers

* fix hydration for same imageIds

* feat: Add SR toolGroup creation on modeEnter

* feat: remove the need for separate mapper for SR hydration

* add SR display for ellipse

* handle hydration of elliptical ROI tool

* remove cornerstone extension

* add arrow mapping

* feat: Add ArrowAnnotate SR display and hydration

* apply review comments

* apply review comments

* move viewport labels to the viewportData

* apply review comments

* fix: integration cypress tests with cornerstone3D and add CINE tool (#2795)

* fix: integration cypress tests with cornerstone3D

* revert to addOrUpdate as it makes more sense

* fix local drag and drop

* fix tests

* move dicomLoaderService to cornerstone extension

* fix various import bugs

* fix bug for local PT series

* fix various unit tests

* bump cs3d versions

* add angle and magnify tool

* bump dependencies to avoid broken peerDeps

* feat: add initial work for capture using cs3d

* feat: show annotations on the image capture

* feat: add svg layer export

* feat: Add CINE Tool

* feat: remove unnecessary viewport rendering for cine state changes

Co-authored-by: Erik Ziegler <[email protected]>

* docs: modify and improve documentation (#2800)

* cleanup docs versionings

* feat: Add all version explanations

* version docs for 3.0

* wip for changing docs

* wip for updated docs

* add utility module documentation

* fix demo with nohoisting of history

* add slides and video to resources

* apply review comments

* fix: drag and drop SR into SR viewport (#2803)

* update yarn lock

Co-authored-by: Erik <[email protected]>

* update pathnames to match v3-stable

* update the e2e pathname

* fix: various bugs with regard to tracking workflow (#2811)

* fix: various issues with measurement panel

* fix: update default tool style for annotations

* fix: annotatoin label getting removed

* feat: Add backward compatibility for SR hydration with legacy cornerstone

* fix: cursors and ellipse ROI max style

* fix: ArrowAnnotate SRDisplay

* apply review comments

* bump package versions

* fix: bugin rehydration of SR

* fix: e2e tests

* fix active viewport thickness and arrowTool ui

* add readme for measurement tracking

* use uploaded image for readme

* add back images

* try to fix e2e test

* fix: window level presets hotkeys

* Update README.md

* update yarn lock

* feat: volume api and TMTV mode (#2817)

* feat: volumeAPI and TMTV mode

* feat: use cs3d cache service to obtain viewportData

* wip for volume api

* wip: fusion viewport

* feat: add blend mode option

* wip for image scrollbar

* fix drag and drop thumbnail

* wip for image scrollbar for voluems

* fix: element mismatch bug for scroll

* feat: Add image scrollbar to volumes

* feat: add syncGroups to volume api

* feat: add tmtv mode initial setup

* feat: add initial image options for the stack viewports

* feat: Add custom load strategy for volume viewports via HP

* apply review comments

fix: Jump presets cs3d (#2812)

* feat: Add JumpPreset to OHIF for Cornerstone3D

* fix: accessing viewport service from servicesManager

feat: volume API and TMTV mode (#2814)

* fix: do not display overlays on mip viewports

* feat: add optional disableCommands for toggle buttons

* fix: toggleCrossharis

* feat: config the crosshairs

* feat: add PetSUV Panel for changing metadata

* feat: initial work for the rectangleROIThreshold panel

* wip: measurement service

* roi threshold working

* feat: Add displayText to segmentations

* feat: add remove segmentation

* feat: add csv export

* feat: add RT export for annotations in tmtv mode

* fix: fusion to use pt in tmtv mode and measuremet mappings

* fix: various bugs

* apply review comments

* apply review comments

* feat: add fusion color maps

* add readme to tmtv mode

* Update README.md

* fix: try to fix build

* fix unit tests

* Update README.md

* feat: add about to the panel

* fix: changing strategy in roi panel

* apply review comments

* update package versions

* wip for stackPrefetch

* fix: cornerstone3d hydration and renaming (#2818)

* update readme

* renamed cornerstone extension

* wip for renaming cornerstone3D variables

* wip for renaming cornerstone3D variables

* wip for fixing bugs for SR viewport

* fix: jumpToMeasurement and initial label after hydration

* fix: fileName capitalization

* feat: use the new prefetch stack in the cs3d (#2820)

* feat: use the new prefetch stack in the cs3d

* use viewport scroll api for stack viewport

* fix cine stop when scrollbar changes

* feat: use new prefetch events

* fix loading state to not show repeatedly

* fix: various bugs for tmtv mode thresholding and new icons (#2823)

* feat: make tmtv mode available in worklist

* feat: add new icons for tmtv mode

* feat: add fusion color icon

* fix: parallel scale calculation

* fix: bump Cornerstone to get large image support working

* fix: Fix issues with CPU viewport flipping, including config files

* fix: bump cornerstone to fix magnify tool

* fix: Bump Cornerstone version to fix resetCamera issue in StackViewport

* ci: Add _headers file to enable CORS headers for Netlify Drag/Drop deploys

* fix: WADO-URI was not working. PET Metadata was coming from the wrong place. Fixed some minor React errors

* feat(OHIF):Allow modes and extensions to be added after commpile time. (#2838)

Also works with the compile time add that the existing cli uses, so that both build types work.
Eric and I agreed this doesn't change existing functionality, but is almost entirely build issues/fixes.

* bump: dependency versions to fix hydration bugs (#2848)

* bump: dcmjs version to fix hydration bugs

* try to fix tests

* bump dependency versions

Co-authored-by: Alireza <[email protected]>
Co-authored-by: Bill Wallace <[email protected]>
  • Loading branch information
3 people authored Jul 27, 2022
1 parent 86dcaf6 commit bd1c38c
Show file tree
Hide file tree
Showing 668 changed files with 41,700 additions and 13,441 deletions.
9 changes: 8 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
{
"plugins": [
"@typescript-eslint",
"import",
"eslint-plugin-tsdoc",
"prettier"
],
"extends": [
"react-app",
"eslint:recommended",
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended"
],
"parser": "babel-eslint",
"parser": "@typescript-eslint/parser",
"env": {
"jest": true
},
Expand Down
13 changes: 13 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,18 @@
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}"
}
// {
// "name": "Debug Jest Tests",
// "type": "node",
// "request": "launch",
// "runtimeArgs": [
// "--inspect-brk",
// "${workspaceRoot}/node_modules/.bin/jest",
// "--runInBand"
// ],
// "console": "integratedTerminal",
// "internalConsoleOptions": "neverOpen",
// "port": 9229
// }
]
}
4 changes: 2 additions & 2 deletions .webpack/rules/transpileJavaScript.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ function transpileJavaScript(mode) {
const exclude =
mode === 'production'
? excludeNodeModulesExcept([
'vtk.js',
// 'dicomweb-client',
// https://github.com/react-dnd/react-dnd/blob/master/babel.config.js
'react-dnd',
Expand All @@ -21,7 +20,8 @@ function transpileJavaScript(mode) {
: excludeNodeModulesExcept([]);

return {
test: /\.(mjs|js|jsx)?$/,
// Include mjs, ts, tsx, js, and jsx files.
test: /\.(mjs|ts|js)x?$/,
// These are packages that are not transpiled to our lowest supported
// JS version (currently ES5). Most of these leverage ES6+ features,
// that we need to transpile to a different syntax.
Expand Down
17 changes: 14 additions & 3 deletions .webpack/webpack.base.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ const CopyPlugin = require('copy-webpack-plugin');

// ~~ PackageJSON
const PACKAGE = require('../platform/viewer/package.json');
// const vtkRules = require('vtk.js/Utilities/config/dependency.js').webpack.core
// .rules;
// ~~ RULES
const loadShadersRule = require('./rules/loadShaders.js');
const loadWebWorkersRule = require('./rules/loadWebWorkers.js');
Expand Down Expand Up @@ -66,19 +68,28 @@ module.exports = (env, argv, { SRC_DIR, DIST_DIR }) => {
children: false,
warnings: true,
},
devServer: {
open: true,
port: 3000,
historyApiFallback: true,
headers: {
'Cross-Origin-Embedder-Policy': 'require-corp',
'Cross-Origin-Opener-Policy': 'same-origin',
},
},
module: {
rules: [
transpileJavaScriptRule(mode),
loadWebWorkersRule,
loadShadersRule,
// loadShadersRule,
{
test: /\.m?js/,
resolve: {
fullySpecified: false,
},
},
cssToJavaScript,
],
], //.concat(vtkRules),
},
resolve: {
mainFields: ['module', 'browser', 'main'],
Expand Down Expand Up @@ -106,7 +117,7 @@ module.exports = (env, argv, { SRC_DIR, DIST_DIR }) => {
SRC_DIR,
],
// Attempt to resolve these extensions in order.
extensions: ['.js', '.jsx', '.json', '*'],
extensions: ['.js', '.jsx', '.json', '.ts', '.tsx', '*'],
// symlinked resources are resolved to their real path, not their symlinked location
symlinks: true,
fallback: { fs: false, path: false, zlib: false },
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,13 +190,14 @@ you'll see the following:
├── extensions #
│ ├── _example # Skeleton of example extension
│ ├── default #
│ ├── cornerstone # 2D images w/ Cornerstone.js
│ ├── dicom-sr #
│ ├── cornerstone # image rendering and tools w/ Cornerstone
│ ├── cornerstone- dicom-sr #
│ └── measurement-tracking #
├── modes #
│ ├── _example # Skeleton of example mode
│ └── longitudinal #
│ ├── basic-dev-mode # Basic development mode
│ └── longitudinal # Longitudinal mode (measurement tracking)
├── platform #
│ ├── core # Business Logic
Expand Down
18 changes: 14 additions & 4 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
const aliases = require('./aliases.config');
const path = require('path');

// https://babeljs.io/docs/en/options#babelrcroots
module.exports = {
babelrcRoots: ['./platform/*', './extensions/*', './modes/*'],
plugins: ['inline-react-svg', '@babel/plugin-proposal-class-properties'],
presets: [
'@babel/preset-env',
'@babel/preset-react',
'@babel/preset-typescript',
],
plugins: [
'inline-react-svg',
'@babel/plugin-proposal-class-properties',
'@babel/plugin-transform-typescript',
],
env: {
test: {
presets: [
Expand All @@ -17,19 +23,22 @@ module.exports = {
},
],
'@babel/preset-react',
'@babel/preset-typescript',
],
plugins: [
'@babel/plugin-proposal-object-rest-spread',
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-transform-regenerator',
'@babel/plugin-transform-runtime',
'@babel/plugin-transform-typescript',
],
},
production: {
presets: [
// WebPack handles ES6 --> Target Syntax
['@babel/preset-env', { modules: false }],
'@babel/preset-react',
'@babel/preset-typescript',
],
ignore: ['**/*.test.jsx', '**/*.test.js', '__snapshots__', '__tests__'],
},
Expand All @@ -38,6 +47,7 @@ module.exports = {
// WebPack handles ES6 --> Target Syntax
['@babel/preset-env', { modules: false }],
'@babel/preset-react',
'@babel/preset-typescript',
],
plugins: ['react-hot-loader/babel'],
ignore: ['**/*.test.jsx', '**/*.test.js', '__snapshots__', '__tests__'],
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ module.exports = (env, argv) => {
const commonConfig = webpackCommon(env, argv, { SRC_DIR, DIST_DIR });

return merge(commonConfig, {
devtool: 'source-map',
stats: {
colors: true,
hash: true,
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "@ohif/extension-dicom-sr",
"name": "@ohif/extension-cornerstone-dicom-sr",
"version": "3.0.0",
"description": "OHIF extension for an SR Cornerstone Viewport",
"author": "OHIF",
"license": "MIT",
"repository": "OHIF/Viewers",
"main": "dist/index.umd.js",
"module": "src/index.js",
"module": "src/index.tsx",
"engines": {
"node": ">=14",
"npm": ">=6",
Expand Down Expand Up @@ -34,21 +34,18 @@
"peerDependencies": {
"@ohif/core": "^3.0.0",
"@ohif/ui": "^2.0.0",
"cornerstone-core": "^2.6.0",
"cornerstone-math": "^0.1.9",
"cornerstone-tools": "6.0.2",
"cornerstone-wado-image-loader": "4.0.4",
"dcmjs": "0.16.1",
"dcmjs": "^0.24.5",
"dicom-parser": "^1.8.9",
"hammerjs": "^2.0.8",
"prop-types": "^15.6.2",
"react": "^17.0.2",
"react-cornerstone-viewport": "4.1.2",
"@ohif/extension-cornerstone": "^3.0.0",
"@ohif/extension-measurement-tracking": "^3.0.0"
},
"dependencies": {
"@babel/runtime": "7.16.3",
"classnames": "^2.2.6"
"classnames": "^2.2.6",
"@cornerstonejs/core": "^0.13.11",
"@cornerstonejs/tools": "^0.20.15"
}
}
143 changes: 143 additions & 0 deletions extensions/cornerstone-dicom-sr/src/commandsModule.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import { metaData, utilities } from '@cornerstonejs/core';

import OHIF from '@ohif/core';
import dcmjs from 'dcmjs';

import getFilteredCornerstoneToolState from './utils/getFilteredCornerstoneToolState';

const { MeasurementReport } = dcmjs.adapters.Cornerstone3D;
const { log } = OHIF;

/**
*
* @param measurementData An array of measurements from the measurements service
* that you wish to serialize.
* @param additionalFindingTypes toolTypes that should be stored with labels as Findings
* @param options Naturalized DICOM JSON headers to merge into the displaySet.
*
*/
const _generateReport = (
measurementData,
additionalFindingTypes,
options = {}
) => {
const filteredToolState = getFilteredCornerstoneToolState(
measurementData,
additionalFindingTypes
);

const report = MeasurementReport.generateReport(
filteredToolState,
metaData,
utilities.worldToImageCoords
);

const { dataset } = report;

// Add in top level series options
Object.assign(dataset, options);

return dataset;
};

const commandsModule = ({}) => {
const actions = {
/**
*
* @param measurementData An array of measurements from the measurements service
* @param additionalFindingTypes toolTypes that should be stored with labels as Findings
* @param options Naturalized DICOM JSON headers to merge into the displaySet.
* as opposed to Finding Sites.
* that you wish to serialize.
*/
downloadReport: ({
measurementData,
additionalFindingTypes,
options = {},
}) => {
const srDataset = actions.generateReport(
measurementData,
additionalFindingTypes,
options
);
const reportBlob = dcmjs.data.datasetToBlob(srDataset);

//Create a URL for the binary.
var objectUrl = URL.createObjectURL(reportBlob);
window.location.assign(objectUrl);
},

/**
*
* @param measurementData An array of measurements from the measurements service
* that you wish to serialize.
* @param dataSource The dataSource that you wish to use to persist the data.
* @param additionalFindingTypes toolTypes that should be stored with labels as Findings
* @param options Naturalized DICOM JSON headers to merge into the displaySet.
* @return The naturalized report
*/
storeMeasurements: async ({
measurementData,
dataSource,
additionalFindingTypes,
options = {},
}) => {
// TODO -> Eventually use the measurements directly and not the dcmjs adapter,
// But it is good enough for now whilst we only have cornerstone as a datasource.
log.info('[DICOMSR] storeMeasurements');

if (!dataSource || !dataSource.store || !dataSource.store.dicom) {
log.error(
'[DICOMSR] datasource has no dataSource.store.dicom endpoint!'
);
return Promise.reject({});
}

try {
const naturalizedReport = _generateReport(
measurementData,
additionalFindingTypes,
options
);
const { StudyInstanceUID } = naturalizedReport;

await dataSource.store.dicom(naturalizedReport);

if (StudyInstanceUID) {
dataSource.deleteStudyMetadataPromise(StudyInstanceUID);
}

return naturalizedReport;
} catch (error) {
console.warn(error);
log.error(
`[DICOMSR] Error while saving the measurements: ${error.message}`
);
throw new Error(
error.message || 'Error while saving the measurements.'
);
}
},
};

const definitions = {
downloadReport: {
commandFn: actions.downloadReport,
storeContexts: [],
options: {},
},
storeMeasurements: {
commandFn: actions.storeMeasurements,
storeContexts: [],
options: {},
},
};

return {
actions,
definitions,
defaultContext: 'CORNERSTONE_STRUCTURED_REPORT',
};
};

export default commandsModule;
Loading

0 comments on commit bd1c38c

Please sign in to comment.