1 /*=========================================================================
2 Program: vv http://www.creatis.insa-lyon.fr/rio/vv
5 - University of LYON http://www.universite-lyon.fr/
6 - Léon Bérard cancer center http://www.centreleonberard.fr
7 - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
9 This software is distributed WITHOUT ANY WARRANTY; without even
10 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 PURPOSE. See the copyright notices for more information.
13 It is distributed under dual licence
15 - BSD See included LICENSE.txt file
16 - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ===========================================================================**/
18 #ifndef __clitkShapedBLUTSpatioTemporalDeformableTransformInitializer_txx
19 #define __clitkShapedBLUTSpatioTemporalDeformableTransformInitializer_txx
20 #include "clitkShapedBLUTSpatioTemporalDeformableTransformInitializer.h"
26 template < class TTransform, class TImage >
27 ShapedBLUTSpatioTemporalDeformableTransformInitializer<TTransform, TImage >
28 ::ShapedBLUTSpatioTemporalDeformableTransformInitializer()
30 this->m_NumberOfControlPointsInsideTheImage.Fill( 5 );
31 this->m_ControlPointSpacing.Fill(64.);
32 m_ControlPointSpacing[InputDimension-1]=2;
33 this->m_ChosenSpacing.Fill(64.);
34 m_ChosenSpacing[InputDimension-1]=2;
35 m_ControlPointSpacing[InputDimension-1]=2;
36 m_NumberOfControlPointsIsGiven=false;
37 m_ControlPointSpacingIsGiven=false;
38 m_TransformRegionIsGiven=false;
39 m_SamplingFactorIsGiven=false;
40 m_SplineOrders.Fill(3);
46 template < class TTransform, class TImage >
48 ShapedBLUTSpatioTemporalDeformableTransformInitializer<TTransform, TImage >
49 ::InitializeTransform()
52 // The image is required for the region and spacing
55 itkExceptionMacro( "Reference Image has not been set" );
59 // A pointer to the transform is required
60 if( ! this->m_Transform )
62 itkExceptionMacro( "Transform has not been set" );
66 // If the image come from a filter, then update that filter.
67 if( this->m_Image->GetSource() )
69 this->m_Image->GetSource()->Update();
73 //--------------------------------------
74 // Spacing & Size on image
75 //--------------------------------------
76 SpacingType fixedImageSpacing = m_Image->GetSpacing();
77 SizeType fixedImageSize=m_Image->GetLargestPossibleRegion().GetSize();
78 typename RegionType::SizeType gridBorderSize;
79 typename RegionType::SizeType totalGridSize;
81 // Only spacing given: adjust if necessary
82 if (m_ControlPointSpacingIsGiven && !m_NumberOfControlPointsIsGiven)
84 for(unsigned int r=0; r<InputDimension; r++)
87 m_ChosenSpacing[r]= m_ControlPointSpacing[r];
88 m_ControlPointSpacing[r]= ( itk::Math::Round<double>(m_ChosenSpacing[r]/fixedImageSpacing[r]) *fixedImageSpacing[r] ) ;
89 m_NumberOfControlPointsInsideTheImage[r] = ceil( (double)fixedImageSize[r]*fixedImageSpacing[r]/ m_ControlPointSpacing[r] );
90 if ( ( ( ceil( (double)fixedImageSize[r]*fixedImageSpacing[r]/ m_ControlPointSpacing[r] ) )
91 == ( (double)fixedImageSize[r]*fixedImageSpacing[r]/ m_ControlPointSpacing[r] ) )
92 && (r!= InputDimension-1) )
94 m_NumberOfControlPointsInsideTheImage[r] +=1;
95 DD("Adding control point");
100 // Only number of CP given: adjust if necessary
102 else if (!m_ControlPointSpacingIsGiven && m_NumberOfControlPointsIsGiven)
104 for(unsigned int r=0; r<InputDimension; r++)
106 m_ChosenSpacing[r]=fixedImageSpacing[r]*( (double)(fixedImageSize[r]) /
107 (double)(m_NumberOfControlPointsInsideTheImage[r]) );
108 m_ControlPointSpacing[r]= fixedImageSpacing[r]* ceil( (double)(fixedImageSize[r] - 1) /
109 (double)(m_NumberOfControlPointsInsideTheImage[r] - 1) );
113 // Both or none of Spacing and number of CP given: no adjustment adjust, just warnings
116 for(unsigned int r=0; r<InputDimension; r++)
118 m_ChosenSpacing[r]= m_ControlPointSpacing[r];
119 if (m_NumberOfControlPointsInsideTheImage[r]*m_ControlPointSpacing[r]< fixedImageSize[r]*fixedImageSpacing[r])
121 std::cout<<"WARNING: Specified control point region ("<<m_NumberOfControlPointsInsideTheImage[r]*m_ControlPointSpacing[r]
122 <<"mm) does not cover the fixed image region ("<< fixedImageSize[r]*fixedImageSpacing[r]
123 <<"mm) for dimension "<<r<<"!" <<std::endl
124 <<"Specify only --spacing or --control for automatic adjustment..."<<std::endl;
126 if ( fmod(m_ControlPointSpacing[r], fixedImageSpacing[r]) )
128 std::cout<<"WARNING: Specified control point spacing for dimension "<<r
129 <<" does not allow exact representation of BLUT FFD!"<<std::endl
130 <<"Spacing ratio is non-integer: "<<m_ControlPointSpacing[r]/ fixedImageSpacing[r]<<std::endl
131 <<"Specify only --spacing or --control for automatic adjustment..."<<std::endl;
136 //--------------------------------------
137 // LUT sampling factors
138 //--------------------------------------
139 for (unsigned int i=0; i< InputDimension; i++)
141 if (m_Verbose) std::cout<<"For dimension "<<i<<", the ideal sampling factor (if integer) is a multitude of "
142 << m_ControlPointSpacing[i]/ fixedImageSpacing[i]<<"..."<<std::endl;
143 if ( !m_SamplingFactorIsGiven) m_SamplingFactors[i]= (int) ( m_ControlPointSpacing[i]/ fixedImageSpacing[i]);
146 //--------------------------------------
147 // Set the transform properties
148 //--------------------------------------
149 RegionType gridRegion;
150 OriginType gridOrigin;
151 DirectionType gridDirection;
153 //--------------------------------------
155 //--------------------------------------
156 for(unsigned int r=0; r<InputDimension; r++) gridBorderSize[r]=m_SplineOrders[r]; // Border for spline order = 3 ( 1 lower, 2 upper )
157 totalGridSize = m_NumberOfControlPointsInsideTheImage + gridBorderSize;
159 //--------------------------------------
161 //--------------------------------------
162 OriginType fixedImageOrigin;
164 // In case of non-zero index
165 m_Image->TransformIndexToPhysicalPoint(m_Image->GetLargestPossibleRegion().GetIndex(),fixedImageOrigin);
166 gridDirection = m_Image->GetDirection();
167 itk::FixedArray<int, InputDimension> orderShift;
169 // Spacing is 2.5 : manually modify the props
170 if( !(m_Transform->GetTransformShape()%2) )
172 m_ControlPointSpacing[InputDimension-1]=2.5;
173 m_SamplingFactors[InputDimension-1]=5;
174 totalGridSize[InputDimension-1]-=1;
175 gridRegion.SetSize(totalGridSize);
179 switch(m_Transform->GetTransformShape()){
185 if (m_Verbose) std::cout<<"Using the egg shape..."<<std::endl;
187 //--------------------------------------
189 //--------------------------------------
190 // Boundary condition1: cyclic
192 totalGridSize[InputDimension-1]-=3;
194 // Boundary condition1: reference is on trajectory
196 totalGridSize[InputDimension-1]-=1;
198 gridRegion.SetSize(totalGridSize);
200 //--------------------------------------
202 //--------------------------------------
203 // Shift depends on order
204 for(unsigned int r=0; r<InputDimension; r++)
206 orderShift[r] = m_SplineOrders[r] / 2;
207 if (r==InputDimension-1)
209 // Boundary condition1: cyclic
213 // Boundary condition1: reference is on trajectory
218 gridOrigin[r] = fixedImageOrigin[r]- (double) orderShift[r]* m_ControlPointSpacing[r];
223 // The rabit: a diamond with fixed extreme values
228 if (m_Verbose) std::cout<<"Using the rabbit shape..."<<std::endl;
230 //--------------------------------------
232 //--------------------------------------
233 // Boundary condition1: cyclic
235 totalGridSize[InputDimension-1]-=1;
237 // Boundary condition1: reference is on trajectory
239 totalGridSize[InputDimension-1]-=1;
241 // Extreme values are constrained
242 totalGridSize[InputDimension-1]-=2;
244 gridRegion.SetSize(totalGridSize);
246 //--------------------------------------
248 //--------------------------------------
249 // Shift depends on order
250 for(unsigned int r=0; r<InputDimension; r++)
252 orderShift[r] = m_SplineOrders[r] / 2;
253 if (r==InputDimension-1)
255 // Boundary condition1: cyclic
258 gridOrigin[r] = fixedImageOrigin[r]- (double) orderShift[r]* m_ControlPointSpacing[r];
264 // The sputnik: a diamond with one indepent extreme value and 4DOF
268 if (m_Verbose) std::cout<<"Using the sputnik shape..."<<std::endl;
270 //--------------------------------------
272 //--------------------------------------
273 // Boundary condition1: cyclic
275 totalGridSize[InputDimension-1]-=1;
277 // Boundary condition1: reference is on trajectory
279 totalGridSize[InputDimension-1]-=1;
281 // One extreme value is fixed
282 totalGridSize[InputDimension-1]-=1;
283 gridRegion.SetSize(totalGridSize);
285 //--------------------------------------
287 //--------------------------------------
288 // Shift depends on order
289 for(unsigned int r=0; r<InputDimension; r++)
291 orderShift[r] = m_SplineOrders[r] / 2;
292 if (r==InputDimension-1)
294 // Boundary condition1: cyclic
297 gridOrigin[r] = fixedImageOrigin[r]- (double) orderShift[r]* m_ControlPointSpacing[r];
306 if (m_Verbose) std::cout<<"Using the diamond shape..."<<std::endl;
308 //--------------------------------------
310 //--------------------------------------
311 // Boundary condition1: cyclic
313 totalGridSize[InputDimension-1]-=1;
315 // Boundary condition1: reference is on trajectory
317 totalGridSize[InputDimension-1]-=1;
319 gridRegion.SetSize(totalGridSize);
321 //--------------------------------------
323 //--------------------------------------
324 // Shift depends on order
325 for(unsigned int r=0; r<InputDimension; r++)
327 orderShift[r] = m_SplineOrders[r] / 2;
328 gridOrigin[r] = fixedImageOrigin[r]- (double) orderShift[r]* m_ControlPointSpacing[r];
335 // The sputnik: a diamond with one indepent extreme value and 4DOF
339 if (m_Verbose) std::cout<<"Using the sputnik shape..."<<std::endl;
341 //--------------------------------------
343 //--------------------------------------
344 // Boundary condition1: cyclic
346 totalGridSize[InputDimension-1]-=1;
348 // Boundary condition1: reference is on trajectory
350 totalGridSize[InputDimension-1]-=1;
352 // One extreme value is fixed
353 totalGridSize[InputDimension-1]-=1;
354 gridRegion.SetSize(totalGridSize);
356 //--------------------------------------
358 //--------------------------------------
359 // Shift depends on order
360 for(unsigned int r=0; r<InputDimension; r++)
362 orderShift[r] = m_SplineOrders[r] / 2;
363 if (r==InputDimension-1)
365 // Boundary condition1: cyclic
368 gridOrigin[r] = fixedImageOrigin[r]- (double) orderShift[r]* m_ControlPointSpacing[r];
375 DD("Shape not available");
382 if (m_Verbose) std::cout<<"The chosen control point spacing "<<m_ChosenSpacing<<"..."<<std::endl;
383 if (m_Verbose) std::cout<<"The control points spacing was adapted to "<<m_ControlPointSpacing<<"..."<<std::endl;
384 if (m_Verbose) std::cout<<"The number of (internal) control points is "<<m_NumberOfControlPointsInsideTheImage<<"..."<<std::endl;
385 if (m_Verbose) std::cout<<"Setting sampling factors to "<<m_SamplingFactors<<"..."<<std::endl;
386 if (m_Verbose) std::cout<<"The total control point grid size was set to "<<totalGridSize<<"..."<<std::endl;
387 if (m_Verbose) std::cout<<"The control point grid origin was set to "<<gridOrigin<<"..."<<std::endl;
389 //--------------------------------------
391 //--------------------------------------
392 this->m_Transform->SetSplineOrders(m_SplineOrders);
393 this->m_Transform->SetGridSpacing( m_ControlPointSpacing );
394 this->m_Transform->SetGridOrigin( gridOrigin );
395 this->m_Transform->SetGridDirection( gridDirection );
396 this->m_Transform->SetGridRegion( gridRegion );
397 this->m_Transform->SetLUTSamplingFactors(m_SamplingFactors);
401 template < class TTransform, class TImage >
403 ShapedBLUTSpatioTemporalDeformableTransformInitializer<TTransform, TImage >
404 ::SetInitialParameters( const std::string& s, ParametersType& params)
406 //---------------------------------------
407 // Read Initial parameters
408 //---------------------------------------
409 typedef itk::ImageFileReader<CoefficientImageType> CoefficientReaderType;
410 typename CoefficientReaderType::Pointer coeffReader=CoefficientReaderType::New();
411 coeffReader->SetFileName(s);
412 if(m_Verbose) std::cout<<"Reading initial coefficients from file: "<<s<<"..."<<std::endl;
413 coeffReader->Update();
414 typename CoefficientImageType::Pointer coefficientImage=coeffReader->GetOutput();
415 this->SetInitialParameters(coefficientImage, params);
418 template < class TTransform, class TImage >
420 ShapedBLUTSpatioTemporalDeformableTransformInitializer<TTransform, TImage >
421 ::SetInitialParameters(const typename CoefficientImageType::Pointer coefficientImage, ParametersType& params)
424 m_Parameters=¶ms;
427 typedef ResampleBSplineDeformableTransformImageFilter<CoefficientImageType,CoefficientImageType> ResamplerType;
428 typename ResamplerType::Pointer resampler=ResamplerType::New();
429 resampler->SetVerbose(m_Verbose);
430 resampler->SetInput(coefficientImage);
431 resampler->SetOutputParametersFromImage(m_Transform->GetCoefficientImage());
432 if(m_Verbose) std::cout<<"Resampling initial coefficients..."<<std::endl;
435 // Copy parameters into the existing array, I know its crappy
436 typedef itk::ImageRegionConstIterator<CoefficientImageType> Iterator;
437 Iterator it (resampler->GetOutput(), resampler->GetOutput()->GetLargestPossibleRegion() );
440 while(! it.IsAtEnd())
442 for (unsigned int j=0; j<InputDimension-1;j++)
443 params[i+j]=it.Get()[j];
449 // JV pass the reference to the array !!
450 // JV Update the padded version !!
451 this->m_Transform->SetParameters(params);
455 // template < class TTransform, class TImage >
457 // ShapedBLUTSpatioTemporalDeformableTransformInitializer<TTransform, TImage >
458 // ::SetInitialPaddedParameters( const std::string& s, ParametersType& params)
460 // //---------------------------------------
461 // // Read Initial parameters
462 // //---------------------------------------
463 // typedef itk::ImageFileReader<CoefficientImageType> CoefficientReaderType;
464 // typename CoefficientReaderType::Pointer coeffReader=CoefficientReaderType::New();
465 // coeffReader->SetFileName(s);
466 // if(m_Verbose) std::cout<<"Reading initial padded coefficients from file: "<<s<<"..."<<std::endl;
467 // coeffReader->Update();
468 // typename CoefficientImageType::Pointer coefficientImage=coeffReader->GetOutput();
469 // this->SetInitialPaddedParameters(coefficientImage, params);
472 // template < class TTransform, class TImage >
474 // ShapedBLUTSpatioTemporalDeformableTransformInitializer<TTransform, TImage >
475 // ::SetInitialPaddedParameters(const typename CoefficientImageType::Pointer coefficientImage, ParametersType& params)
478 // typedef ResampleBSplineSpatioTemporalDeformableTransformImageFilter<CoefficientImageType,CoefficientImageType> ResamplerType;
479 // typename ResamplerType::Pointer resampler=ResamplerType::New();
480 // resampler->SetInput(coefficientImage);
481 // resampler->SetOutputParametersFromImage(m_Transform->GetCoefficientImage());
482 // if(m_Verbose) std::cout<<"Resampling initial padded coefficients..."<<std::endl;
483 // resampler->Update();
485 // // Copy parameters into the existing array, I know its crappy
486 // typedef itk::ImageRegionConstIterator<CoefficientImageType> Iterator;
487 // Iterator it (resampler->GetOutput(), resampler->GetOutput()->GetLargestPossibleRegion() );
490 // while(! it.IsAtEnd())
492 // for (unsigned int j=0; j<InputDimension;j++)
493 // params[i+j]=it.Get()[j];
496 // i+=InputDimension;