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 "vvToolStructureSetManager.h"
20 #include "vvImageReader.h"
21 #include "vvStructureSetActor.h"
23 #include "vvROIActor.h"
25 #include <QFileDialog>
26 #include <QMessageBox>
27 #include <QColorDialog>
29 #include <vtkLookupTable.h>
30 #include <vtkRenderWindow.h>
32 //------------------------------------------------------------------------------
33 // Create the tool and automagically (I like this word) insert it in
34 // the main window menu.
35 ADD_TOOL(vvToolStructureSetManager);
36 //------------------------------------------------------------------------------
38 //------------------------------------------------------------------------------
39 vvToolStructureSetManager::vvToolStructureSetManager(vvMainWindowBase * parent, Qt::WindowFlags f)
40 :vvToolWidgetBase(parent, f),
41 vvToolBase<vvToolStructureSetManager>(parent),
42 Ui::vvToolStructureSetManager()
45 Ui_vvToolStructureSetManager::setupUi(mToolWidget);
47 mCurrentStructureSet = NULL;
48 mCurrentStructureSetIndex = -1;
49 mGroupBoxROI->setEnabled(false);
50 mCurrentROIActor = NULL;
51 mIsAllVisibleEnabled = false;
52 mDefaultLUTColor = vtkLookupTable::New();
53 for(unsigned int i=0; i<mDefaultLUTColor->GetNumberOfTableValues(); i++) {
54 double r = (rand()/(RAND_MAX+1.0));
55 double v = (rand()/(RAND_MAX+1.0));
56 double b = (rand()/(RAND_MAX+1.0));
57 mDefaultLUTColor->SetTableValue(i, r, v, b);
58 // std::cout << "mDefaultLUTColor->SetTableValue(" << i << ", " << r << ", " << v << ", " << b << ");" << std::endl;
60 #include "vvDefaultLut.h"
63 AddInputSelector("Select image");
65 //------------------------------------------------------------------------------
68 //------------------------------------------------------------------------------
69 vvToolStructureSetManager::~vvToolStructureSetManager()
71 DD("vvToolStructureSetManager DESTRUCTOR");
73 //------------------------------------------------------------------------------
76 //------------------------------------------------------------------------------
77 void vvToolStructureSetManager::Initialize() {
78 SetToolName("ROIManager");
79 SetToolMenuName("Display ROI");
80 SetToolIconFilename(":/common/icons/ducky.png");
81 SetToolTip("Display ROI from label image.");
82 SetToolExperimental(true);
84 //------------------------------------------------------------------------------
87 //------------------------------------------------------------------------------
88 void vvToolStructureSetManager::InputIsSelected(vvSlicerManager *m)
90 // Hide the input selector
94 splitter->setSizes(s);
96 // connect(mOpenComboBox, SIGNAL(activated(int)), this, SLOT(open(int)));
97 connect(mOpenBinaryButton, SIGNAL(clicked()), this, SLOT(OpenBinaryImage()));
98 DD(mCurrentImage->GetNumberOfDimensions());
100 // Seems that the following is not needed to refresh ...
101 // connect(m, SIGNAL(LeftButtonReleaseSignal(int)), SLOT(LeftButtonReleaseEvent(int)));
103 connect(mTree, SIGNAL(itemSelectionChanged()), this, SLOT(SelectedItemChangedInTree()));
104 connect(mCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleROIToggled(bool)));
105 connect(mOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(OpacityChanged(int)));
106 connect(mChangeColorButton, SIGNAL(clicked()), this, SLOT(ChangeColor()));
107 connect(mContourCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleContourROIToggled(bool)));
108 connect(mChangeContourColorButton, SIGNAL(clicked()), this, SLOT(ChangeContourColor()));
109 connect(mContourWidthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeContourWidth(int)));
111 connect(mCheckBoxShowAll, SIGNAL(toggled(bool)), this, SLOT(AllVisibleROIToggled(bool)));
112 connect(mOpacitySliderAll, SIGNAL(valueChanged(int)), this, SLOT(AllOpacityChanged(int)));
113 connect(mContourCheckBoxShowAll, SIGNAL(toggled(bool)), this, SLOT(AllVisibleContourROIToggled(bool)));
115 //------------------------------------------------------------------------------
118 //------------------------------------------------------------------------------
119 void vvToolStructureSetManager::LeftButtonReleaseEvent(int slicer)
121 DD("vvToolStructureSetManager::UpdateSlice");
125 for(int i=0; i<mCurrentSlicerManager->NumberOfSlicers(); i++) {
127 mCurrentSlicerManager->GetSlicer(i)->GetRenderWindow()->Render();
130 //------------------------------------------------------------------------------
133 //------------------------------------------------------------------------------
134 void vvToolStructureSetManager::Open(int type) {
136 case 0: OpenBinaryImage(); return; // Open binary image;
137 case 1: DD("TODO"); return; // Open DICOM RT
138 case 2: DD("TODO"); return; // Open mesh
139 default: std::cerr << "Error ????" << std::endl; exit(0);
142 //------------------------------------------------------------------------------
145 //------------------------------------------------------------------------------
146 void vvToolStructureSetManager::AddRoiInTreeWidget(clitk::DicomRT_ROI * roi, QTreeWidget * ww) {
147 QTreeWidgetItem * w = new QTreeWidgetItem(ww);
148 w->setText(0, QString("%1").arg(roi->GetROINumber()));
149 w->setText(1, QString("%1").arg(roi->GetName().c_str()));
150 // w->setText(1, QString("%1").arg(roi->GetName().c_str()));
151 QBrush brush(QColor(roi->GetDisplayColor()[0]*255, roi->GetDisplayColor()[1]*255, roi->GetDisplayColor()[2]*255));
152 brush.setStyle(Qt::SolidPattern);
153 // for(int i=0; i<w->columnCount (); i++) {
154 w->setBackground(2, brush);
156 mMapROIToTreeWidget[roi] = w;
157 mMapTreeWidgetToROI[w] = roi;
158 // Connect ROI TreeWidget
161 //------------------------------------------------------------------------------
164 //------------------------------------------------------------------------------
165 void vvToolStructureSetManager::UpdateStructureSetInTreeWidget(int index, clitk::DicomRT_StructureSet * s) {
167 /* ==> Please, keep this comment (if need several SS)
168 QTreeWidgetItem * ss;
169 if (mMapStructureSetIndexToTreeWidget.find(index) == mMapStructureSetIndexToTreeWidget.end()) {
171 ss = new QTreeWidgetItem(mTree);
172 // ss->setFlags(Qt::ItemIsSelectable|Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsTristate);
173 ss->setText(0, QString("S%1").arg(index));
174 ss->setText(1, QString("%1").arg(s->GetLabel().c_str()));
176 mMapStructureSetIndexToTreeWidget[index] = ss;
178 // Connect Structure TreeWidget
181 else ss = mMapStructureSetIndexToTreeWidget[index];
185 const std::vector<clitk::DicomRT_ROI*> & rois = s->GetListOfROI();
186 for(unsigned int i=0; i<rois.size(); i++) {
187 if (mMapROIToTreeWidget.find(rois[i]) == mMapROIToTreeWidget.end())
188 AddRoiInTreeWidget(rois[i], mTree); // replace mTree with ss if several SS
191 //------------------------------------------------------------------------------
194 //------------------------------------------------------------------------------
195 int vvToolStructureSetManager::AddStructureSet(clitk::DicomRT_StructureSet * mStructureSet) {
197 // Create actor for this SS
198 vvStructureSetActor * mStructureSetActor = new vvStructureSetActor;
199 mStructureSetActor->SetStructureSet(mStructureSet);
200 mStructureSetActor->SetSlicerManager(mCurrentSlicerManager);
202 // Insert in lists and get index
203 mStructureSetsList.push_back(mStructureSet);
204 mStructureSetActorsList.push_back(mStructureSetActor);
205 int index = mStructureSetsList.size()-1;
210 //------------------------------------------------------------------------------
213 //------------------------------------------------------------------------------
214 void vvToolStructureSetManager::OpenBinaryImage() {
215 // DD("openBinaryImage");
216 // Select current StructureSet (or create)
218 // DD(mCurrentStructureSetIndex);
219 if (mCurrentStructureSet == NULL) {
220 if (mStructureSetsList.size() == 0) { // Create a default SS
221 clitk::DicomRT_StructureSet * mStructureSet = new clitk::DicomRT_StructureSet;
222 index = AddStructureSet(mStructureSet);
225 else { // Get first SS
229 index = mCurrentStructureSetIndex;
232 // TODO -> SET THIS SS AS CURRENT
233 mCurrentStructureSet = mStructureSetsList[index];
234 mCurrentStructureSetActor = mStructureSetActorsList[index];
235 mCurrentStructureSetIndex = index;
236 // DD(mCurrentStructureSetIndex);
237 //DD(mCurrentStructureSet->GetName());
240 QString Extensions = "Images files ( *.mhd *.hdr *.his)";
241 Extensions += ";;All Files (*)";
242 QStringList filename =
243 QFileDialog::getOpenFileNames(this,tr("Open binary image"),
244 mMainWindowBase->GetInputPathName(),Extensions);
245 if (filename.size() == 0) return;
247 std::vector<int> mLoadedROIIndex;
248 for(int i=0; i<filename.size(); i++) {
249 //DD(filename[i].toStdString());
252 //init the progress events
253 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
254 vvImageReader * mReader = new vvImageReader;
255 std::vector<std::string> filenames;
256 filenames.push_back(filename[i].toStdString());
257 mReader->SetInputFilenames(filenames);
258 mReader->Update(IMAGE);
259 QApplication::restoreOverrideCursor();
261 if (mReader->GetLastError().size() != 0) {
262 std::cerr << "Error while reading " << filename[i].toStdString() << std::endl;
263 QString error = "Cannot open file \n";
264 error += mReader->GetLastError().c_str();
265 QMessageBox::information(this,tr("Reading problem"),error);
269 vvImage::Pointer binaryImage = mReader->GetOutput();
273 int dim = mCurrentImage->GetNumberOfDimensions();
275 int bin_dim = binaryImage->GetNumberOfDimensions();
277 if (dim < bin_dim) { ////////// TO CHANGE FOR 3D/4D
278 std::ostringstream os;
279 os << "Error. Loaded binary image is " << bin_dim
280 << "D while selected image is " << dim << "D" << std::endl;
281 QMessageBox::information(this,tr("Reading problem"),os.str().c_str());
285 // Add a new roi to the structure
286 int n = mCurrentStructureSet->AddBinaryImageAsNewROI(binaryImage, filename[i].toStdString());
288 mLoadedROIIndex.push_back(n);
290 mCurrentStructureSet->GetROI(n)->SetBackgroundValueLabelImage(mBackgroundValueSpinBox->value());
292 // Change color NEED DEFAULT COLOR LIST
293 //DD(mDefaultLUTColor->GetNumberOfTableValues ());
294 if (n<mDefaultLUTColor->GetNumberOfTableValues ()) {
295 double * color = mDefaultLUTColor->GetTableValue(n % mDefaultLUTColor->GetNumberOfTableValues ());
299 mCurrentStructureSet->GetROI(n)->SetDisplayColor(color[0], color[1], color[2]);
302 // Add a new roi actor
303 mCurrentStructureSetActor->CreateNewROIActor(n);
305 // CheckBox for "All"
306 if (mCurrentStructureSetActor->GetROIActor(n)->IsVisible())
307 mNumberOfVisibleROI++;
308 } // end loop on n selected filenames
310 // Update the TreeWidget
311 UpdateStructureSetInTreeWidget(index, mCurrentStructureSet);
312 // Render loaded ROIs (the first is sufficient)
313 for(unsigned int i=0; i<mLoadedROIIndex.size(); i++) {
314 mCurrentStructureSetActor->GetROIActor(mLoadedROIIndex[i])->Update();
316 for(int i=0; i<mCurrentSlicerManager->NumberOfSlicers(); i++) {
317 mCurrentSlicerManager->GetSlicer(i)->Render();
321 //------------------------------------------------------------------------------
324 //------------------------------------------------------------------------------
325 void vvToolStructureSetManager::apply() {
328 //------------------------------------------------------------------------------
331 //------------------------------------------------------------------------------
332 // CURRENT ROI INTERACTION
333 //------------------------------------------------------------------------------
336 //------------------------------------------------------------------------------
337 void vvToolStructureSetManager::SelectedItemChangedInTree() {
338 // Search which roi is selected
339 QList<QTreeWidgetItem *> l = mTree->selectedItems();
340 if (l.size() == 0) return;
341 QTreeWidgetItem * w = l[0];
342 if (mMapTreeWidgetToROI.find(w) == mMapTreeWidgetToROI.end()) {
343 mCurrentROIActor = NULL;
345 mGroupBoxROI->setEnabled(false);
346 return; // Search for SS (first)
348 clitk::DicomRT_ROI * roi = mMapTreeWidgetToROI[w];
349 // DD(roi->GetName());
351 // Get selected roi actor
352 if (mCurrentROIActor != NULL) {
353 mCurrentROIActor->SetSelected(false);
354 mCurrentROIActor->Update();
357 vvROIActor * actor = mStructureSetActorsList[mCurrentStructureSetIndex]->GetROIActor(roi->GetROINumber());
359 mCurrentROIActor = actor;
362 mGroupBoxROI->setEnabled(true);
363 mROInameLabel->setText(roi->GetName().c_str());
364 mCheckBoxShow->setChecked(actor->IsVisible());
365 mContourCheckBoxShow->setChecked(actor->IsContourVisible());
366 mContourWidthSpinBox->setValue(actor->GetContourWidth());
368 // Warning -> avoir unuseful Render here by disconnect slider
369 disconnect(mOpacitySlider, SIGNAL(valueChanged(int)),
370 this, SLOT(OpacityChanged(int)));
371 mOpacitySlider->setValue((int)lrint(actor->GetOpacity()*100));
372 mOpacitySpinBox->setValue((int)lrint(actor->GetOpacity()*100));
373 connect(mOpacitySlider, SIGNAL(valueChanged(int)),
374 this, SLOT(OpacityChanged(int)));
376 // Temporary disable selection
377 // actor->SetSelected(true); // remove old selection
379 // The following must not render !!
380 // DD("before update");
381 actor->Update(); // To change in UpdateSelecte
382 //DD("after update");
384 mCurrentSlicerManager->Render();
386 //------------------------------------------------------------------------------
389 //------------------------------------------------------------------------------
390 void vvToolStructureSetManager::VisibleROIToggled(bool b) {
391 mCurrentROIActor->SetVisible(b);
392 if (b) mNumberOfVisibleROI++;
393 else mNumberOfVisibleROI--;
394 //mNumberOfVisibleROI;
395 // if (mNumberOfVisibleROI == mCurrentStructureSetIndex
397 //------------------------------------------------------------------------------
400 //------------------------------------------------------------------------------
401 void vvToolStructureSetManager::VisibleContourROIToggled(bool b) {
402 mCurrentROIActor->SetContourVisible(b);
403 mCurrentROIActor->UpdateColor();
404 mCurrentSlicerManager->Render();
406 //------------------------------------------------------------------------------
409 //------------------------------------------------------------------------------
410 void vvToolStructureSetManager::OpacityChanged(int v) {
411 if (mCurrentROIActor == NULL) return;
412 mCurrentROIActor->SetOpacity((double)v/100.0);
413 mCurrentROIActor->UpdateColor();
414 mCurrentSlicerManager->Render();
416 //------------------------------------------------------------------------------
419 //------------------------------------------------------------------------------
420 void vvToolStructureSetManager::AllVisibleROIToggled(bool b) {
422 DD(mIsAllVisibleEnabled);
423 DD(mNumberOfVisibleROI);
424 if (b == mIsAllVisibleEnabled) return;
425 if (b) mCheckBoxShowAll->setCheckState(Qt::Checked);
426 else mCheckBoxShowAll->setCheckState(Qt::Unchecked);
427 mIsAllVisibleEnabled = b;
428 for(int i=0; i<mCurrentStructureSetActor->GetNumberOfROIs(); i++) {
429 mCurrentStructureSetActor->GetROIList()[i]->SetVisible(b);
431 // Update current selection
432 mCheckBoxShow->setChecked(b);
434 //------------------------------------------------------------------------------
437 //------------------------------------------------------------------------------
438 void vvToolStructureSetManager::AllVisibleContourROIToggled(bool b) {
439 /*mCurrentROIActor->SetContourVisible(b);
440 mCurrentROIActor->UpdateColor();
441 mCurrentSlicerManager->Render();
444 //------------------------------------------------------------------------------
447 //------------------------------------------------------------------------------
448 void vvToolStructureSetManager::AllOpacityChanged(int v) {
449 /*if (mCurrentROIActor == NULL) return;
450 mCurrentROIActor->SetOpacity((double)v/100.0);
451 mCurrentROIActor->UpdateColor();
452 mCurrentSlicerManager->Render();
455 //------------------------------------------------------------------------------
458 //------------------------------------------------------------------------------
459 void vvToolStructureSetManager::ChangeColor() {
461 color.setRgbF(mCurrentROIActor->GetROI()->GetDisplayColor()[0],
462 mCurrentROIActor->GetROI()->GetDisplayColor()[1],
463 mCurrentROIActor->GetROI()->GetDisplayColor()[2]);
464 QColor c = QColorDialog::getColor(color, this, "Choose the ROI color");
465 mCurrentROIActor->GetROI()->SetDisplayColor(c.redF(), c.greenF(), c.blueF());
466 mCurrentROIActor->UpdateColor();
468 QTreeWidgetItem * w = mMapROIToTreeWidget[mCurrentROI];
469 QBrush brush(QColor(mCurrentROI->GetDisplayColor()[0]*255,
470 mCurrentROI->GetDisplayColor()[1]*255,
471 mCurrentROI->GetDisplayColor()[2]*255));
472 brush.setStyle(Qt::SolidPattern);
473 // for(int i=0; i<w->columnCount (); i++) {
474 w->setBackground(2, brush);
478 mCurrentSlicerManager->Render();
480 //------------------------------------------------------------------------------
483 //------------------------------------------------------------------------------
484 void vvToolStructureSetManager::ChangeContourColor() {
486 color.setRgbF(mCurrentROIActor->GetContourColor()[0],
487 mCurrentROIActor->GetContourColor()[1],
488 mCurrentROIActor->GetContourColor()[2]);
489 QColor c = QColorDialog::getColor(color, this, "Choose the contour color");
490 mCurrentROIActor->SetContourColor(c.redF(), c.greenF(), c.blueF());
491 mCurrentROIActor->UpdateColor();
492 mCurrentSlicerManager->Render();
494 //------------------------------------------------------------------------------
497 //------------------------------------------------------------------------------
498 void vvToolStructureSetManager::ChangeContourWidth(int n) {
499 mCurrentROIActor->SetContourWidth(n);
500 mCurrentROIActor->UpdateColor();
501 mCurrentSlicerManager->Render();
503 //------------------------------------------------------------------------------
506 //------------------------------------------------------------------------------
507 //void vvToolStructureSetManager::getActorFromROI() {
508 // mStructureSetActorsList[mCurrentStructureSetIndex]->GetROIActor(n);
510 //------------------------------------------------------------------------------