Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
18d9f5a
added submodule
hosseinjafar Jan 20, 2025
ee4d8c4
trying setup a clean docker file and installation script
hosseinjafar Jan 20, 2025
56b1c0b
renamed docker folder
hosseinjafar Jan 20, 2025
1258c08
got the image bulding to work. plastimatch command runs on the cli. i…
hosseinjafar Jan 20, 2025
3da672b
made some slolid progress on the registration. we ge the input now, l…
hosseinjafar Jan 21, 2025
9a56389
put down the draft way to call register on plasti match. let's test i…
hosseinjafar Jan 21, 2025
a0ea798
downloaded the sample data for testing of pyplastimatch
hosseinjafar Jan 21, 2025
81d1845
wrote the first test
hosseinjafar Jan 21, 2025
3fe2516
runnign registration worked for the basic example case
hosseinjafar Jan 21, 2025
b04c7d9
just organized the docker file a bit better
hosseinjafar Jan 21, 2025
a32c97b
wrote a simple api for registration
hosseinjafar Jan 22, 2025
7659a4b
wrote a bash script to run the api
hosseinjafar Jan 22, 2025
467221b
updated the input model in the api to handle paths to the temp_data
hosseinjafar Jan 22, 2025
a9b460c
added some print statement for the logs!
hosseinjafar Jan 23, 2025
6508b18
put a .env file that helps out docker compose with environment variables
hosseinjafar Jan 23, 2025
81bdca7
Update README.md
hosseinjafar Jan 25, 2025
93410c5
exporing transforms as nrrd
hosseinjafar Feb 13, 2025
0c7d8c8
made a bunch of changes to work with convert over the api. the change…
hosseinjafar Feb 26, 2025
695c4e8
simplified the api and tested it over the web. good to go to the next…
hosseinjafar Feb 26, 2025
c411d5e
very important bug fix. fastapi needs to be run with the run command …
hosseinjafar Mar 3, 2025
8a74f8c
played with the temp file paths
hosseinjafar Apr 16, 2025
43726dc
simpler docker i guess
hosseinjafar Jul 1, 2025
2a620f7
Merge branch 'main' of https://github.com/engerlab/pyplastimatch-brac…
hosseinjafar Jul 1, 2025
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
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
data_test/*
!data_test/.gitkeep
temp_data/*
!temp_data/.gitkeep
plastimatch-ubuntu_24_04
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down Expand Up @@ -103,6 +108,7 @@ celerybeat.pid

# Environments
.env
!docker_src/.env
.venv
env/
venv/
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "plastimatch"]
path = plastimatch
url = https://gitlab.com/plastimatch/plastimatch.git
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,14 @@ Note: provided you have a Google Cloud Platform project correctly set up, you wi

# Ubuntu 22.04 LTS Plastimatch Docker Container

If you want to test Plastimatch for Ubuntu 22.04 LTS, you can use the Docker image we shared for this purpose under `dockerfiles`.
If you want to test Plastimatch for Ubuntu 22.04 LTS, you can use the Docker image we shared for this purpose under `docker_src`.

## Build the Docker Container

To build the Ubuntu 22.04 LTS Platimatch Docker container, run the following commands from the root of the PyPlastimatch repository:

```
cd dockerfiles/
cd docker_src/

docker build --tag pypla_22.04 . --no-cache
```
Expand Down
Empty file added data_test/.gitkeep
Empty file.
3 changes: 3 additions & 0 deletions docker_src/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.trunk
.git
*build
1 change: 1 addition & 0 deletions docker_src/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
HOST_HOME=${HOME}
21 changes: 21 additions & 0 deletions docker_src/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
FROM ubuntu:latest

RUN apt-get update && apt-get install -y \
build-essential cmake git \
libboost-all-dev libssl-dev \
libzmq3-dev pkg-config \
python3 python3-pip \
python3-setuptools python3-wheel \
wget libdcmtk-dev libdlib-dev libfftw3-dev \
libinsighttoolkit5-dev \
libpng-dev libtiff-dev uuid-dev zlib1g-dev \
plastimatch
# apt-get clean && \
# rm -rf /var/lib/apt/lists/*

# RUN apt-get install pipx
RUN pip3 install --break-system-packages pyplastimatch
# RUN python3 -c 'from pyplastimatch.utils.install import install_precompiled_binaries; install_precompiled_binaries()'

# ENTRYPOINT ["plastimatch"]

7 changes: 7 additions & 0 deletions docker_src/command_docker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash
# to build the image and run the container
docker compose up --build -d
# to run the container without building the image
# docker compose up --no-build -d
# to enter the container
docker exec -it PyPlastimatch bash
15 changes: 15 additions & 0 deletions docker_src/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
services:
PyPlastimatch:
build:
context: ../
dockerfile: docker_src/Dockerfile
image: pyplastimatch:latest
container_name: PyPlastimatch
stdin_open: true # docker run -i
tty: true # docker run -t
environment:
- HOST_HOME=${HOST_HOME}
- DEBIAN_FRONTEND=noninteractive
volumes:
- ../:/root/Software/pyplastimatch
- ${HOST_HOME}:/root/YourLocalHome
22 changes: 0 additions & 22 deletions dockerfiles/Dockerfile

This file was deleted.

139 changes: 136 additions & 3 deletions pyplastimatch/pyplastimatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
import os
import json
import subprocess
from typing import Dict

from typing import Dict, List
from pathlib import Path
from collections import defaultdict
## ----------------------------------------

# FIXME: like this, every command is basically the same function with a line changed
Expand Down Expand Up @@ -44,8 +45,10 @@ def convert(verbose = True, path_to_log_file = None, return_bash_command = False
bash_command += ["plastimatch", "convert"]

for key, val in kwargs.items():
if "_" in key:
key = key.replace("_", "-")
bash_command += ["--%s"%(key), val]

if verbose:
print("\nRunning 'plastimatch convert' with the specified arguments:")
for key, val in kwargs.items():
Expand Down Expand Up @@ -282,3 +285,133 @@ def compare(path_to_reference_img, path_to_test_img, verbose = True) -> Dict[str
return comparison_dict

## ----------------------------------------

def register(
global_params: Dict[str, str],
stage_params_list: List[Dict[str, str]]
) -> Dict[str, float]:
"""
Purpose:
- To register two images using the plastimatch register command. The input to the command is a
text file called parm.txt. This text file has [Global] commands and [Stage] commands.
While the variables for the global commands stay the same throughout many stages of the registration,
the stage commands can be different for each stage. For the full list of these variables
look at https://plastimatch.org/registration_command_file_reference.html.
Here is an example of the parm.txt file:
[GLOBAL]
fixed=t5.mha
moving=t0.mha
image_out=warped.mha
vf_out=deformation.nrrd

[STAGE]
xform=bspline
grid_spac=50 50 50

[STAGE]
grid_spac=20 20 20

Inputs:
- global_params: dict := a dictionary containing the global parameters for the registration.
The possible global parameters are:
- fixed: str := the path to the fixed image.
- moving: str := the path to the moving image.
- fixed_roi: str := the path to the fixed region of interest.
- moving_roi: str := the path to the moving region of interest.
- fixed_landmarks: str := the path to the fixed landmarks.
- moving_landmarks: str := the path to the moving landmarks.
- warped_landmarks: str := the path to the warped landmarks.
- xform_in: str := the path to the input transformation.
- xform_out: str := the path to the output transformation.
- vf_out: str := the path to the output vector field.
- img_out: str := the path to the output image.
- img_out_fmt: str := the format of the output image.
- img_out_type: str := the type of the output image.
- resample_when_linear: bool := whether to resample when linear.
- logfile: str := the path to the log file.
- stage_params_list: List[Dict[str, str]] := a list of dictionaries containing the stage parameters for the registration.
please look at the plastimatch documentation for the full list of possible stage parameters.
Outputs:
- registration_summary: Dict[str, float] := a dictionary containing the registration summary.
The possible keys are:
- pth_registered_data: str := the path to the registered data.
- log_file: str := the path to the log file.
"""

# here are the possible global parameters for the registration
# some are optional, some are mandatory, we loop through them
# and create the command
global_param_possible_key_list = [
"fixed", "moving", "fixed_roi",
"moving_roi", "fixed_landmarks",
"moving_landmarks","warped_landmarks",
"xform_in", "xform_out", "vf_out",
"image_out", "img_out_fmt", "img_out_type",
"resample_when_linear", "logfile"
]
final_global_params = defaultdict(str)
# loop through the global parameters and create the command
for key in global_params:
if key in global_param_possible_key_list:
final_global_params[key] = global_params[key]

# make sure the required global parameters are present
if "fixed" not in final_global_params:
raise ValueError("The fixed image is required.")
if "moving" not in final_global_params:
raise ValueError("The moving image is required.")
if "image_out" not in final_global_params:
raise ValueError("The output image is required.")

# here are the possible stage parameters for the registration
# some are optional, some are mandatory, we loop through them
# and create the command
stage_param_possible_key_list = [
"fixed_landmarks", "moving_landmarks", "warped_landmarks", "xform_out",
"xform", "vf_out", "img_out", "img_out_fmt", "img_out_type",
"resample_when_linear", "background_max", "convergence_tol", "default_value",
"demons_acceleration", "demons_filter_width", "demons_homogenization", "demons_std",
"demons_gradient_type", "demons_smooth_update_field", "demons_std_update_field",
"demons_smooth_deformation_field", "demons_std_deformation_field", "demons_step_length",
"grad_tol", "grid_spac", "gridsearch_min_overlap", "histoeq", "landmark_stiffness",
"lbfgsb_mmax", "mattes_fixed_minVal", "mattes_fixed_maxVal", "mattes_moving_minVal",
"mattes_moving_maxVal", "max_its", "max_step", "metric", "mi_histogram_bins", "min_its",
"min_step", "num_hist_levels_equal", "num_matching_points", "num_samples", "num_samples_pct",
"num_substages","optim", "optim_subtype", "pgtol", "regularization", "diffusion_penalty",
"curvature_penalty", "linear_elastic_multiplier", "third_order_penalty",
"total_displacement_penalty", "lame_coefficient_1", "lame_coefficient_2", "res",
"res_mm", "res_mm_fixed", "res_mm_moving", "res_vox", "res_vox_fixed",
"res_vox_moving", "rsg_grad_tol", "ss", "ss_fixed", "ss_moving",
"threading", "thresh_mean_intensity", "translation_scale_factor",
]
# loop through the stage parameters and create the command for each stage
final_stage_params_list = []
for stage_params in stage_params_list:
final_stage_params = defaultdict(str)
for key in stage_params:
if key in stage_param_possible_key_list:
final_stage_params[key] = stage_params[key]
final_stage_params_list.append(final_stage_params)

# create the parm.txt file in the same directory as image_out
out_dir = Path(final_global_params["image_out"]).parent
os.makedirs(out_dir, exist_ok=True)
parm_txt_path = out_dir.joinpath("parm.txt")
param_txt = "[Global]\n"
for key in final_global_params:
param_txt += f"{key}={final_global_params[key]}\n"
param_txt += "\n"
for stage in final_stage_params_list:
param_txt += "[Stage]\n"
for key in stage:
param_txt += f"{key}={stage[key]}\n"
param_txt += "\n"

with open(parm_txt_path, "w") as f:
f.write(param_txt)

command = ["plastimatch", "register", str(parm_txt_path)]
try:
registration_summary = subprocess.run(command, capture_output = True, check = True)
except Exception as e:
print(e)
Empty file added pyplastimatch/tests/__init__.py
Empty file.
22 changes: 22 additions & 0 deletions pyplastimatch/tests/test_register.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from pyplastimatch import register

def test_register():
pth_static = "../data_test/registration-tutorial/t5.mha"
pth_moving = "../data_test/registration-tutorial/t0.mha"
pth_output = "../data_test/test_output/registered.nrrd"

global_params = {
"fixed" : f"{pth_static}",
"moving" : f"{pth_moving}",
"image_out" : f"{pth_output}",
}

stage_params_list = [
{
"xform": "bspline"
}
]
register(global_params, stage_params_list)

if __name__ == "__main__":
test_register()
Loading