A Vue plugin that provides a set of functionalities and components to read and render DICOM images and their metadata.
- DITTO file-system-api
- DITTO relative-height
- DITTO data-types/dicom
- Larvitar
- Vue
- Vuetify
- vue-resize-directive
Import the plugin and register it:
import dicomPlugin from "@/../ditto/dicom";
Vue.use(dicomPlugin, {...});
Available plugin options:
Option | Description | Default |
---|---|---|
canvas | whether this plugin should register the ditto-dicom-canvas and ditto-dicom-canvas-data components globally |
true |
dataTypes | whether this plugin should register the dicom data types components globally with the name of ditto-data-type-[name] (see the data-types docs for more information) |
false |
import | whether this plugin should register the ditto-dicom-import and ditto-dicom-import-modal components globally |
true |
series | whether this plugin should register the ditto-dicom-series-summary component globally |
false |
store | the vuex store object of your application; when provided, this plugin tells larvitar to use a vuex store named larvitar (that currently should be registered manually by your application) | undefined |
toolsStyle | the configuration object of the cornerstone tools style; available keys: activeColor , backgroundColor ,color ,fillColor ,fontFamily ,fontSize , width |
undefined |
utils | whether this plugin should expose its utilities methods at Vue.prototype.$ditto.dicom |
false |
Here is a custom configuration example:
import store from "./store";
const lightTheme = vuetify.userPreset.theme.themes.light;
let toolsStyle = {
activeColor: lightTheme.secondary,
backgroundColor: "rgba(1, 1, 1, 0.85)",
color: lightTheme.dicomTool,
fillColor: lightTheme.dicomTool,
fontFamily: "Comfortaa",
fontSize: 14,
width: 2
};
const dicomPluginOptions = {
dataTypes: true,
series: true,
store,
toolsStyle,
utils: true
};
Vue.use(dicomPlugin, dicomPluginOptions);
This component renders a series stack into a canvas using larvitar.
Name | Description | Type | Default |
---|---|---|---|
clearCacheOnDestroy | whether to tell larvitar to clear the image cache for the rendered series on component unmount; it works only with clearOnDestroy set to true |
Boolean | false |
clearOnDestroy | whether to tell larvitar to clear the data stored by larvitar for the rendered series on component unmount (see clearSeriesData in utils) | Boolean | false |
canvasId | the id to assign to the canvas element | String | true |
getImageIdsFn | the function the component should use to get the series loading status; should return the list of the image ids | Array | (store, seriesId) => (store.state.larvitar.series[seriesId] |
getProgressFn | the function the component should use to get the series loading status; should return a value between 0 and 100 | Function | (store, seriesId) => (store.state.larvitar.series[seriesId] |
getViewportFn | the function the component should use to get the viewport object | Function | (store, seriesId, canvasId) => store.getters"larvitar/viewport" |
seriesId | the id of the series you want to render; when the stack is not provided by the stack prop this value is used to get the series stack from larvitar | String, Number | true |
showMultiframeIcon | whether this component shoul show the multiframe icon | Boolean | false |
showProgress | whether this component shoul show a loading progress | Boolean | false |
stack | the stack of the series you want to render (larvitar stack format is required) | Object | undefined |
tools | the list of the tools you want to activate on this canvas (larvitar tools format is required) | Array | stackTools.default , see defaults |
toolsHandlers | the tools handlers configuration (larvitar tools handlers format is required) | Object | undefined |
showSlider | whether this component should show a slider to scroll the images | Boolean | false |
showPercentage | whether this component should show a circular loader with series download percentage | Boolean | false |
downloaded | whether the series this component is rendering has been fully downloaded (masks included) | Boolean | false |
Name | Description | v-bind |
---|---|---|
stack-metadata | Allows your application to access the stack metadata; generally used to show static metadata fields over the canvas | an object with the stack metadata |
viewport-data | Allows your application to access the viewport data; generally used to show dynamic viewport data over the canvas | an object with the viewport data |
viewport-slider | Allows your application to access the viewport sliceId and maxSliceId information, needed to build a stack slider component |
{i: [the current slice id], n: [the series max slide id]} |
Name | Description | Args |
---|---|---|
ready | emitted when the series is rendered | none |
Basic usage:
<ditto-dicom-canvas canvas-id="main" series-id="1234125" />
With slots:
<ditto-dicom-canvas :canvas-id="main" :series-id="1234125">
<template v-slot:stack-metadata="data"><div>...</div></template>
<template v-slot:viewport-data="data"><div>...</div></template>
<template v-slot:viewport-slider="{ i, n }"><div>...</div></template>
</ditto-dicom-canvas>
With events:
<ditto-dicom-canvas
canvas-id="main"
series-id="1234125"
@ready="onCanvasReady"
/>
This component renders a set of common dynamic viewport data (the viewport size, spacing, thickness, voi...). Is generally used as slot content of the stack-metadata slot provided by the ditto-dicom-canvas component.
Name | Description | Type |
---|---|---|
data | the viewport data object | Object |
<ditto-dicom-canvas-data :data="data" />
This component allows a user to select and parse DICOM files, renders a preview of the parsed series with a subset of their metadata and then performs one of the available actions before returning the control to your application.
Name | Description | Type | Default |
---|---|---|---|
icon | the icon shown in the import modal | String | mdi-upload-multiple |
label | the label shown in the import modal | String | dicom-import.import-exams |
options | the import modal customization object | Object | use all default options |
!!! NOTE: you can use the option prop to customize the behaviour of this component. The options prop values will override the default options you can find at options.
Each import step is described by an object with the following keys:
- component: the Vue component to be rendered for that step
- label: the name of the step
- back: a function that returns
true
if the navigation to the previous step is allowed - next: a function that returns
true
if the navigation to the next step is allowed (this function receives the parsed series list as parameter) - actions: a list of allowed actions; when a list of actions is available the user should select one action to go to the next step and the next function is ignored
- closeConfirmation: a function that returns
true
if the import modal can be closed (this function receives the status value as parameter); if the modal can not be close it is minimized but not destroyed; default istrue
- status: an object that describes the status of the step, updated by your application by reference; it accepts the following keys: completed (Boolean), loading (Boolean), errors (Array) and progress (Object); this is currently supported by step 3 only, but could be extended to the other steps too (each default step component can be replaced by a custom one)
Each action is described by an object with the following keys:
- cacheStacks: whether to tell larvitar to cache the parsed images before emitting the action event; it works only if storeStacks is
true
- closeOnEmit: whether to close the import modal after emitting the action event (by default the component renders the next steps)
- default: whether the action is selected by default,
- disabled: whether the action is disabled or not,
- emitter: the name of the event emitted to your application when the action is selected; the event receives as argument the list of the selected parsed series with the subset of the required metadata (or the default ones: see next section)
- hint: the action subtitle
- storeStacks: whether to tell larvitar to store the series stacks before emitting the action event
- text: the action title
The default available action emitter names are the following:
- dicom-import-open to open the parsed series in your application viewer
- dicom-import-upload to upload the parsed series to your application server
- dicom-import-upload-and-open to upload and open the parsed series
!!!: you can customize these steps with an array of objects using the described keys. The values of the keys of the object at index 0 will override the values of the keys at step 0 and so on. The same happens for the actions array. Add the steps key to the options prop with your overrides data. Go to the usage section to see some examples.
By deafult this component extracts from the parsed series stacks a list of metadata that are used to present basic series information to the user. You can find this list at options. You can replace this list with a custom one: use the standard dicom metadata tags (x00000000) to write your own list. You can also use the metadata dictionary, that you can import into your application indipendently. Some metatada are required by this component to work correctly, but don't worry: if you don't include theme into your custom list, will be added automatically.
Remember that you need to exctract a specific metadata to:
- see that information into the list of parsed series (import modal, step 2)
- receive that information with the data emitted by the step actions
!!!: to customize the metadata add the metadata key to the options prop with your metadata list. Go to the usage section to see some examples.
The table headers represents the information shown in the parsed series table: each table header is a vuetify table column (see the vuetify doc for more information).
This components manages the following cases:
- by deafult this component uses the list of table headers you can find at options
- if you customize the metadata option key the table headers will be automatically computed based on your custom metadata (each metadata will be a table header)
- if you add the headers key to the options prop with a custom table headers list this component will use your customized list (see the vuetify doc for the headers configuration options)
In addition to the vuetify configuration options the component supports the following keys:
- slot: whether to use a custom slot to render the content of an header cell (you have to provide the slot element: its name will be the value of the value header key)
- keys: the list of stack metadata whose values will be rendered as the content of an header cell, usefull to group a set of information into a single cell (eg for the patient, as already done by the default headers); you can also specify a keyClass (the class that will be applied to each value of the header cell) and a keyTag (the tag of each header cell sub components)
When available the strings components defined in data-types/dicom will be used to render the values of the headers metadata.
If you provide an header with the string preview for the key value (this is provided by default headers) the component will render the ditto-dicom-canvas component into theser header cells.
!!!: to customize the table headers add the headers key to the options prop with your header list. Go to the usage section to see some examples.
By default this components activates on the preview canvas (if required by the table headers) the tools specified in stackTools.preview
(see defaults).
!!!: to customize the tools add the tools key to the options prop with your tools list (larvitar tools format required). Go to the usage section to see some examples.
See the ditto-dicom-canvas props. Used only if a preview header is available.
!!!: to customize these functions add the getProgressFn and the getViewportFn keys to the options prop.
Name | Description | v-bind |
---|---|---|
value key of each header that requires a custom slot (slot key is true ) |
Custom header cell content (see previous explanations) | { item: the table row item } |
step-3 | Step 3 extra content | none |
Name | Description | Args |
---|---|---|
cancel | the import component should be closed | none |
minimize | the import component should be minimized | none |
step action emitter name | the user chose an action | list of objects of the selected parsed series metadata |
See the ditto-dicom-import-modal usage section.
This component is a wrapper for the ditto-dicom-import component: it allows to open the ditto-dicom-import component inside a modal, using a button as modal activator.
It manages the events emitted from the ditto-dicom-import component and eventually shows the minimized status information (eg the number of series parsed, the upload status).
It support both the desktop and mobile visualization modes.
!!!: use this component istead then the ditto-dicom-import component directly, eventually replacing the button modal activator with a custom one using the activator slot.
Name | Description | Type | Default |
---|---|---|---|
defaultActive | default modal behaviour, active or not | Boolean | false |
activatorClass | custom activator class | String | undefined |
badgeColor | color of the activator badge | String | primary |
icon | the icon of the activator button and shown in the import modal header | String | mdi-upload-multiple |
iconColor | the color of the activator button | String | undefined |
label | the label of the activator button and shown in the import modal header | String | import-exams |
mobile | whether to render the component using the mobile mode | Boolean | false |
options | the options passed to the ditto-dicom-import component (see previous docs) | Object | {} |
Name | Description | v-bind |
---|---|---|
activator | the button that activates the modal, with support for desktop and mobile screens | { on, attrs, minimizedSeries, uploading } |
value key of each header that requires a custom slot (slot key is true ) |
Custom header cell content (see previous explanations); used by the ditto-dicom-import component | { item: the table row item } |
step-3 | Step 3 extra content; used by the ditto-dicom-import component | none |
The actions events triggered by the ditto-dicom-import component are redirected from this component to be accessible by your application.
Basic usage:
<ditto-dicom-import-modal @dicom-import-open="openViewer" />
UI changes:
<ditto-dicom-import-modal
badge-color="black"
icon="mdi-plus"
icon-color="accent"
label="load dicom exams"
@dicom-import-open="openViewer"
/>
Customize steps:
const steps = [
// step 1: preserve default options
undefined,
// step 2: enable first default action and change step description
{ actions: [{ disabled: false }], text: "custom step description" },
// step 3: add upload status data
{ status: { ... } }
];
<ditto-dicom-import-modal
:options="{ steps }"
@dicom-import-open="openViewer"
@dicom-import-upload="uploadData"
/>
Customize metadata and headers:
const metadata = ["x00100010", "x00100040", "x0008103e"];
<ditto-dicom-import-modal
:options="{ metadata }"
@dicom-import-open="openViewer"
/>
Customize headers:
- show the preview
- group patient information using header.keys
const metadata = ["x00100010", "x00100040", "x0008103e"];
const headers = [
{ sortable: false, text: "", value: "preview" },
{
cellClass: "cell-patient",
sortable: false,
keys: ["x00100010", "x00100040"],
text: "patient",
value: "patient"
},
{
cellClass: "cell-x0008103e",
sortable: true,
text: "metadata-x0008103e",
value: "x0008103e"
}
];
<ditto-dicom-import-modal
:options="{ headers, metadata }"
@dicom-import-open="openViewer"
/>
Use custom header slots:
const metadata = ["x00100010", "x00100040", "x0008103e"];
const headers = [
{
cellClass: "cell-patient",
sortable: false,
slot: true,
text: "patient",
value: "patient"
},
{
cellClass: "cell-x0008103e",
sortable: true,
slot: true,
text: "metadata-x0008103e",
value: "x0008103e"
}
];
<ditto-dicom-import-modal
:options="{ headers, metadata }"
@dicom-import-open="openViewer"
>
<template v-slot:patient="{ item }">patient custom slot content</template>
<template v-slot:x0008103e="{ item }">x0008103e custom slot content</template>
</ditto-dicom-import-modal>
Customize activator:
<ditto-dicom-import-modal @dicom-import-open="openViewer">
<template v-slot="{ minimizedSeries, on, uploading }">
activator custom slot content
</template>
</ditto-dicom-import-modal>
This component renders a set of a series stack information.
Name | Description | Type | Default |
---|---|---|---|
canvasId | the id to assign to the canvas element, when the series canvas is required | String | undefined |
clearCacheOnDestroy | whether to tell larvitar to clear the image cache for the rendered series on component unmount; it works only with clearOnDestroy set to; used only when the showCanvas prop is true |
Boolean | true |
clearOnDestroy | whether to tell larvitar to clear the data stored by larvitar for the rendered series on component unmount (see clearSeriesData in utils; used only when the showCanvas prop is true |
Boolean | true |
data | the series stack data (larvitar stack format is required) | Object | undefined |
showCanvas | whether this component should render the series canvas using the ditto-dicom-canvas component | Boolean | true |
showProgress | whether this component shoul show a a loading progress; used only when the showCanvas prop is true |
Boolean | false |
showThumbnail | whether this component should render the series thumbnail; the thumbnail should be an image url or a base64 string available at data.thumbnail |
Boolean | false |
tools | the list of the tools you want to activate on this canvas (larvitar tools format is required); used only when the showCanvas prop is true |
Array | stackTools.preview , see defaults |
showSlider | whether this component should render the series slider; the slider allows user to change a series slice manually. | Boolean | false |
A default slot is available to add your preferred content.
Basic usage:
<ditto-dicom-series-summary :canvas-id="summary-main" :data="series" />
With series thumbnail instead of canvas:
<ditto-dicom-series-summary
:canvas-id="summary-main"
:data="{ ...series, thumbnail: '...' }"
show-thumbnail
/>
Without tools:
<ditto-dicom-series-summary
:canvas-id="summary-main"
:data="series"
:tools="[]"
/>
With slot:
<ditto-dicom-series-summary :canvas-id="summary-main" :data="series">
<div>custom content</div>
</ditto-dicom-series-summary>
The utils module provides utilities methods based on larvitar. The aim of these methods/wrappers is to group all larvitar functinalities in a single module in order to change only this file on larvitar upgrades that requires api changes.
- activateTool(tool, elementIds, options = { mouseButtonMask: 1 }): calls the larvitar setToolActive function
- addTools(tools, elementId, handlers): calls the larvitar addTool and addMouseKeyHandlers functions, calls activateTool for default active tools
- disableTool(tool, elements): calls the larvitar setToolEnabled function
- editTool(tool, elements): calls the larvitar setToolPassive function
- hideTool(tool, elements): calls the larvitar setToolDisabled function
- showTool(tool, elements): calls the larvitar setToolEnabled function
- buildData(stack): wraps the larvitar buildDataAsync function into a promise
- buildHeader: calls the larvitar buildHeader function
- clearSeriesCache: calls the larvitar clearImageCache function
- clearSeriesData(seriesId, clearCache = false): calls the larvitar removeSeriesFromLarvitarManager, clearImageCache and larvitar_store.removeSeriesIds functions
- deleteViewport(elementId): calls the larvitar larvitar_store.deleteViewport function
- disableCanvas: calls the larvitar disableViewport function
- getCinematicData(seriesId): reads frameDelay and frameTime from the larvitar stack
- getSeriesStack(seriesId): reads the series stack from the larvitar manager
- mergeSeries(...series): merges the instances of a list of series into a single series object if their instance uids matches
- parseFiles(files, extractMetadata = []): uses larvitar to parse files and get series stacks, extracting the required metadata
- parseFile(seriesId, file): uses larvitar to parse a single file and get single image stack object
- renderSeries(elementId, seriesStack): calls the larvitar larvitar_store.addViewport and renderImage functions
- resizeViewport: calls the larvitar resizeViewport function
- seriesIdToElementId(seriesId): replaces dots with underscores to get a valid html element id
- setup(store, toolsStyle): larvitar initialization
- storeSeriesStack(seriesId, stack, cache = false): calls the larvitar populateLarvitarManager and eventually cacheImages functions
- updateSeriesSlice(elementId, seriesId, sliceId, imageCache): uses larvitar to update a series slice
- updateViewportProperty(action, element): uses larvitar to update the canvas with one of the available actions: flip-horizontal, flip-vertical, invert, reset-viewport
A dictionary of the metadata tags used by the dicom plugin. If you need it you can import it into your application as a stand alone module:
import metadata from "@/../ditto/dicomMetadata";
See the DICOM examples code for more information.
- !!! modal minimization is lost if the application mounts this component in a page that can be unmounted (eg after a route change)
- the larvitar renderSeries function should return a promise and the ditto-dicom-canvas component should manage that
- imported series stacks data should be cleared once uploaded
- allow to customize import study row