diff --git a/Modules/DiffusionImaging/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkADCAverageFunctor.cpp b/Modules/DiffusionImaging/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkADCAverageFunctor.cpp index 1605ef0d52..ac8d3f9a53 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkADCAverageFunctor.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkADCAverageFunctor.cpp @@ -1,56 +1,56 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "itkADCAverageFunctor.h" #include #include #include void itk::ADCAverageFunctor::operator()(vnl_matrix & newSignal, const vnl_matrix & SignalMatrix, const double & S0) { vnl_matrix ADCMatrix(SignalMatrix.rows(),SignalMatrix.cols()); // Calculate ADC for each measurement for(unsigned int i = 0 ; i < SignalMatrix.rows(); ++i) for(unsigned int j = 0; j < SignalMatrix.cols(); ++j) ADCMatrix(i,j) = std::log(SignalMatrix(i,j) / S0) / (-m_BValueList[j]);// D = ln(S/S0)/-b // Calculate new Signal using Average ADC for(unsigned int i = 0 ; i < SignalMatrix.rows(); ++i){ double averageADC = ADCMatrix.get_row(i).mean(); newSignal.put(i,0, S0 * std::exp(-m_TargetBvalue * averageADC) ); // S = S0*exp(-b*D) //OUTPUT FOR EVALUATION // Root Mean Squares Error double error = 0; for(unsigned int j = 0 ; j < SignalMatrix.cols(); ++j) - error += std::pow( S0 * std::exp(-m_BValueList[j] * averageADC),2); // sum of squres + error += std::pow(SignalMatrix(i,j) - S0 * std::exp(-m_BValueList[j] * averageADC),2); // sum of squres error /= (double)SignalMatrix.cols(); // mean error = std::sqrt(error); newSignal.put(i, 1, error ); // RMS Error /*std::cout << std::scientific << std::setprecision(5) << averageADC << "," // AverageADC << S0 << "," // S0 value << error << ","; // End error for(unsigned int j = 0; j < SignalMatrix.get_row(i).size(); j++ ) std::cout << std::scientific << std::setprecision(5) << SignalMatrix.get_row(i)[j] << ","; // S_n Values corresponding to shell 1 to shell n std::cout << std::endl;*/ } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp index b167a022d5..f3a76724ef 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingView.cpp @@ -1,859 +1,862 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //#define MBILOG_ENABLE_DEBUG #include "QmitkPreprocessingView.h" #include "mitkDiffusionImagingConfigure.h" // qt includes #include // itk includes #include "itkTimeProbe.h" #include "itkB0ImageExtractionImageFilter.h" #include "itkB0ImageExtractionToSeparateImageFilter.h" #include "itkBrainMaskExtractionImageFilter.h" #include "itkCastImageFilter.h" #include "itkVectorContainer.h" #include #include #include // Multishell includes #include // Multishell Functors #include #include #include #include // mitk includes #include "QmitkDataStorageComboBox.h" #include "QmitkStdMultiWidget.h" #include "mitkProgressBar.h" #include "mitkStatusBar.h" #include "mitkNodePredicateDataType.h" #include "mitkProperties.h" #include "mitkVtkResliceInterpolationProperty.h" #include "mitkLookupTable.h" #include "mitkLookupTableProperty.h" #include "mitkTransferFunction.h" #include "mitkTransferFunctionProperty.h" #include "mitkDataNodeObject.h" #include "mitkOdfNormalizationMethodProperty.h" #include "mitkOdfScaleByProperty.h" #include #include #include #include const std::string QmitkPreprocessingView::VIEW_ID = "org.mitk.views.preprocessing"; #define DI_INFO MITK_INFO("DiffusionImaging") typedef float TTensorPixelType; QmitkPreprocessingView::QmitkPreprocessingView() : QmitkFunctionality(), m_Controls(NULL), m_MultiWidget(NULL), m_DiffusionImage(NULL) { } QmitkPreprocessingView::QmitkPreprocessingView(const QmitkPreprocessingView& other) { Q_UNUSED(other) throw std::runtime_error("Copy constructor not implemented"); } QmitkPreprocessingView::~QmitkPreprocessingView() { } void QmitkPreprocessingView::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkPreprocessingViewControls; m_Controls->setupUi(parent); this->CreateConnections(); m_Controls->m_MeasurementFrameTable->horizontalHeader()->setResizeMode(QHeaderView::Stretch); m_Controls->m_MeasurementFrameTable->verticalHeader()->setResizeMode(QHeaderView::Stretch); } } void QmitkPreprocessingView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkPreprocessingView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkPreprocessingView::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_ButtonAverageGradients), SIGNAL(clicked()), this, SLOT(AverageGradients()) ); connect( (QObject*)(m_Controls->m_ButtonExtractB0), SIGNAL(clicked()), this, SLOT(ExtractB0()) ); connect( (QObject*)(m_Controls->m_ModifyMeasurementFrame), SIGNAL(clicked()), this, SLOT(DoApplyMesurementFrame()) ); connect( (QObject*)(m_Controls->m_ReduceGradientsButton), SIGNAL(clicked()), this, SLOT(DoReduceGradientDirections()) ); connect( (QObject*)(m_Controls->m_ShowGradientsButton), SIGNAL(clicked()), this, SLOT(DoShowGradientDirections()) ); connect( (QObject*)(m_Controls->m_MirrorGradientToHalfSphereButton), SIGNAL(clicked()), this, SLOT(DoHalfSphereGradientDirections()) ); connect( (QObject*)(m_Controls->m_MergeDwisButton), SIGNAL(clicked()), this, SLOT(MergeDwis()) ); connect( (QObject*)(m_Controls->m_AdcSignalAverage), SIGNAL(clicked()), this, SLOT(DoADCAverage()) ); //connect( (QObject*)(m_Controls->m_AdcSignalFit), SIGNAL(clicked()), this, SLOT(DoADCFit()) ); connect( (QObject*)(m_Controls->m_AkcSignalFit), SIGNAL(clicked()), this, SLOT(DoAKCFit()) ); connect( (QObject*)(m_Controls->m_BiExpSignalFit), SIGNAL(clicked()), this, SLOT(DoBiExpFit()) ); connect( (QObject*)(m_Controls->m_B_ValueMap_Rounder_SpinBox), SIGNAL(valueChanged(int)), this, SLOT(UpdateDwiBValueMapRounder(int))); connect( (QObject*)(m_Controls->m_CreateLengthCorrectedDwi), SIGNAL(clicked()), this, SLOT(DoLengthCorrection()) ); connect( (QObject*)(m_Controls->m_CalcAdcButton), SIGNAL(clicked()), this, SLOT(DoAdcCalculation()) ); } } void QmitkPreprocessingView::DoLengthCorrection() { if (m_DiffusionImage.IsNull()) return; typedef mitk::DiffusionImage DiffusionImageType; typedef itk::DwiGradientLengthCorrectionFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetRoundingValue( m_Controls->m_B_ValueMap_Rounder_SpinBox->value()); filter->SetReferenceBValue(m_DiffusionImage->GetB_Value()); filter->SetReferenceGradientDirectionContainer(m_DiffusionImage->GetDirections()); filter->Update(); DiffusionImageType::Pointer image = DiffusionImageType::New(); image->SetVectorImage( m_DiffusionImage->GetVectorImage()); image->SetB_Value( filter->GetNewBValue() ); image->SetDirections( filter->GetOutputGradientDirectionContainer()); image->InitializeFromVectorImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( image ); QString name = m_SelectedDiffusionNodes.front()->GetName().c_str(); imageNode->SetName((name+"_rounded").toStdString().c_str()); GetDefaultDataStorage()->Add(imageNode); } void QmitkPreprocessingView::UpdateDwiBValueMapRounder(int i) { if (m_DiffusionImage.IsNull()) return; m_DiffusionImage->UpdateBValueMap(); UpdateBValueTableWidget(i); } void QmitkPreprocessingView::CallMultishellToSingleShellFilter(itk::DWIVoxelFunctor * functor, mitk::DiffusionImage::Pointer ImPtr, QString imageName) { typedef itk::RadialMultishellToSingleshellImageFilter FilterType; // filter input parameter const mitk::DiffusionImage::BValueMap &originalShellMap = ImPtr->GetB_ValueMap(); const mitk::DiffusionImage::ImageType *vectorImage = ImPtr->GetVectorImage(); const mitk::DiffusionImage::GradientDirectionContainerType::Pointer gradientContainer = ImPtr->GetDirections(); const unsigned int &bValue = ImPtr->GetB_Value(); mitk::DataNode::Pointer imageNode = 0; // filter call FilterType::Pointer filter = FilterType::New(); filter->SetInput(vectorImage); filter->SetOriginalGradientDirections(gradientContainer); filter->SetOriginalBValueMap(originalShellMap); filter->SetOriginalBValue(bValue); filter->SetFunctor(functor); filter->Update(); // create new DWI image mitk::DiffusionImage::Pointer outImage = mitk::DiffusionImage::New(); outImage->SetVectorImage( filter->GetOutput() ); outImage->SetB_Value( m_Controls->m_targetBValueSpinBox->value() ); outImage->SetDirections( filter->GetTargetGradientDirections() ); outImage->InitializeFromVectorImage(); imageNode = mitk::DataNode::New(); imageNode->SetData( outImage ); imageNode->SetName(imageName.toStdString().c_str()); GetDefaultDataStorage()->Add(imageNode); - // create new Error image - FilterType::ErrorImageType::Pointer errImage = filter->GetErrorImage(); - mitk::Image::Pointer mitkErrImage = mitk::Image::New(); - mitkErrImage->InitializeByItk(errImage); - mitkErrImage->SetVolume(errImage->GetBufferPointer()); - - imageNode = mitk::DataNode::New(); - imageNode->SetData( mitkErrImage ); - imageNode->SetName((imageName+"_Error").toStdString().c_str()); - GetDefaultDataStorage()->Add(imageNode); + if(m_Controls->m_OutputRMSErrorImage->isChecked()){ + // create new Error image + FilterType::ErrorImageType::Pointer errImage = filter->GetErrorImage(); + mitk::Image::Pointer mitkErrImage = mitk::Image::New(); + mitkErrImage->InitializeByItk(errImage); + mitkErrImage->SetVolume(errImage->GetBufferPointer()); + + imageNode = mitk::DataNode::New(); + imageNode->SetData( mitkErrImage ); + imageNode->SetName((imageName+"_Error").toStdString().c_str()); + GetDefaultDataStorage()->Add(imageNode); + } } void QmitkPreprocessingView::DoBiExpFit() { itk::BiExpFitFunctor::Pointer functor = itk::BiExpFitFunctor::New(); for (int i=0; i::Pointer inImage = dynamic_cast< mitk::DiffusionImage* >(m_SelectedDiffusionNodes.at(i)->GetData()); QString name(m_SelectedDiffusionNodes.at(i)->GetName().c_str()); const mitk::DiffusionImage::BValueMap & originalShellMap = inImage->GetB_ValueMap(); mitk::DiffusionImage::BValueMap::const_iterator it = originalShellMap.begin(); ++it;/* skip b=0*/ unsigned int s = 0; /*shell index */ vnl_vector bValueList(originalShellMap.size()-1); while(it != originalShellMap.end()) bValueList.put(s++,(it++)->first); const double targetBValue = bValueList.mean(); functor->setListOfBValues(bValueList); functor->setTargetBValue(targetBValue); CallMultishellToSingleShellFilter(functor,inImage,name + "_BiExp"); } } void QmitkPreprocessingView::DoAKCFit() { itk::KurtosisFitFunctor::Pointer functor = itk::KurtosisFitFunctor::New(); for (int i=0; i::Pointer inImage = dynamic_cast< mitk::DiffusionImage* >(m_SelectedDiffusionNodes.at(i)->GetData()); QString name(m_SelectedDiffusionNodes.at(i)->GetName().c_str()); const mitk::DiffusionImage::BValueMap & originalShellMap = inImage->GetB_ValueMap(); mitk::DiffusionImage::BValueMap::const_iterator it = originalShellMap.begin(); ++it;/* skip b=0*/ unsigned int s = 0; /*shell index */ vnl_vector bValueList(originalShellMap.size()-1); while(it != originalShellMap.end()) bValueList.put(s++,(it++)->first); const double targetBValue = bValueList.mean(); functor->setListOfBValues(bValueList); functor->setTargetBValue(targetBValue); CallMultishellToSingleShellFilter(functor,inImage,name + "_AKC"); } } void QmitkPreprocessingView::DoADCFit() { // later } void QmitkPreprocessingView::DoADCAverage() { itk::ADCAverageFunctor::Pointer functor = itk::ADCAverageFunctor::New(); for (int i=0; i::Pointer inImage = dynamic_cast< mitk::DiffusionImage* >(m_SelectedDiffusionNodes.at(i)->GetData()); QString name(m_SelectedDiffusionNodes.at(i)->GetName().c_str()); const mitk::DiffusionImage::BValueMap & originalShellMap = inImage->GetB_ValueMap(); mitk::DiffusionImage::BValueMap::const_iterator it = originalShellMap.begin(); ++it;/* skip b=0*/ unsigned int s = 0; /*shell index */ vnl_vector bValueList(originalShellMap.size()-1); while(it != originalShellMap.end()) bValueList.put(s++,(it++)->first); const double targetBValue = bValueList.mean(); functor->setListOfBValues(bValueList); functor->setTargetBValue(targetBValue); CallMultishellToSingleShellFilter(functor,inImage,name + "_ADC"); } } void QmitkPreprocessingView::DoAdcCalculation() { if (m_DiffusionImage.IsNull()) return; typedef mitk::DiffusionImage< DiffusionPixelType > DiffusionImageType; typedef itk::AdcImageFilter< DiffusionPixelType, double > FilterType; for (int i=0; i(m_SelectedDiffusionNodes.at(i)->GetData()); FilterType::Pointer filter = FilterType::New(); filter->SetInput(inImage->GetVectorImage()); filter->SetGradientDirections(inImage->GetDirections()); filter->SetB_value(inImage->GetB_Value()); filter->Update(); mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk( filter->GetOutput() ); image->SetVolume( filter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( image ); QString name = m_SelectedDiffusionNodes.at(i)->GetName().c_str(); imageNode->SetName((name+"_ADC").toStdString().c_str()); GetDefaultDataStorage()->Add(imageNode); } } void QmitkPreprocessingView::UpdateBValueTableWidget(int i) { foreach(QCheckBox * box, m_ReduceGradientCheckboxes) { m_Controls->m_ReductionFrame->layout()->removeWidget(box); delete box; } foreach(QSpinBox * box, m_ReduceGradientSpinboxes) { m_Controls->m_ReductionFrame->layout()->removeWidget(box); delete box; } m_ReduceGradientCheckboxes.clear(); m_ReduceGradientSpinboxes.clear(); if (m_DiffusionImage.IsNull()) { m_Controls->m_B_ValueMap_TableWidget->clear(); m_Controls->m_B_ValueMap_TableWidget->setRowCount(1); QStringList headerList; headerList << "b-Value" << "Number of gradients"; m_Controls->m_B_ValueMap_TableWidget->setHorizontalHeaderLabels(headerList); m_Controls->m_B_ValueMap_TableWidget->setItem(0,0,new QTableWidgetItem("-")); m_Controls->m_B_ValueMap_TableWidget->setItem(0,1,new QTableWidgetItem("-")); }else{ typedef mitk::DiffusionImage::BValueMap BValueMap; typedef mitk::DiffusionImage::BValueMap::iterator BValueMapIterator; BValueMapIterator it; BValueMap roundedBValueMap; GradientDirectionContainerType::ConstIterator gdcit; for( gdcit = m_DiffusionImage->GetDirections()->Begin(); gdcit != m_DiffusionImage->GetDirections()->End(); ++gdcit) { float currentBvalue = std::floor(m_DiffusionImage->GetB_Value(gdcit.Index())); unsigned int rounded = int((currentBvalue + 0.5 * i)/i)*i; roundedBValueMap[rounded].push_back(gdcit.Index()); } m_Controls->m_B_ValueMap_TableWidget->clear(); m_Controls->m_B_ValueMap_TableWidget->setRowCount(roundedBValueMap.size() ); QStringList headerList; headerList << "b-Value" << "Number of gradients"; m_Controls->m_B_ValueMap_TableWidget->setHorizontalHeaderLabels(headerList); QCheckBox* checkBox; QSpinBox* spinBox; int i = 0 ; for(it = roundedBValueMap.begin() ;it != roundedBValueMap.end(); it++) { m_Controls->m_B_ValueMap_TableWidget->setItem(i,0,new QTableWidgetItem(QString::number(it->first))); m_Controls->m_B_ValueMap_TableWidget->setItem(i,1,new QTableWidgetItem(QString::number(it->second.size()))); // Reduce Gradients GUI adaption if(it->first != 0 && roundedBValueMap.size() > 1){ checkBox = new QCheckBox(QString::number(it->first) + " with " + QString::number(it->second.size()) + " directions"); checkBox->setEnabled(true); checkBox->setChecked(true); checkBox->setCheckable(true); m_ReduceGradientCheckboxes.push_back(checkBox); m_Controls->m_ReductionFrame->layout()->addWidget(checkBox); spinBox = new QSpinBox(); spinBox->setValue(std::ceil((float)it->second.size())); spinBox->setMaximum(it->second.size()); spinBox->setMinimum(0); m_ReduceGradientSpinboxes.push_back(spinBox); m_Controls->m_ReductionFrame->layout()->addWidget(spinBox); } i++; } } } void QmitkPreprocessingView::OnSelectionChanged( std::vector nodes ) { bool foundDwiVolume = false; m_DiffusionImage = NULL; m_SelectedDiffusionNodes.clear(); // iterate selection for( std::vector::iterator it = nodes.begin(); it != nodes.end(); ++it ) { mitk::DataNode::Pointer node = *it; if( node.IsNotNull() && dynamic_cast*>(node->GetData()) ) { foundDwiVolume = true; m_DiffusionImage = dynamic_cast*>(node->GetData()); m_Controls->m_DiffusionImageLabel->setText(node->GetName().c_str()); m_SelectedDiffusionNodes.push_back(node); } } m_Controls->m_ButtonAverageGradients->setEnabled(foundDwiVolume); m_Controls->m_ButtonExtractB0->setEnabled(foundDwiVolume); m_Controls->m_CheckExtractAll->setEnabled(foundDwiVolume); m_Controls->m_ModifyMeasurementFrame->setEnabled(foundDwiVolume); m_Controls->m_MeasurementFrameTable->setEnabled(foundDwiVolume); m_Controls->m_ReduceGradientsButton->setEnabled(foundDwiVolume); m_Controls->m_ShowGradientsButton->setEnabled(foundDwiVolume); m_Controls->m_MirrorGradientToHalfSphereButton->setEnabled(foundDwiVolume); m_Controls->m_MergeDwisButton->setEnabled(foundDwiVolume); m_Controls->m_B_ValueMap_Rounder_SpinBox->setEnabled(foundDwiVolume); //m_Controls->m_AdcSignalFit->setEnabled(foundDwiVolume); m_Controls->m_AdcSignalAverage->setEnabled(foundDwiVolume); m_Controls->m_AkcSignalFit->setEnabled(foundDwiVolume); m_Controls->m_BiExpSignalFit->setEnabled(foundDwiVolume); m_Controls->m_CreateLengthCorrectedDwi->setEnabled(foundDwiVolume); m_Controls->m_CalcAdcButton->setEnabled(foundDwiVolume); m_Controls->m_targetBValueSpinBox->setEnabled(foundDwiVolume); + m_Controls->m_OutputRMSErrorImage->setEnabled(foundDwiVolume); UpdateBValueTableWidget(m_Controls->m_B_ValueMap_Rounder_SpinBox->value()); if (foundDwiVolume) { m_Controls->m_InputData->setTitle("Input Data"); vnl_matrix_fixed< double, 3, 3 > mf = m_DiffusionImage->GetMeasurementFrame(); for (int r=0; r<3; r++) for (int c=0; c<3; c++) { QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item(r,c); delete item; item = new QTableWidgetItem(); item->setTextAlignment(Qt::AlignCenter | Qt::AlignVCenter); item->setText(QString::number(mf.get(r,c))); m_Controls->m_MeasurementFrameTable->setItem(r,c,item); } //calculate target bValue for MultishellToSingleShellfilter const mitk::DiffusionImage::BValueMap & bValMap = m_DiffusionImage->GetB_ValueMap(); mitk::DiffusionImage::BValueMap::const_iterator it = bValMap.begin(); unsigned int targetBVal = 0; while(it != bValMap.end()) targetBVal += (it++)->first; targetBVal /= (float)bValMap.size()-1; m_Controls->m_targetBValueSpinBox->setValue(targetBVal); } else { for (int r=0; r<3; r++) for (int c=0; c<3; c++) { QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item(r,c); delete item; item = new QTableWidgetItem(); m_Controls->m_MeasurementFrameTable->setItem(r,c,item); } m_Controls->m_DiffusionImageLabel->setText("mandatory"); m_Controls->m_InputData->setTitle("Please Select Input Data"); } } void QmitkPreprocessingView::Activated() { QmitkFunctionality::Activated(); } void QmitkPreprocessingView::Deactivated() { QmitkFunctionality::Deactivated(); } void QmitkPreprocessingView::DoHalfSphereGradientDirections() { GradientDirectionContainerType::Pointer gradientContainer = m_DiffusionImage->GetDirections(); for (int j=0; jSize(); j++) if (gradientContainer->at(j)[0]<0) gradientContainer->at(j) = -gradientContainer->at(j); m_DiffusionImage->SetDirections(gradientContainer); } void QmitkPreprocessingView::DoApplyMesurementFrame() { if (m_DiffusionImage.IsNull()) return; vnl_matrix_fixed< double, 3, 3 > mf; for (int r=0; r<3; r++) for (int c=0; c<3; c++) { QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item(r,c); if (!item) return; mf[r][c] = item->text().toDouble(); } m_DiffusionImage->SetMeasurementFrame(mf); } void QmitkPreprocessingView::DoShowGradientDirections() { if (m_DiffusionImage.IsNull()) return; int maxIndex = 0; int maxSize = m_DiffusionImage->GetDimension(0); if (maxSizeGetDimension(1)) { maxSize = m_DiffusionImage->GetDimension(1); maxIndex = 1; } if (maxSizeGetDimension(2)) { maxSize = m_DiffusionImage->GetDimension(2); maxIndex = 2; } mitk::Point3D origin = m_DiffusionImage->GetGeometry()->GetOrigin(); mitk::PointSet::Pointer originSet = mitk::PointSet::New(); typedef mitk::DiffusionImage::BValueMap BValueMap; typedef mitk::DiffusionImage::BValueMap::iterator BValueMapIterator; BValueMap bValMap = m_DiffusionImage->GetB_ValueMap(); GradientDirectionContainerType::Pointer gradientContainer = m_DiffusionImage->GetDirections(); mitk::Geometry3D::Pointer geometry = m_DiffusionImage->GetGeometry(); int shellCount = 1; for(BValueMapIterator it = bValMap.begin(); it!=bValMap.end(); ++it) { mitk::PointSet::Pointer pointset = mitk::PointSet::New(); for (int j=0; jsecond.size(); j++) { mitk::Point3D ip; vnl_vector_fixed< double, 3 > v = gradientContainer->at(it->second[j]); if (v.magnitude()>mitk::eps) { ip[0] = v[0]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[0]-0.5*geometry->GetSpacing()[0] + geometry->GetSpacing()[0]*m_DiffusionImage->GetDimension(0)/2; ip[1] = v[1]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[1]-0.5*geometry->GetSpacing()[1] + geometry->GetSpacing()[1]*m_DiffusionImage->GetDimension(1)/2; ip[2] = v[2]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[2]-0.5*geometry->GetSpacing()[2] + geometry->GetSpacing()[2]*m_DiffusionImage->GetDimension(2)/2; pointset->InsertPoint(j, ip); } else if (originSet->IsEmpty()) { ip[0] = v[0]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[0]-0.5*geometry->GetSpacing()[0] + geometry->GetSpacing()[0]*m_DiffusionImage->GetDimension(0)/2; ip[1] = v[1]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[1]-0.5*geometry->GetSpacing()[1] + geometry->GetSpacing()[1]*m_DiffusionImage->GetDimension(1)/2; ip[2] = v[2]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[2]-0.5*geometry->GetSpacing()[2] + geometry->GetSpacing()[2]*m_DiffusionImage->GetDimension(2)/2; originSet->InsertPoint(j, ip); } } if (it->firstSetData(pointset); QString name = m_SelectedDiffusionNodes.front()->GetName().c_str(); name += "_Shell_"; name += QString::number(it->first); node->SetName(name.toStdString().c_str()); node->SetProperty("pointsize", mitk::FloatProperty::New((float)maxSize/50)); int b0 = shellCount%2; int b1 = 0; int b2 = 0; if (shellCount>4) b2 = 1; if (shellCount%4 >= 2) b1 = 1; node->SetProperty("color", mitk::ColorProperty::New(b2, b1, b0)); GetDefaultDataStorage()->Add(node, m_SelectedDiffusionNodes.front()); shellCount++; } // add origin to datastorage mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(originSet); QString name = m_SelectedDiffusionNodes.front()->GetName().c_str(); name += "_Origin"; node->SetName(name.toStdString().c_str()); node->SetProperty("pointsize", mitk::FloatProperty::New((float)maxSize/50)); node->SetProperty("color", mitk::ColorProperty::New(1,1,1)); GetDefaultDataStorage()->Add(node, m_SelectedDiffusionNodes.front()); } void QmitkPreprocessingView::DoReduceGradientDirections() { if (m_DiffusionImage.IsNull()) return; typedef mitk::DiffusionImage DiffusionImageType; typedef itk::ElectrostaticRepulsionDiffusionGradientReductionFilter FilterType; typedef DiffusionImageType::BValueMap BValueMap; // GetShellSelection from GUI BValueMap shellSlectionMap; BValueMap originalShellMap = m_DiffusionImage->GetB_ValueMap(); std::vector newNumGradientDirections; int shellCounter = 0; foreach(QCheckBox * box , m_ReduceGradientCheckboxes) { if(box->isChecked()) { double BValue = (box->text().split(' ')).at(0).toDouble(); shellSlectionMap[BValue] = originalShellMap[BValue]; newNumGradientDirections.push_back(m_ReduceGradientSpinboxes.at(shellCounter)->value()); } shellCounter++; } if (newNumGradientDirections.empty()) return; GradientDirectionContainerType::Pointer gradientContainer = m_DiffusionImage->GetDirections(); FilterType::Pointer filter = FilterType::New(); filter->SetInput(m_DiffusionImage->GetVectorImage()); filter->SetOriginalGradientDirections(gradientContainer); filter->SetNumGradientDirections(newNumGradientDirections); filter->SetOriginalBValueMap(originalShellMap); filter->SetShellSelectionBValueMap(shellSlectionMap); filter->Update(); DiffusionImageType::Pointer image = DiffusionImageType::New(); image->SetVectorImage( filter->GetOutput() ); image->SetB_Value(m_DiffusionImage->GetB_Value()); image->SetDirections(filter->GetGradientDirections()); image->SetMeasurementFrame(m_DiffusionImage->GetMeasurementFrame()); image->InitializeFromVectorImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( image ); QString name = m_SelectedDiffusionNodes.front()->GetName().c_str(); QList::iterator itSpinBox = m_ReduceGradientSpinboxes.begin(); QList::iterator itCheckBox = m_ReduceGradientCheckboxes.begin(); while(itSpinBox != m_ReduceGradientSpinboxes.end() && itCheckBox != m_ReduceGradientCheckboxes.end()) { name += "_"; if((*itCheckBox)->isChecked()){ name += QString::number((*itSpinBox)->value()); }else { name += QString::number(0); } ++itSpinBox; ++itCheckBox; } imageNode->SetName(name.toStdString().c_str()); GetDefaultDataStorage()->Add(imageNode); } void QmitkPreprocessingView::MergeDwis() { typedef mitk::DiffusionImage DiffusionImageType; typedef DiffusionImageType::GradientDirectionContainerType GradientContainerType; if (m_SelectedDiffusionNodes.size()<2) return; typedef itk::VectorImage DwiImageType; typedef DwiImageType::PixelType DwiPixelType; typedef DwiImageType::RegionType DwiRegionType; typedef std::vector< DwiImageType::Pointer > DwiImageContainerType; typedef std::vector< GradientContainerType::Pointer > GradientListContainerType; DwiImageContainerType imageContainer; GradientListContainerType gradientListContainer; std::vector< double > bValueContainer; QString name = m_SelectedDiffusionNodes.front()->GetName().c_str(); for (int i=0; i* >( m_SelectedDiffusionNodes.at(i)->GetData() ); if ( dwi.IsNotNull() ) { imageContainer.push_back(dwi->GetVectorImage()); gradientListContainer.push_back(dwi->GetDirections()); bValueContainer.push_back(dwi->GetB_Value()); if (i>0) { name += "+"; name += m_SelectedDiffusionNodes.at(i)->GetName().c_str(); } } } typedef itk::MergeDiffusionImagesFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetImageVolumes(imageContainer); filter->SetGradientLists(gradientListContainer); filter->SetBValues(bValueContainer); filter->Update(); vnl_matrix_fixed< double, 3, 3 > mf; mf.set_identity(); DiffusionImageType::Pointer image = DiffusionImageType::New(); image->SetVectorImage( filter->GetOutput() ); image->SetB_Value(filter->GetB_Value()); image->SetDirections(filter->GetOutputGradients()); image->SetMeasurementFrame(mf); image->InitializeFromVectorImage(); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( image ); imageNode->SetName(name.toStdString().c_str()); GetDefaultDataStorage()->Add(imageNode); } void QmitkPreprocessingView::ExtractB0() { typedef mitk::DiffusionImage DiffusionImageType; typedef DiffusionImageType::GradientDirectionContainerType GradientContainerType; int nrFiles = m_SelectedDiffusionNodes.size(); if (!nrFiles) return; // call the extraction withou averaging if the check-box is checked if( this->m_Controls->m_CheckExtractAll->isChecked() ) { DoExtractBOWithoutAveraging(); return; } mitk::DataStorage::SetOfObjects::const_iterator itemiter( m_SelectedDiffusionNodes.begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( m_SelectedDiffusionNodes.end() ); std::vector nodes; while ( itemiter != itemiterend ) // for all items { DiffusionImageType* vols = static_cast( (*itemiter)->GetData()); std::string nodename; (*itemiter)->GetStringProperty("name", nodename); // Extract image using found index typedef itk::B0ImageExtractionImageFilter FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetInput(vols->GetVectorImage()); filter->SetDirections(vols->GetDirections()); filter->Update(); mitk::Image::Pointer mitkImage = mitk::Image::New(); mitkImage->InitializeByItk( filter->GetOutput() ); mitkImage->SetVolume( filter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer node=mitk::DataNode::New(); node->SetData( mitkImage ); node->SetProperty( "name", mitk::StringProperty::New(nodename + "_B0")); GetDefaultDataStorage()->Add(node); ++itemiter; } } void QmitkPreprocessingView::DoExtractBOWithoutAveraging() { // typedefs typedef mitk::DiffusionImage DiffusionImageType; typedef DiffusionImageType::GradientDirectionContainerType GradientContainerType; typedef itk::B0ImageExtractionToSeparateImageFilter< short, short> FilterType; // check number of selected objects, return if empty int nrFiles = m_SelectedDiffusionNodes.size(); if (!nrFiles) return; mitk::DataStorage::SetOfObjects::const_iterator itemiter( m_SelectedDiffusionNodes.begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( m_SelectedDiffusionNodes.end() ); while ( itemiter != itemiterend ) // for all items { DiffusionImageType* vols = static_cast( (*itemiter)->GetData()); std::string nodename; (*itemiter)->GetStringProperty("name", nodename); // Extract image using found index FilterType::Pointer filter = FilterType::New(); filter->SetInput(vols->GetVectorImage()); filter->SetDirections(vols->GetDirections()); filter->Update(); mitk::Image::Pointer mitkImage = mitk::Image::New(); mitkImage->InitializeByItk( filter->GetOutput() ); mitkImage->SetImportChannel( filter->GetOutput()->GetBufferPointer() ); mitk::DataNode::Pointer node=mitk::DataNode::New(); node->SetData( mitkImage ); node->SetProperty( "name", mitk::StringProperty::New(nodename + "_B0_ALL")); GetDefaultDataStorage()->Add(node); ++itemiter; } } void QmitkPreprocessingView::AverageGradients() { int nrFiles = m_SelectedDiffusionNodes.size(); if (!nrFiles) return; mitk::DataStorage::SetOfObjects::const_iterator itemiter( m_SelectedDiffusionNodes.begin() ); mitk::DataStorage::SetOfObjects::const_iterator itemiterend( m_SelectedDiffusionNodes.end() ); std::vector nodes; while ( itemiter != itemiterend ) // for all items { mitk::DiffusionImage* vols = static_cast*>( (*itemiter)->GetData()); vols->AverageRedundantGradients(m_Controls->m_Blur->value()); ++itemiter; } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingViewControls.ui index ce718bc2e4..0e01a927db 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkPreprocessingViewControls.ui @@ -1,682 +1,692 @@ QmitkPreprocessingViewControls 0 0 892 - 1316 + 1351 0 0 false QmitkPreprocessingViewControls true Please Select Input Data Raw DWI: <html><head/><body><p><span style=" color:#ff0000;">mandatory</span></p></body></html> true 0 0 Info + + + + + 0 + 0 + + + + Qt::ScrollBarAsNeeded + + + Qt::ScrollBarAlwaysOff + + + true + + + 100 + + + true + + + false + + + true + + + + b-Value + + + + + Number of gradients + + + + + + + + false + + + Round b-value + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + false + + + 100000 + + + false <html><head/><body><p>Create a new Diffusion Weighted Image (DWI) using an ADC average over all q-shells.</p></body></html> ADC Signal Average false AKC Signal Fit false Bi-Exponential Signal Fit <html><head/><body><p>Define the sampling frame the b-Values are rounded with.</p></body></html> Sampling frame: false <html><head/><body><p>Round b-values to nearest multiple of this value (click &quot;Round b-value&quot; to create new image with these values).</p></body></html> QAbstractSpinBox::CorrectToNearestValue 1 10000 10 false Generate pointset displaying the gradient vectors (applied measurement frame). Show gradients - - - - - 0 - 0 - - - - Qt::ScrollBarAsNeeded - - - Qt::ScrollBarAlwaysOff - - - true - - - 100 - - - true - - - false - - - true - - - - b-Value - - - - - Number of gradients - - - - - - + + false - Round b-value - - - - - - - Qt::Horizontal - - - - - - - Qt::Horizontal - - - - - - - Qt::Horizontal - - - - - - - false - - - 100000 + Output RMS-Error Image Non diffusion weighted image 0 30 Average and extract all images that were acquired without diffusion weighting. true false If multiple baseline acquisitions are present, the default behaviour is to output an averaged image. Extract B0 Create a 3D+t data set containing all b0 images as timesteps Extract all B0 images without averaging false If multiple baseline acquisitions are present, the default behaviour is to output an averaged image. Calculate ADC map Modify DWI QFrame::NoFrame QFrame::Raised 0 Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. 6 2.000000000000000 0.000100000000000 0.001000000000000 Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Accumulates the information that was acquired with multiple repetitions for one gradient. Vectors do not have to be precisely equal in order to be merged, if a "Merge radius" > 0 is configured. Merge radius false Multiple acquistions of one gradient direction can be averaged. Due to rounding errors, similar gradients often differ in the last decimal positions. The Merge radius allows to average them by taking all directions within a certain radius into account. Average redundant gradients Qt::Horizontal QFrame::NoFrame QFrame::Raised 0 9 Specify desired number of gradients per shell: Qt::Horizontal 40 20 false Retain only the specified number of gradient directions and according image volumes. The retained directions are spread equally over the half sphere using an iterative energy repulsion strategy. Reduce number of gradients Qt::Horizontal false Sometimes the gradient directions are not located on one half sphere. Mirror gradients to half sphere Merge selected images false Merges selected DWIs of same dimension. If several b-values are present, the resulting image will contain multiple b-shells. Merge selected DWIs 0 0 Measurment frame Qt::Horizontal 40 20 false 0 0 0 0 IBeamCursor true Qt::ScrollBarAlwaysOff Qt::ScrollBarAlwaysOff true false false true true 0 false true true New Row New Row New Row New Column New Column New Column false Apply new measurement frame Qt::Vertical 20 40