MantisBT - ITK
View Issue Details
0010776ITKpublic2010-05-28 15:312010-11-10 15:02
Bradley Lowekamp 
Jim Miller 
normalminorhave not tried
assignedopen 
 
 
0010776: Pipeline's excessive GenerateOutputInformation causes unnecessary GenerateData

This bug I found causes the pipeline to re-executed under "normal" (non-streaming, non-release data, non-inplace, aka normal) situations. I have attached an example which shows the problem I have discovered. The output is as follows:

--------------- First Update ---------------
-------- Start ShrinkImageFilter "shrinking" ShrinkImageFilter (0x1015b3660)
Progress | 0 | ... 0.994886 | 1
Filter took 0.000846148 seconds.
-------- End ShrinkImageFilter "shrinking"
I0: 223
F0: 10
I1: 227
F1: 23
I2: 231
F2: 41
--------------- Second UpdateOutputInformation ( no modification should occour )---------------
I0: 223
F0: 10
I1: 235 [<- modified!]
F1: 23
I2: 231
F2: 41
--------------- Second Update ( no generation should occour )---------------
-------- Start ShrinkImageFilter "shrinking" ShrinkImageFilter (0x1015b3660)
Progress | 0 ... 0.994886 | 1
Filter took 0.000789046 seconds.
-------- End ShrinkImageFilter "shrinking"



This shows that the GenerateOutputInformation is executed a second time, and modifies the output of the shrink image filter. This then causes the remaining pipeline to re-execute! Because no parameters are changed, ProcessObject::GenerateOutputInformation was not expected to be executed.

Why is it executed?
The answer lies in ProcessObject::UpdateOutputInformation. This method essentially compares the modified time of the input, to the time the GenerateOutputInformation was last called. The GenerateData methods are called after the UpdateOutputInformation phase of the pipeline, which means that after an "Update" ProcessObject::m_OutputInformationMTime is always less then the input's modified time ( if the input was connected to a filter which previously execute). This means that all pipelined ImageToImage filters always call ProcessObject::GenerateOutputInformation for every pipeline Update!

Why is this not always a problem?
The default implementation of ImageToImageFilter::GenerateOutputInformation copies the input information to the output. The first time this methods is executed it sets the correct information, and modifies the time. However, the second time the smart set methods, notices the current value matches the value to be set, and does not modify the time. Therefore, filters who use the default implementation of GenerateOutputInformation do not exhibit this bug.

Which ones do?
The filters who call Superclass::GenerateOutputInformation, and then change the values. Because these filters set the output information to the input, then change the value to an internally calculated one, the output will be modified. Causing the pipeline to be re-executed! The ShrinkImageFilter is one example, many of the filters which change spacing or size will cause this issue as well.

Solutions?
I see two approaches. 1) Don't let the methods be executed excessively. This would likely require a output information time stamp in DataObjects. 2) Don't let the GenerateOutputInformation methods change the time if not needed. I could envision some type of save current output information, set new stuff, then if it didn't change set the old modified time.


I think solution #1 is better. It does assume that the output information only depends on other output information.



Thoughts on if this is really a bug, if you think that the GenerateOutputInformation should usually be called or other views are appreciated!


Brad
No tags attached.
cxx itkGenerateOutputInformationTest1.cxx (3,276) 2010-05-28 15:31
https://public.kitware.com/Bug/file/3153/itkGenerateOutputInformationTest1.cxx
Issue History
2010-05-28 15:31Bradley LowekampNew Issue
2010-05-28 15:31Bradley LowekampFile Added: itkGenerateOutputInformationTest1.cxx
2010-05-31 08:07Dzenan ZukicNote Added: 0020873
2010-11-07 08:54Hans JohnsonStatusnew => assigned
2010-11-07 08:54Hans JohnsonAssigned To => Bradley Lowekamp
2010-11-07 08:55Hans JohnsonNote Added: 0023028
2010-11-10 14:59Bradley LowekampAssigned ToBradley Lowekamp => Jim Miller
2010-11-10 15:02Bradley LowekampNote Added: 0023150

Notes
(0020873)
Dzenan Zukic   
2010-05-31 08:07   
I might be running into the same problem with a different filter, but in my case that causes crash.

typedef itk::TriangleMeshToSimplexMeshFilter<MeshType,SimplexType> triangle2simplexType;
typedef itk::SimplexMeshToTriangleMeshFilter<SimplexType,MeshType> simplex2triangeType;
typedef itk::DeformableSimplexMesh3DFilter<SimplexType,SimplexType> deformableSimplexType;

MeshType::Pointer mesh, dMesh;
SimplexType::Pointer sMesh;

mesh=qe2itkMesh(qe);
triangle2simplexType::Pointer t2simplex=triangle2simplexType::New();
t2simplex->SetInput(mesh);
//t2simplex->Update();
sMesh=t2simplex->GetOutput();

deformableSimplexType::Pointer defSimplex=deformableSimplexType::New();
defSimplex->SetGradient(gradientMapFilter->GetOutput());
defSimplex->SetInput(sMesh);
defSimplex->SetIterations(100);
//defSimplex->Update();
sMesh=defSimplex->GetOutput();

simplex2triangeType::Pointer simplex2t=simplex2triangeType::New();
simplex2t->SetInput(sMesh);
simplex2t->Update();
dMesh=simplex2t->GetOutput();

If I uncomment the two updates above, the program crashes in \InsightToolkit-3.18.0\Code\BasicFilters\itkTriangleMeshToSimplexMeshFilter.txx, on line 95, during second execution of that filter (when second update is called). Furthermore, on line 97 of itkTriangleMeshToSimplexMeshFilter.txx there is a misspelling (tp[0] instead of tp[2]) which can cause confusion.
(0023028)
Hans Johnson   
2010-11-07 08:55   
Brad,

Could you please find somebody willing to take ownership of this task, and then assign it to them?

Thanks,
Hans
(0023150)
Bradley Lowekamp   
2010-11-10 15:02   
Jim,

It looks like I wrote a long description an included a test for this issue. And came up with two solutions to the issue. I am wondering how you think this should be solved the best.

Brad