]> Creatis software - clitk.git/blob - segmentation/clitkRelativePositionList.txx
7a53a99dc1eb3248c230b6690ef346b0906003be
[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     std::string text = "["+s+"] limits ";
150     if (mArgsInfoList[i].orientation_given) text += std::string(mArgsInfoList[i].orientation_arg[0])+" ";
151     else text = text+"("+toString(mArgsInfoList[i].angle1_arg)+" "+
152            toString(mArgsInfoList[i].angle2_arg)+" "+
153            (mArgsInfoList[i].inverse_flag==true?"true":"false")+") ";
154     text = text+mArgsInfoList[i].object_arg+" "+toString(mArgsInfoList[i].threshold_arg);
155     if (mArgsInfoList[i].sliceBySlice_flag) {
156       text += " slice by slice";
157     }
158     else text += " 3D";
159
160     StartNewStep(text);  
161     typename RelPosFilterType::Pointer relPosFilter;
162
163     // Is it slice by slice or 3D ?
164     if (mArgsInfoList[i].sliceBySlice_flag) {
165       typename SliceRelPosFilterType::Pointer f = SliceRelPosFilterType::New();
166       relPosFilter = f;
167       SetFilterOptions(relPosFilter, mArgsInfoList[i]);  
168       f->SetDirection(2);
169       // Set SbS specific options
170       f->SetUniqueConnectedComponentBySliceFlag(mArgsInfoList[i].uniqueCCL_flag);
171       f->SetObjectCCLSelectionFlag(mArgsInfoList[i].uniqueObjectCCL_flag);
172       f->IgnoreEmptySliceObjectFlagOn();
173       //f->SetObjectCCLSelectionDimension(0);
174       //f->SetObjectCCLSelectionDirection(-1);
175       //f->SetAutoCropFlag(false);
176       // Print if needed
177       if (mArgsInfoList[i].verboseOptions_flag) f->PrintOptions();
178     }
179     else {
180       relPosFilter = clitk::AddRelativePositionConstraintToLabelImageFilter<ImageType>::New();
181       SetFilterOptions(relPosFilter, mArgsInfoList[i]);  
182       // Print if needed
183       if (mArgsInfoList[i].verboseOptions_flag) relPosFilter->PrintOptions();
184     }
185
186     // Set input
187     relPosFilter->SetInput(m_working_input);  
188   
189     // Run the filter
190     relPosFilter->Update();
191     m_working_input = relPosFilter->GetOutput();  
192     StopCurrentStep<ImageType>(m_working_input);
193   }
194 }
195 //--------------------------------------------------------------------
196
197
198 //--------------------------------------------------------------------
199 template <class TImageType>
200 void
201 clitk::RelativePositionList<TImageType>::
202 GenerateData() 
203 {
204   // Final Step -> set output
205   this->GraftOutput(m_working_input);
206 }
207 //--------------------------------------------------------------------
208
209
210 //--------------------------------------------------------------------
211 template <class TImageType>
212 void
213 clitk::RelativePositionList<TImageType>::
214 SetFilterOptions(typename RelPosFilterType::Pointer filter, ArgsInfoType & options) {
215
216   if (options.orientation_given > 1) {
217     clitkExceptionMacro("Error in the RelPos options. I need a single --orientation (for the moment)."
218                         << " Current options are for obj = '" << options.object_arg
219                         << "', threshold = " << options.threshold_arg << std::endl);
220   }
221
222   ImagePointer object = GetAFDB()->template GetImage<ImageType>(options.object_arg);
223   filter->SetInputObject(object);
224   filter->WriteStepFlagOff();
225   filter->SetVerboseImageSizeFlag(GetVerboseImageSizeFlag());
226   filter->SetFuzzyThreshold(options.threshold_arg);
227   filter->SetInverseOrientationFlag(options.inverse_flag); // MUST BE BEFORE AddOrientationTypeString
228
229   if (options.orientation_given == 1)  {
230     for(uint i=0; i<options.orientation_given; i++) 
231       filter->AddOrientationTypeString(options.orientation_arg[i]);
232   }
233   else {
234     if (options.angle1_given && options.angle2_given) {
235       filter->AddAnglesInDeg(options.angle1_arg, options.angle2_arg);
236     }
237     else {
238       clitkExceptionMacro("Error in the RelPos options. I need --orientation or (--angle1 and --angle2)."
239                           << " Current options are for obj = '" << options.object_arg
240                           << "', threshold = " << options.threshold_arg << std::endl);
241     }
242   }
243   filter->SetIntermediateSpacing(options.spacing_arg);
244   if (options.spacing_arg == -1) filter->IntermediateSpacingFlagOff();
245   else filter->IntermediateSpacingFlagOn();
246   filter->SetVerboseStepFlag(options.verboseStep_flag);
247   filter->SetAutoCropFlag(!options.noAutoCrop_flag); 
248 }
249 //--------------------------------------------------------------------