Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
501 changes: 501 additions & 0 deletions ANTsPy/Analysis.md

Large diffs are not rendered by default.

155 changes: 155 additions & 0 deletions ANTsPy/Average.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# ANTsPy-III: Average tab, an average reference volume

Previous: [ANTsPy-II: Group-wise tab, rigid alignment to the reference](Groupwise_rigid.md) | Next: [ANTsPy-IV: Template tab, building a population template](Template.md)

---

Now we'll create an average of all rigidly aligned specimens. This becomes our unbiased initial reference volume to initialize the iterative template building procedure.

## Open ANTsPyRegistration Module - Average Tab

1. In the **ANTsPyRegistration** module
2. Click the **"Average"** tab

## Configure Average Settings

1. **Input directory:** Click the folder icon
- Navigate to `ANTsamples/RigidAligned/`
- Select the folder containing all rigidly aligned volumes
- The module will automatically find all .nii.gz files in this directory

2. **Output Volume:** Click the dropdown
- Select **"Create new Volume"**
- It will create a node called `Volume`
- Rename it to `RigidAverage_Template` (click on the name to edit)

## Run Averaging

1. Click **"Compute Average"**

2. **What happens:**
- The module loads all .nii.gz files from the input directory
- Computes the voxel-wise mean across all volumes
- Creates the output averaged volume
- **Time estimate:** 1-2 minutes depending on image size

3. **Completion:**
- The averaged volume `RigidAverage_Template` appears in the Data module
- Verify it loaded correctly by displaying in slice viewers


<img src="images/05_average.png" width="900">

## Save the Average Template

1. Right-click `RigidAverage_Template` in the Data module
2. Select **"Export to file..."**
3. Save as `ANTsamples/RigidAverage_Template.nii.gz`

## Create Average Landmarks (REQUIRED)

**Critical:** You must average the landmark positions to match your averaged volume. There is no tool in ANTsPy extension to do that. We will use a simple python script to do this in Slicer.

1. **Load all transformed landmark files:**
- `File → Add Data`
- Navigate to `ANTsamples/RigidAligned/`
- Select all 30 `*-transformed.mrk.json` files
- Click `Open`, then `OK`

2. **Average the landmarks using Python:**
- Go to **Python Interactor** (View → Python Interactor)
- Run this script:

```python
import numpy as np
import slicer

# List all loaded landmark nodes (the transformed ones from RigidAligned folder)
# Adjust these names to match what was loaded (typically specimen_-transformed)
landmarkNames = [
"129S1_SVLMJ_-transformed",
"129X1_SVJ_-transformed",
"AKR_J_-transformed",
"A_J_-transformed",
"B6AF1_J_-transformed",
"B6D2F1_J_-transformed",
"BALB_CBYJ_-transformed",
"BALB_CJ_-transformed",
"BTBR_T_Itpr3tf_j_-transformed",
"C3H_HEJ_-transformed",
"C3H_HEOUJ_-transformed",
"C57BL6_J_-transformed",
"C57BL_10J_-transformed",
"C57BL_6NJ_-transformed",
"C57L_J_-transformed",
"CAF1_J_-transformed",
"CAST_EIJ_-transformed",
"CB6F1_J_-transformed",
"CBA_CAJ_-transformed",
"CBA_J_-transformed",
"DBA_1J_-transformed",
"DBA_2J_-transformed",
"FVB_NJ_-transformed",
"MRL_MPJ_-transformed",
"NOD_SHILTJ_-transformed",
"NU_J_-transformed",
"NZBWF1_J_-transformed",
"NZW_LACJ_-transformed",
"SJL_J_-transformed",
"TALLYHO_JNGJ_-transformed"
]

# Get landmark nodes
markupNodes = [slicer.util.getNode(name) for name in landmarkNames]

# Get point arrays
pointArrays = [slicer.util.arrayFromMarkupsControlPoints(node) for node in markupNodes]

# Verify all have same number of points
numPoints = [arr.shape[0] for arr in pointArrays]
if len(set(numPoints)) != 1:
print(f"ERROR: Not all landmark sets have same number of points: {set(numPoints)}")
else:
print(f"All {len(pointArrays)} landmark sets have {numPoints[0]} points")

# Compute average
avgPoints = np.mean(pointArrays, axis=0)

# Create new markup node
avgMarkups = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLMarkupsFiducialNode', 'RigidAverage_Landmarks')

# Add averaged points
for i in range(avgPoints.shape[0]):
avgMarkups.AddControlPoint(avgPoints[i])

print(f"Average landmarks created: RigidAverage_Landmarks with {avgPoints.shape[0]} points")
```

3. Save the averaged landmarks:
- Right-click `RigidAverage_Landmarks` in Data module
- Export to file → `ANTsamples/RigidAverage_Landmarks.mrk.json`

**Verify:** The averaged landmarks should have 45 points (same as each individual specimen) and be positioned at the mean location of all specimens' landmarks.

## Discussion: Reference Specimen Bias

**Important considerations:**

1. **Shape bias is reduced but not eliminated:**
- The rigid average reduces bias from any single specimen
- However, if your sample is not representative of the full population, bias remains
- Example: If all specimens are adult males, the template won't represent females/juveniles

2. **The reference affects final template geometry:**
- Template building is iterative, but initial geometry influences convergence
- Very different initial references may lead to slightly different final templates
- For most analyses, this effect is small if you use 2+ iterations

3. **Alternative: No initial template:**
- Setting "Initial Template" to `None` it uses the first sample in your pool as the reference. We don't advise doing that except for testing purposes.

**For this tutorial:** Using a rigid average provides a good balance between computational efficiency and minimizing bias.

---

Previous: [ANTsPy-II: Group-wise tab, rigid alignment to the reference](Groupwise_rigid.md) | Next: [ANTsPy-IV: Template tab, building a population template](Template.md)
187 changes: 187 additions & 0 deletions ANTsPy/Data_and_reference.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
# ANTsPy-I: Data and reference specimen

This part introduces the data and prepares the reference specimen used in the following parts. See the [ANTsPy tutorial overview](README.md) for all parts.

---

## Prerequisites

### Software Requirements

#### 3D Slicer
- Download and install the **latest stable** version of 3D Slicer from [slicer.org](https://download.slicer.org/)

#### SlicerANTsPy Extension
Install the ANTsPy Extension from the Extension Catalogue

### Hardware Recommendations
We advise to run this tutorial using [MorphoCloudInstances](https://morphocloud.org) as registration operations are memory and compute intensive. Standard MorphoCloud instances (g3.l) provide 60GB of RAM and 16 cores.
If you plan to use your own computer, we advise using a computer with at least **16G of RAM**. Similarly we advise using a **CPU** with many cores as the registration will benefit from increased parallelism.
---

## Step 1: Obtaining the Data

### Clone the Repository

Open a terminal (Mac/Linux) or Git Bash (Windows) and run:

```bash
cd ~/Desktop
git clone https://github.com/muratmaga/ANTsamples.git
```

This will create a folder `ANTsamples` with the following structure:

```
ANTsamples/
├── LMs/ # 30 landmark files (.mrk.json)
└── volumes/ # 30 volume files (.nii.gz)
```


### Verify the Data

Check that you have 30 paired files:

```bash
cd ANTsamples
ls volumes/*.nii.gz | wc -l # Should show: 30
ls LMs/*.mrk.json | wc -l # Should show: 30
```

### Sample List

The dataset includes these mouse strains (we'll use all 30 for this tutorial):

- **C57BL6_J_** - C57BL/6J (most common laboratory strain)
- **BALB_CJ_** - BALB/cJ
- **DBA_1J_** - DBA/1J
- **DBA_2J_** - DBA/2J
- **C3H_HEJ_** - C3H/HeJ
- **AKR_J_** - AKR/J
- **129S1_SVLMJ_** - 129S1/SvlmJ
- **FVB_NJ_** - FVB/NJ
- ... and 22 more strains

---

## Step 2: Loading Data into 3D Slicer

### Launch 3D Slicer and Load Sample Volumes

1. Open 3D Slicer
1. Go to `File → Add Data`
2. Click `Choose File(s) to Add`
3. Navigate to `ANTsamples/volumes/`
4. Select these files (hold Ctrl/Cmd to select multiple):
- `C57BL6_J_.nii.gz`
- `BALB_CJ_.nii.gz`
- `DBA_2J_.nii.gz`
5. Click `Open`, then `OK`

### Load Corresponding Landmarks

1. Go to `File → Add Data`
2. Click `Choose File(s) to Add`
3. Navigate to `ANTsamples/LMs/`
4. Select the corresponding landmark files:
- `C57BL6_J_.mrk.json`
- `BALB_CJ_.mrk.json`
- `DBA_2J_.mrk.json`
5. Click `Open`, then `OK`

### Visualize the Data

1. In the **Data** module, you should see:
- 3 volumes (scalar volumes)
- 3 markups (fiducial nodes with 45 points each)

2. To view a volume:
- Click on `C57BL6_J_` in the Data module
- It will appear in the slice viewers (Red, Yellow, Green windows)
- Use the mouse wheel to scroll through slices
- Use the **3D** view to see the full volume

3. To view landmarks:
- In the **Markups** module, select `C57BL6_J__1` from the dropdown (a landmark file loaded after a volume with the same name gets the suffix `_1`)
- Landmarks will appear as small spheres on the skull
- Adjust visibility/size in the Display section if needed


<img src="images/01_loaded_data.png" width="900">


### Understanding the data better

- None of the samples are oriented canonically; slice planes to not correspond to anatomical planes.
- Landmarks are in millimeters (mm)
- Each specimen has 45 anatomical landmarks on the skull

---

## Step 3: Prepare a Reference Specimen (Crop Volume)

Before building the template, we need to prepare a reference specimen that will serve as the initial template. This involves reorienting the specimen to align with anatomical planes and creating an average from rigidly aligned samples.

### Why Use a Reference Specimen?

Using a reference specimen (rather than starting from scratch) has advantages and disadvantages:

**Advantages:**
- Faster convergence during template building
- More anatomically meaningful starting point
- Easier to interpret results in consistent anatomical orientations

**Disadvantages:**
- **Shape bias:** The final template may retain some shape characteristics of the reference specimen
- **Size bias:** Initial size of the reference influences the template
- **Asymmetry bias:** If the reference has asymmetries, these may persist
- **Selection bias:** Choosing one strain over others introduces systematic bias

**Best Practice:** To minimize bias, we'll create an average of rigidly aligned specimens rather than using an actual specimen from our dataset as references. This provides a reasonable starting point while reducing individual specimen bias.

### Reorient a Reference Specimen

We'll use the **NZBWF1_J_** specimen as our initial reference and reorient it so the major axes align with anatomical planes.

#### Load the Reference Specimen

0. Reset the scene to remove other data.
1. `File → Add Data`
2. Select `ANTsamples/volumes/NZBWF1_J_.nii.gz` and `ANTsamples/LMs/NZBWF1_J_.mrk.json`
3. Click `Open`, then `OK`. The landmarks are loaded as `NZBWF1_J__1`, because the volume already has the name `NZBWF1_J_`.

#### Open the Crop Volume Module

1. In the module search bar, type "Crop"
2. Select **Crop Volume**
3. Set **Input volume** to `NZBWF1_J_`, expand **Reorient volume** and click **Initialize**. This creates a transform, `Reorient_NZBWF1_J_`, and rotation handles in the slice and 3D views.
4. Rotate the volume with the handles until the anatomical planes are aligned with the slice views.

For detailed instructions, see the [CropVolume tutorial](https://github.com/SlicerMorph/Tutorials/blob/main/Slicer_Modules/Crop_Volume/Readme.MD#using-cropvolume-to-simulatenously-reorient-and-resample-your-data).

<img src="images/02_reorient_widget.png" width="900">

#### Reorient the Landmarks

**Important:** Do this before you apply the reorientation. Applying it deletes the `Reorient_NZBWF1_J_` transform, and the landmarks must be moved with the same transform.

1. Open the **Transforms** module and select `Reorient_NZBWF1_J_` as the **Active Transform**
2. Under **Apply transform**, move the landmarks (`NZBWF1_J__1`) to the **Transformed** list
3. Click **Harden transform** to make it permanent

#### Apply Reorientation

1. In **Crop Volume**, click **Apply** under **Reorient volume**. The rotation is written into the volume, and the `Reorient_NZBWF1_J_` transform is removed.
2. Resample the volume onto the anatomical axes: set **Input ROI** to **Create new ROI**, open the menu next to **Fit to Volume** and choose **Align to world axes + Resize**, click **Fit to Volume**, then click the main **Apply**.
3. The reoriented volume appears in the scene with the **cropped** suffix (`NZBWF1_J_ cropped`)
4. Verify in slice viewers that anatomical planes are aligned with slice views.
5. Save the result: Right-click `NZBWF1_J_ cropped` → Export to file
- Save as `ANTsamples/NZBWF1_J_reoriented.nii.gz`
6. Save the landmarks (`NZBWF1_J__1`) as `NZBWF1_J_reoriented.mrk.json` in the same folder.

<img src="images/03_reoriented.png" width="900">

---

Next: [ANTsPy-II: Group-wise tab, rigid alignment to the reference](Groupwise_rigid.md)
Loading
Loading