Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation #49

Merged
merged 9 commits into from
Mar 28, 2024
89 changes: 87 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,95 @@

## Installation

With a Python 3.8+ environment, you can install eReg from [pypi.org](https://pypi.org/project/eReg/)
With a Python 3.8+ environment, you can install eReg from [pypi.org](https://pypi.org/project/eReg/).

1. Create a virtual environment

```sh
python3 -m venv venv_ereg ## using native python venv
# conda create -n venv_ereg python=3.8 ## using conda
```

2. Activate the virtual environment

```sh
source venv_ereg/bin/activate ## using native python venv
# conda activate venv_ereg ## using conda
```

3. Install eReg

```sh
pip install ereg
```

## TODO -
## Extending eReg

To extend eReg, you first need to install eReg from source. Clone the repository and install the package:

```sh
git clone https://github.com/BrainLesion/eReg.git
cd eReg
pip install -e .
```

## Usage

eReg can be used via the command line or as a Python package.

### Command Line Interface

The command line interface is available via the `ereg` command:

```sh
(venv_ereg) ~> ereg -h
usage: eReg version0.0.4.post76.dev0+0d89ce7 [-h] -m -t -o -c [-tff] [-lf] [-gt]

Simple registration.

options:
-h, --help show this help message and exit
-m , --movingImg The moving image to register. Can be comma-separated list of images or directory of images.
-t , --targetImg The target image to register to.
-o , --output The output. Can be single file or a directory.
-c , --config The configuration file to use.
-tff , --transfile Registration transform file; if provided, will use this transform instead of computing a new one or will save. Defaults to None.
-lf , --log_file The log file to write to. Defaults to None.
-gt , --gt The ground truth image.
```

### Pythonic Interface

The Pythonic interface is available via the `ereg` package, and can be used in two ways: as a functional interface or as an object-oriented interface.

#### Functional Interface

```python
from ereg import registration_function

ssim = registration_function(
target_image=target_image_file, # the target image, which can be either a file or SimpleITK.Image object
moving_image=moving_image_file, # the moving image, which can be either a file or SimpleITK.Image object
output_image=output_file, # the output image to save the registered image to
transform_file=transform_file, # the transform file to save the transform to; if already present, will use this transform instead of computing a new one
log_file=log_file, # the log file to write to
configuration=configuration_file, # the configuration file to use to customize the registration, and is optional
)
```

#### Object-Oriented Interface

```python
from ereg.registration import RegistrationClass

registration_obj = RegistrationClass(configuration_file) # the configuration file to use to customize the registration, and is optional
registration_obj.register(
target_image=target_image_file, # the target image, which can be either a file or SimpleITK.Image object
moving_image=moving_image_file, # the moving image, which can be either a file or SimpleITK.Image object
output_image=output_file, # the output image to save the registered image to
transform_file=transform_file, # the transform file to save the transform to; if already present, will use this transform instead of computing a new one
log_file=log_file, # the log file to write to
)
```

## TODO
9 changes: 2 additions & 7 deletions ereg/configurations/default_rigid.yaml
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
# Whether to use bias correction before registration (helpful to generate more accurate transforms at the cost of time). Default: false
bias: false

# The registration metric. Options: ["mattes_mutual_information", "ants_neighborhood_correlation", "correlation", "demons", "joint_histogram_mutual_information", "mean_squares"]
# this can be a list as well, which will then become a multi-metric registration using composite transforms [https://simpleitk.org/doxygen/latest/html/classitk_1_1simple_1_1CompositeTransform.html]
metric: mean_squares

## metric-specific parameters
metric_parameters: {
type: "mean_squares", # Options: ["mattes_mutual_information", "ants_neighborhood_correlation", "correlation", "demons", "joint_histogram_mutual_information", "mean_squares"]
histogram_bins: 50, # mattes_mutual_information, joint_histogram_mutual_information
radius: 5, # ants_neighborhood_correlation
intensityDifferenceThreshold: 0.001, # demons
varianceForJointPDFSmoothing: 1.5, # joint_histogram_mutual_information
}

# Optimizer. Options: ["gradient_descent", "regular_step_gradient_descent", "amoeba", "conjugate", "exhaustive", "gadient_descent_line_search", "lbfgsb", "lbfgsb2", "one_plus_one_evolutionary", "powell"]
optimizer: regular_step_gradient_descent

## optimizer-specific parameters
optimizer_parameters: {
type: "regular_step_gradient_descent", # Options: ["gradient_descent", "regular_step_gradient_descent", "amoeba", "conjugate", "exhaustive", "gradient_descent_line_search", "lbfgsb", "lbfgsb2", "one_plus_one_evolutionary", "powell"]
min_step: 1e-4, # regular_step_gradient_descent
max_step: 1.0, # gradient_descent, regular_step_gradient_descent
iterations: 200, # regular_step_gradient_descent, gradient_descent_line_search, gradient_descent, conjugate, lbfgsb, lbfgsb2
Expand Down
9 changes: 2 additions & 7 deletions ereg/configurations/sample_config.yaml
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
# Whether to use bias correction before registration (helpful to generate more accurate transforms at the cost of time). Default: false
bias: false

# The registration metric. Options: ["mattes_mutual_information", "ants_neighborhood_correlation", "correlation", "demons", "joint_histogram_mutual_information", "mean_squares"]
# this can be a list as well, which will then become a multi-metric registration using composite transforms [https://simpleitk.org/doxygen/latest/html/classitk_1_1simple_1_1CompositeTransform.html]
metric: mattes

## metric-specific parameters
metric_parameters: {
type: "mean_squares", # Options: ["mattes_mutual_information", "ants_neighborhood_correlation", "correlation", "demons", "joint_histogram_mutual_information", "mean_squares"]
histogram_bins: 50, # mattes_mutual_information, joint_histogram_mutual_information
radius: 5, # ants_neighborhood_correlation
intensityDifferenceThreshold: 0.001, # demons
varianceForJointPDFSmoothing: 1.5, # joint_histogram_mutual_information
}

# Optimizer. Options: ["gradient_descent", "regular_step_gradient_descent", "amoeba", "conjugate", "exhaustive", "gadient_descent_line_search", "lbfgsb", "lbfgsb2", "one_plus_one_evolutionary", "powell"]
optimizer: regular_step_gradient_descent

## optimizer-specific parameters
optimizer_parameters: {
type: "regular_step_gradient_descent", # Options: ["gradient_descent", "regular_step_gradient_descent", "amoeba", "conjugate", "exhaustive", "gadient_descent_line_search", "lbfgsb", "lbfgsb2", "one_plus_one_evolutionary", "powell"]
min_step: 1e-6, # regular_step_gradient_descent
max_step: 1.0, # gradient_descent, regular_step_gradient_descent
iterations: 1000, # regular_step_gradient_descent, gradient_descent_line_search, gradient_descent, conjugate, lbfgsb, lbfgsb2
Expand Down
17 changes: 9 additions & 8 deletions ereg/functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def registration_function(
target_image: Union[str, sitk.Image],
moving_image: Union[str, sitk.Image],
output_image: str,
configuration: str,
configuration: str = None,
transform_file: str = None,
log_file: str = None,
**kwargs,
Expand All @@ -22,18 +22,19 @@ def registration_function(
target_image (Union[str, sitk.Image]): The target image.
moving_image (Union[str, sitk.Image]): The moving image.
output_image (str): The output image.
config_file (str): The config file for the registration.
config_file (str, optional): The config file for the registration. Defaults to None.
transform_file (str, optional): The transform file. Defaults to None.

Returns:
float: The structural similarity index.
"""
if isinstance(configuration, str):
assert os.path.isfile(configuration), "Config file does not exist."
elif isinstance(configuration, dict):
pass
else:
raise ValueError("Config file must be a string or dictionary.")
if configuration is not None:
if isinstance(configuration, str):
assert os.path.isfile(configuration), "Config file does not exist."
elif isinstance(configuration, dict):
pass
else:
raise ValueError("Config file must be a string or dictionary.")

registration_obj = RegistrationClass(configuration)
registration_obj.register(
Expand Down
4 changes: 3 additions & 1 deletion ereg/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def update_parameters(
config_data = configuration
else:
raise ValueError(
"Configuration must be a string path pointing to a .yml file or dictionary."
"Configuration must be a string path pointing to a yaml/yml file or dictionary."
)

# Update only the keys present in the YAML file
Expand Down Expand Up @@ -294,8 +294,10 @@ def _get_transform_wrapper(self, transform: str, dim: int) -> sitk.Transform:
else:
return eval("sitk.Euler%dDTransform()" % (dim))
elif transform_wrap == "scaleversor":
assert dim == 3, "ScaleVersor only works for 3D images."
return sitk.ScaleVersor3DTransform()
elif transform_wrap == "scaleskewversor":
assert dim == 3, "ScaleSkewVersor only works for 3D images."
return sitk.ScaleSkewVersor3DTransform()
# transforms that have specifically defined dimensions
elif transform_wrap == "euler":
Expand Down
Loading