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