diff --git a/Modules/DiffusionCmdApps/Quantification/TensorReconstruction.cpp b/Modules/DiffusionCmdApps/Quantification/TensorReconstruction.cpp index a497247..ef50f68 100644 --- a/Modules/DiffusionCmdApps/Quantification/TensorReconstruction.cpp +++ b/Modules/DiffusionCmdApps/Quantification/TensorReconstruction.cpp @@ -1,135 +1,137 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center. 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 "mitkImage.h" #include #include "mitkBaseData.h" #include #include #include #include #include #include #include "mitkDiffusionCommandLineParser.h" #include #include #include +#include /** * Convert files from one ending to the other */ int main(int argc, char* argv[]) { mitkDiffusionCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input image", "input raw dwi", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input); parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output image", "output image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output); parser.addArgument("b0_threshold", "", mitkDiffusionCommandLineParser::Int, "b0 threshold", "baseline image intensity threshold", 0); parser.addArgument("correct_negative_eigenv", "", mitkDiffusionCommandLineParser::Bool, "Correct negative eigenvalues", "correct negative eigenvalues", us::Any(false)); parser.setCategory("Signal Modelling"); parser.setTitle("Tensor Reconstruction"); parser.setDescription(""); parser.setContributor("MIC"); std::map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; std::string inFileName = us::any_cast(parsedArgs["i"]); std::string outfilename = us::any_cast(parsedArgs["o"]); if (!itksys::SystemTools::GetFilenamePath(outfilename).empty()) outfilename = itksys::SystemTools::GetFilenamePath(outfilename)+"/"+itksys::SystemTools::GetFilenameWithoutExtension(outfilename); else outfilename = itksys::SystemTools::GetFilenameWithoutExtension(outfilename); outfilename += ".dti"; int threshold = 0; if (parsedArgs.count("b0_threshold")) threshold = us::any_cast(parsedArgs["b0_threshold"]); bool correct_negative_eigenv = false; if (parsedArgs.count("correct_negative_eigenv")) correct_negative_eigenv = us::any_cast(parsedArgs["correct_negative_eigenv"]); try { - mitk::Image::Pointer dwi = mitk::IOUtil::Load(inFileName); + mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images"}, std::vector()); + mitk::Image::Pointer dwi = mitk::IOUtil::Load(inFileName, &functor); mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New(); mitk::CastToItkImage(dwi, itkVectorImagePointer); if (correct_negative_eigenv) { typedef itk::TensorReconstructionWithEigenvalueCorrectionFilter< short, float > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi)); filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), itkVectorImagePointer); filter->SetB0Threshold(threshold); filter->Update(); // Save tensor image itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); io->SetFileType( itk::ImageIOBase::Binary ); io->UseCompressionOn(); mitk::LocaleSwitch localeSwitch("C"); itk::ImageFileWriter< itk::Image< itk::DiffusionTensor3D< float >, 3 > >::Pointer writer = itk::ImageFileWriter< itk::Image< itk::DiffusionTensor3D< float >, 3 > >::New(); writer->SetInput(filter->GetOutput()); writer->SetFileName(outfilename); writer->SetImageIO(io); writer->UseCompressionOn(); writer->Update(); } else { typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, float > TensorReconstructionImageFilterType; TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New(); filter->SetGradientImage( dynamic_cast(dwi->GetProperty(mitk::DiffusionPropertyHelper::GetGradientContainerPropertyName().c_str()).GetPointer())->GetGradientDirectionsContainerCopy(), itkVectorImagePointer ); filter->SetBValue( mitk::DiffusionPropertyHelper::GetReferenceBValue( dwi )); filter->SetThreshold(threshold); filter->Update(); // Save tensor image itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); io->SetFileType( itk::ImageIOBase::Binary ); io->UseCompressionOn(); mitk::LocaleSwitch localeSwitch("C"); itk::ImageFileWriter< itk::Image< itk::DiffusionTensor3D< float >, 3 > >::Pointer writer = itk::ImageFileWriter< itk::Image< itk::DiffusionTensor3D< float >, 3 > >::New(); writer->SetInput(filter->GetOutput()); writer->SetFileName(outfilename); writer->SetImageIO(io); writer->UseCompressionOn(); writer->Update(); } } catch ( itk::ExceptionObject &err) { std::cout << "Exception: " << err; } catch ( std::exception& err) { std::cout << "Exception: " << err.what(); } catch ( ... ) { std::cout << "Exception!"; } return EXIT_SUCCESS; } diff --git a/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNiftiReader.cpp b/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNiftiReader.cpp index 1ab2830..1fe96a8 100644 --- a/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNiftiReader.cpp +++ b/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNiftiReader.cpp @@ -1,489 +1,489 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center. 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. ===================================================================*/ #ifndef __mitkDiffusionImageNiftiReader_cpp #define __mitkDiffusionImageNiftiReader_cpp #include "mitkDiffusionImageNiftiReader.h" #include #include // Diffusion properties #include #include #include #include // ITK includes #include #include #include "itksys/SystemTools.hxx" #include "itkImageFileReader.h" #include "itkMetaDataObject.h" #include "itkNiftiImageIO.h" #include #include #include #include "mitkCustomMimeType.h" #include "mitkDiffusionIOMimeTypes.h" #include #include #include #include #include "mitkIOUtil.h" #include #include #include #include namespace mitk { DiffusionImageNiftiReader:: DiffusionImageNiftiReader(const DiffusionImageNiftiReader & other) : AbstractFileReader(other) { } DiffusionImageNiftiReader* DiffusionImageNiftiReader::Clone() const { return new DiffusionImageNiftiReader(*this); } DiffusionImageNiftiReader:: ~DiffusionImageNiftiReader() {} DiffusionImageNiftiReader:: DiffusionImageNiftiReader() : mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::DWI_NIFTI_MIMETYPE() ), mitk::DiffusionIOMimeTypes::DWI_NIFTI_MIMETYPE_DESCRIPTION() ) { Options defaultOptions; defaultOptions["Apply image rotation to gradients"] = true; this->SetDefaultOptions(defaultOptions); m_ServiceReg = this->RegisterService(); } std::vector > DiffusionImageNiftiReader:: DoRead() { std::vector > result; // Since everything is completely read in GenerateOutputInformation() it is stored // in a cache variable. A timestamp is associated. // If the timestamp of the cache variable is newer than the MTime, we only need to // assign the cache variable to the DataObject. // Otherwise, the tree must be read again from the file and OuputInformation must // be updated! if(m_OutputCache.IsNull()) InternalRead(); result.push_back(m_OutputCache.GetPointer()); return result; } void DiffusionImageNiftiReader::InternalRead() { OutputType::Pointer outputForCache = OutputType::New(); if ( this->GetInputLocation() == "") { throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, the filename to be read is empty!"); } else { try { mitk::LocaleSwitch localeSwitch("C"); MITK_INFO << "DiffusionImageNiftiReader: reading image information"; VectorImageType::Pointer itkVectorImage; std::string ext = this->GetMimeType()->GetExtension( this->GetInputLocation() ); ext = itksys::SystemTools::LowerCase( ext ); itk::Bruker2dseqImageIO::Pointer bruker_io = itk::Bruker2dseqImageIO::New(); typedef itk::Image ImageType4D; ImageType4D::Pointer img4 = ImageType4D::New(); bool bruker = false; if(ext == ".nii" || ext == ".nii.gz") { // create reader and read file itk::NiftiImageIO::Pointer io2 = itk::NiftiImageIO::New(); if (io2->CanReadFile(this->GetInputLocation().c_str())) { typedef itk::ImageFileReader FileReaderType; FileReaderType::Pointer reader = FileReaderType::New(); reader->SetFileName( this->GetInputLocation() ); reader->SetImageIO(io2); reader->Update(); img4 = reader->GetOutput(); } else { vtkSmartPointer reader = vtkSmartPointer::New(); if (reader->CanReadFile(this->GetInputLocation().c_str())) { reader->SetFileName(this->GetInputLocation().c_str()); reader->SetTimeAsVector(true); reader->Update(); auto vtk_image = reader->GetOutput(); auto header = reader->GetNIFTIHeader(); auto dim = header->GetDim(0); auto matrix = reader->GetQFormMatrix(); if (matrix == nullptr) matrix = reader->GetSFormMatrix(); itk::Matrix direction; direction.SetIdentity(); itk::Matrix ras_lps; ras_lps.SetIdentity(); ras_lps[0][0] = -1; ras_lps[1][1] = -1; if (matrix != nullptr) { for (int r=0; rGetElement(r, c); } direction = direction*ras_lps; itk::Vector< double, 4 > spacing; spacing.Fill(1.0); vtk_image->GetSpacing(spacing.GetDataPointer()); itk::Point< double, 4 > origin; origin.Fill(0.0); vtk_image->GetOrigin(origin.GetDataPointer()); itk::ImageRegion< 4 > region; for (int i=0; i<4; ++i) if (iGetDim(i+1)); else region.SetSize(i, 1); img4->SetSpacing( spacing ); img4->SetOrigin( origin ); img4->SetDirection( direction ); img4->SetRegions( region ); img4->Allocate(); img4->FillBuffer(0); switch (header->GetDim(0)) { case 4: for (int g=0; gGetDim(4); g++) for (int z=0; zGetDim(3); z++) for (int y=0; yGetDim(2); y++) for (int x=0; xGetDim(1); x++) { double val = vtk_image->GetScalarComponentAsDouble(x, y, z, g); ImageType4D::IndexType idx; idx[0] = x; idx[1] = y; idx[2] = z; idx[3] = g; img4->SetPixel(idx, val); } break; default: mitkThrow() << "Image dimension " << header->GetDim(0) << " not supported!"; break; } } } } else if(bruker_io->CanReadFile(this->GetInputLocation().c_str())) { MITK_INFO << "Reading bruker 2dseq file"; typedef itk::ImageFileReader FileReaderType; FileReaderType::Pointer reader = FileReaderType::New(); reader->SetFileName( this->GetInputLocation() ); reader->SetImageIO(bruker_io); reader->Update(); img4 = reader->GetOutput(); bruker = true; } // convert 4D file to vector image itkVectorImage = VectorImageType::New(); VectorImageType::SpacingType spacing; ImageType4D::SpacingType spacing4 = img4->GetSpacing(); for(int i=0; i<3; i++) spacing[i] = spacing4[i]; itkVectorImage->SetSpacing( spacing ); // Set the image spacing VectorImageType::PointType origin; ImageType4D::PointType origin4 = img4->GetOrigin(); for(int i=0; i<3; i++) origin[i] = origin4[i]; itkVectorImage->SetOrigin( origin ); // Set the image origin VectorImageType::DirectionType direction; if (bruker) { MITK_INFO << "Setting image matrix to identity (bruker hack!!!)"; direction.SetIdentity(); } else { ImageType4D::DirectionType direction4 = img4->GetDirection(); for(int i=0; i<3; i++) for(int j=0; j<3; j++) direction[i][j] = direction4[i][j]; } itkVectorImage->SetDirection( direction ); // Set the image direction VectorImageType::RegionType region; ImageType4D::RegionType region4 = img4->GetLargestPossibleRegion(); VectorImageType::RegionType::SizeType size; ImageType4D::RegionType::SizeType size4 = region4.GetSize(); for(int i=0; i<3; i++) size[i] = size4[i]; VectorImageType::RegionType::IndexType index; ImageType4D::RegionType::IndexType index4 = region4.GetIndex(); for(int i=0; i<3; i++) index[i] = index4[i]; region.SetSize(size); region.SetIndex(index); itkVectorImage->SetRegions( region ); itkVectorImage->SetVectorLength(size4[3]); itkVectorImage->Allocate(); itk::ImageRegionIterator it ( itkVectorImage, itkVectorImage->GetLargestPossibleRegion() ); typedef VectorImageType::PixelType VecPixType; for (it.GoToBegin(); !it.IsAtEnd(); ++it) { VecPixType vec = it.Get(); VectorImageType::IndexType currentIndex = it.GetIndex(); for(int i=0; i<3; i++) index4[i] = currentIndex[i]; for(unsigned int ind=0; indGetPixel(index4); } it.Set(vec); } // Diffusion Image information START GradientDirectionContainerType::ConstPointer DiffusionVectors; MeasurementFrameType MeasurementFrame; MeasurementFrame.set_identity(); double BValue = -1; // Diffusion Image information END if(ext == ".nii" || ext == ".nii.gz") { std::string base_path = itksys::SystemTools::GetFilenamePath(this->GetInputLocation()); std::string base = this->GetMimeType()->GetFilenameWithoutExtension(this->GetInputLocation()); if (!base_path.empty()) { base = base_path + "/" + base; base_path += "/"; } // check for possible file names std::string bvals_file, bvecs_file; if (itksys::SystemTools::FileExists(base+".bvals")) bvals_file = base+".bvals"; else if (itksys::SystemTools::FileExists(base+".bval")) bvals_file = base+".bval"; else if (itksys::SystemTools::FileExists(base_path+"bvals")) bvals_file = base_path + "bvals"; else if (itksys::SystemTools::FileExists(base_path+"bval")) bvals_file = base_path + "bval"; if (itksys::SystemTools::FileExists(base+".bvecs")) bvecs_file = base+".bvecs"; else if (itksys::SystemTools::FileExists(base+".bvec")) - bvals_file = base+".bvec"; + bvecs_file = base+".bvec"; else if (itksys::SystemTools::FileExists(base_path+"bvecs")) bvecs_file = base_path + "bvecs"; else if (itksys::SystemTools::FileExists(base_path+"bvec")) bvecs_file = base_path + "bvec"; DiffusionVectors = mitk::gradients::ReadBvalsBvecs(bvals_file, bvecs_file, BValue); } else { MITK_INFO << "Parsing bruker method file for gradient information."; std::string base_path = itksys::SystemTools::GetFilenamePath(this->GetInputLocation()); std::string base = this->GetMimeType()->GetFilenameWithoutExtension(this->GetInputLocation()); base_path += "/../../"; std::string method_file = base_path + "method"; int g_count = 0; int num_gradients = 0; int num_b = 0; std::vector grad_values; std::vector b_values; std::fstream newfile; newfile.open(method_file,ios::in); std::string line; while(getline(newfile, line)) { std::vector result; boost::split(result, line, boost::is_any_of("=")); // check if current section is b-value section if (result.size()==2 && result.at(0)=="##$PVM_DwEffBval") { std::vector vec_spec; boost::split(vec_spec, result.at(1), boost::is_any_of("( )"), boost::token_compress_on); for (auto a : vec_spec) if (!a.empty()) { num_b = boost::lexical_cast(a); MITK_INFO << "Found " << num_b << " b-values"; break; } continue; } // check if current section is gradient vector value section if (result.size()==2 && result.at(0)=="##$PVM_DwGradVec") { std::vector vec_spec; boost::split(vec_spec, result.at(1), boost::is_any_of("( ,)"), boost::token_compress_on); for (auto a : vec_spec) if (!a.empty()) { num_gradients = boost::lexical_cast(a); MITK_INFO << "Found " << num_gradients << " gradients"; break; } continue; } // get gradient vector values if (num_gradients>0) { std::vector grad_values_line; boost::split(grad_values_line, line, boost::is_any_of(" ")); for (auto a : grad_values_line) if (!a.empty()) { grad_values.push_back(boost::lexical_cast(a)); ++g_count; if (g_count%3==0) --num_gradients; } } // get b-values if (num_b>0) { std::vector b_values_line; boost::split(b_values_line, line, boost::is_any_of(" ")); for (auto a : b_values_line) if (!a.empty()) { b_values.push_back(boost::lexical_cast(a)); if (b_values.back()>BValue) BValue = b_values.back(); num_b--; } } } newfile.close(); GradientDirectionContainerType::Pointer temp = GradientDirectionContainerType::New(); if (!b_values.empty() && grad_values.size()==b_values.size()*3) { // MITK_INFO << "Switching gradient vector x and y (bruker hack!!!)"; for(unsigned int i=0; i0) { double factor = b_val/BValue; if(vec.magnitude() > 0) { vec.normalize(); vec[0] = sqrt(factor)*vec[0]; vec[1] = sqrt(factor)*vec[1]; vec[2] = sqrt(factor)*vec[2]; } } temp->InsertElement(i,vec); } } else { mitkThrow() << "No valid gradient information found."; } DiffusionVectors = temp; } outputForCache = mitk::GrabItkImageMemory( itkVectorImage); // create BValueMap mitk::BValueMapProperty::BValueMap BValueMap = mitk::BValueMapProperty::CreateBValueMap(DiffusionVectors,BValue); mitk::DiffusionPropertyHelper::SetOriginalGradientContainer(outputForCache, DiffusionVectors); mitk::DiffusionPropertyHelper::SetMeasurementFrame(outputForCache, MeasurementFrame); mitk::DiffusionPropertyHelper::SetBValueMap(outputForCache, BValueMap); mitk::DiffusionPropertyHelper::SetReferenceBValue(outputForCache, BValue); mitk::DiffusionPropertyHelper::SetApplyMatrixToGradients(outputForCache, us::any_cast(this->GetOptions()["Apply image rotation to gradients"])); mitk::DiffusionPropertyHelper::InitializeImage(outputForCache); // Since we have already read the tree, we can store it in a cache variable // so that it can be assigned to the DataObject in GenerateData(); m_OutputCache = outputForCache; m_CacheTime.Modified(); } catch(std::exception& e) { MITK_INFO << "Std::Exception while reading file!!"; MITK_INFO << e.what(); throw itk::ImageFileReaderException(__FILE__, __LINE__, e.what()); } catch(...) { MITK_INFO << "Exception while reading file!!"; throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, an error occurred while reading the requested file!"); } } } } //namespace MITK #endif diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryView.cpp index ff92686..0726d1f 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryView.cpp @@ -1,598 +1,577 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center. 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 #include #include "QmitkTractometryView.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const std::string QmitkTractometryView::VIEW_ID = "org.mitk.views.tractometry"; using namespace mitk; QmitkTractometryView::QmitkTractometryView() : QmitkAbstractView() , m_Controls( nullptr ) , m_Visible(false) { } // Destructor QmitkTractometryView::~QmitkTractometryView() { } void QmitkTractometryView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkTractometryViewControls; m_Controls->setupUi( parent ); connect( m_Controls->m_MethodBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()) ); connect( m_Controls->m_StartButton, SIGNAL(clicked()), this, SLOT(StartTractometry()) ); mitk::TNodePredicateDataType::Pointer imageP = mitk::TNodePredicateDataType::New(); mitk::NodePredicateDimension::Pointer dimP = mitk::NodePredicateDimension::New(3); m_Controls->m_ImageBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_ImageBox->SetPredicate(mitk::NodePredicateAnd::New(imageP, dimP)); - m_Controls->m_ChartWidget->SetTheme(GetColorTheme()); m_Controls->m_ChartWidget->SetXAxisLabel("Tract position"); m_Controls->m_ChartWidget->SetYAxisLabel("Image Value"); - } -} - -::QmitkChartWidget::ColorTheme QmitkTractometryView::GetColorTheme() -{ - berry::IPreferencesService* prefService = berry::WorkbenchPlugin::GetDefault()->GetPreferencesService(); - berry::IPreferences::Pointer m_StylePref = prefService->GetSystemPreferences()->Node(berry::QtPreferences::QT_STYLES_NODE); - - QString styleName = m_StylePref->Get(berry::QtPreferences::QT_STYLE_NAME, ""); - - if (styleName == ":/org.blueberry.ui.qt/darkstyle.qss") - { - return QmitkChartWidget::ColorTheme::darkstyle; - } - else - { - return QmitkChartWidget::ColorTheme::lightstyle; + m_Controls->m_ChartWidget->SetTheme(QmitkChartWidget::ColorTheme::darkstyle); } } void QmitkTractometryView::SetFocus() { } void QmitkTractometryView::UpdateGui() { berry::IWorkbenchPart::Pointer nullPart; OnSelectionChanged(nullPart, QList(m_CurrentSelection)); } bool QmitkTractometryView::Flip(vtkSmartPointer< vtkPolyData > polydata1, int i, vtkSmartPointer< vtkPolyData > ref_poly) { double d_direct = 0; double d_flipped = 0; vtkCell* cell1 = polydata1->GetCell(0); if (ref_poly!=nullptr) cell1 = ref_poly->GetCell(0); auto numPoints1 = cell1->GetNumberOfPoints(); vtkPoints* points1 = cell1->GetPoints(); std::vector> ref_points; for (int j=0; jGetPoint(j); itk::Point itk_p; itk_p[0] = p1[0]; itk_p[1] = p1[1]; itk_p[2] = p1[2]; ref_points.push_back(itk_p); } vtkCell* cell2 = polydata1->GetCell(i); vtkPoints* points2 = cell2->GetPoints(); for (int j=0; jGetPoint(j); d_direct = (p1[0]-p2[0])*(p1[0]-p2[0]) + (p1[1]-p2[1])*(p1[1]-p2[1]) + (p1[2]-p2[2])*(p1[2]-p2[2]); double* p3 = points2->GetPoint(numPoints1-j-1); d_flipped = (p1[0]-p3[0])*(p1[0]-p3[0]) + (p1[1]-p3[1])*(p1[1]-p3[1]) + (p1[2]-p3[2])*(p1[2]-p3[2]); } if (d_direct>d_flipped) return true; return false; } template void QmitkTractometryView::StaticResamplingTractometry(const mitk::PixelType, mitk::Image::Pointer image, mitk::DataNode::Pointer node, std::vector > &data, std::string& clipboard_string) { mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); unsigned int num_points = m_Controls->m_SamplingPointsBox->value(); mitk::ImagePixelReadAccessor readimage(image, image->GetVolumeData(0)); mitk::FiberBundle::Pointer working_fib = fib->GetDeepCopy(); working_fib->ResampleToNumPoints(num_points); vtkSmartPointer< vtkPolyData > polydata = working_fib->GetFiberPolyData(); double rgb[3] = {0,0,0}; mitk::LookupTable::Pointer lookupTable = mitk::LookupTable::New(); lookupTable->SetType(mitk::LookupTable::MULTILABEL); std::vector > all_values; std::vector< double > mean_values; for (unsigned int i=0; iGetNumFibers(); ++i) { vtkCell* cell = polydata->GetCell(i); auto numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); std::vector< double > fib_vals; bool flip = false; if (i>0) flip = Flip(polydata, i); else if (m_ReferencePolyData!=nullptr) flip = Flip(polydata, 0, m_ReferencePolyData); for (int j=0; jGetTableValue(j, rgb); double* p; if (flip) { auto p_idx = numPoints - j - 1; p = points->GetPoint(p_idx); working_fib->ColorSinglePoint(i, p_idx, rgb); } else { p = points->GetPoint(j); working_fib->ColorSinglePoint(i, j, rgb); } Point3D px; px[0] = p[0]; px[1] = p[1]; px[2] = p[2]; double pixelValue = static_cast(readimage.GetPixelByWorldCoordinates(px)); fib_vals.push_back(pixelValue); mean += pixelValue; if (pixelValuemax) max = pixelValue; mean_values.at(j) += pixelValue; } all_values.push_back(fib_vals); } if (m_ReferencePolyData==nullptr) m_ReferencePolyData = polydata; std::vector< double > std_values1; std::vector< double > std_values2; for (unsigned int i=0; iGetNumFibers(); double stdev = 0; for (unsigned int j=0; j(mean_values.at(i)); clipboard_string += " "; clipboard_string += boost::lexical_cast(stdev); clipboard_string += "\n"; } clipboard_string += "\n"; data.push_back(mean_values); data.push_back(std_values1); data.push_back(std_values2); MITK_INFO << "Min: " << min; MITK_INFO << "Max: " << max; MITK_INFO << "Mean: " << mean/working_fib->GetNumberOfPoints(); if (m_Controls->m_ShowBinned->isChecked()) { mitk::DataNode::Pointer new_node = mitk::DataNode::New(); auto children = GetDataStorage()->GetDerivations(node); for (unsigned int i=0; isize(); ++i) { if (children->at(i)->GetName() == "binned_static") { new_node = children->at(i); new_node->SetData(working_fib); new_node->SetVisibility(true); node->SetVisibility(false); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return; } } new_node->SetData(working_fib); new_node->SetName("binned_static"); new_node->SetVisibility(true); node->SetVisibility(false); GetDataStorage()->Add(new_node, node); } } template void QmitkTractometryView::NearestCentroidPointTractometry(const mitk::PixelType, mitk::Image::Pointer image, mitk::DataNode::Pointer node, std::vector< std::vector< double > >& data, std::string& clipboard_string) { mitk::FiberBundle::Pointer fib = dynamic_cast(node->GetData()); unsigned int num_points = m_Controls->m_SamplingPointsBox->value(); mitk::ImagePixelReadAccessor readimage(image, image->GetVolumeData(0)); mitk::FiberBundle::Pointer working_fib = fib->GetDeepCopy(); working_fib->ResampleSpline(1.0); vtkSmartPointer< vtkPolyData > working_polydata = working_fib->GetFiberPolyData(); // clustering std::vector< mitk::ClusteringMetric* > metrics; metrics.push_back({new mitk::ClusteringMetricEuclideanStd()}); mitk::FiberBundle::Pointer fib_static_resampled = fib->GetDeepCopy(); fib_static_resampled->ResampleToNumPoints(num_points); vtkSmartPointer< vtkPolyData > polydata_static_resampled = fib_static_resampled->GetFiberPolyData(); std::vector centroids; std::shared_ptr< mitk::TractClusteringFilter > clusterer = std::make_shared(); int c=0; while (c<30 && (centroids.empty() || centroids.size()>static_cast(m_Controls->m_MaxCentroids->value()))) { float cluster_size = m_Controls->m_ClusterSize->value() + m_Controls->m_ClusterSize->value()*c*0.2; float max_d = 0; int i=1; std::vector< float > distances; while (max_d < working_fib->GetGeometry()->GetDiagonalLength()/2) { distances.push_back(cluster_size*i); max_d = cluster_size*i; ++i; } clusterer->SetDistances(distances); clusterer->SetTractogram(fib_static_resampled); clusterer->SetMetrics(metrics); clusterer->SetMergeDuplicateThreshold(cluster_size); clusterer->SetDoResampling(false); clusterer->SetNumPoints(num_points); // clusterer->SetMaxClusters(m_Controls->m_MaxCentroids->value()); clusterer->SetMinClusterSize(1); clusterer->Update(); centroids = clusterer->GetOutCentroids(); ++c; } double rgb[3] = {0,0,0}; mitk::LookupTable::Pointer lookupTable = mitk::LookupTable::New(); lookupTable->SetType(mitk::LookupTable::MULTILABEL); std::vector > all_values; std::vector< double > mean_values; std::vector< unsigned int > value_count; for (unsigned int i=0; iGetNumFibers(); ++i) { vtkCell* cell = working_polydata->GetCell(i); auto numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); std::vector< double > fib_vals; for (int j=0; jGetPoint(j); int min_bin = 0; float d=999999; for (auto centroid : centroids) { auto centroid_polydata = centroid->GetFiberPolyData(); vtkCell* centroid_cell = centroid_polydata->GetCell(0); auto centroid_numPoints = centroid_cell->GetNumberOfPoints(); vtkPoints* centroid_points = centroid_cell->GetPoints(); bool centroid_flip = Flip(centroid_polydata, 0, centroids.at(0)->GetFiberPolyData()); for (int bin=0; binGetPoint(bin); float temp_d = std::sqrt((p[0]-centroid_p[0])*(p[0]-centroid_p[0]) + (p[1]-centroid_p[1])*(p[1]-centroid_p[1]) + (p[2]-centroid_p[2])*(p[2]-centroid_p[2])); if (temp_dGetTableValue(min_bin, rgb); working_fib->ColorSinglePoint(i, j, rgb); Point3D px; px[0] = p[0]; px[1] = p[1]; px[2] = p[2]; double pixelValue = static_cast(readimage.GetPixelByWorldCoordinates(px)); fib_vals.push_back(pixelValue); mean += pixelValue; if (pixelValuemax) max = pixelValue; mean_values.at(min_bin) += pixelValue; value_count.at(min_bin) += 1; } all_values.push_back(fib_vals); } if (m_ReferencePolyData==nullptr) m_ReferencePolyData = working_polydata; std::vector< double > std_values1; std::vector< double > std_values2; for (unsigned int i=0; i(mean_values.at(i)); clipboard_string += " "; clipboard_string += boost::lexical_cast(stdev); clipboard_string += "\n"; } clipboard_string += "\n"; data.push_back(mean_values); data.push_back(std_values1); data.push_back(std_values2); MITK_INFO << "Min: " << min; MITK_INFO << "Max: " << max; MITK_INFO << "Mean: " << mean/working_fib->GetNumberOfPoints(); if (m_Controls->m_ShowBinned->isChecked()) { mitk::DataNode::Pointer new_node = mitk::DataNode::New(); // mitk::DataNode::Pointer new_node2; auto children = GetDataStorage()->GetDerivations(node); for (unsigned int i=0; isize(); ++i) { if (children->at(i)->GetName() == "binned_centroid") { new_node = children->at(i); new_node->SetData(working_fib); new_node->SetVisibility(true); node->SetVisibility(false); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return; } } new_node->SetData(working_fib); new_node->SetName("binned_centroid"); new_node->SetVisibility(true); node->SetVisibility(false); GetDataStorage()->Add(new_node, node); } } void QmitkTractometryView::Activated() { } void QmitkTractometryView::Deactivated() { } void QmitkTractometryView::Visible() { m_Visible = true; QList selection = GetDataManagerSelection(); berry::IWorkbenchPart::Pointer nullPart; OnSelectionChanged(nullPart, selection); } void QmitkTractometryView::Hidden() { m_Visible = false; } std::string QmitkTractometryView::RGBToHexString(double *rgb) { std::ostringstream os; for (int i = 0; i < 3; ++i) { os << std::setw(2) << std::setfill('0') << std::hex << static_cast(rgb[i] * 255); } return os.str(); } void QmitkTractometryView::StartTractometry() { m_ReferencePolyData = nullptr; - vtkSmartPointer lookupTable = vtkSmartPointer::New(); - lookupTable->SetTableRange(0.0, 1.0); - lookupTable->Build(); + double color[3] = {0,0,0}; + mitk::LookupTable::Pointer lookupTable = mitk::LookupTable::New(); + lookupTable->SetType(mitk::LookupTable::MULTILABEL); mitk::Image::Pointer image = dynamic_cast(m_Controls->m_ImageBox->GetSelectedNode()->GetData()); this->m_Controls->m_ChartWidget->Clear(); std::string clipboardString = ""; int c = 1; for (auto node : m_CurrentSelection) { clipboardString += node->GetName() + "\n"; clipboardString += "mean stdev\n"; std::vector< std::vector< double > > data; if (m_Controls->m_MethodBox->currentIndex()==0) { mitkPixelTypeMultiplex4( StaticResamplingTractometry, image->GetPixelType(), image, node, data, clipboardString ); } else { mitkPixelTypeMultiplex4( NearestCentroidPointTractometry, image->GetPixelType(), image, node, data, clipboardString ); } + m_Controls->m_ChartWidget->AddData1D(data.at(0), node->GetName() + " Mean", QmitkChartWidget::ChartType::line); + m_Controls->m_ChartWidget->SetLineStyle(node->GetName() + " Mean", QmitkChartWidget::LineStyle::solid); if (m_Controls->m_StDevBox->isChecked()) { - this->m_Controls->m_ChartWidget->AddData1D(data.at(1), node->GetName() + " +STDEV", QmitkChartWidget::ChartType::line); - this->m_Controls->m_ChartWidget->AddData1D(data.at(2), node->GetName() + " -STDEV", QmitkChartWidget::ChartType::line); + m_Controls->m_ChartWidget->AddData1D(data.at(1), node->GetName() + " +STDEV", QmitkChartWidget::ChartType::line); + m_Controls->m_ChartWidget->AddData1D(data.at(2), node->GetName() + " -STDEV", QmitkChartWidget::ChartType::line); + m_Controls->m_ChartWidget->SetLineStyle(node->GetName() + " +STDEV", QmitkChartWidget::LineStyle::dashed); + m_Controls->m_ChartWidget->SetLineStyle(node->GetName() + " -STDEV", QmitkChartWidget::LineStyle::dashed); } - double color[3]; - if (m_CurrentSelection.size()>1) - { - float scalar_color = ( (float)c/m_CurrentSelection.size() - 1.0/m_CurrentSelection.size() )/(1.0-1.0/m_CurrentSelection.size()); - lookupTable->GetColor(1.0 - scalar_color, color); - } - else - lookupTable->GetColor(0, color); - + lookupTable->GetTableValue(c, color); this->m_Controls->m_ChartWidget->SetColor(node->GetName() + " Mean", RGBToHexString(color)); if (m_Controls->m_StDevBox->isChecked()) { color[0] *= 0.5; color[1] *= 0.5; color[2] *= 0.5; this->m_Controls->m_ChartWidget->SetColor(node->GetName() + " +STDEV", RGBToHexString(color)); this->m_Controls->m_ChartWidget->SetColor(node->GetName() + " -STDEV", RGBToHexString(color)); } this->m_Controls->m_ChartWidget->Show(true); this->m_Controls->m_ChartWidget->SetShowDataPoints(false); ++c; } QApplication::clipboard()->setText(clipboardString.c_str(), QClipboard::Clipboard); } void QmitkTractometryView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList& nodes) { m_Controls->m_StartButton->setEnabled(false); if (!m_Visible) return; if (m_Controls->m_MethodBox->currentIndex()==0) m_Controls->m_ClusterFrame->setVisible(false); else m_Controls->m_ClusterFrame->setVisible(true); m_CurrentSelection.clear(); if(m_Controls->m_ImageBox->GetSelectedNode().IsNull()) return; for (auto node: nodes) if ( dynamic_cast(node->GetData()) ) m_CurrentSelection.push_back(node); if (!m_CurrentSelection.empty()) m_Controls->m_StartButton->setEnabled(true); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryView.h index d8939fb..e85a6ed 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkTractometryView.h @@ -1,85 +1,84 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center. 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. ===================================================================*/ #ifndef QmitkTractometryView_h #define QmitkTractometryView_h #include #include "ui_QmitkTractometryViewControls.h" #include #include #include #include #include #include /*! \brief Weight fibers by linearly fitting them to the image data. */ class QmitkTractometryView : public QmitkAbstractView, public mitk::ILifecycleAwarePart { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; QmitkTractometryView(); virtual ~QmitkTractometryView(); virtual void CreateQtPartControl(QWidget *parent) override; template void StaticResamplingTractometry(const mitk::PixelType, mitk::Image::Pointer image, mitk::DataNode::Pointer node, std::vector< std::vector< double > >& data, std::string& clipboard_string); template void NearestCentroidPointTractometry(const mitk::PixelType, mitk::Image::Pointer image, mitk::DataNode::Pointer node, std::vector< std::vector< double > >& data, std::string& clipboard_string); virtual void SetFocus() override; virtual void Activated() override; virtual void Deactivated() override; virtual void Visible() override; virtual void Hidden() override; protected slots: void UpdateGui(); void StartTractometry(); protected: /// \brief called by QmitkAbstractView when DataManager's selection has changed virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList& nodes) override; - QmitkChartWidget::ColorTheme GetColorTheme(); Ui::QmitkTractometryViewControls* m_Controls; bool Flip(vtkSmartPointer< vtkPolyData > polydata1, int i, vtkSmartPointer ref_poly=nullptr); std::string RGBToHexString(double *rgb); vtkSmartPointer< vtkPolyData > m_ReferencePolyData; QList m_CurrentSelection; bool m_Visible; }; #endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED