diff --git a/Modules/Python/autoload/PythonService/mitkPythonService.cpp b/Modules/Python/autoload/PythonService/mitkPythonService.cpp index 5ae320d5e1..936fd23382 100644 --- a/Modules/Python/autoload/PythonService/mitkPythonService.cpp +++ b/Modules/Python/autoload/PythonService/mitkPythonService.cpp @@ -1,966 +1,966 @@ /*=================================================================== 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 "mitkPythonService.h" #include #include #include #include #include #include "PythonPath.h" #include #include #include #include #include #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION #include #include #ifndef WIN32 #include #endif const QString mitk::PythonService::m_TmpDataFileName("temp_mitk_data_file"); #ifdef USE_MITK_BUILTIN_PYTHON static char* pHome = nullptr; #endif mitk::PythonService::PythonService() : m_ItkWrappingAvailable( true ), m_OpenCVWrappingAvailable( true ), m_VtkWrappingAvailable( true ), m_ErrorOccured( false ) { { MITK_DEBUG << "will init python if necessary"; } bool pythonInitialized = static_cast( Py_IsInitialized() ); //m_PythonManager.isPythonInitialized() ); { MITK_DEBUG << "pythonInitialized " << pythonInitialized; MITK_DEBUG << "m_PythonManager.isPythonInitialized() " << m_PythonManager.isPythonInitialized(); } // due to strange static var behaviour on windows Py_IsInitialized() returns correct value while // m_PythonManager.isPythonInitialized() does not because it has been constructed and destructed again if( !m_PythonManager.isPythonInitialized() ) { try { //TODO a better way to do this #ifndef WIN32 dlerror(); if(dlopen(PYTHON_LIBRARY, RTLD_NOW | RTLD_GLOBAL) == 0 ) { mitkThrow() << "Python runtime could not be loaded: " << dlerror(); } #endif std::string programPath = mitk::IOUtil::GetProgramPath(); QDir programmDir( QString( programPath.c_str() ).append("/Python") ); QString pythonCommand; // TODO: Check this in the modernization branch with an installer // Set the pythonpath variable depending if // we have an installer or development environment if ( programmDir.exists() ) { // runtime directory used in installers pythonCommand.append( QString("import site, sys\n") ); pythonCommand.append( QString("sys.path.append('')\n") ); pythonCommand.append( QString("sys.path.append('%1')\n").arg(programPath.c_str()) ); pythonCommand.append( QString("sys.path.append('%1/Python')").arg(programPath.c_str()) ); // development } else { pythonCommand.append( QString("import site, sys\n") ); pythonCommand.append( QString("sys.path.append('')\n") ); pythonCommand.append( QString("sys.path.append('%1')\n").arg(EXTERNAL_DIST_PACKAGES) ); pythonCommand.append( QString("\nsite.addsitedir('%1')").arg(EXTERNAL_SITE_PACKAGES) ); } if( pythonInitialized ) m_PythonManager.setInitializationFlags(PythonQt::RedirectStdOut|PythonQt::PythonAlreadyInitialized); else m_PythonManager.setInitializationFlags(PythonQt::RedirectStdOut); // set python home if own runtime is used #ifdef USE_MITK_BUILTIN_PYTHON QString pythonHome; if ( programmDir.exists() ) pythonHome.append(QString("%1/Python").arg(programPath.c_str())); else pythonHome.append(PYTHONHOME); if(pHome) delete[] pHome; pHome = new char[pythonHome.toStdString().length() + 1]; strcpy(pHome,pythonHome.toStdString().c_str()); Py_SetPythonHome(pHome); MITK_DEBUG("PythonService") << "PythonHome: " << pHome; #endif MITK_DEBUG("PythonService") << "initalizing python"; m_PythonManager.initialize(); #ifdef USE_MITK_BUILTIN_PYTHON PyObject* dict = PyDict_New(); // Import builtin modules if (PyDict_GetItemString(dict, "__builtins__") == nullptr) { PyObject* builtinMod = PyImport_ImportModule("__builtin__"); if (builtinMod == nullptr || PyDict_SetItemString(dict, "__builtins__", builtinMod) != 0) { Py_DECREF(dict); Py_XDECREF(dict); return; } Py_DECREF(builtinMod); } #endif MITK_DEBUG("PythonService")<< "Python Search paths: " << Py_GetPath(); MITK_DEBUG("PythonService") << "python initalized"; //MITK_DEBUG("PythonService") << "registering python paths" << PYTHONPATH_COMMAND; m_PythonManager.executeString( pythonCommand, ctkAbstractPythonManager::FileInput ); } catch (...) { MITK_DEBUG("PythonService") << "exception initalizing python"; } } } mitk::PythonService::~PythonService() { MITK_DEBUG("mitk::PythonService") << "destructing PythonService"; #ifdef USE_MITK_BUILTIN_PYTHON if(pHome) delete[] pHome; #endif } std::string mitk::PythonService::Execute(const std::string &stdpythonCommand, int commandType) { QString pythonCommand = QString::fromStdString(stdpythonCommand); { MITK_DEBUG("mitk::PythonService") << "pythonCommand = " << pythonCommand.toStdString(); MITK_DEBUG("mitk::PythonService") << "commandType = " << commandType; } QVariant result; bool commandIssued = true; if(commandType == IPythonService::SINGLE_LINE_COMMAND ) result = m_PythonManager.executeString(pythonCommand, ctkAbstractPythonManager::SingleInput ); else if(commandType == IPythonService::MULTI_LINE_COMMAND ) result = m_PythonManager.executeString(pythonCommand, ctkAbstractPythonManager::FileInput ); else if(commandType == IPythonService::EVAL_COMMAND ) result = m_PythonManager.executeString(pythonCommand, ctkAbstractPythonManager::EvalInput ); else commandIssued = false; if(commandIssued) { this->NotifyObserver(pythonCommand.toStdString()); m_ErrorOccured = PythonQt::self()->hadError(); } return result.toString().toStdString(); } void mitk::PythonService::ExecuteScript( const std::string& pythonScript ) { std::ifstream t(pythonScript.c_str()); std::string str((std::istreambuf_iterator(t)), std::istreambuf_iterator()); t.close(); m_PythonManager.executeString(QString::fromStdString(str)); } std::vector mitk::PythonService::GetVariableStack() const { std::vector list; PyObject* dict = PyImport_GetModuleDict(); PyObject* object = PyDict_GetItemString(dict, "__main__"); PyObject* dirMain = PyObject_Dir(object); PyObject* tempObject = 0; //PyObject* strTempObject = 0; if(dirMain) { std::string name, attrValue, attrType; for(int i = 0; iob_type->tp_name; if(tempObject && ( PyUnicode_Check(tempObject) || PyString_Check(tempObject) ) ) attrValue = PyString_AsString(tempObject); else attrValue = ""; mitk::PythonVariable var; var.m_Name = name; var.m_Value = attrValue; var.m_Type = attrType; list.push_back(var); } } return list; } std::string mitk::PythonService::GetVariable(const std::string& name) const { std::vector allVars = this->GetVariableStack(); for(unsigned int i = 0; i< allVars.size(); i++) { if( allVars.at(i).m_Name == name ) return allVars.at(i).m_Value; } return ""; } bool mitk::PythonService::DoesVariableExist(const std::string& name) const { bool varExists = false; std::vector allVars = this->GetVariableStack(); for(unsigned int i = 0; i< allVars.size(); i++) { if( allVars.at(i).m_Name == name ) { varExists = true; break; } } return varExists; } void mitk::PythonService::AddPythonCommandObserver(mitk::PythonCommandObserver *observer) { if(!m_Observer.contains(observer)) m_Observer.append(observer); } void mitk::PythonService::RemovePythonCommandObserver(mitk::PythonCommandObserver *observer) { m_Observer.removeOne(observer); } void mitk::PythonService::NotifyObserver(const std::string &command) { MITK_DEBUG("mitk::PythonService") << "number of observer " << m_Observer.size(); for( int i=0; i< m_Observer.size(); ++i ) { m_Observer.at(i)->CommandExecuted(command); } } QString mitk::PythonService::GetTempDataFileName(const std::string& ext) const { QString tmpFolder = QDir::tempPath(); QString fileName = tmpFolder + QDir::separator() + m_TmpDataFileName + QString::fromStdString(ext); return fileName; } bool mitk::PythonService::CopyToPythonAsSimpleItkImage(mitk::Image *image, const std::string &stdvarName) { QString varName = QString::fromStdString( stdvarName ); QString command; unsigned int* imgDim = image->GetDimensions(); int npy_nd = 1; // access python module PyObject *pyMod = PyImport_AddModule((char*)"__main__"); // global dictionary PyObject *pyDict = PyModule_GetDict(pyMod); const mitk::Vector3D spacing = image->GetGeometry()->GetSpacing(); const mitk::Point3D origin = image->GetGeometry()->GetOrigin(); mitk::PixelType pixelType = image->GetPixelType(); itk::ImageIOBase::IOPixelType ioPixelType = image->GetPixelType().GetPixelType(); PyObject* npyArray = nullptr; mitk::ImageReadAccessor racc(image); void* array = (void*) racc.GetData(); mitk::Vector3D xDirection; mitk::Vector3D yDirection; mitk::Vector3D zDirection; const vnl_matrix_fixed &transform = image->GetGeometry()->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix(); mitk::Vector3D s = image->GetGeometry()->GetSpacing(); // ToDo: Check if this is a collumn or row vector from the matrix. // right now it works but not sure for rotated geometries mitk::FillVector3D(xDirection, transform[0][0]/s[0], transform[0][1]/s[1], transform[0][2]/s[2]); mitk::FillVector3D(yDirection, transform[1][0]/s[0], transform[1][1]/s[1], transform[1][2]/s[2]); mitk::FillVector3D(zDirection, transform[2][0]/s[0], transform[2][1]/s[1], transform[2][2]/s[2]); // save the total number of elements here (since the numpy array is one dimensional) npy_intp* npy_dims = new npy_intp[1]; npy_dims[0] = imgDim[0]; /** * Build a string in the format [1024,1028,1] * to describe the dimensionality. This is needed for simple itk * to know the dimensions of the image */ QString dimensionString; dimensionString.append(QString("[")); dimensionString.append(QString::number(imgDim[0])); for (unsigned i = 1; i < 3; ++i) // always three because otherwise the 3d-geometry gets destroyed // (relevant for backtransformation of simple itk image to mitk. { dimensionString.append(QString(",")); dimensionString.append(QString::number(imgDim[i])); npy_dims[0] *= imgDim[i]; } dimensionString.append("]"); // the next line is necessary for vectorimages npy_dims[0] *= pixelType.GetNumberOfComponents(); // default pixeltype: unsigned short NPY_TYPES npy_type = NPY_USHORT; std::string sitk_type = "sitkUInt8"; if( ioPixelType == itk::ImageIOBase::SCALAR ) { if( pixelType.GetComponentType() == itk::ImageIOBase::DOUBLE ) { npy_type = NPY_DOUBLE; sitk_type = "sitkFloat64"; } else if( pixelType.GetComponentType() == itk::ImageIOBase::FLOAT ) { npy_type = NPY_FLOAT; sitk_type = "sitkFloat32"; } else if( pixelType.GetComponentType() == itk::ImageIOBase::SHORT) { npy_type = NPY_SHORT; sitk_type = "sitkInt16"; } else if( pixelType.GetComponentType() == itk::ImageIOBase::CHAR ) { npy_type = NPY_BYTE; sitk_type = "sitkInt8"; } else if( pixelType.GetComponentType() == itk::ImageIOBase::INT ) { npy_type = NPY_INT; sitk_type = "sitkInt32"; } else if( pixelType.GetComponentType() == itk::ImageIOBase::LONG ) { npy_type = NPY_LONG; sitk_type = "sitkInt64"; } else if( pixelType.GetComponentType() == itk::ImageIOBase::UCHAR ) { npy_type = NPY_UBYTE; sitk_type = "sitkUInt8"; } else if( pixelType.GetComponentType() == itk::ImageIOBase::UINT ) { npy_type = NPY_UINT; sitk_type = "sitkUInt32"; } else if( pixelType.GetComponentType() == itk::ImageIOBase::ULONG ) { npy_type = NPY_LONG; sitk_type = "sitkUInt64"; } else if( pixelType.GetComponentType() == itk::ImageIOBase::USHORT ) { npy_type = NPY_USHORT; sitk_type = "sitkUInt16"; } } else if ( ioPixelType == itk::ImageIOBase::VECTOR || ioPixelType == itk::ImageIOBase::RGB || ioPixelType == itk::ImageIOBase::RGBA ) { if( pixelType.GetComponentType() == itk::ImageIOBase::DOUBLE ) { npy_type = NPY_DOUBLE; sitk_type = "sitkVectorFloat64"; } else if( pixelType.GetComponentType() == itk::ImageIOBase::FLOAT ) { npy_type = NPY_FLOAT; sitk_type = "sitkVectorFloat32"; } else if( pixelType.GetComponentType() == itk::ImageIOBase::SHORT) { npy_type = NPY_SHORT; sitk_type = "sitkVectorInt16"; } else if( pixelType.GetComponentType() == itk::ImageIOBase::CHAR ) { npy_type = NPY_BYTE; sitk_type = "sitkVectorInt8"; } else if( pixelType.GetComponentType() == itk::ImageIOBase::INT ) { npy_type = NPY_INT; sitk_type = "sitkVectorInt32"; } else if( pixelType.GetComponentType() == itk::ImageIOBase::LONG ) { npy_type = NPY_LONG; sitk_type = "sitkVectorInt64"; } else if( pixelType.GetComponentType() == itk::ImageIOBase::UCHAR ) { npy_type = NPY_UBYTE; sitk_type = "sitkVectorUInt8"; } else if( pixelType.GetComponentType() == itk::ImageIOBase::UINT ) { npy_type = NPY_UINT; sitk_type = "sitkVectorUInt32"; } else if( pixelType.GetComponentType() == itk::ImageIOBase::ULONG ) { npy_type = NPY_LONG; sitk_type = "sitkVectorUInt64"; } else if( pixelType.GetComponentType() == itk::ImageIOBase::USHORT ) { npy_type = NPY_USHORT; sitk_type = "sitkVectorUInt16"; } } else { MITK_WARN << "not a recognized pixeltype"; return false; } // creating numpy array import_array1 (true); npyArray = PyArray_SimpleNewFromData(npy_nd,npy_dims,npy_type,array); // add temp array it to the python dictionary to access it in python code const int status = PyDict_SetItemString( pyDict,QString("%1_numpy_array") .arg(varName).toStdString().c_str(), npyArray ); // sanity check if ( status != 0 ) return false; command.append( QString("%1 = sitk.Image(%2,sitk.%3,%4)\n").arg(varName) .arg(dimensionString) .arg(QString(sitk_type.c_str())).arg(QString::number(pixelType.GetNumberOfComponents())) ); command.append( QString("%1.SetSpacing([%2,%3,%4])\n").arg(varName) .arg(QString::number(spacing[0])) .arg(QString::number(spacing[1])) .arg(QString::number(spacing[2])) ); command.append( QString("%1.SetOrigin([%2,%3,%4])\n").arg(varName) .arg(QString::number(origin[0])) .arg(QString::number(origin[1])) .arg(QString::number(origin[2])) ); command.append( QString("%1.SetDirection([%2,%3,%4,%5,%6,%7,%8,%9,%10])\n").arg(varName) .arg(QString::number(xDirection[0])) .arg(QString::number(xDirection[1])) .arg(QString::number(xDirection[2])) .arg(QString::number(yDirection[0])) .arg(QString::number(yDirection[1])) .arg(QString::number(yDirection[2])) .arg(QString::number(zDirection[0])) .arg(QString::number(zDirection[1])) .arg(QString::number(zDirection[2])) ); // directly access the cpp api from the lib command.append( QString("_SimpleITK._SetImageFromArray(%1_numpy_array,%1)\n").arg(varName) ); command.append( QString("del %1_numpy_array").arg(varName) ); MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString(); this->Execute( command.toStdString(), IPythonService::MULTI_LINE_COMMAND ); return true; } mitk::PixelType DeterminePixelType(const std::string& pythonPixeltype, int nrComponents, int dimensions) { typedef itk::RGBPixel< unsigned char > UCRGBPixelType; typedef itk::RGBPixel< unsigned short > USRGBPixelType; typedef itk::RGBPixel< float > FloatRGBPixelType; typedef itk::RGBPixel< double > DoubleRGBPixelType; typedef itk::Image< UCRGBPixelType > UCRGBImageType; typedef itk::Image< USRGBPixelType > USRGBImageType; typedef itk::Image< FloatRGBPixelType > FloatRGBImageType; typedef itk::Image< DoubleRGBPixelType > DoubleRGBImageType; typedef itk::RGBAPixel< unsigned char > UCRGBAPixelType; typedef itk::RGBAPixel< unsigned short > USRGBAPixelType; typedef itk::RGBAPixel< float > FloatRGBAPixelType; typedef itk::RGBAPixel< double > DoubleRGBAPixelType; typedef itk::Image< UCRGBAPixelType > UCRGBAImageType; typedef itk::Image< USRGBAPixelType > USRGBAImageType; typedef itk::Image< FloatRGBAPixelType > FloatRGBAImageType; typedef itk::Image< DoubleRGBAPixelType > DoubleRGBAImageType; mitk::PixelType pixelType = mitk::MakePixelType(nrComponents); if (nrComponents == 1) { if( pythonPixeltype.compare("float64") == 0 ) { pixelType = mitk::MakePixelType(nrComponents); } else if( pythonPixeltype.compare("float32") == 0 ) { pixelType = mitk::MakePixelType(nrComponents); } else if( pythonPixeltype.compare("int16") == 0) { pixelType = mitk::MakePixelType(nrComponents); } else if( pythonPixeltype.compare("int8") == 0 ) { pixelType = mitk::MakePixelType(nrComponents); } else if( pythonPixeltype.compare("int32") == 0 ) { pixelType = mitk::MakePixelType(nrComponents); } else if( pythonPixeltype.compare("int64") == 0 ) { pixelType = mitk::MakePixelType(nrComponents); } else if( pythonPixeltype.compare("uint8") == 0 ) { pixelType = mitk::MakePixelType(nrComponents); } else if( pythonPixeltype.compare("uint32") == 0 ) { pixelType = mitk::MakePixelType(nrComponents); } else if( pythonPixeltype.compare("uint64") == 0 ) { pixelType = mitk::MakePixelType(nrComponents); } else if( pythonPixeltype.compare("uint16") == 0 ) { pixelType = mitk::MakePixelType(nrComponents); } else { mitkThrow()<< "unknown scalar PixelType"; } } else if(nrComponents == 3 && dimensions == 2) { if( pythonPixeltype.compare("float64") == 0 ) { pixelType = mitk::MakePixelType(); } else if( pythonPixeltype.compare("float32") == 0 ) { pixelType = mitk::MakePixelType(); } else if( pythonPixeltype.compare("uint8") == 0 ) { pixelType = mitk::MakePixelType(); } else if( pythonPixeltype.compare("uint16") == 0 ) { pixelType = mitk::MakePixelType(); } } else if( (nrComponents == 4) && dimensions == 2 ) { if( pythonPixeltype.compare("float64") == 0 ) { pixelType = mitk::MakePixelType(); } else if( pythonPixeltype.compare("float32") == 0 ) { pixelType = mitk::MakePixelType(); } else if( pythonPixeltype.compare("uint8") == 0 ) { pixelType = mitk::MakePixelType(); } else if( pythonPixeltype.compare("uint16") == 0 ) { pixelType = mitk::MakePixelType(); } } else { if( pythonPixeltype.compare("float64") == 0 ) { pixelType = mitk::MakePixelType >(nrComponents); } else if( pythonPixeltype.compare("float32") == 0 ) { pixelType = mitk::MakePixelType >(nrComponents); } else if( pythonPixeltype.compare("int16") == 0) { pixelType = mitk::MakePixelType >(nrComponents); } else if( pythonPixeltype.compare("int8") == 0 ) { pixelType = mitk::MakePixelType >(nrComponents); } else if( pythonPixeltype.compare("int32") == 0 ) { pixelType = mitk::MakePixelType >(nrComponents); } else if( pythonPixeltype.compare("int64") == 0 ) { pixelType = mitk::MakePixelType >(nrComponents); } else if( pythonPixeltype.compare("uint8") == 0 ) { pixelType = mitk::MakePixelType >(nrComponents); } else if( pythonPixeltype.compare("uint16") == 0 ) { pixelType = mitk::MakePixelType >(nrComponents); } else if( pythonPixeltype.compare("uint32") == 0 ) { pixelType = mitk::MakePixelType >(nrComponents); } else if( pythonPixeltype.compare("uint64") == 0 ) { pixelType = mitk::MakePixelType >(nrComponents); } else { mitkThrow()<< "unknown vectorial PixelType"; } } return pixelType; } mitk::Image::Pointer mitk::PythonService::CopySimpleItkImageFromPython(const std::string &stdvarName) { double*ds = nullptr; // access python module PyObject *pyMod = PyImport_AddModule((char*)"__main__"); // global dictionarry PyObject *pyDict = PyModule_GetDict(pyMod); mitk::Image::Pointer mitkImage = mitk::Image::New(); mitk::Vector3D spacing; mitk::Point3D origin; QString command; QString varName = QString::fromStdString( stdvarName ); command.append( QString("%1_numpy_array = sitk.GetArrayFromImage(%1)\n").arg(varName) ); command.append( QString("%1_spacing = numpy.asarray(%1.GetSpacing())\n").arg(varName) ); command.append( QString("%1_origin = numpy.asarray(%1.GetOrigin())\n").arg(varName) ); command.append( QString("%1_dtype = %1_numpy_array.dtype.name\n").arg(varName) ); command.append( QString("%1_direction = numpy.asarray(%1.GetDirection())\n").arg(varName) ); command.append( QString("%1_nrComponents = numpy.asarray(%1.GetNumberOfComponentsPerPixel())\n").arg(varName)); command.append( QString("%1_dtype = %1_numpy_array.dtype.name\n").arg(varName) ); MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString(); this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND ); PyObject* py_dtype = PyDict_GetItemString(pyDict,QString("%1_dtype").arg(varName).toStdString().c_str() ); std::string dtype = PyString_AsString(py_dtype); PyArrayObject* py_data = (PyArrayObject*) PyDict_GetItemString(pyDict,QString("%1_numpy_array").arg(varName).toStdString().c_str() ); PyArrayObject* py_spacing = (PyArrayObject*) PyDict_GetItemString(pyDict,QString("%1_spacing").arg(varName).toStdString().c_str() ); PyArrayObject* py_origin = (PyArrayObject*) PyDict_GetItemString(pyDict,QString("%1_origin").arg(varName).toStdString().c_str() ); PyArrayObject* py_direction = (PyArrayObject*) PyDict_GetItemString(pyDict,QString("%1_direction").arg(varName).toStdString().c_str() ); PyArrayObject* py_nrComponents = (PyArrayObject*) PyDict_GetItemString(pyDict,QString("%1_nrComponents").arg(varName).toStdString().c_str() ); unsigned int nr_Components = *(reinterpret_cast(PyArray_DATA(py_nrComponents))); unsigned int nr_dimensions = PyArray_NDIM(py_data); if (nr_Components > 1) // for VectorImages the last dimension in the numpy array are the vector components. { --nr_dimensions; } mitk::PixelType pixelType = DeterminePixelType(dtype, nr_Components, nr_dimensions); unsigned int* dimensions = new unsigned int[nr_dimensions]; // fill backwards , nd data saves dimensions in opposite direction for( unsigned i = 0; i < nr_dimensions; ++i ) { dimensions[i] = PyArray_DIMS(py_data)[nr_dimensions - 1 - i]; } mitkImage->Initialize(pixelType, nr_dimensions, dimensions); mitkImage->SetChannel(PyArray_DATA(py_data)); ds = reinterpret_cast(PyArray_DATA(py_spacing)); spacing[0] = ds[0]; spacing[1] = ds[1]; spacing[2] = ds[2]; mitkImage->GetGeometry()->SetSpacing(spacing); ds = reinterpret_cast(PyArray_DATA(py_origin)); origin[0] = ds[0]; origin[1] = ds[1]; origin[2] = ds[2]; mitkImage->GetGeometry()->SetOrigin(origin); itk::Matrix py_transform; ds = reinterpret_cast(PyArray_DATA(py_direction)); py_transform[0][0] = ds[0]; py_transform[0][1] = ds[1]; py_transform[0][2] = ds[2]; py_transform[1][0] = ds[3]; py_transform[1][1] = ds[4]; py_transform[1][2] = ds[5]; py_transform[2][0] = ds[6]; py_transform[2][1] = ds[7]; py_transform[2][2] = ds[8]; mitk::AffineTransform3D::Pointer affineTransform = mitkImage->GetGeometry()->GetIndexToWorldTransform(); itk::Matrix transform = py_transform * affineTransform->GetMatrix(); affineTransform->SetMatrix(transform); mitkImage->GetGeometry()->SetIndexToWorldTransform(affineTransform); // mitk::AffineTransform3D::New(); //mitkImage->GetGeometry()->SetIndexToWorldTransform(); // cleanup command.clear(); command.append( QString("del %1_numpy_array\n").arg(varName) ); command.append( QString("del %1_dtype\n").arg(varName) ); command.append( QString("del %1_spacing\n").arg(varName) ); command.append( QString("del %1_origin\n").arg(varName) ); command.append( QString("del %1_direction\n").arg(varName) ); command.append( QString("del %1_nrComponents\n").arg(varName) ); MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString(); this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND ); delete[] dimensions; return mitkImage; } bool mitk::PythonService::CopyToPythonAsCvImage( mitk::Image* image, const std::string& stdvarName ) { QString varName = QString::fromStdString( stdvarName ); QString command; unsigned int* imgDim = image->GetDimensions(); int npy_nd = 1; // access python module PyObject *pyMod = PyImport_AddModule((char*)"__main__"); // global dictionary PyObject *pyDict = PyModule_GetDict(pyMod); mitk::PixelType pixelType = image->GetPixelType(); PyObject* npyArray = nullptr; mitk::ImageReadAccessor racc(image); void* array = (void*) racc.GetData(); // save the total number of elements here (since the numpy array is one dimensional) npy_intp* npy_dims = new npy_intp[1]; npy_dims[0] = imgDim[0]; /** * Build a string in the format [1024,1028,1] * to describe the dimensionality. This is needed for simple itk * to know the dimensions of the image */ QString dimensionString; dimensionString.append(QString("[")); dimensionString.append(QString::number(imgDim[0])); // ToDo: check if we need this for (unsigned i = 1; i < 3; ++i) // always three because otherwise the 3d-geometry gets destroyed // (relevant for backtransformation of simple itk image to mitk. { dimensionString.append(QString(",")); dimensionString.append(QString::number(imgDim[i])); npy_dims[0] *= imgDim[i]; } dimensionString.append("]"); // the next line is necessary for vectorimages npy_dims[0] *= pixelType.GetNumberOfComponents(); // default pixeltype: unsigned short NPY_TYPES npy_type = NPY_USHORT; if( pixelType.GetComponentType() == itk::ImageIOBase::DOUBLE ) { npy_type = NPY_DOUBLE; } else if( pixelType.GetComponentType() == itk::ImageIOBase::FLOAT ) { npy_type = NPY_FLOAT; } else if( pixelType.GetComponentType() == itk::ImageIOBase::SHORT) { npy_type = NPY_SHORT; } else if( pixelType.GetComponentType() == itk::ImageIOBase::CHAR ) { npy_type = NPY_BYTE; } else if( pixelType.GetComponentType() == itk::ImageIOBase::INT ) { npy_type = NPY_INT; } else if( pixelType.GetComponentType() == itk::ImageIOBase::LONG ) { npy_type = NPY_LONG; } else if( pixelType.GetComponentType() == itk::ImageIOBase::UCHAR ) { npy_type = NPY_UBYTE; } else if( pixelType.GetComponentType() == itk::ImageIOBase::UINT ) { npy_type = NPY_UINT; } else if( pixelType.GetComponentType() == itk::ImageIOBase::ULONG ) { npy_type = NPY_LONG; } else if( pixelType.GetComponentType() == itk::ImageIOBase::USHORT ) { npy_type = NPY_USHORT; } else { MITK_WARN << "not a recognized pixeltype"; return false; } // creating numpy array import_array1 (true); npyArray = PyArray_SimpleNewFromData(npy_nd,npy_dims,npy_type,array); // add temp array it to the python dictionary to access it in python code const int status = PyDict_SetItemString( pyDict,QString("%1_numpy_array") .arg(varName).toStdString().c_str(), npyArray ); // sanity check if ( status != 0 ) return false; command.append( QString("import numpy as np\n")); //command.append( QString("if '%1' in globals():\n").arg(varName)); //command.append( QString(" del %1\n").arg(varName)); command.append( QString("%1_array_tmp=%1_numpy_array.copy()\n").arg(varName)); command.append( QString("%1_array_tmp=%1_array_tmp.reshape(%2,%3,%4)\n").arg( varName, QString::number(imgDim[1]), QString::number(imgDim[0]), QString::number(pixelType.GetNumberOfComponents()))); command.append( QString("%1 = %1_array_tmp[:,...,::-1]\n").arg(varName)); command.append( QString("del %1_numpy_array\n").arg(varName) ); command.append( QString("del %1_array_tmp").arg(varName) ); MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString(); this->Execute( command.toStdString(), IPythonService::MULTI_LINE_COMMAND ); return true; } mitk::Image::Pointer mitk::PythonService::CopyCvImageFromPython( const std::string& stdvarName ) { // access python module PyObject *pyMod = PyImport_AddModule((char*)"__main__"); // global dictionarry PyObject *pyDict = PyModule_GetDict(pyMod); mitk::Image::Pointer mitkImage = mitk::Image::New(); QString command; QString varName = QString::fromStdString( stdvarName ); command.append( QString("import numpy as np\n")); command.append( QString("%1_dtype=%1.dtype.name\n").arg(varName) ); command.append( QString("%1_shape=np.asarray(%1.shape)\n").arg(varName) ); command.append( QString("%1_np_array=%1[:,...,::-1]\n").arg(varName)); command.append( QString("%1_np_array=np.reshape(%1_np_array,%1.shape[0] * %1.shape[1] * %1.shape[2])").arg(varName) ); MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString(); this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND ); PyObject* py_dtype = PyDict_GetItemString(pyDict,QString("%1_dtype").arg(varName).toStdString().c_str() ); std::string dtype = PyString_AsString(py_dtype); PyArrayObject* py_data = (PyArrayObject*) PyDict_GetItemString(pyDict,QString("%1_np_array").arg(varName).toStdString().c_str() ); PyArrayObject* shape = (PyArrayObject*) PyDict_GetItemString(pyDict,QString("%1_shape").arg(varName).toStdString().c_str() ); size_t* d = reinterpret_cast(PyArray_DATA(shape)); unsigned int dimensions[3]; dimensions[0] = d[1]; dimensions[1] = d[0]; dimensions[2] = d[2]; unsigned int nr_dimensions = 2; // get number of components unsigned int nr_Components = (unsigned int) d[2]; mitk::PixelType pixelType = DeterminePixelType(dtype, nr_Components, nr_dimensions); mitkImage->Initialize(pixelType, nr_dimensions, dimensions); //mitkImage->SetChannel(py_data->data); { mitk::ImageWriteAccessor ra(mitkImage); char* data = (char*)(ra.GetData()); memcpy(data, PyArray_DATA(py_data), dimensions[0] * dimensions[1] * pixelType.GetSize()); } command.clear(); command.append( QString("del %1_shape\n").arg(varName) ); command.append( QString("del %1_dtype\n").arg(varName) ); command.append( QString("del %1_np_array").arg(varName)); MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString(); this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND ); return mitkImage; } ctkAbstractPythonManager *mitk::PythonService::GetPythonManager() { return &m_PythonManager; } mitk::Surface::Pointer mitk::PythonService::CopyVtkPolyDataFromPython( const std::string& stdvarName ) { // access python module PyObject *pyMod = PyImport_AddModule((char*)"__main__"); // global dictionarry PyObject *pyDict = PyModule_GetDict(pyMod); // python memory address PyObject *pyAddr = nullptr; // cpp address size_t addr = 0; mitk::Surface::Pointer surface = mitk::Surface::New(); QString command; QString varName = QString::fromStdString( stdvarName ); command.append( QString("%1_addr_str = %1.GetAddressAsString(\"vtkPolyData\")\n").arg(varName) ); // remove 0x from the address command.append( QString("%1_addr = int(%1_addr_str[5:],16)").arg(varName) ); MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString(); this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND ); // get address of the object pyAddr = PyDict_GetItemString(pyDict,QString("%1_addr").arg(varName).toStdString().c_str()); // convert to long addr = PyInt_AsLong(pyAddr); MITK_DEBUG << "Python object address: " << addr; // get the object vtkPolyData* poly = (vtkPolyData*)((void*)addr); surface->SetVtkPolyData(poly); // delete helper variables from python stack command = ""; command.append( QString("del %1_addr_str\n").arg(varName) ); command.append( QString("del %1_addr").arg(varName) ); MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString(); this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND ); return surface; } bool mitk::PythonService::CopyToPythonAsVtkPolyData( mitk::Surface* surface, const std::string& stdvarName ) { QString varName = QString::fromStdString( stdvarName ); std::ostringstream oss; std::string addr = ""; QString command; QString address; oss << (void*) ( surface->GetVtkPolyData() ); // get the address addr = oss.str(); // remove "0x" address = QString::fromStdString(addr.substr(2)); command.append( QString("%1 = vtk.vtkPolyData(\"%2\")\n").arg(varName).arg(address) ); MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString(); this->Execute(command.toStdString(), IPythonService::MULTI_LINE_COMMAND ); return true; } bool mitk::PythonService::IsSimpleItkPythonWrappingAvailable() { this->Execute( "import SimpleITK as sitk\n", IPythonService::SINGLE_LINE_COMMAND ); // directly access cpp lib - this->Execute( "import _SimpleITK\n", IPythonService::SINGLE_LINE_COMMAND ); + this->Execute( "import SimpleITK._SimpleITK as _SimpleITK\n", IPythonService::SINGLE_LINE_COMMAND ); m_ItkWrappingAvailable = !this->PythonErrorOccured(); // check for numpy this->Execute( "import numpy\n", IPythonService::SINGLE_LINE_COMMAND ); if ( this->PythonErrorOccured() ) MITK_ERROR << "Numpy not found."; m_ItkWrappingAvailable = !this->PythonErrorOccured(); return m_ItkWrappingAvailable; } bool mitk::PythonService::IsOpenCvPythonWrappingAvailable() { this->Execute( "import cv2\n", IPythonService::SINGLE_LINE_COMMAND ); m_OpenCVWrappingAvailable = !this->PythonErrorOccured(); return m_OpenCVWrappingAvailable; } bool mitk::PythonService::IsVtkPythonWrappingAvailable() { this->Execute( "import vtk", IPythonService::SINGLE_LINE_COMMAND ); //this->Execute( "print \"Using VTK version \" + vtk.vtkVersion.GetVTKVersion()\n", IPythonService::SINGLE_LINE_COMMAND ); m_VtkWrappingAvailable = !this->PythonErrorOccured(); return m_VtkWrappingAvailable; } bool mitk::PythonService::PythonErrorOccured() const { return m_ErrorOccured; } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingView.cpp index 58a19d4aa9..bb1f55848d 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingView.cpp @@ -1,1026 +1,1028 @@ /*=================================================================== 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 #include // Qmitk #include "QmitkStreamlineTrackingView.h" #include "QmitkStdMultiWidget.h" // Qt #include // MITK #include #include #include #include #include #include #include #include #include #include #include #include #include // VTK #include #include #include #include #include #include #include #include #include #include const std::string QmitkStreamlineTrackingView::VIEW_ID = "org.mitk.views.streamlinetracking"; const std::string id_DataManager = "org.mitk.views.datamanager"; using namespace berry; QmitkStreamlineTrackingWorker::QmitkStreamlineTrackingWorker(QmitkStreamlineTrackingView* view) : m_View(view) { } void QmitkStreamlineTrackingWorker::run() { m_View->m_Tracker->Update(); m_View->m_TrackingThread.quit(); } QmitkStreamlineTrackingView::QmitkStreamlineTrackingView() : m_TrackingWorker(this) , m_Controls(nullptr) , m_FirstTensorProbRun(true) , m_FirstInteractiveRun(true) , m_TrackingHandler(nullptr) , m_ThreadIsRunning(false) , m_DeleteTrackingHandler(false) , m_Visible(false) , m_LastPrior("") , m_TrackingPriorHandler(nullptr) { m_TrackingWorker.moveToThread(&m_TrackingThread); connect(&m_TrackingThread, SIGNAL(started()), this, SLOT(BeforeThread())); connect(&m_TrackingThread, SIGNAL(started()), &m_TrackingWorker, SLOT(run())); connect(&m_TrackingThread, SIGNAL(finished()), this, SLOT(AfterThread())); m_TrackingTimer = new QTimer(this); } // Destructor QmitkStreamlineTrackingView::~QmitkStreamlineTrackingView() { if (m_Tracker.IsNull()) return; m_Tracker->SetStopTracking(true); m_TrackingThread.wait(); } void QmitkStreamlineTrackingView::CreateQtPartControl( QWidget *parent ) { if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkStreamlineTrackingViewControls; m_Controls->setupUi( parent ); m_Controls->m_FaImageBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_SeedImageBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_MaskImageBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_TargetImageBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_PriorImageBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_StopImageBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_ForestBox->SetDataStorage(this->GetDataStorage()); m_Controls->m_ExclusionImageBox->SetDataStorage(this->GetDataStorage()); mitk::TNodePredicateDataType::Pointer isPeakImagePredicate = mitk::TNodePredicateDataType::New(); mitk::TNodePredicateDataType::Pointer isImagePredicate = mitk::TNodePredicateDataType::New(); mitk::TNodePredicateDataType::Pointer isTractographyForest = mitk::TNodePredicateDataType::New(); mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); mitk::NodePredicateNot::Pointer isNotBinaryPredicate = mitk::NodePredicateNot::New( isBinaryPredicate ); mitk::NodePredicateAnd::Pointer isNotABinaryImagePredicate = mitk::NodePredicateAnd::New( isImagePredicate, isNotBinaryPredicate ); mitk::NodePredicateDimension::Pointer dimensionPredicate = mitk::NodePredicateDimension::New(3); m_Controls->m_ForestBox->SetPredicate(isTractographyForest); m_Controls->m_FaImageBox->SetPredicate( mitk::NodePredicateAnd::New(isNotABinaryImagePredicate, dimensionPredicate) ); m_Controls->m_FaImageBox->SetZeroEntryText("--"); m_Controls->m_SeedImageBox->SetPredicate( mitk::NodePredicateAnd::New(isImagePredicate, dimensionPredicate) ); m_Controls->m_SeedImageBox->SetZeroEntryText("--"); m_Controls->m_MaskImageBox->SetPredicate( mitk::NodePredicateAnd::New(isImagePredicate, dimensionPredicate) ); m_Controls->m_MaskImageBox->SetZeroEntryText("--"); m_Controls->m_StopImageBox->SetPredicate( mitk::NodePredicateAnd::New(isImagePredicate, dimensionPredicate) ); m_Controls->m_StopImageBox->SetZeroEntryText("--"); m_Controls->m_TargetImageBox->SetPredicate( mitk::NodePredicateAnd::New(isImagePredicate, dimensionPredicate) ); m_Controls->m_TargetImageBox->SetZeroEntryText("--"); m_Controls->m_PriorImageBox->SetPredicate( isPeakImagePredicate ); m_Controls->m_PriorImageBox->SetZeroEntryText("--"); m_Controls->m_ExclusionImageBox->SetPredicate( mitk::NodePredicateAnd::New(isImagePredicate, dimensionPredicate) ); m_Controls->m_ExclusionImageBox->SetZeroEntryText("--"); connect( m_TrackingTimer, SIGNAL(timeout()), this, SLOT(TimerUpdate()) ); connect( m_Controls->commandLinkButton_2, SIGNAL(clicked()), this, SLOT(StopTractography()) ); connect( m_Controls->commandLinkButton, SIGNAL(clicked()), this, SLOT(DoFiberTracking()) ); connect( m_Controls->m_InteractiveBox, SIGNAL(stateChanged(int)), this, SLOT(ToggleInteractive()) ); connect( m_Controls->m_ModeBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()) ); connect( m_Controls->m_FaImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(DeleteTrackingHandler()) ); connect( m_Controls->m_ModeBox, SIGNAL(currentIndexChanged(int)), this, SLOT(DeleteTrackingHandler()) ); connect( m_Controls->m_OutputProbMap, SIGNAL(stateChanged(int)), this, SLOT(OutputStyleSwitched()) ); connect( m_Controls->m_SeedImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_ModeBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_StopImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_TargetImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_PriorImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_ExclusionImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_MaskImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_FaImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_ForestBox, SIGNAL(currentIndexChanged(int)), this, SLOT(ForestSwitched()) ); connect( m_Controls->m_ForestBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_SeedsPerVoxelBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_NumFibersBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_ScalarThresholdBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_OdfCutoffBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_StepSizeBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_SamplingDistanceBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_AngularThresholdBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_MinTractLengthBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_fBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_gBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_NumSamplesBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_SeedRadiusBox, SIGNAL(editingFinished()), this, SLOT(InteractiveSeedChanged()) ); connect( m_Controls->m_NumSeedsBox, SIGNAL(editingFinished()), this, SLOT(InteractiveSeedChanged()) ); connect( m_Controls->m_OutputProbMap, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_SharpenOdfsBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_InterpolationBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_MaskInterpolationBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_FlipXBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_FlipYBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_FlipZBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_FrontalSamplesBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_StopVotesBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_LoopCheckBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_TrialsPerSeedBox, SIGNAL(editingFinished()), this, SLOT(OnParameterChanged()) ); connect( m_Controls->m_EpConstraintsBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnParameterChanged()) ); m_Controls->m_SeedsPerVoxelBox->editingFinished(); m_Controls->m_NumFibersBox->editingFinished(); m_Controls->m_ScalarThresholdBox->editingFinished(); m_Controls->m_OdfCutoffBox->editingFinished(); m_Controls->m_StepSizeBox->editingFinished(); m_Controls->m_SamplingDistanceBox->editingFinished(); m_Controls->m_AngularThresholdBox->editingFinished(); m_Controls->m_MinTractLengthBox->editingFinished(); m_Controls->m_fBox->editingFinished(); m_Controls->m_gBox->editingFinished(); m_Controls->m_NumSamplesBox->editingFinished(); m_Controls->m_SeedRadiusBox->editingFinished(); m_Controls->m_NumSeedsBox->editingFinished(); m_Controls->m_LoopCheckBox->editingFinished(); m_Controls->m_TrialsPerSeedBox->editingFinished(); StartStopTrackingGui(false); } UpdateGui(); } void QmitkStreamlineTrackingView::StopTractography() { if (m_Tracker.IsNull()) return; m_Tracker->SetStopTracking(true); } void QmitkStreamlineTrackingView::TimerUpdate() { if (m_Tracker.IsNull()) return; QString status_text(m_Tracker->GetStatusText().c_str()); m_Controls->m_StatusTextBox->setText(status_text); } void QmitkStreamlineTrackingView::BeforeThread() { m_TrackingTimer->start(1000); } void QmitkStreamlineTrackingView::AfterThread() { m_TrackingTimer->stop(); if (!m_Tracker->GetUseOutputProbabilityMap()) { vtkSmartPointer fiberBundle = m_Tracker->GetFiberPolyData(); if (!m_Controls->m_InteractiveBox->isChecked() && fiberBundle->GetNumberOfLines() == 0) { QMessageBox warnBox; warnBox.setWindowTitle("Warning"); warnBox.setText("No fiberbundle was generated!"); warnBox.setDetailedText("No fibers were generated using the chosen parameters. Typical reasons are:\n\n- Cutoff too high. Some images feature very low FA/GFA/peak size. Try to lower this parameter.\n- Angular threshold too strict. Try to increase this parameter.\n- A small step sizes also means many steps to go wrong. Especially in the case of probabilistic tractography. Try to adjust the angular threshold."); warnBox.setIcon(QMessageBox::Warning); warnBox.exec(); if (m_InteractivePointSetNode.IsNotNull()) m_InteractivePointSetNode->SetProperty("color", mitk::ColorProperty::New(1,1,1)); StartStopTrackingGui(false); if (m_DeleteTrackingHandler) DeleteTrackingHandler(); UpdateGui(); return; } mitk::FiberBundle::Pointer fib = mitk::FiberBundle::New(fiberBundle); fib->SetReferenceGeometry(dynamic_cast(m_ParentNode->GetData())->GetGeometry()); if (m_Controls->m_ResampleFibersBox->isChecked() && fiberBundle->GetNumberOfLines()>0) fib->Compress(m_Controls->m_FiberErrorBox->value()); fib->ColorFibersByOrientation(); m_Tracker->SetDicomProperties(fib); if (m_Controls->m_InteractiveBox->isChecked()) { if (m_InteractiveNode.IsNull()) { m_InteractiveNode = mitk::DataNode::New(); QString name("Interactive"); m_InteractiveNode->SetName(name.toStdString()); GetDataStorage()->Add(m_InteractiveNode); } m_InteractiveNode->SetData(fib); m_InteractiveNode->SetFloatProperty("Fiber2DSliceThickness", m_Tracker->GetMinVoxelSize()/2); if (auto renderWindowPart = this->GetRenderWindowPart()) renderWindowPart->RequestUpdate(); } else { mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(fib); QString name("FiberBundle_"); name += m_ParentNode->GetName().c_str(); name += "_Streamline"; node->SetName(name.toStdString()); node->SetFloatProperty("Fiber2DSliceThickness", m_Tracker->GetMinVoxelSize()/2); GetDataStorage()->Add(node, m_ParentNode); } } else { TrackerType::ItkDoubleImgType::Pointer outImg = m_Tracker->GetOutputProbabilityMap(); mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk(outImg.GetPointer()); img->SetVolume(outImg->GetBufferPointer()); if (m_Controls->m_InteractiveBox->isChecked()) { if (m_InteractiveNode.IsNull()) { m_InteractiveNode = mitk::DataNode::New(); QString name("Interactive"); m_InteractiveNode->SetName(name.toStdString()); GetDataStorage()->Add(m_InteractiveNode); } m_InteractiveNode->SetData(img); 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); m_InteractiveNode->SetProperty("LookupTable", lut_prop); m_InteractiveNode->SetProperty("opacity", mitk::FloatProperty::New(0.5)); m_InteractiveNode->SetFloatProperty("Fiber2DSliceThickness", m_Tracker->GetMinVoxelSize()/2); if (auto renderWindowPart = this->GetRenderWindowPart()) renderWindowPart->RequestUpdate(); } else { mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(img); QString name("ProbabilityMap_"); name += m_ParentNode->GetName().c_str(); node->SetName(name.toStdString()); 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); node->SetProperty("LookupTable", lut_prop); node->SetProperty("opacity", mitk::FloatProperty::New(0.5)); GetDataStorage()->Add(node, m_ParentNode); } } if (m_InteractivePointSetNode.IsNotNull()) m_InteractivePointSetNode->SetProperty("color", mitk::ColorProperty::New(1,1,1)); StartStopTrackingGui(false); if (m_DeleteTrackingHandler) DeleteTrackingHandler(); UpdateGui(); } void QmitkStreamlineTrackingView::InteractiveSeedChanged(bool posChanged) { if(!CheckAndStoreLastParams(sender()) && !posChanged) return; if (m_ThreadIsRunning || !m_Visible) return; if (!posChanged && (!m_Controls->m_InteractiveBox->isChecked() || !m_Controls->m_ParamUpdateBox->isChecked()) ) return; std::srand(std::time(0)); m_SeedPoints.clear(); itk::Point world_pos = this->GetRenderWindowPart()->GetSelectedPosition(); m_SeedPoints.push_back(world_pos); float radius = m_Controls->m_SeedRadiusBox->value(); int num = m_Controls->m_NumSeedsBox->value(); mitk::PointSet::Pointer pointset = mitk::PointSet::New(); pointset->InsertPoint(0, world_pos); m_InteractivePointSetNode->SetProperty("pointsize", mitk::FloatProperty::New(radius*2)); m_InteractivePointSetNode->SetProperty("point 2D size", mitk::FloatProperty::New(radius*2)); m_InteractivePointSetNode->SetData(pointset); for (int i=1; i p; p[0] = rand()%1000-500; p[1] = rand()%1000-500; p[2] = rand()%1000-500; p.Normalize(); p *= radius; m_SeedPoints.push_back(world_pos+p); } m_InteractivePointSetNode->SetProperty("color", mitk::ColorProperty::New(1,0,0)); DoFiberTracking(); } bool QmitkStreamlineTrackingView::CheckAndStoreLastParams(QObject* obj) { if (obj!=nullptr) { std::string new_val = ""; if(qobject_cast(obj)!=nullptr) new_val = boost::lexical_cast(qobject_cast(obj)->value()); else if (qobject_cast(obj)!=nullptr) new_val = boost::lexical_cast(qobject_cast(obj)->value()); + else + return true; if (m_LastTractoParams.find(obj->objectName())==m_LastTractoParams.end()) { m_LastTractoParams[obj->objectName()] = new_val; return false; } else if (m_LastTractoParams.at(obj->objectName()) != new_val) { m_LastTractoParams[obj->objectName()] = new_val; return true; } else if (m_LastTractoParams.at(obj->objectName()) == new_val) return false; } return true; } void QmitkStreamlineTrackingView::OnParameterChanged() { UpdateGui(); if(!CheckAndStoreLastParams(sender())) return; if (m_Controls->m_InteractiveBox->isChecked() && m_Controls->m_ParamUpdateBox->isChecked()) DoFiberTracking(); } void QmitkStreamlineTrackingView::ToggleInteractive() { UpdateGui(); m_Controls->m_SeedsPerVoxelBox->setEnabled(!m_Controls->m_InteractiveBox->isChecked()); m_Controls->m_SeedsPerVoxelLabel->setEnabled(!m_Controls->m_InteractiveBox->isChecked()); m_Controls->m_SeedImageBox->setEnabled(!m_Controls->m_InteractiveBox->isChecked()); m_Controls->label_6->setEnabled(!m_Controls->m_InteractiveBox->isChecked()); if ( m_Controls->m_InteractiveBox->isChecked() ) { if (m_FirstInteractiveRun) { QMessageBox::information(nullptr, "Information", "Place and move a spherical seed region anywhere in the image by left-clicking and dragging. If the seed region is colored red, tracking is in progress. If the seed region is colored white, tracking is finished.\nPlacing the seed region for the first time in a newly selected dataset might cause a short delay, since the tracker needs to be initialized."); m_FirstInteractiveRun = false; } QApplication::setOverrideCursor(Qt::PointingHandCursor); QApplication::processEvents(); m_InteractivePointSetNode = mitk::DataNode::New(); m_InteractivePointSetNode->SetProperty("color", mitk::ColorProperty::New(1,1,1)); m_InteractivePointSetNode->SetName("InteractiveSeedRegion"); mitk::PointSetShapeProperty::Pointer shape_prop = mitk::PointSetShapeProperty::New(); shape_prop->SetValue(mitk::PointSetShapeProperty::PointSetShape::CIRCLE); m_InteractivePointSetNode->SetProperty("Pointset.2D.shape", shape_prop); GetDataStorage()->Add(m_InteractivePointSetNode); m_SliceChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart()); connect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged())); } else { QApplication::restoreOverrideCursor(); QApplication::processEvents(); m_InteractiveNode = nullptr; m_InteractivePointSetNode = nullptr; m_SliceChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart()); disconnect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged())); } } void QmitkStreamlineTrackingView::Activated() { } void QmitkStreamlineTrackingView::Deactivated() { } void QmitkStreamlineTrackingView::Visible() { m_Visible = true; } void QmitkStreamlineTrackingView::Hidden() { m_Visible = false; m_Controls->m_InteractiveBox->setChecked(false); ToggleInteractive(); } void QmitkStreamlineTrackingView::OnSliceChanged() { InteractiveSeedChanged(true); } void QmitkStreamlineTrackingView::SetFocus() { } void QmitkStreamlineTrackingView::DeleteTrackingHandler() { if (!m_ThreadIsRunning && m_TrackingHandler != nullptr) { delete m_TrackingHandler; m_TrackingHandler = nullptr; m_DeleteTrackingHandler = false; m_LastPrior = ""; if (m_TrackingPriorHandler != nullptr) delete m_TrackingPriorHandler; } else if (m_ThreadIsRunning) { m_DeleteTrackingHandler = true; } } void QmitkStreamlineTrackingView::ForestSwitched() { DeleteTrackingHandler(); } void QmitkStreamlineTrackingView::OutputStyleSwitched() { if (m_InteractiveNode.IsNotNull()) GetDataStorage()->Remove(m_InteractiveNode); m_InteractiveNode = nullptr; } void QmitkStreamlineTrackingView::OnSelectionChanged( berry::IWorkbenchPart::Pointer , const QList& nodes ) { std::vector< mitk::DataNode::Pointer > last_nodes = m_InputImageNodes; m_InputImageNodes.clear(); m_InputImages.clear(); m_AdditionalInputImages.clear(); bool retrack = false; for( auto node : nodes ) { if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { if( dynamic_cast(node->GetData()) ) { m_InputImageNodes.push_back(node); m_InputImages.push_back(dynamic_cast(node->GetData())); retrack = true; } else if ( dynamic_cast(node->GetData()) ) { m_InputImageNodes.push_back(node); m_InputImages.push_back(dynamic_cast(node->GetData())); retrack = true; } else if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(node->GetData())) ) { m_InputImageNodes.push_back(node); m_InputImages.push_back(dynamic_cast(node->GetData())); retrack = true; } else { mitk::Image* img = dynamic_cast(node->GetData()); if (img!=nullptr) { int dim = img->GetDimension(); unsigned int* dimensions = img->GetDimensions(); if (dim==4 && dimensions[3]%3==0) { m_InputImageNodes.push_back(node); m_InputImages.push_back(dynamic_cast(node->GetData())); retrack = true; } else if (dim==3) { m_AdditionalInputImages.push_back(dynamic_cast(node->GetData())); } } } } } // sometimes the OnSelectionChanged event is sent twice and actually no selection has changed for the first event. We need to catch that. if (last_nodes.size() == m_InputImageNodes.size()) { bool same_nodes = true; for (unsigned int i=0; im_TensorImageLabel->setText("select in data-manager"); m_Controls->m_fBox->setEnabled(false); m_Controls->m_fLabel->setEnabled(false); m_Controls->m_gBox->setEnabled(false); m_Controls->m_gLabel->setEnabled(false); m_Controls->m_FaImageBox->setEnabled(true); m_Controls->mFaImageLabel->setEnabled(true); m_Controls->m_OdfCutoffBox->setEnabled(false); m_Controls->m_OdfCutoffLabel->setEnabled(false); m_Controls->m_SharpenOdfsBox->setEnabled(false); m_Controls->m_ForestBox->setVisible(false); m_Controls->m_ForestLabel->setVisible(false); m_Controls->commandLinkButton->setEnabled(false); m_Controls->m_TrialsPerSeedBox->setEnabled(false); m_Controls->m_TrialsPerSeedLabel->setEnabled(false); m_Controls->m_TargetImageBox->setEnabled(false); m_Controls->m_TargetImageLabel->setEnabled(false); if (m_Controls->m_InteractiveBox->isChecked()) { m_Controls->m_InteractiveSeedingFrame->setVisible(true); m_Controls->m_StaticSeedingFrame->setVisible(false); m_Controls->commandLinkButton_2->setVisible(false); m_Controls->commandLinkButton->setVisible(false); } else { m_Controls->m_InteractiveSeedingFrame->setVisible(false); m_Controls->m_StaticSeedingFrame->setVisible(true); m_Controls->commandLinkButton_2->setVisible(m_ThreadIsRunning); m_Controls->commandLinkButton->setVisible(!m_ThreadIsRunning); } if (m_Controls->m_EpConstraintsBox->currentIndex()>0) { m_Controls->m_TargetImageBox->setEnabled(true); m_Controls->m_TargetImageLabel->setEnabled(true); } // trials per seed are only important for probabilistic tractography if (m_Controls->m_ModeBox->currentIndex()==1) { m_Controls->m_TrialsPerSeedBox->setEnabled(true); m_Controls->m_TrialsPerSeedLabel->setEnabled(true); } if(!m_InputImageNodes.empty()) { if (m_InputImageNodes.size()>1) m_Controls->m_TensorImageLabel->setText( ( std::to_string(m_InputImageNodes.size()) + " images selected").c_str() ); else m_Controls->m_TensorImageLabel->setText(m_InputImageNodes.at(0)->GetName().c_str()); m_Controls->commandLinkButton->setEnabled(!m_Controls->m_InteractiveBox->isChecked() && !m_ThreadIsRunning); m_Controls->m_ScalarThresholdBox->setEnabled(true); m_Controls->m_FaThresholdLabel->setEnabled(true); if ( dynamic_cast(m_InputImageNodes.at(0)->GetData()) ) { m_Controls->m_fBox->setEnabled(true); m_Controls->m_fLabel->setEnabled(true); m_Controls->m_gBox->setEnabled(true); m_Controls->m_gLabel->setEnabled(true); } else if ( dynamic_cast(m_InputImageNodes.at(0)->GetData()) ) { m_Controls->m_OdfCutoffBox->setEnabled(true); m_Controls->m_OdfCutoffLabel->setEnabled(true); m_Controls->m_SharpenOdfsBox->setEnabled(true); } else if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_InputImageNodes.at(0)->GetData())) ) { m_Controls->m_ForestBox->setVisible(true); m_Controls->m_ForestLabel->setVisible(true); m_Controls->m_ScalarThresholdBox->setEnabled(false); m_Controls->m_FaThresholdLabel->setEnabled(false); } } } void QmitkStreamlineTrackingView::StartStopTrackingGui(bool start) { m_ThreadIsRunning = start; if (!m_Controls->m_InteractiveBox->isChecked()) { m_Controls->commandLinkButton_2->setVisible(start); m_Controls->commandLinkButton->setVisible(!start); m_Controls->m_InteractiveBox->setEnabled(!start); m_Controls->m_StatusTextBox->setVisible(start); } } void QmitkStreamlineTrackingView::DoFiberTracking() { if (m_InputImages.empty()) { QMessageBox::information(nullptr, "Information", "Please select an input image in the datamaneger (tensor, ODF, peak or dMRI image)!"); return; } if (m_ThreadIsRunning || !m_Visible) return; if (m_Controls->m_InteractiveBox->isChecked() && m_SeedPoints.empty()) return; StartStopTrackingGui(true); m_Tracker = TrackerType::New(); if( dynamic_cast(m_InputImageNodes.at(0)->GetData()) ) { if (m_Controls->m_ModeBox->currentIndex()==1) { if (m_InputImages.size()>1) { QMessageBox::information(nullptr, "Information", "Probabilistic tensor tractography is only implemented for single-tensor mode!"); StartStopTrackingGui(false); return; } if (m_TrackingHandler==nullptr) { m_TrackingHandler = new mitk::TrackingHandlerOdf(); mitk::TensorImage::ItkTensorImageType::Pointer itkImg = mitk::TensorImage::ItkTensorImageType::New(); mitk::CastToItkImage(m_InputImages.at(0), itkImg); typedef itk::TensorImageToOdfImageFilter< float, float > FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetInput( itkImg ); filter->Update(); dynamic_cast(m_TrackingHandler)->SetOdfImage(filter->GetOutput()); if (m_Controls->m_FaImageBox->GetSelectedNode().IsNotNull()) { ItkFloatImageType::Pointer itkImg = ItkFloatImageType::New(); mitk::CastToItkImage(dynamic_cast(m_Controls->m_FaImageBox->GetSelectedNode()->GetData()), itkImg); dynamic_cast(m_TrackingHandler)->SetGfaImage(itkImg); } } dynamic_cast(m_TrackingHandler)->SetGfaThreshold(m_Controls->m_ScalarThresholdBox->value()); dynamic_cast(m_TrackingHandler)->SetOdfThreshold(0); dynamic_cast(m_TrackingHandler)->SetSharpenOdfs(true); dynamic_cast(m_TrackingHandler)->SetIsOdfFromTensor(true); } else { if (m_TrackingHandler==nullptr) { m_TrackingHandler = new mitk::TrackingHandlerTensor(); for (int i=0; i<(int)m_InputImages.size(); i++) { typedef mitk::ImageToItk< mitk::TrackingHandlerTensor::ItkTensorImageType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(m_InputImages.at(i)); caster->Update(); mitk::TrackingHandlerTensor::ItkTensorImageType::ConstPointer itkImg = caster->GetOutput(); dynamic_cast(m_TrackingHandler)->AddTensorImage(itkImg); } if (m_Controls->m_FaImageBox->GetSelectedNode().IsNotNull()) { ItkFloatImageType::Pointer itkImg = ItkFloatImageType::New(); mitk::CastToItkImage(dynamic_cast(m_Controls->m_FaImageBox->GetSelectedNode()->GetData()), itkImg); dynamic_cast(m_TrackingHandler)->SetFaImage(itkImg); } } dynamic_cast(m_TrackingHandler)->SetFaThreshold(m_Controls->m_ScalarThresholdBox->value()); dynamic_cast(m_TrackingHandler)->SetF((float)m_Controls->m_fBox->value()); dynamic_cast(m_TrackingHandler)->SetG((float)m_Controls->m_gBox->value()); } } else if ( dynamic_cast(m_InputImageNodes.at(0)->GetData()) ) { if (m_TrackingHandler==nullptr) { m_TrackingHandler = new mitk::TrackingHandlerOdf(); mitk::TrackingHandlerOdf::ItkOdfImageType::Pointer itkImg = mitk::TrackingHandlerOdf::ItkOdfImageType::New(); mitk::CastToItkImage(m_InputImages.at(0), itkImg); dynamic_cast(m_TrackingHandler)->SetOdfImage(itkImg); if (m_Controls->m_FaImageBox->GetSelectedNode().IsNotNull()) { ItkFloatImageType::Pointer itkImg = ItkFloatImageType::New(); mitk::CastToItkImage(dynamic_cast(m_Controls->m_FaImageBox->GetSelectedNode()->GetData()), itkImg); dynamic_cast(m_TrackingHandler)->SetGfaImage(itkImg); } } dynamic_cast(m_TrackingHandler)->SetGfaThreshold(m_Controls->m_ScalarThresholdBox->value()); dynamic_cast(m_TrackingHandler)->SetOdfThreshold(m_Controls->m_OdfCutoffBox->value()); dynamic_cast(m_TrackingHandler)->SetSharpenOdfs(m_Controls->m_SharpenOdfsBox->isChecked()); } else if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(m_InputImageNodes.at(0)->GetData())) ) { if ( m_Controls->m_ForestBox->GetSelectedNode().IsNull() ) { QMessageBox::information(nullptr, "Information", "Not random forest for machine learning based tractography (raw dMRI tractography) selected. Did you accidentally select the raw diffusion-weighted image in the datamanager?"); StartStopTrackingGui(false); return; } if (m_TrackingHandler==nullptr) { mitk::TractographyForest::Pointer forest = dynamic_cast(m_Controls->m_ForestBox->GetSelectedNode()->GetData()); mitk::Image::Pointer dwi = dynamic_cast(m_InputImageNodes.at(0)->GetData()); std::vector< std::vector< ItkFloatImageType::Pointer > > additionalFeatureImages; additionalFeatureImages.push_back(std::vector< ItkFloatImageType::Pointer >()); for (auto img : m_AdditionalInputImages) { ItkFloatImageType::Pointer itkimg = ItkFloatImageType::New(); mitk::CastToItkImage(img, itkimg); additionalFeatureImages.at(0).push_back(itkimg); } bool forest_valid = false; if (forest->GetNumFeatures()>=100) { int num_previous_directions = (forest->GetNumFeatures() - (100 + additionalFeatureImages.at(0).size()))/3; m_TrackingHandler = new mitk::TrackingHandlerRandomForest<6, 100>(); dynamic_cast*>(m_TrackingHandler)->AddDwi(dwi); dynamic_cast*>(m_TrackingHandler)->SetAdditionalFeatureImages(additionalFeatureImages); dynamic_cast*>(m_TrackingHandler)->SetForest(forest); dynamic_cast*>(m_TrackingHandler)->SetNumPreviousDirections(num_previous_directions); forest_valid = dynamic_cast*>(m_TrackingHandler)->IsForestValid(); } else { int num_previous_directions = (forest->GetNumFeatures() - (28 + additionalFeatureImages.at(0).size()))/3; m_TrackingHandler = new mitk::TrackingHandlerRandomForest<6, 28>(); dynamic_cast*>(m_TrackingHandler)->AddDwi(dwi); dynamic_cast*>(m_TrackingHandler)->SetAdditionalFeatureImages(additionalFeatureImages); dynamic_cast*>(m_TrackingHandler)->SetForest(forest); dynamic_cast*>(m_TrackingHandler)->SetNumPreviousDirections(num_previous_directions); forest_valid = dynamic_cast*>(m_TrackingHandler)->IsForestValid(); } if (!forest_valid) { QMessageBox::information(nullptr, "Information", "Random forest is invalid. The forest signatue does not match the parameters of TrackingHandlerRandomForest."); StartStopTrackingGui(false); return; } } } else { if (m_Controls->m_ModeBox->currentIndex()==1) { QMessageBox::information(nullptr, "Information", "Probabilstic tractography is not implemented for peak images."); StartStopTrackingGui(false); return; } try { if (m_TrackingHandler==nullptr) { typedef mitk::ImageToItk< mitk::TrackingHandlerPeaks::PeakImgType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(m_InputImages.at(0)); caster->SetCopyMemFlag(true); caster->Update(); mitk::TrackingHandlerPeaks::PeakImgType::Pointer itkImg = caster->GetOutput(); m_TrackingHandler = new mitk::TrackingHandlerPeaks(); dynamic_cast(m_TrackingHandler)->SetPeakImage(itkImg); } dynamic_cast(m_TrackingHandler)->SetPeakThreshold(m_Controls->m_ScalarThresholdBox->value()); } catch(...) { QMessageBox::information(nullptr, "Error", "Peak tracker could not be initialized. Is your input image in the correct format (4D float image, peaks in the 4th dimension)?"); StartStopTrackingGui(false); return; } } m_TrackingHandler->SetFlipX(m_Controls->m_FlipXBox->isChecked()); m_TrackingHandler->SetFlipY(m_Controls->m_FlipYBox->isChecked()); m_TrackingHandler->SetFlipZ(m_Controls->m_FlipZBox->isChecked()); m_TrackingHandler->SetInterpolate(m_Controls->m_InterpolationBox->isChecked()); switch (m_Controls->m_ModeBox->currentIndex()) { case 0: m_TrackingHandler->SetMode(mitk::TrackingDataHandler::MODE::DETERMINISTIC); break; case 1: m_TrackingHandler->SetMode(mitk::TrackingDataHandler::MODE::PROBABILISTIC); break; default: m_TrackingHandler->SetMode(mitk::TrackingDataHandler::MODE::DETERMINISTIC); } if (m_Controls->m_InteractiveBox->isChecked()) { m_Tracker->SetSeedPoints(m_SeedPoints); } else if (m_Controls->m_SeedImageBox->GetSelectedNode().IsNotNull()) { ItkFloatImageType::Pointer mask = ItkFloatImageType::New(); mitk::CastToItkImage(dynamic_cast(m_Controls->m_SeedImageBox->GetSelectedNode()->GetData()), mask); m_Tracker->SetSeedImage(mask); } if (m_Controls->m_MaskImageBox->GetSelectedNode().IsNotNull()) { ItkFloatImageType::Pointer mask = ItkFloatImageType::New(); mitk::CastToItkImage(dynamic_cast(m_Controls->m_MaskImageBox->GetSelectedNode()->GetData()), mask); m_Tracker->SetMaskImage(mask); } if (m_Controls->m_StopImageBox->GetSelectedNode().IsNotNull()) { ItkFloatImageType::Pointer mask = ItkFloatImageType::New(); mitk::CastToItkImage(dynamic_cast(m_Controls->m_StopImageBox->GetSelectedNode()->GetData()), mask); m_Tracker->SetStoppingRegions(mask); } if (m_Controls->m_TargetImageBox->GetSelectedNode().IsNotNull()) { ItkFloatImageType::Pointer mask = ItkFloatImageType::New(); mitk::CastToItkImage(dynamic_cast(m_Controls->m_TargetImageBox->GetSelectedNode()->GetData()), mask); m_Tracker->SetTargetRegions(mask); } if (m_Controls->m_PriorImageBox->GetSelectedNode().IsNotNull()) { if (m_LastPrior!=m_Controls->m_PriorImageBox->GetSelectedNode()->GetUID() || m_TrackingPriorHandler==nullptr) { typedef mitk::ImageToItk< mitk::TrackingHandlerPeaks::PeakImgType > CasterType; CasterType::Pointer caster = CasterType::New(); caster->SetInput(dynamic_cast(m_Controls->m_PriorImageBox->GetSelectedNode()->GetData())); caster->SetCopyMemFlag(true); caster->Update(); mitk::TrackingHandlerPeaks::PeakImgType::Pointer itkImg = caster->GetOutput(); m_TrackingPriorHandler = new mitk::TrackingHandlerPeaks(); dynamic_cast(m_TrackingPriorHandler)->SetPeakImage(itkImg); dynamic_cast(m_TrackingPriorHandler)->SetPeakThreshold(0.0); m_LastPrior = m_Controls->m_PriorImageBox->GetSelectedNode()->GetUID(); } m_TrackingPriorHandler->SetInterpolate(m_Controls->m_InterpolationBox->isChecked()); m_TrackingPriorHandler->SetMode(mitk::TrackingDataHandler::MODE::DETERMINISTIC); m_Tracker->SetTrackingPriorHandler(m_TrackingPriorHandler); m_Tracker->SetTrackingPriorWeight(m_Controls->m_PriorWeightBox->value()); m_Tracker->SetTrackingPriorAsMask(m_Controls->m_PriorAsMaskBox->isChecked()); m_Tracker->SetIntroduceDirectionsFromPrior(m_Controls->m_NewDirectionsFromPriorBox->isChecked()); } else if (m_Controls->m_PriorImageBox->GetSelectedNode().IsNull()) m_Tracker->SetTrackingPriorHandler(nullptr); if (m_Controls->m_ExclusionImageBox->GetSelectedNode().IsNotNull()) { ItkFloatImageType::Pointer mask = ItkFloatImageType::New(); mitk::CastToItkImage(dynamic_cast(m_Controls->m_ExclusionImageBox->GetSelectedNode()->GetData()), mask); m_Tracker->SetExclusionRegions(mask); } // Endpoint constraints switch (m_Controls->m_EpConstraintsBox->currentIndex()) { case 0: m_Tracker->SetEndpointConstraint(itk::StreamlineTrackingFilter::EndpointConstraints::NONE); m_Tracker->SetTargetRegions(nullptr); break; case 1: m_Tracker->SetEndpointConstraint(itk::StreamlineTrackingFilter::EndpointConstraints::EPS_IN_TARGET); break; case 2: m_Tracker->SetEndpointConstraint(itk::StreamlineTrackingFilter::EndpointConstraints::EPS_IN_TARGET_LABELDIFF); break; case 3: m_Tracker->SetEndpointConstraint(itk::StreamlineTrackingFilter::EndpointConstraints::EPS_IN_SEED_AND_TARGET); break; case 4: m_Tracker->SetEndpointConstraint(itk::StreamlineTrackingFilter::EndpointConstraints::MIN_ONE_EP_IN_TARGET); break; case 5: m_Tracker->SetEndpointConstraint(itk::StreamlineTrackingFilter::EndpointConstraints::ONE_EP_IN_TARGET); break; case 6: m_Tracker->SetEndpointConstraint(itk::StreamlineTrackingFilter::EndpointConstraints::NO_EP_IN_TARGET); break; } if (m_Tracker->GetEndpointConstraint()!=itk::StreamlineTrackingFilter::EndpointConstraints::NONE && m_Controls->m_TargetImageBox->GetSelectedNode().IsNull()) { QMessageBox::information(nullptr, "Error", "Endpoint constraints are used but no target image is set!"); StartStopTrackingGui(false); return; } else if (m_Tracker->GetEndpointConstraint()==itk::StreamlineTrackingFilter::EndpointConstraints::EPS_IN_SEED_AND_TARGET && (m_Controls->m_SeedImageBox->GetSelectedNode().IsNull()|| m_Controls->m_TargetImageBox->GetSelectedNode().IsNull()) ) { QMessageBox::information(nullptr, "Error", "Endpoint constraint EPS_IN_SEED_AND_TARGET is used but no target or no seed image is set!"); StartStopTrackingGui(false); return; } m_Tracker->SetInterpolateMasks(m_Controls->m_MaskInterpolationBox->isChecked()); m_Tracker->SetVerbose(!m_Controls->m_InteractiveBox->isChecked()); m_Tracker->SetSeedsPerVoxel(m_Controls->m_SeedsPerVoxelBox->value()); m_Tracker->SetStepSize(m_Controls->m_StepSizeBox->value()); m_Tracker->SetSamplingDistance(m_Controls->m_SamplingDistanceBox->value()); m_Tracker->SetUseStopVotes(m_Controls->m_StopVotesBox->isChecked()); m_Tracker->SetOnlyForwardSamples(m_Controls->m_FrontalSamplesBox->isChecked()); m_Tracker->SetTrialsPerSeed(m_Controls->m_TrialsPerSeedBox->value()); m_Tracker->SetMaxNumTracts(m_Controls->m_NumFibersBox->value()); m_Tracker->SetNumberOfSamples(m_Controls->m_NumSamplesBox->value()); m_Tracker->SetTrackingHandler(m_TrackingHandler); m_Tracker->SetLoopCheck(m_Controls->m_LoopCheckBox->value()); m_Tracker->SetAngularThreshold(m_Controls->m_AngularThresholdBox->value()); m_Tracker->SetMinTractLength(m_Controls->m_MinTractLengthBox->value()); m_Tracker->SetUseOutputProbabilityMap(m_Controls->m_OutputProbMap->isChecked()); m_ParentNode = m_InputImageNodes.at(0); m_TrackingThread.start(QThread::LowestPriority); }