docs: Add v3 docs using docusaurus (Merge pull request #2468 from OHIF/feat/v2-main-docusaurus-netlify-monorepo)
@ -15,11 +15,12 @@ node -v
|
||||
yarn run build:ci
|
||||
mkdir -p ./.netlify/www/pwa
|
||||
mv platform/viewer/dist/* .netlify/www/pwa -v
|
||||
echo 'Web application built and copied'
|
||||
|
||||
# Build && Move script output
|
||||
# yarn run build:package
|
||||
|
||||
# Build && Move Docz Output
|
||||
# Build && Move Docz Output (for the UI Component Library)
|
||||
# Using local yarn install to prevent Gatsby from needing to access
|
||||
# node_modules above the platform/ui folder
|
||||
cd platform/ui
|
||||
@ -28,6 +29,16 @@ yarn run build
|
||||
cd ../..
|
||||
mkdir -p ./.netlify/www/ui
|
||||
mv platform/ui/.docz/dist/* .netlify/www/ui -v
|
||||
echo 'UI Component docs (docz) built and copied'
|
||||
|
||||
# Build && Move Docusaurus Output (for the docs themselves)
|
||||
cd platform/docs
|
||||
yarn install
|
||||
yarn run build
|
||||
cd ../..
|
||||
mkdir -p ./.netlify/www/docs
|
||||
mv platform/docs/build/* .netlify/www/docs -v
|
||||
echo 'Docs built (docusaurus) and copied'
|
||||
|
||||
# Cache all of the node_module dependencies in
|
||||
# extensions, modules, and platform packages
|
||||
|
||||
@ -6,3 +6,5 @@
|
||||
/pwa/* /pwa/index.html 200
|
||||
# UI Demo
|
||||
/ui/* /ui/index.html 200
|
||||
# UI Demo
|
||||
/docs/* /docs/index.html 200
|
||||
|
||||
@ -9,7 +9,10 @@
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/pwa">PWA: Viewer</a>
|
||||
<a href="/pwa">OHIF Viewer</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/docs">Documentation</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/ui">UI: Component Library</a>
|
||||
|
||||
@ -9,12 +9,13 @@ const loadShadersRule = require('./rules/loadShaders.js');
|
||||
const loadWebWorkersRule = require('./rules/loadWebWorkers.js');
|
||||
const transpileJavaScriptRule = require('./rules/transpileJavaScript.js');
|
||||
// ~~ PLUGINS
|
||||
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
|
||||
.BundleAnalyzerPlugin;
|
||||
const TerserJSPlugin = require('terser-webpack-plugin');
|
||||
// ~~ ENV VARS
|
||||
const NODE_ENV = process.env.NODE_ENV;
|
||||
const QUICK_BUILD = process.env.QUICK_BUILD;
|
||||
const BUILD_NUM = process.env.CIRCLE_BUILD_NUM || '0';
|
||||
const { UnusedFilesWebpackPlugin } = require("unused-files-webpack-plugin");
|
||||
|
||||
//
|
||||
dotenv.config();
|
||||
@ -30,7 +31,7 @@ module.exports = (env, argv, { SRC_DIR, DIST_DIR }) => {
|
||||
|
||||
const config = {
|
||||
mode: isProdBuild ? 'production' : 'development',
|
||||
devtool: isProdBuild ? 'source-map' : 'cheap-module-eval-source-map',
|
||||
devtool: isProdBuild ? 'source-map' : 'eval',
|
||||
entry: {
|
||||
app: `${SRC_DIR}/index.js`,
|
||||
},
|
||||
@ -55,9 +56,16 @@ module.exports = (env, argv, { SRC_DIR, DIST_DIR }) => {
|
||||
transpileJavaScriptRule(mode),
|
||||
loadWebWorkersRule,
|
||||
loadShadersRule,
|
||||
{
|
||||
test: /\.m?js/,
|
||||
resolve: {
|
||||
fullySpecified: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
mainFields: ['browser', 'module', 'main'],
|
||||
alias: {
|
||||
// Viewer project
|
||||
'@': path.resolve(__dirname, '../platform/viewer/src'),
|
||||
@ -81,6 +89,7 @@ module.exports = (env, argv, { SRC_DIR, DIST_DIR }) => {
|
||||
extensions: ['.js', '.jsx', '.json', '*'],
|
||||
// symlinked resources are resolved to their real path, not their symlinked location
|
||||
symlinks: true,
|
||||
fallback: { fs: false, path: false },
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
@ -89,7 +98,9 @@ module.exports = (env, argv, { SRC_DIR, DIST_DIR }) => {
|
||||
'process.env.DEBUG': JSON.stringify(process.env.DEBUG),
|
||||
'process.env.APP_CONFIG': JSON.stringify(process.env.APP_CONFIG || ''),
|
||||
'process.env.PUBLIC_URL': JSON.stringify(process.env.PUBLIC_URL || '/'),
|
||||
'process.env.VERSION_NUMBER': JSON.stringify(process.env.VERSION_NUMBER || PACKAGE.version || ''),
|
||||
'process.env.VERSION_NUMBER': JSON.stringify(
|
||||
process.env.VERSION_NUMBER || PACKAGE.version || ''
|
||||
),
|
||||
'process.env.BUILD_NUM': JSON.stringify(BUILD_NUM),
|
||||
/* i18n */
|
||||
'process.env.USE_LOCIZE': JSON.stringify(process.env.USE_LOCIZE || ''),
|
||||
@ -99,33 +110,23 @@ module.exports = (env, argv, { SRC_DIR, DIST_DIR }) => {
|
||||
'process.env.LOCIZE_API_KEY': JSON.stringify(
|
||||
process.env.LOCIZE_API_KEY || ''
|
||||
),
|
||||
'process.env.REACT_APP_I18N_DEBUG': JSON.stringify(
|
||||
process.env.REACT_APP_I18N_DEBUG || ''
|
||||
),
|
||||
}),
|
||||
new UnusedFilesWebpackPlugin({
|
||||
failOnUnused: false,
|
||||
globOptions: {
|
||||
ignore: [
|
||||
"node_modules/**/*",
|
||||
"index.umd.js",
|
||||
"sanity.test.js",
|
||||
"__mocks__/fileMock.js",
|
||||
"__tests__/globalSetup.js"
|
||||
]
|
||||
}
|
||||
}),
|
||||
// Uncomment to generate bundle analyzer
|
||||
// new BundleAnalyzerPlugin(),
|
||||
],
|
||||
// Fix: https://github.com/webpack-contrib/css-loader/issues/447#issuecomment-285598881
|
||||
// For issue in cornerstone-wado-image-loader
|
||||
node: {
|
||||
/*node: {
|
||||
fs: 'empty',
|
||||
},
|
||||
},*/
|
||||
};
|
||||
|
||||
if (isProdBuild) {
|
||||
config.optimization.minimizer = [
|
||||
new TerserJSPlugin({
|
||||
// Supports:
|
||||
// source-map and inline-source-map
|
||||
sourceMap: isProdBuild && !isQuickBuild,
|
||||
parallel: true,
|
||||
terserOptions: {},
|
||||
}),
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<!-- markdownlint-disable -->
|
||||
<div align="center">
|
||||
<h1>OHIF Medical Imaging Viewer</h1>
|
||||
<p><strong>The OHIF Viewer</strong> is a zero-footprint medical image viewer provided by the <a href="http://ohif.org/">Open Health Imaging Foundation (OHIF)</a>. It is a configurable and extensible progressive web application with out-of-the-box support for image archives which support <a href="https://www.dicomstandard.org/dicomweb/">DICOMweb</a>.</p>
|
||||
<p><strong>The OHIF Viewer</strong> is a zero-footprint medical image viewer provided by the <a href="https://ohif.org/">Open Health Imaging Foundation (OHIF)</a>. It is a configurable and extensible progressive web application with out-of-the-box support for image archives which support <a href="https://www.dicomstandard.org/dicomweb/">DICOMweb</a>.</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
1
docs/.gitignore
vendored
@ -1 +0,0 @@
|
||||
./_book/*
|
||||
@ -1 +0,0 @@
|
||||
docs.ohif.org
|
||||
@ -1,47 +0,0 @@
|
||||
# How To: Documentation Step-by-Step
|
||||
|
||||
We use [GitBook](https://www.gitbook.com/) to create our documentation. It primarily uses markdown, html, css, js, misc. plugins, and configuration to generate high quality, easy to read, and easy to maintain documentation.
|
||||
|
||||
## Getting Started
|
||||
|
||||
_Requirements:_
|
||||
|
||||
Make sure you have the [`gitbook-cli`](https://www.npmjs.com/package/gitbook-cli) installed globally:
|
||||
|
||||
(Note that gitbook 3.2.3 works with node 10.19.0 and node 10.24.0, but not with node 14.x.)
|
||||
> `npm install -g gitbook-cli`
|
||||
|
||||
### Editing and Previewing Changes
|
||||
|
||||
Currently, you can only edit and preview a single "book" at a time. We maintain one "book" per API major version. You can find each version's book at:
|
||||
|
||||
_Past Versions:_
|
||||
|
||||
- Template:
|
||||
- `<project-root>/docs/v<versionNumber>`
|
||||
- Examples:
|
||||
- `/docs/v1`
|
||||
- `/docs/v2`
|
||||
|
||||
_Latest Version:_
|
||||
|
||||
The latest version will always be located in `/docs/latest`
|
||||
|
||||
_Live Preview:_
|
||||
|
||||
In your terminal / command prompt:
|
||||
|
||||
```bash
|
||||
cd /docs/latest
|
||||
gitbook install
|
||||
gitbook serve
|
||||
```
|
||||
|
||||
Which should generate output like:
|
||||
|
||||
> starting server...
|
||||
> serving book on http://localhost:4000
|
||||
|
||||
Navigating to the the provided URL will show a preview of what the generated book should look like. Any edits you make to the book's markdown files should automatically update in your browser.
|
||||
|
||||
### Publishing
|
||||
@ -1,3 +0,0 @@
|
||||
# Netlify redirects
|
||||
# SPA rules for our docs
|
||||
/* /index.html 200
|
||||
1
docs/latest/.gitignore
vendored
@ -1 +0,0 @@
|
||||
_book/
|
||||
@ -1,95 +0,0 @@
|
||||
<div class='row'>
|
||||
<div class='column' style='text-align: right; padding: 0 20px'>
|
||||
<strong>Looking for a Live Demo?</strong>
|
||||
<a href="http://viewer.ohif.org/">Preview The OHIF Viewer</a>
|
||||
</div>
|
||||
<div class='column' style='text-align: left; padding: 0 20px'>
|
||||
<a href="https://www.netlify.com">
|
||||
<img src="https://www.netlify.com/img/global/badges/netlify-color-bg.svg"/>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
> ATTENTION! You are looking at the docs for the `OHIF-v3` Viewer (third time is always a charm). If you're looking for the our `OHIF-v2` (React stable version) or OHIF-v1 (deprecated `Meteor` version) select it's version from the dropdown box in the top left corner
|
||||
> of this page.
|
||||
|
||||
|
||||
# Introduction
|
||||
|
||||
The [Open Health Imaging Foundation][ohif-org] (OHIF) Viewer is an open source,
|
||||
web-based, medical imaging viewer. It can be configured to connect to Image
|
||||
Archives that support [DicomWeb][dicom-web], and offers support for mapping to
|
||||
proprietary API formats. OHIF maintained extensions add support for viewing,
|
||||
annotating, and reporting on DICOM images in 2D (slices) and 3D (volumes).
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
<center><i>The <strong>OHIF Viewer v3</strong>: A general purpose DICOM Viewer (<a href="http://viewer.ohif.org/">Live Demo</a>)</center>
|
||||
|
||||
|
||||
|
||||
|
||||
## What's new in `OHIF-v3`
|
||||
`OHIF-v3` is our second try for a React-based viewer, and is the third version of
|
||||
our medical image web viewers from the start. The summary of changes include:
|
||||
|
||||
- Addition of workflow modes
|
||||
|
||||
- Often, medical imaging use cases involves lots of specific workflows that re-use
|
||||
functionalities. We have added the capability of workflow modes, that enable people
|
||||
to customize user interface and configure application for specific workflow.
|
||||
- The idea is to re-use the functionalities that extensions provide and create a workflow.
|
||||
Brain segmentation workflow is different from prostate segmentation in UI for sure; however, they share the segmentation tools that can be re-used.
|
||||
- Our vision is that technical people focus of developing extensions which provides
|
||||
core functionalities, and experts to build modes by picking the appropriate functionalities
|
||||
from each extension.
|
||||
|
||||
|
||||
- Redux store has been removed from the viewer, and a cleaner, more powerful
|
||||
- tailwind CSS
|
||||
- End-to-end test suite
|
||||
|
||||
|
||||
Below, you can find the gap analysis between the `OHIF-v2` and `OHIF-v3`:
|
||||
|
||||
|
||||
{% include "./_gap_analysis.md" %}
|
||||
|
||||
|
||||
|
||||
## Where to next?
|
||||
|
||||
|
||||
The Open Health Imaging Foundation intends to provide a simple general purpose
|
||||
DICOM Viewer which can be easily extended for specific uses. If you find
|
||||
yourself unable to extend the viewer for your purposes, please reach out via our
|
||||
[GitHub issues][gh-issues]. We are actively seeking feedback on ways to improve
|
||||
our integration and extension points.
|
||||
|
||||
|
||||
Check out these helpful links:
|
||||
|
||||
- Ready to dive into some code? Check out our
|
||||
[Getting Started Guide](./development/getting-started.md).
|
||||
- We're an active, vibrant community.
|
||||
[Learn how you can be more involved.](./development/contributing.md)
|
||||
- Feeling lost? Read our [help page](./help.md).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
Links
|
||||
-->
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
[ohif-org]: http://www.ohif.org
|
||||
[ohif-demo]: http://viewer.ohif.org/
|
||||
[dicom-web]: https://en.wikipedia.org/wiki/DICOMweb
|
||||
[gh-issues]: https://github.com/OHIF/Viewers/issues
|
||||
<!-- prettier-ignore-end -->
|
||||
@ -1,83 +0,0 @@
|
||||
# OHIF Viewers
|
||||
|
||||
- [Our Process](our-process.md)
|
||||
- User Manuals
|
||||
- [Overview](userManuals/index.md)
|
||||
- [Study List](userManuals/studyList/index.md)
|
||||
- [Viewer](userManuals/viewer/index.md)
|
||||
- [Study Panel](userManuals/viewer/studyPanel/study-panel.md)
|
||||
- [Measurement Panel](userManuals/viewer/measurementPanel/measurement-panel.md)
|
||||
- [Viewport](userManuals/viewer/viewport/viewport.md)
|
||||
- [Toolbar](userManuals/viewer/toolbar/toolbar.md)
|
||||
- [Hot keys](userManuals/viewer/hotkeys/hotkeys.md)
|
||||
- [Language](userManuals/viewer/language/language.md)
|
||||
- Development
|
||||
- [Getting Started](development/getting-started.md)
|
||||
- [Contributing](development/contributing.md)
|
||||
- [Continuous Integration](development/continous-integration.md)
|
||||
- [Testing](development/testing.md)
|
||||
- [Configuring Data Source](configuring/index.md)
|
||||
- [Local DICOM Server](configuring/data-source.md)
|
||||
|
||||
---
|
||||
|
||||
- [Architecture](architecture/index.md)
|
||||
- [Viewer](viewer/index.md)
|
||||
- [Configuration](viewer/configuration.md)
|
||||
- [Theming](viewer/themeing.md)
|
||||
- [Internationalization](viewer/internationalization.md)
|
||||
- [Extensions](extensions/index.md#Overview)
|
||||
- [Registering](extensions/index.md#registering-an-extension)
|
||||
- [OHIF Maintained](extensions/index.md#ohif-maintained-extensions)
|
||||
- [Lifecycle Hooks](extensions/index.md#lifecycle-hooks)
|
||||
- [preRegistration](extensions/lifecycle/pre-registration.md)
|
||||
- [onModeEnter](extensions/lifecycle/on-mode-enter.md)
|
||||
- [onModeExit](extensions/lifecycle/on-mode-exit.md)
|
||||
- [Modules](extensions/index.md#modules)
|
||||
- [Toolbar](extensions/modules/toolbar.md)
|
||||
- [Commands](extensions/modules/commands.md)
|
||||
- [DataSource](extensions/modules/data-source.md)
|
||||
- [SOPClassHandler](extensions/modules/sop-class-handler.md)
|
||||
- [Viewport](extensions/modules/viewport.md)
|
||||
- [Panel](extensions/modules/panel.md)
|
||||
- [LayoutTemplate](extensions/modules/layout-template.md)
|
||||
- [HangingProtocol](extensions/modules/hpModule.md)
|
||||
- [Context](extensions/index.md#contexts)
|
||||
- [ExtensionManager](managers/extension.md)
|
||||
- [Modes](modes/index.md)
|
||||
- [LifeCycle](modes/lifeCycle.md#overview)
|
||||
- [Validity](modes/validity.md#overview)
|
||||
- [Routes](modes/routes.md#overview)
|
||||
- [Managers](managers/index.md)
|
||||
- [Extension Manager](managers/extension.md)
|
||||
- [Service Manager](managers/service.md)
|
||||
- [Commands Manager](managers/commands.md)
|
||||
- [Hotkeys Manager](managers/hotkeys.md)
|
||||
- [Services](services/index.md)
|
||||
- [Data Services](services/data/index.md)
|
||||
- [Dicom Metadata Store](services/data/DicomMetadataStore.md)
|
||||
- [DisplaySet Service](services/data/DisplaySetService.md)
|
||||
- [Hanging Protocol Service](services/data/HangingProtocolService.md)
|
||||
- [Toolbar Service](services/data/ToolbarService.md)
|
||||
- [Measurement Service](services/data/MeasurementService.md)
|
||||
- [UI Services](services/ui/index.md)
|
||||
- [UI Notification Service](services/ui/ui-notification-service.md)
|
||||
- [UI Modal Service](services/ui/ui-modal-service.md)
|
||||
- [UI Dialog Service](services/ui/ui-dialog-service.md)
|
||||
- [UI Viewport Dialog Service](services/ui/ui-viewport-dialog-service.md)
|
||||
- [Viewport Grid Service](services/ui/ViewportGridService.md)
|
||||
- [Pub/Sub Pattern](services/pubsub.md)
|
||||
|
||||
- [Deployment](deployment/index.md)
|
||||
- [Build for Production](deployment/recipes/build-for-production.md)
|
||||
- [Static](deployment/recipes/static-assets.md)
|
||||
- [Nginx + Image Archive](deployment/recipes/nginx--image-archive.md)
|
||||
- [User Account Control](deployment/recipes/user-account-control.md)
|
||||
- [Google Cloud Healthcare](connecting-to-image-archives/google-cloud-healthcare.md)
|
||||
|
||||
|
||||
- [FAQ](faq/index.md)
|
||||
- [Scope of Project](faq/scope-of-project.md)
|
||||
- [Browser Support](faq/browser-support.md)
|
||||
- [PWA vs Packaged](faq/pwa-vs-packaged.md)
|
||||
- [Help](help.md) -->
|
||||
@ -1,110 +0,0 @@
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left" width="50%">OHIF-v2 functionalities</th>
|
||||
<th align="center">OHIF-v3</th>
|
||||
<th align="center">Comment</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left">Rendering of 2D images via Cornerstone</td>
|
||||
<td align="center">✅</td>
|
||||
<td align="center"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">Study List</td>
|
||||
<td align="center">✅</td>
|
||||
<td align="center"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">Series Browser</td>
|
||||
<td align="center">✅</td>
|
||||
<td align="center"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">DICOM JSON</td>
|
||||
<td align="center">✅</td>
|
||||
<td align="center"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">2D Tools via CornerstoneTools</td>
|
||||
<td align="center">✅</td>
|
||||
<td align="center"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">OpenID Connect standard authentication flow for connecting to identity providers</td>
|
||||
<td align="center">🔜</td>
|
||||
<td align="center">In Progress</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">Internationalization</td>
|
||||
<td align="center">🔜</td>
|
||||
<td align="center">Not Started</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">Drag/drop DICOM data into the viewer (see https://viewer.ohif.org/local)</td>
|
||||
<td align="center">🔜</td>
|
||||
<td align="center">Not Started</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">IHE Invoke Image Display - Standard-compliant launching of the viewer (e.g. from PACS or RIS)</td>
|
||||
<td align="center">🔜</td>
|
||||
<td align="center">Not Started</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">DICOM PDF support</td>
|
||||
<td align="center">🔜</td>
|
||||
<td align="center">Not Started</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">DICOM Whole-slide imaging viewport</td>
|
||||
<td align="center">🔜</td>
|
||||
<td align="center">Not Started</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">Displaying non-renderable DICOM as HTML</td>
|
||||
<td align="center">🔜</td>
|
||||
<td align="center">Not Started</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">Segmentation support</td>
|
||||
<td align="center">🔜</td>
|
||||
<td align="center">Not Started</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">RT STRUCT support</td>
|
||||
<td align="center">🔜</td>
|
||||
<td align="center">Not Started</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">White-labelling: Easily replace the OHIF Logo with your logo</td>
|
||||
<td align="center">🔜</td>
|
||||
<td align="center">Not Started</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">DICOM upload to PACS</td>
|
||||
<td align="center">🔜</td>
|
||||
<td align="center">Not Started</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">Google Cloud adapter</td>
|
||||
<td align="center">🔜</td>
|
||||
<td align="center">Not Started</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">VTK Extension + MIP / MPR layout</td>
|
||||
<td align="center">❌</td>
|
||||
<td align="center">Other plans</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">UMD Build (Embedded Viewer). </td>
|
||||
<td align="center">❌</td>
|
||||
<td align="center">The problem is that this breaks a bunch of extensions that rely on third party scripts (e.g. VTK) which have their own web worker loaders.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
❌
|
||||
✅
|
||||
🔜
|
||||
|
Before Width: | Height: | Size: 142 KiB |
|
Before Width: | Height: | Size: 119 KiB |
|
Before Width: | Height: | Size: 268 KiB |
|
Before Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 370 KiB |
|
Before Width: | Height: | Size: 358 KiB |
|
Before Width: | Height: | Size: 321 KiB |
|
Before Width: | Height: | Size: 215 KiB |
@ -1,54 +0,0 @@
|
||||
{
|
||||
"title": "OHIF",
|
||||
"description": "Documentation for the OHIF framework",
|
||||
"gitbook": ">3.0.0",
|
||||
"plugins": [
|
||||
"edit-link",
|
||||
"theme-cornerstone",
|
||||
"-fontsettings",
|
||||
"github",
|
||||
"ga",
|
||||
"sitemap",
|
||||
"anchors",
|
||||
"versions"
|
||||
],
|
||||
"pluginsConfig": {
|
||||
"edit-link": {
|
||||
"base": "https://github.com/OHIF/Viewers/edit/master/docs",
|
||||
"label": "Edit This Page"
|
||||
},
|
||||
"github": {
|
||||
"url": "https://github.com/OHIF/Viewers"
|
||||
},
|
||||
"ga": {
|
||||
"token": "UA-110573590-2"
|
||||
},
|
||||
"sitemap": {
|
||||
"hostname": "https://docs.ohif.org"
|
||||
},
|
||||
"versions": {
|
||||
"gitbookConfigURL": "https://raw.githubusercontent.com/OHIF/Viewers/master/docs/book.json",
|
||||
"options": [
|
||||
{
|
||||
"value": "https://docs.ohif.org/history/v1/",
|
||||
"text": "Version 1.0.0 (Meteor)"
|
||||
},
|
||||
{
|
||||
"value": "https://docs.ohif.org/history/v2/",
|
||||
"text": "Version 2.0.0"
|
||||
},
|
||||
{
|
||||
"value": "https://docs.ohif.org/",
|
||||
"text": "Version 3.0.0",
|
||||
"selected": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"sharing": {
|
||||
"facebook": false,
|
||||
"twitter": false
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
<div style="text-align: center;">
|
||||
<img src="/assets/img/embedded-viewer-diagram.png" alt="Embedded Viewer Diagram" style="margin: 0 auto;" />
|
||||
<div><i>embedded viewer diagram</i></div>
|
||||
</div>
|
||||
@ -1,4 +0,0 @@
|
||||
<div style="text-align: center;">
|
||||
<img src="/assets/img/nginx-image-archive.png" alt="request flow example" style="margin: 0 auto;" />
|
||||
<div><i>simplified request flow diagram</i></div>
|
||||
</div>
|
||||
@ -1,4 +0,0 @@
|
||||
<div style="text-align: center;">
|
||||
<img src="/assets/img/user-access-control-request-flow.png" alt="request flow example" style="margin: 0 auto;" />
|
||||
<div><i>simplified request flow diagram</i></div>
|
||||
</div>
|
||||
@ -1,67 +0,0 @@
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Extension</th>
|
||||
<th>Description</th>
|
||||
<th>Modules</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- CORNERSTONE.js -->
|
||||
<tr>
|
||||
<td>
|
||||
<a href="">
|
||||
Default
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
Default extension provides default viewer layout, a study/series
|
||||
browser, and a datasource that maps to a DICOMWeb compliant backend
|
||||
</td>
|
||||
<td>commandsModule, ContextModule, DataSourceModule, HangingProtocolModule, LayoutTemplateModule, PanelModule, SOPClassHandlerModule, ToolbarModule</td>
|
||||
</tr>
|
||||
<!-- CORNERSTONE.js -->
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://www.npmjs.com/package/@ohif/extension-cornerstone">
|
||||
Cornerstone
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
Provides rendering functionalities for 2D images.
|
||||
</td>
|
||||
<td>ViewportModule, CommandsModule</td>
|
||||
</tr>
|
||||
<!-- dicom-pdf -->
|
||||
<!-- <tr>
|
||||
<td>
|
||||
<a href="https://www.npmjs.com/package/@ohif/extension-dicom-pdf">DICOM PDF</a>
|
||||
</td>
|
||||
<td>
|
||||
Renders PDFs for a <a href="https://github.com/OHIF/Viewers/blob/master/extensions/dicom-pdf/src/OHIFDicomPDFSopClassHandler.js#L4-L6">specific SopClassUID</a>.
|
||||
</td>
|
||||
<td>Viewport, SopClassHandler</td>
|
||||
</tr> -->
|
||||
<!-- dicom-sr -->
|
||||
<tr>
|
||||
<td>
|
||||
<a href="">DICOM SR</a>
|
||||
</td>
|
||||
<td>
|
||||
Maintained extensions for cornerstone and visualization of DICOM Structured Reports
|
||||
</td>
|
||||
<td>ViewportModule, CommandsModule, SOPClassHandlerModule</td>
|
||||
</tr>
|
||||
<!-- Measurement-tracking -->
|
||||
<tr>
|
||||
<td>
|
||||
<a href="">Measurement tracking</a>
|
||||
</td>
|
||||
<td>
|
||||
Tracking measurements in the measurement panel
|
||||
</td>
|
||||
<td> ContextModule,PanelModule,ViewportModule,CommandsModule</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
@ -1,94 +0,0 @@
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left" width="30%">
|
||||
Types
|
||||
</th>
|
||||
<th align="left">Description</th>
|
||||
<th align="left">Examples</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left">
|
||||
<a href="./modules/layout-template.md">
|
||||
LayoutTemplate (NEW)
|
||||
</a>
|
||||
</td>
|
||||
<td align="left">Control Layout of a route</td>
|
||||
<td align="left"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">
|
||||
<a href="./modules/data-source.md">
|
||||
DataSource (NEW)
|
||||
</a>
|
||||
</td>
|
||||
<td align="left">Control the mapping from DICOM metadata to OHIF-metadata</td>
|
||||
<td align="left"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">
|
||||
<a href="./modules/sop-class-handler.md">
|
||||
SOPClassHandler
|
||||
</a>
|
||||
</td>
|
||||
<td align="left">Determines how retrieved study data is split into "DisplaySets"</td>
|
||||
<td align="left"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">
|
||||
<a href="./modules/panel.md">
|
||||
Panel
|
||||
</a>
|
||||
</td>
|
||||
<td align="left">Adds left or right hand side panels</td>
|
||||
<td align="left"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">
|
||||
<a href="./modules/viewport.md">
|
||||
Viewport
|
||||
</a>
|
||||
</td>
|
||||
<td align="left">Adds a component responsible for rendering a "DisplaySet"</td>
|
||||
<td align="left"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">
|
||||
<a href="./modules/commands.md">
|
||||
Commands
|
||||
</a>
|
||||
</td>
|
||||
<td align="left">Adds named commands, scoped to a context, to the CommandsManager</td>
|
||||
<td align="left"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">
|
||||
<a href="./modules/toolbar.md">
|
||||
Toolbar
|
||||
</a>
|
||||
</td>
|
||||
<td align="left">Adds buttons or custom components to the toolbar</td>
|
||||
<td align="left"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">
|
||||
<a href="./modules/context.md">
|
||||
Context
|
||||
</a>
|
||||
</td>
|
||||
<td align="left">Shared state for a workflow or set of extension module definitions</td>
|
||||
<td align="left"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">
|
||||
<a href="./modules/hpModule.md">
|
||||
HangingProtocol
|
||||
</a>
|
||||
</td>
|
||||
<td align="left">Adds hanging protocol rules</td>
|
||||
<td align="left"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@ -1,263 +0,0 @@
|
||||
# Extensions
|
||||
|
||||
- [Extensions](#extensions)
|
||||
- [Overview](#overview)
|
||||
- [Extension Skeleton](#extension-skeleton)
|
||||
- [OHIF-Maintained Extensions](#ohif-maintained-extensions)
|
||||
- [Registering an Extension](#registering-an-extension)
|
||||
- [Registering at Runtime](#registering-at-runtime)
|
||||
- [Registering at Build Time](#registering-at-build-time)
|
||||
- [Lifecycle Hooks](#lifecycle-hooks)
|
||||
- [Modules](#modules)
|
||||
- [Contexts](#contexts)
|
||||
|
||||
## Overview
|
||||
We have re-designed the architecture of the `OHIF-v3` to enable building applications
|
||||
that are easily extensible to various use cases (modes) that behind the scene would utilize desired functionalities (extensions) to reach the goal of the use case.
|
||||
|
||||
Previously, extensions were “additive” and could not easily be mixed and matched within the same viewer for different use cases. Previous `OHIF-v2` architecture meant that
|
||||
any minor extension alteration usually would require the user to hard fork. E.g. removing some of the tools from the toolbar of the cornerstone extension meant you had to hard fork it, which was frustrating if the implementation was otherwise the same as master.
|
||||
|
||||
|
||||
> - Developers should make packages of *reusable* functionality as extensions, and can consume
|
||||
> publicly available extensions.
|
||||
> - Any conceivable radiological workflow or viewer setup will be able to be built with the platform through *modes*.
|
||||
|
||||
|
||||
|
||||
Practical examples of extensions include:
|
||||
|
||||
- A set of segmentation tools that build on top of the `cornerstone` viewport
|
||||
- A set of rendering functionalities to volume render the data
|
||||
- [See our maintained extensions for more examples of what's possible](#maintained-extensions)
|
||||
|
||||
|
||||
|
||||
<mark>Diagram showing how extensions are configured and accessed.
|
||||
<!--
|
||||
<div style="text-align: center;">
|
||||
<a href="/assets/img/extensions-diagram.png">
|
||||
<img src="/assets/img/extensions-diagram.png" alt="Extensions Diagram" style="margin: 0 auto; max-width: 500px;" />
|
||||
</a>
|
||||
<div><i>Diagram showing how extensions are configured and accessed.</i></div>
|
||||
</div> -->
|
||||
|
||||
|
||||
|
||||
## Extension Skeleton
|
||||
|
||||
An extension is a plain JavaScript object that has an `id` property, and one or
|
||||
more [modules](#modules) and/or [lifecycle hooks](#lifecycle-hooks).
|
||||
|
||||
```js
|
||||
// prettier-ignore
|
||||
export default {
|
||||
/**
|
||||
* Only required property. Should be a unique value across all extensions.
|
||||
*/
|
||||
id: 'example-extension',
|
||||
|
||||
// Lifecyle
|
||||
preRegistration() { /* */ },
|
||||
onModeEnter() { /* */ },
|
||||
onModeExit() { /* */ },
|
||||
// Modules
|
||||
getLayoutTemplateModule() { /* */ },
|
||||
getDataSourcesModule() { /* */ },
|
||||
getSopClassHandlerModule() { /* */ },
|
||||
getPanelModule() { /* */ },
|
||||
getViewportModule() { /* */ },
|
||||
getCommandsModule() { /* */ },
|
||||
getContextModule() { /* */ },
|
||||
getToolbarModule() { /* */ },
|
||||
getHangingProtocolModule() { /* */ },
|
||||
}
|
||||
```
|
||||
|
||||
## OHIF-Maintained Extensions
|
||||
A small number of powerful extensions for popular use cases are maintained by
|
||||
OHIF. They're co-located in the [`OHIF/Viewers`][viewers-repo] repository, in
|
||||
the top level [`extensions/`][ext-source] directory.
|
||||
|
||||
{% include "./_maintained-extensions-table.md" %}
|
||||
|
||||
|
||||
## Registering an Extension
|
||||
|
||||
Extensions are building blocks that need to be registered. There are two different ways to register and configure extensions: At
|
||||
[runtime](#registering-at-runtime) and at
|
||||
[build time](#registering-at-build-time).
|
||||
You can leverage one or both strategies. Which one(s) you choose depend on your
|
||||
application's requirements.
|
||||
|
||||
Each [module](#modules) defined by the extension
|
||||
becomes available to the modes via the `ExtensionManager` by requesting it via
|
||||
its id. [Read more about Extension Manager](#extension-manager)
|
||||
|
||||
|
||||
|
||||
### Registering at Runtime
|
||||
|
||||
The `@ohif/viewer` uses a [configuration file](../viewer/configuration.md) at
|
||||
startup. The schema for that file includes an `extensions` key that supports an
|
||||
array of extensions to register.
|
||||
|
||||
```js
|
||||
import MyFirstExtension from '@ohif/extension-first'
|
||||
import MySecondExtension from '@ohif/extension-second'
|
||||
|
||||
const extensionConfig = {/* extension configuration */}
|
||||
|
||||
// prettier-ignore
|
||||
const config = {
|
||||
routerBasename: '/',
|
||||
extensions: [
|
||||
MyFirstExtension,
|
||||
[
|
||||
MySecondExtension,
|
||||
extensionConfig
|
||||
],
|
||||
],
|
||||
modes: [/* modes */],
|
||||
showStudyList: true,
|
||||
dataSources: [ /* data source config */]
|
||||
}
|
||||
```
|
||||
|
||||
Then, behind the scene, the runtime-added extensions will get merged with the
|
||||
default app extensions (note: default app extensions include: `OHIFDefaultExtension`,
|
||||
`OHIFCornerstoneExtension`, `OHIFDICOMSRExtension`,
|
||||
`OHIFMeasurementTrackingExtension`)
|
||||
|
||||
### Registering at Build Time
|
||||
|
||||
The `@ohif/viewer` works best when built as a "Progressive Web Application"
|
||||
(PWA). If you know the extensions your application will need, you can specify
|
||||
them at "build time" to leverage advantages afforded to us by modern tooling:
|
||||
|
||||
- Code Splitting (dynamic imports)
|
||||
- Tree Shaking
|
||||
- Dependency deduplication
|
||||
|
||||
You can update the list of bundled extensions by:
|
||||
|
||||
1. Having your `@ohif/viewer` project depend on the extension
|
||||
2. Importing and adding it to the list of extensions in the
|
||||
`<repo-root>/platform/src/index.js` entrypoint:
|
||||
|
||||
```js
|
||||
import OHIFDefaultExtension from '@ohif/extension-default';
|
||||
import OHIFCornerstoneExtension from '@ohif/extension-cornerstone';
|
||||
import OHIFMeasurementTrackingExtension from '@ohif/extension-measurement-tracking';
|
||||
import OHIFDICOMSRExtension from '@ohif/extension-dicom-sr';
|
||||
import MyFirstExtension from '@ohif/extension-first'
|
||||
|
||||
/** Combine our appConfiguration and "baked-in" extensions */
|
||||
const appProps = {
|
||||
config: window ? window.config : {},
|
||||
defaultExtensions: [
|
||||
OHIFDefaultExtension,
|
||||
OHIFCornerstoneExtension,
|
||||
OHIFMeasurementTrackingExtension,
|
||||
OHIFDICOMSRExtension,
|
||||
MyFirstExtension
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
## Lifecycle Hooks
|
||||
|
||||
Currently, there are three lifecycle hook for extensions:
|
||||
|
||||
|
||||
[`preRegistration`](./lifecycle/pre-registration.md)
|
||||
This hook is called once on initialization of the entire viewer application, used to initialize the extensions state, and consume user defined extension configuration. If an extension defines the [`preRegistration`](./lifecycle/pre-registration.md)
|
||||
lifecycle hook, it is called before any modules are registered in the
|
||||
`ExtensionManager`. It's most commonly used to wire up extensions to
|
||||
[services](./../services/index.md) and [commands](./modules/commands.md), and to
|
||||
bootstrap 3rd party libraries.
|
||||
|
||||
|
||||
[`onModeEnter`](./lifecycle/on-mode-enter.md): This hook is called whenever a new mode is entered, or a mode’s data or datasource is switched. This hook can be used to initialize data.
|
||||
|
||||
[`onModeExit`](./lifecycle/on-mode-exit.md): Similarly to onModeEnter, this hook is called when navigating away from a mode, or before a mode’s data or datasource is changed. This can be used to clean up data (e.g. remove annotations that do not need to be persisted)
|
||||
|
||||
|
||||
|
||||
## Modules
|
||||
Modules are the meat of extensions, the `blocks` that we have been talking about a lot.
|
||||
They provide "definitions", components, and filtering/mapping logic that are then made available to modes and services.
|
||||
|
||||
Each module type has a special purpose, and is consumed by our viewer
|
||||
differently.
|
||||
|
||||
|
||||
{% include "./_modules.md" %}
|
||||
|
||||
|
||||
<figure style="text-align: center; font-style: italic;">Tbl. Module types with abridged descriptions and examples. Each module links to a dedicated documentation page.</figure>
|
||||
|
||||
|
||||
|
||||
|
||||
### Contexts
|
||||
|
||||
The `@ohif/viewer` tracks "active contexts" that extensions can use to scope
|
||||
their functionality. Some example contexts being:
|
||||
|
||||
- Route: `ROUTE:VIEWER`, `ROUTE:STUDY_LIST`
|
||||
- Active Viewport: `ACTIVE_VIEWPORT:CORNERSTONE`, `ACTIVE_VIEWPORT:VTK`
|
||||
|
||||
An extension module can use these to say "Only show this Toolbar Button if the
|
||||
active viewport is a Cornerstone viewport." This helps us use the appropriate UI
|
||||
and behaviors depending on the current contexts.
|
||||
|
||||
For example, if we have hotkey that "rotates the active viewport", each Viewport
|
||||
module that supports this behavior can add a command with the same name, scoped
|
||||
to the appropriate context. When the `command` is fired, the "active contexts"
|
||||
are used to determine the appropriate implementation of the rotate behavior.
|
||||
|
||||
|
||||
<!-- <mark>do we want the followings?
|
||||
## Consuming Extensions
|
||||
|
||||
We consume extensions, via the `ExtensionManager`, in our `@ohif/viewer`
|
||||
project.
|
||||
|
||||
```js
|
||||
const extensionManager = new ExtensionManager({
|
||||
commandsManager,
|
||||
servicesManager,
|
||||
hotkeysManager
|
||||
});
|
||||
|
||||
// prettier-ignore
|
||||
extensionManager.registerExtensions([ /** **/ ]);
|
||||
```
|
||||
|
||||
The `@ohif/viewer` project handles data fetching, basic routing, wires up UI
|
||||
services, and is the home to the more bespoke application logic that doesn't
|
||||
make as much sense to make reusable.
|
||||
|
||||
Long-term, replacing the `@ohif/viewer` application and consuming extensions
|
||||
(and the `ExtensionManager`) in your own project is the ideal path for
|
||||
applications requiring a high degree of customization that can't be achieved
|
||||
with current theming, configuration, extension, and services support.
|
||||
|
||||
If you're not sure how to achieve your goals with the extensibility available
|
||||
today, create a GitHub issue! -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
LINKS
|
||||
-->
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
[viewers-repo]: https://github.com/OHIF/Viewers
|
||||
[ext-source]: https://github.com/OHIF/Viewers/tree/master/extensions
|
||||
[module-types]: https://github.com/OHIF/Viewers/blob/master/platform/core/src/extensions/MODULE_TYPES.js
|
||||
<!-- prettier-ignore-end -->
|
||||
@ -1,29 +0,0 @@
|
||||
# Lifecycle Hook: onModeEnter
|
||||
|
||||
If an extension defines the `onModeEnter` lifecycle hook, it is called
|
||||
when a new mode is enters, or a mode's data or datasource is switched.
|
||||
|
||||
For instance, in DICOM structured report extension (`dicom-sr`), we are using
|
||||
`onModeEnter` to re-create the displaySets after a new mode is entered.
|
||||
|
||||
_Example `onModeEnter` hook implementation_
|
||||
|
||||
```js
|
||||
export default {
|
||||
id: 'org.ohif.dicom-sr',
|
||||
|
||||
onModeEnter({ servicesManager}) {
|
||||
const { DisplaySetService } = servicesManager.services;
|
||||
const displaySetCache = DisplaySetService.getDisplaySetCache();
|
||||
|
||||
const srDisplaySets = displaySetCache.filter(
|
||||
ds => ds.SOPClassHandlerId === SOPClassHandlerId
|
||||
);
|
||||
|
||||
srDisplaySets.forEach(ds => {
|
||||
// New mode route, allow SRs to be hydrated again
|
||||
ds.isHydrated = false;
|
||||
});
|
||||
},
|
||||
};
|
||||
```
|
||||
@ -1,17 +0,0 @@
|
||||
# Lifecylce Hook: onModeExit
|
||||
|
||||
If an extension defines the `onModeExit` lifecycle hook, it is called when navigating
|
||||
away from a mode. This hook can be used to clean up data tasks such as unregistering services,
|
||||
removing annotations that do not need to be persisted.
|
||||
|
||||
_Example `onModeExit` hook implementation_
|
||||
|
||||
```js
|
||||
export default {
|
||||
id: 'myExampleExtension',
|
||||
|
||||
onModeExit({ servicesManager, commandsManager}) {
|
||||
myCacheServie.purge()
|
||||
},
|
||||
};
|
||||
```
|
||||
@ -1,25 +0,0 @@
|
||||
# Managers
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
`OHIF` uses `Managers` to accomplish various purposes such as registering new services, dependency injection, and aggregating and exposing `extension` features.
|
||||
|
||||
`OHIF-v3` provides the following managers which we will discuss in depth.
|
||||
|
||||
{% include "./_managers.md" %}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
LINKS
|
||||
-->
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
|
||||
[core-services]: https://github.com/OHIF/Viewers/tree/master/platform/core/src/services
|
||||
[services-manager]: https://github.com/OHIF/Viewers/blob/master/platform/core/src/services/ServicesManager.js
|
||||
[cross-cutting-concerns]: https://en.wikipedia.org/wiki/Cross-cutting_concern
|
||||
<!-- prettier-ignore-end -->
|
||||
@ -1,95 +0,0 @@
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left">Property</th>
|
||||
<th align="left">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left">
|
||||
id
|
||||
</td>
|
||||
<td align="left">unique mode id used to refer to the mode</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">
|
||||
displayName
|
||||
</td>
|
||||
<td align="left">actual name of the mode being displayed for each study in the study summary panel</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">
|
||||
<a href="./lifeCycle.md#onModeEnter">
|
||||
onModeEnter
|
||||
</a>
|
||||
</td>
|
||||
<td align="left">hook is called when the mode is entered by the specified route</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">
|
||||
<a href="./lifeCycle.md#onModeExit">
|
||||
onModeExit
|
||||
</a>
|
||||
</td>
|
||||
<td align="left">hook is called when the mode exited</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">
|
||||
<a href="">
|
||||
validationTags
|
||||
</a>
|
||||
</td>
|
||||
<td align="left">validationTags</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">
|
||||
<a href="">
|
||||
isValidMode
|
||||
</a>
|
||||
</td>
|
||||
<td align="left">Checks if the mode is valid for a study</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">
|
||||
<a href="">
|
||||
routes
|
||||
</a>
|
||||
</td>
|
||||
<td align="left">route config which defines the route address, and the layout for it</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">
|
||||
<a href="./index.md#consuming-extensions">
|
||||
extensions
|
||||
</a>
|
||||
</td>
|
||||
<td align="left">extensions needed by the mode</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">
|
||||
<a href="">
|
||||
hanging protocol
|
||||
</a>
|
||||
</td>
|
||||
<td align="left">list of hanging protocols that the mode should have access to</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">
|
||||
<a href="">
|
||||
sopClassHandlers
|
||||
</a>
|
||||
</td>
|
||||
<td align="left">list of SOPClass modules needed by the mode </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">
|
||||
<a href="">
|
||||
hotkeys
|
||||
</a>
|
||||
</td>
|
||||
<td align="left">hotkeys</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
@ -1,340 +0,0 @@
|
||||
# Modes
|
||||
|
||||
- [Modes](#modes)
|
||||
- [Overview](#overview)
|
||||
- [Anatomy](#anatomy)
|
||||
- [Consuming Extensions](#consuming-extensions)
|
||||
- [routes](#routes)
|
||||
- [extensions](#extensions)
|
||||
- [hangingProtocols](#hangingprotocols)
|
||||
- [sopClassHandlers](#sopclasshandlers)
|
||||
- [hotkeys](#hotkeys)
|
||||
- [Registration](#registration)
|
||||
|
||||
## Overview
|
||||
A mode can be thought of as a viewer app configured to perform a specific task,
|
||||
such as tracking measurements over time, 3D segmentation, a guided radiological workflow, etc.
|
||||
Addition of modes enables *application* with many *applications* as each mode become
|
||||
a mini *app configuration* behind the scene.
|
||||
|
||||
Upon initialization the viewer will consume extensions and modes and build up the route desired, these can then be accessed via the study list, or directly via url parameters.
|
||||
|
||||
<!-- > Modes make extensions (features) more reusable and powerful. -->
|
||||
|
||||
OHIF-v3 architecture can be seen in the following:
|
||||
|
||||

|
||||
|
||||
>Note: Templates are now a part of “extensions”
|
||||
>Routes are configured by modes and/or app
|
||||
|
||||
|
||||
As mentioned, modes are tied to a specific route in the viewer, and multiple modes/routes can be present within a single application. This allows for tremendously more flexibility than before you can now:
|
||||
|
||||
- Simultaneously host multiple viewers with for different use cases from within the same app deploy.
|
||||
- Make radiological viewers for specific purposes/workflows, e.g.:
|
||||
- Tracking the size of lesions over time.
|
||||
- PET/CT fusion workflows.
|
||||
- Guided review workflows optimized for a specific clinical trial.
|
||||
- Still host one single feature-rich viewer if you desire.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Anatomy
|
||||
A mode configuration has a `route` name which is dynamically transformed into a viewer route on initialization of the application. Modes that are available to a study will appear in the study list.
|
||||
|
||||

|
||||
|
||||
|
||||
The mode configuration specifies which `extensions` the mode requires, which `LayoutTemplate` to use, and what props to pass to the template. For the default template this defines which `side panels` will be available, as well as what `viewports` and which `displaySets` they may hang.
|
||||
|
||||
Mode's config is actually a function that return a config object with certain properties, the high-level view of this config object is:
|
||||
|
||||
|
||||
|
||||
```js
|
||||
// modes/example/src/index.js
|
||||
|
||||
export default function mode() {
|
||||
return {
|
||||
id: '',
|
||||
displayName: '',
|
||||
onModeEnter: () => {},
|
||||
onModeExit: () => {},
|
||||
validationTags: {},
|
||||
isValidMode: () => {},
|
||||
routes: [
|
||||
{
|
||||
path: '',
|
||||
init: () => {},
|
||||
layoutTemplate: () => {},
|
||||
},
|
||||
],
|
||||
extensions: [],
|
||||
hangingProtocols: [],
|
||||
sopClassHandlers: [],
|
||||
hotkeys: [],
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
{% include "./_anatomy.md" %}
|
||||
|
||||
|
||||
|
||||
### Consuming Extensions
|
||||
As mentioned in the [Extensions](../extensions/index.md) section, in `OHIF-v3` developers
|
||||
write their extensions to create re-usable functionalities that later can be used by `modes`.
|
||||
Now, it is time to describe how the registered extensions will get utilized for a workflow mode
|
||||
via its `id`.
|
||||
|
||||
To use a module element you can use the `${extensionId}.${moduleType}.${element.name}` schema.
|
||||
For instance, if a mode requires the left panel with name of `AIPanel` that is added by the `myAIExtension` via the following `getPanelModule` code, it should address it as `myAIExtension.panelModule.AIPanel` inside the mode configuration file.
|
||||
In the background `OHIF` will handle grabbing the correct panel via `ExtensionManager`.
|
||||
|
||||
|
||||
```js
|
||||
// extensions/myAIExtension/getPanelModule.js
|
||||
|
||||
import PanelAI from './PanelAI.js';
|
||||
|
||||
|
||||
function getPanelModule({
|
||||
commandsManager,
|
||||
extensionManager,
|
||||
servicesManager,
|
||||
}) {
|
||||
const wrappedAIPanel = () => {
|
||||
return (
|
||||
<PanelAI
|
||||
commandsManager={commandsManager}
|
||||
servicesManager={servicesManager}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
return [
|
||||
{
|
||||
name: 'AIPanel',
|
||||
iconName: 'list-bullets',
|
||||
iconLabel: '',
|
||||
label: 'AI Panel',
|
||||
isDisabled: studies => {}, // optional
|
||||
component: wrappedAIPanel,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
Now, let's look at `longitudinal` mode which consumes various functionalities from different extensions.
|
||||
Note that, you don't need to have `org.ohif.extensionName`, this is a pattern we chose to
|
||||
name our [OHIF-maintained](../extensions/index.md#ohif-maintained-extensions) extensions, you can simply
|
||||
have `extensionName` as the `id` for yours and refer to it inside your modes.
|
||||
|
||||
|
||||
```js
|
||||
export default function mode({ modeConfiguration }) {
|
||||
return {
|
||||
/*
|
||||
...
|
||||
*/
|
||||
routes: [
|
||||
{
|
||||
/*
|
||||
...
|
||||
*/
|
||||
layoutTemplate: ({ location, servicesManager }) => {
|
||||
return {
|
||||
id: ohif.layout,
|
||||
props: {
|
||||
leftPanels: [
|
||||
'org.ohif.measurement-tracking.panelModule.seriesList',
|
||||
],
|
||||
rightPanels: [
|
||||
'org.ohif.measurement-tracking.panelModule.trackedMeasurements',
|
||||
],
|
||||
viewports: [
|
||||
{
|
||||
namespace:
|
||||
'org.ohif.measurement-tracking.viewportModule.cornerstone-tracked',
|
||||
displaySetsToDisplay: [
|
||||
'org.ohif.default.sopClassHandlerModule.stack',
|
||||
],
|
||||
},
|
||||
{
|
||||
namespace: 'org.ohif.dicom-sr.viewportModule.dicom-sr',
|
||||
displaySetsToDisplay: [
|
||||
'org.ohif.dicom-sr.sopClassHandlerModule.dicom-sr',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
extensions: [
|
||||
'org.ohif.default',
|
||||
'org.ohif.cornerstone',
|
||||
'org.ohif.measurement-tracking',
|
||||
'org.ohif.dicom-sr',
|
||||
],
|
||||
hangingProtocols: ['org.ohif.default.hangingProtocolModule.petCT'],
|
||||
sopClassHandlers: [
|
||||
'org.ohif.default.sopClassHandlerModule.stack',
|
||||
'org.ohif.dicom-sr.sopClassHandlerModule.dicom-sr',
|
||||
],
|
||||
/*...*/
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### routes
|
||||
routes config is an array of route settings, and the overall look and behavior of the viewer at the designated route is defined by the `layoutTemplate` and `init` functions for the route. We will learn more about each of the above properties inside the [route documentation](./routes.md)
|
||||
|
||||
### extensions
|
||||
Currently `extensions` property in the mode config is used to add *contextModule* of the mentioned extensions to the list of contexts and provide them through out the app. Since extensions are registered by the ExtensionManager, modes have access to the them even if they have not been referred in the mode config file inside *extensions* property. [Read more about extension registration](../extensions/index.md#registering-an-extension)
|
||||
|
||||
```js
|
||||
// platform/viewer/src/routes/Mode/Mode.jsx
|
||||
|
||||
const { extensions } = mode;
|
||||
|
||||
extensions.forEach(extensionId => {
|
||||
const allRegisteredModuleIds = Object.keys(extensionManager.modulesMap);
|
||||
const moduleIds = allRegisteredModuleIds.filter(id =>
|
||||
id.includes(`${extensionId}.contextModule.`)
|
||||
);
|
||||
|
||||
const modules = moduleIds.map(extensionManager.getModuleEntry);
|
||||
contextModules = contextModules.concat(modules);
|
||||
});
|
||||
```
|
||||
|
||||
### hangingProtocols
|
||||
Currently, you can pass your defined hanging protocols inside the `hangingProtocols` property of
|
||||
the mode's config. This will get used inside the `Mode.jsx` to configure the `HangingProtocolService`.
|
||||
|
||||
```js
|
||||
// platform/viewer/src/routes/Mode/Mode.jsx
|
||||
|
||||
const { hangingProtocols } = mode;
|
||||
|
||||
hangingProtocols.forEach(extentionProtocols => {
|
||||
const { protocols } = extensionManager.getModuleEntry(extentionProtocols);
|
||||
HangingProtocolService.addProtocols(protocols);
|
||||
});
|
||||
```
|
||||
|
||||
### sopClassHandlers
|
||||
Mode's configuration also accepts the `sopClassHandler` modules that have been added by the extensions.
|
||||
This information will get used inside the `Mode.jsx` to initialize the `DisplaySetService` with the provided
|
||||
SOPClass modules which handles creation of the displaySets.
|
||||
|
||||
```js
|
||||
// platform/viewer/src/routes/Mode/Mode.jsx
|
||||
|
||||
const { sopClassHandlers } = mode;
|
||||
|
||||
DisplaySetService.init(extensionManager, sopClassHandlers);
|
||||
```
|
||||
|
||||
### hotkeys
|
||||
`hotkeys` is another property in the configuration of a mode that can be defined to add the specific hotkeys to the viewer at all routes.
|
||||
|
||||
```js
|
||||
// default hotkeys
|
||||
import { hotkeys } from '@ohif/core';
|
||||
|
||||
|
||||
const myHotkeys = [
|
||||
{
|
||||
commandName: 'setToolActive',
|
||||
commandOptions: { toolName: 'Zoom' },
|
||||
label: 'Zoom',
|
||||
keys: ['z'],
|
||||
isEditable: true,
|
||||
},
|
||||
{
|
||||
commandName: 'scaleUpViewport',
|
||||
label: 'Zoom In',
|
||||
keys: ['+'],
|
||||
isEditable: true,
|
||||
},
|
||||
]
|
||||
|
||||
export default function mode() {
|
||||
return {
|
||||
id: '',
|
||||
displayName: '',
|
||||
/*
|
||||
...
|
||||
*/
|
||||
hotkeys: [..hotkeys.defaults.hotkeyBindings, ...myHotkeys],
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
```js
|
||||
// platform/viewer/src/routes/Mode/Mode.jsx
|
||||
|
||||
hotkeysManager.setDefaultHotKeys(hotkeys);
|
||||
hotkeysManager.setHotkeys(hotkeys);
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Registration
|
||||
Upon release modes will also be plugged into the app via configuration, but this is still an area which is under development/discussion, and they are currently pulled from the `window` in beta.
|
||||
|
||||
|
||||
```js
|
||||
// modes/longitudinal/src/index.js
|
||||
|
||||
export default function mode() {
|
||||
return {
|
||||
id: 'viewer',
|
||||
displayName: 'Basic Viewer',
|
||||
onModeEnter: () => {/**...**/},
|
||||
onModeExit: () => {/**...**/},
|
||||
validationTags: {/**...**/},
|
||||
isValidMode: () => {/**...**/},
|
||||
routes: [
|
||||
{
|
||||
path: 'longitudinal',
|
||||
init: () => {/**...**/},
|
||||
layoutTemplate: () => {/**...**/},
|
||||
},
|
||||
],
|
||||
extensions: [/**...**/],
|
||||
hangingProtocols: [/**...**/],
|
||||
sopClassHandlers: [/**...**/],
|
||||
hotkeys: [/**...**/],
|
||||
}
|
||||
}
|
||||
|
||||
window.longitudinalMode = mode({});
|
||||
|
||||
```
|
||||
|
||||
and inside `@ohif/viwer` we have:
|
||||
|
||||
```js
|
||||
// platform/viewer/src/appInit.js
|
||||
|
||||
if (!appConfig.modes.length) {
|
||||
appConfig.modes.push(window.longitudinalMode);
|
||||
// appConfig.modes.push(window.segmentationMode);
|
||||
}
|
||||
```
|
||||
@ -1,44 +0,0 @@
|
||||
{
|
||||
"name": "ohif-viewer-latest-docs",
|
||||
"version": "2.0.0",
|
||||
"description": "Open Health Imaging Foundation Viewers Metarepo for documentation",
|
||||
"main": ".eslintrc.js",
|
||||
"directories": {
|
||||
"doc": "docs"
|
||||
},
|
||||
"scripts": {
|
||||
"docs": "gitbook install && gitbook serve"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/OHIF/Viewers.git"
|
||||
},
|
||||
"keywords": [
|
||||
"dicom",
|
||||
"cornerstone",
|
||||
"OHIF",
|
||||
"zero",
|
||||
"footprint",
|
||||
"medical",
|
||||
"imaging",
|
||||
"viewer"
|
||||
],
|
||||
"author": "Open Health Imaging Foundation",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/OHIF/Viewers/issues"
|
||||
},
|
||||
"homepage": "https://github.com/OHIF/Viewers#readme",
|
||||
"dependencies": {
|
||||
"gitbook-plugin-anchors": "^0.7.1",
|
||||
"gitbook-plugin-edit-link": "^2.0.2",
|
||||
"gitbook-plugin-ga": "^2.0.0",
|
||||
"gitbook-plugin-github": "^3.0.0",
|
||||
"gitbook-plugin-sitemap": "^1.2.0",
|
||||
"gitbook-plugin-theme-cornerstone": "^1.1.4",
|
||||
"gitbook-plugin-versions": "^2.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"gitbook-cli": "^2.3.2"
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
# Quick Start
|
||||
|
||||
This page details how to get an instance of the OHIF Viewer up and running as
|
||||
fast as possible. It shows how to grab a pre-built version of the application,
|
||||
point it at your data source (PACS), and plop it on a web server.
|
||||
|
||||
## Options
|
||||
|
||||
### 1. Pre-built PWA
|
||||
|
||||
...
|
||||
|
||||
### 2. Script-Tag
|
||||
|
||||
...
|
||||
|
||||
### 3. Docker
|
||||
|
||||
...
|
||||
|
||||
## Security Concerns
|
||||
|
||||
- Secure your data
|
||||
|
||||
## Common Issues
|
||||
|
||||
- Missing server rewrite rules
|
||||
- CORS issues when requesting data from PACS
|
||||
@ -1,40 +0,0 @@
|
||||
# Services And Managers
|
||||
|
||||
- [Services And Managers](#services-and-managers)
|
||||
- [Overview](#overview)
|
||||
- [Services](#services)
|
||||
|
||||
## Overview
|
||||
Services are "concern-specific" code modules that can be consumed across layers. Services provide
|
||||
a set of operations, often tied to some shared state, and are made available to
|
||||
through out the app via the `ServicesManager`. Services are particularly well suited to
|
||||
address [cross-cutting concerns][cross-cutting-concerns].
|
||||
|
||||
Each service should be:
|
||||
|
||||
- self-contained
|
||||
- able to fail and/or be removed without breaking the application
|
||||
- completely interchangeable with another module implementing the same interface
|
||||
|
||||
|
||||
> In `OHIF-v3` we have added multiple non-UI services and have introduced **pub/sub** pattern to reduce coupling between layers.
|
||||
>
|
||||
> [Read more about Pub/Sub](./pubsub.md)
|
||||
|
||||
|
||||
## Services
|
||||
The following services is available in the `OHIF-v3`.
|
||||
|
||||
{% include "./_services.md" %}
|
||||
|
||||
|
||||
<!--
|
||||
LINKS
|
||||
-->
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
|
||||
[core-services]: https://github.com/OHIF/Viewers/tree/master/platform/core/src/services
|
||||
[services-manager]: https://github.com/OHIF/Viewers/blob/master/platform/core/src/services/ServicesManager.js
|
||||
[cross-cutting-concerns]: https://en.wikipedia.org/wiki/Cross-cutting_concern
|
||||
<!-- prettier-ignore-end -->
|
||||
@ -1,19 +0,0 @@
|
||||
# Overview
|
||||
Our documentations in this section is tailored toward the end-user. Developers
|
||||
can skip this section and visit the development section.
|
||||
In this section, we explore various core functionalities and use cases that `OHIF viewer`
|
||||
provides. In order to follow the guides below, you need to have a running instance
|
||||
of the viewer.
|
||||
|
||||
|
||||
- [Study List](./studyList/index.md)
|
||||
- [Filters](./studyList/index.md#filters)
|
||||
- [Study Summary](./studyList/index.md#study-summary)
|
||||
- [Study-specific modes](./studyList/index.md#study-specific-modes)
|
||||
- [Viewer (Basic Viewer)](./viewer/index.md)
|
||||
- [Overview](./viewer/index.md#overview)
|
||||
- [Study Panel](./viewer/studyPanel/study-panel.md#overview)
|
||||
- [Measurement Panel](./viewer/measurementPanel/measurement-panel.md#overview)
|
||||
- [Viewport](./viewer/viewport/viewport.md#overview)
|
||||
- [Toolbar](./viewer/toolbar/toolbar.md#overview)
|
||||
- [HotKeys](./viewer/hotkeys/hotkeys.md#overview)
|
||||
@ -1,70 +0,0 @@
|
||||
# Study list
|
||||
- [Study List](./index.md)
|
||||
- [Filters](./index.md#filters)
|
||||
- [Study Summary](./index.md#study-summary)
|
||||
- [Study-specific modes](./index.md#study-specific-modes)
|
||||
- [View Study](./index.md#view-study)
|
||||
|
||||
## Overview
|
||||
The first page you will see when the viewer is loaded is called `Study List`.
|
||||
In this page you can explore all the studies that are stored on the configured
|
||||
server for the `OIHF Viewer`.
|
||||
|
||||

|
||||
|
||||
At the end of the page you can navigate to the next/previous page or change the
|
||||
default number of studies that are shown
|
||||
|
||||

|
||||
## Filters
|
||||
There are certain filters that can be used to limit the study list to the desired
|
||||
criteria.
|
||||
|
||||
- Patient Name: Searches between patients names
|
||||
- MRN: Searches between patients Medical Record Number
|
||||
- Study Data: Filters the date of the acquisition
|
||||
- Description: Searches between study descriptions
|
||||
- Modality: Filters the modalities
|
||||
- Accession: Searches between patients accession number
|
||||
|
||||
|
||||
An example of using study list filter is shown below:
|
||||
|
||||

|
||||
|
||||
## Study Summary
|
||||
If you you click on one of the studies, the panel for displaying the summary
|
||||
of the study will shows up.
|
||||
|
||||

|
||||
|
||||
As you can see, a summary of series available in the study is shown, which contains
|
||||
the series description, series number, modality of the series, and instances in the series.
|
||||
|
||||
Next, We will discuss the modes, and their enabled/disabled states.
|
||||
|
||||
|
||||
## Study Specific Modes
|
||||
As seen for each study, all the available modes will get shown. What is a mode?
|
||||
Modes define the higher-level functionalities and appearance for the viewer.
|
||||
For instance, as seen, there are two modes shown for the selected study
|
||||
|
||||
- Basic Viewer: Default mode that enables rendering and measurement tracking
|
||||
|
||||
- PET/CT Fusion: Mode for visualizing the PET CT study in a 3x3 format.
|
||||
|
||||
However, based on the mode configurations (e.g., available modalities), they can be
|
||||
enabled or disabled.
|
||||
|
||||
Below, you can see two studies, In Study 1, Basic Viewer mode is enabled and
|
||||
ready to be used; however, the PET/CT fusion is disabled by the viewer since
|
||||
only PET images are found in the study.
|
||||
|
||||

|
||||
|
||||
|
||||
## View Study
|
||||
You can click on the `Basic Viewer` to open the viewer for the selected study.
|
||||
|
||||
|
||||

|
||||
@ -1,12 +0,0 @@
|
||||
# Language
|
||||
|
||||
OHIF supports internationalization capabilities and setting the general language
|
||||
of the Viewer.
|
||||
|
||||
It should be noted that we don't have complete translations for all the components
|
||||
and all the languages; however, you can easily add the key value translation pairs
|
||||
following developer guides.
|
||||
|
||||
Summary of language changing usage can be seen below:
|
||||
|
||||
<mark>Upload
|
||||
@ -1,62 +0,0 @@
|
||||
# Measurement panel
|
||||
|
||||
In `Basic Viewer` mode, right panel is the `Measurement Panel`. When you use an annotation tool, a pop up will show up and asks the user if they want to track measurements for the
|
||||
series on which the annotation was drawn.
|
||||
|
||||

|
||||
|
||||
If you select `yes`, the series becomes a `tracked series`, and the current drawn measurement and next measurements will get shown up on the measurement panel on the right.
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
# Renaming Measurements
|
||||
You can edit the measurement name by hovering over the measurement and selecting the edit icon.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Result:
|
||||
|
||||

|
||||
|
||||
|
||||
# Deleting a Measurement
|
||||
A measurement can be deleting by dragging it outside the image in the viewport. You can
|
||||
take a look at the overview video to see this behavior.
|
||||
|
||||
|
||||
# Jumping to a Measurement
|
||||
Measurements that appear on the measurement panel are linked directly to their original
|
||||
tool on the viewport. This enables the user to click on a measurement and the viewport will jump to the slice that the measurement has been drawn. You can
|
||||
take a look at the overview video to see this behavior.
|
||||
|
||||
# Prev/Next Measurement
|
||||
Measurement navigation inside the top viewport can be used to move to previous and next measurement.
|
||||
|
||||

|
||||
|
||||
# Export Measurements
|
||||
You can export the measurements by clicking on the `Export`. A CSV file will get downloaded to your local computer containing the drawn measurements.
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
If you have set up your DICOM server to be able to store instances from the viewer, then you are able to create a report by clicking on the `Create Report`.
|
||||
This will create a DICOM Structured Report (SR) from the measurements and push it
|
||||
to the server.
|
||||
|
||||
For instance, running the Viewer on a local DCM4CHEE:
|
||||
|
||||
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/557569965?badge=0&autopause=0&player_id=0&app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;" title="DICOM SR Export"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
|
||||
|
||||
|
||||
|
||||
# Overview video
|
||||
An overview of measurement drawing and exporting can be seen below:
|
||||
|
||||
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/545986384?badge=0&autopause=0&player_id=0&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><script src="https://player.vimeo.com/api/player.js"></script>
|
||||
@ -1,16 +0,0 @@
|
||||
# Study panel
|
||||
|
||||
In `Basic Viewer` mode, the left panel includes Studies related to the current patient.
|
||||
You can see three main type of studies below
|
||||
|
||||
- Primary: The opened study from the study list
|
||||
- Recent: Other studies for this patient
|
||||
- All: Includes both primary and recent studies
|
||||
|
||||

|
||||
|
||||
This is a new feature that we have added to `OHIF-v3`, that shows all the studies that the patient with the specific MRN had and are available from the data storage.
|
||||
|
||||

|
||||
|
||||
As you can see the first picture, the dashed circle on the left side of each series demonstrates whether the series is being tracked for measurement or not.
|
||||
@ -1,70 +0,0 @@
|
||||
|
||||
|
||||
|
||||
# Toolbar
|
||||
|
||||
The four main components of the toolbar are:
|
||||
|
||||
- Navigation back to the [Study List](../../studyList/index.md)
|
||||
- Logo and white labelling
|
||||
- [Tools](#tools)
|
||||
- [Preferences](#preferences)
|
||||
|
||||

|
||||
|
||||
|
||||
# Tools
|
||||
This section displays all the available tools inside the mode.
|
||||
|
||||
## Measurement tools
|
||||
They can be used to measure the area of interest. This measurement can be performed
|
||||
via:
|
||||
|
||||
- Length Tool: Calculated the distance between two points
|
||||
- Bidirectional Tool: A 2D Length tool in two main axis
|
||||
- Annotation: To label and point to an area
|
||||
- Ellipse: Calculates statistics on a ellipse area
|
||||
- Rectangle: Calculates statistics on a rectangle area
|
||||
- Probe: To read the intensity value at a location
|
||||
|
||||
|
||||

|
||||
|
||||
To draw a measurement you can select it from the toolbar and click and drag mouse
|
||||
to reach the desired shape, size and direction.
|
||||
|
||||
A sample tool drawing is shown below
|
||||
|
||||
|
||||
# Presets
|
||||
Preset tool enables manipulating the window level and window width of the rendered
|
||||
image, which basically modifies the contrast and brightness.
|
||||
|
||||
You can also choose from the list of pre-defined presets by clicking on the triangle.
|
||||
|
||||

|
||||
|
||||
|
||||
# Download High Quality Image
|
||||
By clicking on the Camera icon you can open the window for downloading the image as
|
||||
common image formats (png, jpg)
|
||||
|
||||

|
||||
|
||||
In the opened modal, you can set the filename, image's width and height, and filetype and press download for downloading the image to your local computer.
|
||||
|
||||

|
||||
|
||||
|
||||
# Extra tools
|
||||
Lots of other tools are also available in the last tool icon drawer. If you
|
||||
click on the triangle they will get appeared.
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
# Overview
|
||||
An overview of tool usage can been seen below:
|
||||
|
||||
<div style="padding:56.25% 0 0 0;position:relative;"><iframe src="https://player.vimeo.com/video/545989422?badge=0&autopause=0&player_id=0&app_id=58479" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen style="position:absolute;top:0;left:0;width:100%;height:100%;" title="Toolbar-annotation"></iframe></div><script src="https://player.vimeo.com/api/player.js"></script>
|
||||
@ -1,3 +0,0 @@
|
||||
# Hotkeys
|
||||
|
||||
...
|
||||
@ -1,7 +0,0 @@
|
||||
# Viewer
|
||||
|
||||
The OHIF Viewing Platform strives to be highly configurable and extensible. This
|
||||
makes it easier for our community members to keep their "secret sauce" private,
|
||||
and incentives contributions back to the platform. The `@ohif/viewer` project
|
||||
of the platform is the lynchpin that combines everything to create our
|
||||
application.
|
||||
@ -1,2 +0,0 @@
|
||||
|
||||
This folder contains the OHIF Viewer installation instructions, categorized by operating system
|
||||
@ -1,2 +0,0 @@
|
||||
|
||||
This folder contains the OHIF Viewer installation instructions on the Microsoft Windows operating system
|
||||
@ -1,2 +0,0 @@
|
||||
|
||||
This folder contains the OHIF Viewer documentation
|
||||
@ -1,61 +0,0 @@
|
||||
# OHIF Viewers
|
||||
|
||||
- Essentials
|
||||
- [Installation](essentials/installation.md)
|
||||
- [Getting Started](essentials/getting-started.md)
|
||||
- [Architecture](essentials/architecture.md)
|
||||
- [Configuration](essentials/configuration.md)
|
||||
- [Troubleshooting](essentials/troubleshooting.md)
|
||||
- Connecting to Image Archives
|
||||
- [What are my options?](connecting-to-image-archives/options.md)
|
||||
- [DICOM Web](connecting-to-image-archives/dicomweb.md)
|
||||
- [DICOM Message Service Element](connecting-to-image-archives/dimse.md)
|
||||
- Examples
|
||||
- [dcm4chee w/ Docker](connecting-to-image-archives/dcm4chee-with-docker.md)
|
||||
- [Orthanc w/ Docker](connecting-to-image-archives/orthanc-with-docker.md)
|
||||
- [Google Cloud Healthcare](connecting-to-image-archives/google-cloud-healthcare.md)
|
||||
- [Osirix](connecting-to-image-archives/osirix.md)
|
||||
- Data Organization
|
||||
- [Data Hierarchy](data/data-hierarchy.md)
|
||||
- [Image Viewport](data/image-viewport.md)
|
||||
- Viewport Layout
|
||||
- [Layout Management](layout/layout-management.md)
|
||||
- [Hanging Protocols](layout/hanging-protocols.md)
|
||||
- Packages
|
||||
- [Measurements Package (ohif-measurements)](packages/measurements.md)
|
||||
- Deployment
|
||||
- [Building for Production](deployment/building-for-production.md)
|
||||
- [Security](deployment/security.md)
|
||||
- I Want To...
|
||||
- [Add a Tool to the Viewer](I-want-to/add-a-tool-to-the-viewer.md)
|
||||
- [Add a Logo to the Viewer](I-want-to/add-a-logo-to-the-viewer.md)
|
||||
----
|
||||
|
||||
- Example Applications
|
||||
- [OHIF Viewer](example-applications/ohif-viewer.md)
|
||||
- [Lesion Tracker](example-applications/lesion-tracker.md)
|
||||
- [Standalone Viewer](example-applications/standalone-viewer.md)
|
||||
|
||||
----
|
||||
- Standalone Viewer Integration
|
||||
- [Usage](standalone-viewer/usage.md)
|
||||
|
||||
----
|
||||
- Lesion Tracker
|
||||
- [User Manual](lesion-tracker/user-manual.md)
|
||||
- [Installation on Windows](lesion-tracker/installation-on-windows.md)
|
||||
- [Manage Studies in Orthanc](lesion-tracker/manage-studies-in-orthanc.md)
|
||||
- [User Accounts](lesion-tracker/user-accounts.md)
|
||||
- [Study and Timepoint Management](lesion-tracker/study-and-timepoint-management.md)
|
||||
- [Using the Viewer](lesion-tracker/using-the-viewer.md)
|
||||
- [User Preferences](lesion-tracker/user-preferences.md)
|
||||
- [Server Management](lesion-tracker/server-management.md)
|
||||
- [Audit Trail](lesion-tracker/audit-trail.md)
|
||||
|
||||
----
|
||||
- FAQ
|
||||
- [General](faq/general.md)
|
||||
- [Technical](faq/technical.md)
|
||||
|
||||
----
|
||||
- [Contributing](contributing.md)
|
||||
@ -1 +0,0 @@
|
||||
docs.ohif.org
|
||||
@ -1,54 +0,0 @@
|
||||
{
|
||||
"title": "OHIF",
|
||||
"description": "Documentation for the OHIF framework",
|
||||
"gitbook": ">3.0.0",
|
||||
"plugins": [
|
||||
"edit-link",
|
||||
"theme-cornerstone",
|
||||
"-fontsettings",
|
||||
"github",
|
||||
"ga",
|
||||
"sitemap",
|
||||
"anchors",
|
||||
"versions"
|
||||
],
|
||||
"pluginsConfig": {
|
||||
"edit-link": {
|
||||
"base": "https://github.com/OHIF/Viewers/edit/master/docs",
|
||||
"label": "Edit This Page"
|
||||
},
|
||||
"github": {
|
||||
"url": "https://github.com/OHIF/Viewers"
|
||||
},
|
||||
"ga": {
|
||||
"token": "UA-110573590-2"
|
||||
},
|
||||
"sitemap": {
|
||||
"hostname": "https://docs.ohif.org"
|
||||
},
|
||||
"versions": {
|
||||
"gitbookConfigURL": "https://raw.githubusercontent.com/OHIF/Viewers/master/docs/book.json",
|
||||
"options": [
|
||||
{
|
||||
"value": "https://docs.ohif.org/history/v1/",
|
||||
"text": "Version 1.0.0 (Meteor)",
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"value": "https://docs.ohif.org/history/v2/",
|
||||
"text": "Version 2.0.0"
|
||||
},
|
||||
{
|
||||
"value": "https://docs.ohif.org/",
|
||||
"text": "Version 3.0.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"sharing": {
|
||||
"facebook": false,
|
||||
"twitter": false
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
# Example: Osirix
|
||||
|
||||
...
|
||||
@ -1,3 +0,0 @@
|
||||
# Getting Started
|
||||
|
||||
...
|
||||
@ -1,20 +0,0 @@
|
||||
# Troubleshooting
|
||||
|
||||
## Common Problems
|
||||
|
||||
Problem | Most Common Reasons
|
||||
--------|--------------------
|
||||
** Can't retrieve Study List over DICOMWeb** | 1. QIDO root URL is incorrect<br> 2. DICOM Web is not enabled on PACS
|
||||
** Can't retrieve Study List over DIMSE** | 1. PACS is not configured to allow connections from OHIF Meteor Server
|
||||
** Can't retrieve images** | 1. WADO Root URL is incorrect<br> 2. DICOM Web is not enabled on PACS<br> 3. HTTP Basic Authentication username and password are incorrect or not provided.
|
||||
|
||||
## Debugging Steps
|
||||
### Can't retrieve Study List over DICOMWeb
|
||||
|
||||
1. Check that you can query your PACS using an alternative DICOM Web client (e.g. cURL, or a Web Browser). If you cannot, then your PACS is configured incorrectly. Refer to the documentation of the image archive.
|
||||
2.
|
||||
|
||||
|
||||
### Can't retrieve Study List over DIMSE
|
||||
|
||||
### Can't retrieve images
|
||||
@ -1,10 +0,0 @@
|
||||
# Lesion Tracker - User Manual
|
||||
|
||||
1. [Installation on Windows](../installation-on-windows.md)
|
||||
2. [Manage Studies in Orthanc](../manage-studies-in-orthanc.md)
|
||||
3. [User Accounts](../user-accounts.md)
|
||||
4. [Study and Timepoint Management](../study-and-timepoint-management.md)
|
||||
5. [Lesion Tracking](../lesion-tracking.md)
|
||||
6. [User Preferences](../user-preferences.md)
|
||||
7. [Server Management](../server-management.md)
|
||||
8. [Audit Trail](../audit-trail.md)
|
||||
@ -1,44 +0,0 @@
|
||||
{
|
||||
"name": "ohif-viewer-v1-docs",
|
||||
"version": "1.0.0",
|
||||
"description": "Open Health Imaging Foundation Viewers Metarepo for documentation",
|
||||
"main": ".eslintrc.js",
|
||||
"directories": {
|
||||
"doc": "docs"
|
||||
},
|
||||
"scripts": {
|
||||
"docs": "gitbook install && gitbook serve"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/OHIF/Viewers.git"
|
||||
},
|
||||
"keywords": [
|
||||
"dicom",
|
||||
"cornerstone",
|
||||
"OHIF",
|
||||
"zero",
|
||||
"footprint",
|
||||
"medical",
|
||||
"imaging",
|
||||
"viewer"
|
||||
],
|
||||
"author": "Open Health Imaging Foundation",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/OHIF/Viewers/issues"
|
||||
},
|
||||
"homepage": "https://github.com/OHIF/Viewers#readme",
|
||||
"dependencies": {
|
||||
"gitbook-plugin-anchors": "^0.7.1",
|
||||
"gitbook-plugin-edit-link": "^2.0.2",
|
||||
"gitbook-plugin-ga": "^2.0.0",
|
||||
"gitbook-plugin-github": "^3.0.0",
|
||||
"gitbook-plugin-sitemap": "^1.2.0",
|
||||
"gitbook-plugin-theme-cornerstone": "^1.1.2",
|
||||
"gitbook-plugin-versions": "^2.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"gitbook-cli": "^2.3.2"
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
rm -rf _book
|
||||
gitbook install
|
||||
gitbook build
|
||||
cp assets/CNAME _book/CNAME
|
||||
cd _book
|
||||
git init
|
||||
git add -A
|
||||
git commit -m 'Update compiled GitBook (this commit is automatic)'
|
||||
git push -f git@github.com:OHIF/Viewers.git master:gh-pages
|
||||
@ -1,61 +0,0 @@
|
||||
# OHIF Viewers
|
||||
|
||||
- [Our Process](our-process.md)
|
||||
- Development
|
||||
- [Getting Started](development/getting-started.md)
|
||||
- [Contributing](development/contributing.md)
|
||||
- [Continuous Integration](development/continous-integration.md)
|
||||
- [Testing](development/testing.md)
|
||||
- [Configuring](configuring/index.md)
|
||||
- [Data Source](configuring/data-source.md)
|
||||
|
||||
---
|
||||
|
||||
- [Architecture](architecture/index.md)
|
||||
- [Viewer](viewer/index.md)
|
||||
- [Configuration](viewer/configuration.md)
|
||||
- [Themeing](viewer/themeing.md)
|
||||
- [Internationalization](viewer/internationalization.md)
|
||||
- [Extensions](extensions/index.md)
|
||||
- [Registering](extensions/index.md#registering-an-extension)
|
||||
- [Lifecycle Hooks](extensions/index.md#lifecycle-hooks)
|
||||
- [preRegistration](extensions/lifecycle/pre-registration.md)
|
||||
- [Modules](extensions/index.md#modules)
|
||||
- [Commands](extensions/modules/commands.md)
|
||||
- [Panel](extensions/modules/panel.md)
|
||||
- [SOP Class Handler](extensions/modules/sop-class-handler.md)
|
||||
- [Toolbar](extensions/modules/toolbar.md)
|
||||
- [Viewport](extensions/modules/viewport.md)
|
||||
- [Contexts](extensions/index.md#contexts)
|
||||
- [ExtensionManager](extensions/index.md#extensionmanager)
|
||||
- [OHIF Maintained](extensions/index.md#maintained-extensions)
|
||||
- [Services](services/index.md)
|
||||
- [Default](services/default/index.md)
|
||||
- [UI](services/ui/index.md)
|
||||
- [Dialog Service](services/ui/ui-dialog-service.md)
|
||||
- [Modal Service](services/ui/ui-modal-service.md)
|
||||
- [Notification Service](services/ui/ui-notification-service.md)
|
||||
|
||||
---
|
||||
|
||||
- [Deployment](deployment/index.md)
|
||||
- [Embedded](deployment/index.md#embedded-viewer)
|
||||
- [Stand-alone](deployment/index.md#stand-alone-viewer)
|
||||
- [Data](deployment/index.md#data)
|
||||
- Recipes
|
||||
- Script Include
|
||||
- [Embedding the Viewer](deployment/recipes/embedded-viewer.md)
|
||||
- Stand-Alone
|
||||
- [Build for Production](deployment/recipes/build-for-production.md)
|
||||
- [Static](deployment/recipes/static-assets.md)
|
||||
- [Nginx + Image Archive](deployment/recipes/nginx--image-archive.md)
|
||||
- [User Account Control](deployment/recipes/user-account-control.md)
|
||||
- [Google Cloud Healthcare](connecting-to-image-archives/google-cloud-healthcare.md)
|
||||
|
||||
---
|
||||
|
||||
- [FAQ](faq/index.md)
|
||||
- [Scope of Project](faq/scope-of-project.md)
|
||||
- [Browser Support](faq/browser-support.md)
|
||||
- [PWA vs Packaged](faq/pwa-vs-packaged.md)
|
||||
- [Help](help.md)
|
||||
@ -1,54 +0,0 @@
|
||||
{
|
||||
"title": "OHIF",
|
||||
"description": "Documentation for the OHIF framework",
|
||||
"gitbook": ">3.0.0",
|
||||
"plugins": [
|
||||
"edit-link",
|
||||
"theme-cornerstone",
|
||||
"-fontsettings",
|
||||
"github",
|
||||
"ga",
|
||||
"sitemap",
|
||||
"anchors",
|
||||
"versions"
|
||||
],
|
||||
"pluginsConfig": {
|
||||
"edit-link": {
|
||||
"base": "https://github.com/OHIF/Viewers/edit/master/docs",
|
||||
"label": "Edit This Page"
|
||||
},
|
||||
"github": {
|
||||
"url": "https://github.com/OHIF/Viewers"
|
||||
},
|
||||
"ga": {
|
||||
"token": "UA-110573590-2"
|
||||
},
|
||||
"sitemap": {
|
||||
"hostname": "https://docs.ohif.org"
|
||||
},
|
||||
"versions": {
|
||||
"gitbookConfigURL": "https://raw.githubusercontent.com/OHIF/Viewers/master/docs/book.json",
|
||||
"options": [
|
||||
{
|
||||
"value": "https://docs.ohif.org/history/v1/",
|
||||
"text": "Version 1.0.0 (Meteor)"
|
||||
},
|
||||
{
|
||||
"value": "https://docs.ohif.org/history/v2/",
|
||||
"text": "Version 2.0.0",
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"value": "https://docs.ohif.org/",
|
||||
"text": "Version 3.0.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"sharing": {
|
||||
"facebook": false,
|
||||
"twitter": false
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
<div style="text-align: center;">
|
||||
<img src="/assets/img/embedded-viewer-diagram.png" alt="Embedded Viewer Diagram" style="margin: 0 auto;" />
|
||||
<div><i>embedded viewer diagram</i></div>
|
||||
</div>
|
||||
@ -1,4 +0,0 @@
|
||||
<div style="text-align: center;">
|
||||
<img src="/assets/img/nginx-image-archive.png" alt="request flow example" style="margin: 0 auto;" />
|
||||
<div><i>simplified request flow diagram</i></div>
|
||||
</div>
|
||||
@ -1,4 +0,0 @@
|
||||
<div style="text-align: center;">
|
||||
<img src="/assets/img/user-access-control-request-flow.png" alt="request flow example" style="margin: 0 auto;" />
|
||||
<div><i>simplified request flow diagram</i></div>
|
||||
</div>
|
||||
@ -1,75 +0,0 @@
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Extension</th>
|
||||
<th>Description</th>
|
||||
<th>Modules</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- CORNERSTONE.js -->
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://www.npmjs.com/package/@ohif/extension-cornerstone">
|
||||
Cornerstone
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
A viewport powered by <code>cornerstone.js</code>. Adds support for 2D DICOM rendering and manipulation, as well as support for the tools features in <a href="https://tools.cornerstonejs.org/examples/"><code>cornerstone-tools</code></a>. Also adds "CINE Dialog" to the Toolbar.
|
||||
</td>
|
||||
<td>Viewport, Toolbar</td>
|
||||
</tr>
|
||||
<!-- VTK.js -->
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://www.npmjs.com/package/@ohif/extension-vtk">
|
||||
VTK.js
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
A viewport powered by <code>vtk.js</code>. Adds support for volume renderings and advanced features like MPR. Also adds "3D Rotate" to the Toolbar.
|
||||
</td>
|
||||
<td>Viewport, Toolbar</td>
|
||||
</tr>
|
||||
<!-- dicom-html -->
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://www.npmjs.com/package/@ohif/extension-dicom-html">DICOM HTML</a>
|
||||
</td>
|
||||
<td>
|
||||
Renders text and HTML content for <a href="https://github.com/OHIF/Viewers/blob/master/extensions/dicom-html/src/OHIFDicomHtmlSopClassHandler.js#L4-L12">specific SopClassUIDs</a>.
|
||||
</td>
|
||||
<td>Viewport, SopClassHandler</td>
|
||||
</tr>
|
||||
<!-- dicom-pdf -->
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://www.npmjs.com/package/@ohif/extension-dicom-pdf">DICOM PDF</a>
|
||||
</td>
|
||||
<td>
|
||||
Renders PDFs for a <a href="https://github.com/OHIF/Viewers/blob/master/extensions/dicom-pdf/src/OHIFDicomPDFSopClassHandler.js#L4-L6">specific SopClassUID</a>.
|
||||
</td>
|
||||
<td>Viewport, SopClassHandler</td>
|
||||
</tr>
|
||||
<!-- dicom-microscopy -->
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://www.npmjs.com/package/@ohif/extension-dicom-microscopy">DICOM Microscopy</a>
|
||||
</td>
|
||||
<td>
|
||||
Renders Microscopy images for a <a href="https://github.com/OHIF/Viewers/blob/master/extensions/dicom-microscopy/src/DicomMicroscopySopClassHandler.js#L5-L7">specific SopClassUID</a>.
|
||||
</td>
|
||||
<td>Viewport, SopClassHandler</td>
|
||||
</tr>
|
||||
<!-- dicom-segmentation -->
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://www.npmjs.com/package/@ohif/extension-dicom-segmentation">DICOM Segmentation</a>
|
||||
</td>
|
||||
<td>
|
||||
Renders segmentation images for a <a href="https://github.com/OHIF/Viewers/blob/master/extensions/dicom-segmentation/src/OHIFDicomSegSopClassHandler.js#L5-L7">specific SopClassUID</a>.
|
||||
</td>
|
||||
<td>Panel, Toolbar</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@ -1,44 +0,0 @@
|
||||
{
|
||||
"name": "ohif-viewer-latest-docs",
|
||||
"version": "2.0.0",
|
||||
"description": "Open Health Imaging Foundation Viewers Metarepo for documentation",
|
||||
"main": ".eslintrc.js",
|
||||
"directories": {
|
||||
"doc": "docs"
|
||||
},
|
||||
"scripts": {
|
||||
"docs": "gitbook install && gitbook serve"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/OHIF/Viewers.git"
|
||||
},
|
||||
"keywords": [
|
||||
"dicom",
|
||||
"cornerstone",
|
||||
"OHIF",
|
||||
"zero",
|
||||
"footprint",
|
||||
"medical",
|
||||
"imaging",
|
||||
"viewer"
|
||||
],
|
||||
"author": "Open Health Imaging Foundation",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/OHIF/Viewers/issues"
|
||||
},
|
||||
"homepage": "https://github.com/OHIF/Viewers#readme",
|
||||
"dependencies": {
|
||||
"gitbook-plugin-anchors": "^0.7.1",
|
||||
"gitbook-plugin-edit-link": "^2.0.2",
|
||||
"gitbook-plugin-ga": "^2.0.0",
|
||||
"gitbook-plugin-github": "^3.0.0",
|
||||
"gitbook-plugin-sitemap": "^1.2.0",
|
||||
"gitbook-plugin-theme-cornerstone": "^1.1.4",
|
||||
"gitbook-plugin-versions": "^2.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"gitbook-cli": "^2.3.2"
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
# Quick Start
|
||||
|
||||
This page details how to get an instance of the OHIF Viewer up and running as
|
||||
fast as possible. It shows how to grab a pre-built version of the application,
|
||||
point it at your data source (PACS), and plop it on a web server.
|
||||
|
||||
## Options
|
||||
|
||||
### 1. Pre-built PWA
|
||||
|
||||
...
|
||||
|
||||
### 2. Script-Tag
|
||||
|
||||
...
|
||||
|
||||
### 3. Docker
|
||||
|
||||
...
|
||||
|
||||
## Security Concerns
|
||||
|
||||
- Secure your data
|
||||
|
||||
## Common Issues
|
||||
|
||||
- Missing server rewrite rules
|
||||
- CORS issues when requesting data from PACS
|
||||
@ -1,65 +0,0 @@
|
||||
# Services (default)
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Example](#example)
|
||||
|
||||
## Overview
|
||||
|
||||
Services are a work in progress. As we are still in the progress of creating a
|
||||
non-ui maintained service, this usage may change.
|
||||
|
||||
<div style="text-align: center;">
|
||||
<a href="/assets/img/services.png">
|
||||
<img src="/assets/img/services.png" alt="UI Services Diagram" style="margin: 0 auto; max-width: 500px;" />
|
||||
</a>
|
||||
<div><i>Diagram showing relationship between React Context and UI Service</i></div>
|
||||
</div>
|
||||
|
||||
## Example
|
||||
|
||||
The simplest service return a new object that has a `name` property, and
|
||||
methods/properties that give the service its functionality. The "Factory
|
||||
Function" that creates the service is provided with the implementation (this is
|
||||
slightly different for UI Services).
|
||||
|
||||
```js
|
||||
const _speak = () => {
|
||||
console.warn('Speak is not implemented');
|
||||
};
|
||||
|
||||
/**
|
||||
* Factory function to create `HelloWorldService`
|
||||
*
|
||||
* @param {object} implementation
|
||||
* @param {function} implementation.speak - Speak's implementation
|
||||
* @returns HelloWorldService
|
||||
*/
|
||||
export default function createHelloWorldService({ speak }) {
|
||||
return {
|
||||
name: 'HelloWorldService',
|
||||
speak: speak || _speak,
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
A service, once created, can be registered with the `ServicesManager` to make it
|
||||
accessible to extensions. Similarly, the application code can access named
|
||||
services from the `ServicesManager`.
|
||||
|
||||
```js
|
||||
// In the application
|
||||
const speak = () => {
|
||||
window.alert('HELLO WORLD');
|
||||
};
|
||||
const HelloWorldService = createHelloWorldService({ speak });
|
||||
const servicesManager = new ServicesManager();
|
||||
|
||||
servicesManager.registerService(HelloWorldService);
|
||||
|
||||
// In an extension
|
||||
const { HelloWorldService } = servicesManager.services;
|
||||
|
||||
if (HelloWorldService) {
|
||||
HelloWorldService.speak();
|
||||
}
|
||||
```
|
||||
@ -1,15 +0,0 @@
|
||||
# Service: Measurements
|
||||
|
||||
...
|
||||
|
||||
## Usage
|
||||
|
||||
## How to define a Measurement tool
|
||||
|
||||
## How to validate Measurements
|
||||
|
||||
## Data exchange concepts
|
||||
|
||||
## Longitudinal Measurements
|
||||
|
||||
## Timepoints
|
||||
@ -1,3 +0,0 @@
|
||||
# Hotkeys
|
||||
|
||||
...
|
||||
@ -1,9 +0,0 @@
|
||||
# Viewer
|
||||
|
||||
The OHIF Viewing Platform strives to be highly configurable and extensible. This
|
||||
makes it easier for our community members to keep their "secret sauce" private,
|
||||
and incentivises contributions back to the platform. The `@ohif/viewer` project
|
||||
of the platform is the lynchpin that combines everything to create our
|
||||
application.
|
||||
|
||||
- When configuration and themeing aren't enough
|
||||
3413
docs/v2/yarn.lock
@ -1,13 +0,0 @@
|
||||
:: REQUIRES GLOBAL INSTALL OF GITBOOK and GITBOOK-CLI
|
||||
::
|
||||
:: Call this script from the command line while in the directory of the book
|
||||
:: you want to actively edit + preview
|
||||
::
|
||||
:: `gitbook serve` can break with permission issues on Windows for misc.
|
||||
:: machines. This script is a workaround. When `gitbook serve` fails, it silently
|
||||
:: restarts it.
|
||||
:: https://github.com/GitbookIO/gitbook/issues/1379#issuecomment-288048275
|
||||
@Echo off
|
||||
:Start
|
||||
call gitbook serve
|
||||
goto Start
|
||||
@ -39,8 +39,8 @@
|
||||
"dicom-parser": "^1.8.3",
|
||||
"hammerjs": "^2.0.8",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^16.11.0",
|
||||
"react-dom": "^16.11.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-resize-detector": "^3.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@ -35,7 +35,9 @@
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-i18next": "^10.11.0",
|
||||
"webpack": "^4.0.0",
|
||||
"react-router": "next",
|
||||
"react-router-dom": "next",
|
||||
"webpack": "^5.43.0",
|
||||
"webpack-merge": "^5.7.3"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@ -12,7 +12,7 @@ import {
|
||||
|
||||
import i18n from '@ohif/i18n';
|
||||
import { hotkeys } from '@ohif/core';
|
||||
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
const { availableLanguages, defaultLanguage, currentLanguage } = i18n;
|
||||
|
||||
@ -91,6 +91,11 @@ function ViewerLayout({
|
||||
ViewportGridComp,
|
||||
}) {
|
||||
const [appConfig] = useAppConfig();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const onClickReturnButton = () => {
|
||||
navigate('/')
|
||||
};
|
||||
|
||||
const { t } = useTranslation();
|
||||
const { show, hide } = useModal();
|
||||
@ -176,7 +181,7 @@ function ViewerLayout({
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Header menuOptions={menuOptions} WhiteLabeling={appConfig.whiteLabeling} >
|
||||
<Header menuOptions={menuOptions} onClickReturnButton={onClickReturnButton} WhiteLabeling={appConfig.whiteLabeling} >
|
||||
<ErrorBoundary context="Primary Toolbar">
|
||||
<div className="relative flex justify-center">
|
||||
<Toolbar servicesManager={servicesManager} />
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
"dicom-parser": "^1.8.3",
|
||||
"hammerjs": "^2.0.8",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^16.11.0",
|
||||
"react": "^17.0.2",
|
||||
"react-cornerstone-viewport": "4.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
"react": "^16.13.1",
|
||||
"react-cornerstone-viewport": "^4.0.5",
|
||||
"react-dom": "^16.13.1",
|
||||
"webpack": "^4.0.0",
|
||||
"webpack": "^5.43.0",
|
||||
"webpack-merge": "^5.7.3"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
"@babel/runtime": "7.7.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"webpack": "^5.21.2",
|
||||
"webpack": "^5.43.0",
|
||||
"webpack-merge": "^5.7.3"
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +18,6 @@ const dicomsr = {
|
||||
viewport: 'org.ohif.dicom-sr.viewportModule.dicom-sr',
|
||||
};
|
||||
|
||||
|
||||
export default function mode({ modeConfiguration }) {
|
||||
return {
|
||||
// TODO: We're using this as a route segment
|
||||
|
||||
36
package.json
@ -6,6 +6,9 @@
|
||||
"platform/*",
|
||||
"extensions/*",
|
||||
"modes/*"
|
||||
],
|
||||
"nohoist": [
|
||||
"**/html-minifier-terser"
|
||||
]
|
||||
},
|
||||
"engines": {
|
||||
@ -30,7 +33,6 @@
|
||||
"test:unit": "jest --collectCoverage",
|
||||
"test:unit:ci": "lerna run test:unit:ci --parallel --stream",
|
||||
"test:e2e": "lerna run test:e2e --stream",
|
||||
"test:e2e:script-tag": "lerna run test:e2e:script-tag --stream",
|
||||
"test:e2e:ci": "lerna run test:e2e:ci --stream",
|
||||
"test:e2e:dist": "lerna run test:e2e:dist --stream",
|
||||
"test:e2e:serve": "lerna run test:e2e:serve --stream",
|
||||
@ -38,6 +40,7 @@
|
||||
"docs:preview": "lerna run docs:preview --stream",
|
||||
"docs:publish": "chmod +x ./build-and-publish-docs.sh && ./build-and-publish-docs.sh",
|
||||
"release": "yarn run lerna:version && yarn run lerna:publish",
|
||||
"lerna:clean": "lerna clean",
|
||||
"lerna:cache": "./netlify-lerna-cache.sh",
|
||||
"lerna:restore": "./netlify-lerna-restore.sh",
|
||||
"lerna:version": "npx lerna version prerelease --force-publish",
|
||||
@ -48,13 +51,15 @@
|
||||
"@babel/runtime": "7.7.6",
|
||||
"core-js": "^3.2.1",
|
||||
"cornerstone-core": "2.3.0",
|
||||
"react": "16.11.0",
|
||||
"react-dom": "16.11.0",
|
||||
"shader-loader": "^1.3.1",
|
||||
"webpack": "^4.35.2",
|
||||
"worker-loader": "^2.0.0",
|
||||
"webpack": "^5.43.0",
|
||||
"worker-loader": "^3.0.8",
|
||||
"wslink": "^0.1.8"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.5.0",
|
||||
"@babel/plugin-proposal-class-properties": "^7.5.0",
|
||||
@ -71,7 +76,7 @@
|
||||
"babel-plugin-inline-react-svg": "1.1.0",
|
||||
"babel-plugin-module-resolver": "^3.2.0",
|
||||
"clean-webpack-plugin": "^3.0.0",
|
||||
"copy-webpack-plugin": "^5.0.3",
|
||||
"copy-webpack-plugin": "^9.0.1",
|
||||
"cross-env": "^5.2.0",
|
||||
"css-loader": "^3.2.0",
|
||||
"dotenv": "^8.1.0",
|
||||
@ -86,8 +91,8 @@
|
||||
"eslint-plugin-promise": "^4.2.1",
|
||||
"eslint-plugin-react": "7.x",
|
||||
"eslint-plugin-react-hooks": "4.2.0",
|
||||
"extract-css-chunks-webpack-plugin": "^4.5.4",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"extract-css-chunks-webpack-plugin": "^4.9.0",
|
||||
"html-webpack-plugin": "^5.3.2",
|
||||
"husky": "^3.0.0",
|
||||
"jest": "^24.8.0",
|
||||
"jest-canvas-mock": "^2.1.0",
|
||||
@ -95,22 +100,21 @@
|
||||
"lerna": "^3.15.0",
|
||||
"lint-staged": "^9.0.2",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.3",
|
||||
"postcss": "^8.2.15",
|
||||
"postcss-import": "^12.0.1",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"postcss-loader": "^4.0.3",
|
||||
"postcss-preset-env": "^6.6.0",
|
||||
"prettier": "^1.18.2",
|
||||
"react-hot-loader": "^4.12.21",
|
||||
"react-hot-loader": "^4.13.0",
|
||||
"serve": "^11.1.0",
|
||||
"start-server-and-test": "^1.10.0",
|
||||
"style-loader": "^1.0.0",
|
||||
"terser-webpack-plugin": "^2.1.0",
|
||||
"unused-files-webpack-plugin": "^3.4.0",
|
||||
"terser-webpack-plugin": "^5.1.4",
|
||||
"unused-webpack-plugin": "2.4.0",
|
||||
"webpack-cli": "^3.3.5",
|
||||
"webpack-dev-server": "^3.7.2",
|
||||
"webpack-cli": "^4.7.2",
|
||||
"webpack-hot-middleware": "^2.25.0",
|
||||
"webpack-merge": "^4.2.1",
|
||||
"workbox-webpack-plugin": "^5.0.0-beta.1"
|
||||
"webpack-merge": "^5.7.3",
|
||||
"workbox-webpack-plugin": "^6.1.5"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
const merge = require('webpack-merge');
|
||||
const path = require('path');
|
||||
const webpackCommon = require('./../../../.webpack/webpack.commonjs.js');
|
||||
const webpackCommon = require('./../../../.webpack/webpack.base.js');
|
||||
const pkg = require('./../package.json');
|
||||
|
||||
const ROOT_DIR = path.join(__dirname, './..');
|
||||
@ -33,5 +33,15 @@ module.exports = (env, argv) => {
|
||||
libraryTarget: 'umd',
|
||||
filename: pkg.main,
|
||||
},
|
||||
externals: [
|
||||
{
|
||||
'cornerstone-math': {
|
||||
commonjs: 'cornerstone-math',
|
||||
commonjs2: 'cornerstone-math',
|
||||
amd: 'cornerstone-math',
|
||||
root: 'cornerstoneMath',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
};
|
||||
|
||||
@ -32,8 +32,10 @@
|
||||
"peerDependencies": {
|
||||
"cornerstone-core": "^2.3.0",
|
||||
"cornerstone-tools": "5.1.2",
|
||||
"cornerstone-math": "0.1.9",
|
||||
"cornerstone-wado-image-loader": "^3.1.2",
|
||||
"dicom-parser": "^1.8.3"
|
||||
"dicom-parser": "^1.8.3",
|
||||
"@ohif/ui": "^1.8.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.7.6",
|
||||
@ -43,10 +45,8 @@
|
||||
"lodash.merge": "^4.6.1",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"moment": "^2.24.0",
|
||||
"mousetrap": "^1.6.3",
|
||||
"query-string": "^6.14.0",
|
||||
"object-hash": "2.1.1",
|
||||
"cornerstone-math": "0.1.9",
|
||||
"validate.js": "^0.12.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import objectHash from 'object-hash';
|
||||
import hotkeys from './../utils/hotkeys';
|
||||
import log from './../log.js';
|
||||
import { hotkeys } from '../utils';
|
||||
|
||||
/**
|
||||
*
|
||||
@ -26,6 +26,8 @@ export class HotkeysManager {
|
||||
|
||||
this._servicesManager = servicesManager;
|
||||
this._commandsManager = commandsManager;
|
||||
|
||||
hotkeys.initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -163,25 +165,40 @@ export class HotkeysManager {
|
||||
* @param {String} extension
|
||||
* @returns {undefined}
|
||||
*/
|
||||
registerHotkeys({ commandName, commandOptions = {}, keys, label, isEditable } = {}, extension) {
|
||||
registerHotkeys(
|
||||
{ commandName, commandOptions = {}, keys, label, isEditable } = {},
|
||||
extension
|
||||
) {
|
||||
if (!commandName) {
|
||||
throw new Error(`No command was defined for hotkey "${keys}"`);
|
||||
}
|
||||
|
||||
const commandHash = objectHash({ commandName, commandOptions });
|
||||
const options = Object.keys(commandOptions).length ? JSON.stringify(commandOptions) : 'no';
|
||||
const options = Object.keys(commandOptions).length
|
||||
? JSON.stringify(commandOptions)
|
||||
: 'no';
|
||||
const previouslyRegisteredDefinition = this.hotkeyDefinitions[commandHash];
|
||||
|
||||
if (previouslyRegisteredDefinition) {
|
||||
const previouslyRegisteredKeys = previouslyRegisteredDefinition.keys;
|
||||
this._unbindHotkeys(commandName, previouslyRegisteredKeys);
|
||||
log.info(`[hotkeys] Unbinding ${commandName} with ${options} options from ${previouslyRegisteredKeys}`);
|
||||
log.info(
|
||||
`[hotkeys] Unbinding ${commandName} with ${options} options from ${previouslyRegisteredKeys}`
|
||||
);
|
||||
}
|
||||
|
||||
// Set definition & bind
|
||||
this.hotkeyDefinitions[commandHash] = { commandName, commandOptions, keys, label, isEditable };
|
||||
this.hotkeyDefinitions[commandHash] = {
|
||||
commandName,
|
||||
commandOptions,
|
||||
keys,
|
||||
label,
|
||||
isEditable,
|
||||
};
|
||||
this._bindHotkeys(commandName, commandOptions, keys);
|
||||
log.info(`[hotkeys] Binding ${commandName} with ${options} options to ${keys}`);
|
||||
log.info(
|
||||
`[hotkeys] Binding ${commandName} with ${options} options to ${keys}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -2,7 +2,7 @@ import CommandsManager from './CommandsManager.js';
|
||||
import HotkeysManager from './HotkeysManager.js';
|
||||
import hotkeys from './../utils/hotkeys';
|
||||
import log from './../log.js';
|
||||
import objectHash from "object-hash";
|
||||
import objectHash from 'object-hash';
|
||||
|
||||
jest.mock('./CommandsManager.js');
|
||||
jest.mock('./../utils/hotkeys');
|
||||
@ -10,6 +10,9 @@ jest.mock('./../log.js');
|
||||
|
||||
describe('HotkeysManager', () => {
|
||||
let hotkeysManager, commandsManager;
|
||||
beforeAll(() => {
|
||||
hotkeys.initialize();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
commandsManager = new CommandsManager();
|
||||
@ -19,7 +22,6 @@ describe('HotkeysManager', () => {
|
||||
log.warn.mockClear();
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('has expected properties', () => {
|
||||
const allProperties = Object.keys(hotkeysManager);
|
||||
const expectedProprties = [
|
||||
@ -122,11 +124,16 @@ describe('HotkeysManager', () => {
|
||||
const definition = { commandName: undefined, keys: '+' };
|
||||
|
||||
expect(() => {
|
||||
hotkeysManager.registerHotkeys(definition)
|
||||
hotkeysManager.registerHotkeys(definition);
|
||||
}).toThrow();
|
||||
});
|
||||
it('updates hotkeyDefinitions property with registered keys', () => {
|
||||
const definition = { commandName: 'dance', commandOptions: {}, label: 'hello', keys: '+', };
|
||||
const definition = {
|
||||
commandName: 'dance',
|
||||
commandOptions: {},
|
||||
label: 'hello',
|
||||
keys: '+',
|
||||
};
|
||||
|
||||
hotkeysManager.registerHotkeys(definition);
|
||||
|
||||
@ -136,13 +143,15 @@ describe('HotkeysManager', () => {
|
||||
|
||||
const commandHash = objectHash({
|
||||
commandName: definition.commandName,
|
||||
commandOptions: definition.commandOptions
|
||||
commandOptions: definition.commandOptions,
|
||||
});
|
||||
const hotkeyDefinitionForRegisteredCommand =
|
||||
hotkeysManager.hotkeyDefinitions[commandHash];
|
||||
|
||||
expect(numOfHotkeyDefinitions).toBe(1);
|
||||
expect(Object.keys(hotkeysManager.hotkeyDefinitions)[0]).toEqual(commandHash);
|
||||
expect(Object.keys(hotkeysManager.hotkeyDefinitions)[0]).toEqual(
|
||||
commandHash
|
||||
);
|
||||
expect(hotkeyDefinitionForRegisteredCommand).toEqual(definition);
|
||||
});
|
||||
it('calls hotkeys.bind for the group of keys', () => {
|
||||
|
||||
@ -16,8 +16,8 @@ const serviceImplementation = {
|
||||
_getState: () => console.warn('getState() NOT IMPLEMENTED'),
|
||||
_setUser: () => console.warn('_setUser() NOT IMPLEMENTED'),
|
||||
_getUser: () => console.warn('_setUser() NOT IMPLEMENTED'),
|
||||
_getAuthorizationHeader: () =>
|
||||
console.warn('_getAuthorizationHeader() NOT IMPLEMENTED'),
|
||||
_getAuthorizationHeader: () => {}, // TODO: have enabled/disabled state?
|
||||
//console.warn('_getAuthorizationHeader() NOT IMPLEMENTED'),
|
||||
_handleUnauthenticated: () =>
|
||||
console.warn('_handleUnauthenticated() NOT IMPLEMENTED'),
|
||||
_reset: () => console.warn('reset() NOT IMPLEMENTED'),
|
||||
|
||||
@ -2,7 +2,30 @@ import Mousetrap from 'mousetrap';
|
||||
import pausePlugin from './pausePlugin';
|
||||
import recordPlugin from './recordPlugin';
|
||||
|
||||
recordPlugin(Mousetrap);
|
||||
pausePlugin(Mousetrap);
|
||||
Mousetrap.initialize = () => {
|
||||
if (!Mousetrap._initialized) {
|
||||
recordPlugin(Mousetrap);
|
||||
pausePlugin(Mousetrap);
|
||||
|
||||
Mousetrap._initialized = true;
|
||||
}
|
||||
};
|
||||
|
||||
// These are only here so that Jest mocks them properly before .initialize() is called
|
||||
Mousetrap.handleKey = () =>
|
||||
console.debug('Mousetrap recordPlugin not yet initialized');
|
||||
Mousetrap.startRecording = () =>
|
||||
console.debug('Mousetrap recordPlugin not yet initialized');
|
||||
Mousetrap.stopRecording = () =>
|
||||
console.debug('Mousetrap recordPlugin not yet initialized');
|
||||
Mousetrap.record = () =>
|
||||
console.debug('Mousetrap recordPlugin not yet initialized');
|
||||
|
||||
Mousetrap.stopCallback = () =>
|
||||
console.debug('Mousetrap pausePlugin not yet initialized');
|
||||
Mousetrap.pause = () =>
|
||||
console.debug('Mousetrap pausePlugin not yet initialized');
|
||||
Mousetrap.unpause = () =>
|
||||
console.debug('Mousetrap pausePlugin not yet initialized');
|
||||
|
||||
export default Mousetrap;
|
||||
|
||||
@ -46,7 +46,7 @@ const utils = {
|
||||
resolveObjectPath,
|
||||
hierarchicalListUtils,
|
||||
progressTrackingUtils,
|
||||
isLowPriorityModality
|
||||
isLowPriorityModality,
|
||||
};
|
||||
|
||||
export {
|
||||
@ -69,7 +69,7 @@ export {
|
||||
resolveObjectPath,
|
||||
hierarchicalListUtils,
|
||||
progressTrackingUtils,
|
||||
isLowPriorityModality
|
||||
isLowPriorityModality,
|
||||
};
|
||||
|
||||
export default utils;
|
||||
|
||||
20
platform/docs/.gitignore
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
# Dependencies
|
||||
/node_modules
|
||||
|
||||
# Production
|
||||
/build
|
||||
|
||||
# Generated files
|
||||
.docusaurus
|
||||
.cache-loader
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
33
platform/docs/README.md
Normal file
@ -0,0 +1,33 @@
|
||||
# Website
|
||||
|
||||
This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.
|
||||
|
||||
## Installation
|
||||
|
||||
```console
|
||||
yarn install
|
||||
```
|
||||
|
||||
## Local Development
|
||||
|
||||
```console
|
||||
yarn start
|
||||
```
|
||||
|
||||
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
|
||||
|
||||
## Build
|
||||
|
||||
```console
|
||||
yarn build
|
||||
```
|
||||
|
||||
This command generates static content into the `build` directory and can be served using any static contents hosting service.
|
||||
|
||||
## Deployment
|
||||
|
||||
```console
|
||||
GIT_USER=<Your GitHub username> USE_SSH=true yarn deploy
|
||||
```
|
||||
|
||||
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
|
||||
3
platform/docs/babel.config.js
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
|
||||
};
|
||||
186
platform/docs/docs/README.md
Normal file
@ -0,0 +1,186 @@
|
||||
---
|
||||
id: Introduction
|
||||
slug: /
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
<div className="text--center">
|
||||
<a style={{marginRight:'10px'}} href="http://viewer.ohif.org/">Preview The OHIF Viewer</a>
|
||||
<a href="https://www.netlify.com"/>
|
||||
<img style={{width:'70px'}} src="https://www.netlify.com/img/global/badges/netlify-color-bg.svg" />
|
||||
</div>
|
||||
|
||||
> ATTENTION! You are looking at the docs for the `OHIF-v3` Viewer (third time is
|
||||
> always a charm). If you're looking for the our `OHIF-v2` (React stable
|
||||
> version) or OHIF-v1 (deprecated `Meteor` version) select it's version from the
|
||||
> dropdown box in the top left corner of this page.
|
||||
|
||||
The [Open Health Imaging Foundation][ohif-org] (OHIF) Viewer is an open source,
|
||||
web-based, medical imaging viewer. It can be configured to connect to Image
|
||||
Archives that support [DicomWeb][dicom-web], and offers support for mapping to
|
||||
proprietary API formats. OHIF maintained extensions add support for viewing,
|
||||
annotating, and reporting on DICOM images in 2D (slices) and 3D (volumes).
|
||||
|
||||

|
||||
|
||||
<!-- <center><i>The <strong>OHIF Viewer v3</strong>: A general purpose DICOM Viewer (<a href="http://viewer.ohif.org/">Live Demo</a>)</center> -->
|
||||
|
||||
|
||||
|
||||
## What's new in `OHIF-v3`
|
||||
|
||||
`OHIF-v3` is our second try for a React-based viewer, and is the third version
|
||||
of our medical image web viewers from the start. The summary of changes include:
|
||||
|
||||
- Addition of workflow modes
|
||||
- Often, medical imaging use cases involves lots of specific workflows that
|
||||
re-use functionalities. We have added the capability of workflow modes, that
|
||||
enable people to customize user interface and configure application for
|
||||
specific workflow.
|
||||
- The idea is to re-use the functionalities that extensions provide and create
|
||||
a workflow. Brain segmentation workflow is different from prostate
|
||||
segmentation in UI for sure; however, they share the segmentation tools that
|
||||
can be re-used.
|
||||
- Our vision is that technical people focus of developing extensions which
|
||||
provides core functionalities, and experts to build modes by picking the
|
||||
appropriate functionalities from each extension.
|
||||
|
||||
* Redux store has been removed from the viewer, and a cleaner, more powerful
|
||||
* Tailwind CSS
|
||||
* End-to-end test suite
|
||||
|
||||
Below, you can find the gap analysis between the `OHIF-v2` and `OHIF-v3`:
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="left" width="50%">OHIF-v2 functionalities</th>
|
||||
<th align="center">OHIF-v3</th>
|
||||
<th align="center">Comment</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left">Rendering of 2D images via Cornerstone</td>
|
||||
<td align="center">✅</td>
|
||||
<td align="center"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">Study List</td>
|
||||
<td align="center">✅</td>
|
||||
<td align="center"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">Series Browser</td>
|
||||
<td align="center">✅</td>
|
||||
<td align="center"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">DICOM JSON</td>
|
||||
<td align="center">✅</td>
|
||||
<td align="center"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">2D Tools via CornerstoneTools</td>
|
||||
<td align="center">✅</td>
|
||||
<td align="center"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">OpenID Connect standard authentication flow for connecting to identity providers</td>
|
||||
<td align="center">✅</td>
|
||||
<td align="center"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">Internationalization</td>
|
||||
<td align="center">✅</td>
|
||||
<td align="center"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">Drag/drop DICOM data into the viewer (see https://viewer.ohif.org/local)</td>
|
||||
<td align="center">✅</td>
|
||||
<td align="center"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">White-labelling: Easily replace the OHIF Logo with your logo</td>
|
||||
<td align="center">✅</td>
|
||||
<td align="center"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">DICOM Whole-slide imaging viewport</td>
|
||||
<td align="center">🔜</td>
|
||||
<td align="center">In Progress</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">IHE Invoke Image Display - Standard-compliant launching of the viewer (e.g. from PACS or RIS)</td>
|
||||
<td align="center">🔜</td>
|
||||
<td align="center">Not Started</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">DICOM PDF support</td>
|
||||
<td align="center">🔜</td>
|
||||
<td align="center">Not Started</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">Displaying non-renderable DICOM as HTML</td>
|
||||
<td align="center">🔜</td>
|
||||
<td align="center">Not Started</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">Segmentation support</td>
|
||||
<td align="center">🔜</td>
|
||||
<td align="center">Not Started</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">RT STRUCT support</td>
|
||||
<td align="center">🔜</td>
|
||||
<td align="center">Not Started</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">DICOM upload to PACS</td>
|
||||
<td align="center">🔜</td>
|
||||
<td align="center">Not Started</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">Google Cloud adapter</td>
|
||||
<td align="center">🔜</td>
|
||||
<td align="center">Not Started</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">VTK Extension + MIP / MPR layout</td>
|
||||
<td align="center">❌</td>
|
||||
<td align="center">Other plans that involves amazing news soon!</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">UMD Build (Embedded Viewer). </td>
|
||||
<td align="center">❌</td>
|
||||
<td align="center">The problem is that this breaks a bunch of extensions that rely on third party scripts (e.g. VTK) which have their own web worker loaders.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## Where to next?
|
||||
|
||||
The Open Health Imaging Foundation intends to provide a simple general purpose
|
||||
DICOM Viewer which can be easily extended for specific uses. If you find
|
||||
yourself unable to extend the viewer for your purposes, please reach out via our
|
||||
[GitHub issues][gh-issues]. We are actively seeking feedback on ways to improve
|
||||
our integration and extension points.
|
||||
|
||||
Check out these helpful links:
|
||||
|
||||
- Ready to dive into some code? Check out our
|
||||
[Getting Started Guide](./development/getting-started.md).
|
||||
- We're an active, vibrant community.
|
||||
[Learn how you can be more involved.](./development/contributing.md)
|
||||
- Feeling lost? Read our [help page](./help.md).
|
||||
|
||||
<!--
|
||||
Links
|
||||
-->
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
[ohif-org]: https://www.ohif.org
|
||||
[ohif-demo]: http://viewer.ohif.org/
|
||||
[dicom-web]: https://en.wikipedia.org/wiki/DICOMweb
|
||||
[gh-issues]: https://github.com/OHIF/Viewers/issues
|
||||
<!-- prettier-ignore-end -->
|
||||
|
Before Width: | Height: | Size: 818 B After Width: | Height: | Size: 818 B |