feat(segmentation mode): Add create, and export SEG with Brushes (#3632)

This commit is contained in:
Alireza authored and GitHub committed 2023-09-22 10:23:44 -04:00
1 parent 896866e9d0
commit 48bbd6281a
186 files changed
+6801 -2883

No files matched your search

@@ -116,6 +116,26 @@ In the video below notice that there is `platform/viewer` which has been renamed
<iframe src="https://player.vimeo.com/video/551957266?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
</div>
### Build for non-root path
If you would like to access the viewer from a non-root path (e.g., `/my-awesome-viewer` instead of `/`),
You can achieve so by using the `PUBLIC_URL` environment variable AND the `routerBasename` configuration option.
1. use a config (e.g. config/myConfig.js) file that is using the `routerBasename` of your choice `/my-awesome-viewer` (note there is only one / - it is not /my-awesome-viewer/).
2. build the viewer with `PUBLIC_URL=/my-awesome-viewer/ APP_CONFIG=config/myConfig.js yarn build` (note there are two / - it is not /my-awesome-viewer).
:::tip
The PUBLIC_URL tells the application where to find the static assets and the routerBasename will tell the application how to handle the routes
:::
:::tip
Testing, you can use `npx http-server` to serve the files in the generated `dist` folder and access the viewer from `http://localhost:8080/my-awesome-viewer`. To achieve
so, you should first rename the `dist` folder to `my-awesome-viewer` and then change the working directory
to the `platform/app` folder and run `npx http-server ./`. Then on the browser, you can access the viewer from `http://localhost:8080/my-awesome-viewer`
:::
### Automating Builds and Deployments
If you found setting up your environment and running all of these steps to be a
+1 -1
View File
@@ -28,7 +28,7 @@ It is also required that the PUBLIC_URL environment variable is set to the same
`<iframe src="./ohif" />` (which means there is a `ohif` folder containing the build in your main app), then you need to:
1. use a config (e.g. config/myConfig.js) file that is using the `routerBasename` of `/ohif` (note the one / - it is not /ohif/).
2. build the viewer with `PUBLIC_URL=./ohif/ APP_CONFIG=config/myConfig.js yarn build` (note the one / - it is not /ohif/).
2. build the viewer with `PUBLIC_URL=/ohif/ APP_CONFIG=config/myConfig.js yarn build` (note the two / - it is not /ohif).
:::tip
Check to make sure the `app-config.js` in the build is reflecting the correct routerBasename.
@@ -21,7 +21,7 @@ specific `SOPClassHandlerUID`, so if you want to fork just a single Viewport
component for a specialized mode, this is possible.
```jsx
// displaySet, viewportIndex, dataSource
// displaySet, dataSource
const getViewportModule = () => {
const wrappedViewport = props => {
return (
@@ -45,8 +45,8 @@ There are seven events that get publish in `MeasurementService`:
### Segment Behavior
- setSegmentLockedForSegmentation, removeSegment, addSegment, setSegmentLockedForSegmentation, setSegmentLabel, setActiveSegmentForSegmentation,
setSegmentRGBAColorForSegmentation
- setSegmentLocked, removeSegment, addSegment, setSegmentLocked, setSegmentLabel, setActiveSegment,
setSegmentRGBAColor
### Segmentation Configuration
@@ -44,6 +44,7 @@ In the `value` of each customizations, you will define customization prototype(s
These customization prototype(s) can be considered like "Prototype" in Javascript.
These can be used to extend the customization definitions from configurations.
Default customizations will be often used to define all the customization prototypes,
Default customizations will be often used to define all the customization prototypes,
as they will be loaded automatically along with the defining extension or mode.
@@ -58,7 +59,6 @@ For example, the `@ohif/extension-default` extension defines,
value: [
{
id: 'ohif.overlayItem',
uiType: 'uiType',
content: function (props) {
if (this.condition && !this.condition(props)) return null;
@@ -92,8 +92,9 @@ For example, the `@ohif/extension-default` extension defines,
],
```
And this `ohif.overlayItem` object will be used as a prototype to define items
to be displayed on `CustomizableViewportOverlay`. See the next section.
And this `ohif.overlayItem` object will be used as a prototype (and template) to define items
to be displayed on `CustomizableViewportOverlay`. See how we use the `ohif.overlayItem` in
the example below.
## Configuring customizations
@@ -119,13 +120,16 @@ window.config = {
customizationService: {
cornerstoneOverlayTopRight: {
id: 'cornerstoneOverlayTopRight',
customizationType: 'ohif.cornerstoneOverlay',
items: [
{
id: 'PatientNameOverlay',
// Note the overlayItem as a parent type - this provides the
// rendering functionality to read the attribute and use the label.
// Note below that here we are using the customization prototype of
// `ohif.overlayItem` which was registered to the customization module in
// `ohif/extension-default` extension.
customizationType: 'ohif.overlayItem',
// the following props are passed to the `ohif.overlayItem` prototype
// which is used to render the overlay item based on the label, color,
// conditions, etc.
attribute: 'PatientName',
label: 'PN:',
title: 'Patient Name',
@@ -157,20 +161,19 @@ The `customizationType` field is simply the id of another customization object.
### Mode Customizations
Mode-specific customizations are no different from the global ones,
except that the mode customizations are cleared before the mode `onModeEnter`
is called, and they can have new values registered in the `onModeEnter`
except that the mode customizations are specific to one mode and
are not globally applied. Mode-specific customizations are also cleared
before the mode `onModeEnter` is called, and they can have new values registered in the `onModeEnter`
In the mode customization, the overlay is then further customized
with a bottom-right overlay, which extends the customizationService configuration.
Following on our example above to customize the overlay, we can now add a mode customization
with a bottom-right overlay.
```js
// Import the type from the extension itself
import OverlayUICustomization from '@ohif/cornerstone-extension';
import OverlayUICustomization from "@ohif/cornerstone-extension";
// In the mode itself, customizations can be registered:
onModeEnter() {
...
onModeEnter: {
// Note how the object can be strongly typed
const bottomRight: OverlayUICustomization = {
id: 'cornerstoneOverlayBottomRight',
@@ -182,6 +185,7 @@ onModeEnter() {
],
};
customizationService.addModeCustomizations(bottomRight);
}
```
The mode customizations are retrieved via the `getModeCustomization` function,
@@ -198,9 +202,17 @@ can then be used in a way defined by the extension provided that customization
point.
```ts
cornerstoneOverlay = uiConfigurationService.getModeCustomization("cornerstoneOverlay", {customizationType: "ohif.cornerstoneOverlay", ...});
const { component: overlayComponent, props} = uiConfigurationService.getComponent(cornerstoneOverlay);
return (<defaultComponent {...props} overlay={cornerstoneOverlay}....></defaultComponent>);
const cornerstoneOverlay = customizationService.getModeCustomization(
"cornerstoneOverlay",
{ customizationType: "ohif.cornerstoneOverlay" },
);
const { component: overlayComponent, props } =
customizationService.getComponent(cornerstoneOverlay);
return (
<defaultComponent {...props} overlay={cornerstoneOverlay}></defaultComponent>
);
```
This example shows fetching the default component to render this object. The
@@ -210,8 +222,11 @@ example (this example comes from the context menu customizations as that one
uses commands lists):
```ts
cornerstoneContextMenu = uiConfigurationService.get("cornerstoneContextMenu", defaultMenu);
commandsManager.run(cornerstoneContextMenu, extraProps);
cornerstoneContextMenu = customizationService.get(
"cornerstoneContextMenu",
defaultMenu,
);
commandsManager.run(cornerstoneContextMenu, extraProps);
```
### Global Customizations
@@ -339,7 +354,6 @@ window.config = {
customizationService: {
cornerstoneOverlayTopLeft: {
id: 'cornerstoneOverlayTopLeft',
customizationType: 'ohif.cornerstoneOverlay',
items: [
{
id: 'WindowLevel',
@@ -398,7 +412,6 @@ window.config = {
},
cornerstoneOverlayTopRight: {
id: 'cornerstoneOverlayTopRight',
customizationType: 'ohif.cornerstoneOverlay',
items: [
{
@@ -438,7 +451,6 @@ window.config = {
},
cornerstoneOverlayBottomLeft: {
id: 'cornerstoneOverlayBottomLeft',
customizationType: 'ohif.cornerstoneOverlay',
items: [
{
@@ -32,6 +32,7 @@ is expected to support, [check out it's interface in `@ohif/core`][interface]
| `reset()` | Resets the default states |
| `getNumViewportPanes()` | Gets the number of visible viewport panes |
| `getLayoutOptionsFromState(gridState)` | Utility method that produces a `ViewportLayoutOptions` based on the passed in state|
| `getActiveViewportId()` | Returns the viewport Id of the active viewport in the grid|
## Implementations