# MRB File Format - Structure and Naming

**URL:** <https://discourse.slicer.org/t/mrb-file-format-structure-and-naming/10624>\
**Category:** Development\
**Tags:** file-export, mrml\
**Created:** [March 10, 2020, 8:08pm UTC](https://discourse.slicer.org/t/mrb-file-format-structure-and-naming/10624 "2020-03-10T20:08:04Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![ArneGroskurth](https://avatars.discourse-cdn.com/v4/letter/a/0ea827/32.png) [@ArneGroskurth](https://discourse.slicer.org/u/ArneGroskurth)\
**Post date:** [March 10, 2020, 8:08pm UTC](https://discourse.slicer.org/t/mrb-file-format-structure-and-naming/10624/1 "2020-03-10T20:08:04Z")

</div>

Hi there,

is there any documentation for the \*.mrb file format?

I would like to implement an interface to this format for another application but would ideally not have to reverse-engineer the format.

And if there is no such documentation:

- Is the mrb-fiel always a zip-archive?
- How is the general structure and naming within the archive?
- Is there always a directory called “input” in the root of the archive and nothing else? (And why is that so?)
- How is the naming within the “Data” directory?

I am primarily interested in extracting segmentations from the file.

Thank you very much,  
Arne

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [March 10, 2020, 8:30pm UTC](https://discourse.slicer.org/t/mrb-file-format-structure-and-naming/10624/2 "2020-03-10T20:30:04Z")

</div>

Hi Arne -

First the standard disclaimer: mrb files are meant to be a application-specific format not an interchange format, so they are subject to change without notice as Slicer’s implementation changes. You have been warned 😜

For interchange we suggest using DICOM, particularly SEG objects if you are interested in segmentation (see [dicom4qi](https://dicom4qi.readthedocs.io/en/latest/results/seg/3dslicer/) for example).

That said, certain things are likely to persist. Basically yes, .mrb is likely to always be a .zip file containing a top level mrml scene file. All of the storable nodes are redirected into the Data directory and the result is zipped up. Everything else about it is basically an implementation detail byproduct of [this code](https://github.com/Slicer/Slicer/blob/b849223cb547bab4dbca641185c83a2fa2b8b3be/Libs/MRML/Logic/vtkMRMLApplicationLogic.cxx#L627).

If you are determined to parse the structure it should be pretty easy to do - just read the mrml xml and all the names, datatypes, filenames, etc will be there. It’s essentially just a serialization of the application state.

---

<div class="post-metadata">

**Author:** ![ArneGroskurth](https://avatars.discourse-cdn.com/v4/letter/a/0ea827/32.png) [@ArneGroskurth](https://discourse.slicer.org/u/ArneGroskurth)\
**Post date:** [March 10, 2020, 9:19pm UTC](https://discourse.slicer.org/t/mrb-file-format-structure-and-naming/10624/3 "2020-03-10T21:19:44Z")

</div>

Thanks for the quick response!

Using DICOM SEG objects would be fine. How can I export them from slicer?

Thank you very much!

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [March 10, 2020, 9:43pm UTC](https://discourse.slicer.org/t/mrb-file-format-structure-and-naming/10624/4 "2020-03-10T21:43:43Z")

</div>

[https://qiicr.gitbooks.io/quantitativereporting-guide/](https://qiicr.gitbooks.io/quantitativereporting-guide/)

Good luck with your research - let us know how it goes!

---

<div class="post-metadata">

**Author:** ![ArneGroskurth](https://avatars.discourse-cdn.com/v4/letter/a/0ea827/32.png) [@ArneGroskurth](https://discourse.slicer.org/u/ArneGroskurth)\
**Post date:** [March 24, 2020, 10:36am UTC](https://discourse.slicer.org/t/mrb-file-format-structure-and-naming/10624/5 "2020-03-24T10:36:24Z")

</div>

Unfortunately, the plugin is not ideal for the workflow in our lab. So I do have some more questions regarding the mrb format - or perhaps, slicer in general.

- **What is the data-model for segmentations?**
- As documented [here](https://www.slicer.org/wiki/Documentation/Nightly/Modules/Segmentations), I understand that one _segmentation_ consists of multiple _segments_. But what is a _segmentation_/  
_segment_ then really? Intuitively, I would expect just multiple _segmentations_ being associated with an image, each being defined by a single mask with the same shape as the image volume.
- Why are there both Segmentation- and LabelMapVolume-Nodes within the mrml-document? Aren’t label-maps just a different representation for a set of multiple segmentations? Or in what way are they distinct from one another?

(Some questions might arise from my lack of usage-experience with slicer.)

Thank you very much!

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [March 24, 2020, 12:08pm UTC](https://discourse.slicer.org/t/mrb-file-format-structure-and-naming/10624/6 "2020-03-24T12:08:23Z")

</div>

> [@ArneGroskurth](#):
>
> Unfortunately, the plugin is not ideal for the workflow

Could you write about your workflow? It would help in understanding what you would like to do and what would be the best potential solutions.

> [@ArneGroskurth](#):
>
> what is a _segmentation_

Segmentation defines multiple, potentially overlapping regions. Internally, it can use various representations (binary labelmap, closed surface, fractional labelmap, set of parallel contours, ribbons, etc.) and keep them all in sync. See an overview of how it is related to other nodes [here](https://slicer.readthedocs.io/en/latest/user_guide/data_loading_and_saving.html).

> [@ArneGroskurth](#):
>
> Why are there both Segmentation- and LabelMapVolume-Nodes within the mrml-document?

Normally you only have segmentation in the scene because segmentation can do everything that a labelmap, but much more (it can store overlapping segments, can be displayed directly in 3D, can be edited in Segment Editor, etc.). If some external software creates a labelmap volume then you can load it directly as segmentation.

---

<div class="post-metadata">

**Author:** ![ArneGroskurth](https://avatars.discourse-cdn.com/v4/letter/a/0ea827/32.png) [@ArneGroskurth](https://discourse.slicer.org/u/ArneGroskurth)\
**Post date:** [March 24, 2020, 4:28pm UTC](https://discourse.slicer.org/t/mrb-file-format-structure-and-naming/10624/7 "2020-03-24T16:28:58Z")

</div>

Thank you for the background!

Together with the input from a colleague I conclude the following:

- What I intuitively named a _segmentation_ is a _segment_ is slicer-terms
- A _segmentation_ in slicer terms is just a set of multiple _segments_ and every _segment_ has to be part of a _segmentation_. (Presumably, _segmentations_ have been introduced to slicer to help organize a large number of _segments_)
- A mrb record can have an arbitrary number of _segmentations_, each containing an arbitrary number of _segments_.
- A _label-map_ can be actively derived from a set of _segmentations_ (or _segments_?) and saved within the slicer data-model.
- As label-maps are derived from segmentations (in some point in time of their edit-history), they are potentially outdated w.r.t. the segmentations

Is that about right?

(Side-Note: Having all this information about the data-model as e.g. an UML-diagram would be really helpful)

About our workflow: We currently need to re-visit and slightly correct the segmentations within a large number of scans (thousands). Just loading and saving those segmentations into/from slicer using the plugin takes just too long as the number of required steps/clicks is quite high.

---

<div class="post-metadata">

**Author:** ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)\
**Post date:** [March 24, 2020, 5:36pm UTC](https://discourse.slicer.org/t/mrb-file-format-structure-and-naming/10624/8 "2020-03-24T17:36:48Z")

</div>

> [@ArneGroskurth](#):
>
> A _label-map_ can be actively derived from a set of _segmentations_ (or _segments_ ?) and saved within the slicer data-model.

A labelmap is a lossy representation of a segmentation (no overlap information).

> [@ArneGroskurth](#):
>
> As label-maps are derived from segmentations (in some point in time of their edit-history), they are potentially outdated w.r.t. the segmentations

Labelmaps or other data can also be imported back into segmentations. So which one is up to date depends on what modules you need to use to process data.

> [@ArneGroskurth](#):
>
> (Side-Note: Having all this information about the data-model as e.g. an UML-diagram would be really helpful)

Yes please do! (haha)

> [@ArneGroskurth](#):
>
> About our workflow: We currently need to re-visit and slightly correct the segmentations within a large number of scans (thousands). Just loading and saving those segmentations into/from slicer using the plugin takes just too long as the number of required steps/clicks is quite high.

Sounds like a good opportunity to make a custom scripted module to simplify things.

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [March 24, 2020, 8:11pm UTC](https://discourse.slicer.org/t/mrb-file-format-structure-and-naming/10624/9 "2020-03-24T20:11:39Z")

</div>

> [@ArneGroskurth](#):
>
> About our workflow: We currently need to re-visit and slightly correct the segmentations within a large number of scans (thousands). Just loading and saving those segmentations into/from slicer using the plugin takes just too long as the number of required steps/clicks is quite high.

[CaseIterator extension](https://github.com/JoostJM/SlicerCaseIterator) was developed for exactly this. You can probably use it as is, but since it is a Python scripted module you can also easily customize and/or extend it to do exactly what you need.

---

<div class="post-metadata">

**Author:** ![ArneGroskurth](https://avatars.discourse-cdn.com/v4/letter/a/0ea827/32.png) [@ArneGroskurth](https://discourse.slicer.org/u/ArneGroskurth)\
**Post date:** [March 26, 2020, 6:05pm UTC](https://discourse.slicer.org/t/mrb-file-format-structure-and-naming/10624/10 "2020-03-26T18:05:33Z")

</div>

That extensions seems promising but when I try to install the extension via the slicer extension manager I just get these error messages:

“Retrieving extension metadata [extensionId: 293501]”  
“{6835d4d9-c3bb-4f34-8d9e-615305101b29}: 5: Operation canceled”

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [March 26, 2020, 7:00pm UTC](https://discourse.slicer.org/t/mrb-file-format-structure-and-naming/10624/11 "2020-03-26T19:00:57Z")

</div>

The extension manager website can be overwhelmed with requests sometimes. If you have trouble installing an extension then click on Install button again, until download and installation succeeds. We plan to migrate to a new server backend soon, which should not have these inconveniences anymore.

---

<div class="post-metadata">

**Author:** ![ArneGroskurth](https://avatars.discourse-cdn.com/v4/letter/a/0ea827/32.png) [@ArneGroskurth](https://discourse.slicer.org/u/ArneGroskurth)\
**Post date:** [March 26, 2020, 7:42pm UTC](https://discourse.slicer.org/t/mrb-file-format-structure-and-naming/10624/12 "2020-03-26T19:42:28Z")

</div>

Okay I will try that - thanks!

One more question: What is the _extent_ being associated with a _segment_? It gets written into the nrrd header for each segment and is a space-separated list for six integer numbers. (E.g.: `Segment5_Extent: '23 333 14 237 0 0'`)

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [March 26, 2020, 7:49pm UTC](https://discourse.slicer.org/t/mrb-file-format-structure-and-naming/10624/13 "2020-03-26T19:49:22Z")

</div>

_SegmentN\_Extent_ defines where within the volume the segment has non-zero voxels according usual VTK extent conventions (xmin, xmax, ymin, ymax, zmin, zmax). It is a hint used for optimizing segmentation reading performance.

---

<div class="post-metadata">

**Author:** ![ArneGroskurth](https://avatars.discourse-cdn.com/v4/letter/a/0ea827/32.png) [@ArneGroskurth](https://discourse.slicer.org/u/ArneGroskurth)\
**Post date:** [March 28, 2020, 1:31am UTC](https://discourse.slicer.org/t/mrb-file-format-structure-and-naming/10624/14 "2020-03-28T01:31:29Z")

</div>

Great!

I hope, this will be the last (for now…):

What is the relationship between all of these values?:

- “space origin” and “space directions” from image volume nrrd header
- “space origin”, “space directions” and “Segmentation\_ReferenceImageExtentOffset” from segmentation volume nrrd header
- the attributes “dimensions”, “xyzOrigin”, “uvwExtents”, “uvwDimensions”, “uvwOrigin” and “sliceToRAS” of a node within the mrml file
- voxel coordinates within the image- and segmentation-volumes

I assume, most of those values can be derived from basic information about the image volume and a segmentation volume but I struggle to get the complete picture of that.

Thank you very much for your input!

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [March 28, 2020, 1:43am UTC](https://discourse.slicer.org/t/mrb-file-format-structure-and-naming/10624/15 "2020-03-28T01:43:34Z")

</div>

> [@ArneGroskurth](#):
>
> - “space origin” and “space directions” from image volume nrrd header
> - “space origin”, “space directions” and “Segmentation\_ReferenceImageExtentOffset” from segmentation volume nrrd header

These are all standard nrrd fields that describe image geometry, except Segmentation\_ReferenceImageExtentOffset (which is added to allow extent to start at any voxel position; this is needed, since VTK allows non-zero extent start values, but nrrd format always assumes extents start from 0).

> [@ArneGroskurth](#):
>
> the attributes “dimensions”, “xyzOrigin”, “uvwExtents”, “uvwDimensions”, “uvwOrigin” and “sliceToRAS” of a node within the mrml file

These are slice view properties, define the size and origin of slice display (XYZ) and texture image (UVW) coordinate systems.

> [@ArneGroskurth](#):
>
> voxel coordinates within the image- and segmentation-volumes

IJK to RAS (or IJK to LPS) transform specifies mapping between voxel and physical coordinate system. You can compute these transforms from origin, spacing, and axis directions (e.g., defined by space origin, space directions values in a NRRD file).

---

<div class="post-metadata">

**Author:** ![ArneGroskurth](https://avatars.discourse-cdn.com/v4/letter/a/0ea827/32.png) [@ArneGroskurth](https://discourse.slicer.org/u/ArneGroskurth)\
**Post date:** [April 7, 2020, 4:03pm UTC](https://discourse.slicer.org/t/mrb-file-format-structure-and-naming/10624/16 "2020-04-07T16:03:36Z")

</div>

I’ve still another question 😃:

When trying to read the image-volume nrrd and overlay it with a segmentation volume nrrd, I’m currently getting a slight mismatch of 22 voxels in the anterior-posterior axis. My assumption was, that I must only care about the _Segmentation\_ReferenceImageExtentOffset_ nrrd header field within the segmentation volume to rebuild the _full_ segmentation volume - is that correct?

My python code for that looks roughly like this:

```
# read 3D image volume
image_nrrd_data, image_nrrd_header = nrrd.read(...)

# Read 4D segmentation mask
segmentations_nrrd_data, segmentations_nrrd_header = nrrd.read(...)

# Read segmentation volume offset w.r.t. image volume origin
offset = [
    int(s)
    for s in segmentations_nrrd_data["Segmentation_ReferenceImageExtentOffset"].split()
]

# iterate over all segments
for segment_index in range(...):

    segment_mask = segmentations_nrrd_data[segment_index]

    # Build 3D mask with full size
    mask = np.zeros(image_nrrd_data.shape, dtype=np.bool)
    mask[
        offset[0] : offset[0] + segment_mask.shape[0],
        offset[1] : offset[1] + segment_mask.shape[1],
        offset[2] : offset[2] + segment_mask.shape[2],
    ] = segment_mask

    # save mask for that segment...

```

Note, that I’m not taking into consideration information from the nrrd headers _SegmentX\_Extent_, _space\_direction_ or _space origin_.

---

<div class="post-metadata">

**Author:** ![ArneGroskurth](https://avatars.discourse-cdn.com/v4/letter/a/0ea827/32.png) [@ArneGroskurth](https://discourse.slicer.org/u/ArneGroskurth)\
**Post date:** [April 7, 2020, 5:11pm UTC](https://discourse.slicer.org/t/mrb-file-format-structure-and-naming/10624/17 "2020-04-07T17:11:45Z")

</div>

Edit: Nevermind - I find a bug in the surrounding code. Thank you for all the input!
