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 ===========================================================================**/
21 #include <QFileDialog>
22 #include <QProgressDialog>
23 #include <QMessageBox>
27 #include <itkWarpImageFilter.h>
28 #include <itkJoinSeriesImageFilter.h>
29 #include <itkImageFileReader.h>
30 #include <itkSubtractImageFilter.h>
31 #include <itkDisplacementFieldJacobianDeterminantFilter.h>
34 #include <vtksys/SystemTools.hxx>
35 #include <itksys/SystemTools.hxx>
37 #include "clitkCommon.h"
39 #include "vvDeformationDialog.h"
40 #include "vvDeformableRegistration.h"
43 #include "vvFromITK.h"
44 #include "vvSlicerManager.h"
46 vvSlicerManager * vvDeformationDialog::GetSelectedSlicer() const
48 return mSlicerManagers[inputSequenceBox->currentIndex()];
51 int vvDeformationDialog::GetReferenceFrameIndex() const
53 return refImageSlider->value();
56 vvDeformationDialog::vvDeformationDialog(int initialSlicer,const std::vector<vvSlicerManager*>& slicerManagers)
57 : mSlicerManagers(slicerManagers)
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);
69 //Compute ideal number of threads and update dialog accordingly
70 int best_thread=QThread::idealThreadCount();
71 threadSpin->setValue(best_thread);
75 void vvDeformationDialog::selectOutputFile()
77 QString Extensions = "MHD Images( *.mhd);;";
78 QString fileName = QFileDialog::getSaveFileName(this,
80 itksys::SystemTools::GetFilenamePath(
81 mSlicerManagers[inputSequenceBox->currentIndex()]->GetFileName()).c_str(),
83 outputLineEdit->setText(fileName);
86 void vvDeformationDialog::updateSliderLabel(int refimage)
89 count.setNum(refimage); //Normal people start counting at 1...
90 QString newlabel="Reference Image (";
93 refImageLabel->setText(newlabel);
96 void vvDeformationDialog::resetSlider(int slicer_index)
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);
104 void vvDeformationDialog::computeDeformationField()
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."));
117 QProgressDialog progress(this);
118 QProgressDialog cancel(this);
119 cancel.setLabelText("Canceling, please wait...");
120 cancel.setCancelButtonText(0);
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());
135 vvDeformableRegistration registrator(sequence,refImageSlider->value(), iterSpin->value(),threadSpin->value(), alphaSpin->value(), sigmaSpin->value(),outputLineEdit->text().toStdString(),stopSpin->value());
137 while (!registrator.isFinished()) {
138 if (progress.wasCanceled() && !aborted) {
139 this->setResult(QDialog::Rejected);
146 progress.setValue(registrator.getProgress());
147 qApp->processEvents();
148 registrator.wait(50);
151 mOutput=registrator.getOutput();