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"
33 #include <vtkImageActor.h>
34 #include <vtkCamera.h>
35 #include <vtkImageClip.h>
36 #include <vtkRenderWindow.h>
37 #include <vtkChartXY.h>
39 #include <vtkRendererCollection.h>
40 #include <vtkRenderer.h>
43 #include <vtkCellArray.h>
44 #include <vtkCellData.h>
45 #include <vtkPolyDataMapper.h>
46 #include <vtkProperty.h>
48 #include <vtkInformation.h>
51 # include "vvOSXHelper.h"
54 //------------------------------------------------------------------------------
55 // Create the tool and automagically (I like this word) insert it in
56 // the main window menu.
57 ADD_TOOL(vvToolHistogram);
58 //------------------------------------------------------------------------------
61 //------------------------------------------------------------------------------
62 void vvToolHistogram::Initialize()
64 SetToolName("Histogram");
65 SetToolMenuName("Intensity Histogram");
66 SetToolIconFilename(":/common/icons/histogram.png");
67 SetToolTip("Display the histogram of the image.");
68 SetToolExperimental(false);
70 //------------------------------------------------------------------------------
73 //------------------------------------------------------------------------------
74 vvToolHistogram::vvToolHistogram(vvMainWindowBase * parent, Qt::WindowFlags f)
75 :vvToolWidgetBase(parent,f),
76 vvToolBase<vvToolHistogram>(parent),
80 Ui_vvToolHistogram::setupUi(mToolWidget);
82 // Connect signals & slots
83 connect(mSaveHistogramButton, SIGNAL(clicked()), this, SLOT(SaveAs()));
85 // Initialize some widget
86 HistogramWidget->hide();
88 mView = vtkSmartPointer<vtkContextView>::New();
89 vtkSmartPointer<vtkChartXY> chart = vtkSmartPointer<vtkChartXY>::New();
90 chart->SetAutoSize(false);
91 chart->SetRenderEmpty(true);
92 mView->GetScene()->AddItem(chart);
93 this->HistogramWidget->GetRenderWindow()->GetRenderers()->RemoveAllItems();
94 this->HistogramWidget->GetRenderWindow()->AddRenderer(mView->GetRenderer());
95 HistogramWidget->show();
98 disableGLHiDPI(HistogramWidget->winId());
102 mFilter = clitk::HistogramImageGenericFilter::New();
104 // Set how many inputs are needed for this tool
105 AddInputSelector("Select one image", mFilter);
107 //------------------------------------------------------------------------------
110 //------------------------------------------------------------------------------
111 vvToolHistogram::~vvToolHistogram()
114 //------------------------------------------------------------------------------
117 //------------------------------------------------------------------------------
118 void vvToolHistogram::computeHistogram()
120 if (!mCurrentSlicerManager) close();
121 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
122 GetArgsInfoFromGUI();
123 HistogramWidget->hide();
126 mFilter->SetInputVVImage(mCurrentImage);
127 mFilter->SetArgsInfo(mArgsInfo);
130 //Creation of the XY chart
131 vtkSmartPointer<vtkTable> table = vtkSmartPointer<vtkTable>::New();
132 vtkSmartPointer<vtkFloatArray> arrX = vtkSmartPointer<vtkFloatArray>::New();
133 vtkSmartPointer<vtkFloatArray> arrY = vtkSmartPointer<vtkFloatArray>::New();
134 arrX = mFilter->GetArrayX();
135 arrY = mFilter->GetArrayY();
136 arrX->SetName("Intensity");
137 arrY->SetName("#Voxels");
139 table->AddColumn(arrX);
140 table->AddColumn(arrY);
142 mView->GetRenderer()->SetBackground(1.0, 1.0, 1.0);
144 vtkSmartPointer<vtkChartXY> chart = vtkSmartPointer<vtkChartXY>::New();
145 chart->SetAutoSize(true);
146 mView->GetScene()->ClearItems();
147 mView->GetScene()->AddItem(chart);
148 vtkPlot *line = chart->AddPlot(vtkChart::LINE);
149 #if VTK_MAJOR_VERSION <= 5
150 line->SetInput(table, 0, 1);
152 line->SetInputData(table, 0, 1);
154 line->SetColor(0, 255, 0, 255);
157 //Upper and Lower lines for window/level
158 vtkSmartPointer<vtkTable> tableWindowLevel = vtkSmartPointer<vtkTable>::New();
159 vtkSmartPointer<vtkFloatArray> arrXUpperWindowLevel = vtkSmartPointer<vtkFloatArray>::New();
160 vtkSmartPointer<vtkFloatArray> arrXLowerWindowLevel = vtkSmartPointer<vtkFloatArray>::New();
161 vtkSmartPointer<vtkFloatArray> arrYWindowLevel = vtkSmartPointer<vtkFloatArray>::New();
162 arrXUpperWindowLevel->InsertNextTuple1(mMaxWindowLevel);
163 arrXUpperWindowLevel->InsertNextTuple1(mMaxWindowLevel);
164 arrXLowerWindowLevel->InsertNextTuple1(mMinWindowLevel);
165 arrXLowerWindowLevel->InsertNextTuple1(mMinWindowLevel);
166 arrYWindowLevel->InsertNextTuple1(0.0);
167 arrYWindowLevel->InsertNextTuple1(arrY->GetMaxNorm());
168 arrXUpperWindowLevel->SetName("IntensityUp");
169 arrXLowerWindowLevel->SetName("IntensityLow");
170 arrYWindowLevel->SetName("#Voxels");
171 tableWindowLevel->AddColumn(arrXUpperWindowLevel);
172 tableWindowLevel->AddColumn(arrXLowerWindowLevel);
173 tableWindowLevel->AddColumn(arrYWindowLevel);
174 vtkPlot *upperWindowLine = chart->AddPlot(vtkChart::LINE);
175 vtkPlot *lowerWindowLine = chart->AddPlot(vtkChart::LINE);
176 #if VTK_MAJOR_VERSION <= 5
177 upperWindowLine->SetInput(tableWindowLevel, 0, 2);
178 lowerWindowLine->SetInput(tableWindowLevel, 1, 2);
180 upperWindowLine->SetInputData(tableWindowLevel, 0, 2);
181 lowerWindowLine->SetInputData(tableWindowLevel, 1, 2);
183 upperWindowLine->SetColor(255, 0, 0, 255);
184 lowerWindowLine->SetColor(255, 0, 0, 255);
185 upperWindowLine->SetWidth(1.0);
186 lowerWindowLine->SetWidth(1.0);
188 chart->GetAxis(vtkAxis::LEFT)->SetTitle("#Voxels");
189 chart->GetAxis(vtkAxis::BOTTOM)->SetTitle("Intensity");
191 this->HistogramWidget->GetRenderWindow()->GetRenderers()->RemoveAllItems();
192 this->HistogramWidget->GetRenderWindow()->AddRenderer(mView->GetRenderer());
193 HistogramWidget->show();
195 //mView->GetInteractor()->Start();
197 QApplication::restoreOverrideCursor();
199 //------------------------------------------------------------------------------
201 //------------------------------------------------------------------------------
202 void vvToolHistogram::changeWindowLevel()
204 vtkChartXY* chart = vtkChartXY::New();
205 chart = static_cast<vtkChartXY*>(mView->GetScene()->GetItem(0));
206 vtkFloatArray* upperArray = vtkFloatArray::New();
207 upperArray = static_cast<vtkFloatArray*>(chart->GetPlot(1)->GetInput()->GetColumn(0));
208 upperArray->SetTuple1(0, mMaxWindowLevel);
209 upperArray->SetTuple1(1, mMaxWindowLevel);
210 vtkFloatArray* lowerArray = vtkFloatArray::New();
211 lowerArray = static_cast<vtkFloatArray*>(chart->GetPlot(2)->GetInput()->GetColumn(1));
212 lowerArray->SetTuple1(0, mMinWindowLevel);
213 lowerArray->SetTuple1(1, mMinWindowLevel);
215 //------------------------------------------------------------------------------
218 //------------------------------------------------------------------------------
219 void vvToolHistogram::windowLevelChanged()
224 //------------------------------------------------------------------------------
227 //------------------------------------------------------------------------------
228 void vvToolHistogram::RemoveVTKObjects()
230 if (mCurrentSlicerManager)
232 connect(mCurrentSlicerManager, SIGNAL(callAddLandmark(float,float,float,float)), mCurrentSlicerManager, SLOT(AddLandmark(float,float,float,float)));
234 mCurrentSlicerManager->Render();
237 //------------------------------------------------------------------------------
240 //------------------------------------------------------------------------------
241 bool vvToolHistogram::close()
243 //RemoveVTKObjects();
245 return vvToolWidgetBase::close();
247 //------------------------------------------------------------------------------
250 //------------------------------------------------------------------------------
251 void vvToolHistogram::closeEvent(QCloseEvent *event)
256 //------------------------------------------------------------------------------
259 //------------------------------------------------------------------------------
260 void vvToolHistogram::reject()
262 // DD("vvToolHistogram::reject");
264 return vvToolWidgetBase::reject();
266 //------------------------------------------------------------------------------
269 //------------------------------------------------------------------------------
270 void vvToolHistogram::InputIsSelected(vvSlicerManager * m)
272 mCurrentSlicerManager = m;
274 mSaveHistogramButton->setEnabled(true);
275 mTextFileName = "Histogram.txt";
277 //Compute Min & Max for Window/Level
282 disconnect(mCurrentSlicerManager, SIGNAL(callAddLandmark(float,float,float,float)), mCurrentSlicerManager, SLOT(AddLandmark(float,float,float,float)));
284 //------------------------------------------------------------------------------
287 //------------------------------------------------------------------------------
288 void vvToolHistogram::computeMinMax()
290 mMinWindowLevel = mCurrentSlicerManager->GetColorLevel() - mCurrentSlicerManager->GetColorWindow()/2.0;
291 mMaxWindowLevel = mCurrentSlicerManager->GetColorLevel() + mCurrentSlicerManager->GetColorWindow()/2.0;
293 //------------------------------------------------------------------------------
296 //------------------------------------------------------------------------------
297 void vvToolHistogram::computeWindowLevel()
299 double window = mMaxWindowLevel - mMinWindowLevel;
300 double level = (mMaxWindowLevel + mMinWindowLevel)/2.0;
302 //------------------------------------------------------------------------------
305 //------------------------------------------------------------------------------
306 void vvToolHistogram::GetArgsInfoFromGUI()
309 /* //KEEP THIS FOR READING GGO FROM FILE
311 std::string a = "toto";
312 char * const* argv = new char*;
314 struct cmdline_parser_params p;
315 p.check_required = 0;
316 int good = cmdline_parser_ext(argc, argv, &args_info, &p);
319 cmdline_parser_clitkHistogramImage_init(&mArgsInfo); // Initialisation to default
321 mArgsInfo.verbose_flag = false;
323 // Required (even if not used)
324 mArgsInfo.input_given = 0;
325 mArgsInfo.output_given = 0;
327 mArgsInfo.input_arg = new char;
328 mArgsInfo.output_arg = new char;
331 //------------------------------------------------------------------------------
334 //------------------------------------------------------------------------------
335 void vvToolHistogram::apply()
339 //------------------------------------------------------------------------------
342 //------------------------------------------------------------------------------
343 void vvToolHistogram::SaveAs()
345 QStringList OutputListeFormat;
346 OutputListeFormat.clear();
347 OutputListeFormat.push_back(".txt");
349 QString Extensions = "AllFiles(*.*)";
350 for (int i = 0; i < OutputListeFormat.count(); i++) {
351 Extensions += ";;Text File ( *";
352 Extensions += OutputListeFormat[i];
355 QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), mTextFileName.c_str(), Extensions);
356 if (!fileName.isEmpty()) {
357 std::string fileformat = itksys::SystemTools::GetFilenameLastExtension(fileName.toStdString());
358 QString fileQFormat = fileformat.c_str();
359 if (OutputListeFormat.contains(fileformat.c_str()) || fileQFormat.isEmpty()) {
360 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
361 std::string action = "Saving";
362 vvProgressDialog progress("Saving "+fileName.toStdString());
363 qApp->processEvents();
365 if (!mCurrentSlicerManager) {
371 mTextFileName = fileName.toStdString();
372 if (fileQFormat.isEmpty())
373 mTextFileName += ".txt";
374 ofstream fileOpen(mTextFileName.c_str(), std::ofstream::trunc);
377 cerr << "Error during saving" << endl;
378 QApplication::restoreOverrideCursor();
383 vtkSmartPointer<vtkFloatArray> arrX = vtkSmartPointer<vtkFloatArray>::New();
384 vtkSmartPointer<vtkFloatArray> arrY = vtkSmartPointer<vtkFloatArray>::New();
385 vtkSmartPointer<vtkFloatArray> coords = vtkSmartPointer<vtkFloatArray>::New();
386 arrX = mFilter->GetArrayX();
387 arrY = mFilter->GetArrayY();
389 fileOpen << "Value represents the number of voxels around the corresponding intensity (by default the windows size around intensity is log(range))" << endl;
390 fileOpen << "Intensity" << "\t" << "Value" << endl;
392 while (i<arrX->GetNumberOfTuples()) {
393 fileOpen << arrX->GetTuple(i)[0] << "\t" << arrY->GetTuple(i)[0] << endl;
398 QApplication::restoreOverrideCursor();
400 QString error = fileformat.c_str();
401 error += " format unknown !!!\n";
402 QMessageBox::information(this,tr("Saving Problem"),error);
407 //------------------------------------------------------------------------------