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 <QFileDialog>
25 #include "vvToolHistogram.h"
26 #include "vvProgressDialog.h"
27 #include "vvSlicerManager.h"
29 #include "vvToolInputSelectorWidget.h"
30 #include "vvToolHistogramCommand.h"
34 #include <vtkImageActor.h>
35 #include <vtkCamera.h>
36 #include <vtkImageClip.h>
37 #include <vtkRenderWindow.h>
38 #include <vtkChartXY.h>
40 #include <vtkRendererCollection.h>
41 #include <vtkRenderer.h>
44 #include <vtkCellArray.h>
45 #include <vtkCellData.h>
46 #include <vtkPolyDataMapper.h>
47 #include <vtkProperty.h>
49 #include <vtkInformation.h>
52 # include "vvOSXHelper.h"
55 //------------------------------------------------------------------------------
56 // Create the tool and automagically (I like this word) insert it in
57 // the main window menu.
58 ADD_TOOL(vvToolHistogram);
59 //------------------------------------------------------------------------------
62 //------------------------------------------------------------------------------
63 void vvToolHistogram::Initialize()
65 SetToolName("Histogram");
66 SetToolMenuName("Intensity Histogram");
67 SetToolIconFilename(":/common/icons/histogram.png");
68 SetToolTip("Display the histogram of the image.");
69 SetToolExperimental(false);
71 //------------------------------------------------------------------------------
74 //------------------------------------------------------------------------------
75 vvToolHistogram::vvToolHistogram(vvMainWindowBase * parent, Qt::WindowFlags f)
76 :vvToolWidgetBase(parent,f),
77 vvToolBase<vvToolHistogram>(parent),
81 Ui_vvToolHistogram::setupUi(mToolWidget);
83 mModificationsDone = false;
85 // Connect signals & slots
86 connect(mSaveHistogramButton, SIGNAL(clicked()), this, SLOT(SaveAs()));
88 // Initialize some widget
89 HistogramWidget->hide();
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();
102 disableGLHiDPI(HistogramWidget->winId());
106 mFilter = clitk::HistogramImageGenericFilter::New();
108 // Set how many inputs are needed for this tool
109 AddInputSelector("Select one image", mFilter);
111 //------------------------------------------------------------------------------
114 //------------------------------------------------------------------------------
115 vvToolHistogram::~vvToolHistogram()
118 //------------------------------------------------------------------------------
121 //------------------------------------------------------------------------------
122 void vvToolHistogram::computeHistogram()
124 if (!mCurrentSlicerManager) close();
125 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
126 GetArgsInfoFromGUI();
127 HistogramWidget->hide();
130 mFilter->SetInputVVImage(mCurrentImage);
131 mFilter->SetArgsInfo(mArgsInfo);
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);
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);
163 //------------------------------------------------------------------------------
166 //------------------------------------------------------------------------------
167 void vvToolHistogram::displayHistogram()
169 if (!mCurrentSlicerManager) close();
170 HistogramWidget->hide();
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);
181 line->SetInputData(mTable, 0, 1);
183 line->SetColor(0, 255, 0, 255);
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);
193 upperWindowLine->SetInputData(mTableWindowLevel, 0, 2);
194 lowerWindowLine->SetInputData(mTableWindowLevel, 1, 2);
196 upperWindowLine->SetColor(255, 0, 0, 255);
197 lowerWindowLine->SetColor(255, 0, 0, 255);
198 upperWindowLine->SetWidth(1.0);
199 lowerWindowLine->SetWidth(1.0);
201 chart->GetAxis(vtkAxis::LEFT)->SetTitle("#Voxels");
202 chart->GetAxis(vtkAxis::BOTTOM)->SetTitle("Intensity");
204 this->HistogramWidget->GetRenderWindow()->GetRenderers()->RemoveAllItems();
205 this->HistogramWidget->GetRenderWindow()->AddRenderer(mView->GetRenderer());
206 HistogramWidget->show();
208 QApplication::restoreOverrideCursor();
210 //------------------------------------------------------------------------------
213 //------------------------------------------------------------------------------
214 void vvToolHistogram::changeWindowLevel()
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);
225 mCurrentSlicerManager->UpdateWindowLevel();
226 mCurrentSlicerManager->Render();
228 //------------------------------------------------------------------------------
231 //------------------------------------------------------------------------------
232 void vvToolHistogram::windowLevelChanged()
237 //------------------------------------------------------------------------------
240 //------------------------------------------------------------------------------
241 void vvToolHistogram::RemoveVTKObjects()
244 //------------------------------------------------------------------------------
247 //------------------------------------------------------------------------------
248 bool vvToolHistogram::close()
250 if (!mModificationsDone)
252 mCurrentSlicerManager->SetColorLevel(originalLevel);
253 mCurrentSlicerManager->SetColorWindow(originalWindow);
254 mCurrentSlicerManager->UpdateWindowLevel();
255 mCurrentSlicerManager->Render();
257 return vvToolWidgetBase::close();
259 //------------------------------------------------------------------------------
262 //------------------------------------------------------------------------------
263 void vvToolHistogram::closeEvent(QCloseEvent *event)
268 //------------------------------------------------------------------------------
271 //------------------------------------------------------------------------------
272 void vvToolHistogram::reject()
274 // DD("vvToolHistogram::reject");
276 return vvToolWidgetBase::reject();
278 //------------------------------------------------------------------------------
281 //------------------------------------------------------------------------------
282 void vvToolHistogram::InputIsSelected(vvSlicerManager * m)
284 mCurrentSlicerManager = m;
286 mSaveHistogramButton->setEnabled(true);
287 mTextFileName = "Histogram.txt";
289 mTableWindowLevel = vtkSmartPointer<vtkTable>::New();
290 mTable = vtkSmartPointer<vtkTable>::New();
292 originalWindow = mCurrentSlicerManager->GetColorWindow();
293 originalLevel = mCurrentSlicerManager->GetColorLevel();
295 //Compute Min & Max for Window/Level
300 // Connect signals & slots
301 vvToolHistogramCommand *smc = vvToolHistogramCommand::New();
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);
310 //------------------------------------------------------------------------------
313 //------------------------------------------------------------------------------
314 #if (VTK_MAJOR_VERSION == 8 && VTK_MINOR_VERSION >= 1) || VTK_MAJOR_VERSION >= 9
315 QVTKOpenGLNativeWidget* vvToolHistogram::GetHistogramWidget()
317 QVTKWidget* vvToolHistogram::GetHistogramWidget()
320 return(HistogramWidget);
322 //------------------------------------------------------------------------------
325 //------------------------------------------------------------------------------
326 void vvToolHistogram::computeMinMax()
328 mMinWindowLevel = mCurrentSlicerManager->GetColorLevel() - mCurrentSlicerManager->GetColorWindow()/2.0;
329 mMaxWindowLevel = mCurrentSlicerManager->GetColorLevel() + mCurrentSlicerManager->GetColorWindow()/2.0;
331 //------------------------------------------------------------------------------
334 //------------------------------------------------------------------------------
335 void vvToolHistogram::computeWindowLevel()
337 double window = mMaxWindowLevel - mMinWindowLevel;
338 double level = (mMaxWindowLevel + mMinWindowLevel)/2.0;
340 //------------------------------------------------------------------------------
343 //------------------------------------------------------------------------------
344 void vvToolHistogram::expandWindow()
346 mCurrentSlicerManager->SetColorWindow(mCurrentSlicerManager->GetColorWindow()+10.0);
350 //------------------------------------------------------------------------------
353 //------------------------------------------------------------------------------
354 void vvToolHistogram::reduceWindow()
356 mCurrentSlicerManager->SetColorWindow(mCurrentSlicerManager->GetColorWindow()-10.0);
360 //------------------------------------------------------------------------------
363 //------------------------------------------------------------------------------
364 void vvToolHistogram::translateWindow(double x)
366 mCurrentSlicerManager->SetColorLevel(mCurrentSlicerManager->GetColorLevel()+10.0*x);
370 //------------------------------------------------------------------------------
373 //------------------------------------------------------------------------------
374 void vvToolHistogram::GetArgsInfoFromGUI()
377 /* //KEEP THIS FOR READING GGO FROM FILE
379 std::string a = "toto";
380 char * const* argv = new char*;
382 struct cmdline_parser_params p;
383 p.check_required = 0;
384 int good = cmdline_parser_ext(argc, argv, &args_info, &p);
387 cmdline_parser_clitkHistogramImage_init(&mArgsInfo); // Initialisation to default
389 mArgsInfo.verbose_flag = false;
391 // Required (even if not used)
392 mArgsInfo.input_given = 0;
393 mArgsInfo.output_given = 0;
395 mArgsInfo.input_arg = new char;
396 mArgsInfo.output_arg = new char;
399 //------------------------------------------------------------------------------
402 //------------------------------------------------------------------------------
403 void vvToolHistogram::apply()
405 mModificationsDone = true;
408 //------------------------------------------------------------------------------
411 //------------------------------------------------------------------------------
412 void vvToolHistogram::SaveAs()
414 QStringList OutputListeFormat;
415 OutputListeFormat.clear();
416 OutputListeFormat.push_back(".txt");
418 QString Extensions = "AllFiles(*.*)";
419 for (int i = 0; i < OutputListeFormat.count(); i++) {
420 Extensions += ";;Text File ( *";
421 Extensions += OutputListeFormat[i];
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();
434 if (!mCurrentSlicerManager) {
440 mTextFileName = fileName.toStdString();
441 if (fileQFormat.isEmpty())
442 mTextFileName += ".txt";
443 ofstream fileOpen(mTextFileName.c_str(), std::ofstream::trunc);
446 cerr << "Error during saving" << endl;
447 QApplication::restoreOverrideCursor();
452 vtkSmartPointer<vtkFloatArray> arrX = vtkSmartPointer<vtkFloatArray>::New();
453 vtkSmartPointer<vtkFloatArray> arrY = vtkSmartPointer<vtkFloatArray>::New();
454 arrX = mFilter->GetArrayX();
455 arrY = mFilter->GetArrayY();
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;
460 while (i<arrX->GetNumberOfTuples()) {
461 fileOpen << arrX->GetTuple(i)[0] << "\t" << arrY->GetTuple(i)[0] << endl;
466 QApplication::restoreOverrideCursor();
468 QString error = fileformat.c_str();
469 error += " format unknown !!!\n";
470 QMessageBox::information(this,tr("Saving Problem"),error);
475 //------------------------------------------------------------------------------