1 /*=========================================================================
2 Program: vv http://www.creatis.insa-lyon.fr/rio/vv
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
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.
13 It is distributed under dual licence
15 - BSD See included LICENSE.txt file
16 - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ======================================================================-====*/
19 #include "clitkLabelImageOverlapMeasureFilter.h"
21 //--------------------------------------------------------------------
22 template <class TImageType>
23 clitk::RelativePositionList<TImageType>::
24 RelativePositionList():
26 clitk::FilterWithAnatomicalFeatureDatabaseManagement(),
27 itk::ImageToImageFilter<TImageType, TImageType>()
29 ComputeOverlapFlagOff();
31 //--------------------------------------------------------------------
34 //--------------------------------------------------------------------
35 template <class TImageType>
37 clitk::RelativePositionList<TImageType>::
38 SetReferenceImageForOverlapMeasure(ImagePointer ref) {
40 ComputeOverlapFlagOn();
42 //--------------------------------------------------------------------
45 //--------------------------------------------------------------------
46 template <class TImageType>
48 clitk::RelativePositionList<TImageType>::
49 Read(std::string filename) {
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.
60 openFileForReading(is, filename);
62 // Read input -> the structure name that will be used as input
68 FATAL("while reading RelativePositionList file. This file must start with 'input = '");
73 FATAL("while reading RelativePositionList file. This file must start with 'input = '");
80 // Create a temporary filename
81 char n[] = "tmp_clitkRelativePosition_XXXXXX";
82 mkstemp(n); // tmpnam(n);
83 std::string tmpfilename(n);
85 // Loop on the file text ; Every time we see a "object" token, we
89 std::ostringstream ss;
90 // first part of ss is the last 'object = ' found, stored in s
97 if (s.find("object") != std::string::npos) stop=true;
98 else ss << s << std::endl;
102 std::string text = ss.str();
103 if (text.size() > 10) { // if too small, it is not a list of option
105 openFileForWriting(os, tmpfilename);
107 os << "input = nothing" << std::endl;
108 os << "output = nothing" << std::endl;
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;
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);
126 // Delete the temporary file
127 std::remove(tmpfilename.c_str());
131 // Set the main input name
134 //--------------------------------------------------------------------
137 //--------------------------------------------------------------------
138 template <class TImageType>
140 clitk::RelativePositionList<TImageType>::
141 GenerateInputRequestedRegion()
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());
149 //--------------------------------------------------------------------
153 //--------------------------------------------------------------------
154 template <class TImageType>
156 clitk::RelativePositionList<TImageType>::
157 GenerateOutputInformation() {
160 m_working_input = dynamic_cast<ImageType*>(itk::ProcessObject::GetInput(0));
161 std::string s = GetInputName();
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);
172 // Loop on RelativePositionList of operations
173 for(uint i=0; i<mArgsInfoList.size(); i++) {
175 // clitk::PrintMemory(true, "Start");
176 // remove _S in station name
177 std::string sname = s;
178 clitk::findAndReplace<std::string>(sname, "_S", " ");
179 std::string text = "["+sname+"] ";
180 if (mArgsInfoList[i].orientation_given) text += std::string(mArgsInfoList[i].orientation_arg[0])+" ";
181 else text = text+"("+toString(mArgsInfoList[i].angle1_arg)+" "+
182 toString(mArgsInfoList[i].angle2_arg)+" "+
183 (mArgsInfoList[i].inverse_flag?"true":"false")+") ";
184 text = text+mArgsInfoList[i].object_arg+" "+toString(mArgsInfoList[i].threshold_arg);
185 if (mArgsInfoList[i].sliceBySlice_flag) {
189 text += " sp=" + toString(mArgsInfoList[i].spacing_arg)+" ";
191 StartNewStep(text, false); // no endl
192 typename RelPosFilterType::Pointer relPosFilter;
194 // Is it slice by slice or 3D ?
195 if (mArgsInfoList[i].sliceBySlice_flag) {
196 typename SliceRelPosFilterType::Pointer f = SliceRelPosFilterType::New();
198 SetFilterOptions(relPosFilter, mArgsInfoList[i]);
200 // Set SbS specific options
201 f->SetUniqueConnectedComponentBySliceFlag(mArgsInfoList[i].uniqueCCL_flag);
202 f->SetObjectCCLSelectionFlag(mArgsInfoList[i].uniqueObjectCCL_flag);
203 f->IgnoreEmptySliceObjectFlagOn();
204 f->SetVerboseSlicesFlag(mArgsInfoList[i].verboseSlices_flag);
205 //f->SetObjectCCLSelectionDimension(0);
206 //f->SetObjectCCLSelectionDirection(-1);
207 //f->SetAutoCropFlag(false);
209 if (mArgsInfoList[i].verboseOptions_flag) f->PrintOptions();
212 relPosFilter = clitk::AddRelativePositionConstraintToLabelImageFilter<ImageType>::New();
213 SetFilterOptions(relPosFilter, mArgsInfoList[i]);
215 if (mArgsInfoList[i].verboseOptions_flag) relPosFilter->PrintOptions();
219 relPosFilter->SetInput(m_working_input);
222 relPosFilter->Update();
223 m_working_input = relPosFilter->GetOutput();
224 StopCurrentStep<ImageType>(m_working_input);
226 // Compute overlap with reference if needed
227 if (GetComputeOverlapFlag()) {
228 typedef clitk::LabelImageOverlapMeasureFilter<ImageType> FilterType;
229 typename FilterType::Pointer filter = FilterType::New();
230 filter->SetInput(0, m_working_input);
231 filter->SetInput(1, m_reference);
234 std::cout << std::endl;
237 //--------------------------------------------------------------------
240 //--------------------------------------------------------------------
241 template <class TImageType>
243 clitk::RelativePositionList<TImageType>::
246 // Final Step -> set output
247 this->GraftOutput(m_working_input);
249 //--------------------------------------------------------------------
252 //--------------------------------------------------------------------
253 template <class TImageType>
255 clitk::RelativePositionList<TImageType>::
256 SetFilterOptions(typename RelPosFilterType::Pointer filter, ArgsInfoType & options) {
258 if (options.orientation_given > 1) {
259 clitkExceptionMacro("Error in the RelPos options. I need a single --orientation (for the moment)."
260 << " Current options are for obj = '" << options.object_arg
261 << "', threshold = " << options.threshold_arg << std::endl);
264 ImagePointer object = GetAFDB()->template GetImage<ImageType>(options.object_arg);
265 filter->SetInputObject(object);
266 filter->WriteStepFlagOff();
267 filter->SetRadius(options.radius_arg);
268 if (options.writeStep_flag) filter->WriteStepFlagOn();
269 filter->SetVerboseImageSizeFlag(GetVerboseImageSizeFlag());
270 filter->SetFuzzyThreshold(options.threshold_arg);
271 filter->SetInverseOrientationFlag(options.inverse_flag); // MUST BE BEFORE AddOrientationTypeString
272 filter->SetFastFlag(options.fastFlag_flag);
274 if (options.orientation_given == 1) {
275 for(uint i=0; i<options.orientation_given; i++)
276 filter->AddOrientationTypeString(options.orientation_arg[i]);
279 if (options.angle1_given && options.angle2_given) {
280 filter->AddAnglesInDeg(options.angle1_arg, options.angle2_arg);
283 clitkExceptionMacro("Error in the RelPos options. I need --orientation or (--angle1 and --angle2)."
284 << " Current options are for obj = '" << options.object_arg
285 << "', threshold = " << options.threshold_arg << std::endl);
288 filter->SetIntermediateSpacing(options.spacing_arg);
289 if (options.spacing_arg == -1) filter->IntermediateSpacingFlagOff();
290 else filter->IntermediateSpacingFlagOn();
291 filter->SetVerboseStepFlag(options.verboseStep_flag);
292 filter->SetAutoCropFlag(!options.noAutoCrop_flag);
294 //--------------------------------------------------------------------