SimpleElastix icon indicating copy to clipboard operation
SimpleElastix copied to clipboard

SimpleElastix segfaults if an InitialTransformParameterFile itself contains `InitialTransformParametersFileName`

Open romangrothausmann opened this issue 7 years ago • 35 comments

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?

romangrothausmann avatar Aug 09 '17 08:08 romangrothausmann

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

kaspermarstal avatar Aug 14 '17 07:08 kaspermarstal

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".

romangrothausmann avatar Aug 14 '17 10:08 romangrothausmann

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.

kaspermarstal avatar Oct 08 '17 13:10 kaspermarstal

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?

romangrothausmann avatar Oct 10 '17 15:10 romangrothausmann

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 avatar Oct 10 '17 18:10 kaspermarstal

@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?

romangrothausmann avatar Nov 10 '17 15:11 romangrothausmann

It should be now!

kaspermarstal avatar Dec 04 '17 13:12 kaspermarstal

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".

romangrothausmann avatar Dec 20 '17 12:12 romangrothausmann

@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.

romangrothausmann avatar Jan 02 '18 09:01 romangrothausmann

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)

romangrothausmann avatar Feb 26 '18 10:02 romangrothausmann

Let's just keep the discussion here. Thanks for reminding me, this should be fixed before release of v1.1.0.

kaspermarstal avatar Feb 28 '18 08:02 kaspermarstal

That I would be very thankful for! This is really giving me hard times for realising reliable manual intervention during registration of image series.

romangrothausmann avatar Apr 06 '18 11:04 romangrothausmann

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.

nicolasdarmanthe avatar Aug 07 '18 02:08 nicolasdarmanthe

Hm, I'm not sure but could this problem be related to https://github.com/SuperElastix/SimpleElastix/issues/119#issuecomment-412095132?

romangrothausmann avatar Aug 14 '18 13:08 romangrothausmann

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.

kaspermarstal avatar Sep 10 '18 19:09 kaspermarstal

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

nicolasdarmanthe avatar Sep 10 '18 22:09 nicolasdarmanthe

Yes, after you have installed the Python package onto your system you can remove the entire build directory.

kaspermarstal avatar Sep 12 '18 11:09 kaspermarstal

You can also use the master now.

kaspermarstal avatar Sep 12 '18 11:09 kaspermarstal

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.

f--f avatar Jan 22 '19 18:01 f--f

If you provide a sample script along with data that reproduces the problem I will take a look.

kaspermarstal avatar Jan 22 '19 18:01 kaspermarstal

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.

f--f avatar Jan 22 '19 19:01 f--f

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?

romangrothausmann avatar Jan 23 '19 15:01 romangrothausmann

Hi @romangrothausmann yes you very welcome to open a new issue if the problem persists.

kaspermarstal avatar Feb 06 '19 09:02 kaspermarstal

@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?

kaspermarstal avatar Feb 06 '19 09:02 kaspermarstal

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.

romangrothausmann avatar Feb 08 '19 15:02 romangrothausmann

@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

MarHHM avatar Oct 10 '19 13:10 MarHHM

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.

romangrothausmann avatar Dec 19 '19 12:12 romangrothausmann

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 . `

sorenchr2011 avatar Feb 24 '20 10:02 sorenchr2011

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.

reynoldscem avatar Mar 09 '20 18:03 reynoldscem

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?

romangrothausmann avatar Aug 15 '20 18:08 romangrothausmann