Table of Contents
ZAViewer is a web 2D image viewer that was primarily designed to explore the Brain/MINDS Marmoset Reference Atlas.
It can display up to 3 sets of multimodal, regularly interspaced, large image slices along the 3 standard orthogonal axes (Axial, Coronal, Sagittal). Each slice view may contains several raster images layers, and Atlas regions (represented by aligned vector images, SVG) displayed as an overlay over the raster images.
zaviewer_overview.mp4
-
ZAViewer User Interface is a javascript web application that can run in any modern Web browser (Firefox, Chrome, Edge) on a desktop or tablet environment since it is focused on displaying large images.
It is usually served from a remote web server, but can be conveniently executed locally in a container thanks to the provided Docker images. -
ZAViewer can run with a dedicated back-end (Image server & web services providing the configuration), or without (as a simple web app hosted with its image and configuration data stored as static files).
-
When used with a backend, ZAViewer can retrieve Pyramidal Images following IIIF protocol or IIProtocol.
-
The standalone version of ZAViewer can display image in DZI (Deep Zoom Image) format.
Note: these images may be retrieved from a remote domain (if properly configured to serve cross-origin content)
-
Have a look at the Brain/MINDS Marmoset Atlas in ZAViewer
Prerequisite: Docker Engine must be installed and running on your machine.
Notes:
- Depending on your configuration, you might need to have root permission to run docker, in this case you will need to preface the
docker
command withsudo
in all the following examples (more details here ). - By default, ZAViewer Docker image will be downloaded from Docker Hub registry if it's not already on your local machine; You can also choose to locally build the image beforehand.
-
Run the web-server container :
docker run -it --rm -p 9090:80 rikencau/zaviewer:latest-ui
â–º This container will display web-server log in the terminal window and keep running until stopped using
[Ctrl-C]
, then the container will be automatically removed (but ZAViewer Docker image will remain in your local repository for later use) -
Launch ZAViewer by opening the following URL in your web browser :
http://localhost:9090/?datasrc=https://dataportal.brainminds.jp/ZAViewer_BMA_2019/
â–º in this configuration, images are actually retrieved from a remote domain, as specified by the
datasrc
parameter.
Notes:
- If you don't intend to use ZAViewer anymore, you may remove locally stored Docker image with the following command:
docker image rm rikencau/zaviewer:latest-ui
ZAViewer is able to display sets of large slice images, along with several kinds of optional secondary data, such as :
- region delineation images (SVG) sets (one for each slice),
- region informations, and their hierarchical organization,
- subview images (single or sets),
An utility script is provided to help with the preparation and setup of the data in the right format and location, and generation of appropriate configuration file.
Note : It will produce Deep Zoom Images copies derived from your source images, so enough free space must be available on your disk (roughly same amount of space than the original images).
The utility script expects a set of slice images (single axis with only 1 layer) as minimal input.
If several layers are defined :
- Within a specific axis, every layers must contains the same number of slice images.
- All slice images of a specific axis/layer must have same size.
Moreover, in case of multiplane configuration:
- All axis must have the same layer/overlay composition, however image sizes may be different between axis.
The script will ask you the following parameters:
-
output directory, where the generated files will be saved,
-
input directory, where the source files are stored as explained below:
The conventions detailed below must be followed so the script will be able to import your data :
- axis directories are located in the input directory, at least 1 must be defined (
coronal
,sagittal
,axial
) - axis directory contains layers (for raster images) and overlays subdirectories (for region delineations)
- Layers directory name must contain :
- the "
layer
" prefix, - an integer to order the layers (from bottom to top) in the UI,
- an underscore separator ("
_
"), - the name of the layer displayed in the UI (free string)
- the "
- Image file name must contain :
- any prefix,
- an underscore separator ("
_
"), - an integer to order the image slice in the UI,
- the image file extension ("
.tif
" as it is currently the only supported format)
- There is only 1 overlay directory (named
overlay0_Regions
) which contains SVG files defining region delineations for each slice. These SVG files must conform to the following rules described here. ZAViever includes a simple region editing feature to interactively create those SVG files and edit their content (see here).
To sum things up, the overall structure of the input directory should look like this:
. ├── coronal │ ├── layer0_Nissl │ │ ├── whatever_0.tif │ │ ├── ... │ │ └── whatever_N.tif │ ├── layer1_T2 MRI │ │ ├── whatever_0.tif │ │ ├── ... │ │ └── whatever_N.tif │ ├── overlay0_Regions │ │ ├── whatever_0.svg │ │ ├── ... │ │ └── whatever_N.svg ├── sagittal │ ├── layer0_Nissl │ ... └── axial ├── layer0_Nissl ...
- axis directories are located in the input directory, at least 1 must be defined (
An optional resource containing hierarchical organization of brain regions may be provided to ZAViewer, which will then be able to :
- dynamically show the long name of the hovered region,
- display in a treeview widget all brain regions to allow navigation and selection.
A default version of the resource (for Marmoset brain) is shipped with the script and is copied in the output folder when the script is executed. Therefore, if you wish to use your own version of the resource, just overwrite the one provided, or alternatively update the configuration file generated in the ouput folder (check configuration details here).
The structure of the region information resource is detailed there.
- In case of single axis image set, you may provide a small image from on an orthogonal plane which will be displayed in the subview wigdet (it allows to see the current slice position in the set)
Note: By default, the docker image will be downloaded from Docker Hub registry if it's not already on your local machine; You can also choose to locally build the image beforehand.
-
Run the import utility script
mkdir OUTPUT docker run -it --rm -u "$(id -u):$(id -g)" -v "$PWD":/mnt/hostdir rikencau/zaviewer:latest-prepimg
Important note :
-
The utility will interactively prompt for output & input paths used during the preparation process; Be careful that these paths must be relative to current directory, eg:
OUTPUT
or./INPUT
-
Alternatively, you can pass argument values on the command line as follow:
```sh
docker run -it --rm -u "$(id -u):$(id -g)" -v "$PWD":/mnt/hostdir \
rikencau/zaviewer:latest-prepimg \
-i ./INPUT -o OUTPUT
```
The same ZAViewer Docker image as before is used, but with different parameters to display local data.
-
Run the web-server container:
docker run -it --rm \ -v /full/path/to/output/dir:/usr/share/nginx/html/data:ro \ -p 9090:80 rikencau/zaviewer:latest-ui
-
Launch ZAViewer by opening the following URL in your web browser :
Notes :
- Replace
/full/path/to/output/dir
with the absolute path to the output directory where images and configuration file have been prepared. - It is of course possible to prepare distinct sets of images into distinct ouput directories, and display one or the other by specifying the right path when running the web-server container (just change the
/full/path/to/output/dir
path). - Several instances of the web-server container may be launched concurrently, just be careful to use distinct listening ports on each instances (e.g. replace
9090
by9010
or any unused value on the command line to launch the container and in address bar of your web browser).
Warning :
- For MS-Windows, Docker might not be able to mount the ouput directory if it is located on a removable media.
It is possible to create custom image processing routine that can be run on (part of) the images displayed in ZAViewer. These routines are Javascript code that can be easily plugged in ZAViewer as explained below.
-
Clone ZAViewer git repo to get the latest sources, including extension directory :
git clone https://github.com/cau-riken/zaviewer.git cd zaviewer
-
Add your custom processsing :
-
declare your custom processsing code inside the following source file :
zaviewer/extension/ZAVProcessings.js
-
insert the required dependencies in the inside the html fragment file :
zaviewer/extension/customProcessings.html
(the content of this file will be included in the main page header)
-
-
Load ZAViewer and test your processing!
The same ZAViewer Docker image as before is used, but with different parameters to allow runing custom processing code.
-
Run the web-server container:
docker run -it --rm \ -v /full/path/to/output/dir:/usr/share/nginx/html/data:ro \ -v /full/path/to/zaviewer/extension/nginx_extra.conf:/etc/nginx/conf.d/nginx_extra.conf:ro \ -v /full/path/to/zaviewer/extension:/usr/share/nginx/html/ext:ro \ -p 9090:80 rikencau/zaviewer:latest-ed
-
Launch ZAViewer by opening the following URL in your web browser :
Note
- ZAViewer needs to be manually reloaded (press
[F5]
key) after changes of the custom processing code.
-
ZAViewer allows to edit the region delineations displayed on top of the slice images (using another Docker image). As before local data will be displayed, but this time the displayed/edited region SVG will be located in a different directory.
Note: By default, the docker image will be downloaded from Docker Hub registry if it's not already on your local machine; You can also choose to locally build the image beforehand.
-
Run the UI+Editor container:
docker run -it --rm \ -v /full/path/to/output/dir:/usr/share/nginx/html/data:rw \ -v /full/path/to/zaviewer/extension/nginx_extra.conf:/etc/nginx/conf.d/nginx_extra.conf:ro \ -v /full/path/to/editableSVGs/dir:/usr/share/nginx/html/data/SVGEdit:rw \ -p 9090:80 rikencau/zaviewer:latest-ed
Notes
- When running in editing mode, ZAViewer works on an independant set of SVG files (basically copied and renamed version of the previously used SVG).
- These files will be retrieved from
/full/path/to/editableSVGs/dir/
directory, and it must contain anARCHIVE
subfolder used to backup the previous version of the edited file each time modifications are saved. (ARCHIVE
subfolder must be created before starting editing). - The SVG file names should be
AtlasReg_
<N>
.svg
, where<N>
is the slice number, which is a bit different from the one used for display, but their internal structure follow the same rules (as explained here). - All files and directory must be readeable & writeable from the Docker container. (🟠add more details here).
-
Launch ZAViewer by opening the following URL in your web browser :
ZAViewer UI source code is composed of Javascript and CSS files that are bundled to produce the WebApp deliverable.
NodeJs
^v16.13.2 (andnpm
^v8.13.1) must be installed on your platform beforehand
Use terminal windows and go to source folder
cd zaviewer
Since one of the package dependency is published on Github package registry, you'll need some sort of authentication to install it (yes, even if it's a public package; see more explanation on authenticating to github packages)
Depending on your current settings, you may be in one of the 2 following cases:
-
If you are already using github package registry for other projects, and have some github token included in your global
.npmrc
, then you don't have to do anything more. -
Alternatively, if you are not using github package registry, you'll require a github account and have to provide one of your github token to compile the project:
- Go to your github settings page, and create a personal (classic) token with
read:packages
scope. - Create a new local
.npmrc
in the project directory, including your token:
(cat npmrc.template ; echo '<REPLACE_BY_YOUR_TOKEN>' > .npmrc
- Go to your github settings page, and create a personal (classic) token with
npm install
npm run build
Javascript
and css
bundles are produced in assets/
subfolder
The viewer is flexible thanks to its detailed configuration descriptors which describe the data to display, according to which the UI adapts its behavior. Note that some limited parts of the configuration are expressed in a similar, but not strictly identical way, depending if ZAViewer runs with or without a backend.
This configuration is loaded in several steps when ZAViewer runs with a backend, This configuration is loaded in a single step when ZAViewer runs with or without a backend, the configuration is merged as a single simplified descriptor.
In this mode, the configuration needs to be loaded in several sequential steps.
This configuration descriptor is the first one loaded when the UI starts, and it is retrieved from the root URL of the UI. It contains base URLs used to retrieve data, metadata and extended configuration descriptors.
entry | description |
---|---|
admin_path |
relative base URL where subsequent configuration descriptors can be retrieved from |
iipserver_path |
URL prefix of the image server used to retrieved raster images |
publish_path |
relative base URL where subview images, detailed region's information and SVG region delineations can be retrieved from |
Example:
{
"admin_path":"./admin/",
"iipserver_path":"/iipsrv/iipsrv.fcgi?IIIF=/data/",
"publish_path":"../data/"
}
This configuration descriptor is loaded in a 2nd step from the admin_path
specified in the path.json
configuration.
It contains information to display slices images for the 3 possible orthogonal axis.
When ZAViewer is used with images along a single axis (aka "single-plane mode") some descriptor field names are slightly simplified compared to multi-plane mode, as indicated respectively by single vs multi indicators.
entry | description |
---|---|
data_root_path |
not used in backend mode |
subview |
|
subview.foldername |
URL prefix of the subview images location (using publish_path base URL) |
subview.axial_slide multi |
optional 1 number of slides in the Axial image set |
subview.coronal_slide multi |
optional 1 as above but for Coronal image set |
subview.sagittal_slide multi |
optional 1 as above but for Sagittal image set |
subview.size |
size of the (square) subview images |
subview.min single |
minimum boundary (in percent) of the space covered by orthogonal slices on the subview image. |
subview.max single |
maximum boundary (in percent) of the space covered by orthogonal slices on the subview image. |
subview.x_min multi |
minimum boundary (in pixels), on the subview image, of the space covered by orthogonal slices along x axis |
subview.x_max multi |
maximum boundary (in pixels), on the subview image, of the space covered by orthogonal slices along x axis |
subview.y_min multi |
same as above, but for y axis |
subview.y_max multi |
same as above, but for y axis |
subview.z_min multi |
same as above, but for z axis |
subview.z_max multi |
same as above, but for z axis |
delineations |
URL prefix of the regions delineation SVG location (using publish_path base URL) |
tree |
URL prefix of the detailed regions information location (using publish_path base URL) |
verofdata.all |
|
verofdata.all.label |
Text description of the dataset (displayed the UI) |
verofdata.all.uri |
URI for the link displayed with the datset description |
first_access |
|
first_access.plane multi |
plane displayed by default after loading (allowed values: axial ,coronal or sagittal ) |
first_access.slide |
initial slide to display |
first_access.delineations |
set whether Atlas region area are displayed by default (allowed values: show or hide ) |
first_access.region_labels |
set whether Atlas region labels are displayed by default (allowed values: show or hide ) |
matrix |
Matrix to convert image space coordinates to physical space coordinates : String representation of a single dimensional vector with the entries (values expressed in millimeters) in row major order |
[unused] gamma |
not used |
[unused] bright |
not used |
image_size |
Size (width) of image in pixel. 🟠Assumes that images are square |
slide_count single |
number of slides in the image set |
slice_step |
single |
axial_slice_step multi |
|
coronal_slice_step multi |
|
sagittal_slice_step multi |
|
[unused] group_name |
not used |
[unused] group_id |
not used |
data |
|
data. layerId .metadata |
Name of the layer displayed in the UI |
data. layerId .extension |
extension of the pyramidal image |
data. layerId .opacity |
initial opacity of the layer |
data. layerId .protocol |
image retrieval protocol (by default IIIF, or IIP) |
data. layerId .contrast |
initial contrast adjustement of the layer (IIP protocol only) |
data. layerId .gamma |
initial gamma adjustment of the layer (IIP protocol only) |
1 : value must be defined for at least 1 axis!
single : single-plane mode only
multi : multi-plane mode only
Example:
{
"data_root_path": "1",
"subview": {
"foldername": "RdMm8CWZuKbsP5",
"coronal_slide": 100,
"size": "200",
"min": "1",
"max": "200"
},
"delineations": "uYRo4S2ZITbCvZ",
"tree": "auE7XHmvCdIcvE",
"first_access": {
"slide": "10",
"delineations": "hide"
},
"matrix": "0.001339262803,0,0,0,0,0.050,0,0,0,0,0.001385689385,0,0,0,0,0",
"gamma": 10,
"bright": "1",
"image_size": "18000",
"slide_count": "64",
"slice_step": "10",
"group_name": "agroup",
"group_id": "1",
"data": {
"oomgNImyri70Fd": {
"metadata": "R01_0028_c2_50mu",
"extension": "ptif",
"opacity": "100"
},
"IjKa5lmYPlIYza": {
"metadata": "R01_0028_nn_tracer",
"extension": "ptif",
"opacity": "100"
}
}
}
In this simple mode, the configuration is loaded in a single step.
This configuration descriptor is retrieved from the root URL of the UI.
Since its contents is almost identical to json.php
of descriptors described above, one should refers to the explanation above.
entry | description |
---|---|
data_root_path |
relative base URL from where all data is loaded (raster image, SVG) |
dataset_id |
dataset ID (Brain/MINDS ID) used to retrieve dataset extended info |
subview |
|
subview.foldername |
see above |
subview.axial_slide |
optional 1 see above |
subview.coronal_slide |
optional 1 see above |
subview.sagittal_slide |
optional 1 see above |
subview.size |
see above |
subview.min single |
as above, but value is expressed in pixels instead of percent. |
subview.max single |
as above, but value is expressed in pixels instead of percent. |
subview.label single |
optional custom label used in UI for the plane |
subview.x_min multi |
see above |
subview.x_max multi |
see above |
subview.y_min multi |
see above |
subview.y_max multi |
see above |
subview.z_min multi |
see above |
subview.z_max multi |
see above |
subview.x_label multi |
optional custom label used in UI for the Sagittal plane |
subview.y_label multi |
optional custom label used in UI for the Coronal plane |
subview.z_label multi |
optional custom label used in UI for the Axial plane |
branding |
|
branding.short |
optional short label displayed right to ZAViewer's logo |
branding.descr |
optional multi-line description of the dataset |
branding.theme |
optional color theme for the UI (allowed value: light ), default theme is dark |
delineations |
see above |
ADD tree |
see above |
verofdata.all |
|
verofdata.all.label |
see above |
verofdata.all.uri |
see above |
first_access |
|
first_access.plane multi |
see above |
first_access.slide |
see above |
first_access.delineations |
see above |
first_access.region_labels |
see above |
matrix |
see above |
image_size |
see above |
axial_size |
optional 1 see above |
coronnal_size |
optional 1 see above |
sagital_size |
optional 1 see above |
slide_count |
see above |
slice_step |
see above |
data |
|
data. layerId .metadata |
see above |
data. layerId .colortable |
Color table file (.ctbl) to be used with this layer. If defined this layer will be used as a raster labelmap (i.e. layer pixel color map a region, as specified in the color table) Important: This layer's tiles must be in .PNG format |
1 : at least one axis image set must be defined!
single : single-plane mode only
multi : multi-plane mode only
Example:
{
"data_root_path": "./data",
"subview": {
"foldername": "subview",
"axial_slide": 235,
"coronal_slide": 200,
"sagittal_slide": 271,
"x_min": 33,
"x_max": 167,
"y_min": 1,
"y_max": 195,
"z_min": 47,
"z_max": 153,
"size": 200
},
"delineations": "SVGs",
"verofdata": {
"all": {
"label": "Brain\/MINDS Reference Brain Atlas Ver. 1.0",
"uri": "https://doi.org/10.24475/bma.2799"
}
},
"data": {
"MRI": {
"metadata": "T2 MRI"
},
"Nissl": {
"metadata": "Nissl"
}
},
"first_access": {
"plane": "coronal",
"slide": 120,
"delineations": "show"
},
"matrix": "0.05,0,0,-13.54,0,0.05,0,-16.00,0,0,0.05,-3.0,0,0,0,1",
"axial_slice_step": 1,
"coronal_slice_step": 2,
"sagittal_slice_step": 1,
"image_size": 1000
}
Region delineations display on top of images are defined in SVG files that must conform to the following rules :
- SVG viewport (defined by
<svg>
'swidth
andheight
attributes) must be identical to corresponding raster image dimensions in pixels. - SVG user coordinate system must be identical to the viewport (i.e. it must not be redefined via a
viewBox
attribute, or by anytransform
attribute on container or graphic elements, since those will be lost when the SVG is imported in the UI). - Therefore, coordinates used for graphic elements directly map to pixels (1 user unit maps to 1 pixel),
- Region delineations are represented by
<path>
elements, which must have a unique value for theirid
attribute, and a region id in the custom attributebma:regionId
(declared namespacexmlns:bma="https://www.brainminds.riken.jp/Atlas"
). The region hemisphere is indicated by a 2 characters suffix in the region id: an underscore separator_
and the side letter (L
orR
). - Region's path must be contained in the
<svg>
's first group element. - One path defining a closed rectangle the size of the image must be defined with
id="backgound"
(This element is mandatory for correct region rendering and region edition feature). - [Optionally] Region's labels may be included within a group element whose id is
region-labels
(<g id="region-labels">
). - [Optionally] Other regions of interest may be defined within a group element whose id is
rois
(<g id="rois">
).
<?xml version="1.0"?>
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:bma="https://www.brainminds.riken.jp/Atlas"
xmlns:zav="https://www.brainminds.riken.jp/ZAViewer"
width="18500" height="18500">
<g>
<path id="background" style="fill:#00000000;stroke:#00000000;stroke-width:0;" d="M 0 0 L 0 18500 18500 18500 18500 0Z"/>
<path id="A8aD_L-1" bma:regionId="A8aD_L" style="fill:#a3c2f2;stroke:#a3c2f2;stroke-width:1;" d=" M 6381 3847 ..."/>
...
</g>
<g id="region-labels">
<text id="lbl-A8aD_L_0" bma:regionId="A8aD_L" x="12098" y="5023" text-anchor="middle">A8aD</text>
</g>
<g id="rois">
<path zav:roi-id="inj-mask" fill="#00ff00" opacity="0.4" d="M 244.30 96.33 C 248.70 ..." />
...
</g>
</svg>
This optional resource is used by ZAViewer to dynamically show the long name of focused region, or to display hierarchical organisation of all brain regions.
Regions are described in the resource by json
blocks which follow the typescript
interface below.
Each region is identifed by a unique region abbreviation, which is specified in bma:regionId
(or xml:id
) attribute of overlay SVG paths' in order to make the link between shapes and brain regions.
interface IRegion {
abb: string, // region's abbreviation. MUST be unique as it is used as region identifier.
parent: string | null, // abbreviation of the parent region, null only for the (unique) root region.
name: string, // long name of the region.
exists: number, // indicates if the region is identified in at least one slice (then its value is 1, 0 otherwise)
color: string, // RGB hex value of the color associated to the region
children?: string[], // [optional] list of abbreviation of sub-regions, if any
}
e.g.
{
"parent": "CorA",
"abb": "VC",
"name": "Visual cortex",
"exists": 1,
"children": [
"V1", "V2", "V3", "V3A", "A19DI", "A19M", "V4", "V4T", "V5", "MST", "FST", "V6"]
}
A list of software tools to create Deep Zoom Images can be found here
ZAViewer is licensed under the Apache License, Version 2.0. See LICENSE.txt for the full license text.