-
Notifications
You must be signed in to change notification settings - Fork 2
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
Save output with the same format as brainreg
#66
Open
IgorTatarnikov
wants to merge
34
commits into
main
Choose a base branch
from
output-deformation-fields
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,049
−105
Open
Changes from all commits
Commits
Show all changes
34 commits
Select commit
Hold shift + click to select a range
d02d294
Added output directory field
IgorTatarnikov 15bf1ea
WIP use output directory as output for elastix
IgorTatarnikov 807e034
Save the deformation fields in the brainreg format to the output dire…
IgorTatarnikov bc1b8cd
Save deformation fields as tiff not tif
IgorTatarnikov b7f79eb
Add function to save output from registration
IgorTatarnikov b2733e7
Update elastix default to save tiff not nii
IgorTatarnikov 189f52b
WIP writing brainreg output directory
IgorTatarnikov 84f010f
WIP calculate area of annotations
IgorTatarnikov e8f745a
Remap labels outside of float precision to allow transforming of anno…
IgorTatarnikov 2b96d46
Save all files as per brainreg, save the forward and inverse transfor…
IgorTatarnikov 75f70f5
Make ara-tools default options with 2 registration types
IgorTatarnikov d42ebc6
Changed convert_atlas_labels function to avoid weird edge cases
IgorTatarnikov e1a5c79
Merge branch 'main' into output-deformation-fields
IgorTatarnikov ec01d54
Update docstrings
IgorTatarnikov eea29a6
Add tests for dconverting atlas labels
IgorTatarnikov f766fdb
Updated docstring for convert_atlas_labels
IgorTatarnikov c713371
Fixed tests to account for updates for changes to transform select view
IgorTatarnikov afa7e51
Add pandas as explicit dependency
IgorTatarnikov a91f176
Update docstring for calculate_areas
IgorTatarnikov 574187b
Added tests for calculating area
IgorTatarnikov b23bd8f
Remove superfluous function
IgorTatarnikov d46f771
Remove rigid transformation option
IgorTatarnikov 862b616
Fixed tests to account for removing rigid transformation option
IgorTatarnikov a3db01b
Add new test data
IgorTatarnikov 47e8683
Update register.py testing such that affine only transforms are run o…
IgorTatarnikov 116c14c
Added tests for register
IgorTatarnikov 87f7c58
Tests for calculate_deformation_field, transform_image
IgorTatarnikov 5f80694
Add tolerance when comparing transform parameter objects
IgorTatarnikov f53e02c
Add slack for all floating point parameters
IgorTatarnikov b073fed
Ensure example_mouse_100um is loaded for testing the registration_widget
IgorTatarnikov b4ceda3
GetImage not View from annotation array
IgorTatarnikov b10f636
Fixed key error for transforming annotation
IgorTatarnikov 1f18fbb
Removed non-linear regression test files
IgorTatarnikov 01f4ce2
merge main
adamltyson File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,7 @@ name: tests | |
on: | ||
push: | ||
branches: | ||
- '*' | ||
- 'main' | ||
tags: | ||
- '*' | ||
pull_request: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,22 @@ | ||
from typing import List, Tuple | ||
from pathlib import Path | ||
from typing import List, Optional, Tuple | ||
|
||
import itk | ||
import numpy as np | ||
import numpy.typing as npt | ||
from brainglobe_atlasapi import BrainGlobeAtlas | ||
|
||
|
||
def get_atlas_by_name(atlas_name: str) -> BrainGlobeAtlas: | ||
""" | ||
Get a BrainGlobeAtlas object by its name. | ||
|
||
Parameters | ||
---------- | ||
atlas_name : str | ||
The name of the atlas. | ||
|
||
Returns | ||
------- | ||
BrainGlobeAtlas | ||
The BrainGlobeAtlas object. | ||
""" | ||
atlas = BrainGlobeAtlas(atlas_name) | ||
|
||
return atlas | ||
from brainglobe_registration.utils.utils import ( | ||
convert_atlas_labels, | ||
restore_atlas_labels, | ||
) | ||
|
||
|
||
def run_registration( | ||
atlas_image, | ||
moving_image, | ||
annotation_image, | ||
atlas_image: npt.NDArray, | ||
moving_image: npt.NDArray, | ||
parameter_lists: List[Tuple[str, dict]], | ||
) -> Tuple[npt.NDArray, itk.ParameterObject, npt.NDArray]: | ||
output_directory: Optional[Path] = None, | ||
) -> Tuple[npt.NDArray, itk.ParameterObject]: | ||
""" | ||
Run the registration process on the given images. | ||
|
||
|
@@ -40,19 +26,17 @@ | |
The atlas image. | ||
moving_image : npt.NDArray | ||
The moving image. | ||
annotation_image : npt.NDArray | ||
The annotation image. | ||
parameter_lists : List[tuple[str, dict]], optional | ||
The list of parameter lists, by default None | ||
parameter_lists : List[tuple[str, dict]] | ||
The list of registration parameters, one for each transform. | ||
output_directory : Optional[Path], optional | ||
The output directory for the registration results, by default None | ||
|
||
Returns | ||
------- | ||
npt.NDArray | ||
The result image. | ||
itk.ParameterObject | ||
The result transform parameters. | ||
npt.NDArray | ||
The transformed annotation image. | ||
""" | ||
# convert to ITK, view only | ||
atlas_image = itk.GetImageViewFromArray(atlas_image).astype(itk.F) | ||
|
@@ -66,33 +50,200 @@ | |
parameter_object = setup_parameter_object(parameter_lists=parameter_lists) | ||
|
||
elastix_object.SetParameterObject(parameter_object) | ||
|
||
# update filter object | ||
elastix_object.UpdateLargestPossibleRegion() | ||
|
||
# get results | ||
result_image = elastix_object.GetOutput() | ||
result_transform_parameters = elastix_object.GetTransformParameterObject() | ||
temp_interp_order = result_transform_parameters.GetParameter( | ||
|
||
if output_directory: | ||
file_names = [ | ||
f"{output_directory}/TransformParameters.{i}.txt" | ||
for i in range(len(parameter_lists)) | ||
] | ||
|
||
itk.ParameterObject.WriteParameterFile( | ||
result_transform_parameters, file_names | ||
) | ||
|
||
return ( | ||
np.asarray(result_image), | ||
result_transform_parameters, | ||
) | ||
|
||
|
||
def transform_annotation_image( | ||
annotation_image: npt.NDArray[np.uint32], | ||
transform_parameters: itk.ParameterObject, | ||
) -> npt.NDArray[np.uint32]: | ||
""" | ||
Transform the annotation image using the given transform parameters. | ||
Sets the FinalBSplineInterpolationOrder to 0 to avoid interpolation. | ||
Resets the FinalBSplineInterpolationOrder to its original value after | ||
transforming the annotation image. | ||
|
||
Parameters | ||
---------- | ||
annotation_image : npt.NDArray | ||
The annotation image. | ||
transform_parameters : itk.ParameterObject | ||
The transform parameters. | ||
|
||
Returns | ||
------- | ||
npt.NDArray | ||
The transformed annotation image. | ||
""" | ||
adjusted_annotation_image, mapping = convert_atlas_labels(annotation_image) | ||
|
||
annotation_image = itk.GetImageFromArray(adjusted_annotation_image).astype( | ||
itk.F | ||
) | ||
temp_interp_order = transform_parameters.GetParameter( | ||
0, "FinalBSplineInterpolationOrder" | ||
) | ||
result_transform_parameters.SetParameter( | ||
"FinalBSplineInterpolationOrder", "0" | ||
transform_parameters.SetParameter("FinalBSplineInterpolationOrder", "0") | ||
|
||
transformix_object = itk.TransformixFilter.New(annotation_image) | ||
transformix_object.SetTransformParameterObject(transform_parameters) | ||
transformix_object.UpdateLargestPossibleRegion() | ||
|
||
transformed_annotation = transformix_object.GetOutput() | ||
|
||
transform_parameters.SetParameter( | ||
"FinalBSplineInterpolationOrder", temp_interp_order | ||
) | ||
transformed_annotation_array = np.asarray(transformed_annotation).astype( | ||
np.uint32 | ||
) | ||
|
||
annotation_image_transformix = itk.transformix_filter( | ||
annotation_image.astype(np.float32, copy=False), | ||
result_transform_parameters, | ||
transformed_annotation_array = restore_atlas_labels( | ||
transformed_annotation_array, mapping | ||
) | ||
|
||
return transformed_annotation_array | ||
|
||
|
||
def transform_image( | ||
image: npt.NDArray, | ||
transform_parameters: itk.ParameterObject, | ||
) -> npt.NDArray: | ||
""" | ||
Transform the image using the given transform parameters. | ||
|
||
Parameters | ||
---------- | ||
image: npt.NDArray | ||
The image to transform. | ||
transform_parameters: itk.ParameterObject | ||
The transform parameters. | ||
|
||
Returns | ||
------- | ||
npt.NDArray | ||
The transformed image. | ||
""" | ||
image = itk.GetImageViewFromArray(image).astype(itk.F) | ||
|
||
transformix_object = itk.TransformixFilter.New(image) | ||
transformix_object.SetTransformParameterObject(transform_parameters) | ||
transformix_object.UpdateLargestPossibleRegion() | ||
|
||
transformed_image = transformix_object.GetOutput() | ||
|
||
return np.asarray(transformed_image) | ||
|
||
|
||
def calculate_deformation_field( | ||
moving_image: npt.NDArray, | ||
transform_parameters: itk.ParameterObject, | ||
) -> npt.NDArray: | ||
""" | ||
Calculate the deformation field for the moving image using the given | ||
transform parameters. | ||
|
||
Parameters | ||
---------- | ||
moving_image : npt.NDArray | ||
The moving image. | ||
transform_parameters : itk.ParameterObject | ||
The transform parameters. | ||
|
||
Returns | ||
------- | ||
npt.NDArray | ||
The deformation field. | ||
""" | ||
transformix_object = itk.TransformixFilter.New( | ||
itk.GetImageViewFromArray(moving_image).astype(itk.F), | ||
transform_parameters, | ||
) | ||
transformix_object.SetComputeDeformationField(True) | ||
|
||
transformix_object.UpdateLargestPossibleRegion() | ||
|
||
# Change from ITK to numpy axes ordering | ||
deformation_field = itk.GetArrayFromImage( | ||
transformix_object.GetOutputDeformationField() | ||
)[..., ::-1] | ||
|
||
# Cleanup files generated by elastix | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there any conceivable reason to keep these files, e.g. in a "Debug" mode that could be chosen by the user? |
||
(Path.cwd() / "DeformationField.tiff").unlink(missing_ok=True) | ||
|
||
return deformation_field | ||
|
||
|
||
def invert_transformation( | ||
fixed_image: npt.NDArray, | ||
parameter_list: List[Tuple[str, dict]], | ||
transform_parameters: itk.ParameterObject, | ||
output_directory: Optional[Path] = None, | ||
) -> itk.ParameterObject: | ||
|
||
fixed_image = itk.GetImageFromArray(fixed_image).astype(itk.F) | ||
|
||
elastix_object = itk.ElastixRegistrationMethod.New( | ||
fixed_image, fixed_image | ||
) | ||
|
||
parameter_object_inverse = setup_parameter_object(parameter_list) | ||
|
||
elastix_object.SetInitialTransformParameterObject(transform_parameters) | ||
|
||
elastix_object.SetParameterObject(parameter_object_inverse) | ||
|
||
elastix_object.UpdateLargestPossibleRegion() | ||
|
||
num_initial_transforms = transform_parameters.GetNumberOfParameterMaps() | ||
|
||
result_image = elastix_object.GetOutput() | ||
out_parameters = elastix_object.GetTransformParameterObject() | ||
result_transform_parameters = itk.ParameterObject.New() | ||
|
||
for i in range( | ||
num_initial_transforms, out_parameters.GetNumberOfParameterMaps() | ||
): | ||
result_transform_parameters.AddParameterMap( | ||
out_parameters.GetParameterMap(i) | ||
) | ||
|
||
result_transform_parameters.SetParameter( | ||
"FinalBSplineInterpolationOrder", temp_interp_order | ||
0, "InitialTransformParameterFileName", "NoInitialTransform" | ||
) | ||
|
||
if output_directory: | ||
file_names = [ | ||
f"{output_directory}/InverseTransformParameters.{i}.txt" | ||
for i in range(len(parameter_list)) | ||
] | ||
|
||
itk.ParameterObject.WriteParameterFiles( | ||
result_transform_parameters, file_names | ||
) | ||
|
||
return ( | ||
np.asarray(result_image), | ||
result_transform_parameters, | ||
np.asarray(annotation_image_transformix), | ||
) | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 0 additions & 24 deletions
24
brainglobe_registration/parameters/elastix_default/rigid.txt
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it make sense to use pathlib here?