---
# System prepended metadata

title: Registration pipeline outside of CemrgApp

---

# Registration pipeline outside of CemrgApp
This example uses CINE and LGE images from Abdul's. 
## Data
Two folders, each with an `Images` and a `masks` subfolders. 
+ `Cine_dataset`
+ `LGE_images_masks`

The data tree looks as follows: 
```
❯ tree .
├── Cine_dataset
│   ├── images
│   │   ├── L71_0000.nii.gz
│   │   └── N93_0000.nii.gz
│   └── masks
│       ├── L71_0000_gt.nii.gz
│       └── N93_0000_gt.nii.gz
└── LGE_images_masks
    ├── images
    │   ├── L71LGE_high-res_psir_3slice_MAG-111_0000.nii.gz
    │   ├── L71LGE_high-res_psir_3slice_PSIR-112_0000.nii.gz (*)
    │   ├── N93LGE_high-res_psir_stack_MAG-105_0000.nii.gz
    │   └── N93LGE_high-res_psir_stack_PSIR-106_0000.nii.gz  (*)
    └── masks
        ├── MASK_L71LGE_high-res_psir_3slice_MAG-111.nii.gz
        ├── MASK_L71LGE_high-res_psir_3slice_PSIR-112.nii.gz (*)
        ├── MASK_N93LGE_high-res_psir_stack_MAG-105.nii.gz
        └── MASK_N93LGE_high-res_psir_stack_PSIR-106.nii.gz  (*)
```

Two images: `L71_0000` and `N93_0000`, each with a corresponding CINE 
segmentation and corresponding LGE images and masks. 

We focus on the ones with the `PSIR`, marked with a `(*)`.

## Registration
We need to get the deformation information file (dof, or DFV). 
We need to use MIRTK, these executables come installed by default with CemrgApp.

### Using the user interface
CemrgApp (v2.3-rc6) has a built in function to register, transform images, and 
transform meshes. 

**1. Navigate the menus at the top of the UI: **

Window > Show View > Cemrg Common Tools, 

then click on the **External Tools (MIRTK)**  button, three options pop out: 
+ Register
+ Transform (allows for images or meshes)
+ Inverse Register 

**2. Click on Register**

1. Select the root folder of your data
2. Use the UI to select:
    +  the Moving file (LGE)
    +  the Target/Fixed file (the Cine)
    +  Registration model (Rigid, Affine, or Rigid+Affine)
    +  The name of the registration file (optional, default=`MODEL.dof`) 
3. Click OK to start the registration 

The file will be saved in the root folder you selected at the beginning.

> Note that another option is to create different folders per case, put all the necessary files (cine, lge, and lge-segmentation) and keep everything contained per case.

> **ALSO NOTE:** CemrgApp will give you the command to run in the log file. Only see the terminal from where you're running the app. 

### Using the command line
CemrgApp utilises the same binaries. Go to the folder you have CemrgApp in, 
inside the `bin/MLib` folder you will find all the MIRTK tools you need. 

To do a registration, the command is: 
```shell!
register MOVING FIXED -dofout DISPLACEMENT_FILE -model MODEL -verbose 3
```

In the case of our example, 
```shell
PATH_TO_CEMRGAPP/bin/MLib/register \
    PATH_TO_DATA/LGE_images_masks/images/L71LGE_high-res_psir_3slice_PSIR-112_0000.nii.gz    \
    PATH_TO_DATA/Cine_dataset/images/L71_0000.nii.gz \
    -dofout PATH_TO_DATA/Rigid.dof \
    -model Rigid \
    -verbose 3
```

From here, you get a `Rigid.dof` file!

## Transforming 

### Using the UI
This is simple, similar to the registration, but pick the **Transform** button 
instead of the Register one.

### On the command line 
Usage is
```shell!
transform-image LGE_SEGMENTATION OUTPUT_SEG_NAME -dofin DISPLACEMENT_FILE 
```
In the case of our example:
```
PATH_TO_CEMRGAPP/bin/MLib/transform-image \
    PATH_TO_DATA/LGE_images_masks/masks/L71LGE_high-res_psir_3slice_PSIR-112.nii.gz \
    PATH_TO_DATA/Cine_dataset/masks/tx_L71LGE_high-res_psir_3slice_PSIR-112-by-Rigid.nii \
    -dofin PATH_TO_DATA/Rigid.dof 
```

### Transform meshes (vtk files)

The command is very similar: 
```shell!
transform-points VTK_INPUT VTK_OUTPUT -dofin DISPLACEMENT_FILE 
```

> Note that `DISPLACEMENT_FILE=Rigid.dof` we got from doing the registration 


## How to read the dof file
For this, use the terminal. In the same `MLib` folder described before, 
do this:

```
info PATH_TO_DATA/Rigid.dof
```

You will see the output like: 
```
> info Rigid.dof 
tx  =  -0.8649  ty  =   1.0436  tz  =   0.2945
rx  =  -0.6644  ry  =  -0.0855  rz  =  -0.4600
```

Save your deformation file like: 
```
> info Rigid.dof  >> transform_file.txt
```

You can then use the following python example script to 
load the file as numpy 
```python!
# rigid_transform.py

import numpy as np
import re
from scipy.spatial.transform import Rotation as R

def load_rigid_transform(filepath, degrees=True, euler_order='xyz'):
    """
    Reads a rigid transform file with format:
    tx = <val> ty = <val> tz = <val>
    rx = <val> ry = <val> rz = <val>

    Returns:
        translation (np.ndarray): shape (3,)
        rotation_matrix (np.ndarray): shape (3, 3)
    """
    with open(filepath, 'r') as f:
        content = f.read()

    # Extract floats
    numbers = list(map(float, re.findall(r"[-+]?\d*\.\d+|\d+", content)))
    if len(numbers) != 6:
        raise ValueError("Expected 6 values (tx ty tz rx ry rz), got: {}".format(numbers))

    tx, ty, tz = numbers[0:3]
    rx, ry, rz = numbers[3:6]

    # Euler to rotation matrix
    rotation = R.from_euler(euler_order, [rx, ry, rz], degrees=degrees)
    rotation_matrix = rotation.as_matrix()

    translation = np.array([tx, ty, tz])

    return translation, rotation_matrix

def build_transform_matrix(translation, rotation_matrix):
    """
    Builds a 4x4 homogeneous transformation matrix from translation and rotation.
    """
    transform = np.eye(4)
    transform[:3, :3] = rotation_matrix
    transform[:3, 3] = translation
    return transform

# Optional CLI
if __name__ == "__main__":
    import sys
    if len(sys.argv) != 2:
        print("Usage: python rigid_transform.py <transform_file.txt>")
        sys.exit(1)

    translation, rotation_matrix = load_rigid_transform(sys.argv[1])
    transform = build_transform_matrix(translation, rotation_matrix)

    print("Translation vector:", translation)
    print("Rotation matrix:\n", rotation_matrix)
    print("Full 4x4 transformation matrix:\n", transform)

```
> Abdul has the code to apply the translation vector and rotation matrix 

