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://www.centreleonberard.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 "clitkGammaIndex_ggo.h"
27 #include <vtkPoints.h>
28 #include <vtkCellArray.h>
29 #include <vtkPointData.h>
30 #include <vtkImageData.h>
31 #include <vtkMetaImageReader.h>
32 #include <vtkMetaImageWriter.h>
33 #include <vtkPNGReader.h>
34 #include <vtkPolyData.h>
35 #include <vtkCellLocator.h>
38 #include <vvImageReader.h>
39 #include <vvImageWriter.h>
42 #include <itkImageRegionIterator.h>
43 typedef itk::Image<double> OutputImageType;
44 typedef itk::ImageRegionIterator<OutputImageType> OutputImageIterator;
49 vtkImageData* loadImage(const std::string& filename)
51 vvImageReader::Pointer reader = vvImageReader::New();
52 reader->SetInputFilename(filename);
54 vvImage::Pointer vvimage = reader->GetOutput();
55 if (!vvimage) { cerr << "can't load " << filename << endl; return NULL; }
57 vtkImageData *image = vtkImageData::New();
58 image->DeepCopy(vvimage->GetFirstVTKImageData());
62 void saveImage(OutputImageType* image,const std::string &filename) {
63 vvImage::Pointer vvimage = vvImage::New();
64 vvimage->AddItkImage(image);
66 vvImageWriter::Pointer writer = vvImageWriter::New();
67 writer->SetOutputFileName(filename.c_str());
68 writer->SetInput(vvimage);
73 void insertTriangles(vtkCellArray *cells, vtkPoints *points, const vtkIdType ids[4]) {
74 double p0[3]; points->GetPoint(ids[0],p0);
75 double p1[3]; points->GetPoint(ids[1],p1);
76 double p2[3]; points->GetPoint(ids[2],p2);
77 double p3[3]; points->GetPoint(ids[3],p3);
78 //cout << "----------------------------------" << endl;
79 //cout << "p0=[" << p0[0] << "," << p0[1] << "," << p0[2] << "]" << endl;
80 //cout << "p1=[" << p1[0] << "," << p1[1] << "," << p1[2] << "]" << endl;
81 //cout << "p2=[" << p2[0] << "," << p2[1] << "," << p2[2] << "]" << endl;
82 //cout << "p3=[" << p3[0] << "," << p3[1] << "," << p3[2] << "]" << endl;
84 double center[] = {0,0,0};
85 for (int kk=0; kk<3; kk++) {
93 vtkIdType center_id = points->InsertNextPoint(center);
94 //cout << "center=[" << center[0] << "," << center[1] << "," << center[2] << "]" << endl;
96 cells->InsertNextCell(3);
97 cells->InsertCellPoint(ids[0]);
98 cells->InsertCellPoint(ids[1]);
99 cells->InsertCellPoint(center_id);
101 cells->InsertNextCell(3);
102 cells->InsertCellPoint(ids[1]);
103 cells->InsertCellPoint(ids[3]);
104 cells->InsertCellPoint(center_id);
106 cells->InsertNextCell(3);
107 cells->InsertCellPoint(ids[3]);
108 cells->InsertCellPoint(ids[2]);
109 cells->InsertCellPoint(center_id);
111 cells->InsertNextCell(3);
112 cells->InsertCellPoint(ids[2]);
113 cells->InsertCellPoint(ids[0]);
114 cells->InsertCellPoint(center_id);
117 void insertLine(vtkCellArray *cells, vtkPoints *points, const vtkIdType ids[2]) {
118 cells->InsertNextCell(2);
119 cells->InsertCellPoint(ids[0]);
120 cells->InsertCellPoint(ids[1]);
123 double getMaximum(vtkImageData *image) {
127 vtkPointData* point_data = image->GetPointData();
129 vtkDataArray* scalars = point_data->GetScalars();
132 for (int kk=0; kk<image->GetNumberOfPoints(); kk++) {
133 double value = scalars->GetTuple1(kk);
141 if (maximum<value) maximum = value;
148 vtkPolyData *buildPlane(vtkImageData *image,double spatial_margin,double dose_margin) {
149 vtkPoints *points = vtkPoints::New();
150 for (int kk=0; kk<image->GetNumberOfPoints(); kk++) {
151 double *point = image->GetPoint(kk);
152 double value = image->GetPointData()->GetScalars()->GetTuple1(kk);
157 point[0] /= spatial_margin;
158 point[1] /= spatial_margin;
159 point[2] /= dose_margin;
162 vtkIdType point_id = points->InsertNextPoint(point);
163 assert(kk==point_id);
165 points->InsertNextPoint(point);
169 vtkCellArray *cells = vtkCellArray::New();
170 for (int kk=0; kk<image->GetNumberOfCells(); kk++) {
171 vtkCell *cell = image->GetCell(kk);
173 if (cell->GetNumberOfPoints()==4) {
174 insertTriangles(cells,points,cell->GetPointIds()->GetPointer(0));
178 if (cell->GetNumberOfPoints()==2) {
179 insertLine(cells,points,cell->GetPointIds()->GetPointer(0));
186 vtkPolyData *data = vtkPolyData::New();
187 data->SetPoints(points);
188 data->SetPolys(cells);
195 int main(int argc,char * argv[])
197 clitk::RegisterClitkFactories();
199 args_info_clitkGammaIndex args_info;
201 if (cmdline_parser_clitkGammaIndex(argc, argv, &args_info) != 0)
204 if (!args_info.absolute_dose_margin_given && !args_info.relative_dose_margin_given) {
205 std::cerr << "Specify either relative or absolute dose margin" << endl;
209 bool verbose = args_info.verbose_flag;
211 std::string reference_filename(args_info.reference_arg);
212 std::string target_filename(args_info.target_arg);
213 std::string gamma_filename(args_info.output_arg);
214 double space_margin = args_info.spatial_margin_arg;
215 double dose_rel_margin = args_info.relative_dose_margin_arg;
216 double dose_margin = args_info.absolute_dose_margin_arg;
217 bool use_dose_margin = args_info.absolute_dose_margin_given;
220 cout << "reference_filename=" << reference_filename << endl;
221 cout << "target_filename=" << target_filename << endl;
222 cout << "gamma_filename=" << gamma_filename << endl;
223 cout << "space_margin=" << space_margin << endl;
224 if (use_dose_margin) cout << "dose_margin=" << dose_margin << endl;
225 else cout << "dose_rel_margin=" << dose_rel_margin << endl;
229 vtkImageData* reference = loadImage(reference_filename);
232 // translate target with arguments values
233 // reference is translated instead of target so that the output space stay the same as target
235 double reference_origin[3];
236 reference->GetOrigin(reference_origin);
237 reference_origin[0] -= args_info.translation_x_arg;
238 reference_origin[1] -= args_info.translation_y_arg;
239 reference_origin[2] -= args_info.translation_z_arg;
240 reference->SetOrigin(reference_origin);
243 // intensity normalisation
244 if (!use_dose_margin) {
245 dose_margin = getMaximum(reference)*dose_rel_margin;
246 if (verbose) cout << "dose_margin=" << dose_margin << endl;
250 vtkPolyData *data = buildPlane(reference,space_margin,dose_margin);
253 vtkAbstractCellLocator *locator = vtkCellLocator::New();
254 locator->SetDataSet(data);
257 locator->CacheCellBoundsOn();
258 locator->AutomaticOn();
260 locator->BuildLocator();
261 DD("end BuildLocator");
264 vtkImageData* target = loadImage(target_filename);
269 OutputImageType::Pointer output = OutputImageType::New();
271 OutputImageType::SizeType::SizeValueType output_array_size[2];
272 output_array_size[0] = target->GetDimensions()[0];
273 output_array_size[1] = target->GetDimensions()[1];
274 OutputImageType::SizeType output_size;
275 output_size.SetSize(output_array_size);
276 output->SetRegions(OutputImageType::RegionType(output_size));
277 output->SetOrigin(target->GetOrigin());
278 output->SetSpacing(target->GetSpacing());
283 unsigned long kk = 0;
284 unsigned long over_one = 0;
285 OutputImageIterator iter(output,output->GetLargestPossibleRegion());
288 while (!iter.IsAtEnd()) {
289 double *point = target->GetPoint(kk);
290 double value = target->GetPointData()->GetScalars()->GetTuple1(kk);
295 point[0] /= space_margin;
296 point[1] /= space_margin;
297 point[2] /= dose_margin;
299 double closest_point[3] = {0,0,0};
300 vtkIdType cell_id = 0;
302 double squared_distance = 0;
304 locator->FindClosestPoint(point,closest_point,cell_id,foo,squared_distance);
305 double distance = sqrt(squared_distance);
308 if (distance>1) over_one++;
314 cout << "total=" << kk << endl;
315 cout << "over_one=" << over_one << endl;
316 cout << "ratio=" << static_cast<float>(over_one)/kk << endl;
322 saveImage(output,gamma_filename);