SimpleElastix
SimpleElastix copied to clipboard
SimpleElastix segfaults if an InitialTransformParameterFile itself contains `InitialTransformParametersFileName`
Following suggestion number 2 (http://lists.bigr.nl/pipermail/elastix/2016-December/002431.html), i.e. setting an InitialTransformParameterFile which itself contains InitialTransformParametersFileName
SimpleElastix segfaults during Execute()
. Removing/commenting InitialTransformParametersFileName
in the InitialTransformParameterFile resovles the issue but that way no chaining of TransformParameterFiles is possible. In any case, if SimpleElastix cannot support this, it should at least not segfault. Possibly connected to @kaspermarstal comment on https://github.com/SuperElastix/SimpleElastix/issues/119#issuecomment-320644930?
Can you attach a minimum working example that reproduces the problem? Fx a zip with a script, the parameter files and ideally also the images you use
Here it is. Checkout https://github.com/romangrothausmann/elastix_scripts at 3269906 (branch reg2tra+prevTra) and change into tests/recRegStack/ (https://github.com/romangrothausmann/elastix_scripts/tree/3269906cadcb12130298535f14cc9f8bf26a71ce/tests/recRegStack) and try this MWE.py:
import SimpleITK as sitk
fI= sitk.ReadImage("reg/2016_12_02_0101_s00_08.tif")
mI= sitk.ReadImage("2016_12_02_0101_s00_09.png")
selx=sitk.ElastixImageFilter()
selx.LogToFileOff()
selx.LogToConsoleOn()
selx.SetFixedImage(fI)
selx.SetFixedMask(fI != 0)
selx.SetMovingImage(mI)
pM= selx.ReadParameterFile("parameterFile.txt")
pM.erase('InitialTransformParametersFileName')
selx.SetParameterMap(pM)
selx.SetInitialTransformParameterFileName("reg/2016_12_02_0101_s00_08.txt")
print selx.GetInitialTransformParameterFileName(),
selx.Execute()
which segfaults for me with current selx (v0.10.0-663-gd756f638). If commenting InitialTransformParametersFileName in tests/recRegStack/reg/2016_12_02_0101_s00_08.txt the MWE works. It also works if InitialTransformParametersFileName is set to "NoInitialTransform".
From this commit develop uses a version of elastix that fixes the issue on my machine (see SuperElastix/elastix#31). Try it out and reopen if you still see the segfault.
Many thanks @kaspermarstal for looking into this. I gave SimpleElastix@648a0f01 a try but it seems to me that it still uses Elastix@5df7a7787 (https://github.com/SuperElastix/SimpleElastix/commit/555c73fe81aa5f685b376164facd8f33342332a0#diff-05d9a8114b8b2c2e3ee208209d415276R5) which does not include the fix in Elastix@6a7f9164108. I tried with Elastix checked out with develop, but then make stops with:
make[5]: *** No rule to make target '/opt/compilation/SimpleElastix_build/Elastix-build/bin/libelastix-4.8.a', needed by 'BufferImportExport'. Stop.
How should I proceed?
Ah. I might have missed some of open PRs for elastix and SuperElastix. Some of them are blocked until review. Just wait 'til they are merged :) Will ping this issue.
@kaspermarstal, noticed You did some more integration lately, so gave it another try with v1.0.1 and the develop branch. They compile all fine now, but the segfaults during execution remain. Are the PRs already integrated that should solve this issue?
It should be now!
Many thanks @kaspermarstal for the update. Sadly the segfault problems still remain. Did the MWE.py from above work for you when you ran it in branch "reg2tra+prevTra" (https://github.com/romangrothausmann/elastix_scripts/tree/reg2tra+prevTra)? You could also try the internal test of that repos by running make SE=/path/to/SE -C tests/recRegStack/ -B
, git status
should then tell if the test-results differ.
I can confirm though that your changes to SE and Elastix do make a difference in the test results for the branches "master" (https://github.com/romangrothausmann/elastix_scripts/tree/478cf9f166ca79a52552e01aa1049551d55d7a11) and "combT_01" (https://github.com/romangrothausmann/elastix_scripts/tree/338251381ec56ace8ff81be101eb59871e20c0e7) are now as expected. See for example the projection/average image "tests/recRegStack/reg/avg.png". (If you are happy with my ".gitconfig", execute git config --local include.path ../.gitconfig
and then git diff 6e1f7f573c9..338251381ec -- tests/recRegStack/reg/avg.png
will show (with the help of imagematick) the difference of the average image for the SE@33a6bbb6 and the earlier version.)
Please let me know if SE@33a6bbb6 does not segfault on your machine on branch "reg2tra+prevTra".
@kaspermarstal so do the MWE or the tests not segfault for You? Otherwise I would not say the issue should be closed since the problem is not yet resolved.
It seems TransformixImageFilter
suffers the same problem. At least it also segfaults if InitialTransformParametersFileName
is specified when using stfx.SetTransformParameterMap
(see commit 19fdb19 referenced above). @kaspermarstal should I open a separate Issue for this?
(Amazing that GH noticed I referenced this in a commit message)
Let's just keep the discussion here. Thanks for reminding me, this should be fixed before release of v1.1.0.
That I would be very thankful for! This is really giving me hard times for realising reliable manual intervention during registration of image series.
Is there an update on this issue? The alternative is to use something like
transformParameterMap = elastixImageFilter.GetTransformParameterMap() transformixImageFilter.SetTransformParameterMap(transformParameterMap)
within a script to propagate transforms from a parent image to daughter images, but it's far from being a practical solution.
Hm, I'm not sure but could this problem be related to https://github.com/SuperElastix/SimpleElastix/issues/119#issuecomment-412095132?
This has since been fixed in elastix. You can try to the develop branch SimpleElastix (i.e. clone, compile, and install from scratch) which has just been updated to the newest version.
Fantastic, thanks for the heads up Kasper. Is it possible to delete some files after compilation? The build data is >12gb - would be good to cleanup what is no longer needed
Yes, after you have installed the Python package onto your system you can remove the entire build directory.
You can also use the master now.
I recently started working with SimpleElastix and have been experiencing this exact issue after building it from master yesterday. I just tried the MWE from above and it still crashes my Python interpreter (right after the line WARNING: The parameter "UseBinaryFormatForTransformationParameters", requested at entry number 0, does not exist at all. The default value "false" is used instead.
). Is anyone else still experiencing this issue?
My SimpleITK version string is '1.1.0.dev362-gb3783'. I don't have this problem if I use the (regular) elastix 4.9 binary and register on my parameter files generated from SimpleElastix.
If you provide a sample script along with data that reproduces the problem I will take a look.
The sample script and data posted by @romangrothausmann (which contains the InitialTransformParameterFile "nesting") still reproduces the error for me so I hope it's okay if I simply refer to that. I was able to set up the data using these commands:
git clone --single-branch --branch reg2tra+prevTra https://github.com/romangrothausmann/elastix_scripts.git
cd elastix_scripts/tests/recRegStack
Running python MWE.py
crashes, where MWE.py is copy+pasted from here: https://github.com/SuperElastix/SimpleElastix/issues/121#issuecomment-322154980 (had to remove the second-last line for py3)
If instead I use elastix.exe, running elastix.exe -f reg/2016_12_02_0101_s00_08.tif -m 2016_12_02_0101_s00_09.png -p parameterFile.txt -t0 reg/2016_12_02_0101_s00_08.txt -out .
from the same folder, the registration proceeds normally.
The SimpleElastix output is this (up until it crashes):
elastix_scripts\tests\recRegStack (reg2tra+prevTra -> origin)
(base) λ python MWE.py
Installing all components.
InstallingComponents was successful.
ELASTIX version: 4.900
Command line options from ElastixBase:
-fMask unspecified, so no fixed mask used
-mMask unspecified, so no moving mask used
-out ./
-priority unspecified, so NORMAL process priority
-threads unspecified, so all available threads are used
WARNING: The parameter "UseDirectionCosines", requested at entry number 0, does not exist at all.
The default value "true" is used instead.
WARNING: The option "UseDirectionCosines" was not found in your parameter file.
From elastix 4.8 it defaults to true!
This may change the behavior of your registrations considerably.
Command line options from TransformBase:
-t0 reg/2016_12_02_0101_s00_08.txt
Reading images...
Reading images took 0 ms.
Reading the elastix parameters from file ...
WARNING: The parameter "UseBinaryFormatForTransformationParameters", requested at entry number 0, does not exist at all.
The default value "false" is used instead.
Haven't been on this for a while and can't remember if I actually tested this with the new master before the issue was closed the first time, sorry. One reason I did not go on with this project for a while is this unresolved issue: https://github.com/SuperElastix/SimpleElastix/issues/119#issuecomment-412095132 @kaspermarstal Do you have any idea on that? As I can't reopen the issue, should I create a new one?
Hi @romangrothausmann yes you very welcome to open a new issue if the problem persists.
@f--f @romangrothausmann Now that I think about it, this issue may be related the implementation of the elastix library interface. I am not sure it can even handle file names on disk. What happens if you manually load the initial parameter maps into your python session, prepends them to your parameter map vector, and then run the registration?
What happens if you manually load the initial parameter maps into your python session, prepends them to your parameter map vector, and then run the registration?
I think I tried that already but currently cannot remember the outcome, will have a look and report back.
@f--f @romangrothausmann Now that I think about it, this issue may be related the implementation of the elastix library interface. I am not sure it can even handle file names on disk. What happens if you manually load the initial parameter maps into your python session, prepends them to your parameter map vector, and then run the registration?
I have faced the same issue with transformix (reported it on the google group) & solved it using the same workaround you are suggesting if I understood it correctly :)
I'm not sure if this issue is already solved on the develop branch, so i have to give it a try also..
Cheers, M
What happens if you manually load the initial parameter maps into your python session, prepends them to your parameter map vector, and then run the registration?
That works. I used @MarHHM workaround as a base for https://github.com/romangrothausmann/elastix_scripts/commit/ba86940716bacfed96641a48a39053014519cb54 and stfx then does not segfault in case an initial transform parameter file (name) is provided (https://github.com/romangrothausmann/elastix_scripts/commit/0ae2a9a97e871c59554c53edb600a51a742e7d75). While this surely is an acceptable workaround I would still suggest that SE should be fixed to not segfault in case an initial transform parameter file (name) is given but instead issue a warning/error, ideally pointing to the doc of this workaround. NB: So far I did not test if the workaround also works for selx.
I seem to have this issue too. Here's a self contained minimal example below. I don't see an obvious way to incorporate the workaround above. Cheers, Soren
`myimg=sitk.GetImageFromArray(np.zeros((64,64,64))) sitk.WriteImage(myimg,'myimg.nii') # for transformix command line comparison se=sitk.ElastixImageFilter() rigid_pmap=sitk.GetDefaultParameterMap("rigid",1) sitk.WriteParameterFile(rigid_pmap,'rigid1.txt') se.SetParameterMap(sitk.GetDefaultParameterMap("rigid",1))
#create a transformparameter file template to use for this example se.SetMovingImage(myimg) se.SetFixedImage(myimg) se.Execute() rigid_xfm_template=se.GetTransformParameterMap()
#create two transforms that we would like SimpleElastix to preload xfm1 = sitk.SimpleITK.ParameterMap(rigid_xfm_template[0]) xfm2 = sitk.SimpleITK.ParameterMap(rigid_xfm_template[0])
#First load xfm2 which then loads xfm1 xfm2["InitialTransformParametersFileName"]=["xfm1.txt"] xfm1["InitialTransformParametersFileName"] = ["NoInitialTransform"]
sitk.WriteParameterFile(xfm1,'xfm1.txt') sitk.WriteParameterFile(xfm2,'xfm2.txt')
se.SetInitialTransformParameterFileName('xfm2.txt') se.Execute() #segfaults, but works in elastix cmd line call #this runs: /usr/local/elastix/bin/elastix -m myimg.nii -f myimg.nii -t0 xfm2.txt -p rigid1.txt -out . `
I am getting this same issue on version 1.2.0rc2.dev1167-gd4cf2
on Ubuntu 19.10. Same on Mac OSX using the same version.
Still having this issues with current SimpleElastix (https://github.com/SuperElastix/SimpleElastix/commit/8244e0001f4137514b0f545f1e846910b3dd7769): https://github.com/romangrothausmann/elastix_scripts/commit/b639883a0d44ec0970a3978421821b73ad91b901 While the above workaround (https://github.com/SuperElastix/SimpleElastix/issues/121#issuecomment-567476205) works fine in simple cases, it would be very helpful if SimpleElastix could do this internally, since InitialTransformParameterFile is an optional parameter and could be nested multiple times. @kaspermarstal do you see a chance of realizing that?