-
Notifications
You must be signed in to change notification settings - Fork 15
Description
Describe the bug
When using dm.register
sometimes an error is thrown indicating that the transform file is not found:
FileNotFoundError: No such file or directory '['/dataNAS/people/jdemarre/repeat_3T7T/Repeatability/results_April-04-2022/repeat001/3T/9582/elastix_reg_2/moving-0/TransformParameters.0.txt']' for output 'transform' of a Registration interface
If you look inside of the folder where the transform file should be you can find an elastix.log
file which includes the printout of what happened during the registration process. In my case, it turns out that there was an error in the registration process - in particular, the error was only being thrown when I passed a segmentation mask to help in the registration process and it was because the segmentation mask was too small:
Description: itk::ERROR: RandomCoordinateSampler(0x4330850): Could not find enough image samples within reasonable time. Probably the mask is too small
Looking under the hood at interregister
I noticed that __dilate_mask__
is called on all segmentation masks before they are passed to dm.register
:
DOSMA/dosma/scan_sequences/mri/cones.py
Lines 88 to 89 in 63dbc9e
if target_mask_path: | |
target_mask_path = self.__dilate_mask__(target_mask_path, out_path) |
To fix this problem, I re-implemented the __dilate_mask__
function and called it on the mask and then passed this dilated ask to the registration tool.
DOSMA/dosma/scan_sequences/scans.py
Line 267 in 76d834e
def __dilate_mask__( |
The Fix
To fix the problem, I created the following version of the __dilate_mask__
function and used it on my segmentation mask before passing the segmentation mask on to dm.register
. The main tweak is that it allows the user to specify if they want to receive a path
in return or if they want to receive the MedicalVolume
itself. Im wondering if this (or something like it) could be implemented as a utility function and then have __dilate_mask__
call this utility function. This way, users can access this as necessary for registration. An option could also be placed in dm.register
to dilate a mask before passing it on to the registration process => maybe this should be a default?
from dosma.defaults import preferences
import scipy.ndimage as sni
from dosma.utils import env, io_utils
from dosma.core.med_volume import MedicalVolume
from dosma.core.io import format_io_utils as fio_utils
def dilate_mask(
mask_path,
temp_path: str = env.temp_dir(),
dil_rate: float = preferences.mask_dilation_rate,
dil_threshold: float = preferences.mask_dilation_threshold,
return_path: bool=True
):
"""Dilate mask using gaussian blur and write to disk to use with Elastix.
Args:
mask_path (str | MedicalVolume): File path for mask or mask to use to use as
focus points for registration. Mask must be binary.
temp_path (str): Directory path to store temporary data.
dil_rate (`float`, optional): Dilation rate (sigma).
Defaults to ``preferences.mask_dilation_rate``.
dil_threshold (`float`, optional): Threshold to binarize dilated mask.
Must be between [0, 1]. Defaults to ``preferences.mask_dilation_threshold``.
return_path (`bool`, optional): Should a path be returned; if not, return the
dilated mask itself. Defaults to ``True``.
Returns:
str: File path of dilated mask.
Raises:
FileNotFoundError: If `mask_path` not valid file.
ValueError: If `dil_threshold` not in range [0, 1].
"""
if dil_threshold < 0 or dil_threshold > 1:
raise ValueError("'dil_threshold' must be in range [0, 1]")
if isinstance(mask_path, MedicalVolume):
mask = mask_path
elif os.path.isfile(mask_path):
mask = fio_utils.generic_load(mask_path, expected_num_volumes=1)
else:
raise FileNotFoundError("File {} not found".format(mask_path))
dilated_mask = (
sni.gaussian_filter(np.asarray(mask.volume, dtype=np.float32), sigma=dil_rate)
> dil_threshold
)
dilated_mask = np.asarray(dilated_mask, dtype=np.int8)
dilated_mask_volume = MedicalVolume(dilated_mask, affine=mask.affine)
if return_path is False:
return dilated_mask_volume
else:
fixed_mask_filepath = os.path.join(io_utils.mkdirs(temp_path), "dilated-mask.nii.gz")
dilated_mask_volume.save_volume(fixed_mask_filepath)
return fixed_mask_filepath
Desktop (please complete the following information):
- OS: Ubuntu 20.04 LTS
- Browser chrome
- Version 95.0.4638.69
Please also provide the output of the following code:
sys.platform linux
Python 3.8.5 (default, Sep 4 2020, 07:30:14) [GCC 7.3.0]
numpy 1.19.2
dosma 0.1.1 @/dataNAS/people/aagatti/miniconda/envs/dosma-ai/lib/python3.8/site-packages/dosma
h5py 2.10.0
nibabel 3.2.2
nipype 1.7.0
pandas 1.4.1
pydicom 2.2.2
scipy 1.5.2
skimage 0.19.2
tensorflow 2.2.0
keras 2.4.3
Additional context
Add any other context about the problem here.