]> 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
20 //--------------------------------------------------------------------
21 template <class TImageType>
22 clitk::RelativePositionList<TImageType>::
23 RelativePositionList() {
24 }
25 //--------------------------------------------------------------------
26
27
28 //--------------------------------------------------------------------
29 template <class TImageType>
30 void
31 clitk::RelativePositionList<TImageType>::
32 Read(std::string filename) {
33   /*
34     The goal here is to read a text file that contains options for the
35     RelativePosition filter. The text file contains options in the
36     same form of the config file of the clitkRelativePosition tool. In
37     this text file, each time a "object" option is found, a new set of
38     options is considered.
39    */
40
41   // Open the file
42   std::ifstream is;
43   openFileForReading(is, filename);
44
45   // Read input -> the structure name that will be used as input
46   // (initial support)
47   skipComment(is);
48   std::string s;
49   is >> s;
50   if (s != "input") {
51     FATAL("while reading RelativePositionList file. This file must start with 'input = '");
52     exit(0);
53   }
54   is >> s; 
55   if (s != "=") {
56     FATAL("while reading RelativePositionList file. This file must start with 'input = '");
57     exit(0);
58   }
59   std::string name;
60   is >> name;
61   skipComment(is);
62
63   // Create a temporary filename 
64   char n[] = "tmp_clitkRelativePosition_XXXXXX";
65   mkstemp(n); // tmpnam(n); 
66   std::string tmpfilename(n);
67   
68   // Loop on the file text ; Every time we see a "object" token, we
69   // split the file.
70   while (is) {
71     bool stop=false;
72     std::ostringstream ss;
73     // first part of ss is the last 'object = ' found, stored in s
74     ss << s << std::endl; 
75     while (!stop) {
76       skipComment(is);
77       if (!is) stop = true;
78       else {
79         std::getline(is, s);
80         if (s.find("object") != std::string::npos) stop=true;
81         else ss << s << std::endl;
82         if (!is) stop = true;
83       }
84     }
85     std::string text = ss.str();
86     if (text.size() > 10) { // if too small, it is not a list of option
87       std::ofstream os;
88       openFileForWriting(os, tmpfilename);
89       os << text;
90       os.close();
91
92       // Create a struct to store options. I use two step to allow to
93       // fill the args values with de default and then check
94       // automatically the options.
95       ArgsInfoType args_info;
96       std::vector<char> writable(tmpfilename.size() + 1);
97       std::copy(tmpfilename.begin(), tmpfilename.end(), writable.begin());
98       char ** argv = new char*[1];
99       argv[0] = new char[1];
100       cmdline_parser_clitkRelativePosition2(1, argv, &args_info, 1, 1, 0);
101       args_info.input_given = 1;
102       args_info.input_arg = new char[1];
103       args_info.output_given = 1;
104       args_info.output_arg = new char[1];
105       cmdline_parser_clitkRelativePosition_configfile(&writable[0], &args_info, 0, 0, 1);
106       
107       // Store the args
108       mArgsInfoList.push_back(args_info);
109       
110       // Delete the temporary file
111       std::remove(tmpfilename.c_str());
112     }
113   }
114
115   // Set the main input name
116   SetInputName(name);
117 }
118 //--------------------------------------------------------------------
119
120
121 //--------------------------------------------------------------------
122 template <class TImageType>
123 void 
124 clitk::RelativePositionList<TImageType>::
125 GenerateInputRequestedRegion() 
126 {
127   // Call default
128   itk::ImageToImageFilter<ImageType, ImageType>::GenerateInputRequestedRegion();
129   // Get input pointers and set requested region to common region
130   ImagePointer input1 = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
131   input1->SetRequestedRegion(input1->GetLargestPossibleRegion());
132 }
133 //--------------------------------------------------------------------
134
135
136
137 //--------------------------------------------------------------------
138 template <class TImageType>
139 void
140 clitk::RelativePositionList<TImageType>::
141 GenerateOutputInformation() {
142
143   // Get input
144   m_working_input = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
145
146   // Loop on RelativePositionList of operations
147   std::string s = GetInputName();
148   for(uint i=0; i<mArgsInfoList.size(); i++) {
149     // clitk::PrintMemory(true, "Start"); 
150     std::string text = "["+s+"] limits ";
151     if (mArgsInfoList[i].orientation_given) text += std::string(mArgsInfoList[i].orientation_arg[0])+" ";
152     else text = text+"("+toString(mArgsInfoList[i].angle1_arg)+" "+
153            toString(mArgsInfoList[i].angle2_arg)+" "+
154            (mArgsInfoList[i].inverse_flag?"true":"false")+") ";
155     text = text+mArgsInfoList[i].object_arg+" "+toString(mArgsInfoList[i].threshold_arg);
156     if (mArgsInfoList[i].sliceBySlice_flag) {
157       text += " slice by slice";
158     }
159     else text += " 3D";
160
161     StartNewStep(text);  
162     typename RelPosFilterType::Pointer relPosFilter;
163
164     // Is it slice by slice or 3D ?
165     if (mArgsInfoList[i].sliceBySlice_flag) {
166       typename SliceRelPosFilterType::Pointer f = SliceRelPosFilterType::New();
167       relPosFilter = f;
168       SetFilterOptions(relPosFilter, mArgsInfoList[i]);  
169       f->SetDirection(2);
170       // Set SbS specific options
171       f->SetUniqueConnectedComponentBySliceFlag(mArgsInfoList[i].uniqueCCL_flag);
172       f->SetObjectCCLSelectionFlag(mArgsInfoList[i].uniqueObjectCCL_flag);
173       f->IgnoreEmptySliceObjectFlagOn();
174       //f->SetObjectCCLSelectionDimension(0);
175       //f->SetObjectCCLSelectionDirection(-1);
176       //f->SetAutoCropFlag(false);
177       // Print if needed
178       if (mArgsInfoList[i].verboseOptions_flag) f->PrintOptions();
179     }
180     else {
181       relPosFilter = clitk::AddRelativePositionConstraintToLabelImageFilter<ImageType>::New();
182       SetFilterOptions(relPosFilter, mArgsInfoList[i]);  
183       // Print if needed
184       if (mArgsInfoList[i].verboseOptions_flag) relPosFilter->PrintOptions();
185     }
186
187     // Set input
188     relPosFilter->SetInput(m_working_input);  
189   
190     // Run the filter
191     relPosFilter->Update();
192     m_working_input = relPosFilter->GetOutput();  
193     StopCurrentStep<ImageType>(m_working_input);
194     // clitk::PrintMemory(true, "End"); 
195   }
196 }
197 //--------------------------------------------------------------------
198
199
200 //--------------------------------------------------------------------
201 template <class TImageType>
202 void
203 clitk::RelativePositionList<TImageType>::
204 GenerateData() 
205 {
206   // Final Step -> set output
207   this->GraftOutput(m_working_input);
208 }
209 //--------------------------------------------------------------------
210
211
212 //--------------------------------------------------------------------
213 template <class TImageType>
214 void
215 clitk::RelativePositionList<TImageType>::
216 SetFilterOptions(typename RelPosFilterType::Pointer filter, ArgsInfoType & options) {
217
218   if (options.orientation_given > 1) {
219     clitkExceptionMacro("Error in the RelPos options. I need a single --orientation (for the moment)."
220                         << " Current options are for obj = '" << options.object_arg
221                         << "', threshold = " << options.threshold_arg << std::endl);
222   }
223
224   ImagePointer object = GetAFDB()->template GetImage<ImageType>(options.object_arg);
225   filter->SetInputObject(object);
226   filter->WriteStepFlagOff();
227   filter->SetVerboseImageSizeFlag(GetVerboseImageSizeFlag());
228   filter->SetFuzzyThreshold(options.threshold_arg);
229   filter->SetInverseOrientationFlag(options.inverse_flag); // MUST BE BEFORE AddOrientationTypeString
230
231   if (options.orientation_given == 1)  {
232     for(uint i=0; i<options.orientation_given; i++) 
233       filter->AddOrientationTypeString(options.orientation_arg[i]);
234   }
235   else {
236     if (options.angle1_given && options.angle2_given) {
237       filter->AddAnglesInDeg(options.angle1_arg, options.angle2_arg);
238     }
239     else {
240       clitkExceptionMacro("Error in the RelPos options. I need --orientation or (--angle1 and --angle2)."
241                           << " Current options are for obj = '" << options.object_arg
242                           << "', threshold = " << options.threshold_arg << std::endl);
243     }
244   }
245   filter->SetIntermediateSpacing(options.spacing_arg);
246   if (options.spacing_arg == -1) filter->IntermediateSpacingFlagOff();
247   else filter->IntermediateSpacingFlagOn();
248   filter->SetVerboseStepFlag(options.verboseStep_flag);
249   filter->SetAutoCropFlag(!options.noAutoCrop_flag); 
250 }
251 //--------------------------------------------------------------------