]> Creatis software - clitk.git/blob - segmentation/clitkRelativePositionList.txx
Merge branch 'master' of git.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->SetVerboseSlicesFlag(mArgsInfoList[i].verboseSlices_flag);
202       //f->SetObjectCCLSelectionDimension(0);
203       //f->SetObjectCCLSelectionDirection(-1);
204       //f->SetAutoCropFlag(false);
205       // Print if needed
206       if (mArgsInfoList[i].verboseOptions_flag) f->PrintOptions();
207     }
208     else {
209       relPosFilter = clitk::AddRelativePositionConstraintToLabelImageFilter<ImageType>::New();
210       SetFilterOptions(relPosFilter, mArgsInfoList[i]);  
211       // Print if needed
212       if (mArgsInfoList[i].verboseOptions_flag) relPosFilter->PrintOptions();
213     }
214
215     // Set input
216     relPosFilter->SetInput(m_working_input);  
217   
218     // Run the filter
219     relPosFilter->Update();
220     m_working_input = relPosFilter->GetOutput();  
221     StopCurrentStep<ImageType>(m_working_input);
222
223     // Compute overlap with reference if needed
224     if (GetComputeOverlapFlag()) {
225       typedef clitk::LabelImageOverlapMeasureFilter<ImageType> FilterType;
226       typename FilterType::Pointer filter = FilterType::New();
227       filter->SetInput(0, m_working_input);
228       filter->SetInput(1, m_reference);
229       filter->Update();
230       std::cout << std::endl;
231     }
232     
233   }
234 }
235 //--------------------------------------------------------------------
236
237
238 //--------------------------------------------------------------------
239 template <class TImageType>
240 void
241 clitk::RelativePositionList<TImageType>::
242 GenerateData() 
243 {
244   // Final Step -> set output
245   this->GraftOutput(m_working_input);
246 }
247 //--------------------------------------------------------------------
248
249
250 //--------------------------------------------------------------------
251 template <class TImageType>
252 void
253 clitk::RelativePositionList<TImageType>::
254 SetFilterOptions(typename RelPosFilterType::Pointer filter, ArgsInfoType & options) {
255
256   if (options.orientation_given > 1) {
257     clitkExceptionMacro("Error in the RelPos options. I need a single --orientation (for the moment)."
258                         << " Current options are for obj = '" << options.object_arg
259                         << "', threshold = " << options.threshold_arg << std::endl);
260   }
261
262   ImagePointer object = GetAFDB()->template GetImage<ImageType>(options.object_arg);
263   filter->SetInputObject(object);
264   filter->WriteStepFlagOff();
265   if (options.writeStep_flag) filter->WriteStepFlagOn();
266   filter->SetVerboseImageSizeFlag(GetVerboseImageSizeFlag());
267   filter->SetFuzzyThreshold(options.threshold_arg);
268   filter->SetInverseOrientationFlag(options.inverse_flag); // MUST BE BEFORE AddOrientationTypeString
269
270   if (options.orientation_given == 1)  {
271     for(uint i=0; i<options.orientation_given; i++) 
272       filter->AddOrientationTypeString(options.orientation_arg[i]);
273   }
274   else {
275     if (options.angle1_given && options.angle2_given) {
276       filter->AddAnglesInDeg(options.angle1_arg, options.angle2_arg);
277     }
278     else {
279       clitkExceptionMacro("Error in the RelPos options. I need --orientation or (--angle1 and --angle2)."
280                           << " Current options are for obj = '" << options.object_arg
281                           << "', threshold = " << options.threshold_arg << std::endl);
282     }
283   }
284   filter->SetIntermediateSpacing(options.spacing_arg);
285   if (options.spacing_arg == -1) filter->IntermediateSpacingFlagOff();
286   else filter->IntermediateSpacingFlagOn();
287   filter->SetVerboseStepFlag(options.verboseStep_flag);
288   filter->SetAutoCropFlag(!options.noAutoCrop_flag); 
289 }
290 //--------------------------------------------------------------------
291
292