]> Creatis software - clitk.git/blob - vv/vvToolHistogram.cxx
Debug RTStruct conversion with empty struc
[clitk.git] / vv / vvToolHistogram.cxx
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://www.centreleonberard.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 <QFileDialog>
20 #include <QShortcut>
21
22 #include <algorithm>
23
24 // vv
25 #include "vvToolHistogram.h"
26 #include "vvProgressDialog.h"
27 #include "vvSlicerManager.h"
28 #include "vvSlicer.h"
29 #include "vvToolInputSelectorWidget.h"
30 #include "vvToolHistogramCommand.h"
31
32 // vtk
33 #include <vtkAxis.h>
34 #include <vtkImageActor.h>
35 #include <vtkCamera.h>
36 #include <vtkImageClip.h>
37 #include <vtkRenderWindow.h>
38 #include <vtkChartXY.h>
39 #include <vtkPlot.h>
40 #include <vtkRendererCollection.h>
41 #include <vtkRenderer.h>
42
43 #include <vtkLine.h>
44 #include <vtkCellArray.h>
45 #include <vtkCellData.h>
46 #include <vtkPolyDataMapper.h>
47 #include <vtkProperty.h>
48 #include <vtkBox.h>
49 #include <vtkInformation.h>
50
51 #ifdef Q_OS_OSX
52 # include "vvOSXHelper.h"
53 #endif
54
55 //------------------------------------------------------------------------------
56 // Create the tool and automagically (I like this word) insert it in
57 // the main window menu.
58 ADD_TOOL(vvToolHistogram);
59 //------------------------------------------------------------------------------
60
61
62 //------------------------------------------------------------------------------
63 void vvToolHistogram::Initialize()
64
65   SetToolName("Histogram");
66   SetToolMenuName("Intensity Histogram");
67   SetToolIconFilename(":/common/icons/histogram.png");
68   SetToolTip("Display the histogram of the image.");
69   SetToolExperimental(false);
70 }
71 //------------------------------------------------------------------------------
72
73
74 //------------------------------------------------------------------------------
75 vvToolHistogram::vvToolHistogram(vvMainWindowBase * parent, Qt::WindowFlags f)
76   :vvToolWidgetBase(parent,f),
77    vvToolBase<vvToolHistogram>(parent),
78    Ui::vvToolHistogram()
79
80   // GUI Initialization
81   Ui_vvToolHistogram::setupUi(mToolWidget);
82
83   mModificationsDone = false;
84
85   // Connect signals & slots
86   connect(mSaveHistogramButton, SIGNAL(clicked()), this, SLOT(SaveAs()));
87
88   // Initialize some widget
89   HistogramWidget->hide();
90
91   mView = vtkSmartPointer<vtkContextView>::New();
92   vtkSmartPointer<vtkChartXY> chart = vtkSmartPointer<vtkChartXY>::New();
93   chart->SetAutoSize(false);
94   chart->SetRenderEmpty(true);
95   mView->GetScene()->AddItem(chart);
96   mView->GetRenderer()->SetBackground(1.0, 1.0, 1.0);
97   this->HistogramWidget->GetRenderWindow()->GetRenderers()->RemoveAllItems();
98   this->HistogramWidget->GetRenderWindow()->AddRenderer(mView->GetRenderer());
99   HistogramWidget->show();
100
101 #ifdef Q_OS_OSX
102   disableGLHiDPI(HistogramWidget->winId());
103 #endif
104
105   // Main filter
106   mFilter = clitk::HistogramImageGenericFilter::New();
107
108   // Set how many inputs are needed for this tool
109   AddInputSelector("Select one image", mFilter);
110 }
111 //------------------------------------------------------------------------------
112
113
114 //------------------------------------------------------------------------------
115 vvToolHistogram::~vvToolHistogram()
116
117 }
118 //------------------------------------------------------------------------------
119
120
121 //------------------------------------------------------------------------------
122 void vvToolHistogram::computeHistogram()
123 {
124     if (!mCurrentSlicerManager) close();
125     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
126     GetArgsInfoFromGUI();
127     HistogramWidget->hide();
128
129     // Main filter
130     mFilter->SetInputVVImage(mCurrentImage);
131     mFilter->SetArgsInfo(mArgsInfo);
132     mFilter->Update();
133
134     //Creation of the XY chart
135     vtkSmartPointer<vtkFloatArray> arrX = vtkSmartPointer<vtkFloatArray>::New();
136     vtkSmartPointer<vtkFloatArray> arrY = vtkSmartPointer<vtkFloatArray>::New();
137     arrX = mFilter->GetArrayX();
138     arrY = mFilter->GetArrayY();
139     arrX->SetName("Intensity");
140     arrY->SetName("#Voxels");
141     mTable->AddColumn(arrX);
142     mTable->AddColumn(arrY);
143
144     //Upper and Lower lines for window/level
145     vtkSmartPointer<vtkFloatArray> arrXUpperWindowLevel = vtkSmartPointer<vtkFloatArray>::New();
146     vtkSmartPointer<vtkFloatArray> arrXLowerWindowLevel = vtkSmartPointer<vtkFloatArray>::New();
147     vtkSmartPointer<vtkFloatArray> arrYWindowLevel = vtkSmartPointer<vtkFloatArray>::New();
148     arrXUpperWindowLevel->InsertNextTuple1(mMaxWindowLevel);
149     arrXUpperWindowLevel->InsertNextTuple1(mMaxWindowLevel);
150     arrXLowerWindowLevel->InsertNextTuple1(mMinWindowLevel);
151     arrXLowerWindowLevel->InsertNextTuple1(mMinWindowLevel);
152     arrYWindowLevel->InsertNextTuple1(0.0);
153     arrYWindowLevel->InsertNextTuple1(arrY->GetMaxNorm());
154     arrXUpperWindowLevel->SetName("IntensityUp");
155     arrXLowerWindowLevel->SetName("IntensityLow");
156     arrYWindowLevel->SetName("#Voxels");
157     mTableWindowLevel->AddColumn(arrXUpperWindowLevel);
158     mTableWindowLevel->AddColumn(arrXLowerWindowLevel);
159     mTableWindowLevel->AddColumn(arrYWindowLevel);
160
161     displayHistogram();
162 }
163 //------------------------------------------------------------------------------
164
165
166 //------------------------------------------------------------------------------
167 void vvToolHistogram::displayHistogram()
168 {
169     if (!mCurrentSlicerManager) close();
170     HistogramWidget->hide();
171
172
173     vtkSmartPointer<vtkChartXY> chart = vtkSmartPointer<vtkChartXY>::New();
174     chart->SetAutoSize(true);
175     mView->GetScene()->ClearItems();
176     mView->GetScene()->AddItem(chart);
177     vtkPlot *line = chart->AddPlot(vtkChart::LINE);
178 #if VTK_MAJOR_VERSION <= 5
179     line->SetInput(mTable, 0, 1);
180 #else
181     line->SetInputData(mTable, 0, 1);
182 #endif
183     line->SetColor(0, 255, 0, 255);
184     line->SetWidth(1.0);
185
186
187     vtkPlot *upperWindowLine = chart->AddPlot(vtkChart::LINE);
188     vtkPlot *lowerWindowLine = chart->AddPlot(vtkChart::LINE);
189 #if VTK_MAJOR_VERSION <= 5
190     upperWindowLine->SetInput(mTableWindowLevel, 0, 2);
191     lowerWindowLine->SetInput(mTableWindowLevel, 1, 2);
192 #else
193     upperWindowLine->SetInputData(mTableWindowLevel, 0, 2);
194     lowerWindowLine->SetInputData(mTableWindowLevel, 1, 2);
195 #endif
196     upperWindowLine->SetColor(255, 0, 0, 255);
197     lowerWindowLine->SetColor(255, 0, 0, 255);
198     upperWindowLine->SetWidth(1.0);
199     lowerWindowLine->SetWidth(1.0);
200
201     chart->GetAxis(vtkAxis::LEFT)->SetTitle("#Voxels");
202     chart->GetAxis(vtkAxis::BOTTOM)->SetTitle("Intensity");
203
204     this->HistogramWidget->GetRenderWindow()->GetRenderers()->RemoveAllItems();
205     this->HistogramWidget->GetRenderWindow()->AddRenderer(mView->GetRenderer());
206     HistogramWidget->show();
207
208     QApplication::restoreOverrideCursor();
209 }
210 //------------------------------------------------------------------------------
211
212
213 //------------------------------------------------------------------------------
214 void vvToolHistogram::changeWindowLevel()
215 {
216   vtkFloatArray* upperArray = vtkFloatArray::New();
217   upperArray = static_cast<vtkFloatArray*>(mTableWindowLevel->GetColumn(0));
218   upperArray->SetTuple1(0, mMaxWindowLevel);
219   upperArray->SetTuple1(1, mMaxWindowLevel);
220   vtkFloatArray* lowerArray = vtkFloatArray::New();
221   lowerArray = static_cast<vtkFloatArray*>(mTableWindowLevel->GetColumn(1));
222   lowerArray->SetTuple1(0, mMinWindowLevel);
223   lowerArray->SetTuple1(1, mMinWindowLevel);
224   displayHistogram();
225   mCurrentSlicerManager->UpdateWindowLevel();
226   mCurrentSlicerManager->Render();
227 }
228 //------------------------------------------------------------------------------
229
230
231 //------------------------------------------------------------------------------
232 void vvToolHistogram::windowLevelChanged()
233 {
234   computeMinMax();
235   changeWindowLevel();
236 }
237 //------------------------------------------------------------------------------
238
239
240 //------------------------------------------------------------------------------
241 void vvToolHistogram::RemoveVTKObjects()
242
243 }
244 //------------------------------------------------------------------------------
245
246
247 //------------------------------------------------------------------------------
248 bool vvToolHistogram::close()
249
250   if (!mModificationsDone)
251   {
252     mCurrentSlicerManager->SetColorLevel(originalLevel);
253     mCurrentSlicerManager->SetColorWindow(originalWindow);
254     mCurrentSlicerManager->UpdateWindowLevel();
255     mCurrentSlicerManager->Render();
256   }
257   return vvToolWidgetBase::close();
258 }
259 //------------------------------------------------------------------------------
260
261
262 //------------------------------------------------------------------------------
263 void vvToolHistogram::closeEvent(QCloseEvent *event)
264
265   RemoveVTKObjects();
266   event->accept();
267 }
268 //------------------------------------------------------------------------------
269
270
271 //------------------------------------------------------------------------------
272 void vvToolHistogram::reject()
273
274   // DD("vvToolHistogram::reject");
275   RemoveVTKObjects();
276   return vvToolWidgetBase::reject();
277 }
278 //------------------------------------------------------------------------------
279
280
281 //------------------------------------------------------------------------------
282 void vvToolHistogram::InputIsSelected(vvSlicerManager * m)
283
284   mCurrentSlicerManager = m;
285
286   mSaveHistogramButton->setEnabled(true);
287   mTextFileName = "Histogram.txt";
288
289   mTableWindowLevel = vtkSmartPointer<vtkTable>::New();
290   mTable = vtkSmartPointer<vtkTable>::New();
291
292   originalWindow = mCurrentSlicerManager->GetColorWindow();
293   originalLevel = mCurrentSlicerManager->GetColorLevel();
294
295   //Compute Min & Max for Window/Level
296   computeMinMax();
297
298   computeHistogram();
299
300   // Connect signals & slots
301   vvToolHistogramCommand *smc = vvToolHistogramCommand::New();
302   smc->mHist = this;
303   HistogramWidget->GetRenderWindow()->GetInteractor()->GetInteractorStyle()->AddObserver(vtkCommand::LeftButtonPressEvent, smc);
304   HistogramWidget->GetRenderWindow()->GetInteractor()->GetInteractorStyle()->AddObserver(vtkCommand::MouseMoveEvent, smc);
305   HistogramWidget->GetRenderWindow()->GetInteractor()->GetInteractorStyle()->AddObserver(vtkCommand::MouseWheelForwardEvent, smc);
306   HistogramWidget->GetRenderWindow()->GetInteractor()->GetInteractorStyle()->AddObserver(vtkCommand::MouseWheelBackwardEvent, smc);
307   smc->Delete();
308
309 }
310 //------------------------------------------------------------------------------
311
312
313 //------------------------------------------------------------------------------
314 #if (VTK_MAJOR_VERSION == 8 && VTK_MINOR_VERSION >= 2) || VTK_MAJOR_VERSION >= 9
315 QVTKOpenGLNativeWidget* vvToolHistogram::GetHistogramWidget()
316 #else
317 QVTKWidget* vvToolHistogram::GetHistogramWidget()
318 #endif
319 {
320   return(HistogramWidget);
321 }
322 //------------------------------------------------------------------------------
323
324
325 //------------------------------------------------------------------------------
326 void vvToolHistogram::computeMinMax()
327 {
328   mMinWindowLevel = mCurrentSlicerManager->GetColorLevel() - mCurrentSlicerManager->GetColorWindow()/2.0;
329   mMaxWindowLevel = mCurrentSlicerManager->GetColorLevel() + mCurrentSlicerManager->GetColorWindow()/2.0;
330 }
331 //------------------------------------------------------------------------------
332
333
334 //------------------------------------------------------------------------------
335 void vvToolHistogram::computeWindowLevel()
336 {
337   double window = mMaxWindowLevel - mMinWindowLevel;
338   double level = (mMaxWindowLevel + mMinWindowLevel)/2.0;
339 }
340 //------------------------------------------------------------------------------
341
342
343 //------------------------------------------------------------------------------
344 void vvToolHistogram::expandWindow()
345 {
346   mCurrentSlicerManager->SetColorWindow(mCurrentSlicerManager->GetColorWindow()+10.0);
347   computeMinMax();
348   changeWindowLevel();
349 }
350 //------------------------------------------------------------------------------
351
352
353 //------------------------------------------------------------------------------
354 void vvToolHistogram::reduceWindow()
355 {
356   mCurrentSlicerManager->SetColorWindow(mCurrentSlicerManager->GetColorWindow()-10.0);
357   computeMinMax();
358   changeWindowLevel();
359 }
360 //------------------------------------------------------------------------------
361
362
363 //------------------------------------------------------------------------------
364 void vvToolHistogram::translateWindow(double x)
365 {
366   mCurrentSlicerManager->SetColorLevel(mCurrentSlicerManager->GetColorLevel()+10.0*x);
367   computeMinMax();
368   changeWindowLevel();
369 }
370 //------------------------------------------------------------------------------
371
372
373 //------------------------------------------------------------------------------
374 void vvToolHistogram::GetArgsInfoFromGUI()
375
376
377   /* //KEEP THIS FOR READING GGO FROM FILE
378      int argc=1;
379      std::string a = "toto";
380      char * const* argv = new char*;
381      //a.c_str();
382      struct cmdline_parser_params p;
383      p.check_required = 0;
384      int good = cmdline_parser_ext(argc, argv, &args_info, &p);
385      DD(good);
386   */
387   cmdline_parser_clitkHistogramImage_init(&mArgsInfo); // Initialisation to default
388
389   mArgsInfo.verbose_flag = false;
390
391   // Required (even if not used)
392   mArgsInfo.input_given = 0;
393   mArgsInfo.output_given = 0;
394
395   mArgsInfo.input_arg = new char;
396   mArgsInfo.output_arg = new char;
397
398 }
399 //------------------------------------------------------------------------------
400
401
402 //------------------------------------------------------------------------------
403 void vvToolHistogram::apply()
404 {
405   mModificationsDone = true;
406   close();
407 }
408 //------------------------------------------------------------------------------
409
410
411 //------------------------------------------------------------------------------
412 void vvToolHistogram::SaveAs()
413
414   QStringList OutputListeFormat;
415   OutputListeFormat.clear();
416   OutputListeFormat.push_back(".txt");
417   
418   QString Extensions = "AllFiles(*.*)";
419   for (int i = 0; i < OutputListeFormat.count(); i++) {
420     Extensions += ";;Text File ( *";
421     Extensions += OutputListeFormat[i];
422     Extensions += ")";
423   }
424   QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), mTextFileName.c_str(), Extensions);
425   if (!fileName.isEmpty()) {
426     std::string fileformat = itksys::SystemTools::GetFilenameLastExtension(fileName.toStdString());
427     QString fileQFormat = fileformat.c_str();
428     if (OutputListeFormat.contains(fileformat.c_str()) || fileQFormat.isEmpty()) {
429         QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
430         std::string action = "Saving";
431         vvProgressDialog progress("Saving "+fileName.toStdString());
432         qApp->processEvents();
433         
434         if (!mCurrentSlicerManager) {
435             close();
436             return;
437         }
438
439         // Output
440         mTextFileName = fileName.toStdString();
441         if (fileQFormat.isEmpty())
442             mTextFileName += ".txt";
443         ofstream fileOpen(mTextFileName.c_str(), std::ofstream::trunc);
444   
445         if(!fileOpen) {
446             cerr << "Error during saving" << endl;
447             QApplication::restoreOverrideCursor();
448             close();
449             return;
450         }
451         
452         vtkSmartPointer<vtkFloatArray> arrX = vtkSmartPointer<vtkFloatArray>::New();
453         vtkSmartPointer<vtkFloatArray> arrY = vtkSmartPointer<vtkFloatArray>::New();
454         arrX = mFilter->GetArrayX();
455         arrY = mFilter->GetArrayY();
456         int i(0);
457         fileOpen << "Value represents the number of voxels around the corresponding intensity (by default the windows size around intensity is log(range))" << endl;
458         fileOpen << "Intensity" << "\t" << "Value" << endl;
459    
460         while (i<arrX->GetNumberOfTuples()) {
461             fileOpen << arrX->GetTuple(i)[0] << "\t" << arrY->GetTuple(i)[0] << endl;
462             ++i;
463         }
464
465         fileOpen.close();
466         QApplication::restoreOverrideCursor();
467     } else {
468       QString error = fileformat.c_str();
469       error += " format unknown !!!\n";
470       QMessageBox::information(this,tr("Saving Problem"),error);
471       SaveAs();
472     }
473   }
474 }
475 //------------------------------------------------------------------------------