diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.python/resources/tractseg.py b/Plugins/org.mitk.gui.qt.diffusionimaging.python/resources/tractseg.py index c25cc15987..069fc81e4e 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.python/resources/tractseg.py +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.python/resources/tractseg.py @@ -1,54 +1,92 @@ error_string = None del error_string try: import SimpleITK as sitk import nibabel as nib import numpy as np from tractseg.TractSeg import run_tractseg data = sitk.GetArrayFromImage(in_image) data = np.nan_to_num(data) swapaxes = False if data.shape != (sx, sy, sz): + print("Swapping axes!") data = np.swapaxes(data, 0, 2) swapaxes = True - seg = run_tractseg(data=data, output_type=output_type, input_type="peaks", verbose=verbose, get_probs=get_probs) + print('output_type', output_type) + print('get_probs', get_probs) + print('dropout_sampling', dropout_sampling) + print('threshold', threshold) + seg = run_tractseg(data=data, output_type=output_type, input_type="peaks", verbose=verbose, get_probs=get_probs, dropout_sampling=dropout_sampling, threshold=threshold) if swapaxes: seg = np.swapaxes(seg, 0, 2) - if not output_type == "TOM": + if output_type == "tract_segmentation": - if not get_probs: + print("tract_segmentation", get_probs, dropout_sampling) + if not get_probs and not dropout_sampling: if collapse: temp = np.zeros((seg.shape[0], seg.shape[1], seg.shape[2])) for l in range(seg.shape[3]): - temp[np.where(seg[:, :, :, l]>0)] = l + 1 + temp[np.where(seg[:, :, :, l] > 0)] = l + 1 seg = temp segmentation = sitk.GetImageFromArray(seg.astype(np.uint8)) else: segmentation = sitk.GetImageFromArray(seg) segmentation.SetOrigin(in_image.GetOrigin()) segmentation.SetSpacing(in_image.GetSpacing()) segmentation.SetDirection(in_image.GetDirection()) - else: + + elif output_type == "endings_segmentation": + + print("endings_segmentation", get_probs, dropout_sampling) + if not get_probs and not dropout_sampling: + + # merge start and end into labelmap + temp = np.zeros((seg.shape[0], seg.shape[1], seg.shape[2], seg.shape[3] // 2)) + for l in range(temp.shape[3]): + temp[:, :, :, l][np.where(seg[:, :, :, l * 2] > 0)] = 1 + temp[:, :, :, l][np.where(seg[:, :, :, l * 2 + 1] > 0)] = 2 + seg = temp + + if collapse: + temp = np.zeros((seg.shape[0], seg.shape[1], seg.shape[2])) + for l in range(seg.shape[3]): + temp[np.where(seg[:, :, :, l] == 1)] = 2*l + 1 + temp[np.where(seg[:, :, :, l] == 2)] = 2*l + 2 + seg = temp + segmentation = sitk.GetImageFromArray(seg.astype(np.uint8)) + else: + + temp = np.zeros((seg.shape[0], seg.shape[1], seg.shape[2], seg.shape[3] // 2)) + for l in range(temp.shape[3]): + temp[:, :, :, l] += seg[:, :, :, l * 2] + temp[:, :, :, l] += seg[:, :, :, l * 2 + 1] + seg = temp + segmentation = sitk.GetImageFromArray(seg) + + segmentation.SetOrigin(in_image.GetOrigin()) + segmentation.SetSpacing(in_image.GetSpacing()) + segmentation.SetDirection(in_image.GetDirection()) + + elif output_type == "TOM": + if not collapse: for x in range(0, 20): tom = sitk.GetImageFromArray(seg[:, :, :, x * 3:x * 3 + 3]) tom.SetOrigin(in_image.GetOrigin()) tom.SetSpacing(in_image.GetSpacing()) tom.SetDirection(in_image.GetDirection()) globals()['tom%s' % x] = tom else: tom0 = sitk.GetImageFromArray(seg) tom0.SetOrigin(in_image.GetOrigin()) tom0.SetSpacing(in_image.GetSpacing()) tom0.SetDirection(in_image.GetDirection()) - - except Exception as e: error_string = str(e) print(error_string) diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkTractSegView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkTractSegView.cpp index c2839bbf80..7944ec2eb5 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkTractSegView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkTractSegView.cpp @@ -1,278 +1,353 @@ /*=================================================================== 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. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkTractSegView.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include +#include +#include +#include const std::string QmitkTractSegView::VIEW_ID = "org.mitk.views.tractseg"; QmitkTractSegView::QmitkTractSegView() : QmitkAbstractView() , m_Controls( 0 ) { } // Destructor QmitkTractSegView::~QmitkTractSegView() { } void QmitkTractSegView::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::QmitkTractSegViewControls; m_Controls->setupUi( parent ); connect( m_Controls->m_ImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGUI()) ); connect( m_Controls->m_StartButton, SIGNAL(clicked()), this, SLOT(Start()) ); - connect( m_Controls->m_OutputTypeBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGUI()) ); + connect( m_Controls->m_OutputBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGUI()) ); + connect( m_Controls->m_ModeBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGUI()) ); this->m_Parent = parent; m_Controls->m_ImageBox->SetDataStorage(this->GetDataStorage()); mitk::NodePredicateDataType::Pointer isDwi = mitk::NodePredicateDataType::New("PeakImage"); m_Controls->m_ImageBox->SetPredicate( isDwi ); UpdateGUI(); } } void QmitkTractSegView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList& ) { } void QmitkTractSegView::UpdateGUI() { if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull()) m_Controls->m_StartButton->setEnabled(true); else m_Controls->m_StartButton->setEnabled(false); + + m_Controls->m_CollapseBox->setVisible(true); + m_Controls->m_thresholdFrame->setVisible(true); + + if (m_Controls->m_OutputBox->currentIndex()==3 || m_Controls->m_OutputBox->currentIndex()==1) + m_Controls->m_thresholdFrame->setVisible(false); + + if (m_Controls->m_OutputBox->currentIndex()>0) + m_Controls->m_CollapseBox->setVisible(false); } void QmitkTractSegView::SetFocus() { UpdateGUI(); m_Controls->m_StartButton->setFocus(); } void QmitkTractSegView::Start() { + std::locale::global(std::locale::classic()); mitk::DataNode::Pointer node = m_Controls->m_ImageBox->GetSelectedNode(); mitk::Image::Pointer input_image = dynamic_cast(node->GetData()); // get python script as string QString data; QString fileName(":/QmitkDiffusionImaging/tractseg.py"); QFile file(fileName); if(!file.open(QIODevice::ReadOnly)) { qDebug()<<"filenot opened"< m_PythonServiceRef = context->GetServiceReference(); mitk::IPythonService* m_PythonService = dynamic_cast ( context->GetService(m_PythonServiceRef) ); mitk::IPythonService::ForceLoadModule(); typedef mitk::ImageToItk< mitk::PeakImage::ItkPeakImageType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(input_image); caster->Update(); mitk::PeakImage::ItkPeakImageType::Pointer itk_peaks = caster->GetOutput(); if (itk_peaks->GetLargestPossibleRegion().GetSize()[3]!=9) { QMessageBox::warning(nullptr, "Error", "TractSeg only works with 3-peak images!", QMessageBox::Ok); return; } itk::FlipPeaksFilter< float >::Pointer flipper = itk::FlipPeaksFilter< float >::New(); flipper->SetInput(itk_peaks); flipper->SetFlipX(false); flipper->SetFlipY(true); flipper->SetFlipZ(false); flipper->Update(); itk::FourDToVectorImageFilter< float >::Pointer converter = itk::FourDToVectorImageFilter< float >::New(); converter->SetInputImage(flipper->GetOutput()); converter->GenerateData(); mitk::Image::Pointer mitk_vec_img = mitk::GrabItkImageMemory( converter->GetOutputImage().GetPointer() ); m_PythonService->Execute("import SimpleITK as sitk"); m_PythonService->Execute("import SimpleITK._SimpleITK as _SimpleITK"); m_PythonService->Execute("import numpy"); m_PythonService->CopyToPythonAsSimpleItkImage( mitk_vec_img, "in_image"); m_PythonService->Execute("sx=" + boost::lexical_cast(itk_peaks->GetLargestPossibleRegion().GetSize()[0])); m_PythonService->Execute("sy=" + boost::lexical_cast(itk_peaks->GetLargestPossibleRegion().GetSize()[1])); m_PythonService->Execute("sz=" + boost::lexical_cast(itk_peaks->GetLargestPossibleRegion().GetSize()[2])); if (m_PythonService->DoesVariableExist("segmentation")) m_PythonService->Execute("del segmentation"); - switch(m_Controls->m_OutputTypeBox->currentIndex()) - { - case 0: - { + if(m_Controls->m_ModeBox->currentIndex()==0) m_PythonService->Execute("output_type=\"tract_segmentation\""); - break; - } - case 1: - { + else if(m_Controls->m_ModeBox->currentIndex()==1) m_PythonService->Execute("output_type=\"endings_segmentation\""); - break; - } - case 2: - { + + if(m_Controls->m_OutputBox->currentIndex()==3) m_PythonService->Execute("output_type=\"TOM\""); - break; - } - } - if (m_Controls->m_CollapseBox->isChecked()) + + if (m_Controls->m_CollapseBox->isChecked() && m_Controls->m_OutputBox->currentIndex()==0) m_PythonService->Execute("collapse=True"); else m_PythonService->Execute("collapse=False"); + m_PythonService->Execute("get_probs=False"); + m_PythonService->Execute("dropout_sampling=False"); + + if (m_Controls->m_OutputBox->currentIndex()==1) + m_PythonService->Execute("get_probs=True"); + else if (m_Controls->m_OutputBox->currentIndex()==2) + m_PythonService->Execute("dropout_sampling=True"); + + m_PythonService->Execute("threshold=" + boost::lexical_cast(m_Controls->m_SegThresholdBox->value())); + m_PythonService->Execute("verbose=False"); m_PythonService->Execute(data.toStdString(), mitk::IPythonService::MULTI_LINE_COMMAND); // clean up after running script (better way than deleting individual variables?) if(m_PythonService->DoesVariableExist("in_image")) m_PythonService->Execute("del in_image"); if(m_PythonService->DoesVariableExist("collapse")) m_PythonService->Execute("del collapse"); // check for errors if(!m_PythonService->GetVariable("error_string").empty()) { QMessageBox::warning(nullptr, "Error", QString(m_PythonService->GetVariable("error_string").c_str()), QMessageBox::Ok); return; } std::vector small_name_list = {"AF_left", "AF_right", "CA", "CST_left", "CST_right", "CG_left", "CG_right", "ICP_left", "ICP_right", "MCP", "SCP_left", "SCP_right", "ILF_left", "ILF_right", "IFO_left", "IFO_right", "OR_left", "OR_right", "UF_left", "UF_right"}; std::vector large_name_list = {"AF_left", "AF_right", "ATR_left", "ATR_right", "CA", "CC_1", "CC_2", "CC_3", "CC_4", "CC_5", "CC_6", "CC_7","CG_left","CG_right","CST_left","CST_right" ,"MLF_left","MLF_right","FPT_left" ,"FPT_right","FX_left","FX_right","ICP_left","ICP_right","IFO_left","IFO_right" ,"ILF_left" ,"ILF_right","MCP","OR_left","OR_right","POPT_left","POPT_right" ,"SCP_left","SCP_right","SLF_I_left","SLF_I_right","SLF_II_left","SLF_II_right" ,"SLF_III_left","SLF_III_right","STR_left","STR_right","UF_left","UF_right" ,"CC","T_PREF_left","T_PREF_right","T_PREM_left","T_PREM_right","T_PREC_left" ,"T_PREC_right","T_POSTC_left","T_POSTC_right","T_PAR_left","T_PAR_right","T_OCC_left" ,"T_OCC_right","ST_FO_left","ST_FO_right","ST_PREF_left","ST_PREF_right","ST_PREM_left" ,"ST_PREM_right","ST_PREC_left","ST_PREC_right","ST_POSTC_left","ST_POSTC_right" ,"ST_PAR_left","ST_PAR_right","ST_OCC_left","ST_OCC_right"}; if (m_PythonService->DoesVariableExist("segmentation")) { mitk::Image::Pointer out_image = m_PythonService->CopySimpleItkImageFromPython("segmentation"); - if (!m_Controls->m_CollapseBox->isChecked()) + if (!m_Controls->m_CollapseBox->isChecked() || m_Controls->m_OutputBox->currentIndex()>0) { - itk::VectorImage::Pointer vectorImage = itk::VectorImage::New(); - mitk::CastToItkImage(out_image, vectorImage); - itk::SplitVectorImageFilter::Pointer splitter = itk::SplitVectorImageFilter::New(); - splitter->SetInputImage(vectorImage); - splitter->GenerateData(); - int c = 0; - for (auto itk_seg : splitter->GetOutputImages()) + if (m_Controls->m_OutputBox->currentIndex()>0) { - mitk::DataNode::Pointer seg = mitk::DataNode::New(); - seg->SetData( mitk::GrabItkImageMemory(itk_seg) ); - seg->SetBoolProperty("binary", true); - if (m_Controls->m_OutputTypeBox->currentIndex()==0) - seg->SetName(large_name_list.at(c)); - else if (c%2==0) - seg->SetName(small_name_list.at(c/2) + "_Start"); - else if (c%2==1) - seg->SetName(small_name_list.at((c-1)/2) + "_End"); - GetDataStorage()->Add(seg, node); - ++c; + itk::VectorImage::Pointer vectorImage = itk::VectorImage::New(); + mitk::CastToItkImage(out_image, vectorImage); + itk::SplitVectorImageFilter::Pointer splitter = itk::SplitVectorImageFilter::New(); + splitter->SetInputImage(vectorImage); + splitter->GenerateData(); + int c = 0; + for (auto itk_seg : splitter->GetOutputImages()) + { + mitk::DataNode::Pointer seg = mitk::DataNode::New(); + seg->SetData( mitk::GrabItkImageMemory(itk_seg) ); + if (m_Controls->m_ModeBox->currentIndex()==0) + seg->SetName(large_name_list.at(c)); + else + seg->SetName(small_name_list.at(c)); + + mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); + lut->SetType( mitk::LookupTable::JET_TRANSPARENT ); + mitk::LookupTableProperty::Pointer lut_prop = mitk::LookupTableProperty::New(); + lut_prop->SetLookupTable( lut ); + seg->SetProperty("LookupTable", lut_prop ); + mitk::LevelWindow lw; lw.SetRangeMinMax(0.0,1.0); + seg->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( lw ) ); + + GetDataStorage()->Add(seg, node); + ++c; + } + } + else + { + itk::VectorImage::Pointer vectorImage = itk::VectorImage::New(); + mitk::CastToItkImage(out_image, vectorImage); + itk::SplitVectorImageFilter::Pointer splitter = itk::SplitVectorImageFilter::New(); + splitter->SetInputImage(vectorImage); + splitter->GenerateData(); + int c = 0; + for (auto itk_seg : splitter->GetOutputImages()) + { + mitk::DataNode::Pointer seg = mitk::DataNode::New(); + seg->SetData( mitk::GrabItkImageMemory(itk_seg) ); + if (m_Controls->m_ModeBox->currentIndex()==0) + { + seg->SetName(large_name_list.at(c)); + seg->SetBoolProperty("binary", true); + } + else + { + mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); + lut->SetType( mitk::LookupTable::MULTILABEL ); + mitk::LookupTableProperty::Pointer lut_prop = mitk::LookupTableProperty::New(); + lut_prop->SetLookupTable( lut ); + seg->SetProperty("LookupTable", lut_prop ); + mitk::LevelWindow lw; lw.SetRangeMinMax(0,2); + seg->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( lw ) ); + + seg->SetName(small_name_list.at(c)); + } + GetDataStorage()->Add(seg, node); + ++c; + } } } else { mitk::DataNode::Pointer seg = mitk::DataNode::New(); seg->SetData(out_image); - if (m_Controls->m_OutputTypeBox->currentIndex()==0) + mitk::LevelWindow lw; + if (m_Controls->m_ModeBox->currentIndex()==0) + { seg->SetName("TractLabels"); - else if (m_Controls->m_OutputTypeBox->currentIndex()==1) + lw.SetRangeMinMax(0, 72); + } + else + { seg->SetName("TractEndpointRegionLabels"); + lw.SetRangeMinMax(0, 40); + } + + if (m_Controls->m_OutputBox->currentIndex()==0) + { + mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); + lut->SetType( mitk::LookupTable::MULTILABEL ); + mitk::LookupTableProperty::Pointer lut_prop = mitk::LookupTableProperty::New(); + lut_prop->SetLookupTable( lut ); + seg->SetProperty("LookupTable", lut_prop ); + seg->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( lw ) ); + } + GetDataStorage()->Add(seg, node); } m_PythonService->Execute("del segmentation"); } else { for (int i=0; i<20; ++i) if (m_PythonService->DoesVariableExist("tom" + boost::lexical_cast(i))) { mitk::Image::Pointer out_image = m_PythonService->CopySimpleItkImageFromPython("tom" + boost::lexical_cast(i)); itk::VectorImage::Pointer vectorImage = itk::VectorImage::New(); mitk::CastToItkImage(out_image, vectorImage); itk::VectorImageToFourDImageFilter< float >::Pointer converter = itk::VectorImageToFourDImageFilter< float >::New(); converter->SetInputImage(vectorImage); converter->GenerateData(); mitk::PeakImage::ItkPeakImageType::Pointer itk_peaks = converter->GetOutputImage(); mitk::Image::Pointer mitk_peaks = dynamic_cast(mitk::PeakImage::New().GetPointer()); mitk::CastToMitkImage(itk_peaks, mitk_peaks); mitk_peaks->SetVolume(itk_peaks->GetBufferPointer()); mitk::DataNode::Pointer seg = mitk::DataNode::New(); seg->SetData( mitk_peaks ); if (!m_Controls->m_CollapseBox->isChecked()) seg->SetName(small_name_list.at(i) + "_TOM"); else seg->SetName("Collapsed_TOM"); GetDataStorage()->Add(seg, node); m_PythonService->Execute("del tom" + boost::lexical_cast(i)); } } } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkTractSegViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkTractSegViewControls.ui index c20a546ac3..1d701069b0 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkTractSegViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkTractSegViewControls.ui @@ -1,136 +1,233 @@ QmitkTractSegViewControls 0 0 435 803 Form QCommandLinkButton:disabled { border: none; } QGroupBox { background-color: transparent; } 25 - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - false - - - - - - Start TractSeg - - - - + QFrame::NoFrame QFrame::Raised - + 0 0 0 0 - - - - - + + + + + - Input Peaks: + Collapse tracts into single 3D volume - - - - Output: + + + + QFrame::NoFrame + + + QFrame::Raised + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Mode: + + + + + + + + + + Input Peaks: + + + + + + + + Tracts + + + + + Tract Endpoint Regions + + + + + + + + Output: + + + + + + + + Segmentations + + + + + Probability Maps + + + + + Uncertainty Maps + + + + + Tract Orientation Maps + + + + + - - - - - Tract Segmentations + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 - - - - Tract Endpoint Regions + + 0 - - - - Tract Orientation Maps + + 0 - + + 0 + + + + + Segmentation Threshold: + + + + + + + 1.000000000000000 + + + 0.100000000000000 + + + 0.500000000000000 + + + + - - + + + + false + - Collapse tracts into single 3D volume + Start TractSeg + + + + Qt::Vertical + + + + 20 + 40 + + + + QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h