Config files
After following the steps outlined in Getting Started, you'll notice that the OHIF Viewer has data for several studies and their images. You didn't add this data, so where is it coming from?
By default, the viewer is configured to connect to a Amazon S3 bucket that is hosting
a Static WADO server (see Static WADO DICOMWeb).
By default we use default.js
for the configuration file. You can change this by setting the APP_CONFIG
environment variable
and select other options such as config/local_orthanc.js
or config/google.js
.
Configuration Files​
The configuration for our viewer is in the <root>platform/app/public/config
directory. Our build process knows which configuration file to use based on the
APP_CONFIG
environment variable. By default, its value is
config/default.js
. The majority of the viewer's features,
and registered extension's features, are configured using this file.
The simplest way is to update the existing default config:
window.config = {
routerBasename: '/',
extensions: [],
modes: [],
showStudyList: true,
dataSources: [
{
namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',
sourceName: 'dicomweb',
configuration: {
friendlyName: 'dcmjs DICOMWeb Server',
name: 'DCM4CHEE',
wadoUriRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/wado',
qidoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
wadoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
qidoSupportsIncludeField: true,
supportsReject: true,
imageRendering: 'wadors',
thumbnailRendering: 'wadors',
enableStudyLazyLoad: true,
supportsFuzzyMatching: true,
supportsWildcard: true,
omitQuotationForMultipartRequest: true,
},
},
],
defaultDataSourceName: 'dicomweb',
};
As you can see a new change in
OHIF-v3
is the addition ofdataSources
. You can build your own datasource and map it to the internal data structure of OHIF’s > metadata and enjoy using other peoples developed mode on your own data!You can read more about data sources at Data Source section in Modes
The configuration can also be written as a JS Function in case you need to inject dependencies like external services:
window.config = ({ servicesManager } = {}) => {
const { UIDialogService } = servicesManager.services;
return {
cornerstoneExtensionConfig: {
tools: {
ArrowAnnotate: {
configuration: {
getTextCallback: (callback, eventDetails) => UIDialogService.create({...
}
}
},
},
routerBasename: '/',
dataSources: [
{
namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',
sourceName: 'dicomweb',
configuration: {
friendlyName: 'dcmjs DICOMWeb Server',
name: 'DCM4CHEE',
wadoUriRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/wado',
qidoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
wadoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
qidoSupportsIncludeField: true,
supportsReject: true,
imageRendering: 'wadors',
thumbnailRendering: 'wadors',
enableStudyLazyLoad: true,
supportsFuzzyMatching: true,
supportsWildcard: true,
omitQuotationForMultipartRequest: true,
},
},
],
defaultDataSourceName: 'dicomweb',
};
};
Configuration Options​
Here are a list of some options available:
disableEditing
: If true, it disables editing in OHIF, hiding edit buttons in segmentation panel and locking already stored measurements.maxNumberOfWebWorkers
: The maximum number of web workers to use for decoding. Defaults to minimum ofnavigator.hardwareConcurrency
and what is specified bymaxNumberOfWebWorkers
. Some windows machines require smaller values.acceptHeader
: accept header to request specific dicom transfer syntax ex : [ 'multipart/related; type=image/jls; q=1', 'multipart/related; type=application/octet-stream; q=0.1' ]requestTransferSyntaxUID
: Request a specific Transfer syntax from dicom web server ex: 1.2.840.10008.1.2.4.80 (applied only if acceptHeader is not set)omitQuotationForMultipartRequest
: Some servers (e.g., .NET) require themultipart/related
request to be sent without quotation marks. Defaults tofalse
. If your server doesn't require this, then setting this flag totrue
might improve performance (by removing the need for preflight requests). Also note that if auth headers are used, a preflight request is required.maxNumRequests
: The maximum number of requests to allow in parallel. It is an object with keys ofinteraction
,thumbnail
, andprefetch
. You can specify a specific number for each type.modesConfiguration
: Allows overriding modes configuration.- Example config:
Note: Although the mode configuration is passed to the mode factory function, it is up to the particular mode itself if its going to use it to allow overwriting its original configuration e.g.modesConfiguration: {
'@ohif/mode-longitudinal': {
displayName: 'Custom Name',
routeName: 'customRouteName',
routes: [
{
path: 'customPath',
layoutTemplate: () => {
/** Custom Layout */
return {
id: ohif.layout,
props: {
leftPanels: [tracked.thumbnailList],
rightPanels: [dicomSeg.panel, tracked.measurements],
rightPanelDefaultClosed: true,
viewports: [
{
namespace: tracked.viewport,
displaySetsToDisplay: [ohif.sopClassHandler],
},
],
},
};
},
},
],
}
},function modeFactory({ modeConfiguration }) {
return {
id,
routeName: 'viewer',
displayName: 'Basic Viewer',
...
onModeEnter: ({ servicesManager, extensionManager, commandsManager }) => {
...
},
/**
* This mode allows its configuration to be overwritten by
* destructuring the modeConfiguration value from the mode fatory function
* at the end of the mode configuration definition.
*/
...modeConfiguration,
};
}showLoadingIndicator
: (default to true), if set to false, the loading indicator will not be shown when navigating between studies.useNorm16Texture
: (default to false), if set to true, it will use 16 bit data type for the image data wherever possible which has significant impact on reducing the memory usage. However, the 16Bit textures require EXT_texture_norm16 extension in webGL 2.0 (you can check if you have it here https://webglreport.com/?v=2). In addition to the extension, there are reported problems for Intel Macs that might cause the viewer to crash. In summary, it is great a configuration if you have support for it.useSharedArrayBuffer
(default to 'TRUE', options: 'AUTO', 'FALSE', 'TRUE', note that these are strings), for volume loading we use sharedArrayBuffer to be able to load the volume progressively as the data arrives (each webworker has the shared buffer and can write to it). However, there might be certain environments that do not support sharedArrayBuffer. In that case, you can set this flag to false and the viewer will use the regular arrayBuffer which might be slower for large volume loading.supportsWildcard
: (default to false), if set to true, the datasource will support wildcard matching for patient name and patient id.allowMultiSelectExport
: (default to false), if set to true, the user will be able to select the datasource to export the report to.autoPlayCine
: (default to false), if set to true, data sets with the DICOM frame time tag (i.e. (0018,1063)) will auto play when displayeddangerouslyUseDynamicConfig
: Dynamic config allows user to passconfigUrl
query string. This allows to load config without recompiling application. If theconfigUrl
query string is passed, the worklist and modes will load from the referenced json rather than the default .env config. If there is noconfigUrl
path provided, the default behaviour is used and there should not be any deviation from current user experience.
Points to consider while usingdangerouslyUseDynamicConfig
:- User have to enable this feature by setting
dangerouslyUseDynamicConfig.enabled:true
. By default it isfalse
. - Regex helps to avoid easy exploit. Default is
/.*/
. Setup your own regex to choose a specific source of configuration only. - System administrators can return
cross-origin: same-origin
with OHIF files to disallow any loading from other origin. It will block read access to resources loaded from a different origin to avoid potential attack vector. - Example config:
```js
dangerouslyUseDynamicConfig: {
enabled: false,
regex: /.*/
}
```Example 1, to allow numbers and letters in an absolute or sub-path only.
regex: /(0-9A-Za-z.]+)(\/[0-9A-Za-z.]+)*/
Example 2, to restricts to either hosptial.com or othersite.com.
regex: /(https:\/\/hospital.com(\/[0-9A-Za-z.]+)*)|(https:\/\/othersite.com(\/[0-9A-Za-z.]+)*)/
Example usage:
http://localhost:3000/?configUrl=http://localhost:3000/config/example.json
- User have to enable this feature by setting
onConfiguration
: Currently only available for DicomWebDataSource, this option allows the interception of the data source configuration for dynamic values e.g. values coming from url params or query params. Here is an example of building the dicomweb datasource configuration object with values that are based on the route url params:This configuration would allow the user to build a dicomweb configuration from a GCP healthcare api path e.g. http://localhost:3000/projects/your-gcp-project/locations/us-central1/datasets/your-dataset/dicomStores/your-dicom-store/study/1.3.6.1.4.1.1234.5.2.1.1234.1234.123123123123123123123123123123{
namespace: '@ohif/extension-default.dataSourcesModule.dicomweb',
sourceName: 'gcpdicomweb',
configuration: {
friendlyName: 'GCP DICOMWeb Server',
name: 'gcpdicomweb',
qidoSupportsIncludeField: false,
imageRendering: 'wadors',
thumbnailRendering: 'wadors',
enableStudyLazyLoad: true,
supportsFuzzyMatching: false,
supportsWildcard: false,
singlepart: 'bulkdata,video,pdf',
useBulkDataURI: false,
onConfiguration: (dicomWebConfig, options) => {
const { params } = options;
const { project, location, dataset, dicomStore } = params;
const pathUrl = `https://healthcare.googleapis.com/v1/projects/${project}/locations/${location}/datasets/${dataset}/dicomStores/${dicomStore}/dicomWeb`;
return {
...dicomWebConfig,
wadoRoot: pathUrl,
qidoRoot: pathUrl,
wadoUri: pathUrl,
wadoUriRoot: pathUrl,
};
},
},
},
Environment Variables​
We use environment variables at build and dev time to change the Viewer's
behavior. We can update the HTML_TEMPLATE
to easily change which extensions
are registered, and specify a different APP_CONFIG
to connect to an
alternative data source (or even specify different default hotkeys).
Environment Variable | Description | Default |
---|---|---|
HTML_TEMPLATE | Which HTML template to use as our web app's entry point. Specific to PWA builds. | index.html |
PUBLIC_URL | The route relative to the host that the app will be served from. Specific to PWA builds. | / |
APP_CONFIG | Which [configuration file][config-file] to copy to output as app-config.js | config/default.js |
PROXY_TARGET | When developing, proxy requests that match this pattern to PROXY_DOMAIN | undefined |
PROXY_DOMAIN | When developing, proxy requests from PROXY_TARGET to PROXY_DOMAIN | undefined |
You can also create a new config file and specify its path relative to the build
output's root by setting the APP_CONFIG
environment variable. You can set the
value of this environment variable a few different ways:
- ~Add a temporary environment variable in your shell~
- Previous
react-scripts
functionality that we need to duplicate withdotenv-webpack
- Previous
- ~Add environment specific variables in
.env
file(s)~- Previous
react-scripts
functionality that we need to duplicate withdotenv-webpack
- Previous
- Using the
cross-env
package in a npm script:"build": "cross-env APP_CONFIG=config/my-config.js react-scripts build"
After updating the configuration, yarn run build
to generate updated build
output.