]> Creatis software - clitk.git/blob - vv/vvDeformationDialog.cxx
Return 0.0 if libstatgrab is not used
[clitk.git] / vv / vvDeformationDialog.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://oncora1.lyon.fnclcc.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 #include <vector>
19 #include <QComboBox>
20 #include <QThread>
21 #include <QFileDialog>
22 #include <QProgressDialog>
23 #include <QMessageBox>
24 #include <QFileInfo>
25
26 #include <itkImage.h>
27 #include <itkWarpImageFilter.h>
28 #include <itkJoinSeriesImageFilter.h>
29 #include <itkImageFileReader.h>
30 #include <itkSubtractImageFilter.h>
31 #include <itkDisplacementFieldJacobianDeterminantFilter.h>
32
33
34 #include <vtksys/SystemTools.hxx>
35 #include <itksys/SystemTools.hxx>
36
37 #include "clitkCommon.h"
38
39 #include "vvDeformationDialog.h"
40 #include "vvDeformableRegistration.h"
41 #include "vvSlicer.h"
42 #include "vvToITK.h"
43 #include "vvFromITK.h"
44 #include "vvSlicerManager.h"
45
46 vvSlicerManager * vvDeformationDialog::GetSelectedSlicer() const
47 {
48   return mSlicerManagers[inputSequenceBox->currentIndex()];
49 }
50
51 int vvDeformationDialog::GetReferenceFrameIndex() const
52 {
53   return refImageSlider->value();
54 }
55
56 vvDeformationDialog::vvDeformationDialog(int initialSlicer,const std::vector<vvSlicerManager*>& slicerManagers)
57   : mSlicerManagers(slicerManagers)
58 {
59   setupUi(this);
60   connect(this,SIGNAL(accepted()),this,SLOT(computeDeformationField()));
61   for (unsigned int i=0; i<slicerManagers.size(); i++)
62     inputSequenceBox->addItem(vtksys::SystemTools::GetFilenameName(slicerManagers[i]->GetFileName()).c_str());
63   connect(inputSequenceBox,SIGNAL(currentIndexChanged(int)),this,SLOT(resetSlider(int)));
64   connect(refImageSlider,SIGNAL(valueChanged(int)),this,SLOT(updateSliderLabel(int)));
65   connect(outputPushButton, SIGNAL(clicked()), this, SLOT(selectOutputFile()));
66   inputSequenceBox->setCurrentIndex(initialSlicer);
67   resetSlider(initialSlicer);
68
69   //Compute ideal number of threads and update dialog accordingly
70   int best_thread=QThread::idealThreadCount();
71   threadSpin->setValue(best_thread);
72
73 }
74
75 void vvDeformationDialog::selectOutputFile()
76 {
77   QString Extensions = "MHD Images( *.mhd);;";
78   QString fileName = QFileDialog::getSaveFileName(this,
79                      tr("Save As"),
80                      itksys::SystemTools::GetFilenamePath(
81                        mSlicerManagers[inputSequenceBox->currentIndex()]->GetFileName()).c_str(),
82                      Extensions);
83   outputLineEdit->setText(fileName);
84 }
85
86 void vvDeformationDialog::updateSliderLabel(int refimage)
87 {
88   QString count;
89   count.setNum(refimage); //Normal people start counting at 1...
90   QString newlabel="Reference Image (";
91   newlabel+=count;
92   newlabel+=")";
93   refImageLabel->setText(newlabel);
94 }
95
96 void vvDeformationDialog::resetSlider(int slicer_index)
97 {
98   refImageSlider->setRange(0,mSlicerManagers[slicer_index]->GetSlicer(0)->GetImage()->GetSize()[3]-1);
99   int refimage=mSlicerManagers[slicer_index]->GetSlicer(0)->GetTSlice();
100   refImageSlider->setSliderPosition(refimage);
101   updateSliderLabel(refimage);
102 }
103
104 void vvDeformationDialog::computeDeformationField()
105 {
106   vvImage::Pointer sequence=mSlicerManagers[inputSequenceBox->currentIndex()]->GetSlicer(0)->GetImage();
107   vtkImageData * first_image = sequence->GetVTKImages()[0];
108   if (!sequence->IsTimeSequence()) {
109     this->setResult(QDialog::Rejected);
110     QMessageBox::warning(this,tr("Image type error"), tr("Deformable image registration only makes sense on time sequences."));
111   } else if ((first_image->GetSpacing()[0] != first_image->GetSpacing()[1]) || (first_image->GetSpacing()[0] != first_image->GetSpacing()[2])) {
112     this->setResult(QDialog::Rejected);
113     QMessageBox::warning(this,tr("Image type error"), tr("Deformable registration only works well with isotropic voxels. Please resample the image."));
114     return;
115   } else {
116     bool aborted=false;
117     QProgressDialog progress(this);
118     QProgressDialog cancel(this);
119     cancel.setLabelText("Canceling, please wait...");
120     cancel.setCancelButtonText(0);
121     cancel.hide();
122     //1 step per registration plus one for each of the image conversions
123     progress.setMaximum(mSlicerManagers[inputSequenceBox->currentIndex()]
124                         ->GetSlicer(0)->GetImage()->GetSize()[3]+2);
125     progress.setLabelText("Computing deformation model...");
126     progress.setMinimumDuration(0);
127     progress.setWindowModality(Qt::WindowModal);
128     progress.setCancelButtonText("Cancel");
129     qApp->processEvents();
130     QFileInfo info(outputLineEdit->text().toStdString().c_str());
131     if (info.isRelative()) { //this is a bit hackish, but should work
132       QFileInfo im_info(mSlicerManagers[inputSequenceBox->currentIndex()]->GetFileName().c_str());
133       outputLineEdit->setText((im_info.path().toStdString() + "/" + outputLineEdit->text().toStdString()).c_str());
134     }
135     vvDeformableRegistration registrator(sequence,refImageSlider->value(), iterSpin->value(),threadSpin->value(), alphaSpin->value(), sigmaSpin->value(),outputLineEdit->text().toStdString(),stopSpin->value());
136     registrator.start();
137     while (!registrator.isFinished()) {
138       if (progress.wasCanceled() && !aborted) {
139         this->setResult(QDialog::Rejected);
140         registrator.abort();
141         aborted=true;
142         progress.hide();
143         cancel.show();
144       }
145       if (!aborted)
146         progress.setValue(registrator.getProgress());
147       qApp->processEvents();
148       registrator.wait(50);
149     }
150     if (!aborted) {
151       mOutput=registrator.getOutput();
152     }
153   }
154 }