]> Creatis software - clitk.git/blob - segmentation/clitkRelativePositionList.txx
Merge branch 'master' of tux.creatis.insa-lyon.fr:clitk
[clitk.git] / segmentation / clitkRelativePositionList.txx
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to: 
5   - University of LYON              http://www.universite-lyon.fr/
6   - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
7   - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
8
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.
12
13   It is distributed under dual licence
14
15   - BSD        See included LICENSE.txt file
16   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17   ======================================================================-====*/
18
19 #include "clitkLabelImageOverlapMeasureFilter.h"
20
21 //--------------------------------------------------------------------
22 template <class TImageType>
23 clitk::RelativePositionList<TImageType>::
24 RelativePositionList():  
25   clitk::FilterBase(),
26   clitk::FilterWithAnatomicalFeatureDatabaseManagement(),
27   itk::ImageToImageFilter<TImageType, TImageType>()
28 {
29   ComputeOverlapFlagOff();
30 }
31 //--------------------------------------------------------------------
32
33
34 //--------------------------------------------------------------------
35 template <class TImageType>
36 void
37 clitk::RelativePositionList<TImageType>::
38 SetReferenceImageForOverlapMeasure(ImagePointer ref) {
39   m_reference = ref;
40   ComputeOverlapFlagOn();
41 }
42 //--------------------------------------------------------------------
43
44
45 //--------------------------------------------------------------------
46 template <class TImageType>
47 void
48 clitk::RelativePositionList<TImageType>::
49 Read(std::string filename) {
50   /*
51     The goal here is to read a text file that contains options for the
52     RelativePosition filter. The text file contains options in the
53     same form of the config file of the clitkRelativePosition tool. In
54     this text file, each time a "object" option is found, a new set of
55     options is considered.
56    */
57
58   // Open the file
59   std::ifstream is;
60   openFileForReading(is, filename);
61
62   // Read input -> the structure name that will be used as input
63   // (initial support)
64   skipComment(is);
65   std::string s;
66   is >> s;
67   if (s != "input") {
68     FATAL("while reading RelativePositionList file. This file must start with 'input = '");
69     exit(0);
70   }
71   is >> s; 
72   if (s != "=") {
73     FATAL("while reading RelativePositionList file. This file must start with 'input = '");
74     exit(0);
75   }
76   std::string name;
77   is >> name;
78   skipComment(is);
79
80   // Create a temporary filename 
81   char n[] = "tmp_clitkRelativePosition_XXXXXX";
82   mkstemp(n); // tmpnam(n); 
83   std::string tmpfilename(n);
84   
85   // Loop on the file text ; Every time we see a "object" token, we
86   // split the file.
87   while (is) {
88     bool stop=false;
89     std::ostringstream ss;
90     // first part of ss is the last 'object = ' found, stored in s
91     ss << s << std::endl; 
92     while (!stop) {
93       skipComment(is);
94       if (!is) stop = true;
95       else {
96         std::getline(is, s);
97         if (s.find("object") != std::string::npos) stop=true;
98         else ss << s << std::endl;
99         if (!is) stop = true;
100       }
101     }
102     std::string text = ss.str();
103     if (text.size() > 10) { // if too small, it is not a list of option
104       std::ofstream os;
105       openFileForWriting(os, tmpfilename);
106       os << text;
107       os << "input = nothing" << std::endl;
108       os << "output = nothing" << std::endl;
109       os.close();
110
111       // Create a struct to store options. I use two step to allow to
112       // fill the args values with de default and then check
113       // automatically the options.
114       ArgsInfoType args_info;
115       std::vector<char> writable(tmpfilename.size() + 1);
116       std::copy(tmpfilename.begin(), tmpfilename.end(), writable.begin());
117       char ** argv = new char*[1];
118       argv[0] = new char[1];
119       struct cmdline_parser_clitkRelativePosition_params params;
120       params.override = 0;
121       params.initialize = 1;
122       params.check_required = 0;
123       cmdline_parser_clitkRelativePosition_configfile(&writable[0], &args_info, 1, 1, 1);
124       mArgsInfoList.push_back(args_info);
125       
126       // Delete the temporary file
127       std::remove(tmpfilename.c_str());
128     }
129   }
130
131   // Set the main input name
132   SetInputName(name);
133 }
134 //--------------------------------------------------------------------
135
136
137 //--------------------------------------------------------------------
138 template <class TImageType>
139 void 
140 clitk::RelativePositionList<TImageType>::
141 GenerateInputRequestedRegion() 
142 {
143   // Call default
144   itk::ImageToImageFilter<ImageType, ImageType>::GenerateInputRequestedRegion();
145   // Get input pointers and set requested region to common region
146   ImagePointer input1 = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
147   input1->SetRequestedRegion(input1->GetLargestPossibleRegion());
148 }
149 //--------------------------------------------------------------------
150
151
152
153 //--------------------------------------------------------------------
154 template <class TImageType>
155 void
156 clitk::RelativePositionList<TImageType>::
157 GenerateOutputInformation() {
158
159   // Get input
160   m_working_input = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
161   std::string s = GetInputName();
162
163   // Debug
164   if (GetDisplayUsedStructuresOnlyFlag()) {
165     for(uint i=0; i<mArgsInfoList.size(); i++) {
166       // Check if we only want to display structure name
167       AddUsedStructures(s, mArgsInfoList[i].object_arg);
168     }
169     return;
170   }
171
172   // Loop on RelativePositionList of operations
173   for(uint i=0; i<mArgsInfoList.size(); i++) {
174
175     // clitk::PrintMemory(true, "Start"); 
176     std::string text = "["+s+"] limits ";
177     if (mArgsInfoList[i].orientation_given) text += std::string(mArgsInfoList[i].orientation_arg[0])+" ";
178     else text = text+"("+toString(mArgsInfoList[i].angle1_arg)+" "+
179            toString(mArgsInfoList[i].angle2_arg)+" "+
180            (mArgsInfoList[i].inverse_flag?"true":"false")+") ";
181     text = text+mArgsInfoList[i].object_arg+" "+toString(mArgsInfoList[i].threshold_arg);
182     if (mArgsInfoList[i].sliceBySlice_flag) {
183       text += " slice by slice";
184     }
185     else text += " 3D";
186     text += " spacing=" + toString(mArgsInfoList[i].spacing_arg);
187
188     StartNewStep(text);  
189     typename RelPosFilterType::Pointer relPosFilter;
190
191     // Is it slice by slice or 3D ?
192     if (mArgsInfoList[i].sliceBySlice_flag) {
193       typename SliceRelPosFilterType::Pointer f = SliceRelPosFilterType::New();
194       relPosFilter = f;
195       SetFilterOptions(relPosFilter, mArgsInfoList[i]);  
196       f->SetDirection(2);
197       // Set SbS specific options
198       f->SetUniqueConnectedComponentBySliceFlag(mArgsInfoList[i].uniqueCCL_flag);
199       f->SetObjectCCLSelectionFlag(mArgsInfoList[i].uniqueObjectCCL_flag);
200       f->IgnoreEmptySliceObjectFlagOn();
201       //f->SetObjectCCLSelectionDimension(0);
202       //f->SetObjectCCLSelectionDirection(-1);
203       //f->SetAutoCropFlag(false);
204       // Print if needed
205       if (mArgsInfoList[i].verboseOptions_flag) f->PrintOptions();
206     }
207     else {
208       relPosFilter = clitk::AddRelativePositionConstraintToLabelImageFilter<ImageType>::New();
209       SetFilterOptions(relPosFilter, mArgsInfoList[i]);  
210       // Print if needed
211       if (mArgsInfoList[i].verboseOptions_flag) relPosFilter->PrintOptions();
212     }
213
214     // Set input
215     relPosFilter->SetInput(m_working_input);  
216   
217     // Run the filter
218     relPosFilter->Update();
219     m_working_input = relPosFilter->GetOutput();  
220     StopCurrentStep<ImageType>(m_working_input);
221
222     // Compute overlap with reference if needed
223     if (GetComputeOverlapFlag()) {
224       typedef clitk::LabelImageOverlapMeasureFilter<ImageType> FilterType;
225       typename FilterType::Pointer filter = FilterType::New();
226       filter->SetInput(0, m_working_input);
227       filter->SetInput(1, m_reference);
228       filter->Update();
229     }
230     
231   }
232 }
233 //--------------------------------------------------------------------
234
235
236 //--------------------------------------------------------------------
237 template <class TImageType>
238 void
239 clitk::RelativePositionList<TImageType>::
240 GenerateData() 
241 {
242   // Final Step -> set output
243   this->GraftOutput(m_working_input);
244 }
245 //--------------------------------------------------------------------
246
247
248 //--------------------------------------------------------------------
249 template <class TImageType>
250 void
251 clitk::RelativePositionList<TImageType>::
252 SetFilterOptions(typename RelPosFilterType::Pointer filter, ArgsInfoType & options) {
253
254   if (options.orientation_given > 1) {
255     clitkExceptionMacro("Error in the RelPos options. I need a single --orientation (for the moment)."
256                         << " Current options are for obj = '" << options.object_arg
257                         << "', threshold = " << options.threshold_arg << std::endl);
258   }
259
260   ImagePointer object = GetAFDB()->template GetImage<ImageType>(options.object_arg);
261   filter->SetInputObject(object);
262   filter->WriteStepFlagOff();
263   filter->SetVerboseImageSizeFlag(GetVerboseImageSizeFlag());
264   filter->SetFuzzyThreshold(options.threshold_arg);
265   filter->SetInverseOrientationFlag(options.inverse_flag); // MUST BE BEFORE AddOrientationTypeString
266
267   if (options.orientation_given == 1)  {
268     for(uint i=0; i<options.orientation_given; i++) 
269       filter->AddOrientationTypeString(options.orientation_arg[i]);
270   }
271   else {
272     if (options.angle1_given && options.angle2_given) {
273       filter->AddAnglesInDeg(options.angle1_arg, options.angle2_arg);
274     }
275     else {
276       clitkExceptionMacro("Error in the RelPos options. I need --orientation or (--angle1 and --angle2)."
277                           << " Current options are for obj = '" << options.object_arg
278                           << "', threshold = " << options.threshold_arg << std::endl);
279     }
280   }
281   filter->SetIntermediateSpacing(options.spacing_arg);
282   if (options.spacing_arg == -1) filter->IntermediateSpacingFlagOff();
283   else filter->IntermediateSpacingFlagOn();
284   filter->SetVerboseStepFlag(options.verboseStep_flag);
285   filter->SetAutoCropFlag(!options.noAutoCrop_flag); 
286 }
287 //--------------------------------------------------------------------
288
289