# Interop with the `mitk` package This page describes how `mitk-workbench-remote` integrates with the native `mitk` Python package (the pybind11 bindings shipped with MITK source code and published as the `mitk-python` distribution (imported as `mitk`) on [PyPI](https://pypi.org/project/mitk-python/)). ## Installing both packages The `mitk` package is part of the MITK C++ build (so you can directly build it on your own with the whole of MITK). But the easiest way is to use the published standalone PyPI distributions To install `mitk-workbench-remote` with the optional `mitk` dependency declaration: ```bash pip install "mitk-workbench-remote[mitk]" ``` `mitk-python` currently ships CPython 3.12 wheels only, so the `mitk` and `layout` extras require Python 3.12; on other versions the install fails fast. The remote-control client itself runs on Python 3.11+. If you want to use a self build `mitk` wheel, you have to install the wheel generated by the MITK build and that can be found in the `MITK-build` directory and install `mitk-workbench-remote` without the extra. ## Three ways to pull data `DataNode.get_data()` accepts an `as_type` keyword argument of type `DataRepresentation`: | `as_type` | `mitk` installed? | Return type | |---|---|---| | `AUTO` (default) | yes | `mitk.Image` | | `AUTO` (default) | no | `mw.Image` | | `REMOTE` | either | `mw.Image` | | `MITK` | yes | `mitk.Image` | | `MITK` | no | `ImportError` | ```python import mitk_workbench_remote as mw wb = mw.connect("http://localhost:8080") node = wb.storage["CT_Scan"] # AUTO: returns mitk.Image when mitk is available, mw.Image otherwise data = node.get_data() # Always a remote thin wrapper (no mitk dependency): mw_image = node.get_data(as_type=mw.DataRepresentation.REMOTE) # Always a native mitk.Image (ImportError if mitk absent): mitk_image = node.get_data(as_type=mw.DataRepresentation.MITK) ``` **Trade-offs:** - `AUTO` / `MITK` — pixel data is always copied; you get MITK's full geometry and property API. - `REMOTE` — pixel data is also copied (from NRRD), but the `mw.Image` wrapper is lighter and has no dependency on the `mitk` package. ## Uploading back `DataNode.set_data()` accepts any object handled by the converter registry, including `mitk.Image`. The `MitkImageConverter` is auto-registered whenever `mitk` is importable, so no code change is needed: ```python local = mw.Image(np.zeros((64, 64, 64), dtype=np.uint8)) mitk_img = local.to_mitk() # mw.Image → mitk.Image node.set_data(mitk_img) # converter picks up mitk.Image automatically ``` You can also convert in the other direction: ```python # node.get_data returns mitk.Image (if mitk is installed) mitk_img = node.get_data(as_type=mw.DataRepresentation.MITK) # Work with native MITK API print(mitk_img.get_spacing()) arr = np.asarray(mitk_img) # Push a modified version back node.set_data(mitk_img) ``` ## Property round-trip ### Inbound: `get_data(include_properties=True)` When `include_properties=True` is passed to `get_data()` and the result is a `mitk.Image`, the data-scope properties fetched from the REST server are applied to the `mitk.Image` via `set_property()`. The MITK C++ binding auto-wraps these scalar Python value types: | Python type | MITK property class | |---|---| | `bool` | `BoolProperty` | | `int` | `IntProperty` | | `float` | `FloatProperty` | | `str` | `StringProperty` | | `(r, g, b)` 3-tuple | `ColorProperty` | Properties of unknown complex types are returned by the REST API as `{"type": "...", "value": ...}` dicts. These are reconstructed into their original `BaseProperty` subclass via `mitk.BaseProperty.from_json()` and applied to the image. No properties are dropped on the inbound path. ### Outbound: `set_data(include_properties=True)` When `include_properties=True` is passed to `set_data()` with a `mitk.Image`, properties are extracted from the image and uploaded to the REST server. The converter calls `img.get_property(key)` for each property key, which returns a coerced Python-native value for all known types (same table as above). For unknown property types that have no native Python equivalent, the binding falls back to `BaseProperty.to_json()`, which is guaranteed on every property subclass and produces the `{"type": "...", "value": ...}` wire format understood by the REST API. No properties are silently dropped on the outbound path.