Page MenuHomePhabricator

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/Applications/Diffusion/MitkDiffusion.cpp b/Applications/Diffusion/MitkDiffusion.cpp
index c63d5f1..47ed67b 100644
--- a/Applications/Diffusion/MitkDiffusion.cpp
+++ b/Applications/Diffusion/MitkDiffusion.cpp
@@ -1,65 +1,65 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkBaseApplication.h>
#include <QPixmap>
#include <QSplashScreen>
#include <QTimer>
#include <QVariant>
int main(int argc, char **argv)
{
mitk::BaseApplication app(argc, argv);
app.setSingleMode(true);
app.setApplicationName("MitkDiffusion");
app.setOrganizationName("DKFZ");
/*
bool showSplashScreen(true);
QPixmap pixmap(":/splash/splashscreen.png");
QSplashScreen splash(pixmap);
splash.setMask(pixmap.mask());
splash.setWindowFlags(Qt::SplashScreen | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
if (showSplashScreen)
{
splash.show();
app.sendPostedEvents();
app.processEvents();
qSafeApp.flush();
QTimer::singleShot(4000, &splash, SLOT(close()));
}
*/
// Preload the org.mitk.gui.qt.ext plug-in (and hence also QmitkExt) to speed
// up a clean-cache start. This also works around bugs in older gcc and glibc implementations,
// which have difficulties with multiple dynamic opening and closing of shared libraries with
// many global static initializers. It also helps if dependent libraries have weird static
// initialization methods and/or missing de-initialization code.
QStringList preloadLibs;
preloadLibs << "liborg_mitk_gui_qt_ext";
app.setPreloadLibraries(preloadLibs);
// app.setProperty(mitk::BaseApplication::PROP_APPLICATION, "org.mitk.qt.diffusionimagingapp");
app.setProperty(mitk::BaseApplication::PROP_PRODUCT, "org.mitk.gui.qt.diffusionimagingapp.diffusion");
// Run the workbench.
return app.run();
}
\ No newline at end of file
diff --git a/Applications/Diffusion/QDiffusionImagingSplashScreen.cpp b/Applications/Diffusion/QDiffusionImagingSplashScreen.cpp
index e5ae3c7..5c8ff6b 100644
--- a/Applications/Diffusion/QDiffusionImagingSplashScreen.cpp
+++ b/Applications/Diffusion/QDiffusionImagingSplashScreen.cpp
@@ -1,105 +1,105 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QDiffusionImagingSplashScreen.h"
#include <QtGui>
#include <iostream>
QDiffusionImagingSplashScreen::QDiffusionImagingSplashScreen(const QImage &image, QWidget *parent)
: QWidget(parent, Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::SplashScreen), backgroundImage(image)
{
setAttribute(Qt::WA_TranslucentBackground);
resize(image.size());
resizeEvent(nullptr);
}
QDiffusionImagingSplashScreen::~QDiffusionImagingSplashScreen()
{
}
QSize QDiffusionImagingSplashScreen::sizeHint() const
{
return backgroundImage.size();
}
void QDiffusionImagingSplashScreen::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.drawImage(rect(), backgroundImage);
}
void QDiffusionImagingSplashScreen::resizeEvent(QResizeEvent *)
{
setMask(createMaskRegion(backgroundImage));
}
QRegion QDiffusionImagingSplashScreen::createMaskRegion(const QImage &image, bool posMask)
{
if (image.isNull())
return QRegion();
if (image.depth() != 32)
{
QImage img32 = image.convertToFormat(QImage::Format_RGB32);
return createMaskRegion(img32, posMask);
}
int width = image.width();
int height = image.height();
QRegion retVal;
for (int y = 0; y < height; ++y)
{
// guarented to be 32 bit by the check above
QRgb *currLine = (QRgb *)image.scanLine(y);
int xstart = -1;
int xcurr = -1;
QRgb *currVal = currLine;
for (int x = 0; x < width; ++x, ++currVal)
{
int alpha = qAlpha(*currVal);
if ((posMask && alpha != 0) || (!posMask && alpha == 0))
{
// on non-alpha pixel
if (xstart == -1)
{
// remember start of non-alpha line-segment (if necessary)
xstart = x;
}
xcurr = x;
}
else // alpha-pixel
if (xcurr != -1) // if this alpha pixel is following a non-alpha line-segment
{
retVal += QRegion(xstart, y, xcurr - xstart + 1, 1);
xstart = -1;
xcurr = -1;
}
}
if (xcurr != -1)
{
retVal += QRegion(xstart, y, xcurr - xstart + 1, 1);
}
}
return retVal;
}
void QDiffusionImagingSplashScreen::mouseReleaseEvent(QMouseEvent *mouseEvent)
{
QWidget::mouseReleaseEvent(mouseEvent);
hide();
}
diff --git a/Applications/Diffusion/QDiffusionImagingSplashScreen.h b/Applications/Diffusion/QDiffusionImagingSplashScreen.h
index 666ad90..491426e 100644
--- a/Applications/Diffusion/QDiffusionImagingSplashScreen.h
+++ b/Applications/Diffusion/QDiffusionImagingSplashScreen.h
@@ -1,42 +1,42 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QDiffusionImagingSplashScreen_h_included
#define QDiffusionImagingSplashScreen_h_included
#include <QImage>
#include <QWidget>
class QDiffusionImagingSplashScreen : public QWidget
{
Q_OBJECT
public:
QDiffusionImagingSplashScreen(const QImage &image, QWidget *parent = 0);
~QDiffusionImagingSplashScreen();
virtual QSize sizeHint() const;
protected:
virtual void paintEvent(QPaintEvent *paintEvent);
virtual void resizeEvent(QResizeEvent *resizeEvent);
virtual void mouseReleaseEvent(QMouseEvent *mouseEvent);
QRegion createMaskRegion(const QImage &image, bool posMask = true);
QImage backgroundImage;
};
#endif
diff --git a/CMakeExternals/BetData.h.in b/CMakeExternals/BetData.h.in
index 5730982..5e1b68b 100644
--- a/CMakeExternals/BetData.h.in
+++ b/CMakeExternals/BetData.h.in
@@ -1,31 +1,31 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 BetData_h
#define BetData_h
//#define BetData_DIR "@BetData_DIR@"
namespace mitk
{
namespace bet
{
std::vector< std::string > relative_search_dirs = {"/","/bin/","/BetData/","/bin/BetData/"};
std::vector< std::string > absolute_search_dirs = {"@BetData_DIR@"};
}
}
#endif
diff --git a/Modules/Connectomics/Algorithms/BrainParcellation/mitkCostFunctionBase.cpp b/Modules/Connectomics/Algorithms/BrainParcellation/mitkCostFunctionBase.cpp
index 2070c1f..430abcb 100644
--- a/Modules/Connectomics/Algorithms/BrainParcellation/mitkCostFunctionBase.cpp
+++ b/Modules/Connectomics/Algorithms/BrainParcellation/mitkCostFunctionBase.cpp
@@ -1,178 +1,178 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkCostFunctionBase.h>
//Itk Iterators
#include <itkNeighborhoodIterator.h>
#include <itkImageRegionIterator.h>
//Set Functions
template <typename TPixel, unsigned int VImageDimension>
void mitk::CostFunctionBase<TPixel, VImageDimension>::SetRegion(std::pair<RegionType, int> regionPair)
{
m_RegionPair = regionPair;
}
template <typename TPixel, unsigned int VImageDimension>
void mitk::CostFunctionBase<TPixel, VImageDimension>::SetImage(itk::Image<TPixel, VImageDimension> * image)
{
m_Image = image;
}
//Other Functions
template < typename TPixel, unsigned int VImageDimension >
int mitk::CostFunctionBase<TPixel, VImageDimension>::RegionIsFullEnough ()
{
//Calculate the volume of the region cuboid
itk::Size<3> size = m_RegionPair.first.GetSize();
double volume = size[0] * size[1] * size[2];
typedef itk::Image< int, VImageDimension > IntegerImageType;
itk::ImageRegionIterator<IntegerImageType> it_region(m_Image, m_RegionPair.first);
double voxelsWithRegionValue(1); //Because the possible new voxel hasn't been set to the region value yet
double voxelsWithValueZero(0);
for(it_region.GoToBegin(); !it_region.IsAtEnd(); ++it_region)
{
if (it_region.Value() == m_RegionPair.second)
{
voxelsWithRegionValue++;
}
if (it_region.Value() == 0)
{
voxelsWithValueZero++;
}
}
double measurement = voxelsWithRegionValue / (volume - voxelsWithValueZero);
if (measurement > 0.3)
{
return 1;
}
return 0;
}
template < typename TPixel, unsigned int VImageDimension >
int mitk::CostFunctionBase<TPixel, VImageDimension>::SidesAreNotTooLong ()
{
itk::Size<3> size = m_RegionPair.first.GetSize();
if (size[0] < size[1] + size[2] + 1 && size[1] < size[0] + size[2] + 1 && size[2] < size[0] + size[1] + 1)
{
return 1;
}
return 0;
}
template < typename TPixel, unsigned int VImageDimension >
int mitk::CostFunctionBase<TPixel, VImageDimension>::COMLiesWithinParcel()
{
std::pair<RegionType, int> chosenRegion = m_RegionPair;
typedef itk::Image< int, VImageDimension > IntegerImageType;
itk::ImageRegionIterator<IntegerImageType> it_region(m_Image, chosenRegion.first);
std::vector<double> centerOfMass;
centerOfMass = this->GetCenterOfMass();
typename IntegerImageType::IndexType indexCenterOfMass;
indexCenterOfMass.SetElement(0, centerOfMass[0] + 0.5);
indexCenterOfMass.SetElement(1, centerOfMass[1] + 0.5);
indexCenterOfMass.SetElement(2, centerOfMass[2] + 0.5);
it_region.SetIndex(indexCenterOfMass);
if (it_region.Value() == chosenRegion.second || it_region.Value() == 0)
{
return 1;
}
return 0;
}
template < typename TPixel, unsigned int VImageDimension >
int mitk::CostFunctionBase<TPixel, VImageDimension>::CalculateCost()
{
int costFunctionValue(0);
std::vector<int> costVector;
costVector.push_back(this->RegionIsFullEnough());
costVector.push_back(this->SidesAreNotTooLong());
costVector.push_back(this->COMLiesWithinParcel());
m_weight.clear();
m_weight.push_back(1); //weight for RegionIsFullEnough
m_weight.push_back(1); //weight for SidesAreNotTooLong
m_weight.push_back(0); //weight for COMLiesWithinParcel
//Vector multiplication
for (std::size_t i = 0; i < costVector.size(); i++)
{
costFunctionValue += costVector[i]*m_weight[i];
}
return costFunctionValue;
}
template <typename TPixel, unsigned int VImageDimension>
std::vector<double> mitk::CostFunctionBase<TPixel, VImageDimension>::GetCenterOfMass()
{
//Count all tagged voxels in this region
itk::ImageRegionIterator<ImageType> it_region(m_Image, m_RegionPair.first);
typedef itk::Image< TPixel, VImageDimension > ImageType;
int currentSizeOfRegion (0);
std::vector<typename ImageType::IndexType> indexVoxel;
std::vector<double> centerOfMass;
double xValue(0);
double yValue(0);
double zValue(0);
for (it_region.GoToBegin(); !it_region.IsAtEnd(); ++it_region)
{
if(it_region.Value() == m_RegionPair.second)
{
indexVoxel.push_back(it_region.GetIndex());
currentSizeOfRegion++;
}
}
xValue = 0;
yValue = 0;
zValue = 0;
for (int i = 0; i < currentSizeOfRegion; i++)
{
xValue += indexVoxel[i][0];
yValue += indexVoxel[i][1];
zValue += indexVoxel[i][2];
}
centerOfMass.push_back(xValue/currentSizeOfRegion);
centerOfMass.push_back(yValue/currentSizeOfRegion);
centerOfMass.push_back(zValue/currentSizeOfRegion);
return centerOfMass;
}
template <typename TPixel, unsigned int VImageDimension>
int mitk::CostFunctionBase<TPixel, VImageDimension>::MaximalValue()
{
int maximalValue(0);
for (std::size_t i = 0; i < m_weight.size(); i++)
{
maximalValue += m_weight[i];
}
return maximalValue;
}
diff --git a/Modules/Connectomics/Algorithms/BrainParcellation/mitkCostFunctionBase.h b/Modules/Connectomics/Algorithms/BrainParcellation/mitkCostFunctionBase.h
index 3e66301..40f6282 100644
--- a/Modules/Connectomics/Algorithms/BrainParcellation/mitkCostFunctionBase.h
+++ b/Modules/Connectomics/Algorithms/BrainParcellation/mitkCostFunctionBase.h
@@ -1,73 +1,73 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkCostFunctionBase_h
#define mitkCostFunctionBase_h
//Which one do we really need?
//#include <berryISelectionListener.h>
#include <itkImage.h>
#include <vector>
#include "mitkCommon.h"
#include "MitkConnectomicsExports.h"
//To use pair
#include <utility>
namespace mitk
{
template <typename TPixel, unsigned int VImageDimension>
class CostFunctionBase
{
public:
typedef itk::ImageRegion<3> RegionType;
typedef itk::Image< TPixel, VImageDimension > ImageType;
//Set Functions
void SetImage(itk::Image<TPixel, VImageDimension> *);
void SetRegion(std::pair<RegionType, int>);
//Main Function
/** \brief Checks if the functions RegionIsFullEnough, SidesAreNotTooLong and COMLiesWithinParcel all return value 1*/
int CalculateCost();
/** \brief Calculates the maximal possible value of the cost function*/
int MaximalValue();
private:
ImageType * m_Image;
std::pair<RegionType, int> m_RegionPair;
//Functions to calculate cost
/** \brief Checks if the parcel fills out the region it lies within quit well
* This is to get a convex structure.
*/
int RegionIsFullEnough ();
/** \brief Checks if the length of one direction is much longer than the length of the other two directions
* So we don't get parcels which just grow in one direction and look like a line.
*/
int SidesAreNotTooLong ();
/** \brief Checks if the center of mass of a parcel lies within the parcel
* This is to avoid U-shaped parcels.
*/
int COMLiesWithinParcel();
/** \brief Gives back the center of mass of a parcel as a vector*/
std::vector<double> GetCenterOfMass();
std::vector<int> m_weight;
};
}
#include "mitkCostFunctionBase.cpp"
#endif /* mitkCostFunctionBase_h */
\ No newline at end of file
diff --git a/Modules/Connectomics/Algorithms/BrainParcellation/mitkRandomParcellationGenerator.cpp b/Modules/Connectomics/Algorithms/BrainParcellation/mitkRandomParcellationGenerator.cpp
index 9310b26..3bd7b87 100644
--- a/Modules/Connectomics/Algorithms/BrainParcellation/mitkRandomParcellationGenerator.cpp
+++ b/Modules/Connectomics/Algorithms/BrainParcellation/mitkRandomParcellationGenerator.cpp
@@ -1,1189 +1,1189 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkRandomParcellationGenerator.h>
//To sort
#include <algorithm>
//To use sqrt
#include <cmath>
//Itk Iterators
#include <itkNeighborhoodIterator.h>
#include <itkImageRegionIterator.h>
//for the use of abs()
#include <cstdlib>
template <typename TPixel, unsigned int VImageDimension>
mitk::RandomParcellationGenerator<TPixel, VImageDimension>::RandomParcellationGenerator()
: m_RandGen(ItkRngType::New())
{
}
//Definition of the Set-Functions
template <typename TPixel, unsigned int VImageDimension>
void mitk::RandomParcellationGenerator<TPixel, VImageDimension>::SetImage(itk::Image<TPixel, VImageDimension> * image)
{
m_Image = image;
}
template <typename TPixel, unsigned int VImageDimension>
void mitk::RandomParcellationGenerator<TPixel, VImageDimension>::SetNumberNodes(int numberNodes)
{
m_NumberNodes = numberNodes;
}
template <typename TPixel, unsigned int VImageDimension>
void mitk::RandomParcellationGenerator<TPixel, VImageDimension>::SetVariablesForMerging (int givenSizeOfSmallestRegion, int desiredNumberOfParcels, int givenSizeOfSmallestRegionBeginning)
{
m_GivenSizeOfSmallestRegion = givenSizeOfSmallestRegion;
m_DesiredNumberOfParcels = desiredNumberOfParcels;
m_GivenSizeOfSmallestRegionBeginning = givenSizeOfSmallestRegionBeginning;
}
template <typename TPixel, unsigned int VImageDimension>
void mitk::RandomParcellationGenerator<TPixel, VImageDimension>::SetBoolsForMerging(bool mergingWithNumberParcels, bool mergingWithSmallestParcel, bool justMergeSmallParcels)
{
m_MergingWithNumberParcels = mergingWithNumberParcels;
m_MergingWithSmallestParcel = mergingWithSmallestParcel;
m_JustMergeSmallParcels = justMergeSmallParcels;
}
//Definition of other functions
//Calculates the Center of mass (COM) and m_SizeOfRegions
template <typename TPixel, unsigned int VImageDimension>
std::vector<double> mitk::RandomParcellationGenerator<TPixel, VImageDimension>::GetCenterOfMass( itk::ImageRegionIterator<ImageType> it_region, int valueOfRegion, bool getSizeOfRegions)
{
//Counts all tagged voxels in this region
typedef itk::Image< TPixel, VImageDimension > ImageType;
int currentSizeOfRegion (0);
std::vector<typename ImageType::IndexType> indexVoxel;
std::vector<double> centerOfMass;
double xValue(0);
double yValue(0);
double zValue(0);
for (it_region.GoToBegin(); !it_region.IsAtEnd(); ++it_region)
{
if(it_region.Value() == valueOfRegion)
{
indexVoxel.push_back(it_region.GetIndex());
currentSizeOfRegion++;
}
}
if (getSizeOfRegions == true)
{
m_SizeOfRegions.push_back(currentSizeOfRegion);
}
xValue = 0;
yValue = 0;
zValue = 0;
for (int i = 0; i < currentSizeOfRegion; i++)
{
xValue += indexVoxel[i][0];
yValue += indexVoxel[i][1];
zValue += indexVoxel[i][2];
}
centerOfMass.push_back(xValue/currentSizeOfRegion);
centerOfMass.push_back(yValue/currentSizeOfRegion);
centerOfMass.push_back(zValue/currentSizeOfRegion);
return centerOfMass;
}
template <typename TPixel, unsigned int VImageDimension>
double mitk::RandomParcellationGenerator<TPixel, VImageDimension>::GetDistance( std::vector<double> centerOfMass, typename itk::Image< TPixel, VImageDimension >::IndexType indexNewVoxel)
{
double distancetemp(0);
for (int i = 0; i < 3; i++)
{
distancetemp += (centerOfMass[i] - indexNewVoxel[i])*(centerOfMass[i] - indexNewVoxel[i]);
}
return sqrt(distancetemp);
}
template <typename TPixel, unsigned int VImageDimension>
double mitk::RandomParcellationGenerator<TPixel, VImageDimension>::GetDistanceVector( std::vector<double> centerOfMass, std::vector<double> indexNewVoxel)
{
double distancetemp(0);
for (int i = 0; i < 3; i++)
{
distancetemp += (centerOfMass[i] - indexNewVoxel[i])*(centerOfMass[i] - indexNewVoxel[i]);
}
return sqrt(distancetemp);
}
template < typename TPixel, unsigned int VImageDimension >
int mitk::RandomParcellationGenerator<TPixel, VImageDimension>::SmallestValue (std::vector<int> distance)
{
int distancemin;
distancemin = distance[0];
for (std::size_t i = 1; i < distance.size(); i++)
{
if (distance[i] < distancemin)
{
distancemin = distance[i];
}
}
return distancemin;
}
template < typename TPixel, unsigned int VImageDimension >
double mitk::RandomParcellationGenerator<TPixel, VImageDimension>::SmallestValue (std::vector<double> distance)
{
double distancemin;
distancemin = distance[0];
for (std::size_t i = 1; i < distance.size(); i++)
{
if (distance[i] < distancemin)
{
distancemin = distance[i];
}
}
return distancemin;
}
template < typename TPixel, unsigned int VImageDimension >
void mitk::RandomParcellationGenerator<TPixel, VImageDimension>::SetAppropriateValues()
{
typedef itk::Image< TPixel, VImageDimension > TemplateImageType;
itk::ImageRegionIterator<TemplateImageType> it_image(m_Image, m_Image->GetLargestPossibleRegion());
TPixel minimumValue, maximumValue;
it_image.GoToBegin();
maximumValue = minimumValue = it_image.Value();
for(it_image.GoToBegin(); !it_image.IsAtEnd(); ++it_image)
{
if ( it_image.Value() < minimumValue )
{
minimumValue = it_image.Value();
}
else
{
if ( it_image.Value() > maximumValue )
{
maximumValue = it_image.Value();
}
}
}
int range = int ( maximumValue - minimumValue ); //needs to be castable to int
int offset = int ( minimumValue );
if ( range < 0 ) //error
{
return;
}
std::vector< std::size_t > histogram;
histogram.resize( range + 1, 0 );
for(it_image.GoToBegin(); !it_image.IsAtEnd(); ++it_image)
{
histogram[ int ( it_image.Value() ) - offset ] += 1;
}
int gapCounter = 0; //this variable will be used to count the empty labels
//stores how much has to be subtracted from the image to remove gaps
std::vector< TPixel > subtractionStorage;
subtractionStorage.resize( range + 1, 0 );
for( int index = 0; index <= range; index++ )
{
if( histogram[ index ] == 0 )
{
gapCounter++; //if the label is empty, increase gapCounter
}
else
{
subtractionStorage[ index ] = TPixel ( gapCounter );
}
}
//remove gaps from label image
for(it_image.GoToBegin(); !it_image.IsAtEnd(); ++it_image)
{
it_image.Value() = it_image.Value() - subtractionStorage[ int ( it_image.Value() ) ];
}
}
template < typename TPixel, unsigned int VImageDimension >
typename itk::Image< TPixel, VImageDimension >::RegionType mitk::RandomParcellationGenerator<TPixel, VImageDimension>::ExtendedRegion(typename itk::Image< TPixel, VImageDimension >::RegionType chosenRegion, typename ImageType::IndexType indexChosenVoxel)
{
itk::Size<3> size = chosenRegion.GetSize();
itk::Index<3> start = chosenRegion.GetIndex();
std::vector<int> greatestValues;
std::vector<int> smallestValues;
for(int i = 0; i < 3; i++)
{
greatestValues.push_back(start[i] + size[i]);
smallestValues.push_back(start[i]);
}
for(int i = 0; i < 3; i++)
{
if (indexChosenVoxel[i] == greatestValues[i])
{
size[i] += 1;
}
if (indexChosenVoxel[i] == smallestValues[i] - 1)
{
start[i] -= 1;
size[i] += 1;
}
}
chosenRegion.SetSize(size);
chosenRegion.SetIndex(start);
return chosenRegion;
}
template < typename TPixel, unsigned int VImageDimension >
typename itk::Image< TPixel, VImageDimension >::RegionType mitk::RandomParcellationGenerator<TPixel, VImageDimension>::ExtendedRegionNotNeighbor(typename itk::Image< TPixel, VImageDimension >::RegionType chosenRegion, typename itk::Image< TPixel, VImageDimension >::RegionType smallestRegion)
{
itk::Size<3> sizeChosenRegion = chosenRegion.GetSize();
itk::Index<3> startChosenRegion = chosenRegion.GetIndex();
itk::Size<3> sizeSmallestRegion = smallestRegion.GetSize();
itk::Index<3> startSmallestRegion = smallestRegion.GetIndex();
//size and start of the new merged region
itk::Size<3> size;
itk::Index<3> start;
//Calculate the size of the merged region
for (int i = 0; i < 3; i++)
{
//Overlapping (start of ChosenRegion before start of SmallestRegion)
if ((startChosenRegion[i] + (itk::IndexValueType)sizeChosenRegion[i] > startSmallestRegion[i]) &&
(startChosenRegion[i] <= startSmallestRegion[i]))
{
//Not integrated
if (startSmallestRegion[i] + sizeSmallestRegion[i] > startChosenRegion[i] + sizeChosenRegion[i])
{
size[i] = abs(startSmallestRegion[i] - startChosenRegion[i]) + sizeSmallestRegion[i];
}
//Integrated
else
{
size[i] = std::max(sizeChosenRegion[i], sizeSmallestRegion[i]);
}
}
//Overlapping (start of SmallestRegion before start of ChosenRegion)
if ((startSmallestRegion[i] + (itk::IndexValueType)sizeSmallestRegion[i] > startChosenRegion[i]) &&
(startChosenRegion[i] >= startSmallestRegion[i]))
{
//Not integrated
if (startChosenRegion[i] + sizeChosenRegion[i] > startSmallestRegion[i] + sizeSmallestRegion[i])
{
size[i] = abs(startSmallestRegion[i] - startChosenRegion[i]) + sizeChosenRegion[i];
}
//Integrated
else
{
size[i] = std::max(sizeChosenRegion[i], sizeSmallestRegion[i]);
}
}
//No overlapping (right next to each other)
if ((startChosenRegion[i] + (itk::IndexValueType)sizeChosenRegion[i] == startSmallestRegion[i]) ||
(startSmallestRegion[i] + (itk::IndexValueType)sizeSmallestRegion[i] == startChosenRegion[i]))
{
size[i] = sizeChosenRegion[i] + sizeSmallestRegion[i];
}
//Isolated
if ((startChosenRegion[i] + (itk::IndexValueType)sizeChosenRegion[i] < startSmallestRegion[i]) ||
(startSmallestRegion[i] + (itk::IndexValueType)sizeSmallestRegion[i] < startChosenRegion[i]))
{
if(startChosenRegion[i] + (itk::IndexValueType)sizeChosenRegion[i] < startSmallestRegion[i])
{
size[i] = abs(startChosenRegion[i] - startSmallestRegion[i]) +1;
}
if(startSmallestRegion[i] + (itk::IndexValueType)sizeSmallestRegion[i] < startChosenRegion[i])
{
size[i] = abs(startChosenRegion[i] - startSmallestRegion[i]) + sizeChosenRegion[i];
}
}
}
//Calculate the start point of the new region, choose the smallest value respectively
for (int i = 0; i < 3; i++)
{
start[i] = std::min(startChosenRegion[i], startSmallestRegion[i]);
}
chosenRegion.SetSize(size);
chosenRegion.SetIndex(start);
return chosenRegion;
}
//checks if a number is already an element of the vector
template < typename TPixel, unsigned int VImageDimension >
bool mitk::RandomParcellationGenerator<TPixel, VImageDimension>::IsUnique (int number, std::vector<int> vec)
{
for (std::size_t i = 0; i < vec.size(); i++)
{
if (vec[i] == number)
{
return false;
}
}
return true;
}
template < typename TPixel, unsigned int VImageDimension >
void mitk::RandomParcellationGenerator<TPixel, VImageDimension>::GetRandomSeedVoxels()
{
typedef itk::Image< TPixel, VImageDimension > ImageType;
RegionVoxelCounter<int, 3> counter;
counter.SetImage(m_Image);
counter.SetRegion(m_Image->GetLargestPossibleRegion());
int numberVoxels = counter.VoxelWithValue(1);
//Create vector with unique numbers
std::vector<int> randomvector;
int randomnumber;
//for-loop to get (m_NumberNodes) randomly chosen seed-points
for (int j = 0; j < m_NumberNodes; j++)
{
//m_RandGen->GetIntegerVariate() is the same as rand() but with an extended range
randomnumber = m_RandGen->GetIntegerVariate() % numberVoxels +1;
//Bool-function (IsUnique)
if (this->IsUnique(randomnumber, randomvector))
{
randomvector.push_back(randomnumber);
}
else
{
j--;
}
}
//sorts the numbers in randomvector according to their size
sort (randomvector.begin(), randomvector.end());
//assign new values to the chosen voxels and build the regions
itk::Size<3> originalSize;
originalSize.Fill(1);
itk::Index<3> originalStart;
typename ImageType::IndexType currentIndex;
int valueCounter(0);
int regionNumber(0);
typename ImageType::RegionType tempRegion;
itk::ImageRegionIterator<ImageType> it_image(m_Image, m_Image->GetLargestPossibleRegion());
for (it_image.GoToBegin(); !it_image.IsAtEnd() && regionNumber < m_NumberNodes; ++it_image)
{
if (it_image.Value() >= 1)
{
valueCounter++;
if (valueCounter == randomvector[regionNumber])
{
it_image.Value() = regionNumber+3;
//Build the Regions
currentIndex = it_image.GetIndex();
originalStart[0] = currentIndex[0];
originalStart[1] = currentIndex[1];
originalStart[2] = currentIndex[2];
tempRegion.SetSize(originalSize);
tempRegion.SetIndex(originalStart);
std::pair<RegionType, int> tempPair (tempRegion, regionNumber+3);
m_OddRegions.push_back(tempPair);
regionNumber++;
}
}
}
}
template < typename TPixel, unsigned int VImageDimension >
void mitk::RandomParcellationGenerator<TPixel, VImageDimension>::ParcelGrowthOverFaces()
{
typedef itk::Image< int, VImageDimension > IntegerImageType;
typedef itk::NeighborhoodIterator< IntegerImageType > NeighborhoodIteratorType;
typename NeighborhoodIteratorType::RadiusType radius;
radius.Fill(1);
std::pair<RegionType, int> chosenRegion;
int thisRegion;
typename IntegerImageType::IndexType indexChosenVoxel;
std::vector<double> distance;
std::vector<int> possibleNeighbor;
int thisNeighbor;
std::vector<double> centerOfMass;
typename IntegerImageType::IndexType indexNewVoxel;
std::vector<typename IntegerImageType::IndexType> indexNewVoxelVector;
int numberAvailableVoxels(0);
bool validVoxelNotYetFound;
bool checkRegionsOfOddSize(true);
std::vector<std::pair<RegionType,int> > * possibleRegions = nullptr;
int costValue;
//As long as there are still non invalid regions (of even or odd size) add a voxel to them in each iteration step
while(m_OddRegions.size() != 0 || m_EvenRegions.size() != 0)
{
//When we change from odd to even or vice versa
if (m_OddRegions.size() == 0)
{
checkRegionsOfOddSize = false;
possibleRegions = &m_EvenRegions;
}
if (m_EvenRegions.size() == 0)
{
checkRegionsOfOddSize = true;
possibleRegions = &m_OddRegions;
}
//All our smallest regions are contained in possibleRegions, choose one randomly and check whether we can expand it
thisRegion = m_RandGen->GetIntegerVariate() % possibleRegions->size();
chosenRegion = (*possibleRegions)[thisRegion];
//Calculate Center of mass (COM)
centerOfMass.clear();
itk::ImageRegionIterator<IntegerImageType> it_region(m_Image, chosenRegion.first);
centerOfMass = this->GetCenterOfMass(it_region, chosenRegion.second, false);
numberAvailableVoxels = 0;
NeighborhoodIteratorType it_neighborhood(radius, m_Image, chosenRegion.first);
//Check if there are any valid voxels which we can add to our chosen region
for (it_neighborhood.GoToBegin(); !it_neighborhood.IsAtEnd(); ++it_neighborhood)
{
if (it_neighborhood.GetCenterPixel() == chosenRegion.second)
{
//Now the Neighborhood of a Parcel-Voxel is available
//Check if there is a valid voxel
for (int k = 0; k <27; k++)
{
if (it_neighborhood.GetPixel(k) == 1 && (k == 4 || k == 10 || k == 12 || k == 14 || k == 16 || k == 22) )
{
// Calculate the distance btw. the centerOfMass and the NewVoxel
indexNewVoxel = it_neighborhood.GetIndex(k);
indexNewVoxelVector.push_back(indexNewVoxel);
distance.push_back(this->GetDistance(centerOfMass, indexNewVoxel));
numberAvailableVoxels++;
}
}
}
}
if (numberAvailableVoxels > 0)
{
validVoxelNotYetFound = true;
while (validVoxelNotYetFound && distance.size() > 0)
{
possibleNeighbor.clear();
//Find the possible neighbors with the smallest distance to the COM of the region
for (std::size_t i = 0; i < distance.size(); i++)
{
if (distance[i] == this->SmallestValue(distance))
{
possibleNeighbor.push_back(i);
}
}
//Choose a random voxel and check if it is valid
//Get the index of this voxel
thisNeighbor = m_RandGen->GetIntegerVariate() % possibleNeighbor.size();
indexChosenVoxel = indexNewVoxelVector[possibleNeighbor[thisNeighbor]];
//Check if we now have to expand the region due to the possible new voxel
std::pair<RegionType, int> chosenRegionChanged;
chosenRegionChanged.first = this->ExtendedRegion(chosenRegion.first, indexChosenVoxel);
chosenRegionChanged.second = chosenRegion.second;
//Constraints
CostFunctionBase<TPixel, VImageDimension> costCalculator;
costCalculator.SetImage(m_Image);
costCalculator.SetRegion(chosenRegionChanged);
costValue = costCalculator.CalculateCost();
if(costValue >= costCalculator.MaximalValue())//Constraints are fulfilled
{
validVoxelNotYetFound = false;
chosenRegion = chosenRegionChanged;
}
else //Constraints are not fulfilled
{
validVoxelNotYetFound = true; //So we are still in the while loop
distance.erase(distance.begin() + possibleNeighbor[thisNeighbor]);
indexNewVoxelVector.erase(indexNewVoxelVector.begin() + possibleNeighbor[thisNeighbor]);
if (distance.size() == 0)
{
if (checkRegionsOfOddSize == true)
{
m_InvalidRegions.push_back(chosenRegion);
m_OddRegions.erase(m_OddRegions.begin() + thisRegion);
}
else
{
m_InvalidRegions.push_back(chosenRegion);
m_EvenRegions.erase(m_EvenRegions.begin() + thisRegion);
}
}
}
}
if (distance.size() > 0)
{
//Change the value of the new voxel
itk::ImageRegionIterator<IntegerImageType> it_region(m_Image, m_Image->GetLargestPossibleRegion());
it_region.SetIndex(indexChosenVoxel);
it_region.Value() = chosenRegion.second;
//Change from even to odd or vice versa
if (checkRegionsOfOddSize == true)
{
m_EvenRegions.push_back(chosenRegion);
m_OddRegions.erase(m_OddRegions.begin() + thisRegion);
}
else
{
m_OddRegions.push_back(chosenRegion);
m_EvenRegions.erase(m_EvenRegions.begin() + thisRegion);
}
distance.clear();
indexNewVoxelVector.clear();
}
}
else
{
//The region can't be extended, put it into the m_InvalidRegions vector
m_InvalidRegions.push_back((*possibleRegions)[thisRegion]);
possibleRegions->erase(possibleRegions->begin() + thisRegion);
}
}
}
template < typename TPixel, unsigned int VImageDimension >
void mitk::RandomParcellationGenerator<TPixel, VImageDimension>::FillOverEdgeOrVertex()
{
typedef itk::Image< int, VImageDimension > IntegerImageType;
typedef itk::NeighborhoodIterator< IntegerImageType > NeighborhoodIteratorType;
typename NeighborhoodIteratorType::RadiusType radius;
radius.Fill(1);
NeighborhoodIteratorType it_neighborhood(radius, m_Image, m_Image->GetLargestPossibleRegion());
std::vector<int> valueOfRegions;
std::vector<int> sizeOfPossibleRegions;
std::vector<int> valueOfPossibleRegions;
std::vector<int> indexInvalidRegions;
std::vector<int> indexOfPossibleInvalidRegions;
std::vector<double> distance;
std::vector<int> possibleNeighbor;
typename IntegerImageType::IndexType indexNewVoxel;
std::vector<double> centerOfMass;
int thisNeighbor;
std::pair<RegionType, int> chosenRegion;
typename IntegerImageType::IndexType indexChosenVoxel;
RegionVoxelCounter<int, VImageDimension> wholeImageCounter;
wholeImageCounter.SetImage(m_Image);
wholeImageCounter.SetRegion(m_Image->GetLargestPossibleRegion());
int voxelsWithValueOne = wholeImageCounter.VoxelWithValue(1);
if (voxelsWithValueOne > 0)
{
std::stringstream message;
message << "Edge " << voxelsWithValueOne << endl;
MITK_DEBUG << message.str();
for (it_neighborhood.GoToBegin(); !it_neighborhood.IsAtEnd(); ++it_neighborhood)
{
if (it_neighborhood.GetCenterPixel() == 1) //Found Voxel with Value 1
{
m_SizeOfRegions.clear();
distance.clear();
valueOfRegions.clear();
possibleNeighbor.clear();
indexInvalidRegions.clear();
indexOfPossibleInvalidRegions.clear();
indexNewVoxel = it_neighborhood.GetIndex();
//Add this voxel to a region
//first check if it shares an edge or vertex with (at least) one region
for (int k = 0; k <27; k++)
{
if (it_neighborhood.GetPixel(k) > 2)
{
for (std::size_t i = 0; i < m_InvalidRegions.size(); i++)
{
if (it_neighborhood.GetPixel(k) == m_InvalidRegions[i].second)
{
valueOfRegions.push_back(m_InvalidRegions[i].second);
itk::ImageRegionIterator<IntegerImageType> it_region(m_Image, m_InvalidRegions[i].first);
//Gets center of mass and the m_SizeOfRegions
centerOfMass = this->GetCenterOfMass(it_region, m_InvalidRegions[i].second, true);
distance.push_back(this->GetDistance(centerOfMass, indexNewVoxel));
indexInvalidRegions.push_back(i);
break;
}
}
}
}
//Minimal distance
if (distance.size() != 0)
{
for (std::size_t i = 0; i < distance.size(); i++)
{
if (distance[i] == this->SmallestValue(distance))
{
possibleNeighbor.push_back(i);
}
}
distance.clear();
//Check the Size of the Regions and get the smallest one!
//First get the regions with the same distance to COM
for (std::size_t i = 0; i < possibleNeighbor.size(); i++)
{
sizeOfPossibleRegions.push_back(m_SizeOfRegions[possibleNeighbor[i]]);
valueOfPossibleRegions.push_back(valueOfRegions[possibleNeighbor[i]]);
indexOfPossibleInvalidRegions.push_back(indexInvalidRegions[possibleNeighbor[i]]);
}
possibleNeighbor.clear();
indexInvalidRegions.clear();
for (std::size_t i = 0; i < sizeOfPossibleRegions.size(); i++)
{
if (sizeOfPossibleRegions[i] == this->SmallestValue(sizeOfPossibleRegions))
{
possibleNeighbor.push_back(i);
}
}
sizeOfPossibleRegions.clear();
thisNeighbor = m_RandGen->GetIntegerVariate() % possibleNeighbor.size();
it_neighborhood.SetCenterPixel(valueOfPossibleRegions[thisNeighbor]);
valueOfPossibleRegions.clear();
//region extansion if necessary
//first we need to get the right region
chosenRegion = m_InvalidRegions[indexOfPossibleInvalidRegions[thisNeighbor]];
indexChosenVoxel = it_neighborhood.GetIndex();
m_InvalidRegions[indexOfPossibleInvalidRegions[thisNeighbor]].first = this->ExtendedRegion(chosenRegion.first, indexChosenVoxel);
indexOfPossibleInvalidRegions.clear();
}
}
}
}
}
template < typename TPixel, unsigned int VImageDimension >
void mitk::RandomParcellationGenerator<TPixel, VImageDimension>::AllocateIsolatedVoxels()
{
typedef itk::Image< int, VImageDimension > IntegerImageType;
std::vector<int> valueOfRegions;
std::vector<int> sizeOfPossibleRegions;
std::vector<int> valueOfPossibleRegions;
std::vector<int> indexInvalidRegions;
std::vector<int> indexOfPossibleInvalidRegions;
std::vector<double> distance;
std::vector<int> possibleNeighbor;
typename IntegerImageType::IndexType indexNewVoxel;
std::vector<double> centerOfMass;
int thisNeighbor;
std::pair<RegionType, int> chosenRegion;
typename IntegerImageType::IndexType indexChosenVoxel;
RegionVoxelCounter<int, VImageDimension> wholeImageCounter;
wholeImageCounter.SetImage(m_Image);
wholeImageCounter.SetRegion(m_Image->GetLargestPossibleRegion());
int voxelsWithValueOne = wholeImageCounter.VoxelWithValue(1);
if (voxelsWithValueOne > 0)
{
std::stringstream message;
message << "Isolated " << voxelsWithValueOne << endl;
MITK_DEBUG << message.str();
std::vector<std::vector<double> > comOfRegions;
m_SizeOfRegions.clear();
//Calculate all center of mass
for (std::size_t i = 0; i < m_InvalidRegions.size(); i++)
{
valueOfRegions.push_back(m_InvalidRegions[i].second);
itk::ImageRegionIterator<IntegerImageType> it_region(m_Image, m_InvalidRegions[i].first);
centerOfMass = this->GetCenterOfMass(it_region, m_InvalidRegions[i].second, true);
comOfRegions.push_back(centerOfMass);
}
itk::ImageRegionIterator<IntegerImageType> it_region(m_Image, m_Image->GetLargestPossibleRegion());
for (it_region.GoToBegin(); !it_region.IsAtEnd(); ++it_region)
{
if (it_region.Value() == 1) //Found Voxel with Value 1
{
indexNewVoxel = it_region.GetIndex();
//distance calculation
for (std::size_t j = 0; j < m_InvalidRegions.size(); j++)
{
distance.push_back(this->GetDistance(comOfRegions[j], indexNewVoxel));
indexInvalidRegions.push_back(j);
}
//Minimal distance
if (distance.size() != 0)
{
for (std::size_t i = 0; i < distance.size(); i++)
{
if (distance[i] == this->SmallestValue(distance))
{
possibleNeighbor.push_back(i);
}
}
distance.clear();
//Check the Size of the Regions and get the smallest one!
//First get the regions with the same distance to COM
for (std::size_t i = 0; i < possibleNeighbor.size(); i++)
{
sizeOfPossibleRegions.push_back(m_SizeOfRegions[possibleNeighbor[i]]);
valueOfPossibleRegions.push_back(valueOfRegions[possibleNeighbor[i]]);
indexOfPossibleInvalidRegions.push_back(indexInvalidRegions[possibleNeighbor[i]]);
}
possibleNeighbor.clear();
indexInvalidRegions.clear();
for (std::size_t i = 0; i < sizeOfPossibleRegions.size(); i++)
{
if (sizeOfPossibleRegions[i] == this->SmallestValue(sizeOfPossibleRegions))
{
possibleNeighbor.push_back(i);
}
}
sizeOfPossibleRegions.clear();
thisNeighbor = m_RandGen->GetIntegerVariate() % possibleNeighbor.size();
it_region.Value() = valueOfPossibleRegions[thisNeighbor];
valueOfPossibleRegions.clear();
possibleNeighbor.clear();
//region extansion if necessary
//first we need to get the right region
chosenRegion = m_InvalidRegions[indexOfPossibleInvalidRegions[thisNeighbor]];
indexChosenVoxel = it_region.GetIndex();
RegionType voxelRegion;
voxelRegion.SetIndex(indexChosenVoxel);
itk::Size<3> voxelSize;
voxelSize.Fill(1);
voxelRegion.SetSize(voxelSize);
m_InvalidRegions[indexOfPossibleInvalidRegions[thisNeighbor]].first = this->ExtendedRegionNotNeighbor(chosenRegion.first, voxelRegion);
indexOfPossibleInvalidRegions.clear();
}
}
}
}
}
template < typename TPixel, unsigned int VImageDimension >
int mitk::RandomParcellationGenerator<TPixel, VImageDimension>::MergeParcels()
{
typedef itk::Image< int, VImageDimension > IntegerImageType;
typedef itk::NeighborhoodIterator< IntegerImageType > NeighborhoodIteratorType;
typename NeighborhoodIteratorType::RadiusType radius;
radius.Fill(1);
//Calculate the m_SizeOfRegions
this->GetSizeOfRegions();
int sizeOfSmallestRegion = this->SmallestValue(m_SizeOfRegions);
std::vector<int> smallRegions;
std::vector<int> indexSmallRegions;
int thisIndex = 0;
int thisSmallRegion;
bool mergingStillPossible(true);
std::vector<int> smallDistances;
std::vector<double> centerOfMassPossibleRegion;
std::vector<std::vector<double> > comOfRegions;
std::vector<int> sizeSmallRegions;
std::vector<int> smallestRegions;
bool tooManyParcels(true);
int currentNumberOfParcels = m_NumberNodes;
int sizeNewParcel;
std::vector<double> costFunctionValue;
std::vector<double> smallestCostFunctionValues;
std::vector<int> valueOfPossibleRegions;
std::vector<double> distance;
std::pair<RegionType, int> chosenRegion;
std::vector<double> centerOfMass;
bool smallRegionFound(false);
bool hasNeighbors(false);
while (sizeOfSmallestRegion < m_GivenSizeOfSmallestRegion && mergingStillPossible && tooManyParcels)
{
smallRegions.clear();
sizeSmallRegions.clear();
smallestRegions.clear();
//Find all small Regions
for (std::size_t i = 0; i < m_SizeOfRegions.size(); i++)
{
if (m_SizeOfRegions[i] < m_GivenSizeOfSmallestRegion)
{
smallRegions.push_back(i);
sizeSmallRegions.push_back(m_SizeOfRegions[i]);
}
}
//Find one of the smallest regions
for (std::size_t i = 0; i < sizeSmallRegions.size(); i++)
{
if (sizeSmallRegions[i] == this->SmallestValue(sizeSmallRegions))
{
smallestRegions.push_back(smallRegions[i]);
}
}
if (smallestRegions.size() > 0 && this->SmallestValue(sizeSmallRegions) < m_GivenSizeOfSmallestRegionBeginning)
{
thisSmallRegion = rand() % smallestRegions.size();
//Choose a random small region
//First check if it has direct neighbors
NeighborhoodIteratorType it_neighborhood(radius, m_Image, m_InvalidRegions[smallestRegions[thisSmallRegion]].first);
valueOfPossibleRegions.clear();
smallRegionFound = false;
hasNeighbors = false;
for (it_neighborhood.GoToBegin(); !it_neighborhood.IsAtEnd(); ++it_neighborhood)
{
for (int k = 0; k <27; k++)
{
if ((k == 4 || k == 10 || k == 12 || k == 14 || k == 16 || k == 22) &&//over faces
it_neighborhood.GetPixel(k) > 2 //found value which belongs to a region != the chosen region
&& it_neighborhood.GetPixel(k) != m_InvalidRegions[smallestRegions[thisSmallRegion]].second)
{
hasNeighbors = true;
for (std::size_t i = 0; i < smallRegions.size(); i++)
{
if (it_neighborhood.GetPixel(k) == m_InvalidRegions[smallRegions[i]].second) //The value belongs to a small region
{
valueOfPossibleRegions.push_back(it_neighborhood.GetPixel(k));
smallRegionFound = true;
break;
}
}
}
}
}
if (hasNeighbors == true)
{
if (smallRegionFound == true)//the region has direct neighbors
{
//valueOfPossibleRegions may contain some values, that are the same. Erase the duplicates and sort the vector.
std::sort(valueOfPossibleRegions.begin(), valueOfPossibleRegions.end());
valueOfPossibleRegions.erase(std::unique(valueOfPossibleRegions.begin(), valueOfPossibleRegions.end()), valueOfPossibleRegions.end());
indexSmallRegions.clear();
//Get the values of the possible regions!
for (std::size_t i = 0; i < valueOfPossibleRegions.size() ; i++)
{
for (std::size_t j = 0; j < m_InvalidRegions.size(); j++)
{
if (valueOfPossibleRegions[i] == m_InvalidRegions[j].second)
{
indexSmallRegions.push_back(j);
break;
}
}
}
//take the region with the greatest value of the cost function
//the cost function depends on the distance (btw the 2 COMs) and the size of the merged parcel
//First get all the distances
itk::ImageRegionIterator<IntegerImageType> it_regionSmallest(m_Image, m_InvalidRegions[smallestRegions[thisSmallRegion]].first);
std::vector<double> centerOfMassCurrentRegion = this->GetCenterOfMass(it_regionSmallest, m_InvalidRegions[smallestRegions[thisSmallRegion]].second, false);
distance.clear();
for (std::size_t i = 0; i < indexSmallRegions.size(); i++)
{
itk::ImageRegionIterator<IntegerImageType> it_region(m_Image, m_InvalidRegions[indexSmallRegions[i]].first);
centerOfMassPossibleRegion = this->GetCenterOfMass(it_region, m_InvalidRegions[indexSmallRegions[i]].second, false);
distance.push_back(this->GetDistanceVector(centerOfMassCurrentRegion, centerOfMassPossibleRegion));
}
smallDistances.clear();
if (m_MergingWithSmallestParcel && m_JustMergeSmallParcels)
{
//If there are small Regions with equal distance btw the COMs choose a random one
for (std::size_t i = 0; i < distance.size(); i++)
{
if (distance[i] == this->SmallestValue(distance))
{
smallDistances.push_back(indexSmallRegions[i]);
}
}
thisIndex = smallDistances[rand() % smallDistances.size()];
}
//Calculate the cost function values
if (m_MergingWithNumberParcels || (m_MergingWithSmallestParcel && !m_JustMergeSmallParcels))
{
costFunctionValue.clear();
for (std::size_t i = 0; i < indexSmallRegions.size(); i++)
{
if (distance[i] == 0)
{
distance[i] = 0.01;
}
sizeNewParcel = (m_SizeOfRegions[smallestRegions[thisSmallRegion]] + m_SizeOfRegions[indexSmallRegions[i]]);
costFunctionValue.push_back(-(1.0/distance[i]) - (1.0/sizeNewParcel)); //1, 2 or 3 at sizeNewParcel
}
smallestCostFunctionValues.clear();
for (std::size_t i = 0; i < indexSmallRegions.size(); i++)
{
if (costFunctionValue[i] == this->SmallestValue(costFunctionValue))
{
smallestCostFunctionValues.push_back(indexSmallRegions[i]);
}
}
thisIndex = smallestCostFunctionValues[rand() % smallestCostFunctionValues.size()];
}
//m_InvalidRegions[thisIndex].first is the region we want to merge with our current one
//Colour the small parcel like the found one
for (it_regionSmallest.GoToBegin(); !it_regionSmallest.IsAtEnd(); ++it_regionSmallest)
{
if (it_regionSmallest.Value() == m_InvalidRegions[smallestRegions[thisSmallRegion]].second)
{
it_regionSmallest.Value() = m_InvalidRegions[thisIndex].second;
}
}
//Expand the region of the new parcel if necessary!
chosenRegion = m_InvalidRegions[thisIndex];
chosenRegion.first = this->ExtendedRegionNotNeighbor(chosenRegion.first, m_InvalidRegions[smallestRegions[thisSmallRegion]].first);
m_InvalidRegions[thisIndex] = chosenRegion;
//Erase the smallest Region from m_InvalidRegions
m_InvalidRegions.erase(m_InvalidRegions.begin() + smallestRegions[thisSmallRegion]);
currentNumberOfParcels--;
if (currentNumberOfParcels <= m_DesiredNumberOfParcels)
{
tooManyParcels = false;
}
//m_SizeOfRegions changed, get the new one
this->GetSizeOfRegions();
}
else //No merging possible, erase this small region from m_InvalidRegions and from m_SizeOfRegions
{
m_InvalidRegions.erase(m_InvalidRegions.begin() + smallestRegions[thisSmallRegion]);
currentNumberOfParcels--;
m_SizeOfFinishedRegions.push_back(m_SizeOfRegions[smallestRegions[thisSmallRegion]]);
m_SizeOfRegions.erase(m_SizeOfRegions.begin() + smallestRegions[thisSmallRegion]);
if (currentNumberOfParcels <= m_DesiredNumberOfParcels)
{
tooManyParcels = false;
}
}
}
else //There are no 6-connected neighborhood-regions. Try to merge this small region to a near region (according to the Center of Mass)
{
comOfRegions.clear();
//Calculate the center of mass of all small regions
for (std::size_t i = 0; i < smallRegions.size(); i++)
{
itk::ImageRegionIterator<IntegerImageType> it_region(m_Image, m_InvalidRegions[smallRegions[i]].first);
centerOfMass = this->GetCenterOfMass(it_region, m_InvalidRegions[smallRegions[i]].second, false);
comOfRegions.push_back(centerOfMass);
}
//Calculate the distance between the center of mass of our small region and all other regions
itk::ImageRegionIterator<IntegerImageType> it_regionSmallest(m_Image, m_InvalidRegions[smallestRegions[thisSmallRegion]].first);
std::vector<double> centerOfMassCurrentRegion = this->GetCenterOfMass(it_regionSmallest, m_InvalidRegions[smallestRegions[thisSmallRegion]].second, false);
distance.clear();
for (std::size_t i = 0; i < smallRegions.size(); i++)
{
itk::ImageRegionIterator<IntegerImageType> it_region(m_Image, m_InvalidRegions[smallRegions[i]].first);
centerOfMassPossibleRegion = this->GetCenterOfMass(it_region, m_InvalidRegions[smallRegions[i]].second, false);
distance.push_back(this->GetDistanceVector(centerOfMassCurrentRegion, centerOfMassPossibleRegion));
}
smallDistances.clear();
std::vector<double> distanceWithoutZero = distance;
for (std::size_t i = 0; i < distanceWithoutZero.size(); i++)
{
if (distanceWithoutZero[i] == 0)
{
distanceWithoutZero.erase(distanceWithoutZero.begin() + i); //Our smallestRegion is calculated too, erase the zero entry
break;
}
}
if (distanceWithoutZero.size() > 0)
{
//If there are small Regions with equal distance btw the COM's choose a random one
for (std::size_t i = 0; i < distance.size(); i++)
{
if (distance[i] == this->SmallestValue(distanceWithoutZero))
{
smallDistances.push_back(smallRegions[i]);
}
}
thisIndex = smallDistances[rand() % smallDistances.size()];
//Colour the small parcel like the found one
for (it_regionSmallest.GoToBegin(); !it_regionSmallest.IsAtEnd(); ++it_regionSmallest)
{
if (it_regionSmallest.Value() == m_InvalidRegions[smallestRegions[thisSmallRegion]].second)
{
it_regionSmallest.Value() = m_InvalidRegions[thisIndex].second;
}
}
//Expand the region of the new parcel if necessary!
chosenRegion = m_InvalidRegions[thisIndex];
chosenRegion.first = this->ExtendedRegionNotNeighbor(chosenRegion.first , m_InvalidRegions[smallestRegions[thisSmallRegion]].first);
m_InvalidRegions[thisIndex] = chosenRegion;
//Erase the smallest Region from m_InvalidRegions
m_InvalidRegions.erase(m_InvalidRegions.begin() + smallestRegions[thisSmallRegion]);
currentNumberOfParcels--;
if (currentNumberOfParcels <= m_DesiredNumberOfParcels)
{
tooManyParcels = false;
}
//m_SizeOfRegions changed, get the new one
this->GetSizeOfRegions();
}
else//No merging possible, erase this small region from m_InvalidRegions and from m_SizeOfRegions
{
m_InvalidRegions.erase(m_InvalidRegions.begin() + smallestRegions[thisSmallRegion]);
currentNumberOfParcels--;
m_SizeOfFinishedRegions.push_back(m_SizeOfRegions[smallestRegions[thisSmallRegion]]);
m_SizeOfRegions.erase(m_SizeOfRegions.begin() + smallestRegions[thisSmallRegion]);
if (currentNumberOfParcels <= m_DesiredNumberOfParcels)
{
tooManyParcels = false;
}
}
}
}
else //there are no parcels left to merge with
{
mergingStillPossible = false;
}
}
return (m_SizeOfFinishedRegions.size() + m_SizeOfRegions.size());
}
template < typename TPixel, unsigned int VImageDimension >
void mitk::RandomParcellationGenerator<TPixel, VImageDimension>::GetSizeOfRegions()
{
m_SizeOfRegions.clear();
RegionVoxelCounter<int, VImageDimension> voxelCounter;
voxelCounter.SetImage(m_Image);
for (std::size_t i = 0; i < m_InvalidRegions.size(); i++)
{
voxelCounter.SetRegion(m_InvalidRegions[i].first);
m_SizeOfRegions.push_back(voxelCounter.VoxelWithValue(m_InvalidRegions[i].second));
}
}
template < typename TPixel, unsigned int VImageDimension >
void mitk::RandomParcellationGenerator<TPixel, VImageDimension>::ShowSizeOfRegions()
{
RegionVoxelCounter<int, VImageDimension> voxelCounter;
voxelCounter.SetImage(m_Image);
std::stringstream message;
for (std::size_t i = 0; i < m_InvalidRegions.size(); i++)
{
voxelCounter.SetRegion(m_InvalidRegions[i].first);
m_SizeOfRegions.push_back(voxelCounter.VoxelWithValue(m_InvalidRegions[i].second));
message << voxelCounter.VoxelWithValue(m_InvalidRegions[i].second) << " , ";
}
MITK_DEBUG << message.str();
}
diff --git a/Modules/Connectomics/Algorithms/BrainParcellation/mitkRandomParcellationGenerator.h b/Modules/Connectomics/Algorithms/BrainParcellation/mitkRandomParcellationGenerator.h
index 47a5df1..5432274 100644
--- a/Modules/Connectomics/Algorithms/BrainParcellation/mitkRandomParcellationGenerator.h
+++ b/Modules/Connectomics/Algorithms/BrainParcellation/mitkRandomParcellationGenerator.h
@@ -1,132 +1,132 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkRandomParcellationGenerator_h
#define mitkRandomParcellationGenerator_h
#include<itkImage.h>
#include "mitkCommon.h"
#include "MitkConnectomicsExports.h"
// mitk
#include <mitkCostFunctionBase.h>
#include <mitkRegionVoxelCounter.h>
//Itk Iterators
#include <itkNeighborhoodIterator.h>
#include <itkImageRegionIterator.h>
#include <vector>
//To use pair
#include <utility>
#include <itkMersenneTwisterRandomVariateGenerator.h>
namespace mitk
{
template <typename TPixel, unsigned int VImageDimension>
class RandomParcellationGenerator
{
public:
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::Statistics::MersenneTwisterRandomVariateGenerator ItkRngType;
RandomParcellationGenerator();
//Set-Functions
void SetImage(itk::Image<TPixel, VImageDimension> *);
void SetNumberNodes(int inputNumberNodes);
void SetVariablesForMerging(int givenSizeOfSmallestRegion, int desiredNumberOfParcels, int givenSizeOfSmallestRegionBeginning);
void SetBoolsForMerging(bool mergingWithNumberParcels, bool mergingWithSmallestParcel, bool justMergeSmallParcels);
//Main Functions
/** \brief Sets randomly chosen seed voxels (1x1x1 regions) on the segmented image
* This is done by creating a vector with unique values, which represents the position of a voxel respectively.
* For this purpose we count all voxels with value one and choose random numbers.
*/
void GetRandomSeedVoxels();
/** \brief Add appropriate voxels of the segmented part to a region (just 6-connected neighborhood)
* A voxel is appropriate if the cost function value is high enough. Several constraints have to be fulfilled for this purpose.
*/
void ParcelGrowthOverFaces();
/** \brief Add voxels of the segmented part to an appropriate region (26-connected neighborhood)
* Checks which voxels still have value one and to which neighborhood-region each one should be added.
*/
void FillOverEdgeOrVertex();
/** \brief Add voxels of the segmented part to an appropriate region (no neighbors necessary)
* Checks which voxels still have value one and calculates the distance to all parcels.
* Finally each voxel is added to the region with the smallest distance to it.
*/
void AllocateIsolatedVoxels();
/** \brief Merge parcels according to a cost function
* Looks for the parcel with the smallest number of voxels.
* Then merges it to a neighborhood-parcel such that the cost function value is small enough.
* The new number of nodes is returned so we can show them on the GUI.
*/
int MergeParcels();
/** \brief Changes the values of the nodes, such that no gaps exist and it starts with value 1*/
void SetAppropriateValues();
/** \brief Calculates and shows the size (number of voxels) of all regions on the console*/
void ShowSizeOfRegions();
protected:
//Sub-Functions
/** \brief Gives back the center of mass and -if wanted- the size (number of voxels) of a parcel*/
std::vector<double> GetCenterOfMass( itk::ImageRegionIterator<ImageType> it_region, int valueOfRegion, bool getSizeOfRegions );
/** \brief Calculates the distance between two voxels, the position of the first one is given by an index and the position of the second one is given by a vector*/
double GetDistance( std::vector<double> centerOfMass, typename ImageType::IndexType indexNewVoxel);
/** \brief Calculates the distance between two voxels, both positions are given by vectors*/
double GetDistanceVector( std::vector<double> centerOfMass, std::vector<double> indexNewVoxel);
/** \brief Gives back the smallest value of an int-vector*/
int SmallestValue (std::vector<int> distance);
/** \brief Gives back the smallest value of a double-vector*/
double SmallestValue (std::vector<double> distance);
/** \brief Extends the region if the chosen voxel lies outside*/
typename ImageType::RegionType ExtendedRegion(typename ImageType::RegionType chosenRegion, typename ImageType::IndexType indexChosenVoxel);
/** \brief Extends the region of a parcel such that the second region lies within*/
typename ImageType::RegionType ExtendedRegionNotNeighbor(typename ImageType::RegionType chosenRegion, typename ImageType::RegionType smallestRegion);
/** \brief Checks if a number is an element of the vector already*/
bool IsUnique (int number, std::vector<int> vec);
/** \brief Calculates the size (number of voxels) of all regions*/
void GetSizeOfRegions();
typedef itk::ImageRegion<3> RegionType;
//Start the algorithm ParcelGrowthOverFaces with m_OddRegions and transfer them to m_EvenRegions or m_InvalidRegions respectively
std::vector<std::pair<RegionType, int> > m_EvenRegions;
std::vector<std::pair<RegionType, int> > m_OddRegions;
std::vector<std::pair<RegionType, int> > m_InvalidRegions;
std::vector<int> m_SizeOfRegions;
//For merging; regions that can't be merged any more
std::vector<int> m_SizeOfFinishedRegions;
ImageType * m_Image;
int m_NumberNodes;
int m_GivenSizeOfSmallestRegion;
int m_DesiredNumberOfParcels;
int m_GivenSizeOfSmallestRegionBeginning;
bool m_MergingWithNumberParcels;
bool m_MergingWithSmallestParcel;
bool m_JustMergeSmallParcels;
ItkRngType::Pointer m_RandGen;
};
}
#include "mitkRandomParcellationGenerator.cpp"
#endif /* mitkRandomParcellationGenerator_h */
diff --git a/Modules/Connectomics/Algorithms/BrainParcellation/mitkRegionVoxelCounter.cpp b/Modules/Connectomics/Algorithms/BrainParcellation/mitkRegionVoxelCounter.cpp
index ead93a7..c56d171 100644
--- a/Modules/Connectomics/Algorithms/BrainParcellation/mitkRegionVoxelCounter.cpp
+++ b/Modules/Connectomics/Algorithms/BrainParcellation/mitkRegionVoxelCounter.cpp
@@ -1,61 +1,61 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkRegionVoxelCounter.h>
//Itk Iterators
#include <itkNeighborhoodIterator.h>
#include <itkImageRegionIterator.h>
//Set Functions
template <typename TPixel, unsigned int VImageDimension>
void mitk::RegionVoxelCounter<TPixel, VImageDimension>::SetRegion(typename ImageType::RegionType region)
{
m_Region = region;
}
template <typename TPixel, unsigned int VImageDimension>
void mitk::RegionVoxelCounter<TPixel, VImageDimension>::SetImage(itk::Image<TPixel, VImageDimension> * image)
{
m_Image = image;
}
//Other Functions
template <typename TPixel, unsigned int VImageDimension>
int mitk::RegionVoxelCounter<TPixel, VImageDimension>::VoxelWithValue(TPixel value)
{
itk::ImageRegionIterator<ImageType> it_region(m_Image, m_Region);
int counter(0);
for (it_region.GoToBegin(); !it_region.IsAtEnd(); ++it_region)
{
if (it_region.Value() == value) //Found Voxel with chosen value
{
counter++;
}
}
return counter;
}
template <typename TPixel, unsigned int VImageDimension>
double mitk::RegionVoxelCounter<TPixel, VImageDimension>::PercentageVoxelWithValueZeroExcluded(int value)
{
itk::Size<3> regionSize = m_Region.GetSize();
double volume = regionSize[0] * regionSize[1] * regionSize[2];
double measurement = this->VoxelWithValue(value) / (volume - this->VoxelWithValue(0));
return measurement;
}
diff --git a/Modules/Connectomics/Algorithms/BrainParcellation/mitkRegionVoxelCounter.h b/Modules/Connectomics/Algorithms/BrainParcellation/mitkRegionVoxelCounter.h
index 5496364..637079b 100644
--- a/Modules/Connectomics/Algorithms/BrainParcellation/mitkRegionVoxelCounter.h
+++ b/Modules/Connectomics/Algorithms/BrainParcellation/mitkRegionVoxelCounter.h
@@ -1,51 +1,51 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkRegionVoxelCounter_h
#define mitkRegionVoxelCounter_h
#include<itkImage.h>
#include "mitkCommon.h"
#include "MitkConnectomicsExports.h"
namespace mitk
{
template <typename TPixel, unsigned int VImageDimension>
class RegionVoxelCounter
{
public:
typedef itk::Image< TPixel, VImageDimension > ImageType;
void SetRegion(typename ImageType::RegionType);
void SetImage(itk::Image<TPixel, VImageDimension> *);
/** \brief Counts all voxels with the chosen value in the set region*/
int VoxelWithValue(TPixel value);
/** \brief Gives back the percentage of the number of voxels with the chosen value in comparison to the number of voxels with other values (except zero)*/
double PercentageVoxelWithValueZeroExcluded(int value);
private:
typename ImageType::RegionType m_Region;
ImageType * m_Image;
};
}
#include "mitkRegionVoxelCounter.cpp"
#endif /* mitkRegionVoxelCounter_h */
diff --git a/Modules/Connectomics/Algorithms/itkConnectomicsNetworkToConnectivityMatrixImageFilter.cpp b/Modules/Connectomics/Algorithms/itkConnectomicsNetworkToConnectivityMatrixImageFilter.cpp
index 4b36c8d..d7f5501 100644
--- a/Modules/Connectomics/Algorithms/itkConnectomicsNetworkToConnectivityMatrixImageFilter.cpp
+++ b/Modules/Connectomics/Algorithms/itkConnectomicsNetworkToConnectivityMatrixImageFilter.cpp
@@ -1,186 +1,186 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 ITK_ConnectomicsNetworkToConnectivityMatrixImageFilter_CPP
#define ITK_ConnectomicsNetworkToConnectivityMatrixImageFilter_CPP
#include <itkImageRegionIterator.h>
#include <vector>
itk::ConnectomicsNetworkToConnectivityMatrixImageFilter::ConnectomicsNetworkToConnectivityMatrixImageFilter()
: m_BinaryConnectivity(false)
, m_RescaleConnectivity(false)
, m_InputNetwork(nullptr)
{
}
itk::ConnectomicsNetworkToConnectivityMatrixImageFilter::~ConnectomicsNetworkToConnectivityMatrixImageFilter()
{
}
void itk::ConnectomicsNetworkToConnectivityMatrixImageFilter::GenerateData()
{
this->AllocateOutputs();
OutputImageType::Pointer output = this->GetOutput();
if(m_InputNetwork.IsNull())
{
MITK_ERROR << "Failed to generate data, no valid network was set.";
return;
}
typedef mitk::ConnectomicsNetwork::NetworkType NetworkType;
typedef boost::graph_traits< NetworkType >::vertex_descriptor DescriptorType;
typedef boost::graph_traits< NetworkType >::vertex_iterator IteratorType;
// prepare connectivity matrix for data
std::vector< std::vector< double > > connectivityMatrix;
int numberOfVertices = m_InputNetwork->GetNumberOfVertices();
connectivityMatrix.resize( numberOfVertices );
for( int index(0); index < numberOfVertices; index++ )
{
connectivityMatrix[ index ].resize( numberOfVertices );
}
// Create LabelToIndex translation
std::map< std::string, DescriptorType > labelToIndexMap;
NetworkType boostGraph = *(m_InputNetwork->GetBoostGraph());
// translate index to label
IteratorType iterator, end;
boost::tie(iterator, end) = boost::vertices( boostGraph );
for ( ; iterator != end; ++iterator)
{
labelToIndexMap.insert(
std::pair< std::string, DescriptorType >(
boostGraph[ *iterator ].label, *iterator )
);
}
std::vector< std::string > indexToLabel;
// translate index to label
indexToLabel.resize( numberOfVertices );
boost::tie(iterator, end) = boost::vertices( boostGraph );
for ( ; iterator != end; ++iterator)
{
indexToLabel[ *iterator ] = boostGraph[ *iterator ].label;
}
//translate label to position
std::vector< std::string > positionToLabelVector;
positionToLabelVector = indexToLabel;
std::sort ( positionToLabelVector.begin(), positionToLabelVector.end() );
for( int outerLoop( 0 ); outerLoop < numberOfVertices; outerLoop++ )
{
DescriptorType fromVertexDescriptor = labelToIndexMap.find( positionToLabelVector[ outerLoop ] )->second;
for( int innerLoop( outerLoop + 1 ); innerLoop < numberOfVertices; innerLoop++ )
{
DescriptorType toVertexDescriptor = labelToIndexMap.find( positionToLabelVector[ innerLoop ] )->second;
double fiber_count( 0 );
if( boost::edge(toVertexDescriptor, fromVertexDescriptor, boostGraph ).second )
{
fiber_count = m_InputNetwork->GetEdge( fromVertexDescriptor , toVertexDescriptor ).fiber_count;
}
connectivityMatrix[outerLoop][innerLoop] = fiber_count;
connectivityMatrix[innerLoop][outerLoop] = fiber_count;
}
}
OutputImageType::SpacingType spacing;
spacing[0] = 1.0;
spacing[1] = 1.0;
OutputImageType::PointType origin;
origin[0] = 0.0;
origin[1] = 0.0;
OutputImageType::IndexType index;
index[0] = 0.0;
index[1] = 0.0;
OutputImageType::SizeType size;
size[0] = numberOfVertices;
size[1] = numberOfVertices;
OutputImageType::RegionType region;
region.SetIndex( index );
region.SetSize( size );
output->SetSpacing( spacing ); // Set the image spacing
output->SetOrigin( origin ); // Set the image origin
output->SetRegions( region );
output->Allocate();
output->FillBuffer(0);
itk::ImageRegionIterator< OutputImageType > it_connect(output, output->GetLargestPossibleRegion());
int counter( 0 );
double rescaleFactor( 1.0 );
double rescaleMax( 255.0 );
if( m_RescaleConnectivity )
{
rescaleFactor = rescaleMax / m_InputNetwork->GetMaximumWeight();
}
// Colour pixels according to connectivity
if( m_BinaryConnectivity )
{
// binary connectivity
while( !it_connect.IsAtEnd() )
{
if( connectivityMatrix[ ( counter - counter % numberOfVertices ) / numberOfVertices][ counter % numberOfVertices ] )
{
it_connect.Set( 1 );
}
else
{
it_connect.Set( 0 );
}
++it_connect;
counter++;
}
}
else
{
// if desired rescale to the 0-255 range
while( !it_connect.IsAtEnd() )
{
it_connect.Set( ( unsigned short ) (rescaleFactor *
connectivityMatrix[ ( counter - counter % numberOfVertices ) / numberOfVertices][ counter % numberOfVertices ])
);
++it_connect;
counter++;
}
}
}
#endif
diff --git a/Modules/Connectomics/Algorithms/itkConnectomicsNetworkToConnectivityMatrixImageFilter.h b/Modules/Connectomics/Algorithms/itkConnectomicsNetworkToConnectivityMatrixImageFilter.h
index b500344..8c443e8 100644
--- a/Modules/Connectomics/Algorithms/itkConnectomicsNetworkToConnectivityMatrixImageFilter.h
+++ b/Modules/Connectomics/Algorithms/itkConnectomicsNetworkToConnectivityMatrixImageFilter.h
@@ -1,81 +1,81 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 ITK_ConnectomicsNetworkToConnectivityMatrixImageFilter_H
#define ITK_ConnectomicsNetworkToConnectivityMatrixImageFilter_H
// ITK includes
#include <itkImageSource.h>
#include <itkImage.h>
// MITK includes
#include "mitkConnectomicsNetwork.h"
namespace itk
{
class ConnectomicsNetworkToConnectivityMatrixImageFilter : public ImageSource< itk::Image< unsigned short, 2 > >
{
public:
typedef ConnectomicsNetworkToConnectivityMatrixImageFilter Self;
typedef ProcessObject Superclass;
typedef SmartPointer< Self > Pointer;
typedef SmartPointer< const Self > ConstPointer;
typedef itk::Image< unsigned short, 2 > OutputImageType;
typedef OutputImageType::PixelType OutPixelType;
typedef mitk::ConnectomicsNetwork InputType;
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
itkTypeMacro( ConnectomicsNetworkToConnectivityMatrixImageFilter, ImageSource )
/** Get/Set m_BinaryConnectivity **/
itkSetMacro( BinaryConnectivity, bool)
itkGetMacro( BinaryConnectivity, bool)
/** Get/Set m_RescaleConnectivity **/
itkSetMacro( RescaleConnectivity, bool)
itkGetMacro( RescaleConnectivity, bool)
itkSetMacro( InputNetwork, InputType::Pointer)
void GenerateData() override;
protected:
ConnectomicsNetworkToConnectivityMatrixImageFilter();
virtual ~ConnectomicsNetworkToConnectivityMatrixImageFilter();
/** Controls whether the connectivity matrix is binary */
bool m_BinaryConnectivity;
/** Controls whether the connectivity matrix entries are rescaled to lie between 0 and 255*/
bool m_RescaleConnectivity;
InputType::Pointer m_InputNetwork;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkConnectomicsNetworkToConnectivityMatrixImageFilter.cpp"
#endif
#endif /* ITK_ConnectomicsNetworkToConnectivityMatrixImageFilter_H */
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsBetweennessHistogram.cpp b/Modules/Connectomics/Algorithms/mitkConnectomicsBetweennessHistogram.cpp
index 4a237ef..bbe76f5 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsBetweennessHistogram.cpp
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsBetweennessHistogram.cpp
@@ -1,130 +1,130 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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<mitkConnectomicsBetweennessHistogram.h>
#include <boost/numeric/conversion/converter.hpp>
#include <mitkConnectomicsConstantsManager.h>
mitk::ConnectomicsBetweennessHistogram::ConnectomicsBetweennessHistogram()
: m_Mode( UnweightedUndirectedMode )
, m_CentralityMap()
{
m_Subject = "Node Betweenness";
}
mitk::ConnectomicsBetweennessHistogram::~ConnectomicsBetweennessHistogram()
{
}
void mitk::ConnectomicsBetweennessHistogram::SetBetweennessCalculationMode(
const mitk::ConnectomicsBetweennessHistogram::BetweennessCalculationMode & mode )
{
m_Mode = mode;
}
mitk::ConnectomicsBetweennessHistogram::BetweennessCalculationMode mitk::ConnectomicsBetweennessHistogram::GetBetweennessCalculationMode()
{
return m_Mode;
}
void mitk::ConnectomicsBetweennessHistogram::ComputeFromConnectomicsNetwork( ConnectomicsNetwork* source )
{
NetworkType* boostGraph = source->GetBoostGraph();
IteratorType vertex_iterator_begin, vertex_iterator_end;
m_CentralityMap.clear();
m_CentralityMap.resize( source->GetNumberOfVertices() );
switch( m_Mode )
{
case UnweightedUndirectedMode:
{
CalculateUnweightedUndirectedBetweennessCentrality( boostGraph, vertex_iterator_begin, vertex_iterator_end );
break;
}
case WeightedUndirectedMode:
{
CalculateWeightedUndirectedBetweennessCentrality( boostGraph, vertex_iterator_begin, vertex_iterator_end );
break;
}
}
ConvertCentralityMapToHistogram();
}
void mitk::ConnectomicsBetweennessHistogram::CalculateUnweightedUndirectedBetweennessCentrality(
NetworkType* boostGraph, IteratorType /*vertex_iterator_begin*/, IteratorType /*vertex_iterator_end*/ )
{
boost::brandes_betweenness_centrality(
*boostGraph,
boost::centrality_map(
boost::make_iterator_property_map( m_CentralityMap.begin(), boost::get( &mitk::ConnectomicsNetwork::NetworkNode::id, *boostGraph ), double() )
).vertex_index_map( boost::get( &mitk::ConnectomicsNetwork::NetworkNode::id, *boostGraph ) )
);
}
void mitk::ConnectomicsBetweennessHistogram::CalculateWeightedUndirectedBetweennessCentrality(
NetworkType* /*boostGraph*/, IteratorType /*vertex_iterator_begin*/, IteratorType /*vertex_iterator_end*/ )
{
MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_UNIMPLEMENTED_FEATURE;
}
void mitk::ConnectomicsBetweennessHistogram::ConvertCentralityMapToHistogram()
{
double maximumFloat( 0.0 );
for ( unsigned int index( 0 ); index < m_CentralityMap.size(); index++ )
{
if( m_CentralityMap[ index ] > maximumFloat )
{
maximumFloat = m_CentralityMap[ index ];
}
}
// use the boost double to int converter
// it defaults to trunc
typedef boost::numeric::converter<int,double> Double2Int ;
// for rounding, reduces the number of nodes classed as zero
maximumFloat += 0.5;
int maximumInt( 0 );
try
{
maximumInt = Double2Int::convert( maximumFloat );
}
catch ( boost::numeric::positive_overflow const& )
{
MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_OUTSIDE_INTEGER_RANGE;
}
m_HistogramVector.resize( maximumInt + 1 );
for ( unsigned int index( 0 ); index < m_CentralityMap.size(); index++ )
{
int value( 0 );
value = Double2Int::convert( ( m_CentralityMap[index ] + 0.5 ) );
m_HistogramVector[ value ]++;
}
UpdateYMax();
m_Valid = true;
}
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsBetweennessHistogram.h b/Modules/Connectomics/Algorithms/mitkConnectomicsBetweennessHistogram.h
index 7481671..16bcb12 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsBetweennessHistogram.h
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsBetweennessHistogram.h
@@ -1,90 +1,90 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_ConnectomicsBetweennessHistogram_H
#define _MITK_ConnectomicsBetweennessHistogram_H
#include<mitkConnectomicsHistogramBase.h>
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4172)
#endif
#include <boost/graph/betweenness_centrality.hpp>
#ifdef _MSC_VER
# pragma warning(pop)
#endif
namespace mitk {
/**
* \brief A class to calculate and store the betweenness of each node */
class ConnectomicsBetweennessHistogram : public mitk::ConnectomicsHistogramBase
{
public:
/** Enum for different ways to calculate betweenness centrality */
enum BetweennessCalculationMode
{
UnweightedUndirectedMode,
WeightedUndirectedMode
};
ConnectomicsBetweennessHistogram();
~ConnectomicsBetweennessHistogram() override;
/** Set the calucaltion mode */
void SetBetweennessCalculationMode( const BetweennessCalculationMode & );
/** Get the calculation mode */
BetweennessCalculationMode GetBetweennessCalculationMode();
protected:
/* Typedefs */
typedef mitk::ConnectomicsNetwork::NetworkType NetworkType;
typedef boost::graph_traits< NetworkType >::vertex_iterator IteratorType;
typedef std::vector< double > BCMapType;
/** @brief Creates a new histogram from the network source. */
void ComputeFromConnectomicsNetwork( ConnectomicsNetwork* source ) override;
/** Calculate betweenness centrality ignoring the weight of the edges */
void CalculateUnweightedUndirectedBetweennessCentrality( NetworkType*, IteratorType, IteratorType );
/** Calculate betweenness centrality taking into consideration the weight of the edges */
void CalculateWeightedUndirectedBetweennessCentrality( NetworkType*, IteratorType, IteratorType );
/** Converts the centrality map to a histogram by binning */
void ConvertCentralityMapToHistogram();
/** Stores which mode has been selected for betweenness centrality calculation */
BetweennessCalculationMode m_Mode;
/** Stores the betweenness centralities for each node */
BCMapType m_CentralityMap;
};
}
#endif /* _MITK_ConnectomicsBetweennessHistogram_H */
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsDegreeHistogram.cpp b/Modules/Connectomics/Algorithms/mitkConnectomicsDegreeHistogram.cpp
index 2c52b24..1e94508 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsDegreeHistogram.cpp
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsDegreeHistogram.cpp
@@ -1,58 +1,58 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkConnectomicsDegreeHistogram.h>
mitk::ConnectomicsDegreeHistogram::ConnectomicsDegreeHistogram()
{
m_Subject = "Node degree";
}
mitk::ConnectomicsDegreeHistogram::~ConnectomicsDegreeHistogram()
{
}
void mitk::ConnectomicsDegreeHistogram::ComputeFromConnectomicsNetwork( ConnectomicsNetwork* source )
{
std::vector< int > degreeOfNodesVector = source->GetDegreeOfNodes();
int maximumDegree( 0 );
for(unsigned int index( 0 ); index < degreeOfNodesVector.size(); index++ )
{
if( maximumDegree < degreeOfNodesVector[ index ] )
{
maximumDegree = degreeOfNodesVector[ index ];
}
}
this->m_HistogramVector.resize( maximumDegree + 1 );
for(unsigned int index( 0 ); index < m_HistogramVector.size(); index++ )
{
this->m_HistogramVector[ index ] = 0;
}
this->m_TopValue = maximumDegree;
for(unsigned int index( 0 ); index < degreeOfNodesVector.size(); index++ )
{
this->m_HistogramVector[ degreeOfNodesVector[ index ] ]++;
}
// successfully created a valid histogram
this->m_Valid = true;
}
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsDegreeHistogram.h b/Modules/Connectomics/Algorithms/mitkConnectomicsDegreeHistogram.h
index 3526393..dae8277 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsDegreeHistogram.h
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsDegreeHistogram.h
@@ -1,47 +1,47 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_ConnectomicsDegreeHistogram_H
#define _MITK_ConnectomicsDegreeHistogram_H
#include<mitkConnectomicsHistogramBase.h>
namespace mitk {
/**
* \brief A class to calculate and store the degree of each node */
class ConnectomicsDegreeHistogram : public mitk::ConnectomicsHistogramBase
{
public:
ConnectomicsDegreeHistogram();
~ConnectomicsDegreeHistogram() override;
protected:
/** @brief Creates a new histogram from the network source. */
void ComputeFromConnectomicsNetwork( ConnectomicsNetwork* source ) override;
};
}
#endif /* _MITK_ConnectomicsDegreeHistogram_H */
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsHistogramBase.cpp b/Modules/Connectomics/Algorithms/mitkConnectomicsHistogramBase.cpp
index eb97afc..d7d91a0 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsHistogramBase.cpp
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsHistogramBase.cpp
@@ -1,226 +1,226 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkConnectomicsHistogramBase.h>
#include <mitkConnectomicsConstantsManager.h>
#include <boost/numeric/conversion/converter.hpp>
mitk::ConnectomicsHistogramBase::ConnectomicsHistogramBase()
: m_Valid( false )
, m_BaselineValue( 0 )
, m_TopValue( 1 )
, m_StartValue( 0 )
, m_Subject( "" )
{
}
mitk::ConnectomicsHistogramBase::~ConnectomicsHistogramBase()
{
}
double mitk::ConnectomicsHistogramBase::GetYMin() const
{
return m_BaselineValue;
}
double mitk::ConnectomicsHistogramBase::GetYMax() const
{
return m_TopValue;
}
double mitk::ConnectomicsHistogramBase::GetMin() const
{
return this->GetXMin();
}
double mitk::ConnectomicsHistogramBase::GetMax() const
{
return this->GetXMax();
}
double mitk::ConnectomicsHistogramBase::GetXMin() const
{
return m_StartValue;
}
double mitk::ConnectomicsHistogramBase::GetXMax() const
{
return ( m_StartValue + this->GetRange() );
}
int mitk::ConnectomicsHistogramBase::GetRange() const
{
return m_HistogramVector.size();
}
bool mitk::ConnectomicsHistogramBase::IsValid() const
{
return m_Valid;
}
void mitk::ConnectomicsHistogramBase::PrintToConsole() const
{
MITK_INFO << "Histogram - Maximum " << this->GetYMax() << " Minimum " << this->GetYMin() << " Range " << this->GetRange();
for(unsigned int index( 0 ); index < m_HistogramVector.size(); index++ )
{
MITK_INFO << " Bin: " << index << " Value: " << m_HistogramVector[ index ];
}
}
std::string mitk::ConnectomicsHistogramBase::GetSubject() const
{
return m_Subject;
}
void mitk::ConnectomicsHistogramBase::SetSubject( std::string subject )
{
m_Subject = subject;
}
void mitk::ConnectomicsHistogramBase::ComputeFromBaseData( BaseData* source )
{
m_Valid = false;
m_HistogramVector.clear();
//check if input is valid
if (source==nullptr)
{ // empty base data
return;
}
mitk::ConnectomicsNetwork* networkSource = dynamic_cast<mitk::ConnectomicsNetwork*>(source);
if (networkSource==nullptr)
{ // base data but no network
return;
}
ComputeFromConnectomicsNetwork( networkSource );
}
float mitk::ConnectomicsHistogramBase::GetRelativeBin( double start, double end ) const
{
// use the boost double to int converter
// it defaults to trunc
typedef boost::numeric::converter<int,double> Double2Int ;
float result( 0.0 );
if( !m_Valid )
{
MITK_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_TRIED_TO_ACCESS_INVALID_HISTOGRAM;
return result;
}
if( ( start < 0.0 ) ||
( end < 0.0 ) )
{
MITK_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_PASSED_NEGATIVE_INDEX_TO_HISTOGRAM;
return result;
}
// calculate result
if( std::abs( end - start ) <= 1.0 )
{ // if the bin size is one or less, we can do not need to interpolate
unsigned int index( 0 );
try
{
// show the value for n between n - .5 and n + .5
double temp = ( start + end ) / 2.0;
index = Double2Int::convert( temp ); // By default throws positive_overflow()
}
catch ( boost::numeric::positive_overflow const& )
{
MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_OUTSIDE_INTEGER_RANGE;
}
if( index < m_HistogramVector.size() )
{
result = m_HistogramVector[ index ];
}
else
{
MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_BEYOND_SCOPE <<
index << " on vector sized: " << m_HistogramVector.size();
}
}
else
{ // if the bin size is more than one we need to interpolate
unsigned int indexStart( 0 ), indexEnd( 0 );
try
{
indexStart = Double2Int::convert( start );
indexEnd = Double2Int::convert( end );
}
catch ( boost::numeric::positive_overflow const& )
{
MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_OUTSIDE_INTEGER_RANGE;
}
if( ( indexStart < m_HistogramVector.size() ) &&
( indexEnd < m_HistogramVector.size() ) )
{
// add up weighted values and divide by range
// add partial start and end bin
double startPercentage = 1.0 - start + indexStart;
double endPercentage = end - indexEnd;
result += startPercentage * m_HistogramVector[ indexStart ];
result += endPercentage * m_HistogramVector[ indexEnd ];
// add whole inbetween bins
for( unsigned int tempIndex = indexStart + 1; tempIndex < indexEnd; tempIndex++ )
{
result += m_HistogramVector[ tempIndex ];
}
}
else
{
MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_BEYOND_SCOPE << indexStart << " to " <<
indexEnd << " on vector sized: " << m_HistogramVector.size();
}
}
// normalizeresult by dividing through maximum degree
result = result / GetYMax();
return result;
}
void mitk::ConnectomicsHistogramBase::UpdateYMax()
{
for ( unsigned int index( 0 ); index < m_HistogramVector.size(); index++ )
{
if( m_HistogramVector[ index ] > m_TopValue )
{
m_TopValue = m_HistogramVector[ index ];
}
}
}
std::vector< double > mitk::ConnectomicsHistogramBase::GetHistogramVector()
{
return m_HistogramVector;
}
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsHistogramBase.h b/Modules/Connectomics/Algorithms/mitkConnectomicsHistogramBase.h
index 5682d5f..a1ebf08 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsHistogramBase.h
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsHistogramBase.h
@@ -1,101 +1,101 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_ConnectomicsHistogramBase_H
#define _MITK_ConnectomicsHistogramBase_H
#include "mitkSimpleHistogram.h"
#include "mitkCommon.h"
#include "mitkConnectomicsNetwork.h"
namespace mitk {
/**
* \brief Superclass for histograms working with connectomic networks
*/
class ConnectomicsHistogramBase : public mitk::SimpleHistogram
{
public:
ConnectomicsHistogramBase();
virtual ~ConnectomicsHistogramBase();
/** @brief Returns the minimal y=f(x) value of the histogram. */
virtual double GetYMin() const;
/** @brief Returns the maximum y=f(x) value of the histogram. */
virtual double GetYMax() const;
/** @brief Returns the minimal x value of the histogram. */
virtual double GetXMin() const;
/** @brief Returns the maximum x value of the histogram. */
virtual double GetXMax() const;
/** @brief Returns the range of the histogram. */
virtual int GetRange() const;
/** @brief Update the Y maximum to the maximal value in the histogram */
virtual void UpdateYMax();
/** @brief Creates a new histogram from the source. */
void ComputeFromBaseData( BaseData* source ) override;
/** @brief Print values to console. */
virtual void PrintToConsole( ) const;
/** @brief Returns whether the histogram can be considered valid. */
virtual bool IsValid() const;
/** @brief Returns the subject of the histogram as a string. */
virtual std::string GetSubject() const;
/** @brief Set the subject of the histogram as a string. */
virtual void SetSubject( std::string );
/** @brief Get bin height for the bin between start and end*/
float GetRelativeBin( double start, double end ) const override;
/** @brief Get the double vector*/
virtual std::vector< double > GetHistogramVector();
protected:
// Functions
/** @brief Creates a new histogram from the network source. */
virtual void ComputeFromConnectomicsNetwork( ConnectomicsNetwork* source ) = 0;
/** @brief Legacy method, do no use */
double GetMin() const override;
/** @brief Legacy method, do no use */
double GetMax() const override;
// Variables
/** @brief Is this a valid histogram*/
bool m_Valid;
/** @brief Which is the baseline value for the histogram
This value should be zero for all network histograms */
int m_BaselineValue;
/** @brief Which is the top value for the histogram */
int m_TopValue;
/** @brief Which is the starting x value for the histogram */
int m_StartValue;
/** @brief We expect not continuous but discrete histograms */
std::vector< double > m_HistogramVector;
/** @brief Subject of the histogram as a string. */
std::string m_Subject;
};
}
#endif /* _MITK_ConnectomicsHistogramBase_H */
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsHistogramCache.cpp b/Modules/Connectomics/Algorithms/mitkConnectomicsHistogramCache.cpp
index 4c29f71..c85b375 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsHistogramCache.cpp
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsHistogramCache.cpp
@@ -1,95 +1,95 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsHistogramCache.h"
mitk::ConnectomicsHistogramCache::ConnectomicsHistogramCache()
{
}
mitk::ConnectomicsHistogramCache::~ConnectomicsHistogramCache()
{
}
mitk::ConnectomicsHistogramsContainer * mitk::ConnectomicsHistogramCache::operator[]( mitk::ConnectomicsNetwork::Pointer sp_NetworkData )
{
BaseData *p_BaseData = dynamic_cast< BaseData* >( sp_NetworkData.GetPointer() );
if(!p_BaseData)
{
MITK_WARN << "ConnectomicsHistogramCache::operator[] with null connectomics network data called";
return nullptr;
}
ConnectomicsHistogramsCacheElement *elementToUpdate = nullptr;
bool first( true );
bool found( false );
for(auto iter = cache.begin(); iter != cache.end(); iter++)
{
ConnectomicsHistogramsCacheElement *e = dynamic_cast<ConnectomicsHistogramsCacheElement *>(*iter);
BaseData *p_tmp = e->baseData.Lock();
if(p_tmp == p_BaseData)
{
if(!first)
{
cache.erase(iter);
cache.push_front(e);
}
if( p_BaseData->GetMTime() > e->m_LastUpdateTime.GetMTime())
{
// found but needs an update
found = true;
elementToUpdate = e;
break;
}
// found but no update needed
return dynamic_cast<ConnectomicsHistogramsContainer*>( e->GetHistograms() );
}
first = false;
}
if( !found )
{
if (dynamic_cast<ConnectomicsNetwork*>(p_BaseData))
{
elementToUpdate = new ConnectomicsHistogramsCacheElement();
}
else
{
MITK_WARN << "not supported: " << p_BaseData->GetNameOfClass();
return nullptr;
}
elementToUpdate->baseData = p_BaseData;
cache.push_front(elementToUpdate);
TrimCache();
}
if(elementToUpdate)
{
elementToUpdate->ComputeFromBaseData(p_BaseData);
elementToUpdate->m_LastUpdateTime.Modified();
return dynamic_cast<ConnectomicsHistogramsContainer*>( elementToUpdate->GetHistograms() );
}
return nullptr;
}
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsHistogramCache.h b/Modules/Connectomics/Algorithms/mitkConnectomicsHistogramCache.h
index f739856..25e4ec4 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsHistogramCache.h
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsHistogramCache.h
@@ -1,113 +1,113 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKCONNECTOMICSHISTOGRAMCACHE_H
#define MITKCONNECTOMICSHISTOGRAMCACHE_H
#include "mitkSimpleHistogram.h"
#include "mitkConnectomicsNetwork.h"
#include <mitkConnectomicsDegreeHistogram.h>
#include <mitkConnectomicsBetweennessHistogram.h>
#include <mitkConnectomicsShortestPathHistogram.h>
#include <MitkConnectomicsExports.h>
namespace mitk {
/**
* @brief Provides a method to cache network histograms
*/
class ConnectomicsHistogramsContainer
{
public:
void ComputeFromBaseData(BaseData* baseData)
{
m_BetweennessHistogram.ComputeFromBaseData(baseData);
m_DegreeHistogram.ComputeFromBaseData(baseData);
m_ShortestPathHistogram.ComputeFromBaseData(baseData);
}
ConnectomicsBetweennessHistogram* GetBetweennessHistogram( )
{
return &m_BetweennessHistogram;
}
ConnectomicsDegreeHistogram* GetDegreeHistogram( )
{
return &m_DegreeHistogram;
}
ConnectomicsShortestPathHistogram* GetShortestPathHistogram( )
{
return &m_ShortestPathHistogram;
}
ConnectomicsBetweennessHistogram m_BetweennessHistogram;
ConnectomicsDegreeHistogram m_DegreeHistogram;
ConnectomicsShortestPathHistogram m_ShortestPathHistogram;
};
class MITKCONNECTOMICS_EXPORT ConnectomicsHistogramCache : public SimpleHistogramCache
{
public:
ConnectomicsHistogramCache();
~ConnectomicsHistogramCache();
ConnectomicsHistogramsContainer *operator[]( ConnectomicsNetwork::Pointer sp_NetworkData);
protected:
// purposely not implemented
SimpleHistogram *operator[](BaseData::Pointer sp_BaseData);
};
class ConnectomicsHistogramsCacheElement : public ConnectomicsHistogramCache::Element
{
public:
void ComputeFromBaseData(BaseData* baseData) override
{
m_Container.ComputeFromBaseData(baseData);
}
ConnectomicsHistogramsContainer* GetHistograms()
{
return &m_Container;
}
ConnectomicsHistogramsContainer m_Container;
private:
ConnectomicsHistogramBase* GetHistogram() override
{
return nullptr;
}
};
}
#endif // MITKCONNECTOMICSHISTOGRAMCACHE_H
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkConverter.cpp b/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkConverter.cpp
index 14ee187..305fd95 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkConverter.cpp
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkConverter.cpp
@@ -1,71 +1,71 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsNetworkConverter.h"
mitk::ConnectomicsNetworkConverter::ConnectomicsNetworkConverter()
{
}
mitk::ConnectomicsNetworkConverter::~ConnectomicsNetworkConverter()
{
}
vnl_matrix<double> mitk::ConnectomicsNetworkConverter::GetNetworkAsVNLAdjacencyMatrix()
{
int numberOfNodes = boost::num_vertices( *(m_Network->GetBoostGraph()) );
//initialize a matrix N by N
vnl_matrix<double> matrix(numberOfNodes, numberOfNodes, 0);
//Define the vertex iterators
VertexIteratorType vi, vi_end;
for(boost::tie(vi, vi_end) = boost::vertices( *(m_Network->GetBoostGraph()) ); vi != vi_end; ++vi)
{
//Define the neighbor iterator
AdjacencyIteratorType neighbors, neighbors_end;
for(boost::tie(neighbors, neighbors_end) = boost::adjacent_vertices(*vi, *(m_Network->GetBoostGraph()) );
neighbors != neighbors_end; ++neighbors )
{
//Set the i,j element of the matrix to 1.
matrix.put(*vi, *neighbors, 1);
}
}
return matrix;
}
vnl_matrix<double> mitk::ConnectomicsNetworkConverter::GetNetworkAsVNLDegreeMatrix()
{
int numberOfNodes = boost::num_vertices( *(m_Network->GetBoostGraph()) );
vnl_matrix<double> matrix( numberOfNodes, numberOfNodes, 0);
//Define the vertex iterators
VertexIteratorType vi, vi_end;
for(boost::tie(vi, vi_end) = boost::vertices( *(m_Network->GetBoostGraph()) ); vi != vi_end; ++vi)
{
double numberOfNeighbors = 0;
//Define the neighbor iterator
AdjacencyIteratorType neighbors, neighbors_end;
for( boost::tie(neighbors, neighbors_end) = adjacent_vertices(*vi, *(m_Network->GetBoostGraph()) );
neighbors != neighbors_end; ++neighbors )
{
numberOfNeighbors++;
}
matrix.put(*vi, *vi, numberOfNeighbors);
}
return matrix;
}
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkConverter.h b/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkConverter.h
index 9ac97bf..007be82 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkConverter.h
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkConverter.h
@@ -1,77 +1,77 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkConnectomicsNetworkConverter_h
#define mitkConnectomicsNetworkConverter_h
#include <itkObject.h>
#include <itkObjectFactory.h>
#include <itkMacro.h>
#include "mitkCommon.h"
#include <MitkConnectomicsExports.h>
#include <mitkConnectomicsNetwork.h>
namespace mitk
{
/**
* \brief A class giving functions for conversion of connectomics networks into different formats */
class MITKCONNECTOMICS_EXPORT ConnectomicsNetworkConverter : public itk::Object
{
public:
/** Standard class typedefs. */
/** Method for creation through the object factory. */
mitkClassMacroItkParent(ConnectomicsNetworkConverter, itk::Object);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
// Typedefs
typedef mitk::ConnectomicsNetwork::NetworkType NetworkType;
typedef mitk::ConnectomicsNetwork::VertexDescriptorType VertexDescriptorType;
typedef mitk::ConnectomicsNetwork::EdgeDescriptorType EdgeDescriptorType;
typedef boost::graph_traits<NetworkType>::vertex_iterator VertexIteratorType;
typedef boost::graph_traits<NetworkType>::adjacency_iterator AdjacencyIteratorType;
typedef std::map<EdgeDescriptorType, int> EdgeIndexStdMapType;
typedef boost::associative_property_map< EdgeIndexStdMapType > EdgeIndexMapType;
typedef boost::iterator_property_map< std::vector< double >::iterator, EdgeIndexMapType > EdgeIteratorPropertyMapType;
typedef boost::property_map< NetworkType, boost::vertex_index_t>::type VertexIndexMapType;
typedef boost::iterator_property_map< std::vector< double >::iterator, VertexIndexMapType > VertexIteratorPropertyMapType;
//Macro
itkSetObjectMacro( Network, mitk::ConnectomicsNetwork );
// Conversion Getters
vnl_matrix<double> GetNetworkAsVNLAdjacencyMatrix();
vnl_matrix<double> GetNetworkAsVNLDegreeMatrix();
protected:
//////////////////// Functions ///////////////////////
ConnectomicsNetworkConverter();
~ConnectomicsNetworkConverter() override;
/////////////////////// Variables ////////////////////////
// The connectomics network, which is converted
mitk::ConnectomicsNetwork::Pointer m_Network;
};
}// end namespace mitk
#endif // mitkConnectomicsNetworkConverter_h
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkCreator.cpp b/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkCreator.cpp
index f49e79d..03a2194 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkCreator.cpp
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkCreator.cpp
@@ -1,853 +1,853 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsNetworkCreator.h"
#include <sstream>
#include <vector>
#include "mitkConnectomicsConstantsManager.h"
#include "mitkImageAccessByItk.h"
#include "mitkImageStatisticsHolder.h"
#include "mitkImageCast.h"
#include "itkImageRegionIteratorWithIndex.h"
#include <mitkDiffusionFunctionCollection.h>
// VTK
#include <vtkPolyData.h>
#include <vtkPolyLine.h>
#include <vtkCellArray.h>
mitk::ConnectomicsNetworkCreator::ConnectomicsNetworkCreator()
: m_FiberBundle()
, m_Segmentation()
, m_ConNetwork( mitk::ConnectomicsNetwork::New() )
, idCounter(0)
, m_LabelToVertexMap()
, m_LabelToNodePropertyMap()
, allowLoops( false )
, m_UseCoMCoordinates( false )
, m_LabelsToCoordinatesMap()
, m_MappingStrategy( EndElementPositionAvoidingWhiteMatter )
, m_EndPointSearchRadius( 10.0 )
, m_ZeroLabelInvalid( true )
, m_AbortConnection( false )
{
}
mitk::ConnectomicsNetworkCreator::ConnectomicsNetworkCreator( mitk::Image::Pointer segmentation, mitk::FiberBundle::Pointer fiberBundle )
: m_FiberBundle(fiberBundle)
, m_Segmentation(segmentation)
, m_ConNetwork( mitk::ConnectomicsNetwork::New() )
, idCounter(0)
, m_LabelToVertexMap()
, m_LabelToNodePropertyMap()
, allowLoops( false )
, m_LabelsToCoordinatesMap()
, m_MappingStrategy( EndElementPositionAvoidingWhiteMatter )
, m_EndPointSearchRadius( 10.0 )
, m_ZeroLabelInvalid( true )
, m_AbortConnection( false )
{
mitk::CastToItkImage( segmentation, m_SegmentationItk );
}
mitk::ConnectomicsNetworkCreator::~ConnectomicsNetworkCreator()
{
}
void mitk::ConnectomicsNetworkCreator::SetFiberBundle(mitk::FiberBundle::Pointer fiberBundle)
{
m_FiberBundle = fiberBundle;
}
void mitk::ConnectomicsNetworkCreator::SetSegmentation(mitk::Image::Pointer segmentation)
{
m_Segmentation = segmentation;
mitk::CastToItkImage( segmentation, m_SegmentationItk );
}
void mitk::ConnectomicsNetworkCreator::CreateNetworkFromFibersAndSegmentation()
{
//empty graph
m_ConNetwork = mitk::ConnectomicsNetwork::New();
m_LabelToVertexMap.clear();
m_LabelToNodePropertyMap.clear();
idCounter = 0;
vtkSmartPointer<vtkPolyData> fiberPolyData = m_FiberBundle->GetFiberPolyData();
int numFibers = m_FiberBundle->GetNumFibers();
for( int fiberID( 0 ); fiberID < numFibers; fiberID++ )
{
vtkCell* cell = fiberPolyData->GetCell(fiberID);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
TractType::Pointer singleTract = TractType::New();
for( int pointInCellID( 0 ); pointInCellID < numPoints ; pointInCellID++)
{
// push back point
PointType point = mitk::imv::GetItkPoint( points->GetPoint( pointInCellID ) );
singleTract->InsertElement( singleTract->Size(), point );
}
if ( singleTract && ( singleTract->Size() > 0 ) )
{
AddConnectionToNetwork(
ReturnAssociatedVertexPairForLabelPair(
ReturnLabelForFiberTract( singleTract, m_MappingStrategy )
), m_FiberBundle->GetFiberWeight(fiberID)
);
m_AbortConnection = false;
}
}
// Prune unconnected nodes
//m_ConNetwork->PruneUnconnectedSingleNodes();
// provide network with geometry
m_ConNetwork->SetGeometry( dynamic_cast<mitk::BaseGeometry*>(m_Segmentation->GetGeometry()->Clone().GetPointer()) );
m_ConNetwork->UpdateBounds();
m_ConNetwork->SetIsModified( true );
MBI_INFO << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_INFO_NETWORK_CREATED;
}
void mitk::ConnectomicsNetworkCreator::AddConnectionToNetwork(ConnectionType newConnection, double fiber_count)
{
if( m_AbortConnection )
{
MITK_DEBUG << "Connection aborted";
return;
}
VertexType vertexA = newConnection.first;
VertexType vertexB = newConnection.second;
// check for loops (if they are not allowed)
if( allowLoops || !( vertexA == vertexB ) )
{
// If the connection already exists, increment weight, else create connection
if ( m_ConNetwork->EdgeExists( vertexA, vertexB ) )
{
m_ConNetwork->IncreaseEdgeWeight( vertexA, vertexB, fiber_count );
}
else
{
m_ConNetwork->AddEdge( vertexA, vertexB, fiber_count );
}
}
}
mitk::ConnectomicsNetworkCreator::VertexType mitk::ConnectomicsNetworkCreator::ReturnAssociatedVertexForLabel( ImageLabelType label )
{
if( m_ZeroLabelInvalid && ( label == 0 ) )
{
m_AbortConnection = true;
return ULONG_MAX;
}
// if label is not known, create entry
if( ! ( m_LabelToVertexMap.count( label ) > 0 ) )
{
VertexType newVertex = m_ConNetwork->AddVertex( idCounter );
idCounter++;
SupplyVertexWithInformation(label, newVertex);
m_LabelToVertexMap.insert( std::pair< ImageLabelType, VertexType >( label, newVertex ) );
}
//return associated vertex
return m_LabelToVertexMap.find( label )->second;
}
mitk::ConnectomicsNetworkCreator::ConnectionType mitk::ConnectomicsNetworkCreator::ReturnAssociatedVertexPairForLabelPair( ImageLabelPairType labelpair )
{
//hand both labels through to the single label function
ConnectionType connection( ReturnAssociatedVertexForLabel(labelpair.first), ReturnAssociatedVertexForLabel(labelpair.second) );
return connection;
}
mitk::ConnectomicsNetworkCreator::ImageLabelPairType mitk::ConnectomicsNetworkCreator::ReturnLabelForFiberTract( TractType::Pointer singleTract, mitk::ConnectomicsNetworkCreator::MappingStrategy strategy)
{
switch( strategy )
{
case EndElementPosition:
{
return EndElementPositionLabel( singleTract );
}
case JustEndPointVerticesNoLabel:
{
return JustEndPointVerticesNoLabelTest( singleTract );
}
case EndElementPositionAvoidingWhiteMatter:
{
return EndElementPositionLabelAvoidingWhiteMatter( singleTract );
}
case PrecomputeAndDistance:
{
return PrecomputeVertexLocationsBySegmentation( singleTract );
}
}
// To remove warnings, this code should never be reached
MBI_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_MAPPING;
ImageLabelPairType nullPair( 0,0 );
return nullPair;
}
mitk::ConnectomicsNetworkCreator::ImageLabelPairType mitk::ConnectomicsNetworkCreator::EndElementPositionLabel( TractType::Pointer singleTract )
{
ImageLabelPairType labelpair;
{// Note: .fib image tracts are safed using index coordinates
mitk::Point3D firstElementFiberCoord, lastElementFiberCoord;
mitk::Point3D firstElementSegCoord, lastElementSegCoord;
itk::Index<3> firstElementSegIndex, lastElementSegIndex;
if( singleTract->front().Size() != 3 )
{
MBI_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_DIMENSION_NEED_3;
}
for( unsigned int index = 0; index < singleTract->front().Size(); index++ )
{
firstElementFiberCoord.SetElement( index, singleTract->front().GetElement( index ) );
lastElementFiberCoord.SetElement( index, singleTract->back().GetElement( index ) );
}
// convert from fiber index coordinates to segmentation index coordinates
FiberToSegmentationCoords( firstElementFiberCoord, firstElementSegCoord );
FiberToSegmentationCoords( lastElementFiberCoord, lastElementSegCoord );
for( int index = 0; index < 3; index++ )
{
firstElementSegIndex.SetElement( index, firstElementSegCoord.GetElement( index ) );
lastElementSegIndex.SetElement( index, lastElementSegCoord.GetElement( index ) );
}
int firstLabel = m_SegmentationItk->GetPixel(firstElementSegIndex);
int lastLabel = m_SegmentationItk->GetPixel(lastElementSegIndex );
labelpair.first = firstLabel;
labelpair.second = lastLabel;
// Add property to property map
CreateNewNode( firstLabel, firstElementSegIndex, m_UseCoMCoordinates );
CreateNewNode( lastLabel, lastElementSegIndex, m_UseCoMCoordinates );
}
return labelpair;
}
mitk::ConnectomicsNetworkCreator::ImageLabelPairType mitk::ConnectomicsNetworkCreator::PrecomputeVertexLocationsBySegmentation( TractType::Pointer /*singleTract*/ )
{
ImageLabelPairType labelpair;
return labelpair;
}
mitk::ConnectomicsNetworkCreator::ImageLabelPairType mitk::ConnectomicsNetworkCreator::EndElementPositionLabelAvoidingWhiteMatter( TractType::Pointer singleTract )
{
ImageLabelPairType labelpair;
{// Note: .fib image tracts are safed using index coordinates
mitk::Point3D firstElementFiberCoord, lastElementFiberCoord;
mitk::Point3D firstElementSegCoord, lastElementSegCoord;
itk::Index<3> firstElementSegIndex, lastElementSegIndex;
if( singleTract->front().Size() != 3 )
{
MBI_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_DIMENSION_NEED_3;
}
for( unsigned int index = 0; index < singleTract->front().Size(); index++ )
{
firstElementFiberCoord.SetElement( index, singleTract->front().GetElement( index ) );
lastElementFiberCoord.SetElement( index, singleTract->back().GetElement( index ) );
}
// convert from fiber index coordinates to segmentation index coordinates
FiberToSegmentationCoords( firstElementFiberCoord, firstElementSegCoord );
FiberToSegmentationCoords( lastElementFiberCoord, lastElementSegCoord );
for( int index = 0; index < 3; index++ )
{
firstElementSegIndex.SetElement( index, firstElementSegCoord.GetElement( index ) );
lastElementSegIndex.SetElement( index, lastElementSegCoord.GetElement( index ) );
}
int firstLabel = m_SegmentationItk->GetPixel(firstElementSegIndex);
int lastLabel = m_SegmentationItk->GetPixel(lastElementSegIndex );
// Check whether the labels belong to the white matter (which means, that the fibers ended early)
bool extendFront(false), extendEnd(false), retractFront(false), retractEnd(false);
extendFront = !IsNonWhiteMatterLabel( firstLabel );
extendEnd = !IsNonWhiteMatterLabel( lastLabel );
retractFront = IsBackgroundLabel( firstLabel );
retractEnd = IsBackgroundLabel( lastLabel );
//if( extendFront || extendEnd )
//{
//MBI_INFO << "Before Start: " << firstLabel << " at " << firstElementSegIndex[ 0 ] << " " << firstElementSegIndex[ 1 ] << " " << firstElementSegIndex[ 2 ] << " End: " << lastLabel << " at " << lastElementSegIndex[ 0 ] << " " << lastElementSegIndex[ 1 ] << " " << lastElementSegIndex[ 2 ];
//}
if ( extendFront )
{
std::vector< int > indexVectorOfPointsToUse;
//Use first two points for direction
indexVectorOfPointsToUse.push_back( 1 );
indexVectorOfPointsToUse.push_back( 0 );
// label and coordinate temp storage
int tempLabel( firstLabel );
itk::Index<3> tempIndex = firstElementSegIndex;
LinearExtensionUntilGreyMatter( indexVectorOfPointsToUse, singleTract, tempLabel, tempIndex );
firstLabel = tempLabel;
firstElementSegIndex = tempIndex;
}
if ( extendEnd )
{
std::vector< int > indexVectorOfPointsToUse;
//Use last two points for direction
indexVectorOfPointsToUse.push_back( singleTract->Size() - 2 );
indexVectorOfPointsToUse.push_back( singleTract->Size() - 1 );
// label and coordinate temp storage
int tempLabel( lastLabel );
itk::Index<3> tempIndex = lastElementSegIndex;
LinearExtensionUntilGreyMatter( indexVectorOfPointsToUse, singleTract, tempLabel, tempIndex );
lastLabel = tempLabel;
lastElementSegIndex = tempIndex;
}
if ( retractFront )
{
// label and coordinate temp storage
int tempLabel( firstLabel );
itk::Index<3> tempIndex = firstElementSegIndex;
RetractionUntilBrainMatter( true, singleTract, tempLabel, tempIndex );
firstLabel = tempLabel;
firstElementSegIndex = tempIndex;
}
if ( retractEnd )
{
// label and coordinate temp storage
int tempLabel( lastLabel );
itk::Index<3> tempIndex = lastElementSegIndex;
RetractionUntilBrainMatter( false, singleTract, tempLabel, tempIndex );
lastLabel = tempLabel;
lastElementSegIndex = tempIndex;
}
//if( extendFront || extendEnd )
//{
// MBI_INFO << "After Start: " << firstLabel << " at " << firstElementSegIndex[ 0 ] << " " << firstElementSegIndex[ 1 ] << " " << firstElementSegIndex[ 2 ] << " End: " << lastLabel << " at " << lastElementSegIndex[ 0 ] << " " << lastElementSegIndex[ 1 ] << " " << lastElementSegIndex[ 2 ];
//}
labelpair.first = firstLabel;
labelpair.second = lastLabel;
// Add property to property map
CreateNewNode( firstLabel, firstElementSegIndex, m_UseCoMCoordinates );
CreateNewNode( lastLabel, lastElementSegIndex, m_UseCoMCoordinates );
}
return labelpair;
}
mitk::ConnectomicsNetworkCreator::ImageLabelPairType mitk::ConnectomicsNetworkCreator::JustEndPointVerticesNoLabelTest( TractType::Pointer singleTract )
{
ImageLabelPairType labelpair;
{// Note: .fib image tracts are safed using index coordinates
mitk::Point3D firstElementFiberCoord, lastElementFiberCoord;
mitk::Point3D firstElementSegCoord, lastElementSegCoord;
itk::Index<3> firstElementSegIndex, lastElementSegIndex;
if( singleTract->front().Size() != 3 )
{
MBI_ERROR << mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_DIMENSION_NEED_3;
}
for( unsigned int index = 0; index < singleTract->front().Size(); index++ )
{
firstElementFiberCoord.SetElement( index, singleTract->front().GetElement( index ) );
lastElementFiberCoord.SetElement( index, singleTract->back().GetElement( index ) );
}
// convert from fiber index coordinates to segmentation index coordinates
FiberToSegmentationCoords( firstElementFiberCoord, firstElementSegCoord );
FiberToSegmentationCoords( lastElementFiberCoord, lastElementSegCoord );
for( int index = 0; index < 3; index++ )
{
firstElementSegIndex.SetElement( index, firstElementSegCoord.GetElement( index ) );
lastElementSegIndex.SetElement( index, lastElementSegCoord.GetElement( index ) );
}
int firstLabel = 1 * firstElementSegIndex[ 0 ] + 1000 * firstElementSegIndex[ 1 ] + 1000000 * firstElementSegIndex[ 2 ];
int lastLabel = 1 * firstElementSegIndex[ 0 ] + 1000 * firstElementSegIndex[ 1 ] + 1000000 * firstElementSegIndex[ 2 ];
labelpair.first = firstLabel;
labelpair.second = lastLabel;
// Add property to property map
CreateNewNode( firstLabel, firstElementSegIndex, m_UseCoMCoordinates );
CreateNewNode( lastLabel, lastElementSegIndex, m_UseCoMCoordinates );
}
return labelpair;
}
void mitk::ConnectomicsNetworkCreator::SupplyVertexWithInformation( ImageLabelType& label, VertexType& vertex )
{ // supply a vertex with the additional information belonging to the label
// TODO: Implement additional information acquisition
m_ConNetwork->SetLabel( vertex, m_LabelToNodePropertyMap.find( label )->second.label );
m_ConNetwork->SetCoordinates( vertex, m_LabelToNodePropertyMap.find( label )->second.coordinates );
}
std::string mitk::ConnectomicsNetworkCreator::LabelToString( ImageLabelType& label )
{
int tempInt = (int) label;
std::stringstream ss;//create a stringstream
std::string tempString;
ss << tempInt;//add number to the stream
tempString = ss.str();
return tempString;//return a string with the contents of the stream
}
mitk::ConnectomicsNetwork::Pointer mitk::ConnectomicsNetworkCreator::GetNetwork()
{
return m_ConNetwork;
}
void mitk::ConnectomicsNetworkCreator::FiberToSegmentationCoords( mitk::Point3D& fiberCoord, mitk::Point3D& segCoord )
{
mitk::Point3D tempPoint;
// convert from fiber index coordinates to segmentation index coordinates
m_FiberBundle->GetGeometry()->IndexToWorld( fiberCoord, tempPoint );
m_Segmentation->GetGeometry()->WorldToIndex( tempPoint, segCoord );
}
void mitk::ConnectomicsNetworkCreator::SegmentationToFiberCoords( mitk::Point3D& segCoord, mitk::Point3D& fiberCoord )
{
mitk::Point3D tempPoint;
// convert from fiber index coordinates to segmentation index coordinates
m_Segmentation->GetGeometry()->IndexToWorld( segCoord, tempPoint );
m_FiberBundle->GetGeometry()->WorldToIndex( tempPoint, fiberCoord );
}
bool mitk::ConnectomicsNetworkCreator::IsNonWhiteMatterLabel( int labelInQuestion )
{
bool isWhite( false );
isWhite = (
( labelInQuestion == freesurfer_Left_Cerebral_White_Matter ) ||
( labelInQuestion == freesurfer_Left_Cerebellum_White_Matter ) ||
( labelInQuestion == freesurfer_Right_Cerebral_White_Matter ) ||
( labelInQuestion == freesurfer_Right_Cerebellum_White_Matter )||
( labelInQuestion == freesurfer_Left_Cerebellum_Cortex ) ||
( labelInQuestion == freesurfer_Right_Cerebellum_Cortex ) ||
( labelInQuestion == freesurfer_Brain_Stem )
);
return !isWhite;
}
bool mitk::ConnectomicsNetworkCreator::IsBackgroundLabel( int labelInQuestion )
{
bool isBackground( false );
isBackground = ( labelInQuestion == 0 );
return isBackground;
}
void mitk::ConnectomicsNetworkCreator::LinearExtensionUntilGreyMatter(
std::vector<int> & indexVectorOfPointsToUse,
TractType::Pointer singleTract,
int & label,
itk::Index<3> & mitkIndex )
{
if( indexVectorOfPointsToUse.size() > singleTract->Size() )
{
MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_MORE_POINTS_THAN_PRESENT;
return;
}
if( indexVectorOfPointsToUse.size() < 2 )
{
MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ESTIMATING_LESS_THAN_2;
return;
}
for( unsigned int index( 0 ); index < indexVectorOfPointsToUse.size(); index++ )
{
if( indexVectorOfPointsToUse[ index ] < 0 )
{
MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ESTIMATING_BEYOND_START;
return;
}
if( (unsigned int)indexVectorOfPointsToUse[ index ] > singleTract->Size() )
{
MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ESTIMATING_BEYOND_END;
return;
}
}
mitk::Point3D startPoint, endPoint;
std::vector< double > differenceVector;
differenceVector.resize( singleTract->front().Size() );
{
// which points to use, currently only last two //TODO correct using all points
int endPointIndex = indexVectorOfPointsToUse.size() - 1;
int startPointIndex = indexVectorOfPointsToUse.size() - 2;
// convert to segmentation coords
mitk::Point3D startFiber, endFiber;
for( unsigned int index = 0; index < singleTract->front().Size(); index++ )
{
endFiber.SetElement( index, singleTract->GetElement( indexVectorOfPointsToUse[ endPointIndex ] ).GetElement( index ) );
startFiber.SetElement( index, singleTract->GetElement( indexVectorOfPointsToUse[ startPointIndex ] ).GetElement( index ) );
}
FiberToSegmentationCoords( endFiber, endPoint );
FiberToSegmentationCoords( startFiber, startPoint );
// calculate straight line
for( unsigned int index = 0; index < singleTract->front().Size(); index++ )
{
differenceVector[ index ] = endPoint.GetElement( index ) - startPoint.GetElement( index );
}
// normalizing direction vector
double length( 0.0 );
double sum( 0.0 );
for( unsigned int index = 0; index < differenceVector.size() ; index++ )
{
sum = sum + differenceVector[ index ] * differenceVector[ index ];
}
length = std::sqrt( sum );
for( unsigned int index = 0; index < differenceVector.size() ; index++ )
{
differenceVector[ index ] = differenceVector[ index ] / length;
}
// follow line until first non white matter label
itk::Index<3> tempIndex;
int tempLabel( label );
bool keepOn( true );
itk::ImageRegion<3> itkRegion = m_SegmentationItk->GetLargestPossibleRegion();
for( int parameter( 0 ) ; keepOn ; parameter++ )
{
if( parameter > 1000 )
{
MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_DID_NOT_FIND_WHITE;
break;
}
for( int index( 0 ); index < 3; index++ )
{
tempIndex.SetElement( index, endPoint.GetElement( index ) + parameter * differenceVector[ index ] );
}
if( itkRegion.IsInside( tempIndex ) )
{
tempLabel = m_SegmentationItk->GetPixel( tempIndex );
}
else
{
tempLabel = -1;
}
if( IsNonWhiteMatterLabel( tempLabel ) )
{
if( tempLabel < 1 )
{
keepOn = false;
//MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_NOT_EXTEND_TO_WHITE;
}
else
{
label = tempLabel;
mitkIndex = tempIndex;
keepOn = false;
}
}
}
}
}
void mitk::ConnectomicsNetworkCreator::RetractionUntilBrainMatter( bool retractFront, TractType::Pointer singleTract,
int & label, itk::Index<3> & mitkIndex )
{
int retractionStartIndex( singleTract->Size() - 1 );
int retractionStepIndexSize( -1 );
int retractionTerminationIndex( 0 );
if( retractFront )
{
retractionStartIndex = 0;
retractionStepIndexSize = 1;
retractionTerminationIndex = singleTract->Size() - 1;
}
int currentRetractionIndex = retractionStartIndex;
bool keepRetracting( true );
mitk::Point3D currentPoint, nextPoint;
std::vector< double > differenceVector;
differenceVector.resize( singleTract->front().Size() );
while( keepRetracting && ( currentRetractionIndex != retractionTerminationIndex ) )
{
// convert to segmentation coords
mitk::Point3D currentPointFiberCoord, nextPointFiberCoord;
for( unsigned int index = 0; index < singleTract->front().Size(); index++ )
{
currentPointFiberCoord.SetElement( index, singleTract->GetElement( currentRetractionIndex ).GetElement( index ) );
nextPointFiberCoord.SetElement( index, singleTract->GetElement( currentRetractionIndex + retractionStepIndexSize ).GetElement( index ) );
}
FiberToSegmentationCoords( currentPointFiberCoord, currentPoint );
FiberToSegmentationCoords( nextPointFiberCoord, nextPoint );
// calculate straight line
for( unsigned int index = 0; index < singleTract->front().Size(); index++ )
{
differenceVector[ index ] = nextPoint.GetElement( index ) - currentPoint.GetElement( index );
}
// calculate length of direction vector
double length( 0.0 );
double sum( 0.0 );
for( unsigned int index = 0; index < differenceVector.size() ; index++ )
{
sum = sum + differenceVector[ index ] * differenceVector[ index ];
}
length = std::sqrt( sum );
// retract
itk::Index<3> tempIndex;
int tempLabel( label );
for( int parameter( 0 ) ; parameter < length ; parameter++ )
{
for( int index( 0 ); index < 3; index++ )
{
tempIndex.SetElement( index,
currentPoint.GetElement( index ) + ( 1.0 + parameter ) / ( 1.0 + length ) * differenceVector[ index ] );
}
tempLabel = m_SegmentationItk->GetPixel( tempIndex );
if( !IsBackgroundLabel( tempLabel ) )
{
// check whether result is within the search space
{
mitk::Point3D endPoint, foundPointSegmentation, foundPointFiber;
for( unsigned int index = 0; index < singleTract->front().Size(); index++ )
{
// this is in fiber (world) coordinates
endPoint.SetElement( index, singleTract->GetElement( retractionStartIndex ).GetElement( index ) );
}
for( int index( 0 ); index < 3; index++ )
{
foundPointSegmentation.SetElement( index,
currentPoint.GetElement( index ) + ( 1.0 + parameter ) / ( 1.0 + length ) * differenceVector[ index ] );
}
SegmentationToFiberCoords( foundPointSegmentation, foundPointFiber );
std::vector< double > finalDistance;
finalDistance.resize( singleTract->front().Size() );
for( unsigned int index = 0; index < singleTract->front().Size(); index++ )
{
finalDistance[ index ] = foundPointFiber.GetElement( index ) - endPoint.GetElement( index );
}
// calculate length of direction vector
double finalLength( 0.0 );
double finalSum( 0.0 );
for( unsigned int index = 0; index < finalDistance.size() ; index++ )
{
finalSum = finalSum + finalDistance[ index ] * finalDistance[ index ];
}
finalLength = std::sqrt( finalSum );
if( finalLength > m_EndPointSearchRadius )
{
// the found point was not within the search space
return;
}
}
label = tempLabel;
mitkIndex = tempIndex;
return;
}
// hit next point without finding brain matter
currentRetractionIndex = currentRetractionIndex + retractionStepIndexSize;
if( ( currentRetractionIndex < 1 ) || ( (unsigned int)currentRetractionIndex > ( singleTract->Size() - 2 ) ) )
{
keepRetracting = false;
}
}
}
}
void mitk::ConnectomicsNetworkCreator::CalculateCenterOfMass()
{
const int dimensions = 3;
int max = m_Segmentation->GetStatistics()->GetScalarValueMax();
int min = m_Segmentation->GetStatistics()->GetScalarValueMin();
int range = max - min +1;
// each label owns a vector of coordinates
std::vector< std::vector< std::vector< double> > > coordinatesPerLabelVector;
coordinatesPerLabelVector.resize( range );
itk::ImageRegionIteratorWithIndex<ITKImageType> it_itkImage( m_SegmentationItk, m_SegmentationItk->GetLargestPossibleRegion() );
for( it_itkImage.GoToBegin(); !it_itkImage.IsAtEnd(); ++it_itkImage )
{
std::vector< double > coordinates;
coordinates.resize(dimensions);
itk::Index< dimensions > index = it_itkImage.GetIndex();
for( int loop(0); loop < dimensions; loop++)
{
coordinates.at( loop ) = index.GetElement( loop );
}
// add the coordinates to the corresponding label vector
coordinatesPerLabelVector.at( it_itkImage.Value() - min ).push_back( coordinates );
}
for(int currentIndex(0), currentLabel( min ); currentIndex < range; currentIndex++, currentLabel++ )
{
std::vector< double > currentCoordinates;
currentCoordinates.resize(dimensions);
int numberOfPoints = coordinatesPerLabelVector.at( currentIndex ).size();
std::vector< double > sumCoords;
sumCoords.resize( dimensions );
for( int loop(0); loop < numberOfPoints; loop++ )
{
for( int loopDimension( 0 ); loopDimension < dimensions; loopDimension++ )
{
sumCoords.at( loopDimension ) += coordinatesPerLabelVector.at( currentIndex ).at( loop ).at( loopDimension );
}
}
for( int loopDimension( 0 ); loopDimension < dimensions; loopDimension++ )
{
currentCoordinates.at( loopDimension ) = sumCoords.at( loopDimension ) / numberOfPoints;
}
m_LabelsToCoordinatesMap.insert( std::pair< int, std::vector<double> >( currentLabel, currentCoordinates ) );
}
//can now use center of mass coordinates
m_UseCoMCoordinates = true;
}
std::vector< double > mitk::ConnectomicsNetworkCreator::GetCenterOfMass( int label )
{
// if label is not known, warn
if( ! ( m_LabelsToCoordinatesMap.count( label ) > 0 ) )
{
MITK_ERROR << "Label " << label << " not found. Could not return coordinates.";
std::vector< double > nullVector;
nullVector.resize(3);
return nullVector;
}
//return associated coordinates
return m_LabelsToCoordinatesMap.find( label )->second;
}
void mitk::ConnectomicsNetworkCreator::CreateNewNode( int label, itk::Index<3> index, bool useCoM )
{
// Only create node if it does not exist yet
if( ! ( m_LabelToNodePropertyMap.count( label ) > 0 ) )
{
NetworkNode newNode;
newNode.coordinates.resize( 3 );
if( !useCoM )
{
for( unsigned int loop = 0; loop < newNode.coordinates.size() ; loop++ )
{
newNode.coordinates[ loop ] = index[ loop ] ;
}
}
else
{
std::vector<double> labelCoords = GetCenterOfMass( label );
for( unsigned int loop = 0; loop < newNode.coordinates.size() ; loop++ )
{
newNode.coordinates[ loop ] = labelCoords.at( loop ) ;
}
}
newNode.label = LabelToString( label );
m_LabelToNodePropertyMap.insert( std::pair< ImageLabelType, NetworkNode >( label, newNode ) );
}
}
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkCreator.h b/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkCreator.h
index 4af8649..afcf38f 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkCreator.h
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkCreator.h
@@ -1,246 +1,246 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkConnectomicsNetworkCreator_h
#define mitkConnectomicsNetworkCreator_h
#include <itkObject.h>
#include <itkObjectFactory.h>
#include <itkMacro.h>
#include "mitkCommon.h"
#include "mitkImage.h"
#include "mitkFiberBundle.h"
#include "mitkConnectomicsNetwork.h"
#include <MitkConnectomicsExports.h>
namespace mitk
{
/**
* \brief Creates connectomics networks from fibers and parcellation
*
* This class needs a parcellation image and a fiber image to be set. Then you can create
* a connectomics network from the two, using different strategies.
*/
class MITKCONNECTOMICS_EXPORT ConnectomicsNetworkCreator : public itk::Object
{
public:
/** Enum for different ways to create the mapping from fibers to network */
enum MappingStrategy
{
EndElementPosition,
EndElementPositionAvoidingWhiteMatter,
JustEndPointVerticesNoLabel,
PrecomputeAndDistance
};
/** Standard class typedefs. */
/** Method for creation through the object factory. */
mitkClassMacroItkParent(ConnectomicsNetworkCreator, itk::Object);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Type for Images **/
typedef itk::Image<int, 3 > ITKImageType;
/** Types for the standardized Tract **/
typedef itk::Point<float,3> PointType;
typedef itk::VectorContainer<unsigned int, PointType> TractType;
typedef itk::VectorContainer< unsigned int, TractType::Pointer > TractContainerType; //init via smartpointer
/** Types for Network **/
typedef mitk::ConnectomicsNetwork::VertexDescriptorType VertexType;
typedef mitk::ConnectomicsNetwork::EdgeDescriptorType EdgeType;
typedef mitk::ConnectomicsNetwork::NetworkNode NetworkNode;
typedef std::pair< VertexType, VertexType > ConnectionType;
/** Types for labels **/
typedef int ImageLabelType;
typedef std::pair< ImageLabelType, ImageLabelType > ImageLabelPairType;
/** Given a fiber bundle and a parcellation are set, this will create a network from both */
void CreateNetworkFromFibersAndSegmentation();
void SetFiberBundle(mitk::FiberBundle::Pointer fiberBundle);
void SetSegmentation(mitk::Image::Pointer segmentation);
mitk::ConnectomicsNetwork::Pointer GetNetwork();
itkSetMacro(MappingStrategy, MappingStrategy);
itkSetMacro(EndPointSearchRadius, double);
itkSetMacro(ZeroLabelInvalid, bool);
/** \brief Calculate the locations of vertices
*
* Calculate the center of mass for each label and store the information. This will need a set parcellation image.
* Unless this function is called the first location where a label is encountered will be used. After calling this function
* the center of mass will be used instead.
*/
void CalculateCenterOfMass();
protected:
//////////////////// Functions ///////////////////////
ConnectomicsNetworkCreator();
ConnectomicsNetworkCreator( mitk::Image::Pointer segmentation, mitk::FiberBundle::Pointer fiberBundle );
~ConnectomicsNetworkCreator() override;
/** Add a connection to the network */
void AddConnectionToNetwork(ConnectionType newConnection, double fiber_count);
/** Determine if a label is already identified with a vertex, otherwise create a new one */
VertexType ReturnAssociatedVertexForLabel( ImageLabelType label );
/** Return the vertexes associated with a pair of labels */
ConnectionType ReturnAssociatedVertexPairForLabelPair( ImageLabelPairType labelpair );
/** Return the pair of labels which identify the areas connected by a single fiber */
ImageLabelPairType ReturnLabelForFiberTract( TractType::Pointer singleTract, MappingStrategy strategy );
/** Assign the additional information which should be part of the vertex */
void SupplyVertexWithInformation( ImageLabelType& label, VertexType& vertex );
/** Create a string from the label */
std::string LabelToString( ImageLabelType& label );
/** Check whether the label in question belongs to white matter according to the freesurfer table */
bool IsNonWhiteMatterLabel( int labelInQuestion );
/** Check whether the label in question belongs to background according to the freesurfer table */
bool IsBackgroundLabel( int labelInQuestion );
/** Extend a straight line through the given points and look for the first non white matter label
It will try extend in the direction of the points in the vector so a vector {B,C} will result in
extending from C in the direction C-B */
void LinearExtensionUntilGreyMatter( std::vector<int> & indexVectorOfPointsToUse, TractType::Pointer singleTract,
int & label, itk::Index<3> & mitkIndex );
/** Retract fiber until the first brain matter label is hit
The bool parameter controls whether the front or the end is retracted */
void RetractionUntilBrainMatter( bool retractFront, TractType::Pointer singleTract,
int & label, itk::Index<3> & mitkIndex );
/** \brief Get the location of the center of mass for a specific label
* This can throw an exception if the label is not found.
*/
std::vector< double > GetCenterOfMass( int label );
/** \brief Creates a new node
*
* A new node will be created, using the label and either the supplied coordinates
* or the center of mass coordinates, depending on the supplied bool.
*/
void CreateNewNode( int label, itk::Index<3>, bool useIndex );
///////// Mapping strategies //////////
/** Use the position of the end and starting element only to map to labels
Map a fiber to a vertex by taking the value of the parcellation image at the same world coordinates as the last
and first element of the tract.*/
ImageLabelPairType EndElementPositionLabel( TractType::Pointer singleTract );
/** Map by distance between elements and vertices depending on their volume
First go through the parcellation and compute the coordinates of the future vertices. Assign a radius according on their volume.
Then map an edge to a label by considering the nearest vertices and comparing the distance to them to their radii. */
ImageLabelPairType PrecomputeVertexLocationsBySegmentation( TractType::Pointer singleTract );
/** Use the position of the end and starting element only to map to labels
Just take first and last position, no labelling, nothing */
ImageLabelPairType JustEndPointVerticesNoLabelTest( TractType::Pointer singleTract );
/** Use the position of the end and starting element unless it is in white matter, then search for nearby parcellation to map to labels
Map a fiber to a vertex by taking the value of the parcellation image at the same world coordinates as the last
and first element of the tract. If this happens to be white matter, then try to extend the fiber in a line and
take the first non-white matter parcel, that is intersected. */
ImageLabelPairType EndElementPositionLabelAvoidingWhiteMatter( TractType::Pointer singleTract );
///////// Conversions //////////
/** Convert fiber index to segmentation index coordinates */
void FiberToSegmentationCoords( mitk::Point3D& fiberCoord, mitk::Point3D& segCoord );
/** Convert segmentation index to fiber index coordinates */
void SegmentationToFiberCoords( mitk::Point3D& segCoord, mitk::Point3D& fiberCoord );
/////////////////////// Variables ////////////////////////
mitk::FiberBundle::Pointer m_FiberBundle;
mitk::Image::Pointer m_Segmentation;
ITKImageType::Pointer m_SegmentationItk;
// the graph itself
mitk::ConnectomicsNetwork::Pointer m_ConNetwork;
// the id counter
int idCounter;
// the map mapping labels to vertices
std::map< ImageLabelType, VertexType > m_LabelToVertexMap;
// mapping labels to additional information
std::map< ImageLabelType, NetworkNode > m_LabelToNodePropertyMap;
// toggles whether edges between a node and itself can exist
bool allowLoops;
// toggles whether to use the center of mass coordinates
bool m_UseCoMCoordinates;
// stores the coordinates of labels
std::map< int, std::vector< double> > m_LabelsToCoordinatesMap;
// the straty to use for mapping
MappingStrategy m_MappingStrategy;
// search radius for finding a non white matter/background area. Should be in mm
double m_EndPointSearchRadius;
// toggles whether a node with the label 0 may be present
bool m_ZeroLabelInvalid;
// used internally to communicate a connection should not be added if the a problem
// is encountered while adding it
bool m_AbortConnection;
//////////////////////// IDs ////////////////////////////
// These IDs are the freesurfer ids used in parcellation
static const int freesurfer_Left_Cerebral_White_Matter = 2;
static const int freesurfer_Left_Cerebellum_White_Matter = 7;
static const int freesurfer_Left_Cerebellum_Cortex = 8;
static const int freesurfer_Brain_Stem = 16;
static const int freesurfer_Right_Cerebral_White_Matter = 41;
static const int freesurfer_Right_Cerebellum_White_Matter = 46;
static const int freesurfer_Right_Cerebellum_Cortex = 47;
};
}// end namespace mitk
#endif // _mitkConnectomicsNetworkCreator_H_INCLUDED
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkThresholder.cpp b/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkThresholder.cpp
index 31a97ac..c0d0729 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkThresholder.cpp
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkThresholder.cpp
@@ -1,251 +1,251 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsNetworkThresholder.h"
#include <mitkConnectomicsStatisticsCalculator.h>
#include "vnl/vnl_random.h"
mitk::ConnectomicsNetworkThresholder::ConnectomicsNetworkThresholder()
: m_Network( nullptr )
, m_ThresholdingScheme( mitk::ConnectomicsNetworkThresholder::ThresholdBased )
, m_TargetThreshold( 0.0 )
, m_TargetDensity( 1.0 )
{
}
mitk::ConnectomicsNetworkThresholder::~ConnectomicsNetworkThresholder()
{
}
mitk::ConnectomicsNetwork::Pointer mitk::ConnectomicsNetworkThresholder::GetThresholdedNetwork()
{
mitk::ConnectomicsNetwork::Pointer result;
if( ! CheckValidity() )
{
MITK_ERROR << "Aborting";
return m_Network;
}
switch(m_ThresholdingScheme)
{
case RandomRemovalOfWeakest :
{
result = ThresholdByRandomRemoval( m_Network, m_TargetDensity );
break;
}
case LargestLowerThanDensity :
{
result = ThresholdBelowDensity( m_Network, m_TargetDensity );
break;
}
case ThresholdBased :
{
result = Threshold( m_Network, m_TargetThreshold );
break;
}
default :
{
MITK_ERROR << "Specified unknown Thresholding Scheme";
result = m_Network;
}
}
return result;
}
bool mitk::ConnectomicsNetworkThresholder::CheckValidity()
{
bool valid(true);
if( m_Network.IsNull() )
{
valid = false;
MITK_ERROR << "Network is nullptr.";
}
switch(m_ThresholdingScheme)
{
case RandomRemovalOfWeakest :
case LargestLowerThanDensity :
{
if( m_TargetDensity < 0.0 )
{
valid = false;
MITK_ERROR << "Target density is negative.";
}
if( m_TargetDensity > 1.0 )
{
valid = false;
MITK_ERROR << "Target density is larger than 1.";
}
break;
}
case ThresholdBased :
{
if( m_TargetThreshold < 0 )
{
valid = false;
MITK_ERROR << "Target threshold is negative.";
}
break;
}
default :
{
valid = false;
MITK_ERROR << "Specified unknown Thresholding Scheme";
}
}
return valid;
}
mitk::ConnectomicsNetwork::Pointer mitk::ConnectomicsNetworkThresholder::ThresholdByRandomRemoval( mitk::ConnectomicsNetwork::Pointer input, double targetDensity )
{
mitk::ConnectomicsNetwork::Pointer result = mitk::ConnectomicsNetwork::New();
result->ImportNetwort( input );
mitk::ConnectomicsStatisticsCalculator::Pointer calculator = mitk::ConnectomicsStatisticsCalculator::New();
calculator->SetNetwork( result );
calculator->Update();
//the random number generator
vnl_random rng( (unsigned int) rand() );
bool notBelow( targetDensity < calculator->GetConnectionDensity() );
double minWeight( result->GetMaximumWeight() );
int count( 0 );
while( notBelow )
{
// result = Threshold( result, loop );
std::vector< EdgeDescriptorType > candidateVector;
minWeight = result->GetMaximumWeight();
count = 0;
// determine minimum weight and number of edges having that weight
NetworkType* boostGraph = result->GetBoostGraph();
EdgeIteratorType iterator, end;
// sets iterator to start end end to end
boost::tie(iterator, end) = boost::edges( *boostGraph );
for ( ; iterator != end; ++iterator)
{
double tempWeight;
// the value of an iterator is a descriptor
tempWeight = (*boostGraph)[ *iterator ].fiber_count;
if( mitk::Equal( tempWeight, minWeight ) )
{
candidateVector.push_back( *iterator );
count++;
}
else if( tempWeight < minWeight )
{
candidateVector.clear();
candidateVector.push_back( *iterator );
minWeight = tempWeight;
count = 1;
}
}
// Which to delete
int deleteNumber( rng.lrand32( count - 1 ) );
boost::remove_edge( candidateVector.at( deleteNumber ), *boostGraph );
calculator->SetNetwork( result );
calculator->Update();
notBelow = targetDensity < calculator->GetConnectionDensity();
}
result->UpdateIDs();
return result;
}
mitk::ConnectomicsNetwork::Pointer mitk::ConnectomicsNetworkThresholder::ThresholdBelowDensity( mitk::ConnectomicsNetwork::Pointer input, double targetDensity )
{
mitk::ConnectomicsNetwork::Pointer result = mitk::ConnectomicsNetwork::New();
result->ImportNetwort( input );
mitk::ConnectomicsStatisticsCalculator::Pointer calculator = mitk::ConnectomicsStatisticsCalculator::New();
calculator->SetNetwork( result );
calculator->Update();
bool notBelow( targetDensity < calculator->GetConnectionDensity() );
for( int loop( 1 ); notBelow; loop++ )
{
result = Threshold( result, loop );
calculator->SetNetwork( result );
calculator->Update();
notBelow = targetDensity < calculator->GetConnectionDensity();
}
return result;
}
mitk::ConnectomicsNetwork::Pointer mitk::ConnectomicsNetworkThresholder::Threshold( mitk::ConnectomicsNetwork::Pointer input, double targetThreshold )
{
mitk::ConnectomicsNetwork::Pointer result = mitk::ConnectomicsNetwork::New();
result->ImportNetwort( input );
NetworkType* boostGraph = result->GetBoostGraph();
EdgeIteratorType iterator, end;
// set to true if iterators are invalidated by deleting an edge
bool edgeHasBeenRemoved( true );
// if no edge has been removed in the last loop, we are done
while( edgeHasBeenRemoved )
{
edgeHasBeenRemoved = false;
// sets iterator to start and end to end
boost::tie(iterator, end) = boost::edges( *boostGraph );
bool endReached( false );
while( !edgeHasBeenRemoved && !endReached )
{
if( iterator != end )
{
// If the edge is below the target threshold it is deleted
if( (*boostGraph)[ *iterator ].fiber_count < targetThreshold )
{
edgeHasBeenRemoved = true;
// this invalidates all iterators
boost::remove_edge( *iterator, *boostGraph );
}
else
{
++iterator;
}
}
else
{
endReached = true;
}
}
}
result->UpdateIDs();
return result;
}
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkThresholder.h b/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkThresholder.h
index 2187368..5304952 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkThresholder.h
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsNetworkThresholder.h
@@ -1,111 +1,111 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkConnectomicsNetworkThresholder_h
#define mitkConnectomicsNetworkThresholder_h
#include <itkObject.h>
#include <itkObjectFactory.h>
#include <itkMacro.h>
#include "mitkCommon.h"
#include <MitkConnectomicsExports.h>
#include <mitkConnectomicsNetwork.h>
namespace mitk
{
/**
* \brief A class for thresholding connectomics networks */
class MITKCONNECTOMICS_EXPORT ConnectomicsNetworkThresholder : public itk::Object
{
public:
/** Standard class typedefs. */
/** Method for creation through the object factory. */
mitkClassMacroItkParent(ConnectomicsNetworkThresholder, itk::Object);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
// Typedefs
typedef mitk::ConnectomicsNetwork::NetworkType NetworkType;
typedef mitk::ConnectomicsNetwork::VertexDescriptorType VertexDescriptorType;
typedef mitk::ConnectomicsNetwork::EdgeDescriptorType EdgeDescriptorType;
typedef boost::graph_traits<NetworkType>::vertex_iterator VertexIteratorType;
typedef boost::graph_traits<NetworkType>::edge_iterator EdgeIteratorType;
typedef boost::graph_traits<NetworkType>::adjacency_iterator AdjacencyIteratorType;
typedef std::map<EdgeDescriptorType, int> EdgeIndexStdMapType;
typedef boost::associative_property_map< EdgeIndexStdMapType > EdgeIndexMapType;
typedef std::map<VertexDescriptorType, int> VertexIndexStdMapType;
typedef boost::associative_property_map< VertexIndexStdMapType > VertexIndexMapType;
/** \brief Possible schemes for thresholding the network
*
* \li \c RandomRemovalOfWeakest: Randomly remove one of the weakest edges until a given density is reached
* \li \c LargestLowerThanDensity: Remove all edges of the lowest weight, repeat until below the specified density
* \li \c ThresholdBased: Remove all edges with a weight of threshold and lower. This will not take density information into account.
*/
enum ThresholdingSchemes
{
RandomRemovalOfWeakest,
LargestLowerThanDensity,
ThresholdBased
};
// Set/Get Macros
itkSetObjectMacro( Network, mitk::ConnectomicsNetwork );
itkSetMacro( ThresholdingScheme, ThresholdingSchemes );
itkSetMacro( TargetThreshold, double );
itkSetMacro( TargetDensity, double );
itkGetObjectMacro( Network, mitk::ConnectomicsNetwork );
itkGetMacro( ThresholdingScheme, ThresholdingSchemes );
itkGetMacro( TargetThreshold, double );
itkGetMacro( TargetDensity, double );
/** \brief Apply thresholding scheme and get resulting network */
mitk::ConnectomicsNetwork::Pointer GetThresholdedNetwork();
protected:
//////////////////// Functions ///////////////////////
ConnectomicsNetworkThresholder();
~ConnectomicsNetworkThresholder() override;
mitk::ConnectomicsNetwork::Pointer ThresholdByRandomRemoval( mitk::ConnectomicsNetwork::Pointer input, double targetDensity );
mitk::ConnectomicsNetwork::Pointer ThresholdBelowDensity( mitk::ConnectomicsNetwork::Pointer input, double targetDensity );
mitk::ConnectomicsNetwork::Pointer Threshold( mitk::ConnectomicsNetwork::Pointer input, double targetThreshold );
// Returns false if parameter combination is invalid
bool CheckValidity();
/////////////////////// Variables ////////////////////////
// The connectomics network, which is used for statistics calculation
mitk::ConnectomicsNetwork::Pointer m_Network;
// The thresholding scheme to be used
ThresholdingSchemes m_ThresholdingScheme;
double m_TargetThreshold;
double m_TargetDensity;
};
}// end namespace mitk
#endif // mitkConnectomicsNetworkThresholder_h
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsShortestPathHistogram.cpp b/Modules/Connectomics/Algorithms/mitkConnectomicsShortestPathHistogram.cpp
index 2be8c2f..56477de 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsShortestPathHistogram.cpp
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsShortestPathHistogram.cpp
@@ -1,193 +1,193 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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<mitkConnectomicsShortestPathHistogram.h>
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4172)
#endif
#include <boost/graph/dijkstra_shortest_paths.hpp>
#ifdef _MSC_VER
# pragma warning(pop)
#endif
#include "mitkConnectomicsConstantsManager.h"
mitk::ConnectomicsShortestPathHistogram::ConnectomicsShortestPathHistogram()
: m_Mode( UnweightedUndirectedMode )
, m_EverythingConnected( true )
{
m_Subject = "Shortest path";
}
mitk::ConnectomicsShortestPathHistogram::~ConnectomicsShortestPathHistogram()
{
}
void mitk::ConnectomicsShortestPathHistogram::SetShortestPathCalculationMode( const mitk::ConnectomicsShortestPathHistogram::ShortestPathCalculationMode & mode)
{
m_Mode = mode;
}
mitk::ConnectomicsShortestPathHistogram::ShortestPathCalculationMode mitk::ConnectomicsShortestPathHistogram::GetShortestPathCalculationMode()
{
return m_Mode;
}
void mitk::ConnectomicsShortestPathHistogram::ComputeFromConnectomicsNetwork( ConnectomicsNetwork* source )
{
NetworkType* boostGraph = source->GetBoostGraph();
switch( m_Mode )
{
case UnweightedUndirectedMode:
{
CalculateUnweightedUndirectedShortestPaths( boostGraph );
break;
}
case WeightedUndirectedMode:
{
CalculateWeightedUndirectedShortestPaths( boostGraph );
break;
}
}
ConvertDistanceMapToHistogram();
}
void mitk::ConnectomicsShortestPathHistogram::CalculateUnweightedUndirectedShortestPaths( NetworkType* boostGraph )
{
std::vector< DescriptorType > predecessorMap( boost::num_vertices( *boostGraph ) );
int numberOfNodes( boost::num_vertices( *boostGraph ) );
m_DistanceMatrix.resize( numberOfNodes );
for(unsigned int index(0); index < m_DistanceMatrix.size(); index++ )
{
m_DistanceMatrix[ index ].resize( numberOfNodes );
}
IteratorType iterator, end;
boost::tie(iterator, end) = boost::vertices( *boostGraph );
for ( int index(0) ; iterator != end; ++iterator, index++)
{
boost::dijkstra_shortest_paths(*boostGraph, *iterator, boost::predecessor_map(&predecessorMap[ 0 ]).distance_map(&m_DistanceMatrix[ index ][ 0 ]).weight_map( boost::get( &mitk::ConnectomicsNetwork::NetworkEdge::edge_weight ,*boostGraph ) ) ) ;
}
}
void mitk::ConnectomicsShortestPathHistogram::CalculateWeightedUndirectedShortestPaths( NetworkType* /*boostGraph*/ )
{
MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_UNIMPLEMENTED_FEATURE;
}
void mitk::ConnectomicsShortestPathHistogram::ConvertDistanceMapToHistogram()
{
// get the longest path between any two nodes in the network
// we assume that no nodes are farther apart than there are nodes,
// this is to filter unconnected nodes
int longestPath( 0 );
int numberOfNodes( m_DistanceMatrix.size() );
m_EverythingConnected = true;
for(unsigned int index(0); index < m_DistanceMatrix.size(); index++ )
{
for(unsigned int innerIndex(0); innerIndex < m_DistanceMatrix[ index ].size(); innerIndex++ )
{
if( m_DistanceMatrix[ index ][ innerIndex ] > longestPath )
{
if( m_DistanceMatrix[ index ][ innerIndex ] < numberOfNodes )
{
longestPath = m_DistanceMatrix[ index ][ innerIndex ];
}
else
{
// these nodes are not connected
m_EverythingConnected = false;
}
}
}
}
m_HistogramVector.resize( longestPath + 1 );
for(unsigned int index(0); index < m_DistanceMatrix.size(); index++ )
{
for( unsigned int innerIndex(0); innerIndex < m_DistanceMatrix[ index ].size(); innerIndex++ )
{
if( m_DistanceMatrix[ index ][ innerIndex ] < numberOfNodes )
{
m_HistogramVector[ m_DistanceMatrix[ index ][ innerIndex ] ]++;
}
}
}
// correct for every path being counted twice
for( unsigned int index(1); index < m_HistogramVector.size(); index++ )
{
m_HistogramVector[ index ] = m_HistogramVector[ index ] / 2;
}
// correct for every node being distance zero to itself
if( m_HistogramVector[ 0 ] >= numberOfNodes )
{
m_HistogramVector[ 0 ] = m_HistogramVector[ 0 ] - numberOfNodes;
}
else
{
MBI_WARN << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ZERO_DISTANCE_NODES;
}
UpdateYMax();
this->m_Valid = true;
}
double mitk::ConnectomicsShortestPathHistogram::GetEfficiency()
{
if( !this->m_Valid )
{
MBI_INFO << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_CAN_NOT_COMPUTE_EFFICIENCY << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_NETWORK_NOT_VALID;
return 0.0;
}
if( !m_EverythingConnected )
{ // efficiency of disconnected graphs is 0
MBI_INFO << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_NETWORK_DISCONNECTED;
return 0.0;
}
double efficiency( 0.0 );
double overallDistance( 0.0 );
double numberOfPairs( 0.0 );
// add up all distances
for( unsigned int index(0); index < m_HistogramVector.size(); index++ )
{
overallDistance = overallDistance + m_HistogramVector[ index ] * index;
numberOfPairs = numberOfPairs + m_HistogramVector[ index ];
}
// efficiency = 1 / averageDistance = 1 / ( overallDistance / numberofPairs )
efficiency = numberOfPairs / overallDistance;
return efficiency;
}
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsShortestPathHistogram.h b/Modules/Connectomics/Algorithms/mitkConnectomicsShortestPathHistogram.h
index c8639ce..37656f4 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsShortestPathHistogram.h
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsShortestPathHistogram.h
@@ -1,86 +1,86 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_ConnectomicsShortestPathHistogram_H
#define _MITK_ConnectomicsShortestPathHistogram_H
#include<mitkConnectomicsHistogramBase.h>
#include <MitkConnectomicsExports.h>
namespace mitk {
/**
* \brief A class to calculate and store the shortest path between each pair of nodes */
class MITKCONNECTOMICS_EXPORT ConnectomicsShortestPathHistogram : public mitk::ConnectomicsHistogramBase
{
public:
/** Enum for different ways to calculate shortest paths */
enum ShortestPathCalculationMode
{
UnweightedUndirectedMode,
WeightedUndirectedMode
};
ConnectomicsShortestPathHistogram();
~ConnectomicsShortestPathHistogram() override;
/** Set the calucaltion mode */
void SetShortestPathCalculationMode( const ShortestPathCalculationMode & );
/** Get the calculation mode */
ShortestPathCalculationMode GetShortestPathCalculationMode();
/** Get efficiency */
double GetEfficiency();
protected:
/* Typedefs */
typedef mitk::ConnectomicsNetwork::NetworkType NetworkType;
typedef boost::graph_traits< NetworkType >::vertex_descriptor DescriptorType;
typedef boost::graph_traits< NetworkType >::vertex_iterator IteratorType;
/** @brief Creates a new histogram from the network source. */
void ComputeFromConnectomicsNetwork( ConnectomicsNetwork* source ) override;
/** Calculate shortest paths ignoring the weight of the edges */
void CalculateUnweightedUndirectedShortestPaths( NetworkType* boostGraph );
/** Calculate shortest paths taking into consideration the weight of the edges */
void CalculateWeightedUndirectedShortestPaths( NetworkType* boostGraph );
/** Converts the distance map to a histogram */
void ConvertDistanceMapToHistogram();
/** Stores which mode has been selected for shortest path calculation */
ShortestPathCalculationMode m_Mode;
/** Stores the shortest paths between the nodes */
std::vector< std::vector< int > > m_DistanceMatrix;
/** Stores, whether the graph has disconnected components */
bool m_EverythingConnected;
};
}
#endif /* _MITK_ConnectomicsShortestPathHistogram_H */
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionBase.cpp b/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionBase.cpp
index ba06dee..b8fbd86 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionBase.cpp
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionBase.cpp
@@ -1,25 +1,25 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsSimulatedAnnealingCostFunctionBase.h"
mitk::ConnectomicsSimulatedAnnealingCostFunctionBase::ConnectomicsSimulatedAnnealingCostFunctionBase()
{
}
mitk::ConnectomicsSimulatedAnnealingCostFunctionBase::~ConnectomicsSimulatedAnnealingCostFunctionBase()
{
}
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionBase.h b/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionBase.h
index 68c0ba9..f725695 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionBase.h
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionBase.h
@@ -1,55 +1,55 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkConnectomicsSimulatedAnnealingCostFunctionBase_h
#define mitkConnectomicsSimulatedAnnealingCostFunctionBase_h
#include <itkObject.h>
#include <itkObjectFactory.h>
#include <itkMacro.h>
#include "mitkCommon.h"
#include <MitkConnectomicsExports.h>
namespace mitk
{
/**
* \brief A generic base class for cost functions for use in simulated annealing */
class MITKCONNECTOMICS_EXPORT ConnectomicsSimulatedAnnealingCostFunctionBase : public itk::Object
{
public:
/** Standard class typedefs. */
/** Method for creation through the object factory. */
mitkClassMacroItkParent(ConnectomicsSimulatedAnnealingCostFunctionBase, itk::Object);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
protected:
//////////////////// Functions ///////////////////////
ConnectomicsSimulatedAnnealingCostFunctionBase();
~ConnectomicsSimulatedAnnealingCostFunctionBase() override;
};
}// end namespace mitk
#endif // mitkConnectomicsSimulatedAnnealingCostFunctionBase_h
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.cpp b/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.cpp
index 2a441a2..f4af278 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.cpp
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.cpp
@@ -1,125 +1,125 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsSimulatedAnnealingCostFunctionModularity.h"
mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::ConnectomicsSimulatedAnnealingCostFunctionModularity()
{
}
mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::~ConnectomicsSimulatedAnnealingCostFunctionModularity()
{
}
double mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::Evaluate( mitk::ConnectomicsNetwork::Pointer network, ToModuleMapType* vertexToModuleMap ) const
{
double cost( 0.0 );
cost = 100.0 * ( 1.0 - CalculateModularity( network, vertexToModuleMap ) );
return cost;
}
double mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::CalculateModularity( mitk::ConnectomicsNetwork::Pointer network, ToModuleMapType* vertexToModuleMap ) const
{
double modularity( 0.0 );
int numberOfModules = getNumberOfModules( vertexToModuleMap );
if( network->GetNumberOfVertices() != (int)vertexToModuleMap->size() )
{
MBI_ERROR << "Number of vertices and vertex to module map size do not match!";
return modularity;
}
int numberOfLinksInNetwork( 0 );
std::vector< int > numberOfLinksInModule, sumOfDegreesInModule;
numberOfLinksInModule.resize( numberOfModules, 0 );
sumOfDegreesInModule.resize( numberOfModules, 0 );
// get vector of all vertex descriptors in the network
const std::vector< VertexDescriptorType > allNodesVector
= network->GetVectorOfAllVertexDescriptors();
for( unsigned int nodeNumber( 0 ); nodeNumber < allNodesVector.size() ; nodeNumber++)
{
int correspondingModule = vertexToModuleMap->find( allNodesVector[ nodeNumber ] )->second;
const std::vector< VertexDescriptorType > adjacentNodexVector
= network->GetVectorOfAdjacentNodes( allNodesVector[ nodeNumber ] );
numberOfLinksInNetwork += adjacentNodexVector.size();
sumOfDegreesInModule[ correspondingModule ] += adjacentNodexVector.size();
for( unsigned int adjacentNodeNumber( 0 ); adjacentNodeNumber < adjacentNodexVector.size() ; adjacentNodeNumber++)
{
if( correspondingModule == vertexToModuleMap->find( adjacentNodexVector[ adjacentNodeNumber ] )->second )
{
numberOfLinksInModule[ correspondingModule ]++;
}
}
}
// the numbers for links have to be halved, as each edge was counted twice
numberOfLinksInNetwork = numberOfLinksInNetwork / 2;
// if the network contains no links return 0
if( numberOfLinksInNetwork < 1)
{
return 0;
}
for( int index( 0 ); index < numberOfModules ; index++)
{
numberOfLinksInModule[ index ] = numberOfLinksInModule[ index ] / 2;
}
//Calculate modularity M:
//M = sum_{s=1}^{N_{M}} [ (l_{s} / L) - (d_{s} / ( 2L ))^2 ]
//where N_{M} is the number of modules
//L is the number of links in the network
//l_{s} is the number of links between nodes in the module
//s is the module
//d_{s} is the sum of degrees of the nodes in the module
//( taken from Guimera, R. AND Amaral, L. A. N.
// Cartography of complex networks: modules and universal roles
// Journal of Statistical Mechanics: Theory and Experiment, 2005, 2005, P02001 )
for( int moduleID( 0 ); moduleID < numberOfModules; moduleID++ )
{
modularity += (((double) numberOfLinksInModule[ moduleID ]) / ((double) numberOfLinksInNetwork)) -
(
(((double) sumOfDegreesInModule[ moduleID ]) / ((double) 2 * numberOfLinksInNetwork) ) *
(((double) sumOfDegreesInModule[ moduleID ]) / ((double) 2 * numberOfLinksInNetwork) )
);
}
return modularity;
}
int mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::getNumberOfModules(
ToModuleMapType *vertexToModuleMap ) const
{
int maxModule( 0 );
auto iter = vertexToModuleMap->begin();
auto end = vertexToModuleMap->end();
while( iter != end )
{
if( iter->second > maxModule )
{
maxModule = iter->second;
}
iter++;
}
return maxModule + 1;
}
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.h b/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.h
index 3ca22bc..baed421 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.h
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingCostFunctionModularity.h
@@ -1,63 +1,63 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkConnectomicsSimulatedAnnealingCostFunctionModularity_h
#define mitkConnectomicsSimulatedAnnealingCostFunctionModularity_h
#include "mitkConnectomicsSimulatedAnnealingCostFunctionBase.h"
#include "mitkConnectomicsNetwork.h"
namespace mitk
{
/**
* \brief A cost function using the modularity of the network */
class MITKCONNECTOMICS_EXPORT ConnectomicsSimulatedAnnealingCostFunctionModularity : public mitk::ConnectomicsSimulatedAnnealingCostFunctionBase
{
public:
typedef mitk::ConnectomicsNetwork::VertexDescriptorType VertexDescriptorType;
typedef std::map< VertexDescriptorType, int > ToModuleMapType;
typedef std::map< VertexDescriptorType, VertexDescriptorType > VertexToVertexMapType;
/** Standard class typedefs. */
/** Method for creation through the object factory. */
mitkClassMacro(ConnectomicsSimulatedAnnealingCostFunctionModularity, mitk::ConnectomicsSimulatedAnnealingCostFunctionBase);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
// Evaluate the network according to the set cost function
double Evaluate( mitk::ConnectomicsNetwork::Pointer network, ToModuleMapType *vertexToModuleMap ) const;
// Will calculate and return the modularity of the network
double CalculateModularity( mitk::ConnectomicsNetwork::Pointer network, ToModuleMapType *vertexToModuleMap ) const;
protected:
// returns the number of modules
int getNumberOfModules( ToModuleMapType *vertexToModuleMap ) const;
//////////////////// Functions ///////////////////////
ConnectomicsSimulatedAnnealingCostFunctionModularity();
~ConnectomicsSimulatedAnnealingCostFunctionModularity() override;
};
}// end namespace mitk
#endif // mitkConnectomicsSimulatedAnnealingCostFunctionModularity_h
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingManager.cpp b/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingManager.cpp
index a8ba9ed..01db28d 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingManager.cpp
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingManager.cpp
@@ -1,95 +1,95 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsSimulatedAnnealingManager.h"
//for random number generation
#include "vnl/vnl_random.h"
#include "vnl/vnl_math.h"
mitk::ConnectomicsSimulatedAnnealingManager::ConnectomicsSimulatedAnnealingManager()
: m_Permutation( nullptr )
{
}
mitk::ConnectomicsSimulatedAnnealingManager::~ConnectomicsSimulatedAnnealingManager()
{
}
bool mitk::ConnectomicsSimulatedAnnealingManager::AcceptChange( double costBefore, double costAfter, double temperature )
{
if( costAfter <= costBefore )
{// if cost is lower after
return true;
}
//the random number generators
vnl_random rng( (unsigned int) rand() );
//randomly generate threshold
const double threshold = rng.drand64( 0.0 , 1.0);
//the likelihood of acceptance
double likelihood = std::exp( - ( costAfter - costBefore ) / temperature );
if( threshold < likelihood )
{
return true;
}
return false;
}
void mitk::ConnectomicsSimulatedAnnealingManager::SetPermutation( mitk::ConnectomicsSimulatedAnnealingPermutationBase::Pointer permutation )
{
m_Permutation = permutation;
}
void mitk::ConnectomicsSimulatedAnnealingManager::RunSimulatedAnnealing(
double temperature,
double stepSize
)
{
if( m_Permutation.IsNull() )
{
MBI_ERROR << "Trying to run simulated annealing on empty permutation.";
return;
}
if( !m_Permutation->HasCostFunction() )
{
MBI_ERROR << "Trying to run simulated annealing on empty cost function.";
return;
}
// Initialize the associated permutation
m_Permutation->Initialize();
for( double currentTemperature( temperature );
currentTemperature > 0.00001;
currentTemperature = currentTemperature / stepSize )
{
// Run Permutations at the current temperature
m_Permutation->Permutate( currentTemperature );
}
// Clean up result
m_Permutation->CleanUp();
}
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingManager.h b/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingManager.h
index 144e038..9d14ad5 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingManager.h
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingManager.h
@@ -1,68 +1,68 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkConnectomicsSimulatedAnnealingManager_h
#define mitkConnectomicsSimulatedAnnealingManager_h
#include <itkObject.h>
#include <itkObjectFactory.h>
#include <itkMacro.h>
#include "mitkCommon.h"
#include <MitkConnectomicsExports.h>
#include "mitkConnectomicsSimulatedAnnealingPermutationBase.h"
namespace mitk
{
/**
* \brief A class allow generic simulated annealing by using classes derived from ConnectomicsSimulatedAnnealingPermutationBase */
class MITKCONNECTOMICS_EXPORT ConnectomicsSimulatedAnnealingManager : public itk::Object
{
public:
/** Standard class typedefs. */
/** Method for creation through the object factory. */
mitkClassMacroItkParent(ConnectomicsSimulatedAnnealingManager, itk::Object);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
// Decide whether to accept the change or not
bool AcceptChange( double costBefore, double costAfter, double temperature );
// Run the permutations at different temperatures, where t_n = t_n-1 / stepSize
void RunSimulatedAnnealing( double temperature, double stepSize );
// Set the permutation to be used
void SetPermutation( mitk::ConnectomicsSimulatedAnnealingPermutationBase::Pointer permutation );
protected:
//////////////////// Functions ///////////////////////
ConnectomicsSimulatedAnnealingManager();
~ConnectomicsSimulatedAnnealingManager() override;
/////////////////////// Variables ////////////////////////
// The permutation assigned to the simulated annealing manager
mitk::ConnectomicsSimulatedAnnealingPermutationBase::Pointer m_Permutation;
};
}// end namespace mitk
#endif // mitkConnectomicsSimulatedAnnealingManager_h
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingPermutationBase.cpp b/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingPermutationBase.cpp
index daeb1ae..b1e8b08 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingPermutationBase.cpp
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingPermutationBase.cpp
@@ -1,44 +1,44 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsSimulatedAnnealingPermutationBase.h"
mitk::ConnectomicsSimulatedAnnealingPermutationBase::ConnectomicsSimulatedAnnealingPermutationBase()
: m_CostFunction( nullptr )
{
}
mitk::ConnectomicsSimulatedAnnealingPermutationBase::~ConnectomicsSimulatedAnnealingPermutationBase()
{
}
void mitk::ConnectomicsSimulatedAnnealingPermutationBase::SetCostFunction(
mitk::ConnectomicsSimulatedAnnealingCostFunctionBase::Pointer costFunction )
{
m_CostFunction = costFunction;
}
bool mitk::ConnectomicsSimulatedAnnealingPermutationBase::HasCostFunction( )
{
bool hasCostFunction( false );
if( m_CostFunction.IsNotNull() )
{
hasCostFunction = true;
}
return hasCostFunction;
}
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingPermutationBase.h b/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingPermutationBase.h
index 4516817..014aa3b 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingPermutationBase.h
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingPermutationBase.h
@@ -1,75 +1,75 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkConnectomicsSimulatedAnnealingPermutationBase_h
#define mitkConnectomicsSimulatedAnnealingPermutationBase_h
#include <itkObject.h>
#include <itkObjectFactory.h>
#include <itkMacro.h>
#include "mitkCommon.h"
#include <MitkConnectomicsExports.h>
#include "mitkConnectomicsSimulatedAnnealingCostFunctionBase.h"
namespace mitk
{
/**
* \brief Base class of a permutation to be used in simulated annealing */
class MITKCONNECTOMICS_EXPORT ConnectomicsSimulatedAnnealingPermutationBase : public itk::Object
{
public:
/** Standard class typedefs. */
/** Method for creation through the object factory. */
mitkClassMacroItkParent(ConnectomicsSimulatedAnnealingPermutationBase, itk::Object);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
// Set the cost function
void SetCostFunction( mitk::ConnectomicsSimulatedAnnealingCostFunctionBase::Pointer costFunction );
// Returns true if a cost function is assigned
bool HasCostFunction( );
// Initialize the permutation
virtual void Initialize(){};
// Do a permutation for a specific temperature
virtual void Permutate( double /*temperature*/ ){};
// Do clean up necessary after a permutation
virtual void CleanUp(){};
protected:
//////////////////// Functions ///////////////////////
ConnectomicsSimulatedAnnealingPermutationBase();
~ConnectomicsSimulatedAnnealingPermutationBase() override;
/////////////////////// Variables ////////////////////////
// The cost function assigned to the permutation
mitk::ConnectomicsSimulatedAnnealingCostFunctionBase::Pointer m_CostFunction;
};
}// end namespace mitk
#endif // mitkConnectomicsSimulatedAnnealingPermutationBase_h
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingPermutationModularity.cpp b/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingPermutationModularity.cpp
index 1581129..bde74d1 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingPermutationModularity.cpp
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingPermutationModularity.cpp
@@ -1,540 +1,540 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsSimulatedAnnealingPermutationModularity.h"
#include "mitkConnectomicsSimulatedAnnealingCostFunctionModularity.h"
#include "mitkConnectomicsSimulatedAnnealingManager.h"
//for random number generation
#include "vnl/vnl_random.h"
#include "vnl/vnl_math.h"
mitk::ConnectomicsSimulatedAnnealingPermutationModularity::ConnectomicsSimulatedAnnealingPermutationModularity()
{
}
mitk::ConnectomicsSimulatedAnnealingPermutationModularity::~ConnectomicsSimulatedAnnealingPermutationModularity()
{
}
void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::SetNetwork(
mitk::ConnectomicsNetwork::Pointer theNetwork )
{
m_Network = theNetwork;
}
void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::Initialize()
{
// create entry for every vertex
std::vector< VertexDescriptorType > vertexVector = m_Network->GetVectorOfAllVertexDescriptors();
const int vectorSize = vertexVector.size();
for( int index( 0 ); index < vectorSize; index++)
{
m_BestSolution.insert( std::pair<VertexDescriptorType, int>( vertexVector[ index ], 0 ) );
}
// initialize with random distribution of n modules
int n( 5 );
randomlyAssignNodesToModules( &m_BestSolution, n );
}
void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::Permutate( double temperature )
{
ToModuleMapType currentSolution = m_BestSolution;
ToModuleMapType currentBestSolution = m_BestSolution;
int factor = 1;
int numberOfVertices = m_BestSolution.size();
int singleNodeMaxNumber = factor * numberOfVertices * numberOfVertices;
int moduleMaxNumber = factor * numberOfVertices;
double currentBestCost = Evaluate( &currentBestSolution );
// do singleNodeMaxNumber node permutations and evaluate
for(int loop( 0 ); loop < singleNodeMaxNumber; loop++)
{
permutateMappingSingleNodeShift( &currentSolution, m_Network );
if( AcceptChange( currentBestCost, Evaluate( &currentSolution ), temperature ) )
{
currentBestSolution = currentSolution;
currentBestCost = Evaluate( &currentBestSolution );
}
}
// do moduleMaxNumber module permutations
for(int loop( 0 ); loop < moduleMaxNumber; loop++)
{
permutateMappingModuleChange( &currentSolution, temperature, m_Network );
if( AcceptChange( currentBestCost, Evaluate( &currentSolution ), temperature ) )
{
currentBestSolution = currentSolution;
currentBestCost = Evaluate( &currentBestSolution );
}
}
// store the best solution after the run
m_BestSolution = currentBestSolution;
}
void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::CleanUp()
{
// delete empty modules, if any
for( int loop( 0 ); loop < getNumberOfModules( &m_BestSolution ) ; loop++ )
{
if( getNumberOfVerticesInModule( &m_BestSolution, loop ) < 1 )
{
removeModule( &m_BestSolution, loop );
}
}
}
void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::permutateMappingSingleNodeShift(
ToModuleMapType *vertexToModuleMap, mitk::ConnectomicsNetwork::Pointer network )
{
const int nodeCount = vertexToModuleMap->size();
const int moduleCount = getNumberOfModules( vertexToModuleMap );
// the random number generators
vnl_random rng( (unsigned int) rand() );
unsigned long randomNode = rng.lrand32( nodeCount - 1 );
// move the node either to any existing module, or to its own
//unsigned long randomModule = rng.lrand32( moduleCount );
unsigned long randomModule = rng.lrand32( moduleCount - 1 );
// do some sanity checks
if ( nodeCount < 2 )
{
// no sense in doing anything
return;
}
const std::vector< VertexDescriptorType > allNodesVector
= network->GetVectorOfAllVertexDescriptors();
auto iter = vertexToModuleMap->find( allNodesVector[ randomNode ] );
const int previousModuleNumber = iter->second;
// if we move the node to its own module, do nothing
if( previousModuleNumber == (long)randomModule )
{
return;
}
iter->second = randomModule;
if( getNumberOfVerticesInModule( vertexToModuleMap, previousModuleNumber ) < 1 )
{
removeModule( vertexToModuleMap, previousModuleNumber );
}
}
void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::permutateMappingModuleChange(
ToModuleMapType *vertexToModuleMap, double currentTemperature, mitk::ConnectomicsNetwork::Pointer network )
{
//the random number generators
vnl_random rng( (unsigned int) rand() );
//randomly generate threshold
const double threshold = rng.drand64( 0.0 , 1.0);
//for deciding whether to join two modules or split one
double splitThreshold = 0.5;
//stores whether to join or two split
bool joinModules( false );
//select random module
int numberOfModules = getNumberOfModules( vertexToModuleMap );
unsigned long randomModuleA = rng.lrand32( numberOfModules - 1 );
//select the second module to join, if joining
unsigned long randomModuleB = rng.lrand32( numberOfModules - 1 );
if( ( threshold < splitThreshold ) && ( randomModuleA != randomModuleB ) )
{
joinModules = true;
}
if( joinModules )
{
// this being an kommutative operation, we will always join B to A
joinTwoModules( vertexToModuleMap, randomModuleA, randomModuleB );
//eliminate the empty module
removeModule( vertexToModuleMap, randomModuleB );
}
else
{
//split module
splitModule( vertexToModuleMap, currentTemperature, network, randomModuleA );
}
}
void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::joinTwoModules(
ToModuleMapType *vertexToModuleMap, int moduleA, int moduleB )
{
auto iter = vertexToModuleMap->begin();
auto end = vertexToModuleMap->end();
while( iter != end )
{
// if vertex belongs to module B move it to A
if( iter->second == moduleB )
{
iter->second = moduleA;
}
iter++;
}// end while( iter != end )
}
void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::splitModule(
ToModuleMapType *vertexToModuleMap, double currentTemperature, mitk::ConnectomicsNetwork::Pointer network, int moduleToSplit )
{
if( m_Depth == 0 )
{
// do nothing
return;
}
// if the module contains only one node, no more division is sensible
if( getNumberOfVerticesInModule( vertexToModuleMap, moduleToSplit ) < 2 )
{
// do nothing
return;
}
// create subgraph of the module, that is to be splitted
mitk::ConnectomicsNetwork::Pointer subNetwork = mitk::ConnectomicsNetwork::New();
VertexToVertexMapType graphToSubgraphVertexMap;
VertexToVertexMapType subgraphToGraphVertexMap;
extractModuleSubgraph( vertexToModuleMap, network, moduleToSplit, subNetwork, &graphToSubgraphVertexMap, &subgraphToGraphVertexMap );
// The submap
ToModuleMapType vertexToModuleSubMap;
// run simulated annealing on the subgraph to determine how the module should be split
if( m_Depth > 0 && m_StepSize > 0 )
{
mitk::ConnectomicsSimulatedAnnealingManager::Pointer manager = mitk::ConnectomicsSimulatedAnnealingManager::New();
mitk::ConnectomicsSimulatedAnnealingPermutationModularity::Pointer permutation = mitk::ConnectomicsSimulatedAnnealingPermutationModularity::New();
mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::Pointer costFunction = mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::New();
permutation->SetCostFunction( costFunction.GetPointer() );
permutation->SetNetwork( subNetwork );
permutation->SetDepth( m_Depth - 1 );
permutation->SetStepSize( m_StepSize * 2 );
manager->SetPermutation( permutation.GetPointer() );
manager->RunSimulatedAnnealing( currentTemperature, m_StepSize * 2 );
vertexToModuleSubMap = permutation->GetMapping();
}
// now carry the information over to the original map
std::vector< int > moduleTranslationVector;
moduleTranslationVector.resize( getNumberOfModules( &vertexToModuleSubMap ), 0 );
int originalNumber = getNumberOfModules( vertexToModuleMap );
// the new parts are added at the end
for(unsigned int index( 0 ); index < moduleTranslationVector.size() ; index++)
{
moduleTranslationVector[ index ] = originalNumber + index;
}
auto iter2 = vertexToModuleSubMap.begin();
auto end2 = vertexToModuleSubMap.end();
while( iter2 != end2 )
{
// translate vertex descriptor from subgraph to graph
VertexDescriptorType key = subgraphToGraphVertexMap.find( iter2->first )->second;
// translate module number from subgraph to graph
int value = moduleTranslationVector[ iter2->second ];
// change the corresponding entry
vertexToModuleMap->find( key )->second = value;
iter2++;
}
// remove the now empty module, that was splitted
removeModule( vertexToModuleMap, moduleToSplit );
}
void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::extractModuleSubgraph(
ToModuleMapType *vertexToModuleMap,
mitk::ConnectomicsNetwork::Pointer network,
int moduleToSplit,
mitk::ConnectomicsNetwork::Pointer subNetwork,
VertexToVertexMapType* graphToSubgraphVertexMap,
VertexToVertexMapType* subgraphToGraphVertexMap )
{
const std::vector< VertexDescriptorType > allNodesVector = network->GetVectorOfAllVertexDescriptors();
// add vertices to subgraph
for( unsigned int nodeNumber( 0 ); nodeNumber < allNodesVector.size() ; nodeNumber++)
{
if( moduleToSplit == vertexToModuleMap->find( allNodesVector[ nodeNumber ] )->second )
{
int id = network->GetNode( allNodesVector[ nodeNumber ] ).id;
VertexDescriptorType newVertex = subNetwork->AddVertex( id );
graphToSubgraphVertexMap->insert(
std::pair<VertexDescriptorType, VertexDescriptorType>(
allNodesVector[ nodeNumber ], newVertex
)
);
subgraphToGraphVertexMap->insert(
std::pair<VertexDescriptorType, VertexDescriptorType>(
newVertex, allNodesVector[ nodeNumber ]
)
);
}
}
// add edges to subgraph
auto iter = graphToSubgraphVertexMap->begin();
auto end = graphToSubgraphVertexMap->end();
while( iter != end )
{
const std::vector< VertexDescriptorType > adjacentNodexVector
= network->GetVectorOfAdjacentNodes( iter->first );
for( unsigned int adjacentNodeNumber( 0 ); adjacentNodeNumber < adjacentNodexVector.size() ; adjacentNodeNumber++)
{
// if the adjacent vertex is part of the subgraph,
// add edge, if it does not exist yet, else do nothing
VertexDescriptorType adjacentVertex = adjacentNodexVector[ adjacentNodeNumber ];
if( graphToSubgraphVertexMap->count( adjacentVertex ) > 0 )
{
if( !subNetwork->EdgeExists( iter->second, graphToSubgraphVertexMap->find( adjacentVertex )->second ) )
{ //edge exists in parent network, but not yet in sub network
const VertexDescriptorType vertexA = iter->second;
const VertexDescriptorType vertexB = graphToSubgraphVertexMap->find( adjacentVertex )->second;
const int sourceID = network->GetNode( vertexA ).id;
const int targetID = network->GetNode( vertexB ).id;
const double fiber_count = network->GetEdge( iter->first, graphToSubgraphVertexMap->find( adjacentVertex )->first ).fiber_count;
subNetwork->AddEdge( vertexA , vertexB, sourceID, targetID, fiber_count );
}
}
}
iter++;
}// end while( iter != end )
}
int mitk::ConnectomicsSimulatedAnnealingPermutationModularity::getNumberOfModules(
ToModuleMapType *vertexToModuleMap ) const
{
int maxModule( 0 );
auto iter = vertexToModuleMap->begin();
auto end = vertexToModuleMap->end();
while( iter != end )
{
if( iter->second > maxModule )
{
maxModule = iter->second;
}
iter++;
}
return maxModule + 1;
}
int mitk::ConnectomicsSimulatedAnnealingPermutationModularity::getNumberOfVerticesInModule(
ToModuleMapType *vertexToModuleMap, int module ) const
{
int number( 0 );
auto iter = vertexToModuleMap->begin();
auto end = vertexToModuleMap->end();
while( iter != end )
{
if( iter->second == module )
{
number++;
}
iter++;
}
return number;
}
void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::removeModule(
ToModuleMapType *vertexToModuleMap, int module )
{
int lastModuleNumber = getNumberOfModules( vertexToModuleMap ) - 1;
if( module == lastModuleNumber )
{
// no need to do anything, the last module is deleted "automatically"
return;
}
if( getNumberOfVerticesInModule( vertexToModuleMap, module ) > 0 )
{
MBI_WARN << "Trying to remove non-empty module";
return;
}
auto iter = vertexToModuleMap->begin();
auto end = vertexToModuleMap->end();
while( iter != end )
{
if( iter->second == lastModuleNumber )
{
// renumber last module to to-be-deleted module
iter->second = module;
}
iter++;
}
}
void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::randomlyAssignNodesToModules(
ToModuleMapType *vertexToModuleMap, int numberOfIntendedModules )
{
// we make sure that each intended module contains *at least* one node
// thus if more modules are asked for than node exists we will only generate
// as many modules as there are nodes
if( numberOfIntendedModules > 0 &&
(unsigned int)numberOfIntendedModules > vertexToModuleMap->size() )
{
MBI_ERROR << "Tried to generate more modules than vertices were provided";
numberOfIntendedModules = vertexToModuleMap->size();
}
//the random number generators
vnl_random rng( (unsigned int) rand() );
std::vector< int > histogram;
std::vector< int > nodeList;
histogram.resize( numberOfIntendedModules, 0 );
nodeList.resize( vertexToModuleMap->size(), 0 );
int numberOfVertices = vertexToModuleMap->size();
//randomly distribute nodes to modules
for( unsigned int nodeIndex( 0 ); nodeIndex < nodeList.size(); nodeIndex++ )
{
//select random module
nodeList[ nodeIndex ] = rng.lrand32( numberOfIntendedModules - 1 );
histogram[ nodeList[ nodeIndex ] ]++;
}
// make sure no module contains no node, if one does assign it one of a random module
// that does contain at least two
for( unsigned int moduleIndex( 0 ); moduleIndex < histogram.size(); moduleIndex++ )
{
while( histogram[ moduleIndex ] == 0 )
{
int randomNodeIndex = rng.lrand32( numberOfVertices - 1 );
if( histogram[ nodeList[ randomNodeIndex ] ] > 1 )
{
histogram[ moduleIndex ]++;
histogram[ nodeList[ randomNodeIndex ] ]--;
nodeList[ randomNodeIndex ] = moduleIndex;
}
}
}
auto iter = vertexToModuleMap->begin();
auto end = vertexToModuleMap->end();
for( unsigned int index( 0 ); ( iter != end ) && ( index < nodeList.size() ); index++, iter++ )
{
iter->second = nodeList[ index ] ;
}
}
void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::SetMapping( ToModuleMapType mapping )
{
m_BestSolution = mapping;
}
mitk::ConnectomicsSimulatedAnnealingPermutationModularity::ToModuleMapType
mitk::ConnectomicsSimulatedAnnealingPermutationModularity::GetMapping()
{
return m_BestSolution;
}
double mitk::ConnectomicsSimulatedAnnealingPermutationModularity::Evaluate( ToModuleMapType* mapping ) const
{
mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity* costMapping =
dynamic_cast<mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity*>( m_CostFunction.GetPointer() );
if( costMapping )
{
return costMapping->Evaluate( m_Network, mapping );
}
else
{
return 0;
}
}
bool mitk::ConnectomicsSimulatedAnnealingPermutationModularity::AcceptChange( double costBefore, double costAfter, double temperature ) const
{
if( costAfter <= costBefore )
{// if cost is lower after
return true;
}
//the random number generators
vnl_random rng( (unsigned int) rand() );
//randomly generate threshold
const double threshold = rng.drand64( 0.0 , 1.0);
//the likelihood of acceptance
double likelihood = std::exp( - ( costAfter - costBefore ) / temperature );
if( threshold < likelihood )
{
return true;
}
return false;
}
void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::SetDepth( int depth )
{
m_Depth = depth;
}
void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::SetStepSize( double size )
{
m_StepSize = size;
}
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingPermutationModularity.h b/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingPermutationModularity.h
index 93904df..9e94dc8 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingPermutationModularity.h
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsSimulatedAnnealingPermutationModularity.h
@@ -1,140 +1,140 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkConnectomicsSimulatedAnnealingPermutationModularity_h
#define mitkConnectomicsSimulatedAnnealingPermutationModularity_h
#include "mitkConnectomicsSimulatedAnnealingPermutationBase.h"
#include "mitkConnectomicsNetwork.h"
namespace mitk
{
/**
* \brief A class providing permutations for the calculation of modularity using simulated annealing */
class MITKCONNECTOMICS_EXPORT ConnectomicsSimulatedAnnealingPermutationModularity : public mitk::ConnectomicsSimulatedAnnealingPermutationBase
{
public:
typedef mitk::ConnectomicsNetwork::VertexDescriptorType VertexDescriptorType;
typedef std::map< VertexDescriptorType, int > ToModuleMapType;
typedef std::map< VertexDescriptorType, VertexDescriptorType > VertexToVertexMapType;
/** Standard class typedefs. */
/** Method for creation through the object factory. */
mitkClassMacroItkParent(ConnectomicsSimulatedAnnealingPermutationModularity, itk::Object);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
// Initialize the permutation
void Initialize() override;
// Do a permutation for a specific temperature
void Permutate( double temperature ) override;
// Do clean up necessary after a permutation
void CleanUp() override;
// set the network permutation is to be run upon
void SetNetwork( mitk::ConnectomicsNetwork::Pointer theNetwork );
// Get the number of modules the graph has ( highest number - 1 )
int getNumberOfModules( ToModuleMapType *vertexToModuleMap ) const;
// Get the number of vertices belonging to a given module
int getNumberOfVerticesInModule( ToModuleMapType *vertexToModuleMap, int module ) const;
// Set the mapping
void SetMapping( ToModuleMapType mapping );
// Get the mapping
ToModuleMapType GetMapping();
// Set depth
void SetDepth( int depth );
// Set stepSize
void SetStepSize( double size );
protected:
//////////////////// Functions ///////////////////////
ConnectomicsSimulatedAnnealingPermutationModularity();
~ConnectomicsSimulatedAnnealingPermutationModularity() override;
// This function moves one single node from a module to another
void permutateMappingSingleNodeShift(
ToModuleMapType *vertexToModuleMap,
mitk::ConnectomicsNetwork::Pointer network );
// This function splits and joins modules
void permutateMappingModuleChange(
ToModuleMapType *vertexToModuleMap,
double currentTemperature,
mitk::ConnectomicsNetwork::Pointer network );
// join the two given modules to a single one
void joinTwoModules( ToModuleMapType *vertexToModuleMap, int moduleA, int moduleB );
// split the given module recursively up to a certain level
// first randomly assigns nodes and then starts another simulated annealing
// on the sub network, as long as depthOfModuleChange > 0
void splitModule(
ToModuleMapType *vertexToModuleMap,
double currentTemperature,
mitk::ConnectomicsNetwork::Pointer network,
int moduleToSplit );
// Extract the subgraph of a network containing all nodes
// of a given module and the egdes between them
void extractModuleSubgraph(
ToModuleMapType *vertexToModuleMap,
mitk::ConnectomicsNetwork::Pointer network,
int moduleToSplit,
mitk::ConnectomicsNetwork::Pointer subNetwork,
VertexToVertexMapType* graphToSubgraphVertexMap,
VertexToVertexMapType* subgraphToGraphVertexMap );
// Remove empty modules by moving all nodes of the highest module to the given module
void removeModule( ToModuleMapType *vertexToModuleMap, int module );
// Randomly assign nodes to modules, this makes sure each module contains at least one node
// as long as numberOfIntendedModules < number of nodes
void randomlyAssignNodesToModules(ToModuleMapType *vertexToModuleMap, int numberOfIntendedModules );
// Evaluate mapping using a modularity cost function
double Evaluate( ToModuleMapType* mapping ) const;
// Whether to accept the permutation
bool AcceptChange( double costBefore, double costAfter, double temperature ) const;
// the current best solution
ToModuleMapType m_BestSolution;
// the network
mitk::ConnectomicsNetwork::Pointer m_Network;
// How many levels of recursive calls can be gone down
int m_Depth;
// The step size for recursive configuring of simulated annealing manager
double m_StepSize;
};
}// end namespace mitk
#endif // mitkConnectomicsSimulatedAnnealingPermutationModularity_h
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsStatisticsCalculator.cpp b/Modules/Connectomics/Algorithms/mitkConnectomicsStatisticsCalculator.cpp
index 4a6763f..7075777 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsStatisticsCalculator.cpp
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsStatisticsCalculator.cpp
@@ -1,749 +1,749 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsStatisticsCalculator.h"
#include "mitkConnectomicsNetworkConverter.h"
#include <numeric>
#include <boost/graph/clustering_coefficient.hpp>
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4172)
#endif
#include <boost/graph/connected_components.hpp>
#include <boost/graph/betweenness_centrality.hpp>
#ifdef _MSC_VER
# pragma warning(pop)
#endif
#include <boost/graph/visitors.hpp>
#include "vnl/algo/vnl_symmetric_eigensystem.h"
template<typename GraphType>
class all_pairs_shortest_recorder : public boost::default_bfs_visitor
{
public:
typedef typename boost::graph_traits<GraphType>::vertex_descriptor VertexType;
typedef typename boost::graph_traits<GraphType>::edge_descriptor EdgeType;
all_pairs_shortest_recorder(int* dist, int &max, unsigned int &size)
{
d = dist;
ecc = &max;
component_size = &size;
}
void tree_edge(EdgeType edge, const GraphType& graph) {
VertexType u = boost::source(edge, graph);
VertexType v = boost::target(edge, graph);
d[v] = d[u] + 1;
*ecc = d[v];
*component_size = *component_size + 1;
}
private:
int* d;
int* ecc;
unsigned int* component_size;
};
mitk::ConnectomicsStatisticsCalculator::ConnectomicsStatisticsCalculator()
: m_Network( nullptr )
, m_NumberOfVertices( 0 )
, m_NumberOfEdges( 0 )
, m_AverageDegree( 0.0 )
, m_ConnectionDensity( 0.0 )
, m_NumberOfConnectedComponents( 0 )
, m_AverageComponentSize( 0.0 )
, m_Components(0)
, m_LargestComponentSize( 0 )
, m_HopPlotExponent( 0.0 )
, m_EffectiveHopDiameter( 0.0 )
, m_VectorOfClusteringCoefficientsC( 0 )
, m_VectorOfClusteringCoefficientsD( 0 )
, m_VectorOfClusteringCoefficientsE( 0 )
, m_AverageClusteringCoefficientsC( 0.0 )
, m_AverageClusteringCoefficientsD( 0.0 )
, m_AverageClusteringCoefficientsE( 0.0 )
, m_VectorOfVertexBetweennessCentralities( 0 )
, m_PropertyMapOfVertexBetweennessCentralities( )
, m_AverageVertexBetweennessCentrality( 0.0 )
, m_VectorOfEdgeBetweennessCentralities( 0 )
, m_PropertyMapOfEdgeBetweennessCentralities( )
, m_AverageEdgeBetweennessCentrality( 0.0 )
, m_NumberOfIsolatedPoints( 0 )
, m_RatioOfIsolatedPoints( 0.0 )
, m_NumberOfEndPoints( 0 )
, m_RatioOfEndPoints( 0.0 )
, m_VectorOfEccentrities( 0 )
, m_VectorOfEccentrities90( 0 )
, m_VectorOfAveragePathLengths( 0.0 )
, m_Diameter( 0 )
, m_Diameter90( 0 )
, m_Radius( 0 )
, m_Radius90( 0 )
, m_AverageEccentricity( 0.0 )
, m_AverageEccentricity90( 0.0 )
, m_AveragePathLength( 0.0 )
, m_NumberOfCentralPoints( 0 )
, m_RatioOfCentralPoints( 0.0 )
, m_VectorOfSortedEigenValues( 0 )
, m_SpectralRadius( 0.0 )
, m_SecondLargestEigenValue( 0.0 )
, m_AdjacencyTrace( 0.0 )
, m_AdjacencyEnergy( 0.0 )
, m_VectorOfSortedLaplacianEigenValues( 0 )
, m_LaplacianTrace( 0.0 )
, m_LaplacianEnergy( 0.0 )
, m_LaplacianSpectralGap( 0.0 )
, m_VectorOfSortedNormalizedLaplacianEigenValues( 0 )
, m_NormalizedLaplacianTrace( 0.0 )
, m_NormalizedLaplacianEnergy( 0.0 )
, m_NormalizedLaplacianNumberOf2s( 0 )
, m_NormalizedLaplacianNumberOf1s( 0 )
, m_NormalizedLaplacianNumberOf0s( 0 )
, m_NormalizedLaplacianLowerSlope( 0.0 )
, m_NormalizedLaplacianUpperSlope( 0.0 )
, m_SmallWorldness( 0.0 )
{
}
mitk::ConnectomicsStatisticsCalculator::~ConnectomicsStatisticsCalculator()
{
}
void mitk::ConnectomicsStatisticsCalculator::Update()
{
CalculateNumberOfVertices();
CalculateNumberOfEdges();
CalculateAverageDegree();
CalculateConnectionDensity();
CalculateNumberOfConnectedComponents();
CalculateAverageComponentSize();
CalculateLargestComponentSize();
CalculateRatioOfNodesInLargestComponent();
CalculateHopPlotValues();
CalculateClusteringCoefficients();
CalculateBetweennessCentrality();
CalculateIsolatedAndEndPoints();
CalculateShortestPathMetrics();
CalculateSpectralMetrics();
CalculateLaplacianMetrics();
CalculateNormalizedLaplacianMetrics();
CalculateSmallWorldness();
}
void mitk::ConnectomicsStatisticsCalculator::CalculateNumberOfVertices()
{
m_NumberOfVertices = boost::num_vertices( *(m_Network->GetBoostGraph()) );
}
void mitk::ConnectomicsStatisticsCalculator::CalculateNumberOfEdges()
{
m_NumberOfEdges = boost::num_edges( *(m_Network->GetBoostGraph()) );
}
void mitk::ConnectomicsStatisticsCalculator::CalculateAverageDegree()
{
m_AverageDegree = ( ( (double) m_NumberOfEdges * 2.0 ) / (double) m_NumberOfVertices );
}
void mitk::ConnectomicsStatisticsCalculator::CalculateConnectionDensity()
{
double numberOfPossibleEdges = (double) m_NumberOfVertices * ( (double) m_NumberOfVertices - 1 ) / 2;
m_ConnectionDensity = (double) m_NumberOfEdges / numberOfPossibleEdges;
}
void mitk::ConnectomicsStatisticsCalculator::CalculateNumberOfConnectedComponents()
{
m_Components.resize( m_NumberOfVertices );
m_NumberOfConnectedComponents = boost::connected_components( *(m_Network->GetBoostGraph()), &m_Components[0] );
}
void mitk::ConnectomicsStatisticsCalculator::CalculateAverageComponentSize()
{
m_AverageComponentSize = (double) m_NumberOfVertices / (double) m_NumberOfConnectedComponents ;
}
void mitk::ConnectomicsStatisticsCalculator::CalculateLargestComponentSize()
{
m_LargestComponentSize = 0;
std::vector<unsigned int> bins( m_NumberOfConnectedComponents );
for(unsigned int i=0; i < m_NumberOfVertices; i++)
{
bins[ m_Components[i] ]++;
}
for(unsigned int i=0; i < m_NumberOfConnectedComponents; i++)
{
if (bins[i] > m_LargestComponentSize )
{
m_LargestComponentSize = bins[i];
}
}
}
void mitk::ConnectomicsStatisticsCalculator::CalculateRatioOfNodesInLargestComponent()
{
m_RatioOfNodesInLargestComponent = (double) m_LargestComponentSize / (double) m_NumberOfVertices ;
}
void mitk::ConnectomicsStatisticsCalculator::CalculateHopPlotValues()
{
std::vector<int> bins( m_NumberOfVertices );
VertexIteratorType vi, vi_end;
unsigned int index( 0 );
for( boost::tie( vi, vi_end ) = boost::vertices( *(m_Network->GetBoostGraph()) ); vi != vi_end; ++vi)
{
std::vector<int> distances(m_NumberOfVertices, 0);
int max_distance = 0;
VertexDescriptorType src = *vi;
distances[src] = 0;
unsigned int size = 0;
boost::breadth_first_search(*(m_Network->GetBoostGraph()), src,
visitor(all_pairs_shortest_recorder< NetworkType >
(&distances[0], max_distance, size)));
for(index=0; index < distances.size(); index++)
{
if(distances[index] > 0)
{
bins[distances[index]]++;
}
}
}
bins[0] = m_NumberOfVertices;
for(index=1; index < bins.size(); index++)
{
bins[index] = bins[index] + bins[index-1];
}
int counter = 0;
double C=0, D=0, E=0, F=0;
for (unsigned int i=1; i<bins.size()-1; i++)
{
counter ++;
if(fabs(log(double(bins[i+1])) - log(double(bins[i]))) < 0.0000001)
{
break;
}
}
for (int i=1; i<=counter; i++)
{
double x = log(double(i));
double y = log(double(bins[i]));
C += x;
D += y;
E += x * y;
F += x * x;
}
double b = (D*F - C*E)/(F*counter - C*C);
m_HopPlotExponent = (E - b*C)/F;
m_EffectiveHopDiameter =
std::pow( ( m_NumberOfVertices * m_NumberOfVertices )
/ ( m_NumberOfVertices + 2 * m_NumberOfEdges ), 1.0 / m_HopPlotExponent );
}
void mitk::ConnectomicsStatisticsCalculator::CalculateClusteringCoefficients()
{
VertexIteratorType vi, vi_end;
std::vector<double> m_VectorOfClusteringCoefficientsC;
std::vector<double> m_VectorOfClusteringCoefficientsD;
std::vector<double> m_VectorOfClusteringCoefficientsE;
typedef std::set<VertexDescriptorType> NeighborSetType;
typedef NetworkType::out_edge_iterator OutEdgeIterType;
for(boost::tie(vi,vi_end) = boost::vertices( *(m_Network->GetBoostGraph()) ); vi!=vi_end; ++vi)
{
// Get the list of vertices which are in the neighborhood of vi.
std::pair<AdjacencyIteratorType, AdjacencyIteratorType> adjacent =
boost::adjacent_vertices(*vi, *(m_Network->GetBoostGraph()) );
//Populate a set with the neighbors of vi
NeighborSetType neighbors;
for(; adjacent.first!=adjacent.second; ++adjacent.first)
{
neighbors.insert(*adjacent.first);
}
// Now, count the edges between vertices in the neighborhood.
unsigned int neighborhood_edge_count = 0;
if(neighbors.size() > 0)
{
NeighborSetType::iterator iter;
for(iter = neighbors.begin(); iter != neighbors.end(); ++iter)
{
std::pair<OutEdgeIterType, OutEdgeIterType> oe = out_edges(*iter, *(m_Network->GetBoostGraph()) );
for(; oe.first != oe.second; ++oe.first)
{
if(neighbors.find(target(*oe.first, *(m_Network->GetBoostGraph()) )) != neighbors.end())
{
++neighborhood_edge_count;
}
}
}
neighborhood_edge_count /= 2;
}
//Clustering Coefficienct C,E
if(neighbors.size() > 1)
{
double num = neighborhood_edge_count;
double denum = neighbors.size() * (neighbors.size()-1)/2;
m_VectorOfClusteringCoefficientsC.push_back( num / denum);
m_VectorOfClusteringCoefficientsE.push_back( num / denum);
}
else
{
m_VectorOfClusteringCoefficientsC.push_back(0.0);
}
//Clustering Coefficienct D
if(neighbors.size() > 0)
{
double num = neighbors.size() + neighborhood_edge_count;
double denum = ( (neighbors.size()+1) * neighbors.size()) / 2;
m_VectorOfClusteringCoefficientsD.push_back( num / denum);
}
else
{
m_VectorOfClusteringCoefficientsD.push_back(0.0);
}
}
// Average Clustering coefficienies:
m_AverageClusteringCoefficientsC = std::accumulate(m_VectorOfClusteringCoefficientsC.begin(),
m_VectorOfClusteringCoefficientsC.end(),
0.0) / m_NumberOfVertices;
m_AverageClusteringCoefficientsD = std::accumulate(m_VectorOfClusteringCoefficientsD.begin(),
m_VectorOfClusteringCoefficientsD.end(),
0.0) / m_NumberOfVertices;
m_AverageClusteringCoefficientsE = std::accumulate(m_VectorOfClusteringCoefficientsE.begin(),
m_VectorOfClusteringCoefficientsE.end(),
0.0) / m_VectorOfClusteringCoefficientsE.size();
}
void mitk::ConnectomicsStatisticsCalculator::CalculateBetweennessCentrality()
{
// std::map used for convenient initialization
EdgeIndexStdMapType stdEdgeIndex;
// associative property map needed for iterator property map-wrapper
EdgeIndexMapType edgeIndex(stdEdgeIndex);
EdgeIteratorType iterator, end;
// sets iterator to start end end to end
boost::tie(iterator, end) = boost::edges( *(m_Network->GetBoostGraph()) );
int i(0);
for ( ; iterator != end; ++iterator, ++i)
{
stdEdgeIndex.insert(std::pair< EdgeDescriptorType, int >( *iterator, i));
}
// Define EdgeCentralityMap
m_VectorOfEdgeBetweennessCentralities.resize( m_NumberOfEdges, 0.0);
// Create the external property map
m_PropertyMapOfEdgeBetweennessCentralities = EdgeIteratorPropertyMapType(m_VectorOfEdgeBetweennessCentralities.begin(), edgeIndex);
// Define VertexCentralityMap
VertexIndexMapType vertexIndex = get(boost::vertex_index, *(m_Network->GetBoostGraph()) );
m_VectorOfVertexBetweennessCentralities.resize( m_NumberOfVertices, 0.0);
// Create the external property map
m_PropertyMapOfVertexBetweennessCentralities = VertexIteratorPropertyMapType(m_VectorOfVertexBetweennessCentralities.begin(), vertexIndex);
boost::brandes_betweenness_centrality( *(m_Network->GetBoostGraph()),
m_PropertyMapOfVertexBetweennessCentralities, m_PropertyMapOfEdgeBetweennessCentralities );
m_AverageVertexBetweennessCentrality = std::accumulate(m_VectorOfVertexBetweennessCentralities.begin(),
m_VectorOfVertexBetweennessCentralities.end(),
0.0) / (double) m_NumberOfVertices;
m_AverageEdgeBetweennessCentrality = std::accumulate(m_VectorOfEdgeBetweennessCentralities.begin(),
m_VectorOfEdgeBetweennessCentralities.end(),
0.0) / (double) m_NumberOfEdges;
}
void mitk::ConnectomicsStatisticsCalculator::CalculateIsolatedAndEndPoints()
{
m_NumberOfIsolatedPoints = 0;
m_NumberOfEndPoints = 0;
VertexIteratorType vi, vi_end;
for( boost::tie(vi,vi_end) = boost::vertices( *(m_Network->GetBoostGraph()) ); vi!=vi_end; ++vi)
{
int degree = boost::out_degree(*vi, *(m_Network->GetBoostGraph()) );
if(degree == 0)
{
m_NumberOfIsolatedPoints++;
}
else if (degree == 1)
{
m_NumberOfEndPoints++;
}
}
m_RatioOfEndPoints = (double) m_NumberOfEndPoints / (double) m_NumberOfVertices;
m_RatioOfIsolatedPoints = (double) m_NumberOfIsolatedPoints / (double) m_NumberOfVertices;
}
/**
* Calculates Shortest Path Related metrics of the graph. The
* function runs a BFS from each node to find out the shortest
* distances to other nodes in the graph. The maximum of this distance
* is called the eccentricity of that node. The maximum eccentricity
* in the graph is called diameter and the minimum eccentricity is
* called the radius of the graph. Central points are those nodes
* having eccentricity equals to radius.
*/
void mitk::ConnectomicsStatisticsCalculator::CalculateShortestPathMetrics()
{
//for all vertices:
VertexIteratorType vi, vi_end;
//store the eccentricities in a vector.
m_VectorOfEccentrities.resize( m_NumberOfVertices );
m_VectorOfEccentrities90.resize( m_NumberOfVertices );
m_VectorOfAveragePathLengths.resize( m_NumberOfVertices );
//assign diameter and radius while iterating over the ecccencirities.
m_Diameter = 0;
m_Diameter90 = 0;
m_Radius = std::numeric_limits<unsigned int>::max();
m_Radius90 = std::numeric_limits<unsigned int>::max();
m_AverageEccentricity = 0.0;
m_AverageEccentricity90 = 0.0;
m_AveragePathLength = 0.0;
//The size of the giant connected component so far.
unsigned int giant_component_size = 0;
VertexDescriptorType radius_src(0);
//Loop over the vertices
for( boost::tie(vi, vi_end) = boost::vertices( *(m_Network->GetBoostGraph()) ); vi!=vi_end; ++vi)
{
//We are going to start a BFS, initialize the neccessary
//structures for that. Store the distances of nodes from the
//source in distance vector. The maximum distance is stored in
//max. The BFS will start from the node that vi is pointing, that
//is the src is *vi. We also init the distance of the src node to
//itself to 0. size gives the number of nodes discovered during
//this BFS.
std::vector<int> distances( m_NumberOfVertices );
int max_distance = 0;
VertexDescriptorType src = *vi;
distances[src] = 0;
unsigned int size = 0;
breadth_first_search(*(m_Network->GetBoostGraph()), src,
visitor(all_pairs_shortest_recorder<NetworkType>
(&distances[0], max_distance, size)));
// vertex vi has eccentricity equal to max_distance
m_VectorOfEccentrities[src] = max_distance;
//check whether there is any change in the diameter or the radius.
//note that the diameter we are calculating here is also the
//diameter of the giant connected component!
if(m_VectorOfEccentrities[src] > m_Diameter)
{
m_Diameter = m_VectorOfEccentrities[src];
}
//The radius should be calculated on the largest connected
//component, otherwise it is very likely that radius will be 1.
//We change the value of the radius only if this is the giant
//connected component so far. After all the eccentricities are
//found we should loop over this connected component and find the
//minimum eccentricity which is the radius. So we keep the src
//node, so that we can find the connected component later on.
if(size > giant_component_size)
{
giant_component_size = size;
radius_src = src;
}
//Calculate in how many hops we can reach 90 percent of the
//nodes. We store the number of hops we can reach in h hops in the
//bucket vector. That is bucket[h] gives the number of nodes
//reachable in exactly h hops. sum of bucket[i<h] gives the number
//of nodes that are reachable in less than h hops. We also
//calculate sum of the distances from this node to every single
//other node in the graph.
int reachable90 = std::ceil((double)size * 0.9);
std::vector <int> bucket (max_distance+1);
int counter = 0;
for(unsigned int i=0; i<distances.size(); i++)
{
if(distances[i]>0)
{
bucket[distances[i]]++;
m_VectorOfAveragePathLengths[src] += distances[i];
counter ++;
}
}
if(counter > 0)
{
m_VectorOfAveragePathLengths[src] = m_VectorOfAveragePathLengths[src] / counter;
}
int eccentricity90 = 0;
while(reachable90 > 0)
{
eccentricity90 ++;
reachable90 = reachable90 - bucket[eccentricity90];
}
// vertex vi has eccentricity90 equal to eccentricity90
m_VectorOfEccentrities90[src] = eccentricity90;
if(m_VectorOfEccentrities90[src] > m_Diameter90)
{
m_Diameter90 = m_VectorOfEccentrities90[src];
}
}
//We are going to calculate the radius now. We stored the src node
//that when we start a BFS gives the giant connected component, and
//we have the eccentricities calculated. Iterate over the nodes of
//this giant component and find the minimum eccentricity.
std::vector<int> component( m_NumberOfVertices );
boost::connected_components( *(m_Network->GetBoostGraph()), &component[0]);
for (unsigned int i=0; i<component.size(); i++)
{
//If we are in the same component and the radius is not the
//minimum so far store the eccentricity as the radius.
if( component[i] == component[radius_src])
{
if(m_Radius > m_VectorOfEccentrities[i])
{
m_Radius = m_VectorOfEccentrities[i];
}
if(m_Radius90 > m_VectorOfEccentrities90[i])
{
m_Radius90 = m_VectorOfEccentrities90[i];
}
}
}
m_AverageEccentricity = std::accumulate(m_VectorOfEccentrities.begin(),
m_VectorOfEccentrities.end(), 0.0) / m_NumberOfVertices;
m_AverageEccentricity90 = std::accumulate(m_VectorOfEccentrities90.begin(),
m_VectorOfEccentrities90.end(), 0.0) / m_NumberOfVertices;
m_AveragePathLength = std::accumulate(m_VectorOfAveragePathLengths.begin(),
m_VectorOfAveragePathLengths.end(), 0.0) / m_NumberOfVertices;
//calculate Number of Central Points, nodes having eccentricity = radius.
m_NumberOfCentralPoints = 0;
for (boost::tie(vi, vi_end) = boost::vertices( *(m_Network->GetBoostGraph()) ); vi != vi_end; ++vi)
{
if(m_VectorOfEccentrities[*vi] == m_Radius)
{
m_NumberOfCentralPoints++;
}
}
m_RatioOfCentralPoints = (double)m_NumberOfCentralPoints / m_NumberOfVertices;
}
void mitk::ConnectomicsStatisticsCalculator::CalculateSpectralMetrics()
{
mitk::ConnectomicsNetworkConverter::Pointer converter = mitk::ConnectomicsNetworkConverter::New();
converter->SetNetwork( m_Network );
vnl_matrix<double> adjacencyMatrix = converter->GetNetworkAsVNLAdjacencyMatrix();
vnl_symmetric_eigensystem<double> eigenSystem(adjacencyMatrix);
m_AdjacencyTrace = 0;
m_AdjacencyEnergy = 0;
m_VectorOfSortedEigenValues.clear();
for(unsigned int i=0; i < m_NumberOfVertices; ++i)
{
double value = std::fabs(eigenSystem.get_eigenvalue(i));
m_VectorOfSortedEigenValues.push_back(value);
m_AdjacencyTrace += value;
m_AdjacencyEnergy += value * value;
}
std::sort(m_VectorOfSortedEigenValues.begin(), m_VectorOfSortedEigenValues.end());
m_SpectralRadius = m_VectorOfSortedEigenValues[ m_NumberOfVertices - 1];
m_SecondLargestEigenValue = m_VectorOfSortedEigenValues[ m_NumberOfVertices - 2];
}
void mitk::ConnectomicsStatisticsCalculator::CalculateLaplacianMetrics()
{
mitk::ConnectomicsNetworkConverter::Pointer converter = mitk::ConnectomicsNetworkConverter::New();
converter->SetNetwork( m_Network );
vnl_matrix<double> adjacencyMatrix = converter->GetNetworkAsVNLAdjacencyMatrix();
vnl_matrix<double> laplacianMatrix ( m_NumberOfVertices, m_NumberOfVertices, 0);
vnl_matrix<double> degreeMatrix = converter->GetNetworkAsVNLDegreeMatrix();
m_VectorOfSortedLaplacianEigenValues.clear();
laplacianMatrix = degreeMatrix - adjacencyMatrix;
int numberOfConnectedComponents = 0;
vnl_symmetric_eigensystem <double> laplacianEigenSystem( laplacianMatrix );
m_LaplacianEnergy = 0;
m_LaplacianTrace = 0;
for(unsigned int i(0); i < m_NumberOfVertices; ++i)
{
double value = std::fabs( laplacianEigenSystem.get_eigenvalue(i) );
m_VectorOfSortedLaplacianEigenValues.push_back( value );
m_LaplacianTrace += value;
m_LaplacianEnergy += value * value;
if ( std::fabs( value ) < mitk::eps )
{
numberOfConnectedComponents++;
}
}
std::sort(m_VectorOfSortedLaplacianEigenValues.begin(), m_VectorOfSortedLaplacianEigenValues.end());
for(unsigned int i(0); i < m_VectorOfSortedLaplacianEigenValues.size(); ++i)
{
if(m_VectorOfSortedLaplacianEigenValues[i] > mitk::eps )
{
m_LaplacianSpectralGap = m_VectorOfSortedLaplacianEigenValues[i];
break;
}
}
}
void mitk::ConnectomicsStatisticsCalculator::CalculateNormalizedLaplacianMetrics()
{
vnl_matrix<double> normalizedLaplacianMatrix(m_NumberOfVertices, m_NumberOfVertices, 0);
EdgeIteratorType ei, ei_end;
VertexDescriptorType sourceVertex, destinationVertex;
int sourceIndex, destinationIndex;
VertexIndexMapType vertexIndexMap = boost::get(boost::vertex_index, *(m_Network->GetBoostGraph()) );
m_VectorOfSortedNormalizedLaplacianEigenValues.clear();
// Normalized laplacian matrix
for( boost::tie(ei, ei_end) = boost::edges( *(m_Network->GetBoostGraph()) ); ei != ei_end; ++ei)
{
sourceVertex = boost::source(*ei, *(m_Network->GetBoostGraph()) );
sourceIndex = vertexIndexMap[sourceVertex];
destinationVertex = boost::target(*ei, *(m_Network->GetBoostGraph()) );
destinationIndex = vertexIndexMap[destinationVertex];
int sourceDegree = boost::out_degree(sourceVertex, *(m_Network->GetBoostGraph()) );
int destinationDegree = boost::out_degree(destinationVertex, *(m_Network->GetBoostGraph()) );
normalizedLaplacianMatrix.put(
sourceIndex, destinationIndex, -1 / (sqrt(double(sourceDegree * destinationDegree))));
normalizedLaplacianMatrix.put(
destinationIndex, sourceIndex, -1 / (sqrt(double(sourceDegree * destinationDegree))));
}
VertexIteratorType vi, vi_end;
for(boost::tie(vi, vi_end)=boost::vertices( *(m_Network->GetBoostGraph()) ); vi!=vi_end; ++vi)
{
if(boost::out_degree(*vi, *(m_Network->GetBoostGraph()) ) > 0)
{
normalizedLaplacianMatrix.put(vertexIndexMap[*vi], vertexIndexMap[*vi], 1);
}
}
//End of normalized laplacian matrix definition
vnl_symmetric_eigensystem <double>
normalizedLaplacianEigensystem(normalizedLaplacianMatrix);
double N1=0, C1=0, D1=0, E1=0, F1=0, b1=0;
double N2=0, C2=0, D2=0, E2=0, F2=0, b2=0;
m_NormalizedLaplacianNumberOf2s = 0;
m_NormalizedLaplacianNumberOf1s = 0;
m_NormalizedLaplacianNumberOf0s = 0;
m_NormalizedLaplacianTrace = 0;
m_NormalizedLaplacianEnergy = 0;
for(unsigned int i(0); i< m_NumberOfVertices; ++i)
{
double eigenValue = std::fabs(normalizedLaplacianEigensystem.get_eigenvalue(i));
m_VectorOfSortedNormalizedLaplacianEigenValues.push_back(eigenValue);
m_NormalizedLaplacianTrace += eigenValue;
m_NormalizedLaplacianEnergy += eigenValue * eigenValue;
//0
if(eigenValue < mitk::eps)
{
m_NormalizedLaplacianNumberOf0s++;
}
//Between 0 and 1.
else if(eigenValue > mitk::eps && eigenValue< 1 - mitk::eps)
{
C1 += i;
D1 += eigenValue;
E1 += i * eigenValue;
F1 += i * i;
N1 ++;
}
//1
else if(std::fabs( std::fabs(eigenValue) - 1) < mitk::eps)
{
m_NormalizedLaplacianNumberOf1s++;
}
//Between 1 and 2
else if(std::fabs(eigenValue) > 1+mitk::eps && std::fabs(eigenValue)< 2 - mitk::eps)
{
C2 += i;
D2 += eigenValue;
E2 += i * eigenValue;
F2 += i * i;
N2 ++;
}
//2
else if(std::fabs( std::fabs(eigenValue) - 2) < mitk::eps)
{
m_NormalizedLaplacianNumberOf2s++;
}
}
b1 = (D1*F1 - C1*E1)/(F1*N1 - C1*C1);
m_NormalizedLaplacianLowerSlope = (E1 - b1*C1)/F1;
b2 = (D2*F2 - C2*E2)/(F2*N2 - C2*C2);
m_NormalizedLaplacianUpperSlope = (E2 - b2*C2)/F2;
}
void mitk::ConnectomicsStatisticsCalculator::CalculateSmallWorldness()
{
double k( this->GetAverageDegree() );
double N( this->GetNumberOfVertices() );
// The clustering coefficient of an Erdos-Reny network is equivalent to
// the likelihood two random nodes are connected
double gamma = this->GetAverageClusteringCoefficientsC() / ( k / N );
//The mean path length of an Erdos-Reny network is approximately
// ln( #vertices ) / ln( average degree )
double lambda = this->GetAveragePathLength() / ( std::log( N ) / std::log( k ) );
m_SmallWorldness = gamma / lambda;
}
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsStatisticsCalculator.h b/Modules/Connectomics/Algorithms/mitkConnectomicsStatisticsCalculator.h
index d14aee5..2cae954 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsStatisticsCalculator.h
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsStatisticsCalculator.h
@@ -1,243 +1,243 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkConnectomicsStatisticsCalculator_h
#define mitkConnectomicsStatisticsCalculator_h
#include <itkObject.h>
#include <itkObjectFactory.h>
#include <itkMacro.h>
#include "mitkCommon.h"
#include <MitkConnectomicsExports.h>
#include <mitkConnectomicsNetwork.h>
namespace mitk
{
/**
* \brief A class giving functions for calculating a variety of network indices */
class MITKCONNECTOMICS_EXPORT ConnectomicsStatisticsCalculator : public itk::Object
{
public:
/** Standard class typedefs. */
/** Method for creation through the object factory. */
mitkClassMacroItkParent(ConnectomicsStatisticsCalculator, itk::Object);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
// Typedefs
typedef mitk::ConnectomicsNetwork::NetworkType NetworkType;
typedef mitk::ConnectomicsNetwork::VertexDescriptorType VertexDescriptorType;
typedef mitk::ConnectomicsNetwork::EdgeDescriptorType EdgeDescriptorType;
typedef boost::graph_traits<NetworkType>::vertex_iterator VertexIteratorType;
typedef boost::graph_traits<NetworkType>::edge_iterator EdgeIteratorType;
typedef boost::graph_traits<NetworkType>::adjacency_iterator AdjacencyIteratorType;
typedef std::map<EdgeDescriptorType, int> EdgeIndexStdMapType;
typedef boost::associative_property_map< EdgeIndexStdMapType > EdgeIndexMapType;
typedef boost::iterator_property_map< std::vector< double >::iterator, EdgeIndexMapType > EdgeIteratorPropertyMapType;
typedef boost::property_map< NetworkType, boost::vertex_index_t>::type VertexIndexMapType;
typedef boost::iterator_property_map< std::vector< double >::iterator, VertexIndexMapType > VertexIteratorPropertyMapType;
// Set/Get Macros
itkSetObjectMacro( Network, mitk::ConnectomicsNetwork );
itkGetMacro( NumberOfVertices, unsigned int );
itkGetMacro( NumberOfEdges, unsigned int );
itkGetMacro( AverageDegree, double );
itkGetMacro( ConnectionDensity, double );
itkGetMacro( NumberOfConnectedComponents, unsigned int );
itkGetMacro( AverageComponentSize, double );
itkGetMacro( Components, std::vector< int > );
itkGetMacro( LargestComponentSize, unsigned int );
itkGetMacro( RatioOfNodesInLargestComponent, double );
itkGetMacro( HopPlotExponent, double );
itkGetMacro( EffectiveHopDiameter, double );
itkGetMacro( VectorOfClusteringCoefficientsC, std::vector< double > );
itkGetMacro( VectorOfClusteringCoefficientsD, std::vector< double > );
itkGetMacro( VectorOfClusteringCoefficientsE, std::vector< double > );
itkGetMacro( AverageClusteringCoefficientsC, double );
itkGetMacro( AverageClusteringCoefficientsD, double );
itkGetMacro( AverageClusteringCoefficientsE, double );
itkGetMacro( VectorOfVertexBetweennessCentralities, std::vector< double > );
itkGetMacro( PropertyMapOfVertexBetweennessCentralities, VertexIteratorPropertyMapType );
itkGetMacro( AverageVertexBetweennessCentrality, double );
itkGetMacro( VectorOfEdgeBetweennessCentralities, std::vector< double > );
itkGetMacro( PropertyMapOfEdgeBetweennessCentralities, EdgeIteratorPropertyMapType );
itkGetMacro( AverageEdgeBetweennessCentrality, double );
itkGetMacro( NumberOfIsolatedPoints, unsigned int );
itkGetMacro( RatioOfIsolatedPoints, double );
itkGetMacro( NumberOfEndPoints, unsigned int );
itkGetMacro( RatioOfEndPoints, double );
itkGetMacro( VectorOfEccentrities, std::vector< unsigned int > );
itkGetMacro( VectorOfEccentrities90, std::vector< unsigned int > );
itkGetMacro( VectorOfAveragePathLengths, std::vector< double > );
itkGetMacro( Diameter, unsigned int );
itkGetMacro( Diameter90, unsigned int );
itkGetMacro( Radius, unsigned int );
itkGetMacro( Radius90, unsigned int );
itkGetMacro( AverageEccentricity, double );
itkGetMacro( AverageEccentricity90, double );
itkGetMacro( AveragePathLength, double );
itkGetMacro( NumberOfCentralPoints, unsigned int );
itkGetMacro( RatioOfCentralPoints, double );
itkGetMacro( VectorOfSortedEigenValues, std::vector< double > );
itkGetMacro( SpectralRadius, double );
itkGetMacro( SecondLargestEigenValue, double );
itkGetMacro( AdjacencyTrace, double );
itkGetMacro( AdjacencyEnergy, double );
itkGetMacro( VectorOfSortedLaplacianEigenValues, std::vector< double > );
itkGetMacro( LaplacianTrace, double );
itkGetMacro( LaplacianEnergy, double );
itkGetMacro( LaplacianSpectralGap, double );
itkGetMacro( VectorOfSortedNormalizedLaplacianEigenValues, std::vector< double > );
itkGetMacro( NormalizedLaplacianTrace, double );
itkGetMacro( NormalizedLaplacianEnergy, double );
itkGetMacro( NormalizedLaplacianNumberOf2s, unsigned int );
itkGetMacro( NormalizedLaplacianNumberOf1s, unsigned int );
itkGetMacro( NormalizedLaplacianNumberOf0s, unsigned int );
itkGetMacro( NormalizedLaplacianLowerSlope, double );
itkGetMacro( NormalizedLaplacianUpperSlope, double );
itkGetMacro( SmallWorldness, double );
void Update();
protected:
//////////////////// Functions ///////////////////////
ConnectomicsStatisticsCalculator();
~ConnectomicsStatisticsCalculator() override;
void CalculateNumberOfVertices();
void CalculateNumberOfEdges();
void CalculateAverageDegree();
void CalculateConnectionDensity();
void CalculateNumberOfConnectedComponents();
void CalculateAverageComponentSize();
void CalculateLargestComponentSize();
void CalculateRatioOfNodesInLargestComponent();
void CalculateHopPlotValues();
/**
* \brief Calculate the different clustering coefficients
*
* The clustering coefficient (cc) measures how strong the tendency to form cliques
* is in the network. Groups of nodes, that are highly interconnected.
*
* CC C - Percentage of connections between nodes connected with the given node
* CC D - Same as C, but including the connections with the given node
* CC E - Same as C, but not counting isolated nodes when averaging
*/
void CalculateClusteringCoefficients();
void CalculateBetweennessCentrality();
void CalculateIsolatedAndEndPoints();
void CalculateShortestPathMetrics();
void CalculateSpectralMetrics();
void CalculateLaplacianMetrics();
void CalculateNormalizedLaplacianMetrics();
/**
* \brief Calculate the small worldness of the network.
*
* This will compare the clustering coefficient and mean path length of the network
* to an Erdos-Reny network of the same number of nodes and edges.
*/
void CalculateSmallWorldness();
/////////////////////// Variables ////////////////////////
// The connectomics network, which is used for statistics calculation
mitk::ConnectomicsNetwork::Pointer m_Network;
// Statistics
unsigned int m_NumberOfVertices;
unsigned int m_NumberOfEdges;
double m_AverageDegree;
double m_ConnectionDensity;
unsigned int m_NumberOfConnectedComponents;
double m_AverageComponentSize;
std::vector< int > m_Components;
unsigned int m_LargestComponentSize;
double m_RatioOfNodesInLargestComponent;
double m_HopPlotExponent;
double m_EffectiveHopDiameter;
std::vector< double > m_VectorOfClusteringCoefficientsC;
std::vector< double > m_VectorOfClusteringCoefficientsD;
std::vector< double > m_VectorOfClusteringCoefficientsE;
double m_AverageClusteringCoefficientsC;
double m_AverageClusteringCoefficientsD;
double m_AverageClusteringCoefficientsE;
std::vector< double > m_VectorOfVertexBetweennessCentralities;
VertexIteratorPropertyMapType m_PropertyMapOfVertexBetweennessCentralities;
double m_AverageVertexBetweennessCentrality;
std::vector< double > m_VectorOfEdgeBetweennessCentralities;
EdgeIteratorPropertyMapType m_PropertyMapOfEdgeBetweennessCentralities;
double m_AverageEdgeBetweennessCentrality;
unsigned int m_NumberOfIsolatedPoints;
double m_RatioOfIsolatedPoints;
unsigned int m_NumberOfEndPoints;
double m_RatioOfEndPoints;
std::vector< unsigned int > m_VectorOfEccentrities;
std::vector< unsigned int > m_VectorOfEccentrities90;
std::vector< double > m_VectorOfAveragePathLengths;
unsigned int m_Diameter;
unsigned int m_Diameter90;
unsigned int m_Radius;
unsigned int m_Radius90;
double m_AverageEccentricity;
double m_AverageEccentricity90;
double m_AveragePathLength;
unsigned int m_NumberOfCentralPoints;
double m_RatioOfCentralPoints;
std::vector<double> m_VectorOfSortedEigenValues;
double m_SpectralRadius;
double m_SecondLargestEigenValue;
double m_AdjacencyTrace;
double m_AdjacencyEnergy;
std::vector<double> m_VectorOfSortedLaplacianEigenValues;
double m_LaplacianTrace;
double m_LaplacianEnergy;
double m_LaplacianSpectralGap;
std::vector<double> m_VectorOfSortedNormalizedLaplacianEigenValues;
double m_NormalizedLaplacianTrace;
double m_NormalizedLaplacianEnergy;
unsigned int m_NormalizedLaplacianNumberOf2s;
unsigned int m_NormalizedLaplacianNumberOf1s;
unsigned int m_NormalizedLaplacianNumberOf0s;
double m_NormalizedLaplacianLowerSlope;
double m_NormalizedLaplacianUpperSlope;
double m_SmallWorldness;
};
}// end namespace mitk
#endif // mitkConnectomicsStatisticsCalculator_h
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsSyntheticNetworkGenerator.cpp b/Modules/Connectomics/Algorithms/mitkConnectomicsSyntheticNetworkGenerator.cpp
index d2e3bb2..bf84322 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsSyntheticNetworkGenerator.cpp
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsSyntheticNetworkGenerator.cpp
@@ -1,353 +1,353 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsSyntheticNetworkGenerator.h"
#include <sstream>
#include <vector>
#include "mitkConnectomicsConstantsManager.h"
#include <mitkConnectomicsNetworkProperties.h>
#include <vtkMatrix4x4.h>
//for random number generation
#include "vnl/vnl_random.h"
#include "vnl/vnl_math.h"
mitk::ConnectomicsSyntheticNetworkGenerator::ConnectomicsSyntheticNetworkGenerator()
: m_LastGenerationWasSuccess( false )
{
}
mitk::ConnectomicsSyntheticNetworkGenerator::~ConnectomicsSyntheticNetworkGenerator()
{
}
mitk::ConnectomicsNetwork::Pointer mitk::ConnectomicsSyntheticNetworkGenerator::CreateSyntheticNetwork(int networkTypeId, int paramterOne, double parameterTwo)
{
mitk::ConnectomicsNetwork::Pointer network = mitk::ConnectomicsNetwork::New();
m_LastGenerationWasSuccess = false;
// give the network an artificial geometry
network->SetGeometry( this->GenerateDefaultGeometry() );
switch (networkTypeId) {
case 0:
GenerateSyntheticCubeNetwork( network, paramterOne, parameterTwo );
break;
case 1:
GenerateSyntheticCenterToSurfaceNetwork( network, paramterOne, parameterTwo );
break;
case 2:
GenerateSyntheticRandomNetwork( network, paramterOne, parameterTwo );
break;
case 3:
//GenerateSyntheticScaleFreeNetwork( network, 1000 );
break;
case 4:
//GenerateSyntheticSmallWorldNetwork( network, 1000 );
break;
default:
MBI_ERROR << "Unrecognized Network ID";
}
network->UpdateBounds();
network->SetProperty(connectomicsDataAdditionalHeaderInformation.c_str(), mitk::StringProperty::New("Synthetic Network"));
return network;
}
mitk::Geometry3D::Pointer mitk::ConnectomicsSyntheticNetworkGenerator::GenerateDefaultGeometry()
{
mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New();
double zero( 0.0 );
double one( 1.0 );
// origin = {0,0,0}
mitk::Point3D origin;
origin[0] = zero;
origin[1] = zero;
origin[2] = zero;
geometry->SetOrigin(origin);
// spacing = {1,1,1}
ScalarType spacing[3];
spacing[0] = one;
spacing[1] = one;
spacing[2] = one;
geometry->SetSpacing(spacing);
// transform
vtkMatrix4x4* transformMatrix = vtkMatrix4x4::New();
transformMatrix->SetElement(0,0,one);
transformMatrix->SetElement(1,0,zero);
transformMatrix->SetElement(2,0,zero);
transformMatrix->SetElement(0,1,zero);
transformMatrix->SetElement(1,1,one);
transformMatrix->SetElement(2,1,zero);
transformMatrix->SetElement(0,2,zero);
transformMatrix->SetElement(1,2,zero);
transformMatrix->SetElement(2,2,one);
transformMatrix->SetElement(0,3,origin[0]);
transformMatrix->SetElement(1,3,origin[1]);
transformMatrix->SetElement(2,3,origin[2]);
transformMatrix->SetElement(3,3,1);
geometry->SetIndexToWorldTransformByVtkMatrix( transformMatrix );
geometry->SetImageGeometry(true);
return geometry;
}
void mitk::ConnectomicsSyntheticNetworkGenerator::GenerateSyntheticCubeNetwork(
mitk::ConnectomicsNetwork::Pointer network, int cubeExtent, double distance )
{
// map for storing the conversion from indices to vertex descriptor
std::map< int, mitk::ConnectomicsNetwork::VertexDescriptorType > idToVertexMap;
int vertexID(0);
for( int loopX( 0 ); loopX < cubeExtent; loopX++ )
{
for( int loopY( 0 ); loopY < cubeExtent; loopY++ )
{
for( int loopZ( 0 ); loopZ < cubeExtent; loopZ++ )
{
std::vector< float > position;
std::string label;
std::stringstream labelStream;
labelStream << vertexID;
label = labelStream.str();
position.push_back( loopX * distance );
position.push_back( loopY * distance );
position.push_back( loopZ * distance );
mitk::ConnectomicsNetwork::VertexDescriptorType newVertex = network->AddVertex( vertexID );
network->SetLabel( newVertex, label );
network->SetCoordinates( newVertex, position );
if ( idToVertexMap.count( vertexID ) > 0 )
{
MITK_ERROR << "Aborting network creation, duplicate vertex ID generated.";
m_LastGenerationWasSuccess = false;
return;
}
idToVertexMap.insert( std::pair< int, mitk::ConnectomicsNetwork::VertexDescriptorType >( vertexID, newVertex) );
vertexID++;
}
}
}
int edgeID(0), edgeSourceID(0), edgeTargetID(0);
// uniform weight of one
int edgeWeight(1);
mitk::ConnectomicsNetwork::VertexDescriptorType source;
mitk::ConnectomicsNetwork::VertexDescriptorType target;
for( int loopX( 0 ); loopX < cubeExtent; loopX++ )
{
for( int loopY( 0 ); loopY < cubeExtent; loopY++ )
{
for( int loopZ( 0 ); loopZ < cubeExtent; loopZ++ )
{
// to avoid creating an edge twice (this being an undirected graph) we only generate
// edges in three directions, the others will be supplied by the corresponding nodes
if( loopX != 0 )
{
edgeTargetID = edgeSourceID - cubeExtent * cubeExtent;
source = idToVertexMap.find( edgeSourceID )->second;
target = idToVertexMap.find( edgeTargetID )->second;
network->AddEdge( source, target, edgeSourceID, edgeTargetID, edgeWeight);
edgeID++;
}
if( loopY != 0 )
{
edgeTargetID = edgeSourceID - cubeExtent;
source = idToVertexMap.find( edgeSourceID )->second;
target = idToVertexMap.find( edgeTargetID )->second;
network->AddEdge( source, target, edgeSourceID, edgeTargetID, edgeWeight);
edgeID++;
}
if( loopZ != 0 )
{
edgeTargetID = edgeSourceID - 1;
source = idToVertexMap.find( edgeSourceID )->second;
target = idToVertexMap.find( edgeTargetID )->second;
network->AddEdge( source, target, edgeSourceID, edgeTargetID, edgeWeight);
edgeID++;
}
edgeSourceID++;
} // end for( int loopZ( 0 ); loopZ < cubeExtent; loopZ++ )
} // end for( int loopY( 0 ); loopY < cubeExtent; loopY++ )
} // end for( int loopX( 0 ); loopX < cubeExtent; loopX++ )
m_LastGenerationWasSuccess = true;
}
void mitk::ConnectomicsSyntheticNetworkGenerator::GenerateSyntheticCenterToSurfaceNetwork(
mitk::ConnectomicsNetwork::Pointer network, int numberOfPoints, double radius )
{
vnl_random rng( (unsigned int) rand() );
mitk::ConnectomicsNetwork::VertexDescriptorType centerVertex;
int vertexID(0);
{ //add center vertex
std::vector< float > position;
std::string label;
std::stringstream labelStream;
labelStream << vertexID;
label = labelStream.str();
position.push_back( 0 );
position.push_back( 0 );
position.push_back( 0 );
centerVertex = network->AddVertex( vertexID );
network->SetLabel( centerVertex, label );
network->SetCoordinates( centerVertex, position );
}//end add center vertex
// uniform weight of one
int edgeWeight(1);
//add vertices on sphere surface
for( int loopID( 1 ); loopID < numberOfPoints; loopID++ )
{
std::vector< float > position;
std::string label;
std::stringstream labelStream;
labelStream << loopID;
label = labelStream.str();
//generate random, uniformly distributed points on a sphere surface
const double uVariable = rng.drand64( 0.0 , 1.0);
const double vVariable = rng.drand64( 0.0 , 1.0);
const double phi = 2 * vnl_math::pi * uVariable;
const double theta = std::acos( 2 * vVariable - 1 );
double xpos = radius * std::cos( phi ) * std::sin( theta );
double ypos = radius * std::sin( phi ) * std::sin( theta );
double zpos = radius * std::cos( theta );
position.push_back( xpos );
position.push_back( ypos );
position.push_back( zpos );
mitk::ConnectomicsNetwork::VertexDescriptorType newVertex = network->AddVertex( loopID );
network->SetLabel( newVertex, label );
network->SetCoordinates( newVertex, position );
network->AddEdge( newVertex, centerVertex, loopID, 0, edgeWeight);
}
m_LastGenerationWasSuccess = true;
}
void mitk::ConnectomicsSyntheticNetworkGenerator::GenerateSyntheticRandomNetwork(
mitk::ConnectomicsNetwork::Pointer network, int numberOfPoints, double threshold )
{
// as the surface is proportional to the square of the radius the density stays the same
double radius = 5 * std::sqrt( (float) numberOfPoints );
vnl_random rng( (unsigned int) rand() );
// map for storing the conversion from indices to vertex descriptor
std::map< int, mitk::ConnectomicsNetwork::VertexDescriptorType > idToVertexMap;
//add vertices on sphere surface
for( int loopID( 0 ); loopID < numberOfPoints; loopID++ )
{
std::vector< float > position;
std::string label;
std::stringstream labelStream;
labelStream << loopID;
label = labelStream.str();
//generate random, uniformly distributed points on a sphere surface
const double uVariable = rng.drand64( 0.0 , 1.0);
const double vVariable = rng.drand64( 0.0 , 1.0);
const double phi = 2 * vnl_math::pi * uVariable;
const double theta = std::acos( 2 * vVariable - 1 );
double xpos = radius * std::cos( phi ) * std::sin( theta );
double ypos = radius * std::sin( phi ) * std::sin( theta );
double zpos = radius * std::cos( theta );
position.push_back( xpos );
position.push_back( ypos );
position.push_back( zpos );
mitk::ConnectomicsNetwork::VertexDescriptorType newVertex = network->AddVertex( loopID );
network->SetLabel( newVertex, label );
network->SetCoordinates( newVertex, position );
if ( idToVertexMap.count( loopID ) > 0 )
{
MITK_ERROR << "Aborting network creation, duplicate vertex ID generated.";
m_LastGenerationWasSuccess = false;
return;
}
idToVertexMap.insert( std::pair< int, mitk::ConnectomicsNetwork::VertexDescriptorType >( loopID, newVertex) );
}
int edgeID(0);
// uniform weight of one
int edgeWeight(1);
mitk::ConnectomicsNetwork::VertexDescriptorType source;
mitk::ConnectomicsNetwork::VertexDescriptorType target;
for( int loopID( 0 ); loopID < numberOfPoints; loopID++ )
{
// to avoid creating an edge twice (this being an undirected graph) we only
// potentially generate edges with all nodes with a bigger ID
for( int innerLoopID( loopID ); innerLoopID < numberOfPoints; innerLoopID++ )
{
if( rng.drand64( 0.0 , 1.0) > threshold)
{
// do nothing
}
else
{
source = idToVertexMap.find( loopID )->second;
target = idToVertexMap.find( innerLoopID )->second;
network->AddEdge( source, target, loopID, innerLoopID, edgeWeight);
edgeID++;
}
} // end for( int innerLoopID( loopID ); innerLoopID < numberOfPoints; innerLoopID++ )
} // end for( int loopID( 0 ); loopID < numberOfPoints; loopID++ )
m_LastGenerationWasSuccess = true;
}
bool mitk::ConnectomicsSyntheticNetworkGenerator::WasGenerationSuccessfull()
{
return m_LastGenerationWasSuccess;
}
diff --git a/Modules/Connectomics/Algorithms/mitkConnectomicsSyntheticNetworkGenerator.h b/Modules/Connectomics/Algorithms/mitkConnectomicsSyntheticNetworkGenerator.h
index 7b2a10d..f0f106a 100644
--- a/Modules/Connectomics/Algorithms/mitkConnectomicsSyntheticNetworkGenerator.h
+++ b/Modules/Connectomics/Algorithms/mitkConnectomicsSyntheticNetworkGenerator.h
@@ -1,88 +1,88 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkConnectomicsSyntheticNetworkGenerator_h
#define mitkConnectomicsSyntheticNetworkGenerator_h
#include <itkObject.h>
#include <itkObjectFactory.h>
#include <itkMacro.h>
#include "mitkCommon.h"
#include "mitkImage.h"
#include "mitkConnectomicsNetwork.h"
#include <MitkConnectomicsExports.h>
namespace mitk
{
/**
* \brief A class to generate synthetic networks */
class MITKCONNECTOMICS_EXPORT ConnectomicsSyntheticNetworkGenerator : public itk::Object
{
public:
/** Standard class typedefs. */
/** Method for creation through the object factory. */
mitkClassMacroItkParent(ConnectomicsSyntheticNetworkGenerator, itk::Object);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Create Synthetic Networks */
mitk::ConnectomicsNetwork::Pointer CreateSyntheticNetwork(int networkTypeId, int paramterOne, double parameterTwo);
/** Return whether the last attempted network generation was a success*/
bool WasGenerationSuccessfull();
protected:
//////////////////// Functions ///////////////////////
ConnectomicsSyntheticNetworkGenerator();
~ConnectomicsSyntheticNetworkGenerator() override;
/** Generate a default geometry for synthetic images */
mitk::Geometry3D::Pointer GenerateDefaultGeometry();
/** Generate a synthetic cube (regular lattice) network */
void GenerateSyntheticCubeNetwork( mitk::ConnectomicsNetwork::Pointer network, int cubeExtent, double distance );
/** Generate a highly heterogenic network
*
* This is achieved by generating a center vertex and vertices on
* a sphere surface, which are all only connected to the center
* vertex. */
void GenerateSyntheticCenterToSurfaceNetwork(
mitk::ConnectomicsNetwork::Pointer network, int numberOfPoints, double radius );
/** Generate a random network without specific characteristics
*
* This is achieved by generating vertices and then deciding whether to
* specific vertices are connected by comparing a random number to the threshold */
void GenerateSyntheticRandomNetwork(
mitk::ConnectomicsNetwork::Pointer network, int numberOfPoints, double threshold );
/////////////////////// Variables ////////////////////////
/** Store whether the network generated last was generated properly */
bool m_LastGenerationWasSuccess;
};
}// end namespace mitk
#endif // _mitkConnectomicsSyntheticNetworkGenerator_H_INCLUDED
diff --git a/Modules/Connectomics/Algorithms/mitkCorrelationCalculator.h b/Modules/Connectomics/Algorithms/mitkCorrelationCalculator.h
index 6228341..c61d513 100644
--- a/Modules/Connectomics/Algorithms/mitkCorrelationCalculator.h
+++ b/Modules/Connectomics/Algorithms/mitkCorrelationCalculator.h
@@ -1,173 +1,173 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_CORRELATIONCALCULATOR_H
#define _MITK_CORRELATIONCALCULATOR_H
#include "mitkCommon.h"
#include <itkObject.h>
#include <mitkImage.h>
#include <vnl/vnl_matrix.h>
#include <mitkConnectomicsNetwork.h>
namespace mitk {
/**
* \brief Class to calculate covariance and correlation
*
* In addition to static functions to calculate covariance and correlation,
* this class offers capability to set a time series image and optionally a
* parcellation image and calculate a correlation matrix.
*
* Whole correlation only needs a time series image and will return a
* #voxel x #voxel matrix where each voxel's time series is correlated
* against the time series of each other voxel.
*
* Parcel correlation will compute an average time series for each parcel
* of a parcellation image and create a #parcel x #parcel correlation matrix.
*
* Please note that time series images are assumed to be 4D and parcellation
* images integer valued and 3D.
*/
template< class T >
class CorrelationCalculator : public itk::Object
{
public:
// Standard macros
mitkClassMacroItkParent(CorrelationCalculator, itk::Object);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/**
* @brief The ParcelMode enum defines how to define the correlation between two parcels
*
* Available choices are:
* <ol>
* <li> UseAverageTimeSeries - Average time series across the parcel, correlate average time series between parcels
* <li> UseMaximumCorrelation - Correlate all voxels of the parcels with each other, use maximum correlation
* <li> UseAverageCorrelation - Correlate all voxels of the parcels with each other, use average correlation
* </ol>
*/
enum ParcelMode
{
UseAverageTimeSeries,
UseMaximumCorrelation,
UseAverageCorrelation
};
/**
* @brief Calculate and return the pearson correlation coefficient for two vectors of data
*
* This function expects two vectors of the same length and data type and calculates the
* pearson correlation coefficient.
*
* @param one first data vector
* @param two second data vector
* @return pearson correlation coefficent
*/
static double CalculatePearsonCorrelationCoefficient( const std::vector<T>& one, const std::vector<T>& two );
/**
* @brief Calculates the covariance of two vectors of data
*
* Expects two vectors of the same length and data type and returns the covariance of the two.
* Variance can be calculated by providing the same data vector twice.
*
* @param one first data vector
* @param two second data vector
* @return covariance of the two
*/
static double CalculateCovariance( const std::vector<T>& one, const std::vector<T>& two );
/**
* @brief Extracts the average time series from a roi defined by the parcellation image
*
* This function requires a parcellation image and a time series image to be set and registered to each other.
* For each voxel in the time series image it will check whether it is inside the specified parcel of the
* parcellation image. All inside voxels will be averaged for all time steps and an average time series
* is returned.
*
* Calculates and saves the averages for all parcellations, to speed up consecutive calls.
*
* @param parcelValue the voxel value of the roi in the parcellation image.
* @return vector of the average values of the roi for each timestep
*/
std::vector< double > ExtractAverageTimeSeriesOfParcel( int parcelValue );
/**
* @brief Create a #voxel x #voxel correlation matrix
*/
void DoWholeCorrelation();
/**
* @brief Create a #parcel x #parcel correlation matrix
*/
void DoParcelCorrelation( ParcelMode mode = UseAverageTimeSeries );
/**
* @brief Marks average time series as invalid and calls superclass modified
*/
virtual void Modified();
const vnl_matrix< double >* GetCorrelationMatrix() const;
const std::map< unsigned int, int >* GetLabelOrderMap() const;
mitk::ConnectomicsNetwork::Pointer GetConnectomicsNetwork();
// Get/Set macros
itkSetMacro(ParcellationImage, mitk::Image::Pointer)
itkSetMacro(TimeSeriesImage, mitk::Image::Pointer)
protected:
// intentionally not accessible, use our non-const Modified function instead
void Modified() const override;
CorrelationCalculator();
~CorrelationCalculator() override;
template< typename TPixel, unsigned int VImageDimension >
void ExtractAllAverageTimeSeries( itk::Image< TPixel, VImageDimension>* itkTimeSeriesImage );
void ExtractCenterOfMassForParcels();
double GetParcelCorrelation(const int& parcelA,const int& parcelB, ParcelMode& mode) const;
// Member variables
bool m_InvalidTimeSeries;
mitk::Image::Pointer m_ParcellationImage;
mitk::Image::Pointer m_TimeSeriesImage;
std::map< int, std::vector<double> > m_AverageTimeSeries;
std::map< int, std::vector<std::vector< T > > > m_ParcelTimeSeries;
std::map< int, mitk::Point3D > m_ParcelCenterOfMass;
vnl_matrix< double > m_CorrelationMatrix;
std::map< unsigned int, int > m_LabelOrderMap;
};
}
#include <mitkCorrelationCalculator.txx>
#endif /* _MITK_CORRELATIONCALCULATOR_H */
diff --git a/Modules/Connectomics/Algorithms/mitkCorrelationCalculator.txx b/Modules/Connectomics/Algorithms/mitkCorrelationCalculator.txx
index df72f8f..04315e0 100644
--- a/Modules/Connectomics/Algorithms/mitkCorrelationCalculator.txx
+++ b/Modules/Connectomics/Algorithms/mitkCorrelationCalculator.txx
@@ -1,454 +1,454 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_CORRELATIONCALCULATOR_TXX
#define _MITK_CORRELATIONCALCULATOR_TXX
#include <algorithm>
#include <numeric>
#include <mitkLogMacros.h>
#include <mitkLog.h>
#include <mitkImageCast.h>
#include <mitkImageAccessByItk.h>
#include <mitkImagePixelReadAccessor.h>
#include <itkImageRegionConstIteratorWithIndex.h>
template< class T >
mitk::CorrelationCalculator<T>::CorrelationCalculator()
: m_InvalidTimeSeries( true )
, m_ParcellationImage( nullptr )
, m_TimeSeriesImage( nullptr )
{
}
template< class T >
mitk::CorrelationCalculator<T>::~CorrelationCalculator()
{
}
template< class T >
double mitk::CorrelationCalculator<T>::CalculatePearsonCorrelationCoefficient( const std::vector<T>& one, const std::vector<T>& two )
{
double standardDevOne( std::sqrt(CalculateCovariance( one, one )) );
double standardDevTwo( std::sqrt(CalculateCovariance( two, two )) );
return CalculateCovariance(one, two) / (standardDevOne * standardDevTwo);
}
template< class T >
double mitk::CorrelationCalculator<T>::CalculateCovariance( const std::vector<T>& one, const std::vector<T>& two )
{
if( one.size() != two.size() )
{
MITK_WARN << "Expect two same length vectors for covariance.";
return 0;
}
double meanOne( std::accumulate( one.begin(), one.end(), 0.0 ) / double(one.size()) );
double meanTwo( std::accumulate( two.begin(), two.end(), 0.0 ) / double(two.size()) );
double sum( 0.0 );
for(unsigned int index(0); index < one.size(); ++index)
{
sum += (one[index] - meanOne ) * (two[index] - meanTwo);
}
double n( one.size() );
return sum/n;
}
template< class T >
std::vector< double > mitk::CorrelationCalculator<T>::ExtractAverageTimeSeriesOfParcel( int parcelValue )
{
if( this->m_InvalidTimeSeries)
{
this->ExtractAllAverageTimeSeries();
this->m_InvalidTimeSeries = false;
}
std::vector< double > result;
if( m_AverageTimeSeries.count(parcelValue) > 0 )
{
result = m_AverageTimeSeries.find(parcelValue)->second;
}
return result;
}
template< class T >
void mitk::CorrelationCalculator<T>::DoWholeCorrelation( )
{
if(this->m_TimeSeriesImage->GetDimension() != 4 )
{
MITK_ERROR << "Expect 3D+t timeseries image.";
return;
}
// calculate numbe of voxels
unsigned int numberOfVoxels(1);
unsigned int dim[3];
for(unsigned int loop(0); loop < 3; ++loop)
{
numberOfVoxels *= this->m_TimeSeriesImage->GetDimension( loop );
dim[loop] = this->m_TimeSeriesImage->GetDimension( loop );
}
m_CorrelationMatrix = vnl_matrix<double>(numberOfVoxels, numberOfVoxels);
unsigned int numberOfSteps( this->m_TimeSeriesImage->GetDimension( 3 ));
//iterate over all voxels and calculate correlation
for( unsigned int i( 0 ); i < numberOfVoxels; ++i )
{
for( unsigned int j(0); j < i; ++j)
{
std::vector< T > one, two;
one.resize(numberOfSteps);
two.resize(numberOfSteps);
mitk::ImagePixelReadAccessor<T, 4> readAccess(m_TimeSeriesImage);
itk::Index<4> idx_i;
itk::Index<4> idx_j;
idx_i[2] = (i / (dim[0] * dim[1])) % dim[2];
idx_i[1] = (i / dim[0]) % dim[1];
idx_i[0] = i % dim[0];
idx_j[2] = (j / (dim[0] * dim[1])) % dim[2];
idx_j[1] = (j / dim[0]) % dim[1];
idx_j[0] = j % dim[0];
for(unsigned int timestep(0); timestep < numberOfSteps; ++timestep)
{
idx_i[3] = timestep;
idx_j[3] = timestep;
one[timestep] = readAccess.GetPixelByIndex(idx_i);
two[timestep] = readAccess.GetPixelByIndex(idx_j);
}
m_CorrelationMatrix[i][j] = mitk::CorrelationCalculator<T>::CalculatePearsonCorrelationCoefficient( one, two );
m_CorrelationMatrix[j][i] = m_CorrelationMatrix[i][j];
}
m_CorrelationMatrix[i][i] = 1;
}
}
template< class T >
void mitk::CorrelationCalculator<T>::DoParcelCorrelation( typename mitk::CorrelationCalculator<T>::ParcelMode mode )
{
this->ExtractCenterOfMassForParcels();
m_CorrelationMatrix = vnl_matrix<double>(m_ParcelCenterOfMass.size(), m_ParcelCenterOfMass.size());
AccessFixedDimensionByItk(this->m_TimeSeriesImage, ExtractAllAverageTimeSeries, 4);
// fill matrix
unsigned int i(0);
for( std::map< int, std::vector<double> >::const_iterator it(m_AverageTimeSeries.begin()); it != m_AverageTimeSeries.end(); ++it, ++i)
{
unsigned int j(0);
for(std::map< int, std::vector<double> >::const_iterator inner_it(m_AverageTimeSeries.begin()); inner_it != it; ++inner_it, ++j)
{
switch( mode )
{
case UseAverageTimeSeries :
m_CorrelationMatrix[i][j] = mitk::CorrelationCalculator<double>::CalculatePearsonCorrelationCoefficient( it->second, inner_it->second );
break;
case UseMaximumCorrelation :
m_CorrelationMatrix[i][j] = mitk::CorrelationCalculator<T>::GetParcelCorrelation(it->first, inner_it->first, mode);
break;
case UseAverageCorrelation :
m_CorrelationMatrix[i][j] = mitk::CorrelationCalculator<T>::GetParcelCorrelation(it->first, inner_it->first, mode);
break;
default:
mitkThrow() << "No valid parcel correlation mode selected";
}
m_CorrelationMatrix[j][i] = m_CorrelationMatrix[i][j];
}
m_CorrelationMatrix[i][i] = 1;
m_LabelOrderMap.insert(std::pair< unsigned int, int >(i, it->first));
}
}
template< class T >
double mitk::CorrelationCalculator<T>::GetParcelCorrelation(const int& parcelA, const int& parcelB, typename mitk::CorrelationCalculator<T>::ParcelMode& mode) const
{
double result(0.0);
if(m_ParcelTimeSeries.count(parcelA) < 1 || m_ParcelTimeSeries.count(parcelB) < 1)
{
MITK_ERROR << "Tried to calculate correlation between at least one non-existent parcel " << parcelA << " and " << parcelB;
return result;
}
std::vector< std::vector< T > > parcelATimeSeriesVector = m_ParcelTimeSeries.find( parcelA )->second;
std::vector< std::vector< T > > parcelBTimeSeriesVector = m_ParcelTimeSeries.find( parcelB )->second;
switch( mode )
{
case UseAverageTimeSeries :
{
mitkThrow() << "Wrong function called for this mode.";
break;
}
case UseMaximumCorrelation :
{
for(unsigned int i(0); i < parcelATimeSeriesVector.size(); ++i)
{
for(unsigned int j(0); j < parcelBTimeSeriesVector.size(); ++j)
{
double corr =
mitk::CorrelationCalculator<T>::CalculatePearsonCorrelationCoefficient(
parcelATimeSeriesVector[i], parcelBTimeSeriesVector[j]
);
if( corr > result )
{
result = corr;
}
}
}
break;
}
case UseAverageCorrelation :
{
double corr(0.0);
for(unsigned int i(0); i < parcelATimeSeriesVector.size(); ++i)
{
for(unsigned int j(0); j < parcelBTimeSeriesVector.size(); ++j)
{
corr +=
mitk::CorrelationCalculator<T>::CalculatePearsonCorrelationCoefficient(
parcelATimeSeriesVector[i], parcelBTimeSeriesVector[j]
);
}
}
result = corr / double( parcelATimeSeriesVector.size() * parcelBTimeSeriesVector.size() );
break;
}
default:
{
mitkThrow() << "No valid parcel correlation mode selected";
}
}
return result;
}
template< class T >
void mitk::CorrelationCalculator<T>::Modified( ) const
{
Superclass::Modified();
}
template< class T >
void mitk::CorrelationCalculator<T>::Modified( )
{
Superclass::Modified();
this->m_InvalidTimeSeries = true;
}
template< class T>
template< typename TPixel, unsigned int VImageDimension >
void mitk::CorrelationCalculator<T>::ExtractAllAverageTimeSeries( itk::Image<TPixel, VImageDimension>* itkTimeSeriesImage )
{
// storage contains for each parcel value a vector of length time steps,
// which manages the pixel value vectors for each time step
std::map< int, std::vector< std::vector< T > > > storage;
itk::ImageRegionConstIteratorWithIndex< itk::Image<TPixel, VImageDimension> > it_itkTimeSeriesImage(
itkTimeSeriesImage, itkTimeSeriesImage->GetLargestPossibleRegion() );
unsigned int timesteps( itkTimeSeriesImage->GetLargestPossibleRegion().GetSize()[3] );
for( it_itkTimeSeriesImage.GoToBegin(); !it_itkTimeSeriesImage.IsAtEnd(); ++it_itkTimeSeriesImage )
{
itk::Index< 4 > itkIndex = it_itkTimeSeriesImage.GetIndex();
itk::Index< 3 > itkIndex3D;
for(unsigned int axis( 0 ); axis < 3; ++axis )
{
itkIndex3D.SetElement( axis, itkIndex.GetElement(axis) );
}
mitk::Point3D tempPoint;
m_TimeSeriesImage->GetGeometry()->IndexToWorld( itkIndex3D, tempPoint );
mitk::ImagePixelReadAccessor<int, 3> readAccess(m_ParcellationImage);
int value( std::floor( readAccess.GetPixelByWorldCoordinates( tempPoint ) + 0.5 ) );
if(storage.count(value) == 0)
{
std::vector< std::vector< T > > temp;
temp.resize( timesteps );
storage.insert(std::pair< int, std::vector< std::vector< T > > >(value, temp));
}
storage[value][ itkIndex.GetElement( 3 ) ].push_back( it_itkTimeSeriesImage.Value() );
}
// store means
for( typename std::map< int, std::vector< std::vector< T > > >::iterator it = storage.begin(); it != storage.end(); ++it )
{
std::vector< double > means;
means.resize( timesteps );
for(unsigned int loop(0); loop < timesteps; ++loop)
{
means[loop] = std::accumulate( it->second[loop].begin(), it->second[loop].end(), 0.0 ) / double(it->second[loop].size());
}
m_AverageTimeSeries.insert( std::pair< int, std::vector< double > >(it->first, means) );
// reorder the information in storage for m_ParcelTimeSeries
// time series of each voxel by their parcellation value
std::vector< std::vector< T > > vectorOfTimeSeriesVectors;
vectorOfTimeSeriesVectors.resize(it->second[0].size());
for(unsigned int loop(0); loop < vectorOfTimeSeriesVectors.size(); ++loop)
{
vectorOfTimeSeriesVectors[loop].resize(timesteps);
}
for(unsigned int step(0); step < timesteps; ++step)
{
for(unsigned int number(0); number < vectorOfTimeSeriesVectors.size(); ++number)
{
vectorOfTimeSeriesVectors[number][step] = it->second[step][number];
}
}
m_ParcelTimeSeries.insert(std::pair< int, std::vector< std::vector< T > > >(it->first, vectorOfTimeSeriesVectors));
}
}
template< class T >
void mitk::CorrelationCalculator<T>::ExtractCenterOfMassForParcels()
{
itk::Image< int, 3 >::Pointer itkParcelImage;
mitk::CastToItkImage( m_ParcellationImage, itkParcelImage );
itk::ImageRegionConstIteratorWithIndex< itk::Image<int, 3> > it_itkParcelImage(
itkParcelImage, itkParcelImage->GetLargestPossibleRegion() );
std::map< int, std::vector< mitk::Point3D > > storage;
for( it_itkParcelImage.GoToBegin(); !it_itkParcelImage.IsAtEnd(); ++it_itkParcelImage )
{
mitk::Point3D tempPoint;
m_ParcellationImage->GetGeometry()->IndexToWorld( it_itkParcelImage.GetIndex(), tempPoint );
if( storage.count( it_itkParcelImage.Value() ) == 1 )
{
storage[ it_itkParcelImage.Value() ].push_back( tempPoint );
}
else
{
storage.insert( std::pair< int, std::vector< mitk::Point3D > >(
it_itkParcelImage.Value(), std::vector< mitk::Point3D >( 1, tempPoint ) ));
}
}
for( std::map< int, std::vector< mitk::Point3D > >::iterator it( storage.begin() ); it != storage.end(); ++it )
{
itk::Vector< int, 3 > tempVector( 0 );
for( unsigned int loop(0); loop < it->second.size(); ++loop)
{
for(unsigned int index(0); index < 3; ++index)
{
tempVector[index] = tempVector[index] + it->second[loop][index];
}
}
mitk::Point3D tempPoint;
for( unsigned int loop(0); loop < 3; ++loop )
{
tempPoint.SetElement(loop, tempVector.GetElement(loop) / it->second.size());
}
m_ParcelCenterOfMass.insert( std::pair< int, mitk::Point3D >(it->first, tempPoint) );
}
}
template< class T >
const vnl_matrix< double >* mitk::CorrelationCalculator<T>::GetCorrelationMatrix() const
{
return &m_CorrelationMatrix;
}
template< class T >
const std::map< unsigned int, int >* mitk::CorrelationCalculator<T>::GetLabelOrderMap() const
{
return &m_LabelOrderMap;
}
template< class T >
mitk::ConnectomicsNetwork::Pointer mitk::CorrelationCalculator<T>::GetConnectomicsNetwork()
{
mitk::ConnectomicsNetwork::NetworkType* boostGraph = new mitk::ConnectomicsNetwork::NetworkType;
std::map< int, mitk::ConnectomicsNetwork::VertexDescriptorType > idToVertexMap;
// fill nodes
unsigned int numberOfNodes( m_CorrelationMatrix.columns() );
for(unsigned int loop(0); loop < numberOfNodes; ++loop )
{
idToVertexMap.insert( std::pair< int, mitk::ConnectomicsNetwork::VertexDescriptorType >(loop, boost::add_vertex( *boostGraph )) );
}
if( m_ParcelCenterOfMass.size() > 0)
{
std::map< int, mitk::Point3D >::const_iterator it = m_ParcelCenterOfMass.begin();
for(unsigned int loop(0); (loop < numberOfNodes) && (it != m_ParcelCenterOfMass.end()); ++loop, ++it )
{
(*boostGraph)[ idToVertexMap[loop] ].id = idToVertexMap[loop];
(*boostGraph)[ idToVertexMap[loop] ].label = std::to_string( it->first );
(*boostGraph)[ idToVertexMap[loop] ].coordinates.resize(3);
for(unsigned int dimension(0); dimension < 3; ++dimension)
{
(*boostGraph)[ idToVertexMap[loop] ].coordinates[dimension] = it->second[dimension];
}
}
}
//fill edges
for( unsigned int i(0); i < numberOfNodes; ++i)
{
for(unsigned int j(0); j < i; ++j)
{
mitk::ConnectomicsNetwork::VertexDescriptorType vertexA = idToVertexMap[i];
mitk::ConnectomicsNetwork::VertexDescriptorType vertexB = idToVertexMap[j];
boost::add_edge( vertexA, vertexB, *boostGraph );
(*boostGraph)[ boost::edge(vertexA, vertexB, *boostGraph ).first ].sourceId = (*boostGraph)[vertexA].id;
(*boostGraph)[ boost::edge(vertexA, vertexB, *boostGraph ).first ].targetId = (*boostGraph)[vertexB].id;
(*boostGraph)[ boost::edge(vertexA, vertexB, *boostGraph ).first ].fiber_count = 1;
(*boostGraph)[ boost::edge(vertexA, vertexB, *boostGraph ).first ].edge_weight = m_CorrelationMatrix[i][j];
}
}
// create data node
mitk::ConnectomicsNetwork::Pointer network = mitk::ConnectomicsNetwork::New();
network->SetBoostGraph( boostGraph );
network->SetGeometry( dynamic_cast<mitk::BaseGeometry*>(m_TimeSeriesImage->GetGeometry()->Clone().GetPointer()) );
network->UpdateBounds();
network->SetIsModified( true );
return network;
}
#endif /* _MITK_CORRELATIONCALCULATOR_TXX */
diff --git a/Modules/Connectomics/Algorithms/mitkFreeSurferParcellationTranslator.cpp b/Modules/Connectomics/Algorithms/mitkFreeSurferParcellationTranslator.cpp
index e3b9b7b..a07a002 100644
--- a/Modules/Connectomics/Algorithms/mitkFreeSurferParcellationTranslator.cpp
+++ b/Modules/Connectomics/Algorithms/mitkFreeSurferParcellationTranslator.cpp
@@ -1,3919 +1,3919 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkLookupTableProperty.h>
#include <mitkRenderingModeProperty.h>
#include <mitkTransferFunctionProperty.h>
#include "mitkFreeSurferParcellationTranslator.h"
using namespace mitk;
/*########### Static Members ###########*/
LookupTable::Pointer FreeSurferParcellationTranslator::m_LookupTable = FreeSurferParcellationTranslator::CreateLookupTable();
const FreeSurferParcellationTranslator::NameTable FreeSurferParcellationTranslator::m_NameTable = FreeSurferParcellationTranslator::CreateNameTable();
TransferFunction::Pointer FreeSurferParcellationTranslator::m_TransferFunction = FreeSurferParcellationTranslator::CreateTransferFunction();
/*########### Constructors ###########*/
FreeSurferParcellationTranslator::FreeSurferParcellationTranslator()
{
}
FreeSurferParcellationTranslator::~FreeSurferParcellationTranslator()
{
}
/*########### Methods ###########*/
// Assign the lookup table to the given node
void FreeSurferParcellationTranslator::AssignLookupTable(DataNode::Pointer node) const
{
LookupTableProperty::Pointer lookupTableProp = LookupTableProperty::New( this->GetLookupTable() );
node->SetProperty( "LookupTable", lookupTableProp );
}
// Assign the color transfer function to the given node
void FreeSurferParcellationTranslator::AssignTransferFunction(DataNode::Pointer node) const
{
TransferFunctionProperty::Pointer transferFunctionProp = TransferFunctionProperty::New( this->GetTransferFunction() );
node->SetProperty( "Image Rendering.Transfer Function", transferFunctionProp );
}
// Get the label assigned to the given name
const std::string FreeSurferParcellationTranslator::GetLabel(const std::string& name) const
{
NameTable::const_iterator iter;
for( iter = m_NameTable.begin(); iter != m_NameTable.end(); ++iter )
{
if( iter->second == name )
return iter->first;
}
return "0";
}
// Get the label assigned to the given name as integer
int FreeSurferParcellationTranslator::GetLabelAsNumber(const std::string &name) const
{
return std::atoi(this->GetLabel( name ).c_str()) ;
}
// Return the lookup table
LookupTable::Pointer FreeSurferParcellationTranslator::GetLookupTable() const
{
return m_LookupTable;
}
// Get the name assigned to the given label
const std::string FreeSurferParcellationTranslator::GetName(const std::string & label) const
{
auto endIter = this->m_NameTable.end();
auto iter = this->m_NameTable.find( label );
if( iter != endIter )
{
return iter->second;
}
else
{
return "Unknown area or outside the cerebrum.";
}
}
// Get the name assigned to the given label
const std::string FreeSurferParcellationTranslator::GetName(int label) const
{
std::stringstream ss;//create a stringstream
ss << label;//add number to the stream
return this->GetName( ss.str() );
}
// Get the transfer function
TransferFunction::Pointer FreeSurferParcellationTranslator::GetTransferFunction() const
{
return m_TransferFunction;
}
LookupTable::Pointer FreeSurferParcellationTranslator::CreateLookupTable()
{
vtkSmartPointer<vtkLookupTable> table = vtkSmartPointer<vtkLookupTable>::New();
table->SetRange(0.0, 14175.0);
table->SetNumberOfTableValues( 14176.0 ); // Count of the overall range (0 - 14175)
table->Build();
table->SetTableValue( 0.0, 0, 0, 0, 0);
table->SetTableValue( 1.0, 0.27451, 0.509804, 0.705882 );
table->SetTableValue( 2.0, 0.960784, 0.960784, 0.960784 );
table->SetTableValue( 3.0, 0.803922, 0.243137, 0.305882 );
table->SetTableValue( 4.0, 0.470588, 0.0705882, 0.52549 );
table->SetTableValue( 5.0, 0.768627, 0.227451, 0.980392 );
table->SetTableValue( 6.0, 0, 0.580392, 0 );
table->SetTableValue( 7.0, 0.862745, 0.972549, 0.643137 );
table->SetTableValue( 8.0, 0.901961, 0.580392, 0.133333 );
table->SetTableValue( 9.0, 0, 0.462745, 0.054902 );
table->SetTableValue( 10.0, 0, 0.462745, 0.054902 );
table->SetTableValue( 11.0, 0.478431, 0.729412, 0.862745 );
table->SetTableValue( 12.0, 0.92549, 0.0509804, 0.690196 );
table->SetTableValue( 13.0, 0.0470588, 0.188235, 1 );
table->SetTableValue( 14.0, 0.8, 0.713725, 0.556863 );
table->SetTableValue( 15.0, 0.164706, 0.8, 0.643137 );
table->SetTableValue( 16.0, 0.466667, 0.623529, 0.690196 );
table->SetTableValue( 17.0, 0.862745, 0.847059, 0.0784314 );
table->SetTableValue( 18.0, 0.403922, 1, 1 );
table->SetTableValue( 19.0, 0.313725, 0.768627, 0.384314 );
table->SetTableValue( 20.0, 0.235294, 0.227451, 0.823529 );
table->SetTableValue( 21.0, 0.235294, 0.227451, 0.823529 );
table->SetTableValue( 22.0, 0.235294, 0.227451, 0.823529 );
table->SetTableValue( 23.0, 0.235294, 0.227451, 0.823529 );
table->SetTableValue( 24.0, 0.235294, 0.235294, 0.235294 );
table->SetTableValue( 25.0, 1, 0.647059, 0 );
table->SetTableValue( 26.0, 1, 0.647059, 0 );
table->SetTableValue( 27.0, 0, 1, 0.498039 );
table->SetTableValue( 28.0, 0.647059, 0.164706, 0.164706 );
table->SetTableValue( 29.0, 0.529412, 0.807843, 0.921569 );
table->SetTableValue( 30.0, 0.627451, 0.12549, 0.941176 );
table->SetTableValue( 31.0, 0, 0.784314, 0.784314 );
table->SetTableValue( 32.0, 0.392157, 0.196078, 0.392157 );
table->SetTableValue( 33.0, 0.529412, 0.196078, 0.290196 );
table->SetTableValue( 34.0, 0.478431, 0.529412, 0.196078 );
table->SetTableValue( 35.0, 0.2, 0.196078, 0.529412 );
table->SetTableValue( 36.0, 0.290196, 0.607843, 0.235294 );
table->SetTableValue( 37.0, 0.470588, 0.243137, 0.168627 );
table->SetTableValue( 38.0, 0.290196, 0.607843, 0.235294 );
table->SetTableValue( 39.0, 0.478431, 0.529412, 0.196078 );
table->SetTableValue( 40.0, 0.27451, 0.509804, 0.705882 );
table->SetTableValue( 41.0, 0, 0.882353, 0 );
table->SetTableValue( 42.0, 0.803922, 0.243137, 0.305882 );
table->SetTableValue( 43.0, 0.470588, 0.0705882, 0.52549 );
table->SetTableValue( 44.0, 0.768627, 0.227451, 0.980392 );
table->SetTableValue( 45.0, 0, 0.580392, 0 );
table->SetTableValue( 46.0, 0.862745, 0.972549, 0.643137 );
table->SetTableValue( 47.0, 0.901961, 0.580392, 0.133333 );
table->SetTableValue( 48.0, 0, 0.462745, 0.054902 );
table->SetTableValue( 49.0, 0, 0.462745, 0.054902 );
table->SetTableValue( 50.0, 0.478431, 0.729412, 0.862745 );
table->SetTableValue( 51.0, 0.92549, 0.0509804, 0.690196 );
table->SetTableValue( 52.0, 0.0509804, 0.188235, 1 );
table->SetTableValue( 53.0, 0.862745, 0.847059, 0.0784314 );
table->SetTableValue( 54.0, 0.403922, 1, 1 );
table->SetTableValue( 55.0, 0.313725, 0.768627, 0.384314 );
table->SetTableValue( 56.0, 0.235294, 0.227451, 0.823529 );
table->SetTableValue( 57.0, 1, 0.647059, 0 );
table->SetTableValue( 58.0, 1, 0.647059, 0 );
table->SetTableValue( 59.0, 0, 1, 0.498039 );
table->SetTableValue( 60.0, 0.647059, 0.164706, 0.164706 );
table->SetTableValue( 61.0, 0.529412, 0.807843, 0.921569 );
table->SetTableValue( 62.0, 0.627451, 0.12549, 0.941176 );
table->SetTableValue( 63.0, 0, 0.784314, 0.866667 );
table->SetTableValue( 64.0, 0.392157, 0.196078, 0.392157 );
table->SetTableValue( 65.0, 0.529412, 0.196078, 0.290196 );
table->SetTableValue( 66.0, 0.478431, 0.529412, 0.196078 );
table->SetTableValue( 67.0, 0.2, 0.196078, 0.529412 );
table->SetTableValue( 68.0, 0.290196, 0.607843, 0.235294 );
table->SetTableValue( 69.0, 0.470588, 0.243137, 0.168627 );
table->SetTableValue( 70.0, 0.290196, 0.607843, 0.235294 );
table->SetTableValue( 71.0, 0.478431, 0.529412, 0.196078 );
table->SetTableValue( 72.0, 0.470588, 0.745098, 0.588235 );
table->SetTableValue( 73.0, 0.478431, 0.529412, 0.196078 );
table->SetTableValue( 74.0, 0.478431, 0.529412, 0.196078 );
table->SetTableValue( 77.0, 0.784314, 0.27451, 1 );
table->SetTableValue( 78.0, 1, 0.580392, 0.0392157 );
table->SetTableValue( 79.0, 1, 0.580392, 0.0392157 );
table->SetTableValue( 80.0, 0.643137, 0.423529, 0.886275 );
table->SetTableValue( 81.0, 0.643137, 0.423529, 0.886275 );
table->SetTableValue( 82.0, 0.643137, 0.423529, 0.886275 );
table->SetTableValue( 83.0, 1, 0.854902, 0.72549 );
table->SetTableValue( 84.0, 1, 0.854902, 0.72549 );
table->SetTableValue( 85.0, 0.917647, 0.662745, 0.117647 );
table->SetTableValue( 192.0, 0.980392, 1, 0.196078 );
table->SetTableValue( 86.0, 0.784314, 0.470588, 1 );
table->SetTableValue( 87.0, 0.784314, 0.47451, 1 );
table->SetTableValue( 88.0, 0.784314, 0.478431, 1 );
table->SetTableValue( 96.0, 0.803922, 0.0392157, 0.490196 );
table->SetTableValue( 97.0, 0.803922, 0.0392157, 0.490196 );
table->SetTableValue( 98.0, 0.627451, 0.12549, 0.941176 );
table->SetTableValue( 100.0, 0.486275, 0.54902, 0.698039 );
table->SetTableValue( 101.0, 0.490196, 0.54902, 0.698039 );
table->SetTableValue( 102.0, 0.494118, 0.54902, 0.698039 );
table->SetTableValue( 103.0, 0.498039, 0.54902, 0.698039 );
table->SetTableValue( 104.0, 0.486275, 0.552941, 0.698039 );
table->SetTableValue( 105.0, 0.486275, 0.556863, 0.698039 );
table->SetTableValue( 106.0, 0.486275, 0.560784, 0.698039 );
table->SetTableValue( 107.0, 0.486275, 0.564706, 0.698039 );
table->SetTableValue( 108.0, 0.486275, 0.54902, 0.701961 );
table->SetTableValue( 109.0, 0.486275, 0.54902, 0.698039 );
table->SetTableValue( 110.0, 0.490196, 0.54902, 0.698039 );
table->SetTableValue( 111.0, 0.494118, 0.54902, 0.698039 );
table->SetTableValue( 112.0, 0.498039, 0.54902, 0.698039 );
table->SetTableValue( 113.0, 0.486275, 0.552941, 0.698039 );
table->SetTableValue( 114.0, 0.486275, 0.556863, 0.698039 );
table->SetTableValue( 115.0, 0.486275, 0.560784, 0.698039 );
table->SetTableValue( 116.0, 0.486275, 0.564706, 0.698039 );
table->SetTableValue( 117.0, 0.486275, 0.54902, 0.701961 );
table->SetTableValue( 118.0, 1, 0.0784314, 0.576471 );
table->SetTableValue( 119.0, 0.803922, 0.701961, 0.545098 );
table->SetTableValue( 120.0, 0.933333, 0.933333, 0.819608 );
table->SetTableValue( 121.0, 0.784314, 0.784314, 0.784314 );
table->SetTableValue( 122.0, 0.290196, 1, 0.290196 );
table->SetTableValue( 123.0, 0.933333, 0, 0 );
table->SetTableValue( 124.0, 0, 0, 0.545098 );
table->SetTableValue( 125.0, 0.678431, 1, 0.184314 );
table->SetTableValue( 126.0, 0.521569, 0.796078, 0.898039 );
table->SetTableValue( 127.0, 0.101961, 0.929412, 0.223529 );
table->SetTableValue( 128.0, 0.133333, 0.545098, 0.133333 );
table->SetTableValue( 129.0, 0.117647, 0.564706, 1 );
table->SetTableValue( 130.0, 0.576471, 0.0745098, 0.678431 );
table->SetTableValue( 131.0, 0.933333, 0.231373, 0.231373 );
table->SetTableValue( 132.0, 0.866667, 0.152941, 0.784314 );
table->SetTableValue( 133.0, 0.933333, 0.682353, 0.933333 );
table->SetTableValue( 134.0, 1, 0, 0 );
table->SetTableValue( 135.0, 0.282353, 0.239216, 0.545098 );
table->SetTableValue( 136.0, 0.0823529, 0.152941, 0.517647 );
table->SetTableValue( 137.0, 0.0823529, 0.152941, 0.517647 );
table->SetTableValue( 138.0, 0.254902, 0.529412, 0.0784314 );
table->SetTableValue( 139.0, 0.254902, 0.529412, 0.0784314 );
table->SetTableValue( 140.0, 0.52549, 0.0156863, 0.627451 );
table->SetTableValue( 142.0, 0.866667, 0.886275, 0.266667 );
table->SetTableValue( 143.0, 1, 1, 0.996078 );
table->SetTableValue( 144.0, 0.203922, 0.819608, 0.886275 );
table->SetTableValue( 145.0, 0.937255, 0.627451, 0.87451 );
table->SetTableValue( 146.0, 0.27451, 0.509804, 0.705882 );
table->SetTableValue( 147.0, 0.27451, 0.509804, 0.709804 );
table->SetTableValue( 148.0, 0.545098, 0.47451, 0.368627 );
table->SetTableValue( 149.0, 0.878431, 0.878431, 0.878431 );
table->SetTableValue( 150.0, 1, 0, 0 );
table->SetTableValue( 151.0, 0.803922, 0.803922, 0 );
table->SetTableValue( 152.0, 0.933333, 0.933333, 0.819608 );
table->SetTableValue( 153.0, 0.545098, 0.47451, 0.368627 );
table->SetTableValue( 154.0, 0.933333, 0.231373, 0.231373 );
table->SetTableValue( 155.0, 0.933333, 0.231373, 0.231373 );
table->SetTableValue( 156.0, 0.933333, 0.231373, 0.231373 );
table->SetTableValue( 157.0, 0.243137, 0.0392157, 0.803922 );
table->SetTableValue( 158.0, 0.243137, 0.0392157, 0.803922 );
table->SetTableValue( 159.0, 0, 0.462745, 0.054902 );
table->SetTableValue( 160.0, 0, 0.462745, 0.054902 );
table->SetTableValue( 161.0, 0.862745, 0.847059, 0.0823529 );
table->SetTableValue( 162.0, 0.862745, 0.847059, 0.0823529 );
table->SetTableValue( 163.0, 0.478431, 0.729412, 0.862745 );
table->SetTableValue( 164.0, 0.478431, 0.729412, 0.862745 );
table->SetTableValue( 165.0, 1, 0.647059, 0 );
table->SetTableValue( 166.0, 0.054902, 0.188235, 1 );
table->SetTableValue( 167.0, 0.65098, 0.164706, 0.164706 );
table->SetTableValue( 168.0, 0.47451, 0.0705882, 0.52549 );
table->SetTableValue( 169.0, 0.92549, 0.0509804, 0.498039 );
table->SetTableValue( 176.0, 0.92549, 0.0509804, 0.494118 );
table->SetTableValue( 170.0, 0.466667, 0.623529, 0.690196 );
table->SetTableValue( 171.0, 0.466667, 0, 0.690196 );
table->SetTableValue( 172.0, 0.466667, 0.392157, 0.690196 );
table->SetTableValue( 173.0, 0.466667, 0.784314, 0.690196 );
table->SetTableValue( 174.0, 0.466667, 0.623529, 0.392157 );
table->SetTableValue( 175.0, 0.466667, 0.623529, 0.784314 );
table->SetTableValue( 180.0, 0.286275, 0.239216, 0.545098 );
table->SetTableValue( 181.0, 0.286275, 0.243137, 0.545098 );
table->SetTableValue( 193.0, 0, 0.768627, 1 );
table->SetTableValue( 194.0, 1, 0.643137, 0.643137 );
table->SetTableValue( 195.0, 0.768627, 0.768627, 0 );
table->SetTableValue( 196.0, 0, 0.392157, 1 );
table->SetTableValue( 197.0, 0.501961, 0.768627, 0.643137 );
table->SetTableValue( 198.0, 0, 0.494118, 0.294118 );
table->SetTableValue( 199.0, 0.501961, 0.376471, 0.25098 );
table->SetTableValue( 200.0, 0, 0.196078, 0.501961 );
table->SetTableValue( 201.0, 1, 0.8, 0.6 );
table->SetTableValue( 202.0, 1, 0.501961, 0.501961 );
table->SetTableValue( 203.0, 1, 1, 0 );
table->SetTableValue( 204.0, 0.25098, 0, 0.25098 );
table->SetTableValue( 205.0, 0, 0, 1 );
table->SetTableValue( 206.0, 1, 0, 0 );
table->SetTableValue( 207.0, 0.501961, 0.501961, 1 );
table->SetTableValue( 208.0, 0, 0.501961, 0 );
table->SetTableValue( 209.0, 0.768627, 0.627451, 0.501961 );
table->SetTableValue( 210.0, 0.12549, 0.784314, 1 );
table->SetTableValue( 211.0, 0.501961, 1, 0.501961 );
table->SetTableValue( 212.0, 0.8, 0.6, 0.8 );
table->SetTableValue( 213.0, 0.47451, 0.0666667, 0.533333 );
table->SetTableValue( 214.0, 0.501961, 0, 0 );
table->SetTableValue( 215.0, 0.501961, 0.12549, 1 );
table->SetTableValue( 216.0, 1, 0.8, 0.4 );
table->SetTableValue( 217.0, 0.501961, 0.501961, 0.501961 );
table->SetTableValue( 218.0, 0.407843, 1, 1 );
table->SetTableValue( 219.0, 0, 0.886275, 0 );
table->SetTableValue( 220.0, 0.803922, 0.247059, 0.305882 );
table->SetTableValue( 221.0, 0.772549, 0.227451, 0.980392 );
table->SetTableValue( 222.0, 0.129412, 0.588235, 0.980392 );
table->SetTableValue( 223.0, 0.886275, 0, 0 );
table->SetTableValue( 224.0, 0.392157, 0.392157, 0.392157 );
table->SetTableValue( 225.0, 0.772549, 0.588235, 0.980392 );
table->SetTableValue( 226.0, 0.666667, 0.666667, 1 );
table->SetTableValue( 250.0, 1, 0, 0 );
table->SetTableValue( 251.0, 0, 0, 0.25098 );
table->SetTableValue( 252.0, 0, 0, 0.439216 );
table->SetTableValue( 253.0, 0, 0, 0.627451 );
table->SetTableValue( 254.0, 0, 0, 0.815686 );
table->SetTableValue( 255.0, 0, 0, 1 );
table->SetTableValue( 256.0, 0, 0, 0, 0);
table->SetTableValue( 331.0, 1, 0, 0 );
table->SetTableValue( 332.0, 1, 0.313725, 0 );
table->SetTableValue( 333.0, 1, 0.627451, 0 );
table->SetTableValue( 334.0, 1, 1, 0 );
table->SetTableValue( 335.0, 0, 1, 0 );
table->SetTableValue( 336.0, 1, 0, 0.627451 );
table->SetTableValue( 337.0, 1, 0, 1 );
table->SetTableValue( 338.0, 1, 0.196078, 0.313725 );
table->SetTableValue( 339.0, 0.313725, 1, 0.196078 );
table->SetTableValue( 340.0, 0.627451, 1, 0.196078 );
table->SetTableValue( 341.0, 0.627451, 0.784314, 1 );
table->SetTableValue( 342.0, 0, 1, 0.627451 );
table->SetTableValue( 343.0, 0, 0, 1 );
table->SetTableValue( 344.0, 0.313725, 0.196078, 1 );
table->SetTableValue( 345.0, 0.627451, 0, 1 );
table->SetTableValue( 346.0, 1, 0.823529, 0 );
table->SetTableValue( 347.0, 0, 0.627451, 1 );
table->SetTableValue( 348.0, 1, 0.784314, 0.313725 );
table->SetTableValue( 349.0, 1, 0.784314, 0.627451 );
table->SetTableValue( 350.0, 1, 0.313725, 0.784314 );
table->SetTableValue( 351.0, 1, 0.627451, 0.784314 );
table->SetTableValue( 352.0, 0.117647, 1, 0.313725 );
table->SetTableValue( 353.0, 0.313725, 0.784314, 1 );
table->SetTableValue( 354.0, 0.313725, 1, 0.784314 );
table->SetTableValue( 355.0, 0.764706, 1, 0.784314 );
table->SetTableValue( 356.0, 0.470588, 0.784314, 0.0784314 );
table->SetTableValue( 357.0, 0.666667, 0.0392157, 0.784314 );
table->SetTableValue( 358.0, 0.0784314, 0.509804, 0.705882 );
table->SetTableValue( 359.0, 0.0784314, 0.705882, 0.509804 );
table->SetTableValue( 400.0, 0.807843, 0.243137, 0.305882 );
table->SetTableValue( 401.0, 0.47451, 0.0705882, 0.52549 );
table->SetTableValue( 402.0, 0.780392, 0.227451, 0.980392 );
table->SetTableValue( 403.0, 0.00392157, 0.580392, 0 );
table->SetTableValue( 404.0, 0.866667, 0.972549, 0.643137 );
table->SetTableValue( 405.0, 0.905882, 0.580392, 0.133333 );
table->SetTableValue( 406.0, 0.00392157, 0.462745, 0.054902 );
table->SetTableValue( 407.0, 0.470588, 0.462745, 0.054902 );
table->SetTableValue( 408.0, 0.482353, 0.729412, 0.866667 );
table->SetTableValue( 409.0, 0.933333, 0.0509804, 0.694118 );
table->SetTableValue( 410.0, 0.482353, 0.729412, 0.862745 );
table->SetTableValue( 411.0, 0.541176, 0.0509804, 0.807843 );
table->SetTableValue( 412.0, 0.933333, 0.509804, 0.690196 );
table->SetTableValue( 413.0, 0.854902, 0.901961, 0.298039 );
table->SetTableValue( 414.0, 0.14902, 0.835294, 0.690196 );
table->SetTableValue( 415.0, 0.00392157, 0.882353, 0.690196 );
table->SetTableValue( 416.0, 0.00392157, 0.882353, 0.690196 );
table->SetTableValue( 417.0, 0.784314, 0.00784314, 0.392157 );
table->SetTableValue( 418.0, 0.784314, 0.00784314, 0.392157 );
table->SetTableValue( 419.0, 0.0196078, 0.784314, 0.352941 );
table->SetTableValue( 420.0, 0.0196078, 0.784314, 0.352941 );
table->SetTableValue( 421.0, 0.392157, 0.0196078, 0.784314 );
table->SetTableValue( 422.0, 0.0980392, 1, 0.392157 );
table->SetTableValue( 423.0, 0.0980392, 1, 0.392157 );
table->SetTableValue( 424.0, 0.901961, 0.027451, 0.392157 );
table->SetTableValue( 425.0, 0.901961, 0.027451, 0.392157 );
table->SetTableValue( 426.0, 0.392157, 0.0196078, 0.784314 );
table->SetTableValue( 427.0, 0.588235, 0.0392157, 0.784314 );
table->SetTableValue( 428.0, 0.588235, 0.0392157, 0.784314 );
table->SetTableValue( 429.0, 0.686275, 0.0392157, 0.690196 );
table->SetTableValue( 430.0, 0.686275, 0.0392157, 0.690196 );
table->SetTableValue( 431.0, 0.0392157, 0.392157, 1 );
table->SetTableValue( 432.0, 0.0392157, 0.392157, 1 );
table->SetTableValue( 433.0, 0.588235, 0.176471, 0.27451 );
table->SetTableValue( 434.0, 0.588235, 0.176471, 0.27451 );
table->SetTableValue( 435.0, 0.176471, 0.784314, 0.0588235 );
table->SetTableValue( 436.0, 0.176471, 0.784314, 0.0588235 );
table->SetTableValue( 437.0, 0.890196, 0.176471, 0.392157 );
table->SetTableValue( 438.0, 0.890196, 0.176471, 0.392157 );
table->SetTableValue( 439.0, 0.890196, 0.176471, 0.392157 );
table->SetTableValue( 498.0, 0.560784, 0.737255, 0.560784 );
table->SetTableValue( 499.0, 1, 0.972549, 0.862745 );
table->SetTableValue( 500.0, 0.0666667, 0.333333, 0.533333 );
table->SetTableValue( 501.0, 0.466667, 0.733333, 0.4 );
table->SetTableValue( 502.0, 0.8, 0.266667, 0.133333 );
table->SetTableValue( 503.0, 0.8, 0, 1 );
table->SetTableValue( 504.0, 0.866667, 0.733333, 0.0666667 );
table->SetTableValue( 505.0, 0.6, 0.866667, 0.933333 );
table->SetTableValue( 506.0, 0.2, 0.0666667, 0.0666667 );
table->SetTableValue( 507.0, 0, 0.466667, 0.333333 );
table->SetTableValue( 508.0, 0.0784314, 0.392157, 0.784314 );
table->SetTableValue( 550.0, 0.0666667, 0.333333, 0.537255 );
table->SetTableValue( 551.0, 0.466667, 0.733333, 0.403922 );
table->SetTableValue( 552.0, 0.8, 0.266667, 0.137255 );
table->SetTableValue( 553.0, 0.8, 0, 0.996078 );
table->SetTableValue( 554.0, 0.866667, 0.733333, 0.0627451 );
table->SetTableValue( 555.0, 0.6, 0.866667, 0.937255 );
table->SetTableValue( 556.0, 0.2, 0.0666667, 0.0705882 );
table->SetTableValue( 557.0, 0, 0.466667, 0.337255 );
table->SetTableValue( 558.0, 0.0784314, 0.392157, 0.788235 );
table->SetTableValue( 600.0, 0.996078, 0.996078, 0.996078 );
table->SetTableValue( 601.0, 0.27451, 0.509804, 0.705882 );
table->SetTableValue( 602.0, 0.960784, 0.960784, 0.960784 );
table->SetTableValue( 603.0, 0.803922, 0.243137, 0.305882 );
table->SetTableValue( 604.0, 0.470588, 0.0705882, 0.52549 );
table->SetTableValue( 605.0, 0.768627, 0.227451, 0.980392 );
table->SetTableValue( 606.0, 0, 0.580392, 0 );
table->SetTableValue( 607.0, 0.862745, 0.972549, 0.643137 );
table->SetTableValue( 608.0, 0.901961, 0.580392, 0.133333 );
table->SetTableValue( 609.0, 0, 0.462745, 0.054902 );
table->SetTableValue( 610.0, 0, 0.462745, 0.054902 );
table->SetTableValue( 611.0, 0.478431, 0.729412, 0.862745 );
table->SetTableValue( 612.0, 0.92549, 0.0509804, 0.690196 );
table->SetTableValue( 613.0, 0.0470588, 0.188235, 1 );
table->SetTableValue( 614.0, 0.8, 0.713725, 0.556863 );
table->SetTableValue( 615.0, 0.164706, 0.8, 0.643137 );
table->SetTableValue( 616.0, 0.466667, 0.623529, 0.690196 );
table->SetTableValue( 617.0, 0.862745, 0.847059, 0.0784314 );
table->SetTableValue( 618.0, 0.403922, 1, 1 );
table->SetTableValue( 619.0, 0.313725, 0.768627, 0.384314 );
table->SetTableValue( 620.0, 0.235294, 0.227451, 0.823529 );
table->SetTableValue( 621.0, 0.235294, 0.227451, 0.823529 );
table->SetTableValue( 622.0, 0.235294, 0.227451, 0.823529 );
table->SetTableValue( 623.0, 0.235294, 0.227451, 0.823529 );
table->SetTableValue( 624.0, 0.235294, 0.235294, 0.235294 );
table->SetTableValue( 625.0, 1, 0.647059, 0 );
table->SetTableValue( 626.0, 1, 0.647059, 0 );
table->SetTableValue( 627.0, 0, 1, 0.498039 );
table->SetTableValue( 628.0, 0.647059, 0.164706, 0.164706 );
table->SetTableValue( 640.0, 0.8, 0, 0 );
table->SetTableValue( 641.0, 1, 0, 0 );
table->SetTableValue( 642.0, 0, 0, 1 );
table->SetTableValue( 643.0, 0.117647, 0.564706, 1 );
table->SetTableValue( 644.0, 0.392157, 0.831373, 0.929412 );
table->SetTableValue( 645.0, 0.854902, 0.647059, 0.12549 );
table->SetTableValue( 646.0, 1, 0.843137, 0 );
table->SetTableValue( 647.0, 1, 1, 0.65098 );
table->SetTableValue( 648.0, 0.6, 0, 0.8 );
table->SetTableValue( 649.0, 0.6, 0.552941, 0.819608 );
table->SetTableValue( 650.0, 0.8, 0.8, 1 );
table->SetTableValue( 651.0, 0.121569, 0.831373, 0.760784 );
table->SetTableValue( 652.0, 0.0117647, 1, 0.929412 );
table->SetTableValue( 653.0, 0.8, 1, 1 );
table->SetTableValue( 654.0, 0.337255, 0.290196, 0.576471 );
table->SetTableValue( 655.0, 0.447059, 0.447059, 0.745098 );
table->SetTableValue( 656.0, 0.721569, 0.698039, 1 );
table->SetTableValue( 657.0, 0.494118, 0.541176, 0.145098 );
table->SetTableValue( 658.0, 0.741176, 0.772549, 0.458824 );
table->SetTableValue( 659.0, 0.941176, 0.901961, 0.54902 );
table->SetTableValue( 660.0, 0.8, 0, 0 );
table->SetTableValue( 661.0, 1, 0, 0 );
table->SetTableValue( 662.0, 0, 0, 1 );
table->SetTableValue( 663.0, 0.117647, 0.564706, 1 );
table->SetTableValue( 664.0, 0.392157, 0.831373, 0.929412 );
table->SetTableValue( 665.0, 0.854902, 0.647059, 0.12549 );
table->SetTableValue( 666.0, 1, 0.843137, 0 );
table->SetTableValue( 667.0, 1, 1, 0.65098 );
table->SetTableValue( 668.0, 0.6, 0, 0.8 );
table->SetTableValue( 669.0, 0.6, 0.552941, 0.819608 );
table->SetTableValue( 670.0, 0.8, 0.8, 1 );
table->SetTableValue( 671.0, 0.121569, 0.831373, 0.760784 );
table->SetTableValue( 672.0, 0.0117647, 1, 0.929412 );
table->SetTableValue( 673.0, 0.8, 1, 1 );
table->SetTableValue( 674.0, 0.337255, 0.290196, 0.576471 );
table->SetTableValue( 675.0, 0.447059, 0.447059, 0.745098 );
table->SetTableValue( 676.0, 0.721569, 0.698039, 1 );
table->SetTableValue( 677.0, 0.494118, 0.541176, 0.145098 );
table->SetTableValue( 678.0, 0.741176, 0.772549, 0.458824 );
table->SetTableValue( 679.0, 0.941176, 0.901961, 0.54902 );
table->SetTableValue( 701.0, 0.470588, 0.0705882, 0.52549 );
table->SetTableValue( 702.0, 0.803922, 0.243137, 0.305882 );
table->SetTableValue( 703.0, 0, 0.882353, 0 );
table->SetTableValue( 999.0, 1, 0.392157, 0.392157 );
table->SetTableValue( 1000.0, 0.0980392, 0.0196078, 0.0980392 );
table->SetTableValue( 1001.0, 0.0980392, 0.392157, 0.156863 );
table->SetTableValue( 1002.0, 0.490196, 0.392157, 0.627451 );
table->SetTableValue( 1003.0, 0.392157, 0.0980392, 0 );
table->SetTableValue( 1004.0, 0.470588, 0.27451, 0.196078 );
table->SetTableValue( 1005.0, 0.862745, 0.0784314, 0.392157 );
table->SetTableValue( 1006.0, 0.862745, 0.0784314, 0.0392157 );
table->SetTableValue( 1007.0, 0.705882, 0.862745, 0.54902 );
table->SetTableValue( 1008.0, 0.862745, 0.235294, 0.862745 );
table->SetTableValue( 1009.0, 0.705882, 0.156863, 0.470588 );
table->SetTableValue( 1010.0, 0.54902, 0.0784314, 0.54902 );
table->SetTableValue( 1011.0, 0.0784314, 0.117647, 0.54902 );
table->SetTableValue( 1012.0, 0.137255, 0.294118, 0.196078 );
table->SetTableValue( 1013.0, 0.882353, 0.54902, 0.54902 );
table->SetTableValue( 1014.0, 0.784314, 0.137255, 0.294118 );
table->SetTableValue( 1015.0, 0.627451, 0.392157, 0.196078 );
table->SetTableValue( 1016.0, 0.0784314, 0.862745, 0.235294 );
table->SetTableValue( 1017.0, 0.235294, 0.862745, 0.235294 );
table->SetTableValue( 1018.0, 0.862745, 0.705882, 0.54902 );
table->SetTableValue( 1019.0, 0.0784314, 0.392157, 0.196078 );
table->SetTableValue( 1020.0, 0.862745, 0.235294, 0.0784314 );
table->SetTableValue( 1021.0, 0.470588, 0.392157, 0.235294 );
table->SetTableValue( 1022.0, 0.862745, 0.0784314, 0.0784314 );
table->SetTableValue( 1023.0, 0.862745, 0.705882, 0.862745 );
table->SetTableValue( 1024.0, 0.235294, 0.0784314, 0.862745 );
table->SetTableValue( 1025.0, 0.627451, 0.54902, 0.705882 );
table->SetTableValue( 1026.0, 0.313725, 0.0784314, 0.54902 );
table->SetTableValue( 1027.0, 0.294118, 0.196078, 0.490196 );
table->SetTableValue( 1028.0, 0.0784314, 0.862745, 0.627451 );
table->SetTableValue( 1029.0, 0.0784314, 0.705882, 0.54902 );
table->SetTableValue( 1030.0, 0.54902, 0.862745, 0.862745 );
table->SetTableValue( 1031.0, 0.313725, 0.627451, 0.0784314 );
table->SetTableValue( 1032.0, 0.392157, 0, 0.392157 );
table->SetTableValue( 1033.0, 0.27451, 0.27451, 0.27451 );
table->SetTableValue( 1034.0, 0.588235, 0.588235, 0.784314 );
table->SetTableValue( 1035.0, 1, 0.752941, 0.12549 );
table->SetTableValue( 2000.0, 0.0980392, 0.0196078, 0.0980392 );
table->SetTableValue( 2001.0, 0.0980392, 0.392157, 0.156863 );
table->SetTableValue( 2002.0, 0.490196, 0.392157, 0.627451 );
table->SetTableValue( 2003.0, 0.392157, 0.0980392, 0 );
table->SetTableValue( 2004.0, 0.470588, 0.27451, 0.196078 );
table->SetTableValue( 2005.0, 0.862745, 0.0784314, 0.392157 );
table->SetTableValue( 2006.0, 0.862745, 0.0784314, 0.0392157 );
table->SetTableValue( 2007.0, 0.705882, 0.862745, 0.54902 );
table->SetTableValue( 2008.0, 0.862745, 0.235294, 0.862745 );
table->SetTableValue( 2009.0, 0.705882, 0.156863, 0.470588 );
table->SetTableValue( 2010.0, 0.54902, 0.0784314, 0.54902 );
table->SetTableValue( 2011.0, 0.0784314, 0.117647, 0.54902 );
table->SetTableValue( 2012.0, 0.137255, 0.294118, 0.196078 );
table->SetTableValue( 2013.0, 0.882353, 0.54902, 0.54902 );
table->SetTableValue( 2014.0, 0.784314, 0.137255, 0.294118 );
table->SetTableValue( 2015.0, 0.627451, 0.392157, 0.196078 );
table->SetTableValue( 2016.0, 0.0784314, 0.862745, 0.235294 );
table->SetTableValue( 2017.0, 0.235294, 0.862745, 0.235294 );
table->SetTableValue( 2018.0, 0.862745, 0.705882, 0.54902 );
table->SetTableValue( 2019.0, 0.0784314, 0.392157, 0.196078 );
table->SetTableValue( 2020.0, 0.862745, 0.235294, 0.0784314 );
table->SetTableValue( 2021.0, 0.470588, 0.392157, 0.235294 );
table->SetTableValue( 2022.0, 0.862745, 0.0784314, 0.0784314 );
table->SetTableValue( 2023.0, 0.862745, 0.705882, 0.862745 );
table->SetTableValue( 2024.0, 0.235294, 0.0784314, 0.862745 );
table->SetTableValue( 2025.0, 0.627451, 0.54902, 0.705882 );
table->SetTableValue( 2026.0, 0.313725, 0.0784314, 0.54902 );
table->SetTableValue( 2027.0, 0.294118, 0.196078, 0.490196 );
table->SetTableValue( 2028.0, 0.0784314, 0.862745, 0.627451 );
table->SetTableValue( 2029.0, 0.0784314, 0.705882, 0.54902 );
table->SetTableValue( 2030.0, 0.54902, 0.862745, 0.862745 );
table->SetTableValue( 2031.0, 0.313725, 0.627451, 0.0784314 );
table->SetTableValue( 2032.0, 0.392157, 0, 0.392157 );
table->SetTableValue( 2033.0, 0.27451, 0.27451, 0.27451 );
table->SetTableValue( 2034.0, 0.588235, 0.588235, 0.784314 );
table->SetTableValue( 2035.0, 1, 0.752941, 0.12549 );
table->SetTableValue( 3000.0, 0.901961, 0.980392, 0.901961 );
table->SetTableValue( 3001.0, 0.901961, 0.607843, 0.843137 );
table->SetTableValue( 3002.0, 0.509804, 0.607843, 0.372549 );
table->SetTableValue( 3003.0, 0.607843, 0.901961, 1 );
table->SetTableValue( 3004.0, 0.529412, 0.72549, 0.803922 );
table->SetTableValue( 3005.0, 0.137255, 0.921569, 0.607843 );
table->SetTableValue( 3006.0, 0.137255, 0.921569, 0.960784 );
table->SetTableValue( 3007.0, 0.294118, 0.137255, 0.45098 );
table->SetTableValue( 3008.0, 0.137255, 0.764706, 0.137255 );
table->SetTableValue( 3009.0, 0.294118, 0.843137, 0.529412 );
table->SetTableValue( 3010.0, 0.45098, 0.921569, 0.45098 );
table->SetTableValue( 3011.0, 0.921569, 0.882353, 0.45098 );
table->SetTableValue( 3012.0, 0.862745, 0.705882, 0.803922 );
table->SetTableValue( 3013.0, 0.117647, 0.45098, 0.45098 );
table->SetTableValue( 3014.0, 0.215686, 0.862745, 0.705882 );
table->SetTableValue( 3015.0, 0.372549, 0.607843, 0.803922 );
table->SetTableValue( 3016.0, 0.921569, 0.137255, 0.764706 );
table->SetTableValue( 3017.0, 0.764706, 0.137255, 0.764706 );
table->SetTableValue( 3018.0, 0.137255, 0.294118, 0.45098 );
table->SetTableValue( 3019.0, 0.921569, 0.607843, 0.803922 );
table->SetTableValue( 3020.0, 0.137255, 0.764706, 0.921569 );
table->SetTableValue( 3021.0, 0.529412, 0.607843, 0.764706 );
table->SetTableValue( 3022.0, 0.137255, 0.921569, 0.921569 );
table->SetTableValue( 3023.0, 0.137255, 0.294118, 0.137255 );
table->SetTableValue( 3024.0, 0.764706, 0.921569, 0.137255 );
table->SetTableValue( 3025.0, 0.372549, 0.45098, 0.294118 );
table->SetTableValue( 3026.0, 0.686275, 0.921569, 0.45098 );
table->SetTableValue( 3027.0, 0.705882, 0.803922, 0.509804 );
table->SetTableValue( 3028.0, 0.921569, 0.137255, 0.372549 );
table->SetTableValue( 3029.0, 0.921569, 0.294118, 0.45098 );
table->SetTableValue( 3030.0, 0.45098, 0.137255, 0.137255 );
table->SetTableValue( 3031.0, 0.686275, 0.372549, 0.921569 );
table->SetTableValue( 3032.0, 0.607843, 1, 0.607843 );
table->SetTableValue( 3033.0, 0.72549, 0.72549, 0.72549 );
table->SetTableValue( 3034.0, 0.411765, 0.411765, 0.215686 );
table->SetTableValue( 3035.0, 0.996078, 0.74902, 0.121569 );
table->SetTableValue( 4000.0, 0.901961, 0.980392, 0.901961 );
table->SetTableValue( 4001.0, 0.901961, 0.607843, 0.843137 );
table->SetTableValue( 4002.0, 0.509804, 0.607843, 0.372549 );
table->SetTableValue( 4003.0, 0.607843, 0.901961, 1 );
table->SetTableValue( 4004.0, 0.529412, 0.72549, 0.803922 );
table->SetTableValue( 4005.0, 0.137255, 0.921569, 0.607843 );
table->SetTableValue( 4006.0, 0.137255, 0.921569, 0.960784 );
table->SetTableValue( 4007.0, 0.294118, 0.137255, 0.45098 );
table->SetTableValue( 4008.0, 0.137255, 0.764706, 0.137255 );
table->SetTableValue( 4009.0, 0.294118, 0.843137, 0.529412 );
table->SetTableValue( 4010.0, 0.45098, 0.921569, 0.45098 );
table->SetTableValue( 4011.0, 0.921569, 0.882353, 0.45098 );
table->SetTableValue( 4012.0, 0.862745, 0.705882, 0.803922 );
table->SetTableValue( 4013.0, 0.117647, 0.45098, 0.45098 );
table->SetTableValue( 4014.0, 0.215686, 0.862745, 0.705882 );
table->SetTableValue( 4015.0, 0.372549, 0.607843, 0.803922 );
table->SetTableValue( 4016.0, 0.921569, 0.137255, 0.764706 );
table->SetTableValue( 4017.0, 0.764706, 0.137255, 0.764706 );
table->SetTableValue( 4018.0, 0.137255, 0.294118, 0.45098 );
table->SetTableValue( 4019.0, 0.921569, 0.607843, 0.803922 );
table->SetTableValue( 4020.0, 0.137255, 0.764706, 0.921569 );
table->SetTableValue( 4021.0, 0.529412, 0.607843, 0.764706 );
table->SetTableValue( 4022.0, 0.137255, 0.921569, 0.921569 );
table->SetTableValue( 4023.0, 0.137255, 0.294118, 0.137255 );
table->SetTableValue( 4024.0, 0.764706, 0.921569, 0.137255 );
table->SetTableValue( 4025.0, 0.372549, 0.45098, 0.294118 );
table->SetTableValue( 4026.0, 0.686275, 0.921569, 0.45098 );
table->SetTableValue( 4027.0, 0.705882, 0.803922, 0.509804 );
table->SetTableValue( 4028.0, 0.921569, 0.137255, 0.372549 );
table->SetTableValue( 4029.0, 0.921569, 0.294118, 0.45098 );
table->SetTableValue( 4030.0, 0.45098, 0.137255, 0.137255 );
table->SetTableValue( 4031.0, 0.686275, 0.372549, 0.921569 );
table->SetTableValue( 4032.0, 0.607843, 1, 0.607843 );
table->SetTableValue( 4033.0, 0.72549, 0.72549, 0.72549 );
table->SetTableValue( 4034.0, 0.411765, 0.411765, 0.215686 );
table->SetTableValue( 4035.0, 0.996078, 0.74902, 0.121569 );
table->SetTableValue( 1100.0, 0, 0, 0, 0);
table->SetTableValue( 1101.0, 0.196078, 0.196078, 0.196078 );
table->SetTableValue( 1102.0, 0.705882, 0.0784314, 0.117647 );
table->SetTableValue( 1103.0, 0.235294, 0.0980392, 0.0980392 );
table->SetTableValue( 1104.0, 0.0980392, 0.235294, 0.235294 );
table->SetTableValue( 1200.0, 0.0980392, 0.235294, 0.239216 );
table->SetTableValue( 1201.0, 0.0980392, 0.352941, 0.235294 );
table->SetTableValue( 1202.0, 0.0980392, 0.470588, 0.235294 );
table->SetTableValue( 1205.0, 0.0980392, 0.588235, 0.235294 );
table->SetTableValue( 1206.0, 0.0980392, 0.705882, 0.235294 );
table->SetTableValue( 1207.0, 0.0980392, 0.823529, 0.235294 );
table->SetTableValue( 1210.0, 0.0980392, 0.588235, 0.352941 );
table->SetTableValue( 1211.0, 0.0980392, 0.705882, 0.352941 );
table->SetTableValue( 1212.0, 0.0980392, 0.823529, 0.352941 );
table->SetTableValue( 1105.0, 0.705882, 0.0784314, 0.0784314 );
table->SetTableValue( 1106.0, 0.862745, 0.0784314, 0.392157 );
table->SetTableValue( 1107.0, 0.54902, 0.235294, 0.235294 );
table->SetTableValue( 1108.0, 0.705882, 0.862745, 0.54902 );
table->SetTableValue( 1109.0, 0.54902, 0.392157, 0.705882 );
table->SetTableValue( 1110.0, 0.705882, 0.0784314, 0.54902 );
table->SetTableValue( 1111.0, 0.54902, 0.0784314, 0.54902 );
table->SetTableValue( 1112.0, 0.0823529, 0.0392157, 0.0392157 );
table->SetTableValue( 1113.0, 0.882353, 0.54902, 0.54902 );
table->SetTableValue( 1114.0, 0.0901961, 0.235294, 0.705882 );
table->SetTableValue( 1115.0, 0.705882, 0.235294, 0.705882 );
table->SetTableValue( 1116.0, 0.0784314, 0.862745, 0.235294 );
table->SetTableValue( 1117.0, 0.235294, 0.0784314, 0.54902 );
table->SetTableValue( 1118.0, 0.862745, 0.705882, 0.54902 );
table->SetTableValue( 1119.0, 0.254902, 0.392157, 0.0784314 );
table->SetTableValue( 1120.0, 0.862745, 0.235294, 0.0784314 );
table->SetTableValue( 1121.0, 0.235294, 0.392157, 0.235294 );
table->SetTableValue( 1122.0, 0.0784314, 0.235294, 0.862745 );
table->SetTableValue( 1123.0, 0.392157, 0.392157, 0.235294 );
table->SetTableValue( 1124.0, 0.862745, 0.705882, 0.862745 );
table->SetTableValue( 1125.0, 0.0784314, 0.705882, 0.54902 );
table->SetTableValue( 1126.0, 0.235294, 0.54902, 0.705882 );
table->SetTableValue( 1127.0, 0.0980392, 0.0784314, 0.54902 );
table->SetTableValue( 1128.0, 0.0784314, 0.235294, 0.392157 );
table->SetTableValue( 1129.0, 0.235294, 0.862745, 0.0784314 );
table->SetTableValue( 1130.0, 0.235294, 0.0784314, 0.862745 );
table->SetTableValue( 1131.0, 0.862745, 0.862745, 0.392157 );
table->SetTableValue( 1132.0, 0.705882, 0.235294, 0.235294 );
table->SetTableValue( 1133.0, 0.235294, 0.235294, 0.862745 );
table->SetTableValue( 1134.0, 0.862745, 0.235294, 0.862745 );
table->SetTableValue( 1135.0, 0.254902, 0.862745, 0.235294 );
table->SetTableValue( 1136.0, 0.0980392, 0.54902, 0.0784314 );
table->SetTableValue( 1137.0, 0.0509804, 0, 0.980392 );
table->SetTableValue( 1138.0, 0.239216, 0.0784314, 0.862745 );
table->SetTableValue( 1139.0, 0.239216, 0.0784314, 0.235294 );
table->SetTableValue( 1140.0, 0.239216, 0.235294, 0.392157 );
table->SetTableValue( 1141.0, 0.0980392, 0.0980392, 0.0980392 );
table->SetTableValue( 1142.0, 0.54902, 0.0784314, 0.235294 );
table->SetTableValue( 1143.0, 0.862745, 0.705882, 0.0784314 );
table->SetTableValue( 1144.0, 0.247059, 0.705882, 0.705882 );
table->SetTableValue( 1145.0, 0.866667, 0.0784314, 0.0392157 );
table->SetTableValue( 1146.0, 0.0823529, 0.862745, 0.0784314 );
table->SetTableValue( 1147.0, 0.717647, 0.392157, 0.0784314 );
table->SetTableValue( 1148.0, 0.866667, 0.0784314, 0.392157 );
table->SetTableValue( 1149.0, 0.866667, 0.235294, 0.54902 );
table->SetTableValue( 1150.0, 0.866667, 0.0784314, 0.862745 );
table->SetTableValue( 1151.0, 0.239216, 0.862745, 0.862745 );
table->SetTableValue( 1152.0, 0.392157, 0.784314, 0.784314 );
table->SetTableValue( 1153.0, 0.0392157, 0.784314, 0.784314 );
table->SetTableValue( 1154.0, 0.866667, 0.862745, 0.0784314 );
table->SetTableValue( 1155.0, 0.552941, 0.0784314, 0.392157 );
table->SetTableValue( 1156.0, 0.239216, 0.862745, 0.392157 );
table->SetTableValue( 1157.0, 0.0823529, 0.862745, 0.235294 );
table->SetTableValue( 1158.0, 0.552941, 0.235294, 0.0784314 );
table->SetTableValue( 1159.0, 0.560784, 0.0784314, 0.862745 );
table->SetTableValue( 1160.0, 0.239216, 0.0784314, 0.705882 );
table->SetTableValue( 1161.0, 0.396078, 0.235294, 0.862745 );
table->SetTableValue( 1162.0, 0.0823529, 0.0784314, 0.54902 );
table->SetTableValue( 1163.0, 0.866667, 0.54902, 0.0784314 );
table->SetTableValue( 1164.0, 0.552941, 0.392157, 0.862745 );
table->SetTableValue( 1165.0, 0.396078, 0.0784314, 0.0784314 );
table->SetTableValue( 1166.0, 0.866667, 0.392157, 0.0784314 );
table->SetTableValue( 1167.0, 0.709804, 0.784314, 0.0784314 );
table->SetTableValue( 1168.0, 0.0823529, 0.705882, 0.54902 );
table->SetTableValue( 1169.0, 0.396078, 0.392157, 0.705882 );
table->SetTableValue( 1170.0, 0.709804, 0.862745, 0.0784314 );
table->SetTableValue( 1171.0, 0.0823529, 0.54902, 0.784314 );
table->SetTableValue( 1172.0, 0.0823529, 0.0784314, 0.941176 );
table->SetTableValue( 1173.0, 0.0823529, 0.0784314, 0.784314 );
table->SetTableValue( 1174.0, 0.239216, 0.705882, 0.235294 );
table->SetTableValue( 1175.0, 0.239216, 0.705882, 0.980392 );
table->SetTableValue( 1176.0, 0.0823529, 0.0784314, 0.235294 );
table->SetTableValue( 1177.0, 0.396078, 0.235294, 0.235294 );
table->SetTableValue( 1178.0, 0.0823529, 0.862745, 0.862745 );
table->SetTableValue( 1179.0, 0.0823529, 0.705882, 0.705882 );
table->SetTableValue( 1180.0, 0.87451, 0.862745, 0.235294 );
table->SetTableValue( 1181.0, 0.866667, 0.235294, 0.235294 );
table->SetTableValue( 2100.0, 0, 0, 0, 0);
table->SetTableValue( 2101.0, 0.196078, 0.196078, 0.196078 );
table->SetTableValue( 2102.0, 0.705882, 0.0784314, 0.117647 );
table->SetTableValue( 2103.0, 0.235294, 0.0980392, 0.0980392 );
table->SetTableValue( 2104.0, 0.0980392, 0.235294, 0.235294 );
table->SetTableValue( 2105.0, 0.705882, 0.0784314, 0.0784314 );
table->SetTableValue( 2106.0, 0.862745, 0.0784314, 0.392157 );
table->SetTableValue( 2107.0, 0.54902, 0.235294, 0.235294 );
table->SetTableValue( 2108.0, 0.705882, 0.862745, 0.54902 );
table->SetTableValue( 2109.0, 0.54902, 0.392157, 0.705882 );
table->SetTableValue( 2110.0, 0.705882, 0.0784314, 0.54902 );
table->SetTableValue( 2111.0, 0.54902, 0.0784314, 0.54902 );
table->SetTableValue( 2112.0, 0.0823529, 0.0392157, 0.0392157 );
table->SetTableValue( 2113.0, 0.882353, 0.54902, 0.54902 );
table->SetTableValue( 2114.0, 0.0901961, 0.235294, 0.705882 );
table->SetTableValue( 2115.0, 0.705882, 0.235294, 0.705882 );
table->SetTableValue( 2116.0, 0.0784314, 0.862745, 0.235294 );
table->SetTableValue( 2117.0, 0.235294, 0.0784314, 0.54902 );
table->SetTableValue( 2118.0, 0.862745, 0.705882, 0.54902 );
table->SetTableValue( 2119.0, 0.254902, 0.392157, 0.0784314 );
table->SetTableValue( 2120.0, 0.862745, 0.235294, 0.0784314 );
table->SetTableValue( 2121.0, 0.235294, 0.392157, 0.235294 );
table->SetTableValue( 2122.0, 0.0784314, 0.235294, 0.862745 );
table->SetTableValue( 2123.0, 0.392157, 0.392157, 0.235294 );
table->SetTableValue( 2124.0, 0.862745, 0.705882, 0.862745 );
table->SetTableValue( 2125.0, 0.0784314, 0.705882, 0.54902 );
table->SetTableValue( 2126.0, 0.235294, 0.54902, 0.705882 );
table->SetTableValue( 2127.0, 0.0980392, 0.0784314, 0.54902 );
table->SetTableValue( 2128.0, 0.0784314, 0.235294, 0.392157 );
table->SetTableValue( 2129.0, 0.235294, 0.862745, 0.0784314 );
table->SetTableValue( 2130.0, 0.235294, 0.0784314, 0.862745 );
table->SetTableValue( 2131.0, 0.862745, 0.862745, 0.392157 );
table->SetTableValue( 2132.0, 0.705882, 0.235294, 0.235294 );
table->SetTableValue( 2133.0, 0.235294, 0.235294, 0.862745 );
table->SetTableValue( 2134.0, 0.862745, 0.235294, 0.862745 );
table->SetTableValue( 2135.0, 0.254902, 0.862745, 0.235294 );
table->SetTableValue( 2136.0, 0.0980392, 0.54902, 0.0784314 );
table->SetTableValue( 2137.0, 0.0509804, 0, 0.980392 );
table->SetTableValue( 2138.0, 0.239216, 0.0784314, 0.862745 );
table->SetTableValue( 2139.0, 0.239216, 0.0784314, 0.235294 );
table->SetTableValue( 2140.0, 0.239216, 0.235294, 0.392157 );
table->SetTableValue( 2141.0, 0.0980392, 0.0980392, 0.0980392 );
table->SetTableValue( 2142.0, 0.54902, 0.0784314, 0.235294 );
table->SetTableValue( 2143.0, 0.862745, 0.705882, 0.0784314 );
table->SetTableValue( 2144.0, 0.247059, 0.705882, 0.705882 );
table->SetTableValue( 2145.0, 0.866667, 0.0784314, 0.0392157 );
table->SetTableValue( 2146.0, 0.0823529, 0.862745, 0.0784314 );
table->SetTableValue( 2147.0, 0.717647, 0.392157, 0.0784314 );
table->SetTableValue( 2148.0, 0.866667, 0.0784314, 0.392157 );
table->SetTableValue( 2149.0, 0.866667, 0.235294, 0.54902 );
table->SetTableValue( 2150.0, 0.866667, 0.0784314, 0.862745 );
table->SetTableValue( 2151.0, 0.239216, 0.862745, 0.862745 );
table->SetTableValue( 2152.0, 0.392157, 0.784314, 0.784314 );
table->SetTableValue( 2153.0, 0.0392157, 0.784314, 0.784314 );
table->SetTableValue( 2154.0, 0.866667, 0.862745, 0.0784314 );
table->SetTableValue( 2155.0, 0.552941, 0.0784314, 0.392157 );
table->SetTableValue( 2156.0, 0.239216, 0.862745, 0.392157 );
table->SetTableValue( 2157.0, 0.0823529, 0.862745, 0.235294 );
table->SetTableValue( 2158.0, 0.552941, 0.235294, 0.0784314 );
table->SetTableValue( 2159.0, 0.560784, 0.0784314, 0.862745 );
table->SetTableValue( 2160.0, 0.239216, 0.0784314, 0.705882 );
table->SetTableValue( 2161.0, 0.396078, 0.235294, 0.862745 );
table->SetTableValue( 2162.0, 0.0823529, 0.0784314, 0.54902 );
table->SetTableValue( 2163.0, 0.866667, 0.54902, 0.0784314 );
table->SetTableValue( 2164.0, 0.552941, 0.392157, 0.862745 );
table->SetTableValue( 2165.0, 0.396078, 0.0784314, 0.0784314 );
table->SetTableValue( 2166.0, 0.866667, 0.392157, 0.0784314 );
table->SetTableValue( 2167.0, 0.709804, 0.784314, 0.0784314 );
table->SetTableValue( 2168.0, 0.0823529, 0.705882, 0.54902 );
table->SetTableValue( 2169.0, 0.396078, 0.392157, 0.705882 );
table->SetTableValue( 2170.0, 0.709804, 0.862745, 0.0784314 );
table->SetTableValue( 2171.0, 0.0823529, 0.54902, 0.784314 );
table->SetTableValue( 2172.0, 0.0823529, 0.0784314, 0.941176 );
table->SetTableValue( 2173.0, 0.0823529, 0.0784314, 0.784314 );
table->SetTableValue( 2174.0, 0.239216, 0.705882, 0.235294 );
table->SetTableValue( 2175.0, 0.239216, 0.705882, 0.980392 );
table->SetTableValue( 2176.0, 0.0823529, 0.0784314, 0.235294 );
table->SetTableValue( 2177.0, 0.396078, 0.235294, 0.235294 );
table->SetTableValue( 2178.0, 0.0823529, 0.862745, 0.862745 );
table->SetTableValue( 2179.0, 0.0823529, 0.705882, 0.705882 );
table->SetTableValue( 2180.0, 0.87451, 0.862745, 0.235294 );
table->SetTableValue( 2181.0, 0.866667, 0.235294, 0.235294 );
table->SetTableValue( 2200.0, 0.0980392, 0.235294, 0.239216 );
table->SetTableValue( 2201.0, 0.0980392, 0.352941, 0.235294 );
table->SetTableValue( 2202.0, 0.0980392, 0.470588, 0.235294 );
table->SetTableValue( 2205.0, 0.0980392, 0.588235, 0.235294 );
table->SetTableValue( 2206.0, 0.0980392, 0.705882, 0.235294 );
table->SetTableValue( 2207.0, 0.0980392, 0.823529, 0.235294 );
table->SetTableValue( 2210.0, 0.0980392, 0.588235, 0.352941 );
table->SetTableValue( 2211.0, 0.0980392, 0.705882, 0.352941 );
table->SetTableValue( 2212.0, 0.0980392, 0.823529, 0.352941 );
table->SetTableValue( 3100.0, 0, 0, 0, 0);
table->SetTableValue( 3101.0, 0.196078, 0.196078, 0.196078 );
table->SetTableValue( 3102.0, 0.705882, 0.0784314, 0.117647 );
table->SetTableValue( 3103.0, 0.235294, 0.0980392, 0.0980392 );
table->SetTableValue( 3104.0, 0.0980392, 0.235294, 0.235294 );
table->SetTableValue( 3105.0, 0.705882, 0.0784314, 0.0784314 );
table->SetTableValue( 3106.0, 0.862745, 0.0784314, 0.392157 );
table->SetTableValue( 3107.0, 0.54902, 0.235294, 0.235294 );
table->SetTableValue( 3108.0, 0.705882, 0.862745, 0.54902 );
table->SetTableValue( 3109.0, 0.54902, 0.392157, 0.705882 );
table->SetTableValue( 3110.0, 0.705882, 0.0784314, 0.54902 );
table->SetTableValue( 3111.0, 0.54902, 0.0784314, 0.54902 );
table->SetTableValue( 3112.0, 0.0823529, 0.0392157, 0.0392157 );
table->SetTableValue( 3113.0, 0.882353, 0.54902, 0.54902 );
table->SetTableValue( 3114.0, 0.0901961, 0.235294, 0.705882 );
table->SetTableValue( 3115.0, 0.705882, 0.235294, 0.705882 );
table->SetTableValue( 3116.0, 0.0784314, 0.862745, 0.235294 );
table->SetTableValue( 3117.0, 0.235294, 0.0784314, 0.54902 );
table->SetTableValue( 3118.0, 0.862745, 0.705882, 0.54902 );
table->SetTableValue( 3119.0, 0.254902, 0.392157, 0.0784314 );
table->SetTableValue( 3120.0, 0.862745, 0.235294, 0.0784314 );
table->SetTableValue( 3121.0, 0.235294, 0.392157, 0.235294 );
table->SetTableValue( 3122.0, 0.0784314, 0.235294, 0.862745 );
table->SetTableValue( 3123.0, 0.392157, 0.392157, 0.235294 );
table->SetTableValue( 3124.0, 0.862745, 0.705882, 0.862745 );
table->SetTableValue( 3125.0, 0.0784314, 0.705882, 0.54902 );
table->SetTableValue( 3126.0, 0.235294, 0.54902, 0.705882 );
table->SetTableValue( 3127.0, 0.0980392, 0.0784314, 0.54902 );
table->SetTableValue( 3128.0, 0.0784314, 0.235294, 0.392157 );
table->SetTableValue( 3129.0, 0.235294, 0.862745, 0.0784314 );
table->SetTableValue( 3130.0, 0.235294, 0.0784314, 0.862745 );
table->SetTableValue( 3131.0, 0.862745, 0.862745, 0.392157 );
table->SetTableValue( 3132.0, 0.705882, 0.235294, 0.235294 );
table->SetTableValue( 3133.0, 0.235294, 0.235294, 0.862745 );
table->SetTableValue( 3134.0, 0.862745, 0.235294, 0.862745 );
table->SetTableValue( 3135.0, 0.254902, 0.862745, 0.235294 );
table->SetTableValue( 3136.0, 0.0980392, 0.54902, 0.0784314 );
table->SetTableValue( 3137.0, 0.0509804, 0, 0.980392 );
table->SetTableValue( 3138.0, 0.239216, 0.0784314, 0.862745 );
table->SetTableValue( 3139.0, 0.239216, 0.0784314, 0.235294 );
table->SetTableValue( 3140.0, 0.239216, 0.235294, 0.392157 );
table->SetTableValue( 3141.0, 0.0980392, 0.0980392, 0.0980392 );
table->SetTableValue( 3142.0, 0.54902, 0.0784314, 0.235294 );
table->SetTableValue( 3143.0, 0.862745, 0.705882, 0.0784314 );
table->SetTableValue( 3144.0, 0.247059, 0.705882, 0.705882 );
table->SetTableValue( 3145.0, 0.866667, 0.0784314, 0.0392157 );
table->SetTableValue( 3146.0, 0.0823529, 0.862745, 0.0784314 );
table->SetTableValue( 3147.0, 0.717647, 0.392157, 0.0784314 );
table->SetTableValue( 3148.0, 0.866667, 0.0784314, 0.392157 );
table->SetTableValue( 3149.0, 0.866667, 0.235294, 0.54902 );
table->SetTableValue( 3150.0, 0.866667, 0.0784314, 0.862745 );
table->SetTableValue( 3151.0, 0.239216, 0.862745, 0.862745 );
table->SetTableValue( 3152.0, 0.392157, 0.784314, 0.784314 );
table->SetTableValue( 3153.0, 0.0392157, 0.784314, 0.784314 );
table->SetTableValue( 3154.0, 0.866667, 0.862745, 0.0784314 );
table->SetTableValue( 3155.0, 0.552941, 0.0784314, 0.392157 );
table->SetTableValue( 3156.0, 0.239216, 0.862745, 0.392157 );
table->SetTableValue( 3157.0, 0.0823529, 0.862745, 0.235294 );
table->SetTableValue( 3158.0, 0.552941, 0.235294, 0.0784314 );
table->SetTableValue( 3159.0, 0.560784, 0.0784314, 0.862745 );
table->SetTableValue( 3160.0, 0.239216, 0.0784314, 0.705882 );
table->SetTableValue( 3161.0, 0.396078, 0.235294, 0.862745 );
table->SetTableValue( 3162.0, 0.0823529, 0.0784314, 0.54902 );
table->SetTableValue( 3163.0, 0.866667, 0.54902, 0.0784314 );
table->SetTableValue( 3164.0, 0.552941, 0.392157, 0.862745 );
table->SetTableValue( 3165.0, 0.396078, 0.0784314, 0.0784314 );
table->SetTableValue( 3166.0, 0.866667, 0.392157, 0.0784314 );
table->SetTableValue( 3167.0, 0.709804, 0.784314, 0.0784314 );
table->SetTableValue( 3168.0, 0.0823529, 0.705882, 0.54902 );
table->SetTableValue( 3169.0, 0.396078, 0.392157, 0.705882 );
table->SetTableValue( 3170.0, 0.709804, 0.862745, 0.0784314 );
table->SetTableValue( 3171.0, 0.0823529, 0.54902, 0.784314 );
table->SetTableValue( 3172.0, 0.0823529, 0.0784314, 0.941176 );
table->SetTableValue( 3173.0, 0.0823529, 0.0784314, 0.784314 );
table->SetTableValue( 3174.0, 0.239216, 0.705882, 0.235294 );
table->SetTableValue( 3175.0, 0.239216, 0.705882, 0.980392 );
table->SetTableValue( 3176.0, 0.0823529, 0.0784314, 0.235294 );
table->SetTableValue( 3177.0, 0.396078, 0.235294, 0.235294 );
table->SetTableValue( 3178.0, 0.0823529, 0.862745, 0.862745 );
table->SetTableValue( 3179.0, 0.0823529, 0.705882, 0.705882 );
table->SetTableValue( 3180.0, 0.87451, 0.862745, 0.235294 );
table->SetTableValue( 3181.0, 0.866667, 0.235294, 0.235294 );
table->SetTableValue( 4100.0, 0, 0, 0, 0);
table->SetTableValue( 4101.0, 0.196078, 0.196078, 0.196078 );
table->SetTableValue( 4102.0, 0.705882, 0.0784314, 0.117647 );
table->SetTableValue( 4103.0, 0.235294, 0.0980392, 0.0980392 );
table->SetTableValue( 4104.0, 0.0980392, 0.235294, 0.235294 );
table->SetTableValue( 4105.0, 0.705882, 0.0784314, 0.0784314 );
table->SetTableValue( 4106.0, 0.862745, 0.0784314, 0.392157 );
table->SetTableValue( 4107.0, 0.54902, 0.235294, 0.235294 );
table->SetTableValue( 4108.0, 0.705882, 0.862745, 0.54902 );
table->SetTableValue( 4109.0, 0.54902, 0.392157, 0.705882 );
table->SetTableValue( 4110.0, 0.705882, 0.0784314, 0.54902 );
table->SetTableValue( 4111.0, 0.54902, 0.0784314, 0.54902 );
table->SetTableValue( 4112.0, 0.0823529, 0.0392157, 0.0392157 );
table->SetTableValue( 4113.0, 0.882353, 0.54902, 0.54902 );
table->SetTableValue( 4114.0, 0.0901961, 0.235294, 0.705882 );
table->SetTableValue( 4115.0, 0.705882, 0.235294, 0.705882 );
table->SetTableValue( 4116.0, 0.0784314, 0.862745, 0.235294 );
table->SetTableValue( 4117.0, 0.235294, 0.0784314, 0.54902 );
table->SetTableValue( 4118.0, 0.862745, 0.705882, 0.54902 );
table->SetTableValue( 4119.0, 0.254902, 0.392157, 0.0784314 );
table->SetTableValue( 4120.0, 0.862745, 0.235294, 0.0784314 );
table->SetTableValue( 4121.0, 0.235294, 0.392157, 0.235294 );
table->SetTableValue( 4122.0, 0.0784314, 0.235294, 0.862745 );
table->SetTableValue( 4123.0, 0.392157, 0.392157, 0.235294 );
table->SetTableValue( 4124.0, 0.862745, 0.705882, 0.862745 );
table->SetTableValue( 4125.0, 0.0784314, 0.705882, 0.54902 );
table->SetTableValue( 4126.0, 0.235294, 0.54902, 0.705882 );
table->SetTableValue( 4127.0, 0.0980392, 0.0784314, 0.54902 );
table->SetTableValue( 4128.0, 0.0784314, 0.235294, 0.392157 );
table->SetTableValue( 4129.0, 0.235294, 0.862745, 0.0784314 );
table->SetTableValue( 4130.0, 0.235294, 0.0784314, 0.862745 );
table->SetTableValue( 4131.0, 0.862745, 0.862745, 0.392157 );
table->SetTableValue( 4132.0, 0.705882, 0.235294, 0.235294 );
table->SetTableValue( 4133.0, 0.235294, 0.235294, 0.862745 );
table->SetTableValue( 4134.0, 0.862745, 0.235294, 0.862745 );
table->SetTableValue( 4135.0, 0.254902, 0.862745, 0.235294 );
table->SetTableValue( 4136.0, 0.0980392, 0.54902, 0.0784314 );
table->SetTableValue( 4137.0, 0.0509804, 0, 0.980392 );
table->SetTableValue( 4138.0, 0.239216, 0.0784314, 0.862745 );
table->SetTableValue( 4139.0, 0.239216, 0.0784314, 0.235294 );
table->SetTableValue( 4140.0, 0.239216, 0.235294, 0.392157 );
table->SetTableValue( 4141.0, 0.0980392, 0.0980392, 0.0980392 );
table->SetTableValue( 4142.0, 0.54902, 0.0784314, 0.235294 );
table->SetTableValue( 4143.0, 0.862745, 0.705882, 0.0784314 );
table->SetTableValue( 4144.0, 0.247059, 0.705882, 0.705882 );
table->SetTableValue( 4145.0, 0.866667, 0.0784314, 0.0392157 );
table->SetTableValue( 4146.0, 0.0823529, 0.862745, 0.0784314 );
table->SetTableValue( 4147.0, 0.717647, 0.392157, 0.0784314 );
table->SetTableValue( 4148.0, 0.866667, 0.0784314, 0.392157 );
table->SetTableValue( 4149.0, 0.866667, 0.235294, 0.54902 );
table->SetTableValue( 4150.0, 0.866667, 0.0784314, 0.862745 );
table->SetTableValue( 4151.0, 0.239216, 0.862745, 0.862745 );
table->SetTableValue( 4152.0, 0.392157, 0.784314, 0.784314 );
table->SetTableValue( 4153.0, 0.0392157, 0.784314, 0.784314 );
table->SetTableValue( 4154.0, 0.866667, 0.862745, 0.0784314 );
table->SetTableValue( 4155.0, 0.552941, 0.0784314, 0.392157 );
table->SetTableValue( 4156.0, 0.239216, 0.862745, 0.392157 );
table->SetTableValue( 4157.0, 0.0823529, 0.862745, 0.235294 );
table->SetTableValue( 4158.0, 0.552941, 0.235294, 0.0784314 );
table->SetTableValue( 4159.0, 0.560784, 0.0784314, 0.862745 );
table->SetTableValue( 4160.0, 0.239216, 0.0784314, 0.705882 );
table->SetTableValue( 4161.0, 0.396078, 0.235294, 0.862745 );
table->SetTableValue( 4162.0, 0.0823529, 0.0784314, 0.54902 );
table->SetTableValue( 4163.0, 0.866667, 0.54902, 0.0784314 );
table->SetTableValue( 4164.0, 0.552941, 0.392157, 0.862745 );
table->SetTableValue( 4165.0, 0.396078, 0.0784314, 0.0784314 );
table->SetTableValue( 4166.0, 0.866667, 0.392157, 0.0784314 );
table->SetTableValue( 4167.0, 0.709804, 0.784314, 0.0784314 );
table->SetTableValue( 4168.0, 0.0823529, 0.705882, 0.54902 );
table->SetTableValue( 4169.0, 0.396078, 0.392157, 0.705882 );
table->SetTableValue( 4170.0, 0.709804, 0.862745, 0.0784314 );
table->SetTableValue( 4171.0, 0.0823529, 0.54902, 0.784314 );
table->SetTableValue( 4172.0, 0.0823529, 0.0784314, 0.941176 );
table->SetTableValue( 4173.0, 0.0823529, 0.0784314, 0.784314 );
table->SetTableValue( 4174.0, 0.239216, 0.705882, 0.235294 );
table->SetTableValue( 4175.0, 0.239216, 0.705882, 0.980392 );
table->SetTableValue( 4176.0, 0.0823529, 0.0784314, 0.235294 );
table->SetTableValue( 4177.0, 0.396078, 0.235294, 0.235294 );
table->SetTableValue( 4178.0, 0.0823529, 0.862745, 0.862745 );
table->SetTableValue( 4179.0, 0.0823529, 0.705882, 0.705882 );
table->SetTableValue( 4180.0, 0.87451, 0.862745, 0.235294 );
table->SetTableValue( 4181.0, 0.866667, 0.235294, 0.235294 );
table->SetTableValue( 5001.0, 0.0784314, 0.117647, 0.156863 );
table->SetTableValue( 5002.0, 0.0784314, 0.117647, 0.156863 );
table->SetTableValue( 5100.0, 0.8, 0.4, 0.4 );
table->SetTableValue( 5101.0, 0.8, 0.4, 0.4 );
table->SetTableValue( 5102.0, 1, 1, 0.4 );
table->SetTableValue( 5103.0, 0.6, 0.8, 0 );
table->SetTableValue( 5104.0, 0, 0.6, 0.6 );
table->SetTableValue( 5105.0, 0.8, 0.6, 1 );
table->SetTableValue( 5106.0, 1, 0.6, 0.2 );
table->SetTableValue( 5107.0, 0.8, 0.8, 0.8 );
table->SetTableValue( 5108.0, 0.6, 1, 1 );
table->SetTableValue( 5109.0, 0.4, 0.6, 1 );
table->SetTableValue( 5110.0, 1, 1, 0.4 );
table->SetTableValue( 5111.0, 0.6, 0.8, 0 );
table->SetTableValue( 5112.0, 0, 0.6, 0.6 );
table->SetTableValue( 5113.0, 0.8, 0.6, 1 );
table->SetTableValue( 5114.0, 1, 0.6, 0.2 );
table->SetTableValue( 5115.0, 0.8, 0.8, 0.8 );
table->SetTableValue( 5116.0, 0.6, 1, 1 );
table->SetTableValue( 5117.0, 0.4, 0.6, 1 );
table->SetTableValue( 5200.0, 0.8, 0.4, 0.4 );
table->SetTableValue( 5201.0, 0.8, 0.4, 0.4 );
table->SetTableValue( 5202.0, 1, 1, 0.4 );
table->SetTableValue( 5203.0, 0.6, 0.8, 0 );
table->SetTableValue( 5204.0, 0, 0.6, 0.6 );
table->SetTableValue( 5205.0, 0.8, 0.6, 1 );
table->SetTableValue( 5206.0, 1, 0.6, 0.2 );
table->SetTableValue( 5207.0, 0.8, 0.8, 0.8 );
table->SetTableValue( 5208.0, 0.6, 1, 1 );
table->SetTableValue( 5209.0, 0.4, 0.6, 1 );
table->SetTableValue( 5210.0, 1, 1, 0.4 );
table->SetTableValue( 5211.0, 0.6, 0.8, 0 );
table->SetTableValue( 5212.0, 0, 0.6, 0.6 );
table->SetTableValue( 5213.0, 0.8, 0.6, 1 );
table->SetTableValue( 5214.0, 1, 0.6, 0.2 );
table->SetTableValue( 5215.0, 0.8, 0.8, 0.8 );
table->SetTableValue( 5216.0, 0.6, 1, 1 );
table->SetTableValue( 5217.0, 0.4, 0.6, 1 );
table->SetTableValue( 6000.0, 0, 1, 0 );
table->SetTableValue( 6001.0, 1, 1, 0 );
table->SetTableValue( 6002.0, 0, 1, 1 );
table->SetTableValue( 6003.0, 0, 0, 1 );
table->SetTableValue( 6010.0, 0.92549, 0.0627451, 0.905882 );
table->SetTableValue( 6020.0, 0.929412, 0.0705882, 0.909804 );
table->SetTableValue( 6030.0, 0.92549, 0.0509804, 0.890196 );
table->SetTableValue( 6040.0, 0.92549, 0.0666667, 0.894118 );
table->SetTableValue( 6050.0, 0.00392157, 1, 0.00392157 );
table->SetTableValue( 6060.0, 0.00784314, 1, 0.00392157 );
table->SetTableValue( 6070.0, 0.92549, 0.054902, 0.901961 );
table->SetTableValue( 6080.0, 0.929412, 0.054902, 0.901961 );
table->SetTableValue( 7001.0, 0.282353, 0.517647, 0.709804 );
table->SetTableValue( 7002.0, 0.952941, 0.952941, 0.952941 );
table->SetTableValue( 7003.0, 0.811765, 0.247059, 0.309804 );
table->SetTableValue( 7004.0, 0.47451, 0.0784314, 0.529412 );
table->SetTableValue( 7005.0, 0.772549, 0.235294, 0.972549 );
table->SetTableValue( 7006.0, 0.00784314, 0.584314, 0.00784314 );
table->SetTableValue( 7007.0, 0.866667, 0.976471, 0.65098 );
table->SetTableValue( 7008.0, 0.909804, 0.572549, 0.137255 );
table->SetTableValue( 7009.0, 0.0784314, 0.235294, 0.470588 );
table->SetTableValue( 7010.0, 0.980392, 0.980392, 0 );
table->SetTableValue( 7011.0, 0.478431, 0.733333, 0.870588 );
table->SetTableValue( 7012.0, 0.929412, 0.0470588, 0.694118 );
table->SetTableValue( 7013.0, 0.0392157, 0.192157, 1 );
table->SetTableValue( 7014.0, 0.803922, 0.721569, 0.564706 );
table->SetTableValue( 7015.0, 0.176471, 0.803922, 0.647059 );
table->SetTableValue( 7016.0, 0.458824, 0.627451, 0.686275 );
table->SetTableValue( 7017.0, 0.866667, 0.85098, 0.0823529 );
table->SetTableValue( 7018.0, 0.0784314, 0.235294, 0.470588 );
table->SetTableValue( 7019.0, 0.552941, 0.0823529, 0.392157 );
table->SetTableValue( 7020.0, 0.882353, 0.54902, 0.552941 );
table->SetTableValue( 7100.0, 0.164706, 0.788235, 0.658824 );
table->SetTableValue( 7101.0, 0.658824, 0.407843, 0.635294 );
table->SetTableValue( 8001.0, 0.290196, 0.509804, 0.709804 );
table->SetTableValue( 8002.0, 0.94902, 0.945098, 0.941176 );
table->SetTableValue( 8003.0, 0.807843, 0.254902, 0.305882 );
table->SetTableValue( 8004.0, 0.470588, 0.0823529, 0.521569 );
table->SetTableValue( 8005.0, 0.764706, 0.239216, 0.964706 );
table->SetTableValue( 8006.0, 0.0117647, 0.576471, 0.0235294 );
table->SetTableValue( 8007.0, 0.862745, 0.984314, 0.639216 );
table->SetTableValue( 8008.0, 0.909804, 0.572549, 0.129412 );
table->SetTableValue( 8009.0, 0.0156863, 0.447059, 0.054902 );
table->SetTableValue( 8010.0, 0.47451, 0.721569, 0.862745 );
table->SetTableValue( 8011.0, 0.921569, 0.0431373, 0.686275 );
table->SetTableValue( 8012.0, 0.0470588, 0.180392, 0.980392 );
table->SetTableValue( 8013.0, 0.796078, 0.713725, 0.560784 );
table->SetTableValue( 8014.0, 0.164706, 0.8, 0.654902 );
table->SetTableValue( 9000.0, 0.117647, 0.0196078, 0.117647 );
table->SetTableValue( 9001.0, 0.117647, 0.392157, 0.176471 );
table->SetTableValue( 9002.0, 0.509804, 0.392157, 0.647059 );
table->SetTableValue( 9003.0, 0.411765, 0.0980392, 0.0196078 );
table->SetTableValue( 9004.0, 0.490196, 0.27451, 0.215686 );
table->SetTableValue( 9005.0, 0.882353, 0.0784314, 0.411765 );
table->SetTableValue( 9006.0, 0.882353, 0.0784314, 0.0588235 );
table->SetTableValue( 9500.0, 0.117647, 0.215686, 0.117647 );
table->SetTableValue( 9501.0, 0.117647, 0.588235, 0.176471 );
table->SetTableValue( 9502.0, 0.509804, 0.588235, 0.647059 );
table->SetTableValue( 9503.0, 0.411765, 0.294118, 0.0196078 );
table->SetTableValue( 9504.0, 0.490196, 0.470588, 0.215686 );
table->SetTableValue( 9505.0, 0.882353, 0.27451, 0.411765 );
table->SetTableValue( 9506.0, 0.882353, 0.27451, 0.0588235 );
table->SetTableValue( 11100.0, 0, 0, 0, 0);
table->SetTableValue( 11101.0, 0.0901961, 0.862745, 0.235294 );
table->SetTableValue( 11102.0, 0.0901961, 0.235294, 0.705882 );
table->SetTableValue( 11103.0, 0.247059, 0.392157, 0.235294 );
table->SetTableValue( 11104.0, 0.247059, 0.0784314, 0.862745 );
table->SetTableValue( 11105.0, 0.0509804, 0, 0.980392 );
table->SetTableValue( 11106.0, 0.101961, 0.235294, 0 );
table->SetTableValue( 11107.0, 0.101961, 0.235294, 0.294118 );
table->SetTableValue( 11108.0, 0.101961, 0.235294, 0.588235 );
table->SetTableValue( 11109.0, 0.0980392, 0.235294, 0.980392 );
table->SetTableValue( 11110.0, 0.235294, 0.0980392, 0.0980392 );
table->SetTableValue( 11111.0, 0.705882, 0.0784314, 0.0784314 );
table->SetTableValue( 11112.0, 0.862745, 0.0784314, 0.392157 );
table->SetTableValue( 11113.0, 0.54902, 0.235294, 0.235294 );
table->SetTableValue( 11114.0, 0.705882, 0.862745, 0.54902 );
table->SetTableValue( 11115.0, 0.54902, 0.392157, 0.705882 );
table->SetTableValue( 11116.0, 0.705882, 0.0784314, 0.54902 );
table->SetTableValue( 11117.0, 0.0901961, 0.0392157, 0.0392157 );
table->SetTableValue( 11118.0, 0.882353, 0.54902, 0.54902 );
table->SetTableValue( 11119.0, 0.705882, 0.235294, 0.705882 );
table->SetTableValue( 11120.0, 0.0784314, 0.862745, 0.235294 );
table->SetTableValue( 11121.0, 0.235294, 0.0784314, 0.54902 );
table->SetTableValue( 11122.0, 0.862745, 0.705882, 0.54902 );
table->SetTableValue( 11123.0, 0.254902, 0.392157, 0.0784314 );
table->SetTableValue( 11124.0, 0.862745, 0.235294, 0.0784314 );
table->SetTableValue( 11125.0, 0.0784314, 0.235294, 0.862745 );
table->SetTableValue( 11126.0, 0.392157, 0.392157, 0.235294 );
table->SetTableValue( 11127.0, 0.862745, 0.705882, 0.862745 );
table->SetTableValue( 11128.0, 0.0784314, 0.705882, 0.54902 );
table->SetTableValue( 11129.0, 0.235294, 0.54902, 0.705882 );
table->SetTableValue( 11130.0, 0.0980392, 0.0784314, 0.54902 );
table->SetTableValue( 11131.0, 0.0784314, 0.235294, 0.392157 );
table->SetTableValue( 11132.0, 0.235294, 0.862745, 0.0784314 );
table->SetTableValue( 11133.0, 0.235294, 0.235294, 0.862745 );
table->SetTableValue( 11134.0, 0.862745, 0.235294, 0.862745 );
table->SetTableValue( 11135.0, 0.254902, 0.862745, 0.235294 );
table->SetTableValue( 11136.0, 0.0980392, 0.54902, 0.0784314 );
table->SetTableValue( 11137.0, 0.862745, 0.862745, 0.392157 );
table->SetTableValue( 11138.0, 0.705882, 0.235294, 0.235294 );
table->SetTableValue( 11139.0, 0.239216, 0.0784314, 0.862745 );
table->SetTableValue( 11140.0, 0.239216, 0.0784314, 0.235294 );
table->SetTableValue( 11141.0, 0.239216, 0.235294, 0.392157 );
table->SetTableValue( 11142.0, 0.0980392, 0.0980392, 0.0980392 );
table->SetTableValue( 11143.0, 0.54902, 0.0784314, 0.235294 );
table->SetTableValue( 11144.0, 0.862745, 0.705882, 0.0784314 );
table->SetTableValue( 11145.0, 0.247059, 0.705882, 0.705882 );
table->SetTableValue( 11146.0, 0.866667, 0.0784314, 0.0392157 );
table->SetTableValue( 11147.0, 0.866667, 0.0784314, 0.392157 );
table->SetTableValue( 11148.0, 0.866667, 0.235294, 0.54902 );
table->SetTableValue( 11149.0, 0.866667, 0.0784314, 0.862745 );
table->SetTableValue( 11150.0, 0.239216, 0.862745, 0.862745 );
table->SetTableValue( 11151.0, 0.392157, 0.784314, 0.784314 );
table->SetTableValue( 11152.0, 0.0392157, 0.784314, 0.784314 );
table->SetTableValue( 11153.0, 0.866667, 0.862745, 0.0784314 );
table->SetTableValue( 11154.0, 0.552941, 0.0784314, 0.392157 );
table->SetTableValue( 11155.0, 0.239216, 0.862745, 0.392157 );
table->SetTableValue( 11156.0, 0.552941, 0.235294, 0.0784314 );
table->SetTableValue( 11157.0, 0.560784, 0.0784314, 0.862745 );
table->SetTableValue( 11158.0, 0.396078, 0.235294, 0.862745 );
table->SetTableValue( 11159.0, 0.0823529, 0.0784314, 0.54902 );
table->SetTableValue( 11160.0, 0.239216, 0.0784314, 0.705882 );
table->SetTableValue( 11161.0, 0.866667, 0.54902, 0.0784314 );
table->SetTableValue( 11162.0, 0.552941, 0.392157, 0.862745 );
table->SetTableValue( 11163.0, 0.866667, 0.392157, 0.0784314 );
table->SetTableValue( 11164.0, 0.709804, 0.784314, 0.0784314 );
table->SetTableValue( 11165.0, 0.396078, 0.0784314, 0.0784314 );
table->SetTableValue( 11166.0, 0.396078, 0.392157, 0.705882 );
table->SetTableValue( 11167.0, 0.709804, 0.862745, 0.0784314 );
table->SetTableValue( 11168.0, 0.0823529, 0.54902, 0.784314 );
table->SetTableValue( 11169.0, 0.0823529, 0.0784314, 0.941176 );
table->SetTableValue( 11170.0, 0.0823529, 0.0784314, 0.784314 );
table->SetTableValue( 11171.0, 0.0823529, 0.0784314, 0.235294 );
table->SetTableValue( 11172.0, 0.396078, 0.235294, 0.235294 );
table->SetTableValue( 11173.0, 0.0823529, 0.705882, 0.705882 );
table->SetTableValue( 11174.0, 0.87451, 0.862745, 0.235294 );
table->SetTableValue( 11175.0, 0.866667, 0.235294, 0.235294 );
table->SetTableValue( 12100.0, 0, 0, 0, 0);
table->SetTableValue( 12101.0, 0.0901961, 0.862745, 0.235294 );
table->SetTableValue( 12102.0, 0.0901961, 0.235294, 0.705882 );
table->SetTableValue( 12103.0, 0.247059, 0.392157, 0.235294 );
table->SetTableValue( 12104.0, 0.247059, 0.0784314, 0.862745 );
table->SetTableValue( 12105.0, 0.0509804, 0, 0.980392 );
table->SetTableValue( 12106.0, 0.101961, 0.235294, 0 );
table->SetTableValue( 12107.0, 0.101961, 0.235294, 0.294118 );
table->SetTableValue( 12108.0, 0.101961, 0.235294, 0.588235 );
table->SetTableValue( 12109.0, 0.0980392, 0.235294, 0.980392 );
table->SetTableValue( 12110.0, 0.235294, 0.0980392, 0.0980392 );
table->SetTableValue( 12111.0, 0.705882, 0.0784314, 0.0784314 );
table->SetTableValue( 12112.0, 0.862745, 0.0784314, 0.392157 );
table->SetTableValue( 12113.0, 0.54902, 0.235294, 0.235294 );
table->SetTableValue( 12114.0, 0.705882, 0.862745, 0.54902 );
table->SetTableValue( 12115.0, 0.54902, 0.392157, 0.705882 );
table->SetTableValue( 12116.0, 0.705882, 0.0784314, 0.54902 );
table->SetTableValue( 12117.0, 0.0901961, 0.0392157, 0.0392157 );
table->SetTableValue( 12118.0, 0.882353, 0.54902, 0.54902 );
table->SetTableValue( 12119.0, 0.705882, 0.235294, 0.705882 );
table->SetTableValue( 12120.0, 0.0784314, 0.862745, 0.235294 );
table->SetTableValue( 12121.0, 0.235294, 0.0784314, 0.54902 );
table->SetTableValue( 12122.0, 0.862745, 0.705882, 0.54902 );
table->SetTableValue( 12123.0, 0.254902, 0.392157, 0.0784314 );
table->SetTableValue( 12124.0, 0.862745, 0.235294, 0.0784314 );
table->SetTableValue( 12125.0, 0.0784314, 0.235294, 0.862745 );
table->SetTableValue( 12126.0, 0.392157, 0.392157, 0.235294 );
table->SetTableValue( 12127.0, 0.862745, 0.705882, 0.862745 );
table->SetTableValue( 12128.0, 0.0784314, 0.705882, 0.54902 );
table->SetTableValue( 12129.0, 0.235294, 0.54902, 0.705882 );
table->SetTableValue( 12130.0, 0.0980392, 0.0784314, 0.54902 );
table->SetTableValue( 12131.0, 0.0784314, 0.235294, 0.392157 );
table->SetTableValue( 12132.0, 0.235294, 0.862745, 0.0784314 );
table->SetTableValue( 12133.0, 0.235294, 0.235294, 0.862745 );
table->SetTableValue( 12134.0, 0.862745, 0.235294, 0.862745 );
table->SetTableValue( 12135.0, 0.254902, 0.862745, 0.235294 );
table->SetTableValue( 12136.0, 0.0980392, 0.54902, 0.0784314 );
table->SetTableValue( 12137.0, 0.862745, 0.862745, 0.392157 );
table->SetTableValue( 12138.0, 0.705882, 0.235294, 0.235294 );
table->SetTableValue( 12139.0, 0.239216, 0.0784314, 0.862745 );
table->SetTableValue( 12140.0, 0.239216, 0.0784314, 0.235294 );
table->SetTableValue( 12141.0, 0.239216, 0.235294, 0.392157 );
table->SetTableValue( 12142.0, 0.0980392, 0.0980392, 0.0980392 );
table->SetTableValue( 12143.0, 0.54902, 0.0784314, 0.235294 );
table->SetTableValue( 12144.0, 0.862745, 0.705882, 0.0784314 );
table->SetTableValue( 12145.0, 0.247059, 0.705882, 0.705882 );
table->SetTableValue( 12146.0, 0.866667, 0.0784314, 0.0392157 );
table->SetTableValue( 12147.0, 0.866667, 0.0784314, 0.392157 );
table->SetTableValue( 12148.0, 0.866667, 0.235294, 0.54902 );
table->SetTableValue( 12149.0, 0.866667, 0.0784314, 0.862745 );
table->SetTableValue( 12150.0, 0.239216, 0.862745, 0.862745 );
table->SetTableValue( 12151.0, 0.392157, 0.784314, 0.784314 );
table->SetTableValue( 12152.0, 0.0392157, 0.784314, 0.784314 );
table->SetTableValue( 12153.0, 0.866667, 0.862745, 0.0784314 );
table->SetTableValue( 12154.0, 0.552941, 0.0784314, 0.392157 );
table->SetTableValue( 12155.0, 0.239216, 0.862745, 0.392157 );
table->SetTableValue( 12156.0, 0.552941, 0.235294, 0.0784314 );
table->SetTableValue( 12157.0, 0.560784, 0.0784314, 0.862745 );
table->SetTableValue( 12158.0, 0.396078, 0.235294, 0.862745 );
table->SetTableValue( 12159.0, 0.0823529, 0.0784314, 0.54902 );
table->SetTableValue( 12160.0, 0.239216, 0.0784314, 0.705882 );
table->SetTableValue( 12161.0, 0.866667, 0.54902, 0.0784314 );
table->SetTableValue( 12162.0, 0.552941, 0.392157, 0.862745 );
table->SetTableValue( 12163.0, 0.866667, 0.392157, 0.0784314 );
table->SetTableValue( 12164.0, 0.709804, 0.784314, 0.0784314 );
table->SetTableValue( 12165.0, 0.396078, 0.0784314, 0.0784314 );
table->SetTableValue( 12166.0, 0.396078, 0.392157, 0.705882 );
table->SetTableValue( 12167.0, 0.709804, 0.862745, 0.0784314 );
table->SetTableValue( 12168.0, 0.0823529, 0.54902, 0.784314 );
table->SetTableValue( 12169.0, 0.0823529, 0.0784314, 0.941176 );
table->SetTableValue( 12170.0, 0.0823529, 0.0784314, 0.784314 );
table->SetTableValue( 12171.0, 0.0823529, 0.0784314, 0.235294 );
table->SetTableValue( 12172.0, 0.396078, 0.235294, 0.235294 );
table->SetTableValue( 12173.0, 0.0823529, 0.705882, 0.705882 );
table->SetTableValue( 12174.0, 0.87451, 0.862745, 0.235294 );
table->SetTableValue( 12175.0, 0.866667, 0.235294, 0.235294 );
table->SetTableValue( 13100.0, 0, 0, 0, 0);
table->SetTableValue( 13101.0, 0.0901961, 0.862745, 0.235294 );
table->SetTableValue( 13102.0, 0.0901961, 0.235294, 0.705882 );
table->SetTableValue( 13103.0, 0.247059, 0.392157, 0.235294 );
table->SetTableValue( 13104.0, 0.247059, 0.0784314, 0.862745 );
table->SetTableValue( 13105.0, 0.0509804, 0, 0.980392 );
table->SetTableValue( 13106.0, 0.101961, 0.235294, 0 );
table->SetTableValue( 13107.0, 0.101961, 0.235294, 0.294118 );
table->SetTableValue( 13108.0, 0.101961, 0.235294, 0.588235 );
table->SetTableValue( 13109.0, 0.0980392, 0.235294, 0.980392 );
table->SetTableValue( 13110.0, 0.235294, 0.0980392, 0.0980392 );
table->SetTableValue( 13111.0, 0.705882, 0.0784314, 0.0784314 );
table->SetTableValue( 13112.0, 0.862745, 0.0784314, 0.392157 );
table->SetTableValue( 13113.0, 0.54902, 0.235294, 0.235294 );
table->SetTableValue( 13114.0, 0.705882, 0.862745, 0.54902 );
table->SetTableValue( 13115.0, 0.54902, 0.392157, 0.705882 );
table->SetTableValue( 13116.0, 0.705882, 0.0784314, 0.54902 );
table->SetTableValue( 13117.0, 0.0901961, 0.0392157, 0.0392157 );
table->SetTableValue( 13118.0, 0.882353, 0.54902, 0.54902 );
table->SetTableValue( 13119.0, 0.705882, 0.235294, 0.705882 );
table->SetTableValue( 13120.0, 0.0784314, 0.862745, 0.235294 );
table->SetTableValue( 13121.0, 0.235294, 0.0784314, 0.54902 );
table->SetTableValue( 13122.0, 0.862745, 0.705882, 0.54902 );
table->SetTableValue( 13123.0, 0.254902, 0.392157, 0.0784314 );
table->SetTableValue( 13124.0, 0.862745, 0.235294, 0.0784314 );
table->SetTableValue( 13125.0, 0.0784314, 0.235294, 0.862745 );
table->SetTableValue( 13126.0, 0.392157, 0.392157, 0.235294 );
table->SetTableValue( 13127.0, 0.862745, 0.705882, 0.862745 );
table->SetTableValue( 13128.0, 0.0784314, 0.705882, 0.54902 );
table->SetTableValue( 13129.0, 0.235294, 0.54902, 0.705882 );
table->SetTableValue( 13130.0, 0.0980392, 0.0784314, 0.54902 );
table->SetTableValue( 13131.0, 0.0784314, 0.235294, 0.392157 );
table->SetTableValue( 13132.0, 0.235294, 0.862745, 0.0784314 );
table->SetTableValue( 13133.0, 0.235294, 0.235294, 0.862745 );
table->SetTableValue( 13134.0, 0.862745, 0.235294, 0.862745 );
table->SetTableValue( 13135.0, 0.254902, 0.862745, 0.235294 );
table->SetTableValue( 13136.0, 0.0980392, 0.54902, 0.0784314 );
table->SetTableValue( 13137.0, 0.862745, 0.862745, 0.392157 );
table->SetTableValue( 13138.0, 0.705882, 0.235294, 0.235294 );
table->SetTableValue( 13139.0, 0.239216, 0.0784314, 0.862745 );
table->SetTableValue( 13140.0, 0.239216, 0.0784314, 0.235294 );
table->SetTableValue( 13141.0, 0.239216, 0.235294, 0.392157 );
table->SetTableValue( 13142.0, 0.0980392, 0.0980392, 0.0980392 );
table->SetTableValue( 13143.0, 0.54902, 0.0784314, 0.235294 );
table->SetTableValue( 13144.0, 0.862745, 0.705882, 0.0784314 );
table->SetTableValue( 13145.0, 0.247059, 0.705882, 0.705882 );
table->SetTableValue( 13146.0, 0.866667, 0.0784314, 0.0392157 );
table->SetTableValue( 13147.0, 0.866667, 0.0784314, 0.392157 );
table->SetTableValue( 13148.0, 0.866667, 0.235294, 0.54902 );
table->SetTableValue( 13149.0, 0.866667, 0.0784314, 0.862745 );
table->SetTableValue( 13150.0, 0.239216, 0.862745, 0.862745 );
table->SetTableValue( 13151.0, 0.392157, 0.784314, 0.784314 );
table->SetTableValue( 13152.0, 0.0392157, 0.784314, 0.784314 );
table->SetTableValue( 13153.0, 0.866667, 0.862745, 0.0784314 );
table->SetTableValue( 13154.0, 0.552941, 0.0784314, 0.392157 );
table->SetTableValue( 13155.0, 0.239216, 0.862745, 0.392157 );
table->SetTableValue( 13156.0, 0.552941, 0.235294, 0.0784314 );
table->SetTableValue( 13157.0, 0.560784, 0.0784314, 0.862745 );
table->SetTableValue( 13158.0, 0.396078, 0.235294, 0.862745 );
table->SetTableValue( 13159.0, 0.0823529, 0.0784314, 0.54902 );
table->SetTableValue( 13160.0, 0.239216, 0.0784314, 0.705882 );
table->SetTableValue( 13161.0, 0.866667, 0.54902, 0.0784314 );
table->SetTableValue( 13162.0, 0.552941, 0.392157, 0.862745 );
table->SetTableValue( 13163.0, 0.866667, 0.392157, 0.0784314 );
table->SetTableValue( 13164.0, 0.709804, 0.784314, 0.0784314 );
table->SetTableValue( 13165.0, 0.396078, 0.0784314, 0.0784314 );
table->SetTableValue( 13166.0, 0.396078, 0.392157, 0.705882 );
table->SetTableValue( 13167.0, 0.709804, 0.862745, 0.0784314 );
table->SetTableValue( 13168.0, 0.0823529, 0.54902, 0.784314 );
table->SetTableValue( 13169.0, 0.0823529, 0.0784314, 0.941176 );
table->SetTableValue( 13170.0, 0.0823529, 0.0784314, 0.784314 );
table->SetTableValue( 13171.0, 0.0823529, 0.0784314, 0.235294 );
table->SetTableValue( 13172.0, 0.396078, 0.235294, 0.235294 );
table->SetTableValue( 13173.0, 0.0823529, 0.705882, 0.705882 );
table->SetTableValue( 13174.0, 0.87451, 0.862745, 0.235294 );
table->SetTableValue( 13175.0, 0.866667, 0.235294, 0.235294 );
table->SetTableValue( 14100.0, 0, 0, 0, 0);
table->SetTableValue( 14101.0, 0.0901961, 0.862745, 0.235294 );
table->SetTableValue( 14102.0, 0.0901961, 0.235294, 0.705882 );
table->SetTableValue( 14103.0, 0.247059, 0.392157, 0.235294 );
table->SetTableValue( 14104.0, 0.247059, 0.0784314, 0.862745 );
table->SetTableValue( 14105.0, 0.0509804, 0, 0.980392 );
table->SetTableValue( 14106.0, 0.101961, 0.235294, 0 );
table->SetTableValue( 14107.0, 0.101961, 0.235294, 0.294118 );
table->SetTableValue( 14108.0, 0.101961, 0.235294, 0.588235 );
table->SetTableValue( 14109.0, 0.0980392, 0.235294, 0.980392 );
table->SetTableValue( 14110.0, 0.235294, 0.0980392, 0.0980392 );
table->SetTableValue( 14111.0, 0.705882, 0.0784314, 0.0784314 );
table->SetTableValue( 14112.0, 0.862745, 0.0784314, 0.392157 );
table->SetTableValue( 14113.0, 0.54902, 0.235294, 0.235294 );
table->SetTableValue( 14114.0, 0.705882, 0.862745, 0.54902 );
table->SetTableValue( 14115.0, 0.54902, 0.392157, 0.705882 );
table->SetTableValue( 14116.0, 0.705882, 0.0784314, 0.54902 );
table->SetTableValue( 14117.0, 0.0901961, 0.0392157, 0.0392157 );
table->SetTableValue( 14118.0, 0.882353, 0.54902, 0.54902 );
table->SetTableValue( 14119.0, 0.705882, 0.235294, 0.705882 );
table->SetTableValue( 14120.0, 0.0784314, 0.862745, 0.235294 );
table->SetTableValue( 14121.0, 0.235294, 0.0784314, 0.54902 );
table->SetTableValue( 14122.0, 0.862745, 0.705882, 0.54902 );
table->SetTableValue( 14123.0, 0.254902, 0.392157, 0.0784314 );
table->SetTableValue( 14124.0, 0.862745, 0.235294, 0.0784314 );
table->SetTableValue( 14125.0, 0.0784314, 0.235294, 0.862745 );
table->SetTableValue( 14126.0, 0.392157, 0.392157, 0.235294 );
table->SetTableValue( 14127.0, 0.862745, 0.705882, 0.862745 );
table->SetTableValue( 14128.0, 0.0784314, 0.705882, 0.54902 );
table->SetTableValue( 14129.0, 0.235294, 0.54902, 0.705882 );
table->SetTableValue( 14130.0, 0.0980392, 0.0784314, 0.54902 );
table->SetTableValue( 14131.0, 0.0784314, 0.235294, 0.392157 );
table->SetTableValue( 14132.0, 0.235294, 0.862745, 0.0784314 );
table->SetTableValue( 14133.0, 0.235294, 0.235294, 0.862745 );
table->SetTableValue( 14134.0, 0.862745, 0.235294, 0.862745 );
table->SetTableValue( 14135.0, 0.254902, 0.862745, 0.235294 );
table->SetTableValue( 14136.0, 0.0980392, 0.54902, 0.0784314 );
table->SetTableValue( 14137.0, 0.862745, 0.862745, 0.392157 );
table->SetTableValue( 14138.0, 0.705882, 0.235294, 0.235294 );
table->SetTableValue( 14139.0, 0.239216, 0.0784314, 0.862745 );
table->SetTableValue( 14140.0, 0.239216, 0.0784314, 0.235294 );
table->SetTableValue( 14141.0, 0.239216, 0.235294, 0.392157 );
table->SetTableValue( 14142.0, 0.0980392, 0.0980392, 0.0980392 );
table->SetTableValue( 14143.0, 0.54902, 0.0784314, 0.235294 );
table->SetTableValue( 14144.0, 0.862745, 0.705882, 0.0784314 );
table->SetTableValue( 14145.0, 0.247059, 0.705882, 0.705882 );
table->SetTableValue( 14146.0, 0.866667, 0.0784314, 0.0392157 );
table->SetTableValue( 14147.0, 0.866667, 0.0784314, 0.392157 );
table->SetTableValue( 14148.0, 0.866667, 0.235294, 0.54902 );
table->SetTableValue( 14149.0, 0.866667, 0.0784314, 0.862745 );
table->SetTableValue( 14150.0, 0.239216, 0.862745, 0.862745 );
table->SetTableValue( 14151.0, 0.392157, 0.784314, 0.784314 );
table->SetTableValue( 14152.0, 0.0392157, 0.784314, 0.784314 );
table->SetTableValue( 14153.0, 0.866667, 0.862745, 0.0784314 );
table->SetTableValue( 14154.0, 0.552941, 0.0784314, 0.392157 );
table->SetTableValue( 14155.0, 0.239216, 0.862745, 0.392157 );
table->SetTableValue( 14156.0, 0.552941, 0.235294, 0.0784314 );
table->SetTableValue( 14157.0, 0.560784, 0.0784314, 0.862745 );
table->SetTableValue( 14158.0, 0.396078, 0.235294, 0.862745 );
table->SetTableValue( 14159.0, 0.0823529, 0.0784314, 0.54902 );
table->SetTableValue( 14160.0, 0.239216, 0.0784314, 0.705882 );
table->SetTableValue( 14161.0, 0.866667, 0.54902, 0.0784314 );
table->SetTableValue( 14162.0, 0.552941, 0.392157, 0.862745 );
table->SetTableValue( 14163.0, 0.866667, 0.392157, 0.0784314 );
table->SetTableValue( 14164.0, 0.709804, 0.784314, 0.0784314 );
table->SetTableValue( 14165.0, 0.396078, 0.0784314, 0.0784314 );
table->SetTableValue( 14166.0, 0.396078, 0.392157, 0.705882 );
table->SetTableValue( 14167.0, 0.709804, 0.862745, 0.0784314 );
table->SetTableValue( 14168.0, 0.0823529, 0.54902, 0.784314 );
table->SetTableValue( 14169.0, 0.0823529, 0.0784314, 0.941176 );
table->SetTableValue( 14170.0, 0.0823529, 0.0784314, 0.784314 );
table->SetTableValue( 14171.0, 0.0823529, 0.0784314, 0.235294 );
table->SetTableValue( 14172.0, 0.396078, 0.235294, 0.235294 );
table->SetTableValue( 14173.0, 0.0823529, 0.705882, 0.705882 );
table->SetTableValue( 14174.0, 0.87451, 0.862745, 0.235294 );
table->SetTableValue( 14175.0, 0.866667, 0.235294, 0.235294 );
mitk::LookupTable::Pointer lookupTable = mitk::LookupTable::New();
lookupTable->SetVtkLookupTable( table );
return lookupTable;
}
TransferFunction::Pointer FreeSurferParcellationTranslator::CreateTransferFunction()
{
mitk::TransferFunction::Pointer transferFunction = mitk::TransferFunction::New();
transferFunction->AddRGBPoint( 1.0, 0.27451, 0.509804, 0.705882 );
transferFunction->AddRGBPoint( 2.0, 0.960784, 0.960784, 0.960784 );
transferFunction->AddRGBPoint( 3.0, 0.803922, 0.243137, 0.305882 );
transferFunction->AddRGBPoint( 4.0, 0.470588, 0.0705882, 0.52549 );
transferFunction->AddRGBPoint( 5.0, 0.768627, 0.227451, 0.980392 );
transferFunction->AddRGBPoint( 6.0, 0, 0.580392, 0 );
transferFunction->AddRGBPoint( 7.0, 0.862745, 0.972549, 0.643137 );
transferFunction->AddRGBPoint( 8.0, 0.901961, 0.580392, 0.133333 );
transferFunction->AddRGBPoint( 9.0, 0, 0.462745, 0.054902 );
transferFunction->AddRGBPoint( 10.0, 0, 0.462745, 0.054902 );
transferFunction->AddRGBPoint( 11.0, 0.478431, 0.729412, 0.862745 );
transferFunction->AddRGBPoint( 12.0, 0.92549, 0.0509804, 0.690196 );
transferFunction->AddRGBPoint( 13.0, 0.0470588, 0.188235, 1 );
transferFunction->AddRGBPoint( 14.0, 0.8, 0.713725, 0.556863 );
transferFunction->AddRGBPoint( 15.0, 0.164706, 0.8, 0.643137 );
transferFunction->AddRGBPoint( 16.0, 0.466667, 0.623529, 0.690196 );
transferFunction->AddRGBPoint( 17.0, 0.862745, 0.847059, 0.0784314 );
transferFunction->AddRGBPoint( 18.0, 0.403922, 1, 1 );
transferFunction->AddRGBPoint( 19.0, 0.313725, 0.768627, 0.384314 );
transferFunction->AddRGBPoint( 20.0, 0.235294, 0.227451, 0.823529 );
transferFunction->AddRGBPoint( 21.0, 0.235294, 0.227451, 0.823529 );
transferFunction->AddRGBPoint( 22.0, 0.235294, 0.227451, 0.823529 );
transferFunction->AddRGBPoint( 23.0, 0.235294, 0.227451, 0.823529 );
transferFunction->AddRGBPoint( 24.0, 0.235294, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 25.0, 1, 0.647059, 0 );
transferFunction->AddRGBPoint( 26.0, 1, 0.647059, 0 );
transferFunction->AddRGBPoint( 27.0, 0, 1, 0.498039 );
transferFunction->AddRGBPoint( 28.0, 0.647059, 0.164706, 0.164706 );
transferFunction->AddRGBPoint( 29.0, 0.529412, 0.807843, 0.921569 );
transferFunction->AddRGBPoint( 30.0, 0.627451, 0.12549, 0.941176 );
transferFunction->AddRGBPoint( 31.0, 0, 0.784314, 0.784314 );
transferFunction->AddRGBPoint( 32.0, 0.392157, 0.196078, 0.392157 );
transferFunction->AddRGBPoint( 33.0, 0.529412, 0.196078, 0.290196 );
transferFunction->AddRGBPoint( 34.0, 0.478431, 0.529412, 0.196078 );
transferFunction->AddRGBPoint( 35.0, 0.2, 0.196078, 0.529412 );
transferFunction->AddRGBPoint( 36.0, 0.290196, 0.607843, 0.235294 );
transferFunction->AddRGBPoint( 37.0, 0.470588, 0.243137, 0.168627 );
transferFunction->AddRGBPoint( 38.0, 0.290196, 0.607843, 0.235294 );
transferFunction->AddRGBPoint( 39.0, 0.478431, 0.529412, 0.196078 );
transferFunction->AddRGBPoint( 40.0, 0.27451, 0.509804, 0.705882 );
transferFunction->AddRGBPoint( 41.0, 0, 0.882353, 0 );
transferFunction->AddRGBPoint( 42.0, 0.803922, 0.243137, 0.305882 );
transferFunction->AddRGBPoint( 43.0, 0.470588, 0.0705882, 0.52549 );
transferFunction->AddRGBPoint( 44.0, 0.768627, 0.227451, 0.980392 );
transferFunction->AddRGBPoint( 45.0, 0, 0.580392, 0 );
transferFunction->AddRGBPoint( 46.0, 0.862745, 0.972549, 0.643137 );
transferFunction->AddRGBPoint( 47.0, 0.901961, 0.580392, 0.133333 );
transferFunction->AddRGBPoint( 48.0, 0, 0.462745, 0.054902 );
transferFunction->AddRGBPoint( 49.0, 0, 0.462745, 0.054902 );
transferFunction->AddRGBPoint( 50.0, 0.478431, 0.729412, 0.862745 );
transferFunction->AddRGBPoint( 51.0, 0.92549, 0.0509804, 0.690196 );
transferFunction->AddRGBPoint( 52.0, 0.0509804, 0.188235, 1 );
transferFunction->AddRGBPoint( 53.0, 0.862745, 0.847059, 0.0784314 );
transferFunction->AddRGBPoint( 54.0, 0.403922, 1, 1 );
transferFunction->AddRGBPoint( 55.0, 0.313725, 0.768627, 0.384314 );
transferFunction->AddRGBPoint( 56.0, 0.235294, 0.227451, 0.823529 );
transferFunction->AddRGBPoint( 57.0, 1, 0.647059, 0 );
transferFunction->AddRGBPoint( 58.0, 1, 0.647059, 0 );
transferFunction->AddRGBPoint( 59.0, 0, 1, 0.498039 );
transferFunction->AddRGBPoint( 60.0, 0.647059, 0.164706, 0.164706 );
transferFunction->AddRGBPoint( 61.0, 0.529412, 0.807843, 0.921569 );
transferFunction->AddRGBPoint( 62.0, 0.627451, 0.12549, 0.941176 );
transferFunction->AddRGBPoint( 63.0, 0, 0.784314, 0.866667 );
transferFunction->AddRGBPoint( 64.0, 0.392157, 0.196078, 0.392157 );
transferFunction->AddRGBPoint( 65.0, 0.529412, 0.196078, 0.290196 );
transferFunction->AddRGBPoint( 66.0, 0.478431, 0.529412, 0.196078 );
transferFunction->AddRGBPoint( 67.0, 0.2, 0.196078, 0.529412 );
transferFunction->AddRGBPoint( 68.0, 0.290196, 0.607843, 0.235294 );
transferFunction->AddRGBPoint( 69.0, 0.470588, 0.243137, 0.168627 );
transferFunction->AddRGBPoint( 70.0, 0.290196, 0.607843, 0.235294 );
transferFunction->AddRGBPoint( 71.0, 0.478431, 0.529412, 0.196078 );
transferFunction->AddRGBPoint( 72.0, 0.470588, 0.745098, 0.588235 );
transferFunction->AddRGBPoint( 73.0, 0.478431, 0.529412, 0.196078 );
transferFunction->AddRGBPoint( 74.0, 0.478431, 0.529412, 0.196078 );
transferFunction->AddRGBPoint( 77.0, 0.784314, 0.27451, 1 );
transferFunction->AddRGBPoint( 78.0, 1, 0.580392, 0.0392157 );
transferFunction->AddRGBPoint( 79.0, 1, 0.580392, 0.0392157 );
transferFunction->AddRGBPoint( 80.0, 0.643137, 0.423529, 0.886275 );
transferFunction->AddRGBPoint( 81.0, 0.643137, 0.423529, 0.886275 );
transferFunction->AddRGBPoint( 82.0, 0.643137, 0.423529, 0.886275 );
transferFunction->AddRGBPoint( 83.0, 1, 0.854902, 0.72549 );
transferFunction->AddRGBPoint( 84.0, 1, 0.854902, 0.72549 );
transferFunction->AddRGBPoint( 85.0, 0.917647, 0.662745, 0.117647 );
transferFunction->AddRGBPoint( 192.0, 0.980392, 1, 0.196078 );
transferFunction->AddRGBPoint( 86.0, 0.784314, 0.470588, 1 );
transferFunction->AddRGBPoint( 87.0, 0.784314, 0.47451, 1 );
transferFunction->AddRGBPoint( 88.0, 0.784314, 0.478431, 1 );
transferFunction->AddRGBPoint( 96.0, 0.803922, 0.0392157, 0.490196 );
transferFunction->AddRGBPoint( 97.0, 0.803922, 0.0392157, 0.490196 );
transferFunction->AddRGBPoint( 98.0, 0.627451, 0.12549, 0.941176 );
transferFunction->AddRGBPoint( 100.0, 0.486275, 0.54902, 0.698039 );
transferFunction->AddRGBPoint( 101.0, 0.490196, 0.54902, 0.698039 );
transferFunction->AddRGBPoint( 102.0, 0.494118, 0.54902, 0.698039 );
transferFunction->AddRGBPoint( 103.0, 0.498039, 0.54902, 0.698039 );
transferFunction->AddRGBPoint( 104.0, 0.486275, 0.552941, 0.698039 );
transferFunction->AddRGBPoint( 105.0, 0.486275, 0.556863, 0.698039 );
transferFunction->AddRGBPoint( 106.0, 0.486275, 0.560784, 0.698039 );
transferFunction->AddRGBPoint( 107.0, 0.486275, 0.564706, 0.698039 );
transferFunction->AddRGBPoint( 108.0, 0.486275, 0.54902, 0.701961 );
transferFunction->AddRGBPoint( 109.0, 0.486275, 0.54902, 0.698039 );
transferFunction->AddRGBPoint( 110.0, 0.490196, 0.54902, 0.698039 );
transferFunction->AddRGBPoint( 111.0, 0.494118, 0.54902, 0.698039 );
transferFunction->AddRGBPoint( 112.0, 0.498039, 0.54902, 0.698039 );
transferFunction->AddRGBPoint( 113.0, 0.486275, 0.552941, 0.698039 );
transferFunction->AddRGBPoint( 114.0, 0.486275, 0.556863, 0.698039 );
transferFunction->AddRGBPoint( 115.0, 0.486275, 0.560784, 0.698039 );
transferFunction->AddRGBPoint( 116.0, 0.486275, 0.564706, 0.698039 );
transferFunction->AddRGBPoint( 117.0, 0.486275, 0.54902, 0.701961 );
transferFunction->AddRGBPoint( 118.0, 1, 0.0784314, 0.576471 );
transferFunction->AddRGBPoint( 119.0, 0.803922, 0.701961, 0.545098 );
transferFunction->AddRGBPoint( 120.0, 0.933333, 0.933333, 0.819608 );
transferFunction->AddRGBPoint( 121.0, 0.784314, 0.784314, 0.784314 );
transferFunction->AddRGBPoint( 122.0, 0.290196, 1, 0.290196 );
transferFunction->AddRGBPoint( 123.0, 0.933333, 0, 0 );
transferFunction->AddRGBPoint( 124.0, 0, 0, 0.545098 );
transferFunction->AddRGBPoint( 125.0, 0.678431, 1, 0.184314 );
transferFunction->AddRGBPoint( 126.0, 0.521569, 0.796078, 0.898039 );
transferFunction->AddRGBPoint( 127.0, 0.101961, 0.929412, 0.223529 );
transferFunction->AddRGBPoint( 128.0, 0.133333, 0.545098, 0.133333 );
transferFunction->AddRGBPoint( 129.0, 0.117647, 0.564706, 1 );
transferFunction->AddRGBPoint( 130.0, 0.576471, 0.0745098, 0.678431 );
transferFunction->AddRGBPoint( 131.0, 0.933333, 0.231373, 0.231373 );
transferFunction->AddRGBPoint( 132.0, 0.866667, 0.152941, 0.784314 );
transferFunction->AddRGBPoint( 133.0, 0.933333, 0.682353, 0.933333 );
transferFunction->AddRGBPoint( 134.0, 1, 0, 0 );
transferFunction->AddRGBPoint( 135.0, 0.282353, 0.239216, 0.545098 );
transferFunction->AddRGBPoint( 136.0, 0.0823529, 0.152941, 0.517647 );
transferFunction->AddRGBPoint( 137.0, 0.0823529, 0.152941, 0.517647 );
transferFunction->AddRGBPoint( 138.0, 0.254902, 0.529412, 0.0784314 );
transferFunction->AddRGBPoint( 139.0, 0.254902, 0.529412, 0.0784314 );
transferFunction->AddRGBPoint( 140.0, 0.52549, 0.0156863, 0.627451 );
transferFunction->AddRGBPoint( 142.0, 0.866667, 0.886275, 0.266667 );
transferFunction->AddRGBPoint( 143.0, 1, 1, 0.996078 );
transferFunction->AddRGBPoint( 144.0, 0.203922, 0.819608, 0.886275 );
transferFunction->AddRGBPoint( 145.0, 0.937255, 0.627451, 0.87451 );
transferFunction->AddRGBPoint( 146.0, 0.27451, 0.509804, 0.705882 );
transferFunction->AddRGBPoint( 147.0, 0.27451, 0.509804, 0.709804 );
transferFunction->AddRGBPoint( 148.0, 0.545098, 0.47451, 0.368627 );
transferFunction->AddRGBPoint( 149.0, 0.878431, 0.878431, 0.878431 );
transferFunction->AddRGBPoint( 150.0, 1, 0, 0 );
transferFunction->AddRGBPoint( 151.0, 0.803922, 0.803922, 0 );
transferFunction->AddRGBPoint( 152.0, 0.933333, 0.933333, 0.819608 );
transferFunction->AddRGBPoint( 153.0, 0.545098, 0.47451, 0.368627 );
transferFunction->AddRGBPoint( 154.0, 0.933333, 0.231373, 0.231373 );
transferFunction->AddRGBPoint( 155.0, 0.933333, 0.231373, 0.231373 );
transferFunction->AddRGBPoint( 156.0, 0.933333, 0.231373, 0.231373 );
transferFunction->AddRGBPoint( 157.0, 0.243137, 0.0392157, 0.803922 );
transferFunction->AddRGBPoint( 158.0, 0.243137, 0.0392157, 0.803922 );
transferFunction->AddRGBPoint( 159.0, 0, 0.462745, 0.054902 );
transferFunction->AddRGBPoint( 160.0, 0, 0.462745, 0.054902 );
transferFunction->AddRGBPoint( 161.0, 0.862745, 0.847059, 0.0823529 );
transferFunction->AddRGBPoint( 162.0, 0.862745, 0.847059, 0.0823529 );
transferFunction->AddRGBPoint( 163.0, 0.478431, 0.729412, 0.862745 );
transferFunction->AddRGBPoint( 164.0, 0.478431, 0.729412, 0.862745 );
transferFunction->AddRGBPoint( 165.0, 1, 0.647059, 0 );
transferFunction->AddRGBPoint( 166.0, 0.054902, 0.188235, 1 );
transferFunction->AddRGBPoint( 167.0, 0.65098, 0.164706, 0.164706 );
transferFunction->AddRGBPoint( 168.0, 0.47451, 0.0705882, 0.52549 );
transferFunction->AddRGBPoint( 169.0, 0.92549, 0.0509804, 0.498039 );
transferFunction->AddRGBPoint( 176.0, 0.92549, 0.0509804, 0.494118 );
transferFunction->AddRGBPoint( 170.0, 0.466667, 0.623529, 0.690196 );
transferFunction->AddRGBPoint( 171.0, 0.466667, 0, 0.690196 );
transferFunction->AddRGBPoint( 172.0, 0.466667, 0.392157, 0.690196 );
transferFunction->AddRGBPoint( 173.0, 0.466667, 0.784314, 0.690196 );
transferFunction->AddRGBPoint( 174.0, 0.466667, 0.623529, 0.392157 );
transferFunction->AddRGBPoint( 175.0, 0.466667, 0.623529, 0.784314 );
transferFunction->AddRGBPoint( 180.0, 0.286275, 0.239216, 0.545098 );
transferFunction->AddRGBPoint( 181.0, 0.286275, 0.243137, 0.545098 );
transferFunction->AddRGBPoint( 193.0, 0, 0.768627, 1 );
transferFunction->AddRGBPoint( 194.0, 1, 0.643137, 0.643137 );
transferFunction->AddRGBPoint( 195.0, 0.768627, 0.768627, 0 );
transferFunction->AddRGBPoint( 196.0, 0, 0.392157, 1 );
transferFunction->AddRGBPoint( 197.0, 0.501961, 0.768627, 0.643137 );
transferFunction->AddRGBPoint( 198.0, 0, 0.494118, 0.294118 );
transferFunction->AddRGBPoint( 199.0, 0.501961, 0.376471, 0.25098 );
transferFunction->AddRGBPoint( 200.0, 0, 0.196078, 0.501961 );
transferFunction->AddRGBPoint( 201.0, 1, 0.8, 0.6 );
transferFunction->AddRGBPoint( 202.0, 1, 0.501961, 0.501961 );
transferFunction->AddRGBPoint( 203.0, 1, 1, 0 );
transferFunction->AddRGBPoint( 204.0, 0.25098, 0, 0.25098 );
transferFunction->AddRGBPoint( 205.0, 0, 0, 1 );
transferFunction->AddRGBPoint( 206.0, 1, 0, 0 );
transferFunction->AddRGBPoint( 207.0, 0.501961, 0.501961, 1 );
transferFunction->AddRGBPoint( 208.0, 0, 0.501961, 0 );
transferFunction->AddRGBPoint( 209.0, 0.768627, 0.627451, 0.501961 );
transferFunction->AddRGBPoint( 210.0, 0.12549, 0.784314, 1 );
transferFunction->AddRGBPoint( 211.0, 0.501961, 1, 0.501961 );
transferFunction->AddRGBPoint( 212.0, 0.8, 0.6, 0.8 );
transferFunction->AddRGBPoint( 213.0, 0.47451, 0.0666667, 0.533333 );
transferFunction->AddRGBPoint( 214.0, 0.501961, 0, 0 );
transferFunction->AddRGBPoint( 215.0, 0.501961, 0.12549, 1 );
transferFunction->AddRGBPoint( 216.0, 1, 0.8, 0.4 );
transferFunction->AddRGBPoint( 217.0, 0.501961, 0.501961, 0.501961 );
transferFunction->AddRGBPoint( 218.0, 0.407843, 1, 1 );
transferFunction->AddRGBPoint( 219.0, 0, 0.886275, 0 );
transferFunction->AddRGBPoint( 220.0, 0.803922, 0.247059, 0.305882 );
transferFunction->AddRGBPoint( 221.0, 0.772549, 0.227451, 0.980392 );
transferFunction->AddRGBPoint( 222.0, 0.129412, 0.588235, 0.980392 );
transferFunction->AddRGBPoint( 223.0, 0.886275, 0, 0 );
transferFunction->AddRGBPoint( 224.0, 0.392157, 0.392157, 0.392157 );
transferFunction->AddRGBPoint( 225.0, 0.772549, 0.588235, 0.980392 );
transferFunction->AddRGBPoint( 226.0, 0.666667, 0.666667, 1 );
transferFunction->AddRGBPoint( 250.0, 1, 0, 0 );
transferFunction->AddRGBPoint( 251.0, 0, 0, 0.25098 );
transferFunction->AddRGBPoint( 252.0, 0, 0, 0.439216 );
transferFunction->AddRGBPoint( 253.0, 0, 0, 0.627451 );
transferFunction->AddRGBPoint( 254.0, 0, 0, 0.815686 );
transferFunction->AddRGBPoint( 255.0, 0, 0, 1 );
transferFunction->AddRGBPoint( 331.0, 1, 0, 0 );
transferFunction->AddRGBPoint( 332.0, 1, 0.313725, 0 );
transferFunction->AddRGBPoint( 333.0, 1, 0.627451, 0 );
transferFunction->AddRGBPoint( 334.0, 1, 1, 0 );
transferFunction->AddRGBPoint( 335.0, 0, 1, 0 );
transferFunction->AddRGBPoint( 336.0, 1, 0, 0.627451 );
transferFunction->AddRGBPoint( 337.0, 1, 0, 1 );
transferFunction->AddRGBPoint( 338.0, 1, 0.196078, 0.313725 );
transferFunction->AddRGBPoint( 339.0, 0.313725, 1, 0.196078 );
transferFunction->AddRGBPoint( 340.0, 0.627451, 1, 0.196078 );
transferFunction->AddRGBPoint( 341.0, 0.627451, 0.784314, 1 );
transferFunction->AddRGBPoint( 342.0, 0, 1, 0.627451 );
transferFunction->AddRGBPoint( 343.0, 0, 0, 1 );
transferFunction->AddRGBPoint( 344.0, 0.313725, 0.196078, 1 );
transferFunction->AddRGBPoint( 345.0, 0.627451, 0, 1 );
transferFunction->AddRGBPoint( 346.0, 1, 0.823529, 0 );
transferFunction->AddRGBPoint( 347.0, 0, 0.627451, 1 );
transferFunction->AddRGBPoint( 348.0, 1, 0.784314, 0.313725 );
transferFunction->AddRGBPoint( 349.0, 1, 0.784314, 0.627451 );
transferFunction->AddRGBPoint( 350.0, 1, 0.313725, 0.784314 );
transferFunction->AddRGBPoint( 351.0, 1, 0.627451, 0.784314 );
transferFunction->AddRGBPoint( 352.0, 0.117647, 1, 0.313725 );
transferFunction->AddRGBPoint( 353.0, 0.313725, 0.784314, 1 );
transferFunction->AddRGBPoint( 354.0, 0.313725, 1, 0.784314 );
transferFunction->AddRGBPoint( 355.0, 0.764706, 1, 0.784314 );
transferFunction->AddRGBPoint( 356.0, 0.470588, 0.784314, 0.0784314 );
transferFunction->AddRGBPoint( 357.0, 0.666667, 0.0392157, 0.784314 );
transferFunction->AddRGBPoint( 358.0, 0.0784314, 0.509804, 0.705882 );
transferFunction->AddRGBPoint( 359.0, 0.0784314, 0.705882, 0.509804 );
transferFunction->AddRGBPoint( 400.0, 0.807843, 0.243137, 0.305882 );
transferFunction->AddRGBPoint( 401.0, 0.47451, 0.0705882, 0.52549 );
transferFunction->AddRGBPoint( 402.0, 0.780392, 0.227451, 0.980392 );
transferFunction->AddRGBPoint( 403.0, 0.00392157, 0.580392, 0 );
transferFunction->AddRGBPoint( 404.0, 0.866667, 0.972549, 0.643137 );
transferFunction->AddRGBPoint( 405.0, 0.905882, 0.580392, 0.133333 );
transferFunction->AddRGBPoint( 406.0, 0.00392157, 0.462745, 0.054902 );
transferFunction->AddRGBPoint( 407.0, 0.470588, 0.462745, 0.054902 );
transferFunction->AddRGBPoint( 408.0, 0.482353, 0.729412, 0.866667 );
transferFunction->AddRGBPoint( 409.0, 0.933333, 0.0509804, 0.694118 );
transferFunction->AddRGBPoint( 410.0, 0.482353, 0.729412, 0.862745 );
transferFunction->AddRGBPoint( 411.0, 0.541176, 0.0509804, 0.807843 );
transferFunction->AddRGBPoint( 412.0, 0.933333, 0.509804, 0.690196 );
transferFunction->AddRGBPoint( 413.0, 0.854902, 0.901961, 0.298039 );
transferFunction->AddRGBPoint( 414.0, 0.14902, 0.835294, 0.690196 );
transferFunction->AddRGBPoint( 415.0, 0.00392157, 0.882353, 0.690196 );
transferFunction->AddRGBPoint( 416.0, 0.00392157, 0.882353, 0.690196 );
transferFunction->AddRGBPoint( 417.0, 0.784314, 0.00784314, 0.392157 );
transferFunction->AddRGBPoint( 418.0, 0.784314, 0.00784314, 0.392157 );
transferFunction->AddRGBPoint( 419.0, 0.0196078, 0.784314, 0.352941 );
transferFunction->AddRGBPoint( 420.0, 0.0196078, 0.784314, 0.352941 );
transferFunction->AddRGBPoint( 421.0, 0.392157, 0.0196078, 0.784314 );
transferFunction->AddRGBPoint( 422.0, 0.0980392, 1, 0.392157 );
transferFunction->AddRGBPoint( 423.0, 0.0980392, 1, 0.392157 );
transferFunction->AddRGBPoint( 424.0, 0.901961, 0.027451, 0.392157 );
transferFunction->AddRGBPoint( 425.0, 0.901961, 0.027451, 0.392157 );
transferFunction->AddRGBPoint( 426.0, 0.392157, 0.0196078, 0.784314 );
transferFunction->AddRGBPoint( 427.0, 0.588235, 0.0392157, 0.784314 );
transferFunction->AddRGBPoint( 428.0, 0.588235, 0.0392157, 0.784314 );
transferFunction->AddRGBPoint( 429.0, 0.686275, 0.0392157, 0.690196 );
transferFunction->AddRGBPoint( 430.0, 0.686275, 0.0392157, 0.690196 );
transferFunction->AddRGBPoint( 431.0, 0.0392157, 0.392157, 1 );
transferFunction->AddRGBPoint( 432.0, 0.0392157, 0.392157, 1 );
transferFunction->AddRGBPoint( 433.0, 0.588235, 0.176471, 0.27451 );
transferFunction->AddRGBPoint( 434.0, 0.588235, 0.176471, 0.27451 );
transferFunction->AddRGBPoint( 435.0, 0.176471, 0.784314, 0.0588235 );
transferFunction->AddRGBPoint( 436.0, 0.176471, 0.784314, 0.0588235 );
transferFunction->AddRGBPoint( 437.0, 0.890196, 0.176471, 0.392157 );
transferFunction->AddRGBPoint( 438.0, 0.890196, 0.176471, 0.392157 );
transferFunction->AddRGBPoint( 439.0, 0.890196, 0.176471, 0.392157 );
transferFunction->AddRGBPoint( 498.0, 0.560784, 0.737255, 0.560784 );
transferFunction->AddRGBPoint( 499.0, 1, 0.972549, 0.862745 );
transferFunction->AddRGBPoint( 500.0, 0.0666667, 0.333333, 0.533333 );
transferFunction->AddRGBPoint( 501.0, 0.466667, 0.733333, 0.4 );
transferFunction->AddRGBPoint( 502.0, 0.8, 0.266667, 0.133333 );
transferFunction->AddRGBPoint( 503.0, 0.8, 0, 1 );
transferFunction->AddRGBPoint( 504.0, 0.866667, 0.733333, 0.0666667 );
transferFunction->AddRGBPoint( 505.0, 0.6, 0.866667, 0.933333 );
transferFunction->AddRGBPoint( 506.0, 0.2, 0.0666667, 0.0666667 );
transferFunction->AddRGBPoint( 507.0, 0, 0.466667, 0.333333 );
transferFunction->AddRGBPoint( 508.0, 0.0784314, 0.392157, 0.784314 );
transferFunction->AddRGBPoint( 550.0, 0.0666667, 0.333333, 0.537255 );
transferFunction->AddRGBPoint( 551.0, 0.466667, 0.733333, 0.403922 );
transferFunction->AddRGBPoint( 552.0, 0.8, 0.266667, 0.137255 );
transferFunction->AddRGBPoint( 553.0, 0.8, 0, 0.996078 );
transferFunction->AddRGBPoint( 554.0, 0.866667, 0.733333, 0.0627451 );
transferFunction->AddRGBPoint( 555.0, 0.6, 0.866667, 0.937255 );
transferFunction->AddRGBPoint( 556.0, 0.2, 0.0666667, 0.0705882 );
transferFunction->AddRGBPoint( 557.0, 0, 0.466667, 0.337255 );
transferFunction->AddRGBPoint( 558.0, 0.0784314, 0.392157, 0.788235 );
transferFunction->AddRGBPoint( 600.0, 0.996078, 0.996078, 0.996078 );
transferFunction->AddRGBPoint( 601.0, 0.27451, 0.509804, 0.705882 );
transferFunction->AddRGBPoint( 602.0, 0.960784, 0.960784, 0.960784 );
transferFunction->AddRGBPoint( 603.0, 0.803922, 0.243137, 0.305882 );
transferFunction->AddRGBPoint( 604.0, 0.470588, 0.0705882, 0.52549 );
transferFunction->AddRGBPoint( 605.0, 0.768627, 0.227451, 0.980392 );
transferFunction->AddRGBPoint( 606.0, 0, 0.580392, 0 );
transferFunction->AddRGBPoint( 607.0, 0.862745, 0.972549, 0.643137 );
transferFunction->AddRGBPoint( 608.0, 0.901961, 0.580392, 0.133333 );
transferFunction->AddRGBPoint( 609.0, 0, 0.462745, 0.054902 );
transferFunction->AddRGBPoint( 610.0, 0, 0.462745, 0.054902 );
transferFunction->AddRGBPoint( 611.0, 0.478431, 0.729412, 0.862745 );
transferFunction->AddRGBPoint( 612.0, 0.92549, 0.0509804, 0.690196 );
transferFunction->AddRGBPoint( 613.0, 0.0470588, 0.188235, 1 );
transferFunction->AddRGBPoint( 614.0, 0.8, 0.713725, 0.556863 );
transferFunction->AddRGBPoint( 615.0, 0.164706, 0.8, 0.643137 );
transferFunction->AddRGBPoint( 616.0, 0.466667, 0.623529, 0.690196 );
transferFunction->AddRGBPoint( 617.0, 0.862745, 0.847059, 0.0784314 );
transferFunction->AddRGBPoint( 618.0, 0.403922, 1, 1 );
transferFunction->AddRGBPoint( 619.0, 0.313725, 0.768627, 0.384314 );
transferFunction->AddRGBPoint( 620.0, 0.235294, 0.227451, 0.823529 );
transferFunction->AddRGBPoint( 621.0, 0.235294, 0.227451, 0.823529 );
transferFunction->AddRGBPoint( 622.0, 0.235294, 0.227451, 0.823529 );
transferFunction->AddRGBPoint( 623.0, 0.235294, 0.227451, 0.823529 );
transferFunction->AddRGBPoint( 624.0, 0.235294, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 625.0, 1, 0.647059, 0 );
transferFunction->AddRGBPoint( 626.0, 1, 0.647059, 0 );
transferFunction->AddRGBPoint( 627.0, 0, 1, 0.498039 );
transferFunction->AddRGBPoint( 628.0, 0.647059, 0.164706, 0.164706 );
transferFunction->AddRGBPoint( 640.0, 0.8, 0, 0 );
transferFunction->AddRGBPoint( 641.0, 1, 0, 0 );
transferFunction->AddRGBPoint( 642.0, 0, 0, 1 );
transferFunction->AddRGBPoint( 643.0, 0.117647, 0.564706, 1 );
transferFunction->AddRGBPoint( 644.0, 0.392157, 0.831373, 0.929412 );
transferFunction->AddRGBPoint( 645.0, 0.854902, 0.647059, 0.12549 );
transferFunction->AddRGBPoint( 646.0, 1, 0.843137, 0 );
transferFunction->AddRGBPoint( 647.0, 1, 1, 0.65098 );
transferFunction->AddRGBPoint( 648.0, 0.6, 0, 0.8 );
transferFunction->AddRGBPoint( 649.0, 0.6, 0.552941, 0.819608 );
transferFunction->AddRGBPoint( 650.0, 0.8, 0.8, 1 );
transferFunction->AddRGBPoint( 651.0, 0.121569, 0.831373, 0.760784 );
transferFunction->AddRGBPoint( 652.0, 0.0117647, 1, 0.929412 );
transferFunction->AddRGBPoint( 653.0, 0.8, 1, 1 );
transferFunction->AddRGBPoint( 654.0, 0.337255, 0.290196, 0.576471 );
transferFunction->AddRGBPoint( 655.0, 0.447059, 0.447059, 0.745098 );
transferFunction->AddRGBPoint( 656.0, 0.721569, 0.698039, 1 );
transferFunction->AddRGBPoint( 657.0, 0.494118, 0.541176, 0.145098 );
transferFunction->AddRGBPoint( 658.0, 0.741176, 0.772549, 0.458824 );
transferFunction->AddRGBPoint( 659.0, 0.941176, 0.901961, 0.54902 );
transferFunction->AddRGBPoint( 660.0, 0.8, 0, 0 );
transferFunction->AddRGBPoint( 661.0, 1, 0, 0 );
transferFunction->AddRGBPoint( 662.0, 0, 0, 1 );
transferFunction->AddRGBPoint( 663.0, 0.117647, 0.564706, 1 );
transferFunction->AddRGBPoint( 664.0, 0.392157, 0.831373, 0.929412 );
transferFunction->AddRGBPoint( 665.0, 0.854902, 0.647059, 0.12549 );
transferFunction->AddRGBPoint( 666.0, 1, 0.843137, 0 );
transferFunction->AddRGBPoint( 667.0, 1, 1, 0.65098 );
transferFunction->AddRGBPoint( 668.0, 0.6, 0, 0.8 );
transferFunction->AddRGBPoint( 669.0, 0.6, 0.552941, 0.819608 );
transferFunction->AddRGBPoint( 670.0, 0.8, 0.8, 1 );
transferFunction->AddRGBPoint( 671.0, 0.121569, 0.831373, 0.760784 );
transferFunction->AddRGBPoint( 672.0, 0.0117647, 1, 0.929412 );
transferFunction->AddRGBPoint( 673.0, 0.8, 1, 1 );
transferFunction->AddRGBPoint( 674.0, 0.337255, 0.290196, 0.576471 );
transferFunction->AddRGBPoint( 675.0, 0.447059, 0.447059, 0.745098 );
transferFunction->AddRGBPoint( 676.0, 0.721569, 0.698039, 1 );
transferFunction->AddRGBPoint( 677.0, 0.494118, 0.541176, 0.145098 );
transferFunction->AddRGBPoint( 678.0, 0.741176, 0.772549, 0.458824 );
transferFunction->AddRGBPoint( 679.0, 0.941176, 0.901961, 0.54902 );
transferFunction->AddRGBPoint( 701.0, 0.470588, 0.0705882, 0.52549 );
transferFunction->AddRGBPoint( 702.0, 0.803922, 0.243137, 0.305882 );
transferFunction->AddRGBPoint( 703.0, 0, 0.882353, 0 );
transferFunction->AddRGBPoint( 999.0, 1, 0.392157, 0.392157 );
transferFunction->AddRGBPoint( 1000.0, 0.0980392, 0.0196078, 0.0980392 );
transferFunction->AddRGBPoint( 1001.0, 0.0980392, 0.392157, 0.156863 );
transferFunction->AddRGBPoint( 1002.0, 0.490196, 0.392157, 0.627451 );
transferFunction->AddRGBPoint( 1003.0, 0.392157, 0.0980392, 0 );
transferFunction->AddRGBPoint( 1004.0, 0.470588, 0.27451, 0.196078 );
transferFunction->AddRGBPoint( 1005.0, 0.862745, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 1006.0, 0.862745, 0.0784314, 0.0392157 );
transferFunction->AddRGBPoint( 1007.0, 0.705882, 0.862745, 0.54902 );
transferFunction->AddRGBPoint( 1008.0, 0.862745, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 1009.0, 0.705882, 0.156863, 0.470588 );
transferFunction->AddRGBPoint( 1010.0, 0.54902, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 1011.0, 0.0784314, 0.117647, 0.54902 );
transferFunction->AddRGBPoint( 1012.0, 0.137255, 0.294118, 0.196078 );
transferFunction->AddRGBPoint( 1013.0, 0.882353, 0.54902, 0.54902 );
transferFunction->AddRGBPoint( 1014.0, 0.784314, 0.137255, 0.294118 );
transferFunction->AddRGBPoint( 1015.0, 0.627451, 0.392157, 0.196078 );
transferFunction->AddRGBPoint( 1016.0, 0.0784314, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 1017.0, 0.235294, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 1018.0, 0.862745, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 1019.0, 0.0784314, 0.392157, 0.196078 );
transferFunction->AddRGBPoint( 1020.0, 0.862745, 0.235294, 0.0784314 );
transferFunction->AddRGBPoint( 1021.0, 0.470588, 0.392157, 0.235294 );
transferFunction->AddRGBPoint( 1022.0, 0.862745, 0.0784314, 0.0784314 );
transferFunction->AddRGBPoint( 1023.0, 0.862745, 0.705882, 0.862745 );
transferFunction->AddRGBPoint( 1024.0, 0.235294, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 1025.0, 0.627451, 0.54902, 0.705882 );
transferFunction->AddRGBPoint( 1026.0, 0.313725, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 1027.0, 0.294118, 0.196078, 0.490196 );
transferFunction->AddRGBPoint( 1028.0, 0.0784314, 0.862745, 0.627451 );
transferFunction->AddRGBPoint( 1029.0, 0.0784314, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 1030.0, 0.54902, 0.862745, 0.862745 );
transferFunction->AddRGBPoint( 1031.0, 0.313725, 0.627451, 0.0784314 );
transferFunction->AddRGBPoint( 1032.0, 0.392157, 0, 0.392157 );
transferFunction->AddRGBPoint( 1033.0, 0.27451, 0.27451, 0.27451 );
transferFunction->AddRGBPoint( 1034.0, 0.588235, 0.588235, 0.784314 );
transferFunction->AddRGBPoint( 1035.0, 1, 0.752941, 0.12549 );
transferFunction->AddRGBPoint( 2000.0, 0.0980392, 0.0196078, 0.0980392 );
transferFunction->AddRGBPoint( 2001.0, 0.0980392, 0.392157, 0.156863 );
transferFunction->AddRGBPoint( 2002.0, 0.490196, 0.392157, 0.627451 );
transferFunction->AddRGBPoint( 2003.0, 0.392157, 0.0980392, 0 );
transferFunction->AddRGBPoint( 2004.0, 0.470588, 0.27451, 0.196078 );
transferFunction->AddRGBPoint( 2005.0, 0.862745, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 2006.0, 0.862745, 0.0784314, 0.0392157 );
transferFunction->AddRGBPoint( 2007.0, 0.705882, 0.862745, 0.54902 );
transferFunction->AddRGBPoint( 2008.0, 0.862745, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 2009.0, 0.705882, 0.156863, 0.470588 );
transferFunction->AddRGBPoint( 2010.0, 0.54902, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 2011.0, 0.0784314, 0.117647, 0.54902 );
transferFunction->AddRGBPoint( 2012.0, 0.137255, 0.294118, 0.196078 );
transferFunction->AddRGBPoint( 2013.0, 0.882353, 0.54902, 0.54902 );
transferFunction->AddRGBPoint( 2014.0, 0.784314, 0.137255, 0.294118 );
transferFunction->AddRGBPoint( 2015.0, 0.627451, 0.392157, 0.196078 );
transferFunction->AddRGBPoint( 2016.0, 0.0784314, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 2017.0, 0.235294, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 2018.0, 0.862745, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 2019.0, 0.0784314, 0.392157, 0.196078 );
transferFunction->AddRGBPoint( 2020.0, 0.862745, 0.235294, 0.0784314 );
transferFunction->AddRGBPoint( 2021.0, 0.470588, 0.392157, 0.235294 );
transferFunction->AddRGBPoint( 2022.0, 0.862745, 0.0784314, 0.0784314 );
transferFunction->AddRGBPoint( 2023.0, 0.862745, 0.705882, 0.862745 );
transferFunction->AddRGBPoint( 2024.0, 0.235294, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 2025.0, 0.627451, 0.54902, 0.705882 );
transferFunction->AddRGBPoint( 2026.0, 0.313725, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 2027.0, 0.294118, 0.196078, 0.490196 );
transferFunction->AddRGBPoint( 2028.0, 0.0784314, 0.862745, 0.627451 );
transferFunction->AddRGBPoint( 2029.0, 0.0784314, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 2030.0, 0.54902, 0.862745, 0.862745 );
transferFunction->AddRGBPoint( 2031.0, 0.313725, 0.627451, 0.0784314 );
transferFunction->AddRGBPoint( 2032.0, 0.392157, 0, 0.392157 );
transferFunction->AddRGBPoint( 2033.0, 0.27451, 0.27451, 0.27451 );
transferFunction->AddRGBPoint( 2034.0, 0.588235, 0.588235, 0.784314 );
transferFunction->AddRGBPoint( 2035.0, 1, 0.752941, 0.12549 );
transferFunction->AddRGBPoint( 3000.0, 0.901961, 0.980392, 0.901961 );
transferFunction->AddRGBPoint( 3001.0, 0.901961, 0.607843, 0.843137 );
transferFunction->AddRGBPoint( 3002.0, 0.509804, 0.607843, 0.372549 );
transferFunction->AddRGBPoint( 3003.0, 0.607843, 0.901961, 1 );
transferFunction->AddRGBPoint( 3004.0, 0.529412, 0.72549, 0.803922 );
transferFunction->AddRGBPoint( 3005.0, 0.137255, 0.921569, 0.607843 );
transferFunction->AddRGBPoint( 3006.0, 0.137255, 0.921569, 0.960784 );
transferFunction->AddRGBPoint( 3007.0, 0.294118, 0.137255, 0.45098 );
transferFunction->AddRGBPoint( 3008.0, 0.137255, 0.764706, 0.137255 );
transferFunction->AddRGBPoint( 3009.0, 0.294118, 0.843137, 0.529412 );
transferFunction->AddRGBPoint( 3010.0, 0.45098, 0.921569, 0.45098 );
transferFunction->AddRGBPoint( 3011.0, 0.921569, 0.882353, 0.45098 );
transferFunction->AddRGBPoint( 3012.0, 0.862745, 0.705882, 0.803922 );
transferFunction->AddRGBPoint( 3013.0, 0.117647, 0.45098, 0.45098 );
transferFunction->AddRGBPoint( 3014.0, 0.215686, 0.862745, 0.705882 );
transferFunction->AddRGBPoint( 3015.0, 0.372549, 0.607843, 0.803922 );
transferFunction->AddRGBPoint( 3016.0, 0.921569, 0.137255, 0.764706 );
transferFunction->AddRGBPoint( 3017.0, 0.764706, 0.137255, 0.764706 );
transferFunction->AddRGBPoint( 3018.0, 0.137255, 0.294118, 0.45098 );
transferFunction->AddRGBPoint( 3019.0, 0.921569, 0.607843, 0.803922 );
transferFunction->AddRGBPoint( 3020.0, 0.137255, 0.764706, 0.921569 );
transferFunction->AddRGBPoint( 3021.0, 0.529412, 0.607843, 0.764706 );
transferFunction->AddRGBPoint( 3022.0, 0.137255, 0.921569, 0.921569 );
transferFunction->AddRGBPoint( 3023.0, 0.137255, 0.294118, 0.137255 );
transferFunction->AddRGBPoint( 3024.0, 0.764706, 0.921569, 0.137255 );
transferFunction->AddRGBPoint( 3025.0, 0.372549, 0.45098, 0.294118 );
transferFunction->AddRGBPoint( 3026.0, 0.686275, 0.921569, 0.45098 );
transferFunction->AddRGBPoint( 3027.0, 0.705882, 0.803922, 0.509804 );
transferFunction->AddRGBPoint( 3028.0, 0.921569, 0.137255, 0.372549 );
transferFunction->AddRGBPoint( 3029.0, 0.921569, 0.294118, 0.45098 );
transferFunction->AddRGBPoint( 3030.0, 0.45098, 0.137255, 0.137255 );
transferFunction->AddRGBPoint( 3031.0, 0.686275, 0.372549, 0.921569 );
transferFunction->AddRGBPoint( 3032.0, 0.607843, 1, 0.607843 );
transferFunction->AddRGBPoint( 3033.0, 0.72549, 0.72549, 0.72549 );
transferFunction->AddRGBPoint( 3034.0, 0.411765, 0.411765, 0.215686 );
transferFunction->AddRGBPoint( 3035.0, 0.996078, 0.74902, 0.121569 );
transferFunction->AddRGBPoint( 4000.0, 0.901961, 0.980392, 0.901961 );
transferFunction->AddRGBPoint( 4001.0, 0.901961, 0.607843, 0.843137 );
transferFunction->AddRGBPoint( 4002.0, 0.509804, 0.607843, 0.372549 );
transferFunction->AddRGBPoint( 4003.0, 0.607843, 0.901961, 1 );
transferFunction->AddRGBPoint( 4004.0, 0.529412, 0.72549, 0.803922 );
transferFunction->AddRGBPoint( 4005.0, 0.137255, 0.921569, 0.607843 );
transferFunction->AddRGBPoint( 4006.0, 0.137255, 0.921569, 0.960784 );
transferFunction->AddRGBPoint( 4007.0, 0.294118, 0.137255, 0.45098 );
transferFunction->AddRGBPoint( 4008.0, 0.137255, 0.764706, 0.137255 );
transferFunction->AddRGBPoint( 4009.0, 0.294118, 0.843137, 0.529412 );
transferFunction->AddRGBPoint( 4010.0, 0.45098, 0.921569, 0.45098 );
transferFunction->AddRGBPoint( 4011.0, 0.921569, 0.882353, 0.45098 );
transferFunction->AddRGBPoint( 4012.0, 0.862745, 0.705882, 0.803922 );
transferFunction->AddRGBPoint( 4013.0, 0.117647, 0.45098, 0.45098 );
transferFunction->AddRGBPoint( 4014.0, 0.215686, 0.862745, 0.705882 );
transferFunction->AddRGBPoint( 4015.0, 0.372549, 0.607843, 0.803922 );
transferFunction->AddRGBPoint( 4016.0, 0.921569, 0.137255, 0.764706 );
transferFunction->AddRGBPoint( 4017.0, 0.764706, 0.137255, 0.764706 );
transferFunction->AddRGBPoint( 4018.0, 0.137255, 0.294118, 0.45098 );
transferFunction->AddRGBPoint( 4019.0, 0.921569, 0.607843, 0.803922 );
transferFunction->AddRGBPoint( 4020.0, 0.137255, 0.764706, 0.921569 );
transferFunction->AddRGBPoint( 4021.0, 0.529412, 0.607843, 0.764706 );
transferFunction->AddRGBPoint( 4022.0, 0.137255, 0.921569, 0.921569 );
transferFunction->AddRGBPoint( 4023.0, 0.137255, 0.294118, 0.137255 );
transferFunction->AddRGBPoint( 4024.0, 0.764706, 0.921569, 0.137255 );
transferFunction->AddRGBPoint( 4025.0, 0.372549, 0.45098, 0.294118 );
transferFunction->AddRGBPoint( 4026.0, 0.686275, 0.921569, 0.45098 );
transferFunction->AddRGBPoint( 4027.0, 0.705882, 0.803922, 0.509804 );
transferFunction->AddRGBPoint( 4028.0, 0.921569, 0.137255, 0.372549 );
transferFunction->AddRGBPoint( 4029.0, 0.921569, 0.294118, 0.45098 );
transferFunction->AddRGBPoint( 4030.0, 0.45098, 0.137255, 0.137255 );
transferFunction->AddRGBPoint( 4031.0, 0.686275, 0.372549, 0.921569 );
transferFunction->AddRGBPoint( 4032.0, 0.607843, 1, 0.607843 );
transferFunction->AddRGBPoint( 4033.0, 0.72549, 0.72549, 0.72549 );
transferFunction->AddRGBPoint( 4034.0, 0.411765, 0.411765, 0.215686 );
transferFunction->AddRGBPoint( 4035.0, 0.996078, 0.74902, 0.121569 );
transferFunction->AddRGBPoint( 1101.0, 0.196078, 0.196078, 0.196078 );
transferFunction->AddRGBPoint( 1102.0, 0.705882, 0.0784314, 0.117647 );
transferFunction->AddRGBPoint( 1103.0, 0.235294, 0.0980392, 0.0980392 );
transferFunction->AddRGBPoint( 1104.0, 0.0980392, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 1200.0, 0.0980392, 0.235294, 0.239216 );
transferFunction->AddRGBPoint( 1201.0, 0.0980392, 0.352941, 0.235294 );
transferFunction->AddRGBPoint( 1202.0, 0.0980392, 0.470588, 0.235294 );
transferFunction->AddRGBPoint( 1205.0, 0.0980392, 0.588235, 0.235294 );
transferFunction->AddRGBPoint( 1206.0, 0.0980392, 0.705882, 0.235294 );
transferFunction->AddRGBPoint( 1207.0, 0.0980392, 0.823529, 0.235294 );
transferFunction->AddRGBPoint( 1210.0, 0.0980392, 0.588235, 0.352941 );
transferFunction->AddRGBPoint( 1211.0, 0.0980392, 0.705882, 0.352941 );
transferFunction->AddRGBPoint( 1212.0, 0.0980392, 0.823529, 0.352941 );
transferFunction->AddRGBPoint( 1105.0, 0.705882, 0.0784314, 0.0784314 );
transferFunction->AddRGBPoint( 1106.0, 0.862745, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 1107.0, 0.54902, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 1108.0, 0.705882, 0.862745, 0.54902 );
transferFunction->AddRGBPoint( 1109.0, 0.54902, 0.392157, 0.705882 );
transferFunction->AddRGBPoint( 1110.0, 0.705882, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 1111.0, 0.54902, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 1112.0, 0.0823529, 0.0392157, 0.0392157 );
transferFunction->AddRGBPoint( 1113.0, 0.882353, 0.54902, 0.54902 );
transferFunction->AddRGBPoint( 1114.0, 0.0901961, 0.235294, 0.705882 );
transferFunction->AddRGBPoint( 1115.0, 0.705882, 0.235294, 0.705882 );
transferFunction->AddRGBPoint( 1116.0, 0.0784314, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 1117.0, 0.235294, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 1118.0, 0.862745, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 1119.0, 0.254902, 0.392157, 0.0784314 );
transferFunction->AddRGBPoint( 1120.0, 0.862745, 0.235294, 0.0784314 );
transferFunction->AddRGBPoint( 1121.0, 0.235294, 0.392157, 0.235294 );
transferFunction->AddRGBPoint( 1122.0, 0.0784314, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 1123.0, 0.392157, 0.392157, 0.235294 );
transferFunction->AddRGBPoint( 1124.0, 0.862745, 0.705882, 0.862745 );
transferFunction->AddRGBPoint( 1125.0, 0.0784314, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 1126.0, 0.235294, 0.54902, 0.705882 );
transferFunction->AddRGBPoint( 1127.0, 0.0980392, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 1128.0, 0.0784314, 0.235294, 0.392157 );
transferFunction->AddRGBPoint( 1129.0, 0.235294, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 1130.0, 0.235294, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 1131.0, 0.862745, 0.862745, 0.392157 );
transferFunction->AddRGBPoint( 1132.0, 0.705882, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 1133.0, 0.235294, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 1134.0, 0.862745, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 1135.0, 0.254902, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 1136.0, 0.0980392, 0.54902, 0.0784314 );
transferFunction->AddRGBPoint( 1137.0, 0.0509804, 0, 0.980392 );
transferFunction->AddRGBPoint( 1138.0, 0.239216, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 1139.0, 0.239216, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 1140.0, 0.239216, 0.235294, 0.392157 );
transferFunction->AddRGBPoint( 1141.0, 0.0980392, 0.0980392, 0.0980392 );
transferFunction->AddRGBPoint( 1142.0, 0.54902, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 1143.0, 0.862745, 0.705882, 0.0784314 );
transferFunction->AddRGBPoint( 1144.0, 0.247059, 0.705882, 0.705882 );
transferFunction->AddRGBPoint( 1145.0, 0.866667, 0.0784314, 0.0392157 );
transferFunction->AddRGBPoint( 1146.0, 0.0823529, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 1147.0, 0.717647, 0.392157, 0.0784314 );
transferFunction->AddRGBPoint( 1148.0, 0.866667, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 1149.0, 0.866667, 0.235294, 0.54902 );
transferFunction->AddRGBPoint( 1150.0, 0.866667, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 1151.0, 0.239216, 0.862745, 0.862745 );
transferFunction->AddRGBPoint( 1152.0, 0.392157, 0.784314, 0.784314 );
transferFunction->AddRGBPoint( 1153.0, 0.0392157, 0.784314, 0.784314 );
transferFunction->AddRGBPoint( 1154.0, 0.866667, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 1155.0, 0.552941, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 1156.0, 0.239216, 0.862745, 0.392157 );
transferFunction->AddRGBPoint( 1157.0, 0.0823529, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 1158.0, 0.552941, 0.235294, 0.0784314 );
transferFunction->AddRGBPoint( 1159.0, 0.560784, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 1160.0, 0.239216, 0.0784314, 0.705882 );
transferFunction->AddRGBPoint( 1161.0, 0.396078, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 1162.0, 0.0823529, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 1163.0, 0.866667, 0.54902, 0.0784314 );
transferFunction->AddRGBPoint( 1164.0, 0.552941, 0.392157, 0.862745 );
transferFunction->AddRGBPoint( 1165.0, 0.396078, 0.0784314, 0.0784314 );
transferFunction->AddRGBPoint( 1166.0, 0.866667, 0.392157, 0.0784314 );
transferFunction->AddRGBPoint( 1167.0, 0.709804, 0.784314, 0.0784314 );
transferFunction->AddRGBPoint( 1168.0, 0.0823529, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 1169.0, 0.396078, 0.392157, 0.705882 );
transferFunction->AddRGBPoint( 1170.0, 0.709804, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 1171.0, 0.0823529, 0.54902, 0.784314 );
transferFunction->AddRGBPoint( 1172.0, 0.0823529, 0.0784314, 0.941176 );
transferFunction->AddRGBPoint( 1173.0, 0.0823529, 0.0784314, 0.784314 );
transferFunction->AddRGBPoint( 1174.0, 0.239216, 0.705882, 0.235294 );
transferFunction->AddRGBPoint( 1175.0, 0.239216, 0.705882, 0.980392 );
transferFunction->AddRGBPoint( 1176.0, 0.0823529, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 1177.0, 0.396078, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 1178.0, 0.0823529, 0.862745, 0.862745 );
transferFunction->AddRGBPoint( 1179.0, 0.0823529, 0.705882, 0.705882 );
transferFunction->AddRGBPoint( 1180.0, 0.87451, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 1181.0, 0.866667, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 2101.0, 0.196078, 0.196078, 0.196078 );
transferFunction->AddRGBPoint( 2102.0, 0.705882, 0.0784314, 0.117647 );
transferFunction->AddRGBPoint( 2103.0, 0.235294, 0.0980392, 0.0980392 );
transferFunction->AddRGBPoint( 2104.0, 0.0980392, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 2105.0, 0.705882, 0.0784314, 0.0784314 );
transferFunction->AddRGBPoint( 2106.0, 0.862745, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 2107.0, 0.54902, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 2108.0, 0.705882, 0.862745, 0.54902 );
transferFunction->AddRGBPoint( 2109.0, 0.54902, 0.392157, 0.705882 );
transferFunction->AddRGBPoint( 2110.0, 0.705882, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 2111.0, 0.54902, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 2112.0, 0.0823529, 0.0392157, 0.0392157 );
transferFunction->AddRGBPoint( 2113.0, 0.882353, 0.54902, 0.54902 );
transferFunction->AddRGBPoint( 2114.0, 0.0901961, 0.235294, 0.705882 );
transferFunction->AddRGBPoint( 2115.0, 0.705882, 0.235294, 0.705882 );
transferFunction->AddRGBPoint( 2116.0, 0.0784314, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 2117.0, 0.235294, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 2118.0, 0.862745, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 2119.0, 0.254902, 0.392157, 0.0784314 );
transferFunction->AddRGBPoint( 2120.0, 0.862745, 0.235294, 0.0784314 );
transferFunction->AddRGBPoint( 2121.0, 0.235294, 0.392157, 0.235294 );
transferFunction->AddRGBPoint( 2122.0, 0.0784314, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 2123.0, 0.392157, 0.392157, 0.235294 );
transferFunction->AddRGBPoint( 2124.0, 0.862745, 0.705882, 0.862745 );
transferFunction->AddRGBPoint( 2125.0, 0.0784314, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 2126.0, 0.235294, 0.54902, 0.705882 );
transferFunction->AddRGBPoint( 2127.0, 0.0980392, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 2128.0, 0.0784314, 0.235294, 0.392157 );
transferFunction->AddRGBPoint( 2129.0, 0.235294, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 2130.0, 0.235294, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 2131.0, 0.862745, 0.862745, 0.392157 );
transferFunction->AddRGBPoint( 2132.0, 0.705882, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 2133.0, 0.235294, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 2134.0, 0.862745, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 2135.0, 0.254902, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 2136.0, 0.0980392, 0.54902, 0.0784314 );
transferFunction->AddRGBPoint( 2137.0, 0.0509804, 0, 0.980392 );
transferFunction->AddRGBPoint( 2138.0, 0.239216, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 2139.0, 0.239216, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 2140.0, 0.239216, 0.235294, 0.392157 );
transferFunction->AddRGBPoint( 2141.0, 0.0980392, 0.0980392, 0.0980392 );
transferFunction->AddRGBPoint( 2142.0, 0.54902, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 2143.0, 0.862745, 0.705882, 0.0784314 );
transferFunction->AddRGBPoint( 2144.0, 0.247059, 0.705882, 0.705882 );
transferFunction->AddRGBPoint( 2145.0, 0.866667, 0.0784314, 0.0392157 );
transferFunction->AddRGBPoint( 2146.0, 0.0823529, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 2147.0, 0.717647, 0.392157, 0.0784314 );
transferFunction->AddRGBPoint( 2148.0, 0.866667, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 2149.0, 0.866667, 0.235294, 0.54902 );
transferFunction->AddRGBPoint( 2150.0, 0.866667, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 2151.0, 0.239216, 0.862745, 0.862745 );
transferFunction->AddRGBPoint( 2152.0, 0.392157, 0.784314, 0.784314 );
transferFunction->AddRGBPoint( 2153.0, 0.0392157, 0.784314, 0.784314 );
transferFunction->AddRGBPoint( 2154.0, 0.866667, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 2155.0, 0.552941, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 2156.0, 0.239216, 0.862745, 0.392157 );
transferFunction->AddRGBPoint( 2157.0, 0.0823529, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 2158.0, 0.552941, 0.235294, 0.0784314 );
transferFunction->AddRGBPoint( 2159.0, 0.560784, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 2160.0, 0.239216, 0.0784314, 0.705882 );
transferFunction->AddRGBPoint( 2161.0, 0.396078, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 2162.0, 0.0823529, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 2163.0, 0.866667, 0.54902, 0.0784314 );
transferFunction->AddRGBPoint( 2164.0, 0.552941, 0.392157, 0.862745 );
transferFunction->AddRGBPoint( 2165.0, 0.396078, 0.0784314, 0.0784314 );
transferFunction->AddRGBPoint( 2166.0, 0.866667, 0.392157, 0.0784314 );
transferFunction->AddRGBPoint( 2167.0, 0.709804, 0.784314, 0.0784314 );
transferFunction->AddRGBPoint( 2168.0, 0.0823529, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 2169.0, 0.396078, 0.392157, 0.705882 );
transferFunction->AddRGBPoint( 2170.0, 0.709804, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 2171.0, 0.0823529, 0.54902, 0.784314 );
transferFunction->AddRGBPoint( 2172.0, 0.0823529, 0.0784314, 0.941176 );
transferFunction->AddRGBPoint( 2173.0, 0.0823529, 0.0784314, 0.784314 );
transferFunction->AddRGBPoint( 2174.0, 0.239216, 0.705882, 0.235294 );
transferFunction->AddRGBPoint( 2175.0, 0.239216, 0.705882, 0.980392 );
transferFunction->AddRGBPoint( 2176.0, 0.0823529, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 2177.0, 0.396078, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 2178.0, 0.0823529, 0.862745, 0.862745 );
transferFunction->AddRGBPoint( 2179.0, 0.0823529, 0.705882, 0.705882 );
transferFunction->AddRGBPoint( 2180.0, 0.87451, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 2181.0, 0.866667, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 2200.0, 0.0980392, 0.235294, 0.239216 );
transferFunction->AddRGBPoint( 2201.0, 0.0980392, 0.352941, 0.235294 );
transferFunction->AddRGBPoint( 2202.0, 0.0980392, 0.470588, 0.235294 );
transferFunction->AddRGBPoint( 2205.0, 0.0980392, 0.588235, 0.235294 );
transferFunction->AddRGBPoint( 2206.0, 0.0980392, 0.705882, 0.235294 );
transferFunction->AddRGBPoint( 2207.0, 0.0980392, 0.823529, 0.235294 );
transferFunction->AddRGBPoint( 2210.0, 0.0980392, 0.588235, 0.352941 );
transferFunction->AddRGBPoint( 2211.0, 0.0980392, 0.705882, 0.352941 );
transferFunction->AddRGBPoint( 2212.0, 0.0980392, 0.823529, 0.352941 );
transferFunction->AddRGBPoint( 3101.0, 0.196078, 0.196078, 0.196078 );
transferFunction->AddRGBPoint( 3102.0, 0.705882, 0.0784314, 0.117647 );
transferFunction->AddRGBPoint( 3103.0, 0.235294, 0.0980392, 0.0980392 );
transferFunction->AddRGBPoint( 3104.0, 0.0980392, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 3105.0, 0.705882, 0.0784314, 0.0784314 );
transferFunction->AddRGBPoint( 3106.0, 0.862745, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 3107.0, 0.54902, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 3108.0, 0.705882, 0.862745, 0.54902 );
transferFunction->AddRGBPoint( 3109.0, 0.54902, 0.392157, 0.705882 );
transferFunction->AddRGBPoint( 3110.0, 0.705882, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 3111.0, 0.54902, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 3112.0, 0.0823529, 0.0392157, 0.0392157 );
transferFunction->AddRGBPoint( 3113.0, 0.882353, 0.54902, 0.54902 );
transferFunction->AddRGBPoint( 3114.0, 0.0901961, 0.235294, 0.705882 );
transferFunction->AddRGBPoint( 3115.0, 0.705882, 0.235294, 0.705882 );
transferFunction->AddRGBPoint( 3116.0, 0.0784314, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 3117.0, 0.235294, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 3118.0, 0.862745, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 3119.0, 0.254902, 0.392157, 0.0784314 );
transferFunction->AddRGBPoint( 3120.0, 0.862745, 0.235294, 0.0784314 );
transferFunction->AddRGBPoint( 3121.0, 0.235294, 0.392157, 0.235294 );
transferFunction->AddRGBPoint( 3122.0, 0.0784314, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 3123.0, 0.392157, 0.392157, 0.235294 );
transferFunction->AddRGBPoint( 3124.0, 0.862745, 0.705882, 0.862745 );
transferFunction->AddRGBPoint( 3125.0, 0.0784314, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 3126.0, 0.235294, 0.54902, 0.705882 );
transferFunction->AddRGBPoint( 3127.0, 0.0980392, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 3128.0, 0.0784314, 0.235294, 0.392157 );
transferFunction->AddRGBPoint( 3129.0, 0.235294, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 3130.0, 0.235294, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 3131.0, 0.862745, 0.862745, 0.392157 );
transferFunction->AddRGBPoint( 3132.0, 0.705882, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 3133.0, 0.235294, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 3134.0, 0.862745, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 3135.0, 0.254902, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 3136.0, 0.0980392, 0.54902, 0.0784314 );
transferFunction->AddRGBPoint( 3137.0, 0.0509804, 0, 0.980392 );
transferFunction->AddRGBPoint( 3138.0, 0.239216, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 3139.0, 0.239216, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 3140.0, 0.239216, 0.235294, 0.392157 );
transferFunction->AddRGBPoint( 3141.0, 0.0980392, 0.0980392, 0.0980392 );
transferFunction->AddRGBPoint( 3142.0, 0.54902, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 3143.0, 0.862745, 0.705882, 0.0784314 );
transferFunction->AddRGBPoint( 3144.0, 0.247059, 0.705882, 0.705882 );
transferFunction->AddRGBPoint( 3145.0, 0.866667, 0.0784314, 0.0392157 );
transferFunction->AddRGBPoint( 3146.0, 0.0823529, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 3147.0, 0.717647, 0.392157, 0.0784314 );
transferFunction->AddRGBPoint( 3148.0, 0.866667, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 3149.0, 0.866667, 0.235294, 0.54902 );
transferFunction->AddRGBPoint( 3150.0, 0.866667, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 3151.0, 0.239216, 0.862745, 0.862745 );
transferFunction->AddRGBPoint( 3152.0, 0.392157, 0.784314, 0.784314 );
transferFunction->AddRGBPoint( 3153.0, 0.0392157, 0.784314, 0.784314 );
transferFunction->AddRGBPoint( 3154.0, 0.866667, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 3155.0, 0.552941, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 3156.0, 0.239216, 0.862745, 0.392157 );
transferFunction->AddRGBPoint( 3157.0, 0.0823529, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 3158.0, 0.552941, 0.235294, 0.0784314 );
transferFunction->AddRGBPoint( 3159.0, 0.560784, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 3160.0, 0.239216, 0.0784314, 0.705882 );
transferFunction->AddRGBPoint( 3161.0, 0.396078, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 3162.0, 0.0823529, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 3163.0, 0.866667, 0.54902, 0.0784314 );
transferFunction->AddRGBPoint( 3164.0, 0.552941, 0.392157, 0.862745 );
transferFunction->AddRGBPoint( 3165.0, 0.396078, 0.0784314, 0.0784314 );
transferFunction->AddRGBPoint( 3166.0, 0.866667, 0.392157, 0.0784314 );
transferFunction->AddRGBPoint( 3167.0, 0.709804, 0.784314, 0.0784314 );
transferFunction->AddRGBPoint( 3168.0, 0.0823529, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 3169.0, 0.396078, 0.392157, 0.705882 );
transferFunction->AddRGBPoint( 3170.0, 0.709804, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 3171.0, 0.0823529, 0.54902, 0.784314 );
transferFunction->AddRGBPoint( 3172.0, 0.0823529, 0.0784314, 0.941176 );
transferFunction->AddRGBPoint( 3173.0, 0.0823529, 0.0784314, 0.784314 );
transferFunction->AddRGBPoint( 3174.0, 0.239216, 0.705882, 0.235294 );
transferFunction->AddRGBPoint( 3175.0, 0.239216, 0.705882, 0.980392 );
transferFunction->AddRGBPoint( 3176.0, 0.0823529, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 3177.0, 0.396078, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 3178.0, 0.0823529, 0.862745, 0.862745 );
transferFunction->AddRGBPoint( 3179.0, 0.0823529, 0.705882, 0.705882 );
transferFunction->AddRGBPoint( 3180.0, 0.87451, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 3181.0, 0.866667, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 4101.0, 0.196078, 0.196078, 0.196078 );
transferFunction->AddRGBPoint( 4102.0, 0.705882, 0.0784314, 0.117647 );
transferFunction->AddRGBPoint( 4103.0, 0.235294, 0.0980392, 0.0980392 );
transferFunction->AddRGBPoint( 4104.0, 0.0980392, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 4105.0, 0.705882, 0.0784314, 0.0784314 );
transferFunction->AddRGBPoint( 4106.0, 0.862745, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 4107.0, 0.54902, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 4108.0, 0.705882, 0.862745, 0.54902 );
transferFunction->AddRGBPoint( 4109.0, 0.54902, 0.392157, 0.705882 );
transferFunction->AddRGBPoint( 4110.0, 0.705882, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 4111.0, 0.54902, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 4112.0, 0.0823529, 0.0392157, 0.0392157 );
transferFunction->AddRGBPoint( 4113.0, 0.882353, 0.54902, 0.54902 );
transferFunction->AddRGBPoint( 4114.0, 0.0901961, 0.235294, 0.705882 );
transferFunction->AddRGBPoint( 4115.0, 0.705882, 0.235294, 0.705882 );
transferFunction->AddRGBPoint( 4116.0, 0.0784314, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 4117.0, 0.235294, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 4118.0, 0.862745, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 4119.0, 0.254902, 0.392157, 0.0784314 );
transferFunction->AddRGBPoint( 4120.0, 0.862745, 0.235294, 0.0784314 );
transferFunction->AddRGBPoint( 4121.0, 0.235294, 0.392157, 0.235294 );
transferFunction->AddRGBPoint( 4122.0, 0.0784314, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 4123.0, 0.392157, 0.392157, 0.235294 );
transferFunction->AddRGBPoint( 4124.0, 0.862745, 0.705882, 0.862745 );
transferFunction->AddRGBPoint( 4125.0, 0.0784314, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 4126.0, 0.235294, 0.54902, 0.705882 );
transferFunction->AddRGBPoint( 4127.0, 0.0980392, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 4128.0, 0.0784314, 0.235294, 0.392157 );
transferFunction->AddRGBPoint( 4129.0, 0.235294, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 4130.0, 0.235294, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 4131.0, 0.862745, 0.862745, 0.392157 );
transferFunction->AddRGBPoint( 4132.0, 0.705882, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 4133.0, 0.235294, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 4134.0, 0.862745, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 4135.0, 0.254902, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 4136.0, 0.0980392, 0.54902, 0.0784314 );
transferFunction->AddRGBPoint( 4137.0, 0.0509804, 0, 0.980392 );
transferFunction->AddRGBPoint( 4138.0, 0.239216, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 4139.0, 0.239216, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 4140.0, 0.239216, 0.235294, 0.392157 );
transferFunction->AddRGBPoint( 4141.0, 0.0980392, 0.0980392, 0.0980392 );
transferFunction->AddRGBPoint( 4142.0, 0.54902, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 4143.0, 0.862745, 0.705882, 0.0784314 );
transferFunction->AddRGBPoint( 4144.0, 0.247059, 0.705882, 0.705882 );
transferFunction->AddRGBPoint( 4145.0, 0.866667, 0.0784314, 0.0392157 );
transferFunction->AddRGBPoint( 4146.0, 0.0823529, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 4147.0, 0.717647, 0.392157, 0.0784314 );
transferFunction->AddRGBPoint( 4148.0, 0.866667, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 4149.0, 0.866667, 0.235294, 0.54902 );
transferFunction->AddRGBPoint( 4150.0, 0.866667, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 4151.0, 0.239216, 0.862745, 0.862745 );
transferFunction->AddRGBPoint( 4152.0, 0.392157, 0.784314, 0.784314 );
transferFunction->AddRGBPoint( 4153.0, 0.0392157, 0.784314, 0.784314 );
transferFunction->AddRGBPoint( 4154.0, 0.866667, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 4155.0, 0.552941, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 4156.0, 0.239216, 0.862745, 0.392157 );
transferFunction->AddRGBPoint( 4157.0, 0.0823529, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 4158.0, 0.552941, 0.235294, 0.0784314 );
transferFunction->AddRGBPoint( 4159.0, 0.560784, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 4160.0, 0.239216, 0.0784314, 0.705882 );
transferFunction->AddRGBPoint( 4161.0, 0.396078, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 4162.0, 0.0823529, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 4163.0, 0.866667, 0.54902, 0.0784314 );
transferFunction->AddRGBPoint( 4164.0, 0.552941, 0.392157, 0.862745 );
transferFunction->AddRGBPoint( 4165.0, 0.396078, 0.0784314, 0.0784314 );
transferFunction->AddRGBPoint( 4166.0, 0.866667, 0.392157, 0.0784314 );
transferFunction->AddRGBPoint( 4167.0, 0.709804, 0.784314, 0.0784314 );
transferFunction->AddRGBPoint( 4168.0, 0.0823529, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 4169.0, 0.396078, 0.392157, 0.705882 );
transferFunction->AddRGBPoint( 4170.0, 0.709804, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 4171.0, 0.0823529, 0.54902, 0.784314 );
transferFunction->AddRGBPoint( 4172.0, 0.0823529, 0.0784314, 0.941176 );
transferFunction->AddRGBPoint( 4173.0, 0.0823529, 0.0784314, 0.784314 );
transferFunction->AddRGBPoint( 4174.0, 0.239216, 0.705882, 0.235294 );
transferFunction->AddRGBPoint( 4175.0, 0.239216, 0.705882, 0.980392 );
transferFunction->AddRGBPoint( 4176.0, 0.0823529, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 4177.0, 0.396078, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 4178.0, 0.0823529, 0.862745, 0.862745 );
transferFunction->AddRGBPoint( 4179.0, 0.0823529, 0.705882, 0.705882 );
transferFunction->AddRGBPoint( 4180.0, 0.87451, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 4181.0, 0.866667, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 5001.0, 0.0784314, 0.117647, 0.156863 );
transferFunction->AddRGBPoint( 5002.0, 0.0784314, 0.117647, 0.156863 );
transferFunction->AddRGBPoint( 5100.0, 0.8, 0.4, 0.4 );
transferFunction->AddRGBPoint( 5101.0, 0.8, 0.4, 0.4 );
transferFunction->AddRGBPoint( 5102.0, 1, 1, 0.4 );
transferFunction->AddRGBPoint( 5103.0, 0.6, 0.8, 0 );
transferFunction->AddRGBPoint( 5104.0, 0, 0.6, 0.6 );
transferFunction->AddRGBPoint( 5105.0, 0.8, 0.6, 1 );
transferFunction->AddRGBPoint( 5106.0, 1, 0.6, 0.2 );
transferFunction->AddRGBPoint( 5107.0, 0.8, 0.8, 0.8 );
transferFunction->AddRGBPoint( 5108.0, 0.6, 1, 1 );
transferFunction->AddRGBPoint( 5109.0, 0.4, 0.6, 1 );
transferFunction->AddRGBPoint( 5110.0, 1, 1, 0.4 );
transferFunction->AddRGBPoint( 5111.0, 0.6, 0.8, 0 );
transferFunction->AddRGBPoint( 5112.0, 0, 0.6, 0.6 );
transferFunction->AddRGBPoint( 5113.0, 0.8, 0.6, 1 );
transferFunction->AddRGBPoint( 5114.0, 1, 0.6, 0.2 );
transferFunction->AddRGBPoint( 5115.0, 0.8, 0.8, 0.8 );
transferFunction->AddRGBPoint( 5116.0, 0.6, 1, 1 );
transferFunction->AddRGBPoint( 5117.0, 0.4, 0.6, 1 );
transferFunction->AddRGBPoint( 5200.0, 0.8, 0.4, 0.4 );
transferFunction->AddRGBPoint( 5201.0, 0.8, 0.4, 0.4 );
transferFunction->AddRGBPoint( 5202.0, 1, 1, 0.4 );
transferFunction->AddRGBPoint( 5203.0, 0.6, 0.8, 0 );
transferFunction->AddRGBPoint( 5204.0, 0, 0.6, 0.6 );
transferFunction->AddRGBPoint( 5205.0, 0.8, 0.6, 1 );
transferFunction->AddRGBPoint( 5206.0, 1, 0.6, 0.2 );
transferFunction->AddRGBPoint( 5207.0, 0.8, 0.8, 0.8 );
transferFunction->AddRGBPoint( 5208.0, 0.6, 1, 1 );
transferFunction->AddRGBPoint( 5209.0, 0.4, 0.6, 1 );
transferFunction->AddRGBPoint( 5210.0, 1, 1, 0.4 );
transferFunction->AddRGBPoint( 5211.0, 0.6, 0.8, 0 );
transferFunction->AddRGBPoint( 5212.0, 0, 0.6, 0.6 );
transferFunction->AddRGBPoint( 5213.0, 0.8, 0.6, 1 );
transferFunction->AddRGBPoint( 5214.0, 1, 0.6, 0.2 );
transferFunction->AddRGBPoint( 5215.0, 0.8, 0.8, 0.8 );
transferFunction->AddRGBPoint( 5216.0, 0.6, 1, 1 );
transferFunction->AddRGBPoint( 5217.0, 0.4, 0.6, 1 );
transferFunction->AddRGBPoint( 6000.0, 0, 1, 0 );
transferFunction->AddRGBPoint( 6001.0, 1, 1, 0 );
transferFunction->AddRGBPoint( 6002.0, 0, 1, 1 );
transferFunction->AddRGBPoint( 6003.0, 0, 0, 1 );
transferFunction->AddRGBPoint( 6010.0, 0.92549, 0.0627451, 0.905882 );
transferFunction->AddRGBPoint( 6020.0, 0.929412, 0.0705882, 0.909804 );
transferFunction->AddRGBPoint( 6030.0, 0.92549, 0.0509804, 0.890196 );
transferFunction->AddRGBPoint( 6040.0, 0.92549, 0.0666667, 0.894118 );
transferFunction->AddRGBPoint( 6050.0, 0.00392157, 1, 0.00392157 );
transferFunction->AddRGBPoint( 6060.0, 0.00784314, 1, 0.00392157 );
transferFunction->AddRGBPoint( 6070.0, 0.92549, 0.054902, 0.901961 );
transferFunction->AddRGBPoint( 6080.0, 0.929412, 0.054902, 0.901961 );
transferFunction->AddRGBPoint( 7001.0, 0.282353, 0.517647, 0.709804 );
transferFunction->AddRGBPoint( 7002.0, 0.952941, 0.952941, 0.952941 );
transferFunction->AddRGBPoint( 7003.0, 0.811765, 0.247059, 0.309804 );
transferFunction->AddRGBPoint( 7004.0, 0.47451, 0.0784314, 0.529412 );
transferFunction->AddRGBPoint( 7005.0, 0.772549, 0.235294, 0.972549 );
transferFunction->AddRGBPoint( 7006.0, 0.00784314, 0.584314, 0.00784314 );
transferFunction->AddRGBPoint( 7007.0, 0.866667, 0.976471, 0.65098 );
transferFunction->AddRGBPoint( 7008.0, 0.909804, 0.572549, 0.137255 );
transferFunction->AddRGBPoint( 7009.0, 0.0784314, 0.235294, 0.470588 );
transferFunction->AddRGBPoint( 7010.0, 0.980392, 0.980392, 0 );
transferFunction->AddRGBPoint( 7011.0, 0.478431, 0.733333, 0.870588 );
transferFunction->AddRGBPoint( 7012.0, 0.929412, 0.0470588, 0.694118 );
transferFunction->AddRGBPoint( 7013.0, 0.0392157, 0.192157, 1 );
transferFunction->AddRGBPoint( 7014.0, 0.803922, 0.721569, 0.564706 );
transferFunction->AddRGBPoint( 7015.0, 0.176471, 0.803922, 0.647059 );
transferFunction->AddRGBPoint( 7016.0, 0.458824, 0.627451, 0.686275 );
transferFunction->AddRGBPoint( 7017.0, 0.866667, 0.85098, 0.0823529 );
transferFunction->AddRGBPoint( 7018.0, 0.0784314, 0.235294, 0.470588 );
transferFunction->AddRGBPoint( 7019.0, 0.552941, 0.0823529, 0.392157 );
transferFunction->AddRGBPoint( 7020.0, 0.882353, 0.54902, 0.552941 );
transferFunction->AddRGBPoint( 7100.0, 0.164706, 0.788235, 0.658824 );
transferFunction->AddRGBPoint( 7101.0, 0.658824, 0.407843, 0.635294 );
transferFunction->AddRGBPoint( 8001.0, 0.290196, 0.509804, 0.709804 );
transferFunction->AddRGBPoint( 8002.0, 0.94902, 0.945098, 0.941176 );
transferFunction->AddRGBPoint( 8003.0, 0.807843, 0.254902, 0.305882 );
transferFunction->AddRGBPoint( 8004.0, 0.470588, 0.0823529, 0.521569 );
transferFunction->AddRGBPoint( 8005.0, 0.764706, 0.239216, 0.964706 );
transferFunction->AddRGBPoint( 8006.0, 0.0117647, 0.576471, 0.0235294 );
transferFunction->AddRGBPoint( 8007.0, 0.862745, 0.984314, 0.639216 );
transferFunction->AddRGBPoint( 8008.0, 0.909804, 0.572549, 0.129412 );
transferFunction->AddRGBPoint( 8009.0, 0.0156863, 0.447059, 0.054902 );
transferFunction->AddRGBPoint( 8010.0, 0.47451, 0.721569, 0.862745 );
transferFunction->AddRGBPoint( 8011.0, 0.921569, 0.0431373, 0.686275 );
transferFunction->AddRGBPoint( 8012.0, 0.0470588, 0.180392, 0.980392 );
transferFunction->AddRGBPoint( 8013.0, 0.796078, 0.713725, 0.560784 );
transferFunction->AddRGBPoint( 8014.0, 0.164706, 0.8, 0.654902 );
transferFunction->AddRGBPoint( 9000.0, 0.117647, 0.0196078, 0.117647 );
transferFunction->AddRGBPoint( 9001.0, 0.117647, 0.392157, 0.176471 );
transferFunction->AddRGBPoint( 9002.0, 0.509804, 0.392157, 0.647059 );
transferFunction->AddRGBPoint( 9003.0, 0.411765, 0.0980392, 0.0196078 );
transferFunction->AddRGBPoint( 9004.0, 0.490196, 0.27451, 0.215686 );
transferFunction->AddRGBPoint( 9005.0, 0.882353, 0.0784314, 0.411765 );
transferFunction->AddRGBPoint( 9006.0, 0.882353, 0.0784314, 0.0588235 );
transferFunction->AddRGBPoint( 9500.0, 0.117647, 0.215686, 0.117647 );
transferFunction->AddRGBPoint( 9501.0, 0.117647, 0.588235, 0.176471 );
transferFunction->AddRGBPoint( 9502.0, 0.509804, 0.588235, 0.647059 );
transferFunction->AddRGBPoint( 9503.0, 0.411765, 0.294118, 0.0196078 );
transferFunction->AddRGBPoint( 9504.0, 0.490196, 0.470588, 0.215686 );
transferFunction->AddRGBPoint( 9505.0, 0.882353, 0.27451, 0.411765 );
transferFunction->AddRGBPoint( 9506.0, 0.882353, 0.27451, 0.0588235 );
transferFunction->AddRGBPoint( 11101.0, 0.0901961, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 11102.0, 0.0901961, 0.235294, 0.705882 );
transferFunction->AddRGBPoint( 11103.0, 0.247059, 0.392157, 0.235294 );
transferFunction->AddRGBPoint( 11104.0, 0.247059, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 11105.0, 0.0509804, 0, 0.980392 );
transferFunction->AddRGBPoint( 11106.0, 0.101961, 0.235294, 0 );
transferFunction->AddRGBPoint( 11107.0, 0.101961, 0.235294, 0.294118 );
transferFunction->AddRGBPoint( 11108.0, 0.101961, 0.235294, 0.588235 );
transferFunction->AddRGBPoint( 11109.0, 0.0980392, 0.235294, 0.980392 );
transferFunction->AddRGBPoint( 11110.0, 0.235294, 0.0980392, 0.0980392 );
transferFunction->AddRGBPoint( 11111.0, 0.705882, 0.0784314, 0.0784314 );
transferFunction->AddRGBPoint( 11112.0, 0.862745, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 11113.0, 0.54902, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 11114.0, 0.705882, 0.862745, 0.54902 );
transferFunction->AddRGBPoint( 11115.0, 0.54902, 0.392157, 0.705882 );
transferFunction->AddRGBPoint( 11116.0, 0.705882, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 11117.0, 0.0901961, 0.0392157, 0.0392157 );
transferFunction->AddRGBPoint( 11118.0, 0.882353, 0.54902, 0.54902 );
transferFunction->AddRGBPoint( 11119.0, 0.705882, 0.235294, 0.705882 );
transferFunction->AddRGBPoint( 11120.0, 0.0784314, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 11121.0, 0.235294, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 11122.0, 0.862745, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 11123.0, 0.254902, 0.392157, 0.0784314 );
transferFunction->AddRGBPoint( 11124.0, 0.862745, 0.235294, 0.0784314 );
transferFunction->AddRGBPoint( 11125.0, 0.0784314, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 11126.0, 0.392157, 0.392157, 0.235294 );
transferFunction->AddRGBPoint( 11127.0, 0.862745, 0.705882, 0.862745 );
transferFunction->AddRGBPoint( 11128.0, 0.0784314, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 11129.0, 0.235294, 0.54902, 0.705882 );
transferFunction->AddRGBPoint( 11130.0, 0.0980392, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 11131.0, 0.0784314, 0.235294, 0.392157 );
transferFunction->AddRGBPoint( 11132.0, 0.235294, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 11133.0, 0.235294, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 11134.0, 0.862745, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 11135.0, 0.254902, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 11136.0, 0.0980392, 0.54902, 0.0784314 );
transferFunction->AddRGBPoint( 11137.0, 0.862745, 0.862745, 0.392157 );
transferFunction->AddRGBPoint( 11138.0, 0.705882, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 11139.0, 0.239216, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 11140.0, 0.239216, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 11141.0, 0.239216, 0.235294, 0.392157 );
transferFunction->AddRGBPoint( 11142.0, 0.0980392, 0.0980392, 0.0980392 );
transferFunction->AddRGBPoint( 11143.0, 0.54902, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 11144.0, 0.862745, 0.705882, 0.0784314 );
transferFunction->AddRGBPoint( 11145.0, 0.247059, 0.705882, 0.705882 );
transferFunction->AddRGBPoint( 11146.0, 0.866667, 0.0784314, 0.0392157 );
transferFunction->AddRGBPoint( 11147.0, 0.866667, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 11148.0, 0.866667, 0.235294, 0.54902 );
transferFunction->AddRGBPoint( 11149.0, 0.866667, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 11150.0, 0.239216, 0.862745, 0.862745 );
transferFunction->AddRGBPoint( 11151.0, 0.392157, 0.784314, 0.784314 );
transferFunction->AddRGBPoint( 11152.0, 0.0392157, 0.784314, 0.784314 );
transferFunction->AddRGBPoint( 11153.0, 0.866667, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 11154.0, 0.552941, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 11155.0, 0.239216, 0.862745, 0.392157 );
transferFunction->AddRGBPoint( 11156.0, 0.552941, 0.235294, 0.0784314 );
transferFunction->AddRGBPoint( 11157.0, 0.560784, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 11158.0, 0.396078, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 11159.0, 0.0823529, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 11160.0, 0.239216, 0.0784314, 0.705882 );
transferFunction->AddRGBPoint( 11161.0, 0.866667, 0.54902, 0.0784314 );
transferFunction->AddRGBPoint( 11162.0, 0.552941, 0.392157, 0.862745 );
transferFunction->AddRGBPoint( 11163.0, 0.866667, 0.392157, 0.0784314 );
transferFunction->AddRGBPoint( 11164.0, 0.709804, 0.784314, 0.0784314 );
transferFunction->AddRGBPoint( 11165.0, 0.396078, 0.0784314, 0.0784314 );
transferFunction->AddRGBPoint( 11166.0, 0.396078, 0.392157, 0.705882 );
transferFunction->AddRGBPoint( 11167.0, 0.709804, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 11168.0, 0.0823529, 0.54902, 0.784314 );
transferFunction->AddRGBPoint( 11169.0, 0.0823529, 0.0784314, 0.941176 );
transferFunction->AddRGBPoint( 11170.0, 0.0823529, 0.0784314, 0.784314 );
transferFunction->AddRGBPoint( 11171.0, 0.0823529, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 11172.0, 0.396078, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 11173.0, 0.0823529, 0.705882, 0.705882 );
transferFunction->AddRGBPoint( 11174.0, 0.87451, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 11175.0, 0.866667, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 12101.0, 0.0901961, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 12102.0, 0.0901961, 0.235294, 0.705882 );
transferFunction->AddRGBPoint( 12103.0, 0.247059, 0.392157, 0.235294 );
transferFunction->AddRGBPoint( 12104.0, 0.247059, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 12105.0, 0.0509804, 0, 0.980392 );
transferFunction->AddRGBPoint( 12106.0, 0.101961, 0.235294, 0 );
transferFunction->AddRGBPoint( 12107.0, 0.101961, 0.235294, 0.294118 );
transferFunction->AddRGBPoint( 12108.0, 0.101961, 0.235294, 0.588235 );
transferFunction->AddRGBPoint( 12109.0, 0.0980392, 0.235294, 0.980392 );
transferFunction->AddRGBPoint( 12110.0, 0.235294, 0.0980392, 0.0980392 );
transferFunction->AddRGBPoint( 12111.0, 0.705882, 0.0784314, 0.0784314 );
transferFunction->AddRGBPoint( 12112.0, 0.862745, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 12113.0, 0.54902, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 12114.0, 0.705882, 0.862745, 0.54902 );
transferFunction->AddRGBPoint( 12115.0, 0.54902, 0.392157, 0.705882 );
transferFunction->AddRGBPoint( 12116.0, 0.705882, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 12117.0, 0.0901961, 0.0392157, 0.0392157 );
transferFunction->AddRGBPoint( 12118.0, 0.882353, 0.54902, 0.54902 );
transferFunction->AddRGBPoint( 12119.0, 0.705882, 0.235294, 0.705882 );
transferFunction->AddRGBPoint( 12120.0, 0.0784314, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 12121.0, 0.235294, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 12122.0, 0.862745, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 12123.0, 0.254902, 0.392157, 0.0784314 );
transferFunction->AddRGBPoint( 12124.0, 0.862745, 0.235294, 0.0784314 );
transferFunction->AddRGBPoint( 12125.0, 0.0784314, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 12126.0, 0.392157, 0.392157, 0.235294 );
transferFunction->AddRGBPoint( 12127.0, 0.862745, 0.705882, 0.862745 );
transferFunction->AddRGBPoint( 12128.0, 0.0784314, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 12129.0, 0.235294, 0.54902, 0.705882 );
transferFunction->AddRGBPoint( 12130.0, 0.0980392, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 12131.0, 0.0784314, 0.235294, 0.392157 );
transferFunction->AddRGBPoint( 12132.0, 0.235294, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 12133.0, 0.235294, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 12134.0, 0.862745, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 12135.0, 0.254902, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 12136.0, 0.0980392, 0.54902, 0.0784314 );
transferFunction->AddRGBPoint( 12137.0, 0.862745, 0.862745, 0.392157 );
transferFunction->AddRGBPoint( 12138.0, 0.705882, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 12139.0, 0.239216, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 12140.0, 0.239216, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 12141.0, 0.239216, 0.235294, 0.392157 );
transferFunction->AddRGBPoint( 12142.0, 0.0980392, 0.0980392, 0.0980392 );
transferFunction->AddRGBPoint( 12143.0, 0.54902, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 12144.0, 0.862745, 0.705882, 0.0784314 );
transferFunction->AddRGBPoint( 12145.0, 0.247059, 0.705882, 0.705882 );
transferFunction->AddRGBPoint( 12146.0, 0.866667, 0.0784314, 0.0392157 );
transferFunction->AddRGBPoint( 12147.0, 0.866667, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 12148.0, 0.866667, 0.235294, 0.54902 );
transferFunction->AddRGBPoint( 12149.0, 0.866667, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 12150.0, 0.239216, 0.862745, 0.862745 );
transferFunction->AddRGBPoint( 12151.0, 0.392157, 0.784314, 0.784314 );
transferFunction->AddRGBPoint( 12152.0, 0.0392157, 0.784314, 0.784314 );
transferFunction->AddRGBPoint( 12153.0, 0.866667, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 12154.0, 0.552941, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 12155.0, 0.239216, 0.862745, 0.392157 );
transferFunction->AddRGBPoint( 12156.0, 0.552941, 0.235294, 0.0784314 );
transferFunction->AddRGBPoint( 12157.0, 0.560784, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 12158.0, 0.396078, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 12159.0, 0.0823529, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 12160.0, 0.239216, 0.0784314, 0.705882 );
transferFunction->AddRGBPoint( 12161.0, 0.866667, 0.54902, 0.0784314 );
transferFunction->AddRGBPoint( 12162.0, 0.552941, 0.392157, 0.862745 );
transferFunction->AddRGBPoint( 12163.0, 0.866667, 0.392157, 0.0784314 );
transferFunction->AddRGBPoint( 12164.0, 0.709804, 0.784314, 0.0784314 );
transferFunction->AddRGBPoint( 12165.0, 0.396078, 0.0784314, 0.0784314 );
transferFunction->AddRGBPoint( 12166.0, 0.396078, 0.392157, 0.705882 );
transferFunction->AddRGBPoint( 12167.0, 0.709804, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 12168.0, 0.0823529, 0.54902, 0.784314 );
transferFunction->AddRGBPoint( 12169.0, 0.0823529, 0.0784314, 0.941176 );
transferFunction->AddRGBPoint( 12170.0, 0.0823529, 0.0784314, 0.784314 );
transferFunction->AddRGBPoint( 12171.0, 0.0823529, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 12172.0, 0.396078, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 12173.0, 0.0823529, 0.705882, 0.705882 );
transferFunction->AddRGBPoint( 12174.0, 0.87451, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 12175.0, 0.866667, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 13101.0, 0.0901961, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 13102.0, 0.0901961, 0.235294, 0.705882 );
transferFunction->AddRGBPoint( 13103.0, 0.247059, 0.392157, 0.235294 );
transferFunction->AddRGBPoint( 13104.0, 0.247059, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 13105.0, 0.0509804, 0, 0.980392 );
transferFunction->AddRGBPoint( 13106.0, 0.101961, 0.235294, 0 );
transferFunction->AddRGBPoint( 13107.0, 0.101961, 0.235294, 0.294118 );
transferFunction->AddRGBPoint( 13108.0, 0.101961, 0.235294, 0.588235 );
transferFunction->AddRGBPoint( 13109.0, 0.0980392, 0.235294, 0.980392 );
transferFunction->AddRGBPoint( 13110.0, 0.235294, 0.0980392, 0.0980392 );
transferFunction->AddRGBPoint( 13111.0, 0.705882, 0.0784314, 0.0784314 );
transferFunction->AddRGBPoint( 13112.0, 0.862745, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 13113.0, 0.54902, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 13114.0, 0.705882, 0.862745, 0.54902 );
transferFunction->AddRGBPoint( 13115.0, 0.54902, 0.392157, 0.705882 );
transferFunction->AddRGBPoint( 13116.0, 0.705882, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 13117.0, 0.0901961, 0.0392157, 0.0392157 );
transferFunction->AddRGBPoint( 13118.0, 0.882353, 0.54902, 0.54902 );
transferFunction->AddRGBPoint( 13119.0, 0.705882, 0.235294, 0.705882 );
transferFunction->AddRGBPoint( 13120.0, 0.0784314, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 13121.0, 0.235294, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 13122.0, 0.862745, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 13123.0, 0.254902, 0.392157, 0.0784314 );
transferFunction->AddRGBPoint( 13124.0, 0.862745, 0.235294, 0.0784314 );
transferFunction->AddRGBPoint( 13125.0, 0.0784314, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 13126.0, 0.392157, 0.392157, 0.235294 );
transferFunction->AddRGBPoint( 13127.0, 0.862745, 0.705882, 0.862745 );
transferFunction->AddRGBPoint( 13128.0, 0.0784314, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 13129.0, 0.235294, 0.54902, 0.705882 );
transferFunction->AddRGBPoint( 13130.0, 0.0980392, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 13131.0, 0.0784314, 0.235294, 0.392157 );
transferFunction->AddRGBPoint( 13132.0, 0.235294, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 13133.0, 0.235294, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 13134.0, 0.862745, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 13135.0, 0.254902, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 13136.0, 0.0980392, 0.54902, 0.0784314 );
transferFunction->AddRGBPoint( 13137.0, 0.862745, 0.862745, 0.392157 );
transferFunction->AddRGBPoint( 13138.0, 0.705882, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 13139.0, 0.239216, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 13140.0, 0.239216, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 13141.0, 0.239216, 0.235294, 0.392157 );
transferFunction->AddRGBPoint( 13142.0, 0.0980392, 0.0980392, 0.0980392 );
transferFunction->AddRGBPoint( 13143.0, 0.54902, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 13144.0, 0.862745, 0.705882, 0.0784314 );
transferFunction->AddRGBPoint( 13145.0, 0.247059, 0.705882, 0.705882 );
transferFunction->AddRGBPoint( 13146.0, 0.866667, 0.0784314, 0.0392157 );
transferFunction->AddRGBPoint( 13147.0, 0.866667, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 13148.0, 0.866667, 0.235294, 0.54902 );
transferFunction->AddRGBPoint( 13149.0, 0.866667, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 13150.0, 0.239216, 0.862745, 0.862745 );
transferFunction->AddRGBPoint( 13151.0, 0.392157, 0.784314, 0.784314 );
transferFunction->AddRGBPoint( 13152.0, 0.0392157, 0.784314, 0.784314 );
transferFunction->AddRGBPoint( 13153.0, 0.866667, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 13154.0, 0.552941, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 13155.0, 0.239216, 0.862745, 0.392157 );
transferFunction->AddRGBPoint( 13156.0, 0.552941, 0.235294, 0.0784314 );
transferFunction->AddRGBPoint( 13157.0, 0.560784, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 13158.0, 0.396078, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 13159.0, 0.0823529, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 13160.0, 0.239216, 0.0784314, 0.705882 );
transferFunction->AddRGBPoint( 13161.0, 0.866667, 0.54902, 0.0784314 );
transferFunction->AddRGBPoint( 13162.0, 0.552941, 0.392157, 0.862745 );
transferFunction->AddRGBPoint( 13163.0, 0.866667, 0.392157, 0.0784314 );
transferFunction->AddRGBPoint( 13164.0, 0.709804, 0.784314, 0.0784314 );
transferFunction->AddRGBPoint( 13165.0, 0.396078, 0.0784314, 0.0784314 );
transferFunction->AddRGBPoint( 13166.0, 0.396078, 0.392157, 0.705882 );
transferFunction->AddRGBPoint( 13167.0, 0.709804, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 13168.0, 0.0823529, 0.54902, 0.784314 );
transferFunction->AddRGBPoint( 13169.0, 0.0823529, 0.0784314, 0.941176 );
transferFunction->AddRGBPoint( 13170.0, 0.0823529, 0.0784314, 0.784314 );
transferFunction->AddRGBPoint( 13171.0, 0.0823529, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 13172.0, 0.396078, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 13173.0, 0.0823529, 0.705882, 0.705882 );
transferFunction->AddRGBPoint( 13174.0, 0.87451, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 13175.0, 0.866667, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 14101.0, 0.0901961, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 14102.0, 0.0901961, 0.235294, 0.705882 );
transferFunction->AddRGBPoint( 14103.0, 0.247059, 0.392157, 0.235294 );
transferFunction->AddRGBPoint( 14104.0, 0.247059, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 14105.0, 0.0509804, 0, 0.980392 );
transferFunction->AddRGBPoint( 14106.0, 0.101961, 0.235294, 0 );
transferFunction->AddRGBPoint( 14107.0, 0.101961, 0.235294, 0.294118 );
transferFunction->AddRGBPoint( 14108.0, 0.101961, 0.235294, 0.588235 );
transferFunction->AddRGBPoint( 14109.0, 0.0980392, 0.235294, 0.980392 );
transferFunction->AddRGBPoint( 14110.0, 0.235294, 0.0980392, 0.0980392 );
transferFunction->AddRGBPoint( 14111.0, 0.705882, 0.0784314, 0.0784314 );
transferFunction->AddRGBPoint( 14112.0, 0.862745, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 14113.0, 0.54902, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 14114.0, 0.705882, 0.862745, 0.54902 );
transferFunction->AddRGBPoint( 14115.0, 0.54902, 0.392157, 0.705882 );
transferFunction->AddRGBPoint( 14116.0, 0.705882, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 14117.0, 0.0901961, 0.0392157, 0.0392157 );
transferFunction->AddRGBPoint( 14118.0, 0.882353, 0.54902, 0.54902 );
transferFunction->AddRGBPoint( 14119.0, 0.705882, 0.235294, 0.705882 );
transferFunction->AddRGBPoint( 14120.0, 0.0784314, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 14121.0, 0.235294, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 14122.0, 0.862745, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 14123.0, 0.254902, 0.392157, 0.0784314 );
transferFunction->AddRGBPoint( 14124.0, 0.862745, 0.235294, 0.0784314 );
transferFunction->AddRGBPoint( 14125.0, 0.0784314, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 14126.0, 0.392157, 0.392157, 0.235294 );
transferFunction->AddRGBPoint( 14127.0, 0.862745, 0.705882, 0.862745 );
transferFunction->AddRGBPoint( 14128.0, 0.0784314, 0.705882, 0.54902 );
transferFunction->AddRGBPoint( 14129.0, 0.235294, 0.54902, 0.705882 );
transferFunction->AddRGBPoint( 14130.0, 0.0980392, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 14131.0, 0.0784314, 0.235294, 0.392157 );
transferFunction->AddRGBPoint( 14132.0, 0.235294, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 14133.0, 0.235294, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 14134.0, 0.862745, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 14135.0, 0.254902, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 14136.0, 0.0980392, 0.54902, 0.0784314 );
transferFunction->AddRGBPoint( 14137.0, 0.862745, 0.862745, 0.392157 );
transferFunction->AddRGBPoint( 14138.0, 0.705882, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 14139.0, 0.239216, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 14140.0, 0.239216, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 14141.0, 0.239216, 0.235294, 0.392157 );
transferFunction->AddRGBPoint( 14142.0, 0.0980392, 0.0980392, 0.0980392 );
transferFunction->AddRGBPoint( 14143.0, 0.54902, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 14144.0, 0.862745, 0.705882, 0.0784314 );
transferFunction->AddRGBPoint( 14145.0, 0.247059, 0.705882, 0.705882 );
transferFunction->AddRGBPoint( 14146.0, 0.866667, 0.0784314, 0.0392157 );
transferFunction->AddRGBPoint( 14147.0, 0.866667, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 14148.0, 0.866667, 0.235294, 0.54902 );
transferFunction->AddRGBPoint( 14149.0, 0.866667, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 14150.0, 0.239216, 0.862745, 0.862745 );
transferFunction->AddRGBPoint( 14151.0, 0.392157, 0.784314, 0.784314 );
transferFunction->AddRGBPoint( 14152.0, 0.0392157, 0.784314, 0.784314 );
transferFunction->AddRGBPoint( 14153.0, 0.866667, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 14154.0, 0.552941, 0.0784314, 0.392157 );
transferFunction->AddRGBPoint( 14155.0, 0.239216, 0.862745, 0.392157 );
transferFunction->AddRGBPoint( 14156.0, 0.552941, 0.235294, 0.0784314 );
transferFunction->AddRGBPoint( 14157.0, 0.560784, 0.0784314, 0.862745 );
transferFunction->AddRGBPoint( 14158.0, 0.396078, 0.235294, 0.862745 );
transferFunction->AddRGBPoint( 14159.0, 0.0823529, 0.0784314, 0.54902 );
transferFunction->AddRGBPoint( 14160.0, 0.239216, 0.0784314, 0.705882 );
transferFunction->AddRGBPoint( 14161.0, 0.866667, 0.54902, 0.0784314 );
transferFunction->AddRGBPoint( 14162.0, 0.552941, 0.392157, 0.862745 );
transferFunction->AddRGBPoint( 14163.0, 0.866667, 0.392157, 0.0784314 );
transferFunction->AddRGBPoint( 14164.0, 0.709804, 0.784314, 0.0784314 );
transferFunction->AddRGBPoint( 14165.0, 0.396078, 0.0784314, 0.0784314 );
transferFunction->AddRGBPoint( 14166.0, 0.396078, 0.392157, 0.705882 );
transferFunction->AddRGBPoint( 14167.0, 0.709804, 0.862745, 0.0784314 );
transferFunction->AddRGBPoint( 14168.0, 0.0823529, 0.54902, 0.784314 );
transferFunction->AddRGBPoint( 14169.0, 0.0823529, 0.0784314, 0.941176 );
transferFunction->AddRGBPoint( 14170.0, 0.0823529, 0.0784314, 0.784314 );
transferFunction->AddRGBPoint( 14171.0, 0.0823529, 0.0784314, 0.235294 );
transferFunction->AddRGBPoint( 14172.0, 0.396078, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 14173.0, 0.0823529, 0.705882, 0.705882 );
transferFunction->AddRGBPoint( 14174.0, 0.87451, 0.862745, 0.235294 );
transferFunction->AddRGBPoint( 14175.0, 0.866667, 0.235294, 0.235294 );
transferFunction->AddRGBPoint( 0.0, 0.0, 0.0, 0.0 );
transferFunction->AddRGBPoint( 256.0, 0.0, 0.0, 0.0 );
transferFunction->AddRGBPoint( 1100.0, 0.0, 0.0, 0.0 );
transferFunction->AddRGBPoint( 2100.0, 0.0, 0.0, 0.0 );
transferFunction->AddRGBPoint( 3100.0, 0.0, 0.0, 0.0 );
transferFunction->AddRGBPoint( 4100.0, 0.0, 0.0, 0.0 );
transferFunction->AddRGBPoint( 11100.0, 0.0, 0.0, 0.0 );
transferFunction->AddRGBPoint( 12100.0, 0.0, 0.0, 0.0 );
transferFunction->AddRGBPoint( 13100.0, 0.0, 0.0, 0.0 );
transferFunction->AddRGBPoint( 14100.0, 0.0, 0.0, 0.0 );
return transferFunction;
}
FreeSurferParcellationTranslator::NameTable FreeSurferParcellationTranslator::CreateNameTable()
{
mitk::FreeSurferParcellationTranslator::NameTable nameTable;
nameTable["0"] = "Unknown";
nameTable["1"] = "Left-Cerebral-Exterior";
nameTable["2"] = "Left-Cerebral-White-Matter";
nameTable["3"] = "Left-Cerebral-Cortex";
nameTable["4"] = "Left-Lateral-Ventricle";
nameTable["5"] = "Left-Inf-Lat-Vent";
nameTable["6"] = "Left-Cerebellum-Exterior";
nameTable["7"] = "Left-Cerebellum-White-Matter";
nameTable["8"] = "Left-Cerebellum-Cortex";
nameTable["9"] = "Left-Thalamus";
nameTable["10"] = "Left-Thalamus-Proper";
nameTable["11"] = "Left-Caudate";
nameTable["12"] = "Left-Putamen";
nameTable["13"] = "Left-Pallidum";
nameTable["14"] = "3rd-Ventricle";
nameTable["15"] = "4th-Ventricle";
nameTable["16"] = "Brain-Stem";
nameTable["17"] = "Left-Hippocampus";
nameTable["18"] = "Left-Amygdala";
nameTable["19"] = "Left-Insula";
nameTable["20"] = "Left-Operculum";
nameTable["21"] = "Line-1";
nameTable["22"] = "Line-2";
nameTable["23"] = "Line-3";
nameTable["24"] = "CSF";
nameTable["25"] = "Left-Lesion";
nameTable["26"] = "Left-Accumbens-area";
nameTable["27"] = "Left-Substancia-Nigra";
nameTable["28"] = "Left-VentralDC";
nameTable["29"] = "Left-undetermined";
nameTable["30"] = "Left-vessel";
nameTable["31"] = "Left-choroid-plexus";
nameTable["32"] = "Left-F3orb";
nameTable["33"] = "Left-lOg";
nameTable["34"] = "Left-aOg";
nameTable["35"] = "Left-mOg";
nameTable["36"] = "Left-pOg";
nameTable["37"] = "Left-Stellate";
nameTable["38"] = "Left-Porg";
nameTable["39"] = "Left-Aorg";
nameTable["40"] = "Right-Cerebral-Exterior";
nameTable["41"] = "Right-Cerebral-White-Matter";
nameTable["42"] = "Right-Cerebral-Cortex";
nameTable["43"] = "Right-Lateral-Ventricle";
nameTable["44"] = "Right-Inf-Lat-Vent";
nameTable["45"] = "Right-Cerebellum-Exterior";
nameTable["46"] = "Right-Cerebellum-White-Matter";
nameTable["47"] = "Right-Cerebellum-Cortex";
nameTable["48"] = "Right-Thalamus";
nameTable["49"] = "Right-Thalamus-Proper";
nameTable["50"] = "Right-Caudate";
nameTable["51"] = "Right-Putamen";
nameTable["52"] = "Right-Pallidum";
nameTable["53"] = "Right-Hippocampus";
nameTable["54"] = "Right-Amygdala";
nameTable["55"] = "Right-Insula";
nameTable["56"] = "Right-Operculum";
nameTable["57"] = "Right-Lesion";
nameTable["58"] = "Right-Accumbens-area";
nameTable["59"] = "Right-Substancia-Nigra";
nameTable["60"] = "Right-VentralDC";
nameTable["61"] = "Right-undetermined";
nameTable["62"] = "Right-vessel";
nameTable["63"] = "Right-choroid-plexus";
nameTable["64"] = "Right-F3orb";
nameTable["65"] = "Right-lOg";
nameTable["66"] = "Right-aOg";
nameTable["67"] = "Right-mOg";
nameTable["68"] = "Right-pOg";
nameTable["69"] = "Right-Stellate";
nameTable["70"] = "Right-Porg";
nameTable["71"] = "Right-Aorg";
nameTable["72"] = "5th-Ventricle";
nameTable["73"] = "Left-Interior";
nameTable["74"] = "Right-Interior";
nameTable["77"] = "WM-hypointensities";
nameTable["78"] = "Left-WM-hypointensities";
nameTable["79"] = "Right-WM-hypointensities";
nameTable["80"] = "non-WM-hypointensities";
nameTable["81"] = "Left-non-WM-hypointensities";
nameTable["82"] = "Right-non-WM-hypointensities";
nameTable["83"] = "Left-F1";
nameTable["84"] = "Right-F1";
nameTable["85"] = "Optic-Chiasm";
nameTable["192"] = "Corpus_Callosum";
nameTable["86"] = "Left_future_WMSA";
nameTable["87"] = "Right_future_WMSA";
nameTable["88"] = "future_WMSA";
nameTable["96"] = "Left-Amygdala-Anterior";
nameTable["97"] = "Right-Amygdala-Anterior";
nameTable["98"] = "Dura";
nameTable["100"] = "Left-wm-intensity-abnormality";
nameTable["101"] = "Left-caudate-intensity-abnormality";
nameTable["102"] = "Left-putamen-intensity-abnormality";
nameTable["103"] = "Left-accumbens-intensity-abnormality";
nameTable["104"] = "Left-pallidum-intensity-abnormality";
nameTable["105"] = "Left-amygdala-intensity-abnormality";
nameTable["106"] = "Left-hippocampus-intensity-abnormality";
nameTable["107"] = "Left-thalamus-intensity-abnormality";
nameTable["108"] = "Left-VDC-intensity-abnormality";
nameTable["109"] = "Right-wm-intensity-abnormality";
nameTable["110"] = "Right-caudate-intensity-abnormality";
nameTable["111"] = "Right-putamen-intensity-abnormality";
nameTable["112"] = "Right-accumbens-intensity-abnormality";
nameTable["113"] = "Right-pallidum-intensity-abnormality";
nameTable["114"] = "Right-amygdala-intensity-abnormality";
nameTable["115"] = "Right-hippocampus-intensity-abnormality";
nameTable["116"] = "Right-thalamus-intensity-abnormality";
nameTable["117"] = "Right-VDC-intensity-abnormality";
nameTable["118"] = "Epidermis";
nameTable["119"] = "Conn-Tissue";
nameTable["120"] = "SC-Fat-Muscle";
nameTable["121"] = "Cranium";
nameTable["122"] = "CSF-SA";
nameTable["123"] = "Muscle";
nameTable["124"] = "Ear";
nameTable["125"] = "Adipose";
nameTable["126"] = "Spinal-Cord";
nameTable["127"] = "Soft-Tissue";
nameTable["128"] = "Nerve";
nameTable["129"] = "Bone";
nameTable["130"] = "Air";
nameTable["131"] = "Orbital-Fat";
nameTable["132"] = "Tongue";
nameTable["133"] = "Nasal-Structures";
nameTable["134"] = "Globe";
nameTable["135"] = "Teeth";
nameTable["136"] = "Left-Caudate-Putamen";
nameTable["137"] = "Right-Caudate-Putamen";
nameTable["138"] = "Left-Claustrum";
nameTable["139"] = "Right-Claustrum";
nameTable["140"] = "Cornea";
nameTable["142"] = "Diploe";
nameTable["143"] = "Vitreous-Humor";
nameTable["144"] = "Lens";
nameTable["145"] = "Aqueous-Humor";
nameTable["146"] = "Outer-Table";
nameTable["147"] = "Inner-Table";
nameTable["148"] = "Periosteum";
nameTable["149"] = "Endosteum";
nameTable["150"] = "R-C-S";
nameTable["151"] = "Iris";
nameTable["152"] = "SC-Adipose-Muscle";
nameTable["153"] = "SC-Tissue";
nameTable["154"] = "Orbital-Adipose";
nameTable["155"] = "Left-IntCapsule-Ant";
nameTable["156"] = "Right-IntCapsule-Ant";
nameTable["157"] = "Left-IntCapsule-Pos";
nameTable["158"] = "Right-IntCapsule-Pos";
nameTable["159"] = "Left-Cerebral-WM-unmyelinated";
nameTable["160"] = "Right-Cerebral-WM-unmyelinated";
nameTable["161"] = "Left-Cerebral-WM-myelinated";
nameTable["162"] = "Right-Cerebral-WM-myelinated";
nameTable["163"] = "Left-Subcortical-Gray-Matter";
nameTable["164"] = "Right-Subcortical-Gray-Matter";
nameTable["165"] = "Skull";
nameTable["166"] = "Posterior-fossa";
nameTable["167"] = "Scalp";
nameTable["168"] = "Hematoma";
nameTable["169"] = "Left-Basal-Ganglia";
nameTable["176"] = "Right-Basal-Ganglia";
nameTable["170"] = "brainstem";
nameTable["171"] = "DCG";
nameTable["172"] = "Vermis";
nameTable["173"] = "Midbrain";
nameTable["174"] = "Pons";
nameTable["175"] = "Medulla";
nameTable["180"] = "Left-Cortical-Dysplasia";
nameTable["181"] = "Right-Cortical-Dysplasia";
nameTable["193"] = "Left-hippocampal_fissure";
nameTable["194"] = "Left-CADG-head";
nameTable["195"] = "Left-subiculum";
nameTable["196"] = "Left-fimbria";
nameTable["197"] = "Right-hippocampal_fissure";
nameTable["198"] = "Right-CADG-head";
nameTable["199"] = "Right-subiculum";
nameTable["200"] = "Right-fimbria";
nameTable["201"] = "alveus";
nameTable["202"] = "perforant_pathway";
nameTable["203"] = "parasubiculum";
nameTable["204"] = "presubiculum";
nameTable["205"] = "subiculum";
nameTable["206"] = "CA1";
nameTable["207"] = "CA2";
nameTable["208"] = "CA3";
nameTable["209"] = "CA4";
nameTable["210"] = "GC-ML-DG";
nameTable["211"] = "HATA";
nameTable["212"] = "fimbria";
nameTable["213"] = "lateral_ventricle";
nameTable["214"] = "molecular_layer_HP";
nameTable["215"] = "hippocampal_fissure";
nameTable["216"] = "entorhinal_cortex";
nameTable["217"] = "molecular_layer_subiculum";
nameTable["218"] = "Amygdala";
nameTable["219"] = "Cerebral_White_Matter";
nameTable["220"] = "Cerebral_Cortex";
nameTable["221"] = "Inf_Lat_Vent";
nameTable["222"] = "Perirhinal";
nameTable["223"] = "Cerebral_White_Matter_Edge";
nameTable["224"] = "Background";
nameTable["225"] = "Ectorhinal";
nameTable["226"] = "HP_tail";
nameTable["250"] = "Fornix";
nameTable["251"] = "CC_Posterior";
nameTable["252"] = "CC_Mid_Posterior";
nameTable["253"] = "CC_Central";
nameTable["254"] = "CC_Mid_Anterior";
nameTable["255"] = "CC_Anterior";
nameTable["256"] = "Voxel-Unchanged";
nameTable["331"] = "Aorta";
nameTable["332"] = "Left-Common-IliacA";
nameTable["333"] = "Right-Common-IliacA";
nameTable["334"] = "Left-External-IliacA";
nameTable["335"] = "Right-External-IliacA";
nameTable["336"] = "Left-Internal-IliacA";
nameTable["337"] = "Right-Internal-IliacA";
nameTable["338"] = "Left-Lateral-SacralA";
nameTable["339"] = "Right-Lateral-SacralA";
nameTable["340"] = "Left-ObturatorA";
nameTable["341"] = "Right-ObturatorA";
nameTable["342"] = "Left-Internal-PudendalA";
nameTable["343"] = "Right-Internal-PudendalA";
nameTable["344"] = "Left-UmbilicalA";
nameTable["345"] = "Right-UmbilicalA";
nameTable["346"] = "Left-Inf-RectalA";
nameTable["347"] = "Right-Inf-RectalA";
nameTable["348"] = "Left-Common-IliacV";
nameTable["349"] = "Right-Common-IliacV";
nameTable["350"] = "Left-External-IliacV";
nameTable["351"] = "Right-External-IliacV";
nameTable["352"] = "Left-Internal-IliacV";
nameTable["353"] = "Right-Internal-IliacV";
nameTable["354"] = "Left-ObturatorV";
nameTable["355"] = "Right-ObturatorV";
nameTable["356"] = "Left-Internal-PudendalV";
nameTable["357"] = "Right-Internal-PudendalV";
nameTable["358"] = "Pos-Lymph";
nameTable["359"] = "Neg-Lymph";
nameTable["400"] = "V1";
nameTable["401"] = "V2";
nameTable["402"] = "BA44";
nameTable["403"] = "BA45";
nameTable["404"] = "BA4a";
nameTable["405"] = "BA4p";
nameTable["406"] = "BA6";
nameTable["407"] = "BA2";
nameTable["408"] = "BA1_old";
nameTable["409"] = "BAun2";
nameTable["410"] = "BA1";
nameTable["411"] = "BA2b";
nameTable["412"] = "BA3a";
nameTable["413"] = "BA3b";
nameTable["414"] = "MT";
nameTable["415"] = "AIPS_AIP_l";
nameTable["416"] = "AIPS_AIP_r";
nameTable["417"] = "AIPS_VIP_l";
nameTable["418"] = "AIPS_VIP_r";
nameTable["419"] = "IPL_PFcm_l";
nameTable["420"] = "IPL_PFcm_r";
nameTable["421"] = "IPL_PF_l";
nameTable["422"] = "IPL_PFm_l";
nameTable["423"] = "IPL_PFm_r";
nameTable["424"] = "IPL_PFop_l";
nameTable["425"] = "IPL_PFop_r";
nameTable["426"] = "IPL_PF_r";
nameTable["427"] = "IPL_PFt_l";
nameTable["428"] = "IPL_PFt_r";
nameTable["429"] = "IPL_PGa_l";
nameTable["430"] = "IPL_PGa_r";
nameTable["431"] = "IPL_PGp_l";
nameTable["432"] = "IPL_PGp_r";
nameTable["433"] = "Visual_V3d_l";
nameTable["434"] = "Visual_V3d_r";
nameTable["435"] = "Visual_V4_l";
nameTable["436"] = "Visual_V4_r";
nameTable["437"] = "Visual_V5_b";
nameTable["438"] = "Visual_VP_l";
nameTable["439"] = "Visual_VP_r";
nameTable["498"] = "wmsa";
nameTable["499"] = "other_wmsa";
nameTable["500"] = "right_CA2_3";
nameTable["501"] = "right_alveus";
nameTable["502"] = "right_CA1";
nameTable["503"] = "right_fimbria";
nameTable["504"] = "right_presubiculum";
nameTable["505"] = "right_hippocampal_fissure";
nameTable["506"] = "right_CA4_DG";
nameTable["507"] = "right_subiculum";
nameTable["508"] = "right_fornix";
nameTable["550"] = "left_CA2_3";
nameTable["551"] = "left_alveus";
nameTable["552"] = "left_CA1";
nameTable["553"] = "left_fimbria";
nameTable["554"] = "left_presubiculum";
nameTable["555"] = "left_hippocampal_fissure";
nameTable["556"] = "left_CA4_DG";
nameTable["557"] = "left_subiculum";
nameTable["558"] = "left_fornix";
nameTable["600"] = "Tumor";
nameTable["601"] = "Cbm_Left_I_IV";
nameTable["602"] = "Cbm_Right_I_IV";
nameTable["603"] = "Cbm_Left_V";
nameTable["604"] = "Cbm_Right_V";
nameTable["605"] = "Cbm_Left_VI";
nameTable["606"] = "Cbm_Vermis_VI";
nameTable["607"] = "Cbm_Right_VI";
nameTable["608"] = "Cbm_Left_CrusI";
nameTable["609"] = "Cbm_Vermis_CrusI";
nameTable["610"] = "Cbm_Right_CrusI";
nameTable["611"] = "Cbm_Left_CrusII";
nameTable["612"] = "Cbm_Vermis_CrusII";
nameTable["613"] = "Cbm_Right_CrusII";
nameTable["614"] = "Cbm_Left_VIIb";
nameTable["615"] = "Cbm_Vermis_VIIb";
nameTable["616"] = "Cbm_Right_VIIb";
nameTable["617"] = "Cbm_Left_VIIIa";
nameTable["618"] = "Cbm_Vermis_VIIIa";
nameTable["619"] = "Cbm_Right_VIIIa";
nameTable["620"] = "Cbm_Left_VIIIb";
nameTable["621"] = "Cbm_Vermis_VIIIb";
nameTable["622"] = "Cbm_Right_VIIIb";
nameTable["623"] = "Cbm_Left_IX";
nameTable["624"] = "Cbm_Vermis_IX";
nameTable["625"] = "Cbm_Right_IX";
nameTable["626"] = "Cbm_Left_X";
nameTable["627"] = "Cbm_Vermis_X";
nameTable["628"] = "Cbm_Right_X";
nameTable["640"] = "Cbm_Right_I_V_med";
nameTable["641"] = "Cbm_Right_I_V_mid";
nameTable["642"] = "Cbm_Right_VI_med";
nameTable["643"] = "Cbm_Right_VI_mid";
nameTable["644"] = "Cbm_Right_VI_lat";
nameTable["645"] = "Cbm_Right_CrusI_med";
nameTable["646"] = "Cbm_Right_CrusI_mid";
nameTable["647"] = "Cbm_Right_CrusI_lat";
nameTable["648"] = "Cbm_Right_CrusII_med";
nameTable["649"] = "Cbm_Right_CrusII_mid";
nameTable["650"] = "Cbm_Right_CrusII_lat";
nameTable["651"] = "Cbm_Right_7med";
nameTable["652"] = "Cbm_Right_7mid";
nameTable["653"] = "Cbm_Right_7lat";
nameTable["654"] = "Cbm_Right_8med";
nameTable["655"] = "Cbm_Right_8mid";
nameTable["656"] = "Cbm_Right_8lat";
nameTable["657"] = "Cbm_Right_PUNs";
nameTable["658"] = "Cbm_Right_TONs";
nameTable["659"] = "Cbm_Right_FLOs";
nameTable["660"] = "Cbm_Left_I_V_med";
nameTable["661"] = "Cbm_Left_I_V_mid";
nameTable["662"] = "Cbm_Left_VI_med";
nameTable["663"] = "Cbm_Left_VI_mid";
nameTable["664"] = "Cbm_Left_VI_lat";
nameTable["665"] = "Cbm_Left_CrusI_med";
nameTable["666"] = "Cbm_Left_CrusI_mid";
nameTable["667"] = "Cbm_Left_CrusI_lat";
nameTable["668"] = "Cbm_Left_CrusII_med";
nameTable["669"] = "Cbm_Left_CrusII_mid";
nameTable["670"] = "Cbm_Left_CrusII_lat";
nameTable["671"] = "Cbm_Left_7med";
nameTable["672"] = "Cbm_Left_7mid";
nameTable["673"] = "Cbm_Left_7lat";
nameTable["674"] = "Cbm_Left_8med";
nameTable["675"] = "Cbm_Left_8mid";
nameTable["676"] = "Cbm_Left_8lat";
nameTable["677"] = "Cbm_Left_PUNs";
nameTable["678"] = "Cbm_Left_TONs";
nameTable["679"] = "Cbm_Left_FLOs";
nameTable["701"] = "CSF-FSL-FAST";
nameTable["702"] = "GrayMatter-FSL-FAST";
nameTable["703"] = "WhiteMatter-FSL-FAST";
nameTable["999"] = "SUSPICIOUS";
nameTable["1000"] = "ctx-lh-unknown";
nameTable["1001"] = "ctx-lh-bankssts";
nameTable["1002"] = "ctx-lh-caudalanteriorcingulate";
nameTable["1003"] = "ctx-lh-caudalmiddlefrontal";
nameTable["1004"] = "ctx-lh-corpuscallosum";
nameTable["1005"] = "ctx-lh-cuneus";
nameTable["1006"] = "ctx-lh-entorhinal";
nameTable["1007"] = "ctx-lh-fusiform";
nameTable["1008"] = "ctx-lh-inferiorparietal";
nameTable["1009"] = "ctx-lh-inferiortemporal";
nameTable["1010"] = "ctx-lh-isthmuscingulate";
nameTable["1011"] = "ctx-lh-lateraloccipital";
nameTable["1012"] = "ctx-lh-lateralorbitofrontal";
nameTable["1013"] = "ctx-lh-lingual";
nameTable["1014"] = "ctx-lh-medialorbitofrontal";
nameTable["1015"] = "ctx-lh-middletemporal";
nameTable["1016"] = "ctx-lh-parahippocampal";
nameTable["1017"] = "ctx-lh-paracentral";
nameTable["1018"] = "ctx-lh-parsopercularis";
nameTable["1019"] = "ctx-lh-parsorbitalis";
nameTable["1020"] = "ctx-lh-parstriangularis";
nameTable["1021"] = "ctx-lh-pericalcarine";
nameTable["1022"] = "ctx-lh-postcentral";
nameTable["1023"] = "ctx-lh-posteriorcingulate";
nameTable["1024"] = "ctx-lh-precentral";
nameTable["1025"] = "ctx-lh-precuneus";
nameTable["1026"] = "ctx-lh-rostralanteriorcingulate";
nameTable["1027"] = "ctx-lh-rostralmiddlefrontal";
nameTable["1028"] = "ctx-lh-superiorfrontal";
nameTable["1029"] = "ctx-lh-superiorparietal";
nameTable["1030"] = "ctx-lh-superiortemporal";
nameTable["1031"] = "ctx-lh-supramarginal";
nameTable["1032"] = "ctx-lh-frontalpole";
nameTable["1033"] = "ctx-lh-temporalpole";
nameTable["1034"] = "ctx-lh-transversetemporal";
nameTable["1035"] = "ctx-lh-insula";
nameTable["2000"] = "ctx-rh-unknown";
nameTable["2001"] = "ctx-rh-bankssts";
nameTable["2002"] = "ctx-rh-caudalanteriorcingulate";
nameTable["2003"] = "ctx-rh-caudalmiddlefrontal";
nameTable["2004"] = "ctx-rh-corpuscallosum";
nameTable["2005"] = "ctx-rh-cuneus";
nameTable["2006"] = "ctx-rh-entorhinal";
nameTable["2007"] = "ctx-rh-fusiform";
nameTable["2008"] = "ctx-rh-inferiorparietal";
nameTable["2009"] = "ctx-rh-inferiortemporal";
nameTable["2010"] = "ctx-rh-isthmuscingulate";
nameTable["2011"] = "ctx-rh-lateraloccipital";
nameTable["2012"] = "ctx-rh-lateralorbitofrontal";
nameTable["2013"] = "ctx-rh-lingual";
nameTable["2014"] = "ctx-rh-medialorbitofrontal";
nameTable["2015"] = "ctx-rh-middletemporal";
nameTable["2016"] = "ctx-rh-parahippocampal";
nameTable["2017"] = "ctx-rh-paracentral";
nameTable["2018"] = "ctx-rh-parsopercularis";
nameTable["2019"] = "ctx-rh-parsorbitalis";
nameTable["2020"] = "ctx-rh-parstriangularis";
nameTable["2021"] = "ctx-rh-pericalcarine";
nameTable["2022"] = "ctx-rh-postcentral";
nameTable["2023"] = "ctx-rh-posteriorcingulate";
nameTable["2024"] = "ctx-rh-precentral";
nameTable["2025"] = "ctx-rh-precuneus";
nameTable["2026"] = "ctx-rh-rostralanteriorcingulate";
nameTable["2027"] = "ctx-rh-rostralmiddlefrontal";
nameTable["2028"] = "ctx-rh-superiorfrontal";
nameTable["2029"] = "ctx-rh-superiorparietal";
nameTable["2030"] = "ctx-rh-superiortemporal";
nameTable["2031"] = "ctx-rh-supramarginal";
nameTable["2032"] = "ctx-rh-frontalpole";
nameTable["2033"] = "ctx-rh-temporalpole";
nameTable["2034"] = "ctx-rh-transversetemporal";
nameTable["2035"] = "ctx-rh-insula";
nameTable["3000"] = "wm-lh-unknown";
nameTable["3001"] = "wm-lh-bankssts";
nameTable["3002"] = "wm-lh-caudalanteriorcingulate";
nameTable["3003"] = "wm-lh-caudalmiddlefrontal";
nameTable["3004"] = "wm-lh-corpuscallosum";
nameTable["3005"] = "wm-lh-cuneus";
nameTable["3006"] = "wm-lh-entorhinal";
nameTable["3007"] = "wm-lh-fusiform";
nameTable["3008"] = "wm-lh-inferiorparietal";
nameTable["3009"] = "wm-lh-inferiortemporal";
nameTable["3010"] = "wm-lh-isthmuscingulate";
nameTable["3011"] = "wm-lh-lateraloccipital";
nameTable["3012"] = "wm-lh-lateralorbitofrontal";
nameTable["3013"] = "wm-lh-lingual";
nameTable["3014"] = "wm-lh-medialorbitofrontal";
nameTable["3015"] = "wm-lh-middletemporal";
nameTable["3016"] = "wm-lh-parahippocampal";
nameTable["3017"] = "wm-lh-paracentral";
nameTable["3018"] = "wm-lh-parsopercularis";
nameTable["3019"] = "wm-lh-parsorbitalis";
nameTable["3020"] = "wm-lh-parstriangularis";
nameTable["3021"] = "wm-lh-pericalcarine";
nameTable["3022"] = "wm-lh-postcentral";
nameTable["3023"] = "wm-lh-posteriorcingulate";
nameTable["3024"] = "wm-lh-precentral";
nameTable["3025"] = "wm-lh-precuneus";
nameTable["3026"] = "wm-lh-rostralanteriorcingulate";
nameTable["3027"] = "wm-lh-rostralmiddlefrontal";
nameTable["3028"] = "wm-lh-superiorfrontal";
nameTable["3029"] = "wm-lh-superiorparietal";
nameTable["3030"] = "wm-lh-superiortemporal";
nameTable["3031"] = "wm-lh-supramarginal";
nameTable["3032"] = "wm-lh-frontalpole";
nameTable["3033"] = "wm-lh-temporalpole";
nameTable["3034"] = "wm-lh-transversetemporal";
nameTable["3035"] = "wm-lh-insula";
nameTable["4000"] = "wm-rh-unknown";
nameTable["4001"] = "wm-rh-bankssts";
nameTable["4002"] = "wm-rh-caudalanteriorcingulate";
nameTable["4003"] = "wm-rh-caudalmiddlefrontal";
nameTable["4004"] = "wm-rh-corpuscallosum";
nameTable["4005"] = "wm-rh-cuneus";
nameTable["4006"] = "wm-rh-entorhinal";
nameTable["4007"] = "wm-rh-fusiform";
nameTable["4008"] = "wm-rh-inferiorparietal";
nameTable["4009"] = "wm-rh-inferiortemporal";
nameTable["4010"] = "wm-rh-isthmuscingulate";
nameTable["4011"] = "wm-rh-lateraloccipital";
nameTable["4012"] = "wm-rh-lateralorbitofrontal";
nameTable["4013"] = "wm-rh-lingual";
nameTable["4014"] = "wm-rh-medialorbitofrontal";
nameTable["4015"] = "wm-rh-middletemporal";
nameTable["4016"] = "wm-rh-parahippocampal";
nameTable["4017"] = "wm-rh-paracentral";
nameTable["4018"] = "wm-rh-parsopercularis";
nameTable["4019"] = "wm-rh-parsorbitalis";
nameTable["4020"] = "wm-rh-parstriangularis";
nameTable["4021"] = "wm-rh-pericalcarine";
nameTable["4022"] = "wm-rh-postcentral";
nameTable["4023"] = "wm-rh-posteriorcingulate";
nameTable["4024"] = "wm-rh-precentral";
nameTable["4025"] = "wm-rh-precuneus";
nameTable["4026"] = "wm-rh-rostralanteriorcingulate";
nameTable["4027"] = "wm-rh-rostralmiddlefrontal";
nameTable["4028"] = "wm-rh-superiorfrontal";
nameTable["4029"] = "wm-rh-superiorparietal";
nameTable["4030"] = "wm-rh-superiortemporal";
nameTable["4031"] = "wm-rh-supramarginal";
nameTable["4032"] = "wm-rh-frontalpole";
nameTable["4033"] = "wm-rh-temporalpole";
nameTable["4034"] = "wm-rh-transversetemporal";
nameTable["4035"] = "wm-rh-insula";
nameTable["1100"] = "ctx-lh-Unknown";
nameTable["1101"] = "ctx-lh-Corpus_callosum";
nameTable["1102"] = "ctx-lh-G_and_S_Insula_ONLY_AVERAGE";
nameTable["1103"] = "ctx-lh-G_cingulate-Isthmus";
nameTable["1104"] = "ctx-lh-G_cingulate-Main_part";
nameTable["1200"] = "ctx-lh-G_cingulate-caudal_ACC";
nameTable["1201"] = "ctx-lh-G_cingulate-rostral_ACC";
nameTable["1202"] = "ctx-lh-G_cingulate-posterior";
nameTable["1205"] = "ctx-lh-S_cingulate-caudal_ACC";
nameTable["1206"] = "ctx-lh-S_cingulate-rostral_ACC";
nameTable["1207"] = "ctx-lh-S_cingulate-posterior";
nameTable["1210"] = "ctx-lh-S_pericallosal-caudal";
nameTable["1211"] = "ctx-lh-S_pericallosal-rostral";
nameTable["1212"] = "ctx-lh-S_pericallosal-posterior";
nameTable["1105"] = "ctx-lh-G_cuneus";
nameTable["1106"] = "ctx-lh-G_frontal_inf-Opercular_part";
nameTable["1107"] = "ctx-lh-G_frontal_inf-Orbital_part";
nameTable["1108"] = "ctx-lh-G_frontal_inf-Triangular_part";
nameTable["1109"] = "ctx-lh-G_frontal_middle";
nameTable["1110"] = "ctx-lh-G_frontal_superior";
nameTable["1111"] = "ctx-lh-G_frontomarginal";
nameTable["1112"] = "ctx-lh-G_insular_long";
nameTable["1113"] = "ctx-lh-G_insular_short";
nameTable["1114"] = "ctx-lh-G_and_S_occipital_inferior";
nameTable["1115"] = "ctx-lh-G_occipital_middle";
nameTable["1116"] = "ctx-lh-G_occipital_superior";
nameTable["1117"] = "ctx-lh-G_occipit-temp_lat-Or_fusiform";
nameTable["1118"] = "ctx-lh-G_occipit-temp_med-Lingual_part";
nameTable["1119"] = "ctx-lh-G_occipit-temp_med-Parahippocampal_part";
nameTable["1120"] = "ctx-lh-G_orbital";
nameTable["1121"] = "ctx-lh-G_paracentral";
nameTable["1122"] = "ctx-lh-G_parietal_inferior-Angular_part";
nameTable["1123"] = "ctx-lh-G_parietal_inferior-Supramarginal_part";
nameTable["1124"] = "ctx-lh-G_parietal_superior";
nameTable["1125"] = "ctx-lh-G_postcentral";
nameTable["1126"] = "ctx-lh-G_precentral";
nameTable["1127"] = "ctx-lh-G_precuneus";
nameTable["1128"] = "ctx-lh-G_rectus";
nameTable["1129"] = "ctx-lh-G_subcallosal";
nameTable["1130"] = "ctx-lh-G_subcentral";
nameTable["1131"] = "ctx-lh-G_temporal_inferior";
nameTable["1132"] = "ctx-lh-G_temporal_middle";
nameTable["1133"] = "ctx-lh-G_temp_sup-G_temp_transv_and_interm_S";
nameTable["1134"] = "ctx-lh-G_temp_sup-Lateral_aspect";
nameTable["1135"] = "ctx-lh-G_temp_sup-Planum_polare";
nameTable["1136"] = "ctx-lh-G_temp_sup-Planum_tempolare";
nameTable["1137"] = "ctx-lh-G_and_S_transverse_frontopolar";
nameTable["1138"] = "ctx-lh-Lat_Fissure-ant_sgt-ramus_horizontal";
nameTable["1139"] = "ctx-lh-Lat_Fissure-ant_sgt-ramus_vertical";
nameTable["1140"] = "ctx-lh-Lat_Fissure-post_sgt";
nameTable["1141"] = "ctx-lh-Medial_wall";
nameTable["1142"] = "ctx-lh-Pole_occipital";
nameTable["1143"] = "ctx-lh-Pole_temporal";
nameTable["1144"] = "ctx-lh-S_calcarine";
nameTable["1145"] = "ctx-lh-S_central";
nameTable["1146"] = "ctx-lh-S_central_insula";
nameTable["1147"] = "ctx-lh-S_cingulate-Main_part_and_Intracingulate";
nameTable["1148"] = "ctx-lh-S_cingulate-Marginalis_part";
nameTable["1149"] = "ctx-lh-S_circular_insula_anterior";
nameTable["1150"] = "ctx-lh-S_circular_insula_inferior";
nameTable["1151"] = "ctx-lh-S_circular_insula_superior";
nameTable["1152"] = "ctx-lh-S_collateral_transverse_ant";
nameTable["1153"] = "ctx-lh-S_collateral_transverse_post";
nameTable["1154"] = "ctx-lh-S_frontal_inferior";
nameTable["1155"] = "ctx-lh-S_frontal_middle";
nameTable["1156"] = "ctx-lh-S_frontal_superior";
nameTable["1157"] = "ctx-lh-S_frontomarginal";
nameTable["1158"] = "ctx-lh-S_intermedius_primus-Jensen";
nameTable["1159"] = "ctx-lh-S_intraparietal-and_Parietal_transverse";
nameTable["1160"] = "ctx-lh-S_occipital_anterior";
nameTable["1161"] = "ctx-lh-S_occipital_middle_and_Lunatus";
nameTable["1162"] = "ctx-lh-S_occipital_superior_and_transversalis";
nameTable["1163"] = "ctx-lh-S_occipito-temporal_lateral";
nameTable["1164"] = "ctx-lh-S_occipito-temporal_medial_and_S_Lingual";
nameTable["1165"] = "ctx-lh-S_orbital-H_shapped";
nameTable["1166"] = "ctx-lh-S_orbital_lateral";
nameTable["1167"] = "ctx-lh-S_orbital_medial-Or_olfactory";
nameTable["1168"] = "ctx-lh-S_paracentral";
nameTable["1169"] = "ctx-lh-S_parieto_occipital";
nameTable["1170"] = "ctx-lh-S_pericallosal";
nameTable["1171"] = "ctx-lh-S_postcentral";
nameTable["1172"] = "ctx-lh-S_precentral-Inferior-part";
nameTable["1173"] = "ctx-lh-S_precentral-Superior-part";
nameTable["1174"] = "ctx-lh-S_subcentral_ant";
nameTable["1175"] = "ctx-lh-S_subcentral_post";
nameTable["1176"] = "ctx-lh-S_suborbital";
nameTable["1177"] = "ctx-lh-S_subparietal";
nameTable["1178"] = "ctx-lh-S_supracingulate";
nameTable["1179"] = "ctx-lh-S_temporal_inferior";
nameTable["1180"] = "ctx-lh-S_temporal_superior";
nameTable["1181"] = "ctx-lh-S_temporal_transverse";
nameTable["2100"] = "ctx-rh-Unknown";
nameTable["2101"] = "ctx-rh-Corpus_callosum";
nameTable["2102"] = "ctx-rh-G_and_S_Insula_ONLY_AVERAGE";
nameTable["2103"] = "ctx-rh-G_cingulate-Isthmus";
nameTable["2104"] = "ctx-rh-G_cingulate-Main_part";
nameTable["2105"] = "ctx-rh-G_cuneus";
nameTable["2106"] = "ctx-rh-G_frontal_inf-Opercular_part";
nameTable["2107"] = "ctx-rh-G_frontal_inf-Orbital_part";
nameTable["2108"] = "ctx-rh-G_frontal_inf-Triangular_part";
nameTable["2109"] = "ctx-rh-G_frontal_middle";
nameTable["2110"] = "ctx-rh-G_frontal_superior";
nameTable["2111"] = "ctx-rh-G_frontomarginal";
nameTable["2112"] = "ctx-rh-G_insular_long";
nameTable["2113"] = "ctx-rh-G_insular_short";
nameTable["2114"] = "ctx-rh-G_and_S_occipital_inferior";
nameTable["2115"] = "ctx-rh-G_occipital_middle";
nameTable["2116"] = "ctx-rh-G_occipital_superior";
nameTable["2117"] = "ctx-rh-G_occipit-temp_lat-Or_fusiform";
nameTable["2118"] = "ctx-rh-G_occipit-temp_med-Lingual_part";
nameTable["2119"] = "ctx-rh-G_occipit-temp_med-Parahippocampal_part";
nameTable["2120"] = "ctx-rh-G_orbital";
nameTable["2121"] = "ctx-rh-G_paracentral";
nameTable["2122"] = "ctx-rh-G_parietal_inferior-Angular_part";
nameTable["2123"] = "ctx-rh-G_parietal_inferior-Supramarginal_part";
nameTable["2124"] = "ctx-rh-G_parietal_superior";
nameTable["2125"] = "ctx-rh-G_postcentral";
nameTable["2126"] = "ctx-rh-G_precentral";
nameTable["2127"] = "ctx-rh-G_precuneus";
nameTable["2128"] = "ctx-rh-G_rectus";
nameTable["2129"] = "ctx-rh-G_subcallosal";
nameTable["2130"] = "ctx-rh-G_subcentral";
nameTable["2131"] = "ctx-rh-G_temporal_inferior";
nameTable["2132"] = "ctx-rh-G_temporal_middle";
nameTable["2133"] = "ctx-rh-G_temp_sup-G_temp_transv_and_interm_S";
nameTable["2134"] = "ctx-rh-G_temp_sup-Lateral_aspect";
nameTable["2135"] = "ctx-rh-G_temp_sup-Planum_polare";
nameTable["2136"] = "ctx-rh-G_temp_sup-Planum_tempolare";
nameTable["2137"] = "ctx-rh-G_and_S_transverse_frontopolar";
nameTable["2138"] = "ctx-rh-Lat_Fissure-ant_sgt-ramus_horizontal";
nameTable["2139"] = "ctx-rh-Lat_Fissure-ant_sgt-ramus_vertical";
nameTable["2140"] = "ctx-rh-Lat_Fissure-post_sgt";
nameTable["2141"] = "ctx-rh-Medial_wall";
nameTable["2142"] = "ctx-rh-Pole_occipital";
nameTable["2143"] = "ctx-rh-Pole_temporal";
nameTable["2144"] = "ctx-rh-S_calcarine";
nameTable["2145"] = "ctx-rh-S_central";
nameTable["2146"] = "ctx-rh-S_central_insula";
nameTable["2147"] = "ctx-rh-S_cingulate-Main_part_and_Intracingulate";
nameTable["2148"] = "ctx-rh-S_cingulate-Marginalis_part";
nameTable["2149"] = "ctx-rh-S_circular_insula_anterior";
nameTable["2150"] = "ctx-rh-S_circular_insula_inferior";
nameTable["2151"] = "ctx-rh-S_circular_insula_superior";
nameTable["2152"] = "ctx-rh-S_collateral_transverse_ant";
nameTable["2153"] = "ctx-rh-S_collateral_transverse_post";
nameTable["2154"] = "ctx-rh-S_frontal_inferior";
nameTable["2155"] = "ctx-rh-S_frontal_middle";
nameTable["2156"] = "ctx-rh-S_frontal_superior";
nameTable["2157"] = "ctx-rh-S_frontomarginal";
nameTable["2158"] = "ctx-rh-S_intermedius_primus-Jensen";
nameTable["2159"] = "ctx-rh-S_intraparietal-and_Parietal_transverse";
nameTable["2160"] = "ctx-rh-S_occipital_anterior";
nameTable["2161"] = "ctx-rh-S_occipital_middle_and_Lunatus";
nameTable["2162"] = "ctx-rh-S_occipital_superior_and_transversalis";
nameTable["2163"] = "ctx-rh-S_occipito-temporal_lateral";
nameTable["2164"] = "ctx-rh-S_occipito-temporal_medial_and_S_Lingual";
nameTable["2165"] = "ctx-rh-S_orbital-H_shapped";
nameTable["2166"] = "ctx-rh-S_orbital_lateral";
nameTable["2167"] = "ctx-rh-S_orbital_medial-Or_olfactory";
nameTable["2168"] = "ctx-rh-S_paracentral";
nameTable["2169"] = "ctx-rh-S_parieto_occipital";
nameTable["2170"] = "ctx-rh-S_pericallosal";
nameTable["2171"] = "ctx-rh-S_postcentral";
nameTable["2172"] = "ctx-rh-S_precentral-Inferior-part";
nameTable["2173"] = "ctx-rh-S_precentral-Superior-part";
nameTable["2174"] = "ctx-rh-S_subcentral_ant";
nameTable["2175"] = "ctx-rh-S_subcentral_post";
nameTable["2176"] = "ctx-rh-S_suborbital";
nameTable["2177"] = "ctx-rh-S_subparietal";
nameTable["2178"] = "ctx-rh-S_supracingulate";
nameTable["2179"] = "ctx-rh-S_temporal_inferior";
nameTable["2180"] = "ctx-rh-S_temporal_superior";
nameTable["2181"] = "ctx-rh-S_temporal_transverse";
nameTable["2200"] = "ctx-rh-G_cingulate-caudal_ACC";
nameTable["2201"] = "ctx-rh-G_cingulate-rostral_ACC";
nameTable["2202"] = "ctx-rh-G_cingulate-posterior";
nameTable["2205"] = "ctx-rh-S_cingulate-caudal_ACC";
nameTable["2206"] = "ctx-rh-S_cingulate-rostral_ACC";
nameTable["2207"] = "ctx-rh-S_cingulate-posterior";
nameTable["2210"] = "ctx-rh-S_pericallosal-caudal";
nameTable["2211"] = "ctx-rh-S_pericallosal-rostral";
nameTable["2212"] = "ctx-rh-S_pericallosal-posterior";
nameTable["3100"] = "wm-lh-Unknown";
nameTable["3101"] = "wm-lh-Corpus_callosum";
nameTable["3102"] = "wm-lh-G_and_S_Insula_ONLY_AVERAGE";
nameTable["3103"] = "wm-lh-G_cingulate-Isthmus";
nameTable["3104"] = "wm-lh-G_cingulate-Main_part";
nameTable["3105"] = "wm-lh-G_cuneus";
nameTable["3106"] = "wm-lh-G_frontal_inf-Opercular_part";
nameTable["3107"] = "wm-lh-G_frontal_inf-Orbital_part";
nameTable["3108"] = "wm-lh-G_frontal_inf-Triangular_part";
nameTable["3109"] = "wm-lh-G_frontal_middle";
nameTable["3110"] = "wm-lh-G_frontal_superior";
nameTable["3111"] = "wm-lh-G_frontomarginal";
nameTable["3112"] = "wm-lh-G_insular_long";
nameTable["3113"] = "wm-lh-G_insular_short";
nameTable["3114"] = "wm-lh-G_and_S_occipital_inferior";
nameTable["3115"] = "wm-lh-G_occipital_middle";
nameTable["3116"] = "wm-lh-G_occipital_superior";
nameTable["3117"] = "wm-lh-G_occipit-temp_lat-Or_fusiform";
nameTable["3118"] = "wm-lh-G_occipit-temp_med-Lingual_part";
nameTable["3119"] = "wm-lh-G_occipit-temp_med-Parahippocampal_part";
nameTable["3120"] = "wm-lh-G_orbital";
nameTable["3121"] = "wm-lh-G_paracentral";
nameTable["3122"] = "wm-lh-G_parietal_inferior-Angular_part";
nameTable["3123"] = "wm-lh-G_parietal_inferior-Supramarginal_part";
nameTable["3124"] = "wm-lh-G_parietal_superior";
nameTable["3125"] = "wm-lh-G_postcentral";
nameTable["3126"] = "wm-lh-G_precentral";
nameTable["3127"] = "wm-lh-G_precuneus";
nameTable["3128"] = "wm-lh-G_rectus";
nameTable["3129"] = "wm-lh-G_subcallosal";
nameTable["3130"] = "wm-lh-G_subcentral";
nameTable["3131"] = "wm-lh-G_temporal_inferior";
nameTable["3132"] = "wm-lh-G_temporal_middle";
nameTable["3133"] = "wm-lh-G_temp_sup-G_temp_transv_and_interm_S";
nameTable["3134"] = "wm-lh-G_temp_sup-Lateral_aspect";
nameTable["3135"] = "wm-lh-G_temp_sup-Planum_polare";
nameTable["3136"] = "wm-lh-G_temp_sup-Planum_tempolare";
nameTable["3137"] = "wm-lh-G_and_S_transverse_frontopolar";
nameTable["3138"] = "wm-lh-Lat_Fissure-ant_sgt-ramus_horizontal";
nameTable["3139"] = "wm-lh-Lat_Fissure-ant_sgt-ramus_vertical";
nameTable["3140"] = "wm-lh-Lat_Fissure-post_sgt";
nameTable["3141"] = "wm-lh-Medial_wall";
nameTable["3142"] = "wm-lh-Pole_occipital";
nameTable["3143"] = "wm-lh-Pole_temporal";
nameTable["3144"] = "wm-lh-S_calcarine";
nameTable["3145"] = "wm-lh-S_central";
nameTable["3146"] = "wm-lh-S_central_insula";
nameTable["3147"] = "wm-lh-S_cingulate-Main_part_and_Intracingulate";
nameTable["3148"] = "wm-lh-S_cingulate-Marginalis_part";
nameTable["3149"] = "wm-lh-S_circular_insula_anterior";
nameTable["3150"] = "wm-lh-S_circular_insula_inferior";
nameTable["3151"] = "wm-lh-S_circular_insula_superior";
nameTable["3152"] = "wm-lh-S_collateral_transverse_ant";
nameTable["3153"] = "wm-lh-S_collateral_transverse_post";
nameTable["3154"] = "wm-lh-S_frontal_inferior";
nameTable["3155"] = "wm-lh-S_frontal_middle";
nameTable["3156"] = "wm-lh-S_frontal_superior";
nameTable["3157"] = "wm-lh-S_frontomarginal";
nameTable["3158"] = "wm-lh-S_intermedius_primus-Jensen";
nameTable["3159"] = "wm-lh-S_intraparietal-and_Parietal_transverse";
nameTable["3160"] = "wm-lh-S_occipital_anterior";
nameTable["3161"] = "wm-lh-S_occipital_middle_and_Lunatus";
nameTable["3162"] = "wm-lh-S_occipital_superior_and_transversalis";
nameTable["3163"] = "wm-lh-S_occipito-temporal_lateral";
nameTable["3164"] = "wm-lh-S_occipito-temporal_medial_and_S_Lingual";
nameTable["3165"] = "wm-lh-S_orbital-H_shapped";
nameTable["3166"] = "wm-lh-S_orbital_lateral";
nameTable["3167"] = "wm-lh-S_orbital_medial-Or_olfactory";
nameTable["3168"] = "wm-lh-S_paracentral";
nameTable["3169"] = "wm-lh-S_parieto_occipital";
nameTable["3170"] = "wm-lh-S_pericallosal";
nameTable["3171"] = "wm-lh-S_postcentral";
nameTable["3172"] = "wm-lh-S_precentral-Inferior-part";
nameTable["3173"] = "wm-lh-S_precentral-Superior-part";
nameTable["3174"] = "wm-lh-S_subcentral_ant";
nameTable["3175"] = "wm-lh-S_subcentral_post";
nameTable["3176"] = "wm-lh-S_suborbital";
nameTable["3177"] = "wm-lh-S_subparietal";
nameTable["3178"] = "wm-lh-S_supracingulate";
nameTable["3179"] = "wm-lh-S_temporal_inferior";
nameTable["3180"] = "wm-lh-S_temporal_superior";
nameTable["3181"] = "wm-lh-S_temporal_transverse";
nameTable["4100"] = "wm-rh-Unknown";
nameTable["4101"] = "wm-rh-Corpus_callosum";
nameTable["4102"] = "wm-rh-G_and_S_Insula_ONLY_AVERAGE";
nameTable["4103"] = "wm-rh-G_cingulate-Isthmus";
nameTable["4104"] = "wm-rh-G_cingulate-Main_part";
nameTable["4105"] = "wm-rh-G_cuneus";
nameTable["4106"] = "wm-rh-G_frontal_inf-Opercular_part";
nameTable["4107"] = "wm-rh-G_frontal_inf-Orbital_part";
nameTable["4108"] = "wm-rh-G_frontal_inf-Triangular_part";
nameTable["4109"] = "wm-rh-G_frontal_middle";
nameTable["4110"] = "wm-rh-G_frontal_superior";
nameTable["4111"] = "wm-rh-G_frontomarginal";
nameTable["4112"] = "wm-rh-G_insular_long";
nameTable["4113"] = "wm-rh-G_insular_short";
nameTable["4114"] = "wm-rh-G_and_S_occipital_inferior";
nameTable["4115"] = "wm-rh-G_occipital_middle";
nameTable["4116"] = "wm-rh-G_occipital_superior";
nameTable["4117"] = "wm-rh-G_occipit-temp_lat-Or_fusiform";
nameTable["4118"] = "wm-rh-G_occipit-temp_med-Lingual_part";
nameTable["4119"] = "wm-rh-G_occipit-temp_med-Parahippocampal_part";
nameTable["4120"] = "wm-rh-G_orbital";
nameTable["4121"] = "wm-rh-G_paracentral";
nameTable["4122"] = "wm-rh-G_parietal_inferior-Angular_part";
nameTable["4123"] = "wm-rh-G_parietal_inferior-Supramarginal_part";
nameTable["4124"] = "wm-rh-G_parietal_superior";
nameTable["4125"] = "wm-rh-G_postcentral";
nameTable["4126"] = "wm-rh-G_precentral";
nameTable["4127"] = "wm-rh-G_precuneus";
nameTable["4128"] = "wm-rh-G_rectus";
nameTable["4129"] = "wm-rh-G_subcallosal";
nameTable["4130"] = "wm-rh-G_subcentral";
nameTable["4131"] = "wm-rh-G_temporal_inferior";
nameTable["4132"] = "wm-rh-G_temporal_middle";
nameTable["4133"] = "wm-rh-G_temp_sup-G_temp_transv_and_interm_S";
nameTable["4134"] = "wm-rh-G_temp_sup-Lateral_aspect";
nameTable["4135"] = "wm-rh-G_temp_sup-Planum_polare";
nameTable["4136"] = "wm-rh-G_temp_sup-Planum_tempolare";
nameTable["4137"] = "wm-rh-G_and_S_transverse_frontopolar";
nameTable["4138"] = "wm-rh-Lat_Fissure-ant_sgt-ramus_horizontal";
nameTable["4139"] = "wm-rh-Lat_Fissure-ant_sgt-ramus_vertical";
nameTable["4140"] = "wm-rh-Lat_Fissure-post_sgt";
nameTable["4141"] = "wm-rh-Medial_wall";
nameTable["4142"] = "wm-rh-Pole_occipital";
nameTable["4143"] = "wm-rh-Pole_temporal";
nameTable["4144"] = "wm-rh-S_calcarine";
nameTable["4145"] = "wm-rh-S_central";
nameTable["4146"] = "wm-rh-S_central_insula";
nameTable["4147"] = "wm-rh-S_cingulate-Main_part_and_Intracingulate";
nameTable["4148"] = "wm-rh-S_cingulate-Marginalis_part";
nameTable["4149"] = "wm-rh-S_circular_insula_anterior";
nameTable["4150"] = "wm-rh-S_circular_insula_inferior";
nameTable["4151"] = "wm-rh-S_circular_insula_superior";
nameTable["4152"] = "wm-rh-S_collateral_transverse_ant";
nameTable["4153"] = "wm-rh-S_collateral_transverse_post";
nameTable["4154"] = "wm-rh-S_frontal_inferior";
nameTable["4155"] = "wm-rh-S_frontal_middle";
nameTable["4156"] = "wm-rh-S_frontal_superior";
nameTable["4157"] = "wm-rh-S_frontomarginal";
nameTable["4158"] = "wm-rh-S_intermedius_primus-Jensen";
nameTable["4159"] = "wm-rh-S_intraparietal-and_Parietal_transverse";
nameTable["4160"] = "wm-rh-S_occipital_anterior";
nameTable["4161"] = "wm-rh-S_occipital_middle_and_Lunatus";
nameTable["4162"] = "wm-rh-S_occipital_superior_and_transversalis";
nameTable["4163"] = "wm-rh-S_occipito-temporal_lateral";
nameTable["4164"] = "wm-rh-S_occipito-temporal_medial_and_S_Lingual";
nameTable["4165"] = "wm-rh-S_orbital-H_shapped";
nameTable["4166"] = "wm-rh-S_orbital_lateral";
nameTable["4167"] = "wm-rh-S_orbital_medial-Or_olfactory";
nameTable["4168"] = "wm-rh-S_paracentral";
nameTable["4169"] = "wm-rh-S_parieto_occipital";
nameTable["4170"] = "wm-rh-S_pericallosal";
nameTable["4171"] = "wm-rh-S_postcentral";
nameTable["4172"] = "wm-rh-S_precentral-Inferior-part";
nameTable["4173"] = "wm-rh-S_precentral-Superior-part";
nameTable["4174"] = "wm-rh-S_subcentral_ant";
nameTable["4175"] = "wm-rh-S_subcentral_post";
nameTable["4176"] = "wm-rh-S_suborbital";
nameTable["4177"] = "wm-rh-S_subparietal";
nameTable["4178"] = "wm-rh-S_supracingulate";
nameTable["4179"] = "wm-rh-S_temporal_inferior";
nameTable["4180"] = "wm-rh-S_temporal_superior";
nameTable["4181"] = "wm-rh-S_temporal_transverse";
nameTable["5001"] = "Left-UnsegmentedWhiteMatter";
nameTable["5002"] = "Right-UnsegmentedWhiteMatter";
nameTable["5100"] = "fmajor";
nameTable["5101"] = "fminor";
nameTable["5102"] = "lh.atr";
nameTable["5103"] = "lh.cab";
nameTable["5104"] = "lh.ccg";
nameTable["5105"] = "lh.cst";
nameTable["5106"] = "lh.ilf";
nameTable["5107"] = "lh.slfp";
nameTable["5108"] = "lh.slft";
nameTable["5109"] = "lh.unc";
nameTable["5110"] = "rh.atr";
nameTable["5111"] = "rh.cab";
nameTable["5112"] = "rh.ccg";
nameTable["5113"] = "rh.cst";
nameTable["5114"] = "rh.ilf";
nameTable["5115"] = "rh.slfp";
nameTable["5116"] = "rh.slft";
nameTable["5117"] = "rh.unc";
nameTable["5200"] = "CC-ForcepsMajor";
nameTable["5201"] = "CC-ForcepsMinor";
nameTable["5202"] = "LAntThalRadiation";
nameTable["5203"] = "LCingulumAngBundle";
nameTable["5204"] = "LCingulumCingGyrus";
nameTable["5205"] = "LCorticospinalTract";
nameTable["5206"] = "LInfLongFas";
nameTable["5207"] = "LSupLongFasParietal";
nameTable["5208"] = "LSupLongFasTemporal";
nameTable["5209"] = "LUncinateFas";
nameTable["5210"] = "RAntThalRadiation";
nameTable["5211"] = "RCingulumAngBundle";
nameTable["5212"] = "RCingulumCingGyrus";
nameTable["5213"] = "RCorticospinalTract";
nameTable["5214"] = "RInfLongFas";
nameTable["5215"] = "RSupLongFasParietal";
nameTable["5216"] = "RSupLongFasTemporal";
nameTable["5217"] = "RUncinateFas";
nameTable["6000"] = "CST-orig";
nameTable["6001"] = "CST-hammer";
nameTable["6002"] = "CST-CVS";
nameTable["6003"] = "CST-flirt";
nameTable["6010"] = "Left-SLF1";
nameTable["6020"] = "Right-SLF1";
nameTable["6030"] = "Left-SLF3";
nameTable["6040"] = "Right-SLF3";
nameTable["6050"] = "Left-CST";
nameTable["6060"] = "Right-CST";
nameTable["6070"] = "Left-SLF2";
nameTable["6080"] = "Right-SLF2";
nameTable["7001"] = "Lateral-nucleus";
nameTable["7002"] = "Basolateral-nucleus";
nameTable["7003"] = "Basal-nucleus";
nameTable["7004"] = "Centromedial-nucleus";
nameTable["7005"] = "Central-nucleus";
nameTable["7006"] = "Medial-nucleus";
nameTable["7007"] = "Cortical-nucleus";
nameTable["7008"] = "Accessory-Basal-nucleus";
nameTable["7009"] = "Corticoamygdaloid-transitio";
nameTable["7010"] = "Anterior-amygdaloid-area-AAA";
nameTable["7011"] = "Fusion-amygdala-HP-FAH";
nameTable["7012"] = "Hippocampal-amygdala-transition-HATA";
nameTable["7013"] = "Endopiriform-nucleus";
nameTable["7014"] = "Lateral-nucleus-olfactory-tract";
nameTable["7015"] = "Paralaminar-nucleus";
nameTable["7016"] = "Intercalated-nucleus";
nameTable["7017"] = "Prepiriform-cortex";
nameTable["7018"] = "Periamygdaloid-cortex";
nameTable["7019"] = "Envelope-Amygdala";
nameTable["7020"] = "Extranuclear-Amydala";
nameTable["7100"] = "Brainstem-inferior-colliculus";
nameTable["7101"] = "Brainstem-cochlear-nucleus";
nameTable["8001"] = "Thalamus-Anterior";
nameTable["8002"] = "Thalamus-Ventral-anterior";
nameTable["8003"] = "Thalamus-Lateral-dorsal";
nameTable["8004"] = "Thalamus-Lateral-posterior";
nameTable["8005"] = "Thalamus-Ventral-lateral";
nameTable["8006"] = "Thalamus-Ventral-posterior-medial";
nameTable["8007"] = "Thalamus-Ventral-posterior-lateral";
nameTable["8008"] = "Thalamus-intralaminar";
nameTable["8009"] = "Thalamus-centromedian";
nameTable["8010"] = "Thalamus-mediodorsal";
nameTable["8011"] = "Thalamus-medial";
nameTable["8012"] = "Thalamus-pulvinar";
nameTable["8013"] = "Thalamus-lateral-geniculate";
nameTable["8014"] = "Thalamus-medial-geniculate";
nameTable["9000"] = "ctx-lh-prefrontal";
nameTable["9001"] = "ctx-lh-primary-motor";
nameTable["9002"] = "ctx-lh-premotor";
nameTable["9003"] = "ctx-lh-temporal";
nameTable["9004"] = "ctx-lh-posterior-parietal";
nameTable["9005"] = "ctx-lh-prim-sec-somatosensory";
nameTable["9006"] = "ctx-lh-occipital";
nameTable["9500"] = "ctx-rh-prefrontal";
nameTable["9501"] = "ctx-rh-primary-motor";
nameTable["9502"] = "ctx-rh-premotor";
nameTable["9503"] = "ctx-rh-temporal";
nameTable["9504"] = "ctx-rh-posterior-parietal";
nameTable["9505"] = "ctx-rh-prim-sec-somatosensory";
nameTable["9506"] = "ctx-rh-occipital";
nameTable["11100"] = "ctx_lh_Unknown";
nameTable["11101"] = "ctx_lh_G_and_S_frontomargin";
nameTable["11102"] = "ctx_lh_G_and_S_occipital_inf";
nameTable["11103"] = "ctx_lh_G_and_S_paracentral";
nameTable["11104"] = "ctx_lh_G_and_S_subcentral";
nameTable["11105"] = "ctx_lh_G_and_S_transv_frontopol";
nameTable["11106"] = "ctx_lh_G_and_S_cingul-Ant";
nameTable["11107"] = "ctx_lh_G_and_S_cingul-Mid-Ant";
nameTable["11108"] = "ctx_lh_G_and_S_cingul-Mid-Post";
nameTable["11109"] = "ctx_lh_G_cingul-Post-dorsal";
nameTable["11110"] = "ctx_lh_G_cingul-Post-ventral";
nameTable["11111"] = "ctx_lh_G_cuneus";
nameTable["11112"] = "ctx_lh_G_front_inf-Opercular";
nameTable["11113"] = "ctx_lh_G_front_inf-Orbital";
nameTable["11114"] = "ctx_lh_G_front_inf-Triangul";
nameTable["11115"] = "ctx_lh_G_front_middle";
nameTable["11116"] = "ctx_lh_G_front_sup";
nameTable["11117"] = "ctx_lh_G_Ins_lg_and_S_cent_ins";
nameTable["11118"] = "ctx_lh_G_insular_short";
nameTable["11119"] = "ctx_lh_G_occipital_middle";
nameTable["11120"] = "ctx_lh_G_occipital_sup";
nameTable["11121"] = "ctx_lh_G_oc-temp_lat-fusifor";
nameTable["11122"] = "ctx_lh_G_oc-temp_med-Lingual";
nameTable["11123"] = "ctx_lh_G_oc-temp_med-Parahip";
nameTable["11124"] = "ctx_lh_G_orbital";
nameTable["11125"] = "ctx_lh_G_pariet_inf-Angular";
nameTable["11126"] = "ctx_lh_G_pariet_inf-Supramar";
nameTable["11127"] = "ctx_lh_G_parietal_sup";
nameTable["11128"] = "ctx_lh_G_postcentral";
nameTable["11129"] = "ctx_lh_G_precentral";
nameTable["11130"] = "ctx_lh_G_precuneus";
nameTable["11131"] = "ctx_lh_G_rectus";
nameTable["11132"] = "ctx_lh_G_subcallosal";
nameTable["11133"] = "ctx_lh_G_temp_sup-G_T_transv";
nameTable["11134"] = "ctx_lh_G_temp_sup-Lateral";
nameTable["11135"] = "ctx_lh_G_temp_sup-Plan_polar";
nameTable["11136"] = "ctx_lh_G_temp_sup-Plan_tempo";
nameTable["11137"] = "ctx_lh_G_temporal_inf";
nameTable["11138"] = "ctx_lh_G_temporal_middle";
nameTable["11139"] = "ctx_lh_Lat_Fis-ant-Horizont";
nameTable["11140"] = "ctx_lh_Lat_Fis-ant-Vertical";
nameTable["11141"] = "ctx_lh_Lat_Fis-post";
nameTable["11142"] = "ctx_lh_Medial_wall";
nameTable["11143"] = "ctx_lh_Pole_occipital";
nameTable["11144"] = "ctx_lh_Pole_temporal";
nameTable["11145"] = "ctx_lh_S_calcarine";
nameTable["11146"] = "ctx_lh_S_central";
nameTable["11147"] = "ctx_lh_S_cingul-Marginalis";
nameTable["11148"] = "ctx_lh_S_circular_insula_ant";
nameTable["11149"] = "ctx_lh_S_circular_insula_inf";
nameTable["11150"] = "ctx_lh_S_circular_insula_sup";
nameTable["11151"] = "ctx_lh_S_collat_transv_ant";
nameTable["11152"] = "ctx_lh_S_collat_transv_post";
nameTable["11153"] = "ctx_lh_S_front_inf";
nameTable["11154"] = "ctx_lh_S_front_middle";
nameTable["11155"] = "ctx_lh_S_front_sup";
nameTable["11156"] = "ctx_lh_S_interm_prim-Jensen";
nameTable["11157"] = "ctx_lh_S_intrapariet_and_P_trans";
nameTable["11158"] = "ctx_lh_S_oc_middle_and_Lunatus";
nameTable["11159"] = "ctx_lh_S_oc_sup_and_transversal";
nameTable["11160"] = "ctx_lh_S_occipital_ant";
nameTable["11161"] = "ctx_lh_S_oc-temp_lat";
nameTable["11162"] = "ctx_lh_S_oc-temp_med_and_Lingual";
nameTable["11163"] = "ctx_lh_S_orbital_lateral";
nameTable["11164"] = "ctx_lh_S_orbital_med-olfact";
nameTable["11165"] = "ctx_lh_S_orbital-H_Shaped";
nameTable["11166"] = "ctx_lh_S_parieto_occipital";
nameTable["11167"] = "ctx_lh_S_pericallosal";
nameTable["11168"] = "ctx_lh_S_postcentral";
nameTable["11169"] = "ctx_lh_S_precentral-inf-part";
nameTable["11170"] = "ctx_lh_S_precentral-sup-part";
nameTable["11171"] = "ctx_lh_S_suborbital";
nameTable["11172"] = "ctx_lh_S_subparietal";
nameTable["11173"] = "ctx_lh_S_temporal_inf";
nameTable["11174"] = "ctx_lh_S_temporal_sup";
nameTable["11175"] = "ctx_lh_S_temporal_transverse";
nameTable["12100"] = "ctx_rh_Unknown";
nameTable["12101"] = "ctx_rh_G_and_S_frontomargin";
nameTable["12102"] = "ctx_rh_G_and_S_occipital_inf";
nameTable["12103"] = "ctx_rh_G_and_S_paracentral";
nameTable["12104"] = "ctx_rh_G_and_S_subcentral";
nameTable["12105"] = "ctx_rh_G_and_S_transv_frontopol";
nameTable["12106"] = "ctx_rh_G_and_S_cingul-Ant";
nameTable["12107"] = "ctx_rh_G_and_S_cingul-Mid-Ant";
nameTable["12108"] = "ctx_rh_G_and_S_cingul-Mid-Post";
nameTable["12109"] = "ctx_rh_G_cingul-Post-dorsal";
nameTable["12110"] = "ctx_rh_G_cingul-Post-ventral";
nameTable["12111"] = "ctx_rh_G_cuneus";
nameTable["12112"] = "ctx_rh_G_front_inf-Opercular";
nameTable["12113"] = "ctx_rh_G_front_inf-Orbital";
nameTable["12114"] = "ctx_rh_G_front_inf-Triangul";
nameTable["12115"] = "ctx_rh_G_front_middle";
nameTable["12116"] = "ctx_rh_G_front_sup";
nameTable["12117"] = "ctx_rh_G_Ins_lg_and_S_cent_ins";
nameTable["12118"] = "ctx_rh_G_insular_short";
nameTable["12119"] = "ctx_rh_G_occipital_middle";
nameTable["12120"] = "ctx_rh_G_occipital_sup";
nameTable["12121"] = "ctx_rh_G_oc-temp_lat-fusifor";
nameTable["12122"] = "ctx_rh_G_oc-temp_med-Lingual";
nameTable["12123"] = "ctx_rh_G_oc-temp_med-Parahip";
nameTable["12124"] = "ctx_rh_G_orbital";
nameTable["12125"] = "ctx_rh_G_pariet_inf-Angular";
nameTable["12126"] = "ctx_rh_G_pariet_inf-Supramar";
nameTable["12127"] = "ctx_rh_G_parietal_sup";
nameTable["12128"] = "ctx_rh_G_postcentral";
nameTable["12129"] = "ctx_rh_G_precentral";
nameTable["12130"] = "ctx_rh_G_precuneus";
nameTable["12131"] = "ctx_rh_G_rectus";
nameTable["12132"] = "ctx_rh_G_subcallosal";
nameTable["12133"] = "ctx_rh_G_temp_sup-G_T_transv";
nameTable["12134"] = "ctx_rh_G_temp_sup-Lateral";
nameTable["12135"] = "ctx_rh_G_temp_sup-Plan_polar";
nameTable["12136"] = "ctx_rh_G_temp_sup-Plan_tempo";
nameTable["12137"] = "ctx_rh_G_temporal_inf";
nameTable["12138"] = "ctx_rh_G_temporal_middle";
nameTable["12139"] = "ctx_rh_Lat_Fis-ant-Horizont";
nameTable["12140"] = "ctx_rh_Lat_Fis-ant-Vertical";
nameTable["12141"] = "ctx_rh_Lat_Fis-post";
nameTable["12142"] = "ctx_rh_Medial_wall";
nameTable["12143"] = "ctx_rh_Pole_occipital";
nameTable["12144"] = "ctx_rh_Pole_temporal";
nameTable["12145"] = "ctx_rh_S_calcarine";
nameTable["12146"] = "ctx_rh_S_central";
nameTable["12147"] = "ctx_rh_S_cingul-Marginalis";
nameTable["12148"] = "ctx_rh_S_circular_insula_ant";
nameTable["12149"] = "ctx_rh_S_circular_insula_inf";
nameTable["12150"] = "ctx_rh_S_circular_insula_sup";
nameTable["12151"] = "ctx_rh_S_collat_transv_ant";
nameTable["12152"] = "ctx_rh_S_collat_transv_post";
nameTable["12153"] = "ctx_rh_S_front_inf";
nameTable["12154"] = "ctx_rh_S_front_middle";
nameTable["12155"] = "ctx_rh_S_front_sup";
nameTable["12156"] = "ctx_rh_S_interm_prim-Jensen";
nameTable["12157"] = "ctx_rh_S_intrapariet_and_P_trans";
nameTable["12158"] = "ctx_rh_S_oc_middle_and_Lunatus";
nameTable["12159"] = "ctx_rh_S_oc_sup_and_transversal";
nameTable["12160"] = "ctx_rh_S_occipital_ant";
nameTable["12161"] = "ctx_rh_S_oc-temp_lat";
nameTable["12162"] = "ctx_rh_S_oc-temp_med_and_Lingual";
nameTable["12163"] = "ctx_rh_S_orbital_lateral";
nameTable["12164"] = "ctx_rh_S_orbital_med-olfact";
nameTable["12165"] = "ctx_rh_S_orbital-H_Shaped";
nameTable["12166"] = "ctx_rh_S_parieto_occipital";
nameTable["12167"] = "ctx_rh_S_pericallosal";
nameTable["12168"] = "ctx_rh_S_postcentral";
nameTable["12169"] = "ctx_rh_S_precentral-inf-part";
nameTable["12170"] = "ctx_rh_S_precentral-sup-part";
nameTable["12171"] = "ctx_rh_S_suborbital";
nameTable["12172"] = "ctx_rh_S_subparietal";
nameTable["12173"] = "ctx_rh_S_temporal_inf";
nameTable["12174"] = "ctx_rh_S_temporal_sup";
nameTable["12175"] = "ctx_rh_S_temporal_transverse";
nameTable["13100"] = "wm_lh_Unknown";
nameTable["13101"] = "wm_lh_G_and_S_frontomargin";
nameTable["13102"] = "wm_lh_G_and_S_occipital_inf";
nameTable["13103"] = "wm_lh_G_and_S_paracentral";
nameTable["13104"] = "wm_lh_G_and_S_subcentral";
nameTable["13105"] = "wm_lh_G_and_S_transv_frontopol";
nameTable["13106"] = "wm_lh_G_and_S_cingul-Ant";
nameTable["13107"] = "wm_lh_G_and_S_cingul-Mid-Ant";
nameTable["13108"] = "wm_lh_G_and_S_cingul-Mid-Post";
nameTable["13109"] = "wm_lh_G_cingul-Post-dorsal";
nameTable["13110"] = "wm_lh_G_cingul-Post-ventral";
nameTable["13111"] = "wm_lh_G_cuneus";
nameTable["13112"] = "wm_lh_G_front_inf-Opercular";
nameTable["13113"] = "wm_lh_G_front_inf-Orbital";
nameTable["13114"] = "wm_lh_G_front_inf-Triangul";
nameTable["13115"] = "wm_lh_G_front_middle";
nameTable["13116"] = "wm_lh_G_front_sup";
nameTable["13117"] = "wm_lh_G_Ins_lg_and_S_cent_ins";
nameTable["13118"] = "wm_lh_G_insular_short";
nameTable["13119"] = "wm_lh_G_occipital_middle";
nameTable["13120"] = "wm_lh_G_occipital_sup";
nameTable["13121"] = "wm_lh_G_oc-temp_lat-fusifor";
nameTable["13122"] = "wm_lh_G_oc-temp_med-Lingual";
nameTable["13123"] = "wm_lh_G_oc-temp_med-Parahip";
nameTable["13124"] = "wm_lh_G_orbital";
nameTable["13125"] = "wm_lh_G_pariet_inf-Angular";
nameTable["13126"] = "wm_lh_G_pariet_inf-Supramar";
nameTable["13127"] = "wm_lh_G_parietal_sup";
nameTable["13128"] = "wm_lh_G_postcentral";
nameTable["13129"] = "wm_lh_G_precentral";
nameTable["13130"] = "wm_lh_G_precuneus";
nameTable["13131"] = "wm_lh_G_rectus";
nameTable["13132"] = "wm_lh_G_subcallosal";
nameTable["13133"] = "wm_lh_G_temp_sup-G_T_transv";
nameTable["13134"] = "wm_lh_G_temp_sup-Lateral";
nameTable["13135"] = "wm_lh_G_temp_sup-Plan_polar";
nameTable["13136"] = "wm_lh_G_temp_sup-Plan_tempo";
nameTable["13137"] = "wm_lh_G_temporal_inf";
nameTable["13138"] = "wm_lh_G_temporal_middle";
nameTable["13139"] = "wm_lh_Lat_Fis-ant-Horizont";
nameTable["13140"] = "wm_lh_Lat_Fis-ant-Vertical";
nameTable["13141"] = "wm_lh_Lat_Fis-post";
nameTable["13142"] = "wm_lh_Medial_wall";
nameTable["13143"] = "wm_lh_Pole_occipital";
nameTable["13144"] = "wm_lh_Pole_temporal";
nameTable["13145"] = "wm_lh_S_calcarine";
nameTable["13146"] = "wm_lh_S_central";
nameTable["13147"] = "wm_lh_S_cingul-Marginalis";
nameTable["13148"] = "wm_lh_S_circular_insula_ant";
nameTable["13149"] = "wm_lh_S_circular_insula_inf";
nameTable["13150"] = "wm_lh_S_circular_insula_sup";
nameTable["13151"] = "wm_lh_S_collat_transv_ant";
nameTable["13152"] = "wm_lh_S_collat_transv_post";
nameTable["13153"] = "wm_lh_S_front_inf";
nameTable["13154"] = "wm_lh_S_front_middle";
nameTable["13155"] = "wm_lh_S_front_sup";
nameTable["13156"] = "wm_lh_S_interm_prim-Jensen";
nameTable["13157"] = "wm_lh_S_intrapariet_and_P_trans";
nameTable["13158"] = "wm_lh_S_oc_middle_and_Lunatus";
nameTable["13159"] = "wm_lh_S_oc_sup_and_transversal";
nameTable["13160"] = "wm_lh_S_occipital_ant";
nameTable["13161"] = "wm_lh_S_oc-temp_lat";
nameTable["13162"] = "wm_lh_S_oc-temp_med_and_Lingual";
nameTable["13163"] = "wm_lh_S_orbital_lateral";
nameTable["13164"] = "wm_lh_S_orbital_med-olfact";
nameTable["13165"] = "wm_lh_S_orbital-H_Shaped";
nameTable["13166"] = "wm_lh_S_parieto_occipital";
nameTable["13167"] = "wm_lh_S_pericallosal";
nameTable["13168"] = "wm_lh_S_postcentral";
nameTable["13169"] = "wm_lh_S_precentral-inf-part";
nameTable["13170"] = "wm_lh_S_precentral-sup-part";
nameTable["13171"] = "wm_lh_S_suborbital";
nameTable["13172"] = "wm_lh_S_subparietal";
nameTable["13173"] = "wm_lh_S_temporal_inf";
nameTable["13174"] = "wm_lh_S_temporal_sup";
nameTable["13175"] = "wm_lh_S_temporal_transverse";
nameTable["14100"] = "wm_rh_Unknown";
nameTable["14101"] = "wm_rh_G_and_S_frontomargin";
nameTable["14102"] = "wm_rh_G_and_S_occipital_inf";
nameTable["14103"] = "wm_rh_G_and_S_paracentral";
nameTable["14104"] = "wm_rh_G_and_S_subcentral";
nameTable["14105"] = "wm_rh_G_and_S_transv_frontopol";
nameTable["14106"] = "wm_rh_G_and_S_cingul-Ant";
nameTable["14107"] = "wm_rh_G_and_S_cingul-Mid-Ant";
nameTable["14108"] = "wm_rh_G_and_S_cingul-Mid-Post";
nameTable["14109"] = "wm_rh_G_cingul-Post-dorsal";
nameTable["14110"] = "wm_rh_G_cingul-Post-ventral";
nameTable["14111"] = "wm_rh_G_cuneus";
nameTable["14112"] = "wm_rh_G_front_inf-Opercular";
nameTable["14113"] = "wm_rh_G_front_inf-Orbital";
nameTable["14114"] = "wm_rh_G_front_inf-Triangul";
nameTable["14115"] = "wm_rh_G_front_middle";
nameTable["14116"] = "wm_rh_G_front_sup";
nameTable["14117"] = "wm_rh_G_Ins_lg_and_S_cent_ins";
nameTable["14118"] = "wm_rh_G_insular_short";
nameTable["14119"] = "wm_rh_G_occipital_middle";
nameTable["14120"] = "wm_rh_G_occipital_sup";
nameTable["14121"] = "wm_rh_G_oc-temp_lat-fusifor";
nameTable["14122"] = "wm_rh_G_oc-temp_med-Lingual";
nameTable["14123"] = "wm_rh_G_oc-temp_med-Parahip";
nameTable["14124"] = "wm_rh_G_orbital";
nameTable["14125"] = "wm_rh_G_pariet_inf-Angular";
nameTable["14126"] = "wm_rh_G_pariet_inf-Supramar";
nameTable["14127"] = "wm_rh_G_parietal_sup";
nameTable["14128"] = "wm_rh_G_postcentral";
nameTable["14129"] = "wm_rh_G_precentral";
nameTable["14130"] = "wm_rh_G_precuneus";
nameTable["14131"] = "wm_rh_G_rectus";
nameTable["14132"] = "wm_rh_G_subcallosal";
nameTable["14133"] = "wm_rh_G_temp_sup-G_T_transv";
nameTable["14134"] = "wm_rh_G_temp_sup-Lateral";
nameTable["14135"] = "wm_rh_G_temp_sup-Plan_polar";
nameTable["14136"] = "wm_rh_G_temp_sup-Plan_tempo";
nameTable["14137"] = "wm_rh_G_temporal_inf";
nameTable["14138"] = "wm_rh_G_temporal_middle";
nameTable["14139"] = "wm_rh_Lat_Fis-ant-Horizont";
nameTable["14140"] = "wm_rh_Lat_Fis-ant-Vertical";
nameTable["14141"] = "wm_rh_Lat_Fis-post";
nameTable["14142"] = "wm_rh_Medial_wall";
nameTable["14143"] = "wm_rh_Pole_occipital";
nameTable["14144"] = "wm_rh_Pole_temporal";
nameTable["14145"] = "wm_rh_S_calcarine";
nameTable["14146"] = "wm_rh_S_central";
nameTable["14147"] = "wm_rh_S_cingul-Marginalis";
nameTable["14148"] = "wm_rh_S_circular_insula_ant";
nameTable["14149"] = "wm_rh_S_circular_insula_inf";
nameTable["14150"] = "wm_rh_S_circular_insula_sup";
nameTable["14151"] = "wm_rh_S_collat_transv_ant";
nameTable["14152"] = "wm_rh_S_collat_transv_post";
nameTable["14153"] = "wm_rh_S_front_inf";
nameTable["14154"] = "wm_rh_S_front_middle";
nameTable["14155"] = "wm_rh_S_front_sup";
nameTable["14156"] = "wm_rh_S_interm_prim-Jensen";
nameTable["14157"] = "wm_rh_S_intrapariet_and_P_trans";
nameTable["14158"] = "wm_rh_S_oc_middle_and_Lunatus";
nameTable["14159"] = "wm_rh_S_oc_sup_and_transversal";
nameTable["14160"] = "wm_rh_S_occipital_ant";
nameTable["14161"] = "wm_rh_S_oc-temp_lat";
nameTable["14162"] = "wm_rh_S_oc-temp_med_and_Lingual";
nameTable["14163"] = "wm_rh_S_orbital_lateral";
nameTable["14164"] = "wm_rh_S_orbital_med-olfact";
nameTable["14165"] = "wm_rh_S_orbital-H_Shaped";
nameTable["14166"] = "wm_rh_S_parieto_occipital";
nameTable["14167"] = "wm_rh_S_pericallosal";
nameTable["14168"] = "wm_rh_S_postcentral";
nameTable["14169"] = "wm_rh_S_precentral-inf-part";
nameTable["14170"] = "wm_rh_S_precentral-sup-part";
nameTable["14171"] = "wm_rh_S_suborbital";
nameTable["14172"] = "wm_rh_S_subparietal";
nameTable["14173"] = "wm_rh_S_temporal_inf";
nameTable["14174"] = "wm_rh_S_temporal_sup";
nameTable["14175"] = "wm_rh_S_temporal_transverse";
return nameTable;
}
diff --git a/Modules/Connectomics/Algorithms/mitkFreeSurferParcellationTranslator.h b/Modules/Connectomics/Algorithms/mitkFreeSurferParcellationTranslator.h
index 74adcbc..0be96fa 100644
--- a/Modules/Connectomics/Algorithms/mitkFreeSurferParcellationTranslator.h
+++ b/Modules/Connectomics/Algorithms/mitkFreeSurferParcellationTranslator.h
@@ -1,111 +1,111 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkFreeSurferParcellationTranslator_h
#define mitkFreeSurferParcellationTranslator_h
// MITK
#include <MitkConnectomicsExports.h>
#include <itkObject.h>
#include <mitkDataNode.h>
#include <mitkLookupTable.h>
#include <mitkTransferFunction.h>
// VTK
#include <vtkSmartPointer.h>
using namespace mitk;
namespace mitk
{
/**
* @brief The mitkFreeSurferParcellationTranslator class
*
* This class provides a ready to use lookup table for freesurfer processed images and further functions e.g. to get the name assigned to a given label.
* Additional you can assign the lookup table or transferfunction by using the AssignLookupTable(DataNode* node) or AssignTransferfunction(DataNode* node) methods.
*
*/
class MITKCONNECTOMICS_EXPORT FreeSurferParcellationTranslator : public itk::Object
{
/*########### Constructors, Typedefs and Enumerations ###########*/
public:
typedef std::map<std::string, std::string> NameTable;
mitkClassMacroItkParent( FreeSurferParcellationTranslator, itk::Object )
itkNewMacro( FreeSurferParcellationTranslator )
protected:
FreeSurferParcellationTranslator();
~FreeSurferParcellationTranslator() override;
/*########### Methods ###########*/
public:
/**
* @brief Assign the lookup table to the given node
* @param node the lookup table should be assigned to
*/
virtual void AssignLookupTable( DataNode::Pointer node ) const;
/**
* @brief Assign the color transfer function to the given node
* @param node the transferfunction should be assigned to
*/
virtual void AssignTransferFunction( DataNode::Pointer node ) const;
/**
* @brief Get the label assigned to the given name
* @param name the label should be assigned to
* @return label
*/
virtual const std::string GetLabel( const std::string & name ) const;
/**
* @brief Get the label assigned to the given name
* @param name the label should be assigned to
* @return label
*/
virtual int GetLabelAsNumber( const std::string & name ) const;
/**
* @brief Return the lookup table
* @return lookup table
*/
virtual LookupTable::Pointer GetLookupTable() const;
/**
* @brief Get the name assigned to the given label
* @param label
* @return name
*/
virtual const std::string GetName( const std::string & label ) const;
/**
* @brief Get the name assigned to the given label
* @param label
* @return name
*/
virtual const std::string GetName( int label ) const;
/**
* @brief Get the transfer function
* @return transfer function
*/
virtual TransferFunction::Pointer GetTransferFunction() const;
private:
static LookupTable::Pointer CreateLookupTable();
static TransferFunction::Pointer CreateTransferFunction();
static NameTable CreateNameTable();
/*########### Static Members ###########*/
private:
static LookupTable::Pointer m_LookupTable;
static TransferFunction::Pointer m_TransferFunction;
static const NameTable m_NameTable;
};
}
#endif // mitkFreeSurferParcellationTranslator_h
diff --git a/Modules/Connectomics/IODataStructures/mitkConnectomicsConstantsManager.cpp b/Modules/Connectomics/IODataStructures/mitkConnectomicsConstantsManager.cpp
index ebb2d13..b7bd4f9 100644
--- a/Modules/Connectomics/IODataStructures/mitkConnectomicsConstantsManager.cpp
+++ b/Modules/Connectomics/IODataStructures/mitkConnectomicsConstantsManager.cpp
@@ -1,62 +1,62 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_ConnectomicsConstantsManager_CPP
//#define _MITK_ConnectomicsConstantsManager_CPP
#include "mitkConnectomicsConstantsManager.h"
//============== String and other constants ===================
//==== Error messages ====
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_TRIED_TO_ACCESS_INVALID_HISTOGRAM = "Tried to access invalid histogram.";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_PASSED_NEGATIVE_INDEX_TO_HISTOGRAM = "Passed negative index to histogram.";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_OUTSIDE_INTEGER_RANGE = "Tried to access histogram vector outside integer range.";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_BEYOND_SCOPE = "Tried to access histogram vector for value beyond scope: ";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_MAPPING = "Invalid mapping strategy selected.";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_ERROR_INVALID_DIMENSION_NEED_3 = "Invalid dimension, need dimension 3.";
//==== Warnings ====
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ZERO_DISTANCE_NODES = "There are nodes which are not distance 0 to themselves.";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_UNIMPLEMENTED_FEATURE = "You are trying to use an as of yet unimplemented feature.";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_MORE_POINTS_THAN_PRESENT = "Trying to estimate using more points than are present.";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ESTIMATING_LESS_THAN_2 = "Trying to estimate using less than two points.";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ESTIMATING_BEYOND_END = "Trying to estimate using points beyond track end.";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_ESTIMATING_BEYOND_START = "Trying to estimate using points beyond track start.";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_DID_NOT_FIND_WHITE = "Did not find a non white matter label.";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_NOT_EXTEND_TO_WHITE = "Could not extend to non white matter.";
//==== Information ====
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_INFO_NETWORK_CREATED = "Network has been created.";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_NETWORK_NOT_VALID = "Network not valid.";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_NETWORK_DISCONNECTED = "Network is disconnected.";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_CAN_NOT_COMPUTE_EFFICIENCY = "Can not compute efficiency. ";
//==== GUI ====
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_DASH = "-";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS = "Connectomics";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS_CREATION = "Connectomics Creation";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_SELECTION_WARNING = "Please load and select exactly one parcellation image and one fiber image before starting network creation.";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_FMRI_CORRELATION_SELECTION_WARNING = "Please load and select either only one time series image or one parcellation image and one time series image before starting correlation analysis.";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_ONLY_PARCELLATION_SELECTION_WARNING = "Please load and select one parcellation image.";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_PERFORMING_IMAGE_PROCESSING_FOR_IMAGE = "Performing image processing for image ";
//==== Properties ====
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_DEFAULT_RGBA_NAME = "rgbaImage";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_NAME = "name";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_VOLUMERENDERING = "volumerendering";
const char* mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_DEFAULT_CNF_NAME = "Connectomics network";
//#endif /* _MITK_ConnectomicsConstantsManager_CPP */
diff --git a/Modules/Connectomics/IODataStructures/mitkConnectomicsConstantsManager.h b/Modules/Connectomics/IODataStructures/mitkConnectomicsConstantsManager.h
index 271fe1c..475bbf3 100644
--- a/Modules/Connectomics/IODataStructures/mitkConnectomicsConstantsManager.h
+++ b/Modules/Connectomics/IODataStructures/mitkConnectomicsConstantsManager.h
@@ -1,87 +1,87 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_ConnectomicsConstantsManager_H
#define _MITK_ConnectomicsConstantsManager_H
#include <MitkConnectomicsExports.h>
namespace mitk
{
/** \brief The XML consts for reading and writing
*/
class MITKCONNECTOMICS_EXPORT ConnectomicsConstantsManager
{
public:
//============== String and other constants ===================
//==== Error messages ====
static const char* CONNECTOMICS_ERROR_TRIED_TO_ACCESS_INVALID_HISTOGRAM;
static const char* CONNECTOMICS_ERROR_PASSED_NEGATIVE_INDEX_TO_HISTOGRAM;
static const char* CONNECTOMICS_ERROR_OUTSIDE_INTEGER_RANGE;
static const char* CONNECTOMICS_ERROR_BEYOND_SCOPE;
static const char* CONNECTOMICS_ERROR_INVALID_MAPPING;
static const char* CONNECTOMICS_ERROR_INVALID_DIMENSION_NEED_3;
//==== Warnings ====
static const char* CONNECTOMICS_WARNING_ZERO_DISTANCE_NODES;
static const char* CONNECTOMICS_WARNING_UNIMPLEMENTED_FEATURE;
static const char* CONNECTOMICS_WARNING_MORE_POINTS_THAN_PRESENT;
static const char* CONNECTOMICS_WARNING_ESTIMATING_LESS_THAN_2;
static const char* CONNECTOMICS_WARNING_ESTIMATING_BEYOND_END;
static const char* CONNECTOMICS_WARNING_ESTIMATING_BEYOND_START;
static const char* CONNECTOMICS_WARNING_DID_NOT_FIND_WHITE;
static const char* CONNECTOMICS_WARNING_NOT_EXTEND_TO_WHITE;
//==== Information ====
static const char* CONNECTOMICS_WARNING_INFO_NETWORK_CREATED;
static const char* CONNECTOMICS_WARNING_NETWORK_NOT_VALID;
static const char* CONNECTOMICS_WARNING_NETWORK_DISCONNECTED;
static const char* CONNECTOMICS_WARNING_CAN_NOT_COMPUTE_EFFICIENCY;
//==== GUI ====
static const char* CONNECTOMICS_GUI_DASH;
static const char* CONNECTOMICS_GUI_CONNECTOMICS;
static const char* CONNECTOMICS_GUI_CONNECTOMICS_CREATION;
static const char* CONNECTOMICS_GUI_SELECTION_WARNING;
static const char* CONNECTOMICS_GUI_FMRI_CORRELATION_SELECTION_WARNING;
static const char* CONNECTOMICS_GUI_ONLY_PARCELLATION_SELECTION_WARNING;
static const char* CONNECTOMICS_GUI_PERFORMING_IMAGE_PROCESSING_FOR_IMAGE;
//==== Properties ====
static const char* CONNECTOMICS_PROPERTY_DEFAULT_RGBA_NAME;
static const char* CONNECTOMICS_PROPERTY_NAME;
static const char* CONNECTOMICS_PROPERTY_VOLUMERENDERING;
static const char* CONNECTOMICS_PROPERTY_DEFAULT_CNF_NAME;
private:
ConnectomicsConstantsManager();
~ConnectomicsConstantsManager();
};
} //namespace MITK
// include cpp
//#include <mitkConnectomicsConstantsManager.cpp>
#endif /* _MITK_ConnectomicsConstantsManager_H */
diff --git a/Modules/Connectomics/IODataStructures/mitkConnectomicsNetwork.cpp b/Modules/Connectomics/IODataStructures/mitkConnectomicsNetwork.cpp
index a344961..ccc8026 100644
--- a/Modules/Connectomics/IODataStructures/mitkConnectomicsNetwork.cpp
+++ b/Modules/Connectomics/IODataStructures/mitkConnectomicsNetwork.cpp
@@ -1,782 +1,782 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsNetwork.h"
#include <mitkConnectomicsStatisticsCalculator.h>
#include <boost/graph/clustering_coefficient.hpp>
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4172)
#endif
#include <boost/graph/betweenness_centrality.hpp>
#ifdef _MSC_VER
# pragma warning(pop)
#endif
/* Constructor and Destructor */
mitk::ConnectomicsNetwork::ConnectomicsNetwork()
: m_IsModified( false )
{
}
mitk::ConnectomicsNetwork::~ConnectomicsNetwork()
{
}
/* Wrapper methods */
bool mitk::ConnectomicsNetwork::EdgeExists(
mitk::ConnectomicsNetwork::VertexDescriptorType vertexA, mitk::ConnectomicsNetwork::VertexDescriptorType vertexB ) const
{
return boost::edge(vertexA, vertexB, m_Network ).second;
}
void mitk::ConnectomicsNetwork::IncreaseEdgeWeight(mitk::ConnectomicsNetwork::VertexDescriptorType vertexA, mitk::ConnectomicsNetwork::VertexDescriptorType vertexB , double fiber_count)
{
m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ].fiber_count += fiber_count;
SetIsModified( true );
}
void mitk::ConnectomicsNetwork::AddEdge(mitk::ConnectomicsNetwork::VertexDescriptorType vertexA,
mitk::ConnectomicsNetwork::VertexDescriptorType vertexB
, double fiber_count)
{
AddEdge(vertexA, vertexB, m_Network[ vertexA ].id, m_Network[ vertexB ].id, fiber_count );
}
void mitk::ConnectomicsNetwork::AddEdge(
mitk::ConnectomicsNetwork::VertexDescriptorType vertexA,
mitk::ConnectomicsNetwork::VertexDescriptorType vertexB,
int sourceID, int targetID, double fiber_count, double edge_weight )
{
boost::add_edge( vertexA, vertexB, m_Network );
m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ].sourceId = sourceID;
m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ].targetId = targetID;
m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ].fiber_count = fiber_count;
m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ].edge_weight = edge_weight;
SetIsModified( true );
}
mitk::ConnectomicsNetwork::VertexDescriptorType mitk::ConnectomicsNetwork::AddVertex( int id )
{
VertexDescriptorType vertex = boost::add_vertex( m_Network );
m_Network[vertex].id = id;
SetIsModified( true );
return vertex;
}
void mitk::ConnectomicsNetwork::SetLabel(
mitk::ConnectomicsNetwork::VertexDescriptorType vertex, std::string inLabel )
{
m_Network[vertex].label = inLabel;
SetIsModified( true );
}
void mitk::ConnectomicsNetwork::SetCoordinates(
mitk::ConnectomicsNetwork::VertexDescriptorType vertex, std::vector< float > inCoordinates )
{
m_Network[vertex].coordinates = inCoordinates;
SetIsModified( true );
}
void mitk::ConnectomicsNetwork::clear()
{
m_Network.clear();
SetIsModified( true );
}
/* Superclass methods, that need to be implemented */
void mitk::ConnectomicsNetwork::UpdateOutputInformation()
{
}
void mitk::ConnectomicsNetwork::SetRequestedRegionToLargestPossibleRegion()
{
}
bool mitk::ConnectomicsNetwork::RequestedRegionIsOutsideOfTheBufferedRegion()
{
return false;
}
bool mitk::ConnectomicsNetwork::VerifyRequestedRegion()
{
return true;
}
void mitk::ConnectomicsNetwork::SetRequestedRegion(const itk::DataObject * /*data*/ )
{
}
std::vector< mitk::ConnectomicsNetwork::NetworkNode >
mitk::ConnectomicsNetwork::GetVectorOfAllNodes() const
{
boost::graph_traits<NetworkType>::vertex_iterator iterator, end;
// sets iterator to start end end to end
boost::tie(iterator, end) = boost::vertices( m_Network );
std::vector< NetworkNode > vectorOfNodes;
for ( ; iterator != end; ++iterator)
{
NetworkNode tempNode;
// the value of an iterator is a descriptor
tempNode = m_Network[ *iterator ];
vectorOfNodes.push_back( tempNode );
}
return vectorOfNodes;
}
std::vector< mitk::ConnectomicsNetwork::VertexDescriptorType >
mitk::ConnectomicsNetwork::GetVectorOfAllVertexDescriptors() const
{
boost::graph_traits<NetworkType>::vertex_iterator iterator, end;
// sets iterator to start end end to end
boost::tie(iterator, end) = boost::vertices( m_Network );
std::vector< VertexDescriptorType > vectorOfDescriptors;
for ( ; iterator != end; ++iterator)
{
vectorOfDescriptors.push_back( *iterator );
}
return vectorOfDescriptors;
}
std::vector< std::pair<
std::pair< mitk::ConnectomicsNetwork::NetworkNode, mitk::ConnectomicsNetwork::NetworkNode >
, mitk::ConnectomicsNetwork::NetworkEdge > >
mitk::ConnectomicsNetwork::GetVectorOfAllEdges() const
{
boost::graph_traits<NetworkType>::edge_iterator iterator, end;
// sets iterator to start end end to end
boost::tie(iterator, end) = boost::edges( m_Network );
std::vector<
std::pair<
std::pair< NetworkNode, NetworkNode >
, NetworkEdge
>
> vectorOfEdges;
for ( ; iterator != end; ++iterator)
{
NetworkNode sourceNode, targetNode;
NetworkEdge tempEdge;
// the value of an iterator is a descriptor
tempEdge = m_Network[ *iterator ];
sourceNode = m_Network[ boost::source( *iterator, m_Network ) ];
targetNode = m_Network[ boost::target( *iterator, m_Network ) ];
std::pair< NetworkNode, NetworkNode > nodePair( sourceNode, targetNode );
std::pair< std::pair< NetworkNode, NetworkNode > , NetworkEdge > edgePair( nodePair, tempEdge);
vectorOfEdges.push_back( edgePair );
}
return vectorOfEdges;
}
int mitk::ConnectomicsNetwork::GetNumberOfVertices() const
{
return boost::num_vertices( m_Network );
}
int mitk::ConnectomicsNetwork::GetNumberOfEdges() const
{
return boost::num_edges( m_Network );
}
double mitk::ConnectomicsNetwork::GetMaximumWeight() const
{
int maxWeight( 0 );
boost::graph_traits<NetworkType>::edge_iterator iterator, end;
// sets iterator to start end end to end
boost::tie(iterator, end) = boost::edges( m_Network );
for ( ; iterator != end; ++iterator)
{
int tempWeight;
// the value of an iterator is a descriptor
tempWeight = m_Network[ *iterator ].fiber_count;
if( tempWeight > maxWeight )
{
maxWeight = tempWeight;
}
}
return maxWeight;
}
int mitk::ConnectomicsNetwork::GetNumberOfSelfLoops()
{
int noOfSelfLoops( 0 );
std::vector< std::pair< std::pair< NetworkNode, NetworkNode > , NetworkEdge > >
edgeVector = GetVectorOfAllEdges();
for( unsigned int index = 0; index < edgeVector.size() ; index++ )
{
double sourceX, sourceY, sourceZ, targetX, targetY, targetZ;
sourceX = edgeVector[ index ].first.first.coordinates[0] ;
sourceY = edgeVector[ index ].first.first.coordinates[1] ;
sourceZ = edgeVector[ index ].first.first.coordinates[2] ;
targetX = edgeVector[ index ].first.second.coordinates[0] ;
targetY = edgeVector[ index ].first.second.coordinates[1] ;
targetZ = edgeVector[ index ].first.second.coordinates[2] ;
// if the coordinates are the same
if(
sourceX > ( targetX - 0.01 ) &&
sourceX < ( targetX + 0.01 ) &&
sourceY > ( targetY - 0.01 ) &&
sourceY < ( targetY + 0.01 ) &&
sourceZ > ( targetZ - 0.01 ) &&
sourceZ < ( targetZ + 0.01 )
)
{
noOfSelfLoops++;
}
}
return noOfSelfLoops;
}
double mitk::ConnectomicsNetwork::GetAverageDegree()
{
double vertices = (double) GetNumberOfVertices();
double edges = (double) GetNumberOfEdges();
return ( ( edges * 2.0 ) / vertices );
}
double mitk::ConnectomicsNetwork::GetConnectionDensity()
{
double vertices = (double) GetNumberOfVertices();
double edges = (double) GetNumberOfEdges();
double numberOfPossibleEdges = vertices * ( vertices - 1 ) / 2 ;
return ( edges / numberOfPossibleEdges );
}
std::vector< int > mitk::ConnectomicsNetwork::GetDegreeOfNodes( ) const
{
std::vector< int > vectorOfDegree;
boost::graph_traits<NetworkType>::vertex_iterator iterator, end;
// sets iterator to start end end to end
boost::tie( iterator, end ) = boost::vertices( m_Network );
vectorOfDegree.resize( this->GetNumberOfVertices() );
for ( ; iterator != end; ++iterator)
{
// the value of an iterator is a descriptor
vectorOfDegree[ m_Network[ *iterator ].id ] = GetVectorOfAdjacentNodes( *iterator ).size();
}
return vectorOfDegree;
}
std::vector< mitk::ConnectomicsNetwork::VertexDescriptorType >
mitk::ConnectomicsNetwork::GetVectorOfAdjacentNodes( mitk::ConnectomicsNetwork::VertexDescriptorType vertex ) const
{
std::vector< mitk::ConnectomicsNetwork::VertexDescriptorType > vectorOfAdjacentNodes;
boost::graph_traits<NetworkType>::adjacency_iterator adjIter, adjEnd;
boost::tie( adjIter, adjEnd ) = boost::adjacent_vertices( vertex, m_Network);
for ( ; adjIter != adjEnd; ++adjIter)
{
vectorOfAdjacentNodes.push_back( *adjIter );
}
return vectorOfAdjacentNodes;
}
int mitk::ConnectomicsNetwork::GetMaximumDegree() const
{
int maximumDegree( 0 );
std::vector< int > vectorOfDegree = GetDegreeOfNodes();
for( unsigned int index( 0 ); index < vectorOfDegree.size(); ++index )
{
if( maximumDegree < vectorOfDegree[ index ] )
{
maximumDegree = vectorOfDegree[ index ];
}
}
return maximumDegree;
}
std::vector< double > mitk::ConnectomicsNetwork::GetLocalClusteringCoefficients( ) const
{
std::vector< double > vectorOfClusteringCoefficients;
typedef boost::graph_traits<NetworkType>::vertex_iterator vertexIter;
vectorOfClusteringCoefficients.resize( this->GetNumberOfVertices() );
std::pair<vertexIter, vertexIter> vertexPair;
//for every vertex calculate the clustering coefficient
int size = vectorOfClusteringCoefficients.size();
for (vertexPair = vertices(m_Network); vertexPair.first != vertexPair.second; ++vertexPair.first)
{
int index = m_Network[ *vertexPair.first ].id;
if( index > size )
{
MITK_ERROR << "Trying to access out of bounds clustering coefficient";
continue;
}
vectorOfClusteringCoefficients[ index ] =
boost::clustering_coefficient(m_Network,*vertexPair.first) ;
}
return vectorOfClusteringCoefficients;
}
std::vector< double > mitk::ConnectomicsNetwork::GetClusteringCoefficientsByDegree( )
{
std::vector< double > vectorOfClusteringCoefficients = GetLocalClusteringCoefficients();
std::vector< int > vectorOfDegree = GetDegreeOfNodes();
std::vector< double > vectorOfClusteringCoefficientsByDegree;
vectorOfClusteringCoefficientsByDegree.resize( GetMaximumDegree() + 1, 0 );
// c_{mean}(k) = frac{1}_{N_{k}} sum_{i in Y(k)} c_{i}
// where N_{k} is the number of vertices of degree k
// Y(k) is the set of vertices of degree k
// c_{i} is the local clustering coefficient of vertex i
for( unsigned int degree( 0 ); degree < vectorOfClusteringCoefficientsByDegree.size(); ++degree )
{
vectorOfClusteringCoefficientsByDegree[ degree ] = 0;
int n_k( 0 );
for( unsigned int index( 0 ); index < vectorOfDegree.size(); ++index )
{
if( degree == (unsigned int)vectorOfDegree[ index ] )
{// if in Y( degree )
vectorOfClusteringCoefficientsByDegree[ degree ] += vectorOfClusteringCoefficients[ index ];
n_k++;
}
}
if( n_k != 0 )
{
vectorOfClusteringCoefficientsByDegree[ degree ] =
vectorOfClusteringCoefficientsByDegree[ degree ] / n_k;
}
}
return vectorOfClusteringCoefficientsByDegree;
}
double mitk::ConnectomicsNetwork::GetGlobalClusteringCoefficient( )
{
double globalClusteringCoefficient( 0.0 );
std::vector< double > vectorOfClusteringCoefficientsByDegree = GetClusteringCoefficientsByDegree();
std::vector< int > vectorOfDegree = GetDegreeOfNodes();
std::vector< int > degreeDistribution;
degreeDistribution.resize( vectorOfClusteringCoefficientsByDegree.size(), 0 );
int normalizationParameter( 0 );
for( unsigned int index( 0 ); index < vectorOfDegree.size(); ++index )
{
degreeDistribution[ vectorOfDegree[ index ] ]++;
normalizationParameter++;
}
// c_{mean} = sum_{k} P_{k} c_{mean}(k)
// where P_{k} is the degree distribution
// k is the degree
for( unsigned int degree( 0 ); degree < degreeDistribution.size(); ++degree )
{
globalClusteringCoefficient +=
degreeDistribution[ degree ] / ( (double) normalizationParameter)
* vectorOfClusteringCoefficientsByDegree[ degree ];
}
return globalClusteringCoefficient;
}
mitk::ConnectomicsNetwork::NetworkType* mitk::ConnectomicsNetwork::GetBoostGraph()
{
return &m_Network;
}
void mitk::ConnectomicsNetwork::SetBoostGraph( NetworkType* newGraph )
{
this->clear();
m_Network = *newGraph;
this->SetIsModified( true );
}
void mitk::ConnectomicsNetwork::ImportNetwort( mitk::ConnectomicsNetwork::Pointer source )
{
typedef std::vector< std::pair< std::pair< NetworkNode, NetworkNode >, NetworkEdge > > EdgeVectorType;
typedef std::vector< NetworkNode > VertexVectorType;
this->clear();
this->SetGeometry( source->GetGeometry());
VertexVectorType vertexVector = source->GetVectorOfAllNodes();
EdgeVectorType edgeVector = source->GetVectorOfAllEdges();
std::map< int, VertexDescriptorType > idToVertexMap;
for( unsigned int loop(0); loop < vertexVector.size(); loop++ )
{
VertexDescriptorType newVertex = this->AddVertex( vertexVector[ loop ].id );
this->SetLabel( newVertex, vertexVector[ loop ].label );
this->SetCoordinates( newVertex, vertexVector[ loop ].coordinates );
if ( idToVertexMap.count( vertexVector[ loop ].id ) > 0 )
{
MITK_ERROR << "Aborting network import, duplicate vertex ID discovered.";
return;
}
idToVertexMap.insert( std::pair< int, VertexDescriptorType >( vertexVector[ loop ].id, newVertex) );
}
for( unsigned int loop(0); loop < edgeVector.size(); loop++ )
{
VertexDescriptorType source = idToVertexMap.find( edgeVector[ loop ].second.sourceId )->second;
VertexDescriptorType target = idToVertexMap.find( edgeVector[ loop ].second.targetId )->second;
this->AddEdge( source, target, edgeVector[ loop ].second.sourceId, edgeVector[ loop ].second.targetId, edgeVector[ loop ].second.fiber_count);
}
this->SetIsModified( true );
}
bool mitk::ConnectomicsNetwork::GetIsModified() const
{
return m_IsModified;
}
void mitk::ConnectomicsNetwork::SetIsModified( bool value)
{
m_IsModified = value;
}
mitk::ConnectomicsNetwork::NetworkNode mitk::ConnectomicsNetwork::GetNode( VertexDescriptorType vertex ) const
{
return m_Network[ vertex ];
}
mitk::ConnectomicsNetwork::NetworkEdge mitk::ConnectomicsNetwork::GetEdge( VertexDescriptorType vertexA, VertexDescriptorType vertexB ) const
{
if( EdgeExists(vertexA, vertexB) )
{
return m_Network[ boost::edge(vertexA, vertexB, m_Network ).first ];
}
else
{
mitkThrow() << "Edge does not exist";
}
}
void mitk::ConnectomicsNetwork::UpdateBounds( )
{
float min = itk::NumericTraits<float>::min();
float max = itk::NumericTraits<float>::max();
float bounds[] = {max, min, max, min, max, min};
std::vector< mitk::ConnectomicsNetwork::NetworkNode > nodeVector = this->GetVectorOfAllNodes();
if( nodeVector.size() == 0 )
{
bounds[0] = 0;
bounds[1] = 1;
bounds[2] = 0;
bounds[3] = 1;
bounds[4] = 0;
bounds[5] = 1;
}
// for each direction, make certain the point is in between
for(auto & elem : nodeVector)
{
for( unsigned int direction(0); direction < elem.coordinates.size(); direction++ )
{
if( elem.coordinates.at(direction) < bounds[ 2 * direction ] )
{
bounds[ 2 * direction ] = elem.coordinates.at(direction);
}
if( elem.coordinates.at(direction) > bounds[ 2 * direction + 1] )
{
bounds[ 2 * direction + 1] = elem.coordinates.at(direction);
}
}
}
// provide some border margin
for(int i=0; i<=4; i+=2)
{
bounds[i] -=10;
}
for(int i=1; i<=5; i+=2)
{
bounds[i] +=10;
}
this->GetGeometry()->SetFloatBounds(bounds);
this->GetTimeGeometry()->Update();
}
void mitk::ConnectomicsNetwork::PruneUnconnectedSingleNodes()
{
boost::graph_traits<NetworkType>::vertex_iterator iterator, end;
// set to true if iterators are invalidated by deleting a vertex
bool vertexHasBeenRemoved( true );
// if no vertex has been removed in the last loop, we are done
while( vertexHasBeenRemoved )
{
vertexHasBeenRemoved = false;
// sets iterator to start and end to end
boost::tie(iterator, end) = boost::vertices( m_Network );
for ( ; iterator != end && !vertexHasBeenRemoved; ++iterator)
{
// If the node has no adjacent vertices it should be deleted
if( GetVectorOfAdjacentNodes( *iterator ).size() == 0 )
{
vertexHasBeenRemoved = true;
// this invalidates all iterators
boost::remove_vertex( *iterator, m_Network );
}
}
}
UpdateIDs();
}
void mitk::ConnectomicsNetwork::UpdateIDs()
{
boost::graph_traits<NetworkType>::vertex_iterator v_i, v_end;
boost::graph_traits<NetworkType>::edge_iterator e_i, e_end;
// update node ids
boost::tie( v_i, v_end ) = boost::vertices( m_Network );
for ( ; v_i != v_end; ++v_i)
{
m_Network[*v_i].id = *v_i;
}
// update edge information
boost::tie(e_i, e_end) = boost::edges( m_Network );
for ( ; e_i != e_end; ++e_i)
{
m_Network[ *e_i ].sourceId = m_Network[ boost::source( *e_i, m_Network ) ].id;
m_Network[ *e_i ].targetId = m_Network[ boost::target( *e_i, m_Network ) ].id;
}
this->SetIsModified( true );
}
std::vector< double > mitk::ConnectomicsNetwork::GetNodeBetweennessVector() const
{
std::vector< double > betweennessVector;
betweennessVector.clear();
betweennessVector.resize( this->GetNumberOfVertices() );
boost::brandes_betweenness_centrality(
m_Network,
boost::centrality_map(
boost::make_iterator_property_map( betweennessVector.begin(), boost::get( &NetworkNode::id, m_Network ), double() )
).vertex_index_map( boost::get( &NetworkNode::id, m_Network ) )
);
return betweennessVector;
}
std::vector< double > mitk::ConnectomicsNetwork::GetEdgeBetweennessVector() const
{
// std::map used for convenient initialization
typedef std::map<EdgeDescriptorType, int> EdgeIndexStdMap;
EdgeIndexStdMap stdEdgeIndex;
// associative property map needed for iterator property map-wrapper
typedef boost::associative_property_map< EdgeIndexStdMap > EdgeIndexMap;
EdgeIndexMap edgeIndex(stdEdgeIndex);
boost::graph_traits<NetworkType>::edge_iterator iterator, end;
// sets iterator to start end end to end
boost::tie(iterator, end) = boost::edges( m_Network );
int i(0);
for ( ; iterator != end; ++iterator, ++i)
{
stdEdgeIndex.insert(std::pair< EdgeDescriptorType, int >( *iterator, i));
}
// Define EdgeCentralityMap
std::vector< double > edgeBetweennessVector(boost::num_edges( m_Network ), 0.0);
// Create the external property map
boost::iterator_property_map< std::vector< double >::iterator, EdgeIndexMap >
e_centrality_map(edgeBetweennessVector.begin(), edgeIndex);
// Define VertexCentralityMap
typedef boost::property_map< NetworkType, boost::vertex_index_t>::type VertexIndexMap;
VertexIndexMap vertexIndex = get(boost::vertex_index, m_Network );
std::vector< double > betweennessVector(boost::num_vertices( m_Network ), 0.0);
// Create the external property map
boost::iterator_property_map< std::vector< double >::iterator, VertexIndexMap >
v_centrality_map(betweennessVector.begin(), vertexIndex);
boost::brandes_betweenness_centrality( m_Network, v_centrality_map, e_centrality_map );
return edgeBetweennessVector;
}
std::vector< double > mitk::ConnectomicsNetwork::GetShortestDistanceVectorFromLabel( std::string targetLabel ) const
{
std::vector< VertexDescriptorType > predecessorMap( boost::num_vertices( m_Network ) );
int numberOfNodes( boost::num_vertices( m_Network ) );
std::vector< double > distanceMatrix;
distanceMatrix.resize( numberOfNodes );
boost::graph_traits<NetworkType>::vertex_iterator iterator, end;
boost::tie(iterator, end) = boost::vertices( m_Network );
while( (iterator != end) && (m_Network[ *iterator ].label != targetLabel) )
{
++iterator;
}
if( iterator == end )
{
MITK_WARN << "Label not found";
return distanceMatrix;
}
boost::dijkstra_shortest_paths(m_Network, *iterator, boost::predecessor_map(&predecessorMap[ 0 ]).distance_map(&distanceMatrix[ 0 ]).weight_map( boost::get( &NetworkEdge::edge_weight ,m_Network ) ) ) ;
return distanceMatrix;
}
bool mitk::ConnectomicsNetwork::CheckForLabel( std::string targetLabel ) const
{
boost::graph_traits<NetworkType>::vertex_iterator iterator, end;
boost::tie(iterator, end) = boost::vertices( m_Network );
while( (iterator != end) && (m_Network[ *iterator ].label != targetLabel) )
{
++iterator;
}
if( iterator == end )
{
return false;
}
return true;
}
bool mitk::Equal( mitk::ConnectomicsNetwork* leftHandSide, mitk::ConnectomicsNetwork* rightHandSide, mitk::ScalarType eps, bool verbose )
{
bool noDifferenceFound = true;
if( rightHandSide == nullptr )
{
if(verbose)
{
MITK_INFO << "[Equal( ConnectomicsNetwork*, ConnectomicsNetwork* )] rightHandSide nullptr.";
}
return false;
}
if( leftHandSide == nullptr )
{
if(verbose)
{
MITK_INFO << "[Equal( ConnectomicsNetwork*, ConnectomicsNetwork* )] leftHandSide nullptr.";
}
return false;
}
mitk::ConnectomicsStatisticsCalculator::Pointer calculatorLeft = mitk::ConnectomicsStatisticsCalculator::New();
mitk::ConnectomicsStatisticsCalculator::Pointer calculatorRight = mitk::ConnectomicsStatisticsCalculator::New();
calculatorLeft->SetNetwork( leftHandSide );
calculatorRight->SetNetwork( rightHandSide );
calculatorLeft->Update();
calculatorRight->Update();
if( ! mitk::Equal( calculatorLeft->GetNumberOfVertices(), calculatorRight->GetNumberOfVertices(), eps ) )
{
if(verbose)
MITK_INFO << "[Equal( ConnectomicsNetwork*, ConnectomicsNetwork* )] Number of vertices not equal. " << calculatorLeft->GetNumberOfVertices() << " vs " << calculatorRight->GetNumberOfVertices();
noDifferenceFound = false;
}
if( ! mitk::Equal( calculatorLeft->GetNumberOfEdges(), calculatorRight->GetNumberOfEdges(), eps ) )
{
if(verbose)
MITK_INFO << "[Equal( ConnectomicsNetwork*, ConnectomicsNetwork* )] Number of edges not equal. " << calculatorLeft->GetNumberOfEdges() << " vs " << calculatorRight->GetNumberOfEdges();
noDifferenceFound = false;
}
if( ! mitk::Equal( calculatorLeft->GetSmallWorldness(), calculatorRight->GetSmallWorldness(), eps ) )
{
if(verbose)
MITK_INFO << "[Equal( ConnectomicsNetwork*, ConnectomicsNetwork* )] Small worldness not equal. " << calculatorLeft->GetSmallWorldness() << " vs " << calculatorRight->GetSmallWorldness();
noDifferenceFound = false;
}
return noDifferenceFound;
}
diff --git a/Modules/Connectomics/IODataStructures/mitkConnectomicsNetwork.h b/Modules/Connectomics/IODataStructures/mitkConnectomicsNetwork.h
index b0284ac..c783c08 100644
--- a/Modules/Connectomics/IODataStructures/mitkConnectomicsNetwork.h
+++ b/Modules/Connectomics/IODataStructures/mitkConnectomicsNetwork.h
@@ -1,238 +1,238 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_ConnectomicsNetwork_H
#define _MITK_ConnectomicsNetwork_H
#include <MitkConnectomicsExports.h>
#include "mitkBaseData.h"
#ifndef Q_MOC_RUN
#include <boost/graph/adjacency_list.hpp>
#endif
namespace mitk {
/**
* \brief Connectomics Network Class
*
* This class is designed to represent a connectomics network (brain network). It encapsulates a
* boost adjacency list and provides additional capabilities. The information contained in the nodes and edges is:
*
* Network Node:
* <ul>
* <li> int ID - The id of the node
* <li> string label - The label of the node, this can be any string, such as an anatomical label
* <li> vector<float> coordinates - The coordinates the node should be displayed at
* </ul>
*
* Network Edge:
* <ul>
* <li> int sourceId - The Id of the source node
* <li> int targetId - The Id of the target node
* <li> int weight - Weight of the edge as int (used for counting fibers)
* <li> double edge_weight - Used for boost and algorithms, should be between 0 and 1
* </ul>
*/
class MITKCONNECTOMICS_EXPORT ConnectomicsNetwork : public BaseData
{
public:
/** Structs for the graph */
/** The Node */
struct NetworkNode
{
int id;
std::string label;
std::vector< float > coordinates;
};
/** The Edge */
struct NetworkEdge
{
int sourceId;
int targetId;
double fiber_count; // For now the number of times it was present
double edge_weight; // For boost, currently set to 1 by default for unweighted calculations
};
/** Typedefs **/
//typedef boost::adjacency_list< boost::listS, boost::listS, boost::undirectedS, NetworkNode, NetworkEdge > NetworkType;
typedef boost::adjacency_list< boost::vecS, boost::vecS, boost::undirectedS, NetworkNode, NetworkEdge > NetworkType;
typedef boost::graph_traits<NetworkType>::vertex_descriptor VertexDescriptorType;
typedef boost::graph_traits<NetworkType>::edge_descriptor EdgeDescriptorType;
// virtual methods that need to be implemented
void UpdateOutputInformation() override;
void SetRequestedRegionToLargestPossibleRegion() override;
bool RequestedRegionIsOutsideOfTheBufferedRegion() override;
bool VerifyRequestedRegion() override;
void SetRequestedRegion(const itk::DataObject * ) override;
// Macros
mitkClassMacro( ConnectomicsNetwork, BaseData );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
////////////////// Interface ///////////////////
/** return whether an edge exists between the two given vertices */
bool EdgeExists( VertexDescriptorType vertexA, VertexDescriptorType vertexB ) const;
/** increase the weight of an edge between the two given vertices */
void IncreaseEdgeWeight( VertexDescriptorType vertexA, VertexDescriptorType vertexB, double fiber_count );
/** add an edge between two given vertices */
void AddEdge( VertexDescriptorType vertexA, VertexDescriptorType vertexB, double fiber_count);
/** add an edge between two given vertices ( with a specific weight ) */
void AddEdge(VertexDescriptorType vertexA, VertexDescriptorType vertexB, int sourceID, int targetID, double fiber_count, double edge_weight = 1.0 );
/** add a vertex with a specified id */
VertexDescriptorType AddVertex( int id);
/** set the label of a vertex */
void SetLabel( VertexDescriptorType vertex, std::string inLabel );
/** set the coordinates of a vertex */
void SetCoordinates( VertexDescriptorType vertex, std::vector< float > inCoordinates );
/** clear the graph */
void clear();
/** return the node struct for a given node descriptor */
NetworkNode GetNode( VertexDescriptorType vertex ) const;
/** return the edge struct for two given node descriptors */
NetworkEdge GetEdge( VertexDescriptorType vertexA, VertexDescriptorType vertexB ) const;
/** get vector containing all the nodes of the network */
std::vector< NetworkNode > GetVectorOfAllNodes() const;
/** get vector containing all the vertex descriptors of the network */
std::vector< VertexDescriptorType > GetVectorOfAllVertexDescriptors() const;
/** get vector containing the descriptors of nodes adjacent to the vertex denoted by the given descriptor */
std::vector< VertexDescriptorType > GetVectorOfAdjacentNodes( VertexDescriptorType vertex ) const;
/** get vector containing all the edges of the network and the connected nodes */
std::vector< std::pair< std::pair< NetworkNode, NetworkNode > , NetworkEdge > > GetVectorOfAllEdges() const;
/** get overall number of vertices in the network */
int GetNumberOfVertices() const;
/** get overall number of edges in the network */
int GetNumberOfEdges() const;
/** get number of vertices, that are connected to themselves */
int GetNumberOfSelfLoops();
/** get number of vertices, that are connected to themselves */
double GetAverageDegree();
/** get number of edges divided by number of possible edges */
double GetConnectionDensity();
/** Get the maximum weight of all edges */
double GetMaximumWeight() const;
/** Get a vector in the format vector[ vertexID ] = degree */
std::vector< int > GetDegreeOfNodes( ) const;
/** Get the maximum degree of all nodes */
int GetMaximumDegree() const;
/** Get a vector in the format vector[ vertexID ] = clustering coefficient */
std::vector< double > GetLocalClusteringCoefficients( ) const;
/** Get a vector in the format vector[ degree ] = average clustering coefficient */
std::vector< double > GetClusteringCoefficientsByDegree( );
/** Get the global clustering coefficient */
double GetGlobalClusteringCoefficient( );
/** Get the betweenness centrality for each vertex in form of a vector of length (number vertices)*/
std::vector< double > GetNodeBetweennessVector() const;
/** Get the betweenness centrality for each edge in form of a vector of length (number edges)*/
std::vector< double > GetEdgeBetweennessVector() const;
/** Check whether a vertex with the specified label exists*/
bool CheckForLabel( std::string targetLabel ) const;
/** Get the shortest distance from a specified vertex to all other vertices in form of a vector of length (number vertices)*/
std::vector< double > GetShortestDistanceVectorFromLabel( std::string targetLabel ) const;
/** Access boost graph directly */
NetworkType* GetBoostGraph();
/** Set the boost graph directly */
void SetBoostGraph( NetworkType* newGraph );
void ImportNetwort( mitk::ConnectomicsNetwork::Pointer source );
/** Get the modified flag */
bool GetIsModified() const;
/** Set the modified flag */
void SetIsModified( bool );
/** Update the bounds of the geometry to fit the network */
void UpdateBounds( );
/** Remove nodes not connected to any other node */
void PruneUnconnectedSingleNodes();
/** This function will relabel all vertices and edges in a continuous manner
*
* Mainly important after removing vertices, to make sure that the ids run continuously from
* 0 to number of vertices - 1 and edge target and source ids match the corresponding node.
*/
void UpdateIDs();
protected:
ConnectomicsNetwork();
~ConnectomicsNetwork() override;
NetworkType m_Network;
/// Flag which indicates whether the network has been modified since the last check
///
/// mainly for rendering purposes
bool m_IsModified;
private:
};
/**
* \brief Returns true if the networks are considered equal.
*
* For now two networks are considered equal if they are equal in the following properties:
* - Number of nodes
* - Number of edges
* - Smallworldness
*/
MITKCONNECTOMICS_EXPORT bool Equal( mitk::ConnectomicsNetwork* leftHandSide, mitk::ConnectomicsNetwork* rightHandSide, mitk::ScalarType eps, bool verbose);
} // namespace mitk
#endif /* _MITK_ConnectomicsNetwork_H */
diff --git a/Modules/Connectomics/IODataStructures/mitkConnectomicsNetworkProperties.h b/Modules/Connectomics/IODataStructures/mitkConnectomicsNetworkProperties.h
index 3d7e376..b317ebe 100644
--- a/Modules/Connectomics/IODataStructures/mitkConnectomicsNetworkProperties.h
+++ b/Modules/Connectomics/IODataStructures/mitkConnectomicsNetworkProperties.h
@@ -1,43 +1,43 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 ConnectomicsNetworkProperties_H_HEADER_INCLUDED
#define ConnectomicsNetworkProperties_H_HEADER_INCLUDED
#include <cstring>
#include "mitkProperties.h"
#include "mitkStringProperty.h"
namespace mitk {
/** \file mitkConnectomicsNetworkProperties.h
* \brief This file defines the data properties for connectomics networks in MITK.
*
* This file collects and explains the properties which can be used store additional
* information in connectomics networks.
*/
/**
* \brief Additional header information
*
* This property contains a string with additional information which can be stored
* as a header in file formats which support it.
*/
const std::string connectomicsDataAdditionalHeaderInformation = "Connectomics.Data.AdditionalHeaderInformation";
} // namespace mitk
#endif //ConnectomicsNetworkProperties_H_HEADER_INCLUDED
diff --git a/Modules/Connectomics/Rendering/mitkConnectomicsEnumerationSubclassesSerializer.cpp b/Modules/Connectomics/Rendering/mitkConnectomicsEnumerationSubclassesSerializer.cpp
index 08eaa91..84d4bd2 100644
--- a/Modules/Connectomics/Rendering/mitkConnectomicsEnumerationSubclassesSerializer.cpp
+++ b/Modules/Connectomics/Rendering/mitkConnectomicsEnumerationSubclassesSerializer.cpp
@@ -1,79 +1,79 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkConnectomicsEnumerationSubclassesSerializer_h_included
#define mitkConnectomicsEnumerationSubclassesSerializer_h_included
#include "mitkEnumerationPropertySerializer.h"
#include "mitkConnectomicsRenderingEdgeColorParameterProperty.h"
#include "mitkConnectomicsRenderingEdgeFilteringProperty.h"
#include "mitkConnectomicsRenderingEdgeRadiusParameterProperty.h"
#include "mitkConnectomicsRenderingEdgeThresholdParameterProperty.h"
#include "mitkConnectomicsRenderingNodeColorParameterProperty.h"
#include "mitkConnectomicsRenderingNodeFilteringProperty.h"
#include "mitkConnectomicsRenderingNodeRadiusParameterProperty.h"
#include "mitkConnectomicsRenderingNodeThresholdParameterProperty.h"
#include "mitkConnectomicsRenderingSchemeProperty.h"
#include <MitkConnectomicsExports.h>
#define MITK_REGISTER_ENUM_SUB_SERIALIZER(classname) \
\
namespace mitk \
{ \
\
class MITKCONNECTOMICS_EXPORT classname ## Serializer : public EnumerationPropertySerializer \
{ \
public: \
\
mitkClassMacro( classname ## Serializer, EnumerationPropertySerializer ) \
itkFactorylessNewMacro(Self) \
itkCloneMacro(Self) \
\
virtual BaseProperty::Pointer Deserialize(TiXmlElement* element) \
{ \
if (!element) return nullptr; \
const char* sa( element->Attribute("value") ); \
\
std::string s(sa?sa:""); \
classname::Pointer property = classname::New(); \
property->SetValue( s ); \
\
return property.GetPointer(); \
} \
\
protected: \
\
classname ## Serializer () {} \
virtual ~classname ## Serializer () {} \
}; \
\
} \
\
MITK_REGISTER_SERIALIZER( classname ## Serializer );
MITK_REGISTER_ENUM_SUB_SERIALIZER(ConnectomicsRenderingEdgeColorParameterProperty);
MITK_REGISTER_ENUM_SUB_SERIALIZER(ConnectomicsRenderingEdgeFilteringProperty);
MITK_REGISTER_ENUM_SUB_SERIALIZER(ConnectomicsRenderingEdgeRadiusParameterProperty);
MITK_REGISTER_ENUM_SUB_SERIALIZER(ConnectomicsRenderingEdgeThresholdParameterProperty);
MITK_REGISTER_ENUM_SUB_SERIALIZER(ConnectomicsRenderingNodeColorParameterProperty);
MITK_REGISTER_ENUM_SUB_SERIALIZER(ConnectomicsRenderingNodeFilteringProperty);
MITK_REGISTER_ENUM_SUB_SERIALIZER(ConnectomicsRenderingNodeRadiusParameterProperty);
MITK_REGISTER_ENUM_SUB_SERIALIZER(ConnectomicsRenderingNodeThresholdParameterProperty);
MITK_REGISTER_ENUM_SUB_SERIALIZER(ConnectomicsRenderingSchemeProperty);
#endif
diff --git a/Modules/Connectomics/Rendering/mitkConnectomicsNetworkMapper3D.cpp b/Modules/Connectomics/Rendering/mitkConnectomicsNetworkMapper3D.cpp
index 7b92f52..7946c92 100644
--- a/Modules/Connectomics/Rendering/mitkConnectomicsNetworkMapper3D.cpp
+++ b/Modules/Connectomics/Rendering/mitkConnectomicsNetworkMapper3D.cpp
@@ -1,830 +1,830 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsNetworkMapper3D.h"
#include "vtkGlyph3D.h"
#include "vtkGlyphSource2D.h"
#include "vtkGraphLayout.h"
#include "vtkGraphToPolyData.h"
#include <vtkMutableUndirectedGraph.h>
#include <vtkPassThroughLayoutStrategy.h>
#include <vtkPoints.h>
#include "mitkConnectomicsRenderingEdgeColorParameterProperty.h"
#include "mitkConnectomicsRenderingEdgeFilteringProperty.h"
#include "mitkConnectomicsRenderingEdgeRadiusParameterProperty.h"
#include "mitkConnectomicsRenderingEdgeThresholdParameterProperty.h"
#include "mitkConnectomicsRenderingNodeColorParameterProperty.h"
#include "mitkConnectomicsRenderingNodeFilteringProperty.h"
#include "mitkConnectomicsRenderingNodeRadiusParameterProperty.h"
#include "mitkConnectomicsRenderingNodeThresholdParameterProperty.h"
#include "mitkConnectomicsRenderingProperties.h"
#include "mitkConnectomicsRenderingSchemeProperty.h"
#include <mbilog.h>
#include <mitkManualPlacementAnnotationRenderer.h>
#include <vtkIndent.h>
#include <string>
#include <algorithm>
mitk::ConnectomicsNetworkMapper3D::ConnectomicsNetworkMapper3D()
{
m_NetworkAssembly = vtkPropAssembly::New();
m_Translator = mitk::FreeSurferParcellationTranslator::New();
}
mitk::ConnectomicsNetworkMapper3D::~ConnectomicsNetworkMapper3D()
{
m_NetworkAssembly->Delete();
}
void mitk::ConnectomicsNetworkMapper3D::GenerateDataForRenderer(mitk::BaseRenderer *renderer)
{
if (this->GetInput() == nullptr)
{
m_TextOverlay3D->UnRegisterMicroservice();
return;
}
bool propertiesHaveChanged = this->PropertiesChanged();
if (this->GetInput()->GetIsModified() || propertiesHaveChanged)
{
m_NetworkAssembly->Delete();
m_NetworkAssembly = vtkPropAssembly::New();
// Here is the part where a graph is given and converted to points and connections between points...
std::vector<mitk::ConnectomicsNetwork::NetworkNode> vectorOfNodes = this->GetInput()->GetVectorOfAllNodes();
std::vector<std::pair<std::pair<mitk::ConnectomicsNetwork::NetworkNode, mitk::ConnectomicsNetwork::NetworkNode>,
mitk::ConnectomicsNetwork::NetworkEdge>>
vectorOfEdges = this->GetInput()->GetVectorOfAllEdges();
// Decide on the style of rendering due to property
if (m_ChosenRenderingScheme == connectomicsRenderingMITKScheme)
{
mitk::Point3D tempWorldPoint, tempCNFGeometryPoint;
////// Prepare BalloonWidgets/Overlays: ////////////////////
if ((m_ChosenNodeLabel == "" || m_ChosenNodeLabel == "-1") && m_TextOverlay3D)
{
m_TextOverlay3D->UnRegisterMicroservice();
GetDataNode()->SetProperty(
connectomicsRenderingBalloonTextName.c_str(), mitk::StringProperty::New(""), nullptr);
GetDataNode()->SetProperty(
connectomicsRenderingBalloonNodeStatsName.c_str(), mitk::StringProperty::New(""), nullptr);
}
//////////////////////Prepare coloring and radius////////////
std::vector<double> vectorOfNodeRadiusParameterValues;
vectorOfNodeRadiusParameterValues.resize(vectorOfNodes.size());
double maxNodeRadiusParameterValue(
FillNodeParameterVector(&vectorOfNodeRadiusParameterValues, m_NodeRadiusParameter));
std::vector<double> vectorOfNodeColorParameterValues;
vectorOfNodeColorParameterValues.resize(vectorOfNodes.size());
double maxNodeColorParameterValue(
FillNodeParameterVector(&vectorOfNodeColorParameterValues, m_NodeColorParameter));
std::vector<double> vectorOfEdgeRadiusParameterValues;
vectorOfEdgeRadiusParameterValues.resize(vectorOfEdges.size());
double maxEdgeRadiusParameterValue(
FillEdgeParameterVector(&vectorOfEdgeRadiusParameterValues, m_EdgeRadiusParameter));
std::vector<double> vectorOfEdgeColorParameterValues;
vectorOfEdgeColorParameterValues.resize(vectorOfEdges.size());
double maxEdgeColorParameterValue(
FillEdgeParameterVector(&vectorOfEdgeColorParameterValues, m_EdgeColorParameter));
//////////////////////Prepare Filtering//////////////////////
// true will be rendered
std::vector<bool> vectorOfNodeFilterBools(vectorOfNodes.size(), true);
if (m_ChosenNodeFilter == connectomicsRenderingNodeThresholdingFilter)
{
FillNodeFilterBoolVector(&vectorOfNodeFilterBools, m_NodeThresholdParameter);
}
std::vector<bool> vectorOfEdgeFilterBools(vectorOfEdges.size(), true);
if (m_ChosenEdgeFilter == connectomicsRenderingEdgeThresholdFilter)
{
FillEdgeFilterBoolVector(&vectorOfEdgeFilterBools, m_EdgeThresholdParameter);
}
//////////////////////Create Spheres/////////////////////////
std::stringstream
nodeLabelStream; // local stream variable to hold csv list of node label names and node label numbers.
for (unsigned int i = 0; i < vectorOfNodes.size(); i++)
{
vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New();
for (unsigned int dimension = 0; dimension < 3; dimension++)
{
tempCNFGeometryPoint.SetElement(dimension, vectorOfNodes[i].coordinates[dimension]);
}
GetDataNode()->GetData()->GetGeometry()->IndexToWorld(tempCNFGeometryPoint, tempWorldPoint);
sphereSource->SetCenter(tempWorldPoint[0], tempWorldPoint[1], tempWorldPoint[2]);
// determine radius
double radiusFactor = vectorOfNodeRadiusParameterValues[i] / maxNodeRadiusParameterValue;
double radius = m_NodeRadiusStart + (m_NodeRadiusEnd - m_NodeRadiusStart) * radiusFactor;
sphereSource->SetRadius(radius);
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(sphereSource->GetOutputPort());
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
// determine color
double colorFactor = vectorOfNodeColorParameterValues[i] / maxNodeColorParameterValue;
double redStart = m_NodeColorStart.GetElement(0);
double greenStart = m_NodeColorStart.GetElement(1);
double blueStart = m_NodeColorStart.GetElement(2);
double redEnd = m_NodeColorEnd.GetElement(0);
double greenEnd = m_NodeColorEnd.GetElement(1);
double blueEnd = m_NodeColorEnd.GetElement(2);
double red = redStart + (redEnd - redStart) * colorFactor;
double green = greenStart + (greenEnd - greenStart) * colorFactor;
double blue = blueStart + (blueEnd - blueStart) * colorFactor;
actor->GetProperty()->SetColor(red, green, blue);
// append to csv list of nodelabels.
nodeLabelStream << m_Translator->GetName(std::stoi(vectorOfNodes[i].label)) << ": " << vectorOfNodes[i].label
<< ",";
if (vectorOfNodeFilterBools[i])
{
if (vectorOfNodes[i].label == m_ChosenNodeLabel)
{ // if chosen and enabled, show information in Balloon or TextOverlay:
// What to show:
std::stringstream balloonStringstream;
balloonStringstream << "Node id: " << vectorOfNodes[i].id << "\nlabel: " << vectorOfNodes[i].label
<< "\nname: " << m_Translator->GetName(std::stoi(vectorOfNodes[i].label)) << std::endl;
m_BalloonText = balloonStringstream.str();
GetDataNode()->SetProperty(
connectomicsRenderingBalloonTextName.c_str(), mitk::StringProperty::New(m_BalloonText.c_str()), nullptr);
std::stringstream balloonNodeStatsStream;
balloonNodeStatsStream << "Coordinates: (" << vectorOfNodes[i].coordinates[0] << " ; "
<< vectorOfNodes[i].coordinates[1] << " ; " << vectorOfNodes[i].coordinates[2]
<< " )"
<< "\nDegree: " << (this->GetInput()->GetDegreeOfNodes()).at(vectorOfNodes[i].id)
<< "\nBetweenness centrality: "
<< (this->GetInput()->GetNodeBetweennessVector()).at(vectorOfNodes[i].id)
<< "\nClustering coefficient: "
<< (this->GetInput()->GetLocalClusteringCoefficients()).at(vectorOfNodes[i].id)
<< std::endl;
m_BalloonNodeStats = balloonNodeStatsStream.str();
GetDataNode()->SetProperty(connectomicsRenderingBalloonNodeStatsName.c_str(),
mitk::StringProperty::New(m_BalloonNodeStats.c_str()),
nullptr);
// Where to show:
float r[3];
r[0] = vectorOfNodes[i].coordinates[0];
r[1] = vectorOfNodes[i].coordinates[1];
r[2] = vectorOfNodes[i].coordinates[2];
mitk::Point3D BalloonAnchor(r);
mitk::Point3D BalloonAnchorWorldCoord(r);
GetDataNode()->GetData()->GetGeometry()->IndexToWorld(BalloonAnchor, BalloonAnchorWorldCoord);
// How to show:
if (m_ChosenNodeLabel != "-1")
{
if (m_TextOverlay3D != nullptr)
{
m_TextOverlay3D->UnRegisterMicroservice();
}
m_TextOverlay3D = mitk::TextAnnotation3D::New();
mitk::ManualPlacementAnnotationRenderer::AddAnnotation(m_TextOverlay3D.GetPointer(), renderer);
m_TextOverlay3D->SetFontSize(2);
m_TextOverlay3D->SetColor(0.96, 0.69, 0.01);
m_TextOverlay3D->SetOpacity(0.81);
m_TextOverlay3D->SetPosition3D(BalloonAnchorWorldCoord);
m_TextOverlay3D->SetText("...." + m_BalloonText);
m_TextOverlay3D->SetForceInForeground(true); // TODO: does not work anymore.
m_TextOverlay3D->SetVisibility(GetDataNode()->IsVisible(renderer));
// Colorize chosen node:
actor->GetProperty()->SetColor(1.0, 0.69, 0.01);
}
}
m_NetworkAssembly->AddPart(actor);
}
}
m_AllNodeLabels = nodeLabelStream.str(); // Store all Node Names and Node Labels in 1 Property.
m_AllNodeLabels.erase(m_AllNodeLabels.rfind(","), 1); // remove trailing ,.
GetDataNode()->SetProperty(connectomicsRenderingBalloonAllNodeLabelsName.c_str(),
mitk::StringProperty::New(m_AllNodeLabels.c_str()),
nullptr);
//////////////////////Create Tubes/////////////////////////
for (unsigned int i = 0; i < vectorOfEdges.size(); i++)
{
vtkSmartPointer<vtkLineSource> lineSource = vtkSmartPointer<vtkLineSource>::New();
for (unsigned int dimension = 0; dimension < 3; dimension++)
{
tempCNFGeometryPoint[dimension] = vectorOfEdges[i].first.first.coordinates[dimension];
}
GetDataNode()->GetData()->GetGeometry()->IndexToWorld(tempCNFGeometryPoint, tempWorldPoint);
lineSource->SetPoint1(tempWorldPoint[0], tempWorldPoint[1], tempWorldPoint[2]);
for (unsigned int dimension = 0; dimension < 3; dimension++)
{
tempCNFGeometryPoint[dimension] = vectorOfEdges[i].first.second.coordinates[dimension];
}
GetDataNode()->GetData()->GetGeometry()->IndexToWorld(tempCNFGeometryPoint, tempWorldPoint);
lineSource->SetPoint2(tempWorldPoint[0], tempWorldPoint[1], tempWorldPoint[2]);
vtkSmartPointer<vtkTubeFilter> tubes = vtkSmartPointer<vtkTubeFilter>::New();
tubes->SetInputConnection(lineSource->GetOutputPort());
tubes->SetNumberOfSides(12);
// determine radius
double radiusFactor = vectorOfEdgeRadiusParameterValues[i] / maxEdgeRadiusParameterValue;
double radius = m_EdgeRadiusStart + (m_EdgeRadiusEnd - m_EdgeRadiusStart) * radiusFactor;
tubes->SetRadius(radius);
// originally we used a logarithmic scaling,
// double radiusFactor = 1.0 + ((double) vectorOfEdges[i].second.weight) / 10.0 ;
// tubes->SetRadius( std::log10( radiusFactor ) );
vtkSmartPointer<vtkPolyDataMapper> mapper2 = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper2->SetInputConnection(tubes->GetOutputPort());
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper2);
// determine color
double colorFactor = vectorOfEdgeColorParameterValues[i] / maxEdgeColorParameterValue;
double redStart = m_EdgeColorStart.GetElement(0);
double greenStart = m_EdgeColorStart.GetElement(1);
double blueStart = m_EdgeColorStart.GetElement(2);
double redEnd = m_EdgeColorEnd.GetElement(0);
double greenEnd = m_EdgeColorEnd.GetElement(1);
double blueEnd = m_EdgeColorEnd.GetElement(2);
double red = redStart + (redEnd - redStart) * colorFactor;
double green = greenStart + (greenEnd - greenStart) * colorFactor;
double blue = blueStart + (blueEnd - blueStart) * colorFactor;
actor->GetProperty()->SetColor(red, green, blue);
if (vectorOfEdgeFilterBools[i])
{
m_NetworkAssembly->AddPart(actor);
}
}
}
else if (m_ChosenRenderingScheme == connectomicsRenderingVTKScheme)
{
vtkSmartPointer<vtkMutableUndirectedGraph> graph = vtkSmartPointer<vtkMutableUndirectedGraph>::New();
std::vector<vtkIdType> networkToVTKvector;
networkToVTKvector.resize(vectorOfNodes.size());
for (unsigned int i = 0; i < vectorOfNodes.size(); i++)
{
networkToVTKvector[vectorOfNodes[i].id] = graph->AddVertex();
}
for (unsigned int i = 0; i < vectorOfEdges.size(); i++)
{
graph->AddEdge(networkToVTKvector[vectorOfEdges[i].first.first.id],
networkToVTKvector[vectorOfEdges[i].first.second.id]);
}
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
for (unsigned int i = 0; i < vectorOfNodes.size(); i++)
{
double x = vectorOfNodes[i].coordinates[0];
double y = vectorOfNodes[i].coordinates[1];
double z = vectorOfNodes[i].coordinates[2];
points->InsertNextPoint(x, y, z);
}
graph->SetPoints(points);
vtkGraphLayout *layout = vtkGraphLayout::New();
layout->SetInputData(graph);
vtkPassThroughLayoutStrategy *ptls = vtkPassThroughLayoutStrategy::New();
layout->SetLayoutStrategy(ptls);
vtkGraphToPolyData *graphToPoly = vtkGraphToPolyData::New();
graphToPoly->SetInputConnection(layout->GetOutputPort());
// Create the standard VTK polydata mapper and actor
// for the connections (edges) in the tree.
vtkPolyDataMapper *edgeMapper = vtkPolyDataMapper::New();
edgeMapper->SetInputConnection(graphToPoly->GetOutputPort());
vtkActor *edgeActor = vtkActor::New();
edgeActor->SetMapper(edgeMapper);
edgeActor->GetProperty()->SetColor(0.0, 0.5, 1.0);
// Glyph the points of the tree polydata to create
// VTK_VERTEX cells at each vertex in the tree.
vtkGlyph3D *vertGlyph = vtkGlyph3D::New();
vertGlyph->SetInputConnection(0, graphToPoly->GetOutputPort());
vtkGlyphSource2D *glyphSource = vtkGlyphSource2D::New();
glyphSource->SetGlyphTypeToVertex();
vertGlyph->SetInputConnection(1, glyphSource->GetOutputPort());
// Create a mapper for the vertices, and tell the mapper
// to use the specified color array.
vtkPolyDataMapper *vertMapper = vtkPolyDataMapper::New();
vertMapper->SetInputConnection(vertGlyph->GetOutputPort());
/*if (colorArray)
{
vertMapper->SetScalarModeToUsePointFieldData();
vertMapper->SelectColorArray(colorArray);
vertMapper->SetScalarRange(colorRange);
}*/
// Create an actor for the vertices. Move the actor forward
// in the z direction so it is drawn on top of the edge actor.
vtkActor *vertActor = vtkActor::New();
vertActor->SetMapper(vertMapper);
vertActor->GetProperty()->SetPointSize(5);
vertActor->SetPosition(0, 0, 0.001);
// vtkProp3D.h: virtual void SetPosition(double,double,double):
// Set/Get/Add the position of the Prop3D in world coordinates.
m_NetworkAssembly->AddPart(edgeActor);
m_NetworkAssembly->AddPart(vertActor);
}
(static_cast<mitk::ConnectomicsNetwork *>(GetDataNode()->GetData()))->SetIsModified(false);
}
}
const mitk::ConnectomicsNetwork *mitk::ConnectomicsNetworkMapper3D::GetInput()
{
return static_cast<const mitk::ConnectomicsNetwork *>(GetDataNode()->GetData());
}
void mitk::ConnectomicsNetworkMapper3D::SetDefaultProperties(DataNode *node, BaseRenderer *renderer, bool overwrite)
{
// Initialize enumeration properties
mitk::ConnectomicsRenderingSchemeProperty::Pointer connectomicsRenderingScheme =
mitk::ConnectomicsRenderingSchemeProperty::New();
mitk::ConnectomicsRenderingEdgeFilteringProperty::Pointer connectomicsRenderingEdgeFiltering =
mitk::ConnectomicsRenderingEdgeFilteringProperty::New();
mitk::ConnectomicsRenderingNodeFilteringProperty::Pointer connectomicsRenderingNodeFiltering =
mitk::ConnectomicsRenderingNodeFilteringProperty::New();
mitk::ConnectomicsRenderingNodeColorParameterProperty::Pointer connectomicsRenderingNodeGradientColorParameter =
mitk::ConnectomicsRenderingNodeColorParameterProperty::New();
mitk::ConnectomicsRenderingNodeRadiusParameterProperty::Pointer connectomicsRenderingNodeRadiusParameter =
mitk::ConnectomicsRenderingNodeRadiusParameterProperty::New();
mitk::ConnectomicsRenderingEdgeColorParameterProperty::Pointer connectomicsRenderingEdgeGradientColorParameter =
mitk::ConnectomicsRenderingEdgeColorParameterProperty::New();
mitk::ConnectomicsRenderingEdgeRadiusParameterProperty::Pointer connectomicsRenderingEdgeRadiusParameter =
mitk::ConnectomicsRenderingEdgeRadiusParameterProperty::New();
mitk::ConnectomicsRenderingNodeThresholdParameterProperty::Pointer connectomicsRenderingNodeThresholdParameter =
mitk::ConnectomicsRenderingNodeThresholdParameterProperty::New();
mitk::ConnectomicsRenderingEdgeThresholdParameterProperty::Pointer connectomicsRenderingEdgeThresholdParameter =
mitk::ConnectomicsRenderingEdgeThresholdParameterProperty::New();
mitk::StringProperty::Pointer balloonText = mitk::StringProperty::New();
// set the properties
node->AddProperty(connectomicsRenderingSchemePropertyName.c_str(), connectomicsRenderingScheme, renderer, overwrite);
node->AddProperty(
connectomicsRenderingEdgeFilteringPropertyName.c_str(), connectomicsRenderingEdgeFiltering, renderer, overwrite);
node->AddProperty(connectomicsRenderingEdgeThresholdFilterParameterName.c_str(),
connectomicsRenderingEdgeThresholdParameter,
renderer,
overwrite);
node->AddProperty(connectomicsRenderingEdgeThresholdFilterThresholdName.c_str(),
connectomicsRenderingEdgeThresholdFilterThresholdDefault,
renderer,
overwrite);
node->AddProperty(
connectomicsRenderingNodeFilteringPropertyName.c_str(), connectomicsRenderingNodeFiltering, renderer, overwrite);
node->AddProperty(connectomicsRenderingNodeThresholdFilterParameterName.c_str(),
connectomicsRenderingNodeThresholdParameter,
renderer,
overwrite);
node->AddProperty(connectomicsRenderingNodeThresholdFilterThresholdName.c_str(),
connectomicsRenderingNodeThresholdFilterThresholdDefault,
renderer,
overwrite);
node->AddProperty(connectomicsRenderingNodeGradientStartColorName.c_str(),
connectomicsRenderingNodeGradientStartColorDefault,
renderer,
overwrite);
node->AddProperty(connectomicsRenderingNodeGradientEndColorName.c_str(),
connectomicsRenderingNodeGradientEndColorDefault,
renderer,
overwrite);
node->AddProperty(connectomicsRenderingNodeGradientColorParameterName.c_str(),
connectomicsRenderingNodeGradientColorParameter,
renderer,
overwrite);
node->AddProperty(
connectomicsRenderingNodeRadiusStartName.c_str(), connectomicsRenderingNodeRadiusStartDefault, renderer, overwrite);
node->AddProperty(
connectomicsRenderingNodeRadiusEndName.c_str(), connectomicsRenderingNodeRadiusEndDefault, renderer, overwrite);
node->AddProperty(connectomicsRenderingNodeRadiusParameterName.c_str(),
connectomicsRenderingNodeRadiusParameter,
renderer,
overwrite);
node->AddProperty(
connectomicsRenderingNodeChosenNodeName.c_str(), connectomicsRenderingNodeChosenNodeDefault, renderer, overwrite);
node->AddProperty(connectomicsRenderingEdgeGradientStartColorName.c_str(),
connectomicsRenderingEdgeGradientStartColorDefault,
renderer,
overwrite);
node->AddProperty(connectomicsRenderingEdgeGradientEndColorName.c_str(),
connectomicsRenderingEdgeGradientEndColorDefault,
renderer,
overwrite);
node->AddProperty(connectomicsRenderingEdgeGradientColorParameterName.c_str(),
connectomicsRenderingEdgeGradientColorParameter,
renderer,
overwrite);
node->AddProperty(
connectomicsRenderingEdgeRadiusStartName.c_str(), connectomicsRenderingEdgeRadiusStartDefault, renderer, overwrite);
node->AddProperty(
connectomicsRenderingEdgeRadiusEndName.c_str(), connectomicsRenderingEdgeRadiusEndDefault, renderer, overwrite);
node->AddProperty(connectomicsRenderingEdgeRadiusParameterName.c_str(),
connectomicsRenderingEdgeRadiusParameter,
renderer,
overwrite);
node->AddProperty(connectomicsRenderingBalloonTextName.c_str(),
balloonText,
nullptr,
overwrite); // renderer=nullptr: Property is renderer independent.
Superclass::SetDefaultProperties(node, renderer, overwrite);
}
void mitk::ConnectomicsNetworkMapper3D::UpdateVtkObjects()
{
// TODO: implement
}
vtkProp *mitk::ConnectomicsNetworkMapper3D::GetVtkProp(mitk::BaseRenderer * /*renderer*/)
{
return m_NetworkAssembly;
}
bool mitk::ConnectomicsNetworkMapper3D::PropertiesChanged()
{
mitk::ConnectomicsRenderingSchemeProperty *renderingScheme = static_cast<mitk::ConnectomicsRenderingSchemeProperty *>(
this->GetDataNode()->GetProperty(connectomicsRenderingSchemePropertyName.c_str()));
mitk::ConnectomicsRenderingEdgeFilteringProperty *edgeFilter =
static_cast<mitk::ConnectomicsRenderingEdgeFilteringProperty *>(
this->GetDataNode()->GetProperty(connectomicsRenderingEdgeFilteringPropertyName.c_str()));
mitk::FloatProperty *edgeThreshold = static_cast<mitk::FloatProperty *>(
this->GetDataNode()->GetProperty(connectomicsRenderingEdgeThresholdFilterThresholdName.c_str()));
mitk::ConnectomicsRenderingNodeFilteringProperty *nodeFilter =
static_cast<mitk::ConnectomicsRenderingNodeFilteringProperty *>(
this->GetDataNode()->GetProperty(connectomicsRenderingNodeFilteringPropertyName.c_str()));
mitk::ConnectomicsRenderingNodeThresholdParameterProperty *nodeThresholdParameter =
static_cast<mitk::ConnectomicsRenderingNodeThresholdParameterProperty *>(
this->GetDataNode()->GetProperty(connectomicsRenderingNodeThresholdFilterParameterName.c_str()));
mitk::ConnectomicsRenderingEdgeThresholdParameterProperty *edgeThresholdParameter =
static_cast<mitk::ConnectomicsRenderingEdgeThresholdParameterProperty *>(
this->GetDataNode()->GetProperty(connectomicsRenderingEdgeThresholdFilterParameterName.c_str()));
mitk::FloatProperty *nodeThreshold = static_cast<mitk::FloatProperty *>(
this->GetDataNode()->GetProperty(connectomicsRenderingNodeThresholdFilterThresholdName.c_str()));
mitk::ColorProperty *nodeColorStart = static_cast<mitk::ColorProperty *>(
this->GetDataNode()->GetProperty(connectomicsRenderingNodeGradientStartColorName.c_str()));
mitk::ColorProperty *nodeColorEnd = static_cast<mitk::ColorProperty *>(
this->GetDataNode()->GetProperty(connectomicsRenderingNodeGradientEndColorName.c_str()));
mitk::FloatProperty *nodeRadiusStart = static_cast<mitk::FloatProperty *>(
this->GetDataNode()->GetProperty(connectomicsRenderingNodeRadiusStartName.c_str()));
mitk::FloatProperty *nodeRadiusEnd = static_cast<mitk::FloatProperty *>(
this->GetDataNode()->GetProperty(connectomicsRenderingNodeRadiusEndName.c_str()));
mitk::StringProperty *chosenNode = static_cast<mitk::StringProperty *>(
this->GetDataNode()->GetProperty(connectomicsRenderingNodeChosenNodeName.c_str()));
mitk::ColorProperty *edgeColorStart = static_cast<mitk::ColorProperty *>(
this->GetDataNode()->GetProperty(connectomicsRenderingEdgeGradientStartColorName.c_str()));
mitk::ColorProperty *edgeColorEnd = static_cast<mitk::ColorProperty *>(
this->GetDataNode()->GetProperty(connectomicsRenderingEdgeGradientEndColorName.c_str()));
mitk::FloatProperty *edgeRadiusStart = static_cast<mitk::FloatProperty *>(
this->GetDataNode()->GetProperty(connectomicsRenderingEdgeRadiusStartName.c_str()));
mitk::FloatProperty *edgeRadiusEnd = static_cast<mitk::FloatProperty *>(
this->GetDataNode()->GetProperty(connectomicsRenderingEdgeRadiusEndName.c_str()));
mitk::ConnectomicsRenderingNodeColorParameterProperty *nodeColorParameter =
static_cast<mitk::ConnectomicsRenderingNodeColorParameterProperty *>(
this->GetDataNode()->GetProperty(connectomicsRenderingNodeGradientColorParameterName.c_str()));
mitk::ConnectomicsRenderingNodeRadiusParameterProperty *nodeRadiusParameter =
static_cast<mitk::ConnectomicsRenderingNodeRadiusParameterProperty *>(
this->GetDataNode()->GetProperty(connectomicsRenderingNodeRadiusParameterName.c_str()));
mitk::ConnectomicsRenderingEdgeColorParameterProperty *edgeColorParameter =
static_cast<mitk::ConnectomicsRenderingEdgeColorParameterProperty *>(
this->GetDataNode()->GetProperty(connectomicsRenderingEdgeGradientColorParameterName.c_str()));
mitk::ConnectomicsRenderingEdgeRadiusParameterProperty *edgeRadiusParameter =
static_cast<mitk::ConnectomicsRenderingEdgeRadiusParameterProperty *>(
this->GetDataNode()->GetProperty(connectomicsRenderingEdgeRadiusParameterName.c_str()));
if (m_ChosenRenderingScheme != renderingScheme->GetValueAsString() ||
m_ChosenEdgeFilter != edgeFilter->GetValueAsString() || m_EdgeThreshold != edgeThreshold->GetValue() ||
m_EdgeThresholdParameter != edgeThresholdParameter->GetValueAsString() ||
m_ChosenNodeFilter != nodeFilter->GetValueAsString() || m_NodeThreshold != nodeThreshold->GetValue() ||
m_NodeThresholdParameter != nodeThresholdParameter->GetValueAsString() ||
m_NodeColorStart != nodeColorStart->GetValue() || m_NodeColorEnd != nodeColorEnd->GetValue() ||
m_NodeRadiusStart != nodeRadiusStart->GetValue() || m_NodeRadiusEnd != nodeRadiusEnd->GetValue() ||
m_ChosenNodeLabel != chosenNode->GetValueAsString() || m_EdgeColorStart != edgeColorStart->GetValue() ||
m_EdgeColorEnd != edgeColorEnd->GetValue() || m_EdgeRadiusStart != edgeRadiusStart->GetValue() ||
m_EdgeRadiusEnd != edgeRadiusEnd->GetValue() || m_NodeColorParameter != nodeColorParameter->GetValueAsString() ||
m_NodeRadiusParameter != nodeRadiusParameter->GetValueAsString() ||
m_EdgeColorParameter != edgeColorParameter->GetValueAsString() ||
m_EdgeRadiusParameter != edgeRadiusParameter->GetValueAsString())
{
m_ChosenRenderingScheme = renderingScheme->GetValueAsString();
m_ChosenEdgeFilter = edgeFilter->GetValueAsString();
m_EdgeThreshold = edgeThreshold->GetValue();
m_EdgeThresholdParameter = edgeThresholdParameter->GetValueAsString();
m_ChosenNodeFilter = nodeFilter->GetValueAsString();
m_NodeThreshold = nodeThreshold->GetValue();
m_NodeThresholdParameter = nodeThresholdParameter->GetValueAsString();
m_NodeColorStart = nodeColorStart->GetValue();
m_NodeColorEnd = nodeColorEnd->GetValue();
m_NodeRadiusStart = nodeRadiusStart->GetValue();
m_NodeRadiusEnd = nodeRadiusEnd->GetValue();
m_ChosenNodeLabel = chosenNode->GetValueAsString();
m_EdgeColorStart = edgeColorStart->GetValue();
m_EdgeColorEnd = edgeColorEnd->GetValue();
m_EdgeRadiusStart = edgeRadiusStart->GetValue();
m_EdgeRadiusEnd = edgeRadiusEnd->GetValue();
m_NodeColorParameter = nodeColorParameter->GetValueAsString();
m_NodeRadiusParameter = nodeRadiusParameter->GetValueAsString();
m_EdgeColorParameter = edgeColorParameter->GetValueAsString();
m_EdgeRadiusParameter = edgeRadiusParameter->GetValueAsString();
return true;
}
return false;
}
double mitk::ConnectomicsNetworkMapper3D::FillNodeParameterVector(std::vector<double> *parameterVector,
std::string parameterName)
{
int end(parameterVector->size());
// constant parameter - uniform style
if (parameterName == connectomicsRenderingNodeParameterConstant)
{
for (int index(0); index < end; index++)
{
parameterVector->at(index) = 1.0;
}
return 1.0;
}
double maximum(0.0);
// using the degree as parameter
if (parameterName == connectomicsRenderingNodeParameterDegree)
{
std::vector<int> vectorOfDegree = this->GetInput()->GetDegreeOfNodes();
for (int index(0); index < end; index++)
{
parameterVector->at(index) = vectorOfDegree[index];
}
maximum = *std::max_element(parameterVector->begin(), parameterVector->end());
}
// using betweenness centrality as parameter
if (parameterName == connectomicsRenderingNodeParameterBetweenness)
{
std::vector<double> vectorOfBetweenness = this->GetInput()->GetNodeBetweennessVector();
for (int index(0); index < end; index++)
{
parameterVector->at(index) = vectorOfBetweenness[index];
}
maximum = *std::max_element(parameterVector->begin(), parameterVector->end());
}
// using clustering coefficient as parameter
if (parameterName == connectomicsRenderingNodeParameterClustering)
{
const std::vector<double> vectorOfClustering = this->GetInput()->GetLocalClusteringCoefficients();
for (int index(0); index < end; index++)
{
parameterVector->at(index) = vectorOfClustering[index];
}
maximum = *std::max_element(parameterVector->begin(), parameterVector->end());
}
// using distance to a specific node as parameter
if (parameterName == connectomicsRenderingNodeParameterColoringShortestPath)
{
bool labelFound(this->GetInput()->CheckForLabel(m_ChosenNodeLabel));
// check whether the chosen node is valid
if (!labelFound)
{
MITK_WARN << "Node chosen for rendering is not valid.";
for (int index(0); index < end; index++)
{
parameterVector->at(index) = 1.0;
}
return 1.0;
}
else
{
const std::vector<double> distanceVector =
this->GetInput()->GetShortestDistanceVectorFromLabel(m_ChosenNodeLabel);
for (int index(0); index < end; index++)
{
parameterVector->at(index) = distanceVector[index];
}
maximum = *std::max_element(parameterVector->begin(), parameterVector->end());
}
}
// if the maximum is nearly zero
if (std::abs(maximum) < mitk::eps)
{
maximum = 1.0;
}
return maximum;
}
double mitk::ConnectomicsNetworkMapper3D::FillEdgeParameterVector(std::vector<double> *parameterVector,
std::string parameterName)
{
int end(parameterVector->size());
// constant parameter - uniform style
if (parameterName == connectomicsRenderingEdgeParameterConstant)
{
for (int index(0); index < end; index++)
{
parameterVector->at(index) = 1.0;
}
return 1.0;
}
double maximum(0.0);
// using the weight as parameter
if (parameterName == connectomicsRenderingEdgeParameterWeight)
{
std::vector<std::pair<std::pair<mitk::ConnectomicsNetwork::NetworkNode, mitk::ConnectomicsNetwork::NetworkNode>,
mitk::ConnectomicsNetwork::NetworkEdge>>
vectorOfEdges = this->GetInput()->GetVectorOfAllEdges();
for (int index(0); index < end; index++)
{
parameterVector->at(index) = vectorOfEdges[index].second.fiber_count;
}
maximum = *std::max_element(parameterVector->begin(), parameterVector->end());
}
// using the edge centrality as parameter
if (parameterName == connectomicsRenderingEdgeParameterCentrality)
{
const std::vector<double> vectorOfCentrality = this->GetInput()->GetEdgeBetweennessVector();
for (int index(0); index < end; index++)
{
parameterVector->at(index) = vectorOfCentrality[index];
}
maximum = *std::max_element(parameterVector->begin(), parameterVector->end());
}
// if the maximum is nearly zero
if (std::abs(maximum) < mitk::eps)
{
maximum = 1.0;
}
return maximum;
}
void mitk::ConnectomicsNetworkMapper3D::FillNodeFilterBoolVector(std::vector<bool> *boolVector,
std::string parameterName)
{
std::vector<double> parameterVector;
parameterVector.resize(boolVector->size());
int end(parameterVector.size());
// using the degree as parameter
if (parameterName == connectomicsRenderingNodeParameterDegree)
{
std::vector<int> vectorOfDegree = this->GetInput()->GetDegreeOfNodes();
for (int index(0); index < end; index++)
{
parameterVector.at(index) = vectorOfDegree[index];
}
}
// using betweenness centrality as parameter
if (parameterName == connectomicsRenderingNodeParameterBetweenness)
{
std::vector<double> vectorOfBetweenness = this->GetInput()->GetNodeBetweennessVector();
for (int index(0); index < end; index++)
{
parameterVector.at(index) = vectorOfBetweenness[index];
}
}
// using clustering coefficient as parameter
if (parameterName == connectomicsRenderingNodeParameterClustering)
{
const std::vector<double> vectorOfClustering = this->GetInput()->GetLocalClusteringCoefficients();
for (int index(0); index < end; index++)
{
parameterVector.at(index) = vectorOfClustering[index];
}
}
for (int index(0), end(boolVector->size()); index < end; index++)
{
if (parameterVector.at(index) >= m_NodeThreshold)
{
boolVector->at(index) = true;
}
else
{
boolVector->at(index) = false;
}
}
return;
}
void mitk::ConnectomicsNetworkMapper3D::FillEdgeFilterBoolVector(std::vector<bool> *boolVector,
std::string parameterName)
{
std::vector<double> parameterVector;
parameterVector.resize(boolVector->size());
int end(parameterVector.size());
// using the weight as parameter
if (parameterName == connectomicsRenderingEdgeParameterWeight)
{
std::vector<std::pair<std::pair<mitk::ConnectomicsNetwork::NetworkNode, mitk::ConnectomicsNetwork::NetworkNode>,
mitk::ConnectomicsNetwork::NetworkEdge>>
vectorOfEdges = this->GetInput()->GetVectorOfAllEdges();
for (int index(0); index < end; index++)
{
parameterVector.at(index) = vectorOfEdges[index].second.fiber_count;
}
}
// using the edge centrality as parameter
if (parameterName == connectomicsRenderingEdgeParameterCentrality)
{
const std::vector<double> vectorOfCentrality = this->GetInput()->GetEdgeBetweennessVector();
for (int index(0); index < end; index++)
{
parameterVector.at(index) = vectorOfCentrality[index];
}
}
for (int index(0), end(boolVector->size()); index < end; index++)
{
if (parameterVector.at(index) >= m_EdgeThreshold)
{
boolVector->at(index) = true;
}
else
{
boolVector->at(index) = false;
}
}
return;
}
diff --git a/Modules/Connectomics/Rendering/mitkConnectomicsNetworkMapper3D.h b/Modules/Connectomics/Rendering/mitkConnectomicsNetworkMapper3D.h
index 222f50d..db500db 100644
--- a/Modules/Connectomics/Rendering/mitkConnectomicsNetworkMapper3D.h
+++ b/Modules/Connectomics/Rendering/mitkConnectomicsNetworkMapper3D.h
@@ -1,145 +1,145 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 ConnectomicsNetworkMapper3D_H_HEADER_INCLUDED
#define ConnectomicsNetworkMapper3D_H_HEADER_INCLUDED
// VTK includes
#include "vtkPropAssembly.h"
#include <vtkSmartPointer.h>
// MITK includes
// base class
#include "mitkVtkMapper.h"
// data type
#include "mitkConnectomicsNetwork.h"
#include <vtkActor.h>
#include <vtkCellArray.h>
#include <vtkCellData.h>
#include <vtkDoubleArray.h>
#include <vtkLineSource.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkPolyLine.h>
#include <vtkProperty.h>
#include <vtkSphereSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkTubeFilter.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkInteractorStyleTrackball.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include "mitkFreeSurferParcellationTranslator.h"
#include "mitkTextAnnotation2D.h"
#include "mitkTextAnnotation3D.h"
#include "mitkVtkInteractorStyle.h"
#include <mitkManualPlacementAnnotationRenderer.h>
#include <vtkActor2D.h>
#include <vtkPolyDataMapper2D.h>
#include <vtkProperty2D.h>
#include <vtkRegularPolygonSource.h>
#include <iostream>
#include <string>
#include <vector>
#include <MitkConnectomicsExports.h>
namespace mitk
{
/**
* \brief Mapper for Networks
* \ingroup Mapper
*/
class MITKCONNECTOMICS_EXPORT ConnectomicsNetworkMapper3D : public VtkMapper
{
public:
mitkClassMacro(ConnectomicsNetworkMapper3D, VtkMapper);
itkFactorylessNewMacro(Self) itkCloneMacro(Self)
vtkProp *GetVtkProp(
mitk::BaseRenderer *renderer) override; // looks like deprecated.. should be replaced bz GetViewProp()
static void SetDefaultProperties(DataNode *node, BaseRenderer *renderer = nullptr, bool overwrite = false);
void GenerateDataForRenderer(mitk::BaseRenderer *renderer) override;
virtual const mitk::ConnectomicsNetwork *GetInput();
protected:
ConnectomicsNetworkMapper3D();
~ConnectomicsNetworkMapper3D() override;
void UpdateVtkObjects();
vtkPropAssembly *m_NetworkAssembly;
/**
* \brief Returns true if the properties have changed since the last data generation
*/
bool PropertiesChanged();
// Create vectors for customizing color and radius and return maximum
double FillNodeParameterVector(std::vector<double> *parameterVector, std::string parameterName);
double FillEdgeParameterVector(std::vector<double> *parameterVector, std::string parameterName);
void FillNodeFilterBoolVector(std::vector<bool> *boolVector, std::string parameterName);
void FillEdgeFilterBoolVector(std::vector<bool> *boolVector, std::string parameterName);
// Property storing members
std::string m_ChosenRenderingScheme;
std::string m_ChosenEdgeFilter;
std::string m_EdgeThresholdParameter;
double m_EdgeThreshold;
std::string m_ChosenNodeFilter;
std::string m_NodeThresholdParameter;
double m_NodeThreshold;
mitk::Color m_NodeColorStart;
mitk::Color m_NodeColorEnd;
double m_NodeRadiusStart;
double m_NodeRadiusEnd;
std::string m_ChosenNodeLabel;
mitk::Color m_EdgeColorStart;
mitk::Color m_EdgeColorEnd;
double m_EdgeRadiusStart;
double m_EdgeRadiusEnd;
std::string m_NodeRadiusParameter;
std::string m_NodeColorParameter;
std::string m_EdgeRadiusParameter;
std::string m_EdgeColorParameter;
// Balloons
std::string m_BalloonText;
std::string m_BalloonNodeStats;
mitk::FreeSurferParcellationTranslator::Pointer m_Translator;
std::string m_AllNodeLabels;
mitk::TextAnnotation3D::Pointer m_TextOverlay3D;
};
} // namespace mitk
#endif /* ConnectomicsNetworkMapper3D_H_HEADER_INCLUDED */
diff --git a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeColorParameterProperty.cpp b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeColorParameterProperty.cpp
index cb46579..aac70c9 100644
--- a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeColorParameterProperty.cpp
+++ b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeColorParameterProperty.cpp
@@ -1,70 +1,70 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsRenderingEdgeColorParameterProperty.h"
#include "mitkConnectomicsRenderingProperties.h"
#define EDGE_COLOR_CONSTANT 0
#define EDGE_COLOR_WEIGHT 1
#define EDGE_COLOR_CENTRALITY 2
mitk::ConnectomicsRenderingEdgeColorParameterProperty::ConnectomicsRenderingEdgeColorParameterProperty( )
{
AddRenderingEdgeColorParameters();
SetValue( EDGE_COLOR_CONSTANT );
}
mitk::ConnectomicsRenderingEdgeColorParameterProperty::ConnectomicsRenderingEdgeColorParameterProperty( const IdType& value )
{
AddRenderingEdgeColorParameters();
if ( IsValidEnumerationValue( value ) )
{
SetValue( value ) ;
}
else
{
SetValue( EDGE_COLOR_CONSTANT );
}
}
mitk::ConnectomicsRenderingEdgeColorParameterProperty::ConnectomicsRenderingEdgeColorParameterProperty( const std::string& value )
{
AddRenderingEdgeColorParameters();
if ( IsValidEnumerationValue( value ) )
{
SetValue( value );
}
else
{
SetValue( EDGE_COLOR_CONSTANT );
}
}
void mitk::ConnectomicsRenderingEdgeColorParameterProperty::AddRenderingEdgeColorParameters()
{
AddEnum( connectomicsRenderingEdgeParameterConstant , EDGE_COLOR_CONSTANT );
AddEnum( connectomicsRenderingEdgeParameterWeight , EDGE_COLOR_WEIGHT );
AddEnum( connectomicsRenderingEdgeParameterCentrality , EDGE_COLOR_CENTRALITY );
}
bool mitk::ConnectomicsRenderingEdgeColorParameterProperty::AddEnum( const std::string& name, const IdType& id )
{
return Superclass::AddEnum( name, id );
}
diff --git a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeColorParameterProperty.h b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeColorParameterProperty.h
index 68e7c04..524ddf4 100644
--- a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeColorParameterProperty.h
+++ b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeColorParameterProperty.h
@@ -1,95 +1,95 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_CONNECTOMICS_RENDERING_EDGE_COLOR_PARAMETER_PROPERTY__H_
#define _MITK_CONNECTOMICS_RENDERING_EDGE_COLOR_PARAMETER_PROPERTY__H_
#include "mitkEnumerationProperty.h"
#include <MitkConnectomicsExports.h>
namespace mitk
{
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4522)
#endif
/**
* Encapsulates the enumeration of different rendering schemes for connectomics networks
*/
class MITKCONNECTOMICS_EXPORT ConnectomicsRenderingEdgeColorParameterProperty : public EnumerationProperty
{
public:
mitkClassMacro( ConnectomicsRenderingEdgeColorParameterProperty, EnumerationProperty );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitkNewMacro1Param(ConnectomicsRenderingEdgeColorParameterProperty, const IdType&);
mitkNewMacro1Param(ConnectomicsRenderingEdgeColorParameterProperty, const std::string&);
using BaseProperty::operator=;
protected:
/**
* Constructor. Sets the representation to a default value of 0
*/
ConnectomicsRenderingEdgeColorParameterProperty( );
/**
* Constructor. Sets the parameter to the given value. If it is not
* valid, the value is set to 0
* @param value the integer representation of the parameter
*/
ConnectomicsRenderingEdgeColorParameterProperty( const IdType& value );
/**
* Constructor. Sets the parameter to the given value. If it is not
* valid, the value is set to 0
* @param value the string representation of the parameter
*/
ConnectomicsRenderingEdgeColorParameterProperty( const std::string& value );
/**
* this function is overridden as protected, so that the user may not add
* additional enumerations.
*/
bool AddEnum( const std::string& name, const IdType& id ) override;
/**
* Adds the enumeration types as defined by vtk to the list of known
* enumeration values.
*/
virtual void AddRenderingEdgeColorParameters();
private:
// purposely not implemented
ConnectomicsRenderingEdgeColorParameterProperty(const ConnectomicsRenderingEdgeColorParameterProperty&);
ConnectomicsRenderingEdgeColorParameterProperty& operator=(const ConnectomicsRenderingEdgeColorParameterProperty&);
};
#ifdef _MSC_VER
# pragma warning(pop)
#endif
} // end of namespace mitk
#endif
diff --git a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeFilteringProperty.cpp b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeFilteringProperty.cpp
index 518266b..fb20749 100644
--- a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeFilteringProperty.cpp
+++ b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeFilteringProperty.cpp
@@ -1,70 +1,70 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsRenderingEdgeFilteringProperty.h"
#include "mitkConnectomicsRenderingProperties.h"
#define NO_FILTER 0
#define SHORTEST_PATH_FILTER 1
#define THRESHOLDING_FILTER 2
mitk::ConnectomicsRenderingEdgeFilteringProperty::ConnectomicsRenderingEdgeFilteringProperty( )
{
AddRenderingFilter();
SetValue( NO_FILTER );
}
mitk::ConnectomicsRenderingEdgeFilteringProperty::ConnectomicsRenderingEdgeFilteringProperty( const IdType& value )
{
AddRenderingFilter();
if ( IsValidEnumerationValue( value ) )
{
SetValue( value ) ;
}
else
{
SetValue( NO_FILTER );
}
}
mitk::ConnectomicsRenderingEdgeFilteringProperty::ConnectomicsRenderingEdgeFilteringProperty( const std::string& value )
{
AddRenderingFilter();
if ( IsValidEnumerationValue( value ) )
{
SetValue( value );
}
else
{
SetValue( NO_FILTER );
}
}
void mitk::ConnectomicsRenderingEdgeFilteringProperty::AddRenderingFilter()
{
AddEnum( connectomicsRenderingEdgeNoFilter, NO_FILTER );
//AddEnum( connectomicsRenderingEdgeShortestPathFilter, SHORTEST_PATH_FILTER );
AddEnum( connectomicsRenderingEdgeThresholdFilter, THRESHOLDING_FILTER );
}
bool mitk::ConnectomicsRenderingEdgeFilteringProperty::AddEnum( const std::string& name, const IdType& id )
{
return Superclass::AddEnum( name, id );
}
diff --git a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeFilteringProperty.h b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeFilteringProperty.h
index 99289bb..c55c09d 100644
--- a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeFilteringProperty.h
+++ b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeFilteringProperty.h
@@ -1,95 +1,95 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_CONNECTOMICS_RENDERING_EDGE_FILTERING_PROPERTY__H_
#define _MITK_CONNECTOMICS_RENDERING_EDGE_FILTERING_PROPERTY__H_
#include "mitkEnumerationProperty.h"
#include <MitkConnectomicsExports.h>
namespace mitk
{
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4522)
#endif
/**
* Encapsulates the enumeration of different edge filtering options for rendering connectomics networks
*/
class MITKCONNECTOMICS_EXPORT ConnectomicsRenderingEdgeFilteringProperty : public EnumerationProperty
{
public:
mitkClassMacro( ConnectomicsRenderingEdgeFilteringProperty, EnumerationProperty );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitkNewMacro1Param(ConnectomicsRenderingEdgeFilteringProperty, const IdType&);
mitkNewMacro1Param(ConnectomicsRenderingEdgeFilteringProperty, const std::string&);
using BaseProperty::operator=;
protected:
/**
* Constructor. Sets the representation to a default value of 0
*/
ConnectomicsRenderingEdgeFilteringProperty( );
/**
* Constructor. Sets the filter to the given value. If it is not
* valid, the value is set to 0
* @param value the integer representation of the filter
*/
ConnectomicsRenderingEdgeFilteringProperty( const IdType& value );
/**
* Constructor. Sets the filter to the given value. If it is not
* valid, the value is set to 0
* @param value the string representation of the filter
*/
ConnectomicsRenderingEdgeFilteringProperty( const std::string& value );
/**
* this function is overridden as protected, so that the user may not add
* additional enumerations.
*/
bool AddEnum( const std::string& name, const IdType& id ) override;
/**
* Adds the enumeration types as defined by vtk to the list of known
* enumeration values.
*/
virtual void AddRenderingFilter();
private:
// purposely not implemented
ConnectomicsRenderingEdgeFilteringProperty(const ConnectomicsRenderingEdgeFilteringProperty&);
ConnectomicsRenderingEdgeFilteringProperty& operator=(const ConnectomicsRenderingEdgeFilteringProperty&);
};
#ifdef _MSC_VER
# pragma warning(pop)
#endif
} // end of namespace mitk
#endif
diff --git a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeRadiusParameterProperty.cpp b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeRadiusParameterProperty.cpp
index c1a8657..ec402d5 100644
--- a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeRadiusParameterProperty.cpp
+++ b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeRadiusParameterProperty.cpp
@@ -1,70 +1,70 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsRenderingEdgeRadiusParameterProperty.h"
#include "mitkConnectomicsRenderingProperties.h"
#define EDGE_RADIUS_CONSTANT 0
#define EDGE_RADIUS_WEIGHT 1
#define EDGE_RADIUS_CENTRALITY 2
mitk::ConnectomicsRenderingEdgeRadiusParameterProperty::ConnectomicsRenderingEdgeRadiusParameterProperty( )
{
AddRenderingEdgeRadiusParameters();
SetValue( EDGE_RADIUS_CONSTANT );
}
mitk::ConnectomicsRenderingEdgeRadiusParameterProperty::ConnectomicsRenderingEdgeRadiusParameterProperty( const IdType& value )
{
AddRenderingEdgeRadiusParameters();
if ( IsValidEnumerationValue( value ) )
{
SetValue( value ) ;
}
else
{
SetValue( EDGE_RADIUS_CONSTANT );
}
}
mitk::ConnectomicsRenderingEdgeRadiusParameterProperty::ConnectomicsRenderingEdgeRadiusParameterProperty( const std::string& value )
{
AddRenderingEdgeRadiusParameters();
if ( IsValidEnumerationValue( value ) )
{
SetValue( value );
}
else
{
SetValue( EDGE_RADIUS_CONSTANT );
}
}
void mitk::ConnectomicsRenderingEdgeRadiusParameterProperty::AddRenderingEdgeRadiusParameters()
{
AddEnum( connectomicsRenderingEdgeParameterConstant , EDGE_RADIUS_CONSTANT );
AddEnum( connectomicsRenderingEdgeParameterWeight , EDGE_RADIUS_WEIGHT );
AddEnum( connectomicsRenderingEdgeParameterCentrality , EDGE_RADIUS_CENTRALITY );
}
bool mitk::ConnectomicsRenderingEdgeRadiusParameterProperty::AddEnum( const std::string& name, const IdType& id )
{
return Superclass::AddEnum( name, id );
}
diff --git a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeRadiusParameterProperty.h b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeRadiusParameterProperty.h
index 39ea7d4..661cb5f 100644
--- a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeRadiusParameterProperty.h
+++ b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeRadiusParameterProperty.h
@@ -1,95 +1,95 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_CONNECTOMICS_RENDERING_EDGE_RADIUS_PARAMETER_PROPERTY__H_
#define _MITK_CONNECTOMICS_RENDERING_EDGE_RADIUS_PARAMETER_PROPERTY__H_
#include "mitkEnumerationProperty.h"
#include <MitkConnectomicsExports.h>
namespace mitk
{
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4522)
#endif
/**
* Encapsulates the enumeration of different rendering schemes for connectomics networks
*/
class MITKCONNECTOMICS_EXPORT ConnectomicsRenderingEdgeRadiusParameterProperty : public EnumerationProperty
{
public:
mitkClassMacro( ConnectomicsRenderingEdgeRadiusParameterProperty, EnumerationProperty );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitkNewMacro1Param(ConnectomicsRenderingEdgeRadiusParameterProperty, const IdType&);
mitkNewMacro1Param(ConnectomicsRenderingEdgeRadiusParameterProperty, const std::string&);
using BaseProperty::operator=;
protected:
/**
* Constructor. Sets the representation to a default value of 0
*/
ConnectomicsRenderingEdgeRadiusParameterProperty( );
/**
* Constructor. Sets the parameter to the given value. If it is not
* valid, the value is set to 0
* @param value the integer representation of the parameter
*/
ConnectomicsRenderingEdgeRadiusParameterProperty( const IdType& value );
/**
* Constructor. Sets the parameter to the given value. If it is not
* valid, the value is set to 0
* @param value the string representation of the parameter
*/
ConnectomicsRenderingEdgeRadiusParameterProperty( const std::string& value );
/**
* this function is overridden as protected, so that the user may not add
* additional enumerations.
*/
bool AddEnum( const std::string& name, const IdType& id ) override;
/**
* Adds the enumeration types as defined by vtk to the list of known
* enumeration values.
*/
virtual void AddRenderingEdgeRadiusParameters();
private:
// purposely not implemented
ConnectomicsRenderingEdgeRadiusParameterProperty(const ConnectomicsRenderingEdgeRadiusParameterProperty&);
ConnectomicsRenderingEdgeRadiusParameterProperty& operator=(const ConnectomicsRenderingEdgeRadiusParameterProperty&);
};
#ifdef _MSC_VER
# pragma warning(pop)
#endif
} // end of namespace mitk
#endif
diff --git a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeThresholdParameterProperty.cpp b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeThresholdParameterProperty.cpp
index 4cb95fb..6591147 100644
--- a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeThresholdParameterProperty.cpp
+++ b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeThresholdParameterProperty.cpp
@@ -1,68 +1,68 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsRenderingEdgeThresholdParameterProperty.h"
#include "mitkConnectomicsRenderingProperties.h"
#define EDGE_THRESHOLD_WEIGHT 0
#define EDGE_THRESHOLD_CENTRALITY 1
mitk::ConnectomicsRenderingEdgeThresholdParameterProperty::ConnectomicsRenderingEdgeThresholdParameterProperty( )
{
AddRenderingEdgeThresholdParameters();
SetValue( EDGE_THRESHOLD_WEIGHT );
}
mitk::ConnectomicsRenderingEdgeThresholdParameterProperty::ConnectomicsRenderingEdgeThresholdParameterProperty( const IdType& value )
{
AddRenderingEdgeThresholdParameters();
if ( IsValidEnumerationValue( value ) )
{
SetValue( value ) ;
}
else
{
SetValue( EDGE_THRESHOLD_WEIGHT );
}
}
mitk::ConnectomicsRenderingEdgeThresholdParameterProperty::ConnectomicsRenderingEdgeThresholdParameterProperty( const std::string& value )
{
AddRenderingEdgeThresholdParameters();
if ( IsValidEnumerationValue( value ) )
{
SetValue( value );
}
else
{
SetValue( EDGE_THRESHOLD_WEIGHT );
}
}
void mitk::ConnectomicsRenderingEdgeThresholdParameterProperty::AddRenderingEdgeThresholdParameters()
{
AddEnum( connectomicsRenderingEdgeParameterWeight , EDGE_THRESHOLD_WEIGHT );
AddEnum( connectomicsRenderingEdgeParameterCentrality , EDGE_THRESHOLD_CENTRALITY );
}
bool mitk::ConnectomicsRenderingEdgeThresholdParameterProperty::AddEnum( const std::string& name, const IdType& id )
{
return Superclass::AddEnum( name, id );
}
diff --git a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeThresholdParameterProperty.h b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeThresholdParameterProperty.h
index 1803352..60ce4b6 100644
--- a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeThresholdParameterProperty.h
+++ b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingEdgeThresholdParameterProperty.h
@@ -1,95 +1,95 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_CONNECTOMICS_RENDERING_EDGE_THRESHOLD_PARAMETER_PROPERTY__H_
#define _MITK_CONNECTOMICS_RENDERING_EDGE_THRESHOLD_PARAMETER_PROPERTY__H_
#include "mitkEnumerationProperty.h"
#include <MitkConnectomicsExports.h>
namespace mitk
{
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4522)
#endif
/**
* Encapsulates the enumeration of different rendering schemes for connectomics networks
*/
class MITKCONNECTOMICS_EXPORT ConnectomicsRenderingEdgeThresholdParameterProperty : public EnumerationProperty
{
public:
mitkClassMacro( ConnectomicsRenderingEdgeThresholdParameterProperty, EnumerationProperty );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitkNewMacro1Param(ConnectomicsRenderingEdgeThresholdParameterProperty, const IdType&);
mitkNewMacro1Param(ConnectomicsRenderingEdgeThresholdParameterProperty, const std::string&);
using BaseProperty::operator=;
protected:
/**
* Constructor. Sets the representation to a default value of 0
*/
ConnectomicsRenderingEdgeThresholdParameterProperty( );
/**
* Constructor. Sets the parameter to the given value. If it is not
* valid, the value is set to 0
* @param value the integer representation of the parameter
*/
ConnectomicsRenderingEdgeThresholdParameterProperty( const IdType& value );
/**
* Constructor. Sets the parameter to the given value. If it is not
* valid, the value is set to 0
* @param value the string representation of the parameter
*/
ConnectomicsRenderingEdgeThresholdParameterProperty( const std::string& value );
/**
* this function is overridden as protected, so that the user may not add
* additional enumerations.
*/
bool AddEnum( const std::string& name, const IdType& id ) override;
/**
* Adds the enumeration types as defined by vtk to the list of known
* enumeration values.
*/
virtual void AddRenderingEdgeThresholdParameters();
private:
// purposely not implemented
ConnectomicsRenderingEdgeThresholdParameterProperty(const ConnectomicsRenderingEdgeThresholdParameterProperty&);
ConnectomicsRenderingEdgeThresholdParameterProperty& operator=(const ConnectomicsRenderingEdgeThresholdParameterProperty&);
};
#ifdef _MSC_VER
# pragma warning(pop)
#endif
} // end of namespace mitk
#endif
diff --git a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeColorParameterProperty.cpp b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeColorParameterProperty.cpp
index 3f22ed8..caff1c2 100644
--- a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeColorParameterProperty.cpp
+++ b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeColorParameterProperty.cpp
@@ -1,71 +1,71 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsRenderingNodeColorParameterProperty.h"
#include "mitkConnectomicsRenderingProperties.h"
#define NODE_COLOR_CONSTANT 0
#define NODE_COLOR_DEGREE 1
#define NODE_COLOR_BETWEENNESS 2
#define NODE_COLOR_CLUSTERING 3
#define NODE_COLOR_SHORTEST_PATH 4
mitk::ConnectomicsRenderingNodeColorParameterProperty::ConnectomicsRenderingNodeColorParameterProperty( )
{
AddRenderingNodeColorParameters();
SetValue( NODE_COLOR_CONSTANT );
}
mitk::ConnectomicsRenderingNodeColorParameterProperty::ConnectomicsRenderingNodeColorParameterProperty( const IdType& value )
{
AddRenderingNodeColorParameters();
if ( IsValidEnumerationValue( value ) )
{
SetValue( value ) ;
}
else
{
SetValue( NODE_COLOR_CONSTANT );
}
}
mitk::ConnectomicsRenderingNodeColorParameterProperty::ConnectomicsRenderingNodeColorParameterProperty( const std::string& value )
{
AddRenderingNodeColorParameters();
if ( IsValidEnumerationValue( value ) )
{
SetValue( value );
}
else
{
SetValue( NODE_COLOR_CONSTANT );
}
}
void mitk::ConnectomicsRenderingNodeColorParameterProperty::AddRenderingNodeColorParameters()
{
AddEnum( connectomicsRenderingNodeParameterConstant , NODE_COLOR_CONSTANT );
AddEnum( connectomicsRenderingNodeParameterDegree , NODE_COLOR_DEGREE );
AddEnum( connectomicsRenderingNodeParameterBetweenness , NODE_COLOR_BETWEENNESS );
AddEnum( connectomicsRenderingNodeParameterClustering , NODE_COLOR_CLUSTERING );
AddEnum( connectomicsRenderingNodeParameterColoringShortestPath , NODE_COLOR_SHORTEST_PATH );
}
bool mitk::ConnectomicsRenderingNodeColorParameterProperty::AddEnum( const std::string& name, const IdType& id )
{
return Superclass::AddEnum( name, id );
}
diff --git a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeColorParameterProperty.h b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeColorParameterProperty.h
index bf1f191..4d6f893 100644
--- a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeColorParameterProperty.h
+++ b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeColorParameterProperty.h
@@ -1,95 +1,95 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_CONNECTOMICS_RENDERING_NODE_COLOR_PARAMETER_PROPERTY__H_
#define _MITK_CONNECTOMICS_RENDERING_NODE_COLOR_PARAMETER_PROPERTY__H_
#include "mitkEnumerationProperty.h"
#include <MitkConnectomicsExports.h>
namespace mitk
{
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4522)
#endif
/**
* Encapsulates the enumeration of different rendering schemes for connectomics networks
*/
class MITKCONNECTOMICS_EXPORT ConnectomicsRenderingNodeColorParameterProperty : public EnumerationProperty
{
public:
mitkClassMacro( ConnectomicsRenderingNodeColorParameterProperty, EnumerationProperty );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitkNewMacro1Param(ConnectomicsRenderingNodeColorParameterProperty, const IdType&);
mitkNewMacro1Param(ConnectomicsRenderingNodeColorParameterProperty, const std::string&);
using BaseProperty::operator=;
protected:
/**
* Constructor. Sets the representation to a default value of 0
*/
ConnectomicsRenderingNodeColorParameterProperty( );
/**
* Constructor. Sets the parameter to the given value. If it is not
* valid, the value is set to 0
* @param value the integer representation of the parameter
*/
ConnectomicsRenderingNodeColorParameterProperty( const IdType& value );
/**
* Constructor. Sets the parameter to the given value. If it is not
* valid, the value is set to 0
* @param value the string representation of the parameter
*/
ConnectomicsRenderingNodeColorParameterProperty( const std::string& value );
/**
* this function is overridden as protected, so that the user may not add
* additional enumerations.
*/
bool AddEnum( const std::string& name, const IdType& id ) override;
/**
* Adds the enumeration types as defined by vtk to the list of known
* enumeration values.
*/
virtual void AddRenderingNodeColorParameters();
private:
// purposely not implemented
ConnectomicsRenderingNodeColorParameterProperty(const ConnectomicsRenderingNodeColorParameterProperty&);
ConnectomicsRenderingNodeColorParameterProperty& operator=(const ConnectomicsRenderingNodeColorParameterProperty&);
};
#ifdef _MSC_VER
# pragma warning(pop)
#endif
} // end of namespace mitk
#endif
diff --git a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeFilteringProperty.cpp b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeFilteringProperty.cpp
index 4af21d6..632ca8d 100644
--- a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeFilteringProperty.cpp
+++ b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeFilteringProperty.cpp
@@ -1,68 +1,68 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsRenderingNodeFilteringProperty.h"
#include "mitkConnectomicsRenderingProperties.h"
#define NO_FILTER 0
#define THRESHOLDING_FILTER 1
mitk::ConnectomicsRenderingNodeFilteringProperty::ConnectomicsRenderingNodeFilteringProperty( )
{
AddRenderingFilter();
SetValue( NO_FILTER );
}
mitk::ConnectomicsRenderingNodeFilteringProperty::ConnectomicsRenderingNodeFilteringProperty( const IdType& value )
{
AddRenderingFilter();
if ( IsValidEnumerationValue( value ) )
{
SetValue( value ) ;
}
else
{
SetValue( NO_FILTER );
}
}
mitk::ConnectomicsRenderingNodeFilteringProperty::ConnectomicsRenderingNodeFilteringProperty( const std::string& value )
{
AddRenderingFilter();
if ( IsValidEnumerationValue( value ) )
{
SetValue( value );
}
else
{
SetValue( NO_FILTER );
}
}
void mitk::ConnectomicsRenderingNodeFilteringProperty::AddRenderingFilter()
{
AddEnum( connectomicsRenderingNodeNoFilter, NO_FILTER );
AddEnum( connectomicsRenderingNodeThresholdingFilter, THRESHOLDING_FILTER );
}
bool mitk::ConnectomicsRenderingNodeFilteringProperty::AddEnum( const std::string& name, const IdType& id )
{
return Superclass::AddEnum( name, id );
}
diff --git a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeFilteringProperty.h b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeFilteringProperty.h
index 087cd06..36034a8 100644
--- a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeFilteringProperty.h
+++ b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeFilteringProperty.h
@@ -1,95 +1,95 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_CONNECTOMICS_RENDERING_NODE_FILTERING_PROPERTY__H_
#define _MITK_CONNECTOMICS_RENDERING_NODE_FILTERING_PROPERTY__H_
#include "mitkEnumerationProperty.h"
#include <MitkConnectomicsExports.h>
namespace mitk
{
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4522)
#endif
/**
* Encapsulates the enumeration of different node filtering options for rendering connectomics networks
*/
class MITKCONNECTOMICS_EXPORT ConnectomicsRenderingNodeFilteringProperty : public EnumerationProperty
{
public:
mitkClassMacro( ConnectomicsRenderingNodeFilteringProperty, EnumerationProperty );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitkNewMacro1Param(ConnectomicsRenderingNodeFilteringProperty, const IdType&);
mitkNewMacro1Param(ConnectomicsRenderingNodeFilteringProperty, const std::string&);
using BaseProperty::operator=;
protected:
/**
* Constructor. Sets the representation to a default value of 0
*/
ConnectomicsRenderingNodeFilteringProperty( );
/**
* Constructor. Sets the filter to the given value. If it is not
* valid, the value is set to 0
* @param value the integer representation of the filter
*/
ConnectomicsRenderingNodeFilteringProperty( const IdType& value );
/**
* Constructor. Sets the filter to the given value. If it is not
* valid, the value is set to 0
* @param value the string representation of the filter
*/
ConnectomicsRenderingNodeFilteringProperty( const std::string& value );
/**
* this function is overridden as protected, so that the user may not add
* additional enumerations.
*/
bool AddEnum( const std::string& name, const IdType& id ) override;
/**
* Adds the enumeration types as defined by vtk to the list of known
* enumeration values.
*/
virtual void AddRenderingFilter();
private:
// purposely not implemented
ConnectomicsRenderingNodeFilteringProperty(const ConnectomicsRenderingNodeFilteringProperty&);
ConnectomicsRenderingNodeFilteringProperty& operator=(const ConnectomicsRenderingNodeFilteringProperty&);
};
#ifdef _MSC_VER
# pragma warning(pop)
#endif
} // end of namespace mitk
#endif
diff --git a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeRadiusParameterProperty.cpp b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeRadiusParameterProperty.cpp
index 7ebb339..b1cb70b 100644
--- a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeRadiusParameterProperty.cpp
+++ b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeRadiusParameterProperty.cpp
@@ -1,72 +1,72 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsRenderingNodeRadiusParameterProperty.h"
#include "mitkConnectomicsRenderingProperties.h"
#define NODE_RADIUS_CONSTANT 0
#define NODE_RADIUS_DEGREE 1
#define NODE_RADIUS_BETWEENNESS 2
#define NODE_RADIUS_CLUSTERING 3
mitk::ConnectomicsRenderingNodeRadiusParameterProperty::ConnectomicsRenderingNodeRadiusParameterProperty( )
{
AddRenderingNodeRadiusParameters();
SetValue( NODE_RADIUS_CONSTANT );
}
mitk::ConnectomicsRenderingNodeRadiusParameterProperty::ConnectomicsRenderingNodeRadiusParameterProperty( const IdType& value )
{
AddRenderingNodeRadiusParameters();
if ( IsValidEnumerationValue( value ) )
{
SetValue( value ) ;
}
else
{
SetValue( NODE_RADIUS_CONSTANT );
}
}
mitk::ConnectomicsRenderingNodeRadiusParameterProperty::ConnectomicsRenderingNodeRadiusParameterProperty( const std::string& value )
{
AddRenderingNodeRadiusParameters();
if ( IsValidEnumerationValue( value ) )
{
SetValue( value );
}
else
{
SetValue( NODE_RADIUS_CONSTANT );
}
}
void mitk::ConnectomicsRenderingNodeRadiusParameterProperty::AddRenderingNodeRadiusParameters()
{
AddEnum( connectomicsRenderingNodeParameterConstant, NODE_RADIUS_CONSTANT );
AddEnum( connectomicsRenderingNodeParameterDegree , NODE_RADIUS_DEGREE );
AddEnum( connectomicsRenderingNodeParameterBetweenness , NODE_RADIUS_BETWEENNESS );
AddEnum( connectomicsRenderingNodeParameterClustering , NODE_RADIUS_CLUSTERING );
}
bool mitk::ConnectomicsRenderingNodeRadiusParameterProperty::AddEnum( const std::string& name, const IdType& id )
{
return Superclass::AddEnum( name, id );
}
diff --git a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeRadiusParameterProperty.h b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeRadiusParameterProperty.h
index bcd75c3..b0293b5 100644
--- a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeRadiusParameterProperty.h
+++ b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeRadiusParameterProperty.h
@@ -1,95 +1,95 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_CONNECTOMICS_RENDERING_NODE_RADIUS_PARAMETER_PROPERTY__H_
#define _MITK_CONNECTOMICS_RENDERING_NODE_RADIUS_PARAMETER_PROPERTY__H_
#include "mitkEnumerationProperty.h"
#include <MitkConnectomicsExports.h>
namespace mitk
{
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4522)
#endif
/**
* Encapsulates the enumeration of different rendering schemes for connectomics networks
*/
class MITKCONNECTOMICS_EXPORT ConnectomicsRenderingNodeRadiusParameterProperty : public EnumerationProperty
{
public:
mitkClassMacro( ConnectomicsRenderingNodeRadiusParameterProperty, EnumerationProperty );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitkNewMacro1Param(ConnectomicsRenderingNodeRadiusParameterProperty, const IdType&);
mitkNewMacro1Param(ConnectomicsRenderingNodeRadiusParameterProperty, const std::string&);
using BaseProperty::operator=;
protected:
/**
* Constructor. Sets the representation to a default value of 0
*/
ConnectomicsRenderingNodeRadiusParameterProperty( );
/**
* Constructor. Sets the parameter to the given value. If it is not
* valid, the value is set to 0
* @param value the integer representation of the parameter
*/
ConnectomicsRenderingNodeRadiusParameterProperty( const IdType& value );
/**
* Constructor. Sets the parameter to the given value. If it is not
* valid, the value is set to 0
* @param value the string representation of the parameter
*/
ConnectomicsRenderingNodeRadiusParameterProperty( const std::string& value );
/**
* this function is overridden as protected, so that the user may not add
* additional enumerations.
*/
bool AddEnum( const std::string& name, const IdType& id ) override;
/**
* Adds the enumeration types as defined by vtk to the list of known
* enumeration values.
*/
virtual void AddRenderingNodeRadiusParameters();
private:
// purposely not implemented
ConnectomicsRenderingNodeRadiusParameterProperty(const ConnectomicsRenderingNodeRadiusParameterProperty&);
ConnectomicsRenderingNodeRadiusParameterProperty& operator=(const ConnectomicsRenderingNodeRadiusParameterProperty&);
};
#ifdef _MSC_VER
# pragma warning(pop)
#endif
} // end of namespace mitk
#endif
diff --git a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeThresholdParameterProperty.cpp b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeThresholdParameterProperty.cpp
index abf9226..b46ca71 100644
--- a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeThresholdParameterProperty.cpp
+++ b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeThresholdParameterProperty.cpp
@@ -1,70 +1,70 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsRenderingNodeThresholdParameterProperty.h"
#include "mitkConnectomicsRenderingProperties.h"
#define NODE_THRESHOLD_DEGREE 0
#define NODE_THRESHOLD_BETWEENNESS 1
#define NODE_THRESHOLD_CLUSTERING 2
mitk::ConnectomicsRenderingNodeThresholdParameterProperty::ConnectomicsRenderingNodeThresholdParameterProperty( )
{
AddRenderingNodeThresholdParameters();
SetValue( NODE_THRESHOLD_DEGREE );
}
mitk::ConnectomicsRenderingNodeThresholdParameterProperty::ConnectomicsRenderingNodeThresholdParameterProperty( const IdType& value )
{
AddRenderingNodeThresholdParameters();
if ( IsValidEnumerationValue( value ) )
{
SetValue( value ) ;
}
else
{
SetValue( NODE_THRESHOLD_DEGREE );
}
}
mitk::ConnectomicsRenderingNodeThresholdParameterProperty::ConnectomicsRenderingNodeThresholdParameterProperty( const std::string& value )
{
AddRenderingNodeThresholdParameters();
if ( IsValidEnumerationValue( value ) )
{
SetValue( value );
}
else
{
SetValue( NODE_THRESHOLD_DEGREE );
}
}
void mitk::ConnectomicsRenderingNodeThresholdParameterProperty::AddRenderingNodeThresholdParameters()
{
AddEnum( connectomicsRenderingNodeParameterDegree , NODE_THRESHOLD_DEGREE );
AddEnum( connectomicsRenderingNodeParameterBetweenness , NODE_THRESHOLD_BETWEENNESS );
AddEnum( connectomicsRenderingNodeParameterClustering , NODE_THRESHOLD_CLUSTERING );
}
bool mitk::ConnectomicsRenderingNodeThresholdParameterProperty::AddEnum( const std::string& name, const IdType& id )
{
return Superclass::AddEnum( name, id );
}
diff --git a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeThresholdParameterProperty.h b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeThresholdParameterProperty.h
index 84f3dab..0ef2144 100644
--- a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeThresholdParameterProperty.h
+++ b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingNodeThresholdParameterProperty.h
@@ -1,95 +1,95 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_CONNECTOMICS_RENDERING_NODE_THRESHOLD_PARAMETER_PROPERTY__H_
#define _MITK_CONNECTOMICS_RENDERING_NODE_THRESHOLD_PARAMETER_PROPERTY__H_
#include "mitkEnumerationProperty.h"
#include <MitkConnectomicsExports.h>
namespace mitk
{
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4522)
#endif
/**
* Encapsulates the enumeration of different rendering schemes for connectomics networks
*/
class MITKCONNECTOMICS_EXPORT ConnectomicsRenderingNodeThresholdParameterProperty : public EnumerationProperty
{
public:
mitkClassMacro( ConnectomicsRenderingNodeThresholdParameterProperty, EnumerationProperty );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitkNewMacro1Param(ConnectomicsRenderingNodeThresholdParameterProperty, const IdType&);
mitkNewMacro1Param(ConnectomicsRenderingNodeThresholdParameterProperty, const std::string&);
using BaseProperty::operator=;
protected:
/**
* Constructor. Sets the representation to a default value of 0
*/
ConnectomicsRenderingNodeThresholdParameterProperty( );
/**
* Constructor. Sets the parameter to the given value. If it is not
* valid, the value is set to 0
* @param value the integer representation of the parameter
*/
ConnectomicsRenderingNodeThresholdParameterProperty( const IdType& value );
/**
* Constructor. Sets the parameter to the given value. If it is not
* valid, the value is set to 0
* @param value the string representation of the parameter
*/
ConnectomicsRenderingNodeThresholdParameterProperty( const std::string& value );
/**
* this function is overridden as protected, so that the user may not add
* additional enumerations.
*/
bool AddEnum( const std::string& name, const IdType& id ) override;
/**
* Adds the enumeration types as defined by vtk to the list of known
* enumeration values.
*/
virtual void AddRenderingNodeThresholdParameters();
private:
// purposely not implemented
ConnectomicsRenderingNodeThresholdParameterProperty(const ConnectomicsRenderingNodeThresholdParameterProperty&);
ConnectomicsRenderingNodeThresholdParameterProperty& operator=(const ConnectomicsRenderingNodeThresholdParameterProperty&);
};
#ifdef _MSC_VER
# pragma warning(pop)
#endif
} // end of namespace mitk
#endif
diff --git a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingProperties.h b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingProperties.h
index b8f499d..074ab31 100644
--- a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingProperties.h
+++ b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingProperties.h
@@ -1,338 +1,338 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 ConnectomicsRenderingProperties_H_HEADER_INCLUDED
#define ConnectomicsRenderingProperties_H_HEADER_INCLUDED
#include <cstring>
#include "mitkProperties.h"
#include "mitkStringProperty.h"
#include "mitkEnumerationProperty.h"
#include "mitkColorProperty.h"
namespace mitk {
/** \file mitkConnectomicsRenderingProperties.h
* \brief This file defines the rendering properties available for connectomics networks in MITK.
*
* This file collects and explains the properties which can be used to modify the visualisation
* of connectomics networks.
*/
// Switching between rendering modes
/**
* \brief Define the rendering scheme to be used.
*
* Currently there are two possible rendering schemes in MITK.
* <ol>
* <li> The VTK Graph Layout
* <li> The MITK Connectomics Visualisation - Default
* </ol>
*
* The VTK Graph Layout is faster than the MITK Connectomics Visualisation, but provides less features
* and settings.
*/
const std::string connectomicsRenderingSchemePropertyName = "Connectomics.Rendering.Scheme";
/**
* \brief Much faster but less features.
*/
const std::string connectomicsRenderingVTKScheme = "VTK Graph Layout";
/**
* \brief Slower but with several visualisation options.
*/
const std::string connectomicsRenderingMITKScheme = "MITK Connectomics Visualisation";
// All options below are only for the MITK Connectomics Visualisation scheme
////////////////////////////////////////
// Filtering Options
////////////////////////////////////////
/** \brief Edge filter option
*
* This option controls the filtering of edges for visualization purposes. Edges filtered out will not be shown, but still included in calculations.
*
* Currently there these options:
* <ol>
* <li> No Edge Filtering - Default
* <li> Shortest Path to Node
* <li> Thresholding
* </ol>
*
*/
const std::string connectomicsRenderingEdgeFilteringPropertyName = "Connectomics.Rendering.Edges.Filtering";
/**
* \brief Do not filter edges
*/
const std::string connectomicsRenderingEdgeNoFilter = "No Edge Filtering";
/**
* \brief Only show edges which are part of a shortest path to the selected node from any other node
*/
const std::string connectomicsRenderingEdgeShortestPathFilter = "Shortest Path to Node";
/**
* \brief Show only edges above a certain parameter threshold
*/
const std::string connectomicsRenderingEdgeThresholdFilter = "Thresholding";
/**
* \brief Parameter to be thresholded
*/
const std::string connectomicsRenderingEdgeThresholdFilterParameterName = "Connectomics.Rendering.Edges.Filtering.ThresholdParameter";
/**
* \brief Threshold
*/
const std::string connectomicsRenderingEdgeThresholdFilterThresholdName = "Connectomics.Rendering.Edges.Filtering.Threshold";
/** \brief Node filter option
*
* This option controls the filtering of nodes for visualization purposes. Nodes filtered out will not be shown, but still included in calculations.
*
* Currently there these options:
* <ol>
* <li> No Node Filtering - Default
* <li> Thresholding
* </ol>
*
*/
const std::string connectomicsRenderingNodeFilteringPropertyName = "Connectomics.Rendering.Nodes.Filtering";
/**
* \brief Do not filter nodes
*/
const std::string connectomicsRenderingNodeNoFilter = "No Node Filtering";
/**
* \brief Only show nodes above a certain parameter threshold
*/
const std::string connectomicsRenderingNodeThresholdingFilter = "Thresholding";
/**
* \brief Parameter to be thresholded
*/
const std::string connectomicsRenderingNodeThresholdFilterParameterName = "Connectomics.Rendering.Nodes.Filtering.ThresholdParameter";
/**
* \brief Threshold
*/
const std::string connectomicsRenderingNodeThresholdFilterThresholdName = "Connectomics.Rendering.Nodes.Filtering.Threshold";
// Default values
const mitk::StringProperty::Pointer connectomicsRenderingEdgeThresholdFilterParameterDefault =
mitk::StringProperty::New( "" );
const mitk::FloatProperty::Pointer connectomicsRenderingEdgeThresholdFilterThresholdDefault =
mitk::FloatProperty::New( 1.0 );
const mitk::StringProperty::Pointer connectomicsRenderingNodeThresholdFilterParameterDefault =
mitk::StringProperty::New( "" );
const mitk::FloatProperty::Pointer connectomicsRenderingNodeThresholdFilterThresholdDefault =
mitk::FloatProperty::New( 1.0 );
////////////////////////////////////////
// Node Options
////////////////////////////////////////
// Color gradient
/**
* \brief Start Color
*
* The start color that will be used for gradient creation
*/
const std::string connectomicsRenderingNodeGradientStartColorName = "Connectomics.Rendering.Nodes.Gradient.StartColor";
/**
* \brief End Color
*
* The end color that will be used for gradient creation
*/
const std::string connectomicsRenderingNodeGradientEndColorName = "Connectomics.Rendering.Nodes.Gradient.EndColor";
/**
* \brief Color parameter
*
* This parameter will be used to select the color of the node.
*/
const std::string connectomicsRenderingNodeGradientColorParameterName = "Connectomics.Rendering.Nodes.Gradient.Parameter";
/**
* \brief The chosen node label
*
* This node will be used for any visualisation requiring a specific node
*/
const std::string connectomicsRenderingNodeChosenNodeName = "Connectomics.Rendering.Nodes.ChosenNode";
// Radius
/**
* \brief Start Radius
*
* The start radius that will be used
*/
const std::string connectomicsRenderingNodeRadiusStartName = "Connectomics.Rendering.Nodes.Radius.Start";
/**
* \brief End Radius
*
* The end radius that will be used
*/
const std::string connectomicsRenderingNodeRadiusEndName = "Connectomics.Rendering.Nodes.Radius.End";
/**
* \brief Radius parameter
*
* This parameter will be used to select the radius of the node.
*/
const std::string connectomicsRenderingNodeRadiusParameterName = "Connectomics.Rendering.Nodes.Radius.Parameter";
// Possible parameters
/**
* \brief Using the node degree as parameter
*/
const std::string connectomicsRenderingNodeParameterDegree = "Degree";
/**
* \brief Using the node betweenness as parameter
*/
const std::string connectomicsRenderingNodeParameterBetweenness = "Betweenness centrality";
/**
* \brief Using the node clustering coefficient as parameter
*/
const std::string connectomicsRenderingNodeParameterClustering = "Clustering coefficient";
/**
* \brief Color nodes by shortest path length to a chosen node
*/
const std::string connectomicsRenderingNodeParameterColoringShortestPath = "Shortest Path Steps";
/**
* \brief Constant
*
* The node property will be constant.
*/
const std::string connectomicsRenderingNodeParameterConstant = "Constant";
// Default values
const mitk::StringProperty::Pointer connectomicsRenderingNodeChosenNodeDefault =
mitk::StringProperty::New("");
const mitk::ColorProperty::Pointer connectomicsRenderingNodeGradientStartColorDefault =
mitk::ColorProperty::New(0.0f, 0.0f, 1.0f);
const mitk::ColorProperty::Pointer connectomicsRenderingNodeGradientEndColorDefault =
mitk::ColorProperty::New(0.0f, 1.0f, 0.0f);
const mitk::FloatProperty::Pointer connectomicsRenderingNodeRadiusStartDefault =
mitk::FloatProperty::New( 1.0 );
const mitk::FloatProperty::Pointer connectomicsRenderingNodeRadiusEndDefault =
mitk::FloatProperty::New( 1.0 );
////////////////////////////////////////
// Edge Options
////////////////////////////////////////
// Color gradient
/**
* \brief Start Color
*
* The start color that will be used for gradient creation
*/
const std::string connectomicsRenderingEdgeGradientStartColorName = "Connectomics.Rendering.Edges.Gradient.StartColor";
/**
* \brief End Color
*
* The end color that will be used for gradient creation
*/
const std::string connectomicsRenderingEdgeGradientEndColorName = "Connectomics.Rendering.Edges.Gradient.EndColor";
/**
* \brief Color parameter
*
* This parameter will be used to select the color of the edge.
*/
const std::string connectomicsRenderingEdgeGradientColorParameterName = "Connectomics.Rendering.Edges.Gradient.Parameter";
// Radius
/**
* \brief Start Radius
*
* The start radius that will be used
*/
const std::string connectomicsRenderingEdgeRadiusStartName = "Connectomics.Rendering.Edges.Radius.Start";
/**
* \brief End Radius
*
* The end radius that will be used
*/
const std::string connectomicsRenderingEdgeRadiusEndName = "Connectomics.Rendering.Edges.Radius.End";
/**
* \brief Radius parameter
*
* This parameter will be used to select the radius of the edge.
*/
const std::string connectomicsRenderingEdgeRadiusParameterName = "Connectomics.Rendering.Edges.Radius.Parameter";
// Possible parameters
/**
* \brief Using the weight as parameter
*/
const std::string connectomicsRenderingEdgeParameterWeight = "Weight";
/**
* \brief Using the edge centrality as parameter
*/
const std::string connectomicsRenderingEdgeParameterCentrality = "Edge betweenness centrality";
/**
* \brief Constant
*
* The edge property will be constant.
*/
const std::string connectomicsRenderingEdgeParameterConstant = "Constant";
// Default values
const mitk::ColorProperty::Pointer connectomicsRenderingEdgeGradientStartColorDefault =
mitk::ColorProperty::New(0.8f, 0.0f, 0.6f);
const mitk::ColorProperty::Pointer connectomicsRenderingEdgeGradientEndColorDefault =
mitk::ColorProperty::New(0.0f, 0.8f, 0.2f);
const mitk::FloatProperty::Pointer connectomicsRenderingEdgeRadiusStartDefault =
mitk::FloatProperty::New( 0.1 );
const mitk::FloatProperty::Pointer connectomicsRenderingEdgeRadiusEndDefault =
mitk::FloatProperty::New( 0.4 );
/**
* \brief Balloon controls and content
*/
const std::string connectomicsRenderingBalloonTextName =
"Connectomics.Rendering.Balloon.Text";
const std::string connectomicsRenderingBalloonAllNodeLabelsName =
"Connectomics.Rendering.Balloon.AllNodeLabels";
const std::string connectomicsRenderingBalloonNodeStatsName =
"Connectomics.Rendering.Balloon.NodeStats";
} // namespace mitk
#endif /* ConnectomicsRenderingProperties_H_HEADER_INCLUDED */
diff --git a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingSchemeProperty.cpp b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingSchemeProperty.cpp
index c3e9378..21237ee 100644
--- a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingSchemeProperty.cpp
+++ b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingSchemeProperty.cpp
@@ -1,68 +1,68 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsRenderingSchemeProperty.h"
#include "mitkConnectomicsRenderingProperties.h"
#define MITK_SCHEME 0
#define VTK_SCHEME 1
mitk::ConnectomicsRenderingSchemeProperty::ConnectomicsRenderingSchemeProperty( )
{
AddRenderingSchemes();
SetValue( MITK_SCHEME );
}
mitk::ConnectomicsRenderingSchemeProperty::ConnectomicsRenderingSchemeProperty( const IdType& value )
{
AddRenderingSchemes();
if ( IsValidEnumerationValue( value ) )
{
SetValue( value ) ;
}
else
{
SetValue( MITK_SCHEME );
}
}
mitk::ConnectomicsRenderingSchemeProperty::ConnectomicsRenderingSchemeProperty( const std::string& value )
{
AddRenderingSchemes();
if ( IsValidEnumerationValue( value ) )
{
SetValue( value );
}
else
{
SetValue( MITK_SCHEME );
}
}
void mitk::ConnectomicsRenderingSchemeProperty::AddRenderingSchemes()
{
AddEnum( connectomicsRenderingMITKScheme, MITK_SCHEME );
AddEnum( connectomicsRenderingVTKScheme, VTK_SCHEME );
}
bool mitk::ConnectomicsRenderingSchemeProperty::AddEnum( const std::string& name, const IdType& id )
{
return Superclass::AddEnum( name, id );
}
diff --git a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingSchemeProperty.h b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingSchemeProperty.h
index 2f73ddc..41a0721 100644
--- a/Modules/Connectomics/Rendering/mitkConnectomicsRenderingSchemeProperty.h
+++ b/Modules/Connectomics/Rendering/mitkConnectomicsRenderingSchemeProperty.h
@@ -1,95 +1,95 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_CONNECTOMICS_RENDERING_SCHEME_PROPERTY__H_
#define _MITK_CONNECTOMICS_RENDERING_SCHEME_PROPERTY__H_
#include "mitkEnumerationProperty.h"
#include <MitkConnectomicsExports.h>
namespace mitk
{
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable: 4522)
#endif
/**
* Encapsulates the enumeration of different rendering schemes for connectomics networks
*/
class MITKCONNECTOMICS_EXPORT ConnectomicsRenderingSchemeProperty : public EnumerationProperty
{
public:
mitkClassMacro( ConnectomicsRenderingSchemeProperty, EnumerationProperty );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitkNewMacro1Param(ConnectomicsRenderingSchemeProperty, const IdType&);
mitkNewMacro1Param(ConnectomicsRenderingSchemeProperty, const std::string&);
using BaseProperty::operator=;
protected:
/**
* Constructor. Sets the representation to a default value of 0
*/
ConnectomicsRenderingSchemeProperty( );
/**
* Constructor. Sets the scheme to the given value. If it is not
* valid, the value is set to 0
* @param value the integer representation of the scheme
*/
ConnectomicsRenderingSchemeProperty( const IdType& value );
/**
* Constructor. Sets the scheme to the given value. If it is not
* valid, the value is set to 0
* @param value the string representation of the scheme
*/
ConnectomicsRenderingSchemeProperty( const std::string& value );
/**
* this function is overridden as protected, so that the user may not add
* additional enumerations.
*/
bool AddEnum( const std::string& name, const IdType& id ) override;
/**
* Adds the enumeration types as defined by vtk to the list of known
* enumeration values.
*/
virtual void AddRenderingSchemes();
private:
// purposely not implemented
ConnectomicsRenderingSchemeProperty(const ConnectomicsRenderingSchemeProperty&);
ConnectomicsRenderingSchemeProperty& operator=(const ConnectomicsRenderingSchemeProperty&);
};
#ifdef _MSC_VER
# pragma warning(pop)
#endif
} // end of namespace mitk
#endif
diff --git a/Modules/Connectomics/Testing/mitkConnectomicsNetworkCreationTest.cpp b/Modules/Connectomics/Testing/mitkConnectomicsNetworkCreationTest.cpp
index fcd4f36..7f99c91 100644
--- a/Modules/Connectomics/Testing/mitkConnectomicsNetworkCreationTest.cpp
+++ b/Modules/Connectomics/Testing/mitkConnectomicsNetworkCreationTest.cpp
@@ -1,113 +1,113 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// Testing
#include "mitkTestingMacros.h"
#include "mitkTestFixture.h"
// std includes
#include <string>
// MITK includes
#include "mitkConnectomicsNetworkCreator.h"
#include "mitkIOUtil.h"
// VTK includes
#include <vtkDebugLeaks.h>
class mitkConnectomicsNetworkCreationTestSuite : public mitk::TestFixture
{
CPPUNIT_TEST_SUITE(mitkConnectomicsNetworkCreationTestSuite);
/// \todo Fix VTK memory leaks. Bug 18097.
vtkDebugLeaks::SetExitError(0);
MITK_TEST(CreateNetworkFromFibersAndParcellation);
CPPUNIT_TEST_SUITE_END();
private:
std::string m_ParcellationPath;
std::string m_FiberPath;
std::string m_ReferenceNetworkPath;
public:
/**
* @brief Setup Always call this method before each Test-case to ensure correct and new intialization of the used members for a new test case. (If the members are not used in a test, the method does not need to be called).
*/
void setUp() override
{
m_ReferenceNetworkPath = GetTestDataFilePath("DiffusionImaging/Connectomics/reference.cnf");
m_ParcellationPath = GetTestDataFilePath("DiffusionImaging/Connectomics/parcellation.nrrd");
m_FiberPath = GetTestDataFilePath("DiffusionImaging/Connectomics/fiberBundle.fib");
}
void tearDown() override
{
m_ReferenceNetworkPath = "";
m_ParcellationPath = "";
m_FiberPath = "";
}
void CreateNetworkFromFibersAndParcellation()
{
// load fiber image
std::vector<mitk::BaseData::Pointer> fiberInfile = mitk::IOUtil::Load( m_FiberPath );
if( fiberInfile.empty() )
{
std::string errorMessage = "Fiber Image at " + m_FiberPath + " could not be read. Aborting.";
CPPUNIT_ASSERT_MESSAGE( errorMessage, false );
}
mitk::BaseData* fiberBaseData = fiberInfile.at(0);
mitk::FiberBundle* fiberBundle = dynamic_cast<mitk::FiberBundle*>( fiberBaseData );
// load parcellation
std::vector<mitk::BaseData::Pointer> parcellationInFile = mitk::IOUtil::Load( m_ParcellationPath );
if( parcellationInFile.empty() )
{
std::string errorMessage = "Parcellation at " + m_ParcellationPath + " could not be read. Aborting.";
CPPUNIT_ASSERT_MESSAGE( errorMessage, false );
}
mitk::BaseData* parcellationBaseData = parcellationInFile.at(0);
mitk::Image* parcellationImage = dynamic_cast<mitk::Image*>( parcellationBaseData );
// do creation
mitk::ConnectomicsNetworkCreator::Pointer connectomicsNetworkCreator = mitk::ConnectomicsNetworkCreator::New();
connectomicsNetworkCreator->SetSegmentation( parcellationImage );
connectomicsNetworkCreator->SetFiberBundle( fiberBundle );
connectomicsNetworkCreator->CalculateCenterOfMass();
connectomicsNetworkCreator->SetEndPointSearchRadius( 15 );
connectomicsNetworkCreator->CreateNetworkFromFibersAndSegmentation();
// load network
std::vector<mitk::BaseData::Pointer> referenceFile = mitk::IOUtil::Load( m_ReferenceNetworkPath );
if( referenceFile.empty() )
{
std::string errorMessage = "Reference Network at " + m_ReferenceNetworkPath + " could not be read. Aborting.";
CPPUNIT_ASSERT_MESSAGE( errorMessage, false );
}
mitk::BaseData* referenceBaseData = referenceFile.at(0);
mitk::ConnectomicsNetwork* referenceNetwork = dynamic_cast<mitk::ConnectomicsNetwork*>( referenceBaseData );
mitk::ConnectomicsNetwork::Pointer network = connectomicsNetworkCreator->GetNetwork();
CPPUNIT_ASSERT_MESSAGE( "Comparing created and reference network.", mitk::Equal( network.GetPointer(), referenceNetwork, mitk::eps, true) );
}
};
MITK_TEST_SUITE_REGISTRATION(mitkConnectomicsNetworkCreation)
diff --git a/Modules/Connectomics/Testing/mitkConnectomicsNetworkTest.cpp b/Modules/Connectomics/Testing/mitkConnectomicsNetworkTest.cpp
index 4c5e8b6..05db891 100644
--- a/Modules/Connectomics/Testing/mitkConnectomicsNetworkTest.cpp
+++ b/Modules/Connectomics/Testing/mitkConnectomicsNetworkTest.cpp
@@ -1,530 +1,530 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkTestingMacros.h"
#include "mitkConnectomicsNetwork.h"
#include "mitkConnectomicsSyntheticNetworkGenerator.h"
#include "mitkConnectomicsSimulatedAnnealingManager.h"
#include "mitkConnectomicsSimulatedAnnealingPermutationModularity.h"
#include "mitkConnectomicsSimulatedAnnealingCostFunctionModularity.h"
#include <vtkDebugLeaks.h>
#include <vector>
#include <string>
#include <utility>
/**Documentation
* Test for synthetic connectomics generation and connectomics network functionality
*/
int mitkConnectomicsNetworkTest(int, char* [])
{
// Test begins
MITK_TEST_BEGIN("mitkConnectomicsNetworkTest");
/// \todo Fix VTK memory leaks. Bug 18097.
vtkDebugLeaks::SetExitError(0);
// Typedefs
typedef mitk::ConnectomicsNetwork::VertexDescriptorType VertexType;
typedef mitk::ConnectomicsNetwork::NetworkNode NodeType;
// The test network
std::vector< NodeType > inNodes;
NodeType node;
node.id = 0;
node.label = "1-1";
node.coordinates.clear();
node.coordinates.push_back( 0 );
node.coordinates.push_back( 0 );
node.coordinates.push_back( 0 );
inNodes.push_back(node);
node.id = 1;
node.label = "2-1";
node.coordinates.clear();
node.coordinates.push_back( 10 );
node.coordinates.push_back( 0 );
node.coordinates.push_back( 0 );
inNodes.push_back(node);
node.id = 2;
node.label = "3-1";
node.coordinates.clear();
node.coordinates.push_back( 20 );
node.coordinates.push_back( 10 );
node.coordinates.push_back( 0 );
inNodes.push_back(node);
node.id = 3;
node.label = "4-1";
node.coordinates.clear();
node.coordinates.push_back( 30 );
node.coordinates.push_back( 20 );
node.coordinates.push_back( 0 );
inNodes.push_back(node);
node.id = 4;
node.label = "5-1";
node.coordinates.clear();
node.coordinates.push_back( 40 );
node.coordinates.push_back( 50 );
node.coordinates.push_back( 0 );
inNodes.push_back(node);
node.id = 5;
node.label = "6-2";
node.coordinates.clear();
node.coordinates.push_back( 0 );
node.coordinates.push_back( 0 );
node.coordinates.push_back( 10 );
inNodes.push_back(node);
node.id = 6;
node.label = "7-2";
node.coordinates.clear();
node.coordinates.push_back( 0 );
node.coordinates.push_back( 10 );
node.coordinates.push_back( 20 );
inNodes.push_back(node);
node.id = 7;
node.label = "8-2";
node.coordinates.clear();
node.coordinates.push_back( 0 );
node.coordinates.push_back( 20 );
node.coordinates.push_back( 30 );
inNodes.push_back(node);
node.id = 8;
node.label = "9-2";
node.coordinates.clear();
node.coordinates.push_back( 0 );
node.coordinates.push_back( 30 );
node.coordinates.push_back( 40 );
inNodes.push_back(node);
node.id = 9;
node.label = "10-3";
node.coordinates.clear();
node.coordinates.push_back( 20 );
node.coordinates.push_back( 0 );
node.coordinates.push_back( 10 );
inNodes.push_back(node);
node.id = 10;
node.label = "11-3";
node.coordinates.clear();
node.coordinates.push_back( 30 );
node.coordinates.push_back( 0 );
node.coordinates.push_back( 20 );
inNodes.push_back(node);
node.id = 11;
node.label = "12-3";
node.coordinates.clear();
node.coordinates.push_back( 40 );
node.coordinates.push_back( 0 );
node.coordinates.push_back( 30 );
inNodes.push_back(node);
std::vector< mitk::ConnectomicsNetwork::NetworkEdge > inEdges;
mitk::ConnectomicsNetwork::NetworkEdge edge;
edge.sourceId = 0;
edge.targetId = 1;
edge.fiber_count = 2;
inEdges.push_back( edge );
edge.sourceId = 0;
edge.targetId = 2;
edge.fiber_count = 2;
inEdges.push_back( edge );
edge.sourceId = 0;
edge.targetId = 4;
edge.fiber_count = 2;
inEdges.push_back( edge );
edge.sourceId = 1;
edge.targetId = 4;
edge.fiber_count = 2;
inEdges.push_back( edge );
edge.sourceId = 1;
edge.targetId = 3;
edge.fiber_count = 2;
inEdges.push_back( edge );
edge.sourceId = 2;
edge.targetId = 3;
edge.fiber_count = 2;
inEdges.push_back( edge );
edge.sourceId = 3;
edge.targetId = 4;
edge.fiber_count = 2;
inEdges.push_back( edge );
edge.sourceId = 4;
edge.targetId = 5;
edge.fiber_count = 2;
inEdges.push_back( edge );
edge.sourceId = 5;
edge.targetId = 6;
edge.fiber_count = 2;
inEdges.push_back( edge );
edge.sourceId = 5;
edge.targetId = 7;
edge.fiber_count = 2;
inEdges.push_back( edge );
edge.sourceId = 5;
edge.targetId = 8;
edge.fiber_count = 2;
inEdges.push_back( edge );
edge.sourceId = 7;
edge.targetId = 8;
edge.fiber_count = 2;
inEdges.push_back( edge );
edge.sourceId = 6;
edge.targetId = 8;
edge.fiber_count = 2;
inEdges.push_back( edge );
edge.sourceId = 6;
edge.targetId = 9;
edge.fiber_count = 2;
inEdges.push_back( edge );
edge.sourceId = 3;
edge.targetId = 10;
edge.fiber_count = 2;
inEdges.push_back( edge );
edge.sourceId = 9;
edge.targetId = 10;
edge.fiber_count = 2;
inEdges.push_back( edge );
edge.sourceId = 10;
edge.targetId = 11;
edge.fiber_count = 2;
inEdges.push_back( edge );
edge.sourceId = 9;
edge.targetId = 11;
edge.fiber_count = 2;
inEdges.push_back( edge );
// further variables
double eps(0.001);
try
{
// Testing synthetic network generation
mitk::ConnectomicsSyntheticNetworkGenerator::Pointer generator = mitk::ConnectomicsSyntheticNetworkGenerator::New();
MITK_TEST_CONDITION_REQUIRED(generator.IsNotNull(),"Synthetic network generator has been instantiated")
// first and second parameter
std::vector< std::pair<int, double> > parameterVector;
// name and isRandom
std::vector< std::pair<std::string, bool> > messageVector;
// order of results is # vertices, # edges, # self loops, average degree, connection density
// global clustering coefficient
std::vector< std::vector< double > > resultVector;
int numberOfOptions = 3;
parameterVector.resize(numberOfOptions);
messageVector.resize(numberOfOptions);
resultVector.resize(numberOfOptions);
// Create regular lattice network in the form of a cube with sidelength 5 and distance 10 between nodes
parameterVector[0] = std::pair< int, double>(5, 10);
messageVector[0] = std::pair<std::string, bool>("Regular Lattice Network", false);
resultVector[0].push_back( 5 * 5 * 5 );
resultVector[0].push_back( 300 );
resultVector[0].push_back( 0 );
resultVector[0].push_back( 4.8 );
resultVector[0].push_back(0.0387);
resultVector[0].push_back(0);
// Create a heterogeneous sphere network with 1 central node and 49 nodes on the surface and radius 10
parameterVector[1] = std::pair< int, double>(50, 10);
messageVector[1] = std::pair<std::string, bool>("Heterogeneous Sphere Network", false);
resultVector[1].push_back( 50 );
resultVector[1].push_back( 49 );
resultVector[1].push_back( 0 );
resultVector[1].push_back( 1.96 );
resultVector[1].push_back(0.0400);
resultVector[1].push_back(0);
// Create random network with 50 nodes and edges between them generated with a 0.1 likelihood
parameterVector[2] = std::pair< int, double>(50, 0.1);
messageVector[2] = std::pair<std::string, bool>("Random Network", true);
resultVector[2].push_back( 50 );
for(int loop(0); loop < numberOfOptions; loop++)
{
mitk::ConnectomicsNetwork::Pointer network =
generator->CreateSyntheticNetwork(loop, parameterVector[loop].first, parameterVector[loop].second);
bool generationWorked = generator->WasGenerationSuccessfull() && network.IsNotNull();
std::string message = messageVector[loop].first + " has been instantiated";
MITK_TEST_CONDITION_REQUIRED(generationWorked,message)
bool verticesCloseEnough( std::abs(resultVector[loop][0] - network->GetNumberOfVertices()) < eps);
MITK_TEST_CONDITION_REQUIRED( verticesCloseEnough, "Expected number of vertices")
if(!messageVector[loop].second)
{
bool edgesCloseEnough( std::abs(resultVector[loop][1] - network->GetNumberOfEdges()) < eps);
MITK_TEST_CONDITION_REQUIRED( edgesCloseEnough, "Expected number of edges")
bool selfLoopsCloseEnough( std::abs(resultVector[loop][2] - network->GetNumberOfSelfLoops()) < eps);
MITK_TEST_CONDITION_REQUIRED( selfLoopsCloseEnough, "Expected number of self loops")
bool avDegCloseEnough( std::abs(resultVector[loop][3] - network->GetAverageDegree()) < eps);
MITK_TEST_CONDITION_REQUIRED( avDegCloseEnough, "Expected average degree")
bool conDensCloseEnough( std::abs(resultVector[loop][4] - network->GetConnectionDensity()) < eps);
MITK_TEST_CONDITION_REQUIRED( conDensCloseEnough, "Expected connection density")
bool clustCoeffCloseEnough( std::abs(resultVector[loop][5] - network->GetGlobalClusteringCoefficient()) < eps);
MITK_TEST_CONDITION_REQUIRED( clustCoeffCloseEnough, "Expected global clustering coefficient")
}
}
}
catch (...)
{
MITK_ERROR << "Unhandled exception caught while testing synthetic network generation [FAILED]" ;
return EXIT_FAILURE;
}
try
{
// Testing network interface
// Create network
mitk::ConnectomicsNetwork::Pointer network = mitk::ConnectomicsNetwork::New();
std::vector< VertexType > vertexVector;
vertexVector.resize( inNodes.size() );
for(unsigned int loop(0); loop < inNodes.size(); loop++)
{
VertexType newVertex = network->AddVertex( inNodes[loop].id );
vertexVector[ inNodes[loop].id ] = newVertex;
network->SetLabel( newVertex, inNodes[loop].label );
network->SetCoordinates( newVertex, inNodes[loop].coordinates );
}
for(unsigned int loop(0); loop < inEdges.size(); loop++)
{
int sourceId = inEdges[loop].sourceId;
int targetId = inEdges[loop].targetId;
VertexType sourceVertex = vertexVector[ sourceId ];
VertexType targetVertex = vertexVector[ targetId ];
// there are two methods to add nodes
if( loop % 2 == 0 )
{
network->AddEdge(sourceVertex, targetVertex, 1);
for( int remaining( inEdges[loop].fiber_count ); remaining > 1; remaining-- )
{
network->IncreaseEdgeWeight( sourceVertex, targetVertex, 1 );
}
}
else
{
network->AddEdge(sourceVertex, targetVertex, sourceId, targetId, inEdges[loop].fiber_count );
}
}
// Test whether network parameters are as expected
MITK_TEST_CONDITION_REQUIRED( inNodes.size() == (unsigned int)network->GetNumberOfVertices(), "Expected number of vertices")
MITK_TEST_CONDITION_REQUIRED( inEdges.size() == (unsigned int)network->GetNumberOfEdges(), "Expected number of edges")
MITK_TEST_CONDITION_REQUIRED( 0 == network->GetNumberOfSelfLoops(), "Expected number of self loops")
bool avDegCloseEnough( std::abs(3 - network->GetAverageDegree()) < eps);
MITK_TEST_CONDITION_REQUIRED( avDegCloseEnough, "Expected average degree")
bool conDensCloseEnough( std::abs(0.2727 - network->GetConnectionDensity()) < eps);
MITK_TEST_CONDITION_REQUIRED( conDensCloseEnough, "Expected connection density")
bool clustCoeffCloseEnough( std::abs(0.4583 - network->GetGlobalClusteringCoefficient()) < eps);
MITK_TEST_CONDITION_REQUIRED( clustCoeffCloseEnough, "Expected global clustering coefficient")
MITK_TEST_CONDITION_REQUIRED( network->GetMaximumWeight() == 2, "Expected maximum weight")
MITK_TEST_CONDITION_REQUIRED( network->GetVectorOfAllVertexDescriptors().size() == vertexVector.size(), "Expected number of vertex descriptors")
}
catch (...)
{
MITK_ERROR << "Unhandled exception caught while testing network interface [FAILED]" ;
return EXIT_FAILURE;
}
try
{
// Testing modularity calculation
typedef std::map< VertexType, int > ToModuleMapType;
// Create network
mitk::ConnectomicsNetwork::Pointer network = mitk::ConnectomicsNetwork::New();
std::vector< VertexType > vertexVector;
vertexVector.resize( inNodes.size() );
for(unsigned int loop(0); loop < inNodes.size(); loop++)
{
VertexType newVertex = network->AddVertex( inNodes[loop].id );
vertexVector[ inNodes[loop].id ] = newVertex;
network->SetLabel( newVertex, inNodes[loop].label );
network->SetCoordinates( newVertex, inNodes[loop].coordinates );
}
for(unsigned int loop(0); loop < inEdges.size(); loop++)
{
int sourceId = inEdges[loop].sourceId;
int targetId = inEdges[loop].targetId;
VertexType sourceVertex = vertexVector[ sourceId ];
VertexType targetVertex = vertexVector[ targetId ];
// there are two methods to add nodes
if( loop % 2 == 0 )
{
network->AddEdge(sourceVertex, targetVertex, 1);
for( int remaining( inEdges[loop].fiber_count ); remaining > 1; remaining-- )
{
network->IncreaseEdgeWeight( sourceVertex, targetVertex, 1 );
}
}
else
{
network->AddEdge(sourceVertex, targetVertex, sourceId, targetId, inEdges[loop].fiber_count );
}
}
// Simulated annealing classes
mitk::ConnectomicsSimulatedAnnealingManager::Pointer manager = mitk::ConnectomicsSimulatedAnnealingManager::New();
mitk::ConnectomicsSimulatedAnnealingPermutationModularity::Pointer permutation = mitk::ConnectomicsSimulatedAnnealingPermutationModularity::New();
mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::Pointer costFunction = mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::New();
// Test whether modularity calculation behaves as expected
ToModuleMapType threeModuleSolution;
std::vector< VertexType > vertexInVector = network->GetVectorOfAllVertexDescriptors();
threeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 0 ], 0 ) );
threeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 1 ], 0 ) );
threeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 2 ], 0 ) );
threeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 3 ], 0 ) );
threeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 4 ], 0 ) );
threeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 5 ], 1 ) );
threeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 6 ], 1 ) );
threeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 7 ], 1 ) );
threeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 8 ], 1 ) );
threeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 9 ], 2 ) );
threeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 10 ], 2 ) );
threeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 11 ], 2 ) );
bool threeModuleModularity( std::abs(0.4753 - costFunction->CalculateModularity( network, &threeModuleSolution )) < eps);
MITK_TEST_CONDITION_REQUIRED( threeModuleModularity, "Expected three module modularity")
bool correctNumberOfModules( permutation->getNumberOfModules( &threeModuleSolution ) == 3 );
MITK_TEST_CONDITION_REQUIRED( correctNumberOfModules, "Expected number of modules")
bool correctNumberOfVertices( permutation->getNumberOfVerticesInModule( &threeModuleSolution, 0 ) == 5
&& permutation->getNumberOfVerticesInModule( &threeModuleSolution, 1 ) == 4
&& permutation->getNumberOfVerticesInModule( &threeModuleSolution, 2 ) == 3 );
MITK_TEST_CONDITION_REQUIRED( correctNumberOfVertices, "Expected number of vertices per module")
ToModuleMapType oneModuleSolution;
oneModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 0 ], 0 ) );
oneModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 1 ], 0 ) );
oneModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 2 ], 0 ) );
oneModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 3 ], 0 ) );
oneModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 4 ], 0 ) );
oneModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 5 ], 0 ) );
oneModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 6 ], 0 ) );
oneModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 7 ], 0 ) );
oneModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 8 ], 0 ) );
oneModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 9 ], 0 ) );
oneModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 10 ], 0 ) );
oneModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 11 ], 0 ) );
bool oneModuleModularity( std::abs(0.0 - costFunction->CalculateModularity( network, &oneModuleSolution )) < eps);
MITK_TEST_CONDITION_REQUIRED( oneModuleModularity, "Expected one module modularity")
ToModuleMapType badTwoModuleSolution;
badTwoModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 0 ], 0 ) );
badTwoModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 1 ], 0 ) );
badTwoModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 2 ], 0 ) );
badTwoModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 3 ], 0 ) );
badTwoModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 4 ], 0 ) );
badTwoModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 5 ], 1 ) );
badTwoModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 6 ], 1 ) );
badTwoModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 7 ], 1 ) );
badTwoModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 8 ], 0 ) );
badTwoModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 9 ], 1 ) );
badTwoModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 10 ], 1 ) );
badTwoModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 11 ], 0 ) );
bool badTwoModuleModularity( std::abs(0.097222 - costFunction->CalculateModularity( network, &badTwoModuleSolution )) < eps);
MITK_TEST_CONDITION_REQUIRED( badTwoModuleModularity, "Expected bad two module modularity")
ToModuleMapType noInternalLinksThreeModuleSolution;
noInternalLinksThreeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 0 ], 0 ) );
noInternalLinksThreeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 1 ], 2 ) );
noInternalLinksThreeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 2 ], 1 ) );
noInternalLinksThreeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 3 ], 0 ) );
noInternalLinksThreeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 4 ], 1 ) );
noInternalLinksThreeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 5 ], 2 ) );
noInternalLinksThreeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 6 ], 0 ) );
noInternalLinksThreeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 7 ], 0 ) );
noInternalLinksThreeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 8 ], 1 ) );
noInternalLinksThreeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 9 ], 2 ) );
noInternalLinksThreeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 10 ], 1 ) );
noInternalLinksThreeModuleSolution.insert( std::pair<VertexType, int>( vertexInVector[ 11 ], 0 ) );
bool noInternalThreeModuleModularity( std::abs(-0.3395 - costFunction->CalculateModularity( network, &noInternalLinksThreeModuleSolution )) < eps);
MITK_TEST_CONDITION_REQUIRED( noInternalThreeModuleModularity, "Expected three module modularity containing no internal links")
}
catch (...)
{
MITK_ERROR << "Unhandled exception caught while testing modularity calculation [FAILED]" ;
return EXIT_FAILURE;
}
// Test ends
MITK_TEST_END();
}
diff --git a/Modules/Connectomics/Testing/mitkConnectomicsStatisticsCalculatorTest.cpp b/Modules/Connectomics/Testing/mitkConnectomicsStatisticsCalculatorTest.cpp
index 02b6689..c5be53e 100644
--- a/Modules/Connectomics/Testing/mitkConnectomicsStatisticsCalculatorTest.cpp
+++ b/Modules/Connectomics/Testing/mitkConnectomicsStatisticsCalculatorTest.cpp
@@ -1,141 +1,141 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// Testing
#include "mitkTestingMacros.h"
#include "mitkTestFixture.h"
// std includes
#include <string>
#include <sstream>
// MITK includes
#include <mitkIOUtil.h>
#include <mitkConnectomicsStatisticsCalculator.h>
// VTK includes
#include <vtkDebugLeaks.h>
class mitkConnectomicsStatisticsCalculatorTestSuite : public mitk::TestFixture
{
CPPUNIT_TEST_SUITE(mitkConnectomicsStatisticsCalculatorTestSuite);
/// \todo Fix VTK memory leaks. Bug 18097.
vtkDebugLeaks::SetExitError(0);
MITK_TEST(StatisticsCalculatorUpdate);
CPPUNIT_TEST_SUITE_END();
private:
mitk::ConnectomicsNetwork::Pointer m_Network;
std::string m_NetworkPath;
public:
/**
* @brief Setup Always call this method before each Test-case to ensure correct and new intialization of the used members for a new test case. (If the members are not used in a test, the method does not need to be called).
*/
void setUp() override
{
//load network
m_NetworkPath = GetTestDataFilePath("DiffusionImaging/Connectomics/reference.cnf");
std::vector<mitk::BaseData::Pointer> networkFile = mitk::IOUtil::Load( m_NetworkPath );
if( networkFile.empty() )
{
std::string errorMessage = "File at " + m_NetworkPath + " could not be read. Aborting.";
CPPUNIT_ASSERT_MESSAGE( errorMessage, !networkFile.empty() );
return;
}
mitk::BaseData* networkBaseData = networkFile.at(0);
mitk::ConnectomicsNetwork* network = dynamic_cast<mitk::ConnectomicsNetwork*>( networkBaseData );
if( !network )
{
std::string errorMessage = "Read file at " + m_NetworkPath + " could not be recognized as network. Aborting.";
CPPUNIT_ASSERT_MESSAGE( errorMessage, network);
return;
}
m_Network = network;
}
void tearDown() override
{
m_Network = nullptr;
m_NetworkPath = "";
}
void StatisticsCalculatorUpdate()
{
mitk::ConnectomicsStatisticsCalculator::Pointer statisticsCalculator = mitk::ConnectomicsStatisticsCalculator::New();
statisticsCalculator->SetNetwork( m_Network );
statisticsCalculator->Update();
double eps( 0.0001 );
CPPUNIT_ASSERT_MESSAGE( "GetNumberOfVertices", mitk::Equal( statisticsCalculator->GetNumberOfVertices( ), 4 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetNumberOfEdges" , mitk::Equal( statisticsCalculator->GetNumberOfEdges( ), 5 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetAverageDegree", mitk::Equal( statisticsCalculator->GetAverageDegree( ), 2.5 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetConnectionDensity", mitk::Equal( statisticsCalculator->GetConnectionDensity( ), 0.833333 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetNumberOfConnectedComponents", mitk::Equal( statisticsCalculator->GetNumberOfConnectedComponents( ), 1 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetAverageComponentSize", mitk::Equal( statisticsCalculator->GetAverageComponentSize( ), 4 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetLargestComponentSize", mitk::Equal( statisticsCalculator->GetLargestComponentSize( ), 4 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetRatioOfNodesInLargestComponent", mitk::Equal( statisticsCalculator->GetRatioOfNodesInLargestComponent( ), 1 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetHopPlotExponent", mitk::Equal( statisticsCalculator->GetHopPlotExponent( ), 0.192645 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetEffectiveHopDiameter", mitk::Equal( statisticsCalculator->GetEffectiveHopDiameter( ), 1 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetAverageClusteringCoefficientsC", mitk::Equal( statisticsCalculator->GetAverageClusteringCoefficientsC( ), 0.833333 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetAverageClusteringCoefficientsD", mitk::Equal( statisticsCalculator->GetAverageClusteringCoefficientsD( ), 0.916667 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetAverageClusteringCoefficientsE", mitk::Equal( statisticsCalculator->GetAverageClusteringCoefficientsE( ), 0.833333 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetAverageVertexBetweennessCentrality", mitk::Equal( statisticsCalculator->GetAverageVertexBetweennessCentrality( ), 0.25 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetAverageEdgeBetweennessCentrality", mitk::Equal( statisticsCalculator->GetAverageEdgeBetweennessCentrality( ), 1.4 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetNumberOfIsolatedPoints" , mitk::Equal( statisticsCalculator->GetNumberOfIsolatedPoints( ), 0 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetRatioOfIsolatedPoints", mitk::Equal( statisticsCalculator->GetRatioOfIsolatedPoints( ), 0 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetNumberOfEndPoints", mitk::Equal( statisticsCalculator->GetNumberOfEndPoints( ), 0 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetRatioOfEndPoints", mitk::Equal( statisticsCalculator->GetRatioOfEndPoints( ), 0 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetDiameter", mitk::Equal( statisticsCalculator->GetDiameter( ), 2 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetDiameter90", mitk::Equal( statisticsCalculator->GetDiameter90( ), 2 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetRadius" , mitk::Equal( statisticsCalculator->GetRadius( ), 1 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetRadius90", mitk::Equal( statisticsCalculator->GetRadius90( ), 1 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetAverageEccentricity", mitk::Equal( statisticsCalculator->GetAverageEccentricity( ), 1.5 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetAverageEccentricity90", mitk::Equal( statisticsCalculator->GetAverageEccentricity90( ), 1.5 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetAveragePathLength" , mitk::Equal( statisticsCalculator->GetAveragePathLength( ), 1.16667 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetNumberOfCentralPoints" , mitk::Equal( statisticsCalculator->GetNumberOfCentralPoints( ), 2 , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetRatioOfCentralPoints", mitk::Equal( statisticsCalculator->GetRatioOfCentralPoints( ), 0.5 , eps, true ) );
// CPPUNIT_ASSERT_MESSAGE( " ", mitk::Equal( statisticsCalculator->GetSpectralRadius( ), , eps, true ) );
// CPPUNIT_ASSERT_MESSAGE( " ", mitk::Equal( statisticsCalculator->GetSecondLargestEigenValue( ), , eps, true ) );
// CPPUNIT_ASSERT_MESSAGE( " ", mitk::Equal( statisticsCalculator->GetAdjacencyTrace( ), , eps, true ) );
// CPPUNIT_ASSERT_MESSAGE( " ", mitk::Equal( statisticsCalculator->GetAdjacencyEnergy( ), , eps, true ) );
// CPPUNIT_ASSERT_MESSAGE( " ", mitk::Equal( statisticsCalculator->GetLaplacianTrace( ), , eps, true ) );
// CPPUNIT_ASSERT_MESSAGE( " ", mitk::Equal( statisticsCalculator->GetLaplacianEnergy( ), , eps, true ) );
// CPPUNIT_ASSERT_MESSAGE( " ", mitk::Equal( statisticsCalculator->GetLaplacianSpectralGap( ), , eps, true ) );
// CPPUNIT_ASSERT_MESSAGE( " ", mitk::Equal( statisticsCalculator->GetNormalizedLaplacianTrace( ), , eps, true ) );
// CPPUNIT_ASSERT_MESSAGE( " ", mitk::Equal( statisticsCalculator->GetNormalizedLaplacianEnergy( ), , eps, true ) );
// CPPUNIT_ASSERT_MESSAGE( " ", mitk::Equal( statisticsCalculator->GetNormalizedLaplacianNumberOf2s( ), , eps, true ) );
// CPPUNIT_ASSERT_MESSAGE( " ", mitk::Equal( statisticsCalculator->GetNormalizedLaplacianNumberOf1s( ), , eps, true ) );
// CPPUNIT_ASSERT_MESSAGE( " ", mitk::Equal( statisticsCalculator->GetNormalizedLaplacianNumberOf0s( ), , eps, true ) );
// CPPUNIT_ASSERT_MESSAGE( " ", mitk::Equal( statisticsCalculator->GetNormalizedLaplacianLowerSlope( ), , eps, true ) );
// CPPUNIT_ASSERT_MESSAGE( " ", mitk::Equal( statisticsCalculator->GetNormalizedLaplacianUpperSlope( ), , eps, true ) );
CPPUNIT_ASSERT_MESSAGE( "GetSmallWorldness", mitk::Equal( statisticsCalculator->GetSmallWorldness( ), 1.72908 , eps, true ) );
}
};
MITK_TEST_SUITE_REGISTRATION(mitkConnectomicsStatisticsCalculator)
diff --git a/Modules/Connectomics/Testing/mitkCorrelationCalculatorTest.cpp b/Modules/Connectomics/Testing/mitkCorrelationCalculatorTest.cpp
index bb97b7a..d0f703d 100644
--- a/Modules/Connectomics/Testing/mitkCorrelationCalculatorTest.cpp
+++ b/Modules/Connectomics/Testing/mitkCorrelationCalculatorTest.cpp
@@ -1,294 +1,294 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// Testing
#include "mitkTestingMacros.h"
#include "mitkTestFixture.h"
// std includes
#include <string>
// MITK includes
#include "mitkCorrelationCalculator.h"
#include <mitkImage.h>
#include <mitkImagePixelWriteAccessor.h>
#include <mitkImageCast.h>
#include <mitkITKImageImport.h>
// VTK includes
#include <vtkDebugLeaks.h>
class mitkCorrelationCalculatorTestSuite : public mitk::TestFixture
{
CPPUNIT_TEST_SUITE(mitkCorrelationCalculatorTestSuite);
/// \todo Fix VTK memory leaks. Bug 18097.
vtkDebugLeaks::SetExitError(0);
MITK_TEST(CalculateWholeCorrelation);
MITK_TEST(CalculateParcelCorrelation);
CPPUNIT_TEST_SUITE_END();
private:
mitk::Image::Pointer m_ParcellationImage;
mitk::Image::Pointer m_TimeSeriesImage;
public:
/**
* @brief Setup Always call this method before each Test-case to ensure correct and new intialization of the used members for a new test case. (If the members are not used in a test, the method does not need to be called).
*/
void setUp() override
{
// The setup is somewhat cumbersome, due to the fact, that the mitk-itk conversion
// functions do not play nicely with 4D images
//create test images
itk::Image<int, 4>::Pointer timeSeriesTestImage = itk::Image<int, 4>::New();
itk::Image<int, 4>::RegionType timeSeriesTestRegion;
itk::Image<int, 4>::IndexType timeSeriesTestIndex;
itk::Image<int, 4>::SizeType timeSeriesTestSize;
timeSeriesTestIndex[0] = 0;
timeSeriesTestIndex[1] = 0;
timeSeriesTestIndex[2] = 0;
timeSeriesTestIndex[3] = 0;
timeSeriesTestSize[0] = 3;
timeSeriesTestSize[1] = 3;
timeSeriesTestSize[2] = 3;
timeSeriesTestSize[3] = 10;
timeSeriesTestRegion.SetIndex(timeSeriesTestIndex);
timeSeriesTestRegion.SetSize(timeSeriesTestSize);
timeSeriesTestImage->SetRegions(timeSeriesTestRegion);
timeSeriesTestImage->Allocate();
timeSeriesTestImage->FillBuffer(0);
timeSeriesTestImage->Update();
itk::Image<int, 3>::Pointer parcellationTestImage = itk::Image<int, 3>::New();
itk::Image<int, 3>::RegionType parcellationTestRegion;
itk::Image<int, 3>::IndexType parcellationTestIndex;
itk::Image<int, 3>::SizeType parcellationTestSize;
parcellationTestIndex[0] = 0;
parcellationTestIndex[1] = 0;
parcellationTestIndex[2] = 0;
parcellationTestSize[0] = 3;
parcellationTestSize[1] = 3;
parcellationTestSize[2] = 3;
parcellationTestRegion.SetIndex(parcellationTestIndex);
parcellationTestRegion.SetSize(parcellationTestSize);
parcellationTestImage->SetRegions(parcellationTestRegion);
parcellationTestImage->Allocate();
//Fill test images with values
mitk::Image::Pointer tsTestImage = mitk::Image::New();
mitk::GrabItkImageMemory( timeSeriesTestImage, tsTestImage.GetPointer() );
mitk::Image::Pointer pTestImage = mitk::Image::New();
mitk::GrabItkImageMemory( parcellationTestImage, pTestImage.GetPointer());
//divide parcellation image into 3 different parcels
for( int loop(0); loop < 27; ++loop)
{
itk::Image<int, 3>::IndexType parcellationIndex;
parcellationIndex[2] = (loop / 9);
parcellationIndex[1] = (loop / 3) % 3;
parcellationIndex[0] = loop % 3;
if(loop < 9)
{
parcellationTestImage->SetPixel(parcellationIndex, 1);
}
else if( loop < 15 || (loop > 17 && loop < 21) )
{
parcellationTestImage->SetPixel(parcellationIndex, 2);
}
else
{
parcellationTestImage->SetPixel(parcellationIndex, 3);
}
}
mitk::ImagePixelWriteAccessor<int,4> writeAccess( tsTestImage );
//fill time series image with similar time series in each parcel
for( int loop(0); loop < 270; ++loop)
{
itk::Image<int, 4>::IndexType timeSeriesIndex;
timeSeriesIndex[3] = (loop / 27);
timeSeriesIndex[2] = (loop / 9) % 3;
timeSeriesIndex[1] = (loop / 3) % 3;
timeSeriesIndex[0] = loop % 3;
itk::Image<int, 3>::IndexType parcellationIndex;
parcellationIndex[2] = (loop / 9) % 3;
parcellationIndex[1] = (loop / 3) % 3;
parcellationIndex[0] = loop % 3;
if( mitk::Equal(parcellationTestImage->GetPixel(parcellationIndex), 1) )
{
writeAccess.SetPixelByIndex(timeSeriesIndex, 1 + loop);
}
else if( mitk::Equal(parcellationTestImage->GetPixel(parcellationIndex), 2) )
{
writeAccess.SetPixelByIndex(timeSeriesIndex, 1 + (loop % 13 - loop % 11) );
}
else
{
writeAccess.SetPixelByIndex(timeSeriesIndex, 1 + ( loop - loop % 2) );
}
}
//end create test images
m_ParcellationImage = pTestImage;
m_TimeSeriesImage = tsTestImage;
}
void tearDown() override
{
m_ParcellationImage = nullptr;
m_TimeSeriesImage = nullptr;
}
void CalculateWholeCorrelation()
{
mitk::CorrelationCalculator<int>::Pointer correlationCalculator = mitk::CorrelationCalculator<int>::New();
correlationCalculator->SetTimeSeriesImage( m_TimeSeriesImage );
correlationCalculator->DoWholeCorrelation();
const vnl_matrix< double >* cM = correlationCalculator->GetCorrelationMatrix();
bool equal(true);
// instead of checking the entire 27 x 27 matrix
// just check 3 values and assume if they are equal entire
// matrix is likely to be equal
if( std::abs((*cM)[0][0] - 1) > 0.00001 )
{
equal = false;
}
if( std::abs((*cM)[2][10] - 0.00828941) > 0.00001 )
{
equal = false;
}
if( std::abs((*cM)[14][8] - 0.636613) > 0.00001 )
{
equal = false;
}
CPPUNIT_ASSERT_MESSAGE( "Comparing created and reference correlation matrix sample points.", equal );
}
void CalculateParcelCorrelation()
{
mitk::CorrelationCalculator<int>::Pointer correlationCalculator = mitk::CorrelationCalculator<int>::New();
correlationCalculator->SetTimeSeriesImage( m_TimeSeriesImage );
correlationCalculator->SetParcellationImage( m_ParcellationImage );
correlationCalculator->DoParcelCorrelation();
const vnl_matrix< double >* cM = correlationCalculator->GetCorrelationMatrix();
bool equal(true);
// diagonal should be 1
if( std::abs((*cM)[0][0] - 1) > 0.00001 )
{
equal = false;
}
if( std::abs((*cM)[1][1] - 1) > 0.00001 )
{
equal = false;
}
if( std::abs((*cM)[2][2] - 1) > 0.00001 )
{
equal = false;
}
// parcel 0 and parcel 1 should correlate with -0.431111
if( std::abs((*cM)[1][0] - -0.431111) > 0.00001 )
{
equal = false;
}
if( std::abs((*cM)[0][1] - -0.431111) > 0.00001 )
{
equal = false;
}
// parcel 0 and parcel 2 should correlate with 1
if( std::abs((*cM)[0][2] - 1) > 0.00001 )
{
equal = false;
}
if( std::abs((*cM)[2][0] - 1) > 0.00001 )
{
equal = false;
}
// parcel 1 and parcel 2 should correlate with -0.430522
if( std::abs((*cM)[1][2] - -0.430522) > 0.00001 )
{
equal = false;
}
if( std::abs((*cM)[2][1] - -0.430522) > 0.00001 )
{
equal = false;
}
CPPUNIT_ASSERT_MESSAGE( "Comparing created and reference correlation matrix.", equal );
mitk::ConnectomicsNetwork::Pointer network = correlationCalculator->GetConnectomicsNetwork();
mitk::ConnectomicsNetwork::Pointer refNetwork = mitk::ConnectomicsNetwork::New();
mitk::ConnectomicsNetwork::VertexDescriptorType x = refNetwork->AddVertex( 1 );
mitk::ConnectomicsNetwork::VertexDescriptorType y = refNetwork->AddVertex( 2 );
mitk::ConnectomicsNetwork::VertexDescriptorType z = refNetwork->AddVertex( 3 );
refNetwork->AddEdge(x,y,1);
refNetwork->AddEdge(x,z,1);
refNetwork->AddEdge(y,z,1);
CPPUNIT_ASSERT_MESSAGE( "Comparing created and reference network.", mitk::Equal( network.GetPointer(), refNetwork, mitk::eps, true) );
// check sample parcels for other methods
correlationCalculator->DoParcelCorrelation( mitk::CorrelationCalculator<int>::UseAverageCorrelation );
cM = correlationCalculator->GetCorrelationMatrix();
// parcel 0 and parcel 1 should correlate with -0.0643023
equal = true;
if( std::abs((*cM)[1][0] - -0.0643023) > 0.00001 )
{
equal = false;
}
// parcel 0 and parcel 2 should correlate with 0.99998
if( std::abs((*cM)[2][0] - 0.99998) > 0.00001 )
{
equal = false;
}
CPPUNIT_ASSERT_MESSAGE( "Comparing sample parcel correlation for average correlation.", equal );
correlationCalculator->DoParcelCorrelation( mitk::CorrelationCalculator<int>::UseMaximumCorrelation );
cM = correlationCalculator->GetCorrelationMatrix();
// parcel 0 and parcel 1 should correlate with 0.636613
equal = true;
if( std::abs((*cM)[1][0] - 0.636613) > 0.00001 )
{
equal = false;
}
// parcel 0 and parcel 2 should correlate with 0.99998
if( std::abs((*cM)[2][0] - 0.99998) > 0.00001 )
{
equal = false;
}
CPPUNIT_ASSERT_MESSAGE( "Comparing sample parcel correlation for maximum correlation.", equal );
}
};
MITK_TEST_SUITE_REGISTRATION(mitkCorrelationCalculator)
diff --git a/Modules/DiffusionCmdApps/Connectomics/NetworkCreation.cpp b/Modules/DiffusionCmdApps/Connectomics/NetworkCreation.cpp
index 8c1d204..22b6dfd 100644
--- a/Modules/DiffusionCmdApps/Connectomics/NetworkCreation.cpp
+++ b/Modules/DiffusionCmdApps/Connectomics/NetworkCreation.cpp
@@ -1,119 +1,119 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// std includes
#include <string>
// CTK includes
#include "mitkDiffusionCommandLineParser.h"
// MITK includes
#include "mitkConnectomicsNetworkCreator.h"
#include <mitkCoreObjectFactory.h>
#include <mitkIOUtil.h>
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Network Creation");
parser.setCategory("Connectomics");
parser.setDescription("");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "f", mitkDiffusionCommandLineParser::String, "Input Tractogram", "input tractogram (.fib)", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "p", mitkDiffusionCommandLineParser::String, "Parcellation", "parcellation image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output network", "where to save the output (.cnf; .mat)", us::Any(), false);
parser.addArgument("noCenterOfMass", "", mitkDiffusionCommandLineParser::Bool, "No center of mass", "Do not use center of mass for node positions");
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
//default values
bool noCenterOfMass( false );
// parse command line arguments
std::string fiberFilename = us::any_cast<std::string>(parsedArgs["f"]);
std::string parcellationFilename = us::any_cast<std::string>(parsedArgs["p"]);
std::string outputFilename = us::any_cast<std::string>(parsedArgs["o"]);
if (parsedArgs.count("noCenterOfMass"))
noCenterOfMass = us::any_cast<bool>(parsedArgs["noCenterOfMass"]);
try
{
// load fiber image
std::vector<mitk::BaseData::Pointer> fiberInfile = mitk::IOUtil::Load( fiberFilename);
if( fiberInfile.empty() )
{
std::string errorMessage = "Fiber Image at " + fiberFilename + " could not be read. Aborting.";
MITK_ERROR << errorMessage;
return EXIT_FAILURE;
}
mitk::BaseData* fiberBaseData = fiberInfile.at(0);
mitk::FiberBundle* fiberBundle = dynamic_cast<mitk::FiberBundle*>( fiberBaseData );
// load parcellation
std::vector<mitk::BaseData::Pointer> parcellationInFile =
mitk::IOUtil::Load( parcellationFilename);
if( parcellationInFile.empty() )
{
std::string errorMessage = "Parcellation at " + parcellationFilename + " could not be read. Aborting.";
MITK_ERROR << errorMessage;
return EXIT_FAILURE;
}
mitk::BaseData* parcellationBaseData = parcellationInFile.at(0);
mitk::Image* parcellationImage = dynamic_cast<mitk::Image*>( parcellationBaseData );
// do creation
mitk::ConnectomicsNetworkCreator::Pointer connectomicsNetworkCreator = mitk::ConnectomicsNetworkCreator::New();
connectomicsNetworkCreator->SetSegmentation( parcellationImage );
connectomicsNetworkCreator->SetFiberBundle( fiberBundle );
if( !noCenterOfMass )
{
connectomicsNetworkCreator->CalculateCenterOfMass();
}
connectomicsNetworkCreator->SetMappingStrategy(mitk::ConnectomicsNetworkCreator::MappingStrategy::EndElementPosition);
connectomicsNetworkCreator->CreateNetworkFromFibersAndSegmentation();
mitk::ConnectomicsNetwork::Pointer network = connectomicsNetworkCreator->GetNetwork();
mitk::IOUtil::Save(network.GetPointer(), outputFilename );
return EXIT_SUCCESS;
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
std::cout << "DONE";
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/Connectomics/NetworkStatistics.cpp b/Modules/DiffusionCmdApps/Connectomics/NetworkStatistics.cpp
index 573f86b..68fc1f4 100644
--- a/Modules/DiffusionCmdApps/Connectomics/NetworkStatistics.cpp
+++ b/Modules/DiffusionCmdApps/Connectomics/NetworkStatistics.cpp
@@ -1,570 +1,570 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// std includes
#include <string>
#include <sstream>
#include <fstream>
#include <vector>
#include <map>
#include <utility>
// boost includes
#include <boost/algorithm/string.hpp>
// ITK includes
#include <itkImageFileWriter.h>
// CTK includes
#include "mitkDiffusionCommandLineParser.h"
// MITK includes
#include <mitkConnectomicsStatisticsCalculator.h>
#include <mitkConnectomicsNetworkThresholder.h>
#include <itkConnectomicsNetworkToConnectivityMatrixImageFilter.h>
#include <mitkIOUtil.h>
#include <mitkLocaleSwitch.h>
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Network Creation");
parser.setCategory("Connectomics");
parser.setDescription("");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input network", "input connectomics network (.cnf)", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output file", "name of output file", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("noGlobalStatistics", "g", mitkDiffusionCommandLineParser::Bool, "No global statistics", "Do not calculate global statistics");
parser.addArgument("createConnectivityMatriximage", "I", mitkDiffusionCommandLineParser::Bool, "Write connectivity matrix image", "Write connectivity matrix image");
parser.addArgument("binaryConnectivity", "b", mitkDiffusionCommandLineParser::Bool, "Binary connectivity", "Whether to create a binary connectivity matrix");
parser.addArgument("rescaleConnectivity", "r", mitkDiffusionCommandLineParser::Bool, "Rescale connectivity", "Whether to rescale the connectivity matrix");
parser.addArgument("localStatistics", "L", mitkDiffusionCommandLineParser::StringList, "Local statistics", "Provide a list of node labels for local statistics", us::Any());
parser.addArgument("regionList", "R", mitkDiffusionCommandLineParser::StringList, "Region list", "A space separated list of regions. Each region has the format\n regionname;label1;label2;...;labelN", us::Any());
parser.addArgument("granularity", "gr", mitkDiffusionCommandLineParser::Int, "Granularity", "How finely to test the density range and how many thresholds to consider",1);
parser.addArgument("startDensity", "d", mitkDiffusionCommandLineParser::Float, "Start Density", "Largest density for the range",1.0);
parser.addArgument("thresholdStepSize", "t", mitkDiffusionCommandLineParser::Int, "Step size threshold", "Distance of two adjacent thresholds",3);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
//default values
bool noGlobalStatistics( false );
bool binaryConnectivity( false );
bool rescaleConnectivity( false );
bool createConnectivityMatriximage( false );
int granularity( 1 );
double startDensity( 1.0 );
int thresholdStepSize( 3 );
// parse command line arguments
std::string networkName = us::any_cast<std::string>(parsedArgs["i"]);
std::string outName = us::any_cast<std::string>(parsedArgs["o"]);
mitkDiffusionCommandLineParser::StringContainerType localLabels;
if(parsedArgs.count("localStatistics"))
{
localLabels = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["localStatistics"]);
}
mitkDiffusionCommandLineParser::StringContainerType unparsedRegions;
std::map< std::string, std::vector<std::string> > parsedRegions;
std::map< std::string, std::vector<std::string> >::iterator parsedRegionsIterator;
if(parsedArgs.count("regionList"))
{
unparsedRegions = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["regionList"]);
for(unsigned int index(0); index < unparsedRegions.size(); index++ )
{
std::vector< std::string > tempRegionVector;
boost::split(tempRegionVector, unparsedRegions.at(index), boost::is_any_of(";"));
std::vector< std::string >::const_iterator begin = tempRegionVector.begin();
std::vector< std::string >::const_iterator last = tempRegionVector.begin() + tempRegionVector.size();
std::vector< std::string > insertRegionVector(begin + 1, last);
if( parsedRegions.count( tempRegionVector.at(0) ) == 0 )
{
parsedRegions.insert( std::pair< std::string, std::vector<std::string> >( tempRegionVector.at(0), insertRegionVector) );
}
else
{
MITK_ERROR << "Region already exists. Skipping second occurrence.";
}
}
}
if (parsedArgs.count("noGlobalStatistics"))
noGlobalStatistics = us::any_cast<bool>(parsedArgs["noGlobalStatistics"]);
if (parsedArgs.count("binaryConnectivity"))
binaryConnectivity = us::any_cast<bool>(parsedArgs["binaryConnectivity"]);
if (parsedArgs.count("rescaleConnectivity"))
rescaleConnectivity = us::any_cast<bool>(parsedArgs["rescaleConnectivity"]);
if (parsedArgs.count("createConnectivityMatriximage"))
createConnectivityMatriximage = us::any_cast<bool>(parsedArgs["createConnectivityMatriximage"]);
if (parsedArgs.count("granularity"))
granularity = us::any_cast<int>(parsedArgs["granularity"]);
if (parsedArgs.count("startDensity"))
startDensity = us::any_cast<float>(parsedArgs["startDensity"]);
if (parsedArgs.count("thresholdStepSize"))
thresholdStepSize = us::any_cast<int>(parsedArgs["thresholdStepSize"]);
try
{
// load network
std::vector<mitk::BaseData::Pointer> networkFile =
mitk::IOUtil::Load( networkName);
if( networkFile.empty() )
{
std::string errorMessage = "File at " + networkName + " could not be read. Aborting.";
MITK_ERROR << errorMessage;
return EXIT_FAILURE;
}
mitk::BaseData* networkBaseData = networkFile.at(0);
mitk::ConnectomicsNetwork* network = dynamic_cast<mitk::ConnectomicsNetwork*>( networkBaseData );
if( !network )
{
std::string errorMessage = "Read file at " + networkName + " could not be recognized as network. Aborting.";
MITK_ERROR << errorMessage;
return EXIT_FAILURE;
}
// streams
std::stringstream globalHeaderStream;
globalHeaderStream << "NumberOfVertices "
<< "NumberOfEdges "
<< "AverageDegree "
<< "ConnectionDensity "
<< "NumberOfConnectedComponents "
<< "AverageComponentSize "
<< "LargestComponentSize "
<< "RatioOfNodesInLargestComponent "
<< "HopPlotExponent "
<< "EffectiveHopDiameter "
<< "AverageClusteringCoefficientsC "
<< "AverageClusteringCoefficientsD "
<< "AverageClusteringCoefficientsE "
<< "AverageVertexBetweennessCentrality "
<< "AverageEdgeBetweennessCentrality "
<< "NumberOfIsolatedPoints "
<< "RatioOfIsolatedPoints "
<< "NumberOfEndPoints "
<< "RatioOfEndPoints "
<< "Diameter "
<< "Diameter90 "
<< "Radius "
<< "Radius90 "
<< "AverageEccentricity "
<< "AverageEccentricity90 "
<< "AveragePathLength "
<< "NumberOfCentralPoints "
<< "RatioOfCentralPoints "
<< "SpectralRadius "
<< "SecondLargestEigenValue "
<< "AdjacencyTrace "
<< "AdjacencyEnergy "
<< "LaplacianTrace "
<< "LaplacianEnergy "
<< "LaplacianSpectralGap "
<< "NormalizedLaplacianTrace "
<< "NormalizedLaplacianEnergy "
<< "NormalizedLaplacianNumberOf2s "
<< "NormalizedLaplacianNumberOf1s "
<< "NormalizedLaplacianNumberOf0s "
<< "NormalizedLaplacianLowerSlope "
<< "NormalizedLaplacianUpperSlope "
<< "SmallWorldness"
<< std::endl;
std::stringstream localHeaderStream;
std::stringstream regionalHeaderStream;
std::stringstream globalDataStream;
std::stringstream localDataStream;
std::stringstream regionalDataStream;
std::string globalOutName = outName + "_global.txt";
std::string localOutName = outName + "_local.txt";
std::string regionalOutName = outName + "_regional.txt";
bool firstRun( true );
// iterate over all three possible methods
for(unsigned int method( 0 ); method < 3; method++)
{
// 0 - Random removal threshold
// 1 - Largest density below threshold
// 2 - Threshold based
// iterate over possible targets
for( int step = 0; step < granularity; ++step )
{
double targetValue( 0.0 );
switch ( method )
{
case mitk::ConnectomicsNetworkThresholder::RandomRemovalOfWeakest :
case mitk::ConnectomicsNetworkThresholder::LargestLowerThanDensity :
targetValue = startDensity * (1 - static_cast<double>( step ) / ( granularity + 0.5 ) );
break;
case mitk::ConnectomicsNetworkThresholder::ThresholdBased :
targetValue = static_cast<double>( thresholdStepSize * step );
break;
default:
MITK_ERROR << "Invalid thresholding method called, aborting.";
return EXIT_FAILURE;
break;
}
mitk::ConnectomicsNetworkThresholder::Pointer thresholder = mitk::ConnectomicsNetworkThresholder::New();
thresholder->SetNetwork( network );
thresholder->SetTargetThreshold( targetValue );
thresholder->SetTargetDensity( targetValue );
thresholder->SetThresholdingScheme( static_cast<mitk::ConnectomicsNetworkThresholder::ThresholdingSchemes>(method) );
mitk::ConnectomicsNetwork::Pointer thresholdedNetwork = thresholder->GetThresholdedNetwork();
mitk::ConnectomicsStatisticsCalculator::Pointer statisticsCalculator = mitk::ConnectomicsStatisticsCalculator::New();
statisticsCalculator->SetNetwork( thresholdedNetwork );
statisticsCalculator->Update();
// global statistics
if( !noGlobalStatistics )
{
globalDataStream << statisticsCalculator->GetNumberOfVertices() << " "
<< statisticsCalculator->GetNumberOfEdges() << " "
<< statisticsCalculator->GetAverageDegree() << " "
<< statisticsCalculator->GetConnectionDensity() << " "
<< statisticsCalculator->GetNumberOfConnectedComponents() << " "
<< statisticsCalculator->GetAverageComponentSize() << " "
<< statisticsCalculator->GetLargestComponentSize() << " "
<< statisticsCalculator->GetRatioOfNodesInLargestComponent() << " "
<< statisticsCalculator->GetHopPlotExponent() << " "
<< statisticsCalculator->GetEffectiveHopDiameter() << " "
<< statisticsCalculator->GetAverageClusteringCoefficientsC() << " "
<< statisticsCalculator->GetAverageClusteringCoefficientsD() << " "
<< statisticsCalculator->GetAverageClusteringCoefficientsE() << " "
<< statisticsCalculator->GetAverageVertexBetweennessCentrality() << " "
<< statisticsCalculator->GetAverageEdgeBetweennessCentrality() << " "
<< statisticsCalculator->GetNumberOfIsolatedPoints() << " "
<< statisticsCalculator->GetRatioOfIsolatedPoints() << " "
<< statisticsCalculator->GetNumberOfEndPoints() << " "
<< statisticsCalculator->GetRatioOfEndPoints() << " "
<< statisticsCalculator->GetDiameter() << " "
<< statisticsCalculator->GetDiameter90() << " "
<< statisticsCalculator->GetRadius() << " "
<< statisticsCalculator->GetRadius90() << " "
<< statisticsCalculator->GetAverageEccentricity() << " "
<< statisticsCalculator->GetAverageEccentricity90() << " "
<< statisticsCalculator->GetAveragePathLength() << " "
<< statisticsCalculator->GetNumberOfCentralPoints() << " "
<< statisticsCalculator->GetRatioOfCentralPoints() << " "
<< statisticsCalculator->GetSpectralRadius() << " "
<< statisticsCalculator->GetSecondLargestEigenValue() << " "
<< statisticsCalculator->GetAdjacencyTrace() << " "
<< statisticsCalculator->GetAdjacencyEnergy() << " "
<< statisticsCalculator->GetLaplacianTrace() << " "
<< statisticsCalculator->GetLaplacianEnergy() << " "
<< statisticsCalculator->GetLaplacianSpectralGap() << " "
<< statisticsCalculator->GetNormalizedLaplacianTrace() << " "
<< statisticsCalculator->GetNormalizedLaplacianEnergy() << " "
<< statisticsCalculator->GetNormalizedLaplacianNumberOf2s() << " "
<< statisticsCalculator->GetNormalizedLaplacianNumberOf1s() << " "
<< statisticsCalculator->GetNormalizedLaplacianNumberOf0s() << " "
<< statisticsCalculator->GetNormalizedLaplacianLowerSlope() << " "
<< statisticsCalculator->GetNormalizedLaplacianUpperSlope() << " "
<< statisticsCalculator->GetSmallWorldness()
<< std::endl;
} // end global statistics
//create connectivity matrix png
if( createConnectivityMatriximage )
{
std::string connectivity_png_postfix = "_connectivity";
if( binaryConnectivity )
{
connectivity_png_postfix += "_binary";
}
else if( rescaleConnectivity )
{
connectivity_png_postfix += "_rescaled";
}
connectivity_png_postfix += ".png";
/* File format
* A png file depicting the binary connectivity matrix
*/
itk::ConnectomicsNetworkToConnectivityMatrixImageFilter::Pointer filter = itk::ConnectomicsNetworkToConnectivityMatrixImageFilter::New();
filter->SetInputNetwork( network );
filter->SetBinaryConnectivity( binaryConnectivity );
filter->SetRescaleConnectivity( rescaleConnectivity );
filter->Update();
typedef itk::ConnectomicsNetworkToConnectivityMatrixImageFilter::OutputImageType connectivityMatrixImageType;
mitk::LocaleSwitch localeSwitch("C");
itk::ImageFileWriter< connectivityMatrixImageType >::Pointer connectivityWriter = itk::ImageFileWriter< connectivityMatrixImageType >::New();
connectivityWriter->SetInput( filter->GetOutput() );
connectivityWriter->SetFileName( outName + connectivity_png_postfix);
connectivityWriter->Update();
std::cout << "Connectivity matrix image written.";
} // end create connectivity matrix png
/*
* We can either calculate local indices for specific nodes, or specific regions
*/
// Create LabelToIndex translation
std::map< std::string, int > labelToIdMap;
std::vector< mitk::ConnectomicsNetwork::NetworkNode > nodeVector = thresholdedNetwork->GetVectorOfAllNodes();
for(std::size_t loop(0); loop < nodeVector.size(); loop++)
{
labelToIdMap.insert( std::pair< std::string, int>(nodeVector.at(loop).label, nodeVector.at(loop).id) );
}
std::vector< int > degreeVector = thresholdedNetwork->GetDegreeOfNodes();
std::vector< double > ccVector = thresholdedNetwork->GetLocalClusteringCoefficients( );
std::vector< double > bcVector = thresholdedNetwork->GetNodeBetweennessVector( );
// calculate local indices
{
// only add to header for the first step of the first method
if( firstRun )
{
localHeaderStream << "Th_method " << "Th_target " << "density";
}
double density = statisticsCalculator->GetConnectionDensity();
localDataStream << "\n"
<< method << " "
<< targetValue << " "
<< density;
for(unsigned int loop(0); loop < localLabels.size(); loop++ )
{
if( network->CheckForLabel(localLabels.at( loop )) )
{
if( firstRun )
{
localHeaderStream << " "
<< localLabels.at( loop ) << "_Degree "
<< localLabels.at( loop ) << "_CC "
<< localLabels.at( loop ) << "_BC";
}
localDataStream << " " << degreeVector.at( labelToIdMap.find( localLabels.at( loop ) )->second )
<< " " << ccVector.at( labelToIdMap.find( localLabels.at( loop ) )->second )
<< " " << bcVector.at( labelToIdMap.find( localLabels.at( loop ) )->second );
}
else
{
MITK_ERROR << "Illegal label. Label: \"" << localLabels.at( loop ) << "\" not found.";
}
}
}
// calculate regional indices
{
// only add to header for the first step of the first method
if( firstRun )
{
regionalHeaderStream << "Th_method " << "Th_target " << "density";
}
double density = statisticsCalculator->GetConnectionDensity();
regionalDataStream << "\n"
<< method << " "
<< targetValue << " "
<< density;
for( parsedRegionsIterator = parsedRegions.begin(); parsedRegionsIterator != parsedRegions.end(); parsedRegionsIterator++ )
{
std::vector<std::string> regionLabelsVector = parsedRegionsIterator->second;
std::string regionName = parsedRegionsIterator->first;
double sumDegree( 0 );
double sumCC( 0 );
double sumBC( 0 );
double count( 0 );
for( std::size_t loop(0); loop < regionLabelsVector.size(); loop++ )
{
if( thresholdedNetwork->CheckForLabel(regionLabelsVector.at( loop )) )
{
sumDegree = sumDegree + degreeVector.at( labelToIdMap.find( regionLabelsVector.at( loop ) )->second );
sumCC = sumCC + ccVector.at( labelToIdMap.find( regionLabelsVector.at( loop ) )->second );
sumBC = sumBC + bcVector.at( labelToIdMap.find( regionLabelsVector.at( loop ) )->second );
count = count + 1;
}
else
{
MITK_ERROR << "Illegal label. Label: \"" << regionLabelsVector.at( loop ) << "\" not found.";
}
}
// only add to header for the first step of the first method
if( firstRun )
{
regionalHeaderStream << " " << regionName << "_LocalAverageDegree "
<< regionName << "_LocalAverageCC "
<< regionName << "_LocalAverageBC "
<< regionName << "_NumberOfNodes";
}
regionalDataStream << " " << sumDegree / count
<< " " << sumCC / count
<< " " << sumBC / count
<< " " << count;
// count number of connections and fibers between regions
std::map< std::string, std::vector<std::string> >::iterator loopRegionsIterator;
for (loopRegionsIterator = parsedRegionsIterator; loopRegionsIterator != parsedRegions.end(); loopRegionsIterator++)
{
int numberConnections(0), possibleConnections(0);
double summedFiberCount(0.0);
std::vector<std::string> loopLabelsVector = loopRegionsIterator->second;
std::string loopName = loopRegionsIterator->first;
for (std::size_t loop(0); loop < regionLabelsVector.size(); loop++)
{
if (thresholdedNetwork->CheckForLabel(regionLabelsVector.at(loop)))
{
for (std::size_t innerLoop(0); innerLoop < loopLabelsVector.size(); innerLoop++)
{
if (thresholdedNetwork->CheckForLabel(loopLabelsVector.at(loop)))
{
bool exists = thresholdedNetwork->EdgeExists(
labelToIdMap.find(regionLabelsVector.at(loop))->second,
labelToIdMap.find(loopLabelsVector.at(innerLoop))->second);
possibleConnections++;
if (exists)
{
numberConnections++;
summedFiberCount += thresholdedNetwork->GetEdge(
labelToIdMap.find(regionLabelsVector.at(loop))->second,
labelToIdMap.find(loopLabelsVector.at(innerLoop))->second).fiber_count;
}
}
else
{
MITK_ERROR << "Illegal label. Label: \"" << loopLabelsVector.at(loop) << "\" not found.";
}
}
}
else
{
MITK_ERROR << "Illegal label. Label: \"" << regionLabelsVector.at(loop) << "\" not found.";
}
}
if (firstRun)
{
regionalHeaderStream << " " << regionName << "_" << loopName << "_Connections "
<< " " << regionName << "_" << loopName << "_possibleConnections "
<< " " << regionName << "_" << loopName << "_ConnectingFibers";
}
regionalDataStream << " " << numberConnections
<< " " << possibleConnections
<< " " << summedFiberCount;
}
}
}
firstRun = false;
}
}// end calculate local averages
if( !noGlobalStatistics )
{
std::cout << "Writing to " << globalOutName;
std::ofstream glocalOutFile( globalOutName.c_str(), ios::out );
if( ! glocalOutFile.is_open() )
{
std::string errorMessage = "Could not open " + globalOutName + " for writing.";
MITK_ERROR << errorMessage;
return EXIT_FAILURE;
}
glocalOutFile << globalHeaderStream.str() << globalDataStream.str();
glocalOutFile.close();
}
if( localLabels.size() > 0 )
{
std::cout << "Writing to " << localOutName;
std::ofstream localOutFile( localOutName.c_str(), ios::out );
if( ! localOutFile.is_open() )
{
std::string errorMessage = "Could not open " + localOutName + " for writing.";
MITK_ERROR << errorMessage;
return EXIT_FAILURE;
}
localOutFile << localHeaderStream.str() << localDataStream.str();
localOutFile.close();
}
if( parsedRegions.size() > 0 )
{
std::cout << "Writing to " << regionalOutName;
std::ofstream regionalOutFile( regionalOutName.c_str(), ios::out );
if( ! regionalOutFile.is_open() )
{
std::string errorMessage = "Could not open " + regionalOutName + " for writing.";
MITK_ERROR << errorMessage;
return EXIT_FAILURE;
}
regionalOutFile << regionalHeaderStream.str() << regionalDataStream.str();
regionalOutFile.close();
}
return EXIT_SUCCESS;
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
std::cout << "DONE";
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/FiberProcessing/FiberClustering.cpp b/Modules/DiffusionCmdApps/FiberProcessing/FiberClustering.cpp
index d2c7261..743207b 100644
--- a/Modules/DiffusionCmdApps/FiberProcessing/FiberClustering.cpp
+++ b/Modules/DiffusionCmdApps/FiberProcessing/FiberClustering.cpp
@@ -1,273 +1,273 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkFiberBundle.h>
#include <mitkDiffusionCommandLineParser.h>
#include <mitkLexicalCast.h>
#include <mitkIOUtil.h>
#include <itkTractClusteringFilter.h>
#include <mitkClusteringMetricEuclideanMean.h>
#include <mitkClusteringMetricEuclideanMax.h>
#include <mitkClusteringMetricEuclideanStd.h>
#include <mitkClusteringMetricAnatomic.h>
#include <mitkClusteringMetricScalarMap.h>
#include <mitkClusteringMetricInnerAngles.h>
#include <mitkClusteringMetricLength.h>
#include <itksys/SystemTools.hxx>
typedef itksys::SystemTools ist;
mitk::FiberBundle::Pointer LoadFib(std::string filename)
{
std::vector<mitk::BaseData::Pointer> fibInfile = mitk::IOUtil::Load(filename);
if( fibInfile.empty() )
std::cout << "File " << filename << " could not be read!";
mitk::BaseData::Pointer baseData = fibInfile.at(0);
return dynamic_cast<mitk::FiberBundle*>(baseData.GetPointer());
}
/*!
\brief Spatially cluster fibers
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Fiber Clustering");
parser.setCategory("Fiber Processing");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "input fiber bundle (.fib; .trk; .tck)", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output root", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("cluster_size", "", mitkDiffusionCommandLineParser::Int, "Cluster size:", "", 10);
parser.addArgument("fiber_points", "", mitkDiffusionCommandLineParser::Int, "Fiber points:", "", 12);
parser.addArgument("min_fibers", "", mitkDiffusionCommandLineParser::Int, "Min. fibers per cluster:", "", 1);
parser.addArgument("max_clusters", "", mitkDiffusionCommandLineParser::Int, "Max. clusters:", "");
parser.addArgument("merge_clusters", "", mitkDiffusionCommandLineParser::Float, "Merge clusters:", "Set to 0 to avoid merging and to -1 to use the original cluster size", -1.0);
parser.addArgument("output_centroids", "", mitkDiffusionCommandLineParser::Bool, "Output centroids:", "");
parser.addArgument("only_centroids", "", mitkDiffusionCommandLineParser::Bool, "Output only centroids:", "");
parser.addArgument("merge_centroids", "", mitkDiffusionCommandLineParser::Bool, "Merge centroids:", "");
parser.addArgument("metrics", "", mitkDiffusionCommandLineParser::StringList, "Metrics:", "EU_MEAN; EU_STD; EU_MAX; ANAT; MAP; LENGTH", std::string("EU_MEAN"));
parser.addArgument("metric_weights", "", mitkDiffusionCommandLineParser::StringList, "Metric weights:", "add one float weight for each used metric");
parser.addArgument("input_centroids", "", mitkDiffusionCommandLineParser::String, "Input centroids:", "", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("scalar_map", "", mitkDiffusionCommandLineParser::String, "Scalar map:", "", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("parcellation", "", mitkDiffusionCommandLineParser::String, "Parcellation:", "", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("file_ending", "", mitkDiffusionCommandLineParser::String, "File ending:", "");
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
std::string inFileName = us::any_cast<std::string>(parsedArgs["i"]);
std::string out_root = us::any_cast<std::string>(parsedArgs["o"]);
bool only_centroids = false;
if (parsedArgs.count("only_centroids"))
only_centroids = us::any_cast<bool>(parsedArgs["only_centroids"]);
bool merge_centroids = false;
if (parsedArgs.count("merge_centroids"))
merge_centroids = us::any_cast<bool>(parsedArgs["merge_centroids"]);
int cluster_size = 10;
if (parsedArgs.count("cluster_size"))
cluster_size = us::any_cast<int>(parsedArgs["cluster_size"]);
int fiber_points = 12;
if (parsedArgs.count("fiber_points"))
fiber_points = us::any_cast<int>(parsedArgs["fiber_points"]);
int min_fibers = 1;
if (parsedArgs.count("min_fibers"))
min_fibers = us::any_cast<int>(parsedArgs["min_fibers"]);
int max_clusters = 0;
if (parsedArgs.count("max_clusters"))
max_clusters = us::any_cast<int>(parsedArgs["max_clusters"]);
float merge_clusters = -1.0;
if (parsedArgs.count("merge_clusters"))
merge_clusters = us::any_cast<float>(parsedArgs["merge_clusters"]);
bool output_centroids = false;
if (parsedArgs.count("output_centroids"))
output_centroids = us::any_cast<bool>(parsedArgs["output_centroids"]);
std::vector< std::string > metric_strings = {"EU_MEAN"};
if (parsedArgs.count("metrics"))
metric_strings = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["metrics"]);
std::vector< std::string > metric_weights = {"1.0"};
if (parsedArgs.count("metric_weights"))
metric_weights = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["metric_weights"]);
std::string input_centroids = "";
if (parsedArgs.count("input_centroids"))
input_centroids = us::any_cast<std::string>(parsedArgs["input_centroids"]);
std::string scalar_map = "";
if (parsedArgs.count("scalar_map"))
scalar_map = us::any_cast<std::string>(parsedArgs["scalar_map"]);
std::string parcellation = "";
if (parsedArgs.count("parcellation"))
parcellation = us::any_cast<std::string>(parsedArgs["parcellation"]);
std::string file_ending = ".fib";
if (parsedArgs.count("file_ending"))
file_ending = us::any_cast<std::string>(parsedArgs["file_ending"]);
if (metric_strings.size()!=metric_weights.size())
{
MITK_INFO << "Each metric needs an associated metric weight!";
return EXIT_FAILURE;
}
try
{
typedef itk::Image< float, 3 > FloatImageType;
typedef itk::Image< short, 3 > ShortImageType;
mitk::FiberBundle::Pointer fib = LoadFib(inFileName);
float max_d = 0;
int i=1;
std::vector< float > distances;
while (max_d < fib->GetGeometry()->GetDiagonalLength()/2)
{
distances.push_back(cluster_size*i);
max_d = cluster_size*i;
++i;
}
itk::TractClusteringFilter::Pointer clusterer = itk::TractClusteringFilter::New();
clusterer->SetDistances(distances);
clusterer->SetTractogram(fib);
if (input_centroids!="")
{
mitk::FiberBundle::Pointer in_centroids = LoadFib(input_centroids);
clusterer->SetInCentroids(in_centroids);
}
std::vector< mitk::ClusteringMetric* > metrics;
int mc = 0;
for (auto m : metric_strings)
{
float w = boost::lexical_cast<float>(metric_weights.at(mc));
MITK_INFO << "Metric: " << m << " (w=" << w << ")";
if (m=="EU_MEAN")
metrics.push_back({new mitk::ClusteringMetricEuclideanMean()});
else if (m=="EU_STD")
metrics.push_back({new mitk::ClusteringMetricEuclideanStd()});
else if (m=="EU_MAX")
metrics.push_back({new mitk::ClusteringMetricEuclideanMax()});
else if (m=="ANGLES")
metrics.push_back({new mitk::ClusteringMetricInnerAngles()});
else if (m=="LENGTH")
metrics.push_back({new mitk::ClusteringMetricLength()});
else if (m=="MAP" && scalar_map!="")
{
mitk::Image::Pointer mitk_map = mitk::IOUtil::Load<mitk::Image>(scalar_map);
if (mitk_map->GetDimension()==3)
{
FloatImageType::Pointer itk_map = FloatImageType::New();
mitk::CastToItkImage(mitk_map, itk_map);
mitk::ClusteringMetricScalarMap* metric = new mitk::ClusteringMetricScalarMap();
metric->SetImages({itk_map});
metric->SetScale(distances.at(0));
metrics.push_back(metric);
}
}
else if (m=="ANAT" && parcellation!="")
{
mitk::Image::Pointer mitk_map = mitk::IOUtil::Load<mitk::Image>(parcellation);
if (mitk_map->GetDimension()==3)
{
ShortImageType::Pointer itk_map = ShortImageType::New();
mitk::CastToItkImage(mitk_map, itk_map);
mitk::ClusteringMetricAnatomic* metric = new mitk::ClusteringMetricAnatomic();
metric->SetParcellations({itk_map});
metrics.push_back(metric);
}
}
metrics.back()->SetScale(w);
mc++;
}
if (metrics.empty())
{
MITK_INFO << "No metric selected!";
return EXIT_FAILURE;
}
clusterer->SetMetrics(metrics);
clusterer->SetMergeDuplicateThreshold(merge_clusters);
clusterer->SetNumPoints(fiber_points);
clusterer->SetMaxClusters(max_clusters);
clusterer->SetMinClusterSize(min_fibers);
clusterer->Update();
std::vector<mitk::FiberBundle::Pointer> tracts = clusterer->GetOutTractograms();
std::vector<mitk::FiberBundle::Pointer> centroids = clusterer->GetOutCentroids();
MITK_INFO << "Saving clusters";
std::streambuf *old = cout.rdbuf(); // <-- save
std::stringstream ss;
std::cout.rdbuf (ss.rdbuf()); // <-- redirect
if (!only_centroids)
for (unsigned int i=0; i<tracts.size(); ++i)
mitk::IOUtil::Save(tracts.at(i), out_root + "Cluster_" + boost::lexical_cast<std::string>(i) + file_ending);
if (output_centroids && !merge_centroids)
{
for (unsigned int i=0; i<centroids.size(); ++i)
mitk::IOUtil::Save(centroids.at(i), out_root + "Centroid_" + boost::lexical_cast<std::string>(i) + file_ending);
}
else if (output_centroids)
{
mitk::FiberBundle::Pointer centroid = mitk::FiberBundle::New();
centroid = centroid->AddBundles(centroids);
mitk::IOUtil::Save(centroid, out_root + ist::GetFilenameWithoutExtension(inFileName) + "_Centroids" + file_ending);
}
std::cout.rdbuf (old); // <-- restore
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/FiberProcessing/FiberDirectionExtraction.cpp b/Modules/DiffusionCmdApps/FiberProcessing/FiberDirectionExtraction.cpp
index ef34ea7..de5f1b7 100644
--- a/Modules/DiffusionCmdApps/FiberProcessing/FiberDirectionExtraction.cpp
+++ b/Modules/DiffusionCmdApps/FiberProcessing/FiberDirectionExtraction.cpp
@@ -1,183 +1,183 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkBaseData.h>
#include <mitkImageCast.h>
#include <mitkImageToItk.h>
#include <metaCommand.h>
#include "mitkDiffusionCommandLineParser.h"
#include <usAny.h>
#include <itkImageFileWriter.h>
#include <mitkIOUtil.h>
#include <mitkLexicalCast.h>
#include <itkEvaluateDirectionImagesFilter.h>
#include <itkTractsToVectorImageFilter.h>
#include <mitkCoreObjectFactory.h>
#include <mitkLocaleSwitch.h>
/*!
\brief Extract principal fiber directions from a tractogram
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Fiber Direction Extraction");
parser.setCategory("Fiber Tracking and Processing Methods");
parser.setDescription("Extract principal fiber directions from a tractogram");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "input tractogram (.fib/.trk)", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output root", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("mask", "", mitkDiffusionCommandLineParser::String, "Mask:", "mask image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("athresh", "", mitkDiffusionCommandLineParser::Float, "Angular threshold:", "angular threshold in degrees. closer fiber directions are regarded as one direction and clustered together.", 25, true);
parser.addArgument("peakthresh", "", mitkDiffusionCommandLineParser::Float, "Peak size threshold:", "peak size threshold relative to largest peak in voxel", 0.2, true);
parser.addArgument("only_mask_geometry", "", mitkDiffusionCommandLineParser::Bool, "Only mask geometry:", "don't use content of mask image, only use it's geometry", false);
parser.addArgument("verbose", "", mitkDiffusionCommandLineParser::Bool, "Verbose:", "output optional and intermediate calculation results");
parser.addArgument("numdirs", "", mitkDiffusionCommandLineParser::Int, "Max. num. directions:", "maximum number of fibers per voxel", 3, true);
parser.addArgument("normalization", "", mitkDiffusionCommandLineParser::Int, "Normalization method:", "1=global maximum; 2=single vector; 3=voxel-wise maximum", 1);
parser.addArgument("file_ending", "", mitkDiffusionCommandLineParser::String, "Image type:", ".nrrd; .nii; .nii.gz", std::string(".nii.gz"));
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
std::string fibFile = us::any_cast<std::string>(parsedArgs["i"]);
std::string maskImage("");
if (parsedArgs.count("mask"))
maskImage = us::any_cast<std::string>(parsedArgs["mask"]);
float peakThreshold = 0.2;
if (parsedArgs.count("peakthresh"))
peakThreshold = us::any_cast<float>(parsedArgs["peakthresh"]);
float angularThreshold = 25;
if (parsedArgs.count("athresh"))
angularThreshold = us::any_cast<float>(parsedArgs["athresh"]);
std::string outRoot = us::any_cast<std::string>(parsedArgs["o"]);
bool verbose = false;
if (parsedArgs.count("verbose"))
verbose = us::any_cast<bool>(parsedArgs["verbose"]);
bool only_mask_geometry = false;
if (parsedArgs.count("only_mask_geometry"))
only_mask_geometry = us::any_cast<bool>(parsedArgs["only_mask_geometry"]);
int maxNumDirs = 3;
if (parsedArgs.count("numdirs"))
maxNumDirs = us::any_cast<int>(parsedArgs["numdirs"]);
int normalization = 1;
if (parsedArgs.count("normalization"))
normalization = us::any_cast<int>(parsedArgs["normalization"]);
std::string file_ending = ".nii.gz";
if (parsedArgs.count("file_ending"))
file_ending = us::any_cast<std::string>(parsedArgs["file_ending"]);
try
{
typedef itk::Image<unsigned char, 3> ItkUcharImgType;
// load fiber bundle
mitk::FiberBundle::Pointer inputTractogram = mitk::IOUtil::Load<mitk::FiberBundle>(fibFile);
// load/create mask image
ItkUcharImgType::Pointer itkMaskImage = nullptr;
if (maskImage.compare("")!=0)
{
std::cout << "Using mask image";
itkMaskImage = ItkUcharImgType::New();
mitk::Image::Pointer mitkMaskImage = mitk::IOUtil::Load<mitk::Image>(maskImage);
mitk::CastToItkImage(mitkMaskImage, itkMaskImage);
}
// extract directions from fiber bundle
itk::TractsToVectorImageFilter<float>::Pointer fOdfFilter = itk::TractsToVectorImageFilter<float>::New();
fOdfFilter->SetFiberBundle(inputTractogram);
fOdfFilter->SetOnlyUseMaskGeometry(only_mask_geometry);
fOdfFilter->SetMaskImage(itkMaskImage);
fOdfFilter->SetAngularThreshold(cos(angularThreshold*itk::Math::pi/180));
switch (normalization)
{
case 1:
fOdfFilter->SetNormalizationMethod(itk::TractsToVectorImageFilter<float>::NormalizationMethods::GLOBAL_MAX);
break;
case 2:
fOdfFilter->SetNormalizationMethod(itk::TractsToVectorImageFilter<float>::NormalizationMethods::SINGLE_VEC_NORM);
break;
case 3:
fOdfFilter->SetNormalizationMethod(itk::TractsToVectorImageFilter<float>::NormalizationMethods::MAX_VEC_NORM);
break;
}
fOdfFilter->SetSizeThreshold(peakThreshold);
fOdfFilter->SetMaxNumDirections(maxNumDirs);
fOdfFilter->Update();
mitk::LocaleSwitch localeSwitch("C");
{
itk::TractsToVectorImageFilter<float>::ItkDirectionImageType::Pointer itkImg = fOdfFilter->GetDirectionImage();
typedef itk::ImageFileWriter< itk::TractsToVectorImageFilter<float>::ItkDirectionImageType > WriterType;
WriterType::Pointer writer = WriterType::New();
std::string outfilename = outRoot;
outfilename.append("_DIRECTIONS");
outfilename.append(file_ending);
writer->SetFileName(outfilename.c_str());
writer->SetInput(itkImg);
writer->Update();
}
if (verbose)
{
// write num direction image
ItkUcharImgType::Pointer numDirImage = fOdfFilter->GetNumDirectionsImage();
typedef itk::ImageFileWriter< ItkUcharImgType > WriterType;
WriterType::Pointer writer = WriterType::New();
std::string outfilename = outRoot;
outfilename.append("_NUM_DIRECTIONS");
outfilename.append(file_ending);
writer->SetFileName(outfilename.c_str());
writer->SetInput(numDirImage);
writer->Update();
}
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/FiberProcessing/FiberExtraction.cpp b/Modules/DiffusionCmdApps/FiberProcessing/FiberExtraction.cpp
index 5ff5d81..8a15873 100644
--- a/Modules/DiffusionCmdApps/FiberProcessing/FiberExtraction.cpp
+++ b/Modules/DiffusionCmdApps/FiberProcessing/FiberExtraction.cpp
@@ -1,151 +1,151 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <metaCommand.h>
#include "mitkDiffusionCommandLineParser.h"
#include <usAny.h>
#include <mitkIOUtil.h>
#include <mitkLexicalCast.h>
#include <mitkCoreObjectFactory.h>
#include <mitkPlanarFigure.h>
#include <mitkPlanarFigureComposite.h>
#include <mitkFiberBundle.h>
#include <mitkImageCast.h>
#include <mitkImageToItk.h>
#include <mitkStandaloneDataStorage.h>
#define _USE_MATH_DEFINES
#include <math.h>
/*!
\brief Extract fibers from a tractogram using planar figure ROIs
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Fiber Extraction");
parser.setCategory("Fiber Tracking and Processing Methods");
parser.setContributor("MIC");
parser.setDescription("Extract fibers from a tractogram using planar figure ROIs");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "input tractogram (.fib/.trk)", us::Any(), false);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output tractogram", us::Any(), false);
parser.addArgument("planfirgure1", "pf1", mitkDiffusionCommandLineParser::String, "Figure 1:", "first planar figure ROI", us::Any(), false);
parser.addArgument("planfirgure2", "pf2", mitkDiffusionCommandLineParser::String, "Figure 2:", "second planar figure ROI", us::Any());
parser.addArgument("operation", "op", mitkDiffusionCommandLineParser::String, "Operation:", "logical operation (AND; OR; NOT)", us::Any());
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
std::string inFib = us::any_cast<std::string>(parsedArgs["i"]);
std::string outFib = us::any_cast<std::string>(parsedArgs["o"]);
std::string pf1_path = us::any_cast<std::string>(parsedArgs["planfirgure1"]);
std::string operation("");
std::string pf2_path("");
if (parsedArgs.count("operation"))
{
operation = us::any_cast<std::string>(parsedArgs["operation"]);
if (parsedArgs.count("planfirgure2") && (operation=="AND" || operation=="OR"))
pf2_path = us::any_cast<std::string>(parsedArgs["planfirgure2"]);
}
try
{
// load fiber bundle
mitk::FiberBundle::Pointer inputTractogram = mitk::IOUtil::Load<mitk::FiberBundle>(inFib);
mitk::FiberBundle::Pointer result;
mitk::StandaloneDataStorage::Pointer storage = mitk::StandaloneDataStorage::New();
auto data = mitk::IOUtil::Load(pf1_path)[0];
auto input1 = mitk::DataNode::New();
input1->SetData(data);
if (input1.IsNotNull())
{
mitk::PlanarFigureComposite::Pointer pfc = mitk::PlanarFigureComposite::New();
mitk::DataNode::Pointer pfcNode = mitk::DataNode::New();
pfcNode->SetData(pfc);
mitk::DataStorage::SetOfObjects::Pointer set1 = mitk::DataStorage::SetOfObjects::New();
set1->push_back(pfcNode);
storage->Add(pfcNode);
auto input2 = mitk::DataNode::New();
if (!pf2_path.empty())
{
data = mitk::IOUtil::Load(pf2_path)[0];
input2->SetData(data);
}
if (operation.empty())
{
result = inputTractogram->ExtractFiberSubset(input1, nullptr);
}
else if (operation=="NOT")
{
pfc->setOperationType(mitk::PlanarFigureComposite::NOT);
storage->Add(input1, set1);
result = inputTractogram->ExtractFiberSubset(pfcNode, storage);
}
else if (operation=="AND" && input2.IsNotNull())
{
pfc->setOperationType(mitk::PlanarFigureComposite::AND);
storage->Add(input1, set1);
storage->Add(input2, set1);
result = inputTractogram->ExtractFiberSubset(pfcNode, storage);
}
else if (operation=="OR" && input2.IsNotNull())
{
pfc->setOperationType(mitk::PlanarFigureComposite::OR);
storage->Add(input1, set1);
storage->Add(input2, set1);
result = inputTractogram->ExtractFiberSubset(pfcNode, storage);
}
else
{
std::cout << "Could not process input:";
std::cout << pf1_path;
std::cout << pf2_path;
std::cout << operation;
}
}
if (result.IsNotNull())
mitk::IOUtil::Save(result, outFib);
else
std::cout << "No valid fiber bundle extracted.";
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/FiberProcessing/FiberExtractionRoi.cpp b/Modules/DiffusionCmdApps/FiberProcessing/FiberExtractionRoi.cpp
index 526c335..3c7740f 100644
--- a/Modules/DiffusionCmdApps/FiberProcessing/FiberExtractionRoi.cpp
+++ b/Modules/DiffusionCmdApps/FiberProcessing/FiberExtractionRoi.cpp
@@ -1,276 +1,276 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <metaCommand.h>
#include "mitkDiffusionCommandLineParser.h"
#include <usAny.h>
#include <mitkIOUtil.h>
#include <mitkLexicalCast.h>
#include <mitkCoreObjectFactory.h>
#include <mitkPlanarFigure.h>
#include <mitkPlanarFigureComposite.h>
#include <mitkFiberBundle.h>
#include <mitkImageCast.h>
#include <mitkImageToItk.h>
#include <mitkStandaloneDataStorage.h>
#include <itksys/SystemTools.hxx>
#include <itkFiberExtractionFilter.h>
#define _USE_MATH_DEFINES
#include <math.h>
typedef itksys::SystemTools ist;
typedef itk::Image<float, 3> ItkFloatImgType;
ItkFloatImgType::Pointer LoadItkImage(const std::string& filename)
{
mitk::Image::Pointer img = mitk::IOUtil::Load<mitk::Image>(filename);
ItkFloatImgType::Pointer itk_image = ItkFloatImgType::New();
mitk::CastToItkImage(img, itk_image);
return itk_image;
}
/*!
\brief Extract fibers from a tractogram using binary image ROIs
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Fiber Extraction With ROI Image");
parser.setCategory("Fiber Tracking and Processing Methods");
parser.setContributor("MIC");
parser.setDescription("Extract fibers from a tractogram using binary image ROIs");
parser.setArgumentPrefix("--", "-");
parser.beginGroup("1. Mandatory arguments:");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "input tractogram (.fib/.trk/.tck/.dcm)", us::Any(), false);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output root", us::Any(), false);
parser.addArgument("rois", "", mitkDiffusionCommandLineParser::StringList, "ROI images:", "ROI images", us::Any(), false);
parser.endGroup();
parser.beginGroup("2. Label based extraction:");
parser.addArgument("split_labels", "", mitkDiffusionCommandLineParser::Bool, "Split labels:", "output a separate tractogram for each label-->label tract", false);
parser.addArgument("skip_self_connections", "", mitkDiffusionCommandLineParser::Bool, "Skip self connections:", "ignore streamlines between two identical labels", false);
parser.addArgument("all_labels", "", mitkDiffusionCommandLineParser::Bool, "All labels:", "use all labels (0 is excluded)", false);
parser.addArgument("labels", "", mitkDiffusionCommandLineParser::StringList, "Labels:", "positive means roi image value in labels vector", us::Any());
parser.addArgument("start_labels", "", mitkDiffusionCommandLineParser::StringList, "Start Labels:", "use separate start and end labels instead of one mixed set", us::Any());
parser.addArgument("end_labels", "", mitkDiffusionCommandLineParser::StringList, "End Labels:", "use separate start and end labels instead of one mixed set", us::Any());
parser.addArgument("paired", "", mitkDiffusionCommandLineParser::Bool, "Paired:", "start and end label list are paired", false);
parser.endGroup();
parser.beginGroup("3. Misc:");
parser.addArgument("both_ends", "", mitkDiffusionCommandLineParser::Bool, "Both ends:", "Fibers are extracted if both endpoints are located in the ROI.", false);
parser.addArgument("overlap_fraction", "", mitkDiffusionCommandLineParser::Float, "Overlap fraction:", "Extract by overlap, not by endpoints. Extract fibers that overlap to at least the provided factor (0-1) with the ROI.", -1);
parser.addArgument("invert", "", mitkDiffusionCommandLineParser::Bool, "Invert:", "get streamlines not positive for any of the ROI images", false);
parser.addArgument("output_negatives", "", mitkDiffusionCommandLineParser::Bool, "Negatives:", "output negatives", false);
parser.addArgument("interpolate", "", mitkDiffusionCommandLineParser::Bool, "Interpolate:", "interpolate ROI images (only for endpoint based extraction)", false);
parser.addArgument("threshold", "", mitkDiffusionCommandLineParser::Float, "Threshold:", "positive means ROI image value threshold", 0.5);
parser.addArgument("min_fibers", "", mitkDiffusionCommandLineParser::Int, "Min. num. fibers:", "discard positive tracts with less fibers", 0);
parser.addArgument("split_rois", "", mitkDiffusionCommandLineParser::Bool, "Split ROIs:", "output a separate tractogram for each ROI", false);
parser.endGroup();
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
std::string inFib = us::any_cast<std::string>(parsedArgs["i"]);
std::string outFib = us::any_cast<std::string>(parsedArgs["o"]);
mitkDiffusionCommandLineParser::StringContainerType roi_files = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["rois"]);
bool both_ends = false;
if (parsedArgs.count("both_ends"))
both_ends = us::any_cast<bool>(parsedArgs["both_ends"]);
bool invert = false;
if (parsedArgs.count("invert"))
invert = us::any_cast<bool>(parsedArgs["invert"]);
unsigned int min_fibers = 0;
if (parsedArgs.count("min_fibers"))
min_fibers = us::any_cast<int>(parsedArgs["min_fibers"]);
bool all_labels = false;
if (parsedArgs.count("all_labels"))
all_labels = us::any_cast<bool>(parsedArgs["all_labels"]);
bool split_labels = false;
if (parsedArgs.count("split_labels"))
split_labels = us::any_cast<bool>(parsedArgs["split_labels"]);
bool split_rois = false;
if (parsedArgs.count("split_rois"))
split_rois = us::any_cast<bool>(parsedArgs["split_rois"]);
bool skip_self_connections = false;
if (parsedArgs.count("skip_self_connections"))
skip_self_connections = us::any_cast<bool>(parsedArgs["skip_self_connections"]);
bool output_negatives = false;
if (parsedArgs.count("output_negatives"))
output_negatives = us::any_cast<bool>(parsedArgs["output_negatives"]);
float overlap_fraction = -1;
if (parsedArgs.count("overlap_fraction"))
overlap_fraction = us::any_cast<float>(parsedArgs["overlap_fraction"]);
bool any_point = false;
if (overlap_fraction>=0)
any_point = true;
bool interpolate = false;
if (parsedArgs.count("interpolate"))
interpolate = us::any_cast<bool>(parsedArgs["interpolate"]);
float threshold = 0.5;
if (parsedArgs.count("threshold"))
threshold = us::any_cast<float>(parsedArgs["threshold"]);
mitkDiffusionCommandLineParser::StringContainerType labels;
if (parsedArgs.count("labels"))
labels = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["labels"]);
mitkDiffusionCommandLineParser::StringContainerType start_labels;
if (parsedArgs.count("start_labels"))
start_labels = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["start_labels"]);
mitkDiffusionCommandLineParser::StringContainerType end_labels;
if (parsedArgs.count("end_labels"))
end_labels = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["end_labels"]);
bool paired = false;
if (parsedArgs.count("paired"))
paired = us::any_cast<bool>(parsedArgs["paired"]);
try
{
// load fiber bundle
mitk::FiberBundle::Pointer inputTractogram = mitk::IOUtil::Load<mitk::FiberBundle>(inFib);
std::streambuf *old = cout.rdbuf(); // <-- save
std::stringstream ss;
std::cout.rdbuf (ss.rdbuf()); // <-- redirect
std::vector< ItkFloatImgType::Pointer > roi_images;
std::vector< std::string > roi_names;
for (std::size_t i=0; i<roi_files.size(); ++i)
{
roi_images.push_back( LoadItkImage(roi_files.at(i)) );
roi_names.push_back(itksys::SystemTools::GetFilenameWithoutExtension(roi_files.at(i)));
}
std::cout.rdbuf (old); // <-- restore
MITK_INFO << "Loaded " << roi_images.size() << " ROI images.";
std::vector< ItkFloatImgType* > roi_images2;
for (auto roi : roi_images)
roi_images2.push_back(roi);
std::vector< unsigned short > short_labels;
for (auto l : labels)
short_labels.push_back(boost::lexical_cast<unsigned short>(l));
std::vector< unsigned short > short_start_labels;
for (auto l : start_labels)
short_start_labels.push_back(boost::lexical_cast<unsigned short>(l));
std::vector< unsigned short > short_end_labels;
for (auto l : end_labels)
short_end_labels.push_back(boost::lexical_cast<unsigned short>(l));
itk::FiberExtractionFilter<float>::Pointer extractor = itk::FiberExtractionFilter<float>::New();
extractor->SetInputFiberBundle(inputTractogram);
extractor->SetRoiImages(roi_images2);
extractor->SetRoiImageNames(roi_names);
extractor->SetOverlapFraction(overlap_fraction);
extractor->SetBothEnds(both_ends);
extractor->SetInterpolate(interpolate);
extractor->SetThreshold(threshold);
extractor->SetLabels(short_labels);
extractor->SetStartLabels(short_start_labels);
extractor->SetEndLabels(short_end_labels);
extractor->SetSplitLabels(split_labels);
extractor->SetSplitByRoi(split_rois);
extractor->SetMinFibersPerTract(min_fibers);
extractor->SetSkipSelfConnections(skip_self_connections);
extractor->SetPairedStartEndLabels(paired);
if (!any_point)
extractor->SetMode(itk::FiberExtractionFilter<float>::MODE::ENDPOINTS);
if (all_labels || short_labels.size()>0 || short_start_labels.size()>0 || short_end_labels.size()>0)
extractor->SetInputType(itk::FiberExtractionFilter<float>::INPUT::LABEL_MAP);
extractor->Update();
std::string ext = itksys::SystemTools::GetFilenameExtension(outFib);
if (ext.empty())
ext = ".trk";
outFib = itksys::SystemTools::GetFilenamePath(outFib) + '/' + itksys::SystemTools::GetFilenameWithoutExtension(outFib);
if (invert)
mitk::IOUtil::Save(extractor->GetNegatives().at(0), outFib + ext);
else
{
int c = 0;
std::vector< std::string > positive_labels = extractor->GetPositiveLabels();
for (auto fib : extractor->GetPositives())
{
std::string l = positive_labels.at(c);
if (l.size()>0)
mitk::IOUtil::Save(fib, outFib + "_" + l + ext);
else
mitk::IOUtil::Save(fib, outFib + ext);
++c;
}
}
if (output_negatives)
{
invert = !invert;
if (invert)
mitk::IOUtil::Save(extractor->GetNegatives().at(0), outFib + "_negatives" + ext);
else
{
int c = 0;
std::vector< std::string > positive_labels = extractor->GetPositiveLabels();
for (auto fib : extractor->GetPositives())
{
std::string l = positive_labels.at(c);
if (l.size()>0)
mitk::IOUtil::Save(fib, outFib + "_" + l + "_negatives" + ext);
else
mitk::IOUtil::Save(fib, outFib + "_negatives" + ext);
++c;
}
}
}
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/FiberProcessing/FiberJoin.cpp b/Modules/DiffusionCmdApps/FiberProcessing/FiberJoin.cpp
index 725fb33..534dcd7 100644
--- a/Modules/DiffusionCmdApps/FiberProcessing/FiberJoin.cpp
+++ b/Modules/DiffusionCmdApps/FiberProcessing/FiberJoin.cpp
@@ -1,100 +1,100 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkIOUtil.h>
#include <metaCommand.h>
#include "mitkDiffusionCommandLineParser.h"
#include <usAny.h>
#include <mitkIOUtil.h>
#include <mitkLexicalCast.h>
#include <mitkCoreObjectFactory.h>
#include <mitkPlanarFigure.h>
#include <mitkPlanarFigureComposite.h>
#include <mitkFiberBundle.h>
#define _USE_MATH_DEFINES
#include <math.h>
mitk::FiberBundle::Pointer LoadFib(std::string filename)
{
std::vector<mitk::BaseData::Pointer> fibInfile = mitk::IOUtil::Load(filename);
if( fibInfile.empty() )
std::cout << "File " << filename << " could not be read!";
mitk::BaseData::Pointer baseData = fibInfile.at(0);
return dynamic_cast<mitk::FiberBundle*>(baseData.GetPointer());
}
/*!
\brief Join multiple tractograms
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Fiber Join");
parser.setCategory("Fiber Tracking and Processing Methods");
parser.setContributor("MIC");
parser.setDescription("Join multiple tractograms");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::StringList, "Input:", "input tractograms", us::Any(), false);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output tractogram", us::Any(), false);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
mitkDiffusionCommandLineParser::StringContainerType inFibs = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["i"]);
std::string outFib = us::any_cast<std::string>(parsedArgs["o"]);
if (inFibs.size()<=1)
{
std::cout << "More than one input tractogram required!";
return EXIT_FAILURE;
}
try
{
std::vector< mitk::FiberBundle::Pointer > tractograms;
mitk::FiberBundle::Pointer result = LoadFib(inFibs.at(0));
for (std::size_t i=1; i<inFibs.size(); ++i)
{
try
{
tractograms.push_back(LoadFib(inFibs.at(i)));
}
catch(...){ std::cout << "could not load: " << inFibs.at(i); }
}
result = result->AddBundles(tractograms);
mitk::IOUtil::Save(result, outFib);
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/FiberProcessing/FiberProcessing.cpp b/Modules/DiffusionCmdApps/FiberProcessing/FiberProcessing.cpp
index 586fb52..061f031 100644
--- a/Modules/DiffusionCmdApps/FiberProcessing/FiberProcessing.cpp
+++ b/Modules/DiffusionCmdApps/FiberProcessing/FiberProcessing.cpp
@@ -1,301 +1,301 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <vector>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <itkImageFileWriter.h>
#include <itkMetaDataObject.h>
#include <itkVectorImage.h>
#include <mitkBaseData.h>
#include <mitkFiberBundle.h>
#include "mitkDiffusionCommandLineParser.h"
#include <mitkLexicalCast.h>
#include <mitkCoreObjectFactory.h>
#include <mitkIOUtil.h>
#include <itkFiberCurvatureFilter.h>
#include <mitkDiffusionDataIOHelper.h>
#include <itkImage.h>
mitk::FiberBundle::Pointer LoadFib(std::string filename)
{
std::vector<mitk::BaseData::Pointer> fibInfile = mitk::IOUtil::Load(filename);
if( fibInfile.empty() )
std::cout << "File " << filename << " could not be read!";
mitk::BaseData::Pointer baseData = fibInfile.at(0);
return dynamic_cast<mitk::FiberBundle*>(baseData.GetPointer());
}
/*!
\brief Modify input tractogram: fiber resampling, compression, pruning and transformation.
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Fiber Processing");
parser.setCategory("Fiber Tracking and Processing Methods");
parser.setDescription("Modify input tractogram: fiber resampling, compression, pruning and transformation.");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.beginGroup("1. Mandatory arguments:");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "Input fiber bundle (.fib, .trk, .tck)", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "Output fiber bundle (.fib, .trk)", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.endGroup();
parser.beginGroup("2. Resampling:");
parser.addArgument("spline_resampling", "", mitkDiffusionCommandLineParser::Float, "Spline resampling:", "Resample fiber using splines with the given point distance (in mm)");
parser.addArgument("linear_resampling", "", mitkDiffusionCommandLineParser::Float, "Linear resampling:", "Resample fiber linearly with the given point distance (in mm)");
parser.addArgument("num_resampling", "", mitkDiffusionCommandLineParser::Int, "Num. fiber points resampling:", "Resample all fibers to the given number of points");
parser.addArgument("compress", "", mitkDiffusionCommandLineParser::Float, "Compress:", "Compress fiber using the given error threshold (in mm)");
parser.endGroup();
parser.beginGroup("3. Filtering:");
parser.addArgument("min_length", "", mitkDiffusionCommandLineParser::Float, "Minimum length:", "Minimum fiber length (in mm)");
parser.addArgument("max_length", "", mitkDiffusionCommandLineParser::Float, "Maximum length:", "Maximum fiber length (in mm)");
parser.addArgument("max_angle", "", mitkDiffusionCommandLineParser::Float, "Maximum angle:", "Maximum angular STDEV (in degree) over given distance");
parser.addArgument("max_angle_dist", "", mitkDiffusionCommandLineParser::Float, "Distance:", "Distance in mm", 10);
parser.addArgument("remove", "", mitkDiffusionCommandLineParser::Bool, "Remove fibers exceeding curvature threshold:", "If false, only the high curvature parts are removed");
parser.addArgument("subsample", "", mitkDiffusionCommandLineParser::Float, "Randomly select fraction of streamlines:", "Randomly select the specified fraction of streamlines from the input tractogram");
parser.addArgument("random_subsample", "", mitkDiffusionCommandLineParser::Bool, "Randomly seed subsampling:", "Randomly seed subsampling. Else, use seed 0.");
parser.endGroup();
parser.beginGroup("4. Transformation:");
parser.addArgument("mirror", "", mitkDiffusionCommandLineParser::Int, "Invert coordinates:", "Invert fiber coordinates XYZ (e.g. 010 to invert y-coordinate of each fiber point)");
parser.addArgument("rotate_x", "", mitkDiffusionCommandLineParser::Float, "Rotate x-axis:", "Rotate around x-axis (in deg)");
parser.addArgument("rotate_y", "", mitkDiffusionCommandLineParser::Float, "Rotate y-axis:", "Rotate around y-axis (in deg)");
parser.addArgument("rotate_z", "", mitkDiffusionCommandLineParser::Float, "Rotate z-axis:", "Rotate around z-axis (in deg)");
parser.addArgument("scale_x", "", mitkDiffusionCommandLineParser::Float, "Scale x-axis:", "Scale in direction of x-axis");
parser.addArgument("scale_y", "", mitkDiffusionCommandLineParser::Float, "Scale y-axis:", "Scale in direction of y-axis");
parser.addArgument("scale_z", "", mitkDiffusionCommandLineParser::Float, "Scale z-axis", "Scale in direction of z-axis");
parser.addArgument("translate_x", "", mitkDiffusionCommandLineParser::Float, "Translate x-axis:", "Translate in direction of x-axis (in mm)");
parser.addArgument("translate_y", "", mitkDiffusionCommandLineParser::Float, "Translate y-axis:", "Translate in direction of y-axis (in mm)");
parser.addArgument("translate_z", "", mitkDiffusionCommandLineParser::Float, "Translate z-axis:", "Translate in direction of z-axis (in mm)");
parser.endGroup();
parser.beginGroup("5. Remove fiber parts:");
parser.addArgument("remove_inside", "", mitkDiffusionCommandLineParser::Bool, "Remove fibers inside mask:", "remove fibers inside mask");
parser.addArgument("remove_outside", "", mitkDiffusionCommandLineParser::Bool, "Remove fibers outside mask:", "remove fibers outside mask");
parser.addArgument("mask", "", mitkDiffusionCommandLineParser::String, "Mask image:", "mask image", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.endGroup();
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
bool remove_outside = false;
if (parsedArgs.count("remove_outside"))
remove_outside = us::any_cast<bool>(parsedArgs["remove_outside"]);
bool remove_inside = false;
if (!remove_outside && parsedArgs.count("remove_inside"))
remove_inside = us::any_cast<bool>(parsedArgs["remove_inside"]);
typedef itk::Image< unsigned char, 3 > UcharImageType;
UcharImageType::Pointer mask = nullptr;
if (remove_inside || remove_outside)
{
if (parsedArgs.count("mask"))
mask = mitk::DiffusionDataIOHelper::load_itk_image< UcharImageType >(us::any_cast<std::string>(parsedArgs["mask"]));
else {
MITK_INFO << "Mask needed to remove fibers inside or outside mask!";
return EXIT_FAILURE;
}
}
bool remove = false;
if (parsedArgs.count("remove"))
remove = us::any_cast<bool>(parsedArgs["remove"]);
bool random_subsample = false;
if (parsedArgs.count("random_subsample"))
random_subsample = us::any_cast<bool>(parsedArgs["random_subsample"]);
float spline_resampling = -1;
if (parsedArgs.count("spline_resampling"))
spline_resampling = us::any_cast<float>(parsedArgs["spline_resampling"]);
float linear_resampling = -1;
if (parsedArgs.count("linear_resampling"))
linear_resampling = us::any_cast<float>(parsedArgs["linear_resampling"]);
int num_resampling = -1;
if (parsedArgs.count("num_resampling"))
num_resampling = us::any_cast<int>(parsedArgs["num_resampling"]);
float subsample = -1;
if (parsedArgs.count("subsample"))
subsample = us::any_cast<float>(parsedArgs["subsample"]);
float compress = -1;
if (parsedArgs.count("compress"))
compress = us::any_cast<float>(parsedArgs["compress"]);
float minFiberLength = -1;
if (parsedArgs.count("min_length"))
minFiberLength = us::any_cast<float>(parsedArgs["min_length"]);
float maxFiberLength = -1;
if (parsedArgs.count("max_length"))
maxFiberLength = us::any_cast<float>(parsedArgs["max_length"]);
float max_angle_dist = 10;
if (parsedArgs.count("max_angle_dist"))
max_angle_dist = us::any_cast<float>(parsedArgs["max_angle_dist"]);
float maxAngularDev = -1;
if (parsedArgs.count("max_angle"))
maxAngularDev = us::any_cast<float>(parsedArgs["max_angle"]);
int axis = 0;
if (parsedArgs.count("mirror"))
axis = us::any_cast<int>(parsedArgs["mirror"]);
float rotateX = 0;
if (parsedArgs.count("rotate_x"))
rotateX = us::any_cast<float>(parsedArgs["rotate_x"]);
float rotateY = 0;
if (parsedArgs.count("rotate_y"))
rotateY = us::any_cast<float>(parsedArgs["rotate_y"]);
float rotateZ = 0;
if (parsedArgs.count("rotate_z"))
rotateZ = us::any_cast<float>(parsedArgs["rotate_z"]);
float scaleX = 0;
if (parsedArgs.count("scale_x"))
scaleX = us::any_cast<float>(parsedArgs["scale_x"]);
float scaleY = 0;
if (parsedArgs.count("scale_y"))
scaleY = us::any_cast<float>(parsedArgs["scale_y"]);
float scaleZ = 0;
if (parsedArgs.count("scale_z"))
scaleZ = us::any_cast<float>(parsedArgs["scale_z"]);
float translateX = 0;
if (parsedArgs.count("translate_x"))
translateX = us::any_cast<float>(parsedArgs["translate_x"]);
float translateY = 0;
if (parsedArgs.count("translate_y"))
translateY = us::any_cast<float>(parsedArgs["translate_y"]);
float translateZ = 0;
if (parsedArgs.count("translate_z"))
translateZ = us::any_cast<float>(parsedArgs["translate_z"]);
std::string inFileName = us::any_cast<std::string>(parsedArgs["i"]);
std::string outFileName = us::any_cast<std::string>(parsedArgs["o"]);
try
{
mitk::FiberBundle::Pointer fib = LoadFib(inFileName);
if (subsample>0)
fib = fib->SubsampleFibers(subsample, random_subsample);
if (maxAngularDev>0)
{
auto filter = itk::FiberCurvatureFilter::New();
filter->SetInputFiberBundle(fib);
filter->SetAngularDeviation(maxAngularDev);
filter->SetDistance(max_angle_dist);
filter->SetRemoveFibers(remove);
filter->Update();
fib = filter->GetOutputFiberBundle();
}
if (minFiberLength>0)
fib->RemoveShortFibers(minFiberLength);
if (maxFiberLength>0)
fib->RemoveLongFibers(maxFiberLength);
if (spline_resampling>0)
fib->ResampleSpline(spline_resampling);
if (linear_resampling>0)
fib->ResampleLinear(linear_resampling);
if (num_resampling>0)
fib->ResampleToNumPoints(num_resampling);
if (compress>0)
fib->Compress(compress);
if ( mask.IsNotNull() )
{
if (remove_outside)
fib = fib->RemoveFibersOutside(mask, false);
else if (remove_inside)
fib = fib->RemoveFibersOutside(mask, true);
}
if (axis/100==1)
fib->MirrorFibers(0);
if ((axis%100)/10==1)
fib->MirrorFibers(1);
if (axis%10==1)
fib->MirrorFibers(2);
if (rotateX > 0 || rotateY > 0 || rotateZ > 0){
std::cout << "Rotate " << rotateX << " " << rotateY << " " << rotateZ;
fib->RotateAroundAxis(rotateX, rotateY, rotateZ);
}
if (translateX > 0 || translateY > 0 || translateZ > 0){
fib->TranslateFibers(translateX, translateY, translateZ);
}
if (scaleX > 0 || scaleY > 0 || scaleZ > 0)
fib->ScaleFibers(scaleX, scaleY, scaleZ);
mitk::IOUtil::Save(fib.GetPointer(), outFileName );
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/FiberProcessing/FitFibersToImage.cpp b/Modules/DiffusionCmdApps/FiberProcessing/FitFibersToImage.cpp
index c970795..98235b3 100644
--- a/Modules/DiffusionCmdApps/FiberProcessing/FitFibersToImage.cpp
+++ b/Modules/DiffusionCmdApps/FiberProcessing/FitFibersToImage.cpp
@@ -1,321 +1,321 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkBaseData.h>
#include <mitkImageCast.h>
#include <mitkImageToItk.h>
#include <metaCommand.h>
#include <mitkDiffusionCommandLineParser.h>
#include <usAny.h>
#include <mitkIOUtil.h>
#include <mitkFiberBundle.h>
#include <mitkPreferenceListReaderOptionsFunctor.h>
#include <itkImageFileWriter.h>
#include <mitkPeakImage.h>
#include <itkFitFibersToImageFilter.h>
#include <mitkTensorModel.h>
#include <mitkITKImageImport.h>
#include <mitkDiffusionDataIOHelper.h>
typedef itk::Point<float, 4> PointType4;
typedef itk::Image< float, 4 > PeakImgType;
/*!
\brief Fits the tractogram to the input peak image by assigning a weight to each fiber (similar to https://doi.org/10.1016/j.neuroimage.2015.06.092).
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Fit Fibers To Image");
parser.setCategory("Fiber Tracking and Processing Methods");
parser.setDescription("Assigns a weight to each fiber in order to optimally explain the input peak image");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i1", mitkDiffusionCommandLineParser::StringList, "Input tractograms:", "input tractograms (files or folder)", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "i2", mitkDiffusionCommandLineParser::String, "Input image:", "input image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output root", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("max_iter", "", mitkDiffusionCommandLineParser::Int, "Max. iterations:", "maximum number of optimizer iterations", 20);
parser.addArgument("bundle_based", "", mitkDiffusionCommandLineParser::Bool, "Bundle based fit:", "fit one weight per input tractogram/bundle, not for each fiber", false);
parser.addArgument("min_g", "", mitkDiffusionCommandLineParser::Float, "Min. g:", "lower termination threshold for gradient magnitude", 1e-5);
parser.addArgument("lambda", "", mitkDiffusionCommandLineParser::Float, "Lambda:", "modifier for regularization", 1.0);
parser.addArgument("save_res", "", mitkDiffusionCommandLineParser::Bool, "Save Residuals:", "save residual images", false);
parser.addArgument("save_weights", "", mitkDiffusionCommandLineParser::Bool, "Save Weights:", "save fiber weights in a separate text file", false);
parser.addArgument("filter_zero", "", mitkDiffusionCommandLineParser::Bool, "Filter Zero Weights:", "filter fibers with zero weight", false);
parser.addArgument("filter_outliers", "", mitkDiffusionCommandLineParser::Bool, "Filter outliers:", "perform second optimization run with an upper weight bound based on the first weight estimation (99% quantile)", false);
parser.addArgument("join_tracts", "", mitkDiffusionCommandLineParser::Bool, "Join output tracts:", "outout tracts are merged into a single tractogram", false);
parser.addArgument("regu", "", mitkDiffusionCommandLineParser::String, "Regularization:", "MSM; Variance; VoxelVariance; Lasso; GroupLasso; GroupVariance; NONE", std::string("VoxelVariance"));
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
mitkDiffusionCommandLineParser::StringContainerType fib_files = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["i1"]);
std::string input_image_name = us::any_cast<std::string>(parsedArgs["i2"]);
std::string outRoot = us::any_cast<std::string>(parsedArgs["o"]);
bool single_fib = true;
if (parsedArgs.count("bundle_based"))
single_fib = !us::any_cast<bool>(parsedArgs["bundle_based"]);
bool save_residuals = false;
if (parsedArgs.count("save_res"))
save_residuals = us::any_cast<bool>(parsedArgs["save_res"]);
bool filter_zero = false;
if (parsedArgs.count("filter_zero"))
filter_zero = us::any_cast<bool>(parsedArgs["filter_zero"]);
bool save_weights = false;
if (parsedArgs.count("save_weights"))
save_weights = us::any_cast<bool>(parsedArgs["save_weights"]);
std::string regu = "VoxelVariance";
if (parsedArgs.count("regu"))
regu = us::any_cast<std::string>(parsedArgs["regu"]);
bool join_tracts = false;
if (parsedArgs.count("join_tracts"))
join_tracts = us::any_cast<bool>(parsedArgs["join_tracts"]);
int max_iter = 20;
if (parsedArgs.count("max_iter"))
max_iter = us::any_cast<int>(parsedArgs["max_iter"]);
float g_tol = 1e-5;
if (parsedArgs.count("min_g"))
g_tol = us::any_cast<float>(parsedArgs["min_g"]);
float lambda = 1.0;
if (parsedArgs.count("lambda"))
lambda = us::any_cast<float>(parsedArgs["lambda"]);
bool filter_outliers = false;
if (parsedArgs.count("filter_outliers"))
filter_outliers = us::any_cast<bool>(parsedArgs["filter_outliers"]);
try
{
MITK_INFO << "Loading data";
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Peak Image", "Fiberbundles"}, {});
std::vector< std::string > fib_names;
auto input_tracts = mitk::DiffusionDataIOHelper::load_fibs(fib_files, &fib_names);
itk::FitFibersToImageFilter::Pointer fitter = itk::FitFibersToImageFilter::New();
mitk::BaseData::Pointer inputData = mitk::IOUtil::Load(input_image_name, &functor)[0].GetPointer();
mitk::Image::Pointer mitk_image = dynamic_cast<mitk::Image*>(inputData.GetPointer());
mitk::PeakImage::Pointer mitk_peak_image = dynamic_cast<mitk::PeakImage*>(inputData.GetPointer());
if (mitk_peak_image.IsNotNull())
{
typedef mitk::ImageToItk< mitk::PeakImage::ItkPeakImageType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(mitk_peak_image);
caster->Update();
mitk::PeakImage::ItkPeakImageType::Pointer peak_image = caster->GetOutput();
fitter->SetPeakImage(peak_image);
}
else if (mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(mitk_image))
{
fitter->SetDiffImage(mitk::DiffusionPropertyHelper::GetItkVectorImage(mitk_image));
mitk::TensorModel<>* model = new mitk::TensorModel<>();
model->SetBvalue(1000);
model->SetDiffusivity1(0.0010);
model->SetDiffusivity2(0.00015);
model->SetDiffusivity3(0.00015);
model->SetGradientList(mitk::DiffusionPropertyHelper::GetGradientContainer(mitk_image));
fitter->SetSignalModel(model);
}
else if (mitk_image->GetDimension()==3)
{
itk::FitFibersToImageFilter::DoubleImgType::Pointer scalar_image = itk::FitFibersToImageFilter::DoubleImgType::New();
mitk::CastToItkImage(mitk_image, scalar_image);
fitter->SetScalarImage(scalar_image);
}
else
{
MITK_INFO << "Input image invalid. Valid options are peak image, 3D scalar image or raw diffusion-weighted image.";
return EXIT_FAILURE;
}
fitter->SetTractograms(input_tracts);
fitter->SetFitIndividualFibers(single_fib);
fitter->SetMaxIterations(max_iter);
fitter->SetGradientTolerance(g_tol);
fitter->SetLambda(lambda);
fitter->SetFilterOutliers(filter_outliers);
if (regu=="MSM")
fitter->SetRegularization(VnlCostFunction::REGU::MSM);
else if (regu=="Variance")
fitter->SetRegularization(VnlCostFunction::REGU::VARIANCE);
else if (regu=="Lasso")
fitter->SetRegularization(VnlCostFunction::REGU::LASSO);
else if (regu=="VoxelVariance")
fitter->SetRegularization(VnlCostFunction::REGU::VOXEL_VARIANCE);
else if (regu=="GroupLasso")
fitter->SetRegularization(VnlCostFunction::REGU::GROUP_LASSO);
else if (regu=="GroupVariance")
fitter->SetRegularization(VnlCostFunction::REGU::GROUP_VARIANCE);
else if (regu=="NONE")
fitter->SetRegularization(VnlCostFunction::REGU::NONE);
fitter->Update();
mitk::LocaleSwitch localeSwitch("C");
if (save_residuals && mitk_peak_image.IsNotNull())
{
itk::ImageFileWriter< PeakImgType >::Pointer writer = itk::ImageFileWriter< PeakImgType >::New();
writer->SetInput(fitter->GetFittedImage());
writer->SetFileName(outRoot + "_fitted.nii.gz");
writer->Update();
writer->SetInput(fitter->GetResidualImage());
writer->SetFileName(outRoot + "_residual.nii.gz");
writer->Update();
writer->SetInput(fitter->GetOverexplainedImage());
writer->SetFileName(outRoot + "_overexplained.nii.gz");
writer->Update();
writer->SetInput(fitter->GetUnderexplainedImage());
writer->SetFileName(outRoot + "_underexplained.nii.gz");
writer->Update();
}
else if (save_residuals && mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(mitk_image))
{
{
mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( fitter->GetFittedImageDiff().GetPointer() );
mitk::DiffusionPropertyHelper::CopyProperties(mitk_image, outImage, true);
mitk::DiffusionPropertyHelper::InitializeImage( outImage );
mitk::IOUtil::Save(outImage, "application/vnd.mitk.nii.gz", outRoot + "_fitted_image.nii.gz");
}
{
mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( fitter->GetResidualImageDiff().GetPointer() );
mitk::DiffusionPropertyHelper::CopyProperties(mitk_image, outImage, true);
mitk::DiffusionPropertyHelper::InitializeImage( outImage );
mitk::IOUtil::Save(outImage, "application/vnd.mitk.nii.gz", outRoot + "_residual_image.nii.gz");
}
{
mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( fitter->GetOverexplainedImageDiff().GetPointer() );
mitk::DiffusionPropertyHelper::CopyProperties(mitk_image, outImage, true);
mitk::DiffusionPropertyHelper::InitializeImage( outImage );
mitk::IOUtil::Save(outImage, "application/vnd.mitk.nii.gz", outRoot + "_overexplained_image.nii.gz");
}
{
mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( fitter->GetUnderexplainedImageDiff().GetPointer() );
mitk::DiffusionPropertyHelper::CopyProperties(mitk_image, outImage, true);
mitk::DiffusionPropertyHelper::InitializeImage( outImage );
mitk::IOUtil::Save(outImage, "application/vnd.mitk.nii.gz", outRoot + "_underexplained_image.nii.gz");
}
}
else if (save_residuals)
{
itk::ImageFileWriter< itk::FitFibersToImageFilter::DoubleImgType >::Pointer writer = itk::ImageFileWriter< itk::FitFibersToImageFilter::DoubleImgType >::New();
writer->SetInput(fitter->GetFittedImageScalar());
writer->SetFileName(outRoot + "_fitted_image.nii.gz");
writer->Update();
writer->SetInput(fitter->GetResidualImageScalar());
writer->SetFileName(outRoot + "_residual_image.nii.gz");
writer->Update();
writer->SetInput(fitter->GetOverexplainedImageScalar());
writer->SetFileName(outRoot + "_overexplained_image.nii.gz");
writer->Update();
writer->SetInput(fitter->GetUnderexplainedImageScalar());
writer->SetFileName(outRoot + "_underexplained_image.nii.gz");
writer->Update();
}
std::vector< mitk::FiberBundle::Pointer > output_tracts = fitter->GetTractograms();
if (!join_tracts)
{
for (unsigned int bundle=0; bundle<output_tracts.size(); bundle++)
{
std::string name = fib_names.at(bundle);
name = ist::GetFilenameWithoutExtension(name);
auto fib = output_tracts.at(bundle);
if (filter_zero)
fib = fib->FilterByWeights(0.0);
if (fib->GetNumFibers()>0)
{
fib->ColorFibersByFiberWeights(false, true);
mitk::IOUtil::Save(fib, outRoot + name + "_fitted.fib");
if (save_weights)
{
ofstream logfile;
logfile.open (outRoot + name + "_weights.txt");
for (unsigned int f=0; f<output_tracts.at(bundle)->GetNumFibers(); ++f)
logfile << output_tracts.at(bundle)->GetFiberWeight(f) << "\n";
logfile.close();
}
}
else
MITK_INFO << "Output contains no fibers!";
}
}
else
{
mitk::FiberBundle::Pointer out = mitk::FiberBundle::New();
out = out->AddBundles(output_tracts);
if (filter_zero)
out = out->FilterByWeights(0.0);
if (out->GetNumFibers()>0)
{
out->ColorFibersByFiberWeights(false, true);
mitk::IOUtil::Save(out, outRoot + "_fitted.fib");
if (save_weights)
{
ofstream logfile;
logfile.open (outRoot + "_weights.txt");
for (unsigned int f=0; f<out->GetNumFibers(); ++f)
logfile << out->GetFiberWeight(f) << "\n";
logfile.close();
}
}
else
MITK_INFO << "Output contains no fibers!";
}
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/FiberProcessing/Sift2WeightCopy.cpp b/Modules/DiffusionCmdApps/FiberProcessing/Sift2WeightCopy.cpp
index 7190e3f..2c4c5da 100644
--- a/Modules/DiffusionCmdApps/FiberProcessing/Sift2WeightCopy.cpp
+++ b/Modules/DiffusionCmdApps/FiberProcessing/Sift2WeightCopy.cpp
@@ -1,107 +1,107 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <vector>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <string>
#include <istream>
#include <itkMetaDataObject.h>
#include <itkVectorImage.h>
#include <mitkImageCast.h>
#include <mitkBaseData.h>
#include <mitkFiberBundle.h>
#include "mitkDiffusionCommandLineParser.h"
#include <mitkLexicalCast.h>
#include <mitkCoreObjectFactory.h>
#include <mitkIOUtil.h>
#include <itkTractDensityImageFilter.h>
#include <itkTractsToFiberEndingsImageFilter.h>
mitk::FiberBundle::Pointer LoadFib(std::string filename)
{
std::vector<mitk::BaseData::Pointer> fibInfile = mitk::IOUtil::Load(filename);
if( fibInfile.empty() )
std::cout << "File " << filename << " could not be read!";
mitk::BaseData::Pointer baseData = fibInfile.at(0);
return dynamic_cast<mitk::FiberBundle*>(baseData.GetPointer());
}
/*!
\brief Import Sift2 Fiber Weights txt file.
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("SIFT2 Fiber Weight Import");
parser.setCategory("Fiber Tracking and Processing Methods");
parser.setDescription("Import SIFT2 fiber weights.");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "input fiber bundle", us::Any(), false);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output fiber bundle (.fib)", us::Any(), false);
parser.addArgument("weights", "", mitkDiffusionCommandLineParser::String, "Weights:", "input weights file (.txt)", us::Any(), false);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
std::string inFileName = us::any_cast<std::string>(parsedArgs["i"]);
std::string weightsFileName = us::any_cast<std::string>(parsedArgs["weights"]);
std::string outFileName = us::any_cast<std::string>(parsedArgs["o"]);
try
{
mitk::FiberBundle::Pointer fib = LoadFib(inFileName);
std::ifstream fin;
fin.open(weightsFileName);
if (!fin.good())
return 1; // exit if file not found
std::vector<float> weights;
for (float d; fin >> d; ) { weights.push_back(d); }
for(std::size_t i = 0; i != weights.size(); i++) {
fib->SetFiberWeight(i, weights[i]);
}
mitk::IOUtil::Save(fib.GetPointer(), outFileName );
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/FiberProcessing/TractDensity.cpp b/Modules/DiffusionCmdApps/FiberProcessing/TractDensity.cpp
index aa2b8b7..e6b3853 100644
--- a/Modules/DiffusionCmdApps/FiberProcessing/TractDensity.cpp
+++ b/Modules/DiffusionCmdApps/FiberProcessing/TractDensity.cpp
@@ -1,213 +1,213 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <vector>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <string>
#include <itkImageFileWriter.h>
#include <itkMetaDataObject.h>
#include <itkVectorImage.h>
#include <mitkImageCast.h>
#include <mitkBaseData.h>
#include <mitkFiberBundle.h>
#include "mitkDiffusionCommandLineParser.h"
#include <mitkLexicalCast.h>
#include <mitkCoreObjectFactory.h>
#include <mitkIOUtil.h>
#include <itkTractDensityImageFilter.h>
#include <itkTractsToFiberEndingsImageFilter.h>
mitk::FiberBundle::Pointer LoadFib(std::string filename)
{
std::vector<mitk::BaseData::Pointer> fibInfile = mitk::IOUtil::Load(filename);
if( fibInfile.empty() )
std::cout << "File " << filename << " could not be read!";
mitk::BaseData::Pointer baseData = fibInfile.at(0);
return dynamic_cast<mitk::FiberBundle*>(baseData.GetPointer());
}
/*!
\brief Modify input tractogram: fiber resampling, compression, pruning and transformation.
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Tract Density");
parser.setCategory("Fiber Tracking and Processing Methods");
parser.setDescription("Generate tract density image, fiber envelope or fiber endpoints image.");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "input fiber bundle", us::Any(), false);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output image", us::Any(), false);
parser.addArgument("binary", "", mitkDiffusionCommandLineParser::Bool, "Binary output:", "calculate binary tract envelope", us::Any());
parser.addArgument("normalize", "", mitkDiffusionCommandLineParser::Bool, "Normalized output:", "normalize output to 0-1", us::Any());
parser.addArgument("endpoints", "", mitkDiffusionCommandLineParser::Bool, "Output endpoints image:", "calculate image of fiber endpoints instead of mask", us::Any());
parser.addArgument("reference_image", "", mitkDiffusionCommandLineParser::String, "Reference image:", "output image will have geometry of this reference image", us::Any());
parser.addArgument("upsampling", "", mitkDiffusionCommandLineParser::Float, "Upsampling:", "upsampling", 1.0);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
bool binary = false;
if (parsedArgs.count("binary"))
binary = us::any_cast<bool>(parsedArgs["binary"]);
bool endpoints = false;
if (parsedArgs.count("endpoints"))
endpoints = us::any_cast<bool>(parsedArgs["endpoints"]);
bool normalize = false;
if (parsedArgs.count("normalize"))
normalize = us::any_cast<bool>(parsedArgs["normalize"]);
float upsampling = 1.0;
if (parsedArgs.count("upsampling"))
upsampling = us::any_cast<float>(parsedArgs["upsampling"]);
MITK_INFO << "Upsampling: " << upsampling;
std::string reference_image = "";
if (parsedArgs.count("reference_image"))
reference_image = us::any_cast<std::string>(parsedArgs["reference_image"]);
std::string inFileName = us::any_cast<std::string>(parsedArgs["i"]);
std::string outFileName = us::any_cast<std::string>(parsedArgs["o"]);
try
{
mitk::FiberBundle::Pointer fib = LoadFib(inFileName);
mitk::Image::Pointer ref_img;
if (!reference_image.empty())
ref_img = mitk::IOUtil::Load<mitk::Image>(reference_image);
if (endpoints)
{
typedef unsigned int OutPixType;
typedef itk::Image<OutPixType, 3> OutImageType;
typedef itk::TractsToFiberEndingsImageFilter< OutImageType > ImageGeneratorType;
ImageGeneratorType::Pointer generator = ImageGeneratorType::New();
generator->SetFiberBundle(fib);
generator->SetUpsamplingFactor(upsampling);
if (ref_img.IsNotNull())
{
OutImageType::Pointer itkImage = OutImageType::New();
CastToItkImage(ref_img, itkImage);
generator->SetInputImage(itkImage);
generator->SetUseImageGeometry(true);
}
generator->Update();
// get output image
typedef itk::Image<OutPixType,3> OutType;
OutType::Pointer outImg = generator->GetOutput();
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk(outImg.GetPointer());
img->SetVolume(outImg->GetBufferPointer());
mitk::IOUtil::Save(img, outFileName );
}
else if (binary)
{
typedef unsigned char OutPixType;
typedef itk::Image<OutPixType, 3> OutImageType;
itk::TractDensityImageFilter< OutImageType >::Pointer generator = itk::TractDensityImageFilter< OutImageType >::New();
generator->SetFiberBundle(fib);
generator->SetBinaryOutput(binary);
generator->SetOutputAbsoluteValues(!normalize);
generator->SetUpsamplingFactor(upsampling);
if (ref_img.IsNotNull())
{
OutImageType::Pointer itkImage = OutImageType::New();
CastToItkImage(ref_img, itkImage);
generator->SetInputImage(itkImage);
generator->SetUseImageGeometry(true);
}
generator->Update();
// get output image
typedef itk::Image<OutPixType,3> OutType;
OutType::Pointer outImg = generator->GetOutput();
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk(outImg.GetPointer());
img->SetVolume(outImg->GetBufferPointer());
mitk::IOUtil::Save(img, outFileName );
}
else
{
typedef float OutPixType;
typedef itk::Image<OutPixType, 3> OutImageType;
itk::TractDensityImageFilter< OutImageType >::Pointer generator = itk::TractDensityImageFilter< OutImageType >::New();
generator->SetFiberBundle(fib);
generator->SetBinaryOutput(binary);
generator->SetOutputAbsoluteValues(!normalize);
generator->SetUpsamplingFactor(upsampling);
if (ref_img.IsNotNull())
{
OutImageType::Pointer itkImage = OutImageType::New();
CastToItkImage(ref_img, itkImage);
generator->SetInputImage(itkImage);
generator->SetUseImageGeometry(true);
}
generator->Update();
// get output image
typedef itk::Image<OutPixType,3> OutType;
OutType::Pointer outImg = generator->GetOutput();
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk(outImg.GetPointer());
img->SetVolume(outImg->GetBufferPointer());
mitk::IOUtil::Save(img, outFileName );
}
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/FiberProcessing/TractDensityFilter.cpp b/Modules/DiffusionCmdApps/FiberProcessing/TractDensityFilter.cpp
index c64f123..6271ee2 100644
--- a/Modules/DiffusionCmdApps/FiberProcessing/TractDensityFilter.cpp
+++ b/Modules/DiffusionCmdApps/FiberProcessing/TractDensityFilter.cpp
@@ -1,110 +1,110 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <metaCommand.h>
#include "mitkDiffusionCommandLineParser.h"
#include <usAny.h>
#include <mitkIOUtil.h>
#include <mitkLexicalCast.h>
#include <mitkFiberBundle.h>
#include <mitkImageCast.h>
#include <mitkImageToItk.h>
#include <itksys/SystemTools.hxx>
#include <itkFiberExtractionFilter.h>
#include <itkTractDensityImageFilter.h>
#define _USE_MATH_DEFINES
#include <math.h>
typedef itksys::SystemTools ist;
typedef itk::Image<float, 3> ItkFloatImgType;
/*!
\brief Extract fibers from a tractogram using binary image ROIs
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Filter Outliers by Tract Density");
parser.setCategory("Fiber Tracking and Processing Methods");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "input tractogram (.fib/.trk/.tck/.dcm)", us::Any(), false);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output tractogram", us::Any(), false);
parser.addArgument("threshold", "", mitkDiffusionCommandLineParser::Float, "Threshold:", "positive means ROI image value threshold", 0.05);
parser.addArgument("overlap", "", mitkDiffusionCommandLineParser::Float, "Overlap:", "positive means ROI image value threshold", 0.5);
parser.addArgument("min_fibers", "", mitkDiffusionCommandLineParser::Int, "Min. num. fibers:", "discard positive tracts with less fibers", 0);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
std::string inFib = us::any_cast<std::string>(parsedArgs["i"]);
std::string outFib = us::any_cast<std::string>(parsedArgs["o"]);
int min_fibers = 0;
if (parsedArgs.count("min_fibers"))
min_fibers = us::any_cast<int>(parsedArgs["min_fibers"]);
float overlap = 0.5;
if (parsedArgs.count("overlap"))
overlap = us::any_cast<float>(parsedArgs["overlap"]);
float threshold = 0.05f;
if (parsedArgs.count("threshold"))
threshold = us::any_cast<float>(parsedArgs["threshold"]);
try
{
mitk::FiberBundle::Pointer inputTractogram = mitk::IOUtil::Load<mitk::FiberBundle>(inFib);
itk::TractDensityImageFilter< ItkFloatImgType >::Pointer generator = itk::TractDensityImageFilter< ItkFloatImgType >::New();
generator->SetFiberBundle(inputTractogram);
generator->SetBinaryOutput(false);
generator->SetOutputAbsoluteValues(false);
generator->Update();
itk::FiberExtractionFilter<float>::Pointer extractor = itk::FiberExtractionFilter<float>::New();
extractor->SetRoiImages({generator->GetOutput()});
extractor->SetInputFiberBundle(inputTractogram);
extractor->SetOverlapFraction(overlap);
extractor->SetInterpolate(true);
extractor->SetThreshold(threshold);
extractor->SetNoNegatives(true);
extractor->Update();
if (extractor->GetPositives().at(0)->GetNumFibers() >= static_cast<unsigned int>(min_fibers))
mitk::IOUtil::Save(extractor->GetPositives().at(0), outFib);
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/Fiberfox/Fiberfox.cpp b/Modules/DiffusionCmdApps/Fiberfox/Fiberfox.cpp
index fa19b8a..cd9beb9 100644
--- a/Modules/DiffusionCmdApps/Fiberfox/Fiberfox.cpp
+++ b/Modules/DiffusionCmdApps/Fiberfox/Fiberfox.cpp
@@ -1,289 +1,289 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkImageCast.h>
#include <mitkITKImageImport.h>
#include <mitkProperties.h>
#include <mitkImage.h>
#include <mitkIOUtil.h>
#include <mitkFiberBundle.h>
#include <mitkFiberfoxParameters.h>
#include "mitkDiffusionCommandLineParser.h"
#include <itkTractsToDWIImageFilter.h>
#include <mitkLexicalCast.h>
#include <mitkPreferenceListReaderOptionsFunctor.h>
#include <itksys/SystemTools.hxx>
#include <mitkFiberfoxParameters.h>
#include <mitkDiffusionVersion.h>
using namespace mitk;
/*!
* \brief Command line interface to Fiberfox.
* Simulate a diffusion-weighted image from a tractogram using the specified parameter file.
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Fiberfox");
parser.setCategory("Diffusion Simulation Tools");
parser.setContributor("MIC");
parser.setDescription("Command line interface to Fiberfox." " Simulate a diffusion-weighted image from a tractogram using the specified parameter file.");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output root:", "output folder and file prefix", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "input tractogram or diffusion-weighted image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("parameters", "p", mitkDiffusionCommandLineParser::String, "Parameter file:", "fiberfox parameter file (.ffp)", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("template", "t", mitkDiffusionCommandLineParser::String, "Template image:", "use parameters of the template image", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("verbose", "v", mitkDiffusionCommandLineParser::Bool, "Output additional images:", "output volume fraction images etc.", us::Any());
parser.addArgument("dont_apply_direction_matrix", "", mitkDiffusionCommandLineParser::Bool, "Don't apply direction matrix:", "don't rotate gradients by image direction matrix", us::Any());
parser.addArgument("fix_seed", "", mitkDiffusionCommandLineParser::Bool, "Use fix random seed:", "always use same sequence of random numbers", us::Any());
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
{
return EXIT_FAILURE;
}
std::string outName = us::any_cast<std::string>(parsedArgs["o"]);
std::string paramName = us::any_cast<std::string>(parsedArgs["parameters"]);
std::string input="";
if (parsedArgs.count("i"))
input = us::any_cast<std::string>(parsedArgs["i"]);
bool fix_seed = false;
if (parsedArgs.count("fix_seed"))
fix_seed = us::any_cast<bool>(parsedArgs["fix_seed"]);
bool verbose = false;
if (parsedArgs.count("verbose"))
verbose = us::any_cast<bool>(parsedArgs["verbose"]);
bool apply_direction_matrix = true;
if (parsedArgs.count("dont_apply_direction_matrix"))
apply_direction_matrix = false;
FiberfoxParameters parameters;
parameters.LoadParameters(paramName, fix_seed);
// Test if /path/dir is an existing directory:
std::string file_extension = "";
if( itksys::SystemTools::FileIsDirectory( outName ) )
{
while( *(--(outName.cend())) == '/')
{
outName.pop_back();
}
outName = outName + '/';
parameters.m_Misc.m_OutputPath = outName;
outName = outName + parameters.m_Misc.m_OutputPrefix; // using default m_OutputPrefix as initialized.
}
else
{
// outName is NOT an existing directory, so we need to remove all trailing slashes:
while( *(--(outName.cend())) == '/')
{
outName.pop_back();
}
// now split up the given outName into directory and (prefix of) filename:
if( ! itksys::SystemTools::GetFilenamePath( outName ).empty()
&& itksys::SystemTools::FileIsDirectory(itksys::SystemTools::GetFilenamePath( outName ) ) )
{
parameters.m_Misc.m_OutputPath = itksys::SystemTools::GetFilenamePath( outName ) + '/';
}
else
{
parameters.m_Misc.m_OutputPath = itksys::SystemTools::GetCurrentWorkingDirectory() + '/';
}
file_extension = itksys::SystemTools::GetFilenameExtension(outName);
if( ! itksys::SystemTools::GetFilenameWithoutExtension( outName ).empty() )
{
parameters.m_Misc.m_OutputPrefix = itksys::SystemTools::GetFilenameWithoutExtension( outName );
}
else
{
parameters.m_Misc.m_OutputPrefix = "fiberfox";
}
outName = parameters.m_Misc.m_OutputPath + parameters.m_Misc.m_OutputPrefix;
}
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images", "Fiberbundles"}, {});
mitk::BaseData::Pointer inputData = mitk::IOUtil::Load(input, &functor)[0];
itk::TractsToDWIImageFilter< short >::Pointer tractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New();
if ( dynamic_cast<mitk::FiberBundle*>(inputData.GetPointer()) ) // simulate dataset from fibers
{
tractsToDwiFilter->SetFiberBundle(dynamic_cast<mitk::FiberBundle*>(inputData.GetPointer()));
if (parsedArgs.count("template"))
{
MITK_INFO << "Loading template image";
typedef itk::VectorImage< short, 3 > ItkDwiType;
typedef itk::Image< short, 3 > ItkImageType;
mitk::BaseData::Pointer templateData = mitk::IOUtil::Load(us::any_cast<std::string>(parsedArgs["template"]), &functor)[0];
mitk::Image::Pointer template_image = dynamic_cast<mitk::Image*>(templateData.GetPointer());
if (mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(template_image))
{
ItkDwiType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::GetItkVectorImage(template_image);
parameters.m_SignalGen.m_ImageRegion = itkVectorImagePointer->GetLargestPossibleRegion();
parameters.m_SignalGen.m_ImageSpacing = itkVectorImagePointer->GetSpacing();
parameters.m_SignalGen.m_ImageOrigin = itkVectorImagePointer->GetOrigin();
parameters.m_SignalGen.m_ImageDirection = itkVectorImagePointer->GetDirection();
parameters.SetBvalue(mitk::DiffusionPropertyHelper::GetReferenceBValue(template_image));
parameters.SetGradienDirections(mitk::DiffusionPropertyHelper::GetOriginalGradientContainer(template_image));
}
else
{
ItkImageType::Pointer itkImagePointer = ItkImageType::New();
mitk::CastToItkImage(template_image, itkImagePointer);
parameters.m_SignalGen.m_ImageRegion = itkImagePointer->GetLargestPossibleRegion();
parameters.m_SignalGen.m_ImageSpacing = itkImagePointer->GetSpacing();
parameters.m_SignalGen.m_ImageOrigin = itkImagePointer->GetOrigin();
parameters.m_SignalGen.m_ImageDirection = itkImagePointer->GetDirection();
}
}
}
else if ( dynamic_cast<mitk::Image*>(inputData.GetPointer()) ) // add artifacts to existing image
{
typedef itk::VectorImage< short, 3 > ItkDwiType;
mitk::Image::Pointer diffImg = dynamic_cast<mitk::Image*>(inputData.GetPointer());
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(diffImg, itkVectorImagePointer);
parameters.m_SignalGen.m_SignalScale = 1;
parameters.m_SignalGen.m_ImageRegion = itkVectorImagePointer->GetLargestPossibleRegion();
parameters.m_SignalGen.m_ImageSpacing = itkVectorImagePointer->GetSpacing();
parameters.m_SignalGen.m_ImageOrigin = itkVectorImagePointer->GetOrigin();
parameters.m_SignalGen.m_ImageDirection = itkVectorImagePointer->GetDirection();
parameters.SetBvalue(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImg));
parameters.SetGradienDirections(mitk::DiffusionPropertyHelper::GetOriginalGradientContainer(diffImg));
tractsToDwiFilter->SetInputImage(itkVectorImagePointer);
}
if (verbose)
{
MITK_DEBUG << outName << ".ffp";
parameters.m_Misc.m_OutputAdditionalImages = true;
parameters.SaveParameters(outName+".ffp");
}
else
parameters.m_Misc.m_OutputAdditionalImages = false;
if (apply_direction_matrix)
{
MITK_INFO << "Applying direction matrix to gradient directions.";
parameters.ApplyDirectionMatrix();
}
tractsToDwiFilter->SetParameters(parameters);
tractsToDwiFilter->SetUseConstantRandSeed(fix_seed);
tractsToDwiFilter->Update();
mitk::Image::Pointer image = mitk::GrabItkImageMemory(tractsToDwiFilter->GetOutput());
if (parameters.m_SignalGen.GetNumWeightedVolumes()>0)
{
if (apply_direction_matrix)
mitk::DiffusionPropertyHelper::SetGradientContainer(image, parameters.m_SignalGen.GetItkGradientContainer());
else
mitk::DiffusionPropertyHelper::SetOriginalGradientContainer(image, parameters.m_SignalGen.GetItkGradientContainer());
mitk::DiffusionPropertyHelper::SetReferenceBValue(image, parameters.m_SignalGen.GetBvalue());
mitk::DiffusionPropertyHelper::InitializeImage(image);
if (file_extension=="")
mitk::IOUtil::Save(image, "DWI_NIFTI", outName+".nii.gz");
else if (file_extension==".nii" || file_extension==".nii.gz")
mitk::IOUtil::Save(image, "DWI_NIFTI", outName+file_extension);
else
mitk::IOUtil::Save(image, outName+file_extension);
}
else
mitk::IOUtil::Save(image, outName+".nii.gz");
if (verbose)
{
if (tractsToDwiFilter->GetTickImage().IsNotNull())
{
mitk::Image::Pointer mitkImage = mitk::Image::New();
itk::TractsToDWIImageFilter< short >::Float2DImageType::Pointer itkImage = tractsToDwiFilter->GetTickImage();
mitkImage = mitk::GrabItkImageMemory( itkImage.GetPointer() );
mitk::IOUtil::Save(mitkImage, outName+"_Ticks.nii.gz");
}
if (tractsToDwiFilter->GetRfImage().IsNotNull())
{
mitk::Image::Pointer mitkImage = mitk::Image::New();
itk::TractsToDWIImageFilter< short >::Float2DImageType::Pointer itkImage = tractsToDwiFilter->GetRfImage();
mitkImage = mitk::GrabItkImageMemory( itkImage.GetPointer() );
mitk::IOUtil::Save(mitkImage, outName+"_TimeFromRf.nii.gz");
}
std::vector< itk::TractsToDWIImageFilter< short >::ItkDoubleImgType::Pointer > volumeFractions = tractsToDwiFilter->GetVolumeFractions();
for (unsigned int k=0; k<volumeFractions.size(); k++)
{
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk(volumeFractions.at(k).GetPointer());
image->SetVolume(volumeFractions.at(k)->GetBufferPointer());
mitk::IOUtil::Save(image, outName+"_Compartment"+boost::lexical_cast<std::string>(k+1)+".nii.gz");
}
if (tractsToDwiFilter->GetPhaseImage().IsNotNull())
{
mitk::Image::Pointer image = mitk::Image::New();
itk::TractsToDWIImageFilter< short >::DoubleDwiType::Pointer itkPhase = tractsToDwiFilter->GetPhaseImage();
image = mitk::GrabItkImageMemory( itkPhase.GetPointer() );
mitk::IOUtil::Save(image, outName+"_Phase.nii.gz");
}
if (tractsToDwiFilter->GetKspaceImage().IsNotNull())
{
mitk::Image::Pointer image = mitk::Image::New();
itk::TractsToDWIImageFilter< short >::DoubleDwiType::Pointer itkImage = tractsToDwiFilter->GetKspaceImage();
image = mitk::GrabItkImageMemory( itkImage.GetPointer() );
mitk::IOUtil::Save(image, outName+"_kSpace.nii.gz");
}
int c = 1;
std::vector< itk::TractsToDWIImageFilter< short >::DoubleDwiType::Pointer > output_real = tractsToDwiFilter->GetOutputImagesReal();
for (auto real : output_real)
{
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk(real.GetPointer());
image->SetVolume(real->GetBufferPointer());
mitk::IOUtil::Save(image, outName+"_Coil-"+boost::lexical_cast<std::string>(c)+"-real.nii.gz");
++c;
}
c = 1;
std::vector< itk::TractsToDWIImageFilter< short >::DoubleDwiType::Pointer > output_imag = tractsToDwiFilter->GetOutputImagesImag();
for (auto imag : output_imag)
{
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk(imag.GetPointer());
image->SetVolume(imag->GetBufferPointer());
mitk::IOUtil::Save(image, outName+"_Coil-"+boost::lexical_cast<std::string>(c)+"-imag.nii.gz");
++c;
}
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/Fiberfox/RandomFiberPhantom.cpp b/Modules/DiffusionCmdApps/Fiberfox/RandomFiberPhantom.cpp
index e6ac8e4..da56ef7 100644
--- a/Modules/DiffusionCmdApps/Fiberfox/RandomFiberPhantom.cpp
+++ b/Modules/DiffusionCmdApps/Fiberfox/RandomFiberPhantom.cpp
@@ -1,172 +1,172 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <metaCommand.h>
#include "mitkDiffusionCommandLineParser.h"
#include <usAny.h>
#include <mitkCoreObjectFactory.h>
#include <mitkFiberBundle.h>
#include <mitkDiffusionDataIOHelper.h>
#include <itkRandomPhantomFilter.h>
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Random Fiber Phantom");
parser.setCategory("Diffusion Simulation Tools");
parser.setContributor("MIC");
parser.setDescription("Create Random Fiber Configurations");
parser.setArgumentPrefix("--", "-");
parser.addArgument("num_bundles", "", mitkDiffusionCommandLineParser::Int, "", "", 50);
parser.addArgument("min_density", "", mitkDiffusionCommandLineParser::Int, "", "", 50);
parser.addArgument("max_density", "", mitkDiffusionCommandLineParser::Int, "", "", 200);
parser.addArgument("size_x", "", mitkDiffusionCommandLineParser::Int, "", "", 250);
parser.addArgument("size_y", "", mitkDiffusionCommandLineParser::Int, "", "", 250);
parser.addArgument("size_z", "", mitkDiffusionCommandLineParser::Int, "", "", 250);
parser.addArgument("min_stepsize", "", mitkDiffusionCommandLineParser::Int, "", "", 15);
parser.addArgument("max_stepsize", "", mitkDiffusionCommandLineParser::Int, "", "", 30);
parser.addArgument("min_curve", "", mitkDiffusionCommandLineParser::Int, "", "", 5);
parser.addArgument("max_curve", "", mitkDiffusionCommandLineParser::Int, "", "", 45);
parser.addArgument("min_radius", "", mitkDiffusionCommandLineParser::Int, "", "", 5);
parser.addArgument("max_radius", "", mitkDiffusionCommandLineParser::Int, "", "", 25);
parser.addArgument("min_twist", "", mitkDiffusionCommandLineParser::Int, "", "", 15);
parser.addArgument("max_twist", "", mitkDiffusionCommandLineParser::Int, "", "", 30);
parser.addArgument("compress", "", mitkDiffusionCommandLineParser::Float, "Compress:", "compress fiber using the given error threshold (in mm)", 0.1);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output folder:", "output folder", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("fix_seed", "", mitkDiffusionCommandLineParser::Int, "Fix random seed:", "if >= 0, produce same random values on each run using this seed.", -1);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
std::string out_folder = us::any_cast<std::string>(parsedArgs["o"]);
float compress=0.1;
if (parsedArgs.count("compress"))
compress = us::any_cast<float>(parsedArgs["compress"]);
int num_bundles=50;
if (parsedArgs.count("num_bundles"))
num_bundles = us::any_cast<int>(parsedArgs["num_bundles"]);
int min_density=50;
if (parsedArgs.count("min_density"))
min_density = us::any_cast<int>(parsedArgs["min_density"]);
int max_density=200;
if (parsedArgs.count("max_density"))
max_density = us::any_cast<int>(parsedArgs["max_density"]);
int size_x=250;
if (parsedArgs.count("size_x"))
size_x = us::any_cast<int>(parsedArgs["size_x"]);
int size_y=250;
if (parsedArgs.count("size_y"))
size_y = us::any_cast<int>(parsedArgs["size_y"]);
int size_z=250;
if (parsedArgs.count("size_z"))
size_z = us::any_cast<int>(parsedArgs["size_z"]);
int min_stepsize=15;
if (parsedArgs.count("min_stepsize"))
min_stepsize = us::any_cast<int>(parsedArgs["min_stepsize"]);
int max_stepsize=30;
if (parsedArgs.count("max_stepsize"))
max_stepsize = us::any_cast<int>(parsedArgs["max_stepsize"]);
int min_curve=5;
if (parsedArgs.count("min_curve"))
min_curve = us::any_cast<int>(parsedArgs["min_curve"]);
int max_curve=45;
if (parsedArgs.count("max_curve"))
max_curve = us::any_cast<int>(parsedArgs["max_curve"]);
int min_radius=5;
if (parsedArgs.count("min_radius"))
min_radius = us::any_cast<int>(parsedArgs["min_radius"]);
int max_radius=25;
if (parsedArgs.count("max_radius"))
max_radius = us::any_cast<int>(parsedArgs["max_radius"]);
int min_twist=15;
if (parsedArgs.count("min_twist"))
min_twist = us::any_cast<int>(parsedArgs["min_twist"]);
int max_twist=30;
if (parsedArgs.count("max_twist"))
max_twist = us::any_cast<int>(parsedArgs["max_twist"]);
int fix_seed = -1;
if (parsedArgs.count("fix_seed"))
fix_seed = us::any_cast<int>(parsedArgs["fix_seed"]);
try
{
itk::RandomPhantomFilter::Pointer filter = itk::RandomPhantomFilter::New();
filter->SetNumTracts(static_cast<unsigned int>(num_bundles));
filter->SetMinStreamlineDensity(static_cast<unsigned int>(min_density));
filter->SetMaxStreamlineDensity(static_cast<unsigned int>(max_density));
mitk::Vector3D vol;
vol[0] = size_x;
vol[1] = size_y;
vol[2] = size_z;
filter->SetVolumeSize(vol);
filter->SetStepSizeMin(static_cast<unsigned int>(min_stepsize));
filter->SetStepSizeMax(static_cast<unsigned int>(max_stepsize));
filter->SetCurvynessMin(static_cast<unsigned int>(min_curve));
filter->SetCurvynessMax(static_cast<unsigned int>(max_curve));
filter->SetStartRadiusMin(static_cast<unsigned int>(min_radius));
filter->SetStartRadiusMax(static_cast<unsigned int>(max_radius));
filter->SetMinTwist(static_cast<unsigned int>(min_twist));
filter->SetMaxTwist(static_cast<unsigned int>(max_twist));
filter->SetFixSeed(fix_seed);
filter->Update();
auto fibs = filter->GetFiberBundles();
std::vector< mitk::DataNode::Pointer > fiber_nodes;
int c = 1;
for (auto fib : fibs)
{
if (compress>0)
fib->Compress(compress);
mitk::IOUtil::Save(fib, out_folder + "Bundle_" + boost::lexical_cast<std::string>(c) + ".fib");
++c;
}
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/Misc/CopyGeometry.cpp b/Modules/DiffusionCmdApps/Misc/CopyGeometry.cpp
index 46c4c8d..72dcfb1 100644
--- a/Modules/DiffusionCmdApps/Misc/CopyGeometry.cpp
+++ b/Modules/DiffusionCmdApps/Misc/CopyGeometry.cpp
@@ -1,114 +1,114 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkImageCast.h>
#include <mitkImage.h>
#include <mitkIOUtil.h>
#include "mitkDiffusionCommandLineParser.h"
/*!
\brief Copies transformation matrix of one image to another
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Copy Geometry");
parser.setCategory("Preprocessing Tools");
parser.setDescription("Copies transformation matrix of one image to another");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "input image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("ref", "r", mitkDiffusionCommandLineParser::String, "Reference:", "reference image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("alignCentroid", "a", mitkDiffusionCommandLineParser::Bool, "align centroids", "align centroids", us::Any(), true);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
// mandatory arguments
std::string imageName = us::any_cast<std::string>(parsedArgs["i"]);
std::string refImage = us::any_cast<std::string>(parsedArgs["ref"]);
std::string outImage = us::any_cast<std::string>(parsedArgs["o"]);
bool originOnly = false;
// Show a help message
if ( parsedArgs.count("alignCentroid") || parsedArgs.count("a"))
{
originOnly = true;
}
try
{
mitk::Image::Pointer source = mitk::IOUtil::Load<mitk::Image>(refImage);
mitk::Image::Pointer target = mitk::IOUtil::Load<mitk::Image>(imageName);
if (originOnly)
{
// Calculate correction to align centroids
double c[3];
c[0] = source->GetGeometry()->GetOrigin()[0]
+ source->GetGeometry()->GetExtent(0)/2.0
- target->GetGeometry()->GetOrigin()[0]
- target->GetGeometry()->GetExtent(0)/2.0;
c[1] = source->GetGeometry()->GetOrigin()[1]
+ source->GetGeometry()->GetExtent(1)/2.0
- target->GetGeometry()->GetOrigin()[1]
- target->GetGeometry()->GetExtent(1)/2.0;
c[2] = source->GetGeometry()->GetOrigin()[2]
+ source->GetGeometry()->GetExtent(2)/2.0
- target->GetGeometry()->GetOrigin()[2]
- target->GetGeometry()->GetExtent(2)/2.0;
double newOrigin[3];
newOrigin[0] = target->GetGeometry()->GetOrigin()[0] +c[0];
newOrigin[1] = target->GetGeometry()->GetOrigin()[1] +c[1];
newOrigin[2] = target->GetGeometry()->GetOrigin()[2] +c[2];
target->GetGeometry()->SetOrigin(newOrigin);
}
else
{
mitk::BaseGeometry* s_geom = source->GetGeometry();
mitk::BaseGeometry* t_geom = target->GetGeometry();
t_geom->SetIndexToWorldTransform(s_geom->GetIndexToWorldTransform());
target->SetGeometry(t_geom);
}
mitk::IOUtil::Save(target, outImage);
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/Misc/DImp.cpp b/Modules/DiffusionCmdApps/Misc/DImp.cpp
index b9550b1..4bb5d25 100644
--- a/Modules/DiffusionCmdApps/Misc/DImp.cpp
+++ b/Modules/DiffusionCmdApps/Misc/DImp.cpp
@@ -1,72 +1,72 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkImageCast.h>
#include <mitkImage.h>
#include <mitkIOUtil.h>
#include "mitkDiffusionCommandLineParser.h"
#include <itksys/SystemTools.hxx>
#include <mitkPreferenceListReaderOptionsFunctor.h>
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("DIMP");
parser.setCategory("Preprocessing Tools");
parser.setDescription("TEMPORARY: Converts DICOM to other image types");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "input image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
// mandatory arguments
std::string imageName = us::any_cast<std::string>(parsedArgs["i"]);
std::string outImage = us::any_cast<std::string>(parsedArgs["o"]);
try
{
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images"}, {});
mitk::Image::Pointer source = mitk::IOUtil::Load<mitk::Image>(imageName, &functor);
std::string ext = itksys::SystemTools::GetFilenameExtension(outImage);
if (ext==".nii" || ext==".nii.gz")
mitk::IOUtil::Save(source, "DWI_NIFTI", outImage);
else
mitk::IOUtil::Save(source, outImage);
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/Misc/DReg.cpp b/Modules/DiffusionCmdApps/Misc/DReg.cpp
index 756a2a5..b5ff43e 100644
--- a/Modules/DiffusionCmdApps/Misc/DReg.cpp
+++ b/Modules/DiffusionCmdApps/Misc/DReg.cpp
@@ -1,222 +1,222 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkImageCast.h>
#include <mitkImage.h>
#include <mitkIOUtil.h>
#include "mitkDiffusionCommandLineParser.h"
#include <mitkMultiModalRigidDefaultRegistrationAlgorithm.h>
#include <mitkDiffusionPropertyHelper.h>
#include <mitkAlgorithmHelper.h>
#include <itkExtractDwiChannelFilter.h>
#include <mitkRegistrationHelper.h>
#include <mitkImageMappingHelper.h>
#include <itksys/SystemTools.hxx>
#include <mitkPreferenceListReaderOptionsFunctor.h>
#include <itkComposeImageFilter.h>
#include <mitkITKImageImport.h>
#include <mitkDiffusionImageCorrectionFilter.h>
#include <mitkDiffusionDataIOHelper.h>
typedef mitk::DiffusionPropertyHelper DPH;
mitk::Image::Pointer apply_transform(mitk::Image::Pointer moving, mitk::Image::Pointer fixed_single, mitk::MAPRegistrationWrapper::Pointer reg, bool resample)
{
mitk::Image::Pointer registered_image;
if (!resample)
{
registered_image = mitk::ImageMappingHelper::refineGeometry(moving, reg, true);
}
else
{
if (!mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(moving))
{
registered_image = mitk::ImageMappingHelper::map(moving, reg, false, 0, fixed_single->GetGeometry(), false, 0, mitk::ImageMappingInterpolator::BSpline_3);
}
else
{
typedef itk::Image<mitk::DiffusionPropertyHelper::DiffusionPixelType, 3> ITKDiffusionVolumeType;
typedef itk::ComposeImageFilter < ITKDiffusionVolumeType > ComposeFilterType;
auto composer = ComposeFilterType::New();
auto itkVectorImagePointer = mitk::DiffusionPropertyHelper::GetItkVectorImage(moving);
for (unsigned int i=0; i<itkVectorImagePointer->GetVectorLength(); ++i)
{
itk::ExtractDwiChannelFilter< short >::Pointer filter = itk::ExtractDwiChannelFilter< short >::New();
filter->SetInput( itkVectorImagePointer);
filter->SetChannelIndex(i);
filter->Update();
mitk::Image::Pointer gradientVolume = mitk::Image::New();
gradientVolume->InitializeByItk( filter->GetOutput() );
gradientVolume->SetImportChannel( filter->GetOutput()->GetBufferPointer() );
mitk::Image::Pointer registered_mitk_image = mitk::ImageMappingHelper::map(gradientVolume, reg, false, 0, fixed_single->GetGeometry(), false, 0, mitk::ImageMappingInterpolator::BSpline_3);
auto registered_itk_image = ITKDiffusionVolumeType::New();
mitk::CastToItkImage(registered_mitk_image, registered_itk_image);
composer->SetInput(i, registered_itk_image);
}
composer->Update();
registered_image = mitk::GrabItkImageMemory( composer->GetOutput() );
mitk::DiffusionPropertyHelper::CopyProperties(moving, registered_image, true);
typedef mitk::DiffusionImageCorrectionFilter CorrectionFilterType;
CorrectionFilterType::Pointer corrector = CorrectionFilterType::New();
corrector->SetImage( registered_image );
corrector->CorrectDirections( mitk::MITKRegistrationHelper::getAffineMatrix(reg, false)->GetMatrix().GetVnlMatrix() );
}
}
return registered_image;
}
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("DREG");
parser.setCategory("Preprocessing Tools");
parser.setDescription("TEMPORARY: Rigid registration of two images");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "f", mitkDiffusionCommandLineParser::String, "Fixed:", "fixed image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "m", mitkDiffusionCommandLineParser::String, "Moving:", "moving image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("resample", "", mitkDiffusionCommandLineParser::Bool, "Resample:", "resample moving image", false);
parser.addArgument("coreg", "", mitkDiffusionCommandLineParser::StringList, "", "additionally apply transform to these images", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
// mandatory arguments
std::string f = us::any_cast<std::string>(parsedArgs["f"]);
std::string m = us::any_cast<std::string>(parsedArgs["m"]);
std::string o = us::any_cast<std::string>(parsedArgs["o"]);
bool resample = false;
if (parsedArgs.count("resample"))
resample = true;
mitkDiffusionCommandLineParser::StringContainerType coreg;
if (parsedArgs.count("coreg"))
coreg = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["coreg"]);
try
{
typedef itk::Image< float, 3 > ItkFloatImageType;
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images"}, {});
mitk::Image::Pointer fixed = mitk::IOUtil::Load<mitk::Image>(f, &functor);
mitk::Image::Pointer moving = mitk::IOUtil::Load<mitk::Image>(m, &functor);
mitk::Image::Pointer fixed_single = fixed;
mitk::Image::Pointer moving_single = moving;
mitk::MultiModalRigidDefaultRegistrationAlgorithm< ItkFloatImageType >::Pointer algo = mitk::MultiModalRigidDefaultRegistrationAlgorithm< ItkFloatImageType >::New();
mitk::MITKAlgorithmHelper helper(algo);
if (mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(fixed))
{
DPH::ImageType::Pointer itkVectorImagePointer = DPH::ImageType::New();
mitk::CastToItkImage(fixed, itkVectorImagePointer);
itk::ExtractDwiChannelFilter< short >::Pointer filter = itk::ExtractDwiChannelFilter< short >::New();
filter->SetInput( itkVectorImagePointer);
filter->SetChannelIndex(0);
filter->Update();
fixed_single = mitk::Image::New();
fixed_single->InitializeByItk( filter->GetOutput() );
fixed_single->SetImportChannel( filter->GetOutput()->GetBufferPointer() );
}
if (mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(moving))
{
DPH::ImageType::Pointer itkVectorImagePointer = DPH::ImageType::New();
mitk::CastToItkImage(moving, itkVectorImagePointer);
itk::ExtractDwiChannelFilter< short >::Pointer filter = itk::ExtractDwiChannelFilter< short >::New();
filter->SetInput( itkVectorImagePointer);
filter->SetChannelIndex(0);
filter->Update();
moving_single = mitk::Image::New();
moving_single->InitializeByItk( filter->GetOutput() );
moving_single->SetImportChannel( filter->GetOutput()->GetBufferPointer() );
}
helper.SetData(moving_single, fixed_single);
mitk::MAPRegistrationWrapper::Pointer reg = helper.GetMITKRegistrationWrapper();
mitk::Image::Pointer registered_image = apply_transform(moving, fixed_single, reg, resample);
if (mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(registered_image))
{
mitk::DiffusionPropertyHelper::InitializeImage( registered_image );
std::string file_extension = itksys::SystemTools::GetFilenameExtension(o);
if (file_extension==".nii" || file_extension==".nii.gz")
mitk::IOUtil::Save(registered_image, "DWI_NIFTI", o);
else
mitk::IOUtil::Save(registered_image, o);
}
else
mitk::IOUtil::Save(registered_image, o);
std::string path = ist::GetFilenamePath(o) + "/";
std::vector< std::string > file_names;
auto coreg_images = mitk::DiffusionDataIOHelper::load_mitk_images(coreg, &file_names);
for (unsigned int i=0; i<coreg_images.size(); ++i)
{
std::string ext = ist::GetFilenameExtension(file_names.at(i));
std::string out_name = path + ist::GetFilenameWithoutExtension(file_names.at(i)) + "_registered" + ext;
registered_image = apply_transform(coreg_images.at(i), fixed_single, reg, resample);
if (mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(registered_image))
{
mitk::DiffusionPropertyHelper::InitializeImage( registered_image );
if (ext==".nii" || ext==".nii.gz")
mitk::IOUtil::Save(registered_image, "DWI_NIFTI", out_name);
else
mitk::IOUtil::Save(registered_image, out_name);
}
else
mitk::IOUtil::Save(registered_image, out_name);
}
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/Misc/DiffusionDICOMLoader.cpp b/Modules/DiffusionCmdApps/Misc/DiffusionDICOMLoader.cpp
index f05718d..0abc985 100644
--- a/Modules/DiffusionCmdApps/Misc/DiffusionDICOMLoader.cpp
+++ b/Modules/DiffusionCmdApps/Misc/DiffusionDICOMLoader.cpp
@@ -1,315 +1,315 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkBaseData.h"
#include <mitkDiffusionPropertyHelper.h>
#include <mitkImageCast.h>
#include <mitkITKImageImport.h>
#include "mitkDiffusionCommandLineParser.h"
#include <itksys/SystemTools.hxx>
#include <itksys/Directory.hxx>
#include "mitkDiffusionDICOMFileReader.h"
#include "mitkSortByImagePositionPatient.h"
#include "mitkDICOMTagBasedSorter.h"
#include "mitkDICOMSortByTag.h"
#include "itkMergeDiffusionImagesFilter.h"
#include <mitkIOUtil.h>
static mitk::StringList& GetInputFilenames()
{
static mitk::StringList inputs;
return inputs;
}
// FIXME slash at the end
void SetInputFileNames( std::string input_directory )
{
// I. Get all files in directory
itksys::Directory input;
input.Load( input_directory.c_str() );
// II. Push back files
mitk::StringList inputlist;//, mergedlist;
for( unsigned long idx=0; idx<input.GetNumberOfFiles(); idx++)
{
if( ! itksys::SystemTools::FileIsDirectory( input.GetFile(idx)) )
{
std::string fullpath = input_directory + "/" + std::string( input.GetFile(idx) );
//inputlist.push_back( itksys::SystemTools::ConvertToOutputPath( fullpath.c_str() ) );
inputlist.push_back( fullpath.c_str() );
MITK_INFO("dicom.loader.inputdir.addfile") << input.GetFile(idx);
}
}
/*mergedlist.reserve( GetInputFilenames().size() + inputlist.size() );
mergedlist.insert( mergedlist.end(), GetInputFilenames().begin(), GetInputFilenames().end() );
mergedlist.insert( mergedlist.end(), inputlist.begin(), inputlist.end() );*/
GetInputFilenames() = inputlist;//mergedlist;
MITK_INFO("dicom.loader.setinputfiles.end") << "[]";
}
static mitk::Image::Pointer ReadInDICOMFiles( mitk::StringList& input_files, const std::string &)
{
mitk::DiffusionDICOMFileReader::Pointer gdcmReader = mitk::DiffusionDICOMFileReader::New();
//mitk::ClassicDICOMSeriesReader::Pointer gdcmReader = mitk::ClassicDICOMSeriesReader::New();
/* mitk::DICOMTagBasedSorter::Pointer tagSorter = mitk::DICOMTagBasedSorter::New();
// Use tags as in Qmitk
// all the things that split by tag in DicomSeriesReader
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0010) ); // Number of Rows
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0011) ); // Number of Columns
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0030) ); // Pixel Spacing
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0018, 0x1164) ); // Imager Pixel Spacing
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0020, 0x0037) ); // Image Orientation (Patient) // TODO add tolerance parameter (l. 1572 of original code)
// TODO handle as real vectors! cluster with configurable errors!
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0020, 0x000e) ); // Series Instance UID
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0018, 0x0050) ); // Slice Thickness
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0008) ); // Number of Frames
//tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0020, 0x0052) ); // Frame of Reference UID
// gdcmReader->AddSortingElement( tagSorter );
//mitk::DICOMFileReaderTestHelper::TestOutputsContainInputs( gdcmReader );
mitk::DICOMSortCriterion::ConstPointer sorting =
mitk::SortByImagePositionPatient::New( // Image Position (Patient)
//mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0020, 0x0013), // instance number
mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0020, 0x0012), // aqcuisition number
mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0008, 0x0032), // aqcuisition time
mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0018, 0x1060), // trigger time
mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0008, 0x0018) // SOP instance UID (last resort, not really meaningful but decides clearly)
).GetPointer()
).GetPointer()
).GetPointer()
).GetPointer()
// ).GetPointer()
).GetPointer();
tagSorter->SetSortCriterion( sorting );
// mosaic
//gdcmReader->SetResolveMosaic( this->m_Controls->m_SplitMosaicCheckBox->isChecked() );
gdcmReader->AddSortingElement( tagSorter );*/
gdcmReader->SetInputFiles( input_files );
try
{
gdcmReader->AnalyzeInputFiles();
}
catch( const itk::ExceptionObject &e)
{
MITK_ERROR << "Failed to analyze data. " << e.what();
}
catch( const std::exception &se)
{
MITK_ERROR << "Std Exception " << se.what();
}
gdcmReader->LoadImages();
mitk::Image::Pointer loaded_image = gdcmReader->GetOutput(0).GetMitkImage();
return loaded_image;
}
typedef short DiffusionPixelType;
typedef itk::VectorImage<DiffusionPixelType,3> DwiImageType;
typedef DwiImageType::PixelType DwiPixelType;
typedef DwiImageType::RegionType DwiRegionType;
typedef std::vector< DwiImageType::Pointer > DwiImageContainerType;
typedef mitk::Image DiffusionImageType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientContainerType;
typedef std::vector< GradientContainerType::Pointer > GradientListContainerType;
void SearchForInputInSubdirs( std::string root_directory, std::string subdir_prefix , std::vector<DiffusionImageType::Pointer>& output_container)
{
// I. Get all dirs in directory
itksys::Directory rootdir;
rootdir.Load( root_directory.c_str() );
MITK_INFO("dicom.loader.setinputdirs.start") << "Prefix = " << subdir_prefix;
for( unsigned int idx=0; idx<rootdir.GetNumberOfFiles(); idx++)
{
std::string current_path = rootdir.GetFile(idx);
std::string directory_path = std::string(rootdir.GetPath()) + current_path;
MITK_INFO("dicom.loader.inputrootdir.test") << "ProbePath: " << current_path << "\n"
<< "escaped to " << itksys::SystemTools::ConvertToOutputPath( directory_path.c_str() );
MITK_INFO("dicom.loader.inputrootdir.test") << " IsDirectory: " << itksys::SystemTools::FileIsDirectory( directory_path.c_str() )
<< " StartsWith: " << itksys::SystemTools::StringStartsWith( current_path.c_str(), subdir_prefix.c_str() );
// test for prefix
if( itksys::SystemTools::FileIsDirectory( directory_path.c_str() )
&& itksys::SystemTools::StringStartsWith( current_path.c_str(), subdir_prefix.c_str() )
)
{
MITK_INFO("dicom.loader.inputrootdir.searchin") << directory_path;
SetInputFileNames( directory_path.c_str() );
MITK_INFO("dicom.loader.inputrootdir.preload") << "[]" ;
DiffusionImageType::Pointer dwi = ReadInDICOMFiles( GetInputFilenames(), "" );
output_container.push_back( dwi );
}
}
MITK_INFO("dicom.loader.setinputdirs.end") << "[]";
}
using namespace mitk;
/**
* Read DICOM Files through the new (refactored) Diffusion DICOM Loader. It serves also as a first test of the new functionality, it will replace the
* current loading mechanism after the necessary parts are merged into the master branch.
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setArgumentPrefix("--", "-");
parser.setTitle("Diffusion Dicom Loader");
parser.setCategory("Preprocessing Tools");
parser.setDescription("Loads Diffusion Dicom files.");
parser.setContributor("MIC");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input Directory" ,"input directory containing dicom files", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output File Name", "output file", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("dwprefix", "p", mitkDiffusionCommandLineParser::String, "Recursive Scan Prefix", "prefix for subfolders search rootdir is specified by the 'inputdir' argument value", us::Any(), true);
parser.addArgument("dryrun", "s", mitkDiffusionCommandLineParser::Bool, "Dry run","do not read, only look for input files ", us::Any(), true );
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
{
return EXIT_FAILURE;
}
std::string inputDirectory = us::any_cast<std::string>( parsedArgs["i"] );
MITK_INFO << "Loading data from directory: " << inputDirectory;
// retrieve the prefix flag (if set)
bool search_for_subdirs = false;
std::string subdir_prefix;
if( parsedArgs.count("dwprefix"))
{
subdir_prefix = us::any_cast<std::string>( parsedArgs["dwprefix"] );
if (subdir_prefix != "")
{
MITK_INFO << "Prefix specified, will search for subdirs in the input directory!";
search_for_subdirs = true;
}
}
// retrieve the output
std::string outputFile = us::any_cast< std::string >( parsedArgs["o"] );
// if the executable is called with a single directory, just parse the given folder for files and read them into a diffusion image
if( !search_for_subdirs )
{
SetInputFileNames( inputDirectory );
MITK_INFO << "Got " << GetInputFilenames().size() << " input files.";
mitk::Image::Pointer d_img = ReadInDICOMFiles( GetInputFilenames(), outputFile );
try
{
mitk::IOUtil::Save(d_img, outputFile.c_str());
}
catch( const itk::ExceptionObject& e)
{
MITK_ERROR << "Failed to write out the output file. \n\t Reason : ITK Exception " << e.what();
}
}
// if the --dwprefix flag is set, then we have to look for the directories, load each of them separately and afterwards merge the images
else
{
std::vector<mitk::Image::Pointer> output_container;
SearchForInputInSubdirs( inputDirectory, subdir_prefix, output_container );
// final output image
mitk::Image::Pointer image = mitk::Image::New();
if( output_container.size() > 1 )
{
DwiImageContainerType imageContainer;
GradientListContainerType gradientListContainer;
std::vector< double > bValueContainer;
for ( std::vector< mitk::Image::Pointer >::iterator dwi = output_container.begin();
dwi != output_container.end(); ++dwi )
{
mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New();
mitk::CastToItkImage(*dwi, itkVectorImagePointer);
imageContainer.push_back(itkVectorImagePointer);
gradientListContainer.push_back( mitk::DiffusionPropertyHelper::GetGradientContainer(*dwi));
bValueContainer.push_back( mitk::DiffusionPropertyHelper::GetReferenceBValue(*dwi));
}
typedef itk::MergeDiffusionImagesFilter<short> FilterType;
FilterType::Pointer filter = FilterType::New();
filter->SetImageVolumes(imageContainer);
filter->SetGradientLists(gradientListContainer);
filter->SetBValues(bValueContainer);
filter->Update();
vnl_matrix_fixed< double, 3, 3 > mf; mf.set_identity();
image = mitk::GrabItkImageMemory( filter->GetOutput() );
mitk::DiffusionPropertyHelper::SetGradientContainer(image, filter->GetOutputGradients());
mitk::DiffusionPropertyHelper::SetReferenceBValue(image, filter->GetB_Value());
mitk::DiffusionPropertyHelper::SetMeasurementFrame(image, mf);
mitk::DiffusionPropertyHelper::InitializeImage( image );
}
// just output the image if there was only one folder found
else
{
image = output_container.at(0);
}
MITK_INFO("dicom.import.writeout") << " [OutputFile] " << outputFile.c_str();
try
{
mitk::IOUtil::Save(image, outputFile.c_str());
}
catch( const itk::ExceptionObject& e)
{
MITK_ERROR << "Failed to write out the output file. \n\t Reason : ITK Exception " << e.what();
}
}
return 1;
}
diff --git a/Modules/DiffusionCmdApps/Misc/DmriDenoising.cpp b/Modules/DiffusionCmdApps/Misc/DmriDenoising.cpp
index da3b464..4f5a430 100644
--- a/Modules/DiffusionCmdApps/Misc/DmriDenoising.cpp
+++ b/Modules/DiffusionCmdApps/Misc/DmriDenoising.cpp
@@ -1,234 +1,234 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkImageCast.h>
#include <mitkImage.h>
#include <mitkIOUtil.h>
#include "mitkDiffusionCommandLineParser.h"
#include <mitkPreferenceListReaderOptionsFunctor.h>
#include <itksys/SystemTools.hxx>
#include <itkTotalVariationDenoisingImageFilter.h>
#include <itkNonLocalMeansDenoisingFilter.h>
#include <itkDiscreteGaussianImageFilter.h>
#include <itkPatchBasedDenoisingImageFilter.h>
#include <itkVectorImageToImageFilter.h>
#include <itkComposeImageFilter.h>
#include <mitkDiffusionPropertyHelper.h>
#include <itkGaussianRandomSpatialNeighborSubsampler.h>
#include <mitkITKImageImport.h>
#include <mitkProperties.h>
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("DmriDenoising");
parser.setCategory("Preprocessing Tools");
parser.setDescription("dMRI denoising tool");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.beginGroup("1. Mandatory arguments:");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "input image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("type", "", mitkDiffusionCommandLineParser::Int, "Type:", "0 (TotalVariation), 1 (Gauss), 2 (NLM)", 0);
parser.endGroup();
parser.beginGroup("2. Total variation parameters:");
parser.addArgument("tv_iterations", "", mitkDiffusionCommandLineParser::Int, "Iterations:", "", 1);
parser.addArgument("lambda", "", mitkDiffusionCommandLineParser::Float, "Lambda:", "", 0.1);
parser.endGroup();
parser.beginGroup("3. Gauss parameters:");
parser.addArgument("variance", "", mitkDiffusionCommandLineParser::Float, "Variance:", "", 1.0);
parser.endGroup();
parser.beginGroup("4. NLM parameters:");
parser.addArgument("nlm_iterations", "", mitkDiffusionCommandLineParser::Int, "Iterations:", "", 4);
parser.addArgument("sampling_radius", "", mitkDiffusionCommandLineParser::Int, "Sampling radius:", "", 4);
parser.addArgument("patch_radius", "", mitkDiffusionCommandLineParser::Int, "Patch radius:", "", 1);
parser.addArgument("num_patches", "", mitkDiffusionCommandLineParser::Int, "Num. patches:", "", 10);
parser.endGroup();
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
// mandatory arguments
std::string imageName = us::any_cast<std::string>(parsedArgs["i"]);
std::string outImage = us::any_cast<std::string>(parsedArgs["o"]);
int type = 0;
if (parsedArgs.count("type"))
type = us::any_cast<int>(parsedArgs["type"]);
int tv_iterations = 1;
if (parsedArgs.count("tv_iterations"))
tv_iterations = us::any_cast<int>(parsedArgs["tv_iterations"]);
float lambda = 0.1;
if (parsedArgs.count("lambda"))
lambda = us::any_cast<float>(parsedArgs["lambda"]);
float variance = 1.0;
if (parsedArgs.count("variance"))
variance = us::any_cast<float>(parsedArgs["variance"]);
int nlm_iterations = 4;
if (parsedArgs.count("nlm_iterations"))
nlm_iterations = us::any_cast<int>(parsedArgs["nlm_iterations"]);
int sampling_radius = 4;
if (parsedArgs.count("sampling_radius"))
sampling_radius = us::any_cast<int>(parsedArgs["sampling_radius"]);
int patch_radius = 1;
if (parsedArgs.count("patch_radius"))
patch_radius = us::any_cast<int>(parsedArgs["patch_radius"]);
int num_patches = 10;
if (parsedArgs.count("num_patches"))
num_patches = us::any_cast<int>(parsedArgs["num_patches"]);
try
{
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images"}, {});
mitk::Image::Pointer input_image = mitk::IOUtil::Load<mitk::Image>(imageName, &functor);
typedef short DiffusionPixelType;
typedef itk::VectorImage<DiffusionPixelType, 3> DwiImageType;
typedef itk::Image<DiffusionPixelType, 3> DwiVolumeType;
typedef itk::DiscreteGaussianImageFilter < DwiVolumeType, DwiVolumeType > GaussianFilterType;
typedef itk::PatchBasedDenoisingImageFilter < DwiVolumeType, DwiVolumeType > NlmFilterType;
typedef itk::VectorImageToImageFilter < DiffusionPixelType > ExtractFilterType;
typedef itk::ComposeImageFilter < itk::Image<DiffusionPixelType, 3> > ComposeFilterType;
if (!mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(input_image))
mitkThrow() << "Input is not a diffusion-weighted image!";
DwiImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::GetItkVectorImage(input_image);
mitk::Image::Pointer denoised_image = nullptr;
switch (type)
{
case 0:
{
ComposeFilterType::Pointer composer = ComposeFilterType::New();
for (unsigned int i=0; i<itkVectorImagePointer->GetVectorLength(); ++i)
{
ExtractFilterType::Pointer extractor = ExtractFilterType::New();
extractor->SetInput( itkVectorImagePointer );
extractor->SetIndex( i );
extractor->Update();
DwiVolumeType::Pointer gradient_volume = extractor->GetOutput();
itk::TotalVariationDenoisingImageFilter< DwiVolumeType, DwiVolumeType >::Pointer filter = itk::TotalVariationDenoisingImageFilter< DwiVolumeType, DwiVolumeType >::New();
filter->SetInput(gradient_volume);
filter->SetLambda(lambda);
filter->SetNumberIterations(tv_iterations);
filter->Update();
composer->SetInput(i, filter->GetOutput());
}
composer->Update();
denoised_image = mitk::GrabItkImageMemory(composer->GetOutput());
break;
}
case 1:
{
ExtractFilterType::Pointer extractor = ExtractFilterType::New();
extractor->SetInput( itkVectorImagePointer );
ComposeFilterType::Pointer composer = ComposeFilterType::New();
for (unsigned int i = 0; i < itkVectorImagePointer->GetVectorLength(); ++i)
{
extractor->SetIndex(i);
extractor->Update();
GaussianFilterType::Pointer filter = GaussianFilterType::New();
filter->SetVariance(variance);
filter->SetInput(extractor->GetOutput());
filter->Update();
composer->SetInput(i, filter->GetOutput());
}
composer->Update();
denoised_image = mitk::GrabItkImageMemory(composer->GetOutput());
break;
}
case 2:
{
typedef itk::Statistics::GaussianRandomSpatialNeighborSubsampler< NlmFilterType::PatchSampleType, DwiVolumeType::RegionType > SamplerType;
// sampling the image to find similar patches
SamplerType::Pointer sampler = SamplerType::New();
sampler->SetRadius( sampling_radius );
sampler->SetVariance( sampling_radius*sampling_radius );
sampler->SetNumberOfResultsRequested( num_patches );
MITK_INFO << "Starting NLM denoising";
ExtractFilterType::Pointer extractor = ExtractFilterType::New();
extractor->SetInput( itkVectorImagePointer );
ComposeFilterType::Pointer composer = ComposeFilterType::New();
for (unsigned int i = 0; i < itkVectorImagePointer->GetVectorLength(); ++i)
{
extractor->SetIndex(i);
extractor->Update();
NlmFilterType::Pointer filter = NlmFilterType::New();
filter->SetInput(extractor->GetOutput());
filter->SetPatchRadius(patch_radius);
filter->SetNoiseModel(NlmFilterType::RICIAN);
filter->UseSmoothDiscPatchWeightsOn();
filter->UseFastTensorComputationsOn();
filter->SetNumberOfIterations(nlm_iterations);
filter->SetSmoothingWeight( 1 );
filter->SetKernelBandwidthEstimation(true);
filter->SetSampler( sampler );
filter->Update();
composer->SetInput(i, filter->GetOutput());
MITK_INFO << "Gradient " << i << " finished";
}
composer->Update();
denoised_image = mitk::GrabItkImageMemory(composer->GetOutput());
break;
}
}
mitk::DiffusionPropertyHelper::SetGradientContainer(denoised_image, mitk::DiffusionPropertyHelper::GetGradientContainer(input_image));
mitk::DiffusionPropertyHelper::SetReferenceBValue(denoised_image, mitk::DiffusionPropertyHelper::GetReferenceBValue(input_image));
mitk::DiffusionPropertyHelper::InitializeImage( denoised_image );
std::string ext = itksys::SystemTools::GetFilenameExtension(outImage);
if (ext==".nii" || ext==".nii.gz")
mitk::IOUtil::Save(denoised_image, "DWI_NIFTI", outImage);
else
mitk::IOUtil::Save(denoised_image, outImage);
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/Misc/FileFormatConverter.cpp b/Modules/DiffusionCmdApps/Misc/FileFormatConverter.cpp
index 7204542..fd2b1a0 100644
--- a/Modules/DiffusionCmdApps/Misc/FileFormatConverter.cpp
+++ b/Modules/DiffusionCmdApps/Misc/FileFormatConverter.cpp
@@ -1,80 +1,80 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkImageCast.h>
#include <mitkImage.h>
#include <mitkIOUtil.h>
#include "mitkDiffusionCommandLineParser.h"
#include <mitkPreferenceListReaderOptionsFunctor.h>
#include <mitkFiberBundle.h>
/*!
\brief Load image and save as specified file type.
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Format Converter");
parser.setCategory("Preprocessing Tools");
parser.setDescription("Load image and save as specified file type.");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "input file", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output file", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
// mandatory arguments
std::string inName = us::any_cast<std::string>(parsedArgs["i"]);
std::string outName = us::any_cast<std::string>(parsedArgs["o"]);
try
{
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images"}, {});
std::vector<mitk::BaseData::Pointer> baseData = mitk::IOUtil::Load(inName, &functor);
if ( baseData.size()>0 && dynamic_cast<mitk::Image*>(baseData[0].GetPointer()) )
{
mitk::IOUtil::Save(dynamic_cast<mitk::Image*>(baseData[0].GetPointer()), outName.c_str());
}
else if ( baseData.size()>0 && dynamic_cast<mitk::FiberBundle*>(baseData[0].GetPointer()) )
{
mitk::IOUtil::Save(dynamic_cast<mitk::FiberBundle*>(baseData[0].GetPointer()) ,outName.c_str());
}
else
std::cout << "File type currently not supported!";
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/Misc/FlipPeaks.cpp b/Modules/DiffusionCmdApps/Misc/FlipPeaks.cpp
index 01b992f..6d60810 100644
--- a/Modules/DiffusionCmdApps/Misc/FlipPeaks.cpp
+++ b/Modules/DiffusionCmdApps/Misc/FlipPeaks.cpp
@@ -1,104 +1,104 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkImageCast.h>
#include <mitkImage.h>
#include <mitkIOUtil.h>
#include "mitkDiffusionCommandLineParser.h"
#include <mitkPeakImage.h>
#include <itkFlipPeaksFilter.h>
#include <mitkImageToItk.h>
#include <mitkPreferenceListReaderOptionsFunctor.h>
/*!
\brief Copies transformation matrix of one image to another
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Flip Peaks");
parser.setCategory("Preprocessing Tools");
parser.setDescription("Flips the peaks of the input peak image along the given dimensions.");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input", "input image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output", "output image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("", "x", mitkDiffusionCommandLineParser::Bool, "Flip x", "flip along x-axis");
parser.addArgument("", "y", mitkDiffusionCommandLineParser::Bool, "Flip y", "flip along y-axis");
parser.addArgument("", "z", mitkDiffusionCommandLineParser::Bool, "Flip z", "flip along z-axis");
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
std::string imageName = us::any_cast<std::string>(parsedArgs["i"]);
std::string outImage = us::any_cast<std::string>(parsedArgs["o"]);
bool x = false;
if (parsedArgs.count("x"))
x = us::any_cast<bool>(parsedArgs["x"]);
bool y = false;
if (parsedArgs.count("y"))
y = us::any_cast<bool>(parsedArgs["y"]);
bool z = false;
if (parsedArgs.count("z"))
z = us::any_cast<bool>(parsedArgs["z"]);
try
{
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Peak Image"}, {});
mitk::PeakImage::Pointer image = mitk::IOUtil::Load<mitk::PeakImage>(imageName, &functor);
typedef mitk::ImageToItk< mitk::PeakImage::ItkPeakImageType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(image);
caster->Update();
mitk::PeakImage::ItkPeakImageType::Pointer itkImg = caster->GetOutput();
itk::FlipPeaksFilter< float >::Pointer flipper = itk::FlipPeaksFilter< float >::New();
flipper->SetInput(itkImg);
flipper->SetFlipX(x);
flipper->SetFlipY(y);
flipper->SetFlipZ(z);
flipper->Update();
mitk::Image::Pointer resultImage = dynamic_cast<mitk::Image*>(mitk::PeakImage::New().GetPointer());
mitk::CastToMitkImage(flipper->GetOutput(), resultImage);
resultImage->SetVolume(flipper->GetOutput()->GetBufferPointer());
mitk::IOUtil::Save(resultImage, outImage);
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/Misc/HeadMotionCorrection.cpp b/Modules/DiffusionCmdApps/Misc/HeadMotionCorrection.cpp
index 2264915..46c5d8d 100644
--- a/Modules/DiffusionCmdApps/Misc/HeadMotionCorrection.cpp
+++ b/Modules/DiffusionCmdApps/Misc/HeadMotionCorrection.cpp
@@ -1,78 +1,78 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkImageCast.h>
#include <mitkImage.h>
#include <mitkIOUtil.h>
#include "mitkDiffusionCommandLineParser.h"
#include <mitkDWIHeadMotionCorrectionFilter.h>
#include <mitkPreferenceListReaderOptionsFunctor.h>
#include <itksys/SystemTools.hxx>
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("HeadMotionCorrection");
parser.setCategory("Preprocessing Tools");
parser.setDescription("Simple affine head-motion correction tool");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "input image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
// mandatory arguments
std::string imageName = us::any_cast<std::string>(parsedArgs["i"]);
std::string outImage = us::any_cast<std::string>(parsedArgs["o"]);
try
{
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images"}, {});
mitk::Image::Pointer in_image = mitk::IOUtil::Load<mitk::Image>(imageName, &functor);
mitk::DWIHeadMotionCorrectionFilter::Pointer registerer = mitk::DWIHeadMotionCorrectionFilter::New();
registerer->SetInput(in_image);
registerer->Update();
mitk::Image::Pointer out_image = registerer->GetCorrectedImage();
std::string ext = itksys::SystemTools::GetFilenameExtension(outImage);
if (ext==".nii" || ext==".nii.gz")
mitk::IOUtil::Save(out_image, "DWI_NIFTI", outImage);
else
mitk::IOUtil::Save(out_image, outImage);
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/Misc/ImageResampler.cpp b/Modules/DiffusionCmdApps/Misc/ImageResampler.cpp
index 249e67c..ba7ff96 100644
--- a/Modules/DiffusionCmdApps/Misc/ImageResampler.cpp
+++ b/Modules/DiffusionCmdApps/Misc/ImageResampler.cpp
@@ -1,420 +1,420 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkDiffusionCommandLineParser.h"
#include <mitkIOUtil.h>
#include <mitkRegistrationWrapper.h>
#include <mitkImage.h>
#include <mitkImageCast.h>
#include <mitkITKImageImport.h>
#include <mitkImageTimeSelector.h>
#include <mitkDiffusionPropertyHelper.h>
#include <mitkProperties.h>
// ITK
#include <itksys/SystemTools.hxx>
#include <itkDirectory.h>
#include "itkLinearInterpolateImageFunction.h"
#include "itkWindowedSincInterpolateImageFunction.h"
#include "itkNearestNeighborInterpolateImageFunction.h"
#include "itkIdentityTransform.h"
#include "itkResampleImageFilter.h"
#include "itkResampleDwiImageFilter.h"
typedef itk::Image<double, 3> InputImageType;
typedef itk::Image<unsigned char, 3> BinaryImageType;
static mitk::Image::Pointer TransformToReference(mitk::Image *reference, mitk::Image *moving, bool sincInterpol = false, bool nn = false)
{
// Convert to itk Images
// Identify Transform
typedef itk::IdentityTransform<double, 3> T_Transform;
T_Transform::Pointer _pTransform = T_Transform::New();
_pTransform->SetIdentity();
typedef itk::WindowedSincInterpolateImageFunction< InputImageType, 3> WindowedSincInterpolatorType;
WindowedSincInterpolatorType::Pointer sinc_interpolator = WindowedSincInterpolatorType::New();
typedef itk::LinearInterpolateImageFunction< InputImageType> LinearInterpolateImageFunctionType;
LinearInterpolateImageFunctionType::Pointer lin_interpolator = LinearInterpolateImageFunctionType::New();
typedef itk::NearestNeighborInterpolateImageFunction< BinaryImageType> NearestNeighborInterpolateImageFunctionType;
NearestNeighborInterpolateImageFunctionType::Pointer nn_interpolator = NearestNeighborInterpolateImageFunctionType::New();
if (!nn)
{
InputImageType::Pointer itkReference = InputImageType::New();
InputImageType::Pointer itkMoving = InputImageType::New();
mitk::CastToItkImage(reference,itkReference);
mitk::CastToItkImage(moving,itkMoving);
typedef itk::ResampleImageFilter<InputImageType, InputImageType> ResampleFilterType;
ResampleFilterType::Pointer resampler = ResampleFilterType::New();
resampler->SetInput(itkMoving);
resampler->SetReferenceImage( itkReference );
resampler->UseReferenceImageOn();
resampler->SetTransform(_pTransform);
if ( sincInterpol)
resampler->SetInterpolator(sinc_interpolator);
else
resampler->SetInterpolator(lin_interpolator);
resampler->Update();
// Convert back to mitk
mitk::Image::Pointer result = mitk::Image::New();
result->InitializeByItk(resampler->GetOutput());
GrabItkImageMemory( resampler->GetOutput() , result );
return result;
}
BinaryImageType::Pointer itkReference = BinaryImageType::New();
BinaryImageType::Pointer itkMoving = BinaryImageType::New();
mitk::CastToItkImage(reference,itkReference);
mitk::CastToItkImage(moving,itkMoving);
typedef itk::ResampleImageFilter<BinaryImageType, BinaryImageType> ResampleFilterType;
ResampleFilterType::Pointer resampler = ResampleFilterType::New();
resampler->SetInput(itkMoving);
resampler->SetReferenceImage( itkReference );
resampler->UseReferenceImageOn();
resampler->SetTransform(_pTransform);
resampler->SetInterpolator(nn_interpolator);
resampler->Update();
// Convert back to mitk
mitk::Image::Pointer result = mitk::Image::New();
result->InitializeByItk(resampler->GetOutput());
GrabItkImageMemory( resampler->GetOutput() , result );
return result;
}
static std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems)
{
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim))
{
elems.push_back(item);
}
return elems;
}
static std::vector<std::string> split(const std::string &s, char delim)
{
std::vector < std::string > elems;
return split(s, delim, elems);
}
static mitk::Image::Pointer ResampleBySpacing(mitk::Image *input, float *spacing, bool useLinInt = true, bool useNN = false)
{
if (!useNN)
{
InputImageType::Pointer itkImage = InputImageType::New();
CastToItkImage(input,itkImage);
/**
* 1) Resampling
*
*/
// Identity transform.
// We don't want any transform on our image except rescaling which is not
// specified by a transform but by the input/output spacing as we will see
// later.
// So no transform will be specified.
typedef itk::IdentityTransform<double, 3> T_Transform;
// The resampler type itself.
typedef itk::ResampleImageFilter<InputImageType, InputImageType> T_ResampleFilter;
// Prepare the resampler.
// Instantiate the transform and specify it should be the id transform.
T_Transform::Pointer _pTransform = T_Transform::New();
_pTransform->SetIdentity();
// Instantiate the resampler. Wire in the transform and the interpolator.
T_ResampleFilter::Pointer _pResizeFilter = T_ResampleFilter::New();
// Specify the input.
_pResizeFilter->SetInput(itkImage);
_pResizeFilter->SetTransform(_pTransform);
// Set the output origin.
_pResizeFilter->SetOutputOrigin(itkImage->GetOrigin());
// Compute the size of the output.
// The size (# of pixels) in the output is recomputed using
// the ratio of the input and output sizes.
InputImageType::SpacingType inputSpacing = itkImage->GetSpacing();
InputImageType::SpacingType outputSpacing;
const InputImageType::RegionType& inputSize = itkImage->GetLargestPossibleRegion();
InputImageType::SizeType outputSize;
typedef InputImageType::SizeType::SizeValueType SizeValueType;
// Set the output spacing.
outputSpacing[0] = spacing[0];
outputSpacing[1] = spacing[1];
outputSpacing[2] = spacing[2];
outputSize[0] = static_cast<SizeValueType>(inputSize.GetSize()[0] * inputSpacing[0] / outputSpacing[0] + .5);
outputSize[1] = static_cast<SizeValueType>(inputSize.GetSize()[1] * inputSpacing[1] / outputSpacing[1] + .5);
outputSize[2] = static_cast<SizeValueType>(inputSize.GetSize()[2] * inputSpacing[2] / outputSpacing[2] + .5);
_pResizeFilter->SetOutputSpacing(outputSpacing);
_pResizeFilter->SetSize(outputSize);
typedef itk::LinearInterpolateImageFunction< InputImageType > LinearInterpolatorType;
LinearInterpolatorType::Pointer lin_interpolator = LinearInterpolatorType::New();
typedef itk::WindowedSincInterpolateImageFunction< InputImageType, 4> WindowedSincInterpolatorType;
WindowedSincInterpolatorType::Pointer sinc_interpolator = WindowedSincInterpolatorType::New();
if (useLinInt)
_pResizeFilter->SetInterpolator(lin_interpolator);
else
_pResizeFilter->SetInterpolator(sinc_interpolator);
_pResizeFilter->Update();
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk(_pResizeFilter->GetOutput());
mitk::GrabItkImageMemory( _pResizeFilter->GetOutput(), image);
return image;
}
BinaryImageType::Pointer itkImage = BinaryImageType::New();
CastToItkImage(input,itkImage);
/**
* 1) Resampling
*
*/
// Identity transform.
// We don't want any transform on our image except rescaling which is not
// specified by a transform but by the input/output spacing as we will see
// later.
// So no transform will be specified.
typedef itk::IdentityTransform<double, 3> T_Transform;
// The resampler type itself.
typedef itk::ResampleImageFilter<BinaryImageType, BinaryImageType> T_ResampleFilter;
// Prepare the resampler.
// Instantiate the transform and specify it should be the id transform.
T_Transform::Pointer _pTransform = T_Transform::New();
_pTransform->SetIdentity();
// Instantiate the resampler. Wire in the transform and the interpolator.
T_ResampleFilter::Pointer _pResizeFilter = T_ResampleFilter::New();
// Specify the input.
_pResizeFilter->SetInput(itkImage);
_pResizeFilter->SetTransform(_pTransform);
// Set the output origin.
_pResizeFilter->SetOutputOrigin(itkImage->GetOrigin());
// Compute the size of the output.
// The size (# of pixels) in the output is recomputed using
// the ratio of the input and output sizes.
BinaryImageType::SpacingType inputSpacing = itkImage->GetSpacing();
BinaryImageType::SpacingType outputSpacing;
const BinaryImageType::RegionType& inputSize = itkImage->GetLargestPossibleRegion();
BinaryImageType::SizeType outputSize;
typedef BinaryImageType::SizeType::SizeValueType SizeValueType;
// Set the output spacing.
outputSpacing[0] = spacing[0];
outputSpacing[1] = spacing[1];
outputSpacing[2] = spacing[2];
outputSize[0] = static_cast<SizeValueType>(inputSize.GetSize()[0] * inputSpacing[0] / outputSpacing[0] + .5);
outputSize[1] = static_cast<SizeValueType>(inputSize.GetSize()[1] * inputSpacing[1] / outputSpacing[1] + .5);
outputSize[2] = static_cast<SizeValueType>(inputSize.GetSize()[2] * inputSpacing[2] / outputSpacing[2] + .5);
_pResizeFilter->SetOutputSpacing(outputSpacing);
_pResizeFilter->SetSize(outputSize);
typedef itk::NearestNeighborInterpolateImageFunction< BinaryImageType> NearestNeighborInterpolateImageType;
NearestNeighborInterpolateImageType::Pointer nn_interpolator = NearestNeighborInterpolateImageType::New();
_pResizeFilter->SetInterpolator(nn_interpolator);
_pResizeFilter->Update();
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk(_pResizeFilter->GetOutput());
mitk::GrabItkImageMemory( _pResizeFilter->GetOutput(), image);
return image;
}
static mitk::Image::Pointer ResampleDWIbySpacing(mitk::Image::Pointer input, float* spacing)
{
itk::Vector<double, 3> spacingVector;
spacingVector[0] = spacing[0];
spacingVector[1] = spacing[1];
spacingVector[2] = spacing[2];
typedef itk::ResampleDwiImageFilter<short> ResampleFilterType;
mitk::DiffusionPropertyHelper::ImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::ImageType::New();
mitk::CastToItkImage(input, itkVectorImagePointer);
ResampleFilterType::Pointer resampler = ResampleFilterType::New();
resampler->SetInput( itkVectorImagePointer );
resampler->SetInterpolation(ResampleFilterType::Interpolate_Linear);
resampler->SetNewSpacing(spacingVector);
resampler->Update();
mitk::Image::Pointer output = mitk::GrabItkImageMemory( resampler->GetOutput() );
mitk::DiffusionPropertyHelper::SetGradientContainer(output, mitk::DiffusionPropertyHelper::GetGradientContainer(input));
mitk::DiffusionPropertyHelper::SetReferenceBValue(output, mitk::DiffusionPropertyHelper::GetReferenceBValue(input));
mitk::DiffusionPropertyHelper::InitializeImage( output );
return output;
}
int main( int argc, char* argv[] )
{
mitkDiffusionCommandLineParser parser;
parser.setArgumentPrefix("--","-");
parser.setTitle("Image Resampler");
parser.setCategory("Preprocessing Tools");
parser.setContributor("MIC");
parser.setDescription("Resample an image to eigther a specific spacing or to a reference image.");
// Add command line argument names
parser.addArgument("help", "h",mitkDiffusionCommandLineParser::Bool, "Show this help text");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "Input file",us::Any(),false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "Output file",us::Any(),false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("spacing", "s", mitkDiffusionCommandLineParser::String, "Spacing:", "Resample provide x,y,z spacing in mm (e.g. -r 1,1,3), is not applied to tensor data",us::Any());
parser.addArgument("reference", "r", mitkDiffusionCommandLineParser::String, "Reference:", "Resample using supplied reference image. Also cuts image to same dimensions",us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("win-sinc", "w", mitkDiffusionCommandLineParser::Bool, "Windowed-sinc interpolation:", "Use windowed-sinc interpolation (3) instead of linear interpolation ",us::Any());
parser.addArgument("nearest-neigh", "n", mitkDiffusionCommandLineParser::Bool, "Nearest Neighbor:", "Use Nearest Neighbor interpolation instead of linear interpolation ",us::Any());
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
// Handle special arguments
bool useSpacing = false;
bool useLinearInterpol = true;
bool useNN= false;
{
if (parsedArgs.size() == 0)
{
return EXIT_FAILURE;
}
if (parsedArgs.count("sinc-int"))
useLinearInterpol = false;
if (parsedArgs.count("nearest-neigh"))
useNN = true;
// Show a help message
if ( parsedArgs.count("help") || parsedArgs.count("h"))
{
std::cout << parser.helpText();
return EXIT_SUCCESS;
}
}
std::string outputFile = us::any_cast<std::string>(parsedArgs["i"]);
std::string inputFile = us::any_cast<std::string>(parsedArgs["o"]);
std::vector<std::string> spacings;
float spacing[] = { 0.0f, 0.0f, 0.0f };
if (parsedArgs.count("spacing"))
{
std::string arg = us::any_cast<std::string>(parsedArgs["spacing"]);
if (arg != "")
{
spacings = split(arg ,',');
spacing[0] = atoi(spacings.at(0).c_str());
spacing[1] = atoi(spacings.at(1).c_str());
spacing[2] = atoi(spacings.at(2).c_str());
useSpacing = true;
}
}
std::string refImageFile = "";
if (parsedArgs.count("reference"))
{
refImageFile = us::any_cast<std::string>(parsedArgs["reference"]);
}
if (refImageFile =="" && useSpacing == false)
{
MITK_ERROR << "No information how to resample is supplied. Use eigther --spacing or --reference !";
return EXIT_FAILURE;
}
mitk::Image::Pointer refImage;
if (!useSpacing)
refImage = mitk::IOUtil::Load<mitk::Image>(refImageFile);
mitk::Image::Pointer inputDWI = mitk::IOUtil::Load<mitk::Image>(inputFile);
if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(inputDWI.GetPointer()))
{
mitk::Image::Pointer outputImage;
if (useSpacing)
outputImage = ResampleDWIbySpacing(inputDWI, spacing);
else
{
MITK_WARN << "Not supported yet, to resample a DWI please set a new spacing.";
return EXIT_FAILURE;
}
mitk::IOUtil::Save(outputImage, outputFile.c_str());
return EXIT_SUCCESS;
}
mitk::Image::Pointer inputImage = mitk::IOUtil::Load<mitk::Image>(inputFile);
mitk::Image::Pointer resultImage;
if (useSpacing)
resultImage = ResampleBySpacing(inputImage,spacing,useLinearInterpol,useNN);
else
resultImage = TransformToReference(refImage,inputImage,useLinearInterpol,useNN);
mitk::IOUtil::Save(resultImage, outputFile);
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/Misc/PeakExtraction.cpp b/Modules/DiffusionCmdApps/Misc/PeakExtraction.cpp
index 99a874a..3bed904 100644
--- a/Modules/DiffusionCmdApps/Misc/PeakExtraction.cpp
+++ b/Modules/DiffusionCmdApps/Misc/PeakExtraction.cpp
@@ -1,294 +1,294 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <itkImageFileWriter.h>
#include <itkResampleImageFilter.h>
#include <itkOdfMaximaExtractionFilter.h>
#include <mitkImage.h>
#include <mitkOdfImage.h>
#include <mitkImageCast.h>
#include <mitkImageToItk.h>
#include <mitkTensorImage.h>
#include <mitkCoreObjectFactory.h>
#include "mitkDiffusionCommandLineParser.h"
#include <itkShCoefficientImageImporter.h>
#include <itkFlipImageFilter.h>
#include <mitkLexicalCast.h>
#include <boost/algorithm/string.hpp>
#include <mitkLocaleSwitch.h>
#include <mitkIOUtil.h>
template<int shOrder>
int StartPeakExtraction(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input image", "sh coefficient image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output directory", "output root", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("mask", "", mitkDiffusionCommandLineParser::String, "Mask", "mask image", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("normalization", "", mitkDiffusionCommandLineParser::Int, "Normalization", "0=no norm, 1=max norm, 2=single vec norm", 1, true);
parser.addArgument("numpeaks", "", mitkDiffusionCommandLineParser::Int, "Max. number of peaks", "maximum number of extracted peaks", 2, true);
parser.addArgument("rel_peakthr", "", mitkDiffusionCommandLineParser::Float, "Relative peak threshold", "peak threshold relative to largest peak", 0.4, true);
parser.addArgument("abs_peakthr", "", mitkDiffusionCommandLineParser::Float, "Absolute peak threshold", "absolute peak magnitude threshold", 0.03, true);
parser.addArgument("angular_thr", "", mitkDiffusionCommandLineParser::Float, "Angular threshold", "in degree", 15);
parser.addArgument("shConvention", "", mitkDiffusionCommandLineParser::String, "Use specified SH-basis", "use specified SH-basis (MRtrix, FSL)", std::string("MRtrix"), true);
parser.addArgument("flipX", "", mitkDiffusionCommandLineParser::Bool, "Flip X", "Flip peaks in x direction");
parser.addArgument("flipY", "", mitkDiffusionCommandLineParser::Bool, "Flip Y", "Flip peaks in y direction");
parser.addArgument("flipZ", "", mitkDiffusionCommandLineParser::Bool, "Flip Z", "Flip peaks in z direction");
parser.addArgument("scale_by_gfa", "", mitkDiffusionCommandLineParser::Bool, "Scale by GFA", "Scale ODF values and peaks by GFA");
parser.setCategory("Preprocessing Tools");
parser.setTitle("Peak Extraction");
parser.setDescription("");
parser.setContributor("MIC");
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
// mandatory arguments
std::string imageName = us::any_cast<std::string>(parsedArgs["i"]);
std::string outRoot = us::any_cast<std::string>(parsedArgs["o"]);
// optional arguments
std::string maskImageName("");
if (parsedArgs.count("mask"))
maskImageName = us::any_cast<std::string>(parsedArgs["mask"]);
int normalization = 1;
if (parsedArgs.count("normalization"))
normalization = us::any_cast<int>(parsedArgs["normalization"]);
int numPeaks = 2;
if (parsedArgs.count("numpeaks"))
numPeaks = us::any_cast<int>(parsedArgs["numpeaks"]);
float rel_peakthr = 0.4;
if (parsedArgs.count("rel_peakthr"))
rel_peakthr = us::any_cast<float>(parsedArgs["rel_peakthr"]);
float abs_peakthr = 0.03;
if (parsedArgs.count("abs_peakthr"))
abs_peakthr = us::any_cast<float>(parsedArgs["abs_peakthr"]);
float angular_thr = 15;
if (parsedArgs.count("angular_thr"))
angular_thr = us::any_cast<float>(parsedArgs["angular_thr"]);
angular_thr = cos((float)angular_thr*itk::Math::pi / 180);
bool scale_by_gfa = false;
if (parsedArgs.count("scale_by_gfa"))
scale_by_gfa = us::any_cast<bool>(parsedArgs["scale_by_gfa"]);
bool flipX = false;
if (parsedArgs.count("flipX"))
flipX = us::any_cast<bool>(parsedArgs["flipX"]);
bool flipY = false;
if (parsedArgs.count("flipY"))
flipY = us::any_cast<bool>(parsedArgs["flipY"]);
bool flipZ = false;
if (parsedArgs.count("flipZ"))
flipZ = us::any_cast<bool>(parsedArgs["flipZ"]);
std::cout << "image: " << imageName;
std::cout << "outroot: " << outRoot;
if (!maskImageName.empty())
std::cout << "mask: " << maskImageName;
else
std::cout << "no mask image selected";
std::cout << "numpeaks: " << numPeaks;
std::cout << "peakthres: " << rel_peakthr;
std::cout << "abspeakthres: " << abs_peakthr;
std::cout << "shOrder: " << shOrder;
try
{
mitk::Image::Pointer image = mitk::IOUtil::Load<mitk::Image>(imageName);
mitk::Image::Pointer mask = mitk::IOUtil::Load<mitk::Image>(maskImageName);
typedef itk::Image<unsigned char, 3> ItkUcharImgType;
typedef itk::OdfMaximaExtractionFilter< float, shOrder, 20242 > MaximaExtractionFilterType;
typename MaximaExtractionFilterType::Pointer peak_extraction_filter = MaximaExtractionFilterType::New();
ItkUcharImgType::Pointer itkMaskImage = nullptr;
if (mask.IsNotNull())
{
try{
itkMaskImage = ItkUcharImgType::New();
mitk::CastToItkImage(mask, itkMaskImage);
peak_extraction_filter->SetMaskImage(itkMaskImage);
}
catch(...)
{
}
}
if (parsedArgs.count("shConvention"))
{
std::string convention = us::any_cast<std::string>(parsedArgs["shConvention"]).c_str();
if ( convention=="FSL" )
peak_extraction_filter->SetToolkit(MaximaExtractionFilterType::FSL);
else
peak_extraction_filter->SetToolkit(MaximaExtractionFilterType::MRTRIX);
}
else
peak_extraction_filter->SetToolkit(MaximaExtractionFilterType::MRTRIX);
try{
typedef mitk::ImageToItk< typename MaximaExtractionFilterType::CoefficientImageType > CasterType;
typename CasterType::Pointer caster = CasterType::New();
caster->SetInput(image);
caster->Update();
peak_extraction_filter->SetInput(caster->GetOutput());
}
catch(...)
{
std::cout << "wrong image type";
return EXIT_FAILURE;
}
peak_extraction_filter->SetMaxNumPeaks(numPeaks);
peak_extraction_filter->SetRelativePeakThreshold(rel_peakthr);
peak_extraction_filter->SetAbsolutePeakThreshold(abs_peakthr);
peak_extraction_filter->SetAngularThreshold(angular_thr);
peak_extraction_filter->SetFlipX(flipX);
peak_extraction_filter->SetFlipY(flipY);
peak_extraction_filter->SetFlipZ(flipZ);
peak_extraction_filter->SetScaleByGfa(scale_by_gfa);
switch (normalization)
{
case 0:
peak_extraction_filter->SetNormalizationMethod(MaximaExtractionFilterType::NO_NORM);
break;
case 1:
peak_extraction_filter->SetNormalizationMethod(MaximaExtractionFilterType::MAX_VEC_NORM);
break;
case 2:
peak_extraction_filter->SetNormalizationMethod(MaximaExtractionFilterType::SINGLE_VEC_NORM);
break;
}
std::cout << "Starting extraction";
peak_extraction_filter->Update();
mitk::LocaleSwitch localeSwitch("C");
// write direction image
{
typename MaximaExtractionFilterType::PeakImageType::Pointer itkImg = peak_extraction_filter->GetPeakImage();
std::string outfilename = outRoot;
outfilename.append("_PEAKS.nrrd");
typedef itk::ImageFileWriter< typename MaximaExtractionFilterType::PeakImageType > WriterType;
typename WriterType::Pointer writer = WriterType::New();
writer->SetFileName(outfilename);
writer->SetInput(itkImg);
writer->Update();
}
// write num directions image
{
ItkUcharImgType::Pointer numDirImage = peak_extraction_filter->GetNumDirectionsImage();
if (itkMaskImage.IsNotNull())
{
numDirImage->SetDirection(itkMaskImage->GetDirection());
numDirImage->SetOrigin(itkMaskImage->GetOrigin());
}
std::string outfilename = outRoot.c_str();
outfilename.append("_NUM_PEAKS.nrrd");
typedef itk::ImageFileWriter< ItkUcharImgType > WriterType;
WriterType::Pointer writer = WriterType::New();
writer->SetFileName(outfilename);
writer->SetInput(numDirImage);
writer->Update();
}
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
/*!
\brief Extract maxima in the input spherical harmonics image.
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input image", "sh coefficient image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output directory", "output root", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("shOrder", "sh", mitkDiffusionCommandLineParser::Int, "Spherical harmonics order", "spherical harmonics order");
parser.addArgument("mask", "m", mitkDiffusionCommandLineParser::String, "Mask", "mask image", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("normalization", "n", mitkDiffusionCommandLineParser::Int, "Normalization", "0=no norm, 1=max norm, 2=single vec norm", 1, true);
parser.addArgument("numpeaks", "p", mitkDiffusionCommandLineParser::Int, "Max. number of peaks", "maximum number of extracted peaks", 2, true);
parser.addArgument("peakthres", "r", mitkDiffusionCommandLineParser::Float, "Peak threshold", "peak threshold relative to largest peak", 0.4, true);
parser.addArgument("abspeakthres", "a", mitkDiffusionCommandLineParser::Float, "Absolute peak threshold", "absolute peak threshold weighted with local GFA value", 0.06, true);
parser.addArgument("shConvention", "s", mitkDiffusionCommandLineParser::String, "Use specified SH-basis", "use specified SH-basis (MITK, FSL, MRtrix)", std::string("MITK"), true);
parser.addArgument("noFlip", "f", mitkDiffusionCommandLineParser::Bool, "No flip", "do not flip input image to match MITK coordinate convention");
parser.setCategory("Preprocessing Tools");
parser.setTitle("Peak Extraction");
parser.setDescription("Extract maxima in the input spherical harmonics image.");
parser.setContributor("MIC");
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
int shOrder = -1;
if (parsedArgs.count("shOrder"))
shOrder = us::any_cast<int>(parsedArgs["shOrder"]);
switch (shOrder)
{
case 4:
return StartPeakExtraction<4>(argc, argv);
case 6:
return StartPeakExtraction<6>(argc, argv);
case 8:
return StartPeakExtraction<8>(argc, argv);
case 10:
return StartPeakExtraction<10>(argc, argv);
case 12:
return StartPeakExtraction<12>(argc, argv);
}
return EXIT_FAILURE;
}
diff --git a/Modules/DiffusionCmdApps/Misc/Registration.cpp b/Modules/DiffusionCmdApps/Misc/Registration.cpp
index f22f4ef..d0b7b93 100644
--- a/Modules/DiffusionCmdApps/Misc/Registration.cpp
+++ b/Modules/DiffusionCmdApps/Misc/Registration.cpp
@@ -1,445 +1,445 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// CTK
#include "mitkDiffusionCommandLineParser.h"
#include <mitkIOUtil.h>
#include <mitkRegistrationWrapper.h>
#include <mitkImage.h>
#include <mitkImageCast.h>
#include <mitkImageReadAccessor.h>
#include <mitkITKImageImport.h>
#include <mitkImageTimeSelector.h>
// ITK
#include <itksys/SystemTools.hxx>
#include <itkDirectory.h>
#include "itkLinearInterpolateImageFunction.h"
#include "itkWindowedSincInterpolateImageFunction.h"
#include "itkIdentityTransform.h"
#include "itkResampleImageFilter.h"
#include "itkNrrdImageIO.h"
typedef std::vector<std::string> FileListType;
typedef itk::Image<double, 3> InputImageType;
static mitk::Image::Pointer ExtractFirstTS(mitk::Image* image, std::string fileType)
{
if (fileType == ".dwi")
return image;
mitk::ImageTimeSelector::Pointer selector = mitk::ImageTimeSelector::New();
selector->SetInput(image);
selector->SetTimeNr(0);
selector->UpdateLargestPossibleRegion();
mitk::Image::Pointer img =selector->GetOutput()->Clone();
return img;
}
static std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems)
{
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim))
{
elems.push_back(item);
}
return elems;
}
static std::vector<std::string> split(const std::string &s, char delim)
{
std::vector < std::string > elems;
return split(s, delim, elems);
}
/// Create list of all files in provided folder ending with same postfix
static FileListType CreateFileList(std::string folder , std::string postfix)
{
itk::Directory::Pointer dir = itk::Directory::New();
FileListType fileList;
if( dir->Load(folder.c_str() ) )
{
int n = dir->GetNumberOfFiles();
for(int r=0;r<n;r++)
{
std::string filename = dir->GetFile( r );
if (filename == "." || filename == "..")
continue;
filename = folder + filename;
if (!itksys::SystemTools::FileExists( filename.c_str()))
continue;
if (filename.length() <= postfix.length() )
continue;
if (filename.substr(filename.length() -postfix.length() ) == postfix)
fileList.push_back(filename);
}
}
return fileList;
}
static std::string GetSavePath(std::string outputFolder, std::string fileName)
{
std::string fileType = itksys::SystemTools::GetFilenameExtension(fileName);
std::string fileStem = itksys::SystemTools::GetFilenameWithoutExtension(fileName);
std::string savePathAndFileName = outputFolder +fileStem + fileType;
return savePathAndFileName;
}
static mitk::Image::Pointer ResampleBySpacing(mitk::Image *input, float *spacing)
{
InputImageType::Pointer itkImage = InputImageType::New();
CastToItkImage(input,itkImage);
/**
* 1) Resampling
*
*/
// Identity transform.
// We don't want any transform on our image except rescaling which is not
// specified by a transform but by the input/output spacing as we will see
// later.
// So no transform will be specified.
typedef itk::IdentityTransform<double, 3> T_Transform;
// The resampler type itself.
typedef itk::ResampleImageFilter<InputImageType, InputImageType> T_ResampleFilter;
// Prepare the resampler.
// Instantiate the transform and specify it should be the id transform.
T_Transform::Pointer _pTransform = T_Transform::New();
_pTransform->SetIdentity();
// Instantiate the resampler. Wire in the transform and the interpolator.
T_ResampleFilter::Pointer _pResizeFilter = T_ResampleFilter::New();
_pResizeFilter->SetTransform(_pTransform);
// Set the output origin.
_pResizeFilter->SetOutputOrigin(itkImage->GetOrigin());
// Compute the size of the output.
// The size (# of pixels) in the output is recomputed using
// the ratio of the input and output sizes.
InputImageType::SpacingType inputSpacing = itkImage->GetSpacing();
InputImageType::SpacingType outputSpacing;
const InputImageType::RegionType& inputSize = itkImage->GetLargestPossibleRegion();
InputImageType::SizeType outputSize;
typedef InputImageType::SizeType::SizeValueType SizeValueType;
// Set the output spacing.
outputSpacing[0] = spacing[0];
outputSpacing[1] = spacing[1];
outputSpacing[2] = spacing[2];
outputSize[0] = static_cast<SizeValueType>(inputSize.GetSize()[0] * inputSpacing[0] / outputSpacing[0] + .5);
outputSize[1] = static_cast<SizeValueType>(inputSize.GetSize()[1] * inputSpacing[1] / outputSpacing[1] + .5);
outputSize[2] = static_cast<SizeValueType>(inputSize.GetSize()[2] * inputSpacing[2] / outputSpacing[2] + .5);
_pResizeFilter->SetOutputSpacing(outputSpacing);
_pResizeFilter->SetSize(outputSize);
typedef itk::Function::WelchWindowFunction<4> WelchWindowFunction;
typedef itk::WindowedSincInterpolateImageFunction< InputImageType, 4,WelchWindowFunction> WindowedSincInterpolatorType;
WindowedSincInterpolatorType::Pointer sinc_interpolator = WindowedSincInterpolatorType::New();
_pResizeFilter->SetInterpolator(sinc_interpolator);
// Specify the input.
_pResizeFilter->SetInput(itkImage);
_pResizeFilter->Update();
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk(_pResizeFilter->GetOutput());
mitk::GrabItkImageMemory( _pResizeFilter->GetOutput(), image);
return image;
}
/// Build a derived file name from moving images e.g. xxx_T2.nrrd becomes xxx_GTV.nrrd
static FileListType CreateDerivedFileList(std::string baseFN, std::string baseSuffix, std::vector<std::string> derivedPatterns)
{
FileListType files;
for (unsigned int i=0; i < derivedPatterns.size(); i++)
{
std::string derResourceSuffix = derivedPatterns.at(i);
std::string derivedResourceFilename = baseFN.substr(0,baseFN.length() -baseSuffix.length()) + derResourceSuffix;
MITK_INFO <<" Looking for file: " << derivedResourceFilename;
if (!itksys::SystemTools::FileExists(derivedResourceFilename.c_str()))
{
MITK_INFO << "CreateDerivedFileList: File does not exit. Skipping entry.";
continue;
}
files.push_back(derivedResourceFilename);
}
return files;
}
/// Copy derived resources from first time step. Append _reg tag, but leave data untouched.
static void CopyResources(FileListType fileList, std::string outputPath)
{
for (unsigned int j=0; j < fileList.size(); j++)
{
std::string derivedResourceFilename = fileList.at(j);
std::string fileType = itksys::SystemTools::GetFilenameExtension(derivedResourceFilename);
std::string fileStem = itksys::SystemTools::GetFilenameWithoutExtension(derivedResourceFilename);
std::string savePathAndFileName = outputPath +fileStem + "." + fileType;
MITK_INFO << "Copy resource " << savePathAndFileName;
mitk::Image::Pointer resImage = ExtractFirstTS(mitk::IOUtil::Load<mitk::Image>(derivedResourceFilename), fileType);
mitk::IOUtil::Save(resImage, savePathAndFileName);
}
}
int main( int argc, char* argv[] )
{
mitkDiffusionCommandLineParser parser;
parser.setArgumentPrefix("--","-");
parser.setTitle("Folder Registration");
parser.setCategory("Preprocessing Tools");
parser.setDescription("For detail description see http://docs.mitk.org/nightly/DiffusionMiniApps.html");
parser.setContributor("MIC");
// Add command line argument names
parser.addArgument("help", "h",mitkDiffusionCommandLineParser::Bool, "Help", "Show this help text");
//parser.addArgument("usemask", "u", QVariant::Bool, "Use segmentations (derived resources) to exclude areas from registration metrics");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "Input folder",us::Any(),false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "Output folder (ending with /)",us::Any(),false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("fixed", "f", mitkDiffusionCommandLineParser::String, "Fixed images:", "Suffix for fixed image (if none is supplied first file matching moving pattern is chosen)",us::Any(),true);
parser.addArgument("moving", "m", mitkDiffusionCommandLineParser::String, "Moving images:", "Suffix for moving images",us::Any(),false);
parser.addArgument("derived", "d", mitkDiffusionCommandLineParser::String, "Derived resources:", "Derived resources suffixes (replaces suffix for moving images); comma separated",us::Any(),true);
parser.addArgument("silent", "s", mitkDiffusionCommandLineParser::Bool, "Silent:", "No xml progress output.");
parser.addArgument("resample", "r", mitkDiffusionCommandLineParser::String, "Resample (x,y,z)mm:", "Resample provide x,y,z spacing in mm (e.g. -r 1,1,3), is not applied to tensor data",us::Any());
parser.addArgument("binary", "b", mitkDiffusionCommandLineParser::Bool, "Binary:", "Speficies that derived resource are binary (interpolation using nearest neighbor)",us::Any());
parser.addArgument("correct-origin", "c", mitkDiffusionCommandLineParser::Bool, "Origin correction:", "Correct for large origin displacement. Use switch when you reveive: Joint PDF summed to zero ",us::Any());
parser.addArgument("sinc-int", "s", mitkDiffusionCommandLineParser::Bool, "Windowed-sinc interpolation:", "Use windowed-sinc interpolation (3) instead of linear interpolation ",us::Any());
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
// Handle special arguments
bool silent = false;
bool isBinary = false;
bool alignOrigin = false;
{
if (parsedArgs.size() == 0)
{
return EXIT_FAILURE;
}
if (parsedArgs.count("silent"))
silent = true;
if (parsedArgs.count("binary"))
isBinary = true;
if (parsedArgs.count("correct-origin"))
alignOrigin = true;
// Show a help message
if ( parsedArgs.count("help") || parsedArgs.count("h"))
{
std::cout << parser.helpText();
return EXIT_SUCCESS;
}
}
std::string refPattern = "";
bool useFirstMoving = false;
std::string movingImgPattern = us::any_cast<std::string>(parsedArgs["moving"]);
if (parsedArgs.count("fixed"))
{
refPattern = us::any_cast<std::string>(parsedArgs["fixed"]);
}
else
{
useFirstMoving = true;
refPattern = movingImgPattern;
}
std::string outputPath = us::any_cast<std::string>(parsedArgs["o"]);
std::string inputPath = us::any_cast<std::string>(parsedArgs["i"]);
//QString resampleReference = parsedArgs["resample"].toString();
//bool maskTumor = parsedArgs["usemask"].toBool();
// if derived sources pattern is provided, populate QStringList with possible filename postfixes
std::vector<std::string> derPatterns;
if (parsedArgs.count("derived") || parsedArgs.count("d") )
{
std::string arg = us::any_cast<std::string>(parsedArgs["derived"]);
derPatterns = split(arg ,',');
}
std::vector<std::string> spacings;
float spacing[] = { 0.0f, 0.0f, 0.0f };
bool doResampling = false;
if (parsedArgs.count("resample") || parsedArgs.count("d") )
{
std::string arg = us::any_cast<std::string>(parsedArgs["resample"]);
spacings = split(arg ,',');
spacing[0] = atoi(spacings.at(0).c_str());
spacing[1] = atoi(spacings.at(1).c_str());
spacing[2] = atoi(spacings.at(2).c_str());
doResampling = true;
}
MITK_INFO << "Input Folder : " << inputPath;
MITK_INFO << "Looking for reference image ...";
FileListType referenceFileList = CreateFileList(inputPath,refPattern);
if ((!useFirstMoving && referenceFileList.size() != 1) || (useFirstMoving && referenceFileList.size() == 0))
{
MITK_ERROR << "None or more than one possible reference images (" << refPattern <<") found. Exiting." << referenceFileList.size();
MITK_INFO << "Choose a fixed arguement that is unique in the given folder!";
return EXIT_FAILURE;
}
std::string referenceFileName = referenceFileList.at(0);
MITK_INFO << "Loading Reference (fixed) image: " << referenceFileName;
std::string fileType = itksys::SystemTools::GetFilenameExtension(referenceFileName);
mitk::Image::Pointer refImage = ExtractFirstTS(mitk::IOUtil::Load<mitk::Image>(referenceFileName), fileType);
mitk::Image::Pointer resampleReference = nullptr;
if (doResampling)
{
refImage = ResampleBySpacing(refImage,spacing);
resampleReference = refImage;
}
if (refImage.IsNull())
MITK_ERROR << "Loaded fixed image is nullptr";
// Copy reference image to destination
std::string savePathAndFileName = GetSavePath(outputPath, referenceFileName);
mitk::IOUtil::Save(refImage, savePathAndFileName);
// Copy all derived resources also to output folder, adding _reg suffix
referenceFileList = CreateDerivedFileList(referenceFileName, movingImgPattern,derPatterns);
CopyResources(referenceFileList, outputPath);
std::string derivedResourceFilename;
mitk::Image::Pointer referenceMask = nullptr; // union of all segmentations
if (!silent)
{
// XML Output to report progress
std::cout << "<filter-start>";
std::cout << "<filter-name>Batched Registration</filter-name>";
std::cout << "<filter-comment>Starting registration ... </filter-comment>";
std::cout << "</filter-start>";
}
// Now iterate over all files and register them to the reference image,
// also register derived resources based on file patterns
// ------------------------------------------------------------------------------
// Create File list
FileListType movingImagesList = CreateFileList(inputPath, movingImgPattern);
for (unsigned int i =0; i < movingImagesList.size(); i++)
{
std::string fileMorphName = movingImagesList.at(i);
if (fileMorphName == referenceFileName)
{
// do not process reference image again
continue;
}
MITK_INFO << "Processing image " << fileMorphName;
// 1 Register morphological file to reference image
if (!itksys::SystemTools::FileExists(fileMorphName.c_str()))
{
MITK_WARN << "File does not exit. Skipping entry.";
continue;
}
// Origin of images is cancelled
// TODO make this optional!!
double transf[6];
double offset[3];
{
std::string fileType = itksys::SystemTools::GetFilenameExtension(fileMorphName);
mitk::Image::Pointer movingImage = ExtractFirstTS(mitk::IOUtil::Load<mitk::Image>(fileMorphName), fileType);
if (movingImage.IsNull())
MITK_ERROR << "Loaded moving image is nullptr";
// Store transformation, apply it to morph file
MITK_INFO << "----------Registering moving image to reference----------";
mitk::RegistrationWrapper::GetTransformation(refImage, movingImage, transf, offset, alignOrigin, referenceMask);
mitk::RegistrationWrapper::ApplyTransformationToImage(movingImage, transf,offset, resampleReference); // , resampleImage
savePathAndFileName = GetSavePath(outputPath, fileMorphName);
if (fileType == ".dwi")
fileType = "dwi";
{
mitk::ImageReadAccessor readAccess(movingImage);
if (readAccess.GetData() == nullptr)
MITK_INFO <<"POST DATA is null";
}
mitk::IOUtil::Save(movingImage, savePathAndFileName);
}
if (!silent)
{
std::cout << "<filter-progress-text progress=\"" <<
(float)i / (float)movingImagesList.size()
<< "\" >.</filter-progress-text>";
}
// Now parse all derived resource and apply the above calculated transformation to them
// ------------------------------------------------------------------------------------
FileListType fList = CreateDerivedFileList(fileMorphName, movingImgPattern,derPatterns);
if (fList.size() > 0)
MITK_INFO << "----------DERIVED RESOURCES ---------";
for (unsigned int j=0; j < fList.size(); j++)
{
derivedResourceFilename = fList.at(j);
MITK_INFO << "----Processing derived resorce " << derivedResourceFilename << " ...";
std::string fileType = itksys::SystemTools::GetFilenameExtension(derivedResourceFilename);
mitk::Image::Pointer derivedMovingResource = ExtractFirstTS(mitk::IOUtil::Load<mitk::Image>(derivedResourceFilename), fileType);
// Apply transformation to derived resource, treat derived resource as binary
mitk::RegistrationWrapper::ApplyTransformationToImage(derivedMovingResource, transf,offset, resampleReference,isBinary);
savePathAndFileName = GetSavePath(outputPath, derivedResourceFilename);
mitk::IOUtil::Save(derivedMovingResource, savePathAndFileName);
}
}
if (!silent)
std::cout << "<filter-end/>";
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/Misc/ResampleGradients.cpp b/Modules/DiffusionCmdApps/Misc/ResampleGradients.cpp
index 0eb1489..d7771d8 100644
--- a/Modules/DiffusionCmdApps/Misc/ResampleGradients.cpp
+++ b/Modules/DiffusionCmdApps/Misc/ResampleGradients.cpp
@@ -1,230 +1,230 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <vector>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <string>
#include <istream>
#include <itkMetaDataObject.h>
#include <itkVectorImage.h>
#include <mitkImageCast.h>
#include <mitkBaseData.h>
#include "mitkDiffusionCommandLineParser.h"
#include <mitkLexicalCast.h>
#include <mitkCoreObjectFactory.h>
#include <mitkIOUtil.h>
#include <mitkBValueMapProperty.h>
#include <mitkGradientDirectionsProperty.h>
#include <itkElectrostaticRepulsionDiffusionGradientReductionFilter.h>
#include <itkImage.h>
#include <mitkImage.h>
#include "itkDWIVoxelFunctor.h"
#include <mitkDiffusionPropertyHelper.h>
typedef short DiffusionPixelType;
typedef itk::VectorImage< short, 3 > ItkDwiType;
// itk includes
#include "itkTimeProbe.h"
#include "itkB0ImageExtractionImageFilter.h"
#include "itkB0ImageExtractionToSeparateImageFilter.h"
#include "itkBrainMaskExtractionImageFilter.h"
#include "itkCastImageFilter.h"
#include "itkVectorContainer.h"
#include <itkElectrostaticRepulsionDiffusionGradientReductionFilter.h>
#include <itkMergeDiffusionImagesFilter.h>
#include <itkDwiGradientLengthCorrectionFilter.h>
#include <itkDwiNormilzationFilter.h>
#include <mitkTensorImage.h>
#include <mitkOdfImage.h>
// Multishell includes
#include <itkRadialMultishellToSingleshellImageFilter.h>
// Multishell Functors
#include <itkADCAverageFunctor.h>
#include <itkKurtosisFitFunctor.h>
#include <itkBiExpFitFunctor.h>
#include <itkADCFitFunctor.h>
// mitk includes
#include "mitkProgressBar.h"
#include "mitkStatusBar.h"
#include "mitkNodePredicateDataType.h"
#include "mitkProperties.h"
#include "mitkVtkResliceInterpolationProperty.h"
#include "mitkLookupTable.h"
#include "mitkLookupTableProperty.h"
#include "mitkTransferFunction.h"
#include "mitkTransferFunctionProperty.h"
//#include "mitkDataNodeObject.h"
#include "mitkOdfNormalizationMethodProperty.h"
#include "mitkOdfScaleByProperty.h"
#include <mitkPointSet.h>
#include <itkAdcImageFilter.h>
#include <itkBrainMaskExtractionImageFilter.h>
#include <mitkImageCast.h>
#include <mitkRotationOperation.h>
//#include <QTableWidgetItem>
//#include <QTableWidget>
#include <mitkInteractionConst.h>
#include <mitkImageAccessByItk.h>
#include <itkResampleDwiImageFilter.h>
#include <itkResampleImageFilter.h>
#include <itkImageDuplicator.h>
#include <itkMaskImageFilter.h>
#include <mitkNodePredicateProperty.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateOr.h>
#include <itkCropImageFilter.h>
#include <itkDiffusionTensor3DReconstructionImageFilter.h>
#include <itkRemoveDwiChannelFilter.h>
#include <itkExtractDwiChannelFilter.h>
#include <mitkITKImageImport.h>
#include <mitkBValueMapProperty.h>
#include <mitkGradientDirectionsProperty.h>
#include <mitkMeasurementFrameProperty.h>
#include <itkImageDuplicator.h>
#include <itkFlipImageFilter.h>
#include <mitkITKImageImport.h>
#include "mitkPreferenceListReaderOptionsFunctor.h"
mitk::Image::Pointer DoReduceGradientDirections(mitk::Image::Pointer image, double BValue, unsigned int numOfGradientsToKeep, bool use_first_n)
{
bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image) );
if ( !isDiffusionImage ) {
std::cout << "Image is not a Diffusion Weighted Image" << std::endl;
//return;
}
typedef itk::ElectrostaticRepulsionDiffusionGradientReductionFilter<DiffusionPixelType, DiffusionPixelType> FilterType;
typedef mitk::BValueMapProperty::BValueMap BValueMap;
BValueMap shellSlectionMap;
BValueMap originalShellMap = mitk::DiffusionPropertyHelper::GetBValueMap(image);
std::vector<unsigned int> newNumGradientDirections;
//Keeps 1 b0 gradient
double B0Value = 0;
shellSlectionMap[B0Value] = originalShellMap[B0Value];
unsigned int num = 1;
newNumGradientDirections.push_back(num);
//BValue = 1000;
shellSlectionMap[BValue] = originalShellMap[BValue];
//numOfGradientsToKeep = 32;
newNumGradientDirections.push_back(numOfGradientsToKeep);
if (newNumGradientDirections.empty()) {
std::cout << "newNumGradientDirections is empty" << std::endl;
//return;
}
auto gradientContainer = mitk::DiffusionPropertyHelper::GetGradientContainer(image);
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(image, itkVectorImagePointer);
std::cout << "1" << std::endl;
FilterType::Pointer filter = FilterType::New();
filter->SetInput( itkVectorImagePointer );
filter->SetOriginalGradientDirections(gradientContainer);
filter->SetNumGradientDirections(newNumGradientDirections);
filter->SetOriginalBValueMap(originalShellMap);
filter->SetShellSelectionBValueMap(shellSlectionMap);
filter->SetUseFirstN(use_first_n);
filter->Update();
std::cout << "2" << std::endl;
if( filter->GetOutput() == nullptr) {
std::cout << "filter get output is nullptr" << std::endl;
}
mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( filter->GetOutput() );
mitk::DiffusionPropertyHelper::CopyProperties(image, newImage, true);
mitk::DiffusionPropertyHelper::SetGradientContainer(newImage, filter->GetGradientDirections());
mitk::DiffusionPropertyHelper::InitializeImage( newImage );
return newImage;
}
/*!
\brief Resample gradients of input DWI image.
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Resample Gradients");
parser.setCategory("Preprocessing Tools");
parser.setDescription("Resample gradients of input DWI image. You can select one b-value shell and the number of gradients within this shell you want to have. It will also keep one b0 image.");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "input image", us::Any(), false);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output image", us::Any(), false);
parser.addArgument("b_value", "", mitkDiffusionCommandLineParser::Float, "b-value:", "float", 1000, false);
parser.addArgument("num_gradients", "", mitkDiffusionCommandLineParser::Int, "Nr of gradients:", "integer", 32, false);
parser.addArgument("use_first_n", "", mitkDiffusionCommandLineParser::Bool, "Use first N:", "no optimization, simply use first n gradients", 0);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
std::string inFileName = us::any_cast<std::string>(parsedArgs["i"]);
std::string outFileName = us::any_cast<std::string>(parsedArgs["o"]);
double bValue = us::any_cast<float>(parsedArgs["b_value"]);
unsigned int nrOfGradients = us::any_cast<int>(parsedArgs["num_gradients"]);
bool use_first_n = false;
if (parsedArgs.count("use_first_n"))
use_first_n = true;
try
{
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({ "Diffusion Weighted Images" }, {});
mitk::Image::Pointer mitkImage = mitk::IOUtil::Load<mitk::Image>(inFileName, &functor);
mitk::Image::Pointer newImage = DoReduceGradientDirections(mitkImage, bValue, nrOfGradients, use_first_n);
//mitk::IOUtil::Save(newImage, outFileName); //save as dwi image
mitk::IOUtil::Save(newImage, "DWI_NIFTI", outFileName); //save as nifti image
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/Misc/RoundBvalues.cpp b/Modules/DiffusionCmdApps/Misc/RoundBvalues.cpp
index b195296..18ec92e 100644
--- a/Modules/DiffusionCmdApps/Misc/RoundBvalues.cpp
+++ b/Modules/DiffusionCmdApps/Misc/RoundBvalues.cpp
@@ -1,106 +1,106 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkImageCast.h>
#include <mitkImage.h>
#include <mitkIOUtil.h>
#include "mitkDiffusionCommandLineParser.h"
#include <mitkPreferenceListReaderOptionsFunctor.h>
#include <itksys/SystemTools.hxx>
#include <itkDwiGradientLengthCorrectionFilter.h>
#include <mitkDiffusionPropertyHelper.h>
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("RoundBvalues");
parser.setCategory("Preprocessing Tools");
parser.setDescription("Round b-values");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "input image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("to_nearest", "", mitkDiffusionCommandLineParser::Int, "To nearest:", "integer", 1000);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
// mandatory arguments
std::string imageName = us::any_cast<std::string>(parsedArgs["i"]);
std::string outImage = us::any_cast<std::string>(parsedArgs["o"]);
int to_nearest = 1000;
if (parsedArgs.count("to_nearest"))
to_nearest = us::any_cast<int>(parsedArgs["to_nearest"]);
try
{
typedef mitk::DiffusionPropertyHelper PropHelper;
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images"}, {});
mitk::Image::Pointer in_image = mitk::IOUtil::Load<mitk::Image>(imageName, &functor);
if (!PropHelper::IsDiffusionWeightedImage(in_image))
{
mitkThrow() << "Input is not a diffusion weighted image: " << imageName;
}
typedef itk::DwiGradientLengthCorrectionFilter FilterType;
auto itkVectorImagePointer = PropHelper::GetItkVectorImage(in_image);
FilterType::Pointer filter = FilterType::New();
filter->SetRoundingValue(to_nearest);
filter->SetReferenceBValue(PropHelper::GetReferenceBValue(in_image));
filter->SetReferenceGradientDirectionContainer(PropHelper::GetGradientContainer(in_image));
filter->Update();
mitk::Image::Pointer newImage = mitk::Image::New();
newImage->InitializeByItk( itkVectorImagePointer.GetPointer() );
newImage->SetImportVolume( itkVectorImagePointer->GetBufferPointer(), 0, 0, mitk::Image::CopyMemory);
itkVectorImagePointer->GetPixelContainer()->ContainerManageMemoryOff();
PropHelper::CopyProperties(in_image, newImage, true);
PropHelper::SetReferenceBValue(newImage, filter->GetNewBValue());
PropHelper::SetGradientContainer(newImage, filter->GetOutputGradientDirectionContainer());
PropHelper::InitializeImage(newImage);
std::string ext = itksys::SystemTools::GetFilenameExtension(outImage);
if (ext==".nii" || ext==".nii.gz")
mitk::IOUtil::Save(newImage, "DWI_NIFTI", outImage);
else
mitk::IOUtil::Save(newImage, outImage);
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/Misc/ShToOdfImage.cpp b/Modules/DiffusionCmdApps/Misc/ShToOdfImage.cpp
index 5350b0d..f3e6487 100644
--- a/Modules/DiffusionCmdApps/Misc/ShToOdfImage.cpp
+++ b/Modules/DiffusionCmdApps/Misc/ShToOdfImage.cpp
@@ -1,72 +1,72 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkImageCast.h>
#include <mitkImage.h>
#include <mitkIOUtil.h>
#include "mitkDiffusionCommandLineParser.h"
#include <mitkPreferenceListReaderOptionsFunctor.h>
#include <itkShToOdfImageFilter.h>
#include <mitkShImage.h>
#include <mitkDiffusionFunctionCollection.h>
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("ShToOdfImage");
parser.setCategory("Preprocessing Tools");
parser.setDescription("Calculate discrete ODF image from SH coefficient image");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "input image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
// mandatory arguments
std::string imageName = us::any_cast<std::string>(parsedArgs["i"]);
std::string outImage = us::any_cast<std::string>(parsedArgs["o"]);
try
{
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"SH Image"}, {});
mitk::ShImage::Pointer source = mitk::IOUtil::Load<mitk::ShImage>(imageName, &functor);
mitk::Image::Pointer mitkImage = dynamic_cast<mitk::Image*>(source.GetPointer());
mitk::OdfImage::Pointer out_image = mitk::convert::GetOdfFromShImage(mitkImage);
if (out_image.IsNotNull())
mitk::IOUtil::Save(out_image, outImage);
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/Python/BrainExtraction.cpp b/Modules/DiffusionCmdApps/Python/BrainExtraction.cpp
index 91dbfdc..acd0d5d 100644
--- a/Modules/DiffusionCmdApps/Python/BrainExtraction.cpp
+++ b/Modules/DiffusionCmdApps/Python/BrainExtraction.cpp
@@ -1,179 +1,179 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkImageCast.h>
#include <mitkImage.h>
#include <mitkIOUtil.h>
#include "mitkDiffusionCommandLineParser.h"
#include <mitkDiffusionPropertyHelper.h>
#include <itksys/SystemTools.hxx>
#include <itkB0ImageExtractionToSeparateImageFilter.h>
#include <mitkIPythonService.h>
#include <mitkImageCast.h>
#include <usGetModuleContext.h>
#include <usModuleContext.h>
#include <usModule.h>
#include <usModuleResource.h>
#include <usModuleResourceStream.h>
#include <BetData.h>
#include <mitkPreferenceListReaderOptionsFunctor.h>
#include <boost/algorithm/string.hpp>
typedef mitk::DiffusionPropertyHelper DPH;
typedef itksys::SystemTools ist;
std::string GetPythonFile(std::string filename, std::string exec_dir)
{
std::string out = "";
for (auto dir : mitk::bet::relative_search_dirs)
{
if ( ist::FileExists( exec_dir + dir + filename) )
{
out = exec_dir + dir + filename;
return out;
}
if ( ist::FileExists( ist::GetCurrentWorkingDirectory() + dir + filename) )
{
out = ist::GetCurrentWorkingDirectory() + dir + filename;
return out;
}
}
for (auto dir : mitk::bet::absolute_search_dirs)
{
if ( ist::FileExists( dir + filename) )
{
out = dir + filename;
return out;
}
}
return out;
}
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("BrainExtraction");
parser.setCategory("Preprocessing Tools");
parser.setDescription("Performs brain extraction using a deep learning model");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "input image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output root", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
// mandatory arguments
std::string i = us::any_cast<std::string>(parsedArgs["i"]);
std::string o = us::any_cast<std::string>(parsedArgs["o"]);
std::string exec_dir = ist::GetFilenamePath(argv[0]);
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images"}, {});
mitk::Image::Pointer mitk_image = mitk::IOUtil::Load<mitk::Image>(i, &functor);
bool missing_file = false;
std::string missing_file_string = "";
if ( GetPythonFile("run_mitk.py", exec_dir).empty() )
{
missing_file_string += "Brain extraction script file missing: run_mitk.py\n\n";
missing_file = true;
}
if ( GetPythonFile("model_final.model", exec_dir).empty() )
{
missing_file_string += "Brain extraction model file missing: model_final.model\n\n";
missing_file = true;
}
if ( GetPythonFile("basic_config_just_like_braintumor.py", exec_dir).empty() )
{
missing_file_string += "Config file missing: basic_config_just_like_braintumor.py\n\n";
missing_file = true;
}
if (missing_file)
{
mitkThrow() << missing_file_string;
}
us::ModuleContext* context = us::GetModuleContext();
us::ServiceReference<mitk::IPythonService> m_PythonServiceRef = context->GetServiceReference<mitk::IPythonService>();
mitk::IPythonService* m_PythonService = dynamic_cast<mitk::IPythonService*> ( context->GetService<mitk::IPythonService>(m_PythonServiceRef) );
mitk::IPythonService::ForceLoadModule();
m_PythonService->AddAbsoluteSearchDirs(mitk::bet::absolute_search_dirs);
m_PythonService->AddRelativeSearchDirs(mitk::bet::relative_search_dirs);
m_PythonService->Execute("paths=[]");
// set input files (model and config)
m_PythonService->Execute("model_file=\""+GetPythonFile("model_final.model", exec_dir)+"\"");
m_PythonService->Execute("config_file=\""+GetPythonFile("basic_config_just_like_braintumor.py", exec_dir)+"\"");
// copy input image to python
m_PythonService->CopyToPythonAsSimpleItkImage( mitk_image, "in_image");
// run segmentation script
m_PythonService->ExecuteScript( GetPythonFile("run_mitk.py", exec_dir) );
// clean up after running script (better way than deleting individual variables?)
if(m_PythonService->DoesVariableExist("in_image"))
m_PythonService->Execute("del in_image");
// check for errors
if(!m_PythonService->GetVariable("error_string").empty())
mitkThrow() << m_PythonService->GetVariable("error_string");
// get output images and add to datastorage
std::string output_variables = m_PythonService->GetVariable("output_variables");
std::vector<std::string> outputs;
boost::split(outputs, output_variables, boost::is_any_of(","));
std::string output_types = m_PythonService->GetVariable("output_types");
std::vector<std::string> types;
boost::split(types, output_types, boost::is_any_of(","));
for (unsigned int i=0; i<outputs.size(); ++i)
{
if (m_PythonService->DoesVariableExist(outputs.at(i)))
{
mitk::Image::Pointer image = m_PythonService->CopySimpleItkImageFromPython(outputs.at(i));
if(types.at(i)=="input" && mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(mitk_image))
{
mitk::DiffusionPropertyHelper::CopyProperties(mitk_image, image, true);
mitk::DiffusionPropertyHelper::InitializeImage(image);
}
mitk::DataNode::Pointer corrected_node = mitk::DataNode::New();
corrected_node->SetData( image );
std::string name = o + "_";
name += outputs.at(i);
if(types.at(i)=="input" && mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(mitk_image))
mitk::IOUtil::Save(image, "DWI_NIFTI", name+".nii.gz");
else
mitk::IOUtil::Save(image, name+".nii.gz");
}
}
MITK_INFO << "Finished brain extraction";
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/Quantification/DiffusionIndices.cpp b/Modules/DiffusionCmdApps/Quantification/DiffusionIndices.cpp
index 2455973..42f915c 100644
--- a/Modules/DiffusionCmdApps/Quantification/DiffusionIndices.cpp
+++ b/Modules/DiffusionCmdApps/Quantification/DiffusionIndices.cpp
@@ -1,196 +1,196 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkImageCast.h>
#include <itkExceptionObject.h>
#include <itkImageFileWriter.h>
#include <mitkOdfImage.h>
#include <itkTensorDerivedMeasurementsFilter.h>
#include <itkDiffusionOdfGeneralizedFaImageFilter.h>
#include <mitkTensorImage.h>
#include "mitkDiffusionCommandLineParser.h"
#include <boost/algorithm/string.hpp>
#include <itksys/SystemTools.hxx>
#include <itkMultiThreader.h>
#include <mitkIOUtil.h>
#include <mitkPreferenceListReaderOptionsFunctor.h>
#include <mitkImage.h>
#include <mitkShImage.h>
#include <mitkOdfImage.h>
#include <mitkTensorImage.h>
#include <mitkDiffusionPropertyHelper.h>
#include <itkAdcImageFilter.h>
#include <mitkDiffusionFunctionCollection.h>
#include <mitkLocaleSwitch.h>
/**
*
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Diffusion Indices");
parser.setCategory("Diffusion Related Measures");
parser.setDescription("Computes requested diffusion related measures");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "input image (tensor, ODF or SH-coefficient image)", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("index", "idx", mitkDiffusionCommandLineParser::String, "Index:", "index (fa, gfa, ra, ad, rd, ca, l2, l3, md, adc)", us::Any(), false);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
std::string inFileName = us::any_cast<std::string>(parsedArgs["i"]);
std::string index = us::any_cast<std::string>(parsedArgs["index"]);
std::string outFileName = us::any_cast<std::string>(parsedArgs["o"]);
std::string ext = itksys::SystemTools::GetFilenameLastExtension(outFileName);
if (ext.empty())
outFileName += ".nii.gz";
try
{
// load input image
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images", "SH Image", "ODF Image", "Tensor Image"}, {});
auto input = mitk::IOUtil::Load<mitk::Image>(inFileName, &functor);
bool is_odf = (dynamic_cast<mitk::ShImage*>(input.GetPointer()) || dynamic_cast<mitk::OdfImage*>(input.GetPointer()));
bool is_dt = dynamic_cast<mitk::TensorImage*>(input.GetPointer());
bool is_dw = mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(input);
if (is_odf)
MITK_INFO << "Input is ODF image";
else if (is_dt)
MITK_INFO << "Input is tensor image";
else if (is_dw)
MITK_INFO << "Input is dMRI";
else
{
MITK_WARN << "Input is no ODF, SH, tensor or raw dMRI.";
return EXIT_FAILURE;
}
mitk::LocaleSwitch localeSwitch("C");
if( is_odf && index=="gfa" )
{
typedef itk::Vector<float,ODF_SAMPLING_SIZE> OdfVectorType;
typedef itk::Image<OdfVectorType,3> OdfVectorImgType;
OdfVectorImgType::Pointer itkvol;
if (dynamic_cast<mitk::ShImage*>(input.GetPointer()))
{
MITK_INFO << "Assuming MITK/MRtrix style SH convention!";
itkvol = mitk::convert::GetItkOdfFromShImage(input);
}
else
itkvol = mitk::convert::GetItkOdfFromOdfImage(input);
typedef itk::DiffusionOdfGeneralizedFaImageFilter<float,float,ODF_SAMPLING_SIZE> GfaFilterType;
GfaFilterType::Pointer gfaFilter = GfaFilterType::New();
gfaFilter->SetInput(itkvol);
gfaFilter->SetComputationMethod(GfaFilterType::GFA_STANDARD);
gfaFilter->Update();
itk::ImageFileWriter< itk::Image<float,3> >::Pointer fileWriter = itk::ImageFileWriter< itk::Image<float,3> >::New();
fileWriter->SetInput(gfaFilter->GetOutput());
fileWriter->SetFileName(outFileName);
fileWriter->Update();
}
else if( is_dt )
{
typedef itk::Image< itk::DiffusionTensor3D<float>, 3 > ItkTensorImage;
mitk::TensorImage::Pointer mitkTensorImage = dynamic_cast<mitk::TensorImage*>(input.GetPointer());
ItkTensorImage::Pointer itk_dti = ItkTensorImage::New();
mitk::CastToItkImage(mitkTensorImage, itk_dti);
typedef itk::TensorDerivedMeasurementsFilter<float> MeasurementsType;
MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New();
measurementsCalculator->SetInput(itk_dti.GetPointer() );
if(index=="fa")
measurementsCalculator->SetMeasure(MeasurementsType::FA);
else if(index=="ra")
measurementsCalculator->SetMeasure(MeasurementsType::RA);
else if(index=="ad")
measurementsCalculator->SetMeasure(MeasurementsType::AD);
else if(index=="rd")
measurementsCalculator->SetMeasure(MeasurementsType::RD);
else if(index=="ca")
measurementsCalculator->SetMeasure(MeasurementsType::CA);
else if(index=="l2")
measurementsCalculator->SetMeasure(MeasurementsType::L2);
else if(index=="l3")
measurementsCalculator->SetMeasure(MeasurementsType::L3);
else if(index=="md")
measurementsCalculator->SetMeasure(MeasurementsType::MD);
else
{
MITK_WARN << "No valid diffusion index for input image (tensor image) defined";
return EXIT_FAILURE;
}
measurementsCalculator->Update();
itk::ImageFileWriter< itk::Image<float,3> >::Pointer fileWriter = itk::ImageFileWriter< itk::Image<float,3> >::New();
fileWriter->SetInput(measurementsCalculator->GetOutput());
fileWriter->SetFileName(outFileName);
fileWriter->Update();
}
else if(is_dw && (index=="adc" || index=="md"))
{
typedef itk::AdcImageFilter< short, double > FilterType;
auto itkVectorImagePointer = mitk::DiffusionPropertyHelper::GetItkVectorImage(input);
FilterType::Pointer filter = FilterType::New();
filter->SetInput( itkVectorImagePointer );
filter->SetGradientDirections( mitk::DiffusionPropertyHelper::GetGradientContainer(input) );
filter->SetB_value( static_cast<double>(mitk::DiffusionPropertyHelper::GetReferenceBValue(input)) );
if (index=="adc")
filter->SetFitSignal(true);
else
filter->SetFitSignal(false);
filter->Update();
itk::ImageFileWriter< itk::Image<double,3> >::Pointer fileWriter = itk::ImageFileWriter< itk::Image<double,3> >::New();
fileWriter->SetInput(filter->GetOutput());
fileWriter->SetFileName(outFileName);
fileWriter->Update();
}
else
std::cout << "Diffusion index " << index << " not supported for supplied file type.";
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/Quantification/DiffusionIvimFit.cpp b/Modules/DiffusionCmdApps/Quantification/DiffusionIvimFit.cpp
index 7369743..690e2e8 100644
--- a/Modules/DiffusionCmdApps/Quantification/DiffusionIvimFit.cpp
+++ b/Modules/DiffusionCmdApps/Quantification/DiffusionIvimFit.cpp
@@ -1,166 +1,166 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkDiffusionCommandLineParser.h"
#include <mitkIOUtil.h>
#include <mitkDiffusionPropertyHelper.h>
#include <mitkImageCaster.h>
#include <itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.h>
#include "mitkImage.h"
#include <iostream>
#include <usAny.h>
#include <fstream>
#include "mitkIOUtil.h"
#include <itkFileTools.h>
#include <itksys/SystemTools.hxx>
//vnl_includes
#include "vnl/vnl_math.h"
#include "vnl/vnl_cost_function.h"
#include "vnl/vnl_least_squares_function.h"
#include "vnl/algo/vnl_lbfgsb.h"
#include "vnl/algo/vnl_lbfgs.h"
#include "vnl/algo/vnl_levenberg_marquardt.h"
typedef mitk::DiffusionPropertyHelper DPH;
#include <itkGaussianBlurImageFunction.h>
#include <itkUnaryFunctorImageFilter.h>
#include <itkImageFileWriter.h>
#include <itkVectorIndexSelectionCastImageFilter.h>
#include <itkComposeImageFilter.h>
#include <itkDiscreteGaussianImageFilter.h>
#include <mitkPreferenceListReaderOptionsFunctor.h>
void IvimMapComputation( mitk::Image::Pointer input,
std::string output_prefix ,
std::string output_type,
double b_thresh)
{
MITK_INFO << "Starting fit";
DPH::ImageType::Pointer vectorImage = DPH::ImageType::New();
mitk::CastToItkImage( input, vectorImage );
typedef itk::DiffusionIntravoxelIncoherentMotionReconstructionImageFilter<short, float> IVIMFilterType;
IVIMFilterType::Pointer ivim_filter = IVIMFilterType::New();
ivim_filter->SetInput( vectorImage );
ivim_filter->SetBValue( DPH::GetReferenceBValue( input.GetPointer() ) );
ivim_filter->SetGradientDirections( DPH::GetGradientContainer( input.GetPointer() ) );
ivim_filter->SetMethod(IVIMFilterType::IVIM_D_THEN_DSTAR);
ivim_filter->SetBThres(b_thresh);
ivim_filter->SetS0Thres(0);
ivim_filter->SetFitDStar(true);
ivim_filter->SetNumberOfThreads(1);
try
{
ivim_filter->Update();
}
catch( const itk::ExceptionObject& e)
{
mitkThrow() << "IVIM fit failed with an ITK Exception: " << e.what();
}
mitk::Image::Pointer f_image = mitk::Image::New();
f_image->InitializeByItk( ivim_filter->GetOutput() );
f_image->SetVolume( ivim_filter->GetOutput()->GetBufferPointer() );
mitk::Image::Pointer d_image = mitk::Image::New();
d_image->InitializeByItk( ivim_filter->GetOutput(1) );
d_image->SetVolume( ivim_filter->GetOutput(1)->GetBufferPointer() );
mitk::Image::Pointer dstar_image = mitk::Image::New();
dstar_image->InitializeByItk( ivim_filter->GetOutput(1) );
dstar_image->SetVolume( ivim_filter->GetOutput(2)->GetBufferPointer() );
std::string outputf_FileName = output_prefix + "_f_map." + output_type;
std::string outputD_FileName = output_prefix + "_D_map." + output_type;
std::string outputDstar_FileName = output_prefix + "_Dstar_map." + output_type;
try
{
mitk::IOUtil::Save( dstar_image, outputDstar_FileName );
mitk::IOUtil::Save( d_image, outputD_FileName );
mitk::IOUtil::Save( f_image, outputf_FileName );
}
catch( const itk::ExceptionObject& e)
{
mitkThrow() << "Failed to save the KurtosisFit Results due to exception: " << e.what();
}
}
int main( int argc, char* argv[] )
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Diffusion IVIM Fit");
parser.setCategory("Diffusion Related Measures");
parser.setContributor("MIC");
parser.setDescription("Fitting IVIM");
parser.setArgumentPrefix("--","-");
// mandatory arguments
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input: ", "input image (DWI)", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output Preifx: ", "Prefix for the output images, will append _ADC, _AKC accordingly ", us::Any(), false);
parser.addArgument("output_type", "", mitkDiffusionCommandLineParser::String, "Output Type: ", "choose data type of output image, e.g. '.nii' or '.nrrd' ", std::string(".nrrd"));
parser.addArgument("b_threshold", "", mitkDiffusionCommandLineParser::Float, "b-threshold:", "Omit samller b-values", 0.0);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
// mandatory arguments
std::string inFileName = us::any_cast<std::string>(parsedArgs["i"]);
std::string out_prefix = us::any_cast<std::string>(parsedArgs["o"]);
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images"}, {});
mitk::Image::Pointer inputImage = mitk::IOUtil::Load<mitk::Image>(inFileName, &functor);
double b_thresh = 0;
std::string out_type = "nrrd";
if (parsedArgs.count("output_type"))
out_type = us::any_cast<std::string>(parsedArgs["output_type"]);
if (parsedArgs.count("b_threshold"))
b_thresh = us::any_cast<float>(parsedArgs["lowerkbound"]);
if( !DPH::IsDiffusionWeightedImage( inputImage ) )
{
MITK_ERROR("DiffusionIVIMFit.Input") << "No valid diffusion-weighted image provided, failed to load " << inFileName << " as DW Image. Aborting...";
return EXIT_FAILURE;
}
IvimMapComputation( inputImage,
out_prefix ,
out_type,
b_thresh);
}
diff --git a/Modules/DiffusionCmdApps/Quantification/DiffusionKurtosisFit.cpp b/Modules/DiffusionCmdApps/Quantification/DiffusionKurtosisFit.cpp
index de37e02..72b5cc4 100644
--- a/Modules/DiffusionCmdApps/Quantification/DiffusionKurtosisFit.cpp
+++ b/Modules/DiffusionCmdApps/Quantification/DiffusionKurtosisFit.cpp
@@ -1,254 +1,254 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkDiffusionCommandLineParser.h"
#include <mitkIOUtil.h>
#include <mitkDiffusionPropertyHelper.h>
#include <mitkImageCaster.h>
#include <itkDiffusionKurtosisReconstructionImageFilter.h>
#include "mitkImage.h"
#include <iostream>
#include <usAny.h>
#include <fstream>
#include "mitkIOUtil.h"
#include <itkFileTools.h>
#include <itksys/SystemTools.hxx>
//vnl_includes
#include "vnl/vnl_math.h"
#include "vnl/vnl_cost_function.h"
#include "vnl/vnl_least_squares_function.h"
#include "vnl/algo/vnl_lbfgsb.h"
#include "vnl/algo/vnl_lbfgs.h"
#include "vnl/algo/vnl_levenberg_marquardt.h"
typedef mitk::DiffusionPropertyHelper DPH;
#include <itkGaussianBlurImageFunction.h>
#include <itkUnaryFunctorImageFilter.h>
#include <itkImageFileWriter.h>
#include <itkVectorIndexSelectionCastImageFilter.h>
#include <itkComposeImageFilter.h>
#include <itkDiscreteGaussianImageFilter.h>
#include <mitkPreferenceListReaderOptionsFunctor.h>
DPH::ImageType::Pointer GetBlurredVectorImage( DPH::ImageType::Pointer vectorImage, double sigma)
{
typedef itk::DiscreteGaussianImageFilter< itk::Image<DPH::DiffusionPixelType, 3 >, itk::Image<DPH::DiffusionPixelType, 3 > > GaussianFilterType;
typedef itk::VectorIndexSelectionCastImageFilter< DPH::ImageType, itk::Image<DPH::DiffusionPixelType, 3 > > IndexSelectionType;
IndexSelectionType::Pointer indexSelectionFilter = IndexSelectionType::New();
indexSelectionFilter->SetInput( vectorImage );
typedef itk::ComposeImageFilter< itk::Image<DPH::DiffusionPixelType, 3>, DPH::ImageType > ComposeFilterType;
ComposeFilterType::Pointer vec_composer = ComposeFilterType::New();
for( unsigned int i=0; i<vectorImage->GetVectorLength(); ++i)
{
GaussianFilterType::Pointer gaussian_filter = GaussianFilterType::New();
indexSelectionFilter->SetIndex( i );
gaussian_filter->SetInput( indexSelectionFilter->GetOutput() );
gaussian_filter->SetVariance( sigma );
vec_composer->SetInput(i, gaussian_filter->GetOutput() );
gaussian_filter->Update();
}
try
{
vec_composer->Update();
}
catch(const itk::ExceptionObject &e)
{
mitkThrow() << "[VectorImage.GaussianSmoothing] !! Failed with ITK Exception: " << e.what();
}
DPH::ImageType::Pointer smoothed_vector = vec_composer->GetOutput();
/*
itk::ImageFileWriter< DPH::ImageType >::Pointer writer =
itk::ImageFileWriter< DPH::ImageType >::New();
writer->SetInput( smoothed_vector );
writer->SetFileName( "/tmp/itk_smoothed_vector.nrrd");
writer->Update();*/
return smoothed_vector;
}
void KurtosisMapComputation( mitk::Image::Pointer input,
std::string output_prefix ,
std::string output_type,
std::string maskPath,
bool omitBZero,
double lower,
double upper )
{
DPH::ImageType::Pointer vectorImage = DPH::ImageType::New();
mitk::CastToItkImage( input, vectorImage );
typedef itk::DiffusionKurtosisReconstructionImageFilter< short, double > KurtosisFilterType;
KurtosisFilterType::Pointer kurtosis_filter = KurtosisFilterType::New();
kurtosis_filter->SetInput( GetBlurredVectorImage( vectorImage, 1.5 ) );
kurtosis_filter->SetReferenceBValue( DPH::GetReferenceBValue( input.GetPointer() ) );
kurtosis_filter->SetGradientDirections( DPH::GetGradientContainer( input.GetPointer() ) );
// kurtosis_filter->SetNumberOfThreads(1);
kurtosis_filter->SetOmitUnweightedValue(omitBZero);
kurtosis_filter->SetBoundariesForKurtosis(-lower,upper);
// kurtosis_filter->SetInitialSolution(const vnl_vector<double>& x0 );
if(maskPath != "")
{
mitk::Image::Pointer segmentation;
segmentation = mitk::IOUtil::Load<mitk::Image>(maskPath);
typedef itk::Image< short , 3> MaskImageType;
MaskImageType::Pointer vectorSeg = MaskImageType::New() ;
mitk::CastToItkImage( segmentation, vectorSeg );
kurtosis_filter->SetImageMask(vectorSeg) ;
}
try
{
kurtosis_filter->Update();
}
catch( const itk::ExceptionObject& e)
{
mitkThrow() << "Kurtosis fit failed with an ITK Exception: " << e.what();
}
mitk::Image::Pointer d_image = mitk::Image::New();
d_image->InitializeByItk( kurtosis_filter->GetOutput(0) );
d_image->SetVolume( kurtosis_filter->GetOutput(0)->GetBufferPointer() );
mitk::Image::Pointer k_image = mitk::Image::New();
k_image->InitializeByItk( kurtosis_filter->GetOutput(1) );
k_image->SetVolume( kurtosis_filter->GetOutput(1)->GetBufferPointer() );
std::string outputD_FileName = output_prefix + "_ADC_map." + output_type;
std::string outputK_FileName = output_prefix + "_AKC_map." + output_type;
try
{
mitk::IOUtil::Save( d_image, outputD_FileName );
mitk::IOUtil::Save( k_image, outputK_FileName );
}
catch( const itk::ExceptionObject& e)
{
mitkThrow() << "Failed to save the KurtosisFit Results due to exception: " << e.what();
}
}
int main( int argc, char* argv[] )
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Diffusion Kurtosis Fit");
parser.setCategory("Diffusion Related Measures");
parser.setContributor("MIC");
parser.setDescription("Fitting Kurtosis");
parser.setArgumentPrefix("--","-");
// mandatory arguments
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input: ", "input image (DWI)", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output Preifx: ", "Prefix for the output images, will append _ADC, _AKC accordingly ", us::Any(), false);
parser.addArgument("output_type", "", mitkDiffusionCommandLineParser::String, "Output Type: ", "choose data type of output image, e.g. '.nii' or '.nrrd' ");
// optional arguments
parser.addArgument("mask", "m", mitkDiffusionCommandLineParser::String, "Masking Image: ", "ROI (segmentation)", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("help", "h", mitkDiffusionCommandLineParser::Bool, "Help", "Show this help text");
parser.addArgument("omitbzero", "om", mitkDiffusionCommandLineParser::Bool, "Omit b0:", "Omit b0 value during fit (default = false)", us::Any());
parser.addArgument("lowerkbound", "kl", mitkDiffusionCommandLineParser::Float, "lower Kbound:", "Set (unsigned) lower boundary for Kurtosis parameter (default = -1000)", us::Any());
parser.addArgument("upperkbound", "ku", mitkDiffusionCommandLineParser::Float, "upper Kbound:", "Set upper boundary for Kurtosis parameter (default = 1000)", us::Any());
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0 || parsedArgs.count("help") || parsedArgs.count("h")){
std::cout << parser.helpText();
return EXIT_SUCCESS;
}
// mandatory arguments
std::string inFileName = us::any_cast<std::string>(parsedArgs["i"]);
std::string out_prefix = us::any_cast<std::string>(parsedArgs["o"]);
std::string maskPath = "";
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images"}, {});
mitk::Image::Pointer inputImage = mitk::IOUtil::Load<mitk::Image>(inFileName, &functor);
bool omitBZero = false;
double lower = -1000;
double upper = 1000;
std::string out_type = "nrrd";
if (parsedArgs.count("mask") || parsedArgs.count("m"))
{
maskPath = us::any_cast<std::string>(parsedArgs["mask"]);
}
if (parsedArgs.count("output_type") || parsedArgs.count("ot"))
{
out_type = us::any_cast<std::string>(parsedArgs["output_type"]);
}
if (parsedArgs.count("omitbzero") || parsedArgs.count("om"))
{
omitBZero = us::any_cast<bool>(parsedArgs["omitbzero"]);
}
if (parsedArgs.count("lowerkbound") || parsedArgs.count("kl"))
{
lower = us::any_cast<float>(parsedArgs["lowerkbound"]);
}
if (parsedArgs.count("upperkbound") || parsedArgs.count("ku"))
{
upper = us::any_cast<float>(parsedArgs["upperkbound"]);
}
if( !DPH::IsDiffusionWeightedImage( inputImage ) )
{
MITK_ERROR("DiffusionKurtosisFit.Input") << "No valid diffusion-weighted image provided, failed to load " << inFileName << " as DW Image. Aborting...";
return EXIT_FAILURE;
}
KurtosisMapComputation( inputImage,
out_prefix ,
out_type,
maskPath,
omitBZero,
lower,
upper);
}
diff --git a/Modules/DiffusionCmdApps/Quantification/MultishellMethods.cpp b/Modules/DiffusionCmdApps/Quantification/MultishellMethods.cpp
index 7cd1af0..118890c 100644
--- a/Modules/DiffusionCmdApps/Quantification/MultishellMethods.cpp
+++ b/Modules/DiffusionCmdApps/Quantification/MultishellMethods.cpp
@@ -1,215 +1,215 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <vector>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <itkImage.h>
#include <itkImageFileReader.h>
#include <itkExceptionObject.h>
#include <itkMetaDataObject.h>
#include <itkVectorImage.h>
#include <itkResampleImageFilter.h>
#include <mitkImage.h>
#include <mitkOdfImage.h>
#include <mitkBaseData.h>
#include "mitkDiffusionCommandLineParser.h"
#include <mitkLexicalCast.h>
#include <itkRadialMultishellToSingleshellImageFilter.h>
#include <itkADCAverageFunctor.h>
#include <itkBiExpFitFunctor.h>
#include <itkKurtosisFitFunctor.h>
#include <itkDwiGradientLengthCorrectionFilter.h>
#include <mitkIOUtil.h>
#include <mitkDiffusionPropertyHelper.h>
#include <mitkProperties.h>
#include <mitkImageCast.h>
#include <mitkITKImageImport.h>
#include <mitkPreferenceListReaderOptionsFunctor.h>
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Multishell Methods");
parser.setCategory("Preprocessing Tools");
parser.setDescription("");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "input file", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output file", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("adc", "D", mitkDiffusionCommandLineParser::Bool, "ADC:", "ADC Average", us::Any(), false);
parser.addArgument("akc", "K", mitkDiffusionCommandLineParser::Bool, "Kurtosis fit:", "Kurtosis Fit", us::Any(), false);
parser.addArgument("biexp", "B", mitkDiffusionCommandLineParser::Bool, "BiExp fit:", "BiExp fit", us::Any(), false);
parser.addArgument("targetbvalue", "b", mitkDiffusionCommandLineParser::String, "b Value:", "target bValue (mean, min, max)", us::Any(), false);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
// mandatory arguments
std::string inName = us::any_cast<std::string>(parsedArgs["i"]);
std::string outName = us::any_cast<std::string>(parsedArgs["o"]);
bool applyADC = us::any_cast<bool>(parsedArgs["adc"]);
bool applyAKC = us::any_cast<bool>(parsedArgs["akc"]);
bool applyBiExp = us::any_cast<bool>(parsedArgs["biexp"]);
std::string targetType = us::any_cast<std::string>(parsedArgs["targetbvalue"]);
try
{
std::cout << "Loading " << inName;
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images"}, {});
mitk::Image::Pointer dwi = mitk::IOUtil::Load<mitk::Image>(inName, &functor);
if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dwi ) )
{
typedef itk::RadialMultishellToSingleshellImageFilter<short, short> FilterType;
typedef itk::DwiGradientLengthCorrectionFilter CorrectionFilterType;
CorrectionFilterType::Pointer roundfilter = CorrectionFilterType::New();
roundfilter->SetRoundingValue( 1000 );
roundfilter->SetReferenceBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue( dwi ));
roundfilter->SetReferenceGradientDirectionContainer(mitk::DiffusionPropertyHelper::GetGradientContainer(dwi));
roundfilter->Update();
mitk::DiffusionPropertyHelper::SetReferenceBValue(dwi, roundfilter->GetNewBValue());
mitk::DiffusionPropertyHelper::SetGradientContainer(dwi, roundfilter->GetOutputGradientDirectionContainer());
// filter input parameter
const mitk::DiffusionPropertyHelper::BValueMapType
&originalShellMap = mitk::DiffusionPropertyHelper::GetBValueMap(dwi);
mitk::DiffusionPropertyHelper::ImageType::Pointer vectorImage = mitk::DiffusionPropertyHelper::ImageType::New();
mitk::CastToItkImage(dwi, vectorImage);
const mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer
gradientContainer = mitk::DiffusionPropertyHelper::GetGradientContainer(dwi);
const unsigned int
&bValue = mitk::DiffusionPropertyHelper::GetReferenceBValue( dwi );
// filter call
vnl_vector<double> bValueList(originalShellMap.size()-1);
double targetBValue = bValueList.mean();
mitk::DiffusionPropertyHelper::BValueMapType::const_iterator it = originalShellMap.begin();
++it; int i = 0 ;
for(; it != originalShellMap.end(); ++it)
bValueList.put(i++,it->first);
if( targetType == "mean" )
targetBValue = bValueList.mean();
else if( targetType == "min" )
targetBValue = bValueList.min_value();
else if( targetType == "max" )
targetBValue = bValueList.max_value();
if(applyADC)
{
FilterType::Pointer filter = FilterType::New();
filter->SetInput(vectorImage);
filter->SetOriginalGradientDirections(gradientContainer);
filter->SetOriginalBValueMap(originalShellMap);
filter->SetOriginalBValue(bValue);
itk::ADCAverageFunctor::Pointer functor = itk::ADCAverageFunctor::New();
functor->setListOfBValues(bValueList);
functor->setTargetBValue(targetBValue);
filter->SetFunctor(functor);
filter->Update();
// create new DWI image
mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( filter->GetOutput() );
mitk::DiffusionPropertyHelper::SetReferenceBValue(outImage, targetBValue);
mitk::DiffusionPropertyHelper::SetGradientContainer(outImage, filter->GetTargetGradientDirections());
mitk::DiffusionPropertyHelper::InitializeImage( outImage );
mitk::IOUtil::Save(outImage, (outName + "_ADC.dwi").c_str());
}
if(applyAKC)
{
FilterType::Pointer filter = FilterType::New();
filter->SetInput(vectorImage);
filter->SetOriginalGradientDirections(gradientContainer);
filter->SetOriginalBValueMap(originalShellMap);
filter->SetOriginalBValue(bValue);
itk::KurtosisFitFunctor::Pointer functor = itk::KurtosisFitFunctor::New();
functor->setListOfBValues(bValueList);
functor->setTargetBValue(targetBValue);
filter->SetFunctor(functor);
filter->Update();
// create new DWI image
mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( filter->GetOutput() );
mitk::DiffusionPropertyHelper::SetReferenceBValue(outImage, targetBValue);
mitk::DiffusionPropertyHelper::SetGradientContainer(outImage, filter->GetTargetGradientDirections());
mitk::DiffusionPropertyHelper::InitializeImage( outImage );
mitk::IOUtil::Save(outImage, (std::string(outName) + "_AKC.dwi").c_str());
}
if(applyBiExp)
{
FilterType::Pointer filter = FilterType::New();
filter->SetInput(vectorImage);
filter->SetOriginalGradientDirections(gradientContainer);
filter->SetOriginalBValueMap(originalShellMap);
filter->SetOriginalBValue(bValue);
itk::BiExpFitFunctor::Pointer functor = itk::BiExpFitFunctor::New();
functor->setListOfBValues(bValueList);
functor->setTargetBValue(targetBValue);
filter->SetFunctor(functor);
filter->Update();
// create new DWI image
mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( filter->GetOutput() );
mitk::DiffusionPropertyHelper::SetReferenceBValue(outImage, targetBValue);
mitk::DiffusionPropertyHelper::SetGradientContainer(outImage, filter->GetTargetGradientDirections());
mitk::DiffusionPropertyHelper::InitializeImage( outImage );
mitk::IOUtil::Save(outImage, (std::string(outName) + "_BiExp.dwi").c_str());
}
}
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/Quantification/QballReconstruction.cpp b/Modules/DiffusionCmdApps/Quantification/QballReconstruction.cpp
index 9f0357f..18a1b9a 100644
--- a/Modules/DiffusionCmdApps/Quantification/QballReconstruction.cpp
+++ b/Modules/DiffusionCmdApps/Quantification/QballReconstruction.cpp
@@ -1,266 +1,266 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkCoreObjectFactory.h>
#include "mitkImage.h"
#include "itkAnalyticalDiffusionQballReconstructionImageFilter.h"
#include <mitkLexicalCast.h>
#include "mitkDiffusionCommandLineParser.h"
#include <mitkIOUtil.h>
#include <itksys/SystemTools.hxx>
#include <mitkDiffusionPropertyHelper.h>
#include <mitkITKImageImport.h>
#include <mitkImageCast.h>
#include <mitkProperties.h>
#include <mitkIOUtil.h>
#include <mitkPreferenceListReaderOptionsFunctor.h>
#include <itkDiffusionMultiShellQballReconstructionImageFilter.h>
#include <itkDwiGradientLengthCorrectionFilter.h>
template<int L>
void TemplatedMultishellQBallReconstruction(float lambda, mitk::Image::Pointer dwi, bool output_sampled, int threshold, std::string outfilename)
{
typedef itk::DiffusionMultiShellQballReconstructionImageFilter<short,short,float,L,ODF_SAMPLING_SIZE> FilterType;
typename FilterType::Pointer filter = FilterType::New();
auto bMap = mitk::DiffusionPropertyHelper::GetBValueMap(dwi);
auto it1 = bMap.rbegin();
auto it2 = bMap.rbegin();
++it2;
// Get average distance
int avdistance = 0;
for(; it2 != bMap.rend(); ++it1, ++it2)
avdistance += static_cast<int>(it1->first - it2->first);
avdistance /= bMap.size()-1;
// Check if all shells are using the same averae distance
it1 = bMap.rbegin();
it2 = bMap.rbegin();
++it2;
for(; it2 != bMap.rend(); ++it1,++it2)
{
if(avdistance != static_cast<int>(it1->first - it2->first))
{
mitkThrow() << "Shells are not equidistant.";
}
}
auto itkVectorImagePointer = mitk::DiffusionPropertyHelper::GetItkVectorImage(dwi);
filter->SetBValueMap(bMap);
filter->SetGradientImage(mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), itkVectorImagePointer, mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi));
filter->SetThreshold(static_cast<short>(threshold));
filter->SetLambda(static_cast<double>(lambda));
filter->Update();
mitk::OdfImage::Pointer image = mitk::OdfImage::New();
mitk::Image::Pointer coeffsImage = dynamic_cast<mitk::Image*>(mitk::ShImage::New().GetPointer());
image->InitializeByItk( filter->GetOutput() );
image->SetVolume( filter->GetOutput()->GetBufferPointer() );
coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() );
coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() );
std::string coeffout = outfilename;
coeffout += ".nii.gz";
mitk::IOUtil::Save(coeffsImage, "SH_IMAGE", coeffout);
outfilename += ".odf";
if (output_sampled)
mitk::IOUtil::Save(image, outfilename);
}
template<int L>
void TemplatedCsaQBallReconstruction(float lambda, mitk::Image::Pointer dwi, bool output_sampled, int threshold, std::string outfilename)
{
typedef itk::AnalyticalDiffusionQballReconstructionImageFilter<short,short,float,4,ODF_SAMPLING_SIZE> FilterType;
auto itkVectorImagePointer = mitk::DiffusionPropertyHelper::GetItkVectorImage(dwi);
FilterType::Pointer filter = FilterType::New();
filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi));
filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), itkVectorImagePointer );
filter->SetThreshold(static_cast<short>(threshold));
filter->SetLambda(static_cast<double>(lambda));
// filter->SetUseMrtrixBasis(mrTrix);
filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE);
filter->Update();
mitk::OdfImage::Pointer image = mitk::OdfImage::New();
mitk::Image::Pointer coeffsImage = dynamic_cast<mitk::Image*>(mitk::ShImage::New().GetPointer());
image->InitializeByItk( filter->GetOutput() );
image->SetVolume( filter->GetOutput()->GetBufferPointer() );
coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() );
coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() );
std::string coeffout = outfilename;
coeffout += ".nii.gz";
mitk::IOUtil::Save(coeffsImage, "SH_IMAGE", coeffout);
outfilename += ".odf";
if (output_sampled)
mitk::IOUtil::Save(image, outfilename);
}
/**
* Perform Q-ball reconstruction using a spherical harmonics basis
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input image", "input raw dwi (.dwi or .nii/.nii.gz)", 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("sh_order", "", mitkDiffusionCommandLineParser::Int, "Spherical harmonics order", "spherical harmonics order", 4);
parser.addArgument("b0_threshold", "", mitkDiffusionCommandLineParser::Int, "b0 threshold", "baseline image intensity threshold", 0);
parser.addArgument("round_bvalues", "", mitkDiffusionCommandLineParser::Int, "Round b-values", "round to specified integer", 0);
parser.addArgument("lambda", "", mitkDiffusionCommandLineParser::Float, "Lambda", "ragularization factor lambda", 0.006);
parser.addArgument("output_sampled", "", mitkDiffusionCommandLineParser::Bool, "Output sampled ODFs", "output file containing the sampled ODFs");
parser.setCategory("Signal Modelling");
parser.setTitle("Qball Reconstruction");
parser.setDescription("");
parser.setContributor("MIC");
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
std::string inFileName = us::any_cast<std::string>(parsedArgs["i"]);
std::string outfilename = us::any_cast<std::string>(parsedArgs["o"]);
if (itksys::SystemTools::GetFilenamePath(outfilename).size()>0)
outfilename = itksys::SystemTools::GetFilenamePath(outfilename)+"/"+itksys::SystemTools::GetFilenameWithoutExtension(outfilename);
else
outfilename = itksys::SystemTools::GetFilenameWithoutExtension(outfilename);
int threshold = 0;
if (parsedArgs.count("b0_threshold"))
threshold = us::any_cast<int>(parsedArgs["b0_threshold"]);
int round_bvalues = 0;
if (parsedArgs.count("round_bvalues"))
round_bvalues = us::any_cast<int>(parsedArgs["round_bvalues"]);
int shOrder = 4;
if (parsedArgs.count("sh_order"))
shOrder = us::any_cast<int>(parsedArgs["sh_order"]);
float lambda = 0.006f;
if (parsedArgs.count("lambda"))
lambda = us::any_cast<float>(parsedArgs["lambda"]);
bool outCoeffs = false;
if (parsedArgs.count("output_coeffs"))
outCoeffs = us::any_cast<bool>(parsedArgs["output_coeffs"]);
// bool mrTrix = false;
// if (parsedArgs.count("mrtrix"))
// mrTrix = us::any_cast<bool>(parsedArgs["mrtrix"]);
try
{
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images"}, {});
std::vector< mitk::BaseData::Pointer > infile = mitk::IOUtil::Load(inFileName, &functor);
mitk::Image::Pointer dwi = dynamic_cast<mitk::Image*>(infile.at(0).GetPointer());
if (round_bvalues>0)
{
MITK_INFO << "Rounding b-values";
typedef itk::DwiGradientLengthCorrectionFilter FilterType;
FilterType::Pointer filter = FilterType::New();
filter->SetRoundingValue(round_bvalues);
filter->SetReferenceBValue(static_cast<double>(mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi)));
filter->SetReferenceGradientDirectionContainer(mitk::DiffusionPropertyHelper::GetGradientContainer(dwi));
filter->Update();
mitk::DiffusionPropertyHelper::SetReferenceBValue(dwi, static_cast<float>(filter->GetNewBValue()));
mitk::DiffusionPropertyHelper::CopyProperties(dwi, dwi, true);
mitk::DiffusionPropertyHelper::SetGradientContainer(dwi, filter->GetOutputGradientDirectionContainer());
mitk::DiffusionPropertyHelper::InitializeImage(dwi);
}
auto bMap = mitk::DiffusionPropertyHelper::GetBValueMap(dwi);
if(bMap.size()!=4 && bMap.size()!=2)
mitkThrow() << "Only three equidistant shells or a single shell are supported. Found " << bMap.size();
MITK_INFO << "Averaging redundant gradients";
mitk::DiffusionPropertyHelper::AverageRedundantGradients(dwi, 0.001);
MITK_INFO << "SH order: " << shOrder;
MITK_INFO << "lambda: " << lambda;
MITK_INFO << "B0 threshold: " << threshold;
MITK_INFO << "Round bvalues: " << round_bvalues;
switch ( shOrder )
{
case 4:
{
if(bMap.size()==2)
TemplatedCsaQBallReconstruction<4>(lambda, dwi, outCoeffs, threshold, outfilename);
else if(bMap.size()==4)
TemplatedMultishellQBallReconstruction<4>(lambda, dwi, outCoeffs, threshold, outfilename);
break;
}
case 6:
{
if(bMap.size()==2)
TemplatedCsaQBallReconstruction<6>(lambda, dwi, outCoeffs, threshold, outfilename);
else if(bMap.size()==4)
TemplatedMultishellQBallReconstruction<6>(lambda, dwi, outCoeffs, threshold, outfilename);
break;
}
case 8:
{
if(bMap.size()==2)
TemplatedCsaQBallReconstruction<8>(lambda, dwi, outCoeffs, threshold, outfilename);
else if(bMap.size()==4)
TemplatedMultishellQBallReconstruction<8>(lambda, dwi, outCoeffs, threshold, outfilename);
break;
}
case 10:
{
if(bMap.size()==2)
TemplatedCsaQBallReconstruction<10>(lambda, dwi, outCoeffs, threshold, outfilename);
else if(bMap.size()==4)
TemplatedMultishellQBallReconstruction<10>(lambda, dwi, outCoeffs, threshold, outfilename);
break;
}
case 12:
{
if(bMap.size()==2)
TemplatedCsaQBallReconstruction<12>(lambda, dwi, outCoeffs, threshold, outfilename);
else if(bMap.size()==4)
TemplatedMultishellQBallReconstruction<12>(lambda, dwi, outCoeffs, threshold, outfilename);
break;
}
default:
{
mitkThrow() << "SH order not supported";
}
}
}
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/DiffusionCmdApps/Quantification/TensorReconstruction.cpp b/Modules/DiffusionCmdApps/Quantification/TensorReconstruction.cpp
index 0c5afa0..bd3df17 100644
--- a/Modules/DiffusionCmdApps/Quantification/TensorReconstruction.cpp
+++ b/Modules/DiffusionCmdApps/Quantification/TensorReconstruction.cpp
@@ -1,135 +1,135 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkImageCast.h>
#include "mitkBaseData.h"
#include <mitkDiffusionPropertyHelper.h>
#include <itkTensorReconstructionWithEigenvalueCorrectionFilter.h>
#include <itkDiffusionTensor3DReconstructionImageFilter.h>
#include <itkDiffusionTensor3D.h>
#include <itkImageFileWriter.h>
#include <itkNrrdImageIO.h>
#include "mitkDiffusionCommandLineParser.h"
#include <itksys/SystemTools.hxx>
#include <mitkIOUtil.h>
#include <mitkLocaleSwitch.h>
/**
* 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<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
std::string inFileName = us::any_cast<std::string>(parsedArgs["i"]);
std::string outfilename = us::any_cast<std::string>(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<int>(parsedArgs["b0_threshold"]);
bool correct_negative_eigenv = false;
if (parsedArgs.count("correct_negative_eigenv"))
correct_negative_eigenv = us::any_cast<bool>(parsedArgs["correct_negative_eigenv"]);
try
{
mitk::Image::Pointer dwi = mitk::IOUtil::Load<mitk::Image>(inFileName);
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( mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), 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/DiffusionCmdApps/Tractography/GlobalTractography.cpp b/Modules/DiffusionCmdApps/Tractography/GlobalTractography.cpp
index c621f61..fd20d77 100644
--- a/Modules/DiffusionCmdApps/Tractography/GlobalTractography.cpp
+++ b/Modules/DiffusionCmdApps/Tractography/GlobalTractography.cpp
@@ -1,134 +1,134 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkImageCast.h>
#include <mitkOdfImage.h>
#include <mitkTensorImage.h>
#include <mitkFiberBundle.h>
#include <itkGibbsTrackingFilter.h>
#include <itkDiffusionTensor3D.h>
#include <itkShCoefficientImageImporter.h>
#include <itkShToOdfImageFilter.h>
#include <mitkImageToItk.h>
#include <mitkIOUtil.h>
#include "mitkDiffusionCommandLineParser.h"
#include <boost/algorithm/string.hpp>
#include <itkFlipImageFilter.h>
#include <mitkCoreObjectFactory.h>
#include <mitkPreferenceListReaderOptionsFunctor.h>
#include <mitkShImage.h>
#include <mitkDiffusionFunctionCollection.h>
/*!
\brief Perform global fiber tractography (Gibbs tractography)
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Gibbs Tracking");
parser.setCategory("Fiber Tracking and Processing Methods");
parser.setDescription("Perform global fiber tractography (Gibbs tractography)");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "input image (tensor, ODF or SH-coefficient image)", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output tractogram", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("parameters", "", mitkDiffusionCommandLineParser::String, "Parameters:", "parameter file (.gtp)", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("mask", "", mitkDiffusionCommandLineParser::String, "Mask:", "binary mask image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
std::string inFileName = us::any_cast<std::string>(parsedArgs["i"]);
std::string paramFileName = us::any_cast<std::string>(parsedArgs["parameters"]);
std::string outFileName = us::any_cast<std::string>(parsedArgs["o"]);
try
{
// instantiate gibbs tracker
typedef itk::Vector<float, ODF_SAMPLING_SIZE> OdfVectorType;
typedef itk::Image<OdfVectorType,3> ItkOdfImageType;
typedef itk::GibbsTrackingFilter<ItkOdfImageType> GibbsTrackingFilterType;
GibbsTrackingFilterType::Pointer gibbsTracker = GibbsTrackingFilterType::New();
// load input image
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"SH Image"}, {});
mitk::Image::Pointer mitkImage = mitk::IOUtil::Load<mitk::Image>(inFileName, &functor);
// try to cast to Odf image
if( dynamic_cast<mitk::OdfImage*>(mitkImage.GetPointer()) )
{
mitk::OdfImage::Pointer mitkOdfImage = dynamic_cast<mitk::OdfImage*>(mitkImage.GetPointer());
ItkOdfImageType::Pointer itk_odf = ItkOdfImageType::New();
mitk::CastToItkImage(mitkOdfImage, itk_odf);
gibbsTracker->SetOdfImage(itk_odf.GetPointer());
}
else if( dynamic_cast<mitk::TensorImage*>(mitkImage.GetPointer()) )
{
typedef itk::Image< itk::DiffusionTensor3D<float>, 3 > ItkTensorImage;
mitk::TensorImage::Pointer mitkTensorImage = dynamic_cast<mitk::TensorImage*>(mitkImage.GetPointer());
ItkTensorImage::Pointer itk_dti = ItkTensorImage::New();
mitk::CastToItkImage(mitkTensorImage, itk_dti);
gibbsTracker->SetTensorImage(itk_dti);
}
else if ( dynamic_cast<mitk::ShImage*>(mitkImage.GetPointer()) )
{
MITK_INFO << "Assuming MITK/MRtrix style SH convention!";
mitk::Image::Pointer shImage = dynamic_cast<mitk::Image*>(mitkImage.GetPointer());
gibbsTracker->SetOdfImage(mitk::convert::GetItkOdfFromShImage(shImage));
}
else
return EXIT_FAILURE;
// global tracking
if (parsedArgs.count("mask"))
{
typedef itk::Image<float,3> MaskImgType;
mitk::Image::Pointer mitkMaskImage = mitk::IOUtil::Load<mitk::Image>(us::any_cast<std::string>(parsedArgs["mask"]));
MaskImgType::Pointer itk_mask = MaskImgType::New();
mitk::CastToItkImage(mitkMaskImage, itk_mask);
gibbsTracker->SetMaskImage(itk_mask);
}
gibbsTracker->SetDuplicateImage(false);
gibbsTracker->SetLoadParameterFile( paramFileName );
// gibbsTracker->SetLutPath( "" );
gibbsTracker->Update();
mitk::FiberBundle::Pointer mitkFiberBundle = mitk::FiberBundle::New(gibbsTracker->GetFiberBundle());
mitkFiberBundle->SetTrackVisHeader(mitkImage->GetGeometry());
mitk::IOUtil::Save(mitkFiberBundle, outFileName );
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/Tractography/RfTraining.cpp b/Modules/DiffusionCmdApps/Tractography/RfTraining.cpp
index 9ba7248..67d200e 100644
--- a/Modules/DiffusionCmdApps/Tractography/RfTraining.cpp
+++ b/Modules/DiffusionCmdApps/Tractography/RfTraining.cpp
@@ -1,238 +1,238 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkBaseData.h>
#include <mitkImageCast.h>
#include <mitkImageToItk.h>
#include <metaCommand.h>
#include "mitkDiffusionCommandLineParser.h"
#include <usAny.h>
#include <mitkIOUtil.h>
#include <iostream>
#include <fstream>
#include <itksys/SystemTools.hxx>
#include <mitkCoreObjectFactory.h>
#include <mitkPreferenceListReaderOptionsFunctor.h>
#include <mitkFiberBundle.h>
#include <mitkTrackingHandlerRandomForest.h>
#include <mitkTractographyForest.h>
#define _USE_MATH_DEFINES
#include <math.h>
/*!
\brief Train random forest classifier for machine learning based streamline tractography
*/
int main(int argc, char* argv[])
{
MITK_INFO << "RfTraining";
mitkDiffusionCommandLineParser parser;
parser.setTitle("Trains Random Forests for Machine Learning Based Tractography");
parser.setCategory("Fiber Tracking and Processing Methods");
parser.setDescription("Train random forest classifier for machine learning based streamline tractography");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.beginGroup("1. Mandatory arguments:");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::StringList, "DWIs:", "input diffusion-weighted images", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "t", mitkDiffusionCommandLineParser::StringList, "Tractograms:", "input training tractograms", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Forest:", "output random forest (HDF5)", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.endGroup();
parser.beginGroup("2. Additional input images:");
parser.addArgument("masks", "", mitkDiffusionCommandLineParser::StringList, "Masks:", "restrict training using a binary mask image", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("wm_masks", "", mitkDiffusionCommandLineParser::StringList, "WM-Masks:", "if no binary white matter mask is specified, the envelope of the input tractogram is used", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("volume_modification_images", "", mitkDiffusionCommandLineParser::StringList, "Volume modification images:", "specify a list of float images that modify the fiber density", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("additional_feature_images", "", mitkDiffusionCommandLineParser::StringList, "Additional feature images:", "specify a list of float images that hold additional features (float)", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.endGroup();
parser.beginGroup("3. Forest parameters:");
parser.addArgument("num_trees", "", mitkDiffusionCommandLineParser::Int, "Number of trees:", "number of trees", 30);
parser.addArgument("max_tree_depth", "", mitkDiffusionCommandLineParser::Int, "Max. tree depth:", "maximum tree depth", 25);
parser.addArgument("sample_fraction", "", mitkDiffusionCommandLineParser::Float, "Sample fraction:", "fraction of samples used per tree", 0.7);
parser.endGroup();
parser.beginGroup("4. Feature parameters:");
parser.addArgument("use_sh_features", "", mitkDiffusionCommandLineParser::Bool, "Use SH features:", "use SH features", false);
parser.addArgument("sampling_distance", "", mitkDiffusionCommandLineParser::Float, "Sampling distance:", "resampling parameter for the input tractogram in mm (determines number of white-matter samples)", us::Any());
parser.addArgument("max_wm_samples", "", mitkDiffusionCommandLineParser::Int, "Max. num. WM samples:", "upper limit for the number of WM samples");
parser.addArgument("num_gm_samples", "", mitkDiffusionCommandLineParser::Int, "Number of gray matter samples per voxel:", "Number of gray matter samples per voxel", us::Any());
parser.endGroup();
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
bool shfeatures = false;
if (parsedArgs.count("use_sh_features"))
shfeatures = us::any_cast<bool>(parsedArgs["use_sh_features"]);
mitkDiffusionCommandLineParser::StringContainerType imageFiles = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["i"]);
mitkDiffusionCommandLineParser::StringContainerType wmMaskFiles;
if (parsedArgs.count("wm_masks"))
wmMaskFiles = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["wm_masks"]);
mitkDiffusionCommandLineParser::StringContainerType volModFiles;
if (parsedArgs.count("volume_modification_images"))
volModFiles = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["volume_modification_images"]);
mitkDiffusionCommandLineParser::StringContainerType addFeatFiles;
if (parsedArgs.count("additional_feature_images"))
addFeatFiles = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["additional_feature_images"]);
mitkDiffusionCommandLineParser::StringContainerType maskFiles;
if (parsedArgs.count("masks"))
maskFiles = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["masks"]);
std::string forestFile = us::any_cast<std::string>(parsedArgs["o"]);
mitkDiffusionCommandLineParser::StringContainerType tractogramFiles;
if (parsedArgs.count("t"))
tractogramFiles = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["t"]);
int num_trees = 30;
if (parsedArgs.count("num_trees"))
num_trees = us::any_cast<int>(parsedArgs["num_trees"]);
int gm_samples = -1;
if (parsedArgs.count("num_gm_samples"))
gm_samples = us::any_cast<int>(parsedArgs["num_gm_samples"]);
float sampling_distance = -1;
if (parsedArgs.count("sampling_distance"))
sampling_distance = us::any_cast<float>(parsedArgs["sampling_distance"]);
int max_tree_depth = 25;
if (parsedArgs.count("max_tree_depth"))
max_tree_depth = us::any_cast<int>(parsedArgs["max_tree_depth"]);
double sample_fraction = 0.7;
if (parsedArgs.count("sample_fraction"))
sample_fraction = us::any_cast<float>(parsedArgs["sample_fraction"]);
int maxWmSamples = -1;
if (parsedArgs.count("max_wm_samples"))
maxWmSamples = us::any_cast<int>(parsedArgs["max_wm_samples"]);
MITK_INFO << "loading diffusion-weighted images";
std::vector< mitk::Image::Pointer > rawData;
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images"}, {});
for (auto imgFile : imageFiles)
{
auto dwi = mitk::IOUtil::Load<mitk::Image>(imgFile, &functor);
rawData.push_back(dwi);
}
typedef itk::Image<float, 3> ItkFloatImgType;
typedef itk::Image<unsigned char, 3> ItkUcharImgType;
MITK_INFO << "loading mask images";
std::vector< ItkUcharImgType::Pointer > maskImageVector;
for (auto maskFile : maskFiles)
{
mitk::Image::Pointer img = mitk::IOUtil::Load<mitk::Image>(maskFile);
ItkUcharImgType::Pointer mask = ItkUcharImgType::New();
mitk::CastToItkImage(img, mask);
maskImageVector.push_back(mask);
}
MITK_INFO << "loading white matter mask images";
std::vector< ItkUcharImgType::Pointer > wmMaskImageVector;
for (auto wmFile : wmMaskFiles)
{
mitk::Image::Pointer img = mitk::IOUtil::Load<mitk::Image>(wmFile);
ItkUcharImgType::Pointer wmmask = ItkUcharImgType::New();
mitk::CastToItkImage(img, wmmask);
wmMaskImageVector.push_back(wmmask);
}
MITK_INFO << "loading tractograms";
std::vector< mitk::FiberBundle::Pointer > tractograms;
for (auto tractFile : tractogramFiles)
{
mitk::FiberBundle::Pointer fib = mitk::IOUtil::Load<mitk::FiberBundle>(tractFile);
tractograms.push_back(fib);
}
MITK_INFO << "loading white volume modification images";
std::vector< ItkFloatImgType::Pointer > volumeModImages;
for (auto file : volModFiles)
{
mitk::Image::Pointer img = mitk::IOUtil::Load<mitk::Image>(file);
ItkFloatImgType::Pointer itkimg = ItkFloatImgType::New();
mitk::CastToItkImage(img, itkimg);
volumeModImages.push_back(itkimg);
}
MITK_INFO << "loading additional feature images";
std::vector< std::vector< ItkFloatImgType::Pointer > > addFeatImages;
for (std::size_t i=0; i<rawData.size(); ++i)
addFeatImages.push_back(std::vector< ItkFloatImgType::Pointer >());
int c = 0;
for (auto file : addFeatFiles)
{
mitk::Image::Pointer img = mitk::IOUtil::Load<mitk::Image>(file);
ItkFloatImgType::Pointer itkimg = ItkFloatImgType::New();
mitk::CastToItkImage(img, itkimg);
addFeatImages.at(c%addFeatImages.size()).push_back(itkimg);
c++;
}
mitk::TractographyForest::Pointer forest = nullptr;
if (shfeatures)
{
mitk::TrackingHandlerRandomForest<6,28> forestHandler;
forestHandler.SetDwis(rawData);
forestHandler.SetMaskImages(maskImageVector);
forestHandler.SetWhiteMatterImages(wmMaskImageVector);
forestHandler.SetFiberVolumeModImages(volumeModImages);
forestHandler.SetAdditionalFeatureImages(addFeatImages);
forestHandler.SetTractograms(tractograms);
forestHandler.SetNumTrees(num_trees);
forestHandler.SetMaxTreeDepth(max_tree_depth);
forestHandler.SetGrayMatterSamplesPerVoxel(gm_samples);
forestHandler.SetSampleFraction(sample_fraction);
forestHandler.SetFiberSamplingStep(sampling_distance);
forestHandler.SetMaxNumWmSamples(maxWmSamples);
forestHandler.StartTraining();
forest = forestHandler.GetForest();
}
else
{
mitk::TrackingHandlerRandomForest<6,100> forestHandler;
forestHandler.SetDwis(rawData);
forestHandler.SetMaskImages(maskImageVector);
forestHandler.SetWhiteMatterImages(wmMaskImageVector);
forestHandler.SetFiberVolumeModImages(volumeModImages);
forestHandler.SetAdditionalFeatureImages(addFeatImages);
forestHandler.SetTractograms(tractograms);
forestHandler.SetNumTrees(num_trees);
forestHandler.SetMaxTreeDepth(max_tree_depth);
forestHandler.SetGrayMatterSamplesPerVoxel(gm_samples);
forestHandler.SetSampleFraction(sample_fraction);
forestHandler.SetFiberSamplingStep(sampling_distance);
forestHandler.SetMaxNumWmSamples(maxWmSamples);
forestHandler.StartTraining();
forest = forestHandler.GetForest();
}
mitk::IOUtil::Save(forest, forestFile);
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/Tractography/StreamlineTractography.cpp b/Modules/DiffusionCmdApps/Tractography/StreamlineTractography.cpp
index f697c7b..e03c52b 100644
--- a/Modules/DiffusionCmdApps/Tractography/StreamlineTractography.cpp
+++ b/Modules/DiffusionCmdApps/Tractography/StreamlineTractography.cpp
@@ -1,577 +1,577 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkBaseData.h>
#include <mitkImageCast.h>
#include <mitkImageToItk.h>
#include <metaCommand.h>
#include <mitkDiffusionCommandLineParser.h>
#include <mitkLog.h>
#include <usAny.h>
#include <mitkIOUtil.h>
#include <iostream>
#include <fstream>
#include <itksys/SystemTools.hxx>
#include <mitkCoreObjectFactory.h>
#include <omp.h>
#include <itksys/SystemTools.hxx>
#include <mitkFiberBundle.h>
#include <itkStreamlineTrackingFilter.h>
#include <Algorithms/TrackingHandlers/mitkTrackingDataHandler.h>
#include <Algorithms/TrackingHandlers/mitkTrackingHandlerRandomForest.h>
#include <Algorithms/TrackingHandlers/mitkTrackingHandlerPeaks.h>
#include <Algorithms/TrackingHandlers/mitkTrackingHandlerTensor.h>
#include <Algorithms/TrackingHandlers/mitkTrackingHandlerOdf.h>
#include <itkTensorImageToOdfImageFilter.h>
#include <mitkTractographyForest.h>
#include <mitkPreferenceListReaderOptionsFunctor.h>
#include <mitkStreamlineTractographyParameters.h>
#define _USE_MATH_DEFINES
#include <math.h>
const int numOdfSamples = 200;
typedef itk::Image< itk::Vector< float, numOdfSamples > , 3 > SampledShImageType;
/*!
\brief
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Streamline Tractography");
parser.setCategory("Fiber Tracking and Processing Methods");
parser.setDescription("Perform streamline tractography");
parser.setContributor("MIC");
// parameters fo all methods
parser.setArgumentPrefix("--", "-");
parser.beginGroup("1. Mandatory arguments:");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::StringList, "Input:", "input image (multiple possible for 'DetTensor' algorithm)", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output fiberbundle/probability map", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("type", "", mitkDiffusionCommandLineParser::String, "Type:", "which tracker to use (Peaks; Tensor; ODF; ODF-DIPY/FSL; RF)", us::Any(), false);
parser.addArgument("probabilistic", "", mitkDiffusionCommandLineParser::Bool, "Probabilistic:", "Probabilistic tractography", us::Any(false));
parser.endGroup();
parser.beginGroup("2. Seeding:");
parser.addArgument("seeds", "", mitkDiffusionCommandLineParser::Int, "Seeds per voxel:", "number of seed points per voxel", 1);
parser.addArgument("seed_image", "", mitkDiffusionCommandLineParser::String, "Seed image:", "mask image defining seed voxels", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("trials_per_seed", "", mitkDiffusionCommandLineParser::Int, "Max. trials per seed:", "try each seed N times until a valid streamline is obtained (only for probabilistic tractography)", 10);
parser.addArgument("max_tracts", "", mitkDiffusionCommandLineParser::Int, "Max. number of tracts:", "tractography is stopped if the reconstructed number of tracts is exceeded", -1);
parser.endGroup();
parser.beginGroup("3. Tractography constraints:");
parser.addArgument("tracking_mask", "", mitkDiffusionCommandLineParser::String, "Mask image:", "streamlines leaving the mask will stop immediately", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("stop_image", "", mitkDiffusionCommandLineParser::String, "Stop ROI image:", "streamlines entering the mask will stop immediately", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("exclusion_image", "", mitkDiffusionCommandLineParser::String, "Exclusion ROI image:", "streamlines entering the mask will be discarded", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("ep_constraint", "", mitkDiffusionCommandLineParser::String, "Endpoint constraint:", "determines which fibers are accepted based on their endpoint location - options are NONE, EPS_IN_TARGET, EPS_IN_TARGET_LABELDIFF, EPS_IN_SEED_AND_TARGET, MIN_ONE_EP_IN_TARGET, ONE_EP_IN_TARGET and NO_EP_IN_TARGET", us::Any());
parser.addArgument("target_image", "", mitkDiffusionCommandLineParser::String, "Target ROI image:", "effact depends on the chosen endpoint constraint (option ep_constraint)", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.endGroup();
parser.beginGroup("4. Streamline integration parameters:");
parser.addArgument("sharpen_odfs", "", mitkDiffusionCommandLineParser::Bool, "SHarpen ODFs:", "if you are using dODF images as input, it is advisable to sharpen the ODFs (min-max normalize and raise to the power of 4). this is not necessary for CSD fODFs, since they are narurally much sharper.");
parser.addArgument("cutoff", "", mitkDiffusionCommandLineParser::Float, "Cutoff:", "set the FA, GFA or Peak amplitude cutoff for terminating tracks", 0.1);
parser.addArgument("odf_cutoff", "", mitkDiffusionCommandLineParser::Float, "ODF Cutoff:", "threshold on the ODF magnitude. this is useful in case of CSD fODF tractography.", 0.0);
parser.addArgument("step_size", "", mitkDiffusionCommandLineParser::Float, "Step size:", "step size (in voxels)", 0.5);
parser.addArgument("min_tract_length", "", mitkDiffusionCommandLineParser::Float, "Min. tract length:", "minimum fiber length (in mm)", 20);
parser.addArgument("angular_threshold", "", mitkDiffusionCommandLineParser::Float, "Angular threshold:", "angular threshold between two successive steps, (default: 90° * step_size, minimum 15°)");
parser.addArgument("loop_check", "", mitkDiffusionCommandLineParser::Float, "Check for loops:", "threshold on angular stdev over the last 4 voxel lengths");
parser.addArgument("peak_jitter", "", mitkDiffusionCommandLineParser::Float, "Peak jitter:", "important for probabilistic peak tractography and peak prior. actual jitter is drawn from a normal distribution with peak_jitter*fabs(direction_value) as standard deviation.", 0.01);
parser.endGroup();
parser.beginGroup("5. Tractography prior:");
parser.addArgument("prior_image", "", mitkDiffusionCommandLineParser::String, "Peak prior:", "tractography prior in thr for of a peak image", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("prior_weight", "", mitkDiffusionCommandLineParser::Float, "Prior weight", "weighting factor between prior and data.", 0.5);
parser.addArgument("dont_restrict_to_prior", "", mitkDiffusionCommandLineParser::Bool, "Don't restrict to prior:", "don't restrict tractography to regions where the prior is valid.", us::Any(false));
parser.addArgument("no_new_directions_from_prior", "", mitkDiffusionCommandLineParser::Bool, "No new directios from prior:", "the prior cannot create directions where there are none in the data.", us::Any(false));
parser.addArgument("prior_flip_x", "", mitkDiffusionCommandLineParser::Bool, "Prior Flip X:", "multiply x-coordinate of prior direction by -1");
parser.addArgument("prior_flip_y", "", mitkDiffusionCommandLineParser::Bool, "Prior Flip Y:", "multiply y-coordinate of prior direction by -1");
parser.addArgument("prior_flip_z", "", mitkDiffusionCommandLineParser::Bool, "Prior Flip Z:", "multiply z-coordinate of prior direction by -1");
parser.endGroup();
parser.beginGroup("6. Neighborhood sampling:");
parser.addArgument("num_samples", "", mitkDiffusionCommandLineParser::Int, "Num. neighborhood samples:", "number of neighborhood samples that are use to determine the next progression direction", 0);
parser.addArgument("sampling_distance", "", mitkDiffusionCommandLineParser::Float, "Sampling distance:", "distance of neighborhood sampling points (in voxels)", 0.25);
parser.addArgument("use_stop_votes", "", mitkDiffusionCommandLineParser::Bool, "Use stop votes:", "use stop votes");
parser.addArgument("use_only_forward_samples", "", mitkDiffusionCommandLineParser::Bool, "Use only forward samples:", "use only forward samples");
parser.endGroup();
parser.beginGroup("7. Tensor tractography specific:");
parser.addArgument("tend_f", "", mitkDiffusionCommandLineParser::Float, "Weight f", "weighting factor between first eigenvector (f=1 equals FACT tracking) and input vector dependent direction (f=0).", 1.0);
parser.addArgument("tend_g", "", mitkDiffusionCommandLineParser::Float, "Weight g", "weighting factor between input vector (g=0) and tensor deflection (g=1 equals TEND tracking)", 0.0);
parser.endGroup();
parser.beginGroup("8. Random forest tractography specific:");
parser.addArgument("forest", "", mitkDiffusionCommandLineParser::String, "Forest:", "input random forest (HDF5 file)", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("use_sh_features", "", mitkDiffusionCommandLineParser::Bool, "Use SH features:", "use SH features");
parser.endGroup();
parser.beginGroup("9. Additional input:");
parser.addArgument("additional_images", "", mitkDiffusionCommandLineParser::StringList, "Additional images:", "specify a list of float images that hold additional information (FA, GFA, additional features for RF tractography)", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.endGroup();
parser.beginGroup("10. Misc:");
parser.addArgument("flip_x", "", mitkDiffusionCommandLineParser::Bool, "Flip X:", "multiply x-coordinate of direction proposal by -1");
parser.addArgument("flip_y", "", mitkDiffusionCommandLineParser::Bool, "Flip Y:", "multiply y-coordinate of direction proposal by -1");
parser.addArgument("flip_z", "", mitkDiffusionCommandLineParser::Bool, "Flip Z:", "multiply z-coordinate of direction proposal by -1");
parser.addArgument("no_data_interpolation", "", mitkDiffusionCommandLineParser::Bool, "Don't interpolate input data:", "don't interpolate input image values");
parser.addArgument("no_mask_interpolation", "", mitkDiffusionCommandLineParser::Bool, "Don't interpolate masks:", "don't interpolate mask image values");
parser.addArgument("compress", "", mitkDiffusionCommandLineParser::Float, "Compress:", "compress output fibers using the given error threshold (in mm)");
parser.addArgument("fix_seed", "", mitkDiffusionCommandLineParser::Bool, "Fix Random Seed:", "always use the same random numbers");
parser.addArgument("parameter_file", "", mitkDiffusionCommandLineParser::String, "Parameter File:", "load parameters from json file (svae using MITK Diffusion GUI). the parameters loaded form this file are overwritten by the manually set parameters.", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.endGroup();
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
mitkDiffusionCommandLineParser::StringContainerType input_files = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["i"]);
std::string outFile = us::any_cast<std::string>(parsedArgs["o"]);
std::string type = us::any_cast<std::string>(parsedArgs["type"]);
std::shared_ptr< mitk::StreamlineTractographyParameters > params = std::make_shared<mitk::StreamlineTractographyParameters>();
if (parsedArgs.count("parameter_file"))
{
auto parameter_file = us::any_cast<std::string>(parsedArgs["parameter_file"]);
params->LoadParameters(parameter_file);
}
if (parsedArgs.count("probabilistic"))
params->m_Mode = mitk::StreamlineTractographyParameters::MODE::PROBABILISTIC;
else {
params->m_Mode = mitk::StreamlineTractographyParameters::MODE::DETERMINISTIC;
}
std::string prior_image = "";
if (parsedArgs.count("prior_image"))
prior_image = us::any_cast<std::string>(parsedArgs["prior_image"]);
if (parsedArgs.count("prior_weight"))
params->m_Weight = us::any_cast<float>(parsedArgs["prior_weight"]);
if (parsedArgs.count("fix_seed"))
params->m_FixRandomSeed = us::any_cast<bool>(parsedArgs["fix_seed"]);
params->m_RestrictToPrior = true;
if (parsedArgs.count("dont_restrict_to_prior"))
params->m_RestrictToPrior = !us::any_cast<bool>(parsedArgs["dont_restrict_to_prior"]);
params->m_NewDirectionsFromPrior = true;
if (parsedArgs.count("no_new_directions_from_prior"))
params->m_NewDirectionsFromPrior = !us::any_cast<bool>(parsedArgs["no_new_directions_from_prior"]);
params->m_SharpenOdfs = false;
if (parsedArgs.count("sharpen_odfs"))
params->m_SharpenOdfs = us::any_cast<bool>(parsedArgs["sharpen_odfs"]);
params->m_InterpolateTractographyData = true;
if (parsedArgs.count("no_data_interpolation"))
params->m_InterpolateTractographyData = !us::any_cast<bool>(parsedArgs["no_data_interpolation"]);
params->m_InterpolateRoiImages = true;
if (parsedArgs.count("no_mask_interpolation"))
params->m_InterpolateRoiImages = !us::any_cast<bool>(parsedArgs["no_mask_interpolation"]);
bool use_sh_features = false;
if (parsedArgs.count("use_sh_features"))
use_sh_features = us::any_cast<bool>(parsedArgs["use_sh_features"]);
params->m_StopVotes = false;
if (parsedArgs.count("use_stop_votes"))
params->m_StopVotes = us::any_cast<bool>(parsedArgs["use_stop_votes"]);
params->m_OnlyForwardSamples = false;
if (parsedArgs.count("use_only_forward_samples"))
params->m_OnlyForwardSamples = us::any_cast<bool>(parsedArgs["use_only_forward_samples"]);
params->m_FlipX = false;
if (parsedArgs.count("flip_x"))
params->m_FlipX = us::any_cast<bool>(parsedArgs["flip_x"]);
params->m_FlipY = false;
if (parsedArgs.count("flip_y"))
params->m_FlipY = us::any_cast<bool>(parsedArgs["flip_y"]);
params->m_FlipZ = false;
if (parsedArgs.count("flip_z"))
params->m_FlipZ = us::any_cast<bool>(parsedArgs["flip_z"]);
bool prior_flip_x = false;
if (parsedArgs.count("prior_flip_x"))
prior_flip_x = us::any_cast<bool>(parsedArgs["prior_flip_x"]);
bool prior_flip_y = false;
if (parsedArgs.count("prior_flip_y"))
prior_flip_y = us::any_cast<bool>(parsedArgs["prior_flip_y"]);
bool prior_flip_z = false;
if (parsedArgs.count("prior_flip_z"))
prior_flip_z = us::any_cast<bool>(parsedArgs["prior_flip_z"]);
params->m_ApplyDirectionMatrix = false;
if (parsedArgs.count("apply_image_rotation"))
params->m_ApplyDirectionMatrix = us::any_cast<bool>(parsedArgs["apply_image_rotation"]);
float compress = -1;
if (parsedArgs.count("compress"))
compress = us::any_cast<float>(parsedArgs["compress"]);
params->m_MinTractLengthMm = 20;
if (parsedArgs.count("min_tract_length"))
params->m_MinTractLengthMm = us::any_cast<float>(parsedArgs["min_tract_length"]);
params->SetLoopCheckDeg(-1);
if (parsedArgs.count("loop_check"))
params->SetLoopCheckDeg(us::any_cast<float>(parsedArgs["loop_check"]));
std::string forestFile;
if (parsedArgs.count("forest"))
forestFile = us::any_cast<std::string>(parsedArgs["forest"]);
std::string maskFile = "";
if (parsedArgs.count("tracking_mask"))
maskFile = us::any_cast<std::string>(parsedArgs["tracking_mask"]);
std::string seedFile = "";
if (parsedArgs.count("seed_image"))
seedFile = us::any_cast<std::string>(parsedArgs["seed_image"]);
std::string targetFile = "";
if (parsedArgs.count("target_image"))
targetFile = us::any_cast<std::string>(parsedArgs["target_image"]);
std::string exclusionFile = "";
if (parsedArgs.count("exclusion_image"))
exclusionFile = us::any_cast<std::string>(parsedArgs["exclusion_image"]);
std::string stopFile = "";
if (parsedArgs.count("stop_image"))
stopFile = us::any_cast<std::string>(parsedArgs["stop_image"]);
std::string ep_constraint = "NONE";
if (parsedArgs.count("ep_constraint"))
ep_constraint = us::any_cast<std::string>(parsedArgs["ep_constraint"]);
params->m_Cutoff = 0.1f;
if (parsedArgs.count("cutoff"))
params->m_Cutoff = us::any_cast<float>(parsedArgs["cutoff"]);
params->m_OdfCutoff = 0.0;
if (parsedArgs.count("odf_cutoff"))
params->m_OdfCutoff = us::any_cast<float>(parsedArgs["odf_cutoff"]);
params->m_PeakJitter = 0.01;
if (parsedArgs.count("peak_jitter"))
params->m_PeakJitter = us::any_cast<float>(parsedArgs["peak_jitter"]);
params->SetStepSizeVox(-1);
if (parsedArgs.count("step_size"))
params->SetStepSizeVox(us::any_cast<float>(parsedArgs["step_size"]));
params->SetSamplingDistanceVox(-1);
if (parsedArgs.count("sampling_distance"))
params->SetSamplingDistanceVox(us::any_cast<float>(parsedArgs["sampling_distance"]));
params->m_NumSamples = 0;
if (parsedArgs.count("num_samples"))
params->m_NumSamples = static_cast<unsigned int>(us::any_cast<int>(parsedArgs["num_samples"]));
params->m_SeedsPerVoxel = 1;
if (parsedArgs.count("seeds"))
params->m_SeedsPerVoxel = us::any_cast<int>(parsedArgs["seeds"]);
params->m_TrialsPerSeed = 10;
if (parsedArgs.count("trials_per_seed"))
params->m_TrialsPerSeed = static_cast<unsigned int>(us::any_cast<int>(parsedArgs["trials_per_seed"]));
params->m_F = 1;
if (parsedArgs.count("tend_f"))
params->m_F = us::any_cast<float>(parsedArgs["tend_f"]);
params->m_G = 0;
if (parsedArgs.count("tend_g"))
params->m_G = us::any_cast<float>(parsedArgs["tend_g"]);
params->SetAngularThresholdDeg(-1);
if (parsedArgs.count("angular_threshold"))
params->SetAngularThresholdDeg(us::any_cast<float>(parsedArgs["angular_threshold"]));
params->m_MaxNumFibers = -1;
if (parsedArgs.count("max_tracts"))
params->m_MaxNumFibers = us::any_cast<int>(parsedArgs["max_tracts"]);
std::string ext = itksys::SystemTools::GetFilenameExtension(outFile);
if (ext != ".fib" && ext != ".trk")
{
MITK_INFO << "Output file format not supported. Use one of .fib, .trk, .nii, .nii.gz, .nrrd";
return EXIT_FAILURE;
}
// LOAD DATASETS
mitkDiffusionCommandLineParser::StringContainerType addFiles;
if (parsedArgs.count("additional_images"))
addFiles = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["additional_images"]);
typedef itk::Image<float, 3> ItkFloatImgType;
ItkFloatImgType::Pointer mask = nullptr;
if (!maskFile.empty())
{
MITK_INFO << "loading mask image";
mitk::Image::Pointer img = mitk::IOUtil::Load<mitk::Image>(maskFile);
mask = ItkFloatImgType::New();
mitk::CastToItkImage(img, mask);
}
ItkFloatImgType::Pointer seed = nullptr;
if (!seedFile.empty())
{
MITK_INFO << "loading seed ROI image";
mitk::Image::Pointer img = mitk::IOUtil::Load<mitk::Image>(seedFile);
seed = ItkFloatImgType::New();
mitk::CastToItkImage(img, seed);
}
ItkFloatImgType::Pointer stop = nullptr;
if (!stopFile.empty())
{
MITK_INFO << "loading stop ROI image";
mitk::Image::Pointer img = mitk::IOUtil::Load<mitk::Image>(stopFile);
stop = ItkFloatImgType::New();
mitk::CastToItkImage(img, stop);
}
ItkFloatImgType::Pointer target = nullptr;
if (!targetFile.empty())
{
MITK_INFO << "loading target ROI image";
mitk::Image::Pointer img = mitk::IOUtil::Load<mitk::Image>(targetFile);
target = ItkFloatImgType::New();
mitk::CastToItkImage(img, target);
}
ItkFloatImgType::Pointer exclusion = nullptr;
if (!exclusionFile.empty())
{
MITK_INFO << "loading exclusion ROI image";
mitk::Image::Pointer img = mitk::IOUtil::Load<mitk::Image>(exclusionFile);
exclusion = ItkFloatImgType::New();
mitk::CastToItkImage(img, exclusion);
}
MITK_INFO << "loading additional images";
std::vector< std::vector< ItkFloatImgType::Pointer > > addImages;
addImages.push_back(std::vector< ItkFloatImgType::Pointer >());
for (auto file : addFiles)
{
mitk::Image::Pointer img = mitk::IOUtil::Load<mitk::Image>(file);
ItkFloatImgType::Pointer itkimg = ItkFloatImgType::New();
mitk::CastToItkImage(img, itkimg);
addImages.at(0).push_back(itkimg);
}
// //////////////////////////////////////////////////////////////////
// omp_set_num_threads(1);
typedef itk::StreamlineTrackingFilter TrackerType;
TrackerType::Pointer tracker = TrackerType::New();
if (!prior_image.empty())
{
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Peak Image"}, {});
mitk::PeakImage::Pointer priorImage = mitk::IOUtil::Load<mitk::PeakImage>(prior_image, &functor);
if (priorImage.IsNull())
{
MITK_INFO << "Only peak images are supported as prior at the moment!";
return EXIT_FAILURE;
}
mitk::TrackingDataHandler* priorhandler = new mitk::TrackingHandlerPeaks();
typedef mitk::ImageToItk< mitk::TrackingHandlerPeaks::PeakImgType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(priorImage);
caster->Update();
mitk::TrackingHandlerPeaks::PeakImgType::Pointer itkImg = caster->GetOutput();
std::shared_ptr< mitk::StreamlineTractographyParameters > prior_params = std::make_shared< mitk::StreamlineTractographyParameters >(*params);
prior_params->m_FlipX = prior_flip_x;
prior_params->m_FlipY = prior_flip_y;
prior_params->m_FlipZ = prior_flip_z;
prior_params->m_Cutoff = 0.0;
dynamic_cast<mitk::TrackingHandlerPeaks*>(priorhandler)->SetPeakImage(itkImg);
priorhandler->SetParameters(prior_params);
tracker->SetTrackingPriorHandler(priorhandler);
}
mitk::TrackingDataHandler* handler;
mitk::Image::Pointer reference_image;
if (type == "RF")
{
mitk::TractographyForest::Pointer forest = mitk::IOUtil::Load<mitk::TractographyForest>(forestFile);
if (forest.IsNull())
mitkThrow() << "Forest file " << forestFile << " could not be read.";
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images"}, {});
auto input = mitk::IOUtil::Load<mitk::Image>(input_files.at(0), &functor);
reference_image = input;
if (use_sh_features)
{
handler = new mitk::TrackingHandlerRandomForest<6,28>();
dynamic_cast<mitk::TrackingHandlerRandomForest<6,28>*>(handler)->SetForest(forest);
dynamic_cast<mitk::TrackingHandlerRandomForest<6,28>*>(handler)->AddDwi(input);
dynamic_cast<mitk::TrackingHandlerRandomForest<6,28>*>(handler)->SetAdditionalFeatureImages(addImages);
}
else
{
handler = new mitk::TrackingHandlerRandomForest<6,100>();
dynamic_cast<mitk::TrackingHandlerRandomForest<6,100>*>(handler)->SetForest(forest);
dynamic_cast<mitk::TrackingHandlerRandomForest<6,100>*>(handler)->AddDwi(input);
dynamic_cast<mitk::TrackingHandlerRandomForest<6,100>*>(handler)->SetAdditionalFeatureImages(addImages);
}
}
else if (type == "Peaks")
{
handler = new mitk::TrackingHandlerPeaks();
MITK_INFO << "loading input peak image";
mitk::Image::Pointer mitkImage = mitk::IOUtil::Load<mitk::Image>(input_files.at(0));
reference_image = mitkImage;
mitk::TrackingHandlerPeaks::PeakImgType::Pointer itkImg = mitk::convert::GetItkPeakFromPeakImage(mitkImage);
dynamic_cast<mitk::TrackingHandlerPeaks*>(handler)->SetPeakImage(itkImg);
}
else if (type == "Tensor" && params->m_Mode == mitk::StreamlineTractographyParameters::MODE::DETERMINISTIC)
{
handler = new mitk::TrackingHandlerTensor();
MITK_INFO << "loading input tensor images";
std::vector< mitk::Image::Pointer > input_images;
for (unsigned int i=0; i<input_files.size(); i++)
{
mitk::Image::Pointer mitkImage = mitk::IOUtil::Load<mitk::Image>(input_files.at(i));
reference_image = mitkImage;
mitk::TensorImage::ItkTensorImageType::Pointer itkImg = mitk::convert::GetItkTensorFromTensorImage(mitkImage);
dynamic_cast<mitk::TrackingHandlerTensor*>(handler)->AddTensorImage(itkImg.GetPointer());
}
if (addImages.at(0).size()>0)
dynamic_cast<mitk::TrackingHandlerTensor*>(handler)->SetFaImage(addImages.at(0).at(0));
}
else if (type == "ODF" || type == "ODF-DIPY/FSL" || (type == "Tensor" && params->m_Mode == mitk::StreamlineTractographyParameters::MODE::PROBABILISTIC))
{
handler = new mitk::TrackingHandlerOdf();
mitk::OdfImage::ItkOdfImageType::Pointer itkImg = nullptr;
if (type == "Tensor")
{
MITK_INFO << "Converting Tensor to ODF image";
auto input = mitk::IOUtil::Load<mitk::Image>(input_files.at(0));
reference_image = input;
itkImg = mitk::convert::GetItkOdfFromTensorImage(input);
dynamic_cast<mitk::TrackingHandlerOdf*>(handler)->SetIsOdfFromTensor(true);
}
else
{
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"SH Image", "ODF Image"}, {});
auto input = mitk::IOUtil::Load(input_files.at(0), &functor)[0];
reference_image = dynamic_cast<mitk::Image*>(input.GetPointer());
if (dynamic_cast<mitk::ShImage*>(input.GetPointer()))
{
MITK_INFO << "Converting SH to ODF image";
mitk::ShImage::Pointer mitkShImage = dynamic_cast<mitk::ShImage*>(input.GetPointer());
if (type == "ODF-DIPY/FSL")
mitkShImage->SetShConvention(mitk::ShImage::SH_CONVENTION::FSL);
mitk::Image::Pointer mitkImg = dynamic_cast<mitk::Image*>(mitkShImage.GetPointer());
itkImg = mitk::convert::GetItkOdfFromShImage(mitkImg);
}
else if (dynamic_cast<mitk::OdfImage*>(input.GetPointer()))
{
mitk::Image::Pointer mitkImg = dynamic_cast<mitk::Image*>(input.GetPointer());
itkImg = mitk::convert::GetItkOdfFromOdfImage(mitkImg);
}
else
mitkThrow() << "";
}
dynamic_cast<mitk::TrackingHandlerOdf*>(handler)->SetOdfImage(itkImg);
if (addImages.at(0).size()>0)
dynamic_cast<mitk::TrackingHandlerOdf*>(handler)->SetGfaImage(addImages.at(0).at(0));
}
else
{
MITK_INFO << "Unknown tractography algorithm (" + type+"). Known types are Peaks, DetTensor, ProbTensor, DetODF, ProbODF, DetRF, ProbRF.";
return EXIT_FAILURE;
}
if (ep_constraint=="NONE")
params->m_EpConstraints = itk::StreamlineTrackingFilter::EndpointConstraints::NONE;
else if (ep_constraint=="EPS_IN_TARGET")
params->m_EpConstraints = itk::StreamlineTrackingFilter::EndpointConstraints::EPS_IN_TARGET;
else if (ep_constraint=="EPS_IN_TARGET_LABELDIFF")
params->m_EpConstraints = itk::StreamlineTrackingFilter::EndpointConstraints::EPS_IN_TARGET_LABELDIFF;
else if (ep_constraint=="EPS_IN_SEED_AND_TARGET")
params->m_EpConstraints = itk::StreamlineTrackingFilter::EndpointConstraints::EPS_IN_SEED_AND_TARGET;
else if (ep_constraint=="MIN_ONE_EP_IN_TARGET")
params->m_EpConstraints = itk::StreamlineTrackingFilter::EndpointConstraints::MIN_ONE_EP_IN_TARGET;
else if (ep_constraint=="ONE_EP_IN_TARGET")
params->m_EpConstraints = itk::StreamlineTrackingFilter::EndpointConstraints::ONE_EP_IN_TARGET;
else if (ep_constraint=="NO_EP_IN_TARGET")
params->m_EpConstraints = itk::StreamlineTrackingFilter::EndpointConstraints::NO_EP_IN_TARGET;
MITK_INFO << "Tractography algorithm: " << type;
tracker->SetMaskImage(mask);
tracker->SetSeedImage(seed);
tracker->SetStoppingRegions(stop);
tracker->SetTargetRegions(target);
tracker->SetExclusionRegions(exclusion);
tracker->SetTrackingHandler(handler);
if (ext != ".fib" && ext != ".trk")
params->m_OutputProbMap = true;
tracker->SetParameters(params);
tracker->Update();
if (ext == ".fib" || ext == ".trk")
{
vtkSmartPointer< vtkPolyData > poly = tracker->GetFiberPolyData();
mitk::FiberBundle::Pointer outFib = mitk::FiberBundle::New(poly);
if (compress > 0)
outFib->Compress(compress);
outFib->SetTrackVisHeader(reference_image->GetGeometry());
mitk::IOUtil::Save(outFib, outFile);
}
else
{
TrackerType::ItkDoubleImgType::Pointer outImg = tracker->GetOutputProbabilityMap();
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk(outImg.GetPointer());
img->SetVolume(outImg->GetBufferPointer());
if (ext != ".nii" && ext != ".nii.gz" && ext != ".nrrd")
outFile += ".nii.gz";
mitk::IOUtil::Save(img, outFile);
}
delete handler;
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/TractographyEvaluation/AnchorConstrainedPlausibility.cpp b/Modules/DiffusionCmdApps/TractographyEvaluation/AnchorConstrainedPlausibility.cpp
index 4da10a4..d64e8e9 100644
--- a/Modules/DiffusionCmdApps/TractographyEvaluation/AnchorConstrainedPlausibility.cpp
+++ b/Modules/DiffusionCmdApps/TractographyEvaluation/AnchorConstrainedPlausibility.cpp
@@ -1,447 +1,447 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkBaseData.h>
#include <mitkImageCast.h>
#include <mitkImageToItk.h>
#include <metaCommand.h>
#include <mitkDiffusionCommandLineParser.h>
#include <usAny.h>
#include <mitkIOUtil.h>
#include <itksys/SystemTools.hxx>
#include <itkDirectory.h>
#include <mitkFiberBundle.h>
#include <mitkPreferenceListReaderOptionsFunctor.h>
#include <itkImageFileWriter.h>
#include <mitkPeakImage.h>
#include <itkFitFibersToImageFilter.h>
#include <mitkLexicalCast.h>
#include <itkTractDensityImageFilter.h>
#include <itkFlipPeaksFilter.h>
#include <mitkDiffusionDataIOHelper.h>
typedef itk::Point<float, 4> PointType4;
typedef mitk::PeakImage::ItkPeakImageType PeakImgType;
typedef itk::Image< unsigned char, 3 > ItkUcharImageType;
/*!
\brief Score input candidate tracts using ACP analysis
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Anchor Constrained Plausibility");
parser.setCategory("Fiber Tracking Evaluation");
parser.setDescription("Score input candidate tracts using ACP analysis");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "a", mitkDiffusionCommandLineParser::String, "Anchor tractogram:", "anchor tracts in one tractogram file", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "p", mitkDiffusionCommandLineParser::String, "Input peaks:", "input peak image", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "c", mitkDiffusionCommandLineParser::StringList, "Candidates:", "Folder(s) or file list of candidate tracts", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output folder:", "output folder", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("reference_mask_folders", "", mitkDiffusionCommandLineParser::StringList, "Reference Mask Folder(s):", "Folder(s) or file list containing reference tract masks for accuracy evaluation", true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("reference_peaks_folders", "", mitkDiffusionCommandLineParser::StringList, "Reference Peaks Folder(s):", "Folder(s) or file list containing reference peak images for accuracy evaluation", true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("mask", "", mitkDiffusionCommandLineParser::String, "Mask image:", "scoring is only performed inside the mask image", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("greedy_add", "", mitkDiffusionCommandLineParser::Bool, "Greedy:", "if enabled, the candidate tracts are not jointly fitted to the residual image but one after the other employing a greedy scheme", false);
parser.addArgument("lambda", "", mitkDiffusionCommandLineParser::Float, "Lambda:", "modifier for regularization", 0.1);
parser.addArgument("filter_outliers", "", mitkDiffusionCommandLineParser::Bool, "Filter outliers:", "perform second optimization run with an upper weight bound based on the first weight estimation (99% quantile)", false);
parser.addArgument("regu", "", mitkDiffusionCommandLineParser::String, "Regularization:", "MSM; Variance; VoxelVariance; Lasso; GroupLasso; GroupVariance; NONE", std::string("NONE"));
parser.addArgument("use_num_streamlines", "", mitkDiffusionCommandLineParser::Bool, "Use number of streamlines as score:", "Don't fit candidates, simply use number of streamlines per candidate as score", false);
parser.addArgument("use_weights", "", mitkDiffusionCommandLineParser::Bool, "Use input weights as score:", "Don't fit candidates, simply use first input streamline weight per candidate as score", false);
parser.addArgument("filter_zero_weights", "", mitkDiffusionCommandLineParser::Bool, "Filter zero-weights", "Remove streamlines with weight 0 from candidates", false);
parser.addArgument("flipx", "", mitkDiffusionCommandLineParser::Bool, "Flip x", "flip along x-axis", false);
parser.addArgument("flipy", "", mitkDiffusionCommandLineParser::Bool, "Flip y", "flip along y-axis", false);
parser.addArgument("flipz", "", mitkDiffusionCommandLineParser::Bool, "Flip z", "flip along z-axis", false);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
std::string peak_file_name = us::any_cast<std::string>(parsedArgs["p"]);
std::string out_folder = us::any_cast<std::string>(parsedArgs["o"]);
mitkDiffusionCommandLineParser::StringContainerType candidate_tract_folders = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["c"]);
if (!out_folder.empty() && out_folder.back() != '/')
out_folder += "/";
bool greedy_add = false;
if (parsedArgs.count("greedy_add"))
greedy_add = us::any_cast<bool>(parsedArgs["greedy_add"]);
float lambda = 0.1f;
if (parsedArgs.count("lambda"))
lambda = us::any_cast<float>(parsedArgs["lambda"]);
bool filter_outliers = false;
if (parsedArgs.count("filter_outliers"))
filter_outliers = us::any_cast<bool>(parsedArgs["filter_outliers"]);
bool filter_zero_weights = false;
if (parsedArgs.count("filter_zero_weights"))
filter_zero_weights = us::any_cast<bool>(parsedArgs["filter_zero_weights"]);
std::string mask_file = "";
if (parsedArgs.count("mask"))
mask_file = us::any_cast<std::string>(parsedArgs["mask"]);
mitkDiffusionCommandLineParser::StringContainerType reference_mask_files_folders;
if (parsedArgs.count("reference_mask_folders"))
reference_mask_files_folders = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["reference_mask_folders"]);
mitkDiffusionCommandLineParser::StringContainerType reference_peaks_files_folders;
if (parsedArgs.count("reference_peaks_folders"))
reference_peaks_files_folders = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["reference_peaks_folders"]);
std::string regu = "NONE";
if (parsedArgs.count("regu"))
regu = us::any_cast<std::string>(parsedArgs["regu"]);
bool use_weights = false;
if (parsedArgs.count("use_weights"))
use_weights = us::any_cast<bool>(parsedArgs["use_weights"]);
bool use_num_streamlines = false;
if (parsedArgs.count("use_num_streamlines"))
use_num_streamlines = us::any_cast<bool>(parsedArgs["use_num_streamlines"]);
bool flipx = false;
if (parsedArgs.count("flipx"))
flipx = us::any_cast<bool>(parsedArgs["flipx"]);
bool flipy = false;
if (parsedArgs.count("flipy"))
flipy = us::any_cast<bool>(parsedArgs["flipy"]);
bool flipz = false;
if (parsedArgs.count("flipz"))
flipz = us::any_cast<bool>(parsedArgs["flipz"]);
try
{
itk::TimeProbe clock;
clock.Start();
if (!ist::PathExists(out_folder))
{
MITK_INFO << "Creating output directory";
ist::MakeDirectory(out_folder);
}
MITK_INFO << "Loading data";
// Load mask file. Fit is only performed inside the mask
MITK_INFO << "Loading mask image";
auto mask = mitk::DiffusionDataIOHelper::load_itk_image<itk::FitFibersToImageFilter::UcharImgType>(mask_file);
// Load masks covering the true positives for evaluation purposes
MITK_INFO << "Loading reference peaks and masks";
std::vector< std::string > anchor_mask_files;
auto reference_masks = mitk::DiffusionDataIOHelper::load_itk_images<itk::FitFibersToImageFilter::UcharImgType>(reference_mask_files_folders, &anchor_mask_files);
auto reference_peaks = mitk::DiffusionDataIOHelper::load_itk_images<PeakImgType>(reference_peaks_files_folders);
// Load peak image
MITK_INFO << "Loading peak image";
auto peak_image = mitk::DiffusionDataIOHelper::load_itk_image<PeakImgType>(peak_file_name);
// Load all candidate tracts
MITK_INFO << "Loading candidate tracts";
std::vector< std::string > candidate_tract_files;
auto input_candidates = mitk::DiffusionDataIOHelper::load_fibs(candidate_tract_folders, &candidate_tract_files);
if (flipx || flipy || flipz)
{
itk::FlipPeaksFilter< float >::Pointer flipper = itk::FlipPeaksFilter< float >::New();
flipper->SetInput(peak_image);
flipper->SetFlipX(flipx);
flipper->SetFlipY(flipy);
flipper->SetFlipZ(flipz);
flipper->Update();
peak_image = flipper->GetOutput();
}
mitk::LocaleSwitch localeSwitch("C");
itk::ImageFileWriter< PeakImgType >::Pointer peak_image_writer = itk::ImageFileWriter< PeakImgType >::New();
ofstream logfile;
logfile.open (out_folder + "scores.txt");
double rmse = 0.0;
int iteration = 0;
std::string name = "NOANCHOR";
if (parsedArgs.count("a"))
{
// Load reference tractogram consisting of all known tracts
std::string anchors_file = us::any_cast<std::string>(parsedArgs["a"]);
mitk::FiberBundle::Pointer anchor_tractogram = mitk::IOUtil::Load<mitk::FiberBundle>(anchors_file);
if ( !(anchor_tractogram.IsNull() || anchor_tractogram->GetNumFibers()==0) )
{
// Fit known tracts to peak image to obtain underexplained image
MITK_INFO << "Fit anchor tracts";
itk::FitFibersToImageFilter::Pointer fitter = itk::FitFibersToImageFilter::New();
fitter->SetTractograms({anchor_tractogram});
fitter->SetLambda(static_cast<double>(lambda));
fitter->SetFilterOutliers(filter_outliers);
fitter->SetPeakImage(peak_image);
fitter->SetVerbose(true);
fitter->SetMaskImage(mask);
fitter->SetRegularization(VnlCostFunction::REGU::NONE);
fitter->Update();
rmse = fitter->GetRMSE();
vnl_vector<double> rms_diff = fitter->GetRmsDiffPerBundle();
name = ist::GetFilenameWithoutExtension(anchors_file);
mitk::FiberBundle::Pointer anchor_tracts = fitter->GetTractograms().at(0);
anchor_tracts->SetFiberColors(255,255,255);
mitk::IOUtil::Save(anchor_tracts, out_folder + boost::lexical_cast<std::string>(static_cast<int>(100000*rms_diff[0])) + "_" + name + ".fib");
logfile << name << " " << setprecision(5) << rms_diff[0] << "\n";
peak_image = fitter->GetUnderexplainedImage();
peak_image_writer->SetInput(peak_image);
peak_image_writer->SetFileName(out_folder + "Residual_" + name + ".nii.gz");
peak_image_writer->Update();
}
}
if (use_weights || use_num_streamlines)
{
MITK_INFO << "Using tract weights as scores";
unsigned int c = 0;
for (auto fib : input_candidates)
{
int mod = 1;
float score = 0;
if (use_weights)
{
score = fib->GetFiberWeight(0);
mod = 100000;
}
else if (use_num_streamlines)
score = fib->GetNumFibers();
fib->ColorFibersByOrientation();
std::string bundle_name = ist::GetFilenameWithoutExtension(candidate_tract_files.at(c));
std::streambuf *old = cout.rdbuf(); // <-- save
std::stringstream ss;
std::cout.rdbuf (ss.rdbuf()); // <-- redirect
mitk::IOUtil::Save(fib, out_folder + boost::lexical_cast<std::string>(static_cast<int>(mod*score)) + "_" + bundle_name + ".fib");
unsigned int num_voxels = 0;
{
itk::TractDensityImageFilter< ItkUcharImageType >::Pointer masks_filter = itk::TractDensityImageFilter< ItkUcharImageType >::New();
masks_filter->SetInputImage(mask);
masks_filter->SetBinaryOutput(true);
masks_filter->SetFiberBundle(fib);
masks_filter->SetUseImageGeometry(true);
masks_filter->Update();
num_voxels = masks_filter->GetNumCoveredVoxels();
}
float weight_sum = 0;
for (unsigned int i=0; i<fib->GetNumFibers(); i++)
weight_sum += fib->GetFiberWeight(i);
std::cout.rdbuf (old); // <-- restore
logfile << bundle_name << " " << setprecision(5) << score << " " << num_voxels << " " << fib->GetNumFibers() << " " << weight_sum << "\n";
++c;
}
}
else if (!greedy_add)
{
MITK_INFO << "Fit candidate tracts";
itk::FitFibersToImageFilter::Pointer fitter = itk::FitFibersToImageFilter::New();
fitter->SetLambda(static_cast<double>(lambda));
fitter->SetFilterOutliers(filter_outliers);
fitter->SetVerbose(true);
fitter->SetPeakImage(peak_image);
fitter->SetMaskImage(mask);
fitter->SetTractograms(input_candidates);
fitter->SetFitIndividualFibers(true);
if (regu=="MSM")
fitter->SetRegularization(VnlCostFunction::REGU::MSM);
else if (regu=="Variance")
fitter->SetRegularization(VnlCostFunction::REGU::VARIANCE);
else if (regu=="Lasso")
fitter->SetRegularization(VnlCostFunction::REGU::LASSO);
else if (regu=="VoxelVariance")
fitter->SetRegularization(VnlCostFunction::REGU::VOXEL_VARIANCE);
else if (regu=="GroupLasso")
fitter->SetRegularization(VnlCostFunction::REGU::GROUP_LASSO);
else if (regu=="GroupVariance")
fitter->SetRegularization(VnlCostFunction::REGU::GROUP_VARIANCE);
else if (regu=="NONE")
fitter->SetRegularization(VnlCostFunction::REGU::NONE);
fitter->Update();
vnl_vector<double> rms_diff = fitter->GetRmsDiffPerBundle();
unsigned int c = 0;
for (auto fib : input_candidates)
{
std::string bundle_name = ist::GetFilenameWithoutExtension(candidate_tract_files.at(c));
std::streambuf *old = cout.rdbuf(); // <-- save
std::stringstream ss;
std::cout.rdbuf (ss.rdbuf()); // <-- redirect
if (filter_zero_weights)
fib = fib->FilterByWeights(0);
mitk::IOUtil::Save(fib, out_folder + boost::lexical_cast<std::string>((int)(100000*rms_diff[c])) + "_" + bundle_name + ".fib");
unsigned int num_voxels = 0;
{
itk::TractDensityImageFilter< ItkUcharImageType >::Pointer masks_filter = itk::TractDensityImageFilter< ItkUcharImageType >::New();
masks_filter->SetInputImage(mask);
masks_filter->SetBinaryOutput(true);
masks_filter->SetFiberBundle(fib);
masks_filter->SetUseImageGeometry(true);
masks_filter->Update();
num_voxels = masks_filter->GetNumCoveredVoxels();
}
float weight_sum = 0;
for (unsigned int i=0; i<fib->GetNumFibers(); i++)
weight_sum += fib->GetFiberWeight(i);
std::cout.rdbuf (old); // <-- restore
logfile << bundle_name << " " << setprecision(5) << rms_diff[c] << " " << num_voxels << " " << fib->GetNumFibers() << " " << weight_sum << "\n";
++c;
}
mitk::FiberBundle::Pointer out_fib = mitk::FiberBundle::New();
out_fib = out_fib->AddBundles(input_candidates);
out_fib->ColorFibersByFiberWeights(false, true);
mitk::IOUtil::Save(out_fib, out_folder + "AllCandidates.fib");
peak_image = fitter->GetUnderexplainedImage();
peak_image_writer->SetInput(peak_image);
peak_image_writer->SetFileName(out_folder + "Residual_AllCandidates.nii.gz");
peak_image_writer->Update();
}
else
{
MITK_INFO << "RMSE: " << setprecision(5) << rmse;
// fitter->SetPeakImage(peak_image);
// Iteratively add candidate bundles in a greedy manner
while (!input_candidates.empty())
{
double next_rmse = rmse;
mitk::FiberBundle::Pointer best_candidate = nullptr;
PeakImgType::Pointer best_candidate_peak_image = nullptr;
for (unsigned int i=0; i<input_candidates.size(); ++i)
{
// WHY NECESSARY AGAIN??
itk::FitFibersToImageFilter::Pointer fitter = itk::FitFibersToImageFilter::New();
fitter->SetLambda(static_cast<double>(lambda));
fitter->SetFilterOutliers(filter_outliers);
fitter->SetVerbose(false);
fitter->SetPeakImage(peak_image);
fitter->SetMaskImage(mask);
// ******************************
fitter->SetTractograms({input_candidates.at(i)});
std::streambuf *old = cout.rdbuf(); // <-- save
std::stringstream ss;
std::cout.rdbuf (ss.rdbuf()); // <-- redirect
fitter->Update();
std::cout.rdbuf (old); // <-- restore
double candidate_rmse = fitter->GetRMSE();
if (candidate_rmse<next_rmse)
{
next_rmse = candidate_rmse;
best_candidate = fitter->GetTractograms().at(0);
best_candidate_peak_image = fitter->GetUnderexplainedImage();
}
}
if (best_candidate.IsNull())
break;
// fitter->SetPeakImage(peak_image);
peak_image = best_candidate_peak_image;
unsigned int i=0;
std::vector< mitk::FiberBundle::Pointer > remaining_candidates;
std::vector< std::string > remaining_candidate_files;
for (auto fib : input_candidates)
{
if (fib!=best_candidate)
{
remaining_candidates.push_back(fib);
remaining_candidate_files.push_back(candidate_tract_files.at(i));
}
else
name = ist::GetFilenameWithoutExtension(candidate_tract_files.at(i));
++i;
}
input_candidates = remaining_candidates;
candidate_tract_files = remaining_candidate_files;
iteration++;
std::streambuf *old = cout.rdbuf(); // <-- save
std::stringstream ss;
std::cout.rdbuf (ss.rdbuf()); // <-- redirect
// Save winning candidate
if (filter_zero_weights)
best_candidate = best_candidate->FilterByWeights(0);
mitk::IOUtil::Save(best_candidate, out_folder + boost::lexical_cast<std::string>(iteration) + "_" + name + ".fib");
peak_image_writer->SetInput(peak_image);
peak_image_writer->SetFileName(out_folder + boost::lexical_cast<std::string>(iteration) + "_" + name + ".nrrd");
peak_image_writer->Update();
std::cout.rdbuf (old); // <-- restore
// logfile << name << " " << setprecision(5) << score << " " << num_voxels << " " << fib->GetNumFibers() << " " << weight_sum << "\n";
}
}
clock.Stop();
int h = static_cast<int>(clock.GetTotal()/3600);
int m = (static_cast<int>(clock.GetTotal())%3600)/60;
int s = static_cast<int>(clock.GetTotal())%60;
MITK_INFO << "Plausibility estimation took " << h << "h, " << m << "m and " << s << "s";
logfile.close();
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/TractographyEvaluation/CalculateOverlap.cpp b/Modules/DiffusionCmdApps/TractographyEvaluation/CalculateOverlap.cpp
index 7310e89..e4c3c0c 100644
--- a/Modules/DiffusionCmdApps/TractographyEvaluation/CalculateOverlap.cpp
+++ b/Modules/DiffusionCmdApps/TractographyEvaluation/CalculateOverlap.cpp
@@ -1,108 +1,108 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkBaseData.h>
#include <mitkImageCast.h>
#include <mitkImageToItk.h>
#include <metaCommand.h>
#include <mitkDiffusionCommandLineParser.h>
#include <usAny.h>
#include <mitkIOUtil.h>
#include <mitkLexicalCast.h>
#include <itksys/SystemTools.hxx>
#include <itkDirectory.h>
#include <mitkFiberBundle.h>
#include <vtkTransformPolyDataFilter.h>
#include <fstream>
#include <chrono>
#include <boost/progress.hpp>
#include <itkTractsToFiberEndingsImageFilter.h>
#include <itkTractDensityImageFilter.h>
#include <itkImageRegionConstIterator.h>
typedef itksys::SystemTools ist;
typedef itk::Image<unsigned char, 3> ItkFloatImgType;
typedef itk::Image<unsigned int, 3> ItkUIntImgType;
/*!
\brief
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Calculate Overlap");
parser.setCategory("Fiber Tracking Evaluation");
parser.setDescription("");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("tractogram", "", mitkDiffusionCommandLineParser::String, "", "", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("mask", "", mitkDiffusionCommandLineParser::String, "", "", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("peaks", "", mitkDiffusionCommandLineParser::String, "", "", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
std::string input_tractogram = us::any_cast<std::string>(parsedArgs["tractogram"]);
std::string mask_file = us::any_cast<std::string>(parsedArgs["mask"]);
try
{
mitk::FiberBundle::Pointer fib = mitk::IOUtil::Load<mitk::FiberBundle>(input_tractogram);
mitk::Image::Pointer mask = mitk::IOUtil::Load<mitk::Image>(mask_file);
ItkFloatImgType::Pointer itk_mask;
mitk::CastToItkImage(mask, itk_mask);
mitk::PeakImage::ItkPeakImageType::Pointer peaks = nullptr;
if (parsedArgs.count("peaks"))
{
mitk::Image::Pointer mitk_peaks = mitk::IOUtil::Load<mitk::Image>(us::any_cast<std::string>(parsedArgs["peaks"]));
typedef mitk::ImageToItk< mitk::PeakImage::ItkPeakImageType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(mitk_peaks);
caster->Update();
peaks = caster->GetOutput();
float overlap = 0;
float directional_overlap = 0;
std::tie(directional_overlap, overlap) = fib->GetDirectionalOverlap(itk_mask, peaks);
MITK_INFO << "Overlap<<" << overlap;
MITK_INFO << "DirectionalOverlap<<" << directional_overlap;
}
else
MITK_INFO << "Overlap<<" << fib->GetOverlap(itk_mask);
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/TractographyEvaluation/CheckEpsAndOverlap.cpp b/Modules/DiffusionCmdApps/TractographyEvaluation/CheckEpsAndOverlap.cpp
index 4a8a896..8d9304a 100644
--- a/Modules/DiffusionCmdApps/TractographyEvaluation/CheckEpsAndOverlap.cpp
+++ b/Modules/DiffusionCmdApps/TractographyEvaluation/CheckEpsAndOverlap.cpp
@@ -1,98 +1,98 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkBaseData.h>
#include <mitkImageCast.h>
#include <mitkImageToItk.h>
#include <metaCommand.h>
#include <mitkDiffusionCommandLineParser.h>
#include <usAny.h>
#include <mitkIOUtil.h>
#include <mitkLexicalCast.h>
#include <itksys/SystemTools.hxx>
#include <itkDirectory.h>
#include <mitkFiberBundle.h>
#include <vtkTransformPolyDataFilter.h>
#include <fstream>
#include <chrono>
#include <boost/progress.hpp>
#include <itkTractsToFiberEndingsImageFilter.h>
#include <itkTractDensityImageFilter.h>
#include <itkImageRegionConstIterator.h>
typedef itksys::SystemTools ist;
typedef itk::Image<unsigned char, 3> ItkUcharImgType;
typedef itk::Image<unsigned int, 3> ItkUIntImgType;
/*!
\brief
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Calculate Overlap");
parser.setCategory("Fiber Tracking Evaluation");
parser.setDescription("");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("tractogram", "", mitkDiffusionCommandLineParser::String, "", "file", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("overlap_image", "", mitkDiffusionCommandLineParser::String, "", "file", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("ep_image", "", mitkDiffusionCommandLineParser::String, "", "file", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
std::string input_tractogram = us::any_cast<std::string>(parsedArgs["tractogram"]);
std::string mask_file = us::any_cast<std::string>(parsedArgs["overlap_image"]);
std::string mask_file2 = us::any_cast<std::string>(parsedArgs["ep_image"]);
try
{
mitk::FiberBundle::Pointer fib = mitk::IOUtil::Load<mitk::FiberBundle>(input_tractogram);
mitk::Image::Pointer mask = mitk::IOUtil::Load<mitk::Image>(mask_file);
mitk::Image::Pointer mask2 = mitk::IOUtil::Load<mitk::Image>(mask_file2);
ItkUcharImgType::Pointer itk_mask;
mitk::CastToItkImage(mask, itk_mask);
ItkUcharImgType::Pointer itk_mask2;
mitk::CastToItkImage(mask2, itk_mask2);
float ol = fib->GetOverlap(itk_mask);
float ep = fib->GetNumEpFractionInMask(itk_mask2, true);
MITK_INFO << "Overlap<<" << ol;
MITK_INFO << "EP-Fraction<<" << ep;
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/TractographyEvaluation/ExtractSimilarTracts.cpp b/Modules/DiffusionCmdApps/TractographyEvaluation/ExtractSimilarTracts.cpp
index a11e030..58a8453 100644
--- a/Modules/DiffusionCmdApps/TractographyEvaluation/ExtractSimilarTracts.cpp
+++ b/Modules/DiffusionCmdApps/TractographyEvaluation/ExtractSimilarTracts.cpp
@@ -1,199 +1,199 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkFiberBundle.h>
#include <mitkDiffusionCommandLineParser.h>
#include <mitkLexicalCast.h>
#include <mitkIOUtil.h>
#include <itkTractClusteringFilter.h>
#include <mitkClusteringMetricEuclideanMean.h>
#include <mitkClusteringMetricEuclideanMax.h>
#include <mitkClusteringMetricEuclideanStd.h>
#include <mitkClusteringMetricAnatomic.h>
#include <mitkClusteringMetricScalarMap.h>
#include <mitkDiffusionDataIOHelper.h>
typedef itk::Image<unsigned char, 3> ItkFloatImgType;
/*!
\brief Spatially cluster fibers
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Extract Similar Tracts");
parser.setCategory("Fiber Tracking Evaluation");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::String, "Input:", "input fiber bundle (.fib, .trk, .tck)", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("ref_tracts", "", mitkDiffusionCommandLineParser::StringList, "Ref. Tracts:", "reference tracts (.fib, .trk, .tck)", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("ref_masks", "", mitkDiffusionCommandLineParser::StringList, "Ref. Masks:", "reference bundle masks", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output root", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("distance", "", mitkDiffusionCommandLineParser::Int, "Distance:", "", 10);
parser.addArgument("metric", "", mitkDiffusionCommandLineParser::String, "Metric:", "EU_MEAN (default), EU_STD, EU_MAX");
parser.addArgument("subsample", "", mitkDiffusionCommandLineParser::Float, "Subsampling factor:", "Only use specified fraction of input fibers", 1.0);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
std::string in_fib = us::any_cast<std::string>(parsedArgs["i"]);
std::string out_root = us::any_cast<std::string>(parsedArgs["o"]);
mitkDiffusionCommandLineParser::StringContainerType ref_bundle_files = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["ref_tracts"]);
mitkDiffusionCommandLineParser::StringContainerType ref_mask_files;
if (parsedArgs.count("ref_masks"))
ref_mask_files = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["ref_masks"]);
if (ref_mask_files.size()>0 && ref_mask_files.size()!=ref_bundle_files.size())
{
MITK_INFO << "If reference masks are used, there has to be one mask per reference tract.";
return EXIT_FAILURE;
}
int distance = 10;
if (parsedArgs.count("distance"))
distance = us::any_cast<int>(parsedArgs["distance"]);
std::string metric = "EU_MEAN";
if (parsedArgs.count("metric"))
metric = us::any_cast<std::string>(parsedArgs["metric"]);
float subsample = 1.0;
if (parsedArgs.count("subsample"))
subsample = us::any_cast<float>(parsedArgs["subsample"]);
try
{
mitk::FiberBundle::Pointer fib = mitk::IOUtil::Load<mitk::FiberBundle>(in_fib);
std::srand(0);
if (subsample<1.0f)
fib = fib->SubsampleFibers(subsample, true);
mitk::FiberBundle::Pointer resampled_fib = fib->GetDeepCopy();
resampled_fib->ResampleToNumPoints(12);
auto ref_fibs = mitk::DiffusionDataIOHelper::load_fibs(ref_bundle_files);
auto ref_masks = mitk::DiffusionDataIOHelper::load_itk_images<ItkFloatImgType>(ref_mask_files);
std::vector< float > distances;
distances.push_back(distance);
mitk::FiberBundle::Pointer extracted = mitk::FiberBundle::New(nullptr);
unsigned int c = 0;
for (auto ref_fib : ref_fibs)
{
MITK_INFO << "Extracting " << ist::GetFilenameName(ref_bundle_files.at(c));
std::streambuf *old = cout.rdbuf(); // <-- save
std::stringstream ss;
std::cout.rdbuf (ss.rdbuf()); // <-- redirect
try
{
itk::TractClusteringFilter::Pointer segmenter = itk::TractClusteringFilter::New();
// calculate centroids from reference bundle
{
itk::TractClusteringFilter::Pointer clusterer = itk::TractClusteringFilter::New();
clusterer->SetDistances({10,20,30});
clusterer->SetTractogram(ref_fib);
clusterer->SetMetrics({new mitk::ClusteringMetricEuclideanStd()});
clusterer->SetMergeDuplicateThreshold(0.0);
clusterer->Update();
std::vector<mitk::FiberBundle::Pointer> tracts = clusterer->GetOutCentroids();
ref_fib = mitk::FiberBundle::New(nullptr);
ref_fib = ref_fib->AddBundles(tracts);
mitk::IOUtil::Save(ref_fib, out_root + "centroids_" + ist::GetFilenameName(ref_bundle_files.at(c)));
segmenter->SetInCentroids(ref_fib);
}
// segment tract
if (c<ref_masks.size())
{
segmenter->SetFilterMask(ref_masks.at(c));
segmenter->SetOverlapThreshold(0.8f);
}
segmenter->SetDistances(distances);
segmenter->SetTractogram(resampled_fib);
segmenter->SetMergeDuplicateThreshold(0.0);
segmenter->SetDoResampling(false);
if (metric=="EU_MEAN")
segmenter->SetMetrics({new mitk::ClusteringMetricEuclideanMean()});
else if (metric=="EU_STD")
segmenter->SetMetrics({new mitk::ClusteringMetricEuclideanStd()});
else if (metric=="EU_MAX")
segmenter->SetMetrics({new mitk::ClusteringMetricEuclideanMax()});
segmenter->Update();
std::vector< std::vector< unsigned int > > clusters = segmenter->GetOutFiberIndices();
if (clusters.size()>0)
{
vtkSmartPointer<vtkFloatArray> weights = vtkSmartPointer<vtkFloatArray>::New();
mitk::FiberBundle::Pointer result = mitk::FiberBundle::New(nullptr);
std::vector< mitk::FiberBundle::Pointer > result_fibs;
for (unsigned int cluster_index=0; cluster_index<clusters.size()-1; ++cluster_index)
result_fibs.push_back(mitk::FiberBundle::New(fib->GeneratePolyDataByIds(clusters.at(cluster_index), weights)));
result = result->AddBundles(result_fibs);
extracted = extracted->AddBundle(result);
mitk::IOUtil::Save(result, out_root + "extracted_" + ist::GetFilenameName(ref_bundle_files.at(c)));
fib = mitk::FiberBundle::New(fib->GeneratePolyDataByIds(clusters.back(), weights));
resampled_fib = mitk::FiberBundle::New(resampled_fib->GeneratePolyDataByIds(clusters.back(), weights));
}
}
catch(itk::ExceptionObject& excpt)
{
MITK_INFO << "Exception while processing " << ist::GetFilenameName(ref_bundle_files.at(c));
MITK_INFO << excpt.GetDescription();
}
catch(std::exception& excpt)
{
MITK_INFO << "Exception while processing " << ist::GetFilenameName(ref_bundle_files.at(c));
MITK_INFO << excpt.what();
}
std::cout.rdbuf (old); // <-- restore
if (fib->GetNumFibers()==0)
break;
++c;
}
MITK_INFO << "Extracted streamlines: " << extracted->GetNumFibers();
mitk::IOUtil::Save(extracted, out_root + "extracted_streamlines.trk");
MITK_INFO << "Residual streamlines: " << fib->GetNumFibers();
mitk::IOUtil::Save(fib, out_root + "residual_streamlines.trk");
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/TractographyEvaluation/GetOverlappingTracts.cpp b/Modules/DiffusionCmdApps/TractographyEvaluation/GetOverlappingTracts.cpp
index 2c3916d..e106074 100644
--- a/Modules/DiffusionCmdApps/TractographyEvaluation/GetOverlappingTracts.cpp
+++ b/Modules/DiffusionCmdApps/TractographyEvaluation/GetOverlappingTracts.cpp
@@ -1,167 +1,167 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <metaCommand.h>
#include "mitkDiffusionCommandLineParser.h"
#include <usAny.h>
#include <mitkIOUtil.h>
#include <mitkLexicalCast.h>
#include <mitkCoreObjectFactory.h>
#include <mitkFiberBundle.h>
#include <mitkImageCast.h>
#include <mitkImageToItk.h>
#include <itksys/SystemTools.hxx>
#include <itkTractDensityImageFilter.h>
#include <mitkDiffusionDataIOHelper.h>
#define _USE_MATH_DEFINES
#include <math.h>
typedef itksys::SystemTools ist;
typedef itk::Image<unsigned char, 3> ItkFloatImgType;
/*!
\brief Extract fibers from a tractogram using binary image ROIs
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Get Overlapping Tracts");
parser.setCategory("Fiber Tracking and Processing Methods");
parser.setContributor("MIC");
parser.setDescription("Find tracts that overlap with the reference masks or tracts");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::StringList, "Input:", "input tractograms (.fib/.trk/.tck/.dcm)", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output Folder:", "move input tracts that do/don't overlap here", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("reference", "", mitkDiffusionCommandLineParser::StringList, "Reference:", "reference tractograms or mask images", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("overlap_fraction", "", mitkDiffusionCommandLineParser::Float, "Overlap fraction:", "", 0.9);
parser.addArgument("use_any_overlap", "", mitkDiffusionCommandLineParser::Bool, "Use any overlap:", "Don't find maximum overlap but use first overlap larger threshold");
parser.addArgument("dont_save_tracts", "", mitkDiffusionCommandLineParser::Bool, "Don't save tracts:", "if true, only text files documenting the overlaps are saved and no tract files are copied");
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
mitkDiffusionCommandLineParser::StringContainerType input = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["i"]);
mitkDiffusionCommandLineParser::StringContainerType reference = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["reference"]);
std::string out_folder = us::any_cast<std::string>(parsedArgs["o"]);
bool use_any_overlap = false;
if (parsedArgs.count("use_any_overlap"))
use_any_overlap = us::any_cast<bool>(parsedArgs["use_any_overlap"]);
bool dont_save_tracts = false;
if (parsedArgs.count("dont_save_tracts"))
dont_save_tracts = us::any_cast<bool>(parsedArgs["dont_save_tracts"]);
float overlap_threshold = 0.9;
if (parsedArgs.count("overlap_fraction"))
overlap_threshold = us::any_cast<float>(parsedArgs["overlap_fraction"]);
try
{
MITK_INFO << "Loading references";
std::vector< std::string > reference_names;
auto masks = mitk::DiffusionDataIOHelper::load_itk_images<ItkFloatImgType>(reference, &reference_names);
auto reference_fibs = mitk::DiffusionDataIOHelper::load_fibs(reference, &reference_names);
std::streambuf *old = cout.rdbuf(); // <-- save
std::stringstream ss;
std::cout.rdbuf (ss.rdbuf()); // <-- redirect
itk::TractDensityImageFilter< ItkFloatImgType >::Pointer filter = itk::TractDensityImageFilter< ItkFloatImgType >::New();
filter->SetUpsamplingFactor(0.25);
filter->SetBinaryOutput(true);
for (auto fib : reference_fibs)
{
filter->SetFiberBundle(fib);
filter->Update();
masks.push_back(filter->GetOutput());
}
std::cout.rdbuf (old); // <-- restore
MITK_INFO << "Loading input tractograms";
std::vector< std::string > input_names;
auto input_fibs = mitk::DiffusionDataIOHelper::load_fibs(input, &input_names);
MITK_INFO << "Finding overlaps";
ofstream logfile;
logfile.open (out_folder + "Overlaps.txt");
ofstream logfile2;
logfile2.open (out_folder + "AllOverlaps.txt");
boost::progress_display disp(input.size());
unsigned int c = 0;
for (auto fib : input_fibs)
{
++disp;
std::streambuf *old = cout.rdbuf(); // <-- save
std::stringstream ss;
std::cout.rdbuf (ss.rdbuf()); // <-- redirect
bool is_overlapping = false;
float overlap = 0;
float max_overlap = 0;
std::string max_ref = "-";
int i = 0;
std::string overlap_string = ist::GetFilenameWithoutExtension(input_names.at(c));
for (auto m : masks)
{
overlap = fib->GetOverlap(m);
if (overlap>max_overlap)
{
max_overlap = overlap;
max_ref = ist::GetFilenameWithoutExtension(reference_names.at(i));
}
if (use_any_overlap && overlap>=overlap_threshold)
break;
overlap_string += " " + ist::GetFilenameWithoutExtension(reference_names.at(i)) + " " + boost::lexical_cast<std::string>(overlap);
++i;
}
if (overlap>=overlap_threshold)
is_overlapping = true;
logfile << ist::GetFilenameWithoutExtension(input_names.at(c)) << " - " << max_ref << ": " << boost::lexical_cast<std::string>(max_overlap) << "\n";
logfile2 << overlap_string << "\n";
if (!dont_save_tracts && is_overlapping)
ist::CopyAFile(input_names.at(c), out_folder + ist::GetFilenameName(input_names.at(c)));
std::cout.rdbuf (old); // <-- restore
++c;
}
logfile.close();
logfile2.close();
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/TractographyEvaluation/MergeOverlappingTracts.cpp b/Modules/DiffusionCmdApps/TractographyEvaluation/MergeOverlappingTracts.cpp
index 712cfda..cf440f6 100644
--- a/Modules/DiffusionCmdApps/TractographyEvaluation/MergeOverlappingTracts.cpp
+++ b/Modules/DiffusionCmdApps/TractographyEvaluation/MergeOverlappingTracts.cpp
@@ -1,214 +1,214 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkBaseData.h>
#include <mitkImageCast.h>
#include <mitkImageToItk.h>
#include <metaCommand.h>
#include <mitkDiffusionCommandLineParser.h>
#include <usAny.h>
#include <mitkIOUtil.h>
#include <mitkLexicalCast.h>
#include <mitkFiberBundle.h>
#include <vtkTransformPolyDataFilter.h>
#include <fstream>
#include <chrono>
#include <boost/progress.hpp>
#include <itkTractsToFiberEndingsImageFilter.h>
#include <itkTractDensityImageFilter.h>
#include <itkImageRegionConstIterator.h>
#include <mitkDiffusionDataIOHelper.h>
typedef itk::Image<unsigned char, 3> ItkFloatImgType;
typedef itk::Image<unsigned int, 3> ItkUIntImgType;
/*!
\brief
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Merge Overlapping Tracts");
parser.setCategory("Fiber Tracking Evaluation");
parser.setDescription("");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::StringList, "Input:", "input tracts", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output Folder:", "output folder", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("overlap", "", mitkDiffusionCommandLineParser::Float, "Overlap threshold:", "Tracts with overlap larger than this threshold are merged", 0.8, false);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
mitkDiffusionCommandLineParser::StringContainerType input_folder = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["i"]);
std::string out_folder = us::any_cast<std::string>(parsedArgs["o"]);
float overlap = 0.8;
if (parsedArgs.count("overlap"))
overlap = us::any_cast<float>(parsedArgs["overlap"]);
try
{
if (!ist::PathExists(out_folder))
ist::MakeDirectory(out_folder);
std::vector< mitk::FiberBundle::Pointer > fibs = mitk::DiffusionDataIOHelper::load_fibs(input_folder);
std::streambuf *old = cout.rdbuf(); // <-- save
std::stringstream ss;
std::cout.rdbuf (ss.rdbuf()); // <-- redirect
mitk::FiberBundle::Pointer combined = mitk::FiberBundle::New();
combined = combined->AddBundles(fibs);
itk::TractsToFiberEndingsImageFilter< ItkFloatImgType >::Pointer endings = itk::TractsToFiberEndingsImageFilter< ItkFloatImgType >::New();
endings->SetFiberBundle(combined);
endings->SetUpsamplingFactor(0.25);
endings->Update();
ItkFloatImgType::Pointer ref_image = endings->GetOutput();
std::cout.rdbuf (old); // <-- restore
for (int its = 0; its<3; its++)
{
std::streambuf *old = cout.rdbuf(); // <-- save
std::stringstream ss;
std::cout.rdbuf (ss.rdbuf()); // <-- redirect
std::vector< ItkFloatImgType::Pointer > mask_images;
for (auto fib : fibs)
{
itk::TractDensityImageFilter< ItkFloatImgType >::Pointer masks = itk::TractDensityImageFilter< ItkFloatImgType >::New();
masks->SetInputImage(ref_image);
masks->SetBinaryOutput(true);
masks->SetFiberBundle(fib);
masks->SetUseImageGeometry(true);
masks->Update();
mask_images.push_back(masks->GetOutput());
}
int r=0;
vnl_matrix< int > mat; mat.set_size(mask_images.size(), mask_images.size()); mat.fill(0);
for (auto m1 : mask_images)
{
float max_overlap = overlap;
int c = 0;
for (auto m2 : mask_images)
{
if (c<=r)
{
++c;
continue;
}
itk::ImageRegionConstIterator<ItkFloatImgType> it1(m1, m1->GetLargestPossibleRegion());
itk::ImageRegionConstIterator<ItkFloatImgType> it2(m2, m2->GetLargestPossibleRegion());
unsigned int c1 = 0;
unsigned int c2 = 0;
unsigned int intersect = 0;
while( !it1.IsAtEnd() )
{
if( it1.Get()>0 && it2.Get()>0)
++intersect;
if(it1.Get()>0)
++c1;
if(it2.Get()>0)
++c2;
++it1;
++it2;
}
if ( (float)intersect/c1>max_overlap )
{
max_overlap = (float)intersect/c1;
mat.put(r,c, 1);
}
if ( (float)intersect/c2>max_overlap )
{
max_overlap = (float)intersect/c2;
mat.put(r,c, 1);
}
++c;
}
++r;
}
std::vector< mitk::FiberBundle::Pointer > out_fibs;
std::vector< bool > used;
for (unsigned int i=0; i<fibs.size(); i++)
used.push_back(false);
for (unsigned int r=0; r<mask_images.size(); r++)
{
if (used.at(r))
continue;
mitk::FiberBundle::Pointer fib = fibs.at(r);
for (unsigned int c=r+1; c<mask_images.size(); c++)
{
if (mat.get(r,c)>0)
{
fib = fib->AddBundle(fibs.at(c));
used[c] = true;
}
}
out_fibs.push_back(fib);
}
std::cout.rdbuf (old); // <-- restore
MITK_INFO << fibs.size() << " --> " << out_fibs.size();
if (fibs.size()==out_fibs.size())
break;
fibs = out_fibs;
}
int c = 0;
for (auto fib : fibs)
{
std::streambuf *old = cout.rdbuf(); // <-- save
std::stringstream ss;
std::cout.rdbuf (ss.rdbuf()); // <-- redirect
mitk::IOUtil::Save(fib, out_folder + "/bundle_" + boost::lexical_cast<std::string>(c) + ".trk");
std::cout.rdbuf (old); // <-- restore
++c;
}
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/TractographyEvaluation/PeaksAngularError.cpp b/Modules/DiffusionCmdApps/TractographyEvaluation/PeaksAngularError.cpp
index 7fc671a..b9d4b62 100644
--- a/Modules/DiffusionCmdApps/TractographyEvaluation/PeaksAngularError.cpp
+++ b/Modules/DiffusionCmdApps/TractographyEvaluation/PeaksAngularError.cpp
@@ -1,190 +1,190 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkBaseData.h>
#include <mitkImageCast.h>
#include <mitkImageToItk.h>
#include <itkEvaluateDirectionImagesFilter.h>
#include <metaCommand.h>
#include "mitkDiffusionCommandLineParser.h"
#include <itkTractsToVectorImageFilter.h>
#include <usAny.h>
#include <itkImageFileWriter.h>
#include <mitkIOUtil.h>
#include <mitkLexicalCast.h>
#include <iostream>
#include <fstream>
#include <mitkPeakImage.h>
#include <mitkDiffusionDataIOHelper.h>
#include <mitkLocaleSwitch.h>
typedef itk::Image< unsigned char, 3 > ItkUcharImageType;
/*!
\brief Calculate angular error between two sets of directions stored in multiple 3D vector images where each pixel corresponds to a vector (itk::Image< itk::Vector< float, 3>, 3 >)
*/
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setArgumentPrefix("--", "-");
parser.addArgument("test", "", mitkDiffusionCommandLineParser::StringList, "Test images", "test direction images", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("reference", "", mitkDiffusionCommandLineParser::StringList, "Reference images", "reference direction images", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output folder", "output folder", us::Any(), false, false, false, mitkDiffusionCommandLineParser::Output);
parser.addArgument("masks", "", mitkDiffusionCommandLineParser::StringList, "Mask(s)", "mask image(s)", us::Any(), true, false, false, mitkDiffusionCommandLineParser::Input);
parser.addArgument("verbose", "", mitkDiffusionCommandLineParser::Bool, "Verbose", "output error images");
parser.addArgument("ignore_test", "", mitkDiffusionCommandLineParser::Bool, "Ignore missing test", "don't increase error if no test directions are found");
parser.addArgument("ignore_ref", "", mitkDiffusionCommandLineParser::Bool, "Ignore ignore missing ref", "don't increase error if no ref directions are found");
parser.setCategory("Fiber Tracking Evaluation");
parser.setTitle("Peaks Angular Error");
parser.setDescription("Calculate angular error between two sets of peak images (1-1 correspondence)");
parser.setContributor("MIC");
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
mitkDiffusionCommandLineParser::StringContainerType testImages = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["test"]);
mitkDiffusionCommandLineParser::StringContainerType referenceImages = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["reference"]);
mitkDiffusionCommandLineParser::StringContainerType maskImages;
if (parsedArgs.count("masks"))
maskImages = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["masks"]);
std::string outRoot = us::any_cast<std::string>(parsedArgs["o"]);
bool verbose = false;
if (parsedArgs.count("verbose"))
verbose = us::any_cast<bool>(parsedArgs["verbose"]);
bool ignore_test = false;
if (parsedArgs.count("ignore_test"))
ignore_test = us::any_cast<bool>(parsedArgs["ignore_test"]);
bool ignore_ref = false;
if (parsedArgs.count("ignore_ref"))
ignore_ref = us::any_cast<bool>(parsedArgs["ignore_ref"]);
try
{
typedef itk::ComparePeakImagesFilter< float > EvaluationFilterType;
std::vector<std::string> test_names;
auto test_images = mitk::DiffusionDataIOHelper::load_itk_images<EvaluationFilterType::PeakImageType>(testImages, &test_names);
// load reference directions
std::vector<std::string> ref_names;
auto ref_images = mitk::DiffusionDataIOHelper::load_itk_images<EvaluationFilterType::PeakImageType>(referenceImages, &ref_names);
// load/create mask image
auto itkMaskImages = mitk::DiffusionDataIOHelper::load_itk_images<ItkUcharImageType>(maskImages);
if (test_images.size()!=ref_images.size())
mitkThrow() << "Matching number of test and reference image required!";
for (unsigned int i=0; i<test_images.size(); ++i)
{
// evaluate directions
EvaluationFilterType::Pointer evaluationFilter = EvaluationFilterType::New();
evaluationFilter->SetTestImage(test_images.at(i));
evaluationFilter->SetReferenceImage(ref_images.at(i));
if (i<maskImages.size())
evaluationFilter->SetMaskImage(itkMaskImages.at(i));
evaluationFilter->SetIgnoreMissingTestDirections(ignore_test);
evaluationFilter->SetIgnoreMissingRefDirections(ignore_ref);
evaluationFilter->Update();
std::string ref_name = ist::GetFilenameWithoutExtension(ref_names.at(i));
std::string test_name = ist::GetFilenameWithoutExtension(test_names.at(i));
if (verbose)
{
mitk::LocaleSwitch localeSwitch("C");
EvaluationFilterType::OutputImageType::Pointer angularErrorImage = evaluationFilter->GetOutput(0);
EvaluationFilterType::OutputImageType::Pointer lengthErrorImage = evaluationFilter->GetOutput(1);
typedef itk::ImageFileWriter< EvaluationFilterType::OutputImageType > WriterType;
{
WriterType::Pointer writer = WriterType::New();
std::string outfilename = outRoot;
outfilename.append(ref_name + "_" + test_name + "_AngularError.nii.gz");
writer->SetFileName(outfilename.c_str());
writer->SetInput(angularErrorImage);
writer->Update();
}
{
WriterType::Pointer writer = WriterType::New();
std::string outfilename = outRoot;
outfilename.append(ref_name + "_" + test_name + "_LengthError.nii.gz");
writer->SetFileName(outfilename.c_str());
writer->SetInput(lengthErrorImage);
writer->Update();
}
}
std::string logFile = outRoot;
logFile.append("AngularErrors.csv");
bool add_header = true;
if (ist::FileExists(logFile, true))
add_header = false;
ofstream file;
file.open (logFile.c_str(), std::fstream::app);
std::string sens;
if (add_header)
sens.append("Test,Reference,Mean,Median,Maximum,Minimum,Stdev\n");
sens.append(test_name);
sens.append(",");
sens.append(ref_name);
sens.append(",");
sens.append(boost::lexical_cast<std::string>(evaluationFilter->GetMeanAngularError()));
sens.append(",");
sens.append(boost::lexical_cast<std::string>(evaluationFilter->GetMedianAngularError()));
sens.append(",");
sens.append(boost::lexical_cast<std::string>(evaluationFilter->GetMaxAngularError()));
sens.append(",");
sens.append(boost::lexical_cast<std::string>(evaluationFilter->GetMinAngularError()));
sens.append(",");
sens.append(boost::lexical_cast<std::string>(std::sqrt(evaluationFilter->GetVarAngularError())));
sens.append("\n");
std::cout << sens;
file << sens;
file.close();
}
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/TractographyEvaluation/ReferenceSimilarity.cpp b/Modules/DiffusionCmdApps/TractographyEvaluation/ReferenceSimilarity.cpp
index 83b1f0b..54666d3 100644
--- a/Modules/DiffusionCmdApps/TractographyEvaluation/ReferenceSimilarity.cpp
+++ b/Modules/DiffusionCmdApps/TractographyEvaluation/ReferenceSimilarity.cpp
@@ -1,149 +1,149 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkFiberBundle.h>
#include <mitkDiffusionCommandLineParser.h>
#include <mitkDiffusionDataIOHelper.h>
#include <mitkLexicalCast.h>
#include <itkTractDistanceFilter.h>
#include <mitkClusteringMetricEuclideanMean.h>
#include <mitkClusteringMetricEuclideanMax.h>
#include <mitkClusteringMetricEuclideanStd.h>
#include <boost/progress.hpp>
typedef itk::Image< unsigned char, 3 > ItkUcharImageType;
typedef itk::Image< float, 4 > ItkPeakImgType;
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Reference Similarity");
parser.setCategory("Fiber Tracking Evaluation");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i", mitkDiffusionCommandLineParser::StringList, "Input Tracts:", "input tracts folder", us::Any(), false);
parser.addArgument("reference_tracts", "", mitkDiffusionCommandLineParser::StringList, "", "", us::Any(), false);
parser.addArgument("reference_masks", "", mitkDiffusionCommandLineParser::StringList, "", "", us::Any(), false);
parser.addArgument("reference_peaks", "", mitkDiffusionCommandLineParser::StringList, "", "", us::Any(), false);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "", "", us::Any(), false);
parser.addArgument("fiber_points", "", mitkDiffusionCommandLineParser::Int, "Fiber points:", "", 20);
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
std::string out_folder = us::any_cast<std::string>(parsedArgs["o"]);
mitkDiffusionCommandLineParser::StringContainerType input_tract_files = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["i"]);
mitkDiffusionCommandLineParser::StringContainerType reference_tract_files = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["reference_tracts"]);
mitkDiffusionCommandLineParser::StringContainerType reference_mask_files = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["reference_masks"]);
mitkDiffusionCommandLineParser::StringContainerType reference_peak_files = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["reference_peaks"]);
int fiber_points = 20;
if (parsedArgs.count("fiber_points"))
fiber_points = us::any_cast<int>(parsedArgs["fiber_points"]);
try
{
std::vector<std::string> input_tract_names;
std::vector<std::string> ref_tract_names;
std::vector< mitk::FiberBundle::Pointer > input_tracts = mitk::DiffusionDataIOHelper::load_fibs(input_tract_files, &input_tract_names);
std::vector< mitk::FiberBundle::Pointer > reference_tracts = mitk::DiffusionDataIOHelper::load_fibs(reference_tract_files, &ref_tract_names);
std::vector< ItkUcharImageType::Pointer > reference_masks = mitk::DiffusionDataIOHelper::load_itk_images<ItkUcharImageType>(reference_mask_files);
std::vector< ItkPeakImgType::Pointer > reference_peaks = mitk::DiffusionDataIOHelper::load_itk_images<ItkPeakImgType>(reference_peak_files);
MITK_INFO << "Calculating distances";
itk::TractDistanceFilter::Pointer distance_calculator = itk::TractDistanceFilter::New();
distance_calculator->SetNumPoints(fiber_points);
distance_calculator->SetTracts1(input_tracts);
distance_calculator->SetTracts2(reference_tracts);
distance_calculator->SetMetrics({new mitk::ClusteringMetricEuclideanMean()});
distance_calculator->Update();
auto distances = distance_calculator->GetAllDistances();
vnl_matrix<float> voxel_overlap; voxel_overlap.set_size(input_tracts.size(), reference_tracts.size());
vnl_matrix<float> dir_overlap; dir_overlap.set_size(input_tracts.size(), reference_tracts.size());
MITK_INFO << "Calculating overlap";
boost::progress_display disp(input_tracts.size()*reference_tracts.size());
int r=0;
for (auto fib : input_tracts)
{
int c=0;
for (auto ref_mask : reference_masks)
{
// ++disp;
// std::streambuf *old = cout.rdbuf(); // <-- save
// std::stringstream ss;
// std::cout.rdbuf (ss.rdbuf()); // <-- redirect
float overlap = 0;
float directional_overlap = 0;
std::tie(directional_overlap, overlap) = fib->GetDirectionalOverlap(ref_mask, reference_peaks.at(c));
voxel_overlap[r][c] = overlap;
dir_overlap[r][c] = directional_overlap;
// std::cout.rdbuf (old); // <-- restore
++c;
}
++r;
}
ofstream logfile;
logfile.open(out_folder + "ref_tract_names.txt");
for (unsigned int i=0; i<ref_tract_names.size(); ++i)
logfile << ist::GetFilenameWithoutExtension(ref_tract_names.at(i)) << std::endl;
logfile << "----------" << std::endl;
for (unsigned int i=0; i<input_tract_names.size(); ++i)
logfile << ist::GetFilenameWithoutExtension(input_tract_names.at(i)) << std::endl;
logfile.close();
MITK_INFO << "Saving matrices";
{
std::ofstream OutputStream(out_folder + "ref_distances.txt");
OutputStream << distances;
OutputStream.close();
}
{
std::ofstream OutputStream(out_folder + "ref_voxel_overlap.txt");
OutputStream << voxel_overlap;
OutputStream.close();
}
{
std::ofstream OutputStream(out_folder + "ref_dir_overlap.txt");
OutputStream << dir_overlap;
OutputStream.close();
}
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/TractographyEvaluation/TractDistance.cpp b/Modules/DiffusionCmdApps/TractographyEvaluation/TractDistance.cpp
index 8e42073..845ccbc 100644
--- a/Modules/DiffusionCmdApps/TractographyEvaluation/TractDistance.cpp
+++ b/Modules/DiffusionCmdApps/TractographyEvaluation/TractDistance.cpp
@@ -1,139 +1,139 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkFiberBundle.h>
#include <mitkDiffusionCommandLineParser.h>
#include <mitkLexicalCast.h>
#include <mitkIOUtil.h>
#include <itkTractDistanceFilter.h>
#include <mitkClusteringMetricEuclideanMean.h>
#include <mitkClusteringMetricEuclideanMax.h>
#include <mitkClusteringMetricEuclideanStd.h>
#include <mitkDiffusionDataIOHelper.h>
int main(int argc, char* argv[])
{
mitkDiffusionCommandLineParser parser;
parser.setTitle("Tract Distance");
parser.setCategory("Fiber Processing");
parser.setContributor("MIC");
parser.setArgumentPrefix("--", "-");
parser.addArgument("", "i1", mitkDiffusionCommandLineParser::StringList, "Input tracts 1:", "input tracts 1", us::Any(), false);
parser.addArgument("", "i2", mitkDiffusionCommandLineParser::StringList, "Input tracts 2:", "input tracts 2", us::Any(), false);
parser.addArgument("", "o", mitkDiffusionCommandLineParser::String, "Output:", "output logfile", us::Any(), false);
parser.addArgument("fiber_points", "", mitkDiffusionCommandLineParser::Int, "Fiber points:", "", 12);
parser.addArgument("metrics", "", mitkDiffusionCommandLineParser::StringList, "Metrics:", "EU_MEAN (default), EU_STD, EU_MAX");
parser.addArgument("metric_weights", "", mitkDiffusionCommandLineParser::StringList, "Metric weights:", "add one float weight for each used metric");
std::map<std::string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
if (parsedArgs.size()==0)
return EXIT_FAILURE;
mitkDiffusionCommandLineParser::StringContainerType t1_folder = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["i1"]);
mitkDiffusionCommandLineParser::StringContainerType t2_folder = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["i2"]);
std::string out_file = us::any_cast<std::string>(parsedArgs["o"]);
int fiber_points = 12;
if (parsedArgs.count("fiber_points"))
fiber_points = us::any_cast<int>(parsedArgs["fiber_points"]);
std::vector< std::string > metric_strings = {"EU_MEAN"};
if (parsedArgs.count("metrics"))
metric_strings = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["metrics"]);
std::vector< std::string > metric_weights = {"1.0"};
if (parsedArgs.count("metric_weights"))
metric_weights = us::any_cast<mitkDiffusionCommandLineParser::StringContainerType>(parsedArgs["metric_weights"]);
if (metric_strings.size()!=metric_weights.size())
{
MITK_INFO << "Each metric needs an associated metric weight!";
return EXIT_FAILURE;
}
try
{
std::vector<std::string> t1_files;
std::vector< mitk::FiberBundle::Pointer > tractograms1 = mitk::DiffusionDataIOHelper::load_fibs(t1_folder, &t1_files);
std::vector<std::string> t2_files;
std::vector< mitk::FiberBundle::Pointer > tractograms2 = mitk::DiffusionDataIOHelper::load_fibs(t2_folder, &t2_files);
MITK_INFO << "Loaded " << tractograms1.size() << " source tractograms.";
MITK_INFO << "Loaded " << tractograms2.size() << " target tractograms.";
itk::TractDistanceFilter::Pointer distance_calculator = itk::TractDistanceFilter::New();
distance_calculator->SetNumPoints(fiber_points);
distance_calculator->SetTracts1(tractograms1);
distance_calculator->SetTracts2(tractograms2);
std::vector< mitk::ClusteringMetric* > metrics;
int mc = 0;
for (auto m : metric_strings)
{
float w = boost::lexical_cast<float>(metric_weights.at(mc));
MITK_INFO << "Metric: " << m << " (w=" << w << ")";
if (m=="EU_MEAN")
metrics.push_back({new mitk::ClusteringMetricEuclideanMean()});
else if (m=="EU_STD")
metrics.push_back({new mitk::ClusteringMetricEuclideanStd()});
else if (m=="EU_MAX")
metrics.push_back({new mitk::ClusteringMetricEuclideanMax()});
metrics.back()->SetScale(w);
mc++;
}
if (metrics.empty())
{
MITK_INFO << "No metric selected!";
return EXIT_FAILURE;
}
distance_calculator->SetMetrics(metrics);
distance_calculator->Update();
MITK_INFO << "Distances:";
auto distances = distance_calculator->GetMinDistances();
auto indices = distance_calculator->GetMinIndices();
ofstream logfile;
logfile.open (out_file);
for (unsigned int i=0; i<distances.size(); ++i)
{
std::cout << ist::GetFilenameWithoutExtension(t1_files.at(i)) << " << " << ist::GetFilenameWithoutExtension(t2_files.at(indices[i])) << ": " << distances[i] << std::endl;
logfile << ist::GetFilenameWithoutExtension(t1_files.at(i)) << " " << ist::GetFilenameWithoutExtension(t2_files.at(indices[i])) << " " << distances[i] << std::endl;
}
logfile.close();
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
catch (...)
{
std::cout << "ERROR!?!";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
diff --git a/Modules/DiffusionCmdApps/mitkDiffusionCommandLineParser.cpp b/Modules/DiffusionCmdApps/mitkDiffusionCommandLineParser.cpp
index aa82269..5226d0d 100644
--- a/Modules/DiffusionCmdApps/mitkDiffusionCommandLineParser.cpp
+++ b/Modules/DiffusionCmdApps/mitkDiffusionCommandLineParser.cpp
@@ -1,71 +1,71 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*=========================================================================
Library: CTK
Copyright (c) Kitware Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.txt
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=========================================================================*/
#include <iostream>
#include <mitkDiffusionVersion.h>
#include "mitkDiffusionCommandLineParser.h"
mitkDiffusionCommandLineParser::mitkDiffusionCommandLineParser() : mitkCommandLineParser::mitkCommandLineParser()
{
}
std::map<std::string, us::Any> mitkDiffusionCommandLineParser::parseArguments(const StringContainerType &arguments, bool *ok)
{
for (unsigned int i = 1; i < arguments.size(); ++i)
{
std::string argument = arguments.at(i);
if (!argument.compare("--version"))
{
std::cout << "MITK Diffusion git commit hash: " << MITKDIFFUSION_REVISION << std::endl;
std::cout << "MITK Diffusion branch name: " << MITKDIFFUSION_REVISION_NAME << std::endl;
}
}
return mitkCommandLineParser::parseArguments(arguments, ok);
}
std::map<std::string, us::Any> mitkDiffusionCommandLineParser::parseArguments(int argc, char **argv, bool *ok)
{
std::cout << "Running Command Line Utility *" << Title << "*" << std::endl;
StringContainerType arguments;
// Create a StringContainerType of arguments
for (int i = 0; i < argc; ++i)
arguments.push_back(argv[i]);
return this->parseArguments(arguments, ok);
}
diff --git a/Modules/DiffusionCmdApps/mitkDiffusionCommandLineParser.h b/Modules/DiffusionCmdApps/mitkDiffusionCommandLineParser.h
index 5248f7f..5e3057b 100644
--- a/Modules/DiffusionCmdApps/mitkDiffusionCommandLineParser.h
+++ b/Modules/DiffusionCmdApps/mitkDiffusionCommandLineParser.h
@@ -1,37 +1,37 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkDiffusionCommandLineParser_h
#define __mitkDiffusionCommandLineParser_h
#include <mitkCommandLineParser.h>
#include <MitkDiffusionCmdAppsExports.h>
class MITKDIFFUSIONCMDAPPS_EXPORT mitkDiffusionCommandLineParser : public mitkCommandLineParser
{
public:
mitkDiffusionCommandLineParser();
std::map<std::string, us::Any> parseArguments(const StringContainerType &arguments, bool *ok = nullptr);
std::map<std::string, us::Any> parseArguments(int argc, char **argv, bool *ok = nullptr);
private:
};
#endif
diff --git a/Modules/DiffusionCmdApps/mitkDiffusionDataIOHelper.cpp b/Modules/DiffusionCmdApps/mitkDiffusionDataIOHelper.cpp
index 557cbc0..7e49278 100644
--- a/Modules/DiffusionCmdApps/mitkDiffusionDataIOHelper.cpp
+++ b/Modules/DiffusionCmdApps/mitkDiffusionDataIOHelper.cpp
@@ -1,127 +1,127 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkDiffusionDataIOHelper.h"
std::vector< std::string > mitk::DiffusionDataIOHelper::get_file_list(const std::string& path, const std::vector<std::string> extensions)
{
std::vector< std::string > file_list;
itk::Directory::Pointer dir = itk::Directory::New();
if (dir->Load(path.c_str()))
{
int n = dir->GetNumberOfFiles();
for (int r = 0; r < n; r++)
{
const char *filename = dir->GetFile(r);
std::string ext = ist::GetFilenameExtension(filename);
for (auto e : extensions)
{
if (ext==e)
{
file_list.push_back(path + '/' + filename);
break;
}
}
}
}
std::sort(file_list.begin(), file_list.end());
return file_list;
}
std::vector< mitk::Image::Pointer > mitk::DiffusionDataIOHelper::load_mitk_images(const std::vector<std::string> files, std::vector<std::string>* filenames)
{
mitk::LocaleSwitch localeSwitch("C");
std::streambuf *old = cout.rdbuf(); // <-- save
std::stringstream ss;
std::cout.rdbuf (ss.rdbuf()); // <-- redirect
std::vector< mitk::Image::Pointer > out;
for (auto f : files)
{
if (itksys::SystemTools::FileExists(f, true))
{
mitk::Image::Pointer image = mitk::IOUtil::Load<mitk::Image>(f);
if (image.IsNotNull())
{
out.push_back(image);
if (filenames!=nullptr)
filenames->push_back(f);
}
}
else if (itksys::SystemTools::PathExists(f))
{
if (!f.empty() && f.back() != '/')
f += "/";
auto list = get_file_list(f, {".nrrd",".nii.gz",".nii"});
for (auto file : list)
{
mitk::Image::Pointer image = mitk::IOUtil::Load<mitk::Image>(file);
if (image.IsNotNull())
{
out.push_back(image);
if (filenames!=nullptr)
filenames->push_back(file);
}
}
}
}
std::cout.rdbuf (old); // <-- restore
MITK_INFO << "Loaded " << out.size() << " images";
return out;
}
std::vector< mitk::FiberBundle::Pointer > mitk::DiffusionDataIOHelper::load_fibs(const std::vector<std::string> files, std::vector<std::string>* filenames)
{
std::streambuf *old = cout.rdbuf(); // <-- save
std::stringstream ss;
std::cout.rdbuf (ss.rdbuf()); // <-- redirect
std::vector< mitk::FiberBundle::Pointer > out;
for (auto f : files)
{
if (itksys::SystemTools::FileExists(f, true))
{
mitk::FiberBundle::Pointer fib = mitk::IOUtil::Load<mitk::FiberBundle>(f);
if (fib.IsNotNull())
{
out.push_back(fib);
if (filenames!=nullptr)
filenames->push_back(f);
}
}
else if (itksys::SystemTools::PathExists(f))
{
if (!f.empty() && f.back() != '/')
f += "/";
auto list = get_file_list(f, {".fib",".trk",".tck"});
for (auto file : list)
{
mitk::FiberBundle::Pointer fib = mitk::IOUtil::Load<mitk::FiberBundle>(file);
if (fib.IsNotNull())
{
out.push_back(fib);
if (filenames!=nullptr)
filenames->push_back(file);
}
}
}
}
std::cout.rdbuf (old); // <-- restore
MITK_INFO << "Loaded " << out.size() << " tractograms";
return out;
}
diff --git a/Modules/DiffusionCmdApps/mitkDiffusionDataIOHelper.h b/Modules/DiffusionCmdApps/mitkDiffusionDataIOHelper.h
index 5ea19c6..999f258 100644
--- a/Modules/DiffusionCmdApps/mitkDiffusionDataIOHelper.h
+++ b/Modules/DiffusionCmdApps/mitkDiffusionDataIOHelper.h
@@ -1,134 +1,134 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkDiffusionDataIOHelper_h_
#define __mitkDiffusionDataIOHelper_h_
#include <MitkDiffusionCmdAppsExports.h>
#include <itkImage.h>
#include <mitkImage.h>
#include <mitkIOUtil.h>
#include <mitkFiberBundle.h>
#include <mitkImageToItk.h>
#include <itksys/SystemTools.hxx>
#include <itkDirectory.h>
#include <mitkLocaleSwitch.h>
typedef itksys::SystemTools ist;
namespace mitk{
class MITKDIFFUSIONCMDAPPS_EXPORT DiffusionDataIOHelper
{
public:
static std::vector< std::string > get_file_list(const std::string& path, const std::vector< std::string > extensions={".fib", ".trk"});
static std::vector< mitk::FiberBundle::Pointer > load_fibs(const std::vector<std::string> files, std::vector<std::string>* filenames=nullptr);
static std::vector< mitk::Image::Pointer > load_mitk_images(const std::vector<std::string> files, std::vector<std::string>* filenames=nullptr);
template< class TYPE >
static typename TYPE::Pointer load_itk_image(const std::string file)
{
mitk::LocaleSwitch localeSwitch("C");
std::streambuf *old = cout.rdbuf(); // <-- save
std::stringstream ss;
std::cout.rdbuf (ss.rdbuf()); // <-- redirect
std::vector< typename TYPE::Pointer > out;
if (file.compare("")!=0 && itksys::SystemTools::FileExists(file))
{
mitk::Image::Pointer image = mitk::IOUtil::Load<mitk::Image>(file);
if (image.IsNotNull())
{
typedef mitk::ImageToItk< TYPE > CasterType;
typename CasterType::Pointer caster = CasterType::New();
caster->SetInput(image);
caster->Update();
typename TYPE::Pointer itk_image = caster->GetOutput();
std::cout.rdbuf (old); // <-- restore
MITK_INFO << "Loaded 1 image";
return itk_image;
}
}
std::cout.rdbuf (old); // <-- restore // <-- restore
MITK_INFO << "Loaded 0 images";
return nullptr;
}
template< class TYPE >
static std::vector< typename TYPE::Pointer > load_itk_images(const std::vector<std::string> files, std::vector<std::string>* filenames=nullptr)
{
mitk::LocaleSwitch localeSwitch("C");
std::streambuf *old = cout.rdbuf(); // <-- save
std::stringstream ss;
std::cout.rdbuf (ss.rdbuf()); // <-- redirect
std::vector< typename TYPE::Pointer > out;
for (auto f : files)
{
if (itksys::SystemTools::FileExists(f, true))
{
mitk::Image::Pointer image = mitk::IOUtil::Load<mitk::Image>(f);
if (image.IsNotNull())
{
typedef mitk::ImageToItk< TYPE > CasterType;
typename CasterType::Pointer caster = CasterType::New();
caster->SetInput(image);
caster->Update();
typename TYPE::Pointer itk_image = caster->GetOutput();
out.push_back(itk_image);
if (filenames!=nullptr)
filenames->push_back(f);
}
}
else if (itksys::SystemTools::PathExists(f))
{
if (!f.empty() && f.back() != '/')
f += "/";
auto list = get_file_list(f, {".nrrd",".nii.gz",".nii"});
for (auto file : list)
{
mitk::Image::Pointer image = mitk::IOUtil::Load<mitk::Image>(file);
if (image.IsNotNull())
{
typedef mitk::ImageToItk< TYPE > CasterType;
typename CasterType::Pointer caster = CasterType::New();
caster->SetInput(image);
caster->Update();
typename TYPE::Pointer itk_image = caster->GetOutput();
out.push_back(itk_image);
if (filenames!=nullptr)
filenames->push_back(file);
}
}
}
}
std::cout.rdbuf (old); // <-- restore
MITK_INFO << "Loaded " << out.size() << " images";
return out;
}
};
}
#endif //__mitkDiffusionDataIOHelper_h_
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/FittingFunctions/mitkAbstractFitter.h b/Modules/DiffusionCore/Algorithms/Reconstruction/FittingFunctions/mitkAbstractFitter.h
index 5356144..5bf4eb0 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/FittingFunctions/mitkAbstractFitter.h
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/FittingFunctions/mitkAbstractFitter.h
@@ -1,125 +1,125 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_AbstractFitter_H
#define _MITK_AbstractFitter_H
#include <vnl/vnl_least_squares_function.h>
#include <mitkDiffusionPropertyHelper.h>
#include <itkVectorImage.h>
#include <mitkTensorImage.h>
namespace mitk {
class AbstractFitter: public vnl_least_squares_function
{
public:
typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientContainerType;
typedef itk::VectorImage< unsigned short, 3 > DiffusionImageType;
typedef TensorImage::PixelType TensorType;
AbstractFitter(unsigned int number_of_parameters, unsigned int number_of_measurements) :
vnl_least_squares_function(number_of_parameters, number_of_measurements, no_gradient)
{
}
GradientContainerType::Pointer gradientDirections;
DiffusionImageType::PixelType measurements;
std::vector<double> bValues;
double S0;
std::vector<int> weightedIndices;
void set_S0(double val)
{
S0 = val;
}
void set_measurements(const DiffusionImageType::PixelType& m)
{
measurements = m;
}
void set_bvalues(std::vector<double>& x)
{
bValues = x;
}
void set_weightedIndices(std::vector<int>& x)
{
weightedIndices = x;
}
void set_gradient_directions(const GradientContainerType::Pointer& directions)
{
gradientDirections = directions;
}
static void Sph2Cart(vnl_vector_fixed<double,3>& dir, const double &theta, const double &phi)
{
dir[0] = std::sin(theta)*std::cos(phi);
dir[1] = std::sin(theta)*std::sin(phi);
dir[2] = std::cos(theta);
}
static void Cart2Sph(const vnl_vector_fixed<double,3>& dir, double &theta, double &phi)
{
theta = std::acos( dir[2] );
// phi goes from 0.0 (+x axis) and wraps at 2 * PI
// theta goes from 0.0 (+z axis) and wraps at PI
// if x and y are 0.0 or very close, return phi == 0
if (fabs(dir[0]) + fabs(dir[1]) < 1E-9)
{
phi = 0.0;
}
else {
// ie, if ( x == 0 && y == 0 ) == false
if (dir[1] == 0.0)
{
if (dir[0] > 0.0)
phi = 0.0;
else
phi = itk::Math::pi;
}
else if (dir[0] == 0.0)
{
// avoid div by zero
if (dir[1] > 0) {
phi = itk::Math::pi / 2.0;
}
else {
phi = 1.5 * itk::Math::pi;
}
}
else if (dir[0] > 0.0 && dir[1] > 0.0) // first quadrant
phi = atan(dir[1] / dir[0]);
else if (dir[0] < 0.0 && dir[1] > 0.0) // second quadrant
phi = itk::Math::pi + atan(dir[1] / dir[0]);
else if (dir[0] < 0.0 && dir[1] < 0.0) // third quadrant
phi = itk::Math::pi + atan(dir[1] / dir[0]);
else // fourth quadrant
phi = 2.0 * itk::Math::pi + atan(dir[1] / dir[0]);
}
}
};
}
#endif
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/FittingFunctions/mitkBallStickFitter.h b/Modules/DiffusionCore/Algorithms/Reconstruction/FittingFunctions/mitkBallStickFitter.h
index 8c5efa4..21d42ad 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/FittingFunctions/mitkBallStickFitter.h
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/FittingFunctions/mitkBallStickFitter.h
@@ -1,72 +1,72 @@
#include <mitkAbstractFitter.h>
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_BallStickFitter_H
#define _MITK_BallStickFitter_H
#include <mitkAbstractFitter.h>
namespace mitk {
struct BallStickFitter: public AbstractFitter
{
public :
BallStickFitter(unsigned int number_of_parameters, unsigned int number_of_measurements) :
AbstractFitter(number_of_parameters, number_of_measurements)
{
}
double penalty(const vnl_vector<double>& x)
{
double p = 0;
if (x[0]<0 || x[0]>1)
p += 10e6;
if (x[1]<0)
p += 10e6;
return p;
}
void f(const vnl_vector<double>& x, vnl_vector<double>& fx) override
{
const double & f = x[0];
const double & d = x[1];
const double & theta = x[2];
const double & phi = x[3];
vnl_vector_fixed<double,3> dir;
Sph2Cart(dir, theta, phi);
for(auto s : weightedIndices)
{
double s_iso = S0 * std::exp(-bValues[s] * d);
GradientDirectionType g = gradientDirections->GetElement(s);
g.normalize();
double dot = dot_product(g, dir);
double s_aniso = S0 * std::exp(-bValues[s] * d * dot*dot );
double approx = (1-f)*s_iso + f*s_aniso;
const double factor = measurements[s] - approx;
fx[s] = factor*factor + penalty(x);
}
}
};
}
#endif
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/FittingFunctions/mitkMultiTensorFitter.h b/Modules/DiffusionCore/Algorithms/Reconstruction/FittingFunctions/mitkMultiTensorFitter.h
index 348491a..472cb8c 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/FittingFunctions/mitkMultiTensorFitter.h
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/FittingFunctions/mitkMultiTensorFitter.h
@@ -1,117 +1,117 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_MultiTensorFitter_H
#define _MITK_MultiTensorFitter_H
#include <mitkAbstractFitter.h>
namespace mitk {
class MultiTensorFitter: public AbstractFitter
{
public:
MultiTensorFitter(unsigned int number_of_tensors=2, unsigned int number_of_measurements=1) :
AbstractFitter(check(number_of_tensors), number_of_measurements)
{
num_tensors = number_of_tensors;
}
int num_tensors;
int check(int n)
{
if (n==1)
return 6;
return n*7;
}
vnl_vector_fixed<double,3> GetLargestEv(TensorType& tensor)
{
TensorType::EigenValuesArrayType eigenvalues;
TensorType::EigenVectorsMatrixType eigenvectors;
tensor.ComputeEigenAnalysis(eigenvalues, eigenvectors);
vnl_vector_fixed<double,3> ev;
ev[0] = eigenvectors(2, 0);
ev[1] = eigenvectors(2, 1);
ev[2] = eigenvectors(2, 2);
if (ev.magnitude()>mitk::eps)
ev.normalize();
else
ev.fill(0.0);
return ev;
}
double penalty(const vnl_vector<double>& x)
{
double p = 0;
if (num_tensors>1)
{
double f = 0;
for (int i=0; i<num_tensors; i++)
{
if (x[6+i*7]<0)
p += 10e6;
f += x[6+i*7];
}
p += 10e7*fabs(1-f);
}
return p;
}
void f(const vnl_vector<double>& x, vnl_vector<double>& fx) override
{
int elements = 7;
for(auto s : weightedIndices)
{
GradientDirectionType g = gradientDirections->GetElement(s);
g.normalize();
itk::DiffusionTensor3D< double > S;
S[0] = g[0]*g[0];
S[1] = g[1]*g[0];
S[2] = g[2]*g[0];
S[3] = g[1]*g[1];
S[4] = g[2]*g[1];
S[5] = g[2]*g[2];
double approx = 0;
for (int i=0; i<num_tensors; i++)
{
double D = x[0+i*elements]*S[0] + x[1+i*elements]*S[1] + x[2+i*elements]*S[2] +
x[1+i*elements]*S[1] + x[3+i*elements]*S[3] + x[4+i*elements]*S[4] +
x[2+i*elements]*S[2] + x[4+i*elements]*S[4] + x[5+i*elements]*S[5];
double signal = S0 * std::exp ( -bValues[s] * D );
if (num_tensors>1 && x.size()>6)
signal *= x[elements-1+i*elements];
approx += signal;
}
const double factor = measurements[s] - approx;
fx[s] = factor*factor + penalty(x);
}
}
};
}
#endif
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkADCAverageFunctor.cpp b/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkADCAverageFunctor.cpp
index fe78b9e..0716ce3 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkADCAverageFunctor.cpp
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkADCAverageFunctor.cpp
@@ -1,56 +1,56 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "itkADCAverageFunctor.h"
#include <cmath>
#include <iostream>
#include <iomanip>
void itk::ADCAverageFunctor::operator()(vnl_matrix<double> & newSignal, const vnl_matrix<double> & SignalMatrix, const double & S0)
{
vnl_matrix<double> ADCMatrix(SignalMatrix.rows(),SignalMatrix.cols());
// Calculate ADC for each measurement
for(unsigned int i = 0 ; i < SignalMatrix.rows(); ++i)
for(unsigned int j = 0; j < SignalMatrix.cols(); ++j)
ADCMatrix(i,j) = std::log(SignalMatrix(i,j) / S0) / (-m_BValueList[j]);// D = ln(S/S0)/-b
// Calculate new Signal using Average ADC
for(unsigned int i = 0 ; i < SignalMatrix.rows(); ++i){
double averageADC = ADCMatrix.get_row(i).mean();
newSignal.put(i,0, S0 * std::exp(-m_TargetBvalue * averageADC) ); // S = S0*exp(-b*D)
//OUTPUT FOR EVALUATION
// Root Mean Squares Error
double error = 0;
for(unsigned int j = 0 ; j < SignalMatrix.cols(); ++j)
error += std::pow(SignalMatrix(i,j) - S0 * std::exp(-m_BValueList[j] * averageADC),2); // sum of squres
error /= (double)SignalMatrix.cols(); // mean
error = std::sqrt(error);
newSignal.put(i, 1, error ); // RMS Error
/*std::cout << std::scientific << std::setprecision(5)
<< averageADC << "," // AverageADC
<< S0 << "," // S0 value
<< error << ","; // End error
for(unsigned int j = 0; j < SignalMatrix.get_row(i).size(); j++ )
std::cout << std::scientific << std::setprecision(5) << SignalMatrix.get_row(i)[j] << ","; // S_n Values corresponding to shell 1 to shell n
std::cout << std::endl;*/
}
}
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkADCAverageFunctor.h b/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkADCAverageFunctor.h
index 7524929..421eae4 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkADCAverageFunctor.h
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkADCAverageFunctor.h
@@ -1,56 +1,56 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _itk_ADCAverageFunctor_h_
#define _itk_ADCAverageFunctor_h_
#include "itkDWIVoxelFunctor.h"
#include <cmath>
namespace itk
{
class MITKDIFFUSIONCORE_EXPORT ADCAverageFunctor : public DWIVoxelFunctor
{
public:
ADCAverageFunctor(){}
~ADCAverageFunctor() override{}
typedef ADCAverageFunctor Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef DWIVoxelFunctor Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(ADCAverageFunctor, DWIVoxelFunctor)
void operator()(vnl_matrix<double> & newSignal, const vnl_matrix<double> & SignalMatrix, const double & S0) override;
void setTargetBValue(const double & targetBValue){m_TargetBvalue = targetBValue;}
void setListOfBValues(const vnl_vector<double> & BValueList){m_BValueList = BValueList;}
protected:
double m_TargetBvalue;
vnl_vector<double> m_BValueList;
};
}
#endif
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkADCFitFunctor.cpp b/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkADCFitFunctor.cpp
index 42d399f..a44cf15 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkADCFitFunctor.cpp
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkADCFitFunctor.cpp
@@ -1,64 +1,64 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "itkADCFitFunctor.h"
#include <cmath>
#include <iostream>
#include <iomanip>
#include "vnl/algo/vnl_levenberg_marquardt.h"
void itk::ADCFitFunctor::operator()(vnl_matrix<double> & newSignal,const vnl_matrix<double> & SignalMatrix, const double & S0)
{
vnl_vector<double> initalGuess(1);
// initialize Least Squres Function
// SignalMatrix.cols() defines the number of shells points
lestSquaresFunction model(SignalMatrix.cols());
model.set_bvalues(m_BValueList);// set BValue Vector e.g.: [1000, 2000, 3000] <- shell b Values
// initialize Levenberg Marquardt
vnl_levenberg_marquardt minimizer(model);
minimizer.set_max_function_evals(1000); // Iterations
minimizer.set_f_tolerance(1e-10); // Function tolerance
// for each Direction calculate LSF Coeffs ADC & AKC
for(unsigned int i = 0 ; i < SignalMatrix.rows(); i++)
{
model.set_measurements(SignalMatrix.get_row(i));
model.set_reference_measurement(S0);
initalGuess.put(0, 0.f); // ADC_slow
// start Levenberg-Marquardt
minimizer.minimize_without_gradient(initalGuess);
const double & ADC = initalGuess.get(0);
newSignal.put(i, 0, S0 * std::exp(-m_TargetBvalue * ADC) );
newSignal.put(i, 1, minimizer.get_end_error()); // RMS Error
//OUTPUT FOR EVALUATION
std::cout << std::scientific << std::setprecision(5)
<< ADC << "," // lambda
<< S0 << "," // S0 value
<< minimizer.get_end_error() << ","; // End error
for(unsigned int j = 0; j < SignalMatrix.get_row(i).size(); j++ ){
std::cout << std::scientific << std::setprecision(5) << SignalMatrix.get_row(i)[j]; // S_n Values corresponding to shell 1 to shell n
if(j != SignalMatrix.get_row(i).size()-1) std::cout << ",";
}
std::cout << std::endl;
}
}
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkADCFitFunctor.h b/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkADCFitFunctor.h
index 23dbb0f..46dddbe 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkADCFitFunctor.h
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkADCFitFunctor.h
@@ -1,102 +1,102 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _itk_ADCFitFunctor_h_
#define _itk_ADCFitFunctor_h_
#include "itkDWIVoxelFunctor.h"
#include "vnl/vnl_least_squares_function.h"
#include "vnl/vnl_math.h"
namespace itk
{
class MITKDIFFUSIONCORE_EXPORT ADCFitFunctor : public DWIVoxelFunctor
{
public:
ADCFitFunctor(){}
~ADCFitFunctor() override{}
typedef ADCFitFunctor Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef DWIVoxelFunctor Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(ADCFitFunctor, DWIVoxelFunctor)
void operator()(vnl_matrix<double> & newSignal, const vnl_matrix<double> & SignalMatrix, const double & S0) override;
void setTargetBValue(const double & targetBValue){m_TargetBvalue = targetBValue;}
void setListOfBValues(const vnl_vector<double> & BValueList){m_BValueList = BValueList;}
protected:
double m_TargetBvalue;
vnl_vector<double> m_BValueList;
/**
* \brief The lestSquaresFunction struct for Non-Linear-Least-Squres fit of monoexponential model
*/
struct lestSquaresFunction: public vnl_least_squares_function
{
void set_measurements(const vnl_vector<double>& x)
{
measurements.set_size(x.size());
measurements.copy_in(x.data_block());
}
void set_bvalues(const vnl_vector<double>& x)
{
bValueVector.set_size(x.size());
bValueVector.copy_in(x.data_block());
}
void set_reference_measurement(const double & x)
{
S0 = x;
}
vnl_vector<double> measurements;
vnl_vector<double> bValueVector;
double S0;
int N;
lestSquaresFunction(unsigned int number_of_measurements) :
vnl_least_squares_function(1 /*number of unknowns [ ADC ]*/, number_of_measurements, no_gradient)
{
N = get_number_of_residuals();
}
void f(const vnl_vector<double>& x, vnl_vector<double>& fx) override {
const double & ADC = x[0];
const vnl_vector<double> & b = bValueVector;
for(int s=0; s<N; s++)
{
double approx = S0 * std::exp(-b[s] * ADC);
fx[s] = vnl_math_abs( measurements[s] - approx );
}
}
};
};
}
#endif
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkBiExpFitFunctor.cpp b/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkBiExpFitFunctor.cpp
index f5326cb..9526d22 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkBiExpFitFunctor.cpp
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkBiExpFitFunctor.cpp
@@ -1,70 +1,70 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "itkBiExpFitFunctor.h"
#include <cmath>
#include <iostream>
#include <iomanip>
void itk::BiExpFitFunctor::operator()(vnl_matrix<double> & newSignal,const vnl_matrix<double> & SignalMatrix, const double & S0)
{
vnl_vector<double> initalGuess(3);
// initialize Least Squres Function
// SignalMatrix.cols() defines the number of shells points
lestSquaresFunction model(SignalMatrix.cols());
model.set_bvalues(m_BValueList);// set BValue Vector e.g.: [1000, 2000, 3000] <- shell b Values
// initialize Levenberg Marquardt
vnl_levenberg_marquardt minimizer(model);
minimizer.set_max_function_evals(1000); // Iterations
minimizer.set_f_tolerance(1e-10); // Function tolerance
// for each Direction calculate LSF Coeffs ADC & AKC
for(unsigned int i = 0 ; i < SignalMatrix.rows(); i++)
{
model.set_measurements(SignalMatrix.get_row(i));
model.set_reference_measurement(S0);
initalGuess.put(0, 0.f); // ADC_slow
initalGuess.put(1, 0.009f); // ADC_fast
initalGuess.put(2, 0.7f); // lambda
// start Levenberg-Marquardt
minimizer.minimize_without_gradient(initalGuess);
const double & ADC_slow = initalGuess.get(0);
const double & ADC_fast = initalGuess.get(1);
const double & lambda = initalGuess(2);
newSignal.put(i, 0, S0 * (lambda * std::exp(-m_TargetBvalue * ADC_slow) + (1-lambda)* std::exp(-m_TargetBvalue * ADC_fast)));
newSignal.put(i, 1, minimizer.get_end_error()); // RMS Error
//OUTPUT FOR EVALUATION
/*std::cout << std::scientific << std::setprecision(5)
<< ADC_slow << "," // lambda
<< ADC_fast << "," // alpha
<< lambda << "," // lambda
<< S0 << "," // S0 value
<< minimizer.get_end_error() << ","; // End error
for(unsigned int j = 0; j < SignalMatrix.get_row(i).size(); j++ ){
std::cout << std::scientific << std::setprecision(5) << SignalMatrix.get_row(i)[j]; // S_n Values corresponding to shell 1 to shell n
if(j != SignalMatrix.get_row(i).size()-1) std::cout << ",";
}
std::cout << std::endl;*/
}
}
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkBiExpFitFunctor.h b/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkBiExpFitFunctor.h
index 8a80ea6..f9bd68a 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkBiExpFitFunctor.h
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkBiExpFitFunctor.h
@@ -1,111 +1,111 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _itk_BiExpFitFunctor_h_
#define _itk_BiExpFitFunctor_h_
#include "itkDWIVoxelFunctor.h"
#include <cmath>
// vnl include
#include "vnl/vnl_least_squares_function.h"
#include "vnl/algo/vnl_levenberg_marquardt.h"
#include "vnl/vnl_math.h"
namespace itk
{
class MITKDIFFUSIONCORE_EXPORT BiExpFitFunctor : public DWIVoxelFunctor
{
public:
BiExpFitFunctor(){}
~BiExpFitFunctor() override{}
typedef BiExpFitFunctor Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef DWIVoxelFunctor Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(BiExpFitFunctor, DWIVoxelFunctor)
void operator()(vnl_matrix<double> & newSignal,const vnl_matrix<double> & SignalMatrix, const double & S0) override;
void setTargetBValue(const double & targetBValue){m_TargetBvalue = targetBValue;}
void setListOfBValues(const vnl_vector<double> & BValueList){m_BValueList = BValueList;}
protected:
double m_TargetBvalue;
vnl_vector<double> m_BValueList;
/**
* \brief The lestSquaresFunction struct for Non-Linear-Least-Squres fit of Biexponential model
*/
struct lestSquaresFunction: public vnl_least_squares_function
{
void set_measurements(const vnl_vector<double>& x)
{
measurements.set_size(x.size());
measurements.copy_in(x.data_block());
}
void set_bvalues(const vnl_vector<double>& x)
{
bValueVector.set_size(x.size());
bValueVector.copy_in(x.data_block());
}
void set_reference_measurement(const double & x)
{
S0 = x;
}
vnl_vector<double> measurements;
vnl_vector<double> bValueVector;
double S0;
int N;
lestSquaresFunction(unsigned int number_of_measurements) :
vnl_least_squares_function(3 /*number of unknowns [ ADC_slow ADC_fast lambda]*/, number_of_measurements, no_gradient)
{
N = get_number_of_residuals();
}
void f(const vnl_vector<double>& x, vnl_vector<double>& fx) override {
const double & ADC_slow = x[0];
const double & ADC_fast = x[1];
const double & lambda = x[2];
const vnl_vector<double> & b = bValueVector;
for(int s=0; s<N; s++)
{
double approx = lambda * std::exp(-b[s] * ADC_slow) + (1-lambda) * std::exp(-b[s] * ADC_fast);
fx[s] = vnl_math_abs( measurements[s] - approx*S0 );
}
}
};
};
}
#endif
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkDWIVoxelFunctor.h b/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkDWIVoxelFunctor.h
index ee8a124..958f9dc 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkDWIVoxelFunctor.h
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkDWIVoxelFunctor.h
@@ -1,64 +1,64 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _itk_DWIVoxelFunctor_h_
#define _itk_DWIVoxelFunctor_h_
#include <MitkDiffusionCoreExports.h>
#include "vnl/vnl_vector.h"
#include "vnl/vnl_matrix.h"
#include <itkObject.h>
#include <itkObjectFactory.h>
namespace itk
{
/**
* \brief The DWIVoxelFunctor class
* Abstract basisclass for voxelprocessing of Diffusion Weighted Images
*/
class MITKDIFFUSIONCORE_EXPORT DWIVoxelFunctor: public Object
{
protected:
DWIVoxelFunctor(){}
~DWIVoxelFunctor() override{}
public:
typedef DWIVoxelFunctor Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef itk::Object Superclass;
/** Runtime information support. */
itkTypeMacro(DWIVoxelFunctor, Object)
/** Method for creation through the object factory. */
//itkFactorylessNewMacro(Self)
//itkCloneMacro(Self)
/**
* \brief operator ()
* \param SignalMatrix is a NxM matrix (N = Number of gradients; M = Number of Shells)
* \param S0 is the reference signal (b=0)
* \return NxP Signal vector containing the new signal (e.g. [S_1 S_2 S_3 ... S_N] -> only diffusion weighted signal).
*The first column of the matrix is reserved for the new calculated signal (other columns can hold e.g. the RMS-error)
*/
virtual void operator()(vnl_matrix<double> & /*newSignal*/,const vnl_matrix<double> & /*SignalMatrix*/, const double & /*S0*/)=0;
};
}
#endif
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkKurtosisFitFunctor.cpp b/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkKurtosisFitFunctor.cpp
index 4e252bf..b63727c 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkKurtosisFitFunctor.cpp
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkKurtosisFitFunctor.cpp
@@ -1,66 +1,66 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "itkKurtosisFitFunctor.h"
#include <iostream>
#include <iomanip>
void itk::KurtosisFitFunctor::operator()(vnl_matrix<double> & newSignal, const vnl_matrix<double> & SignalMatrix, const double & S0)
{
vnl_vector<double> initalGuess(2);
// initialize Least Squres Function
// SignalMatrix.cols() defines the number of shells points
lestSquaresFunction model(SignalMatrix.cols());
model.set_bvalues(m_BValueList);// set BValue Vector e.g.: [1000, 2000, 3000] <- shell b Values
// initialize Levenberg Marquardt
vnl_levenberg_marquardt minimizer(model);
minimizer.set_max_function_evals(1000); // Iterations
minimizer.set_f_tolerance(1e-10); // Function tolerance
// for each Direction calculate LSF Coeffs ADC & AKC
for(unsigned int i = 0 ; i < SignalMatrix.rows(); i++)
{
model.set_measurements(SignalMatrix.get_row(i));
model.set_reference_measurement(S0);
initalGuess.put(0, 0.f); // ADC
initalGuess.put(1, 0.8f); // AKC
// start Levenberg-Marquardt
minimizer.minimize_without_gradient(initalGuess);
const double & ADC = initalGuess.get(0);
const double & AKC = initalGuess.get(1);
newSignal.put(i, 0, S0 * std::exp(-m_TargetBvalue * ADC + 1./6. * m_TargetBvalue* m_TargetBvalue * ADC * ADC * AKC));
newSignal.put(i, 1, minimizer.get_end_error()); // RMS Error
//OUTPUT FOR EVALUATION
/*std::cout << std::scientific << std::setprecision(5)
<< initalGuess[0] << "," // fitted ADC
<< initalGuess[1] << "," // fitted AKC
<< S0 << "," // S0 value
<< minimizer.get_end_error() << ","; // End error
for(unsigned int j = 0; j < SignalMatrix.get_row(i).size(); j++ ){
std::cout << std::scientific << std::setprecision(5) << SignalMatrix.get_row(i)[j]; // S_n Values corresponding to shell 1 to shell n
if(j != SignalMatrix.get_row(i).size()-1) std::cout << ",";
}
std::cout << std::endl;*/
}
}
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkKurtosisFitFunctor.h b/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkKurtosisFitFunctor.h
index 9a520f6..3364bba 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkKurtosisFitFunctor.h
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkKurtosisFitFunctor.h
@@ -1,109 +1,109 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _itk_KurtosisFitFunctor_h_
#define _itk_KurtosisFitFunctor_h_
#include "itkDWIVoxelFunctor.h"
#include <cmath>
// vnl include
#include "vnl/vnl_least_squares_function.h"
#include "vnl/algo/vnl_levenberg_marquardt.h"
#include "vnl/vnl_math.h"
namespace itk
{
class MITKDIFFUSIONCORE_EXPORT KurtosisFitFunctor : public DWIVoxelFunctor
{
public:
KurtosisFitFunctor(){}
~KurtosisFitFunctor() override{}
typedef KurtosisFitFunctor Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef DWIVoxelFunctor Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(KurtosisFitFunctor, DWIVoxelFunctor)
void operator()(vnl_matrix<double> & newSignal,const vnl_matrix<double> & SignalMatrix, const double & S0) override;
void setTargetBValue(const double & targetBValue){m_TargetBvalue = targetBValue;}
void setListOfBValues(const vnl_vector<double> & BValueList){m_BValueList = BValueList;}
protected:
double m_TargetBvalue;
vnl_vector<double> m_BValueList;
/**
* \brief The lestSquaresFunction struct for Non-Linear-Least-Squres fit of Kurtosis
*/
struct lestSquaresFunction: public vnl_least_squares_function
{
void set_measurements(const vnl_vector<double>& x)
{
measurements.set_size(x.size());
measurements.copy_in(x.data_block());
}
void set_bvalues(const vnl_vector<double>& x)
{
bValueVector.set_size(x.size());
bValueVector.copy_in(x.data_block());
}
void set_reference_measurement(const double & x)
{
S0 = x;
}
vnl_vector<double> measurements;
vnl_vector<double> bValueVector;
double S0;
int N;
lestSquaresFunction(unsigned int number_of_measurements) :
vnl_least_squares_function(2 /*number of unknowns [ADC AKC]*/, number_of_measurements, no_gradient)
{
N = get_number_of_residuals();
}
void f(const vnl_vector<double>& x, vnl_vector<double>& fx) override {
const double & D = x[0];
const double & K = x[1];
const vnl_vector<double> & b = bValueVector;
for(int s=0; s<N; s++)
{
double approx = S0 * std::exp(- b[s] * D + 1./6. *b[s] * b[s] *D * D * K);
fx[s] = vnl_math_abs( measurements[s] - approx );
}
}
};
};
}
#endif
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkRadialMultishellToSingleshellImageFilter.cpp b/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkRadialMultishellToSingleshellImageFilter.cpp
index 3a8f0c3..03af8e7 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkRadialMultishellToSingleshellImageFilter.cpp
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkRadialMultishellToSingleshellImageFilter.cpp
@@ -1,237 +1,237 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*=========================================================================
Program: Tensor ToolKit - TTK
Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkElectrostaticRepulsionDiffusionGradientReductionFilter.txx $
Language: C++
Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $
Version: $Revision: 68 $
Copyright (c) INRIA 2010. All rights reserved.
See LICENSE.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef _itk_RadialMultishellToSingleshellImageFilter_cpp_
#define _itk_RadialMultishellToSingleshellImageFilter_cpp_
#endif
#define _USE_MATH_DEFINES
#include "itkRadialMultishellToSingleshellImageFilter.h"
#include "mitkDiffusionFunctionCollection.h"
namespace itk
{
template <class TInputScalarType, class TOutputScalarType>
RadialMultishellToSingleshellImageFilter<TInputScalarType, TOutputScalarType>
::RadialMultishellToSingleshellImageFilter()
{
this->SetNumberOfRequiredInputs( 1 );
//this->SetNumberOfThreads(1);
}
template <class TInputScalarType, class TOutputScalarType>
void RadialMultishellToSingleshellImageFilter<TInputScalarType, TOutputScalarType>
::BeforeThreadedGenerateData()
{
// test whether BvalueMap contains all necessary information
if(m_BValueMap.size() == 0)
{
itkWarningMacro(<< "No BValueMap given: create one using GradientDirectionContainer");
GradientDirectionContainerType::ConstIterator gdcit;
for( gdcit = m_OriginalGradientDirections->Begin(); gdcit != m_OriginalGradientDirections->End(); ++gdcit)
{
double bValueKey = int(((m_OriginalBValue * gdcit.Value().two_norm() * gdcit.Value().two_norm())+7.5)/10)*10;
m_BValueMap[bValueKey].push_back(gdcit.Index());
}
}
//# BValueMap contains no bZero --> itkException
if(m_BValueMap.find(0.0) == m_BValueMap.end())
{
MITK_INFO << "No ReferenceSignal (BZeroImages) found!";
itkExceptionMacro(<< "No ReferenceSignal (BZeroImages) found!");
}
// [allDirectionsContainer] Gradient DirectionContainer containing all unique directions
m_TargetDirectionsIndicies = mitk::gradients::GetAllUniqueDirections(m_BValueMap, m_OriginalGradientDirections);
// [sizeAllDirections] size of GradientContainer cointaining all unique directions
m_NumberTargetDirections = m_TargetDirectionsIndicies.size();
m_TargetGradientDirections = mitk::gradients::CreateNormalizedUniqueGradientDirectionContainer(m_BValueMap,m_OriginalGradientDirections);
m_ShellInterpolationMatrixVector.reserve(m_BValueMap.size()-1);
// for each shell
BValueMap::const_iterator it = m_BValueMap.begin();
it++; //skip bZeroIndices
unsigned int shellIndex = 0;
for(;it != m_BValueMap.end();++it)
{
//- calculate maxShOrder
const IndicesVector currentShell = it->second;
unsigned int SHMaxOrder = 12;
while( ((SHMaxOrder+1)*(SHMaxOrder+2)/2) > currentShell.size() && ((SHMaxOrder+1)*(SHMaxOrder+2)/2) >= 4 )
SHMaxOrder -= 2 ;
//- get TragetSHBasis using allDirectionsContainer
vnl_matrix<double> sphericalCoordinates;
sphericalCoordinates = mitk::gradients::ComputeSphericalFromCartesian(m_TargetDirectionsIndicies, m_OriginalGradientDirections);
vnl_matrix<double> TargetSHBasis = mitk::gradients::ComputeSphericalHarmonicsBasis(sphericalCoordinates, SHMaxOrder);
//- get ShellSHBasis using currentShellDirections
sphericalCoordinates = mitk::gradients::ComputeSphericalFromCartesian(currentShell, m_OriginalGradientDirections);
vnl_matrix<double> ShellSHBasis = mitk::gradients::ComputeSphericalHarmonicsBasis(sphericalCoordinates, SHMaxOrder);
//- calculate interpolationSHBasis [TargetSHBasis * ShellSHBasis^-1]
vnl_matrix_inverse<double> invShellSHBasis(ShellSHBasis);
vnl_matrix<double> shellInterpolationMatrix = TargetSHBasis * invShellSHBasis.pinverse();
//- save interpolationSHBasis
m_ShellInterpolationMatrixVector.push_back(shellInterpolationMatrix);
++shellIndex;
}
// initialize output image
typename OutputImageType::Pointer outImage = static_cast<OutputImageType * >(ProcessObject::GetOutput(0));
outImage->SetSpacing( this->GetInput()->GetSpacing() );
outImage->SetOrigin( this->GetInput()->GetOrigin() );
outImage->SetDirection( this->GetInput()->GetDirection() ); // Set the image direction using bZeroDirection+AllDirectionsContainer
outImage->SetLargestPossibleRegion( this->GetInput()->GetLargestPossibleRegion());
outImage->SetBufferedRegion( this->GetInput()->GetLargestPossibleRegion() );
outImage->SetRequestedRegion( this->GetInput()->GetLargestPossibleRegion() );
outImage->SetVectorLength( 1+m_NumberTargetDirections ); // size of 1(bzeroValue) + AllDirectionsContainer
outImage->Allocate();
m_ErrorImage = ErrorImageType::New();
m_ErrorImage->SetSpacing( this->GetInput()->GetSpacing() );
m_ErrorImage->SetOrigin( this->GetInput()->GetOrigin() );
m_ErrorImage->SetDirection( this->GetInput()->GetDirection() ); // Set the image direction using bZeroDirection+AllDirectionsContainer
m_ErrorImage->SetLargestPossibleRegion( this->GetInput()->GetLargestPossibleRegion());
m_ErrorImage->SetBufferedRegion( this->GetInput()->GetLargestPossibleRegion() );
m_ErrorImage->SetRequestedRegion( this->GetInput()->GetLargestPossibleRegion() );
m_ErrorImage->Allocate();
MITK_INFO << "Input:" << std::endl << std::endl
<< " GradientDirections: " << m_OriginalGradientDirections->Size() << std::endl
<< " Shells: " << (m_BValueMap.size() - 1) << std::endl
<< " ReferenceImages: " << m_BValueMap[0.0].size() << std::endl;
MITK_INFO << "Output:" << std::endl << std::endl
<< " OutImageVectorLength: " << outImage->GetVectorLength() << std::endl
<< " TargetDirections: " << m_NumberTargetDirections << std::endl
<< std::endl;
}
template <class TInputScalarType, class TOutputScalarType>
void
RadialMultishellToSingleshellImageFilter<TInputScalarType, TOutputScalarType>
::ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, ThreadIdType /*threadId*/)
{
// Get input gradient image pointer
typename InputImageType::Pointer inputImage = static_cast< InputImageType * >(ProcessObject::GetInput(0));
// ImageRegionIterator for the input image
ImageRegionIterator< InputImageType > iit(inputImage, outputRegionForThread);
iit.GoToBegin();
// Get output gradient image pointer
typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(ProcessObject::GetOutput(0));
// ImageRegionIterator for the output image
ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread);
oit.GoToBegin();
// ImageRegionIterator for the output image
ImageRegionIterator< ErrorImageType > eit(m_ErrorImage, outputRegionForThread);
eit.GoToBegin();
// calculate target bZero-Value [b0_t]
const IndicesVector IndicesS0 = m_BValueMap[0.0];
double AverageS0 = 0.0;
unsigned int numberOfShells = m_BValueMap.size()-1;
// create empty nxm SignalMatrix containing n->signals/directions (in case of interpolation ~ sizeAllDirections otherwise the size of any shell) for m->shells
vnl_matrix<double> SignalMatrix(m_NumberTargetDirections, numberOfShells);
// create nx1 targetSignalVector
vnl_vector<double> SignalVector(m_NumberTargetDirections);
OutputPixelType out;
InputPixelType b;
BValueMap::const_iterator shellIterator;
vnl_matrix<double> NewSignalMatrix (m_NumberTargetDirections, 2);
vnl_vector<double> InterpVector;
unsigned int shellIndex = 0;
// ** walking over each Voxel
while(!iit.IsAtEnd())
{
b = iit.Get();
AverageS0=0.0;
for(unsigned int i = 0 ; i < IndicesS0.size(); i++){
AverageS0 += b[IndicesS0[i]];
}
AverageS0 /= (double)IndicesS0.size();
out = oit.Get();
out.SetElement(0,AverageS0);
shellIterator = m_BValueMap.begin();
shellIterator++; //skip bZeroImages
shellIndex = 0;
// for each shell
while(shellIterator != m_BValueMap.end())
{
const IndicesVector & currentShell = shellIterator->second;
InterpVector.set_size(currentShell.size());
// get the raw signal for currente shell (signal for eacht direction)
for(unsigned int i = 0 ; i < currentShell.size(); i++)
InterpVector.put(i,b[currentShell[i]]);
// interpolate the signal using corresponding interpolationSHBasis
SignalVector = m_ShellInterpolationMatrixVector.at(shellIndex) * InterpVector;
// save interpolated signal column
SignalMatrix.set_column(shellIndex, SignalVector);
shellIterator++;
shellIndex++;
}
// apply voxel wise signal manipulation functor
(*m_Functor)(NewSignalMatrix, /*const &*/SignalMatrix,/*const &*/ AverageS0);
SignalVector = NewSignalMatrix.get_column(0);
for(unsigned int i = 1 ; i < out.Size(); i ++)
out.SetElement(i,SignalVector.get(i-1));
eit.Set(NewSignalMatrix.get_column(1).mean());
oit.Set(out);
++eit;
++oit;
++iit;
}
}
} // end of namespace
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkRadialMultishellToSingleshellImageFilter.h b/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkRadialMultishellToSingleshellImageFilter.h
index 8c85ccd..42ed9ed 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkRadialMultishellToSingleshellImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/MultishellProcessing/itkRadialMultishellToSingleshellImageFilter.h
@@ -1,111 +1,111 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _itk_RadialMultishellToSingleshellImageFilterr_h_
#define _itk_RadialMultishellToSingleshellImageFilterr_h_
#include <itkImageToImageFilter.h>
#include <itkVectorImage.h>
#include "itkDWIVoxelFunctor.h"
namespace itk
{
template <class TInputScalarType, class TOutputScalarType>
class RadialMultishellToSingleshellImageFilter
: public ImageToImageFilter<itk::VectorImage<TInputScalarType,3>, itk::VectorImage<TOutputScalarType,3> >
{
public:
typedef RadialMultishellToSingleshellImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< itk::VectorImage<TInputScalarType,3>, itk::VectorImage<TOutputScalarType,3> > Superclass;
typedef typename Superclass::OutputImageRegionType OutputImageRegionType;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(RadialMultishellToSingleshellImageFilter, ImageToImageFilter)
typedef TInputScalarType InputScalarType;
typedef itk::VectorImage<InputScalarType,3> InputImageType;
typedef typename InputImageType::PixelType InputPixelType;
typedef TOutputScalarType OutputScalarType;
typedef itk::VectorImage<OutputScalarType,3> OutputImageType;
typedef typename OutputImageType::PixelType OutputPixelType;
typedef OutputScalarType BaselineScalarType;
typedef BaselineScalarType BaselinePixelType;
typedef typename itk::Image<BaselinePixelType,3> BaselineImageType;
typedef float ErrorScalarType;
typedef ErrorScalarType ErrorPixelType;
typedef typename itk::Image<ErrorPixelType,3> ErrorImageType;
typedef vnl_vector_fixed< double, 3 > GradientDirectionType;
typedef itk::VectorContainer< unsigned int, GradientDirectionType > GradientDirectionContainerType;
typedef std::vector<unsigned int> IndicesVector;
typedef std::map<unsigned int, IndicesVector> BValueMap;
void SetOriginalGradientDirections(GradientDirectionContainerType::Pointer ptr){m_OriginalGradientDirections = ptr;}
void SetOriginalBValue(const double & val){m_OriginalBValue = val;}
void SetOriginalBValueMap(const BValueMap & inp){m_BValueMap = inp;}
void SetFunctor(DWIVoxelFunctor * functor){m_Functor = functor;}
GradientDirectionContainerType::Pointer GetTargetGradientDirections(){return m_TargetGradientDirections;}
ErrorImageType::Pointer GetErrorImage(){return m_ErrorImage;}
protected:
RadialMultishellToSingleshellImageFilter();
~RadialMultishellToSingleshellImageFilter() {}
void BeforeThreadedGenerateData();
void ThreadedGenerateData( const OutputImageRegionType &, ThreadIdType);
GradientDirectionContainerType::Pointer m_TargetGradientDirections; ///< container for the subsampled output gradient directions
GradientDirectionContainerType::Pointer m_OriginalGradientDirections; ///< input gradient directions
BValueMap m_BValueMap;
double m_OriginalBValue;
std::vector<vnl_matrix< double > > m_ShellInterpolationMatrixVector;
IndicesVector m_TargetDirectionsIndicies;
unsigned int m_NumberTargetDirections;
DWIVoxelFunctor * m_Functor;
ErrorImageType::Pointer m_ErrorImage;
};
} // end of namespace
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkRadialMultishellToSingleshellImageFilter.cpp"
#endif
#endif
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/itkAnalyticalDiffusionQballReconstructionImageFilter.cpp b/Modules/DiffusionCore/Algorithms/Reconstruction/itkAnalyticalDiffusionQballReconstructionImageFilter.cpp
index 08b8306..ee3055e 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/itkAnalyticalDiffusionQballReconstructionImageFilter.cpp
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/itkAnalyticalDiffusionQballReconstructionImageFilter.cpp
@@ -1,655 +1,655 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkAnalyticalDiffusionQballReconstructionImageFilter_cpp
#define __itkAnalyticalDiffusionQballReconstructionImageFilter_cpp
#include <itkAnalyticalDiffusionQballReconstructionImageFilter.h>
#include <itkImageRegionConstIterator.h>
#include <itkImageRegionConstIteratorWithIndex.h>
#include <itkImageRegionIterator.h>
#include <itkArray.h>
#include <vnl/vnl_vector.h>
#include <mitkDiffusionFunctionCollection.h>
#include <cstdio>
#include <locale>
#include <fstream>
#include "itkPointShell.h"
namespace itk {
template< class T, class TG, class TO, int ShOrder, int NrOdfDirections>
AnalyticalDiffusionQballReconstructionImageFilter<T,TG,TO,ShOrder,NrOdfDirections>::AnalyticalDiffusionQballReconstructionImageFilter() :
m_GradientDirectionContainer(nullptr),
m_NumberOfGradientDirections(0),
m_NumberOfBaselineImages(1),
m_Threshold(NumericTraits< ReferencePixelType >::NonpositiveMin()),
m_BValue(-1),
m_Lambda(0.0),
m_DirectionsDuplicated(false),
m_Delta1(0.001),
m_Delta2(0.001),
m_UseMrtrixBasis(false)
{
// At least 1 inputs is necessary for a vector image.
// For images added one at a time we need at least six
this->SetNumberOfRequiredInputs( 1 );
}
template<
class TReferenceImagePixelType,
class TGradientImagePixelType,
class TOdfPixelType,
int ShOrder,
int NrOdfDirections>
typename itk::AnalyticalDiffusionQballReconstructionImageFilter< TReferenceImagePixelType,TGradientImagePixelType,TOdfPixelType, ShOrder,NrOdfDirections>::OdfPixelType
itk::AnalyticalDiffusionQballReconstructionImageFilter<TReferenceImagePixelType, TGradientImagePixelType, TOdfPixelType, ShOrder, NrOdfDirections>::Normalize( OdfPixelType odf, typename NumericTraits<ReferencePixelType>::AccumulateType b0 )
{
switch( m_NormalizationMethod )
{
case QBAR_STANDARD:
{
TOdfPixelType sum = 0;
for(int i=0; i<NrOdfDirections; i++)
{
sum += odf[i];
}
if(sum>0)
odf /= sum;
return odf;
break;
}
case QBAR_B_ZERO_B_VALUE:
{
for(int i=0; i<NrOdfDirections; i++)
{
odf[i] = ((TOdfPixelType)log((TOdfPixelType)b0)-odf[i])/m_BValue;
}
return odf;
break;
}
case QBAR_B_ZERO:
{
odf *= 1.0/b0;
return odf;
break;
}
case QBAR_NONE:
{
return odf;
break;
}
case QBAR_ADC_ONLY:
{
for(int i=0; i<NrOdfDirections; i++)
{
odf[i] = ((TOdfPixelType)log((TOdfPixelType)b0)-odf[i])/m_BValue;
}
return odf;
break;
}
case QBAR_RAW_SIGNAL:
{
return odf;
break;
}
case QBAR_SOLID_ANGLE:
{
for(int i=0; i<NrOdfDirections; i++)
odf[i] *= itk::Math::pi*4/NrOdfDirections;
break;
}
case QBAR_NONNEG_SOLID_ANGLE:
{
break;
}
}
return odf;
}
template<
class TReferenceImagePixelType,
class TGradientImagePixelType,
class TOdfPixelType,
int ShOrder,
int NrOdfDirections>
vnl_vector<TOdfPixelType> itk::AnalyticalDiffusionQballReconstructionImageFilter<TReferenceImagePixelType, TGradientImagePixelType, TOdfPixelType, ShOrder, NrOdfDirections>::PreNormalize( vnl_vector<TOdfPixelType> vec, typename NumericTraits<ReferencePixelType>::AccumulateType b0 )
{
switch( m_NormalizationMethod )
{
case QBAR_STANDARD:
{
int n = vec.size();
double b0f = (double)b0;
for(int i=0; i<n; i++)
{
vec[i] = vec[i]/b0f;
}
return vec;
break;
}
case QBAR_B_ZERO_B_VALUE:
{
int n = vec.size();
for(int i=0; i<n; i++)
{
if (vec[i]<=0)
vec[i] = 0.001;
vec[i] = log(vec[i]);
}
return vec;
break;
}
case QBAR_B_ZERO:
{
return vec;
break;
}
case QBAR_NONE:
{
return vec;
break;
}
case QBAR_ADC_ONLY:
{
int n = vec.size();
for(int i=0; i<n; i++)
{
if (vec[i]<=0)
vec[i] = 0.001;
vec[i] = log(vec[i]);
}
return vec;
break;
}
case QBAR_RAW_SIGNAL:
{
return vec;
break;
}
case QBAR_SOLID_ANGLE:
case QBAR_NONNEG_SOLID_ANGLE:
{
int n = vec.size();
double b0f = (double)b0;
for(int i=0; i<n; i++)
{
vec[i] = vec[i]/b0f;
if (vec[i]<0)
vec[i] = m_Delta1;
else if (vec[i]<m_Delta1)
vec[i] = m_Delta1/2 + vec[i]*vec[i]/(2*m_Delta1);
else if (vec[i]>=1)
vec[i] = 1-m_Delta2/2;
else if (vec[i]>=1-m_Delta2)
vec[i] = 1-m_Delta2/2-(1-vec[i])*(1-vec[i])/(2*m_Delta2);
vec[i] = log(-log(vec[i]));
}
return vec;
break;
}
}
return vec;
}
template< class T, class TG, class TO, int ShOrder, int NrOdfDirections>
void AnalyticalDiffusionQballReconstructionImageFilter<T,TG,TO,ShOrder,NrOdfDirections>::BeforeThreadedGenerateData()
{
// If we have more than 2 inputs, then each input, except the first is a
// gradient image. The number of gradient images must match the number of
// gradient directions.
//const unsigned int numberOfInputs = this->GetNumberOfInputs();
// There need to be at least 6 gradient directions to be able to compute the
// tensor basis
if( m_NumberOfGradientDirections < (ShOrder*ShOrder + ShOrder + 2)/2 + ShOrder )
{
itkExceptionMacro( << "Not enough gradient directions supplied (" << m_NumberOfGradientDirections << "). At least " << (ShOrder*ShOrder + ShOrder + 2)/2 + ShOrder << " needed for SH-order " << ShOrder);
}
// Input must be an itk::VectorImage.
std::string gradientImageClassName(
this->ProcessObject::GetInput(0)->GetNameOfClass());
if ( strcmp(gradientImageClassName.c_str(),"VectorImage") != 0 )
{
itkExceptionMacro( << "There is only one Gradient image. I expect that to be a VectorImage. " << "But its of type: " << gradientImageClassName );
}
this->ComputeReconstructionMatrix();
typename GradientImagesType::Pointer img = static_cast< GradientImagesType * >( this->ProcessObject::GetInput(0) );
m_BZeroImage = BZeroImageType::New();
m_BZeroImage->SetSpacing( img->GetSpacing() ); // Set the image spacing
m_BZeroImage->SetOrigin( img->GetOrigin() ); // Set the image origin
m_BZeroImage->SetDirection( img->GetDirection() ); // Set the image direction
m_BZeroImage->SetLargestPossibleRegion( img->GetLargestPossibleRegion());
m_BZeroImage->SetBufferedRegion( img->GetLargestPossibleRegion() );
m_BZeroImage->Allocate();
m_ODFSumImage = BZeroImageType::New();
m_ODFSumImage->SetSpacing( img->GetSpacing() ); // Set the image spacing
m_ODFSumImage->SetOrigin( img->GetOrigin() ); // Set the image origin
m_ODFSumImage->SetDirection( img->GetDirection() ); // Set the image direction
m_ODFSumImage->SetLargestPossibleRegion( img->GetLargestPossibleRegion());
m_ODFSumImage->SetBufferedRegion( img->GetLargestPossibleRegion() );
m_ODFSumImage->Allocate();
m_CoefficientImage = CoefficientImageType::New();
m_CoefficientImage->SetSpacing( img->GetSpacing() ); // Set the image spacing
m_CoefficientImage->SetOrigin( img->GetOrigin() ); // Set the image origin
m_CoefficientImage->SetDirection( img->GetDirection() ); // Set the image direction
m_CoefficientImage->SetLargestPossibleRegion( img->GetLargestPossibleRegion());
m_CoefficientImage->SetBufferedRegion( img->GetLargestPossibleRegion() );
m_CoefficientImage->Allocate();
if(m_NormalizationMethod == QBAR_SOLID_ANGLE || m_NormalizationMethod == QBAR_NONNEG_SOLID_ANGLE)
m_Lambda = 0.0;
}
template< class T, class TG, class TO, int ShOrder, int NrOdfDirections>
void AnalyticalDiffusionQballReconstructionImageFilter<T,TG,TO,ShOrder,NrOdfDirections>
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, ThreadIdType )
{
typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetPrimaryOutput());
ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread);
oit.GoToBegin();
ImageRegionIterator< BZeroImageType > oit2(m_BZeroImage, outputRegionForThread);
oit2.GoToBegin();
ImageRegionIterator< FloatImageType > oit3(m_ODFSumImage, outputRegionForThread);
oit3.GoToBegin();
ImageRegionIterator< CoefficientImageType > oit4(m_CoefficientImage, outputRegionForThread);
oit4.GoToBegin();
typedef ImageRegionConstIterator< GradientImagesType > GradientIteratorType;
typedef typename GradientImagesType::PixelType GradientVectorType;
typename GradientImagesType::Pointer gradientImagePointer = nullptr;
// Would have liked a dynamic_cast here, but seems SGI doesn't like it
// The enum will ensure that an inappropriate cast is not done
gradientImagePointer = static_cast< GradientImagesType * >(
this->ProcessObject::GetInput(0) );
GradientIteratorType git(gradientImagePointer, outputRegionForThread );
git.GoToBegin();
// Compute the indicies of the baseline images and gradient images
std::vector<unsigned int> baselineind; // contains the indicies of
// the baseline images
std::vector<unsigned int> gradientind; // contains the indicies of
// the gradient images
for(GradientDirectionContainerType::ConstIterator gdcit = this->m_GradientDirectionContainer->Begin();
gdcit != this->m_GradientDirectionContainer->End(); ++gdcit)
{
float bval = gdcit.Value().two_norm();
bval = bval*bval*m_BValue;
if(bval < 100)
baselineind.push_back(gdcit.Index());
else
gradientind.push_back(gdcit.Index());
}
if( m_DirectionsDuplicated )
{
int gradIndSize = gradientind.size();
for(int i=0; i<gradIndSize; i++)
gradientind.push_back(gradientind[i]);
}
while( !git.IsAtEnd() )
{
GradientVectorType b = git.Get();
typename NumericTraits<ReferencePixelType>::AccumulateType b0 = NumericTraits<ReferencePixelType>::Zero;
// Average the baseline image pixels
for(unsigned int i = 0; i < baselineind.size(); ++i)
{
b0 += b[baselineind[i]];
}
b0 /= this->m_NumberOfBaselineImages;
OdfPixelType odf(0.0);
typename CoefficientImageType::PixelType coeffPixel(0.0);
vnl_vector<TO> B(m_NumberOfGradientDirections);
if( (b0 != 0) && (b0 >= m_Threshold) )
{
for( unsigned int i = 0; i< m_NumberOfGradientDirections; i++ )
{
B[i] = static_cast<TO>(b[gradientind[i]]);
}
B = PreNormalize(B, b0);
if(m_NormalizationMethod == QBAR_SOLID_ANGLE)
{
vnl_vector<TO> coeffs(m_NumberCoefficients);
coeffs = ( m_CoeffReconstructionMatrix * B );
coeffs[0] += 1.0/(2.0*sqrt(itk::Math::pi));
odf = ( m_SphericalHarmonicBasisMatrix * coeffs ).data_block();
coeffPixel = coeffs.data_block();
}
else if(m_NormalizationMethod == QBAR_NONNEG_SOLID_ANGLE)
{
/** this would be the place to implement a non-negative
* solver for quadratic programming problem:
* min .5*|| Bc-s ||^2 subject to -CLPc <= 4*pi*ones
* (refer to MICCAI 2009 Goh et al. "Estimating ODFs with PDF constraints")
* .5*|| Bc-s ||^2 == .5*c'B'Bc - x'B's + .5*s's
*/
itkExceptionMacro( << "Nonnegative Solid Angle not yet implemented");
}
else
{
vnl_vector<TO> coeffs(m_NumberCoefficients);
coeffs = ( m_CoeffReconstructionMatrix * B );
coeffs[0] += 1.0/(2.0*sqrt(itk::Math::pi));
coeffPixel = coeffs.data_block();
odf = ( m_ReconstructionMatrix * B ).data_block();
}
odf = Normalize(odf, b0);
}
oit.Set( odf );
oit2.Set( b0 );
float sum = 0;
for (unsigned int k=0; k<odf.Size(); k++)
sum += (float) odf[k];
oit3.Set( sum-1 );
oit4.Set(coeffPixel);
++oit; // odf image iterator
++oit3; // odf sum image iterator
++oit2; // b0 image iterator
++oit4; // coefficient image iterator
++git; // Gradient image iterator
}
std::cout << "One Thread finished reconstruction" << std::endl;
}
template< class T, class TG, class TO, int ShOrder, int NrOdfDirections>
void AnalyticalDiffusionQballReconstructionImageFilter<T,TG,TO,ShOrder,NrOdfDirections>
::tofile2(vnl_matrix<float> *pA, std::string fname)
{
vnl_matrix<float> A = (*pA);
std::ofstream myfile;
std::locale C("C");
std::locale originalLocale = myfile.getloc();
myfile.imbue(C);
myfile.open (fname.c_str());
myfile << "A1=[";
for(unsigned int i=0; i<A.rows(); i++)
{
for(unsigned int j=0; j<A.columns(); j++)
{
myfile << A(i,j) << " ";
if(j==A.columns()-1 && i!=A.rows()-1)
myfile << ";";
}
}
myfile << "];";
myfile.close();
myfile.imbue( originalLocale );
}
template< class T, class TG, class TO, int ShOrder, int NrOdfDirections>
void AnalyticalDiffusionQballReconstructionImageFilter<T,TG,TO,ShOrder,NrOdfDirections>::ComputeReconstructionMatrix()
{
m_NumberCoefficients = (ShOrder*ShOrder + ShOrder + 2)/2 + ShOrder;
if( m_NumberOfGradientDirections < m_NumberCoefficients )
{
itkExceptionMacro( << "Not enough gradient directions supplied (" << m_NumberOfGradientDirections << "). At least " << (ShOrder*ShOrder + ShOrder + 2)/2 + ShOrder << " needed for SH-order " << ShOrder);
}
// Gradient preprocessing
{
// check for duplicate diffusion gradients
bool warning = false;
for(GradientDirectionContainerType::ConstIterator gdcit1 = this->m_GradientDirectionContainer->Begin();
gdcit1 != this->m_GradientDirectionContainer->End(); ++gdcit1)
{
for(GradientDirectionContainerType::ConstIterator gdcit2 = this->m_GradientDirectionContainer->Begin();
gdcit2 != this->m_GradientDirectionContainer->End(); ++gdcit2)
{
if(gdcit1.Value() == gdcit2.Value() && gdcit1.Index() != gdcit2.Index())
{
itkWarningMacro( << "Some of the Diffusion Gradients equal each other. Corresponding image data should be averaged before calling this filter." );
warning = true;
break;
}
}
if (warning)
break;
}
// handle acquisition schemes where only half of the spherical
// shell is sampled by the gradient directions. In this case,
// each gradient direction is duplicated in negative direction.
vnl_vector<double> centerMass(3);
centerMass.fill(0.0);
int count = 0;
for(GradientDirectionContainerType::ConstIterator gdcit1 = this->m_GradientDirectionContainer->Begin();
gdcit1 != this->m_GradientDirectionContainer->End(); ++gdcit1)
{
float bval = gdcit1.Value().two_norm();
bval = bval*bval*m_BValue;
if(bval > 100)
{
centerMass += gdcit1.Value();
count ++;
}
}
centerMass /= count;
if(centerMass.two_norm() > 0.1)
{
m_DirectionsDuplicated = true;
m_NumberOfGradientDirections *= 2;
}
}
// Create 3xM matrix Q that contains the gradient vectors in polar coordinates
vnl_matrix<float> Q(3, m_NumberOfGradientDirections);
{
int i = 0;
for(GradientDirectionContainerType::ConstIterator gdcit = this->m_GradientDirectionContainer->Begin(); gdcit != this->m_GradientDirectionContainer->End(); ++gdcit)
{
float bval = gdcit.Value().two_norm();
bval = bval*bval*m_BValue;
if(bval > 100)
{
double x = gdcit.Value().get(0);
double y = gdcit.Value().get(1);
double z = gdcit.Value().get(2);
double cart[3];
mitk::sh::Cart2Sph(x,y,z,cart);
Q(0,i) = cart[0];
Q(1,i) = cart[1];
Q(2,i++) = cart[2];
}
}
if(m_DirectionsDuplicated)
{
for(GradientDirectionContainerType::ConstIterator gdcit = this->m_GradientDirectionContainer->Begin(); gdcit != this->m_GradientDirectionContainer->End(); ++gdcit)
{
float bval = gdcit.Value().two_norm();
bval = bval*bval*m_BValue;
if(bval > 100)
{
double x = gdcit.Value().get(0);
double y = gdcit.Value().get(1);
double z = gdcit.Value().get(2);
double cart[3];
mitk::sh::Cart2Sph(x,y,z,cart);
Q(0,i) = cart[0];
Q(1,i) = cart[1];
Q(2,i++) = cart[2];
}
}
}
}
// Calcualte SH basis B
vnl_matrix<float> L(m_NumberCoefficients,m_NumberCoefficients, 0);
vnl_vector<int> lj(m_NumberCoefficients);
vnl_matrix<float> B(m_NumberOfGradientDirections,m_NumberCoefficients);
for(unsigned int i=0; i<m_NumberOfGradientDirections; i++)
{
for(int k=0; k<=ShOrder; k+=2)
{
for(int m=-k; m<=k; m++)
{
int j = (k*k + k + 2)/2 + m - 1;
L(j,j) = -k*(k+1);
lj[j] = k;
B(i,j) = mitk::sh::Yj(m, k, Q(1,i), Q(0,i));
}
}
}
vnl_matrix<float> P(m_NumberCoefficients,m_NumberCoefficients, 0);
for(unsigned int i=0; i<m_NumberCoefficients; i++)
P(i,i) = mitk::sh::legendre0(lj[i]);
vnl_matrix<float> B_transpose(B.transpose());
vnl_matrix_inverse<float>* pseudoInverse = new vnl_matrix_inverse<float>( B_transpose * B + L*L*m_Lambda );
m_CoeffReconstructionMatrix = pseudoInverse->pinverse() * B_transpose;
switch(m_NormalizationMethod)
{
case QBAR_ADC_ONLY:
case QBAR_RAW_SIGNAL:
break;
case QBAR_STANDARD:
case QBAR_B_ZERO_B_VALUE:
case QBAR_B_ZERO:
case QBAR_NONE:
{
m_CoeffReconstructionMatrix = P * m_CoeffReconstructionMatrix;
break;
}
case QBAR_SOLID_ANGLE:
{
m_CoeffReconstructionMatrix = (float)(1.0/(8.0*itk::Math::pi)) * P * L * m_CoeffReconstructionMatrix;
break;
}
case QBAR_NONNEG_SOLID_ANGLE:
break;
}
// needed to calculate the ODF values from the SH coefficients
vnl_matrix_fixed<double, 3, NrOdfDirections>* U = itk::PointShell<NrOdfDirections, vnl_matrix_fixed<double, 3, NrOdfDirections> >::DistributePointShell();
m_SphericalHarmonicBasisMatrix = mitk::sh::CalcShBasisForDirections(ShOrder, U->as_matrix());
m_ReconstructionMatrix = m_SphericalHarmonicBasisMatrix * m_CoeffReconstructionMatrix;
}
template< class T, class TG, class TO, int ShOrder, int NrOdfDirections>
void AnalyticalDiffusionQballReconstructionImageFilter<T,TG,TO,ShOrder,NrOdfDirections>
::SetGradientImage(const GradientDirectionContainerType *gradientDirection,
const GradientImagesType *gradientImage )
{
// Copy Gradient Direction Container
this->m_GradientDirectionContainer = GradientDirectionContainerType::New();
for(GradientDirectionContainerType::ConstIterator it = gradientDirection->Begin();
it != gradientDirection->End(); it++)
{
this->m_GradientDirectionContainer->push_back(it.Value());
}
if (m_BValue<0)
mitkThrow() << "B-value needs to be set before gradient image! " << m_BValue;
unsigned int numImages = gradientDirection->Size();
this->m_NumberOfBaselineImages = 0;
for(GradientDirectionContainerType::Iterator it = this->m_GradientDirectionContainer->Begin();
it != this->m_GradientDirectionContainer->End(); it++)
{
float bval = it.Value().two_norm();
bval = bval*bval*m_BValue;
if(bval < 100)
{
this->m_NumberOfBaselineImages++;
}
else // Normalize non-zero gradient directions
{
it.Value() = it.Value() / it.Value().two_norm();
}
}
if (this->m_NumberOfBaselineImages==0)
itkExceptionMacro("No baseline image detected (no b-zero image)");
this->m_NumberOfGradientDirections = numImages - this->m_NumberOfBaselineImages;
// ensure that the gradient image we received has as many components as
// the number of gradient directions
if( gradientImage->GetVectorLength() != this->m_NumberOfBaselineImages + m_NumberOfGradientDirections )
{
itkExceptionMacro( << m_NumberOfGradientDirections << " gradients + " << this->m_NumberOfBaselineImages
<< "baselines = " << m_NumberOfGradientDirections + this->m_NumberOfBaselineImages
<< " directions specified but image has " << gradientImage->GetVectorLength()
<< " components.");
}
this->ProcessObject::SetNthInput( 0, const_cast< GradientImagesType* >(gradientImage) );
}
template< class T, class TG, class TO, int ShOrder, int NrOdfDirections>
void AnalyticalDiffusionQballReconstructionImageFilter<T,TG,TO,ShOrder,NrOdfDirections>
::PrintSelf(std::ostream& os, Indent indent) const
{
std::locale C("C");
std::locale originalLocale = os.getloc();
os.imbue(C);
Superclass::PrintSelf(os,indent);
os << indent << "OdfReconstructionMatrix: " << m_ReconstructionMatrix << std::endl;
if ( m_GradientDirectionContainer )
os << indent << "GradientDirectionContainer: " << m_GradientDirectionContainer << std::endl;
else
os << indent << "GradientDirectionContainer: (Gradient directions not set)" << std::endl;
os << indent << "NumberOfGradientDirections: " << m_NumberOfGradientDirections << std::endl;
os << indent << "NumberOfBaselineImages: " << m_NumberOfBaselineImages << std::endl;
os << indent << "Threshold for reference B0 image: " << m_Threshold << std::endl;
os << indent << "BValue: " << m_BValue << std::endl;
os.imbue( originalLocale );
}
}
#endif // __itkAnalyticalDiffusionQballReconstructionImageFilter_cpp
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/itkAnalyticalDiffusionQballReconstructionImageFilter.h b/Modules/DiffusionCore/Algorithms/Reconstruction/itkAnalyticalDiffusionQballReconstructionImageFilter.h
index 9863fe2..f3ed194 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/itkAnalyticalDiffusionQballReconstructionImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/itkAnalyticalDiffusionQballReconstructionImageFilter.h
@@ -1,265 +1,265 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkAnalyticalDiffusionQballReconstructionImageFilter_h_
#define __itkAnalyticalDiffusionQballReconstructionImageFilter_h_
#include "itkImageToImageFilter.h"
#include "vnl/vnl_vector_fixed.h"
#include "vnl/vnl_matrix.h"
#include "vnl/algo/vnl_svd.h"
#include "itkVectorContainer.h"
#include "itkVectorImage.h"
namespace itk{
/** \class AnalyticalDiffusionQballReconstructionImageFilter
* \brief This class takes as input one or more reference image (acquired in the
* absence of diffusion sensitizing gradients) and 'n' diffusion
* weighted images and their gradient directions and computes an image of
* orientation distribution function coefficients in a spherical harmonic basis.
*
* \par Inputs and Usage
* \par
* When you have the 'n' gradient and one or more reference images in a single
* multi-component image (VectorImage), you can specify the images as
* \code
* filter->SetGradientImage( directionsContainer, vectorImage );
* \endcode
* Note that this method is used to specify both the reference and gradient images.
* This is convenient when the DWI images are read in using the
* <a href="http://wiki.na-mic.org/Wiki/index.php/NAMIC_Wiki:DTI:Nrrd_format">NRRD</a>
* format. Like the Nrrd format, the reference images are those components of the
* vectorImage whose gradient direction is (0,0,0). If more than one reference image
* is present, they are averaged prior to the reconstruction.
*
* \par Outputs
* The output image is an image of vectors that must be understood as ODFs:
* \code
* Image< Vector< TPixelType, OdfNrDirections >, 3 >
* \endcode
*
* \par Parameters
* \li Threshold - Threshold on the reference image data. The output ODF will
* be a null pdf for pixels in the reference image that have a value less
* than this.
* \li BValue - See the documentation of SetBValue().
* \li At least 6 gradient images must be specified for the filter to be able
* to run. If the input gradient directions g_i are majorly sampled on one half
* of the sqhere, then each input image I_i will be duplicated and assign -g_i
* in order to guarantee stability of the algorithm.
* \li OdfDirections - directions of resulting orientation distribution function
* \li EquatorNrSamplingPoints - number of sampling points on equator when
* performing Funk Radeon Transform (FRT)
* \li BasisFunctionCenters - the centers of the basis functions are used for
* the sRBF (spherical radial basis functions interpolation). If not set, they
* will be defaulted to equal m_EquatorNrSamplingPoints
*
* \par Template parameters
* The class is templated over
* \li the pixel type of the reference and gradient images
* (expected to be scalar data types)
* \li the internal representation of the ODF pixels (double, float etc).
* \li the number of OdfDirections
* \li the number of basis function centers for the sRBF
*
* \par References:
* \li<a href="http://www3.interscience.wiley.com/cgi-bin/fulltext/109800293/PDFSTART">[1]</a>
* <em>Tuch DS,
* "Q-ball imaging", Magn Reson Med. 2004 Dec;52(6):1358-72.</em>
*
*/
template< class TReferenceImagePixelType, class TGradientImagePixelType, class TOdfPixelType, int ShOrder, int NrOdfDirections>
class AnalyticalDiffusionQballReconstructionImageFilter : public ImageToImageFilter< Image< TReferenceImagePixelType, 3 >, Image< Vector< TOdfPixelType, NrOdfDirections >, 3 > >
{
public:
enum Normalization {
QBAR_STANDARD,
QBAR_B_ZERO_B_VALUE,
QBAR_B_ZERO,
QBAR_NONE,
QBAR_ADC_ONLY,
QBAR_RAW_SIGNAL,
QBAR_SOLID_ANGLE,
QBAR_NONNEG_SOLID_ANGLE
};
typedef AnalyticalDiffusionQballReconstructionImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< Image< TReferenceImagePixelType, 3>,
Image< Vector< TOdfPixelType, NrOdfDirections >, 3 > > Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(AnalyticalDiffusionQballReconstructionImageFilter, ImageToImageFilter)
typedef TReferenceImagePixelType ReferencePixelType;
typedef TGradientImagePixelType GradientPixelType;
typedef Vector< TOdfPixelType, NrOdfDirections > OdfPixelType;
typedef TOdfPixelType BZeroPixelType;
/** Reference image data, This image is aquired in the absence
* of a diffusion sensitizing field gradient */
typedef typename Superclass::InputImageType ReferenceImageType;
typedef Image< OdfPixelType, 3 > OdfImageType;
typedef OdfImageType OutputImageType;
typedef Image< Vector< TOdfPixelType, (ShOrder*ShOrder + ShOrder + 2)/2 + ShOrder >, 3 > CoefficientImageType;
typedef Image< BZeroPixelType, 3 > BZeroImageType;
typedef typename Superclass::OutputImageRegionType
OutputImageRegionType;
/** Typedef defining one (of the many) gradient images. */
typedef Image< GradientPixelType, 3 > GradientImageType;
/** An alternative typedef defining one (of the many) gradient images.
* It will be assumed that the vectorImage has the same dimension as the
* Reference image and a vector length parameter of \c n (number of
* gradient directions)*/
typedef VectorImage< GradientPixelType, 3 > GradientImagesType;
/** Holds each magnetic field gradient used to acquire one DWImage */
typedef vnl_vector_fixed< double, 3 > GradientDirectionType;
/** Container to hold gradient directions of the 'n' DW measurements */
typedef VectorContainer< unsigned int,
GradientDirectionType > GradientDirectionContainerType;
/** set method to add gradient directions and its corresponding
* image. The image here is a VectorImage. The user is expected to pass the
* gradient directions in a container. The ith element of the container
* corresponds to the gradient direction of the ith component image the
* VectorImage. For the baseline image, a vector of all zeros
* should be set.*/
void SetGradientImage( const GradientDirectionContainerType *,
const GradientImagesType *image);
/** Get reference image */
virtual ReferenceImageType * GetReferenceImage()
{ return ( static_cast< ReferenceImageType *>(this->ProcessObject::GetInput(0)) ); }
/** Return the gradient direction. idx is 0 based */
virtual GradientDirectionType GetGradientDirection( unsigned int idx) const
{
if( idx >= m_NumberOfGradientDirections )
itkExceptionMacro( << "Gradient direction " << idx << "does not exist" );
return m_GradientDirectionContainer->ElementAt( idx+1 );
}
static void tofile2(vnl_matrix<float> *A, std::string fname);
OdfPixelType Normalize(OdfPixelType odf, typename NumericTraits<ReferencePixelType>::AccumulateType b0 );
vnl_vector<TOdfPixelType> PreNormalize( vnl_vector<TOdfPixelType> vec, typename NumericTraits<ReferencePixelType>::AccumulateType b0 );
/** Threshold on the reference image data. The output ODF will be a null
* pdf for pixels in the reference image that have a value less than this
* threshold. */
itkSetMacro( Threshold, ReferencePixelType )
itkGetMacro( Threshold, ReferencePixelType )
itkSetMacro( NormalizationMethod, Normalization)
itkGetMacro( NormalizationMethod, Normalization )
typedef Image<float, 3> FloatImageType;
itkGetMacro( BZeroImage, typename BZeroImageType::Pointer)
itkGetMacro( ODFSumImage, typename FloatImageType::Pointer)
itkGetMacro( CoefficientImage, typename CoefficientImageType::Pointer)
itkSetMacro( BValue, float)
itkSetMacro( Lambda, double )
itkGetMacro( Lambda, double )
itkSetMacro( UseMrtrixBasis, bool )
#ifdef ITK_USE_CONCEPT_CHECKING
/** Begin concept checking */
itkConceptMacro(ReferenceEqualityComparableCheck,
(Concept::EqualityComparable<ReferencePixelType>));
itkConceptMacro(TensorEqualityComparableCheck,
(Concept::EqualityComparable<OdfPixelType>));
itkConceptMacro(GradientConvertibleToDoubleCheck,
(Concept::Convertible<GradientPixelType, double>));
itkConceptMacro(DoubleConvertibleToTensorCheck,
(Concept::Convertible<double, OdfPixelType>));
itkConceptMacro(GradientReferenceAdditiveOperatorsCheck,
(Concept::AdditiveOperators<GradientPixelType, GradientPixelType,
ReferencePixelType>));
itkConceptMacro(ReferenceOStreamWritableCheck,
(Concept::OStreamWritable<ReferencePixelType>));
itkConceptMacro(TensorOStreamWritableCheck,
(Concept::OStreamWritable<OdfPixelType>));
/** End concept checking */
#endif
protected:
AnalyticalDiffusionQballReconstructionImageFilter();
~AnalyticalDiffusionQballReconstructionImageFilter() override {};
void PrintSelf(std::ostream& os, Indent indent) const override;
void ComputeReconstructionMatrix();
void BeforeThreadedGenerateData() override;
void ThreadedGenerateData( const
OutputImageRegionType &outputRegionForThread, ThreadIdType) override;
private:
vnl_matrix< float > m_ReconstructionMatrix;
vnl_matrix< float > m_CoeffReconstructionMatrix;
vnl_matrix< float > m_SphericalHarmonicBasisMatrix;
/** container to hold gradient directions */
GradientDirectionContainerType::Pointer m_GradientDirectionContainer;
/** Number of gradient measurements */
unsigned int m_NumberOfGradientDirections;
/** Number of baseline images */
unsigned int m_NumberOfBaselineImages;
/** Threshold on the reference image data */
ReferencePixelType m_Threshold;
/** LeBihan's b-value for normalizing tensors */
float m_BValue;
typename BZeroImageType::Pointer m_BZeroImage;
double m_Lambda;
bool m_DirectionsDuplicated;
Normalization m_NormalizationMethod;
unsigned int m_NumberCoefficients;
FloatImageType::Pointer m_ODFSumImage;
typename CoefficientImageType::Pointer m_CoefficientImage;
TOdfPixelType m_Delta1;
TOdfPixelType m_Delta2;
bool m_UseMrtrixBasis;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkAnalyticalDiffusionQballReconstructionImageFilter.cpp"
#endif
#endif //__itkAnalyticalDiffusionQballReconstructionImageFilter_h_
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/itkBallAndSticksImageFilter.h b/Modules/DiffusionCore/Algorithms/Reconstruction/itkBallAndSticksImageFilter.h
index 5b65554..3c55c30 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/itkBallAndSticksImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/itkBallAndSticksImageFilter.h
@@ -1,104 +1,104 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkBallAndSticksImageFilter_h_
#define __itkBallAndSticksImageFilter_h_
#include "itkImageToImageFilter.h"
#include "itkVectorImage.h"
#include <mitkDiffusionPropertyHelper.h>
#include <vnl/algo/vnl_levenberg_marquardt.h>
#include <mitkOdfImage.h>
#include <itkDiffusionTensor3D.h>
#include <itkDiffusionTensor3DReconstructionImageFilter.h>
#include <cmath>
#include <mitkTensorImage.h>
#define NUM_TENSORS 2
namespace itk{
/** \class BallAndSticksImageFilter
*/
template< class TInPixelType, class TOutPixelType >
class BallAndSticksImageFilter :
public ImageToImageFilter< VectorImage< TInPixelType, 3 >, Image< TOutPixelType, 3 > >
{
public:
typedef BallAndSticksImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< VectorImage< TInPixelType, 3 >, Image< TOutPixelType, 3 > > Superclass;
typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientContainerType;
typedef itk::Image< unsigned char, 3> ItkUcharImageType;
typedef itk::Image< float, 4 > PeakImageType;
typedef itk::DiffusionTensor3DReconstructionImageFilter< TInPixelType, TInPixelType, float > TensorRecFilterType;
typedef mitk::TensorImage::PixelType TensorType;
typedef mitk::TensorImage::ItkTensorImageType TensorImageType;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(BallAndSticksImageFilter, ImageToImageFilter)
typedef typename Superclass::InputImageType InputImageType;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename Superclass::OutputImageRegionType OutputImageRegionType;
itkSetMacro( MaskImage, ItkUcharImageType::Pointer )
itkSetMacro( B_value, double )
itkSetMacro( GradientDirections, GradientContainerType::Pointer )
itkGetMacro( PeakImage, PeakImageType::Pointer )
itkGetMacro( OutDwi, typename InputImageType::Pointer )
protected:
BallAndSticksImageFilter();
~BallAndSticksImageFilter() {}
void PrintSelf(std::ostream& os, Indent indent) const override;
void BeforeThreadedGenerateData() override;
void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType) override;
double m_B_value;
std::vector<double> m_B_values;
std::vector<int> m_WeightedIndices;
std::vector<int> m_UnWeightedIndices;
GradientContainerType::Pointer m_GradientDirections;
ItkUcharImageType::Pointer m_MaskImage;
PeakImageType::Pointer m_PeakImage;
TensorImageType::Pointer m_TensorImage;
typename InputImageType::Pointer m_OutDwi;
vnl_vector<double> FitSingleVoxel( const typename InputImageType::PixelType &input, const typename InputImageType::IndexType &idx);
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkBallAndSticksImageFilter.txx"
#endif
#endif //__itkBallAndSticksImageFilter_h_
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/itkBallAndSticksImageFilter.txx b/Modules/DiffusionCore/Algorithms/Reconstruction/itkBallAndSticksImageFilter.txx
index 5e13f22..39bb6ff 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/itkBallAndSticksImageFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/itkBallAndSticksImageFilter.txx
@@ -1,252 +1,252 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkBallAndSticksImageFilter_txx
#define __itkBallAndSticksImageFilter_txx
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionConstIteratorWithIndex.h"
#include "itkImageRegionIterator.h"
#include <mitkBallStickFitter.h>
namespace itk {
template< class TInPixelType, class TOutPixelType >
BallAndSticksImageFilter< TInPixelType, TOutPixelType>
::BallAndSticksImageFilter()
: m_B_value(0)
{
this->SetNumberOfRequiredInputs( 1 );
}
template< class TInPixelType, class TOutPixelType >
void
BallAndSticksImageFilter< TInPixelType, TOutPixelType>
::BeforeThreadedGenerateData()
{
typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0));
outputImage->FillBuffer(0.0);
m_UnWeightedIndices.clear();
m_WeightedIndices.clear();
m_B_values.clear();
for (unsigned int i=0; i<m_GradientDirections->Size(); i++)
{
GradientDirectionType g = m_GradientDirections->GetElement(i);
double twonorm = g.two_norm();
double b = m_B_value*twonorm*twonorm;
m_B_values.push_back(b);
if (b>100)
m_WeightedIndices.push_back(i);
else
m_UnWeightedIndices.push_back(i);
}
if (m_UnWeightedIndices.empty())
mitkThrow() << "Unweighted (b=0 s/mm²) image volume missing!";
itk::Vector<double, 3> spacing3 = outputImage->GetSpacing();
itk::Point<float, 3> origin3 = outputImage->GetOrigin();
itk::Matrix<double, 3, 3> direction3 = outputImage->GetDirection();
itk::ImageRegion<3> imageRegion3 = outputImage->GetLargestPossibleRegion();
itk::Vector<double, 4> spacing4;
itk::Point<float, 4> origin4;
itk::Matrix<double, 4, 4> direction4;
itk::ImageRegion<4> imageRegion4;
spacing4[0] = spacing3[0]; spacing4[1] = spacing3[1]; spacing4[2] = spacing3[2]; spacing4[3] = 1;
origin4[0] = origin3[0]; origin4[1] = origin3[1]; origin4[2] = origin3[2]; origin4[3] = 0;
for (int r=0; r<3; r++)
for (int c=0; c<3; c++)
direction4[r][c] = direction3[r][c];
direction4[3][3] = 1;
imageRegion4.SetSize(0, imageRegion3.GetSize()[0]);
imageRegion4.SetSize(1, imageRegion3.GetSize()[1]);
imageRegion4.SetSize(2, imageRegion3.GetSize()[2]);
imageRegion4.SetSize(3, 3);
m_PeakImage = PeakImageType::New();
m_PeakImage->SetSpacing( spacing4 );
m_PeakImage->SetOrigin( origin4 );
m_PeakImage->SetDirection( direction4 );
m_PeakImage->SetRegions( imageRegion4 );
m_PeakImage->Allocate();
m_PeakImage->FillBuffer(0.0);
m_OutDwi = InputImageType::New();
m_OutDwi->SetSpacing( spacing3 );
m_OutDwi->SetOrigin( origin3 );
m_OutDwi->SetDirection( direction3 );
m_OutDwi->SetRegions( imageRegion3 );
m_OutDwi->SetVectorLength(m_GradientDirections->Size());
m_OutDwi->Allocate();
MITK_INFO << "Initial tensor fit";
typename InputImageType::Pointer inputImagePointer = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
typename TensorRecFilterType::Pointer tensorReconstructionFilter = TensorRecFilterType::New();
tensorReconstructionFilter->SetBValue( m_B_value );
tensorReconstructionFilter->SetGradientImage( m_GradientDirections, inputImagePointer );
tensorReconstructionFilter->Update();
m_TensorImage = tensorReconstructionFilter->GetOutput();
}
template< class TInPixelType, class TOutPixelType >
vnl_vector<double>
BallAndSticksImageFilter< TInPixelType, TOutPixelType>::FitSingleVoxel( const typename InputImageType::PixelType &input, const typename InputImageType::IndexType &idx)
{
double S0 = 0;
for (auto i : m_UnWeightedIndices)
S0 += input[i];
S0 /= m_UnWeightedIndices.size();
// Linear tensor fit
double md = 0.001;
double f = 0.5;
double theta = 0;
double phi = 0;
{
TensorType tensor = m_TensorImage->GetPixel(idx);
TensorType::EigenValuesArrayType eigenvalues;
TensorType::EigenVectorsMatrixType eigenvectors;
tensor.ComputeEigenAnalysis(eigenvalues, eigenvectors);
vnl_vector_fixed<double,3> ev;
ev[0] = eigenvectors(2, 0);
ev[1] = eigenvectors(2, 1);
ev[2] = eigenvectors(2, 2);
if (ev.magnitude()>mitk::eps)
ev.normalize();
else
ev.fill(0.0);
md = fabs(eigenvalues[0]+eigenvalues[1]+eigenvalues[2])/3;
f = tensor.GetFractionalAnisotropy();
if (f<0.1)
f = 0.1;
else if (f>0.9)
f = 0.9;
mitk::AbstractFitter::Cart2Sph(ev, theta, phi);
}
int num_params = 4; // f, d, phi, theta
vnl_vector<double> x; x.set_size(num_params); x.fill(0.0);
x[0] = f; // f (volume fraction)
x[1] = md; // d
x[2] = theta;
x[3] = phi;
mitk::BallStickFitter bs_fit(num_params, m_GradientDirections->size());
bs_fit.set_S0(S0);
bs_fit.set_weightedIndices(m_WeightedIndices);
bs_fit.set_bvalues(m_B_values);
bs_fit.set_gradient_directions(m_GradientDirections);
bs_fit.set_measurements(input);
vnl_levenberg_marquardt lm(bs_fit);
lm.minimize(x);
return x;
}
template< class TInPixelType, class TOutPixelType >
void
BallAndSticksImageFilter< TInPixelType, TOutPixelType>
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, ThreadIdType )
{
typename OutputImageType::Pointer outputImage =
static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0));
ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread);
oit.GoToBegin();
typedef ImageRegionConstIterator< InputImageType > InputIteratorType;
typename InputImageType::Pointer inputImagePointer = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
InputIteratorType git( inputImagePointer, outputRegionForThread );
git.GoToBegin();
while( !git.IsAtEnd() )
{
typename InputImageType::PixelType pix = git.Get();
vnl_vector<double> x = FitSingleVoxel(pix, git.GetIndex());
/// PEAKS
PeakImageType::IndexType idx4;
idx4[0] = oit.GetIndex()[0];
idx4[1] = oit.GetIndex()[1];
idx4[2] = oit.GetIndex()[2];
oit.Set( x[0] );
vnl_vector_fixed<double,3> dir;
mitk::AbstractFitter::Sph2Cart(dir, x[2], x[3]);
idx4[3] = 0;
m_PeakImage->SetPixel(idx4, dir[0]);
idx4[3] = 1;
m_PeakImage->SetPixel(idx4, dir[1]);
idx4[3] = 2;
m_PeakImage->SetPixel(idx4, dir[2]);
/// DWI from ball-stick
typename InputImageType::PixelType dPix; dPix.SetSize(m_GradientDirections->Size()); dPix.Fill(0.0);
for (unsigned int i=0; i<m_GradientDirections->Size(); i++)
{
GradientDirectionType g = m_GradientDirections->GetElement(i);
double twonorm = g.two_norm();
double b = m_B_value*twonorm*twonorm;
g.normalize();
double s_iso = 1000 * std::exp(-b * x[1]);
double dot = dot_product(g, dir);
double s_aniso = 1000 * std::exp(-b * x[1] * dot*dot );
double approx = (1-x[0])*s_iso + x[0]*s_aniso;
dPix[i] = approx;
}
m_OutDwi->SetPixel(oit.GetIndex(), dPix);
++oit;
++git;
}
std::cout << "One Thread finished calculation" << std::endl;
}
template< class TInPixelType, class TOutPixelType >
void
BallAndSticksImageFilter< TInPixelType, TOutPixelType>
::PrintSelf(std::ostream& os, Indent indent) const
{
Superclass::PrintSelf(os,indent);
}
}
#endif // __itkBallAndSticksImageFilter_txx
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.cpp b/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.cpp
index ff8e879..de2531f 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.cpp
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.cpp
@@ -1,781 +1,781 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter_cpp
#define __itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter_cpp
#include "itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.h"
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionConstIteratorWithIndex.h"
#include "itkImageRegionIterator.h"
#include "vnl/vnl_matrix.h"
#include "vnl/algo/vnl_symmetric_eigensystem.h"
#include "itkRegularizedIVIMReconstructionFilter.h"
#include <mitkLogMacros.h>
#define IVIM_FOO -100000
namespace itk {
template< class TIn, class TOut>
DiffusionIntravoxelIncoherentMotionReconstructionImageFilter<TIn, TOut>
::DiffusionIntravoxelIncoherentMotionReconstructionImageFilter() :
m_GradientDirectionContainer(nullptr),
m_Method(IVIM_DSTAR_FIX),
m_FitDStar(true),
m_Verbose(false)
{
this->SetNumberOfRequiredInputs( 1 );
this->SetNumberOfRequiredOutputs( 3 );
typename OutputImageType::Pointer outputPtr1 = OutputImageType::New();
this->SetNthOutput(0, outputPtr1.GetPointer());
typename OutputImageType::Pointer outputPtr2 = OutputImageType::New();
this->SetNthOutput(1, outputPtr2.GetPointer());
typename OutputImageType::Pointer outputPtr3 = OutputImageType::New();
this->SetNthOutput(2, outputPtr3.GetPointer());
}
template< class TIn, class TOut>
void DiffusionIntravoxelIncoherentMotionReconstructionImageFilter<TIn, TOut>
::BeforeThreadedGenerateData()
{
// Input must be an itk::VectorImage.
std::string gradientImageClassName(
this->ProcessObject::GetInput(0)->GetNameOfClass());
if ( strcmp(gradientImageClassName.c_str(),"VectorImage") != 0 )
{
itkExceptionMacro( <<
"There is only one Gradient image. I expect that to be a VectorImage. "
<< "But its of type: " << gradientImageClassName );
}
// Compute the indicies of the baseline images and gradient images
// If no b=0 mm/s² gradients ar found, the next lowest b-value is used.
GradientDirectionContainerType::ConstIterator gdcit = this->m_GradientDirectionContainer->Begin();
double minNorm = itk::NumericTraits<double>::max();
while( gdcit != this->m_GradientDirectionContainer->End() )
{
double norm = gdcit.Value().one_norm();
if (norm<minNorm)
minNorm = norm;
++gdcit;
}
minNorm += 0.001;
gdcit = this->m_GradientDirectionContainer->Begin();
while( gdcit != this->m_GradientDirectionContainer->End() )
{
if(gdcit.Value().one_norm() <= minNorm)
{
m_Snap.baselineind.push_back(gdcit.Index());
}
else
{
m_Snap.gradientind.push_back(gdcit.Index());
double twonorm = gdcit.Value().two_norm();
m_Snap.bvals.push_back( m_BValue*twonorm*twonorm );
}
++gdcit;
}
if (m_Snap.gradientind.size()==0)
itkExceptionMacro("Only one b-value supplied. At least two needed for IVIM fit.");
// check sind die grad und base gleichlang? alle grad gerade und base ungerade? dann iterierende aufnahme!!
m_Snap.iterated_sequence = false;
if(m_Snap.baselineind.size() == m_Snap.gradientind.size())
{
int size = m_Snap.baselineind.size();
int sum_b = 0, sum_g = 0;
for(int i=0; i<size; i++)
{
sum_b += m_Snap.baselineind.at(i) % 2;
sum_g += m_Snap.gradientind.at(i) % 2;
}
if( (sum_b == size || sum_b == 0)
&& (sum_g == size || sum_g == 0) )
{
m_Snap.iterated_sequence = true;
if(m_Verbose)
{
MITK_INFO << "Iterating b0 and diffusion weighted aquisition detected. Weighting each weighted measurement with its own b0.";
}
}
}
// number of measurements
m_Snap.N = m_Snap.gradientind.size();
// bvalue array
m_Snap.bvalues.set_size(m_Snap.N);
for(int i=0; i<m_Snap.N; i++)
{
m_Snap.bvalues[i] = m_Snap.bvals.at(i);
}
if(m_Verbose)
{
std::cout << "ref bval: " << m_BValue << "; b-values: ";
for(int i=0; i<m_Snap.N; i++)
{
std::cout << m_Snap.bvalues[i] << "; ";
}
std::cout << std::endl;
}
// extract bvals higher than threshold
if(m_Method == IVIM_D_THEN_DSTAR || m_Method == IVIM_LINEAR_D_THEN_F || m_Method == IVIM_REGULARIZED)
{
for(int i=0; i<m_Snap.N; i++)
{
if(m_Snap.bvalues[i]>m_BThres)
{
m_Snap.high_indices.push_back(i);
}
}
}
m_Snap.Nhigh = m_Snap.high_indices.size();
m_Snap.high_bvalues.set_size(m_Snap.Nhigh);
m_Snap.high_meas.set_size(m_Snap.Nhigh);
for(int i=0; i<m_Snap.Nhigh; i++)
{
m_Snap.high_bvalues[i] = m_Snap.bvalues[m_Snap.high_indices.at(i)];
}
}
template< class TIn, class TOut>
MeasAndBvals DiffusionIntravoxelIncoherentMotionReconstructionImageFilter<TIn, TOut>
::ApplyS0Threshold(vnl_vector<double> &meas, vnl_vector<double> &bvals)
{
std::vector<double> newmeas;
std::vector<double> newbvals;
int N = meas.size();
for(int i=0; i<N; i++)
{
if( meas[i] != IVIM_FOO )
{
newmeas.push_back(meas[i]);
newbvals.push_back(bvals[i]);
}
}
MeasAndBvals retval;
retval.N = newmeas.size();
retval.meas.set_size(retval.N);
for(size_t i=0; i<newmeas.size(); i++)
{
retval.meas[i] = newmeas[i];
}
retval.bvals.set_size(retval.N);
for(size_t i=0; i<newbvals.size(); i++)
{
retval.bvals[i] = newbvals[i];
}
return retval;
}
template< class TIn, class TOut>
void DiffusionIntravoxelIncoherentMotionReconstructionImageFilter<TIn, TOut>
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
ThreadIdType )
{
typename OutputImageType::Pointer outputImage =
static_cast< OutputImageType * >(this->ProcessObject::GetPrimaryOutput());
ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread);
oit.GoToBegin();
typename OutputImageType::Pointer dImage =
static_cast< OutputImageType * >(this->ProcessObject::GetOutput(1));
ImageRegionIterator< OutputImageType > oit1(dImage, outputRegionForThread);
oit1.GoToBegin();
typename OutputImageType::Pointer dstarImage =
static_cast< OutputImageType * >(this->ProcessObject::GetOutput(2));
ImageRegionIterator< OutputImageType > oit2(dstarImage, outputRegionForThread);
oit2.GoToBegin();
typedef ImageRegionConstIterator< InputImageType > InputIteratorType;
typedef typename InputImageType::PixelType InputVectorType;
typename InputImageType::Pointer inputImagePointer = nullptr;
// Would have liked a dynamic_cast here, but seems SGI doesn't like it
// The enum will DiffusionIntravoxelIncoherentMotionReconstructionImageFilterensure that an inappropriate cast is not done
inputImagePointer = static_cast< InputImageType * >(
this->ProcessObject::GetInput(0) );
InputIteratorType iit(inputImagePointer, outputRegionForThread );
iit.GoToBegin();
// init internal vector image for regularized fit
m_InternalVectorImage = VectorImageType::New();
m_InternalVectorImage->SetSpacing( inputImagePointer->GetSpacing() ); // Set the image spacing
m_InternalVectorImage->SetOrigin( inputImagePointer->GetOrigin() ); // Set the image origin
m_InternalVectorImage->SetDirection( inputImagePointer->GetDirection() ); // Set the image direction
m_InternalVectorImage->SetRegions( inputImagePointer->GetLargestPossibleRegion() );
m_InitialFitImage = InitialFitImageType::New();
m_InitialFitImage->SetSpacing( inputImagePointer->GetSpacing() ); // Set the image spacing
m_InitialFitImage->SetOrigin( inputImagePointer->GetOrigin() ); // Set the image origin
m_InitialFitImage->SetDirection( inputImagePointer->GetDirection() ); // Set the image direction
m_InitialFitImage->SetRegions( inputImagePointer->GetLargestPossibleRegion() );
if(m_Method == IVIM_REGULARIZED)
{
m_InternalVectorImage->SetVectorLength(m_Snap.Nhigh);
m_InternalVectorImage->Allocate();
VectorImageType::PixelType varvec(m_Snap.Nhigh);
for(int i=0; i<m_Snap.Nhigh; i++) varvec[i] = IVIM_FOO;
m_InternalVectorImage->FillBuffer(varvec);
m_InitialFitImage->Allocate();
InitialFitImageType::PixelType vec;
vec[0] = 0.5; vec[1] = 0.01; vec[2]=0.001;
m_InitialFitImage->FillBuffer(vec);
}
typedef itk::ImageRegionIterator<VectorImageType> VectorIteratorType;
VectorIteratorType vecit(m_InternalVectorImage, outputRegionForThread );
vecit.GoToBegin();
typedef itk::ImageRegionIterator<InitialFitImageType> InitIteratorType;
InitIteratorType initit(m_InitialFitImage, outputRegionForThread );
initit.GoToBegin();
while( !iit.IsAtEnd() )
{
InputVectorType measvec = iit.Get();
typename NumericTraits<InputPixelType>::AccumulateType b0 = NumericTraits<InputPixelType>::Zero;
m_Snap.meas.set_size(m_Snap.N);
m_Snap.allmeas.set_size(m_Snap.N);
if(!m_Snap.iterated_sequence)
{
// Average the baseline image pixels
for(unsigned int i = 0; i < m_Snap.baselineind.size(); ++i)
{
b0 += measvec[m_Snap.baselineind[i]];
}
if(m_Snap.baselineind.size())
b0 /= m_Snap.baselineind.size();
// measurement vector
for(int i = 0; i < m_Snap.N; ++i)
{
m_Snap.allmeas[i] = measvec[m_Snap.gradientind[i]] / (b0+.0001);
if(measvec[m_Snap.gradientind[i]] > m_S0Thres)
{
m_Snap.meas[i] = measvec[m_Snap.gradientind[i]] / (b0+.0001);
}
else
{
m_Snap.meas[i] = IVIM_FOO;
}
}
}
else
{
// measurement vector
for(int i = 0; i < m_Snap.N; ++i)
{
b0 = measvec[m_Snap.baselineind[i]];
m_Snap.allmeas[i] = measvec[m_Snap.gradientind[i]] / (b0+.0001);
if(measvec[m_Snap.gradientind[i]] > m_S0Thres)
{
m_Snap.meas[i] = measvec[m_Snap.gradientind[i]] / (b0+.0001);
}
else
{
m_Snap.meas[i] = IVIM_FOO;
}
}
}
m_Snap.currentF = 0;
m_Snap.currentD = 0;
m_Snap.currentDStar = 0;
switch(m_Method)
{
case IVIM_D_THEN_DSTAR:
{
for(int i=0; i<m_Snap.Nhigh; i++)
{
m_Snap.high_meas[i] = m_Snap.meas[m_Snap.high_indices.at(i)];
}
MeasAndBvals input = ApplyS0Threshold(m_Snap.high_meas, m_Snap.high_bvalues);
m_Snap.bvals1 = input.bvals;
m_Snap.meas1 = input.meas;
if (input.N < 2)
{
if (input.N == 1)
{
m_Snap.currentD = - log(input.meas[0]) / input.bvals[0];
m_Snap.currentF = 0;
m_Snap.currentDStar = 0;
}
break;
}
IVIM_d_and_f f_donly(input.N);
f_donly.set_bvalues(input.bvals);
f_donly.set_measurements(input.meas);
vnl_vector< double > x_donly(2);
x_donly[0] = 0.001;
x_donly[1] = 0.1;
// f 0.1 Dstar 0.01 D 0.001
vnl_levenberg_marquardt lm_donly(f_donly);
lm_donly.set_f_tolerance(0.0001);
lm_donly.minimize(x_donly);
m_Snap.currentD = x_donly[0];
m_Snap.currentF = x_donly[1];
if(m_FitDStar)
{
MeasAndBvals input2 = ApplyS0Threshold(m_Snap.meas, m_Snap.bvalues);
m_Snap.bvals2 = input2.bvals;
m_Snap.meas2 = input2.meas;
if (input2.N < 2) break;
IVIM_dstar_only f_dstar_only(input2.N,m_Snap.currentD,m_Snap.currentF);
f_dstar_only.set_bvalues(input2.bvals);
f_dstar_only.set_measurements(input2.meas);
vnl_vector< double > x_dstar_only(1);
vnl_vector< double > fx_dstar_only(input2.N);
double opt = 1111111111111111.0;
int opt_idx = -1;
int num_its = 100;
double min_val = .001;
double max_val = .15;
for(int i=0; i<num_its; i++)
{
x_dstar_only[0] = min_val + i * ((max_val-min_val) / num_its);
f_dstar_only.f(x_dstar_only, fx_dstar_only);
double err = fx_dstar_only.two_norm();
if(err<opt)
{
opt = err;
opt_idx = i;
}
}
m_Snap.currentDStar = min_val + opt_idx * ((max_val-min_val) / num_its);
// IVIM_fixd f_fixd(input2.N,m_Snap.currentD);
// f_fixd.set_bvalues(input2.bvals);
// f_fixd.set_measurements(input2.meas);
// vnl_vector< double > x_fixd(2);
// x_fixd[0] = 0.1;
// x_fixd[1] = 0.01;
// // f 0.1 Dstar 0.01 D 0.001
// vnl_levenberg_marquardt lm_fixd(f_fixd);
// lm_fixd.set_f_tolerance(0.0001);
// lm_fixd.minimize(x_fixd);
// m_Snap.currentF = x_fixd[0];
// m_Snap.currentDStar = x_fixd[1];
}
break;
}
case IVIM_DSTAR_FIX:
{
MeasAndBvals input = ApplyS0Threshold(m_Snap.meas, m_Snap.bvalues);
m_Snap.bvals1 = input.bvals;
m_Snap.meas1 = input.meas;
if (input.N < 2) break;
IVIM_fixdstar f_fixdstar(input.N,m_DStar);
f_fixdstar.set_bvalues(input.bvals);
f_fixdstar.set_measurements(input.meas);
vnl_vector< double > x(2);
x[0] = 0.1;
x[1] = 0.001;
// f 0.1 Dstar 0.01 D 0.001
vnl_levenberg_marquardt lm(f_fixdstar);
lm.set_f_tolerance(0.0001);
lm.minimize(x);
m_Snap.currentF = x[0];
m_Snap.currentD = x[1];
m_Snap.currentDStar = m_DStar;
break;
}
case IVIM_FIT_ALL:
{
MeasAndBvals input = ApplyS0Threshold(m_Snap.meas, m_Snap.bvalues);
m_Snap.bvals1 = input.bvals;
m_Snap.meas1 = input.meas;
if (input.N < 3) break;
IVIM_3param f_3param(input.N);
f_3param.set_bvalues(input.bvals);
f_3param.set_measurements(input.meas);
vnl_vector< double > x(3);
x[0] = 0.1;
x[1] = 0.001;
x[2] = 0.01;
// f 0.1 Dstar 0.01 D 0.001
vnl_levenberg_marquardt lm(f_3param);
lm.set_f_tolerance(0.0001);
lm.minimize(x);
m_Snap.currentF = x[0];
m_Snap.currentD = x[1];
m_Snap.currentDStar = x[2];
break;
}
case IVIM_LINEAR_D_THEN_F:
{
// // neglect zero-measurements
// bool zero = false;
// for(int i=0; i<Nhigh; i++)
// {
// if( meas[high_indices.at(i)] == 0 )
// {
// f=0;
// zero = true;
// break;
// }
// }
// if(zero) break;
for(int i=0; i<m_Snap.Nhigh; i++)
{
m_Snap.high_meas[i] = m_Snap.meas[m_Snap.high_indices.at(i)];
}
MeasAndBvals input = ApplyS0Threshold(m_Snap.high_meas, m_Snap.high_bvalues);
m_Snap.bvals1 = input.bvals;
m_Snap.meas1 = input.meas;
if (input.N < 2)
{
if (input.N == 1)
{
m_Snap.currentD = - log(input.meas[0]) / input.bvals[0];
m_Snap.currentF = 0;
m_Snap.currentDStar = 0;
}
break;
}
for(int i=0; i<input.N; i++)
{
input.meas[i] = log(input.meas[i]);
}
double bval_m = 0;
double meas_m = 0;
for(int i=0; i<input.N; i++)
{
bval_m += input.bvals[i];
meas_m += input.meas[i];
}
bval_m /= input.N;
meas_m /= input.N;
vnl_matrix<double> X(input.N,2);
for(int i=0; i<input.N; i++)
{
X(i,0) = input.bvals[i] - bval_m;
X(i,1) = input.meas[i] - meas_m;
}
vnl_matrix<double> XX = X.transpose() * X;
vnl_symmetric_eigensystem<double> eigs(XX);
vnl_vector<double> eig;
if(eigs.get_eigenvalue(0) > eigs.get_eigenvalue(1))
eig = eigs.get_eigenvector(0);
else
eig = eigs.get_eigenvector(1);
m_Snap.currentF = 1 - exp( meas_m - bval_m*(eig(1)/eig(0)) );
m_Snap.currentD = -eig(1)/eig(0);
if(m_FitDStar)
{
MeasAndBvals input2 = ApplyS0Threshold(m_Snap.meas, m_Snap.bvalues);
m_Snap.bvals2 = input2.bvals;
m_Snap.meas2 = input2.meas;
if (input2.N < 2) break;
IVIM_dstar_only f_dstar_only(input2.N,m_Snap.currentD,m_Snap.currentF);
f_dstar_only.set_bvalues(input2.bvals);
f_dstar_only.set_measurements(input2.meas);
vnl_vector< double > x_dstar_only(1);
vnl_vector< double > fx_dstar_only(input2.N);
double opt = 1111111111111111.0;
int opt_idx = -1;
int num_its = 100;
double min_val = .001;
double max_val = .15;
for(int i=0; i<num_its; i++)
{
x_dstar_only[0] = min_val + i * ((max_val-min_val) / num_its);
f_dstar_only.f(x_dstar_only, fx_dstar_only);
double err = fx_dstar_only.two_norm();
if(err<opt)
{
opt = err;
opt_idx = i;
}
}
m_Snap.currentDStar = min_val + opt_idx * ((max_val-min_val) / num_its);
}
// MITK_INFO << "choosing " << opt_idx << " => " << DStar;
// x_dstar_only[0] = 0.01;
// // f 0.1 Dstar 0.01 D 0.001
// vnl_levenberg_marquardt lm_dstar_only(f_dstar_only);
// lm_dstar_only.set_f_tolerance(0.0001);
// lm_dstar_only.minimize(x_dstar_only);
// DStar = x_dstar_only[0];
break;
}
case IVIM_REGULARIZED:
{
//m_Snap.high_meas, m_Snap.high_bvalues;
for(int i=0; i<m_Snap.Nhigh; i++)
{
m_Snap.high_meas[i] = m_Snap.meas[m_Snap.high_indices.at(i)];
}
MeasAndBvals input = ApplyS0Threshold(m_Snap.high_meas, m_Snap.high_bvalues);
vnl_vector< double > x_donly(2);
x_donly[0] = 0.001;
x_donly[1] = 0.1;
if(input.N >= 2)
{
IVIM_d_and_f f_donly(input.N);
f_donly.set_bvalues(input.bvals);
f_donly.set_measurements(input.meas);
//MITK_INFO << "initial fit N=" << input.N << ", min-b = " << input.bvals[0] << ", max-b = " << input.bvals[input.N-1];
vnl_levenberg_marquardt lm_donly(f_donly);
lm_donly.set_f_tolerance(0.0001);
lm_donly.minimize(x_donly);
}
typename InitialFitImageType::PixelType initvec;
initvec[0] = x_donly[1];
initvec[1] = x_donly[0];
initit.Set(initvec);
//MITK_INFO << "Init vox " << initit.GetIndex() << " with " << initvec[0] << "; " << initvec[1];
++initit;
int N = m_Snap.high_meas.size();
typename VectorImageType::PixelType vec(N);
for(int i=0; i<N; i++)
{
vec[i] = m_Snap.high_meas[i];
//MITK_INFO << "vec" << i << " = " << m_Snap.high_meas[i];
}
vecit.Set(vec);
++vecit;
if(!m_Verbose)
{
// report the middle voxel
if( vecit.GetIndex()[0] == m_CrossPosition[0]
&& vecit.GetIndex()[0] == m_CrossPosition[1]
&& vecit.GetIndex()[0] == m_CrossPosition[2] )
{
MeasAndBvals input = ApplyS0Threshold(m_Snap.high_meas, m_Snap.high_bvalues);
m_Snap.bvals1 = input.bvals;
m_Snap.meas1 = input.meas;
MeasAndBvals input2 = ApplyS0Threshold(m_Snap.meas, m_Snap.bvalues);
m_Snap.bvals2 = input2.bvals;
m_Snap.meas2 = input2.meas;
m_tmp_allmeas = m_Snap.allmeas;
}
}
break;
}
}
m_Snap.currentFunceiled = m_Snap.currentF;
IVIM_CEIL( m_Snap.currentF, 0.0, 1.0 );
oit.Set( m_Snap.currentF );
oit1.Set( m_Snap.currentD );
oit2.Set( m_Snap.currentDStar );
// std::cout << "\tf=" << x[0] << "\tD=" << x[1] << " ; "<<std::endl;
++oit;
++oit1;
++oit2;
++iit;
}
if(m_Verbose)
{
std::cout << "One Thread finished reconstruction" << std::endl;
}
}
template< class TIn, class TOut>
void DiffusionIntravoxelIncoherentMotionReconstructionImageFilter<TIn, TOut>
::AfterThreadedGenerateData()
{
if(m_Method == IVIM_REGULARIZED)
{
typename OutputImageType::Pointer outputImage =
static_cast< OutputImageType * >(this->ProcessObject::GetPrimaryOutput());
ImageRegionIterator< OutputImageType > oit0(outputImage, outputImage->GetLargestPossibleRegion());
oit0.GoToBegin();
typename OutputImageType::Pointer dImage =
static_cast< OutputImageType * >(this->ProcessObject::GetOutput(1));
ImageRegionIterator< OutputImageType > oit1(dImage, dImage->GetLargestPossibleRegion());
oit1.GoToBegin();
typename OutputImageType::Pointer dstarImage =
static_cast< OutputImageType * >(this->ProcessObject::GetOutput(2));
ImageRegionIterator< OutputImageType > oit2(dstarImage, dstarImage->GetLargestPossibleRegion());
oit2.GoToBegin();
typedef itk::RegularizedIVIMReconstructionFilter
<double,double,float> RegFitType;
RegFitType::Pointer filter = RegFitType::New();
filter->SetInput(m_InitialFitImage);
filter->SetReferenceImage(m_InternalVectorImage);
filter->SetBValues(m_Snap.high_bvalues);
filter->SetNumberIterations(m_NumberIterations);
filter->SetNumberOfThreads(1);
filter->SetLambda(m_Lambda);
filter->Update();
typename RegFitType::OutputImageType::Pointer outimg = filter->GetOutput();
ImageRegionConstIterator< RegFitType::OutputImageType > iit(outimg, outimg->GetLargestPossibleRegion());
iit.GoToBegin();
while( !iit.IsAtEnd() )
{
double f = iit.Get()[0];
IVIM_CEIL( f, 0.0, 1.0 );
oit0.Set( myround(f * 100.0) );
oit1.Set( myround(iit.Get()[1] * 10000.0) );
oit2.Set( myround(iit.Get()[2] * 1000.0) );
if(!m_Verbose)
{
// report the middle voxel
if( iit.GetIndex()[0] == m_CrossPosition[0]
&& iit.GetIndex()[1] == m_CrossPosition[1]
&& iit.GetIndex()[2] == m_CrossPosition[2] )
{
m_Snap.currentF = f;
m_Snap.currentD = iit.Get()[1];
m_Snap.currentDStar = iit.Get()[2];
m_Snap.allmeas = m_tmp_allmeas;
MITK_INFO << "setting " << f << ";" << iit.Get()[1] << ";" << iit.Get()[2];
}
}
++oit0;
++oit1;
++oit2;
++iit;
}
}
}
template< class TIn, class TOut>
double DiffusionIntravoxelIncoherentMotionReconstructionImageFilter<TIn, TOut>
::myround(double number)
{
return number < 0.0 ? ceil(number - 0.5) : floor(number + 0.5);
}
template< class TIn, class TOut>
void DiffusionIntravoxelIncoherentMotionReconstructionImageFilter<TIn, TOut>
::SetGradientDirections( GradientDirectionContainerType *gradientDirection )
{
this->m_GradientDirectionContainer = gradientDirection;
this->m_NumberOfGradientDirections = gradientDirection->Size();
}
template< class TIn, class TOut>
void DiffusionIntravoxelIncoherentMotionReconstructionImageFilter<TIn, TOut>
::PrintSelf(std::ostream& os, Indent indent) const
{
Superclass::PrintSelf(os,indent);
if ( m_GradientDirectionContainer )
{
os << indent << "GradientDirectionContainer: "
<< m_GradientDirectionContainer << std::endl;
}
else
{
os << indent <<
"GradientDirectionContainer: (Gradient directions not set)" << std::endl;
}
}
}
#endif // __itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter_cpp
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.h b/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.h
index b688d39..d97f4fd 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.h
@@ -1,381 +1,381 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter_h
#define __itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter_h
#include "itkImageToImageFilter.h"
//#include "vnl/vnl_matrix.h"
#include "vnl/vnl_vector_fixed.h"
#include "vnl/vnl_matrix.h"
#include "vnl/algo/vnl_svd.h"
#include "itkVectorContainer.h"
#include "itkVectorImage.h"
//#include "QuadProg.h"
#include "itkVectorImage.h"
#include "vnl/vnl_least_squares_function.h"
#include "vnl/algo/vnl_levenberg_marquardt.h"
#include "vnl/vnl_math.h"
#define IVIM_CEIL(val,u,o) (val) = \
( (val) < (u) ) ? ( (u) ) : ( ( (val)>(o) ) ? ( (o) ) : ( (val) ) );
namespace itk{
/** baseclass for IVIM fitting algorithms */
struct IVIM_base
{
void set_measurements(const vnl_vector<double>& x)
{
measurements.set_size(x.size());
measurements.copy_in(x.data_block());
}
void set_bvalues(const vnl_vector<double>& x)
{
bvalues.set_size(x.size());
bvalues.copy_in(x.data_block());
}
vnl_vector<double> measurements;
vnl_vector<double> bvalues;
int N;
};
/** Fitt all three parameters */
struct IVIM_3param : public IVIM_base, vnl_least_squares_function
{
IVIM_3param(unsigned int number_of_measurements) :
vnl_least_squares_function(3, number_of_measurements, no_gradient)
{
N = get_number_of_residuals();
}
void f(const vnl_vector<double>& x, vnl_vector<double>& fx) override {
double ef = x[0];
double D = x[1];
double Dstar = x[2];
for(int s=0; s<N; s++)
{
double approx = (1-ef)*exp(-bvalues[s]*D)+ef*exp(-bvalues[s]*(D+Dstar));
fx[s] = vnl_math_abs( measurements[s] - approx );
}
}
};
/** fit by setting DStar to a fix value */
struct IVIM_fixdstar : public IVIM_base, vnl_least_squares_function
{
IVIM_fixdstar(unsigned int number_of_measurements, double DStar) :
vnl_least_squares_function(2, number_of_measurements, no_gradient)
{
N = get_number_of_residuals();
fixDStar = DStar;
}
void f(const vnl_vector<double>& x, vnl_vector<double>& fx) override {
double ef = x[0];
double D = x[1];
for(int s=0; s<N; s++)
{
double approx = (1-ef)*exp(-bvalues[s]*D)+ef*exp(-bvalues[s]*(D+fixDStar));
fx[s] = vnl_math_abs( measurements[s] - approx );
}
}
double fixDStar;
};
/** fit a monoexponential curve only estimating D */
struct IVIM_d_and_f : public IVIM_base, vnl_least_squares_function
{
IVIM_d_and_f(unsigned int number_of_measurements) :
vnl_least_squares_function(2, number_of_measurements, no_gradient)
{
N = get_number_of_residuals();
}
void f(const vnl_vector<double>& x, vnl_vector<double>& fx) override {
double D = x[0];
double f = x[1];
for(int s=0; s<N; s++)
{
double approx = (1-f) * exp(-bvalues[s]*D);
fx[s] = vnl_math_abs( measurements[s] - approx );
}
}
};
/** fiting DStar and f with fix value of D */
struct IVIM_fixd : public IVIM_base, vnl_least_squares_function
{
IVIM_fixd(unsigned int number_of_measurements, double D) :
vnl_least_squares_function(2, number_of_measurements, no_gradient)
{
N = get_number_of_residuals();
fixD = D;
}
void f(const vnl_vector<double>& x, vnl_vector<double>& fx) override {
double ef = x[0];
double Dstar = x[1];
for(int s=0; s<N; s++)
{
double approx = (1-ef)*exp(-bvalues[s]*fixD)+ef*exp(-bvalues[s]*(fixD+Dstar));
fx[s] = vnl_math_abs( measurements[s] - approx );
}
}
double fixD;
};
/** fiting DStar with given f and D */
struct IVIM_dstar_only : public IVIM_base, vnl_least_squares_function
{
IVIM_dstar_only(unsigned int number_of_measurements, double D, double f) :
vnl_least_squares_function(1, number_of_measurements, no_gradient)
{
N = get_number_of_residuals();
fixD = D;
fixF = f;
}
void f(const vnl_vector<double>& x, vnl_vector<double>& fx) override {
double Dstar = x[0];
for(int s=0; s<N; s++)
{
double approx = (1-fixF)*exp(-bvalues[s]*fixD)+fixF*exp(-bvalues[s]*(fixD+Dstar));
fx[s] = vnl_math_abs( measurements[s] - approx );
}
}
double fixD;
double fixF;
};
struct MeasAndBvals
{
vnl_vector<double> meas;
vnl_vector<double> bvals;
int N;
};
/** \class DiffusionIntravoxelIncoherentMotionReconstructionImageFilter */
template< class TInputPixelType,
class TOutputPixelType>
class DiffusionIntravoxelIncoherentMotionReconstructionImageFilter :
public ImageToImageFilter< VectorImage< TInputPixelType, 3 >,
Image< TOutputPixelType, 3 > >
{
public:
struct IVIMSnapshot
{
double currentF;
double currentFunceiled;
double currentD;
double currentDStar;
bool iterated_sequence; // wether each measurement has its own b0-acqu.
std::vector<unsigned int> baselineind; // baseline image indicies
int N; // total number of measurements
std::vector<unsigned int> gradientind; // gradient image indicies
std::vector<double> bvals; // b-values != 0
vnl_vector<double> bvalues; // copy of bvalues != 0
vnl_vector<double> meas; // all measurements, thresholded blanked out
vnl_vector<double> allmeas; // all measurements
int Nhigh; // number of used measurements
std::vector<int> high_indices; // indices of used measurements
vnl_vector<double> high_bvalues; // bvals of used measurements
vnl_vector<double> high_meas; // used measurements
vnl_vector<double> meas1;
vnl_vector<double> bvals1;
vnl_vector<double> meas2;
vnl_vector<double> bvals2;
};
enum IVIM_Method
{
IVIM_FIT_ALL,
IVIM_DSTAR_FIX,
IVIM_D_THEN_DSTAR,
IVIM_LINEAR_D_THEN_F,
IVIM_REGULARIZED
};
typedef DiffusionIntravoxelIncoherentMotionReconstructionImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< VectorImage< TInputPixelType, 3>,
Image< TOutputPixelType,3 > > Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(DiffusionIntravoxelIncoherentMotionReconstructionImageFilter,
ImageToImageFilter);
typedef TOutputPixelType OutputPixelType;
typedef TInputPixelType InputPixelType;
/** Reference image data, This image is aquired in the absence
* of a diffusion sensitizing field gradient */
typedef typename Superclass::InputImageType InputImageType;
typedef Image< OutputPixelType, 3 > OutputImageType;
typedef typename Superclass::OutputImageRegionType
OutputImageRegionType;
/** Holds each magnetic field gradient used to acquire one DWImage */
typedef vnl_vector_fixed< double, 3 > GradientDirectionType;
/** Container to hold gradient directions of the 'n' DW measurements */
typedef VectorContainer< unsigned int,
GradientDirectionType > GradientDirectionContainerType;
// vector image typedefs for regularized fit
typedef itk::VectorImage<float,3> VectorImageType;
typedef itk::Image<itk::Vector<double, 3>, 3> InitialFitImageType;
/** set method to add gradient directions and its corresponding
* image. The image here is a VectorImage. The user is expected to pass the
* gradient directions in a container. The ith element of the container
* corresponds to the gradient direction of the ith component image the
* VectorImage. For the baseline image, a vector of all zeros
* should be set.*/
void SetGradientDirections( GradientDirectionContainerType * );
void SetBValue(double bval){m_BValue = bval;}
void SetBThres(double bval){m_BThres = bval;}
void SetS0Thres(double val){m_S0Thres = val;}
void SetDStar(double dstar){m_DStar = dstar;}
void SetFitDStar(bool fit){m_FitDStar = fit;}
void SetVerbose(bool verbose){m_Verbose = verbose;}
void SetNumberIterations(int num){m_NumberIterations = num;}
void SetLambda(double lambda){m_Lambda = lambda;}
void SetCrossPosition(typename InputImageType::IndexType crosspos){this->m_CrossPosition = crosspos;}
void SetMethod(IVIM_Method method){m_Method = method;}
IVIMSnapshot GetSnapshot(){return m_Snap;}
/** Return the gradient direction. idx is 0 based */
virtual GradientDirectionType GetGradientDirection( unsigned int idx) const
{
if( idx >= m_NumberOfGradientDirections )
{
itkExceptionMacro( << "Gradient direction " << idx << "does not exist" );
}
return m_GradientDirectionContainer->ElementAt( idx+1 );
}
protected:
DiffusionIntravoxelIncoherentMotionReconstructionImageFilter();
~DiffusionIntravoxelIncoherentMotionReconstructionImageFilter() {};
void PrintSelf(std::ostream& os, Indent indent) const;
void BeforeThreadedGenerateData();
void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread,
ThreadIdType);
void AfterThreadedGenerateData();
MeasAndBvals ApplyS0Threshold(vnl_vector<double> &meas, vnl_vector<double> &bvals);
private:
double myround(double number);
/** container to hold gradient directions */
GradientDirectionContainerType::Pointer m_GradientDirectionContainer;
/** Number of gradient measurements */
unsigned int m_NumberOfGradientDirections;
double m_BValue;
double m_BThres;
double m_S0Thres;
double m_DStar;
IVIM_Method m_Method;
typename OutputImageType::Pointer m_DMap;
typename OutputImageType::Pointer m_DStarMap;
bool m_FitDStar;
IVIMSnapshot m_Snap;
bool m_Verbose;
typename VectorImageType::Pointer m_InternalVectorImage;
typename InitialFitImageType::Pointer m_InitialFitImage;
int m_NumberIterations; // for total variation
vnl_vector<double> m_tmp_allmeas;
double m_Lambda;
typename InputImageType::IndexType m_CrossPosition;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.cpp"
#endif
#endif //__itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter_h
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionKurtosisReconstructionImageFilter.cxx b/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionKurtosisReconstructionImageFilter.cxx
index 9e03a0e..37c66c7 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionKurtosisReconstructionImageFilter.cxx
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionKurtosisReconstructionImageFilter.cxx
@@ -1,484 +1,484 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 DIFFUSIONKURTOSISRECONSTRUCTIONIMAGEFILTER_CXX
#define DIFFUSIONKURTOSISRECONSTRUCTIONIMAGEFILTER_CXX
#include "itkDiffusionKurtosisReconstructionImageFilter.h"
#include <itkImageRegionConstIterator.h>
#include <itkImageRegionConstIteratorWithIndex.h>
#include <itkImageRegionIteratorWithIndex.h>
#include <itkImageRegionIterator.h>
#include <itkVectorIndexSelectionCastImageFilter.h>
#include <itkComposeImageFilter.h>
#include <itkDiscreteGaussianImageFilter.h>
template< class TInputPixelType>
static void FitSingleVoxel( const itk::VariableLengthVector< TInputPixelType > &input,
const vnl_vector<double>& bvalues,
vnl_vector<double>& result,
itk::KurtosisFitConfiguration kf_config)
{
// check for length
assert( input.Size() == bvalues.size() );
// assembly data vectors for fitting
auto bvalueIter = bvalues.begin();
unsigned int unused_values = 0;
while( bvalueIter != bvalues.end() )
{
if( *bvalueIter < vnl_math::eps && kf_config.omit_bzero )
{
++unused_values;
}
++bvalueIter;
}
// initialize data vectors with the estimated size (after filtering)
vnl_vector<double> fit_measurements( input.Size() - unused_values, 0 );
vnl_vector<double> fit_bvalues( input.Size() - unused_values, 0 );
bvalueIter = bvalues.begin();
unsigned int running_index = 0;
unsigned int skip_count = 0;
while( bvalueIter != bvalues.end() )
{
// skip b=0 if the corresponding flag is set
if( ( kf_config.omit_bzero && *bvalueIter < vnl_math::eps )
// skip bvalues higher than the limit provided, if the flag is activated
|| ( kf_config.exclude_high_b && *bvalueIter > kf_config.b_upper_threshold ) )
{
++skip_count;
}
else
{
fit_measurements[ running_index - skip_count ] = input.GetElement(running_index);
fit_bvalues[ running_index - skip_count] = *bvalueIter;
}
++running_index;
++bvalueIter;
}
MITK_DEBUG("KurtosisFilter.FitSingleVoxel.Meas") << fit_measurements;
MITK_DEBUG("KurtosisFilter.FitSingleVoxel.Bval") << fit_bvalues;
// perform fit on data vectors
if( kf_config.omit_bzero )
{
itk::kurtosis_fit_omit_unweighted kurtosis_cost_fn( fit_measurements.size() );
// configuration
kurtosis_cost_fn.set_fit_logscale( static_cast<bool>(kf_config.fit_scale) );
kurtosis_cost_fn.initialize( fit_measurements, fit_bvalues );
if( kf_config.use_K_limits)
{
kurtosis_cost_fn.set_K_bounds( kf_config.K_limits );
}
vnl_levenberg_marquardt nonlinear_fit( kurtosis_cost_fn );
nonlinear_fit.minimize( result );
}
else
{
itk::kurtosis_fit_lsq_function kurtosis_cost_fn( fit_measurements.size() );
// configuration
kurtosis_cost_fn.set_fit_logscale( static_cast<bool>(kf_config.fit_scale) );
kurtosis_cost_fn.initialize( fit_measurements, fit_bvalues );
if( kf_config.use_K_limits)
{
kurtosis_cost_fn.set_K_bounds( kf_config.K_limits );
}
vnl_levenberg_marquardt nonlinear_fit( kurtosis_cost_fn );
nonlinear_fit.minimize(result);
}
MITK_DEBUG("KurtosisFilter.FitSingleVoxel.Rslt") << result;
}
template< class TInputPixelType, class TOutputPixelType>
itk::DiffusionKurtosisReconstructionImageFilter<TInputPixelType, TOutputPixelType>
::DiffusionKurtosisReconstructionImageFilter()
: m_ReferenceBValue(-1),
m_OmitBZero(false),
m_ApplyPriorSmoothing(false),
m_SmoothingSigma(1.5),
m_UseKBounds( false ),
m_MaxFitBValue( 3000 ),
m_ScaleForFitting( STRAIGHT )
{
this->m_InitialPosition = vnl_vector<double>(3, 0);
this->m_InitialPosition[2] = 1000.0; // S_0
this->m_InitialPosition[0] = 0.001; // D
this->m_InitialPosition[1] = 1; // K
this->m_KurtosisBounds.fill(0);
// single input image
this->SetNumberOfRequiredInputs(1);
// two output images (D, K)
this->SetNumberOfRequiredOutputs(2);
typename OutputImageType::Pointer outputPtr1 = OutputImageType::New();
typename OutputImageType::Pointer outputPtr2 = OutputImageType::New();
this->SetNthOutput(0, outputPtr1.GetPointer() );
this->SetNthOutput(1, outputPtr2.GetPointer() );
}
template< class TInputPixelType, class TOutputPixelType>
void itk::DiffusionKurtosisReconstructionImageFilter<TInputPixelType, TOutputPixelType>
::GenerateOutputInformation()
{
// first call superclass
Superclass::GenerateOutputInformation();
}
template< class TInputPixelType, class TOutputPixelType>
void itk::DiffusionKurtosisReconstructionImageFilter<TInputPixelType, TOutputPixelType>
::SetImageMask(MaskImageType::Pointer mask)
{
this->m_MaskImage = mask;
}
template< class TInputPixelType, class TOutputPixelType>
void itk::DiffusionKurtosisReconstructionImageFilter<TInputPixelType, TOutputPixelType>
::BeforeThreadedGenerateData()
{
// if we have a region set, convert it to a mask image, which is to be used as default for telling
// we need to set the image anyway, so by default the mask is overall 1
if( m_MaskImage.IsNull() )
{
m_MaskImage = MaskImageType::New();
m_MaskImage->SetRegions( this->GetInput()->GetLargestPossibleRegion() );
m_MaskImage->CopyInformation( this->GetInput() );
m_MaskImage->Allocate();
if( this->m_MapOutputRegion.GetNumberOfPixels() > 0 )
{
m_MaskImage->FillBuffer(0);
typedef itk::ImageRegionIteratorWithIndex< MaskImageType > MaskIteratorType;
MaskIteratorType maskIter( this->m_MaskImage, this->m_MapOutputRegion );
maskIter.GoToBegin();
while( !maskIter.IsAtEnd() )
{
maskIter.Set( 1 );
++maskIter;
}
}
else
{
m_MaskImage->FillBuffer(1);
}
}
// apply smoothing to the input image
if( this->m_ApplyPriorSmoothing )
{
// filter typedefs
typedef itk::DiscreteGaussianImageFilter< itk::Image<TInputPixelType, 3 >, itk::Image<TInputPixelType, 3 > > GaussianFilterType;
typedef itk::VectorIndexSelectionCastImageFilter< InputImageType, itk::Image<TInputPixelType, 3 > > IndexSelectionType;
typedef itk::ComposeImageFilter< itk::Image<TInputPixelType, 3>, InputImageType > ComposeFilterType;
auto vectorImage = this->GetInput();
typename IndexSelectionType::Pointer indexSelectionFilter = IndexSelectionType::New();
indexSelectionFilter->SetInput( vectorImage );
typename ComposeFilterType::Pointer vec_composer = ComposeFilterType::New();
for( unsigned int i=0; i<vectorImage->GetVectorLength(); ++i)
{
typename GaussianFilterType::Pointer gaussian_filter = GaussianFilterType::New();
indexSelectionFilter->SetIndex( i );
gaussian_filter->SetInput( indexSelectionFilter->GetOutput() );
gaussian_filter->SetVariance( m_SmoothingSigma );
vec_composer->SetInput(i, gaussian_filter->GetOutput() );
gaussian_filter->Update();
}
try
{
vec_composer->Update();
}
catch(const itk::ExceptionObject &e)
{
mitkThrow() << "[VectorImage.GaussianSmoothing] !! Failed with ITK Exception: " << e.what();
}
this->m_ProcessedInputImage = vec_composer->GetOutput();
}
else
{
this->m_ProcessedInputImage = const_cast<InputImageType*>( this->GetInput() );
}
}
template< class TInputPixelType, class TOutputPixelType>
void itk::DiffusionKurtosisReconstructionImageFilter<TInputPixelType, TOutputPixelType>
::AfterThreadedGenerateData()
{
/* // initialize buffer to zero overall, but don't forget the requested region pointer
for( unsigned int i=0; i<this->GetNumberOfOutputs(); ++i)
{
typename OutputImageType::Pointer output = this->GetOutput(i);
// after generating, set the buffered region to max, we have taken care about filling it with valid data in
// UpdateOutputInformation, if not set, a writer (or any filter using the LargestPossibleRegion() during update may
// complain about not getting the requested region
output->SetBufferedRegion( output->GetLargestPossibleRegion() );
std::cout << "[DiffusionKurtosisReconstructionImageFilter.After]" << output->GetLargestPossibleRegion() << std::endl;
}*/
}
template< class TInputPixelType, class TOutputPixelType>
typename itk::DiffusionKurtosisReconstructionImageFilter<TInputPixelType, TOutputPixelType>::KurtosisSnapshot
itk::DiffusionKurtosisReconstructionImageFilter<TInputPixelType, TOutputPixelType>
::GetSnapshot(const itk::VariableLengthVector<TInputPixelType> &input, GradientDirectionContainerType::Pointer gradients, float bvalue, KurtosisFitConfiguration kf_conf)
{
// initialize bvalues from reference value and the gradients provided on input
this->SetReferenceBValue(bvalue);
this->SetGradientDirections( gradients );
// call the other method
return this->GetSnapshot( input, this->m_BValues, kf_conf );
}
template< class TInputPixelType, class TOutputPixelType>
typename itk::DiffusionKurtosisReconstructionImageFilter<TInputPixelType, TOutputPixelType>::KurtosisSnapshot
itk::DiffusionKurtosisReconstructionImageFilter<TInputPixelType, TOutputPixelType>
::GetSnapshot(const itk::VariableLengthVector<TInputPixelType> &input, vnl_vector<double> bvalues, KurtosisFitConfiguration kf_conf)
{
// initialize
vnl_vector<double> initial_position;
bool omit_bzero = kf_conf.omit_bzero;
if( !omit_bzero )
{
initial_position.set_size(2);
initial_position[0] = this->m_InitialPosition[0];
initial_position[1] = this->m_InitialPosition[1];
}
else
{
initial_position.set_size(3);
initial_position = this->m_InitialPosition;
}
// fit
FitSingleVoxel( input, bvalues, initial_position, kf_conf );
// assembly result snapshot
KurtosisSnapshot result;
result.m_D = initial_position[0];
result.m_K = initial_position[1];
if( omit_bzero )
{
result.m_f = 1 - initial_position[2] / std::fmax(0.01, input.GetElement(0));
result.m_BzeroFit = initial_position[2];
}
else
result.m_f = 1;
// assembly data vectors for fitting
auto bvalueIter = bvalues.begin();
unsigned int unused_values = 0;
while( bvalueIter != bvalues.end() )
{
if( *bvalueIter < vnl_math::eps && omit_bzero )
{
++unused_values;
}
++bvalueIter;
}
// initialize data vectors with the estimated size (after filtering)
vnl_vector<double> fit_measurements( input.Size() - unused_values, 0 );
vnl_vector<double> fit_bvalues( input.Size() - unused_values, 0 );
// original data
vnl_vector<double> orig_measurements( input.Size(), 0 );
bvalueIter = bvalues.begin();
unsigned int running_index = 0;
unsigned int skip_count = 0;
while( bvalueIter != bvalues.end() )
{
if( *bvalueIter < vnl_math::eps && omit_bzero )
{
++skip_count;
}
else
{
fit_measurements[ running_index - skip_count ] = input.GetElement(running_index);
fit_bvalues[ running_index - skip_count ] = *bvalueIter;
}
orig_measurements[ running_index ] = input.GetElement(running_index);
++running_index;
++bvalueIter;
}
result.fit_bvalues = fit_bvalues;
result.fit_measurements = fit_measurements;
result.bvalues = bvalues;
result.measurements = orig_measurements;
result.m_fittedBZero = omit_bzero;
return result;
}
template< class TInputPixelType, class TOutputPixelType>
void itk::DiffusionKurtosisReconstructionImageFilter<TInputPixelType, TOutputPixelType>
::SetGradientDirections(GradientDirectionContainerType::Pointer gradients)
{
if( this->m_ReferenceBValue < 0)
{
itkExceptionMacro( << "Specify reference b-value prior to setting the gradient directions." );
}
if( gradients->Size() == 0 )
{
itkExceptionMacro( << "Empty gradient directions container retrieved" );
}
vnl_vector<double> vnl_bvalues( gradients->Size(), 0 );
// initialize the b-values
auto grIter = gradients->Begin();
unsigned int index = 0;
while( grIter != gradients->End() )
{
const double twonorm = grIter.Value().two_norm();
vnl_bvalues( index++ ) = this->m_ReferenceBValue * twonorm * twonorm;
++grIter;
}
this->m_BValues = vnl_bvalues;
}
template< class TInputPixelType, class TOutputPixelType>
void itk::DiffusionKurtosisReconstructionImageFilter<TInputPixelType, TOutputPixelType>
::SetInitialSolution(const vnl_vector<double>& x0 )
{
assert( x0.size() == (2 + static_cast<int>( this->m_OmitBZero )) );
this->m_InitialPosition = x0;
}
template< class TInputPixelType, class TOutputPixelType>
void itk::DiffusionKurtosisReconstructionImageFilter<TInputPixelType, TOutputPixelType>
::ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, ThreadIdType /*threadId*/)
{
typename OutputImageType::Pointer dImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0));
itk::ImageRegionIteratorWithIndex< OutputImageType > dImageIt(dImage, outputRegionForThread);
dImageIt.GoToBegin();
typename OutputImageType::Pointer kImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(1));
itk::ImageRegionIteratorWithIndex< OutputImageType > kImageIt(kImage, outputRegionForThread);
kImageIt.GoToBegin();
typedef itk::ImageRegionConstIteratorWithIndex< InputImageType > InputIteratorType;
InputIteratorType inputIter( m_ProcessedInputImage, outputRegionForThread );
inputIter.GoToBegin();
typedef itk::ImageRegionConstIteratorWithIndex< MaskImageType > MaskIteratorType;
MaskIteratorType maskIter( this->m_MaskImage, outputRegionForThread );
maskIter.GoToBegin();
KurtosisFitConfiguration fit_config;
fit_config.omit_bzero = this->m_OmitBZero;
fit_config.fit_scale = this->m_ScaleForFitting;
fit_config.use_K_limits = this->m_UseKBounds;
fit_config.K_limits = this->m_KurtosisBounds;
vnl_vector<double> initial_position;
if( !this->m_OmitBZero )
{
initial_position.set_size(2);
initial_position[0] = this->m_InitialPosition[0];
initial_position[1] = this->m_InitialPosition[1];
}
else
{
initial_position.set_size(3);
initial_position = this->m_InitialPosition;
}
while( !inputIter.IsAtEnd() )
{
// set (reset) each iteration
vnl_vector<double> result = initial_position;
// fit single voxel (if inside mask )
if( maskIter.Get() > 0 )
{
FitSingleVoxel( inputIter.Get(), this->m_BValues, result, fit_config );
}
else
{
result.fill(0);
}
// regardless the fit type, the parameters are always in the first two position
// of the results vector
dImageIt.Set( result[0] );
kImageIt.Set( result[1] );
//std::cout << "[Kurtosis.Fit]" << inputIter.GetIndex() << " --> " << dImageIt.GetIndex() << " result: " << result << std::endl;
++maskIter;
++inputIter;
++dImageIt;
++kImageIt;
}
}
#endif // guards
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionKurtosisReconstructionImageFilter.h b/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionKurtosisReconstructionImageFilter.h
index d5d07b2..734c040 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionKurtosisReconstructionImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionKurtosisReconstructionImageFilter.h
@@ -1,442 +1,442 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 DIFFUSIONKURTOSISRECONSTRUCTIONIMAGEFILTER_H
#define DIFFUSIONKURTOSISRECONSTRUCTIONIMAGEFILTER_H
#include "itkImageToImageFilter.h"
#include "itkVectorImage.h"
#include "mitkDiffusionPropertyHelper.h"
// vnl includes
#include <vnl/algo/vnl_levenberg_marquardt.h>
#include <vnl/vnl_least_squares_function.h>
namespace itk
{
// Fitting routines
/** @struct Kurtosis_fit_lsq_function
@brief A base least-squares function for the diffusion kurtosis fit (non-IVIM)
The basic function fits the signal to S_0 = S * exp [ -b * D + -b^2 * D^2 * K^2 ]
*/
struct kurtosis_fit_lsq_function :
public vnl_least_squares_function
{
public:
/** full lsq_function constructor */
kurtosis_fit_lsq_function( unsigned int num_params, unsigned int num_measurements, UseGradient g=no_gradient)
: vnl_least_squares_function( num_params, num_measurements, g),
m_use_bounds(false),
m_use_logscale(false),
m_skip_fit(false)
{}
/** simplified constructor for the 2-parameters fit */
kurtosis_fit_lsq_function( unsigned int number_measurements)
: kurtosis_fit_lsq_function( 2, number_measurements, no_gradient )
{}
/** Initialize the function by setting measurements and the corresponding b-values */
void initialize( vnl_vector< double > const& _meas, vnl_vector< double> const& _bvals )
{
meas = _meas;
if( m_use_logscale )
{
for( unsigned int i=0; i< meas.size(); ++i)
{
// would produce NaN values, skip the fit
// using the virtual function from the superclass (sets a boolean flag)
if( meas[i] < vnl_math::eps )
{
m_skip_fit = true;
throw_failure();
continue;
}
meas[i] = log( meas[i] );
}
}
bvalues = _bvals;
}
/** use penalty terms on fitting to force the parameters stay within the default bounds */
void use_bounds()
{
m_use_bounds = true;
// initialize bounds
double upper_bounds[2] = {4e-3, 4 };
kurtosis_upper_bounds = vnl_vector<double>(2, 2, upper_bounds);
kurtosis_lower_bounds = vnl_vector<double>(2, 0);
}
void set_fit_logscale( bool flag )
{
this->m_use_logscale = flag;
}
void set_K_bounds( const vnl_vector_fixed<double, 2> k_bounds )
{
// init
this->use_bounds();
// override K bounds
kurtosis_lower_bounds[1] = k_bounds[0];
kurtosis_upper_bounds[1] = k_bounds[1];
}
virtual void f(const vnl_vector<double> &x, vnl_vector<double> &fx)
{
for ( unsigned int s=0; s < fx.size(); s++ )
{
const double factor = ( meas[s] - M(x, s) );
fx[s] = factor * factor + penalty_term(x);
}
MITK_DEBUG("Fit.x_and_f") << x << " | " << fx;
}
protected:
/** Formula for diffusion term, use for internal computations */
double Diff( double x1, double x2, double b)
{
const double quotient = -1. * b * x1 + b*b * x1 * x1 * x2 / 6;
if( m_use_logscale )
return quotient;
else
return exp(quotient);
}
/** The fitting measurement function, has to be reimplemented in the classes */
virtual double M( vnl_vector<double> const& x, unsigned int idx )
{
const double bvalue = bvalues[idx];
double result = Diff( x[0], x[1], bvalue);
if( m_use_logscale )
return meas[0] + result;
else
return meas[0] * result ;
}
/** Penalty term on D and K during fitting, make sure the vector that is passed in contains (D, K) in this ordering */
virtual double penalty_term( vnl_vector<double> const& x)
{
double penalty = 0;
// skip when turned off
if( !m_use_bounds )
return penalty;
// we have bounds for D and K only (the first two params )
for( unsigned int i=0; i< 2; i++)
{
// 5% penalty boundary
// use exponential function to scale the penalty (max when x[i] == bounds )
double penalty_boundary = 0.02 * (kurtosis_upper_bounds[i] - kurtosis_lower_bounds[i]);
if( x[i] < kurtosis_lower_bounds[i] + penalty_boundary )
{
penalty += 1e6 * exp( -1 * ( x[i] - kurtosis_lower_bounds[i]) / penalty_boundary );
}
else if ( x[i] > kurtosis_upper_bounds[i] - penalty_boundary )
{
penalty += 1e6 * exp( -1 * ( kurtosis_upper_bounds[i] - x[i]) / penalty_boundary );
}
}
MITK_DEBUG("Fit.Orig.Penalty") << x << " || penalty: " << penalty;
return penalty;
}
bool m_use_bounds;
bool m_use_logscale;
bool m_skip_fit;
vnl_vector<double> kurtosis_upper_bounds;
vnl_vector<double> kurtosis_lower_bounds;
vnl_vector<double> meas;
vnl_vector<double> bvalues;
};
/** @struct kurtosis_fit_omit_unweighted
@brief A fitting function handling the unweighted signal b_0 as a fitted parameter */
struct kurtosis_fit_omit_unweighted
: public kurtosis_fit_lsq_function
{
public:
/** simplified constructor for the 3-parameters fit */
kurtosis_fit_omit_unweighted( unsigned int number_measurements)
: kurtosis_fit_lsq_function( 3, number_measurements, no_gradient )
{}
protected:
virtual double M(const vnl_vector<double> &x, unsigned int idx) override
{
const double bvalue = bvalues[idx];
double result = Diff( x[0], x[1], bvalue);
if( m_use_logscale )
return log( x[2] ) + result;
else
return x[2] * result ;
}
};
enum FitScale
{
STRAIGHT = 0,
LOGARITHMIC
};
struct KurtosisFitConfiguration
{
KurtosisFitConfiguration()
: omit_bzero(false)
, use_K_limits(false)
, exclude_high_b(false)
, b_upper_threshold(10e9)
{}
bool omit_bzero;
FitScale fit_scale;
bool use_K_limits;
vnl_vector_fixed<double, 2> K_limits;
bool exclude_high_b;
double b_upper_threshold;
};
/**
@class DiffusionKurtosisReconstructionImageFilter
@brief This filter provides the fit of the kurtosis (non-IVIM) signal to the data
It has two main modes of operation, either as an image filter to compute the D and K maps, i.e. fitting the values to each voxel or a computation on a single voxel
or a voxel group (with mask) can be triggered by @sa GetSnapshot, GetCurrentSnapshot methods.
*/
template< class TInputPixelType, class TOutputPixelType >
class DiffusionKurtosisReconstructionImageFilter :
public ImageToImageFilter< VectorImage< TInputPixelType, 3>, Image<TOutputPixelType, 3> >
{
public:
/**
@struct KurtosisSnapshot
@brief Struct describing a result (and the data) of a Kurtosis model fit
*/
struct KurtosisSnapshot
{
KurtosisSnapshot()
: m_f(1), m_BzeroFit(1), m_D(0.001), m_K(0) {}
// input data structures
//vnl_vector<double> filtered_measurements;
vnl_vector<double> bvalues;
vnl_vector<double> measurements;
vnl_vector<double> fit_bvalues;
vnl_vector<double> fit_measurements;
vnl_vector<unsigned int> weighted_image_indices;
bool m_fittedBZero;
// variables holding the fitted values
double m_f;
double m_BzeroFit;
double m_D;
double m_K;
};
//-- class typedefs
typedef DiffusionKurtosisReconstructionImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< VectorImage< TInputPixelType, 3>,
Image< TOutputPixelType,3 > > Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(DiffusionKurtosisReconstructionImageFilter, ImageToImageFilter)
typedef TOutputPixelType OutputPixelType;
typedef TInputPixelType InputPixelType;
typedef typename Superclass::InputImageType InputImageType;
typedef Image< OutputPixelType, 3 > OutputImageType;
typedef itk::Image< short , 3> MaskImageType;
typedef typename Superclass::OutputImageRegionType OutputImageRegionType;
/** Holds each magnetic field gradient used to acquire one DWImage */
typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType
GradientDirectionContainerType;
// vector image typedefs for regularized fit
typedef itk::VectorImage<float,3> VectorImageType;
typedef itk::Image<itk::Vector<double, 3>, 3> InitialFitImageType;
//-- input (Set) methods
/** Set the initial solution for fitting, make sure the length and the values correspond to the parameters
* x0 = ( S_0, ADC_0, AKC_0 ) when also the S_0 is estimated
* x0 = ( ADC_0, AKC_0 ) when the S_0 is used in fitting
*/
void SetInitialSolution(const vnl_vector<double>& x0 );
/** Set whether the S_0 value is fitted or used in fitting */
void SetOmitUnweightedValue( bool flag)
{ this->m_OmitBZero = flag; }
/**
Trigger a single computation of the Kurtosis values from the given input vector and the bvalues and returns the result as a KurtosisSnapshot object */
KurtosisSnapshot GetSnapshot( const itk::VariableLengthVector< TInputPixelType > &input, vnl_vector<double> bvalues, KurtosisFitConfiguration kf_conf);
/**
Trigger a single computation of the kurtosis values, first the bvalues vector is computed internally but then also stored into the returend snapshot */
KurtosisSnapshot GetSnapshot( const itk::VariableLengthVector< TInputPixelType > &input, GradientDirectionContainerType::Pointer, float bvalue, KurtosisFitConfiguration kf_conf);
/**
* Returns the value of the current data presented to the filter.
If a mask is set, the voxels are first averaged before passed to the fitting procedure
*/
KurtosisSnapshot GetCurrentSnapshot(bool omit_bzero);
/** Set the reference bvalue of the input DW image */
void SetReferenceBValue( double bvalue )
{ this->m_ReferenceBValue = bvalue; }
/** Set the gradient directions */
void SetGradientDirections( GradientDirectionContainerType::Pointer gradients );
/** Restrict map generation to an image region */
void SetMapOutputRegion( OutputImageRegionType region )
{
m_MapOutputRegion = region;
this->m_ApplyPriorSmoothing = true;
}
void SetImageMask( MaskImageType::Pointer mask );
/** Set smoothing sigma (default = 1.5 ), automatically enables smoothing prior to fitting */
void SetSmoothingSigma( double sigma )
{
this->m_SmoothingSigma = sigma;
this->m_ApplyPriorSmoothing = true;
}
/** Activate/Deactivate the gaussian smoothing applied to the input prior to fitting ( default = off ) */
void SetUseSmoothingPriorToFitting( bool flag)
{
this->m_ApplyPriorSmoothing = flag;
}
/** Set boundaries enforced by penalty terms in the fitting procedure */
void SetBoundariesForKurtosis( double lower, double upper )
{
m_UseKBounds = true;
m_KurtosisBounds[0] = lower; m_KurtosisBounds[1] = upper;
}
/** Exclude measurements associated with b-values higher than max_bvalue from fitting */
void SetMaximalBValueUsedForFitting( double max_bvalue )
{
m_MaxFitBValue = max_bvalue;
}
/** Select the method used in fitting of the data
STRAIHT - fit the exponential signal equation S / S_0 = exp [ ... ]
LOGARITHMIC - fit the logarithmic signal equation ln( S / S_0 ) = []
*/
void SetFittingScale( FitScale scale )
{
m_ScaleForFitting = scale;
}
protected:
DiffusionKurtosisReconstructionImageFilter();
virtual ~DiffusionKurtosisReconstructionImageFilter() {}
void GenerateOutputInformation() override;
void AfterThreadedGenerateData() override;
void BeforeThreadedGenerateData() override;
void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, ThreadIdType threadId) override;
double m_ReferenceBValue;
vnl_vector<double> m_BValues;
vnl_vector<double> m_InitialPosition;
bool m_OmitBZero;
OutputImageRegionType m_MapOutputRegion;
MaskImageType::Pointer m_MaskImage;
typename InputImageType::Pointer m_ProcessedInputImage;
bool m_ApplyPriorSmoothing;
double m_SmoothingSigma;
bool m_UseKBounds;
vnl_vector_fixed<double, 2> m_KurtosisBounds;
double m_MaxFitBValue;
FitScale m_ScaleForFitting;
private:
};
} //end namespace itk
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkDiffusionKurtosisReconstructionImageFilter.cxx"
#endif
#endif // DIFFUSIONKURTOSISRECONSTRUCTIONIMAGEFILTER_H
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionMultiShellQballReconstructionImageFilter.cpp b/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionMultiShellQballReconstructionImageFilter.cpp
index 39e7b3f..b18010e 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionMultiShellQballReconstructionImageFilter.cpp
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionMultiShellQballReconstructionImageFilter.cpp
@@ -1,1261 +1,1261 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkDiffusionMultiShellQballReconstructionImageFilter_cpp
#define __itkDiffusionMultiShellQballReconstructionImageFilter_cpp
#include <itkDiffusionMultiShellQballReconstructionImageFilter.h>
#include <itkTimeProbe.h>
#include <itkPointShell.h>
#include <mitkDiffusionFunctionCollection.h>
namespace itk {
template< class T, class TG, class TO, int L, int NODF>
DiffusionMultiShellQballReconstructionImageFilter<T,TG,TO,L,NODF>
::DiffusionMultiShellQballReconstructionImageFilter() :
m_ReconstructionType(Mode_Standard1Shell),
m_Interpolation_Flag(false),
m_Interpolation_SHT1_inv(nullptr),
m_Interpolation_SHT2_inv(nullptr),
m_Interpolation_SHT3_inv(nullptr),
m_TARGET_SH_shell1(nullptr),
m_TARGET_SH_shell2(nullptr),
m_TARGET_SH_shell3(nullptr),
m_MaxDirections(0),
m_CoeffReconstructionMatrix(nullptr),
m_ODFSphericalHarmonicBasisMatrix(nullptr),
m_GradientDirectionContainer(nullptr),
m_NumberOfGradientDirections(0),
m_NumberOfBaselineImages(0),
m_Threshold(0),
m_BZeroImage(nullptr),
m_CoefficientImage(nullptr),
m_BValue(1.0),
m_Lambda(0.0),
m_IsHemisphericalArrangementOfGradientDirections(false),
m_IsArithmeticProgession(false)
{
// At least 1 inputs is necessary for a vector image.
// For images added one at a time we need at least six
this->SetNumberOfRequiredInputs( 1 );
}
template< class T, class TG, class TO, int L, int NODF>
void DiffusionMultiShellQballReconstructionImageFilter<T,TG,TO,L,NODF>
::SetGradientImage(const GradientDirectionContainerType *gradientDirection
, const GradientImagesType *gradientImage
, float bvalue)
{
m_BValue = bvalue;
m_NumberOfBaselineImages = 0;
this->m_GradientDirectionContainer = GradientDirectionContainerType::New();
for(GradientDirectionContainerType::ConstIterator it = gradientDirection->Begin();
it != gradientDirection->End(); it++)
{
this->m_GradientDirectionContainer->push_back(it.Value());
}
if(m_BValueMap.size() == 0){
itkWarningMacro(<< "DiffusionMultiShellQballReconstructionImageFilter.cpp : no GradientIndexMapAvalible");
GradientDirectionContainerType::ConstIterator gdcit;
for( gdcit = m_GradientDirectionContainer->Begin(); gdcit != m_GradientDirectionContainer->End(); ++gdcit)
{
double bValueKey = int(((m_BValue * gdcit.Value().two_norm() * gdcit.Value().two_norm())+7.5)/10)*10;
MITK_INFO << bValueKey;
m_BValueMap[bValueKey].push_back(gdcit.Index());
}
}
if(m_BValueMap.find(0) == m_BValueMap.end())
{
itkExceptionMacro(<< "DiffusionMultiShellQballReconstructionImageFilter.cpp : GradientIndxMap with no b-Zero indecies found: check input BValueMap");
}
m_NumberOfBaselineImages = m_BValueMap[0].size();
m_NumberOfGradientDirections = gradientDirection->Size() - m_NumberOfBaselineImages;
// ensure that the gradient image we received has as many components as
// the number of gradient directions
if( gradientImage->GetVectorLength() != m_NumberOfBaselineImages + m_NumberOfGradientDirections )
{
itkExceptionMacro( << m_NumberOfGradientDirections << " gradients + " << m_NumberOfBaselineImages
<< "baselines = " << m_NumberOfGradientDirections + m_NumberOfBaselineImages
<< " directions specified but image has " << gradientImage->GetVectorLength()
<< " components.");
}
ProcessObject::SetNthInput( 0, const_cast< GradientImagesType* >(gradientImage) );
std::string gradientImageClassName(ProcessObject::GetInput(0)->GetNameOfClass());
if ( strcmp(gradientImageClassName.c_str(),"VectorImage") != 0 )
itkExceptionMacro( << "There is only one Gradient image. I expect that to be a VectorImage. But its of type: " << gradientImageClassName );
m_BZeroImage = BZeroImageType::New();
typename GradientImagesType::Pointer img = static_cast< GradientImagesType * >( ProcessObject::GetInput(0) );
m_BZeroImage->SetSpacing( img->GetSpacing() ); // Set the image spacing
m_BZeroImage->SetOrigin( img->GetOrigin() ); // Set the image origin
m_BZeroImage->SetDirection( img->GetDirection() ); // Set the image direction
m_BZeroImage->SetLargestPossibleRegion( img->GetLargestPossibleRegion());
m_BZeroImage->SetBufferedRegion( img->GetLargestPossibleRegion() );
m_BZeroImage->Allocate();
m_CoefficientImage = CoefficientImageType::New();
m_CoefficientImage->SetSpacing( img->GetSpacing() ); // Set the image spacing
m_CoefficientImage->SetOrigin( img->GetOrigin() ); // Set the image origin
m_CoefficientImage->SetDirection( img->GetDirection() ); // Set the image direction
m_CoefficientImage->SetLargestPossibleRegion( img->GetLargestPossibleRegion());
m_CoefficientImage->SetBufferedRegion( img->GetLargestPossibleRegion() );
m_CoefficientImage->Allocate();
}
template<class TReferenceImagePixelType, class TGradientImagePixelType, class TOdfPixelType, int NOrderL, int NrOdfDirections>
void DiffusionMultiShellQballReconstructionImageFilter<TReferenceImagePixelType, TGradientImagePixelType, TOdfPixelType,NOrderL, NrOdfDirections>
::Normalize( OdfPixelType & out)
{
for(int i=0; i<NrOdfDirections; i++)
{
out[i] = out[i] < 0 ? 0 : out[i];
out[i] *= itk::Math::pi * 4 / NrOdfDirections;
}
}
template<class TReferenceImagePixelType, class TGradientImagePixelType, class TOdfPixelType, int NOrderL, int NrOdfDirections>
void DiffusionMultiShellQballReconstructionImageFilter<TReferenceImagePixelType, TGradientImagePixelType, TOdfPixelType,NOrderL, NrOdfDirections>
::Projection1(vnl_vector<double> & vec, double delta)
{
if (delta==0){ //Clip attenuation values. If att<0 => att=0, if att>1 => att=1
for (unsigned int i=0; i<vec.size(); i++)
vec[i]=(vec[i]>=0 && vec[i]<=1)*vec[i]+(vec[i]>1);
}
else{ //Use function from Aganj et al, MRM, 2010
for (unsigned int i=0; i< vec.size(); i++)
vec[i]=CalculateThreashold(vec[i], delta);
}
}
template<class TReferenceImagePixelType, class TGradientImagePixelType, class TOdfPixelType, int NOrderL, int NrOdfDirections>
double DiffusionMultiShellQballReconstructionImageFilter<TReferenceImagePixelType, TGradientImagePixelType, TOdfPixelType,NOrderL, NrOdfDirections>
::CalculateThreashold(const double value, const double delta)
{
return (value<0)*(0.5*delta) + (value>=0 && value<delta)*(0.5*delta+0.5*(value*value)/delta)
+ (value>=delta && value<1-delta)*value+(value>=1-delta && value<1)*(1-0.5*delta-0.5*((1-value)*(1-value))/delta)
+ (value>=1)*(1-0.5*delta);
}
template<class TReferenceImagePixelType, class TGradientImagePixelType, class TOdfPixelType, int NOrderL, int NrOdfDirections>
void DiffusionMultiShellQballReconstructionImageFilter<TReferenceImagePixelType, TGradientImagePixelType, TOdfPixelType,NOrderL, NrOdfDirections>
::Projection2( vnl_vector<double> & E1,vnl_vector<double> & E2, vnl_vector<double> & E3, double delta )
{
const double sF = sqrt(5.0);
vnl_vector<double> vOnes(m_MaxDirections);
vOnes.fill(1.0);
vnl_matrix<double> T0(m_MaxDirections, 3);
vnl_matrix<unsigned char> C(m_MaxDirections, 7);
vnl_matrix<double> A(m_MaxDirections, 7);
vnl_matrix<double> B(m_MaxDirections, 7);
vnl_vector<double> s0(m_MaxDirections);
vnl_vector<double> a0(m_MaxDirections);
vnl_vector<double> b0(m_MaxDirections);
vnl_vector<double> ta(m_MaxDirections);
vnl_vector<double> tb(m_MaxDirections);
vnl_vector<double> e(m_MaxDirections);
vnl_vector<double> m(m_MaxDirections);
vnl_vector<double> a(m_MaxDirections);
vnl_vector<double> b(m_MaxDirections);
// logarithmierung aller werte in E
for(unsigned int i = 0 ; i < m_MaxDirections; i++)
{
T0(i,0) = -log(E1(i));
T0(i,1) = -log(E2(i));
T0(i,2) = -log(E3(i));
}
//T0 = -T0.apply(std::log);
// Summeiere Zeilenweise über alle Shells sum = E1+E2+E3
for(unsigned int i = 0 ; i < m_MaxDirections; i++)
{
s0[i] = T0(i,0) + T0(i,1) + T0(i,2);
}
for(unsigned int i = 0; i < m_MaxDirections; i ++)
{
// Alle Signal-Werte auf der Ersten shell E(N,0) normiert auf s0
a0[i] = T0(i,0) / s0[i];
// Alle Signal-Werte auf der Zweiten shell E(N,1) normiert auf s0
b0[i] = T0(i,1) / s0[i];
}
ta = a0 * 3.0;
tb = b0 * 3.0;
e = tb - (ta * 2.0);
m = (tb * 2.0 ) + ta;
for(unsigned int i = 0; i <m_MaxDirections; i++)
{
C(i,0) = (tb[i] < 1+3*delta && 0.5+1.5*(sF+1)*delta < ta[i] && ta[i] < 1-3* (sF+2) *delta);
C(i,1) = (e[i] <= -1+3*(2*sF+5)*delta) && (ta[i]>=1-3*(sF+2)*delta);
C(i,2) = (m[i] > 3-3*sF*delta) && (-1+3*(2*sF+5)*delta<e[i]) && (e[i]<-3*sF*delta);
C(i,3) = (m[i] >= 3-3*sF*delta && e[i] >= -3 *sF * delta);
C(i,4) = (2.5 + 1.5*(5+sF)*delta < m[i] && m[i] < 3-3*sF*delta && e[i] > -3*sF*delta);
C(i,5) = (ta[i] <= 0.5+1.5 *(sF+1)*delta && m[i] <= 2.5 + 1.5 *(5+sF) * delta);
C(i,6) = !((bool) C(i,0) ||(bool) C(i,1) ||(bool) C(i,2) ||(bool) C(i,3) ||(bool) C(i,4) ||(bool) C(i,5) ); // ~ANY(C(i,[0-5] ),2)
A(i,0)=(bool)C(i,0) * a0(i);
A(i,1)=(bool)C(i,1) * (1.0/3.0-(sF+2)*delta);
A(i,2)=(bool)C(i,2) * (0.2+0.8*a0(i)-0.4*b0(i)-delta/sF);
A(i,3)=(bool)C(i,3) * (0.2+delta/sF);
A(i,4)=(bool)C(i,4) * (0.2*a0(i)+0.4*b0(i)+2*delta/sF);
A(i,5)=(bool)C(i,5) * (1.0/6.0+0.5*(sF+1)*delta);
A(i,6)=(bool)C(i,6) * a0(i);
B(i,0)=(bool)C(i,0) * (1.0/3.0+delta);
B(i,1)=(bool)C(i,1) * (1.0/3.0+delta);
B(i,2)=(bool)C(i,2) * (0.4-0.4*a0(i)+0.2*b0(i)-2*delta/sF);
B(i,3)=(bool)C(i,3) * (0.4-3*delta/sF);
B(i,4)=(bool)C(i,4) * (0.4*a0(i)+0.8*b0(i)-delta/sF);
B(i,5)=(bool)C(i,5) * (1.0/3.0+delta);
B(i,6)=(bool)C(i,6) * b0(i);
}
for(unsigned int i = 0 ; i < m_MaxDirections; i++)
{
double sumA = 0;
double sumB = 0;
for(int j = 0 ; j < 7; j++)
{
sumA += A(i,j);
sumB += B(i,j);
}
a[i] = sumA;
b[i] = sumB;
}
for(unsigned int i = 0; i < m_MaxDirections; i++)
{
E1(i) = exp(-(a[i]*s0[i]));
E2(i) = exp(-(b[i]*s0[i]));
E3(i) = exp(-((1-a[i]-b[i])*s0[i]));
}
}
template<class TReferenceImagePixelType, class TGradientImagePixelType, class TOdfPixelType, int NOrderL, int NrOdfDirections>
void DiffusionMultiShellQballReconstructionImageFilter<TReferenceImagePixelType, TGradientImagePixelType, TOdfPixelType,NOrderL, NrOdfDirections>
::Projection3( vnl_vector<double> & A, vnl_vector<double> & a, vnl_vector<double> & b, double delta0)
{
const double s6 = sqrt(6.0);
const double s15 = s6/2.0;
vnl_vector<double> delta(a.size());
delta.fill(delta0);
vnl_matrix<double> AM(a.size(), 15);
vnl_matrix<double> aM(a.size(), 15);
vnl_matrix<double> bM(a.size(), 15);
vnl_matrix<unsigned char> B(a.size(), 15);
AM.set_column(0, A);
AM.set_column(1, A);
AM.set_column(2, A);
AM.set_column(3, delta);
AM.set_column(4, (A+a-b - (delta*s6))/3.0);
AM.set_column(5, delta);
AM.set_column(6, delta);
AM.set_column(7, delta);
AM.set_column(8, A);
AM.set_column(9, 0.2*(a*2+A-2*(s6+1)*delta));
AM.set_column(10,0.2*(b*(-2)+A+2-2*(s6+1)*delta));
AM.set_column(11, delta);
AM.set_column(12, delta);
AM.set_column(13, delta);
AM.set_column(14, 0.5-(1+s15)*delta);
aM.set_column(0, a);
aM.set_column(1, a);
aM.set_column(2, -delta + 1);
aM.set_column(3, a);
aM.set_column(4, (A*2+a*5+b+s6*delta)/6.0);
aM.set_column(5, a);
aM.set_column(6, -delta + 1);
aM.set_column(7, 0.5*(a+b)+(1+s15)*delta);
aM.set_column(8, -delta + 1);
aM.set_column(9, 0.2*(a*4+A*2+(s6+1)*delta));
aM.set_column(10, -delta + 1);
aM.set_column(11, (s6+3)*delta);
aM.set_column(12, -delta + 1);
aM.set_column(13, -delta + 1);
aM.set_column(14, -delta + 1);
bM.set_column(0, b);
bM.set_column(1, delta);
bM.set_column(2, b);
bM.set_column(3, b);
bM.set_column(4, (A*(-2)+a+b*5-s6*delta)/6.0);
bM.set_column(5, delta);
bM.set_column(6, b);
bM.set_column(7, 0.5*(a+b)-(1+s15)*delta);
bM.set_column(8, delta);
bM.set_column(9, delta);
bM.set_column(10, 0.2*(b*4-A*2+1-(s6+1)*delta));
bM.set_column(11, delta);
bM.set_column(12, delta);
bM.set_column(13, -delta*(s6+3) + 1);
bM.set_column(14, delta);
delta0 *= 0.99;
vnl_matrix<double> R2(a.size(), 15);
std::vector<unsigned int> I(a.size());
for (unsigned int i=0; i<AM.rows(); i++){
for (unsigned int j=0; j<AM.cols(); j++){
if (delta0 < AM(i,j) && 2*(AM(i,j)+delta0*s15)<aM(i,j)-bM(i,j) && bM(i,j)>delta0 && aM(i,j)<1-delta0)
R2(i,j) = (AM(i,j)-A(i))*(AM(i,j)-A(i))+ (aM(i,j)-a(i))*(aM(i,j)-a(i))+(bM(i,j)-b(i))*(bM(i,j)-b(i));
else
R2(i,j) = 1e20;
}
unsigned int index = 0;
double minvalue = 999;
for(int j = 0 ; j < 15 ; j++)
{
if(R2(i,j) < minvalue){
minvalue = R2(i,j);
index = j;
}
}
I[i] = index;
}
for (unsigned int i=0; i < A.size(); i++){
A(i) = AM(i,(int)I[i]);
a(i) = aM(i,(int)I[i]);
b(i) = bM(i,(int)I[i]);
}
}
template<class TReferenceImagePixelType, class TGradientImagePixelType, class TOdfPixelType, int NOrderL, int NrOdfDirections>
void DiffusionMultiShellQballReconstructionImageFilter<TReferenceImagePixelType, TGradientImagePixelType, TOdfPixelType,NOrderL, NrOdfDirections>
::S_S0Normalization( vnl_vector<double> & vec, double S0 )
{
for(unsigned int i = 0; i < vec.size(); i++)
{
if (S0==0)
S0 = 0.01;
vec[i] /= S0;
}
}
template< class T, class TG, class TO, int L, int NODF>
void DiffusionMultiShellQballReconstructionImageFilter<T,TG,TO,L,NODF>
::DoubleLogarithm(vnl_vector<double> & vec)
{
for(unsigned int i = 0; i < vec.size(); i++)
{
vec[i] = log(-log(vec[i]));
}
}
template< class T, class TG, class TO, int L, int NODF>
void DiffusionMultiShellQballReconstructionImageFilter<T,TG,TO,L,NODF>
::AfterThreadedGenerateData()
{
MITK_INFO << "Finished reconstruction";
}
template< class T, class TG, class TO, int L, int NODF>
void DiffusionMultiShellQballReconstructionImageFilter<T,TG,TO,L,NODF>
::BeforeThreadedGenerateData()
{
m_ReconstructionType = Mode_Standard1Shell;
if(m_BValueMap.size() == 4 ){
BValueMapIteraotr it = m_BValueMap.begin();
it++; // skip b0 entry
const unsigned int bValue_shell1 = it->first;
const unsigned int size_shell1 = it->second.size();
IndiciesVector shell1 = it->second;
it++;
const unsigned int bValue_shell2 = it->first;
const unsigned int size_shell2 = it->second.size();
IndiciesVector shell2 = it->second;
it++;
const unsigned int bValue_shell3 = it->first;
const unsigned int size_shell3 = it->second.size();
IndiciesVector shell3 = it->second;
// arithmetic progrssion
if(bValue_shell2 - bValue_shell1 == bValue_shell1 && bValue_shell3 - bValue_shell2 == bValue_shell1 )
{
// check if Interpolation is needed
// if shells with different numbers of directions exist
m_Interpolation_Flag = false;
if(size_shell1 != size_shell2 || size_shell2 != size_shell3 || size_shell1 != size_shell3)
{
m_Interpolation_Flag = true;
MITK_INFO << "Shell interpolation: shells with different numbers of directions";
}
else
{
// else if each shell holds same numbers of directions, but the gradient direction differ more than one 1 degree
m_Interpolation_Flag = CheckForDifferingShellDirections();
if(m_Interpolation_Flag) MITK_INFO << "Shell interpolation: gradient direction differ more than one 1 degree";
}
m_ReconstructionType = Mode_Analytical3Shells;
if(m_Interpolation_Flag)
{
unsigned int interp_SHOrder_shell1 = 12;
while( ((interp_SHOrder_shell1+1)*(interp_SHOrder_shell1+2)/2) > size_shell1 && interp_SHOrder_shell1 > L )
interp_SHOrder_shell1 -= 2 ;
const int number_coeffs_shell1 = (int)(interp_SHOrder_shell1*interp_SHOrder_shell1 + interp_SHOrder_shell1 + 2.0)/2.0 + interp_SHOrder_shell1;
unsigned int interp_SHOrder_shell2 = 12;
while( ((interp_SHOrder_shell2+1)*(interp_SHOrder_shell2+2)/2) > size_shell2 && interp_SHOrder_shell2 > L )
interp_SHOrder_shell2 -= 2 ;
const int number_coeffs_shell2 = (int)(interp_SHOrder_shell2*interp_SHOrder_shell2 + interp_SHOrder_shell2 + 2.0)/2.0 + interp_SHOrder_shell2;
unsigned int interp_SHOrder_shell3 = 12;
while( ((interp_SHOrder_shell3+1)*(interp_SHOrder_shell3+2)/2) > size_shell3 && interp_SHOrder_shell3 > L )
interp_SHOrder_shell3 -= 2 ;
const int number_coeffs_shell3 = (int)(interp_SHOrder_shell3*interp_SHOrder_shell3 + interp_SHOrder_shell3 + 2.0)/2.0 + interp_SHOrder_shell3;
// Create direction container for all directions (no duplicates, different directions from all shells)
IndiciesVector all_directions_container = GetAllDirections();
m_MaxDirections = all_directions_container.size();
// create target SH-Basis
// initialize empty target matrix and set the wanted directions
vnl_matrix<double> * Q = new vnl_matrix<double>(3, m_MaxDirections);
ComputeSphericalFromCartesian(Q, all_directions_container);
// initialize a SH Basis, neede to interpolate from oldDirs -> newDirs
m_TARGET_SH_shell1 = new vnl_matrix<double>(m_MaxDirections, number_coeffs_shell1);
ComputeSphericalHarmonicsBasis(Q, m_TARGET_SH_shell1, interp_SHOrder_shell1);
delete Q;
Q = new vnl_matrix<double>(3, m_MaxDirections);
ComputeSphericalFromCartesian(Q, all_directions_container);
m_TARGET_SH_shell2 = new vnl_matrix<double>(m_MaxDirections, number_coeffs_shell2);
ComputeSphericalHarmonicsBasis(Q, m_TARGET_SH_shell2, interp_SHOrder_shell2);
delete Q;
Q = new vnl_matrix<double>(3, m_MaxDirections);
ComputeSphericalFromCartesian(Q, all_directions_container);
m_TARGET_SH_shell3 = new vnl_matrix<double>(m_MaxDirections, number_coeffs_shell3);
ComputeSphericalHarmonicsBasis(Q, m_TARGET_SH_shell3, interp_SHOrder_shell3);
delete Q;
// end creat target SH-Basis
// create measured-SHBasis
// Shell 1
vnl_matrix<double> * tempSHBasis;
vnl_matrix_inverse<double> * temp;
// initialize empty matrix and set the measured directions of shell1
Q = new vnl_matrix<double>(3, shell1.size());
ComputeSphericalFromCartesian(Q, shell1);
// initialize a SH Basis, need to get the coeffs from measuredShell
tempSHBasis = new vnl_matrix<double>(shell1.size(), number_coeffs_shell1);
ComputeSphericalHarmonicsBasis(Q, tempSHBasis, interp_SHOrder_shell1);
// inversion of the SH=Basis
// c_s1 = B^-1 * shell1
// interp_Values = targetSHBasis * c_s1
// Values = m_TARGET_SH_shell1 * Interpolation_SHT1_inv * DataShell1;
temp = new vnl_matrix_inverse<double>((*tempSHBasis));
m_Interpolation_SHT1_inv = new vnl_matrix<double>(temp->inverse());
delete Q;
delete temp;
delete tempSHBasis;
// Shell 2
Q = new vnl_matrix<double>(3, shell2.size());
ComputeSphericalFromCartesian(Q, shell2);
tempSHBasis = new vnl_matrix<double>(shell2.size(), number_coeffs_shell2);
ComputeSphericalHarmonicsBasis(Q, tempSHBasis, interp_SHOrder_shell2);
temp = new vnl_matrix_inverse<double>((*tempSHBasis));
m_Interpolation_SHT2_inv = new vnl_matrix<double>(temp->inverse());
delete Q;
delete temp;
delete tempSHBasis;
// Shell 3
Q = new vnl_matrix<double>(3, shell3.size());
ComputeSphericalFromCartesian(Q, shell3);
tempSHBasis = new vnl_matrix<double>(shell3.size(), number_coeffs_shell3);
ComputeSphericalHarmonicsBasis(Q, tempSHBasis, interp_SHOrder_shell3);
temp = new vnl_matrix_inverse<double>((*tempSHBasis));
m_Interpolation_SHT3_inv = new vnl_matrix<double>(temp->inverse());
delete Q;
delete temp;
delete tempSHBasis;
ComputeReconstructionMatrix(all_directions_container);
MITK_INFO << "Reconstruction information: Multishell Reconstruction filter - Interpolation";
MITK_INFO << "Shell 1";
MITK_INFO << " SHOrder: " << interp_SHOrder_shell1;
MITK_INFO << " Number of Coeffs: " << number_coeffs_shell1;
MITK_INFO << " Number of Gradientdirections: " << size_shell1;
MITK_INFO << "Shell 2";
MITK_INFO << " SHOrder: " << interp_SHOrder_shell2;
MITK_INFO << " Number of Coeffs: " << number_coeffs_shell2;
MITK_INFO << " Number of Gradientdirections: " << size_shell2;
MITK_INFO << "Shell 3";
MITK_INFO << " SHOrder: " << interp_SHOrder_shell3;
MITK_INFO << " Number of Coeffs: " << number_coeffs_shell3;
MITK_INFO << " Number of Gradientdirections: " << size_shell3;
MITK_INFO << "Overall";
MITK_INFO << " SHOrder: " << L;
MITK_INFO << " Number of Coeffs: " << (L+1)*(L+2)*0.5;
MITK_INFO << " Number of Gradientdirections: " << m_MaxDirections;
return;
}else
{
ComputeReconstructionMatrix(shell1);
}
}
}
if(m_BValueMap.size() > 2 && m_ReconstructionType != Mode_Analytical3Shells)
{
m_ReconstructionType = Mode_NumericalNShells;
}
if(m_BValueMap.size() == 2){
BValueMapIteraotr it = m_BValueMap.begin();
it++; // skip b0 entry
IndiciesVector shell = it->second;
ComputeReconstructionMatrix(shell);
}
}
template< class T, class TG, class TO, int L, int NODF>
void DiffusionMultiShellQballReconstructionImageFilter<T,TG,TO,L,NODF>
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, ThreadIdType /*NumberOfThreads*/)
{
itk::TimeProbe clock;
clock.Start();
switch(m_ReconstructionType)
{
case Mode_Standard1Shell:
StandardOneShellReconstruction(outputRegionForThread);
break;
case Mode_Analytical3Shells:
AnalyticalThreeShellReconstruction(outputRegionForThread);
break;
case Mode_NumericalNShells:
break;
}
clock.Stop();
}
template< class T, class TG, class TO, int L, int NODF>
void DiffusionMultiShellQballReconstructionImageFilter<T,TG,TO,L,NODF>
::StandardOneShellReconstruction(const OutputImageRegionType& outputRegionForThread)
{
// Get output image pointer
typename OdfImageType::Pointer outputImage = static_cast< OdfImageType * >(ProcessObject::GetPrimaryOutput());
// Get input gradient image pointer
typename GradientImagesType::Pointer gradientImagePointer = static_cast< GradientImagesType * >( ProcessObject::GetInput(0) );
// ImageRegionIterator for the output image
ImageRegionIterator< OdfImageType > oit(outputImage, outputRegionForThread);
oit.GoToBegin();
// ImageRegionIterator for the BZero (output) image
ImageRegionIterator< BZeroImageType > bzeroIterator(m_BZeroImage, outputRegionForThread);
bzeroIterator.GoToBegin();
// Const ImageRegionIterator for input gradient image
typedef ImageRegionConstIterator< GradientImagesType > GradientIteratorType;
GradientIteratorType git(gradientImagePointer, outputRegionForThread );
git.GoToBegin();
BValueMapIteraotr it = m_BValueMap.begin();
it++; // skip b0 entry
IndiciesVector SignalIndicies = it->second;
IndiciesVector BZeroIndicies = m_BValueMap[0];
unsigned int NumbersOfGradientIndicies = SignalIndicies.size();
typedef typename GradientImagesType::PixelType GradientVectorType;
// iterate overall voxels of the gradient image region
while( ! git.IsAtEnd() )
{
GradientVectorType b = git.Get();
// ODF Vector
OdfPixelType odf(0.0);
double b0average = 0;
const unsigned int b0size = BZeroIndicies.size();
for(unsigned int i = 0; i < b0size ; ++i)
{
b0average += b[BZeroIndicies[i]];
}
b0average /= b0size;
bzeroIterator.Set(b0average);
++bzeroIterator;
// Create the Signal Vector
vnl_vector<double> SignalVector(NumbersOfGradientIndicies);
if( (b0average != 0) && (b0average >= m_Threshold) )
{
for( unsigned int i = 0; i< SignalIndicies.size(); i++ )
{
SignalVector[i] = static_cast<double>(b[SignalIndicies[i]]);
}
// apply threashold an generate ln(-ln(E)) signal
// Replace SignalVector with PreNormalized SignalVector
S_S0Normalization(SignalVector, b0average);
Projection1(SignalVector);
DoubleLogarithm(SignalVector);
// approximate ODF coeffs
vnl_vector<double> coeffs = ( (*m_CoeffReconstructionMatrix) * SignalVector );
coeffs[0] = 1.0/(2.0*sqrt(itk::Math::pi));
odf = element_cast<double, TO>(( (*m_ODFSphericalHarmonicBasisMatrix) * coeffs )).data_block();
odf *= (itk::Math::pi*4/NODF);
}
// set ODF to ODF-Image
oit.Set( odf );
++oit;
++git;
}
}
//#include "itkLevenbergMarquardtOptimizer.h"
template< class T, class TG, class TO, int L, int NODF>
void DiffusionMultiShellQballReconstructionImageFilter<T,TG,TO,L,NODF>
::NumericalNShellReconstruction(const OutputImageRegionType& /*outputRegionForThread*/)
{
/* itk::LevenbergMarquardtOptimizer::Pointer optimizer = itk::LevenbergMarquardtOptimizer::New();
optimizer->SetUseCostFunctionGradient(false);
// Scale the translation components of the Transform in the Optimizer
itk::LevenbergMarquardtOptimizer::ScalesType scales(transform->GetNumberOfParameters());
scales.Fill(0.01);
unsigned long numberOfIterations = 80000;
double gradientTolerance = 1e-10; // convergence criterion
double valueTolerance = 1e-10; // convergence criterion
double epsilonFunction = 1e-10; // convergence criterion
optimizer->SetScales( scales );
optimizer->SetNumberOfIterations( numberOfIterations );
optimizer->SetValueTolerance( valueTolerance );
optimizer->SetGradientTolerance( gradientTolerance );
optimizer->SetEpsilonFunction( epsilonFunction );*/
}
template< class T, class TG, class TO, int L, int NODF>
void DiffusionMultiShellQballReconstructionImageFilter<T,TG,TO,L,NODF>
::AnalyticalThreeShellReconstruction(const OutputImageRegionType& outputRegionForThread)
{
// Input Gradient Image and Output ODF Image
typedef typename GradientImagesType::PixelType GradientVectorType;
typename OdfImageType::Pointer outputImage = static_cast< OdfImageType * >(ProcessObject::GetPrimaryOutput());
typename GradientImagesType::Pointer gradientImagePointer = static_cast< GradientImagesType * >( ProcessObject::GetInput(0) );
// Define Image iterators
ImageRegionIterator< OdfImageType > odfOutputImageIterator(outputImage, outputRegionForThread);
ImageRegionConstIterator< GradientImagesType > gradientInputImageIterator(gradientImagePointer, outputRegionForThread );
ImageRegionIterator< BZeroImageType > bzeroIterator(m_BZeroImage, outputRegionForThread);
ImageRegionIterator< CoefficientImageType > coefficientImageIterator(m_CoefficientImage, outputRegionForThread);
// All iterators seht to Begin of the specific OutputRegion
coefficientImageIterator.GoToBegin();
bzeroIterator.GoToBegin();
odfOutputImageIterator.GoToBegin();
gradientInputImageIterator.GoToBegin();
// Get Shell Indicies for all non-BZero Gradients
// it MUST be a arithmetic progression eg.: 1000, 2000, 3000
BValueMapIteraotr it = m_BValueMap.begin();
it++;
// it = b-value = 1000
IndiciesVector Shell1Indiecies = it->second;
it++;
// it = b-value = 2000
IndiciesVector Shell2Indiecies = it->second;
it++;
// it = b-value = 3000
IndiciesVector Shell3Indiecies = it->second;
IndiciesVector BZeroIndicies = m_BValueMap[0];
if(!m_Interpolation_Flag)
{
m_MaxDirections = Shell1Indiecies.size();
}// else: m_MaxDirection is set in BeforeThreadedGenerateData
// Nx3 Signal Matrix with E(0) = Shell 1, E(1) = Shell 2, E(2) = Shell 3
vnl_vector< double > E1(m_MaxDirections);
vnl_vector< double > E2(m_MaxDirections);
vnl_vector< double > E3(m_MaxDirections);
vnl_vector<double> AlphaValues(m_MaxDirections);
vnl_vector<double> BetaValues(m_MaxDirections);
vnl_vector<double> LAValues(m_MaxDirections);
vnl_vector<double> PValues(m_MaxDirections);
vnl_vector<double> DataShell1(Shell1Indiecies.size());
vnl_vector<double> DataShell2(Shell2Indiecies.size());
vnl_vector<double> DataShell3(Shell3Indiecies.size());
vnl_matrix<double> tempInterpolationMatrixShell1,tempInterpolationMatrixShell2,tempInterpolationMatrixShell3;
if(m_Interpolation_Flag)
{
tempInterpolationMatrixShell1 = (*m_TARGET_SH_shell1) * (*m_Interpolation_SHT1_inv);
tempInterpolationMatrixShell2 = (*m_TARGET_SH_shell2) * (*m_Interpolation_SHT2_inv);
tempInterpolationMatrixShell3 = (*m_TARGET_SH_shell3) * (*m_Interpolation_SHT3_inv);
}
OdfPixelType odf(0.0);
typename CoefficientImageType::PixelType coeffPixel(0.0);
double P2,A,B2,B,P,alpha,beta,lambda, ER1, ER2;
// iterate overall voxels of the gradient image region
while( ! gradientInputImageIterator.IsAtEnd() )
{
odf = 0.0;
coeffPixel = 0.0;
GradientVectorType b = gradientInputImageIterator.Get();
// calculate for each shell the corresponding b0-averages
double shell1b0Norm =0;
double shell2b0Norm =0;
double shell3b0Norm =0;
double b0average = 0;
const unsigned int b0size = BZeroIndicies.size();
if(b0size == 1)
{
shell1b0Norm = b[BZeroIndicies[0]];
shell2b0Norm = b[BZeroIndicies[0]];
shell3b0Norm = b[BZeroIndicies[0]];
b0average = b[BZeroIndicies[0]];
}else if(b0size % 3 ==0)
{
for(unsigned int i = 0; i < b0size ; ++i)
{
if(i < b0size / 3) shell1b0Norm += b[BZeroIndicies[i]];
if(i >= b0size / 3 && i < (b0size / 3)*2) shell2b0Norm += b[BZeroIndicies[i]];
if(i >= (b0size / 3) * 2) shell3b0Norm += b[BZeroIndicies[i]];
}
shell1b0Norm /= (b0size/3);
shell2b0Norm /= (b0size/3);
shell3b0Norm /= (b0size/3);
b0average = (shell1b0Norm + shell2b0Norm+ shell3b0Norm)/3;
}else
{
for(unsigned int i = 0; i <b0size ; ++i)
{
shell1b0Norm += b[BZeroIndicies[i]];
}
shell1b0Norm /= b0size;
shell2b0Norm = shell1b0Norm;
shell3b0Norm = shell1b0Norm;
b0average = shell1b0Norm;
}
bzeroIterator.Set(b0average);
++bzeroIterator;
if( (b0average != 0) && ( b0average >= m_Threshold) )
{
// Get the Signal-Value for each Shell at each direction (specified in the ShellIndicies Vector .. this direction corresponse to this shell...)
/*//fsl fix ---------------------------------------------------
for(int i = 0 ; i < Shell1Indiecies.size(); i++)
DataShell1[i] = static_cast<double>(b[Shell1Indiecies[i]]);
for(int i = 0 ; i < Shell2Indiecies.size(); i++)
DataShell2[i] = static_cast<double>(b[Shell2Indiecies[i]]);
for(int i = 0 ; i < Shell3Indiecies.size(); i++)
DataShell3[i] = static_cast<double>(b[Shell2Indiecies[i]]);
// Normalize the Signal: Si/S0
S_S0Normalization(DataShell1, shell1b0Norm);
S_S0Normalization(DataShell2, shell2b0Norm);
S_S0Normalization(DataShell3, shell2b0Norm);
*///fsl fix -------------------------------------------ende--
///correct version
for(unsigned int i = 0 ; i < Shell1Indiecies.size(); i++)
DataShell1[i] = static_cast<double>(b[Shell1Indiecies[i]]);
for(unsigned int i = 0 ; i < Shell2Indiecies.size(); i++)
DataShell2[i] = static_cast<double>(b[Shell2Indiecies[i]]);
for(unsigned int i = 0 ; i < Shell3Indiecies.size(); i++)
DataShell3[i] = static_cast<double>(b[Shell3Indiecies[i]]);
// Normalize the Signal: Si/S0
S_S0Normalization(DataShell1, shell1b0Norm);
S_S0Normalization(DataShell2, shell2b0Norm);
S_S0Normalization(DataShell3, shell3b0Norm);
if(m_Interpolation_Flag)
{
E1 = tempInterpolationMatrixShell1 * DataShell1;
E2 = tempInterpolationMatrixShell2 * DataShell2;
E3 = tempInterpolationMatrixShell3 * DataShell3;
}else{
E1 = (DataShell1);
E2 = (DataShell2);
E3 = (DataShell3);
}
//Implements Eq. [19] and Fig. 4.
Projection1(E1);
Projection1(E2);
Projection1(E3);
//inqualities [31]. Taking the lograithm of th first tree inqualities
//convert the quadratic inqualities to linear ones.
Projection2(E1,E2,E3);
for( unsigned int i = 0; i< m_MaxDirections; i++ )
{
double e1 = E1.get(i);
double e2 = E2.get(i);
double e3 = E3.get(i);
P2 = e2-e1*e1;
A = (e3 -e1*e2) / ( 2* P2);
B2 = A * A -(e1 * e3 - e2 * e2) /P2;
B = 0;
if(B2 > 0) B = sqrt(B2);
P = 0;
if(P2 > 0) P = sqrt(P2);
alpha = A + B;
beta = A - B;
PValues.put(i, P);
AlphaValues.put(i, alpha);
BetaValues.put(i, beta);
}
Projection3(PValues, AlphaValues, BetaValues);
for(unsigned int i = 0 ; i < m_MaxDirections; i++)
{
const double fac = (PValues[i] * 2 ) / (AlphaValues[i] - BetaValues[i]);
lambda = 0.5 + 0.5 * std::sqrt(1 - fac * fac);;
ER1 = std::fabs(lambda * (AlphaValues[i] - BetaValues[i]) + (BetaValues[i] - E1.get(i) ))
+ std::fabs(lambda * (AlphaValues[i] * AlphaValues[i] - BetaValues[i] * BetaValues[i]) + (BetaValues[i] * BetaValues[i] - E2.get(i) ))
+ std::fabs(lambda * (AlphaValues[i] * AlphaValues[i] * AlphaValues[i] - BetaValues[i] * BetaValues[i] * BetaValues[i]) + (BetaValues[i] * BetaValues[i] * BetaValues[i] - E3.get(i) ));
ER2 = std::fabs((1-lambda) * (AlphaValues[i] - BetaValues[i]) + (BetaValues[i] - E1.get(i) ))
+ std::fabs((1-lambda) * (AlphaValues[i] * AlphaValues[i] - BetaValues[i] * BetaValues[i]) + (BetaValues[i] * BetaValues[i] - E2.get(i) ))
+ std::fabs((1-lambda) * (AlphaValues[i] * AlphaValues[i] * AlphaValues[i] - BetaValues[i] * BetaValues[i] * BetaValues[i]) + (BetaValues[i] * BetaValues[i] * BetaValues[i] - E3.get(i)));
if(ER1 < ER2)
LAValues.put(i, lambda);
else
LAValues.put(i, 1-lambda);
}
DoubleLogarithm(AlphaValues);
DoubleLogarithm(BetaValues);
vnl_vector<double> SignalVector(element_product((LAValues) , (AlphaValues)-(BetaValues)) + (BetaValues));
vnl_vector<double> coeffs((*m_CoeffReconstructionMatrix) *SignalVector );
// the first coeff is a fix value
coeffs[0] = 1.0/(2.0*sqrt(itk::Math::pi));
coeffPixel = element_cast<double, TO>(coeffs).data_block();
// Cast the Signal-Type from double to float for the ODF-Image
odf = element_cast<double, TO>( (*m_ODFSphericalHarmonicBasisMatrix) * coeffs ).data_block();
odf *= ((itk::Math::pi*4)/NODF);
}
// set ODF to ODF-Image
coefficientImageIterator.Set(coeffPixel);
odfOutputImageIterator.Set( odf );
++odfOutputImageIterator;
++coefficientImageIterator;
++gradientInputImageIterator;
}
}
template< class T, class TG, class TO, int L, int NODF>
void DiffusionMultiShellQballReconstructionImageFilter<T, TG, TO, L, NODF>::
ComputeSphericalHarmonicsBasis(vnl_matrix<double> * QBallReference, vnl_matrix<double> *SHBasisOutput, int LOrder , vnl_matrix<double>* LaplaciaBaltramiOutput, vnl_vector<int>* SHOrderAssociation, vnl_matrix<double>* SHEigenvalues)
{
for(unsigned int i=0; i< (*SHBasisOutput).rows(); i++)
{
for(int k = 0; k <= LOrder; k += 2)
{
for(int m =- k; m <= k; m++)
{
int j = ( k * k + k + 2 ) / 2 + m - 1;
// Compute SHBasisFunctions
if(QBallReference){
double phi = (*QBallReference)(0,i);
double th = (*QBallReference)(1,i);
(*SHBasisOutput)(i,j) = mitk::sh::Yj(m,k,th,phi);
}
// Laplacian Baltrami Order Association
if(LaplaciaBaltramiOutput)
(*LaplaciaBaltramiOutput)(j,j) = k*k*(k + 1)*(k+1);
// SHEigenvalues with order Accosiation kj
if(SHEigenvalues)
(*SHEigenvalues)(j,j) = -k* (k+1);
// Order Association
if(SHOrderAssociation)
(*SHOrderAssociation)[j] = k;
}
}
}
}
template< class T, class TG, class TO, int L, int NOdfDirections>
void DiffusionMultiShellQballReconstructionImageFilter<T,TG,TO,L,NOdfDirections>
::ComputeReconstructionMatrix(IndiciesVector const & refVector)
{
typedef std::unique_ptr< vnl_matrix< double> > MatrixDoublePtr;
typedef std::unique_ptr< vnl_vector< int > > VectorIntPtr;
typedef std::unique_ptr< vnl_matrix_inverse< double > > InverseMatrixDoublePtr;
int numberOfGradientDirections = refVector.size();
if( numberOfGradientDirections <= (((L+1)*(L+2))/2) || numberOfGradientDirections < 6 )
{
itkExceptionMacro( << "At least (L+1)(L+2)/2 gradient directions for each shell are required; current : " << numberOfGradientDirections );
}
CheckDuplicateDiffusionGradients();
const int LOrder = L;
int NumberOfCoeffs = (int)(LOrder*LOrder + LOrder + 2.0)/2.0 + LOrder;
MatrixDoublePtr SHBasisMatrix(new vnl_matrix<double>(numberOfGradientDirections,NumberOfCoeffs));
SHBasisMatrix->fill(0.0);
VectorIntPtr SHOrderAssociation(new vnl_vector<int>(NumberOfCoeffs));
SHOrderAssociation->fill(0.0);
MatrixDoublePtr LaplacianBaltrami(new vnl_matrix<double>(NumberOfCoeffs,NumberOfCoeffs));
LaplacianBaltrami->fill(0.0);
MatrixDoublePtr FRTMatrix(new vnl_matrix<double>(NumberOfCoeffs,NumberOfCoeffs));
FRTMatrix->fill(0.0);
MatrixDoublePtr SHEigenvalues(new vnl_matrix<double>(NumberOfCoeffs,NumberOfCoeffs));
SHEigenvalues->fill(0.0);
MatrixDoublePtr Q(new vnl_matrix<double>(3, numberOfGradientDirections));
// Convert Cartesian to Spherical Coordinates refVector -> Q
ComputeSphericalFromCartesian(Q.get(), refVector);
// SHBasis-Matrix + LaplacianBaltrami-Matrix + SHOrderAssociationVector
ComputeSphericalHarmonicsBasis(Q.get() ,SHBasisMatrix.get() , LOrder , LaplacianBaltrami.get(), SHOrderAssociation.get(), SHEigenvalues.get());
// Compute FunkRadon Transformation Matrix Associated to SHBasis Order lj
for(int i=0; i<NumberOfCoeffs; i++)
{
(*FRTMatrix)(i,i) = 2.0 * itk::Math::pi * mitk::sh::legendre0((*SHOrderAssociation)[i]);
}
MatrixDoublePtr temp(new vnl_matrix<double>(((SHBasisMatrix->transpose()) * (*SHBasisMatrix)) + (m_Lambda * (*LaplacianBaltrami))));
InverseMatrixDoublePtr pseudo_inv(new vnl_matrix_inverse<double>((*temp)));
MatrixDoublePtr inverse(new vnl_matrix<double>(NumberOfCoeffs,NumberOfCoeffs));
(*inverse) = pseudo_inv->inverse();
const double factor = (1.0/(16.0*itk::Math::pi*itk::Math::pi));
MatrixDoublePtr SignalReonstructionMatrix (new vnl_matrix<double>((*inverse) * (SHBasisMatrix->transpose())));
m_CoeffReconstructionMatrix = new vnl_matrix<double>(( factor * ((*FRTMatrix) * ((*SHEigenvalues) * (*SignalReonstructionMatrix))) ));
// SH Basis for ODF-reconstruction
vnl_matrix_fixed<double, 3, NOdfDirections>* U = PointShell<NOdfDirections, vnl_matrix_fixed<double, 3, NOdfDirections> >::DistributePointShell();
for(int i=0; i<NOdfDirections; i++)
{
double x = (*U)(0,i);
double y = (*U)(1,i);
double z = (*U)(2,i);
double cart[3];
mitk::sh::Cart2Sph(x,y,z,cart);
(*U)(0,i) = cart[0];
(*U)(1,i) = cart[1];
(*U)(2,i) = cart[2];
}
MatrixDoublePtr tempPtr (new vnl_matrix<double>( U->as_matrix() ));
m_ODFSphericalHarmonicBasisMatrix = new vnl_matrix<double>(NOdfDirections,NumberOfCoeffs);
ComputeSphericalHarmonicsBasis(tempPtr.get(), m_ODFSphericalHarmonicBasisMatrix, LOrder);
}
template< class T, class TG, class TO, int L, int NOdfDirections>
void DiffusionMultiShellQballReconstructionImageFilter<T,TG,TO,L,NOdfDirections>
::ComputeSphericalFromCartesian(vnl_matrix<double> * Q, IndiciesVector const & refShell)
{
for(unsigned int i = 0; i < refShell.size(); i++)
{
double x = m_GradientDirectionContainer->ElementAt(refShell[i]).normalize().get(0);
double y = m_GradientDirectionContainer->ElementAt(refShell[i]).normalize().get(1);
double z = m_GradientDirectionContainer->ElementAt(refShell[i]).normalize().get(2);
double cart[3];
mitk::sh::Cart2Sph(x,y,z,cart);
(*Q)(0,i) = cart[0];
(*Q)(1,i) = cart[1];
(*Q)(2,i) = cart[2];
}
}
template< class T, class TG, class TO, int L, int NODF>
bool DiffusionMultiShellQballReconstructionImageFilter<T,TG,TO,L,NODF>
::CheckDuplicateDiffusionGradients()
{
bool value = false;
BValueMapIteraotr mapIterator = m_BValueMap.begin();
mapIterator++;
while(mapIterator != m_BValueMap.end())
{
std::vector<unsigned int>::const_iterator it1 = mapIterator->second.begin();
std::vector<unsigned int>::const_iterator it2 = mapIterator->second.begin();
for(; it1 != mapIterator->second.end(); ++it1)
{
for(; it2 != mapIterator->second.end(); ++it2)
{
if(m_GradientDirectionContainer->ElementAt(*it1) == m_GradientDirectionContainer->ElementAt(*it2) && it1 != it2)
{
itkWarningMacro( << "Some of the Diffusion Gradients equal each other. Corresponding image data should be averaged before calling this filter." );
value = true;
}
}
}
++mapIterator;
}
return value;
}
template< class T, class TG, class TO, int L, int NODF>
std::vector<unsigned int> DiffusionMultiShellQballReconstructionImageFilter<T,TG,TO,L,NODF>
::GetAllDirections()
{
IndiciesVector directioncontainer;
BValueMapIteraotr mapIterator = m_BValueMap.begin();
mapIterator++;
IndiciesVector shell1 = mapIterator->second;
mapIterator++;
IndiciesVector shell2 = mapIterator->second;
mapIterator++;
IndiciesVector shell3 = mapIterator->second;
while(shell1.size()>0)
{
unsigned int wntIndex = shell1.back();
shell1.pop_back();
IndiciesVector::iterator containerIt = directioncontainer.begin();
bool directionExist = false;
while(containerIt != directioncontainer.end())
{
if (fabs(dot(m_GradientDirectionContainer->ElementAt(*containerIt), m_GradientDirectionContainer->ElementAt(wntIndex))) > 0.9998)
{
directionExist = true;
break;
}
containerIt++;
}
if(!directionExist)
{
directioncontainer.push_back(wntIndex);
}
}
while(shell2.size()>0)
{
unsigned int wntIndex = shell2.back();
shell2.pop_back();
IndiciesVector::iterator containerIt = directioncontainer.begin();
bool directionExist = false;
while(containerIt != directioncontainer.end())
{
if (fabs(dot(m_GradientDirectionContainer->ElementAt(*containerIt), m_GradientDirectionContainer->ElementAt(wntIndex))) > 0.9998)
{
directionExist = true;
break;
}
containerIt++;
}
if(!directionExist)
{
directioncontainer.push_back(wntIndex);
}
}
while(shell3.size()>0)
{
unsigned int wntIndex = shell3.back();
shell3.pop_back();
IndiciesVector::iterator containerIt = directioncontainer.begin();
bool directionExist = false;
while(containerIt != directioncontainer.end())
{
if (fabs(dot(m_GradientDirectionContainer->ElementAt(*containerIt), m_GradientDirectionContainer->ElementAt(wntIndex))) > 0.9998)
{
directionExist = true;
break;
}
containerIt++;
}
if(!directionExist)
{
directioncontainer.push_back(wntIndex);
}
}
return directioncontainer;
}
// corresponding directions between shells (e.g. dir1_shell1 vs dir1_shell2) differ more than 1 degree.
template< class T, class TG, class TO, int L, int NODF>
bool DiffusionMultiShellQballReconstructionImageFilter<T,TG,TO,L,NODF>
::CheckForDifferingShellDirections()
{
bool interp_flag = false;
BValueMapIteraotr mapIterator = m_BValueMap.begin();
mapIterator++;
IndiciesVector shell1 = mapIterator->second;
mapIterator++;
IndiciesVector shell2 = mapIterator->second;
mapIterator++;
IndiciesVector shell3 = mapIterator->second;
for (unsigned int i=0; i< shell1.size(); i++)
if (fabs(dot(m_GradientDirectionContainer->ElementAt(shell1[i]), m_GradientDirectionContainer->ElementAt(shell2[i]))) <= 0.9998) {interp_flag=true; break;}
for (unsigned int i=0; i< shell1.size(); i++)
if (fabs(dot(m_GradientDirectionContainer->ElementAt(shell1[i]), m_GradientDirectionContainer->ElementAt(shell3[i]))) <= 0.9998) {interp_flag=true; break;}
for (unsigned int i=0; i< shell1.size(); i++)
if (fabs(dot(m_GradientDirectionContainer->ElementAt(shell2[i]), m_GradientDirectionContainer->ElementAt(shell3[i]))) <= 0.9998) {interp_flag=true; break;}
return interp_flag;
}
template< class T, class TG, class TO, int L, int NODF>
void DiffusionMultiShellQballReconstructionImageFilter<T,TG,TO,L,NODF>
::PrintSelf(std::ostream& os, Indent indent) const
{
std::locale C("C");
std::locale originalLocale = os.getloc();
os.imbue(C);
Superclass::PrintSelf(os,indent);
//os << indent << "OdfReconstructionMatrix: " << m_ReconstructionMatrix << std::endl;
if ( m_GradientDirectionContainer )
{
os << indent << "GradientDirectionContainer: "
<< m_GradientDirectionContainer << std::endl;
}
else
{
os << indent <<
"GradientDirectionContainer: (Gradient directions not set)" << std::endl;
}
os << indent << "NumberOfGradientDirections: " <<
m_NumberOfGradientDirections << std::endl;
os << indent << "NumberOfBaselineImages: " <<
m_NumberOfBaselineImages << std::endl;
os << indent << "Threshold for reference B0 image: " << m_Threshold << std::endl;
os << indent << "BValue: " << m_BValue << std::endl;
os.imbue( originalLocale );
}
}
#endif // __itkDiffusionMultiShellQballReconstructionImageFilter_cpp
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionMultiShellQballReconstructionImageFilter.h b/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionMultiShellQballReconstructionImageFilter.h
index cb13f06..99341f1 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionMultiShellQballReconstructionImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionMultiShellQballReconstructionImageFilter.h
@@ -1,221 +1,221 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkDiffusionMultiShellQballReconstructionImageFilter_h_
#define __itkDiffusionMultiShellQballReconstructionImageFilter_h_
#include <itkImageToImageFilter.h>
namespace itk{
/** \class DiffusionMultiShellQballReconstructionImageFilter
I. Aganj, C. Lenglet, G. Sapiro, E. Yacoub, K. Ugurbil, and N. Harel, “Reconstruction of the orientation distribution function in single and multiple shell q-ball imaging within constant solid angle,” Magnetic Resonance in Medicine, vol. 64, no. 2, pp. 554–566, 2010.
*/
template< class TReferenceImagePixelType, class TGradientImagePixelType, class TOdfPixelType, int NOrderL, int NrOdfDirections>
class DiffusionMultiShellQballReconstructionImageFilter : public ImageToImageFilter< Image< TReferenceImagePixelType, 3 >, Image< Vector< TOdfPixelType, NrOdfDirections >, 3 > >
{
public:
typedef DiffusionMultiShellQballReconstructionImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< Image< TReferenceImagePixelType, 3>, Image< Vector< TOdfPixelType, NrOdfDirections >, 3 > > Superclass;
typedef typename Superclass::OutputImageRegionType OutputImageRegionType;
typedef TReferenceImagePixelType ReferencePixelType;
/** GradientImageType
* (e.g. type short)*/
typedef TGradientImagePixelType GradientPixelType;
/** GradientImageType
* 3D VectorImage containing GradientPixelTypes */
typedef VectorImage< GradientPixelType, 3 > GradientImagesType;
/** ODF PixelType */
typedef Vector< TOdfPixelType, NrOdfDirections > OdfPixelType;
/** ODF ImageType */
typedef Image< OdfPixelType, 3 > OdfImageType;
/** BzeroImageType */
typedef Image< TOdfPixelType, 3 > BZeroImageType;
/** Container to hold gradient directions of the 'n' DW measurements */
typedef VectorContainer< unsigned int, vnl_vector_fixed< double, 3 > > GradientDirectionContainerType;
typedef Image< Vector< TOdfPixelType, (NOrderL*NOrderL + NOrderL + 2)/2 + NOrderL >, 3 > CoefficientImageType;
typedef std::map<unsigned int, std::vector<unsigned int> > BValueMap;
typedef std::map<unsigned int, std::vector<unsigned int> >::iterator BValueMapIteraotr;
typedef std::vector<unsigned int> IndiciesVector;
// --------------------------------------------------------------------------------------------//
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(DiffusionMultiShellQballReconstructionImageFilter, ImageToImageFilter)
/** Get reference image */
virtual typename Superclass::InputImageType * GetInputImage()
{ return ( static_cast< typename Superclass::InputImageType *>(this->ProcessObject::GetInput(0)) ); }
/** Replaces the Input method.
* Var vols = mitk::Image
* -----------------------------------------------------
* GradientDirectionContainerType-Input gradientDirectionContainer (e.g. GradientDirectionsContainerProperty)
* GradientImagesType-Input gradientImage (e.g. itkVectorImage)
* float-Input bvalue (e.g. ReferenceBValueProperty) */
void SetGradientImage( const GradientDirectionContainerType * gradientDirectionContainer, const GradientImagesType *gradientImage , float bvalue);//, std::vector<bool> listOfUserSelctedBValues );
/** Set a BValue Map (key = bvalue, value = indicies splittet for each shell)
* If the input image containes more than three q-shells
* (e.g. b-Values of 0, 1000, 2000, 3000, 4000, ...).
* For the Analytical-Reconstruction it is needed to set a
* BValue Map containing three shells in an arithmetic series
* (e.g. 0, 1000, 2000, 3000).
*/
inline void SetBValueMap(BValueMap map){this->m_BValueMap = map;}
/** Threshold on the reference image data. The output ODF will be a null
* pdf for pixels in the reference image that have a value less than this
* threshold. */
itkSetMacro( Threshold, ReferencePixelType )
itkGetMacro( Threshold, ReferencePixelType )
itkGetMacro( CoefficientImage, typename CoefficientImageType::Pointer )
/** Return non-diffusion weighted images */
itkGetMacro( BZeroImage, typename BZeroImageType::Pointer)
/** Factor for Laplacian-Baltrami smoothing of the SH-coefficients*/
itkSetMacro( Lambda, double )
itkGetMacro( Lambda, double )
protected:
DiffusionMultiShellQballReconstructionImageFilter();
~DiffusionMultiShellQballReconstructionImageFilter() { }
void PrintSelf(std::ostream& os, Indent indent) const;
void BeforeThreadedGenerateData();
void AfterThreadedGenerateData();
void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType NumberOfThreads );
private:
enum ReconstructionType
{
Mode_Analytical3Shells,
Mode_NumericalNShells,
Mode_Standard1Shell
};
ReconstructionType m_ReconstructionType;
// Interpolation
bool m_Interpolation_Flag;
vnl_matrix< double > * m_Interpolation_SHT1_inv;
vnl_matrix< double > * m_Interpolation_SHT2_inv;
vnl_matrix< double > * m_Interpolation_SHT3_inv;
vnl_matrix< double > * m_TARGET_SH_shell1;
vnl_matrix< double > * m_TARGET_SH_shell2;
vnl_matrix< double > * m_TARGET_SH_shell3;
unsigned int m_MaxDirections;
vnl_matrix< double > * m_CoeffReconstructionMatrix;
vnl_matrix< double > * m_ODFSphericalHarmonicBasisMatrix;
/** container to hold gradient directions */
GradientDirectionContainerType::Pointer m_GradientDirectionContainer;
/** Number of gradient measurements */
unsigned int m_NumberOfGradientDirections;
/** Number of baseline images */
unsigned int m_NumberOfBaselineImages;
/** Threshold on the reference image data */
ReferencePixelType m_Threshold;
typename BZeroImageType::Pointer m_BZeroImage;
typename CoefficientImageType::Pointer m_CoefficientImage;
float m_BValue;
BValueMap m_BValueMap;
double m_Lambda;
bool m_IsHemisphericalArrangementOfGradientDirections;
bool m_IsArithmeticProgession;
void ComputeReconstructionMatrix(IndiciesVector const & refVector);
void ComputeODFSHBasis();
bool CheckDuplicateDiffusionGradients();
bool CheckForDifferingShellDirections();
IndiciesVector GetAllDirections();
void ComputeSphericalHarmonicsBasis(vnl_matrix<double>* QBallReference, vnl_matrix<double>* SHBasisOutput, int Lorder , vnl_matrix<double>* LaplaciaBaltramiOutput =0 , vnl_vector<int>* SHOrderAssociation =0 , vnl_matrix<double> * SHEigenvalues =0);
void Normalize(OdfPixelType & odf );
void S_S0Normalization( vnl_vector<double> & vec, double b0 = 0 );
void DoubleLogarithm(vnl_vector<double> & vec);
double CalculateThreashold(const double value, const double delta);
void Projection1(vnl_vector<double> & vec, double delta = 0.01);
void Projection2( vnl_vector<double> & E1, vnl_vector<double> & E2, vnl_vector<double> & E3, double delta = 0.01);
void Projection3( vnl_vector<double> & A, vnl_vector<double> & alpha, vnl_vector<double> & beta, double delta = 0.01);
void StandardOneShellReconstruction(const OutputImageRegionType& outputRegionForThread);
void AnalyticalThreeShellReconstruction(const OutputImageRegionType& outputRegionForThread);
void NumericalNShellReconstruction(const OutputImageRegionType& outputRegionForThread);
void GenerateAveragedBZeroImage(const OutputImageRegionType& outputRegionForThread);
void ComputeSphericalFromCartesian(vnl_matrix<double> * Q, const IndiciesVector & refShell);
//------------------------- VNL-function ------------------------------------
template<typename CurrentValue, typename WntValue>
vnl_vector< WntValue> element_cast (vnl_vector< CurrentValue> const& v1)
{
vnl_vector<WntValue> result(v1.size());
for(unsigned int i = 0 ; i < v1.size(); i++)
result[i] = static_cast< WntValue>(v1[i]);
return result;
}
template<typename type>
double dot (vnl_vector_fixed< type ,3> const& v1, vnl_vector_fixed< type ,3 > const& v2 )
{
double result = (v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]) / (v1.two_norm() * v2.two_norm());
return result ;
}
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkDiffusionMultiShellQballReconstructionImageFilter.cpp"
#endif
#endif //__itkDiffusionMultiShellQballReconstructionImageFilter_h_
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionQballReconstructionImageFilter.h b/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionQballReconstructionImageFilter.h
index 6b45cf8..37612a5 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionQballReconstructionImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionQballReconstructionImageFilter.h
@@ -1,341 +1,341 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkDiffusionQballReconstructionImageFilter_h_
#define __itkDiffusionQballReconstructionImageFilter_h_
#include "itkImageToImageFilter.h"
//#include "vnl/vnl_matrix.h"
#include "vnl/vnl_vector_fixed.h"
#include "vnl/vnl_matrix.h"
#include "vnl/algo/vnl_svd.h"
#include "itkVectorContainer.h"
#include "itkVectorImage.h"
namespace itk{
/** \class DiffusionQballReconstructionImageFilter
* \brief This class takes as input one or more reference images (acquired in the
* absence of diffusion sensitizing gradients) and 'n' diffusion
* weighted images and their gradient directions and computes an image of
* orientation distribution functions (ODFs).
*
* \par Inputs and Usage
* There are two ways to use this class. When you have one reference image and \c n
* gradient images, you would use the class as
* \code
* filter->SetReferenceImage( image0 );
* filter->AddGradientImage( direction1, image1 );
* filter->AddGradientImage( direction2, image2 );
* ...
* \endcode
*
* \par
* When you have the 'n' gradient and one or more reference images in a single
* multi-component image (VectorImage), you can specify the images simply as
* \code
* filter->SetGradientImage( directionsContainer, vectorImage );
* \endcode
* Note that this method is used to specify both the reference and gradient images.
* This is convenient when the DWI images are read in using the
* <a href="http://wiki.na-mic.org/Wiki/index.php/NAMIC_Wiki:DTI:Nrrd_format">NRRD</a>
* format. Like the Nrrd format, the reference images are those components of the
* vectorImage whose gradient direction is (0,0,0). If more than one reference image
* is present, they are averaged prior to the reconstruction.
*
* \par Outputs
* The output image is an image of vectors that must be understood as ODFs:
* \code
* Image< Vector< TPixelType, OdfNrDirections >, 3 >
* \endcode
*
* \par Parameters
* \li Threshold - Threshold on the reference image data. The output ODF will
* be a null pdf for pixels in the reference image that have a value less
* than this.
* \li BValue - See the documentation of SetBValue().
* \li At least 6 gradient images must be specified for the filter to be able
* to run. If the input gradient directions g_i are majorly sampled on one half
* of the sqhere, then each input image I_i will be duplicated and assign -g_i
* in order to guarantee stability of the Tuch-Algorithm.
* \li OdfDirections - directions of resulting orientation distribution function
* \li EquatorNrSamplingPoints - number of sampling points on equator when
* performing Funk Radeon Transform (FRT)
* \li BasisFunctionCenters - the centers of the basis functions are used for
* the sRBF (spherical radial basis functions interpolation). If not set, they
* will be defaulted to equal m_EquatorNrSamplingPoints
*
* \par Template parameters
* The class is templated over
* \li the pixel type of the reference and gradient images
* (expected to be scalar data types)
* \li the internal representation of the ODF pixels (double, float etc).
* \li the number of OdfDirections
* \li the number of basis function centers for the sRBF
*
* \par References:
* \li<a href="http://www3.interscience.wiley.com/cgi-bin/fulltext/109800293/PDFSTART">[1]</a>
* <em>Tuch DS,
* "Q-ball imaging", Magn Reson Med. 2004 Dec;52(6):1358-72.</em>
*
*/
template< class TReferenceImagePixelType,
class TGradientImagePixelType,
class TOdfPixelType,
int NrOdfDirections,
int NrBasisFunctionCenters = NrOdfDirections>
class DiffusionQballReconstructionImageFilter :
public ImageToImageFilter< Image< TReferenceImagePixelType, 3 >,
Image< Vector< TOdfPixelType, NrOdfDirections >, 3 > >
{
public:
/** \class DiffusionQballReconstructionImageFilter
* \brief This enum defines the normalization of the ODFs.
* \par
* Standard normalization simply divides by sum of ODF-values
* to ensure properties of a probability density function.
* \par
* B-zero/b-value normalization is ADC-style log of ratio
* between b-zero and b_i normalized by b-value.
* \par
* B-zero normalization simply divides by b-zero reference value
*/
enum Normalization {
QBR_STANDARD,
QBR_B_ZERO_B_VALUE,
QBR_B_ZERO,
QBR_NONE
};
typedef DiffusionQballReconstructionImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< Image< TReferenceImagePixelType, 3>,
Image< Vector< TOdfPixelType, NrOdfDirections >, 3 > >
Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(DiffusionQballReconstructionImageFilter,
ImageToImageFilter);
typedef TReferenceImagePixelType ReferencePixelType;
typedef TGradientImagePixelType GradientPixelType;
typedef Vector< TOdfPixelType, NrOdfDirections >
OdfPixelType;
/** Reference image data, This image is aquired in the absence
* of a diffusion sensitizing field gradient */
typedef typename Superclass::InputImageType ReferenceImageType;
typedef Image< OdfPixelType, 3 > OdfImageType;
typedef OdfImageType OutputImageType;
typedef TOdfPixelType BZeroPixelType;
typedef Image< BZeroPixelType, 3 > BZeroImageType;
typedef typename Superclass::OutputImageRegionType
OutputImageRegionType;
/** Typedef defining one (of the many) gradient images. */
typedef Image< GradientPixelType, 3 > GradientImageType;
/** An alternative typedef defining one (of the many) gradient images.
* It will be assumed that the vectorImage has the same dimension as the
* Reference image and a vector length parameter of \c n (number of
* gradient directions)*/
typedef VectorImage< GradientPixelType, 3 > GradientImagesType;
/** Holds the ODF reconstruction matrix */
typedef vnl_matrix< TOdfPixelType >*
OdfReconstructionMatrixType;
/** Holds each magnetic field gradient used to acquire one DWImage */
typedef vnl_vector_fixed< double, 3 > GradientDirectionType;
/** Container to hold gradient directions of the 'n' DW measurements */
typedef VectorContainer< unsigned int,
GradientDirectionType > GradientDirectionContainerType;
itkStaticConstMacro(NOdfDirections,int,NrOdfDirections);
itkStaticConstMacro(NBasisFunctionCenters,int,NrBasisFunctionCenters);
/** Set method to add a gradient direction and its corresponding image. */
void AddGradientImage( const GradientDirectionType &, const GradientImageType *image);
/** Another set method to add a gradient directions and its corresponding
* image. The image here is a VectorImage. The user is expected to pass the
* gradient directions in a container. The ith element of the container
* corresponds to the gradient direction of the ith component image the
* VectorImage. For the baseline image, a vector of all zeros
* should be set.*/
void SetGradientImage( const GradientDirectionContainerType *,
const GradientImagesType *image);
/** Set method to set the reference image. */
void SetReferenceImage( ReferenceImageType *referenceImage )
{
if( m_GradientImageTypeEnumeration == GradientIsInASingleImage)
{
itkExceptionMacro( << "Cannot call both methods:"
<< "AddGradientImage and SetGradientImage. Please call only one of them.");
}
this->ProcessObject::SetNthInput( 0, referenceImage );
m_GradientImageTypeEnumeration = GradientIsInManyImages;
}
/** Get reference image */
virtual ReferenceImageType * GetReferenceImage()
{ return ( static_cast< ReferenceImageType *>(this->ProcessObject::GetInput(0)) ); }
/** Return the gradient direction. idx is 0 based */
virtual GradientDirectionType GetGradientDirection( unsigned int idx) const
{
if( idx >= m_NumberOfGradientDirections )
{
itkExceptionMacro( << "Gradient direction " << idx << "does not exist" );
}
return m_GradientDirectionContainer->ElementAt( idx+1 );
}
/** Normalization performed on the reconstructed ODF according
* to method set in m_NormalizationMethod
*/
OdfPixelType Normalize(OdfPixelType odf, typename NumericTraits<ReferencePixelType>::AccumulateType b0 );
/** Normalization performed on diffusion signal vector according
* to method set in m_NormalizationMethod
*/
vnl_vector<TOdfPixelType> PreNormalize( vnl_vector<TOdfPixelType> vec );
/** Threshold on the reference image data. The output ODF will be a null
* pdf for pixels in the reference image that have a value less than this
* threshold. */
itkSetMacro( Threshold, ReferencePixelType );
itkGetMacro( Threshold, ReferencePixelType );
/** Normalization applied to ODFs */
itkSetMacro( NormalizationMethod, Normalization);
itkGetMacro( NormalizationMethod, Normalization );
/** Output image with b-zero weighted images */
itkGetMacro( BZeroImage, typename BZeroImageType::Pointer);
/** B-value used to acquire the diffusion signal */
itkSetMacro( BValue, TOdfPixelType);
#ifdef GetBValue
#undef GetBValue
#endif
itkGetConstReferenceMacro( BValue, TOdfPixelType);
#ifdef ITK_USE_CONCEPT_CHECKING
/** Begin concept checking */
itkConceptMacro(ReferenceEqualityComparableCheck,
(Concept::EqualityComparable<ReferencePixelType>));
itkConceptMacro(TensorEqualityComparableCheck,
(Concept::EqualityComparable<OdfPixelType>));
itkConceptMacro(GradientConvertibleToDoubleCheck,
(Concept::Convertible<GradientPixelType, double>));
itkConceptMacro(DoubleConvertibleToTensorCheck,
(Concept::Convertible<double, OdfPixelType>));
itkConceptMacro(GradientReferenceAdditiveOperatorsCheck,
(Concept::AdditiveOperators<GradientPixelType, GradientPixelType,
ReferencePixelType>));
itkConceptMacro(ReferenceOStreamWritableCheck,
(Concept::OStreamWritable<ReferencePixelType>));
itkConceptMacro(TensorOStreamWritableCheck,
(Concept::OStreamWritable<OdfPixelType>));
/** End concept checking */
#endif
protected:
DiffusionQballReconstructionImageFilter();
~DiffusionQballReconstructionImageFilter() override {};
void PrintSelf(std::ostream& os, Indent indent) const override;
/** constructs reconstrion matrix according to Tuch's algorithm */
void ComputeReconstructionMatrix();
void BeforeThreadedGenerateData() override;
void ThreadedGenerateData( const
OutputImageRegionType &outputRegionForThread, ThreadIdType) override;
/** enum to indicate if the gradient image is specified as a single multi-
* component image or as several separate images */
typedef enum
{
GradientIsInASingleImage = 1,
GradientIsInManyImages,
Else
} GradientImageTypeEnumeration;
private:
/* Tensor basis coeffs */
OdfReconstructionMatrixType m_ReconstructionMatrix;
/** container to hold gradient directions */
GradientDirectionContainerType::Pointer m_GradientDirectionContainer;
/** Number of gradient measurements */
unsigned int m_NumberOfGradientDirections;
/** Number of Equator Sampling Points (StdValue sqrt(8*pi*NGradDirs)) */
unsigned int m_NumberOfEquatorSamplingPoints;
/** Number of baseline images */
unsigned int m_NumberOfBaselineImages;
/** Threshold on the reference image data */
ReferencePixelType m_Threshold;
/** LeBihan's b-value for normalizing tensors */
TOdfPixelType m_BValue;
/** Gradient image was specified in a single image or in multiple images */
GradientImageTypeEnumeration m_GradientImageTypeEnumeration;
/** Output of b-zero reference image */
typename BZeroImageType::Pointer m_BZeroImage;
/** Flag wether half shell was duplicated to ensure evenly
* distributed directions on the sphere
*/
bool m_DirectionsDuplicated;
/** Normalization method to be applied */
Normalization m_NormalizationMethod;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkDiffusionQballReconstructionImageFilter.txx"
#endif
#endif //__itkDiffusionQballReconstructionImageFilter_h_
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionQballReconstructionImageFilter.txx b/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionQballReconstructionImageFilter.txx
index e64d1fb..ed6e222 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionQballReconstructionImageFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/itkDiffusionQballReconstructionImageFilter.txx
@@ -1,851 +1,851 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkDiffusionQballReconstructionImageFilter_txx
#define __itkDiffusionQballReconstructionImageFilter_txx
#include "itkDiffusionQballReconstructionImageFilter.h"
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionConstIteratorWithIndex.h"
#include "itkImageRegionIterator.h"
#include "itkArray.h"
#include "vnl/vnl_vector.h"
#include "itkPointShell.h"
namespace itk {
template< class TReferenceImagePixelType,
class TGradientImagePixelType,
class TOdfPixelType,
int NrOdfDirections,
int NrBasisFunctionCenters>
DiffusionQballReconstructionImageFilter< TReferenceImagePixelType,
TGradientImagePixelType, TOdfPixelType, NrOdfDirections,
NrBasisFunctionCenters>
::DiffusionQballReconstructionImageFilter() :
m_GradientDirectionContainer(nullptr),
m_NumberOfGradientDirections(0),
m_NumberOfEquatorSamplingPoints(0),
m_NumberOfBaselineImages(1),
m_Threshold(NumericTraits< ReferencePixelType >::NonpositiveMin()),
m_BValue(1.0),
m_GradientImageTypeEnumeration(Else),
m_DirectionsDuplicated(false)
{
// At least 1 inputs is necessary for a vector image.
// For images added one at a time we need at least six
this->SetNumberOfRequiredInputs( 1 );
}
template< class TReferenceImagePixelType,
class TGradientImagePixelType,
class TOdfPixelType,
int NrOdfDirections,
int NrBasisFunctionCenters>
void DiffusionQballReconstructionImageFilter< TReferenceImagePixelType,
TGradientImagePixelType, TOdfPixelType, NrOdfDirections,
NrBasisFunctionCenters>
::BeforeThreadedGenerateData()
{
// If we have more than 2 inputs, then each input, except the first is a
// gradient image. The number of gradient images must match the number of
// gradient directions.
const unsigned int numberOfInputs = this->GetNumberOfInputs();
// There need to be at least 6 gradient directions to be able to compute the
// tensor basis
if( m_NumberOfGradientDirections < 1 )
{
itkExceptionMacro( << "Your image contains no diffusion gradients!" );
}
// If there is only 1 gradient image, it must be an itk::VectorImage. Otherwise
// we must have a container of (numberOfInputs-1) itk::Image. Check to make sure
if ( numberOfInputs == 1
&& m_GradientImageTypeEnumeration != GradientIsInASingleImage )
{
std::string gradientImageClassName(
this->ProcessObject::GetInput(0)->GetNameOfClass());
if ( strcmp(gradientImageClassName.c_str(),"VectorImage") != 0 )
{
itkExceptionMacro( <<
"There is only one Gradient image. I expect that to be a VectorImage. "
<< "But its of type: " << gradientImageClassName );
}
}
// Compute reconstruction matrix that is multiplied to the data-vector
// each voxel in order to reconstruct the ODFs
this->ComputeReconstructionMatrix();
// Allocate the b-zero image
m_BZeroImage = BZeroImageType::New();
if( m_GradientImageTypeEnumeration == GradientIsInManyImages )
{
typename ReferenceImageType::Pointer img = static_cast< ReferenceImageType * >(this->ProcessObject::GetInput(0));
m_BZeroImage->SetSpacing( img->GetSpacing() ); // Set the image spacing
m_BZeroImage->SetOrigin( img->GetOrigin() ); // Set the image origin
m_BZeroImage->SetDirection( img->GetDirection() ); // Set the image direction
m_BZeroImage->SetLargestPossibleRegion( img->GetLargestPossibleRegion());
m_BZeroImage->SetBufferedRegion( img->GetLargestPossibleRegion() );
}
// The gradients are specified in a single multi-component image
else if( m_GradientImageTypeEnumeration == GradientIsInASingleImage )
{
typename GradientImagesType::Pointer img = static_cast< GradientImagesType * >(
this->ProcessObject::GetInput(0) );
m_BZeroImage->SetSpacing( img->GetSpacing() ); // Set the image spacing
m_BZeroImage->SetOrigin( img->GetOrigin() ); // Set the image origin
m_BZeroImage->SetDirection( img->GetDirection() ); // Set the image direction
m_BZeroImage->SetLargestPossibleRegion( img->GetLargestPossibleRegion());
m_BZeroImage->SetBufferedRegion( img->GetLargestPossibleRegion() );
}
m_BZeroImage->Allocate();
}
template< class TReferenceImagePixelType,
class TGradientImagePixelType,
class TOdfPixelType,
int NrOdfDirections,
int NrBasisFunctionCenters>
typename itk::DiffusionQballReconstructionImageFilter<TReferenceImagePixelType, TGradientImagePixelType, TOdfPixelType, NrOdfDirections, NrBasisFunctionCenters>::OdfPixelType
itk::DiffusionQballReconstructionImageFilter<TReferenceImagePixelType, TGradientImagePixelType, TOdfPixelType, NrOdfDirections, NrBasisFunctionCenters>::Normalize( OdfPixelType odf, typename NumericTraits<ReferencePixelType>::AccumulateType b0 )
{
switch( m_NormalizationMethod )
{
// divide by sum to retreive a PDF
case QBR_STANDARD:
{
odf.Normalize();
return odf;
break;
}
// ADC style
case QBR_B_ZERO_B_VALUE:
{
for(int i=0; i<NrOdfDirections; i++)
{
odf[i] = ((TOdfPixelType)log((TOdfPixelType)b0)-odf[i])/m_BValue;
}
return odf;
break;
}
// divide by b-zero value of voxel
case QBR_B_ZERO:
{
odf *= 1.0/b0;
return odf;
break;
}
// no normalization of ODF
case QBR_NONE:
{
return odf;
break;
}
}
return odf;
}
template< class TReferenceImagePixelType,
class TGradientImagePixelType,
class TOdfPixelType,
int NrOdfDirections,
int NrBasisFunctionCenters >
vnl_vector<TOdfPixelType> itk::DiffusionQballReconstructionImageFilter<TReferenceImagePixelType, TGradientImagePixelType, TOdfPixelType, NrOdfDirections, NrBasisFunctionCenters>::PreNormalize( vnl_vector<TOdfPixelType> vec )
{
switch( m_NormalizationMethod )
{
// standard: no normalization before reconstruction
case QBR_STANDARD:
{
return vec;
break;
}
// log of signal
case QBR_B_ZERO_B_VALUE:
{
int n = vec.size();
for(int i=0; i<n; i++)
{
vec[i] = log(vec[i]);
}
return vec;
break;
}
// no normalization before reconstruction here
case QBR_B_ZERO:
{
return vec;
break;
}
// no normalization before reconstruction here
case QBR_NONE:
{
return vec;
break;
}
}
return vec;
}
template< class TReferenceImagePixelType,
class TGradientImagePixelType,
class TOdfPixelType,
int NrOdfDirections,
int NrBasisFunctionCenters>
void DiffusionQballReconstructionImageFilter< TReferenceImagePixelType,
TGradientImagePixelType, TOdfPixelType, NrOdfDirections,
NrBasisFunctionCenters>
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
ThreadIdType )
{
// init output and b-zero iterators
typename OutputImageType::Pointer outputImage =
static_cast< OutputImageType * >(this->ProcessObject::GetPrimaryOutput());
ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread);
oit.GoToBegin();
ImageRegionIterator< BZeroImageType > oit2(m_BZeroImage, outputRegionForThread);
oit2.GoToBegin();
vnl_vector<TOdfPixelType> B(m_NumberOfGradientDirections);
// Two cases here:
// 1. Gradients specified in multiple images
// 'n' iterators for each of the gradient images
// 2. Gradients specified in a single multi-component image
// one iterator for all gradient directions
if( m_GradientImageTypeEnumeration == GradientIsInManyImages )
{
// b-zero reference image iterator
ImageRegionConstIterator< ReferenceImageType >
it(static_cast< ReferenceImageType * >(this->ProcessObject::GetInput(0)),
outputRegionForThread);
it.GoToBegin();
// fill vector with gradient iterators
typedef ImageRegionConstIterator< GradientImageType > GradientIteratorType;
std::vector< GradientIteratorType * > gradientItContainer;
for( unsigned int i = 1; i<= m_NumberOfGradientDirections; i++ )
{
// adapt index in case we have a duplicated shell
int index = i;
if(m_DirectionsDuplicated)
index = i % (m_NumberOfGradientDirections/2);
// init and pushback current input image iterator
typename GradientImageType::Pointer gradientImagePointer = nullptr;
// dynamic_cast would be nice, static because of SGI
gradientImagePointer = static_cast< GradientImageType * >(
this->ProcessObject::GetInput(index) );
GradientIteratorType *git = new GradientIteratorType(
gradientImagePointer, outputRegionForThread );
git->GoToBegin();
gradientItContainer.push_back(git);
}
// Following loop does the actual reconstruction work in each voxel
// (Tuch, Q-Ball Reconstruction [1])
while( !it.IsAtEnd() )
{
// b-zero reference value
ReferencePixelType b0 = it.Get();
// init ODF
OdfPixelType odf(0.0);
// threshold on reference value to suppress noisy regions
if( (b0 != 0) && (b0 >= m_Threshold) )
{
// fill array of diffusion measurements
for( unsigned int i = 0; i< m_NumberOfGradientDirections; i++ )
{
GradientPixelType b = gradientItContainer[i]->Get();
B[i] = static_cast<TOdfPixelType>(b);
++(*gradientItContainer[i]);
}
// pre-normalization according to m_NormalizationMethod
B = PreNormalize(B);
// actual reconstruction
odf = ( (*m_ReconstructionMatrix) * B ).data_block();
// post-normalization according to m_NormalizationMethod
odf.Normalize();
}
else
{
// in case we fall below threshold, we just increment to next voxel
for( unsigned int i = 0; i< m_NumberOfGradientDirections; i++ )
{
++(*gradientItContainer[i]);
}
}
for (unsigned int i=0; i<odf.Size(); i++)
if (odf.GetElement(i)!=odf.GetElement(i))
odf.Fill(0.0);
// set and increment output iterators
oit.Set( odf );
++oit;
oit2.Set( b0 );
++oit2;
++it;
}
// clean up
for( unsigned int i = 0; i< gradientItContainer.size(); i++ )
{
delete gradientItContainer[i];
}
}
// The gradients are specified in a single multi-component image
else if( m_GradientImageTypeEnumeration == GradientIsInASingleImage )
{
// init input iterator
typedef ImageRegionConstIterator< GradientImagesType > GradientIteratorType;
typedef typename GradientImagesType::PixelType GradientVectorType;
typename GradientImagesType::Pointer gradientImagePointer = nullptr;
// dynamic_cast would be nice, static because of SGI
gradientImagePointer = static_cast< GradientImagesType * >(
this->ProcessObject::GetInput(0) );
GradientIteratorType git(gradientImagePointer, outputRegionForThread );
git.GoToBegin();
// set of indicies each for the baseline images and gradient images
std::vector<unsigned int> baselineind; // contains baseline indicies
std::vector<unsigned int> gradientind; // contains gradient indicies
for(GradientDirectionContainerType::ConstIterator gdcit = this->m_GradientDirectionContainer->Begin();
gdcit != this->m_GradientDirectionContainer->End(); ++gdcit)
{
if(gdcit.Value().one_norm() <= 0.0)
{
baselineind.push_back(gdcit.Index());
}
else
{
gradientind.push_back(gdcit.Index());
}
}
// in case we have a duplicated shell, we also duplicate or indices
if( m_DirectionsDuplicated )
{
int gradIndSize = gradientind.size();
for(int i=0; i<gradIndSize; i++)
gradientind.push_back(gradientind[i]);
}
// Following loop does the actual reconstruction work in each voxel
// (Tuch, Q-Ball Reconstruction [1])
while( !git.IsAtEnd() )
{
// current vector of diffusion measurements
GradientVectorType b = git.Get();
// average of current b-zero reference values
typename NumericTraits<ReferencePixelType>::AccumulateType b0 = NumericTraits<ReferencePixelType>::Zero;
for(unsigned int i = 0; i < baselineind.size(); ++i)
{
b0 += b[baselineind[i]];
}
b0 /= this->m_NumberOfBaselineImages;
// init resulting ODF
OdfPixelType odf(0.0);
// threshold on reference value to suppress noisy regions
if( (b0 != 0) && (b0 >= m_Threshold) )
{
for( unsigned int i = 0; i< m_NumberOfGradientDirections; i++ )
{
B[i] = static_cast<TOdfPixelType>(b[gradientind[i]]);
}
// pre-normalization according to m_NormalizationMethod
B = PreNormalize(B);
// actual reconstruction
odf = ( (*m_ReconstructionMatrix) * B ).data_block();
// post-normalization according to m_NormalizationMethod
odf = Normalize(odf, b0);
}
for (unsigned int i=0; i<odf.Size(); i++)
if (odf.GetElement(i)!=odf.GetElement(i))
odf.Fill(0.0);
// set and increment output iterators
oit.Set( odf );
++oit;
oit2.Set( b0 );
++oit2;
++git; // Gradient image iterator
}
}
std::cout << "One Thread finished reconstruction" << std::endl;
}
template< class TReferenceImagePixelType,
class TGradientImagePixelType,
class TOdfPixelType,
int NrOdfDirections,
int NrBasisFunctionCenters>
void DiffusionQballReconstructionImageFilter< TReferenceImagePixelType,
TGradientImagePixelType, TOdfPixelType, NrOdfDirections,
NrBasisFunctionCenters>
::ComputeReconstructionMatrix()
{
if( m_NumberOfGradientDirections < 1 )
{
itkExceptionMacro( << "Your image contains no diffusion gradients!" );
}
{
// check for duplicate diffusion gradients
bool warning = false;
for(GradientDirectionContainerType::ConstIterator gdcit1 = this->m_GradientDirectionContainer->Begin();
gdcit1 != this->m_GradientDirectionContainer->End(); ++gdcit1)
{
for(GradientDirectionContainerType::ConstIterator gdcit2 = this->m_GradientDirectionContainer->Begin();
gdcit2 != this->m_GradientDirectionContainer->End(); ++gdcit2)
{
if(gdcit1.Value() == gdcit2.Value() && gdcit1.Index() != gdcit2.Index())
{
itkWarningMacro( << "Some of the Diffusion Gradients equal each other. Corresponding image data should be averaged before calling this filter." );
warning = true;
break;
}
}
if (warning) break;
}
// handle acquisition schemes where only half of the spherical
// shell is sampled by the gradient directions. In this case,
// each gradient direction is duplicated in negative direction.
vnl_vector<double> centerMass(3);
centerMass.fill(0.0);
int count = 0;
for(GradientDirectionContainerType::ConstIterator gdcit1 = this->m_GradientDirectionContainer->Begin();
gdcit1 != this->m_GradientDirectionContainer->End(); ++gdcit1)
{
if(gdcit1.Value().one_norm() > 0.0)
{
centerMass += gdcit1.Value();
count ++;
}
}
centerMass /= count;
if(centerMass.two_norm() > 0.1)
{
m_DirectionsDuplicated = true;
m_NumberOfGradientDirections *= 2;
}
}
// set default number of equator sampling points if needed
if(!this->m_NumberOfEquatorSamplingPoints)
this->m_NumberOfEquatorSamplingPoints
= (int) ceil((double)sqrt(8*itk::Math::pi*this->m_NumberOfGradientDirections));
vnl_matrix<double>* Q =
new vnl_matrix<double>(3, m_NumberOfGradientDirections);
{
// Fill matrix Q with gradient directions
int i = 0;
for(GradientDirectionContainerType::ConstIterator gdcit = this->m_GradientDirectionContainer->Begin();
gdcit != this->m_GradientDirectionContainer->End(); ++gdcit)
{
if(gdcit.Value().one_norm() > 0.0)
{
(*Q)(0,i) = gdcit.Value().get(0);
(*Q)(1,i) = gdcit.Value().get(1);
(*Q)(2,i++) = gdcit.Value().get(2);
}
}
if(m_DirectionsDuplicated)
{
for(GradientDirectionContainerType::ConstIterator gdcit = this->m_GradientDirectionContainer->Begin();
gdcit != this->m_GradientDirectionContainer->End(); ++gdcit)
{
if(gdcit.Value().one_norm() > 0.0)
{
(*Q)(0,i) = -gdcit.Value().get(0);
(*Q)(1,i) = -gdcit.Value().get(1);
(*Q)(2,i++) = -gdcit.Value().get(2);
}
}
}
}
vnl_matrix_fixed<double, 3, NOdfDirections>* U =
itk::PointShell<NOdfDirections, vnl_matrix_fixed<double, 3, NOdfDirections> >::DistributePointShell();
vnl_matrix_fixed<double, 3, NBasisFunctionCenters>* V =
itk::PointShell<NBasisFunctionCenters, vnl_matrix_fixed<double, 3, NBasisFunctionCenters> >::DistributePointShell();
// calculate sampling points on the equator perpendicular to z-axis
vnl_matrix<double> *C
= new vnl_matrix<double>(3, m_NumberOfEquatorSamplingPoints);
for(unsigned int i=0; i<m_NumberOfEquatorSamplingPoints; i++)
{
double theta = i * (2*itk::Math::pi / m_NumberOfEquatorSamplingPoints);
(*C)(0,i) = cos(theta);
(*C)(1,i) = sin(theta);
(*C)(2,i) = NumericTraits<double>::Zero;
}
// rotate the sampling points to each directions of interest
vnl_matrix<double> *S
= new vnl_matrix<double>(3,m_NumberOfEquatorSamplingPoints*NOdfDirections);
{
vnl_vector_fixed<double,3> z(NumericTraits<double>::Zero);
z.put(2,NumericTraits<double>::One);
vnl_matrix_fixed<double,3,3> eye(NumericTraits<double>::Zero);
eye.fill_diagonal(NumericTraits<double>::One);
for(int i=0; i<NOdfDirections; i++)
{
vnl_vector_fixed<double,3> ui = (*U).get_column(i);
vnl_matrix<double> *RC
= new vnl_matrix<double>(3,m_NumberOfEquatorSamplingPoints);
if( (z(0)*ui(0)+z(1)*ui(1)+z(2)*ui(2)+1) != 0 )
{
vnl_matrix_fixed<double,3,3> R;
R.set_column(0, (z+ui)*(z(0)+ui(0)));
R.set_column(1, (z+ui)*(z(1)+ui(1)));
R.set_column(2, (z+ui)*(z(2)+ui(2)));
R /= (z(0)*ui(0)+z(1)*ui(1)+z(2)*ui(2)+1);
R -= eye;
(*RC) = R*(*C);
}
else
{
RC = C;
}
(*S).set_columns(i*m_NumberOfEquatorSamplingPoints, *RC);
}
}
// determine interpolation kernel width first
// use to determine diffusion measurement contribution to each of the kernels
vnl_matrix<double> *H_plus
= new vnl_matrix<double>(NBasisFunctionCenters,m_NumberOfGradientDirections);
double maxSigma = itk::Math::pi/6;
double bestSigma = maxSigma;
{
double stepsize = 0.01;
double start = 0.01;
double minCondition = NumericTraits<double>::max();
vnl_matrix<double> *H
= new vnl_matrix<double>(m_NumberOfGradientDirections,NBasisFunctionCenters,(double)0);
{
int increasing = 0;
for( double sigma=start; sigma<maxSigma; sigma+=stepsize)
{
vnl_matrix<double> *tmpH
= new vnl_matrix<double>(m_NumberOfGradientDirections,NBasisFunctionCenters);
for(unsigned int r=0; r<m_NumberOfGradientDirections; r++)
{
for(int c=0; c<NBasisFunctionCenters; c++)
{
double qtv = (*Q)(0,r)*(*V)(0,c)
+ (*Q)(1,r)*(*V)(1,c)
+ (*Q)(2,r)*(*V)(2,c);
qtv = (qtv<-1.0) ? -1.0 : ( (qtv>1.0) ? 1.0 : qtv);
double x = acos(qtv);
(*tmpH)(r,c) = (1.0/(sigma*sqrt(2.0*itk::Math::pi)))
*exp((-x*x)/(2*sigma*sigma));
}
}
vnl_svd<double> *solver;
if(m_NumberOfGradientDirections>NBasisFunctionCenters)
{
solver = new vnl_svd<double>(*tmpH);
}
else
{
solver = new vnl_svd<double>(tmpH->transpose());
}
double condition = solver->sigma_max() / solver->sigma_min();
std::cout << sigma << ": " << condition << std::endl;
if( condition < minCondition )
{
minCondition = condition;
bestSigma = sigma;
H->update(*tmpH);
}
else
{
// optimum assumed to be hit after condition increased 3 times
if (++increasing>3) break;
}
}
}
vnl_matrix_inverse<double> *pseudoInverse
= new vnl_matrix_inverse<double>(*H);
(*H_plus) = pseudoInverse->pinverse();
std::cout << "choosing sigma = " << bestSigma << std::endl;
}
// this is the contribution of each kernel to each sampling point on the
// equator
vnl_matrix<double> *G
= new vnl_matrix<double>(m_NumberOfEquatorSamplingPoints*NOdfDirections,NBasisFunctionCenters);
{
for(unsigned int r=0; r<m_NumberOfEquatorSamplingPoints*NOdfDirections; r++)
{
for(int c=0; c<NBasisFunctionCenters; c++)
{
double stv = (*S)(0,r)*(*V)(0,c)
+ (*S)(1,r)*(*V)(1,c)
+ (*S)(2,r)*(*V)(2,c);
stv = (stv<-1.0) ? -1.0 : ( (stv>1.0) ? 1.0 : stv);
double x = acos(stv);
(*G)(r,c) = (1.0/(bestSigma*sqrt(2.0*itk::Math::pi)))
*exp((-x*x)/(2*bestSigma*bestSigma));
}
}
}
vnl_matrix<double> *GH_plus =
new vnl_matrix<double>(m_NumberOfEquatorSamplingPoints*NOdfDirections,m_NumberOfGradientDirections);
// simple matrix multiplication, manual cause of stack overflow using operator
for (unsigned i = 0; i < m_NumberOfEquatorSamplingPoints*NOdfDirections; ++i)
{
for (unsigned j = 0; j < m_NumberOfGradientDirections; ++j)
{
double accum = (*G)(i,0) * (*H_plus)(0,j);
for (unsigned k = 1; k < NOdfDirections; ++k)
accum += (*G)(i,k) * (*H_plus)(k,j);
(*GH_plus)(i,j) = accum;
}
}
typename vnl_matrix<double>::iterator it3;
for( it3 = (*GH_plus).begin(); it3 != (*GH_plus).end(); it3++)
{
if(*it3<0.0)
*it3 = 0;
}
// this is an addition to the original tuch algorithm
for(unsigned int i=0; i<NOdfDirections*m_NumberOfEquatorSamplingPoints; i++)
{
vnl_vector< double > r = GH_plus->get_row(i);
r /= r.sum();
GH_plus->set_row(i,r);
}
m_ReconstructionMatrix
= new vnl_matrix<TOdfPixelType>(NOdfDirections,m_NumberOfGradientDirections,0.0);
for(int i=0; i<NOdfDirections; i++)
{
for(unsigned int j=0; j<m_NumberOfGradientDirections; j++)
{
for(unsigned int k=0; k<m_NumberOfEquatorSamplingPoints; k++)
{
(*m_ReconstructionMatrix)(i,j) += (TOdfPixelType)(*GH_plus)(m_NumberOfEquatorSamplingPoints*i+k,j);
}
}
}
// this is also an addition to the original tuch algorithm
for(int i=0; i<NOdfDirections; i++)
{
vnl_vector< TOdfPixelType > r = m_ReconstructionMatrix->get_row(i);
r /= r.sum();
m_ReconstructionMatrix->set_row(i,r);
}
std::cout << "Reconstruction Matrix computed." << std::endl;
}
template< class TReferenceImagePixelType,
class TGradientImagePixelType,
class TOdfPixelType,
int NrOdfDirections,
int NrBasisFunctionCenters>
void DiffusionQballReconstructionImageFilter< TReferenceImagePixelType,
TGradientImagePixelType, TOdfPixelType, NrOdfDirections,
NrBasisFunctionCenters>
::AddGradientImage( const GradientDirectionType &gradientDirection,
const GradientImageType *gradientImage )
{
// Make sure crazy users did not call both AddGradientImage and
// SetGradientImage
if( m_GradientImageTypeEnumeration == GradientIsInASingleImage)
{
itkExceptionMacro( << "Cannot call both methods:"
<< "AddGradientImage and SetGradientImage. Please call only one of them.");
}
// If the container to hold the gradient directions hasn't been allocated
// yet, allocate it.
if( !this->m_GradientDirectionContainer )
{
this->m_GradientDirectionContainer = GradientDirectionContainerType::New();
}
this->m_NumberOfGradientDirections = m_GradientDirectionContainer->Size();
m_GradientDirectionContainer->InsertElement( this->m_NumberOfGradientDirections,
gradientDirection / gradientDirection.two_norm() );
this->ProcessObject::SetNthInput( this->m_NumberOfGradientDirections,
const_cast< GradientImageType* >(gradientImage) );
m_GradientImageTypeEnumeration = GradientIsInManyImages;
}
template< class TReferenceImagePixelType,
class TGradientImagePixelType,
class TOdfPixelType,
int NrOdfDirections,
int NrBasisFunctionCenters>
void DiffusionQballReconstructionImageFilter< TReferenceImagePixelType,
TGradientImagePixelType, TOdfPixelType, NrOdfDirections,
NrBasisFunctionCenters>
::SetGradientImage(const GradientDirectionContainerType *gradientDirection,
const GradientImagesType *gradientImage )
{
// Make sure crazy users did not call both AddGradientImage and
// SetGradientImage
if( m_GradientImageTypeEnumeration == GradientIsInManyImages )
{
itkExceptionMacro( << "Cannot call both methods:"
<< "AddGradientImage and SetGradientImage. Please call only one of them.");
}
this->m_GradientDirectionContainer = GradientDirectionContainerType::New();
for(GradientDirectionContainerType::ConstIterator it = gradientDirection->Begin();
it != gradientDirection->End(); it++)
{
this->m_GradientDirectionContainer->push_back(it.Value());
}
unsigned int numImages = gradientDirection->Size();
this->m_NumberOfBaselineImages = 0;
for(GradientDirectionContainerType::Iterator it = this->m_GradientDirectionContainer->Begin();
it != this->m_GradientDirectionContainer->End(); it++)
{
if(it.Value().one_norm() <= 0.0)
{
this->m_NumberOfBaselineImages++;
}
else // Normalize non-zero gradient directions
{
it.Value() = it.Value() / it.Value().two_norm();
}
}
this->m_NumberOfGradientDirections = numImages - this->m_NumberOfBaselineImages;
// ensure that the gradient image we received has as many components as
// the number of gradient directions
if( gradientImage->GetVectorLength() != this->m_NumberOfBaselineImages + m_NumberOfGradientDirections )
{
itkExceptionMacro( << m_NumberOfGradientDirections << " gradients + " << this->m_NumberOfBaselineImages
<< "baselines = " << m_NumberOfGradientDirections + this->m_NumberOfBaselineImages
<< " directions specified but image has " << gradientImage->GetVectorLength()
<< " components.");
}
this->ProcessObject::SetNthInput( 0,
const_cast< GradientImagesType* >(gradientImage) );
m_GradientImageTypeEnumeration = GradientIsInASingleImage;
}
template< class TReferenceImagePixelType,
class TGradientImagePixelType,
class TOdfPixelType,
int NrOdfDirections,
int NrBasisFunctionCenters>
void DiffusionQballReconstructionImageFilter< TReferenceImagePixelType,
TGradientImagePixelType, TOdfPixelType, NrOdfDirections,
NrBasisFunctionCenters>
::PrintSelf(std::ostream& os, Indent indent) const
{
std::locale C("C");
std::locale originalLocale = os.getloc();
os.imbue(C);
Superclass::PrintSelf(os,indent);
os << indent << "OdfReconstructionMatrix: " << m_ReconstructionMatrix << std::endl;
if ( m_GradientDirectionContainer )
{
os << indent << "GradientDirectionContainer: "
<< m_GradientDirectionContainer << std::endl;
}
else
{
os << indent <<
"GradientDirectionContainer: (Gradient directions not set)" << std::endl;
}
os << indent << "NumberOfGradientDirections: " <<
m_NumberOfGradientDirections << std::endl;
os << indent << "NumberOfBaselineImages: " <<
m_NumberOfBaselineImages << std::endl;
os << indent << "Threshold for reference B0 image: " << m_Threshold << std::endl;
os << indent << "BValue: " << m_BValue << std::endl;
if ( this->m_GradientImageTypeEnumeration == GradientIsInManyImages )
{
os << indent << "Gradient images haven been supplied " << std::endl;
}
else if ( this->m_GradientImageTypeEnumeration == GradientIsInManyImages )
{
os << indent << "A multicomponent gradient image has been supplied" << std::endl;
}
os.imbue( originalLocale );
}
}
#endif // __itkDiffusionQballReconstructionImageFilter_txx
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/itkMultiTensorImageFilter.h b/Modules/DiffusionCore/Algorithms/Reconstruction/itkMultiTensorImageFilter.h
index 9b8f087..d18d173 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/itkMultiTensorImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/itkMultiTensorImageFilter.h
@@ -1,200 +1,200 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*===================================================================
This file is based heavily on a corresponding ITK filter.
===================================================================*/
#ifndef __itkMultiTensorImageFilter_h_
#define __itkMultiTensorImageFilter_h_
#include "itkImageToImageFilter.h"
#include "itkVectorImage.h"
#include <mitkDiffusionPropertyHelper.h>
#include <vnl/algo/vnl_levenberg_marquardt.h>
#include <mitkOdfImage.h>
#include <mitkPeakImage.h>
#include <mitkTensorImage.h>
namespace itk{
/** \class MultiTensorImageFilter
*/
template< class TInPixelType, class TOutPixelType >
class MultiTensorImageFilter :
public ImageToImageFilter< VectorImage< TInPixelType, 3 >, Image< TOutPixelType, 3 > >
{
public:
typedef MultiTensorImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< VectorImage< TInPixelType, 3 >, Image< TOutPixelType, 3 > > Superclass;
typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientContainerType;
typedef itk::Image< unsigned char, 3> ItkUcharImageType;
typedef mitk::PeakImage::ItkPeakImageType PeakImageType;
typedef mitk::TensorImage::PixelType TensorType;
typedef mitk::TensorImage::ItkTensorImageType TensorImageType;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(MultiTensorImageFilter, ImageToImageFilter)
typedef typename Superclass::InputImageType InputImageType;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename Superclass::OutputImageRegionType OutputImageRegionType;
itkSetMacro( MaskImage, ItkUcharImageType::Pointer )
itkSetMacro( B_value, double )
itkSetMacro( GradientDirections, GradientContainerType::Pointer )
itkGetMacro( PeakImage, PeakImageType::Pointer )
std::vector< TensorImageType::Pointer > GetTensorImages(){ return m_TensorImages; }
protected:
MultiTensorImageFilter();
~MultiTensorImageFilter() {}
void PrintSelf(std::ostream& os, Indent indent) const override;
void BeforeThreadedGenerateData() override;
void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType) override;
double m_B_value;
std::vector<double> m_B_values;
std::vector<int> m_WeightedIndices;
std::vector<int> m_UnWeightedIndices;
GradientContainerType::Pointer m_GradientDirections;
ItkUcharImageType::Pointer m_MaskImage;
PeakImageType::Pointer m_PeakImage;
std::vector< TensorImageType::Pointer > m_TensorImages;
int m_NumTensors;
vnl_vector<double> FitSingleVoxel( const typename InputImageType::PixelType &input);
// struct multiTensorLeastSquaresFunction: public vnl_least_squares_function
// {
// GradientContainerType::Pointer gradientDirections;
// typename InputImageType::PixelType measurements;
// std::vector<double> bValues;
// double S0;
// int num_tensors;
// std::vector<int> weightedIndices;
// void set_S0(double val)
// {
// S0 = val;
// }
// void set_measurements(const typename InputImageType::PixelType& m)
// {
// measurements = m;
// }
// void set_bvalues(std::vector<double>& x)
// {
// bValues = x;
// }
// void set_weightedIndices(std::vector<int>& x)
// {
// weightedIndices = x;
// }
// void set_gradient_directions(const GradientContainerType::Pointer& directions)
// {
// gradientDirections = directions;
// }
// int check(int n)
// {
// if (n==1)
// return 6;
// return n*7;
// }
// multiTensorLeastSquaresFunction(unsigned int number_of_tensors=2, unsigned int number_of_measurements=1) :
// vnl_least_squares_function(check(number_of_tensors), number_of_measurements, no_gradient)
// {
// num_tensors = number_of_tensors;
// }
// void f(const vnl_vector<double>& x, vnl_vector<double>& fx) override
// {
// int elements = 7;
// for(auto s : weightedIndices)
// {
// GradientDirectionType g = gradientDirections->GetElement(s);
// g.normalize();
// itk::DiffusionTensor3D< double > S;
// S[0] = g[0]*g[0];
// S[1] = g[1]*g[0];
// S[2] = g[2]*g[0];
// S[3] = g[1]*g[1];
// S[4] = g[2]*g[1];
// S[5] = g[2]*g[2];
// double approx = 0;
// double penalty = 0;
// double f = 0;
// if (num_tensors==1 && x.size()==6)
// f = 1;
// for (int i=0; i<num_tensors; i++)
// {
// if (num_tensors>1 && x.size()>6 && x[elements-1+i*elements]<0) // penalty if volume fractiuon is < 0
// penalty += 10e6;
// if (num_tensors>1 && x.size()>6)
// f += fabs(x[elements-1+i*elements]);
// double D = x[0+i*elements]*S[0] + x[1+i*elements]*S[1] + x[2+i*elements]*S[2] +
// x[1+i*elements]*S[1] + x[3+i*elements]*S[3] + x[4+i*elements]*S[4] +
// x[2+i*elements]*S[2] + x[4+i*elements]*S[4] + x[5+i*elements]*S[5];
// double signal = S0 * std::exp ( -bValues[s] * D );
// if (num_tensors>1 && x.size()>6)
// signal *= x[elements-1+i*elements];
// approx += signal;
// }
// const double factor = measurements[s] - approx;
// penalty += fabs(f-1)*10e7; // penalty if volume fractiuon sum is != 1
// fx[s] = factor*factor + penalty;
// }
// }
// };
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkMultiTensorImageFilter.txx"
#endif
#endif //__itkMultiTensorImageFilter_h_
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/itkMultiTensorImageFilter.txx b/Modules/DiffusionCore/Algorithms/Reconstruction/itkMultiTensorImageFilter.txx
index 1a991ec..65a10b9 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/itkMultiTensorImageFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/itkMultiTensorImageFilter.txx
@@ -1,253 +1,253 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkMultiTensorImageFilter_txx
#define __itkMultiTensorImageFilter_txx
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionConstIteratorWithIndex.h"
#include "itkImageRegionIterator.h"
#include <itkDiffusionTensor3D.h>
#include <mitkMultiTensorFitter.h>
namespace itk {
template< class TInPixelType, class TOutPixelType >
MultiTensorImageFilter< TInPixelType, TOutPixelType>
::MultiTensorImageFilter()
: m_B_value(0)
, m_NumTensors(2)
{
this->SetNumberOfRequiredInputs( 1 );
}
template< class TInPixelType, class TOutPixelType >
void
MultiTensorImageFilter< TInPixelType, TOutPixelType>
::BeforeThreadedGenerateData()
{
typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0));
outputImage->FillBuffer(0.0);
m_UnWeightedIndices.clear();
m_WeightedIndices.clear();
m_B_values.clear();
for (unsigned int i=0; i<m_GradientDirections->Size(); i++)
{
GradientDirectionType g = m_GradientDirections->GetElement(i);
double twonorm = g.two_norm();
double b = m_B_value*twonorm*twonorm;
m_B_values.push_back(b);
if (b>100)
m_WeightedIndices.push_back(i);
else
m_UnWeightedIndices.push_back(i);
}
if (m_UnWeightedIndices.empty())
mitkThrow() << "Unweighted (b=0 s/mm²) image volume missing!";
itk::Vector<double, 3> spacing3 = outputImage->GetSpacing();
itk::Point<float, 3> origin3 = outputImage->GetOrigin();
itk::Matrix<double, 3, 3> direction3 = outputImage->GetDirection();
itk::ImageRegion<3> imageRegion3 = outputImage->GetLargestPossibleRegion();
itk::Vector<double, 4> spacing4;
itk::Point<float, 4> origin4;
itk::Matrix<double, 4, 4> direction4;
itk::ImageRegion<4> imageRegion4;
spacing4[0] = spacing3[0]; spacing4[1] = spacing3[1]; spacing4[2] = spacing3[2]; spacing4[3] = 1;
origin4[0] = origin3[0]; origin4[1] = origin3[1]; origin4[2] = origin3[2]; origin4[3] = 0;
for (int r=0; r<3; r++)
for (int c=0; c<3; c++)
direction4[r][c] = direction3[r][c];
direction4[3][3] = 1;
imageRegion4.SetSize(0, imageRegion3.GetSize()[0]);
imageRegion4.SetSize(1, imageRegion3.GetSize()[1]);
imageRegion4.SetSize(2, imageRegion3.GetSize()[2]);
imageRegion4.SetSize(3, 3*m_NumTensors);
m_PeakImage = PeakImageType::New();
m_PeakImage->SetSpacing( spacing4 );
m_PeakImage->SetOrigin( origin4 );
m_PeakImage->SetDirection( direction4 );
m_PeakImage->SetRegions( imageRegion4 );
m_PeakImage->Allocate();
m_PeakImage->FillBuffer(0.0);
m_TensorImages.clear();
for (int i=0; i<m_NumTensors; i++)
{
TensorImageType::Pointer tImg = TensorImageType::New();
tImg->SetSpacing( spacing3 );
tImg->SetOrigin( origin3 );
tImg->SetDirection( direction3 );
tImg->SetRegions( imageRegion3 );
tImg->Allocate();
m_TensorImages.push_back(tImg);
}
}
template< class TInPixelType, class TOutPixelType >
vnl_vector<double>
MultiTensorImageFilter< TInPixelType, TOutPixelType>::FitSingleVoxel( const typename InputImageType::PixelType &input)
{
double S0 = 0;
for (auto i : m_UnWeightedIndices)
S0 += input[i];
S0 /= m_UnWeightedIndices.size();
// signle tensor fit
mitk::MultiTensorFitter ls_fit(1, m_GradientDirections->size());
ls_fit.set_S0(S0);
ls_fit.set_weightedIndices(m_WeightedIndices);
ls_fit.set_bvalues(m_B_values);
ls_fit.set_gradient_directions(m_GradientDirections);
ls_fit.set_measurements(input);
vnl_levenberg_marquardt lm(ls_fit);
vnl_vector<double> x;
x.set_size(6);
x.fill(0.0);
lm.minimize(x);
// TensorType tensor;
vnl_vector<double> y;
y.set_size(7*m_NumTensors);
y.fill(0.0);
for (int i=0; i<6; i++)
{
y[i] = x[i];
// tensor[i] = x[i];
}
y[6]=1;
// double fa = tensor.GetFractionalAnisotropy();
if (m_NumTensors>1)
{
mitk::MultiTensorFitter ls_fit(m_NumTensors, m_GradientDirections->size());
ls_fit.set_S0(S0);
ls_fit.set_weightedIndices(m_WeightedIndices);
ls_fit.set_bvalues(m_B_values);
ls_fit.set_gradient_directions(m_GradientDirections);
ls_fit.set_measurements(input);
vnl_levenberg_marquardt lm(ls_fit);
for (int i=0; i<m_NumTensors; i++)
y[6+i*7] = 1.0/m_NumTensors;
lm.minimize(y);
}
return y;
}
template< class TInPixelType, class TOutPixelType >
void
MultiTensorImageFilter< TInPixelType, TOutPixelType>
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, ThreadIdType )
{
typedef ImageRegionConstIterator< InputImageType > InputIteratorType;
typename InputImageType::Pointer inputImagePointer = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
InputIteratorType git( inputImagePointer, outputRegionForThread );
git.GoToBegin();
while( !git.IsAtEnd() )
{
typename InputImageType::PixelType pix = git.Get();
vnl_vector<double> x = FitSingleVoxel(pix);
typedef itk::DiffusionTensor3D<float> TensorType;
int elements = 7;
for (int t=0; t<m_NumTensors; t++)
{
TensorType tensor;
double f = x[6+t*elements];
for (int i=0; i<6; i++)
tensor[i] = f * x[i+t*elements];
m_TensorImages.at(t)->SetPixel(git.GetIndex(), tensor);
}
// TensorType tensor;
// tensor.Fill(0.0);
// tensor[0] = x[0]*x[1];
// tensor[3] = tensor[0];
// tensor[5] = tensor[0];
// m_TensorImages.at(m_NumTensors+1)->SetPixel(git.GetIndex(), tensor);
// /// DWI from tensor
// int elements = 7;
// int num_ten = m_NumTensors;
// typename DiffusionImageType::PixelType dPix; dPix.SetSize(m_GradientDirections->Size()); dPix.Fill(0.0);
// for (unsigned int i=0; i<m_GradientDirections->Size(); i++)
// {
// GradientDirectionType g = m_GradientDirections->GetElement(i);
// double twonorm = g.two_norm();
// double b = m_B_value*twonorm*twonorm;
// itk::DiffusionTensor3D< double > S;
// S[0] = g[0]*g[0];
// S[1] = g[1]*g[0];
// S[2] = g[2]*g[0];
// S[3] = g[1]*g[1];
// S[4] = g[2]*g[1];
// S[5] = g[2]*g[2];
// double approx = 0;
// for (int i=0; i<num_ten; i++)
// {
// double D = x[0+i*elements]*S[0] + x[1+i*elements]*S[1] + x[2+i*elements]*S[2] +
// x[1+i*elements]*S[1] + x[3+i*elements]*S[3] + x[4+i*elements]*S[4] +
// x[2+i*elements]*S[2] + x[4+i*elements]*S[4] + x[5+i*elements]*S[5];
// approx += x[elements-1+i*elements] * 1000 * std::exp ( -b * D );
// }
// dPix[i] = approx;
// }
// m_OutDwi->SetPixel(oit.GetIndex(), dPix);
++git;
}
std::cout << "One Thread finished calculation" << std::endl;
}
template< class TInPixelType, class TOutPixelType >
void
MultiTensorImageFilter< TInPixelType, TOutPixelType>
::PrintSelf(std::ostream& os, Indent indent) const
{
Superclass::PrintSelf(os,indent);
}
}
#endif // __itkMultiTensorImageFilter_txx
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/itkOrientationDistributionFunction.h b/Modules/DiffusionCore/Algorithms/Reconstruction/itkOrientationDistributionFunction.h
index 5803168..2bb2950 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/itkOrientationDistributionFunction.h
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/itkOrientationDistributionFunction.h
@@ -1,249 +1,249 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkOrientationDistributionFunction_h
#define __itkOrientationDistributionFunction_h
#include <MitkDiffusionCoreExports.h>
#include "itkIndent.h"
#include "itkFixedArray.h"
#include "itkMatrix.h"
#include "itkSymmetricEigenAnalysis.h"
#include "itkSimpleFastMutexLock.h"
#include "itkDiffusionTensor3D.h"
#include "vtkPolyData.h"
#include "vtkPoints.h"
#include "vtkCellArray.h"
#include "vtkDelaunay2D.h"
#include "vtkCleanPolyData.h"
#include "vtkAppendPolyData.h"
#include "vtkPlane.h"
namespace itk
{
/** \class OrientationDistributionFunction
* \brief Represents an ODF
*
* Reference: David S. Tuch, Q-ball imaging,
* Magnetic Resonance in Medicine Volume 52 Issue 6, Pages 1358 - 1372
*
* \author Klaus Fritzsche, MBI
*
*/
template < typename TComponent, unsigned int NOdfDirections >
class OrientationDistributionFunction: public
FixedArray<TComponent,NOdfDirections>
{
public:
enum InterpolationMethods {
ODF_NEAREST_NEIGHBOR_INTERP,
ODF_TRILINEAR_BARYCENTRIC_INTERP,
ODF_SPHERICAL_GAUSSIAN_BASIS_FUNCTIONS
};
/** Standard class typedefs. */
typedef OrientationDistributionFunction Self;
typedef FixedArray<TComponent,NOdfDirections> Superclass;
/** Dimension of the vector space. */
itkStaticConstMacro(InternalDimension, unsigned int, NOdfDirections);
/** Convenience typedefs. */
typedef FixedArray<TComponent,
itkGetStaticConstMacro(InternalDimension)> BaseArray;
/** Define the component type. */
typedef TComponent ComponentType;
typedef typename Superclass::ValueType ValueType;
typedef typename NumericTraits<ValueType>::RealType AccumulateValueType;
typedef typename NumericTraits<ValueType>::RealType RealValueType;
typedef Matrix<TComponent, NOdfDirections, NOdfDirections> MatrixType;
typedef vnl_matrix_fixed<double, 3, NOdfDirections> DirectionsType;
/** Default constructor has nothing to do. */
OrientationDistributionFunction() {this->Fill(0); m_EigenAnalysisCalculated = false; }
OrientationDistributionFunction (const ComponentType& r) { this->Fill(r); m_EigenAnalysisCalculated = false; }
typedef ComponentType ComponentArrayType[ itkGetStaticConstMacro(InternalDimension) ];
/** Pass-through constructor for the Array base class. */
OrientationDistributionFunction(const Self& r): BaseArray(r) { m_EigenAnalysisCalculated = false; }
OrientationDistributionFunction(const ComponentArrayType r): BaseArray(r) { m_EigenAnalysisCalculated = false; }
/** Pass-through assignment operator for the Array base class. */
Self& operator= (const Self& r);
Self& operator= (const ComponentType& r);
Self& operator= (const ComponentArrayType r);
/** Aritmetic operations between pixels. Return a new OrientationDistributionFunction. */
Self operator+(const Self &vec) const;
Self operator-(const Self &vec) const;
const Self & operator+=(const Self &vec);
const Self & operator-=(const Self &vec);
/** Arithmetic operations between ODFs and scalars */
Self operator*(const RealValueType & scalar ) const;
Self operator/(const RealValueType & scalar ) const;
const Self & operator*=(const RealValueType & scalar );
const Self & operator/=(const RealValueType & scalar );
/** Return the number of components. */
static DirectionsType* GetDirections()
{
return itkGetStaticConstMacro(m_Directions);
}
/** Return the number of components. */
static unsigned int GetNumberOfComponents()
{
return itkGetStaticConstMacro(InternalDimension);
}
/** Return the value for the Nth component. */
ComponentType GetNthComponent(int c) const
{ return this->operator[](c); }
/** Return the value for the Nth component. */
ComponentType GetInterpolatedComponent( vnl_vector_fixed<double,3> dir, InterpolationMethods method ) const;
/** Set the Nth component to v. */
void SetNthComponent(int c, const ComponentType& v)
{ this->operator[](c) = v; }
/** Matrix notation, in const and non-const forms. */
ValueType & operator()( unsigned int row, unsigned int col );
const ValueType & operator()( unsigned int row, unsigned int col ) const;
/** Set the distribution to isotropic.*/
void SetIsotropic();
void InitFromTensor(itk::DiffusionTensor3D<TComponent> tensor);
/** Evaluate diffusion tensor as ellipsoid. */
void InitFromEllipsoid(itk::DiffusionTensor3D<TComponent> tensor);
/** Pre-Multiply by a Matrix as ResultingTensor = Matrix * ThisTensor. */
Self PreMultiply( const MatrixType & m ) const;
/** Post-Multiply by a Matrix as ResultingTensor = ThisTensor * Matrix. */
Self PostMultiply( const MatrixType & m ) const;
void Normalize();
Self MinMaxNormalize() const;
Self MaxNormalize() const;
void L2Normalize();
int GetPrincipalDiffusionDirectionIndex() const;
vnl_vector_fixed<double,3> GetPrincipalDiffusionDirection() const;
int GetNthDiffusionDirection(int n, vnl_vector_fixed<double,3> rndVec) const;
TComponent GetGeneralizedFractionalAnisotropy() const;
TComponent GetGeneralizedGFA(int k, int p) const;
TComponent GetNormalizedEntropy() const;
TComponent GetNematicOrderParameter() const;
TComponent GetStdDevByMaxValue() const;
ComponentType GetMaxValue() const;
ComponentType GetMinValue() const;
ComponentType GetMeanValue() const;
TComponent GetPrincipleCurvature(double alphaMinDegree, double alphaMaxDegree, int invert) const;
static std::vector<int> GetNeighbors(int idx);
static vtkPolyData* GetBaseMesh(){ComputeBaseMesh(); return m_BaseMesh;}
static void ComputeBaseMesh();
static double GetMaxChordLength();
static vnl_vector_fixed<double,3> GetDirection(int i);
private:
static vtkPolyData* m_BaseMesh;
static double m_MaxChordLength;
static DirectionsType* m_Directions;
static std::vector< std::vector<int>* >* m_NeighborIdxs;
static std::vector< std::vector<int>* >* m_AngularRangeIdxs;
static std::vector<int>* m_HalfSphereIdxs;
static itk::SimpleFastMutexLock m_MutexBaseMesh;
static itk::SimpleFastMutexLock m_MutexHalfSphereIdxs;
static itk::SimpleFastMutexLock m_MutexNeighbors;
static itk::SimpleFastMutexLock m_MutexAngularRange;
typename itk::DiffusionTensor3D<TComponent>::EigenValuesArrayType m_EigenValues;
typename itk::DiffusionTensor3D<TComponent>::EigenVectorsMatrixType m_EigenVectors;
bool m_EigenAnalysisCalculated;
};
/** This extra typedef is necessary for preventing an Internal Compiler Error in
* Microsoft Visual C++ 6.0. This typedef is not needed for any other compiler. */
typedef std::ostream OutputStreamType;
typedef std::istream InputStreamType;
template< typename TComponent, unsigned int NOdfDirections >
MITKDIFFUSIONCORE_EXPORT OutputStreamType& operator<<(OutputStreamType& os,
const OrientationDistributionFunction<TComponent,NOdfDirections> & c);
template< typename TComponent, unsigned int NOdfDirections >
MITKDIFFUSIONCORE_EXPORT InputStreamType& operator>>(InputStreamType& is,
OrientationDistributionFunction<TComponent,NOdfDirections> & c);
} // end namespace itk
// Define instantiation macro for this template.
#define ITK_TEMPLATE_OrientationDistributionFunction(_, EXPORT, x, y) namespace itk { \
_(2(class MITKDIFFUSIONCORE_EXPORT EXPORT OrientationDistributionFunction< ITK_TEMPLATE_2 x >)) \
namespace Templates { typedef OrientationDistributionFunction< ITK_TEMPLATE_2 x > \
OrientationDistributionFunction##y; } \
}
#if ITK_TEMPLATE_EXPLICIT
# include "Templates/itkOrientationDistributionFunction+-.h"
#endif
#if ITK_TEMPLATE_TXX
# include "itkOrientationDistributionFunction.txx"
#endif
#endif //__itkOrientationDistributionFunction_h
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/itkOrientationDistributionFunction.txx b/Modules/DiffusionCore/Algorithms/Reconstruction/itkOrientationDistributionFunction.txx
index 446cb64..885a635 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/itkOrientationDistributionFunction.txx
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/itkOrientationDistributionFunction.txx
@@ -1,1366 +1,1366 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _itkOrientationDistributionFunction_txx
#define _itkOrientationDistributionFunction_txx
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <vector>
#include <vnl/algo/vnl_matrix_inverse.h>
#include "itkPointShell.h"
#ifdef _MSC_VER
#if _MSC_VER <= 1700
#define fmin(a,b) ((a<=b)?(a):(b))
#define fmax(a,b) ((a>=b)?(a):(b))
#define isnan(c) (c!=c)
#endif
#endif
#include <itkMatrix.h>
#include <vnl/vnl_matrix.h>
#include <vnl/vnl_matrix_fixed.h>
#include <vnl/vnl_inverse.h>
#include <typeinfo>
#include <ciso646>
namespace itk
{
template<class T, unsigned int N>
vtkPolyData* itk::OrientationDistributionFunction<T,N>::m_BaseMesh = nullptr;
template<class T, unsigned int N>
double itk::OrientationDistributionFunction<T,N>::m_MaxChordLength = -1.0;
template<class T, unsigned int N>
vnl_matrix_fixed<double, 3, N>* itk::OrientationDistributionFunction<T,N>::m_Directions
= itk::PointShell<N, vnl_matrix_fixed<double, 3, N> >::DistributePointShell();
template<class T, unsigned int N>
std::vector< std::vector<int>* >* itk::OrientationDistributionFunction<T,N>::m_NeighborIdxs = nullptr;
template<class T, unsigned int N>
std::vector< std::vector<int>* >* itk::OrientationDistributionFunction<T,N>::m_AngularRangeIdxs = nullptr;
template<class T, unsigned int N>
std::vector<int>* itk::OrientationDistributionFunction<T,N>::m_HalfSphereIdxs = nullptr;
template<class T, unsigned int N>
itk::SimpleFastMutexLock itk::OrientationDistributionFunction<T,N>::m_MutexBaseMesh;
template<class T, unsigned int N>
itk::SimpleFastMutexLock itk::OrientationDistributionFunction<T,N>::m_MutexHalfSphereIdxs;
template<class T, unsigned int N>
itk::SimpleFastMutexLock itk::OrientationDistributionFunction<T,N>::m_MutexNeighbors;
template<class T, unsigned int N>
itk::SimpleFastMutexLock itk::OrientationDistributionFunction<T,N>::m_MutexAngularRange;
/**
* Assignment Operator
*/
template<class T, unsigned int NOdfDirections>
OrientationDistributionFunction<T, NOdfDirections>&
OrientationDistributionFunction<T, NOdfDirections>
::operator= (const Self& r)
{
BaseArray::operator=(r);
return *this;
}
/**
* Assignment Operator from a scalar constant
*/
template<class T, unsigned int NOdfDirections>
OrientationDistributionFunction<T, NOdfDirections>&
OrientationDistributionFunction<T, NOdfDirections>
::operator= (const ComponentType & r)
{
BaseArray::operator=(&r);
return *this;
}
/**
* Assigment from a plain array
*/
template<class T, unsigned int NOdfDirections>
OrientationDistributionFunction<T, NOdfDirections>&
OrientationDistributionFunction<T, NOdfDirections>
::operator= (const ComponentArrayType r )
{
BaseArray::operator=(r);
return *this;
}
/**
* Returns a temporary copy of a vector
*/
template<class T, unsigned int NOdfDirections>
OrientationDistributionFunction<T, NOdfDirections>
OrientationDistributionFunction<T, NOdfDirections>
::operator+(const Self & r) const
{
Self result;
for( unsigned int i=0; i<InternalDimension; i++)
{
result[i] = (*this)[i] + r[i];
}
return result;
}
/**
* Returns a temporary copy of a vector
*/
template<class T, unsigned int NOdfDirections>
OrientationDistributionFunction<T, NOdfDirections>
OrientationDistributionFunction<T, NOdfDirections>
::operator-(const Self & r) const
{
Self result;
for( unsigned int i=0; i<InternalDimension; i++)
{
result[i] = (*this)[i] - r[i];
}
return result;
}
/**
* Performs addition in place
*/
template<class T, unsigned int NOdfDirections>
const OrientationDistributionFunction<T, NOdfDirections> &
OrientationDistributionFunction<T, NOdfDirections>
::operator+=(const Self & r)
{
for( unsigned int i=0; i<InternalDimension; i++)
{
(*this)[i] += r[i];
}
return *this;
}
/**
* Performs subtraction in place
*/
template<class T, unsigned int NOdfDirections>
const OrientationDistributionFunction<T, NOdfDirections> &
OrientationDistributionFunction<T, NOdfDirections>
::operator-=(const Self & r)
{
for( unsigned int i=0; i<InternalDimension; i++)
{
(*this)[i] -= r[i];
}
return *this;
}
/**
* Performs multiplication by a scalar, in place
*/
template<class T, unsigned int NOdfDirections>
const OrientationDistributionFunction<T, NOdfDirections> &
OrientationDistributionFunction<T, NOdfDirections>
::operator*=(const RealValueType & r)
{
for( unsigned int i=0; i<InternalDimension; i++)
{
(*this)[i] *= r;
}
return *this;
}
/**
* Performs division by a scalar, in place
*/
template<class T, unsigned int NOdfDirections>
const OrientationDistributionFunction<T, NOdfDirections> &
OrientationDistributionFunction<T, NOdfDirections>
::operator/=(const RealValueType & r)
{
for( unsigned int i=0; i<InternalDimension; i++)
{
(*this)[i] /= r;
}
return *this;
}
/**
* Performs multiplication with a scalar
*/
template<class T, unsigned int NOdfDirections>
OrientationDistributionFunction<T, NOdfDirections>
OrientationDistributionFunction<T, NOdfDirections>
::operator*(const RealValueType & r) const
{
Self result;
for( unsigned int i=0; i<InternalDimension; i++)
{
result[i] = (*this)[i] * r;
}
return result;
}
/**
* Performs division by a scalar
*/
template<class T, unsigned int NOdfDirections>
OrientationDistributionFunction<T, NOdfDirections>
OrientationDistributionFunction<T, NOdfDirections>
::operator/(const RealValueType & r) const
{
Self result;
for( unsigned int i=0; i<InternalDimension; i++)
{
result[i] = (*this)[i] / r;
}
return result;
}
/**
* Matrix notation access to elements
*/
template<class T, unsigned int NOdfDirections>
const typename OrientationDistributionFunction<T, NOdfDirections>::ValueType &
OrientationDistributionFunction<T, NOdfDirections>
::operator()(unsigned int row, unsigned int col) const
{
unsigned int k;
if( row < col )
{
k = row * InternalDimension + col - row * ( row + 1 ) / 2;
}
else
{
k = col * InternalDimension + row - col * ( col + 1 ) / 2;
}
if( k >= InternalDimension )
{
k = 0;
}
return (*this)[k];
}
/**
* Matrix notation access to elements
*/
template<class T, unsigned int NOdfDirections>
typename OrientationDistributionFunction<T, NOdfDirections>::ValueType &
OrientationDistributionFunction<T, NOdfDirections>
::operator()(unsigned int row, unsigned int col)
{
unsigned int k;
if( row < col )
{
k = row * InternalDimension + col - row * ( row + 1 ) / 2;
}
else
{
k = col * InternalDimension + row - col * ( col + 1 ) / 2;
}
if( k >= InternalDimension )
{
k = 0;
}
return (*this)[k];
}
/**
* Set the Tensor to an Identity.
* Set ones in the diagonal and zeroes every where else.
*/
template<class T, unsigned int NOdfDirections>
void
OrientationDistributionFunction<T, NOdfDirections>
::SetIsotropic()
{
this->Fill(NumericTraits< T >::One / NOdfDirections);
}
/**
* InitFromTensor()
*/
template<class T, unsigned int NOdfDirections>
void
OrientationDistributionFunction<T, NOdfDirections>
::InitFromTensor(itk::DiffusionTensor3D<T> tensor)
{
m_EigenAnalysisCalculated = false;
for(unsigned int i=0; i<NOdfDirections; i++)
{
/*
* | t0 t1 t2 | g0
* g0 g1 g2 * | t1 t3 t4 | * g1
* | t2 t4 t5 | g2
*
* = g0 * (t0g0*t1g1*t2g2)
* + g1 * (t1g0+t3g1+t4g2)
* + g2 * (t2g0+t4g1+t5g2)
*/
T g0 = (*m_Directions)(0,i);
T g1 = (*m_Directions)(1,i);
T g2 = (*m_Directions)(2,i);
T t0 = tensor[0];
T t1 = tensor[1];
T t2 = tensor[2];
T t3 = tensor[3];
T t4 = tensor[4];
T t5 = tensor[5];
(*this)[i] = g0 * (t0*g0+t1*g1+t2*g2)
+ g1 * (t1*g0+t3*g1+t4*g2)
+ g2 * (t2*g0+t4*g1+t5*g2);
if ((*this)[i]<0 || (*this)[i]!=(*this)[i])
(*this)[i] = 0;
}
}
/**
* InitFromEllipsoid()
*/
template<class T, unsigned int NOdfDirections>
void OrientationDistributionFunction<T, NOdfDirections>::
InitFromEllipsoid( itk::DiffusionTensor3D<T> tensor )
{
m_EigenAnalysisCalculated = false;
FixedArray<T, 6> nulltensor;
nulltensor.Fill(0.0);
if( tensor == nulltensor )
{
for ( unsigned int it=0; it < NOdfDirections; ++it ){ (*this)[it] = (T)0; }
MITK_DEBUG << "OrientationDistributionFunction<" << typeid(T).name() << ", " << NOdfDirections
<< ">::InitFromEllipsoid(" << typeid(tensor).name()
<< ") encountered a nulltensor as dti input point and ignorend it.";
return;
}
tensor.ComputeEigenAnalysis( m_EigenValues, this->m_EigenVectors ); // gives normalized eigenvectors as lines i.e. rows.
m_EigenAnalysisCalculated = true;
double a = m_EigenValues[0]; // those eigenvalues are the 3 |axes of the ellipsoid|,
double b = m_EigenValues[1]; // ComputeEigenAnalysis gives eigenValues in ascending < order per default,
double c = m_EigenValues[2]; // therefor the third eigenVector is the main direction of diffusion.
if( a <= 0.0 || b <= 0.0 || c <= 0.0 )
{
for ( unsigned int it=0; it < NOdfDirections; ++it ){ (*this)[it] = (T)0; }
MITK_DEBUG << "OrientationDistributionFunction<" << typeid(T).name() << ", " << NOdfDirections
<< ">::InitFromEllipsoid(" << typeid(tensor).name()
<< ") encountered an eigenvalue <= 0 and ignored this input point.";
return;
}
// check magnitude and scale towards 1 to minimize numerical condition kappa:
#ifdef _MSC_VER
#if _MSC_VER <= 1700
int exponent_a = floor(std::log(a)/std::log(2));
int exponent_b = floor(std::log(b)/std::log(2));
int exponent_c = floor(std::log(c)/std::log(2));
#else
int exponent_a = std::ilogb(a);
int exponent_b = std::ilogb(b);
int exponent_c = std::ilogb(c);
#endif
#else
int exponent_a = std::ilogb(a);
int exponent_b = std::ilogb(b);
int exponent_c = std::ilogb(c);
#endif
T min_exponent= fmin(exponent_a, fmin(exponent_b, exponent_c) );
T max_exponent= fmax(exponent_c, fmax(exponent_b, exponent_a) );
int scale_exponent = floor(0.5 * (min_exponent + max_exponent));
double scaling = pow(2, scale_exponent);
a= a/scaling;
b= b/scaling;
c= c/scaling;
vnl_matrix_fixed<double, 3, 3> eigenBase; // for change of base system.
for (int row = 0 ; row < 3; ++row) // Transposing because ComputeEigenAnalysis(,) gave us _row_ vectors.
{
for (int col = 0; col < 3; ++col)
{
eigenBase(row, col) = this->m_EigenVectors(col, row);
}
}
eigenBase= vnl_inverse(eigenBase); // Assuming canonical orthonormal system x=[1;0;0];y=[0;1;0];z=[0;0;1] for original DT.
eigenBase.assert_finite();
#ifndef NDEBUG
double kappa=1.0;
{ // calculate numerical condition kappa= ||f(x)-f(x~)|| approximately:
double gxaa = pow( a, -2.0); double gybb = pow( b, -2.0); double gzcc = pow( c, -2.0);
kappa = sqrt( pow( a, 2.0)+ pow( b, 2.0)+ pow( c, 2.0) + 1 ) / (gxaa + gybb + gzcc)
* sqrt( pow( a, -6.0)+ pow( b, -6.0)+ pow( c, -6.0) + pow( a, -4.0)+ pow( b, -4.0)+ pow( c, -4.0) );
MITK_DEBUG <<"kappa= "<< kappa << ", eigenvalues= [" << a <<", "<< b <<", "<< c <<"], eigenbase= ["
<<eigenBase(0,0)<<", "<<eigenBase(1,0)<<", "<<eigenBase(2,0)<<"; "
<<eigenBase(0,1)<<", "<<eigenBase(1,1)<<", "<<eigenBase(2,1)<<"; "
<<eigenBase(0,2)<<", "<<eigenBase(1,2)<<", "<<eigenBase(2,2)<<"] ";
if( std::isnan(kappa) )
{
MITK_DEBUG << "oh noes: kappa was NaN, setting kappa to 1e5"; // typical value kappa=1e5 for 1e-6<=a,b,c<=1e-4.
kappa=1e5;
};
}
#endif
for( unsigned int i=0; i < NOdfDirections; ++i )
{
/// calculate probability p(g)=r as ellipsoids magnitude in direction of g' = B^-1 * g:
/// (g0*r/evx)² + (g1*r/evy)² + (g2*r/evz)² = 1, |g'|=1.
vnl_vector_fixed<double, 3> g( (*m_Directions)(0,i), (*m_Directions)(1,i), (*m_Directions)(2,i) );
g = eigenBase*g; // passive change of base system of g.
g = g.normalize(); // unit vectors necessary.
(*this)[i] = scaling / sqrt( (g[0]/a)*(g[0]/a) + (g[1]/b)*(g[1]/b) + (g[2]/c)*(g[2]/c) );
#ifndef NDEBUG
{ // boundary check for numerical stability, assuming sigma=6, ||f(x~)-f~(x~)|| <= eps*kappa*sigma.
T min_ev= fmin(a, fmin(b, c) ); T max_ev= fmax(c, fmax(b, a) );
double eps= std::numeric_limits<T>::epsilon();
assert( scaling*min_ev <= ((*this)[i] + eps*kappa*6.0) ); // we should be between smallest and
assert( (*this)[i] <= (scaling*max_ev + eps*kappa*6.0) ); // biggest eigenvalue.
}
#endif
if ( (*this)[i] < T(0) || (*this)[i] > T(1) || std::isnan((*this)[i]) ) // P∈[0;1] sanity check.
{ // C: NaN != NaN, C++11: isnan((*this)[i]).
MITK_DEBUG << "OrientationDistributionFunction<" << typeid(T).name() << ", " << NOdfDirections
<< ">::InitFromEllipsoid(" << typeid(tensor).name()
<< ") encountered a probability value out of range [0;1] and set it to zero: (*this)["
<< i <<"]= " << (*this)[i];
(*this)[i] = T(0);
}
}
}
/**
* L2-Normalization
*/
template<class T, unsigned int NOdfDirections>
void
OrientationDistributionFunction<T, NOdfDirections>
::L2Normalize()
{
T sum = 0;
for( unsigned int i=0; i<InternalDimension; i++)
{
sum += (*this)[i]*(*this)[i];
}
sum = std::sqrt(sum);
for( unsigned int i=0; i<InternalDimension; i++)
{
(*this)[i] = (*this)[i] / sum;
}
}
/**
* Normalization to PDF
*/
template<class T, unsigned int NOdfDirections>
void
OrientationDistributionFunction<T, NOdfDirections>
::Normalize()
{
T sum = 0;
for( unsigned int i=0; i<InternalDimension; i++)
{
sum += (*this)[i];
}
if (sum>0)
{
for( unsigned int i=0; i<InternalDimension; i++)
{
(*this)[i] = (*this)[i] / sum;
}
}
}
/**
* Min/Max-Normalization
*/
template<class T, unsigned int NOdfDirections>
OrientationDistributionFunction<T, NOdfDirections>
OrientationDistributionFunction<T, NOdfDirections>
::MinMaxNormalize() const
{
T max = NumericTraits<T>::NonpositiveMin();
T min = NumericTraits<T>::max();
for( unsigned int i=0; i<InternalDimension; i++)
{
max = (*this)[i] > max ? (*this)[i] : max;
min = (*this)[i] < min ? (*this)[i] : min;
}
Self retval;
for( unsigned int i=0; i<InternalDimension; i++)
{
retval[i] = ((*this)[i] - min) / (max - min);
}
return retval;
}
/**
* Max-Normalization
*/
template<class T, unsigned int NOdfDirections>
OrientationDistributionFunction<T, NOdfDirections>
OrientationDistributionFunction<T, NOdfDirections>
::MaxNormalize() const
{
T max = NumericTraits<T>::NonpositiveMin();
for( unsigned int i=0; i<InternalDimension; i++)
{
max = (*this)[i] > max ? (*this)[i] : max;
}
Self retval;
for( unsigned int i=0; i<InternalDimension; i++)
{
retval[i] = (*this)[i] / max;
}
return retval;
}
template<class T, unsigned int NOdfDirections>
T
OrientationDistributionFunction<T, NOdfDirections>
::GetMaxValue() const
{
T max = NumericTraits<T>::NonpositiveMin();
for( unsigned int i=0; i<InternalDimension; i++)
{
if((*this)[i] >= max )
{
max = (*this)[i];
}
}
return max;
}
template<class T, unsigned int NOdfDirections>
T
OrientationDistributionFunction<T, NOdfDirections>
::GetMinValue() const
{
T min = NumericTraits<T>::max();
for( unsigned int i=0; i<InternalDimension; i++)
{
if((*this)[i] >= min )
{
min = (*this)[i];
}
}
return min;
}
template<class T, unsigned int NOdfDirections>
T
OrientationDistributionFunction<T, NOdfDirections>
::GetMeanValue() const
{
T sum = 0;
for( unsigned int i=0; i<InternalDimension; i++)
sum += (*this)[i];
return sum/InternalDimension;
}
template<class T, unsigned int NOdfDirections>
double
OrientationDistributionFunction<T, NOdfDirections>
::GetMaxChordLength()
{
if(m_MaxChordLength<0.0)
{
ComputeBaseMesh();
double max_dist = -1;
vtkPoints* points = m_BaseMesh->GetPoints();
for(int i=0; i<NOdfDirections; i++)
{
double p[3];
points->GetPoint(i,p);
std::vector<int> neighbors = GetNeighbors(i);
for(std::size_t j=0; j<neighbors.size(); j++)
{
double n[3];
points->GetPoint(neighbors[j],n);
double d = sqrt(
(p[0]-n[0])*(p[0]-n[0]) +
(p[1]-n[1])*(p[1]-n[1]) +
(p[2]-n[2])*(p[2]-n[2]));
max_dist = d>max_dist ? d : max_dist;
}
}
m_MaxChordLength = max_dist;
}
return m_MaxChordLength;
}
template<class T, unsigned int NOdfDirections>
void
OrientationDistributionFunction<T, NOdfDirections>
::ComputeBaseMesh()
{
m_MutexBaseMesh.Lock();
if(m_BaseMesh == nullptr)
{
vtkPoints* points = vtkPoints::New();
for(unsigned int j=0; j<NOdfDirections; j++){
double x = (*m_Directions)(0,j);
double y = (*m_Directions)(1,j);
double z = (*m_Directions)(2,j);
double az = atan2(y,x);
double elev = atan2(z,sqrt(x*x+y*y));
double r = sqrt(x*x+y*y+z*z);
points->InsertNextPoint(az,elev,r);
}
vtkPolyData* polydata = vtkPolyData::New();
polydata->SetPoints( points );
vtkDelaunay2D *delaunay = vtkDelaunay2D::New();
delaunay->SetInputData( polydata );
delaunay->Update();
vtkCellArray* vtkpolys = delaunay->GetOutput()->GetPolys();
vtkCellArray* vtknewpolys = vtkCellArray::New();
vtkIdType npts; vtkIdType *pts;
while(vtkpolys->GetNextCell(npts,pts))
{
bool insert = true;
for(int i=0; i<npts; i++)
{
double *tmpPoint = points->GetPoint(pts[i]);
double az = tmpPoint[0];
double elev = tmpPoint[1];
if((std::abs(az)>itk::Math::pi-0.5) || (std::abs(elev)>itk::Math::pi/2-0.5))
insert = false;
}
if(insert)
vtknewpolys->InsertNextCell(npts, pts);
}
vtkPoints* points2 = vtkPoints::New();
for(unsigned int j=0; j<NOdfDirections; j++){
double x = -(*m_Directions)(0,j);
double y = -(*m_Directions)(2,j);
double z = -(*m_Directions)(1,j);
double az = atan2(y,x);
double elev = atan2(z,sqrt(x*x+y*y));
double r = sqrt(x*x+y*y+z*z);
points2->InsertNextPoint(az,elev,r);
}
vtkPolyData* polydata2 = vtkPolyData::New();
polydata2->SetPoints( points2 );
vtkDelaunay2D *delaunay2 = vtkDelaunay2D::New();
delaunay2->SetInputData( polydata2 );
delaunay2->Update();
vtkpolys = delaunay2->GetOutput()->GetPolys();
while(vtkpolys->GetNextCell(npts,pts))
{
bool insert = true;
for(int i=0; i<npts; i++)
{
double *tmpPoint = points2->GetPoint(pts[i]);
double az = tmpPoint[0];
double elev = tmpPoint[1];
if((std::abs(az)>itk::Math::pi-0.5) || (std::abs(elev)>itk::Math::pi/2-0.5))
insert = false;
}
if(insert)
vtknewpolys->InsertNextCell(npts, pts);
}
polydata->SetPolys(vtknewpolys);
for (unsigned int p = 0; p < NOdfDirections; p++)
{
points->SetPoint(p,m_Directions->get_column(p).data_block());
}
polydata->SetPoints( points );
m_BaseMesh = polydata;
}
m_MutexBaseMesh.Unlock();
}
/**
* Extract the index of the principal diffusion direction
*/
template<class T, unsigned int NOdfDirections>
int OrientationDistributionFunction<T, NOdfDirections>::GetPrincipalDiffusionDirectionIndex() const
{
T max = NumericTraits<T>::NonpositiveMin();
int maxidx = -1;
for( unsigned int i=0; i<InternalDimension; i++)
{
if((*this)[i] >= max )
{
max = (*this)[i];
maxidx = i;
}
}
return maxidx;
}
/**
* Extract the principal diffusion direction
*/
template<class T, unsigned int NOdfDirections>
vnl_vector_fixed<double,3> OrientationDistributionFunction<T, NOdfDirections>::GetPrincipalDiffusionDirection() const
{
if (m_EigenAnalysisCalculated)
{
vnl_vector_fixed<double,3> vec;
vec[0] = this->m_EigenVectors(2,0);
vec[1] = this->m_EigenVectors(2,1);
vec[2] = this->m_EigenVectors(2,2);
vec.normalize();
return vec;
}
else
{
int idx = GetPrincipalDiffusionDirectionIndex();
if (idx>0 && idx<(int)NOdfDirections)
return OrientationDistributionFunction<T, NOdfDirections>::GetDirection(idx);
vnl_vector_fixed<double,3> vec; vec.fill(0);
return vec;
}
}
template<class T, unsigned int NOdfDirections>
std::vector<int>
OrientationDistributionFunction<T, NOdfDirections>
::GetNeighbors(int idx)
{
ComputeBaseMesh();
m_MutexNeighbors.Lock();
if(m_NeighborIdxs == nullptr)
{
m_NeighborIdxs = new std::vector< std::vector<int>* >();
vtkCellArray* polys = m_BaseMesh->GetPolys();
for(unsigned int i=0; i<NOdfDirections; i++)
{
auto idxs = new std::vector<int>();
polys->InitTraversal();
vtkIdType npts; vtkIdType *pts;
while(polys->GetNextCell(npts,pts))
{
if( pts[0] == i )
{
idxs->push_back(pts[1]);
idxs->push_back(pts[2]);
}
else if( pts[1] == i )
{
idxs->push_back(pts[0]);
idxs->push_back(pts[2]);
}
else if( pts[2] == i )
{
idxs->push_back(pts[0]);
idxs->push_back(pts[1]);
}
}
std::sort(idxs->begin(), idxs->end());
std::vector< int >::iterator endLocation;
endLocation = std::unique( idxs->begin(), idxs->end() );
idxs->erase(endLocation, idxs->end());
m_NeighborIdxs->push_back(idxs);
}
}
m_MutexNeighbors.Unlock();
return *m_NeighborIdxs->at(idx);
}
/**
* Extract the n-th diffusion direction
*/
template<class T, unsigned int NOdfDirections>
int
OrientationDistributionFunction<T, NOdfDirections>
::GetNthDiffusionDirection(int n, vnl_vector_fixed<double,3> rndVec) const
{
if( n == 0 )
return GetPrincipalDiffusionDirectionIndex();
m_MutexHalfSphereIdxs.Lock();
if( !m_HalfSphereIdxs )
{
m_HalfSphereIdxs = new std::vector<int>();
for( unsigned int i=0; i<InternalDimension; i++)
{
if(dot_product(m_Directions->get_column(i),rndVec) > 0.0)
{
m_HalfSphereIdxs->push_back(i);
}
}
}
m_MutexHalfSphereIdxs.Unlock();
// collect indices of directions
// that are local maxima
std::vector<int> localMaxima;
std::vector<int>::iterator it;
for( it=m_HalfSphereIdxs->begin();
it!=m_HalfSphereIdxs->end();
it++)
{
std::vector<int> nbs = GetNeighbors(*it);
std::vector<int>::iterator it2;
bool max = true;
for(it2 = nbs.begin();
it2 != nbs.end();
it2++)
{
if((*this)[*it2] > (*this)[*it])
{
max = false;
break;
}
}
if(max)
localMaxima.push_back(*it);
}
// delete n highest local maxima from list
// and return remaining highest
int maxidx = -1;
for( int i=0; i<=n; i++ )
{
maxidx = -1;
T max = NumericTraits<T>::NonpositiveMin();
for(it = localMaxima.begin();
it != localMaxima.end();
it++)
{
if((*this)[*it]>max)
{
max = (*this)[*it];
maxidx = *it;
}
}
it = find(localMaxima.begin(), localMaxima.end(), maxidx);
if(it!=localMaxima.end())
localMaxima.erase(it);
}
return maxidx;
}
template < typename TComponent, unsigned int NOdfDirections >
vnl_vector_fixed<double,3> itk::OrientationDistributionFunction<TComponent, NOdfDirections>
::GetDirection( int i )
{
return m_Directions->get_column(i);
}
/**
* Interpolate a position between sampled directions
*/
template<class T, unsigned int NOdfDirections>
T
OrientationDistributionFunction<T, NOdfDirections>
::GetInterpolatedComponent(vnl_vector_fixed<double,3> dir, InterpolationMethods method) const
{
ComputeBaseMesh();
double retval = -1.0;
switch(method)
{
case ODF_NEAREST_NEIGHBOR_INTERP:
{
vtkPoints* points = m_BaseMesh->GetPoints();
double current_min = NumericTraits<double>::max();
int current_min_idx = -1;
for(int i=0; i<NOdfDirections; i++)
{
vnl_vector_fixed<double,3> P(points->GetPoint(i));
double dist = (dir-P).two_norm();
current_min_idx = dist<current_min ? i : current_min_idx;
current_min = dist<current_min ? dist : current_min;
}
retval = this->GetNthComponent(current_min_idx);
break;
}
case ODF_TRILINEAR_BARYCENTRIC_INTERP:
{
double maxChordLength = GetMaxChordLength();
vtkCellArray* polys = m_BaseMesh->GetPolys();
vtkPoints* points = m_BaseMesh->GetPoints();
vtkIdType npts; vtkIdType *pts;
double current_min = NumericTraits<double>::max();
polys->InitTraversal();
while(polys->GetNextCell(npts,pts))
{
vnl_vector_fixed<double,3> A(points->GetPoint(pts[0]));
vnl_vector_fixed<double,3> B(points->GetPoint(pts[1]));
vnl_vector_fixed<double,3> C(points->GetPoint(pts[2]));
vnl_vector_fixed<double,3> d1;
d1.put(0,(dir-A).two_norm());
d1.put(1,(dir-B).two_norm());
d1.put(2,(dir-C).two_norm());
double maxval = d1.max_value();
if(maxval>maxChordLength)
{
continue;
}
// Compute vectors
vnl_vector_fixed<double,3> v0 = C - A;
vnl_vector_fixed<double,3> v1 = B - A;
// Project direction to plane ABC
vnl_vector_fixed<double,3> v6 = dir;
vnl_vector_fixed<double,3> cross = vnl_cross_3d(v0, v1);
cross = cross.normalize();
vtkPlane::ProjectPoint(v6.data_block(),A.data_block(),cross.data_block(),v6.data_block());
v6 = v6-A;
// Calculate barycentric coords
vnl_matrix_fixed<double,3,2> mat;
mat.set_column(0, v0);
mat.set_column(1, v1);
vnl_matrix_inverse<double> inv(mat);
vnl_matrix_fixed<double,2,3> inver = inv.pinverse();
vnl_vector<double> uv = inv.pinverse()*v6;
// Check if point is in triangle
double eps = 0.01;
if( (uv(0) >= 0-eps) && (uv(1) >= 0-eps) && (uv(0) + uv(1) <= 1+eps) )
{
// check if minimum angle is the max so far
if(d1.two_norm() < current_min)
{
current_min = d1.two_norm();
vnl_vector<double> barycentricCoords(3);
barycentricCoords[2] = uv[0]<0 ? 0 : (uv[0]>1?1:uv[0]);
barycentricCoords[1] = uv[1]<0 ? 0 : (uv[1]>1?1:uv[1]);
barycentricCoords[0] = 1-(barycentricCoords[1]+barycentricCoords[2]);
retval = barycentricCoords[0]*this->GetNthComponent(pts[0]) +
barycentricCoords[1]*this->GetNthComponent(pts[1]) +
barycentricCoords[2]*this->GetNthComponent(pts[2]);
}
}
}
break;
}
case ODF_SPHERICAL_GAUSSIAN_BASIS_FUNCTIONS:
{
double maxChordLength = GetMaxChordLength();
double sigma = asin(maxChordLength/2);
// this is the contribution of each kernel to each sampling point on the
// equator
vnl_vector<double> contrib;
contrib.set_size(NOdfDirections);
vtkPoints* points = m_BaseMesh->GetPoints();
double sum = 0;
for(int i=0; i<NOdfDirections; i++)
{
vnl_vector_fixed<double,3> P(points->GetPoint(i));
double stv = dir[0]*P[0]
+ dir[1]*P[1]
+ dir[2]*P[2];
stv = (stv<-1.0) ? -1.0 : ( (stv>1.0) ? 1.0 : stv);
double x = acos(stv);
contrib[i] = (1.0/(sigma*sqrt(2.0*itk::Math::pi)))
*exp((-x*x)/(2*sigma*sigma));
sum += contrib[i];
}
retval = 0;
for(int i=0; i<NOdfDirections; i++)
{
retval += (contrib[i] / sum)*this->GetNthComponent(i);
}
break;
}
}
if(retval==-1)
{
std::cout << "Interpolation failed" << std::endl;
return 0;
}
return retval;
}
/**
* Calculate Generalized Fractional Anisotropy
*/
template<class T, unsigned int NOdfDirections>
T
OrientationDistributionFunction<T, NOdfDirections>
::GetGeneralizedFractionalAnisotropy() const
{
double mean = 0;
double std = 0;
double rms = 0;
for( unsigned int i=0; i<InternalDimension; i++)
{
T val = (*this)[i];
mean += val;
}
mean /= NOdfDirections;
for( unsigned int i=0; i<InternalDimension; i++)
{
T val = (*this)[i];
std += (val - mean) * (val - mean);
rms += val*val;
}
std *= NOdfDirections;
rms *= NOdfDirections - 1;
if(rms == 0)
{
return 0;
}
else
{
return sqrt(std/rms);
}
}
template < typename T, unsigned int N>
T itk::OrientationDistributionFunction<T, N>
::GetGeneralizedGFA( int k, int p ) const
{
double mean = 0;
double std = 0;
double rms = 0;
double max = NumericTraits<double>::NonpositiveMin();
for( unsigned int i=0; i<InternalDimension; i++)
{
double val = (double)(*this)[i];
mean += pow(val,(double)p);
max = val > max ? val : max;
}
max = pow(max,(double)p);
mean /= N;
for( unsigned int i=0; i<InternalDimension; i++)
{
double val = (double)(*this)[i];
std += (pow(val,(double)p) - mean) * (pow(val,(double)p) - mean);
if(k>0)
{
rms += pow(val,(double)(p*k));
}
}
std /= N - 1;
std = sqrt(std);
if(k>0)
{
rms /= N;
rms = pow(rms,(double)(1.0/k));
}
else if(k<0) // lim k->inf gives us the maximum
{
rms = max;
}
else // k==0 undefined, we define zeros root from 1 as 1
{
rms = 1;
}
if(rms == 0)
{
return 0;
}
else
{
return (T)(std/rms);
}
}
/**
* Calculate Nematic Order Parameter
*/
template < typename T, unsigned int N >
T itk::OrientationDistributionFunction<T, N>
::GetNematicOrderParameter() const
{
// not yet implemented
return 0;
}
/**
* Calculate StdDev by MaxValue
*/
template < typename T, unsigned int N >
T itk::OrientationDistributionFunction<T, N>
::GetStdDevByMaxValue() const
{
double mean = 0;
double std = 0;
T max = NumericTraits<T>::NonpositiveMin();
for( unsigned int i=0; i<InternalDimension; i++)
{
T val = (*this)[i];
mean += val;
max = (*this)[i] > max ? (*this)[i] : max;
}
mean /= InternalDimension;
for( unsigned int i=0; i<InternalDimension; i++)
{
T val = (*this)[i];
std += (val - mean) * (val - mean);
}
std /= InternalDimension-1;
if(max == 0)
{
return 0;
}
else
{
return (sqrt(std)/max);
}
}
template < typename T, unsigned int N >
T itk::OrientationDistributionFunction<T, N>
::GetPrincipleCurvature(double alphaMinDegree, double alphaMaxDegree, int invert) const
{
// following loop only performed once
// (computing indices of each angular range)
m_MutexAngularRange.Lock();
if(m_AngularRangeIdxs == nullptr)
{
m_AngularRangeIdxs = new std::vector< std::vector<int>* >();
for(unsigned int i=0; i<N; i++)
{
vnl_vector_fixed<double,3> pDir = GetDirection(i);
auto idxs = new std::vector<int>();
for(unsigned int j=0; j<N; j++)
{
vnl_vector_fixed<double,3> cDir = GetDirection(j);
double angle = ( 180 / itk::Math::pi ) * acos( dot_product(pDir, cDir) );
if( (angle < alphaMaxDegree) && (angle > alphaMinDegree) )
{
idxs->push_back(j);
}
}
m_AngularRangeIdxs->push_back(idxs);
}
}
m_MutexAngularRange.Unlock();
// find the maximum (or minimum) direction (remember index and value)
T mode;
int pIdx = -1;
if(invert == 0)
{
pIdx = GetPrincipalDiffusionDirectionIndex();
mode = (*this)[pIdx];
}
else
{
mode = NumericTraits<T>::max();
for( unsigned int i=0; i<N; i++)
{
if((*this)[i] < mode )
{
mode = (*this)[i];
pIdx = i;
}
}
}
//////////////////////
//////// compute median of mode and its neighbors to become more stable to noise
//////// compared to simply using the mode
//////////////////////
//////// values of mode and its neighbors
//////std::vector<int> nbs = GetNeighbors(pIdx);
//////std::vector<T> modeAndNeighborVals;
//////modeAndNeighborVals.push_back(mode);
//////int numNeighbors = nbs.size();
//////for(int i=0; i<numNeighbors; i++)
//////{
////// modeAndNeighborVals.push_back((*this)[nbs[i]]);
//////}
//////// sort by value
//////std::sort( modeAndNeighborVals.begin(), modeAndNeighborVals.end() );
//////// median of mode and neighbors
//////mode = modeAndNeighborVals[floor(0.5*(double)(numNeighbors+1)+0.5)];
////////////////
// computing a quantile of the angular range
////////////////
// define quantile
double quantile = 0.00;
// collect all values in angular range of mode
std::vector<T> odfValuesInAngularRange;
int numInRange = m_AngularRangeIdxs->at(pIdx)->size();
for(int i=0; i<numInRange; i++)
{
odfValuesInAngularRange.push_back((*this)[(*m_AngularRangeIdxs->at(pIdx))[i] ]);
}
// sort them by value
std::sort( odfValuesInAngularRange.begin(), odfValuesInAngularRange.end() );
// median of angular range
T median = odfValuesInAngularRange[floor(quantile*(double)numInRange+0.5)];
// compute and return final value
if(mode > median)
{
return mode/median - 1.0;
}
else
{
return median/mode - 1.0;
}
}
/**
* Calculate Normalized Entropy
*/
template < typename T, unsigned int N >
T itk::OrientationDistributionFunction<T, N>
::GetNormalizedEntropy() const
{
double mean = 0;
for( unsigned int i=0; i<InternalDimension; i++)
{
T val = (*this)[i];
if( val != 0 )
{
val = log(val);
}
else
{
val = log(0.0000001);
}
mean += val;
}
double _n = (double) InternalDimension;
mean /= _n;
return (T) (-_n / log(_n) * mean);
}
/**
* Pre-multiply the Tensor by a Matrix
*/
template<class T, unsigned int NOdfDirections>
OrientationDistributionFunction<T, NOdfDirections>
OrientationDistributionFunction<T, NOdfDirections>
::PreMultiply( const MatrixType & m ) const
{
Self result;
typedef typename NumericTraits<T>::AccumulateType AccumulateType;
for(unsigned int r=0; r<NOdfDirections; r++)
{
for(unsigned int c=0; c<NOdfDirections; c++)
{
AccumulateType sum = NumericTraits<AccumulateType>::ZeroValue();
for(unsigned int t=0; t<NOdfDirections; t++)
{
sum += m(r,t) * (*this)(t,c);
}
result(r,c) = static_cast<T>( sum );
}
}
return result;
}
/**
* Post-multiply the Tensor by a Matrix
*/
template<class T, unsigned int NOdfDirections>
OrientationDistributionFunction<T, NOdfDirections>
OrientationDistributionFunction<T, NOdfDirections>
::PostMultiply( const MatrixType & m ) const
{
Self result;
typedef typename NumericTraits<T>::AccumulateType AccumulateType;
for(unsigned int r=0; r<NOdfDirections; r++)
{
for(unsigned int c=0; c<NOdfDirections; c++)
{
AccumulateType sum = NumericTraits<AccumulateType>::ZeroValue();
for(unsigned int t=0; t<NOdfDirections; t++)
{
sum += (*this)(r,t) * m(t,c);
}
result(r,c) = static_cast<T>( sum );
}
}
return result;
}
/**
* Print content to an ostream
*/
template<class T, unsigned int NOdfDirections>
std::ostream &
operator<<(std::ostream& os,const OrientationDistributionFunction<T, NOdfDirections> & c )
{
for(unsigned int i=0; i<c.GetNumberOfComponents(); i++)
{
os << static_cast<typename NumericTraits<T>::PrintType>(c[i]) << " ";
}
return os;
}
/**
* Read content from an istream
*/
template<class T, unsigned int NOdfDirections>
std::istream &
operator>>(std::istream& is, OrientationDistributionFunction<T, NOdfDirections> & dt )
{
for(unsigned int i=0; i < dt.GetNumberOfComponents(); i++)
{
is >> dt[i];
}
return is;
}
} // end namespace itk
#endif
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/itkPointShell.h b/Modules/DiffusionCore/Algorithms/Reconstruction/itkPointShell.h
index f6b960a..2fc6aa6 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/itkPointShell.h
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/itkPointShell.h
@@ -1,47 +1,47 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkPointShell_h__
#define __itkPointShell_h__
#include "mitkOdfImage.h"
#include <MitkDiffusionCoreExports.h>
namespace itk
{
// generate by n-fold subdivisions of an icosahedron
template<int NPoints, class TMatrixType >
class PointShell
{
public:
static TMatrixType *DistributePointShell();
};
template<int NpointsShell1, int NpointsShell2, int NpointsShell3, class TMatrixTypeshell1, class TMatrixTypeshell2, class TMatrixTypeshell3>
class ThreeLayerPointShell
{
public:
static TMatrixTypeshell1 *DistributePointShell1();
static TMatrixTypeshell2 *DistributePointShell2();
static TMatrixTypeshell3 *DistributePointShell3();
};
}
#include "itkPointShell.txx"
#endif //__itkPointShell_h__
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/itkPointShell.txx b/Modules/DiffusionCore/Algorithms/Reconstruction/itkPointShell.txx
index c68daf2..1f1e92f 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/itkPointShell.txx
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/itkPointShell.txx
@@ -1,5242 +1,5242 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkPointShell_txx__
#define __itkPointShell_txx__
#include "vnl/vnl_vector_fixed.h"
#include "vnl/vnl_matrix_fixed.h"
namespace itk
{
template<int NPoints, class TMatrixType >
TMatrixType *
PointShell<NPoints, TMatrixType >
::DistributePointShell()
{
auto theta
= new vnl_vector_fixed<double,NPoints>();
auto phi
= new vnl_vector_fixed<double,NPoints>();
double C = sqrt(4*itk::Math::pi);
(*phi)(0) = 0.0;
(*phi)(NPoints-1) = 0.0;
for(int i=0; i<NPoints; i++)
{
(*theta)(i) = acos(-1.0+2.0*i/(NPoints-1.0)) - itk::Math::pi / 2.0;
if( i>0 && i<NPoints-1)
{
(*phi)(i) = ((*phi)(i-1) + C /
sqrt(NPoints*(1-(-1.0+2.0*i/(NPoints-1.0))*(-1.0+2.0*i/(NPoints-1.0)))));
// % (2*itk::Math::pi);
}
}
auto pointshell
= new vnl_matrix_fixed<double, 3, NPoints>();
for(int i=0; i<NPoints; i++)
{
(*pointshell)(0,i) = cos((*theta)(i)) * cos((*phi)(i));
(*pointshell)(1,i) = cos((*theta)(i)) * sin((*phi)(i));
(*pointshell)(2,i) = sin((*theta)(i));
}
return pointshell;
}
// generate by n-fold subdivisions of an icosahedron
// 1 - 12
// 2 - 42
// 3 - 92
// 4 - 162
// 5 - 252
// 6 - 362
// 7 - 492
// 8 - 642
// 9 - 812
// 10 - 1002
template<> class PointShell<12, vnl_matrix_fixed<double, 3, 12> >
{
public:
static vnl_matrix_fixed<double, 3, 12>* DistributePointShell()
{
double coords[3*12] = {
0.250254,0.320072,0.437594,
0.550563,0.623196,0.975676,
-0.250253,-0.320073,-0.437593,
-0.550563,-0.6231950000000001,-0.975676,
-0.916162,-0.078054,-0.598061,
0.758025,0.436642,-0.177816,
0.916161,0.078054,0.598061,
-0.758024,-0.436643,0.177817,
-0.313083,-0.944171,0.671442,
-0.349682,0.648821,-0.128204,
0.313082,0.944172,-0.671442,
0.349683,-0.648822,0.128204 };
auto pointshell
= new vnl_matrix_fixed<double, 3, 12>(coords);
return pointshell;
}
};
template<> class PointShell<42, vnl_matrix_fixed<double, 3, 42> >
{
public:
static vnl_matrix_fixed<double, 3, 42>* DistributePointShell()
{
double coords[3*42] = {
0.9756767549555488,0.9397937974509784,0.6231965669156312,
0.8971014254962764,0.6899186612252972,0.5505632701289798,
0.4375940376503738,0.06907711216819172,-0.3200730131503601,
0.6235168560971455,0.1781713819192711,0.3200724178002418,
0.7616224484252742,0.5117469206751248,0.2502538949373057,
0.4043068999720243,0.7205836671095894,0.8306996157029517,
-0.4375932291383154,-0.06907715072573903,0.06640211724156461,
-0.6231952788307174,-0.2192092047974508,-0.1781713502362079,
0.3352293490184233,-0.2502532651867688,-0.4043060780204903,
0.1765178736510398,-0.975676581463901,-0.9397935597648752,
-0.8306992108488227,-0.6235158879179115,0.21921067448898,
-0.7616223457476226,-0.3352294641675141,-0.7205834943870382,
-0.5117470172320778,-0.06640153973221416,-0.5505634949474448,
-0.176517304179968,-0.6899183532182501,-0.8971016370404784,
-0.1778161375899129,0.1521341729788544,0.4366423972091847,
0.3410385404813853,0.7022080829625521,0.7580253719184177,
-0.5980610514568759,-0.3056524524744078,0.07805400320688782,
-0.09487972868743588,0.3025309778153461,-0.07805410188638827,
-0.1503967869358663,0.3996773221825281,-0.9161616153729887,
-0.8900379255247358,-0.6430242175142256,-0.4560492515462431,
0.5980613131647216,0.3056526230838691,0.797087559189558,
-0.4366431953633789,-0.7951587738972527,-0.3025315118038733,
-0.5843857415998933,0.9161619708326186,0.8900381161951118,
0.9840623116657442,0.1778171059718252,-0.1521342296531137,
0.4560499397602033,0.09487917246041,0.7951586652134927,
0.1503972383762518,0.584385354546882,0.6430245879023526,
-0.399676350745083,-0.7970870947583816,-0.7580246814516085,
-0.9840624137666333,-0.7022083677250226,-0.3410374453295617,
-0.1282040992012935,0.3060111300013609,0.6488215902264565,
-0.2808945465452747,0.1758296024995542,-0.3496821715684524,
0.6714420577705413,0.9496341036793501,0.9441720387917811,
0.7760312926982584,0.9363385958760152,-0.9441722324566724,
-0.6303269409870232,-0.7605084662990487,-0.3130828685601688,
0.2106381298878163,-0.2593820240207756,0.3193074202631062,
-0.671442351589465,-0.9496340459616871,-0.6002017842451572,
-0.648822290296783,-0.5653935344751363,-0.9363384293729856,
-0.7389956620788968,0.3130823317650696,-0.2106389019045293,
-0.02151295053653907,0.1282040764044601,-0.3060118317848469,
-0.3193074905789999,-0.7760321386045594,0.5653931175085022,
0.6303269573377657,0.7389959159190775,0.2593815856416469,
0.7605089118538748,0.6002024649156598,0.3496833143594963,
0.02151295276860444,-0.175829673802738,0.2808952005684321 };
auto pointshell
= new vnl_matrix_fixed<double, 3, 42>(coords);
return pointshell;
}
};
template<> class PointShell<92, vnl_matrix_fixed<double, 3, 92> >
{
public:
static vnl_matrix_fixed<double, 3, 92>* DistributePointShell()
{
double coords[3*92] = {
0.9756767549555487,0.9881046683022421,0.8528238339140162,
0.6231965669156312,0.9602286065935876,0.9016229543668698,
0.68966672282401,0.7970712198937139,0.6617902410567804,
0.5505632701289798,0.4375940376503739,0.2130515669413184,
-0.07773888316805401,-0.3200730131503601,0.575075565563677,
0.3107083252171692,-0.006505365777837463,0.6463093264667951,
0.3555189519163455,0.3200724178002418,0.6201479032959075,
0.8717669667532965,0.4569904905821254,0.7744719807282636,
0.5454521871592555,0.2502538949373057,0.3600408236839538,
0.4319414682718342,0.5665551499276381,0.697797754038698,
0.7103565350090897,0.8449704612165639,0.9168712118355732,
-0.4375932291383153,-0.213051272338593,0.07773856031405026,
-0.1245894223683107,0.181648017057727,0.2546621526726748,
-0.6231952788307172,-0.3823142165271753,-0.04708691012811009,
-0.3555183995893311,-0.02217694060430831,0.3149362814931866,
0.006504983859799645,0.3417324928044827,-0.2502532651867688,
-0.3600400745299253,-0.4319406005716204,0.01921174674137865,
-0.05758606025521316,0.3265627679363224,-0.9756765814639009,
-0.988104613901425,-0.8528232434185344,-0.9168708930751739,
-0.854235225343551,-0.6463082287051728,-0.7103560109842373,
-0.5750746905699001,0.3823157740702657,0.0470881327099307,
0.3873829237054168,-0.6201479767677171,-0.8717667933239607,
-0.3417327749428254,-0.6485010946606566,-0.8449702640289916,
-0.3149361858566655,-0.5665549223826651,0.854235631268382,
-0.4569906864326022,-0.1816479322770386,0.1245901828483064,
-0.5454522916908328,-0.2546618495309371,-0.5505634949474448,
0.6485010946606566,0.05758689641252078,-0.01921097131735245,
-0.3265625234832059,-0.3107079508004592,-0.3873820250532686,
-0.6896660583043277,-0.6617902107749167,-0.6977972953381247,
-0.9016230372124288,-0.9602286916122059,-0.7970714969272577,
0.02217737847260294,-0.774471897882643,-0.1778161375899129,
0.03109142233089637,0.2669187829195654,0.4366423972091846,
0.1544374088220477,0.4265382311030135,0.6260922126282031,
0.5136107375104821,0.7494380454402638,0.7580253719184178,
-0.5980610514568761,-0.4291113361140411,-0.1696203080333493,
0.07805400320688781,-0.2914862882507431,-0.03496909012717316,
0.2274959035287995,0.1056298518860434,0.3651211825280409,
-0.07805410188638827,-0.1281592432697842,-0.1664476243728032,
0.2310143008479173,0.2106389321639752,0.5518992169467314,
-0.9161616153729886,-0.9327747060225072,-0.8106886470978539,
-0.771485918473268,-0.7097589298055721,-0.5273136421678301,
-0.4881111164997092,-0.3660248731570757,0.5980613131647216,
0.4291115157626469,0.1696204410073287,0.7499962909367706,
0.5360957563846484,0.8113900261915854,-0.4366431953633788,
-0.6867851479477911,-0.8708228680516066,-0.365121777041269,
-0.6002019152270697,-0.7331976694123558,-0.2274963530521035,
-0.4115345048612673,0.9161619708326186,0.9327749805257903,
0.8106887957474585,0.9941684586829005,0.9531387910864955,
0.9334760373935599,0.1778171059718252,-0.03109104889813258,
-0.266919222145987,0.3660256667153609,0.1422988506889488,
-0.1056306282458797,0.5273142067726671,0.2914860445503094,
0.6867847261588661,0.8708230332223915,0.8854287054759334,
0.1281594836202007,0.1664482855753907,0.4115339986401247,
0.4916319868779721,0.4881116080953447,0.7331975726799166,
0.7714862700692517,-0.1422987785572308,-0.2310136280273065,
-0.5360950867028047,-0.749995864312011,-0.551898166785698,
-0.8113895155772442,-0.7580246814516086,-0.4916319868779721,
-0.9531387450388693,-0.9941684373181742,-0.9334760519103793,
0.03496867572798409,-0.885428988462601,-0.6260926899993671,
-0.7494380619781833,0.7097593165624652,-0.4265380492676017,
-0.154436271103469,-0.513609764630649,0.6002015742230613,
-0.2106379566061765,-0.1282040992012935,0.1506070646973712,
0.448827218017063,0.6488215902264565,-0.232615798766268,
0.07170206110196441,0.3638246180723771,-0.3176184514965804,
-0.01939827024983318,-0.3496821715684524,0.6714420577705416,
0.8777656242085763,0.9824386073167399,0.9441720387917811,
0.7644107780855932,0.9498618317294465,0.9737573075945113,
0.7557291769626011,0.8604026946131842,-0.9441722324566724,
-0.7739455965390631,-0.4607792790679794,-0.8589482430980673,
-0.5965101770495287,-0.6307845637432553,-0.3130828685601688,
0.01737679733452725,0.3952347219739472,-0.2895250242862085,
0.09654302677976184,0.4661908578614318,-0.2185691140597737,
0.1592889611288683,-0.671442351589465,-0.8777656078901646,
-0.982438609905361,-0.649602216294724,-0.8243817913354027,
-0.5261115978506249,-0.6488222902967828,-0.6181925269683732,
-0.4893366483035592,-0.8604026705465684,-0.7995410210009178,
-0.6026908960383706,-0.9737572051250643,-0.8449013283633929,
0.3130823317650696,-0.01737758434298078,-0.3952353653550799,
0.1061130743462423,-0.2970021727032599,-0.1482539922220807,
0.1282040764044601,-0.1506074987015245,-0.4488280788164578,
-0.159288972427813,-0.5000332157715695,-0.7557300072673856,
-0.4661910177108468,-0.7644115292814133,0.6181920323103048,
0.4893362367199527,0.2568082513095248,0.7739454978673308,
0.4607793683387657,0.8449014608184471,0.5811577408091089,
0.2185687785328751,0.6026910636921159,0.2895245326714229,
0.5000325428335932,0.8589483198537152,0.8243822455102904,
0.6496025629973337,0.6307853921801013,0.5261125320735169,
0.3496833143594963,-0.5811577408091089,0.2970021583546204,
-0.1061134148983228,0.1482544392795429,-0.9498619694604108,
-0.2568086311939767,-0.3638250562458945,0.01939866440958929,
-0.0965434988571485,-0.07170210104888378,0.2326162031595532,
0.3176193294845107,0.7995412648414353,0.5965106290979496 };
auto pointshell
= new vnl_matrix_fixed<double, 3, 92>(coords);
return pointshell;
}
};
template<> class PointShell<162, vnl_matrix_fixed<double, 3, 162> >
{
public:
static vnl_matrix_fixed<double, 3, 162>* DistributePointShell()
{
double coords[3*162] = {
0.9756767549555488,0.9968737649581846,0.9397937974509784,
0.7989268505692991,0.6231965669156312,0.9764792677814802,
0.9657129396229355,0.8567905682573015,0.679558714000995,
0.8971014254962764,0.8343457228904876,0.6899186612252972,
0.7377425905504456,0.6387690340353133,0.5505632701289798,
0.4375940376503738,0.2787444080680243,0.06907711216819172,
-0.1467487371786262,-0.3200730131503601,0.5436064763029955,
0.3641181930198064,0.1299861910861632,-0.09463328683104604,
0.6235168560971455,0.421472539809791,0.1781713819192711,
0.6478378002177454,0.4350913076613168,0.3200724178002418,
0.543583002477908,0.7616224484252742,0.9117594243665534,
0.4242146396073646,0.6694499319211135,0.8720427891122669,
0.5117469206751248,0.7406754453578036,0.5536544075493044,
0.2502538949373057,0.3336803609057232,0.4043068999720243,
0.438887490788423,0.4847692553550146,0.5913899314506929,
0.6492812914734455,0.6425800233106177,0.7205836671095894,
0.8155579470101821,0.8306996157029517,0.8921547074343706,
0.9447583574027534,-0.4375932291383154,-0.278743955138478,
-0.06907715072573903,0.1467483093137361,-0.2140239599986307,
-0.001406336898152031,0.2327251986251803,0.06640211724156461,
0.3039508137298482,0.3409081262151013,-0.6231952788307174,
-0.4546947222788382,-0.2192092047974508,0.03581973661208818,
-0.4350905112236564,-0.2089153242611869,0.0609953219830862,
0.3006812043050254,-0.1781713502362079,0.08257031568712175,
0.3352293490184233,0.09463277722176672,0.3398901915912972,
-0.2502532651867688,-0.3336796480610522,-0.4043060780204903,
-0.4388866188864613,-0.05621340666038893,-0.1197552832780665,
-0.1776465335448071,0.1765178736510398,0.1277105869872963,
0.3935116760630417,-0.975676581463901,-0.9968737272214637,
-0.9397935597648752,-0.7989260596435309,-0.9447580743829742,
-0.9308031701048347,-0.8218804228775519,-0.6478366382006043,
-0.8306992108488227,-0.7645261844287355,-0.6235158879179115,
-0.6425794288509028,-0.543605629081954,0.4546962564744617,
0.21921067448898,-0.03581866880653414,0.4779576265881325,
0.2080468003445843,0.4555126388719097,-0.543583197615373,
-0.7616223457476226,-0.9117592443356049,-0.3398905505309818,
-0.5766491384642831,-0.7792417673233771,-0.8921544952781482,
-0.3352294641675141,-0.5550737397870624,-0.7205834943870382,
-0.3006809838192767,-0.4847689570296102,0.8218810203164033,
0.9308033931946534,0.7645267056644409,-0.4242149221746557,
-0.2327253235991419,0.00140664545831139,0.2140247669633664,
-0.5117470172320778,-0.3039507303469009,-0.06640153973221416,
-0.5536545418185335,-0.3409079709201472,-0.5505634949474448,
0.7792418677670352,0.5766490604842006,0.5550737528785307,
0.1776474313398276,0.1197561650892531,0.05621421006516834,
-0.1277100030888262,-0.176517304179968,-0.3935115910448358,
-0.1299862309792015,-0.3641176806190365,-0.4214718858755578,
-0.2080457563809749,-0.477956563666828,-0.6795578679273953,
-0.4555121490743896,-0.6899183532182501,-0.6387691005409376,
-0.6492806993353901,-0.5913894852863821,-0.8155575864896008,
-0.8567903368462096,-0.9657130735429578,-0.9764792804081987,
-0.834345897568434,-0.8971016370404784,-0.7377428728490714,
-0.06099477310985241,0.2089161290281741,-0.08257033948198818,
-0.8720426859708773,-0.6694498734011487,-0.740675476302381,
-0.1778161375899129,-0.02718233037986957,0.1521341729788544,
0.3178872248051531,0.4366423972091847,0.06305939500089614,
0.2592762165236786,0.4491542846588709,0.5806638189836385,
0.3410385404813853,0.5484671467389891,0.7022080829625521,
0.5886123721388867,0.761147081998915,0.7580253719184177,
-0.5980610514568759,-0.4818747107897384,-0.3056524524744078,
-0.102179801407443,0.07805400320688782,-0.3811861908796716,
-0.2105722545208477,-0.001641189844283069,0.1883562467232593,
-0.09487972868743588,0.1091686599118738,0.3025309778153461,
0.1998858588754617,0.3897335832229792,-0.07805410188638827,
-0.1156801299839266,-0.1503967869358663,-0.1717048170733874,
0.1470965334761953,0.1310545667952879,0.100226360425432,
0.3996773221825281,0.3894173756029716,0.6166247865338805,
-0.9161616153729887,-0.93968222548459,-0.8900379255247358,
-0.7610423024299814,-0.8216809647863927,-0.8059784419089511,
-0.7076799521032789,-0.5537209611836944,-0.6430242175142256,
-0.577817181345379,-0.4560492515462431,-0.4070385900414059,
-0.3177184789930138,0.5980613131647216,0.4818748986235024,
0.3056526230838691,0.1021798945147061,0.7166389355513205,
0.5797448495418049,0.3708138719979267,0.797087559189558,
0.6291765311790336,0.8064720598658887,-0.4366431953633789,
-0.6250679008877252,-0.7951587738972527,-0.894357332660672,
-0.3897342152274581,-0.5770900179397438,-0.7252694054566711,
-0.7936687210308288,-0.3025315118038733,-0.4662800296194353,
-0.5843857415998933,-0.1883566309643827,-0.3230016809603438,
0.9161619708326186,0.9396825386256142,0.8900381161951118,
0.7610424573388179,0.98459889389352,0.985272860446651,
0.8869743499570832,0.9840623116657442,0.9364058649128151,
0.8957919700911449,0.1778171059718252,0.02718289859111821,
-0.1521342296531137,-0.3178878068603045,0.31771932061924,
0.1597779786826127,-0.03010074909289372,-0.1998866892639353,
0.4560499397602033,0.2896405921772683,0.09487917246041,
0.5537214556082512,0.3811861035860583,0.6250673427588886,
0.7951586652134927,0.8943575917970892,0.7872122199392447,
0.9353918603084618,0.8865248509843126,0.1156802730367007,
0.1503972383762518,0.1717055726654157,0.3230012075937738,
0.3862979863651042,0.4171265008378126,0.4070391829394841,
0.584385354546882,0.6452876111171104,0.6430245879023526,
0.7936687790069655,0.8216813253645509,0.03010042800399446,
-0.159777601870924,-0.2896404384341761,-0.1470960585711635,
-0.3708132697350703,-0.5797443521912047,-0.7166385361913998,
-0.399676350745083,-0.6291757405426562,-0.7970870947583816,
-0.6166237809711579,-0.8064715143730887,-0.7580246814516085,
-0.417126245587897,-0.3862981411371962,-0.6452875761129986,
-0.8869742038831786,-0.9852727972566903,-0.9845987728990332,
-0.9364058061885231,-0.9840624137666333,-0.8957918541675716,
0.001640881330767951,0.2105720065923513,-0.109169268647464,
-0.9353919526972201,-0.7872126141915534,-0.5806643774075225,
-0.8865251005609038,-0.7022083677250226,-0.7611469342493191,
0.707680317140174,0.8059787882713181,0.577817672809353,
-0.4491544873380491,-0.2592757174096171,-0.063058272648828,
-0.5484668466671915,-0.3410374453295617,-0.5886114742048517,
0.7252693007743299,0.5770896067011005,0.4662795459560942,
-0.1002253860034311,-0.1310538163159151,-0.3894163023521484,
-0.1282040992012935,0.07418771901881034,0.3060111300013609,
0.5105522497698926,0.6488215902264565,-0.2061837828129686,
0.01320461245153456,0.2533186742384155,0.4483631157317138,
-0.2808945465452747,-0.05523589088936585,0.1758296024995542,
-0.3305621657917769,-0.1123798946526014,-0.3496821715684524,
0.6714420577705413,0.8307215647087252,0.9496341036793501,
0.983882155708098,0.9441720387917811,0.7477894668983293,
0.9072360592139173,0.9915144459980433,0.9775308002021622,
0.7760312926982584,0.9002461340540874,0.9363385958760152,
0.7350862725086435,0.8116669810370153,-0.9441722324566724,
-0.8313456723553714,-0.6303269409870232,-0.3731115220313701,
-0.8935348618728204,-0.7312055040636086,-0.4790574606800003,
-0.7605084662990487,-0.5474979380988695,-0.5596790773588694,
-0.3130828685601688,-0.07519795113003093,0.2106381298878163,
0.4776948653078811,-0.299731815412124,-0.02562616156907596,
0.2786088475509629,0.5296074119458033,-0.2593820240207756,
0.03150460300683353,0.3193074202631062,-0.1959070295313489,
0.08053951964108649,-0.671442351589465,-0.8307216077305004,
-0.9496340459616871,-0.9838822098556939,-0.6637939293172054,
-0.8147968652653733,-0.8990751104656249,-0.6002017842451572,
-0.7153675946298389,-0.4830988161196208,-0.648822290296783,
-0.6344626299567083,-0.5653935344751363,-0.4459169294668335,
-0.8116671044980045,-0.7895071237697285,-0.6857578728711079,
-0.5288485365725882,-0.9363384293729856,-0.8807752703984302,
-0.7389956620788968,-0.9775307754986758,-0.8832579304805722,
0.3130823317650696,0.07519720122433592,-0.2106389019045293,
-0.4776954195825031,0.1655447705464922,-0.1220494268493898,
-0.4262841911656161,-0.02151295053653907,-0.3268548028226648,
-0.2066526242811376,0.1282040764044601,-0.07418801789892716,
-0.3060118317848469,-0.51055312502423,-0.08053951945115613,
-0.3287498381001709,-0.5688642328312289,-0.7350870708018485,
-0.3193074905789999,-0.5758541835274278,-0.7760321386045594,
-0.5296076162752261,-0.7477901272839138,0.6344620803203709,
0.5653931175085022,0.4459164955009389,0.389683753785766,
0.2859346018498913,0.08112906023855893,0.831345524857385,
0.6303269573377657,0.3731116142445962,0.8832579654623612,
0.7198955735651289,0.467747528435525,0.1959067638111305,
0.7389959159190775,0.5248781214125594,0.2593815856416469,
0.5288485749239231,0.2997313094215869,0.5688633866559212,
0.3287493895928871,0.5758535688432742,0.8935348059013593,
0.8990753265127792,0.8147972186077681,0.6637941002839092,
0.7605089118538748,0.7153683254339585,0.6002024649156598,
0.5596800524090022,0.4830998363360157,0.3496833143594963,
-0.4677475887278177,-0.7198955529773995,-0.5248781506021705,
0.4262841209617862,0.1220490717256491,-0.165545217365127,
0.326855199205205,0.02151295276860444,0.2066532886754674,
-0.9915144412787341,-0.9072363224101446,-0.9002463663906001,
-0.2859350592025221,-0.3896842610441149,-0.4483636748755489,
-0.0811290830782055,-0.175829673802738,0.1123805173372347,
-0.2786093002807504,0.02562556437243592,-0.03150492197167008,
-0.253319097564816,-0.01320461850800903,0.2061840662709727,
0.05523623192861417,0.2808952005684321,0.3305631346577989,
0.6857580324047194,0.78950721141067,0.8807755242176112,
0.4790578522946484,0.7312056921497674,0.5474986596025796 };
auto pointshell
= new vnl_matrix_fixed<double, 3, 162>(coords);
return pointshell;
}
};
template<> class PointShell<252, vnl_matrix_fixed<double, 3, 252> >
{
public:
static vnl_matrix_fixed<double, 3, 252>* DistributePointShell()
{
double coords[3*252] = {
0.9756767549555488,0.9977154378498742,0.9738192119472443,
0.8915721200771204,0.7646073555341725,0.6231965669156312,
0.9817040172417226,0.9870396762453547,0.9325589150767597,
0.8173592116492303,0.6708930871960926,0.9399233672993689,
0.9144882783890762,0.8267930935417315,0.6931818659696647,
0.8407280774774689,0.782394344826989,0.6762337155773353,
0.7005607434301688,0.6228579759074076,0.5505632701289798,
0.4375940376503738,0.3153040621970065,0.1569517536476641,
-0.01984099037382634,-0.1857690950088067,-0.3200730131503601,
0.5232435944036425,0.3889403678268736,0.2135250052622625,
0.02420694871807206,-0.1448539951504302,0.5971534158422009,
0.4482053228282282,0.2597018771197477,0.06677517278138323,
0.6404616222418184,0.4782876117785159,0.2868761951248767,
0.6459894362878276,0.4789651252338281,0.3200724178002418,
0.4973180497018747,0.6793811951363423,0.8323587928990375,
0.9308933612987835,0.4036036036586492,0.5984781165037405,
0.7817280923310203,0.9140795130247613,0.4809905907165384,
0.6759621154318279,0.8390728924802671,0.5347729120192694,
0.7094340284155564,0.5560356639783846,0.2502538949373057,
0.3171352000240629,0.3793963897789465,0.4231100429674418,
0.4410301813437042,0.4357529867703999,0.5208717223808415,
0.5850086433327374,0.611055499882272,0.6009463532173235,
0.6305067000562991,0.7188806066405239,0.7654898954879897,
0.7616477696596397,0.7997756996573342,0.8700831379830764,
0.8872031228985237,0.9155019734809123,0.9568003701205341,
-0.4375932291383153,-0.3153035222278598,-0.1569515927579475,
0.0198407706589918,0.1857686171195431,-0.2644927501381796,
-0.1064219080255857,0.07849995612144045,0.2583107784678281,
-0.04938676750055992,0.1358448755096817,0.3243479900672576,
0.1811879481039926,0.3692668145365748,0.3890115016151001,
-0.6231952788307174,-0.4943551945928708,-0.319458133528771,
-0.1156489798772063,0.08328895892415776,-0.4789641985801549,
-0.3127252940830145,-0.1059392282183739,0.1077444781964869,
0.2912280153186658,-0.2868758523956744,-0.08856892011805101,
0.1287405357080231,0.3245517154572714,-0.06677541204276306,
0.1413542883070481,0.3408430926744944,0.1448534358763926,
0.3374016489097037,-0.2502532651867688,-0.3171345072414974,
-0.3793956104585266,-0.4231091882680272,-0.4410293135613324,
-0.09929959410007272,-0.1535127609134815,-0.2052877394623771,
-0.2436963810571767,0.08175409117371149,0.04056025153798869,
-0.006048944565669369,0.2686152102237028,0.2319923070602857,
0.430309819720559,-0.975676581463901,-0.9977153903038788,
-0.9738191090293654,-0.8915716840571059,-0.7646064477130079,
-0.9568001079664734,-0.9598482725023617,-0.9044523389503778,
-0.7901672201648241,-0.6459882395962464,-0.8872027729137049,
-0.8582754834679532,-0.7705800268610806,-0.6404605781008121,
-0.7616472974254324,-0.7008201753656432,-0.5971525097007422,
-0.6009457148226922,-0.5232427588825813,0.4943566966479628,
0.3194596781650836,0.1156503154178581,-0.0832879858164388,
0.5222841738261358,0.3225497922064885,0.1018140973507329,
0.5217885230992481,0.3044789836562512,0.4873191346491355,
-0.4973183240635209,-0.6793811856410323,-0.8323586364840968,
-0.9308931819742911,-0.3374020539278631,-0.5261951664998159,
-0.7070125356849136,-0.8417962075837926,-0.9155017573317124,
-0.3408433114184408,-0.5265312606271311,-0.6896418460594331,
-0.7997755164970677,-0.3245517106425898,-0.4925847482169691,
-0.6305065080228541,-0.2912277152063287,-0.4357526334612896,
0.7901679726328494,0.9044526665335126,0.9598484396937114,
0.7705806468939737,0.858275831469383,0.7008207681995118,
-0.4036039458806759,-0.2583110138480089,-0.0784999126587471,
0.1064223584250461,0.264493571710179,-0.4809907334514471,
-0.3243480295764106,-0.1358446002697818,0.04938746901646566,
-0.5347730026038946,-0.3692667658371347,-0.1811875286592425,
-0.5560358190148772,-0.3890114324926668,-0.5505634949474449,
0.8417963565884857,0.7070125813068046,0.5261950179989611,
0.6896418985458221,0.5265311900255359,0.4925848265160583,
0.2436972866599269,0.2052886581368649,0.153513629451971,
0.09930039009433847,0.006049691633511915,-0.04055950638179381,
-0.08175337578691833,-0.2319919155781195,-0.2686148310916902,
-0.430309819678344,-0.02420720081803753,-0.2135248270679241,
-0.3889397838050994,-0.2597016312374675,-0.4482046405142344,
-0.4782867918076852,-0.1018130528605821,-0.322548598821141,
-0.5222830294256716,-0.6708921376896406,-0.304478224282928,
-0.5217878437313506,-0.6931813485878851,-0.4873188675145023,
-0.6762335873429084,-0.6228580878699612,-0.6110548409057,
-0.5850080622199078,-0.5208712693637837,-0.7654894328832393,
-0.7188802647693375,-0.8700828159137221,-0.8173587433845655,
-0.9325588839421305,-0.9870397834787261,-0.9817039872478999,
-0.8267930492778305,-0.9144884914916022,-0.9399235077793813,
-0.7823945479956939,-0.8407283372889187,-0.7005610213599369,
-0.1077438933887955,0.1059400956623477,0.3127262866621893,
-0.1287403742204129,0.08856921814263634,-0.1413545191115968,
-0.9140794058749131,-0.7817279594934516,-0.5984781448346268,
-0.8390728949381593,-0.6759620794963979,-0.709434131000089,
-0.1778161375899129,-0.06053925384414331,0.07929679392711581,
0.222673458561735,0.3458247516791153,0.4366423972091846,
0.01030826616734189,0.1591522280204451,0.3173816763430465,
0.4549463955350546,0.5521270265729551,0.2292788658415479,
0.3973400932411465,0.5502139834879405,0.6594089221868847,
0.4476465561008348,0.6096570464011057,0.7343998566036512,
0.629214796874201,0.7646693979379596,0.7580253719184178,
-0.5980610514568761,-0.5101530988159087,-0.382225667160838,
-0.2244621267538426,-0.06301328229424107,0.07805400320688782,
-0.4311039309963852,-0.3079662136138592,-0.1501157132113724,
0.01750888497279251,0.1650825345160538,-0.2148810450151756,
-0.06090095222676627,0.1073128739652992,0.2584097661066967,
0.02655484252908358,0.1901297170957776,0.3420822257932489,
0.2531835106264871,0.4022303494272352,-0.07805410188638827,
-0.1080255529483224,-0.1376217050758367,-0.1609000070073124,
-0.1740018618448228,0.09827676798573926,0.083291898217249,
0.06127443921955168,0.03526739273256396,0.2991139104294396,
0.2941068360088736,0.2692865316145088,0.4942032775296958,
0.4857723178878524,0.6512069539966677,-0.9161616153729886,
-0.9396953110011561,-0.9204280785344878,-0.8462030522374957,
-0.7293237120999879,-0.8470541513588044,-0.8482966176587544,
-0.7977006542517769,-0.6951661565374421,-0.566558592627622,
-0.7243096319272092,-0.6931460376496088,-0.6140043047773551,
-0.5016343691560573,-0.5520254073275178,-0.4928644880867128,
-0.403575153350467,-0.3587591578566765,-0.2886351685087218,
0.5980613131647216,0.5101532951859686,0.382225843595672,
0.2244622808787926,0.06301334452030186,0.6944632949786616,
0.5955168212825119,0.4473425940100297,0.2700417838303327,
0.7724043956082883,0.6553545192922715,0.4871408620353512,
0.8097301284690857,0.6725220182496192,0.8002534097038426,
-0.4366431953633789,-0.5869882376922511,-0.7332080507197046,
-0.8450980113065225,-0.9041113586460733,-0.4022310083998925,
-0.554596445154436,-0.6925605687496104,-0.7854318984598006,
-0.8250621271173465,-0.3420827953668352,-0.4840440064641756,
-0.6033456975789954,-0.6777531805937266,-0.2584102557043402,
-0.3819753792546441,-0.4821906665520286,-0.1650828712784331,
-0.270790845781693,0.9161619708326184,0.9396956424389374,
0.9204283182965946,0.8462032095340455,0.7293238793541417,
0.9749588444840027,0.9879501207294071,0.942053498973333,
0.8348196077814718,0.9950795014807369,0.9818515654328379,
0.9027098746674149,0.9581801446138297,0.9118246030313639,
0.8703772282258925,0.1778171059718252,0.06053992567271226,
-0.07929659020903117,-0.2226737578340799,-0.345825401239635,
0.2886360377097776,0.1672516508448342,0.02000533874392893,
-0.1285435155191929,-0.2531843553864728,0.403575906447316,
0.2774342678683828,0.1245598363284875,-0.02655554762561945,
0.5016349858535857,0.3695530582277636,0.2148806720954671,
0.5665590425344393,0.431103930292903,0.5869876102086139,
0.7332077514676827,0.845098078457225,0.9041116580482536,
0.7182616282077119,0.8617334421407644,0.9490975365686583,
0.8223898048944452,0.9416915744235097,0.8729720010540123,
0.1080256414522809,0.1376220280275969,0.1609005865750696,
0.1740026689030255,0.2707904196202965,0.3196768235430837,
0.3552546724685221,0.3677018240803483,0.3587598208776521,
0.4821901792282771,0.5389508449256169,0.5637713635689835,
0.5520258363563475,0.6777529577987501,0.7231337276202411,
0.724309982145211,0.8250622687013296,0.8470545173149734,
0.1285429999155006,-0.02000532948058562,-0.1672511147059996,
-0.1245600244829796,-0.2774338902981233,-0.3695528631494325,
-0.09827641615811868,-0.2700412859530667,-0.4473420975374328,
-0.5955164071695848,-0.6944629164413806,-0.2991130971968019,
-0.4871400501186961,-0.6553538941234454,-0.7724039524031648,
-0.4942022299541438,-0.6725212074710563,-0.8097296395344389,
-0.6512059956089504,-0.8002528392148971,-0.7580246814516085,
-0.3677014077761052,-0.3552545716101517,-0.3196770257819652,
-0.5637712030900536,-0.5389510214534028,-0.7231336172569296,
-0.8348194119106425,-0.9420533966954356,-0.9879499956150448,
-0.9749586635216289,-0.9027097279159257,-0.9818515951566739,
-0.9950795477220543,-0.9118244750171576,-0.9581802235578871,
-0.8703770126934449,-0.0175091339170676,0.1501155140512474,
0.3079660822386824,-0.1073133727582037,0.06090046334304851,
-0.1901304002696938,-0.9490974969653682,-0.8617336589899791,
-0.7182621005240754,-0.5521276321758419,-0.941691783045487,
-0.8223901593137167,-0.6594093292610237,-0.872972144171723,
-0.7343999908188845,-0.7646691446910742,0.6951665021597787,
0.7977009700656229,0.8482969664746548,0.6140047811934269,
0.6931464276818936,0.4928650597255946,-0.4549467775084718,
-0.3173815862988101,-0.1591515620353438,-0.01030716362341688,
-0.5502140363721867,-0.3973395475484636,-0.2292777334167206,
-0.609656670182737,-0.4476455277450017,-0.6292139442700462,
0.7854319364049284,0.6925603649758249,0.5545959620739339,
0.6033453603619342,0.4840435291285519,0.3819748711371402,
-0.03526641653115874,-0.06127364342066123,-0.0832913202753871,
-0.2692854573778917,-0.2941058574917593,-0.4857712605383084,
-0.1282040992012934,0.02998172476739921,0.2130449739264662,
0.394354771181159,0.5438573645627299,0.6488215902264565,
-0.1901340637026595,-0.02057293935230464,0.1720544722828635,
0.3534794142829396,0.4950335464190314,-0.252933321812349,
-0.07636778766011496,0.1169519253626288,0.2909961752861106,
-0.304612640171253,-0.1271903099934383,0.0580070042064605,
-0.3366056805211806,-0.1653138037361849,-0.3496821715684524,
0.6714420577705413,0.8002044514563711,0.9106424580428781,
0.9742808059046055,0.9805708386415104,0.9441720387917811,
0.7350956003099328,0.8682639008659977,0.9653353535299492,
0.9995536316680411,0.9755844796257857,0.7728091190204586,
0.8918537226509272,0.9597077065970592,0.9637247890765801,
0.767530944505584,0.857374860312736,0.8948082473172733,
0.7201359303293944,0.7802583897718675,-0.9441722324566724,
-0.8608166107545396,-0.7207644955095487,-0.5303678229575245,
-0.3211867088850157,-0.9096404828216634,-0.7967975927156801,
-0.620601831095295,-0.4039985827676406,-0.8241231220089414,
-0.6757043639889994,-0.4726959329165278,-0.6854057579633669,
-0.5106159168102177,-0.5164821811548767,-0.3130828685601688,
-0.128054626578418,0.09418349997750548,0.3239109228229815,
0.523048087763098,-0.3043330399192493,-0.09531787499064681,
0.146419102006115,0.3786227553496849,0.5638039035645359,
-0.2789925774668332,-0.05252850546893189,0.1924160430438771,
0.4101897544477446,-0.2358533016570041,-0.006318969895916147,
0.2236016867495729,-0.1820659309330632,0.03496843200875603,
-0.6714423515894649,-0.8002045390283683,-0.9106424117173109,
-0.9742807748705438,-0.9805709251787237,-0.6691519386893557,
-0.79626257796142,-0.8909109722488041,-0.9275521423149625,
-0.6332080201962388,-0.7430051304270751,-0.8108589038018792,
-0.5581290590099237,-0.6413705283620924,-0.4563600901355626,
-0.648822290296783,-0.6411378559950974,-0.600293640880965,
-0.5219527418637842,-0.4191009430775375,-0.7802586188950914,
-0.7711197529973893,-0.713538182957094,-0.6094980396194888,
-0.4842093859996422,-0.8948081394501657,-0.8705497953564927,
-0.7870195954857328,-0.6597854273844109,-0.9637246412193355,
-0.9132982945459158,-0.8070428410352181,-0.975584505681221,
-0.9015722073987464,0.3130823317650696,0.1280539101236855,
-0.09418429615654819,-0.3239116283455282,-0.523048586255087,
0.1989845274738189,-0.01970764286946627,-0.2653151882168217,
-0.4936479477555078,0.05597369301027853,-0.1852629737758222,
-0.4302072668465533,-0.09867461327158224,-0.3387557568094476,
-0.2393260112020272,0.1282040764044601,-0.0299819504088954,
-0.2130455201840074,-0.3943555879655132,-0.5438582278251758,
-0.03496843048443223,-0.2252069693946209,-0.4261053308619027,
-0.5992598174372795,-0.720136706807033,-0.2236017161594696,
-0.4317330442416767,-0.6250530132529536,-0.7675317913865697,
-0.4101898771205939,-0.6101488498350025,-0.7728099228904255,
-0.5638041319099237,-0.7350961954485662,0.6411372723067146,
0.6002931843810706,0.5219523372221417,0.4191004905746099,
0.4596949806286311,0.3916338931244087,0.2980734064957148,
0.226741584116328,0.1432114770939381,-0.02097489882147943,
0.8608164411414747,0.7207644427956729,0.5303678926086439,
0.3211867913977836,0.9015721838250796,0.7879881821713033,
0.6114960278478284,0.3951892122332402,0.1820657113417612,
0.8070430398170311,0.6574928275930984,0.4544842943197335,
0.2358529185889448,0.6597856586149884,0.4841878538357612,
0.2789921022280572,0.4842093252521232,0.3043325272261384,
0.5992589358516202,0.4261046359672609,0.2252066549797059,
0.6250522113657903,0.4317325950511361,0.6101482870567641,
0.9096403689902206,0.9275522217134882,0.8909112253661301,
0.796262827475376,0.6691520068054228,0.8241233338640371,
0.810859375773786,0.7430057321681839,0.6332085061147845,
0.6854064426268304,0.6413714065577412,0.5581299045184589,
0.5164832226272315,0.4563611494403301,0.3496833143594963,
-0.3951892821849063,-0.6114960336943951,-0.787988199289983,
-0.4544844137443082,-0.657492739431111,-0.484187939006181,
0.4936478319326018,0.2653148405479006,0.01970714938077021,
-0.1989850169013517,0.4302075642722875,0.1852629793843341,
-0.0559739158243807,0.3387563694841473,0.09867487876932232,
0.2393267951217032,-0.999553621201999,-0.9653354239158236,
-0.8682642090770526,-0.9597077173597477,-0.8918540989344099,
-0.8573751662344773,-0.2980738893651726,-0.3916343988495664,
-0.4596955428592778,-0.4950341577852201,-0.1432117197792371,
-0.2267418620329016,-0.2909964852939082,0.02097514873862574,
-0.05800679989935065,0.1653145532988453,-0.3786231842883476,
-0.1464197032303796,0.09531724619007391,-0.1924163631703616,
0.05252803743712917,0.006318730357784829,-0.3534800054422614,
-0.1720548071373146,0.02057294660420643,0.190134278339324,
-0.1169519894866824,0.07636807502743861,0.2529338262925594,
0.1271908635410245,0.3046134343217798,0.3366066958443542,
0.6094980941008995,0.7135382519498201,0.7711196978950583,
0.7870198804193677,0.8705500304441893,0.9132984713369965,
0.403998910419839,0.62060207699311,0.7967976318501995,
0.4726965405256068,0.6757048258462731,0.5106167801856609 };
auto pointshell
= new vnl_matrix_fixed<double, 3, 252>(coords);
return pointshell;
}
};
template<> class PointShell<362, vnl_matrix_fixed<double, 3, 362> >
{
public:
static vnl_matrix_fixed<double, 3, 362>* DistributePointShell()
{
double coords[3*362] = {
0.9756767549555487,0.9966345256373878,0.9881046683022421,
0.9397937974509782,0.8528238339140162,0.7412214378486838,
0.6231965669156312,0.9834769262997924,0.9946239689739521,
0.9675363014408187,0.8953435882073797,0.7874413200090197,
0.6642104349774659,0.9602286065935876,0.9526601679743949,
0.9016229543668698,0.8082746868815032,0.68966672282401,
0.8971014254962764,0.865591182877164,0.7933984257386667,
0.6899186612252972,0.7970712198937139,0.7447486127431006,
0.6617902410567804,0.6754324093484999,0.6115790799976598,
0.5505632701289798,0.4375940376503739,0.3383775196739809,
0.2130515669413184,0.06907711216819173,-0.07773888316805401,
-0.2106409255960856,-0.3200730131503601,0.5092547181142852,
0.4023388431564537,0.265404014577164,0.1102235177567159,
-0.04300669133613336,-0.1770183828831563,0.575075565563677,
0.4585983658816588,0.3107083252171692,0.1482373789939068,
-0.006505365777837463,0.6235168560971455,0.4966123011343984,
0.3414318272800055,0.178171381919271,0.6463093264667951,
0.5114333072914884,0.3555189519163455,0.6437455132939696,
0.5064909697503934,0.3200724178002418,0.4666605048128079,
0.6201479032959075,0.7616224484252742,0.8717669667532965,
0.9417225609211535,0.3896493566867455,0.5498790773446007,
0.7090922337204692,0.8433688828589941,0.9352336066902967,
0.4569904905821254,0.6220231833138386,0.7744719807282636,
0.8905764752647638,0.5117469206751248,0.6692307929647209,
0.8035074327650433,0.5454521871592555,0.6853580997057199,
0.5566669166856135,0.2502538949373057,0.3059448167491349,
0.3600408236839538,0.4043068999720242,0.4319414682718342,
0.441694708443188,0.4034206272561209,0.4730271557866856,
0.532848297654098,0.5712181400125941,0.5831430197408345,
0.573108039637807,0.5665551499276381,0.6430548267994817,
0.697797754038698,0.7197945422057391,0.7103565350090897,
0.7205836671095895,0.7916313033238946,0.830001177910469,
0.8306996157029517,0.8449704612165639,0.8994200667307424,
0.9168712118355732,0.9290744770112713,0.9630120083465428,
-0.4375932291383153,-0.3383769257894378,-0.213051272338593,
-0.069077150725739,0.07773856031405026,0.210640419502912,
-0.2966224671809508,-0.1723655417522876,-0.02500201334267453,
0.1301781584808292,0.2729791005675229,-0.1245894223683107,
0.02220568982766716,0.181648017057727,0.3325661017840546,
0.06640211724156465,0.224593525159963,0.3797737583307059,
0.2546621526726748,0.4084582460890006,0.4194124862841989,
-0.6231952788307172,-0.5191377313825043,-0.3823142165271753,
-0.2192092047974507,-0.04708691012811009,0.1137784201343049,
-0.5064899646320268,-0.3766634899185586,-0.2148504892229182,
-0.03595624973804722,0.1367370476543766,0.2846552253706529,
-0.3555183995893311,-0.2005508680670486,-0.02217694060430831,
0.1572376520619428,0.3149362814931866,-0.1781713502362079,
-0.007356907961155389,0.1715373930872541,0.3352293490184234,
0.006504983859799645,0.1777752170237141,0.3417324928044827,
0.1770178009419758,0.3352469806136632,-0.2502532651867688,
-0.305944136422603,-0.3600400745299253,-0.4043060780204903,
-0.4319406005716204,-0.4416938460694254,-0.1269352612818317,
-0.1739928009393344,-0.2202529758737042,-0.2586227459701909,
-0.284108486127532,0.01921174674137865,-0.0178650781598001,
-0.05758606025521316,-0.0946046496972474,0.1765178736510398,
0.1461529703905971,0.1077831731751904,0.3265627679363224,
0.2967152689909496,0.4533499532981318,-0.9756765814639009,
-0.9966344649740785,-0.988104613901425,-0.9397935597648753,
-0.8528232434185344,-0.7412204556286736,-0.9630117602017364,
-0.9724898559386537,-0.9443983719046766,-0.872205391539895,
-0.7653064930405823,-0.6437442957669286,-0.9168708930751739,
-0.9063844772960285,-0.854235225343551,-0.7619985358162277,
-0.6463082287051728,-0.8306992108488227,-0.7961776618828416,
-0.7239846967363567,-0.6235158879179115,-0.7103560109842373,
-0.6562122899574033,-0.5750746905699001,-0.57310737178428,
-0.5092538887995088,0.5191392058051657,0.3823157740702657,
0.21921067448898,0.0470881327099307,-0.1137775092906953,
0.5472470006444878,0.3931697400830757,0.2142753542688524,
0.03384607877300972,0.5571877569557013,0.3873829237054168,
0.1993990574966068,0.5423114310655514,0.3634170963876792,
0.5045541233354154,-0.4666608333315146,-0.6201479767677171,
-0.7616223457476226,-0.8717667933239607,-0.9417223829869568,
-0.3352474166348553,-0.4910400536375052,-0.6475846838452103,
-0.7818611891844719,-0.8763941477411082,-0.9290742611527086,
-0.3417327749428254,-0.4990082491682611,-0.6485010946606566,
-0.7675612257958812,-0.8449702640289916,-0.3352294641675141,
-0.4847082676062016,-0.6189847486203324,-0.7205834943870382,
-0.3149361858566655,-0.4500011545486986,-0.5665549223826651,
-0.2846548708446658,-0.4034202330037945,0.7653073532861547,
0.872205859792842,0.9443985741044771,0.9724900050827093,
0.761999264311147,0.854235631268382,0.9063847463761845,
0.7239853440497003,0.7961780994118357,0.656212928522132,
-0.3896497406159066,-0.2729794041072619,-0.1301782703739063,
0.02500220716165068,0.1723660797382231,0.2966232936614225,
-0.4569906864326022,-0.3325662253633467,-0.1816479322770386,
-0.02220527620210722,0.1245901828483064,-0.5117470172320778,
-0.379773775950072,-0.2245933008307449,-0.0664015397322142,
-0.5454522916908328,-0.4084582325525932,-0.2546618495309371,
-0.5566670856360056,-0.4194124724547443,-0.5505634949474448,
0.8763943198737287,0.7818612997205676,0.6475846717443501,
0.4910398461057182,0.7675613256844861,0.6485010946606566,
0.4990081234589473,0.6189848075516286,0.4847082388524531,
0.450001299655162,0.2841093866952762,0.2586236728290179,
0.2202538772848093,0.1739936456875063,0.1269360432434686,
0.09460546886511037,0.05758689641252078,0.01786589383219402,
-0.01921097131735245,-0.1077825867383485,-0.1461523912078012,
-0.176517304179968,-0.2967150069434516,-0.3265625234832059,
-0.4533500040307881,0.04300632519905166,-0.1102235647973928,
-0.2654036978528873,-0.4023382153059064,-0.148237402516883,
-0.3107079508004592,-0.4585976694770509,-0.341431363569028,
-0.4966114955495211,-0.5114323842282982,-0.0338450669354788,
-0.2142741518944354,-0.3931684703578905,-0.5472458119265531,
-0.6642094200020999,-0.1993981773021475,-0.3873820250532686,
-0.5571869441797634,-0.6896660583043277,-0.3634165630969035,
-0.5423109973324143,-0.6899183532182501,-0.504553984174398,
-0.6617902107749167,-0.6115792176515682,-0.5831423229868272,
-0.5712174808640838,-0.5328477301676857,-0.4730266887482617,
-0.7197940112087894,-0.6977972953381247,-0.643054488612089,
-0.8300007800598662,-0.7916309980553373,-0.8994197666839766,
-0.787440689562144,-0.8953433656420341,-0.9675363415293142,
-0.9946240407011416,-0.9834768689460589,-0.8082744359221968,
-0.9016230372124288,-0.9526603585193832,-0.9602286916122059,
-0.7933984756354565,-0.8655914258905276,-0.8971016370404785,
-0.7447488265146829,-0.7970714969272577,-0.6754326817805886,
-0.1367364480221615,0.03595711502889169,0.2148515425621942,
0.3766645834143537,-0.1572373865760062,0.02217737847260294,
0.2005514111744157,-0.1715374471229988,0.007356909834687842,
-0.1777755545457471,-0.9352334959045954,-0.8433687324667886,
-0.7090921450939843,-0.5498791863597017,-0.8905764592918793,
-0.774471897882643,-0.6220231689320465,-0.8035075122026962,
-0.6692308066909014,-0.6853582437416091,-0.1778161375899129,
-0.08196112014272428,0.03109142233089637,0.1521341729788544,
0.2669187829195654,0.3632859224072412,0.4366423972091846,
-0.02374119024204515,0.09471244259515242,0.2248569419991813,
0.350706344617783,0.4558820271112225,0.5328176919569597,
0.1544374088220477,0.290680604004569,0.4265382311030135,
0.5423794137964371,0.6260922126282031,0.3410385404813853,
0.4823536424782295,0.6082030290912097,0.702208082962552,
0.5136107375104821,0.6447862719396159,0.7494380454402638,
0.6543855332308085,0.7656972306146125,0.7580253719184178,
-0.5980610514568761,-0.5275667073977156,-0.4291113361140411,
-0.3056524524744078,-0.1696203080333493,-0.0376422258299667,
0.07805400320688781,-0.4626069507186271,-0.367865039277211,
-0.2460698157210856,-0.1075922772772709,0.02954542570643959,
0.1497986786591435,-0.2914862882507431,-0.1726261297241735,
-0.03496909012717316,0.1043290137555473,0.2274959035287995,
-0.09487972868743588,0.03929513959897087,0.1777727700059916,
0.3025309778153461,0.1056298518860434,0.2403183339972744,
0.3651211825280409,0.2871566925727233,0.4096380159360284,
-0.07805410188638827,-0.1029113333575652,-0.1281592432697842,
-0.1503967869358663,-0.1664476243728032,-0.1752005995696255,
0.06662046905832243,0.05250750966401235,0.0344560317246887,
0.01402339491018058,-0.006131193542750579,0.2310143008479173,
0.2261291767278549,0.2106389321639752,0.1852638684253743,
0.399677322182528,0.3973696146518023,0.3769369479489949,
0.5518992169467314,0.5439427436094942,0.6724578932085956,
-0.9161616153729886,-0.9381742633287281,-0.9327747060225072,
-0.8900379255247358,-0.8106886470978539,-0.7076732091095549,
-0.8620450993411092,-0.8700248897395222,-0.8443283587296551,
-0.7791770527382307,-0.6830500709829336,-0.5739187050780551,
-0.771485918473268,-0.7582565243728648,-0.7097589298055721,
-0.6279538602818827,-0.5273136421678301,-0.6430242175142256,
-0.6070333936049677,-0.5418820315598687,-0.456049251546243,
-0.4881111164997092,-0.4360363777707778,-0.3660248731570757,
-0.327027482762229,-0.2694021154175107,0.5980613131647216,
0.5275669112241526,0.4291115157626469,0.305652623083869,
0.1696204410073287,0.03764226488103771,0.6790262210552894,
0.60193444501539,0.4907540154202648,0.3522765038549025,
0.2045239960649213,0.7499962909367706,0.6619943399357987,
0.5360957563846484,0.3850393813839648,0.7970875591895581,
0.6947571795971019,0.5562797487334057,0.8113900261915854,
0.6959590446635378,0.7949388873021738,-0.4366431953633788,
-0.5614655245500564,-0.6867851479477911,-0.7951587738972525,
-0.8708228680516066,-0.908932652052906,-0.4096386948450996,
-0.5369984265979351,-0.6595626659529629,-0.757774542842855,
-0.8188523117857327,-0.8439728473440037,-0.365121777041269,
-0.4879068833210152,-0.6002019152270697,-0.6843307714263435,
-0.7331976694123558,-0.3025315118038733,-0.4144630434096209,
-0.5126750515159538,-0.5843857415998934,-0.2274963530521035,
-0.3262252144152584,-0.4115345048612673,-0.1497989805512191,
-0.2366659840339851,0.9161619708326186,0.938174604388516,
0.9327749805257903,0.890038116195112,0.8106887957474585,
0.7076733877280226,0.9671526283488294,0.9837044593162763,
0.9631630917506131,0.8980117463611794,0.7967295682829974,
0.9941684586829005,0.9959257775132996,0.9531387910864955,
0.8656231437836883,0.9840623116657442,0.9635372003220445,
0.8983859076909864,0.9334760373935599,0.8907539689815491,
0.8525641076255658,0.1778171059718252,0.08196185466921782,
-0.03109104889813258,-0.1521342296531137,-0.266919222145987,
-0.363286609556101,0.2694030024488408,0.1709841140913856,
0.0528882307987244,-0.07296161244603722,-0.1901866620094973,
-0.2871575400870702,0.3660256667153609,0.2648098022646842,
0.1422988506889488,0.01311012528268693,-0.1056306282458797,
0.4560499397602033,0.3508815236279322,0.2250316837343615,
0.09487917246041001,0.5273142067726671,0.4179974732249477,
0.2914860445503094,0.5739191244872464,0.4626070035784272,
0.5614648567136933,0.6867847261588661,0.7951586652134927,
0.8708230332223915,0.9089329717882446,0.6702235465196067,
0.7988296386378929,0.8970417421055762,0.9520780267590907,
0.7664410264477003,0.8854287054759334,0.9628651295567006,
0.8322645377129818,0.9304765454032002,0.8591275181397264,
0.1029113872119272,0.1281594836202007,0.1503972383762519,
0.1664482855753907,0.175201438535584,0.2366655991467124,
0.2755134432217821,0.308440535504026,0.3288733874144261,
0.3341527600467577,0.3270281951640686,0.4115339986401247,
0.4596635416815941,0.4916319868779721,0.5005292304537458,
0.4881116080953447,0.584385354546882,0.6313194611701424,
0.6517522812978667,0.6430245879023526,0.7331975726799166,
0.7681409935232665,0.7714862700692517,0.8439730388551088,
0.8620454677591289,0.1901860445525563,0.0729613782704526,
-0.05288800289873952,-0.1709834836318114,-0.01311052982462483,
-0.1422987785572308,-0.2648092917366038,-0.2250317714436444,
-0.3508811505850218,-0.4179972559636759,-0.06662019868190015,
-0.2045235871714226,-0.3522760475882291,-0.490753594798392,
-0.6019340751777634,-0.6790258583886756,-0.2310136280273065,
-0.385038640575524,-0.5360950867028047,-0.6619938111098648,
-0.749995864312011,-0.399676350745083,-0.5562788600968236,
-0.6947565047867294,-0.7970870947583818,-0.551898166785698,
-0.6959582378852542,-0.8113895155772442,-0.6724569726942554,
-0.794938298671674,-0.7580246814516086,-0.3341522378920435,
-0.3288731104321892,-0.3084405200297279,-0.2755136565752797,
-0.5005289572181015,-0.4916319868779721,-0.4596638193626508,
-0.651752116850578,-0.6313195665821806,-0.7681408256666581,
-0.7967293465331413,-0.8980116136367456,-0.9631629650010809,
-0.9837042844506774,-0.9671524096287046,-0.8656229381767455,
-0.9531387450388693,-0.9959257826316365,-0.9941684373181742,
-0.8983857314821276,-0.9635372279543751,-0.9840624137666333,
-0.890753770890823,-0.9334760519103793,-0.8525638190917326,
-0.0295456393046314,0.1075921183812993,0.24606969704266,
0.3678649858572621,-0.1043294399383607,0.03496867572798409,
0.1726257663402015,-0.1777733562873886,-0.03929575512161578,
-0.2403190522322838,-0.9520779048267128,-0.8970418148986564,
-0.7988299587745943,-0.6702240741753134,-0.5328183289734231,
-0.9628652449155908,-0.885428988462601,-0.7664414449873368,
-0.6260926899993671,-0.9304767531770004,-0.8322648150388383,
-0.7022083677250226,-0.8591275565599557,-0.7494380619781833,
-0.7656969051450071,0.6830504023375936,0.7791773456982055,
0.8443286725827212,0.8700252447721738,0.6279543165738012,
0.7097593165624652,0.7582568868087332,0.5418825825925072,
0.6070338354963091,0.4360370100657923,-0.4558825077011868,
-0.3507064981157044,-0.2248566368863532,-0.0947116843681468,
0.02374227578387531,-0.5423796577050666,-0.4265380492676017,
-0.2906799053833736,-0.154436271103469,-0.6082029717256227,
-0.4823530727762694,-0.3410374453295618,-0.6447858429341417,
-0.513609764630649,-0.654384710247139,0.8188524345231695,
0.757774488968496,0.6595623604908243,0.5369978886010214,
0.6843305795053973,0.6002015742230613,0.4879063887999532,
0.512674598571755,0.4144625345167917,0.3262247228510809,
0.006132171174653799,-0.01402256634368312,-0.03445538312060447,
-0.05250705338074756,-0.1852627984273255,-0.2106379566061765,
-0.226128333686081,-0.376935865064754,-0.397368560322806,
-0.5439417227815399,-0.1282040992012935,0.001413185228105039,
0.1506070646973712,0.3060111300013609,0.448827218017063,
0.5644591381617006,0.6488215902264565,-0.1794700290349442,
-0.04186542201104336,0.1153813721057172,0.2745267180089526,
0.4148587047410423,0.5243374917023425,-0.232615798766268,
-0.08912570230038545,0.07170206110196441,0.2291650104977662,
0.3638246180723771,-0.2808945465452747,-0.1344874258557153,
0.02465792853592251,0.1758296024995542,-0.3176184514965804,
-0.1720469916489061,-0.01939827024983318,-0.3399568124040331,
-0.1991953311157892,-0.3496821715684524,0.6714420577705416,
0.7792137212760166,0.8777656242085763,0.9496341036793504,
0.9824386073167399,0.9768385042055774,0.9441720387917811,
0.7257096121901333,0.8383309419108317,0.9322072488654631,
0.9880661303797563,0.9986378183907035,0.9727408945826257,
0.7644107780855932,0.871715411213502,0.9498618317294465,
0.9834333410851046,0.9737573075945113,0.7760312926982584,
0.8670825303083295,0.9229415742963546,0.9363385958760152,
0.7557291769626011,0.8250351935145946,0.8604026946131842,
0.7093185095742097,0.7587249788041119,-0.9441722324566724,
-0.8784288421462625,-0.7739455965390631,-0.6303269409870232,
-0.4607792790679794,-0.2871643574027738,-0.9185505385856864,
-0.8335922034949309,-0.7042733744470981,-0.5371520006668183,
-0.3539781199209927,-0.8589482430980673,-0.7496350811244772,
-0.5965101770495287,-0.4153923937207508,-0.7605084662990487,
-0.6278754136763828,-0.4607541022738985,-0.6307845637432553,
-0.4841596501592634,-0.4877728218435191,-0.3130828685601688,
-0.1619469688877697,0.01737679733452725,0.2106381298878163,
0.3952347219739472,0.5514566289762698,-0.3068061997519851,
-0.1389316419038192,0.05641200521180441,0.2580561121281895,
0.4397576822043592,0.5849482839226374,-0.2895250242862085,
-0.1073663493645557,0.09654302677976184,0.2959218923430848,
0.4661908578614318,-0.2593820240207756,-0.06950063773914905,
0.1321435149365393,0.3193074202631061,-0.2185691140597737,
-0.03026253166221194,0.1592889611288683,-0.1728399308158635,
0.005511078744538343,-0.671442351589465,-0.7792138411724322,
-0.8777656078901646,-0.949634045961687,-0.982438609905361,
-0.9768386118322019,-0.6715195478039778,-0.7797211321494723,
-0.8709393754318948,-0.9267982045118057,-0.9400278430381637,
-0.649602216294724,-0.7491798190236064,-0.8243817913354027,
-0.8608974751546269,-0.6002017842451572,-0.6832790131816587,
-0.7391378312821431,-0.5261115978506249,-0.5905953516181053,
-0.4383666636546263,-0.6488222902967828,-0.6444008694878965,
-0.6181925269683732,-0.5653935344751363,-0.4893366483035592,
-0.4011183181354504,-0.7587252832301369,-0.7548226978527568,
-0.7202890787466467,-0.6515250496520278,-0.557479929039536,
-0.4546220799908838,-0.8604026705465684,-0.8495447148476215,
-0.7995410210009178,-0.7120166543368723,-0.6026908960383706,
-0.9363384293729855,-0.9100364067183718,-0.8412723782021747,
-0.7389956620788968,-0.9737572051250643,-0.9284250544292145,
-0.8449013283633929,-0.9727409539931392,-0.9119203221721993,
0.3130823317650696,0.1619462783427865,-0.01737758434298078,
-0.2106389019045294,-0.3952353653550799,-0.5514570904847834,
0.220234495302766,0.04529946956154991,-0.1542902631671154,
-0.3559342336221437,-0.5333895041467447,0.1061130743462423,
-0.08838939227573586,-0.2970021727032599,-0.4916772652886296,
-0.02151295053653907,-0.2241324894823635,-0.4257764066297352,
-0.1482539922220807,-0.3442635849044243,-0.2600158884245429,
0.1282040764044601,-0.001413366553346585,-0.1506074987015245,
-0.3060118317848468,-0.4488280788164578,-0.564459985716308,
-0.005511078361168723,-0.1582021264863434,-0.3245220334380661,
-0.4836676111525484,-0.6149268292273564,-0.7093192714417703,
-0.159288972427813,-0.3291548996161899,-0.5000332157715695,
-0.6474460255720145,-0.7557300072673856,-0.319307490579,
-0.4929333495466833,-0.6520789064271625,-0.7760321386045594,
-0.4661910177108468,-0.6282225265671552,-0.7644115292814133,
-0.5849485267562503,-0.7257101604516547,0.6444002635563192,
0.6181920323103048,0.5653931175085022,0.4893362367199527,
0.4011178519784379,0.5013193772200437,0.4552897581943395,
0.3865257888849735,0.3039767654183579,0.319546485626849,
0.2568082513095248,0.1820185654081009,0.1150393454476789,
0.04627539851448641,-0.08558647206366617,0.8784286613131731,
0.7739454978673308,0.6303269573377658,0.4607793683387657,
0.2871644290583872,0.9119202617664459,0.8264212051537363,
0.6967772336314446,0.5296559032972297,0.3468071953669221,
0.1728397432053184,0.8449014608184471,0.7346429035325667,
0.5811577408091089,0.4004001175275866,0.2185687785328751,
0.7389959159190774,0.6053871763277086,0.4382657239603054,
0.2593815856416469,0.6026910636921159,0.4554759872637936,
0.2895245326714229,0.4546219464457031,0.3068056829967603,
0.6149259495773405,0.4836668020692608,0.3245214821530512,
0.1582018910739125,0.6474451599919397,0.5000325428335932,
0.329154569384261,0.6520781574644046,0.4929329083973684,
0.6282220041094108,0.9185503953325266,0.9400278438555837,
0.9267983622223734,0.8709396068783997,0.7797212987315195,
0.6715195494525621,0.8589483198537152,0.8608977587445145,
0.8243822455102904,0.7491802985670569,0.6496025629973337,
0.7605089118538747,0.7391384910218132,0.6832797730640632,
0.6002024649156599,0.6307853921801013,0.5905963116881646,
0.5261125320735169,0.4877738980761407,0.4383677443133593,
0.3496833143594963,-0.3468072634833415,-0.5296559121107985,
-0.6967772517279487,-0.8264212573361066,-0.4004002676068469,
-0.5811577408091089,-0.734642815176818,-0.4382658852809146,
-0.6053870894221652,-0.4554761269845107,0.5333893556910446,
0.3559338950225972,0.1542897676170885,-0.04530002222683179,
-0.2202350051083672,0.491677469651672,0.2970021583546204,
0.08838916973894111,-0.1061134148983228,0.4257769268822734,
0.2241327483663198,0.02151295276860445,0.3442643233016264,
0.1482544392795429,0.2600167460395648,-0.998637827838979,
-0.988066142434594,-0.9322073703652781,-0.8383312666748716,
-0.9834332923270373,-0.9498619694604108,-0.8717158495436891,
-0.9229416329138649,-0.8670829638030551,-0.8250355565045274,
-0.3039772599799364,-0.3865262864971092,-0.4552902929786847,
-0.5013199694054605,-0.5243381301130434,-0.1820189194073548,
-0.2568086311939767,-0.319546898969995,-0.3638250562458945,
-0.04627540884770265,-0.1150393837809054,-0.1758296738027379,
0.08558690678521951,0.01939866440958929,0.1991961595715477,
-0.4397580914639075,-0.2580566866135989,-0.05641266799084353,
0.1389310087452558,-0.295922215665352,-0.0965434988571485,
0.107365815243832,-0.1321437542333658,0.06950025525528913,
0.03026233882278601,-0.4148593732748149,-0.2745272477919344,
-0.1153816305493603,0.04186543327713237,0.1794701997231261,
-0.2291653183673072,-0.07170210104888378,0.08912594410177796,
0.2326162031595532,-0.02465773800362392,0.134487905062478,
0.2808952005684321,0.1720476740810845,0.3176193294845107,
0.3399578552959914,0.5574798958328108,0.6515250645580214,
0.7202890442609949,0.754822534930785,0.7120168974234773,
0.7995412648414353,0.8495448706478895,0.841272643210163,
0.9100366384710021,0.9284251625234463,0.3539783956892765,
0.5371522584244614,0.7042734954121332,0.8335921603240184,
0.4153929051801631,0.5965106290979496,0.7496353473630305,
0.4607548496345096,0.6278760663083329,0.4841605931432954 };
auto pointshell
= new vnl_matrix_fixed<double, 3, 362>(coords);
return pointshell;
}
};
template<> class PointShell<492, vnl_matrix_fixed<double, 3, 492> >
{
public:
static vnl_matrix_fixed<double, 3, 492>* DistributePointShell()
{
double coords[3*492] = {
0.9756767549555487,0.995129146382046,0.9942990656144199,
0.9656349505028294,0.906669314667086,0.8226336999568686,
0.7243638464104109,0.6231965669156312,0.9839703767589784,
0.997142038124067,0.984428692964357,0.9391662760580684,
0.862670051560969,0.7648456045484533,0.6590519021583431,
0.9707167715611407,0.9718838371878742,0.9426229117731289,
0.8796306184740903,0.7892458129328142,0.6846076300785651,
0.929183358966584,0.9136522029381524,0.8666502644050813,
0.7898345918065129,0.693320589737796,0.8580670030245058,
0.8250351905308677,0.7641558269670571,0.6811699046825979,
0.7636773150775941,0.7169778531093051,0.6492336193335421,
0.6574101272386674,0.6032570204852985,0.5505632701289798,
0.4375940376503738,0.3542026794336651,0.2512745383622963,
0.1321836977435469,0.005435183516526082,-0.1177256014717769,
-0.2278158095071639,-0.3200730131503601,0.499121216713679,
0.4104288008617515,0.2993922246212043,0.1713800199472592,
0.03766821044034947,-0.08889959511906904,-0.1993010113619456,
0.5575360887326264,0.462310883286662,0.3429526003657482,
0.2075487278198905,0.06972486181048379,-0.0574641852590465,
0.6055762148233742,0.5027272059054465,0.3761219220443625,
0.2365775369888062,0.09858215717061569,0.6366252883681098,
0.5264243511029411,0.3955623729759449,0.2563797979489069,
0.647928555739847,0.5327472238507116,0.4019285426857001,
0.6416958910015911,0.5252922545125212,0.3200724178002418,
0.4449423089720693,0.5765874507842912,0.7038338496229432,
0.8135085046154491,0.8958808454008315,0.9485590875281112,
0.3796302423021757,0.5151344445922483,0.6532516657507655,
0.7794467577011209,0.879719713309462,0.9471999912418547,
0.4385611209938041,0.579827292674625,0.7171156368030697,
0.8342797026222076,0.9195293587283735,0.4904847582024935,
0.6301148467885526,0.7583069705424822,0.8604123883748889,
0.529043067100619,0.6594466179023598,0.7726806309784415,
0.5508150816257275,0.6670356654438421,0.5566867904077125,
0.2502538949373057,0.2979150767790733,0.345210193321538,
0.3870703453412754,0.4184100968812649,0.4364489070347424,
0.4418245296642042,0.3805829325031832,0.4390055479929592,
0.492568207092815,0.5338014037295256,0.5572819316169835,
0.5624691657697151,0.5532743164301828,0.5199151685430116,
0.5855041443032848,0.6393053209231115,0.6727852191382864,
0.6825747626046904,0.6719797747984303,0.6571141852151331,
0.7228163905998002,0.7689467902788032,0.7886244561063042,
0.78247330591778,0.7784686816166657,0.8360899632174316,
0.8684468597631155,0.8724880558103147,0.8732117959842211,
0.9170839626929869,0.9340377000206754,0.9378324283560583,
0.9666143691402809,-0.4375932291383153,-0.354202049210883,
-0.2512741515648044,-0.1321835946181268,-0.005435354322950186,
0.1177252152663303,0.2278152856398797,-0.318790682468547,
-0.2170414107297249,-0.09666371763400751,0.03477626912480049,
0.1650597498899593,0.28228599025285,-0.17643804815428,
-0.05685397486912016,0.07657633376040601,0.2119799408472924,
0.3357313012364012,-0.01650847491202961,0.1157420722211241,
0.2531713417578513,0.3818912918445931,0.1487980970433173,
0.2844888970254793,0.4153506930815835,0.3048153313129787,
0.4341873267571942,0.4402832445658493,-0.6231952788307174,
-0.5360175915304849,-0.4245963103234196,-0.291418513965459,
-0.1453010498480997,0.0007922214273259519,0.13494147117507,
-0.5252911977287607,-0.4194174780522606,-0.28881747505953,
-0.1402907332818909,0.01290161533377887,0.1562152529527386,
0.2798596737299269,-0.401927847344762,-0.2767587723714138,
-0.1302687984978551,0.02582668527333206,0.1758198972364496,
0.3070530822616677,-0.2563795458672579,-0.1157654558096325,
0.03830398324407951,0.191055688005941,0.3280904342412125,
-0.09858232519641157,0.04907792605008903,0.199937541973602,
0.3397702575045667,0.05746372336207268,0.2022279185194857,
0.3410562736291031,0.1993004179530413,0.3334923558881231,
-0.2502532651867688,-0.2979144048694595,-0.34520946527015,
-0.3870695532799813,-0.4184092501028168,-0.4364480352337543,
-0.4418236723862358,-0.1460995017681994,-0.1875439456120633,
-0.2289599148396085,-0.2657355106897256,-0.2936735229963843,
-0.3110073744636102,-0.02437365804953178,-0.05828840766257726,
-0.0937912788361675,-0.1272711110222873,-0.1553588546931559,
0.1088504388442424,0.08137944753513068,0.04932387614619547,
0.01557150971513331,0.2428173001617129,0.2183408313117627,
0.1859840000400707,0.3656411198910443,0.3402213332299013,
0.4690651309969549,-0.975676581463901,-0.995129073697949,
-0.9942990262685066,-0.9656348165534084,-0.9066689404406876,
-0.8226329948202892,-0.7243628133079894,-0.9666141311314619,
-0.9785291857720615,-0.9649167587949544,-0.9193242448617983,
-0.8431576679717276,-0.7462319572506099,-0.6416946598622301,
-0.9340374019521771,-0.9328600498682232,-0.9022446524809692,
-0.8392521444630035,-0.7502214356485383,-0.6479274205124774,
-0.8724876912825506,-0.8541267298323965,-0.8060828752150751,
-0.7303087484697733,-0.6366242668463477,-0.7824728542655722,
-0.7469876674129576,-0.6861081367635697,-0.6055752927616058,
-0.6719792111143933,-0.6239138376203725,-0.557535231009602,
-0.5532736276163508,-0.4991203912134258,0.5360190436422174,
0.4245978595344713,0.2914200439268497,0.1453024287888095,
-0.0007910862586512385,-0.1349406039583337,0.5628633831872754,
0.4391923979565908,0.2932083572735901,0.1374730553820866,
-0.01276978562268766,0.5775069821113988,0.4414551280568763,
0.2853595486273291,0.1249280534487668,0.5745152767417482,
0.4284746793321108,0.2676940340983546,0.5524169045150343,
0.4015572805868465,0.5149954726706612,-0.4449426764484256,
-0.576587591800914,-0.7038338094577924,-0.8135083597704743,
-0.8958806666660788,-0.9485589107573548,-0.3334928142377668,
-0.4656561029153702,-0.6013830911884229,-0.7267009436209915,
-0.8278508961406972,-0.8977211598944568,-0.9378322143189233,
-0.3410565997728103,-0.4760902226557944,-0.6097779474907786,
-0.7269418806406593,-0.8157918899746622,-0.8732115893121841,
-0.3397704479470293,-0.4718778429932776,-0.5973004074862646,
-0.7021751105216565,-0.7784685034185206,-0.3280904656572098,
-0.4519721780114144,-0.5652060578754561,-0.6571140026135045,
-0.3070529166634529,-0.4196426265222307,-0.5199149039850575,
-0.2798592799108112,-0.3805825072580722,0.7462328929439237,
0.843158260373911,0.9193245436545445,0.9649169034529495,
0.9785293294285902,0.7502222547730358,0.8392526460505537,
0.9022449400962008,0.9328602810500073,0.7303094694378339,
0.8060833454941833,0.8541270795356295,0.6861088083158182,
0.7469881692208658,0.6239145070358707,-0.3796306565856781,
-0.2822863401756764,-0.1650599593464782,-0.03477624931230538,
0.09666402587967657,0.2170420055376572,0.3187915103535204,
-0.4385613640703605,-0.3357314877557171,-0.2119799800663603,
-0.07657612650429085,0.05685448230997714,0.1764388387711721,
-0.4904848834824611,-0.3818913632934865,-0.2531712491023975,
-0.1157417111569205,0.01650914517247642,-0.5290431556806968,
-0.415350713896117,-0.2844887227712293,-0.1487976298306422,
-0.5508152020150771,-0.4341873428629178,-0.3048151129115739,
-0.5566869690240907,-0.4402832689070376,-0.5505634949474448,
0.8977213434708383,0.8278510409608931,0.7267010116232644,
0.601383022760614,0.4656558477896065,0.8157920246508805,
0.7269419391910862,0.6097779075806529,0.4760900512385949,
0.7021751903445496,0.5973004014138014,0.4718777509809839,
0.5652061482232076,0.4519722029963607,0.4196428289231057,
0.3110082673965054,0.2936744473798271,0.2657364265527945,
0.2289607907051673,0.1875447674114613,0.1461002696873639,
0.1553597055562715,0.1272719901065957,0.09379215148049876,
0.05828924862952556,0.02437445585198169,-0.01557080948102478,
-0.04932316861007474,-0.08137874963697227,-0.1088497589109511,
-0.1859835450151495,-0.2183403902096033,-0.2428168640462141,
-0.3402211599784607,-0.3656409687130195,-0.4690652148440055,
0.08889916251124211,-0.03766840286064398,-0.1713799135166342,
-0.2993918156335824,-0.4104281434194711,-0.06972505514639399,
-0.2075485942610162,-0.3429521440427875,-0.4623101760624211,
-0.2365773504687261,-0.3761213898309075,-0.5027264164274929,
-0.3955617526602613,-0.5264234573415938,-0.5327462324847574,
0.0127707607707569,-0.1374718849546943,-0.293207061528236,
-0.4391910893180505,-0.5628621680946149,-0.6590508424134647,
-0.1249271271017331,-0.2853585453187341,-0.4414541323690568,
-0.5775060764024141,-0.684606860838456,-0.2676933323589697,
-0.4284740156087684,-0.5745147048698985,-0.6933201342296018,
-0.4015569080051182,-0.5524166274339118,-0.6811697288917756,
-0.5149954132531107,-0.6492336477442618,-0.6032571744726157,
-0.562468445445845,-0.557281226121636,-0.5338007588723378,
-0.4925676465433573,-0.4390050662086606,-0.6825741836716002,
-0.6727846814032147,-0.6393048713560345,-0.5855037965960378,
-0.7886240006308879,-0.7689463943189565,-0.7228160987485833,
-0.8684464995603698,-0.8360896738847699,-0.9170836780332227,
-0.7648448608123986,-0.8626696659610523,-0.939166188119448,
-0.9844287505675849,-0.9971420785412131,-0.9839703005564542,
-0.789245396544295,-0.8796305387421426,-0.9426230395503291,
-0.9718839912389975,-0.9707168152563411,-0.7898344765948023,
-0.8666504070362878,-0.9136524365050784,-0.9291835215938483,
-0.7641559277074473,-0.8250354441736533,-0.8580672517338752,
-0.7169780714779912,-0.7636775971947915,-0.6574103946704876,
-0.1562146458746545,-0.01290076927461595,0.1402917844716378,
0.2888186351042548,0.4194186302321976,-0.1758195663775944,
-0.02582617528460154,0.1302694498290071,0.2767594860031721,
-0.1910556254438784,-0.03830382499862148,0.11576568242264,
-0.1999377238417288,-0.04907809969461731,-0.2022283181311396,
-0.9471998764213244,-0.8797195604896335,-0.7794466205193276,
-0.653251640029333,-0.5151346189117816,-0.9195293275646416,
-0.834279604589424,-0.717115548266178,-0.579827326676834,
-0.8604124463046277,-0.7583069490956061,-0.6301148416214684,
-0.7726807603671683,-0.659446675397405,-0.6670358344072718,
-0.1778161375899129,-0.09682873617143042,-0.002564331870712152,
0.1001489444293402,0.20294037487074,0.2966901028193483,
0.375180936757441,0.4366423972091846,-0.0474532387078642,
0.05034809081619229,0.1589075235585833,0.2695165933494903,
0.3711623656745905,0.4552971059046723,0.5189584406200277,
0.1017827048364344,0.2144158936234644,0.3316684820340907,
0.4414792935657015,0.5327981708248342,0.6005401860053867,
0.2614395442328129,0.3824105897655243,0.4989141911429241,
0.5982545824011208,0.6726053169812281,0.4179945008346566,
0.5376874271465311,0.6438148252422833,0.7263687759217851,
0.5575576702299878,0.6670994939031171,0.7570605631322944,
0.6714338802491097,0.7658357564785362,0.7580253719184177,
-0.5980610514568761,-0.539304606284799,-0.4601049879074139,
-0.3610209854418669,-0.247915131130675,-0.1308224218325103,
-0.01993206276454632,0.07805400320688782,-0.4842131513641215,
-0.4078776799069966,-0.3108032946618485,-0.1973076501762547,
-0.07725012597615898,0.03770515913931162,0.1390339189204285,
-0.3436782750638498,-0.2488690439489935,-0.1366770376390136,
-0.015847433302958,0.1014607675543575,0.2051261004110744,
-0.1810587170687898,-0.07134455272126199,0.04823642170967721,
0.1661580441221543,0.2713649127044082,-0.007965415159176724,
0.1085527127599039,0.2253294012222397,0.3313524432512411,
0.1602444452922388,0.2740270626018594,0.3797664442036205,
0.3106168108763466,0.4144914982680714,-0.07805410188638828,
-0.09926944144321027,-0.1210902608980977,-0.1414695137250296,
-0.1581584914998737,-0.1696765129666563,-0.1759038243562996,
0.0445080871572717,0.0312941062385701,0.01557512261039578,
-0.001683488527681644,-0.01888610824676229,-0.03445251803458384,
0.1827599102095679,0.1772109890337862,0.1655328468312471,
0.1477041886655562,0.1255191042072879,0.3281955954096453,
0.327054627020386,0.3149499526725762,0.2920106184972662,
0.4680615585920147,0.4660213421080895,0.4487906967476448,
0.5899485877914471,0.5822989875106862,0.6867607929057539,
-0.9161616153729887,-0.9364062548880398,-0.9378298619231508,
-0.9131962255692416,-0.8599818711884049,-0.7829080825969388,
-0.6920503887795537,-0.8718421840682521,-0.8825595832157751,
-0.8702495449678662,-0.8290948069847427,-0.7603667866829383,
-0.6729204873538853,-0.5786150802505966,-0.8013843264777428,
-0.7976661081468692,-0.768502718877635,-0.711654457383761,
-0.632841917808473,-0.5431812243043028,-0.7022906139785883,
-0.681473218889239,-0.6365518584536976,-0.5697323001067327,
-0.4894330041487118,-0.5787744062647625,-0.5426164975113815,
-0.4876750583595674,-0.4191311379161569,-0.4417943029188641,
-0.3959648506658267,-0.3385129506001341,-0.3046660637665696,
-0.2557948010777292,0.5980613131647217,0.5393048163248674,
0.4601051714264852,0.3610211606830505,0.2479152916167419,
0.1308225338647039,0.01993208413931726,0.6677553214177145,
0.6047094356064554,0.5171428148173597,0.40713632090741,
0.2835896681332588,0.1591265698738985,0.7315641787700664,
0.661547900814459,0.5636788840886751,0.4428493496799737,
0.3112182413099586,0.7806188517072566,0.7008301889050352,
0.5922663576988024,0.4633278474811566,0.8073788931114407,
0.7168049773549268,0.6000284935406993,0.8094700983598709,
0.7101312760741833,0.7906351929054215,-0.4366431953633788,
-0.5432543873236343,-0.6518847469150993,-0.7519687641278953,
-0.8321863440327827,-0.8854204339944604,-0.9116068551607237,
-0.4144921923404347,-0.5235089742164267,-0.6316176685916446,
-0.7265196152590857,-0.7972596530206874,-0.8395279581409318,
-0.8565153620209197,-0.3797670590739394,-0.4868622160190148,
-0.5894554430684077,-0.6751509712448159,-0.7353253350307362,
-0.7689936060115737,-0.3313530028134794,-0.4321132275126733,
-0.5253715109567975,-0.600556355906943,-0.6522238398741106,
-0.271365416599326,-0.3629934344088176,-0.4458145633979653,
-0.5120186635901344,-0.2051265147794646,-0.2871867138062492,
-0.3608173514139882,-0.1390341944715653,-0.2127048766307628,
0.9161619708326185,0.9364066014623644,0.937830159535626,
0.9131964504670906,0.8599820357483486,0.7829082325289186,
0.6920505768643884,0.9609824530756677,0.9781541365013002,
0.9704616345084118,0.9310013912281646,0.86057880605657,
0.7685149559210446,0.989767208703788,0.9980900358901049,
0.9758827628822744,0.91903449699185,0.833265855013368,
0.9934762859646802,0.9871926244298611,0.9476218597261858,
0.8754517847749737,0.9670219266787334,0.9434641845143519,
0.8885228243698201,0.9127512333378954,0.8739366103094172,
0.8395063271314147,0.1778171059718252,0.09682951222050769,
0.002564819628494808,-0.1001488152988667,-0.2029406081721617,
-0.2966906282753529,-0.3751816472846526,0.2557957005565683,
0.173079435577695,0.07531211221520523,-0.03133676316818776,
-0.1369434620566336,-0.2318708914823758,-0.3106176573163182,
0.3385137719481263,0.2540232415826708,0.1530285137711279,
0.04321731529158302,-0.06436010707835081,-0.160245257281258,
0.4191318730425461,0.3321294046295875,0.2281310249483762,
0.1162846541659367,0.007964747877728702,0.489433642057663,
0.3991899134973828,0.2930621280324591,0.1810582896385999,
0.5431817494666105,0.4500346846996958,0.3436781221558973,
0.5786154775493708,0.4842132402051962,0.5432536936373913,
0.6518842443443043,0.751968519322874,0.8321863638644724,
0.8854206569589087,0.9116071863986105,0.6355394193271248,
0.7490598502163163,0.8459479265844492,0.9147022337905197,
0.9515590961968758,0.7217468924595103,0.832492462220627,
0.9181881173363158,0.9702103552386692,0.7903983024315012,
0.8899272054685274,0.9588415071652456,0.8327634000595739,
0.9155844937451473,0.847341552439817,0.09926947140308087,
0.1210904447270627,0.141469873017204,0.1581590349215481,
0.16967722932441,0.1759046848916014,0.2127045253884476,
0.2445425491615283,0.273585758469152,0.2957341763491218,
0.308047355491858,0.310289867067379,0.304666812316337,
0.360816856533433,0.40111044364496,0.4328607304643095,
0.4506895618367096,0.4528028309124678,0.441794849646433,
0.5120181966189056,0.5550964104131831,0.5826403298719719,
0.5901407115935625,0.5787748141912227,0.6522235657335231,
0.6906215449122578,0.7078523050511999,0.7022909666912099,
0.7689935992922883,0.7968842810746374,0.8013846828119295,
0.8565155859292075,0.8718425534235449,0.2318702160237238,
0.1369430725775421,0.03133674940539507,-0.07531173762971051,
-0.1730787436687962,0.06435957029576898,-0.0432174738186679,
-0.1530282625973764,-0.2540226452878776,-0.1162849524413907,
-0.2281309051554154,-0.3321289161485715,-0.2930621449512896,
-0.3991895474466183,-0.4500344545042632,-0.04450787402063819,
-0.1591262308672862,-0.2835892617928241,-0.4071359133189035,
-0.5171424431454641,-0.6047090919043497,-0.667754971050827,
-0.182759348567292,-0.311217588457912,-0.4428487008416941,
-0.5636783165490287,-0.6615474307561048,-0.7315637666610734,
-0.3281947296279775,-0.4633269810702052,-0.5922656048068207,
-0.7008296027194382,-0.7806184022682794,-0.4680605237949423,
-0.6000275832292742,-0.7168042826134902,-0.8073784119772466,
-0.5899475572826254,-0.7101304786227719,-0.8094695688943716,
-0.6867599019180602,-0.7906345906969057,-0.7580246814516085,
-0.3102892714845059,-0.3080469554975349,-0.2957339957005241,
-0.2735857903437153,-0.2445427612771611,-0.4528024643637317,
-0.4506894194251309,-0.4328608289948512,-0.4011107629731985,
-0.5901404834522559,-0.5826403283348299,-0.5550966534493702,
-0.7078521147132451,-0.6906215734113883,-0.7968840729809553,
-0.7685147196433009,-0.8605786508071993,-0.9310012591522379,
-0.9704614726381049,-0.9781539258256538,-0.9609822090426239,
-0.833265614060389,-0.9190343924750819,-0.9758827239891746,
-0.9980899940222691,-0.9897671312659951,-0.8754515637483313,
-0.9476218214663272,-0.9871926808705815,-0.9934763548505058,
-0.8885226077999228,-0.9434641720148271,-0.9670220212347258,
-0.8739363526795478,-0.912751179432779,-0.8395059839899685,
-0.03770535005341785,0.07724999366628089,0.1973075542157886,
0.3108032352691305,0.4078776804650779,-0.1014611429922413,
0.0158470793272554,0.1366767120232094,0.2488687826864697,
-0.1661585633922329,-0.04823695834758815,0.07134403839749669,
-0.2253300338935004,-0.1085533974058879,-0.2740278002009307,
-0.951558921251018,-0.9147022049495029,-0.8459481068009407,
-0.7490602493222091,-0.6355399873284351,-0.5189591001755303,
-0.9702103859734443,-0.9181883003327364,-0.8324928057608664,
-0.7217473579669872,-0.6005407102760519,-0.9588416857098183,
-0.8899274903619968,-0.7903986578533415,-0.6726056915299506,
-0.9155846529394258,-0.8327635907539088,-0.7263689563436138,
-0.8473415025692198,-0.7570604878450786,-0.7658353788323373,
0.6729208082532415,0.7603670653263657,0.8290950909162599,
0.8702498673585751,0.8825599429670654,0.6328423544382739,
0.7116548337644016,0.7685030738837739,0.7976664655237659,
0.569732829878993,0.6365523011473486,0.6814736060981027,
0.4876756652068531,0.542616991447444,0.3959655290681676,
-0.4552976478369847,-0.3711626697331859,-0.2695165436861755,
-0.158907070465767,-0.05034727738276638,0.04745431047424936,
-0.5327985288361234,-0.4414793439189789,-0.3316681166200877,
-0.2144151021287253,-0.1017815730335519,-0.5982547186038516,
-0.498913942879685,-0.3824098828497664,-0.261438418974126,
-0.6438146830008175,-0.5376868414254443,-0.4179934509733508,
-0.6670990265838406,-0.5575567398179423,-0.6714330779441176,
0.8395281342551513,0.797259699808284,0.7265194573448021,
0.631617280616129,0.5235083955500395,0.7353252547527041,
0.6751507612001276,0.5894550707609513,0.4868616963131356,
0.6005560087932349,0.5253710768222695,0.4321127152346745,
0.4458140656510558,0.3629929231163813,0.287186249855225,
0.03445349641709906,0.01888696113562014,0.001684189644027077,
-0.01557458737398696,-0.03129373726645494,-0.1255180400739348,
-0.1477032144715439,-0.1655319877909157,-0.1772102701265833,
-0.2920095247225022,-0.3149489017570188,-0.3270536482990907,
-0.4487896352785713,-0.466020275040162,-0.5822980026295906,
-0.1282040992012934,-0.01849805050225584,0.1065963991903489,
0.2398318813191588,0.3698188179209382,0.48502451338496,
0.5783911156884447,0.6488215902264565,-0.1719025532007262,
-0.05632783998118585,0.07515681888535472,0.2129025876416392,
0.343567868763417,0.4557584300457211,0.5443645168181878,
-0.2175987830988393,-0.0973017552494557,0.03818460718077296,
0.1770480397960358,0.3053148472212455,0.4131148482333044,
-0.2612807879100861,-0.1378469909045712,-0.001396095557054295,
0.1351028209250271,0.2586670590048458,-0.2983313855304687,
-0.1738078395074255,-0.03960230940919204,0.09162948390440753,
-0.3254633663003954,-0.2022894544581522,-0.07317794255704746,
-0.3420357716053446,-0.2226579469368842,-0.3496821715684524,
0.6714420577705413,0.7639967300466739,0.8515659143445876,
0.9231420898872643,0.968766507749211,0.9843912721595947,
0.9735002156201846,0.9441720387917811,0.7186206475410257,
0.8155881299141562,0.9020895786249314,0.9652453470205394,
0.9962999166711242,0.9953266714812502,0.9700250905310301,
0.7556710613817772,0.8510774619026286,0.9293561756854016,
0.9780963063206267,0.9923931460327553,0.9770471587096806,
0.7749162464509299,0.8614959728515891,0.9253137561812753,
0.9572996257002351,0.9574145614312103,0.7711321510425843,
0.8432637257218606,0.8903690639450959,0.9080060338759378,
0.7446544865975486,0.8006806881904648,0.8332051934736653,
0.701244308549226,0.7431452383031477,-0.9441722324566724,
-0.8900404033987204,-0.8080124134651047,-0.6961352518091236,
-0.5596336341615111,-0.4106183042575765,-0.2632365894868439,
-0.9240670480583062,-0.8565379051211715,-0.7569806316871794,
-0.6264662143927534,-0.4751173969978469,-0.3187870772043735,
-0.8799221319939898,-0.7952336612815645,-0.6770111077910543,
-0.5311881497579278,-0.3724388713810448,-0.8072870326747171,
-0.7042659659540528,-0.5707688373923591,-0.4176365891727677,
-0.7078360053862648,-0.5898764843905154,-0.4489449331750177,
-0.5903925893983768,-0.4647486526822006,-0.4673964384898752,
-0.3130828685601689,-0.185445228664084,-0.03612578735626812,
0.1274723552911619,0.2921714771415931,0.4433590934587491,
0.5708391580621228,-0.3082982931616353,-0.1684123240900115,
-0.006503141132676928,0.1663065314632002,0.3335853689877698,
0.4804232043289857,0.5992429554740794,-0.2957556065313156,
-0.1446156178201561,0.0263111709560856,0.2022572179054991,
0.3655171685702938,0.5033858756710694,-0.2738409047359961,
-0.1145893425106214,0.05935120233887466,0.2312500236673017,
0.3849556597532595,-0.2429129440661442,-0.08075215189426678,
0.08929215655126845,0.2511845570441078,-0.2057157098095482,
-0.04657083216475545,0.1139410251668723,-0.1662796617532138,
-0.01502268661531953,-0.671442351589465,-0.7639968739619373,
-0.8515659293219712,-0.9231420361206036,-0.9687664657212128,
-0.984391303457987,-0.973500337776358,-0.6726628661443731,
-0.7663025019644482,-0.850423091629073,-0.9127051151953394,
-0.9446333569667822,-0.9460408841414493,-0.6585464808986428,
-0.7477446091210315,-0.8224367335791617,-0.8711767663146228,
-0.8890600090241656,-0.624789307379154,-0.7038755707064229,
-0.7649345287347953,-0.7996789024113027,-0.570962738954507,
-0.6365977473321981,-0.6837028657947305,-0.5018423792963483,
-0.5542516901414858,-0.4254957770577467,-0.648822290296783,
-0.6461886815965452,-0.6283026738755576,-0.5912852336175236,
-0.5351200741127089,-0.4647903048152701,-0.3882830681102161,
-0.7431455981686927,-0.7416382763983708,-0.7194745213161431,
-0.6726721034791168,-0.603498627991077,-0.5203744826993632,
-0.4336588493758105,-0.8332052486459366,-0.828474359608384,
-0.7972278976396602,-0.7372273383122565,-0.6545105158801499,
-0.5606846159713372,-0.9080059008549388,-0.8943581597155409,
-0.8500103413150977,-0.7764211405289977,-0.6833452492402967,
-0.957414401308411,-0.9304983201224565,-0.8725103749365023,
-0.7889189186796404,-0.9770470988810096,-0.9362839635412132,
-0.8680388569279747,-0.9700251729575815,-0.918444056010861,
0.3130823317650696,0.1854445580462805,0.03612501838448451,
-0.1274731492430557,-0.2921722054174978,-0.4433596869123763,
-0.5708395935644333,0.2348779693026915,0.08967582567032931,
-0.07603665789539318,-0.2502419786720302,-0.4161249577436337,
-0.5591593471944528,0.1405944428773656,-0.02046318130327168,
-0.1971193271182073,-0.3730652190141688,-0.5305955532581022,
0.03400663448859465,-0.1372155522896737,-0.3155629354201782,
-0.4830545524260225,-0.07686580556220674,-0.2494045186454276,
-0.4194486169997139,-0.1821860518397986,-0.3471084060868513,
-0.2742390008535104,0.1282040764044601,0.01849789837253189,
-0.1065967544617238,-0.2398324745610959,-0.3698196073694229,
-0.4850253879196206,-0.5783919486276667,0.0150226853040112,
-0.1119113111904829,-0.2515228306741237,-0.3922511186515919,
-0.5199342604026214,-0.6239982016489247,-0.7012450602090677,
-0.1139410284132941,-0.2554296773980814,-0.4031586053186698,
-0.542022233559877,-0.6580467871742169,-0.7446552996299098,
-0.251184596582457,-0.4001969364777949,-0.5460646790820674,
-0.673147094708149,-0.7711330012738366,-0.384955766757247,
-0.5316548106571598,-0.6658605062472989,-0.7749170668851217,
-0.5033860614642302,-0.6389055531086461,-0.7556717637535928,
-0.5992432078251344,-0.718621161033365,0.6461880602442403,
0.6283021483764009,0.5912847908960939,0.5351196688462319,
0.4647898820036706,0.3882825918191143,0.5284642450992455,
0.4960034056042855,0.4454222319691665,0.3800276076057463,
0.3072006168941325,0.3815325789989955,0.3347740585202575,
0.2747735598444634,0.2075688995229241,0.2126093137747108,
0.156329837645353,0.09467242600265936,0.03661534005366113,
-0.02137253427038529,-0.1295837823093738,0.890040216351073,
0.808012285288426,0.696135219402544,0.5596336911375484,
0.4106183982029223,0.263236651429863,0.9184439709263976,
0.8505076927737054,0.7506591839147216,0.6200379306780087,
0.468796032975448,0.3127569623094897,0.1662794974092329,
0.868038934491271,0.7825908968870643,0.6639295465452925,
0.5181065730349851,0.3597960374562562,0.2057154129295492,
0.7889191397304282,0.6849812234203291,0.5511465043193342,
0.3983516721236944,0.2429125431986682,0.6833454958120994,
0.5645910307529023,0.4236593282043838,0.2738404383453708,
0.5606847158751149,0.4345981000668111,0.2957551060736421,
0.4336586612857497,0.3082977736038213,0.6239973336558853,
0.5199334023086634,0.3922504194657625,0.2515223878822021,
0.1119111251755824,0.6580459058109899,0.5420214442749262,
0.4031580569915867,0.2554294261048449,0.6731462609902346,
0.5460640349170377,0.4001965955151434,0.6658598068272309,
0.5316543804516458,0.6389050615461086,0.9240668881257947,
0.9460408367508209,0.9446334423554673,0.9127052977657962,
0.8504232826059466,0.7663026047198382,0.672662821600414,
0.8799221274953846,0.8890601671224364,0.8711770865982926,
0.8224371418546537,0.7477449864099799,0.6585467268780121,
0.8072873085337188,0.7996793702817474,0.7649351423426319,
0.7038762137269466,0.6247898512026207,0.7078366234465509,
0.6837036520525703,0.6365986074780202,0.5709635410688519,
0.5903935068116462,0.5542526992524547,0.5018433659765416,
0.4673975349060661,0.4254968708628413,0.3496833143594963,
-0.3127570262656423,-0.4687960400735756,-0.6200379371399192,
-0.7506592271179455,-0.8505077714673068,-0.3597961933958567,
-0.5181066147650901,-0.6639295189615018,-0.7825908374998334,
-0.3983518694010773,-0.5511465125252933,-0.684981089854631,
-0.4236595256885799,-0.5645909758908611,-0.4345982861939252,
0.5591591752824973,0.4161246264414231,0.250241497477734,
0.07603608646389884,-0.08967640497055197,-0.2348784900769719,
0.5305956825248687,0.3730651765875013,0.1971191044524291,
0.02046282792852898,-0.1405948497186229,0.4830549755697658,
0.3155631609030148,0.1372155601346925,-0.03400679840825552,
0.4194492775199674,0.2494049520909613,0.07686599366344003,
0.3471092245505432,0.1821866253122765,0.2742399078697009,
-0.9953267028881266,-0.996299919654964,-0.9652453855328264,
-0.9020897348256817,-0.8155884604797163,-0.9923930940648169,
-0.9780963403965233,-0.9293563919654181,-0.851077922468494,
-0.9572995816653358,-0.9253139445404677,-0.8614964761454963,
-0.8903691794182322,-0.843264195535517,-0.8006810953746416,
-0.3072011182546949,-0.3800281004182731,-0.4454227426500373,
-0.49600396162629,-0.5284648561961354,-0.5443651710562558,
-0.2075693133952311,-0.2747739903004954,-0.3347745172062594,
-0.3815330693216025,-0.4131153608788349,-0.09467260192740248,
-0.156330035009575,-0.2126095377726251,-0.2586673060001281,
0.02137271473539107,-0.03661518331511127,-0.09162936047901911,
0.1295843445482322,0.07317846937762097,0.2226588286505751,
-0.4804235981897006,-0.3335859124413625,-0.1663071857914592,
0.006502456545087328,0.1684116947040793,-0.3655174937182495,
-0.2022576822989345,-0.02631172536408047,0.1446150543700356,
-0.2312502717555327,-0.05935158437557636,0.1145888807063153,
-0.08929234550841479,0.08075182856000082,0.04657066968406794,
-0.4557591367849598,-0.3435685084916551,-0.2129030384298065,
-0.07515702237270272,0.05632785157141965,0.171902693522397,
-0.3053152988366306,-0.1770483103705765,-0.03818462683571519,
0.09730196068160382,0.2175991175749613,-0.1351028913474505,
0.001396275074369462,0.1378474039188301,0.2612813355040192,
0.03960267796661452,0.1738084474791471,0.2983321411535529,
0.2022902215891641,0.3254642982361922,0.3420368325512359,
0.5203743808147369,0.603498584268205,0.6726720548002406,
0.719474396239089,0.741638033276861,0.6545106949482685,
0.7372275485364457,0.7972280664875324,0.8284744266242357,
0.7764214244136933,0.8500106167743341,0.8943583778920716,
0.8725105875877179,0.9304985104221231,0.9362840195367765,
0.3187873126271887,0.4751176460530464,0.6264663831892676,
0.7569806648964799,0.8565378137633573,0.3724393069541885,
0.5311885746144091,0.6770114116120104,0.7952337966915513,
0.4176372345893317,0.5707694457794332,0.7042664250854263,
0.4489457715859918,0.5898772631309003,0.4647496441635906 };
auto pointshell
= new vnl_matrix_fixed<double, 3, 492>(coords);
return pointshell;
}
};
template<> class PointShell<642, vnl_matrix_fixed<double, 3, 642> >
{
public:
static vnl_matrix_fixed<double, 3, 642>* DistributePointShell()
{
double coords[3*642] = {
0.9756767549555488,0.9936273045965159,0.9968737649581846,
0.9799612120178374,0.9397937974509784,0.8775847359538656,
0.7989268505692991,0.7116707502187636,0.6231965669156312,
0.9839439883131955,0.997606269193783,0.9928389431247303,
0.9642927845075879,0.9105363959854476,0.8355633282696746,
0.7474316403407526,0.6549945735140008,0.9764792677814802,
0.98203616585628,0.9657129396229355,0.9235205478703636,
0.8567905682573015,0.7723352820545265,0.679558714000995,
0.9483175267842808,0.9421385440112533,0.9121470670895898,
0.8569526200134567,0.7808692882316954,0.6923761132322002,
0.8971014254962764,0.8773049187483365,0.8343457228904876,
0.7697920647699087,0.6899186612252972,0.8248449061833976,
0.7923517869921962,0.7399265426789414,0.6712800260218211,
0.7377425905504456,0.6958798370509692,0.6387690340353133,
0.6438863846345996,0.5968935863094567,0.5505632701289798,
0.4375940376503738,0.3657089664269339,0.2787444080680243,
0.1782978006253255,0.06907711216819172,-0.04176369281672855,
-0.1467487371786262,-0.2403654598146251,-0.3200730131503601,
0.4914658799359538,0.415730180051685,0.322900981562039,
0.2155490838668689,0.09999803429967301,-0.01516787889370763,
-0.1220279512352428,-0.2156209889399338,0.5436064763029955,
0.4631956410318647,0.3641181930198064,0.2503784412304452,
0.1299861910861632,0.01243715490308354,-0.09463328683104604,
0.5892511755529848,0.5032632034506475,0.398083833846048,
0.2794416963056139,0.1566100659016669,0.03909742267488438,
0.6235168560971455,0.5315692770219257,0.421472539809791,
0.300467209121473,0.1781713819192711,0.6431587521468424,
0.5460109940101698,0.4333214055893837,0.3130665794035795,
0.6478378002177454,0.547462575328819,0.4350913076613168,
0.6399334332955604,0.5389210845670883,0.3200724178002418,
0.4287826750526064,0.543583002477908,0.6574820925009807,
0.7616224484252742,0.84789985457486,0.9117594243665534,
0.9532148993238304,0.3721063927495636,0.4892591428502506,
0.6101418466998186,0.7256202393614284,0.8256057937005235,
0.9026705854615993,0.9545776898360481,0.4242146396073646,
0.5469136809977159,0.6694499319211135,0.7811234805255704,
0.8720427891122669,0.9369519951934821,0.4722731360977363,
0.595952912761318,0.7145554586697968,0.8172157093145741,
0.8959095653312069,0.5117469206751248,0.6311048134383331,
0.7406754453578036,0.8310759079383635,0.5392182936767531,
0.6497579584113991,0.7472675269245613,0.5536544075493044,
0.6528511281517397,0.5564810307882812,0.2502538949373057,
0.2918876561725356,0.3336803609057232,0.3723595102048779,
0.4043068999720243,0.4267717639621923,0.438887490788423,
0.4417451579814044,0.3636248847448722,0.4137579266740147,
0.4613876866690337,0.5016743933949674,0.5302454776050456,
0.5449783839335098,0.5467236437808158,0.5384586718996058,
0.4847692553550146,0.5414178984405463,0.5913899314506929,
0.6286876371986284,0.6492812914734455,0.6528721916210272,
0.6425800233106177,0.6067853073481849,0.6657991451456106,
0.7129452846304364,0.742280692335758,0.7515124484581964,
0.7428160470273413,0.7205836671095894,0.7764326916323942,
0.8155579470101821,0.8335749126408774,0.8306996157029517,
0.8174816717930142,0.8650995515806045,0.8929631510323212,
0.8991001659430972,0.8921547074343706,0.9286306144549926,
0.9447583574027534,0.943906557149077,0.9688828514077716,
-0.4375932291383154,-0.3657083101776577,-0.278743955138478,
-0.1782975892372044,-0.06907715072573903,0.04176343253822806,
0.1467483093137361,0.2403649238452659,-0.334979155028856,
-0.249113234922861,-0.1483246071802934,-0.03654010765740752,
0.07901069585299947,0.1897435516910367,0.2886438308249422,
-0.2140239599986307,-0.114043112737167,-0.001406336898152031,
0.1172166109444462,0.2327251986251803,0.3367145075141528,
-0.07787968046152194,0.03376382657255556,0.153308912419789,
0.2719508349268641,0.3804163499145621,0.06640211724156461,
0.1844665658852621,0.3039508137298482,0.4155682770935452,
0.2091265361205084,0.3268694132891478,0.4395588586722926,
0.3409081262151013,0.4522359229770948,0.4554687573578106,
-0.6231952788307174,-0.5482281060337162,-0.4546947222788382,
-0.3434835709283097,-0.2192092047974508,-0.08979359660521438,
0.03581973661208818,0.1504629769958484,-0.538919991494099,
-0.4498208454617149,-0.3413996198032652,-0.2168595871258214,
-0.08365072681681855,0.04833087340999961,0.1701142201456619,
0.2762195992594308,-0.4350905112236564,-0.3310154747857772,
-0.2089153242611869,-0.07495576041016457,0.0609953219830862,
0.1886252092359959,0.3006812043050254,-0.3130661573786132,
-0.1955639168315415,-0.06402306061993944,0.07274927837670857,
0.2040627320686719,0.3211588705998562,-0.1781713502362079,
-0.05170714345574682,0.08257031568712175,0.2147106704082434,
0.3352293490184233,-0.03909771946676634,0.08986774257262679,
0.2197779802638865,0.3414374432933526,0.09463277722176672,
0.2196681717134536,0.3398901915912972,0.2156203893390849,
0.3320690152456851,-0.2502532651867688,-0.2918869903084482,
-0.3336796480610522,-0.3723587421891308,-0.4043060780204903,
-0.4267709034446925,-0.4388866188864613,-0.4417443051644412,
-0.1601455684487161,-0.1971059987993399,-0.2343857490409392,
-0.2689083414095461,-0.2974793723400317,-0.3179763028669095,
-0.3300715220338927,-0.05621340666038893,-0.08741483463411388,
-0.1197552832780665,-0.1507029759524935,-0.1776465335448071,
-0.1988689416472687,0.05815084571042724,0.03249724572817093,
0.004031222699520391,-0.02530412585141796,-0.053215898827698,
0.1765178736510398,0.1546289422059015,0.1277105869872963,
0.09748683381429475,0.2907448784422404,0.269907109295262,
0.2420435658170933,0.3935116760630417,0.371277608971055,
0.4804450046073554,-0.975676581463901,-0.9936272216648101,
-0.9968737272214637,-0.9799611311880234,-0.9397935597648752,
-0.8775842433730664,-0.7989260596435309,-0.7116696803542213,
-0.9688826210954523,-0.9815699711830299,-0.9760365766523995,
-0.9470636842643547,-0.893307090661199,-0.8187603857237982,
-0.7313944919484914,-0.6399321926850757,-0.9447580743829742,
-0.9484314744303296,-0.9308031701048347,-0.8881406289392687,
-0.8218804228775519,-0.7387299092709896,-0.6478366382006043,
-0.8990998280625567,-0.8904516044143657,-0.8590773924437412,
-0.8038827695098977,-0.7291818553952708,-0.6431576879244336,
-0.8306992108488227,-0.808389020899373,-0.7645261844287355,
-0.700875860490056,-0.6235158879179115,-0.7428155559569007,
-0.7083401623912103,-0.6559147788974127,-0.5892502820769048,
-0.6425794288509028,-0.599662429956479,-0.543605629081954,
-0.5384579674699886,-0.4914650570197842,0.5482295401850756,
0.4546962564744617,0.3434851238806179,0.21921067448898,
0.08979489147188233,-0.03581866880653414,-0.1504621418996611,
0.5734097649981191,0.4708926749454921,0.3496406892388488,
0.2164317110563474,0.08116185373706966,-0.04652577585176784,
0.5899999525047667,0.4779576265881325,0.3476203004228133,
0.2080468003445843,0.07035894736836774,0.5939040461937424,
0.4730191144791596,0.3362467154220247,0.1942772308316476,
0.5828267863796578,0.4555126388719097,0.3164089231485616,
0.5575911119751512,0.4276808797198417,0.5218578151430378,
-0.4287830717591774,-0.543583197615373,-0.6574821123382336,
-0.7616223457476226,-0.8478996902559745,-0.9117592443356049,
-0.953214723425574,-0.332069490448325,-0.446630150856391,
-0.5654761604524486,-0.6798202351943792,-0.7798056854765759,
-0.8580045844734643,-0.9119481688022204,-0.943906345398722,
-0.3398905505309818,-0.4575823132651822,-0.5766491384642831,
-0.6870731075595852,-0.7792417673233771,-0.8476201697382868,
-0.8921544952781482,-0.3414376861695784,-0.4585532096219049,
-0.5734800429475671,-0.6761401742385725,-0.7585095042345053,
-0.8174814835779161,-0.3352294641675141,-0.4479051019866874,
-0.5550737397870624,-0.6478759583634458,-0.7205834943870382,
-0.3211588327497382,-0.4264290282814993,-0.5239384830804104,
-0.6067851042454853,-0.3006809838192767,-0.3970753303611698,
-0.4847689570296102,-0.2762191758252563,-0.3636244354414296,
0.7313954822136002,0.8187610780655567,0.8933074970084837,
0.9470638862390964,0.9760366948920106,0.9815701139230523,
0.7387307994522452,0.8218810203164033,0.8881409840733967,
0.9308033931946534,0.9484316859524741,0.7291826478779969,
0.8038833043893007,0.8590777515266519,0.8904519038272285,
0.7008765828222415,0.7645267056644409,0.808389434193021,
0.6559154701692661,0.7083407113717404,0.5996631212693852,
-0.3721068299668963,-0.2886442143937944,-0.1897438268706112,
-0.07901079510230862,0.0365402424927288,0.1483250002713656,
0.249113868623751,0.3349799829238154,-0.4242149221746557,
-0.3367147430533525,-0.2327253235991419,-0.1172165489233448,
0.00140664545831139,0.1140436844250324,0.2140247669633664,
-0.4722732967958943,-0.3804164687039511,-0.2719508356433764,
-0.1533087105593531,-0.03376336567881106,0.07788040640138937,
-0.5117470172320778,-0.415568329019231,-0.3039507303469009,
-0.1844662592618953,-0.06640153973221416,-0.5392183881102406,
-0.4395588911842847,-0.3268692828205596,-0.2091261596739739,
-0.5536545418185335,-0.4522359631907089,-0.3409079709201472,
-0.5564812164049491,-0.4554688095204276,-0.5505634949474448,
0.911948358176072,0.8580047480914766,0.779805799941989,
0.6798202570778734,0.5654760412600151,0.4466298574551351,
0.847620327622159,0.7792418677670352,0.6870731334410928,
0.5766490604842006,0.457582102461728,0.7585096116294638,
0.6761402059852791,0.5734799960054555,0.458553071765391,
0.6478760427254714,0.5550737528785307,0.4479050525999325,
0.523938612103898,0.42642910652745,0.3970755800133287,
0.330072407434952,0.3179772211416992,0.2974802928098944,
0.268909235983653,0.2343866000755754,0.1971068007343541,
0.1601463238235379,0.1988698061348988,0.1776474313398276,
0.1507038783156887,0.1197561650892531,0.08741568024186514,
0.05621421006516834,0.05321666456243916,0.02530491044308729,
-0.004030439768117324,-0.03249647940113914,-0.05815010397008495,
-0.09748624755051107,-0.1277100030888262,-0.1546283656290311,
-0.176517304179968,-0.2420432126719758,-0.2699067748969105,
-0.2907445498638314,-0.3712774990883263,-0.3935115910448358,
-0.4804451115014433,0.1220274770108985,0.01516759063021488,
-0.09999808166532918,-0.2155488634876903,-0.3229005078918639,
-0.4157295012949034,-0.01243745747761582,-0.1299862309792015,
-0.2503781938406115,-0.3641176806190365,-0.4631949245146199,
-0.1566100780036334,-0.2794414004304853,-0.3980832592651996,
-0.5032624248731086,-0.3004668503638805,-0.4214718858755578,
-0.531568413027702,-0.4333206720101446,-0.5460100361038957,
-0.5474615360697464,0.04652671746835695,-0.08116072547370122,
-0.2164304342992144,-0.349639340464782,-0.4708913462876021,
-0.5734085330236464,-0.6549934813681663,-0.07035800928464173,
-0.2080457563809749,-0.3476192098203675,-0.477956563666828,
-0.5899989806009898,-0.6795578679273953,-0.1942764317499744,
-0.3362459041917389,-0.4730183457316648,-0.5939033648561503,
-0.6923755409289452,-0.3164083741856072,-0.4555121490743896,
-0.5828263835645211,-0.6899183532182501,-0.4276806208272582,
-0.5575909387515523,-0.6712799366842756,-0.5218578089727968,
-0.6387691005409376,-0.5968937515401853,-0.5467229076134115,
-0.5449776495480215,-0.5302447815086285,-0.5016737622437388,
-0.4613871281827766,-0.4137574314122305,-0.6528715777859069,
-0.6492806993353901,-0.6286871066630142,-0.5913894852863821,
-0.5414175353843733,-0.751511947518686,-0.7422802285333175,
-0.7129448986517994,-0.6657988547064399,-0.8335745044290338,
-0.8155575864896008,-0.7764324183665692,-0.8929628157948554,
-0.865099271542177,-0.9286303415753032,-0.7474308144934858,
-0.8355628131811949,-0.910536173478481,-0.964292764650283,
-0.9928389973443023,-0.9976062839252843,-0.9839438984088483,
-0.7723347377989339,-0.8567903368462096,-0.9235205630598494,
-0.9657130735429578,-0.9820362841720375,-0.9764792804081987,
-0.7808690244142814,-0.8569526309007678,-0.9121472452874007,
-0.9421387497441781,-0.94831764697765,-0.7697920349927029,
-0.834345897568434,-0.877305173541843,-0.8971016370404784,
-0.7399266733270721,-0.7923520436827605,-0.8248451738745377,
-0.6958800576642888,-0.7377428728490714,-0.6438866478040335,
-0.1701136087322269,-0.04833004892467691,0.08365175264713676,
0.2168607561552602,0.3414008427548977,0.4498220342255287,
-0.1886248334720497,-0.06099477310985241,0.07495646481991973,
0.2089161290281741,0.3310163070583758,-0.2040625875734068,
-0.07274901933354507,0.06402341598693255,0.1955643282951042,
-0.2147107402706368,-0.08257033948198818,0.05170715566660035,
-0.2197782438454324,-0.0898680254606548,-0.2196686109085476,
-0.9545775709750491,-0.9026704336737921,-0.8256056375543351,
-0.7256201416180276,-0.6101418826154756,-0.4892593689607926,
-0.9369519509430696,-0.8720426859708773,-0.7811233602703923,
-0.6694498734011487,-0.5469137667342426,-0.895909603120296,
-0.8172156710096443,-0.7145554011223244,-0.595952924378129,
-0.8310760190279151,-0.740675476302381,-0.631104833094877,
-0.747267688498931,-0.6497580495472918,-0.6528513129029779,
-0.1778161375899129,-0.107732211558371,-0.02718233037986957,
0.06111658446407255,0.1521341729788544,0.2395836558807668,
0.3178872248051531,0.3837865324362482,0.4366423972091847,
-0.06488531255731433,0.01813723762238458,0.1103935391881494,
0.2069070831033206,0.3006175096647589,0.3845630878227619,
0.4542522939636228,0.5085532875085977,0.06305939500089614,
0.1581936380649512,0.2592762165236786,0.3589842883205384,
0.4491542846588709,0.5237530566427051,0.5806638189836385,
0.2011334080862844,0.3049347792866978,0.4093092940034627,
0.5055265527628903,0.5860660664928973,0.6473011578337731,
0.3410385404813853,0.4476590365909358,0.5484671467389891,
0.6350798717696985,0.7022080829625521,0.4729450152996533,
0.5757634189631973,0.6671532416651529,0.7406455836915592,
0.5886123721388867,0.682355586840312,0.761147081998915,
0.6837147822732754,0.765634519258382,0.7580253719184177,
-0.5980610514568759,-0.5477295977070786,-0.4818747107897384,
-0.4002556178808948,-0.3056524524744078,-0.2038805884680659,
-0.102179801407443,-0.006890393767211274,0.07805400320688782,
-0.4999225208961594,-0.4363106684051463,-0.3565940723019476,
-0.2625351309487317,-0.1594214993217877,-0.0549134894376971,
0.04356549235716502,0.1310565626039044,-0.3811861908796716,
-0.3032604317093944,-0.2105722545208477,-0.107535321253739,
-0.001641189844283069,0.09898039401487412,0.1883562467232593,
-0.2440298576445608,-0.1531593370054226,-0.05138446179122957,
0.05448758952315854,0.1561816678501543,0.2469078854412431,
-0.09487972868743588,0.004642223416678918,0.1091686599118738,
0.2108696280700075,0.3025309778153461,0.05649572496138416,
0.1584211910021343,0.2589814921571267,0.3510585742974243,
0.1998858588754617,0.298075413103841,0.3897335832229792,
0.3277592945902335,0.4178993211010856,-0.07805410188638827,
-0.09654989477487182,-0.1156801299839266,-0.1341453490447077,
-0.1503967869358663,-0.1631208476237052,-0.1717048170733874,
-0.1763517237002561,0.02821687967586119,0.015882211907606,
0.001803084777968777,-0.01336575229369984,-0.02858037077889998,
-0.04271047578209198,-0.0549244526833743,0.1470965334761953,
0.140993103021656,0.1310545667952879,0.117197412734933,
0.100226360425432,0.0816416498682333,0.273572290929994,
0.2720829158426912,0.2637397329328206,0.2481180890825449,
0.2264390031249597,0.3996773221825281,0.3995925724178936,
0.3894173756029716,0.3691632841122737,0.5164083739773968,
0.514049378265622,0.4992114966670869,0.6166247865338805,
0.609293992020038,0.6970151178651957,-0.9161616153729887,
-0.9347343784055889,-0.93968222548459,-0.9257960724039628,
-0.8900379255247358,-0.8334050053153379,-0.7610423024299814,
-0.6802788134766146,-0.8787071877689653,-0.8904371961034525,
-0.8856636768163644,-0.8596394026846126,-0.8111262103564944,
-0.743728138896018,-0.6646636793709766,-0.581842306375343,
-0.8216809647863927,-0.8231596650234216,-0.8059784419089511,
-0.7670189419545808,-0.7076799521032789,-0.6339122309388853,
-0.5537209611836944,-0.7427083018941957,-0.7314571731747196,
-0.7012133398208896,-0.6514023484259069,-0.5859175101354265,
-0.511730458968065,-0.6430242175142256,-0.6188528748169413,
-0.577817181345379,-0.5218263992188138,-0.4560492515462431,
-0.5282587532766855,-0.4937121240962341,-0.4464002188664107,
-0.3896719563417937,-0.4070385900414059,-0.3663927387120716,
-0.3177184789930138,-0.2880885834764299,-0.2456792441590282,
0.5980613131647216,0.5477298128889157,0.4818748986235024,
0.4002557953563768,0.3056526230838691,0.2038807357406828,
0.1021798945147061,0.006890401333784563,0.6591961567279382,
0.6058950950047038,0.5342799125746878,0.4447327915277979,
0.3416191699708766,0.2325993338657758,0.1260188711040966,
0.7166389355513205,0.658631931443462,0.5797448495418049,
0.481678385980196,0.3708138719979267,0.256391213430893,
0.7645097528661115,0.6997519467043368,0.6125989595293794,
0.5067270065580872,0.3904111886835731,0.797087559189558,
0.724147921463701,0.6291765311790336,0.5179208049695498,
0.8109706900869452,0.7300074788244177,0.6294473765659205,
0.8064720598658887,0.7194304887783171,0.7871548899782018,
-0.4366431953633789,-0.5296368489080719,-0.6250679008877252,
-0.7161969218969775,-0.7951587738972527,-0.8554711457309036,
-0.894357332660672,-0.9132140384692056,-0.4179000270237177,
-0.5130217272422377,-0.6088499338150114,-0.697440817161931,
-0.770571681316741,-0.8228096498409901,-0.8533624251889405,
-0.8654069300758386,-0.3897342152274581,-0.4841961940355134,
-0.5770900179397438,-0.659947012990183,-0.7252694054566711,
-0.769475954957455,-0.7936687210308288,-0.3510591528670133,
-0.441802940329269,-0.528708833131731,-0.6037960859260583,
-0.6611957546281005,-0.6992451996033126,-0.3025315118038733,
-0.3871149210682015,-0.4662800296194353,-0.5333768673612823,
-0.5843857415998933,-0.2469083611836815,-0.3241948947822677,
-0.3955149325344624,-0.4558201674611825,-0.1883566309643827,
-0.2585114083922621,-0.3230016809603438,-0.131056817682024,
-0.1949865131648375,0.9161619708326186,0.934734728353398,
0.9396825386256142,0.9257963253168833,0.8900381161951118,
0.8334051579656884,0.7610424573388179,0.6802790093210535,
0.95606107640987,0.9727986783919703,0.9719596947667498,
0.9481265951474337,0.8996133652092656,0.830024065837643,
0.7470250693356176,0.98459889389352,0.9957514224668438,
0.985272860446651,0.9487272931457502,0.8869743499570832,
0.8065039787728745,0.9954874564049441,0.9969183323524673,
0.9737757915263076,0.9239648191561672,0.851378736753008,
0.9840623116657442,0.9728010399724041,0.9364058649128151,
0.8757746689964236,0.9495572492185336,0.9251912324727678,
0.8778794078487933,0.8957919700911449,0.8605602916932662,
0.8295641154807277,0.1778171059718252,0.1077330169440829,
0.02718289859111821,-0.06111631614771156,-0.1521342296531137,
-0.2395840100830868,-0.3178878068603045,-0.3837872586817543,
0.2456801528075706,0.1743614211692323,0.0913009251307558,
-9.150547636147518e-005,-0.09380226130703311,-0.1828695547719357,
-0.2617550281067236,-0.3277601386896922,0.31771932061924,
0.2451950112624202,0.1597779786826127,0.06571158217888019,
-0.03010074909289372,-0.1203656141836725,-0.1998866892639353,
0.3896727248396884,0.31551207359359,0.2277347108654265,
0.1315171099293629,0.03437982180295363,-0.05649645964725484,
0.4560499397602033,0.379603102905924,0.2896405921772683,
0.1921815993207149,0.09487917246041,0.5117310565618495,
0.432706773459909,0.3413166137711556,0.2440295330914618,
0.5537214556082512,0.4726319336973814,0.3811861035860583,
0.5818426869442771,0.4999226354150897,0.5296361374668247,
0.6250673427588886,0.7161965757306298,0.7951586652134927,
0.8554712518134584,0.8943575917970892,0.9132143767653008,
0.6095437192932451,0.7099831823616649,0.80114225201565,
0.874273305605062,0.9239434255089938,0.9498851810027883,
0.6864630907143527,0.7872122199392447,0.8728983750907815,
0.9353918603084618,0.9717433027190985,0.7529076094482211,
0.8481358928542101,0.9232232087908666,0.9723005987504904,
0.8019213565969565,0.8865248509843126,0.9481833022791925,
0.8298631139894471,0.9011831013407439,0.8376467778090524,
0.09654990728233075,0.1156802730367007,0.1341456406128616,
0.1503972383762518,0.163121458312337,0.1717055726654157,
0.1763525997352119,0.1949861891736041,0.2217704348994384,
0.2472029328538624,0.2686947191514402,0.2839095008331465,
0.2917169688378368,0.2925778501087149,0.2880893594612404,
0.3230012075937738,0.3570186650821726,0.3862979863651042,
0.4071207791101573,0.4171265008378126,0.4163707105097114,
0.4070391829394841,0.4558196682853914,0.4939031399298617,
0.5227372695226704,0.5383590521019039,0.5395474601226077,
0.5282592036287527,0.584385354546882,0.6217221861558012,
0.6452876111171104,0.652151703940053,0.6430245879023526,
0.6992450234541641,0.7309800986736478,0.7458180696675939,
0.7427086516187589,0.7936687790069655,0.8166219571778315,
0.8216813253645509,0.8654071763861386,0.8787075572966508,
0.2617543171369139,0.1828690638929441,0.09380207139517749,
9.165794599607253e-005,-0.09130044825545007,-0.1743606863382632,
0.1203649946594492,0.03010042800399446,-0.06571155052616354,
-0.159777601870924,-0.2451943556628112,-0.03438026636045293,
-0.1315172003159161,-0.2277344419143756,-0.3155115060038017,
-0.1921818096757193,-0.2896404384341761,-0.3796026338863787,
-0.3413165804505149,-0.4327064149448353,-0.4726316954005857,
-0.02821670874193007,-0.1260185867435537,-0.2325989754896013,
-0.3416187871825309,-0.444732423910872,-0.5342795725490167,
-0.6058947680736913,-0.6591958160975573,-0.1470960585711635,
-0.2563906423085273,-0.3708132697350703,-0.4816778179392841,
-0.5797443521912047,-0.6586314997511467,-0.7166385361913998,
-0.2735715277331494,-0.3904103835191622,-0.5067262463544535,
-0.6125983088644244,-0.6997514194040853,-0.7645093154710443,
-0.399676350745083,-0.5179198795056302,-0.6291757405426562,
-0.7241473051258307,-0.7970870947583816,-0.516407321060813,
-0.6294464664763966,-0.7300067759514388,-0.8109701936315704,
-0.6166237809711579,-0.7194297010446339,-0.8064715143730887,
-0.697014250125597,-0.7871542772926711,-0.7580246814516085,
-0.2925772011093052,-0.2917164801053564,-0.2839091960301776,
-0.2686946036173254,-0.2472029920942969,-0.2217706416368722,
-0.4163702688077253,-0.417126245587897,-0.407120730642943,
-0.3862981411371962,-0.3570189974757899,-0.5395471670390704,
-0.5383589526996108,-0.5227373833229371,-0.493903460730213,
-0.6521514808212688,-0.6452875761129986,-0.6217223634380962,
-0.7458178526549705,-0.730980062865163,-0.8166217206889562,
-0.7470248243274916,-0.8300238938854384,-0.8996132253994521,
-0.9481264427436803,-0.9719595014156921,-0.9727984419199607,
-0.9560608144734745,-0.8065037168656155,-0.8869742038831786,
-0.9487272157391016,-0.9852727972566903,-0.9957513357128307,
-0.9845987728990332,-0.8513784827612589,-0.9239647227267276,
-0.9737757945994621,-0.9969183688503204,-0.9954874793720167,
-0.8757744250303561,-0.9364058061885231,-0.9728010979637555,
-0.9840624137666333,-0.8778791504147609,-0.9251911695017921,
-0.9495573085262712,-0.8605599852861939,-0.8957918541675716,
-0.8295637303264062,-0.04356566771769104,0.05491337401809196,
0.1594214223252114,0.2625350815284993,0.3565940574819209,
0.4363107079656693,-0.09898073214385947,0.001640881330767951,
0.107535036331357,0.2105720065923513,0.3032602493938258,
-0.1561821374463407,-0.0544880626634626,0.05138399870775862,
0.1531589210125483,-0.2108702003917341,-0.109169268647464,
-0.004642833898907788,-0.2589821529532703,-0.158421915656623,
-0.2980761626942871,-0.9498849702325406,-0.9239433259414138,
-0.8742733756226419,-0.8011425227232617,-0.7099836412348224,
-0.6095443176654687,-0.508553964054817,-0.9717432666228709,
-0.9353919526972201,-0.8728986221002711,-0.7872126141915534,
-0.6864635931358892,-0.5806643774075225,-0.9723007209152063,
-0.9232234443044223,-0.8481362314873311,-0.7529080174160984,
-0.647301592079592,-0.948183485298304,-0.8865251005609038,
-0.8019216417165289,-0.7022083677250226,-0.9011831985532854,
-0.829863222791688,-0.7406456753648975,-0.8376466557989706,
-0.7611469342493191,-0.7656341022868733,0.6646639924076627,
0.7437284087719479,0.8111264735787829,0.8596396929680696,
0.8856640083476979,0.8904375589329932,0.6339126501414293,
0.707680317140174,0.7670192843558462,0.8059787882713181,
0.8231600236208387,0.5859180191150533,0.651402785083716,
0.7012137302542939,0.7314575393289862,0.5218269830903716,
0.577817672809353,0.6188532957478536,0.446400869266141,
0.4937126651205253,0.3663934528166599,-0.4542528774843695,
-0.3845634904875965,-0.3006176376093279,-0.2069068719953542,
-0.11039298336186,-0.01813638876408994,0.06488637319187028,
-0.5237534893339546,-0.4491544873380491,-0.358984163651417,
-0.2592757174096171,-0.1581927886880057,-0.063058272648828,
-0.5860663263409258,-0.5055265231286077,-0.4093088881435918,
-0.3049339801812209,-0.2011322717929374,-0.6350799196461491,
-0.5484668466671915,-0.4476583293687135,-0.3410374453295617,
-0.6671530327423928,-0.5757628211692016,-0.4729440070010416,
-0.6823550906513535,-0.5886114742048517,-0.6837139951578899,
0.8533626369422408,0.8228097648480324,0.7705716341879386,
0.6974405664026642,0.6088494821992544,0.513021117997808,
0.7694759566268259,0.7252693007743299,0.6599467606818161,
0.5770896067011005,0.4841956488153404,0.6611955122025592,
0.6037957522821978,0.5287083985893539,0.441802418256347,
0.5333764308745213,0.4662795459560942,0.387114402450423,
0.3955144253601533,0.3241943959991313,0.2585109731392027,
0.05492543133462732,0.04271134692005163,0.02858111208036886,
0.01336634929270618,-0.001802636489293655,-0.01588190769759986,
-0.08164059192530317,-0.1002253860034311,-0.1171965412658538,
-0.1310538163159151,-0.1409924872128895,-0.2264379065659517,
-0.2481170428345225,-0.2637387553592617,-0.2720820325977006,
-0.3691621981499088,-0.3894163023521484,-0.3995915326289882,
-0.4992104641187212,-0.5140483226358935,-0.6092930383066186,
-0.1282040992012935,-0.03314438343075717,0.07418771901881034,
0.1895805529161077,0.3060111300013609,0.4152646181118619,
0.5105522497698926,0.5884153641804594,0.6488215902264565,
-0.1662652220900749,-0.06672909617768248,0.04565193884691998,
0.1653145024136672,0.2838178720038453,0.392358453375388,
0.4847688072125908,0.5588878800183537,-0.2061837828129686,
-0.1028578719693947,0.01320461245153456,0.135055834380525,
0.2533186742384155,0.3594175117480762,0.4483631157317138,
-0.2454367954185786,-0.1392470619788042,-0.0212985877993455,
0.1003748549375823,0.2162630814588294,0.3187734758296685,
-0.2808945465452747,-0.1730244679184136,-0.05523589088936585,
0.0639822904424641,0.1758296024995542,-0.309764254307227,
-0.2016807651564305,-0.08611192469610081,0.02876188488837943,
-0.3305621657917769,-0.2239243298387429,-0.1123798946526014,
-0.3434303716667939,-0.2398370895892076,-0.3496821715684524,
0.6714420577705413,0.7524953419593941,0.8307215647087252,
0.8988911695232938,0.9496341036793501,0.9781045443142695,
0.983882155708098,0.9706580078492304,0.9441720387917811,
0.7131190377206373,0.7979983822227008,0.8766844493347566,
0.9405391525406509,0.982132974036711,0.9983759032186432,
0.9915700817355307,0.967642375326243,0.7477894668983293,
0.8327562120383802,0.9072360592139173,0.9621573628309809,
0.9915144459980433,0.9950116576093856,0.9775308002021622,
0.7702158662916526,0.8504518596256061,0.9159087827490561,
0.958615376965025,0.9752335996497555,0.9682499097067426,
0.7760312926982584,0.8470020976881563,0.9002461340540874,
0.9301900108044431,0.9363385958760152,0.7636458947692996,
0.8226631878609201,0.863227169508762,0.8824665400301602,
0.7350862725086435,0.7819435892168385,0.8116669810370153,
0.6950244929211268,0.7313851393296726,-0.9441722324566724,
-0.8982335639429714,-0.8313456723553714,-0.7414326155290212,
-0.6303269409870232,-0.504437732215241,-0.3731115220313701,
-0.2455227591385536,-0.9277610900314076,-0.8719938339703784,
-0.7922901462160301,-0.6879655695561273,-0.5635230570387244,
-0.4282074607020305,-0.2928561738545139,-0.8935348618728204,
-0.8252311012303484,-0.7312055040636086,-0.6132787902902372,
-0.4790574606800003,-0.3397875802758924,-0.8379237951960332,
-0.7555203588771385,-0.6479597593660587,-0.5201883296648473,
-0.3821929206720374,-0.7605084662990487,-0.6648552402767216,
-0.5474979380988695,-0.4159703173399101,-0.6652563588950895,
-0.5599712780007364,-0.4386104476633646,-0.5596790773588694,
-0.4500513701337736,-0.452215421939787,-0.3130828685601688,
-0.2026653349757201,-0.07519795113003093,0.06519223482424771,
0.2106381298878163,0.3511437862186094,0.4776948653078811,
0.5848777234045024,-0.3092743464263315,-0.189541493899996,
-0.05216564154993419,0.09665867971286488,0.2468076262033025,
0.3871266155400391,0.5092302530840672,0.6095258724352348,
-0.299731815412124,-0.1710988752936458,-0.02562616156907596,
0.1281943739657924,0.2786088475509629,0.4146241489277275,
0.5296074119458033,-0.2831889282507517,-0.1472477576556685,
0.002978788421451789,0.1571443739074394,0.3031991278501129,
0.4316900017871718,-0.2593820240207756,-0.1190520671608967,
0.03150460300683353,0.1812458940061291,0.3193074202631062,
-0.229491624834242,-0.08860645786522432,0.05782435035907074,
0.1994358494400003,-0.1959070295313489,-0.05832274784344905,
0.08053951964108649,-0.1613858092941266,-0.03012854522533278,
-0.671442351589465,-0.7524955042654247,-0.8307216077305004,
-0.8988911324269672,-0.9496340459616871,-0.9781045247295723,
-0.9838822098556939,-0.9706581405182357,-0.6732379910932457,
-0.7555353929734253,-0.8321927576733623,-0.8949176301047361,
-0.9365114268652753,-0.9538841305299445,-0.949106939734586,
-0.6637939293172054,-0.7437729138119192,-0.8147968652653733,
-0.8684734875620626,-0.8990751104656249,-0.906028082404147,
-0.6398902977415805,-0.7135875679260879,-0.7753830615613055,
-0.8180895331241328,-0.8383689548572043,-0.6002017842451572,
-0.6645162706136697,-0.7153675946298389,-0.747703849697991,
-0.5464363016035276,-0.6002045214061834,-0.6407682965760649,
-0.4830988161196208,-0.5271645300902241,-0.4158550110968205,
-0.648822290296783,-0.6472486014147985,-0.6344626299567083,
-0.6075203746111165,-0.5653935344751363,-0.5100061066600627,
-0.4459169294668335,-0.3786832614419487,-0.7313855414086173,
-0.7310744930343959,-0.7160642832118092,-0.6830433558919348,
-0.6318400429346884,-0.5662582509809229,-0.492781618346183,
-0.418059300054038,-0.8116671044980045,-0.8099276517898805,
-0.7895071237697285,-0.74756375917153,-0.6857578728711079,
-0.6101862708902825,-0.5288485365725882,-0.882466459585,
-0.8755369303175729,-0.8463852653947486,-0.7938122127531423,
-0.7219269876119373,-0.6386807736786417,-0.9363384293729856,
-0.920580474049937,-0.8807752703984302,-0.8181738478934094,
-0.7389956620788968,-0.9682497764059059,-0.9417119830617079,
-0.8917766410561483,-0.8219783739569782,-0.9775307754986758,
-0.9407006676234038,-0.8832579304805722,-0.9676424743883053,
-0.9228815898031446,0.3130823317650696,0.2026646799488628,
0.07519720122433592,-0.06519302988114704,-0.2106389019045293,
-0.3511444697687643,-0.4776954195825031,-0.5848781397282268,
0.2455618355531619,0.1217043818280624,-0.01891222872758066,
-0.1695413327023869,-0.3196901877897432,-0.4582042349710876,
-0.5770670118160844,0.1655447705464922,0.0289439344448441,
-0.1220494268493898,-0.2778581225722938,-0.4262841911656161,
-0.5567786600361208,0.07498802093385774,-0.07139865292607843,
-0.2274740800198117,-0.3816395081442781,-0.5218451060581218,
-0.02151295053653907,-0.1724761631672423,-0.3268548028226648,
-0.4727737792825113,-0.1175093448034605,-0.2667795638863601,
-0.413210185645996,-0.2066526242811376,-0.3486960301430706,
-0.2845979196243639,0.1282040764044601,0.03314425179116901,
-0.07418801789892716,-0.1895810572320515,-0.3060118317848469,
-0.4152654547344749,-0.51055312502423,-0.5884161844630592,
0.03012854220925541,-0.07822075478791662,-0.1975265605100549,
-0.3210457437412529,-0.4395492890997685,-0.5442335497807274,
-0.6297193044589443,-0.6950252371327137,-0.08053951945115613,
-0.2008908777469321,-0.3287498381001709,-0.454849657793549,
-0.5688642328312289,-0.6631668267266261,-0.7350870708018485,
-0.1994358711312821,-0.3279452265433291,-0.4583916832350944,
-0.5800652917395807,-0.683455813944916,-0.7636467367251844,
-0.3193074905789999,-0.4498985165051642,-0.5758541835274278,
-0.6869055692486817,-0.7760321386045594,-0.4316901383846216,
-0.5576908306091364,-0.6732598101682218,-0.7702166526708257,
-0.5296076162752261,-0.6457739738857279,-0.7477901272839138,
-0.6095261314476621,-0.7131195245736661,0.6472479688324123,
0.6344620803203709,0.6075199046816795,0.5653931175085022,
0.5100057007389891,0.4459164955009389,0.3786827774326808,
0.5474099886510654,0.5236257914257873,0.4857185197867951,
0.4345152489333596,0.3738198763531287,0.3091172837171857,
0.4250511511939136,0.389683753785766,0.3423573476615138,
0.2859346018498913,0.2253099468416643,0.2835632478824897,
0.2385758256608239,0.1860028309402729,0.1299534657091715,
0.1312824242313411,0.08112906023855893,0.02887591783637235,
-0.02047837605993849,-0.07041365620347247,-0.1612832799773341,
0.8982333732257657,0.831345524857385,0.7414325451852105,
0.6303269573377657,0.5044378109359756,0.3731116142445962,
0.2455228128124526,0.9228814872695982,0.8667983517234625,
0.7868465046935174,0.6823837598597929,0.5579412946135831,
0.4227639330815517,0.2876608055402039,0.1613856625640601,
0.8832579654623612,0.8143439687072217,0.7198955735651289,
0.6018165967179313,0.467747528435525,0.3289004093680582,
0.1959067638111305,0.8219785498827571,0.7387750958937861,
0.6307665078242817,0.5029950256220953,0.3654474931658011,
0.2294912586325793,0.7389959159190775,0.6425282428469168,
0.5248781214125594,0.3936431094566906,0.2593815856416469,
0.6386809855643202,0.5327535820451708,0.4113926019080829,
0.2831884462269615,0.5288485749239231,0.4188791724037085,
0.2997313094215869,0.418059069948,0.3092738247890606,
0.6297184498311313,0.5442326731425132,0.4395485037972626,
0.3210451478850294,0.1975261966743493,0.07822060158766293,
0.6631659475585863,0.5688633866559212,0.4548489689298922,
0.3287493895928871,0.2008906793070462,0.6834549460780991,
0.5800645299836926,0.4583911438911752,0.3279449596345045,
0.6869047733719595,0.5758535688432742,0.449898169624651,
0.6732591535970365,0.5576904114999332,0.6457735063412144,
0.9277609198709332,0.949106860839256,0.9538841631800392,
0.9365115581247451,0.8949178072878723,0.8321929059126493,
0.755535446210326,0.6732379126875105,0.8935348059013593,
0.9060281564869469,0.8990753265127792,0.8684738109832391,
0.8147972186077681,0.7437732084300421,0.6637941002839092,
0.8379239537972928,0.8383692759036656,0.8180900037577743,
0.7753836155369005,0.7135881068095284,0.639890731966599,
0.7605089118538748,0.747704461889213,0.7153683254339585,
0.664517027376214,0.6002024649156598,0.6652570996829634,
0.6407691682823238,0.6002054473372921,0.5464371824658241,
0.5596800524090022,0.5271655706244485,0.4830998363360157,
0.4522165310007144,0.4158561136906575,0.3496833143594963,
-0.2876608652754351,-0.4227639382532795,-0.5579412897306785,
-0.6823837835510913,-0.7868465717409772,-0.8667984500087526,
-0.3289005616515215,-0.4677475887278177,-0.6018165999573247,
-0.7198955529773995,-0.8143439414326642,-0.3654477029697049,
-0.5029950893382186,-0.6307664561929963,-0.7387749669914671,
-0.3936433402523272,-0.5248781506021705,-0.6425281057326593,
-0.4113928310116375,-0.5327535685472626,-0.4188793967911134,
0.577066822550539,0.4582039092088336,0.3196897246958904,
0.169540766109225,0.01891161845986538,-0.1217049732030892,
-0.2455623627393322,0.5567787306370593,0.4262841209617862,
0.2778578974521733,0.1220490717256491,-0.02894436515050694,
-0.165545217365127,0.5218454423524129,0.3816396895816639,
0.2274740807377008,0.07139849210836301,-0.07498829123147716,
0.4727743520975624,0.326855199205205,0.1724763529977552,
0.02151295276860444,0.4132109394322543,0.2667801205874505,
0.1175096785325448,0.3486969033343195,0.2066532886754674,
0.2845988618411943,-0.9915701323913838,-0.9983759139464571,
-0.9821329817122836,-0.9405392168410572,-0.8766846298252051,
-0.7979987142017131,-0.9950116201913212,-0.9915144412787341,
-0.9621574590524813,-0.9072363224101446,-0.8327566769720253,
-0.9752335225013484,-0.9586154363208594,-0.9159090584602802,
-0.8504523952727223,-0.9301899969464084,-0.9002463663906001,
-0.8470026365747616,-0.863227339500068,-0.8226636840857314,
-0.7819440310902068,-0.3091177896659217,-0.3738203674077975,
-0.4345157440029583,-0.4857190441849699,-0.5236263640902669,
-0.5474106128468904,-0.5588885443532919,-0.2253103954606045,
-0.2859350592025221,-0.3423578252345214,-0.3896842610441149,
-0.4250516888435538,-0.4483636748755489,-0.1299537462879293,
-0.1860031284708927,-0.2385761459990237,-0.2835635916740772,
-0.3187738370923436,-0.02887592341002545,-0.0811290830782055,
-0.1312824709082232,-0.175829673802738,0.07041398450649188,
0.02047868355036482,-0.02876160928094873,0.1612839336168132,
0.1123805173372347,0.2398380094723457,-0.5092306348673886,
-0.3871271308997349,-0.2468082566335953,-0.09665937383397012,
0.05216495245602301,0.189540870507144,-0.4146244745670597,
-0.2786093002807504,-0.1281949271302634,0.02562556437243592,
0.1710982989127918,-0.3031993859046618,-0.1571447546490307,
-0.00297925984664287,0.147247252029971,-0.1812460903983632,
-0.03150492197167008,0.119051661271318,-0.05782450627681404,
0.08860617741886109,0.05832260658459812,-0.4847695337402862,
-0.3923591556376936,-0.2838184503258238,-0.1653148824643805,
-0.04565210375030839,0.06672910665806144,0.1662653402185898,
-0.3594180507425287,-0.253319097564816,-0.1350560618895416,
-0.01320461850800903,0.1028580486723768,0.2061840662709727,
-0.2162633298539993,-0.1003749112365929,0.02129875586186771,
0.139247419944916,0.2454372621958313,-0.06398217348632655,
0.05523623192861417,0.17302500577526,0.2808952005684321,
0.08611242071710691,0.2016814632806757,0.3097650809527805,
0.2239251562628219,0.3305631346577989,0.3434314452768145,
0.4927814627145429,0.5662581542385627,0.6318399645986254,
0.683043240780333,0.7160640841376876,0.7310741891309572,
0.6101863849438733,0.6857580324047194,0.7475639112793486,
0.78950721141067,0.8099276375885235,0.7219272504872226,
0.7938124902720932,0.8463855099577528,0.8755371018531016,
0.8181741141101887,0.8807755242176112,0.9205806914487843,
0.8917768010350154,0.9417121277771469,0.9407006846750625,
0.2928563777418555,0.4282076937835696,0.5635232482078705,
0.6879656610506216,0.7922901195775008,0.8719937126447483,
0.3397879564876633,0.4790578522946484,0.6132791099941464,
0.7312056921497674,0.8252311496217807,0.3821934817691987,
0.520188888877212,0.6479602207299933,0.7555206677931847,
0.415971059154168,0.5474986596025796,0.6648558465528478,
0.4386113475958364,0.5599721413103722,0.4500523932965443 };
auto pointshell
= new vnl_matrix_fixed<double, 3, 642>(coords);
return pointshell;
}
};
template<> class PointShell<812, vnl_matrix_fixed<double, 3, 812> >
{
public:
static vnl_matrix_fixed<double, 3, 812>* DistributePointShell()
{
double coords[3*812] = {
0.9756767549555487,0.9922508097125681,0.9977223655964853,
0.9881046683022422,0.9605519470607568,0.9146195529015363,
0.8528238339140162,0.7799959774035472,0.7017828679367573,
0.6231965669156313,0.9837002757017411,0.9971982264747434,
0.9970195212545997,0.9790578176231792,0.9411837637692063,
0.8844913295435498,0.8132898830804115,0.733693935416079,
0.6517368229295557,0.9797764734635961,0.9875546637606186,
0.9791028733313679,0.9508425500024201,0.9020818068674743,
0.8358206809420552,0.757892552927626,0.6749593629473696,
0.9602286065935876,0.9595713376770644,0.9407948278222147,
0.9016229543668696,0.8432733179563544,0.7704382634077368,
0.6896667228240099,0.9226923908191266,0.9116587851060941,
0.8819863001926875,0.833225536765196,0.7683765355083914,
0.693030195174853,0.8672949635738141,0.8455181303237055,
0.8062955359163166,0.7509515682311381,0.6835651897016059,
0.7970712198937139,0.7659650471206068,0.7200326020746473,
0.6617902410567805,0.7171844959174759,0.6793953685069648,
0.6300938559406523,0.6333774065241421,0.5918819525326566,
0.5505632701289798,0.4375940376503738,0.3744427273176402,
0.2993381563954681,0.2130515669413183,0.1182813882301629,
0.01954824200640591,-0.07773888316805401,-0.1686715778074173,
-0.2499271804752164,-0.32007301315036,0.4854882574576871,
0.4194229010537701,0.3399338752288831,0.2482942679442456,
0.1481384200976902,0.04502062388977755,-0.05499873367858239,
-0.1469877513574829,-0.2280773868570659,0.5324004751734927,
0.4628532125512143,0.3786136701220479,0.2817283713716202,
0.1769156386035929,0.07062416136199023,-0.03081255771979229,
-0.1228131994141411,0.5750755655636769,0.5013629074790578,
0.4122166091807719,0.3107083252171691,0.2025911492637849,
0.09481562164394035,-0.006505365777837463,0.6099587706972414,
0.5315747218240751,0.4378921540503243,0.3330794318970117,
0.2235852429888137,0.1162930447896056,0.6341450324413492,
0.5511580300049011,0.4540605894555947,0.3478844246654598,
0.2392124945153528,0.6463093264667951,0.5595982440953389,
0.46086512448968,0.3555189519163455,0.647046909800018,
0.5581741842011717,0.4598430939447178,0.6384375755240163,
0.5492419252084272,0.3200724178002418,0.4163027723501219,
0.5178612432225475,0.6201479032959074,0.7171164359379398,
0.8025495773806206,0.8717669667532965,0.9228269911622408,
0.9565659576168886,0.3662566345969678,0.4693191708546967,
0.5762858482292442,0.6811797034275579,0.7768921407658641,
0.8570710368648269,0.9180184145424319,0.9594305591455454,
0.4128244293574089,0.5208884118196857,0.6304558785383466,
0.7343501607073976,0.8250439179808262,0.8969571451990621,
0.9480541165102998,0.4569904905821253,0.5671264332790738,
0.6755415775491402,0.7744719807282637,0.8569290887080647,
0.9189090911818834,0.4955267041670984,0.6040846468052238,
0.7074267562469234,0.7981205092043148,0.8705859012982401,
0.5255624261223592,0.6289645166670731,0.7241496615411406,
0.804855834362468,0.5454521871592556,0.6410312785579098,
0.7264644091774437,0.5551982228864044,0.641627582268501,
0.5561969667017818,0.2502538949373057,0.2872027754172267,
0.3245344712904296,0.3600408236839537,0.3911506315330521,
0.4155633223527059,0.4319414682718341,0.4402542183539166,
0.4415840008368697,0.3505479885894233,0.3943500788462172,
0.43685649380825,0.4748347886538213,0.5050141859852789,
0.5250961060909611,0.5345072780254662,0.5344003893389805,
0.5269837056592495,0.4574833953114167,0.5069750581222974,
0.5525393550046852,0.5900243847437713,0.6159403270481748,
0.6286926742607352,0.6290385665487288,0.6194911060068102,
0.5665551499276381,0.6191962274832306,0.6644606027057701,
0.6977977540386979,0.7162925017359711,0.7197189132272425,
0.7103565350090897,0.6716249671619864,0.7237430894816727,
0.7648128117488485,0.7907287689487973,0.7998964507309693,
0.7936885378432519,0.7661563418365048,0.813819159923423,
0.8474217166041815,0.864080531689031,0.8638072256614686,
0.8449704612165639,0.8851005033495888,0.9095132315221558,
0.9168712118355733,0.9055760485508874,0.9366559154796388,
0.9518640240021961,0.9483465315553231,0.9704010313875515,
-0.4375932291383154,-0.3744420515634606,-0.2993376542433732,
-0.213051272338593,-0.1182813170567518,-0.01954838456202594,
0.07773856031405028,0.1686711209781245,0.249926635788548,
-0.3473076758598704,-0.2731773531779083,-0.1869784560548725,
-0.09084077595186728,0.01090483422160223,0.1124324367516528,
0.2079533392573423,0.2932321828182562,-0.2423880400933935,
-0.156942680061891,-0.06052677114529338,0.04301840739087177,
0.1478309256372904,0.2474621200563187,0.336722136779245,
-0.1245894223683107,-0.02900257303954696,0.07490364945070915,
0.181648017057727,0.2845287164429474,0.3775439714321544,
0.00186176882165046,0.104598795853549,0.2116013903531214,
0.3164139369537128,0.4125877669907546,0.1306304412032901,
0.2361087796289779,0.3411560209375105,0.4393820957485916,
0.2546621526726749,0.358132074959863,0.4568650785571312,
0.3679945821324933,0.465540692618106,0.46700138061564,
-0.6231952788307172,-0.5574600324007678,-0.4770927236000206,
-0.3823142165271753,-0.2756046525485073,-0.1617836973833182,
-0.0470869101281101,0.06243545366421368,0.1623223370722767,
-0.5492408053824432,-0.4724705019699099,-0.3803275558898422,
-0.2743443251752258,-0.1587631541423281,-0.04000763487086941,
0.07495625978661888,0.180495590370777,0.2733676095225912,
-0.4598422233986804,-0.3712294758837851,-0.2676544688598244,
-0.1524290150215411,-0.03159943316739083,0.08740013657156358,
0.1978753137579477,0.2954972412516565,-0.3555183995893311,
-0.2556130138286056,-0.1427706895826486,-0.02217694060430834,
0.09888849629266881,0.2130604246988013,0.3149362814931866,
-0.2392122924568965,-0.1303824105317197,-0.01228273317409482,
0.1085468771341984,0.2246722751170698,0.3298926161068582,
-0.116293170907997,-0.002544855969777311,0.1157810363722986,
0.2317919381153067,0.3389908350437634,0.006504983859799631,
0.1204470178133221,0.2342680443317885,0.3417324928044827,
0.122812659812205,0.23268986296373,0.338624103921372,
0.2280767837862029,0.330902937710777,-0.2502532651867688,
-0.2872021140968067,-0.3245337697854004,-0.3600400745299252,
-0.3911498325365141,-0.4155624805143979,-0.4319406005716203,
-0.4402533481355587,-0.4415831518511793,-0.1708721571930995,
-0.2041871265271164,-0.2379683866812855,-0.2700974862342881,
-0.2982093646817494,-0.3203587126138262,-0.3356190104303782,
-0.3442372407872382,-0.08038054194912378,-0.1091996275570321,
-0.1389306574098392,-0.1677554863057991,-0.1936713782240709,
-0.2150838382608105,-0.2312629415986541,0.01921174674137868,
-0.004986017519443271,-0.03105772275158658,-0.05758606025521312,
-0.08288952042427381,-0.1055085254918716,0.123925135248786,
0.1034734912606135,0.07972411299125522,0.05380820853884998,
0.02732027507363822,0.2282811487692264,0.2098640891542395,
0.1865989201629623,0.1596028170589836,0.3265627679363224,
0.3082244742822114,0.2838117948729975,0.4142824694706087,
0.3944807806873461,0.4890558390601624,-0.975676581463901,
-0.9922507181739645,-0.9977223240044052,-0.988104613901425,
-0.9605517932270823,-0.9146192114249708,-0.8528232434185343,
-0.7799951208906594,-0.7017817703686649,-0.9704008071255719,
-0.9831225967982262,-0.9822981052334858,-0.9639034131304861,
-0.9258761899238439,-0.8693365652843744,-0.798567800167315,
-0.7196174154484367,-0.6384363279989543,-0.951863752574358,
-0.9581118567763953,-0.948488121885417,-0.9195867065770826,
-0.8708257888235816,-0.8052054331206489,-0.7284489979298084,
-0.6470457280542714,-0.9168708930751738,-0.9141083375203286,
-0.8939111910264987,-0.854235225343551,-0.7963893637954717,
-0.7249746765437297,-0.6463082287051728,-0.8638068526880216,
-0.8504293560497204,-0.8194747846295519,-0.7707138739098191,
-0.7071466871144221,-0.6341440232385527,-0.7936880971710701,
-0.7697465167330589,-0.7297586716006348,-0.675179694541184,
-0.609957839140293,-0.7103560109842373,-0.6776367931781411,
-0.631704229014305,-0.5750746905699001,-0.6194904872158699,
-0.5808664875389803,-0.53239963484432,-0.5269829891706682,
-0.4854874364134862,0.5574614519339011,0.4770942414262169,
0.3823157740702657,0.2756061719864941,0.1617850988203112,
0.0470881327099307,-0.06243443855232068,-0.1623215265517549,
0.5809489294799253,0.4937832424572646,0.3911366273799454,
0.276734760526323,0.1567997280124966,0.03849904347704674,
-0.07201766541821289,0.5981392304579348,0.5035962293740359,
0.3933108814734469,0.2724812113143264,0.1485413749948833,
0.02903407175199371,0.6059866911555354,0.5040926955212129,
0.3873829237054168,0.2624333853186085,0.1373130258988978,
0.6022642769367629,0.4940448560674484,0.3732152095431146,
0.2472094891883707,0.5864999399564288,0.4740709200953988,
0.352163126792074,0.5602791768912673,0.4464581629930486,
0.5266502279007443,-0.4163031917414612,-0.5178614819829612,
-0.6201479767677171,-0.7171163801074496,-0.8025494402189062,
-0.8717667933239608,-0.9228268112486158,-0.9565657823609164,
-0.3309034260843112,-0.4319023018909033,-0.5371520139920846,
-0.6408948133012854,-0.7362003328755568,-0.8167859635709049,
-0.8788842105927732,-0.9220131313955344,-0.9483463221383831,
-0.338624488411881,-0.4426206857782847,-0.5490725801393385,
-0.6512627192307555,-0.7419563768480812,-0.8155735468033498,
-0.8697858892475217,-0.9055758335701712,-0.3417327749428255,
-0.4462719473348893,-0.5509105300296661,-0.6485010946606566,
-0.7322978310246682,-0.7980541850077586,-0.8449702640289916,
-0.3389910093648414,-0.4413180005751814,-0.5412519758066311,
-0.6319456221810869,-0.7078189355434928,-0.7661561658452967,
-0.3298926669562023,-0.427540138135818,-0.5206911591272092,
-0.6034312473993601,-0.6716247883748602,-0.3149361858566656,
-0.4062273552356623,-0.49166038715387,-0.566554922382665,
-0.2954969768757202,-0.37970711664501,-0.4574830674709519,
-0.2733671630067541,-0.3505475201547475,0.7196184465472099,
0.7985685715325342,0.8693370709616777,0.9258764738945257,
0.9639035601847371,0.9822982118031284,0.9831227403545156,
0.7284499433836592,0.8052061147659351,0.8708262265695167,
0.9195869704437927,0.9484883092395549,0.9581120573066315,
0.7249755313208718,0.796389971071354,0.8542356312683819,
0.8939114816111898,0.9141086068192968,0.7071474645768509,
0.7707144394707161,0.8194752023181837,0.8504297125393642,
0.675180421967678,0.7297592328398797,0.7697469803916117,
0.6317049359907486,0.6776373777282386,0.5808671950649753,
-0.366257089693115,-0.2932325919216836,-0.2079536613378413,
-0.1124326200188124,-0.01090482797043428,0.09084100501255125,
0.1869789126919778,0.2731780147607579,0.3473085031912251,
-0.4128247445431558,-0.3367224114404735,-0.2474623076665533,
-0.1478309677445388,-0.04301824976707492,0.06052715939621055,
0.1569432970144201,0.2423888563057751,-0.4569906864326022,
-0.377544132020254,-0.2845287871856594,-0.1816479322770386,
-0.07490335342398057,0.02900310611676332,0.1245901828483064,
-0.4955268212110568,-0.4125878505007722,-0.3164139219124497,
-0.2116012050517462,-0.1045983865863539,-0.001861117423562203,
-0.5255625148012287,-0.4393821442371415,-0.3411559538741524,
-0.2361085232789399,-0.1306299482392742,-0.5454522916908328,
-0.4568651248612463,-0.3581319814379551,-0.2546618495309371,
-0.5551983685993169,-0.4655407524301317,-0.3679944751189687,
-0.5561971575770934,-0.4670014539093825,-0.5505634949474449,
0.9220133236751157,0.8788843849049742,0.8167861054780646,
0.7362004119831233,0.6408947895214253,0.5371518506414063,
0.4319019774051972,0.8697860623176014,0.8155736760665241,
0.7419564499373366,0.6512627126170119,0.5490724656572447,
0.4426204410195734,0.7980543166386451,0.73229789903684,
0.6485010946606566,0.5509104500833818,0.446271772176749,
0.7078190327552072,0.6319456504394643,0.5412519405164845,
0.4413178995840423,0.6034313501235972,0.5206912029562619,
0.4275401340932171,0.4916605546162393,0.4062274818767118,
0.379707405130632,0.3442381194341675,0.3356199216704505,
0.3203596326360576,0.2982102696268391,0.2700983579505985,
0.2379692158357015,0.2041879117102824,0.1708729017037819,
0.2312638113027555,0.2150847428759935,0.1936722946488835,
0.1677563920072661,0.1389315354365512,0.1092004686440709,
0.08038134335000687,0.1055093293250425,0.08289035011594331,
0.05758689641252075,0.03105854840479935,0.004986821056754707,
-0.01921097131735246,-0.02731960194972041,-0.05380752683403425,
-0.0797234336008201,-0.103472821018762,-0.1239244773230862,
-0.1596023291970502,-0.1865984417823142,-0.209863618928254,
-0.2282806816594251,-0.2838115205510092,-0.3082242217152255,
-0.3265625234832059,-0.39448071777243,-0.41428243288548,
-0.4890559628033717,0.1469872495241008,0.05499837995147388,
-0.04502078247419547,-0.1481383500660343,-0.2482939617934105,
-0.3399333541527281,-0.4194222062209155,0.03081218235410985,
-0.07062432464607897,-0.1769155567176647,-0.281728039903757,
-0.3786131170062194,-0.462852487954783,-0.09481577398373708,
-0.2025910390450985,-0.3107079508004592,-0.4122160055133201,
-0.5013621351348974,-0.2235850902780548,-0.3330789997683635,
-0.4378914824575998,-0.5315738812374622,-0.3478839295034498,
-0.4540598420421491,-0.5511571070104784,-0.4608643070543677,
-0.5595972383031447,-0.5581731097866064,0.07201857797974105,
-0.03849795696968416,-0.1567984874655333,-0.2767334157256128,
-0.3911352491971175,-0.4937819036034042,-0.5809476860617484,
-0.6517357063102128,-0.02903313746554977,-0.1485403228794575,
-0.2724800804665481,-0.3933097299991974,-0.503595119108857,
-0.598138209964731,-0.6749584587129783,-0.1373121735202105,
-0.2624324872189829,-0.3873820250532686,-0.5040918441619855,
-0.6059859240149241,-0.6896660583043277,-0.2472088184389502,
-0.3732145606963823,-0.4940442637379011,-0.6022637655195766,
-0.6930297734586861,-0.3521626999463403,-0.4740705579739117,
-0.5864996568405977,-0.6835649861113746,-0.4464579863091031,
-0.5602790756561028,-0.6617902107749168,-0.5266502592949665,
-0.6300939487796368,-0.5918821259544012,-0.53439964190375,
-0.5345065247441787,-0.525095375735572,-0.5050135034697202,
-0.4748341677209202,-0.4368559346659283,-0.3943495717901673,
-0.6290379264397734,-0.6286920435345361,-0.6159397381647077,
-0.5900238619718436,-0.552538907016351,-0.5069746781213621,
-0.7197183758293895,-0.7162919864381756,-0.6977972953381246,
-0.6644602226954861,-0.6191959297333463,-0.7998960023058911,
-0.7907283519716943,-0.7648124613084771,-0.7237428249931476,
-0.8640801553848605,-0.8474213786178793,-0.8138188945925402,
-0.9095129144421652,-0.8851002301776055,-0.936655652047691,
-0.7336930479121847,-0.8132892661843129,-0.8844909854341375,
-0.9411836430482039,-0.9790578295745921,-0.9970195644563975,
-0.9971982203541059,-0.9837001754183022,-0.7578919095374027,
-0.8358203200836417,-0.9020816987419813,-0.9508426122816337,
-0.9791029969688041,-0.9875547507725127,-0.9797764622248338,
-0.7704378741700656,-0.8432731964302291,-0.9016230372124288,
-0.9407950105701793,-0.959571511273145,-0.960228691612206,
-0.768376378413949,-0.8332256052212422,-0.8819865069139035,
-0.9116590219002929,-0.9226925651801682,-0.7509515941742244,
-0.8062957285440923,-0.8455183951051963,-0.8672952051616537,
-0.7200327517213486,-0.7659653038152823,-0.7970714969272577,
-0.6793955903243286,-0.717184776407749,-0.633377666107338,
-0.1804949761426579,-0.07495545509988207,0.04000862921312944,
0.1587643045074381,0.2743455685619207,0.380328817183559,
0.472471714864844,-0.1978749051329674,-0.08739956539043256,
0.0316001612578226,0.152429864698119,0.2676553828144042,
0.3712303926692266,-0.213060219387871,-0.0988881700848137,
0.02217737847260294,0.1427712082619221,0.2556135701396871,
-0.2246722609068409,-0.1085467937789958,0.01228287704184508,
0.130382595337822,-0.2317920983902931,-0.1157811822543603,
0.002544721985696509,-0.2342683636555594,-0.1204473722877317,
-0.23269032918574,-0.9594304364836954,-0.9180182641419954,
-0.8570708740276961,-0.7768920058412835,-0.6811796536024748,
-0.5762859389154773,-0.4693194383350184,-0.9480540609614943,
-0.8969570397650206,-0.8250437852464129,-0.7343500529080861,
-0.6304558624488807,-0.5208885452010862,-0.9189091107086019,
-0.8569290407920915,-0.774471897882643,-0.6755415222905497,
-0.5671264763802179,-0.8705859926593716,-0.798120523611733,
-0.7074267366705677,-0.6040846614078772,-0.8048559824957469,
-0.724149733213467,-0.6289645629177542,-0.7264645919207081,
-0.641031394884048,-0.6416277774997261,-0.1778161375899129,
-0.1160626578000681,-0.04588612344347009,0.03109142233089637,
0.1117410720994994,0.1918123956592439,0.2669187829195654,
0.3336638559940376,0.3902934987610119,0.4366423972091847,
-0.07822810590231034,-0.006235377192768587,0.07354985884216768,
0.1581390650418906,0.2429944925392092,0.3229913994840846,
0.3938351936689208,0.4531165220472979,0.5004647043037878,
0.03352103754179751,0.1154299733980676,0.2032831078056842,
0.292541229210957,0.3775430167942871,0.4530586788103156,
0.5157866661887469,0.5648910982101242,0.1544374088220477,
0.2443626306102227,0.3370001516124326,0.4265382311030134,
0.5070037257166236,0.5740673187258024,0.6260922126282031,
0.2792615471857886,0.3736358874527184,0.4664608463431823,
0.5514626265288498,0.6234114376019896,0.6796182090584544,
0.4012129841179684,0.495438498091003,0.5837000128597972,
0.660290805551725,0.7214982694759079,0.513610737510482,
0.6032356918969084,0.6833069969058528,0.7494380454402638,
0.6115888872401081,0.6933734762473292,0.7634088105496576,
0.6929698693584984,0.7653064136814648,0.7580253719184178,
-0.5980610514568759,-0.5540609356997265,-0.4979043682596813,
-0.4291113361140411,-0.3489872892412604,-0.26088135031786,
-0.1696203080333493,-0.08026917121509158,0.003104503401481844,
0.07805400320688781,-0.5118464583535911,-0.4574805454176465,
-0.3903649047262822,-0.3111481867341126,-0.2226772699131629,
-0.1297540437661504,-0.03794114332033659,0.04796410149079763,
0.1249140518997611,-0.4093046623238462,-0.3436365672482747,
-0.2657018883722788,-0.177734023626004,-0.08420287536469411,
0.009136975046692321,0.09689317432239272,0.1753846695482919,
-0.2914862882507431,-0.214943022039254,-0.1281283439422551,
-0.03496909012717313,0.05893398726743186,0.1478453618978381,
0.2274959035287995,-0.16207395039147,-0.07691226494625918,
0.01500850865584403,0.108539699421764,0.1979267183009546,
0.2784559688242085,-0.02723965791063066,0.06265634702765752,
0.1549020715540746,0.2440506450225836,0.3251843877273637,
0.1056298518860434,0.1957006847953421,0.2838067303057802,
0.3651211825280409,0.2298299119587134,0.3160346825162738,
0.3968842416588859,0.3408204777877171,0.4204156838417109,
-0.07805410188638827,-0.09444407992200232,-0.1114341761737927,
-0.1281592432697841,-0.1435433307961642,-0.1565435248513201,
-0.1664476243728032,-0.1730570234043899,-0.1766548755042983,
0.0157271412771055,0.00421518985213093,-0.008591614873188899,
-0.02222682113317407,-0.03596894129854906,-0.0489918802882604,
-0.0605924265125066,-0.07036414931943043,0.1197931219386519,
0.1133598979509488,0.1043544464570979,0.09273871068686244,
0.07893799958180921,0.06380141477309535,0.04835884529075852,
0.2310143008479173,0.2288491935457802,0.2221994711972146,
0.2106389321639752,0.1945980336985477,0.1753190140959641,
0.3442626575810957,0.344448149200232,0.3378594888639801,
0.3240587639448084,0.3038950785717152,0.4532138881334763,
0.4531600279320766,0.4442184199518987,0.4263949183927991,
0.5518992169467315,0.5491648599857102,0.536164631289481,
0.636238087652084,0.6292447926211703,0.7047142955122331,
-0.9161616153729886,-0.9332409689531019,-0.9400448551193769,
-0.9327747060225071,-0.9086729333885725,-0.8672206083002895,
-0.8106886470978539,-0.7435546757108702,-0.671104187615456,
-0.8837679892439161,-0.8957169226742606,-0.8953622468139258,
-0.879022816612988,-0.8447970322719913,-0.7936799886395396,
-0.7295529133114078,-0.6579138707033989,-0.5841830474046977,
-0.8362110030564622,-0.8405992754866302,-0.8309565568491305,
-0.8043503638067647,-0.7603455612152211,-0.7016495768401146,
-0.6333375620907219,-0.5611246469661415,-0.771485918473268,
-0.766275808658604,-0.7462153282219795,-0.709758929805572,
-0.6582056983470901,-0.595590067087498,-0.5273136421678301,
-0.6896210625953493,-0.6739687249276908,-0.6440754938657285,
-0.6000706653666524,-0.544661671880628,-0.4823592409207763,
-0.5934057828726733,-0.5681859910978439,-0.5308212768379395,
-0.4828430686319266,-0.4275962761242672,-0.4881111164997092,
-0.4557380987684553,-0.4142857087129486,-0.3660248731570757,
-0.3801362714084162,-0.3437506203025199,-0.3015400644213536,
-0.2753204578199928,-0.2378722763394139,0.5980613131647216,
0.5540611551609296,0.4979045604542198,0.4291115157626469,
0.3489874637290572,0.2608815137134187,0.1696204410073288,
0.08026924777144263,-0.003104506871877828,0.6524878671692068,
0.6063306836302526,0.5460446037762663,0.4714063018804604,
0.3845537031663028,0.2900121666992721,0.1936208245443922,
0.1008859431994594,0.7044824728062356,0.6549957846833561,
0.589454559810383,0.5082654506345897,0.4147343369684993,
0.3146157758763655,0.2144661074447615,0.7499962909367706,
0.6957170016368869,0.6239253864871747,0.5360957563846484,
0.4368631914867457,0.3329288310787005,0.7847921789285285,
0.7244174460120194,0.6460542235032618,0.5525231471367963,
0.4495787672324474,0.805637417939517,0.7386336021807628,
0.6544795745347518,0.5572396030423862,0.8113900261915854,
0.7383768115126219,0.6502709550316551,0.8032920019996154,
0.725915395913506,0.7843092736443379,-0.4366431953633788,
-0.5190819485847166,-0.6039640604128714,-0.686785147947791,
-0.7620470421725769,-0.8245340389659808,-0.8708228680516067,
-0.9001617337332903,-0.9142381355016868,-0.4204163992491611,
-0.5047005830710198,-0.5903445107000899,-0.6720308549719619,
-0.7437914180445663,-0.8006802874293815,-0.8402926072696949,
-0.8631751150784488,-0.8720236313262308,-0.396884888208038,
-0.4811289714781835,-0.5652543720979706,-0.6434244315426998,
-0.7097591671683677,-0.7601772892083588,-0.7935642249312238,
-0.8115619523188943,-0.3651217770412689,-0.4471759195096291,
-0.5274838962988779,-0.6002019152270698,-0.6601534291553377,
-0.7044750126107846,-0.7331976694123559,-0.3251849417564136,
-0.4031031327086847,-0.4778781266280965,-0.5442129229008882,
-0.5980262207943586,-0.6376204486797759,-0.2784564800311357,
-0.3509705292257924,-0.4194890855987771,-0.4796201828812963,
-0.5284049821532861,-0.2274963530521034,-0.2942151694937769,
-0.3567023183694048,-0.4115345048612673,-0.1753850281553566,
-0.2366295712717834,-0.2938643950650254,-0.1249142906614369,
-0.1813653192898883,0.9161619708326186,0.9332413210693342,
0.9400451789678279,0.9327749805257902,0.9086731502239969,
0.8672207777405768,0.8106887957474585,0.7435548367414557,
0.6711043898508244,0.9520728550100875,0.9680084878195204,
0.9709706641436524,0.9568547607732569,0.923414887485804,
0.8715118657296428,0.8051612260268248,0.7302053387950368,
0.9795688039876239,0.9918158125836303,0.9881921235557868,
0.9648780850920352,0.9208732655385489,0.8588851060453266,
0.7845540741828551,0.9941684586829005,0.9997711640715929,
0.9870068177874959,0.9531387910864955,0.8989972043871354,
0.829085472566247,0.9920538154161512,0.9884396081113127,
0.9651307683693848,0.9211259732003716,0.8591326593451197,
0.9714466929952836,0.9573448137030386,0.9239099284934242,
0.8720020075968424,0.9334760373935599,0.9093872922332051,
0.8679349808976941,0.881888023912356,0.8497898935937275,
0.8217573530818993,0.1778171059718252,0.116063484932519,
0.04588675059291181,-0.03109104889813256,-0.111740984528746,
-0.1918125910017186,-0.266919222145987,-0.3336644772286424,
-0.3902942361971635,0.2378731920177505,0.1751982200024925,
0.103165135794194,0.0237726939459323,-0.05924605897326656,
-0.1410802144925054,-0.217121271652078,-0.2841551297870086,
-0.3408213192163667,0.3015409214864257,0.2379996307470747,
0.1642142712273472,0.08265050914794721,-0.002351577711465992,
-0.08556215486494216,-0.1623583634318567,-0.2298307519128458,
0.3660256667153609,0.3013724622732556,0.225787563312025,
0.1422988506889489,0.05578339303902819,-0.02833333511696591,
-0.1056306282458797,0.42759700108315,0.3613584700754575,
0.2839225264985345,0.1989204411880135,0.1115820483497766,
0.0272390133777002,0.4823598903354967,0.4141193140607006,
0.3350423572261403,0.2492664112715316,0.1620734932467959,
0.5273142067726671,0.4570511845454862,0.376979581956603,
0.2914860445503094,0.5611251168568853,0.4893610105925254,
0.409304623993076,0.5841834148888068,0.5118465920502688,
0.5190812242961226,0.6039634624796284,0.686784726158866,
0.7620468277893128,0.8245340313583351,0.8708230332223915,
0.9001620167170649,0.9142384783990968,0.5894211704148156,
0.6789524307604198,0.7632448457303311,0.8359266838325403,
0.891894617970833,0.9289011503005559,0.9478965192118636,
0.6583452758445511,0.749524790850048,0.8315532424890266,
0.8978881068207238,0.944448070806156,0.9707810672151929,
0.7208184417027227,0.809677174255781,0.8854287054759336,
0.9423468561715556,0.9781178066356491,0.7716444357268979,
0.854135980832467,0.9204708008966339,0.9665675908847857,
0.8070418390872103,0.8801658592323851,0.9356914498708749,
0.8258654425765057,0.8883525351377126,0.8296779096104938,
0.09444407913201958,0.1114342885457886,0.1281594836202007,
0.1435437104478973,0.1565440479837881,0.1664482855753907,
0.1730578081089095,0.176655763191492,0.1813650175735936,
0.2043807284477892,0.226758533434972,0.2468100045265798,
0.262820145857554,0.2735753518716192,0.2787599021207723,
0.2789608606213531,0.2753212552695638,0.2938639456031617,
0.3229737187957749,0.3493473093663221,0.3704627992219873,
0.3842636510528081,0.3899007538969458,0.3879754312808241,
0.380136902581416,0.4115339986401249,0.4448996490238289,
0.4726025527270443,0.4916319868779722,0.5002042468552221,
0.4984303277487671,0.4881116080953447,0.5284045295040382,
0.5629551752469137,0.5885431838636429,0.6023440210047828,
0.6035085783646522,0.5934061805946154,0.6376201472701202,
0.6697547537752425,0.6900358414869175,0.6965200475426346,
0.6896214177247305,0.7331975726799168,0.7598360876893205,
0.7728363883884936,0.7714862700692517,0.8115620579167974,
0.8309267868599184,0.8362113667997926,0.8720238939031298,
0.8837683585624158,0.2841543957726532,0.2171207121163834,
0.1410798976495498,0.0592460337919352,-0.02377241605014863,
-0.1031645846803213,-0.175197453605406,0.1623576902420928,
0.08556172001198789,0.002351438316001383,-0.08265033236073645,
-0.1642138033298737,-0.2379989318886596,0.02833279000440243,
-0.05578364441956794,-0.1422987785572308,-0.2257871853292439,
-0.301371837576038,-0.1115824064790156,-0.1989204755639271,
-0.2839222453034268,-0.3613579271786332,-0.2492665519223285,
-0.3350421794323328,-0.4141188622036356,-0.376979512041707,
-0.4570508332511692,-0.489360766920074,-0.01572700265409594,
-0.1008857021547371,-0.1936205087916404,-0.2900118132468701,
-0.3845533472228392,-0.4714059641664385,-0.5460442847763476,
-0.6063303681777003,-0.6524875344052207,-0.1197927153790677,
-0.214465606765001,-0.3146152265921756,-0.4147337903295822,
-0.5082649460772711,-0.5894541111166113,-0.65499537962445,
-0.7044820845747036,-0.2310136280273066,-0.3329280970872507,
-0.43686246029571,-0.5360950867028047,-0.6239248102620224,
-0.695716515229827,-0.749995864312011,-0.3442617649825689,
-0.4495778732913127,-0.5525223259640154,-0.6460535267660109,
-0.7244168848320439,-0.7847917261432807,-0.4532128635509181,
-0.5572386535616057,-0.654478768383796,-0.7386329688076397,
-0.805636940817698,-0.5518981667856981,-0.6502700535877015,
-0.7383761054919119,-0.811389515577244,-0.6362371067112403,
-0.7259146170102994,-0.8032914429700343,-0.7047134464025514,
-0.7843086526571425,-0.7580246814516085,-0.2789601712242363,
-0.2787593471791244,-0.2735749526850533,-0.2628199127188,
-0.2468099337172354,-0.2267586092205901,-0.2043809286570809,
-0.3879749291048343,-0.3899004091962853,-0.3842634838788619,
-0.3704628145053439,-0.349347495161076,-0.3229740508586004,
-0.498429974108997,-0.5002040604834036,-0.4916319868779722,
-0.4726027411534949,-0.4449000101574501,-0.6035083146581218,
-0.602343922563195,-0.588543271739299,-0.5629554529176811,
-0.6965198150492191,-0.690035767365203,-0.6697548637373957,
-0.7728361486877732,-0.7598360011487315,-0.8309265297968929,
-0.7302050882445748,-0.8051610414501039,-0.8715117174305623,
-0.9234147395568944,-0.9568545837269061,-0.9709704452151936,
-0.968008232338148,-0.9520725798532584,-0.7845537997567457,
-0.8588849308275506,-0.9208731569645157,-0.9648780014111388,
-0.9881920288336453,-0.9918156880829223,-0.9795686493343514,
-0.8290851961543591,-0.8989970625213397,-0.9531387450388693,
-0.987006817440241,-0.9997711657617464,-0.9941684373181741,
-0.8591323903215224,-0.9211258673075536,-0.9651307788218259,
-0.9884396774035085,-0.9920538947738091,-0.8720017371830424,
-0.9239098369784071,-0.9573448480949935,-0.9714467930697923,
-0.8679346859597882,-0.9093871792307242,-0.9334760519103793,
-0.8497895472965013,-0.8818878542954445,-0.8217569347483581,
-0.04796426561714673,0.03794103867724843,0.1297539800598756,
0.2226772328227925,0.3111481732455522,0.3903649242566535,
0.4574806142481337,-0.09689348391076305,-0.00913724963965745,
0.08420262555973922,0.177733799656962,0.265701704660737,
0.3436364458954788,-0.1478457927031966,-0.05893441045550545,
0.0349686757279841,0.1281279562907054,0.214942691058949,
-0.1979272450610679,-0.1085402471877293,-0.01500906268915838,
0.07691173856262062,-0.2440512506935033,-0.154902725197284,
-0.06265701957101971,-0.2838074100306656,-0.1957014339320081,
-0.3160354401730464,-0.9478962831266258,-0.9289010005915933,
-0.8918946048405405,-0.8359268445086131,-0.7632451895269284,
-0.6789529354540513,-0.5894217923304083,-0.5004653941257039,
-0.970780979775399,-0.9444480894583087,-0.8978882630448816,
-0.8315535470087182,-0.7495252275742876,-0.6583458081952406,
-0.5648916828872914,-0.9781178706298981,-0.942347026709516,
-0.885428988462601,-0.8096775549851075,-0.7208188890120822,
-0.6260926899993671,-0.9665677527611446,-0.9204710448766127,
-0.8541362909342279,-0.7716447840125762,-0.6796185647672793,
-0.9356916072835824,-0.8801660576917285,-0.8070420537147268,
-0.7214984744500784,-0.8883525705162149,-0.8258654786670103,
-0.7494380619781833,-0.8296777286633932,-0.7634086046890135,
-0.7653059660649493,0.6579141776573929,0.7295531777521024,
0.7936802384922247,0.8447972973738501,0.8790231171992372,
0.8953625859168114,0.8957172874110191,0.6333379663382935,
0.7016499314834187,0.7603458913147364,0.8043506945733514,
0.8309569030556652,0.8405996366357998,0.5955905567158142,
0.6582061258811204,0.7097593165624652,0.7462156952614298,
0.7662761679440523,0.5446622343557217,0.6000711505073423,
0.6440759195726991,0.6739691095309485,0.4828436947701487,
0.5308218111264984,0.5681864487641957,0.4142863939154359,
0.455738680653885,0.3437513626484632,-0.4531171355531167,
-0.3938356644953573,-0.3229916528986729,-0.2429944658048455,
-0.1581387295403868,-0.07354922969450257,0.00623625010153865,
0.07822915744532465,-0.5157871513702247,-0.4530589859436308,
-0.3775430647931653,-0.2925409610470896,-0.2032825122447724,
-0.1154290866147241,-0.0335199252992554,-0.5740676626100093,
-0.5070038470041614,-0.4265380492676018,-0.3369996244991067,
-0.244361769966899,-0.154436271103469,-0.6234116143878676,
-0.5514625314967724,-0.4664604103168303,-0.3736350915397741,
-0.2792604271482146,-0.6602907797777987,-0.5836996709958147,
-0.4954377928330375,-0.4012119230675125,-0.6833067346898886,
-0.6032350844987688,-0.5136097646306489,-0.6933729576191783,
-0.6115880145737621,-0.6929690938467825,0.8631753518491425,
0.8402927698803195,0.8006803216023103,0.7437912797965405,
0.6720305274074914,0.5903440100883541,0.504699950277095,
0.7935642870226529,0.7601772654056832,0.7097590166001092,
0.6434241301081504,0.5652539229757697,0.4811284030348103,
0.7044748595212692,0.66015319194957,0.6002015742230613,
0.5274834493042921,0.4471753838390926,0.5980258661419307,
0.5442125068737823,0.4778776501574548,0.4031026076549349,
0.4796197003718685,0.4194885812207204,0.3509700147775985,
0.356701818393901,0.2942146894919281,0.2366291626721505,
0.07036512794891495,0.06059331156828225,0.04899265284320812,
0.0359695874535567,0.02222733419962072,0.008591995504757999,
-0.004214935230486583,-0.048357793313131,-0.06380043950324864,
-0.07893711715811484,-0.09273793551230918,-0.1043537896571689,
-0.113359365885021,-0.1753179190717106,-0.1945969916350631,
-0.2106379566061765,-0.2221985793343545,-0.2288484037077831,
-0.3038939791712426,-0.3240576891045761,-0.3378584512937831,
-0.3444471709858402,-0.4263938526473902,-0.4442173491846191,
-0.4531589664405656,-0.5361636274888475,-0.5491638241821553,
-0.6292438651304321,-0.1282040992012934,-0.04435978008441287,
0.04944233877845754,0.1506070646973712,0.2546642688007949,
0.3559200448438602,0.4488272180170631,0.5294097717623608,
0.5959629108387098,0.6488215902264566,-0.1619077855794933,
-0.07454406204984147,0.02329146842828509,0.1282100848553425,
0.234790969615194,0.3366773586411712,0.4283146113627389,
0.5063384506251003,0.5698896326340842,-0.1972673366002622,
-0.1068255930288844,-0.005791503701260298,0.1015779223878756,
0.2090686111987675,0.3100671263842886,0.3994533679902369,
0.4746871659657975,-0.232615798766268,-0.1396773162324554,
-0.03655119363532085,0.07170206110196441,0.1784301917623365,
0.2772572737517244,0.3638246180723772,-0.2658039506626713,
-0.1710978759257405,-0.06718962048721892,0.04030107224694054,
0.1447607652202159,0.2404750267534745,-0.2946652126306246,
-0.1990974281683128,-0.09582172900178909,0.009369859926838612,
0.110357956539064,-0.3176184514965803,-0.222270660707132,
-0.1210148748258565,-0.01939827024983316,-0.3340739915348134,
-0.2401148801885883,-0.1420870179889694,-0.3444209939391287,
-0.2529463331304582,-0.3496821715684524,0.6714420577705413,
0.7435113472506464,0.8139336018335218,0.8777656242085762,
0.9296329303259336,0.9651729312878542,0.9824386073167399,
0.9823984726130219,0.9682596586238317,0.9441720387917811,
0.7087413879135209,0.7840892682826439,0.8556051669023013,
0.9173531285160066,0.9635713995106854,0.9905236148375803,
0.9977653075434614,0.9879747192712225,0.9655968026264566,
0.7409584518952473,0.8171173803566061,0.8865969745674289,
0.942889039924638,0.9806175261526792,0.9974611488769433,
0.9948177215231417,0.976809672217213,0.7644107780855932,
0.8381137943506111,0.9020313711806934,0.9498618317294466,
0.9774884200770568,0.984455050704485,0.9737573075945112,
0.7756818501512159,0.8435121923354123,0.8989022227634631,
0.9366307840854883,0.95437657834853,0.9533825051676448,
0.7727341579527024,0.8320450757851201,0.8774020340365609,
0.9052158359967212,0.9148948007536834,0.7557291769626011,
0.805326671094437,0.8408668603662851,0.8604026946131843,
0.7269859063883545,0.7671790270453136,0.7943722223707224,
0.690100618808278,0.7222076989157948,-0.9441722324566724,
-0.904307645384738,-0.8481757819865325,-0.773945596539063,
-0.6820112385376135,-0.5756807280718292,-0.4607792790679794,
-0.3441534701740746,-0.2318935611202809,-0.9303809621015218,
-0.8830185434308674,-0.8172030379805079,-0.7317787780884728,
-0.6286054699715032,-0.5128635622007778,-0.3918810385950385,
-0.2730236045989769,-0.9028984430498929,-0.8460642977744163,
-0.7691784804069041,-0.6724056610478215,-0.5595277701998983,
-0.4374897246213904,-0.3144118544998256,-0.8589482430980673,
-0.7911988721488439,-0.703044075433466,-0.5965101770495288,
-0.4772883218837695,-0.3533685405348139,-0.7974562734423089,
-0.7186356601273992,-0.6208045991538126,-0.507926737136379,
-0.3869469856202812,-0.7199870192241779,-0.6317037484916127,
-0.5275199172214167,-0.4127886377572592,-0.6307845637432554,
-0.5361873333707976,-0.4298568952019761,-0.5356827691130239,
-0.4385943873688064,-0.4404800743875191,-0.3130828685601688,
-0.2158144102235012,-0.1048477339184343,0.01737679733452727,
0.145995491636905,0.2742909798999176,0.3952347219739472,
0.503291831296798,0.595502090315309,-0.3099520106140219,
-0.2053757769283784,-0.08650347275041102,0.04302105714473008,
0.1768577004771411,0.3071581921441303,0.4266784695958356,
0.5306275177659158,0.6172668313578871,-0.302423711672288,
-0.1907069702272193,-0.06489577644534418,0.0699408153488305,
0.2061362196609274,0.3353108895502397,0.4507704673548409,
0.5489716751760349,-0.2895250242862085,-0.1715150632893158,
-0.04067912706104116,0.09654302677976182,0.2317116972020255,
0.3567592436499814,0.4661908578614318,-0.2708185619737357,
-0.1481961478813345,-0.01510368122142407,0.1210917442402347,
0.2520105777387078,0.3706589640013763,-0.2467266437111619,
-0.1219141274081689,0.01025701144397722,0.142223084729963,
0.2664554400639934,-0.2185691140597738,-0.09433919811625824,
0.03395634318261122,0.1592889611288683,-0.1882244284110535,
-0.06716551971534636,0.055031530590314,-0.1575991801780021,
-0.0416967436508152,-0.671442351589465,-0.7435115240281642,
-0.8139336689380561,-0.8777656078901646,-0.9296328738783285,
-0.9651728842355707,-0.9824386099053611,-0.982398544792382,
-0.9682597992070626,-0.673525768984227,-0.7468180740978238,
-0.8166237491391959,-0.8772252002603724,-0.9230382082945876,
-0.9503956493652942,-0.9587838051377746,-0.9507033782544355,
-0.6670475871543912,-0.7391545962936478,-0.8055307765029669,
-0.860125367790516,-0.8978538005513599,-0.9163947908554175,
-0.9168546729772998,-0.649602216294724,-0.7177302448625567,
-0.7778859526921634,-0.8243817913354027,-0.853342815897189,
-0.8640711446818524,-0.6197562179675709,-0.6813798175903147,
-0.733374932687383,-0.7711033603736286,-0.7922438176365504,
-0.5778269971598609,-0.6314056112449312,-0.6747362861851252,
-0.7045760418412901,-0.5261115978506249,-0.571437749107807,
-0.6069777467397017,-0.4682968578205298,-0.5062792722326205,
-0.4083732040408349,-0.6488222902967828,-0.6479137619538795,
-0.6384433779259612,-0.6181925269683732,-0.5859405951200543,
-0.5421896843793962,-0.4893366483035593,-0.4310576147663105,
-0.3712412833748336,-0.722208134089623,-0.7225295469502088,
-0.7119299887749709,-0.6878297181787101,-0.6492831334094801,
-0.5977545202455957,-0.5369263387902474,-0.4715400964562942,
-0.4060110053588667,-0.7943724032793758,-0.7941684890748284,
-0.780287498377037,-0.7501802425240992,-0.7037353198781235,
-0.6438103021069973,-0.5754139215508255,-0.5040323183695714,
-0.8604026705465683,-0.8571439110045493,-0.8374826979355753,
-0.7995410210009178,-0.744592852017412,-0.6769935095953296,
-0.6026908960383707,-0.9148946566640305,-0.9058191273231,
-0.8783402703714518,-0.831895347992814,-0.7693419318067468,
-0.6961400902573952,-0.9533823404746037,-0.9363830473278872,
-0.9003464103777271,-0.846307850369865,-0.7783786922776838,
-0.9737572051250643,-0.9481191644195498,-0.904368254349328,
-0.8449013283633929,-0.9768096756732072,-0.9433249035584995,
-0.8938553761971309,-0.9655969141863968,-0.9260722794540685,
0.3130823317650696,0.2158137676495382,0.1048470017130739,
-0.01737758434298081,-0.1459962827220426,-0.2742917196047844,
-0.3952353653550799,-0.5032923546149073,-0.5955024919545937,
0.2536926972719504,0.1458327290767235,0.02422841952626041,
-0.1071275628186857,-0.241611507146674,-0.3712645460380625,
-0.4889532492383237,-0.5901702171834956,0.1843472992213911,
0.06615765451161945,-0.06461113970496464,-0.2021592879969449,
-0.338354586304306,-0.4648175094943233,-0.575319351774491,
0.1061130743462423,-0.02080286326993523,-0.1576482143840719,
-0.2970021727032601,-0.4300387818650189,-0.549076707052971,
0.0217206853443193,-0.1108168656978456,-0.2493324402368818,
-0.3855277139058982,-0.5110231660272195,-0.06464549315404491,
-0.1986151347691201,-0.3340228839844541,-0.4627520281251212,
-0.1482539922220807,-0.2793070464170456,-0.4076024215152396,
-0.2250412157123533,-0.3496313063989884,-0.2924709198142461,
0.1282040764044601,0.04435966353085222,-0.04944259604098935,
-0.1506074987015245,-0.2546648874595455,-0.3559208170725224,
-0.4488280788164576,-0.5294106421507812,-0.5959637203467131,
0.04169673907303984,-0.0526834259769666,-0.1563566027108192,
-0.2651887425550946,-0.3731530321841731,-0.4736563198547184,
-0.5613802828138158,-0.6335666007603626,-0.690101357380803,
-0.05503152918262894,-0.1593042550239766,-0.2709316440867437,
-0.3840952777948459,-0.4915861222634885,-0.5867907021484375,
-0.6655838183420531,-0.7269866926442972,-0.159288972427813,
-0.2712574169662021,-0.3872244295124012,-0.5000332157715695,
-0.6022061061584294,-0.6881925170266414,-0.7557300072673857,
-0.2664554858018714,-0.3823479651751564,-0.4978444298202386,
-0.6053352646595813,-0.6982069960901036,-0.7727350088749903,
-0.3706590624880138,-0.4857936740008229,-0.5959856542636139,
-0.6942612161795336,-0.7756826781990721,-0.4661910177108468,
-0.5761185565808596,-0.6773744620468557,-0.7644115292814133,
-0.5489718931615636,-0.6504766905631515,-0.7409590768696484,
-0.6172670952623341,-0.7087418537741278,0.6479131208665134,
0.6384428093318625,0.6181920323103047,0.5859401592476801,
0.5421892777726929,0.4893362367199527,0.4310571708515276,
0.3712407933301676,0.5613207863628051,0.5433246784685077,
0.5142659275004758,0.4739667199004282,0.4241908010905809,
0.3683211596170611,0.3103315078005186,0.4569583774922522,
0.4296550077229934,0.3922062664218491,0.345761387535644,
0.293177934819726,0.2382039928591278,0.3364534206151339,
0.3005219256748686,0.2568082513095248,0.2076321770193636,
0.1563031965788156,0.2045546517133144,0.1623927536580789,
0.1159478851139529,0.06807760796624844,0.0685659565224499,
0.02376600432590625,-0.02150913216682495,-0.06350995748665327,
-0.1072608130272718,-0.1851326652875042,0.9043074523981195,
0.8481756214456443,0.7739454978673308,0.6820112173362239,
0.5756807770328707,0.4607793683387657,0.3441535580133543,
0.2318936078193602,0.926072164038092,0.8784582627879883,
0.8124335550546075,0.7268690803364112,0.6236462465254911,
0.5079539512218285,0.3871116910406285,0.2684634496083129,
0.1575990472160092,0.8938553783036348,0.8365254960181361,
0.7592600076242926,0.6622795368519036,0.5494016575639665,
0.4275712710943025,0.3048730417540333,0.1882241880032878,
0.8449014608184471,0.7764699938313133,0.6878549375110379,
0.5811577408091089,0.4620991215146014,0.3386395224598848,
0.2185687785328751,0.7783789236415784,0.6987988931237948,
0.6005524285298199,0.4876744928391774,0.3671099975843117,
0.2467262336464146,0.6961403422326237,0.6071556637949365,
0.5027238349931351,0.3882403289629487,0.2708181010489455,
0.602691063692116,0.5075711336386517,0.4012405518966602,
0.2895245326714229,0.5040323033369615,0.4066733092394736,
0.3024232018417092,0.4060107420397416,0.3099514873609258,
0.6335657588222857,0.5613794019471703,0.4736554861193561,
0.3731523315866652,0.2651882329560032,0.1563562968227162,
0.05268329572084096,0.665582947801096,0.5867898301880646,
0.4915853474795021,0.3840946840958189,0.2709312717864595,
0.159304093053227,0.6881916390051439,0.6022052797777839,
0.500032542833593,0.387223979093218,0.2712572035078997,
0.6982061514387302,0.6053345332894541,0.4978439026516569,
0.3823476853537574,0.694260458246256,0.5959850669993192,
0.4857933245168793,0.6773738416456014,0.5761181477179906,
0.6504762420694124,0.9303807852901133,0.9507032776506229,
0.9587837990451511,0.9503957355401843,0.9230383566605702,
0.8772253580218827,0.8166238578878361,0.7468180882094819,
0.6735256647351061,0.90289835288087,0.9168546892221431,
0.9163949287729053,0.8978540461202875,0.860125673826823,
0.8055310756657073,0.7391548242370243,0.6670477005822436,
0.8589483198537152,0.8640713573235344,0.8533431666375708,
0.8243822455102904,0.7778864433741867,0.7177306948097215,
0.6496025629973337,0.7974565860481383,0.7922442814347184,
0.7711039549446601,0.7333755999307914,0.6813804770418425,
0.6197567932818368,0.7199875994402858,0.704576762533665,
0.6747371020412667,0.6314064480391776,0.5778277738330908,
0.6307853921801013,0.6069786776259655,0.5714387199953477,
0.5261125320735169,0.5356837831672402,0.5062803340418997,
0.4682979008420118,0.4404811918375181,0.4083743128719785,
0.3496833143594963,-0.2684635055945434,-0.3871116949027418,
-0.5079539380311434,-0.6236462513912529,-0.7268691253470475,
-0.8124336419036672,-0.8784583757439789,-0.3048731870534707,
-0.4275713388616055,-0.5494016757834509,-0.6622795348064975,
-0.7592600049270052,-0.8365254973182974,-0.3386397327605397,
-0.4620992154744972,-0.5811577408091089,-0.6878548720792258,
-0.7764698875810475,-0.3671102436707482,-0.487674577809656,
-0.6005523742168883,-0.6987987332107705,-0.3882405864046344,
-0.5027238913366621,-0.6071555453420947,-0.4012408083880579,
-0.5075711618348809,-0.4066735651215305,0.590170014682346,
0.4889529277025601,0.3712641002824293,0.2416109555838913,
0.1071269463449765,-0.02422904936538466,-0.1458333255362707,
-0.2536932284372023,0.575319376406684,0.4648174146687293,
0.3383543572464268,0.2021589358241457,0.06461070043643219,
-0.06615813268612159,-0.1843477715691807,0.5490769699623794,
0.4300389185128004,0.2970021583546204,0.157648053896879,
0.02080258943368662,-0.1061134148983228,0.5110236542957048,
0.3855280620563327,0.2493326170112359,0.110816873466397,
-0.02172081454080515,0.4627527059506328,0.3340234043580559,
0.1986154658537707,0.06464563879740347,0.4076032405543511,
0.2793076930534321,0.1482544392795429,0.3496322190693472,
0.2250419477534466,0.2924718882891986,-0.9879747859642711,
-0.9977653310206788,-0.990523615974921,-0.9635714188487002,
-0.9173532159549495,-0.85560536501624,-0.7840895998008963,
-0.994817702995987,-0.997461134800403,-0.9806175623759372,
-0.9428891811827549,-0.886597265826606,-0.8171178418357974,
-0.9844549713337977,-0.9774884174060016,-0.9498619694604108,
-0.9020317021121872,-0.8381143412526206,-0.9543765048804849,
-0.9366308742795815,-0.8989025406729466,-0.8435127700618501,
-0.9052158630007405,-0.8774023054284241,-0.8320456365430426,
-0.8408670789696687,-0.805327187943167,-0.7671794966406347,
-0.3103320171372975,-0.3683216507471385,-0.4241912872571255,
-0.4739672217049487,-0.5142664654627133,-0.5433252645626975,
-0.5613214202090539,-0.5698903038330552,-0.2382044630883786,
-0.2931784077953506,-0.3457618730212876,-0.3922067754962655,
-0.4296555471996706,-0.4569589463091218,-0.4746877559159965,
-0.1563035449296971,-0.2076325381624787,-0.2568086311939766,
-0.300522327960348,-0.336453843995229,-0.3638250562458944,
-0.06807774532319075,-0.1159480367576914,-0.1623929246512774,
-0.2045548436199081,-0.2404752368196474,0.02150927301351948,
-0.02376587784419006,-0.06856585200941642,-0.1103578775111495,
0.1072612554376189,0.06351038126206604,0.0193986644095893,
0.1851333868984673,0.142087712340153,0.2529472816242414,
-0.5306278899290351,-0.4266789610910172,-0.3071587951012373,
-0.1768583830726642,-0.0430217688399398,0.08650278658817297,
0.2053751597977648,-0.4507707926372612,-0.3353113300288001,
-0.2061367616665949,-0.06994142151255993,0.06489515773394869,
0.1907063885440197,-0.3567595103770218,-0.231712075682342,
-0.09654349885714854,0.04067860126609572,0.171514533036228,
-0.2520107854074638,-0.1210920629807046,0.01510327295162653,
0.1481956904535304,-0.1422232452547296,-0.01025728491155416,
0.1219137656087612,-0.03395647625215152,0.09433895004400768,
0.06716539409874363,-0.5063391876138633,-0.4283153498076878,
-0.3366780195432001,-0.2347914812056201,-0.1282104074092338,
-0.0232916058381637,0.07454407090624685,0.1619078867980062,
-0.3994539622273614,-0.310067650345868,-0.2090689910564566,
-0.101578111712534,0.005791506035575475,0.1068257468493955,
0.1972675814170221,-0.2772576433388097,-0.1784304214682155,
-0.07170210104888376,0.0365513498207285,0.1396776293169983,
0.2326162031595532,-0.1447608377351292,-0.04030095729466294,
0.06718993398467658,0.1710983522944223,0.2658045221403088,
-0.009369596982657442,0.09582219059763358,0.1990980586833061,
0.2946659462714916,0.1210154650283388,0.2222714245712332,
0.3176193294845107,0.2401157501920485,0.3340749869695284,
0.3444220768905359,0.4715398981500615,0.5369261966393798,
0.5977544079195963,0.6492830104914913,0.6878295422870739,
0.7119297300805439,0.7225291958412279,0.5754139764385705,
0.6438104077520811,0.703735439041779,0.7501803284162304,
0.7802875102236209,0.7941684049065568,0.6769937335137454,
0.7445931056463463,0.7995412648414352,0.8374828910500066,
0.8571440245657689,0.7693422116354997,0.8318956310273866,
0.8783405275925528,0.9058193343789728,0.8463080799206776,
0.900346626617332,0.936383240514816,0.9043683688324304,
0.948119268339247,0.9433248910510675,0.2730237834281818,
0.3918812540743772,0.512863760525918,0.6286055997510109,
0.7317788088844818,0.817202970027369,0.883018402482024,
0.3144121837974857,0.4374900830135051,0.559528090412838,
0.6724058856901879,0.7691785827023693,0.8460642869454081,
0.3533690330364157,0.4772888327771027,0.5965106290979496,
0.7030444104060292,0.7911990697093608,0.3869476434981415,
0.5079274002472546,0.6208051861357136,0.718636116718038,
0.4127894497989522,0.5275207205127158,0.631704463913464,
0.4298578384111184,0.536188255170367,0.4385954324163403 };
auto pointshell
= new vnl_matrix_fixed<double, 3, 812>(coords);
return pointshell;
}
};
template<> class PointShell<1002, vnl_matrix_fixed<double, 3, 1002> >
{
public:
static vnl_matrix_fixed<double, 3, 1002>* DistributePointShell()
{
double coords[3*1002] = {
0.9756767549555488,0.9910244201339067,0.9977154378498742,
0.9927800993607139,0.9738192119472443,0.9397937974509784,
0.8915721200771204,0.8318778673129345,0.7646073555341725,
0.693869346809198,0.6231965669156312,0.9833704607135893,
0.9964241736681655,0.9989802553190876,0.987902775761947,
0.9610864540427623,0.9183225885811028,0.8616492668438125,
0.7948923552800862,0.7226196323725681,0.6490709211350905,
0.9817040172417226,0.9905693687720445,0.9870396762453547,
0.9681598062324672,0.9325589150767597,0.881205326354676,
0.8173592116492303,0.7456638277324369,0.6708930871960926,
0.9679134019101711,0.9705588332310378,0.959200825309353,
0.9315264271335991,0.8872988802116832,0.8287690756632178,
0.7601362175694236,0.6863342915062906,0.9399233672993689,
0.934650496070032,0.9144882783890762,0.8781852416959071,
0.8267930935417315,0.7635949206829796,0.6931818659696647,
0.8971014254962764,0.8830745457598012,0.8543282347786828,
0.8108509720355672,0.754782849204541,0.6899186612252973,
0.8407280774774689,0.8182890571891552,0.782394344826989,
0.7341199823031558,0.6762337155773353,0.7738549713477869,
0.7444263912611687,0.7036087793266443,0.6531781708866408,
0.7005607434301688,0.6661985543964391,0.6228579759074076,
0.6249824933683414,0.5878380796842572,0.5505632701289798,
0.4375940376503738,0.3812939184075813,0.3153040621970065,
0.2399906033000567,0.1569517536476641,0.06907711216819173,
-0.01984099037382634,-0.1058738447453135,-0.1857690950088067,
-0.2574501777461976,-0.3200730131503601,0.4806956770236153,
0.4221182950629059,0.3527542025586833,0.2732412963568581,
0.1857299193159225,0.09380763985613347,0.001855404825389049,
-0.08593912303271299,-0.1664330628904374,-0.2378914640002027,
0.5232435944036425,0.4619857831524665,0.3889403678268736,
0.305177254463085,0.2135250052622625,0.1182658918935892,
0.02420694871807206,-0.06444621903648747,-0.1448539951504302,
0.5629325029626137,0.4984853033494325,0.4215263456365218,
0.3337322884960374,0.2386638182445053,0.1411593054699449,
0.04617547921974115,-0.04233031957129997,0.5971534158422009,
0.5290500940108692,0.4482053228282282,0.3570208135159443,
0.2597018771197477,0.1613609902081595,0.06677517278138323,
0.6235168560971456,0.5515679242489461,0.4673132571654228,
0.3738575901923395,0.2758011201251887,0.1781713819192711,
0.6404616222418184,0.5649656062523414,0.4782876117785159,
0.3840417218310146,0.2868761951248767,0.6476575150457713,
0.5694506961858633,0.481712063543859,0.388259258354853,
0.6459894362878276,0.566293293292668,0.4789651252338281,
0.6371661773752719,0.5573232120043787,0.3200724178002418,
0.4063802566221164,0.4973180497018747,0.5897273522875156,
0.6793811951363423,0.7616224484252742,0.8323587928990375,
0.889001584581435,0.9308933612987835,0.9590813334864968,
0.3615817483188572,0.4535168742898277,0.5491779429163389,
0.64449992308253,0.7344437631005388,0.8139835008962493,
0.8793283338489147,0.9287763706314454,0.9627864725173401,
0.4036036036586492,0.499949320334643,0.5984781165037405,
0.6942590478190055,0.7817280923310203,0.8559922020830166,
0.9140795130247613,0.9554674311422222,0.4441835036049274,
0.5429866860840018,0.6418227066741695,0.7351609508563529,
0.8174230627001258,0.8844224346157006,0.9343673632346869,
0.4809905907165384,0.5797158369815773,0.6759621154318279,
0.7640818148143264,0.8390728924802671,0.897874775015538,
0.5117469206751248,0.6076796078041039,0.6986831899155831,
0.7795497616193484,0.8462988042859838,0.5347729120192694,
0.6255452713743446,0.7094340284155564,0.7820975288082114,
0.5493993272212266,0.633404689923654,0.7093243648499448,
0.5560356639783846,0.6325607438661257,0.5558948726075613,
0.2502538949373057,0.2834596649308375,0.3171352000240629,
0.3497321770767574,0.3793963897789465,0.4043068999720242,
0.4231100429674418,0.4352503773152589,0.4410301813437042,
0.4413950384816501,0.3401627625801983,0.3789979847088327,
0.4171897539368579,0.4525063773118708,0.4825397797856335,
0.5052684266816663,0.5196090830694199,0.5256607773912181,
0.5245227828309349,0.5178400854028183,0.4357529867703999,
0.479500221024681,0.5208717223808415,0.5569598687552583,
0.5850086433327374,0.6031754713474787,0.611055499882272,
0.6096654752354952,0.6009463532173235,0.5339523560360242,
0.5809954188619362,0.6233304915365264,0.6575940739282847,
0.6811006607903708,0.6926539121832439,0.6928333109300957,
0.6836092937706954,0.6305067000562991,0.6783846661286849,
0.7188806066405239,0.7486166997908829,0.7654898954879897,
0.7692993175005894,0.7616477696596397,0.7205836671095895,
0.7663950141411601,0.8022874547238388,0.8253952737866894,
0.8345810205360885,0.8306996157029517,0.7997756996573342,
0.8408319454787708,0.8700831379830764,0.8855671363619817,
0.8872031228985237,0.8650978792558638,0.8995240516802058,
0.921218286608597,0.9292366279325103,0.9155019734809123,
0.9425022788739567,0.9568003701205341,0.951723763021908,
0.9714657198391669,-0.4375932291383153,-0.3812932275173999,
-0.3153035222278598,-0.2399902437364576,-0.1569515927579475,
-0.06907715072573904,0.0198407706589918,0.1058734766109667,
0.1857686171195431,0.257449626507278,-0.3570040493097855,
-0.2918648787974354,-0.2168311251285635,-0.1330995445648626,
-0.04332608784719146,0.04859599442048472,0.1382857743932946,
0.2218613031927873,0.2966853245585511,-0.2644927501381796,
-0.1901399993818987,-0.1064219080255857,-0.01561852722247663,
0.07849995612144045,0.1712924506084217,0.2583107784678281,
0.3362909838861173,-0.1610782390926968,-0.0780603807507026,
0.01281177251559359,0.1081011253085713,0.2031694108248999,
0.2931782765634202,0.3742486038435638,-0.04938676750055992,
0.04056537812597379,0.1358448755096817,0.232090324110116,
0.3243479900672576,0.4082538491780348,0.06640211724156458,
0.1604512568352431,0.2565833049862117,0.3500388266409877,
0.436217636937124,0.1811879481039926,0.2758835926122972,
0.3692668145365748,0.4568072375603044,0.2900013554556395,
0.3820078910424991,0.4697464271137876,0.3890115016151001,
0.4757292848583335,0.4760519631420977,-0.6231952788307174,
-0.5646794654796425,-0.4943551945928708,-0.4121616924667699,
-0.319458133528771,-0.2192092047974507,-0.1156489798772063,
-0.01344431006605927,0.08328895892415776,0.1716736688754058,
-0.5573220717056252,-0.4899613221250736,-0.4101426439397438,
-0.3185871044669488,-0.2177607050610849,-0.1117914195951733,
-0.005729665044898873,0.09558913699521315,0.1885288856066103,
0.2710751964644532,-0.4789641985801549,-0.402057686424166,
-0.3127252940830145,-0.2127814923512051,-0.1059392282183739,
0.002692533596869102,0.1077444781964869,0.2048204657664428,
0.2912280153186658,-0.3882586050506625,-0.3019152874380811,
-0.2041697091828281,-0.09809683500613878,0.01149943312218195,
0.1190413522149791,0.2195138260022026,0.3094968646292108,
-0.2868758523956744,-0.1923492526670043,-0.08856892011805101,
0.02025987059937257,0.1287405357080231,0.2315279747463358,
0.3245517154572714,-0.1781713502362079,-0.07790941981152795,
0.02852799618806018,0.136265045008317,0.2399985475821452,
0.3352293490184233,-0.06677541204276306,0.035950103618558,
0.1413542883070481,0.2445218382684434,0.3408430926744944,
0.04232987969953258,0.1440992946503647,0.2452457212250337,
0.3413681152295799,0.1448534358763926,0.2427634183836315,
0.3374016489097037,0.2378908589603879,0.3299350928268919,
-0.2502532651867688,-0.2834590071461157,-0.3171345072414974,
-0.3497314427767591,-0.3793956104585266,-0.4043060780204903,
-0.4231091882680272,-0.43524950627169,-0.4410293135613324,
-0.4413941927799012,-0.1793269230918291,-0.2096296374650262,
-0.2404488793458187,-0.2702796532141552,-0.2973713527283103,
-0.3200999575733405,-0.3373822412281449,-0.3489197313348205,
-0.3551542383465527,-0.09929959410007272,-0.1260192341590947,
-0.1535127609134815,-0.1804461251889914,-0.2052877394623771,
-0.2266616403246165,-0.2436963810571767,-0.2561842894548281,
-0.01142151773467507,-0.034316887225212,-0.05856032689489409,
-0.08307746147223684,-0.1065840014642066,-0.1278836167145054,
-0.1461545898453977,0.08175409117371149,0.06228642306456245,
0.04056025153798869,0.01740518175433122,-0.006048944565669369,
-0.02862806146519492,0.1765178736510397,0.1594436875323896,
0.1389956691289133,0.1158878972138483,0.09125781311736192,
0.2686152102237028,0.2525244737680689,0.2319923070602857,
0.2077893717181683,0.3541399826172473,0.3376577748776239,
0.3159635830269856,0.430309819720559,0.4124399032037845,
0.4957938830064738,-0.975676581463901,-0.9910243213530433,
-0.9977153903038788,-0.9927800571163499,-0.9738191090293654,
-0.9397935597648752,-0.8915716840571059,-0.8318771966689975,
-0.7646064477130079,-0.6938682276631534,-0.9714655004610564,
-0.983887723902267,-0.9858981447798461,-0.9744145976009966,
-0.9473804480134012,-0.9046164166427493,-0.8481606115014303,
-0.7818095106057968,-0.7100822624036758,-0.6371649246085965,
-0.9568001079664734,-0.9644051676944579,-0.9598482725023617,
-0.9402907381732713,-0.9044523389503778,-0.8533359449908623,
-0.7901672201648241,-0.7194988284538555,-0.6459882395962464,
-0.9292363237529666,-0.9300944286029187,-0.9173973041924147,
-0.8890014167596085,-0.844773720173384,-0.7869651249304563,
-0.7196711542084638,-0.6476563908917461,-0.8872027729137049,
-0.8798270414245473,-0.8582754834679532,-0.8214852287823353,
-0.7705800268610806,-0.7087709559526547,-0.6404605781008121,
-0.8306992108488226,-0.8145452502402749,-0.7846557072154475,
-0.7411783184941589,-0.6862531911113832,-0.6235158879179116,
-0.7616472974254324,-0.73736034048619,-0.7008201753656432,
-0.6531910402117445,-0.5971525097007422,-0.6836087421746132,
-0.652851924507533,-0.612034208511092,-0.5629316404694558,
-0.6009457148226922,-0.5659076360456838,-0.5232427588825813,
-0.5178393593330568,-0.4806948574024101,0.5646808729466086,
0.4943566966479628,0.4121632456350594,0.3194596781650836,
0.21921067448898,0.1156503154178581,0.013445471844618,
-0.0832879858164388,-0.1716728777368211,0.5865775784632071,
0.5109645672417243,0.4225383974740667,0.323390011818691,
0.2174206286797427,0.1096806787773226,0.005232361633134523,
-0.09191315247018395,0.6036999320472409,0.5222841738261358,
0.4275626351684279,0.3225497922064885,0.2120884454656291,
0.1018140973507329,-0.003178626653090429,0.6137659240175044,
0.5263406106031267,0.4258274919194899,0.3162311593161161,
0.2031293654582096,0.09233653282973062,0.6148617703985678,
0.5217885230992481,0.4167137837086616,0.3044789836562512,
0.190984387847104,0.6060496757760786,0.5084224141934828,
0.4006853449688581,0.2881416501332511,0.5877496225758772,
0.4873191346491355,0.3791778875849738,0.5616447830131567,
0.460498372897877,0.5301563765120954,-0.4063806941036804,
-0.4973183240635209,-0.5897274724251101,-0.6793811856410323,
-0.7616223457476226,-0.8323586364840968,-0.8890014069516364,
-0.9308931819742911,-0.9590811587055613,-0.3299355917757612,
-0.4201916721510849,-0.5144019383498233,-0.6086443620415749,
-0.6980092714824531,-0.7775489279696631,-0.8434725272922868,
-0.8939999530932097,-0.9294606883512702,-0.9517235558231533,
-0.3374020539278631,-0.4303972015599547,-0.5261951664998159,
-0.6201746406216091,-0.7070125356849136,-0.7819076179156583,
-0.8417962075837926,-0.8859147779324957,-0.9155017573317124,
-0.3413684282280401,-0.4354200733480757,-0.5306961815651272,
-0.6221165659419365,-0.7043785843697545,-0.7732956289121359,
-0.8268002829198581,-0.8650976752328781,-0.3408433114184408,
-0.4339783095259441,-0.5265312606271311,-0.6133559560669121,
-0.6896418460594331,-0.752136864699832,-0.7997755164970677,
-0.3352294641675141,-0.4255076064827776,-0.5134721858345982,
-0.594338662260662,-0.6641265172984932,-0.7205834943870382,
-0.3245517106425898,-0.4104116666038574,-0.4925847482169691,
-0.5669637398252093,-0.6305065080228541,-0.3094967204309826,
-0.3899712787954628,-0.4658908667926167,-0.5339521035735905,
-0.2912277152063287,-0.3659561925975448,-0.4357526334612896,
-0.2710747314715586,-0.3401622786069621,0.7100833249889532,
0.78181034476627,0.8481612032420389,0.9046167870637368,
0.9473806530146282,0.9744147135590244,0.9858982469324079,
0.9838878689052019,0.7194998173208004,0.7901679726328494,
0.8533364642620689,0.9044526665335126,0.9402909454666769,
0.9598484396937114,0.9644053616541416,0.7196720611840924,
0.7869658012318539,0.8447741887331299,0.8890017361264828,
0.9173975522215362,0.930094678876582,0.7087717858204172,
0.7705806468939737,0.8214856791906156,0.858275831469383,
0.8798273607029399,0.6862539610403643,0.741178910976439,
0.7846561726417634,0.8145456545188131,0.6531917738872118,
0.7008207681995118,0.7373608444418822,0.6120349280184139,
0.6528525365910808,0.5659083559960189,-0.3615822177172413,
-0.2966857537063793,-0.22186166029524,-0.1382860190443388,
-0.04859608414266816,0.04332618727116257,0.1330998494814693,
0.2168316303130393,0.2918655611474421,0.3570048758530226,
-0.4036039458806759,-0.3362912903737734,-0.2583110138480089,
-0.1712925696560921,-0.0784999126587471,0.01561876770079114,
0.1064223584250461,0.1901406492265948,0.264493571710179,
-0.4441837318029271,-0.3742488010631976,-0.2931784021968726,
-0.2031694140087586,-0.1081009568659323,-0.01281139938873339,
0.07806096659640296,0.1610790216932629,-0.4809907334514471,
-0.4082539641847306,-0.3243480295764106,-0.2320902314782855,
-0.1358446002697818,-0.04056489081311081,0.04938746901646566,
-0.5117470172320779,-0.4362177044221099,-0.3500388090292672,
-0.2565831412886956,-0.1604508981073868,-0.06640153973221416,
-0.5347730026038946,-0.4568072901222747,-0.3692667658371347,
-0.2758833806070636,-0.1811875286592425,-0.5493994424693911,
-0.4697464869291438,-0.3820078284652705,-0.2900011116348868,
-0.5560358190148772,-0.4757293607590583,-0.3890114324926668,
-0.5558950675560154,-0.4760520530085997,-0.5505634949474449,
0.9294608819831129,0.8940001336574592,0.8434726858300888,
0.7775490434174117,0.6980093127768466,0.6086442955222793,
0.5144017370522948,0.4201913220833389,0.8859149609435977,
0.8417963565884857,0.7819077242323556,0.7070125813068046,
0.6201746011540189,0.5261950179989611,0.4303969275523253,
0.8268004336113636,0.7732957269571541,0.7043786253344242,
0.622116538987203,0.5306960716781189,0.4354198662954997,
0.7521369798040806,0.6896418985458221,0.6133559483764451,
0.5265311900255359,0.4339781689134173,0.664126617868866,
0.5943387021482599,0.5134721735844615,0.4255075445403705,
0.5669638671854947,0.4925848265160583,0.4104117066697837,
0.4658910697532281,0.3899714480143811,0.3659565132385014,
0.3551551111068512,0.3489206356503204,0.3373831583083507,
0.3201008675109025,0.2973722384562898,0.2702805035644438,
0.2404496897688697,0.2096304085552757,0.1793276582557128,
0.2561851603269178,0.2436972866599269,0.2266625621335284,
0.2052886581368649,0.1804470242976833,0.153513629451971,
0.1260200668693211,0.09930039009433847,0.1461554161525869,
0.1278844724735265,0.1065848698133528,0.08307832599156778,
0.05856117448713494,0.03431770949468276,0.01142231063250637,
0.02862879196054897,0.006049691633511915,-0.01740443052828812,
-0.04055950638179381,-0.06228569088648633,-0.08175337578691833,
-0.09125722755264572,-0.1158873114023829,-0.1389950879223139,
-0.1594431124986218,-0.176517304179968,-0.2077889659882155,
-0.2319919155781195,-0.2525240921328624,-0.2686148310916902,
-0.3159633704917529,-0.3376575857943411,-0.3541398039589991,
-0.4124398762523879,-0.430309819678344,-0.4957940195469321,
0.1664325418685087,0.08593872296651928,-0.001855644740443331,
-0.09380768650859528,-0.1857297549973136,-0.2732409243006708,
-0.3527536454451026,-0.4221175876781037,0.06444579340302205,
-0.02420720081803753,-0.1182659371646478,-0.2135248270679241,
-0.3051768592760364,-0.3889397838050994,-0.4619850515450297,
-0.04617573152762199,-0.1411593366285305,-0.238663612601281,
-0.3337318558644699,-0.4215257202593218,-0.4984845341024346,
-0.1613609945604779,-0.2597016312374675,-0.3570203295626905,
-0.4482046405142344,-0.529049270280373,-0.2758008261967574,
-0.3738570466287534,-0.467312506887279,-0.5515670310282831,
-0.3840411190982298,-0.4782867918076852,-0.5649646363950814,
-0.4817111823705308,-0.5694496536902212,-0.5662921921093249,
0.0919140401962618,-0.005231313174239269,-0.1096794790522038,
-0.2174193094193431,-0.3233886246408304,-0.4225370035538252,
-0.510963223483816,-0.5865763269261466,-0.6490697854071827,
0.003179550365269548,-0.1018130528605821,-0.2120873052250725,
-0.322548598821141,-0.4275614411441423,-0.5222830294256716,
-0.6036988748207749,-0.6708921376896406,-0.09233565318963641,
-0.2031284196976215,-0.316230181653878,-0.4258265246770868,
-0.5263396945379846,-0.6137650892643368,-0.6863335534851791,
-0.190983636619622,-0.304478224282928,-0.4167130490396238,
-0.5217878437313506,-0.6148611676086653,-0.6931813485878851,
-0.2881410938833685,-0.4006848272509508,-0.5084219568812576,
-0.6060492919686921,-0.68991835321825,-0.3791775567551729,
-0.4873188675145023,-0.5877494261961844,-0.6762335873429084,
-0.4604982573084285,-0.5616447337445059,-0.653178182658568,
-0.5301564355851682,-0.6228580878699612,-0.5878382593304642,
-0.5245220270255621,-0.5256600112160642,-0.5196083293421272,
-0.5052677071807448,-0.4825391100490625,-0.4525057633827704,
-0.4171891927640138,-0.3789974674618629,-0.6096648147710031,
-0.6110548409057,-0.6031748400009704,-0.5850080622199078,
-0.5569593510286511,-0.5208712693637837,-0.4794998244238688,
-0.6928327439316474,-0.6926533571029836,-0.6811001461047985,
-0.6575936218265264,-0.6233301120657577,-0.5809951090033914,
-0.769298834842142,-0.7654894328832393,-0.7486162870521085,
-0.7188802647693375,-0.6783844022430058,-0.8345806089171193,
-0.8253948883356401,-0.8022871256496356,-0.766394760848657,
-0.8855667831280848,-0.8700828159137221,-0.840831684134326,
-0.9212179835682319,-0.8995237842791114,-0.9425020232333647,
-0.7226186971374691,-0.794891657666899,-0.8616488184692596,
-0.9183223647655301,-0.9610863946187903,-0.9879028002301763,
-0.9989802852434637,-0.9964241505078985,-0.9833703523103508,
-0.7456631063614969,-0.8173587433845655,-0.8812051016459226,
-0.9325588839421305,-0.9681598882374777,-0.9870397834787261,
-0.99056942924076,-0.9817039872478999,-0.7601357246335175,
-0.82876883364816,-0.887298854659372,-0.931526545874374,
-0.9592009976026995,-0.9705589758896634,-0.9679134580585838,
-0.7635946484712315,-0.8267930492778305,-0.8781853684611858,
-0.9144884914916022,-0.934650707238976,-0.9399235077793813,
-0.7547827674388909,-0.8108510779697197,-0.8543284576557796,
-0.8830748007745595,-0.8971016370404786,-0.7341200461470681,
-0.7823945479956939,-0.8182893261768063,-0.8407283372889187,
-0.7036089418396923,-0.7444266467538491,-0.7738552525426188,
-0.6661987769113784,-0.7005610213599369,-0.6249827499272808,
-0.1885282693989691,-0.09558834947432154,0.005730628355370741,
0.111792540109273,0.2177619400763412,0.3185883951684442,
0.4101439293014277,0.4899625516770138,-0.2048200319759604,
-0.1077438933887955,-0.002691796830558471,0.1059400956623477,
0.2127824486290439,0.3127262866621893,0.4020586651367561,
-0.2195135736243867,-0.1190409791973846,-0.01149894225597868,
0.09809742254017301,0.2041703576935574,0.3019159562443602,
-0.2315278949190421,-0.1287403742204129,-0.02025963236651961,
0.08856921814263634,0.1923495858173033,-0.2399986269164587,
-0.136265086596977,-0.02852800385427971,0.07790943731694504,
-0.2445220631569563,-0.1413545191115968,-0.03595033950187966,
-0.2452460806309568,-0.1440996982422414,-0.2427639040507477,
-0.9627863463864214,-0.9287762212458259,-0.8793281693046819,
-0.8139833471872829,-0.734443661783315,-0.6444999213728085,
-0.5491780807749006,-0.4535171752887245,-0.9554673658442766,
-0.9140794058749131,-0.8559920650689382,-0.7817279594934516,
-0.6942589693680463,-0.5984781448346268,-0.4999494955348047,
-0.934367366569149,-0.8844223798763841,-0.8174229679769948,
-0.7351608585502457,-0.641822673191966,-0.542986764989374,
-0.8978748469678216,-0.8390728949381593,-0.7640817734701692,
-0.6759620794963979,-0.5797158650472573,-0.8462989355647894,
-0.7795498187240726,-0.6986832060861172,-0.6076796358995511,
-0.7820977027354027,-0.709434131000089,-0.6255453415851245,
-0.7093245618847172,-0.6334048252011675,-0.6325609463354179,
-0.1778161375899129,-0.1226310892230631,-0.06053925384414331,
0.007442324388539504,0.07929679392711581,0.1521341729788544,
0.222673458561735,0.2879340035685283,0.3458247516791153,
0.3953823593491522,0.4366423972091846,-0.08876371160394406,
-0.02528588772613339,0.04476837629156977,0.1195214252181962,
0.1959986327009231,0.2705464283542062,0.3396119290589926,
0.4005431057992871,0.4520218529859129,0.4940014731008501,
0.01030826616734189,0.08198490466663314,0.1591522280204451,
0.2389097207973864,0.3173816763430465,0.3904924510986985,
0.4549463955350546,0.5089146064888007,0.5521270265729551,
0.117472560686524,0.1962648015037478,0.2785512690899858,
0.3604576080817683,0.4375569230040101,0.505925367029105,
0.5630823357891753,0.6083330877322986,0.2292788658415479,
0.3129719884702788,0.3973400932411465,0.4778825649301736,
0.5502139834879405,0.6111631805503013,0.6594089221868847,
0.3410385404813853,0.4265108902934403,0.5094170629259336,
0.5852084170909949,0.6501542610793901,0.7022080829625521,
0.4476465561008348,0.5314703253828574,0.6096570464011057,
0.6781972947322877,0.7343998566036512,0.5446711990330303,
0.6238421950486808,0.6949971116211809,0.7550398975145011,
0.629214796874201,0.7016703235997708,0.7646693979379596,
0.7001887122370751,0.7649403475532479,0.7580253719184178,
-0.5980610514568761,-0.5589881370818129,-0.5101530988159087,
-0.4510385045651341,-0.382225667160838,-0.3056524524744078,
-0.2244621267538426,-0.1424014047662905,-0.06301328229424107,
0.01100431499766755,0.07805400320688782,-0.5212000928328268,
-0.473821384591564,-0.4161517087436187,-0.3483435180237136,
-0.2719386249037586,-0.1899104644827079,-0.106168437105403,
-0.0246774460389087,0.05138083746707222,0.120041421580981,
-0.4311039309963852,-0.3746268308434739,-0.3079662136138592,
-0.2322443529582202,-0.1501157132113724,-0.06545131715451497,
0.01750888497279251,0.09514231706859014,0.1650825345160538,
-0.3282706848689272,-0.2627160067380389,-0.1880137321428399,
-0.1064226243048281,-0.0215868970434456,0.06217585792644167,
0.1409092129286223,0.2118443492085483,-0.2148810450151756,
-0.1414239428971924,-0.06090095222676627,0.0234070437450894,
0.1073128739652992,0.1866888371989906,0.2584097661066967,
-0.0948797286874359,-0.01589086440904075,0.06724059985094104,
0.1506371707417032,0.2301937869064764,0.3025309778153461,
0.02655484252908358,0.1079004271192526,0.1901297170957776,
0.269350641258243,0.3420822257932489,0.1440569199487702,
0.2244719783102178,0.3027669323023652,0.3755350385655634,
0.2531835106264871,0.3299301683341083,0.4022303494272352,
0.3510968726936461,0.4223460594339758,-0.07805410188638827,
-0.09276641502761757,-0.1080255529483224,-0.123231540300325,
-0.1376217050758367,-0.1503967869358663,-0.1609000070073124,
-0.1687715154704865,-0.1740018618448228,-0.1768698604837748,
0.005852711686888685,-0.004907458921365185,-0.01667363978400245,
-0.02910230703937302,-0.04167551826680154,-0.05377893240309974,
-0.06483570957325965,-0.07443642513334246,-0.08240206216970784,
0.09827676798573926,0.09169789424305551,0.083291898217249,
0.07306224170584404,0.06127443921955168,0.04845159286147566,
0.03526739273256396,0.0223825152995957,0.1971676395871742,
0.1943681810797974,0.1884952036420767,0.1792304305890973,
0.1667127428266929,0.1515792114414989,0.134812448209863,
0.2991139104294396,0.2989413652639448,0.2941068360088736,
0.2841377396140656,0.2692865316145088,0.2505276366498019,
0.399677322182528,0.4003768622965933,0.3947504029769399,
0.382445062756354,0.3640665537863402,0.4942032775296958,
0.4938403319910914,0.4857723178878524,0.470018015874229,
0.5788262679961029,0.575792452883696,0.5642398722628517,
0.6512069539966677,0.6445542311848552,0.7107016666079528,
-0.9161616153729886,-0.9319303956122561,-0.9396953110011561,
-0.9366313083669698,-0.9204280785344878,-0.8900379255247357,
-0.8462030522374957,-0.7914228667351423,-0.7293237120999879,
-0.663758722300958,-0.8876449455755545,-0.8994356085395798,
-0.9017511736022054,-0.8917607021504116,-0.8675634598042835,
-0.8289706205471806,-0.7778214867506247,-0.7175692482251322,
-0.6523369554154551,-0.5859517695425136,-0.8470541513588044,
-0.8530863623730024,-0.8482966176587544,-0.8301999149225319,
-0.7977006542517769,-0.7517266504248017,-0.6951661565374421,
-0.6320680091083589,-0.566558592627622,-0.7927543534178244,
-0.7914101005217242,-0.7783641365944748,-0.7518828443693624,
-0.7119690859200297,-0.660654211393362,-0.6015113260745434,
-0.5386394371453509,-0.7243096319272092,-0.7146076494872069,
-0.6931460376496088,-0.6592387683821411,-0.6140043047773551,
-0.5602361841518015,-0.5016343691560573,-0.6430242175142256,
-0.6250295478554301,-0.596219325041805,-0.5569826617529877,
-0.5092509168566325,-0.4560492515462431,-0.5520254073275178,
-0.5269450103103401,-0.4928644880867128,-0.4509854395387125,
-0.403575153350467,-0.4557100264506188,-0.425580431270515,
-0.3887439926860071,-0.3468035231429711,-0.3587591578566765,
-0.3258932157449829,-0.2886351685087218,-0.2651897825092151,
-0.2316682604407079,0.5980613131647216,0.5589883601394342,
0.5101532951859686,0.451038686721687,0.382225843595672,
0.3056526230838691,0.2244622808787926,0.1424015236007947,
0.06301334452030186,-0.01100432747032814,0.6470944588058076,
0.6063945120633992,0.5544956308560397,0.4909814474854842,
0.4168791394819704,0.3348509827825754,0.248806364862682,
0.163021328012756,0.08119217116689301,0.6944632949786616,
0.6513144930113939,0.5955168212825119,0.5269608417915713,
0.4473425940100297,0.3601678525102263,0.2700417838303327,
0.1815453704759045,0.7372825381163968,0.6906294333400347,
0.6300883699674214,0.5561262995663098,0.4712906267013536,
0.3798989213097872,0.2870043862751919,0.7724043956082883,
0.7211854504544825,0.6553545192922715,0.576197864204669,
0.4871408620353512,0.3930729578844198,0.797087559189558,
0.7405927447841627,0.6695504697315396,0.5861540209201834,
0.4945084290202527,0.8097301284690857,0.7479263796731634,
0.6725220182496192,0.5864764631401966,0.8103038862615974,
0.7439345925004668,0.6656398165194758,0.8002534097038426,
0.7306537225524881,0.7819506470598,-0.4366431953633789,
-0.5106666754492736,-0.5869882376922511,-0.6624740500734984,
-0.7332080507197046,-0.7951587738972527,-0.8450980113065225,
-0.8813674368391481,-0.9041113586460733,-0.9149201193897882,
-0.4223467825896815,-0.4979651901691212,-0.5751701148400569,
-0.6502749910785526,-0.7189488051634834,-0.7771253015026822,
-0.8220318406135049,-0.8528138420803982,-0.8704523073313828,
-0.877132051866122,-0.4022310083998925,-0.4781163288807728,
-0.554596445154436,-0.6275642260210416,-0.6925605687496104,
-0.7458582025116769,-0.7854318984598006,-0.8112889263329699,
-0.8250621271173465,-0.3755356470489176,-0.4501425958887488,
-0.5241864933378524,-0.5934002650897944,-0.6535679922027033,
-0.7016275314245141,-0.7364042366101387,-0.758599491836005,
-0.3420827953668352,-0.4139041914442195,-0.4840440064641756,
-0.5484062706939985,-0.6033456975789954,-0.6466104559972755,
-0.6777531805937266,-0.3025315118038733,-0.3703991963484116,
-0.435725075678865,-0.4948721352375582,-0.5449289606848956,
-0.5843857415998934,-0.2584102557043402,-0.321701018732575,
-0.3819753792546441,-0.436205800680254,-0.4821906665520286,
-0.2118447747227839,-0.2704914294051139,-0.3260202911877148,
-0.3760152101544279,-0.1650828712784331,-0.2194154020550029,
-0.270790845781693,-0.1200416470582943,-0.1705734571487906,
0.9161619708326184,0.9319307491762596,0.9396956424389374,
0.9366315992939006,0.9204283182965946,0.8900381161951118,
0.8462032095340455,0.7914230156292639,0.7293238793541417,
0.6637589298557965,0.9487876867424746,0.9638219991954514,
0.9689402187057976,0.9610351558002814,0.937956150415152,
0.8993632776707052,0.8470958517094176,0.7847581799295993,
0.716723246034345,0.9749588444840027,0.9874641413480602,
0.9879501207294071,0.9733335913695014,0.942053498973333,
0.8948602911895638,0.8348196077814718,0.7664457510261931,
0.9913973712326389,0.9992329380155185,0.9930645438165779,
0.9702883664051513,0.9303746073596573,0.8753546246993716,
0.8093341962935008,0.9950795014807369,0.9961777933609237,
0.9818515654328379,0.9504460903479695,0.9027098746674149,
0.841806420960272,0.9840623116657442,0.9769921932350635,
0.9540532376241087,0.9148166158751114,0.8612136882276913,
0.9581801446138297,0.9425905156295621,0.9118246030313639,
0.8666310652479987,0.9192101668893,0.895902096029785,
0.8590657328509213,0.8703772282258925,0.8409823115598557,
0.8154720767160899,0.1778171059718252,0.1226319330808614,
0.06053992567271226,-0.007441870151939188,-0.07929659020903117,
-0.1521342296531137,-0.2226737578340799,-0.2879345044307138,
-0.345825401239635,-0.3953831051073846,0.2316691816765674,
0.1757724390286309,0.1122685379972423,0.04238946123155791,
-0.03147431095673338,-0.1060223690705309,-0.1777018008392572,
-0.2435073681639464,-0.3015367950655638,-0.3510977114791443,
0.2886360377097776,0.2320884584878828,0.1672516508448342,
0.09562800512668546,0.02000533874392893,-0.05595525429524186,
-0.1285435155191929,-0.1948426136371608,-0.2531843553864728,
0.3468043362453595,0.289467434229511,0.2232553503091939,
0.1500085463918315,0.07290895867983387,-0.004119533631953385,
-0.07735131409521774,-0.1440577225948253,0.403575906447316,
0.3451254769459608,0.2774342678683828,0.2027388030014913,
0.1245598363284875,0.04693326425220518,-0.02655554762561945,
0.4560499397602033,0.396110678421097,0.3269267724177788,
0.2511351438644352,0.1724665161635576,0.09487917246041,
0.5016349858535857,0.4399931207714222,0.3695530582277636,
0.2932656162238703,0.2148806720954671,0.5386399743309223,
0.4754121349188742,0.4042569522642996,0.3282705050396187,
0.5665590425344393,0.5022156935301549,0.431103930292903,
0.5859521265200787,0.5212002413653404,0.5106659414837471,
0.5869876102086139,0.6624735709935894,0.7332077514676827,
0.7951586652134928,0.845098078457225,0.8813676435997579,
0.9041116580482536,0.9149204654298684,0.5734213362282777,
0.6539109564930851,0.7314600073324019,0.8014445481530106,
0.8596212046135118,0.9032173146992399,0.9315553799266565,
0.9459093111069366,0.6355985255876813,0.7182616282077119,
0.7953081408089798,0.8617334421407644,0.9136023622650965,
0.9490975365686583,0.9687717311497821,0.6936983436880695,
0.7758024684863688,0.8493585337677274,0.9095263441824443,
0.9532437439744202,0.9799603432594377,0.7438876747925507,
0.8223898048944452,0.8896840618492347,0.9416915744235097,
0.9765940848309838,0.782878718417177,0.8550853688846947,
0.9142324281909144,0.9574084820329141,0.808813197110931,
0.8729720010540123,0.9233179132328828,0.8216808702627202,
0.8772096742129835,0.8230696091572214,0.09276640377310574,
0.1080256414522809,0.1232317408385954,0.1376220280275969,
0.1503972383762519,0.1609005865750696,0.1687722156036723,
0.1740026689030255,0.1768707572388351,0.1705731738763045,
0.1906930126322413,0.2105464412580206,0.2289927972013699,
0.2447929403327111,0.2568964854662051,0.2647265853183172,
0.2683098464673112,0.2681884415185128,0.2651905971794372,
0.2707904196202965,0.2960475246517403,0.3196768235430837,
0.3399487493807457,0.3552546724685221,0.3645596525653644,
0.3677018240803483,0.3653636154505258,0.3587598208776521,
0.3760147097386288,0.4053026883769021,0.4310210766569808,
0.4509771335793986,0.4634949414172432,0.4679374232163439,
0.464858993637328,0.4557105558116591,0.4821901792282771,
0.5135270414103618,0.5389508449256169,0.5561389504462149,
0.5637713635689835,0.5619411906656432,0.5520258363563475,
0.584385354546882,0.6152086674144305,0.6377766977965403,
0.6500821302058097,0.651519250667168,0.6430245879023526,
0.6777529577987501,0.7055014818762047,0.7231337276202411,
0.7293239492942762,0.724309982145211,0.7585994584260806,
0.7813166545183711,0.7928692947394784,0.7927547081501097,
0.8250622687013296,0.8417304368393459,0.8470545173149734,
0.8771323267159262,0.887645314498864,0.3015360453845148,
0.2435067604258691,0.1777013915256129,0.1060222058462941,
0.0314744189369969,-0.04238908731366174,-0.1122679310637554,
-0.1757716484888774,0.1948419043847709,0.1285429999155006,
0.05595498503480459,-0.02000532948058562,-0.0956277167931003,
-0.1672511147059996,-0.2320877267540867,0.07735069910586773,
0.004119161966720001,-0.07290904878978868,-0.1500083477710563,
-0.2232548905422917,-0.2894667665085293,-0.04693373219192027,
-0.1245600244829796,-0.2027386973931088,-0.2774338902981233,
-0.3451248789428226,-0.1724667992141356,-0.2511351336125937,
-0.3269264832443289,-0.3961101570586181,-0.2932657019670711,
-0.3695528631494325,-0.4399926839835791,-0.4042568549159931,
-0.475411790223567,-0.5022154461218424,-0.005852598553161901,
-0.08119196505793361,-0.163021049159767,-0.2488060411927053,
-0.3348506437156618,-0.4168788074510346,-0.4909811315875961,
-0.554495326274857,-0.6063942048702905,-0.6470941325142202,
-0.09827641615811868,-0.1815449292413942,-0.2700412859530667,
-0.3601673374231551,-0.4473420975374328,-0.5269603854089682,
-0.5955164071695848,-0.6513141073946994,-0.6944629164413806,
-0.1971670439169432,-0.2870037215224481,-0.3798982345693028,
-0.4712899665970914,-0.5561257020948373,-0.6300878481113522,
-0.6906289766699522,-0.7372821213716372,-0.2991130971968019,
-0.3930721160778319,-0.4871400501186961,-0.5761971323316351,
-0.6553538941234454,-0.7211849292226609,-0.7724039524031648,
-0.399676350745083,-0.4945074863044202,-0.5861531681464745,
-0.6695497477032463,-0.7405921623591333,-0.7970870947583817,
-0.4942022299541438,-0.5864755076757882,-0.6725212074710563,
-0.74792573591698,-0.8097296395344389,-0.5788252298638613,
-0.665638926578608,-0.7439338855424372,-0.810303362756081,
-0.6512059956089504,-0.7306529513600663,-0.8002528392148971,
-0.7107008326980349,-0.7819500193454378,-0.7580246814516085,
-0.2681877205946842,-0.2683092406063016,-0.2647261130437045,
-0.2568961585702784,-0.2447927610385159,-0.2289927579868598,
-0.2105465274520093,-0.1906932062912961,-0.3653630641630742,
-0.3677014077761052,-0.3645593896043551,-0.3552545716101517,
-0.339948807237406,-0.3196770257819652,-0.2960478502452225,
-0.464858585918057,-0.4679371612123701,-0.4634948428974661,
-0.4509772049977542,-0.4310213111152231,-0.4053030678481073,
-0.5619408834098191,-0.5637712030900536,-0.5561389551781383,
-0.5389510214534028,-0.5135273825534448,-0.651518994572369,
-0.6500820157815153,-0.6377767462064369,-0.6152088877366557,
-0.7293237033806105,-0.7231336172569296,-0.7055015320014856,
-0.7928690367045447,-0.7813165283080149,-0.841730164442513,
-0.7167229918086124,-0.7847579855913325,-0.8470956951046914,
-0.8993631303768833,-0.9379559853910195,-0.9610349555582707,
-0.968939979478583,-0.9638217293378932,-0.9487874014792429,
-0.7664454690716618,-0.8348194119106425,-0.8948601580568658,
-0.9420533966954356,-0.9733334885435185,-0.9879499956150448,
-0.9874639861492262,-0.9749586635216289,-0.8093339051128812,
-0.8753544488679451,-0.9303745202617085,-0.9702883306150087,
-0.9930645219898977,-0.9992329031534651,-0.9913973109989458,
-0.8418061322197662,-0.9027097279159257,-0.9504460536566606,
-0.9818515951566739,-0.996177846854893,-0.9950795477220543,
-0.8612134015838815,-0.9148164899330201,-0.9540532347842757,
-0.9769922654221862,-0.9840624137666333,-0.8666307679449418,
-0.9118244750171576,-0.9425905155806792,-0.9581802235578871,
-0.8590654047339893,-0.8959019370925372,-0.9192101353217356,
-0.8409819323578077,-0.8703770126934449,-0.8154716315810106,
-0.05138099314083437,0.02467734836797703,0.1061683820305035,
0.1899104376062115,0.2719386182644327,0.3483435331583406,
0.4161517553821363,0.4738214760951626,-0.09514260413767517,
-0.0175091339170676,0.06545109551523358,0.1501155140512474,
0.2322441809962577,0.3079660822386824,0.3746267572069504,
-0.1409096123632751,-0.06217624169087836,0.02158652471546835,
0.1064222699680223,0.1880134132638135,0.262715746535069,
-0.1866893275259466,-0.1073133727582037,-0.02340754682308935,
0.06090046334304851,0.1414234968618731,-0.2301943507183196,
-0.1506377672576039,-0.06724121511703012,0.01589026002363016,
-0.2693512698554454,-0.1901304002696938,-0.1079011406857555,
-0.3027676257747358,-0.224472743157967,-0.3299309317589397,
-0.9459090564395943,-0.9315551937272754,-0.9032172391195878,
-0.8596212762960382,-0.8014447869733361,-0.7314604096467703,
-0.6539114969940219,-0.5734219768623257,-0.4940021735847102,
-0.9687716041275991,-0.9490974969653682,-0.913602441262072,
-0.8617336589899791,-0.7953084953825064,-0.7182621005240754,
-0.6355990826652251,-0.5521276321758419,-0.9799603552305356,
-0.9532438509855897,-0.909526560381993,-0.8493588583184724,
-0.77580288428704,-0.6936988224175965,-0.6083335981356588,
-0.9765942083818028,-0.941691783045487,-0.8896843516207826,
-0.8223901593137167,-0.7438880688474475,-0.6594093292610237,
-0.9574086493790075,-0.9142326541123561,-0.8550856370062082,
-0.782879006233477,-0.7022083677250226,-0.9233180317911697,
-0.872972144171723,-0.8088133452877488,-0.7343999908188845,
-0.877209652594128,-0.8216808432264592,-0.7550398503916647,
-0.8230693796089513,-0.7646691446910742,-0.7649398754101678,
0.6523372575426411,0.7175695092343044,0.7778217282247372,
0.828970867566289,0.867563733535706,0.8917610129438806,
0.9017515185532632,0.8994359744121508,0.6320684006265465,
0.6951665021597787,0.7517269700406279,0.7977009700656229,
0.8302002440404257,0.8482969664746548,0.8530867259579973,
0.6015117982089927,0.6606546288416104,0.7119694660426552,
0.7518832062338756,0.7783644942261146,0.7914104587099922,
0.5602367267427266,0.6140047811934269,0.6592391933644046,
0.6931464276818936,0.7146080169943935,0.509251521131838,
0.5569831878642361,0.5962197855090862,0.6250299573281404,
0.4509860998418013,0.4928650597255946,0.5269455040116824,
0.3887447062136717,0.4255810481267848,0.3258939808872747,
-0.4520224891160809,-0.4005436259417036,-0.3396122734793814,
-0.2705465411303475,-0.1959984769042034,-0.1195209939316481,
-0.04476769320458044,0.02528677771990007,0.08876475562044144,
-0.5089151305978357,-0.4549467775084718,-0.3904926248184883,
-0.3173815862988101,-0.2389093389601502,-0.1591515620353438,
-0.08198399284624955,-0.01030716362341688,-0.5630827400946593,
-0.5059255957776372,-0.4375569069570671,-0.3604572977868911,
-0.2785506506829446,-0.1962638993317844,-0.1174714262849324,
-0.6111634481983498,-0.5502140363721867,-0.477882336850574,
-0.3973395475484636,-0.3129711292234176,-0.2292777334167206,
-0.6501543660224874,-0.5852082672248219,-0.509416602839924,
-0.4265101014752001,-0.3410374453295618,-0.6781972070318585,
-0.609656670182737,-0.531469622469496,-0.4476455277450017,
-0.6949968061057114,-0.6238415797897515,-0.5446702557332809,
-0.701669787076208,-0.6292139442700462,-0.7001879458668289,
0.8704525623995767,0.8528140389888319,0.8220319347625164,
0.7771252518482044,0.7189485862927419,0.6502746013906258,
0.5751695760111849,0.497964538802267,0.8112890338044526,
0.7854319364049284,0.7458581338540565,0.6925603649758249,
0.6275638768849461,0.5545959620739339,0.4781157400838166,
0.7364041563355311,0.7016273774526178,0.6535677410698937,
0.5933999047634313,0.5241860281758185,0.4501420452269545,
0.6466101827787859,0.6033453603619342,0.5484058620979402,
0.4840435291285519,0.4139036582576368,0.5449285342030792,
0.4948716695409166,0.4357245760359055,0.3703986729586991,
0.4362052982975687,0.3819748711371402,0.3217005151313638,
0.3260198057983744,0.270490970101615,0.2194150172838141,
0.08240304061283914,0.07443732100834362,0.06483650679882089,
0.05377961812205672,0.04167608470977979,0.02910275219613371,
0.01667396676186753,0.004907674513220617,-0.0223814688467947,
-0.03526641653115874,-0.04845070073398356,-0.06127364342066123,
-0.07306155181298434,-0.0832913202753871,-0.09169743029697446,
-0.1348113569049385,-0.1515781730059853,-0.1667117684090611,
-0.1792295328710818,-0.1884943959488113,-0.1943674753097082,
-0.2505265309683513,-0.2692854573778917,-0.2841367059314813,
-0.2941058574917593,-0.2989404603106648,-0.3640654661632947,
-0.3824439829710035,-0.394749339616747,-0.4003758331308906,
-0.4700169740867185,-0.4857712605383084,-0.4938392688789908,
-0.5642388946704648,-0.5757914389111062,-0.6445533256821902,
-0.1282040992012934,-0.05321855554427612,0.02998172476739921,
0.1197175263736552,0.2130449739264662,0.3060111300013609,
0.394354771181159,0.4744188270546212,0.5438573645627299,
0.6018455943795508,0.6488215902264565,-0.1584409684968982,
-0.08061941460724659,0.005851663594817331,0.09880655117780221,
0.1946724526862442,0.2889433394395604,0.3771263430050333,
0.4557536219427536,0.5229695128140037,0.5785062522661573,
-0.1901340637026595,-0.1097761406561385,-0.02057293935230464,
0.07475784175875169,0.1720544722828635,0.2664447755897635,
0.3534794142829396,0.4301062418911859,0.4950335464190314,
-0.2221347426415571,-0.1396269276604669,-0.04840420657561294,
0.04825793538561177,0.1457553988926505,0.2391262056337631,
0.3242394390900903,0.3985926425219686,-0.252933321812349,
-0.168751250747966,-0.07636778766011496,0.02046791155100532,
0.1169519253626288,0.2083323398966038,0.2909961752861106,
-0.2808945465452747,-0.1956215915798094,-0.1030413667410095,
-0.007197896555794293,0.08719109671857094,0.1758296024995542,
-0.304612640171253,-0.218957329454675,-0.1271903099934383,
-0.03341079168503205,0.0580070042064605,-0.3232363968742333,
-0.2380131586083366,-0.1480327683071742,-0.05721040323642156,
-0.3366056805211806,-0.2526623104055841,-0.1653138037361849,
-0.3451559795786212,-0.2632729700486575,-0.3496821715684524,
0.6714420577705413,0.7363064649907652,0.8002044514563711,
0.8596329319699905,0.9106424580428781,0.9496341036793503,
0.9742808059046055,0.9841303617506333,0.9805708386415104,
0.9662289123338648,0.9441720387917811,0.7051823376417343,
0.772857969148872,0.8380824708147486,0.8966582333398196,
0.9442212565687949,0.9773096449869836,0.994346428784018,
0.9959947242778775,0.9847131791126237,0.9638452720539006,
0.7350956003099328,0.8038805096388253,0.8682639008659977,
0.9235417715931376,0.9653353535299492,0.9908225390539687,
0.9995536316680411,0.9933753693114809,0.9755844796257857,
0.7585152302781616,0.8261311652202954,0.8871112537106268,
0.9366413319148751,0.9708622908203767,0.988032496009293,
0.9889451040531339,0.9763862533615466,0.7728091190204586,
0.8367229328771276,0.8918537226509272,0.9338031104143576,
0.9597077065970592,0.9690768333338338,0.9637247890765801,
0.7760312926982586,0.8339786000659982,0.8815310666159923,
0.9151715385907231,0.933244106655567,0.9363385958760152,
0.767530944505584,0.8180289491084085,0.857374860312736,
0.8831546795136415,0.8948082473172733,0.7481893791144126,
0.790783305063361,0.8223658994270935,0.8415629406712848,
0.7201359303293944,0.755286693908195,0.7802583897718675,
0.6861124167319267,0.7148528823763073,-0.9441722324566724,
-0.9089826616996974,-0.8608166107545396,-0.798145123044153,
-0.7207644955095487,-0.6303269409870232,-0.5303678229575245,
-0.4256669568776663,-0.3211867088850157,-0.221088326716299,
-0.9323220393450906,-0.8912341788673274,-0.8355390934902637,
-0.7640503287556382,-0.6773887436471858,-0.5783931938554159,
-0.4717817419682783,-0.3630890689211784,-0.2573948493808621,
-0.9096404828216634,-0.8611864915849053,-0.7967975927156801,
-0.7160071810801653,-0.620601831095295,-0.5147133115844718,
-0.4039985827676406,-0.2942465140581043,-0.873971359384776,
-0.8169372490707259,-0.7433257505302604,-0.6537697064615564,
-0.5513858884167668,-0.4413849791363659,-0.329823034867975,
-0.8241231220089414,-0.7579997417459179,-0.6757043639889994,
-0.5791759017751473,-0.4726959329165278,-0.3620176676150795,
-0.7605084662990487,-0.6858745237990584,-0.5966690200428781,
-0.4960221196000292,-0.388888002229758,-0.6854057579633669,
-0.603999039701328,-0.5106159168102177,-0.4091534188855591,
-0.6025948313141819,-0.5169734519149861,-0.4224835049786242,
-0.5164821811548767,-0.4294377118759299,-0.4311427045530306,
-0.3130828685601688,-0.2261777090945995,-0.128054626578418,
-0.02022860607974414,0.09418349997750548,0.2106381298878162,
0.3239109228229815,0.4291933772271586,0.523048087763098,
0.6038168419091856,-0.3104444323030748,-0.2176605469020037,
-0.1131261690200332,0.0009102704499983739,0.1203702792920805,
0.2398156109769667,0.3535535822768655,0.4569191625595045,
0.5471127369113119,0.6232994222041273,-0.3043330399192493,
-0.2057260225894636,-0.09531787499064681,0.02374459641152675,
0.146419102006115,0.2666203176913846,0.3786227553496849,
0.4783283811020137,0.5638039035645359,-0.2939990078566014,
-0.1900378279544306,-0.07488904582360796,0.04735210953525339,
0.1708856651832371,0.2894245513177179,0.3977010533927281,
0.4924894823466497,-0.2789925774668332,-0.1706755754519138,
-0.05252850546893189,0.07054986219834002,0.1924160430438771,
0.307105809225674,0.4101897544477446,-0.2593820240207756,
-0.1482455618465796,-0.02928064957337935,0.0921572380074013,
0.2100905134498461,0.3193074202631062,-0.2358533016570041,
-0.1238167822688868,-0.006318969895916147,0.1112788403952597,
0.2236016867495729,-0.2096044634529125,-0.09868017515402502,
0.01532894544522089,0.127462173385832,-0.1820659309330632,
-0.07404772953164979,0.03496843200875603,-0.1545841458628095,
-0.05083475466396539,-0.6714423515894649,-0.7363066534250458,
-0.8002045390283683,-0.859632936776908,-0.9106424117173109,
-0.9496340459616872,-0.9742807748705438,-0.9841303841597815,
-0.9805709251787237,-0.9662290590683913,-0.6736593131243975,
-0.739662482666216,-0.8034418824887359,-0.8609423496737078,
-0.9079287599677793,-0.9410171351552678,-0.9586305009774437,
-0.9613540496396505,-0.9515175508275152,-0.6691519386893557,
-0.7345993546337776,-0.79626257796142,-0.8497460401941979,
-0.8909109722488041,-0.9170267250100911,-0.9275521423149625,
-0.9240939630879936,-0.656100800090535,-0.7189837013183803,
-0.7764177384094252,-0.8240374297552895,-0.8582583152457706,
-0.8773387645254044,-0.8817972923410141,-0.6332080201962388,
-0.6915533212632716,-0.7430051304270751,-0.7836645345684842,
-0.8108589038018792,-0.8239068177963524,-0.6002017842451572,
-0.6525164982995073,-0.6970417319534228,-0.7306820673883421,
-0.7517816084827516,-0.5581290590099237,-0.6037336945345413,
-0.6413705283620924,-0.6688591076565297,-0.5092217844350768,
-0.5482985439178426,-0.5798809609547027,-0.4563600901355626,
-0.4897211300815704,-0.4024024278645879,-0.648822290296783,
-0.648349171242789,-0.6411378559950974,-0.6255004973956005,
-0.600293640880965,-0.5653935344751363,-0.5219527418637842,
-0.4722400785685584,-0.4191009430775375,-0.3653071673956498,
-0.7148533441384284,-0.7155197916209453,-0.7077869387160182,
-0.6896699883604869,-0.6600703681315339,-0.6193375043296356,
-0.5694127009086171,-0.5133919240157367,-0.4547192979777763,
-0.3964310803290843,-0.7802586188950914,-0.7808677178913338,
-0.7711197529973893,-0.7489240139903413,-0.713538182957094,
-0.6660993109205865,-0.6094980396194888,-0.5475936950081823,
-0.4842093859996422,-0.841562970549242,-0.8403682541467874,
-0.8267667446471012,-0.798907464199165,-0.7567804454437204,
-0.7025296887747676,-0.6399394350221852,-0.5733572200389935,
-0.8948081394501657,-0.8897668713226807,-0.8705497953564927,
-0.8359665662613534,-0.7870195954857328,-0.7268354112898293,
-0.6597854273844109,-0.9363384293729855,-0.9255995665778384,
-0.8996275962075316,-0.8582152453052212,-0.8034009739634004,
-0.7389956620788967,-0.9637246412193355,-0.9461585726484955,
-0.9132982945459158,-0.8659870495929599,-0.8070428410352181,
-0.9763861801087089,-0.9518769772925728,-0.91299797697185,
-0.8614408694954784,-0.975584505681221,-0.9449459265141765,
-0.9015722073987464,-0.963845393304663,-0.9284651475621579,
0.3130823317650696,0.2261770766623218,0.1280539101236855,
0.02022783076448256,-0.09418429615654819,-0.2106389019045293,
-0.3239116283455282,-0.4291939860046181,-0.523048586255087,
-0.6038172319641657,0.2600841789503569,0.1646285788165745,
0.05778571619095332,-0.05796842566746966,-0.1783494840893115,
-0.297794748004312,-0.4106115455276073,-0.5122593289719761,
-0.6001443622816693,0.1989845274738189,0.09504589509123174,
-0.01970764286946627,-0.1416365624266124,-0.2653151882168217,
-0.3845121065161455,-0.4936479477555078,-0.5890080819228373,
0.1303871207046509,0.01886496318699474,-0.1019485160673513,
-0.2272413285785661,-0.3507747719153151,-0.4662617951252705,
-0.5688734433747777,0.05597369301027853,-0.06123892158082981,
-0.1852629737758222,-0.3104018186002749,-0.4302072668465533,
-0.5390198361162625,-0.02151295053653907,-0.1416473256500602,
-0.2654479680509194,-0.3868857125795179,-0.4999829944651056,
-0.09867461327158224,-0.2185280531038441,-0.3387557568094476,
-0.4536233831584169,-0.1721555744064095,-0.2886982185503227,
-0.4027071899557529,-0.2393260112020272,-0.3502029095948441,
-0.2986531728773539,0.1282040764044601,0.05321845051851246,
-0.0299819504088954,-0.1197179049294584,-0.2130455201840074,
-0.3060118317848468,-0.3943555879655132,-0.4744196990222574,
-0.5438582278251758,-0.6018463947181518,0.0508347486986919,
-0.03269551088976293,-0.1240992485699228,-0.2207245467966487,
-0.3185587143239474,-0.4128297421420895,-0.4990447345439135,
-0.5740017863876323,-0.6362851104978535,-0.6861131509034271,
-0.03496843048443223,-0.126718664611582,-0.2252069693946209,
-0.3266628419962321,-0.4261053308619027,-0.5183500501623459,
-0.5992598174372795,-0.6666016739887244,-0.720136706807033,
-0.1274621786236507,-0.2261259790523726,-0.329452932630458,
-0.4326360098383147,-0.5301336109403396,-0.6169837287853274,
-0.6899929014185586,-0.7481901976756111,-0.2236017161594696,
-0.3267916497417753,-0.4317330442416767,-0.5329718535250777,
-0.6250530132529536,-0.703875699754291,-0.7675317913865697,
-0.3193074905789999,-0.4238069911549194,-0.5267203305462205,
-0.6225639241960304,-0.7066200241231836,-0.7760321386045594,
-0.4101898771205939,-0.5125483215775021,-0.6101488498350025,
-0.6980950818677443,-0.7728099228904255,-0.4924896604754524,
-0.589718294305585,-0.679698789286976,-0.7585159482037284,
-0.5638041319099237,-0.6538562109800681,-0.7350961954485662,
-0.623299689837984,-0.7051827865650066,0.6483485235093655,
0.6411372723067146,0.6254999813609712,0.6002931843810706,
0.5653931175085023,0.5219523372221417,0.4722396596033476,
0.4191004905746099,0.3653066725193389,0.5719394335088436,
0.5579566936615924,0.5351892752413209,0.5030959515755655,
0.4623631200726549,0.4149320801413646,0.3635618193945052,
0.3111391128807077,0.4812077579558775,0.4596949806286311,
0.4297384718300117,0.3916338931244087,0.3469138437185931,
0.2980734064957148,0.2479339211516947,0.3769270466275512,
0.34798863705642,0.3118670040922781,0.2697400287604772,
0.2237517049369116,0.1764984145646341,0.2618704462020703,
0.226741584116328,0.1865794537419862,0.1432114770939381,
0.09893915843486868,0.1407291822657564,0.1016644513337693,
0.06025214993119726,0.01853073096018258,0.0192767564986509,
-0.02097489882147943,-0.06089466864900071,-0.09693134249768307,
-0.1358102942547418,-0.2036925009060082,0.9089824672626068,
0.8608164411414747,0.7981450033151747,0.7207644427956729,
0.6303269573377657,0.5303678926086439,0.4256670502613963,
0.3211867913977836,0.2210883675134422,0.9284650222993554,
0.8871725500645941,0.8313006928275277,0.7596804192454199,
0.6729483436994259,0.5739528381046123,0.4674119497069649,
0.3588508188064044,0.2533333547826946,0.1545840239447369,
0.9015721838250796,0.8527098639261403,0.7879881821713033,
0.7069782619885319,0.6114960278478284,0.5056844240896506,
0.3951892122332402,0.285769898249863,0.1820657113417612,
0.8614409638909055,0.8038277741655933,0.7297824294607609,
0.6399926588400225,0.5376088254129453,0.4278416041703199,
0.3167134480853839,0.2096041546069603,0.8070430398170311,
0.7402383431039794,0.6574928275930984,0.560806507588693,
0.4544842943197335,0.3442560602121421,0.2358529185889448,
0.7389959159190774,0.6636727901334047,0.5740968543042024,
0.4734498690772693,0.3666860169560138,0.2593815856416469,
0.6597856586149884,0.5777801683909922,0.4841878538357612,
0.3829343216652333,0.2789921022280572,0.5733573420809426,
0.4873055377141242,0.3928154550148792,0.2939985098519586,
0.4842093252521232,0.3969457605237173,0.3043325272261384,
0.3964307901608145,0.3104439077532887,0.6362842799460792,
0.5740009080509757,0.4990438745890764,0.4128289723722984,
0.3185580939893934,0.2207241066952111,0.1240989860968612,
0.03269539736236529,0.6666008139591869,0.5992589358516202,
0.5183492243752909,0.4261046359672609,0.3266623297142192,
0.2252066549797059,0.1267185286485934,0.689992024373379,
0.6169828686407737,0.530132851891722,0.4326354224553247,
0.3294525535291586,0.2261258043934048,0.7038748329124103,
0.6250522113657903,0.5329711994696135,0.4317325950511361,
0.3267914216946357,0.7066192072999724,0.622563222965479,
0.5267198166849954,0.423806701432994,0.6980943593640034,
0.6101482870567641,0.5125479715352314,0.6796981993053423,
0.5897178945758851,0.6538557778979411,0.9323218580087335,
0.9515174346052251,0.9613540145138462,0.9586305496920505,
0.9410172511751344,0.9079289076765579,0.8609424826856753,
0.8034419563572277,0.7396624652608896,0.6736591885240169,
0.9096403689902206,0.9240939382365192,0.9275522217134882,
0.9170269050764695,0.8909112253661301,0.849746318794698,
0.796262827475376,0.7345995283284186,0.6691520068054228,
0.8739713777891581,0.8817974249990892,0.8773390199098727,
0.8582586769711391,0.8240378550735361,0.7764181680693131,
0.7189840763729405,0.656101076264991,0.8241233338640371,
0.8239071624215608,0.810859375773786,0.7836651001194045,
0.7430057321681839,0.6915538934135402,0.6332085061147845,
0.7605089118538748,0.7517821894256266,0.730682759920626,
0.6970424857617678,0.6525172475488723,0.6002024649156599,
0.6854064426268304,0.6688599095382908,0.6413714065577412,
0.6037345889195533,0.5581299045184589,0.6025957234227359,
0.5798819340529643,0.5482995467196561,0.5092227563225322,
0.5164832226272315,0.4897222069506372,0.4563611494403301,
0.4311438278222397,0.4024035413263246,0.3496833143594963,
-0.2533334075588959,-0.3588508219660573,-0.4674119310964882,
-0.5739528280203016,-0.6729483660875734,-0.7596804843602077,
-0.8313007955580714,-0.8871726742411541,-0.2857700357309581,
-0.3951892821849063,-0.5056844492735352,-0.6114960336943951,
-0.7069782687900093,-0.787988199289983,-0.8527098891878181,
-0.3167136531290147,-0.4278417135183467,-0.5376088566787567,
-0.639992634716211,-0.7297823708955478,-0.8038276949870052,
-0.3442563102744645,-0.4544844137443082,-0.5608065113072425,
-0.657492739431111,-0.7402381888786644,-0.3666862898302455,
-0.4734499761180304,-0.5740968114811118,-0.6636726256137523,
-0.3829346014572981,-0.484187939006181,-0.5777800787254197,
-0.3928157351219527,-0.4873056046530535,-0.3969460425371419,
0.600144149407117,0.5122590107240774,0.4106111150772491,
0.2977942147481387,0.1783488751426739,0.05796778060322072,
-0.05778635529341983,-0.1646291768340628,-0.260084712697206,
0.5890080700362191,0.4936478319326018,0.3845118729629886,
0.2653148405479006,0.1416361235766341,0.01970714938077021,
-0.09504640342765641,-0.1989850169013517,0.568873645341387,
0.4662618905156885,0.3507747390771843,0.2272411653349327,
0.1019482418076114,-0.01886531395275474,-0.1303875092325712,
0.5390202482542535,0.4302075642722875,0.3104019730711553,
0.1852629793843341,0.061238796088284,-0.0559739158243807,
0.4999835950826037,0.3868861858512856,0.2654482825921611,
0.1416474750285941,0.02151295276860444,0.4536241369952758,
0.3387563694841473,0.2185284943201295,0.09867487876932232,
0.4027080566573236,0.2886989329203987,0.1721561104744125,
0.3502038519557472,0.2393267951217032,0.298654161645374,
-0.984713259051105,-0.9959947612173518,-0.9943464342167785,
-0.9773096457316496,-0.9442212908026748,-0.8966583408378461,
-0.8380826821486993,-0.772858299407996,-0.9933753694301851,
-0.999553621201999,-0.9908225482912788,-0.9653354239158236,
-0.9235419454230499,-0.8682642090770526,-0.8038809644055149,
-0.9889450353591552,-0.9880324674077218,-0.9708623496514911,
-0.9366415263248317,-0.8871116184521261,-0.8261317121277938,
-0.9690767381494427,-0.9597077173597477,-0.9338032828335274,
-0.8918540989344099,-0.8367235291009597,-0.9332440544501512,
-0.9151716624555581,-0.881531417418751,-0.8339792023300259,
-0.8831547498989281,-0.8573751662344773,-0.8180295248104962,
-0.8223661602728524,-0.7907838386634013,-0.7552871860588483,
-0.3111396248637522,-0.3635623115811258,-0.4149325617880891,
-0.4623636071651684,-0.503096462804278,-0.5351898259002444,
-0.5579572907903124,-0.5719400747815568,-0.5785069283639182,
-0.2479344056308305,-0.2980738893651726,-0.3469143327715778,
-0.3916343988495664,-0.4297390036046975,-0.4596955428592778,
-0.4812083484887336,-0.4950341577852201,-0.1764988082863052,
-0.2237521076309895,-0.2697404459306319,-0.3118674408741246,
-0.3479890956417611,-0.3769275248330646,-0.3985931343359159,
-0.09893938901501213,-0.1432117197792371,-0.186579712833973,
-0.2267418620329016,-0.2618707421483436,-0.2909964852939082,
-0.01853073419918189,-0.06025216482046628,-0.1016644832117871,
-0.1407292340032114,-0.1758296738027379,0.06089493100791283,
0.02097514873862574,-0.01927652693035482,-0.05800679989935065,
0.1358108258261833,0.09693185715603557,0.0572108907410362,
0.2036932746994002,0.1653145532988453,0.2632739407438701,
-0.5471131012749936,-0.4569196340994406,-0.3535541587646317,
-0.2398162730231354,-0.1203709912173413,-0.0009109877496780188,
0.1131254888510733,0.2176599356582619,-0.478328705556794,
-0.3786231842883476,-0.2666208448402719,-0.1464197032303796,
-0.02374523314186032,0.09531724619007391,0.2057254392916539,
-0.3977013270678494,-0.2894249268534429,-0.1708861328457008,
-0.04735264212838212,0.07488848723411734,0.1900372836013431,
-0.3071060284643041,-0.1924163631703616,-0.07055027067676212,
0.05252803743712917,0.1706750855887899,-0.2100906838592314,
-0.0921575105240425,0.02928029003178066,0.1482451448989572,
-0.1112789754160983,0.006318730357784829,0.123816455924515,
-0.01532906198457091,0.09867995232819112,0.07404761591340303,
-0.5229702552542058,-0.455754381535759,-0.3771270572800299,
-0.2889439451759633,-0.194672902916372,-0.09880682824059986,
-0.005851780927923981,0.08061942171187554,0.1584410564110822,
-0.4301068723700084,-0.3534800054422614,-0.2664452641642683,
-0.1720548071373146,-0.07475800001082551,0.02057294660420643,
0.1097762759917693,0.190134278339324,-0.324239892584746,
-0.2391265604455334,-0.1457556026172962,-0.04825796103784657,
0.04840435106572794,0.1396272041512353,0.2221350978923813,
-0.2083325524549613,-0.1169519894866824,-0.02046779780351893,
0.07636807502743861,0.1687516747481361,0.2529338262925594,
-0.08719102201021951,0.007198147474544054,0.1030417934166896,
0.1956221602390349,0.2808952005684322,0.03341116907881747,
0.1271908635410245,0.2189580303556818,0.3046134343217798,
0.1480334302314487,0.2380139721282078,0.323237313179716,
0.2526632136782334,0.3366066958443542,0.3451570696887505,
0.4547190651923899,0.5133917435529424,0.5694125552964621,
0.6193373643788831,0.6600701990863211,0.6896697595590643,
0.7077866317530298,0.7155194029861072,0.5475936980371527,
0.6094980941008995,0.6660993907770576,0.7135382519498201,
0.748924034855715,0.7711196978950583,0.7808675744788959,
0.6399396139686974,0.7025299057553986,0.7567806697847073,
0.7989076596939885,0.8267668794191896,0.8403683088289017,
0.7268356797799225,0.7870198804193677,0.8359668400797895,
0.8705500304441893,0.8897670473314109,0.803401239536944,
0.858215507236093,0.8996278379610205,0.9255997745502057,
0.8659872391476647,0.9132984713369965,0.9461587349139229,
0.9129980537560551,0.9518770467134829,0.9449458910860361,
0.2573950079345842,0.363089267383967,0.4717819390919956,
0.5783933464143868,0.6773888186481814,0.7640503132419058,
0.835538996354342,0.8912340245126464,0.2942468056901541,
0.403998910419839,0.5147136234231619,0.62060207699311,
0.7160073275453937,0.7967976318501995,0.8611864392751584,
0.3298234714814622,0.4413854454351217,0.5513863234589741,
0.6537700563672823,0.7433259842576552,0.8169373645440049,
0.3620182543235557,0.4726965405256068,0.5791764634315589,
0.6757048258462731,0.7580000771779366,0.3888887347419664,
0.4960228623929952,0.5966697046150125,0.685875099677583,
0.4091542831822379,0.5106167801856609,0.6039998362037971,
0.422484479771868,0.5169744155067602,0.4294387727293252 };
auto pointshell
= new vnl_matrix_fixed<double, 3, 1002>(coords);
return pointshell;
}
};
// ThreeLayerPointShell using a staggered-distribution
#include <itkMacro.h>
template<int NpointsShell1, int NpointsShell2, int NpointsShell3, class TMatrixTypeshell1, class TMatrixTypeshell2, class TMatrixTypeshell3>
TMatrixTypeshell1 *
ThreeLayerPointShell< NpointsShell1, NpointsShell2, NpointsShell3, TMatrixTypeshell1, TMatrixTypeshell2, TMatrixTypeshell3>
::DistributePointShell1()
{
itkGenericExceptionMacro(<<"This type of PointShell is not Supported and should not be used!");
return 0;
}
template<int NpointsShell1, int NpointsShell2, int NpointsShell3, class TMatrixTypeshell1, class TMatrixTypeshell2, class TMatrixTypeshell3>
TMatrixTypeshell2 *
ThreeLayerPointShell< NpointsShell1, NpointsShell2, NpointsShell3, TMatrixTypeshell1, TMatrixTypeshell2, TMatrixTypeshell3>
::DistributePointShell2()
{
itkGenericExceptionMacro(<<"This type of PointShell is not Supported and should not be used!");
return 0;
}
template<int NpointsShell1, int NpointsShell2, int NpointsShell3, class TMatrixTypeshell1, class TMatrixTypeshell2, class TMatrixTypeshell3>
TMatrixTypeshell3 *
ThreeLayerPointShell< NpointsShell1, NpointsShell2, NpointsShell3, TMatrixTypeshell1, TMatrixTypeshell2, TMatrixTypeshell3>
::DistributePointShell3()
{
itkGenericExceptionMacro(<<"This type of PointShell is not Supported and should not be used!");
return 0;
}
//Distributed Pointshell 7 - 16 - 22
template<> class ThreeLayerPointShell<7,16,22, vnl_matrix_fixed<double, 3, 7>,vnl_matrix_fixed<double, 3, 16>,vnl_matrix_fixed<double, 3, 22> >
{
public:
static vnl_matrix_fixed<double, 3, 7>* DistributePointShell1()
{
double coords[3*7] = {
0.8134386897688890,-0.4341253640420510,0.3871080808797820,
-0.4587290424636170,-0.8386718051774130,-0.2935937138306440,
0.9664216428893120,0.2069240694656700,-0.1523536597226610,
0.2351246687899070,-0.9681943247699460,0.0855344352275928,
0.3639220075873960,0.5047564346894090,-0.7828037519284090,
0.5319989685716170,-0.4881652317616310,-0.6918611160759410,
0.3581867553682760,0.1086899080235520,0.9273018668009770
};
auto pointshell
= new vnl_matrix_fixed<double, 3, 7>(coords);
// List sorted for each row [x,y,z]
// pointshell need [x...x
// y...y
// z...z]
int i=0;
for(int c =0; c < 7; c++)
{
for(int r=0; r<3; r++){
pointshell->put(r,c,coords[i++]);
}
}
return pointshell;
}
static vnl_matrix_fixed<double, 3, 16>* DistributePointShell2()
{
double coords[3*16] = {
-0.5452474978820280,0.0761974966412968,0.8348048320170320,
0.2927980757498900,-0.6773379396203400,0.6748945120446840,
-0.1417004162163040,-0.9633970491958960,0.2275678308653590,
-0.6140671213404080,0.1662941114081500,-0.7715360257302810,
-0.7535977994952050,0.5644302557976330,0.3369107343736630,
0.6046201505721580,-0.7556729189381400,0.2517794930204040,
-0.5761191698601790,-0.6394532899960390,0.5091033215692650,
-0.8771756234198420,-0.0996725024517006,0.4697108876032420,
0.1777092608486050,-0.9423569168215250,-0.2835187117762620,
-0.9768429239415920,0.1642087829444060,-0.1371618662353210,
-0.1487223091187880,0.6561163072920720,0.7398601665691900,
0.8263922468011810,0.2709995685589460,0.4935940520992520,
0.0308686015665059,0.1530129849183750,0.9877419480227090,
0.4225700117384330,0.6462523317724860,0.6354467002495210,
0.7837589636894810,0.6201599634850410,0.0335187488821074,
0.0539036789368123,0.3663544585938050,-0.9289126999161520
};
auto pointshell
= new vnl_matrix_fixed<double, 3, 16>(coords);
// List sorted for each row [x,y,z]
// pointshell need [x...x
// y...y
// z...z]
int i=0;
for(int c =0; c < 16; c++)
{
for(int r=0; r<3; r++){
pointshell->put(r,c,coords[i++]);
}
}
return pointshell;
}
static vnl_matrix_fixed<double, 3, 22>* DistributePointShell3()
{
double coords[3*22] = {
-0.8173635684245140,-0.4833486694613540,0.3135137329404920,
-0.2868452120883920,-0.8216012153929990,0.4926370541957950,
-0.7664861123034300,0.2467518351336330,0.5929692837779680,
-0.6473847770633690,-0.2749696442612980,0.7108337676007140,
-0.8434413337089970,0.5359848183688930,-0.0364278886191929,
-0.6982955004575730,-0.6008181795242910,-0.3891026974897790,
-0.1840600867015900,-0.4748774851820570,-0.8605889021772050,
-0.5838330320870200,0.5227863025561340,-0.6211549504783510,
0.2399013062530760,-0.8837050331449780,0.4018865233524250,
0.2572284397529420,0.1068009420516400,-0.9604306786849050,
0.0228576846453402,0.6541700548957510,-0.7560020274644400,
0.2865351008629760,-0.2558878809381770,0.9232654159895800,
-0.9589554732993380,0.1841748711215180,0.2156015238272050,
-0.1416546797498710,-0.9826949020935590,-0.1193510833813020,
0.5319624136210260,0.8404508833828820,-0.1032390580905500,
-0.9539866018255820,-0.2464051857069770,-0.1708626582784740,
-0.5967074337720730,-0.2735711735415940,-0.7543865398376490,
-0.8579620414436700,0.0965216321209641,-0.5045638809650520,
0.4190874972849550,-0.7580966160880540,-0.4996550713194790,
-0.1112620377459570,-0.8350080959462270,-0.5388712635322760,
0.2732684357685670,-0.3457098692283190,-0.8976686740277500,
-0.5333383595673660,0.8405849409324210,0.0946950436486956
};
auto pointshell
= new vnl_matrix_fixed<double, 3, 22>();
// List sorted for each row [x,y,z]
// pointshell need [x...x
// y...y
// z...z]
int i=0;
for(int c =0; c < 22; c++)
{
for(int r=0; r<3; r++){
pointshell->put(r,c,coords[i++]);
}
}
return pointshell;
}
};
//Distributed Pointshell 15 - 30 - 45
template<> class ThreeLayerPointShell<15,30,45, vnl_matrix_fixed<double, 3, 15>,vnl_matrix_fixed<double, 3, 30>,vnl_matrix_fixed<double, 3, 45> >
{
public:
static vnl_matrix_fixed<double, 3, 15>* DistributePointShell1()
{
double coords[3*15] = {
-0.8262066830854160,-0.4726354124122490,0.3065913954417130,
-0.1648544111105980,-0.8594278487393920,-0.4839491666988980,
-0.0358642514967783,-0.3860637871945480,-0.9217746512470260,
-0.7684991573547760,0.6362727605963740,-0.0675723261999100,
0.1470231744209000,-0.2445782513554300,0.9584183142798970,
-0.4269215415769730,0.7783400701208900,0.4603528348796690,
0.3354375712062210,0.5671194195694440,-0.7522348036155240,
0.4782763791345030,0.8758625019989820,-0.0641606012602034,
0.9898549006984430,0.0293790674196844,0.1390113159452260,
-0.6942246846812260,0.1045517495672360,-0.7121243001342390,
-0.5002034766634700,0.0396563572397201,0.8649993383027830,
-0.3370551539814700,0.7499893159794020,-0.5691307838197430,
-0.8609008763099680,0.2402687527531810,0.4484647228257290,
-0.6557865116475140,-0.4999608118385060,-0.5656706088944040,
-0.0693103556967315,0.9875634181798020,-0.1411189911607090
};
auto pointshell
= new vnl_matrix_fixed<double, 3, 15>(coords);
// List sorted for each row [x,y,z]
// pointshell need [x...x
// y...y
// z...z]
int i=0;
for(int c =0; c < 15; c++)
{
for(int r=0; r<3; r++){
pointshell->put(r,c,coords[i++]);
}
}
return pointshell;
}
static vnl_matrix_fixed<double, 3, 30>* DistributePointShell2()
{
double coords[3*30] = {
0.2837014644823930,-0.2206420544708420,-0.9331830275189480,
0.6952056236193340,-0.1366087970901870,-0.7057104062188850,
-0.3982427056422320,-0.8946622247526970,-0.2024407345454680,
0.6912813662578750,0.2350369054844600,0.6832918305709010,
0.3004304980870820,0.2618613453462440,0.9171532868788080,
-0.8122424463478870,0.2721420733854360,-0.5159466060013130,
0.9419343376574850,0.3217426374876110,-0.0961320901898529,
0.7896221636664980,0.5657937790715650,0.2374325971945600,
0.4752045378048260,-0.5551457462701800,0.6826374203395420,
0.7035350948936570,-0.6486284012073840,0.2903783177169470,
-0.9657370911439440,0.2516454388878180,-0.0634542660172643,
0.4335627021602730,0.7069616605804370,-0.5587741885277380,
-0.8057237269560320,0.4981857033689590,0.3203440038128640,
0.9405564452144110,-0.0095010729465114,-0.3395044962566700,
0.1927525893653990,0.9455549503304530,-0.2622446857393060,
0.0977862568275677,-0.8610667582542970,-0.4990008875794600,
-0.9244603975979140,-0.1428771862175540,-0.3534955203841470,
-0.0587838438498267,0.9919184790835770,0.1124374962135020,
0.0413372764424745,-0.4921846796379190,0.8695087525183610,
-0.0416085831127836,0.5985263605884460,0.8000218256348350,
-0.0355639978656969,-0.0871145642116132,0.9955632851597270,
0.4117279464778380,0.2997527998928850,-0.8605976743203040,
-0.3489182251383090,0.9011702877335440,-0.2571928938998360,
-0.4466362970172200,0.1524928751735680,-0.8816246033363880,
0.7474002986676580,0.3366743112988240,-0.5727505579769920,
0.0459516120636567,-0.8054328299457180,0.5909030426342220,
-0.6709586581555420,-0.7177574233281400,0.1861149115559070,
0.4102749262480260,0.6499693688374480,0.6396986043952450,
0.4840608825017460,-0.5520432393197750,-0.6789207052027200,
0.4932109057185150,-0.8496377203461870,-0.1867049722028180
};
auto pointshell
= new vnl_matrix_fixed<double, 3, 30>(coords);
// List sorted for each row [x,y,z]
// pointshell need [x...x
// y...y
// z...z]
int i=0;
for(int c =0; c < 30; c++)
{
for(int r=0; r<3; r++){
pointshell->put(r,c,coords[i++]);
}
}
return pointshell;
}
static vnl_matrix_fixed<double, 3, 45>* DistributePointShell3()
{
double coords[3*45] = {
-0.5319244251302650,-0.0924062555950406,-0.8417348097095310,
-0.1568078023044440,-0.3505682049930730,0.9233164391390330,
-0.0268033601770698,0.1671912039337100,0.9855600850330810,
-0.8635644949706830,0.4302558439150240,-0.2629377717312540,
-0.1232991287092530,-0.6582015219317060,0.7426762965022680,
0.2376788616301610,0.5073218686335690,0.8283316246168160,
-0.2566320540992200,0.7153437906464810,0.6499409588511380,
-0.2043674419674510,0.6455892128571940,-0.7358318536908470,
0.4526173742466210,0.8360898783655450,-0.3099858510073980,
0.6836009409422150,-0.5146343588192300,0.5175337962545400,
-0.2416560443524480,-0.0050416195905518,-0.9703488745290690,
0.6217071536966980,0.1629149642421430,-0.7661193963530300,
0.3925487362456630,0.8090879125984540,0.4373582505898420,
0.9937673576390050,0.0621775579881003,-0.0925223766114162,
-0.6145262933579910,0.6346672434383510,0.4685668841030610,
0.8259615790179220,0.5617603544414460,-0.0470401335461508,
-0.9322660404149650,-0.3254138676429420,-0.1580691134746520,
0.1164156506796110,-0.9181409097759250,0.3787672980507660,
0.3168138266596370,-0.3901334055493560,0.8645374052704360,
0.2176339314862630,0.9758048396839600,-0.0209853929005879,
-0.8962471871878890,-0.2522993236544900,0.3648095814822890,
-0.6612497786305060,-0.6092040683197140,0.4377432277075390,
0.6864998437314790,-0.7035766895855040,-0.1835696228371040,
0.5089165208574290,0.4070575405636090,0.7584906943850230,
-0.8813116916999880,0.4680173236355270,0.0651880882519394,
-0.2012114505332470,-0.8431942495440670,0.4985352642593330,
0.5022346836643460,-0.7613661632799880,0.4099779115231480,
0.2920837705654530,0.0626526547841476,-0.9543383654767130,
0.9371632886212690,-0.1374669688206610,0.3206677454060930,
0.5505816317240350,0.4677412077906900,-0.6914318689087190,
-0.7167807102053720,0.3777968874482810,0.5860844011845660,
-0.2932320783275170,0.9560381526252190,-0.0024492784000661,
0.6321152281530360,0.6671359233891630,0.3941573265343710,
0.8208025699405450,0.0279728493062268,-0.5705266522088930,
-0.2446598581934500,0.4624912733458210,0.8521991409686590,
0.5981132830055560,-0.3201976866112960,0.7346658711149490,
0.5635872282435520,-0.8205568040328310,0.0951628473521853,
0.8170510623081950,0.3573123713720030,0.4524990948560730,
-0.1077825148871900,-0.7347609483441290,-0.6697083531456270,
-0.9500761846368700,0.2288974134306240,0.2120406034480560,
-0.2525195159846320,0.9165943360942510,0.3099818012187580,
-0.1132939165725980,-0.9559551317814730,-0.2707660881430790,
0.6286490080714330,0.7713217806218580,0.0993133192936744,
0.8227143106676380,0.0339170261757165,0.5674423304249230,
-0.5076617466917020,0.3007946007639900,0.8073426528415060
};
auto pointshell
= new vnl_matrix_fixed<double, 3, 45>();
// List sorted for each row [x,y,z]
// pointshell need [x...x
// y...y
// z...z]
int i=0;
for(int c =0; c < 45; c++)
{
for(int r=0; r<3; r++){
pointshell->put(r,c,coords[i++]);
}
}
return pointshell;
}
};
//Distributed Pointshell 22 - 46 - 67
template<> class ThreeLayerPointShell<22,46,67, vnl_matrix_fixed<double, 3, 22>,vnl_matrix_fixed<double, 3, 46>,vnl_matrix_fixed<double, 3, 67> >
{
public:
static vnl_matrix_fixed<double, 3, 22>* DistributePointShell1()
{
double coords[3*22] = {
0.25642497332897700,0.69733994966702500,-0.66930055106179500,
-0.63587617425647900,0.60181880252846700,-0.48319314971980300,
0.02750479511080110,-0.49812287900990700,-0.86667011235694100,
-0.35667911834084000,-0.89655924253456900,0.26260527634729500,
-0.97064232445283100,-0.10849397816068500,0.21466842963899700,
0.13668042906880200,-0.37888572303413600,0.91529452592620000,
0.51081097493717800,0.82410825259274000,0.24478099577432200,
0.56937377655062700,-0.82148556938178300,-0.03122437948083380,
-0.70712711556887700,0.17758768051548200,-0.68442228058149100,
0.77448769645207600,-0.17248893945546000,-0.60861841395893200,
-0.10740168736203100,0.99190238197584200,0.06778305232459120,
0.33092898900280500,0.01295617559776370,-0.94356671293102500,
0.96250467033690100,-0.16189196397475400,0.21765971510605600,
-0.45033217736158200,0.66660174976094400,0.59400592358024700,
-0.85650276118059000,-0.36171210207403600,-0.36819475186809100,
0.27465477100258400,0.05835151655784800,0.95977073162340000,
0.11563788475332800,0.85791228608919200,0.50061401197628500,
-0.54693056940441200,-0.44061696250608900,-0.71184523922189100,
-0.84737370301991400,0.46653338404151400,0.25358314022247300,
0.81343236730821000,0.56190972107245100,-0.15028389527703900,
-0.18653146496488500,0.84209830314271900,-0.50603997907498000,
-0.63212021995023600,-0.37635030041830100,0.67733631152118100,
};
auto pointshell
= new vnl_matrix_fixed<double, 3, 22>(coords);
// List sorted for each row [x,y,z]
// pointshell need [x...x
// y...y
// z...z]
int i=0;
for(int c =0; c < 22; c++)
{
for(int r=0; r<3; r++){
pointshell->put(r,c,coords[i++]);
}
}
return pointshell;
}
static vnl_matrix_fixed<double, 3, 46>* DistributePointShell2()
{
double coords[3*46] = {
-0.23824007219091700,-0.86075578881685600,0.44982345428038400,
-0.51769500181405200,-0.84172584112854800,0.15326282482449900,
0.44541900890312100,0.24566021345088800,0.86096049040302900,
-0.07063199679231950,-0.74435681728880700,-0.66403618093053200,
0.28462319785348100,0.44431638677441600,-0.84945428581377100,
-0.64536739671188300,-0.00105803610891677,-0.76387158856768400,
0.99957798463419400,-0.02741827295649930,0.00959640259292167,
0.25010658086046200,-0.76013925657241700,-0.59969576355667200,
0.39532812932947400,-0.74907082575728600,0.53160941315984400,
-0.34325878056226200,-0.92866133182164700,-0.14057574593845400,
-0.26920408631492800,0.17274923523146300,0.94746338274272500,
-0.54467024543405600,0.38808975702695900,-0.74345185737178700,
0.52496025794034400,0.62807129953803100,-0.57440679860166600,
-0.78050768202914100,-0.24385280423360000,-0.57562450274541400,
-0.71694800106757700,-0.61231043102019300,0.33325890810159900,
-0.79056173292908700,0.40623831712611600,-0.45823855809687000,
-0.01131173053347560,-0.71410951594821100,0.69994260049274700,
0.51711028616473900,-0.41981678757221700,-0.74588927919307400,
0.09293538971980670,0.99313719503650500,-0.07100369830262170,
0.06305806394427750,0.10620573522794300,0.99234269402071500,
-0.33630459418638300,0.16690245213556600,-0.92684561357340800,
-0.91315571223437600,0.04840489638883500,-0.40472658822878600,
0.93648363925049100,-0.29927660444831100,-0.18284394287491200,
-0.05612562081659480,-0.20305248576816200,0.97755797920702400,
-0.37275429556215800,0.89636189167834400,0.23997832045161700,
-0.67013076748237900,0.05267398640468540,0.74037166722512800,
-0.71746069173368600,-0.55944913994429100,-0.41505037722258700,
0.32124017988313500,-0.93693212076753000,0.13770601984920100,
0.28299823115899100,-0.54968353921141900,0.78597710391644900,
0.15427673771645000,0.42717011000338400,0.89091210863881800,
0.73177570493927800,-0.66613283838403200,-0.14412272300735500,
-0.75153823442269900,-0.65477491803088400,-0.08037467834125450,
0.48366214065856300,0.15108779957940700,-0.86211565959088600,
0.93951136227144300,0.29289842100589400,0.17756383397277200,
-0.87960856796377400,0.45546435899697500,-0.13726246700461500,
-0.64569564311752200,0.72655108088168600,-0.23494821414239600,
-0.78338372249755100,-0.28544299520279600,0.55211614703387900,
-0.21774715968345700,0.47658876151730000,0.85173313123606500,
-0.02304329061227880,-0.94618817341094000,-0.32279551926107200,
-0.57374791604915700,0.69666566365718000,0.43066260797792600,
-0.07108119393689040,0.93003463387864700,-0.36053161255944900,
0.76657473659095900,-0.39315791656506800,-0.50773026880688800,
-0.92597907090953600,-0.32929755574671300,0.18473191390972800,
0.91121096468807600,-0.03396316106949220,-0.41053755190286000,
-0.43706646286549800,-0.78947199903364200,-0.43093719934587400,
-0.40196779675371200,-0.59965623521593900,-0.69197853286038600,
};
auto pointshell
= new vnl_matrix_fixed<double, 3, 46>(coords);
// List sorted for each row [x,y,z]
// pointshell need [x...x
// y...y
// z...z]
int i=0;
for(int c =0; c < 46; c++)
{
for(int r=0; r<3; r++){
pointshell->put(r,c,coords[i++]);
}
}
return pointshell;
}
static vnl_matrix_fixed<double, 3, 67>* DistributePointShell3()
{
double coords[3*67] = {
0.56913096982886400,-0.78778656243185400,-0.23554674957098500,
-0.83141868259485000,-0.50643545944750500,-0.22861780255797400,
0.66520728747741500,0.16406099937578400,-0.72841145870363500,
0.89843444153226500,-0.32337141111972700,0.29706309891846700,
0.10682918210921600,-0.98310908722825000,0.14860702695065500,
0.47695410914339100,0.34004755151800200,-0.81048284403671700,
0.73195863370355600,-0.57860748500094100,-0.35979151858778900,
-0.34693446874899500,0.36681507780719100,-0.86318200461267500,
0.69155604307511300,0.71307629015228000,-0.11520609232567700,
0.46165051573275700,0.03834019742989470,0.88623294374826500,
-0.97397281635692200,0.09418099894164960,0.20617199721620300,
-0.29851857051594800,0.88978611904209300,-0.34520620709530000,
-0.35435497259052800,0.57535527165268900,0.73715592976101400,
0.81483656941218300,0.03423671864623110,-0.57867885069779600,
0.09093817184312330,-0.56161837808076500,0.82238375853597700,
-0.38426863203906100,-0.76843844817080100,0.51170300937524000,
-0.73642722235150800,0.67410491319471600,-0.05707461945896040,
-0.54419758869133900,-0.83725684681843000,-0.05338498776051840,
-0.21793670722020900,0.72064410859729600,-0.65816081651069200,
-0.86994783943189000,0.48926427520412000,0.06173512514583880,
0.10775852899571900,-0.66193658502334100,-0.74177358866187400,
0.64544044927716800,-0.27486614918135400,-0.71263961893168700,
-0.11695347642120100,0.01614429356247260,0.99300616621366600,
-0.76804280354387200,0.56311186828017900,-0.30498405815136400,
-0.89852079402656700,-0.17264968995044600,-0.40354983243941700,
0.15476743176759600,0.59389894762264400,-0.78951319309861900,
-0.08940325110166170,0.85346959988929000,0.51341669310343500,
-0.70606292132486000,-0.42769174553909800,-0.56440669904592900,
-0.07667441970353810,-0.38529704221355400,0.91960166519238700,
0.97761562873568900,0.05518196801914950,0.20303357568948200,
0.27057965262888700,0.90009485795734400,0.34149070011052800,
-0.07518696164793450,0.30024488370383200,0.95089427940640300,
0.13690225805945900,0.94909731680809600,-0.28367596825584700,
-0.50251469982969000,0.85107263931481100,-0.15216549893059300,
0.21156984762048800,0.24711360232026500,0.94560724781811200,
0.54655302079371500,0.64091673556772900,0.53898565243470900,
-0.55776925354389300,-0.75378730237748100,0.34741641091860700,
0.33541827007282600,-0.94032512320547200,-0.05729962277332840,
0.67560875362133500,-0.41311684917543700,0.61064497128657700,
0.89999152407210300,0.19323788395138500,-0.39073568662762600,
-0.98068938405211500,-0.19462539941972600,0.01921681316436500,
-0.83571217382768900,-0.43205465164452500,0.33898958761077700,
0.17146282600716700,-0.94464169246048600,-0.27973661212473500,
-0.54059787517480200,0.19148492705680600,-0.81919927982545100,
-0.11323347366714700,-0.98395720927995300,-0.13786366724876500,
-0.96778324010342800,0.25052610173143600,-0.02514502985004660,
-0.37464301489130600,0.81614231968582300,0.43994809399632100,
0.87643936365442000,-0.25855236763220800,-0.40620772398960400,
0.52679822663262800,-0.75204791987234000,0.39611558241554000,
-0.83302160989998000,0.19922527352743200,-0.51612429494024400,
-0.36881247628488900,-0.43365274990848600,-0.82214515131661200,
-0.68494199482737100,-0.50458868526765800,0.52558988044078300,
-0.47018702426243700,0.58505538166360200,-0.66078314340008000,
-0.37416836671127000,0.32358269311843500,0.86907552840178400,
-0.27722979680714700,-0.21344561523946000,0.93679485966636000,
-0.42391010237203500,-0.55511199435901700,0.71564718879185400,
0.14056187290120700,-0.12797911064355400,0.98176560701900200,
0.65560180621904000,0.70152916060800800,0.27936196680821600,
0.31456644451092300,0.94702007926960300,-0.06481451571947000,
0.17066405874813200,0.60471657508100000,0.77794064225615400,
0.79129808311628700,0.03500830070119940,0.61042752439458600,
0.89399321972683600,0.44808044136416500,-0.00020285300027376,
0.62673064388188000,0.22888439553392000,0.74486282864731200,
0.04867785807210680,0.84066847580244300,-0.53935793303288600,
-0.61746764544761500,0.52381468179607700,0.58681503556082400,
0.28885209645735200,0.75743720323072100,0.58553680459405300,
-0.49988083572550200,0.08893492748180820,0.86151594805214000,
};
auto pointshell
= new vnl_matrix_fixed<double, 3, 67>();
// List sorted for each row [x,y,z]
// pointshell need [x...x
// y...y
// z...z]
int i=0;
for(int c =0; c < 67; c++)
{
for(int r=0; r<3; r++){
pointshell->put(r,c,coords[i++]);
}
}
return pointshell;
}
};
// Distributed Pointshell 30-60-90
template<> class ThreeLayerPointShell<30,60,90, vnl_matrix_fixed<double, 3, 30>,vnl_matrix_fixed<double, 3, 60>,vnl_matrix_fixed<double, 3, 90> >
{
public:
static vnl_matrix_fixed<double, 3, 30>* DistributePointShell1()
{
double coords[3*30] = {
-0.0384531292653293 ,0.0948025501623591 ,-0.9947531519590260,
0.5110816729083550,0.5146956026128700,0.6883923011395250,
-0.1446942037238470,0.9515456918526300,0.2713381354056610,
-0.4478957210732550,0.8874427193875220,-0.1087880639148770,
0.0234550198951957,-0.3332336016908820,-0.9425525071558810,
0.9229881949625620,0.3842551764058190,0.0209940792863651,
-0.6911807120917000,-0.6043864949901590,0.3962148254494260,
-0.0316674103891205,-0.6829866700288160,-0.7297440535435660,
0.8018580068378580,-0.1378458982057450,0.5813968053041460,
0.3973142766999960,0.4262411104325310,-0.8126868285555020,
-0.8315080441618440,0.3951380066705710,0.3904616859290430,
-0.8752414233521170,-0.2348057149272050,-0.4228696336769560,
-0.2818275522720080,-0.8725715270267310,-0.3989889234084150,
0.2217711399465410,0.7995959805053020,-0.5580894457401740,
-0.3678809968698430,-0.0344850464711680,0.9292332073876450,
0.6642059344014850,0.6635911630050780,0.3442052368680880,
-0.8248962619923230,0.5292990045320030,-0.1984659183651500,
-0.1835415051538410,0.8857989535243100,-0.4262308410017950,
-0.1166555399998580,-0.9878457938197680,0.1027237685247790,
-0.5153844228415700,-0.8501138123201320,0.1080990415997830,
0.5451858248749490,-0.3086757610614890,-0.7794175330902750,
-0.5671903126002800,0.6003393592309330,-0.5638153980254410,
-0.4890503721480340,-0.1375661511749660,-0.8613392406902020,
0.3976996460860260,-0.6740608343992310,-0.6224764919513510,
0.4349956952359570,-0.3316293950165250,0.8371383932702870,
0.6340600901853650,-0.7334511285536860,-0.2449841710344760,
0.9845956419603380,-0.1475029048111290,0.0938845828929696,
0.9610090220995200,0.0558414999946514,-0.2708198410782880,
-0.7632149908465080,-0.1335295186020360,0.6321967616249480,
0.0826215834627986,-0.6217188595585800,0.7788705499730220,
};
auto pointshell
= new vnl_matrix_fixed<double, 3, 30>(coords);
// List sorted for each row [x,y,z]
// pointshell need [x...x
// y...y
// z...z]
int i=0;
for(int c =0; c < 30; c++)
{
for(int r=0; r<3; r++){
pointshell->put(r,c,coords[i++]);
}
}
return pointshell;
}
static vnl_matrix_fixed<double, 3, 60>* DistributePointShell2()
{
double coords[3*60] = {
-0.9757323531821020,0.1141645636029930,0.1868497454401630,
-0.3081645385608390,-0.9413175847225490,0.1376801433239040,
0.2268128430936140,0.3605118823065700,-0.9047580433041550,
0.0053723381344127,-0.9527141369992010,0.3038205245615180,
0.4997098468405750,0.8591889901243150,0.1099288325223530,
0.2826871445408290,-0.5384236997311110,0.7938437490332800,
-0.9169656502561230,0.3927426788378230,0.0701939062145264,
-0.4122096064130160,-0.6082501787985420,0.6783177429290540,
0.8689901348066610,0.0966091330875035,-0.4853069348492570,
0.9016117108528340,-0.0311940714365313,0.4314200421401830,
0.0602430803117106,-0.3322121265937110,0.9412788504044060,
-0.7401273323624760,0.6637816179074090,-0.1077288058887970,
0.2609246136270950,0.8706803367668190,-0.4169341640729010,
-0.3416095796360020,0.1763315450422400,-0.9231522525152230,
0.2417187698627780,-0.7721496224459510,-0.5876708235505650,
0.0613208945746505,0.1158091933659950,0.9913768096039370,
0.6752331524032520,0.5192825815894980,0.5238375610371130,
0.1859160712558880,0.0545608595018432,-0.9810496047902950,
-0.8705635614786970,-0.3824245858905910,-0.3096296522168640,
-0.7511998187032470,-0.2098339818012360,-0.6258342691652840,
-0.3238272471878560,0.9093048344891080,0.2613438959560160,
0.0312467158098265,-0.9020995865833540,-0.4303951424415010,
0.1997844244448850,-0.2949296496204980,-0.9343996390859500,
0.0993378318350216,0.6282103369083360,-0.7716759473819500,
0.7029961904247910,-0.5712633600352550,0.4236207380776580,
0.6081885222938300,-0.0369636906278732,0.7929315272614730,
-0.8386908835040670,-0.4071869261928720,0.3616578618871240,
-0.6722483496885470,-0.0353283318457414,0.7394822954675930,
0.0999489360975153,-0.5914665380137460,-0.8001109576696270,
0.1502553918254090,0.7709976382621730,0.6188585937203620,
-0.2288419561759350,-0.9457701920389410,-0.2305430609326490,
0.2000892573988740,0.4465173368776440,0.8721161373012560,
0.6810481798116100,0.7159072717862530,-0.1537860688711920,
-0.9675337290891160,-0.1992515487286990,0.1554905251265250,
-0.6915973408017530,0.2529246583829880,0.6765517240963850,
0.4051983586769120,-0.6954173613750950,0.5934719737474010,
0.3828531024787670,0.6364092429998630,0.6696318222327270,
0.5431852686098420,0.7191354072485380,-0.4333520854994610,
-0.4766435443833670,-0.7756897459394560,-0.4136621201440160,
-0.2634864894153490,0.9592084977706880,-0.1024398735848210,
-0.7706589629193440,0.6046810772525520,0.2011108094677480,
-0.5074055034405280,0.8063323635715170,-0.3039206714513410,
-0.5457935890943380,0.8354998025106060,0.0636351955151979,
0.3190257966006890,0.1393790695388820,0.9374412067312650,
-0.4883735140357740,-0.2538251441534990,0.8349036513178050,
0.7814334110960810,-0.3206898482390990,0.5352754853896490,
0.5674042808667500,-0.3889648144620360,0.7257814789346710,
0.7365968935987790,0.6532051494950900,0.1753512161740710,
0.5454313517376770,-0.7269270773618580,-0.4172309489236830,
0.9213613541912860,-0.2944856448350440,0.2537153128782090,
0.8605683113688990,0.5039629381095560,-0.0737803393843139,
0.9884254663736010,0.0653918314621231,0.1368904883553190,
-0.6908004715469640,0.4998012720691420,0.5224877002844740,
0.6727955231552780,0.3943331152249490,-0.6259772985174470,
-0.4586010376503450,0.1473697927994620,0.8763373964611290,
-0.0145240600324916,0.9964844905654110,0.0825088585714514,
0.5144395480682960,0.3368539248460700,0.7885945629403520,
0.4119578382931460,-0.5109788900305280,-0.7544476876576700,
-0.1166393819714400,0.8099047244599660,-0.5748474509561170,
0.8653655945438620,-0.2118053715810700,-0.4541815411805620,
};
auto pointshell
= new vnl_matrix_fixed<double, 3, 60>(coords);
// List sorted for each row [x,y,z]
// pointshell need [x...x
// y...y
// z...z]
int i=0;
for(int c =0; c < 60; c++)
{
for(int r=0; r<3; r++){
pointshell->put(r,c,coords[i++]);
}
}
return pointshell;
}
static vnl_matrix_fixed<double, 3, 90>* DistributePointShell3()
{
double coords[3*90] = {
0.7830306271444820,0.5716685391117410,-0.2450675791359720,
-0.3870553382696590,0.9200004222080310,0.0615417602445897,
0.9237963183374240,-0.2584997104179900,-0.2824504592668160,
-0.5842983723039450,-0.7712899205183550,-0.2524029925134570,
0.3359998847225240,0.7641041306124860,0.5506804473080420,
-0.9783788169663750,-0.2066075720365220,-0.0093915754081947,
-0.0445468908163855,-0.8801917861335100,0.4725230091135180,
0.8775085322085220,-0.2202272889989130,0.4260031890507770,
-0.5808389302765810,0.4437425367947590,0.6824358564100420,
0.5331596759297140,0.4366496520639920,-0.7246225509290440,
0.6151687893470670,-0.1325993633208080,-0.7771645703840200,
0.4011147552907920,0.8712537751236570,-0.2828848041531790,
0.7304993029031530,-0.0076263316203289,0.6828708571348050,
-0.5475051350669790,0.6162612183405430,0.5660920754123990,
0.8023122911715880,0.2709359026259910,-0.5318728458036140,
0.2336323077450560,-0.6929349377840680,0.6820975859625270,
0.1689148924284850,-0.9486250397707260,0.2675411987635920,
-0.8314637780782760,0.5554909857699080,0.0098868838455222,
-0.1011517806960660,-0.2148730146317450,0.9713896771353290,
0.3877486434569820,-0.3420676320990350,-0.8559443466531150,
-0.3648694025982520,0.8893842897839550,-0.2754376592499350,
0.1726950806932710,0.9829215274686680,0.0635742081586933,
-0.3959729941386110,-0.7643798871495520,0.5088504456460080,
-0.9617290799445310,0.1062410103220330,-0.2525668713723110,
-0.0327316740125812,-0.4982367497870410,-0.8664229790800670,
0.1706515883535990,-0.2008209194778680,0.9646496740747160,
0.2501225023053060,0.6910620770273610,-0.6781385843138260,
0.3654852701417630,0.4920313286800810,0.7901428281688790,
0.9153163381057960,-0.3852897569037580,0.1172510316442380,
-0.6881847644097410,0.7218125899083820,0.0734051434441835,
-0.6873457829778960,0.2458189841721520,-0.6834682155324220,
-0.3219850147738870,0.8095000604196670,-0.4909534626027350,
-0.5632523312637280,-0.5973559275989310,0.5708876483936170,
-0.9084685052242310,-0.3740631899713040,0.1864449112315510,
-0.7845198100635990,-0.3605738415896990,-0.5044949676448910,
-0.2000039873810240,-0.6330205581036100,-0.7478525108936150,
-0.9148801969792540,0.0534543198667285,0.4001710395103400,
0.7664323664233560,-0.3341914416639150,-0.5485412546174510,
0.4872976306941970,-0.8343714235123850,-0.2576147254054740,
-0.6413753405832620,-0.2298206308844890,0.7319973702900570,
0.7054813742936480,-0.6006428992790810,-0.3761969405382820,
-0.1929691654472430,0.9760562116682670,0.1003851226546300,
-0.9439691512808960,-0.1047955385010510,-0.3129538888403490,
-0.4276451629474120,0.0186575235064224,-0.9037541211105420,
-0.7344812627593790,-0.4734265259198780,0.4862145608790640,
0.6377710213710160,0.3906960864871740,0.6637806055489840,
0.0474387462958210,0.9621772979130640,0.2682618361425920,
0.7913486901745450,-0.0748105169885527,-0.6067706626946760,
-0.0982434620561768,0.1155119940049920,0.9884357345848060,
-0.2883901942644810,0.3703318191063880,-0.8829979839215070,
0.3295292140825860,0.2147146585289090,-0.9194063913628870,
-0.5210574847572160,-0.0609880081835259,0.8513398618861260,
0.1729068266771900,0.9459249066560850,-0.2744618375222680,
-0.2062545956858610,0.4593595720405990,0.8639721206920620,
0.6720182971610780,-0.4607369705129640,0.5797524060176540,
-0.2554108625029320,0.6389014951165470,0.7256515491979250,
0.4500266667406290,-0.5361016246739610,0.7141925841425810,
-0.9983559681192810,-0.0042300087224308,0.0571617699762653,
-0.8406688842019840,-0.0901045876756096,-0.5340009273535010,
-0.3909575963129450,0.7939675140678560,0.4655832304648770,
-0.9713179118089640,0.2320449947116890,0.0519291308258172,
-0.0612195458720222,0.7850603547539780,0.6163865723689800,
-0.6242925102191230,-0.1774216962215860,-0.7607761848232110,
-0.0802679405745239,-0.4570324492769940,0.8858207482463910,
-0.3609460670444700,-0.2996972708558150,-0.8831191779860200,
0.1285945459353310,0.8707004556055770,0.4747042862287270,
0.5951730348219600,-0.7933110389121110,0.1281665095140040,
0.2033751954557950,0.0131770863036256,0.9790122033304090,
-0.2052893840274300,0.8803381043882250,0.4276226032002800,
-0.3731942266334910,-0.9275730588324440,-0.0182835919789316,
0.2685955896736170,0.5262799019911600,-0.8067749834793190,
0.9390948774123210,0.2816262184669510,0.1969453840280110,
-0.9130820847807490,-0.2162790214867180,0.3456942164936930,
-0.7722185508796150,-0.6352920195758570,0.0090862280741177,
0.1460103850487270,0.2737759341802480,0.9506459410956610,
-0.7668676175868570,-0.5322707367226740,-0.3586110984414160,
0.5327000875787680,-0.1961334068751380,0.8232632042069670,
-0.8210993253048930,0.4385794796816200,-0.3652997919326650,
-0.6255762780977020,-0.7798597751409450,-0.0217497447925055,
0.2991048825976350,-0.1334972919760040,-0.9448358281952090,
0.0606298744362150,-0.9937831824740320,0.0933756100790349,
0.8564420120030050,-0.4610622959465800,-0.2322254063032560,
-0.5455890340730230,-0.6468991032576630,-0.5327796506096080,
-0.8522969529983180,-0.5007967009121140,-0.1509720777671300,
-0.0228411934161264,-0.7512799112567760,0.6595883373933590,
0.5854881600260220,0.7616691389056020,-0.2776035614111240,
-0.1213541141003080,0.4896966102871260,-0.8634062826179960,
0.5356517245344040,-0.7170045054372250,0.4460737261776780,
-0.3912157018163170,-0.8815613582567070,-0.2641966053547140,
-0.6919685152992150,0.6644155090244570,-0.2823678544069240,
};
auto pointshell
= new vnl_matrix_fixed<double, 3, 90>(coords);
// List sorted for each row [x,y,z]
// pointshell need [x...x
// y...y
// z...z]
int i=0;
for(int c =0; c < 90; c++)
{
for(int r=0; r<3; r++){
pointshell->put(r,c,coords[i++]);
}
}
return pointshell;
}
};
// Optimal PointDistribution For Multishell Scheme 50 - 100 - 150
// Generated by Emmanuel Caruyer
template<> class ThreeLayerPointShell<50,100,150, vnl_matrix_fixed<double, 3, 50>,vnl_matrix_fixed<double, 3, 100>,vnl_matrix_fixed<double, 3, 150> >
{
public:
static vnl_matrix_fixed<double, 3, 50>* DistributePointShell1()
{
double coords[3*50] = {
0.913310030405731,-0.305436511654557,-0.269394368368340,
0.274520611983463,-0.931497424367645,-0.238644048726690,
0.724295307031846,-0.291296816682609,-0.624933974754310,
0.179546279617146,0.559467539325302,-0.809171926055848,
0.333306860790720,0.932650091766363,0.138095412226576,
-0.423224047088266,0.854335111704236,-0.301650332132319,
-0.057337449880758,-0.311676405763001,-0.948456764924911,
-0.167285210491163,0.516195511070583,0.839974911947675,
0.763325168891534,0.512093536284904,-0.393820894102804,
0.457619183693223,-0.672231259407514,0.581970632069466,
-0.246793802164352,-0.050216662420050,-0.967766038889902,
0.927994874653326,0.242210812920042,-0.283124415622830,
0.613792300977422,0.763214386431347,0.201898022786412,
0.720951430921191,-0.550579081664088,-0.420822657525251,
-0.566617724460163,-0.603447657535153,-0.561066198360694,
0.575968738378302,-0.783648913166458,-0.232710965156210,
-0.532150073708023,-0.619733926203769,0.576841537828723,
-0.911227494753416,-0.409216343893830,-0.046972722888692,
0.243129633174557,0.820980315213879,-0.516603623200345,
0.429059425848317,0.332137825141317,-0.839995520345857,
-0.862659530206915,0.023610632091113,0.505233681572638,
0.837291268298631,-0.163164674031590,0.521843483411485,
0.803588479073049,0.456397841392963,0.382029536388100,
0.303630079812031,0.840160692576492,0.449375995445604,
0.558311152322438,-0.044011396373360,-0.828463429598227,
0.238930415896487,-0.057120162540996,-0.969355220438215,
0.246985899213630,-0.326331770359038,0.912417416122670,
0.837050631211904,-0.547095262685976,0.005745810152941,
-0.554571420346131,0.053288087401785,-0.830428154313384,
0.751372177673996,-0.530499886791399,0.392440722570616,
0.204389904673926,0.615196807070163,0.761418186963024,
0.106700970850229,-0.867025439314806,0.486705034287282,
0.717231391359855,0.239339763160166,-0.654442976139587,
0.069544882069961,0.220289919002015,-0.972952137036535,
0.648780744604385,-0.754349357811800,0.100202753452702,
-0.727376323458570,-0.175112683983955,-0.663520332755394,
0.726060483848279,0.676802250037960,-0.121551997669954,
0.580156273414571,-0.371836855429485,0.724676514978945,
-0.060890718603115,0.804268669172008,0.591138078773718,
-0.386606299473394,0.736073310034347,0.555636258232458,
0.171832268210408,-0.620770257189966,0.764930035617617,
0.030029178348917,0.973024956515624,0.228737147060675,
0.197806050466708,-0.977284832169067,0.076073143822506,
0.941717594278340,-0.292439497987513,0.166274209195007,
0.103620708501302,0.975442422157789,-0.194357479466658,
-0.999930437744010,0.003907201094968,0.011128946611211,
-0.453284936431437,-0.867544703290094,0.204692340349242,
-0.939310554852217,-0.109134901287686,-0.325246452500478,
0.453912788215515,0.373549749748161,0.808964625405526,
0.446853673336740,-0.414239447718517,-0.792923372451158
};
auto pointshell
= new vnl_matrix_fixed<double, 3, 50>();
// List sorted for each row [x,y,z]
// pointshell need [x...x
// y...y
// z...z]
int i=0;
for(int c =0; c < 50; c++)
{
for(int r=0; r<3; r++){
pointshell->put(r,c,coords[i++]);
}
}
return pointshell;
}
static vnl_matrix_fixed<double, 3, 100>* DistributePointShell2()
{
double coords[3*100] = {
-0.6783406728914600,-0.6757825732021540,-0.2883952934037510,
-0.7868810762760640,0.3417432912343670,0.5138381989448860,
0.1812675472397420,0.9341812435603770,0.3073230881298610,
0.4392152776431420,0.8556891913232610,0.2736529695387940,
-0.6296241987663400,0.2128741188301860,0.7471666332620290,
0.6170474427091470,0.0980582575477010,-0.7807925662894150,
0.3935013484893500,0.9192019551005550,0.0149818048438275,
-0.3269299998796330,-0.4401580515926610,0.8362880274145110,
-0.2869929508839660,0.8309767335503890,0.4765634421992920,
0.5088992607891730,-0.7072946217461350,-0.4906687889169470,
0.5806843974003410,0.3583450335309360,-0.7310228912691540,
0.9491724956627390,-0.1834420594707910,0.2557744793650880,
0.0153560310858227,0.1752309003794950,0.9844076004691760,
-0.0479773456177447,0.9905464575577180,-0.1285141615828030,
0.0693843127112566,-0.5942844228507240,-0.8012564145806050,
-0.3165721030432440,-0.4164032785066600,-0.8522854059666170,
0.4896581521634270,0.7211168510820520,0.4901279232051600,
0.7776461071669160,-0.0320557656217032,-0.6278845115931320,
0.2300492326525960,0.8027977937856420,0.5500845869944510,
-0.3766021271868230,-0.7564724591162180,0.5347151170455350,
-0.1790056555604940,-0.2983809560973960,0.9375104161105410,
-0.5841988205464850,-0.8089448753434100,-0.0657261494972090,
-0.8551587253793000,0.4448943753338720,0.2660311057074570,
-0.7752975795230930,0.6190258715864510,0.1253819504245550,
-0.6764680634440770,-0.5064314530534920,0.5347131403830920,
0.7501893689724760,0.6048830482657770,-0.2670812771449510,
-0.5138286280086930,-0.4945630265573110,-0.7009904092076970,
0.5804145400895790,0.7956021922609330,-0.1735975613947330,
-0.1755232810907650,0.3977545839146920,0.9005458726627870,
0.0397560432054666,0.4921914390519250,-0.8695786590945290,
0.5538585716719580,-0.8081611673456340,0.2002903147434720,
0.8992305597521990,0.1140934067118160,-0.4223352873637700,
0.7698402757004470,0.6378303091348330,0.0227694237612964,
-0.4412960658520300,0.8971893864056890,0.0175780313033856,
-0.0811198993955311,0.2753962213738170,-0.9579021260938310,
-0.8572077886102190,-0.3790625619618600,0.3485776545690900,
0.6857756541322800,0.5415157578159610,0.4862843162558790,
0.8549241931498690,-0.2861863354061220,0.4326684705335710,
-0.4182775751481730,0.7970464185340600,-0.4356155149098700,
0.3499190445152290,0.8866592889390710,-0.3023110444949170,
-0.0132033510852791,-0.8749575867614390,-0.4840195170535130,
0.9116379197252770,-0.0091996476760664,0.4108913114214080,
-0.6490542475593910,-0.0530061128719349,-0.7588932307797450,
0.2036777677589340,-0.7982257583158190,0.5668782988277740,
0.3791318665509280,0.1705982429677800,-0.9094807679450480,
-0.1470179365181320,0.9220511216311460,-0.3580606868125770,
-0.3344979114418210,-0.6343147268032640,-0.6969619606560740,
-0.6076879381877640,0.5109764367904180,0.6079625406438060,
-0.5844013508588990,-0.7109052658706510,0.3912655927521240,
0.9862110505381910,-0.1637207304543020,0.0241513191330477,
-0.2051748270057740,0.7136488133907960,0.6697825479281010,
0.9069081158736650,-0.4209955960690930,0.0167444752950723,
-0.1319432828456750,0.9392959075033450,0.3167241201098720,
0.7549548594926640,-0.1430122887152190,0.6399926916808070,
0.2084074643614400,-0.1965342739298880,-0.9580921709153480,
-0.4579812060622150,-0.5603838600979070,0.6900892291838540,
-0.5044451924143650,-0.2283097986021220,-0.8327122454439420,
-0.1632507891313170,0.0595367888203028,-0.9847865507941140,
0.6304967444231040,-0.7732039721298140,-0.0680402289424677,
-0.4189905487906070,0.2950674433427220,0.8587095690065030,
-0.1064870135377420,-0.0503578524476393,0.9930380670672570,
-0.9594694024759230,-0.2706424081220130,-0.0785566842376365,
0.6572248348109010,-0.6577047684772120,0.3680760166461810,
0.8938413333977800,-0.1605095289995250,-0.4186697526810690,
0.9676575561375490,0.2066292219530930,-0.1447177207012450,
0.8845432302365500,0.4553528053106210,-0.1011785379338700,
0.3127824838603270,-0.9329319353982300,0.1783399049687880,
0.0538977574368990,0.9943600559842480,0.0913406306430770,
-0.8270410405970430,-0.3169506321051900,-0.4642686872666290,
-0.3836295436457290,0.5570493630789800,0.7365625433970090,
-0.4341709114900190,0.8573912849439030,0.2763617269416430,
-0.6794088494430530,-0.3329865853053170,-0.6538528498868610,
-0.3373613680825300,0.6537103259033100,-0.6773847629913670,
0.3577142489860180,-0.2395141136991300,0.9025926575212580,
0.0475306676831556,-0.6921666442661880,0.7201709326228570,
-0.9238533114270850,-0.2442810637733990,-0.2946554273162900,
-0.7702042751707540,0.6239784781621260,-0.1320463301238260,
-0.1058068553327490,-0.9342834914303710,0.3404691865723970,
-0.6712641876558270,0.6601081560713440,0.3371373795040410,
-0.9902933383503500,-0.0392378960032633,-0.1333397597723740,
0.2680611017833540,0.2096519795061000,0.9403134015847410,
-0.2193780563994170,0.9713963546921800,0.0908976922763060,
0.4259546539557210,-0.0086224931160314,0.9047034239937000,
-0.7126278602910880,0.4094408405402170,-0.5696663328955520,
-0.2175209712545230,0.4840278946263750,-0.8475857622022950,
0.5687366838665980,-0.5871979617261380,0.5759662647838790,
0.0944273658455115,0.8302981465345910,-0.5492617412861550,
0.2132739207069970,0.6628352636620030,-0.7177490146230690,
0.9572113632369580,-0.2441349912405500,-0.1553850447823740,
-0.8451592214984760,-0.4858715283504990,-0.2227885729889170,
-0.8457073503037060,0.4544256488253640,-0.2797792117580030,
-0.4568229734634650,0.4521433068383050,-0.7660804141846460,
0.2161513748810380,0.9712225012944180,-0.1000271768893380,
-0.9727568289959310,0.0233660996838811,0.2306473000651490,
0.0955550598977780,0.4497094877292240,0.8880487639618950,
-0.5803054956345510,0.2185728470394220,-0.7845198801008280,
0.0802960854964209,0.7085380275275620,0.7010894395163160,
-0.8170365471147090,-0.1054124160886850,-0.5668681532889450,
-0.7903491223400260,-0.2661789011279690,0.5518125201648250,
-0.4240807031724980,0.0532021972358502,0.9040603317290260
};
auto pointshell
= new vnl_matrix_fixed<double, 3, 100>();
// List sorted for each row [x,y,z]
// pointshell need [x...x
// y...y
// z...z]
int i=0;
for(int c =0; c < 100; c++)
{
for(int r=0; r<3; r++){
pointshell->put(r,c,coords[i++]);
}
}
return pointshell;
}
static vnl_matrix_fixed<double, 3, 150>* DistributePointShell3()
{
double coords[3*150] = {
-0.5818137157755120,-0.5030550053652260,0.6390840803153230,
0.9670851419246870,0.1662861674810110,0.1926012429165080,
0.0578846316476645,-0.7976809936025330,0.6002952622370840,
0.4660628327321890,-0.1511747542980830,0.8717405747173640,
0.6902368719591830,0.3748091607024440,-0.6189435787222700,
-0.1997955747625600,-0.1526408912355860,0.9678752433181160,
0.9511193914166630,0.1151598714233260,-0.2865486124289540,
0.0822444520102396,-0.5510970245321980,0.8303781787025070,
0.7452339673590670,0.4163359900238880,0.5208557163985940,
0.7753251365196900,0.6018341048080190,0.1914853596770620,
0.1116030335825260,-0.9761251513556840,-0.1863449805764000,
-0.3170679847245510,0.9480932422722550,-0.0242300850265728,
-0.1215812147248450,0.4013080511364970,-0.9078380121580370,
0.8680201958339400,-0.2937180126790240,-0.4003381928473620,
0.7117815464094280,-0.4555489837210150,-0.5346420799205320,
-0.4221584476961910,-0.8100472693071080,-0.4069467612929700,
0.0186640877956507,-0.9603335901627470,0.2782284087434000,
-0.5396677502633030,0.3145543091567380,0.7809060800868890,
-0.4898321413919820,-0.0679885797782780,0.8691616801718060,
-0.6750918694436950,0.2756900693390990,-0.6842849943399450,
-0.4765551297163720,-0.8680896906246820,-0.1389802049651460,
-0.8007926338965610,0.4138072508780090,-0.4330066011249610,
0.6252172011926140,0.2326499546399870,-0.7449680865237690,
0.6824097373557610,-0.7075614150231750,-0.1835042079420600,
-0.7485107920414520,-0.0179476036655747,-0.6628796857048340,
0.6619059872141820,-0.0443716919725870,-0.7482724216764290,
-0.0389254961022405,0.4513344326841560,0.8915054882763560,
0.6705154952625320,-0.7056948744571640,0.2289185767423150,
-0.0421968777730212,-0.3582833631874890,0.9326588096240070,
-0.0859685420644288,0.2858229400217130,0.9544184914033570,
0.9471108604678190,0.3162982815144110,-0.0541886989596281,
-0.5550008908723820,-0.7690560878042730,-0.3170595290194690,
-0.9104090909480310,-0.3561208782301570,0.2105545231234920,
-0.8278006128591360,-0.4943059810149400,0.2653445731174760,
0.9608962244735380,-0.0205957379787835,0.2761417414474080,
0.2202282819057040,-0.6075951351306100,-0.7631039612100540,
0.6244544517901810,0.4795352369175020,0.6165246095606390,
-0.1883106968238980,-0.4391326823901580,0.8784654624505860,
-0.2302051549830810,-0.9409736043275990,0.2481416179884810,
-0.0791847103092564,-0.9956294659870780,0.0495151301272986,
0.3432876609136320,-0.1606450217698800,-0.9253900576756810,
0.6910132782044240,0.7150303514681560,0.1059822901455680,
-0.3743211784491260,-0.1177211051182680,-0.9197963887590500,
-0.0638117734968980,-0.6201179359188230,0.7819090759896310,
-0.6081942748353220,0.4670488067500740,-0.6418451029421870,
-0.9237110100984830,0.0253860825460826,0.3822479779355320,
-0.9551685142832210,0.2944878574922000,-0.0304960835458829,
0.2047274908347290,-0.2027142615186940,0.9575978188537430,
0.4664286040672840,0.4413500991724570,-0.7665862295060520,
0.2436221916378790,0.7468678862924580,-0.6187378994102360,
0.7739427622698460,-0.5762620863418250,0.2625540107769950,
-0.8824775950813450,-0.1623522085699230,-0.4414465477857010,
-0.5674249283656180,-0.3593537766554100,-0.7408736828048120,
0.6114933730446530,0.6602715260117740,0.4360245023626030,
0.6580967800369840,-0.1033246068935280,0.7458100654424360,
-0.0651725243592964,-0.5903861242505850,-0.8044854046911040,
0.6288524174560490,0.2026776272049530,0.7506440011684980,
-0.5594322362469380,0.7479956050065880,0.3571248352307300,
0.5065956414163710,-0.4948790783785480,-0.7060138482219270,
-0.7796248885518470,0.2823581769849720,-0.5589802259832120,
0.1069521912958730,-0.0945188164394620,-0.9897612955232660,
-0.1677987609066020,-0.9702091453514290,-0.1747506512567480,
0.6497726089471500,0.7581321700271420,-0.0550560571776502,
-0.7436099555683260,-0.5675313008756160,-0.3534861475448520,
0.8705569853960000,-0.4718161643221160,0.1397141448193180,
-0.7367938401263080,0.6760868762135980,-0.0064321818744716,
-0.8709771462534060,-0.3550310615284370,-0.3396347391746950,
-0.5568793244548770,0.8296552833726470,-0.0394655389742952,
0.8255863288934740,-0.1743226461918030,-0.5366738567965490,
0.5123909885019620,-0.8475608044158260,-0.1381888480304350,
0.3892383734256480,0.6628221159035160,-0.6396564166192190,
-0.3850734793456500,-0.5125887952201850,-0.7674445533843810,
-0.0303214011502939,0.1349348899639910,-0.9903904220572250,
-0.1951010042782680,-0.3408158110301630,-0.9196630801991900,
-0.7299481699543050,0.1633700135838910,0.6636911238233930,
-0.3764204298254850,-0.8272654006443230,0.4170606873187450,
-0.0207934145254701,-0.9354136997804840,-0.3529431174783800,
0.0530508631426718,0.0286917551417508,0.9981795375115150,
-0.9893103145653900,-0.1443535615447680,-0.0206676259852998,
0.3520785503091250,-0.7515903016454040,0.5578106424986840,
0.4646561319602880,-0.5645009731359150,0.6822267440963500,
-0.3638080873049480,-0.7397671945737120,-0.5660284210567990,
0.8993857269815550,-0.3263912150460360,0.2908162458368350,
-0.1700781261443220,0.9625883335514640,-0.2109434310848530,
-0.3098321331013300,-0.2959672665364290,0.9035526694315240,
0.3772438334691890,0.2858348804818840,0.8809003980072750,
0.4170539029542560,-0.8070208930488820,-0.4180709511712160,
0.3535382771055950,0.9267047409094850,-0.1273931308865980,
0.0162686253194627,0.8954558957620720,-0.4448528639619620,
-0.4409570938666000,0.8843580437434560,-0.1531916833087520,
0.1659388260557630,0.8826574008153690,0.4397501777067190,
-0.6722877318211110,0.5534153014066750,-0.4916916816581130,
-0.5022690191279730,-0.7127108731518800,0.4896621730492420,
-0.2994694405516180,0.9013048000637180,-0.3129979417788570,
-0.3172838107693270,-0.5624673796012650,0.7635191093274480,
0.7315837873258040,0.0963804929381182,-0.6749044100485910,
-0.2068469360516820,0.7944607239234560,0.5710048188842610,
0.5378470897916880,-0.7741067897070790,0.3338849893780950,
0.1257284809109600,-0.8835082232405290,-0.4512267374105670,
0.3130995324769140,-0.4640943924714670,-0.8286042949679160,
0.9894576229982930,0.0690358063959267,-0.1273093465768750,
-0.0845800025595276,-0.7421395656655050,0.6648872748375060,
0.5451534912742490,-0.6927392692238080,0.4721440202170950,
-0.5063313485711320,0.1671271448910190,0.8459888196038490,
0.9140701463180970,0.3632958280951350,0.1802551216988890,
0.8112330574743470,0.5738372376167550,-0.1123020533436160,
0.8691548124260960,0.2553703834185790,-0.4235042848770290,
0.2587208365075750,-0.8528680460626400,0.4535191558932370,
-0.7810165842314370,-0.4032429479626940,0.4768733794979690,
0.6386218421663880,-0.3771596505315350,-0.6707553508686590,
0.6209847697030420,-0.6181456007191380,-0.4819480595545900,
0.1495129959273720,0.1671684875068860,0.9745258133233210,
0.8500517134843810,0.5236094820204760,0.0569666107515227,
0.2831566624639810,-0.3165192184973970,-0.9053385492864280,
-0.9842250831135330,0.1106121936986040,-0.1380794277774220,
0.5302801835192860,0.0861689235342689,0.8434321807849740,
0.8470084161413430,-0.0276085553364133,0.5308620448458990,
-0.2172067203511410,-0.5051072452535100,-0.8352771464769700,
0.3204407112933310,0.0455278779726987,-0.9461738544649850,
-0.4935635772769070,0.6256485875038120,0.6041182335769260,
0.4980559918394660,0.2263222843527210,-0.8370892739715230,
0.2021779827202400,-0.7110486153559470,0.6734492778996520,
0.6602958653226490,0.7044162570524200,-0.2603979781758510,
0.4825507527225460,-0.3146110298685950,0.8174134027112130,
-0.8074813189441350,0.4434122850213180,0.3890494377947510,
0.7706009639641810,-0.5764170340352260,-0.2718778350868380,
0.9877213210351460,-0.1170482811531720,-0.1034712126713200,
0.9471546743930560,-0.1633313871864270,-0.2760812937073770,
0.9072494495203930,-0.1579003412593720,0.3898280628368310,
-0.3139240581363140,0.0802169066474812,-0.9460533460704720,
0.2464642940724080,0.9686222614596370,0.0320353921812441,
-0.3117655950297000,-0.9062547169400450,-0.2854901080242450,
0.0608632767228376,-0.7075111154985250,-0.7040764752444090,
-0.4607335862628370,-0.6188008149745030,-0.6362468969482480,
0.2190580158109430,0.7137403609578260,0.6652730889257150,
-0.0823847846664380,-0.8044875371365980,-0.5882283143876660,
-0.8295547427688960,-0.1162092353369240,0.5461999106298320,
-0.0852410700430401,0.9961766497246490,0.0191322377491922,
0.3131894593955590,-0.5541595443573950,0.7712454615238390,
-0.2053809775103630,-0.8866791538596230,0.4142689128907330,
-0.2803794157477670,0.8920364641234400,0.3544831870471280,
0.3607197436800900,-0.9212300461377630,-0.1456587402540090,
0.5099563266151200,0.8025819147395540,-0.3095267598741700,
0.3434662076553160,-0.3991341139236100,0.8501311212402990,
-0.8525024407450160,0.5081350695533460,0.1226309080689130,
-0.7808884875619300,-0.2500741633167730,-0.5724299807266000,
-0.5053813675827790,-0.8611316666645480,0.0551536577907309,
-0.9210719657807660,0.3672285791438610,0.1294975077471940,
0.6652607437466560,0.6063117536090580,-0.4356767153121150,
0.3394557649489950,-0.6705912128459400,-0.6596038272301810
};
auto pointshell
= new vnl_matrix_fixed<double, 3, 150>();
// List sorted for each row [x,y,z]
// pointshell need [x...x
// y...y
// z...z]
int i=0;
for(int c =0; c < 150; c++)
{
for(int r=0; r<3; r++){
pointshell->put(r,c,coords[i++]);
}
}
return pointshell;
}
};
}
#endif //__itkPointShell_txx__
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/mitkTeemDiffusionTensor3DReconstructionImageFilter.cpp b/Modules/DiffusionCore/Algorithms/Reconstruction/mitkTeemDiffusionTensor3DReconstructionImageFilter.cpp
index 4e32276..3fab7df 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/mitkTeemDiffusionTensor3DReconstructionImageFilter.cpp
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/mitkTeemDiffusionTensor3DReconstructionImageFilter.cpp
@@ -1,220 +1,220 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <cstdlib>
#include <ctime>
#include <iostream>
#include <fstream>
#include <itksys/SystemTools.hxx>
#include "mitkPixelType.h"
#include "itkImageRegionIterator.h"
#include "itkImageFileReader.h"
#include <mitkIOUtil.h>
#include <mitkLocaleSwitch.h>
#include <itkMersenneTwisterRandomVariateGenerator.h>
template< class D, class T >
mitk::TeemDiffusionTensor3DReconstructionImageFilter<D,T>
::TeemDiffusionTensor3DReconstructionImageFilter():
m_EstimateErrorImage(false),m_Sigma(-19191919),
m_EstimationMethod(TeemTensorEstimationMethodsLLS),
m_NumIterations(1),m_ConfidenceThreshold(-19191919.0),
m_ConfidenceFuzzyness(0.0),m_MinPlausibleValue(1.0)
{
}
template< class D, class T >
mitk::TeemDiffusionTensor3DReconstructionImageFilter<D,T>
::~TeemDiffusionTensor3DReconstructionImageFilter()
{
}
void file_replace(std::string filename, std::string what, std::string with)
{
ofstream myfile2;
std::locale C("C");
std::locale originalLocale2 = myfile2.getloc();
myfile2.imbue(C);
char filename2[512];
sprintf(filename2, "%s2",filename.c_str());
myfile2.open (filename2);
std::string line;
ifstream myfile (filename.c_str());
std::locale originalLocale = myfile.getloc();
myfile.imbue(C);
if (myfile.is_open())
{
while (! myfile.eof() )
{
getline (myfile,line);
itksys::SystemTools::ReplaceString(line,what.c_str(),with.c_str());
myfile2 << line << std::endl;
}
myfile.close();
}
myfile2.close();
itksys::SystemTools::RemoveFile(filename.c_str());
rename(filename2,filename.c_str());
myfile.imbue( originalLocale );
myfile2.imbue( originalLocale2 );
}
// do the work
template< class D, class T >
void
mitk::TeemDiffusionTensor3DReconstructionImageFilter<D,T>
::Update()
{
itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer randgen = itk::Statistics::MersenneTwisterRandomVariateGenerator::New();
randgen->SetSeed();
// save input image to nrrd file in temp-folder
char filename[512];
int random_integer = randgen->GetIntegerVariate();
sprintf( filename, "dwi_%d.nhdr",random_integer);
try
{
mitk::IOUtil::Save(m_Input, filename);
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.GetDescription() << std::endl;
}
file_replace(filename,"vector","list");
// build up correct command from input params
char command[4096];
sprintf( command, "tend estim -i %s -B kvp -o tensors_%d.nhdr -knownB0 true",
filename, random_integer);
//m_DiffusionImages;
if(m_EstimateErrorImage)
{
sprintf( command, "%s -ee error_image_%d.nhdr", command, random_integer);
}
if(m_Sigma != -19191919)
{
sprintf( command, "%s -sigma %f", command, m_Sigma);
}
switch(m_EstimationMethod)
{
case TeemTensorEstimationMethodsLLS:
sprintf( command, "%s -est lls", command);
break;
case TeemTensorEstimationMethodsMLE:
sprintf( command, "%s -est mle", command);
break;
case TeemTensorEstimationMethodsNLS:
sprintf( command, "%s -est nls", command);
break;
case TeemTensorEstimationMethodsWLS:
sprintf( command, "%s -est wls", command);
break;
}
sprintf( command, "%s -wlsi %d", command, m_NumIterations);
if(m_ConfidenceThreshold != -19191919.0)
{
sprintf( command, "%s -t %f", command, m_ConfidenceThreshold);
}
sprintf( command, "%s -soft %f", command, m_ConfidenceFuzzyness);
sprintf( command, "%s -mv %f", command, m_MinPlausibleValue);
// call tend estim command
std::cout << "Calling <" << command << ">" << std::endl;
int success = system(command);
if(!success)
{
MITK_ERROR << "system command could not be called!";
}
remove(filename);
sprintf( filename, "dwi_%d.raw", random_integer);
remove(filename);
// change kind from tensor to vector
sprintf( filename, "tensors_%d.nhdr", random_integer);
file_replace(filename,"3D-masked-symmetric-matrix","vector");
mitk::LocaleSwitch localeSwitch("C");
// read result as mitk::Image and provide it in m_Output
typedef itk::ImageFileReader<VectorImageType> FileReaderType;
typename FileReaderType::Pointer reader = FileReaderType::New();
reader->SetFileName(filename);
reader->Update();
typename VectorImageType::Pointer vecImage = reader->GetOutput();
remove(filename);
sprintf( filename, "tensors_%d.raw", random_integer);
remove(filename);
typename ItkTensorImageType::Pointer itkTensorImage = ItkTensorImageType::New();
itkTensorImage->SetSpacing( vecImage->GetSpacing() ); // Set the image spacing
itkTensorImage->SetOrigin( vecImage->GetOrigin() ); // Set the image origin
itkTensorImage->SetDirection( vecImage->GetDirection() ); // Set the image direction
itkTensorImage->SetLargestPossibleRegion( vecImage->GetLargestPossibleRegion() );
itkTensorImage->SetBufferedRegion( vecImage->GetLargestPossibleRegion() );
itkTensorImage->SetRequestedRegion( vecImage->GetLargestPossibleRegion() );
itkTensorImage->Allocate();
itk::ImageRegionIterator<VectorImageType> it(vecImage,
vecImage->GetLargestPossibleRegion());
itk::ImageRegionIterator<ItkTensorImageType> it2(itkTensorImage,
itkTensorImage->GetLargestPossibleRegion());
it2 = it2.Begin();
//#pragma omp parallel private (it)
{
for(it=it.Begin();!it.IsAtEnd(); ++it, ++it2)
{
//#pragma omp single nowait
{
VectorType vec = it.Get();
TensorType tensor;
for(int i=1;i<7;i++)
tensor[i-1] = vec[i] * vec[0];
it2.Set( tensor );
}
} // end for
} // end ompparallel
m_OutputItk = mitk::TensorImage::New();
m_OutputItk->InitializeByItk(itkTensorImage.GetPointer());
m_OutputItk->SetVolume( itkTensorImage->GetBufferPointer() );
// in case: read resulting error-image and provide it in m_ErrorImage
if(m_EstimateErrorImage)
{
// open error image here
}
}
diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/mitkTeemDiffusionTensor3DReconstructionImageFilter.h b/Modules/DiffusionCore/Algorithms/Reconstruction/mitkTeemDiffusionTensor3DReconstructionImageFilter.h
index d7bba0b..e903cc5 100644
--- a/Modules/DiffusionCore/Algorithms/Reconstruction/mitkTeemDiffusionTensor3DReconstructionImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/Reconstruction/mitkTeemDiffusionTensor3DReconstructionImageFilter.h
@@ -1,116 +1,116 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkTeemDiffusionTensor3DReconstructionImageFilter_h__
#define __mitkTeemDiffusionTensor3DReconstructionImageFilter_h__
#include "mitkImage.h"
#include "mitkTensorImage.h"
#include "itkDiffusionTensor3D.h"
namespace mitk
{
enum TeemTensorEstimationMethods{
TeemTensorEstimationMethodsLLS,
TeemTensorEstimationMethodsNLS,
TeemTensorEstimationMethodsWLS,
TeemTensorEstimationMethodsMLE,
};
template< class DiffusionImagePixelType = short,
class TTensorPixelType=float >
class TeemDiffusionTensor3DReconstructionImageFilter : public itk::Object
{
public:
typedef TTensorPixelType TensorPixelType;
typedef itk::Vector<TensorPixelType,7> VectorType;
typedef itk::Image<VectorType,3> VectorImageType;
typedef itk::DiffusionTensor3D<TensorPixelType> TensorType;
typedef itk::Image<TensorType,3 > ItkTensorImageType;
typedef itk::Vector<TensorPixelType,6> ItkTensorVectorType;
typedef itk::Image<ItkTensorVectorType,3> ItkTensorVectorImageType;
typedef DiffusionImagePixelType DiffusionPixelType;
typedef itk::VectorImage< DiffusionPixelType, 3 > DiffusionImageType;
mitkClassMacroItkParent( TeemDiffusionTensor3DReconstructionImageFilter,
itk::Object );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
itkGetMacro(Input,
mitk::Image::Pointer);
itkSetMacro(Input,
mitk::Image::Pointer);
itkGetMacro(EstimateErrorImage, bool);
itkSetMacro(EstimateErrorImage, bool);
itkGetMacro(Sigma, float);
itkSetMacro(Sigma, float);
itkGetMacro(EstimationMethod, TeemTensorEstimationMethods);
itkSetMacro(EstimationMethod, TeemTensorEstimationMethods);
itkGetMacro(NumIterations, int);
itkSetMacro(NumIterations, int);
itkGetMacro(ConfidenceThreshold, double);
itkSetMacro(ConfidenceThreshold, double);
itkGetMacro(ConfidenceFuzzyness, float);
itkSetMacro(ConfidenceFuzzyness, float);
itkGetMacro(MinPlausibleValue, double);
itkSetMacro(MinPlausibleValue, double);
itkGetMacro(Output, mitk::TensorImage::Pointer);
itkGetMacro(OutputItk, mitk::TensorImage::Pointer);
// do the work
virtual void Update();
protected:
TeemDiffusionTensor3DReconstructionImageFilter();
virtual ~TeemDiffusionTensor3DReconstructionImageFilter();
mitk::Image::Pointer m_Input;
bool m_EstimateErrorImage;
float m_Sigma;
TeemTensorEstimationMethods m_EstimationMethod;
int m_NumIterations;
double m_ConfidenceThreshold;
float m_ConfidenceFuzzyness;
double m_MinPlausibleValue;
mitk::TensorImage::Pointer m_Output;
mitk::TensorImage::Pointer m_OutputItk;
mitk::Image::Pointer m_ErrorImage;
};
}
#include "mitkTeemDiffusionTensor3DReconstructionImageFilter.cpp"
#endif
diff --git a/Modules/DiffusionCore/Algorithms/Registration/mitkDWIHeadMotionCorrectionFilter.cpp b/Modules/DiffusionCore/Algorithms/Registration/mitkDWIHeadMotionCorrectionFilter.cpp
index 28bb111..a417857 100644
--- a/Modules/DiffusionCore/Algorithms/Registration/mitkDWIHeadMotionCorrectionFilter.cpp
+++ b/Modules/DiffusionCore/Algorithms/Registration/mitkDWIHeadMotionCorrectionFilter.cpp
@@ -1,149 +1,149 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKDWIHEADMOTIONCORRECTIONFILTER_CPP
#define MITKDWIHEADMOTIONCORRECTIONFILTER_CPP
#include "mitkDWIHeadMotionCorrectionFilter.h"
#include "itkSplitDWImageFilter.h"
#include "itkB0ImageExtractionToSeparateImageFilter.h"
#include "mitkImageTimeSelector.h"
#include <itkExtractDwiChannelFilter.h>
#include <mitkMultiModalAffineDefaultRegistrationAlgorithm.h>
#include <mitkAlgorithmHelper.h>
#include <mitkMaskedAlgorithmHelper.h>
#include <mitkImageMappingHelper.h>
#include <mitkRegistrationHelper.h>
#include <mitkRegistrationWrapper.h>
#include <mitkRegistrationWrapperMapper3D.h>
#include <itkComposeImageFilter.h>
#include <mitkDiffusionPropertyHelper.h>
#include <mitkImageCast.h>
#include <mitkDiffusionImageCorrectionFilter.h>
#include <mitkImageWriteAccessor.h>
#include <mitkProperties.h>
#include <mitkBValueMapProperty.h>
#include <vector>
#include "mitkIOUtil.h"
#include <itkImage.h>
typedef mitk::DiffusionPropertyHelper DPH;
typedef itk::ExtractDwiChannelFilter< short > ExtractorType;
mitk::DWIHeadMotionCorrectionFilter::DWIHeadMotionCorrectionFilter()
{
}
mitk::Image::Pointer mitk::DWIHeadMotionCorrectionFilter::GetCorrectedImage() const
{
return m_CorrectedImage;
}
void mitk::DWIHeadMotionCorrectionFilter::UpdateOutputInformation()
{
Superclass::UpdateOutputInformation();
}
void mitk::DWIHeadMotionCorrectionFilter::GenerateData()
{
InputImageType::Pointer input = const_cast<InputImageType*>(this->GetInput(0));
if (!DPH::IsDiffusionWeightedImage(input))
mitkThrow() << "Input is not a diffusion-weighted image!";
ITKDiffusionImageType::Pointer itkVectorImagePointer = DPH::GetItkVectorImage(input);
int num_gradients = itkVectorImagePointer->GetVectorLength();
typedef itk::ComposeImageFilter < ITKDiffusionVolumeType > ComposeFilterType;
ComposeFilterType::Pointer composer = ComposeFilterType::New();
// Extract unweighted volumes
mitk::BValueMapProperty::BValueMap bval_map = DPH::GetBValueMap(input);
int first_unweighted_index = bval_map.begin()->second.front();
MITK_INFO << "Reference b-value: " << bval_map.begin()->first << " (volume " << first_unweighted_index << ")";
ExtractorType::Pointer filter = ExtractorType::New();
filter->SetInput( itkVectorImagePointer);
filter->SetChannelIndex(first_unweighted_index);
filter->Update();
mitk::Image::Pointer fixedImage = mitk::Image::New();
fixedImage->InitializeByItk( filter->GetOutput() );
fixedImage->SetImportChannel( filter->GetOutput()->GetBufferPointer() );
composer->SetInput(0, filter->GetOutput());
mitk::MultiModalAffineDefaultRegistrationAlgorithm< ITKDiffusionVolumeType >::Pointer algo = mitk::MultiModalAffineDefaultRegistrationAlgorithm< ITKDiffusionVolumeType >::New();
mitk::MITKAlgorithmHelper helper(algo);
typedef vnl_matrix_fixed< double, 3, 3> TransformMatrixType;
std::vector< TransformMatrixType > estimated_transforms;
std::vector< ITKDiffusionVolumeType::Pointer > registered_itk_images;
for (int i=0; i<num_gradients; ++i)
{
if (i==first_unweighted_index)
continue;
MITK_INFO << "Correcting volume " << i;
ExtractorType::Pointer filter = ExtractorType::New();
filter->SetInput( itkVectorImagePointer);
filter->SetChannelIndex(i);
filter->Update();
mitk::Image::Pointer movingImage = mitk::Image::New();
movingImage->InitializeByItk( filter->GetOutput() );
movingImage->SetImportChannel( filter->GetOutput()->GetBufferPointer() );
helper.SetData(movingImage, fixedImage);
mitk::MAPRegistrationWrapper::Pointer reg = helper.GetMITKRegistrationWrapper();
mitk::MITKRegistrationHelper::Affine3DTransformType::Pointer affine = mitk::MITKRegistrationHelper::getAffineMatrix(reg, false);
estimated_transforms.push_back(affine->GetMatrix().GetVnlMatrix());
mitk::Image::Pointer registered_mitk_image = mitk::ImageMappingHelper::map(movingImage, reg, false, 0, nullptr, false, 0, mitk::ImageMappingInterpolator::BSpline_3);
ITKDiffusionVolumeType::Pointer registered_itk_image = ITKDiffusionVolumeType::New();
mitk::CastToItkImage(registered_mitk_image, registered_itk_image);
registered_itk_images.push_back(registered_itk_image);
}
int i=1;
for (auto image : registered_itk_images)
{
composer->SetInput(i, image);
++i;
}
composer->Update();
m_CorrectedImage = mitk::GrabItkImageMemory( composer->GetOutput() );
DPH::CopyProperties(input, m_CorrectedImage, true);
typedef mitk::DiffusionImageCorrectionFilter CorrectionFilterType;
CorrectionFilterType::Pointer corrector = CorrectionFilterType::New();
corrector->SetImage( m_CorrectedImage );
corrector->CorrectDirections( estimated_transforms );
DPH::InitializeImage(m_CorrectedImage);
}
#endif // MITKDWIHEADMOTIONCORRECTIONFILTER_CPP
diff --git a/Modules/DiffusionCore/Algorithms/Registration/mitkDWIHeadMotionCorrectionFilter.h b/Modules/DiffusionCore/Algorithms/Registration/mitkDWIHeadMotionCorrectionFilter.h
index 67f635a..b4695a9 100644
--- a/Modules/DiffusionCore/Algorithms/Registration/mitkDWIHeadMotionCorrectionFilter.h
+++ b/Modules/DiffusionCore/Algorithms/Registration/mitkDWIHeadMotionCorrectionFilter.h
@@ -1,80 +1,80 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKDWIHEADMOTIONCORRECTIONFILTER_H
#define MITKDWIHEADMOTIONCORRECTIONFILTER_H
#include "mitkImageToImageFilter.h"
#include <itkAccumulateImageFilter.h>
#include <itkExtractImageFilter.h>
#include "mitkITKImageImport.h"
#include <itkVectorImage.h>
#include <MitkDiffusionCoreExports.h>
namespace mitk
{
/**
* @class DWIHeadMotionCorrectionFilter
*
* @brief Performs standard head-motion correction by using affine registration of the gradient images.
*
* (Head) motion correction is a essential pre-processing step before performing any further analysis of a diffusion-weighted
* images since all model fits ( tensor, ODF ) rely on an aligned diffusion-weighted dataset. The correction is done in two steps. First the
* unweighted images ( if multiple present ) are separately registered on the first one by means of rigid registration and normalized correlation
* as error metric. Second, the weighted gradient images are registered to the unweighted reference ( computed as average from the aligned images from first step )
* by an affine transformation using the MattesMutualInformation metric as optimizer guidance.
*
*/
class MITKDIFFUSIONCORE_EXPORT DWIHeadMotionCorrectionFilter
: public ImageToImageFilter
{
public:
// class macros
mitkClassMacro( DWIHeadMotionCorrectionFilter,
ImageToImageFilter )
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
// public typedefs
typedef short DiffusionPixelType;
typedef Superclass::InputImageType InputImageType;
typedef Superclass::OutputImageType OutputImageType;
typedef itk::VectorImage<DiffusionPixelType, 3> ITKDiffusionImageType;
typedef itk::Image<DiffusionPixelType, 3> ITKDiffusionVolumeType;
mitk::Image::Pointer GetCorrectedImage() const;
void UpdateOutputInformation() override;
protected:
DWIHeadMotionCorrectionFilter();
~DWIHeadMotionCorrectionFilter() override {}
mitk::Image::Pointer m_CorrectedImage;
void GenerateData() override;
};
} //end namespace mitk
#endif // MITKDWIHEADMOTIONCORRECTIONFILTER_H
diff --git a/Modules/DiffusionCore/Algorithms/Registration/mitkPyramidImageRegistrationMethod.cpp b/Modules/DiffusionCore/Algorithms/Registration/mitkPyramidImageRegistrationMethod.cpp
index 7850bcf..5a7f5f8 100644
--- a/Modules/DiffusionCore/Algorithms/Registration/mitkPyramidImageRegistrationMethod.cpp
+++ b/Modules/DiffusionCore/Algorithms/Registration/mitkPyramidImageRegistrationMethod.cpp
@@ -1,597 +1,597 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPyramidImageRegistrationMethod.h"
#include "mitkException.h"
#include "mitkImageAccessByItk.h"
mitk::PyramidImageRegistrationMethod::PyramidImageRegistrationMethod()
: m_FixedImage(nullptr),
m_MovingImage(nullptr),
m_CrossModalityRegistration(true),
m_UseAffineTransform(true),
m_UseWindowedSincInterpolator(false),
m_UseNearestNeighborInterpolator(false),
m_UseMask(false),
m_EstimatedParameters(nullptr),
m_InitialParameters(0),
m_Verbose(false)
{
}
mitk::PyramidImageRegistrationMethod::~PyramidImageRegistrationMethod()
{
if( m_EstimatedParameters != nullptr)
{
delete [] m_EstimatedParameters;
}
}
void mitk::PyramidImageRegistrationMethod::SetFixedImage(mitk::Image::Pointer fixed)
{
if( fixed.IsNotNull() )
{
m_FixedImage = fixed;
}
}
void mitk::PyramidImageRegistrationMethod::SetMovingImage(mitk::Image::Pointer moving)
{
if( moving.IsNotNull() )
{
m_MovingImage = moving;
}
}
void mitk::PyramidImageRegistrationMethod::SetFixedImageMask(mitk::Image::Pointer mask)
{
m_FixedImageMask = mask;
}
void mitk::PyramidImageRegistrationMethod::Update()
{
if( m_MovingImage.IsNull() )
{
mitkThrow() << " Moving image is null";
}
if( m_FixedImage.IsNull() )
{
mitkThrow() << " Moving image is null";
}
unsigned int allowedDimension = 3;
if( m_FixedImage->GetDimension() != allowedDimension ||
m_MovingImage->GetDimension() != allowedDimension )
{
mitkThrow() << " Only 3D Images supported.";
}
//
// One possibility: use the FixedDimesnionByItk, but this instantiates ALL possible
// pixel type combinations!
// AccessTwoImagesFixedDimensionByItk( m_FixedImage, m_MovingImage, RegisterTwoImages, 3);
// in helper: TypeSubset : short, float
AccessTwoImagesFixedDimensionTypeSubsetByItk( m_FixedImage, m_MovingImage, RegisterTwoImagesV4, 3);
}
mitk::PyramidImageRegistrationMethod::TransformMatrixType mitk::PyramidImageRegistrationMethod
::GetLastRotationMatrix()
{
TransformMatrixType output;
if( m_EstimatedParameters == nullptr )
{
output.set_identity();
return output;
}
typedef itk::MatrixOffsetTransformBase< double, 3, 3> BaseTransformType;
BaseTransformType::Pointer base_transform = BaseTransformType::New();
if( this->m_UseAffineTransform )
{
typedef itk::AffineTransform< double > TransformType;
TransformType::Pointer transform = TransformType::New();
TransformType::ParametersType affine_params( TransformType::ParametersDimension );
this->GetParameters( &affine_params[0] );
transform->SetParameters( affine_params );
base_transform = transform;
}
else
{
typedef itk::Euler3DTransform< double > RigidTransformType;
RigidTransformType::Pointer rtransform = RigidTransformType::New();
RigidTransformType::ParametersType rigid_params( RigidTransformType::ParametersDimension );
this->GetParameters( &rigid_params[0] );
rtransform->SetParameters( rigid_params );
base_transform = rtransform;
}
return base_transform->GetMatrix().GetVnlMatrix();
}
mitk::Image::Pointer mitk::PyramidImageRegistrationMethod
::GetResampledMovingImage()
{
mitk::Image::Pointer output = mitk::Image::New();
//output->Initialize( this->m_FixedImage );
AccessFixedDimensionByItk_1( this->m_MovingImage, ResampleMitkImage, 3, output );
return output;
}
mitk::Image::Pointer mitk::PyramidImageRegistrationMethod::GetResampledMovingImage(mitk::Image::Pointer movingImage, double* transform)
{
mitk::Image::Pointer output = mitk::Image::New();
unsigned int dim = 12;
if( !m_UseAffineTransform )
dim = 6;
if (m_EstimatedParameters == nullptr)
m_EstimatedParameters = new double[dim];
double tmpParams[12];
// save and set temporal transformation values
for( unsigned int i=0; i<dim; i++)
{
tmpParams[i] = m_EstimatedParameters[i];
m_EstimatedParameters[i] = transform[i];
}
AccessFixedDimensionByItk_1( movingImage, ResampleMitkImage, 3, output );
// Restore old values
for( unsigned int i=0; i<dim; i++)
{
m_EstimatedParameters[i] = tmpParams[i];
}
return output;
}
// ITK 4 Includes
#include <itkImageRegistrationMethodv4.h>
#include <itkGradientDescentLineSearchOptimizerv4.h>
#include <itkMattesMutualInformationImageToImageMetricv4.h>
#include <itkJointHistogramMutualInformationImageToImageMetricv4.h>
#include <itkCorrelationImageToImageMetricv4.h>
#include <itkOptimizerParameterScalesEstimator.h>
#include <itkRegistrationParameterScalesFromPhysicalShift.h>
template <typename TPixel1, unsigned int VImageDimension1, typename TPixel2, unsigned int VImageDimension2>
void mitk::PyramidImageRegistrationMethod::
RegisterTwoImagesV4(itk::Image<TPixel1, VImageDimension1>* itkImage1, itk::Image<TPixel2, VImageDimension2>* itkImage2)
{
// Basic typedefs needed
typedef typename itk::Image<TPixel1, VImageDimension1> ItkImageTypeFixed;
typedef typename itk::Image<TPixel2, VImageDimension1> ItkImageTypeMoving;
typedef itk::MatrixOffsetTransformBase< double, VImageDimension1, VImageDimension2 > BaseTransformType;
typedef itk::Image< double, 3> ItkRegistrationImageType;
typedef itk::CastImageFilter< ItkImageTypeFixed, ItkRegistrationImageType> FixedCastFilterType;
typedef itk::CastImageFilter< ItkImageTypeMoving, ItkRegistrationImageType> MovingCastFilterType;
typedef typename itk::ImageRegistrationMethodv4< ItkRegistrationImageType, ItkRegistrationImageType, AffineTransformType> RegistrationType;
typedef typename itk::MattesMutualInformationImageToImageMetricv4< ItkRegistrationImageType, ItkRegistrationImageType> MIMetricType;
typedef typename itk::CorrelationImageToImageMetricv4< ItkRegistrationImageType, ItkRegistrationImageType > NCMetricType;
typedef typename itk::ImageToImageMetricv4< ItkRegistrationImageType, ItkRegistrationImageType > BaseMetricType;
typedef typename itk::ImageRegistrationMethodv4< ItkRegistrationImageType, ItkRegistrationImageType, RigidTransformType> RigidRegistrationType;
typedef itk::GradientDescentLineSearchOptimizerv4 OptimizerType;
typename ItkImageTypeFixed::Pointer referenceImage = itkImage1;
typename ItkImageTypeMoving::Pointer movingImage = itkImage2;
// initial parameter dimension ( affine = default )
unsigned int paramDim = 12;
typename BaseTransformType::Pointer transform;
if( m_UseAffineTransform )
{
transform = AffineTransformType::New();
}
else
{
transform = RigidTransformType::New();
paramDim = 6;
}
typename BaseTransformType::ParametersType initialParams(paramDim);
initialParams.Fill(0);
if( m_UseAffineTransform )
{
initialParams[0] = initialParams[4] = initialParams[8] = 1;
}
// [Prepare registration]
// The ITKv4 Methods ( the MI Metric ) require double-type images so we need to perform cast first
typename FixedCastFilterType::Pointer caster_f = FixedCastFilterType::New();
typename MovingCastFilterType::Pointer caster_m = MovingCastFilterType::New();
try
{
caster_f->SetInput(0, referenceImage );
caster_m->SetInput(0, movingImage );
caster_f->Update();
caster_m->Update();
}
catch( const itk::ExceptionObject &/*e*/ )
{
return ;
}
// [Prepare Registration]
// Estimate the size of the pyramid based on image dimension
// here the image size on the topmost level must remain higher than the threshold
unsigned int max_pyramid_lvl = 4;
unsigned int max_schedule_val = 8;
const unsigned int min_required_image_size = 12;
typename ItkImageTypeFixed::RegionType::SizeType image_size = referenceImage->GetLargestPossibleRegion().GetSize();
unsigned int min_value = std::min( image_size[0], std::min( image_size[1], image_size[2]));
// Adapt also the optimizer settings to the number of levels
float optmaxstep = 10;
float optminstep = 0.1f;
unsigned int iterations = 40;
unsigned int convergence_win_size = 8;
double convergence_tolerance = 1e-5;
while( max_schedule_val > 1.0 && (min_value / max_schedule_val < min_required_image_size) )
{
max_schedule_val /= 2;
max_pyramid_lvl--;
optmaxstep -= 2;
optminstep *= 0.5f;
convergence_win_size += 4;
convergence_tolerance *= 0.5;
}
typename RegistrationType::ShrinkFactorsArrayType shrink_factors(max_pyramid_lvl);
shrink_factors.Fill(1);
shrink_factors[0] = max_schedule_val;
for( unsigned int i=1; i<max_pyramid_lvl; i++)
{
shrink_factors[i] = std::max(shrink_factors[i - 1] / 2, itk::SizeValueType(1));
}
if(m_Verbose)
{
MITK_INFO("dw.pyramid.reg") << " : Pyramid size set to : " << max_pyramid_lvl;
}
// [Prepare Registration]
// Initialize the optimizer
// (i) Use the scales estimator ( depends on metric )
typename OptimizerType::Pointer optimizer = OptimizerType::New();
typename BaseMetricType::Pointer base_metric;
if( m_CrossModalityRegistration )
{
typename MIMetricType::Pointer metric = MIMetricType::New();
typename itk::RegistrationParameterScalesFromPhysicalShift< MIMetricType >::Pointer mi_estimator =
itk::RegistrationParameterScalesFromPhysicalShift< MIMetricType >::New();
mi_estimator->SetMetric( metric );
optimizer->SetScalesEstimator( mi_estimator );
base_metric = metric;
}
else
{
typename NCMetricType::Pointer metric = NCMetricType::New();
typename itk::RegistrationParameterScalesFromPhysicalShift< NCMetricType >::Pointer nc_estimator =
itk::RegistrationParameterScalesFromPhysicalShift< NCMetricType >::New();
nc_estimator->SetMetric( metric );
optimizer->SetScalesEstimator( nc_estimator );
base_metric = metric;
}
optimizer->SetDoEstimateLearningRateOnce( false );
optimizer->SetDoEstimateLearningRateAtEachIteration( true );
optimizer->SetNumberOfIterations( iterations );
optimizer->SetConvergenceWindowSize( convergence_win_size );
optimizer->SetMaximumStepSizeInPhysicalUnits( optmaxstep );
optimizer->SetMinimumConvergenceValue( convergence_tolerance );
// line search options
optimizer->SetEpsilon( 1e-3 );
optimizer->SetLowerLimit( 0.3 );
optimizer->SetUpperLimit( 1.7 );
optimizer->SetMaximumLineSearchIterations( 20 );
// add observer tag if verbose
unsigned long vopt_tag = 0;
if(m_Verbose)
{
MITK_INFO << " :: Starting at " << initialParams;
OptimizerIterationCommandv4< OptimizerType >::Pointer iterationObserver =
OptimizerIterationCommandv4<OptimizerType>::New();
vopt_tag = optimizer->AddObserver( itk::IterationEvent(), iterationObserver );
}
// Initializing by Geometry
if( !m_UseAffineTransform && m_InitializeByGeometry )
{
typedef itk::CenteredVersorTransformInitializer< ItkImageTypeFixed, ItkImageTypeMoving> TransformInitializerType;
typename TransformInitializerType::TransformType::Pointer rigidTransform = TransformInitializerType::TransformType::New() ;
MITK_INFO << "Initializer starting at : " << rigidTransform->GetParameters();
typename TransformInitializerType::Pointer initializer = TransformInitializerType::New();
initializer->SetTransform( rigidTransform);
initializer->SetFixedImage( referenceImage.GetPointer() );
initializer->SetMovingImage( movingImage.GetPointer() );
initializer->MomentsOn();
initializer->InitializeTransform();
MITK_INFO << "Initialized Rigid position : " << rigidTransform->GetParameters();
initialParams[3] = rigidTransform->GetParameters()[3];
initialParams[4] = rigidTransform->GetParameters()[4];
initialParams[5] = rigidTransform->GetParameters()[5];
}
// [Prepare Registration]
// Masking (Optional)
if( m_UseMask )
{
typedef itk::Image<unsigned char, 3> BinaryImageType;
BinaryImageType::Pointer itkFixedImageMask = BinaryImageType::New();
itk::ImageMaskSpatialObject< 3 >::Pointer fixedMaskSpatialObject = itk::ImageMaskSpatialObject< 3 >::New();
CastToItkImage( m_FixedImageMask, itkFixedImageMask);
itk::NotImageFilter<BinaryImageType, BinaryImageType>::Pointer notFilter = itk::NotImageFilter<BinaryImageType, BinaryImageType>::New();
notFilter->SetInput(itkFixedImageMask);
notFilter->Update();
fixedMaskSpatialObject->SetImage( notFilter->GetOutput() );
base_metric->SetFixedImageMask( fixedMaskSpatialObject );
}
if( m_EstimatedParameters != nullptr)
{
delete [] m_EstimatedParameters;
}
m_EstimatedParameters = new double[paramDim];
//-----------------
//-----------------
// [Prepare Registration]
// combine all components to set-up registration
if( m_UseAffineTransform )
{
typename RegistrationType::Pointer registration = RegistrationType::New();
registration->SetFixedImage( 0, caster_f->GetOutput() );
registration->SetMovingImage( 0, caster_m->GetOutput() );
registration->SetMetric( base_metric );
registration->SetOptimizer( optimizer );
registration->SetMovingInitialTransform( transform.GetPointer() );
registration->SetNumberOfLevels(max_pyramid_lvl);
registration->SetShrinkFactorsPerLevel( shrink_factors );
// observe the pyramid level change in order to adapt parameters
typename PyramidOptControlCommandv4<RegistrationType>::Pointer pyramid_observer =
PyramidOptControlCommandv4<RegistrationType>::New();
unsigned int pyramid_tag = registration->AddObserver( itk::InitializeEvent(), pyramid_observer );
try
{
registration->Update();
}
catch( const itk::ExceptionObject &e)
{
registration->Print( std::cout );
MITK_ERROR << "[Registration Update] Caught ITK exception: ";
MITK_ERROR("itk.exception") << e.what();
mitkThrow() << "Registration failed with exception: " << e.what();
}
// [Post Registration]
// Retrieve the last transformation parameters from the performed registration task
typename BaseTransformType::ParametersType finalParameters = registration->GetOptimizer()->GetCurrentPosition();
for( unsigned int i=0; i<paramDim; i++)
{
m_EstimatedParameters[i] = finalParameters[i];
}
if( m_Verbose )
{
MITK_INFO("Params") << optimizer->GetValue() << " :: " << finalParameters;
}
if( pyramid_tag )
{
registration->RemoveObserver( pyramid_tag );
}
}
//-----------
//-----------
else
{
typename RigidRegistrationType::Pointer registration = RigidRegistrationType::New();
registration->SetFixedImage( 0, caster_f->GetOutput() );
registration->SetMovingImage( 0, caster_m->GetOutput() );
registration->SetMetric( base_metric );
registration->SetOptimizer( optimizer );
registration->SetMovingInitialTransform( transform.GetPointer() );
registration->SetNumberOfLevels(max_pyramid_lvl);
registration->SetShrinkFactorsPerLevel( shrink_factors );
// observe the pyramid level change in order to adapt parameters
typename PyramidOptControlCommandv4<RigidRegistrationType>::Pointer pyramid_observer =
PyramidOptControlCommandv4<RigidRegistrationType>::New();
unsigned int pyramid_tag = registration->AddObserver( itk::InitializeEvent(), pyramid_observer );
try
{
registration->Update();
}
catch( const itk::ExceptionObject &e)
{
registration->Print( std::cout );
MITK_ERROR << "[Registration Update] Caught ITK exception: ";
MITK_ERROR("itk.exception") << e.what();
mitkThrow() << "Registration failed with exception: " << e.what();
}
// [Post Registration]
// Retrieve the last transformation parameters from the performed registration task
typename BaseTransformType::ParametersType finalParameters = registration->GetOptimizer()->GetCurrentPosition();
for( unsigned int i=0; i<paramDim; i++)
{
m_EstimatedParameters[i] = finalParameters[i];
}
if( m_Verbose )
{
MITK_INFO("Params") << optimizer->GetValue() << " :: " << finalParameters;
}
if( pyramid_tag )
{
registration->RemoveObserver( pyramid_tag );
}
}
if( m_Verbose )
{
MITK_INFO("Termination") << optimizer->GetStopConditionDescription();
}
// remove optimizer tag if used
if( vopt_tag )
{
optimizer->RemoveObserver( vopt_tag );
}
}
template< typename TPixel, unsigned int VDimension>
void mitk::PyramidImageRegistrationMethod::
ResampleMitkImage( itk::Image<TPixel, VDimension>* itkImage,
mitk::Image::Pointer& outputImage )
{
typedef typename itk::Image< TPixel, VDimension> ImageType;
typedef typename itk::ResampleImageFilter< ImageType, ImageType, double> ResampleImageFilterType;
typedef itk::LinearInterpolateImageFunction< ImageType, double > InterpolatorType;
typename InterpolatorType::Pointer linear_interpolator = InterpolatorType::New();
typedef itk::NearestNeighborInterpolateImageFunction< ImageType, double > NearestNeighborInterpolatorType;
typename NearestNeighborInterpolatorType::Pointer nn_interpolator = NearestNeighborInterpolatorType::New();
typedef itk::WindowedSincInterpolateImageFunction< ImageType, 7> WindowedSincInterpolatorType;
typename WindowedSincInterpolatorType::Pointer sinc_interpolator = WindowedSincInterpolatorType::New();
typename ImageType::Pointer reference_image = ImageType::New();
CastToItkImage(m_FixedImage,reference_image);
typedef itk::MatrixOffsetTransformBase< double, 3, 3> BaseTransformType;
BaseTransformType::Pointer base_transform = BaseTransformType::New();
if( this->m_UseAffineTransform )
{
typedef itk::AffineTransform< double > TransformType;
TransformType::Pointer transform = TransformType::New();
TransformType::ParametersType affine_params( TransformType::ParametersDimension );
this->GetParameters( &affine_params[0] );
transform->SetParameters( affine_params );
base_transform = transform;
}
// Rigid
else
{
typedef itk::Euler3DTransform< double > RigidTransformType;
RigidTransformType::Pointer rtransform = RigidTransformType::New();
RigidTransformType::ParametersType rigid_params( RigidTransformType::ParametersDimension );
this->GetParameters( &rigid_params[0] );
rtransform->SetParameters( rigid_params );
base_transform = rtransform;
}
typename ResampleImageFilterType::Pointer resampler = ResampleImageFilterType::New();
resampler->SetInterpolator( linear_interpolator );
if( m_UseWindowedSincInterpolator )
resampler->SetInterpolator( sinc_interpolator );
if ( m_UseNearestNeighborInterpolator)
resampler->SetInterpolator ( nn_interpolator );
//resampler->SetNumberOfThreads(1);
resampler->SetInput( itkImage );
resampler->SetTransform( base_transform );
resampler->SetReferenceImage( reference_image );
resampler->UseReferenceImageOn();
resampler->Update();
mitk::GrabItkImageMemory( resampler->GetOutput(), outputImage);
}
diff --git a/Modules/DiffusionCore/Algorithms/Registration/mitkPyramidImageRegistrationMethod.h b/Modules/DiffusionCore/Algorithms/Registration/mitkPyramidImageRegistrationMethod.h
index 337947f..bccf9d0 100644
--- a/Modules/DiffusionCore/Algorithms/Registration/mitkPyramidImageRegistrationMethod.h
+++ b/Modules/DiffusionCore/Algorithms/Registration/mitkPyramidImageRegistrationMethod.h
@@ -1,343 +1,343 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKPYRAMIDIMAGEREGISTRATION_H
#define MITKPYRAMIDIMAGEREGISTRATION_H
#include <MitkDiffusionCoreExports.h>
#include <itkObject.h>
#include "itkImageMaskSpatialObject.h"
#include "itkNotImageFilter.h"
#include <itkCenteredVersorTransformInitializer.h>
#include <itkOptimizerParameters.h>
#include <vnl/vnl_matrix_fixed.h>
#include "mitkImage.h"
#include "mitkBaseProcess.h"
#include "mitkPyramidRegistrationMethodHelper.h"
#include <itkWindowedSincInterpolateImageFunction.h>
#include "mitkImageToItk.h"
#include "mitkImageCast.h"
#include "mitkImageCaster.h"
#include "mitkITKImageImport.h"
#include "mitkIOUtil.h"
namespace mitk
{
/**
* @brief The PyramidImageRegistration class implements a multi-scale registration method
*
* The PyramidImageRegistration class is suitable for aligning (f.e.) brain MR images. The method offers two
* transform types
* - Rigid: optimizing translation and rotation only and
* - Affine ( default ): with scaling in addition ( 12 DOF )
*
* The error metric is internally chosen based on the selected task type : \sa SetCrossModalityOn
*
* It uses
* - MattesMutualInformation for CrossModality=on ( default ) and
* - NormalizedCorrelation for CrossModality=off.
*/
class MITKDIFFUSIONCORE_EXPORT PyramidImageRegistrationMethod :
public itk::Object
{
public:
/** Typedefs */
mitkClassMacroItkParent(PyramidImageRegistrationMethod, itk::Object)
/** Smart pointer support */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
typedef itk::OptimizerParameters<double> ParametersType;
/** Typedef for the transformation matrix, corresponds to the InternalMatrixType from ITK transforms */
typedef vnl_matrix_fixed< double, 3, 3> TransformMatrixType;
typedef itk::AffineTransform< double > AffineTransformType;
typedef itk::Euler3DTransform< double > RigidTransformType;
/** Registration is between modalities - will take MattesMutualInformation as error metric */
void SetCrossModalityOn()
{
m_CrossModalityRegistration = true;
}
/** Registration is between modalities - will take NormalizedCorrelation as error metric */
void SetCrossModalityOff()
{
m_CrossModalityRegistration = false;
}
/** Turn the cross-modality on/off */
void SetCrossModality(bool flag)
{
if( flag )
this->SetCrossModalityOn();
else
this->SetCrossModalityOff();
}
/** Controll the verbosity of the registration output
*
* for true, each iteration step of the optimizer is watched and passed to the std::cout
*/
void SetVerbose(bool flag)
{
if( flag )
this->SetVerboseOn();
else
this->SetVerboseOff();
}
/** Turn verbosity on, \sa SetVerbose */
void SetVerboseOn()
{
m_Verbose = true;
}
/** Turn verbosity off, \sa SetVerbose */
void SetVerboseOff()
{
m_Verbose = false;
}
/** A rigid ( 6dof : translation + rotation ) transform is optimized */
void SetTransformToRigid()
{
m_UseAffineTransform = false;
}
/** An affine ( 12dof : Rigid + scale + skew ) transform is optimized */
void SetTransformToAffine()
{
m_UseAffineTransform = true;
}
/** Input image, the reference one */
void SetFixedImage( mitk::Image::Pointer );
/** Input image, the one to be transformed */
void SetMovingImage( mitk::Image::Pointer );
/** Fixed image mask, excludes the masked voxels from the registration metric*/
void SetFixedImageMask( mitk::Image::Pointer mask);
/** \brief Use the itk::CenteredVersorTransformInitializer to perform initialization step for the registration
*
* The initializer takes the geometries and their features to perform an initialization for the successive registration
*/
void SetInitializeByGeometry(bool flag)
{
m_InitializeByGeometry = flag;
}
void Update();
/**
* @brief Get the number of parameters optimized ( 12 or 6 )
*
* @return number of paramters
*/
unsigned int GetNumberOfParameters()
{
unsigned int retValue = 12;
if(!m_UseAffineTransform)
retValue = 6;
return retValue;
}
/**
* @brief Copies the estimated parameters to the given array
* @param paramArray, target array for copy, make sure to allocate enough space
*/
void GetParameters( double* paramArray)
{
if( m_EstimatedParameters == nullptr )
{
mitkThrow() << "No parameters were estimated yet, call Update() first.";
}
unsigned int dim = 12;
if( !m_UseAffineTransform )
dim = 6;
for( unsigned int i=0; i<dim; i++)
{
*(paramArray+i) = m_EstimatedParameters[i];
}
}
/**
* @brief Retrieve the parameters of the last registration computed
*
* @return Parameters array ( as an itk::Array )
*/
ParametersType GetLastRegistrationParameters()
{
if( m_EstimatedParameters == nullptr )
{
mitkThrow() << "No parameters were estimated yet, call Update() first.";
}
unsigned int dim = 12;
if( !m_UseAffineTransform )
dim = 6;
ParametersType params(dim);
params.SetDataSameSize( m_EstimatedParameters );
return params;
}
/**
* @brief Set the starting position of the registration
*
* @param params make sure the parameters have the same dimension as the selected transform type
* otherwise the update call will throw an exception
*/
void SetInitialParameters( ParametersType& params )
{
m_InitialParameters = params;
}
/**
* @brief Control the interpolator used for resampling.
*
* The Windowed Sinc Interpolator is more time consuming, but the interpolation preserves more structure
* in the data
*
* The class uses the
* - Linear interpolator on default ( flag = false )
* - WindowedSinc interpolator if called with true
*/
void SetUseAdvancedInterpolation( bool flag)
{
m_UseWindowedSincInterpolator = flag;
}
/**
* @brief Control the interpolator used for resampling.
*
* The class uses the
* - Linear interpolator on default ( flag = false )
* - Nearest neighbor interpolation if this is true
*
* used to resample e.g. segmentations.
*/
void SetUseNearestNeighborInterpolation( bool flag)
{
m_UseNearestNeighborInterpolator = flag;
}
/**
* @brief Set if fixed image mask is used to exclude a region.
* @param flag , true if mask is to be used, false if mask is to be ignored (default)
*/
void SetUseFixedImageMask( bool flag)
{
m_UseMask = flag;
}
/**
* @brief Returns the moving image transformed according to the estimated transformation and resampled
* to the geometry of the fixed/resampling reference image
*
*/
mitk::Image::Pointer GetResampledMovingImage();
/**
* @brief Returns a provided moving image transformed according to the given transformation and resampled
* to the geometry of the fixed/resampling reference image
*/
mitk::Image::Pointer GetResampledMovingImage(mitk::Image::Pointer movingImage, double *transform );
/**
* @brief Get the rotation part of the transformation as a vnl_fixed_matrix<double, 3,3>
*
* It returns identity if the internal parameters are not-yet allocated ( i.e. the filter did not run yet )
*
* @return \sa TransformMatrixType
*/
TransformMatrixType GetLastRotationMatrix();
protected:
PyramidImageRegistrationMethod();
~PyramidImageRegistrationMethod() override;
/** Fixed image, used as reference for registration */
mitk::Image::Pointer m_FixedImage;
/** Moving image, will be transformed */
mitk::Image::Pointer m_MovingImage;
mitk::Image::Pointer m_FixedImageMask;
bool m_CrossModalityRegistration;
bool m_UseAffineTransform;
bool m_UseWindowedSincInterpolator;
bool m_UseNearestNeighborInterpolator;
bool m_UseMask;
double* m_EstimatedParameters;
ParametersType m_InitialParameters;
/** Control the verbosity of the regsitistration output */
bool m_Verbose;
bool m_InitializeByGeometry;
/**
* @brief The method takes two itk::Images and performs a multi-scale registration on them
*
* Can be accessed by the AccessTwoImagesFixedDimensionByItk macro.
*
* @note Currently the access is currently reduced only for short and float ( the only types occuring with mitk::DiffusionImage ) and
* hence the method is accessed by means of the \sa AccessTwoImagesFixedDimensionTypeSubsetByItk macro.
*/
template <typename TPixel1, unsigned int VImageDimension1, typename TPixel2, unsigned int VImageDimension2>
void RegisterTwoImagesV4(itk::Image<TPixel1, VImageDimension1>* itkImage1, itk::Image<TPixel2, VImageDimension2>* itkImage2);
/**
* @brief ResampleMitkImage applies the functionality of an the itk::ResampleImageFilter to the given
* mitk::Image.
*
* The API of the function is conform to the interface of \sa AccessByItk_1 macros.
*/
template< typename TPixel, unsigned int VDimension>
void ResampleMitkImage( itk::Image<TPixel, VDimension>* itkImage,
mitk::Image::Pointer& outputImage );
};
} // end namespace
#endif // MITKPYRAMIDIMAGEREGISTRATION_H
diff --git a/Modules/DiffusionCore/Algorithms/Registration/mitkPyramidRegistrationMethodHelper.h b/Modules/DiffusionCore/Algorithms/Registration/mitkPyramidRegistrationMethodHelper.h
index da81541..0d4ce74 100644
--- a/Modules/DiffusionCore/Algorithms/Registration/mitkPyramidRegistrationMethodHelper.h
+++ b/Modules/DiffusionCore/Algorithms/Registration/mitkPyramidRegistrationMethodHelper.h
@@ -1,212 +1,212 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKPYRAMIDREGISTRATIONMETHODHELPER_H
#define MITKPYRAMIDREGISTRATIONMETHODHELPER_H
#include <MitkDiffusionCoreExports.h>
#include <itkCommand.h>
#include <itkRegularStepGradientDescentOptimizer.h>
#include <itkMattesMutualInformationImageToImageMetricv4.h>
#include <itkCorrelationImageToImageMetricv4.h>
#include <itkGradientDescentLineSearchOptimizerv4.h>
#include <itkImageRegistrationMethodv4.h>
#include <itkAffineTransform.h>
#include <itkEuler3DTransform.h>
#include <itkMattesMutualInformationImageToImageMetric.h>
#include <itkNormalizedCorrelationImageToImageMetric.h>
#include <itkMultiResolutionImageRegistrationMethod.h>
#include <itkImageMomentsCalculator.h>
#include "mitkImageAccessByItk.h"
/**
* @brief Provides same functionality as \a AccessTwoImagesFixedDimensionByItk for a subset of types
*
* For now, the subset defined is only short and float.
*/
#define AccessTwoImagesFixedDimensionTypeSubsetByItk(mitkImage1, mitkImage2, itkImageTypeFunction, dimension) \
{ \
const mitk::PixelType& pixelType1 = mitkImage1->GetPixelType(); \
const mitk::PixelType& pixelType2 = mitkImage2->GetPixelType(); \
const mitk::Image* constImage1 = mitkImage1; \
const mitk::Image* constImage2 = mitkImage2; \
mitk::Image* nonConstImage1 = const_cast<mitk::Image*>(constImage1); \
mitk::Image* nonConstImage2 = const_cast<mitk::Image*>(constImage2); \
nonConstImage1->Update(); \
nonConstImage2->Update(); \
_checkSpecificDimension(mitkImage1, (dimension)); \
_checkSpecificDimension(mitkImage2, (dimension)); \
_accessTwoImagesByItkForEach(itkImageTypeFunction, ((short, dimension))((unsigned short, dimension))((float, dimension))((double, dimension)), ((short, dimension))((unsigned short, dimension))((float, dimension))((double, dimension)) ) \
{ \
std::string msg("Pixel type "); \
msg.append(pixelType1.GetComponentTypeAsString() ); \
msg.append(" or pixel type "); \
msg.append(pixelType2.GetComponentTypeAsString() ); \
msg.append(" is not in " BOOST_PP_STRINGIZE(MITK_ACCESSBYITK_TYPES_DIMN_SEQ(dimension))); \
throw mitk::AccessByItkException(msg); \
} \
}
/**
* @brief The PyramidOptControlCommand class stears the step lenght of the
* gradient descent optimizer in multi-scale registration methods
*/
template <typename RegistrationType >
class PyramidOptControlCommand : public itk::Command
{
public:
typedef itk::RegularStepGradientDescentOptimizer OptimizerType;
mitkClassMacroItkParent(PyramidOptControlCommand<RegistrationType>, itk::Command)
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
void Execute(itk::Object *caller, const itk::EventObject & /*event*/) override
{
RegistrationType* registration = dynamic_cast< RegistrationType* >( caller );
if( registration == nullptr)
return;
MITK_DEBUG << "\t - Pyramid level " << registration->GetCurrentLevel();
if( registration->GetCurrentLevel() == 0 )
{ MITK_WARN("OptCommand") << "Cast to registration failed";
return;
}
OptimizerType* optimizer = dynamic_cast< OptimizerType* >(registration->GetOptimizer());
if( optimizer == nullptr)
{ MITK_WARN("OptCommand") << "Cast to optimizer failed";
return;
}
MITK_DEBUG /*<< optimizer->GetStopConditionDescription() << "\n"*/
<< optimizer->GetValue() << " : " << optimizer->GetCurrentPosition();
optimizer->SetMaximumStepLength( optimizer->GetMaximumStepLength() * 0.25f );
optimizer->SetMinimumStepLength( optimizer->GetMinimumStepLength() * 0.1f );
// optimizer->SetNumberOfIterations( optimizer->GetNumberOfIterations() * 1.5f );
}
void Execute(const itk::Object * /*object*/, const itk::EventObject & /*event*/) override{}
};
#include <itkGradientDescentLineSearchOptimizerv4.h>
template <typename RegistrationType >
class PyramidOptControlCommandv4 : public itk::Command
{
public:
typedef itk::GradientDescentLineSearchOptimizerv4 OptimizerType;
mitkClassMacroItkParent(PyramidOptControlCommandv4<RegistrationType>, itk::Command)
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
void Execute(itk::Object *caller, const itk::EventObject & /*event*/) override
{
RegistrationType* registration = dynamic_cast< RegistrationType* >( caller );
if( registration == nullptr)
return;
MITK_DEBUG << "\t - Pyramid level " << registration->GetCurrentLevel();
if( registration->GetCurrentLevel() == 0 )
return;
OptimizerType* optimizer = dynamic_cast< OptimizerType* >( registration->GetOptimizer() );
if( optimizer == nullptr)
{ MITK_WARN("OptCommand4") << "Cast to optimizer failed";
return;
}
optimizer->SetNumberOfIterations( optimizer->GetNumberOfIterations() * 2.5 );
optimizer->SetMaximumStepSizeInPhysicalUnits( optimizer->GetMaximumStepSizeInPhysicalUnits() * 0.4);
MITK_INFO("Pyramid.Command.Iter") << optimizer->GetNumberOfIterations();
MITK_INFO("Pyramid.Command.MaxStep") << optimizer->GetMaximumStepSizeInPhysicalUnits();
}
void Execute(const itk::Object * /*object*/, const itk::EventObject & /*event*/) override{}
};
template <typename OptimizerType>
class OptimizerIterationCommand : public itk::Command
{
public:
mitkClassMacroItkParent(OptimizerIterationCommand<OptimizerType>, itk::Command)
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
void Execute(itk::Object *caller, const itk::EventObject & /*event*/) override
{
OptimizerType* optimizer = dynamic_cast< OptimizerType* >( caller );
unsigned int currentIter = optimizer->GetCurrentIteration();
MITK_INFO << "[" << currentIter << "] : " << optimizer->GetValue() << " : " << optimizer->GetCurrentPosition();
}
void Execute(const itk::Object * /*object*/, const itk::EventObject & /*event*/) override
{
}
};
template <typename OptimizerType>
class OptimizerIterationCommandv4 : public itk::Command
{
public:
itkNewMacro( OptimizerIterationCommandv4 )
void Execute(itk::Object *object, const itk::EventObject & event) override
{
OptimizerType* optimizer = dynamic_cast< OptimizerType* >( object );
if( typeid( event ) != typeid( itk::IterationEvent ) )
{ return; }
unsigned int currentIter = optimizer->GetCurrentIteration();
MITK_INFO << "[" << currentIter << "] : " << optimizer->GetCurrentMetricValue() << " : "
<< optimizer->GetMetric()->GetParameters() ;
//<< " : " << optimizer->GetScales();
}
void Execute(const itk::Object * /*object*/, const itk::EventObject & /*event*/) override
{
}
};
#endif // MITKPYRAMIDREGISTRATIONMETHODHELPER_H
diff --git a/Modules/DiffusionCore/Algorithms/itkAdcImageFilter.h b/Modules/DiffusionCore/Algorithms/itkAdcImageFilter.h
index 1d8eb44..9c6a05b 100644
--- a/Modules/DiffusionCore/Algorithms/itkAdcImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkAdcImageFilter.h
@@ -1,136 +1,136 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*===================================================================
This file is based heavily on a corresponding ITK filter.
===================================================================*/
#ifndef __itkAdcImageFilter_h_
#define __itkAdcImageFilter_h_
#include "itkImageToImageFilter.h"
#include "itkVectorImage.h"
#include <mitkDiffusionPropertyHelper.h>
#include <vnl/algo/vnl_levenberg_marquardt.h>
#include <vnl/vnl_least_squares_function.h>
namespace itk{
/** \class AdcImageFilter
*/
template< class TInPixelType, class TOutPixelType >
class AdcImageFilter :
public ImageToImageFilter< VectorImage< TInPixelType, 3 >, Image< TOutPixelType, 3 > >
{
public:
typedef AdcImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< VectorImage< TInPixelType, 3 >, Image< TOutPixelType, 3 > > Superclass;
typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer GradientContainerType;
typedef itk::Image< unsigned char, 3> ItkUcharImageType;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(AdcImageFilter, ImageToImageFilter)
typedef typename Superclass::InputImageType InputImageType;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename Superclass::OutputImageRegionType OutputImageRegionType;
itkSetMacro( MaskImage, ItkUcharImageType::Pointer )
itkSetMacro( FitSignal, bool )
itkSetMacro( B_value, double )
itkSetMacro( GradientDirections, GradientContainerType )
/**
* \brief The lestSquaresFunction struct for Non-Linear-Least-Squres fit of monoexponential model Si = S0*exp(-b*ADC)
*/
struct adcLeastSquaresFunction: public vnl_least_squares_function
{
void set_S0(double val)
{
S0 = val;
}
void set_measurements(const vnl_vector<double>& m)
{
measurements.set_size(m.size());
measurements.copy_in(m.data_block());
}
void set_bvalues(const vnl_vector<double>& x)
{
bValues.set_size(x.size());
bValues.copy_in(x.data_block());
}
vnl_vector<double> measurements;
vnl_vector<double> bValues;
double S0;
adcLeastSquaresFunction(unsigned int number_of_measurements=1) :
vnl_least_squares_function(1, number_of_measurements, no_gradient)
{
}
void f(const vnl_vector<double>& x, vnl_vector<double>& fx) override {
const double & ADC = x[0];
for(unsigned int s=0; s<measurements.size(); s++)
{
double approx = S0 * std::exp(-bValues[s] * ADC);
fx[s] = vnl_math_abs( measurements[s] - approx );
}
}
};
protected:
AdcImageFilter();
~AdcImageFilter() override {}
void PrintSelf(std::ostream& os, Indent indent) const override;
void BeforeThreadedGenerateData() override;
void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType) override;
bool m_FitSignal;
double m_B_value;
vnl_vector<double> m_B_values;
vnl_vector<double> m_Nonzero_B_values;
GradientContainerType m_GradientDirections;
ItkUcharImageType::Pointer m_MaskImage;
double FitSingleVoxel( const typename InputImageType::PixelType &input);
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkAdcImageFilter.txx"
#endif
#endif //__itkAdcImageFilter_h_
diff --git a/Modules/DiffusionCore/Algorithms/itkAdcImageFilter.txx b/Modules/DiffusionCore/Algorithms/itkAdcImageFilter.txx
index 4a71b59..db05072 100644
--- a/Modules/DiffusionCore/Algorithms/itkAdcImageFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkAdcImageFilter.txx
@@ -1,208 +1,208 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkAdcImageFilter_txx
#define __itkAdcImageFilter_txx
#include <ctime>
#include <cstdio>
#include <cstdlib>
#define _USE_MATH_DEFINES
#include <cmath>
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionConstIteratorWithIndex.h"
#include "itkImageRegionIterator.h"
namespace itk {
template< class TInPixelType, class TOutPixelType >
AdcImageFilter< TInPixelType, TOutPixelType>
::AdcImageFilter()
: m_FitSignal(true)
, m_B_value(0)
{
this->SetNumberOfRequiredInputs( 1 );
}
template< class TInPixelType, class TOutPixelType >
void
AdcImageFilter< TInPixelType, TOutPixelType>
::BeforeThreadedGenerateData()
{
typename OutputImageType::Pointer outputImage =
static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0));
outputImage->FillBuffer(0.0);
m_B_values.set_size(m_GradientDirections->Size());
int nonzero = 0;
for (unsigned int i=0; i<m_GradientDirections->Size(); i++)
{
GradientDirectionType g = m_GradientDirections->GetElement(i);
double twonorm = g.two_norm();
double b = m_B_value*twonorm*twonorm;
m_B_values[i] = b;
if (g.magnitude()>0.001)
nonzero++;
}
m_Nonzero_B_values.set_size(nonzero);
nonzero = 0;
for (unsigned int i=0; i<m_B_values.size(); i++)
{
if (m_B_values[i]>1)
{
m_Nonzero_B_values[nonzero] = m_B_values[i];
nonzero++;
}
}
if (m_B_values.size() == m_Nonzero_B_values.size())
mitkThrow() << "Unweighted (b=0 s/mm²) image volume missing!";
}
template< class TInPixelType, class TOutPixelType >
double
AdcImageFilter< TInPixelType, TOutPixelType>::FitSingleVoxel( const typename InputImageType::PixelType &input)
{
double S0 = 0;
int nonzero = 0;
vnl_vector<double> m; m.set_size(m_Nonzero_B_values.size());
for (unsigned int i=0; i<m_B_values.size(); i++)
{
if (m_B_values[i]>1)
{
m[nonzero] = input[i];
nonzero++;
}
else
S0 += input[i];
}
S0 /= (m_B_values.size() - m_Nonzero_B_values.size());
adcLeastSquaresFunction f(m_Nonzero_B_values.size());
f.set_bvalues(m_Nonzero_B_values);
f.set_S0(S0);
f.set_measurements(m);
vnl_levenberg_marquardt lm(f);
vnl_vector_fixed<double, 1> x; x.fill(0);
lm.minimize(x);
return x[0];
}
template< class TInPixelType, class TOutPixelType >
void
AdcImageFilter< TInPixelType, TOutPixelType>
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, ThreadIdType )
{
typename OutputImageType::Pointer outputImage =
static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0));
ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread);
oit.GoToBegin();
typedef ImageRegionConstIterator< InputImageType > InputIteratorType;
typename InputImageType::Pointer inputImagePointer = NULL;
inputImagePointer = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
InputIteratorType git( inputImagePointer, outputRegionForThread );
git.GoToBegin();
while( !git.IsAtEnd() )
{
typename InputImageType::PixelType pix = git.Get();
TOutPixelType outval = 0;
if (!m_FitSignal)
{
double S0 = 0;
int c = 0;
for (unsigned int i=0; i<inputImagePointer->GetVectorLength(); i++)
{
GradientDirectionType g = m_GradientDirections->GetElement(i);
if (g.magnitude()<0.001)
{
if (pix[i]>0)
{
S0 += pix[i];
c++;
}
}
}
if (c>0)
S0 /= c;
if (S0>0)
{
c = 0;
for (unsigned int i=0; i<inputImagePointer->GetVectorLength(); i++)
{
GradientDirectionType g = m_GradientDirections->GetElement(i);
if (g.magnitude()>0.001)
{
double twonorm = g.two_norm();
double b = m_B_value*twonorm*twonorm;
if (b>0)
{
double S = pix[i];
if (S>0 && S0>0)
{
outval -= std::log(S/S0)/b;
c++;
}
}
}
}
if (c>0)
outval /= c;
}
}
else
{
outval = FitSingleVoxel(pix);
}
// if (outval<-0.00001)
// outval = -0.00001;
if (outval==outval && outval<1000)
oit.Set( outval );
// else
// oit.Set( -0.00001 );
++oit;
++git;
}
}
template< class TInPixelType, class TOutPixelType >
void
AdcImageFilter< TInPixelType, TOutPixelType>
::PrintSelf(std::ostream& os, Indent indent) const
{
Superclass::PrintSelf(os,indent);
}
}
#endif // __itkAdcImageFilter_txx
diff --git a/Modules/DiffusionCore/Algorithms/itkB0ImageExtractionImageFilter.h b/Modules/DiffusionCore/Algorithms/itkB0ImageExtractionImageFilter.h
index 3e39ca0..a5d2848 100644
--- a/Modules/DiffusionCore/Algorithms/itkB0ImageExtractionImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkB0ImageExtractionImageFilter.h
@@ -1,90 +1,90 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkB0ImageExtractionImageFilter_h_
#define __itkB0ImageExtractionImageFilter_h_
#include "itkImageToImageFilter.h"
namespace itk{
/** \class B0ImageExtractionImageFilter
* \brief This class takes as input a T2-weighted image and computes a brainmask.
*
*/
template< class TInputImagePixelType,
class TOutputImagePixelType >
class B0ImageExtractionImageFilter :
public ImageToImageFilter< VectorImage<TInputImagePixelType, 3>,
Image< TOutputImagePixelType, 3 > >
{
public:
typedef B0ImageExtractionImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< VectorImage< TInputImagePixelType, 3 >,
Image< TOutputImagePixelType, 3 > >
Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(B0ImageExtractionImageFilter,
ImageToImageFilter);
typedef TInputImagePixelType InputPixelType;
typedef TOutputImagePixelType OutputPixelType;
typedef typename Superclass::InputImageType InputImageType;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename Superclass::OutputImageRegionType
OutputImageRegionType;
typedef vnl_vector_fixed< double, 3 > GradientDirectionType;
typedef itk::VectorContainer< unsigned int, GradientDirectionType >
GradientDirectionContainerType;
GradientDirectionContainerType::Pointer GetDirections()
{ return m_Directions; }
void SetDirections( GradientDirectionContainerType::Pointer directions )
{ this->m_Directions = directions; }
protected:
B0ImageExtractionImageFilter();
~B0ImageExtractionImageFilter() override {};
void GenerateData() override;
GradientDirectionContainerType::Pointer m_Directions;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkB0ImageExtractionImageFilter.txx"
#endif
#endif //__itkB0ImageExtractionImageFilter_h_
diff --git a/Modules/DiffusionCore/Algorithms/itkB0ImageExtractionImageFilter.txx b/Modules/DiffusionCore/Algorithms/itkB0ImageExtractionImageFilter.txx
index 6fa00e4..f99b802 100644
--- a/Modules/DiffusionCore/Algorithms/itkB0ImageExtractionImageFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkB0ImageExtractionImageFilter.txx
@@ -1,126 +1,126 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*===================================================================
This file is based heavily on a corresponding ITK filter.
===================================================================*/
#ifndef __itkB0ImageExtractionImageFilter_txx
#define __itkB0ImageExtractionImageFilter_txx
#include "itkB0ImageExtractionImageFilter.h"
#include "itkImageRegionIterator.h"
namespace itk {
template< class TInputImagePixelType,
class TOutputImagePixelType >
B0ImageExtractionImageFilter< TInputImagePixelType,
TOutputImagePixelType >
::B0ImageExtractionImageFilter()
{
// At least 1 inputs is necessary for a vector image.
// For images added one at a time we need at least six
this->SetNumberOfRequiredInputs( 1 );
}
template< class TInputImagePixelType,
class TOutputImagePixelType >
void B0ImageExtractionImageFilter< TInputImagePixelType,
TOutputImagePixelType >
::GenerateData()
{
typename GradientDirectionContainerType::Iterator begin = m_Directions->Begin();
typename GradientDirectionContainerType::Iterator end = m_Directions->End();
// Find the index of the b0 image
std::vector<int> indices;
int index = 0;
while(begin!=end)
{
GradientDirectionType grad = begin->Value();
if(grad[0] == 0 && grad[1] == 0 && grad[2] == 0)
{
indices.push_back(index);
}
++index;
++begin;
}
typedef itk::Image<float,3> TempImageType;
TempImageType::Pointer tmp = TempImageType::New();
typename TempImageType::RegionType region = this->GetInput()->GetLargestPossibleRegion();
tmp->SetSpacing(this->GetInput()->GetSpacing());
tmp->SetOrigin(this->GetInput()->GetOrigin());
tmp->SetDirection(this->GetInput()->GetDirection());
tmp->SetRegions(region);
tmp->Allocate();
itk::ImageRegionIterator<TempImageType> it(tmp.GetPointer(), tmp->GetLargestPossibleRegion() );
itk::ImageRegionConstIterator<InputImageType> vectorIt(this->GetInput(), this->GetInput()->GetLargestPossibleRegion() );
it.GoToBegin();
while(!it.IsAtEnd())
{
it.Set(0);
++it;
}
//Sum all images that have zero diffusion weighting (indices stored in vector index)
for(std::vector<int>::iterator indexIt = indices.begin();
indexIt != indices.end();
indexIt++)
{
it.GoToBegin();
vectorIt.GoToBegin();
while(!it.IsAtEnd() && !vectorIt.IsAtEnd())
{
typename InputImageType::PixelType vec = vectorIt.Get();
it.Set((1.0 * it.Get()) + (1.0 * vec[*indexIt]) / (1.0 * indices.size()));
++it;
++vectorIt;
}
}
typename OutputImageType::Pointer b0Image =
static_cast< OutputImageType * >(this->ProcessObject::GetPrimaryOutput());
typename OutputImageType::RegionType outregion = this->GetInput()->GetLargestPossibleRegion();
b0Image->SetSpacing(this->GetInput()->GetSpacing());
b0Image->SetOrigin(this->GetInput()->GetOrigin());
b0Image->SetDirection(this->GetInput()->GetDirection());
b0Image->SetRegions(outregion);
b0Image->Allocate();
itk::ImageRegionIterator<TempImageType> itIn(tmp, tmp->GetLargestPossibleRegion() );
itk::ImageRegionIterator<OutputImageType> itOut(b0Image, b0Image->GetLargestPossibleRegion() );
itIn.GoToBegin();
itOut.GoToBegin();
while(!itIn.IsAtEnd())
{
itOut.Set(itIn.Get());
++itIn;
++itOut;
}
}
}
#endif // __itkB0ImageExtractionImageFilter_txx
diff --git a/Modules/DiffusionCore/Algorithms/itkB0ImageExtractionToSeparateImageFilter.h b/Modules/DiffusionCore/Algorithms/itkB0ImageExtractionToSeparateImageFilter.h
index d800fde..25cc6f5 100644
--- a/Modules/DiffusionCore/Algorithms/itkB0ImageExtractionToSeparateImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkB0ImageExtractionToSeparateImageFilter.h
@@ -1,107 +1,107 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 ITKB0IMAGEEXTRACTIONTOSEPARATEIMAGEFILTER_H
#define ITKB0IMAGEEXTRACTIONTOSEPARATEIMAGEFILTER_H
#include "itkImageToImageFilter.h"
namespace itk
{
/** \class B0ImageExtractionToSeparateImageFilter
\brief This class has an advanced functionality to the B0ImageExtractionImageFilter, however the b0 images are
stored in a 3D+t image with each b0 image beeing a separate timestep and not averaged to a single 3D volume
*/
template< class TInputImagePixelType,
class TOutputImagePixelType >
class B0ImageExtractionToSeparateImageFilter :
public ImageToImageFilter< VectorImage<TInputImagePixelType, 3>,
Image< TOutputImagePixelType, 4 > >
{
public:
typedef B0ImageExtractionToSeparateImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef TInputImagePixelType InputPixelType;
typedef TOutputImagePixelType OutputPixelType;
typedef ImageToImageFilter< VectorImage<TInputImagePixelType, 3>,
Image< TOutputImagePixelType, 4 > > Superclass;
/** typedefs from superclass */
typedef typename Superclass::InputImageType InputImageType;
//typedef typename Superclass::OutputImageType OutputImageType;
typedef Image< TOutputImagePixelType, 4 > OutputImageType;
typedef typename OutputImageType::RegionType OutputImageRegionType;
typedef vnl_vector_fixed< double, 3 > GradientDirectionType;
typedef itk::VectorContainer< unsigned int, GradientDirectionType >
GradientDirectionContainerType;
typedef typename GradientDirectionContainerType::Iterator GradContainerIteratorType;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(B0ImageExtractionToSeparateImageFilter,
ImageToImageFilter);
GradientDirectionContainerType::Pointer GetDirections()
{
return m_Directions;
}
void SetDirections( GradientDirectionContainerType::Pointer directions )
{
this->m_Directions = directions;
}
protected:
B0ImageExtractionToSeparateImageFilter();
virtual ~B0ImageExtractionToSeparateImageFilter(){};
void GenerateData();
/** The dimension of the output does not match the dimension of the input
hence we need to re-implement the CopyInformation method to avoid
executing the default implementation which tries to copy the input information to the
output
*/
virtual void CopyInformation( const DataObject *data);
/** Override of the ProcessObject::GenerateOutputInformation() because of different
dimensionality of the input and the output
*/
virtual void GenerateOutputInformation();
GradientDirectionContainerType::Pointer m_Directions;
};
} // end namespace itk
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkB0ImageExtractionToSeparateImageFilter.txx"
#endif
#endif // ITKB0IMAGEEXTRACTIONTOSEPARATEIMAGEFILTER_H
diff --git a/Modules/DiffusionCore/Algorithms/itkB0ImageExtractionToSeparateImageFilter.txx b/Modules/DiffusionCore/Algorithms/itkB0ImageExtractionToSeparateImageFilter.txx
index 0b8b7e2..a557c0e 100644
--- a/Modules/DiffusionCore/Algorithms/itkB0ImageExtractionToSeparateImageFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkB0ImageExtractionToSeparateImageFilter.txx
@@ -1,165 +1,165 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkB0ImageExtractionToSeparateImageFilter_txx
#define __itkB0ImageExtractionToSeparateImageFilter_txx
#include "itkB0ImageExtractionToSeparateImageFilter.h"
#include <itkImageRegionConstIterator.h>
#include <itkImageRegionIterator.h>
template< class TInputImagePixelType,
class TOutputImagePixelType>
itk::B0ImageExtractionToSeparateImageFilter< TInputImagePixelType, TOutputImagePixelType >
::B0ImageExtractionToSeparateImageFilter()
{
this->SetNumberOfRequiredInputs( 1 );
}
template< class TInputImagePixelType,
class TOutputImagePixelType>
void itk::B0ImageExtractionToSeparateImageFilter<
TInputImagePixelType, TOutputImagePixelType >::CopyInformation( const DataObject *)
{
}
template< class TInputImagePixelType,
class TOutputImagePixelType>
void itk::B0ImageExtractionToSeparateImageFilter<
TInputImagePixelType, TOutputImagePixelType >::GenerateOutputInformation()
{
}
template< class TInputImagePixelType,
class TOutputImagePixelType>
void itk::B0ImageExtractionToSeparateImageFilter<
TInputImagePixelType, TOutputImagePixelType >::GenerateData()
{
GradContainerIteratorType begin = m_Directions->Begin();
GradContainerIteratorType end = m_Directions->End();
// Find the indices of the b0 images in the diffusion image
std::vector<int> indices;
int index = 0;
while(begin!=end)
{
GradientDirectionType grad = begin->Value();
if(grad[0] == 0 && grad[1] == 0 && grad[2] == 0)
{
indices.push_back(index);
}
++index;
++begin;
}
// declare the output image
// this will have the b0 images stored as timesteps
typename OutputImageType::Pointer outputImage = this->GetOutput();
//OutputImageType::New();
// get the input region
typename Superclass::InputImageType::RegionType inputRegion =
this->GetInput()->GetLargestPossibleRegion();
// allocate image with
// - dimension: [DimX, DimY, DimZ, NumOfb0 ]
// - spacing: old one, 1.0 time
typename OutputImageType::SpacingType spacing;
spacing.Fill(1);
typename OutputImageType::PointType origin;
origin.Fill(0);
OutputImageRegionType outputRegion;
// the spacing and origin corresponds to the respective values in the input image (3D)
// the same for the region
for (unsigned int i=0; i< 3; i++)
{
spacing[i] = (this->GetInput()->GetSpacing())[i];
origin[i] = (this->GetInput()->GetOrigin())[i];
outputRegion.SetSize(i, this->GetInput()->GetLargestPossibleRegion().GetSize()[i]);
outputRegion.SetIndex(i, this->GetInput()->GetLargestPossibleRegion().GetIndex()[i]);
}
// number of timesteps = number of b0 images
outputRegion.SetSize(3, indices.size());
outputRegion.SetIndex( 3, 0 );
// output image direction (4x4)
typename OutputImageType::DirectionType outputDirection;
//initialize to identity
outputDirection.SetIdentity();
// get the input image direction ( 3x3 matrix )
typename InputImageType::DirectionType inputDirection = this->GetInput()->GetDirection();
for( unsigned int i=0; i< 3; i++)
{
outputDirection(0,i) = inputDirection(0,i);
outputDirection(1,i) = inputDirection(1,i);
outputDirection(2,i) = inputDirection(2,i);
}
outputImage->SetSpacing( spacing );
outputImage->SetOrigin( origin );
outputImage->SetDirection( outputDirection );
outputImage->SetRegions( outputRegion );
outputImage->Allocate();
// input iterator
itk::ImageRegionConstIterator<InputImageType> inputIt( this->GetInput(), this->GetInput()->GetLargestPossibleRegion() );
// we want to iterate separately over each 3D volume of the output image
// so reset the regions last dimension
outputRegion.SetSize(3,1);
unsigned int currentTimeStep = 0;
// extract b0 and insert them as a new time step
for(std::vector<int>::iterator indexIt = indices.begin();
indexIt != indices.end();
indexIt++)
{
// set the time step
outputRegion.SetIndex(3, currentTimeStep);
itk::ImageRegionIterator< OutputImageType> outputIt( outputImage.GetPointer(), outputRegion );
// iterate over the current b0 image and store it to corresponding place
outputIt.GoToBegin();
inputIt.GoToBegin();
while( !outputIt.IsAtEnd() && !inputIt.IsAtEnd() )
{
// the input vector
typename InputImageType::PixelType vec = inputIt.Get();
outputIt.Set( vec[*indexIt]);
++outputIt;
++inputIt;
}
// increase time step
currentTimeStep++;
}
}
#endif // ifndef __itkB0ImageExtractionToSeparateImageFilter_txx
diff --git a/Modules/DiffusionCore/Algorithms/itkBrainMaskExtractionImageFilter.h b/Modules/DiffusionCore/Algorithms/itkBrainMaskExtractionImageFilter.h
index 606dc5d..dba681f 100644
--- a/Modules/DiffusionCore/Algorithms/itkBrainMaskExtractionImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkBrainMaskExtractionImageFilter.h
@@ -1,84 +1,84 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkBrainMaskExtractionImageFilter_h_
#define __itkBrainMaskExtractionImageFilter_h_
#include "itkImageToImageFilter.h"
namespace itk{
/** \class BrainMaskExtractionImageFilter
* \brief This class takes as input a T2-weighted image and computes a brainmask.
*
*/
template< class TOutputImagePixelType >
class BrainMaskExtractionImageFilter :
public ImageToImageFilter< Image< unsigned short, 3 >,
Image< TOutputImagePixelType, 3 > >
{
public:
typedef BrainMaskExtractionImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< Image< unsigned short, 3 >,
Image< TOutputImagePixelType, 3 > >
Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(BrainMaskExtractionImageFilter,
ImageToImageFilter);
typedef unsigned short InputPixelType;
typedef TOutputImagePixelType OutputPixelType;
typedef typename Superclass::InputImageType InputImageType;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename Superclass::OutputImageRegionType
OutputImageRegionType;
itkSetMacro( MaxNumIterations, int )
itkGetMacro( MaxNumIterations, int )
protected:
BrainMaskExtractionImageFilter();
~BrainMaskExtractionImageFilter() {};
void GenerateData();
bool CompareImages( typename OutputImageType::Pointer im1, typename OutputImageType::Pointer im2);
int ComputeHistogram( typename InputImageType::Pointer image);
void CopyImage( typename OutputImageType::Pointer target, typename OutputImageType::Pointer source);
int m_MaxNumIterations;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkBrainMaskExtractionImageFilter.txx"
#endif
#endif //__itkBrainMaskExtractionImageFilter_h_
diff --git a/Modules/DiffusionCore/Algorithms/itkBrainMaskExtractionImageFilter.txx b/Modules/DiffusionCore/Algorithms/itkBrainMaskExtractionImageFilter.txx
index b3a54d3..46f924c 100644
--- a/Modules/DiffusionCore/Algorithms/itkBrainMaskExtractionImageFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkBrainMaskExtractionImageFilter.txx
@@ -1,444 +1,444 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*===================================================================
This file is based heavily on a corresponding ITK filter.
===================================================================*/
#ifndef __itkBrainMaskExtractionImageFilter_txx
#define __itkBrainMaskExtractionImageFilter_txx
#include "itkBrainMaskExtractionImageFilter.h"
#include <itkBinaryThresholdImageFilter.h>
#include <itkBinaryErodeImageFilter.h>
#include <itkBinaryDilateImageFilter.h>
#include <itkVotingBinaryHoleFillingImageFilter.h>
#include <itkVotingBinaryIterativeHoleFillingImageFilter.h>
#include <itkBinaryBallStructuringElement.h>
#include <itkBinaryCrossStructuringElement.h>
#include <itkAndImageFilter.h>
#include <itkRecursiveGaussianImageFilter.h>
#include <itkMaskImageFilter.h>
namespace itk {
template< class TOutputImagePixelType >
BrainMaskExtractionImageFilter< TOutputImagePixelType >
::BrainMaskExtractionImageFilter()
: m_MaxNumIterations(itk::NumericTraits<int>::max())
{
// At least 1 inputs is necessary for a vector image.
// For images added one at a time we need at least six
this->SetNumberOfRequiredInputs( 1 );
}
template< class TOutputImagePixelType >
void BrainMaskExtractionImageFilter< TOutputImagePixelType >
::GenerateData()
{
// gaussian filter
typename itk::RecursiveGaussianImageFilter<InputImageType,InputImageType>::Pointer gaussian
= itk::RecursiveGaussianImageFilter<InputImageType,InputImageType>::New();
gaussian->SetInput( this->GetInput(0) );
gaussian->SetSigma( 1.0 );
try
{
gaussian->Update();
}
catch( itk::ExceptionObject &e)
{
std::cerr << e;
return;
}
// threshold the image
typename itk::BinaryThresholdImageFilter<InputImageType,OutputImageType>::Pointer threshold =
itk::BinaryThresholdImageFilter<InputImageType,OutputImageType>::New();
threshold->SetInput( gaussian->GetOutput() );
int seuil = static_cast<int>( ComputeHistogram( gaussian->GetOutput() ) );
threshold->SetLowerThreshold( seuil );
std::cout << "Thresholding..." << std::flush;
try
{
threshold->Update();
}
catch( itk::ExceptionObject &e)
{
std::cerr << e;
return;
}
std::cout << "Done." << std::endl;
#ifdef DEBUG_ME
{
WriterType::Pointer writer = WriterType::New();
writer->SetInput( threshold->GetOutput() );
writer->SetFileName( "AfterThreshold.hdr" );
writer->Update();
}
#endif
// erode to remove background noise
typedef itk::BinaryBallStructuringElement<int, 3> StructuralElementType;
StructuralElementType ball;
typename itk::BinaryErodeImageFilter<OutputImageType,OutputImageType,StructuralElementType>::Pointer erode =
itk::BinaryErodeImageFilter<OutputImageType,OutputImageType,StructuralElementType>::New();
ball.SetRadius( 3 );
erode->SetInput( threshold->GetOutput() );
erode->SetKernel( ball );
std::cout << "Eroding..." << std::flush;
try
{
erode->Update();
}
catch( itk::ExceptionObject &e)
{
std::cerr << e;
return;
}
std::cout << "Done." << std::endl;
#ifdef DEBUG_ME
{
WriterType::Pointer writer = WriterType::New();
writer->SetInput( erode->GetOutput() );
writer->SetFileName( "AfterErode.hdr" );
writer->Update();
}
#endif
typedef BinaryCrossStructuringElement<int, 3> CrossType;
typedef BinaryDilateImageFilter<OutputImageType,OutputImageType,CrossType> DilateFilterType;
typedef AndImageFilter<OutputImageType,OutputImageType,OutputImageType> AndFilterType;
typename OutputImageType::Pointer M0 = threshold->GetOutput();
typename OutputImageType::Pointer Mn = OutputImageType::New();
Mn->SetRegions( M0->GetLargestPossibleRegion() );
Mn->SetSpacing( M0->GetSpacing() );
Mn->SetOrigin( M0->GetOrigin() );
Mn->SetDirection( M0->GetDirection() );
Mn->Allocate();
typename OutputImageType::Pointer Mnplus1 = erode->GetOutput();
CrossType cross;
cross.SetRadius( 1 );
//unsigned long rad[3]={3,3,3};
//ball2.SetRadius( rad );
std::cout << "Conditional reconstruction..." << std::flush;
int iter = 0;
do
{
std::cout << "Iteration: " << iter++ << std::endl;
CopyImage( Mn, Mnplus1);
typename DilateFilterType::Pointer dilater = DilateFilterType::New();
dilater->SetInput( Mn );
dilater->SetKernel( cross );
try
{
dilater->Update();
}
catch( itk::ExceptionObject &e)
{
std::cerr << e;
return;
}
typename AndFilterType::Pointer andfilter = AndFilterType::New();
andfilter->SetInput(0, M0);
andfilter->SetInput(1, dilater->GetOutput() );
try
{
andfilter->Update();
}
catch( itk::ExceptionObject &e)
{
std::cerr << e;
return;
}
Mnplus1 = andfilter->GetOutput();
/*
#ifdef DEBUG_ME
{
WriterType::Pointer writer = WriterType::New();
writer->SetInput( andfilter->GetOutput() );
char filename[512];
sprintf( filename, "CondReconstruction_iter_%d.hdr", iter);
writer->SetFileName( filename );
writer->Update();
}
#endif*/
} while( !CompareImages( Mn, Mnplus1) && iter < m_MaxNumIterations );
std::cout << "Done." << std::endl;
#ifdef DEBUG_ME
{
WriterType::Pointer writer = WriterType::New();
writer->SetInput( Mn );
writer->SetFileName( "AfterCondReconstruction.hdr" );
writer->Update();
}
#endif
// now fill the holes
typename itk::VotingBinaryIterativeHoleFillingImageFilter< OutputImageType >::Pointer filler =
itk::VotingBinaryIterativeHoleFillingImageFilter< OutputImageType >::New();
filler->SetInput( Mn );
filler->SetMaximumNumberOfIterations (1000);
std::cout << "Filling the holes..." << std::flush;
try
{
filler->Update();
}
catch( itk::ExceptionObject &e)
{
std::cerr << e;
return;
}
std::cout << "Done." << std::endl;
typename OutputImageType::Pointer outputImage =
static_cast< OutputImageType * >(this->ProcessObject::GetPrimaryOutput());
outputImage->SetSpacing( filler->GetOutput()->GetSpacing() ); // Set the image spacing
outputImage->SetOrigin( filler->GetOutput()->GetOrigin() ); // Set the image origin
outputImage->SetLargestPossibleRegion( filler->GetOutput()->GetLargestPossibleRegion());
outputImage->SetBufferedRegion( filler->GetOutput()->GetLargestPossibleRegion() );
outputImage->SetDirection( filler->GetOutput()->GetDirection() );
outputImage->Allocate();
itk::ImageRegionIterator<OutputImageType> itIn( filler->GetOutput(), filler->GetOutput()->GetLargestPossibleRegion() );
itk::ImageRegionIterator<OutputImageType> itOut( outputImage, outputImage->GetLargestPossibleRegion() );
while( !itIn.IsAtEnd() )
{
itOut.Set(itIn.Get());
++itIn;
++itOut;
}
}
template< class TOutputImagePixelType >
void BrainMaskExtractionImageFilter< TOutputImagePixelType >
::CopyImage( typename OutputImageType::Pointer target, typename OutputImageType::Pointer source)
{
itk::ImageRegionConstIterator<OutputImageType> itIn( source, source->GetLargestPossibleRegion() );
itk::ImageRegionIterator<OutputImageType> itOut( target, target->GetLargestPossibleRegion() );
while( !itOut.IsAtEnd() )
{
itOut.Set( itIn.Get() );
++itIn;
++itOut;
}
}
template< class TOutputImagePixelType >
bool BrainMaskExtractionImageFilter< TOutputImagePixelType >
::CompareImages( typename OutputImageType::Pointer im1, typename OutputImageType::Pointer im2)
{
itk::ImageRegionConstIterator<OutputImageType> itIn( im1, im1->GetLargestPossibleRegion() );
itk::ImageRegionConstIterator<OutputImageType> itOut( im2, im2->GetLargestPossibleRegion() );
while( !itOut.IsAtEnd() )
{
if( itOut.Value() != itIn.Value() )
{
return false;
}
++itOut;
++itIn;
}
return true;
}
template< class TOutputImagePixelType >
int BrainMaskExtractionImageFilter< TOutputImagePixelType >
::ComputeHistogram( typename InputImageType::Pointer image)
{
// IMPORTANT: IMAGE MUST BE UNSIGNED SHORT
int N=65535;
int* histogram = new int[N];
for( int i=0; i<N; i++)
{
histogram[i] = 0;
}
itk::ImageRegionConstIterator<InputImageType> itIn( image, image->GetLargestPossibleRegion() );
long totVoxels = 0;
int max = -1;
int min = 9999999;
while( !itIn.IsAtEnd() )
{
histogram[ (int)(itIn.Value()) ]++;
if( itIn.Value()>max )
{
max = itIn.Value();
}
if( itIn.Value()<min )
{
min = itIn.Value();
}
++itIn;
++totVoxels;
}
//int EPS = 1;
int seuil = 0;
//int newseuil = (max + min)/2;
N = max;
double V = 0.0;
int S = 0;
double mean = 0.0;
for( int i=min; i<=max; i++)
{
mean += (double)(i) * (double)histogram[i];
}
mean /= (double)totVoxels;
//std::cout << "Min/Max/Mean: " << min << "/" << max << "/" << mean << std::endl;
//while( abs(newseuil - seuil)>EPS )
for( seuil = min; seuil<=max; seuil++)
{
//seuil = newseuil;
// compute the classes:
double mean0 = 0.0;
double mean1 = 0.0;
//double std0 = 0.0;
//double std1 = 0.0;
double num0 = 0.0;
double num1 = 0.0;
for( int i=min; i<seuil; i++)
{
//mean0 += (double)(histogram[i])/(double)(totVoxels) * (double)(i);
mean0 += (double)histogram[i] * (double)i;
num0 += (double)histogram[i];
}
for( int i=seuil; i<max; i++)
{
//mean1 += (double)(histogram[i])/(double)(totVoxels) * (double)(i);
mean1 += (double)histogram[i] * (double)i;
num1 += (double)histogram[i];
}
if( num0 )
{
mean0/=num0;
}
if( num1 )
{
mean1/=num1;
}
/*
for( int i=0; i<seuil; i++)
{
std0 += (double)histogram[i]/(double)totVoxels* ((double)i - mean0)*((double)i - mean0);
//std0 += (double)histogram[i]/num0* ((double)i - mean0)*((double)i - mean0);
}
for( int i=seuil; i<65536; i++)
{
std1 += (double)histogram[i]/(double)totVoxels* ((double)i - mean1)* ((double)i - mean1);
//std1 += (double)histogram[i]/num1* ((double)i - mean1)* ((double)i - mean1);
}
*/
//std0 = sqrt(std0);
//std1 = sqrt(std1);
//std::cout << "Classe 0: " << mean0 << " " << std0 << std::endl;
//std::cout << "Classe 1: " << mean1 << " " << std1 << std::endl;
//std::cout << "Classe 0: " << mean0 << std::endl;
//std::cout << "Classe 1: " << mean1 << std::endl;
//double alpha = std0*std1/(std0+std1);
//std::cout << "alpha: " << alpha << " " << std0 << " " << std1 << std::endl;
//newseuil = (int) (alpha*(mean0/std0 + mean1/std1));
//std::cout << "New threshold: " << newseuil << std::endl;
/*
if( newseuil > 65535 || newseuil<0)
{
std::cerr << "Error: threshold is too low or high, exiting" << std::endl;
return -1;
}*/
double Vm = num0 * (mean0 - mean)*(mean0 - mean) + num1*(mean1 - mean)*(mean1 - mean);
if( Vm > V )
{
V = Vm;
S = seuil;
//std::cout << "New seuil: " << S << std::endl;
//getchar();
}
}
delete [] histogram;
std::cout << "Seuil: " << S << std::endl;
return S;
}
}
#endif // __itkBrainMaskExtractionImageFilter_txx
diff --git a/Modules/DiffusionCore/Algorithms/itkCartesianToPolarVectorImageFilter.h b/Modules/DiffusionCore/Algorithms/itkCartesianToPolarVectorImageFilter.h
index 6642d8f..e9eeaa5 100644
--- a/Modules/DiffusionCore/Algorithms/itkCartesianToPolarVectorImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkCartesianToPolarVectorImageFilter.h
@@ -1,130 +1,130 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkCartesianToPolarVectorImageFilter_h
#define __itkCartesianToPolarVectorImageFilter_h
#include "itkUnaryFunctorImageFilter.h"
namespace itk
{
namespace Functor {
template< typename TInput, typename TOutput, bool symmetric >
class CartesianToPolarFunction
{
public:
CartesianToPolarFunction() {}
~CartesianToPolarFunction() {}
bool operator!=( const CartesianToPolarFunction & ) const
{
return false;
}
bool operator==( const CartesianToPolarFunction & other ) const
{
return !(*this != other);
}
inline TOutput operator()( const TInput & x )
{
TOutput opoint;
if(x[0] || x[1] || x[2])
{
opoint[0] = sqrt( x[0] * x[0] + x[1] * x[1] + x[2] * x[2] );
opoint[1] = atan2( x[1], x[0] );
opoint[2] = 0.5*itk::Math::pi - atan( x[2] / sqrt( x[0] * x[0] + x[1] * x[1] ) );
if(symmetric && opoint[1]>itk::Math::pi)
{
opoint[1] = opoint[1] - itk::Math::pi;
}
}
else
{
opoint[0] = 0;
opoint[1] = 0;
opoint[2] = 0;
}
return opoint;
}
};
} // end namespace functor
/** \class CartesianToPolarVectorImageFilter
*
*/
template <typename TInputImage, typename TOutputImage, bool symmetric>
class CartesianToPolarVectorImageFilter :
public
UnaryFunctorImageFilter<TInputImage,TOutputImage,
Functor::CartesianToPolarFunction<
typename TInputImage::PixelType,
typename TOutputImage::PixelType, symmetric> >
{
public:
/** Standard class typedefs. */
typedef CartesianToPolarVectorImageFilter Self;
typedef UnaryFunctorImageFilter<
TInputImage,TOutputImage,
Functor::CartesianToPolarFunction<
typename TInputImage::PixelType,
typename TOutputImage::PixelType, symmetric > > Superclass;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename OutputImageType::PixelType OutputPixelType;
typedef typename TInputImage::PixelType InputPixelType;
typedef typename InputPixelType::ValueType InputValueType;
/** Run-time type information (and related methods). */
itkTypeMacro( CartesianToPolarVectorImageFilter, UnaryFunctorImageFilter );
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Print internal ivars */
void PrintSelf(std::ostream& os, Indent indent) const
{ this->Superclass::PrintSelf( os, indent ); }
#ifdef ITK_USE_CONCEPT_CHECKING
/** Begin concept checking */
itkConceptMacro(InputHasNumericTraitsCheck,
(Concept::HasNumericTraits<InputValueType>));
/** End concept checking */
#endif
protected:
CartesianToPolarVectorImageFilter() {};
virtual ~CartesianToPolarVectorImageFilter() {};
private:
CartesianToPolarVectorImageFilter(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
};
} // end namespace itk
#endif // __itkCartesianToPolarVectorImageFilter_h
diff --git a/Modules/DiffusionCore/Algorithms/itkDiffusionOdfGeneralizedFaImageFilter.h b/Modules/DiffusionCore/Algorithms/itkDiffusionOdfGeneralizedFaImageFilter.h
index fb6c818..713de43 100644
--- a/Modules/DiffusionCore/Algorithms/itkDiffusionOdfGeneralizedFaImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkDiffusionOdfGeneralizedFaImageFilter.h
@@ -1,128 +1,128 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*===================================================================
This file is based heavily on a corresponding ITK filter.
===================================================================*/
#ifndef __itkDiffusionOdfGeneralizedFaImageFilter_h_
#define __itkDiffusionOdfGeneralizedFaImageFilter_h_
//#include "MitkDiffusionImagingMBIExports.h"
#include "itkImageToImageFilter.h"
//#include "vnl/vnl_matrix.h"
#include "vnl/vnl_vector_fixed.h"
#include "vnl/vnl_matrix.h"
#include "vnl/algo/vnl_svd.h"
#include "itkVectorContainer.h"
#include "itkVectorImage.h"
namespace itk{
/** \class DiffusionOdfGeneralizedFaImageFilter
*/
template< class TOdfPixelType,
class TGfaPixelType,
int NrOdfDirections>
class DiffusionOdfGeneralizedFaImageFilter :
public ImageToImageFilter< Image< Vector< TOdfPixelType, NrOdfDirections >, 3 >,
Image< TGfaPixelType, 3 > >
{
public:
enum GfaComputationMethod
{
GFA_STANDARD,
GFA_QUANTILES_HIGH_LOW,
GFA_QUANTILE_HIGH,
GFA_MAX_ODF_VALUE,
GFA_DECONVOLUTION_COEFFS,
GFA_MIN_MAX_NORMALIZED_STANDARD,
GFA_NORMALIZED_ENTROPY,
GFA_NEMATIC_ORDER_PARAMETER,
GFA_QUANTILE_LOW,
GFA_MIN_ODF_VALUE,
GFA_QUANTILES_LOW_HIGH,
GFA_STD_BY_MAX,
GFA_PRINCIPLE_CURVATURE,
GFA_GENERALIZED_GFA
};
typedef DiffusionOdfGeneralizedFaImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< Image< Vector< TOdfPixelType, NrOdfDirections >, 3 >,
Image< TGfaPixelType, 3 > >
Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(DiffusionOdfGeneralizedFaImageFilter,
ImageToImageFilter);
typedef TOdfPixelType OdfComponentType;
typedef TGfaPixelType DirectionPixelType;
typedef typename Superclass::InputImageType InputImageType;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename Superclass::OutputImageRegionType
OutputImageRegionType;
itkStaticConstMacro(NOdfDirections,int,NrOdfDirections);
void SetOdfImage( const InputImageType *image );
itkGetMacro(ComputationMethod, GfaComputationMethod);
itkSetMacro(ComputationMethod, GfaComputationMethod);
itkGetMacro(Param1, double);
itkSetMacro(Param1, double);
itkGetMacro(Param2, double);
itkSetMacro(Param2, double);
protected:
DiffusionOdfGeneralizedFaImageFilter();
~DiffusionOdfGeneralizedFaImageFilter() override {};
void PrintSelf(std::ostream& os, Indent indent) const override;
void BeforeThreadedGenerateData() override;
void ThreadedGenerateData( const
OutputImageRegionType &outputRegionForThread, ThreadIdType) override;
GfaComputationMethod m_ComputationMethod;
double m_Param1;
double m_Param2;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkDiffusionOdfGeneralizedFaImageFilter.txx"
#endif
#endif //__itkDiffusionOdfGeneralizedFaImageFilter_h_
diff --git a/Modules/DiffusionCore/Algorithms/itkDiffusionOdfGeneralizedFaImageFilter.txx b/Modules/DiffusionCore/Algorithms/itkDiffusionOdfGeneralizedFaImageFilter.txx
index 5b2186c..c0c7047 100644
--- a/Modules/DiffusionCore/Algorithms/itkDiffusionOdfGeneralizedFaImageFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkDiffusionOdfGeneralizedFaImageFilter.txx
@@ -1,220 +1,220 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkDiffusionOdfGeneralizedFaImageFilter_txx
#define __itkDiffusionOdfGeneralizedFaImageFilter_txx
#include <ctime>
#include <cstdio>
#include <cstdlib>
#define _USE_MATH_DEFINES
#include <cmath>
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionConstIteratorWithIndex.h"
#include "itkImageRegionIterator.h"
#include "itkArray.h"
#include "vnl/vnl_vector.h"
#include "itkOrientationDistributionFunction.h"
namespace itk {
template< class TOdfPixelType,
class TGfaPixelType,
int NrOdfDirections>
DiffusionOdfGeneralizedFaImageFilter< TOdfPixelType,
TGfaPixelType, NrOdfDirections>
::DiffusionOdfGeneralizedFaImageFilter() :
m_ComputationMethod(GFA_STANDARD)
{
// At least 1 inputs is necessary for a vector image.
// For images added one at a time we need at least six
this->SetNumberOfRequiredInputs( 1 );
}
template< class TOdfPixelType,
class TGfaPixelType,
int NrOdfDirections>
void DiffusionOdfGeneralizedFaImageFilter< TOdfPixelType,
TGfaPixelType, NrOdfDirections>
::BeforeThreadedGenerateData()
{
}
template< class TOdfPixelType,
class TGfaPixelType,
int NrOdfDirections>
void DiffusionOdfGeneralizedFaImageFilter< TOdfPixelType,
TGfaPixelType, NrOdfDirections>
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
ThreadIdType )
{
typename OutputImageType::Pointer outputImage =
static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0));
ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread);
oit.GoToBegin();
typedef itk::OrientationDistributionFunction<TOdfPixelType,NrOdfDirections> OdfType;
typedef ImageRegionConstIterator< InputImageType > InputIteratorType;
typedef typename InputImageType::PixelType OdfVectorType;
typename InputImageType::Pointer inputImagePointer = nullptr;
inputImagePointer = static_cast< InputImageType * >(
this->ProcessObject::GetInput(0) );
InputIteratorType git(inputImagePointer, outputRegionForThread );
git.GoToBegin();
while( !git.IsAtEnd() )
{
OdfVectorType b = git.Get();
TGfaPixelType outval = -1;
switch( m_ComputationMethod )
{
case GFA_STANDARD:
{
OdfType odf = b.GetDataPointer();
outval = odf.GetGeneralizedFractionalAnisotropy();
break;
}
case GFA_QUANTILES_HIGH_LOW:
{
vnl_vector_fixed<TOdfPixelType,NrOdfDirections> sorted;
for(int i=0; i<NrOdfDirections; i++)
{
sorted[i] = b[i];
}
std::sort( sorted.begin(), sorted.end() );
double q60 = sorted[floor(0.6*(double)NrOdfDirections+0.5)];
double q95 = sorted[floor(0.95*(double)NrOdfDirections+0.5)];
outval = q95/q60 - 1.0;
break;
}
case GFA_QUANTILE_HIGH:
{
vnl_vector_fixed<TOdfPixelType,NrOdfDirections> sorted;
for(int i=0; i<NrOdfDirections; i++)
{
sorted[i] = b[i];
}
std::sort( sorted.begin(), sorted.end() );
//double q40 = sorted[floor(0.4*(double)NrOdfDirections+0.5)];
double q95 = sorted[floor(0.95*(double)NrOdfDirections+0.5)];
outval = q95;
break;
}
case GFA_MAX_ODF_VALUE:
{
outval = b.GetVnlVector().max_value();
break;
}
case GFA_DECONVOLUTION_COEFFS:
{
break;
}
case GFA_MIN_MAX_NORMALIZED_STANDARD:
{
OdfType odf = b.GetDataPointer();
odf = odf.MinMaxNormalize();
outval = odf.GetGeneralizedFractionalAnisotropy();
break;
}
case GFA_NORMALIZED_ENTROPY:
{
OdfType odf = b.GetDataPointer();
outval = odf.GetNormalizedEntropy();
break;
}
case GFA_NEMATIC_ORDER_PARAMETER:
{
OdfType odf = b.GetDataPointer();
outval = odf.GetNematicOrderParameter();
break;
}
case GFA_QUANTILE_LOW:
{
vnl_vector_fixed<TOdfPixelType,NrOdfDirections> sorted;
for(int i=0; i<NrOdfDirections; i++)
{
sorted[i] = b[i];
}
std::sort( sorted.begin(), sorted.end() );
//double q40 = sorted[floor(0.4*(double)NrOdfDirections+0.5)];
double q05 = sorted[floor(0.05*(double)NrOdfDirections+0.5)];
outval = q05;
break;
}
case GFA_MIN_ODF_VALUE:
{
outval = b.GetVnlVector().min_value();
break;
}
case GFA_QUANTILES_LOW_HIGH:
{
vnl_vector_fixed<TOdfPixelType,NrOdfDirections> sorted;
for(int i=0; i<NrOdfDirections; i++)
{
sorted[i] = b[i];
}
std::sort( sorted.begin(), sorted.end() );
double q05 = sorted[floor(0.05*(double)NrOdfDirections+0.5)];
double q40 = sorted[floor(0.4*(double)NrOdfDirections+0.5)];
outval = q40/q05 - 1.0;
break;
}
case GFA_STD_BY_MAX:
{
OdfType odf = b.GetDataPointer();
outval = odf.GetStdDevByMaxValue();
break;
}
case GFA_PRINCIPLE_CURVATURE:
{
OdfType odf = b.GetDataPointer();
outval = odf.GetPrincipleCurvature(m_Param1, m_Param2, 0);
break;
}
case GFA_GENERALIZED_GFA:
{
OdfType odf = b.GetDataPointer();
outval = odf.GetGeneralizedGFA(m_Param1, m_Param2);
break;
}
}
oit.Set( outval );
++oit;
++git; // Gradient image iterator
}
std::cout << "One Thread finished calculation" << std::endl;
}
template< class TOdfPixelType,
class TGfaPixelType,
int NrOdfDirections>
void DiffusionOdfGeneralizedFaImageFilter< TOdfPixelType,
TGfaPixelType, NrOdfDirections>
::PrintSelf(std::ostream& os, Indent indent) const
{
Superclass::PrintSelf(os,indent);
}
}
#endif // __itkDiffusionOdfGeneralizedFaImageFilter_txx
diff --git a/Modules/DiffusionCore/Algorithms/itkDiffusionOdfPrepareVisualizationImageFilter.cpp b/Modules/DiffusionCore/Algorithms/itkDiffusionOdfPrepareVisualizationImageFilter.cpp
index 0df9292..d3e0160 100644
--- a/Modules/DiffusionCore/Algorithms/itkDiffusionOdfPrepareVisualizationImageFilter.cpp
+++ b/Modules/DiffusionCore/Algorithms/itkDiffusionOdfPrepareVisualizationImageFilter.cpp
@@ -1,181 +1,181 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkDiffusionOdfPrepareVisualizationImageFilter_cpp
#define __itkDiffusionOdfPrepareVisualizationImageFilter_cpp
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include "itkDiffusionOdfPrepareVisualizationImageFilter.h"
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionConstIteratorWithIndex.h"
#include "itkImageRegionIterator.h"
#include "itkArray.h"
#include "vnl/vnl_vector.h"
#include "itkOrientationDistributionFunction.h"
namespace itk {
template< class TOdfPixelType, int NrOdfDirections>
DiffusionOdfPrepareVisualizationImageFilter< TOdfPixelType, NrOdfDirections>
::DiffusionOdfPrepareVisualizationImageFilter() :
m_Threshold(0),
m_ScaleByGfaType(GfaFilterType::GFA_STANDARD),
m_DoScaleGfa(false),
m_GfaParam1(2),
m_GfaParam2(1)
{
// At least 1 inputs is necessary for a vector image.
// For images added one at a time we need at least six
this->SetNumberOfRequiredInputs( 1 );
}
template< class TOdfPixelType,
int NrOdfDirections>
void DiffusionOdfPrepareVisualizationImageFilter< TOdfPixelType,
NrOdfDirections>
::BeforeThreadedGenerateData()
{
if( m_NormalizationMethod == PV_GLOBAL_MAX )
{
typename InputImageType::Pointer inputImagePointer = nullptr;
inputImagePointer = static_cast< InputImageType * >(
this->ProcessObject::GetInput(0) );
typename GfaFilterType::Pointer filter = GfaFilterType::New();
filter->SetInput(inputImagePointer);
filter->SetNumberOfThreads(4);
filter->SetComputationMethod(GfaFilterType::GFA_MAX_ODF_VALUE);
filter->Update();
typedef typename itk::MinimumMaximumImageCalculator< typename GfaFilterType::OutputImageType >
MaxFilterType;
typename MaxFilterType::Pointer maxFilter = MaxFilterType::New();
maxFilter->SetImage(filter->GetOutput());
maxFilter->ComputeMaximum();
m_GlobalInputMaximum = maxFilter->GetMaximum();
}
//if(m_DoScaleGfa)
{
typename InputImageType::Pointer inputImagePointer = nullptr;
inputImagePointer = static_cast< InputImageType * >(
this->ProcessObject::GetInput(0) );
typename GfaFilterType::Pointer filter = GfaFilterType::New();
filter->SetInput(inputImagePointer);
filter->SetNumberOfThreads(4);
filter->SetComputationMethod(m_ScaleByGfaType);
filter->SetParam1(m_GfaParam1);
filter->SetParam2(m_GfaParam2);
filter->Update();
m_GfaImage = filter->GetOutput();
}
}
template< class TOdfPixelType,
int NrOdfDirections>
void DiffusionOdfPrepareVisualizationImageFilter< TOdfPixelType,
NrOdfDirections>
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
ThreadIdType )
{
typename OutputImageType::Pointer outputImage =
static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0));
ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread);
oit.GoToBegin();
typedef itk::OrientationDistributionFunction<TOdfPixelType,NrOdfDirections> OdfType;
typedef ImageRegionConstIterator< InputImageType > InputIteratorType;
typedef typename InputImageType::PixelType OdfVectorType;
typename InputImageType::Pointer inputImagePointer = nullptr;
inputImagePointer = static_cast< InputImageType * >(
this->ProcessObject::GetInput(0) );
InputIteratorType git(inputImagePointer, outputRegionForThread );
git.GoToBegin();
typedef ImageRegionConstIterator< GfaImageType > GfaIteratorType;
GfaIteratorType gfaIt(m_GfaImage, outputRegionForThread);
while( !git.IsAtEnd() )
{
OdfVectorType b = git.Get();
OdfType odf = b.GetDataPointer();
switch( m_NormalizationMethod )
{
case PV_NONE:
{
break;
}
case PV_MAX:
{
odf = odf.MaxNormalize();
break;
}
case PV_MIN_MAX:
{
odf = odf.MinMaxNormalize();
break;
}
case PV_GLOBAL_MAX:
{
odf *= 1.0/m_GlobalInputMaximum;
break;
}
case PV_MIN_MAX_INVERT:
{
odf = odf.MinMaxNormalize();
for(int i=0; i<NrOdfDirections; i++)
{
odf[i] = 1.0 - odf[i];
}
break;
}
}
if(m_DoScaleGfa)
{
odf *= gfaIt.Get();
++gfaIt;
}
odf *= 0.5;
oit.Set( odf.GetDataPointer() );
++oit;
++git; // Gradient image iterator
}
std::cout << "One Thread finished extraction" << std::endl;
}
template< class TOdfPixelType,
int NrOdfDirections>
void DiffusionOdfPrepareVisualizationImageFilter< TOdfPixelType,
NrOdfDirections>
::PrintSelf(std::ostream& os, Indent indent) const
{
Superclass::PrintSelf(os,indent);
os << indent << "m_Threshold: " <<
m_Threshold << std::endl;
}
}
#endif // __itkDiffusionOdfPrepareVisualizationImageFilter_cpp
diff --git a/Modules/DiffusionCore/Algorithms/itkDiffusionOdfPrepareVisualizationImageFilter.h b/Modules/DiffusionCore/Algorithms/itkDiffusionOdfPrepareVisualizationImageFilter.h
index b504ce3..39a5900 100644
--- a/Modules/DiffusionCore/Algorithms/itkDiffusionOdfPrepareVisualizationImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkDiffusionOdfPrepareVisualizationImageFilter.h
@@ -1,142 +1,142 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*===================================================================
This file is based heavily on a corresponding ITK filter.
===================================================================*/
#ifndef __itkDiffusionOdfPrepareVisualizationImageFilter_h_
#define __itkDiffusionOdfPrepareVisualizationImageFilter_h_
#include <MitkDiffusionCoreExports.h>
#include "itkImageToImageFilter.h"
//#include "vnl/vnl_matrix.h"
#include "vnl/vnl_vector_fixed.h"
#include "vnl/vnl_matrix.h"
#include "vnl/algo/vnl_svd.h"
#include "itkVectorContainer.h"
#include "itkVectorImage.h"
#include "itkDiffusionOdfGeneralizedFaImageFilter.h"
namespace itk{
/** \class DiffusionOdfPrepareVisualizationImageFilter
*/
template< class TOdfPixelType,
int NrOdfDirections>
class MITKDIFFUSIONCORE_EXPORT DiffusionOdfPrepareVisualizationImageFilter :
public ImageToImageFilter< Image< Vector< TOdfPixelType, NrOdfDirections >, 3 >,
Image< Vector< TOdfPixelType, NrOdfDirections >, 3 > >
{
public:
enum NormalizationMethods
{
PV_NONE,
PV_MAX,
PV_MIN_MAX,
PV_GLOBAL_MAX,
PV_MIN_MAX_INVERT
};
typedef DiffusionOdfPrepareVisualizationImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< Image< Vector< TOdfPixelType, NrOdfDirections >, 3 >,
Image< Vector< TOdfPixelType, NrOdfDirections >, 3 > >
Superclass;
typedef DiffusionOdfGeneralizedFaImageFilter<TOdfPixelType,TOdfPixelType,NrOdfDirections>
GfaFilterType;
typedef typename GfaFilterType::OutputImageType GfaImageType;
typedef typename GfaFilterType::GfaComputationMethod GfaComputationMethod;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(DiffusionOdfPrepareVisualizationImageFilter,
ImageToImageFilter);
typedef TOdfPixelType OdfComponentType;
typedef typename Superclass::InputImageType InputImageType;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename Superclass::OutputImageRegionType
OutputImageRegionType;
itkStaticConstMacro(NOdfDirections,int,NrOdfDirections);
itkSetMacro( Threshold, OdfComponentType );
itkGetMacro( Threshold, OdfComponentType );
itkSetMacro( NormalizationMethod, NormalizationMethods );
itkGetMacro( NormalizationMethod, NormalizationMethods );
itkSetMacro( ScaleByGfaType, GfaComputationMethod );
itkGetMacro( ScaleByGfaType, GfaComputationMethod );
itkSetMacro( DoScaleGfa, bool );
itkGetMacro( DoScaleGfa, bool );
itkSetMacro( GfaParam1, double );
itkGetMacro( GfaParam1, double );
itkSetMacro( GfaParam2, double );
itkGetMacro( GfaParam2, double );
protected:
DiffusionOdfPrepareVisualizationImageFilter();
~DiffusionOdfPrepareVisualizationImageFilter() {};
void PrintSelf(std::ostream& os, Indent indent) const;
void BeforeThreadedGenerateData();
void ThreadedGenerateData( const
OutputImageRegionType &outputRegionForThread, ThreadIdType);
private:
/** Threshold on the reference image data */
OdfComponentType m_Threshold;
NormalizationMethods m_NormalizationMethod;
OdfComponentType m_GlobalInputMaximum;
GfaComputationMethod m_ScaleByGfaType;
bool m_DoScaleGfa;
typename GfaImageType::Pointer m_GfaImage;
double m_GfaParam1;
double m_GfaParam2;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkDiffusionOdfPrepareVisualizationImageFilter.cpp"
#endif
#endif //__itkDiffusionOdfPrepareVisualizationImageFilter_h_
diff --git a/Modules/DiffusionCore/Algorithms/itkDiffusionTensorPrincipalDirectionImageFilter.h b/Modules/DiffusionCore/Algorithms/itkDiffusionTensorPrincipalDirectionImageFilter.h
index 36246cd..506e166 100644
--- a/Modules/DiffusionCore/Algorithms/itkDiffusionTensorPrincipalDirectionImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkDiffusionTensorPrincipalDirectionImageFilter.h
@@ -1,102 +1,102 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*===================================================================
This file is based heavily on a corresponding ITK filter.
===================================================================*/
#ifndef __itkDiffusionTensorPrincipalDirectionImageFilter_h_
#define __itkDiffusionTensorPrincipalDirectionImageFilter_h_
#include <MitkDiffusionCoreExports.h>
#include <itkImageToImageFilter.h>
#include <vnl/vnl_vector_fixed.h>
#include <vnl/vnl_matrix.h>
#include <vnl/algo/vnl_svd.h>
#include <itkVectorContainer.h>
#include <itkVectorImage.h>
#include <itkDiffusionTensor3D.h>
#include <mitkFiberBundle.h>
namespace itk{
/** \brief Extracts principal eigenvectors of the input tensors
*/
template< class TTensorPixelType>
class DiffusionTensorPrincipalDirectionImageFilter : public ImageToImageFilter< Image< DiffusionTensor3D<TTensorPixelType>, 3 >, Image< unsigned char, 3 > >
{
public:
typedef DiffusionTensorPrincipalDirectionImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< Image< DiffusionTensor3D<TTensorPixelType>, 3 >, Image< unsigned char, 3 > >
Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(DiffusionTensorPrincipalDirectionImageFilter, ImageToImageFilter)
typedef TTensorPixelType TensorComponentType;
typedef typename Superclass::InputImageType InputImageType;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename Superclass::OutputImageRegionType OutputImageRegionType;
typedef itk::Image<unsigned char, 3> ItkUcharImgType;
typedef vnl_vector_fixed< double, 3 > DirectionType;
typedef Image< float, 4 > PeakImageType;
void SetImage( const InputImageType *image );
// input
itkSetMacro( MaskImage, ItkUcharImgType::Pointer)
itkSetMacro( NormalizeVectors, bool)
itkSetMacro( UsePolarCoordinates, bool)
itkSetMacro( FaThreshold, float)
// output
itkGetMacro( PeakImage, PeakImageType::Pointer)
protected:
DiffusionTensorPrincipalDirectionImageFilter();
~DiffusionTensorPrincipalDirectionImageFilter() {}
void PrintSelf(std::ostream& os, Indent indent) const;
void BeforeThreadedGenerateData();
void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType );
void AfterThreadedGenerateData();
private:
bool m_NormalizeVectors; ///< Normalizes the output vector to length 1
ItkUcharImgType::Pointer m_MaskImage; ///< Extraction is only performed inside of the binary mask
PeakImageType::Pointer m_PeakImage;
bool m_UsePolarCoordinates;
float m_FaThreshold;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkDiffusionTensorPrincipalDirectionImageFilter.txx"
#endif
#endif //__itkDiffusionTensorPrincipalDirectionImageFilter_h_
diff --git a/Modules/DiffusionCore/Algorithms/itkDiffusionTensorPrincipalDirectionImageFilter.txx b/Modules/DiffusionCore/Algorithms/itkDiffusionTensorPrincipalDirectionImageFilter.txx
index 31e5942..79cddd1 100644
--- a/Modules/DiffusionCore/Algorithms/itkDiffusionTensorPrincipalDirectionImageFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkDiffusionTensorPrincipalDirectionImageFilter.txx
@@ -1,215 +1,215 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkDiffusionTensorPrincipalDirectionImageFilter_txx
#define __itkDiffusionTensorPrincipalDirectionImageFilter_txx
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include "itkDiffusionTensorPrincipalDirectionImageFilter.h"
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionConstIteratorWithIndex.h"
#include "itkImageRegionIterator.h"
#include "itkArray.h"
#include "vnl/vnl_vector.h"
#include <boost/progress.hpp>
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkCellArray.h>
#include <vtkPoints.h>
#include <vtkPolyLine.h>
namespace itk {
template< class TTensorPixelType>
DiffusionTensorPrincipalDirectionImageFilter< TTensorPixelType>::DiffusionTensorPrincipalDirectionImageFilter()
: m_NormalizeVectors(true)
, m_UsePolarCoordinates(false)
, m_FaThreshold(0.2)
{
this->SetNumberOfRequiredInputs( 1 );
}
template< class TTensorPixelType>
void DiffusionTensorPrincipalDirectionImageFilter< TTensorPixelType>::BeforeThreadedGenerateData()
{
typename InputImageType::Pointer inputImagePointer = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
Vector<double,3> spacing3 = inputImagePointer->GetSpacing();
mitk::Point3D origin3 = inputImagePointer->GetOrigin();
itk::Matrix<double, 3, 3> direction3 = inputImagePointer->GetDirection();
ImageRegion<3> imageRegion3 = inputImagePointer->GetLargestPossibleRegion();
if (m_MaskImage.IsNull())
{
m_MaskImage = ItkUcharImgType::New();
m_MaskImage->SetSpacing( spacing3 );
m_MaskImage->SetOrigin( origin3 );
m_MaskImage->SetDirection( direction3 );
m_MaskImage->SetRegions( imageRegion3 );
m_MaskImage->Allocate();
m_MaskImage->FillBuffer(1);
}
typename OutputImageType::Pointer outputImage = OutputImageType::New();
outputImage->SetSpacing( spacing3 );
outputImage->SetOrigin( origin3 );
outputImage->SetDirection( direction3 );
outputImage->SetRegions( imageRegion3 );
outputImage->Allocate();
outputImage->FillBuffer(0);
this->SetNthOutput(0, outputImage);
itk::Vector<double, 4> spacing4;
itk::Point<float, 4> origin4;
itk::Matrix<double, 4, 4> direction4;
itk::ImageRegion<4> imageRegion4;
spacing4[0] = spacing3[0]; spacing4[1] = spacing3[1]; spacing4[2] = spacing3[2]; spacing4[3] = 1;
origin4[0] = origin3[0]; origin4[1] = origin3[1]; origin4[2] = origin3[2]; origin3[3] = 0;
for (int r=0; r<3; r++)
for (int c=0; c<3; c++)
direction4[r][c] = direction3[r][c];
direction4[3][3] = 1;
imageRegion4.SetSize(0, imageRegion3.GetSize()[0]);
imageRegion4.SetSize(1, imageRegion3.GetSize()[1]);
imageRegion4.SetSize(2, imageRegion3.GetSize()[2]);
imageRegion4.SetSize(3, 3);
m_PeakImage = PeakImageType::New();
m_PeakImage->SetSpacing( spacing4 );
m_PeakImage->SetOrigin( origin4 );
m_PeakImage->SetDirection( direction4 );
m_PeakImage->SetRegions( imageRegion4 );
m_PeakImage->Allocate();
m_PeakImage->FillBuffer(0.0);
}
template< class TTensorPixelType>
void DiffusionTensorPrincipalDirectionImageFilter< TTensorPixelType>
::AfterThreadedGenerateData()
{
}
template< class TTensorPixelType>
void DiffusionTensorPrincipalDirectionImageFilter< TTensorPixelType>
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, ThreadIdType )
{
typedef itk::DiffusionTensor3D<TTensorPixelType> TensorType;
typedef ImageRegionConstIterator< InputImageType > InputIteratorType;
typename InputImageType::Pointer inputImagePointer = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetPrimaryOutput());
ImageRegionIterator< OutputImageType > numDirectionsIterator(outputImage, outputRegionForThread);
InputIteratorType tensorIterator(inputImagePointer, outputRegionForThread );
while( !tensorIterator.IsAtEnd() )
{
typename InputImageType::IndexType index = tensorIterator.GetIndex();
if (m_MaskImage->GetPixel(index)==0)
{
++tensorIterator;
++numDirectionsIterator;
continue;
}
typename InputImageType::PixelType b = tensorIterator.Get();
TensorType tensor = b.GetDataPointer();
typename PeakImageType::IndexType peakIndex;
peakIndex[0] = tensorIterator.GetIndex()[0];
peakIndex[1] = tensorIterator.GetIndex()[1];
peakIndex[2] = tensorIterator.GetIndex()[2];
typename TensorType::EigenValuesArrayType eigenvalues;
typename TensorType::EigenVectorsMatrixType eigenvectors;
if(tensor.GetTrace()!=0)
{
tensor.ComputeEigenAnalysis(eigenvalues, eigenvectors);
vnl_vector_fixed<float,3> vec;
vec[0] = eigenvectors(2,0);
vec[1] = eigenvectors(2,1);
vec[2] = eigenvectors(2,2);
vec.normalize();
vnl_vector_fixed<float,3> out; out.fill(0);
float fa = tensor.GetFractionalAnisotropy();
if (fa<m_FaThreshold)
vec.fill(0.0);
else
{
if (!m_NormalizeVectors)
vec *= fa;
if (m_UsePolarCoordinates)
{
if(vec[0] || vec[1] || vec[2])
{
out[0] = sqrt( vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2] );
out[1] = atan2( vec[1], vec[0] );
out[2] = 0.5*itk::Math::pi - atan( vec[2] / sqrt( vec[0] * vec[0] + vec[1] * vec[1] ) );
if(out[1]>itk::Math::pi)
{
out[1] = out[1] - itk::Math::pi;
}
}
else
{
out[0] = 0;
out[1] = 0;
out[2] = 0;
}
}
else
{
out = vec;
}
}
peakIndex[3] = 0;
m_PeakImage->SetPixel(peakIndex, out[0]);
peakIndex[3] = 1;
m_PeakImage->SetPixel(peakIndex, out[1]);
peakIndex[3] = 2;
m_PeakImage->SetPixel(peakIndex, out[2]);
numDirectionsIterator.Set( 1 );
}
++numDirectionsIterator;
++tensorIterator;
}
std::cout << "One Thread finished extraction" << std::endl;
}
template< class TTensorPixelType>
void DiffusionTensorPrincipalDirectionImageFilter< TTensorPixelType>
::PrintSelf(std::ostream& , Indent ) const
{
}
}
#endif
diff --git a/Modules/DiffusionCore/Algorithms/itkDistanceMapFilter.h b/Modules/DiffusionCore/Algorithms/itkDistanceMapFilter.h
index 3d76c27..2d17f2e 100644
--- a/Modules/DiffusionCore/Algorithms/itkDistanceMapFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkDistanceMapFilter.h
@@ -1,94 +1,94 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 ITKDISTANCEMAPFILTER_H_
#define ITKDISTANCEMAPFILTER_H_
#include "itkImageToImageFilter.h"
#include "itkImage.h"
#include "mitkImage.h"
namespace itk
{
template < class TInputImage, class TOutputImage >
class DistanceMapFilter : public ImageToImageFilter<TInputImage, TOutputImage>
{
/**
* \brief This filter creates a map of the distance to the nearest point on a binary mask.
*
*/
public:
/** Typedef for input ImageType. */
typedef TInputImage InputImageType;
/** Typedef for input imageType Pointer. */
typedef typename InputImageType::Pointer InputImagePointer;
/** Typedef for output ImageType. */
typedef TOutputImage OutputImageType;
/** Typedef for input imageType Pointer. */
typedef typename OutputImageType::Pointer OutputImagePointer;
public:
/** */
typedef DistanceMapFilter Self;
/** Superclass */
typedef ImageToImageFilter<InputImageType, OutputImageType> Superclass;
/** Smart Pointer */
typedef SmartPointer<Self> Pointer;
/** Smart Pointer */
typedef SmartPointer<const Self> ConstPointer;
/** */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Generate Data. The image will be divided into a number of pieces, a number of threads
will be spawned and Threaded GenerateData() will be called in each thread. */
void GenerateData() override;
protected:
/** Constructor */
DistanceMapFilter();
/** Destructor */
~DistanceMapFilter() override;
protected:
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkDistanceMapFilter.txx"
#endif
#endif
diff --git a/Modules/DiffusionCore/Algorithms/itkDistanceMapFilter.txx b/Modules/DiffusionCore/Algorithms/itkDistanceMapFilter.txx
index 54d479c..7e7ce5e 100644
--- a/Modules/DiffusionCore/Algorithms/itkDistanceMapFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkDistanceMapFilter.txx
@@ -1,79 +1,79 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _itkDistanceMapFilter_txx
#define _itkDistanceMapFilter_txx
#include "itkDistanceMapFilter.h"
#include <itkSignedMaurerDistanceMapImageFilter.h>
namespace itk
{
template< class TInputImage, class TOutputImage >
DistanceMapFilter<TInputImage, TOutputImage>::DistanceMapFilter()
{
}
template< class TInputImage, class TOutputImage >
DistanceMapFilter<TInputImage, TOutputImage>::~DistanceMapFilter()
{
}
template< class TInputImage, class TOutputImage >
void DistanceMapFilter<TInputImage, TOutputImage>::GenerateData()
{
typedef itk::SignedMaurerDistanceMapImageFilter<InputImageType, OutputImageType> DistanceFilterType;
typename DistanceFilterType::Pointer dFilter = DistanceFilterType::New();
dFilter->SetInput(this->GetInput());
dFilter->SetUseImageSpacing(true);
dFilter->SetSquaredDistance(false);
dFilter->SetInsideIsPositive(true);
dFilter->Update();
typename OutputImageType::Pointer outputImg = dFilter->GetOutput();
typedef itk::ImageRegionIterator<OutputImageType> ImageIteratorType;
ImageIteratorType outIt(outputImg, outputImg->GetRequestedRegion());
outIt.GoToBegin();
while(!outIt.IsAtEnd())
{
typename OutputImageType::PixelType p = outIt.Get();
p *= -1;
outIt.Set(p);
++outIt;
}
Superclass::SetNthOutput( 0, outputImg );
}
}
#endif // _itkDistanceMapFilter_txx
diff --git a/Modules/DiffusionCore/Algorithms/itkDwiGradientLengthCorrectionFilter.cpp b/Modules/DiffusionCore/Algorithms/itkDwiGradientLengthCorrectionFilter.cpp
index 3e942f9..b8cdf17 100644
--- a/Modules/DiffusionCore/Algorithms/itkDwiGradientLengthCorrectionFilter.cpp
+++ b/Modules/DiffusionCore/Algorithms/itkDwiGradientLengthCorrectionFilter.cpp
@@ -1,86 +1,86 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*=========================================================================
Program: Tensor ToolKit - TTK
Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkElectrostaticRepulsionDiffusionGradientReductionFilter.txx $
Language: C++
Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $
Version: $Revision: 68 $
Copyright (c) INRIA 2010. All rights reserved.
See LICENSE.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "itkDwiGradientLengthCorrectionFilter.h"
itk::DwiGradientLengthCorrectionFilter::DwiGradientLengthCorrectionFilter()
: m_ReferenceBValue(0)
, m_RoundingValue(0)
, m_ReferenceGradientDirectionContainer(nullptr)
, m_OutputGradientDirectionContainer(nullptr)
{
}
itk::DwiGradientLengthCorrectionFilter::~DwiGradientLengthCorrectionFilter()
{
}
void itk::DwiGradientLengthCorrectionFilter::GenerateData()
{
if(m_ReferenceBValue == 0 || m_RoundingValue == 0 || m_ReferenceGradientDirectionContainer.IsNull())
itkExceptionMacro("Wrong initialization");
m_OutputGradientDirectionContainer = GradientDirectionContainerType::New();
m_NewBValue = itk::NumericTraits<double>::max();
GradientDirectionContainerType::ConstIterator it = m_ReferenceGradientDirectionContainer->Begin();
for(; it != m_ReferenceGradientDirectionContainer->End(); ++it)
{
const double twonorm = it.Value().two_norm();
const double currentBValue = m_ReferenceBValue*twonorm*twonorm ;
const double roundedBValue = int((currentBValue + 0.5 * m_RoundingValue)/m_RoundingValue)*m_RoundingValue;
if (roundedBValue<m_NewBValue && roundedBValue>1)
m_NewBValue = roundedBValue;
}
it = m_ReferenceGradientDirectionContainer->Begin();
for(; it != m_ReferenceGradientDirectionContainer->End(); ++it)
{
const double twonorm = it.Value().two_norm();
const double currentBValue = m_ReferenceBValue*twonorm*twonorm ;
const double roundedBValue = int((currentBValue + 0.5 * m_RoundingValue)/m_RoundingValue)*m_RoundingValue;
if (roundedBValue>1)
{
const double f = std::sqrt(roundedBValue/m_NewBValue);
GradientDirectionType grad = it.Value();
m_OutputGradientDirectionContainer->push_back( grad.normalize() * f );
}
else
{
GradientDirectionType grad; grad.fill(0.0);
m_OutputGradientDirectionContainer->push_back( grad );
}
}
}
diff --git a/Modules/DiffusionCore/Algorithms/itkDwiGradientLengthCorrectionFilter.h b/Modules/DiffusionCore/Algorithms/itkDwiGradientLengthCorrectionFilter.h
index 4f857da..ad8e203 100644
--- a/Modules/DiffusionCore/Algorithms/itkDwiGradientLengthCorrectionFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkDwiGradientLengthCorrectionFilter.h
@@ -1,75 +1,75 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _itk_DwiGradientLengthCorrectionFilter_h_
#define _itk_DwiGradientLengthCorrectionFilter_h_
#include <itkProcessObject.h>
#include <vnl/vnl_vector_fixed.h>
#include <itkVectorContainer.h>
#include <MitkDiffusionCoreExports.h>
namespace itk
{
class MITKDIFFUSIONCORE_EXPORT DwiGradientLengthCorrectionFilter : public ProcessObject
{
public:
typedef DwiGradientLengthCorrectionFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ProcessObject Superclass;
typedef vnl_vector_fixed< double, 3 > GradientDirectionType;
typedef itk::VectorContainer< unsigned int, GradientDirectionType > GradientDirectionContainerType;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
itkTypeMacro(DwiGradientLengthCorrectionFilter,ProcessObject)
void GenerateData() override;
void Update() override{
this->GenerateData();
}
// input
itkSetMacro(RoundingValue, int)
itkSetMacro(ReferenceBValue, double)
itkSetMacro(ReferenceGradientDirectionContainer, GradientDirectionContainerType::Pointer)
// output
itkGetMacro(OutputGradientDirectionContainer, GradientDirectionContainerType::Pointer)
itkGetMacro(NewBValue, double)
protected:
DwiGradientLengthCorrectionFilter();
~DwiGradientLengthCorrectionFilter() override;
double m_NewBValue;
double m_ReferenceBValue;
int m_RoundingValue;
GradientDirectionContainerType::Pointer m_ReferenceGradientDirectionContainer;
GradientDirectionContainerType::Pointer m_OutputGradientDirectionContainer;
};
} // end of namespace
#endif
diff --git a/Modules/DiffusionCore/Algorithms/itkDwiNormilzationFilter.h b/Modules/DiffusionCore/Algorithms/itkDwiNormilzationFilter.h
index a799146..7de201f 100644
--- a/Modules/DiffusionCore/Algorithms/itkDwiNormilzationFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkDwiNormilzationFilter.h
@@ -1,101 +1,101 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*===================================================================
This file is based heavily on a corresponding ITK filter.
===================================================================*/
#ifndef __itkDwiNormilzationFilter_h_
#define __itkDwiNormilzationFilter_h_
#include "itkImageToImageFilter.h"
#include "itkVectorImage.h"
#include <itkLabelStatisticsImageFilter.h>
#include <itkImageRegionIteratorWithIndex.h>
#include <itkShiftScaleImageFilter.h>
#include <mitkDiffusionPropertyHelper.h>
namespace itk{
/** \class DwiNormilzationFilter
* \brief Normalizes the data vectors either using the specified reference value or the voxelwise baseline value.
*/
template< class TInPixelType >
class DwiNormilzationFilter :
public ImageToImageFilter< VectorImage< TInPixelType, 3 >, VectorImage< TInPixelType, 3 > >
{
public:
typedef DwiNormilzationFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< VectorImage< TInPixelType, 3 >, VectorImage< TInPixelType, 3 > > Superclass;
typedef typename Superclass::InputImageType InputImageType;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename Superclass::OutputImageRegionType OutputImageRegionType;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(DwiNormilzationFilter, ImageToImageFilter)
typedef itk::Image< double, 3 > DoubleImageType;
typedef itk::Image< unsigned char, 3 > UcharImageType;
typedef itk::Image< unsigned short, 3 > BinImageType;
typedef itk::Image< TInPixelType, 3 > TInPixelImageType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer GradientContainerType;
typedef ImageRegionConstIterator< InputImageType > InputIteratorType;
typedef ImageRegionConstIterator< UcharImageType > MaskIteratorType;
itkSetMacro( GradientDirections, GradientContainerType )
itkSetMacro( ScalingFactor, TInPixelType )
itkSetMacro( MaskImage, UcharImageType::Pointer )
itkSetMacro( NewMean, double )
itkSetMacro( NewStdev, double )
protected:
DwiNormilzationFilter();
~DwiNormilzationFilter() {}
void PrintSelf(std::ostream& os, Indent indent) const;
void BeforeThreadedGenerateData();
void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType);
UcharImageType::Pointer m_MaskImage;
GradientContainerType m_GradientDirections;
int m_B0Index;
TInPixelType m_ScalingFactor;
double m_Mean;
double m_Stdev;
double m_NewMean;
double m_NewStdev;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkDwiNormilzationFilter.txx"
#endif
#endif //__itkDwiNormilzationFilter_h_
diff --git a/Modules/DiffusionCore/Algorithms/itkDwiNormilzationFilter.txx b/Modules/DiffusionCore/Algorithms/itkDwiNormilzationFilter.txx
index 5d344c3..3b9ac7b 100644
--- a/Modules/DiffusionCore/Algorithms/itkDwiNormilzationFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkDwiNormilzationFilter.txx
@@ -1,183 +1,183 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkDwiNormilzationFilter_txx
#define __itkDwiNormilzationFilter_txx
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionConstIteratorWithIndex.h"
#include "itkImageRegionIterator.h"
#include <itkNumericTraits.h>
namespace itk {
template< class TInPixelType >
DwiNormilzationFilter< TInPixelType>::DwiNormilzationFilter()
: m_B0Index(-1)
, m_NewMean(1000)
, m_NewStdev(500)
{
this->SetNumberOfRequiredInputs( 1 );
}
template< class TInPixelType >
void DwiNormilzationFilter< TInPixelType>::BeforeThreadedGenerateData()
{
typename InputImageType::Pointer inputImagePointer = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
m_B0Index = -1;
for (unsigned int i=0; i<inputImagePointer->GetVectorLength(); i++)
{
GradientDirectionType g = m_GradientDirections->GetElement(i);
if (g.magnitude()<0.001)
m_B0Index = i;
}
if (m_B0Index==-1)
itkExceptionMacro(<< "DwiNormilzationFilter: No b-Zero indecies found!");
if (m_MaskImage.IsNull())
{
// initialize mask image
m_MaskImage = UcharImageType::New();
m_MaskImage->SetSpacing( inputImagePointer->GetSpacing() );
m_MaskImage->SetOrigin( inputImagePointer->GetOrigin() );
m_MaskImage->SetDirection( inputImagePointer->GetDirection() );
m_MaskImage->SetRegions( inputImagePointer->GetLargestPossibleRegion() );
m_MaskImage->Allocate();
m_MaskImage->FillBuffer(1);
}
else
std::cout << "DwiNormilzationFilter: using mask image" << std::endl;
InputIteratorType git( inputImagePointer, inputImagePointer->GetLargestPossibleRegion() );
MaskIteratorType mit( m_MaskImage, m_MaskImage->GetLargestPossibleRegion() );
git.GoToBegin();
mit.GoToBegin();
int n = 0;
m_Mean = 0;
m_Stdev = 0;
while( !git.IsAtEnd() )
{
if (mit.Get()>0)
{
for (unsigned int i=0; i<inputImagePointer->GetVectorLength(); i++)
{
if ((int)i==m_B0Index)
continue;
m_Mean += git.Get()[i];
n++;
}
}
++git;
++mit;
}
m_Mean /= n;
git.GoToBegin();
mit.GoToBegin();
while( !git.IsAtEnd() )
{
if (mit.Get()>0)
{
for (unsigned int i=0; i<inputImagePointer->GetVectorLength(); i++)
{
if ((int)i==m_B0Index)
continue;
double diff = (double)(git.Get()[i]) - m_Mean;
m_Stdev += diff*diff;
}
}
++git;
++mit;
}
m_Stdev = std::sqrt(m_Stdev/(n-1));
MITK_INFO << "Mean: " << m_Mean;
MITK_INFO << "Stdev: " << m_Stdev;
}
template< class TInPixelType >
void DwiNormilzationFilter< TInPixelType>::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, ThreadIdType )
{
typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0));
ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread);
oit.GoToBegin();
typename InputImageType::Pointer inputImagePointer = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
MaskIteratorType mit( m_MaskImage, outputRegionForThread );
mit.GoToBegin();
InputIteratorType git( inputImagePointer, outputRegionForThread );
git.GoToBegin();
while( !git.IsAtEnd() )
{
typename InputImageType::PixelType pix = git.Get();
typename OutputImageType::PixelType outPix;
outPix.SetSize(inputImagePointer->GetVectorLength());
for (unsigned int i=0; i<inputImagePointer->GetVectorLength(); i++)
{
double val = (double)pix[i] - m_Mean;
val /= m_Stdev;
val *= m_NewStdev;
val += m_NewMean;
if (val<0)
{
val = 0;
MITK_INFO << "Negative value.";
}
if (val>32767)
{
val = 32767;
MITK_INFO << "Range overflow. Value is too large for datatype short.";
}
outPix[i] = (TInPixelType)val;
}
oit.Set(outPix);
++mit;
++oit;
++git;
}
std::cout << "One Thread finished calculation" << std::endl;
}
template< class TInPixelType >
void
DwiNormilzationFilter< TInPixelType>
::PrintSelf(std::ostream& os, Indent indent) const
{
Superclass::PrintSelf(os,indent);
}
}
#endif // __itkDwiNormilzationFilter_txx
diff --git a/Modules/DiffusionCore/Algorithms/itkElectrostaticRepulsionDiffusionGradientReductionFilter.h b/Modules/DiffusionCore/Algorithms/itkElectrostaticRepulsionDiffusionGradientReductionFilter.h
index 2b5f6ca..219d226 100644
--- a/Modules/DiffusionCore/Algorithms/itkElectrostaticRepulsionDiffusionGradientReductionFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkElectrostaticRepulsionDiffusionGradientReductionFilter.h
@@ -1,128 +1,128 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*=========================================================================
Program: Tensor ToolKit - TTK
Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkElectrostaticRepulsionDiffusionGradientReductionFilter.h $
Language: C++
Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $
Version: $Revision: 68 $
Copyright (c) INRIA 2010. All rights reserved.
See LICENSE.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef _itk_ElectrostaticRepulsionDiffusionGradientReductionFilter_h_
#define _itk_ElectrostaticRepulsionDiffusionGradientReductionFilter_h_
#include <itkImageToImageFilter.h>
#include <itkVectorImage.h>
#include <itkPointShell.h>
namespace itk
{
/**
* \brief Select subset of the input vectors equally distributed over the sphere using an iterative electrostatic repulsion strategy. */
template <class TInputScalarType, class TOutputScalarType>
class ElectrostaticRepulsionDiffusionGradientReductionFilter
: public ImageToImageFilter<itk::VectorImage<TInputScalarType,3>, itk::VectorImage<TOutputScalarType,3> >
{
public:
typedef ElectrostaticRepulsionDiffusionGradientReductionFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< itk::VectorImage<TOutputScalarType,3>, itk::VectorImage<TOutputScalarType,3> >
Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(ElectrostaticRepulsionDiffusionGradientReductionFilter, ImageToImageFilter)
typedef TInputScalarType InputScalarType;
typedef itk::VectorImage<InputScalarType,3> InputImageType;
typedef typename InputImageType::PixelType InputPixelType;
typedef TOutputScalarType OutputScalarType;
typedef itk::VectorImage<OutputScalarType,3> OutputImageType;
typedef typename OutputImageType::PixelType OutputPixelType;
typedef OutputScalarType BaselineScalarType;
typedef BaselineScalarType BaselinePixelType;
typedef typename itk::Image<BaselinePixelType,3> BaselineImageType;
typedef vnl_vector_fixed< double, 3 > GradientDirectionType;
typedef itk::VectorContainer< unsigned int, GradientDirectionType > GradientDirectionContainerType;
typedef std::vector<unsigned int> IndicesVector;
typedef std::map<unsigned int, IndicesVector> BValueMap;
itkGetMacro(OriginalGradientDirections, GradientDirectionContainerType::Pointer)
itkSetMacro(OriginalGradientDirections, GradientDirectionContainerType::Pointer)
itkGetMacro(GradientDirections, GradientDirectionContainerType::Pointer)
itkSetMacro(GradientDirections, GradientDirectionContainerType::Pointer)
itkSetMacro(UseFirstN, bool)
IndicesVector GetUsedGradientIndices(){return m_UsedGradientIndices;}
void SetOriginalBValueMap(BValueMap inp){m_OriginalBValueMap = inp;}
void SetShellSelectionBValueMap(BValueMap inp){m_InputBValueMap = inp;}
void SetNumGradientDirections(std::vector<unsigned int> numDirs){m_NumGradientDirections = numDirs;}
void UpdateOutputInformation() override;
protected:
ElectrostaticRepulsionDiffusionGradientReductionFilter();
~ElectrostaticRepulsionDiffusionGradientReductionFilter() override {}
void GenerateData() override;
double Costs(); ///< calculates electrostatic energy of current direction set
GradientDirectionContainerType::Pointer m_GradientDirections; ///< container for the subsampled output gradient directions
GradientDirectionContainerType::Pointer m_OriginalGradientDirections; ///< input gradient directions
IndicesVector m_UsedGradientIndices;
IndicesVector m_UnusedGradientIndices;
IndicesVector m_BaselineImageIndices;
BValueMap m_OriginalBValueMap;
BValueMap m_InputBValueMap;
bool m_UseFirstN;
std::vector<unsigned int> m_NumGradientDirections;
};
} // end of namespace
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkElectrostaticRepulsionDiffusionGradientReductionFilter.txx"
#endif
#endif
diff --git a/Modules/DiffusionCore/Algorithms/itkElectrostaticRepulsionDiffusionGradientReductionFilter.txx b/Modules/DiffusionCore/Algorithms/itkElectrostaticRepulsionDiffusionGradientReductionFilter.txx
index 607e5f8..a802c81 100644
--- a/Modules/DiffusionCore/Algorithms/itkElectrostaticRepulsionDiffusionGradientReductionFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkElectrostaticRepulsionDiffusionGradientReductionFilter.txx
@@ -1,270 +1,270 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*=========================================================================
Program: Tensor ToolKit - TTK
Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkElectrostaticRepulsionDiffusionGradientReductionFilter.txx $
Language: C++
Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $
Version: $Revision: 68 $
Copyright (c) INRIA 2010. All rights reserved.
See LICENSE.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef _itk_ElectrostaticRepulsionDiffusionGradientReductionFilter_txx_
#define _itk_ElectrostaticRepulsionDiffusionGradientReductionFilter_txx_
#endif
#include "itkElectrostaticRepulsionDiffusionGradientReductionFilter.h"
#include <itkMersenneTwisterRandomVariateGenerator.h>
#include <ctime>
#include <itkImageRegionIterator.h>
#include <itkImageRegion.h>
namespace itk
{
template <class TInputScalarType, class TOutputScalarType>
ElectrostaticRepulsionDiffusionGradientReductionFilter<TInputScalarType, TOutputScalarType>
::ElectrostaticRepulsionDiffusionGradientReductionFilter()
: m_UseFirstN(false)
{
this->SetNumberOfRequiredInputs( 1 );
}
template <class TInputScalarType, class TOutputScalarType>
double
ElectrostaticRepulsionDiffusionGradientReductionFilter<TInputScalarType, TOutputScalarType>
::Costs()
{
double costs = 2*itk::Math::pi;
for (IndicesVector::iterator it = m_UsedGradientIndices.begin(); it!=m_UsedGradientIndices.end(); ++it)
{
for (IndicesVector::iterator it2 = m_UsedGradientIndices.begin(); it2!=m_UsedGradientIndices.end(); ++it2)
if (it != it2)
{
vnl_vector_fixed<double,3> v1 = m_OriginalGradientDirections->at(*it);
vnl_vector_fixed<double,3> v2 = m_OriginalGradientDirections->at(*it2);
v1.normalize(); v2.normalize();
double temp = dot_product(v1,v2);
if (temp>1)
temp = 1;
else if (temp<-1)
temp = -1;
double angle = acos(temp);
if (angle<costs)
costs = angle;
temp = dot_product(-v1,v2);
if (temp>1)
temp = 1;
else if (temp<-1)
temp = -1;
angle = acos(temp);
if (angle<costs)
costs = angle;
}
}
return costs;
}
template <class TInputScalarType, class TOutputScalarType>
void
ElectrostaticRepulsionDiffusionGradientReductionFilter<TInputScalarType, TOutputScalarType>
::GenerateData()
{
itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer randgen = itk::Statistics::MersenneTwisterRandomVariateGenerator::New();
if(m_InputBValueMap.empty() || m_NumGradientDirections.size()!=m_InputBValueMap.size())
mitkThrow() << "Vector of the number of desired gradient directions contains more elements than the specified target b-value map.";
BValueMap manipulatedMap = m_InputBValueMap;
IndicesVector final_gradient_indices;
int shellCounter = 0;
for(BValueMap::iterator it = m_InputBValueMap.begin(); it != m_InputBValueMap.end(); it++ )
{
randgen->SetSeed();
m_UsedGradientIndices.clear();
m_UnusedGradientIndices.clear();
MITK_INFO << "Shell number: " << shellCounter;
unsigned int c=0;
for (unsigned int i=0; i<it->second.size(); i++)
{
if (c<m_NumGradientDirections[shellCounter])
m_UsedGradientIndices.push_back(it->second.at(i));
else
m_UnusedGradientIndices.push_back(it->second.at(i));
c++;
}
if ( it->second.size() <= m_NumGradientDirections[shellCounter] )
{
itkWarningMacro( << "current directions: " << it->second.size() << " wanted directions: " << m_NumGradientDirections[shellCounter]);
m_NumGradientDirections[shellCounter] = it->second.size();
}
else if (!m_UseFirstN)
{
double minAngle = Costs();
double newMinAngle = 0;
MITK_INFO << "minimum angle: " << 180*minAngle/itk::Math::pi;
int stagnationCount = 0;
int rejectionCount = 0;
int maxRejections = m_NumGradientDirections[shellCounter] * 1000;
if (maxRejections<10000)
maxRejections = 10000;
int iUsed = 0;
if (m_UsedGradientIndices.size()>0)
{
while ( stagnationCount<1000 && rejectionCount<maxRejections )
{
// make proposal for new gradient configuration by randomly removing one of the currently used directions and instead adding one of the unused directions
int iUnUsed = randgen->GetIntegerVariate() % m_UnusedGradientIndices.size();
int vUsed = m_UsedGradientIndices.at(iUsed);
int vUnUsed = m_UnusedGradientIndices.at(iUnUsed);
m_UsedGradientIndices.at(iUsed) = vUnUsed;
m_UnusedGradientIndices.at(iUnUsed) = vUsed;
newMinAngle = Costs(); // calculate costs of proposed configuration
if (newMinAngle > minAngle) // accept or reject proposal
{
MITK_INFO << "minimum angle: " << 180*newMinAngle/itk::Math::pi;
if ( (newMinAngle-minAngle)<0.01 )
stagnationCount++;
else
stagnationCount = 0;
minAngle = newMinAngle;
rejectionCount = 0;
}
else
{
rejectionCount++;
m_UsedGradientIndices.at(iUsed) = vUsed;
m_UnusedGradientIndices.at(iUnUsed) = vUnUsed;
}
iUsed++;
iUsed = iUsed % m_UsedGradientIndices.size();
}
}
}
manipulatedMap[it->first] = m_UsedGradientIndices;
shellCounter++;
for (auto gidx : m_UsedGradientIndices)
final_gradient_indices.push_back(gidx);
}
std::sort(final_gradient_indices.begin(), final_gradient_indices.end());
int vecLength = 0 ;
for(BValueMap::iterator it = manipulatedMap.begin(); it != manipulatedMap.end(); it++)
vecLength += it->second.size();
// initialize output image
typename OutputImageType::Pointer outImage = OutputImageType::New();
outImage->SetSpacing( this->GetInput()->GetSpacing() ); // Set the image spacing
outImage->SetOrigin( this->GetInput()->GetOrigin() ); // Set the image origin
outImage->SetDirection( this->GetInput()->GetDirection() ); // Set the image direction
outImage->SetLargestPossibleRegion( this->GetInput()->GetLargestPossibleRegion());
outImage->SetBufferedRegion( this->GetInput()->GetLargestPossibleRegion() );
outImage->SetRequestedRegion( this->GetInput()->GetLargestPossibleRegion() );
outImage->SetVectorLength( final_gradient_indices.size() ); // Set the vector length
outImage->Allocate();
itk::ImageRegionIterator< OutputImageType > newIt(outImage, outImage->GetLargestPossibleRegion());
newIt.GoToBegin();
typename InputImageType::Pointer inImage = const_cast<InputImageType*>(this->GetInput(0));
itk::ImageRegionIterator< InputImageType > oldIt(inImage, inImage->GetLargestPossibleRegion());
oldIt.GoToBegin();
// initial new value of voxel
OutputPixelType newVec;
newVec.SetSize( final_gradient_indices.size() );
newVec.AllocateElements( final_gradient_indices.size() );
// generate new pixel values
while(!newIt.IsAtEnd())
{
// init new vector with zeros
newVec.Fill(0.0);
InputPixelType oldVec = oldIt.Get();
for (unsigned int i=0; i<final_gradient_indices.size(); ++i)
newVec[i] = oldVec[final_gradient_indices.at(i)];
// int index = 0;
// for(BValueMap::iterator it=manipulatedMap.begin(); it!=manipulatedMap.end(); it++)
// for(unsigned int j=0; j<it->second.size(); j++)
// {
// newVec[index] = oldVec[it->second.at(j)];
// index++;
// }
newIt.Set(newVec);
++newIt;
++oldIt;
}
// set new gradient directions
m_GradientDirections = GradientDirectionContainerType::New();
for (unsigned int i=0; i<final_gradient_indices.size(); ++i)
m_GradientDirections->InsertElement(i, m_OriginalGradientDirections->at(final_gradient_indices.at(i)));
// int index = 0;
// for(BValueMap::iterator it = manipulatedMap.begin(); it != manipulatedMap.end(); it++)
// for(unsigned int j = 0; j < it->second.size(); j++)
// {
// m_GradientDirections->InsertElement(index, m_OriginalGradientDirections->at(it->second.at(j)));
// index++;
// }
this->SetNumberOfRequiredOutputs (1);
this->SetNthOutput (0, outImage);
MITK_INFO << "...done";
}
template <class TInputScalarType, class TOutputScalarType>
void
ElectrostaticRepulsionDiffusionGradientReductionFilter<TInputScalarType, TOutputScalarType>
::UpdateOutputInformation()
{
Superclass::UpdateOutputInformation();
int vecLength = 0 ;
for(unsigned int index = 0; index < m_NumGradientDirections.size(); index++)
{
vecLength += m_NumGradientDirections[index];
}
this->GetOutput()->SetVectorLength( vecLength );
}
} // end of namespace
diff --git a/Modules/DiffusionCore/Algorithms/itkExtractChannelFromRgbaImageFilter.cpp b/Modules/DiffusionCore/Algorithms/itkExtractChannelFromRgbaImageFilter.cpp
index 04e5d63..f0eae50 100644
--- a/Modules/DiffusionCore/Algorithms/itkExtractChannelFromRgbaImageFilter.cpp
+++ b/Modules/DiffusionCore/Algorithms/itkExtractChannelFromRgbaImageFilter.cpp
@@ -1,171 +1,171 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "itkExtractChannelFromRgbaImageFilter.h"
// VTK
#include <vtkPolyLine.h>
#include <vtkCellArray.h>
#include <vtkCellData.h>
// misc
#include <math.h>
namespace itk{
template< class ReferenceImageType, class OutputImageType >
ExtractChannelFromRgbaImageFilter< ReferenceImageType, OutputImageType >::ExtractChannelFromRgbaImageFilter():
m_Channel(RED)
{
}
template< class ReferenceImageType, class OutputImageType >
ExtractChannelFromRgbaImageFilter< ReferenceImageType, OutputImageType >::~ExtractChannelFromRgbaImageFilter()
{
}
template< class ReferenceImageType, class OutputImageType >
void ExtractChannelFromRgbaImageFilter< ReferenceImageType, OutputImageType >::GenerateData()
{
typename InputImageType::Pointer rgbaImage = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
typename OutputImageType::Pointer outputImage =
static_cast< OutputImageType * >(this->ProcessObject::GetPrimaryOutput());
typename InputImageType::RegionType region = rgbaImage->GetLargestPossibleRegion();
outputImage->SetSpacing( m_ReferenceImage->GetSpacing() ); // Set the image spacing
outputImage->SetOrigin( m_ReferenceImage->GetOrigin() ); // Set the image origin
outputImage->SetDirection( m_ReferenceImage->GetDirection() ); // Set the image direction
outputImage->SetRegions( m_ReferenceImage->GetLargestPossibleRegion());
outputImage->Allocate();
outputImage->FillBuffer(0);
float* outImageBufferPointer = outputImage->GetBufferPointer();
itk::Image< short, 3 >::Pointer counterImage = itk::Image< short, 3 >::New();
counterImage->SetSpacing( m_ReferenceImage->GetSpacing() ); // Set the image spacing
counterImage->SetOrigin( m_ReferenceImage->GetOrigin() ); // Set the image origin
counterImage->SetDirection( m_ReferenceImage->GetDirection() ); // Set the image direction
counterImage->SetRegions( m_ReferenceImage->GetLargestPossibleRegion());
counterImage->Allocate();
counterImage->FillBuffer(0);
short* counterImageBufferPointer = counterImage->GetBufferPointer();
int w = m_ReferenceImage->GetLargestPossibleRegion().GetSize().GetElement(0);
int h = m_ReferenceImage->GetLargestPossibleRegion().GetSize().GetElement(1);
int d = m_ReferenceImage->GetLargestPossibleRegion().GetSize().GetElement(2);
typedef ImageRegionConstIterator< InputImageType > InImageIteratorType;
InImageIteratorType rgbaIt(rgbaImage, region);
rgbaIt.GoToBegin();
while(!rgbaIt.IsAtEnd()){
InPixelType x = rgbaIt.Get();
++rgbaIt;
itk::Point<float, 3> vertex;
itk::Index<3> index = rgbaIt.GetIndex();
rgbaImage->TransformIndexToPhysicalPoint(index, vertex);
outputImage->TransformPhysicalPointToIndex(vertex, index);
itk::ContinuousIndex<float, 3> contIndex;
outputImage->TransformPhysicalPointToContinuousIndex(vertex, contIndex);
float frac_x = contIndex[0] - index[0];
float frac_y = contIndex[1] - index[1];
float frac_z = contIndex[2] - index[2];
int px = index[0];
if (frac_x<0)
{
px -= 1;
frac_x += 1;
}
int py = index[1];
if (frac_y<0)
{
py -= 1;
frac_y += 1;
}
int pz = index[2];
if (frac_z<0)
{
pz -= 1;
frac_z += 1;
}
frac_x = 1-frac_x;
frac_y = 1-frac_y;
frac_z = 1-frac_z;
// int coordinates inside image?
if (px < 0 || px >= w-1)
continue;
if (py < 0 || py >= h-1)
continue;
if (pz < 0 || pz >= d-1)
continue;
OutPixelType out = 0.0f;
switch (m_Channel)
{
case RED:
out = (float)x.GetRed()/255;
break;
case GREEN:
out = (float)x.GetGreen()/255;
break;
case BLUE:
out = (float)x.GetBlue()/255;
break;
case ALPHA:
out = (float)x.GetAlpha()/255;
}
outImageBufferPointer[( px + w*(py + h*pz ))] += out*( frac_x)*( frac_y)*( frac_z);
outImageBufferPointer[( px + w*(py+1+ h*pz ))] += out*( frac_x)*(1-frac_y)*( frac_z);
outImageBufferPointer[( px + w*(py + h*pz+h))] += out*( frac_x)*( frac_y)*(1-frac_z);
outImageBufferPointer[( px + w*(py+1+ h*pz+h))] += out*( frac_x)*(1-frac_y)*(1-frac_z);
outImageBufferPointer[( px+1 + w*(py + h*pz ))] += out*(1-frac_x)*( frac_y)*( frac_z);
outImageBufferPointer[( px+1 + w*(py + h*pz+h))] += out*(1-frac_x)*( frac_y)*(1-frac_z);
outImageBufferPointer[( px+1 + w*(py+1+ h*pz ))] += out*(1-frac_x)*(1-frac_y)*( frac_z);
outImageBufferPointer[( px+1 + w*(py+1+ h*pz+h))] += out*(1-frac_x)*(1-frac_y)*(1-frac_z);
counterImageBufferPointer[( px + w*(py + h*pz ))] += 1;
counterImageBufferPointer[( px + w*(py+1+ h*pz ))] += 1;
counterImageBufferPointer[( px + w*(py + h*pz+h))] += 1;
counterImageBufferPointer[( px + w*(py+1+ h*pz+h))] += 1;
counterImageBufferPointer[( px+1 + w*(py + h*pz ))] += 1;
counterImageBufferPointer[( px+1 + w*(py + h*pz+h))] += 1;
counterImageBufferPointer[( px+1 + w*(py+1+ h*pz ))] += 1;
counterImageBufferPointer[( px+1 + w*(py+1+ h*pz+h))] += 1;
}
typedef ImageRegionIterator< OutputImageType > OutImageIteratorType;
OutImageIteratorType outIt(outputImage, outputImage->GetLargestPossibleRegion());
outIt.GoToBegin();
typedef ImageRegionConstIterator< itk::Image< short, 3 > > CountImageIteratorType;
CountImageIteratorType counterIt(counterImage, counterImage->GetLargestPossibleRegion());
counterIt.GoToBegin();
while(!outIt.IsAtEnd() && !counterIt.IsAtEnd()){
if (counterIt.Value()>0)
outIt.Set(outIt.Value()/counterIt.Value());
++outIt;
++counterIt;
}
}
}
diff --git a/Modules/DiffusionCore/Algorithms/itkExtractChannelFromRgbaImageFilter.h b/Modules/DiffusionCore/Algorithms/itkExtractChannelFromRgbaImageFilter.h
index 462da14..6b35e73 100644
--- a/Modules/DiffusionCore/Algorithms/itkExtractChannelFromRgbaImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkExtractChannelFromRgbaImageFilter.h
@@ -1,73 +1,73 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkExtractChannelFromRgbaImageFilter_h__
#define __itkExtractChannelFromRgbaImageFilter_h__
#include <itkImageToImageFilter.h>
#include <itkImage.h>
#include <itkRGBAPixel.h>
#include <itkVectorImage.h>
namespace itk{
template< class ReferenceImageType, class OutputImageType >
class ExtractChannelFromRgbaImageFilter : public ImageToImageFilter< itk::Image<itk::RGBAPixel<unsigned char>,3>, OutputImageType >
{
public:
enum Channel {
RED,
GREEN,
BLUE,
ALPHA
};
typedef ExtractChannelFromRgbaImageFilter Self;
typedef ProcessObject Superclass;
typedef SmartPointer< Self > Pointer;
typedef SmartPointer< const Self > ConstPointer;
typedef itk::Image<itk::RGBAPixel<unsigned char>,3> InputImageType;
typedef typename OutputImageType::PixelType OutPixelType;
typedef typename InputImageType::PixelType InPixelType;
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
itkTypeMacro( ExtractChannelFromRgbaImageFilter, ImageSource );
/** Upsampling factor **/
void GenerateData();
itkSetMacro(Channel, Channel)
itkSetMacro(ReferenceImage, typename ReferenceImageType::Pointer)
protected:
ExtractChannelFromRgbaImageFilter();
virtual ~ExtractChannelFromRgbaImageFilter();
Channel m_Channel;
typename ReferenceImageType::Pointer m_ReferenceImage;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkExtractChannelFromRgbaImageFilter.cpp"
#endif
#endif // __itkExtractChannelFromRgbaImageFilter_h__
diff --git a/Modules/DiffusionCore/Algorithms/itkExtractDwiChannelFilter.h b/Modules/DiffusionCore/Algorithms/itkExtractDwiChannelFilter.h
index 18ea6cf..afc1834 100644
--- a/Modules/DiffusionCore/Algorithms/itkExtractDwiChannelFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkExtractDwiChannelFilter.h
@@ -1,77 +1,77 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*===================================================================
This file is based heavily on a corresponding ITK filter.
===================================================================*/
#ifndef __itkExtractDwiChannelFilter_h_
#define __itkExtractDwiChannelFilter_h_
#include "itkImageToImageFilter.h"
#include "itkVectorImage.h"
#include <itkImageRegionIteratorWithIndex.h>
#include <mitkImage.h>
namespace itk{
/** \class ExtractDwiChannelFilter
* \brief Remove specified channels from diffusion-weighted image.
*/
template< class TInPixelType >
class ExtractDwiChannelFilter :
public ImageToImageFilter< VectorImage< TInPixelType, 3 >, Image< TInPixelType, 3 > >
{
public:
typedef ExtractDwiChannelFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< VectorImage< TInPixelType, 3 >, Image< TInPixelType, 3 > > Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(ExtractDwiChannelFilter, ImageToImageFilter)
typedef typename Superclass::InputImageType InputImageType;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename Superclass::OutputImageRegionType OutputImageRegionType;
itkSetMacro( ChannelIndex, unsigned int )
protected:
ExtractDwiChannelFilter();
~ExtractDwiChannelFilter() override {}
void BeforeThreadedGenerateData() override;
void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType ) override;
unsigned int m_ChannelIndex;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkExtractDwiChannelFilter.txx"
#endif
#endif //__itkExtractDwiChannelFilter_h_
diff --git a/Modules/DiffusionCore/Algorithms/itkExtractDwiChannelFilter.txx b/Modules/DiffusionCore/Algorithms/itkExtractDwiChannelFilter.txx
index f422f1d..7116b65 100644
--- a/Modules/DiffusionCore/Algorithms/itkExtractDwiChannelFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkExtractDwiChannelFilter.txx
@@ -1,71 +1,71 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkExtractDwiChannelFilter_txx
#define __itkExtractDwiChannelFilter_txx
#include <ctime>
#include <cstdio>
#include <cstdlib>
#define _USE_MATH_DEFINES
#include <cmath>
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionConstIteratorWithIndex.h"
#include "itkImageRegionIterator.h"
namespace itk {
template< class TInPixelType >
ExtractDwiChannelFilter< TInPixelType>::ExtractDwiChannelFilter()
{
this->SetNumberOfRequiredInputs( 1 );
}
template< class TInPixelType >
void ExtractDwiChannelFilter< TInPixelType>::BeforeThreadedGenerateData()
{
typename InputImageType::Pointer inputImagePointer = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
if ( inputImagePointer->GetVectorLength()<=m_ChannelIndex )
itkExceptionMacro("Index out of bounds!");
}
template< class TInPixelType >
void ExtractDwiChannelFilter< TInPixelType>::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, ThreadIdType )
{
typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0));
ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread);
oit.GoToBegin();
typedef ImageRegionConstIterator< InputImageType > InputIteratorType;
typename InputImageType::Pointer inputImagePointer = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
InputIteratorType git( inputImagePointer, outputRegionForThread );
git.GoToBegin();
while( !git.IsAtEnd() )
{
oit.Set( git.Get()[m_ChannelIndex] );
++oit;
++git;
}
}
}
#endif // __itkExtractDwiChannelFilter_txx
diff --git a/Modules/DiffusionCore/Algorithms/itkFlipPeaksFilter.cpp b/Modules/DiffusionCore/Algorithms/itkFlipPeaksFilter.cpp
index dd12554..1e84b99 100644
--- a/Modules/DiffusionCore/Algorithms/itkFlipPeaksFilter.cpp
+++ b/Modules/DiffusionCore/Algorithms/itkFlipPeaksFilter.cpp
@@ -1,99 +1,99 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkFlipPeaksFilter_cpp
#define __itkFlipPeaksFilter_cpp
#include "itkFlipPeaksFilter.h"
#include <itkImageRegionConstIterator.h>
#include <itkImageRegionConstIteratorWithIndex.h>
#include <itkImageRegionIterator.h>
#include <vnl/vnl_vector.h>
#include <itkOrientationDistributionFunction.h>
#include <itkContinuousIndex.h>
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkCellArray.h>
#include <vtkPoints.h>
#include <vtkPolyLine.h>
#include <boost/math/special_functions.hpp>
#include <boost/progress.hpp>
using namespace boost::math;
namespace itk {
template< class PixelType >
FlipPeaksFilter< PixelType>::FlipPeaksFilter()
{
this->SetNumberOfRequiredInputs(1);
}
template< class PixelType >
void FlipPeaksFilter< PixelType>
::BeforeThreadedGenerateData()
{
typename InputImageType::Pointer input = static_cast< InputImageType* >( this->ProcessObject::GetInput(0) );
// typename OutputImageType::Pointer output = OutputImageType::New();
// output->SetSpacing( input->GetSpacing() );
// output->SetOrigin( input->GetOrigin() );
// output->SetDirection( input->GetDirection() );
// output->SetRegions( input->GetLargestPossibleRegion() );
// output->Allocate();
// output->FillBuffer(0.0);
}
template< class PixelType >
void FlipPeaksFilter< PixelType>
::AfterThreadedGenerateData()
{
}
template< class PixelType >
void FlipPeaksFilter< PixelType>
::ThreadedGenerateData( const OutputImageRegionType& outputRegionForThread, ThreadIdType )
{
typename InputImageType::Pointer input_image = static_cast< InputImageType* >( this->ProcessObject::GetInput(0) );
typename OutputImageType::Pointer output_image = static_cast< OutputImageType* >( this->ProcessObject::GetOutput(0) );
ImageRegionIterator< InputImageType > iit(input_image, outputRegionForThread );
ImageRegionIterator< OutputImageType > oit(output_image, outputRegionForThread );
while( !iit.IsAtEnd() )
{
typename InputImageType::IndexType idx = iit.GetIndex();
oit.Set(iit.Get());
if (m_FlipX && idx[3]%3==0)
oit.Set(-1*iit.Get());
if (m_FlipY && idx[3]%3==1)
oit.Set(-1*iit.Get());
if (m_FlipZ && idx[3]%3==2)
oit.Set(-1*iit.Get());
++iit;
++oit;
}
}
}
#endif // __itkFlipPeaksFilter_cpp
diff --git a/Modules/DiffusionCore/Algorithms/itkFlipPeaksFilter.h b/Modules/DiffusionCore/Algorithms/itkFlipPeaksFilter.h
index 64ca362..7caa0d4 100644
--- a/Modules/DiffusionCore/Algorithms/itkFlipPeaksFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkFlipPeaksFilter.h
@@ -1,84 +1,83 @@
-/*=========================================================================
+/*===================================================================
- Program: Insight Segmentation & Registration Toolkit
- Module: $RCSfile: itkDiffusionTensor3DReconstructionImageFilter.h,v $
- Language: C++
- Date: $Date: 2006-03-27 17:01:06 $
- Version: $Revision: 1.12 $
+The Medical Imaging Interaction Toolkit (MITK)
- Copyright (c) Insight Software Consortium. All rights reserved.
- See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
+Copyright (c) German Cancer Research Center.
- This software is distributed WITHOUT ANY WARRANTY; without even
- the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- PURPOSE. See the above copyright notices for more information.
+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 __itkFlipPeaksFilter_h_
#define __itkFlipPeaksFilter_h_
#include "itkImageToImageFilter.h"
#include "vnl/vnl_vector_fixed.h"
#include "vnl/vnl_matrix.h"
#include "vnl/algo/vnl_svd.h"
#include "itkVectorContainer.h"
#include "itkVectorImage.h"
#include <mitkFiberBundle.h>
#include <itkOrientationDistributionFunction.h>
#include <mitkPeakImage.h>
namespace itk{
/**
* \brief Flip peaks along specified axes
*/
template< class PixelType >
class FlipPeaksFilter : public ImageToImageFilter< mitk::PeakImage::ItkPeakImageType, mitk::PeakImage::ItkPeakImageType >
{
public:
typedef FlipPeaksFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< mitk::PeakImage::ItkPeakImageType, mitk::PeakImage::ItkPeakImageType > Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(FlipPeaksFilter, ImageToImageFilter)
typedef typename Superclass::InputImageType InputImageType;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename OutputImageType::RegionType OutputImageRegionType;
itkSetMacro( FlipX, bool) ///< flip peaks in x direction
itkSetMacro( FlipY, bool) ///< flip peaks in y direction
itkSetMacro( FlipZ, bool) ///< flip peaks in z direction
protected:
FlipPeaksFilter();
~FlipPeaksFilter(){}
void BeforeThreadedGenerateData();
void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType threadID );
void AfterThreadedGenerateData();
private:
bool m_FlipX;
bool m_FlipY;
bool m_FlipZ;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkFlipPeaksFilter.cpp"
#endif
#endif //__itkFlipPeaksFilter_h_
diff --git a/Modules/DiffusionCore/Algorithms/itkFourDToVectorImageFilter.cpp b/Modules/DiffusionCore/Algorithms/itkFourDToVectorImageFilter.cpp
index f42cc52..bc3a077 100644
--- a/Modules/DiffusionCore/Algorithms/itkFourDToVectorImageFilter.cpp
+++ b/Modules/DiffusionCore/Algorithms/itkFourDToVectorImageFilter.cpp
@@ -1,101 +1,101 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkFourDToVectorImageFilter_cpp
#define __itkFourDToVectorImageFilter_cpp
#include "itkFourDToVectorImageFilter.h"
#include <itkImageRegionConstIterator.h>
#include <itkImageRegionConstIteratorWithIndex.h>
#include <itkImageRegionIterator.h>
#include <vnl/vnl_vector.h>
#include <itkOrientationDistributionFunction.h>
#include <itkContinuousIndex.h>
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkCellArray.h>
#include <vtkPoints.h>
#include <vtkPolyLine.h>
#include <boost/math/special_functions.hpp>
#include <boost/progress.hpp>
using namespace boost::math;
namespace itk {
template< class PixelType >
FourDToVectorImageFilter< PixelType>::FourDToVectorImageFilter()
{
}
template< class PixelType >
void FourDToVectorImageFilter< PixelType>
::GenerateData()
{
Vector<float, 4> spacing4 = m_InputImage->GetSpacing();
Point<float, 4> origin4 = m_InputImage->GetOrigin();
Matrix<double, 4, 4> direction4 = m_InputImage->GetDirection();
ImageRegion<4> imageRegion4 = m_InputImage->GetLargestPossibleRegion();
Vector<double, 3> spacing3;
Point<float, 3> origin3;
Matrix<double, 3, 3> direction3;
ImageRegion<3> imageRegion3;
spacing3[0] = spacing4[0]; spacing3[1] = spacing4[1]; spacing3[2] = spacing4[2];
origin3[0] = origin4[0]; origin3[1] = origin4[1]; origin3[2] = origin4[2];
for (int r=0; r<3; r++)
for (int c=0; c<3; c++)
direction3[r][c] = direction4[r][c];
imageRegion3.SetSize(0, imageRegion4.GetSize()[0]);
imageRegion3.SetSize(1, imageRegion4.GetSize()[1]);
imageRegion3.SetSize(2, imageRegion4.GetSize()[2]);
m_OutputImage = OutputImageType::New();
m_OutputImage->SetSpacing( spacing3 );
m_OutputImage->SetOrigin( origin3 );
m_OutputImage->SetDirection( direction3 );
m_OutputImage->SetRegions( imageRegion3 );
m_OutputImage->SetVectorLength(imageRegion4.GetSize()[3]);
m_OutputImage->Allocate();
typename OutputImageType::PixelType pix; pix.SetSize(imageRegion4.GetSize()[3]); pix.Fill(0.0);
m_OutputImage->FillBuffer(pix);
ImageRegionIterator< OutputImageType > oit(m_OutputImage, m_OutputImage->GetLargestPossibleRegion() );
while( !oit.IsAtEnd() )
{
auto idx3 = oit.GetIndex();
typename OutputImageType::PixelType pix = oit.Get();
for (unsigned int i=0; i<pix.GetSize(); ++i)
{
typename InputImageType::IndexType idx4;
idx4[0] = idx3[0]; idx4[1] = idx3[1]; idx4[2] = idx3[2]; idx4[3] = i;
pix[i] = m_InputImage->GetPixel(idx4);
}
oit.Set(pix);
++oit;
}
}
}
#endif // __itkFourDToVectorImageFilter_cpp
diff --git a/Modules/DiffusionCore/Algorithms/itkFourDToVectorImageFilter.h b/Modules/DiffusionCore/Algorithms/itkFourDToVectorImageFilter.h
index f4c29d9..acb682b 100644
--- a/Modules/DiffusionCore/Algorithms/itkFourDToVectorImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkFourDToVectorImageFilter.h
@@ -1,74 +1,73 @@
-/*=========================================================================
+/*===================================================================
- Program: Insight Segmentation & Registration Toolkit
- Module: $RCSfile: itkDiffusionTensor3DReconstructionImageFilter.h,v $
- Language: C++
- Date: $Date: 2006-03-27 17:01:06 $
- Version: $Revision: 1.12 $
+The Medical Imaging Interaction Toolkit (MITK)
- Copyright (c) Insight Software Consortium. All rights reserved.
- See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
+Copyright (c) German Cancer Research Center.
- This software is distributed WITHOUT ANY WARRANTY; without even
- the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- PURPOSE. See the above copyright notices for more information.
+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 __itkFourDToVectorImageFilter_h_
#define __itkFourDToVectorImageFilter_h_
#include "itkImageToImageFilter.h"
#include <itkImage.h>
#include <itkVectorImage.h>
namespace itk{
/**
* \brief Flip peaks along specified axes
*/
template< class PixelType >
class FourDToVectorImageFilter : public ProcessObject
{
public:
typedef FourDToVectorImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ProcessObject Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(FourDToVectorImageFilter, ProcessObject)
typedef Image<PixelType, 4> InputImageType;
typedef VectorImage<PixelType, 3> OutputImageType;
typedef typename OutputImageType::RegionType OutputImageRegionType;
itkSetMacro(InputImage, typename InputImageType::Pointer)
itkGetMacro(OutputImage, typename OutputImageType::Pointer)
void GenerateData();
protected:
FourDToVectorImageFilter();
~FourDToVectorImageFilter(){}
typename InputImageType::Pointer m_InputImage;
typename OutputImageType::Pointer m_OutputImage;
private:
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkFourDToVectorImageFilter.cpp"
#endif
#endif //__itkFourDToVectorImageFilter_h_
diff --git a/Modules/DiffusionCore/Algorithms/itkGaussianInterpolateImageFunction.h b/Modules/DiffusionCore/Algorithms/itkGaussianInterpolateImageFunction.h
index 08e7259..bc8e942 100644
--- a/Modules/DiffusionCore/Algorithms/itkGaussianInterpolateImageFunction.h
+++ b/Modules/DiffusionCore/Algorithms/itkGaussianInterpolateImageFunction.h
@@ -1,186 +1,186 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*===================================================================
This file is based heavily on a corresponding ITK filter.
===================================================================*/
#ifndef __itkGaussianInterpolateImageFunction_h
#define __itkGaussianInterpolateImageFunction_h
#include "itkInterpolateImageFunction.h"
#include "itkConceptChecking.h"
#include "itkFixedArray.h"
#include "vnl/vnl_erf.h"
namespace itk
{
/** \class GaussianInterpolateImageFunction
* \brief Evaluates the Gaussian interpolation of an image.
*
* This class defines an N-dimensional Gaussian interpolation function using
* the vnl error function. The two parameters associated with this function
* are:
* 1. Sigma - a scalar array of size ImageDimension determining the width
* of the interpolation function.
* 2. Alpha - a scalar specifying the cutoff distance over which the function
* is calculated.
*
* \ingroup ImageFunctions ImageInterpolators
*/
template <class TInputImage, class TCoordRep = double>
class ITK_EXPORT GaussianInterpolateImageFunction :
public InterpolateImageFunction<TInputImage, TCoordRep>
{
public:
/** Standard class typedefs. */
typedef GaussianInterpolateImageFunction Self;
typedef InterpolateImageFunction<TInputImage, TCoordRep> Superclass;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
/** Run-time type information (and related methods). */
itkTypeMacro( GaussianInterpolateImageFunction, InterpolateImageFunction );
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** ImageDimension constant */
itkStaticConstMacro( ImageDimension, unsigned int,
TInputImage::ImageDimension );
/** OutputType typedef support. */
typedef typename Superclass::OutputType OutputType;
/** InputImageType typedef support. */
typedef typename Superclass::InputImageType InputImageType;
/** RealType typedef support. */
typedef typename Superclass::RealType RealType;
/** Index typedef support. */
typedef typename Superclass::IndexType IndexType;
/** ContinuousIndex typedef support. */
typedef typename Superclass::ContinuousIndexType ContinuousIndexType;
/** Array typedef support */
typedef FixedArray<RealType,
itkGetStaticConstMacro( ImageDimension )> ArrayType;
/**
* Set input image
*/
void SetInputImage( const TInputImage *image ) override
{
Superclass::SetInputImage( image );
this->ComputeBoundingBox();
}
/**
* Set/Get ivars
*/
virtual void SetSigma( const ArrayType s )
{
itkDebugMacro( "setting Sigma to " << s );
if( this->m_Sigma != s )
{
this->m_Sigma = s;
this->ComputeBoundingBox();
this->Modified();
}
}
itkGetConstMacro( Sigma, ArrayType );
void SetSigma( RealType *s )
{
ArrayType sigma;
for( unsigned int d = 0; d < ImageDimension; d++ )
{
sigma[d] = s[d];
}
this->SetSigma( sigma );
}
virtual void SetAlpha( const RealType a )
{
itkDebugMacro( "setting Alpha to " << a );
if( this->m_Alpha != a )
{
this->m_Alpha = a;
this->ComputeBoundingBox();
this->Modified();
}
}
itkGetConstMacro( Alpha, RealType );
void SetParameters( RealType *sigma, RealType alpha )
{
this->SetSigma( sigma );
this->SetAlpha( alpha );
}
/**
* Evaluate at the given index
*/
OutputType EvaluateAtContinuousIndex(
const ContinuousIndexType & cindex ) const override
{
return this->EvaluateAtContinuousIndex( cindex, nullptr );
}
/**
* Evaluate function value and gradient at the given index
*/
virtual OutputType EvaluateAtContinuousIndex(
const ContinuousIndexType &, OutputType * ) const;
protected:
GaussianInterpolateImageFunction();
~GaussianInterpolateImageFunction() override{};
void PrintSelf( std::ostream& os, Indent indent ) const override;
private:
GaussianInterpolateImageFunction( const Self& ); //purposely not implemented
void operator=( const Self& ); //purposely not implemented
void ComputeBoundingBox();
void ComputeErrorFunctionArray( unsigned int dimension, RealType cindex,
vnl_vector<RealType> &erfArray, vnl_vector<RealType> &gerfArray,
bool evaluateGradient = false ) const;
ArrayType m_Sigma;
RealType m_Alpha;
ArrayType m_BoundingBoxStart;
ArrayType m_BoundingBoxEnd;
ArrayType m_ScalingFactor;
ArrayType m_CutoffDistance;
};
} // end namespace itk
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkGaussianInterpolateImageFunction.txx"
#endif
#endif
diff --git a/Modules/DiffusionCore/Algorithms/itkGaussianInterpolateImageFunction.txx b/Modules/DiffusionCore/Algorithms/itkGaussianInterpolateImageFunction.txx
index a4aaa5a..e5fffea 100644
--- a/Modules/DiffusionCore/Algorithms/itkGaussianInterpolateImageFunction.txx
+++ b/Modules/DiffusionCore/Algorithms/itkGaussianInterpolateImageFunction.txx
@@ -1,230 +1,230 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*===================================================================
This file is based heavily on a corresponding ITK filter.
===================================================================*/
#ifndef __itkGaussianInterpolateImageFunction_txx
#define __itkGaussianInterpolateImageFunction_txx
#include "itkGaussianInterpolateImageFunction.h"
#include "itkImageRegionConstIteratorWithIndex.h"
namespace itk
{
/**
* Constructor
*/
template <class TImageType, class TCoordRep>
GaussianInterpolateImageFunction<TImageType, TCoordRep>
::GaussianInterpolateImageFunction()
{
this->m_Alpha = 1.0;
this->m_Sigma.Fill( 1.0 );
}
/**
* Standard "PrintSelf" method
*/
template <class TImageType, class TCoordRep>
void
GaussianInterpolateImageFunction<TImageType, TCoordRep>
::PrintSelf( std::ostream& os, Indent indent ) const
{
Superclass::PrintSelf( os, indent );
os << indent << "Alpha: " << this->m_Alpha << std::endl;
os << indent << "Sigma: " << this->m_Sigma << std::endl;
}
template <class TImageType, class TCoordRep>
void
GaussianInterpolateImageFunction<TImageType, TCoordRep>
::ComputeBoundingBox()
{
if( !this->GetInputImage() )
{
return;
}
for( unsigned int d = 0; d < ImageDimension; d++ )
{
this->m_BoundingBoxStart[d] = -0.5;
this->m_BoundingBoxEnd[d] = static_cast<RealType>(
this->GetInputImage()->GetBufferedRegion().GetSize()[d] ) - 0.5;
this->m_ScalingFactor[d] = 1.0 / ( vnl_math::sqrt2 * this->m_Sigma[d] /
this->GetInputImage()->GetSpacing()[d] );
this->m_CutoffDistance[d] = this->m_Sigma[d] * this->m_Alpha /
this->GetInputImage()->GetSpacing()[d];
}
}
template <class TImageType, class TCoordRep>
typename GaussianInterpolateImageFunction<TImageType, TCoordRep>
::OutputType
GaussianInterpolateImageFunction<TImageType, TCoordRep>
::EvaluateAtContinuousIndex( const ContinuousIndexType &cindex,
OutputType *grad ) const
{
vnl_vector<RealType> erfArray[ImageDimension];
vnl_vector<RealType> gerfArray[ImageDimension];
// Compute the ERF difference arrays
for( unsigned int d = 0; d < ImageDimension; d++ )
{
bool evaluateGradient = false;
if( grad )
{
evaluateGradient = true;
}
this->ComputeErrorFunctionArray( d, cindex[d], erfArray[d],
gerfArray[d], evaluateGradient );
}
RealType sum_me = 0.0;
RealType sum_m = 0.0;
ArrayType dsum_me;
ArrayType dsum_m;
ArrayType dw;
dsum_m.Fill( 0.0 );
dsum_me.Fill( 0.0 );
// Loop over the voxels in the region identified
ImageRegion<ImageDimension> region;
for( unsigned int d = 0; d < ImageDimension; d++ )
{
int boundingBoxSize = static_cast<int>(
this->m_BoundingBoxEnd[d] - this->m_BoundingBoxStart[d] + 0.5 );
int begin = vnl_math_max( 0, static_cast<int>( vcl_floor( cindex[d] -
this->m_BoundingBoxStart[d] - this->m_CutoffDistance[d] ) ) );
int end = vnl_math_min( boundingBoxSize, static_cast<int>( vcl_ceil(
cindex[d] - this->m_BoundingBoxStart[d] + this->m_CutoffDistance[d] ) ) );
region.SetIndex( d, begin );
region.SetSize( d, end - begin );
}
ImageRegionConstIteratorWithIndex<InputImageType> It(
this->GetInputImage(), region );
for( It.GoToBegin(); !It.IsAtEnd(); ++It )
{
unsigned int j = It.GetIndex()[0];
RealType w = erfArray[0][j];
if( grad )
{
dw[0] = gerfArray[0][j];
for( unsigned int d = 1; d < ImageDimension; d++ )
{
dw[d] = erfArray[0][j];
}
}
for( unsigned int d = 1; d < ImageDimension; d++)
{
j = It.GetIndex()[d];
w *= erfArray[d][j];
if( grad )
{
for( unsigned int q = 0; q < ImageDimension; q++ )
{
if( d == q )
{
dw[q] *= gerfArray[d][j];
}
else
{
dw[q] *= erfArray[d][j];
}
}
}
}
RealType V = It.Get();
sum_me += V * w;
sum_m += w;
if( grad )
{
for( unsigned int q = 0; q < ImageDimension; q++ )
{
dsum_me[q] += V * dw[q];
dsum_m[q] += dw[q];
}
}
}
RealType rc = sum_me / sum_m;
if( grad )
{
for( unsigned int q = 0; q < ImageDimension; q++ )
{
grad[q] = ( dsum_me[q] - rc * dsum_m[q] ) / sum_m;
grad[q] /= -vnl_math::sqrt2 * this->m_Sigma[q];
}
}
return rc;
}
template <class TImageType, class TCoordRep>
void
GaussianInterpolateImageFunction<TImageType, TCoordRep>
::ComputeErrorFunctionArray( unsigned int dimension, RealType cindex,
vnl_vector<RealType> &erfArray, vnl_vector<RealType> &gerfArray,
bool evaluateGradient ) const
{
// Determine the range of voxels along the line where to evaluate erf
int boundingBoxSize = static_cast<int>(
this->m_BoundingBoxEnd[dimension] - this->m_BoundingBoxStart[dimension] +
0.5 );
int begin = vnl_math_max( 0, static_cast<int>( vcl_floor( cindex -
this->m_BoundingBoxStart[dimension] -
this->m_CutoffDistance[dimension] ) ) );
int end = vnl_math_min( boundingBoxSize, static_cast<int>( vcl_ceil( cindex -
this->m_BoundingBoxStart[dimension] +
this->m_CutoffDistance[dimension] ) ) );
erfArray.set_size( boundingBoxSize );
gerfArray.set_size( boundingBoxSize );
// Start at the first voxel
RealType t = ( this->m_BoundingBoxStart[dimension] - cindex +
static_cast<RealType>( begin ) ) * this->m_ScalingFactor[dimension];
RealType e_last = vnl_erf( t );
RealType g_last = 0.0;
if( evaluateGradient )
{
g_last = vnl_math::two_over_sqrtpi * vcl_exp( -vnl_math_sqr( t ) );
}
for( int i = begin; i < end; i++ )
{
t += this->m_ScalingFactor[dimension];
RealType e_now = vnl_erf( t );
erfArray[i] = e_now - e_last;
if( evaluateGradient )
{
RealType g_now = vnl_math::two_over_sqrtpi * vcl_exp( -vnl_math_sqr( t ) );
gerfArray[i] = g_now - g_last;
g_last = g_now;
}
e_last = e_now;
}
}
} // namespace itk
#endif
diff --git a/Modules/DiffusionCore/Algorithms/itkMergeDiffusionImagesFilter.h b/Modules/DiffusionCore/Algorithms/itkMergeDiffusionImagesFilter.h
index 2eb5f03..30e6c48 100644
--- a/Modules/DiffusionCore/Algorithms/itkMergeDiffusionImagesFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkMergeDiffusionImagesFilter.h
@@ -1,108 +1,108 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*=========================================================================
Program: Tensor ToolKit - TTK
Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkMergeDiffusionImagesFilter.h $
Language: C++
Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $
Version: $Revision: 68 $
Copyright (c) INRIA 2010. All rights reserved.
See LICENSE.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef _itk_MergeDiffusionImagesFilter_h_
#define _itk_MergeDiffusionImagesFilter_h_
#include "itkImageToImageFilter.h"
#include <itkDiffusionTensor3D.h>
#include <itkVectorImage.h>
#include <itkVectorContainer.h>
namespace itk
{
/**
* \brief Merges diffusion weighted images, e.g. to generate one multishell volume from several single shell volumes. */
template <class TScalarType>
class MergeDiffusionImagesFilter
: public ImageSource<itk::VectorImage<TScalarType,3> >
{
public:
typedef MergeDiffusionImagesFilter Self;
typedef ImageSource< itk::VectorImage<TScalarType,3> > Superclass;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(MergeDiffusionImagesFilter, ImageSource)
typedef itk::VectorImage<TScalarType,3> DwiImageType;
typedef typename DwiImageType::PixelType DwiPixelType;
typedef typename DwiImageType::RegionType DwiRegionType;
typedef typename std::vector< typename DwiImageType::Pointer > DwiImageContainerType;
typedef vnl_vector_fixed< double, 3 > GradientType;
typedef itk::VectorContainer< unsigned int, GradientType > GradientListType;
typedef typename std::vector< GradientListType::Pointer > GradientListContainerType;
// input
void SetImageVolumes(DwiImageContainerType cont); ///< input DWI image volume container
void SetGradientLists(GradientListContainerType cont); ///< gradients of all input images
void SetBValues(std::vector< double > bvals); ///< b-values of all input images
// output
GradientListType::Pointer GetOutputGradients(); ///< gradient list of the merged output image
double GetB_Value(); ///< main b-value of the merged output image
protected:
MergeDiffusionImagesFilter();
~MergeDiffusionImagesFilter();
void GenerateData() override;
DwiImageContainerType m_ImageVolumes; ///< contains input images
GradientListContainerType m_GradientLists; ///< contains gradients of all input images
std::vector< double > m_BValues; ///< contains b-values of all input images
int m_NumGradients; ///< number of gradients in the output image
GradientListType::Pointer m_OutputGradients; ///< container for output gradients
double m_BValue; ///< main output b-value
};
} // end of namespace
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkMergeDiffusionImagesFilter.txx"
#endif
#endif
diff --git a/Modules/DiffusionCore/Algorithms/itkMergeDiffusionImagesFilter.txx b/Modules/DiffusionCore/Algorithms/itkMergeDiffusionImagesFilter.txx
index 6bfab6b..261f233 100644
--- a/Modules/DiffusionCore/Algorithms/itkMergeDiffusionImagesFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkMergeDiffusionImagesFilter.txx
@@ -1,179 +1,179 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*=========================================================================
2
3 Program: Tensor ToolKit - TTK
4 Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkMergeDiffusionImagesFilter.txx $
5 Language: C++
6 Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $
7 Version: $Revision: 68 $
8
9 Copyright (c) INRIA 2010. All rights reserved.
10 See LICENSE.txt for details.
11
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
15
16 =========================================================================*/
#ifndef _itk_MergeDiffusionImagesFilter_txx_
#define _itk_MergeDiffusionImagesFilter_txx_
#endif
#include "itkMergeDiffusionImagesFilter.h"
#include "itkTensorToL2NormImageFilter.h"
#include "itkRescaleIntensityImageFilter.h"
#include <itkImageRegionIterator.h>
#include <itkImageRegionConstIterator.h>
#include <boost/progress.hpp>
namespace itk
{
template <class TScalarType>
MergeDiffusionImagesFilter<TScalarType>::MergeDiffusionImagesFilter()
{
}
template <class TScalarType>
MergeDiffusionImagesFilter<TScalarType>::~MergeDiffusionImagesFilter()
{
}
template <class TScalarType>
void MergeDiffusionImagesFilter<TScalarType>
::SetImageVolumes(DwiImageContainerType cont)
{
m_ImageVolumes=cont;
}
template <class TScalarType>
void MergeDiffusionImagesFilter<TScalarType>
::SetGradientLists(GradientListContainerType cont)
{
m_GradientLists=cont;
}
template <class TScalarType>
void MergeDiffusionImagesFilter<TScalarType>
::SetBValues(std::vector< double > bvals)
{
m_BValues=bvals;
}
template <class TScalarType>
MergeDiffusionImagesFilter<TScalarType>::GradientListType::Pointer MergeDiffusionImagesFilter<TScalarType>
::GetOutputGradients()
{
return m_OutputGradients;
}
template <class TScalarType>
double MergeDiffusionImagesFilter<TScalarType>
::GetB_Value()
{
return m_BValue;
}
template <class TScalarType>
void
MergeDiffusionImagesFilter<TScalarType>
::GenerateData ()
{
if( m_ImageVolumes.size()<2 )
throw itk::ExceptionObject (__FILE__,__LINE__,"Error: cannot combine less than two DWIs.");
if( m_GradientLists.size()!=m_ImageVolumes.size() || m_ImageVolumes.size()!=m_BValues.size() || m_BValues.size()!=m_GradientLists.size() )
throw itk::ExceptionObject (__FILE__,__LINE__,"Error: need same number of b-values, image volumes and gradient containers.");
typename DwiImageType::Pointer img = m_ImageVolumes.at(0);
m_NumGradients = 0;
for (unsigned int i=0; i<m_GradientLists.size(); i++)
{
m_NumGradients += m_GradientLists.at(i)->Size();
typename DwiImageType::Pointer tmp = m_ImageVolumes.at(i);
if ( img->GetLargestPossibleRegion()!=tmp->GetLargestPossibleRegion() )
throw itk::ExceptionObject (__FILE__,__LINE__,"Error: images are not of same size.");
}
m_BValue = 0;
for (auto bval : m_BValues)
if (bval>m_BValue)
m_BValue = bval;
m_OutputGradients = GradientListType::New();
typename DwiImageType::Pointer outImage = DwiImageType::New();
outImage->SetSpacing( img->GetSpacing() ); // Set the image spacing
outImage->SetOrigin( img->GetOrigin() ); // Set the image origin
outImage->SetDirection( img->GetDirection() ); // Set the image direction
outImage->SetLargestPossibleRegion( img->GetLargestPossibleRegion());
outImage->SetBufferedRegion( img->GetLargestPossibleRegion() );
outImage->SetRequestedRegion( img->GetLargestPossibleRegion() );
outImage->SetVectorLength(m_NumGradients);
outImage->Allocate();
this->SetNumberOfRequiredOutputs(1);
this->SetNthOutput (0, outImage);
typedef ImageRegionIterator<DwiImageType> IteratorOutputType;
IteratorOutputType itOut (this->GetOutput(), this->GetOutput()->GetLargestPossibleRegion());
MITK_INFO << "MergeDiffusionImagesFilter: merging images";
GradientType zeroG; zeroG.fill(0.0);
boost::progress_display disp(this->GetOutput()->GetLargestPossibleRegion().GetNumberOfPixels());
while(!itOut.IsAtEnd())
{
++disp;
DwiPixelType out;
out.SetSize(m_NumGradients);
out.Fill(0);
int c=0;
for (unsigned int i=0; i<m_GradientLists.size(); i++)
{
GradientListType::Pointer gradients = m_GradientLists.at(i);
typename DwiImageType::Pointer img = m_ImageVolumes.at(i);
for (unsigned int j=0; j<gradients->Size(); j++)
{
GradientType g = gradients->GetElement(j);
double mag = g.two_norm();
if (mag>0.0001)
{
double frac = m_BValues.at(i)*mag*mag/m_BValue;
g.normalize();
g *= sqrt(frac);
}
else
g = zeroG;
m_OutputGradients->InsertElement(c, g);
out[c] = static_cast<TScalarType>(img->GetPixel(itOut.GetIndex())[j]);
c++;
}
}
itOut.Set(out);
++itOut;
}
}
} // end of namespace
diff --git a/Modules/DiffusionCore/Algorithms/itkNonLocalMeansDenoisingFilter.h b/Modules/DiffusionCore/Algorithms/itkNonLocalMeansDenoisingFilter.h
index 86bd49d..1fed001 100644
--- a/Modules/DiffusionCore/Algorithms/itkNonLocalMeansDenoisingFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkNonLocalMeansDenoisingFilter.h
@@ -1,145 +1,145 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkNonLocalMeansDenoisingFilter_h_
#define __itkNonLocalMeansDenoisingFilter_h_
#include "itkImageToImageFilter.h"
#include "itkVectorImage.h"
namespace itk{
/** @class NonLocalMeansDenoisingFilter
* @brief This class denoises a vectorimage according to the non-local means procedure.
*
* This Filter needs as an input a diffusion weigthed image, which will be denoised unsing the non-local means principle.
* An input mask is optional to denoise only inside the mask range. All other voxels will be set to 0.
*/
template< class TPixelType >
class NonLocalMeansDenoisingFilter :
public ImageToImageFilter< VectorImage < TPixelType, 3 >, VectorImage < TPixelType, 3 > >
{
public:
/** Typedefs */
typedef NonLocalMeansDenoisingFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< VectorImage < TPixelType, 3 >, VectorImage < TPixelType, 3 > > Superclass;
typedef typename Superclass::InputImageType InputImageType;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename Superclass::OutputImageRegionType OutputImageRegionType;
typedef Image <TPixelType, 3> MaskImageType;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(NonLocalMeansDenoisingFilter, ImageToImageFilter)
/**
* @brief Set flag to use joint information
*/
itkSetMacro(UseJointInformation, bool)
/**
* @brief Set the searchradius
*
* The searchradius generates a neighborhood of size (2 * searchradius + 1)³.
* Default is 4.
*/
itkSetMacro(SearchRadius, int)
/**
* @brief Set the comparisonradius
*
* The comparisonradius generates neighborhoods of size (2 * comparisonradius +1)³.
* Default is 1.
*/
itkSetMacro(ComparisonRadius, int)
/**
* @brief Set the variance of the noise
*
* The variance of the noise needs to be estimated to use this filter properly.
* Default is 1.
*/
itkSetMacro(Variance, double)
/**
* @brief Set flag to use a rician adaption
*
* If this flag is true the filter uses a method which is optimized for Rician distributed noise.
*/
itkSetMacro(UseRicianAdaption, bool)
/**
* @brief Get the amount of calculated Voxels
*
* @return the number of calculated Voxels until yet, useful for the use of a progressbars.
*/
itkGetMacro(CurrentVoxelCount, unsigned int)
/** @brief Set the input image. **/
void SetInputImage(const InputImageType* image);
/**
* @brief Set a denoising mask
*
* optional
*
* Set a mask to denoise only the masked area, all voxel outside this area will be set to 0.
*/
void SetInputMask(MaskImageType* mask);
protected:
NonLocalMeansDenoisingFilter();
~NonLocalMeansDenoisingFilter() override {}
/**
* @brief Calculations which need to be done before the denoising starts
*
* This method is called before the denoising starts. It calculates the ROI if a mask is used
* and sets the number of processed voxels to zero.
*/
void BeforeThreadedGenerateData() override;
/**
* @brief Denoising procedure
*
* This method calculates the denoised voxelvalue for each voxel in the image in multiple threads.
* If a mask is used, voxels outside the masked area will be set to 0.
*
* @param outputRegionForThread Region to denoise for each thread.
*/
void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType) override;
private:
int m_SearchRadius; ///< Radius of the searchblock.
int m_ComparisonRadius; ///< Radius of the comparisonblock.
bool m_UseJointInformation; ///< Flag to use joint information.
bool m_UseRicianAdaption; ///< Flag to use rician adaption.
unsigned int m_CurrentVoxelCount; ///< Amount of processed voxels.
double m_Variance; ///< Estimated noise variance.
typename MaskImageType::Pointer m_Mask; ///< Pointer to the mask image.
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkNonLocalMeansDenoisingFilter.txx"
#endif
#endif //__itkNonLocalMeansDenoisingFilter_h_
diff --git a/Modules/DiffusionCore/Algorithms/itkNonLocalMeansDenoisingFilter.txx b/Modules/DiffusionCore/Algorithms/itkNonLocalMeansDenoisingFilter.txx
index 8a29a5a..63e9637 100644
--- a/Modules/DiffusionCore/Algorithms/itkNonLocalMeansDenoisingFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkNonLocalMeansDenoisingFilter.txx
@@ -1,388 +1,388 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkNonLocalMeansDenoisingFilter_txx
#define __itkNonLocalMeansDenoisingFilter_txx
#include <ctime>
#include <cstdio>
#include <cstdlib>
#define _USE_MATH_DEFINES
#include <cmath>
#include "itkImageRegionIterator.h"
#include "itkNeighborhoodIterator.h"
#include <itkImageRegionIteratorWithIndex.h>
#include <vector>
namespace itk {
template< class TPixelType >
NonLocalMeansDenoisingFilter< TPixelType >
::NonLocalMeansDenoisingFilter()
: m_SearchRadius(4),
m_ComparisonRadius(1),
m_UseJointInformation(false),
m_UseRicianAdaption(false),
m_Variance(1),
m_Mask(nullptr)
{
this->SetNumberOfRequiredInputs( 1 );
}
template< class TPixelType >
void
NonLocalMeansDenoisingFilter< TPixelType >
::BeforeThreadedGenerateData()
{
MITK_INFO << "SearchRadius: " << m_SearchRadius;
MITK_INFO << "ComparisonRadius: " << m_ComparisonRadius;
MITK_INFO << "Noisevariance: " << m_Variance;
MITK_INFO << "Use Rician Adaption: " << std::boolalpha << m_UseRicianAdaption;
MITK_INFO << "Use Joint Information: " << std::boolalpha << m_UseJointInformation;
typename InputImageType::Pointer inputImagePointer = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
if (m_Mask.IsNull())
{
// If no mask is used generate a mask of the complete image
m_Mask = MaskImageType::New();
m_Mask->SetRegions(inputImagePointer->GetLargestPossibleRegion());
m_Mask->Allocate();
m_Mask->FillBuffer(1);
}
else
{
// Calculation of the smallest masked region
typename OutputImageType::Pointer outputImage =
static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0));
ImageRegionIterator< OutputImageType > oit(outputImage, inputImagePointer->GetLargestPossibleRegion());
oit.GoToBegin();
ImageRegionIterator< MaskImageType > mit(m_Mask, m_Mask->GetLargestPossibleRegion());
mit.GoToBegin();
typename MaskImageType::IndexType minIndex;
typename MaskImageType::IndexType maxIndex;
minIndex.Fill(10000);
maxIndex.Fill(0);
typename OutputImageType::PixelType outpix;
outpix.SetSize(inputImagePointer->GetVectorLength());
outpix.Fill(0);
while (!mit.IsAtEnd())
{
if (mit.Get())
{
// calculation of the start & end index of the smallest masked region
minIndex[0] = minIndex[0] < mit.GetIndex()[0] ? minIndex[0] : mit.GetIndex()[0];
minIndex[1] = minIndex[1] < mit.GetIndex()[1] ? minIndex[1] : mit.GetIndex()[1];
minIndex[2] = minIndex[2] < mit.GetIndex()[2] ? minIndex[2] : mit.GetIndex()[2];
maxIndex[0] = maxIndex[0] > mit.GetIndex()[0] ? maxIndex[0] : mit.GetIndex()[0];
maxIndex[1] = maxIndex[1] > mit.GetIndex()[1] ? maxIndex[1] : mit.GetIndex()[1];
maxIndex[2] = maxIndex[2] > mit.GetIndex()[2] ? maxIndex[2] : mit.GetIndex()[2];
}
else
{
oit.Set(outpix);
}
++mit;
++oit;
}
// calculation of the masked region
typename OutputImageType::SizeType size;
size[0] = maxIndex[0] - minIndex[0] + 1;
size[1] = maxIndex[1] - minIndex[1] + 1;
size[2] = maxIndex[2] - minIndex[2] + 1;
typename OutputImageType::RegionType region (minIndex, size);
outputImage->SetRequestedRegion(region);
}
m_CurrentVoxelCount = 0;
}
template< class TPixelType >
void
NonLocalMeansDenoisingFilter< TPixelType >
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, ThreadIdType )
{
// initialize iterators
typename OutputImageType::Pointer outputImage =
static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0));
ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread);
oit.GoToBegin();
ImageRegionIterator< MaskImageType > mit(m_Mask, outputRegionForThread);
mit.GoToBegin();
typedef ImageRegionIteratorWithIndex <InputImageType> InputIteratorType;
typename InputImageType::Pointer inputImagePointer = nullptr;
inputImagePointer = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
InputIteratorType git(inputImagePointer, outputRegionForThread );
git.GoToBegin();
// iterate over complete image region
while( !git.IsAtEnd() )
{
typename OutputImageType::PixelType outpix;
outpix.SetSize (inputImagePointer->GetVectorLength());
if (mit.Get() != 0 && !this->GetAbortGenerateData())
{
if(!m_UseJointInformation)
{
for (int i = 0; i < (int)inputImagePointer->GetVectorLength(); ++i)
{
double summw = 0;
double sumj = 0;
double w = 0;
std::vector<double> wj;
std::vector<double> p;
typename InputIteratorType::IndexType index;
index = git.GetIndex();
for (int x = index.GetElement(0) - m_SearchRadius; x <= index.GetElement(0) + m_SearchRadius; ++x)
{
for (int y = index.GetElement(1) - m_SearchRadius; y <= index.GetElement(1) + m_SearchRadius; ++y)
{
for (int z = index.GetElement(2) - m_SearchRadius; z <= index.GetElement(2) + m_SearchRadius; ++z)
{
typename InputIteratorType::IndexType indexV;
indexV.SetElement(0, x);
indexV.SetElement(1, y);
indexV.SetElement(2, z);
if (inputImagePointer->GetLargestPossibleRegion().IsInside(indexV))
{
TPixelType pixelJ = inputImagePointer->GetPixel(indexV)[i];
double sumk = 0;
double size = 0;
for (int xi = index.GetElement(0) - m_ComparisonRadius, xj = x - m_ComparisonRadius; xi <= index.GetElement(0) + m_ComparisonRadius; ++xi, ++xj)
{
for (int yi = index.GetElement(1) - m_ComparisonRadius, yj = y - m_ComparisonRadius; yi <= index.GetElement(1) + m_ComparisonRadius; ++yi, ++yj)
{
for (int zi = index.GetElement(2) - m_ComparisonRadius, zj = z - m_ComparisonRadius; zi <= index.GetElement(2) + m_ComparisonRadius; ++zi, ++zj)
{
typename InputIteratorType::IndexType indexI, indexJ;
indexI.SetElement(0, xi);
indexI.SetElement(1, yi);
indexI.SetElement(2, zi);
indexJ.SetElement(0, xj);
indexJ.SetElement(1, yj);
indexJ.SetElement(2, zj);
// Compare neighborhoods ni & nj
if (inputImagePointer->GetLargestPossibleRegion().IsInside(indexI) && inputImagePointer->GetLargestPossibleRegion().IsInside(indexJ))
{
int diff = inputImagePointer->GetPixel(indexI)[i] - inputImagePointer->GetPixel(indexJ)[i];
sumk += (double)(diff*diff);
++size;
}
}
}
}
// weight all neighborhoods
w = std::exp( - sumk / size / m_Variance);
wj.push_back(w);
if (m_UseRicianAdaption)
{
p.push_back((double)(pixelJ*pixelJ));
}
else
{
p.push_back((double)(pixelJ));
}
summw += w;
}
}
}
}
for (unsigned int n = 0; n < wj.size(); ++n)
{
sumj += (wj[n]/summw) * p[n];
}
if (m_UseRicianAdaption)
{
sumj -=2 * m_Variance;
}
if (sumj < 0)
{
sumj = 0;
}
TPixelType outval;
if (m_UseRicianAdaption)
{
outval = std::floor(std::sqrt(sumj) + 0.5);
}
else
{
outval = std::floor(sumj + 0.5);
}
outpix.SetElement(i, outval);
}
}
else
{
// same procedure for vektoranalysis
double Z = 0;
itk::VariableLengthVector<double> sumj;
sumj.SetSize(inputImagePointer->GetVectorLength());
sumj.Fill(0.0);
double w = 0;
std::vector<double> wj;
std::vector<itk::VariableLengthVector <double> > p;
typename InputIteratorType::IndexType index;
index = git.GetIndex();
for (int x = index.GetElement(0) - m_SearchRadius; x <= index.GetElement(0) + m_SearchRadius; ++x)
{
for (int y = index.GetElement(1) - m_SearchRadius; y <= index.GetElement(1) + m_SearchRadius; ++y)
{
for (int z = index.GetElement(2) - m_SearchRadius; z <= index.GetElement(2) + m_SearchRadius; ++z)
{
typename InputIteratorType::IndexType indexV;
indexV.SetElement(0, x);
indexV.SetElement(1, y);
indexV.SetElement(2, z);
if (inputImagePointer->GetLargestPossibleRegion().IsInside(indexV))
{
typename InputImageType::PixelType pixelJ = inputImagePointer->GetPixel(indexV);
double sumk = 0;
double size = 0;
for (int xi = index.GetElement(0) - m_ComparisonRadius, xj = x - m_ComparisonRadius; xi <= index.GetElement(0) + m_ComparisonRadius; ++xi, ++xj)
{
for (int yi = index.GetElement(1) - m_ComparisonRadius, yj = y - m_ComparisonRadius; yi <= index.GetElement(1) + m_ComparisonRadius; ++yi, ++yj)
{
for (int zi = index.GetElement(2) - m_ComparisonRadius, zj = z - m_ComparisonRadius; zi <= index.GetElement(2) + m_ComparisonRadius; ++zi, ++zj)
{
typename InputIteratorType::IndexType indexI, indexJ;
indexI.SetElement(0, xi);
indexI.SetElement(1, yi);
indexI.SetElement(2, zi);
indexJ.SetElement(0, xj);
indexJ.SetElement(1, yj);
indexJ.SetElement(2, zj);
// Compare neighborhoods ni & nj
if (inputImagePointer->GetLargestPossibleRegion().IsInside(indexI) && inputImagePointer->GetLargestPossibleRegion().IsInside(indexJ))
{
typename InputImageType::PixelType diff = inputImagePointer->GetPixel(indexI) - inputImagePointer->GetPixel(indexJ);
sumk += (double)(diff.GetSquaredNorm());
++size;
}
}
}
}
// weight all neighborhoods
size *= inputImagePointer->GetVectorLength() + 1;
w = std::exp( - (sumk / size) / m_Variance);
wj.push_back(w);
if (m_UseRicianAdaption)
{
itk::VariableLengthVector <double> m;
m.SetSize(inputImagePointer->GetVectorLength());
for (unsigned int i = 0; i < inputImagePointer->GetVectorLength(); ++i)
{
double sp = (double)(pixelJ.GetElement(i) * pixelJ.GetElement(i));
m.SetElement(i,sp);
}
p.push_back(m);
}
else
++size;
{
p.push_back(pixelJ);
}
Z += w;
}
}
}
}
for (unsigned int n = 0; n < wj.size(); ++n)
{
sumj = sumj + ((wj[n]/Z) * p[n]);
}
if (m_UseRicianAdaption)
{
sumj = sumj - (2 * m_Variance);
}
for (unsigned int i = 0; i < inputImagePointer->GetVectorLength(); ++i)
{
double a = sumj.GetElement(i);
if (a < 0)
{
a = 0;
}
TPixelType outval;
if (m_UseRicianAdaption)
{
outval = std::floor(std::sqrt(a) + 0.5);
}
else
{
outval = std::floor(a + 0.5);
}
outpix.SetElement(i, outval);
}
}
}
else
{
outpix.Fill(0);
}
oit.Set(outpix);
++oit;
++m_CurrentVoxelCount;
++git;
++mit;
}
MITK_INFO << "One Thread finished calculation";
}
template< class TPixelType >
void NonLocalMeansDenoisingFilter< TPixelType >::SetInputImage(const InputImageType* image)
{
this->SetNthInput(0, const_cast< InputImageType* >(image));
}
template< class TPixelType >
void NonLocalMeansDenoisingFilter< TPixelType >::SetInputMask(MaskImageType* mask)
{
m_Mask = mask;
}
}
#endif // __itkNonLocalMeansDenoisingFilter_txx
diff --git a/Modules/DiffusionCore/Algorithms/itkOdfMaximaExtractionFilter.cpp b/Modules/DiffusionCore/Algorithms/itkOdfMaximaExtractionFilter.cpp
index 4769e66..6e31ebf 100644
--- a/Modules/DiffusionCore/Algorithms/itkOdfMaximaExtractionFilter.cpp
+++ b/Modules/DiffusionCore/Algorithms/itkOdfMaximaExtractionFilter.cpp
@@ -1,362 +1,362 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkOdfMaximaExtractionFilter_cpp
#define __itkOdfMaximaExtractionFilter_cpp
#include "itkOdfMaximaExtractionFilter.h"
#include <itkImageRegionConstIterator.h>
#include <itkImageRegionConstIteratorWithIndex.h>
#include <itkImageRegionIterator.h>
#include <vnl/vnl_vector.h>
#include <itkOrientationDistributionFunction.h>
#include <itkContinuousIndex.h>
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkCellArray.h>
#include <vtkPoints.h>
#include <vtkPolyLine.h>
#include <boost/math/special_functions.hpp>
#include <boost/progress.hpp>
using namespace boost::math;
namespace itk {
static bool CompareVectors(const vnl_vector_fixed< double, 3 >& v1, const vnl_vector_fixed< double, 3 >& v2)
{
return (v1.magnitude()>v2.magnitude());
}
template< class PixelType, int ShOrder, int NrOdfDirections >
OdfMaximaExtractionFilter< PixelType, ShOrder, NrOdfDirections>
::OdfMaximaExtractionFilter()
: m_NormalizationMethod(MAX_VEC_NORM)
, m_MaxNumPeaks(2)
, m_RelativePeakThreshold(0.4)
, m_AbsolutePeakThreshold(0)
, m_AngularThreshold(0.9)
, m_NumCoeffs((ShOrder*ShOrder + ShOrder + 2)/2 + ShOrder)
, m_Toolkit(MRTRIX)
, m_FlipX(false)
, m_FlipY(false)
, m_FlipZ(false)
, m_ApplyDirectionMatrix(false)
, m_ScaleByGfa(false)
, m_Iterations(10)
{
this->SetNumberOfRequiredInputs(1);
}
template< class PixelType, int ShOrder, int NrOdfDirections >
double OdfMaximaExtractionFilter< PixelType, ShOrder, NrOdfDirections>
::FindCandidatePeaks(OdfType& odf, double thr, std::vector< DirectionType >& container)
{
double gfa = 1.0;
if (m_ScaleByGfa)
gfa = odf.GetGeneralizedFractionalAnisotropy();
//Find the peaks using a finite difference method
bool flag = true;
vnl_vector_fixed< bool, NrOdfDirections > used; used.fill(false);
//Find the peaks
for (int i=0; i<NrOdfDirections; i++)
{
if (used[i])
continue;
double val = odf.GetElement(i);
if (val>thr*0.9 && gfa*val>m_AbsolutePeakThreshold*0.9)
{
flag = true;
std::vector< int > neighbours = odf.GetNeighbors(i);
for (unsigned int j=0; j<neighbours.size(); j++)
if (val<odf.GetElement(neighbours.at(j)))
{
flag = false;
break;
}
if (flag) // point is a peak
{
container.push_back(odf.GetDirection(i).normalize());
used[i] = true;
for (unsigned int j=0; j<neighbours.size(); j++)
used[neighbours.at(j)] = true;
}
}
}
return gfa;
}
template< class PixelType, int ShOrder, int NrOdfDirections >
void OdfMaximaExtractionFilter< PixelType, ShOrder, NrOdfDirections>
::BeforeThreadedGenerateData()
{
typename CoefficientImageType::Pointer ShCoeffImage = static_cast< CoefficientImageType* >( this->ProcessObject::GetInput(0) );
itk::Vector<double,3> spacing = ShCoeffImage->GetSpacing();
double minSpacing = spacing[0];
if (spacing[1]<minSpacing)
minSpacing = spacing[1];
if (spacing[2]<minSpacing)
minSpacing = spacing[2];
mitk::Point3D origin = ShCoeffImage->GetOrigin();
itk::Matrix<double, 3, 3> direction = ShCoeffImage->GetDirection();
ImageRegion<3> imageRegion = ShCoeffImage->GetLargestPossibleRegion();
if (m_MaskImage.IsNotNull())
{
origin = m_MaskImage->GetOrigin();
direction = m_MaskImage->GetDirection();
imageRegion = m_MaskImage->GetLargestPossibleRegion();
}
itk::Vector<double, 3> spacing3 = ShCoeffImage->GetSpacing();
itk::Point<float, 3> origin3 = ShCoeffImage->GetOrigin();
itk::Matrix<double, 3, 3> direction3 = ShCoeffImage->GetDirection();
itk::ImageRegion<3> imageRegion3 = ShCoeffImage->GetLargestPossibleRegion();
itk::Vector<double, 4> spacing4;
itk::Point<float, 4> origin4;
itk::Matrix<double, 4, 4> direction4;
itk::ImageRegion<4> imageRegion4;
spacing4[0] = spacing3[0]; spacing4[1] = spacing3[1]; spacing4[2] = spacing3[2]; spacing4[3] = 1;
origin4[0] = origin3[0]; origin4[1] = origin3[1]; origin4[2] = origin3[2]; origin4[3] = 0;
for (int r=0; r<3; r++)
for (int c=0; c<3; c++)
direction4[r][c] = direction3[r][c];
direction4[3][3] = 1;
imageRegion4.SetSize(0, imageRegion3.GetSize()[0]);
imageRegion4.SetSize(1, imageRegion3.GetSize()[1]);
imageRegion4.SetSize(2, imageRegion3.GetSize()[2]);
imageRegion4.SetSize(3, m_MaxNumPeaks*3);
m_PeakImage = PeakImageType::New();
m_PeakImage->SetSpacing( spacing4 );
m_PeakImage->SetOrigin( origin4 );
m_PeakImage->SetDirection( direction4 );
m_PeakImage->SetRegions( imageRegion4 );
m_PeakImage->Allocate();
m_PeakImage->FillBuffer(0.0);
if (m_MaskImage.IsNull())
{
m_MaskImage = ItkUcharImgType::New();
m_MaskImage->SetSpacing( spacing );
m_MaskImage->SetOrigin( origin );
m_MaskImage->SetDirection( direction );
m_MaskImage->SetRegions( imageRegion );
m_MaskImage->Allocate();
m_MaskImage->FillBuffer(1);
}
m_NumDirectionsImage = ItkUcharImgType::New();
m_NumDirectionsImage->SetSpacing( spacing );
m_NumDirectionsImage->SetOrigin( origin );
m_NumDirectionsImage->SetDirection( direction );
m_NumDirectionsImage->SetRegions( imageRegion );
m_NumDirectionsImage->Allocate();
m_NumDirectionsImage->FillBuffer(0);
// calculate SH basis
OdfType odf;
vnl_matrix< double > dir_matrix;
dir_matrix.set_size(3, NrOdfDirections);
for (int i=0; i<NrOdfDirections; i++)
{
dir_matrix(0, i) = odf.GetDirection(i)[0];
dir_matrix(1, i) = odf.GetDirection(i)[1];
dir_matrix(2, i) = odf.GetDirection(i)[2];
}
if (m_Toolkit==Toolkit::MRTRIX)
m_ShBasis = mitk::sh::CalcShBasisForDirections(ShOrder, dir_matrix);
else
m_ShBasis = mitk::sh::CalcShBasisForDirections(ShOrder, dir_matrix, false);
MITK_INFO << "Starting peak extraction";
MITK_INFO << "SH order: " << ShOrder;
MITK_INFO << "Maximum peaks: " << m_MaxNumPeaks;
MITK_INFO << "Relative threshold: " << m_RelativePeakThreshold;
MITK_INFO << "Absolute threshold: " << m_AbsolutePeakThreshold;
MITK_INFO << "Angular threshold: " << m_AngularThreshold;
this->SetNumberOfThreads(1);
}
template< class PixelType, int ShOrder, int NrOdfDirections >
void OdfMaximaExtractionFilter< PixelType, ShOrder, NrOdfDirections>
::AfterThreadedGenerateData()
{
}
template< class PixelType, int ShOrder, int NrOdfDirections >
void OdfMaximaExtractionFilter< PixelType, ShOrder, NrOdfDirections>
::ThreadedGenerateData( const OutputImageRegionType& outputRegionForThread, ThreadIdType threadID )
{
typename CoefficientImageType::Pointer ShCoeffImage = static_cast< CoefficientImageType* >( this->ProcessObject::GetInput(0) );
ImageRegionConstIterator< CoefficientImageType > cit(ShCoeffImage, outputRegionForThread );
boost::progress_display disp(outputRegionForThread.GetSize()[0]*outputRegionForThread.GetSize()[1]*outputRegionForThread.GetSize()[2]);
OdfType odf;
while( !cit.IsAtEnd() )
{
typename CoefficientImageType::IndexType idx3 = cit.GetIndex();
if (m_MaskImage->GetPixel(idx3)==0)
{
++disp;
++cit;
continue;
}
CoefficientPixelType c = cit.Get();
vnl_vector<float> coeffs; coeffs.set_size((ShOrder*ShOrder + ShOrder + 2)/2 + ShOrder);
for (int j=0; j<m_NumCoeffs; j++)
coeffs[j] = c[j];
double max = 0;
for (int i=0; i<NrOdfDirections; i++)
{
odf[i] = 0;
for (int j=0; j<m_NumCoeffs; j++)
odf[i] += c[j]*m_ShBasis(i,j);
if (odf[i]>max)
max = odf[i];
}
if (max<0.0001)
{
++disp;
++cit;
continue;
}
std::vector< DirectionType > candidates, final_peaks;
double scale = FindCandidatePeaks(odf, max*m_RelativePeakThreshold, candidates); // find all local maxima
max = 0;
for (unsigned int i=0; i<candidates.size(); ++i)
{
double spherical[3];
mitk::sh::Cart2Sph(candidates[i][0], candidates[i][1], candidates[i][2], spherical);
vnl_vector<double> x;
x.set_size(2);
x[0] = spherical[1]; // theta
x[1] = spherical[0]; // phi
VnlCostFunction cost;
if (m_Toolkit==Toolkit::MRTRIX)
cost.SetProblem(coeffs, ShOrder, true, max);
else
cost.SetProblem(coeffs, ShOrder, false, max);
vnl_lbfgsb minimizer(cost);
minimizer.set_f_tolerance(1e-6);
// minimizer.set_trace(true);
vnl_vector<double> l; l.set_size(2); l[0] = 0; l[1] = -itk::Math::pi;
vnl_vector<double> u; u.set_size(2); u[0] = itk::Math::pi; u[1] = itk::Math::pi;
vnl_vector<long> bound_selection; bound_selection.set_size(2); bound_selection.fill(2);
minimizer.set_bound_selection(bound_selection);
minimizer.set_lower_bound(l);
minimizer.set_upper_bound(u);
if (m_Iterations>0)
minimizer.set_max_function_evals(m_Iterations);
minimizer.minimize(x);
float v = -minimizer.get_end_error()*scale;
candidates[i] = mitk::sh::Sph2Cart(x[0], x[1], v);
if (v>max)
max = v;
}
std::sort( candidates.begin(), candidates.end(), CompareVectors ); // sort peaks
// kick out directions to close to a larger direction
for (unsigned int i=0; i<candidates.size(); i++)
{
DirectionType v1 = candidates.at(i);
double val = v1.magnitude();
if (val<max*m_RelativePeakThreshold || val<m_AbsolutePeakThreshold)
break;
bool flag = true;
for (unsigned int j=0; j<candidates.size(); j++)
if (i!=j)
{
DirectionType v2 = candidates.at(j);
double val2 = v2.magnitude();
double angle = fabs(dot_product(v1,v2)/(val*val2));
if (angle>m_AngularThreshold && val<val2)
{
flag = false;
break;
}
}
if (flag)
final_peaks.push_back(v1);
}
itk::Index<4> idx4; idx4[0] = idx3[0]; idx4[1] = idx3[1]; idx4[2] = idx3[2];
// fill output image
unsigned int num = final_peaks.size();
if ( num>m_MaxNumPeaks )
num = m_MaxNumPeaks;
for (unsigned int i=0; i<num; i++)
{
DirectionType dir = final_peaks.at(i);
switch (m_NormalizationMethod)
{
case NO_NORM:
break;
case SINGLE_VEC_NORM:
dir.normalize();
break;
case MAX_VEC_NORM:
dir /= max;
break;
}
if (m_ApplyDirectionMatrix)
dir = m_MaskImage->GetDirection()*dir;
if (m_FlipX)
dir[0] = -dir[0];
if (m_FlipY)
dir[1] = -dir[1];
if (m_FlipZ)
dir[2] = -dir[2];
for (unsigned int j = 0; j<3; j++)
{
idx4[3] = i*3 + j;
m_PeakImage->SetPixel(idx4, dir[j]);
}
}
m_NumDirectionsImage->SetPixel(idx3, num);
++disp;
++cit;
}
MITK_INFO << "Thread " << threadID << " finished extraction";
}
}
#endif // __itkOdfMaximaExtractionFilter_cpp
diff --git a/Modules/DiffusionCore/Algorithms/itkOdfMaximaExtractionFilter.h b/Modules/DiffusionCore/Algorithms/itkOdfMaximaExtractionFilter.h
index e82badc..f806907 100644
--- a/Modules/DiffusionCore/Algorithms/itkOdfMaximaExtractionFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkOdfMaximaExtractionFilter.h
@@ -1,182 +1,181 @@
-/*=========================================================================
+/*===================================================================
- Program: Insight Segmentation & Registration Toolkit
- Module: $RCSfile: itkDiffusionTensor3DReconstructionImageFilter.h,v $
- Language: C++
- Date: $Date: 2006-03-27 17:01:06 $
- Version: $Revision: 1.12 $
+The Medical Imaging Interaction Toolkit (MITK)
- Copyright (c) Insight Software Consortium. All rights reserved.
- See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
+Copyright (c) German Cancer Research Center.
- This software is distributed WITHOUT ANY WARRANTY; without even
- the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- PURPOSE. See the above copyright notices for more information.
+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 __itkOdfMaximaExtractionFilter_h_
#define __itkOdfMaximaExtractionFilter_h_
#include "itkImageToImageFilter.h"
#include "vnl/vnl_vector_fixed.h"
#include "vnl/vnl_matrix.h"
#include "vnl/algo/vnl_svd.h"
#include "itkVectorContainer.h"
#include "itkVectorImage.h"
#include <mitkFiberBundle.h>
#include <mitkPeakImage.h>
#include <mitkShImage.h>
#include <itkOrientationDistributionFunction.h>
#include <vnl/algo/vnl_lbfgsb.h>
#include <mitkDiffusionFunctionCollection.h>
class VnlCostFunction : public vnl_cost_function
{
public:
bool mrtrix;
int ShOrder;
vnl_vector<float> coeffs;
double max;
void SetProblem(vnl_vector<float>& coeffs, int ShOrder, bool mrtrix, double max)
{
this->coeffs = coeffs;
this->ShOrder = ShOrder;
this->mrtrix = mrtrix;
this->max = max;
}
VnlCostFunction(const int NumVars=2) : vnl_cost_function(NumVars)
{
}
// cost function
double f(vnl_vector<double> const &x)
{
return -mitk::sh::GetValue(coeffs, ShOrder, x[0], x[1], mrtrix);
}
// gradient of cost function
void gradf(vnl_vector<double> const &x, vnl_vector<double> &dx)
{
fdgradf(x, dx);
}
};
namespace itk{
/**
* \brief Extract ODF peaks by searching all local maxima on a roughly sampled sphere and a successive gradient descent optimization
*/
template< class PixelType, int ShOrder, int NrOdfDirections >
class OdfMaximaExtractionFilter : public ImageToImageFilter< Image< Vector< PixelType, (ShOrder*ShOrder + ShOrder + 2)/2 + ShOrder >, 3 >,
Image< unsigned char, 3 > >
{
public:
enum Toolkit { ///< SH coefficient convention (depends on toolkit)
FSL,
MRTRIX
};
enum NormalizationMethods {
NO_NORM, ///< no length normalization of the output peaks
SINGLE_VEC_NORM, ///< normalize the single peaks to length 1
MAX_VEC_NORM ///< normalize all peaks according to their length in comparison to the largest peak in the respective voxel (0-1)
};
typedef OdfMaximaExtractionFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< Image< Vector< PixelType, (ShOrder*ShOrder + ShOrder + 2)/2 + ShOrder >, 3 >,
Image< unsigned char, 3 > > Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(OdfMaximaExtractionFilter, ImageToImageFilter)
typedef typename Superclass::InputImageType CoefficientImageType;
typedef typename CoefficientImageType::RegionType CoefficientImageRegionType;
typedef typename CoefficientImageType::PixelType CoefficientPixelType;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename Superclass::OutputImageRegionType OutputImageRegionType;
typedef typename Superclass::InputImageRegionType InputImageRegionType;
typedef mitk::PeakImage::ItkPeakImageType PeakImageType;
typedef OrientationDistributionFunction<PixelType, NrOdfDirections> OdfType;
typedef itk::Image<unsigned char, 3> ItkUcharImgType;
typedef vnl_vector_fixed< double, 3 > DirectionType;
// input
itkSetMacro( MaxNumPeaks, unsigned int) ///< maximum number of peaks per voxel. if more peaks are detected, only the largest are kept.
itkSetMacro( RelativePeakThreshold, double) ///< threshold on the peak length relative to the largest peak inside the current voxel
itkSetMacro( AbsolutePeakThreshold, double) ///< hard threshold on the peak length of all local maxima
itkSetMacro( AngularThreshold, double) ///< directions closer together than the specified threshold are discarded
itkSetMacro( MaskImage, ItkUcharImgType::Pointer) ///< only voxels inside the binary mask are processed
itkSetMacro( NormalizationMethod, NormalizationMethods) ///< normalization method of ODF peaks
itkSetMacro( FlipX, bool) ///< flip peaks in x direction
itkSetMacro( FlipY, bool) ///< flip peaks in y direction
itkSetMacro( FlipZ, bool) ///< flip peaks in z direction
itkSetMacro( ApplyDirectionMatrix, bool)
itkSetMacro( ScaleByGfa, bool)
itkSetMacro( Iterations, int)
// output
itkGetMacro( NumDirectionsImage, ItkUcharImgType::Pointer )
itkGetMacro( PeakImage, PeakImageType::Pointer )
itkSetMacro( Toolkit, Toolkit) ///< define SH coefficient convention (depends on toolkit)
itkGetMacro( Toolkit, Toolkit) ///< SH coefficient convention (depends on toolkit)
protected:
OdfMaximaExtractionFilter();
~OdfMaximaExtractionFilter(){}
void BeforeThreadedGenerateData();
void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType threadID );
void AfterThreadedGenerateData();
/** Extract all local maxima from the densely sampled ODF surface. Thresholding possible. **/
double FindCandidatePeaks(OdfType& odf, double odfMax, std::vector< DirectionType >& inDirs);
/** Cluster input directions within a certain angular threshold **/
std::vector< DirectionType > MeanShiftClustering(std::vector< DirectionType >& inDirs);
private:
NormalizationMethods m_NormalizationMethod; ///< normalization method of ODF peaks
unsigned int m_MaxNumPeaks; ///< maximum number of peaks per voxel. if more peaks are detected, only the largest are kept.
double m_RelativePeakThreshold; ///< threshold on the peak length relative to the largest peak inside the current voxel
double m_AbsolutePeakThreshold;///< hard threshold on the peak length of all local maxima
vnl_matrix< float > m_ShBasis; ///< container for evaluated SH base functions
double m_AngularThreshold;
const int m_NumCoeffs; ///< number of spherical harmonics coefficients
PeakImageType::Pointer m_PeakImage;
ItkUcharImgType::Pointer m_NumDirectionsImage; ///< number of peaks per voxel
ItkUcharImgType::Pointer m_MaskImage; ///< only voxels inside the binary mask are processed
Toolkit m_Toolkit;
bool m_FlipX;
bool m_FlipY;
bool m_FlipZ;
bool m_ApplyDirectionMatrix;
bool m_ScaleByGfa;
int m_Iterations;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkOdfMaximaExtractionFilter.cpp"
#endif
#endif //__itkOdfMaximaExtractionFilter_h_
diff --git a/Modules/DiffusionCore/Algorithms/itkOdfToRgbImageFilter.h b/Modules/DiffusionCore/Algorithms/itkOdfToRgbImageFilter.h
index 76dd5fd..4d3eab8 100644
--- a/Modules/DiffusionCore/Algorithms/itkOdfToRgbImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkOdfToRgbImageFilter.h
@@ -1,148 +1,148 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkOdfToRgbImageFilter_h
#define __itkOdfToRgbImageFilter_h
#include "itkUnaryFunctorImageFilter.h"
#include "itkOrientationDistributionFunction.h"
#include "itkRGBAPixel.h"
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionIterator.h"
namespace itk
{
#define __IMG_DAT_ITEM__CEIL_ZERO_ONE__(val) (val) = \
( (val) < 0 ) ? ( 0 ) : ( ( (val)>1 ) ? ( 1 ) : ( (val) ) );
/** \class OdfToRgbImageFilter
*
*/
template <typename TInputImage,
typename TOutputImage=itk::Image<itk::RGBAPixel<unsigned char>,3> >
class OdfToRgbImageFilter :
public ImageToImageFilter<TInputImage,TOutputImage>
{
public:
/** Standard class typedefs. */
typedef OdfToRgbImageFilter Self;
typedef ImageToImageFilter<TInputImage,TOutputImage>
Superclass;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef typename Superclass::InputImageType InputImageType;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename OutputImageType::PixelType OutputPixelType;
typedef typename TInputImage::PixelType InputPixelType;
typedef typename InputPixelType::ValueType InputValueType;
/** Run-time type information (and related methods). */
itkTypeMacro( OdfToRgbImageFilter, ImageToImageFilter )
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Print internal ivars */
void PrintSelf(std::ostream& os, Indent indent) const override
{ this->Superclass::PrintSelf( os, indent ); }
#ifdef ITK_USE_CONCEPT_CHECKING
/** Begin concept checking */
itkConceptMacro(InputHasNumericTraitsCheck,
(Concept::HasNumericTraits<InputValueType>));
/** End concept checking */
#endif
protected:
OdfToRgbImageFilter(){}
~OdfToRgbImageFilter() override{}
void GenerateData() override
{
typename InputImageType::Pointer OdfImage = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
typename OutputImageType::Pointer outputImage =
static_cast< OutputImageType * >(this->ProcessObject::GetPrimaryOutput());
typename InputImageType::RegionType region = OdfImage->GetLargestPossibleRegion();
outputImage->SetSpacing( OdfImage->GetSpacing() ); // Set the image spacing
outputImage->SetOrigin( OdfImage->GetOrigin() ); // Set the image origin
outputImage->SetDirection( OdfImage->GetDirection() ); // Set the image direction
outputImage->SetRegions( OdfImage->GetLargestPossibleRegion());
outputImage->Allocate();
typedef ImageRegionConstIterator< InputImageType > OdfImageIteratorType;
OdfImageIteratorType OdfIt(OdfImage, OdfImage->GetLargestPossibleRegion());
typedef ImageRegionIterator< OutputImageType > OutputImageIteratorType;
OutputImageIteratorType outputIt(outputImage, outputImage->GetLargestPossibleRegion());
OdfIt.GoToBegin();
outputIt.GoToBegin();
while(!OdfIt.IsAtEnd() && !outputIt.IsAtEnd()){
InputPixelType x = OdfIt.Get();
typedef itk::OrientationDistributionFunction<float,ODF_SAMPLING_SIZE> OdfType;
OdfType odf(x.GetDataPointer());
vnl_vector_fixed<double,3> dir;
int pd = odf.GetPrincipalDiffusionDirectionIndex();
if (pd==-1)
dir.fill(0);
else
dir = OdfType::GetDirection(pd);
const float fa = odf.GetGeneralizedFractionalAnisotropy();
float r = fabs(dir[0]) * fa;
float g = fabs(dir[1]) * fa;
float b = fabs(dir[2]) * fa;
// float a = (fa-(m_OpacLevel-m_OpacWindow/2.0f))/m_OpacWindow;
float a = fa;
__IMG_DAT_ITEM__CEIL_ZERO_ONE__(r);
__IMG_DAT_ITEM__CEIL_ZERO_ONE__(g);
__IMG_DAT_ITEM__CEIL_ZERO_ONE__(b);
__IMG_DAT_ITEM__CEIL_ZERO_ONE__(a);
OutputPixelType out;
out.SetRed( r * 255.0f);
out.SetGreen( g * 255.0f);
out.SetBlue( b * 255.0f);
out.SetAlpha( a * 255.0f);
outputIt.Set(out);
++OdfIt;
++outputIt;
}
}
private:
OdfToRgbImageFilter(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
};
} // end namespace itk
#endif
diff --git a/Modules/DiffusionCore/Algorithms/itkPolarToCartesianVectorImageFilter.h b/Modules/DiffusionCore/Algorithms/itkPolarToCartesianVectorImageFilter.h
index 810b783..6632f9f 100644
--- a/Modules/DiffusionCore/Algorithms/itkPolarToCartesianVectorImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkPolarToCartesianVectorImageFilter.h
@@ -1,121 +1,121 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkPolarToCartesianVectorImageFilter_h
#define __itkPolarToCartesianVectorImageFilter_h
#include "itkUnaryFunctorImageFilter.h"
namespace itk
{
namespace Functor {
template< typename TInput, typename TOutput, bool symmetric >
class PolarToCartesianFunction
{
public:
PolarToCartesianFunction() {}
~PolarToCartesianFunction() {}
bool operator!=( const PolarToCartesianFunction & ) const
{
return false;
}
bool operator==( const PolarToCartesianFunction & other ) const
{
return !(*this != other);
}
inline TOutput operator()( const TInput & x )
{
TOutput opoint;
opoint[0] = x[0] * cos( x[1] ) * sin( x[2] );
opoint[1] = x[0] * sin( x[1] ) * sin( x[2] );
opoint[2] = x[0] * cos( x[2] );
if(symmetric && opoint[2]<0)
{
opoint[2] = -opoint[2];
}
return opoint;
;
}
};
} // end namespace functor
/** \class PolarToCartesianVectorImageFilter
*
*/
template <typename TInputImage, typename TOutputImage, bool symmetric>
class PolarToCartesianVectorImageFilter :
public
UnaryFunctorImageFilter<TInputImage,TOutputImage,
Functor::PolarToCartesianFunction<
typename TInputImage::PixelType,
typename TOutputImage::PixelType, symmetric> >
{
public:
/** Standard class typedefs. */
typedef PolarToCartesianVectorImageFilter Self;
typedef UnaryFunctorImageFilter<
TInputImage,TOutputImage,
Functor::PolarToCartesianFunction<
typename TInputImage::PixelType,
typename TOutputImage::PixelType, symmetric > > Superclass;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename OutputImageType::PixelType OutputPixelType;
typedef typename TInputImage::PixelType InputPixelType;
typedef typename InputPixelType::ValueType InputValueType;
/** Run-time type information (and related methods). */
itkTypeMacro( PolarToCartesianVectorImageFilter, UnaryFunctorImageFilter );
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Print internal ivars */
void PrintSelf(std::ostream& os, Indent indent) const
{ this->Superclass::PrintSelf( os, indent ); }
#ifdef ITK_USE_CONCEPT_CHECKING
/** Begin concept checking */
itkConceptMacro(InputHasNumericTraitsCheck,
(Concept::HasNumericTraits<InputValueType>));
/** End concept checking */
#endif
protected:
PolarToCartesianVectorImageFilter() {};
virtual ~PolarToCartesianVectorImageFilter() {};
private:
PolarToCartesianVectorImageFilter(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
};
} // end namespace itk
#endif // __itkPolarToCartesianVectorImageFilter_h
diff --git a/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMLocalVariationImageFilter.h b/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMLocalVariationImageFilter.h
index c4db684..86dd916 100644
--- a/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMLocalVariationImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMLocalVariationImageFilter.h
@@ -1,152 +1,152 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkRegularizedIVIMLocalVariationImageFilter_h
#define __itkRegularizedIVIMLocalVariationImageFilter_h
#include "itkImageToImageFilter.h"
#include "itkImage.h"
namespace itk
{
template<class TPixelType>
class IVIMSquaredEuclideanMetric
{
public:
static double Calc(TPixelType p)
{
return p*p;
}
};
template<>
class IVIMSquaredEuclideanMetric<itk::Vector<double,3> >
{
public:
static double Calc(itk::Vector<double,3> p)
{
return p[1]*p[1];
}
};
template<>
class IVIMSquaredEuclideanMetric<itk::VariableLengthVector<float> >
{
public:
static double Calc(itk::VariableLengthVector<float> p)
{
return p.GetSquaredNorm();
}
};
template<>
class IVIMSquaredEuclideanMetric<itk::VariableLengthVector<double> >
{
public:
static double Calc(itk::VariableLengthVector<double> p)
{
return p.GetSquaredNorm();
}
};
/** \class RegularizedIVIMLocalVariationImageFilter
* \brief Calculates the local variation in each pixel
*
* Reference: Tony F. Chan et al., The digital TV filter and nonlinear denoising
*
* \sa Image
* \sa Neighborhood
* \sa NeighborhoodOperator
* \sa NeighborhoodIterator
*
* \ingroup IntensityImageFilters
*/
template <class TInputImage, class TOutputImage>
class RegularizedIVIMLocalVariationImageFilter :
public ImageToImageFilter< TInputImage, TOutputImage >
{
public:
/** Extract dimension from input and output image. */
itkStaticConstMacro(InputImageDimension, unsigned int,
TInputImage::ImageDimension);
itkStaticConstMacro(OutputImageDimension, unsigned int,
TOutputImage::ImageDimension);
/** Convenient typedefs for simplifying declarations. */
typedef TInputImage InputImageType;
typedef TOutputImage OutputImageType;
/** Standard class typedefs. */
typedef RegularizedIVIMLocalVariationImageFilter Self;
typedef ImageToImageFilter< InputImageType, OutputImageType> Superclass;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Run-time type information (and related methods). */
itkTypeMacro(RegularizedIVIMLocalVariationImageFilter, ImageToImageFilter);
/** Image typedef support. */
typedef typename InputImageType::PixelType InputPixelType;
typedef typename OutputImageType::PixelType OutputPixelType;
typedef typename InputImageType::RegionType InputImageRegionType;
typedef typename OutputImageType::RegionType OutputImageRegionType;
typedef typename InputImageType::SizeType InputSizeType;
/** MedianImageFilter needs a larger input requested region than
* the output requested region. As such, MedianImageFilter needs
* to provide an implementation for GenerateInputRequestedRegion()
* in order to inform the pipeline execution model.
*
* \sa ImageToImageFilter::GenerateInputRequestedRegion() */
virtual void GenerateInputRequestedRegion();
protected:
RegularizedIVIMLocalVariationImageFilter();
virtual ~RegularizedIVIMLocalVariationImageFilter() {}
void PrintSelf(std::ostream& os, Indent indent) const;
/** MedianImageFilter can be implemented as a multithreaded filter.
* Therefore, this implementation provides a ThreadedGenerateData()
* routine which is called for each processing thread. The output
* image data is allocated automatically by the superclass prior to
* calling ThreadedGenerateData(). ThreadedGenerateData can only
* write to the portion of the output image specified by the
* parameter "outputRegionForThread"
*
* \sa ImageToImageFilter::ThreadedGenerateData(),
* ImageToImageFilter::GenerateData() */
void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
ThreadIdType threadId );
private:
RegularizedIVIMLocalVariationImageFilter(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
};
} // end namespace itk
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkRegularizedIVIMLocalVariationImageFilter.txx"
#endif
#endif //RegularizedIVIMLocalVariationImageFilter
diff --git a/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMLocalVariationImageFilter.txx b/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMLocalVariationImageFilter.txx
index f3405d8..552109f 100644
--- a/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMLocalVariationImageFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMLocalVariationImageFilter.txx
@@ -1,192 +1,192 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _itkRegularizedIVIMLocalVariationImageFilter_txx
#define _itkRegularizedIVIMLocalVariationImageFilter_txx
#include "itkConstShapedNeighborhoodIterator.h"
#include "itkNeighborhoodInnerProduct.h"
#include "itkImageRegionIterator.h"
#include "itkNeighborhoodAlgorithm.h"
#include "itkZeroFluxNeumannBoundaryCondition.h"
#include "itkOffset.h"
#include "itkProgressReporter.h"
#include "itkVectorImage.h"
#include <vector>
#include <algorithm>
namespace itk
{
template <class TInputImage, class TOutputImage>
RegularizedIVIMLocalVariationImageFilter<TInputImage, TOutputImage>
::RegularizedIVIMLocalVariationImageFilter()
{}
template <class TInputImage, class TOutputImage>
void
RegularizedIVIMLocalVariationImageFilter<TInputImage, TOutputImage>
::GenerateInputRequestedRegion()
{
// call the superclass' implementation of this method
Superclass::GenerateInputRequestedRegion();
// get pointers to the input and output
typename Superclass::InputImagePointer inputPtr =
const_cast< TInputImage * >( this->GetInput() );
typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
if ( !inputPtr || !outputPtr )
{
return;
}
// get a copy of the input requested region (should equal the output
// requested region)
typename TInputImage::RegionType inputRequestedRegion;
inputRequestedRegion = inputPtr->GetRequestedRegion();
// pad the input requested region by 1
inputRequestedRegion.PadByRadius( 1 );
// crop the input requested region at the input's largest possible region
if ( inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()) )
{
inputPtr->SetRequestedRegion( inputRequestedRegion );
return;
}
else
{
// Couldn't crop the region (requested region is outside the largest
// possible region). Throw an exception.
// store what we tried to request (prior to trying to crop)
inputPtr->SetRequestedRegion( inputRequestedRegion );
// build an exception
InvalidRequestedRegionError e(__FILE__, __LINE__);
e.SetLocation(ITK_LOCATION);
e.SetDescription("Requested region outside possible region.");
e.SetDataObject(inputPtr);
throw e;
}
}
template< class TInputImage, class TOutputImage>
void
RegularizedIVIMLocalVariationImageFilter< TInputImage, TOutputImage>
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
ThreadIdType threadId)
{
// Allocate output
typename OutputImageType::Pointer output = this->GetOutput();
typename InputImageType::ConstPointer input = this->GetInput();
itk::Size<InputImageDimension> size;
for(unsigned int i=0; i<InputImageDimension; i++)
size[i] = 1;
// Find the data-set boundary "faces"
NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<InputImageType> bC;
typename NeighborhoodAlgorithm::
ImageBoundaryFacesCalculator<InputImageType>::FaceListType
faceList = bC(input, outputRegionForThread, size);
// support progress methods/callbacks
ProgressReporter progress(
this, threadId, outputRegionForThread.GetNumberOfPixels());
ZeroFluxNeumannBoundaryCondition<InputImageType> nbc;
std::vector<InputPixelType> pixels;
// Process each of the boundary faces. These are N-d regions which border
// the edge of the buffer.
for ( typename NeighborhoodAlgorithm::
ImageBoundaryFacesCalculator<InputImageType>::FaceListType::iterator
fit=faceList.begin(); fit != faceList.end(); ++fit)
{
// iterators over output and input
ImageRegionIterator<OutputImageType>
output_image_it(output, *fit);
ImageRegionConstIterator<InputImageType>
input_image_it(input.GetPointer(), *fit);
// neighborhood iterator for input image
ConstShapedNeighborhoodIterator<InputImageType>
input_image_neighbors_it(size, input, *fit);
typename ConstShapedNeighborhoodIterator<InputImageType>::
OffsetType offset;
input_image_neighbors_it.OverrideBoundaryCondition(&nbc);
input_image_neighbors_it.ClearActiveList();
for(unsigned int i=0; i<InputImageDimension; i++)
{
offset.Fill(0);
offset[i] = -1;
input_image_neighbors_it.ActivateOffset(offset);
offset[i] = 1;
input_image_neighbors_it.ActivateOffset(offset);
}
input_image_neighbors_it.GoToBegin();
//const unsigned int neighborhoodSize = InputImageDimension*2;
while ( ! input_image_neighbors_it.IsAtEnd() )
{
// collect all the pixels in the neighborhood, note that we use
// GetPixel on the NeighborhoodIterator to honor the boundary conditions
typename OutputImageType::PixelType locVariation = 0;
typename ConstShapedNeighborhoodIterator<InputImageType>::
ConstIterator input_neighbors_it;
for (input_neighbors_it = input_image_neighbors_it.Begin();
! input_neighbors_it.IsAtEnd();
input_neighbors_it++)
{
typename TInputImage::PixelType diffVec =
input_neighbors_it.Get()-input_image_it.Get();
locVariation += IVIMSquaredEuclideanMetric
<typename TInputImage::PixelType>::Calc(diffVec);
}
locVariation = sqrt(locVariation + 0.0001);
output_image_it.Set(locVariation);
// update iterators
++input_image_neighbors_it;
++output_image_it;
++input_image_it;
// report progress
progress.CompletedPixel();
}
}
}
/**
* Standard "PrintSelf" method
*/
template <class TInputImage, class TOutput>
void
RegularizedIVIMLocalVariationImageFilter<TInputImage, TOutput>
::PrintSelf(
std::ostream& os,
Indent indent) const
{
Superclass::PrintSelf( os, indent );
}
} // end namespace itk
#endif //_itkRegularizedIVIMLocalVariationImageFilter_txx
diff --git a/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMReconstructionFilter.h b/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMReconstructionFilter.h
index ef0858e..a276a4d 100644
--- a/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMReconstructionFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMReconstructionFilter.h
@@ -1,132 +1,132 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkRegularizedIVIMReconstructionFilter_h
#define __itkRegularizedIVIMReconstructionFilter_h
#include "itkRegularizedIVIMReconstructionSingleIteration.h"
#include "itkImageToImageFilter.h"
#include "itkCastImageFilter.h"
#include "itkImage.h"
namespace itk
{
/** \class RegularizedIVIMReconstructionFilter
* \brief Applies a total variation denoising filter to an image
*
* Reference: Tony F. Chan et al., The digital TV filter and nonlinear denoising
*
* \sa Image
* \sa Neighborhood
* \sa NeighborhoodOperator
* \sa NeighborhoodIterator
*
* \ingroup IntensityImageFilters
*/
template <class TInputPixel, class TOutputPixel, class TRefPixelType>
class RegularizedIVIMReconstructionFilter :
public ImageToImageFilter< itk::Image<itk::Vector<TInputPixel,3>, 3>, itk::Image<itk::Vector<TOutputPixel,3>, 3> >
{
public:
typedef TInputPixel InputPixelType;
typedef TOutputPixel OutputPixelType;
typedef TRefPixelType RefPixelType;
/** Convenient typedefs for simplifying declarations. */
typedef itk::Image<itk::Vector<TInputPixel,3>, 3> InputImageType;
typedef itk::Image<itk::Vector<TOutputPixel,3>, 3> OutputImageType;
typedef itk::VectorImage<TRefPixelType,3> RefImageType;
/** Image typedef support. */
typedef typename InputImageType::PixelType InputVectorType;
typedef typename OutputImageType::PixelType OutputVectorType;
typedef typename RefImageType::PixelType RefVectorType;
/** Extract dimension from input and output image. */
itkStaticConstMacro(InputImageDimension, unsigned int,
InputImageType::ImageDimension);
itkStaticConstMacro(OutputImageDimension, unsigned int,
InputImageType::ImageDimension);
/** Standard class typedefs. */
typedef RegularizedIVIMReconstructionFilter Self;
typedef ImageToImageFilter< InputImageType, OutputImageType> Superclass;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Run-time type information (and related methods). */
itkTypeMacro(RegularizedIVIMReconstructionFilter, ImageToImageFilter);
typedef typename InputImageType::RegionType InputImageRegionType;
typedef typename OutputImageType::RegionType OutputImageRegionType;
typedef typename RefImageType::RegionType RefImageRegionType;
typedef typename InputImageType::SizeType InputSizeType;
typedef RegularizedIVIMReconstructionSingleIteration
<OutputPixelType, OutputPixelType, RefPixelType>
SingleIterationFilterType;
typedef typename itk::CastImageFilter< InputImageType, OutputImageType > CastType;
itkSetMacro(Lambda, double);
itkGetMacro(Lambda, double);
itkSetMacro(NumberIterations, int);
itkGetMacro(NumberIterations, int);
void SetBValues( vnl_vector<double> bvals )
{ this->m_BValues = bvals; }
vnl_vector<double> GetBValues()
{ return this->m_BValues; }
void SetReferenceImage( typename RefImageType::Pointer refimg )
{ this->m_ReferenceImage = refimg; }
typename RefImageType::Pointer GetReferenceImage()
{ return this->m_ReferenceImage; }
protected:
RegularizedIVIMReconstructionFilter();
virtual ~RegularizedIVIMReconstructionFilter() {}
void PrintSelf(std::ostream& os, Indent indent) const;
void GenerateData();
double m_Lambda;
int m_NumberIterations;
typename RefImageType::Pointer m_ReferenceImage;
vnl_vector<double> m_BValues;
private:
RegularizedIVIMReconstructionFilter(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
};
} // end namespace itk
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkRegularizedIVIMReconstructionFilter.txx"
#endif
#endif //__itkRegularizedIVIMReconstructionFilter__
diff --git a/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMReconstructionFilter.txx b/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMReconstructionFilter.txx
index 4c69819..0594ee1 100644
--- a/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMReconstructionFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMReconstructionFilter.txx
@@ -1,108 +1,108 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _itkRegularizedIVIMReconstructionFilter_txx
#define _itkRegularizedIVIMReconstructionFilter_txx
#include "itkConstShapedNeighborhoodIterator.h"
#include "itkNeighborhoodInnerProduct.h"
#include "itkImageRegionIterator.h"
#include "itkImageRegionConstIterator.h"
#include "itkNeighborhoodAlgorithm.h"
#include "itkZeroFluxNeumannBoundaryCondition.h"
#include "itkOffset.h"
#include "itkProgressReporter.h"
#include <vector>
#include <algorithm>
namespace itk
{
template <class TInputPixel, class TOutputPixel, class TRefPixelType>
RegularizedIVIMReconstructionFilter<TInputPixel, TOutputPixel, TRefPixelType>
::RegularizedIVIMReconstructionFilter()
{
m_Lambda = 1.0;
}
template <class TInputPixel, class TOutputPixel, class TRefPixelType>
void
RegularizedIVIMReconstructionFilter<TInputPixel, TOutputPixel, TRefPixelType>
::GenerateData()
{
// first we cast the input image to match output type
typename CastType::Pointer infilter = CastType::New();
infilter->SetInput(this->GetInput());
infilter->Update();
typename OutputImageType::Pointer image = infilter->GetOutput();
typename SingleIterationFilterType::Pointer filter;
for(int i=0; i<m_NumberIterations; i++)
{
filter = SingleIterationFilterType::New();
filter->SetInput( image.GetPointer() );
filter->SetOriginalImage( m_ReferenceImage );
filter->SetBValues(m_BValues);
filter->SetLambda(m_Lambda);
filter->SetNumberOfThreads(this->GetNumberOfThreads());
filter->UpdateLargestPossibleRegion();
image = filter->GetOutput();
std::cout << "Iteration " << i+1 << "/" <<
m_NumberIterations << std::endl;
}
typename OutputImageType::Pointer output = this->GetOutput();
output->SetOrigin( image->GetOrigin() ); // Set the image origin
output->SetDirection( image->GetDirection() ); // Set the image direction
output->SetSpacing(image->GetSpacing());
output->SetLargestPossibleRegion( image->GetLargestPossibleRegion() );
output->SetBufferedRegion( image->GetLargestPossibleRegion() );
output->Allocate();
itk::ImageRegionIterator<OutputImageType> oit(
output, output->GetLargestPossibleRegion());
oit.GoToBegin();
itk::ImageRegionConstIterator<OutputImageType> iit(
image, image->GetLargestPossibleRegion());
iit.GoToBegin();
while(!oit.IsAtEnd())
{
oit.Set(iit.Get());
++iit;
++oit;
}
}
/**
* Standard "PrintSelf" method
*/
template <class TInputPixel, class TOutputPixel, class TRefPixelType>
void
RegularizedIVIMReconstructionFilter<TInputPixel, TOutputPixel, TRefPixelType>
::PrintSelf(
std::ostream& os,
Indent indent) const
{
Superclass::PrintSelf( os, indent );
}
} // end namespace itk
#endif
diff --git a/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMReconstructionSingleIteration.h b/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMReconstructionSingleIteration.h
index b75f2a4..fb9b9dc 100644
--- a/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMReconstructionSingleIteration.h
+++ b/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMReconstructionSingleIteration.h
@@ -1,141 +1,141 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkRegularizedIVIMReconstructionSingleIteration_h
#define __itkRegularizedIVIMReconstructionSingleIteration_h
#include "itkImageToImageFilter.h"
#include "itkImage.h"
#include "itkVectorImage.h"
namespace itk
{
/** \class RegularizedIVIMReconstructionSingleIteration
* \brief Applies a total variation denoising filter to an image
*
* Reference: Tony F. Chan et al., The digital TV filter and nonlinear denoising
*
* \sa Image
* \sa Neighborhood
* \sa NeighborhoodOperator
* \sa NeighborhoodIterator
*
* \ingroup IntensityImageFilters
*/
template <class TInputPixel, class TOutputPixel, class TRefPixelType>
class RegularizedIVIMReconstructionSingleIteration :
public ImageToImageFilter< itk::Image<itk::Vector<TInputPixel,3>, 3>, itk::Image<itk::Vector<TOutputPixel,3>, 3> >
{
public:
/** Convenient typedefs for simplifying declarations. */
typedef itk::Image<itk::Vector<TInputPixel,3>, 3> InputImageType;
typedef itk::Image<itk::Vector<TOutputPixel,3>, 3> OutputImageType;
typedef itk::VectorImage<TRefPixelType,3> RefImageType;
/** Extract dimension from input and output image. */
itkStaticConstMacro(InputImageDimension, unsigned int,
InputImageType::ImageDimension);
itkStaticConstMacro(OutputImageDimension, unsigned int,
OutputImageType::ImageDimension);
typedef itk::Image<float,InputImageDimension> LocalVariationImageType;
/** Standard class typedefs. */
typedef RegularizedIVIMReconstructionSingleIteration Self;
typedef ImageToImageFilter< InputImageType, OutputImageType> Superclass;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Run-time type information (and related methods). */
itkTypeMacro(RegularizedIVIMReconstructionSingleIteration, ImageToImageFilter);
/** Image typedef support. */
typedef typename InputImageType::PixelType InputPixelType;
typedef typename OutputImageType::PixelType OutputPixelType;
typedef typename InputImageType::RegionType InputImageRegionType;
typedef typename OutputImageType::RegionType OutputImageRegionType;
typedef typename InputImageType::SizeType InputSizeType;
/** A larger input requested region than
* the output requested region is required.
* Therefore, an implementation for GenerateInputRequestedRegion()
* is provided.
*
* \sa ImageToImageFilter::GenerateInputRequestedRegion() */
virtual void GenerateInputRequestedRegion();
itkSetMacro(Lambda, double);
itkGetMacro(Lambda, double);
void SetBValues(vnl_vector<double> bvals)
{ this->m_BValues = bvals; }
vnl_vector<double> GetBValues()
{ return this->m_BValues; }
void SetOriginalImage(RefImageType* in)
{ this->m_OriginalImage = in; }
typename RefImageType::Pointer GetOriginialImage()
{ return this->m_OriginalImage; }
protected:
RegularizedIVIMReconstructionSingleIteration();
virtual ~RegularizedIVIMReconstructionSingleIteration() {}
void PrintSelf(std::ostream& os, Indent indent) const;
/** MedianImageFilter can be implemented as a multithreaded filter.
* Therefore, this implementation provides a ThreadedGenerateData()
* routine which is called for each processing thread. The output
* image data is allocated automatically by the superclass prior to
* calling ThreadedGenerateData(). ThreadedGenerateData can only
* write to the portion of the output image specified by the
* parameter "outputRegionForThread"
*
* \sa ImageToImageFilter::ThreadedGenerateData(),
* ImageToImageFilter::GenerateData() */
void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
ThreadIdType threadId );
void BeforeThreadedGenerateData();
typename LocalVariationImageType::Pointer m_LocalVariation;
typename RefImageType::Pointer m_OriginalImage;
double m_Lambda;
vnl_vector<double> m_BValues;
private:
RegularizedIVIMReconstructionSingleIteration(const Self&);
void operator=(const Self&);
};
} // end namespace itk
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkRegularizedIVIMReconstructionSingleIteration.txx"
#endif
#endif //__itkRegularizedIVIMReconstructionSingleIteration__
diff --git a/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMReconstructionSingleIteration.txx b/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMReconstructionSingleIteration.txx
index ce37694..9c547fc 100644
--- a/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMReconstructionSingleIteration.txx
+++ b/Modules/DiffusionCore/Algorithms/itkRegularizedIVIMReconstructionSingleIteration.txx
@@ -1,310 +1,310 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _itkRegularizedIVIMReconstructionSingleIteration_txx
#define _itkRegularizedIVIMReconstructionSingleIteration_txx
// itk includes
#include "itkConstShapedNeighborhoodIterator.h"
#include "itkNeighborhoodInnerProduct.h"
#include "itkImageRegionIterator.h"
#include "itkNeighborhoodAlgorithm.h"
#include "itkZeroFluxNeumannBoundaryCondition.h"
#include "itkOffset.h"
#include "itkProgressReporter.h"
#include "itkRegularizedIVIMLocalVariationImageFilter.h"
// other includes
#include <vector>
#include <algorithm>
#define IVIM_FOO -100000
namespace itk
{
/**
* constructor
*/
template <class TInputPixel, class TOutputPixel, class TRefPixelType>
RegularizedIVIMReconstructionSingleIteration<TInputPixel, TOutputPixel, TRefPixelType>
::RegularizedIVIMReconstructionSingleIteration()
{
m_Lambda = 1.0;
m_LocalVariation = LocalVariationImageType::New();
}
/**
* generate requested region
*/
template <class TInputPixel, class TOutputPixel, class TRefPixelType>
void
RegularizedIVIMReconstructionSingleIteration<TInputPixel, TOutputPixel, TRefPixelType>
::GenerateInputRequestedRegion()
{
// call the superclass' implementation of this method
Superclass::GenerateInputRequestedRegion();
// get pointers to the input and output
typename Superclass::InputImagePointer inputPtr =
const_cast< InputImageType * >( this->GetInput() );
typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
if ( !inputPtr || !outputPtr )
{
return;
}
// get a copy of the input requested region (should equal the output
// requested region)
typename InputImageType::RegionType inputRequestedRegion;
inputRequestedRegion = inputPtr->GetRequestedRegion();
// pad the input requested region by 1
inputRequestedRegion.PadByRadius( 1 );
// crop the input requested region at the input's largest possible region
if ( inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()) )
{
inputPtr->SetRequestedRegion( inputRequestedRegion );
return;
}
else
{
// Couldn't crop the region (requested region is outside the largest
// possible region). Throw an exception.
// store what we tried to request (prior to trying to crop)
inputPtr->SetRequestedRegion( inputRequestedRegion );
// build an exception
InvalidRequestedRegionError e(__FILE__, __LINE__);
e.SetLocation(ITK_LOCATION);
e.SetDescription("Requested region outside possible region.");
e.SetDataObject(inputPtr);
throw e;
}
}
/**
* generate output
*/
template <class TInputPixel, class TOutputPixel, class TRefPixelType>
void
RegularizedIVIMReconstructionSingleIteration<TInputPixel, TOutputPixel, TRefPixelType>
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
ThreadIdType)
{
typename OutputImageType::Pointer output = this->GetOutput();
typename InputImageType::ConstPointer input = this->GetInput();
// Find the data-set boundary "faces"
itk::Size<InputImageDimension> size;
for( unsigned int i=0; i<InputImageDimension; i++)
size[i] = 1;
NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<InputImageType> bC;
typename NeighborhoodAlgorithm::
ImageBoundaryFacesCalculator<InputImageType>::FaceListType
faceList = bC(input, outputRegionForThread, size);
NeighborhoodAlgorithm::
ImageBoundaryFacesCalculator<LocalVariationImageType> lv_bC;
typename NeighborhoodAlgorithm::
ImageBoundaryFacesCalculator<LocalVariationImageType>::FaceListType
lv_faceList = lv_bC(m_LocalVariation, outputRegionForThread, size);
ZeroFluxNeumannBoundaryCondition<InputImageType> nbc;
ZeroFluxNeumannBoundaryCondition<LocalVariationImageType> lv_nbc;
std::vector<double> ws;
std::vector<double> hs;
typename NeighborhoodAlgorithm::
ImageBoundaryFacesCalculator<InputImageType>::FaceListType::iterator
lv_fit=lv_faceList.begin();
// Process each of the boundary faces. These are N-d regions which border
// the edge of the buffer.
for ( typename NeighborhoodAlgorithm::
ImageBoundaryFacesCalculator<InputImageType>::FaceListType::iterator
fit=faceList.begin(); fit != faceList.end(); ++fit)
{
// iterators over output, input, original and local variation image
ImageRegionIterator<OutputImageType> output_image_it =
ImageRegionIterator<OutputImageType>(output, *fit);
ImageRegionConstIterator<InputImageType> input_image_it =
ImageRegionConstIterator<InputImageType>(input, *fit);
ImageRegionConstIterator<RefImageType> orig_image_it =
ImageRegionConstIterator<RefImageType>(m_OriginalImage, *fit);
ImageRegionConstIterator<LocalVariationImageType> loc_var_image_it =
ImageRegionConstIterator<LocalVariationImageType>(
m_LocalVariation, *fit);
// neighborhood in input image
ConstShapedNeighborhoodIterator<InputImageType>
input_image_neighbors_it(size, input, *fit);
typename ConstShapedNeighborhoodIterator<InputImageType>::
OffsetType offset;
input_image_neighbors_it.OverrideBoundaryCondition(&nbc);
input_image_neighbors_it.ClearActiveList();
for(unsigned int i=0; i<InputImageDimension; i++)
{
offset.Fill(0);
offset[i] = -1;
input_image_neighbors_it.ActivateOffset(offset);
offset[i] = 1;
input_image_neighbors_it.ActivateOffset(offset);
}
input_image_neighbors_it.GoToBegin();
// neighborhood in local variation image
ConstShapedNeighborhoodIterator<LocalVariationImageType>
loc_var_image_neighbors_it(size, m_LocalVariation, *lv_fit);
loc_var_image_neighbors_it.OverrideBoundaryCondition(&lv_nbc);
loc_var_image_neighbors_it.ClearActiveList();
for(unsigned int i=0; i<InputImageDimension; i++)
{
offset.Fill(0);
offset[i] = -1;
loc_var_image_neighbors_it.ActivateOffset(offset);
offset[i] = 1;
loc_var_image_neighbors_it.ActivateOffset(offset);
}
loc_var_image_neighbors_it.GoToBegin();
const unsigned int neighborhoodSize = InputImageDimension*2;
ws.resize(neighborhoodSize);
while ( ! output_image_it.IsAtEnd() )
{
//MITK_INFO << "looking at voxel " << output_image_it.GetIndex();
// 1 / ||nabla_alpha(u)||_a
double locvar_alpha_inv = 1.0/loc_var_image_it.Get();
//MITK_INFO << "locvar: " << loc_var_image_it.Get();
// compute w_alphabetas
int count = 0;
double wsum = 0;
typename ConstShapedNeighborhoodIterator<LocalVariationImageType>::
ConstIterator loc_var_neighbors_it;
for (loc_var_neighbors_it = loc_var_image_neighbors_it.Begin();
! loc_var_neighbors_it.IsAtEnd();
loc_var_neighbors_it++)
{
// w_alphabeta(u) =
// 1 / ||nabla_alpha(u)||_a + 1 / ||nabla_beta(u)||_a
ws[count] =
locvar_alpha_inv + (1.0/(double)loc_var_neighbors_it.Get());
wsum += ws[count++];
//MITK_INFO << "nb var: " << count << ": " << loc_var_neighbors_it.Get();
}
//MITK_INFO << "wsum: " << wsum;
// h_alphaalpha * u_alpha^zero
typename RefImageType::PixelType orig = orig_image_it.Get();
// vnl_vector<double> estim(orig.GetSize());
// vnl_matrix<double> diff(orig.GetSize(),1);
// vnl_matrix<double> estimdash(orig.GetSize(),2);
vnl_vector_fixed<double,2> step;
step[0] = 0; step[1]=0;
for(size_t ind=0; ind<m_BValues.size(); ind++)
{
//MITK_INFO << "refval: " << orig[ind];
double estim = (1-input_image_it.Get()[0])*exp(-m_BValues[ind]*input_image_it.Get()[1]);
double estimdash1 = exp(-m_BValues[ind]*input_image_it.Get()[1]);
double estimdash2 = (-1.0) * (1.0-input_image_it.Get()[0]) * m_BValues[ind] * exp(-m_BValues[ind]*input_image_it.Get()[1]);
//MITK_INFO << "estimdash1: " << estimdash1 << "; estimdash2: " << estimdash2 << "; diff: " << (double) orig[ind] - estim;
if(orig[ind] != IVIM_FOO)
{
step[0] += ((double) orig[ind] - estim) * estimdash2;
step[1] += ((double) orig[ind] - estim) * estimdash1;
}
}
step[1] *= m_Lambda / (m_Lambda+wsum);
// add the different h_alphabeta * u_beta
count = 0;
typename ConstShapedNeighborhoodIterator<InputImageType>::
ConstIterator input_neighbors_it;
for (input_neighbors_it = input_image_neighbors_it.Begin();
! input_neighbors_it.IsAtEnd();
input_neighbors_it++)
{
step[1] += (input_neighbors_it.Get()[1] - input_image_it.Get()[1]) * (ws[count++] / (m_Lambda+wsum));
}
//MITK_INFO << "stepfinal: " << step[0] << "; " << step[1];
// set output result
OutputPixelType out;
out[0] = input_image_it.Get()[0] + .001*step[0];
out[1] = input_image_it.Get()[1] + .00001*step[1];
output_image_it.Set( out );
//MITK_INFO << "(" << input_image_it.Get()[0] << " ; " << input_image_it.Get()[1] << ") => (" << out[0] << " ; " << out[1] << ")";
// increment iterators
++output_image_it;
++input_image_it;
++orig_image_it;
++loc_var_image_it;
++input_image_neighbors_it;
++loc_var_image_neighbors_it;
}
++lv_fit;
}
}
/**
* first calculate local variation in the image
*/
template <class TInputPixel, class TOutputPixel, class TRefPixelType>
void
RegularizedIVIMReconstructionSingleIteration<TInputPixel, TOutputPixel, TRefPixelType>
::BeforeThreadedGenerateData()
{
typedef typename itk::RegularizedIVIMLocalVariationImageFilter
<InputImageType,LocalVariationImageType> FilterType;
typename FilterType::Pointer filter = FilterType::New();
filter->SetInput(this->GetInput(0));
filter->SetNumberOfThreads(this->GetNumberOfThreads());
filter->Update();
this->m_LocalVariation = filter->GetOutput();
}
/**
* Standard "PrintSelf" method
*/
template <class TInputPixel, class TOutputPixel, class TRefPixelType>
void
RegularizedIVIMReconstructionSingleIteration<TInputPixel, TOutputPixel, TRefPixelType>
::PrintSelf(
std::ostream& os,
Indent indent) const
{
Superclass::PrintSelf( os, indent );
}
} // end namespace itk
#endif
diff --git a/Modules/DiffusionCore/Algorithms/itkRemoveDwiChannelFilter.h b/Modules/DiffusionCore/Algorithms/itkRemoveDwiChannelFilter.h
index 35f27f0..d3bbed2 100644
--- a/Modules/DiffusionCore/Algorithms/itkRemoveDwiChannelFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkRemoveDwiChannelFilter.h
@@ -1,84 +1,84 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*===================================================================
This file is based heavily on a corresponding ITK filter.
===================================================================*/
#ifndef __itkRemoveDwiChannelFilter_h_
#define __itkRemoveDwiChannelFilter_h_
#include "itkImageToImageFilter.h"
#include "itkVectorImage.h"
#include <itkImageRegionIteratorWithIndex.h>
#include <mitkDiffusionPropertyHelper.h>
namespace itk{
/** \class RemoveDwiChannelFilter
* \brief Remove spcified channels from diffusion-weighted image.
*/
template< class TInPixelType >
class RemoveDwiChannelFilter :
public ImageToImageFilter< VectorImage< TInPixelType, 3 >, VectorImage< TInPixelType, 3 > >
{
public:
typedef RemoveDwiChannelFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< VectorImage< TInPixelType, 3 >, VectorImage< TInPixelType, 3 > > Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(RemoveDwiChannelFilter, ImageToImageFilter)
typedef typename Superclass::InputImageType InputImageType;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename Superclass::OutputImageRegionType OutputImageRegionType;
typedef typename mitk::DiffusionPropertyHelper::GradientDirectionType DirectionType;
typedef typename mitk::DiffusionPropertyHelper::GradientDirectionsContainerType DirectionContainerType;
void SetChannelIndices( std::vector< unsigned int > indices ){ m_ChannelIndices = indices; }
void SetDirections( typename DirectionContainerType::Pointer directions ){ m_Directions = directions; }
typename DirectionContainerType::Pointer GetNewDirections(){ return m_NewDirections; }
protected:
RemoveDwiChannelFilter();
~RemoveDwiChannelFilter() {}
void PrintSelf(std::ostream& os, Indent indent) const override;
void BeforeThreadedGenerateData() override;
void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType id ) override;
std::vector< unsigned int > m_ChannelIndices;
typename DirectionContainerType::Pointer m_Directions;
typename DirectionContainerType::Pointer m_NewDirections;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkRemoveDwiChannelFilter.txx"
#endif
#endif //__itkRemoveDwiChannelFilter_h_
diff --git a/Modules/DiffusionCore/Algorithms/itkRemoveDwiChannelFilter.txx b/Modules/DiffusionCore/Algorithms/itkRemoveDwiChannelFilter.txx
index 4002677..4985188 100644
--- a/Modules/DiffusionCore/Algorithms/itkRemoveDwiChannelFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkRemoveDwiChannelFilter.txx
@@ -1,133 +1,133 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkRemoveDwiChannelFilter_txx
#define __itkRemoveDwiChannelFilter_txx
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionConstIteratorWithIndex.h"
#include "itkImageRegionIterator.h"
namespace itk {
template< class TInPixelType >
RemoveDwiChannelFilter< TInPixelType>::RemoveDwiChannelFilter()
{
this->SetNumberOfRequiredInputs( 1 );
}
template< class TInPixelType >
void RemoveDwiChannelFilter< TInPixelType>::BeforeThreadedGenerateData()
{
typename InputImageType::Pointer inputImagePointer = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
if ( inputImagePointer->GetVectorLength()-m_ChannelIndices.size()<=0 )
itkExceptionMacro("No channels remaining!");
typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0));
outputImage->SetSpacing( inputImagePointer->GetSpacing() );
outputImage->SetOrigin( inputImagePointer->GetOrigin() );
outputImage->SetDirection( inputImagePointer->GetDirection() );
outputImage->SetLargestPossibleRegion( inputImagePointer->GetLargestPossibleRegion() );
outputImage->SetBufferedRegion( inputImagePointer->GetLargestPossibleRegion() );
outputImage->SetRequestedRegion( inputImagePointer->GetLargestPossibleRegion() );
outputImage->Allocate();
outputImage->SetVectorLength( inputImagePointer->GetVectorLength()-m_ChannelIndices.size() );
typename OutputImageType::PixelType nullPix;
nullPix.SetSize(outputImage->GetVectorLength());
nullPix.Fill(0);
outputImage->FillBuffer(nullPix);
this->SetNthOutput(0, outputImage);
m_NewDirections = DirectionContainerType::New();
int chIdx = 0;
for (unsigned int i=0; i<inputImagePointer->GetVectorLength(); i++)
{
bool use = true;
for (unsigned int j=0; j<m_ChannelIndices.size(); j++)
if (m_ChannelIndices.at(j)==i)
{
use = false;
break;
}
if (use)
{
m_NewDirections->InsertElement(chIdx, m_Directions->GetElement(i));
++chIdx;
MITK_INFO << "Using channel " << i;
}
}
}
template< class TInPixelType >
void RemoveDwiChannelFilter< TInPixelType>::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, ThreadIdType )
{
typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0));
ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread);
oit.GoToBegin();
typedef ImageRegionConstIterator< InputImageType > InputIteratorType;
typename InputImageType::Pointer inputImagePointer = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
InputIteratorType git( inputImagePointer, outputRegionForThread );
git.GoToBegin();
while( !git.IsAtEnd() )
{
int chIdx = 0;
typename OutputImageType::PixelType pix = oit.Get();
for (unsigned int i=0; i<inputImagePointer->GetVectorLength(); i++)
{
bool use = true;
for (unsigned int j=0; j<m_ChannelIndices.size(); j++)
if (m_ChannelIndices.at(j)==i)
{
use = false;
break;
}
if (use)
{
pix[chIdx] = git.Get()[i];
++chIdx;
}
}
oit.Set(pix);
++oit;
++git;
}
std::cout << "One Thread finished calculation" << std::endl;
}
template< class TInPixelType >
void
RemoveDwiChannelFilter< TInPixelType>
::PrintSelf(std::ostream& os, Indent indent) const
{
Superclass::PrintSelf(os,indent);
}
}
#endif // __itkRemoveDwiChannelFilter_txx
diff --git a/Modules/DiffusionCore/Algorithms/itkResampleDwiImageFilter.h b/Modules/DiffusionCore/Algorithms/itkResampleDwiImageFilter.h
index 759b203..c4b70d0 100644
--- a/Modules/DiffusionCore/Algorithms/itkResampleDwiImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkResampleDwiImageFilter.h
@@ -1,146 +1,146 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*=========================================================================
Program: Tensor ToolKit - TTK
Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkResampleDwiImageFilter.h $
Language: C++
Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $
Version: $Revision: 68 $
Copyright (c) INRIA 2010. All rights reserved.
See LICENSE.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef _itk_ResampleDwiImageFilter_h_
#define _itk_ResampleDwiImageFilter_h_
#include <itkImageToImageFilter.h>
#include <itkVectorImage.h>
#include <itkPointShell.h>
namespace itk
{
/**
* \brief Resample DWI channel by channel. */
template <class TScalarType>
class ResampleDwiImageFilter
: public ImageToImageFilter<itk::VectorImage<TScalarType,3>, itk::VectorImage<TScalarType,3> >
{
public:
enum Interpolation {
Interpolate_NearestNeighbour,
Interpolate_Linear,
Interpolate_BSpline,
Interpolate_WindowedSinc
};
typedef ResampleDwiImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< itk::VectorImage<TScalarType,3>, itk::VectorImage<TScalarType,3> >
Superclass;
typedef itk::Vector< double, 3 > DoubleVectorType;
typedef itk::VectorImage<TScalarType,3> DwiImageType;
typedef itk::Image<TScalarType,3> DwiChannelType;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(ResampleDwiImageFilter, ImageToImageFilter)
itkSetMacro( Interpolation, Interpolation )
void SetSamplingFactor(DoubleVectorType sampling)
{
m_NewSpacing = this->GetInput()->GetSpacing();
m_NewSpacing[0] /= sampling[0];
m_NewSpacing[1] /= sampling[1];
m_NewSpacing[2] /= sampling[2];
m_NewImageRegion = this->GetInput()->GetLargestPossibleRegion();
m_NewImageRegion.SetSize(0, m_NewImageRegion.GetSize(0)*sampling[0]);
m_NewImageRegion.SetSize(1, m_NewImageRegion.GetSize(1)*sampling[1]);
m_NewImageRegion.SetSize(2, m_NewImageRegion.GetSize(2)*sampling[2]);
}
void SetNewSpacing(DoubleVectorType spacing)
{
DoubleVectorType oldSpacing = this->GetInput()->GetSpacing();
DoubleVectorType sampling;
sampling[0] = oldSpacing[0]/spacing[0];
sampling[1] = oldSpacing[1]/spacing[1];
sampling[2] = oldSpacing[2]/spacing[2];
m_NewSpacing = spacing;
m_NewImageRegion = this->GetInput()->GetLargestPossibleRegion();
m_NewImageRegion.SetSize(0, m_NewImageRegion.GetSize(0)*sampling[0]);
m_NewImageRegion.SetSize(1, m_NewImageRegion.GetSize(1)*sampling[1]);
m_NewImageRegion.SetSize(2, m_NewImageRegion.GetSize(2)*sampling[2]);
}
void SetNewImageSize(ImageRegion<3> region)
{
ImageRegion<3> oldRegion = this->GetInput()->GetLargestPossibleRegion();
DoubleVectorType sampling;
sampling[0] = (double)region.GetSize(0)/oldRegion.GetSize(0);
sampling[1] = (double)region.GetSize(1)/oldRegion.GetSize(1);
sampling[2] = (double)region.GetSize(2)/oldRegion.GetSize(2);
m_NewImageRegion = region;
m_NewSpacing = this->GetInput()->GetSpacing();
m_NewSpacing[0] /= sampling[0];
m_NewSpacing[1] /= sampling[1];
m_NewSpacing[2] /= sampling[2];
}
void UpdateOutputInformation() override;
virtual void PropagateRequestedRegion(){}
void PropagateRequestedRegion(itk::DataObject *) override{}
void VerifyInputInformation() override{}
protected:
ResampleDwiImageFilter();
~ResampleDwiImageFilter() override{}
void GenerateData() override;
DoubleVectorType m_NewSpacing;
ImageRegion<3> m_NewImageRegion;
Interpolation m_Interpolation;
};
} // end of namespace
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkResampleDwiImageFilter.txx"
#endif
#endif
diff --git a/Modules/DiffusionCore/Algorithms/itkResampleDwiImageFilter.txx b/Modules/DiffusionCore/Algorithms/itkResampleDwiImageFilter.txx
index e7c1bb2..0035dd3 100644
--- a/Modules/DiffusionCore/Algorithms/itkResampleDwiImageFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkResampleDwiImageFilter.txx
@@ -1,176 +1,176 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*=========================================================================
Program: Tensor ToolKit - TTK
Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkResampleDwiImageFilter.txx $
Language: C++
Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $
Version: $Revision: 68 $
Copyright (c) INRIA 2010. All rights reserved.
See LICENSE.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef _itk_ResampleDwiImageFilter_txx_
#define _itk_ResampleDwiImageFilter_txx_
#endif
#define _USE_MATH_DEFINES
#include "itkResampleDwiImageFilter.h"
#include <itkImageRegionIterator.h>
#include <itkImageRegion.h>
#include <itkResampleImageFilter.h>
#include <itkBSplineInterpolateImageFunction.h>
#include <itkNearestNeighborInterpolateImageFunction.h>
#include <itkLinearInterpolateImageFunction.h>
#include <itkWindowedSincInterpolateImageFunction.h>
namespace itk
{
template <class TScalarType>
ResampleDwiImageFilter<TScalarType>
::ResampleDwiImageFilter()
: m_Interpolation(Interpolate_Linear)
{
this->SetNumberOfRequiredInputs( 1 );
}
template <class TScalarType>
void
ResampleDwiImageFilter<TScalarType>
::GenerateData()
{
// // initialize output image
// itk::Vector< double, 3 > spacing = this->GetInput()->GetSpacing();
// spacing[0] /= m_SamplingFactor[0];
// spacing[1] /= m_SamplingFactor[1];
// spacing[2] /= m_SamplingFactor[2];
// ImageRegion<3> region = this->GetInput()->GetLargestPossibleRegion();
// region.SetSize(0, region.GetSize(0)*m_SamplingFactor[0]);
// region.SetSize(1, region.GetSize(1)*m_SamplingFactor[1]);
// region.SetSize(2, region.GetSize(2)*m_SamplingFactor[2]);
itk::Point<double,3> origin = this->GetInput()->GetOrigin();
origin[0] -= this->GetInput()->GetSpacing()[0]/2;
origin[1] -= this->GetInput()->GetSpacing()[1]/2;
origin[2] -= this->GetInput()->GetSpacing()[2]/2;
origin[0] += m_NewSpacing[0]/2;
origin[1] += m_NewSpacing[1]/2;
origin[2] += m_NewSpacing[2]/2;
typename DwiImageType::Pointer outImage = DwiImageType::New();
outImage->SetSpacing( m_NewSpacing );
outImage->SetOrigin( origin );
outImage->SetDirection( this->GetInput()->GetDirection() );
outImage->SetLargestPossibleRegion( m_NewImageRegion );
outImage->SetBufferedRegion( m_NewImageRegion );
outImage->SetRequestedRegion( m_NewImageRegion );
outImage->SetVectorLength( this->GetInput()->GetVectorLength() );
outImage->Allocate();
typename itk::ResampleImageFilter<DwiChannelType, DwiChannelType>::Pointer resampler = itk::ResampleImageFilter<DwiChannelType, DwiChannelType>::New();
resampler->SetOutputParametersFromImage(outImage);
switch (m_Interpolation)
{
case Interpolate_NearestNeighbour:
{
typename itk::NearestNeighborInterpolateImageFunction<DwiChannelType>::Pointer interp = itk::NearestNeighborInterpolateImageFunction<DwiChannelType>::New();
resampler->SetInterpolator(interp);
break;
}
case Interpolate_Linear:
{
typename itk::LinearInterpolateImageFunction<DwiChannelType>::Pointer interp = itk::LinearInterpolateImageFunction<DwiChannelType>::New();
resampler->SetInterpolator(interp);
break;
}
case Interpolate_BSpline:
{
typename itk::BSplineInterpolateImageFunction<DwiChannelType>::Pointer interp = itk::BSplineInterpolateImageFunction<DwiChannelType>::New();
resampler->SetInterpolator(interp);
break;
}
case Interpolate_WindowedSinc:
{
typename itk::WindowedSincInterpolateImageFunction<DwiChannelType, 3>::Pointer interp = itk::WindowedSincInterpolateImageFunction<DwiChannelType, 3>::New();
resampler->SetInterpolator(interp);
break;
}
default:
{
typename itk::LinearInterpolateImageFunction<DwiChannelType>::Pointer interp = itk::LinearInterpolateImageFunction<DwiChannelType>::New();
resampler->SetInterpolator(interp);
}
}
for (unsigned int i=0; i<this->GetInput()->GetVectorLength(); i++)
{
typename DwiChannelType::Pointer channel = DwiChannelType::New();
channel->SetSpacing( this->GetInput()->GetSpacing() );
channel->SetOrigin( this->GetInput()->GetOrigin() );
channel->SetDirection( this->GetInput()->GetDirection() );
channel->SetLargestPossibleRegion( this->GetInput()->GetLargestPossibleRegion() );
channel->SetBufferedRegion( this->GetInput()->GetLargestPossibleRegion() );
channel->SetRequestedRegion( this->GetInput()->GetLargestPossibleRegion() );
channel->Allocate();
ImageRegionIterator<DwiChannelType> it(channel, channel->GetLargestPossibleRegion());
while(!it.IsAtEnd())
{
typename DwiImageType::PixelType pix = this->GetInput()->GetPixel(it.GetIndex());
it.Set(pix[i]);
++it;
}
resampler->SetInput(channel);
resampler->Update();
channel = resampler->GetOutput();
ImageRegionIterator<DwiImageType> it2(outImage, outImage->GetLargestPossibleRegion());
while(!it2.IsAtEnd())
{
typename DwiImageType::PixelType pix = it2.Get();
pix[i] = channel->GetPixel(it2.GetIndex());
it2.Set(pix);
++it2;
}
}
this->SetNthOutput(0, outImage);
}
template <class TScalarType>
void
ResampleDwiImageFilter<TScalarType>
::UpdateOutputInformation()
{
// Calls to superclass updateoutputinformation
//Superclass::UpdateOutputInformation();
this->GetOutput()->SetSpacing(m_NewSpacing);
this->GetOutput()->SetLargestPossibleRegion(m_NewImageRegion);
}
} // end of namespace
diff --git a/Modules/DiffusionCore/Algorithms/itkResidualImageFilter.h b/Modules/DiffusionCore/Algorithms/itkResidualImageFilter.h
index 046b06c..1101ef5 100644
--- a/Modules/DiffusionCore/Algorithms/itkResidualImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkResidualImageFilter.h
@@ -1,177 +1,177 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*=========================================================================
Program: Tensor ToolKit - TTK
Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkTensorImageToDiffusionImageFilter.h $
Language: C++
Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $
Version: $Revision: 68 $
Copyright (c) INRIA 2010. All rights reserved.
See LICENSE.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef _itk_ResidualImageFilter_h_
#define _itk_ResidualImageFilter_h_
#include "itkImageToImageFilter.h"
#include <itkDiffusionTensor3D.h>
namespace itk
{
template <class TInputScalarType, class TOutputScalarType>
class ResidualImageFilter
: public ImageToImageFilter<itk::VectorImage<TInputScalarType,3>, itk::Image<TOutputScalarType,3> >
{
public:
typedef TInputScalarType InputScalarType;
typedef itk::VectorImage<InputScalarType,3> InputImageType;
typedef typename InputImageType::PixelType InputPixelType;
typedef typename InputImageType::RegionType InputImageRegionType;
typedef TOutputScalarType OutputScalarType;
typedef itk::Image<OutputScalarType,3> OutputImageType;
typedef typename OutputImageType::PixelType OutputPixelType;
typedef typename OutputImageType::RegionType OutputImageRegionType;
typedef ResidualImageFilter Self;
typedef ImageToImageFilter<InputImageType, OutputImageType> Superclass;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef vnl_vector_fixed< double, 3 > GradientDirectionType;
typedef itk::VectorContainer< unsigned int,
GradientDirectionType > GradientDirectionContainerType;
typedef itk::Image<InputScalarType,3> BaselineImageType;
itkTypeMacro (ResidualImageFilter, ImageToImageFilter);
itkStaticConstMacro (ImageDimension, unsigned int,
OutputImageType::ImageDimension);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
void SetSecondDiffusionImage(typename InputImageType::Pointer diffImage)
{
m_SecondDiffusionImage = diffImage;
}
std::vector<double> GetQ1()
{
return m_Q1;
}
std::vector<double> GetQ3()
{
return m_Q3;
}
std::vector<double> GetMeans()
{
return m_Means;
}
std::vector<double> GetPercentagesOfOutliers()
{
return m_PercentagesOfOutliers;
}
std::vector< std::vector<double> > GetOutliersPerSlice()
{
return m_OutliersPerSlice;
}
void SetGradients(GradientDirectionContainerType* grads)
{
m_Gradients = grads;
}
void SetBaseLineImage(BaselineImageType* baseline)
{
m_BaseLineImage = baseline;
}
void SetB0Threshold(InputScalarType threshold)
{
m_B0Threshold = threshold;
}
itkSetMacro(B0Index, int)
protected:
ResidualImageFilter()
{
m_B0Threshold = 30.0; // default value. allow user to redefine
};
~ResidualImageFilter(){};
void PrintSelf (std::ostream& os, Indent indent) const override
{
Superclass::PrintSelf (os, indent);
}
void GenerateData() override;
private:
ResidualImageFilter (const Self&);
void operator=(const Self&);
typename InputImageType::Pointer m_SecondDiffusionImage;
std::vector<double> m_Means, m_Q1, m_Q3, m_PercentagesOfOutliers;
// 'Outer' vector: slices, 'Inner' volumes
std::vector< std::vector<double> > m_OutliersPerSlice;
GradientDirectionContainerType* m_Gradients;
typename BaselineImageType::Pointer m_BaseLineImage;
InputScalarType m_B0Threshold;
int m_B0Index;
};
} // end of namespace
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkResidualImageFilter.txx"
#endif
#endif
diff --git a/Modules/DiffusionCore/Algorithms/itkResidualImageFilter.txx b/Modules/DiffusionCore/Algorithms/itkResidualImageFilter.txx
index 7935c83..0fe7d68 100644
--- a/Modules/DiffusionCore/Algorithms/itkResidualImageFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkResidualImageFilter.txx
@@ -1,285 +1,285 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*=========================================================================
Program: Tensor ToolKit - TTK
Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkTensorImageToDiffusionImageFilter.txx $
Language: C++
Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $
Version: $Revision: 68 $
Copyright (c) INRIA 2010. All rights reserved.
See LICENSE.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef _itk_ResidualImageFilter_txx_
#define _itk_ResidualImageFilter_txx_
#endif
#include "itkResidualImageFilter.h"
#include <mitkCommon.h>
#include <cmath>
namespace itk
{
template <class TInputScalarType, class TOutputScalarType>
void
ResidualImageFilter<TInputScalarType, TOutputScalarType>
::GenerateData()
{
typename InputImageType::SizeType size = this->GetInput()->GetLargestPossibleRegion().GetSize();
typename InputImageType::SizeType size2 = m_SecondDiffusionImage->GetLargestPossibleRegion().GetSize();
if(size != size2)
{
MITK_ERROR << "Sizes do not match";
return;
}
// Initialize output image
typename OutputImageType::Pointer outputImage =
static_cast< OutputImageType * >(this->ProcessObject::GetPrimaryOutput());
outputImage->SetSpacing( this->GetInput()->GetSpacing() ); // Set the image spacing
outputImage->SetOrigin( this->GetInput()->GetOrigin() ); // Set the image origin
outputImage->SetDirection( this->GetInput()->GetDirection() ); // Set the image direction
outputImage->SetRegions( this->GetInput()->GetLargestPossibleRegion() );
outputImage->Allocate();
outputImage->FillBuffer(0.0);
std::vector< std::vector<double> > residuals;
// per slice, per volume
std::vector< std::vector <std::vector<double> > > residualsPerSlice;
// Detrmine number of B0 images
int numberB0=0;
for(unsigned int i=0; i<m_Gradients->Size(); i++)
{
GradientDirectionType grad = m_Gradients->ElementAt(i);
if(fabs(grad[0]) < 0.001 && fabs(grad[1]) < 0.001 && fabs(grad[2]) < 0.001)
{
numberB0++;
}
}
residuals.resize(this->GetInput()->GetVectorLength()-numberB0);
// Calculate the standard residual image and for each volume put all residuals in a vector
for(unsigned int z=0; z<size[2]; z++)
{
std::vector< std::vector<double> > sliceResiduals; // residuals per volume for this slice
sliceResiduals.resize(this->GetInput()->GetVectorLength()-numberB0);
for(unsigned int y=0; y<size[1]; y++)
{
for(unsigned int x=0; x<size[0]; x++)
{
// Check if b0 exceeds threshold
itk::Index<3> ix;
ix[0] = x;
ix[1] = y;
ix[2] = z;
typename InputImageType::PixelType p1 = this->GetInput()->GetPixel(ix);
typename InputImageType::PixelType p2 = m_SecondDiffusionImage->GetPixel(ix);
if(p1.GetSize() != p2.GetSize())
{
MITK_ERROR << "Vector sizes do not match";
return;
}
if(p1.GetElement(m_B0Index) <= m_B0Threshold)
{
continue;
}
double res = 0;
int shift = 0; // correction for the skipped B0 images
for(unsigned int i = 0; i<p1.GetSize(); i++)
{
GradientDirectionType grad = m_Gradients->ElementAt(i);
if(!(fabs(grad[0]) < 0.001 && fabs(grad[1]) < 0.001 && fabs(grad[2]) < 0.001))
{
double val1 = (double)p1.GetElement(i);
double val2 = (double)p2.GetElement(i);
res += abs(val1-val2);
residuals[i-shift].push_back(val1-val2);
sliceResiduals[i-shift].push_back(val1-val2);
}
else
{
shift++;
}
}
res = res/p1.GetSize();
outputImage->SetPixel(ix, res);
}
}
residualsPerSlice.push_back(sliceResiduals);
}
// for each dw volume: sort the the measured residuals (for each voxel) to enable determining Q1 and Q3; calculate means
// determine percentage of errors as described in QUALITY ASSESSMENT THROUGH ANALYSIS OF RESIDUALS OF DIFFUSION IMAGE FITTING
// Leemans et al 2008
double q1,q3, median;
std::vector< std::vector<double> >::iterator it = residuals.begin();
while(it != residuals.end())
{
std::vector<double> res = *it;
// sort
std::sort(res.begin(), res.end());
q1 = res[0.25*res.size()];
m_Q1.push_back(q1);
q3 = res[0.75*res.size()];
m_Q3.push_back(q3);
median = res[0.5*res.size()];
double iqr = q3-q1;
double outlierThreshold = median + 1.5*iqr;
double numberOfOutliers = 0.0;
std::vector<double>::iterator resIt = res.begin();
double mean = 0;
while(resIt != res.end())
{
double f = *resIt;
if(f>outlierThreshold)
{
numberOfOutliers++;
}
mean += f;
++resIt;
}
double percOfOutliers = 100 * numberOfOutliers / res.size();
m_PercentagesOfOutliers.push_back(percOfOutliers);
mean /= res.size();
m_Means.push_back(mean);
++it;
}
// Calculate for each slice the number of outliers per volume(dw volume)
std::vector< std::vector <std::vector<double> > >::iterator sliceIt = residualsPerSlice.begin();
while(sliceIt != residualsPerSlice.end())
{
std::vector< std::vector<double> > currentSlice = *sliceIt;
std::vector<double> percentages;
std::vector< std::vector<double> >::iterator volIt = currentSlice.begin();
while(volIt != currentSlice.end())
{
std::vector<double> currentVolume = *volIt;
//sort
std::sort(currentVolume.begin(), currentVolume.end());
q1 = currentVolume[0.25*currentVolume.size()];
q3 = currentVolume[0.75*currentVolume.size()];
median = currentVolume[0.5*currentVolume.size()];
double iqr = q3-q1;
double outlierThreshold = median + 1.5*iqr;
double numberOfOutliers = 0.0;
std::vector<double>::iterator resIt = currentVolume.begin();
double mean(0.0);
while(resIt != currentVolume.end())
{
double f = *resIt;
if(f>outlierThreshold)
{
numberOfOutliers++;
}
mean += f;
++resIt;
}
double percOfOutliers = 100 * numberOfOutliers / currentVolume.size();
percentages.push_back(percOfOutliers);
++volIt;
}
m_OutliersPerSlice.push_back(percentages);
++sliceIt;
}
}
} // end of namespace
diff --git a/Modules/DiffusionCore/Algorithms/itkShCoefficientImageExporter.cpp b/Modules/DiffusionCore/Algorithms/itkShCoefficientImageExporter.cpp
index f5b3bc9..c5a1a17 100644
--- a/Modules/DiffusionCore/Algorithms/itkShCoefficientImageExporter.cpp
+++ b/Modules/DiffusionCore/Algorithms/itkShCoefficientImageExporter.cpp
@@ -1,111 +1,111 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkShCoefficientImageExporter_cpp
#define __itkShCoefficientImageExporter_cpp
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include "itkShCoefficientImageExporter.h"
#include <itkImageRegionIterator.h>
#include <boost/math/special_functions.hpp>
using namespace boost::math;
namespace itk {
template< class PixelType, int ShOrder >
ShCoefficientImageExporter< PixelType, ShOrder >::ShCoefficientImageExporter()
{
}
template< class PixelType, int ShOrder >
void ShCoefficientImageExporter< PixelType, ShOrder >
::GenerateData()
{
if (m_InputImage.IsNull())
return;
Vector<double, 4> spacing4;
Point<float, 4> origin4;
Matrix<double, 4, 4> direction4; direction4.SetIdentity();
ImageRegion<4> imageRegion4;
Vector<double, 3> spacing3 = m_InputImage->GetSpacing();
Point<float, 3> origin3 = m_InputImage->GetOrigin();
Matrix<double, 3, 3> direction3 = m_InputImage->GetDirection();
ImageRegion<3> imageRegion3 = m_InputImage->GetLargestPossibleRegion();
spacing4[0] = spacing3[0]; spacing4[1] = spacing3[1]; spacing4[2] = spacing3[2]; spacing4[3] = 1;
origin4[0] = origin3[0]; origin4[1] = origin3[1]; origin4[2] = origin3[2]; origin4[3] = 0;
for (int r=0; r<3; r++)
for (int c=0; c<3; c++)
direction4[r][c] = direction3[r][c];
imageRegion4.SetSize(0, imageRegion3.GetSize()[0]);
imageRegion4.SetSize(1, imageRegion3.GetSize()[1]);
imageRegion4.SetSize(2, imageRegion3.GetSize()[2]);
imageRegion4.SetSize(3, (ShOrder*ShOrder + ShOrder + 2)/2 + ShOrder );
m_OutputImage = CoefficientImageType::New();
m_OutputImage->SetSpacing( spacing4 );
m_OutputImage->SetOrigin( origin4 );
m_OutputImage->SetDirection( direction4 );
m_OutputImage->SetRegions( imageRegion4 );
m_OutputImage->Allocate();
m_OutputImage->FillBuffer(0.0);
typedef ImageRegionConstIterator< InputImageType > InputIteratorType;
InputIteratorType it(m_InputImage, m_InputImage->GetLargestPossibleRegion());
int numCoeffs = imageRegion4.GetSize(3);
int x = imageRegion3.GetSize(0);
int y = imageRegion3.GetSize(1);
int z = imageRegion3.GetSize(2);
#ifdef WIN32
#pragma omp parallel for
#else
#pragma omp parallel for collapse(3)
#endif
for (int a=0; a<x; a++)
for (int b=0; b<y; b++)
for (int c=0; c<z; c++)
{
typename InputImageType::IndexType index3;
index3.SetElement(0,a);
index3.SetElement(1,b);
index3.SetElement(2,c);
CoefficientImageType::IndexType index4;
index4[0] = index3[0];
index4[1] = index3[1];
index4[2] = index3[2];
typename InputImageType::PixelType pix = m_InputImage->GetPixel(index3);
for (int i=0; i<numCoeffs; i++)
{
index4[3] = i;
m_OutputImage->SetPixel(index4, pix[i]);
}
}
}
}
#endif // __itkShCoefficientImageExporter_cpp
diff --git a/Modules/DiffusionCore/Algorithms/itkShCoefficientImageExporter.h b/Modules/DiffusionCore/Algorithms/itkShCoefficientImageExporter.h
index e517bd0..6253cc5 100644
--- a/Modules/DiffusionCore/Algorithms/itkShCoefficientImageExporter.h
+++ b/Modules/DiffusionCore/Algorithms/itkShCoefficientImageExporter.h
@@ -1,80 +1,79 @@
-/*=========================================================================
+/*===================================================================
- Program: Insight Segmentation & Registration Toolkit
- Module: $RCSfile: itkDiffusionTensor3DReconstructionImageFilter.h,v $
- Language: C++
- Date: $Date: 2006-03-27 17:01:06 $
- Version: $Revision: 1.12 $
+The Medical Imaging Interaction Toolkit (MITK)
- Copyright (c) Insight Software Consortium. All rights reserved.
- See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
+Copyright (c) German Cancer Research Center.
- This software is distributed WITHOUT ANY WARRANTY; without even
- the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- PURPOSE. See the above copyright notices for more information.
+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 __itkShCoefficientImageExporter_h_
#define __itkShCoefficientImageExporter_h_
#include <itkOrientationDistributionFunction.h>
namespace itk{
/** \class ShCoefficientImageExporter
Converts FSL reconstructions of diffusionweighted images (4D images containing the sh coefficients) to Odf images or 3D sh-coefficient images.
*/
template< class PixelType, int ShOrder >
class ShCoefficientImageExporter : public ProcessObject
{
public:
enum NormalizationMethods {
NO_NORM,
SINGLE_VEC_NORM,
SPACING_COMPENSATION
};
typedef ShCoefficientImageExporter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ProcessObject Superclass;
typedef itk::Image< float, 4 > CoefficientImageType;
typedef Image< Vector< PixelType, (ShOrder*ShOrder + ShOrder + 2)/2 + ShOrder >, 3 > InputImageType;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(ShCoefficientImageExporter, ProcessObject)
// input
itkSetMacro( InputImage, typename InputImageType::Pointer) ///< sh coefficient image in FSL file format
// output
itkGetMacro( OutputImage, typename CoefficientImageType::Pointer) ///< mitk style image containing the SH coefficients
void GenerateData() override;
protected:
ShCoefficientImageExporter();
~ShCoefficientImageExporter() override{}
typename InputImageType::Pointer m_InputImage;
CoefficientImageType::Pointer m_OutputImage;
private:
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkShCoefficientImageExporter.cpp"
#endif
#endif //__itkShCoefficientImageExporter_h_
diff --git a/Modules/DiffusionCore/Algorithms/itkShCoefficientImageImporter.cpp b/Modules/DiffusionCore/Algorithms/itkShCoefficientImageImporter.cpp
index cf0985e..e17f85c 100644
--- a/Modules/DiffusionCore/Algorithms/itkShCoefficientImageImporter.cpp
+++ b/Modules/DiffusionCore/Algorithms/itkShCoefficientImageImporter.cpp
@@ -1,104 +1,104 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkShCoefficientImageImporter_cpp
#define __itkShCoefficientImageImporter_cpp
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include "itkShCoefficientImageImporter.h"
#include <itkImageRegionIterator.h>
#include <mitkDiffusionFunctionCollection.h>
namespace itk {
template< class PixelType, int ShOrder >
ShCoefficientImageImporter< PixelType, ShOrder >::ShCoefficientImageImporter()
{
}
template< class PixelType, int ShOrder >
void ShCoefficientImageImporter< PixelType, ShOrder >
::GenerateData()
{
if (m_InputImage.IsNull())
return;
Vector<float, 4> spacing4 = m_InputImage->GetSpacing();
Point<float, 4> origin4 = m_InputImage->GetOrigin();
Matrix<double, 4, 4> direction4 = m_InputImage->GetDirection();
ImageRegion<4> imageRegion4 = m_InputImage->GetLargestPossibleRegion();
Vector<double, 3> spacing3;
Point<float, 3> origin3;
Matrix<double, 3, 3> direction3;
ImageRegion<3> imageRegion3;
spacing3[0] = spacing4[0]; spacing3[1] = spacing4[1]; spacing3[2] = spacing4[2];
origin3[0] = origin4[0]; origin3[1] = origin4[1]; origin3[2] = origin4[2];
for (int r=0; r<3; r++)
for (int c=0; c<3; c++)
direction3[r][c] = direction4[r][c];
imageRegion3.SetSize(0, imageRegion4.GetSize()[0]);
imageRegion3.SetSize(1, imageRegion4.GetSize()[1]);
imageRegion3.SetSize(2, imageRegion4.GetSize()[2]);
m_CoefficientImage = CoefficientImageType::New();
m_CoefficientImage->SetSpacing( spacing3 );
m_CoefficientImage->SetOrigin( origin3 );
m_CoefficientImage->SetDirection( direction3 );
m_CoefficientImage->SetRegions( imageRegion3 );
m_CoefficientImage->Allocate();
Vector< PixelType, (ShOrder*ShOrder + ShOrder + 2)/2 + ShOrder > nullVec2; nullVec2.Fill(0.0);
m_CoefficientImage->FillBuffer(nullVec2);
int x = imageRegion4.GetSize(0);
int y = imageRegion4.GetSize(1);
int z = imageRegion4.GetSize(2);
int numCoeffs = imageRegion4.GetSize(3);
#ifdef WIN32
#pragma omp parallel for
#else
#pragma omp parallel for collapse(3)
#endif
for (int a=0; a<x; a++)
for (int b=0; b<y; b++)
for (int c=0; c<z; c++)
{
typename InputImageType::IndexType index;
index.SetElement(0,a);
index.SetElement(1,b);
index.SetElement(2,c);
typename CoefficientImageType::PixelType pix;
for (int d=0; d<numCoeffs; d++)
{
index.SetElement(3,d);
pix[d] = m_InputImage->GetPixel(index);
}
typename CoefficientImageType::IndexType index2;
index2.SetElement(0,a);
index2.SetElement(1,b);
index2.SetElement(2,c);
m_CoefficientImage->SetPixel(index2, pix);
}
}
}
#endif // __itkShCoefficientImageImporter_cpp
diff --git a/Modules/DiffusionCore/Algorithms/itkShCoefficientImageImporter.h b/Modules/DiffusionCore/Algorithms/itkShCoefficientImageImporter.h
index 1556a00..01c7f0c 100644
--- a/Modules/DiffusionCore/Algorithms/itkShCoefficientImageImporter.h
+++ b/Modules/DiffusionCore/Algorithms/itkShCoefficientImageImporter.h
@@ -1,74 +1,73 @@
-/*=========================================================================
+/*===================================================================
- Program: Insight Segmentation & Registration Toolkit
- Module: $RCSfile: itkDiffusionTensor3DReconstructionImageFilter.h,v $
- Language: C++
- Date: $Date: 2006-03-27 17:01:06 $
- Version: $Revision: 1.12 $
+The Medical Imaging Interaction Toolkit (MITK)
- Copyright (c) Insight Software Consortium. All rights reserved.
- See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
+Copyright (c) German Cancer Research Center.
- This software is distributed WITHOUT ANY WARRANTY; without even
- the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- PURPOSE. See the above copyright notices for more information.
+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 __itkShCoefficientImageImporter_h_
#define __itkShCoefficientImageImporter_h_
#include <itkOrientationDistributionFunction.h>
namespace itk{
/** \class ShCoefficientImageImporter
Converts converts 4D SH coefficient images (MRtrix) to 3D vector images containing the SH coefficients
*/
template< class PixelType, int ShOrder >
class ShCoefficientImageImporter : public ProcessObject
{
public:
typedef ShCoefficientImageImporter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ProcessObject Superclass;
typedef itk::Image< float, 4 > InputImageType;
typedef Image< Vector< PixelType, (ShOrder*ShOrder + ShOrder + 2)/2 + ShOrder >, 3 > CoefficientImageType;
typedef Image< Vector< PixelType, ODF_SAMPLING_SIZE >, 3 > OdfImageType;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(ShCoefficientImageImporter, ProcessObject)
// input
itkSetMacro( InputImage, InputImageType::Pointer) ///< sh coefficient image in FSL file format
// output
itkGetMacro( CoefficientImage, typename CoefficientImageType::Pointer) ///< mitk style image containing the SH coefficients
void GenerateData() override;
protected:
ShCoefficientImageImporter();
~ShCoefficientImageImporter() override{}
InputImageType::Pointer m_InputImage;
typename CoefficientImageType::Pointer m_CoefficientImage; ///< mitk style image containing the SH coefficients
private:
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkShCoefficientImageImporter.cpp"
#endif
#endif //__itkShCoefficientImageImporter_h_
diff --git a/Modules/DiffusionCore/Algorithms/itkShToOdfImageFilter.cpp b/Modules/DiffusionCore/Algorithms/itkShToOdfImageFilter.cpp
index 3fe8371..e686ef1 100644
--- a/Modules/DiffusionCore/Algorithms/itkShToOdfImageFilter.cpp
+++ b/Modules/DiffusionCore/Algorithms/itkShToOdfImageFilter.cpp
@@ -1,80 +1,80 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkShToOdfImageFilter_cpp
#define __itkShToOdfImageFilter_cpp
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include "itkShToOdfImageFilter.h"
#include <itkImageRegionIterator.h>
#include <mitkDiffusionFunctionCollection.h>
namespace itk {
template< class PixelType, int ShOrder >
ShToOdfImageFilter< PixelType, ShOrder >::ShToOdfImageFilter()
: m_Toolkit(mitk::ShImage::SH_CONVENTION::MRTRIX)
{
}
template< class PixelType, int ShOrder >
void ShToOdfImageFilter< PixelType, ShOrder >::BeforeThreadedGenerateData()
{
CalcShBasis();
}
template< class PixelType, int ShOrder >
void ShToOdfImageFilter< PixelType, ShOrder >::ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType)
{
typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetPrimaryOutput());
typename InputImageType::Pointer inputImage = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
typedef ImageRegionConstIterator< InputImageType > InputIteratorType;
InputIteratorType it(inputImage, outputRegionForThread);
typedef ImageRegionIterator< OutputImageType > OutputIteratorType;
OutputIteratorType oit(outputImage, outputRegionForThread);
while(!it.IsAtEnd())
{
auto pix = it.Get();
vnl_vector<PixelType> coeffs = pix.GetVnlVector();
OutputPixelType odf = (m_ShBasis * coeffs).data_block();
oit.Set(odf);
++it;
++oit;
}
}
// generate spherical harmonic values of the desired order for each input direction
template< class PixelType, int ShOrder >
void ShToOdfImageFilter< PixelType, ShOrder >::CalcShBasis()
{
vnl_matrix_fixed<double, 3, ODF_SAMPLING_SIZE>* U = itk::PointShell<ODF_SAMPLING_SIZE, vnl_matrix_fixed<double, 3, ODF_SAMPLING_SIZE> >::DistributePointShell();
if (m_Toolkit==mitk::ShImage::SH_CONVENTION::MRTRIX)
m_ShBasis = mitk::sh::CalcShBasisForDirections(ShOrder, U->as_matrix());
else
m_ShBasis = mitk::sh::CalcShBasisForDirections(ShOrder, U->as_matrix(), false);
}
}
#endif // __itkShToOdfImageFilter_cpp
diff --git a/Modules/DiffusionCore/Algorithms/itkShToOdfImageFilter.h b/Modules/DiffusionCore/Algorithms/itkShToOdfImageFilter.h
index 13e2dca..1b820f6 100644
--- a/Modules/DiffusionCore/Algorithms/itkShToOdfImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkShToOdfImageFilter.h
@@ -1,83 +1,82 @@
-/*=========================================================================
+/*===================================================================
- Program: Insight Segmentation & Registration Toolkit
- Module: $RCSfile: itkDiffusionTensor3DReconstructionImageFilter.h,v $
- Language: C++
- Date: $Date: 2006-03-27 17:01:06 $
- Version: $Revision: 1.12 $
+The Medical Imaging Interaction Toolkit (MITK)
- Copyright (c) Insight Software Consortium. All rights reserved.
- See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
+Copyright (c) German Cancer Research Center.
- This software is distributed WITHOUT ANY WARRANTY; without even
- the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- PURPOSE. See the above copyright notices for more information.
+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 __itkShToOdfImageFilter_h_
#define __itkShToOdfImageFilter_h_
#include <itkOrientationDistributionFunction.h>
#include <itkImageToImageFilter.h>
#include <mitkShImage.h>
namespace itk{
/** \class ShToOdfImageFilter
*/
template< class PixelType, int ShOrder >
class ShToOdfImageFilter : public
ImageToImageFilter< itk::Image< itk::Vector< PixelType, (ShOrder*ShOrder + ShOrder + 2)/2 + ShOrder >, 3 >, itk::Image< itk::Vector<PixelType,ODF_SAMPLING_SIZE>,3> >
{
public:
typedef itk::Vector< PixelType, (ShOrder*ShOrder + ShOrder + 2)/2 + ShOrder > InputPixelType;
typedef itk::Image<InputPixelType,3> InputImageType;
typedef typename InputImageType::RegionType InputImageRegionType;
typedef itk::Vector<PixelType,ODF_SAMPLING_SIZE> OutputPixelType;
typedef itk::Image<OutputPixelType,3> OutputImageType;
typedef typename OutputImageType::RegionType OutputImageRegionType;
typedef ShToOdfImageFilter Self;
typedef itk::ImageToImageFilter<InputImageType, OutputImageType> Superclass;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(ShToOdfImageFilter, ImageToImageFilter)
itkSetMacro( Toolkit, mitk::ShImage::SH_CONVENTION) ///< define SH coefficient convention (depends on toolkit)
itkGetMacro( Toolkit, mitk::ShImage::SH_CONVENTION) ///< SH coefficient convention (depends on toolkit)
void BeforeThreadedGenerateData();
void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType);
protected:
ShToOdfImageFilter();
~ShToOdfImageFilter(){}
void CalcShBasis();
vnl_matrix<float> m_ShBasis;
mitk::ShImage::SH_CONVENTION m_Toolkit;
private:
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkShToOdfImageFilter.cpp"
#endif
#endif //__itkShToOdfImageFilter_h_
diff --git a/Modules/DiffusionCore/Algorithms/itkShToRgbImageFilter.h b/Modules/DiffusionCore/Algorithms/itkShToRgbImageFilter.h
index 26f8933..7735945 100644
--- a/Modules/DiffusionCore/Algorithms/itkShToRgbImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkShToRgbImageFilter.h
@@ -1,160 +1,160 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkShToRgbImageFilter_h
#define __itkShToRgbImageFilter_h
#include "itkUnaryFunctorImageFilter.h"
#include "itkOrientationDistributionFunction.h"
#include "itkRGBAPixel.h"
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionIterator.h"
#include <mitkDiffusionFunctionCollection.h>
#include <mitkShImage.h>
namespace itk
{
#define __IMG_DAT_ITEM__CEIL_ZERO_ONE__(val) (val) = \
( (val) < 0 ) ? ( 0 ) : ( ( (val)>1 ) ? ( 1 ) : ( (val) ) );
/** \class ShToRgbImageFilter
*
*/
template <typename TInputImage, int ShOrder,
typename TOutputImage=itk::Image<itk::RGBAPixel<unsigned char>,3> >
class ShToRgbImageFilter :
public ImageToImageFilter<TInputImage,TOutputImage>
{
public:
/** Standard class typedefs. */
typedef ShToRgbImageFilter Self;
typedef ImageToImageFilter<TInputImage,TOutputImage>
Superclass;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef typename Superclass::InputImageType InputImageType;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename OutputImageType::PixelType OutputPixelType;
typedef typename TInputImage::PixelType InputPixelType;
typedef typename InputPixelType::ValueType InputValueType;
/** Run-time type information (and related methods). */
itkTypeMacro( ShToRgbImageFilter, ImageToImageFilter )
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Print internal ivars */
void PrintSelf(std::ostream& os, Indent indent) const override
{ this->Superclass::PrintSelf( os, indent ); }
#ifdef ITK_USE_CONCEPT_CHECKING
/** Begin concept checking */
itkConceptMacro(InputHasNumericTraitsCheck,
(Concept::HasNumericTraits<InputValueType>));
/** End concept checking */
#endif
itkSetMacro( ShConvention, mitk::ShImage::SH_CONVENTION) ///< define SH coefficient convention
itkGetMacro( ShConvention, mitk::ShImage::SH_CONVENTION) ///< SH coefficient convention
protected:
ShToRgbImageFilter(){}
~ShToRgbImageFilter() override{}
mitk::ShImage::SH_CONVENTION m_ShConvention = mitk::ShImage::SH_CONVENTION::MRTRIX;
void ThreadedGenerateData( const typename OutputImageType::RegionType &outputRegionForThread, ThreadIdType) override
{
typename InputImageType::Pointer coeff_image = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetPrimaryOutput());
outputImage->SetSpacing( coeff_image->GetSpacing() ); // Set the image spacing
outputImage->SetOrigin( coeff_image->GetOrigin() ); // Set the image origin
outputImage->SetDirection( coeff_image->GetDirection() ); // Set the image direction
outputImage->SetRegions( coeff_image->GetLargestPossibleRegion());
outputImage->Allocate();
typedef ImageRegionConstIterator< InputImageType > OdfImageIteratorType;
OdfImageIteratorType it(coeff_image, outputRegionForThread);
typedef ImageRegionIterator< OutputImageType > OutputImageIteratorType;
OutputImageIteratorType oit(outputImage, outputRegionForThread);
it.GoToBegin();
oit.GoToBegin();
typedef itk::OrientationDistributionFunction<float,ODF_SAMPLING_SIZE> OdfType;
vnl_matrix<float> sh2Basis = mitk::sh::CalcShBasisForDirections(ShOrder, itk::PointShell<ODF_SAMPLING_SIZE, vnl_matrix_fixed<double, 3, ODF_SAMPLING_SIZE> >::DistributePointShell()->as_matrix(), m_ShConvention);
while(!it.IsAtEnd() && !oit.IsAtEnd())
{
InputPixelType x = it.Get();
Vector< float, ODF_SAMPLING_SIZE > odf_vals;
vnl_vector< float > coeffs(x.GetNumberOfComponents());
for(unsigned int i=0; i<x.GetNumberOfComponents(); i++)
coeffs[i] = (float)x[i];
odf_vals = ( sh2Basis * coeffs ).data_block();
OdfType odf;
for(int i=0; i<ODF_SAMPLING_SIZE; i++)
odf[i] = odf_vals[i];
vnl_vector_fixed<double,3> dir;
int pd = odf.GetPrincipalDiffusionDirectionIndex();
if (pd==-1)
dir.fill(0);
else
dir = OdfType::GetDirection(pd);
const float fa = odf.GetGeneralizedFractionalAnisotropy();
float r = fabs(dir[0]) * fa;
float g = fabs(dir[1]) * fa;
float b = fabs(dir[2]) * fa;
float a = fa;
__IMG_DAT_ITEM__CEIL_ZERO_ONE__(r);
__IMG_DAT_ITEM__CEIL_ZERO_ONE__(g);
__IMG_DAT_ITEM__CEIL_ZERO_ONE__(b);
__IMG_DAT_ITEM__CEIL_ZERO_ONE__(a);
OutputPixelType out;
out.SetRed( r * 255.0f);
out.SetGreen( g * 255.0f);
out.SetBlue( b * 255.0f);
out.SetAlpha( a * 255.0f);
oit.Set(out);
++it;
++oit;
}
}
private:
ShToRgbImageFilter(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
};
} // end namespace itk
#endif
diff --git a/Modules/DiffusionCore/Algorithms/itkSplitDWImageFilter.h b/Modules/DiffusionCore/Algorithms/itkSplitDWImageFilter.h
index f590bc3..790e5dc 100644
--- a/Modules/DiffusionCore/Algorithms/itkSplitDWImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkSplitDWImageFilter.h
@@ -1,153 +1,153 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 ITKSPLITDWIMAGEFILTER_H
#define ITKSPLITDWIMAGEFILTER_H
#include "itkImageToImageFilter.h"
#include <itkVectorImage.h>
namespace itk
{
/** \class SplitDWImageFilter
*
* \brief Splits a DW-Image passed in as input into a 3D-t image where each volume coresponds to a
* gradient image ( or the unweighted b0 )
*
* Several applications require to get the gradient images as a separate volume, f.e. the registration for
* head-motion correction. Also a reduction of the DW Image is possible when combined with its counterpart filter,
* the \sa mitkImageToDiffusionImageSource, which can reinterpret a 3d+t (scalar) image into a diffusion weighted image.
*/
template< class TInputImagePixelType,
class TOutputImagePixelType >
class SplitDWImageFilter :
public ImageToImageFilter< VectorImage<TInputImagePixelType, 3>,
Image< TOutputImagePixelType, 4 > >
{
public:
typedef SplitDWImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef TInputImagePixelType InputPixelType;
typedef TOutputImagePixelType OutputPixelType;
typedef ImageToImageFilter< VectorImage<TInputImagePixelType, 3>,
Image< TOutputImagePixelType, 4 > > Superclass;
/** typedefs from superclass */
typedef typename Superclass::InputImageType InputImageType;
//typedef typename Superclass::OutputImageType OutputImageType;
typedef Image< TOutputImagePixelType, 4 > OutputImageType;
typedef typename OutputImageType::RegionType OutputImageRegionType;
typedef std::vector< unsigned int > IndexListType;
typedef std::map< unsigned int, IndexListType> BValueMapType;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(SplitDWImageFilter, ImageToImageFilter);
/**
* @brief Set the indices of the images to be extracted.
*
*
*/
void SetExtractIndices( IndexListType list)
{
m_IndexList = list;
}
/**
* @brief Extract all images
*
* The same as setting SetExtractIndices( ) with [0,1,2,...,N]
*/
void SetExtractAll()
{
m_ExtractAllImages = true;
}
/**
* @brief Selects only the weighted images with b-value above the given b_threshold to be extracted
*
* Setting b_threshold to 0 will do the same as \sa SetExtractAll. Please note that some images have no true
* unweighted images as the minimal b-value is something like 5 so for extracting all.
*
* @note It will reorder the images!
*
* @param b_threshold the minimal b-value to be extracted
* @param map the map with b-values to the corresponding image
*
* @sa GetIndexList
*/
void SetExtractAllAboveThreshold( double b_threshold, BValueMapType map);
/**
* @brief SetExtractSingleShell
* @param b_value b-value of the shell to be extracted
* @param tol the tolerance of the shell choice, i.e. all shells within [ b_value - tol, b_value + tol ] will be extracted
*/
void SetExtractSingleShell( double b_value, BValueMapType map, double tol );
/**
* @brief Returns the index list used for extraction
*
* The list is necessary for further processing, especially when a b-value threshold is used ( like in \sa SetExtractAllAboveThreshold )
*
* @return The index list used during the extraction
*/
const IndexListType GetIndexList() const
{
return m_IndexList;
}
protected:
SplitDWImageFilter();
virtual ~SplitDWImageFilter(){};
void GenerateData();
/** The dimension of the output does not match the dimension of the input
hence we need to re-implement the CopyInformation method to avoid
executing the default implementation which tries to copy the input information to the
output
*/
virtual void CopyInformation( const DataObject *data);
/** Override of the ProcessObject::GenerateOutputInformation() because of different
dimensionality of the input and the output
*/
virtual void GenerateOutputInformation();
IndexListType m_IndexList;
bool m_ExtractAllImages;
};
} //end namespace itk
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkSplitDWImageFilter.txx"
#endif
#endif // ITKSPLITDWIMAGEFILTER_H
diff --git a/Modules/DiffusionCore/Algorithms/itkSplitDWImageFilter.txx b/Modules/DiffusionCore/Algorithms/itkSplitDWImageFilter.txx
index df0dd61..ba2edca 100644
--- a/Modules/DiffusionCore/Algorithms/itkSplitDWImageFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkSplitDWImageFilter.txx
@@ -1,212 +1,212 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkSplitDWImageFilter_txx
#define __itkSplitDWImageFilter_txx
#include "itkSplitDWImageFilter.h"
#include <itkImageRegionConstIterator.h>
#include <itkImageRegionIterator.h>
template< class TInputImagePixelType,
class TOutputImagePixelType>
itk::SplitDWImageFilter< TInputImagePixelType, TOutputImagePixelType >
::SplitDWImageFilter()
: m_IndexList(0),
m_ExtractAllImages(true)
{
this->SetNumberOfRequiredInputs(1);
}
template< class TInputImagePixelType,
class TOutputImagePixelType>
void itk::SplitDWImageFilter< TInputImagePixelType, TOutputImagePixelType >
::CopyInformation( const DataObject* /*data*/)
{
}
template< class TInputImagePixelType,
class TOutputImagePixelType>
void itk::SplitDWImageFilter<
TInputImagePixelType, TOutputImagePixelType >::GenerateOutputInformation()
{
}
template< class TInputImagePixelType,
class TOutputImagePixelType>
void itk::SplitDWImageFilter< TInputImagePixelType, TOutputImagePixelType >
::SetExtractAllAboveThreshold(double b_threshold, BValueMapType map)
{
m_ExtractAllImages = false;
m_IndexList.clear();
// create the index list following the given threshold
// iterate over the b-value map
BValueMapType::const_iterator bvalueIt = map.begin();
while( bvalueIt != map.end() )
{
// check threshold
if (bvalueIt->first > b_threshold)
{
// the map contains an index container, this needs to be inserted into the
// index list
IndexListType::const_iterator listIt = bvalueIt->second.begin();
while( listIt != bvalueIt->second.end() )
{
m_IndexList.push_back( *listIt );
++listIt;
}
}
++bvalueIt;
}
}
template< class TInputImagePixelType,
class TOutputImagePixelType>
void itk::SplitDWImageFilter< TInputImagePixelType, TOutputImagePixelType >
::SetExtractSingleShell(double b_value, BValueMapType map, double tol)
{
m_ExtractAllImages = false;
m_IndexList.clear();
// create index list
BValueMapType::const_iterator bvalueIt = map.begin();
while( bvalueIt != map.end() )
{
IndexListType::const_iterator listIt = bvalueIt->second.begin();
if( std::fabs( bvalueIt->first - b_value) < tol)
{
m_IndexList.insert( m_IndexList.begin(), bvalueIt->second.begin(), bvalueIt->second.end() );
++listIt;
}
++bvalueIt;
}
}
template< class TInputImagePixelType,
class TOutputImagePixelType>
void itk::SplitDWImageFilter<
TInputImagePixelType, TOutputImagePixelType >::GenerateData()
{
if( m_IndexList.empty() && !m_ExtractAllImages )
{
itkExceptionMacro(<<"The index list is empty and the option to extract all images is disabled. ");
}
// construct the index list (for each component)
if( m_ExtractAllImages )
{
m_IndexList.clear();
for( unsigned int i=0; i< this->GetInput()->GetNumberOfComponentsPerPixel(); i++)
m_IndexList.push_back(i);
}
// declare the output image
// this will have the b0 images stored as timesteps
typename OutputImageType::Pointer outputImage = this->GetOutput();
//OutputImageType::New();
// allocate image with
// - dimension: [DimX, DimY, DimZ, size(IndexList) ]
// - spacing: old one, 1.0 time
typename OutputImageType::SpacingType spacing;
spacing.Fill(1);
typename OutputImageType::PointType origin;
origin.Fill(0);
OutputImageRegionType outputRegion;
// the spacing and origin corresponds to the respective values in the input image (3D)
// the same for the region
for (unsigned int i=0; i< 3; i++)
{
spacing[i] = (this->GetInput()->GetSpacing())[i];
origin[i] = (this->GetInput()->GetOrigin())[i];
outputRegion.SetSize(i, this->GetInput()->GetLargestPossibleRegion().GetSize()[i]);
outputRegion.SetIndex(i, this->GetInput()->GetLargestPossibleRegion().GetIndex()[i]);
}
// number of timesteps = number of b0 images
outputRegion.SetSize(3, m_IndexList.size());
outputRegion.SetIndex( 3, 0 );
// output image direction (4x4)
typename OutputImageType::DirectionType outputDirection;
//initialize to identity
outputDirection.SetIdentity();
// get the input image direction ( 3x3 matrix )
typename InputImageType::DirectionType inputDirection = this->GetInput()->GetDirection();
for( unsigned int i=0; i< 3; i++)
{
outputDirection(0,i) = inputDirection(0,i);
outputDirection(1,i) = inputDirection(1,i);
outputDirection(2,i) = inputDirection(2,i);
}
outputImage->SetSpacing( spacing );
outputImage->SetOrigin( origin );
outputImage->SetDirection( outputDirection );
outputImage->SetRegions( outputRegion );
outputImage->Allocate();
// input iterator
itk::ImageRegionConstIterator<InputImageType> inputIt( this->GetInput(),
this->GetInput()->GetLargestPossibleRegion() );
// we want to iterate separately over each 3D volume of the output image
// so reset the regions last dimension
outputRegion.SetSize(3,1);
unsigned int currentTimeStep = 0;
// for each index in the iterator list, extract the image and insert it as a new time step
for(IndexListType::const_iterator indexIt = m_IndexList.begin();
indexIt != m_IndexList.end();
indexIt++)
{
// set the time step
outputRegion.SetIndex(3, currentTimeStep);
itk::ImageRegionIterator< OutputImageType> outputIt( outputImage.GetPointer(), outputRegion );
// iterate over the current b0 image and store it to corresponding place
outputIt.GoToBegin();
inputIt.GoToBegin();
while( !outputIt.IsAtEnd() && !inputIt.IsAtEnd() )
{
// the input vector
typename InputImageType::PixelType vec = inputIt.Get();
outputIt.Set( vec[*indexIt]);
++outputIt;
++inputIt;
}
// increase time step
currentTimeStep++;
}
}
#endif // __itkSplitDWImageFilter_txx
diff --git a/Modules/DiffusionCore/Algorithms/itkSplitVectorImageFilter.cpp b/Modules/DiffusionCore/Algorithms/itkSplitVectorImageFilter.cpp
index 5b30262..a3a8c20 100644
--- a/Modules/DiffusionCore/Algorithms/itkSplitVectorImageFilter.cpp
+++ b/Modules/DiffusionCore/Algorithms/itkSplitVectorImageFilter.cpp
@@ -1,79 +1,79 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkSplitVectorImageFilter_cpp
#define __itkSplitVectorImageFilter_cpp
#include "itkSplitVectorImageFilter.h"
#include <itkImageRegionConstIterator.h>
#include <itkImageRegionConstIteratorWithIndex.h>
#include <itkImageRegionIterator.h>
#include <vnl/vnl_vector.h>
#include <itkOrientationDistributionFunction.h>
#include <itkContinuousIndex.h>
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkCellArray.h>
#include <vtkPoints.h>
#include <vtkPolyLine.h>
#include <boost/math/special_functions.hpp>
#include <boost/progress.hpp>
using namespace boost::math;
namespace itk {
template< class PixelType >
SplitVectorImageFilter< PixelType>::SplitVectorImageFilter()
{
}
template< class PixelType >
void SplitVectorImageFilter< PixelType>
::GenerateData()
{
m_OutputImages.clear();
for (unsigned int i=0; i<m_InputImage->GetVectorLength(); ++i)
{
typename OutputImageType::Pointer m_OutputImage = OutputImageType::New();
m_OutputImage->SetSpacing( m_InputImage->GetSpacing() );
m_OutputImage->SetOrigin( m_InputImage->GetOrigin() );
m_OutputImage->SetDirection( m_InputImage->GetDirection() );
m_OutputImage->SetRegions( m_InputImage->GetLargestPossibleRegion() );
m_OutputImage->Allocate();
m_OutputImage->FillBuffer(0);
m_OutputImages.push_back(m_OutputImage);
}
ImageRegionIterator< InputImageType > iit(m_InputImage, m_InputImage->GetLargestPossibleRegion() );
while( !iit.IsAtEnd() )
{
auto idx = iit.GetIndex();
typename InputImageType::PixelType pix = iit.Get();
for (unsigned int i=0; i<pix.GetSize(); ++i)
m_OutputImages.at(i)->SetPixel(idx, pix[i]);
++iit;
}
}
}
#endif // __itkSplitVectorImageFilter_cpp
diff --git a/Modules/DiffusionCore/Algorithms/itkSplitVectorImageFilter.h b/Modules/DiffusionCore/Algorithms/itkSplitVectorImageFilter.h
index 2159995..39cccec 100644
--- a/Modules/DiffusionCore/Algorithms/itkSplitVectorImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkSplitVectorImageFilter.h
@@ -1,73 +1,72 @@
-/*=========================================================================
+/*===================================================================
- Program: Insight Segmentation & Registration Toolkit
- Module: $RCSfile: itkDiffusionTensor3DReconstructionImageFilter.h,v $
- Language: C++
- Date: $Date: 2006-03-27 17:01:06 $
- Version: $Revision: 1.12 $
+The Medical Imaging Interaction Toolkit (MITK)
- Copyright (c) Insight Software Consortium. All rights reserved.
- See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
+Copyright (c) German Cancer Research Center.
- This software is distributed WITHOUT ANY WARRANTY; without even
- the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- PURPOSE. See the above copyright notices for more information.
+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 __itkSplitVectorImageFilter_h_
#define __itkSplitVectorImageFilter_h_
#include "itkImageToImageFilter.h"
#include <itkImage.h>
#include <itkVectorImage.h>
namespace itk{
/**
* \brief Flip peaks along specified axes
*/
template< class PixelType >
class SplitVectorImageFilter : public ProcessObject
{
public:
typedef SplitVectorImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ProcessObject Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(SplitVectorImageFilter, ProcessObject)
typedef VectorImage<PixelType, 3> InputImageType;
typedef Image<PixelType, 3> OutputImageType;
typedef typename OutputImageType::RegionType OutputImageRegionType;
itkSetMacro(InputImage, typename InputImageType::Pointer)
std::vector< typename OutputImageType::Pointer > GetOutputImages(){ return m_OutputImages; }
void GenerateData();
protected:
SplitVectorImageFilter();
~SplitVectorImageFilter(){}
typename InputImageType::Pointer m_InputImage;
std::vector< typename OutputImageType::Pointer > m_OutputImages;
private:
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkSplitVectorImageFilter.cpp"
#endif
#endif //__itkSplitVectorImageFilter_h_
diff --git a/Modules/DiffusionCore/Algorithms/itkTensorDerivedMeasurementsFilter.h b/Modules/DiffusionCore/Algorithms/itkTensorDerivedMeasurementsFilter.h
index 83ec04a..d485ba3 100644
--- a/Modules/DiffusionCore/Algorithms/itkTensorDerivedMeasurementsFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkTensorDerivedMeasurementsFilter.h
@@ -1,93 +1,93 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*===================================================================
This file is based heavily on a corresponding ITK filter.
===================================================================*/
#ifndef __itkTensorDerivedMeasurementsFilter_h_
#define __itkTensorDerivedMeasurementsFilter_h_
#include "itkDiffusionTensor3D.h"
#include "itkImageToImageFilter.h"
namespace itk{
/** \class TensorDerivedMeasurementsFilter
*/
template <class TPixel>
class TensorDerivedMeasurementsFilter :
public ImageToImageFilter< itk::Image< itk::DiffusionTensor3D<TPixel>, 3 >,
itk::Image< TPixel, 3 > >
{
public:
enum Measure
{
FA,// Fractional anisotropy
RA,// Relative anisotropy
AD,// Axial diffusivity
RD,// Radial diffusivity
CA, // Clustering anisotropy 1-(λ2+λ3)/(2*λ1)
L2,
L3,
MD // mean diffusivity
};
typedef itk::DiffusionTensor3D<TPixel> TensorType;
typedef itk::Image< TensorType, 3 > TensorImageType;
typedef itk::Image< TPixel, 3 > OutputImageType;
typedef TensorDerivedMeasurementsFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< TensorType,
OutputImageType >
SuperClass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(TensorDerivedMeasurementsFilter, ImageToImageFilter);
itkSetMacro(Measure, Measure);
protected:
TensorDerivedMeasurementsFilter();
~TensorDerivedMeasurementsFilter() {};
//void PrintSelf(std::ostream& os, Indent indent) const;
Measure m_Measure;
void GenerateData() override;
}; // end class
} // end namespace
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkTensorDerivedMeasurementsFilter.txx"
#endif
#endif //__itkTensorDerivedMeasurements_h_
diff --git a/Modules/DiffusionCore/Algorithms/itkTensorDerivedMeasurementsFilter.txx b/Modules/DiffusionCore/Algorithms/itkTensorDerivedMeasurementsFilter.txx
index 207f6cc..8ea02b8 100644
--- a/Modules/DiffusionCore/Algorithms/itkTensorDerivedMeasurementsFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkTensorDerivedMeasurementsFilter.txx
@@ -1,145 +1,145 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkTensorDerivedMeasurementsFilter_txx
#define __itkTensorDerivedMeasurementsFilter_txx
#include <itkImageRegionIterator.h>
namespace itk {
template <class TPixel>
TensorDerivedMeasurementsFilter<TPixel>::TensorDerivedMeasurementsFilter() : m_Measure(AD)
{
}
template <class TPixel>
void TensorDerivedMeasurementsFilter<TPixel>::GenerateData()
{
typename TensorImageType::Pointer tensorImage = static_cast< TensorImageType * >( this->ProcessObject::GetInput(0) );
typedef ImageRegionConstIterator< TensorImageType > TensorImageIteratorType;
typedef ImageRegionIterator< OutputImageType > OutputImageIteratorType;
typename OutputImageType::Pointer outputImage =
static_cast< OutputImageType * >(this->ProcessObject::GetPrimaryOutput());
typename TensorImageType::RegionType region = tensorImage->GetLargestPossibleRegion();
outputImage->SetSpacing( tensorImage->GetSpacing() ); // Set the image spacing
outputImage->SetOrigin( tensorImage->GetOrigin() ); // Set the image origin
outputImage->SetDirection( tensorImage->GetDirection() ); // Set the image direction
outputImage->SetRegions( tensorImage->GetLargestPossibleRegion());
outputImage->Allocate();
TensorImageIteratorType tensorIt(tensorImage, tensorImage->GetLargestPossibleRegion());
OutputImageIteratorType outputIt(outputImage, outputImage->GetLargestPossibleRegion());
tensorIt.GoToBegin();
outputIt.GoToBegin();
while(!tensorIt.IsAtEnd() && !outputIt.IsAtEnd()){
TensorType tensor = tensorIt.Get();
switch(m_Measure)
{
case FA:
{
TPixel diffusionIndex = tensor.GetFractionalAnisotropy();
outputIt.Set(diffusionIndex);
break;
}
case RA:
{
TPixel diffusionIndex = tensor.GetRelativeAnisotropy();
outputIt.Set(diffusionIndex);
break;
}
case AD:
{
// eigenvalues are sorted in ascending order by default because the
// itk::SymmetricEigenAnalysis defaults are not touched in the tensor implementation
typename TensorType::EigenValuesArrayType evs;
tensor.ComputeEigenValues(evs);
outputIt.Set(evs[2]);
break;
}
case RD:
{
// eigenvalues are sorted in ascending order by default because the
// itk::SymmetricEigenAnalysis defaults are not touched in the tensor implementation
typename TensorType::EigenValuesArrayType evs;
tensor.ComputeEigenValues(evs);
outputIt.Set((evs[0]+evs[1])/2.0);
break;
}
case CA:
{
// eigenvalues are sorted in ascending order by default because the
// itk::SymmetricEigenAnalysis defaults are not touched in the tensor implementation
typename TensorType::EigenValuesArrayType evs;
tensor.ComputeEigenValues(evs);
if (evs[2] == 0)
{
outputIt.Set(0);
break;
}
outputIt.Set(1.0-(evs[0]+evs[1])/(2.0*evs[2]));
break;
}
case L2:
{
// eigenvalues are sorted in ascending order by default because the
// itk::SymmetricEigenAnalysis defaults are not touched in the tensor implementation
typename TensorType::EigenValuesArrayType evs;
tensor.ComputeEigenValues(evs);
outputIt.Set(evs[1]);
break;
}
case L3:
{
// eigenvalues are sorted in ascending order by default because the
// itk::SymmetricEigenAnalysis defaults are not touched in the tensor implementation
typename TensorType::EigenValuesArrayType evs;
tensor.ComputeEigenValues(evs);
outputIt.Set(evs[0]);
break;
}
case MD:
{
typename TensorType::EigenValuesArrayType evs;
tensor.ComputeEigenValues(evs);
outputIt.Set((evs[0]+evs[1]+evs[2])/3.0);
break;
}
}
++tensorIt;
++outputIt;
}
}
}
#endif // __itkTensorDerivedMeasurements_txx
diff --git a/Modules/DiffusionCore/Algorithms/itkTensorImageToDiffusionImageFilter.h b/Modules/DiffusionCore/Algorithms/itkTensorImageToDiffusionImageFilter.h
index 7ed8098..0bd32a8 100644
--- a/Modules/DiffusionCore/Algorithms/itkTensorImageToDiffusionImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkTensorImageToDiffusionImageFilter.h
@@ -1,170 +1,170 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*=========================================================================
Program: Tensor ToolKit - TTK
Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkTensorImageToDiffusionImageFilter.h $
Language: C++
Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $
Version: $Revision: 68 $
Copyright (c) INRIA 2010. All rights reserved.
See LICENSE.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef _itk_TensorImageToDiffusionImageFilter_h_
#define _itk_TensorImageToDiffusionImageFilter_h_
#include "itkImageToImageFilter.h"
#include <itkDiffusionTensor3D.h>
#include <itkVectorContainer.h>
namespace itk
{
template <class TInputScalarType, class TOutputScalarType>
class TensorImageToDiffusionImageFilter
: public ImageToImageFilter<itk::Image<itk::DiffusionTensor3D<TInputScalarType>,3>, itk::VectorImage<TOutputScalarType,3> >
{
public:
typedef TInputScalarType InputScalarType;
typedef itk::DiffusionTensor3D<InputScalarType> InputPixelType;
typedef itk::Image<InputPixelType,3> InputImageType;
typedef typename InputImageType::RegionType InputImageRegionType;
typedef TOutputScalarType OutputScalarType;
typedef itk::VectorImage<OutputScalarType,3> OutputImageType;
typedef typename OutputImageType::PixelType OutputPixelType;
typedef typename OutputImageType::RegionType OutputImageRegionType;
typedef OutputScalarType BaselineScalarType;
typedef BaselineScalarType BaselinePixelType;
typedef typename itk::Image<BaselinePixelType,3> BaselineImageType;
typedef typename BaselineImageType::RegionType BaselineImageRegionType;
typedef itk::Image< short, 3> MaskImageType;
typedef MaskImageType::RegionType MaskImageRegionType;
typedef TensorImageToDiffusionImageFilter Self;
typedef ImageToImageFilter<InputImageType, OutputImageType> Superclass;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
itkTypeMacro (TensorImageToDiffusionImageFilter, ImageToImageFilter);
itkStaticConstMacro (ImageDimension, unsigned int,
OutputImageType::ImageDimension);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
typedef vnl_vector_fixed<double,3> GradientType;
typedef VectorContainer<unsigned int, GradientType> GradientListType;
typedef GradientListType::Pointer GradientListPointerType;
/** Manually Set/Get a list of gradients */
void SetGradientList(const GradientListPointerType list)
{
m_GradientList = list;
this->Modified();
}
GradientListPointerType GetGradientList(void) const
{return m_GradientList;}
void SetBValue( const double& bval)
{ m_BValue = bval; }
void SetMaskImage( MaskImageType::Pointer maskimage )
{
m_MaskImage = maskimage;
}
/**
* @brief Set an external baseline image for signal generation (optional)
*
* An option to enforce a specific baseline image. If none provided (default) the filter uses
* the itk::TensorToL2NormImageFilter to generate the modelled baseline image.
*/
void SetExternalBaselineImage( typename BaselineImageType::Pointer bimage)
{
m_BaselineImage = bimage;
}
itkSetMacro(Min, OutputScalarType);
itkSetMacro(Max, OutputScalarType);
protected:
TensorImageToDiffusionImageFilter()
{
m_BValue = 1.0;
m_BaselineImage = 0;
m_Min = 0.0;
m_Max = 10000.0;
}
virtual ~TensorImageToDiffusionImageFilter(){}
void PrintSelf (std::ostream& os, Indent indent) const override
{
Superclass::PrintSelf (os, indent);
}
virtual void BeforeThreadedGenerateData( void ) override;
virtual void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, ThreadIdType) override;
//void GenerateData();
virtual void UpdateOutputInformation() override;
private:
TensorImageToDiffusionImageFilter (const Self&);
void operator=(const Self&);
GradientListType::Pointer m_GradientList;
double m_BValue;
typename BaselineImageType::Pointer m_BaselineImage;
OutputScalarType m_Min;
OutputScalarType m_Max;
MaskImageType::Pointer m_MaskImage;
};
} // end of namespace
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkTensorImageToDiffusionImageFilter.txx"
#endif
#endif
diff --git a/Modules/DiffusionCore/Algorithms/itkTensorImageToDiffusionImageFilter.txx b/Modules/DiffusionCore/Algorithms/itkTensorImageToDiffusionImageFilter.txx
index 42d581d..c24f83f 100644
--- a/Modules/DiffusionCore/Algorithms/itkTensorImageToDiffusionImageFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkTensorImageToDiffusionImageFilter.txx
@@ -1,244 +1,244 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*=========================================================================
2
3 Program: Tensor ToolKit - TTK
4 Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkTensorImageToDiffusionImageFilter.txx $
5 Language: C++
6 Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $
7 Version: $Revision: 68 $
8
9 Copyright (c) INRIA 2010. All rights reserved.
10 See LICENSE.txt for details.
11
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
15
16 =========================================================================*/
#ifndef _itk_TensorImageToDiffusionImageFilter_txx_
#define _itk_TensorImageToDiffusionImageFilter_txx_
#endif
#include "itkTensorImageToDiffusionImageFilter.h"
#include "itkTensorToL2NormImageFilter.h"
#include "itkRescaleIntensityImageFilter.h"
#include <itkImageRegionIterator.h>
#include <itkImageRegionConstIterator.h>
namespace itk
{
template <class TInputScalarType, class TOutputScalarType>
void
TensorImageToDiffusionImageFilter<TInputScalarType, TOutputScalarType>
::BeforeThreadedGenerateData()
{
if( m_GradientList->Size()==0 )
{
throw itk::ExceptionObject (__FILE__,__LINE__,"Error: gradient list is empty, cannot generate DWI.");
}
if( m_BaselineImage.IsNull() )
{
// create a B0 image by taking the norm of the tensor field * scale:
typedef itk::TensorToL2NormImageFilter<InputImageType, itk::Image<InputScalarType,3> >
TensorToL2NormFilterType;
typename TensorToL2NormFilterType::Pointer myFilter1 = TensorToL2NormFilterType::New();
myFilter1->SetInput (this->GetInput());
try
{
myFilter1->Update();
}
catch (itk::ExceptionObject &e)
{
std::cerr << e;
return;
}
typename itk::RescaleIntensityImageFilter< itk::Image<InputScalarType,3>, BaselineImageType>::Pointer rescaler=
itk::RescaleIntensityImageFilter<itk::Image<InputScalarType,3>, BaselineImageType>::New();
rescaler->SetOutputMinimum ( m_Min );
rescaler->SetOutputMaximum ( m_Max );
rescaler->SetInput ( myFilter1->GetOutput() );
try
{
rescaler->Update();
}
catch (itk::ExceptionObject &e)
{
std::cerr << e;
return;
}
m_BaselineImage = rescaler->GetOutput();
}
typename OutputImageType::Pointer outImage = OutputImageType::New();
outImage->SetSpacing( this->GetInput()->GetSpacing() ); // Set the image spacing
outImage->SetOrigin( this->GetInput()->GetOrigin() ); // Set the image origin
outImage->SetDirection( this->GetInput()->GetDirection() ); // Set the image direction
outImage->SetLargestPossibleRegion( this->GetInput()->GetLargestPossibleRegion());
outImage->SetBufferedRegion( this->GetInput()->GetLargestPossibleRegion() );
outImage->SetRequestedRegion( this->GetInput()->GetLargestPossibleRegion() );
outImage->SetVectorLength(m_GradientList->Size());
outImage->Allocate();
this->SetNumberOfRequiredOutputs (1);
this->SetNthOutput (0, outImage);
}
template <class TInputScalarType, class TOutputScalarType>
void TensorImageToDiffusionImageFilter<TInputScalarType, TOutputScalarType>
::ThreadedGenerateData (const OutputImageRegionType &outputRegionForThread, ThreadIdType threadId )
{
typedef ImageRegionIterator<OutputImageType> IteratorOutputType;
typedef ImageRegionConstIterator<InputImageType> IteratorInputType;
typedef ImageRegionConstIterator<BaselineImageType> IteratorBaselineType;
unsigned long numPixels = outputRegionForThread.GetNumberOfPixels();
unsigned long step = numPixels/100;
unsigned long progress = 0;
IteratorOutputType itOut (this->GetOutput(), outputRegionForThread);
IteratorInputType itIn (this->GetInput(), outputRegionForThread);
IteratorBaselineType itB0 (m_BaselineImage, outputRegionForThread);
typedef ImageRegionConstIterator< MaskImageType > IteratorMaskImageType;
IteratorMaskImageType itMask;
if( m_MaskImage.IsNotNull() )
{
itMask = IteratorMaskImageType( m_MaskImage, outputRegionForThread);
itMask.GoToBegin();
}
if( threadId==0 )
{
this->UpdateProgress (0.0);
}
while(!itIn.IsAtEnd())
{
if( this->GetAbortGenerateData() )
{
throw itk::ProcessAborted(__FILE__,__LINE__);
}
InputPixelType T = itIn.Get();
BaselinePixelType b0 = itB0.Get();
OutputPixelType out;
out.SetSize(m_GradientList->Size());
out.Fill(0);
short maskvalue = 1;
if( m_MaskImage.IsNotNull() )
{
maskvalue = itMask.Get();
++itMask;
}
std::vector<unsigned int> b0_indices;
if( b0 > 0)
{
for( unsigned int i=0; i<m_GradientList->Size(); i++)
{
GradientType g = m_GradientList->at(i);
// normalize vector so the following computations work
const double twonorm = g.two_norm();
if( twonorm < vnl_math::eps )
{
b0_indices.push_back(i);
continue;
}
GradientType gn = g.normalize();
InputPixelType S;
S[0] = gn[0]*gn[0];
S[1] = gn[1]*gn[0];
S[2] = gn[2]*gn[0];
S[3] = gn[1]*gn[1];
S[4] = gn[2]*gn[1];
S[5] = gn[2]*gn[2];
const double res =
T[0]*S[0] +
2 * T[1]*S[1] + T[3]*S[3] +
2 * T[2]*S[2] + 2 * T[4]*S[4] + T[5]*S[5];
// check for corrupted tensor
if (res>=0)
{
// estimate the bvalue from the base value and the norm of the gradient
// - because of this estimation the vector have to be normalized beforehand
// otherwise the modelled signal is wrong ( i.e. not scaled properly )
const double bval = m_BValue * twonorm * twonorm;
out[i] = static_cast<OutputScalarType>( maskvalue * 1.0 * b0 * exp ( -1.0 * bval * res ) );
}
}
}
for(unsigned int idx = 0; idx < b0_indices.size(); idx++ )
{
out[b0_indices.at(idx)] = b0;
}
itOut.Set(out);
if( threadId==0 && step>0)
{
if( (progress%step)==0 )
{
this->UpdateProgress ( double(progress)/double(numPixels) );
}
}
++progress;
++itB0;
++itIn;
++itOut;
}
if( threadId==0 )
{
this->UpdateProgress (1.0);
}
}
template <class TInputScalarType, class TOutputScalarType>
void
TensorImageToDiffusionImageFilter<TInputScalarType, TOutputScalarType>
::UpdateOutputInformation()
{
// Calls to superclass updateoutputinformation
Superclass::UpdateOutputInformation();
this->GetOutput()->SetVectorLength( m_GradientList->size() );
}
} // end of namespace
diff --git a/Modules/DiffusionCore/Algorithms/itkTensorImageToOdfImageFilter.h b/Modules/DiffusionCore/Algorithms/itkTensorImageToOdfImageFilter.h
index a5e74e5..f191c86 100644
--- a/Modules/DiffusionCore/Algorithms/itkTensorImageToOdfImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkTensorImageToOdfImageFilter.h
@@ -1,108 +1,108 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*=========================================================================
Program: Tensor ToolKit - TTK
Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkTensorImageToOdfImageFilter.h $
Language: C++
Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $
Version: $Revision: 68 $
Copyright (c) INRIA 2010. All rights reserved.
See LICENSE.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef _itk_TensorImageToOdfImageFilter_h_
#define _itk_TensorImageToOdfImageFilter_h_
#include "itkImageToImageFilter.h"
#include <mitkOdfImage.h>
#include <itkDiffusionTensor3D.h>
namespace itk
{
template <class TInputScalarType, class TOutputScalarType>
class TensorImageToOdfImageFilter
: public ImageToImageFilter<itk::Image<itk::DiffusionTensor3D<TInputScalarType>,3>, itk::Image<itk::Vector<TOutputScalarType,ODF_SAMPLING_SIZE>,3> >
{
public:
typedef TInputScalarType InputScalarType;
typedef itk::DiffusionTensor3D<InputScalarType> InputPixelType;
typedef itk::Image<InputPixelType,3> InputImageType;
typedef typename InputImageType::RegionType InputImageRegionType;
typedef TOutputScalarType OutputScalarType;
typedef itk::Vector<OutputScalarType,ODF_SAMPLING_SIZE> OutputPixelType;
typedef itk::Image<OutputPixelType,3> OutputImageType;
typedef typename OutputImageType::RegionType OutputImageRegionType;
typedef TensorImageToOdfImageFilter Self;
typedef ImageToImageFilter<InputImageType, OutputImageType> Superclass;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
itkTypeMacro (TensorImageToOdfImageFilter, ImageToImageFilter);
itkStaticConstMacro (ImageDimension, unsigned int,
OutputImageType::ImageDimension);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
protected:
TensorImageToOdfImageFilter(){};
~TensorImageToOdfImageFilter() override{};
void PrintSelf (std::ostream& os, Indent indent) const override
{
Superclass::PrintSelf (os, indent);
}
void BeforeThreadedGenerateData( void ) override;
void ThreadedGenerateData( const
OutputImageRegionType &outputRegionForThread, ThreadIdType) override;
//void GenerateData();
private:
TensorImageToOdfImageFilter (const Self&);
void operator=(const Self&);
typename InputImageType::Pointer m_ItkTensorImage;
typename OutputImageType::Pointer m_ItkOdfImage;
};
} // end of namespace
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkTensorImageToOdfImageFilter.txx"
#endif
#endif
diff --git a/Modules/DiffusionCore/Algorithms/itkTensorImageToOdfImageFilter.txx b/Modules/DiffusionCore/Algorithms/itkTensorImageToOdfImageFilter.txx
index 9a9ec40..d9205ac 100644
--- a/Modules/DiffusionCore/Algorithms/itkTensorImageToOdfImageFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkTensorImageToOdfImageFilter.txx
@@ -1,131 +1,131 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*=========================================================================
Program: Tensor ToolKit - TTK
Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkTensorImageToOdfImageFilter.txx $
Language: C++
Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $
Version: $Revision: 68 $
Copyright (c) INRIA 2010. All rights reserved.
See LICENSE.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef _itk_TensorImageToOdfImageFilter_txx_
#define _itk_TensorImageToOdfImageFilter_txx_
#endif
#include "itkTensorImageToOdfImageFilter.h"
#include <itkImageRegionIterator.h>
#include <itkImageRegionConstIterator.h>
#include <itkOrientationDistributionFunction.h>
namespace itk
{
template <class TInputScalarType, class TOutputScalarType>
void
TensorImageToOdfImageFilter<TInputScalarType, TOutputScalarType>
::BeforeThreadedGenerateData()
{
typename OutputImageType::Pointer outImage = OutputImageType::New();
outImage->SetSpacing( this->GetInput()->GetSpacing() ); // Set the image spacing
outImage->SetOrigin( this->GetInput()->GetOrigin() ); // Set the image origin
outImage->SetDirection( this->GetInput()->GetDirection() ); // Set the image direction
outImage->SetLargestPossibleRegion( this->GetInput()->GetLargestPossibleRegion());
outImage->SetBufferedRegion( this->GetInput()->GetLargestPossibleRegion() );
outImage->SetRequestedRegion( this->GetInput()->GetLargestPossibleRegion() );
outImage->Allocate();
outImage->FillBuffer(0.0);
this->SetNumberOfRequiredOutputs (1);
this->SetNthOutput (0, outImage);
}
template <class TInputScalarType, class TOutputScalarType>
void
TensorImageToOdfImageFilter<TInputScalarType, TOutputScalarType>
::ThreadedGenerateData (const OutputImageRegionType &outputRegionForThread, ThreadIdType threadId )
{
typedef ImageRegionIterator<OutputImageType> IteratorOutputType;
typedef ImageRegionConstIterator<InputImageType> IteratorInputType;
unsigned long numPixels = outputRegionForThread.GetNumberOfPixels();
unsigned long step = numPixels/100;
unsigned long progress = 0;
IteratorOutputType itOut (this->GetOutput(), outputRegionForThread);
IteratorInputType itIn (this->GetInput(), outputRegionForThread);
if( threadId==0 )
this->UpdateProgress (0.0);
while(!itIn.IsAtEnd())
{
if( this->GetAbortGenerateData() )
{
throw itk::ProcessAborted(__FILE__,__LINE__);
}
InputPixelType T = itIn.Get();
OutputPixelType out;
float tensorelems[6] = {
(float)T[0],
(float)T[1],
(float)T[2],
(float)T[3],
(float)T[4],
(float)T[5],
};
itk::DiffusionTensor3D<float> tensor(tensorelems);
itk::OrientationDistributionFunction<TOutputScalarType, ODF_SAMPLING_SIZE> odf;
odf.InitFromTensor(tensor);
odf.Normalize();
for( unsigned int i=0; i<ODF_SAMPLING_SIZE; i++)
out[i] = odf.GetElement(i);
itOut.Set(out);
if( threadId==0 && step>0)
{
if( (progress%step)==0 )
{
this->UpdateProgress ( double(progress)/double(numPixels) );
}
}
++progress;
++itIn;
++itOut;
}
if( threadId==0 )
{
this->UpdateProgress (1.0);
}
MITK_INFO << "one thread finished ODF estimation";
}
} // end of namespace
diff --git a/Modules/DiffusionCore/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.h b/Modules/DiffusionCore/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.h
index b0b199c..f6c9ded 100644
--- a/Modules/DiffusionCore/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.h
@@ -1,227 +1,227 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _itk_TensorReconstructionWithEigenvalueCorrectionFilter_h_
#define _itk_TensorReconstructionWithEigenvalueCorrectionFilter_h_
#include "itkImageToImageFilter.h"
#include <itkDiffusionTensor3D.h>
#include <itkVectorImage.h>
#include <vnl/algo/vnl_symmetric_eigensystem.h>
#include <math.h>
namespace itk
{
template <class TDiffusionPixelType, class TTensorPixelType>
class TensorReconstructionWithEigenvalueCorrectionFilter
: public ImageToImageFilter< itk::Image< TDiffusionPixelType, 3 >, itk::Image<itk::DiffusionTensor3D<TTensorPixelType>,3> >
{
public:
typedef itk::VectorImage<short, 3> ImageType;
typedef TensorReconstructionWithEigenvalueCorrectionFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< Image< TDiffusionPixelType, 3>,
Image< DiffusionTensor3D< TTensorPixelType >, 3 > >
Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(TensorReconstructionWithEigenvalueCorrectionFilter, ImageToImageFilter)
typedef typename itk::Image<itk::DiffusionTensor3D<TTensorPixelType>,3> OutputType;
typedef TDiffusionPixelType GradientPixelType;
typedef DiffusionTensor3D< TTensorPixelType > TensorPixelType;
typedef Image< TensorPixelType, 3 > TensorImageType;
typedef typename Superclass::OutputImageRegionType
OutputImageRegionType;
/** An alternative typedef defining one (of the many) gradient images.
* It will be assumed that the vectorImage has the same dimension as the
* Reference image and a vector length parameter of \c n (number of
* gradient directions) */
typedef VectorImage< GradientPixelType, 3 > GradientImagesType;
typedef typename GradientImagesType::PixelType GradientVectorType;
/** Holds each magnetic field gradient used to acquire one DWImage */
typedef vnl_vector_fixed< double, 3 > GradientDirectionType;
/** Container to hold gradient directions of the 'n' DW measurements */
typedef VectorContainer< unsigned int,
GradientDirectionType > GradientDirectionContainerType;
/** Another set method to add a gradient directions and its corresponding
* image. The image here is a VectorImage. The user is expected to pass the
* gradient directions in a container. The ith element of the container
* corresponds to the gradient direction of the ith component image the
* VectorImage. For the baseline image, a vector of all zeros
* should be set. */
void SetGradientImage( GradientDirectionContainerType *,
const GradientImagesType *image);
itkSetMacro( BValue, TTensorPixelType)
/** Set the b0 threshold */
itkSetMacro( B0Threshold, double)
/** Get the pseudeInverse that was calculated in the process of tensor estimation */
itkGetMacro(PseudoInverse, vnl_matrix<double>)
/** FIXME: added by Sebastian Wirkert due to compile error otherwise. */
itkGetMacro(CorrectedDiffusionVolumes, ImageType::Pointer)
/** Outputs the design matrix that was calculated in the process of tensor estimation */
itkGetMacro(H, vnl_matrix<double>)
/** Outputs the normalized b-vector */
itkGetMacro(BVec, vnl_vector<double>)
/** Outputs the mask created by thresholding the B0 weighted volume*/
itkGetMacro(B0Mask, vnl_vector<short>)
/** Returns the dwi image volumes with smoothed voxels on positions were there were negative eigenvalues in the tensir*/
ImageType::Pointer GetGradientImagePointer()
{
return m_GradientImagePointer;
}
/** Get the mask image*/
itk::Image<short, 3>::Pointer GetMask()
{
return m_MaskImage;
}
protected:
TensorReconstructionWithEigenvalueCorrectionFilter();
~TensorReconstructionWithEigenvalueCorrectionFilter() {}
void GenerateData() override;
typedef enum
{
GradientIsInASingleImage = 1,
GradientIsInManyImages,
Else
} GradientImageTypeEnumeration;
private:
double CheckNeighbours(int x, int y, int z,int f, itk::Size<3> size, itk::Image<short, 3> ::Pointer mask,typename GradientImagesType::Pointer corrected_diffusion_temp);
/** Calculates the attenuation for a voxel*/
void CalculateAttenuation(vnl_vector<double> org_data, vnl_vector<double> &atten,int nof,int numberb0);
/** Correct the diffusion data set for voxels that contain negative eigenvalues in the tensor*/
void CorrectDiffusionImage(int nof,int numberb0,itk::Size<3> size,typename GradientImagesType::Pointer corrected_diffusion,itk::Image<short, 3>::Pointer mask,vnl_vector< double> pixel_max,vnl_vector< double> pixel_min);
/** Calculte a tensor iamge from a diffusion data set*/
void GenerateTensorImage(int nof,int numberb0,itk::Size<3> size,itk::VectorImage<short, 3>::Pointer corrected_diffusion,itk::Image<short, 3>::Pointer mask,double what_mask, typename itk::Image< itk::DiffusionTensor3D<TTensorPixelType>, 3 >::Pointer tensorImg );
//void DeepCopyTensorImage(itk::Image< itk::DiffusionTensor3D<double>, 3 >::Pointer tensorImg, itk::Image< itk::DiffusionTensor3D<double>, 3 >::Pointer temp_tensorImg);
//void DeepCopyDiffusionImage(itk::VectorImage<short, 3>::Pointer corrected_diffusion, itk::VectorImage<short, 3>::Pointer corrected_diffusion_temp,int nof);
void TurnMask( itk::Size<3> size, itk::Image<short, 3>::Pointer mask, double previous_mask, double set_mask);
double CheckNegatives ( itk::Size<3> size, itk::Image<short, 3>::Pointer mask, typename itk::Image< itk::DiffusionTensor3D<TTensorPixelType>, 3 >::Pointer tensorImg );
/** Gradient image was specified in a single image or in multiple images */
GradientImageTypeEnumeration m_GradientImageTypeEnumeration;
/** Number of gradient measurements */
unsigned int m_NumberOfGradientDirections;
/** container to hold gradient directions */
GradientDirectionContainerType::Pointer m_GradientDirectionContainer;
/** b-value */
TTensorPixelType m_BValue;
/** Number of baseline images */
unsigned int m_NumberOfBaselineImages;
ImageType::Pointer m_CorrectedDiffusionVolumes;
double m_B0Threshold;
/** decodes what is to be done with every single voxel */
itk::Image<short, 3>::Pointer m_MaskImage;
/** Pseudoinverse calculated in the process of calculating a tensor */
vnl_matrix<double> m_PseudoInverse;
/** design matrix */
vnl_matrix<double> m_H;
/** normalized b-vector */
vnl_vector<double> m_BVec;
/** m_B0Mask indicates whether a volume identified by an index is B0-weighted or not */
vnl_vector<short> m_B0Mask;
/** volumes of the diffusion data set */
typename GradientImagesType::Pointer m_GradientImagePointer;
};
} // end of namespace
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkTensorReconstructionWithEigenvalueCorrectionFilter.txx"
#endif
#endif
diff --git a/Modules/DiffusionCore/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.txx b/Modules/DiffusionCore/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.txx
index f78c247..55ca97c 100644
--- a/Modules/DiffusionCore/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkTensorReconstructionWithEigenvalueCorrectionFilter.txx
@@ -1,863 +1,863 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _itk_TensorReconstructionWithEigenvalueCorrectionFilter_txx_
#define _itk_TensorReconstructionWithEigenvalueCorrectionFilter_txx_
#endif
#include "itkImageRegionConstIterator.h"
#include <math.h>
#include "itkImage.h"
#include "itkImageRegionIterator.h"
#include <itkImageDuplicator.h>
namespace itk
{
template <class TDiffusionPixelType, class TTensorPixelType>
TensorReconstructionWithEigenvalueCorrectionFilter<TDiffusionPixelType, TTensorPixelType>
::TensorReconstructionWithEigenvalueCorrectionFilter()
{
m_B0Threshold = 50.0;
}
template <class TDiffusionPixelType, class TTensorPixelType>
void
TensorReconstructionWithEigenvalueCorrectionFilter<TDiffusionPixelType, TTensorPixelType>
::GenerateData ()
{
typename GradientImagesType::Pointer input_image = static_cast< GradientImagesType * >( this->ProcessObject::GetInput(0) );
typename itk::ImageDuplicator<GradientImagesType>::Pointer duplicator = itk::ImageDuplicator<GradientImagesType>::New();
duplicator->SetInputImage(input_image);
duplicator->Update();
m_GradientImagePointer = duplicator->GetOutput();
typename GradientImagesType::SizeType size = m_GradientImagePointer->GetLargestPossibleRegion().GetSize();
// number of volumes
int nof = m_GradientDirectionContainer->Size();
// determine the number of b-zero values
int numberb0=0;
for(int i=0; i<nof; i++)
{
vnl_vector_fixed <double, 3 > vec = m_GradientDirectionContainer->ElementAt(i);
float bval = vec.magnitude();
bval = bval*bval*m_BValue;
if(bval<100)
numberb0++;
}
// Matrix to store all diffusion encoding gradients
vnl_matrix<double> directions(nof-numberb0,3);
m_B0Mask.set_size(nof);
int cnt=0;
for(int i=0; i<nof; i++)
{
vnl_vector_fixed <double, 3 > vec = m_GradientDirectionContainer->ElementAt(i);
float bval = vec.magnitude();
bval = bval*bval*m_BValue;
if(bval<100)
{
// the diffusion encoding gradient is approximately zero, wo we are dealing with a non-diffusion weighted volume
m_B0Mask[i]=1;
}
else
{
// dealing with a diffusion weighted volume
m_B0Mask[i]=0;
// set the diffusion encoding gradient to the directions matrix
directions[cnt][0] = vec[0];
directions[cnt][1] = vec[1];
directions[cnt][2] = vec[2];
cnt++;
}
}
// looking for maximal norm among gradients.
// The norm is calculated with use of spectral radius theorem- based on determination of eigenvalue.
vnl_matrix<double> dirsTimesDirsTrans = directions*directions.transpose();
vnl_vector< double> diagonal(nof-numberb0);
vnl_vector< double> b_vec(nof-numberb0);
vnl_vector< double> temporary(3);
for (int i=0;i<nof-numberb0;i++)
diagonal[i]=dirsTimesDirsTrans[i][i];
// normalization: free-water method assumes that directions matrix norm 1 is equal to b=1000
directions=directions*sqrt(m_BValue/1000.0);
//calculation of norms and storing them in vector
dirsTimesDirsTrans = directions*directions.transpose();
for (int i=0;i<nof-numberb0;i++)
b_vec[i]= dirsTimesDirsTrans[i][i];
// Calculation of so called design matrix that is used to obtain expected signal.
vnl_matrix<double> H(nof-numberb0, 6);
vnl_matrix<double> H_org(nof-numberb0, 6);
vnl_vector<double> pre_tensor(9);
//H is matrix that contains covariances for directions. It is stored twice because its original value is needed later
// while H is changed
int etbt[6] = { 0, 4, 8, 1, 5, 2 };// tensor order
for (int i = 0; i < nof-numberb0; i++)
{
for (int j = 0; j < 3; j++)
{
temporary[j] = -directions[i][j];
}
for (int j = 0; j < 3; j++)
{
for (int k = 0; k < 3; k++)
{
pre_tensor[k + 3 * j] = temporary[k] * directions[i][j];
}
}
for (int j = 0; j < 6; j++)
{
H[i][j] = pre_tensor[etbt[j]];
}
for (int j = 0; j < 3; j++)
{
H[i][3 + j] *= 2.0;
}
}
H_org=H;
// calculation of inverse matrix by means of pseudoinverse
vnl_matrix<double> inputtopseudoinverse=H.transpose()*H;
vnl_symmetric_eigensystem<double> eig( inputtopseudoinverse);
vnl_matrix<double> pseudoInverse = eig.pinverse()*H.transpose();
typedef itk::Image<short, 3> MaskImageType;
MaskImageType::Pointer mask = MaskImageType::New();
mask->SetRegions(m_GradientImagePointer->GetLargestPossibleRegion().GetSize());
mask->SetSpacing(m_GradientImagePointer->GetSpacing());
mask->SetOrigin(m_GradientImagePointer->GetOrigin());
mask->SetDirection( m_GradientImagePointer->GetDirection() ); // Set the image direction
mask->SetLargestPossibleRegion( m_GradientImagePointer->GetLargestPossibleRegion() );
mask->SetBufferedRegion( m_GradientImagePointer->GetLargestPossibleRegion() );
mask->SetRequestedRegion( m_GradientImagePointer->GetLargestPossibleRegion() );
mask->Allocate();
// Image thresholding: For every voxel mean B0 image is calculated and then voxels of mean B0 less than the
// treshold on the B0 image proviced by the userare excluded from the dataset with use of defined mask image.
// 1 in mask voxel means that B0 > assumed treshold.
int mask_cnt=0;
#ifdef WIN32
#pragma omp parallel for
#else
#pragma omp parallel for collapse(3)
#endif
for(int x=0;x<(int)size[0];x++)
for(int y=0;y<(int)size[1];y++)
for(int z=0;z<(int)size[2];z++)
{
double mean_b=0.0;
itk::Index<3> ix = {{(itk::IndexValueType)x,(itk::IndexValueType)y,(itk::IndexValueType)z}};
GradientVectorType pixel = m_GradientImagePointer->GetPixel(ix);
for (int i=0;i<nof;i++)
{
if(m_B0Mask[i]==1)
{
mean_b = mean_b + pixel[i];
}
}
mean_b=mean_b/numberb0;
if(mean_b > m_B0Threshold)
{
#pragma omp critical
{
mask->SetPixel(ix, 1);
mask_cnt++;
}
}
else
{
#pragma omp critical
mask->SetPixel(ix, 0);
}
}
#ifdef WIN32
#pragma omp parallel for
#else
#pragma omp parallel for collapse(3)
#endif
for (int x=0;x<(int)size[0];x++)
for (int y=0;y<(int)size[1];y++)
for (int z=0;z<(int)size[2];z++)
{
vnl_vector<double> org_vec(nof);
itk::Index<3> ix = {{(itk::IndexValueType)x,(itk::IndexValueType)y,(itk::IndexValueType)z}};
double mask_val = mask->GetPixel(ix);
GradientVectorType pixel2 = m_GradientImagePointer->GetPixel(ix);
for (int i=0;i<nof;i++)
org_vec[i]=pixel2[i];
if(mask_val >0)
{
for( int f=0;f<nof;f++)
if(org_vec[f] <= 0)
org_vec[f] = CheckNeighbours(x,y,z,f,size,mask,m_GradientImagePointer);
for (int i=0;i<nof;i++)
pixel2[i]=org_vec[i];
#pragma omp critical
m_GradientImagePointer->SetPixel(ix, pixel2);
}
}
typename TensorImageType::Pointer tensorImg;
tensorImg = TensorImageType::New();
tensorImg->SetSpacing( m_GradientImagePointer->GetSpacing() ); // Set the image spacing
tensorImg->SetOrigin( m_GradientImagePointer->GetOrigin() ); // Set the image origin
tensorImg->SetDirection( m_GradientImagePointer->GetDirection() ); // Set the image direction
tensorImg->SetLargestPossibleRegion( m_GradientImagePointer->GetLargestPossibleRegion() );
tensorImg->SetBufferedRegion( m_GradientImagePointer->GetLargestPossibleRegion() );
tensorImg->SetRequestedRegion( m_GradientImagePointer->GetLargestPossibleRegion() );
tensorImg->Allocate();
//Declaration of vectors that contains too high or too low atenuation for each gradient. Attenuation is only calculated for
//non B0 images so nof-numberb0.
vnl_vector< double> pixel_max(nof-numberb0);
vnl_vector< double> pixel_min(nof-numberb0);
// to high and to low attenuation is calculated with use of highest allowed =5 and lowest allowed =0.01 diffusion coefficient
for (int i=0;i<nof-numberb0;i++)
{
pixel_max[i]=exp(-b_vec[i]*0.01);
pixel_min[i]= exp(-b_vec[i]*5);
}
m_PseudoInverse = pseudoInverse;
m_H = H_org;
m_BVec=b_vec;
// in preprocessing we are dealing with 3 types of voxels: voxels excluded = 0 in mask, voxels correct =1 and voxels under correction
//= 2. During pre processing most of voxels should be switched from 2 to 1.
// what mask is a variable declared to simplify tensor calculaton. Tensors are obtained only for voxels that have a mask value bigger
// than what_mask. Sometimes it is 1 sometimes 2.
// initialization of required variables
double what_mask=1.0;
double set_mask=2.0;
double previous_mask=0;
int old_number_negative_eigs=0;
int new_number_negative_eigs=0;
bool stil_correcting = true;
TurnMask(size,mask,previous_mask,set_mask);
// simply defining all possible tensors as with negative eigenvalues
//Preprocessing is performed in multiple iterations as long as the next iteration does not increase the number of bad voxels.
//The final DWI should be the one that has a smaller or equal number of bad voxels as in the
//previous iteration. To obtain this temporary DWI image must be stored in memory.
// ! Initial Calculation of Tensors
std::cout << "Initial tensor calculation" << std::endl;
GenerateTensorImage(nof,numberb0,size,m_GradientImagePointer,mask,what_mask,tensorImg);
std::cout << "Check negatives" << std::endl;
// checking how many tensors have problems, this is working only for mask =2
old_number_negative_eigs = CheckNegatives (size,mask,tensorImg);
//info for the user printed in the consol-debug information to be removed in the future
std::cout << "Number of negative eigenvalues: " << old_number_negative_eigs << std::endl;
CorrectDiffusionImage(nof,numberb0,size,m_GradientImagePointer,mask,pixel_max,pixel_min);
while (stil_correcting == true)
{
//info for the user printed in the consol-debug information to be removed in the future
std::cout << "Number of negative eigenvalues: " << old_number_negative_eigs << std::endl;
GenerateTensorImage(nof,numberb0,size,m_GradientImagePointer,mask,what_mask,tensorImg);
new_number_negative_eigs = CheckNegatives (size,mask,tensorImg);
if(new_number_negative_eigs<old_number_negative_eigs)
{
// if the correction does not introduce new negative eigenvalues and corrects some of negative detected n previous iteration
// smoothed DWI is used to substitute DWI from previous iteration
stil_correcting=true;
old_number_negative_eigs=new_number_negative_eigs;
}
else
{
stil_correcting=false;
}
//14.10.2013
//CorrectDiffusionImage(nof,numberb0,size,corrected_diffusion_temp,mask,pixel_max,pixel_min);
CorrectDiffusionImage(nof,numberb0,size,m_GradientImagePointer,mask,pixel_max,pixel_min);
}
// Changing the mask value for voxels that are still not corrcted. Original idea is to take them into analysis even though
// eigenvalues are still negative
TurnMask(size, mask,1,1);
// Generation of final pre-processed tensor image that might be used as an input for FWE method
// Final Tensor Reconstruction
std::cout << "Final tensors " << std::endl;
GenerateTensorImage(nof,numberb0,size,m_GradientImagePointer,mask,what_mask,tensorImg);
m_MaskImage = mask;
// Change diffusivity representation to standard convention
itk::ImageRegionIterator<OutputType> outputIterator(tensorImg, tensorImg->GetLargestPossibleRegion());
outputIterator.GoToBegin();
while(!outputIterator.IsAtEnd())
{
TensorPixelType tens = outputIterator.Get();
tens/= 1000.0;
outputIterator.Set(tens);
++outputIterator;
}
this->SetNthOutput(0, tensorImg);
}
template <class TDiffusionPixelType, class TTensorPixelType>
void
TensorReconstructionWithEigenvalueCorrectionFilter<TDiffusionPixelType, TTensorPixelType>
::SetGradientImage( GradientDirectionContainerType *gradientDirection,
const GradientImagesType *gradientImage )
{
if( m_GradientImageTypeEnumeration == GradientIsInManyImages )
{
itkExceptionMacro( << "Cannot call both methods:"
<< "AddGradientImage and SetGradientImage. Please call only one of them.");
}
this->m_GradientDirectionContainer = gradientDirection;
unsigned int numImages = gradientDirection->Size();
this->m_NumberOfBaselineImages = 0;
this->m_NumberOfGradientDirections = numImages - this->m_NumberOfBaselineImages;
// ensure that the gradient image we received has as many components as
// the number of gradient directions
if( gradientImage->GetVectorLength() != this->m_NumberOfBaselineImages + this->m_NumberOfGradientDirections )
{
itkExceptionMacro( << this->m_NumberOfGradientDirections << " gradients + " << this->m_NumberOfBaselineImages
<< "baselines = " << this->m_NumberOfGradientDirections + this->m_NumberOfBaselineImages
<< " directions specified but image has " << gradientImage->GetVectorLength()
<< " components.");
}
this->ProcessObject::SetNthInput( 0,
const_cast< GradientImagesType* >(gradientImage) );
m_GradientImageTypeEnumeration = GradientIsInASingleImage;
}
template <class TDiffusionPixelType, class TTensorPixelType>
double
TensorReconstructionWithEigenvalueCorrectionFilter<TDiffusionPixelType, TTensorPixelType>
::CheckNeighbours(int x, int y, int z,int f, itk::Size<3> size, itk::Image<short, 3>::Pointer mask, typename GradientImagesType::Pointer corrected_diffusion_temp)
{
// method is used for finding a new value for the voxel with use of its 27 neighborhood. To perform such a smoothing correct voxels are
// counted an arithmetical mean is calculated and stored as a new value for the voxel. If there is no proper neigborhood voxel is turned
// to the value of 0.
// Definition of neighbourhood avoiding crossing the image boundaries
int x_max=size[0]-1;
int y_max=size[1]-1;
int z_max=size[2]-1;
double back_x=std::max(0,x-1);
double back_y=std::max(0,y-1);
double back_z=std::max(0,z-1);
double forth_x=std::min((x+1),x_max);
double forth_y=std::min((y+1),y_max);
double forth_z=std::min((z+1),z_max);
double tempsum=0;
double temp_number=0;
for(int i=back_x; i<=forth_x; i++)
{
for (int j=back_y; j<=forth_y; j++)
{
for (int k=back_z; k<=forth_z; k++)
{
itk::Index<3> ix = {{i,j,k}};
GradientVectorType p = corrected_diffusion_temp->GetPixel(ix);
if (p[f] > 0.0 )// taking only positive values and counting them
{
if(!(i==x && j==y && k== z))
{
tempsum=tempsum+p[f];
temp_number++;
}
}
}
}
}
//getting back to the original position of the voxel
itk::Index<3> ix = {{x,y,z}};
if (temp_number <= 0.0)
{
tempsum=0;
#pragma omp critical
mask->SetPixel(ix,0);
}
else
{
tempsum=tempsum/temp_number;
}
return tempsum;// smoothed value of voxel
}
template <class TDiffusionPixelType, class TTensorPixelType>
void
TensorReconstructionWithEigenvalueCorrectionFilter<TDiffusionPixelType, TTensorPixelType>
::CalculateAttenuation(vnl_vector<double> org_data,vnl_vector<double> &atten,int nof, int numberb0)
{
double mean_b=0.0;
for (int i=0;i<nof;i++)
if(m_B0Mask[i]>0)
mean_b=mean_b+org_data[i];
mean_b=mean_b/numberb0;
int cnt=0;
for (int i=0;i<nof;i++)
if(m_B0Mask[i]==0)
{
//if(org_data[i]<0.001){org_data[i]=0.01;}
atten[cnt]=org_data[i]/mean_b;
cnt++;
}
}
template <class TDiffusionPixelType, class TTensorPixelType>
double
TensorReconstructionWithEigenvalueCorrectionFilter<TDiffusionPixelType, TTensorPixelType>
::CheckNegatives ( itk::Size<3> size, itk::Image<short, 3>::Pointer mask, typename itk::Image< itk::DiffusionTensor3D<TTensorPixelType>, 3 >::Pointer tensorImg )
{
// The method was created to simplif the flow of negative eigenvalue correction process. The method itself just return the number
// of voxels (tensors) with negative eigenvalues. Then if the voxel was previously bad ( mask=2 ) but it is not bad anymore mask is
//changed to 1.
// declaration of important structures and variables
double badvoxels=0;
#ifdef WIN32
#pragma omp parallel for
#else
#pragma omp parallel for collapse(3)
#endif
for (int x=0;x<(int)size[0];x++)
for (int y=0;y<(int)size[1];y++)
for (int z=0;z<(int)size[2];z++)
{
double pixel=0;
itk::Index<3> ix = {{(itk::IndexValueType)x,(itk::IndexValueType)y,(itk::IndexValueType)z}};
pixel = mask->GetPixel(ix);
// but only if previously marked as bad one-negative eigen value
if(pixel > 1)
{
#pragma omp critical
{
itk::DiffusionTensor3D<double>::EigenValuesArrayType eigenvalues;
itk::DiffusionTensor3D<double>::EigenVectorsMatrixType eigenvectors;
itk::DiffusionTensor3D<double> ten = tensorImg->GetPixel(ix);
ten.ComputeEigenAnalysis(eigenvalues, eigenvectors);
//comparison to 0.01 instead of 0 was proposed by O.Pasternak
if( eigenvalues[0]>0.01 && eigenvalues[1]>0.01 && eigenvalues[2]>0.01)
mask->SetPixel(ix,1);
else
badvoxels++;
}
}
}
return badvoxels;
}
template <class TDiffusionPixelType, class TTensorPixelType>
void
TensorReconstructionWithEigenvalueCorrectionFilter<TDiffusionPixelType, TTensorPixelType>
::CorrectDiffusionImage(int nof, int numberb0, itk::Size<3> size, typename GradientImagesType::Pointer corrected_diffusion,itk::Image<short, 3>::Pointer mask,vnl_vector< double> pixel_max,vnl_vector< double> pixel_min)
{
// in this method the voxels that has tensor negative eigenvalues are smoothed. Smoothing is done on DWI image.For the voxel
//detected as bad one, B0 image is smoothed obligatory. All other gradient images are smoothed only when value of attenuation
//is out of declared bounds for too high or too low attenuation.
// declaration of important variables
#ifdef WIN32
#pragma omp parallel for
#else
#pragma omp parallel for collapse(3)
#endif
for (int z=0;z<(int)size[2];z++)
for (int x=0;x<(int)size[0];x++)
for (int y=0;y<(int)size[1];y++)
{
vnl_vector<double> org_data(nof);
vnl_vector<double> atten(nof-numberb0);
double cnt_atten=0;
itk::Index<3> ix = {{(itk::IndexValueType)x, (itk::IndexValueType)y, (itk::IndexValueType)z}};
if(mask->GetPixel(ix) > 1.0)
{
GradientVectorType pt = corrected_diffusion->GetPixel(ix);
for (int i=0;i<nof;i++)
org_data[i]=pt[i];
double mean_b=0.0;
for (int i=0;i<nof;i++)
if(m_B0Mask[i]>0)
{
mean_b=mean_b+org_data[i];
}
mean_b=mean_b/numberb0;
int cnt=0;
for (int i=0;i<nof;i++)
if(m_B0Mask[i]==0)
{
atten[cnt]=org_data[i]/mean_b;
cnt++;
}
cnt_atten=0;
//smoothing certain gradient images that are out of declared constraints
for (int f=0;f<nof;f++)
{
if(m_B0Mask[f]==0)
{
if(atten[cnt_atten]<pixel_min[cnt_atten] || atten[cnt_atten]> pixel_max[cnt_atten])
{
int x_max=size[0]-1;
int y_max=size[1]-1;
int z_max=size[2]-1;
double back_x=std::max(0,(int)x-1);
double back_y=std::max(0,(int)y-1);
double back_z=std::max(0,(int)z-1);
double forth_x=std::min(((int)x+1),x_max);
double forth_y=std::min(((int)y+1),y_max);
double forth_z=std::min(((int)z+1),z_max);
double tempsum=0;
double temp_number=0;
for(int i=back_x; i<=forth_x; i++)
for (int j=back_y; j<=forth_y; j++)
for (int k=back_z; k<=forth_z; k++)
{
itk::Index<3> ix = {{i,j,k}};
GradientVectorType p = corrected_diffusion->GetPixel(ix);
if(p[f] > 0.0 && !(i==x && j==y && k== z))
{
tempsum=tempsum+p[f];
temp_number++;
}
}
//getting back to the original position of the voxel
itk::Index<3> ix = {{(itk::IndexValueType)x,(itk::IndexValueType)y,(itk::IndexValueType)z}};
if (temp_number <= 0.0)
{
tempsum=0;
#pragma omp critical
mask->SetPixel(ix,0);
}
else
tempsum=tempsum/temp_number;
org_data[f] = tempsum;
}
cnt_atten++;
}
//smoothing B0
if(m_B0Mask[f]==1)
{
int x_max=size[0] - 1;
int y_max=size[1] - 1;
int z_max=size[2] - 1;
double back_x=std::max(0,(int)x-1);
double back_y=std::max(0,(int)y-1);
double back_z=std::max(0,(int)z-1);
double forth_x=std::min(((int)x+1),x_max);
double forth_y=std::min(((int)y+1),y_max);
double forth_z=std::min(((int)z+1),z_max);
double tempsum=0;
double temp_number=0;
for(int i=back_x; i<=forth_x; i++)
for (int j=back_y; j<=forth_y; j++)
for (int k=back_z; k<=forth_z; k++)
{
itk::Index<3> ix = {{i,j,k}};
GradientVectorType p = corrected_diffusion->GetPixel(ix);
//double test= p[f];
if (p[f] > 0.0 )// taking only positive values and counting them
{
if(!(i==x && j==y && k== z))
{
tempsum=tempsum+p[f];
temp_number++;
}
}
}
//getting back to the original position of the voxel
itk::Index<3> ix = {{(itk::IndexValueType)x,(itk::IndexValueType)y,(itk::IndexValueType)z}};
if (temp_number <= 0.0)
{
tempsum=0;
#pragma omp critical
mask->SetPixel(ix,0);
}
else
{
tempsum=tempsum/temp_number;
}
org_data[f] = tempsum;
}
}
for (int i=0;i<nof;i++)
{
pt[i]=org_data[i];
}
#pragma omp critical
corrected_diffusion->SetPixel(ix, pt);
}
else
{
GradientVectorType pt = corrected_diffusion->GetPixel(ix);
#pragma omp critical
corrected_diffusion->SetPixel(ix, pt);
}
}
}
template <class TDiffusionPixelType, class TTensorPixelType>
void
TensorReconstructionWithEigenvalueCorrectionFilter<TDiffusionPixelType, TTensorPixelType>
::GenerateTensorImage(int nof,int numberb0,itk::Size<3> size,itk::VectorImage<short, 3>::Pointer corrected_diffusion,itk::Image<short, 3>::Pointer mask,double , typename itk::Image< itk::DiffusionTensor3D<TTensorPixelType>, 3 >::Pointer tensorImg)
{
// in this method the whole tensor image is updated with a tensors for defined voxels ( defined by a value of mask);
#ifdef WIN32
#pragma omp parallel for
#else
#pragma omp parallel for collapse(3)
#endif
for (int x=0;x<(int)size[0];x++)
for (int y=0;y<(int)size[1];y++)
for (int z=0;z<(int)size[2];z++)
{
itk::Index<3> ix;
vnl_vector<double> org_data(nof);
vnl_vector<double> atten(nof-numberb0);
vnl_vector<double> tensor(6);
itk::DiffusionTensor3D<double> ten;
double mask_val=0;
ix[0] = x; ix[1] = y; ix[2] = z;
mask_val= mask->GetPixel(ix);
//Tensors are calculated only for voxels above theshold for B0 image.
if( mask_val > 0.0 )
{
// calculation of attenuation with use of gradient image and and mean B0 image
GradientVectorType pt = corrected_diffusion->GetPixel(ix);
for (int i=0;i<nof;i++)
{
org_data[i]=pt[i];
}
double mean_b=0.0;
for (int i=0;i<nof;i++)
{
if(m_B0Mask[i]>0)
{
mean_b=mean_b+org_data[i];
}
}
mean_b=mean_b/numberb0;
int cnt=0;
for (int i=0;i<nof;i++)
{
if (org_data[i]<= 0)
{
org_data[i]=0.1;
}
if(m_B0Mask[i]==0)
{
atten[cnt]=org_data[i]/mean_b;
cnt++;
}
}
for (int i=0;i<nof-numberb0;i++)
{
atten[i]=log((double)atten[i]);
}
// Calculation of tensor with use of previously calculated inverse of design matrix and attenuation
tensor = m_PseudoInverse*atten;
ten(0,0) = tensor[0];
ten(0,1) = tensor[3];
ten(0,2) = tensor[5];
ten(1,1) = tensor[1];
ten(1,2) = tensor[4];
ten(2,2) = tensor[2];
#pragma omp critical
tensorImg->SetPixel(ix, ten);
}
// for voxels with mask value 0 - tensor is simply 0 ( outside brain value)
else if (mask_val < 1.0)
{
ten(0,0) = 0;
ten(0,1) = 0;
ten(0,2) = 0;
ten(1,1) = 0;
ten(1,2) = 0;
ten(2,2) = 0;
#pragma omp critical
tensorImg->SetPixel(ix, ten);
}
}
}// end of Generate Tensor
template <class TDiffusionPixelType, class TTensorPixelType>
void
TensorReconstructionWithEigenvalueCorrectionFilter<TDiffusionPixelType, TTensorPixelType>
::TurnMask( itk::Size<3> size, itk::Image<short, 3>::Pointer mask, double previous_mask, double set_mask)
{
// The method changes voxels in the mask that poses a certain value with other value.
itk::Index<3> ix;
double temp_mask_value=0;
#ifdef WIN32
#pragma omp parallel for
#else
#pragma omp parallel for collapse(3)
#endif
for(int x=0;x<(int)size[0];x++)
for(int y=0;y<(int)size[1];y++)
for(int z=0;z<(int)size[2];z++)
{
ix[0] = x; ix[1] = y; ix[2] = z;
temp_mask_value=mask->GetPixel(ix);
if(temp_mask_value>previous_mask)
{
#pragma omp critical
mask->SetPixel(ix,set_mask);
}
}
}
} // end of namespace
diff --git a/Modules/DiffusionCore/Algorithms/itkTensorToL2NormImageFilter.h b/Modules/DiffusionCore/Algorithms/itkTensorToL2NormImageFilter.h
index e2b4818..4c5253c 100644
--- a/Modules/DiffusionCore/Algorithms/itkTensorToL2NormImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkTensorToL2NormImageFilter.h
@@ -1,79 +1,79 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _itk_TensorToL2NormImageFilter_h_
#define _itk_TensorToL2NormImageFilter_h_
#include "itkImageToImageFilter.h"
namespace itk
{
template <class TInputImage, class TOutputImage>
class ITK_EXPORT TensorToL2NormImageFilter
: public ImageToImageFilter<TInputImage, TOutputImage>
{
public:
typedef TensorToL2NormImageFilter Self;
typedef ImageToImageFilter<TInputImage, TOutputImage> Superclass;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
itkTypeMacro (TensorToL2NormImageFilter, ImageToImageFilter);
itkStaticConstMacro (ImageDimension, unsigned int,
TOutputImage::ImageDimension);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
typedef TInputImage InputImageType;
typedef typename InputImageType::PixelType InputPixelType;
typedef TOutputImage OutputImageType;
typedef typename OutputImageType::PixelType OutputPixelType;
typedef typename OutputImageType::RegionType OutputImageRegionType;
protected:
TensorToL2NormImageFilter(){};
~TensorToL2NormImageFilter(){};
void PrintSelf (std::ostream& os, Indent indent) const override
{
Superclass::PrintSelf (os, indent);
}
void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, ThreadIdType threadId) override;
private:
TensorToL2NormImageFilter (const Self&);
void operator=(const Self&);
};
} // end of namespace
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkTensorToL2NormImageFilter.txx"
#endif
#endif
diff --git a/Modules/DiffusionCore/Algorithms/itkTensorToL2NormImageFilter.txx b/Modules/DiffusionCore/Algorithms/itkTensorToL2NormImageFilter.txx
index b3499cb..09b1da9 100644
--- a/Modules/DiffusionCore/Algorithms/itkTensorToL2NormImageFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkTensorToL2NormImageFilter.txx
@@ -1,97 +1,97 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*=========================================================================
Program: Tensor ToolKit - TTK
Module: $URL: svn://scm.gforge.inria.fr/svn/ttk/trunk/Algorithms/itkTensorToL2NormImageFilter.txx $
Language: C++
Date: $Date: 2010-06-07 13:39:13 +0200 (Mo, 07 Jun 2010) $
Version: $Revision: 68 $
Copyright (c) INRIA 2010. All rights reserved.
See LICENSE.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef _itk_TensorToL2NormImageFilter_txx_
#define _itk_TensorToL2NormImageFilter_txx_
#endif
#include "itkTensorToL2NormImageFilter.h"
#include <itkImageRegionIterator.h>
#include <itkImageRegionConstIterator.h>
namespace itk
{
template <class TInputImage, class TOutputImage>
void TensorToL2NormImageFilter<TInputImage, TOutputImage>::ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, ThreadIdType threadId )
{
typedef ImageRegionIterator<OutputImageType> IteratorOutputType;
typedef ImageRegionConstIterator<InputImageType> IteratorInputType;
unsigned long numPixels = outputRegionForThread.GetNumberOfPixels();
unsigned long step = numPixels/100;
unsigned long progress = 0;
IteratorOutputType itOut(this->GetOutput(), outputRegionForThread);
IteratorInputType itIn(this->GetInput(), outputRegionForThread);
if( threadId==0 )
this->UpdateProgress (0.0);
while(!itOut.IsAtEnd())
{
if( this->GetAbortGenerateData() )
throw itk::ProcessAborted(__FILE__,__LINE__);
OutputPixelType out = static_cast<OutputPixelType>( 0.0 ); // be careful, overload in MedINRIA
InputPixelType T = itIn.Get();
if ( !(T[0]==0 && T[1]==0 && T[2]==0 && T[3]==0 && T[4]==0 && T[5]==0) )
{
double sum = T[0]*T[0] + T[3]*T[3] + T[5]*T[5]
+ T[1]*T[2]*2.0 + T[2]*T[4]*2.0 + T[1]*T[4]*2.0;
out = static_cast<OutputPixelType>( vcl_sqrt( sum ));
}
if( threadId==0 && step>0)
{
if( (progress%step)==0 )
this->UpdateProgress ( double(progress)/double(numPixels) );
}
itOut.Set (out);
++progress;
++itOut;
++itIn;
}
if( threadId==0 )
this->UpdateProgress (1.0);
}
} // end of namespace
diff --git a/Modules/DiffusionCore/Algorithms/itkTensorToRgbImageFilter.h b/Modules/DiffusionCore/Algorithms/itkTensorToRgbImageFilter.h
index d50bbef..7cb8556 100644
--- a/Modules/DiffusionCore/Algorithms/itkTensorToRgbImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkTensorToRgbImageFilter.h
@@ -1,153 +1,153 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkTensorToRgbImageFilter_h
#define __itkTensorToRgbImageFilter_h
#include "itkUnaryFunctorImageFilter.h"
#include "itkRGBAPixel.h"
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionIterator.h"
namespace itk
{
#define __IMG_DAT_ITEM__CEIL_ZERO_ONE__(val) (val) = \
( (val) < 0 ) ? ( 0 ) : ( ( (val)>1 ) ? ( 1 ) : ( (val) ) );
/** \class TensorToRgbImageFilter
*
*/
template <typename TInputImage,
typename TOutputImage=itk::Image<itk::RGBAPixel<unsigned char>,3> >
class TensorToRgbImageFilter :
public ImageToImageFilter<TInputImage,TOutputImage>
{
public:
/** Standard class typedefs. */
typedef TensorToRgbImageFilter Self;
typedef ImageToImageFilter<TInputImage,TOutputImage>
Superclass;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef typename Superclass::InputImageType InputImageType;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename OutputImageType::PixelType OutputPixelType;
typedef typename TInputImage::PixelType InputPixelType;
typedef typename InputPixelType::ValueType InputValueType;
/** Run-time type information (and related methods). */
itkTypeMacro( TensorToRgbImageFilter, ImageToImageFilter );
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Print internal ivars */
void PrintSelf(std::ostream& os, Indent indent) const override
{ this->Superclass::PrintSelf( os, indent ); }
#ifdef ITK_USE_CONCEPT_CHECKING
/** Begin concept checking */
itkConceptMacro(InputHasNumericTraitsCheck,
(Concept::HasNumericTraits<InputValueType>));
/** End concept checking */
#endif
protected:
TensorToRgbImageFilter() {};
~TensorToRgbImageFilter() override {};
void GenerateData() override
{
typename InputImageType::Pointer tensorImage = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
typename OutputImageType::Pointer outputImage =
static_cast< OutputImageType * >(this->ProcessObject::GetPrimaryOutput());
typename InputImageType::RegionType region = tensorImage->GetLargestPossibleRegion();
outputImage->SetSpacing( tensorImage->GetSpacing() ); // Set the image spacing
outputImage->SetOrigin( tensorImage->GetOrigin() ); // Set the image origin
outputImage->SetDirection( tensorImage->GetDirection() ); // Set the image direction
outputImage->SetRegions( tensorImage->GetLargestPossibleRegion());
outputImage->Allocate();
typedef ImageRegionConstIterator< InputImageType > TensorImageIteratorType;
TensorImageIteratorType tensorIt(tensorImage, tensorImage->GetLargestPossibleRegion());
typedef ImageRegionIterator< OutputImageType > OutputImageIteratorType;
OutputImageIteratorType outputIt(outputImage, outputImage->GetLargestPossibleRegion());
tensorIt.GoToBegin();
outputIt.GoToBegin();
while(!tensorIt.IsAtEnd() && !outputIt.IsAtEnd()){
InputPixelType x = tensorIt.Get();
// eigenvalues are sorted in ascending order by default because the
// itk::SymmetricEigenAnalysis defaults are not touched in the tensor implementation
typename InputPixelType::EigenValuesArrayType eigenvalues;
typename InputPixelType::EigenVectorsMatrixType eigenvectors;
x.ComputeEigenAnalysis(eigenvalues, eigenvectors);
// int index = 2;
// if( (eigenvalues[0] >= eigenvalues[1])
// && (eigenvalues[0] >= eigenvalues[2]) )
// index = 0;
// else if(eigenvalues[1] >= eigenvalues[2])
// index = 1;
const float fa = x.GetFractionalAnisotropy();
float r = fabs(eigenvectors(2/*index*/,0)) * fa;
float g = fabs(eigenvectors(2/*index*/,1)) * fa;
float b = fabs(eigenvectors(2/*index*/,2)) * fa;
// float a = (fa-(m_OpacLevel-m_OpacWindow/2.0f))/m_OpacWindow;
float a = fa;
__IMG_DAT_ITEM__CEIL_ZERO_ONE__(r);
__IMG_DAT_ITEM__CEIL_ZERO_ONE__(g);
__IMG_DAT_ITEM__CEIL_ZERO_ONE__(b);
__IMG_DAT_ITEM__CEIL_ZERO_ONE__(a);
OutputPixelType out;
out.SetRed( r * 255.0f);
out.SetGreen( g * 255.0f);
out.SetBlue( b * 255.0f);
out.SetAlpha( a * 255.0f);
outputIt.Set(out);
++tensorIt;
++outputIt;
}
}
private:
TensorToRgbImageFilter(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
};
} // end namespace itk
#endif
diff --git a/Modules/DiffusionCore/Algorithms/itkVectorImageToFourDImageFilter.cpp b/Modules/DiffusionCore/Algorithms/itkVectorImageToFourDImageFilter.cpp
index 12798b6..2062500 100644
--- a/Modules/DiffusionCore/Algorithms/itkVectorImageToFourDImageFilter.cpp
+++ b/Modules/DiffusionCore/Algorithms/itkVectorImageToFourDImageFilter.cpp
@@ -1,101 +1,101 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkVectorImageToFourDImageFilter_cpp
#define __itkVectorImageToFourDImageFilter_cpp
#include "itkVectorImageToFourDImageFilter.h"
#include <itkImageRegionConstIterator.h>
#include <itkImageRegionConstIteratorWithIndex.h>
#include <itkImageRegionIterator.h>
#include <vnl/vnl_vector.h>
#include <itkOrientationDistributionFunction.h>
#include <itkContinuousIndex.h>
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkCellArray.h>
#include <vtkPoints.h>
#include <vtkPolyLine.h>
#include <boost/math/special_functions.hpp>
#include <boost/progress.hpp>
using namespace boost::math;
namespace itk {
template< class PixelType >
VectorImageToFourDImageFilter< PixelType>::VectorImageToFourDImageFilter()
{
}
template< class PixelType >
void VectorImageToFourDImageFilter< PixelType>
::GenerateData()
{
Vector<float, 4> spacing4;
Point<float, 4> origin4;
Matrix<double, 4, 4> direction4; direction4.SetIdentity();
ImageRegion<4> imageRegion4;
Vector<double, 3> spacing3 = m_InputImage->GetSpacing();
Point<float, 3> origin3 = m_InputImage->GetOrigin();
Matrix<double, 3, 3> direction3 = m_InputImage->GetDirection();
ImageRegion<3> imageRegion3 = m_InputImage->GetLargestPossibleRegion();
spacing4[0] = spacing3[0]; spacing4[1] = spacing3[1]; spacing4[2] = spacing3[2]; spacing4[3] = 1;
origin4[0] = origin3[0]; origin4[1] = origin3[1]; origin4[2] = origin3[2]; origin4[3] = 0;
for (int r=0; r<3; r++)
for (int c=0; c<3; c++)
direction4[r][c] = direction3[r][c];
imageRegion4.SetSize(0, imageRegion3.GetSize()[0]);
imageRegion4.SetSize(1, imageRegion3.GetSize()[1]);
imageRegion4.SetSize(2, imageRegion3.GetSize()[2]);
imageRegion4.SetSize(3, m_InputImage->GetVectorLength());
m_OutputImage = OutputImageType::New();
m_OutputImage->SetSpacing( spacing4 );
m_OutputImage->SetOrigin( origin4 );
m_OutputImage->SetDirection( direction4 );
m_OutputImage->SetRegions( imageRegion4 );
m_OutputImage->Allocate();
m_OutputImage->FillBuffer(0);
ImageRegionIterator< InputImageType > iit(m_InputImage, m_InputImage->GetLargestPossibleRegion() );
while( !iit.IsAtEnd() )
{
auto idx3 = iit.GetIndex();
typename InputImageType::PixelType pix = iit.Get();
for (unsigned int i=0; i<pix.GetSize(); ++i)
{
typename OutputImageType::IndexType idx4;
idx4[0] = idx3[0]; idx4[1] = idx3[1]; idx4[2] = idx3[2]; idx4[3] = i;
m_OutputImage->SetPixel(idx4, pix[i]);
}
++iit;
}
}
}
#endif // __itkVectorImageToFourDImageFilter_cpp
diff --git a/Modules/DiffusionCore/Algorithms/itkVectorImageToFourDImageFilter.h b/Modules/DiffusionCore/Algorithms/itkVectorImageToFourDImageFilter.h
index 88856fa..9e7a10b 100644
--- a/Modules/DiffusionCore/Algorithms/itkVectorImageToFourDImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkVectorImageToFourDImageFilter.h
@@ -1,74 +1,73 @@
-/*=========================================================================
+/*===================================================================
- Program: Insight Segmentation & Registration Toolkit
- Module: $RCSfile: itkDiffusionTensor3DReconstructionImageFilter.h,v $
- Language: C++
- Date: $Date: 2006-03-27 17:01:06 $
- Version: $Revision: 1.12 $
+The Medical Imaging Interaction Toolkit (MITK)
- Copyright (c) Insight Software Consortium. All rights reserved.
- See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
+Copyright (c) German Cancer Research Center.
- This software is distributed WITHOUT ANY WARRANTY; without even
- the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- PURPOSE. See the above copyright notices for more information.
+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 __itkVectorImageToFourDImageFilter_h_
#define __itkVectorImageToFourDImageFilter_h_
#include "itkImageToImageFilter.h"
#include <itkImage.h>
#include <itkVectorImage.h>
namespace itk{
/**
* \brief Flip peaks along specified axes
*/
template< class PixelType >
class VectorImageToFourDImageFilter : public ProcessObject
{
public:
typedef VectorImageToFourDImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ProcessObject Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(VectorImageToFourDImageFilter, ProcessObject)
typedef VectorImage<PixelType, 3> InputImageType;
typedef Image<PixelType, 4> OutputImageType;
typedef typename OutputImageType::RegionType OutputImageRegionType;
itkSetMacro(InputImage, typename InputImageType::Pointer)
itkGetMacro(OutputImage, typename OutputImageType::Pointer)
void GenerateData();
protected:
VectorImageToFourDImageFilter();
~VectorImageToFourDImageFilter(){}
typename InputImageType::Pointer m_InputImage;
typename OutputImageType::Pointer m_OutputImage;
private:
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkVectorImageToFourDImageFilter.cpp"
#endif
#endif //__itkVectorImageToFourDImageFilter_h_
diff --git a/Modules/DiffusionCore/Algorithms/itkVectorImageToImageFilter.h b/Modules/DiffusionCore/Algorithms/itkVectorImageToImageFilter.h
index 583af1c..0d6048d 100644
--- a/Modules/DiffusionCore/Algorithms/itkVectorImageToImageFilter.h
+++ b/Modules/DiffusionCore/Algorithms/itkVectorImageToImageFilter.h
@@ -1,77 +1,77 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*===================================================================
This file is based heavily on a corresponding ITK filter.
===================================================================*/
#ifndef __itkVectorImageToImageFilter_h_
#define __itkVectorImageToImageFilter_h_
#include "itkImageToImageFilter.h"
#include "itkVectorImage.h"
namespace itk{
/** \class VectorImageToImageFilter
* \brief This class extracts an image out of a vectorimage
*
* An image is extracted at a designated index of a vectorimage. If non index is set, it is an index of 0 used.
*/
template< class TPixelType >
class VectorImageToImageFilter :
public ImageToImageFilter< VectorImage < TPixelType, 3 >, Image < TPixelType, 3 > >
{
public:
typedef VectorImageToImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< VectorImage < TPixelType, 3 >, Image < TPixelType, 3 > > Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(VectorImageToImageFilter, ImageToImageFilter)
typedef typename Superclass::InputImageType InputImageType;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename Superclass::OutputImageRegionType OutputImageRegionType;
itkSetMacro( Index, unsigned int)
protected:
VectorImageToImageFilter();
~VectorImageToImageFilter() {}
void PrintSelf(std::ostream& os, Indent indent) const override;
//void BeforeThreadedGenerateData();
virtual void GenerateData() override;
unsigned int m_Index;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkVectorImageToImageFilter.txx"
#endif
#endif //__itkVectorImageToImageFilter_h_
diff --git a/Modules/DiffusionCore/Algorithms/itkVectorImageToImageFilter.txx b/Modules/DiffusionCore/Algorithms/itkVectorImageToImageFilter.txx
index e4c8622..7dc449f 100644
--- a/Modules/DiffusionCore/Algorithms/itkVectorImageToImageFilter.txx
+++ b/Modules/DiffusionCore/Algorithms/itkVectorImageToImageFilter.txx
@@ -1,79 +1,79 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkVectorImageToImageFilter_txx
#define __itkVectorImageToImageFilter_txx
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "itkImageRegionIterator.h"
namespace itk {
template< class TPixelType >
VectorImageToImageFilter< TPixelType >
::VectorImageToImageFilter()
: m_Index(0)
{
this->SetNumberOfRequiredInputs( 1 );
}
template< class TPixelType >
void
VectorImageToImageFilter< TPixelType >
::GenerateData()
{
typename OutputImageType::Pointer outputImage =
static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0));
outputImage->SetSpacing(this->GetInput()->GetSpacing());
outputImage->SetOrigin(this->GetInput()->GetOrigin());
outputImage->SetRegions(this->GetInput()->GetLargestPossibleRegion());
outputImage->Allocate();
ImageRegionIterator< OutputImageType > oit(outputImage, outputImage->GetLargestPossibleRegion());
oit.GoToBegin();
// InputIteratorType;
typename InputImageType::Pointer inputImagePointer = NULL;
inputImagePointer = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
ImageRegionIterator <InputImageType> git( inputImagePointer, inputImagePointer->GetLargestPossibleRegion() );
git.GoToBegin();
while( !git.IsAtEnd() )
{
oit.Set(git.Get()[m_Index]);
++oit;
++git;
}
}
template< class TPixelType >
void VectorImageToImageFilter< TPixelType >::PrintSelf(std::ostream& os, Indent indent) const
{
Superclass::PrintSelf(os,indent);
}
}
#endif // __itkVectorImageToImageFilter_txx
diff --git a/Modules/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisClusteringCalculator.cpp b/Modules/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisClusteringCalculator.cpp
index e09853d..252177e 100644
--- a/Modules/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisClusteringCalculator.cpp
+++ b/Modules/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisClusteringCalculator.cpp
@@ -1,987 +1,987 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPartialVolumeAnalysisClusteringCalculator.h"
#include "mitkImageAccessByItk.h"
#include "mitkImageToItk.h"
#include "itkScalarImageToHistogramGenerator.h"
#include "itkListSample.h"
namespace mitk
{
PartialVolumeAnalysisClusteringCalculator::PartialVolumeAnalysisClusteringCalculator()
: m_MaxIt(100), m_StepsNumIntegration(100)
{
}
PartialVolumeAnalysisClusteringCalculator::~PartialVolumeAnalysisClusteringCalculator()
{
}
PartialVolumeAnalysisClusteringCalculator::ParamsType*
PartialVolumeAnalysisClusteringCalculator::InitialGuess(HistType h) const
{
int s = h.xVals.size();
int s30 = 0.3 * s;
int s70 = 0.7 * s;
auto params = new ParamsType();
params->means[0] = h.xVals(s30);
params->means[1] = h.xVals(s70);
params->sigmas[0] = (h.xVals(s-1) - h.xVals(0)) / 5.0;
params->sigmas[1] = (h.xVals(s-1) - h.xVals(0)) / 5.0;
params->ps[0] = 0.4;
params->ps[1] = 0.4;
return params;
}
PartialVolumeAnalysisClusteringCalculator::ParamsType*
PartialVolumeAnalysisClusteringCalculator::Cluster(HistType h, ParamsType *initialGuess) const
{
auto params = new ParamsType();
params->Initialize(initialGuess);
double ll = 9999999999999999999.9;
double oll;
double sml = (h.xVals[1] - h.xVals[0]) / 1000;
int arraysz = h.xVals.size();
for (unsigned int it = 0; it < m_MaxIt; it++)
{
// wie sehen basisfunktionen zu aktuellen params aus?
ClusterResultType curves = CalculateCurves(*params,h.xVals);
// summe der basisfunktionen
for(int i=0; i<arraysz; i++)
{
if(curves.combiVals(i) == 0)
{
curves.combiVals(i) = 0.00000000000000000001;
}
}
// alte log likelihood
oll = ll;
ll = 0;
// neue likelihood
for(int i=0; i<arraysz; i++)
{
ll -= h.hVals(i) * log(curves.combiVals(i));
}
if( it>2 && oll-ll < arraysz/2*1e-15 )
{
break;
}
for(int j=0; j<2; j++)
{
VecType array, p(arraysz);
array = curves.vals[j];
for(int i=0; i<arraysz; i++)
{
p(i) = h.hVals(i)*array(i)/curves.combiVals(i);
}
params->ps[j] = 0;
params->means[j] = 0;
for(int i=0; i<arraysz; i++)
{
params->ps[j] += p(i);
params->means[j] += h.xVals(i)*p(i);
}
params->means[j] /= params->ps[j];
VecType vr = h.xVals;
for(int i=0; i<arraysz; i++)
{
vr(i) -= params->means[j];
}
params->sigmas[j] = 0;
for(int i=0; i<arraysz; i++)
{
params->sigmas[j] += vr(i)*vr(i)*p(i);
}
params->sigmas[j] /= params->ps[j];
params->sigmas[j] += sml;
}
double p3 = 0;
for(int i=0; i<arraysz; i++)
{
p3 += h.hVals(i)*curves.mixedVals[0](i)/curves.combiVals(i);
}
p3 += 1e-3;
double sum = 0;
for(int j=0; j<2; j++)
{
params->ps[j] = params->ps[j] + 1e-3;
sum += params->ps[j];
}
sum += p3;
for(int j=0; j<2; j++)
{
params->ps[j] = params->ps[j] / sum;
}
p3 /= sum;
}
return params;
}
void PartialVolumeAnalysisClusteringCalculator::Normalize(ParamsType params, ClusterResultType* curves) const
{
double sum1=0, sum2=0, sum3=0;
int arraysz = curves->vals[0].size();
for(int i=0; i<arraysz; i++)
{
sum1 += curves->vals[0](i);
sum2 += curves->vals[1](i);
sum3 += curves->mixedVals[0](i);
}
sum1 /= params.ps[0];
sum2 /= params.ps[1];
sum3 /= 1.0 -params.ps[0] -params.ps[1];
for(int i=0; i<arraysz; i++)
{
curves->vals[0](i) /= sum1;
curves->vals[1](i) /= sum2;
curves->mixedVals[0](i) /= sum3;
}
for(int i=0; i<arraysz; i++)
{
curves->combiVals(i) = curves->mixedVals[0](i) + curves->vals[0](i) + curves->vals[1](i);
}
}
PartialVolumeAnalysisClusteringCalculator::ClusterResultType
PartialVolumeAnalysisClusteringCalculator::CalculateCurves(ParamsType params, VecType xVals) const
{
int arraysz = xVals.size();
ClusterResultType result(arraysz);
for( int j=0; j<2; j++)
{
for(int i=0; i<arraysz; i++)
{
double d = xVals(i)-params.means[j];
double amp = params.ps[j]/sqrt(2*itk::Math::pi*params.sigmas[j]);
result.vals[j](i) = amp*exp(-0.5 * (d*d)/params.sigmas[j]);
}
}
for(int i=0; i<arraysz; i++)
{
result.mixedVals[0](i) = 0;
}
for(double t=0; t<=1; t = t + 1.0/(m_StepsNumIntegration-1.0))
{
for(int i=0; i<arraysz; i++)
{
double d = xVals(i)-(t*params.means[0]+(1-t)*params.means[1]);
double v = t*params.sigmas[0]+(1-t)*params.sigmas[1];
double p = 1.0 - params.ps[0] - params.ps[1];
double amp = (1.0/m_StepsNumIntegration) * p / sqrt(2.0*itk::Math::pi*v);
result.mixedVals[0](i) = result.mixedVals[0](i) + amp*exp(-0.5 * (d*d)/v);
// MITK_INFO << "d=" << d << "v=" <<v << "p=" << p << "amp=" << amp << "result=" << amp*exp(-0.5 * (d*d)/v) << std::endl;
}
// MITK_INFO << "t=" << t << std::endl;
// params.Print();
// result.Print();
}
for(int i=0; i<arraysz; i++)
{
result.combiVals(i) = result.mixedVals[0](i) + result.vals[0](i) + result.vals[1](i);
}
return result;
}
PartialVolumeAnalysisClusteringCalculator::HelperStructPerformRGBClusteringRetval*
PartialVolumeAnalysisClusteringCalculator::PerformRGBClustering(mitk::Image::ConstPointer image, const MitkHistType *histogram) const
{
auto rgbChannels = new HelperStructRGBChannels();
HelperStructPerformClusteringRetval *resultr = PerformClustering(image, histogram, 2);
rgbChannels->r = resultr->clusteredImage;
HelperStructPerformClusteringRetval *resultg = PerformClustering(image, histogram, 0, resultr);
rgbChannels->g = resultg->clusteredImage;
HelperStructPerformClusteringRetval *resultb = PerformClustering(image, histogram, 1, resultr);
rgbChannels->b = resultb->clusteredImage;
mitk::Image::Pointer outImage = mitk::Image::New();
switch(rgbChannels->r->GetDimension())
{
case 2:
InternalGenerateRGB<2>(rgbChannels, outImage);
break;
case 3:
InternalGenerateRGB<3>(rgbChannels, outImage);
break;
case 4:
InternalGenerateRGB<4>(rgbChannels, outImage);
break;
default:
InternalGenerateRGB<3>(rgbChannels, outImage);
}
auto retval
= new HelperStructPerformRGBClusteringRetval();
retval->rgbChannels = rgbChannels;
retval->rgb = outImage;
retval->params = resultr->params;
retval->result = resultr->result;
retval->hist = resultr->hist;
delete resultr;
delete resultg;
return retval;
}
template < unsigned int VImageDimension >
void PartialVolumeAnalysisClusteringCalculator::InternalGenerateRGB( HelperStructRGBChannels *rgbin, mitk::Image::Pointer retval ) const
{
typedef itk::Image< float, VImageDimension > ProbImageType;
typedef itk::Image< typename itk::RGBAPixel<unsigned char>, VImageDimension > RGBImageType;
typedef mitk::ImageToItk<ProbImageType> CastFilterType;
typename CastFilterType::Pointer castFilter = CastFilterType::New();
castFilter->SetInput( rgbin->r );
castFilter->Update();
typename ProbImageType::Pointer r = castFilter->GetOutput();
castFilter = CastFilterType::New();
castFilter->SetInput( rgbin->g );
castFilter->Update();
typename ProbImageType::Pointer g = castFilter->GetOutput();
typename RGBImageType::Pointer rgb = RGBImageType::New();
rgb->SetSpacing( g->GetSpacing() ); // Set the image spacing
rgb->SetOrigin( g->GetOrigin() ); // Set the image origin
rgb->SetDirection( g->GetDirection() ); // Set the image direction
rgb->SetRegions( g->GetLargestPossibleRegion() );
rgb->Allocate();
itk::ImageRegionConstIterator<ProbImageType>
itr(r, r->GetLargestPossibleRegion());
itk::ImageRegionConstIterator<ProbImageType>
itg(g, g->GetLargestPossibleRegion());
itk::ImageRegionIterator<RGBImageType>
itrgb(rgb, rgb->GetLargestPossibleRegion());
itr.GoToBegin();
itg.GoToBegin();
float maxr = 0;
float maxg = 0;
while( !itr.IsAtEnd() )
{
typename ProbImageType::PixelType pr = itr.Get();
typename ProbImageType::PixelType pg = itg.Get();
if(pr > maxr)
{
maxr = pr;
}
if(pg > maxg)
{
maxg = pg;
}
++itr;
++itg;
}
itr.GoToBegin();
itg.GoToBegin();
itrgb.GoToBegin();
while( !itr.IsAtEnd() )
{
typename ProbImageType::PixelType pr = itr.Get();
typename ProbImageType::PixelType pg = itg.Get();
typename RGBImageType::PixelType prgb;
float valr = (pr/maxr)*255.0f;
float valg = (pg/maxg)*255.0f;
float alpha = valr>valg ? valr : valg;
prgb.Set(valr, valg, 0.0f, alpha);
itrgb.Set(prgb);
++itr;
++itg;
++itrgb;
}
retval->InitializeByItk(rgb.GetPointer());
retval->SetVolume(rgb->GetBufferPointer());
}
PartialVolumeAnalysisClusteringCalculator::HelperStructPerformClusteringRetval*
PartialVolumeAnalysisClusteringCalculator::PerformClustering(mitk::Image::ConstPointer image, const MitkHistType *histogram, int classIdent, HelperStructPerformClusteringRetval* precResult) const
{
auto retval =
new HelperStructPerformClusteringRetval();
if(precResult == nullptr)
{
retval->hist = new HistType();
retval->hist->InitByMitkHistogram(histogram);
ParamsType params;
params.Initialize( Cluster(*(retval->hist)) );
ClusterResultType result = CalculateCurves(params,retval->hist->xVals);
Normalize(params, &result);
retval->params = new ParamsType();
retval->params->Initialize(&params);
retval->result = new ClusterResultType(10);
retval->result->Initialize(&result);
}
else
{
retval->params = new ParamsType();
retval->params->Initialize(precResult->params);
retval->result = new ClusterResultType(10);
retval->result->Initialize(precResult->result);
}
VecType totalProbs = retval->result->combiVals;
VecType pvProbs = retval->result->mixedVals[0];
VecType fiberProbs;
VecType nonFiberProbs;
VecType interestingProbs;
double p_fiber;
double p_nonFiber;
double p_interesting;
// if(retval->params->means[0]<retval->params->means[1])
// {
fiberProbs = retval->result->vals[1];
nonFiberProbs = retval->result->vals[0];
p_fiber = retval->params->ps[1];
p_nonFiber = retval->params->ps[0];
// }
// else
// {
// fiberProbs = retval->result->vals[0];
// nonFiberProbs = retval->result->vals[1];
// p_fiber = retval->params->ps[0];
// p_nonFiber = retval->params->ps[1];
// }
switch(classIdent)
{
case 0:
interestingProbs = nonFiberProbs;
p_interesting = p_nonFiber;
break;
case 1:
interestingProbs = pvProbs;
p_interesting = 1 - p_fiber - p_nonFiber;
break;
case 2:
default:
interestingProbs = fiberProbs;
p_interesting = p_fiber;
break;
}
double sum = histogram->GetTotalFrequency();
// initialize two histograms for class and total probabilities
MitkHistType::MeasurementVectorType min(1);
MitkHistType::MeasurementVectorType max(1);
min.Fill(histogram->GetDimensionMins(0)[0]);
max.Fill(histogram->GetDimensionMaxs(0)[histogram->GetDimensionMaxs(0).size()-1]);
MitkHistType::Pointer interestingHist = MitkHistType::New();
interestingHist->SetMeasurementVectorSize(1);
interestingHist->Initialize(histogram->GetSize(),min,max);
MitkHistType::Iterator newIt = interestingHist->Begin();
MitkHistType::Iterator newEnd = interestingHist->End();
MitkHistType::Pointer totalHist = MitkHistType::New();
totalHist->SetMeasurementVectorSize(1);
totalHist->Initialize(histogram->GetSize(),min,max);
MitkHistType::Iterator totalIt = totalHist->Begin();
int i=0;
while (newIt != newEnd)
{
newIt.SetFrequency(interestingProbs(i)*sum);
totalIt.SetFrequency(totalProbs(i)*sum);
++newIt;
++totalIt;
++i;
}
mitk::Image::Pointer outImage1 = mitk::Image::New();
mitk::Image::Pointer outImage2 = mitk::Image::New();
HelperStructClusteringResults clusterResults;
clusterResults.interestingHist = interestingHist;
clusterResults.totalHist = totalHist;
clusterResults.p_interesting = p_interesting;
AccessFixedDimensionByItk_3(
image.GetPointer(),
InternalGenerateProbabilityImage,
3,
clusterResults,
outImage1, outImage2);
retval->clusteredImage = outImage1;
retval->displayImage = outImage2;
return retval;
}
template < typename TPixel, unsigned int VImageDimension >
void PartialVolumeAnalysisClusteringCalculator::InternalGenerateProbabilityImage(
const itk::Image< TPixel, VImageDimension > *image,
const HelperStructClusteringResults clusterResults,
mitk::Image::Pointer outImage1, mitk::Image::Pointer outImage2 ) const
{
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::Image< itk::RGBAPixel<unsigned char>, VImageDimension > DisplayImageType;
typedef itk::Image< float, VImageDimension > ProbImageType;
typename ProbImageType::Pointer probimage = ProbImageType::New();
probimage->SetSpacing( image->GetSpacing() ); // Set the image spacing
probimage->SetOrigin( image->GetOrigin() ); // Set the image origin
probimage->SetDirection( image->GetDirection() ); // Set the image direction
probimage->SetRegions( image->GetLargestPossibleRegion() );
probimage->Allocate();
probimage->FillBuffer(0);
typename DisplayImageType::Pointer displayimage = DisplayImageType::New();
displayimage->SetSpacing( image->GetSpacing() ); // Set the image spacing
displayimage->SetOrigin( image->GetOrigin() ); // Set the image origin
displayimage->SetDirection( image->GetDirection() ); // Set the image direction
displayimage->SetRegions( image->GetLargestPossibleRegion() );
displayimage->Allocate();
typename DisplayImageType::PixelType rgba;
rgba.Set(0.0f, 0.0f, 0.0f, 0.0f);
displayimage->FillBuffer(rgba);
itk::ImageRegionConstIterator<ImageType>
itimage(image, image->GetLargestPossibleRegion());
itk::ImageRegionIterator<ProbImageType>
itprob(probimage, probimage->GetLargestPossibleRegion());
itk::ImageRegionIterator<DisplayImageType>
itdisp(displayimage, displayimage->GetLargestPossibleRegion());
itimage.GoToBegin();
itprob.GoToBegin();
MitkHistType::IndexType index(1);
float maxp = 0;
while( !itimage.IsAtEnd() )
{
if(itimage.Get())
{
MitkHistType::MeasurementVectorType meas(1);
meas.Fill(itimage.Get());
double aposteriori = 0;
bool success = clusterResults.interestingHist->GetIndex(meas, index );
if(success)
{
double aprioriProb = clusterResults.interestingHist->GetFrequency(index);
double intensityProb = clusterResults.totalHist->GetFrequency(index);
double p_interesting = clusterResults.p_interesting;
aposteriori = p_interesting * aprioriProb / intensityProb;
}
else
{
MITK_ERROR << "index not found in histogram";
}
if(aposteriori > 0.0000000000000001)
{
itprob.Set( aposteriori );
maxp = aposteriori > maxp ? aposteriori : maxp;
}
else
{
itprob.Set(0.0f);
}
}
++itimage;
++itprob;
}
itprob.GoToBegin();
itdisp.GoToBegin();
while( !itprob.IsAtEnd() )
{
if(itprob.Get())
{
typename DisplayImageType::PixelType rgba;
rgba.Set(255.0f, 0.0f, 0.0f, 255.0f*(itprob.Get()/maxp));
itdisp.Set( rgba );
}
++itprob;
++itdisp;
}
outImage1->InitializeByItk(probimage.GetPointer());
outImage1->SetVolume(probimage->GetBufferPointer());
outImage2->InitializeByItk(displayimage.GetPointer());
outImage2->SetVolume(displayimage->GetBufferPointer());
}
double* PartialVolumeAnalysisClusteringCalculator::PerformQuantification(
mitk::Image::ConstPointer image, mitk::Image::Pointer clusteredImage, mitk::Image::Pointer mask) const
{
auto retval = new double[2];
AccessFixedDimensionByItk_3(
image.GetPointer(),
InternalQuantify,
3,
clusteredImage.GetPointer(),
retval, mask );
return retval;
}
template < typename TPixel, unsigned int VImageDimension >
void PartialVolumeAnalysisClusteringCalculator::InternalQuantify(
const itk::Image< TPixel, VImageDimension > *image,
mitk::Image::Pointer clusteredImage, double* retval, mitk::Image::Pointer mask ) const
{
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::Image< float, VImageDimension > ProbImageType;
typedef itk::Image< unsigned char, VImageDimension > MaskImageType;
typedef mitk::ImageToItk<ProbImageType> CastFilterType;
typename CastFilterType::Pointer castFilter = CastFilterType::New();
castFilter->SetInput( clusteredImage );
castFilter->Update();
typename ProbImageType::Pointer clusterImage = castFilter->GetOutput();
typename MaskImageType::Pointer itkmask = nullptr;
if(mask.IsNotNull())
{
typedef mitk::ImageToItk<MaskImageType> CastFilterType2;
typename CastFilterType2::Pointer castFilter2 = CastFilterType2::New();
castFilter2->SetInput( mask );
castFilter2->Update();
itkmask = castFilter2->GetOutput();
}
else
{
itkmask = MaskImageType::New();
itkmask->SetSpacing( clusterImage->GetSpacing() ); // Set the image spacing
itkmask->SetOrigin( clusterImage->GetOrigin() ); // Set the image origin
itkmask->SetDirection( clusterImage->GetDirection() ); // Set the image direction
itkmask->SetRegions( clusterImage->GetLargestPossibleRegion() );
itkmask->Allocate();
itkmask->FillBuffer(1);
}
itk::ImageRegionConstIterator<ImageType>
itimage(image, image->GetLargestPossibleRegion());
itk::ImageRegionConstIterator<ProbImageType>
itprob(clusterImage, clusterImage->GetLargestPossibleRegion());
itk::ImageRegionConstIterator<MaskImageType>
itmask(itkmask, itkmask->GetLargestPossibleRegion());
itimage.GoToBegin();
itprob.GoToBegin();
itmask.GoToBegin();
double totalProb = 0;
double measurement = 0;
double error = 0;
while( !itimage.IsAtEnd() && !itprob.IsAtEnd() && !itmask.IsAtEnd() )
{
double valImag = itimage.Get();
double valProb = itprob.Get();
double valMask = itmask.Get();
typename ProbImageType::PixelType prop = valProb * valMask;
totalProb += prop;
measurement += valImag * prop;
error += valImag * valImag * prop;
++itimage;
++itprob;
++itmask;
}
measurement = measurement / totalProb;
error = error / totalProb;
retval[0] = measurement;
retval[1] = sqrt( error - measurement*measurement );
}
mitk::Image::Pointer PartialVolumeAnalysisClusteringCalculator::CaculateAngularErrorImage(
mitk::Image::Pointer comp1, mitk::Image::Pointer comp2, mitk::Image::Pointer probImg) const
{
// cast input images to itk
typedef itk::Image<float, 3> ImageType;
typedef mitk::ImageToItk<ImageType> CastType;
CastType::Pointer caster = CastType::New();
caster->SetInput(comp1);
caster->Update();
ImageType::Pointer comp1Image = caster->GetOutput();
caster = CastType::New();
caster->SetInput(comp2);
caster->Update();
ImageType::Pointer comp2Image = caster->GetOutput();
caster = CastType::New();
caster->SetInput(probImg);
caster->Update();
ImageType::Pointer probImage = caster->GetOutput();
// figure out maximum probability for fiber class
float maxProb = 0;
itk::ImageRegionConstIterator<ImageType>
itprob(probImage, probImage->GetLargestPossibleRegion());
itprob.GoToBegin();
while( !itprob.IsAtEnd() )
{
maxProb = itprob.Get() > maxProb ? itprob.Get() : maxProb;
++itprob;
}
// generate a list sample of angles at positions
// where the fiber-prob is higher than .2*maxprob
typedef float MeasurementType;
const unsigned int MeasurementVectorLength = 2;
typedef itk::Vector< MeasurementType , MeasurementVectorLength >
MeasurementVectorType;
typedef itk::Statistics::ListSample< MeasurementVectorType > ListSampleType;
ListSampleType::Pointer listSample = ListSampleType::New();
listSample->SetMeasurementVectorSize( MeasurementVectorLength );
itk::ImageRegionIterator<ImageType>
it1(comp1Image, comp1Image->GetLargestPossibleRegion());
itk::ImageRegionIterator<ImageType>
it2(comp2Image, comp2Image->GetLargestPossibleRegion());
it1.GoToBegin();
it2.GoToBegin();
itprob.GoToBegin();
while( !itprob.IsAtEnd() )
{
if(itprob.Get() > 0.2 * maxProb)
{
MeasurementVectorType mv;
mv[0] = ( MeasurementType ) it1.Get();
mv[1] = ( MeasurementType ) it2.Get();
listSample->PushBack(mv);
}
++it1;
++it2;
++itprob;
}
// generate a histogram from the list sample
typedef float HistogramMeasurementType;
typedef itk::Statistics::Histogram< HistogramMeasurementType, itk::Statistics::DenseFrequencyContainer2 > HistogramType;
typedef itk::Statistics::SampleToHistogramFilter< ListSampleType, HistogramType > GeneratorType;
GeneratorType::Pointer generator = GeneratorType::New();
GeneratorType::HistogramType::SizeType size(2);
size.Fill(30);
generator->SetHistogramSize( size );
generator->SetInput( listSample );
generator->SetMarginalScale( 10.0 );
generator->Update();
// look for frequency mode in the histogram
GeneratorType::HistogramType::ConstPointer histogram = generator->GetOutput();
GeneratorType::HistogramType::ConstIterator iter = histogram->Begin();
float maxFreq = 0;
MeasurementVectorType maxValue;
maxValue.Fill(0);
while ( iter != histogram->End() )
{
if(iter.GetFrequency() > maxFreq)
{
maxFreq = iter.GetFrequency();
maxValue[0] = iter.GetMeasurementVector()[0];
maxValue[1] = iter.GetMeasurementVector()[1];
}
++iter;
}
// generate return image that contains the angular
// error of the voxels to the histogram max measurement
ImageType::Pointer returnImage = ImageType::New();
returnImage->SetSpacing( comp1Image->GetSpacing() ); // Set the image spacing
returnImage->SetOrigin( comp1Image->GetOrigin() ); // Set the image origin
returnImage->SetDirection( comp1Image->GetDirection() ); // Set the image direction
returnImage->SetRegions( comp1Image->GetLargestPossibleRegion() );
returnImage->Allocate();
itk::ImageRegionConstIterator<ImageType>
cit1(comp1Image, comp1Image->GetLargestPossibleRegion());
itk::ImageRegionConstIterator<ImageType>
cit2(comp2Image, comp2Image->GetLargestPossibleRegion());
itk::ImageRegionIterator<ImageType>
itout(returnImage, returnImage->GetLargestPossibleRegion());
cit1.GoToBegin();
cit2.GoToBegin();
itout.GoToBegin();
vnl_vector<float> v(3);
v[0] = cos( maxValue[0] ) * sin( maxValue[1] );
v[1] = sin( maxValue[0] ) * sin( maxValue[1] );
v[2] = cos( maxValue[1] );
// MITK_INFO << "max vector: " << v;
while( !cit1.IsAtEnd() )
{
vnl_vector<float> v1(3);
v1[0] = cos( cit1.Get() ) * sin( cit2.Get() );
v1[1] = sin( cit1.Get() ) * sin( cit2.Get() );
v1[2] = cos( cit2.Get() );
itout.Set(fabs(angle(v,v1)));
// MITK_INFO << "ang_error " << v1 << ": " << fabs(angle(v,v1));
++cit1;
++cit2;
++itout;
}
mitk::Image::Pointer retval = mitk::Image::New();
retval->InitializeByItk(returnImage.GetPointer());
retval->SetVolume(returnImage->GetBufferPointer());
return retval;
}
PartialVolumeAnalysisClusteringCalculator::HelperStructPerformRGBClusteringRetval*
PartialVolumeAnalysisClusteringCalculator::PerformRGBQuantiles(mitk::Image::ConstPointer image, const MitkHistType *histogram, double p1, double p2) const
{
auto rgbChannels = new HelperStructRGBChannels();
HelperStructPerformClusteringRetval *resultr = PerformQuantiles(image, histogram, p2, 999999999.0 );
rgbChannels->r = resultr->clusteredImage;
HelperStructPerformClusteringRetval *resultg = PerformQuantiles(image, histogram, -999999999.0, p1 );
rgbChannels->g = resultg->clusteredImage;
HelperStructPerformClusteringRetval *resultb = PerformQuantiles(image, histogram, p1, p2 );
rgbChannels->b = resultb->clusteredImage;
mitk::Image::Pointer outImage = mitk::Image::New();
switch(rgbChannels->r->GetDimension())
{
case 2:
InternalGenerateRGB<2>(rgbChannels, outImage);
break;
case 3:
InternalGenerateRGB<3>(rgbChannels, outImage);
break;
case 4:
InternalGenerateRGB<4>(rgbChannels, outImage);
break;
default:
InternalGenerateRGB<3>(rgbChannels, outImage);
}
auto retval
= new HelperStructPerformRGBClusteringRetval();
retval->rgbChannels = rgbChannels;
retval->rgb = outImage;
retval->params = resultr->params;
retval->result = resultr->result;
retval->hist = resultr->hist;
delete resultr;
delete resultg;
return retval;
}
PartialVolumeAnalysisClusteringCalculator::HelperStructPerformClusteringRetval*
PartialVolumeAnalysisClusteringCalculator::PerformQuantiles(mitk::Image::ConstPointer image, const MitkHistType *histogram, double p1, double p2 ) const
{
auto retval =
new HelperStructPerformClusteringRetval();
retval->hist = new HistType();
retval->hist->InitByMitkHistogram(histogram);
auto q = new double[2];
q[0] = histogram->Quantile(0, p1);
q[1] = histogram->Quantile(0, p2);
mitk::Image::Pointer outImage1 = mitk::Image::New();
mitk::Image::Pointer outImage2 = mitk::Image::New();
AccessFixedDimensionByItk_3(
image.GetPointer(),
InternalGenerateQuantileImage,
3, q,
outImage1, outImage2);
retval->clusteredImage = outImage1;
retval->displayImage = outImage2;
delete[] q;
return retval;
}
template < typename TPixel, unsigned int VImageDimension >
void PartialVolumeAnalysisClusteringCalculator::InternalGenerateQuantileImage(
const itk::Image< TPixel, VImageDimension > *image, double* q,
mitk::Image::Pointer outImage1, mitk::Image::Pointer outImage2 ) const
{
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::Image< itk::RGBAPixel<unsigned char>, VImageDimension > DisplayImageType;
typedef itk::Image< float, VImageDimension > ProbImageType;
typename ProbImageType::Pointer probimage = ProbImageType::New();
probimage->SetSpacing( image->GetSpacing() ); // Set the image spacing
probimage->SetOrigin( image->GetOrigin() ); // Set the image origin
probimage->SetDirection( image->GetDirection() ); // Set the image direction
probimage->SetRegions( image->GetLargestPossibleRegion() );
probimage->Allocate();
probimage->FillBuffer(0);
typename DisplayImageType::Pointer displayimage = DisplayImageType::New();
displayimage->SetSpacing( image->GetSpacing() ); // Set the image spacing
displayimage->SetOrigin( image->GetOrigin() ); // Set the image origin
displayimage->SetDirection( image->GetDirection() ); // Set the image direction
displayimage->SetRegions( image->GetLargestPossibleRegion() );
displayimage->Allocate();
typename DisplayImageType::PixelType rgba;
rgba.Set(0.0f, 0.0f, 0.0f, 0.0f);
displayimage->FillBuffer(rgba);
itk::ImageRegionConstIterator<ImageType>
itimage(image, image->GetLargestPossibleRegion());
itk::ImageRegionIterator<ProbImageType>
itprob(probimage, probimage->GetLargestPossibleRegion());
itk::ImageRegionIterator<DisplayImageType>
itdisp(displayimage, displayimage->GetLargestPossibleRegion());
itimage.GoToBegin();
itprob.GoToBegin();
while( !itimage.IsAtEnd() )
{
if(itimage.Get() > q[0] && itimage.Get() < q[1])
{
itprob.Set(1.0f);
}
++itimage;
++itprob;
}
itprob.GoToBegin();
itdisp.GoToBegin();
while( !itprob.IsAtEnd() )
{
if(itprob.Get())
{
typename DisplayImageType::PixelType rgba;
rgba.Set(255.0f, 0.0f, 0.0f, 255.0f);
itdisp.Set( rgba );
}
++itprob;
++itdisp;
}
outImage1->InitializeByItk(probimage.GetPointer());
outImage1->SetVolume(probimage->GetBufferPointer());
outImage2->InitializeByItk(displayimage.GetPointer());
outImage2->SetVolume(displayimage->GetBufferPointer());
}
}
diff --git a/Modules/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisClusteringCalculator.h b/Modules/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisClusteringCalculator.h
index f6d842a..2cf224a 100644
--- a/Modules/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisClusteringCalculator.h
+++ b/Modules/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisClusteringCalculator.h
@@ -1,505 +1,505 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_PartialVolumeAnalysisClusteringCalculator_H
#define _MITK_PartialVolumeAnalysisClusteringCalculator_H
#include <MitkDiffusionCoreExports.h>
#include "mitkCommon.h"
#include "mitkImage.h"
#include <itkObject.h>
#include <itkObjectFactory.h>
#include <itkImage.h>
#include <itkRGBAPixel.h>
#include <vnl/vnl_vector.h>
namespace mitk
{
class MITKDIFFUSIONCORE_EXPORT PartialVolumeAnalysisClusteringCalculator : public itk::Object
{
public:
typedef vnl_vector<double> VecType;
typedef mitk::Image::HistogramType MitkHistType;
class HistType
{
public:
HistType()
{
}
HistType(const HistType& p)
{
this->xVals = p.xVals;
this->hVals = p.hVals;
}
~HistType()
{
}
HistType operator= (const HistType& p)
{
if (this != &p) // protect against invalid self-assignment
{
this->xVals = p.xVals;
this->hVals = p.hVals;
}
return *this;
}
void InitByMitkHistogram(const MitkHistType* histogram)
{
xVals.set_size(histogram->GetSize()[0]);
hVals.set_size(histogram->GetSize()[0]);
double sum = histogram->GetTotalFrequency();
MitkHistType::ConstIterator endIt = histogram->End();
MitkHistType::ConstIterator it = histogram->Begin();
bool firstNonEmptyBinFound = false;
//++it;
int i=0;
while (it != endIt)
{
if(it.GetFrequency() || firstNonEmptyBinFound)
{
firstNonEmptyBinFound = true;
xVals(i) = it.GetMeasurementVector().GetElement(0);
hVals(i) = it.GetFrequency()/sum;
}
++i;
++it;
}
}
void SetXVals(VecType x)
{xVals = x;}
void SetHVals(VecType h)
{hVals = h;}
void SetXVals(std::vector<double> x)
{
int s = x.size();
xVals.set_size(s);
for(int i=0; i<s; i++)
{
xVals(i) = x[i];
}
}
void SetHVals(std::vector<double> h)
{
int s = h.size();
hVals.set_size(s);
for(int i=0; i<s; i++)
{
hVals(i) = h[i];
}
}
std::vector<double>* GetXVals()
{
int s = xVals.size();
std::vector<double>* retval = new std::vector<double>(s);
for(int i=0; i<s; i++)
{
(*retval)[i] = xVals(i);
}
return retval;
}
std::vector<double>* GetHVals()
{
int s = hVals.size();
std::vector<double>* retval = new std::vector<double>(s);
for(int i=0; i<s; i++)
{
(*retval)[i] = hVals(i);
}
return retval;
}
VecType xVals;
VecType hVals;
};
class ClusterResultType
{
public:
// ClusterResultType()
// {
// vals.push_back(VecType());
// vals.push_back(VecType());
// mixedVals.push_back(VecType());
// }
ClusterResultType(int sz)
{
vals.push_back(VecType(sz));
vals.push_back(VecType(sz));
mixedVals.push_back(VecType(sz));
combiVals.set_size(sz);
}
~ClusterResultType()
{
}
// ClusterResultType operator= (const ClusterResultType *p)
// {
// MITK_DEBUG << "AOJHIFAHFOF";
// if (this != &p) // protect against invalid self-assignment
// {
// MITK_DEBUG << "HRRRHRHRR";
// this->vals.clear();
// this->mixedVals.clear();
// int s = p.vals.size();
// for(int i=0; i<s;i++)
// {
// VecType v = p.vals[i];
// this->vals.push_back(v);
// }
// s = p.mixedVals.size();
// for(int i=0; i<s;i++)
// {
// VecType v = p.mixedVals[i];
// this->mixedVals.push_back(v);
// }
// this->combiVals = p.combiVals;
// }
// return *this;
// }
void Initialize (const ClusterResultType *p)
{
if (this != p) // protect against invalid self-assignment
{
this->vals.clear();
this->mixedVals.clear();
int s = p->vals.size();
for(int i=0; i<s;i++)
{
VecType v = p->vals[i];
this->vals.push_back(v);
}
s = p->mixedVals.size();
for(int i=0; i<s;i++)
{
VecType v = p->mixedVals[i];
this->mixedVals.push_back(v);
}
this->combiVals = p->combiVals;
}
}
std::vector<double> GetFiberVals()
{
if(vals.size()==2 && vals[1].data_block())
{
int s = vals[1].size();
std::vector<double> retval(s);
for(int i=0; i<s; i++)
{
retval[i] = vals[1](i);
}
return retval;
}
else
{
MITK_ERROR << "GetFiberVals() struct not initialized!!";
return std::vector<double>(0);
}
}
std::vector<double> GetNonFiberVals()
{
if(vals.size()==2 && vals[0].data_block())
{
int s = vals[0].size();
std::vector<double> retval(s);
for(int i=0; i<s; i++)
{
retval[i] = vals[0](i);
}
return retval;
}
else
{
MITK_ERROR << "GetNonFiberVals() struct not initialized!!";
return std::vector<double>(0);
}
}
std::vector<double> GetMixedVals()
{
if(mixedVals.size()==1 && mixedVals[0].data_block())
{
int s = mixedVals[0].size();
std::vector<double> retval(s);
for(int i=0; i<s; i++)
{
retval[i] = mixedVals[0](i);
}
return retval;
}
else
{
MITK_ERROR << "GetMixedVals() struct not initialized!!";
return std::vector<double>(0);
}
}
std::vector<double> GetCombiVals()
{
if(combiVals.data_block())
{
int s = combiVals.size();
std::vector<double> retval(s);
for(int i=0; i<s; i++)
{
retval[i] = combiVals(i);
}
return retval;
}
else
{
MITK_ERROR << "GetCombiVals() struct not initialized!!";
return std::vector<double>(0);
}
}
// void Print(VecType vec, int nr=10)
// {
// int sz = vec.size();
// int incr = (int)((1.0*sz)/(1.0*nr));
// for(int i=0; i<sz; i = i+incr)
// {
// std::cout << vec(i) << " ";
// }
// std::cout << std::endl;
// }
// void Print(int nr=10)
// {
// MITK_DEBUG << "CURVES" << std::endl;
// MITK_DEBUG << "Fiber Vals: ";
// Print(vals[0],nr);
// MITK_DEBUG << "Non-Fiber Vals: ";
// Print(vals[1],nr);
// MITK_DEBUG << "Mixed Vals: ";
// Print(mixedVals[0],nr);
// MITK_DEBUG << "Combined Vals: ";
// Print(combiVals,nr);
// }
std::vector<VecType> vals;
std::vector<VecType> mixedVals;
VecType combiVals;
};
class ParamsType
{
public:
ParamsType()
{
}
~ParamsType()
{
}
void Initialize(const ParamsType *p)
{
if (this != p) // protect against invalid self-assignment
{
means[0] = p->means[0];
means[1] = p->means[1];
sigmas[0] = p->sigmas[0];
sigmas[1] = p->sigmas[1];
ps[0] = p->ps[0];
ps[1] = p->ps[1];
}
}
// void Print()
// {
// MITK_DEBUG << "PARAMS" << std::endl;
// MITK_DEBUG << "Class 1: " << means[0] << " +- " << sqrt(sigmas[0]) << " (p=" << ps[0] << ")" << std::endl;
// MITK_DEBUG << "Class 2: " << means[1] << " +- " << sqrt(sigmas[1]) << " (p=" << ps[1] << ")" << std::endl;
// MITK_DEBUG << "Partial V: p=" << 1.0-ps[0]-ps[1] << std::endl;
// }
double means[2];
double sigmas[2];
double ps[2];
};
struct HelperStructClusteringResults
{
MitkHistType *interestingHist;
MitkHistType *totalHist;
double p_interesting;
};
struct HelperStructRGBChannels
{
mitk::Image::Pointer r;
mitk::Image::Pointer g;
mitk::Image::Pointer b;
~HelperStructRGBChannels()
{
r = nullptr;
g = nullptr;
b = nullptr;
}
};
struct HelperStructPerformRGBClusteringRetval
{
HelperStructRGBChannels *rgbChannels;
mitk::Image::Pointer rgb;
ParamsType *params;
ClusterResultType *result;
HistType *hist;
HelperStructPerformRGBClusteringRetval() :
rgbChannels(nullptr), params(nullptr), result(nullptr), hist(nullptr)
{
}
~HelperStructPerformRGBClusteringRetval()
{
rgb = nullptr;
delete rgbChannels;
}
};
struct HelperStructPerformClusteringRetval
{
mitk::Image::Pointer clusteredImage;
mitk::Image::Pointer displayImage;
ParamsType *params;
ClusterResultType *result;
HistType *hist;
HelperStructPerformClusteringRetval() :
clusteredImage(nullptr), displayImage(nullptr),
params(nullptr), result(nullptr), hist(nullptr)
{
}
~HelperStructPerformClusteringRetval()
{
clusteredImage = nullptr;
displayImage = nullptr;
}
};
mitkClassMacroItkParent( PartialVolumeAnalysisClusteringCalculator, itk::Object )
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
ParamsType *InitialGuess(HistType h) const;
ParamsType *Cluster(const HistType h, ParamsType* initialGuess) const;
ClusterResultType CalculateCurves(ParamsType params, VecType xVals) const;
void Normalize(ParamsType params, ClusterResultType* curves) const;
HelperStructPerformClusteringRetval* PerformClustering(mitk::Image::ConstPointer image, const MitkHistType *histogram, int classIdent, HelperStructPerformClusteringRetval* precResult = nullptr) const;
HelperStructPerformRGBClusteringRetval* PerformRGBClustering(mitk::Image::ConstPointer image, const MitkHistType *histogram) const;
HelperStructPerformClusteringRetval* PerformQuantiles(mitk::Image::ConstPointer image, const MitkHistType *histogram, double p1, double p2) const;
HelperStructPerformRGBClusteringRetval* PerformRGBQuantiles(mitk::Image::ConstPointer image, const MitkHistType *histogram, double p1, double p2 ) const;
double* PerformQuantification(mitk::Image::ConstPointer image, mitk::Image::Pointer clusteredImage, mitk::Image::Pointer mask = nullptr) const;
mitk::Image::Pointer CaculateAngularErrorImage(
mitk::Image::Pointer comp1, mitk::Image::Pointer comp2, mitk::Image::Pointer probImg) const;
template < unsigned int VImageDimension >
void InternalGenerateRGB( HelperStructRGBChannels *rgb, mitk::Image::Pointer retval ) const;
template < typename TPixel, unsigned int VImageDimension >
void InternalGenerateProbabilityImage(
const itk::Image< TPixel, VImageDimension > *image,
const HelperStructClusteringResults clusterResults,
mitk::Image::Pointer outImage1, mitk::Image::Pointer outImage2 ) const;
template < typename TPixel, unsigned int VImageDimension >
void InternalQuantify(
const itk::Image< TPixel, VImageDimension > *image,
mitk::Image::Pointer clusteredImage, double* retval, mitk::Image::Pointer mask ) const;
template < typename TPixel, unsigned int VImageDimension >
void InternalGenerateQuantileImage(
const itk::Image< TPixel, VImageDimension > *image,
double* q,
mitk::Image::Pointer outImage1, mitk::Image::Pointer outImage2 ) const;
ParamsType* Cluster(const HistType h) const
{return Cluster(h, InitialGuess(h));}
void SetMaxIt(unsigned int it)
{ m_MaxIt = it; }
unsigned int GetMaxIt()
{ return m_MaxIt; }
void SetStepsNumIntegration(unsigned int n)
{ m_StepsNumIntegration = n; }
unsigned int GetStepsNumIntegration()
{ return m_StepsNumIntegration; }
protected:
PartialVolumeAnalysisClusteringCalculator();
~PartialVolumeAnalysisClusteringCalculator() override;
unsigned int m_MaxIt;
unsigned int m_StepsNumIntegration;
};
}
#endif // #define _MITK_PartialVolumeAnalysisClusteringCalculator_H
diff --git a/Modules/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.cpp b/Modules/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.cpp
index 9291da5..f89bfe2 100644
--- a/Modules/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.cpp
+++ b/Modules/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.cpp
@@ -1,1270 +1,1270 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPartialVolumeAnalysisHistogramCalculator.h"
#include "mitkImageAccessByItk.h"
#include "mitkExtractImageFilter.h"
#include <itkScalarImageToHistogramGenerator.h>
#include <itkStatisticsImageFilter.h>
#include <itkLabelStatisticsImageFilter.h>
#include <itkBSplineUpsampleImageFilter.h>
#include <itkBSplineResampleImageFilterBase.h>
#include "itkResampleImageFilter.h"
#include "itkGaussianInterpolateImageFunction.h"
#include <itkCastImageFilter.h>
#include <itkImageFileWriter.h>
#include <itkVTKImageImport.h>
#include <itkVTKImageExport.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkPolyData.h>
#include <vtkLinearExtrusionFilter.h>
#include <vtkPolyDataToImageStencil.h>
#include <vtkImageStencil.h>
#include <vtkImageImport.h>
#include <vtkImageExport.h>
#include <vtkImageData.h>
#include <vtkMetaImageWriter.h>
#include <exception>
#include "itkGaussianInterpolateImageFunction.h"
#include "itkBSplineInterpolateImageFunction.h"
#include "itkNearestNeighborInterpolateImageFunction.h"
#include "itkImageMaskSpatialObject.h"
#include "itkRegionOfInterestImageFilter.h"
#include "itkListSample.h"
#include "mitkAbstractTransformGeometry.h"
#include <iostream>
#include <sstream>
namespace mitk
{
PartialVolumeAnalysisHistogramCalculator::PartialVolumeAnalysisHistogramCalculator()
: m_MaskingMode( MASKING_MODE_NONE ),
m_MaskingModeChanged( false ),
m_NumberOfBins(256),
m_UpsamplingFactor(1),
m_GaussianSigma(0),
m_ForceUpdate(false),
m_PlanarFigureThickness(0)
{
m_EmptyHistogram = HistogramType::New();
m_EmptyHistogram->SetMeasurementVectorSize(1);
HistogramType::SizeType histogramSize(1);
histogramSize.Fill( 256 );
m_EmptyHistogram->Initialize( histogramSize );
m_EmptyStatistics.Reset();
}
PartialVolumeAnalysisHistogramCalculator::~PartialVolumeAnalysisHistogramCalculator()
{
}
void PartialVolumeAnalysisHistogramCalculator::SetImage( const mitk::Image *image )
{
if ( m_Image != image )
{
m_Image = image;
this->Modified();
m_ImageStatisticsTimeStamp.Modified();
m_ImageStatisticsCalculationTriggerBool = true;
}
}
void PartialVolumeAnalysisHistogramCalculator::AddAdditionalResamplingImage( const mitk::Image *image )
{
m_AdditionalResamplingImages.push_back(image);
this->Modified();
m_ImageStatisticsTimeStamp.Modified();
m_ImageStatisticsCalculationTriggerBool = true;
}
void PartialVolumeAnalysisHistogramCalculator::SetModified( )
{
this->Modified();
m_ImageStatisticsTimeStamp.Modified();
m_ImageStatisticsCalculationTriggerBool = true;
m_MaskedImageStatisticsTimeStamp.Modified();
m_MaskedImageStatisticsCalculationTriggerBool = true;
m_PlanarFigureStatisticsTimeStamp.Modified();
m_PlanarFigureStatisticsCalculationTriggerBool = true;
}
void PartialVolumeAnalysisHistogramCalculator::SetImageMask( const mitk::Image *imageMask )
{
if ( m_Image.IsNull() )
{
itkExceptionMacro( << "Image needs to be set first!" );
}
if ( m_Image->GetTimeSteps() != imageMask->GetTimeSteps() )
{
itkExceptionMacro( << "Image and image mask need to have equal number of time steps!" );
}
if ( m_ImageMask != imageMask )
{
m_ImageMask = imageMask;
this->Modified();
m_MaskedImageStatisticsTimeStamp.Modified();
m_MaskedImageStatisticsCalculationTriggerBool = true;
}
}
void PartialVolumeAnalysisHistogramCalculator::SetPlanarFigure( const mitk::PlanarFigure *planarFigure )
{
if ( m_Image.IsNull() )
{
itkExceptionMacro( << "Image needs to be set first!" );
}
if ( m_PlanarFigure != planarFigure )
{
m_PlanarFigure = planarFigure;
this->Modified();
m_PlanarFigureStatisticsTimeStamp.Modified();
m_PlanarFigureStatisticsCalculationTriggerBool = true;
}
}
void PartialVolumeAnalysisHistogramCalculator::SetMaskingMode( unsigned int mode )
{
if ( m_MaskingMode != mode )
{
m_MaskingMode = mode;
m_MaskingModeChanged = true;
this->Modified();
}
}
void PartialVolumeAnalysisHistogramCalculator::SetMaskingModeToNone()
{
if ( m_MaskingMode != MASKING_MODE_NONE )
{
m_MaskingMode = MASKING_MODE_NONE;
m_MaskingModeChanged = true;
this->Modified();
}
}
void PartialVolumeAnalysisHistogramCalculator::SetMaskingModeToImage()
{
if ( m_MaskingMode != MASKING_MODE_IMAGE )
{
m_MaskingMode = MASKING_MODE_IMAGE;
m_MaskingModeChanged = true;
this->Modified();
}
}
void PartialVolumeAnalysisHistogramCalculator::SetMaskingModeToPlanarFigure()
{
if ( m_MaskingMode != MASKING_MODE_PLANARFIGURE )
{
m_MaskingMode = MASKING_MODE_PLANARFIGURE;
m_MaskingModeChanged = true;
this->Modified();
}
}
bool PartialVolumeAnalysisHistogramCalculator::ComputeStatistics()
{
MITK_DEBUG << "ComputeStatistics() start";
if ( m_Image.IsNull() )
{
itkExceptionMacro( << "Image not set!" );
}
if ( m_Image->GetReferenceCount() == 1 )
{
MITK_DEBUG << "No Stats calculated; no one else holds a reference on it";
return false;
}
// If a mask was set but we are the only ones to still hold a reference on
// it, delete it.
if ( m_ImageMask.IsNotNull() && (m_ImageMask->GetReferenceCount() == 1) )
{
m_ImageMask = nullptr;
}
// Check if statistics is already up-to-date
unsigned long imageMTime = m_ImageStatisticsTimeStamp.GetMTime();
unsigned long maskedImageMTime = m_MaskedImageStatisticsTimeStamp.GetMTime();
unsigned long planarFigureMTime = m_PlanarFigureStatisticsTimeStamp.GetMTime();
bool imageStatisticsCalculationTrigger = m_ImageStatisticsCalculationTriggerBool;
bool maskedImageStatisticsCalculationTrigger = m_MaskedImageStatisticsCalculationTriggerBool;
bool planarFigureStatisticsCalculationTrigger = m_PlanarFigureStatisticsCalculationTriggerBool;
if ( /*prevent calculation without mask*/!m_ForceUpdate &&( m_MaskingMode == MASKING_MODE_NONE || (
((m_MaskingMode != MASKING_MODE_NONE) || (imageMTime > m_Image->GetMTime() && !imageStatisticsCalculationTrigger))
&& ((m_MaskingMode != MASKING_MODE_IMAGE) || (m_ImageMask.IsNotNull() && maskedImageMTime > m_ImageMask->GetMTime() && !maskedImageStatisticsCalculationTrigger))
&& ((m_MaskingMode != MASKING_MODE_PLANARFIGURE) || (m_PlanarFigure.IsNotNull() && planarFigureMTime > m_PlanarFigure->GetMTime() && !planarFigureStatisticsCalculationTrigger)) ) ) )
{
MITK_DEBUG << "Returning, statistics already up to date!";
if ( m_MaskingModeChanged )
{
m_MaskingModeChanged = false;
return true;
}
else
{
return false;
}
}
// Reset state changed flag
m_MaskingModeChanged = false;
// Depending on masking mode, extract and/or generate the required image
// and mask data from the user input
this->ExtractImageAndMask( );
Statistics *statistics;
HistogramType::ConstPointer *histogram;
switch ( m_MaskingMode )
{
case MASKING_MODE_NONE:
default:
statistics = &m_ImageStatistics;
histogram = &m_ImageHistogram;
m_ImageStatisticsTimeStamp.Modified();
m_ImageStatisticsCalculationTriggerBool = false;
break;
case MASKING_MODE_IMAGE:
statistics = &m_MaskedImageStatistics;
histogram = &m_MaskedImageHistogram;
m_MaskedImageStatisticsTimeStamp.Modified();
m_MaskedImageStatisticsCalculationTriggerBool = false;
break;
case MASKING_MODE_PLANARFIGURE:
statistics = &m_PlanarFigureStatistics;
histogram = &m_PlanarFigureHistogram;
m_PlanarFigureStatisticsTimeStamp.Modified();
m_PlanarFigureStatisticsCalculationTriggerBool = false;
break;
}
// Calculate statistics and histogram(s)
if ( m_InternalImage->GetDimension() == 3 )
{
if ( m_MaskingMode == MASKING_MODE_NONE )
{
// Reset state changed flag
AccessFixedDimensionByItk_2(
m_InternalImage,
InternalCalculateStatisticsUnmasked,
3,
*statistics,
histogram );
}
else
{
AccessFixedDimensionByItk_3(
m_InternalImage,
InternalCalculateStatisticsMasked,
3,
m_InternalImageMask3D.GetPointer(),
*statistics,
histogram );
}
}
else if ( m_InternalImage->GetDimension() == 2 )
{
if ( m_MaskingMode == MASKING_MODE_NONE )
{
AccessFixedDimensionByItk_2(
m_InternalImage,
InternalCalculateStatisticsUnmasked,
2,
*statistics,
histogram );
}
else
{
AccessFixedDimensionByItk_3(
m_InternalImage,
InternalCalculateStatisticsMasked,
2,
m_InternalImageMask2D.GetPointer(),
*statistics,
histogram );
}
}
else
{
MITK_ERROR << "ImageStatistics: Image dimension not supported!";
}
// Release unused image smart pointers to free memory
// m_InternalImage = mitk::Image::Pointer();
m_InternalImageMask3D = MaskImage3DType::Pointer();
m_InternalImageMask2D = MaskImage2DType::Pointer();
return true;
}
const PartialVolumeAnalysisHistogramCalculator::HistogramType *
PartialVolumeAnalysisHistogramCalculator::GetHistogram( ) const
{
if ( m_Image.IsNull() )
{
return nullptr;
}
switch ( m_MaskingMode )
{
case MASKING_MODE_NONE:
default:
return m_ImageHistogram;
case MASKING_MODE_IMAGE:
return m_MaskedImageHistogram;
case MASKING_MODE_PLANARFIGURE:
return m_PlanarFigureHistogram;
}
}
const PartialVolumeAnalysisHistogramCalculator::Statistics &
PartialVolumeAnalysisHistogramCalculator::GetStatistics( ) const
{
if ( m_Image.IsNull() )
{
return m_EmptyStatistics;
}
switch ( m_MaskingMode )
{
case MASKING_MODE_NONE:
default:
return m_ImageStatistics;
case MASKING_MODE_IMAGE:
return m_MaskedImageStatistics;
case MASKING_MODE_PLANARFIGURE:
return m_PlanarFigureStatistics;
}
}
void PartialVolumeAnalysisHistogramCalculator::ExtractImageAndMask( )
{
MITK_DEBUG << "ExtractImageAndMask( ) start";
if ( m_Image.IsNull() )
{
throw std::runtime_error( "Error: image empty!" );
}
mitk::Image *timeSliceImage = const_cast<mitk::Image*>(m_Image.GetPointer());//imageTimeSelector->GetOutput();
switch ( m_MaskingMode )
{
case MASKING_MODE_NONE:
{
m_InternalImage = timeSliceImage;
int s = m_AdditionalResamplingImages.size();
m_InternalAdditionalResamplingImages.resize(s);
for(int i=0; i<s; i++)
{
m_InternalAdditionalResamplingImages[i] = const_cast<mitk::Image*>(m_AdditionalResamplingImages[i].GetPointer());
}
m_InternalImageMask2D = nullptr;
m_InternalImageMask3D = nullptr;
break;
}
case MASKING_MODE_IMAGE:
{
if ( m_ImageMask.IsNotNull() && (m_ImageMask->GetReferenceCount() > 1) )
{
ImageTimeSelector::Pointer maskedImageTimeSelector = ImageTimeSelector::New();
maskedImageTimeSelector->SetInput( m_ImageMask );
maskedImageTimeSelector->SetTimeNr( 0 );
maskedImageTimeSelector->UpdateLargestPossibleRegion();
mitk::Image *timeSliceMaskedImage = maskedImageTimeSelector->GetOutput();
InternalMaskImage(timeSliceMaskedImage);
if(m_UpsamplingFactor != 1)
{
InternalResampleImage(m_InternalImageMask3D);
}
AccessFixedDimensionByItk_1(
timeSliceImage,
InternalResampleImageFromMask, 3, -1 );
int s = m_AdditionalResamplingImages.size();
m_InternalAdditionalResamplingImages.resize(s);
for(int i=0; i<s; i++)
{
AccessFixedDimensionByItk_1(
m_AdditionalResamplingImages[i],
InternalResampleImageFromMask, 3, i );
}
}
else
{
throw std::runtime_error( "Error: image mask empty!" );
}
break;
}
case MASKING_MODE_PLANARFIGURE:
{
m_InternalImageMask2D = nullptr;
if ( m_PlanarFigure.IsNull() )
{
throw std::runtime_error( "Error: planar figure empty!" );
}
if ( !m_PlanarFigure->IsClosed() )
{
throw std::runtime_error( "Masking not possible for non-closed figures" );
}
const BaseGeometry *imageGeometry = timeSliceImage->GetUpdatedGeometry();
if ( imageGeometry == nullptr )
{
throw std::runtime_error( "Image geometry invalid!" );
}
const PlaneGeometry *planarFigureGeometry2D = m_PlanarFigure->GetPlaneGeometry();
if ( planarFigureGeometry2D == nullptr )
{
throw std::runtime_error( "Planar-Figure not yet initialized!" );
}
const PlaneGeometry *planarFigureGeometry =
dynamic_cast< const PlaneGeometry * >( planarFigureGeometry2D );
const AbstractTransformGeometry *abstrTransfGeometry =
dynamic_cast< const AbstractTransformGeometry * >( planarFigureGeometry2D );
if ( !planarFigureGeometry || abstrTransfGeometry )
{
throw std::runtime_error( "Only PlaneGeometry supported." );
}
// unsigned int axis = 2;
// unsigned int slice = 0;
AccessFixedDimensionByItk_3(
timeSliceImage,
InternalReorientImagePlane, 3,
timeSliceImage->GetGeometry(),
m_PlanarFigure->GetGeometry(), -1 );
AccessFixedDimensionByItk_1(
m_InternalImage,
InternalCalculateMaskFromPlanarFigure,
3, 2 );
int s = m_AdditionalResamplingImages.size();
for(int i=0; i<s; i++)
{
AccessFixedDimensionByItk_3(
m_AdditionalResamplingImages[i],
InternalReorientImagePlane, 3,
timeSliceImage->GetGeometry(),
m_PlanarFigure->GetGeometry(), i );
AccessFixedDimensionByItk_1(
m_InternalAdditionalResamplingImages[i],
InternalCropAdditionalImage, 3, i );
}
}
}
}
bool PartialVolumeAnalysisHistogramCalculator::GetPrincipalAxis(
const Geometry3D *geometry, Vector3D vector,
unsigned int &axis )
{
vector.Normalize();
for ( unsigned int i = 0; i < 3; ++i )
{
Vector3D axisVector = geometry->GetAxisVector( i );
axisVector.Normalize();
if ( fabs( fabs( axisVector * vector ) - 1.0) < mitk::eps )
{
axis = i;
return true;
}
}
return false;
}
void PartialVolumeAnalysisHistogramCalculator::InternalMaskImage(
mitk::Image *image )
{
typedef itk::ImageMaskSpatialObject<3> ImageMaskSpatialObject;
typedef itk::Image< unsigned char, 3 > ImageType;
typedef mitk::ImageToItk<ImageType> CastType;
CastType::Pointer caster = CastType::New();
caster->SetInput(image);
caster->Update();
ImageMaskSpatialObject::Pointer maskSO = ImageMaskSpatialObject::New();
maskSO->SetImage ( caster->GetOutput() );
m_InternalMask3D =
maskSO->GetAxisAlignedBoundingBoxRegion();
// check if bounding box is empty, if so set it to 1,1,1
// to prevent empty mask image
if (m_InternalMask3D.GetSize()[0] == 0 )
{
m_InternalMask3D.SetSize(0,1);
m_InternalMask3D.SetSize(1,1);
m_InternalMask3D.SetSize(2,1);
}
MITK_DEBUG << "Bounding Box Region: " << m_InternalMask3D;
// crop the mask image to the BoundingBoxRegion extracted via the spatial masking object
typedef itk::RegionOfInterestImageFilter< ImageType, MaskImage3DType > ROIFilterType;
ROIFilterType::Pointer roi = ROIFilterType::New();
roi->SetRegionOfInterest(m_InternalMask3D);
roi->SetInput(caster->GetOutput());
roi->Update();
m_InternalImageMask3D = roi->GetOutput();
MITK_DEBUG << "Created m_InternalImageMask3D";
}
template < typename TPixel, unsigned int VImageDimension >
void PartialVolumeAnalysisHistogramCalculator::InternalReorientImagePlane(
const itk::Image< TPixel, VImageDimension > *image,
mitk::BaseGeometry* , mitk::BaseGeometry* planegeo3D, int additionalIndex )
{
MITK_DEBUG << "InternalReorientImagePlane() start";
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::Image< float, VImageDimension > FloatImageType;
typedef itk::ResampleImageFilter<ImageType, FloatImageType, double> ResamplerType;
typename ResamplerType::Pointer resampler = ResamplerType::New();
mitk::PlaneGeometry* planegeo = dynamic_cast<mitk::PlaneGeometry*>(planegeo3D);
if ( !planegeo )
{
throw std::runtime_error( "Unexpected null pointer returned for pointer to PlaneGeometry." );
}
else
{
mitk::AbstractTransformGeometry* abstrGeo = dynamic_cast<mitk::AbstractTransformGeometry*>(planegeo3D);
if ( abstrGeo )
{
throw std::runtime_error( "Unexpected pointer to AbstractTransformGeometry returned." );
}
}
float upsamp = m_UpsamplingFactor;
float gausssigma = m_GaussianSigma;
// Spacing
typename ResamplerType::SpacingType spacing = planegeo->GetSpacing();
spacing[0] = image->GetSpacing()[0] / upsamp;
spacing[1] = image->GetSpacing()[1] / upsamp;
spacing[2] = image->GetSpacing()[2];
if(m_PlanarFigureThickness)
{
spacing[2] = image->GetSpacing()[2] / upsamp;
}
resampler->SetOutputSpacing( spacing );
// Size
typename ResamplerType::SizeType size;
size[0] = planegeo->GetExtentInMM(0) / spacing[0];
size[1] = planegeo->GetExtentInMM(1) / spacing[1];
size[2] = 1+2*m_PlanarFigureThickness; // klaus add +2*m_PlanarFigureThickness
MITK_DEBUG << "setting size2:="<<size[2] << " (before " << 1 << ")";
resampler->SetSize( size );
// Origin
typename mitk::Point3D orig = planegeo->GetOrigin();
typename mitk::Point3D corrorig;
planegeo3D->WorldToIndex(orig,corrorig);
corrorig[0] += 0.5/upsamp;
corrorig[1] += 0.5/upsamp;
if(m_PlanarFigureThickness)
{
float thickyyy = m_PlanarFigureThickness;
thickyyy/=upsamp;
corrorig[2] -= thickyyy; // klaus add -= (float)m_PlanarFigureThickness/upsamp statt += 0
}
planegeo3D->IndexToWorld(corrorig,corrorig);
resampler->SetOutputOrigin(corrorig );
// Direction
typename ResamplerType::DirectionType direction;
typename mitk::AffineTransform3D::MatrixType matrix = planegeo->GetIndexToWorldTransform()->GetMatrix();
for(unsigned int c = 0; c < matrix.ColumnDimensions; ++c)
{
double sum = 0;
for(unsigned int r = 0 ; r<matrix.RowDimensions; r++)
{
sum += matrix(r,c)*matrix(r,c);
}
for(unsigned int r = 0 ; r<matrix.RowDimensions; ++r)
{
direction(r,c) = matrix(r,c)/sqrt(sum);
}
}
resampler->SetOutputDirection( direction );
// Gaussian interpolation
if(gausssigma != 0)
{
double sigma[3];
for( unsigned int d = 0; d < 3; d++ )
{
sigma[d] = gausssigma * image->GetSpacing()[d];
}
double alpha = 2.0;
typedef itk::GaussianInterpolateImageFunction<ImageType, double>
GaussianInterpolatorType;
typename GaussianInterpolatorType::Pointer interpolator
= GaussianInterpolatorType::New();
interpolator->SetInputImage( image );
interpolator->SetParameters( sigma, alpha );
resampler->SetInterpolator( interpolator );
}
else
{
// typedef typename itk::BSplineInterpolateImageFunction<ImageType, double>
// InterpolatorType;
typedef typename itk::LinearInterpolateImageFunction<ImageType, double> InterpolatorType;
typename InterpolatorType::Pointer interpolator
= InterpolatorType::New();
interpolator->SetInputImage( image );
resampler->SetInterpolator( interpolator );
}
// Other resampling options
resampler->SetInput( image );
resampler->SetDefaultPixelValue(0);
MITK_DEBUG << "Resampling requested image plane ... ";
resampler->Update();
MITK_DEBUG << " ... done";
if(additionalIndex < 0)
{
this->m_InternalImage = mitk::Image::New();
this->m_InternalImage->InitializeByItk( resampler->GetOutput() );
this->m_InternalImage->SetVolume( resampler->GetOutput()->GetBufferPointer() );
}
else
{
unsigned int myIndex = additionalIndex;
this->m_InternalAdditionalResamplingImages.push_back(mitk::Image::New());
this->m_InternalAdditionalResamplingImages[myIndex]->InitializeByItk( resampler->GetOutput() );
this->m_InternalAdditionalResamplingImages[myIndex]->SetVolume( resampler->GetOutput()->GetBufferPointer() );
}
}
template < typename TPixel, unsigned int VImageDimension >
void PartialVolumeAnalysisHistogramCalculator::InternalResampleImageFromMask(
const itk::Image< TPixel, VImageDimension > *image, int additionalIndex )
{
typedef itk::Image< TPixel, VImageDimension > ImageType;
typename ImageType::Pointer outImage = ImageType::New();
outImage->SetSpacing( m_InternalImageMask3D->GetSpacing() ); // Set the image spacing
outImage->SetOrigin( m_InternalImageMask3D->GetOrigin() ); // Set the image origin
outImage->SetDirection( m_InternalImageMask3D->GetDirection() ); // Set the image direction
outImage->SetRegions( m_InternalImageMask3D->GetLargestPossibleRegion() );
outImage->Allocate();
outImage->FillBuffer(0);
typedef itk::InterpolateImageFunction<ImageType, double>
BaseInterpType;
typedef itk::GaussianInterpolateImageFunction<ImageType, double>
GaussianInterpolatorType;
typedef itk::LinearInterpolateImageFunction<ImageType, double>
LinearInterpolatorType;
typename BaseInterpType::Pointer interpolator;
if(m_GaussianSigma != 0)
{
double sigma[3];
for( unsigned int d = 0; d < 3; d++ )
{
sigma[d] = m_GaussianSigma * image->GetSpacing()[d];
}
double alpha = 2.0;
interpolator = GaussianInterpolatorType::New();
dynamic_cast<GaussianInterpolatorType*>(interpolator.GetPointer())->SetParameters( sigma, alpha );
}
else
{
interpolator = LinearInterpolatorType::New();
}
interpolator->SetInputImage( image );
itk::ImageRegionConstIterator<MaskImage3DType>
itmask(m_InternalImageMask3D, m_InternalImageMask3D->GetLargestPossibleRegion());
itk::ImageRegionIterator<ImageType>
itimage(outImage, outImage->GetLargestPossibleRegion());
itmask.GoToBegin();
itimage.GoToBegin();
itk::Point< double, 3 > point;
itk::ContinuousIndex< double, 3 > index;
while( !itmask.IsAtEnd() )
{
if(itmask.Get() != 0)
{
outImage->TransformIndexToPhysicalPoint (itimage.GetIndex(), point);
image->TransformPhysicalPointToContinuousIndex(point, index);
itimage.Set(interpolator->EvaluateAtContinuousIndex(index));
}
++itmask;
++itimage;
}
if(additionalIndex < 0)
{
this->m_InternalImage = mitk::Image::New();
this->m_InternalImage->InitializeByItk( outImage.GetPointer() );
this->m_InternalImage->SetVolume( outImage->GetBufferPointer() );
}
else
{
this->m_InternalAdditionalResamplingImages[additionalIndex] = mitk::Image::New();
this->m_InternalAdditionalResamplingImages[additionalIndex]->InitializeByItk( outImage.GetPointer() );
this->m_InternalAdditionalResamplingImages[additionalIndex]->SetVolume( outImage->GetBufferPointer() );
}
}
void PartialVolumeAnalysisHistogramCalculator::InternalResampleImage(
const MaskImage3DType *image )
{
typedef itk::ResampleImageFilter<MaskImage3DType, MaskImage3DType, double> ResamplerType;
ResamplerType::Pointer resampler = ResamplerType::New();
// Size
ResamplerType::SizeType size;
size[0] = m_UpsamplingFactor * image->GetLargestPossibleRegion().GetSize()[0];
size[1] = m_UpsamplingFactor * image->GetLargestPossibleRegion().GetSize()[1];
size[2] = m_UpsamplingFactor * image->GetLargestPossibleRegion().GetSize()[2];;
resampler->SetSize( size );
// Origin
mitk::Point3D orig = image->GetOrigin();
resampler->SetOutputOrigin(orig );
// Spacing
ResamplerType::SpacingType spacing;
spacing[0] = image->GetSpacing()[0] / m_UpsamplingFactor;
spacing[1] = image->GetSpacing()[1] / m_UpsamplingFactor;
spacing[2] = image->GetSpacing()[2] / m_UpsamplingFactor;
resampler->SetOutputSpacing( spacing );
resampler->SetOutputDirection( image->GetDirection() );
typedef itk::NearestNeighborInterpolateImageFunction<MaskImage3DType, double>
InterpolatorType;
InterpolatorType::Pointer interpolator
= InterpolatorType::New();
interpolator->SetInputImage( image );
resampler->SetInterpolator( interpolator );
// Other resampling options
resampler->SetInput( image );
resampler->SetDefaultPixelValue(0);
resampler->Update();
m_InternalImageMask3D = resampler->GetOutput();
}
template < typename TPixel, unsigned int VImageDimension >
void PartialVolumeAnalysisHistogramCalculator::InternalCalculateStatisticsUnmasked(
const itk::Image< TPixel, VImageDimension > *image,
Statistics &statistics,
typename HistogramType::ConstPointer *histogram )
{
MITK_DEBUG << "InternalCalculateStatisticsUnmasked()";
typedef itk::Image< TPixel, VImageDimension > ImageType;
// Progress listening...
typedef itk::SimpleMemberCommand< PartialVolumeAnalysisHistogramCalculator > ITKCommandType;
ITKCommandType::Pointer progressListener;
progressListener = ITKCommandType::New();
progressListener->SetCallbackFunction( this,
&PartialVolumeAnalysisHistogramCalculator::UnmaskedStatisticsProgressUpdate );
// Issue 100 artificial progress events since ScalarIMageToHistogramGenerator
// does not (yet?) support progress reporting
this->InvokeEvent( itk::StartEvent() );
for ( unsigned int i = 0; i < 100; ++i )
{
this->UnmaskedStatisticsProgressUpdate();
}
// Calculate statistics (separate filter)
typedef itk::StatisticsImageFilter< ImageType > StatisticsFilterType;
typename StatisticsFilterType::Pointer statisticsFilter = StatisticsFilterType::New();
statisticsFilter->SetInput( image );
unsigned long observerTag = statisticsFilter->AddObserver(
itk::ProgressEvent(), progressListener );
statisticsFilter->Update();
statisticsFilter->RemoveObserver( observerTag );
this->InvokeEvent( itk::EndEvent() );
statistics.N = image->GetBufferedRegion().GetNumberOfPixels();
statistics.Min = statisticsFilter->GetMinimum();
statistics.Max = statisticsFilter->GetMaximum();
statistics.Mean = statisticsFilter->GetMean();
statistics.Median = 0.0;
statistics.Sigma = statisticsFilter->GetSigma();
statistics.RMS = sqrt( statistics.Mean * statistics.Mean
+ statistics.Sigma * statistics.Sigma );
typename ImageType::Pointer inImage = const_cast<ImageType*>(image);
// Calculate histogram
typedef itk::Statistics::ScalarImageToHistogramGenerator< ImageType >
HistogramGeneratorType;
typename HistogramGeneratorType::Pointer histogramGenerator = HistogramGeneratorType::New();
histogramGenerator->SetInput( inImage );
histogramGenerator->SetMarginalScale( 10 ); // Defines y-margin width of histogram
histogramGenerator->SetNumberOfBins( m_NumberOfBins ); // CT range [-1024, +2048] --> bin size 4 values
histogramGenerator->SetHistogramMin( statistics.Min );
histogramGenerator->SetHistogramMax( statistics.Max );
histogramGenerator->Compute();
*histogram = histogramGenerator->GetOutput();
}
template < typename TPixel, unsigned int VImageDimension >
void PartialVolumeAnalysisHistogramCalculator::InternalCalculateStatisticsMasked(
const itk::Image< TPixel, VImageDimension > *image,
itk::Image< unsigned char, VImageDimension > *maskImage,
Statistics &,
typename HistogramType::ConstPointer *histogram )
{
MITK_DEBUG << "InternalCalculateStatisticsMasked() start";
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::Image< unsigned char, VImageDimension > MaskImageType;
// generate a list sample of angles at positions
// where the fiber-prob is higher than .2*maxprob
typedef TPixel MeasurementType;
const unsigned int MeasurementVectorLength = 1;
typedef itk::Vector< MeasurementType , MeasurementVectorLength >
MeasurementVectorType;
typedef itk::Statistics::ListSample< MeasurementVectorType > ListSampleType;
typename ListSampleType::Pointer listSample = ListSampleType::New();
listSample->SetMeasurementVectorSize( MeasurementVectorLength );
itk::ImageRegionConstIterator<MaskImageType>
itmask(maskImage, maskImage->GetLargestPossibleRegion());
itk::ImageRegionConstIterator<ImageType>
itimage(image, image->GetLargestPossibleRegion());
itmask.GoToBegin();
itimage.GoToBegin();
while( !itmask.IsAtEnd() )
{
if(itmask.Get() != 0)
{
// apend to list
MeasurementVectorType mv;
mv[0] = ( MeasurementType ) itimage.Get();
listSample->PushBack(mv);
}
++itmask;
++itimage;
}
// generate a histogram from the list sample
typedef double HistogramMeasurementType;
typedef itk::Statistics::Histogram< HistogramMeasurementType, itk::Statistics::DenseFrequencyContainer2 > HistogramType;
typedef itk::Statistics::SampleToHistogramFilter< ListSampleType, HistogramType > GeneratorType;
typename GeneratorType::Pointer generator = GeneratorType::New();
typename GeneratorType::HistogramType::SizeType size(MeasurementVectorLength);
size.Fill(m_NumberOfBins);
generator->SetHistogramSize( size );
generator->SetInput( listSample );
generator->SetMarginalScale( 10.0 );
generator->Update();
*histogram = generator->GetOutput();
}
template < typename TPixel, unsigned int VImageDimension >
void PartialVolumeAnalysisHistogramCalculator::InternalCropAdditionalImage(
itk::Image< TPixel, VImageDimension > *image, int additionalIndex )
{
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::RegionOfInterestImageFilter< ImageType, ImageType > ROIFilterType;
typename ROIFilterType::Pointer roi = ROIFilterType::New();
roi->SetRegionOfInterest(m_CropRegion);
roi->SetInput(image);
roi->Update();
m_InternalAdditionalResamplingImages[additionalIndex] = mitk::Image::New();
m_InternalAdditionalResamplingImages[additionalIndex]->InitializeByItk(roi->GetOutput());
m_InternalAdditionalResamplingImages[additionalIndex]->SetVolume(roi->GetOutput()->GetBufferPointer());
}
template < typename TPixel, unsigned int VImageDimension >
void PartialVolumeAnalysisHistogramCalculator::InternalCalculateMaskFromPlanarFigure(
itk::Image< TPixel, VImageDimension > *image, unsigned int axis )
{
MITK_DEBUG << "InternalCalculateMaskFromPlanarFigure() start";
typedef itk::Image< TPixel, VImageDimension > ImageType;
// Generate mask image as new image with same header as input image and
// initialize with "1".
MaskImage3DType::Pointer newMaskImage = MaskImage3DType::New();
newMaskImage->SetSpacing( image->GetSpacing() ); // Set the image spacing
newMaskImage->SetOrigin( image->GetOrigin() ); // Set the image origin
newMaskImage->SetDirection( image->GetDirection() ); // Set the image direction
newMaskImage->SetRegions( image->GetLargestPossibleRegion() );
newMaskImage->Allocate();
newMaskImage->FillBuffer( 1 );
// Generate VTK polygon from (closed) PlanarFigure polyline
// (The polyline points are shifted by -0.5 in z-direction to make sure
// that the extrusion filter, which afterwards elevates all points by +0.5
// in z-direction, creates a 3D object which is cut by the the plane z=0)
const mitk::PlaneGeometry *planarFigureGeometry2D = m_PlanarFigure->GetPlaneGeometry();
const typename PlanarFigure::PolyLineType planarFigurePolyline = m_PlanarFigure->GetPolyLine( 0 );
const mitk::BaseGeometry *imageGeometry3D = m_InternalImage->GetGeometry( 0 );
vtkPolyData *polyline = vtkPolyData::New();
polyline->Allocate( 1, 1 );
// Determine x- and y-dimensions depending on principal axis
int i0, i1;
switch ( axis )
{
case 0:
i0 = 1;
i1 = 2;
break;
case 1:
i0 = 0;
i1 = 2;
break;
case 2:
default:
i0 = 0;
i1 = 1;
break;
}
// Create VTK polydata object of polyline contour
bool outOfBounds = false;
vtkPoints *points = vtkPoints::New();
typename PlanarFigure::PolyLineType::const_iterator it;
for ( it = planarFigurePolyline.begin();
it != planarFigurePolyline.end();
++it )
{
Point3D point3D;
// Convert 2D point back to the local index coordinates of the selected
// image
mitk::Point2D point2D = *it;
planarFigureGeometry2D->WorldToIndex(point2D, point2D);
point2D[0] -= 0.5/m_UpsamplingFactor;
point2D[1] -= 0.5/m_UpsamplingFactor;
planarFigureGeometry2D->IndexToWorld(point2D, point2D);
planarFigureGeometry2D->Map( point2D, point3D );
// Polygons (partially) outside of the image bounds can not be processed
// further due to a bug in vtkPolyDataToImageStencil
if ( !imageGeometry3D->IsInside( point3D ) )
{
outOfBounds = true;
}
imageGeometry3D->WorldToIndex( point3D, point3D );
point3D[i0] += 0.5;
point3D[i1] += 0.5;
// Add point to polyline array
points->InsertNextPoint( point3D[i0], point3D[i1], -0.5 );
}
polyline->SetPoints( points );
points->Delete();
if ( outOfBounds )
{
polyline->Delete();
throw std::runtime_error( "Figure at least partially outside of image bounds!" );
}
std::size_t numberOfPoints = planarFigurePolyline.size();
auto ptIds = new vtkIdType[numberOfPoints];
for ( std::size_t i = 0; i < numberOfPoints; ++i )
{
ptIds[i] = i;
}
polyline->InsertNextCell( VTK_POLY_LINE, numberOfPoints, ptIds );
// Extrude the generated contour polygon
vtkLinearExtrusionFilter *extrudeFilter = vtkLinearExtrusionFilter::New();
extrudeFilter->SetInputData( polyline );
extrudeFilter->SetScaleFactor( 1 );
extrudeFilter->SetExtrusionTypeToNormalExtrusion();
extrudeFilter->SetVector( 0.0, 0.0, 1.0 );
// Make a stencil from the extruded polygon
vtkPolyDataToImageStencil *polyDataToImageStencil = vtkPolyDataToImageStencil::New();
polyDataToImageStencil->SetInputConnection( extrudeFilter->GetOutputPort() );
// Export from ITK to VTK (to use a VTK filter)
typedef itk::VTKImageImport< MaskImage3DType > ImageImportType;
typedef itk::VTKImageExport< MaskImage3DType > ImageExportType;
typename ImageExportType::Pointer itkExporter = ImageExportType::New();
itkExporter->SetInput( newMaskImage );
vtkImageImport *vtkImporter = vtkImageImport::New();
this->ConnectPipelines( itkExporter, vtkImporter );
vtkImporter->Update();
// Apply the generated image stencil to the input image
vtkImageStencil *imageStencilFilter = vtkImageStencil::New();
imageStencilFilter->SetInputData( vtkImporter->GetOutput() );
imageStencilFilter->SetStencilConnection(polyDataToImageStencil->GetOutputPort() );
imageStencilFilter->ReverseStencilOff();
imageStencilFilter->SetBackgroundValue( 0 );
imageStencilFilter->Update();
// Export from VTK back to ITK
vtkImageExport *vtkExporter = vtkImageExport::New();
vtkExporter->SetInputData( imageStencilFilter->GetOutput() );
vtkExporter->Update();
typename ImageImportType::Pointer itkImporter = ImageImportType::New();
this->ConnectPipelines( vtkExporter, itkImporter );
itkImporter->Update();
// calculate cropping bounding box
m_InternalImageMask3D = itkImporter->GetOutput();
m_InternalImageMask3D->SetDirection(image->GetDirection());
itk::ImageRegionIterator<MaskImage3DType>
itmask(m_InternalImageMask3D, m_InternalImageMask3D->GetLargestPossibleRegion());
itmask.GoToBegin();
while( !itmask.IsAtEnd() )
{
if(itmask.Get() != 0)
{
typename ImageType::IndexType index = itmask.GetIndex();
for(unsigned int thick=0; thick<2*m_PlanarFigureThickness+1; thick++)
{
index[axis] = thick;
m_InternalImageMask3D->SetPixel(index, itmask.Get());
}
}
++itmask;
}
itmask.GoToBegin();
itk::ImageRegionIterator<ImageType>
itimage(image, image->GetLargestPossibleRegion());
itimage.GoToBegin();
typename ImageType::SizeType lowersize;
lowersize.Fill(std::numeric_limits<typename ImageType::SizeValueType>::max());
typename ImageType::SizeType uppersize;
uppersize.Fill(std::numeric_limits<typename ImageType::SizeValueType>::min());
while( !itmask.IsAtEnd() )
{
if(itmask.Get() == 0)
{
itimage.Set(0);
}
else
{
typename ImageType::IndexType index = itimage.GetIndex();
typename ImageType::SizeType signedindex;
signedindex[0] = index[0];
signedindex[1] = index[1];
signedindex[2] = index[2];
lowersize[0] = signedindex[0] < lowersize[0] ? signedindex[0] : lowersize[0];
lowersize[1] = signedindex[1] < lowersize[1] ? signedindex[1] : lowersize[1];
lowersize[2] = signedindex[2] < lowersize[2] ? signedindex[2] : lowersize[2];
uppersize[0] = signedindex[0] > uppersize[0] ? signedindex[0] : uppersize[0];
uppersize[1] = signedindex[1] > uppersize[1] ? signedindex[1] : uppersize[1];
uppersize[2] = signedindex[2] > uppersize[2] ? signedindex[2] : uppersize[2];
}
++itmask;
++itimage;
}
typename ImageType::IndexType index;
index[0] = lowersize[0];
index[1] = lowersize[1];
index[2] = lowersize[2];
typename ImageType::SizeType size;
size[0] = uppersize[0] - lowersize[0] + 1;
size[1] = uppersize[1] - lowersize[1] + 1;
size[2] = uppersize[2] - lowersize[2] + 1;
m_CropRegion = itk::ImageRegion<3>(index, size);
// crop internal image
typedef itk::RegionOfInterestImageFilter< ImageType, ImageType > ROIFilterType;
typename ROIFilterType::Pointer roi = ROIFilterType::New();
roi->SetRegionOfInterest(m_CropRegion);
roi->SetInput(image);
roi->Update();
m_InternalImage = mitk::Image::New();
m_InternalImage->InitializeByItk(roi->GetOutput());
m_InternalImage->SetVolume(roi->GetOutput()->GetBufferPointer());
// crop internal mask
typedef itk::RegionOfInterestImageFilter< MaskImage3DType, MaskImage3DType > ROIMaskFilterType;
typename ROIMaskFilterType::Pointer roi2 = ROIMaskFilterType::New();
roi2->SetRegionOfInterest(m_CropRegion);
roi2->SetInput(m_InternalImageMask3D);
roi2->Update();
m_InternalImageMask3D = roi2->GetOutput();
// Clean up VTK objects
polyline->Delete();
extrudeFilter->Delete();
polyDataToImageStencil->Delete();
vtkImporter->Delete();
imageStencilFilter->Delete();
//vtkExporter->Delete(); // TODO: crashes when outcommented; memory leak??
delete[] ptIds;
}
void PartialVolumeAnalysisHistogramCalculator::UnmaskedStatisticsProgressUpdate()
{
// Need to throw away every second progress event to reach a final count of
// 100 since two consecutive filters are used in this case
static int updateCounter = 0;
if ( updateCounter++ % 2 == 0 )
{
this->InvokeEvent( itk::ProgressEvent() );
}
}
void PartialVolumeAnalysisHistogramCalculator::MaskedStatisticsProgressUpdate()
{
this->InvokeEvent( itk::ProgressEvent() );
}
}
diff --git a/Modules/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.h b/Modules/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.h
index 9757ca2..50c55c9 100644
--- a/Modules/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.h
+++ b/Modules/DiffusionCore/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.h
@@ -1,384 +1,384 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_PartialVolumeAnalysisHistogramCalculator_H
#define _MITK_PartialVolumeAnalysisHistogramCalculator_H
#include "MitkDiffusionCoreExports.h"
#include <itkObject.h>
#include <itkImage.h>
#include <itkTimeStamp.h>
#include "mitkImage.h"
#include "mitkImageTimeSelector.h"
#include "mitkPlanarFigure.h"
namespace mitk
{
/**
* \brief Class for calculating statistics and histogram for an (optionally
* masked) image.
*
* Images can be masked by either a (binary) image (of the same dimensions as
* the original image) or by a closed mitk::PlanarFigure, e.g. a circle or
* polygon. When masking with a planar figure, the slice corresponding to the
* plane containing the figure is extracted and then clipped with contour
* defined by the figure. Planar figures need to be aligned along the main axes
* of the image (axial, sagittal, coronal). Planar figures on arbitrary
* rotated planes are not supported.
*
* For each operating mode (no masking, masking by image, masking by planar
* figure), the calculated statistics and histogram are cached so that, when
* switching back and forth between operation modes without modifying mask or
* image, the information doesn't need to be recalculated.
*
* Note: currently time-resolved and multi-channel pictures are not properly
* supported.
*/
class MITKDIFFUSIONCORE_EXPORT PartialVolumeAnalysisHistogramCalculator : public itk::Object
{
public:
enum
{
MASKING_MODE_NONE = 0,
MASKING_MODE_IMAGE,
MASKING_MODE_PLANARFIGURE
};
typedef mitk::Image::HistogramType HistogramType;
typedef mitk::Image::HistogramType::ConstIterator HistogramConstIteratorType;
struct Statistics
{
unsigned int N;
double Min;
double Max;
double Mean;
double Median;
double Variance;
double Sigma;
double RMS;
void Reset()
{
N = 0;
Min = 0.0;
Max = 0.0;
Mean = 0.0;
Median = 0.0;
Variance = 0.0;
Sigma = 0.0;
RMS = 0.0;
}
};
typedef Statistics StatisticsType;
typedef itk::TimeStamp TimeStampType;
typedef bool BoolType;
typedef itk::Image< unsigned char, 3 > MaskImage3DType;
typedef itk::Image< unsigned char, 2 > MaskImage2DType;
typedef itk::Image< float, 2 > InternalImage2DType;
mitkClassMacroItkParent( PartialVolumeAnalysisHistogramCalculator, itk::Object )
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** \brief Set image from which to compute statistics. */
void SetImage( const mitk::Image *image );
/** \brief Set binary image for masking. */
void SetImageMask( const mitk::Image *imageMask );
/** \brief Set planar figure for masking. */
void SetPlanarFigure( const mitk::PlanarFigure *planarFigure );
/** \brief Set image for which the same resampling will be applied.
and available via GetAdditionalResampledImage() */
void AddAdditionalResamplingImage( const mitk::Image *image );
/** \brief Set/Get operation mode for masking */
void SetMaskingMode( unsigned int mode );
/** \brief Set/Get operation mode for masking */
itkGetMacro( MaskingMode, unsigned int );
/** \brief Set/Get operation mode for masking */
void SetMaskingModeToNone();
/** \brief Set/Get operation mode for masking */
void SetMaskingModeToImage();
/** \brief Set/Get operation mode for masking */
void SetMaskingModeToPlanarFigure();
/** \brief Set histogram number of bins. */
void SetNumberOfBins( unsigned int number )
{
if(m_NumberOfBins != number)
{
m_NumberOfBins = number;
SetModified();
}
}
/** \brief Get histogram number of bins. */
unsigned int GetNumberOfBins( )
{ return m_NumberOfBins; }
/** \brief Set upsampling factor. */
void SetUpsamplingFactor( float number )
{
if(m_UpsamplingFactor != number)
{
m_UpsamplingFactor = number;
SetModified();
}
}
/** \brief Get upsampling factor. */
float GetUpsamplingFactor( )
{ return m_UpsamplingFactor; }
/** \brief Set gaussian sigma. */
void SetGaussianSigma( float number )
{
if(m_GaussianSigma != number)
{
m_GaussianSigma = number;
SetModified();
}
}
/** \brief Get thickness of planar figure. */
unsigned int GetPlanarFigureThickness( )
{ return m_PlanarFigureThickness; }
/** \brief Set thickness of planar figure. */
void SetPlanarFigureThickness( unsigned int number )
{
if(m_PlanarFigureThickness != number)
{
m_PlanarFigureThickness = number;
SetModified();
}
}
/** \brief Get histogram number of bins. */
float GetGaussianSigma( )
{ return m_GaussianSigma; }
void SetModified();
/** \brief Compute statistics (together with histogram) for the current
* masking mode.
*
* Computation is not executed if statistics is already up to date. In this
* case, false is returned; otherwise, true.*/
virtual bool ComputeStatistics( );
/** \brief Retrieve the histogram depending on the current masking mode. */
const HistogramType *GetHistogram( ) const;
/** \brief Retrieve statistics depending on the current masking mode. */
const Statistics &GetStatistics( ) const;
const Image::Pointer GetInternalImage()
{
return m_InternalImage;
}
const Image::Pointer GetInternalAdditionalResampledImage(unsigned int i)
{
if(i < m_InternalAdditionalResamplingImages.size())
{
return m_InternalAdditionalResamplingImages[i];
}
else
{
return nullptr;
}
}
void SetForceUpdate(bool b)
{
m_ForceUpdate = b;
}
protected:
PartialVolumeAnalysisHistogramCalculator();
~PartialVolumeAnalysisHistogramCalculator() override;
/** \brief Depending on the masking mode, the image and mask from which to
* calculate statistics is extracted from the original input image and mask
* data.
*
* For example, a when using a PlanarFigure as mask, the 2D image slice
* corresponding to the PlanarFigure will be extracted from the original
* image. If masking is disabled, the original image is simply passed
* through. */
void ExtractImageAndMask( );
/** \brief If the passed vector matches any of the three principal axes
* of the passed geometry, the ínteger value corresponding to the axis
* is set and true is returned. */
bool GetPrincipalAxis( const Geometry3D *geometry, Vector3D vector,
unsigned int &axis );
template < typename TPixel, unsigned int VImageDimension >
void InternalCalculateStatisticsUnmasked(
const itk::Image< TPixel, VImageDimension > *image,
Statistics &statistics,
typename HistogramType::ConstPointer *histogram );
template < typename TPixel, unsigned int VImageDimension >
void InternalCalculateStatisticsMasked(
const itk::Image< TPixel, VImageDimension > *image,
itk::Image< unsigned char, VImageDimension > *maskImage,
Statistics &statistics,
typename HistogramType::ConstPointer *histogram );
template < typename TPixel, unsigned int VImageDimension >
void InternalCalculateMaskFromPlanarFigure(
itk::Image< TPixel, VImageDimension > *image, unsigned int axis );
template < typename TPixel, unsigned int VImageDimension >
void InternalReorientImagePlane(
const itk::Image< TPixel, VImageDimension > *image, mitk::BaseGeometry* imggeo, mitk::BaseGeometry* planegeo3D, int additionalIndex );
template < typename TPixel, unsigned int VImageDimension >
void InternalResampleImageFromMask(
const itk::Image< TPixel, VImageDimension > *image, int additionalIndex );
void InternalResampleImage(
const MaskImage3DType *image/*, mitk::Geometry3D* imggeo*/ );
template < typename TPixel, unsigned int VImageDimension >
void InternalCropAdditionalImage(
itk::Image< TPixel, VImageDimension > *image, int additionalIndex );
void InternalMaskImage( mitk::Image *image );
/** Connection from ITK to VTK */
template <typename ITK_Exporter, typename VTK_Importer>
void ConnectPipelines(ITK_Exporter exporter, VTK_Importer* importer)
{
importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
importer->SetSpacingCallback(exporter->GetSpacingCallback());
importer->SetOriginCallback(exporter->GetOriginCallback());
importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback());
importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
importer->SetCallbackUserData(exporter->GetCallbackUserData());
}
/** Connection from VTK to ITK */
template <typename VTK_Exporter, typename ITK_Importer>
void ConnectPipelines(VTK_Exporter* exporter, ITK_Importer importer)
{
importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
importer->SetSpacingCallback(exporter->GetSpacingCallback());
importer->SetOriginCallback(exporter->GetOriginCallback());
importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback());
importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
importer->SetCallbackUserData(exporter->GetCallbackUserData());
}
void UnmaskedStatisticsProgressUpdate();
void MaskedStatisticsProgressUpdate();
mitk::Image::ConstPointer m_Image;
mitk::Image::ConstPointer m_ImageMask;
mitk::PlanarFigure::ConstPointer m_PlanarFigure;
HistogramType::ConstPointer m_ImageHistogram;
HistogramType::ConstPointer m_MaskedImageHistogram;
HistogramType::ConstPointer m_PlanarFigureHistogram;
HistogramType::Pointer m_EmptyHistogram;
StatisticsType m_ImageStatistics;
StatisticsType m_MaskedImageStatistics;
StatisticsType m_PlanarFigureStatistics;
Statistics m_EmptyStatistics;
unsigned int m_MaskingMode;
bool m_MaskingModeChanged;
mitk::Image::Pointer m_InternalImage;
MaskImage3DType::Pointer m_InternalImageMask3D;
MaskImage2DType::Pointer m_InternalImageMask2D;
itk::ImageRegion<3> m_InternalMask3D;
std::vector<mitk::Image::ConstPointer> m_AdditionalResamplingImages;
std::vector<mitk::Image::Pointer> m_InternalAdditionalResamplingImages;
TimeStampType m_ImageStatisticsTimeStamp;
TimeStampType m_MaskedImageStatisticsTimeStamp;
TimeStampType m_PlanarFigureStatisticsTimeStamp;
BoolType m_ImageStatisticsCalculationTriggerBool;
BoolType m_MaskedImageStatisticsCalculationTriggerBool;
BoolType m_PlanarFigureStatisticsCalculationTriggerBool;
unsigned int m_NumberOfBins;
float m_UpsamplingFactor;
float m_GaussianSigma;
itk::ImageRegion<3> m_CropRegion;
bool m_ForceUpdate;
unsigned int m_PlanarFigureThickness;
};
}
#endif // #define _MITK_PartialVolumeAnalysisHistogramCalculator_H
diff --git a/Modules/DiffusionCore/DicomImport/mitkDicomDiffusionImageHeaderReader.cpp b/Modules/DiffusionCore/DicomImport/mitkDicomDiffusionImageHeaderReader.cpp
index 7450f3b..dc3afe3 100644
--- a/Modules/DiffusionCore/DicomImport/mitkDicomDiffusionImageHeaderReader.cpp
+++ b/Modules/DiffusionCore/DicomImport/mitkDicomDiffusionImageHeaderReader.cpp
@@ -1,328 +1,328 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkDicomDiffusionImageHeaderReader.h"
#include <mitkLocaleSwitch.h>
#include "mitkGEDicomDiffusionImageHeaderReader.h"
#include "mitkPhilipsDicomDiffusionImageHeaderReader.h"
#include "mitkSiemensDicomDiffusionImageHeaderReader.h"
#include "mitkSiemensMosaicDicomDiffusionImageHeaderReader.h"
void InsertUnique( std::vector<float> & vec, float value )
{
int n = vec.size();
if (n == 0)
{
vec.push_back( value );
return;
}
for (int k = 0; k < n ; k++)
{
if (vec[k] == value)
{
return;
}
}
// if we get here, it means value is not in vec.
vec.push_back( value );
return;
}
mitk::DicomDiffusionImageHeaderReader::DicomDiffusionImageHeaderReader()
{
m_SliceOrderIS = true;
m_SingleSeries = true;
}
mitk::DicomDiffusionImageHeaderReader::~DicomDiffusionImageHeaderReader()
{
}
mitk::DicomDiffusionImageHeaderReader::SupportedVendors
mitk::DicomDiffusionImageHeaderReader::GetVendorID()
{
// adapted from namic-sandbox
// DicomToNrrdConverter.cxx
m_GdcmIO = ImageIOType::New();
m_GdcmIO->LoadPrivateTagsOn();
m_GdcmIO->SetMaxSizeLoadEntry( 65536 );
m_VolumeReader = VolumeReaderType::New();
m_VolumeReader->SetImageIO( m_GdcmIO );
m_VolumeReader->SetFileNames( m_DicomFilenames );
try
{
m_VolumeReader->Update();
}
catch (itk::ExceptionObject &excp)
{
std::cerr << "Exception thrown while reading slice" << std::endl;
std::cerr << excp << std::endl;
return SV_UNKNOWN_VENDOR;
}
VolumeReaderType::DictionaryArrayRawPointer inputDict
= m_VolumeReader->GetMetaDataDictionaryArray();
std::string vendor;
itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0008|0070", vendor );
// std::cout << vendor << std::endl;
std::string ImageType;
itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0008|0008", ImageType );
//std::cout << ImageType << std::endl;
if ( vendor.find("GE") != std::string::npos )
{
// for GE data
return SV_GE;
}
else if( vendor.find("SIEMENS") != std::string::npos )
{
if ( ImageType.find("MOSAIC") != std::string::npos )
{
// for Siemens MOSAIC
return SV_SIEMENS_MOSAIC;
}
else
{
// for Siemens SPLIT
return SV_SIEMENS;
}
}
else if( vendor.find("PHILIPS") != std::string::npos )
{
// for philips data
return SV_PHILIPS;
}
else
{
// for unrecognized vendors
return SV_UNKNOWN_VENDOR;
}
}
// do the work
void mitk::DicomDiffusionImageHeaderReader::Update()
{
// check if there are filenames
if(m_DicomFilenames.size())
{
m_Output = mitk::DiffusionImageHeaderInformation::New();
m_Output->m_DicomFilenames = m_DicomFilenames;
// create correct reader
switch(GetVendorID())
{
case(SV_GE):
{
GEDicomDiffusionImageHeaderReader::Pointer reader
= GEDicomDiffusionImageHeaderReader::New();
reader->SetSeriesDicomFilenames(this->m_DicomFilenames);
reader->SetGdcmIO(this->m_GdcmIO);
reader->SetVolumeReader(this->m_VolumeReader);
reader->SetOutputPointer(this->m_Output);
reader->Update();
this->m_Output = reader->GetOutput();
break;
}
case(SV_SIEMENS):
{
SiemensDicomDiffusionImageHeaderReader::Pointer reader
= SiemensDicomDiffusionImageHeaderReader::New();
reader->SetSeriesDicomFilenames(this->m_DicomFilenames);
reader->SetGdcmIO(this->m_GdcmIO);
reader->SetVolumeReader(this->m_VolumeReader);
reader->SetOutputPointer(this->m_Output);
reader->Update();
this->m_Output = reader->GetOutput();
break;
}
case(SV_SIEMENS_MOSAIC):
{
SiemensMosaicDicomDiffusionImageHeaderReader::Pointer reader
= SiemensMosaicDicomDiffusionImageHeaderReader::New();
reader->SetSeriesDicomFilenames(this->m_DicomFilenames);
reader->SetGdcmIO(this->m_GdcmIO);
reader->SetVolumeReader(this->m_VolumeReader);
reader->SetOutputPointer(this->m_Output);
reader->Update();
this->m_Output = reader->GetOutput();
break;
}
case(SV_PHILIPS):
{
PhilipsDicomDiffusionImageHeaderReader::Pointer reader
= PhilipsDicomDiffusionImageHeaderReader::New();
reader->SetSeriesDicomFilenames(this->m_DicomFilenames);
reader->SetGdcmIO(this->m_GdcmIO);
reader->SetVolumeReader(this->m_VolumeReader);
reader->SetOutputPointer(this->m_Output);
reader->Update();
this->m_Output = reader->GetOutput();
break;
}
case(SV_UNKNOWN_VENDOR):
{
std::cerr << "diffusion header reader: unknown vendor" << std::endl;
break;
}
}
}
}
// return output
mitk::DiffusionImageHeaderInformation::Pointer
mitk::DicomDiffusionImageHeaderReader::GetOutput()
{
return m_Output;
}
void mitk::DicomDiffusionImageHeaderReader::ReadPublicTags()
{
mitk::LocaleSwitch localeSwitch("C");
VolumeReaderType::DictionaryArrayRawPointer inputDict
= m_VolumeReader->GetMetaDataDictionaryArray();
// load in all public tags
m_nSlice = inputDict->size();
std::string tag;
tag.clear();
itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0008|103e", tag );
this->m_Output->seriesDescription = tag.c_str();
tag.clear();
itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0020|0011", tag );
this->m_Output->seriesNumber = atoi(tag.c_str());
tag.clear();
itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0010|0010", tag );
this->m_Output->patientName = tag.c_str();
tag.clear();
itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0028|0010", tag );
this->m_Output->nRows = atoi( tag.c_str() );
tag.clear();
itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0028|0011", tag );
this->m_Output->nCols = atoi( tag.c_str() );
tag.clear();
itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0028|0030", tag );
sscanf( tag.c_str(), "%f\\%f", &this->m_Output->xRes, &this->m_Output->yRes );
tag.clear();
itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0020|0032", tag );
sscanf( tag.c_str(), "%f\\%f\\%f", &this->m_Output->xOrigin, &this->m_Output->yOrigin, &this->m_Output->zOrigin );
tag.clear();
itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0018|0050", tag );
this->m_Output->sliceThickness = atof( tag.c_str() );
tag.clear();
itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0018|0088", tag );
this->m_Output->sliceSpacing = atof( tag.c_str() );
// figure out how many slices are there in a volume, each unique
// SliceLocation represent one slice
for (int k = 0; k < m_nSlice; k++)
{
tag.clear();
itk::ExposeMetaData<std::string> ( *(*inputDict)[k], "0020|1041", tag);
float sliceLocation = atof( tag.c_str() );
InsertUnique( m_sliceLocations, sliceLocation );
}
// check ImageOrientationPatient and figure out slice direction in
// L-P-I (right-handed) system.
// In Dicom, the coordinate frame is L-P by default. Look at
// http://medical.nema.org/dicom/2007/07_03pu.pdf , page 301
tag.clear();
itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0020|0037", tag );
float xRow, yRow, zRow, xCol, yCol, zCol, xSlice, ySlice, zSlice /*, orthoSliceSpacing*/;
sscanf( tag.c_str(), "%f\\%f\\%f\\%f\\%f\\%f", &xRow, &yRow, &zRow, &xCol, &yCol, &zCol );
// In Dicom, the measurement frame is L-P by default. Look at
// http://medical.nema.org/dicom/2007/07_03pu.pdf , page 301, in
// order to make this compatible with Slicer's RAS frame, we
// multiply the direction cosines by the negatives of the resolution
// (resolution is required by nrrd format). Direction cosine is not
// affacted since the resulting frame is still a right-handed frame.
xRow = -xRow;
yRow = -yRow;
xCol = -xCol;
yCol = -yCol;
// Cross product, this gives I-axis direction
xSlice = (yRow*zCol-zRow*yCol)*this->m_Output->sliceSpacing;
ySlice = (zRow*xCol-xRow*zCol)*this->m_Output->sliceSpacing;
zSlice = (xRow*yCol-yRow*xCol)*this->m_Output->sliceSpacing;
xRow *= this->m_Output->xRes;
yRow *= this->m_Output->xRes;
zRow *= this->m_Output->xRes;
xCol *= this->m_Output->yRes;
yCol *= this->m_Output->yRes;
zCol *= this->m_Output->yRes;
this->m_Output->xRow = xRow;
this->m_Output->yRow = yRow;
this->m_Output->zRow = zRow;
this->m_Output->xCol = xCol;
this->m_Output->yCol = yCol;
this->m_Output->zCol = zCol;
this->m_Output->xSlice = xSlice;
this->m_Output->ySlice = ySlice;
this->m_Output->zSlice = zSlice;
}
void mitk::DicomDiffusionImageHeaderReader::ReadPublicTags2()
{
if (!m_SliceOrderIS)
{
this->m_Output->xSlice = -this->m_Output->xSlice;
this->m_Output->ySlice = -this->m_Output->ySlice;
this->m_Output->zSlice = -this->m_Output->zSlice;
}
}
void mitk::DicomDiffusionImageHeaderReader::TransformGradients()
{
// transform gradient directions into RAS frame
if ( !m_SliceOrderIS )
{
this->m_Output->DiffusionVector[2] = -this->m_Output->DiffusionVector[2]; // I -> S
}
}
diff --git a/Modules/DiffusionCore/DicomImport/mitkDicomDiffusionImageHeaderReader.h b/Modules/DiffusionCore/DicomImport/mitkDicomDiffusionImageHeaderReader.h
index baa1917..9837e26 100644
--- a/Modules/DiffusionCore/DicomImport/mitkDicomDiffusionImageHeaderReader.h
+++ b/Modules/DiffusionCore/DicomImport/mitkDicomDiffusionImageHeaderReader.h
@@ -1,115 +1,115 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkDicomDiffusionImageHeaderReader_h__
#define __mitkDicomDiffusionImageHeaderReader_h__
#include <MitkDiffusionCoreExports.h>
#include <mitkFileReader.h>
#include "itkImageSeriesReader.h"
#include "itkImageFileReader.h"
#include "itkImage.h"
#include "itkGDCMImageIO.h"
#include "mitkDiffusionImageHeaderInformation.h"
namespace mitk
{
/**
@brief Reads the header information from a DICOM series and stores it into an output object of type
DiffusionImageHeaderInformation
*/
class MITKDIFFUSIONCORE_EXPORT DicomDiffusionImageHeaderReader : public itk::Object
{
public:
mitkClassMacroItkParent( DicomDiffusionImageHeaderReader, itk::Object );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** En enum to distinguish in processing between the different vendoors */
enum SupportedVendors{
SV_SIEMENS,
SV_SIEMENS_MOSAIC,
SV_PHILIPS,
SV_GE,
SV_UNKNOWN_VENDOR
};
typedef std::vector< std::string > FileNamesContainer;
typedef short PixelValueType;
typedef itk::Image< PixelValueType, 2 > SliceType;
typedef itk::Image< PixelValueType, 3 > VolumeType;
typedef itk::ImageSeriesReader< VolumeType > VolumeReaderType;
typedef itk::ImageFileReader< SliceType > SliceReaderType;
typedef itk::GDCMImageIO ImageIOType;
/** Set the dicom file names to be considered */
void SetSeriesDicomFilenames(FileNamesContainer dicomFilenames)
{ this->m_DicomFilenames = dicomFilenames; }
void SetGdcmIO(ImageIOType::Pointer gdcmIO)
{ this->m_GdcmIO = gdcmIO; }
/** Set the volume reader in case the default volume reader shouldn't be used */
void SetVolumeReader(VolumeReaderType::Pointer volumeReader)
{ this->m_VolumeReader = volumeReader; }
/** Set the output object that will contain the read-in information after update */
void SetOutputPointer(DiffusionImageHeaderInformation::Pointer output)
{ this->m_Output = output; }
/** do the work */
virtual void Update();
/** return output */
DiffusionImageHeaderInformation::Pointer GetOutput();
/** identify vendor */
SupportedVendors GetVendorID();
protected:
/** Default c'tor */
DicomDiffusionImageHeaderReader();
/** Default d'tor */
~DicomDiffusionImageHeaderReader() override;
void ReadPublicTags();
void ReadPublicTags2();
void TransformGradients();
FileNamesContainer m_DicomFilenames;
DiffusionImageHeaderInformation::Pointer m_Output;
ImageIOType::Pointer m_GdcmIO;
VolumeReaderType::Pointer m_VolumeReader;
bool m_SliceOrderIS;
bool m_SingleSeries;
int m_nSlice;
std::vector<float> m_sliceLocations;
};
}
#endif
diff --git a/Modules/DiffusionCore/DicomImport/mitkDicomDiffusionImageReader.cpp b/Modules/DiffusionCore/DicomImport/mitkDicomDiffusionImageReader.cpp
index c2cf684..03a4556 100644
--- a/Modules/DiffusionCore/DicomImport/mitkDicomDiffusionImageReader.cpp
+++ b/Modules/DiffusionCore/DicomImport/mitkDicomDiffusionImageReader.cpp
@@ -1,141 +1,141 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkDicomDiffusionImageReader_cpp
#define __mitkDicomDiffusionImageReader_cpp
#include "mitkDicomDiffusionImageReader.h"
#include "itkImageSeriesReader.h"
namespace mitk
{
template <class TPixelType, const int TDimension>
void DicomDiffusionImageReader<TPixelType, TDimension>
::PrintSelf(std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf(os, indent);
}
template <class TPixelType, const int TDimension>
void DicomDiffusionImageReader<TPixelType, TDimension>
::GenerateOutputInformation(void)
{
typename OutputImageType::Pointer output = this->GetOutput();
typedef itk::ImageSeriesReader<InputImageType> ReaderType;
// Read the first (or last) volume and use its size.
if (m_Headers.size() > 0)
{
typename ReaderType::Pointer reader = ReaderType::New();
try
{
// Read the image
reader->SetFileNames (m_Headers[0]->m_DicomFilenames);
reader->UpdateOutputInformation();
output->SetSpacing( reader->GetOutput()->GetSpacing() ); // Set the image spacing
output->SetOrigin( reader->GetOutput()->GetOrigin() ); // Set the image origin
output->SetDirection( reader->GetOutput()->GetDirection() ); // Set the image direction
output->SetLargestPossibleRegion( reader->GetOutput()->GetLargestPossibleRegion() );
output->SetVectorLength( m_Headers.size() );
}
catch (itk::ExceptionObject &e)
{
throw e;
}
}
else
{
itkExceptionMacro(<< "At least one filename is required." );
}
}
template <class TPixelType, const int TDimension>
void
DicomDiffusionImageReader<TPixelType, TDimension>
::EnlargeOutputRequestedRegion(itk::DataObject *output)
{
typename OutputImageType::Pointer out = dynamic_cast<OutputImageType*>(output);
out->SetRequestedRegion( out->GetLargestPossibleRegion() );
}
template <class TPixelType, const int TDimension>
void DicomDiffusionImageReader<TPixelType, TDimension>
::GenerateData()
{
typedef itk::ImageSeriesReader<InputImageType> ReaderType;
typename OutputImageType::Pointer output = this->GetOutput();
typedef typename OutputImageType::RegionType RegionType;
RegionType requestedRegion = output->GetRequestedRegion();
// Each file must have the same size.
SizeType validSize = requestedRegion.GetSize();
int numberOfVolumes = static_cast<int>(m_Headers.size());
// Allocate the output buffer
output->SetBufferedRegion( requestedRegion );
output->Allocate();
itk::ProgressReporter progress(this, 0,
m_Headers.size(),
m_Headers.size());
itk::ImageRegionIterator<OutputImageType> ot (output, requestedRegion );
typename OutputImageType::PixelType vec;
for (int i = 0; i < numberOfVolumes; i ++)
{
MITK_INFO << "Loading volume " << i+1 << "/" << numberOfVolumes;
typename ReaderType::Pointer reader = ReaderType::New();
reader->SetFileNames(m_Headers[i]->m_DicomFilenames);
reader->UpdateLargestPossibleRegion();
if (reader->GetOutput()->GetRequestedRegion().GetSize() != validSize)
{
itkExceptionMacro(<< "Size mismatch!");
}
itk::ImageRegionConstIterator<InputImageType> it (reader->GetOutput(),
reader->GetOutput()->GetLargestPossibleRegion());
while (!it.IsAtEnd())
{
vec = ot.Get();
vec.SetElement(i, it.Get());
ot.Set(vec);
++it;
++ot;
}
ot.GoToBegin();
progress.CompletedPixel();
}
}
} //namespace MITK
#endif
diff --git a/Modules/DiffusionCore/DicomImport/mitkDicomDiffusionImageReader.h b/Modules/DiffusionCore/DicomImport/mitkDicomDiffusionImageReader.h
index 7bd4cfb..2b6eff2 100644
--- a/Modules/DiffusionCore/DicomImport/mitkDicomDiffusionImageReader.h
+++ b/Modules/DiffusionCore/DicomImport/mitkDicomDiffusionImageReader.h
@@ -1,102 +1,102 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkDicomDiffusionImageReader_h
#define __mitkDicomDiffusionImageReader_h
#include "itkImageSource.h"
#include "itkVectorImage.h"
#include "mitkDiffusionImageHeaderInformation.h"
#include "itkDataObject.h"
#include "mitkCommon.h"
namespace mitk
{
/** \brief Reads in the image data stored as DICOM series. The series is specified by a HeaderContainer
*/
template <class TPixelType, const int TDimension>
class DicomDiffusionImageReader : public itk::ImageSource< itk::VectorImage< TPixelType, TDimension > >
{
public:
typedef itk::VectorImage< TPixelType, TDimension > OutputImageType;
typedef itk::Image<TPixelType, TDimension > InputImageType;
typedef itk::ImageSource< OutputImageType > ImageSourceType;
mitkClassMacro( DicomDiffusionImageReader, ImageSourceType );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** The size of the output image. */
typedef typename OutputImageType::SizeType SizeType;
/** The region of the output image. */
typedef typename OutputImageType::RegionType ImageRegionType;
typedef std::vector<DiffusionImageHeaderInformation::Pointer> HeaderContainer;
/** Set the vector of strings that contains the file names. Files
* are processed in sequential order. */
void SetHeaders (const HeaderContainer &headers)
{
if ( m_Headers != headers)
{
m_Headers = headers;
this->Modified();
}
}
const HeaderContainer & GetHeaders() const
{
return m_Headers;
}
/** Prepare the allocation of the output image during the first back
* propagation of the pipeline. */
virtual void GenerateOutputInformation(void);
/** Give the reader a chance to indicate that it will produce more
* output than it was requested to produce. ImageSeriesReader cannot
* currently read a portion of an image (since the ImageIO objects
* cannot read a portion of an image), so the ImageSeriesReader must
* enlarge the RequestedRegion to the size of the image on disk. */
virtual void EnlargeOutputRequestedRegion(itk::DataObject *output);
protected:
void PrintSelf(std::ostream& os, itk::Indent indent) const;
/** Does the real work. */
virtual void GenerateData();
/** A list of filenames to be processed. */
HeaderContainer m_Headers;
/** The number of independent variables in the images that comprise
* the series. */
int m_NumberOfDimensionsInImage;
private:
void operator=(const Self&); //purposely not implemented
};
} //namespace MITK
#include "mitkDicomDiffusionImageReader.cpp"
#endif // __mitkDicomDiffusionImageReader_h
diff --git a/Modules/DiffusionCore/DicomImport/mitkDiffusionDICOMFileReader.cpp b/Modules/DiffusionCore/DicomImport/mitkDiffusionDICOMFileReader.cpp
index 5edac04..ea82230 100644
--- a/Modules/DiffusionCore/DicomImport/mitkDiffusionDICOMFileReader.cpp
+++ b/Modules/DiffusionCore/DicomImport/mitkDiffusionDICOMFileReader.cpp
@@ -1,437 +1,437 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkDiffusionDICOMFileReader.h"
#include "mitkDiffusionDICOMFileReaderHelper.h"
#include "mitkDiffusionHeaderSiemensDICOMFileReader.h"
#include "mitkDiffusionHeaderSiemensMosaicDICOMFileReader.h"
#include "mitkDiffusionHeaderGEDICOMFileReader.h"
#include "mitkDiffusionHeaderPhilipsDICOMFileReader.h"
#include <mitkDiffusionPropertyHelper.h>
#include <mitkITKImageImport.h>
#include "mitkStringProperty.h"
#include <mitkImageCast.h>
static void PerformHeaderAnalysis( mitk::DiffusionHeaderDICOMFileReader::DICOMHeaderListType headers )
{
unsigned int images = headers.size();
unsigned int unweighted_images = 0;
unsigned int weighted_images = 0;
mitk::DiffusionHeaderDICOMFileReader::DICOMHeaderListType::const_iterator c_iter = headers.begin();
while( c_iter != headers.end() )
{
const mitk::DiffusionImageDICOMHeaderInformation h = *c_iter;
if( h.baseline ) unweighted_images++;
if( h.b_value > 0 ) weighted_images++;
++c_iter;
}
MITK_INFO << " :: Analyzed volumes " << images << "\n"
<< " :: \t"<< unweighted_images << " b = 0" << "\n"
<< " :: \t"<< weighted_images << " b > 0";
}
mitk::DiffusionDICOMFileReader::DiffusionDICOMFileReader()
{
m_ApplyRotationToGradients = true;
m_ResolveMosaic = true;
}
mitk::DiffusionDICOMFileReader::~DiffusionDICOMFileReader()
{
}
bool mitk::DiffusionDICOMFileReader
::LoadImages()
{
unsigned int numberOfOutputs = this->GetNumberOfOutputs();
bool success = true;
for(unsigned int o = 0; o < numberOfOutputs; ++o)
{
success &= this->LoadSingleOutputImage( this->m_OutputHeaderContainer.at(o),
this->InternalGetOutput(o), this->m_IsMosaicData.at(o) );
}
return success;
}
bool mitk::DiffusionDICOMFileReader
::LoadSingleOutputImage( DiffusionHeaderDICOMFileReader::DICOMHeaderListType retrievedHeader,
DICOMImageBlockDescriptor& block, bool is_mosaic)
{
// prepare data reading
DiffusionDICOMFileReaderHelper helper;
DiffusionDICOMFileReaderHelper::VolumeFileNamesContainer filenames;
const DICOMImageFrameList& frames = block.GetImageFrameList();
int numberOfDWImages = block.GetIntProperty("timesteps", 1);
int numberOfFramesPerDWImage = frames.size() / numberOfDWImages;
assert( int( double((double) frames.size() / (double) numberOfDWImages)) == numberOfFramesPerDWImage );
for( int idx = 0; idx < numberOfDWImages; idx++ )
{
std::vector< std::string > FileNamesPerVolume;
auto timeStepStart = frames.begin() + idx * numberOfFramesPerDWImage;
auto timeStepEnd = frames.begin() + (idx+1) * numberOfFramesPerDWImage;
for (auto frameIter = timeStepStart;
frameIter != timeStepEnd;
++frameIter)
{
FileNamesPerVolume.push_back( (*frameIter)->Filename );
}
filenames.push_back( FileNamesPerVolume );
}
// TODO : only prototyping to test loading of diffusion images
// we need some solution for the different types
mitk::Image::Pointer output_image = mitk::Image::New();
mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer directions =
mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::New();
double max_bvalue = 0;
for( int idx = 0; idx < numberOfDWImages; idx++ )
{
DiffusionImageDICOMHeaderInformation header = retrievedHeader.at(idx);
if( max_bvalue < header.b_value )
max_bvalue = header.b_value;
}
// normalize the retrieved gradient directions according to the set b-value (maximal one)
for( int idx = 0; idx < numberOfDWImages; idx++ )
{
DiffusionImageDICOMHeaderInformation header = retrievedHeader.at(idx);
mitk::DiffusionPropertyHelper::GradientDirectionType grad = header.g_vector;
grad.normalize();
grad *= sqrt( header.b_value / max_bvalue );
directions->push_back( grad );
}
// initialize the output image
mitk::DiffusionPropertyHelper::SetOriginalGradientContainer(output_image, directions);
mitk::DiffusionPropertyHelper::SetReferenceBValue(output_image, max_bvalue);
if( is_mosaic && this->m_ResolveMosaic )
{
mitk::DiffusionHeaderSiemensMosaicDICOMFileReader::Pointer mosaic_reader =
mitk::DiffusionHeaderSiemensMosaicDICOMFileReader::New();
// retrieve the remaining meta-information needed for mosaic reconstruction
// it suffices to get it exemplatory from the first file in the file list
mosaic_reader->RetrieveMosaicInformation( filenames.at(0).at(0) );
mitk::MosaicDescriptor mdesc = mosaic_reader->GetMosaicDescriptor();
mitk::CastToMitkImage( helper.LoadMosaicToVector<short, 3>( filenames, mdesc ), output_image );
}
else
{
mitk::CastToMitkImage( helper.LoadToVector<short, 3>( filenames ), output_image );
}
mitk::DiffusionPropertyHelper::SetApplyMatrixToGradients(output_image, m_ApplyRotationToGradients);
mitk::DiffusionPropertyHelper::InitializeImage(output_image);
output_image->SetProperty("diffusion.dicom.importname", mitk::StringProperty::New( helper.GetOutputName(filenames) ) );
block.SetMitkImage( (mitk::Image::Pointer) output_image );
return block.GetMitkImage().IsNotNull();
}
std::vector<std::string> mitk::DiffusionDICOMFileReader::patient_ids() const
{
return m_patient_ids;
}
std::vector<std::string> mitk::DiffusionDICOMFileReader::patient_names() const
{
return m_patient_names;
}
std::vector<std::string> mitk::DiffusionDICOMFileReader::study_instance_uids() const
{
return m_study_instance_uids;
}
std::vector<std::string> mitk::DiffusionDICOMFileReader::series_instance_uids() const
{
return m_series_instance_uids;
}
std::vector<std::string> mitk::DiffusionDICOMFileReader::frame_of_reference_uids() const
{
return m_frame_of_reference_uids;
}
std::vector<std::string> mitk::DiffusionDICOMFileReader::sop_instance_uids() const
{
return m_sop_instance_uids;
}
void mitk::DiffusionDICOMFileReader
::AnalyzeInputFiles()
{
m_Study_names.clear();
m_Series_names.clear();
this->SetGroup3DandT(true);
Superclass::AnalyzeInputFiles();
// collect output from superclass
size_t number_of_outputs = this->GetNumberOfOutputs();
if(number_of_outputs == 0)
{
MITK_ERROR << "Failed to parse input, retrieved 0 outputs from SeriesGDCMReader ";
}
MITK_INFO("diffusion.dicomreader") << "Retrieved " << number_of_outputs << " outputs.";
std::vector< bool > valid_input_list;
for( unsigned int outputidx = 0; outputidx < this->GetNumberOfOutputs(); outputidx++ )
{
DICOMImageBlockDescriptor block_0 = this->GetOutput(outputidx);
// collect vendor ID from the first output, first image
StringList inputFilename;
DICOMImageFrameInfo::Pointer frame_0 = block_0.GetImageFrameList().at(0);
inputFilename.push_back( frame_0->Filename );
mitk::DiffusionHeaderDICOMFileReader::Pointer headerReader;
bool isMosaic = false;
gdcm::Scanner gdcmScanner;
gdcm::Tag t_sop_instance_uid(0x0008, 0x0018);
gdcm::Tag t_frame_of_reference_uid(0x0020, 0x0052);
gdcm::Tag t_series_instance_uid(0x0020, 0x000E);
gdcm::Tag t_study_instance_uid(0x0020, 0x000D);
gdcm::Tag t_patient_name(0x0010, 0x0010);
gdcm::Tag t_patient_id(0x0010, 0x0020);
gdcm::Tag t_vendor(0x008, 0x0070);
gdcm::Tag t_imagetype(0x0008, 0x0008);
gdcm::Tag t_StudyDescription(0x0008, 0x1030);
gdcm::Tag t_SeriesDescription(0x0008, 0x103E);
// add DICOM Tag for vendor
gdcmScanner.AddTag( t_vendor );
// add DICOM Tag for image type
gdcmScanner.AddTag( t_imagetype );
gdcmScanner.AddTag( t_StudyDescription );
gdcmScanner.AddTag( t_SeriesDescription );
gdcmScanner.AddTag( t_sop_instance_uid );
gdcmScanner.AddTag( t_frame_of_reference_uid );
gdcmScanner.AddTag( t_series_instance_uid );
gdcmScanner.AddTag( t_study_instance_uid );
gdcmScanner.AddTag( t_patient_name );
gdcmScanner.AddTag( t_patient_id );
if( gdcmScanner.Scan( inputFilename ) )
{
// retrieve both vendor and image type
const char* ch_vendor = gdcmScanner.GetValue( frame_0->Filename.c_str(), t_vendor );
const char* ch_image_type = gdcmScanner.GetValue( frame_0->Filename.c_str(), t_imagetype );
const char* temp = gdcmScanner.GetValue( frame_0->Filename.c_str(), t_sop_instance_uid );
if (temp!=nullptr)
m_sop_instance_uids.push_back(std::string(temp));
else
m_sop_instance_uids.push_back("-");
temp = nullptr; temp = gdcmScanner.GetValue( frame_0->Filename.c_str(), t_frame_of_reference_uid );
if (temp!=nullptr)
m_frame_of_reference_uids.push_back(std::string(temp));
else
m_frame_of_reference_uids.push_back("-");
temp = nullptr; temp = gdcmScanner.GetValue( frame_0->Filename.c_str(), t_series_instance_uid );
if (temp!=nullptr)
m_series_instance_uids.push_back(std::string(temp));
else
m_series_instance_uids.push_back("-");
temp = nullptr; temp = gdcmScanner.GetValue( frame_0->Filename.c_str(), t_study_instance_uid );
if (temp!=nullptr)
m_study_instance_uids.push_back(std::string(temp));
else
m_study_instance_uids.push_back("-");
temp = nullptr; temp = gdcmScanner.GetValue( frame_0->Filename.c_str(), t_patient_name );
if (temp!=nullptr)
m_patient_names.push_back(std::string(temp));
else
m_patient_names.push_back("-");
temp = nullptr; temp = gdcmScanner.GetValue( frame_0->Filename.c_str(), t_patient_id );
if (temp!=nullptr)
m_patient_ids.push_back(std::string(temp));
else
m_patient_ids.push_back("-");
if( ch_vendor == nullptr || ch_image_type == nullptr )
{
MITK_WARN << "Unable to retrieve vendor/image information from " << frame_0->Filename.c_str() << "\n" <<
"Output " << outputidx+1 << " is not valid, skipping analysis.";
valid_input_list.push_back(false);
continue;
}
std::string vendor = std::string( ch_vendor );
std::string image_type = std::string( ch_image_type );
MITK_INFO("diffusion.dicomreader") << "Output " << outputidx+1 << " Got vendor: " << vendor << " image type " << image_type;
// parse vendor tag
if( vendor.find("SIEMENS") != std::string::npos || vendor.find("Siemens HealthCare GmbH") != std::string::npos )
{
if( image_type.find("MOSAIC") != std::string::npos )
{
headerReader = mitk::DiffusionHeaderSiemensMosaicDICOMFileReader::New();
isMosaic = true;
}
else
{
headerReader = mitk::DiffusionHeaderSiemensDICOMFileReader::New();
}
}
else if( vendor.find("GE") != std::string::npos )
{
headerReader = mitk::DiffusionHeaderGEDICOMFileReader::New();
}
else if( vendor.find("Philips") != std::string::npos )
{
headerReader = mitk::DiffusionHeaderPhilipsDICOMFileReader::New();
}
else
{
// unknown vendor
}
if( headerReader.IsNull() )
{
MITK_ERROR << "No header reader for given vendor. ";
valid_input_list.push_back(false);
continue;
}
}
else
{
valid_input_list.push_back(false);
continue;
}
bool canread = false;
// iterate over the threeD+t block
int numberOfTimesteps = block_0.GetIntProperty("timesteps", 1);
int framesPerTimestep = block_0.GetImageFrameList().size() / numberOfTimesteps;
for( int idx = 0; idx < numberOfTimesteps; idx++ )
{
int access_idx = idx * framesPerTimestep;
DICOMImageFrameInfo::Pointer frame = this->GetOutput( outputidx ).GetImageFrameList().at( access_idx );
canread = headerReader->ReadDiffusionHeader( frame->Filename );
}
if( canread )
{
// collect the information
mitk::DiffusionHeaderDICOMFileReader::DICOMHeaderListType retrievedHeader = headerReader->GetHeaderInformation();
m_IsMosaicData.push_back(isMosaic);
m_OutputHeaderContainer.push_back( retrievedHeader );
m_OutputReaderContainer.push_back( headerReader );
valid_input_list.push_back(true);
const char* ch_StudyDescription = gdcmScanner.GetValue( frame_0->Filename.c_str(), t_StudyDescription );
const char* ch_SeriesDescription = gdcmScanner.GetValue( frame_0->Filename.c_str(), t_SeriesDescription );
if( ch_StudyDescription != nullptr )
m_Study_names.push_back(ch_StudyDescription);
else
m_Study_names.push_back("-");
if( ch_SeriesDescription != nullptr )
m_Series_names.push_back(ch_SeriesDescription);
else
m_Series_names.push_back("-");
}
}
// check status of the outputs and remove the non-valid
std::vector< DICOMImageBlockDescriptor > valid_outputs;
for ( unsigned int outputidx = 0; outputidx < this->GetNumberOfOutputs(); ++outputidx )
{
if( valid_input_list.at(outputidx) )
{
valid_outputs.push_back( this->InternalGetOutput( outputidx ) );
}
}
// clear complete list
this->ClearOutputs();
this->SetNumberOfOutputs( valid_outputs.size() );
// insert only the valid ones
for ( unsigned int outputidx = 0; valid_outputs.size(); ++outputidx )
this->SetOutput( outputidx, valid_outputs.at( outputidx ) );
for( unsigned int outputidx = 0; outputidx < this->GetNumberOfOutputs(); outputidx++ )
{
// TODO : Analyze outputs + header information, i.e. for the loading confidence
MITK_INFO("diffusion.dicomreader") << "---- DICOM Analysis Report ---- :: Output " << outputidx+1 << " of " << this->GetNumberOfOutputs();
try{
PerformHeaderAnalysis( this->m_OutputHeaderContainer.at( outputidx) );
}
catch( const std::exception& se)
{
MITK_ERROR << "STD Exception " << se.what();
}
MITK_INFO("diffusion.dicomreader") << "===========================================";
}
}
bool mitk::DiffusionDICOMFileReader
::CanHandleFile(const std::string & /* filename */)
{
//FIXME :
return true;
}
diff --git a/Modules/DiffusionCore/DicomImport/mitkDiffusionDICOMFileReader.h b/Modules/DiffusionCore/DicomImport/mitkDiffusionDICOMFileReader.h
index 7376b58..e9f973b 100644
--- a/Modules/DiffusionCore/DicomImport/mitkDiffusionDICOMFileReader.h
+++ b/Modules/DiffusionCore/DicomImport/mitkDiffusionDICOMFileReader.h
@@ -1,92 +1,92 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKDIFFUSIONDICOMFILEREADER_H
#define MITKDIFFUSIONDICOMFILEREADER_H
#include "MitkDiffusionCoreExports.h"
#include "mitkDICOMITKSeriesGDCMReader.h"
#include "mitkDiffusionHeaderDICOMFileReader.h"
#include "mitkClassicDICOMSeriesReader.h"
namespace mitk
{
class MITKDIFFUSIONCORE_EXPORT DiffusionDICOMFileReader
: public ClassicDICOMSeriesReader
{
public:
mitkClassMacro( DiffusionDICOMFileReader, ClassicDICOMSeriesReader )
mitkCloneMacro( DiffusionDICOMFileReader )
itkNewMacro( DiffusionDICOMFileReader )
void AnalyzeInputFiles() override;
bool LoadImages() override;
bool CanHandleFile(const std::string &filename) override;
void SetResolveMosaic( bool flag )
{
m_ResolveMosaic = flag;
}
void SetApplyRotationToGradients( bool apply )
{
m_ApplyRotationToGradients = apply;
}
std::string GetStudyName(int i){ return m_Study_names.at(i); }
std::string GetSeriesName(int i){ return m_Series_names.at(i); }
std::vector<std::string> sop_instance_uids() const;
std::vector<std::string> frame_of_reference_uids() const;
std::vector<std::string> series_instance_uids() const;
std::vector<std::string> study_instance_uids() const;
std::vector<std::string> patient_names() const;
std::vector<std::string> patient_ids() const;
protected:
DiffusionDICOMFileReader();
~DiffusionDICOMFileReader() override;
bool LoadSingleOutputImage( DiffusionHeaderDICOMFileReader::DICOMHeaderListType, DICOMImageBlockDescriptor&, bool);
//mitk::DiffusionHeaderDICOMFileReader::DICOMHeaderListType m_RetrievedHeader;
std::vector< mitk::DiffusionHeaderDICOMFileReader::DICOMHeaderListType > m_OutputHeaderContainer;
std::vector< mitk::DiffusionHeaderDICOMFileReader::Pointer> m_OutputReaderContainer;
std::vector< bool > m_IsMosaicData;
std::vector< std::string > m_Study_names;
std::vector< std::string > m_Series_names;
bool m_ResolveMosaic;
bool m_ApplyRotationToGradients;
std::vector< std::string > m_sop_instance_uids;
std::vector< std::string > m_frame_of_reference_uids;
std::vector< std::string > m_series_instance_uids;
std::vector< std::string > m_study_instance_uids;
std::vector< std::string > m_patient_names;
std::vector< std::string > m_patient_ids;
};
}
#endif // MITKDIFFUSIONDICOMFILEREADER_H
diff --git a/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderDICOMFileReader.cpp b/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderDICOMFileReader.cpp
index 3daef01..2d7725a 100644
--- a/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderDICOMFileReader.cpp
+++ b/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderDICOMFileReader.cpp
@@ -1,82 +1,82 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkDiffusionHeaderDICOMFileReader.h"
mitk::DiffusionHeaderDICOMFileReader
::DiffusionHeaderDICOMFileReader()
{
}
mitk::DiffusionHeaderDICOMFileReader
::~DiffusionHeaderDICOMFileReader()
{
}
mitk::DiffusionHeaderDICOMFileReader::DICOMHeaderListType
mitk::DiffusionHeaderDICOMFileReader
::GetHeaderInformation()
{
if( m_HeaderInformationList.size() < 1 )
{
MITK_WARN << "No information retrieved yet. Call AnalyzeInputFiles first!";
}
return m_HeaderInformationList;
}
bool mitk::RevealBinaryTag(const gdcm::Tag tag, const gdcm::DataSet& dataset, std::string& target)
{
if( dataset.FindDataElement( tag ) )
{
MITK_DEBUG << "Found tag " << tag.PrintAsPipeSeparatedString();
const gdcm::DataElement& de = dataset.GetDataElement( tag );
target = std::string( de.GetByteValue()->GetPointer(),
de.GetByteValue()->GetLength() );
return true;
}
else
{
MITK_DEBUG << "Could not find tag " << tag.PrintAsPipeSeparatedString();
return false;
}
}
bool mitk::RevealBinaryTagC(const gdcm::Tag tag, const gdcm::DataSet& dataset, char * target_array )
{
if( dataset.FindDataElement( tag ) )
{
MITK_DEBUG << "Found tag " << tag.PrintAsPipeSeparatedString();
const gdcm::DataElement& de = dataset.GetDataElement( tag );
size_t bytesize = de.GetValue().GetLength(); // GetLength();
//target_array = new char[bytesize];
memcpy( target_array, de.GetByteValue()->GetPointer(), bytesize);
return true;
}
else
{
MITK_DEBUG << "Could not find tag " << tag.PrintAsPipeSeparatedString();
return false;
}
}
diff --git a/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderDICOMFileReader.h b/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderDICOMFileReader.h
index de12453..600b74e 100644
--- a/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderDICOMFileReader.h
+++ b/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderDICOMFileReader.h
@@ -1,120 +1,120 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKDIFFUSIONHEADERFILEREADER_H
#define MITKDIFFUSIONHEADERFILEREADER_H
#include <MitkDiffusionCoreExports.h>
#include <mitkCommon.h>
#include <itkLightObject.h>
#include <itkObjectFactory.h>
#include "gdcmScanner.h"
#include "gdcmReader.h"
#include <vnl/vnl_vector_fixed.h>
namespace mitk
{
/**
* @brief The DiffusionImageHeaderInformation struct
*/
struct DiffusionImageDICOMHeaderInformation
{
DiffusionImageDICOMHeaderInformation()
: b_value(0),
baseline(false),
isotropic(false)
{
g_vector.fill(0);
}
void Print()
{
MITK_INFO << " DiffusionImageHeaderInformation : \n"
<< " : b value : " << b_value << "\n"
<< " : gradient : " << g_vector << "\n"
<< " : isotropic : " << isotropic << "\n --- \n";
}
unsigned int b_value;
vnl_vector_fixed< double, 3> g_vector;
bool baseline;
bool isotropic;
};
struct DiffusionImageMosaicDICOMHeaderInformation
: public DiffusionImageDICOMHeaderInformation
{
unsigned long n_images;
bool slicenormalup;
};
/**
* @class DiffusionHeaderDICOMFileReader
*
* @brief Abstract class for all vendor specific diffusion file header reader
*
* To provide a diffusion header reader for a new vendor, reimplement the \sa ReadDiffusionHeader method.
*/
class MITKDIFFUSIONCORE_EXPORT DiffusionHeaderDICOMFileReader
: public itk::LightObject
{
public:
typedef std::vector< DiffusionImageDICOMHeaderInformation > DICOMHeaderListType;
mitkClassMacroItkParent( DiffusionHeaderDICOMFileReader, itk::LightObject )
itkSimpleNewMacro( Self )
/**
* @brief IsDiffusionHeader Parse the given dicom file and collect the special diffusion image information
* @return
*/
virtual bool ReadDiffusionHeader( std::string ){ return false; }
DICOMHeaderListType GetHeaderInformation();
protected:
DiffusionHeaderDICOMFileReader();
~DiffusionHeaderDICOMFileReader() override;
DICOMHeaderListType m_HeaderInformationList;
};
/**
* @brief Retrieve the value of a gdcm tag to the given string
*
* @param tag the gdcm::Tag to be search for
* @param dataset a gdcm::DataSet to look into
* @param target a string to store the value of the given tag if found
* @param verbose make some output
*
* @return true if a string was found, false otherwise
*/
bool RevealBinaryTag(const gdcm::Tag tag, const gdcm::DataSet& dataset, std::string& target);
bool RevealBinaryTagC(const gdcm::Tag tag, const gdcm::DataSet& dataset, char* target_array );
} // end namespace mitk
#endif // MITKDIFFUSIONHEADERFILEREADER_H
diff --git a/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderPhilipsDICOMFileReader.cpp b/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderPhilipsDICOMFileReader.cpp
index fee3ce5..caa6cb4 100644
--- a/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderPhilipsDICOMFileReader.cpp
+++ b/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderPhilipsDICOMFileReader.cpp
@@ -1,97 +1,97 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkDiffusionHeaderPhilipsDICOMFileReader.h"
#include <sstream>
#include <vnl/vnl_math.h>
mitk::DiffusionHeaderPhilipsDICOMFileReader::DiffusionHeaderPhilipsDICOMFileReader()
{
}
mitk::DiffusionHeaderPhilipsDICOMFileReader::~DiffusionHeaderPhilipsDICOMFileReader()
{
}
bool mitk::DiffusionHeaderPhilipsDICOMFileReader::ReadDiffusionHeader(std::string filename)
{
gdcm::Reader gdcmReader;
gdcmReader.SetFileName( filename.c_str() );
gdcmReader.Read();
gdcm::Tag philips_bvalue_tag( 0x2001, 0x1003 );
//gdcm::Tag philips_gradient_direction( 0x2001, 0x1004 );
DiffusionImageDICOMHeaderInformation header_info;
//std::string tagvalue_string;
//char* pEnd;
// reveal b-value
float bvalue = 0;
if( RevealBinaryTagC( philips_bvalue_tag, gdcmReader.GetFile().GetDataSet(), (char*) &bvalue) )
{
header_info.b_value = std::ceil( bvalue );
if( header_info.b_value == 0)
header_info.baseline = true;
}
else
{
MITK_WARN("diffusion.dicomreader.philips") << "No b-value found. Most probably no diffusion-weighted image.";
return false;
}
gdcm::Tag philips_new_bvalue_tag( 0x0018,0x9087 );
double dbvalue = 0;
if( RevealBinaryTagC( philips_new_bvalue_tag, gdcmReader.GetFile().GetDataSet(), (char*) &dbvalue) )
{
MITK_INFO("philips.dicom.diffusion.bvalue") << dbvalue;
}
if( header_info.baseline )
{
// no direction in unweighted images
header_info.g_vector.fill(0);
}
else
{
MITK_INFO("philips.dicom.diffusion.gradientdir") << "Parsing gradient direction.";
gdcm::Tag philips_gradient_direction_new( 0x0018, 0x9089 );
double gr_dir_arr[3] = {1,0,-1};
if( RevealBinaryTagC( philips_gradient_direction_new, gdcmReader.GetFile().GetDataSet(), (char*) &gr_dir_arr ) )
{
MITK_INFO("philips.dicom.diffusion.gradient") << "(" << gr_dir_arr[0] <<"," << gr_dir_arr[1] <<"," <<gr_dir_arr[2] <<")";
}
header_info.g_vector.copy_in( &gr_dir_arr[0] );
if( header_info.g_vector.two_norm() < vnl_math::eps )
{
header_info.g_vector.fill(1);
header_info.isotropic = true;
}
}
this->m_HeaderInformationList.push_back( header_info );
return true;
}
diff --git a/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderPhilipsDICOMFileReader.h b/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderPhilipsDICOMFileReader.h
index 7fbb2b7..7a66b41 100644
--- a/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderPhilipsDICOMFileReader.h
+++ b/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderPhilipsDICOMFileReader.h
@@ -1,45 +1,45 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKDIFFUSIONHEADERPHILIPSDICOMREADER_H
#define MITKDIFFUSIONHEADERPHILIPSDICOMREADER_H
#include <MitkDiffusionCoreExports.h>
#include "mitkDiffusionHeaderDICOMFileReader.h"
namespace mitk
{
class MITKDIFFUSIONCORE_EXPORT DiffusionHeaderPhilipsDICOMFileReader
: public DiffusionHeaderDICOMFileReader
{
public:
mitkClassMacro( DiffusionHeaderPhilipsDICOMFileReader, DiffusionHeaderDICOMFileReader )
itkNewMacro( Self )
bool ReadDiffusionHeader(std::string filename) override;
protected:
DiffusionHeaderPhilipsDICOMFileReader();
~DiffusionHeaderPhilipsDICOMFileReader() override;
};
}
#endif // MITKDIFFUSIONHEADERPHILIPSDICOMREADER_H
diff --git a/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensDICOMFileReader.cpp b/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensDICOMFileReader.cpp
index 78696a9..40bcc81 100644
--- a/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensDICOMFileReader.cpp
+++ b/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensDICOMFileReader.cpp
@@ -1,250 +1,250 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkDiffusionHeaderSiemensDICOMFileReader.h"
#include "mitkDiffusionHeaderSiemensDICOMFileHelper.h"
#include "mitkDiffusionHeaderDICOMFileReader.h"
#include "gdcmScanner.h"
#include "gdcmReader.h"
#include <vnl/vnl_math.h>
static bool GetTagFromHierarchy( std::vector< gdcm::Tag > hierarchy, const gdcm::Tag& t_tag, const gdcm::DataSet& dataset, gdcm::DataSet& target)
{
if( hierarchy.empty() )
return false;
const gdcm::DataElement& de = dataset.GetDataElement( hierarchy.at(0) );
const auto seq = de.GetValueAsSQ();
if (seq==nullptr)
return false;
// last level of hierarchy, retrieve the first apperance
if( hierarchy.size() == 1 )
{
gdcm::Item& item2 = seq->GetItem(1);
gdcm::DataSet& nestedds2 = item2.GetNestedDataSet();
const gdcm::DataElement& nde2 = nestedds2.GetDataElement( t_tag );
if( !nde2.IsEmpty() )
{
target = nestedds2;
return true;
}
else
{
return false;
}
}
else
{
if( seq->FindDataElement( hierarchy.at(1) ) )
{
for( gdcm::SequenceOfItems::SizeType i=1; i< seq->GetNumberOfItems(); i++ )
{
gdcm::Item& item = seq->GetItem(i);
gdcm::DataSet &nestedds = item.GetNestedDataSet();
// recursive call
return GetTagFromHierarchy( std::vector< gdcm::Tag >( hierarchy.begin() + 1, hierarchy.end() ), t_tag, nestedds, target);
}
}
return false;
}
}
/**
* @brief Extract b value from the siemens diffusion tag
*/
bool mitk::DiffusionHeaderSiemensDICOMFileReader
::ExtractSiemensDiffusionTagInformation( std::string tag_value, mitk::DiffusionImageDICOMHeaderInformation& values)
{
SiemensDiffusionHeaderType hformat = mitk::GetHeaderType( tag_value );
Siemens_Header_Format specs = this->m_SiemensFormatsCollection.at( hformat );
MITK_DEBUG << " Header format: " << hformat;
MITK_DEBUG << " :: Retrieving b value. ";
std::string::size_type tag_position =
tag_value.find( "B_value", 0 );
if( tag_position == std::string::npos )
{
MITK_ERROR << "No b value information found. ";
return false;
}
std::string value_string = tag_value.substr( tag_position, tag_value.size() - tag_position + 1 );
std::vector<double> value_array;
if( ParseInputString(value_string, value_array, specs) )
{
values.b_value = value_array.at(0);
}
else
{
MITK_INFO("diffusion.dicomreader.siemens") << "No b-value tag found. ";
return false;
}
// search for GradientDirectionInformation if the bvalue is not null
if( values.b_value > 0 )
{
std::string::size_type tag_position = tag_value.find( "DiffusionGradientDirection", 0 );
// Possibly it is a IVIM dataset, i.e. the gradient direction is not relevant
// and possibly either not set or set to zero
if( tag_position == std::string::npos )
{
MITK_WARN << "No gradient direction information, but non-zero b-value. Possibly an IVIM dataset. " << "\n"
<< "Setting gradient to (1,1,1).";
values.isotropic = true;
values.g_vector.fill(1);
return false;
}
value_array.clear();
std::string gradient_direction_str = tag_value.substr( tag_position, tag_value.size() - tag_position + 1 );
if( ParseInputString(gradient_direction_str, value_array, specs) )
{
if( value_array.size() != 3 )
{
MITK_ERROR << " Retrieved gradient information of length " << value_array.size();
return false;
}
for( unsigned int i=0; i<value_array.size(); i++)
{
values.g_vector[i] = value_array.at(i);
}
// Test for isotropic data (i.e. IVIM)
if( values.g_vector.two_norm() < vnl_math::eps )
{
values.g_vector.fill(1);
values.isotropic = true;
}
}
}
else
{
values.baseline = true;
}
return true;
}
mitk::DiffusionHeaderSiemensDICOMFileReader
::DiffusionHeaderSiemensDICOMFileReader()
{
Siemens_Header_Format Siemens_CSA1_Format( 64, sizeof(int32_t), 4, sizeof(int32_t), sizeof(int32_t) );
Siemens_Header_Format Siemens_CSA2_Format( 64, sizeof(int32_t), 4, sizeof(int32_t), sizeof(int32_t) );
m_SiemensFormatsCollection.push_back( Siemens_CSA1_Format );
m_SiemensFormatsCollection.push_back( Siemens_CSA2_Format );
}
mitk::DiffusionHeaderSiemensDICOMFileReader
::~DiffusionHeaderSiemensDICOMFileReader()
{
}
bool mitk::DiffusionHeaderSiemensDICOMFileReader
::ReadDiffusionHeader(std::string filename)
{
gdcm::Reader gdcmReader;
gdcmReader.SetFileName( filename.c_str() );
gdcmReader.Read();
MITK_INFO << " -- Analyzing: " << filename;
bool retVal = false;
const gdcm::DataSet& dataset = gdcmReader.GetFile().GetDataSet();
const gdcm::Tag t_sie_diffusion( 0x0029,0x1010 );
//const gdcm::Tag t_sie_diffusion_vec( 0x0029,0x100e );
//const gdcm::Tag t_sie_diffusion2( 0x0029,0x100c );
std::string siemens_diffusionheader_str;
if( RevealBinaryTag( t_sie_diffusion, dataset, siemens_diffusionheader_str ) )
{
DiffusionImageDICOMHeaderInformation values;
this->ExtractSiemensDiffusionTagInformation( siemens_diffusionheader_str, values );
m_HeaderInformationList.push_back( values );
retVal = true;
}
else
{
const gdcm::Tag t_sie_bvalue( 0x0018, 0x9087);
const gdcm::Tag t_sie_gradient( 0x0021, 0x1146);
std::vector< gdcm::Tag > bv_hierarchy;
bv_hierarchy.push_back( gdcm::Tag(0x5200,0x9230) );
bv_hierarchy.push_back( gdcm::Tag(0x0018,0x9117) );
gdcm::DataSet bvalueset;
GetTagFromHierarchy( bv_hierarchy, t_sie_bvalue, dataset, bvalueset );
DiffusionImageDICOMHeaderInformation values;
double dbvalue = 0;
if( mitk::RevealBinaryTagC( t_sie_bvalue, bvalueset, (char*) &dbvalue) )
{
MITK_INFO("siemens.dicom.diffusion.bvalue") << dbvalue;
values.b_value = std::ceil( dbvalue );
if( values.b_value == 0)
values.baseline = true;
}
if( !values.baseline )
{
std::vector< gdcm::Tag > g_hierarchy;
g_hierarchy.push_back( gdcm::Tag(0x5200,0x9230) );
g_hierarchy.push_back( gdcm::Tag(0x0021,0x11fe) );
GetTagFromHierarchy( g_hierarchy, t_sie_gradient, dataset, bvalueset );
double gr_dir_arr[3] = {1,0,-1};
if( mitk::RevealBinaryTagC( t_sie_gradient, bvalueset, (char*) &gr_dir_arr ) )
{
MITK_INFO("siemens.dicom.diffusion.gradient") << "(" << gr_dir_arr[0] <<"," << gr_dir_arr[1] <<"," <<gr_dir_arr[2] <<")";
}
values.g_vector.copy_in( &gr_dir_arr[0] );
}
if( true )
{
m_HeaderInformationList.push_back( values );
retVal = true;
}
}
return retVal;
}
diff --git a/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensDICOMFileReader.h b/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensDICOMFileReader.h
index 3596970..256c6d7 100644
--- a/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensDICOMFileReader.h
+++ b/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensDICOMFileReader.h
@@ -1,49 +1,49 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKDIFFUSIONHEADERSIEMENSDICOMFILEREADER_H
#define MITKDIFFUSIONHEADERSIEMENSDICOMFILEREADER_H
#include "MitkDiffusionCoreExports.h"
#include "mitkDiffusionHeaderDICOMFileReader.h"
#include "mitkDiffusionHeaderSiemensDICOMFileHelper.h"
namespace mitk
{
class MITKDIFFUSIONCORE_EXPORT DiffusionHeaderSiemensDICOMFileReader
: public DiffusionHeaderDICOMFileReader
{
public:
mitkClassMacro( DiffusionHeaderSiemensDICOMFileReader, DiffusionHeaderDICOMFileReader )
itkNewMacro( Self )
bool ReadDiffusionHeader(std::string filename) override;
protected:
DiffusionHeaderSiemensDICOMFileReader();
~DiffusionHeaderSiemensDICOMFileReader() override;
bool ExtractSiemensDiffusionTagInformation( std::string tag_value, mitk::DiffusionImageDICOMHeaderInformation& values );
std::vector< Siemens_Header_Format > m_SiemensFormatsCollection;
};
}
#endif // MITKDIFFUSIONHEADERSIEMENSDICOMFILEREADER_H
diff --git a/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensMosaicDICOMFileReader.h b/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensMosaicDICOMFileReader.h
index 4629f2b..580f55b 100644
--- a/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensMosaicDICOMFileReader.h
+++ b/Modules/DiffusionCore/DicomImport/mitkDiffusionHeaderSiemensMosaicDICOMFileReader.h
@@ -1,53 +1,53 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKDIFFUSIONHEADERSIEMENSMOSAICDICOMFILEREADER_H
#define MITKDIFFUSIONHEADERSIEMENSMOSAICDICOMFILEREADER_H
#include "mitkDiffusionHeaderSiemensDICOMFileReader.h"
#include "mitkDiffusionDICOMFileReaderHelper.h"
namespace mitk
{
class MITKDIFFUSIONCORE_EXPORT DiffusionHeaderSiemensMosaicDICOMFileReader
: public DiffusionHeaderSiemensDICOMFileReader
{
public:
mitkClassMacro( DiffusionHeaderSiemensMosaicDICOMFileReader,
DiffusionHeaderSiemensDICOMFileReader )
itkNewMacro( Self )
bool ReadDiffusionHeader(std::string filename) override;
mitk::MosaicDescriptor GetMosaicDescriptor()
{
return m_MosaicDescriptor;
}
void RetrieveMosaicInformation(std::string filename);
protected:
DiffusionHeaderSiemensMosaicDICOMFileReader();
~DiffusionHeaderSiemensMosaicDICOMFileReader() override;
mitk::MosaicDescriptor m_MosaicDescriptor;
};
}
#endif // MITKDIFFUSIONHEADERSIEMENSMOSAICDICOMFILEREADER_H
diff --git a/Modules/DiffusionCore/DicomImport/mitkGEDicomDiffusionImageHeaderReader.cpp b/Modules/DiffusionCore/DicomImport/mitkGEDicomDiffusionImageHeaderReader.cpp
index de908ed..94b9315 100644
--- a/Modules/DiffusionCore/DicomImport/mitkGEDicomDiffusionImageHeaderReader.cpp
+++ b/Modules/DiffusionCore/DicomImport/mitkGEDicomDiffusionImageHeaderReader.cpp
@@ -1,127 +1,127 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkGEDicomDiffusionImageHeaderReader.h"
#include <mitkLocaleSwitch.h>
#include "gdcmGlobal.h"
#include "gdcmDict.h"
#include "gdcmDicts.h"
#include "gdcmDictEntry.h"
#include "gdcmDictEntry.h"
#include "gdcmDict.h"
#include "gdcmFile.h"
#include "gdcmSerieHelper.h"
mitk::GEDicomDiffusionImageHeaderReader::GEDicomDiffusionImageHeaderReader()
{
}
mitk::GEDicomDiffusionImageHeaderReader::~GEDicomDiffusionImageHeaderReader()
{
}
// do the work
void mitk::GEDicomDiffusionImageHeaderReader::Update()
{
// check if there are filenames
if(m_DicomFilenames.size())
{
mitk::LocaleSwitch localeSwitch("C");
// adapted from namic-sandbox
// DicomToNrrdConverter.cxx
VolumeReaderType::DictionaryArrayRawPointer inputDict
= m_VolumeReader->GetMetaDataDictionaryArray();
ReadPublicTags();
float x0, y0, z0;
float x1, y1, z1;
std::string tag;
tag.clear();
itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0020|0032", tag );
sscanf( tag.c_str(), "%f\\%f\\%f", &x0, &y0, &z0 );
std::cout << "Slice 0: " << tag << std::endl;
tag.clear();
// assume volume interleaving, i.e. the second dicom file stores
// the second slice in the same volume as the first dicom file
itk::ExposeMetaData<std::string> ( *(*inputDict)[1], "0020|0032", tag );
sscanf( tag.c_str(), "%f\\%f\\%f", &x1, &y1, &z1 );
std::cout << "Slice 1: " << tag << std::endl;
x1 -= x0; y1 -= y0; z1 -= z0;
x0 = x1*this->m_Output->xSlice + y1*this->m_Output->ySlice + z1*this->m_Output->zSlice;
if (x0 < 0)
{
m_SliceOrderIS = false;
}
ReadPublicTags2();
int nSliceInVolume;
int nVolume;
nSliceInVolume = m_sliceLocations.size();
nVolume = m_nSlice/nSliceInVolume;
// assume volume interleaving
std::cout << "Number of Slices: " << m_nSlice << std::endl;
std::cout << "Number of Volume: " << nVolume << std::endl;
std::cout << "Number of Slices in each volume: " << nSliceInVolume << std::endl;
for (int k = 0; k < m_nSlice; k += nSliceInVolume)
{
tag.clear();
bool exist = itk::ExposeMetaData<std::string> ( *(*inputDict)[k], "0043|1039", tag);
float b = atof( tag.c_str() );
this->m_Output->bValue = b;
vnl_vector_fixed<double, 3> vect3d;
if (!exist || b == 0)
{
vect3d.fill( 0 );
this->m_Output->DiffusionVector = vect3d;
continue;
}
vect3d.fill( 0 );
tag.clear();
itk::ExposeMetaData<std::string> ( *(*inputDict)[k], "0019|10bb", tag);
vect3d[0] = atof( tag.c_str() );
tag.clear();
itk::ExposeMetaData<std::string> ( *(*inputDict)[k], "0019|10bc", tag);
vect3d[1] = atof( tag.c_str() );
tag.clear();
itk::ExposeMetaData<std::string> ( *(*inputDict)[k], "0019|10bd", tag);
vect3d[2] = atof( tag.c_str() );
vect3d.normalize();
this->m_Output->DiffusionVector = vect3d;
}
TransformGradients();
}
}
diff --git a/Modules/DiffusionCore/DicomImport/mitkGEDicomDiffusionImageHeaderReader.h b/Modules/DiffusionCore/DicomImport/mitkGEDicomDiffusionImageHeaderReader.h
index 7552bfd..62dc6d6 100644
--- a/Modules/DiffusionCore/DicomImport/mitkGEDicomDiffusionImageHeaderReader.h
+++ b/Modules/DiffusionCore/DicomImport/mitkGEDicomDiffusionImageHeaderReader.h
@@ -1,48 +1,48 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkGEDicomDiffusionImageHeaderReader_h__
#define __mitkGEDicomDiffusionImageHeaderReader_h__
#include "mitkDicomDiffusionImageHeaderReader.h"
namespace mitk
{
class GEDicomDiffusionImageHeaderReader : public DicomDiffusionImageHeaderReader
{
public:
mitkClassMacro( GEDicomDiffusionImageHeaderReader, DicomDiffusionImageHeaderReader );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
void Update() override;
protected:
GEDicomDiffusionImageHeaderReader();
~GEDicomDiffusionImageHeaderReader() override;
};
}
#endif
diff --git a/Modules/DiffusionCore/DicomImport/mitkGroupDiffusionHeadersFilter.cpp b/Modules/DiffusionCore/DicomImport/mitkGroupDiffusionHeadersFilter.cpp
index 0449dda..1834140 100644
--- a/Modules/DiffusionCore/DicomImport/mitkGroupDiffusionHeadersFilter.cpp
+++ b/Modules/DiffusionCore/DicomImport/mitkGroupDiffusionHeadersFilter.cpp
@@ -1,157 +1,157 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkGroupDiffusionHeadersFilter.h"
mitk::GroupDiffusionHeadersFilter::GroupDiffusionHeadersFilter()
{
// Modify superclass default values, may be overridden by subclasses
this->SetNumberOfRequiredInputs( 1 );
this->SetNumberOfRequiredOutputs( 4 );
}
mitk::GroupDiffusionHeadersFilter::~GroupDiffusionHeadersFilter()
{}
void mitk::GroupDiffusionHeadersFilter::GenerateOutputInformation()
{
}
void mitk::GroupDiffusionHeadersFilter::Update()
{
InputType input = static_cast<InputType>( this->GetInput( ) );
this->SetNthOutput(0, input);
InputType dwi;
InputType zerodwi;
InputType other;
bool foundDWI = false;
// check each series' first image
unsigned int size = input.size();
HeaderPointer header;
HeaderPointer dwiHeader;
for ( unsigned int i = 0 ; i < size ; ++i )
{
header = input[i];
// list of files
if( header->bValue > 0)
{
header->headerGroup = DHG_NonZeroDiffusionWeighted;
if(!foundDWI)
dwiHeader = header;
foundDWI = true;
}
else
{
header->headerGroup = DHG_ZeroDiffusionWeighted;
}
}
if(foundDWI)
{
for ( unsigned int i = 0 ; i < size ; ++i )
{
header = input[i];
// list of files
if( !header->isIdentical(dwiHeader))
{
header->headerGroup = DHG_Other;
}
}
}
else
{
for ( unsigned int i = 0 ; i < size ; ++i )
{
header = input[i];
header->headerGroup = DHG_Other;
}
}
for ( unsigned int i = 0 ; i < size ; ++i )
{
header = input[i];
switch (header->headerGroup)
{
case DHG_Other:
other.push_back(header);
break;
case DHG_ZeroDiffusionWeighted:
zerodwi.push_back(header);
break;
case DHG_NonZeroDiffusionWeighted:
dwi.push_back(header);
break;
case DHG_NotYetGrouped:
break;
}
}
this->SetNthOutput(1, dwi);
this->SetNthOutput(2, zerodwi);
this->SetNthOutput(3, other);
}
void mitk::GroupDiffusionHeadersFilter::SetInput( mitk::GroupDiffusionHeadersFilter::InputType input )
{
// Process object is not const-correct so the const_cast is required here
m_Input = input;
}
void mitk::GroupDiffusionHeadersFilter::SetInput( const unsigned int& /*idx*/, mitk::GroupDiffusionHeadersFilter::InputType input )
{
this->SetInput( input );
}
mitk::GroupDiffusionHeadersFilter::InputType mitk::GroupDiffusionHeadersFilter::GetInput( void )
{
return m_Input;
}
mitk::GroupDiffusionHeadersFilter::InputType mitk::GroupDiffusionHeadersFilter::GetInput( const unsigned int& /*idx*/ )
{
return this->GetInput();
}
mitk::GroupDiffusionHeadersFilter::OutputType
mitk::GroupDiffusionHeadersFilter::GetOutput()
{
return m_Output;
}
void mitk::GroupDiffusionHeadersFilter::SetNthOutput( const unsigned int& idx, InputType output )
{
if(idx >= m_Output.size())
m_Output.resize(idx+1);
m_Output[idx] = output;
}
void mitk::GroupDiffusionHeadersFilter::operator=( const mitk::GroupDiffusionHeadersFilter::Self& )
{}
diff --git a/Modules/DiffusionCore/DicomImport/mitkGroupDiffusionHeadersFilter.h b/Modules/DiffusionCore/DicomImport/mitkGroupDiffusionHeadersFilter.h
index 1717a7c..681fd0e 100644
--- a/Modules/DiffusionCore/DicomImport/mitkGroupDiffusionHeadersFilter.h
+++ b/Modules/DiffusionCore/DicomImport/mitkGroupDiffusionHeadersFilter.h
@@ -1,110 +1,110 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _mitkGroupDiffusionHeadersFilter_h
#define _mitkGroupDiffusionHeadersFilter_h
#include <MitkDiffusionCoreExports.h>
#include "mitkBaseProcess.h"
#include "mitkDiffusionImageHeaderInformation.h"
namespace mitk
{
/**
* @brief Groups Headers containing Diffusion Information
* @ingroup Process
*/
class MITKDIFFUSIONCORE_EXPORT GroupDiffusionHeadersFilter : public BaseProcess
{
public:
mitkClassMacro( GroupDiffusionHeadersFilter, BaseProcess );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
typedef mitk::DiffusionImageHeaderInformation HeaderType;
typedef HeaderType::Pointer HeaderPointer;
typedef std::vector<HeaderPointer> InputType;
typedef std::vector<InputType> OutputType;
/**
* Sets the input of this process object
* @param input the input
*/
virtual void SetInput( InputType input );
/**
* Sets the input n'th of this process object
* @param idx the number associated with the given input
*/
virtual void SetInput( const unsigned int& idx, InputType input );
/**
* Sets the input n'th of this process object
* @param idx the number associated with the given input
*/
virtual void SetNthOutput( const unsigned int& idx, InputType output );
/**
* @returns the input tree of the process object
*/
InputType GetInput( void );
/**
* @param idx the index of the input to return
* @returns the input object with the given index
*/
InputType GetInput( const unsigned int& idx );
OutputType GetOutput();
virtual DataObjectPointer MakeOutput ( DataObjectPointerArraySizeType ){}
virtual DataObjectPointer MakeOutput(const DataObjectIdentifierType& ) {}
virtual void GenerateOutputInformation();
virtual void Update();
protected:
/**
* A default constructor
*/
GroupDiffusionHeadersFilter();
/**
* The destructor
*/
virtual ~GroupDiffusionHeadersFilter();
OutputType m_Output;
InputType m_Input;
private:
void operator=( const Self& ); //purposely not implemented
}
;
} //end of namespace mitk
#endif
diff --git a/Modules/DiffusionCore/DicomImport/mitkPhilipsDicomDiffusionImageHeaderReader.cpp b/Modules/DiffusionCore/DicomImport/mitkPhilipsDicomDiffusionImageHeaderReader.cpp
index 947ef54..0e9cc20 100644
--- a/Modules/DiffusionCore/DicomImport/mitkPhilipsDicomDiffusionImageHeaderReader.cpp
+++ b/Modules/DiffusionCore/DicomImport/mitkPhilipsDicomDiffusionImageHeaderReader.cpp
@@ -1,42 +1,42 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPhilipsDicomDiffusionImageHeaderReader.h"
mitk::PhilipsDicomDiffusionImageHeaderReader::PhilipsDicomDiffusionImageHeaderReader()
{
}
mitk::PhilipsDicomDiffusionImageHeaderReader::~PhilipsDicomDiffusionImageHeaderReader()
{
}
// do the work
void mitk::PhilipsDicomDiffusionImageHeaderReader::Update()
{
// check if there are filenames
if(m_DicomFilenames.size())
{
ReadPublicTags();
ReadPublicTags2();
TransformGradients();
}
}
diff --git a/Modules/DiffusionCore/DicomImport/mitkPhilipsDicomDiffusionImageHeaderReader.h b/Modules/DiffusionCore/DicomImport/mitkPhilipsDicomDiffusionImageHeaderReader.h
index 1b42b04..eb8a288 100644
--- a/Modules/DiffusionCore/DicomImport/mitkPhilipsDicomDiffusionImageHeaderReader.h
+++ b/Modules/DiffusionCore/DicomImport/mitkPhilipsDicomDiffusionImageHeaderReader.h
@@ -1,53 +1,53 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkPhilipsDicomDiffusionImageHeaderReader_h__
#define __mitkPhilipsDicomDiffusionImageHeaderReader_h__
#include "mitkDicomDiffusionImageHeaderReader.h"
namespace mitk
{
/**
@brief The PhilipsDicomDiffusionImageHeaderReader class reads in the image header information for the Philips DICOM Format */
class PhilipsDicomDiffusionImageHeaderReader : public DicomDiffusionImageHeaderReader
{
public:
mitkClassMacro( PhilipsDicomDiffusionImageHeaderReader, DicomDiffusionImageHeaderReader );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** read in the data */
void Update() override;
protected:
/** Default c'tor */
PhilipsDicomDiffusionImageHeaderReader();
/** Default d'tor */
~PhilipsDicomDiffusionImageHeaderReader() override;
};
}
#endif
diff --git a/Modules/DiffusionCore/DicomImport/mitkSiemensDicomDiffusionImageHeaderReader.cpp b/Modules/DiffusionCore/DicomImport/mitkSiemensDicomDiffusionImageHeaderReader.cpp
index 23d51a5..8a90be6 100644
--- a/Modules/DiffusionCore/DicomImport/mitkSiemensDicomDiffusionImageHeaderReader.cpp
+++ b/Modules/DiffusionCore/DicomImport/mitkSiemensDicomDiffusionImageHeaderReader.cpp
@@ -1,246 +1,246 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkSiemensDicomDiffusionImageHeaderReader.h"
#include <mitkLocaleSwitch.h>
#include "gdcmGlobal.h"
//#include <gdcmVersion.h>
#include "gdcmFile.h"
#include "gdcmImageReader.h"
#include "gdcmDictEntry.h"
#include "gdcmDicts.h"
#include "gdcmTag.h"
mitk::SiemensDicomDiffusionImageHeaderReader::SiemensDicomDiffusionImageHeaderReader()
{
}
mitk::SiemensDicomDiffusionImageHeaderReader::~SiemensDicomDiffusionImageHeaderReader()
{
}
int mitk::SiemensDicomDiffusionImageHeaderReader::ExtractSiemensDiffusionInformation( std::string tagString, std::string nameString, std::vector<double>& valueArray, int startPos )
{
std::string::size_type atPosition = tagString.find( nameString, startPos );
if ( atPosition == std::string::npos)
{
return 0;
}
else
{
std::string infoAsString = tagString.substr( atPosition, tagString.size()-atPosition+1 );
const char * infoAsCharPtr = infoAsString.c_str();
int vm = *(infoAsCharPtr+64);
int offset = 84;
for (int k = 0; k < vm; k++)
{
int itemLength = *(infoAsCharPtr+offset+4);
int strideSize = static_cast<int> (ceil(static_cast<double>(itemLength)/4) * 4);
std::string valueString = infoAsString.substr( offset+16, itemLength );
valueArray.push_back( atof(valueString.c_str()) );
offset += 16+strideSize;
}
return vm;
}
}
int mitk::SiemensDicomDiffusionImageHeaderReader::ExtractSiemensDiffusionGradientInformation( std::string tagString, std::string nameString, std::vector<double>& valueArray )
{
int nItems = 0;
std::string::size_type pos = -1;
while(nItems != 3)
{
nItems = ExtractSiemensDiffusionInformation( tagString, nameString, valueArray, pos+1 );
pos = tagString.find( nameString, pos+1 );
if ( pos == std::string::npos )
{
break;
}
}
return nItems;
}
// do the work
void mitk::SiemensDicomDiffusionImageHeaderReader::Update()
{
// check if there are filenames
if(m_DicomFilenames.size())
{
mitk::LocaleSwitch localeSwitch("C");
// adapted from slicer
// DicomToNrrdConverter.cxx
VolumeReaderType::DictionaryArrayRawPointer
inputDict = m_VolumeReader->GetMetaDataDictionaryArray();
ReadPublicTags();
float x0, y0, z0;
float x1, y1, z1;
std::string tag;
tag.clear();
itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0020|0032", tag );
sscanf( tag.c_str(), "%f\\%f\\%f", &x0, &y0, &z0 );
//MITK_INFO << "Slice 0: " << tag << std::endl;
tag.clear();
// assume volume interleaving, i.e. the second dicom file stores
// the second slice in the same volume as the first dicom file
if((*inputDict).size() > 1)
{
itk::ExposeMetaData<std::string> ( *(*inputDict)[1], "0020|0032", tag );
sscanf( tag.c_str(), "%f\\%f\\%f", &x1, &y1, &z1 );
//MITK_INFO << "Slice 1: " << tag << std::endl;
x1 -= x0; y1 -= y0; z1 -= z0;
x0 = x1*this->m_Output->xSlice + y1*this->m_Output->ySlice + z1*this->m_Output->zSlice;
if (x0 < 0)
{
m_SliceOrderIS = false;
}
}
ReadPublicTags2();
int nStride = 1;
this->m_Output->nSliceInVolume = m_sliceLocations.size();
nStride = this->m_Output->nSliceInVolume;
MITK_INFO << m_DicomFilenames[0] << std::endl;
MITK_INFO << "Dims " << this->m_Output->nRows << "x"
<< this->m_Output->nCols << "x" << this->m_Output->nSliceInVolume << " " << std::endl;
for (int k = 0; k < m_nSlice; k += nStride )
{
gdcm::ImageReader reader;
reader.SetFileName( m_DicomFilenames[k].c_str() );
if( !reader.Read() )
{
itkExceptionMacro(<< "Cannot read requested file");
}
const gdcm::File &f = reader.GetFile();
const gdcm::DataSet &ds = f.GetDataSet();
// gdcm::DataSet ds = header0->GetDataSet();
auto it = ds.Begin();
// Copy of the header->content
// copy information stored in 0029,1010 into a string for parsing
for(; it != ds.End(); ++it)
{
const gdcm::DataElement &ref = *it;
if (ref.GetTag() == gdcm::Tag(0x0029,0x1010)) {
tag = std::string(ref.GetByteValue()->GetPointer(),ref.GetByteValue()->GetLength());
}
}
// parse B_value from 0029,1010 tag
std::vector<double> valueArray(0);
vnl_vector_fixed<double, 3> vect3d;
int nItems = ExtractSiemensDiffusionInformation(tag, "B_value", valueArray);
if (nItems != 1 || valueArray[0] == 0) // did not find enough information
{
tag.clear();
MITK_INFO << "Reading diffusion info from 0019|100c and 0019|100e tags" << std::endl;
bool success = false;
for(it = ds.Begin(); it != ds.End(); ++it)
{
const gdcm::DataElement &ref = *it;
if (ref.GetTag() == gdcm::Tag(0x0019,0x100c)) {
tag = std::string(ref.GetByteValue()->GetPointer(),ref.GetByteValue()->GetLength());
this->m_Output->bValue = atof( tag.c_str() );
success = true;
}
}
tag.clear();
if(success)
{
if(this->m_Output->bValue == 0)
{
MITK_INFO << "BV: 0 (Baseline image)";
continue;
}
success = false;
for(it = ds.Begin(); it != ds.End(); ++it)
{
const gdcm::DataElement &ref = *it;
if (ref.GetTag() == gdcm::Tag(0x0019,0x100e)) {
tag = std::string(ref.GetByteValue()->GetPointer(),ref.GetByteValue()->GetLength());
success = true;
}
}
if(success)
{
memcpy( &vect3d[0], tag.c_str()+0, 8 );
memcpy( &vect3d[1], tag.c_str()+8, 8 );
memcpy( &vect3d[2], tag.c_str()+16, 8 );
vect3d.normalize();
this->m_Output->DiffusionVector = vect3d;
TransformGradients();
MITK_INFO << "BV: " << this->m_Output->bValue;
MITK_INFO << " GD: " << this->m_Output->DiffusionVector;
continue;
}
}
}
else
{
MITK_INFO << "Reading diffusion info from 0029,1010 tag" << std::endl;
this->m_Output->bValue = valueArray[0];
if(this->m_Output->bValue == 0)
{
MITK_INFO << "BV: 0 (Baseline image)";
continue;
}
valueArray.resize(0);
nItems = ExtractSiemensDiffusionGradientInformation(tag, "DiffusionGradientDirection", valueArray);
if (nItems == 3)
{
vect3d[0] = valueArray[0];
vect3d[1] = valueArray[1];
vect3d[2] = valueArray[2];
vect3d.normalize();
this->m_Output->DiffusionVector = vect3d;
TransformGradients();
MITK_INFO << "BV: " << this->m_Output->bValue;
MITK_INFO << " GD: " << this->m_Output->DiffusionVector;
continue;
}
}
MITK_ERROR << "No diffusion info found, forcing to BASELINE image." << std::endl;
this->m_Output->bValue = 0.0;
vect3d.fill( 0.0 );
this->m_Output->DiffusionVector = vect3d;
}
}
}
diff --git a/Modules/DiffusionCore/DicomImport/mitkSiemensDicomDiffusionImageHeaderReader.h b/Modules/DiffusionCore/DicomImport/mitkSiemensDicomDiffusionImageHeaderReader.h
index 813ab27..09145f0 100644
--- a/Modules/DiffusionCore/DicomImport/mitkSiemensDicomDiffusionImageHeaderReader.h
+++ b/Modules/DiffusionCore/DicomImport/mitkSiemensDicomDiffusionImageHeaderReader.h
@@ -1,59 +1,59 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkSiemensDicomDiffusionImageHeaderReader_h__
#define __mitkSiemensDicomDiffusionImageHeaderReader_h__
#include "mitkDicomDiffusionImageHeaderReader.h"
namespace mitk
{
/**
@brief The SiemensDicomDiffusionImageHeaderReader class reads in the header information for the standard Siemens DICOM format
*/
class SiemensDicomDiffusionImageHeaderReader : public DicomDiffusionImageHeaderReader
{
public:
mitkClassMacro( SiemensDicomDiffusionImageHeaderReader, DicomDiffusionImageHeaderReader );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Extract the key value for the key nameString from the tagString */
int ExtractSiemensDiffusionInformation( std::string tagString, std::string nameString, std::vector<double>& valueArray, int startPos = 0 );
/** Extracts the diffusion gradient information from the tagString and stores it into the valueArray vector */
int ExtractSiemensDiffusionGradientInformation( std::string tagString, std::string nameString, std::vector<double>& valueArray);
/** Read the data */
void Update() override;
protected:
/** Default c'tor */
SiemensDicomDiffusionImageHeaderReader();
/** Default d'tor */
~SiemensDicomDiffusionImageHeaderReader() override;
};
}
#endif
diff --git a/Modules/DiffusionCore/DicomImport/mitkSiemensMosaicDicomDiffusionImageHeaderReader.cpp b/Modules/DiffusionCore/DicomImport/mitkSiemensMosaicDicomDiffusionImageHeaderReader.cpp
index fa1988c..8289177 100644
--- a/Modules/DiffusionCore/DicomImport/mitkSiemensMosaicDicomDiffusionImageHeaderReader.cpp
+++ b/Modules/DiffusionCore/DicomImport/mitkSiemensMosaicDicomDiffusionImageHeaderReader.cpp
@@ -1,251 +1,251 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkSiemensMosaicDicomDiffusionImageHeaderReader.h"
#include "gdcmGlobal.h"
//#include "gdcmVersion.h"
#include "gdcmFile.h"
#include "gdcmImageReader.h"
#include "gdcmDict.h"
#include "gdcmDicts.h"
#include "gdcmDictEntry.h"
#include "gdcmDictEntry.h"
#include "gdcmDict.h"
#include "gdcmFile.h"
#include "gdcmSerieHelper.h"
mitk::SiemensMosaicDicomDiffusionImageHeaderReader::SiemensMosaicDicomDiffusionImageHeaderReader()
{
}
mitk::SiemensMosaicDicomDiffusionImageHeaderReader::~SiemensMosaicDicomDiffusionImageHeaderReader()
{
}
int mitk::SiemensMosaicDicomDiffusionImageHeaderReader::ExtractSiemensDiffusionInformation( std::string tagString, std::string nameString, std::vector<double>& valueArray )
{
std::string::size_type atPosition = tagString.find( nameString );
if ( atPosition == std::string::npos)
{
return 0;
}
else
{
std::string infoAsString = tagString.substr( atPosition, tagString.size()-atPosition+1 );
const char * infoAsCharPtr = infoAsString.c_str();
int vm = *(infoAsCharPtr+64);
std::string vr = infoAsString.substr( 68, 4 );
//int syngodt = *(infoAsCharPtr+72);
//int nItems = *(infoAsCharPtr+76);
//int localDummy = *(infoAsCharPtr+80);
int offset = 84;
for (int k = 0; k < vm; k++)
{
int itemLength = *(infoAsCharPtr+offset+4);
int strideSize = static_cast<int> (ceil(static_cast<double>(itemLength)/4) * 4);
std::string valueString = infoAsString.substr( offset+16, itemLength );
valueArray.push_back( atof(valueString.c_str()) );
offset += 16+strideSize;
}
return vm;
}
}
// do the work
void mitk::SiemensMosaicDicomDiffusionImageHeaderReader::Update()
{
// check if there are filenames
if(m_DicomFilenames.size())
{
// adapted from namic-sandbox
// DicomToNrrdConverter.cxx
VolumeReaderType::DictionaryArrayRawPointer inputDict
= m_VolumeReader->GetMetaDataDictionaryArray();
ReadPublicTags();
int mMosaic = 0; // number of raws in each mosaic block;
int nMosaic = 0; // number of columns in each mosaic block
std::cout << "Siemens SliceMosaic......" << std::endl;
m_SliceOrderIS = false;
// for siemens mosaic image, figure out mosaic slice order from 0029|1010
std::string tag;
tag.clear();
gdcm::ImageReader reader;
reader.SetFileName( m_DicomFilenames[0].c_str() );
if( !reader.Read() )
{
itkExceptionMacro(<< "Cannot read requested file");
}
const gdcm::File &f = reader.GetFile();
const gdcm::DataSet &ds = f.GetDataSet();
// gdcm::DataSet ds = header0->GetDataSet();
auto it = ds.Begin();
// Copy of the header->content
// copy information stored in 0029,1010 into a string for parsing
for(; it != ds.End(); ++it)
{
const gdcm::DataElement &ref = *it;
if (ref.GetTag() == gdcm::Tag(0x0029,0x1010)) {
tag = std::string(ref.GetByteValue()->GetPointer(),ref.GetByteValue()->GetLength());
}
}
// parse SliceNormalVector from 0029,1010 tag
std::vector<double> valueArray(0);
int nItems = ExtractSiemensDiffusionInformation(tag, "SliceNormalVector", valueArray);
if (nItems != 3) // did not find enough information
{
std::cout << "Warning: Cannot find complete information on SliceNormalVector in 0029|1010\n";
std::cout << " Slice order may be wrong.\n";
}
else if (valueArray[2] > 0)
{
m_SliceOrderIS = true;
}
// parse NumberOfImagesInMosaic from 0029,1010 tag
valueArray.resize(0);
nItems = ExtractSiemensDiffusionInformation(tag, "NumberOfImagesInMosaic", valueArray);
// Hot-Fix for Bug 14459, no valid Tag (0029,1010)
if (valueArray.size() < 1) // NO data was found
{
MITK_ERROR << "MOSAIC Image has no valid tag (0029,1010). ABORTING" << std::endl;
mitkThrow() << "MOSAIC Image has no valid tag (0029,1010). ABORTING";
return;
}
if (nItems == 0) // did not find enough information
{
std::cout << "Warning: Cannot find complete information on NumberOfImagesInMosaic in 0029|1010\n";
std::cout << " Resulting image may contain empty slices.\n";
}
else
{
this->m_Output->nSliceInVolume = static_cast<int>(valueArray[0]);
mMosaic = static_cast<int> (ceil(sqrt(valueArray[0])));
nMosaic = mMosaic;
}
std::cout << "Mosaic in " << mMosaic << " X " << nMosaic << " blocks (total number of blocks = " << valueArray[0] << ").\n";
ReadPublicTags2();
int nStride = 1;
std::cout << "Data in Siemens Mosaic Format\n";
//nVolume = nSlice;
//std::cout << "Number of Volume: " << nVolume << std::endl;
std::cout << "Number of Slices in each volume: " << this->m_Output->nSliceInVolume << std::endl;
nStride = 1;
for (int k = 0; k < m_nSlice; k += nStride )
{
gdcm::ImageReader reader;
reader.SetFileName( m_DicomFilenames[0].c_str() );
if( !reader.Read() )
{
itkExceptionMacro(<< "Cannot read requested file");
}
const gdcm::File &f = reader.GetFile();
const gdcm::DataSet &ds = f.GetDataSet();
// gdcm::DataSet ds = header0->GetDataSet();
auto it = ds.Begin();
// Copy of the header->content
// copy information stored in 0029,1010 into a string for parsing
for(; it != ds.End(); ++it)
{
const gdcm::DataElement &ref = *it;
if (ref.GetTag() == gdcm::Tag(0x0029,0x1010)) {
tag = std::string(ref.GetByteValue()->GetPointer(),ref.GetByteValue()->GetLength());
}
}
// parse B_value from 0029,1010 tag
std::vector<double> valueArray(0);
vnl_vector_fixed<double, 3> vect3d;
int nItems = ExtractSiemensDiffusionInformation(tag, "B_value", valueArray);
if (nItems != 1 || valueArray[0] == 0) // did not find enough information
{
MITK_INFO << "Reading diffusion info from 0019|100c and 0019|100e tags";
tag.clear();
bool success = itk::ExposeMetaData<std::string> ( *(*inputDict)[0], "0019|100c", tag );
if(success)
{
this->m_Output->bValue = atof( tag.c_str() );
tag.clear();
success = itk::ExposeMetaData<std::string> ( *(*inputDict)[k], "0019|100e", tag);
if(success)
{
memcpy( &vect3d[0], tag.c_str()+0, 8 );
memcpy( &vect3d[1], tag.c_str()+8, 8 );
memcpy( &vect3d[2], tag.c_str()+16, 8 );
vect3d.normalize();
this->m_Output->DiffusionVector = vect3d;
TransformGradients();
MITK_INFO << "BV: " << this->m_Output->bValue;
MITK_INFO << " GD: " << this->m_Output->DiffusionVector << std::endl;
continue;
}
}
}
else
{
MITK_INFO << "Reading diffusion info from 0029|1010 tags";
this->m_Output->bValue = valueArray[0];
// parse DiffusionGradientDirection from 0029,1010 tag
valueArray.resize(0);
nItems = ExtractSiemensDiffusionInformation(tag, "DiffusionGradientDirection", valueArray);
if (nItems == 3)
{
vect3d[0] = valueArray[0];
vect3d[1] = valueArray[1];
vect3d[2] = valueArray[2];
vect3d.normalize();
this->m_Output->DiffusionVector = vect3d;
TransformGradients();
MITK_INFO << "BV: " << this->m_Output->bValue;
MITK_INFO << " GD: " << this->m_Output->DiffusionVector;
continue;
}
}
MITK_ERROR << "No diffusion info found, assuming BASELINE" << std::endl;
this->m_Output->bValue = 0.0;
vect3d.fill( 0.0 );
this->m_Output->DiffusionVector = vect3d;
}
}
}
diff --git a/Modules/DiffusionCore/DicomImport/mitkSiemensMosaicDicomDiffusionImageHeaderReader.h b/Modules/DiffusionCore/DicomImport/mitkSiemensMosaicDicomDiffusionImageHeaderReader.h
index 8f72a57..e66b924 100644
--- a/Modules/DiffusionCore/DicomImport/mitkSiemensMosaicDicomDiffusionImageHeaderReader.h
+++ b/Modules/DiffusionCore/DicomImport/mitkSiemensMosaicDicomDiffusionImageHeaderReader.h
@@ -1,55 +1,55 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkSiemensMosaicDicomDiffusionImageHeaderReader_h__
#define __mitkSiemensMosaicDicomDiffusionImageHeaderReader_h__
#include "mitkDicomDiffusionImageHeaderReader.h"
namespace mitk
{
/**
@brief The SiemensMosaicDicomDiffusionImageHeaderReader class reads the image header for diffusion MR data stored in
Siemens MOSAIC Format
*/
class SiemensMosaicDicomDiffusionImageHeaderReader : public DicomDiffusionImageHeaderReader
{
public:
mitkClassMacro( SiemensMosaicDicomDiffusionImageHeaderReader, DicomDiffusionImageHeaderReader );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Extracts the information stored under the key nameString in the tagString */
int ExtractSiemensDiffusionInformation( std::string tagString, std::string nameString, std::vector<double>& valueArray );
/** Read the data */
void Update() override;
protected:
/** Default c'tor */
SiemensMosaicDicomDiffusionImageHeaderReader();
/** Default class d'tor */
~SiemensMosaicDicomDiffusionImageHeaderReader() override;
};
}
#endif
diff --git a/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageCorrectionFilter.cpp b/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageCorrectionFilter.cpp
index 7fd2de8..a3045dc 100644
--- a/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageCorrectionFilter.cpp
+++ b/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageCorrectionFilter.cpp
@@ -1,117 +1,117 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKDIFFUSIONIMAGECORRECTIONFILTER_CPP
#define MITKDIFFUSIONIMAGECORRECTIONFILTER_CPP
#include "mitkDiffusionImageCorrectionFilter.h"
#include <vnl/algo/vnl_symmetric_eigensystem.h>
#include <vnl/vnl_inverse.h>
#include <mitkDiffusionPropertyHelper.h>
typedef mitk::DiffusionPropertyHelper DPH;
mitk::DiffusionImageCorrectionFilter::DiffusionImageCorrectionFilter()
{
}
mitk::DiffusionImageCorrectionFilter::TransformMatrixType
mitk::DiffusionImageCorrectionFilter
::GetRotationComponent(const TransformMatrixType &A)
{
TransformMatrixType B;
B = A * A.transpose();
// get the eigenvalues and eigenvectors
typedef double MType;
vnl_vector< MType > eigvals;
vnl_matrix< MType > eigvecs;
vnl_symmetric_eigensystem_compute< MType > ( B, eigvecs, eigvals );
vnl_matrix_fixed< MType, 3, 3 > eigvecs_fixed;
eigvecs_fixed.set_columns(0, eigvecs );
TransformMatrixType C;
C.set_identity();
vnl_vector_fixed< MType, 3 > eigvals_sqrt;
for(unsigned int i=0; i<3; i++)
{
C(i,i) = std::sqrt( eigvals[i] );
}
TransformMatrixType S = vnl_inverse( eigvecs_fixed * C * vnl_inverse( eigvecs_fixed )) * A;
return S;
}
void mitk::DiffusionImageCorrectionFilter
::CorrectDirections( const TransformsVectorType& transformations)
{
if( m_SourceImage.IsNull() )
{
mitkThrow() << " No diffusion image given! ";
}
DPH::GradientDirectionsContainerType::Pointer directions = DPH::GetGradientContainer(m_SourceImage);
DPH::GradientDirectionsContainerType::Pointer corrected_directions = DPH::GradientDirectionsContainerType::New();
mitk::BValueMapProperty::BValueMap bval_map = DPH::GetBValueMap(m_SourceImage);
size_t first_unweighted_index = bval_map.begin()->second.front();
unsigned int transformed = 0;
for(size_t i=0; i< directions->Size(); i++ )
{
// skip b-zero images
if(i==first_unweighted_index)
{
corrected_directions->push_back(directions->ElementAt(i));
continue;
}
auto corrected = GetRotationComponent(transformations.at(transformed)) * directions->ElementAt(i);
// store the corrected direction
corrected_directions->push_back(corrected);
transformed++;
}
// replace the old directions with the corrected ones
DPH::SetGradientContainer(m_SourceImage, corrected_directions);
}
void mitk::DiffusionImageCorrectionFilter::CorrectDirections( const TransformMatrixType& transformation)
{
if( m_SourceImage.IsNull() )
{
mitkThrow() << " No diffusion image given! ";
}
TransformsVectorType transfVec;
for (unsigned int i=0; i< DPH::GetGradientContainer(m_SourceImage)->Size();i++)
{
transfVec.push_back(transformation);
}
this->CorrectDirections(transfVec);
}
#endif
diff --git a/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageCorrectionFilter.h b/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageCorrectionFilter.h
index 4c7e57d..25b11fe 100644
--- a/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageCorrectionFilter.h
+++ b/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageCorrectionFilter.h
@@ -1,94 +1,94 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKDIFFUSIONIMAGECORRECTIONFILTER_H
#define MITKDIFFUSIONIMAGECORRECTIONFILTER_H
#include "mitkImageSource.h"
#include <MitkDiffusionCoreExports.h>
namespace mitk
{
/**
* @class DiffusionImageCorrectionFilter
*/
class MITKDIFFUSIONCORE_EXPORT DiffusionImageCorrectionFilter
: public ImageSource
{
public:
/** class macros */
mitkClassMacro( DiffusionImageCorrectionFilter,
ImageSource )
itkSimpleNewMacro(Self)
typedef short DiffusionPixelType;
typedef vnl_matrix_fixed< double, 3, 3 > TransformMatrixType;
typedef std::vector< TransformMatrixType > TransformsVectorType;
typedef Superclass::OutputType DiffusionImageType;
typedef DiffusionImageType::Pointer DiffusionImageTypePointer;
typedef itk::VectorImage<DiffusionPixelType,3> ImageType;
/**
* @brief Set the mitk image ( a 3d+t image ) which is to be reinterpreted as dw image
* @param mitkImage
*/
void SetImage( DiffusionImageTypePointer input )
{
m_SourceImage = input;
}
/**
* @brief Correct each gradient direction according to the given transform
*
* The size of the input is expected to correspond to the count of gradient images in the image.
*/
void CorrectDirections( const TransformsVectorType& );
/**
* @brief Correct all gradient directions according to the given transform
*
* This will apply the same rotation to all directions.
*/
void CorrectDirections( const TransformMatrixType& );
void GenerateOutputInformation() override {}
protected:
DiffusionImageCorrectionFilter();
~DiffusionImageCorrectionFilter() override {}
/**
* @brief Get the rotation component following the Finite Strain
*
* For a given transformation \f$A\f$ its rotation component is defined as \f$ (AA^{T})^{-1/2}\f$.
*
* The computation first computes \f$ B = AA^T \f$ and then estimates the square root. Square root of
* diagonal matrices is defined as
* \f$ S = Q * \sqrt{C} * Q^{-1} \f$ with \f$ C \f$ having the eigenvalues on the diagonal.
*
*/
TransformMatrixType GetRotationComponent( const TransformMatrixType& );
DiffusionImageTypePointer m_SourceImage;
};
}
#endif // MITKDIFFUSIONIMAGECORRECTIONFILTER_H
diff --git a/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageCreationFilter.cpp b/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageCreationFilter.cpp
index 825af5d..38858f8 100644
--- a/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageCreationFilter.cpp
+++ b/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageCreationFilter.cpp
@@ -1,218 +1,218 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkDiffusionImageCreationFilter.h"
#include "mitkProperties.h"
#include "mitkImageTimeSelector.h"
#include "mitkImageCast.h"
#include "mitkImageToItk.h"
#include "mitkImageAccessByItk.h"
#include "mitkITKImageImport.h"
#include "mitkIOUtil.h"
#include <itkComposeImageFilter.h>
/**
* @brief RemapIntoVectorImage Take a 3d+t image and reinterpret it as vector image
* @return vectoriamge
*/
mitk::DiffusionImageCreationFilter::VectorImageType::Pointer
mitk::DiffusionImageCreationFilter::RemapIntoVectorImage( mitk::Image::Pointer input)
{
typedef itk::Image<mitk::DiffusionPropertyHelper::DiffusionPixelType, 3> ImageVolumeType;
typedef itk::ComposeImageFilter< ImageVolumeType > ComposeFilterType;
ComposeFilterType::Pointer vec_composer = ComposeFilterType::New();
mitk::ImageTimeSelector::Pointer t_selector = mitk::ImageTimeSelector::New();
t_selector->SetInput( input );
for( unsigned int i=0; i< input->GetTimeSteps(); i++)
{
t_selector->SetTimeNr(i);
t_selector->Update();
ImageVolumeType::Pointer singleImageItk;
mitk::CastToItkImage( t_selector->GetOutput(), singleImageItk );
vec_composer->SetInput( i, singleImageItk );
}
try
{
vec_composer->Update();
}
catch( const itk::ExceptionObject& e)
{
MITK_ERROR << "Caught exception while updating compose filter: " << e.what();
}
mitk::DiffusionImageCreationFilter::VectorImageType::Pointer vector_image = vec_composer->GetOutput();
vector_image->GetPixelContainer()->ContainerManageMemoryOff();
return vector_image;
}
mitk::DiffusionImageCreationFilter::DiffusionImageCreationFilter()
: m_ReferenceImage( nullptr )
{
m_HeaderDescriptorSet = false;
this->SetNumberOfRequiredInputs(1);
this->SetNumberOfRequiredOutputs(1);
}
mitk::DiffusionImageCreationFilter::~DiffusionImageCreationFilter()
{
}
void mitk::DiffusionImageCreationFilter::SetReferenceImage( mitk::Image::Pointer reference_image )
{
if( reference_image.IsNull() )
{
mitkThrow() << "Null-pointer image provided as reference. ";
}
if( ! DPH::IsDiffusionWeightedImage(reference_image) )
{
mitkThrow() << "The image provided as reference is not a diffusion-weighted image. Cannot proceed. ";
}
this->m_ReferenceImage = reference_image;
}
void mitk::DiffusionImageCreationFilter::GenerateData()
{
const mitk::Image::Pointer input_image = this->GetInput(0);
if( input_image.IsNull() )
{
mitkThrow() << "No input specified. Cannot proceed ";
}
if( !( m_HeaderDescriptorSet ^ m_ReferenceImage.IsNotNull() ) )
{
mitkThrow() << "Either a header descriptor or a reference diffusion-weighted image have to be provided. Terminating.";
}
mitk::Image::Pointer outputForCache = this->GetOutput();
if( input_image->GetTimeSteps() > 1 )
{
mitk::Image::Pointer mitkvectorimage = mitk::GrabItkImageMemory<DPH::ImageType>( RemapIntoVectorImage( input_image ));
outputForCache->Initialize( mitkvectorimage );
}
// no need to remap, we expect to have a vector image directly
else
{
outputForCache->Initialize( input_image );
}
// header information
GradientDirectionContainerType::Pointer DiffusionVectors = this->InternalGetGradientDirections( );
MeasurementFrameType MeasurementFrame = this->InternalGetMeasurementFrame();
float BValue = this->InternalGetBValue();
// create BValueMap
mitk::BValueMapProperty::BValueMap BValueMap = mitk::BValueMapProperty::CreateBValueMap( DiffusionVectors, BValue );
DPH::SetGradientContainer(outputForCache, DiffusionVectors);
DPH::SetMeasurementFrame(outputForCache, MeasurementFrame);
DPH::SetBValueMap(outputForCache, BValueMap);
DPH::SetReferenceBValue(outputForCache, BValue);
outputForCache->Modified();
}
void mitk::DiffusionImageCreationFilter::SetHeaderDescriptor(DiffusionImageHeaderDescriptor header_descriptor)
{
this->m_HeaderDescriptor = header_descriptor;
this->m_HeaderDescriptorSet = true;
}
mitk::DiffusionImageCreationFilter::MeasurementFrameType
mitk::DiffusionImageCreationFilter::InternalGetMeasurementFrame()
{
MeasurementFrameType MeasurementFrame;
if( m_ReferenceImage.IsNotNull() )
{
MeasurementFrame = DPH::GetMeasurementFrame( m_ReferenceImage );
}
else if ( m_HeaderDescriptorSet )
{
MeasurementFrame = m_HeaderDescriptor.m_MeasurementFrame;
}
else
{
MeasurementFrame(0,0) = 1;
MeasurementFrame(0,1) = 0;
MeasurementFrame(0,2) = 0;
MeasurementFrame(1,0) = 0;
MeasurementFrame(1,1) = 1;
MeasurementFrame(1,2) = 0;
MeasurementFrame(2,0) = 0;
MeasurementFrame(2,1) = 0;
MeasurementFrame(2,2) = 1;
MITK_WARN << "Created default measurement frame as non provided ( no reference image or header information provided)";
}
return MeasurementFrame;
}
mitk::DiffusionImageCreationFilter::GradientDirectionContainerType::Pointer
mitk::DiffusionImageCreationFilter::InternalGetGradientDirections()
{
GradientDirectionContainerType::Pointer DiffusionVectors = GradientDirectionContainerType::New();
if( this->m_ReferenceImage )
{
DiffusionVectors = DPH::GetGradientContainer( this->m_ReferenceImage );
}
else if ( m_HeaderDescriptorSet )
{
DiffusionVectors = m_HeaderDescriptor.m_GradientDirections;
}
return DiffusionVectors;
}
float mitk::DiffusionImageCreationFilter::InternalGetBValue()
{
float bvalue = -1;
if( m_ReferenceImage.IsNotNull() )
{
bvalue = DPH::GetReferenceBValue( m_ReferenceImage );
}
else if ( m_HeaderDescriptorSet )
{
bvalue = m_HeaderDescriptor.m_BValue;
}
else
{
MITK_ERROR << "No reference image and no header descriptor provided.";
}
return bvalue;
}
diff --git a/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageCreationFilter.h b/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageCreationFilter.h
index 9d784a2..0881885 100644
--- a/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageCreationFilter.h
+++ b/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageCreationFilter.h
@@ -1,106 +1,106 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 DIFFUSIONIMAGECREATIONFILTER_H
#define DIFFUSIONIMAGECREATIONFILTER_H
#include "mitkImageToImageFilter.h"
#include "mitkDiffusionPropertyHelper.h"
#include <MitkDiffusionCoreExports.h>
namespace mitk
{
/**
* @brief The DiffusionImageHeaderDescriptor struct bundles the necessary diffusion-weighted image header meta information.
*/
struct MITKDIFFUSIONCORE_EXPORT DiffusionImageHeaderDescriptor
{
DiffusionImageHeaderDescriptor()
: m_GradientDirections(nullptr)
{
m_BValue = -1;
}
float m_BValue;
mitk::DiffusionPropertyHelper::BValueMapType m_BValueMapType;
mitk::DiffusionPropertyHelper::MeasurementFrameType m_MeasurementFrame;
mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer m_GradientDirections;
};
/**
* @brief The DiffusionImageCreationFilter class creates a diffusion-weighted image out of a
* given 3D+t regular image and sufficient additional information about gradient directions and b values
*
* For easier use, the filter supports the usage of reference images. Here a diffusion-weighted (dw) image is expected and the meta
* information of this image will be used for the output dw image. The diffusion information can also be specified by setting the HeaderDescriptor
* directly (SetHeaderDescriptor).
*
* At least one of reference image or descriptor must be used, otherwise an exception is thrown.
*/
class MITKDIFFUSIONCORE_EXPORT DiffusionImageCreationFilter
: public ImageToImageFilter
{
public:
/** class macros */
mitkClassMacro( DiffusionImageCreationFilter,
ImageToImageFilter )
itkNewMacro(Self)
typedef short DiffusionPixelType;
typedef mitk::DiffusionPropertyHelper DPH;
typedef mitk::Image OutputType;
typedef mitk::DiffusionPropertyHelper::ImageType VectorImageType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType;
typedef mitk::DiffusionPropertyHelper::MeasurementFrameType MeasurementFrameType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType;
/**
* @brief SetReferenceImage Set a diffusion image as reference, i.e. the header information will be extracted from it
* @param reference_image A reference diffusion-weigted image - will throw exception of the input is not DW image
*/
void SetReferenceImage( mitk::Image::Pointer reference_image );
/**
* @brief SetHeaderDescriptor set the information to be used with the dw image
* @param header_descriptor
*
* \sa DiffusionImageHeaderDescriptor
*/
void SetHeaderDescriptor( DiffusionImageHeaderDescriptor header_descriptor );
void GenerateData() override;
protected:
DiffusionImageCreationFilter();
~DiffusionImageCreationFilter() override;
GradientDirectionContainerType::Pointer InternalGetGradientDirections( );
MeasurementFrameType InternalGetMeasurementFrame();
float InternalGetBValue();
VectorImageType::Pointer RemapIntoVectorImage( mitk::Image::Pointer input);
mitk::Image::Pointer m_ReferenceImage;
DiffusionImageHeaderDescriptor m_HeaderDescriptor;
bool m_HeaderDescriptorSet;
};
} //end namespace mitk
#endif // DIFFUSIONIMAGECREATIONFILTER_H
diff --git a/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageHeaderInformation.cpp b/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageHeaderInformation.cpp
index 0620be3..20857f7 100644
--- a/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageHeaderInformation.cpp
+++ b/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageHeaderInformation.cpp
@@ -1,28 +1,28 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkDiffusionImageHeaderInformation.h"
mitk::DiffusionImageHeaderInformation::DiffusionImageHeaderInformation()
{
}
mitk::DiffusionImageHeaderInformation::~DiffusionImageHeaderInformation()
{
}
diff --git a/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageHeaderInformation.h b/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageHeaderInformation.h
index 261dba6..387b8ed 100644
--- a/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageHeaderInformation.h
+++ b/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageHeaderInformation.h
@@ -1,123 +1,123 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITK_DiffusionImageHeaderInformation_H
#define MITK_DiffusionImageHeaderInformation_H
#include <itkObject.h>
#include "vnl/vnl_vector_fixed.h"
#include "mitkCommon.h"
#include "itkObjectFactory.h"
namespace mitk
{
enum DiffusionHeaderGroup{
DHG_NotYetGrouped,
DHG_ZeroDiffusionWeighted,
DHG_NonZeroDiffusionWeighted,
DHG_Other,
};
class DiffusionImageHeaderInformation : public itk::Object
{
public:
mitkClassMacroItkParent( DiffusionImageHeaderInformation, itk::Object );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
typedef std::vector< std::string > FileNamesContainer;
//DiffusionImageHeaderInformation(int nRows, int nCols, float xRes, float yRes, float xOrigin,
// float yOrigin, float zOrigin, float sliceThickness, float sliceSpacing,
// int nSliceInVolume, float xRow, float yRow, float zRow, float xCol,
// float yCol, float zCol, float xSlice, float ySlice, float zSlice,
// float bValue, vnl_vector_fixed<double, 3> DiffusionVector,
// std::string vendor, bool mosaic, DiffusionHeaderGroup headerGroup = DHG_NotYetGrouped):
// nRows(nRows), nCols(nCols),xRes(xRes),
// yRes(yRes),xOrigin(xOrigin),yOrigin(yOrigin),zOrigin(zOrigin),
// sliceThickness(sliceThickness),sliceSpacing(sliceSpacing),
// nSliceInVolume(nSliceInVolume), xRow(xRow), yRow(yRow), zRow(zRow),
// xCol(xCol),yCol(yCol),zCol(zCol),xSlice(xSlice),ySlice(ySlice),zSlice(zSlice),
// bValue(bValue), DiffusionVector(DiffusionVector), vendor(vendor),mosaic(mosaic),
// headerGroup(headerGroup) {}
std::string seriesDescription;
int seriesNumber;
std::string patientName;
int nRows;
int nCols;
float xRes;
float yRes;
float xOrigin;
float yOrigin;
float zOrigin;
float sliceThickness;
float sliceSpacing;
int nSliceInVolume;
float xRow;
float yRow;
float zRow;
float xCol;
float yCol;
float zCol;
float xSlice;
float ySlice;
float zSlice;
float bValue;
vnl_vector_fixed<double, 3> DiffusionVector;
std::string vendor;
bool mosaic;
DiffusionHeaderGroup headerGroup;
FileNamesContainer m_DicomFilenames;
inline bool isIdentical(const DiffusionImageHeaderInformation::Pointer other) const {
return nRows == other->nRows &&
nCols == other->nCols &&
xRes == other->xRes &&
yRes == other->yRes &&
xOrigin == other->xOrigin &&
yOrigin == other->yOrigin &&
zOrigin == other->zOrigin &&
sliceThickness == other->sliceThickness &&
sliceSpacing == other->sliceSpacing &&
nSliceInVolume == other->nSliceInVolume &&
xRow == other->xRow &&
yRow == other->yRow &&
zRow == other->zRow &&
xCol == other->xCol &&
yCol == other->yCol &&
zCol == other->zCol &&
xSlice == other->xSlice &&
ySlice == other->ySlice &&
zSlice == other->zSlice;
}
protected:
DiffusionImageHeaderInformation();
~DiffusionImageHeaderInformation() override;
};
} // namespace
#endif // MITK_DiffusionImageHeaderInformation_H
diff --git a/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageTransformedCreationFilter.cxx b/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageTransformedCreationFilter.cxx
index 43f2818..bcb81aa 100644
--- a/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageTransformedCreationFilter.cxx
+++ b/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageTransformedCreationFilter.cxx
@@ -1,268 +1,268 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 DIFFUSIONIMAGETRANSFORMEDCREATIONFILTER_CXX
#define DIFFUSIONIMAGETRANSFORMEDCREATIONFILTER_CXX
#include "mitkDiffusionImageTransformedCreationFilter.h"
#include "mitkDiffusionImageCorrectionFilter.h"
#include "mitkImageCast.h"
#include "mitkImageWriteAccessor.h"
#include "mitkImageTimeSelector.h"
#include "mitkProperties.h"
#include "mitkIOUtil.h"
#include <itkResampleImageFilter.h>
#include <itkNearestNeighborInterpolateImageFunction.h>
#include <itkWindowedSincInterpolateImageFunction.h>
#include <itkBSplineInterpolateImageFunction.h>
#include <itkLinearInterpolateImageFunction.h>
template <typename TTransformType, typename ItkImageType>
static void ResampleImage( typename ItkImageType::Pointer itk_reference,
mitk::Image::Pointer mitk_input,
typename TTransformType::Pointer transform,
unsigned int interpolator,
mitk::Image::Pointer output_target, unsigned int position )
{
typedef itk::LinearInterpolateImageFunction< ItkImageType, double > InterpolatorType;
typename InterpolatorType::Pointer linear_interpolator = InterpolatorType::New();
typedef itk::NearestNeighborInterpolateImageFunction< ItkImageType, double > NearestNeighborInterpolatorType;
typename NearestNeighborInterpolatorType::Pointer nn_interpolator = NearestNeighborInterpolatorType::New();
typedef itk::WindowedSincInterpolateImageFunction< ItkImageType, 7> WindowedSincInterpolatorType;
typename WindowedSincInterpolatorType::Pointer sinc_interpolator = WindowedSincInterpolatorType::New();
typedef itk::BSplineInterpolateImageFunction< ItkImageType, double, double> BSplineInterpolatorType;
typename BSplineInterpolatorType::Pointer bicubic_interpolator = BSplineInterpolatorType::New();
bicubic_interpolator->SetSplineOrder(3);
typedef typename itk::ResampleImageFilter< ItkImageType, ItkImageType, double> ResampleImageFilterType;
typename ResampleImageFilterType::Pointer resampler = ResampleImageFilterType::New();
// Create interpolator pool
typedef itk::InterpolateImageFunction< ItkImageType, double> InterpolateFunctionBaseType;
std::vector< InterpolateFunctionBaseType* > InterpolateFunctionsPool;
InterpolateFunctionsPool.push_back( nn_interpolator.GetPointer() );
InterpolateFunctionsPool.push_back( linear_interpolator.GetPointer() );
InterpolateFunctionsPool.push_back( bicubic_interpolator.GetPointer() );
InterpolateFunctionsPool.push_back( sinc_interpolator.GetPointer() );
// select interpolator by the selection flag
resampler->SetInterpolator( InterpolateFunctionsPool.at( interpolator ) );
typename ItkImageType::Pointer itk_input;
mitk::CastToItkImage< ItkImageType >( mitk_input, itk_input );
resampler->SetInput( itk_input );
resampler->SetTransform( transform );
resampler->SetReferenceImage( itk_reference );
resampler->UseReferenceImageOn();
resampler->Update();
mitk::Image::Pointer current_resampled = mitk::Image::New();
current_resampled->InitializeByItk( resampler->GetOutput() );
current_resampled->SetImportChannel( resampler->GetOutput()->GetBufferPointer(),
mitk::Image::CopyMemory );
mitk::ImageWriteAccessor imac( current_resampled );
output_target->SetImportVolume( imac.GetData(),
position, 0, mitk::Image::CopyMemory );
}
/*
template< typename TTransformType >
static mitk::DiffusionPropertyHelper::GradientDirectionType
TransformGradientDirection( mitk::DiffusionPropertyHelper::GradientDirectionType vec_in,
typename TTransformType::Pointer transform )
{
mitk::DiffusionPropertyHelper::GradientDirectionType vec_out;
vec_out.fill(1.0);
typedef typename TTransformType::MatrixType TMatrixType;
return vec_out;
}
*/
template< typename TTransformType>
mitk::DiffusionImageTransformedCreationFilter<TTransformType>
::DiffusionImageTransformedCreationFilter()
{
this->m_OutputPrefix = "/tmp/";
}
template< typename TTransformType>
mitk::DiffusionImageTransformedCreationFilter<TTransformType>
::~DiffusionImageTransformedCreationFilter()
{
}
template< typename TTransformType>
mitk::DiffusionImageHeaderDescriptor
mitk::DiffusionImageTransformedCreationFilter<TTransformType>
::GetTransformedHeaderInformation()
{
typedef mitk::DiffusionPropertyHelper DPH;
DiffusionImageHeaderDescriptor dwhdesc;
dwhdesc.m_BValue = DPH::GetReferenceBValue( this->m_DiffusionReferenceImage );
// TODO : here comes transformation of the gradients
dwhdesc.m_GradientDirections = DPH::GetGradientContainer( this->m_DiffusionReferenceImage );
dwhdesc.m_MeasurementFrame = DPH::GetMeasurementFrame( this->m_DiffusionReferenceImage );
dwhdesc.m_BValueMapType = DPH::GetBValueMap( this->m_DiffusionReferenceImage );
return dwhdesc;
}
template< typename TTransformType>
void mitk::DiffusionImageTransformedCreationFilter< TTransformType >
::GenerateOutputInformation()
{
MITK_INFO << "Debug info";
}
template< typename TTransformType>
void mitk::DiffusionImageTransformedCreationFilter<TTransformType>
::GenerateData()
{
mitk::Image::Pointer input = this->GetInput();
// validity checks
if( m_InternalTransforms.size() != input->GetTimeSteps() )
{
mitkThrow() << "Number of transforms" << m_InternalTransforms.size() << "differ from number of timesteps" << input->GetTimeSteps();
}
typedef itk::Image< DiffusionPropertyHelper::DiffusionPixelType, 3> ImageType;
// create intermediate output
mitk::Image::Pointer resampled_output = mitk::Image::New();
resampled_output->Initialize( input );
ImageType::Pointer current_itk_reference = ImageType::New();
CastToItkImage( this->m_ResamplingReferenceImage, current_itk_reference );
unsigned int time_dim = input->GetDimension(3);
for( unsigned int time_idx = 0; time_idx < time_dim; time_idx++ )
{
mitk::ImageTimeSelector::Pointer t_sel = mitk::ImageTimeSelector::New();
t_sel->SetInput( input );
t_sel->SetTimeNr( time_idx );
t_sel->Update();
ResampleImage< TTransformType, ImageType>( current_itk_reference,
t_sel->GetOutput(),
this->m_InternalTransforms.at(time_idx),
this->m_InterpolationLevel,
resampled_output, time_idx);
}
// call here creation filter
mitk::DiffusionImageCreationFilter::Pointer creator =
mitk::DiffusionImageCreationFilter::New();
creator->SetInput( resampled_output );
creator->SetHeaderDescriptor( this->GetTransformedHeaderInformation() );
creator->Update();
mitk::Image::Pointer output = creator->GetOutput();
mitk::DiffusionPropertyHelper::CopyProperties(resampled_output, output, true);
typedef mitk::DiffusionPropertyHelper DPH;
float BValue = mitk::DiffusionPropertyHelper::GetReferenceBValue( creator->GetOutput() );
mitk::BValueMapProperty::BValueMap BValueMap = mitk::BValueMapProperty::CreateBValueMap( mitk::DiffusionPropertyHelper::GetGradientContainer( creator->GetOutput() ), BValue );
output->GetPropertyList()->ReplaceProperty( DPH::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( mitk::DiffusionPropertyHelper::GetGradientContainer( creator->GetOutput() )) );
output->GetPropertyList()->ReplaceProperty( DPH::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( mitk::DiffusionPropertyHelper::GetMeasurementFrame( creator->GetOutput() ) ) );
output->GetPropertyList()->ReplaceProperty( DPH::BVALUEMAPPROPERTYNAME.c_str(), mitk::BValueMapProperty::New( BValueMap ) );
output->GetPropertyList()->ReplaceProperty( DPH::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( BValue ) );
// correct gradients
mitk::DiffusionImageCorrectionFilter::Pointer corrector = mitk::DiffusionImageCorrectionFilter::New();
corrector->SetImage( output) ;
corrector->CorrectDirections( this->m_RotationMatrices );
DPH pHelper( output );
pHelper.InitializeImage();
m_OutputCache = output;
this->SetPrimaryOutput( m_OutputCache );
m_OutputCache->Modified();
}
template< typename TTransformType>
void mitk::DiffusionImageTransformedCreationFilter<TTransformType>
::SetTransformParameters(const TransformParametersContainerType &params)
{
if( params.empty() )
{
MITK_ERROR << "Empty parameter list given.";
return;
}
TransformContainerType transforms;
auto iter = std::begin( params );
while( iter != std::end( params ) )
{
typename TTransformType::Pointer transform = TTransformType::New();
transform->SetParameters( (*iter) );
transforms.push_back( transform );
++iter;
}
this->SetTransforms( transforms );
}
template< typename TTransformType>
void mitk::DiffusionImageTransformedCreationFilter<TTransformType>
::SetTransforms(const TransformContainerType &transforms)
{
if( transforms.empty() )
{
MITK_ERROR << "Empty transform list given.";
return;
}
this->m_InternalTransforms.reserve( transforms.size() );
std::copy( transforms.begin(), transforms.end(),
std::back_inserter(this->m_InternalTransforms ) );
MatrixType E;
E.set_identity();
for( auto iter = std::begin(this->m_InternalTransforms); iter != std::end( this->m_InternalTransforms); ++iter)
{
MatrixType A = E * (*iter)->GetMatrix().GetVnlMatrix();
this->m_RotationMatrices.push_back( A );
}
}
#endif // DIFFUSIONIMAGETRANSFORMEDCREATIONFILTER_CXX
diff --git a/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageTransformedCreationFilter.h b/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageTransformedCreationFilter.h
index e683e1a..e247981 100644
--- a/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageTransformedCreationFilter.h
+++ b/Modules/DiffusionCore/IODataStructures/DiffusionWeightedImages/mitkDiffusionImageTransformedCreationFilter.h
@@ -1,116 +1,116 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 DIFFUSIONIMAGETRANSFORMEDCREATIONFILTER_H
#define DIFFUSIONIMAGETRANSFORMEDCREATIONFILTER_H
#include "mitkDiffusionPropertyHelper.h"
#include "mitkDiffusionImageCreationFilter.h"
#include "mitkDiffusionImageCorrectionFilter.h"
#include <MitkDiffusionCoreExports.h>
namespace mitk
{
/**
* @brief DiffusionImageTransformedCreationFilter extends its superclass ( DiffusionImageCreationFilter ) by providing the possibility
* to specify a list of transforms to be applied to the separate volumes before
*/
template <typename TTransformType >
class MITKDIFFUSIONCORE_EXPORT DiffusionImageTransformedCreationFilter
: public ImageToImageFilter
{
public:
/** class macros */
mitkClassMacro( DiffusionImageTransformedCreationFilter,
ImageToImageFilter )
itkNewMacro(Self)
enum InterpolatorLevel
{
NearestNeighbor = 0,
Trilinear,
BSpline_Bicubic,
WindowedSinc
};
typedef std::vector< typename TTransformType::Pointer > TransformContainerType;
typedef std::vector< typename TTransformType::ParametersType > TransformParametersContainerType;
/** Set a transform container to be used, one transform per volume */
void SetTransforms( const TransformContainerType& );
/** Set a container of transform parameters to be used to create transforms for transforming the input */
void SetTransformParameters( const TransformParametersContainerType& );
/** Set interpolation type for resampling */
void SetInterpolationLevel( InterpolatorLevel lvl)
{
m_InterpolationLevel = lvl;
}
void GenerateData() override;
void SetResamplingReferenceImage( mitk::Image::Pointer image )
{
this->m_ResamplingReferenceImage = image;
}
void SetReferenceDiffusionImage( mitk::Image::Pointer dwimage )
{
this->m_DiffusionReferenceImage = dwimage;
}
void SetOutputPrefix( std::string prefix )
{
this->m_OutputPrefix = prefix;
}
virtual void GenerateOutputInformation() override;
protected:
DiffusionImageTransformedCreationFilter();
~DiffusionImageTransformedCreationFilter();
DiffusionImageHeaderDescriptor GetTransformedHeaderInformation();
TransformContainerType m_InternalTransforms;
mitk::Image::Pointer m_ResamplingReferenceImage;
mitk::Image::Pointer m_DiffusionReferenceImage;
InterpolatorLevel m_InterpolationLevel;
typedef DiffusionImageCorrectionFilter::TransformMatrixType MatrixType;
std::vector< MatrixType > m_RotationMatrices;
std::string m_OutputPrefix;
mitk::Image::Pointer m_OutputCache;
};
} // end namespace mitk
#ifndef ITK_MANUAL_INSTANTIATION
#include "mitkDiffusionImageTransformedCreationFilter.cxx"
#endif
#endif // DIFFUSIONIMAGETRANSFORMEDCREATIONFILTER_H
diff --git a/Modules/DiffusionCore/IODataStructures/Properties/mitkBValueMapProperty.cpp b/Modules/DiffusionCore/IODataStructures/Properties/mitkBValueMapProperty.cpp
index 03b372d..dec7695 100644
--- a/Modules/DiffusionCore/IODataStructures/Properties/mitkBValueMapProperty.cpp
+++ b/Modules/DiffusionCore/IODataStructures/Properties/mitkBValueMapProperty.cpp
@@ -1,103 +1,103 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkBValueMapProperty.h"
mitk::BValueMapProperty::BValueMapProperty()
: m_BValueMap()
{
}
mitk::BValueMapProperty::BValueMapProperty(const BValueMapProperty& other)
: mitk::BaseProperty(other)
{
m_BValueMap = other.GetBValueMap();
}
mitk::BValueMapProperty::BValueMapProperty(const BValueMap& bValueMap)
{
m_BValueMap = bValueMap;
}
mitk::BValueMapProperty::~BValueMapProperty()
{
}
const mitk::BValueMapProperty::BValueMap & mitk::BValueMapProperty::GetBValueMap() const
{
return m_BValueMap;
}
void mitk::BValueMapProperty::SetBValueMap(const BValueMap & map)
{
this->m_BValueMap = map;
}
bool mitk::BValueMapProperty::IsEqual(const BaseProperty& property) const
{
return this->m_BValueMap == static_cast<const Self&>(property).m_BValueMap;
}
bool mitk::BValueMapProperty::Assign(const BaseProperty& property)
{
this->m_BValueMap = static_cast<const Self&>(property).m_BValueMap;
return true;
}
mitk::BValueMapProperty::BValueMap mitk::BValueMapProperty::CreateBValueMap(const mitk::BValueMapProperty::GradientDirectionsContainerType * gdc, float referenceBValue)
{
mitk::BValueMapProperty::BValueMap map;
mitk::BValueMapProperty::GradientDirectionsContainerType::ConstIterator gdcit;
for( gdcit = gdc->Begin(); gdcit != gdc->End(); ++gdcit)
{
float keyBValue = mitk::BValueMapProperty::GetBValueOfGradientDirection(gdcit.Index(),referenceBValue, gdc);
map[keyBValue].push_back(gdcit.Index());
}
return map;
}
float mitk::BValueMapProperty::GetBValueOfGradientDirection(unsigned int i, float referenceBValue, const mitk::BValueMapProperty::GradientDirectionsContainerType * gdc)
{
if(i > gdc->Size()-1)
return -1;
if(gdc->ElementAt(i).one_norm() <= 0.0)
{
return 0;
}
else
{
double twonorm = gdc->ElementAt(i).two_norm();
double bval = referenceBValue*twonorm*twonorm;
if (bval<0)
bval = ceil(bval - 0.5);
else
bval = floor(bval + 0.5);
return bval;
}
}
itk::LightObject::Pointer mitk::BValueMapProperty::InternalClone() const
{
itk::LightObject::Pointer result(new Self(*this));
result->UnRegister();
return result;
}
diff --git a/Modules/DiffusionCore/IODataStructures/Properties/mitkBValueMapProperty.h b/Modules/DiffusionCore/IODataStructures/Properties/mitkBValueMapProperty.h
index a6016b1..93a2db9 100644
--- a/Modules/DiffusionCore/IODataStructures/Properties/mitkBValueMapProperty.h
+++ b/Modules/DiffusionCore/IODataStructures/Properties/mitkBValueMapProperty.h
@@ -1,74 +1,74 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKBVALUEMAPPROPERTY_H
#define MITKBVALUEMAPPROPERTY_H
#include "mitkBaseProperty.h"
#include <map>
#include <vector>
#include <MitkDiffusionCoreExports.h>
#include <itkVectorContainer.h>
#include <vnl/vnl_vector_fixed.h>
namespace mitk
{
/** This property will store the b value map */
class MITKDIFFUSIONCORE_EXPORT BValueMapProperty : public mitk::BaseProperty
{
public:
/**
* \brief The BValueMap contains seperated IndicesVectors for each b value (index for GradientDirectionContainer)
* key := b value
* value := indicesVector
*/
typedef std::map< unsigned int , std::vector< unsigned int > > BValueMap;
typedef unsigned int IndexType;
typedef vnl_vector_fixed< double, 3 > ValueType;
typedef ValueType GradientDirectionType;
typedef itk::VectorContainer< IndexType, GradientDirectionType > GradientDirectionsContainerType;
mitkClassMacro(BValueMapProperty, BaseProperty)
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitkNewMacro1Param(BValueMapProperty, const BValueMapProperty&)
mitkNewMacro1Param(BValueMapProperty, const BValueMap&)
const BValueMap & GetBValueMap() const;
void SetBValueMap(const BValueMap & map);
static BValueMap CreateBValueMap(const GradientDirectionsContainerType * gdc, float referenceBValue);
static float GetBValueOfGradientDirection(unsigned int i, float referenceBValue, const GradientDirectionsContainerType *gdc);
protected:
BValueMapProperty();
~BValueMapProperty() override;
BValueMapProperty(const BValueMapProperty& other);
BValueMapProperty(const BValueMap& bValueMap);
bool IsEqual(const BaseProperty& property) const override;
bool Assign(const BaseProperty & property) override;
BValueMap m_BValueMap;
itk::LightObject::Pointer InternalClone() const override;
};
}
#endif
diff --git a/Modules/DiffusionCore/IODataStructures/Properties/mitkBValueMapPropertySerializer.cpp b/Modules/DiffusionCore/IODataStructures/Properties/mitkBValueMapPropertySerializer.cpp
index d570221..c5e1654 100644
--- a/Modules/DiffusionCore/IODataStructures/Properties/mitkBValueMapPropertySerializer.cpp
+++ b/Modules/DiffusionCore/IODataStructures/Properties/mitkBValueMapPropertySerializer.cpp
@@ -1,131 +1,131 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkBValueMapPropertySerializer_h_included
#define mitkBValueMapPropertySerializer_h_included
#include "mitkBasePropertySerializer.h"
#include "mitkBValueMapProperty.h"
#include <MitkDiffusionCoreExports.h>
namespace mitk
{
class MITKDIFFUSIONCORE_EXPORT BValueMapPropertySerializer : public BasePropertySerializer
{
protected:
void split(const std::string &s, char delim, std::vector<unsigned int> &elems) {
std::stringstream ss(s);
std::string item;
while (std::getline(ss, item, delim)) {
elems.push_back(std::atoi(item.c_str()));
}
}
std::vector<unsigned int> split(const std::string &s, char delim) {
std::vector<unsigned int> elems;
split(s, delim, elems);
return elems;
}
public:
mitkClassMacro( BValueMapPropertySerializer, BasePropertySerializer )
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
TiXmlElement* Serialize() override
{
if (const BValueMapProperty* prop = dynamic_cast<const BValueMapProperty*>(m_Property.GetPointer()))
{
BValueMapProperty::BValueMap map = prop->GetBValueMap();
if(map.empty()) return nullptr;
BValueMapProperty::BValueMap::const_iterator it = map.begin();
BValueMapProperty::BValueMap::const_iterator end = map.end();
auto element = new TiXmlElement("bvaluemap");
while (it != end) {
auto child = new TiXmlElement("entry");
{
std::stringstream ss;
ss << it->first;
child->SetAttribute("key", ss.str());
}
{
std::stringstream ss;
for(unsigned int i = 0 ; i < it->second.size(); i++)
{
ss << it->second[i] << ",";
}
child->SetAttribute("value", ss.str());
}
element->InsertEndChild(*child);
++it;
}
return element;
}
else return nullptr;
}
BaseProperty::Pointer Deserialize(TiXmlElement* element) override
{
if (!element) return nullptr;
BValueMapProperty::BValueMap map;
TiXmlElement* entry = element->FirstChildElement( "entry" )->ToElement();
while(entry != nullptr){
std::string key, value;
entry->QueryStringAttribute("key",&key);
entry->QueryStringAttribute("value",&value);
std::vector<unsigned int> indices = split(value.c_str(), ',');
map[std::atoi(key.c_str())] = indices;
entry = entry->NextSiblingElement( "entry" );
}
return BValueMapProperty::New(map).GetPointer();
}
protected:
BValueMapPropertySerializer(){}
~BValueMapPropertySerializer() override {}
};
} // namespace
// important to put this into the GLOBAL namespace (because it starts with 'namespace mitk')
MITK_REGISTER_SERIALIZER(BValueMapPropertySerializer)
#endif
diff --git a/Modules/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.cpp b/Modules/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.cpp
index ef453be..119db6a 100644
--- a/Modules/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.cpp
+++ b/Modules/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.cpp
@@ -1,615 +1,615 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkDiffusionPropertyHelper.h"
#include <mitkITKImageImport.h>
#include <mitkImageCast.h>
#include <itkImageRegionIterator.h>
#include <mitkProperties.h>
#include <vnl/algo/vnl_matrix_inverse.h>
#include <mitkCoreServices.h>
#include <mitkPropertyPersistenceInfo.h>
#include <mitkIPropertyDescriptions.h>
#include <mitkIPropertyPersistence.h>
const std::string mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME = "DWMRI.GradientDirections";
const std::string mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME = "DWMRI.OriginalGradientDirections";
const std::string mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME = "DWMRI.MeasurementFrame";
const std::string mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME = "DWMRI.ReferenceBValue";
const std::string mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME = "DWMRI.BValueMap";
const std::string mitk::DiffusionPropertyHelper::MODALITY = "DWMRI.Modality";
const std::string mitk::DiffusionPropertyHelper::APPLY_MATRIX_TO_GRADIENTS = "DWMRI.ApplyMatrixToGradients";
const std::string mitk::DiffusionPropertyHelper::APPLY_MF_TO_GRADIENTS = "DWMRI.ApplyMfToGradients";
mitk::DiffusionPropertyHelper::DiffusionPropertyHelper()
{
}
mitk::DiffusionPropertyHelper::~DiffusionPropertyHelper()
{
}
mitk::DiffusionPropertyHelper::ImageType::Pointer mitk::DiffusionPropertyHelper::GetItkVectorImage(mitk::Image* image)
{
ImageType::Pointer vectorImage = ImageType::New();
mitk::CastToItkImage(image, vectorImage);
return vectorImage;
}
mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer
mitk::DiffusionPropertyHelper::CalcAveragedDirectionSet(double precision, GradientDirectionsContainerType::Pointer directions)
{
// save old and construct new direction container
GradientDirectionsContainerType::Pointer newDirections = GradientDirectionsContainerType::New();
// fill new direction container
for(GradientDirectionsContainerType::ConstIterator gdcitOld = directions->Begin();
gdcitOld != directions->End(); ++gdcitOld)
{
// already exists?
bool found = false;
for(GradientDirectionsContainerType::ConstIterator gdcitNew = newDirections->Begin();
gdcitNew != newDirections->End(); ++gdcitNew)
{
if(AreAlike(gdcitNew.Value(), gdcitOld.Value(), precision))
{
found = true;
break;
}
}
// if not found, add it to new container
if(!found)
{
newDirections->push_back(gdcitOld.Value());
}
}
return newDirections;
}
void mitk::DiffusionPropertyHelper::AverageRedundantGradients(mitk::Image* image, double precision)
{
GradientDirectionsContainerType::Pointer oldDirs = GetOriginalGradientContainer(image);
GradientDirectionsContainerType::Pointer newDirs = CalcAveragedDirectionSet(precision, oldDirs);
// if sizes equal, we do not need to do anything in this function
if(oldDirs->size() == newDirs->size())
return;
// new image
ImageType::Pointer oldImage = ImageType::New();
mitk::CastToItkImage( image, oldImage);
ImageType::Pointer newITKImage = ImageType::New();
newITKImage->SetSpacing( oldImage->GetSpacing() ); // Set the image spacing
newITKImage->SetOrigin( oldImage->GetOrigin() ); // Set the image origin
newITKImage->SetDirection( oldImage->GetDirection() ); // Set the image direction
newITKImage->SetLargestPossibleRegion( oldImage->GetLargestPossibleRegion() );
newITKImage->SetVectorLength( newDirs->size() );
newITKImage->SetBufferedRegion( oldImage->GetLargestPossibleRegion() );
newITKImage->Allocate();
// average image data that corresponds to identical directions
itk::ImageRegionIterator< ImageType > newIt(newITKImage, newITKImage->GetLargestPossibleRegion());
newIt.GoToBegin();
itk::ImageRegionIterator< ImageType > oldIt(oldImage, oldImage->GetLargestPossibleRegion());
oldIt.GoToBegin();
// initial new value of voxel
ImageType::PixelType newVec;
newVec.SetSize(newDirs->size());
newVec.AllocateElements(newDirs->size());
// find which gradients should be averaged
GradientDirectionsContainerType::Pointer oldDirections = oldDirs;
std::vector<std::vector<int> > dirIndices;
for(GradientDirectionsContainerType::ConstIterator gdcitNew = newDirs->Begin();
gdcitNew != newDirs->End(); ++gdcitNew)
{
dirIndices.push_back(std::vector<int>(0));
for(GradientDirectionsContainerType::ConstIterator gdcitOld = oldDirs->Begin();
gdcitOld != oldDirections->End(); ++gdcitOld)
{
if(AreAlike(gdcitNew.Value(), gdcitOld.Value(), precision))
{
//MITK_INFO << gdcitNew.Value() << " " << gdcitOld.Value();
dirIndices[gdcitNew.Index()].push_back(gdcitOld.Index());
}
}
}
//int ind1 = -1;
while(!newIt.IsAtEnd())
{
// init new vector with zeros
newVec.Fill(0.0);
// the old voxel value with duplicates
ImageType::PixelType oldVec = oldIt.Get();
for(unsigned int i=0; i<dirIndices.size(); i++)
{
// do the averaging
const unsigned int numavg = dirIndices[i].size();
unsigned int sum = 0;
for(unsigned int j=0; j<numavg; j++)
{
//MITK_INFO << newVec[i] << " << " << oldVec[dirIndices[i].at(j)];
sum += oldVec[dirIndices[i].at(j)];
}
if(numavg == 0)
{
MITK_ERROR << "VectorImage: Error on averaging. Possibly due to corrupted data";
return;
}
newVec[i] = sum / numavg;
}
newIt.Set(newVec);
++newIt;
++oldIt;
}
mitk::GrabItkImageMemory( newITKImage, image );
SetOriginalGradientContainer(image, newDirs);
InitializeImage(image);
std::cout << std::endl;
}
void mitk::DiffusionPropertyHelper::ApplyMeasurementFrameAndRotationMatrix(mitk::Image* image)
{
if( image->GetProperty(mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str()).IsNull() )
{
return;
}
GradientDirectionsContainerType::Pointer originalDirections = GetOriginalGradientContainer(image);
MeasurementFrameType measurementFrame = GetMeasurementFrame(image);
mitk::Vector3D s = image->GetGeometry()->GetSpacing();
mitk::VnlVector c0 = image->GetGeometry()->GetMatrixColumn(0)/s[0];
mitk::VnlVector c1 = image->GetGeometry()->GetMatrixColumn(1)/s[1];
mitk::VnlVector c2 = image->GetGeometry()->GetMatrixColumn(2)/s[2];
MeasurementFrameType imageRotationMatrix;
imageRotationMatrix[0][0] = c0[0];
imageRotationMatrix[1][0] = c0[1];
imageRotationMatrix[2][0] = c0[2];
imageRotationMatrix[0][1] = c1[0];
imageRotationMatrix[1][1] = c1[1];
imageRotationMatrix[2][1] = c1[2];
imageRotationMatrix[0][2] = c2[0];
imageRotationMatrix[1][2] = c2[1];
imageRotationMatrix[2][2] = c2[2];
GradientDirectionsContainerType::Pointer directions = GradientDirectionsContainerType::New();
if( originalDirections.IsNull() || ( originalDirections->size() == 0 ) )
{
// original direction container was not set
return;
}
bool apply_matrix = true;
image->GetPropertyList()->GetBoolProperty(mitk::DiffusionPropertyHelper::APPLY_MATRIX_TO_GRADIENTS.c_str(), apply_matrix);
bool apply_mf = true;
image->GetPropertyList()->GetBoolProperty(mitk::DiffusionPropertyHelper::APPLY_MF_TO_GRADIENTS.c_str(), apply_mf);
if (apply_matrix)
{
MITK_INFO << "Applying image rotation to diffusion-gradient directions:";
std::cout << imageRotationMatrix << std::endl;
}
if (apply_mf)
{
MITK_INFO << "Applying measurement frame to diffusion-gradient directions:";
std::cout << measurementFrame << std::endl;
}
int c = 0;
for(GradientDirectionsContainerType::ConstIterator gdcit = originalDirections->Begin();
gdcit != originalDirections->End(); ++gdcit)
{
vnl_vector<double> vec = gdcit.Value();
if (apply_matrix)
vec = vec.pre_multiply(measurementFrame);
if (apply_mf)
vec = vec.pre_multiply(imageRotationMatrix);
directions->InsertElement(c, vec);
c++;
}
SetGradientContainer(image, directions);
}
void mitk::DiffusionPropertyHelper::UnApplyMeasurementFrameAndRotationMatrix(mitk::Image* image)
{
if( image->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).IsNull() )
{
return;
}
GradientDirectionsContainerType::Pointer modifiedDirections = GetGradientContainer(image);
MeasurementFrameType measurementFrame = GetMeasurementFrame(image);
measurementFrame = vnl_matrix_inverse<double>(measurementFrame).pinverse();
mitk::Vector3D s = image->GetGeometry()->GetSpacing();
mitk::VnlVector c0 = image->GetGeometry()->GetMatrixColumn(0)/s[0];
mitk::VnlVector c1 = image->GetGeometry()->GetMatrixColumn(1)/s[1];
mitk::VnlVector c2 = image->GetGeometry()->GetMatrixColumn(2)/s[2];
MeasurementFrameType imageRotationMatrix;
imageRotationMatrix[0][0] = c0[0];
imageRotationMatrix[1][0] = c0[1];
imageRotationMatrix[2][0] = c0[2];
imageRotationMatrix[0][1] = c1[0];
imageRotationMatrix[1][1] = c1[1];
imageRotationMatrix[2][1] = c1[2];
imageRotationMatrix[0][2] = c2[0];
imageRotationMatrix[1][2] = c2[1];
imageRotationMatrix[2][2] = c2[2];
imageRotationMatrix = vnl_matrix_inverse<double>(imageRotationMatrix).pinverse();
GradientDirectionsContainerType::Pointer directions = GradientDirectionsContainerType::New();
if( modifiedDirections.IsNull() || ( modifiedDirections->size() == 0 ) )
{
// original direction container was not set
return;
}
bool apply_matrix = true;
image->GetPropertyList()->GetBoolProperty(mitk::DiffusionPropertyHelper::APPLY_MATRIX_TO_GRADIENTS.c_str(), apply_matrix);
bool apply_mf = true;
image->GetPropertyList()->GetBoolProperty(mitk::DiffusionPropertyHelper::APPLY_MF_TO_GRADIENTS.c_str(), apply_mf);
if (apply_matrix)
{
MITK_INFO << "Reverting image rotation to diffusion-gradient directions:";
std::cout << imageRotationMatrix << std::endl;
}
if (apply_mf)
{
MITK_INFO << "Reverting measurement frame to diffusion-gradient directions:";
std::cout << measurementFrame << std::endl;
}
int c = 0;
for(GradientDirectionsContainerType::ConstIterator gdcit = modifiedDirections->Begin();
gdcit != modifiedDirections->End(); ++gdcit)
{
vnl_vector<double> vec = gdcit.Value();
if (apply_matrix)
vec = vec.pre_multiply(imageRotationMatrix);
if (apply_mf)
vec = vec.pre_multiply(measurementFrame);
directions->InsertElement(c, vec);
c++;
}
SetOriginalGradientContainer(image, directions);
}
void mitk::DiffusionPropertyHelper::SetApplyMatrixToGradients(mitk::Image* image, bool apply)
{
image->GetPropertyList()->SetProperty( mitk::DiffusionPropertyHelper::APPLY_MATRIX_TO_GRADIENTS.c_str(), mitk::BoolProperty::New(apply) );
}
void mitk::DiffusionPropertyHelper::SetApplyMfToGradients(mitk::Image* image, bool apply)
{
image->GetPropertyList()->SetProperty( mitk::DiffusionPropertyHelper::APPLY_MF_TO_GRADIENTS.c_str(), mitk::BoolProperty::New(apply) );
}
void mitk::DiffusionPropertyHelper::UpdateBValueMap(mitk::Image* image)
{
BValueMapType b_ValueMap;
if(image->GetProperty(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str()).IsNotNull())
b_ValueMap = GetBValueMap(image);
if(!b_ValueMap.empty())
b_ValueMap.clear();
if(GetGradientContainer(image).IsNotNull())
{
GradientDirectionsContainerType::Pointer directions = GetGradientContainer(image);
for(auto gdcit = directions->Begin(); gdcit!=directions->End(); ++gdcit)
{
b_ValueMap[GetB_Value(image, gdcit.Index())].push_back(gdcit.Index());
}
}
SetBValueMap(image, b_ValueMap);
}
bool mitk::DiffusionPropertyHelper::AreAlike(GradientDirectionType g1, GradientDirectionType g2, double precision)
{
GradientDirectionType diff = g1 - g2;
GradientDirectionType diff2 = g1 + g2;
return diff.two_norm() < precision || diff2.two_norm() < precision;
}
float mitk::DiffusionPropertyHelper::GetB_Value(const mitk::Image* image, unsigned int i)
{
GradientDirectionsContainerType::Pointer directions = GetGradientContainer(image);
float b_value = GetReferenceBValue(image);
if(i > directions->Size()-1)
return -1;
if(directions->ElementAt(i).one_norm() <= 0.0)
{
return 0;
}
else
{
double twonorm = directions->ElementAt(i).two_norm();
double bval = b_value*twonorm*twonorm;
if (bval<0)
bval = ceil(bval - 0.5);
else
bval = floor(bval + 0.5);
return bval;
}
}
void mitk::DiffusionPropertyHelper::CopyProperties(mitk::Image* source, mitk::Image* target, bool ignore_original_gradients)
{
mitk::PropertyList::Pointer props = source->GetPropertyList()->Clone();
if (ignore_original_gradients)
props->RemoveProperty(mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME);
target->SetPropertyList(props);
}
void mitk::DiffusionPropertyHelper::InitializeImage(mitk::Image* image)
{
if ( image->GetProperty(mitk::DiffusionPropertyHelper::APPLY_MATRIX_TO_GRADIENTS.c_str()).IsNull() )
image->SetProperty( mitk::DiffusionPropertyHelper::APPLY_MATRIX_TO_GRADIENTS.c_str(), mitk::BoolProperty::New(true) );
if ( image->GetProperty(mitk::DiffusionPropertyHelper::APPLY_MF_TO_GRADIENTS.c_str()).IsNull() )
image->SetProperty( mitk::DiffusionPropertyHelper::APPLY_MF_TO_GRADIENTS.c_str(), mitk::BoolProperty::New(true) );
if( image->GetProperty(mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str()).IsNull() )
{
// we don't have the original gradient directions. Therefore use the modified directions and rotate them back.
UnApplyMeasurementFrameAndRotationMatrix(image);
}
else
ApplyMeasurementFrameAndRotationMatrix(image);
UpdateBValueMap(image);
// initialize missing properties
mitk::MeasurementFrameProperty::Pointer mf = dynamic_cast<mitk::MeasurementFrameProperty *>( image->GetProperty(MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer());
if( mf.IsNull() )
{
//no measurement frame present, identity is assumed
MeasurementFrameType identity;
identity.set_identity();
image->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( identity ));
}
}
bool mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(const mitk::DataNode* node)
{
if ( node==nullptr )
return false;
if ( node->GetData()==nullptr )
return false;
return IsDiffusionWeightedImage(dynamic_cast<mitk::Image *>(node->GetData()));
}
bool mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(const mitk::Image * image)
{
bool isDiffusionWeightedImage( true );
if( image == nullptr )
{
isDiffusionWeightedImage = false;
}
if( isDiffusionWeightedImage )
{
mitk::FloatProperty::Pointer referenceBValue = dynamic_cast<mitk::FloatProperty *>(image->GetProperty(REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer());
if( referenceBValue.IsNull() )
{
isDiffusionWeightedImage = false;
}
}
unsigned int gradientDirections( 0 );
if( isDiffusionWeightedImage )
{
mitk::GradientDirectionsProperty::Pointer gradientDirectionsProperty = dynamic_cast<mitk::GradientDirectionsProperty *>(image->GetProperty(GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer());
if( gradientDirectionsProperty.IsNull() )
{
isDiffusionWeightedImage = false;
}
else
{
gradientDirections = gradientDirectionsProperty->GetGradientDirectionsContainer()->size();
}
}
if( isDiffusionWeightedImage )
{
unsigned int components = image->GetPixelType().GetNumberOfComponents();
if( components != gradientDirections )
{
isDiffusionWeightedImage = false;
}
}
return isDiffusionWeightedImage;
}
const mitk::DiffusionPropertyHelper::BValueMapType & mitk::DiffusionPropertyHelper::GetBValueMap(const mitk::Image *image)
{
return dynamic_cast<mitk::BValueMapProperty *>(image->GetProperty(BVALUEMAPPROPERTYNAME.c_str()).GetPointer())->GetBValueMap();
}
std::vector< int > mitk::DiffusionPropertyHelper::GetBValueVector(const mitk::Image* image)
{
auto gcon = mitk::DiffusionPropertyHelper::GetGradientContainer(image);
float b_value = mitk::DiffusionPropertyHelper::GetReferenceBValue(image);
std::vector< int > bvalues;
for (unsigned int i=0; i<gcon->Size(); ++i)
{
double twonorm = gcon->ElementAt(i).two_norm();
double bval = b_value*twonorm*twonorm;
if (bval<0)
bval = ceil(bval - 0.5);
else
bval = floor(bval + 0.5);
bvalues.push_back(bval);
}
return bvalues;
}
float mitk::DiffusionPropertyHelper::GetReferenceBValue(const mitk::Image *image)
{
return dynamic_cast<mitk::FloatProperty *>(image->GetProperty(REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer())->GetValue();
}
const mitk::DiffusionPropertyHelper::MeasurementFrameType & mitk::DiffusionPropertyHelper::GetMeasurementFrame(const mitk::Image *image)
{
mitk::MeasurementFrameProperty::Pointer mf = dynamic_cast<mitk::MeasurementFrameProperty *>( image->GetProperty(MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer());
if( mf.IsNull() )
{
//no measurement frame present, identity is assumed
MeasurementFrameType identity;
identity.set_identity();
mf = mitk::MeasurementFrameProperty::New( identity );
}
return mf->GetMeasurementFrame();
}
mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer mitk::DiffusionPropertyHelper::GetOriginalGradientContainer(const mitk::Image *image)
{
return dynamic_cast<mitk::GradientDirectionsProperty *>(image->GetProperty(ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer())->GetGradientDirectionsContainer();
}
mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer mitk::DiffusionPropertyHelper::GetGradientContainer(const mitk::Image *image)
{
return dynamic_cast<mitk::GradientDirectionsProperty *>(image->GetProperty(GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer())->GetGradientDirectionsContainer();
}
void mitk::DiffusionPropertyHelper::SetReferenceBValue(mitk::Image* image, float b_value)
{
image->GetPropertyList()->ReplaceProperty(REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New(b_value));
}
void mitk::DiffusionPropertyHelper::SetBValueMap(mitk::Image* image, BValueMapType map)
{
image->GetPropertyList()->ReplaceProperty( mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME.c_str(), mitk::BValueMapProperty::New(map));
}
void mitk::DiffusionPropertyHelper::SetOriginalGradientContainer(mitk::Image* image, GradientDirectionsContainerType::Pointer g_cont)
{
image->GetPropertyList()->ReplaceProperty(ORIGINALGRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New(g_cont));
}
void mitk::DiffusionPropertyHelper::SetGradientContainer(mitk::Image* image, GradientDirectionsContainerType::Pointer g_cont)
{
image->GetPropertyList()->ReplaceProperty(GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New(g_cont));
}
void mitk::DiffusionPropertyHelper::SetMeasurementFrame(mitk::Image* image, MeasurementFrameType mf)
{
image->GetPropertyList()->ReplaceProperty( MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( mf ) );
}
void mitk::DiffusionPropertyHelper::RotateGradients(mitk::Image* image, vnl_matrix_fixed<double, 3, 3> rotation_matrix, bool normalize_columns)
{
if (normalize_columns)
rotation_matrix = rotation_matrix.normalize_columns();
int c = 0;
auto new_gradients = GradientDirectionsContainerType::New();
auto old_gradients = GetGradientContainer(image);
for(auto gdcit = old_gradients->Begin(); gdcit != old_gradients->End(); ++gdcit)
{
vnl_vector<double> vec = gdcit.Value();
vec = vec.pre_multiply(rotation_matrix);
new_gradients->InsertElement(c, vec);
c++;
}
SetGradientContainer(image, new_gradients);
}
void mitk::DiffusionPropertyHelper::RotateOriginalGradients(mitk::Image* image, vnl_matrix_fixed<double, 3, 3> rotation_matrix, bool normalize_columns)
{
if (normalize_columns)
rotation_matrix = rotation_matrix.normalize_columns();
int c = 0;
auto new_gradients = GradientDirectionsContainerType::New();
auto old_gradients = GetOriginalGradientContainer(image);
for(auto gdcit = old_gradients->Begin(); gdcit != old_gradients->End(); ++gdcit)
{
vnl_vector<double> vec = gdcit.Value();
vec = vec.pre_multiply(rotation_matrix);
new_gradients->InsertElement(c, vec);
c++;
}
SetOriginalGradientContainer(image, new_gradients);
}
void mitk::DiffusionPropertyHelper::SetupProperties()
{
//register relevant properties
//non-persistent properties
mitk::CoreServices::GetPropertyDescriptions()->AddDescription(mitk::DiffusionPropertyHelper::BVALUEMAPPROPERTYNAME, "This map stores which b values belong to which gradients.");
mitk::CoreServices::GetPropertyDescriptions()->AddDescription(mitk::DiffusionPropertyHelper::ORIGINALGRADIENTCONTAINERPROPERTYNAME, "The original gradients used during acquisition. This property may be empty.");
//persistent properties
mitk::CoreServices::GetPropertyDescriptions()->AddDescription(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME, "The reference b value the gradients are normalized to.");
mitk::CoreServices::GetPropertyDescriptions()->AddDescription(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME, "The measurment frame used during acquisition.");
mitk::CoreServices::GetPropertyDescriptions()->AddDescription(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME, "The gradients after applying measurement frame and image matrix.");
mitk::CoreServices::GetPropertyDescriptions()->AddDescription(mitk::DiffusionPropertyHelper::MODALITY, "Defines the modality used for acquisition. DWMRI signifies diffusion weighted images.");
mitk::PropertyPersistenceInfo::Pointer PPI_referenceBValue = mitk::PropertyPersistenceInfo::New();
PPI_referenceBValue->SetNameAndKey(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME, "DWMRI_b-value");
mitk::PropertyPersistenceInfo::Pointer PPI_measurementFrame = mitk::PropertyPersistenceInfo::New();
PPI_measurementFrame->SetNameAndKey(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME, "measurement frame");
mitk::PropertyPersistenceInfo::Pointer PPI_gradientContainer = mitk::PropertyPersistenceInfo::New();
PPI_gradientContainer->SetNameAndKey(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME, "DWMRI_gradient");
mitk::PropertyPersistenceInfo::Pointer PPI_modality = mitk::PropertyPersistenceInfo::New();
PPI_modality->SetNameAndKey(mitk::DiffusionPropertyHelper::MODALITY, "modality");
mitk::CoreServices::GetPropertyPersistence()->AddInfo(PPI_referenceBValue.GetPointer() , true);
mitk::CoreServices::GetPropertyPersistence()->AddInfo(PPI_measurementFrame.GetPointer(), true);
mitk::CoreServices::GetPropertyPersistence()->AddInfo(PPI_gradientContainer.GetPointer(), true);
mitk::CoreServices::GetPropertyPersistence()->AddInfo(PPI_modality.GetPointer(), true);
}
diff --git a/Modules/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.h b/Modules/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.h
index 13b8ca2..db0d97d 100644
--- a/Modules/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.h
+++ b/Modules/DiffusionCore/IODataStructures/Properties/mitkDiffusionPropertyHelper.h
@@ -1,126 +1,126 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKDIFFUSIONPROPERTYHELPER_H
#define MITKDIFFUSIONPROPERTYHELPER_H
#include <MitkDiffusionCoreExports.h>
#include <mitkImage.h>
#include <mitkBValueMapProperty.h>
#include <mitkGradientDirectionsProperty.h>
#include <mitkMeasurementFrameProperty.h>
#include <mitkDataNode.h>
#include <usModuleActivator.h>
namespace mitk
{
/** \brief Helper class for mitk::Images containing diffusion weighted data
*
* This class takes a pointer to a mitk::Image containing diffusion weighted information and provides
* functions to manipulate the diffusion meta-data. Will log an error if required information is
* missing.
*/
class MITKDIFFUSIONCORE_EXPORT DiffusionPropertyHelper
{
public:
typedef short DiffusionPixelType;
typedef mitk::BValueMapProperty::BValueMap BValueMapType;
typedef GradientDirectionsProperty::GradientDirectionType GradientDirectionType;
typedef GradientDirectionsProperty::GradientDirectionsContainerType GradientDirectionsContainerType;
typedef mitk::MeasurementFrameProperty::MeasurementFrameType MeasurementFrameType;
typedef itk::VectorImage< DiffusionPixelType, 3> ImageType;
static bool IsDiffusionWeightedImage(const mitk::Image *);
static bool IsDiffusionWeightedImage(const mitk::DataNode* node);
static void CopyProperties(mitk::Image* source, mitk::Image* target, bool ignore_original_gradients=false);
static ImageType::Pointer GetItkVectorImage(Image *image);
static const BValueMapType & GetBValueMap(const mitk::Image *);
static float GetReferenceBValue(const mitk::Image *);
static std::vector< int > GetBValueVector(const mitk::Image *);
static const MeasurementFrameType & GetMeasurementFrame(const mitk::Image *);
static GradientDirectionsContainerType::Pointer GetOriginalGradientContainer(const mitk::Image *);
static GradientDirectionsContainerType::Pointer GetGradientContainer(const mitk::Image *);
static void SetApplyMatrixToGradients(mitk::Image* image, bool apply);
static void SetApplyMfToGradients(mitk::Image* image, bool apply);
static void SetMeasurementFrame(mitk::Image* image, MeasurementFrameType mf);
static void SetReferenceBValue(mitk::Image* image, float b_value);
static void SetBValueMap(mitk::Image* image, BValueMapType map);
static void SetOriginalGradientContainer(mitk::Image* image, GradientDirectionsContainerType::Pointer g_cont);
static void SetGradientContainer(mitk::Image* image, GradientDirectionsContainerType::Pointer g_cont);
static void RotateGradients(mitk::Image* image, vnl_matrix_fixed<double, 3, 3> rotation_matrix, bool normalize_columns);
static void RotateOriginalGradients(mitk::Image* image, vnl_matrix_fixed<double, 3, 3> rotation_matrix, bool normalize_columns);
static void AverageRedundantGradients(mitk::Image* image, double precision);
static void InitializeImage(mitk::Image* image);
static GradientDirectionsContainerType::Pointer CalcAveragedDirectionSet(double precision, GradientDirectionsContainerType::Pointer directions);
static void SetupProperties(); // called in DiffusionCoreIOActivator
static const std::string GetBvaluePropertyName() { return BVALUEMAPPROPERTYNAME; }
static const std::string GetGradientContainerPropertyName() { return GRADIENTCONTAINERPROPERTYNAME; }
static const std::string GetMeasurementFramePropertyName() { return MEASUREMENTFRAMEPROPERTYNAME; }
protected:
DiffusionPropertyHelper();
~DiffusionPropertyHelper();
static const std::string GRADIENTCONTAINERPROPERTYNAME;
static const std::string ORIGINALGRADIENTCONTAINERPROPERTYNAME;
static const std::string MEASUREMENTFRAMEPROPERTYNAME;
static const std::string REFERENCEBVALUEPROPERTYNAME;
static const std::string BVALUEMAPPROPERTYNAME;
static const std::string MODALITY;
static const std::string APPLY_MATRIX_TO_GRADIENTS;
static const std::string APPLY_MF_TO_GRADIENTS;
/**
* \brief Apply the previously set MeasurementFrame and the image rotation matrix to all gradients
*
* \warning first set the MeasurementFrame
*/
static void ApplyMeasurementFrameAndRotationMatrix(mitk::Image* image);
/**
* \brief Apply the inverse of the previously set MeasurementFrame and the image rotation matrix to all gradients
*
* \warning first set the MeasurementFrame
*/
static void UnApplyMeasurementFrameAndRotationMatrix(mitk::Image* image);
/**
* \brief Update the BValueMap (m_B_ValueMap) using the current gradient directions (m_Directions)
*
* \warning Have to be called after each manipulation on the GradientDirectionContainer
* !especially after manipulation of the m_Directions (GetDirections()) container via pointer access!
*/
static void UpdateBValueMap(mitk::Image* image);
/// Determines whether gradients can be considered to be equal
static bool AreAlike(GradientDirectionType g1, GradientDirectionType g2, double precision);
/// Get the b value belonging to an index
static float GetB_Value(const mitk::Image* image, unsigned int i);
};
}
#endif
diff --git a/Modules/DiffusionCore/IODataStructures/Properties/mitkGradientDirectionsProperty.cpp b/Modules/DiffusionCore/IODataStructures/Properties/mitkGradientDirectionsProperty.cpp
index 36ad4a0..43c0a03 100644
--- a/Modules/DiffusionCore/IODataStructures/Properties/mitkGradientDirectionsProperty.cpp
+++ b/Modules/DiffusionCore/IODataStructures/Properties/mitkGradientDirectionsProperty.cpp
@@ -1,83 +1,83 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkGradientDirectionsProperty.h"
mitk::GradientDirectionsProperty::GradientDirectionsProperty()
{
m_GradientDirectionsContainer = mitk::GradientDirectionsProperty::GradientDirectionsContainerType::New();
}
mitk::GradientDirectionsProperty::GradientDirectionsProperty(const GradientDirectionsProperty& other)
: mitk::BaseProperty(other)
{
m_GradientDirectionsContainer = other.GetGradientDirectionsContainer();
}
mitk::GradientDirectionsProperty::GradientDirectionsProperty(const GradientDirectionsContainerType::Pointer gradientDirectionsContainer)
{
m_GradientDirectionsContainer = gradientDirectionsContainer;
}
mitk::GradientDirectionsProperty::GradientDirectionsProperty(const AlternativeGradientDirectionsContainerType gradientDirectionsContainer)
{
m_GradientDirectionsContainer = mitk::GradientDirectionsProperty::GradientDirectionsContainerType::New();
for(unsigned int index(0); index < gradientDirectionsContainer.size(); index++)
{
GradientDirectionType newDirection = gradientDirectionsContainer.at(index).GetVnlVector();
m_GradientDirectionsContainer->InsertElement( index, newDirection);
}
}
mitk::GradientDirectionsProperty::~GradientDirectionsProperty()
{
}
const mitk::GradientDirectionsProperty::GradientDirectionsContainerType::Pointer mitk::GradientDirectionsProperty::GetGradientDirectionsContainer() const
{
return m_GradientDirectionsContainer;
}
bool mitk::GradientDirectionsProperty::IsEqual(const BaseProperty& property) const
{
GradientDirectionsContainerType::Pointer lhs = this->m_GradientDirectionsContainer;
GradientDirectionsContainerType::Pointer rhs = static_cast<const Self&>(property).m_GradientDirectionsContainer;
if(lhs->Size() != rhs->Size()) return false;
GradientDirectionsContainerType::Iterator lhsit = lhs->Begin();
GradientDirectionsContainerType::Iterator rhsit = rhs->Begin();
bool equal = true;
for(unsigned int i = 0 ; i < lhs->Size(); i++, ++lhsit, ++rhsit)
equal |= lhsit.Value() == rhsit.Value();
return equal;
}
bool mitk::GradientDirectionsProperty::Assign(const BaseProperty& property)
{
this->m_GradientDirectionsContainer = static_cast<const Self&>(property).m_GradientDirectionsContainer;
return true;
}
itk::LightObject::Pointer mitk::GradientDirectionsProperty::InternalClone() const
{
itk::LightObject::Pointer result(new Self(*this));
result->UnRegister();
return result;
}
diff --git a/Modules/DiffusionCore/IODataStructures/Properties/mitkGradientDirectionsProperty.h b/Modules/DiffusionCore/IODataStructures/Properties/mitkGradientDirectionsProperty.h
index b0cb0e3..e23dbce 100644
--- a/Modules/DiffusionCore/IODataStructures/Properties/mitkGradientDirectionsProperty.h
+++ b/Modules/DiffusionCore/IODataStructures/Properties/mitkGradientDirectionsProperty.h
@@ -1,68 +1,68 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKGRADIENTDIRECTIONSPROPERTY_H
#define MITKGRADIENTDIRECTIONSPROPERTY_H
#include "mitkBaseProperty.h"
#include <vnl/vnl_vector_fixed.h>
#include <itkVectorContainer.h>
#include <itkVector.h>
#include <MitkDiffusionCoreExports.h>
namespace mitk
{
/** This property will store the gradients directions and the original gradient directions */
class MITKDIFFUSIONCORE_EXPORT GradientDirectionsProperty : public mitk::BaseProperty
{
public:
typedef unsigned int IndexType;
typedef vnl_vector_fixed< double, 3 > ValueType;
typedef ValueType GradientDirectionType;
typedef itk::VectorContainer< IndexType, GradientDirectionType > GradientDirectionsContainerType;
typedef std::vector< itk::Vector<double,3> > AlternativeGradientDirectionsContainerType;
mitkClassMacro(GradientDirectionsProperty, BaseProperty)
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitkNewMacro1Param(GradientDirectionsProperty, const GradientDirectionsProperty&);
mitkNewMacro1Param(GradientDirectionsProperty, const GradientDirectionsContainerType::Pointer);
mitkNewMacro1Param(GradientDirectionsProperty, const AlternativeGradientDirectionsContainerType );
const GradientDirectionsContainerType::Pointer GetGradientDirectionsContainer() const;
protected:
GradientDirectionsProperty();
~GradientDirectionsProperty() override;
GradientDirectionsProperty(const GradientDirectionsProperty& other);
GradientDirectionsProperty(const GradientDirectionsContainerType::Pointer gradientDirectionsContainer);
GradientDirectionsProperty(const AlternativeGradientDirectionsContainerType gradientDirectionsContainer);
bool IsEqual(const BaseProperty& property) const override;
bool Assign(const BaseProperty & property) override;
GradientDirectionsContainerType::Pointer m_GradientDirectionsContainer;
itk::LightObject::Pointer InternalClone() const override;
};
}
#endif
diff --git a/Modules/DiffusionCore/IODataStructures/Properties/mitkGradientDirectionsPropertySerializer.cpp b/Modules/DiffusionCore/IODataStructures/Properties/mitkGradientDirectionsPropertySerializer.cpp
index 0998e63..8b68fe2 100644
--- a/Modules/DiffusionCore/IODataStructures/Properties/mitkGradientDirectionsPropertySerializer.cpp
+++ b/Modules/DiffusionCore/IODataStructures/Properties/mitkGradientDirectionsPropertySerializer.cpp
@@ -1,106 +1,106 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkGradientDirectionPropertySerializer_h_included
#define mitkGradientDirectionPropertySerializer_h_included
#include "mitkBasePropertySerializer.h"
#include "mitkGradientDirectionsProperty.h"
#include "MitkDiffusionCoreExports.h"
namespace mitk
{
class MITKDIFFUSIONCORE_EXPORT GradientDirectionsPropertySerializer : public BasePropertySerializer
{
public:
mitkClassMacro( GradientDirectionsPropertySerializer, BasePropertySerializer )
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
TiXmlElement* Serialize() override
{
if (const GradientDirectionsProperty* prop = dynamic_cast<const GradientDirectionsProperty*>(m_Property.GetPointer()))
{
typedef mitk::GradientDirectionsProperty::GradientDirectionsContainerType GradientDirectionsContainerType;
GradientDirectionsContainerType::Pointer gdc = prop->GetGradientDirectionsContainer().GetPointer();
if(gdc.IsNull() || gdc->Size() == 0) return nullptr;
GradientDirectionsContainerType::Iterator it = gdc->Begin();
GradientDirectionsContainerType::Iterator end = gdc->End();
auto element = new TiXmlElement("gradientdirections");
while (it != end) {
auto child = new TiXmlElement("entry");
std::stringstream ss;
ss << it.Value();
child->SetAttribute("value", ss.str());
element->InsertEndChild(*child);
++it;
}
return element;
}
else return nullptr;
}
BaseProperty::Pointer Deserialize(TiXmlElement* element) override
{
if (!element) return nullptr;
mitk::GradientDirectionsProperty::GradientDirectionsContainerType::Pointer gdc;
gdc = mitk::GradientDirectionsProperty::GradientDirectionsContainerType::New();
TiXmlElement* entry = element->FirstChildElement( "entry" )->ToElement();
while(entry != nullptr){
std::stringstream ss;
std::string value;
entry->QueryStringAttribute("value",&value);
ss << value;
vnl_vector_fixed<double, 3> vector;
vector.read_ascii(ss);
gdc->push_back(vector);
entry = entry->NextSiblingElement( "entry" );
}
return GradientDirectionsProperty::New(gdc).GetPointer();
}
protected:
GradientDirectionsPropertySerializer() {}
~GradientDirectionsPropertySerializer() override {}
};
} // namespace
// important to put this into the GLOBAL namespace (because it starts with 'namespace mitk')
MITK_REGISTER_SERIALIZER(GradientDirectionsPropertySerializer)
#endif
diff --git a/Modules/DiffusionCore/IODataStructures/Properties/mitkMeasurementFrameProperty.cpp b/Modules/DiffusionCore/IODataStructures/Properties/mitkMeasurementFrameProperty.cpp
index 58cc3bc..50a4e33 100644
--- a/Modules/DiffusionCore/IODataStructures/Properties/mitkMeasurementFrameProperty.cpp
+++ b/Modules/DiffusionCore/IODataStructures/Properties/mitkMeasurementFrameProperty.cpp
@@ -1,65 +1,65 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkMeasurementFrameProperty.h"
mitk::MeasurementFrameProperty::MeasurementFrameProperty()
: m_MeasurementFrame()
{
}
mitk::MeasurementFrameProperty::MeasurementFrameProperty(const MeasurementFrameProperty& other)
: mitk::BaseProperty(other)
{
m_MeasurementFrame = other.GetMeasurementFrame();
}
mitk::MeasurementFrameProperty::MeasurementFrameProperty(const MeasurementFrameType& measurementFrame)
{
m_MeasurementFrame = measurementFrame;
}
mitk::MeasurementFrameProperty::~MeasurementFrameProperty()
{
}
const mitk::MeasurementFrameProperty::MeasurementFrameType & mitk::MeasurementFrameProperty::GetMeasurementFrame() const
{
return m_MeasurementFrame;
}
void mitk::MeasurementFrameProperty::SetMeasurementFrame(const MeasurementFrameType & frame)
{
m_MeasurementFrame = frame;
}
bool mitk::MeasurementFrameProperty::IsEqual(const BaseProperty& property) const
{
return this->m_MeasurementFrame == static_cast<const Self&>(property).m_MeasurementFrame;
}
bool mitk::MeasurementFrameProperty::Assign(const BaseProperty& property)
{
this->m_MeasurementFrame = static_cast<const Self&>(property).m_MeasurementFrame;
return true;
}
itk::LightObject::Pointer mitk::MeasurementFrameProperty::InternalClone() const
{
itk::LightObject::Pointer result(new Self(*this));
result->UnRegister();
return result;
}
diff --git a/Modules/DiffusionCore/IODataStructures/Properties/mitkMeasurementFrameProperty.h b/Modules/DiffusionCore/IODataStructures/Properties/mitkMeasurementFrameProperty.h
index 7b984b9..d0e67c1 100644
--- a/Modules/DiffusionCore/IODataStructures/Properties/mitkMeasurementFrameProperty.h
+++ b/Modules/DiffusionCore/IODataStructures/Properties/mitkMeasurementFrameProperty.h
@@ -1,60 +1,60 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKMEASUREMENTFRAMEPROPERTY_H
#define MITKMEASUREMENTFRAMEPROPERTY_H
#include "mitkBaseProperty.h"
#include <vnl/vnl_matrix_fixed.h>
#include <MitkDiffusionCoreExports.h>
namespace mitk
{
/** This property will store the measurement frame */
class MITKDIFFUSIONCORE_EXPORT MeasurementFrameProperty : public mitk::BaseProperty
{
public:
typedef vnl_matrix_fixed< double, 3, 3 > MeasurementFrameType;
mitkClassMacro(MeasurementFrameProperty, BaseProperty)
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitkNewMacro1Param(MeasurementFrameProperty, const MeasurementFrameProperty&);
mitkNewMacro1Param(MeasurementFrameProperty, const MeasurementFrameType&);
const MeasurementFrameType &GetMeasurementFrame() const;
void SetMeasurementFrame(const MeasurementFrameType & frame);
protected:
MeasurementFrameProperty();
~MeasurementFrameProperty() override;
MeasurementFrameProperty(const MeasurementFrameProperty& other);
MeasurementFrameProperty(const MeasurementFrameType& measurementFrame);
bool IsEqual(const BaseProperty& property) const override;
bool Assign(const BaseProperty & property) override;
MeasurementFrameType m_MeasurementFrame;
itk::LightObject::Pointer InternalClone() const override;
};
}
#endif
diff --git a/Modules/DiffusionCore/IODataStructures/Properties/mitkMeasurementFramePropertySerializer.cpp b/Modules/DiffusionCore/IODataStructures/Properties/mitkMeasurementFramePropertySerializer.cpp
index 30c0e93..3251898 100644
--- a/Modules/DiffusionCore/IODataStructures/Properties/mitkMeasurementFramePropertySerializer.cpp
+++ b/Modules/DiffusionCore/IODataStructures/Properties/mitkMeasurementFramePropertySerializer.cpp
@@ -1,89 +1,89 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkMeasurementFramePropertySerializer_h_included
#define mitkMeasurementFramePropertySerializer_h_included
#include "mitkBasePropertySerializer.h"
#include "mitkMeasurementFrameProperty.h"
#include <MitkDiffusionCoreExports.h>
namespace mitk
{
class MITKDIFFUSIONCORE_EXPORT MeasurementFramePropertySerializer : public BasePropertySerializer
{
public:
mitkClassMacro( MeasurementFramePropertySerializer, BasePropertySerializer )
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
TiXmlElement* Serialize() override
{
if (const MeasurementFrameProperty* prop = dynamic_cast<const MeasurementFrameProperty*>(m_Property.GetPointer()))
{
typedef mitk::MeasurementFrameProperty::MeasurementFrameType MeasurementFrameType;
const MeasurementFrameType & mft = prop->GetMeasurementFrame();
if(mft.is_zero()) return nullptr;
auto element = new TiXmlElement("measurementframe");
auto child = new TiXmlElement("entry");
std::stringstream ss;
ss << mft;
child->SetAttribute("value", ss.str());
element->InsertEndChild(*child);
return element;
}
else return nullptr;
}
BaseProperty::Pointer Deserialize(TiXmlElement* element) override
{
if (!element) return nullptr;
TiXmlElement* entry = element->FirstChildElement( "entry" )->ToElement();
std::stringstream ss;
std::string value;
entry->QueryStringAttribute("value",&value);
ss << value;
MeasurementFrameProperty::MeasurementFrameType matrix;
matrix.read_ascii(ss);
return MeasurementFrameProperty::New(matrix).GetPointer();
}
protected:
MeasurementFramePropertySerializer() {}
~MeasurementFramePropertySerializer() override {}
};
} // namespace
// important to put this into the GLOBAL namespace (because it starts with 'namespace mitk')
MITK_REGISTER_SERIALIZER(MeasurementFramePropertySerializer)
#endif
diff --git a/Modules/DiffusionCore/IODataStructures/Properties/mitkNodePredicateIsDWI.cpp b/Modules/DiffusionCore/IODataStructures/Properties/mitkNodePredicateIsDWI.cpp
index d785a4d..9841c88 100644
--- a/Modules/DiffusionCore/IODataStructures/Properties/mitkNodePredicateIsDWI.cpp
+++ b/Modules/DiffusionCore/IODataStructures/Properties/mitkNodePredicateIsDWI.cpp
@@ -1,39 +1,39 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkNodePredicateIsDWI.h"
#include "mitkDataNode.h"
#include <mitkDiffusionPropertyHelper.h>
mitk::NodePredicateIsDWI::NodePredicateIsDWI()
: NodePredicateBase()
{
}
mitk::NodePredicateIsDWI::~NodePredicateIsDWI()
{
}
bool mitk::NodePredicateIsDWI::CheckNode(const mitk::DataNode* node) const
{
if (node == nullptr)
throw std::invalid_argument("NodePredicateIsDWI: invalid node");
mitk::Image* image = dynamic_cast<mitk::Image*>(node->GetData());
return mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( image );
}
diff --git a/Modules/DiffusionCore/IODataStructures/Properties/mitkNodePredicateIsDWI.h b/Modules/DiffusionCore/IODataStructures/Properties/mitkNodePredicateIsDWI.h
index 4edaefd..bb8e1e7 100644
--- a/Modules/DiffusionCore/IODataStructures/Properties/mitkNodePredicateIsDWI.h
+++ b/Modules/DiffusionCore/IODataStructures/Properties/mitkNodePredicateIsDWI.h
@@ -1,56 +1,56 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKNODEPREDICATEISDWI_H_HEADER_INCLUDED_
#define MITKNODEPREDICATEISDWI_H_HEADER_INCLUDED_
#include <MitkDiffusionCoreExports.h>
#include "mitkNodePredicateBase.h"
#include "mitkBaseProperty.h"
#include "mitkBaseData.h"
namespace mitk {
/**Documentation
* @brief Predicate that evaluates whether a given node contains a diffusion weighted image
* @ingroup DataStorage
*/
class MITKDIFFUSIONCORE_EXPORT NodePredicateIsDWI : public NodePredicateBase
{
public:
mitkClassMacro(NodePredicateIsDWI, NodePredicateBase);
itkFactorylessNewMacro(NodePredicateIsDWI)
//##Documentation
//## @brief Standard Destructor
~NodePredicateIsDWI() override;
//##Documentation
//## @brief Checks, if the node's data contains a property that is equal to m_ValidProperty
bool CheckNode(const mitk::DataNode* node) const override;
protected:
//##Documentation
//## @brief Constructor to check for a named property
NodePredicateIsDWI();
};
} // namespace mitk
#endif /* MITKNODEPREDICATEISDWI_H_HEADER_INCLUDED_ */
diff --git a/Modules/DiffusionCore/IODataStructures/mitkFiberBundle.cpp b/Modules/DiffusionCore/IODataStructures/mitkFiberBundle.cpp
index 9f094a0..713ecbf 100644
--- a/Modules/DiffusionCore/IODataStructures/mitkFiberBundle.cpp
+++ b/Modules/DiffusionCore/IODataStructures/mitkFiberBundle.cpp
@@ -1,2761 +1,2761 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkFiberBundle.h"
#include <mitkPlanarCircle.h>
#include <mitkPlanarPolygon.h>
#include <mitkPlanarFigureComposite.h>
#include "mitkImagePixelReadAccessor.h"
#include <mitkPixelTypeMultiplex.h>
#include <vtkPointData.h>
#include <vtkDataArray.h>
#include <vtkUnsignedCharArray.h>
#include <vtkPolyLine.h>
#include <vtkCellArray.h>
#include <vtkCellData.h>
#include <vtkIdFilter.h>
#include <vtkClipPolyData.h>
#include <vtkPlane.h>
#include <vtkDoubleArray.h>
#include <vtkKochanekSpline.h>
#include <vtkParametricFunctionSource.h>
#include <vtkParametricSpline.h>
#include <vtkPolygon.h>
#include <vtkCleanPolyData.h>
#include <boost/progress.hpp>
#include <vtkTransformPolyDataFilter.h>
#include <mitkTransferFunction.h>
#include <vtkLookupTable.h>
#include <mitkLookupTable.h>
#include <vtkCardinalSpline.h>
#include <vtkAppendPolyData.h>
const char* mitk::FiberBundle::FIBER_ID_ARRAY = "Fiber_IDs";
mitk::FiberBundle::FiberBundle( vtkPolyData* fiberPolyData )
: m_NumFibers(0)
{
m_TrackVisHeader.hdr_size = 0;
m_FiberWeights = vtkSmartPointer<vtkFloatArray>::New();
m_FiberWeights->SetName("FIBER_WEIGHTS");
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
if (fiberPolyData != nullptr)
m_FiberPolyData = fiberPolyData;
else
{
this->m_FiberPolyData->SetPoints(vtkSmartPointer<vtkPoints>::New());
this->m_FiberPolyData->SetLines(vtkSmartPointer<vtkCellArray>::New());
}
this->UpdateFiberGeometry();
this->GenerateFiberIds();
this->ColorFibersByOrientation();
}
mitk::FiberBundle::~FiberBundle()
{
}
mitk::FiberBundle::Pointer mitk::FiberBundle::GetDeepCopy()
{
mitk::FiberBundle::Pointer newFib = mitk::FiberBundle::New(m_FiberPolyData);
newFib->SetFiberColors(this->m_FiberColors);
newFib->SetFiberWeights(this->m_FiberWeights);
newFib->SetTrackVisHeader(this->GetTrackVisHeader());
return newFib;
}
vtkSmartPointer<vtkPolyData> mitk::FiberBundle::GeneratePolyDataByIds(std::vector<unsigned int> fiberIds, vtkSmartPointer<vtkFloatArray> weights)
{
vtkSmartPointer<vtkPolyData> newFiberPolyData = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkCellArray> newLineSet = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkPoints> newPointSet = vtkSmartPointer<vtkPoints>::New();
weights->SetNumberOfValues(fiberIds.size());
int counter = 0;
auto finIt = fiberIds.begin();
while ( finIt != fiberIds.end() )
{
if (*finIt>GetNumFibers()){
MITK_INFO << "FiberID can not be negative or >NumFibers!!! check id Extraction!" << *finIt;
break;
}
vtkSmartPointer<vtkCell> fiber = m_FiberIdDataSet->GetCell(*finIt);//->DeepCopy(fiber);
vtkSmartPointer<vtkPoints> fibPoints = fiber->GetPoints();
vtkSmartPointer<vtkPolyLine> newFiber = vtkSmartPointer<vtkPolyLine>::New();
newFiber->GetPointIds()->SetNumberOfIds( fibPoints->GetNumberOfPoints() );
for(int i=0; i<fibPoints->GetNumberOfPoints(); i++)
{
newFiber->GetPointIds()->SetId(i, newPointSet->GetNumberOfPoints());
newPointSet->InsertNextPoint(fibPoints->GetPoint(i)[0], fibPoints->GetPoint(i)[1], fibPoints->GetPoint(i)[2]);
}
weights->InsertValue(counter, this->GetFiberWeight(*finIt));
newLineSet->InsertNextCell(newFiber);
++finIt;
++counter;
}
newFiberPolyData->SetPoints(newPointSet);
newFiberPolyData->SetLines(newLineSet);
return newFiberPolyData;
}
// merge two fiber bundles
mitk::FiberBundle::Pointer mitk::FiberBundle::AddBundles(std::vector< mitk::FiberBundle::Pointer > fibs)
{
vtkSmartPointer<vtkPolyData> vNewPolyData = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkCellArray> vNewLines = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkPoints> vNewPoints = vtkSmartPointer<vtkPoints>::New();
// add current fiber bundle
vtkSmartPointer<vtkFloatArray> weights = vtkSmartPointer<vtkFloatArray>::New();
auto num_weights = this->GetNumFibers();
for (auto fib : fibs)
num_weights += fib->GetNumFibers();
weights->SetNumberOfValues(num_weights);
unsigned int counter = 0;
for (unsigned int i=0; i<m_FiberPolyData->GetNumberOfCells(); ++i)
{
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (unsigned int j=0; j<numPoints; ++j)
{
double p[3];
points->GetPoint(j, p);
vtkIdType id = vNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
}
weights->InsertValue(counter, this->GetFiberWeight(i));
vNewLines->InsertNextCell(container);
counter++;
}
for (auto fib : fibs)
{
// add new fiber bundle
for (unsigned int i=0; i<fib->GetFiberPolyData()->GetNumberOfCells(); i++)
{
vtkCell* cell = fib->GetFiberPolyData()->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (unsigned int j=0; j<numPoints; j++)
{
double p[3];
points->GetPoint(j, p);
vtkIdType id = vNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
}
weights->InsertValue(counter, fib->GetFiberWeight(i));
vNewLines->InsertNextCell(container);
counter++;
}
}
// initialize PolyData
vNewPolyData->SetPoints(vNewPoints);
vNewPolyData->SetLines(vNewLines);
// initialize fiber bundle
mitk::FiberBundle::Pointer newFib = mitk::FiberBundle::New(vNewPolyData);
newFib->SetFiberWeights(weights);
return newFib;
}
// merge two fiber bundles
mitk::FiberBundle::Pointer mitk::FiberBundle::AddBundle(mitk::FiberBundle* fib)
{
if (fib==nullptr)
return this->GetDeepCopy();
MITK_INFO << "Adding fibers";
vtkSmartPointer<vtkPolyData> vNewPolyData = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkCellArray> vNewLines = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkPoints> vNewPoints = vtkSmartPointer<vtkPoints>::New();
// add current fiber bundle
vtkSmartPointer<vtkFloatArray> weights = vtkSmartPointer<vtkFloatArray>::New();
weights->SetNumberOfValues(this->GetNumFibers()+fib->GetNumFibers());
unsigned int counter = 0;
for (unsigned int i=0; i<m_FiberPolyData->GetNumberOfCells(); i++)
{
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (unsigned int j=0; j<numPoints; j++)
{
double p[3];
points->GetPoint(j, p);
vtkIdType id = vNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
}
weights->InsertValue(counter, this->GetFiberWeight(i));
vNewLines->InsertNextCell(container);
counter++;
}
// add new fiber bundle
for (unsigned int i=0; i<fib->GetFiberPolyData()->GetNumberOfCells(); i++)
{
vtkCell* cell = fib->GetFiberPolyData()->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (unsigned int j=0; j<numPoints; j++)
{
double p[3];
points->GetPoint(j, p);
vtkIdType id = vNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
}
weights->InsertValue(counter, fib->GetFiberWeight(i));
vNewLines->InsertNextCell(container);
counter++;
}
// initialize PolyData
vNewPolyData->SetPoints(vNewPoints);
vNewPolyData->SetLines(vNewLines);
// initialize fiber bundle
mitk::FiberBundle::Pointer newFib = mitk::FiberBundle::New(vNewPolyData);
newFib->SetFiberWeights(weights);
return newFib;
}
// Only retain fibers with a weight larger than the specified threshold
mitk::FiberBundle::Pointer mitk::FiberBundle::FilterByWeights(float weight_thr, bool invert)
{
vtkSmartPointer<vtkPolyData> vNewPolyData = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkCellArray> vNewLines = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkPoints> vNewPoints = vtkSmartPointer<vtkPoints>::New();
std::vector<float> weights;
for (unsigned int i=0; i<this->GetNumFibers(); i++)
{
if ( (invert && this->GetFiberWeight(i)>weight_thr) || (!invert && this->GetFiberWeight(i)<=weight_thr))
continue;
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (int j=0; j<numPoints; j++)
{
double p[3];
points->GetPoint(j, p);
vtkIdType id = vNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
}
vNewLines->InsertNextCell(container);
weights.push_back(this->GetFiberWeight(i));
}
// initialize PolyData
vNewPolyData->SetPoints(vNewPoints);
vNewPolyData->SetLines(vNewLines);
// initialize fiber bundle
mitk::FiberBundle::Pointer newFib = mitk::FiberBundle::New(vNewPolyData);
for (unsigned int i=0; i<weights.size(); ++i)
newFib->SetFiberWeight(i, weights.at(i));
newFib->SetTrackVisHeader(this->GetTrackVisHeader());
return newFib;
}
// Only retain a subsample of the fibers
mitk::FiberBundle::Pointer mitk::FiberBundle::SubsampleFibers(float factor, bool random_seed)
{
vtkSmartPointer<vtkPolyData> vNewPolyData = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkCellArray> vNewLines = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkPoints> vNewPoints = vtkSmartPointer<vtkPoints>::New();
unsigned int new_num_fibs = static_cast<unsigned int>(std::round(this->GetNumFibers()*factor));
MITK_INFO << "Subsampling fibers with factor " << factor << "(" << new_num_fibs << "/" << this->GetNumFibers() << ")";
// add current fiber bundle
vtkSmartPointer<vtkFloatArray> weights = vtkSmartPointer<vtkFloatArray>::New();
weights->SetNumberOfValues(new_num_fibs);
std::vector< unsigned int > ids;
for (unsigned int i=0; i<this->GetNumFibers(); i++)
ids.push_back(i);
if (random_seed)
std::srand(static_cast<unsigned int>(std::time(nullptr)));
else
std::srand(0);
std::random_shuffle(ids.begin(), ids.end());
unsigned int counter = 0;
for (unsigned int i=0; i<new_num_fibs; i++)
{
vtkCell* cell = m_FiberPolyData->GetCell(ids.at(i));
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (int j=0; j<numPoints; j++)
{
double p[3];
points->GetPoint(j, p);
vtkIdType id = vNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
}
weights->InsertValue(counter, this->GetFiberWeight(ids.at(i)));
vNewLines->InsertNextCell(container);
counter++;
}
// initialize PolyData
vNewPolyData->SetPoints(vNewPoints);
vNewPolyData->SetLines(vNewLines);
// initialize fiber bundle
mitk::FiberBundle::Pointer newFib = mitk::FiberBundle::New(vNewPolyData);
newFib->SetFiberWeights(weights);
newFib->SetTrackVisHeader(this->GetTrackVisHeader());
return newFib;
}
// subtract two fiber bundles
mitk::FiberBundle::Pointer mitk::FiberBundle::SubtractBundle(mitk::FiberBundle* fib)
{
if (fib==nullptr)
return this->GetDeepCopy();
MITK_INFO << "Subtracting fibers";
vtkSmartPointer<vtkPolyData> vNewPolyData = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkCellArray> vNewLines = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkPoints> vNewPoints = vtkSmartPointer<vtkPoints>::New();
std::vector< std::vector< itk::Point<float, 3> > > points1;
for(unsigned int i=0; i<m_NumFibers; i++ )
{
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
if (points==nullptr || numPoints<=0)
continue;
itk::Point<float, 3> start = mitk::imv::GetItkPoint(points->GetPoint(0));
itk::Point<float, 3> end = mitk::imv::GetItkPoint(points->GetPoint(numPoints-1));
points1.push_back( {start, end} );
}
std::vector< std::vector< itk::Point<float, 3> > > points2;
for(unsigned int i=0; i<fib->GetNumFibers(); i++ )
{
vtkCell* cell = fib->GetFiberPolyData()->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
if (points==nullptr || numPoints<=0)
continue;
itk::Point<float, 3> start =mitk::imv::GetItkPoint(points->GetPoint(0));
itk::Point<float, 3> end =mitk::imv::GetItkPoint(points->GetPoint(numPoints-1));
points2.push_back( {start, end} );
}
// int progress = 0;
std::vector< int > ids;
#pragma omp parallel for
for (int i=0; i<static_cast<int>(points1.size()); i++)
{
bool match = false;
for (unsigned int j=0; j<points2.size(); j++)
{
auto v1 = points1.at(static_cast<unsigned int>(i));
auto v2 = points2.at(j);
float dist=0;
for (unsigned int c=0; c<v1.size(); c++)
{
float d = v1[c][0]-v2[c][0];
dist += d*d;
d = v1[c][1]-v2[c][1];
dist += d*d;
d = v1[c][2]-v2[c][2];
dist += d*d;
}
dist /= v1.size();
if (dist<0.000001f)
{
match = true;
break;
}
dist=0;
for (unsigned int c=0; c<v1.size(); c++)
{
float d = v1[v1.size()-1-c][0]-v2[c][0];
dist += d*d;
d = v1[v1.size()-1-c][1]-v2[c][1];
dist += d*d;
d = v1[v1.size()-1-c][2]-v2[c][2];
dist += d*d;
}
dist /= v1.size();
if (dist<0.000001f)
{
match = true;
break;
}
}
#pragma omp critical
if (!match)
ids.push_back(i);
}
for( int i : ids )
{
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
if (points==nullptr || numPoints<=0)
continue;
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for( int j=0; j<numPoints; j++)
{
vtkIdType id = vNewPoints->InsertNextPoint(points->GetPoint(j));
container->GetPointIds()->InsertNextId(id);
}
vNewLines->InsertNextCell(container);
}
if(vNewLines->GetNumberOfCells()==0)
return mitk::FiberBundle::New();
// initialize PolyData
vNewPolyData->SetPoints(vNewPoints);
vNewPolyData->SetLines(vNewLines);
// initialize fiber bundle
return mitk::FiberBundle::New(vNewPolyData);
}
/*
* set PolyData (additional flag to recompute fiber geometry, default = true)
*/
void mitk::FiberBundle::SetFiberPolyData(vtkSmartPointer<vtkPolyData> fiberPD, bool updateGeometry)
{
if (fiberPD == nullptr)
this->m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
else
m_FiberPolyData->DeepCopy(fiberPD);
m_NumFibers = static_cast<unsigned int>(m_FiberPolyData->GetNumberOfLines());
if (updateGeometry)
UpdateFiberGeometry();
GenerateFiberIds();
ColorFibersByOrientation();
}
/*
* return vtkPolyData
*/
vtkSmartPointer<vtkPolyData> mitk::FiberBundle::GetFiberPolyData() const
{
return m_FiberPolyData;
}
void mitk::FiberBundle::ColorFibersByLength(bool opacity, bool normalize)
{
if (m_MaxFiberLength<=0)
return;
auto numOfPoints = this->GetNumberOfPoints();
//colors and alpha value for each single point, RGBA = 4 components
unsigned char rgba[4] = {0,0,0,0};
m_FiberColors = vtkSmartPointer<vtkUnsignedCharArray>::New();
m_FiberColors->Allocate(numOfPoints * 4);
m_FiberColors->SetNumberOfComponents(4);
m_FiberColors->SetName("FIBER_COLORS");
auto numOfFibers = m_FiberPolyData->GetNumberOfLines();
if (numOfFibers < 1)
return;
mitk::LookupTable::Pointer mitkLookup = mitk::LookupTable::New();
vtkSmartPointer<vtkLookupTable> lookupTable = vtkSmartPointer<vtkLookupTable>::New();
lookupTable->SetTableRange(0.0, 0.8);
lookupTable->Build();
mitkLookup->SetVtkLookupTable(lookupTable);
mitkLookup->SetType(mitk::LookupTable::JET);
unsigned int count = 0;
for (unsigned int i=0; i<m_FiberPolyData->GetNumberOfCells(); i++)
{
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
float l = m_FiberLengths.at(i)/m_MaxFiberLength;
if (!normalize)
{
l = m_FiberLengths.at(i)/255.0f;
if (l > 1.0f)
l = 1.0;
}
for (int j=0; j<numPoints; j++)
{
double color[3];
lookupTable->GetColor(1.0 - static_cast<double>(l), color);
rgba[0] = static_cast<unsigned char>(255.0 * color[0]);
rgba[1] = static_cast<unsigned char>(255.0 * color[1]);
rgba[2] = static_cast<unsigned char>(255.0 * color[2]);
if (opacity)
rgba[3] = static_cast<unsigned char>(255.0f * l);
else
rgba[3] = static_cast<unsigned char>(255.0);
m_FiberColors->InsertTypedTuple(cell->GetPointId(j), rgba);
count++;
}
}
m_UpdateTime3D.Modified();
m_UpdateTime2D.Modified();
}
void mitk::FiberBundle::ColorFibersByOrientation()
{
//===== FOR WRITING A TEST ========================
// colorT size == tupelComponents * tupelElements
// compare color results
// to cover this code 100% also PolyData needed, where colorarray already exists
// + one fiber with exactly 1 point
// + one fiber with 0 points
//=================================================
vtkPoints* extrPoints = m_FiberPolyData->GetPoints();
vtkIdType numOfPoints = 0;
if (extrPoints!=nullptr)
numOfPoints = extrPoints->GetNumberOfPoints();
//colors and alpha value for each single point, RGBA = 4 components
unsigned char rgba[4] = {0,0,0,0};
m_FiberColors = vtkSmartPointer<vtkUnsignedCharArray>::New();
m_FiberColors->Allocate(numOfPoints * 4);
m_FiberColors->SetNumberOfComponents(4);
m_FiberColors->SetName("FIBER_COLORS");
auto numOfFibers = m_FiberPolyData->GetNumberOfLines();
if (numOfFibers < 1)
return;
/* extract single fibers of fiberBundle */
vtkCellArray* fiberList = m_FiberPolyData->GetLines();
fiberList->InitTraversal();
for (int fi=0; fi<numOfFibers; ++fi) {
vtkIdType* idList; // contains the point id's of the line
vtkIdType pointsPerFiber; // number of points for current line
fiberList->GetNextCell(pointsPerFiber, idList);
/* single fiber checkpoints: is number of points valid */
if (pointsPerFiber > 1)
{
/* operate on points of single fiber */
for (int i=0; i <pointsPerFiber; ++i)
{
/* process all points elastV[0]ept starting and endpoint for calculating color value take current point, previous point and next point */
if (i<pointsPerFiber-1 && i > 0)
{
/* The color value of the current point is influenced by the previous point and next point. */
vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]);
vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]);
vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]);
vnl_vector_fixed< double, 3 > diff1;
diff1 = currentPntvtk - nextPntvtk;
vnl_vector_fixed< double, 3 > diff2;
diff2 = currentPntvtk - prevPntvtk;
vnl_vector_fixed< double, 3 > diff;
diff = (diff1 - diff2) / 2.0;
diff.normalize();
rgba[0] = static_cast<unsigned char>(255.0 * std::fabs(diff[0]));
rgba[1] = static_cast<unsigned char>(255.0 * std::fabs(diff[1]));
rgba[2] = static_cast<unsigned char>(255.0 * std::fabs(diff[2]));
rgba[3] = static_cast<unsigned char>(255.0);
}
else if (i==0)
{
/* First point has no previous point, therefore only diff1 is taken */
vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]);
vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]);
vnl_vector_fixed< double, 3 > diff1;
diff1 = currentPntvtk - nextPntvtk;
diff1.normalize();
rgba[0] = static_cast<unsigned char>(255.0 * std::fabs(diff1[0]));
rgba[1] = static_cast<unsigned char>(255.0 * std::fabs(diff1[1]));
rgba[2] = static_cast<unsigned char>(255.0 * std::fabs(diff1[2]));
rgba[3] = static_cast<unsigned char>(255.0);
}
else if (i==pointsPerFiber-1)
{
/* Last point has no next point, therefore only diff2 is taken */
vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]);
vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]);
vnl_vector_fixed< double, 3 > diff2;
diff2 = currentPntvtk - prevPntvtk;
diff2.normalize();
rgba[0] = static_cast<unsigned char>(255.0 * std::fabs(diff2[0]));
rgba[1] = static_cast<unsigned char>(255.0 * std::fabs(diff2[1]));
rgba[2] = static_cast<unsigned char>(255.0 * std::fabs(diff2[2]));
rgba[3] = static_cast<unsigned char>(255.0);
}
m_FiberColors->InsertTypedTuple(idList[i], rgba);
}
}
else if (pointsPerFiber == 1)
{
/* a single point does not define a fiber (use vertex mechanisms instead */
continue;
}
else
{
MITK_DEBUG << "Fiber with 0 points detected... please check your tractography algorithm!" ;
continue;
}
}
m_UpdateTime3D.Modified();
m_UpdateTime2D.Modified();
}
void mitk::FiberBundle::ColorFibersByCurvature(bool, bool normalize)
{
double window = 5;
//colors and alpha value for each single point, RGBA = 4 components
unsigned char rgba[4] = {0,0,0,0};
m_FiberColors = vtkSmartPointer<vtkUnsignedCharArray>::New();
m_FiberColors->Allocate(m_FiberPolyData->GetNumberOfPoints() * 4);
m_FiberColors->SetNumberOfComponents(4);
m_FiberColors->SetName("FIBER_COLORS");
mitk::LookupTable::Pointer mitkLookup = mitk::LookupTable::New();
vtkSmartPointer<vtkLookupTable> lookupTable = vtkSmartPointer<vtkLookupTable>::New();
lookupTable->SetTableRange(0.0, 0.8);
lookupTable->Build();
mitkLookup->SetVtkLookupTable(lookupTable);
mitkLookup->SetType(mitk::LookupTable::JET);
std::vector< double > values;
double min = 1;
double max = 0;
MITK_INFO << "Coloring fibers by curvature";
boost::progress_display disp(static_cast<unsigned long>(m_FiberPolyData->GetNumberOfCells()));
for (int i=0; i<m_FiberPolyData->GetNumberOfCells(); i++)
{
++disp;
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
// calculate curvatures
for (int j=0; j<numPoints; j++)
{
double dist = 0;
int c = j;
std::vector< vnl_vector_fixed< double, 3 > > vectors;
vnl_vector_fixed< double, 3 > meanV; meanV.fill(0.0);
while(dist<window/2 && c>1)
{
double p1[3];
points->GetPoint(c-1, p1);
double p2[3];
points->GetPoint(c, p2);
vnl_vector_fixed< double, 3 > v;
v[0] = p2[0]-p1[0];
v[1] = p2[1]-p1[1];
v[2] = p2[2]-p1[2];
dist += v.magnitude();
v.normalize();
vectors.push_back(v);
meanV += v;
c--;
}
c = j;
dist = 0;
while(dist<window/2 && c<numPoints-1)
{
double p1[3];
points->GetPoint(c, p1);
double p2[3];
points->GetPoint(c+1, p2);
vnl_vector_fixed< double, 3 > v;
v[0] = p2[0]-p1[0];
v[1] = p2[1]-p1[1];
v[2] = p2[2]-p1[2];
dist += v.magnitude();
v.normalize();
vectors.push_back(v);
meanV += v;
c++;
}
meanV.normalize();
double dev = 0;
for (unsigned int c=0; c<vectors.size(); c++)
{
double angle = dot_product(meanV, vectors.at(c));
if (angle>1.0)
angle = 1.0;
if (angle<-1.0)
angle = -1.0;
dev += acos(angle)*180/itk::Math::pi;
}
if (vectors.size()>0)
dev /= vectors.size();
dev = 1.0-dev/180.0;
values.push_back(dev);
if (dev<min)
min = dev;
if (dev>max)
max = dev;
}
}
unsigned int count = 0;
for (int i=0; i<m_FiberPolyData->GetNumberOfCells(); i++)
{
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
for (int j=0; j<numPoints; j++)
{
double color[3];
double dev = values.at(count);
if (normalize)
dev = (dev-min)/(max-min);
else if (dev>1)
dev = 1;
lookupTable->GetColor(dev, color);
rgba[0] = static_cast<unsigned char>(255.0 * color[0]);
rgba[1] = static_cast<unsigned char>(255.0 * color[1]);
rgba[2] = static_cast<unsigned char>(255.0 * color[2]);
rgba[3] = static_cast<unsigned char>(255.0);
m_FiberColors->InsertTypedTuple(cell->GetPointId(j), rgba);
count++;
}
}
m_UpdateTime3D.Modified();
m_UpdateTime2D.Modified();
}
void mitk::FiberBundle::SetFiberOpacity(vtkDoubleArray* FAValArray)
{
for(long i=0; i<m_FiberColors->GetNumberOfTuples(); i++)
{
double faValue = FAValArray->GetValue(i);
faValue = faValue * 255.0;
m_FiberColors->SetComponent(i,3, static_cast<unsigned char>(faValue) );
}
m_UpdateTime3D.Modified();
m_UpdateTime2D.Modified();
}
void mitk::FiberBundle::ResetFiberOpacity()
{
for(long i=0; i<m_FiberColors->GetNumberOfTuples(); i++)
m_FiberColors->SetComponent(i,3, 255.0 );
m_UpdateTime3D.Modified();
m_UpdateTime2D.Modified();
}
void mitk::FiberBundle::ColorFibersByScalarMap(mitk::Image::Pointer FAimage, bool opacity, bool normalize)
{
mitkPixelTypeMultiplex3( ColorFibersByScalarMap, FAimage->GetPixelType(), FAimage, opacity, normalize );
m_UpdateTime3D.Modified();
m_UpdateTime2D.Modified();
}
template <typename TPixel>
void mitk::FiberBundle::ColorFibersByScalarMap(const mitk::PixelType, mitk::Image::Pointer image, bool opacity, bool normalize)
{
m_FiberColors = vtkSmartPointer<vtkUnsignedCharArray>::New();
m_FiberColors->Allocate(m_FiberPolyData->GetNumberOfPoints() * 4);
m_FiberColors->SetNumberOfComponents(4);
m_FiberColors->SetName("FIBER_COLORS");
mitk::ImagePixelReadAccessor<TPixel,3> readimage(image, image->GetVolumeData(0));
unsigned char rgba[4] = {0,0,0,0};
vtkPoints* pointSet = m_FiberPolyData->GetPoints();
mitk::LookupTable::Pointer mitkLookup = mitk::LookupTable::New();
vtkSmartPointer<vtkLookupTable> lookupTable = vtkSmartPointer<vtkLookupTable>::New();
lookupTable->SetTableRange(0.0, 0.8);
lookupTable->Build();
mitkLookup->SetVtkLookupTable(lookupTable);
mitkLookup->SetType(mitk::LookupTable::JET);
double min = 999999;
double max = -999999;
for(long i=0; i<m_FiberPolyData->GetNumberOfPoints(); ++i)
{
Point3D px;
px[0] = pointSet->GetPoint(i)[0];
px[1] = pointSet->GetPoint(i)[1];
px[2] = pointSet->GetPoint(i)[2];
auto pixelValue = static_cast<double>(readimage.GetPixelByWorldCoordinates(px));
if (pixelValue>max)
max = pixelValue;
if (pixelValue<min)
min = pixelValue;
}
for(long i=0; i<m_FiberPolyData->GetNumberOfPoints(); ++i)
{
Point3D px;
px[0] = pointSet->GetPoint(i)[0];
px[1] = pointSet->GetPoint(i)[1];
px[2] = pointSet->GetPoint(i)[2];
auto pixelValue = static_cast<double>(readimage.GetPixelByWorldCoordinates(px));
if (normalize)
pixelValue = (pixelValue-min)/(max-min);
else if (pixelValue>1)
pixelValue = 1;
double color[3];
lookupTable->GetColor(1-pixelValue, color);
rgba[0] = static_cast<unsigned char>(255.0 * color[0]);
rgba[1] = static_cast<unsigned char>(255.0 * color[1]);
rgba[2] = static_cast<unsigned char>(255.0 * color[2]);
if (opacity)
rgba[3] = static_cast<unsigned char>(255.0 * pixelValue);
else
rgba[3] = static_cast<unsigned char>(255.0);
m_FiberColors->InsertTypedTuple(i, rgba);
}
m_UpdateTime3D.Modified();
m_UpdateTime2D.Modified();
}
void mitk::FiberBundle::ColorFibersByFiberWeights(bool opacity, bool normalize)
{
m_FiberColors = vtkSmartPointer<vtkUnsignedCharArray>::New();
m_FiberColors->Allocate(m_FiberPolyData->GetNumberOfPoints() * 4);
m_FiberColors->SetNumberOfComponents(4);
m_FiberColors->SetName("FIBER_COLORS");
mitk::LookupTable::Pointer mitkLookup = mitk::LookupTable::New();
vtkSmartPointer<vtkLookupTable> lookupTable = vtkSmartPointer<vtkLookupTable>::New();
lookupTable->SetTableRange(0.0, 0.8);
lookupTable->Build();
mitkLookup->SetVtkLookupTable(lookupTable);
mitkLookup->SetType(mitk::LookupTable::JET);
unsigned char rgba[4] = {0,0,0,0};
unsigned int counter = 0;
float max = -999999;
float min = 999999;
for (unsigned int i=0; i<m_NumFibers; i++)
{
float weight = this->GetFiberWeight(i);
if (weight>max)
max = weight;
if (weight<min)
min = weight;
}
if (fabs(max-min)<0.00001f)
{
max = 1;
min = 0;
}
for (unsigned int i=0; i<m_NumFibers; i++)
{
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
auto weight = this->GetFiberWeight(i);
for (int j=0; j<numPoints; j++)
{
float v = weight;
if (normalize)
v = (v-min)/(max-min);
else if (v>1)
v = 1;
double color[3];
lookupTable->GetColor(static_cast<double>(1-v), color);
rgba[0] = static_cast<unsigned char>(255.0 * color[0]);
rgba[1] = static_cast<unsigned char>(255.0 * color[1]);
rgba[2] = static_cast<unsigned char>(255.0 * color[2]);
if (opacity)
rgba[3] = static_cast<unsigned char>(255.0f * v);
else
rgba[3] = static_cast<unsigned char>(255.0);
m_FiberColors->InsertTypedTuple(counter, rgba);
counter++;
}
}
m_UpdateTime3D.Modified();
m_UpdateTime2D.Modified();
}
void mitk::FiberBundle::SetFiberColors(float r, float g, float b, float alpha)
{
m_FiberColors = vtkSmartPointer<vtkUnsignedCharArray>::New();
m_FiberColors->Allocate(m_FiberPolyData->GetNumberOfPoints() * 4);
m_FiberColors->SetNumberOfComponents(4);
m_FiberColors->SetName("FIBER_COLORS");
unsigned char rgba[4] = {0,0,0,0};
for(long i=0; i<m_FiberPolyData->GetNumberOfPoints(); ++i)
{
rgba[0] = static_cast<unsigned char>(r);
rgba[1] = static_cast<unsigned char>(g);
rgba[2] = static_cast<unsigned char>(b);
rgba[3] = static_cast<unsigned char>(alpha);
m_FiberColors->InsertTypedTuple(i, rgba);
}
m_UpdateTime3D.Modified();
m_UpdateTime2D.Modified();
}
void mitk::FiberBundle::GenerateFiberIds()
{
if (m_FiberPolyData == nullptr)
return;
vtkSmartPointer<vtkIdFilter> idFiberFilter = vtkSmartPointer<vtkIdFilter>::New();
idFiberFilter->SetInputData(m_FiberPolyData);
idFiberFilter->CellIdsOn();
// idFiberFilter->PointIdsOn(); // point id's are not needed
idFiberFilter->SetIdsArrayName(FIBER_ID_ARRAY);
idFiberFilter->FieldDataOn();
idFiberFilter->Update();
m_FiberIdDataSet = idFiberFilter->GetOutput();
}
float mitk::FiberBundle::GetNumEpFractionInMask(ItkUcharImgType* mask, bool different_label)
{
vtkSmartPointer<vtkPolyData> PolyData = m_FiberPolyData;
MITK_INFO << "Calculating EP-Fraction";
boost::progress_display disp(m_NumFibers);
unsigned int in_mask = 0;
for (unsigned int i=0; i<m_NumFibers; i++)
{
++disp;
vtkCell* cell = PolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
itk::Point<float, 3> startVertex =mitk::imv::GetItkPoint(points->GetPoint(0));
itk::Index<3> startIndex;
mask->TransformPhysicalPointToIndex(startVertex, startIndex);
itk::Point<float, 3> endVertex =mitk::imv::GetItkPoint(points->GetPoint(numPoints-1));
itk::Index<3> endIndex;
mask->TransformPhysicalPointToIndex(endVertex, endIndex);
if (mask->GetLargestPossibleRegion().IsInside(startIndex) && mask->GetLargestPossibleRegion().IsInside(endIndex))
{
float v1 = mask->GetPixel(startIndex);
if (v1 < 0.5f)
continue;
float v2 = mask->GetPixel(startIndex);
if (v2 < 0.5f)
continue;
if (!different_label)
++in_mask;
else if (fabs(v1-v2)>0.00001f)
++in_mask;
}
}
return float(in_mask)/m_NumFibers;
}
std::tuple<float, float> mitk::FiberBundle::GetDirectionalOverlap(ItkUcharImgType* mask, mitk::PeakImage::ItkPeakImageType* peak_image)
{
vtkSmartPointer<vtkPolyData> PolyData = m_FiberPolyData;
MITK_INFO << "Calculating overlap";
auto spacing = mask->GetSpacing();
boost::progress_display disp(m_NumFibers);
double length_sum = 0;
double in_mask_length = 0;
double aligned_length = 0;
for (unsigned int i=0; i<m_NumFibers; i++)
{
++disp;
vtkCell* cell = PolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
for (int j=0; j<numPoints-1; j++)
{
itk::Point<float, 3> startVertex =mitk::imv::GetItkPoint(points->GetPoint(j));
itk::Index<3> startIndex;
itk::ContinuousIndex<float, 3> startIndexCont;
mask->TransformPhysicalPointToIndex(startVertex, startIndex);
mask->TransformPhysicalPointToContinuousIndex(startVertex, startIndexCont);
itk::Point<float, 3> endVertex =mitk::imv::GetItkPoint(points->GetPoint(j + 1));
itk::Index<3> endIndex;
itk::ContinuousIndex<float, 3> endIndexCont;
mask->TransformPhysicalPointToIndex(endVertex, endIndex);
mask->TransformPhysicalPointToContinuousIndex(endVertex, endIndexCont);
vnl_vector_fixed< float, 3 > fdir;
fdir[0] = endVertex[0] - startVertex[0];
fdir[1] = endVertex[1] - startVertex[1];
fdir[2] = endVertex[2] - startVertex[2];
fdir.normalize();
std::vector< std::pair< itk::Index<3>, double > > segments = mitk::imv::IntersectImage(spacing, startIndex, endIndex, startIndexCont, endIndexCont);
for (std::pair< itk::Index<3>, double > segment : segments)
{
if ( mask->GetLargestPossibleRegion().IsInside(segment.first) && mask->GetPixel(segment.first) > 0 )
{
in_mask_length += segment.second;
mitk::PeakImage::ItkPeakImageType::IndexType idx4;
idx4[0] = segment.first[0];
idx4[1] = segment.first[1];
idx4[2] = segment.first[2];
vnl_vector_fixed< float, 3 > peak;
idx4[3] = 0;
peak[0] = peak_image->GetPixel(idx4);
idx4[3] = 1;
peak[1] = peak_image->GetPixel(idx4);
idx4[3] = 2;
peak[2] = peak_image->GetPixel(idx4);
if (std::isnan(peak[0]) || std::isnan(peak[1]) || std::isnan(peak[2]) || peak.magnitude()<0.0001f)
continue;
peak.normalize();
double f = 1.0 - std::acos(std::fabs(static_cast<double>(dot_product(fdir, peak)))) * 2.0/itk::Math::pi;
aligned_length += segment.second * f;
}
length_sum += segment.second;
}
}
}
if (length_sum<=0.0001)
{
MITK_INFO << "Fiber length sum is zero!";
return std::make_tuple(0,0);
}
return std::make_tuple(aligned_length/length_sum, in_mask_length/length_sum);
}
float mitk::FiberBundle::GetOverlap(ItkUcharImgType* mask)
{
vtkSmartPointer<vtkPolyData> PolyData = m_FiberPolyData;
MITK_INFO << "Calculating overlap";
auto spacing = mask->GetSpacing();
boost::progress_display disp(m_NumFibers);
double length_sum = 0;
double in_mask_length = 0;
for (unsigned int i=0; i<m_NumFibers; i++)
{
++disp;
vtkCell* cell = PolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
for (int j=0; j<numPoints-1; j++)
{
itk::Point<float, 3> startVertex =mitk::imv::GetItkPoint(points->GetPoint(j));
itk::Index<3> startIndex;
itk::ContinuousIndex<float, 3> startIndexCont;
mask->TransformPhysicalPointToIndex(startVertex, startIndex);
mask->TransformPhysicalPointToContinuousIndex(startVertex, startIndexCont);
itk::Point<float, 3> endVertex =mitk::imv::GetItkPoint(points->GetPoint(j + 1));
itk::Index<3> endIndex;
itk::ContinuousIndex<float, 3> endIndexCont;
mask->TransformPhysicalPointToIndex(endVertex, endIndex);
mask->TransformPhysicalPointToContinuousIndex(endVertex, endIndexCont);
std::vector< std::pair< itk::Index<3>, double > > segments = mitk::imv::IntersectImage(spacing, startIndex, endIndex, startIndexCont, endIndexCont);
for (std::pair< itk::Index<3>, double > segment : segments)
{
if ( mask->GetLargestPossibleRegion().IsInside(segment.first) && mask->GetPixel(segment.first) > 0 )
in_mask_length += segment.second;
length_sum += segment.second;
}
}
}
if (length_sum<=0.000001)
{
MITK_INFO << "Fiber length sum is zero!";
return 0;
}
return static_cast<float>(in_mask_length/length_sum);
}
mitk::FiberBundle::Pointer mitk::FiberBundle::RemoveFibersOutside(ItkUcharImgType* mask, bool invert)
{
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
std::vector< float > fib_weights;
MITK_INFO << "Cutting fibers";
boost::progress_display disp(m_NumFibers);
for (unsigned int i=0; i<m_NumFibers; i++)
{
++disp;
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
int newNumPoints = 0;
if (numPoints>1)
{
for (int j=0; j<numPoints; j++)
{
itk::Point<float, 3> itkP =mitk::imv::GetItkPoint(points->GetPoint(j));
itk::Index<3> idx;
mask->TransformPhysicalPointToIndex(itkP, idx);
bool inside = false;
if ( mask->GetLargestPossibleRegion().IsInside(idx) && mask->GetPixel(idx)!=0 )
inside = true;
if (inside && !invert)
{
vtkIdType id = vtkNewPoints->InsertNextPoint(itkP.GetDataPointer());
container->GetPointIds()->InsertNextId(id);
newNumPoints++;
}
else if ( !inside && invert )
{
vtkIdType id = vtkNewPoints->InsertNextPoint(itkP.GetDataPointer());
container->GetPointIds()->InsertNextId(id);
newNumPoints++;
}
else if (newNumPoints>1)
{
fib_weights.push_back(this->GetFiberWeight(i));
vtkNewCells->InsertNextCell(container);
newNumPoints = 0;
container = vtkSmartPointer<vtkPolyLine>::New();
}
else
{
newNumPoints = 0;
container = vtkSmartPointer<vtkPolyLine>::New();
}
}
if (newNumPoints>1)
{
fib_weights.push_back(this->GetFiberWeight(i));
vtkNewCells->InsertNextCell(container);
}
}
}
vtkSmartPointer<vtkFloatArray> newFiberWeights = vtkSmartPointer<vtkFloatArray>::New();
newFiberWeights->SetName("FIBER_WEIGHTS");
newFiberWeights->SetNumberOfValues(static_cast<vtkIdType>(fib_weights.size()));
if (vtkNewCells->GetNumberOfCells()<=0)
return nullptr;
for (unsigned int i=0; i<newFiberWeights->GetNumberOfValues(); i++)
newFiberWeights->SetValue(i, fib_weights.at(i));
// vtkSmartPointer<vtkUnsignedCharArray> newFiberColors = vtkSmartPointer<vtkUnsignedCharArray>::New();
// newFiberColors->Allocate(m_FiberPolyData->GetNumberOfPoints() * 4);
// newFiberColors->SetNumberOfComponents(4);
// newFiberColors->SetName("FIBER_COLORS");
// unsigned char rgba[4] = {0,0,0,0};
// for(long i=0; i<m_FiberPolyData->GetNumberOfPoints(); ++i)
// {
// rgba[0] = (unsigned char) r;
// rgba[1] = (unsigned char) g;
// rgba[2] = (unsigned char) b;
// rgba[3] = (unsigned char) alpha;
// m_FiberColors->InsertTypedTuple(i, rgba);
// }
vtkSmartPointer<vtkPolyData> newPolyData = vtkSmartPointer<vtkPolyData>::New();
newPolyData->SetPoints(vtkNewPoints);
newPolyData->SetLines(vtkNewCells);
mitk::FiberBundle::Pointer newFib = mitk::FiberBundle::New(newPolyData);
newFib->SetFiberWeights(newFiberWeights);
// newFib->Compress(0.1);
newFib->SetTrackVisHeader(this->GetTrackVisHeader());
return newFib;
}
mitk::FiberBundle::Pointer mitk::FiberBundle::ExtractFiberSubset(DataNode* roi, DataStorage* storage)
{
if (roi==nullptr || !(dynamic_cast<PlanarFigure*>(roi->GetData()) || dynamic_cast<PlanarFigureComposite*>(roi->GetData())) )
return nullptr;
std::vector<unsigned int> tmp = ExtractFiberIdSubset(roi, storage);
if (tmp.size()<=0)
return mitk::FiberBundle::New();
vtkSmartPointer<vtkFloatArray> weights = vtkSmartPointer<vtkFloatArray>::New();
vtkSmartPointer<vtkPolyData> pTmp = GeneratePolyDataByIds(tmp, weights);
mitk::FiberBundle::Pointer fib = mitk::FiberBundle::New(pTmp);
fib->SetFiberWeights(weights);
fib->SetTrackVisHeader(this->GetTrackVisHeader());
return fib;
}
std::vector<unsigned int> mitk::FiberBundle::ExtractFiberIdSubset(DataNode *roi, DataStorage* storage)
{
std::vector<unsigned int> result;
if (roi==nullptr || roi->GetData()==nullptr)
return result;
mitk::PlanarFigureComposite::Pointer pfc = dynamic_cast<mitk::PlanarFigureComposite*>(roi->GetData());
if (!pfc.IsNull()) // handle composite
{
DataStorage::SetOfObjects::ConstPointer children = storage->GetDerivations(roi);
if (children->size()==0)
return result;
switch (pfc->getOperationType())
{
case 0: // AND
{
MITK_INFO << "AND";
result = this->ExtractFiberIdSubset(children->ElementAt(0), storage);
std::vector<unsigned int>::iterator it;
for (unsigned int i=1; i<children->Size(); ++i)
{
std::vector<unsigned int> inRoi = this->ExtractFiberIdSubset(children->ElementAt(i), storage);
std::vector<unsigned int> rest(std::min(result.size(),inRoi.size()));
it = std::set_intersection(result.begin(), result.end(), inRoi.begin(), inRoi.end(), rest.begin() );
rest.resize( static_cast<unsigned int>(it - rest.begin()) );
result = rest;
}
break;
}
case 1: // OR
{
MITK_INFO << "OR";
result = ExtractFiberIdSubset(children->ElementAt(0), storage);
std::vector<unsigned int>::iterator it;
for (unsigned int i=1; i<children->Size(); ++i)
{
it = result.end();
std::vector<unsigned int> inRoi = ExtractFiberIdSubset(children->ElementAt(i), storage);
result.insert(it, inRoi.begin(), inRoi.end());
}
// remove duplicates
sort(result.begin(), result.end());
it = unique(result.begin(), result.end());
result.resize( static_cast<unsigned int>(it - result.begin()) );
break;
}
case 2: // NOT
{
MITK_INFO << "NOT";
for(unsigned int i=0; i<this->GetNumFibers(); i++)
result.push_back(i);
std::vector<unsigned int>::iterator it;
for (unsigned int i=0; i<children->Size(); ++i)
{
std::vector<unsigned int> inRoi = ExtractFiberIdSubset(children->ElementAt(i), storage);
std::vector<unsigned int> rest(result.size()-inRoi.size());
it = std::set_difference(result.begin(), result.end(), inRoi.begin(), inRoi.end(), rest.begin() );
rest.resize( static_cast<unsigned int>(it - rest.begin()) );
result = rest;
}
break;
}
}
}
else if ( dynamic_cast<mitk::PlanarFigure*>(roi->GetData()) ) // actual extraction
{
if ( dynamic_cast<mitk::PlanarPolygon*>(roi->GetData()) )
{
mitk::PlanarFigure::Pointer planarPoly = dynamic_cast<mitk::PlanarFigure*>(roi->GetData());
//create vtkPolygon using controlpoints from planarFigure polygon
vtkSmartPointer<vtkPolygon> polygonVtk = vtkSmartPointer<vtkPolygon>::New();
for (unsigned int i=0; i<planarPoly->GetNumberOfControlPoints(); ++i)
{
itk::Point<double,3> p = planarPoly->GetWorldControlPoint(i);
vtkIdType id = polygonVtk->GetPoints()->InsertNextPoint(p[0], p[1], p[2] );
polygonVtk->GetPointIds()->InsertNextId(id);
}
MITK_INFO << "Extracting with polygon";
boost::progress_display disp(m_NumFibers);
for (unsigned int i=0; i<m_NumFibers; i++)
{
++disp ;
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
for (int j=0; j<numPoints-1; j++)
{
// Inputs
double p1[3] = {0,0,0};
points->GetPoint(j, p1);
double p2[3] = {0,0,0};
points->GetPoint(j+1, p2);
double tolerance = 0.001;
// Outputs
double t = 0; // Parametric coordinate of intersection (0 (corresponding to p1) to 1 (corresponding to p2))
double x[3] = {0,0,0}; // The coordinate of the intersection
double pcoords[3] = {0,0,0};
int subId = 0;
int iD = polygonVtk->IntersectWithLine(p1, p2, tolerance, t, x, pcoords, subId);
if (iD!=0)
{
result.push_back(i);
break;
}
}
}
}
else if ( dynamic_cast<mitk::PlanarCircle*>(roi->GetData()) )
{
mitk::PlanarFigure::Pointer planarFigure = dynamic_cast<mitk::PlanarFigure*>(roi->GetData());
Vector3D planeNormal = planarFigure->GetPlaneGeometry()->GetNormal();
planeNormal.Normalize();
//calculate circle radius
mitk::Point3D V1w = planarFigure->GetWorldControlPoint(0); //centerPoint
mitk::Point3D V2w = planarFigure->GetWorldControlPoint(1); //radiusPoint
double radius = V1w.EuclideanDistanceTo(V2w);
radius *= radius;
MITK_INFO << "Extracting with circle";
boost::progress_display disp(m_NumFibers);
for (unsigned int i=0; i<m_NumFibers; i++)
{
++disp ;
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
for (int j=0; j<numPoints-1; j++)
{
// Inputs
double p1[3] = {0,0,0};
points->GetPoint(j, p1);
double p2[3] = {0,0,0};
points->GetPoint(j+1, p2);
// Outputs
double t = 0; // Parametric coordinate of intersection (0 (corresponding to p1) to 1 (corresponding to p2))
double x[3] = {0,0,0}; // The coordinate of the intersection
int iD = vtkPlane::IntersectWithLine(p1,p2,planeNormal.GetDataPointer(),V1w.GetDataPointer(),t,x);
if (iD!=0)
{
double dist = (x[0]-V1w[0])*(x[0]-V1w[0])+(x[1]-V1w[1])*(x[1]-V1w[1])+(x[2]-V1w[2])*(x[2]-V1w[2]);
if( dist <= radius)
{
result.push_back(i);
break;
}
}
}
}
}
return result;
}
return result;
}
void mitk::FiberBundle::UpdateFiberGeometry()
{
vtkSmartPointer<vtkCleanPolyData> cleaner = vtkSmartPointer<vtkCleanPolyData>::New();
cleaner->SetInputData(m_FiberPolyData);
cleaner->PointMergingOff();
cleaner->Update();
m_FiberPolyData = cleaner->GetOutput();
m_FiberLengths.clear();
m_MeanFiberLength = 0;
m_MedianFiberLength = 0;
m_LengthStDev = 0;
m_NumFibers = static_cast<unsigned int>(m_FiberPolyData->GetNumberOfCells());
if (m_FiberColors==nullptr || m_FiberColors->GetNumberOfTuples()!=m_FiberPolyData->GetNumberOfPoints())
this->ColorFibersByOrientation();
if (m_FiberWeights->GetNumberOfValues()!=m_NumFibers)
{
m_FiberWeights = vtkSmartPointer<vtkFloatArray>::New();
m_FiberWeights->SetName("FIBER_WEIGHTS");
m_FiberWeights->SetNumberOfValues(m_NumFibers);
this->SetFiberWeights(1);
}
if (m_NumFibers<=0) // no fibers present; apply default geometry
{
m_MinFiberLength = 0;
m_MaxFiberLength = 0;
mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New();
geometry->SetImageGeometry(false);
float b[] = {0, 1, 0, 1, 0, 1};
geometry->SetFloatBounds(b);
SetGeometry(geometry);
return;
}
double b[6];
m_FiberPolyData->GetBounds(b);
// calculate statistics
for (int i=0; i<m_FiberPolyData->GetNumberOfCells(); i++)
{
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto p = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
float length = 0;
for (int j=0; j<p-1; j++)
{
double p1[3];
points->GetPoint(j, p1);
double p2[3];
points->GetPoint(j+1, p2);
double dist = std::sqrt((p1[0]-p2[0])*(p1[0]-p2[0])+(p1[1]-p2[1])*(p1[1]-p2[1])+(p1[2]-p2[2])*(p1[2]-p2[2]));
length += static_cast<float>(dist);
}
m_FiberLengths.push_back(length);
m_MeanFiberLength += length;
if (i==0)
{
m_MinFiberLength = length;
m_MaxFiberLength = length;
}
else
{
if (length<m_MinFiberLength)
m_MinFiberLength = length;
if (length>m_MaxFiberLength)
m_MaxFiberLength = length;
}
}
m_MeanFiberLength /= m_NumFibers;
std::vector< float > sortedLengths = m_FiberLengths;
std::sort(sortedLengths.begin(), sortedLengths.end());
for (unsigned int i=0; i<m_NumFibers; i++)
m_LengthStDev += (m_MeanFiberLength-sortedLengths.at(i))*(m_MeanFiberLength-sortedLengths.at(i));
if (m_NumFibers>1)
m_LengthStDev /= (m_NumFibers-1);
else
m_LengthStDev = 0;
m_LengthStDev = std::sqrt(m_LengthStDev);
m_MedianFiberLength = sortedLengths.at(m_NumFibers/2);
mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New();
geometry->SetFloatBounds(b);
this->SetGeometry(geometry);
GetTrackVisHeader();
m_UpdateTime3D.Modified();
m_UpdateTime2D.Modified();
}
float mitk::FiberBundle::GetFiberWeight(unsigned int fiber) const
{
return m_FiberWeights->GetValue(fiber);
}
void mitk::FiberBundle::SetFiberWeights(float newWeight)
{
for (int i=0; i<m_FiberWeights->GetNumberOfValues(); i++)
m_FiberWeights->SetValue(i, newWeight);
}
void mitk::FiberBundle::SetFiberWeights(vtkSmartPointer<vtkFloatArray> weights)
{
if (m_NumFibers!=weights->GetNumberOfValues())
{
MITK_INFO << "Weights array not equal to number of fibers! " << weights->GetNumberOfValues() << " vs " << m_NumFibers;
return;
}
for (int i=0; i<weights->GetNumberOfValues(); i++)
m_FiberWeights->SetValue(i, weights->GetValue(i));
m_FiberWeights->SetName("FIBER_WEIGHTS");
}
void mitk::FiberBundle::SetFiberWeight(unsigned int fiber, float weight)
{
m_FiberWeights->SetValue(fiber, weight);
}
void mitk::FiberBundle::SetFiberColors(vtkSmartPointer<vtkUnsignedCharArray> fiberColors)
{
for(long i=0; i<m_FiberPolyData->GetNumberOfPoints(); ++i)
{
unsigned char source[4] = {0,0,0,0};
fiberColors->GetTypedTuple(i, source);
unsigned char target[4] = {0,0,0,0};
target[0] = source[0];
target[1] = source[1];
target[2] = source[2];
target[3] = source[3];
m_FiberColors->InsertTypedTuple(i, target);
}
m_UpdateTime3D.Modified();
m_UpdateTime2D.Modified();
}
itk::Matrix< double, 3, 3 > mitk::FiberBundle::TransformMatrix(itk::Matrix< double, 3, 3 > m, double rx, double ry, double rz)
{
rx = rx*itk::Math::pi/180;
ry = ry*itk::Math::pi/180;
rz = rz*itk::Math::pi/180;
itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity();
rotX[1][1] = cos(rx);
rotX[2][2] = rotX[1][1];
rotX[1][2] = -sin(rx);
rotX[2][1] = -rotX[1][2];
itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity();
rotY[0][0] = cos(ry);
rotY[2][2] = rotY[0][0];
rotY[0][2] = sin(ry);
rotY[2][0] = -rotY[0][2];
itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity();
rotZ[0][0] = cos(rz);
rotZ[1][1] = rotZ[0][0];
rotZ[0][1] = -sin(rz);
rotZ[1][0] = -rotZ[0][1];
itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX;
m = rot*m;
return m;
}
void mitk::FiberBundle::TransformFibers(itk::ScalableAffineTransform< mitk::ScalarType >::Pointer transform)
{
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
for (unsigned int i=0; i<m_NumFibers; i++)
{
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (int j=0; j<numPoints; j++)
{
itk::Point<float, 3> p =mitk::imv::GetItkPoint(points->GetPoint(j));
p = transform->TransformPoint(p);
vtkIdType id = vtkNewPoints->InsertNextPoint(p.GetDataPointer());
container->GetPointIds()->InsertNextId(id);
}
vtkNewCells->InsertNextCell(container);
}
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkNewPoints);
m_FiberPolyData->SetLines(vtkNewCells);
this->SetFiberPolyData(m_FiberPolyData, true);
}
void mitk::FiberBundle::TransformFibers(double rx, double ry, double rz, double tx, double ty, double tz)
{
vnl_matrix_fixed< double, 3, 3 > rot = mitk::imv::GetRotationMatrixVnl(rx, ry, rz);
mitk::BaseGeometry::Pointer geom = this->GetGeometry();
mitk::Point3D center = geom->GetCenter();
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
for (unsigned int i=0; i<m_NumFibers; i++)
{
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (int j=0; j<numPoints; j++)
{
double* p = points->GetPoint(j);
vnl_vector_fixed< double, 3 > dir;
dir[0] = p[0]-center[0];
dir[1] = p[1]-center[1];
dir[2] = p[2]-center[2];
dir = rot*dir;
dir[0] += center[0]+tx;
dir[1] += center[1]+ty;
dir[2] += center[2]+tz;
vtkIdType id = vtkNewPoints->InsertNextPoint(dir.data_block());
container->GetPointIds()->InsertNextId(id);
}
vtkNewCells->InsertNextCell(container);
}
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkNewPoints);
m_FiberPolyData->SetLines(vtkNewCells);
this->SetFiberPolyData(m_FiberPolyData, true);
}
void mitk::FiberBundle::RotateAroundAxis(double x, double y, double z)
{
x = x*itk::Math::pi/180;
y = y*itk::Math::pi/180;
z = z*itk::Math::pi/180;
vnl_matrix_fixed< double, 3, 3 > rotX; rotX.set_identity();
rotX[1][1] = cos(x);
rotX[2][2] = rotX[1][1];
rotX[1][2] = -sin(x);
rotX[2][1] = -rotX[1][2];
vnl_matrix_fixed< double, 3, 3 > rotY; rotY.set_identity();
rotY[0][0] = cos(y);
rotY[2][2] = rotY[0][0];
rotY[0][2] = sin(y);
rotY[2][0] = -rotY[0][2];
vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity();
rotZ[0][0] = cos(z);
rotZ[1][1] = rotZ[0][0];
rotZ[0][1] = -sin(z);
rotZ[1][0] = -rotZ[0][1];
mitk::BaseGeometry::Pointer geom = this->GetGeometry();
mitk::Point3D center = geom->GetCenter();
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
for (unsigned int i=0; i<m_NumFibers; i++)
{
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (int j=0; j<numPoints; j++)
{
double* p = points->GetPoint(j);
vnl_vector_fixed< double, 3 > dir;
dir[0] = p[0]-center[0];
dir[1] = p[1]-center[1];
dir[2] = p[2]-center[2];
dir = rotZ*rotY*rotX*dir;
dir[0] += center[0];
dir[1] += center[1];
dir[2] += center[2];
vtkIdType id = vtkNewPoints->InsertNextPoint(dir.data_block());
container->GetPointIds()->InsertNextId(id);
}
vtkNewCells->InsertNextCell(container);
}
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkNewPoints);
m_FiberPolyData->SetLines(vtkNewCells);
this->SetFiberPolyData(m_FiberPolyData, true);
}
void mitk::FiberBundle::ScaleFibers(double x, double y, double z, bool subtractCenter)
{
MITK_INFO << "Scaling fibers";
boost::progress_display disp(m_NumFibers);
mitk::BaseGeometry* geom = this->GetGeometry();
mitk::Point3D c = geom->GetCenter();
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
for (unsigned int i=0; i<m_NumFibers; i++)
{
++disp ;
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (int j=0; j<numPoints; j++)
{
double* p = points->GetPoint(j);
if (subtractCenter)
{
p[0] -= c[0]; p[1] -= c[1]; p[2] -= c[2];
}
p[0] *= x;
p[1] *= y;
p[2] *= z;
if (subtractCenter)
{
p[0] += c[0]; p[1] += c[1]; p[2] += c[2];
}
vtkIdType id = vtkNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
}
vtkNewCells->InsertNextCell(container);
}
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkNewPoints);
m_FiberPolyData->SetLines(vtkNewCells);
this->SetFiberPolyData(m_FiberPolyData, true);
}
void mitk::FiberBundle::TranslateFibers(double x, double y, double z)
{
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
for (unsigned int i=0; i<m_NumFibers; i++)
{
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (int j=0; j<numPoints; j++)
{
double* p = points->GetPoint(j);
p[0] += x;
p[1] += y;
p[2] += z;
vtkIdType id = vtkNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
}
vtkNewCells->InsertNextCell(container);
}
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkNewPoints);
m_FiberPolyData->SetLines(vtkNewCells);
this->SetFiberPolyData(m_FiberPolyData, true);
}
void mitk::FiberBundle::MirrorFibers(unsigned int axis)
{
if (axis>2)
return;
MITK_INFO << "Mirroring fibers";
boost::progress_display disp(m_NumFibers);
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
for (unsigned int i=0; i<m_NumFibers; i++)
{
++disp;
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (int j=0; j<numPoints; j++)
{
double* p = points->GetPoint(j);
p[axis] = -p[axis];
vtkIdType id = vtkNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
}
vtkNewCells->InsertNextCell(container);
}
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkNewPoints);
m_FiberPolyData->SetLines(vtkNewCells);
this->SetFiberPolyData(m_FiberPolyData, true);
}
void mitk::FiberBundle::RemoveDir(vnl_vector_fixed<double,3> dir, double threshold)
{
dir.normalize();
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
boost::progress_display disp(static_cast<unsigned long>(m_FiberPolyData->GetNumberOfCells()));
for (int i=0; i<m_FiberPolyData->GetNumberOfCells(); i++)
{
++disp ;
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
// calculate curvatures
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
bool discard = false;
for (int j=0; j<numPoints-1; j++)
{
double p1[3];
points->GetPoint(j, p1);
double p2[3];
points->GetPoint(j+1, p2);
vnl_vector_fixed< double, 3 > v1;
v1[0] = p2[0]-p1[0];
v1[1] = p2[1]-p1[1];
v1[2] = p2[2]-p1[2];
if (v1.magnitude()>0.001)
{
v1.normalize();
if (fabs(dot_product(v1,dir))>threshold)
{
discard = true;
break;
}
}
}
if (!discard)
{
for (int j=0; j<numPoints; j++)
{
double p1[3];
points->GetPoint(j, p1);
vtkIdType id = vtkNewPoints->InsertNextPoint(p1);
container->GetPointIds()->InsertNextId(id);
}
vtkNewCells->InsertNextCell(container);
}
}
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkNewPoints);
m_FiberPolyData->SetLines(vtkNewCells);
this->SetFiberPolyData(m_FiberPolyData, true);
// UpdateColorCoding();
// UpdateFiberGeometry();
}
bool mitk::FiberBundle::ApplyCurvatureThreshold(float minRadius, bool deleteFibers)
{
if (minRadius<0)
return true;
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
MITK_INFO << "Applying curvature threshold";
boost::progress_display disp(static_cast<unsigned long>(m_FiberPolyData->GetNumberOfCells()));
for (int i=0; i<m_FiberPolyData->GetNumberOfCells(); i++)
{
++disp ;
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
// calculate curvatures
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (int j=0; j<numPoints-2; j++)
{
double p1[3];
points->GetPoint(j, p1);
double p2[3];
points->GetPoint(j+1, p2);
double p3[3];
points->GetPoint(j+2, p3);
vnl_vector_fixed< float, 3 > v1, v2, v3;
v1[0] = static_cast<float>(p2[0]-p1[0]);
v1[1] = static_cast<float>(p2[1]-p1[1]);
v1[2] = static_cast<float>(p2[2]-p1[2]);
v2[0] = static_cast<float>(p3[0]-p2[0]);
v2[1] = static_cast<float>(p3[1]-p2[1]);
v2[2] = static_cast<float>(p3[2]-p2[2]);
v3[0] = static_cast<float>(p1[0]-p3[0]);
v3[1] = static_cast<float>(p1[1]-p3[1]);
v3[2] = static_cast<float>(p1[2]-p3[2]);
float a = v1.magnitude();
float b = v2.magnitude();
float c = v3.magnitude();
float r = a*b*c/std::sqrt((a+b+c)*(a+b-c)*(b+c-a)*(a-b+c)); // radius of triangle via Heron's formula (area of triangle)
vtkIdType id = vtkNewPoints->InsertNextPoint(p1);
container->GetPointIds()->InsertNextId(id);
if (deleteFibers && r<minRadius)
break;
if (r<minRadius)
{
j += 2;
vtkNewCells->InsertNextCell(container);
container = vtkSmartPointer<vtkPolyLine>::New();
}
else if (j==numPoints-3)
{
id = vtkNewPoints->InsertNextPoint(p2);
container->GetPointIds()->InsertNextId(id);
id = vtkNewPoints->InsertNextPoint(p3);
container->GetPointIds()->InsertNextId(id);
vtkNewCells->InsertNextCell(container);
}
}
}
if (vtkNewCells->GetNumberOfCells()<=0)
return false;
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkNewPoints);
m_FiberPolyData->SetLines(vtkNewCells);
this->SetFiberPolyData(m_FiberPolyData, true);
return true;
}
bool mitk::FiberBundle::RemoveShortFibers(float lengthInMM)
{
MITK_INFO << "Removing short fibers";
if (lengthInMM<=0 || lengthInMM<m_MinFiberLength)
{
MITK_INFO << "No fibers shorter than " << lengthInMM << " mm found!";
return true;
}
if (lengthInMM>m_MaxFiberLength) // can't remove all fibers
{
MITK_WARN << "Process aborted. No fibers would be left!";
return false;
}
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
float min = m_MaxFiberLength;
boost::progress_display disp(m_NumFibers);
for (unsigned int i=0; i<m_NumFibers; i++)
{
++disp;
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
if (m_FiberLengths.at(i)>=lengthInMM)
{
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (int j=0; j<numPoints; j++)
{
double* p = points->GetPoint(j);
vtkIdType id = vtkNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
}
vtkNewCells->InsertNextCell(container);
if (m_FiberLengths.at(i)<min)
min = m_FiberLengths.at(i);
}
}
if (vtkNewCells->GetNumberOfCells()<=0)
return false;
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkNewPoints);
m_FiberPolyData->SetLines(vtkNewCells);
this->SetFiberPolyData(m_FiberPolyData, true);
return true;
}
bool mitk::FiberBundle::RemoveLongFibers(float lengthInMM)
{
if (lengthInMM<=0 || lengthInMM>m_MaxFiberLength)
return true;
if (lengthInMM<m_MinFiberLength) // can't remove all fibers
return false;
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
MITK_INFO << "Removing long fibers";
boost::progress_display disp(m_NumFibers);
for (unsigned int i=0; i<m_NumFibers; i++)
{
++disp;
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
if (m_FiberLengths.at(i)<=lengthInMM)
{
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (int j=0; j<numPoints; j++)
{
double* p = points->GetPoint(j);
vtkIdType id = vtkNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
}
vtkNewCells->InsertNextCell(container);
}
}
if (vtkNewCells->GetNumberOfCells()<=0)
return false;
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkNewPoints);
m_FiberPolyData->SetLines(vtkNewCells);
this->SetFiberPolyData(m_FiberPolyData, true);
return true;
}
void mitk::FiberBundle::ResampleSpline(float pointDistance, double tension, double continuity, double bias )
{
if (pointDistance<=0)
return;
vtkSmartPointer<vtkPoints> vtkSmoothPoints = vtkSmartPointer<vtkPoints>::New(); //in smoothpoints the interpolated points representing a fiber are stored.
//in vtkcells all polylines are stored, actually all id's of them are stored
vtkSmartPointer<vtkCellArray> vtkSmoothCells = vtkSmartPointer<vtkCellArray>::New(); //cellcontainer for smoothed lines
MITK_INFO << "Smoothing fibers";
vtkSmartPointer<vtkFloatArray> newFiberWeights = vtkSmartPointer<vtkFloatArray>::New();
newFiberWeights->SetName("FIBER_WEIGHTS");
newFiberWeights->SetNumberOfValues(m_NumFibers);
std::vector< vtkSmartPointer<vtkPolyLine> > resampled_streamlines;
resampled_streamlines.resize(m_NumFibers);
boost::progress_display disp(m_NumFibers);
#pragma omp parallel for
for (int i=0; i<static_cast<int>(m_NumFibers); i++)
{
vtkSmartPointer<vtkPoints> newPoints = vtkSmartPointer<vtkPoints>::New();
float length = 0;
#pragma omp critical
{
length = m_FiberLengths.at(static_cast<unsigned int>(i));
++disp;
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
for (int j=0; j<numPoints; j++)
newPoints->InsertNextPoint(points->GetPoint(j));
}
int sampling = static_cast<int>(std::ceil(length/pointDistance));
vtkSmartPointer<vtkKochanekSpline> xSpline = vtkSmartPointer<vtkKochanekSpline>::New();
vtkSmartPointer<vtkKochanekSpline> ySpline = vtkSmartPointer<vtkKochanekSpline>::New();
vtkSmartPointer<vtkKochanekSpline> zSpline = vtkSmartPointer<vtkKochanekSpline>::New();
xSpline->SetDefaultBias(bias); xSpline->SetDefaultTension(tension); xSpline->SetDefaultContinuity(continuity);
ySpline->SetDefaultBias(bias); ySpline->SetDefaultTension(tension); ySpline->SetDefaultContinuity(continuity);
zSpline->SetDefaultBias(bias); zSpline->SetDefaultTension(tension); zSpline->SetDefaultContinuity(continuity);
vtkSmartPointer<vtkParametricSpline> spline = vtkSmartPointer<vtkParametricSpline>::New();
spline->SetXSpline(xSpline);
spline->SetYSpline(ySpline);
spline->SetZSpline(zSpline);
spline->SetPoints(newPoints);
vtkSmartPointer<vtkParametricFunctionSource> functionSource = vtkSmartPointer<vtkParametricFunctionSource>::New();
functionSource->SetParametricFunction(spline);
functionSource->SetUResolution(sampling);
functionSource->SetVResolution(sampling);
functionSource->SetWResolution(sampling);
functionSource->Update();
vtkPolyData* outputFunction = functionSource->GetOutput();
vtkPoints* tmpSmoothPnts = outputFunction->GetPoints(); //smoothPoints of current fiber
vtkSmartPointer<vtkPolyLine> smoothLine = vtkSmartPointer<vtkPolyLine>::New();
#pragma omp critical
{
for (int j=0; j<tmpSmoothPnts->GetNumberOfPoints(); j++)
{
vtkIdType id = vtkSmoothPoints->InsertNextPoint(tmpSmoothPnts->GetPoint(j));
smoothLine->GetPointIds()->InsertNextId(id);
}
resampled_streamlines[static_cast<unsigned long>(i)] = smoothLine;
}
}
for (auto container : resampled_streamlines)
{
vtkSmoothCells->InsertNextCell(container);
}
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkSmoothPoints);
m_FiberPolyData->SetLines(vtkSmoothCells);
this->SetFiberPolyData(m_FiberPolyData, true);
}
void mitk::FiberBundle::ResampleSpline(float pointDistance)
{
ResampleSpline(pointDistance, 0, 0, 0 );
}
unsigned int mitk::FiberBundle::GetNumberOfPoints() const
{
unsigned int points = 0;
for (int i=0; i<m_FiberPolyData->GetNumberOfCells(); i++)
{
vtkCell* cell = m_FiberPolyData->GetCell(i);
points += cell->GetNumberOfPoints();
}
return points;
}
void mitk::FiberBundle::Compress(float error)
{
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
MITK_INFO << "Compressing fibers";
unsigned int numRemovedPoints = 0;
boost::progress_display disp(static_cast<unsigned long>(m_FiberPolyData->GetNumberOfCells()));
vtkSmartPointer<vtkFloatArray> newFiberWeights = vtkSmartPointer<vtkFloatArray>::New();
newFiberWeights->SetName("FIBER_WEIGHTS");
newFiberWeights->SetNumberOfValues(m_NumFibers);
#pragma omp parallel for
for (int i=0; i<static_cast<int>(m_FiberPolyData->GetNumberOfCells()); i++)
{
std::vector< vnl_vector_fixed< double, 3 > > vertices;
float weight = 1;
#pragma omp critical
{
++disp;
weight = m_FiberWeights->GetValue(i);
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
for (int j=0; j<numPoints; j++)
{
double cand[3];
points->GetPoint(j, cand);
vnl_vector_fixed< double, 3 > candV;
candV[0]=cand[0]; candV[1]=cand[1]; candV[2]=cand[2];
vertices.push_back(candV);
}
}
// calculate curvatures
auto numPoints = vertices.size();
std::vector< int > removedPoints; removedPoints.resize(numPoints, 0);
removedPoints[0]=-1; removedPoints[numPoints-1]=-1;
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
unsigned int remCounter = 0;
bool pointFound = true;
while (pointFound)
{
pointFound = false;
double minError = static_cast<double>(error);
unsigned int removeIndex = 0;
for (unsigned int j=0; j<vertices.size(); j++)
{
if (removedPoints[j]==0)
{
vnl_vector_fixed< double, 3 > candV = vertices.at(j);
int validP = -1;
vnl_vector_fixed< double, 3 > pred;
for (int k=static_cast<int>(j)-1; k>=0; k--)
if (removedPoints[static_cast<unsigned int>(k)]<=0)
{
pred = vertices.at(static_cast<unsigned int>(k));
validP = k;
break;
}
int validS = -1;
vnl_vector_fixed< double, 3 > succ;
for (unsigned int k=j+1; k<numPoints; k++)
if (removedPoints[k]<=0)
{
succ = vertices.at(k);
validS = static_cast<int>(k);
break;
}
if (validP>=0 && validS>=0)
{
double a = (candV-pred).magnitude();
double b = (candV-succ).magnitude();
double c = (pred-succ).magnitude();
double s=0.5*(a+b+c);
double hc=(2.0/c)*sqrt(fabs(s*(s-a)*(s-b)*(s-c)));
if (hc<minError)
{
removeIndex = j;
minError = hc;
pointFound = true;
}
}
}
}
if (pointFound)
{
removedPoints[removeIndex] = 1;
remCounter++;
}
}
for (unsigned int j=0; j<numPoints; j++)
{
if (removedPoints[j]<=0)
{
#pragma omp critical
{
vtkIdType id = vtkNewPoints->InsertNextPoint(vertices.at(j).data_block());
container->GetPointIds()->InsertNextId(id);
}
}
}
#pragma omp critical
{
newFiberWeights->SetValue(vtkNewCells->GetNumberOfCells(), weight);
numRemovedPoints += remCounter;
vtkNewCells->InsertNextCell(container);
}
}
if (vtkNewCells->GetNumberOfCells()>0)
{
MITK_INFO << "Removed points: " << numRemovedPoints;
SetFiberWeights(newFiberWeights);
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkNewPoints);
m_FiberPolyData->SetLines(vtkNewCells);
this->SetFiberPolyData(m_FiberPolyData, true);
}
}
void mitk::FiberBundle::ResampleToNumPoints(unsigned int targetPoints)
{
if (targetPoints<2)
mitkThrow() << "Minimum two points required for resampling!";
MITK_INFO << "Resampling fibers (number of points " << targetPoints << ")";
bool unequal_fibs = true;
while (unequal_fibs)
{
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkFloatArray> newFiberWeights = vtkSmartPointer<vtkFloatArray>::New();
newFiberWeights->SetName("FIBER_WEIGHTS");
newFiberWeights->SetNumberOfValues(m_NumFibers);
unequal_fibs = false;
for (unsigned int i=0; i<m_FiberPolyData->GetNumberOfCells(); i++)
{
std::vector< vnl_vector_fixed< double, 3 > > vertices;
float weight = 1;
double seg_len = 0;
{
weight = m_FiberWeights->GetValue(i);
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
if (numPoints!=targetPoints)
seg_len = static_cast<double>(this->GetFiberLength(i)/(targetPoints-1));
vtkPoints* points = cell->GetPoints();
for (int j=0; j<numPoints; j++)
{
double cand[3];
points->GetPoint(j, cand);
vnl_vector_fixed< double, 3 > candV;
candV[0]=cand[0]; candV[1]=cand[1]; candV[2]=cand[2];
vertices.push_back(candV);
}
}
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
vnl_vector_fixed< double, 3 > lastV = vertices.at(0);
{
vtkIdType id = vtkNewPoints->InsertNextPoint(lastV.data_block());
container->GetPointIds()->InsertNextId(id);
}
for (unsigned int j=1; j<vertices.size(); j++)
{
vnl_vector_fixed< double, 3 > vec = vertices.at(j) - lastV;
double new_dist = vec.magnitude();
if (new_dist >= seg_len && seg_len>0)
{
vnl_vector_fixed< double, 3 > newV = lastV;
if ( new_dist-seg_len <= mitk::eps )
{
vec.normalize();
newV += vec * seg_len;
}
else
{
// intersection between sphere (radius 'pointDistance', center 'lastV') and line (direction 'd' and point 'p')
vnl_vector_fixed< double, 3 > p = vertices.at(j-1);
vnl_vector_fixed< double, 3 > d = vertices.at(j) - p;
double a = d[0]*d[0] + d[1]*d[1] + d[2]*d[2];
double b = 2 * (d[0] * (p[0] - lastV[0]) + d[1] * (p[1] - lastV[1]) + d[2] * (p[2] - lastV[2]));
double c = (p[0] - lastV[0])*(p[0] - lastV[0]) + (p[1] - lastV[1])*(p[1] - lastV[1]) + (p[2] - lastV[2])*(p[2] - lastV[2]) - seg_len*seg_len;
double v1 =(-b + std::sqrt(b*b-4*a*c))/(2*a);
double v2 =(-b - std::sqrt(b*b-4*a*c))/(2*a);
if (v1>0)
newV = p + d * v1;
else if (v2>0)
newV = p + d * v2;
else
MITK_INFO << "ERROR1 - linear resampling";
j--;
}
//#pragma omp critical
{
vtkIdType id = vtkNewPoints->InsertNextPoint(newV.data_block());
container->GetPointIds()->InsertNextId(id);
}
lastV = newV;
}
else if ( (j==vertices.size()-1 && new_dist>0.0001) || seg_len<=0.0000001)
{
//#pragma omp critical
{
vtkIdType id = vtkNewPoints->InsertNextPoint(vertices.at(j).data_block());
container->GetPointIds()->InsertNextId(id);
}
}
}
//#pragma omp critical
{
newFiberWeights->SetValue(vtkNewCells->GetNumberOfCells(), weight);
vtkNewCells->InsertNextCell(container);
if (container->GetNumberOfPoints()!=targetPoints)
unequal_fibs = true;
}
}
if (vtkNewCells->GetNumberOfCells()>0)
{
SetFiberWeights(newFiberWeights);
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkNewPoints);
m_FiberPolyData->SetLines(vtkNewCells);
this->SetFiberPolyData(m_FiberPolyData, true);
}
}
}
void mitk::FiberBundle::ResampleLinear(double pointDistance)
{
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
MITK_INFO << "Resampling fibers (linear)";
boost::progress_display disp(static_cast<unsigned long>(m_FiberPolyData->GetNumberOfCells()));
vtkSmartPointer<vtkFloatArray> newFiberWeights = vtkSmartPointer<vtkFloatArray>::New();
newFiberWeights->SetName("FIBER_WEIGHTS");
newFiberWeights->SetNumberOfValues(m_NumFibers);
std::vector< vtkSmartPointer<vtkPolyLine> > resampled_streamlines;
resampled_streamlines.resize(static_cast<unsigned long>(m_FiberPolyData->GetNumberOfCells()));
#pragma omp parallel for
for (int i=0; i<static_cast<int>(m_FiberPolyData->GetNumberOfCells()); i++)
{
std::vector< vnl_vector_fixed< double, 3 > > vertices;
#pragma omp critical
{
++disp;
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
for (int j=0; j<numPoints; j++)
{
double cand[3];
points->GetPoint(j, cand);
vnl_vector_fixed< double, 3 > candV;
candV[0]=cand[0]; candV[1]=cand[1]; candV[2]=cand[2];
vertices.push_back(candV);
}
}
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
vnl_vector_fixed< double, 3 > lastV = vertices.at(0);
#pragma omp critical
{
vtkIdType id = vtkNewPoints->InsertNextPoint(lastV.data_block());
container->GetPointIds()->InsertNextId(id);
}
for (unsigned int j=1; j<vertices.size(); j++)
{
vnl_vector_fixed< double, 3 > vec = vertices.at(j) - lastV;
double new_dist = vec.magnitude();
if (new_dist >= pointDistance)
{
vnl_vector_fixed< double, 3 > newV = lastV;
if ( new_dist-pointDistance <= mitk::eps )
{
vec.normalize();
newV += vec * pointDistance;
}
else
{
// intersection between sphere (radius 'pointDistance', center 'lastV') and line (direction 'd' and point 'p')
vnl_vector_fixed< double, 3 > p = vertices.at(j-1);
vnl_vector_fixed< double, 3 > d = vertices.at(j) - p;
double a = d[0]*d[0] + d[1]*d[1] + d[2]*d[2];
double b = 2 * (d[0] * (p[0] - lastV[0]) + d[1] * (p[1] - lastV[1]) + d[2] * (p[2] - lastV[2]));
double c = (p[0] - lastV[0])*(p[0] - lastV[0]) + (p[1] - lastV[1])*(p[1] - lastV[1]) + (p[2] - lastV[2])*(p[2] - lastV[2]) - pointDistance*pointDistance;
double v1 =(-b + std::sqrt(b*b-4*a*c))/(2*a);
double v2 =(-b - std::sqrt(b*b-4*a*c))/(2*a);
if (v1>0)
newV = p + d * v1;
else if (v2>0)
newV = p + d * v2;
else
MITK_INFO << "ERROR1 - linear resampling";
j--;
}
#pragma omp critical
{
vtkIdType id = vtkNewPoints->InsertNextPoint(newV.data_block());
container->GetPointIds()->InsertNextId(id);
}
lastV = newV;
}
else if (j==vertices.size()-1 && new_dist>0.0001)
{
#pragma omp critical
{
vtkIdType id = vtkNewPoints->InsertNextPoint(vertices.at(j).data_block());
container->GetPointIds()->InsertNextId(id);
}
}
}
#pragma omp critical
{
resampled_streamlines[static_cast<unsigned int>(i)] = container;
}
}
for (auto container : resampled_streamlines)
{
vtkNewCells->InsertNextCell(container);
}
if (vtkNewCells->GetNumberOfCells()>0)
{
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
m_FiberPolyData->SetPoints(vtkNewPoints);
m_FiberPolyData->SetLines(vtkNewCells);
this->SetFiberPolyData(m_FiberPolyData, true);
}
}
// reapply selected colorcoding in case PolyData structure has changed
bool mitk::FiberBundle::Equals(mitk::FiberBundle* fib, double eps)
{
if (fib==nullptr)
{
MITK_INFO << "Reference bundle is nullptr!";
return false;
}
if (m_NumFibers!=fib->GetNumFibers())
{
MITK_INFO << "Unequal number of fibers!";
MITK_INFO << m_NumFibers << " vs. " << fib->GetNumFibers();
return false;
}
for (unsigned int i=0; i<m_NumFibers; i++)
{
vtkCell* cell = m_FiberPolyData->GetCell(i);
auto numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vtkCell* cell2 = fib->GetFiberPolyData()->GetCell(i);
auto numPoints2 = cell2->GetNumberOfPoints();
vtkPoints* points2 = cell2->GetPoints();
if (numPoints2!=numPoints)
{
MITK_INFO << "Unequal number of points in fiber " << i << "!";
MITK_INFO << numPoints2 << " vs. " << numPoints;
return false;
}
for (int j=0; j<numPoints; j++)
{
double* p1 = points->GetPoint(j);
double* p2 = points2->GetPoint(j);
if (fabs(p1[0]-p2[0])>eps || fabs(p1[1]-p2[1])>eps || fabs(p1[2]-p2[2])>eps)
{
MITK_INFO << "Unequal points in fiber " << i << " at position " << j << "!";
MITK_INFO << "p1: " << p1[0] << ", " << p1[1] << ", " << p1[2];
MITK_INFO << "p2: " << p2[0] << ", " << p2[1] << ", " << p2[2];
return false;
}
}
}
return true;
}
void mitk::FiberBundle::PrintSelf(std::ostream &os, itk::Indent indent) const
{
os << indent << "Number of fibers: " << this->GetNumFibers() << std::endl;
os << indent << "Min. fiber length: " << this->GetMinFiberLength() << std::endl;
os << indent << "Max. fiber length: " << this->GetMaxFiberLength() << std::endl;
os << indent << "Mean fiber length: " << this->GetMeanFiberLength() << std::endl;
os << indent << "Median fiber length: " << this->GetMedianFiberLength() << std::endl;
os << indent << "STDEV fiber length: " << this->GetLengthStDev() << std::endl;
os << indent << "Number of points: " << this->GetNumberOfPoints() << std::endl;
os << indent << "Extent x: " << this->GetGeometry()->GetExtentInMM(0) << "mm" << std::endl;
os << indent << "Extent y: " << this->GetGeometry()->GetExtentInMM(1) << "mm" << std::endl;
os << indent << "Extent z: " << this->GetGeometry()->GetExtentInMM(2) << "mm" << std::endl;
os << indent << "Diagonal: " << this->GetGeometry()->GetDiagonalLength() << "mm" << std::endl;
os << "\nReference geometry:" << std::endl;
os << indent << "Size: [" << std::defaultfloat << m_TrackVisHeader.dim[0] << " " << m_TrackVisHeader.dim[1] << " " << m_TrackVisHeader.dim[2] << "]" << std::endl;
os << indent << "Voxel size: [" << m_TrackVisHeader.voxel_size[0] << " " << m_TrackVisHeader.voxel_size[1] << " " << m_TrackVisHeader.voxel_size[2] << "]" << std::endl;
os << indent << "Origin: [" << m_TrackVisHeader.origin[0] << " " << m_TrackVisHeader.origin[1] << " " << m_TrackVisHeader.origin[2] << "]" << std::endl;
os << indent << "Matrix: " << std::scientific << std::endl;
os << indent << "[[" << m_TrackVisHeader.vox_to_ras[0][0] << ", " << m_TrackVisHeader.vox_to_ras[0][1] << ", " << m_TrackVisHeader.vox_to_ras[0][2] << ", " << m_TrackVisHeader.vox_to_ras[0][3] << "]" << std::endl;
os << indent << " [" << m_TrackVisHeader.vox_to_ras[1][0] << ", " << m_TrackVisHeader.vox_to_ras[1][1] << ", " << m_TrackVisHeader.vox_to_ras[1][2] << ", " << m_TrackVisHeader.vox_to_ras[1][3] << "]" << std::endl;
os << indent << " [" << m_TrackVisHeader.vox_to_ras[2][0] << ", " << m_TrackVisHeader.vox_to_ras[2][1] << ", " << m_TrackVisHeader.vox_to_ras[2][2] << ", " << m_TrackVisHeader.vox_to_ras[2][3] << "]" << std::endl;
os << indent << " [" << m_TrackVisHeader.vox_to_ras[3][0] << ", " << m_TrackVisHeader.vox_to_ras[3][1] << ", " << m_TrackVisHeader.vox_to_ras[3][2] << ", " << m_TrackVisHeader.vox_to_ras[3][3] << "]]" << std::defaultfloat << std::endl;
if (m_FiberWeights!=nullptr)
{
std::vector< float > weights;
for (int i=0; i<m_FiberWeights->GetSize(); i++)
weights.push_back(m_FiberWeights->GetValue(i));
std::sort(weights.begin(), weights.end());
os << "\nFiber weight statistics" << std::endl;
os << indent << "Min: " << weights.front() << std::endl;
os << indent << "1% quantile: " << weights.at(static_cast<unsigned long>(weights.size()*0.01)) << std::endl;
os << indent << "5% quantile: " << weights.at(static_cast<unsigned long>(weights.size()*0.05)) << std::endl;
os << indent << "25% quantile: " << weights.at(static_cast<unsigned long>(weights.size()*0.25)) << std::endl;
os << indent << "Median: " << weights.at(static_cast<unsigned long>(weights.size()*0.5)) << std::endl;
os << indent << "75% quantile: " << weights.at(static_cast<unsigned long>(weights.size()*0.75)) << std::endl;
os << indent << "95% quantile: " << weights.at(static_cast<unsigned long>(weights.size()*0.95)) << std::endl;
os << indent << "99% quantile: " << weights.at(static_cast<unsigned long>(weights.size()*0.99)) << std::endl;
os << indent << "Max: " << weights.back() << std::endl;
}
else
os << indent << "\n\nNo fiber weight array found." << std::endl;
Superclass::PrintSelf(os, 0);
}
mitk::FiberBundle::TrackVis_header mitk::FiberBundle::GetTrackVisHeader()
{
if (m_TrackVisHeader.hdr_size==0)
{
mitk::Geometry3D::Pointer geom = dynamic_cast<mitk::Geometry3D*>(this->GetGeometry());
SetTrackVisHeader(geom);
}
return m_TrackVisHeader;
}
void mitk::FiberBundle::SetTrackVisHeader(const mitk::FiberBundle::TrackVis_header &TrackVisHeader)
{
m_TrackVisHeader = TrackVisHeader;
}
void mitk::FiberBundle::SetTrackVisHeader(mitk::BaseGeometry* geometry)
{
vtkSmartPointer< vtkMatrix4x4 > matrix = vtkSmartPointer< vtkMatrix4x4 >::New();
matrix->Identity();
if (geometry==nullptr)
return;
for(int i=0; i<3 ;i++)
{
m_TrackVisHeader.dim[i] = geometry->GetExtent(i);
m_TrackVisHeader.voxel_size[i] = geometry->GetSpacing()[i];
m_TrackVisHeader.origin[i] = geometry->GetOrigin()[i];
matrix = geometry->GetVtkMatrix();
}
for (int i=0; i<4; ++i)
for (int j=0; j<4; ++j)
m_TrackVisHeader.vox_to_ras[i][j] = matrix->GetElement(i, j);
m_TrackVisHeader.n_scalars = 0;
m_TrackVisHeader.n_properties = 0;
sprintf(m_TrackVisHeader.voxel_order,"LPS");
m_TrackVisHeader.image_orientation_patient[0] = 1.0;
m_TrackVisHeader.image_orientation_patient[1] = 0.0;
m_TrackVisHeader.image_orientation_patient[2] = 0.0;
m_TrackVisHeader.image_orientation_patient[3] = 0.0;
m_TrackVisHeader.image_orientation_patient[4] = 1.0;
m_TrackVisHeader.image_orientation_patient[5] = 0.0;
m_TrackVisHeader.pad1[0] = 0;
m_TrackVisHeader.pad1[1] = 0;
m_TrackVisHeader.pad2[0] = 0;
m_TrackVisHeader.pad2[1] = 0;
m_TrackVisHeader.invert_x = 0;
m_TrackVisHeader.invert_y = 0;
m_TrackVisHeader.invert_z = 0;
m_TrackVisHeader.swap_xy = 0;
m_TrackVisHeader.swap_yz = 0;
m_TrackVisHeader.swap_zx = 0;
m_TrackVisHeader.n_count = 0;
m_TrackVisHeader.version = 2;
m_TrackVisHeader.hdr_size = 1000;
std::string id = "TRACK";
strcpy(m_TrackVisHeader.id_string, id.c_str());
}
/* ESSENTIAL IMPLEMENTATION OF SUPERCLASS METHODS */
void mitk::FiberBundle::UpdateOutputInformation()
{
}
void mitk::FiberBundle::SetRequestedRegionToLargestPossibleRegion()
{
}
bool mitk::FiberBundle::RequestedRegionIsOutsideOfTheBufferedRegion()
{
return false;
}
bool mitk::FiberBundle::VerifyRequestedRegion()
{
return true;
}
void mitk::FiberBundle::SetRequestedRegion(const itk::DataObject* )
{
}
diff --git a/Modules/DiffusionCore/IODataStructures/mitkFiberBundle.h b/Modules/DiffusionCore/IODataStructures/mitkFiberBundle.h
index 9086423..131b02e 100644
--- a/Modules/DiffusionCore/IODataStructures/mitkFiberBundle.h
+++ b/Modules/DiffusionCore/IODataStructures/mitkFiberBundle.h
@@ -1,244 +1,244 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_FiberBundle_H
#define _MITK_FiberBundle_H
//includes for MITK datastructure
#include <mitkBaseData.h>
#include <MitkDiffusionCoreExports.h>
#include <mitkImage.h>
#include <mitkDataStorage.h>
#include <mitkPlanarFigure.h>
#include <mitkPixelTypeTraits.h>
#include <mitkPlanarFigureComposite.h>
#include <mitkPeakImage.h>
//includes storing fiberdata
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkPoints.h>
#include <vtkDataSet.h>
#include <vtkTransform.h>
#include <vtkFloatArray.h>
#include <itkScalableAffineTransform.h>
#include <mitkDiffusionFunctionCollection.h>
namespace mitk {
/**
* \brief Base Class for Fiber Bundles; */
class MITKDIFFUSIONCORE_EXPORT FiberBundle : public BaseData
{
public:
typedef itk::Image<unsigned char, 3> ItkUcharImgType;
// fiber colorcodings
static const char* FIBER_ID_ARRAY;
void UpdateOutputInformation() override;
void SetRequestedRegionToLargestPossibleRegion() override;
bool RequestedRegionIsOutsideOfTheBufferedRegion() override;
bool VerifyRequestedRegion() override;
void SetRequestedRegion(const itk::DataObject*) override;
mitkClassMacro( FiberBundle, BaseData )
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitkNewMacro1Param(Self, vtkSmartPointer<vtkPolyData>) // custom constructor
// colorcoding related methods
void ColorFibersByFiberWeights(bool opacity, bool normalize);
void ColorFibersByCurvature(bool opacity, bool normalize);
void ColorFibersByLength(bool opacity, bool normalize);
void ColorFibersByScalarMap(mitk::Image::Pointer, bool opacity, bool normalize);
template <typename TPixel>
void ColorFibersByScalarMap(const mitk::PixelType pixelType, mitk::Image::Pointer, bool opacity, bool normalize);
void ColorFibersByOrientation();
void SetFiberOpacity(vtkDoubleArray *FAValArray);
void ResetFiberOpacity();
void SetFiberColors(vtkSmartPointer<vtkUnsignedCharArray> fiberColors);
void SetFiberColors(float r, float g, float b, float alpha=255);
vtkSmartPointer<vtkUnsignedCharArray> GetFiberColors() const { return m_FiberColors; }
// fiber compression
void Compress(float error = 0.0);
// fiber resampling
void ResampleSpline(float pointDistance=1);
void ResampleSpline(float pointDistance, double tension, double continuity, double bias );
void ResampleLinear(double pointDistance=1);
void ResampleToNumPoints(unsigned int targetPoints);
mitk::FiberBundle::Pointer FilterByWeights(float weight_thr, bool invert=false);
bool RemoveShortFibers(float lengthInMM);
bool RemoveLongFibers(float lengthInMM);
bool ApplyCurvatureThreshold(float minRadius, bool deleteFibers);
void MirrorFibers(unsigned int axis);
void RotateAroundAxis(double x, double y, double z);
void TranslateFibers(double x, double y, double z);
void ScaleFibers(double x, double y, double z, bool subtractCenter=true);
void TransformFibers(double rx, double ry, double rz, double tx, double ty, double tz);
void TransformFibers(itk::ScalableAffineTransform< mitk::ScalarType >::Pointer transform);
void RemoveDir(vnl_vector_fixed<double,3> dir, double threshold);
template< class TType=float >
void TransformPoint(itk::Point<TType, 3>& point, itk::Matrix< TType, 3, 3>& rot, TType& tx, TType& ty, TType& tz)
{
mitk::Point3D center = this->GetGeometry()->GetCenter();
point[0] -= center[0];
point[1] -= center[1];
point[2] -= center[2];
point = rot*point;
point[0] += center[0]+tx;
point[1] += center[1]+ty;
point[2] += center[2]+tz;
}
template< class TType=float >
void TransformPoint(itk::Point<TType, 3>& point, TType rx, TType ry, TType rz, TType tx, TType ty, TType tz)
{
auto rot = mitk::imv::GetRotationMatrixItk<TType>(rx, ry, rz);
mitk::Point3D center = this->GetGeometry()->GetCenter();
point[0] -= center[0];
point[1] -= center[1];
point[2] -= center[2];
point = rot*point;
point[0] += center[0]+tx;
point[1] += center[1]+ty;
point[2] += center[2]+tz;
}
itk::Matrix< double, 3, 3 > TransformMatrix(itk::Matrix< double, 3, 3 > m, double rx, double ry, double rz);
// add/subtract fibers
FiberBundle::Pointer AddBundle(FiberBundle* fib);
mitk::FiberBundle::Pointer AddBundles(std::vector< mitk::FiberBundle::Pointer > fibs);
FiberBundle::Pointer SubtractBundle(FiberBundle* fib);
// fiber subset extraction
FiberBundle::Pointer ExtractFiberSubset(DataNode *roi, DataStorage* storage);
std::vector<unsigned int> ExtractFiberIdSubset(DataNode* roi, DataStorage* storage);
FiberBundle::Pointer RemoveFibersOutside(ItkUcharImgType* mask, bool invert=false);
float GetOverlap(ItkUcharImgType* mask);
std::tuple<float, float> GetDirectionalOverlap(ItkUcharImgType* mask, mitk::PeakImage::ItkPeakImageType* peak_image);
float GetNumEpFractionInMask(ItkUcharImgType* mask, bool different_label);
mitk::FiberBundle::Pointer SubsampleFibers(float factor, bool random_seed);
// get/set data
float GetFiberLength(unsigned int index) const { return m_FiberLengths.at(index); }
vtkSmartPointer<vtkFloatArray> GetFiberWeights() const { return m_FiberWeights; }
float GetFiberWeight(unsigned int fiber) const;
void SetFiberWeights(float newWeight);
void SetFiberWeight(unsigned int fiber, float weight);
void SetFiberWeights(vtkSmartPointer<vtkFloatArray> weights);
void SetFiberPolyData(vtkSmartPointer<vtkPolyData>, bool updateGeometry = true);
vtkSmartPointer<vtkPolyData> GetFiberPolyData() const;
itkGetConstMacro( NumFibers, unsigned int)
//itkGetMacro( FiberSampling, int)
itkGetConstMacro( MinFiberLength, float )
itkGetConstMacro( MaxFiberLength, float )
itkGetConstMacro( MeanFiberLength, float )
itkGetConstMacro( MedianFiberLength, float )
itkGetConstMacro( LengthStDev, float )
itkGetConstMacro( UpdateTime2D, itk::TimeStamp )
itkGetConstMacro( UpdateTime3D, itk::TimeStamp )
void RequestUpdate2D(){ m_UpdateTime2D.Modified(); }
void RequestUpdate3D(){ m_UpdateTime3D.Modified(); }
void RequestUpdate(){ m_UpdateTime2D.Modified(); m_UpdateTime3D.Modified(); }
unsigned int GetNumberOfPoints() const;
// copy fiber bundle
mitk::FiberBundle::Pointer GetDeepCopy();
// compare fiber bundles
bool Equals(FiberBundle* fib, double eps=0.01);
vtkSmartPointer<vtkPolyData> GeneratePolyDataByIds(std::vector<unsigned int> fiberIds, vtkSmartPointer<vtkFloatArray> weights);
// Structure to hold metadata of a TrackVis file
struct TrackVis_header
{
char id_string[6];
short int dim[3];
float voxel_size[3];
float origin[3];
short int n_scalars;
char scalar_name[10][20];
short int n_properties;
char property_name[10][20];
float vox_to_ras[4][4];
char reserved[444];
char voxel_order[4];
char pad2[4];
float image_orientation_patient[6];
char pad1[2];
unsigned char invert_x;
unsigned char invert_y;
unsigned char invert_z;
unsigned char swap_xy;
unsigned char swap_yz;
unsigned char swap_zx;
int n_count;
int version;
int hdr_size;
};
TrackVis_header GetTrackVisHeader();
void SetTrackVisHeader(const TrackVis_header &TrackVisHeader);
void SetTrackVisHeader(BaseGeometry *geometry);
protected:
FiberBundle( vtkPolyData* fiberPolyData = nullptr );
~FiberBundle() override;
void GenerateFiberIds();
void UpdateFiberGeometry();
void PrintSelf(std::ostream &os, itk::Indent indent) const override;
private:
// actual fiber container
vtkSmartPointer<vtkPolyData> m_FiberPolyData;
// contains fiber ids
vtkSmartPointer<vtkDataSet> m_FiberIdDataSet;
unsigned int m_NumFibers;
vtkSmartPointer<vtkUnsignedCharArray> m_FiberColors;
vtkSmartPointer<vtkFloatArray> m_FiberWeights;
std::vector< float > m_FiberLengths;
float m_MinFiberLength;
float m_MaxFiberLength;
float m_MeanFiberLength;
float m_MedianFiberLength;
float m_LengthStDev;
itk::TimeStamp m_UpdateTime2D;
itk::TimeStamp m_UpdateTime3D;
TrackVis_header m_TrackVisHeader;
};
} // namespace mitk
#endif /* _MITK_FiberBundle_H */
diff --git a/Modules/DiffusionCore/IODataStructures/mitkOdfImage.cpp b/Modules/DiffusionCore/IODataStructures/mitkOdfImage.cpp
index 3d9b746..7f20a8b 100644
--- a/Modules/DiffusionCore/IODataStructures/mitkOdfImage.cpp
+++ b/Modules/DiffusionCore/IODataStructures/mitkOdfImage.cpp
@@ -1,88 +1,88 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkOdfImage.h"
#include "mitkImageCast.h"
#include "itkImage.h"
#include "mitkImageVtkAccessor.h"
#include "itkOdfToRgbImageFilter.h"
#include <mitkProperties.h>
mitk::OdfImage::OdfImage() : Image()
{
m_RgbImage = nullptr;
// not needed anymore as soon as all diffusion images are identified via properties anyway
this->SetProperty("IsOdfImage", mitk::BoolProperty::New(true));
}
mitk::OdfImage::~OdfImage()
{
}
const vtkImageData* mitk::OdfImage::GetVtkImageData(int t, int n) const
{
if(m_RgbImage.IsNull())
ConstructRgbImage();
return m_RgbImage->GetVtkImageData(t,n);
}
vtkImageData*mitk::OdfImage::GetVtkImageData(int t, int n)
{
if(m_RgbImage.IsNull())
ConstructRgbImage();
return m_RgbImage->GetVtkImageData(t,n);
}
void mitk::OdfImage::ConstructRgbImage() const
{
typedef itk::Image<itk::Vector<float,ODF_SAMPLING_SIZE>,3> ImageType;
typedef itk::OdfToRgbImageFilter<ImageType> FilterType;
FilterType::Pointer filter = FilterType::New();
ImageType::Pointer itkvol = ImageType::New();
mitk::CastToItkImage(this, itkvol);
filter->SetInput(itkvol);
filter->Update();
m_RgbImage = mitk::Image::New();
m_RgbImage->InitializeByItk( filter->GetOutput() );
m_RgbImage->SetVolume( filter->GetOutput()->GetBufferPointer() );
}
const vtkImageData* mitk::OdfImage::GetNonRgbVtkImageData(int t, int n) const
{
return Superclass::GetVtkImageData(t,n);
}
vtkImageData* mitk::OdfImage::GetNonRgbVtkImageData(int t, int n)
{
return Superclass::GetVtkImageData(t,n);
}
//
//void mitk::OdfImage::CopyConstruct(mitk::Image::Pointer img)
//{
// m_LargestPossibleRegion = img->GetLargestPossibleRegion();
// m_RequestedRegion = img->GetRequestedRegion();
// m_Channels.push_back(img->GetChannelData(0).GetPointer());
// m_Volumes.push_back(img->GetVolumeData(0).GetPointer());
// m_Slices.push_back(img->GetSliceData(0).GetPointer());
// m_Dimension = img->GetDimension();
// m_Dimensions = img->GetDimensions();
// m_PixelType = img->GetPixelType();
//}
diff --git a/Modules/DiffusionCore/IODataStructures/mitkOdfImage.h b/Modules/DiffusionCore/IODataStructures/mitkOdfImage.h
index 1aafac6..62a5286 100644
--- a/Modules/DiffusionCore/IODataStructures/mitkOdfImage.h
+++ b/Modules/DiffusionCore/IODataStructures/mitkOdfImage.h
@@ -1,77 +1,77 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkOdfImage__h
#define __mitkOdfImage__h
#include "mitkImage.h"
#include "itkVectorImage.h"
#include "mitkImageVtkAccessor.h"
#include <MitkDiffusionCoreExports.h>
// generate by n-fold subdivisions of an icosahedron
// 1 - 12
// 2 - 42
// 3 - 92
// 4 - 162
// 5 - 252
// 6 - 362
// 7 - 492
// 8 - 642
// 9 - 812
// 10 - 1002
#define ODF_SAMPLING_SIZE 252
namespace mitk
{
/**
* \brief this class encapsulates orientation distribution images
*/
class MITKDIFFUSIONCORE_EXPORT OdfImage : public Image
{
public:
typedef float ScalarPixelType;
typedef itk::Vector< ScalarPixelType, ODF_SAMPLING_SIZE > PixelType;
typedef itk::Image< itk::Vector< ScalarPixelType, ODF_SAMPLING_SIZE >, 3 > ItkOdfImageType;
mitkClassMacro( OdfImage, Image )
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
virtual const vtkImageData* GetNonRgbVtkImageData(int t = 0, int n = 0) const;
virtual vtkImageData* GetNonRgbVtkImageData(int t = 0, int n = 0);
const vtkImageData* GetVtkImageData(int t = 0, int n = 0) const override;
vtkImageData* GetVtkImageData(int t = 0, int n = 0) override;
virtual void ConstructRgbImage() const;
protected:
OdfImage();
~OdfImage() override;
mutable mitk::Image::Pointer m_RgbImage;
};
} // namespace mitk
#endif /* __mitkOdfImage__h */
diff --git a/Modules/DiffusionCore/IODataStructures/mitkPeakImage.cpp b/Modules/DiffusionCore/IODataStructures/mitkPeakImage.cpp
index 007a520..a4d0bdd 100644
--- a/Modules/DiffusionCore/IODataStructures/mitkPeakImage.cpp
+++ b/Modules/DiffusionCore/IODataStructures/mitkPeakImage.cpp
@@ -1,221 +1,221 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPeakImage.h"
#include "mitkImageDataItem.h"
#include "mitkImageCast.h"
#include <mitkImageToItk.h>
#include <vtkPolyLine.h>
#include <vtkPointData.h>
#include <mitkImagePixelWriteAccessor.h>
#include <mitkImagePixelReadAccessor.h>
mitk::PeakImage::PeakImage() : Image()
{
m_PolyData = nullptr;
}
mitk::PeakImage::~PeakImage()
{
}
void mitk::PeakImage::ConstructPolydata()
{
MITK_INFO << "PeakImage constructing polydata";
if (this->GetDimensions()[3]%3!=0)
mitkThrow() << "Fourth dimension needs to be a multiple of 3";
typedef mitk::ImageToItk< ItkPeakImageType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(this);
caster->Update();
ItkPeakImageType::ConstPointer itkImg = caster->GetOutput();
int sz_x = static_cast<int>(this->GetDimensions()[0]);
int sz_y = static_cast<int>(this->GetDimensions()[1]);
int sz_z = static_cast<int>(this->GetDimensions()[2]);
unsigned int num_dirs = this->GetDimensions()[3]/3;
double minSpacing = 1;
ItkPeakImageType::SpacingType spacing = itkImg->GetSpacing();
if(spacing[0]<spacing[1] && spacing[0]<spacing[2])
minSpacing = spacing[0];
else if (spacing[1] < spacing[2])
minSpacing = spacing[1];
else
minSpacing = spacing[2];
vtkSmartPointer<vtkCellArray> m_VtkCellArray = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkPoints> m_VtkPoints = vtkSmartPointer<vtkPoints>::New();
#ifdef WIN32
#pragma omp parallel for
#else
#pragma omp parallel for collapse(3)
#endif
for (int x=0; x<sz_x; ++x)
for (int y=0; y<sz_y; ++y)
for (int z=0; z<sz_z; ++z)
{
itk::Index<4> idx4; idx4[0] = x; idx4[1] = y; idx4[2] = z;
for (unsigned int i=0; i<num_dirs; i++)
{
itk::ContinuousIndex<double, 4> center;
center[0] = idx4[0];
center[1] = idx4[1];
center[2] = idx4[2];
center[3] = 0;
itk::Point<double, 4> worldCenter;
itkImg->TransformContinuousIndexToPhysicalPoint( center, worldCenter );
idx4[3] = 0;
vnl_vector_fixed< float, 3 > dir;
idx4[3] = i*3;
dir[0] = itkImg->GetPixel(idx4);
idx4[3] += 1;
dir[1] = itkImg->GetPixel(idx4);
idx4[3] += 1;
dir[2] = itkImg->GetPixel(idx4);
if (dir.magnitude()<0.001f)
continue;
#pragma omp critical
{
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
// add direction to vector field (with spacing compensation)
itk::Point<double> worldStart;
worldStart[0] = worldCenter[0]-static_cast<double>(dir[0])/2*minSpacing;
worldStart[1] = worldCenter[1]-static_cast<double>(dir[1])/2*minSpacing;
worldStart[2] = worldCenter[2]-static_cast<double>(dir[2])/2*minSpacing;
vtkIdType id = m_VtkPoints->InsertNextPoint(worldStart.GetDataPointer());
container->GetPointIds()->InsertNextId(id);
itk::Point<double> worldEnd;
worldEnd[0] = worldCenter[0]+static_cast<double>(dir[0])/2*minSpacing;
worldEnd[1] = worldCenter[1]+static_cast<double>(dir[1])/2*minSpacing;
worldEnd[2] = worldCenter[2]+static_cast<double>(dir[2])/2*minSpacing;
id = m_VtkPoints->InsertNextPoint(worldEnd.GetDataPointer());
container->GetPointIds()->InsertNextId(id);
m_VtkCellArray->InsertNextCell(container);
}
}
}
m_PolyData = vtkSmartPointer<vtkPolyData>::New();
m_PolyData->SetPoints(m_VtkPoints);
m_PolyData->SetLines(m_VtkCellArray);
MITK_INFO << "PeakImage finished constructing polydata";
ColorByOrientation();
this->Modified();
}
void mitk::PeakImage::SetCustomColor(float r, float g, float b)
{
vtkPoints* extrPoints = nullptr;
extrPoints = m_PolyData->GetPoints();
int numOfPoints = 0;
if (extrPoints!=nullptr)
numOfPoints = static_cast<int>(extrPoints->GetNumberOfPoints());
int componentSize = 4;
vtkSmartPointer<vtkUnsignedCharArray> colors = vtkSmartPointer<vtkUnsignedCharArray>::New();
colors->Allocate(numOfPoints * componentSize);
colors->SetNumberOfComponents(componentSize);
colors->SetName("FIBER_COLORS");
unsigned char rgba[4] = {0,0,0,0};
for(long i=0; i<m_PolyData->GetNumberOfPoints(); ++i)
{
rgba[0] = static_cast<unsigned char>(r);
rgba[1] = static_cast<unsigned char>(g);
rgba[2] = static_cast<unsigned char>(b);
rgba[3] = 255;
colors->InsertTypedTuple(i, rgba);
}
m_PolyData->GetPointData()->AddArray(colors);
this->Modified();
}
void mitk::PeakImage::ColorByOrientation()
{
//===== FOR WRITING A TEST ========================
// colorT size == tupelComponents * tupelElements
// compare color results
// to cover this code 100% also PolyData needed, where colorarray already exists
// + one fiber with exactly 1 point
// + one fiber with 0 points
//=================================================
vtkPoints* extrPoints = nullptr;
extrPoints = m_PolyData->GetPoints();
int numOfPoints = 0;
if (extrPoints!=nullptr)
numOfPoints = static_cast<int>(extrPoints->GetNumberOfPoints());
//colors and alpha value for each single point, RGBA = 4 components
unsigned char rgba[4] = {0,0,0,0};
int componentSize = 4;
vtkSmartPointer<vtkUnsignedCharArray> colors = vtkSmartPointer<vtkUnsignedCharArray>::New();
colors->Allocate(numOfPoints * componentSize);
colors->SetNumberOfComponents(componentSize);
colors->SetName("FIBER_COLORS");
int num_peaks = static_cast<int>(m_PolyData->GetNumberOfLines());
if (num_peaks < 1)
return;
vtkCellArray* fiberList = m_PolyData->GetLines();
fiberList->InitTraversal();
for (int fi=0; fi<num_peaks; ++fi)
{
vtkIdType* idList; // contains the point id's of the line
vtkIdType num_points; // number of points for current line
fiberList->GetNextCell(num_points, idList);
if (num_points == 2)
{
vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[0])[0], extrPoints->GetPoint(idList[0])[1],extrPoints->GetPoint(idList[0])[2]);
vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[1])[0], extrPoints->GetPoint(idList[1])[1], extrPoints->GetPoint(idList[1])[2]);
vnl_vector_fixed< double, 3 > diff1;
diff1 = currentPntvtk - nextPntvtk;
diff1.normalize();
rgba[0] = static_cast<unsigned char>(255.0 * std::fabs(diff1[0]));
rgba[1] = static_cast<unsigned char>(255.0 * std::fabs(diff1[1]));
rgba[2] = static_cast<unsigned char>(255.0 * std::fabs(diff1[2]));
rgba[3] = 255;
colors->InsertTypedTuple(idList[0], rgba);
colors->InsertTypedTuple(idList[1], rgba);
}
else
{
MITK_INFO << "Peak with point number!=2 detected!" ;
continue;
}
}
m_PolyData->GetPointData()->AddArray(colors);
this->Modified();
}
diff --git a/Modules/DiffusionCore/IODataStructures/mitkPeakImage.h b/Modules/DiffusionCore/IODataStructures/mitkPeakImage.h
index a3a26ee..ccb733c 100644
--- a/Modules/DiffusionCore/IODataStructures/mitkPeakImage.h
+++ b/Modules/DiffusionCore/IODataStructures/mitkPeakImage.h
@@ -1,66 +1,66 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkPeakImage__h
#define __mitkPeakImage__h
#include "mitkImage.h"
#include <vtkPolyData.h>
#include <vtkSmartPointer.h>
#include <MitkDiffusionCoreExports.h>
namespace mitk
{
/**
* \brief this class encapsulates tensor images
*/
class MITKDIFFUSIONCORE_EXPORT PeakImage : public Image
{
public:
typedef float PixelType;
typedef itk::Image<PixelType, 4> ItkPeakImageType;
mitkClassMacro( PeakImage, Image )
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
void ConstructPolydata();
vtkSmartPointer< vtkPolyData > GetPolyData()
{
if (m_PolyData==nullptr)
this->ConstructPolydata();
return m_PolyData;
}
void SetCustomColor(float r, float g, float b);
void ColorByOrientation();
protected:
PeakImage();
~PeakImage() override;
mutable vtkSmartPointer< vtkPolyData > m_PolyData;
};
} // namespace mitk
#endif /* __mitkPeakImage__h */
diff --git a/Modules/DiffusionCore/IODataStructures/mitkPlanarFigureComposite.cpp b/Modules/DiffusionCore/IODataStructures/mitkPlanarFigureComposite.cpp
index 37c9a95..a169c9c 100644
--- a/Modules/DiffusionCore/IODataStructures/mitkPlanarFigureComposite.cpp
+++ b/Modules/DiffusionCore/IODataStructures/mitkPlanarFigureComposite.cpp
@@ -1,60 +1,60 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPlanarFigureComposite.h"
mitk::PlanarFigureComposite::PlanarFigureComposite()
{
mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New();
this->SetGeometry(geometry);
}
mitk::PlanarFigureComposite::~PlanarFigureComposite()
{
}
void mitk::PlanarFigureComposite::setOperationType(OperationType pfcOp)
{
this->m_compOperation = pfcOp;
}
mitk::PlanarFigureComposite::OperationType mitk::PlanarFigureComposite::getOperationType() const
{
return this->m_compOperation;
}
/* ESSENTIAL IMPLEMENTATION OF SUPERCLASS METHODS */
void mitk::PlanarFigureComposite::SetRequestedRegionToLargestPossibleRegion()
{
}
bool mitk::PlanarFigureComposite::RequestedRegionIsOutsideOfTheBufferedRegion()
{
return false;
}
bool mitk::PlanarFigureComposite::VerifyRequestedRegion()
{
return true;
}
void mitk::PlanarFigureComposite::SetRequestedRegion(const itk::DataObject* )
{
}
diff --git a/Modules/DiffusionCore/IODataStructures/mitkPlanarFigureComposite.h b/Modules/DiffusionCore/IODataStructures/mitkPlanarFigureComposite.h
index 96a339c..22cd9df 100644
--- a/Modules/DiffusionCore/IODataStructures/mitkPlanarFigureComposite.h
+++ b/Modules/DiffusionCore/IODataStructures/mitkPlanarFigureComposite.h
@@ -1,65 +1,65 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_PLANARFIGURECOMPOSITE_H
#define _MITK_PLANARFIGURECOMPOSITE_H
#include "mitkCommon.h"
#include "mitkBaseData.h"
#include <MitkDiffusionCoreExports.h>
#include "mitkPlanarFigure.h"
#include "itkVectorContainer.h"
#include "mitkDataNode.h"
namespace mitk {
class MITKDIFFUSIONCORE_EXPORT PlanarFigureComposite : public BaseData
{
public:
enum OperationType {
AND,
OR,
NOT
};
mitkClassMacro(PlanarFigureComposite, BaseData)
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
void SetRequestedRegionToLargestPossibleRegion() override;
bool RequestedRegionIsOutsideOfTheBufferedRegion() override;
bool VerifyRequestedRegion() override;
void SetRequestedRegion(const itk::DataObject*) override;
// set if this compsition is AND, OR, NOT
void setOperationType(OperationType);
OperationType getOperationType() const;
protected:
PlanarFigureComposite();
~PlanarFigureComposite() override;
PlanarFigureComposite(const Self& other);
private:
OperationType m_compOperation;
};
}
#endif
diff --git a/Modules/DiffusionCore/IODataStructures/mitkRegistrationObject.cpp b/Modules/DiffusionCore/IODataStructures/mitkRegistrationObject.cpp
index b1d1351..2849ec1 100644
--- a/Modules/DiffusionCore/IODataStructures/mitkRegistrationObject.cpp
+++ b/Modules/DiffusionCore/IODataStructures/mitkRegistrationObject.cpp
@@ -1,45 +1,45 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkRegistrationObject.h"
mitk::RegistrationObject::RegistrationObject()
: m_ReferenceGeometry(0),
m_Transformation(0)
{
}
void mitk::RegistrationObject::SetReferenceGeometry(mitk::Geometry3D::Pointer geom)
{
if( m_ReferenceGeometry.IsNull() )
m_ReferenceGeometry = mitk::Geometry3D::New();
m_ReferenceGeometry = geom->Clone();
}
void mitk::RegistrationObject::SetReferenceImage(mitk::Image::Pointer image)
{
this->SetReferenceGeometry( image->GetTimeGeometry()->GetGeometryForTimeStep() );
}
void mitk::RegistrationObject::SetTransformation(itk::AffineGeometryFrame::Pointer transform)
{
if( m_Transformation.IsNull() )
m_Transformation = mitk::AffineGeometryFrame3D::New();
m_Transformation = transform;
}
diff --git a/Modules/DiffusionCore/IODataStructures/mitkRegistrationObject.h b/Modules/DiffusionCore/IODataStructures/mitkRegistrationObject.h
index 6a2b0ed..680b38d 100644
--- a/Modules/DiffusionCore/IODataStructures/mitkRegistrationObject.h
+++ b/Modules/DiffusionCore/IODataStructures/mitkRegistrationObject.h
@@ -1,74 +1,74 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKREGISTRATIONOBJECT_H
#define MITKREGISTRATIONOBJECT_H
#include <MitkDiffusionCoreExports.h>
#include "mitkBaseData.h"
#include "mitkGeometry3D.h"
#include "mitkImage.h"
namespace mitk
{
/**
* @brief The RegistrationObject class stores all necessary information for image registration.
*
*
*/
class MITKDIFFUSIONCORE_EXPORT RegistrationObject : public BaseData
{
public:
mitkClassMacro( RegistrationObject, BaseData );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
void SetReferenceGeometry( mitk::Geometry3D::Pointer );
void SetReferenceImage( mitk::Image::Pointer );
void SetTransformation( mitk::AffineGeometryFrame3D::Pointer );
mitk::Geometry3D::Pointer GetReferenceGeometry() const
{
return m_ReferenceGeometry;
}
mitk::AffineGeometryFrame3D::Pointer GetTransformation() const
{
return m_Transformation;
}
protected:
RegistrationObject();
virtual ~RegistrationObject(){}
/**
* @brief Reference geometry of the fixed image used for registration computation
*/
mitk::Geometry3D::Pointer m_ReferenceGeometry;
mitk::AffineGeometryFrame3D::Pointer m_Transformation;
};
}
#endif // MITKREGISTRATIONOBJECT_H
diff --git a/Modules/DiffusionCore/IODataStructures/mitkShImage.cpp b/Modules/DiffusionCore/IODataStructures/mitkShImage.cpp
index 7519374..69af75b 100644
--- a/Modules/DiffusionCore/IODataStructures/mitkShImage.cpp
+++ b/Modules/DiffusionCore/IODataStructures/mitkShImage.cpp
@@ -1,156 +1,156 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkShImage.h"
#include "mitkImageCast.h"
#include "itkImage.h"
#include "mitkImageVtkAccessor.h"
#include <mitkProperties.h>
#include "itkShToRgbImageFilter.h"
mitk::ShImage::ShImage() : Image()
, m_ShOrder(0)
, m_NumCoefficients(0)
, m_ShConvention(SH_CONVENTION::MRTRIX)
{
m_RgbImage = nullptr;
// not needed anymore as soon as all diffusion images are identified via properties anyway
this->SetProperty("IsShImage", mitk::BoolProperty::New(true));
}
mitk::ShImage::~ShImage()
{
}
unsigned int mitk::ShImage::NumCoefficients()
{
if (m_NumCoefficients==0 || m_ShOrder==0)
{
m_NumCoefficients = static_cast<unsigned int>(this->m_ImageDescriptor->GetChannelTypeById(0).GetNumberOfComponents());
int c=3, d=2-2*static_cast<int>(m_NumCoefficients);
int D = c*c-4*d;
if (D>0)
{
int s = (-c+static_cast<int>(sqrt(D)))/2;
if (s<0)
s = (-c-static_cast<int>(sqrt(D)))/2;
m_ShOrder = static_cast<unsigned int>(s);
}
else if (D==0)
m_ShOrder = static_cast<unsigned int>(-c/2);
}
return m_NumCoefficients;
}
unsigned int mitk::ShImage::ShOrder()
{
NumCoefficients();
return m_ShOrder;
}
vtkImageData* mitk::ShImage::GetVtkImageData(int t, int n)
{
if(m_RgbImage.IsNull())
{
ShOrder();
NumCoefficients();
ConstructRgbImage();
}
return m_RgbImage->GetVtkImageData(t,n);
}
const vtkImageData*mitk::ShImage::GetVtkImageData(int t, int n) const
{
if(m_RgbImage.IsNull())
{
ConstructRgbImage();
}
return m_RgbImage->GetVtkImageData(t,n);
}
template<int nShOrder>
void mitk::ShImage::Construct() const
{
typedef itk::Image<itk::Vector<float, ( nShOrder * nShOrder + nShOrder + 2)/2 + nShOrder >,3> ImageType;
typedef itk::ShToRgbImageFilter<ImageType, nShOrder> FilterType;
typename FilterType::Pointer filter = FilterType::New();
typename ImageType::Pointer itkvol = ImageType::New();
mitk::CastToItkImage(this, itkvol);
filter->SetInput(itkvol);
filter->SetShConvention(this->m_ShConvention);
filter->Update();
itk::Image<itk::RGBAPixel<unsigned char>,3>::Pointer tmp = filter->GetOutput();
m_RgbImage = mitk::Image::New();
m_RgbImage->InitializeByItk( tmp.GetPointer() );
m_RgbImage->SetVolume( tmp->GetBufferPointer() );
}
void mitk::ShImage::ConstructRgbImage() const
{
switch (this->m_ImageDescriptor->GetChannelTypeById(0).GetNumberOfComponents())
{
case 6:
Construct<2>();
break;
case 15:
Construct<4>();
break;
case 28:
Construct<6>();
break;
case 45:
Construct<8>();
break;
case 66:
Construct<10>();
break;
case 91:
Construct<12>();
break;
default :
mitkThrow() << "SH order larger 12 not supported";
}
}
const vtkImageData* mitk::ShImage::GetNonRgbVtkImageData(int t, int n) const
{
return Superclass::GetVtkImageData(t,n);
}
vtkImageData* mitk::ShImage::GetNonRgbVtkImageData(int t, int n)
{
return Superclass::GetVtkImageData(t,n);
}
void mitk::ShImage::PrintSelf(std::ostream &os, itk::Indent indent) const
{
os << indent << "Spherical harmonics order: " << m_ShOrder << std::endl;
os << indent << "Number of coefficients: " << m_NumCoefficients << std::endl;
Superclass::PrintSelf(os, indent);
}
mitk::ShImage::SH_CONVENTION mitk::ShImage::ShImage::GetShConvention() const
{
return m_ShConvention;
}
void mitk::ShImage::ShImage::SetShConvention(SH_CONVENTION ShConvention)
{
m_ShConvention = ShConvention;
}
diff --git a/Modules/DiffusionCore/IODataStructures/mitkShImage.h b/Modules/DiffusionCore/IODataStructures/mitkShImage.h
index 5fe3104..6766c6b 100644
--- a/Modules/DiffusionCore/IODataStructures/mitkShImage.h
+++ b/Modules/DiffusionCore/IODataStructures/mitkShImage.h
@@ -1,80 +1,80 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkShImage__h
#define __mitkShImage__h
#include "mitkImage.h"
#include "itkVectorImage.h"
#include "mitkImageVtkAccessor.h"
#include <MitkDiffusionCoreExports.h>
namespace mitk
{
/**
* \brief this class encapsulates spherical harmonics coefficients
*/
class MITKDIFFUSIONCORE_EXPORT ShImage : public Image
{
public:
enum SH_CONVENTION { ///< SH coefficient convention (depends on toolkit)
FSL, // used in FSL, Dipy
MRTRIX // used in MRtrix, MITK
};
typedef itk::Image<float,4 > ShOnDiskType; // we store the sh images in MRtrix 4D float format and convert on load to 3D multi-component images
mitkClassMacro( ShImage, Image )
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
virtual const vtkImageData* GetNonRgbVtkImageData(int t = 0, int n = 0) const;
virtual vtkImageData* GetNonRgbVtkImageData(int t = 0, int n = 0);
const vtkImageData* GetVtkImageData(int t = 0, int n = 0) const override;
vtkImageData* GetVtkImageData(int t = 0, int n = 0) override;
virtual void ConstructRgbImage() const;
unsigned int ShOrder();
unsigned int NumCoefficients();
SH_CONVENTION GetShConvention() const;
void SetShConvention(SH_CONVENTION ShConvention);
protected:
ShImage();
~ShImage() override;
template<int num_components>
void Construct() const;
void PrintSelf(std::ostream &os, itk::Indent indent) const override;
mutable mitk::Image::Pointer m_RgbImage;
unsigned int m_ShOrder;
unsigned int m_NumCoefficients;
SH_CONVENTION m_ShConvention; // use mrtrix style SH convention
};
} // namespace mitk
#endif /* __mitkShImage__h */
diff --git a/Modules/DiffusionCore/IODataStructures/mitkTensorImage.cpp b/Modules/DiffusionCore/IODataStructures/mitkTensorImage.cpp
index 999e98d..41890d3 100644
--- a/Modules/DiffusionCore/IODataStructures/mitkTensorImage.cpp
+++ b/Modules/DiffusionCore/IODataStructures/mitkTensorImage.cpp
@@ -1,77 +1,77 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkTensorImage.h"
#include "mitkImageDataItem.h"
#include "mitkImageCast.h"
#include "itkDiffusionTensor3D.h"
#include "itkTensorToRgbImageFilter.h"
#include "vtkImageData.h"
// #ifdef _OPENMP
// #include "omp.h"
// #endif
mitk::TensorImage::TensorImage() : Image()
{
m_RgbImage = nullptr;
}
mitk::TensorImage::~TensorImage()
{
}
vtkImageData* mitk::TensorImage::GetVtkImageData(int t, int n)
{
if(m_RgbImage.IsNull())
{
ConstructRgbImage();
}
return m_RgbImage->GetVtkImageData(t,n);
}
const vtkImageData*mitk::TensorImage::GetVtkImageData(int t, int n) const
{
if(m_RgbImage.IsNull())
{
ConstructRgbImage();
}
return m_RgbImage->GetVtkImageData(t,n);
}
void mitk::TensorImage::ConstructRgbImage() const
{
typedef itk::TensorToRgbImageFilter<ItkTensorImageType> FilterType;
FilterType::Pointer filter = FilterType::New();
ItkTensorImageType::Pointer itkvol = ItkTensorImageType::New();
mitk::CastToItkImage(this, itkvol);
filter->SetInput(itkvol);
filter->Update();
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk( filter->GetOutput() );
image->SetVolume( filter->GetOutput()->GetBufferPointer() );
m_RgbImage = image;
}
vtkImageData* mitk::TensorImage::GetNonRgbVtkImageData(int t, int n)
{
return Superclass::GetVtkImageData(t,n);
}
diff --git a/Modules/DiffusionCore/IODataStructures/mitkTensorImage.h b/Modules/DiffusionCore/IODataStructures/mitkTensorImage.h
index 945dbc8..dd70925 100644
--- a/Modules/DiffusionCore/IODataStructures/mitkTensorImage.h
+++ b/Modules/DiffusionCore/IODataStructures/mitkTensorImage.h
@@ -1,65 +1,65 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkTensorImage__h
#define __mitkTensorImage__h
#include "mitkImage.h"
#include "itkVectorImage.h"
#include <MitkDiffusionCoreExports.h>
#define TENSOR_NUM_ELEMENTS 6
namespace mitk
{
/**
* \brief this class encapsulates tensor images
*/
class MITKDIFFUSIONCORE_EXPORT TensorImage : public Image
{
public:
typedef float ScalarPixelType;
typedef itk::DiffusionTensor3D<ScalarPixelType> PixelType;
typedef itk::Image<PixelType,3> ItkTensorImageType;
mitkClassMacro( TensorImage, Image )
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
virtual vtkImageData* GetNonRgbVtkImageData(int t = 0, int n = 0);
vtkImageData* GetVtkImageData(int t = 0, int n = 0) override;
const vtkImageData* GetVtkImageData(int t = 0, int n = 0) const override;
virtual void ConstructRgbImage() const;
protected:
TensorImage();
~TensorImage() override;
mutable mitk::Image::Pointer m_RgbImage;
};
} // namespace mitk
#endif /* __mitkTensorImage__h */
diff --git a/Modules/DiffusionCore/IODataStructures/mitkTrackvis.h b/Modules/DiffusionCore/IODataStructures/mitkTrackvis.h
index 896154d..ceaf409 100644
--- a/Modules/DiffusionCore/IODataStructures/mitkTrackvis.h
+++ b/Modules/DiffusionCore/IODataStructures/mitkTrackvis.h
@@ -1,53 +1,53 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _TRACKVIS
#define _TRACKVIS
#include <mitkCommon.h>
#include <mitkFiberBundle.h>
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkCellArray.h>
#include <vtkPoints.h>
#include <vtkPolyLine.h>
#include <itkSize.h>
// Class to handle TrackVis files.
// -------------------------------
class MITKDIFFUSIONCORE_EXPORT TrackVisFiberReader
{
private:
std::string m_Filename;
FILE* m_FilePointer;
mitk::FiberBundle::TrackVis_header m_Header;
public:
short create(std::string m_Filename, mitk::FiberBundle *fib, bool print_header);
short open(std::string m_Filename );
short read(mitk::FiberBundle* fib , bool use_matrix, bool print_header);
short write(const mitk::FiberBundle* fib );
void writeHdr();
void updateTotal( int totFibers );
void close();
bool IsTransformValid();
void print_header();
TrackVisFiberReader();
~TrackVisFiberReader();
};
#endif
diff --git a/Modules/DiffusionCore/IODataStructures/mitkTractographyForest.cpp b/Modules/DiffusionCore/IODataStructures/mitkTractographyForest.cpp
index e26a43d..3c7aa4a 100644
--- a/Modules/DiffusionCore/IODataStructures/mitkTractographyForest.cpp
+++ b/Modules/DiffusionCore/IODataStructures/mitkTractographyForest.cpp
@@ -1,117 +1,117 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
#define _USE_MATH_DEFINES
#include "mitkTractographyForest.h"
#include <mitkExceptionMacro.h>
#include <mitkGeometry3D.h>
namespace mitk
{
TractographyForest::TractographyForest( std::shared_ptr< vigra::RandomForest<int> > forest )
{
m_Forest = forest;
mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New();
SetGeometry(geometry);
}
TractographyForest::~TractographyForest()
{
}
void TractographyForest::PredictProbabilities(vigra::MultiArray<2, float>& features, vigra::MultiArray<2, float>& probabilities) const
{
m_Forest->predictProbabilities(features, probabilities);
}
int TractographyForest::GetNumFeatures() const
{
if (!HasForest())
mitkThrow() << "Forest is NULL";
return m_Forest->feature_count();
}
int TractographyForest::GetNumTrees() const
{
if (!HasForest())
mitkThrow() << "Forest is NULL";
return m_Forest->tree_count();
}
int TractographyForest::GetNumClasses() const
{
if (!HasForest())
mitkThrow() << "Forest is NULL";
return m_Forest->class_count();
}
int TractographyForest::GetMaxTreeDepth() const
{
if (!HasForest())
mitkThrow() << "Forest is NULL";
return m_Forest->ext_param_.max_tree_depth;
}
int TractographyForest::IndexToClassLabel(int idx) const
{
if (!HasForest())
mitkThrow() << "Forest is NULL";
unsigned int classLabel = 0;
m_Forest->ext_param_.to_classlabel(idx, classLabel);
return classLabel;
}
bool TractographyForest::HasForest() const
{
return m_Forest!=nullptr;
}
void TractographyForest::PrintSelf(std::ostream &os, itk::Indent indent) const
{
// Superclass::PrintSelf(os, indent);
os << indent << this->GetNameOfClass() << ":\n";
os << indent << "Number of features: " << GetNumFeatures() << std::endl;
os << indent << "Number of classes: " << GetNumClasses() << std::endl;
os << indent << "Number of trees: " << GetNumTrees() << std::endl;
os << indent << "Maximum tree depth: " << GetMaxTreeDepth() << std::endl;
}
/* ESSENTIAL IMPLEMENTATION OF SUPERCLASS METHODS */
void TractographyForest::UpdateOutputInformation()
{
}
void TractographyForest::SetRequestedRegionToLargestPossibleRegion()
{
}
bool TractographyForest::RequestedRegionIsOutsideOfTheBufferedRegion()
{
return false;
}
bool TractographyForest::VerifyRequestedRegion()
{
return true;
}
void TractographyForest::SetRequestedRegion(const itk::DataObject* )
{
}
}
diff --git a/Modules/DiffusionCore/IODataStructures/mitkTractographyForest.h b/Modules/DiffusionCore/IODataStructures/mitkTractographyForest.h
index 2108664..07c61b7 100644
--- a/Modules/DiffusionCore/IODataStructures/mitkTractographyForest.h
+++ b/Modules/DiffusionCore/IODataStructures/mitkTractographyForest.h
@@ -1,72 +1,72 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_TractographyForest_H
#define _MITK_TractographyForest_H
#include <mitkBaseData.h>
#include <MitkDiffusionCoreExports.h>
#undef DIFFERENCE
#define VIGRA_STATIC_LIB
#include <vigra/random_forest.hxx>
namespace mitk {
/**
* \brief Class containing random forest datastructures used for fiber tractography; */
class MITKDIFFUSIONCORE_EXPORT TractographyForest : public BaseData
{
public:
void UpdateOutputInformation() override;
void SetRequestedRegionToLargestPossibleRegion() override;
bool RequestedRegionIsOutsideOfTheBufferedRegion() override;
bool VerifyRequestedRegion() override;
void SetRequestedRegion(const itk::DataObject*) override;
mitkClassMacro( TractographyForest, BaseData )
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitkNewMacro1Param(Self, std::shared_ptr< vigra::RandomForest<int> >) // custom constructor
int GetNumFeatures() const;
int GetNumTrees() const;
int GetNumClasses() const;
int GetMaxTreeDepth() const;
int IndexToClassLabel(int idx) const;
bool HasForest() const;
void PredictProbabilities(vigra::MultiArray<2, float>& features, vigra::MultiArray<2, float>& probabilities) const;
std::shared_ptr< const vigra::RandomForest<int> > GetForest() const
{ return m_Forest; }
protected:
TractographyForest( std::shared_ptr< vigra::RandomForest<int> > forest = nullptr );
~TractographyForest() override;
void PrintSelf(std::ostream &os, itk::Indent indent) const override;
private:
std::shared_ptr< vigra::RandomForest<int> > m_Forest; ///< random forest classifier
};
} // namespace mitk
#endif /* _MITK_TractographyForest_H */
diff --git a/Modules/DiffusionCore/Rendering/mitkCompositeMapper.cpp b/Modules/DiffusionCore/Rendering/mitkCompositeMapper.cpp
index 1745e71..de0f46b 100644
--- a/Modules/DiffusionCore/Rendering/mitkCompositeMapper.cpp
+++ b/Modules/DiffusionCore/Rendering/mitkCompositeMapper.cpp
@@ -1,30 +1,30 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkCompositeMapper.h"
mitk::CompositeMapper::CompositeMapper()
{
m_OdfMapper = mitk::OdfVtkMapper2D<float,ODF_SAMPLING_SIZE>::New();
m_ImgMapper = mitk::CopyImageMapper2D::New();
}
mitk::CompositeMapper::~CompositeMapper()
{
}
diff --git a/Modules/DiffusionCore/Rendering/mitkCompositeMapper.h b/Modules/DiffusionCore/Rendering/mitkCompositeMapper.h
index 8dbecc5..8045295 100644
--- a/Modules/DiffusionCore/Rendering/mitkCompositeMapper.h
+++ b/Modules/DiffusionCore/Rendering/mitkCompositeMapper.h
@@ -1,163 +1,163 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 COMPOSITEMAPPER_H_HEADER_INCLUDED
#define COMPOSITEMAPPER_H_HEADER_INCLUDED
#include "mitkGLMapper.h"
#include "mitkVtkMapper.h"
#include "mitkOdfImage.h"
#include "mitkImageVtkMapper2D.h"
#include "mitkOdfVtkMapper2D.h"
#include "mitkLevelWindowProperty.h"
#include <MitkDiffusionCoreExports.h>
namespace mitk {
class CopyImageMapper2D : public ImageVtkMapper2D
{
public:
mitkClassMacro(CopyImageMapper2D,ImageVtkMapper2D);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
friend class CompositeMapper;
};
//##Documentation
//## @brief Composite pattern for combination of different mappers
//## @ingroup Mapper
class MITKDIFFUSIONCORE_EXPORT CompositeMapper : public VtkMapper
{
public:
mitkClassMacro(CompositeMapper,VtkMapper);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
void MitkRenderOverlay(BaseRenderer* renderer) override
{
m_ImgMapper->MitkRenderOverlay(renderer);
m_OdfMapper->MitkRenderOverlay(renderer);
}
void MitkRenderOpaqueGeometry(BaseRenderer* renderer) override
{
m_ImgMapper->MitkRenderOpaqueGeometry(renderer);
m_OdfMapper->MitkRenderOpaqueGeometry(renderer);
if( mitk::RenderingManager::GetInstance()->GetNextLOD( renderer ) == 0 )
{
renderer->Modified();
}
}
void MitkRenderTranslucentGeometry(BaseRenderer* renderer) override
{
m_ImgMapper->MitkRenderTranslucentGeometry(renderer);
m_OdfMapper->MitkRenderTranslucentGeometry(renderer);
}
void MitkRenderVolumetricGeometry(BaseRenderer* renderer) override
{
m_ImgMapper->MitkRenderVolumetricGeometry(renderer);
m_OdfMapper->MitkRenderVolumetricGeometry(renderer);
}
void SetDataNode(DataNode* node) override
{
m_DataNode = node;
m_ImgMapper->SetDataNode(node);
m_OdfMapper->SetDataNode(node);
}
mitk::ImageVtkMapper2D::Pointer GetImageMapper()
{
ImageVtkMapper2D* retval = m_ImgMapper;
return retval;
}
bool HasVtkProp( const vtkProp* prop, BaseRenderer* renderer ) override
{
return m_OdfMapper->HasVtkProp(prop, renderer);
}
void ReleaseGraphicsResources(mitk::BaseRenderer* renderer) override
{
m_ImgMapper->ReleaseGraphicsResources(renderer);
m_OdfMapper->ReleaseGraphicsResources(renderer);
}
static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = nullptr, bool overwrite = false )
{
mitk::OdfVtkMapper2D<float,ODF_SAMPLING_SIZE>::SetDefaultProperties(node, renderer, overwrite);
mitk::CopyImageMapper2D::SetDefaultProperties(node, renderer, overwrite);
mitk::LevelWindow opaclevwin;
opaclevwin.SetRangeMinMax(0,255);
opaclevwin.SetWindowBounds(0,0);
mitk::LevelWindowProperty::Pointer prop = mitk::LevelWindowProperty::New(opaclevwin);
node->AddProperty( "opaclevelwindow", prop );
}
bool IsLODEnabled( BaseRenderer * renderer ) const override
{
return m_ImgMapper->IsLODEnabled(renderer) || m_OdfMapper->IsLODEnabled(renderer);
}
vtkProp* GetVtkProp(mitk::BaseRenderer* renderer) override
{
m_PropAssembly = vtkSmartPointer<vtkPropAssembly>::New();
m_PropAssembly->AddPart( m_OdfMapper->GetVtkProp(renderer));
m_PropAssembly->AddPart( m_ImgMapper->GetVtkProp(renderer));
return m_PropAssembly;
}
protected:
void Update(mitk::BaseRenderer* renderer) override
{
m_OdfMapper->Update(renderer);
GenerateDataForRenderer(renderer);
}
void GenerateDataForRenderer(mitk::BaseRenderer* renderer) override
{
m_ImgMapper->GenerateDataForRenderer(renderer);
// if( mitk::RenderingManager::GetInstance()->GetNextLOD( renderer ) > 0 )
// {
// m_OdfMapper->GenerateDataForRenderer(renderer);
// }
}
CompositeMapper();
~CompositeMapper() override;
private:
mitk::OdfVtkMapper2D<float,ODF_SAMPLING_SIZE>::Pointer m_OdfMapper;
mitk::CopyImageMapper2D::Pointer m_ImgMapper;
vtkSmartPointer<vtkPropAssembly> m_PropAssembly;
};
} // namespace mitk
#endif /* COMPOSITEMAPPER_H_HEADER_INCLUDED */
diff --git a/Modules/DiffusionCore/Rendering/mitkFiberBundleMapper2D.cpp b/Modules/DiffusionCore/Rendering/mitkFiberBundleMapper2D.cpp
index ea05932..bf11bf2 100644
--- a/Modules/DiffusionCore/Rendering/mitkFiberBundleMapper2D.cpp
+++ b/Modules/DiffusionCore/Rendering/mitkFiberBundleMapper2D.cpp
@@ -1,280 +1,280 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkFiberBundleMapper2D.h"
#include "mitkBaseRenderer.h"
#include "mitkDataNode.h"
#include <vtkActor.h>
#include <vtkOpenGLPolyDataMapper.h>
#include <vtkOpenGLHelper.h>
#include <vtkShaderProgram.h>
#include <vtkPlane.h>
#include <vtkPolyData.h>
#include <vtkPointData.h>
#include <vtkProperty.h>
#include <vtkLookupTable.h>
#include <vtkPoints.h>
#include <vtkCamera.h>
#include <vtkPolyLine.h>
#include <vtkRenderer.h>
#include <vtkCellArray.h>
#include <vtkMatrix4x4.h>
#include <vtkTubeFilter.h>
#include <mitkPlaneGeometry.h>
#include <mitkSliceNavigationController.h>
#include <mitkCoreServices.h>
class vtkShaderCallback : public vtkCommand
{
public:
static vtkShaderCallback *New()
{
return new vtkShaderCallback;
}
mitk::BaseRenderer *renderer;
mitk::DataNode *node;
void Execute(vtkObject *, unsigned long, void*cbo) override
{
vtkShaderProgram *program = reinterpret_cast<vtkShaderProgram*>(cbo);
float fiberOpacity;
bool fiberFading = false;
float fiberThickness = 0.0;
node->GetOpacity(fiberOpacity, nullptr);
node->GetFloatProperty("Fiber2DSliceThickness", fiberThickness);
node->GetBoolProperty("Fiber2DfadeEFX", fiberFading);
program->SetUniformf("fiberOpacity", fiberOpacity);
program->SetUniformi("fiberFadingON", fiberFading);
program->SetUniformf("fiberThickness", fiberThickness);
if (this->renderer)
{
//get information about current position of views
mitk::SliceNavigationController::Pointer sliceContr = renderer->GetSliceNavigationController();
mitk::PlaneGeometry::ConstPointer planeGeo = sliceContr->GetCurrentPlaneGeometry();
//generate according cutting planes based on the view position
float planeNormal[3];
planeNormal[0] = planeGeo->GetNormal()[0];
planeNormal[1] = planeGeo->GetNormal()[1];
planeNormal[2] = planeGeo->GetNormal()[2];
float tmp1 = planeGeo->GetOrigin()[0] * planeNormal[0];
float tmp2 = planeGeo->GetOrigin()[1] * planeNormal[1];
float tmp3 = planeGeo->GetOrigin()[2] * planeNormal[2];
float thickness = tmp1 + tmp2 + tmp3; //attention, correct normalvector
float a[4];
for (int i = 0; i < 3; ++i)
a[i] = planeNormal[i];
a[3] = thickness;
program->SetUniform4f("slicingPlane", a);
}
}
vtkShaderCallback() { this->renderer = nullptr; }
};
mitk::FiberBundleMapper2D::FiberBundleMapper2D()
: m_LineWidth(1)
{
m_lut = vtkSmartPointer<vtkLookupTable>::New();
m_lut->Build();
}
mitk::FiberBundleMapper2D::~FiberBundleMapper2D()
{
}
mitk::FiberBundle* mitk::FiberBundleMapper2D::GetInput()
{
return dynamic_cast< mitk::FiberBundle * > ( GetDataNode()->GetData() );
}
void mitk::FiberBundleMapper2D::Update(mitk::BaseRenderer * renderer)
{
bool visible = true;
GetDataNode()->GetVisibility(visible, renderer, "visible");
if ( !visible )
return;
// Calculate time step of the input data for the specified renderer (integer value)
// this method is implemented in mitkMapper
this->CalculateTimeStep( renderer );
//check if updates occured in the node or on the display
FBXLocalStorage *localStorage = m_LocalStorageHandler.GetLocalStorage(renderer);
//set renderer independent shader properties
const DataNode::Pointer node = this->GetDataNode();
float thickness = 2.0;
if(!this->GetDataNode()->GetPropertyValue("Fiber2DSliceThickness",thickness))
MITK_INFO << "FIBER2D SLICE THICKNESS PROPERTY ERROR";
bool fiberfading = false;
if(!this->GetDataNode()->GetPropertyValue("Fiber2DfadeEFX",fiberfading))
MITK_INFO << "FIBER2D SLICE FADE EFX PROPERTY ERROR";
mitk::FiberBundle* fiberBundle = this->GetInput();
if (fiberBundle==nullptr)
return;
int lineWidth = 1.0;
node->GetIntProperty("LineWidth", lineWidth);
if (m_LineWidth!=lineWidth)
{
m_LineWidth = lineWidth;
fiberBundle->RequestUpdate2D();
}
vtkProperty *property = localStorage->m_Actor->GetProperty();
property->SetLighting(false);
if ( localStorage->m_LastUpdateTime<renderer->GetCurrentWorldPlaneGeometryUpdateTime() || localStorage->m_LastUpdateTime<fiberBundle->GetUpdateTime2D() )
{
this->UpdateShaderParameter(renderer);
this->GenerateDataForRenderer( renderer );
}
}
void mitk::FiberBundleMapper2D::UpdateShaderParameter(mitk::BaseRenderer *)
{
// see new vtkShaderCallback
}
// vtkActors and Mappers are feeded here
void mitk::FiberBundleMapper2D::GenerateDataForRenderer(mitk::BaseRenderer *renderer)
{
mitk::FiberBundle* fiberBundle = this->GetInput();
//the handler of local storage gets feeded in this method with requested data for related renderwindow
FBXLocalStorage *localStorage = m_LocalStorageHandler.GetLocalStorage(renderer);
mitk::DataNode* node = this->GetDataNode();
if (node == nullptr)
return;
vtkSmartPointer<vtkPolyData> fiberPolyData = fiberBundle->GetFiberPolyData();
if (fiberPolyData == nullptr)
return;
fiberPolyData->GetPointData()->AddArray(fiberBundle->GetFiberColors());
localStorage->m_Mapper->ScalarVisibilityOn();
localStorage->m_Mapper->SetScalarModeToUsePointFieldData();
localStorage->m_Mapper->SetLookupTable(m_lut); //apply the properties after the slice was set
localStorage->m_Actor->GetProperty()->SetOpacity(0.999);
localStorage->m_Mapper->SelectColorArray("FIBER_COLORS");
localStorage->m_Mapper->SetInputData(fiberPolyData);
localStorage->m_Mapper->SetVertexShaderCode(
"//VTK::System::Dec\n"
"attribute vec4 vertexMC;\n"
"//VTK::Normal::Dec\n"
"uniform mat4 MCDCMatrix;\n"
"//VTK::Color::Dec\n"
"varying vec4 positionWorld;\n"
"varying vec4 colorVertex;\n"
"void main(void)\n"
"{\n"
" colorVertex = scalarColor;\n"
" positionWorld = vertexMC;\n"
" gl_Position = MCDCMatrix * vertexMC;\n"
"}\n"
);
localStorage->m_Mapper->SetFragmentShaderCode(
"//VTK::System::Dec\n" // always start with this line
"//VTK::Output::Dec\n" // always have this line in your FS
"uniform vec4 slicingPlane;\n"
"uniform float fiberThickness;\n"
"uniform int fiberFadingON;\n"
"uniform float fiberOpacity;\n"
"varying vec4 positionWorld;\n"
"varying vec4 colorVertex;\n"
"out vec4 out_Color;\n"
"void main(void)\n"
"{\n"
" float r1 = dot(positionWorld.xyz, slicingPlane.xyz) - slicingPlane.w;\n"
" if (abs(r1) >= fiberThickness)\n"
" discard;\n"
" if (fiberFadingON != 0)\n"
" {\n"
" float x = (r1 + fiberThickness) / (fiberThickness*2.0);\n"
" x = 1.0 - x;\n"
" out_Color = vec4(colorVertex.xyz*x, fiberOpacity);\n"
" }\n"
" else{\n"
" out_Color = vec4(colorVertex.xyz, fiberOpacity);\n"
" }\n"
"}\n"
);
vtkSmartPointer<vtkShaderCallback> myCallback = vtkSmartPointer<vtkShaderCallback>::New();
myCallback->renderer = renderer;
myCallback->node = this->GetDataNode();
localStorage->m_Mapper->AddObserver(vtkCommand::UpdateShaderEvent,myCallback);
localStorage->m_Actor->SetMapper(localStorage->m_Mapper);
localStorage->m_Actor->GetProperty()->SetLineWidth(m_LineWidth);
// We have been modified => save this for next Update()
localStorage->m_LastUpdateTime.Modified();
}
vtkProp* mitk::FiberBundleMapper2D::GetVtkProp(mitk::BaseRenderer *renderer)
{
this->Update(renderer);
return m_LocalStorageHandler.GetLocalStorage(renderer)->m_Actor;
}
void mitk::FiberBundleMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite)
{
Superclass::SetDefaultProperties(node, renderer, overwrite);
// node->SetProperty("shader",mitk::ShaderProperty::New("mitkShaderFiberClipping"));
//add other parameters to propertylist
node->AddProperty( "Fiber2DSliceThickness", mitk::FloatProperty::New(1.0f), renderer, overwrite );
node->AddProperty( "Fiber2DfadeEFX", mitk::BoolProperty::New(true), renderer, overwrite );
node->AddProperty( "color", mitk::ColorProperty::New(1.0,1.0,1.0), renderer, overwrite);
}
mitk::FiberBundleMapper2D::FBXLocalStorage::FBXLocalStorage()
{
m_Actor = vtkSmartPointer<vtkActor>::New();
m_Mapper = vtkSmartPointer<MITKFIBERBUNDLEMAPPER2D_POLYDATAMAPPER>::New();
}
diff --git a/Modules/DiffusionCore/Rendering/mitkFiberBundleMapper2D.h b/Modules/DiffusionCore/Rendering/mitkFiberBundleMapper2D.h
index 2159cff..55b5b28 100644
--- a/Modules/DiffusionCore/Rendering/mitkFiberBundleMapper2D.h
+++ b/Modules/DiffusionCore/Rendering/mitkFiberBundleMapper2D.h
@@ -1,87 +1,87 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 FiberBundleMAPPER2D_H_HEADER_INCLUDED
#define FiberBundleMAPPER2D_H_HEADER_INCLUDED
#include <mitkCommon.h>
#include <mitkBaseRenderer.h>
#include <mitkVtkMapper.h>
#include <mitkFiberBundle.h>
#include <vtkSmartPointer.h>
#include <MitkDiffusionCoreExports.h>
#define MITKFIBERBUNDLEMAPPER2D_POLYDATAMAPPER vtkOpenGLPolyDataMapper
class vtkActor;
class mitkBaseRenderer;
class MITKFIBERBUNDLEMAPPER2D_POLYDATAMAPPER;
class vtkCutter;
class vtkPlane;
class vtkPolyData;
namespace mitk {
struct IShaderRepository;
class MITKDIFFUSIONCORE_EXPORT FiberBundleMapper2D : public VtkMapper
{
public:
mitkClassMacro(FiberBundleMapper2D, VtkMapper);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitk::FiberBundle* GetInput();
void Update(mitk::BaseRenderer * renderer) override;
static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = nullptr, bool overwrite = false );
vtkProp* GetVtkProp(mitk::BaseRenderer* renderer) override;
class FBXLocalStorage : public mitk::Mapper::BaseLocalStorage
{
public:
vtkSmartPointer<vtkActor> m_Actor;
vtkSmartPointer<MITKFIBERBUNDLEMAPPER2D_POLYDATAMAPPER> m_Mapper;
itk::TimeStamp m_LastUpdateTime;
FBXLocalStorage();
~FBXLocalStorage() override
{
}
};
/** \brief This member holds all three LocalStorages for the three 2D render windows. */
mitk::LocalStorageHandler<FBXLocalStorage> m_LocalStorageHandler;
protected:
FiberBundleMapper2D();
~FiberBundleMapper2D() override;
/** Does the actual resampling, without rendering. */
void GenerateDataForRenderer(mitk::BaseRenderer*) override;
void UpdateShaderParameter(mitk::BaseRenderer*);
private:
vtkSmartPointer<vtkLookupTable> m_lut;
int m_LineWidth;
};
}//end namespace
#endif
diff --git a/Modules/DiffusionCore/Rendering/mitkFiberBundleMapper3D.cpp b/Modules/DiffusionCore/Rendering/mitkFiberBundleMapper3D.cpp
index 25547ba..e8cbb3b 100644
--- a/Modules/DiffusionCore/Rendering/mitkFiberBundleMapper3D.cpp
+++ b/Modules/DiffusionCore/Rendering/mitkFiberBundleMapper3D.cpp
@@ -1,259 +1,259 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkFiberBundleMapper3D.h"
#include <mitkProperties.h>
#include <vtkPropAssembly.h>
#include <vtkPointData.h>
#include <vtkProperty.h>
#include <vtkCellArray.h>
#include <vtkDepthSortPolyData.h>
#include <vtkCamera.h>
#include <vtkTubeFilter.h>
#include <vtkRibbonFilter.h>
#include <vtkLookupTable.h>
#include <vtkOpenGLHelper.h>
#include <vtkShaderProgram.h>
#include <mitkVectorProperty.h>
#include <vtkPlane.h>
#include <mitkClippingProperty.h>
mitk::FiberBundleMapper3D::FiberBundleMapper3D()
: m_TubeRadius(0.0)
, m_TubeSides(15)
, m_LineWidth(1)
{
m_lut = vtkSmartPointer<vtkLookupTable>::New();
m_lut->Build();
}
mitk::FiberBundleMapper3D::~FiberBundleMapper3D()
{
}
const mitk::FiberBundle* mitk::FiberBundleMapper3D::GetInput()
{
return static_cast<const mitk::FiberBundle * > ( GetDataNode()->GetData() );
}
/*
This method is called once the mapper gets new input,
for UI rotation or changes in colorcoding this method is NOT called
*/
void mitk::FiberBundleMapper3D::InternalGenerateData(mitk::BaseRenderer *renderer)
{
m_FiberPolyData->GetPointData()->AddArray(m_FiberBundle->GetFiberColors());
LocalStorage3D *localStorage = m_LocalStorageHandler.GetLocalStorage(renderer);
if (m_TubeRadius>0.0f)
{
vtkSmartPointer<vtkTubeFilter> tubeFilter = vtkSmartPointer<vtkTubeFilter>::New();
tubeFilter->SetInputData(m_FiberPolyData);
tubeFilter->SetNumberOfSides(m_TubeSides);
tubeFilter->SetRadius(m_TubeRadius);
tubeFilter->Update();
m_FiberPolyData = tubeFilter->GetOutput();
}
else if (m_RibbonWidth>0.0f)
{
vtkSmartPointer<vtkRibbonFilter> tubeFilter = vtkSmartPointer<vtkRibbonFilter>::New();
tubeFilter->SetInputData(m_FiberPolyData);
tubeFilter->SetWidth(m_RibbonWidth);
tubeFilter->Update();
m_FiberPolyData = tubeFilter->GetOutput();
}
// if (tmpopa<1)
// {
// vtkSmartPointer<vtkDepthSortPolyData> depthSort = vtkSmartPointer<vtkDepthSortPolyData>::New();
// depthSort->SetInputData( m_FiberPolyData );
// depthSort->SetCamera( renderer->GetVtkRenderer()->GetActiveCamera() );
// depthSort->SetDirectionToBackToFront();
// depthSort->Update();
// localStorage->m_FiberMapper->SetInputConnection(depthSort->GetOutputPort());
// }
// else
// {
localStorage->m_FiberMapper->SetInputData(m_FiberPolyData);
// }
localStorage->m_FiberMapper->SelectColorArray("FIBER_COLORS");
localStorage->m_FiberMapper->ScalarVisibilityOn();
localStorage->m_FiberMapper->SetScalarModeToUsePointFieldData();
localStorage->m_FiberActor->SetMapper(localStorage->m_FiberMapper);
localStorage->m_FiberMapper->SetLookupTable(m_lut);
localStorage->m_FiberActor->GetProperty()->SetLineWidth(m_LineWidth);
localStorage->m_FiberAssembly->AddPart(localStorage->m_FiberActor);
DataNode* node = this->GetDataNode();
mitk::ClippingProperty* prop = dynamic_cast<mitk::ClippingProperty*>(node->GetProperty("3DClipping"));
if (prop==nullptr)
{
SetDefaultProperties(node, nullptr, false);
prop = dynamic_cast<mitk::ClippingProperty*>(node->GetProperty("3DClipping"));
}
mitk::Vector3D plane_normal = prop->GetNormal();
mitk::Point3D plane_origin = prop->GetOrigin();
bool flip;
node->GetBoolProperty("3DClippingPlaneFlip",flip);
if (flip)
plane_normal *= -1;
vtkSmartPointer<vtkPlane> plane = vtkSmartPointer<vtkPlane>::New();
double vp[3], vnormal[3];
vp[0] = plane_origin[0]; vp[1] = plane_origin[1]; vp[2] = plane_origin[2];
vnormal[0] = plane_normal[0]; vnormal[1] = plane_normal[1]; vnormal[2] = plane_normal[2];
plane->SetOrigin(vp);
plane->SetNormal(vnormal);
localStorage->m_FiberMapper->RemoveAllClippingPlanes();
if (plane_normal.GetNorm() > 0.0)
localStorage->m_FiberMapper->AddClippingPlane(plane);
localStorage->m_LastUpdateTime.Modified();
}
void mitk::FiberBundleMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer )
{
bool visible = true;
GetDataNode()->GetVisibility(visible, renderer, "visible");
if ( !visible )
return;
const DataNode* node = this->GetDataNode();
LocalStorage3D* localStorage = m_LocalStorageHandler.GetLocalStorage(renderer);
m_FiberBundle = dynamic_cast<mitk::FiberBundle*>(node->GetData());
m_FiberPolyData = m_FiberBundle->GetFiberPolyData();
// did any rendering properties change?
float tubeRadius = 0;
node->GetFloatProperty("shape.tuberadius", tubeRadius);
if (m_TubeRadius!=tubeRadius)
{
m_TubeRadius = tubeRadius;
m_FiberBundle->RequestUpdate3D();
}
int tubeSides = 0;
node->GetIntProperty("shape.tubesides", tubeSides);
if (m_TubeSides!=tubeSides)
{
m_TubeSides = tubeSides;
m_FiberBundle->RequestUpdate3D();
}
int lineWidth = 0;
node->GetIntProperty("shape.linewidth", lineWidth);
if (m_LineWidth!=lineWidth)
{
m_LineWidth = lineWidth;
m_FiberBundle->RequestUpdate3D();
}
float ribbonWidth = 0;
node->GetFloatProperty("shape.ribbonwidth", ribbonWidth);
if (m_RibbonWidth!=ribbonWidth)
{
m_RibbonWidth = ribbonWidth;
m_FiberBundle->RequestUpdate3D();
}
float opacity;
this->GetDataNode()->GetOpacity(opacity, nullptr);
vtkProperty *property = localStorage->m_FiberActor->GetProperty();
float v = 1;
node->GetFloatProperty("light.ambient", v);
property->SetAmbient(v);
node->GetFloatProperty("light.diffuse", v);
property->SetDiffuse(v);
node->GetFloatProperty("light.specular", v);
property->SetSpecular(v);
node->GetFloatProperty("light.specularpower", v);
property->SetSpecularPower(v);
property->SetLighting(true);
property->SetOpacity(opacity);
if (localStorage->m_LastUpdateTime>=m_FiberBundle->GetUpdateTime3D())
return;
// Calculate time step of the input data for the specified renderer (integer value)
// this method is implemented in mitkMapper
this->CalculateTimeStep( renderer );
this->InternalGenerateData(renderer);
}
void mitk::FiberBundleMapper3D::UpdateShaderParameter(mitk::BaseRenderer * )
{
// see new vtkShaderCallback3D
}
void mitk::FiberBundleMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite)
{
Superclass::SetDefaultProperties(node, renderer, overwrite);
mitk::Vector3D plane_vec; plane_vec.Fill(0.0);
mitk::Point3D plane_origin; plane_origin.Fill(0.0);
node->AddProperty( "3DClipping", mitk::ClippingProperty::New( plane_origin, plane_vec ), renderer, overwrite );
node->AddProperty( "3DClippingPlaneId", mitk::IntProperty::New(-1), renderer, overwrite );
node->AddProperty( "3DClippingPlaneFlip", mitk::BoolProperty::New( false ), renderer, overwrite );
node->AddProperty( "opacity", mitk::FloatProperty::New( 1.0 ), renderer, overwrite);
node->AddProperty( "color", mitk::ColorProperty::New(1.0,1.0,1.0), renderer, overwrite);
node->AddProperty( "pickable", mitk::BoolProperty::New( true ), renderer, overwrite);
node->AddProperty( "shape.linewidth", mitk::IntProperty::New( 1 ), renderer, overwrite );
node->AddProperty( "shape.tuberadius",mitk::FloatProperty::New( 0.0 ), renderer, overwrite);
node->AddProperty( "shape.tubesides",mitk::IntProperty::New( 15 ), renderer, overwrite);
node->AddProperty( "shape.ribbonwidth", mitk::FloatProperty::New( 0.0 ), renderer, overwrite);
node->AddProperty( "light.ambient", mitk::FloatProperty::New( 0.05 ), renderer, overwrite);
node->AddProperty( "light.diffuse", mitk::FloatProperty::New( 0.9 ), renderer, overwrite);
node->AddProperty( "light.specular", mitk::FloatProperty::New( 1.0 ), renderer, overwrite);
node->AddProperty( "light.specularpower", mitk::FloatProperty::New( 16.0 ), renderer, overwrite);
node->AddProperty( "light.ambientcolor", mitk::ColorProperty::New(1,1,1), renderer, overwrite);
node->AddProperty( "light.diffusecolor", mitk::ColorProperty::New(1,1,1), renderer, overwrite);
node->AddProperty( "light.specularcolor", mitk::ColorProperty::New(1,1,1), renderer, overwrite);
}
vtkProp* mitk::FiberBundleMapper3D::GetVtkProp(mitk::BaseRenderer *renderer)
{
return m_LocalStorageHandler.GetLocalStorage(renderer)->m_FiberAssembly;
}
mitk::FiberBundleMapper3D::LocalStorage3D::LocalStorage3D()
{
m_FiberActor = vtkSmartPointer<vtkActor>::New();
m_FiberMapper = vtkSmartPointer<vtkOpenGLPolyDataMapper>::New();
m_FiberAssembly = vtkSmartPointer<vtkPropAssembly>::New();
}
diff --git a/Modules/DiffusionCore/Rendering/mitkFiberBundleMapper3D.h b/Modules/DiffusionCore/Rendering/mitkFiberBundleMapper3D.h
index 3838796..02db35e 100644
--- a/Modules/DiffusionCore/Rendering/mitkFiberBundleMapper3D.h
+++ b/Modules/DiffusionCore/Rendering/mitkFiberBundleMapper3D.h
@@ -1,94 +1,94 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 FiberBundleMapper3D_H_HEADER_INCLUDED
#define FiberBundleMapper3D_H_HEADER_INCLUDED
#include <mitkVtkMapper.h>
#include <mitkFiberBundle.h>
#include <vtkOpenGLPolyDataMapper.h>
#include <vtkSmartPointer.h>
#include <MitkDiffusionCoreExports.h>
class vtkPropAssembly;
class vtkPolyDataMapper;
class vtkLookupTable;
class vtkOpenGLActor;
namespace mitk {
//##Documentation
//## @brief Mapper for FiberBundle
//## @ingroup Mapper
class MITKDIFFUSIONCORE_EXPORT FiberBundleMapper3D : public VtkMapper
{
public:
mitkClassMacro(FiberBundleMapper3D, VtkMapper)
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
const FiberBundle* GetInput();
vtkProp *GetVtkProp(mitk::BaseRenderer *renderer) override; //looks like depricated.. should be replaced bz GetViewProp()
static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = nullptr, bool overwrite = false );
void GenerateDataForRenderer(mitk::BaseRenderer* renderer) override;
class LocalStorage3D : public mitk::Mapper::BaseLocalStorage
{
public:
vtkSmartPointer<vtkActor> m_FiberActor;
vtkSmartPointer<vtkOpenGLPolyDataMapper> m_FiberMapper;
vtkSmartPointer<vtkPropAssembly> m_FiberAssembly;
itk::TimeStamp m_LastUpdateTime;
LocalStorage3D();
~LocalStorage3D() override
{
}
};
/** \brief This member holds all three LocalStorages for the 3D render window(s). */
mitk::LocalStorageHandler<LocalStorage3D> m_LocalStorageHandler;
protected:
FiberBundleMapper3D();
~FiberBundleMapper3D() override;
void InternalGenerateData(mitk::BaseRenderer *renderer);
void UpdateShaderParameter(mitk::BaseRenderer*);
private:
vtkSmartPointer<vtkLookupTable> m_lut;
float m_TubeRadius;
int m_TubeSides;
int m_LineWidth;
float m_RibbonWidth;
vtkSmartPointer<vtkPolyData> m_FiberPolyData;
mitk::FiberBundle* m_FiberBundle;
};
} // end namespace mitk
#endif /* FiberBundleMapper3D_H_HEADER_INCLUDED */
diff --git a/Modules/DiffusionCore/Rendering/mitkOdfNormalizationMethodProperty.cpp b/Modules/DiffusionCore/Rendering/mitkOdfNormalizationMethodProperty.cpp
index 4bfc122..0b7065d 100644
--- a/Modules/DiffusionCore/Rendering/mitkOdfNormalizationMethodProperty.cpp
+++ b/Modules/DiffusionCore/Rendering/mitkOdfNormalizationMethodProperty.cpp
@@ -1,99 +1,99 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkOdfNormalizationMethodProperty.h"
// ODFN_MINMAX, ODFN_MAX, ODFN_NONE ODFN_GLOBAL_MAX
mitk::OdfNormalizationMethodProperty::OdfNormalizationMethodProperty( )
{
this->AddInterpolationTypes();
this->SetValue( static_cast<IdType>( ODFN_MAX ) );
}
mitk::OdfNormalizationMethodProperty::OdfNormalizationMethodProperty( const IdType& value )
{
this->AddInterpolationTypes();
if ( IsValidEnumerationValue( value ) )
{
this->SetValue( value ) ;
}
else
{
this->SetValue( static_cast<IdType>( ODFN_MINMAX ) );
}
}
mitk::OdfNormalizationMethodProperty::OdfNormalizationMethodProperty( const std::string& value )
{
this->AddInterpolationTypes();
if ( IsValidEnumerationValue( value ) )
{
this->SetValue( value );
}
else
{
this->SetValue( static_cast<IdType>( ODFN_MINMAX ) );
}
}
int mitk::OdfNormalizationMethodProperty::GetNormalization()
{
return static_cast<int>( this->GetValueAsId() );
}
void mitk::OdfNormalizationMethodProperty::SetNormalizationToMinMax()
{
this->SetValue( static_cast<IdType>( ODFN_MINMAX ) );
}
void mitk::OdfNormalizationMethodProperty::SetNormalizationToMax()
{
this->SetValue( static_cast<IdType>( ODFN_MAX ) );
}
void mitk::OdfNormalizationMethodProperty::SetNormalizationToNone()
{
this->SetValue( static_cast<IdType>( ODFN_NONE ) );
}
void mitk::OdfNormalizationMethodProperty::SetNormalizationToGlobalMax()
{
this->SetValue( static_cast<IdType>( ODFN_GLOBAL_MAX ) );
}
void mitk::OdfNormalizationMethodProperty::AddInterpolationTypes()
{
AddEnum( "Min-Max", static_cast<IdType>( ODFN_MINMAX ) );
AddEnum( "Maximum", static_cast<IdType>( ODFN_MAX ) );
AddEnum( "None", static_cast<IdType>( ODFN_NONE ) );
AddEnum( "Global Maximum", static_cast<IdType>( ODFN_GLOBAL_MAX ) );
}
bool mitk::OdfNormalizationMethodProperty::AddEnum( const std::string& name, const IdType& id )
{
return Superclass::AddEnum( name, id );
}
MITK_REGISTER_SERIALIZER( OdfNormalizationMethodPropertySerializer )
diff --git a/Modules/DiffusionCore/Rendering/mitkOdfNormalizationMethodProperty.h b/Modules/DiffusionCore/Rendering/mitkOdfNormalizationMethodProperty.h
index 74c88c9..ac503e7 100644
--- a/Modules/DiffusionCore/Rendering/mitkOdfNormalizationMethodProperty.h
+++ b/Modules/DiffusionCore/Rendering/mitkOdfNormalizationMethodProperty.h
@@ -1,137 +1,137 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_OdfNormalizationMethodProperty__H_
#define _MITK_OdfNormalizationMethodProperty__H_
#include "mitkEnumerationProperty.h"
#include "mitkEnumerationPropertySerializer.h"
#include <MitkDiffusionCoreExports.h>
#include "mitkSerializerMacros.h"
namespace mitk
{
enum OdfNormalizationMethod
{
ODFN_MINMAX,
ODFN_MAX,
ODFN_NONE,
ODFN_GLOBAL_MAX
};
/**
* Encapsulates the enumeration for ODF normalization. Valid values are
* ODFN_MINMAX, ODFN_MAX, ODFN_NONE ODFN_GLOBAL_MAX
* Default is ODFN_MINMAX
*/
class MITKDIFFUSIONCORE_EXPORT OdfNormalizationMethodProperty : public EnumerationProperty
{
public:
mitkClassMacro( OdfNormalizationMethodProperty, EnumerationProperty );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitkNewMacro1Param(OdfNormalizationMethodProperty, const IdType&);
mitkNewMacro1Param(OdfNormalizationMethodProperty, const std::string&);
/**
* Returns the current interpolation value as defined by VTK constants.
*/
virtual int GetNormalization();
/**
* Sets the interpolation type to ODFN_MINMAX.
*/
virtual void SetNormalizationToMinMax();
/**
* Sets the interpolation type to ODFN_MAX.
*/
virtual void SetNormalizationToMax();
/**
* Sets the interpolation type to ODFN_NONE.
*/
virtual void SetNormalizationToNone();
/**
* Sets the interpolation type to ODFN_GLOBAL_MAX.
*/
virtual void SetNormalizationToGlobalMax();
protected:
/** Sets reslice interpolation mode to default (VTK_RESLICE_NEAREST).
*/
OdfNormalizationMethodProperty( );
/**
* Constructor. Sets reslice interpolation to the given value.
*/
OdfNormalizationMethodProperty( const IdType& value );
/**
* Constructor. Sets reslice interpolation to the given value.
*/
OdfNormalizationMethodProperty( const std::string& value );
/**
* this function is overridden as protected, so that the user may not add
* additional invalid interpolation types.
*/
bool AddEnum( const std::string& name, const IdType& id ) override;
/**
* Adds the enumeration types as defined by vtk to the list of known
* enumeration values.
*/
virtual void AddInterpolationTypes();
};
class MITKDIFFUSIONCORE_EXPORT OdfNormalizationMethodPropertySerializer : public EnumerationPropertySerializer
{
public:
mitkClassMacro( OdfNormalizationMethodPropertySerializer, EnumerationPropertySerializer );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
BaseProperty::Pointer Deserialize(TiXmlElement* element) override
{
if (!element) return nullptr;
const char* sa( element->Attribute("value") );
std::string s(sa?sa:"");
OdfNormalizationMethodProperty::Pointer property = OdfNormalizationMethodProperty::New();
property->SetValue( s );
return property.GetPointer();
}
protected:
OdfNormalizationMethodPropertySerializer () {}
~OdfNormalizationMethodPropertySerializer () override {}
};
} // end of namespace mitk
#endif
diff --git a/Modules/DiffusionCore/Rendering/mitkOdfScaleByProperty.cpp b/Modules/DiffusionCore/Rendering/mitkOdfScaleByProperty.cpp
index a56e3a9..62fb29e 100644
--- a/Modules/DiffusionCore/Rendering/mitkOdfScaleByProperty.cpp
+++ b/Modules/DiffusionCore/Rendering/mitkOdfScaleByProperty.cpp
@@ -1,87 +1,87 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkOdfScaleByProperty.h"
// ODFN_NONE, ODFN_GFA, ODFN_PC
mitk::OdfScaleByProperty::OdfScaleByProperty( )
{
this->AddInterpolationTypes();
this->SetValue( static_cast<IdType>( ODFSB_NONE ) );
}
mitk::OdfScaleByProperty::OdfScaleByProperty( const IdType& value )
{
this->AddInterpolationTypes();
if ( IsValidEnumerationValue( value ) )
{
this->SetValue( value ) ;
}
else
{
this->SetValue( static_cast<IdType>( ODFSB_NONE ) );
}
}
mitk::OdfScaleByProperty::OdfScaleByProperty( const std::string& value )
{
this->AddInterpolationTypes();
if ( IsValidEnumerationValue( value ) )
{
this->SetValue( value );
}
else
{
this->SetValue( static_cast<IdType>( ODFSB_NONE ) );
}
}
int mitk::OdfScaleByProperty::GetScaleBy()
{
return static_cast<int>( this->GetValueAsId() );
}
void mitk::OdfScaleByProperty::AddInterpolationTypes()
{
AddEnum( "None", static_cast<IdType>( ODFSB_NONE ) );
AddEnum( "GFA", static_cast<IdType>( ODFSB_GFA ) );
AddEnum( "Principal Curvature", static_cast<IdType>( ODFSB_PC ) );
}
void mitk::OdfScaleByProperty::SetScaleByNothing()
{
SetValue(ODFSB_NONE);
}
void mitk::OdfScaleByProperty::SetScaleByGFA()
{
SetValue(ODFSB_GFA);
}
void mitk::OdfScaleByProperty::SetScaleByPrincipalCurvature()
{
SetValue(ODFSB_PC);
}
bool mitk::OdfScaleByProperty::AddEnum( const std::string& name, const IdType& id )
{
return Superclass::AddEnum( name, id );
}
MITK_REGISTER_SERIALIZER( OdfScaleByPropertySerializer )
diff --git a/Modules/DiffusionCore/Rendering/mitkOdfScaleByProperty.h b/Modules/DiffusionCore/Rendering/mitkOdfScaleByProperty.h
index bedb5d6..5ab3e6e 100644
--- a/Modules/DiffusionCore/Rendering/mitkOdfScaleByProperty.h
+++ b/Modules/DiffusionCore/Rendering/mitkOdfScaleByProperty.h
@@ -1,117 +1,117 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_OdfScaleByProperty__H_
#define _MITK_OdfScaleByProperty__H_
#include <MitkDiffusionCoreExports.h>
#include "mitkEnumerationProperty.h"
#include "mitkEnumerationPropertySerializer.h"
namespace mitk
{
enum OdfScaleBy
{
ODFSB_NONE,
ODFSB_GFA,
ODFSB_PC
};
/**
* Encapsulates the enumeration for ODF normalization. Valid values are
* ODFSB_NONE, ODFSB_GFA, ODFSB_PC
* Default is ODFSB_NONE
*/
class MITKDIFFUSIONCORE_EXPORT OdfScaleByProperty : public EnumerationProperty
{
public:
mitkClassMacro( OdfScaleByProperty, EnumerationProperty );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitkNewMacro1Param(OdfScaleByProperty, const IdType&);
mitkNewMacro1Param(OdfScaleByProperty, const std::string&);
/**
* Returns the current interpolation value as defined by VTK constants.
*/
virtual int GetScaleBy();
virtual void SetScaleByNothing();
virtual void SetScaleByGFA();
virtual void SetScaleByPrincipalCurvature();
protected:
/** Sets reslice interpolation mode to default (ODFSB_NONE).
*/
OdfScaleByProperty( );
/**
* Constructor. Sets reslice interpolation to the given value.
*/
OdfScaleByProperty( const IdType& value );
/**
* Constructor. Sets reslice interpolation to the given value.
*/
OdfScaleByProperty( const std::string& value );
/**
* this function is overridden as protected, so that the user may not add
* additional invalid interpolation types.
*/
bool AddEnum( const std::string& name, const IdType& id ) override;
/**
* Adds the enumeration types as defined by vtk to the list of known
* enumeration values.
*/
virtual void AddInterpolationTypes();
};
class MITKDIFFUSIONCORE_EXPORT OdfScaleByPropertySerializer : public EnumerationPropertySerializer
{
public:
mitkClassMacro( OdfScaleByPropertySerializer, EnumerationPropertySerializer );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
BaseProperty::Pointer Deserialize(TiXmlElement* element) override
{
if (!element) return nullptr;
const char* sa( element->Attribute("value") );
std::string s(sa?sa:"");
OdfScaleByProperty::Pointer property = OdfScaleByProperty::New();
property->SetValue( s );
return property.GetPointer();
}
protected:
OdfScaleByPropertySerializer () {}
~OdfScaleByPropertySerializer () override {}
};
} // end of namespace mitk
#endif
diff --git a/Modules/DiffusionCore/Rendering/mitkOdfVtkMapper2D.h b/Modules/DiffusionCore/Rendering/mitkOdfVtkMapper2D.h
index 1d9abef..93618f2 100644
--- a/Modules/DiffusionCore/Rendering/mitkOdfVtkMapper2D.h
+++ b/Modules/DiffusionCore/Rendering/mitkOdfVtkMapper2D.h
@@ -1,161 +1,161 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 ODFVTKMAPPER2D_H_HEADER_INCLUDED
#define ODFVTKMAPPER2D_H_HEADER_INCLUDED
#include "mitkVtkMapper.h"
#include "vtkPropAssembly.h"
#include "vtkAppendPolyData.h"
#include "vtkActor.h"
#include "vtkPolyDataMapper.h"
#include "vtkPlane.h"
#include "vtkCutter.h"
#include "vtkClipPolyData.h"
#include "vtkTransform.h"
#include "vtkDataArrayTemplate.h"
#include "vtkSmartPointer.h"
#include "vtkOdfSource.h"
#include "vtkThickPlane.h"
#include <mitkDiffusionFunctionCollection.h>
namespace mitk {
//##Documentation
//## @brief Mapper for spherical object densitiy function representations
//##
template<class TPixelType, int NrOdfDirections>
class OdfVtkMapper2D : public VtkMapper
{
struct OdfDisplayGeometry {
double vp[ 3 ], vnormal[ 3 ];
Vector3D normal;
double d, d1, d2;
mitk::Point3D M3D, L3D, O3D;
double vp_original[ 3 ], vnormal_original[ 3 ];
mitk::Vector2D size, origin;
bool Equals(OdfDisplayGeometry other)
{
return other.vp_original[0] == vp[0] &&
other.vp_original[1] == vp[1] &&
other.vp_original[2] == vp[2] &&
other.vnormal_original[0] == vnormal[0] &&
other.vnormal_original[1] == vnormal[1] &&
other.vnormal_original[2] == vnormal[2] &&
other.size[0] == size[0] &&
other.size[1] == size[1] &&
other.origin[0] == origin[0] &&
other.origin[1] == origin[1];
}
};
public:
mitkClassMacro(OdfVtkMapper2D,VtkMapper)
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
vtkProp* GetVtkProp(mitk::BaseRenderer* renderer) override;
bool IsVisibleOdfs(mitk::BaseRenderer* renderer);
void MitkRenderOverlay(mitk::BaseRenderer* renderer) override;
void MitkRenderOpaqueGeometry(mitk::BaseRenderer* renderer) override;
void MitkRenderTranslucentGeometry(mitk::BaseRenderer* renderer) override;
void MitkRenderVolumetricGeometry(mitk::BaseRenderer* /*renderer*/) override{}
OdfDisplayGeometry MeasureDisplayedGeometry(mitk::BaseRenderer* renderer);
double GetMinImageSpacing( int index );
void ApplyPropertySettings();
virtual void Slice(mitk::BaseRenderer* renderer, OdfDisplayGeometry dispGeo);
virtual int GetIndex(mitk::BaseRenderer* renderer);
static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = nullptr, bool overwrite = false);
void Update(mitk::BaseRenderer * renderer) override;
void GenerateDataForRenderer(mitk::BaseRenderer* renderer) override;
bool IsLODEnabled( BaseRenderer * /*renderer*/ ) const override { return true; }
class LocalStorage : public mitk::Mapper::BaseLocalStorage
{
public:
std::vector< vtkSmartPointer<vtkPropAssembly> > m_PropAssemblies;
std::vector< vtkSmartPointer<vtkAppendPolyData> > m_OdfsPlanes;
std::vector< vtkSmartPointer<vtkActor> > m_OdfsActors;
std::vector< vtkSmartPointer<vtkPolyDataMapper> > m_OdfsMappers;
vtkSmartPointer< vtkPolyData > m_TemplateOdf;
itk::TimeStamp m_LastUpdateTime;
/** \brief Default constructor of the local storage. */
LocalStorage();
/** \brief Default deconstructor of the local storage. */
~LocalStorage() override
{
}
};
protected:
OdfVtkMapper2D();
~OdfVtkMapper2D() override;
static void GlyphMethod(void *arg);
bool IsPlaneRotated(mitk::BaseRenderer* renderer);
static bool m_ToggleTensorEllipsoidView;
static bool m_ToggleColourisationMode;
static bool m_ToggleGlyphPlacementMode;
typedef vnl_matrix_fixed<double, 3, 3> DirectionsType;
private:
mitk::Image* GetInput();
static vtkSmartPointer<vtkTransform> m_OdfTransform;
static vtkSmartPointer<vtkOdfSource> m_OdfSource;
static float m_Scaling;
static int m_Normalization;
static int m_ScaleBy;
static float m_IndexParam1;
static float m_IndexParam2;
static vtkSmartPointer<vtkDoubleArray> m_ColourScalars;
int m_ShowMaxNumber;
std::vector< vtkSmartPointer<vtkPlane> > m_Planes;
std::vector< vtkSmartPointer<vtkCutter> > m_Cutters;
std::vector< vtkSmartPointer<vtkThickPlane> > m_ThickPlanes1;
std::vector< vtkSmartPointer<vtkClipPolyData> > m_Clippers1;
std::vector< vtkSmartPointer<vtkThickPlane> > m_ThickPlanes2;
std::vector< vtkSmartPointer<vtkClipPolyData> > m_Clippers2;
vtkImageData* m_VtkImage ;
std::vector< OdfDisplayGeometry > m_LastDisplayGeometry;
mitk::LocalStorageHandler<LocalStorage> m_LSH;
static vnl_matrix<float> m_Sh2Basis;
static vnl_matrix<float> m_Sh4Basis;
static vnl_matrix<float> m_Sh6Basis;
static vnl_matrix<float> m_Sh8Basis;
static vnl_matrix<float> m_Sh10Basis;
static vnl_matrix<float> m_Sh12Basis;
};
} // namespace mitk
#include "mitkOdfVtkMapper2D.txx"
#endif /* ODFVTKMAPPER2D_H_HEADER_INCLUDED */
diff --git a/Modules/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx b/Modules/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx
index 477a109..8cb7f2e 100644
--- a/Modules/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx
+++ b/Modules/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx
@@ -1,984 +1,984 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkOdfVtkMapper2D_txx__
#define __mitkOdfVtkMapper2D_txx__
#include "mitkOdfVtkMapper2D.h"
#include "mitkDataNode.h"
#include "mitkBaseRenderer.h"
#include "mitkMatrixConvert.h"
#include "mitkGeometry3D.h"
#include "mitkTimeGeometry.h"
#include "mitkOdfNormalizationMethodProperty.h"
#include "mitkOdfScaleByProperty.h"
#include "mitkProperties.h"
#include "mitkTensorImage.h"
#include "mitkShImage.h"
#include "vtkSphereSource.h"
#include "vtkPropCollection.h"
#include "vtkMaskedGlyph3D.h"
#include "vtkGlyph2D.h"
#include "vtkGlyph3D.h"
#include "vtkMaskedProgrammableGlyphFilter.h"
#include "vtkImageData.h"
#include "vtkLinearTransform.h"
#include "vtkCamera.h"
#include "vtkPointData.h"
#include "vtkTransformPolyDataFilter.h"
#include "vtkTransform.h"
#include "vtkOdfSource.h"
#include "vtkDoubleArray.h"
#include "vtkLookupTable.h"
#include "vtkProperty.h"
#include "vtkPolyDataNormals.h"
#include "vtkLight.h"
#include "vtkLightCollection.h"
#include "vtkMath.h"
#include "vtkFloatArray.h"
#include "vtkDelaunay2D.h"
#include "vtkMapper.h"
#include <vtkInformationVector.h>
#include <vtkInformation.h>
#include "vtkRenderer.h"
#include "itkOrientationDistributionFunction.h"
#include "itkFixedArray.h"
#include <mitkGL.h>
#include "vtkOpenGLRenderer.h"
#define _USE_MATH_DEFINES
#include <cmath>
#include <ciso646>
template<class T, int N>
vtkSmartPointer<vtkTransform> mitk::OdfVtkMapper2D<T,N>::m_OdfTransform = vtkSmartPointer<vtkTransform>::New();
template<class T, int N>
vtkSmartPointer<vtkOdfSource> mitk::OdfVtkMapper2D<T,N>::m_OdfSource = vtkSmartPointer<vtkOdfSource>::New();
template<class T, int N>
float mitk::OdfVtkMapper2D<T,N>::m_Scaling;
template<class T, int N>
int mitk::OdfVtkMapper2D<T,N>::m_Normalization;
template<class T, int N>
int mitk::OdfVtkMapper2D<T,N>::m_ScaleBy;
template<class T, int N>
float mitk::OdfVtkMapper2D<T,N>::m_IndexParam1;
template<class T, int N>
float mitk::OdfVtkMapper2D<T,N>::m_IndexParam2;
template<class T, int N>
bool mitk::OdfVtkMapper2D<T, N>::m_ToggleTensorEllipsoidView = false;
template<class T, int N>
bool mitk::OdfVtkMapper2D<T, N>::m_ToggleColourisationMode = false;
template<class T, int N>
bool mitk::OdfVtkMapper2D<T, N>::m_ToggleGlyphPlacementMode = true;
template<class T, int N>
vtkSmartPointer<vtkDoubleArray> mitk::OdfVtkMapper2D<T, N>::m_ColourScalars = nullptr;
template<class T, int N>
vnl_matrix<float> mitk::OdfVtkMapper2D<T, N>::m_Sh2Basis = mitk::sh::CalcShBasisForDirections(2, itk::PointShell<N, vnl_matrix_fixed<double, 3, N> >::DistributePointShell()->as_matrix());
template<class T, int N>
vnl_matrix<float> mitk::OdfVtkMapper2D<T, N>::m_Sh4Basis = mitk::sh::CalcShBasisForDirections(4, itk::PointShell<N, vnl_matrix_fixed<double, 3, N> >::DistributePointShell()->as_matrix());
template<class T, int N>
vnl_matrix<float> mitk::OdfVtkMapper2D<T, N>::m_Sh6Basis = mitk::sh::CalcShBasisForDirections(6, itk::PointShell<N, vnl_matrix_fixed<double, 3, N> >::DistributePointShell()->as_matrix());
template<class T, int N>
vnl_matrix<float> mitk::OdfVtkMapper2D<T, N>::m_Sh8Basis = mitk::sh::CalcShBasisForDirections(8, itk::PointShell<N, vnl_matrix_fixed<double, 3, N> >::DistributePointShell()->as_matrix());
template<class T, int N>
vnl_matrix<float> mitk::OdfVtkMapper2D<T, N>::m_Sh10Basis = mitk::sh::CalcShBasisForDirections(10, itk::PointShell<N, vnl_matrix_fixed<double, 3, N> >::DistributePointShell()->as_matrix());
template<class T, int N>
vnl_matrix<float> mitk::OdfVtkMapper2D<T, N>::m_Sh12Basis = mitk::sh::CalcShBasisForDirections(12, itk::PointShell<N, vnl_matrix_fixed<double, 3, N> >::DistributePointShell()->as_matrix());
template<class T, int N>
mitk::OdfVtkMapper2D<T,N>::LocalStorage::LocalStorage()
{
m_PropAssemblies.push_back(vtkSmartPointer<vtkPropAssembly>::New());
m_PropAssemblies.push_back(vtkSmartPointer<vtkPropAssembly>::New());
m_PropAssemblies.push_back(vtkSmartPointer<vtkPropAssembly>::New());
m_OdfsPlanes.push_back(vtkSmartPointer<vtkAppendPolyData>::New());
m_OdfsPlanes.push_back(vtkSmartPointer<vtkAppendPolyData>::New());
m_OdfsPlanes.push_back(vtkSmartPointer<vtkAppendPolyData>::New());
m_OdfsPlanes[0]->AddInputData(vtkSmartPointer<vtkPolyData>::New());
m_OdfsPlanes[1]->AddInputData(vtkSmartPointer<vtkPolyData>::New());
m_OdfsPlanes[2]->AddInputData(vtkSmartPointer<vtkPolyData>::New());
m_OdfsActors.push_back(vtkSmartPointer<vtkActor>::New());
m_OdfsActors.push_back(vtkSmartPointer<vtkActor>::New());
m_OdfsActors.push_back(vtkSmartPointer<vtkActor>::New());
m_OdfsActors[0]->GetProperty()->SetInterpolationToGouraud();
m_OdfsActors[1]->GetProperty()->SetInterpolationToGouraud();
m_OdfsActors[2]->GetProperty()->SetInterpolationToGouraud();
m_OdfsMappers.push_back(vtkSmartPointer<vtkPolyDataMapper>::New());
m_OdfsMappers.push_back(vtkSmartPointer<vtkPolyDataMapper>::New());
m_OdfsMappers.push_back(vtkSmartPointer<vtkPolyDataMapper>::New());
vtkSmartPointer<vtkLookupTable> lut = vtkSmartPointer<vtkLookupTable>::New();
m_OdfsMappers[0]->SetLookupTable(lut);
m_OdfsMappers[1]->SetLookupTable(lut);
m_OdfsMappers[2]->SetLookupTable(lut);
m_OdfsActors[0]->SetMapper(m_OdfsMappers[0]);
m_OdfsActors[1]->SetMapper(m_OdfsMappers[1]);
m_OdfsActors[2]->SetMapper(m_OdfsMappers[2]);
}
template<class T, int N>
mitk::OdfVtkMapper2D<T,N>
::OdfVtkMapper2D()
{
m_LastDisplayGeometry.push_back(OdfDisplayGeometry());
m_LastDisplayGeometry.push_back(OdfDisplayGeometry());
m_LastDisplayGeometry.push_back(OdfDisplayGeometry());
m_Planes.push_back(vtkSmartPointer<vtkPlane>::New());
m_Planes.push_back(vtkSmartPointer<vtkPlane>::New());
m_Planes.push_back(vtkSmartPointer<vtkPlane>::New());
m_Cutters.push_back(vtkSmartPointer<vtkCutter>::New());
m_Cutters.push_back(vtkSmartPointer<vtkCutter>::New());
m_Cutters.push_back(vtkSmartPointer<vtkCutter>::New());
m_Cutters[0]->SetCutFunction( m_Planes[0] );
m_Cutters[0]->GenerateValues( 1, 0, 1 );
m_Cutters[1]->SetCutFunction( m_Planes[1] );
m_Cutters[1]->GenerateValues( 1, 0, 1 );
m_Cutters[2]->SetCutFunction( m_Planes[2] );
m_Cutters[2]->GenerateValues( 1, 0, 1 );
// Windowing the cutted planes in direction 1
m_ThickPlanes1.push_back(vtkSmartPointer<vtkThickPlane>::New());
m_ThickPlanes1.push_back(vtkSmartPointer<vtkThickPlane>::New());
m_ThickPlanes1.push_back(vtkSmartPointer<vtkThickPlane>::New());
m_Clippers1.push_back(vtkSmartPointer<vtkClipPolyData>::New());
m_Clippers1.push_back(vtkSmartPointer<vtkClipPolyData>::New());
m_Clippers1.push_back(vtkSmartPointer<vtkClipPolyData>::New());
m_Clippers1[0]->SetClipFunction( m_ThickPlanes1[0] );
m_Clippers1[1]->SetClipFunction( m_ThickPlanes1[1] );
m_Clippers1[2]->SetClipFunction( m_ThickPlanes1[2] );
// Windowing the cutted planes in direction 2
m_ThickPlanes2.push_back(vtkSmartPointer<vtkThickPlane>::New());
m_ThickPlanes2.push_back(vtkSmartPointer<vtkThickPlane>::New());
m_ThickPlanes2.push_back(vtkSmartPointer<vtkThickPlane>::New());
m_Clippers2.push_back(vtkSmartPointer<vtkClipPolyData>::New());
m_Clippers2.push_back(vtkSmartPointer<vtkClipPolyData>::New());
m_Clippers2.push_back(vtkSmartPointer<vtkClipPolyData>::New());
m_Clippers2[0]->SetClipFunction( m_ThickPlanes2[0] );
m_Clippers2[1]->SetClipFunction( m_ThickPlanes2[1] );
m_Clippers2[2]->SetClipFunction( m_ThickPlanes2[2] );
m_ShowMaxNumber = 500;
}
template<class T, int N>
mitk::OdfVtkMapper2D<T,N>
::~OdfVtkMapper2D()
{
}
template<class T, int N>
mitk::Image* mitk::OdfVtkMapper2D<T,N>
::GetInput()
{
return static_cast<mitk::Image * > ( m_DataNode->GetData() );
}
template<class T, int N>
vtkProp* mitk::OdfVtkMapper2D<T,N>
::GetVtkProp(mitk::BaseRenderer* renderer)
{
LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
return localStorage->m_PropAssemblies[GetIndex(renderer)];
}
template<class T, int N>
int mitk::OdfVtkMapper2D<T,N>
::GetIndex(mitk::BaseRenderer* renderer)
{
if(!strcmp(renderer->GetName(),"stdmulti.widget1"))
return 0;
if(!strcmp(renderer->GetName(),"stdmulti.widget2"))
return 1;
if(!strcmp(renderer->GetName(),"stdmulti.widget3"))
return 2;
return 0;
}
template<class T, int N>
void mitk::OdfVtkMapper2D<T,N>
::GlyphMethod(void *arg)
{
vtkMaskedProgrammableGlyphFilter* pfilter=(vtkMaskedProgrammableGlyphFilter*)arg;
double point[3];
double debugpoint[3];
pfilter->GetPoint(point);
pfilter->GetPoint(debugpoint);
itk::Point<double,3> p(point);
Vector3D spacing = pfilter->GetGeometry()->GetSpacing();
p[0] /= spacing[0];
p[1] /= spacing[1];
p[2] /= spacing[2];
mitk::Point3D p2;
pfilter->GetGeometry()->IndexToWorld( p, p2 );
point[0] = p2[0];
point[1] = p2[1];
point[2] = p2[2];
vtkPointData* data = pfilter->GetPointData();
vtkDataArray* image_vals = data->GetArray("vector");
vtkIdType id = pfilter->GetPointId();
m_OdfTransform->Identity();
m_OdfTransform->Translate(point[0],point[1],point[2]);
typedef itk::OrientationDistributionFunction<float,N> OdfType;
OdfType odf;
if( image_vals->GetNumberOfComponents()==6 && !m_ToggleTensorEllipsoidView )
{
float tensorelems[6] = {
(float)image_vals->GetComponent(id,0),
(float)image_vals->GetComponent(id,1),
(float)image_vals->GetComponent(id,2),
(float)image_vals->GetComponent(id,3),
(float)image_vals->GetComponent(id,4),
(float)image_vals->GetComponent(id,5),
};
itk::DiffusionTensor3D<float> tensor(tensorelems);
odf.InitFromTensor(tensor);
}
else if( image_vals->GetNumberOfComponents()==6 && m_ToggleTensorEllipsoidView )
{
float tensorelems[6] = {
(float)image_vals->GetComponent(id,0),
(float)image_vals->GetComponent(id,1),
(float)image_vals->GetComponent(id,2),
(float)image_vals->GetComponent(id,3),
(float)image_vals->GetComponent(id,4),
(float)image_vals->GetComponent(id,5),
};
itk::DiffusionTensor3D<float> tensor( tensorelems );
odf.InitFromEllipsoid( tensor );
}
else if (image_vals->GetNumberOfComponents() == ODF_SAMPLING_SIZE)
{
for(int i=0; i<N; i++)
odf[i] = (double)image_vals->GetComponent(id,i);
}
else
{
int nrCoeffs = image_vals->GetNumberOfComponents();
Vector< float, N > odf_vals;
vnl_vector< float > coeffs(nrCoeffs);
for(int i=0; i<nrCoeffs; i++)
coeffs[i] = (float)image_vals->GetComponent(id,i);
switch (nrCoeffs)
{
case 6:
odf_vals = ( m_Sh2Basis * coeffs ).data_block();
break;
case 15:
odf_vals = ( m_Sh4Basis * coeffs ).data_block();
break;
case 28:
odf_vals = ( m_Sh6Basis * coeffs ).data_block();
break;
case 45:
odf_vals = ( m_Sh8Basis * coeffs ).data_block();
break;
case 66:
odf_vals = ( m_Sh10Basis * coeffs ).data_block();
break;
case 91:
odf_vals = ( m_Sh12Basis * coeffs ).data_block();
break;
default :
mitkThrow() << "SH order larger 12 not supported in current ODF mapper version";
}
for(int i=0; i<N; i++)
odf[i] = odf_vals[i];
}
if (m_ToggleColourisationMode)
{
m_OdfSource->SetUseCustomColor(true);
vnl_vector_fixed<double,3> d = odf.GetPrincipalDiffusionDirection();
m_OdfSource->SetColor(fabs(d[0])*255,fabs(d[1])*255,fabs(d[2])*255);
}
else
{
m_OdfSource->SetUseCustomColor(false);
}
switch(m_ScaleBy)
{
case ODFSB_NONE:
m_OdfSource->SetScale(m_Scaling);
break;
case ODFSB_GFA:
m_OdfSource->SetScale(m_Scaling*odf.GetGeneralizedFractionalAnisotropy());
break;
case ODFSB_PC:
m_OdfSource->SetScale(m_Scaling*odf.GetPrincipleCurvature(m_IndexParam1, m_IndexParam2, 0));
break;
}
m_OdfSource->SetNormalization(m_Normalization);
m_OdfSource->SetOdf(odf);
m_OdfSource->Modified();
}
template<class T, int N>
typename mitk::OdfVtkMapper2D<T,N>::OdfDisplayGeometry mitk::OdfVtkMapper2D<T,N>
::MeasureDisplayedGeometry(mitk::BaseRenderer* renderer)
{
PlaneGeometry::ConstPointer worldPlaneGeometry = renderer->GetCurrentWorldPlaneGeometry();
// set up the cutter orientation according to the current geometry of
// the renderers plane
double vp[ 3 ], vnormal[ 3 ];
Point3D point = worldPlaneGeometry->GetOrigin();
Vector3D normal = worldPlaneGeometry->GetNormal(); normal.Normalize();
vnl2vtk( point.GetVnlVector(), vp );
vnl2vtk( normal.GetVnlVector(), vnormal );
Point2D dispSizeInMM = renderer->GetViewportSizeInMM();
Point2D displayGeometryOriginInMM = renderer->GetOriginInMM();
mitk::Vector2D size = dispSizeInMM.GetVectorFromOrigin();
mitk::Vector2D origin = displayGeometryOriginInMM.GetVectorFromOrigin();
//
// |------O------|
// | d2 |
// L d1 M |
// | |
// |-------------|
//
mitk::Vector2D M;
mitk::Vector2D L;
mitk::Vector2D O;
M[0] = origin[0] + size[0]/2;
M[1] = origin[1] + size[1]/2;
L[0] = origin[0];
L[1] = origin[1] + size[1]/2;
O[0] = origin[0] + size[0]/2;
O[1] = origin[1] + size[1];
mitk::Point2D point1;
point1[0] = M[0]; point1[1] = M[1];
mitk::Point3D M3D;
renderer->GetCurrentWorldPlaneGeometry()->Map(point1, M3D);
point1[0] = L[0]; point1[1] = L[1];
mitk::Point3D L3D;
renderer->GetCurrentWorldPlaneGeometry()->Map(point1, L3D);
point1[0] = O[0]; point1[1] = O[1];
mitk::Point3D O3D;
renderer->GetCurrentWorldPlaneGeometry()->Map(point1, O3D);
double d1 = sqrt((M3D[0]-L3D[0])*(M3D[0]-L3D[0])
+ (M3D[1]-L3D[1])*(M3D[1]-L3D[1])
+ (M3D[2]-L3D[2])*(M3D[2]-L3D[2]));
double d2 = sqrt((M3D[0]-O3D[0])*(M3D[0]-O3D[0])
+ (M3D[1]-O3D[1])*(M3D[1]-O3D[1])
+ (M3D[2]-O3D[2])*(M3D[2]-O3D[2]));
double d = d1>d2 ? d1 : d2;
d = d2;
OdfDisplayGeometry retval;
retval.vp[0] = vp[0];
retval.vp[1] = vp[1];
retval.vp[2] = vp[2];
retval.vnormal[0] = vnormal[0];
retval.vnormal[1] = vnormal[1];
retval.vnormal[2] = vnormal[2];
retval.normal[0] = normal[0];
retval.normal[1] = normal[1];
retval.normal[2] = normal[2];
retval.d = d;
retval.d1 = d1;
retval.d2 = d2;
retval.M3D[0] = M3D[0];
retval.M3D[1] = M3D[1];
retval.M3D[2] = M3D[2];
retval.L3D[0] = L3D[0];
retval.L3D[1] = L3D[1];
retval.L3D[2] = L3D[2];
retval.O3D[0] = O3D[0];
retval.O3D[1] = O3D[1];
retval.O3D[2] = O3D[2];
retval.vp_original[0] = vp[0];
retval.vp_original[1] = vp[1];
retval.vp_original[2] = vp[2];
retval.vnormal_original[0] = vnormal[0];
retval.vnormal_original[1] = vnormal[1];
retval.vnormal_original[2] = vnormal[2];
retval.size[0] = size[0];
retval.size[1] = size[1];
retval.origin[0] = origin[0];
retval.origin[1] = origin[1];
return retval;
}
template<class T, int N>
void mitk::OdfVtkMapper2D<T,N>
::Slice(mitk::BaseRenderer* renderer, OdfDisplayGeometry dispGeo)
{
LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
vtkLinearTransform * vtktransform =
this->GetDataNode()->GetVtkTransform(this->GetTimestep());
int index = GetIndex(renderer);
vtkSmartPointer<vtkTransform> inversetransform = vtkSmartPointer<vtkTransform>::New();
inversetransform->Identity();
inversetransform->Concatenate(vtktransform->GetLinearInverse());
double myscale[3];
((vtkTransform*)vtktransform)->GetScale(myscale);
myscale[0] = fabs(myscale[0]);
myscale[1] = fabs(myscale[1]);
myscale[2] = fabs(myscale[2]);
inversetransform->PostMultiply();
inversetransform->Scale(myscale[0],myscale[1],myscale[2]);
inversetransform->TransformPoint( dispGeo.vp, dispGeo.vp );
inversetransform->TransformNormalAtPoint( dispGeo.vp, dispGeo.vnormal, dispGeo.vnormal );
// vtk works in axis align coords
// thus the normal also must be axis align, since
// we do not allow arbitrary cutting through volume
//
// vnormal should already be axis align, but in order
// to get rid of precision effects, we set the two smaller
// components to zero here
int dims[3];
m_VtkImage->GetDimensions(dims);
double spac[3];
m_VtkImage->GetSpacing(spac);
if(fabs(dispGeo.vnormal[0]) > fabs(dispGeo.vnormal[1])
&& fabs(dispGeo.vnormal[0]) > fabs(dispGeo.vnormal[2]) )
{
if(fabs(dispGeo.vp[0]/spac[0]) < 0.4)
dispGeo.vp[0] = 0.4*spac[0];
if(fabs(dispGeo.vp[0]/spac[0]) > (dims[0]-1)-0.4)
dispGeo.vp[0] = ((dims[0]-1)-0.4)*spac[0];
dispGeo.vnormal[1] = 0;
dispGeo.vnormal[2] = 0;
}
if(fabs(dispGeo.vnormal[1]) > fabs(dispGeo.vnormal[0]) && fabs(dispGeo.vnormal[1]) > fabs(dispGeo.vnormal[2]) )
{
if(fabs(dispGeo.vp[1]/spac[1]) < 0.4)
dispGeo.vp[1] = 0.4*spac[1];
if(fabs(dispGeo.vp[1]/spac[1]) > (dims[1]-1)-0.4)
dispGeo.vp[1] = ((dims[1]-1)-0.4)*spac[1];
dispGeo.vnormal[0] = 0;
dispGeo.vnormal[2] = 0;
}
if(fabs(dispGeo.vnormal[2]) > fabs(dispGeo.vnormal[1]) && fabs(dispGeo.vnormal[2]) > fabs(dispGeo.vnormal[0]) )
{
if(fabs(dispGeo.vp[2]/spac[2]) < 0.4)
dispGeo.vp[2] = 0.4*spac[2];
if(fabs(dispGeo.vp[2]/spac[2]) > (dims[2]-1)-0.4)
dispGeo.vp[2] = ((dims[2]-1)-0.4)*spac[2];
dispGeo.vnormal[0] = 0;
dispGeo.vnormal[1] = 0;
}
m_Planes[index]->SetTransform( (vtkAbstractTransform*)nullptr );
m_Planes[index]->SetOrigin( dispGeo.vp );
m_Planes[index]->SetNormal( dispGeo.vnormal );
vtkSmartPointer<vtkPoints> points;
vtkSmartPointer<vtkPoints> tmppoints;
vtkSmartPointer<vtkPolyData> polydata;
vtkSmartPointer<vtkFloatArray> pointdata;
vtkSmartPointer<vtkDelaunay2D> delaunay;
vtkSmartPointer<vtkPolyData> cuttedPlane;
// the cutter only works if we do not have a 2D-image
// or if we have a 2D-image and want to see the whole image.
//
// for side views of 2D-images, we need some special treatment
if(!( (dims[0] == 1 && dispGeo.vnormal[0] != 0) ||
(dims[1] == 1 && dispGeo.vnormal[1] != 0) ||
(dims[2] == 1 && dispGeo.vnormal[2] != 0) ))
{
m_Cutters[index]->SetCutFunction( m_Planes[index] );
m_Cutters[index]->SetInputData( m_VtkImage );
m_Cutters[index]->Update();
cuttedPlane = m_Cutters[index]->GetOutput();
}
else
{
// cutting of a 2D-Volume does not work,
// so we have to build up our own polydata object
cuttedPlane = vtkSmartPointer<vtkPolyData>::New();
points = vtkSmartPointer<vtkPoints>::New();
points->SetNumberOfPoints(m_VtkImage->GetNumberOfPoints());
for(int i=0; i<m_VtkImage->GetNumberOfPoints(); i++)
{
points->SetPoint(i, m_VtkImage->GetPoint(i));
}
cuttedPlane->SetPoints(points);
int nZero1, nZero2;
if(dims[0]==1)
{
nZero1 = 1; nZero2 = 2;
}
else if(dims[1]==1)
{
nZero1 = 0; nZero2 = 2;
}
else
{
nZero1 = 0; nZero2 = 1;
}
tmppoints = vtkSmartPointer<vtkPoints>::New();
for(int j=0; j<m_VtkImage->GetNumberOfPoints(); j++){
double pt[3];
m_VtkImage->GetPoint(j,pt);
tmppoints->InsertNextPoint(pt[nZero1],pt[nZero2],0);
}
polydata = vtkSmartPointer<vtkPolyData>::New();
polydata->SetPoints( tmppoints );
delaunay = vtkSmartPointer<vtkDelaunay2D>::New();
delaunay->SetInputData( polydata );
delaunay->Update();
vtkCellArray* polys = delaunay->GetOutput()->GetPolys();
cuttedPlane->SetPolys(polys);
}
if(cuttedPlane->GetNumberOfPoints())
{
// WINDOWING HERE
dispGeo.vnormal[0] = dispGeo.M3D[0]-dispGeo.O3D[0];
dispGeo.vnormal[1] = dispGeo.M3D[1]-dispGeo.O3D[1];
dispGeo.vnormal[2] = dispGeo.M3D[2]-dispGeo.O3D[2];
vtkMath::Normalize(dispGeo.vnormal);
dispGeo.vp[0] = dispGeo.M3D[0];
dispGeo.vp[1] = dispGeo.M3D[1];
dispGeo.vp[2] = dispGeo.M3D[2];
inversetransform->TransformPoint( dispGeo.vp, dispGeo.vp );
inversetransform->TransformNormalAtPoint( dispGeo.vp, dispGeo.vnormal, dispGeo.vnormal );
m_ThickPlanes1[index]->count = 0;
m_ThickPlanes1[index]->SetTransform((vtkAbstractTransform*)nullptr );
m_ThickPlanes1[index]->SetPose( dispGeo.vnormal, dispGeo.vp );
m_ThickPlanes1[index]->SetThickness(dispGeo.d2);
m_Clippers1[index]->SetClipFunction( m_ThickPlanes1[index] );
m_Clippers1[index]->SetInputData( cuttedPlane );
m_Clippers1[index]->SetInsideOut(1);
m_Clippers1[index]->Update();
dispGeo.vnormal[0] = dispGeo.M3D[0]-dispGeo.L3D[0];
dispGeo.vnormal[1] = dispGeo.M3D[1]-dispGeo.L3D[1];
dispGeo.vnormal[2] = dispGeo.M3D[2]-dispGeo.L3D[2];
vtkMath::Normalize(dispGeo.vnormal);
dispGeo.vp[0] = dispGeo.M3D[0];
dispGeo.vp[1] = dispGeo.M3D[1];
dispGeo.vp[2] = dispGeo.M3D[2];
inversetransform->TransformPoint( dispGeo.vp, dispGeo.vp );
inversetransform->TransformNormalAtPoint( dispGeo.vp, dispGeo.vnormal, dispGeo.vnormal );
m_ThickPlanes2[index]->count = 0;
m_ThickPlanes2[index]->SetTransform((vtkAbstractTransform*)nullptr );
m_ThickPlanes2[index]->SetPose( dispGeo.vnormal, dispGeo.vp );
m_ThickPlanes2[index]->SetThickness(dispGeo.d1);
m_Clippers2[index]->SetClipFunction( m_ThickPlanes2[index] );
m_Clippers2[index]->SetInputData( m_Clippers1[index]->GetOutput() );
m_Clippers2[index]->SetInsideOut(1);
m_Clippers2[index]->Update();
cuttedPlane = m_Clippers2[index]->GetOutput ();
if(cuttedPlane->GetNumberOfPoints())
{
localStorage->m_OdfsPlanes[index]->RemoveAllInputs();
vtkSmartPointer<vtkPolyDataNormals> normals = vtkSmartPointer<vtkPolyDataNormals>::New();
normals->SetInputConnection( m_OdfSource->GetOutputPort() );
normals->SplittingOff();
normals->ConsistencyOff();
normals->AutoOrientNormalsOff();
normals->ComputePointNormalsOn();
normals->ComputeCellNormalsOff();
normals->FlipNormalsOff();
normals->NonManifoldTraversalOff();
vtkSmartPointer<vtkTransformPolyDataFilter> trans = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
trans->SetInputConnection( normals->GetOutputPort() );
trans->SetTransform(m_OdfTransform);
vtkSmartPointer<vtkMaskedProgrammableGlyphFilter> glyphGenerator = vtkSmartPointer<vtkMaskedProgrammableGlyphFilter>::New();
glyphGenerator->SetMaximumNumberOfPoints(std::min(m_ShowMaxNumber,(int)cuttedPlane->GetNumberOfPoints()));
glyphGenerator->SetRandomMode( m_ToggleGlyphPlacementMode );
glyphGenerator->SetUseMaskPoints(1);
glyphGenerator->SetSourceConnection(trans->GetOutputPort() );
glyphGenerator->SetInput(cuttedPlane);
glyphGenerator->SetColorModeToColorBySource();
glyphGenerator->SetGeometry(this->GetDataNode()->GetData()->GetGeometry());
glyphGenerator->SetGlyphMethod(&(GlyphMethod),(void *)glyphGenerator);
try
{
glyphGenerator->Update();
}
catch( itk::ExceptionObject& err )
{
std::cout << err << std::endl;
}
localStorage->m_OdfsPlanes[index]->AddInputConnection(glyphGenerator->GetOutputPort());
localStorage->m_OdfsPlanes[index]->Update();
}
}
localStorage->m_OdfsMappers[index]->ScalarVisibilityOn();
localStorage->m_OdfsMappers[index]->SetScalarModeToUsePointFieldData();
localStorage->m_OdfsMappers[index]->SelectColorArray("ODF_COLORS");
localStorage->m_PropAssemblies[index]->VisibilityOn();
if(localStorage->m_PropAssemblies[index]->GetParts()->IsItemPresent(localStorage->m_OdfsActors[index]))
{
localStorage->m_PropAssemblies[index]->RemovePart(localStorage->m_OdfsActors[index]);
}
localStorage->m_OdfsMappers[index]->SetInputData(localStorage->m_OdfsPlanes[index]->GetOutput());
localStorage->m_PropAssemblies[index]->AddPart(localStorage->m_OdfsActors[index]);
}
template<class T, int N>
bool mitk::OdfVtkMapper2D<T,N>
::IsVisibleOdfs(mitk::BaseRenderer* renderer)
{
mitk::Image::Pointer input = const_cast<mitk::Image*>(this->GetInput());
const TimeGeometry *inputTimeGeometry = input->GetTimeGeometry();
if(inputTimeGeometry==nullptr || inputTimeGeometry->CountTimeSteps()==0 || !inputTimeGeometry->IsValidTimeStep(this->GetTimestep()))
return false;
if(this->IsPlaneRotated(renderer))
return false;
bool retval = false;
switch(GetIndex(renderer))
{
case 0:
GetDataNode()->GetVisibility(retval, renderer, "VisibleOdfs_T");
break;
case 1:
GetDataNode()->GetVisibility(retval, renderer, "VisibleOdfs_S");
break;
case 2:
GetDataNode()->GetVisibility(retval, renderer, "VisibleOdfs_C");
break;
}
return retval;
}
template<class T, int N>
void mitk::OdfVtkMapper2D<T,N>
::MitkRenderOverlay(mitk::BaseRenderer* renderer)
{
if ( this->IsVisibleOdfs(renderer)==false )
return;
if ( this->GetVtkProp(renderer)->GetVisibility() )
this->GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer());
}
template<class T, int N>
void mitk::OdfVtkMapper2D<T,N>
::MitkRenderOpaqueGeometry(mitk::BaseRenderer* renderer)
{
if ( this->IsVisibleOdfs( renderer )==false )
return;
if ( this->GetVtkProp(renderer)->GetVisibility() )
{
// adapt cam pos
this->GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() );
}
}
template<class T, int N>
void mitk::OdfVtkMapper2D<T,N>
::MitkRenderTranslucentGeometry(mitk::BaseRenderer* renderer)
{
if ( this->IsVisibleOdfs(renderer)==false )
return;
if ( this->GetVtkProp(renderer)->GetVisibility() )
this->GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer());
}
template<class T, int N>
void mitk::OdfVtkMapper2D<T,N>
::Update(mitk::BaseRenderer* renderer)
{
bool visible = true;
GetDataNode()->GetVisibility(visible, renderer, "visible");
if ( !visible ) return;
mitk::Image::Pointer input = const_cast<mitk::Image*>( this->GetInput() );
if ( input.IsNull() ) return ;
std::string classname("TensorImage");
if(classname.compare(input->GetNameOfClass())==0)
m_VtkImage = dynamic_cast<mitk::TensorImage*>( this->GetInput() )->GetNonRgbVtkImageData();
std::string qclassname("OdfImage");
if(qclassname.compare(input->GetNameOfClass())==0)
m_VtkImage = dynamic_cast<mitk::OdfImage*>( this->GetInput() )->GetNonRgbVtkImageData();
std::string shclassname("ShImage");
if(shclassname.compare(input->GetNameOfClass())==0)
m_VtkImage = dynamic_cast<mitk::ShImage*>( this->GetInput() )->GetNonRgbVtkImageData();
if( m_VtkImage )
{
// make sure, that we have point data with more than 1 component (as vectors)
vtkPointData* pointData = m_VtkImage->GetPointData();
if ( pointData == nullptr )
{
itkWarningMacro( << "m_VtkImage->GetPointData() returns NULL!" );
return ;
}
if ( pointData->GetNumberOfArrays() == 0 )
{
itkWarningMacro( << "m_VtkImage->GetPointData()->GetNumberOfArrays() is 0!" );
return ;
}
else if ( pointData->GetArrayName( 0 ) == nullptr )
{
m_VtkImage->GetPointData()->GetArray(0)->SetName("vector");
}
GenerateDataForRenderer(renderer);
}
else
{
itkWarningMacro( << "m_VtkImage is NULL!" );
return ;
}
}
template<class T, int N>
void mitk::OdfVtkMapper2D<T,N>
::GenerateDataForRenderer( mitk::BaseRenderer *renderer )
{
LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer);
OdfDisplayGeometry dispGeo = MeasureDisplayedGeometry( renderer);
if ((localStorage->m_LastUpdateTime >= m_DataNode->GetMTime()) //was the node modified?
&& (localStorage->m_LastUpdateTime >= m_DataNode->GetPropertyList()->GetMTime()) //was a property modified?
&& (localStorage->m_LastUpdateTime >= m_DataNode->GetPropertyList(renderer)->GetMTime())
&& dispGeo.Equals(m_LastDisplayGeometry.at(GetIndex(renderer))))
{
return;
}
localStorage->m_LastUpdateTime.Modified();
if(!IsVisibleOdfs(renderer))
{
localStorage->m_OdfsActors[0]->VisibilityOff();
localStorage->m_OdfsActors[1]->VisibilityOff();
localStorage->m_OdfsActors[2]->VisibilityOff();
}
else
{
localStorage->m_OdfsActors[0]->VisibilityOn();
localStorage->m_OdfsActors[1]->VisibilityOn();
localStorage->m_OdfsActors[2]->VisibilityOn();
m_OdfSource->SetAdditionalScale(GetMinImageSpacing(GetIndex(renderer)));
ApplyPropertySettings();
Slice(renderer, dispGeo);
m_LastDisplayGeometry[GetIndex(renderer)] = dispGeo;
}
}
template<class T, int N>
double mitk::OdfVtkMapper2D<T,N>::GetMinImageSpacing( int index )
{
// Spacing adapted scaling
double spacing[3];
m_VtkImage->GetSpacing(spacing);
double min = spacing[0];
if(index==0)
{
min = spacing[0];
min = min > spacing[1] ? spacing[1] : min;
}
if(index==1)
{
min = spacing[1];
min = min > spacing[2] ? spacing[2] : min;
}
if(index==2)
{
min = spacing[0];
min = min > spacing[2] ? spacing[2] : min;
}
return min;
}
template<class T, int N>
void mitk::OdfVtkMapper2D<T,N>
::ApplyPropertySettings()
{
this->GetDataNode()->GetFloatProperty( "Scaling", m_Scaling );
this->GetDataNode()->GetIntProperty( "ShowMaxNumber", m_ShowMaxNumber );
OdfNormalizationMethodProperty* nmp = dynamic_cast<OdfNormalizationMethodProperty*>(this->GetDataNode()->GetProperty( "Normalization" ));
if(nmp)
m_Normalization = nmp->GetNormalization();
OdfScaleByProperty* sbp = dynamic_cast<OdfScaleByProperty*>(this->GetDataNode()->GetProperty( "ScaleBy" ));
if(sbp)
m_ScaleBy = sbp->GetScaleBy();
this->GetDataNode()->GetFloatProperty( "IndexParam1", m_IndexParam1);
this->GetDataNode()->GetFloatProperty( "IndexParam2", m_IndexParam2);
this->GetDataNode()->GetBoolProperty( "DiffusionCore.Rendering.OdfVtkMapper.SwitchTensorView", m_ToggleTensorEllipsoidView );
this->GetDataNode()->GetBoolProperty( "DiffusionCore.Rendering.OdfVtkMapper.ColourisationModeBit", m_ToggleColourisationMode );
this->GetDataNode()->GetBoolProperty( "DiffusionCore.Rendering.OdfVtkMapper.RandomModeBit", m_ToggleGlyphPlacementMode);
}
template <class T, int N>
bool mitk::OdfVtkMapper2D<T,N>
::IsPlaneRotated(mitk::BaseRenderer* renderer)
{
PlaneGeometry::ConstPointer worldPlaneGeometry = renderer->GetCurrentWorldPlaneGeometry();
double vnormal[ 3 ];
Vector3D normal = worldPlaneGeometry->GetNormal(); normal.Normalize();
vnl2vtk( normal.GetVnlVector(), vnormal );
mitk::Image* currentImage = dynamic_cast<mitk::Image* >( this->GetDataNode()->GetData() );
if( currentImage == nullptr )
return false;
mitk::Vector3D imageNormal0 = currentImage->GetSlicedGeometry()->GetAxisVector(0);
mitk::Vector3D imageNormal1 = currentImage->GetSlicedGeometry()->GetAxisVector(1);
mitk::Vector3D imageNormal2 = currentImage->GetSlicedGeometry()->GetAxisVector(2);
imageNormal0.Normalize();
imageNormal1.Normalize();
imageNormal2.Normalize();
double eps = 0.000001; // Did you mean: std::numeric_limits<T>::epsilon(); ?
int test = 0;
if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal0.GetVnlVector()))-1) > eps )
test++;
if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal1.GetVnlVector()))-1) > eps )
test++;
if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal2.GetVnlVector()))-1) > eps )
test++;
if (test==3)
return true;
return false;
}
template<class T, int N>
void mitk::OdfVtkMapper2D<T,N>
::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* /*renderer*/, bool /*overwrite*/)
{
node->SetProperty( "ShowMaxNumber", mitk::IntProperty::New( 500 ) );
node->SetProperty( "Normalization", mitk::OdfNormalizationMethodProperty::New());
mitk::OdfScaleByProperty::Pointer prop = mitk::OdfScaleByProperty::New();
prop->SetScaleByGFA();
node->SetProperty( "ScaleBy", prop);
if (dynamic_cast<mitk::TensorImage*>(node->GetData()))
{
node->AddProperty( "DiffusionCore.Rendering.OdfVtkMapper.ColourisationModeBit", mitk::BoolProperty::New( true ) );
node->SetProperty( "Scaling", mitk::FloatProperty::New( 3.0 ) );
}
else
{
node->AddProperty( "DiffusionCore.Rendering.OdfVtkMapper.ColourisationModeBit", mitk::BoolProperty::New( false ) );
node->SetProperty( "Scaling", mitk::FloatProperty::New( 1.5 ) );
}
node->SetProperty( "IndexParam1", mitk::FloatProperty::New(2));
node->SetProperty( "IndexParam2", mitk::FloatProperty::New(1));
node->SetProperty( "visible", mitk::BoolProperty::New( true ) );
node->SetProperty( "VisibleOdfs_T", mitk::BoolProperty::New( false ) );
node->SetProperty( "VisibleOdfs_C", mitk::BoolProperty::New( false ) );
node->SetProperty( "VisibleOdfs_S", mitk::BoolProperty::New( false ) );
node->SetProperty( "layer", mitk::IntProperty::New(100));
node->SetProperty( "DoRefresh", mitk::BoolProperty::New( true ) );
node->AddProperty( "DiffusionCore.Rendering.OdfVtkMapper.SwitchTensorView", mitk::BoolProperty::New( true) );
node->AddProperty( "DiffusionCore.Rendering.OdfVtkMapper.RandomModeBit", mitk::BoolProperty::New( true ) );
}
#endif // __mitkOdfVtkMapper2D_txx__
diff --git a/Modules/DiffusionCore/Rendering/mitkPeakImageMapper2D.cpp b/Modules/DiffusionCore/Rendering/mitkPeakImageMapper2D.cpp
index 585e4f4..d52ea1e 100644
--- a/Modules/DiffusionCore/Rendering/mitkPeakImageMapper2D.cpp
+++ b/Modules/DiffusionCore/Rendering/mitkPeakImageMapper2D.cpp
@@ -1,180 +1,180 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPeakImageMapper2D.h"
#include "mitkBaseRenderer.h"
#include "mitkDataNode.h"
#include <vtkActor.h>
#include <vtkOpenGLPolyDataMapper.h>
#include <vtkOpenGLHelper.h>
#include <vtkShaderProgram.h>
#include <vtkPlane.h>
#include <vtkPolyData.h>
#include <vtkPointData.h>
#include <vtkProperty.h>
#include <vtkLookupTable.h>
#include <vtkPoints.h>
#include <vtkCamera.h>
#include <vtkPolyLine.h>
#include <vtkRenderer.h>
#include <vtkCellArray.h>
#include <vtkMatrix4x4.h>
#include <vtkTubeFilter.h>
#include <mitkPlaneGeometry.h>
#include <mitkSliceNavigationController.h>
#include <mitkCoreServices.h>
mitk::PeakImageMapper2D::PeakImageMapper2D()
{
m_lut = vtkSmartPointer<vtkLookupTable>::New();
m_lut->Build();
}
mitk::PeakImageMapper2D::~PeakImageMapper2D()
{
}
mitk::PeakImage* mitk::PeakImageMapper2D::GetInput()
{
return dynamic_cast< mitk::PeakImage * > ( GetDataNode()->GetData() );
}
void mitk::PeakImageMapper2D::UpdateVtkTransform(mitk::BaseRenderer *)
{
// don't apply transform since the peak polydata is already in world coordinates.
return;
}
void mitk::PeakImageMapper2D::Update(mitk::BaseRenderer * renderer)
{
mitk::DataNode* node = this->GetDataNode();
if (node == nullptr)
return;
bool visible = true;
node->GetVisibility(visible, renderer, "visible");
if ( !visible )
return;
this->GenerateDataForRenderer( renderer );
}
// vtkActors and Mappers are feeded here
void mitk::PeakImageMapper2D::GenerateDataForRenderer(mitk::BaseRenderer *renderer)
{
mitk::PeakImage* peakImage = this->GetInput();
//the handler of local storage gets feeded in this method with requested data for related renderwindow
LocalStorage *localStorage = m_LocalStorageHandler.GetLocalStorage(renderer);
vtkSmartPointer<vtkPolyData> polyData = peakImage->GetPolyData();
if (polyData == nullptr)
return;
localStorage->m_Mapper->ScalarVisibilityOn();
localStorage->m_Mapper->SetScalarModeToUsePointFieldData();
localStorage->m_Mapper->SetLookupTable(m_lut); //apply the properties after the slice was set
localStorage->m_Mapper->SelectColorArray("FIBER_COLORS");
localStorage->m_Mapper->SetInputData(polyData);
mitk::SliceNavigationController::Pointer sliceContr = renderer->GetSliceNavigationController();
mitk::PlaneGeometry::ConstPointer planeGeo = sliceContr->GetCurrentPlaneGeometry();
mitk::Point3D plane_origin = planeGeo->GetOrigin();
mitk::DataNode* node = this->GetDataNode();
mitk::Image* image = dynamic_cast<mitk::Image*>(node->GetData());
mitk::Vector3D spacing = image->GetGeometry()->GetSpacing();
localStorage->m_Mapper->RemoveAllClippingPlanes();
float clipping_plane_thickness = 1;
if(spacing[0]<spacing[1] && spacing[0]<spacing[2])
clipping_plane_thickness = spacing[0];
else if (spacing[1] < spacing[2])
clipping_plane_thickness = spacing[1];
else
clipping_plane_thickness = spacing[2];
clipping_plane_thickness /= 2.0;
mitk::Vector3D plane_normal = planeGeo->GetNormal();
plane_normal.Normalize();
double vnormal[3];
double vp1[3];
double vp2[3];
vp1[0] = plane_origin[0] - plane_normal[0] * clipping_plane_thickness;
vp1[1] = plane_origin[1] - plane_normal[1] * clipping_plane_thickness;
vp1[2] = plane_origin[2] - plane_normal[2] * clipping_plane_thickness;
vp2[0] = plane_origin[0] + plane_normal[0] * clipping_plane_thickness;
vp2[1] = plane_origin[1] + plane_normal[1] * clipping_plane_thickness;
vp2[2] = plane_origin[2] + plane_normal[2] * clipping_plane_thickness;
{
vnormal[0] = vp2[0] - vp1[0];
vnormal[1] = vp2[1] - vp1[1];
vnormal[2] = vp2[2] - vp1[2];
vtkSmartPointer<vtkPlane> plane = vtkSmartPointer<vtkPlane>::New();
plane->SetOrigin(vp1);
plane->SetNormal(vnormal);
localStorage->m_Mapper->AddClippingPlane(plane);
}
{
vnormal[0] = vp1[0] - vp2[0];
vnormal[1] = vp1[1] - vp2[1];
vnormal[2] = vp1[2] - vp2[2];
vtkSmartPointer<vtkPlane> plane = vtkSmartPointer<vtkPlane>::New();
plane->SetOrigin(vp2);
plane->SetNormal(vnormal);
localStorage->m_Mapper->AddClippingPlane(plane);
}
localStorage->m_PointActor->SetMapper(localStorage->m_Mapper);
float linewidth = 1.0;
this->GetDataNode()->GetFloatProperty("shape.linewidth",linewidth);
localStorage->m_PointActor->GetProperty()->SetLineWidth(linewidth);
// We have been modified => save this for next Update()
localStorage->m_LastUpdateTime.Modified();
}
vtkProp* mitk::PeakImageMapper2D::GetVtkProp(mitk::BaseRenderer *renderer)
{
this->Update(renderer);
return m_LocalStorageHandler.GetLocalStorage(renderer)->m_PointActor;
}
void mitk::PeakImageMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite)
{
Superclass::SetDefaultProperties(node, renderer, overwrite);
//add other parameters to propertylist
node->AddProperty( "color", mitk::ColorProperty::New(1.0,1.0,1.0), renderer, overwrite);
node->AddProperty( "shape.linewidth", mitk::FloatProperty::New(1.0), renderer, overwrite);
}
mitk::PeakImageMapper2D::LocalStorage::LocalStorage()
{
m_PointActor = vtkSmartPointer<vtkActor>::New();
m_Mapper = vtkSmartPointer<MITKPeakImageMapper2D_POLYDATAMAPPER>::New();
}
diff --git a/Modules/DiffusionCore/Rendering/mitkPeakImageMapper2D.h b/Modules/DiffusionCore/Rendering/mitkPeakImageMapper2D.h
index 662dbe3..fad1508 100644
--- a/Modules/DiffusionCore/Rendering/mitkPeakImageMapper2D.h
+++ b/Modules/DiffusionCore/Rendering/mitkPeakImageMapper2D.h
@@ -1,86 +1,86 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 PeakImageMapper2D_H_HEADER_INCLUDED
#define PeakImageMapper2D_H_HEADER_INCLUDED
//MITK Rendering
#include <mitkCommon.h>
#include <mitkBaseRenderer.h>
#include <mitkVtkMapper.h>
#include <mitkPeakImage.h>
#include <vtkSmartPointer.h>
#include <MitkDiffusionCoreExports.h>
#define MITKPeakImageMapper2D_POLYDATAMAPPER vtkOpenGLPolyDataMapper
class vtkActor;
class mitkBaseRenderer;
class MITKPeakImageMapper2D_POLYDATAMAPPER;
class vtkCutter;
class vtkPlane;
class vtkPolyData;
namespace mitk {
struct IShaderRepository;
class MITKDIFFUSIONCORE_EXPORT PeakImageMapper2D : public VtkMapper
{
public:
mitkClassMacro(PeakImageMapper2D, VtkMapper)
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitk::PeakImage* GetInput();
void Update(mitk::BaseRenderer * renderer) override;
static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = nullptr, bool overwrite = false );
void UpdateVtkTransform(mitk::BaseRenderer *renderer) override;
vtkProp* GetVtkProp(mitk::BaseRenderer* renderer) override;
class LocalStorage : public mitk::Mapper::BaseLocalStorage
{
public:
vtkSmartPointer<vtkActor> m_PointActor;
vtkSmartPointer<MITKPeakImageMapper2D_POLYDATAMAPPER> m_Mapper;
itk::TimeStamp m_LastUpdateTime;
LocalStorage();
~LocalStorage() override
{
}
};
/** \brief This member holds all three LocalStorages for the three 2D render windows. */
mitk::LocalStorageHandler<LocalStorage> m_LocalStorageHandler;
protected:
PeakImageMapper2D();
~PeakImageMapper2D() override;
void GenerateDataForRenderer(mitk::BaseRenderer*) override;
private:
vtkSmartPointer<vtkLookupTable> m_lut;
};
}//end namespace
#endif
diff --git a/Modules/DiffusionCore/Rendering/mitkPeakImageMapper3D.cpp b/Modules/DiffusionCore/Rendering/mitkPeakImageMapper3D.cpp
index b1279f8..d5996df 100644
--- a/Modules/DiffusionCore/Rendering/mitkPeakImageMapper3D.cpp
+++ b/Modules/DiffusionCore/Rendering/mitkPeakImageMapper3D.cpp
@@ -1,195 +1,195 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPeakImageMapper3D.h"
#include "mitkBaseRenderer.h"
#include "mitkDataNode.h"
#include <vtkActor.h>
#include <vtkOpenGLPolyDataMapper.h>
#include <vtkOpenGLHelper.h>
#include <vtkShaderProgram.h>
#include <vtkPlane.h>
#include <vtkPolyData.h>
#include <vtkPointData.h>
#include <vtkProperty.h>
#include <vtkLookupTable.h>
#include <vtkPoints.h>
#include <vtkCamera.h>
#include <vtkPolyLine.h>
#include <vtkRenderer.h>
#include <vtkCellArray.h>
#include <vtkMatrix4x4.h>
#include <vtkTubeFilter.h>
#include <mitkPlaneGeometry.h>
#include <mitkSliceNavigationController.h>
#include <mitkCoreServices.h>
#include <mitkClippingProperty.h>
mitk::PeakImageMapper3D::PeakImageMapper3D()
{
m_lut = vtkSmartPointer<vtkLookupTable>::New();
m_lut->Build();
}
mitk::PeakImageMapper3D::~PeakImageMapper3D()
{
}
mitk::PeakImage* mitk::PeakImageMapper3D::GetInput()
{
return dynamic_cast< mitk::PeakImage * > ( GetDataNode()->GetData() );
}
void mitk::PeakImageMapper3D::UpdateVtkTransform(mitk::BaseRenderer *)
{
// don't apply transform since the peak polydata is already in world coordinates.
return;
}
void mitk::PeakImageMapper3D::Update(mitk::BaseRenderer * renderer)
{
mitk::DataNode* node = this->GetDataNode();
if (node == nullptr)
return;
bool visible = true;
node->GetVisibility(visible, renderer, "visible");
if ( !visible )
return;
this->GenerateDataForRenderer( renderer );
}
// vtkActors and Mappers are feeded here
void mitk::PeakImageMapper3D::GenerateDataForRenderer(mitk::BaseRenderer *renderer)
{
//the handler of local storage gets feeded in this method with requested data for related renderwindow
LocalStorage *localStorage = m_LocalStorageHandler.GetLocalStorage(renderer);
bool enabled = false;
this->GetDataNode()->GetBoolProperty("Enable3DPeaks",enabled);
if (!enabled)
{
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
localStorage->m_Mapper->SetInputData(polyData);
localStorage->m_Actor->SetMapper(localStorage->m_Mapper);
localStorage->m_Assembly->AddPart(localStorage->m_Actor);
return;
}
mitk::PeakImage* peakImage = this->GetInput();
vtkSmartPointer<vtkPolyData> polyData = peakImage->GetPolyData();
if (polyData == nullptr)
return;
float linewidth = 1.0;
this->GetDataNode()->GetFloatProperty("shape.linewidth",linewidth);
localStorage->m_Mapper->SetInputData(polyData);
localStorage->m_Mapper->SelectColorArray("FIBER_COLORS");
localStorage->m_Mapper->ScalarVisibilityOn();
localStorage->m_Mapper->SetScalarModeToUsePointFieldData();
localStorage->m_Actor->SetMapper(localStorage->m_Mapper);
localStorage->m_Mapper->SetLookupTable(m_lut);
localStorage->m_Actor->GetProperty()->SetLineWidth(linewidth);
localStorage->m_Assembly->AddPart(localStorage->m_Actor);
const DataNode* node = this->GetDataNode();
mitk::ClippingProperty* prop = dynamic_cast<mitk::ClippingProperty*>(node->GetProperty("3DClipping"));
mitk::Image* image = dynamic_cast<mitk::Image*>(node->GetData());
localStorage->m_Mapper->RemoveAllClippingPlanes();
mitk::Vector3D spacing = image->GetGeometry()->GetSpacing();
double clipping_plane_thickness = 1;
if(spacing[0]<spacing[1] && spacing[0]<spacing[2])
clipping_plane_thickness = spacing[0];
else if (spacing[1] < spacing[2])
clipping_plane_thickness = spacing[1];
else
clipping_plane_thickness = spacing[2];
clipping_plane_thickness /= 2.0;
mitk::Vector3D plane_normal = prop->GetNormal();
if (plane_normal.GetNorm()>0.0)
{
plane_normal.Normalize();
mitk::Point3D plane_origin = prop->GetOrigin();
double vnormal[3];
double vp1[3];
double vp2[3];
vp1[0] = plane_origin[0] + plane_normal[0] * clipping_plane_thickness;
vp1[1] = plane_origin[1] + plane_normal[1] * clipping_plane_thickness;
vp1[2] = plane_origin[2] + plane_normal[2] * clipping_plane_thickness;
vp2[0] = plane_origin[0] - plane_normal[0] * clipping_plane_thickness;
vp2[1] = plane_origin[1] - plane_normal[1] * clipping_plane_thickness;
vp2[2] = plane_origin[2] - plane_normal[2] * clipping_plane_thickness;
{
vnormal[0] = vp2[0] - vp1[0];
vnormal[1] = vp2[1] - vp1[1];
vnormal[2] = vp2[2] - vp1[2];
vtkSmartPointer<vtkPlane> plane = vtkSmartPointer<vtkPlane>::New();
plane->SetOrigin(vp1);
plane->SetNormal(vnormal);
localStorage->m_Mapper->AddClippingPlane(plane);
}
{
vnormal[0] = vp1[0] - vp2[0];
vnormal[1] = vp1[1] - vp2[1];
vnormal[2] = vp1[2] - vp2[2];
vtkSmartPointer<vtkPlane> plane = vtkSmartPointer<vtkPlane>::New();
plane->SetOrigin(vp2);
plane->SetNormal(vnormal);
localStorage->m_Mapper->AddClippingPlane(plane);
}
}
// We have been modified => save this for next Update()
localStorage->m_LastUpdateTime.Modified();
}
vtkProp* mitk::PeakImageMapper3D::GetVtkProp(mitk::BaseRenderer *renderer)
{
return m_LocalStorageHandler.GetLocalStorage(renderer)->m_Assembly;
}
void mitk::PeakImageMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite)
{
Superclass::SetDefaultProperties(node, renderer, overwrite);
mitk::Vector3D plane_vec; plane_vec.Fill(0.0);
mitk::Point3D plane_origin; plane_origin.Fill(0.0);
node->AddProperty( "3DClipping", mitk::ClippingProperty::New( plane_origin, plane_vec ), renderer, overwrite );
node->AddProperty( "3DClippingPlaneId", mitk::IntProperty::New(-1), renderer, overwrite );
node->AddProperty( "3DClippingPlaneFlip", mitk::BoolProperty::New( false ), renderer, overwrite );
node->AddProperty( "Enable3DPeaks", mitk::BoolProperty::New( false ), renderer, overwrite );
}
mitk::PeakImageMapper3D::LocalStorage::LocalStorage()
{
m_Actor = vtkSmartPointer<vtkActor>::New();
m_Mapper = vtkSmartPointer<MITKPeakImageMapper3D_POLYDATAMAPPER>::New();
m_Assembly = vtkSmartPointer<vtkPropAssembly>::New();
}
diff --git a/Modules/DiffusionCore/Rendering/mitkPeakImageMapper3D.h b/Modules/DiffusionCore/Rendering/mitkPeakImageMapper3D.h
index e8cfab2..4b67c41 100644
--- a/Modules/DiffusionCore/Rendering/mitkPeakImageMapper3D.h
+++ b/Modules/DiffusionCore/Rendering/mitkPeakImageMapper3D.h
@@ -1,86 +1,86 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 PeakImageMapper3D_H_HEADER_INCLUDED
#define PeakImageMapper3D_H_HEADER_INCLUDED
//MITK Rendering
#include <mitkCommon.h>
#include <mitkBaseRenderer.h>
#include <mitkVtkMapper.h>
#include <mitkPeakImage.h>
#include <vtkSmartPointer.h>
#include <MitkDiffusionCoreExports.h>
#define MITKPeakImageMapper3D_POLYDATAMAPPER vtkOpenGLPolyDataMapper
class vtkActor;
class mitkBaseRenderer;
class MITKPeakImageMapper3D_POLYDATAMAPPER;
class vtkCutter;
class vtkPlane;
class vtkPolyData;
namespace mitk {
struct IShaderRepository;
class MITKDIFFUSIONCORE_EXPORT PeakImageMapper3D : public VtkMapper
{
public:
mitkClassMacro(PeakImageMapper3D, VtkMapper)
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
mitk::PeakImage* GetInput();
void Update(mitk::BaseRenderer * renderer) override;
static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = nullptr, bool overwrite = false );
void UpdateVtkTransform(mitk::BaseRenderer *renderer) override;
vtkProp* GetVtkProp(mitk::BaseRenderer* renderer) override;
class LocalStorage : public mitk::Mapper::BaseLocalStorage
{
public:
vtkSmartPointer<vtkActor> m_Actor;
vtkSmartPointer<MITKPeakImageMapper3D_POLYDATAMAPPER> m_Mapper;
vtkSmartPointer<vtkPropAssembly> m_Assembly;
itk::TimeStamp m_LastUpdateTime;
LocalStorage();
~LocalStorage() override
{
}
};
mitk::LocalStorageHandler<LocalStorage> m_LocalStorageHandler;
protected:
PeakImageMapper3D();
~PeakImageMapper3D() override;
void GenerateDataForRenderer(mitk::BaseRenderer*) override;
private:
vtkSmartPointer<vtkLookupTable> m_lut;
};
}//end namespace
#endif
diff --git a/Modules/DiffusionCore/Rendering/mitkVectorImageVtkGlyphMapper3D.cpp b/Modules/DiffusionCore/Rendering/mitkVectorImageVtkGlyphMapper3D.cpp
index f22c886..ed1bab2 100644
--- a/Modules/DiffusionCore/Rendering/mitkVectorImageVtkGlyphMapper3D.cpp
+++ b/Modules/DiffusionCore/Rendering/mitkVectorImageVtkGlyphMapper3D.cpp
@@ -1,219 +1,219 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkVectorImageVtkGlyphMapper3D.h"
#include <vtkMaskedGlyph3D.h>
#include <vtkActor.h>
#include <vtkPolyDataMapper.h>
#include <vtkArrowSource.h>
#include <vtkLineSource.h>
#include <vtkImageData.h>
#include <vtkPolyData.h>
#include <vtkPointData.h>
#include <vtkLookupTable.h>
#include <mitkLookupTable.h>
#include <mitkLookupTableProperty.h>
/*
* Constructor. Doesn't do anything...
*/
mitk::VectorImageVtkGlyphMapper3D::VectorImageVtkGlyphMapper3D()
{
m_RandomMode = true;
m_UseMaskPoints = true;
m_MaximumNumberOfPoints = 5000;
m_GlyphType = ArrowGlyph;
m_Glyph3DGenerator = vtkMaskedGlyph3D::New();
m_Glyph3DMapper = vtkPolyDataMapper::New();
m_Glyph3DActor = vtkActor::New();
}
vtkProp* mitk::VectorImageVtkGlyphMapper3D::GetVtkProp(mitk::BaseRenderer* /*renderer*/)
{
return m_Glyph3DActor;
}
/*
* Destructor
*/
mitk::VectorImageVtkGlyphMapper3D::~VectorImageVtkGlyphMapper3D()
{
if ( m_Glyph3DMapper != nullptr )
m_Glyph3DMapper->Delete();
if ( m_Glyph3DGenerator != nullptr )
m_Glyph3DGenerator->Delete();
}
/*
* Generate a vtkPolyData by creating vectors as glyphs
* This method is called, each time a specific renderer is updated.
*/
void mitk::VectorImageVtkGlyphMapper3D::GenerateDataForRenderer( mitk::BaseRenderer* renderer )
{
bool visible = true;
GetDataNode()->GetVisibility(visible, renderer, "visible");
if ( !visible )
{
if ( m_Glyph3DActor != nullptr )
m_Glyph3DActor->VisibilityOff();
return ;
}
else
{
if ( m_Glyph3DActor != nullptr )
m_Glyph3DActor->VisibilityOn();
}
BaseLocalStorage *ls = m_LSH.GetLocalStorage(renderer);
bool needGenerateData = ls->IsGenerateDataRequired( renderer, this, GetDataNode() );
if(!needGenerateData)
{
return;
}
ls->UpdateGenerateDataTime();
//
// get the input image...
//
mitk::Image::Pointer mitkImage = this->GetInput();
if ( mitkImage.GetPointer() == nullptr )
{
itkWarningMacro( << "VectorImage is null !" );
return;
}
//
// make sure, that the input image is an vector image
//
if ( mitkImage->GetPixelType().GetNumberOfComponents() <= 1 )
{
itkWarningMacro( << "VectorImage has only one scalar component!" );
return ;
}
vtkImageData* vtkImage = mitkImage->GetVtkImageData();
//
// make sure, that we have point data with more than 1 component (as vectors)
//
vtkPointData* pointData = vtkImage->GetPointData();
if ( pointData == nullptr )
{
itkWarningMacro( << "vtkImage->GetPointData() returns nullptr!" );
return ;
}
if ( pointData->GetNumberOfArrays() == 0 )
{
itkWarningMacro( << "vtkImage->GetPointData()->GetNumberOfArrays() is 0!" );
return ;
}
else if ( pointData->GetArrayName( 0 ) == nullptr )
{
vtkImage->GetPointData() ->GetArray( 0 ) ->SetName( "vector" );
}
if ( vtkImage->GetNumberOfPoints() != 0 )
{
//
// create the glyph, which has to be shown at each point
// of the masked image
//
vtkPolyData* glyph;
if ( m_GlyphType == LineGlyph )
{
vtkLineSource * lineSource = vtkLineSource::New();
lineSource->Update();
glyph = lineSource->GetOutput();
}
else if ( m_GlyphType == ArrowGlyph )
{
vtkArrowSource * arrowSource = vtkArrowSource::New();
arrowSource->Update();
glyph = arrowSource->GetOutput();
}
else
{
// Use a vtkLineSource as default, if the GlyphType is
// unknown
itkWarningMacro( << "unknown glyph type!" );
vtkLineSource * lineSource = vtkLineSource::New();
lineSource->Update();
glyph = lineSource->GetOutput();
}
m_RandomMode = false;
m_UseMaskPoints = false;
m_MaximumNumberOfPoints = 80*80*80;
//
// set up the actual glyphing filter
//
m_Glyph3DGenerator->SetSourceData( glyph );
m_Glyph3DGenerator->SetInput( vtkImage );
//m_Glyph3DGenerator->SetInputConnection(m_Cutter->GetOutputPort());
m_Glyph3DGenerator->SetInputArrayToProcess (1, 0,0, vtkDataObject::FIELD_ASSOCIATION_POINTS , "vector");
//m_Glyph3DGenerator->SelectInputVectors( vtkImage->GetPointData() ->GetArray( 0 ) ->GetName() );
m_Glyph3DGenerator->OrientOn();
m_Glyph3DGenerator->SetVectorModeToUseVector();
m_Glyph3DGenerator->SetScaleFactor( 0.00392156862745 );
m_Glyph3DGenerator->SetScaleModeToScaleByVector();
m_Glyph3DGenerator->SetUseMaskPoints( m_UseMaskPoints );
m_Glyph3DGenerator->SetRandomMode( m_RandomMode );
m_Glyph3DGenerator->SetMaximumNumberOfPoints( m_MaximumNumberOfPoints );
m_Glyph3DGenerator->Update();
m_Glyph3DMapper->SetInputConnection( m_Glyph3DGenerator->GetOutputPort() );
m_Glyph3DActor->SetMapper( m_Glyph3DMapper );
if (GetDataNode()->GetProperty("LookupTable"))
{
mitk::LookupTable::Pointer mitkLookupTable = mitk::LookupTable::New();
m_Glyph3DMapper->Update();
mitkLookupTable->SetVtkLookupTable(dynamic_cast<vtkLookupTable*>(m_Glyph3DMapper->GetLookupTable()));
mitk::LookupTableProperty::Pointer LookupTableProp = mitk::LookupTableProperty::New( mitkLookupTable );
GetDataNode()->SetProperty( "LookupTable", LookupTableProp );
}
else
{
mitk::LookupTableProperty::Pointer mitkLutProp = dynamic_cast<mitk::LookupTableProperty*>(GetDataNode()->GetProperty("LookupTable"));
if (mitkLutProp.IsNotNull())
m_Glyph3DMapper->SetLookupTable( mitkLutProp->GetLookupTable()->GetVtkLookupTable() );
}
//vtkDataSetWriter* writer = vtkDataSetWriter::New();
//writer->SetInput( vtkImage );
//writer->SetFileName( "out.vtk" );
//writer->Update();
}
}
/*
* Returns the input data object of the given filter. In this
* case, a mitk::Image is returned.
*/
mitk::Image* mitk::VectorImageVtkGlyphMapper3D::GetInput()
{
return dynamic_cast<mitk::Image*>( GetDataNode()->GetData() );
}
diff --git a/Modules/DiffusionCore/Rendering/mitkVectorImageVtkGlyphMapper3D.h b/Modules/DiffusionCore/Rendering/mitkVectorImageVtkGlyphMapper3D.h
index 9e1b114..6df60d9 100644
--- a/Modules/DiffusionCore/Rendering/mitkVectorImageVtkGlyphMapper3D.h
+++ b/Modules/DiffusionCore/Rendering/mitkVectorImageVtkGlyphMapper3D.h
@@ -1,99 +1,99 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_VECTOR_IMAGE_VTK_MAPPER_3D__H
#define _MITK_VECTOR_IMAGE_VTK_MAPPER_3D__H
#include <MitkDiffusionCoreExports.h>
#include "mitkVtkMapper.h"
#include "mitkImage.h"
class vtkMaskedGlyph3D;
class vtkActor;
class vtkPolyDataMapper;
class vtkMaskPoints;
namespace mitk
{
class MITKDIFFUSIONCORE_EXPORT VectorImageVtkGlyphMapper3D : public VtkMapper
{
public:
mitkClassMacro( VectorImageVtkGlyphMapper3D, VtkMapper );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
enum GlyphType {LineGlyph, ArrowGlyph};
itkSetMacro(MaximumNumberOfPoints, unsigned int);
itkGetMacro(MaximumNumberOfPoints, unsigned int);
itkSetMacro(UseMaskPoints, bool);
itkGetMacro(UseMaskPoints, bool);
itkBooleanMacro(UseMaskPoints);
itkSetMacro(RandomMode, bool);
itkGetMacro(RandomMode, bool);
itkBooleanMacro(RandomMode);
vtkProp* GetVtkProp(mitk::BaseRenderer* renderer) override;
LocalStorageHandler<BaseLocalStorage> m_LSH;
protected:
/**
* Constructor. Doesn't do anything...
*/
VectorImageVtkGlyphMapper3D();
/**
* Destructor
*/
~VectorImageVtkGlyphMapper3D() override;
/**
* Generate a vtkPolyData by creating vectors as glyphs
* This method is called, each time a specific renderer is updated.
*/
void GenerateDataForRenderer( mitk::BaseRenderer* renderer ) override;
/**
* Returns the input data object of the given filter. In this
* case, a mitk::Image is returned.
*/
Image* GetInput();
vtkMaskedGlyph3D* m_Glyph3DGenerator;
vtkActor* m_Glyph3DActor;
vtkPolyDataMapper* m_Glyph3DMapper;
GlyphType m_GlyphType;
unsigned int m_MaximumNumberOfPoints;
bool m_UseMaskPoints;
bool m_RandomMode;
};
} //end of namespace mitk
#endif
diff --git a/Modules/DiffusionCore/Rendering/vtkMaskedProgrammableGlyphFilter.cpp b/Modules/DiffusionCore/Rendering/vtkMaskedProgrammableGlyphFilter.cpp
index 819590f..a8b058c 100644
--- a/Modules/DiffusionCore/Rendering/vtkMaskedProgrammableGlyphFilter.cpp
+++ b/Modules/DiffusionCore/Rendering/vtkMaskedProgrammableGlyphFilter.cpp
@@ -1,100 +1,100 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "vtkMaskedProgrammableGlyphFilter.h"
#include "vtkMaskPoints.h"
#include "vtkObjectFactory.h"
#include "vtkPolyData.h"
vtkStandardNewMacro(vtkMaskedProgrammableGlyphFilter);
vtkMaskedProgrammableGlyphFilter::vtkMaskedProgrammableGlyphFilter()
{
//this->SetColorModeToColorByScalar();
//this->SetScaleModeToScaleByVector();
this->MaskPoints = vtkMaskPoints::New();
this->MaximumNumberOfPoints = 5000;
this->UseMaskPoints = 1;
}
vtkMaskedProgrammableGlyphFilter::~vtkMaskedProgrammableGlyphFilter()
{
if(this->MaskPoints)
{
this->MaskPoints->Delete();
}
}
void vtkMaskedProgrammableGlyphFilter::SetInput(vtkDataSet *input)
{
this->MaskPoints->SetInputData(input);
this->Superclass::SetInputData(this->MaskPoints->GetOutput());
}
void vtkMaskedProgrammableGlyphFilter::SetRandomMode(int mode)
{
this->MaskPoints->SetRandomMode(mode);
}
int vtkMaskedProgrammableGlyphFilter::GetRandomMode()
{
return this->MaskPoints->GetRandomMode();
}
int vtkMaskedProgrammableGlyphFilter::RequestData(
vtkInformation *request,
vtkInformationVector **inputVector,
vtkInformationVector *outputVector)
{
if (this->UseMaskPoints)
{
vtkIdType numPts = this->MaskPoints->GetPolyDataInput(0)->GetNumberOfPoints();
this->MaskPoints->SetMaximumNumberOfPoints(MaximumNumberOfPoints);
this->MaskPoints->SetOnRatio(numPts / MaximumNumberOfPoints);
this->Superclass::SetInputConnection(this->MaskPoints->GetOutputPort());
this->MaskPoints->Update();
}
else
{
this->Superclass::SetInputData(this->MaskPoints->GetInput());
}
return this->Superclass::RequestData(
request,inputVector,outputVector);
}
void vtkMaskedProgrammableGlyphFilter::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
//os << indent << "InputScalarsSelection: "
// << (this->InputScalarsSelection ? this->InputScalarsSelection : "(none)")
// << endl;
//os << indent << "InputVectorsSelection: "
// << (this->InputVectorsSelection ? this->InputVectorsSelection : "(none)")
// << endl;
//os << indent << "InputNormalsSelection: "
// << (this->InputNormalsSelection ? this->InputNormalsSelection : "(none)")
// << endl;
os << indent << "MaximumNumberOfPoints: " << this->GetMaximumNumberOfPoints()
<< endl;
os << indent << "UseMaskPoints: " << (this->UseMaskPoints?"on":"off") << endl;
}
diff --git a/Modules/DiffusionCore/Rendering/vtkMaskedProgrammableGlyphFilter.h b/Modules/DiffusionCore/Rendering/vtkMaskedProgrammableGlyphFilter.h
index 6a2578e..31e39d4 100644
--- a/Modules/DiffusionCore/Rendering/vtkMaskedProgrammableGlyphFilter.h
+++ b/Modules/DiffusionCore/Rendering/vtkMaskedProgrammableGlyphFilter.h
@@ -1,114 +1,114 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __vtkMaskedProgrammableGlyphFilter_h
#define __vtkMaskedProgrammableGlyphFilter_h
#include <MitkDiffusionCoreExports.h>
#include "vtkProgrammableGlyphFilter.h"
#include "mitkBaseGeometry.h"
class vtkMaskPoints;
/**
* This class masked points of the input data set and glyphs
* only the selected poitns. Points may be selected either by
* random or by ratio.
* Additionally, this class allows to set the InputScalars,
* InputVectors and InputNormals by their field name in the
* input dataset.
*/
class MITKDIFFUSIONCORE_EXPORT vtkMaskedProgrammableGlyphFilter : public vtkProgrammableGlyphFilter
{
public:
vtkTypeMacro(vtkMaskedProgrammableGlyphFilter,vtkProgrammableGlyphFilter);
void PrintSelf(ostream& os, vtkIndent indent) override;
/**
* Constructor
*/
static vtkMaskedProgrammableGlyphFilter *New();
/**
* Limit the number of points to glyph
*/
vtkSetMacro(MaximumNumberOfPoints, int);
vtkGetMacro(MaximumNumberOfPoints, int);
/**
* Set the input to this filter.
*/
virtual void SetInput(vtkDataSet *input);
/**
* Set/get whether to mask points
*/
vtkSetMacro(UseMaskPoints, int);
vtkGetMacro(UseMaskPoints, int);
/**
* Set/get flag to cause randomization of which points to mask.
*/
void SetRandomMode(int mode);
int GetRandomMode();
///**
// * If you want to use an arbitrary scalars array, then set its name here.
// * By default this in nullptr and the filter will use the active scalar array.
// */
//vtkGetStringMacro(InputScalarsSelection);
//void SelectInputScalars(const char *fieldName)
// {this->SetInputScalarsSelection(fieldName);}
///**
// * If you want to use an arbitrary vectors array, then set its name here.
// * By default this in nullptr and the filter will use the active vector array.
// */
//vtkGetStringMacro(InputVectorsSelection);
//void SelectInputVectors(const char *fieldName)
// {this->SetInputVectorsSelection(fieldName);}
///**
// * If you want to use an arbitrary normals array, then set its name here.
// * By default this in nullptr and the filter will use the active normal array.
// */
//vtkGetStringMacro(InputNormalsSelection);
//void SelectInputNormals(const char *fieldName)
// {this->SetInputNormalsSelection(fieldName);}
void SetGeometry(mitk::BaseGeometry::Pointer geo)
{ this->m_Geometry = geo; }
mitk::BaseGeometry::Pointer GetGeometry()
{ return this->m_Geometry; }
protected:
vtkMaskedProgrammableGlyphFilter();
~vtkMaskedProgrammableGlyphFilter() override;
int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *) override;
vtkMaskPoints *MaskPoints;
int MaximumNumberOfPoints;
int UseMaskPoints;
mitk::BaseGeometry::Pointer m_Geometry;
private:
vtkMaskedProgrammableGlyphFilter(const vtkMaskedProgrammableGlyphFilter&); // Not implemented.
void operator=(const vtkMaskedProgrammableGlyphFilter&); // Not implemented.
};
#endif
diff --git a/Modules/DiffusionCore/Rendering/vtkOdfSource.h b/Modules/DiffusionCore/Rendering/vtkOdfSource.h
index 3edb4ae..73fd378 100644
--- a/Modules/DiffusionCore/Rendering/vtkOdfSource.h
+++ b/Modules/DiffusionCore/Rendering/vtkOdfSource.h
@@ -1,85 +1,85 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __vtkOdfSource_h
#define __vtkOdfSource_h
#include <MitkDiffusionCoreExports.h>
#include "vtkPolyDataAlgorithm.h"
#include "mitkCommon.h"
#include <vtkFloatArray.h>
#include <itkOrientationDistributionFunction.h>
#include <mitkOdfNormalizationMethodProperty.h>
class MITKDIFFUSIONCORE_EXPORT vtkOdfSource : public vtkPolyDataAlgorithm
{
public:
vtkTypeMacro(vtkOdfSource,vtkPolyDataAlgorithm);
void PrintSelf(ostream& os, vtkIndent indent) override;
typedef itk::OrientationDistributionFunction<float, ODF_SAMPLING_SIZE> OdfType;
// Description:
// Construct sphere with radius=0.5 and default resolution 8 in both Phi
// and Theta directions. Theta ranges from (0,360) and phi (0,180) degrees.
static vtkOdfSource *New();
vtkSetMacro(Scale,double)
vtkGetMacro(Scale,double)
vtkSetMacro(AdditionalScale,double)
vtkGetMacro(AdditionalScale,double)
vtkSetMacro(Normalization,int)
vtkGetMacro(Normalization,int)
vtkSetMacro(Odf,OdfType)
vtkGetMacro(Odf,OdfType)
vtkSetMacro(UseCustomColor,bool)
vtkGetMacro(UseCustomColor,bool)
void SetColor(int r, int g, int b)
{
this->r = r;
this->g = g;
this->b = b;
}
protected:
vtkOdfSource();
~vtkOdfSource() override;
int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *) override;
int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *) override;
OdfType Odf;
double Scale;
double AdditionalScale;
int Normalization;
int r;
int g;
int b;
bool UseCustomColor;
vtkSmartPointer<vtkLookupTable> lut;
private:
vtkOdfSource(const vtkOdfSource&); // Not implemented.
void operator=(const vtkOdfSource&); // Not implemented.
};
#endif //__vtkOdfSource_h
diff --git a/Modules/DiffusionCore/Rendering/vtkThickPlane.h b/Modules/DiffusionCore/Rendering/vtkThickPlane.h
index a8e4c13..27db258 100644
--- a/Modules/DiffusionCore/Rendering/vtkThickPlane.h
+++ b/Modules/DiffusionCore/Rendering/vtkThickPlane.h
@@ -1,96 +1,96 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// .NAME vtkPlane - perform various plane computations
// .SECTION Description
// vtkPlane provides methods for various plane computations. These include
// projecting points onto a plane, evaluating the plane equation, and
// returning plane normal. vtkPlane is a concrete implementation of the
// abstract class vtkImplicitFunction.
#ifndef __vtkThickPlane_h
#define __vtkThickPlane_h
#include <MitkDiffusionCoreExports.h>
#include "vtkImplicitFunction.h"
#include "mitkCommon.h"
class MITKDIFFUSIONCORE_EXPORT vtkThickPlane : public vtkImplicitFunction
{
public:
// Description
// Construct plane passing through origin and normal to z-axis.
static vtkThickPlane *New();
vtkTypeMacro(vtkThickPlane,vtkImplicitFunction);
void PrintSelf(ostream& os, vtkIndent indent) override;
// Description
// Evaluate plane equation for point x[3].
double EvaluateFunction(double x[3]) override;
void EvaluateFunction(vtkDataArray* input, vtkDataArray* output) override;
double EvaluateFunction(double x, double y, double z) override;
// Description
// Evaluate function gradient at point x[3].
void EvaluateGradient(double x[3], double g[3]) override;
// Description:
// Set/get plane normal. Plane is defined by point and normal.
virtual void SetPose (double _n1, double _n2, double _n3, double _o1, double _o2, double _o3);
virtual void SetPose (double _n[3], double _o[3]);
vtkGetVectorMacro(Normal,double,3);
vtkGetVectorMacro(Origin,double,3);
// Description:
// Set/get point through which plane passes. Plane is defined by point
// and normal.
virtual void SetThickness (double _arg);
vtkGetMacro(Thickness,double);
int count;
protected:
vtkThickPlane();
~vtkThickPlane() override {};
// Description:
// Set/get plane normal. Plane is defined by point and normal.
virtual void SetNormal (double _arg1, double _arg2, double _arg3);
virtual void SetNormal (double _arg[3]);
// Description:
// Set/get point through which plane passes. Plane is defined by point
// and normal.
virtual void SetOrigin (double _arg1, double _arg2, double _arg3);
virtual void SetOrigin (double _arg[3]);
double Normal[3];
double Origin[3];
double Thickness;
double Distance;
private:
vtkThickPlane(const vtkThickPlane&); // Not implemented.
void operator=(const vtkThickPlane&); // Not implemented.
};
#endif
diff --git a/Modules/DiffusionCore/Testing/mitkB0ExtractionToSeparateImagesFilterTest.cpp b/Modules/DiffusionCore/Testing/mitkB0ExtractionToSeparateImagesFilterTest.cpp
index be0bea1..6282ef8 100644
--- a/Modules/DiffusionCore/Testing/mitkB0ExtractionToSeparateImagesFilterTest.cpp
+++ b/Modules/DiffusionCore/Testing/mitkB0ExtractionToSeparateImagesFilterTest.cpp
@@ -1,109 +1,109 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkTestingMacros.h"
#include "itkVectorImage.h"
#include "mitkBaseData.h"
#include "mitkBaseDataIOFactory.h"
#include "mitkImageWriter.h"
#include "itkImageFileWriter.h"
#include "itkB0ImageExtractionToSeparateImageFilter.h"
#include "mitkDiffusionCoreObjectFactory.h"
/** Documentation
* Test for factory registration
*/
int mitkB0ExtractionToSeparateImagesFilterTest(int argc , char* argv[])
{
// always start with this!
MITK_TEST_BEGIN("mitkB0ExtractionToSeparateImagesFilterTest");
MITK_TEST_CONDITION_REQUIRED(argc > 2, "Test image is specified. ");
typedef short DiffusionPixelType;
typedef mitk::Image DiffusionImageType;
typedef mitk::NrrdDiffusionImageReader< DiffusionPixelType> DiffusionNrrdReaderType;
RegisterDiffusionImagingObjectFactory();
std::string inputFileName( argv[1] );
std::vector<mitk::BaseData::Pointer> inputBaseDataVector = mitk::BaseDataIO::LoadBaseDataFromFile( inputFileName, "","",false);
MITK_TEST_CONDITION_REQUIRED( inputBaseDataVector.size() > 0, "BaseDataIO returned non-empty vector.");
mitk::BaseData::Pointer baseData = inputBaseDataVector.at(0);
MITK_TEST_CONDITION_REQUIRED( baseData.IsNotNull(), "BaseData is not null")
DiffusionImageType* vols = dynamic_cast< DiffusionImageType* >(baseData.GetPointer());
MITK_TEST_CONDITION_REQUIRED( vols != nullptr, "Casting basedata to diffusion image successfull." );
// filter
typedef itk::B0ImageExtractionToSeparateImageFilter< short, short> FilterType;
typename FilterType::Pointer filter = FilterType::New();
MITK_TEST_CONDITION_REQUIRED(filter.IsNotNull(), "Filter instance created. ");
filter->SetInput(vols->GetVectorImage());
filter->SetDirections(vols->GetDirections());
filter->Update();
// output
mitk::Image::Pointer mitkImage = mitk::Image::New();
MITK_TEST_CONDITION_REQUIRED( mitkImage.IsNotNull(), "mitkImage not null." );
mitkImage->InitializeByItk( filter->GetOutput() );
MITK_TEST_CONDITION_REQUIRED( mitkImage->GetDimension()==4, "Output image is a 4D image.");
mitkImage->SetImportChannel( filter->GetOutput()->GetBufferPointer() );
mitk::LocaleSwitch localeSwitch("C");
typedef itk::ImageFileWriter< FilterType::OutputImageType > itkImageWriterType;
typename itkImageWriterType::Pointer itkWriter = itkImageWriterType::New();
itkWriter->SetFileName( argv[2] );
itkWriter->SetInput( filter->GetOutput() );
try
{
itkWriter->Update();
}
catch(itk::ExceptionObject &e)
{
MITK_ERROR << "Catched exception from image writer. " << e.what();
}
/*
// write output
mitk::ImageWriter::Pointer writer = mitk::ImageWriter::New();
MITK_TEST_CONDITION_REQUIRED( writer.IsNotNull(), "Writer instance created. ");
writer->SetInput( mitkImage );
writer->SetExtension(".nrrd");
writer->SetFileName( "/localdata/hering/_Images/TestB0Extraction" );
writer->Update();
*/
// always end with this!
MITK_TEST_END();
}
diff --git a/Modules/DiffusionCore/Testing/mitkConvertDWITypeTest.cpp b/Modules/DiffusionCore/Testing/mitkConvertDWITypeTest.cpp
index c0f127b..2cde87f 100644
--- a/Modules/DiffusionCore/Testing/mitkConvertDWITypeTest.cpp
+++ b/Modules/DiffusionCore/Testing/mitkConvertDWITypeTest.cpp
@@ -1,46 +1,46 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkTestingMacros.h"
#include "mitkIOUtil.h"
#include "mitkDWIHeadMotionCorrectionFilter.h"
/**
* @brief Custom test to provide CMD-line access to the mitk::DWIHeadMotionCorrectionFilter
*
* @param argv : Input and Output image full path
*/
int mitkConvertDWITypeTest( int argc, char* argv[] )
{
MITK_TEST_BEGIN("mitkConvertDWITypeTest");
MITK_TEST_CONDITION_REQUIRED( argc > 2, "Specify input and output.");
mitk::Image::Pointer inputImage = mitk::IOUtil::Load<mitk::Image>( argv[1] );
try
{
mitk::IOUtil::Save(inputImage, argv[2]);
}
catch( const itk::ExceptionObject& e)
{
MITK_ERROR << "Caught exception: " << e.what();
mitkThrow() << "Failed with exception from subprocess!";
}
MITK_TEST_END();
}
diff --git a/Modules/DiffusionCore/Testing/mitkDWHeadMotionCorrectionTest.cpp b/Modules/DiffusionCore/Testing/mitkDWHeadMotionCorrectionTest.cpp
index 7ede169..69434d6 100644
--- a/Modules/DiffusionCore/Testing/mitkDWHeadMotionCorrectionTest.cpp
+++ b/Modules/DiffusionCore/Testing/mitkDWHeadMotionCorrectionTest.cpp
@@ -1,55 +1,55 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkTestingMacros.h"
#include "mitkIOUtil.h"
#include <mitkDWIHeadMotionCorrectionFilter.h>
typedef short DiffusionPixelType;
typedef mitk::Image DiffusionImageType;
/**
* @brief Custom test to provide CMD-line access to the mitk::DWIHeadMotionCorrectionFilter
*
* @param argv : Input and Output image full path
*/
int mitkDWHeadMotionCorrectionTest( int argc, char* argv[] )
{
MITK_TEST_BEGIN("mitkDWHeadMotionCorrectionTest");
MITK_TEST_CONDITION_REQUIRED( argc > 2, "Specify input and output.");
mitk::Image::Pointer inputImage = mitk::IOUtil::Load<mitk::Image>( argv[1] );
DiffusionImageType* dwimage = static_cast<DiffusionImageType*>( inputImage.GetPointer() );
mitk::DWIHeadMotionCorrectionFilter::Pointer corrfilter = mitk::DWIHeadMotionCorrectionFilter::New();
corrfilter->SetInput( dwimage );
corrfilter->Update();
try
{
mitk::IOUtil::Save(corrfilter->GetOutput(), argv[2]);
}
catch( const itk::ExceptionObject& e)
{
MITK_ERROR << "Catched exception: " << e.what();
mitkThrow() << "Failed with exception from subprocess!";
}
MITK_TEST_END();
}
diff --git a/Modules/DiffusionCore/Testing/mitkDiffusionDICOMFileReaderTest.cpp b/Modules/DiffusionCore/Testing/mitkDiffusionDICOMFileReaderTest.cpp
index dcea83d..ed4051f 100644
--- a/Modules/DiffusionCore/Testing/mitkDiffusionDICOMFileReaderTest.cpp
+++ b/Modules/DiffusionCore/Testing/mitkDiffusionDICOMFileReaderTest.cpp
@@ -1,113 +1,113 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkDiffusionDICOMFileReader.h"
#include "mitkDiffusionDICOMFileReaderTestHelper.h"
#include "mitkDICOMTagBasedSorter.h"
#include "mitkDICOMSortByTag.h"
#include <mitkIOUtil.h>
#include "mitkTestingMacros.h"
using mitk::DICOMTag;
int mitkDiffusionDICOMFileReaderTest(int argc, char* argv[])
{
MITK_TEST_BEGIN("mitkDiffusionDICOMFileReaderTest");
mitk::DiffusionDICOMFileReader::Pointer gdcmReader = mitk::DiffusionDICOMFileReader::New();
MITK_TEST_CONDITION_REQUIRED(gdcmReader.IsNotNull(), "DICOMITKSeriesGDCMReader can be instantiated.");
std::string output_filename = "/tmp/dicom_out.dwi";
if( argc > 3)
{
mitk::DICOMFileReaderTestHelper::SetTestInputFilenames( argc-1,argv );
output_filename = std::string( argv[argc-1] );
}
else
{
mitk::DICOMFileReaderTestHelper::SetTestInputFilenames( argc,argv );
}
// check the Set/GetInput function
mitk::DICOMFileReaderTestHelper::TestInputFilenames( gdcmReader );
MITK_INFO << "Test input filenanems";
// check that output is a good reproduction of input (no duplicates, no new elements)
mitk::DICOMFileReaderTestHelper::TestOutputsContainInputs( gdcmReader );
MITK_INFO << "Test output";
// repeat test with some more realistic sorting
gdcmReader = mitk::DiffusionDICOMFileReader::New(); // this also tests destruction
mitk::DICOMTagBasedSorter::Pointer tagSorter = mitk::DICOMTagBasedSorter::New();
// Use tags as in Qmitk
// all the things that split by tag in DicomSeriesReader
tagSorter->AddDistinguishingTag( DICOMTag(0x0028, 0x0010) ); // Number of Rows
tagSorter->AddDistinguishingTag( DICOMTag(0x0028, 0x0011) ); // Number of Columns
tagSorter->AddDistinguishingTag( DICOMTag(0x0028, 0x0030) ); // Pixel Spacing
tagSorter->AddDistinguishingTag( DICOMTag(0x0018, 0x1164) ); // Imager Pixel Spacing
tagSorter->AddDistinguishingTag( DICOMTag(0x0020, 0x0037) ); // Image Orientation (Patient) // TODO add tolerance parameter (l. 1572 of original code)
// TODO handle as real vectors! cluster with configurable errors!
//tagSorter->AddDistinguishingTag( DICOMTag(0x0020, 0x000e) ); // Series Instance UID
//tagSorter->AddDistinguishingTag( DICOMTag(0x0020, 0x0010) );
tagSorter->AddDistinguishingTag( DICOMTag(0x0018, 0x0050) ); // Slice Thickness
tagSorter->AddDistinguishingTag( DICOMTag(0x0028, 0x0008) ); // Number of Frames
tagSorter->AddDistinguishingTag( DICOMTag(0x0020, 0x0052) ); // Frame of Reference UID
// gdcmReader->AddSortingElement( tagSorter );
//mitk::DICOMFileReaderTestHelper::TestOutputsContainInputs( gdcmReader );
mitk::DICOMSortCriterion::ConstPointer sorting =
mitk::DICOMSortByTag::New( DICOMTag(0x0020, 0x0013), // instance number
mitk::DICOMSortByTag::New( DICOMTag(0x0020, 0x0012), // aqcuisition number
mitk::DICOMSortByTag::New( DICOMTag(0x0008, 0x0032), // aqcuisition time
mitk::DICOMSortByTag::New( DICOMTag(0x0018, 0x1060), // trigger time
mitk::DICOMSortByTag::New( DICOMTag(0x0008, 0x0018) // SOP instance UID (last resort, not really meaningful but decides clearly)
).GetPointer()
).GetPointer()
).GetPointer()
).GetPointer()
).GetPointer();
tagSorter->SetSortCriterion( sorting );
MITK_INFO << "Created sort";
gdcmReader->AddSortingElement( tagSorter );
mitk::DICOMFileReaderTestHelper::TestOutputsContainInputs( gdcmReader );
MITK_INFO << "Created sort";
//gdcmReader->PrintOutputs(std::cout, true);
// really load images
//mitk::DICOMFileReaderTestHelper::TestMitkImagesAreLoaded( gdcmReader );
gdcmReader->LoadImages();
mitk::Image::Pointer loaded_image = gdcmReader->GetOutput(0).GetMitkImage();
try
{
mitk::IOUtil::Save(loaded_image, output_filename.c_str());
}
catch( const itk::ExceptionObject& e)
{
MITK_TEST_FAILED_MSG( << "Writer failed : " << e.what() );
}
MITK_TEST_END();
}
diff --git a/Modules/DiffusionCore/Testing/mitkDiffusionDICOMFileReaderTestHelper.h b/Modules/DiffusionCore/Testing/mitkDiffusionDICOMFileReaderTestHelper.h
index 086108d..5aefad2 100644
--- a/Modules/DiffusionCore/Testing/mitkDiffusionDICOMFileReaderTestHelper.h
+++ b/Modules/DiffusionCore/Testing/mitkDiffusionDICOMFileReaderTestHelper.h
@@ -1,153 +1,153 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkDiffusionDICOMFileReaderTestHelper_h
#define mitkDiffusionDICOMFileReaderTestHelper_h
#include "mitkDICOMFileReader.h"
#include "mitkDICOMEnums.h"
#include "mitkTestingMacros.h"
namespace mitk
{
class DICOMFileReaderTestHelper
{
public:
static StringList& GetInputFilenames()
{
static StringList inputs;
return inputs;
}
static void SetTestInputFilenames(int argc, char* argv[])
{
mitk::StringList inputFiles;
for (int a = 1; a < argc; ++a)
{
inputFiles.push_back( argv[a] );
}
GetInputFilenames() = inputFiles;
}
static void SetTestInputFilenames(const StringList& filenames)
{
GetInputFilenames() = filenames;
}
static void TestInputFilenames(DICOMFileReader* reader)
{
StringList inputFiles = GetInputFilenames();
reader->SetInputFiles( inputFiles );
const StringList& inputFilesReturned = reader->GetInputFiles();
MITK_TEST_CONDITION( inputFilesReturned.size() == inputFiles.size(), "Input file list is received")
MITK_TEST_CONDITION( reader->GetNumberOfOutputs() == 0, "No outputs without analysis")
// TODO: check that strings are actually contained
}
static void TestOutputsContainInputs(DICOMFileReader* reader)
{
StringList inputFiles = GetInputFilenames();
reader->SetInputFiles( inputFiles );
reader->AnalyzeInputFiles();
StringList allSortedInputsFiles;
unsigned int numberOfOutputs = reader->GetNumberOfOutputs();
for (unsigned int o = 0; o < numberOfOutputs; ++o)
{
const DICOMImageBlockDescriptor block = reader->GetOutput(o);
const DICOMImageFrameList& outputFiles = block.GetImageFrameList();
for(DICOMImageFrameList::const_iterator iter = outputFiles.begin();
iter != outputFiles.end();
++iter)
{
// check that output is part of input
StringList::iterator inputPositionOfCurrentOutput = std::find( inputFiles.begin(), inputFiles.end(), (*iter)->Filename );
if (inputPositionOfCurrentOutput != inputFiles.end())
{
// check that output is only part of ONE output
StringList::iterator outputPositionOfCurrentOutput = std::find( allSortedInputsFiles.begin(), allSortedInputsFiles.end(), (*iter)->Filename );
if (outputPositionOfCurrentOutput == allSortedInputsFiles.end())
{
// was not in list before
allSortedInputsFiles.push_back( *inputPositionOfCurrentOutput );
}
else
{
reader->PrintOutputs(std::cout);
MITK_TEST_CONDITION_REQUIRED(false, "File '" << (*iter)->Filename << "' appears in TWO outputs. Readers are expected to use each frame only once." )
}
}
else
{
reader->PrintOutputs(std::cout);
MITK_TEST_CONDITION_REQUIRED(false, "File '" << (*iter)->Filename << "' appears in output, but it was never part of the input list." )
}
}
}
MITK_TEST_CONDITION( allSortedInputsFiles.size() == inputFiles.size(), "Output list size (" << allSortedInputsFiles.size() << ") equals input list size (" << inputFiles.size() << ")" )
try
{
const DICOMImageBlockDescriptor block = reader->GetOutput( inputFiles.size() );
MITK_TEST_CONDITION(false, "Invalid indices for GetOutput() should throw exception")
}
catch( std::invalid_argument& )
{
MITK_TEST_CONDITION(true, "Invalid indices for GetOutput() should throw exception")
}
}
static void TestMitkImagesAreLoaded(DICOMFileReader* reader)
{
StringList inputFiles = GetInputFilenames();
reader->SetInputFiles( inputFiles );
reader->AnalyzeInputFiles();
reader->LoadImages();
unsigned int numberOfOutputs = reader->GetNumberOfOutputs();
for (unsigned int o = 0; o < numberOfOutputs; ++o)
{
const DICOMImageBlockDescriptor block = reader->GetOutput(o);
const DICOMImageFrameList& outputFiles = block.GetImageFrameList();
mitk::Image::Pointer mitkImage = block.GetMitkImage();
MITK_INFO << "-------------------------------------------";
MITK_INFO << "Output " << o << " at " << (void*) mitkImage.GetPointer();
MITK_INFO << " Number of files: " << outputFiles.size();
MITK_INFO << " Dimensions: " << mitkImage->GetDimension(0) << " " << mitkImage->GetDimension(1) << " " << mitkImage->GetDimension(2);
}
}
}; // end test class
} // namespace
#endif
diff --git a/Modules/DiffusionCore/Testing/mitkDiffusionPropertySerializerTest.cpp b/Modules/DiffusionCore/Testing/mitkDiffusionPropertySerializerTest.cpp
index b17704f..506f63c 100644
--- a/Modules/DiffusionCore/Testing/mitkDiffusionPropertySerializerTest.cpp
+++ b/Modules/DiffusionCore/Testing/mitkDiffusionPropertySerializerTest.cpp
@@ -1,183 +1,183 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkIOUtil.h"
#include "mitkTestingMacros.h"
#include "mitkTestFixture.h"
#include <mitkBasePropertySerializer.h>
#include <mitkBValueMapProperty.h>
#include <mitkGradientDirectionsProperty.h>
#include <mitkMeasurementFrameProperty.h>
#include <mitkDiffusionPropertyHelper.h>
class mitkDiffusionPropertySerializerTestSuite : public mitk::TestFixture
{
CPPUNIT_TEST_SUITE(mitkDiffusionPropertySerializerTestSuite);
MITK_TEST(Equal_SerializeandDeserialize_ReturnsTrue);
//MITK_TEST(Equal_DifferentChannels_ReturnFalse);
CPPUNIT_TEST_SUITE_END();
private:
/** Members used inside the different (sub-)tests. All members are initialized via setUp().*/
mitk::PropertyList::Pointer propList; //represet image propertylist
mitk::BValueMapProperty::Pointer bvaluemap_prop;
mitk::GradientDirectionsProperty::Pointer gradientdirection_prop;
mitk::MeasurementFrameProperty::Pointer measurementframe_prop;
public:
/**
* @brief Setup Always call this method before each Test-case to ensure correct and new intialization of the used members for a new test case. (If the members are not used in a test, the method does not need to be called).
*/
void setUp() override
{
propList = mitk::PropertyList::New();
mitk::BValueMapProperty::BValueMap map;
std::vector<unsigned int> indices1;
indices1.push_back(1);
indices1.push_back(2);
indices1.push_back(3);
indices1.push_back(4);
map[0] = indices1;
std::vector<unsigned int> indices2;
indices2.push_back(4);
indices2.push_back(3);
indices2.push_back(2);
indices2.push_back(1);
map[1000] = indices2;
bvaluemap_prop = mitk::BValueMapProperty::New(map).GetPointer();
propList->SetProperty(mitk::DiffusionPropertyHelper::GetBvaluePropertyName().c_str(), bvaluemap_prop);
mitk::GradientDirectionsProperty::GradientDirectionsContainerType::Pointer gdc;
gdc = mitk::GradientDirectionsProperty::GradientDirectionsContainerType::New();
double a[3] = {3.0,4.0,1.4};
vnl_vector_fixed<double,3> vec1;
vec1.set(a);
gdc->push_back(vec1);
double b[3] = {1.0,5.0,123.4};
vnl_vector_fixed<double,3> vec2;
vec2.set(b);
gdc->push_back(vec2);
double c[3] = {13.0,84.02,13.4};
vnl_vector_fixed<double,3> vec3;
vec3.set(c);
gdc->push_back(vec3);
gradientdirection_prop = mitk::GradientDirectionsProperty::New(gdc.GetPointer()).GetPointer();
propList->ReplaceProperty(mitk::DiffusionPropertyHelper::GetGradientContainerPropertyName().c_str(), gradientdirection_prop);
mitk::MeasurementFrameProperty::MeasurementFrameType mft;
double row0[3] = {1,0,0};
double row1[3] = {0,1,0};
double row2[3] = {0,0,1};
mft.set_row(0,row0);
mft.set_row(1,row1);
mft.set_row(2,row2);
measurementframe_prop = mitk::MeasurementFrameProperty::New(mft).GetPointer();
propList->ReplaceProperty(mitk::DiffusionPropertyHelper::GetGradientContainerPropertyName().c_str(), measurementframe_prop);
}
void tearDown() override
{
}
void Equal_SerializeandDeserialize_ReturnsTrue()
{
assert(propList);
/* try to serialize each property in the list, then deserialize again and check for equality */
for (mitk::PropertyList::PropertyMap::const_iterator it = propList->GetMap()->begin(); it != propList->GetMap()->end(); ++it)
{
const mitk::BaseProperty* prop = it->second;
// construct name of serializer class
std::string serializername = std::string(prop->GetNameOfClass()) + "Serializer";
std::list<itk::LightObject::Pointer> allSerializers = itk::ObjectFactoryBase::CreateAllInstance(serializername.c_str());
MITK_TEST_CONDITION(allSerializers.size() > 0, std::string("Creating serializers for ") + serializername);
if (allSerializers.size() == 0)
{
MITK_TEST_OUTPUT( << "serialization not possible, skipping " << prop->GetNameOfClass());
continue;
}
if (allSerializers.size() > 1)
{
MITK_TEST_OUTPUT (<< "Warning: " << allSerializers.size() << " serializers found for " << prop->GetNameOfClass() << "testing only the first one.");
}
mitk::BasePropertySerializer* serializer = dynamic_cast<mitk::BasePropertySerializer*>( allSerializers.begin()->GetPointer());
MITK_TEST_CONDITION(serializer != nullptr, serializername + std::string(" is valid"));
if (serializer != nullptr)
{
serializer->SetProperty(prop);
TiXmlElement* valueelement = nullptr;
try
{
valueelement = serializer->Serialize();
// TiXmlPrinter p;
// valueelement->Accept(&p);
// MITK_INFO << p.CStr();
}
catch (...)
{
}
MITK_TEST_CONDITION(valueelement != nullptr, std::string("Serialize property with ") + serializername);
if (valueelement == nullptr)
{
MITK_TEST_OUTPUT( << "serialization failed, skipping deserialization");
continue;
}
mitk::BaseProperty::Pointer deserializedProp = serializer->Deserialize( valueelement );
MITK_TEST_CONDITION(deserializedProp.IsNotNull(), "serializer created valid property");
if (deserializedProp.IsNotNull())
{
MITK_TEST_CONDITION(*(deserializedProp.GetPointer()) == *prop, "deserialized property equals initial property for type " << prop->GetNameOfClass());
}
}
else
{
MITK_TEST_OUTPUT( << "created serializer object is of class " << allSerializers.begin()->GetPointer()->GetNameOfClass())
}
} // for all properties
}
};
MITK_TEST_SUITE_REGISTRATION(mitkDiffusionPropertySerializer)
diff --git a/Modules/DiffusionCore/Testing/mitkExtractSingleShellTest.cpp b/Modules/DiffusionCore/Testing/mitkExtractSingleShellTest.cpp
index c0c7693..e90580d 100644
--- a/Modules/DiffusionCore/Testing/mitkExtractSingleShellTest.cpp
+++ b/Modules/DiffusionCore/Testing/mitkExtractSingleShellTest.cpp
@@ -1,97 +1,97 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkTestingMacros.h"
#include "mitkIOUtil.h"
#include <itkElectrostaticRepulsionDiffusionGradientReductionFilter.h>
#include "mitkDWIHeadMotionCorrectionFilter.h"
#include <mitkDiffusionPropertyHelper.h>
#include <mitkImageCast.h>
#include <mitkProperties.h>
typedef short DiffusionPixelType;
int mitkExtractSingleShellTest( int argc, char* argv[] )
{
MITK_TEST_BEGIN("mitkExtractSingleShellTest");
MITK_TEST_CONDITION_REQUIRED( argc > 3, "Specify input and output and the shell to be extracted");
/*
1. Get input data
*/
mitk::Image::Pointer dwimage = mitk::IOUtil::Load<mitk::Image>( argv[1] );
unsigned int extract_value = 0;
std::istringstream input(argv[3]);
input >> extract_value;
typedef itk::ElectrostaticRepulsionDiffusionGradientReductionFilter<DiffusionPixelType, DiffusionPixelType> FilterType;
typedef mitk::DiffusionPropertyHelper::BValueMapType BValueMap;
// GetShellSelection from GUI
BValueMap shellSelectionMap;
BValueMap originalShellMap = mitk::DiffusionPropertyHelper::GetBValueMap(dwimage);
std::vector<unsigned int> newNumGradientDirections;
shellSelectionMap[extract_value] = originalShellMap[extract_value];
newNumGradientDirections.push_back( originalShellMap[extract_value].size() ) ;
itk::VectorImage< short, 3 >::Pointer itkVectorImagePointer = itk::VectorImage< short, 3 >::New();
mitk::CastToItkImage(dwimage, itkVectorImagePointer);
itk::VectorImage< short, 3 > *vectorImage = itkVectorImagePointer.GetPointer();
mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradientContainer = mitk::DiffusionPropertyHelper::GetGradientContainer(dwimage);
FilterType::Pointer filter = FilterType::New();
filter->SetInput(vectorImage);
filter->SetOriginalGradientDirections(gradientContainer);
filter->SetNumGradientDirections(newNumGradientDirections);
filter->SetOriginalBValueMap(originalShellMap);
filter->SetShellSelectionBValueMap(shellSelectionMap);
try
{
filter->Update();
}
catch( const itk::ExceptionObject& e)
{
MITK_TEST_FAILED_MSG( << "Failed due to ITK exception: " << e.what() );
}
mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( filter->GetOutput() );
mitk::DiffusionPropertyHelper::CopyProperties(dwimage, outImage, true);
mitk::DiffusionPropertyHelper::SetGradientContainer(outImage, filter->GetGradientDirections());
mitk::DiffusionPropertyHelper::InitializeImage( outImage );
/*
* 3. Write output data
**/
try
{
mitk::IOUtil::Save(outImage, argv[2]);
}
catch( const itk::ExceptionObject& e)
{
MITK_ERROR << "Catched exception: " << e.what();
mitkThrow() << "Failed with exception from subprocess!";
}
MITK_TEST_END();
}
diff --git a/Modules/DiffusionCore/Testing/mitkImageReconstructionTest.cpp b/Modules/DiffusionCore/Testing/mitkImageReconstructionTest.cpp
index 11dfd13..67d95f1 100644
--- a/Modules/DiffusionCore/Testing/mitkImageReconstructionTest.cpp
+++ b/Modules/DiffusionCore/Testing/mitkImageReconstructionTest.cpp
@@ -1,155 +1,155 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkImageCast.h>
#include <mitkTensorImage.h>
#include <mitkOdfImage.h>
#include <mitkIOUtil.h>
#include <itkDiffusionTensor3D.h>
#include <mitkTestingMacros.h>
#include <itkDiffusionTensor3DReconstructionImageFilter.h>
#include <itkDiffusionTensor3D.h>
#include <itkDiffusionQballReconstructionImageFilter.h>
#include <itkAnalyticalDiffusionQballReconstructionImageFilter.h>
#include <mitkImage.h>
#include <mitkDiffusionPropertyHelper.h>
int mitkImageReconstructionTest(int argc, char* argv[])
{
MITK_TEST_BEGIN("mitkImageReconstructionTest");
MITK_TEST_CONDITION_REQUIRED(argc>1,"check for input data")
try
{
mitk::Image::Pointer dwi = mitk::IOUtil::Load<mitk::Image>(argv[1]);
itk::VectorImage<short,3>::Pointer itkVectorImagePointer = itk::VectorImage<short,3>::New();
mitk::CastToItkImage(dwi, itkVectorImagePointer);
float b_value = mitk::DiffusionPropertyHelper::GetReferenceBValue( dwi );
mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradients = mitk::DiffusionPropertyHelper::GetGradientContainer(dwi);
{
MITK_INFO << "Tensor reconstruction " << argv[2];
mitk::TensorImage::Pointer tensorImage = mitk::IOUtil::Load<mitk::TensorImage>(argv[2]);
typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, float > TensorReconstructionImageFilterType;
TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New();
filter->SetBValue( b_value );
filter->SetGradientImage( gradients, itkVectorImagePointer );
filter->Update();
mitk::TensorImage::Pointer testImage = mitk::TensorImage::New();
testImage->InitializeByItk( filter->GetOutput() );
testImage->SetVolume( filter->GetOutput()->GetBufferPointer() );
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *tensorImage, 0.0001, true), "tensor reconstruction test.");
}
{
MITK_INFO << "Numerical Q-ball reconstruction " << argv[3];
mitk::OdfImage::Pointer odfImage = mitk::IOUtil::Load<mitk::OdfImage>(argv[3]);
typedef itk::DiffusionQballReconstructionImageFilter<short, short, float, ODF_SAMPLING_SIZE> QballReconstructionImageFilterType;
QballReconstructionImageFilterType::Pointer filter = QballReconstructionImageFilterType::New();
filter->SetBValue( b_value );
filter->SetGradientImage( gradients, itkVectorImagePointer );
filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_STANDARD);
filter->Update();
mitk::OdfImage::Pointer testImage = mitk::OdfImage::New();
testImage->InitializeByItk( filter->GetOutput() );
testImage->SetVolume( filter->GetOutput()->GetBufferPointer() );
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *odfImage, 0.0001, true), "Numerical Q-ball reconstruction test.");
}
{
MITK_INFO << "Standard Q-ball reconstruction " << argv[4];
mitk::OdfImage::Pointer odfImage = mitk::IOUtil::Load<mitk::OdfImage>(argv[4]);
typedef itk::AnalyticalDiffusionQballReconstructionImageFilter<short,short,float,4,ODF_SAMPLING_SIZE> FilterType;
FilterType::Pointer filter = FilterType::New();
filter->SetBValue( b_value );
filter->SetGradientImage( gradients, itkVectorImagePointer );
filter->SetLambda(0.006);
filter->SetNormalizationMethod(FilterType::QBAR_STANDARD);
filter->Update();
mitk::OdfImage::Pointer testImage = mitk::OdfImage::New();
testImage->InitializeByItk( filter->GetOutput() );
testImage->SetVolume( filter->GetOutput()->GetBufferPointer() );
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *odfImage, 0.0001, true), "Standard Q-ball reconstruction test.");
}
{
MITK_INFO << "CSA Q-ball reconstruction " << argv[5];
mitk::OdfImage::Pointer odfImage = mitk::IOUtil::Load<mitk::OdfImage>(argv[5]);
typedef itk::AnalyticalDiffusionQballReconstructionImageFilter<short,short,float,4,ODF_SAMPLING_SIZE> FilterType;
FilterType::Pointer filter = FilterType::New();
filter->SetBValue( b_value );
filter->SetGradientImage( gradients, itkVectorImagePointer );
filter->SetLambda(0.006);
filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE);
filter->Update();
mitk::OdfImage::Pointer testImage = mitk::OdfImage::New();
testImage->InitializeByItk( filter->GetOutput() );
testImage->SetVolume( filter->GetOutput()->GetBufferPointer() );
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *odfImage, 0.0001, true), "CSA Q-ball reconstruction test.");
}
{
MITK_INFO << "ADC profile reconstruction " << argv[6];
mitk::OdfImage::Pointer odfImage = mitk::IOUtil::Load<mitk::OdfImage>(argv[6]);
typedef itk::AnalyticalDiffusionQballReconstructionImageFilter<short,short,float,4,ODF_SAMPLING_SIZE> FilterType;
FilterType::Pointer filter = FilterType::New();
filter->SetBValue( b_value );
filter->SetGradientImage( gradients, itkVectorImagePointer );
filter->SetLambda(0.006);
filter->SetNormalizationMethod(FilterType::QBAR_ADC_ONLY);
filter->Update();
mitk::OdfImage::Pointer testImage = mitk::OdfImage::New();
testImage->InitializeByItk( filter->GetOutput() );
testImage->SetVolume( filter->GetOutput()->GetBufferPointer() );
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *odfImage, 0.0001, true), "ADC profile reconstruction test.");
}
{
MITK_INFO << "Raw signal modeling " << argv[7];
mitk::OdfImage::Pointer odfImage = mitk::IOUtil::Load<mitk::OdfImage>(argv[7]);
typedef itk::AnalyticalDiffusionQballReconstructionImageFilter<short,short,float,4,ODF_SAMPLING_SIZE> FilterType;
FilterType::Pointer filter = FilterType::New();
filter->SetBValue( b_value );
filter->SetGradientImage( gradients, itkVectorImagePointer );
filter->SetLambda(0.006);
filter->SetNormalizationMethod(FilterType::QBAR_RAW_SIGNAL);
filter->Update();
mitk::OdfImage::Pointer testImage = mitk::OdfImage::New();
testImage->InitializeByItk( filter->GetOutput() );
testImage->SetVolume( filter->GetOutput()->GetBufferPointer() );
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(*testImage, *odfImage, 0.1, true), "Raw signal modeling test.");
}
}
catch (const itk::ExceptionObject& e)
{
MITK_INFO << e.what();
return EXIT_FAILURE;
}
catch (const std::exception& e)
{
MITK_INFO << e.what();
return EXIT_FAILURE;
}
catch (...)
{
MITK_INFO << "ERROR!?!";
return EXIT_FAILURE;
}
MITK_TEST_END();
}
diff --git a/Modules/DiffusionCore/Testing/mitkNonLocalMeansDenoisingTest.cpp b/Modules/DiffusionCore/Testing/mitkNonLocalMeansDenoisingTest.cpp
index efe5831..cd3b6a6 100644
--- a/Modules/DiffusionCore/Testing/mitkNonLocalMeansDenoisingTest.cpp
+++ b/Modules/DiffusionCore/Testing/mitkNonLocalMeansDenoisingTest.cpp
@@ -1,169 +1,169 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkIOUtil.h"
#include "mitkTestingMacros.h"
#include "mitkTestFixture.h"
#include "itkNonLocalMeansDenoisingFilter.h"
#include "mitkGradientDirectionsProperty.h"
#include "mitkITKImageImport.h"
#include <mitkImageCast.h>
class mitkNonLocalMeansDenoisingTestSuite : public mitk::TestFixture
{
CPPUNIT_TEST_SUITE(mitkNonLocalMeansDenoisingTestSuite);
MITK_TEST(Denoise_NLMg_shouldReturnTrue);
MITK_TEST(Denoise_NLMr_shouldReturnTrue);
MITK_TEST(Denoise_NLMv_shouldReturnTrue);
MITK_TEST(Denoise_NLMvr_shouldReturnTrue);
CPPUNIT_TEST_SUITE_END();
private:
typedef itk::VectorImage<short,3> VectorImagetType;
/** Members used inside the different (sub-)tests. All members are initialized via setUp().*/
mitk::Image::Pointer m_Image;
mitk::Image::Pointer m_ReferenceImage;
mitk::Image::Pointer m_DenoisedImage;
itk::Image<short, 3>::Pointer m_ImageMask;
itk::NonLocalMeansDenoisingFilter<short>::Pointer m_DenoisingFilter;
public:
/**
* @brief Setup Always call this method before each Test-case to ensure correct and new intialization of the used members for a new test case. (If the members are not used in a test, the method does not need to be called).
*/
void setUp() override
{
//generate test images
std::string imagePath = GetTestDataFilePath("DiffusionImaging/Denoising/test_multi.dwi");
m_Image = mitk::IOUtil::Load<mitk::Image>(imagePath);
m_ReferenceImage = nullptr;
m_DenoisedImage = mitk::Image::New();
//initialise Filter
m_DenoisingFilter = itk::NonLocalMeansDenoisingFilter<short>::New();
VectorImagetType::Pointer vectorImage;
mitk::CastToItkImage(m_Image,vectorImage);
m_DenoisingFilter->SetInputImage(vectorImage);
m_DenoisingFilter->SetNumberOfThreads(1);
m_DenoisingFilter->SetComparisonRadius(1);
m_DenoisingFilter->SetSearchRadius(1);
m_DenoisingFilter->SetVariance(500);
}
void tearDown() override
{
m_Image = nullptr;
m_ImageMask = nullptr;
m_ReferenceImage = nullptr;
m_DenoisingFilter = nullptr;
m_DenoisedImage = nullptr;
}
void Denoise_NLMg_shouldReturnTrue()
{
std::string referenceImagePath = GetTestDataFilePath("DiffusionImaging/Denoising/test_multi_NLMg.dwi");
m_ReferenceImage = mitk::IOUtil::Load<mitk::Image>(referenceImagePath);
m_DenoisingFilter->SetUseRicianAdaption(false);
m_DenoisingFilter->SetUseJointInformation(false);
try
{
m_DenoisingFilter->Update();
}
catch(std::exception& e)
{
MITK_ERROR << e.what();
}
mitk::GrabItkImageMemory(m_DenoisingFilter->GetOutput(),m_DenoisedImage);
m_DenoisedImage->SetPropertyList(m_Image->GetPropertyList()->Clone());
MITK_ASSERT_EQUAL( m_DenoisedImage, m_ReferenceImage, "NLMg should always return the same result.");
}
void Denoise_NLMr_shouldReturnTrue()
{
std::string referenceImagePath = GetTestDataFilePath("DiffusionImaging/Denoising/test_multi_NLMr.dwi");
m_ReferenceImage = mitk::IOUtil::Load<mitk::Image>(referenceImagePath);
m_DenoisingFilter->SetUseRicianAdaption(true);
m_DenoisingFilter->SetUseJointInformation(false);
try
{
m_DenoisingFilter->Update();
}
catch(std::exception& e)
{
MITK_ERROR << e.what();
}
mitk::GrabItkImageMemory(m_DenoisingFilter->GetOutput(),m_DenoisedImage);
m_DenoisedImage->SetPropertyList(m_Image->GetPropertyList()->Clone());
MITK_ASSERT_EQUAL( m_DenoisedImage, m_ReferenceImage, "NLMr should always return the same result.");
}
void Denoise_NLMv_shouldReturnTrue()
{
std::string referenceImagePath = GetTestDataFilePath("DiffusionImaging/Denoising/test_multi_NLMv.dwi");
m_ReferenceImage = mitk::IOUtil::Load<mitk::Image>(referenceImagePath);
m_DenoisingFilter->SetUseRicianAdaption(false);
m_DenoisingFilter->SetUseJointInformation(true);
try
{
m_DenoisingFilter->Update();
}
catch(std::exception& e)
{
MITK_ERROR << e.what();
}
mitk::GrabItkImageMemory(m_DenoisingFilter->GetOutput(),m_DenoisedImage);
m_DenoisedImage->SetPropertyList(m_Image->GetPropertyList()->Clone());
MITK_ASSERT_EQUAL( m_DenoisedImage, m_ReferenceImage, "NLMv should always return the same result.");
}
void Denoise_NLMvr_shouldReturnTrue()
{
std::string referenceImagePath = GetTestDataFilePath("DiffusionImaging/Denoising/test_multi_NLMvr.dwi");
m_ReferenceImage = mitk::IOUtil::Load<mitk::Image>(referenceImagePath);
m_DenoisingFilter->SetUseRicianAdaption(true);
m_DenoisingFilter->SetUseJointInformation(true);
try
{
m_DenoisingFilter->Update();
}
catch(std::exception& e)
{
MITK_ERROR << e.what();
}
mitk::GrabItkImageMemory(m_DenoisingFilter->GetOutput(),m_DenoisedImage);
m_DenoisedImage->SetPropertyList(m_Image->GetPropertyList()->Clone());
MITK_ASSERT_EQUAL( m_DenoisedImage, m_ReferenceImage, "NLMvr should always return the same result.");
}
};
MITK_TEST_SUITE_REGISTRATION(mitkNonLocalMeansDenoising)
diff --git a/Modules/DiffusionCore/Testing/mitkPyramidImageRegistrationMethodTest.cpp b/Modules/DiffusionCore/Testing/mitkPyramidImageRegistrationMethodTest.cpp
index 594b4fb..5b7a025 100644
--- a/Modules/DiffusionCore/Testing/mitkPyramidImageRegistrationMethodTest.cpp
+++ b/Modules/DiffusionCore/Testing/mitkPyramidImageRegistrationMethodTest.cpp
@@ -1,156 +1,156 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkTestingMacros.h"
#include "mitkIOUtil.h"
#include "Registration/mitkPyramidImageRegistrationMethod.h"
#include <itkTransformFileWriter.h>
int mitkPyramidImageRegistrationMethodTest( int argc, char* argv[] )
{
if( argc < 4 )
{
MITK_ERROR << "Not enough input \n Usage: <TEST_NAME> fixed moving type [output_image [output_transform]]"
<< "\n \t fixed : the path to the fixed image \n"
<< " \t moving : path to the image to be registered"
<< " \t type : Affine or Rigid defining the type of the transformation"
<< " \t output_image : output file optional, (full) path, and optionally output_transform : also (full)path to file";
return EXIT_FAILURE;
}
MITK_TEST_BEGIN("PyramidImageRegistrationMethodTest");
mitk::Image::Pointer fixedImage = mitk::IOUtil::Load<mitk::Image>( argv[1] );
mitk::Image::Pointer movingImage = mitk::IOUtil::Load<mitk::Image>( argv[2] );
std::string type_flag( argv[3] );
mitk::PyramidImageRegistrationMethod::Pointer registrationMethod = mitk::PyramidImageRegistrationMethod::New();
registrationMethod->SetFixedImage( fixedImage );
registrationMethod->SetMovingImage( movingImage );
if( type_flag == "Rigid" )
{
registrationMethod->SetTransformToRigid();
}
else if( type_flag == "Affine" )
{
registrationMethod->SetTransformToAffine();
}
else
{
MITK_WARN << " No type specified, using 'Affine' .";
}
registrationMethod->Update();
bool imageOutput = false;
bool transformOutput = false;
std::string image_out_filename, transform_out_filename;
std::string first_output( argv[4] );
// check for txt, otherwise suppose it is an image
if( first_output.find(".txt") != std::string::npos )
{
transformOutput = true;
transform_out_filename = first_output;
}
else
{
imageOutput = true;
image_out_filename = first_output;
}
if( argc > 4 )
{
std::string second_output( argv[5] );
if( second_output.find(".txt") != std::string::npos )
{
transformOutput = true;
transform_out_filename = second_output;
}
}
MITK_INFO << " Selected output: " << transform_out_filename << " " << image_out_filename;
try{
unsigned int paramCount = registrationMethod->GetNumberOfParameters();
double* params = new double[ paramCount ];
registrationMethod->GetParameters( &params[0] );
std::cout << "Parameters: ";
for( unsigned int i=0; i< paramCount; i++)
{
std::cout << params[ i ] << " ";
}
std::cout << std::endl;
if( imageOutput )
{
mitk::IOUtil::Save( registrationMethod->GetResampledMovingImage(), image_out_filename.c_str() );
}
if( transformOutput )
{
itk::TransformFileWriter::Pointer writer = itk::TransformFileWriter::New();
// Get transform parameter for resampling / saving
// Affine
if( paramCount == 12 )
{
typedef itk::AffineTransform< double > TransformType;
TransformType::Pointer transform = TransformType::New();
TransformType::ParametersType affine_params( paramCount );
registrationMethod->GetParameters( &affine_params[0] );
transform->SetParameters( affine_params );
writer->SetInput( transform );
}
// Rigid
else
{
typedef itk::Euler3DTransform< double > RigidTransformType;
RigidTransformType::Pointer rtransform = RigidTransformType::New();
RigidTransformType::ParametersType rigid_params( paramCount );
registrationMethod->GetParameters( &rigid_params[0] );
rtransform->SetParameters( rigid_params );
writer->SetInput( rtransform );
}
writer->SetFileName( transform_out_filename );
writer->Update();
}
}
catch( const std::exception &e)
{
MITK_ERROR << "Caught exception: " << e.what();
}
MITK_TEST_END();
}
diff --git a/Modules/DiffusionCore/mitkDiffusionFunctionCollection.cpp b/Modules/DiffusionCore/mitkDiffusionFunctionCollection.cpp
index 388bb95..932aafb 100644
--- a/Modules/DiffusionCore/mitkDiffusionFunctionCollection.cpp
+++ b/Modules/DiffusionCore/mitkDiffusionFunctionCollection.cpp
@@ -1,713 +1,713 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkDiffusionFunctionCollection.h"
#include "mitkNumericTypes.h"
#include <boost/math/special_functions/legendre.hpp>
#include <boost/math/special_functions/spherical_harmonic.hpp>
#include <boost/version.hpp>
#include <itkPointShell.h>
#include "itkVectorContainer.h"
#include "vnl/vnl_vector.h"
#include <vtkBox.h>
#include <vtkMath.h>
#include <itksys/SystemTools.hxx>
#include <boost/algorithm/string.hpp>
#include <itkShToOdfImageFilter.h>
#include <itkTensorImageToOdfImageFilter.h>
// Intersect a finite line (with end points p0 and p1) with all of the
// cells of a vtkImageData
std::vector< std::pair< itk::Index<3>, double > > mitk::imv::IntersectImage(const itk::Vector<double,3>& spacing, itk::Index<3>& si, itk::Index<3>& ei, itk::ContinuousIndex<float, 3>& sf, itk::ContinuousIndex<float, 3>& ef)
{
std::vector< std::pair< itk::Index<3>, double > > out;
if (si == ei)
{
double d[3];
for (int i=0; i<3; ++i)
d[i] = static_cast<double>(sf[i]-ef[i])*spacing[i];
double len = std::sqrt( d[0]*d[0] + d[1]*d[1] + d[2]*d[2] );
out.push_back( std::pair< itk::Index<3>, double >(si, len) );
return out;
}
double bounds[6];
double entrancePoint[3];
double exitPoint[3];
double startPoint[3];
double endPoint[3];
double t0, t1;
for (unsigned int i=0; i<3; ++i)
{
startPoint[i] = static_cast<double>(sf[i]);
endPoint[i] = static_cast<double>(ef[i]);
if (si[i]>ei[i])
{
auto t = si[i];
si[i] = ei[i];
ei[i] = t;
}
}
for (auto x = si[0]; x<=ei[0]; ++x)
for (auto y = si[1]; y<=ei[1]; ++y)
for (auto z = si[2]; z<=ei[2]; ++z)
{
bounds[0] = static_cast<double>(x) - 0.5;
bounds[1] = static_cast<double>(x) + 0.5;
bounds[2] = static_cast<double>(y) - 0.5;
bounds[3] = static_cast<double>(y) + 0.5;
bounds[4] = static_cast<double>(z) - 0.5;
bounds[5] = static_cast<double>(z) + 0.5;
int entryPlane;
int exitPlane;
int hit = vtkBox::IntersectWithLine(bounds,
startPoint,
endPoint,
t0,
t1,
entrancePoint,
exitPoint,
entryPlane,
exitPlane);
if (hit)
{
if (entryPlane>=0 && exitPlane>=0)
{
double d[3];
for (int i=0; i<3; ++i)
d[i] = (exitPoint[i] - entrancePoint[i])*spacing[i];
double len = std::sqrt( d[0]*d[0] + d[1]*d[1] + d[2]*d[2] );
itk::Index<3> idx; idx[0] = x; idx[1] = y; idx[2] = z;
out.push_back( std::pair< itk::Index<3>, double >(idx, len) );
}
else if (entryPlane>=0)
{
double d[3];
for (int i=0; i<3; ++i)
d[i] = (static_cast<double>(ef[i]) - entrancePoint[i])*spacing[i];
double len = std::sqrt( d[0]*d[0] + d[1]*d[1] + d[2]*d[2] );
itk::Index<3> idx; idx[0] = x; idx[1] = y; idx[2] = z;
out.push_back( std::pair< itk::Index<3>, double >(idx, len) );
}
else if (exitPlane>=0)
{
double d[3];
for (int i=0; i<3; ++i)
d[i] = (exitPoint[i]-static_cast<double>(sf[i]))*spacing[i];
double len = std::sqrt( d[0]*d[0] + d[1]*d[1] + d[2]*d[2] );
itk::Index<3> idx; idx[0] = x; idx[1] = y; idx[2] = z;
out.push_back( std::pair< itk::Index<3>, double >(idx, len) );
}
}
}
return out;
}
//------------------------- SH-function ------------------------------------
double mitk::sh::factorial(int number) {
if(number <= 1) return 1;
double result = 1.0;
for(int i=1; i<=number; i++)
result *= i;
return result;
}
void mitk::sh::Cart2Sph(double x, double y, double z, double *spherical)
{
double phi, th, rad;
rad = sqrt(x*x+y*y+z*z);
if( rad < mitk::eps )
{
th = itk::Math::pi/2;
phi = itk::Math::pi/2;
}
else
{
th = acos(z/rad);
phi = atan2(y, x);
}
spherical[0] = phi;
spherical[1] = th;
spherical[2] = rad;
}
vnl_vector_fixed<double, 3> mitk::sh::Sph2Cart(const double& theta, const double& phi, const double& rad)
{
vnl_vector_fixed<double, 3> dir;
dir[0] = rad * sin(theta) * cos(phi);
dir[1] = rad * sin(theta) * sin(phi);
dir[2] = rad * cos(theta);
return dir;
}
double mitk::sh::legendre0(int l)
{
if( l%2 != 0 )
{
return 0;
}
else
{
double prod1 = 1.0;
for(int i=1;i<l;i+=2) prod1 *= i;
double prod2 = 1.0;
for(int i=2;i<=l;i+=2) prod2 *= i;
return pow(-1.0,l/2.0)*(prod1/prod2);
}
}
double mitk::sh::Yj(int m, int k, float theta, float phi, bool mrtrix)
{
if (!mrtrix)
{
if (m<0)
return sqrt(2.0)*static_cast<double>(::boost::math::spherical_harmonic_r(static_cast<unsigned int>(k), -m, theta, phi));
else if (m==0)
return static_cast<double>(::boost::math::spherical_harmonic_r(static_cast<unsigned int>(k), m, theta, phi));
else
return pow(-1.0,m)*sqrt(2.0)*static_cast<double>(::boost::math::spherical_harmonic_i(static_cast<unsigned int>(k), m, theta, phi));
}
else
{
double plm = static_cast<double>(::boost::math::legendre_p<float>(k,abs(m),-cos(theta)));
double mag = sqrt((2.0*k+1.0)/(4.0*itk::Math::pi)*::boost::math::factorial<double>(k-abs(m))/::boost::math::factorial<double>(k+abs(m)))*plm;
if (m>0)
return mag*static_cast<double>(cos(m*phi));
else if (m==0)
return mag;
else
return mag*static_cast<double>(sin(-m*phi));
}
return 0;
}
mitk::OdfImage::ItkOdfImageType::Pointer mitk::convert::GetItkOdfFromShImage(mitk::Image::Pointer mitkImage)
{
mitk::ShImage::Pointer mitkShImage = dynamic_cast<mitk::ShImage*>(mitkImage.GetPointer());
if (mitkShImage.IsNull())
mitkThrow() << "Input image is not a SH image!";
mitk::OdfImage::ItkOdfImageType::Pointer output;
switch (mitkShImage->ShOrder())
{
case 2:
{
typedef itk::ShToOdfImageFilter< float, 2 > ShConverterType;
typename ShConverterType::InputImageType::Pointer itkvol = ShConverterType::InputImageType::New();
mitk::CastToItkImage(mitkImage, itkvol);
typename ShConverterType::Pointer converter = ShConverterType::New();
converter->SetInput(itkvol);
converter->SetToolkit(mitkShImage->GetShConvention());
converter->Update();
output = converter->GetOutput();
break;
}
case 4:
{
typedef itk::ShToOdfImageFilter< float, 4 > ShConverterType;
typename ShConverterType::InputImageType::Pointer itkvol = ShConverterType::InputImageType::New();
mitk::CastToItkImage(mitkImage, itkvol);
typename ShConverterType::Pointer converter = ShConverterType::New();
converter->SetInput(itkvol);
converter->SetToolkit(mitkShImage->GetShConvention());
converter->Update();
output = converter->GetOutput();
break;
}
case 6:
{
typedef itk::ShToOdfImageFilter< float, 6 > ShConverterType;
typename ShConverterType::InputImageType::Pointer itkvol = ShConverterType::InputImageType::New();
mitk::CastToItkImage(mitkImage, itkvol);
typename ShConverterType::Pointer converter = ShConverterType::New();
converter->SetInput(itkvol);
converter->SetToolkit(mitkShImage->GetShConvention());
converter->Update();
output = converter->GetOutput();
break;
}
case 8:
{
typedef itk::ShToOdfImageFilter< float, 8 > ShConverterType;
typename ShConverterType::InputImageType::Pointer itkvol = ShConverterType::InputImageType::New();
mitk::CastToItkImage(mitkImage, itkvol);
typename ShConverterType::Pointer converter = ShConverterType::New();
converter->SetInput(itkvol);
converter->SetToolkit(mitkShImage->GetShConvention());
converter->Update();
output = converter->GetOutput();
break;
}
case 10:
{
typedef itk::ShToOdfImageFilter< float, 10 > ShConverterType;
typename ShConverterType::InputImageType::Pointer itkvol = ShConverterType::InputImageType::New();
mitk::CastToItkImage(mitkImage, itkvol);
typename ShConverterType::Pointer converter = ShConverterType::New();
converter->SetInput(itkvol);
converter->SetToolkit(mitkShImage->GetShConvention());
converter->Update();
output = converter->GetOutput();
break;
}
case 12:
{
typedef itk::ShToOdfImageFilter< float, 12 > ShConverterType;
typename ShConverterType::InputImageType::Pointer itkvol = ShConverterType::InputImageType::New();
mitk::CastToItkImage(mitkImage, itkvol);
typename ShConverterType::Pointer converter = ShConverterType::New();
converter->SetInput(itkvol);
converter->SetToolkit(mitkShImage->GetShConvention());
converter->Update();
output = converter->GetOutput();
break;
}
default:
mitkThrow() << "SH orders higher than 12 are not supported!";
}
return output;
}
mitk::OdfImage::Pointer mitk::convert::GetOdfFromShImage(mitk::Image::Pointer mitkImage)
{
mitk::OdfImage::Pointer image = mitk::OdfImage::New();
auto img = GetItkOdfFromShImage(mitkImage);
image->InitializeByItk( img.GetPointer() );
image->SetVolume( img->GetBufferPointer() );
return image;
}
mitk::OdfImage::ItkOdfImageType::Pointer mitk::convert::GetItkOdfFromTensorImage(mitk::Image::Pointer mitkImage)
{
typedef itk::TensorImageToOdfImageFilter< float, float > FilterType;
FilterType::Pointer filter = FilterType::New();
filter->SetInput( GetItkTensorFromTensorImage(mitkImage) );
filter->Update();
return filter->GetOutput();
}
mitk::TensorImage::ItkTensorImageType::Pointer mitk::convert::GetItkTensorFromTensorImage(mitk::Image::Pointer mitkImage)
{
typedef mitk::ImageToItk< mitk::TensorImage::ItkTensorImageType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(mitkImage);
caster->Update();
return caster->GetOutput();
}
mitk::PeakImage::ItkPeakImageType::Pointer mitk::convert::GetItkPeakFromPeakImage(mitk::Image::Pointer mitkImage)
{
typedef mitk::ImageToItk< mitk::PeakImage::ItkPeakImageType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(mitkImage);
caster->SetCopyMemFlag(true);
caster->Update();
return caster->GetOutput();
}
mitk::OdfImage::Pointer mitk::convert::GetOdfFromTensorImage(mitk::Image::Pointer mitkImage)
{
mitk::OdfImage::Pointer image = mitk::OdfImage::New();
auto img = GetItkOdfFromTensorImage(mitkImage);
image->InitializeByItk( img.GetPointer() );
image->SetVolume( img->GetBufferPointer() );
return image;
}
mitk::OdfImage::ItkOdfImageType::Pointer mitk::convert::GetItkOdfFromOdfImage(mitk::Image::Pointer mitkImage)
{
typedef mitk::ImageToItk< mitk::OdfImage::ItkOdfImageType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(mitkImage);
caster->Update();
return caster->GetOutput();
}
vnl_matrix<float> mitk::sh::CalcShBasisForDirections(unsigned int sh_order, vnl_matrix<double> U, bool mrtrix)
{
vnl_matrix<float> sh_basis = vnl_matrix<float>(U.cols(), (sh_order*sh_order + sh_order + 2)/2 + sh_order );
for(unsigned int i=0; i<U.cols(); i++)
{
double x = U(0,i);
double y = U(1,i);
double z = U(2,i);
double spherical[3];
mitk::sh::Cart2Sph(x,y,z,spherical);
U(0,i) = spherical[0];
U(1,i) = spherical[1];
U(2,i) = spherical[2];
}
for(unsigned int i=0; i<U.cols(); i++)
{
for(int k=0; k<=static_cast<int>(sh_order); k+=2)
{
for(int m=-k; m<=k; m++)
{
int j = (k*k + k + 2)/2 + m - 1;
double phi = U(0,i);
double th = U(1,i);
sh_basis(i,j) = mitk::sh::Yj(m,k,th,phi, mrtrix);
}
}
}
return sh_basis;
}
unsigned int mitk::sh::ShOrder(int num_coeffs)
{
int c=3, d=2-2*num_coeffs;
int D = c*c-4*d;
if (D>0)
{
int s = (-c+static_cast<int>(sqrt(D)))/2;
if (s<0)
s = (-c-static_cast<int>(sqrt(D)))/2;
return static_cast<unsigned int>(s);
}
else if (D==0)
return static_cast<unsigned int>(-c/2);
return 0;
}
float mitk::sh::GetValue(const vnl_vector<float> &coefficients, const int &sh_order, const double theta, const double phi, const bool mrtrix)
{
float val = 0;
for(int k=0; k<=sh_order; k+=2)
{
for(int m=-k; m<=k; m++)
{
unsigned int j = static_cast<unsigned int>((k*k + k + 2)/2 + m - 1);
val += coefficients[j] * mitk::sh::Yj(m, k, theta, phi, mrtrix);
}
}
return val;
}
float mitk::sh::GetValue(const vnl_vector<float> &coefficients, const int &sh_order, const vnl_vector_fixed<double, 3> &dir, const bool mrtrix)
{
double spherical[3];
mitk::sh::Cart2Sph(dir[0], dir[1], dir[2], spherical);
float val = 0;
for(int k=0; k<=sh_order; k+=2)
{
for(int m=-k; m<=k; m++)
{
int j = (k*k + k + 2)/2 + m - 1;
val += coefficients[j] * mitk::sh::Yj(m, k, spherical[1], spherical[0], mrtrix);
}
}
return val;
}
//------------------------- gradients-function ------------------------------------
mitk::gradients::GradientDirectionContainerType::Pointer mitk::gradients::ReadBvalsBvecs(std::string bvals_file, std::string bvecs_file, double& reference_bval)
{
mitk::gradients::GradientDirectionContainerType::Pointer directioncontainer = mitk::gradients::GradientDirectionContainerType::New();
std::vector<float> bvec_entries;
if (!itksys::SystemTools::FileExists(bvecs_file))
mitkThrow() << "bvecs file not existing: " << bvecs_file;
else
{
std::string line;
std::ifstream myfile (bvecs_file.c_str());
if (myfile.is_open())
{
while (std::getline(myfile, line))
{
std::vector<std::string> strs;
boost::split(strs,line,boost::is_any_of("\t \n"));
for (auto token : strs)
{
if (!token.empty())
{
try
{
bvec_entries.push_back(boost::lexical_cast<float>(token));
}
catch(...)
{
mitkThrow() << "Encountered invalid bvecs file entry >" << token << "<";
}
}
}
}
myfile.close();
}
else
{
mitkThrow() << "bvecs file could not be opened: " << bvals_file;
}
}
reference_bval = -1;
std::vector<float> bval_entries;
if (!itksys::SystemTools::FileExists(bvals_file))
mitkThrow() << "bvals file not existing: " << bvals_file;
else
{
std::string line;
std::ifstream myfile (bvals_file.c_str());
if (myfile.is_open())
{
while (std::getline(myfile, line))
{
std::vector<std::string> strs;
boost::split(strs,line,boost::is_any_of("\t \n"));
for (auto token : strs)
{
if (!token.empty())
{
try {
bval_entries.push_back(boost::lexical_cast<float>(token));
if (bval_entries.back()>reference_bval)
reference_bval = bval_entries.back();
}
catch(...)
{
mitkThrow() << "Encountered invalid bvals file entry >" << token << "<";
}
}
}
}
myfile.close();
}
else
{
mitkThrow() << "bvals file could not be opened: " << bvals_file;
}
}
for(unsigned int i=0; i<bval_entries.size(); i++)
{
double b_val = bval_entries.at(i);
mitk::gradients::GradientDirectionType vec;
vec[0] = bvec_entries.at(i);
vec[1] = bvec_entries.at(i+bval_entries.size());
vec[2] = bvec_entries.at(i+2*bval_entries.size());
// Adjust the vector length to encode gradient strength
if (reference_bval>0)
{
double factor = b_val/reference_bval;
if(vec.magnitude() > 0)
{
vec.normalize();
vec[0] = sqrt(factor)*vec[0];
vec[1] = sqrt(factor)*vec[1];
vec[2] = sqrt(factor)*vec[2];
}
}
directioncontainer->InsertElement(i,vec);
}
return directioncontainer;
}
void mitk::gradients::WriteBvalsBvecs(std::string bvals_file, std::string bvecs_file, GradientDirectionContainerType::Pointer gradients, double reference_bval)
{
std::ofstream myfile;
myfile.open (bvals_file.c_str());
for(unsigned int i=0; i<gradients->Size(); i++)
{
double twonorm = gradients->ElementAt(i).two_norm();
myfile << std::round(reference_bval*twonorm*twonorm) << " ";
}
myfile.close();
std::ofstream myfile2;
myfile2.open (bvecs_file.c_str());
for(int j=0; j<3; j++)
{
for(unsigned int i=0; i<gradients->Size(); i++)
{
GradientDirectionType direction = gradients->ElementAt(i);
direction.normalize();
myfile2 << direction.get(j) << " ";
}
myfile2 << std::endl;
}
}
std::vector<unsigned int> mitk::gradients::GetAllUniqueDirections(const BValueMap & refBValueMap, GradientDirectionContainerType *refGradientsContainer )
{
IndiciesVector directioncontainer;
auto mapIterator = refBValueMap.begin();
if(refBValueMap.find(0) != refBValueMap.end() && refBValueMap.size() > 1)
mapIterator++; //skip bzero Values
for( ; mapIterator != refBValueMap.end(); mapIterator++){
IndiciesVector currentShell = mapIterator->second;
while(currentShell.size()>0)
{
unsigned int wntIndex = currentShell.back();
currentShell.pop_back();
auto containerIt = directioncontainer.begin();
bool directionExist = false;
while(containerIt != directioncontainer.end())
{
if (fabs(dot_product(refGradientsContainer->ElementAt(*containerIt), refGradientsContainer->ElementAt(wntIndex))) > 0.9998)
{
directionExist = true;
break;
}
containerIt++;
}
if(!directionExist)
{
directioncontainer.push_back(wntIndex);
}
}
}
return directioncontainer;
}
bool mitk::gradients::CheckForDifferingShellDirections(const BValueMap & refBValueMap, GradientDirectionContainerType::ConstPointer refGradientsContainer)
{
auto mapIterator = refBValueMap.begin();
if(refBValueMap.find(0) != refBValueMap.end() && refBValueMap.size() > 1)
mapIterator++; //skip bzero Values
for( ; mapIterator != refBValueMap.end(); mapIterator++){
auto mapIterator_2 = refBValueMap.begin();
if(refBValueMap.find(0) != refBValueMap.end() && refBValueMap.size() > 1)
mapIterator_2++; //skip bzero Values
for( ; mapIterator_2 != refBValueMap.end(); mapIterator_2++){
if(mapIterator_2 == mapIterator) continue;
IndiciesVector currentShell = mapIterator->second;
IndiciesVector testShell = mapIterator_2->second;
for (unsigned int i = 0; i< currentShell.size(); i++)
if (fabs(dot_product(refGradientsContainer->ElementAt(currentShell[i]), refGradientsContainer->ElementAt(testShell[i]))) <= 0.9998) { return true; }
}
}
return false;
}
vnl_matrix<double> mitk::gradients::ComputeSphericalFromCartesian(const IndiciesVector & refShell, const GradientDirectionContainerType * refGradientsContainer)
{
vnl_matrix<double> Q(3, refShell.size());
Q.fill(0.0);
for(unsigned int i = 0; i < refShell.size(); i++)
{
GradientDirectionType dir = refGradientsContainer->ElementAt(refShell[i]);
double x = dir.normalize().get(0);
double y = dir.normalize().get(1);
double z = dir.normalize().get(2);
double cart[3];
mitk::sh::Cart2Sph(x,y,z,cart);
Q(0,i) = cart[0];
Q(1,i) = cart[1];
Q(2,i) = cart[2];
}
return Q;
}
vnl_matrix<double> mitk::gradients::ComputeSphericalHarmonicsBasis(const vnl_matrix<double> & QBallReference, const unsigned int & LOrder)
{
vnl_matrix<double> SHBasisOutput(QBallReference.cols(), (LOrder+1)*(LOrder+2)*0.5);
SHBasisOutput.fill(0.0);
for(unsigned int i=0; i<SHBasisOutput.rows(); i++)
for(int k = 0; k <= (int)LOrder; k += 2)
for(int m =- k; m <= k; m++)
{
int j = ( k * k + k + 2 ) / 2.0 + m - 1;
double phi = QBallReference(0,i);
double th = QBallReference(1,i);
double val = mitk::sh::Yj(m,k,th,phi);
SHBasisOutput(i,j) = val;
}
return SHBasisOutput;
}
mitk::gradients::GradientDirectionContainerType::Pointer mitk::gradients::CreateNormalizedUniqueGradientDirectionContainer(const mitk::gradients::BValueMap & bValueMap,
const GradientDirectionContainerType *origninalGradentcontainer)
{
mitk::gradients::GradientDirectionContainerType::Pointer directioncontainer = mitk::gradients::GradientDirectionContainerType::New();
auto mapIterator = bValueMap.begin();
if(bValueMap.find(0) != bValueMap.end() && bValueMap.size() > 1){
mapIterator++; //skip bzero Values
vnl_vector_fixed<double, 3> vec;
vec.fill(0.0);
directioncontainer->push_back(vec);
}
for( ; mapIterator != bValueMap.end(); mapIterator++){
IndiciesVector currentShell = mapIterator->second;
while(currentShell.size()>0)
{
unsigned int wntIndex = currentShell.back();
currentShell.pop_back();
mitk::gradients::GradientDirectionContainerType::Iterator containerIt = directioncontainer->Begin();
bool directionExist = false;
while(containerIt != directioncontainer->End())
{
if (fabs(dot_product(containerIt.Value(), origninalGradentcontainer->ElementAt(wntIndex))) > 0.9998)
{
directionExist = true;
break;
}
containerIt++;
}
if(!directionExist)
{
GradientDirectionType dir(origninalGradentcontainer->ElementAt(wntIndex));
directioncontainer->push_back(dir.normalize());
}
}
}
return directioncontainer;
}
diff --git a/Modules/DiffusionCore/mitkDiffusionFunctionCollection.h b/Modules/DiffusionCore/mitkDiffusionFunctionCollection.h
index 37867c0..ed135c5 100644
--- a/Modules/DiffusionCore/mitkDiffusionFunctionCollection.h
+++ b/Modules/DiffusionCore/mitkDiffusionFunctionCollection.h
@@ -1,259 +1,259 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkDiffusionFunctionCollection_h_
#define __mitkDiffusionFunctionCollection_h_
#include <MitkDiffusionCoreExports.h>
#include <vnl/vnl_vector.h>
#include <vnl/vnl_vector_fixed.h>
#include <itkVectorContainer.h>
#include <itkImage.h>
#include <itkLinearInterpolateImageFunction.h>
#include <mitkImage.h>
#include <mitkShImage.h>
#include <mitkDiffusionPropertyHelper.h>
#include <mitkOdfImage.h>
#include <mitkTensorImage.h>
#include <mitkPeakImage.h>
#include <itkOrientationDistributionFunction.h>
#include <mitkImageCast.h>
#include <mitkImageToItk.h>
namespace mitk{
class MITKDIFFUSIONCORE_EXPORT imv
{
public:
static std::vector< std::pair< itk::Index<3>, double > > IntersectImage(const itk::Vector<double,3>& spacing, itk::Index<3>& si, itk::Index<3>& ei, itk::ContinuousIndex<float, 3>& sf, itk::ContinuousIndex<float, 3>& ef);
static itk::Point<float, 3> GetItkPoint(double point[3])
{
itk::Point<float, 3> itkPoint;
itkPoint[0] = static_cast<float>(point[0]);
itkPoint[1] = static_cast<float>(point[1]);
itkPoint[2] = static_cast<float>(point[2]);
return itkPoint;
}
template< class TType >
static itk::Point<float, 3> GetItkPoint(double point[3])
{
itk::Point<TType, 3> itkPoint;
itkPoint[0] = static_cast<TType>(point[0]);
itkPoint[1] = static_cast<TType>(point[1]);
itkPoint[2] = static_cast<TType>(point[2]);
return itkPoint;
}
template< class TType >
static itk::Vector<float, 3> GetItkVector(double point[3])
{
itk::Vector<TType, 3> itkVector;
itkVector[0] = static_cast<TType>(point[0]);
itkVector[1] = static_cast<TType>(point[1]);
itkVector[2] = static_cast<TType>(point[2]);
return itkVector;
}
template< class TPixelType, class TOutPixelType=TPixelType >
static TOutPixelType GetImageValue(const itk::Point<float, 3>& itkP, bool interpolate, typename itk::LinearInterpolateImageFunction< itk::Image< TPixelType, 3 >, float >::Pointer interpolator)
{
if (interpolator==nullptr)
return 0.0;
itk::ContinuousIndex< float, 3> cIdx;
interpolator->ConvertPointToContinuousIndex(itkP, cIdx);
if (interpolator->IsInsideBuffer(cIdx))
{
if (interpolate)
return interpolator->EvaluateAtContinuousIndex(cIdx);
else
{
itk::Index<3> idx;
interpolator->ConvertContinuousIndexToNearestIndex(cIdx, idx);
return interpolator->EvaluateAtIndex(idx);
}
}
else
return 0.0;
}
template< class TPixelType=unsigned char >
static bool IsInsideMask(const itk::Point<float, 3>& itkP, bool interpolate, typename itk::LinearInterpolateImageFunction< itk::Image< TPixelType, 3 >, float >::Pointer interpolator, float threshold=0.5)
{
if (interpolator==nullptr)
return false;
itk::ContinuousIndex< float, 3> cIdx;
interpolator->ConvertPointToContinuousIndex(itkP, cIdx);
if (interpolator->IsInsideBuffer(cIdx))
{
float value = 0.0;
if (interpolate)
value = interpolator->EvaluateAtContinuousIndex(cIdx);
else
{
itk::Index<3> idx;
interpolator->ConvertContinuousIndexToNearestIndex(cIdx, idx);
value = interpolator->EvaluateAtIndex(idx);
}
if (value>=threshold)
return true;
}
return false;
}
template< class TType=float >
static vnl_matrix_fixed< TType, 3, 3 > GetRotationMatrixVnl(TType rx, TType ry, TType rz)
{
rx = rx*itk::Math::pi/180;
ry = ry*itk::Math::pi/180;
rz = rz*itk::Math::pi/180;
vnl_matrix_fixed< TType, 3, 3 > rotX; rotX.set_identity();
rotX[1][1] = cos(rx);
rotX[2][2] = rotX[1][1];
rotX[1][2] = -sin(rx);
rotX[2][1] = -rotX[1][2];
vnl_matrix_fixed< TType, 3, 3 > rotY; rotY.set_identity();
rotY[0][0] = cos(ry);
rotY[2][2] = rotY[0][0];
rotY[0][2] = sin(ry);
rotY[2][0] = -rotY[0][2];
vnl_matrix_fixed< TType, 3, 3 > rotZ; rotZ.set_identity();
rotZ[0][0] = cos(rz);
rotZ[1][1] = rotZ[0][0];
rotZ[0][1] = -sin(rz);
rotZ[1][0] = -rotZ[0][1];
vnl_matrix_fixed< TType, 3, 3 > rot = rotZ*rotY*rotX;
return rot;
}
template< class TType=float >
static itk::Matrix< TType, 3, 3 > GetRotationMatrixItk(TType rx, TType ry, TType rz)
{
rx = rx*itk::Math::pi/180;
ry = ry*itk::Math::pi/180;
rz = rz*itk::Math::pi/180;
itk::Matrix< TType, 3, 3 > rotX; rotX.SetIdentity();
rotX[1][1] = cos(rx);
rotX[2][2] = rotX[1][1];
rotX[1][2] = -sin(rx);
rotX[2][1] = -rotX[1][2];
itk::Matrix< TType, 3, 3 > rotY; rotY.SetIdentity();
rotY[0][0] = cos(ry);
rotY[2][2] = rotY[0][0];
rotY[0][2] = sin(ry);
rotY[2][0] = -rotY[0][2];
itk::Matrix< TType, 3, 3 > rotZ; rotZ.SetIdentity();
rotZ[0][0] = cos(rz);
rotZ[1][1] = rotZ[0][0];
rotZ[0][1] = -sin(rz);
rotZ[1][0] = -rotZ[0][1];
itk::Matrix< TType, 3, 3 > rot = rotZ*rotY*rotX;
return rot;
}
};
class MITKDIFFUSIONCORE_EXPORT convert
{
public:
static mitk::OdfImage::ItkOdfImageType::Pointer GetItkOdfFromTensorImage(mitk::Image::Pointer mitkImage);
static mitk::OdfImage::Pointer GetOdfFromTensorImage(mitk::Image::Pointer mitkImage);
static mitk::TensorImage::ItkTensorImageType::Pointer GetItkTensorFromTensorImage(mitk::Image::Pointer mitkImage);
static mitk::PeakImage::ItkPeakImageType::Pointer GetItkPeakFromPeakImage(mitk::Image::Pointer mitkImage);
template<unsigned int NUM_COEFFS>
static typename itk::Image< itk::Vector<float, NUM_COEFFS>, 3>::Pointer GetItkShFromShImage(mitk::Image::Pointer mitkImage)
{
mitk::ShImage::Pointer mitkShImage = dynamic_cast<mitk::ShImage*>(mitkImage.GetPointer());
if (mitkShImage.IsNull())
mitkThrow() << "Input image is not a SH image!";
typename itk::Image< itk::Vector<float, NUM_COEFFS>, 3>::Pointer itkvol;
mitk::CastToItkImage(mitkImage, itkvol);
return itkvol;
}
static mitk::OdfImage::ItkOdfImageType::Pointer GetItkOdfFromShImage(mitk::Image::Pointer mitkImage);
static mitk::OdfImage::Pointer GetOdfFromShImage(mitk::Image::Pointer mitkImage);
static mitk::OdfImage::ItkOdfImageType::Pointer GetItkOdfFromOdfImage(mitk::Image::Pointer mitkImage);
};
class MITKDIFFUSIONCORE_EXPORT sh
{
public:
static double factorial(int number);
static void Cart2Sph(double x, double y, double z, double* spherical);
static vnl_vector_fixed<double, 3> Sph2Cart(const double& theta, const double& phi, const double& rad);
static double legendre0(int l);
static double spherical_harmonic(int m,int l,double theta,double phi, bool complexPart);
static double Yj(int m, int k, float theta, float phi, bool mrtrix=true);
static vnl_matrix<float> CalcShBasisForDirections(unsigned int sh_order, vnl_matrix<double> U, bool mrtrix=true);
static float GetValue(const vnl_vector<float>& coefficients, const int& sh_order, const vnl_vector_fixed<double, 3>& dir, const bool mrtrix);
static float GetValue(const vnl_vector<float> &coefficients, const int &sh_order, const double theta, const double phi, const bool mrtrix);
static unsigned int ShOrder(int num_coeffs);
template <unsigned int N, typename TComponent=float>
static void SampleOdf(const vnl_vector<float>& coefficients, itk::OrientationDistributionFunction<TComponent, N>& odf)
{
auto dirs = odf.GetDirections();
auto basis = CalcShBasisForDirections(ShOrder(coefficients.size()), *dirs);
auto odf_vals = basis * coefficients;
for (unsigned int i=0; i<odf_vals.size(); ++i)
odf[i] = odf_vals[i];
}
};
class MITKDIFFUSIONCORE_EXPORT gradients
{
private:
typedef std::vector<unsigned int> IndiciesVector;
typedef mitk::BValueMapProperty::BValueMap BValueMap;
typedef DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType;
typedef DiffusionPropertyHelper::GradientDirectionType GradientDirectionType;
public:
static GradientDirectionContainerType::Pointer ReadBvalsBvecs(std::string bvals_file, std::string bvecs_file, double& reference_bval);
static void WriteBvalsBvecs(std::string bvals_file, std::string bvecs_file, GradientDirectionContainerType::Pointer gradients, double reference_bval);
static std::vector<unsigned int> GetAllUniqueDirections(const BValueMap &bValueMap, GradientDirectionContainerType *refGradientsContainer );
static bool CheckForDifferingShellDirections(const BValueMap &bValueMap, GradientDirectionContainerType::ConstPointer refGradientsContainer);
static vnl_matrix<double> ComputeSphericalHarmonicsBasis(const vnl_matrix<double> & QBallReference, const unsigned int & LOrder);
static vnl_matrix<double> ComputeSphericalFromCartesian(const IndiciesVector & refShell, const GradientDirectionContainerType * refGradientsContainer);
static GradientDirectionContainerType::Pointer CreateNormalizedUniqueGradientDirectionContainer(const BValueMap &bValueMap, const GradientDirectionContainerType * origninalGradentcontainer);
};
}
#endif //__mitkDiffusionFunctionCollection_h_
diff --git a/Modules/DiffusionIO/ObjectFactories/mitkConnectomicsObjectFactory.cpp b/Modules/DiffusionIO/ObjectFactories/mitkConnectomicsObjectFactory.cpp
index 2069b6c..aed9f88 100644
--- a/Modules/DiffusionIO/ObjectFactories/mitkConnectomicsObjectFactory.cpp
+++ b/Modules/DiffusionIO/ObjectFactories/mitkConnectomicsObjectFactory.cpp
@@ -1,110 +1,110 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsObjectFactory.h"
#include "mitkConnectomicsNetwork.h"
#include "mitkConnectomicsNetworkMapper3D.h"
mitk::ConnectomicsObjectFactory::ConnectomicsObjectFactory()
: CoreObjectFactoryBase()
{
static bool alreadyDone = false;
if (!alreadyDone)
{
MITK_DEBUG << "ConnectomicsObjectFactory c'tor" << std::endl;
alreadyDone = true;
}
}
mitk::ConnectomicsObjectFactory::~ConnectomicsObjectFactory()
{
}
mitk::Mapper::Pointer mitk::ConnectomicsObjectFactory::CreateMapper(mitk::DataNode* node, MapperSlotId id)
{
mitk::Mapper::Pointer newMapper=nullptr;
if ( id == mitk::BaseRenderer::Standard3D )
{
std::string classname("ConnectomicsNetwork");
if (node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
{
newMapper = mitk::ConnectomicsNetworkMapper3D::New();
newMapper->SetDataNode(node);
}
}
return newMapper;
}
void mitk::ConnectomicsObjectFactory::SetDefaultProperties(mitk::DataNode* node)
{
std::string classname("ConnectomicsNetwork");
if(node->GetData() && classname.compare(node->GetData()->GetNameOfClass())==0)
{
mitk::ConnectomicsNetworkMapper3D::SetDefaultProperties(node);
}
}
const char* mitk::ConnectomicsObjectFactory::GetFileExtensions()
{
std::string fileExtension;
this->CreateFileExtensions(m_FileExtensionsMap, fileExtension);
return fileExtension.c_str();
};
mitk::CoreObjectFactoryBase::MultimapType mitk::ConnectomicsObjectFactory::GetFileExtensionsMap()
{
return m_FileExtensionsMap;
}
const char* mitk::ConnectomicsObjectFactory::GetSaveFileExtensions()
{
std::string fileExtension;
this->CreateFileExtensions(m_SaveFileExtensionsMap, fileExtension);
return fileExtension.c_str();
};
mitk::CoreObjectFactoryBase::MultimapType mitk::ConnectomicsObjectFactory::GetSaveFileExtensionsMap()
{
return m_SaveFileExtensionsMap;
}
void mitk::ConnectomicsObjectFactory::CreateFileExtensionsMap()
{
}
struct RegisterConnectomicsObjectFactory{
RegisterConnectomicsObjectFactory()
: m_Factory( mitk::ConnectomicsObjectFactory::New() )
{
mitk::CoreObjectFactory::GetInstance()->RegisterExtraFactory( m_Factory );
}
~RegisterConnectomicsObjectFactory()
{
mitk::CoreObjectFactory::GetInstance()->UnRegisterExtraFactory( m_Factory );
}
mitk::ConnectomicsObjectFactory::Pointer m_Factory;
};
static RegisterConnectomicsObjectFactory registerDiffusionCoreObjectFactory;
diff --git a/Modules/DiffusionIO/ObjectFactories/mitkConnectomicsObjectFactory.h b/Modules/DiffusionIO/ObjectFactories/mitkConnectomicsObjectFactory.h
index 695c577..26addc0 100644
--- a/Modules/DiffusionIO/ObjectFactories/mitkConnectomicsObjectFactory.h
+++ b/Modules/DiffusionIO/ObjectFactories/mitkConnectomicsObjectFactory.h
@@ -1,62 +1,62 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKCONNECTOMICSOBJECTFACTORY_H
#define MITKCONNECTOMICSOBJECTFACTORY_H
#include "mitkCoreObjectFactory.h"
namespace mitk {
class ConnectomicsObjectFactory : public CoreObjectFactoryBase
{
public:
mitkClassMacro(ConnectomicsObjectFactory,CoreObjectFactoryBase)
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
~ConnectomicsObjectFactory() override;
Mapper::Pointer CreateMapper(mitk::DataNode* node, MapperSlotId slotId) override;
void SetDefaultProperties(mitk::DataNode* node) override;
const char* GetFileExtensions() override;
mitk::CoreObjectFactoryBase::MultimapType GetFileExtensionsMap() override;
const char* GetSaveFileExtensions() override;
mitk::CoreObjectFactoryBase::MultimapType GetSaveFileExtensionsMap() override;
protected:
ConnectomicsObjectFactory();
private:
void CreateFileExtensionsMap();
std::string m_ExternalFileExtensions;
std::string m_InternalFileExtensions;
std::string m_SaveFileExtensions;
MultimapType m_FileExtensionsMap;
MultimapType m_SaveFileExtensionsMap;
itk::ObjectFactoryBase::Pointer m_ConnectomicsNetworkIOFactory;
itk::ObjectFactoryBase::Pointer m_ConnectomicsNetworkWriterFactory;
};
}
#endif
diff --git a/Modules/DiffusionIO/ObjectFactories/mitkDiffusionCoreObjectFactory.cpp b/Modules/DiffusionIO/ObjectFactories/mitkDiffusionCoreObjectFactory.cpp
index 6a561e1..94cb6b0 100644
--- a/Modules/DiffusionIO/ObjectFactories/mitkDiffusionCoreObjectFactory.cpp
+++ b/Modules/DiffusionIO/ObjectFactories/mitkDiffusionCoreObjectFactory.cpp
@@ -1,204 +1,204 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkDiffusionCoreObjectFactory.h"
#include "mitkProperties.h"
#include "mitkBaseRenderer.h"
#include "mitkDataNode.h"
#include "mitkCompositeMapper.h"
#include "mitkGPUVolumeMapper3D.h"
#include <mitkFiberBundleMapper3D.h>
#include <mitkFiberBundleMapper2D.h>
#include <mitkPeakImageMapper2D.h>
#include <mitkPeakImageMapper3D.h>
typedef short DiffusionPixelType;
typedef std::multimap<std::string, std::string> MultimapType;
mitk::DiffusionCoreObjectFactory::DiffusionCoreObjectFactory()
: CoreObjectFactoryBase()
{
static bool alreadyDone = false;
if (!alreadyDone)
{
MITK_DEBUG << "DiffusionCoreObjectFactory c'tor" << std::endl;
CreateFileExtensionsMap();
alreadyDone = true;
}
}
mitk::DiffusionCoreObjectFactory::~DiffusionCoreObjectFactory()
{
}
mitk::Mapper::Pointer mitk::DiffusionCoreObjectFactory::CreateMapper(mitk::DataNode* node, MapperSlotId id)
{
mitk::Mapper::Pointer newMapper=nullptr;
if (!node->GetData())
return newMapper;
if ( id == mitk::BaseRenderer::Standard2D )
{
if(std::string("OdfImage").compare(node->GetData()->GetNameOfClass())==0)
{
newMapper = mitk::CompositeMapper::New();
newMapper->SetDataNode(node);
node->SetMapper(3, static_cast<CompositeMapper*>(newMapper.GetPointer())->GetImageMapper());
}
else if(std::string("TensorImage").compare(node->GetData()->GetNameOfClass())==0)
{
newMapper = mitk::CompositeMapper::New();
newMapper->SetDataNode(node);
node->SetMapper(3, static_cast<CompositeMapper*>(newMapper.GetPointer())->GetImageMapper());
}
else if(std::string("ShImage").compare(node->GetData()->GetNameOfClass())==0)
{
newMapper = mitk::CompositeMapper::New();
newMapper->SetDataNode(node);
node->SetMapper(3, static_cast<CompositeMapper*>(newMapper.GetPointer())->GetImageMapper());
}
else if(std::string("FiberBundle").compare(node->GetData()->GetNameOfClass())==0)
{
newMapper = mitk::FiberBundleMapper2D::New();
newMapper->SetDataNode(node);
}
else if(std::string("PeakImage").compare(node->GetData()->GetNameOfClass())==0)
{
newMapper = mitk::PeakImageMapper2D::New();
newMapper->SetDataNode(node);
}
}
else if ( id == mitk::BaseRenderer::Standard3D )
{
if(std::string("OdfImage").compare(node->GetData()->GetNameOfClass())==0)
{
newMapper = mitk::GPUVolumeMapper3D::New();
newMapper->SetDataNode(node);
}
else if(std::string("TensorImage").compare(node->GetData()->GetNameOfClass())==0)
{
newMapper = mitk::GPUVolumeMapper3D::New();
newMapper->SetDataNode(node);
}
else if(std::string("ShImage").compare(node->GetData()->GetNameOfClass())==0)
{
newMapper = mitk::GPUVolumeMapper3D::New();
newMapper->SetDataNode(node);
}
else if(std::string("FiberBundle").compare(node->GetData()->GetNameOfClass())==0)
{
newMapper = mitk::FiberBundleMapper3D::New();
newMapper->SetDataNode(node);
}
else if(std::string("PeakImage").compare(node->GetData()->GetNameOfClass())==0)
{
newMapper = mitk::PeakImageMapper3D::New();
newMapper->SetDataNode(node);
}
}
return newMapper;
}
void mitk::DiffusionCoreObjectFactory::SetDefaultProperties(mitk::DataNode* node)
{
if (!node->GetData())
return;
if(std::string("OdfImage").compare(node->GetData()->GetNameOfClass())==0)
{
mitk::CompositeMapper::SetDefaultProperties(node);
mitk::GPUVolumeMapper3D::SetDefaultProperties(node);
}
else if(std::string("TensorImage").compare(node->GetData()->GetNameOfClass())==0)
{
mitk::CompositeMapper::SetDefaultProperties(node);
mitk::GPUVolumeMapper3D::SetDefaultProperties(node);
}
else if(std::string("ShImage").compare(node->GetData()->GetNameOfClass())==0)
{
mitk::CompositeMapper::SetDefaultProperties(node);
mitk::GPUVolumeMapper3D::SetDefaultProperties(node);
}
else if(std::string("FiberBundle").compare(node->GetData()->GetNameOfClass())==0)
{
mitk::FiberBundleMapper3D::SetDefaultProperties(node);
mitk::FiberBundleMapper2D::SetDefaultProperties(node);
}
else if (std::string("PeakImage").compare(node->GetData()->GetNameOfClass())==0)
{
mitk::PeakImageMapper3D::SetDefaultProperties(node);
mitk::PeakImageMapper2D::SetDefaultProperties(node);
}
}
const char* mitk::DiffusionCoreObjectFactory::GetFileExtensions()
{
std::string fileExtension;
this->CreateFileExtensions(m_FileExtensionsMap, fileExtension);
return fileExtension.c_str();
}
mitk::CoreObjectFactoryBase::MultimapType mitk::DiffusionCoreObjectFactory::GetFileExtensionsMap()
{
return m_FileExtensionsMap;
}
const char* mitk::DiffusionCoreObjectFactory::GetSaveFileExtensions()
{
std::string fileExtension;
this->CreateFileExtensions(m_SaveFileExtensionsMap, fileExtension);
return fileExtension.c_str();
}
mitk::CoreObjectFactoryBase::MultimapType mitk::DiffusionCoreObjectFactory::GetSaveFileExtensionsMap()
{
return m_SaveFileExtensionsMap;
}
void mitk::DiffusionCoreObjectFactory::CreateFileExtensionsMap()
{
}
struct RegisterDiffusionCoreObjectFactory{
RegisterDiffusionCoreObjectFactory()
: m_Factory( mitk::DiffusionCoreObjectFactory::New() )
{
mitk::CoreObjectFactory::GetInstance()->RegisterExtraFactory( m_Factory );
}
~RegisterDiffusionCoreObjectFactory()
{
mitk::CoreObjectFactory::GetInstance()->UnRegisterExtraFactory( m_Factory );
}
mitk::DiffusionCoreObjectFactory::Pointer m_Factory;
};
static RegisterDiffusionCoreObjectFactory registerDiffusionCoreObjectFactory;
diff --git a/Modules/DiffusionIO/ObjectFactories/mitkDiffusionCoreObjectFactory.h b/Modules/DiffusionIO/ObjectFactories/mitkDiffusionCoreObjectFactory.h
index 84fbb09..4f8d1b6 100644
--- a/Modules/DiffusionIO/ObjectFactories/mitkDiffusionCoreObjectFactory.h
+++ b/Modules/DiffusionIO/ObjectFactories/mitkDiffusionCoreObjectFactory.h
@@ -1,66 +1,66 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 DiffusionCoreObjectFactory_H_INCLUDED
#define DiffusionCoreObjectFactory_H_INCLUDED
#include "mitkCoreObjectFactory.h"
namespace mitk {
class DiffusionCoreObjectFactory : public CoreObjectFactoryBase
{
public:
mitkClassMacro(DiffusionCoreObjectFactory,CoreObjectFactoryBase)
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
~DiffusionCoreObjectFactory() override;
Mapper::Pointer CreateMapper(mitk::DataNode* node, MapperSlotId slotId) override;
void SetDefaultProperties(mitk::DataNode* node) override;
const char* GetFileExtensions() override;
mitk::CoreObjectFactoryBase::MultimapType GetFileExtensionsMap() override;
const char* GetSaveFileExtensions() override;
mitk::CoreObjectFactoryBase::MultimapType GetSaveFileExtensionsMap() override;
protected:
DiffusionCoreObjectFactory();
void CreateFileExtensionsMap();
MultimapType m_FileExtensionsMap;
MultimapType m_SaveFileExtensionsMap;
private:
std::string m_ExternalFileExtensions;
std::string m_InternalFileExtensions;
std::string m_SaveFileExtensions;
itk::ObjectFactoryBase::Pointer m_NrrdDiffusionImageIOFactory;
itk::ObjectFactoryBase::Pointer m_NrrdOdfImageIOFactory;
itk::ObjectFactoryBase::Pointer m_NrrdDiffusionImageWriterFactory;
itk::ObjectFactoryBase::Pointer m_NrrdOdfImageWriterFactory;
};
}
#endif
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkCSVWriter.cpp b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkCSVWriter.cpp
index d246175..321d337 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkCSVWriter.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkCSVWriter.cpp
@@ -1,141 +1,141 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsNetworkCSVWriter.h"
#include "mitkConnectomicsNetworkDefinitions.h"
#include "mitkDiffusionIOMimeTypes.h"
#include <mitkConnectomicsNetworkProperties.h>
#include <mitkStringProperty.h>
#include <boost/algorithm/string.hpp>
mitk::ConnectomicsNetworkCSVWriter::ConnectomicsNetworkCSVWriter()
: AbstractFileWriter(mitk::ConnectomicsNetwork::GetStaticNameOfClass(), CustomMimeType( mitk::DiffusionIOMimeTypes::CONNECTOMICS_LIST_MIMETYPE() ), "Write only CSV Connectomics Networks" )
{
RegisterService();
}
mitk::ConnectomicsNetworkCSVWriter::ConnectomicsNetworkCSVWriter(const mitk::ConnectomicsNetworkCSVWriter& other)
: AbstractFileWriter(other)
{
}
mitk::ConnectomicsNetworkCSVWriter::~ConnectomicsNetworkCSVWriter()
{}
mitk::ConnectomicsNetworkCSVWriter* mitk::ConnectomicsNetworkCSVWriter::Clone() const
{
return new ConnectomicsNetworkCSVWriter(*this);
}
void mitk::ConnectomicsNetworkCSVWriter::Write()
{
MITK_INFO << "Writing connectomics network";
InputType::ConstPointer input = dynamic_cast<const InputType*>(this->GetInput());
if (input.IsNull() )
{
MITK_ERROR <<"Sorry, input to ConnectomicsNetworkMatrixWriter is nullptr!";
return;
}
this->ValidateOutputLocation();
std::ostream* out;
std::ofstream outStream;
if( this->GetOutputStream() )
{
out = this->GetOutputStream();
}
else
{
outStream.open( this->GetOutputLocation().c_str() );
out = &outStream;
}
if ( !out->good() )
{
mitkThrow() << "Could not open stream.";
}
try
{
const std::string& locale = "C";
const std::string& currLocale = setlocale( LC_ALL, nullptr );
setlocale(LC_ALL, locale.c_str());
std::locale previousLocale(out->getloc());
std::locale I("C");
out->imbue(I);
// construct header
std::stringstream header;
mitk::StringProperty::Pointer addHeaderInfoProperty = dynamic_cast<mitk::StringProperty*>(input->GetProperty(connectomicsDataAdditionalHeaderInformation.c_str()).GetPointer());
if(addHeaderInfoProperty.IsNotNull())
{
std::string additionalHeaderInfo = addHeaderInfoProperty->GetValue();
// if the additional header info contains newlines we need to add #
// in front of the new lines
std::vector<std::string> strings;
boost::split(strings, additionalHeaderInfo, boost::is_any_of("\n"));
for( unsigned int index(0); index < strings.size(); ++index)
{
header << "#" << strings[index] << "\n";
}
}
// construct body
std::stringstream body;
std::vector< InputType::VertexDescriptorType > nodes = input->GetVectorOfAllVertexDescriptors();
for(unsigned int i(0); i < nodes.size(); ++i)
{
for(unsigned int j(0); j < i; ++j)
{
double weight(0);
if( input->EdgeExists(nodes[i], nodes[j]) )
{
weight = (input->GetEdge(nodes[i], nodes[j])).edge_weight;
}
body << (input->GetNode(nodes[i])).label << " "
<< (input->GetNode(nodes[j])).label << " "
<< weight << "\n";
}
}
(*out)<< header.str() << body.str();
setlocale(LC_ALL, currLocale.c_str());
MITK_INFO << "Connectomics network connection list written";
}
catch(...)
{
mitkThrow() << "Error while writing to stream.";
}
}
mitk::IFileIO::ConfidenceLevel mitk::ConnectomicsNetworkCSVWriter::GetConfidenceLevel() const
{
if (AbstractFileWriter::GetConfidenceLevel() == Unsupported)
{
return Unsupported;
}
// exporting is supported but will result in loss of data
// which prevents re-import
return PartiallySupported;
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkCSVWriter.h b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkCSVWriter.h
index 487ca50..900ccb0 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkCSVWriter.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkCSVWriter.h
@@ -1,61 +1,61 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkConnectomicsNetworkCSVWriter_h
#define __mitkConnectomicsNetworkCSVWriter_h
#include <mitkAbstractFileWriter.h>
#include "mitkConnectomicsNetwork.h"
#include <vtkPolyDataWriter.h>
namespace mitk
{
/**
* Writes connectomics networks to a file
*
* This export is write only, information is lost.
* @ingroup Process
*/
class ConnectomicsNetworkCSVWriter : public mitk::AbstractFileWriter
{
public:
typedef mitk::ConnectomicsNetwork InputType;
typedef std::vector< std::pair< std::pair<
mitk::ConnectomicsNetwork::NetworkNode, mitk::ConnectomicsNetwork::NetworkNode >
, mitk::ConnectomicsNetwork::NetworkEdge > > EdgeVectorType;
typedef std::vector< mitk::ConnectomicsNetwork::NetworkNode > VertexVectorType;
ConnectomicsNetworkCSVWriter();
~ConnectomicsNetworkCSVWriter() override;
using AbstractFileWriter::Write;
void Write() override;
mitk::IFileIO::ConfidenceLevel GetConfidenceLevel() const override;
protected:
ConnectomicsNetworkCSVWriter(const ConnectomicsNetworkCSVWriter& other);
mitk::ConnectomicsNetworkCSVWriter* Clone() const override;
};
} // end of namespace mitk
#endif //__mitkConnectomicsNetworkCSVWriter_h
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkDefinitions.cpp b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkDefinitions.cpp
index 7b24d4a..0edd23d 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkDefinitions.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkDefinitions.cpp
@@ -1,65 +1,65 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsNetworkDefinitions.h"
//============== XML const chars ===================
//==== Header information ====
const char* mitk::ConnectomicsNetworkDefinitions::XML_CONNECTOMICS_FILE = "connectomics_network_file" ;
const char* mitk::ConnectomicsNetworkDefinitions::XML_FILE_VERSION = "file_version" ;
const char* mitk::ConnectomicsNetworkDefinitions::VERSION_STRING = "0.2" ;
const char* mitk::ConnectomicsNetworkDefinitions::ASCII_FILE = "ascii_file" ;
const char* mitk::ConnectomicsNetworkDefinitions::FILE_NAME = "file_name" ;
//==== Geometry details ====
const char* mitk::ConnectomicsNetworkDefinitions::XML_GEOMETRY = "geometry";
const char* mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XX = "xx";
const char* mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XY = "xy";
const char* mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XZ = "xz";
const char* mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YX = "yx";
const char* mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YY = "yy";
const char* mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YZ = "yz";
const char* mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZX = "zx";
const char* mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZY = "zy";
const char* mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZZ = "zz";
const char* mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_X = "origin_x";
const char* mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_Y = "origin_y";
const char* mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_Z = "origin_z";
const char* mitk::ConnectomicsNetworkDefinitions::XML_SPACING_X = "spacing_x";
const char* mitk::ConnectomicsNetworkDefinitions::XML_SPACING_Y = "spacing_y";
const char* mitk::ConnectomicsNetworkDefinitions::XML_SPACING_Z = "spacing_z";
//==== Connectomics structures ====
const char* mitk::ConnectomicsNetworkDefinitions::XML_VERTICES = "vertices";
const char* mitk::ConnectomicsNetworkDefinitions::XML_EDGES = "edges";
const char* mitk::ConnectomicsNetworkDefinitions::XML_VERTEX = "vertex";
const char* mitk::ConnectomicsNetworkDefinitions::XML_EDGE = "edge";
//==== Connectomics properties ====
const char* mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_ID = "v_id";
const char* mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_LABEL = "v_label";
const char* mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_X = "v_x";
const char* mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_Y = "v_y";
const char* mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_Z = "v_z";
const char* mitk::ConnectomicsNetworkDefinitions::XML_EDGE_ID = "e_id";
const char* mitk::ConnectomicsNetworkDefinitions::XML_EDGE_SOURCE_ID = "e_s_id";
const char* mitk::ConnectomicsNetworkDefinitions::XML_EDGE_TARGET_ID = "e_t_id";
const char* mitk::ConnectomicsNetworkDefinitions::XML_EDGE_FIBERCOUNT_ID = "e_weight";
const char* mitk::ConnectomicsNetworkDefinitions::XML_EDGE_DOUBLE_WEIGHT_ID = "e_double_weight";
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkDefinitions.h b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkDefinitions.h
index deb6254..d825f86 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkDefinitions.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkDefinitions.h
@@ -1,86 +1,86 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkConnectomicsNetworkDefinitions_h
#define __mitkConnectomicsNetworkDefinitions_h
namespace mitk
{
/** \brief The XML consts for reading and writing
*/
class ConnectomicsNetworkDefinitions
{
public:
//============== XML const chars ===================
//==== Header information ====
static const char* XML_CONNECTOMICS_FILE;
static const char* XML_FILE_VERSION;
static const char* VERSION_STRING;
static const char* ASCII_FILE;
static const char* FILE_NAME;
//==== Geometry details ====
static const char* XML_GEOMETRY;
static const char* XML_MATRIX_XX;
static const char* XML_MATRIX_XY;
static const char* XML_MATRIX_XZ;
static const char* XML_MATRIX_YX;
static const char* XML_MATRIX_YY;
static const char* XML_MATRIX_YZ;
static const char* XML_MATRIX_ZX;
static const char* XML_MATRIX_ZY;
static const char* XML_MATRIX_ZZ;
static const char* XML_ORIGIN_X;
static const char* XML_ORIGIN_Y;
static const char* XML_ORIGIN_Z;
static const char* XML_SPACING_X;
static const char* XML_SPACING_Y;
static const char* XML_SPACING_Z;
//==== Connectomics structures ====
static const char* XML_VERTICES;
static const char* XML_EDGES;
static const char* XML_VERTEX;
static const char* XML_EDGE;
//==== Connectomics properties ====
static const char* XML_VERTEX_ID;
static const char* XML_VERTEX_LABEL;
static const char* XML_VERTEX_X;
static const char* XML_VERTEX_Y;
static const char* XML_VERTEX_Z;
static const char* XML_EDGE_ID;
static const char* XML_EDGE_SOURCE_ID;
static const char* XML_EDGE_TARGET_ID;
static const char* XML_EDGE_FIBERCOUNT_ID;
static const char* XML_EDGE_DOUBLE_WEIGHT_ID;
private:
ConnectomicsNetworkDefinitions();
~ConnectomicsNetworkDefinitions();
};
} //namespace MITK
#endif // __mitkConnectomicsNetworkDefinitions_h
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkMatrixWriter.cpp b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkMatrixWriter.cpp
index a1c0853..ea2df04 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkMatrixWriter.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkMatrixWriter.cpp
@@ -1,151 +1,151 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsNetworkMatrixWriter.h"
#include "mitkConnectomicsNetworkDefinitions.h"
#include "mitkDiffusionIOMimeTypes.h"
#include <mitkConnectomicsNetworkProperties.h>
#include <boost/algorithm/string.hpp>
mitk::ConnectomicsNetworkMatrixWriter::ConnectomicsNetworkMatrixWriter()
: AbstractFileWriter(mitk::ConnectomicsNetwork::GetStaticNameOfClass(), CustomMimeType( mitk::DiffusionIOMimeTypes::CONNECTOMICS_MATRIX_MIMETYPE() ), "Write only Matrix Connectomics Networks" )
{
RegisterService();
}
mitk::ConnectomicsNetworkMatrixWriter::ConnectomicsNetworkMatrixWriter(const mitk::ConnectomicsNetworkMatrixWriter& other)
: AbstractFileWriter(other)
{
}
mitk::ConnectomicsNetworkMatrixWriter::~ConnectomicsNetworkMatrixWriter()
{}
mitk::ConnectomicsNetworkMatrixWriter* mitk::ConnectomicsNetworkMatrixWriter::Clone() const
{
return new ConnectomicsNetworkMatrixWriter(*this);
}
void mitk::ConnectomicsNetworkMatrixWriter::Write()
{
MITK_INFO << "Writing connectomics network";
InputType::ConstPointer input = dynamic_cast<const InputType*>(this->GetInput());
if (input.IsNull() )
{
MITK_ERROR <<"Sorry, input to ConnectomicsNetworkMatrixWriter is nullptr!";
return;
}
this->ValidateOutputLocation();
std::ostream* out;
std::ofstream outStream;
if( this->GetOutputStream() )
{
out = this->GetOutputStream();
}
else
{
outStream.open( this->GetOutputLocation().c_str() );
out = &outStream;
}
if ( !out->good() )
{
mitkThrow() << "Could not open stream.";
}
try
{
const std::string& locale = "C";
const std::string& currLocale = setlocale( LC_ALL, nullptr );
setlocale(LC_ALL, locale.c_str());
std::locale previousLocale(out->getloc());
std::locale I("C");
out->imbue(I);
// construct header
std::stringstream header;
mitk::StringProperty::Pointer addHeaderInfoProperty = dynamic_cast<mitk::StringProperty*>(input->GetProperty(connectomicsDataAdditionalHeaderInformation.c_str()).GetPointer());
if(addHeaderInfoProperty.IsNotNull())
{
std::string additionalHeaderInfo = addHeaderInfoProperty->GetValue();
// if the additional header info contains newlines we need to add #
// in front of the new lines
std::vector<std::string> strings;
boost::split(strings, additionalHeaderInfo, boost::is_any_of("\n"));
for( unsigned int index(0); index < strings.size(); ++index)
{
header << "#" << strings[index] << "\n";
}
}
// add the order of labels to the header
std::vector< InputType::VertexDescriptorType > nodes = input->GetVectorOfAllVertexDescriptors();
header << "#";
for(unsigned int index(0); index < nodes.size(); ++index)
{
header << " " << (input->GetNode(nodes[index])).label;
}
// construct body
std::stringstream body;
for(unsigned int i(0); i < nodes.size(); ++i)
{
for(unsigned int j(0); j < nodes.size(); ++j)
{
if( input->EdgeExists(nodes[i], nodes[j]))
{
body << (input->GetEdge(nodes[i], nodes[j])).fiber_count;
}
else
{
body << 0;
}
if(j < nodes.size() - 1)
{
body << " ";
}
}
body << "\n";
}
(*out)<< header.str() << "\n" << body.str();
setlocale(LC_ALL, currLocale.c_str());
MITK_INFO << "Connectomics network connection list written";
}
catch(...)
{
mitkThrow() << "Error while writing to stream.";
}
}
mitk::IFileIO::ConfidenceLevel mitk::ConnectomicsNetworkMatrixWriter::GetConfidenceLevel() const
{
if (AbstractFileWriter::GetConfidenceLevel() == Unsupported)
{
return Unsupported;
}
// exporting is supported but will result in loss of data
// which prevents re-import
return PartiallySupported;
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkMatrixWriter.h b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkMatrixWriter.h
index e6c5fc4..7c2e0c5 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkMatrixWriter.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkMatrixWriter.h
@@ -1,62 +1,62 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkConnectomicsNetworkMatrixWriter_h
#define __mitkConnectomicsNetworkMatrixWriter_h
#include <mitkAbstractFileWriter.h>
#include "mitkConnectomicsNetwork.h"
#include <vtkPolyDataWriter.h>
namespace mitk
{
/**
* Writes connectomics networks to a file
*
*
* This export is write only, information is lost.
* @ingroup Process
*/
class ConnectomicsNetworkMatrixWriter : public mitk::AbstractFileWriter
{
public:
typedef mitk::ConnectomicsNetwork InputType;
typedef std::vector< std::pair< std::pair<
mitk::ConnectomicsNetwork::NetworkNode, mitk::ConnectomicsNetwork::NetworkNode >
, mitk::ConnectomicsNetwork::NetworkEdge > > EdgeVectorType;
typedef std::vector< mitk::ConnectomicsNetwork::NetworkNode > VertexVectorType;
ConnectomicsNetworkMatrixWriter();
~ConnectomicsNetworkMatrixWriter() override;
using AbstractFileWriter::Write;
void Write() override;
mitk::IFileIO::ConfidenceLevel GetConfidenceLevel() const override;
protected:
ConnectomicsNetworkMatrixWriter(const ConnectomicsNetworkMatrixWriter& other);
mitk::ConnectomicsNetworkMatrixWriter* Clone() const override;
};
} // end of namespace mitk
#endif //__mitkConnectomicsNetworkMatrixWriter_h
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkReader.cpp b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkReader.cpp
index c008b6b..90cfea7 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkReader.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkReader.cpp
@@ -1,228 +1,228 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsNetworkReader.h"
#include "mitkConnectomicsNetworkDefinitions.h"
#include <tinyxml.h>
#include "itksys/SystemTools.hxx"
#include <vtkMatrix4x4.h>
#include "mitkGeometry3D.h"
#include <mitkCustomMimeType.h>
#include "mitkDiffusionIOMimeTypes.h"
namespace mitk
{
ConnectomicsNetworkReader::ConnectomicsNetworkReader(const ConnectomicsNetworkReader& other)
: mitk::AbstractFileReader(other)
{
}
ConnectomicsNetworkReader::ConnectomicsNetworkReader()
: mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::CONNECTOMICS_MIMETYPE() ), mitk::DiffusionIOMimeTypes::CONNECTOMICS_MIMETYPE_DESCRIPTION() )
{
m_ServiceReg = this->RegisterService();
}
ConnectomicsNetworkReader::~ConnectomicsNetworkReader()
{
}
std::vector<itk::SmartPointer<BaseData> > ConnectomicsNetworkReader::Read()
{
std::vector<itk::SmartPointer<mitk::BaseData> > result;
std::string location = GetInputLocation();
std::string ext = itksys::SystemTools::GetFilenameLastExtension(location);
ext = itksys::SystemTools::LowerCase(ext);
if ( location == "")
{
MITK_ERROR << "No file name specified.";
}
else if (ext == ".cnf")
{
try
{
mitk::ConnectomicsNetwork::Pointer outputNetwork = mitk::ConnectomicsNetwork::New();
TiXmlDocument doc( location );
bool loadOkay = doc.LoadFile();
if(!loadOkay)
{
mitkThrow() << "Could not open file " << location << " for reading.";
}
TiXmlHandle hDoc(&doc);
TiXmlElement* pElem;
TiXmlHandle hRoot(nullptr);
pElem = hDoc.FirstChildElement().Element();
// save this for later
hRoot = TiXmlHandle(pElem);
//get file version
std::string version("");
hRoot.Element()->QueryStringAttribute(mitk::ConnectomicsNetworkDefinitions::XML_FILE_VERSION, &version);
// read geometry
pElem = hRoot.FirstChildElement(mitk::ConnectomicsNetworkDefinitions::XML_GEOMETRY).Element();
mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New();
// read origin
mitk::Point3D origin;
double temp = 0;
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_X, &temp);
origin[0] = temp;
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_Y, &temp);
origin[1] = temp;
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_Z, &temp);
origin[2] = temp;
geometry->SetOrigin(origin);
// read spacing
ScalarType spacing[3];
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_X, &temp);
spacing[0] = temp;
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_Y, &temp);
spacing[1] = temp;
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_Z, &temp);
spacing[2] = temp;
geometry->SetSpacing(spacing);
// read transform
vtkMatrix4x4* m = vtkMatrix4x4::New();
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XX, &temp);
m->SetElement(0,0,temp);
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XY, &temp);
m->SetElement(1,0,temp);
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XZ, &temp);
m->SetElement(2,0,temp);
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YX, &temp);
m->SetElement(0,1,temp);
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YY, &temp);
m->SetElement(1,1,temp);
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YZ, &temp);
m->SetElement(2,1,temp);
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZX, &temp);
m->SetElement(0,2,temp);
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZY, &temp);
m->SetElement(1,2,temp);
pElem->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZZ, &temp);
m->SetElement(2,2,temp);
m->SetElement(0,3,origin[0]);
m->SetElement(1,3,origin[1]);
m->SetElement(2,3,origin[2]);
m->SetElement(3,3,1);
geometry->SetIndexToWorldTransformByVtkMatrix(m);
geometry->SetImageGeometry(true);
outputNetwork->SetGeometry(geometry);
// read network
std::map< int, mitk::ConnectomicsNetwork::VertexDescriptorType > idToVertexMap;
// read vertices
pElem = hRoot.FirstChildElement(mitk::ConnectomicsNetworkDefinitions::XML_VERTICES).Element();
{
// walk through the vertices
TiXmlElement* vertexElement = pElem->FirstChildElement();
for( ; vertexElement; vertexElement=vertexElement->NextSiblingElement())
{
std::vector< float > pos;
std::string label;
int vertexID(0);
vertexElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_X, &temp);
pos.push_back(temp);
vertexElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_Y, &temp);
pos.push_back(temp);
vertexElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_Z, &temp);
pos.push_back(temp);
vertexElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_ID, &vertexID);
vertexElement->QueryStringAttribute(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_LABEL, &label);
mitk::ConnectomicsNetwork::VertexDescriptorType newVertex = outputNetwork->AddVertex( vertexID );
outputNetwork->SetLabel( newVertex, label );
outputNetwork->SetCoordinates( newVertex, pos );
if ( idToVertexMap.count( vertexID ) > 0 )
{
MITK_ERROR << "Aborting network creation, duplicate vertex ID in file.";
return result;
}
idToVertexMap.insert( std::pair< int, mitk::ConnectomicsNetwork::VertexDescriptorType >( vertexID, newVertex) );
}
}
// read edges
pElem = hRoot.FirstChildElement(mitk::ConnectomicsNetworkDefinitions::XML_EDGES).Element();
{
// walk through the edges
TiXmlElement* edgeElement = pElem->FirstChildElement();
for( ; edgeElement; edgeElement=edgeElement->NextSiblingElement())
{
int edgeID(0), edgeSourceID(0), edgeTargetID(0), edgeWeight(0);
double edgeDoubleWeight(0.0);
edgeElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_EDGE_ID, &edgeID);
edgeElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_EDGE_SOURCE_ID, &edgeSourceID);
edgeElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_EDGE_TARGET_ID, &edgeTargetID);
edgeElement->Attribute(mitk::ConnectomicsNetworkDefinitions::XML_EDGE_FIBERCOUNT_ID, &edgeWeight);
if(version == "0.1")
{
// in version 0.1 only the int weight was saved, assume double weight to be one by default
edgeDoubleWeight = 1.0;
}
else
{
edgeElement->QueryDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_EDGE_DOUBLE_WEIGHT_ID, &edgeDoubleWeight);
}
mitk::ConnectomicsNetwork::VertexDescriptorType source = idToVertexMap.find( edgeSourceID )->second;
mitk::ConnectomicsNetwork::VertexDescriptorType target = idToVertexMap.find( edgeTargetID )->second;
outputNetwork->AddEdge( source, target, edgeSourceID, edgeTargetID, edgeWeight, edgeDoubleWeight);
}
}
outputNetwork->UpdateBounds();
result.push_back(outputNetwork.GetPointer());
MITK_INFO << "Network read";
}
catch (mitk::Exception& e)
{
MITK_ERROR << e.GetDescription();
}
catch(...)
{
MITK_ERROR << "Unknown error occured while trying to read file.";
}
}
return result;
}
} //namespace MITK
mitk::ConnectomicsNetworkReader* mitk::ConnectomicsNetworkReader::Clone() const
{
return new ConnectomicsNetworkReader(*this);
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkReader.h b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkReader.h
index 0e8ae95..ad3aa49 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkReader.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkReader.h
@@ -1,53 +1,53 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkConnectomicsNetworkReader_h
#define __mitkConnectomicsNetworkReader_h
#include "mitkCommon.h"
#include <mitkAbstractFileReader.h>
#include <mitkBaseData.h>
#include <mitkMimeType.h>
#include "mitkConnectomicsNetwork.h"
namespace mitk
{
/** \brief The reader for connectomics network files (.cnf)
*/
class ConnectomicsNetworkReader : public mitk::AbstractFileReader
{
public:
typedef mitk::ConnectomicsNetwork OutputType;
ConnectomicsNetworkReader(const ConnectomicsNetworkReader& other);
ConnectomicsNetworkReader();
~ConnectomicsNetworkReader() override;
using AbstractFileReader::Read;
std::vector<itk::SmartPointer<BaseData> > Read() override;
private:
ConnectomicsNetworkReader* Clone() const override;
us::ServiceRegistration<mitk::IFileReader> m_ServiceReg;
};
} //namespace MITK
#endif // __mitkConnectomicsNetworkReader_h
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkSerializer.cpp b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkSerializer.cpp
index e48e63f..69134f0 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkSerializer.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkSerializer.cpp
@@ -1,74 +1,74 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsNetworkSerializer.h"
#include "mitkConnectomicsNetwork.h"
#include "mitkConnectomicsNetworkWriter.h"
#include <itksys/SystemTools.hxx>
MITK_REGISTER_SERIALIZER(ConnectomicsNetworkSerializer)
mitk::ConnectomicsNetworkSerializer::ConnectomicsNetworkSerializer()
{
}
mitk::ConnectomicsNetworkSerializer::~ConnectomicsNetworkSerializer()
{
}
std::string mitk::ConnectomicsNetworkSerializer::Serialize()
{
const ConnectomicsNetwork* conNet = dynamic_cast<const ConnectomicsNetwork*>( m_Data.GetPointer() );
if (conNet == nullptr)
{
MITK_ERROR << " Object at " << (const void*) this->m_Data
<< " is not an mitk::ConnectomicsNetwork. Cannot serialize as ConnectomicsNetwork.";
return "";
}
std::string filename( this->GetUniqueFilenameInWorkingDirectory() );
filename += "_";
filename += m_FilenameHint;
filename += ".cnf";
std::string fullname(m_WorkingDirectory);
fullname += "/";
fullname += itksys::SystemTools::ConvertToOutputPath(filename.c_str());
try
{
ConnectomicsNetworkWriter writer;
writer.SetOutputLocation(fullname);
writer.SetInput(const_cast<ConnectomicsNetwork*>(conNet));
writer.Write();
}
catch (std::exception& e)
{
MITK_ERROR << " Error serializing object at " << (const void*) this->m_Data
<< " to "
<< fullname
<< ": "
<< e.what();
return "";
}
return filename;
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkSerializer.h b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkSerializer.h
index 7205b27..bb445a4 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkSerializer.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkSerializer.h
@@ -1,39 +1,39 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkConnectomicsNetworkSerializer_h_included
#define mitkConnectomicsNetworkSerializer_h_included
#include "mitkBaseDataSerializer.h"
namespace mitk
{
/**
\brief Serializes mitk::ConnectomicsNetwork for mitk::SceneIO
*/
class ConnectomicsNetworkSerializer : public BaseDataSerializer
{
public:
mitkClassMacro( ConnectomicsNetworkSerializer, BaseDataSerializer );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
std::string Serialize() override;
protected:
ConnectomicsNetworkSerializer();
~ConnectomicsNetworkSerializer() override;
};
} // namespace
#endif
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkWriter.cpp b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkWriter.cpp
index 03d0c19..abc33fa 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkWriter.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkWriter.cpp
@@ -1,144 +1,144 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkConnectomicsNetworkWriter.h"
#include "mitkConnectomicsNetworkDefinitions.h"
#include <tinyxml.h>
#include "itksys/SystemTools.hxx"
#include "mitkDiffusionIOMimeTypes.h"
mitk::ConnectomicsNetworkWriter::ConnectomicsNetworkWriter()
: AbstractFileWriter(mitk::ConnectomicsNetwork::GetStaticNameOfClass(), CustomMimeType( mitk::DiffusionIOMimeTypes::CONNECTOMICS_MIMETYPE() ), mitk::DiffusionIOMimeTypes::CONNECTOMICS_MIMETYPE_DESCRIPTION() )
{
RegisterService();
}
mitk::ConnectomicsNetworkWriter::ConnectomicsNetworkWriter(const mitk::ConnectomicsNetworkWriter& other)
: AbstractFileWriter(other)
{
}
mitk::ConnectomicsNetworkWriter::~ConnectomicsNetworkWriter()
{}
mitk::ConnectomicsNetworkWriter* mitk::ConnectomicsNetworkWriter::Clone() const
{
return new ConnectomicsNetworkWriter(*this);
}
void mitk::ConnectomicsNetworkWriter::Write()
{
MITK_INFO << "Writing connectomics network";
InputType::ConstPointer input = dynamic_cast<const InputType*>(this->GetInput());
if (input.IsNull() )
{
MITK_ERROR <<"Sorry, input to ConnectomicsNetworkWriter is nullptr!";
return;
}
if ( this->GetOutputLocation().empty() )
{
MITK_ERROR << "Sorry, filename has not been set!" ;
return ;
}
std::string ext = itksys::SystemTools::GetFilenameLastExtension(this->GetOutputLocation());
ext = itksys::SystemTools::LowerCase(ext);
// default extension is .cnf
if(ext == "")
{
ext = ".cnf";
this->SetOutputLocation(this->GetOutputLocation() + ext);
}
if (ext == ".cnf")
{
// Get geometry of the network
mitk::BaseGeometry* geometry = input->GetGeometry();
// Create XML document
TiXmlDocument documentXML;
{ // begin document
TiXmlDeclaration* declXML = new TiXmlDeclaration( "1.0", "", "" ); // TODO what to write here? encoding? etc....
documentXML.LinkEndChild( declXML );
TiXmlElement* mainXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_CONNECTOMICS_FILE);
mainXML->SetAttribute(mitk::ConnectomicsNetworkDefinitions::XML_FILE_VERSION, mitk::ConnectomicsNetworkDefinitions::VERSION_STRING);
documentXML.LinkEndChild(mainXML);
TiXmlElement* geometryXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_GEOMETRY);
{ // begin geometry
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XX, geometry->GetMatrixColumn(0)[0]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XY, geometry->GetMatrixColumn(0)[1]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_XZ, geometry->GetMatrixColumn(0)[2]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YX, geometry->GetMatrixColumn(1)[0]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YY, geometry->GetMatrixColumn(1)[1]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_YZ, geometry->GetMatrixColumn(1)[2]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZX, geometry->GetMatrixColumn(2)[0]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZY, geometry->GetMatrixColumn(2)[1]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_MATRIX_ZZ, geometry->GetMatrixColumn(2)[2]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_X, geometry->GetOrigin()[0]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_Y, geometry->GetOrigin()[1]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_ORIGIN_Z, geometry->GetOrigin()[2]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_X, geometry->GetSpacing()[0]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_Y, geometry->GetSpacing()[1]);
geometryXML->SetDoubleAttribute(mitk::ConnectomicsNetworkDefinitions::XML_SPACING_Z, geometry->GetSpacing()[2]);
} // end geometry
mainXML->LinkEndChild(geometryXML);
TiXmlElement* verticesXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_VERTICES);
{ // begin vertices section
VertexVectorType vertexVector = dynamic_cast<const InputType*>(this->GetInput())->GetVectorOfAllNodes();
for( unsigned int index = 0; index < vertexVector.size(); index++ )
{
// not localized as of yet TODO
TiXmlElement* vertexXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_VERTEX );
vertexXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_ID , vertexVector[ index ].id );
vertexXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_LABEL , vertexVector[ index ].label );
vertexXML->SetDoubleAttribute( mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_X , vertexVector[ index ].coordinates[0] );
vertexXML->SetDoubleAttribute( mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_Y , vertexVector[ index ].coordinates[1] );
vertexXML->SetDoubleAttribute( mitk::ConnectomicsNetworkDefinitions::XML_VERTEX_Z , vertexVector[ index ].coordinates[2] );
verticesXML->LinkEndChild(vertexXML);
}
} // end vertices section
mainXML->LinkEndChild(verticesXML);
TiXmlElement* edgesXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_EDGES);
{ // begin edges section
EdgeVectorType edgeVector = dynamic_cast<const InputType*>(this->GetInput())->GetVectorOfAllEdges();
for(unsigned int index = 0; index < edgeVector.size(); index++ )
{
TiXmlElement* edgeXML = new TiXmlElement(mitk::ConnectomicsNetworkDefinitions::XML_EDGE );
edgeXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_EDGE_ID , index );
edgeXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_EDGE_SOURCE_ID , edgeVector[ index ].second.sourceId );
edgeXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_EDGE_TARGET_ID , edgeVector[ index ].second.targetId );
edgeXML->SetAttribute( mitk::ConnectomicsNetworkDefinitions::XML_EDGE_FIBERCOUNT_ID , edgeVector[ index ].second.fiber_count );
edgeXML->SetDoubleAttribute( mitk::ConnectomicsNetworkDefinitions::XML_EDGE_DOUBLE_WEIGHT_ID , edgeVector[ index ].second.edge_weight );
edgesXML->LinkEndChild(edgeXML);
}
} // end edges section
mainXML->LinkEndChild(edgesXML);
} // end document
documentXML.SaveFile( this->GetOutputLocation().c_str() );
MITK_INFO << "Connectomics network written";
}
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkWriter.h b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkWriter.h
index 8024b2e..9aed9b5 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkWriter.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkConnectomicsNetworkWriter.h
@@ -1,57 +1,57 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkConnectomicsNetworkWriter_h
#define __mitkConnectomicsNetworkWriter_h
#include <mitkAbstractFileWriter.h>
#include "mitkConnectomicsNetwork.h"
#include <vtkPolyDataWriter.h>
namespace mitk
{
/**
* Writes connectomics networks to a file
* @ingroup Process
*/
class ConnectomicsNetworkWriter : public mitk::AbstractFileWriter
{
public:
typedef mitk::ConnectomicsNetwork InputType;
typedef std::vector< std::pair< std::pair<
mitk::ConnectomicsNetwork::NetworkNode, mitk::ConnectomicsNetwork::NetworkNode >
, mitk::ConnectomicsNetwork::NetworkEdge > > EdgeVectorType;
typedef std::vector< mitk::ConnectomicsNetwork::NetworkNode > VertexVectorType;
ConnectomicsNetworkWriter();
~ConnectomicsNetworkWriter() override;
using AbstractFileWriter::Write;
void Write() override;
protected:
ConnectomicsNetworkWriter(const ConnectomicsNetworkWriter& other);
mitk::ConnectomicsNetworkWriter* Clone() const override;
};
} // end of namespace mitk
#endif //__mitkConnectomicsNetworkWriter_h
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageDicomReader.cpp b/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageDicomReader.cpp
index b09fbb4..29ed414 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageDicomReader.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageDicomReader.cpp
@@ -1,327 +1,327 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkDiffusionImageDicomReader_cpp
#define __mitkDiffusionImageDicomReader_cpp
#include "mitkDiffusionImageDicomReader.h"
#include <iostream>
#include <fstream>
// Diffusion properties
#include <mitkGradientDirectionsProperty.h>
#include <mitkBValueMapProperty.h>
#include <mitkMeasurementFrameProperty.h>
#include <mitkProperties.h>
#include <itkImageRegionIterator.h>
#include <itkMetaDataObject.h>
#include "itksys/SystemTools.hxx"
#include "itkImageFileReader.h"
#include "itkMetaDataObject.h"
#include "itkNrrdImageIO.h"
#include "mitkCustomMimeType.h"
#include "mitkDiffusionIOMimeTypes.h"
#include <mitkDiffusionDICOMFileReader.h>
#include <mitkDICOMTagBasedSorter.h>
#include <mitkSortByImagePositionPatient.h>
#include <mitkDICOMSortByTag.h>
#include <mitkITKImageImport.h>
#include <mitkImageWriteAccessor.h>
#include <mitkImageDataItem.h>
#include <mitkIOUtil.h>
#include <mitkLocaleSwitch.h>
#include <itksys/Directory.hxx>
#include <gdcmDirectory.h>
#include <mitkStringProperty.h>
namespace mitk
{
DiffusionImageDicomReader::
DiffusionImageDicomReader(const DiffusionImageDicomReader & other)
: AbstractFileReader(other)
{
}
DiffusionImageDicomReader* DiffusionImageDicomReader::Clone() const
{
return new DiffusionImageDicomReader(*this);
}
DiffusionImageDicomReader::
~DiffusionImageDicomReader()
{}
DiffusionImageDicomReader::
DiffusionImageDicomReader()
: mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::DWI_DICOM_MIMETYPE() ), mitk::DiffusionIOMimeTypes::DWI_DICOM_MIMETYPE_DESCRIPTION() )
{
Options defaultOptions;
defaultOptions["Apply image rotation to gradients"] = true;
defaultOptions["Load recursive"] = false;
defaultOptions["Split mosaic"] = true;
this->SetDefaultOptions(defaultOptions);
m_ServiceReg = this->RegisterService();
}
std::vector<itk::SmartPointer<mitk::BaseData> >
DiffusionImageDicomReader::Read()
{
return InternalRead();
}
std::vector<itk::SmartPointer<mitk::BaseData> > DiffusionImageDicomReader::InternalRead()
{
std::vector<itk::SmartPointer<mitk::BaseData> > result_images;
OutputType::Pointer outputForCache = OutputType::New();
if ( this->GetInputLocation() == "")
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, the filename to be read is empty!");
}
else
{
const std::string& locale = "C";
const std::string& currLocale = setlocale( LC_ALL, nullptr );
if ( locale.compare(currLocale)!=0 )
{
try
{
setlocale(LC_ALL, locale.c_str());
}
catch(...)
{
MITK_INFO << "Could not set locale " << locale;
}
}
try
{
Options options = this->GetOptions();
bool load_recursive = us::any_cast<bool>(options["Load recursive"]);
bool split_mosaic = us::any_cast<bool>(options["Split mosaic"]);
gdcm::Directory::FilenamesType complete_list;
std::string folderName = itksys::SystemTools::GetFilenamePath( this->GetInputLocation() );
if( load_recursive )
{
std::string subdir_prefix = "";
itksys::Directory rootdir;
rootdir.Load( folderName.c_str() );
for( unsigned int idx=0; idx<rootdir.GetNumberOfFiles(); idx++)
{
std::string current_path = rootdir.GetFile(idx);
std::string directory_path = std::string(rootdir.GetPath()) + std::string("/") + current_path;
MITK_INFO("dicom.loader.inputrootdir.test") << "ProbePath: " << current_path;
MITK_INFO("dicom.loader.inputrootdir.test") << "IsDirectory: " << itksys::SystemTools::FileIsDirectory( itksys::SystemTools::ConvertToOutputPath( directory_path.c_str() ).c_str() )
<< " StartsWith: " << itksys::SystemTools::StringStartsWith( current_path.c_str(), subdir_prefix.c_str() );
// test for prefix
if( itksys::SystemTools::FileIsDirectory( itksys::SystemTools::ConvertToOutputPath( directory_path.c_str() ).c_str() )
&& itksys::SystemTools::StringStartsWith( current_path.c_str(), subdir_prefix.c_str() ) )
{
gdcm::Directory d;
d.Load( itksys::SystemTools::ConvertToOutputPath( directory_path.c_str() ) , false);
MITK_INFO("dicom.load.subdir.attempt") << "In directory " << itksys::SystemTools::ConvertToOutputPath( directory_path.c_str() );
const gdcm::Directory::FilenamesType &l1 = d.GetFilenames();
const unsigned int ntotalfiles = l1.size();
for( unsigned int i=0; i< ntotalfiles; i++)
{
complete_list.push_back( l1.at(i) );
m_ReadFiles.push_back( l1.at(i) );
}
}
}
}
else
{
gdcm::Directory d;
d.Load( folderName.c_str(), load_recursive ); // recursive !
const gdcm::Directory::FilenamesType &l1 = d.GetFilenames();
const unsigned int ntotalfiles = l1.size();
for( unsigned int i=0; i< ntotalfiles; i++)
{
complete_list.push_back( l1.at(i) );
m_ReadFiles.push_back( l1.at(i) );
}
}
mitk::DiffusionDICOMFileReader::Pointer gdcmReader = mitk::DiffusionDICOMFileReader::New();
mitk::DICOMTagBasedSorter::Pointer tagSorter = mitk::DICOMTagBasedSorter::New();
// Use tags as in Qmitk
// all the things that split by tag in ClassicDicomSeriesReader
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0010) ); // Number of Rows
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0011) ); // Number of Columns
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0030) ); // Pixel Spacing
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0018, 0x1164) ); // Imager Pixel Spacing
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0020, 0x0037) ); // Image Orientation (Patient) // TODO add tolerance parameter (l. 1572 of original code)
// TODO handle as real vectors! cluster with configurable errors!
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0020, 0x000e) ); // Series Instance UID
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0018, 0x0050) ); // Slice Thickness
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0008) ); // Number of Frames
//tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0020, 0x0052) ); // Frame of Reference UID
auto tag_sop_instance_uid = mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0008, 0x0018), nullptr ); // SOP instance UID (last resort, not really meaningful but decides clearly)
auto tag_trigger_time = mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0018, 0x1060), tag_sop_instance_uid.GetPointer() ); // trigger time
auto tag_aqcuisition_time = mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0008, 0x0032), tag_trigger_time.GetPointer()); // aqcuisition time
auto tag_aqcuisition_number = mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0020, 0x0012), tag_aqcuisition_time.GetPointer()); // aqcuisition number
mitk::DICOMSortCriterion::ConstPointer sorting = mitk::SortByImagePositionPatient::New(tag_aqcuisition_number.GetPointer()).GetPointer();
tagSorter->SetSortCriterion( sorting );
// mosaic
gdcmReader->SetResolveMosaic( split_mosaic );
gdcmReader->AddSortingElement( tagSorter );
gdcmReader->SetInputFiles( complete_list );
gdcmReader->SetApplyRotationToGradients(us::any_cast<bool>(options["Apply image rotation to gradients"]));
try
{
gdcmReader->AnalyzeInputFiles();
}
catch( const itk::ExceptionObject &e)
{
MITK_ERROR << "Failed to analyze data. " << e.what();
}
catch( const std::exception &se)
{
MITK_ERROR << "Std Exception " << se.what();
}
gdcmReader->LoadImages();
for( unsigned int o = 0; o < gdcmReader->GetNumberOfOutputs(); o++ )
{
mitk::Image::Pointer loaded_image = gdcmReader->GetOutput(o).GetMitkImage();
StringProperty::Pointer nameProp;
if (gdcmReader->GetSeriesName(o)!="-")
nameProp = StringProperty::New(gdcmReader->GetSeriesName(o));
else if (gdcmReader->GetStudyName(o)!="-")
nameProp = StringProperty::New(gdcmReader->GetStudyName(o));
else
nameProp = StringProperty::New(folderName);
loaded_image->SetProperty("name", nameProp);
std::string val = "-";
if (gdcmReader->patient_ids().size()>o)
{
val = gdcmReader->patient_ids().at(o);
loaded_image->GetPropertyList()->SetStringProperty("DICOM.patient_id",val.c_str());
}
if (gdcmReader->patient_names().size()>o)
{
val = gdcmReader->patient_names().at(o);
loaded_image->GetPropertyList()->SetStringProperty("DICOM.patient_name",val.c_str());
}
if (gdcmReader->study_instance_uids().size()>o)
{
val = gdcmReader->study_instance_uids().at(o);
loaded_image->GetPropertyList()->SetStringProperty("DICOM.study_instance_uid",val.c_str());
}
if (gdcmReader->series_instance_uids().size()>o)
{
val = gdcmReader->series_instance_uids().at(o);
loaded_image->GetPropertyList()->SetStringProperty("DICOM.series_instance_uid",val.c_str());
}
if (gdcmReader->sop_instance_uids().size()>o)
{
val = gdcmReader->sop_instance_uids().at(o);
loaded_image->GetPropertyList()->SetStringProperty("DICOM.sop_instance_uid",val.c_str());
}
if (gdcmReader->frame_of_reference_uids().size()>o)
{
val = gdcmReader->frame_of_reference_uids().at(o);
loaded_image->GetPropertyList()->SetStringProperty("DICOM.frame_of_reference_uid",val.c_str());
}
result_images.push_back(loaded_image.GetPointer());
}
// 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();
try
{
setlocale(LC_ALL, currLocale.c_str());
}
catch(...)
{
MITK_INFO << "Could not reset locale " << currLocale;
}
}
catch(std::exception& e)
{
try
{
setlocale(LC_ALL, currLocale.c_str());
}
catch(...)
{
MITK_INFO << "Could not reset locale " << currLocale;
}
MITK_INFO << "Std::Exception while reading file!!";
MITK_INFO << e.what();
throw itk::ImageFileReaderException(__FILE__, __LINE__, e.what());
}
catch(...)
{
try
{
setlocale(LC_ALL, currLocale.c_str());
}
catch(...)
{
MITK_INFO << "Could not reset locale " << currLocale;
}
MITK_INFO << "Exception while reading file!!";
throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, an error occurred while reading the requested vessel tree file!");
}
}
return result_images;
}
} //namespace MITK
#endif
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageDicomReader.h b/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageDicomReader.h
index abe0f82..106418d 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageDicomReader.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageDicomReader.h
@@ -1,73 +1,73 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkDiffusionImageDicomReader_h
#define __mitkDiffusionImageDicomReader_h
#include "mitkCommon.h"
// MITK includes
#include "mitkImageSource.h"
#include "mitkFileReader.h"
#include <mitkDiffusionPropertyHelper.h>
// ITK includes
#include "itkVectorImage.h"
#include "mitkAbstractFileReader.h"
namespace mitk
{
/** \brief
*/
class DiffusionImageDicomReader : public mitk::AbstractFileReader
{
public:
DiffusionImageDicomReader(const DiffusionImageDicomReader & other);
DiffusionImageDicomReader();
~DiffusionImageDicomReader() override;
using AbstractFileReader::Read;
std::vector<itk::SmartPointer<BaseData> > Read() override;
typedef short DiffusionPixelType;
typedef mitk::Image OutputType;
typedef mitk::DiffusionPropertyHelper::ImageType VectorImageType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType;
typedef mitk::DiffusionPropertyHelper::MeasurementFrameType MeasurementFrameType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType;
protected:
OutputType::Pointer m_OutputCache;
itk::TimeStamp m_CacheTime;
std::vector<itk::SmartPointer<BaseData> > InternalRead();
private:
DiffusionImageDicomReader* Clone() const override;
us::ServiceRegistration<mitk::IFileReader> m_ServiceReg;
};
} //namespace MITK
#endif // __mitkDiffusionImageDicomReader_h
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNiftiReader.cpp b/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNiftiReader.cpp
index 347c2d7..7d5405f 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNiftiReader.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNiftiReader.cpp
@@ -1,342 +1,342 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <iostream>
#include <fstream>
// Diffusion properties
#include <mitkGradientDirectionsProperty.h>
#include <mitkBValueMapProperty.h>
#include <mitkMeasurementFrameProperty.h>
#include <mitkProperties.h>
// ITK includes
#include <itkImageRegionIterator.h>
#include <itkMetaDataObject.h>
#include "itksys/SystemTools.hxx"
#include "itkImageFileReader.h"
#include "itkMetaDataObject.h"
#include "itkNiftiImageIO.h"
#include "mitkCustomMimeType.h"
#include "mitkDiffusionIOMimeTypes.h"
#include <mitkITKImageImport.h>
#include <mitkImageWriteAccessor.h>
#include <mitkImageDataItem.h>
#include <mitkLocaleSwitch.h>
#include "mitkIOUtil.h"
#include <mitkDiffusionFunctionCollection.h>
#include <vtkNIFTIImageReader.h>
#include <vtkNIFTIImageHeader.h>
#include <vtkImageIterator.h>
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<itk::SmartPointer<mitk::BaseData> >
DiffusionImageNiftiReader::
Read()
{
std::vector<itk::SmartPointer<mitk::BaseData> > 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 );
if(ext == ".nii" || ext == ".nii.gz")
{
// create reader and read file
typedef itk::Image<DiffusionPixelType,4> ImageType4D;
itk::NiftiImageIO::Pointer io2 = itk::NiftiImageIO::New();
ImageType4D::Pointer img4 = ImageType4D::New();
if (io2->CanReadFile(this->GetInputLocation().c_str()))
{
typedef itk::ImageFileReader<ImageType4D> FileReaderType;
FileReaderType::Pointer reader = FileReaderType::New();
reader->SetFileName( this->GetInputLocation() );
reader->SetImageIO(io2);
reader->Update();
img4 = reader->GetOutput();
}
else
{
vtkSmartPointer<vtkNIFTIImageReader> reader = vtkSmartPointer<vtkNIFTIImageReader>::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<double, 4, 4> direction; direction.SetIdentity();
itk::Matrix<double, 4, 4> ras_lps; ras_lps.SetIdentity();
ras_lps[0][0] = -1;
ras_lps[1][1] = -1;
if (matrix != nullptr)
{
for (int r=0; r<dim; r++)
for (int c=0; c<dim; c++)
direction[r][c] = matrix->GetElement(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 (i<dim)
region.SetSize(i, header->GetDim(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; g<header->GetDim(4); g++)
for (int z=0; z<header->GetDim(3); z++)
for (int y=0; y<header->GetDim(2); y++)
for (int x=0; x<header->GetDim(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;
}
}
}
// 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;
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<VectorImageType> 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; ind<vec.Size(); ind++)
{
index4[3] = ind;
vec[ind] = img4->GetPixel(index4);
}
it.Set(vec);
}
}
// Diffusion Image information START
GradientDirectionContainerType::Pointer DiffusionVectors = GradientDirectionContainerType::New();
MeasurementFrameType MeasurementFrame;
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(std::string(base+".bvecs").c_str()))
bvecs_file = base+".bvecs";
else if (itksys::SystemTools::FileExists(base+".bvec"))
bvals_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);
MeasurementFrame.set_identity();
}
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<bool>(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/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNiftiReader.h b/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNiftiReader.h
index 6242bea..b1c5d32 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNiftiReader.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNiftiReader.h
@@ -1,73 +1,73 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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_h
#define __mitkDiffusionImageNiftiReader_h
#include "mitkCommon.h"
// MITK includes
#include "mitkImageSource.h"
#include "mitkFileReader.h"
#include <mitkDiffusionPropertyHelper.h>
// ITK includes
#include "itkVectorImage.h"
#include "mitkAbstractFileReader.h"
namespace mitk
{
/** \brief
*/
class DiffusionImageNiftiReader : public mitk::AbstractFileReader
{
public:
DiffusionImageNiftiReader(const DiffusionImageNiftiReader & other);
DiffusionImageNiftiReader();
~DiffusionImageNiftiReader() override;
using AbstractFileReader::Read;
std::vector<itk::SmartPointer<BaseData> > Read() override;
typedef short DiffusionPixelType;
typedef mitk::Image OutputType;
typedef mitk::DiffusionPropertyHelper::ImageType VectorImageType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType;
typedef mitk::DiffusionPropertyHelper::MeasurementFrameType MeasurementFrameType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType;
protected:
OutputType::Pointer m_OutputCache;
itk::TimeStamp m_CacheTime;
void InternalRead();
private:
DiffusionImageNiftiReader* Clone() const override;
us::ServiceRegistration<mitk::IFileReader> m_ServiceReg;
};
} //namespace MITK
#endif // __mitkDiffusionImageNiftiReader_h
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNiftiWriter.cpp b/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNiftiWriter.cpp
index 107b7e2..ad107c4 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNiftiWriter.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNiftiWriter.cpp
@@ -1,249 +1,249 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkDiffusionImageNiftiWriter__cpp
#define __mitkDiffusionImageNiftiWriter__cpp
#include "mitkDiffusionImageNiftiWriter.h"
#include "itkMetaDataDictionary.h"
#include "itkMetaDataObject.h"
#include "itkNiftiImageIO.h"
#include "itkImageFileWriter.h"
#include "itksys/SystemTools.hxx"
#include "mitkDiffusionIOMimeTypes.h"
#include "mitkImageCast.h"
#include <mitkLocaleSwitch.h>
#include <iostream>
#include <fstream>
#include <mitkDiffusionFunctionCollection.h>
mitk::DiffusionImageNiftiWriter::DiffusionImageNiftiWriter()
: AbstractFileWriter(mitk::Image::GetStaticNameOfClass(), CustomMimeType( mitk::DiffusionIOMimeTypes::DWI_NIFTI_MIMETYPE() ), mitk::DiffusionIOMimeTypes::DWI_NIFTI_MIMETYPE_DESCRIPTION())
{
RegisterService();
}
mitk::DiffusionImageNiftiWriter::DiffusionImageNiftiWriter(const mitk::DiffusionImageNiftiWriter& other)
: AbstractFileWriter(other)
{
}
mitk::DiffusionImageNiftiWriter::~DiffusionImageNiftiWriter()
{}
void mitk::DiffusionImageNiftiWriter::Write()
{
mitk::Image::ConstPointer input = dynamic_cast<const mitk::Image *>(this->GetInput());
VectorImageType::Pointer itkImg;
mitk::CastToItkImage(input,itkImg);
if (input.IsNull())
{
MITK_ERROR <<"Sorry, input to DiffusionImageNiftiWriter is nullptr!";
return;
}
if ( this->GetOutputLocation().empty() )
{
MITK_ERROR << "Sorry, filename has not been set!";
return ;
}
mitk::LocaleSwitch localeSwitch("C");
char keybuffer[512];
char valbuffer[512];
//itk::MetaDataDictionary dic = input->GetImage()->GetMetaDataDictionary();
vnl_matrix_fixed<double,3,3> measurementFrame = mitk::DiffusionPropertyHelper::GetMeasurementFrame(input);
if (measurementFrame(0,0) || measurementFrame(0,1) || measurementFrame(0,2) ||
measurementFrame(1,0) || measurementFrame(1,1) || measurementFrame(1,2) ||
measurementFrame(2,0) || measurementFrame(2,1) || measurementFrame(2,2))
{
sprintf( valbuffer, " (%lf,%lf,%lf) (%lf,%lf,%lf) (%lf,%lf,%lf)", measurementFrame(0,0), measurementFrame(0,1), measurementFrame(0,2), measurementFrame(1,0), measurementFrame(1,1), measurementFrame(1,2), measurementFrame(2,0), measurementFrame(2,1), measurementFrame(2,2));
itk::EncapsulateMetaData<std::string>(itkImg->GetMetaDataDictionary(),std::string("measurement frame"),std::string(valbuffer));
}
sprintf( valbuffer, "DWMRI");
itk::EncapsulateMetaData<std::string>(itkImg->GetMetaDataDictionary(),std::string("modality"),std::string(valbuffer));
if(mitk::DiffusionPropertyHelper::GetGradientContainer(input)->Size())
{
sprintf( valbuffer, "%1f", mitk::DiffusionPropertyHelper::GetReferenceBValue(input) );
itk::EncapsulateMetaData<std::string>(itkImg->GetMetaDataDictionary(),std::string("DWMRI_b-value"),std::string(valbuffer));
}
for(unsigned int i=0; i<mitk::DiffusionPropertyHelper::GetGradientContainer(input)->Size(); i++)
{
sprintf( keybuffer, "DWMRI_gradient_%04d", i );
/*if(itk::ExposeMetaData<std::string>(input->GetMetaDataDictionary(),
std::string(keybuffer),tmp))
continue;*/
sprintf( valbuffer, "%1f %1f %1f", mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).get(0),
mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).get(1), mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).get(2));
itk::EncapsulateMetaData<std::string>(itkImg->GetMetaDataDictionary(),std::string(keybuffer),std::string(valbuffer));
}
typedef itk::VectorImage<short,3> ImageType;
std::string ext = this->GetMimeType()->GetExtension(this->GetOutputLocation());
ext = itksys::SystemTools::LowerCase(ext);
// default extension is .nii.gz
if( ext == "")
{
ext = ".nii.gz";
this->SetOutputLocation(this->GetOutputLocation() + ext);
}
if (ext == ".nii" || ext == ".nii.gz")
{
MITK_INFO << "Writing Nifti-Image";
typedef itk::Image<short,4> ImageType4D;
ImageType4D::Pointer img4 = ImageType4D::New();
ImageType::SpacingType spacing = itkImg->GetSpacing();
ImageType4D::SpacingType spacing4;
for(int i=0; i<3; i++)
spacing4[i] = spacing[i];
spacing4[3] = 1;
img4->SetSpacing( spacing4 ); // Set the image spacing
ImageType::PointType origin = itkImg->GetOrigin();
ImageType4D::PointType origin4;
for(int i=0; i<3; i++)
origin4[i] = origin[i];
origin4[3] = 0;
img4->SetOrigin( origin4 ); // Set the image origin
ImageType::DirectionType direction = itkImg->GetDirection();
ImageType4D::DirectionType direction4;
for(int i=0; i<3; i++)
for(int j=0; j<3; j++)
direction4[i][j] = direction[i][j];
for(int i=0; i<4; i++)
direction4[i][3] = 0;
for(int i=0; i<4; i++)
direction4[3][i] = 0;
direction4[3][3] = 1;
img4->SetDirection( direction4 ); // Set the image direction
ImageType::RegionType region = itkImg->GetLargestPossibleRegion();
ImageType4D::RegionType region4;
ImageType::RegionType::SizeType size = region.GetSize();
ImageType4D::RegionType::SizeType size4;
for(int i=0; i<3; i++)
size4[i] = size[i];
size4[3] = itkImg->GetVectorLength();
ImageType::RegionType::IndexType index = region.GetIndex();
ImageType4D::RegionType::IndexType index4;
for(int i=0; i<3; i++)
index4[i] = index[i];
index4[3] = 0;
region4.SetSize(size4);
region4.SetIndex(index4);
img4->SetRegions( region4 );
img4->Allocate();
itk::ImageRegionIterator<ImageType> it (itkImg, itkImg->GetLargestPossibleRegion() );
typedef ImageType::PixelType VecPixType;
for (it.GoToBegin(); !it.IsAtEnd(); ++it)
{
VecPixType vec = it.Get();
ImageType::IndexType currentIndex = it.GetIndex();
for(unsigned int ind=0; ind<vec.Size(); ind++)
{
for(int i=0; i<3; i++)
index4[i] = currentIndex[i];
index4[3] = ind;
img4->SetPixel(index4, vec[ind]);
}
}
itk::NiftiImageIO::Pointer io4 = itk::NiftiImageIO::New();
typedef itk::ImageFileWriter<ImageType4D> WriterType4;
WriterType4::Pointer nrrdWriter4 = WriterType4::New();
nrrdWriter4->UseInputMetaDataDictionaryOn();
nrrdWriter4->SetInput( img4 );
nrrdWriter4->SetFileName(this->GetOutputLocation());
nrrdWriter4->UseCompressionOn();
nrrdWriter4->SetImageIO(io4);
try
{
nrrdWriter4->Update();
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.GetDescription() << std::endl;
throw;
}
std::string base_path = itksys::SystemTools::GetFilenamePath(this->GetOutputLocation());
std::string bvals_file = this->GetMimeType()->GetFilenameWithoutExtension(this->GetOutputLocation());
if (!base_path.empty())
bvals_file = base_path + "/" + bvals_file;
bvals_file += ".bvals";
std::string bvecs_file = this->GetMimeType()->GetFilenameWithoutExtension(this->GetOutputLocation());
if (!base_path.empty())
bvecs_file = base_path + "/" + bvecs_file;
bvecs_file += ".bvecs";
if(mitk::DiffusionPropertyHelper::GetOriginalGradientContainer(input)->Size())
{
MITK_INFO << "Saving original gradient directions";
mitk::gradients::WriteBvalsBvecs(bvals_file, bvecs_file, mitk::DiffusionPropertyHelper::GetOriginalGradientContainer(input), mitk::DiffusionPropertyHelper::GetReferenceBValue(input));
}
else if(mitk::DiffusionPropertyHelper::GetGradientContainer(input)->Size())
{
MITK_INFO << "Original gradient directions not found. Saving modified gradient directions";
mitk::gradients::WriteBvalsBvecs(bvals_file, bvecs_file, mitk::DiffusionPropertyHelper::GetGradientContainer(input), mitk::DiffusionPropertyHelper::GetReferenceBValue(input));
}
}
}
mitk::DiffusionImageNiftiWriter* mitk::DiffusionImageNiftiWriter::Clone() const
{
return new DiffusionImageNiftiWriter(*this);
}
mitk::IFileWriter::ConfidenceLevel mitk::DiffusionImageNiftiWriter::GetConfidenceLevel() const
{
mitk::Image::ConstPointer input = dynamic_cast<const mitk::Image*>(this->GetInput());
if (input.IsNull() || !mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( input ) )
{
return Unsupported;
}
else
{
return Supported;
}
}
#endif //__mitkDiffusionImageNiftiWriter__cpp
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNiftiWriter.h b/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNiftiWriter.h
index 5fde20b..a06c305 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNiftiWriter.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNiftiWriter.h
@@ -1,58 +1,58 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_DiffusionImageNiftiWriter__H_
#define _MITK_DiffusionImageNiftiWriter__H_
#include <mitkAbstractFileWriter.h>
#include <mitkDiffusionPropertyHelper.h>
namespace mitk
{
/**
* Writes diffusion volumes to a file
* @ingroup Process
*/
class DiffusionImageNiftiWriter : public mitk::AbstractFileWriter
{
public:
DiffusionImageNiftiWriter();
~DiffusionImageNiftiWriter() override;
using AbstractFileWriter::Write;
void Write() override;
ConfidenceLevel GetConfidenceLevel() const override;
typedef mitk::DiffusionPropertyHelper::ImageType VectorImageType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType;
typedef mitk::DiffusionPropertyHelper::MeasurementFrameType MeasurementFrameType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType;
protected:
DiffusionImageNiftiWriter(const DiffusionImageNiftiWriter& other);
mitk::DiffusionImageNiftiWriter* Clone() const override;
};
} // end of namespace mitk
#endif
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNrrdReader.cpp b/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNrrdReader.cpp
index 3cb364a..2ba88c3 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNrrdReader.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNrrdReader.cpp
@@ -1,249 +1,249 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkDiffusionImageNrrdReader_cpp
#define __mitkDiffusionImageNrrdReader_cpp
#include "mitkDiffusionImageNrrdReader.h"
#include <iostream>
#include <fstream>
// Diffusion properties
#include <mitkGradientDirectionsProperty.h>
#include <mitkBValueMapProperty.h>
#include <mitkMeasurementFrameProperty.h>
#include <mitkProperties.h>
// ITK includes
#include <itkImageRegionIterator.h>
#include <itkMetaDataObject.h>
#include "itksys/SystemTools.hxx"
#include "itkImageFileReader.h"
#include "itkMetaDataObject.h"
#include "itkNrrdImageIO.h"
#include "mitkCustomMimeType.h"
#include "mitkDiffusionIOMimeTypes.h"
#include <mitkITKImageImport.h>
#include <mitkImageWriteAccessor.h>
#include <mitkImageDataItem.h>
#include "mitkIOUtil.h"
#include <mitkLocaleSwitch.h>
namespace mitk
{
DiffusionImageNrrdReader::
DiffusionImageNrrdReader(const DiffusionImageNrrdReader & other)
: AbstractFileReader(other)
{
}
DiffusionImageNrrdReader* DiffusionImageNrrdReader::Clone() const
{
return new DiffusionImageNrrdReader(*this);
}
DiffusionImageNrrdReader::
~DiffusionImageNrrdReader()
{}
DiffusionImageNrrdReader::
DiffusionImageNrrdReader()
: mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::DWI_NRRD_MIMETYPE() ), mitk::DiffusionIOMimeTypes::DWI_NRRD_MIMETYPE_DESCRIPTION() )
{
Options defaultOptions;
defaultOptions["Apply image rotation to gradients"] = true;
this->SetDefaultOptions(defaultOptions);
m_ServiceReg = this->RegisterService();
}
std::vector<itk::SmartPointer<mitk::BaseData> >
DiffusionImageNrrdReader::
Read()
{
std::vector<itk::SmartPointer<mitk::BaseData> > 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 DiffusionImageNrrdReader::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 << "DiffusionImageNrrdReader: reading image information";
VectorImageType::Pointer itkVectorImage;
std::string ext = this->GetMimeType()->GetExtension( this->GetInputLocation() );
ext = itksys::SystemTools::LowerCase( ext );
if (ext == ".hdwi" || ext == ".dwi" || ext == ".nrrd")
{
typedef itk::ImageFileReader<VectorImageType> FileReaderType;
FileReaderType::Pointer reader = FileReaderType::New();
reader->SetFileName(this->GetInputLocation());
itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New();
reader->SetImageIO(io);
reader->Update();
itkVectorImage = reader->GetOutput();
}
// Diffusion Image information START
GradientDirectionContainerType::Pointer DiffusionVectors = GradientDirectionContainerType::New();
GradientDirectionContainerType::Pointer OriginalDiffusionVectors = GradientDirectionContainerType::New();
MeasurementFrameType MeasurementFrame;
float BValue = -1;
// Diffusion Image information END
if (ext == ".hdwi" || ext == ".dwi" || ext == ".nrrd")
{
itk::MetaDataDictionary imgMetaDictionary = itkVectorImage->GetMetaDataDictionary();
std::vector<std::string> imgMetaKeys = imgMetaDictionary.GetKeys();
std::vector<std::string>::const_iterator itKey = imgMetaKeys.begin();
std::string metaString;
GradientDirectionType vect3d;
int numberOfImages = 0;
int numberOfGradientImages = 0;
bool readb0 = false;
double xx, xy, xz, yx, yy, yz, zx, zy, zz;
for (; itKey != imgMetaKeys.end(); itKey ++)
{
double x,y,z;
itk::ExposeMetaData<std::string> (imgMetaDictionary, *itKey, metaString);
if (itKey->find("DWMRI_gradient") != std::string::npos)
{
sscanf(metaString.c_str(), "%lf %lf %lf\n", &x, &y, &z);
vect3d[0] = x; vect3d[1] = y; vect3d[2] = z;
DiffusionVectors->InsertElement( numberOfImages, vect3d );
++numberOfImages;
// If the direction is 0.0, this is a reference image
if (vect3d[0] == 0.0 &&
vect3d[1] == 0.0 &&
vect3d[2] == 0.0)
{
continue;
}
++numberOfGradientImages;;
}
else if (itKey->find("DWMRI_b-value") != std::string::npos)
{
readb0 = true;
BValue = atof(metaString.c_str());
}
else if (itKey->find("measurement frame") != std::string::npos)
{
sscanf(metaString.c_str(), " ( %lf , %lf , %lf ) ( %lf , %lf , %lf ) ( %lf , %lf , %lf ) \n", &xx, &xy, &xz, &yx, &yy, &yz, &zx, &zy, &zz);
if (xx>10e-10 || xy>10e-10 || xz>10e-10 ||
yx>10e-10 || yy>10e-10 || yz>10e-10 ||
zx>10e-10 || zy>10e-10 || zz>10e-10 )
{
MeasurementFrame(0,0) = xx;
MeasurementFrame(0,1) = xy;
MeasurementFrame(0,2) = xz;
MeasurementFrame(1,0) = yx;
MeasurementFrame(1,1) = yy;
MeasurementFrame(1,2) = yz;
MeasurementFrame(2,0) = zx;
MeasurementFrame(2,1) = zy;
MeasurementFrame(2,2) = zz;
}
else
{
MeasurementFrame(0,0) = 1;
MeasurementFrame(0,1) = 0;
MeasurementFrame(0,2) = 0;
MeasurementFrame(1,0) = 0;
MeasurementFrame(1,1) = 1;
MeasurementFrame(1,2) = 0;
MeasurementFrame(2,0) = 0;
MeasurementFrame(2,1) = 0;
MeasurementFrame(2,2) = 1;
}
}
}
if(!readb0)
{
MITK_INFO << "BValue not specified in header file";
}
}
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<bool>(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 vessel tree file!");
}
}
}
} //namespace MITK
#endif
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNrrdReader.h b/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNrrdReader.h
index 9a73f18..6f55b5a 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNrrdReader.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNrrdReader.h
@@ -1,73 +1,73 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkDiffusionImageNrrdReader_h
#define __mitkDiffusionImageNrrdReader_h
#include "mitkCommon.h"
// MITK includes
#include "mitkImageSource.h"
#include "mitkFileReader.h"
#include <mitkDiffusionPropertyHelper.h>
// ITK includes
#include "itkVectorImage.h"
#include "mitkAbstractFileReader.h"
namespace mitk
{
/** \brief
*/
class DiffusionImageNrrdReader : public mitk::AbstractFileReader
{
public:
DiffusionImageNrrdReader(const DiffusionImageNrrdReader & other);
DiffusionImageNrrdReader();
~DiffusionImageNrrdReader() override;
using AbstractFileReader::Read;
std::vector<itk::SmartPointer<BaseData> > Read() override;
typedef short DiffusionPixelType;
typedef mitk::Image OutputType;
typedef mitk::DiffusionPropertyHelper::ImageType VectorImageType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType;
typedef mitk::DiffusionPropertyHelper::MeasurementFrameType MeasurementFrameType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType;
protected:
OutputType::Pointer m_OutputCache;
itk::TimeStamp m_CacheTime;
void InternalRead();
private:
DiffusionImageNrrdReader* Clone() const override;
us::ServiceRegistration<mitk::IFileReader> m_ServiceReg;
};
} //namespace MITK
#endif // __mitkDiffusionImageNrrdReader_h
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNrrdWriter.cpp b/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNrrdWriter.cpp
index 32bee13..ca3e6fa 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNrrdWriter.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNrrdWriter.cpp
@@ -1,173 +1,173 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkDiffusionImageNrrdWriter__cpp
#define __mitkDiffusionImageNrrdWriter__cpp
#include "mitkDiffusionImageNrrdWriter.h"
#include "itkMetaDataDictionary.h"
#include "itkMetaDataObject.h"
#include "itkNrrdImageIO.h"
#include "itkImageFileWriter.h"
#include "itksys/SystemTools.hxx"
#include "mitkDiffusionIOMimeTypes.h"
#include "mitkImageCast.h"
#include <mitkLocaleSwitch.h>
#include <iostream>
#include <fstream>
mitk::DiffusionImageNrrdWriter::DiffusionImageNrrdWriter()
: AbstractFileWriter(mitk::Image::GetStaticNameOfClass(), CustomMimeType( mitk::DiffusionIOMimeTypes::DWI_NRRD_MIMETYPE() ), mitk::DiffusionIOMimeTypes::DWI_NRRD_MIMETYPE_DESCRIPTION())
{
RegisterService();
}
mitk::DiffusionImageNrrdWriter::DiffusionImageNrrdWriter(const mitk::DiffusionImageNrrdWriter& other)
: AbstractFileWriter(other)
{
}
mitk::DiffusionImageNrrdWriter::~DiffusionImageNrrdWriter()
{}
void mitk::DiffusionImageNrrdWriter::Write()
{
mitk::Image::ConstPointer input = dynamic_cast<const mitk::Image *>(this->GetInput());
VectorImageType::Pointer itkImg;
mitk::CastToItkImage(input,itkImg);
if (input.IsNull())
{
MITK_ERROR <<"Sorry, input to DiffusionImageNrrdWriter is nullptr!";
return;
}
if ( this->GetOutputLocation().empty() )
{
MITK_ERROR << "Sorry, filename has not been set!";
return ;
}
mitk::LocaleSwitch localeSwitch("C");
char keybuffer[512];
char valbuffer[512];
//itk::MetaDataDictionary dic = input->GetImage()->GetMetaDataDictionary();
vnl_matrix_fixed<double,3,3> measurementFrame = mitk::DiffusionPropertyHelper::GetMeasurementFrame(input);
if (measurementFrame(0,0) || measurementFrame(0,1) || measurementFrame(0,2) ||
measurementFrame(1,0) || measurementFrame(1,1) || measurementFrame(1,2) ||
measurementFrame(2,0) || measurementFrame(2,1) || measurementFrame(2,2))
{
sprintf( valbuffer, " (%lf,%lf,%lf) (%lf,%lf,%lf) (%lf,%lf,%lf)", measurementFrame(0,0), measurementFrame(0,1), measurementFrame(0,2), measurementFrame(1,0), measurementFrame(1,1), measurementFrame(1,2), measurementFrame(2,0), measurementFrame(2,1), measurementFrame(2,2));
itk::EncapsulateMetaData<std::string>(itkImg->GetMetaDataDictionary(),std::string("measurement frame"),std::string(valbuffer));
}
sprintf( valbuffer, "DWMRI");
itk::EncapsulateMetaData<std::string>(itkImg->GetMetaDataDictionary(),std::string("modality"),std::string(valbuffer));
if (mitk::DiffusionPropertyHelper::GetOriginalGradientContainer(input)->Size())
{
MITK_INFO << "Saving original gradient directions";
sprintf( valbuffer, "%1f", mitk::DiffusionPropertyHelper::GetReferenceBValue(input) );
itk::EncapsulateMetaData<std::string>(itkImg->GetMetaDataDictionary(),std::string("DWMRI_b-value"),std::string(valbuffer));
for(unsigned int i=0; i<mitk::DiffusionPropertyHelper::GetGradientContainer(input)->Size(); i++)
{
sprintf( keybuffer, "DWMRI_gradient_%04d", i );
sprintf( valbuffer, "%1f %1f %1f", mitk::DiffusionPropertyHelper::GetOriginalGradientContainer(input)->ElementAt(i).get(0),
mitk::DiffusionPropertyHelper::GetOriginalGradientContainer(input)->ElementAt(i).get(1), mitk::DiffusionPropertyHelper::GetOriginalGradientContainer(input)->ElementAt(i).get(2));
itk::EncapsulateMetaData<std::string>(itkImg->GetMetaDataDictionary(),std::string(keybuffer),std::string(valbuffer));
}
}
else if(mitk::DiffusionPropertyHelper::GetGradientContainer(input)->Size())
{
MITK_INFO << "Original gradient directions not found. Saving modified gradient directions";
sprintf( valbuffer, "%1f", mitk::DiffusionPropertyHelper::GetReferenceBValue(input) );
itk::EncapsulateMetaData<std::string>(itkImg->GetMetaDataDictionary(),std::string("DWMRI_b-value"),std::string(valbuffer));
for(unsigned int i=0; i<mitk::DiffusionPropertyHelper::GetGradientContainer(input)->Size(); i++)
{
sprintf( keybuffer, "DWMRI_gradient_%04d", i );
sprintf( valbuffer, "%1f %1f %1f", mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).get(0),
mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).get(1), mitk::DiffusionPropertyHelper::GetGradientContainer(input)->ElementAt(i).get(2));
itk::EncapsulateMetaData<std::string>(itkImg->GetMetaDataDictionary(),std::string(keybuffer),std::string(valbuffer));
}
}
typedef itk::VectorImage<short,3> ImageType;
std::string ext = this->GetMimeType()->GetExtension(this->GetOutputLocation());
ext = itksys::SystemTools::LowerCase(ext);
// default extension is .nrrd
if( ext == "")
{
ext = ".nrrd";
this->SetOutputLocation(this->GetOutputLocation() + ext);
}
if (ext == ".hdwi" || ext == ".nrrd" || ext == ".dwi")
{
itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New();
io->SetFileType( itk::ImageIOBase::Binary );
io->UseCompressionOn();
typedef itk::ImageFileWriter<ImageType> WriterType;
WriterType::Pointer nrrdWriter = WriterType::New();
nrrdWriter->UseInputMetaDataDictionaryOn();
nrrdWriter->SetInput( itkImg );
nrrdWriter->SetImageIO(io);
nrrdWriter->SetFileName(this->GetOutputLocation());
nrrdWriter->UseCompressionOn();
nrrdWriter->SetImageIO(io);
try
{
nrrdWriter->Update();
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.GetDescription() << std::endl;
throw;
}
}
}
mitk::DiffusionImageNrrdWriter* mitk::DiffusionImageNrrdWriter::Clone() const
{
return new DiffusionImageNrrdWriter(*this);
}
mitk::IFileWriter::ConfidenceLevel mitk::DiffusionImageNrrdWriter::GetConfidenceLevel() const
{
mitk::Image::ConstPointer input = dynamic_cast<const mitk::Image*>(this->GetInput());
if (input.IsNull() || !mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( input ) )
{
return Unsupported;
}
else
{
return Supported;
}
}
#endif //__mitkDiffusionImageNrrdWriter__cpp
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNrrdWriter.h b/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNrrdWriter.h
index dda3cfa..b29c34f 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNrrdWriter.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkDiffusionImageNrrdWriter.h
@@ -1,58 +1,58 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_DiffusionImageNrrdWriter__H_
#define _MITK_DiffusionImageNrrdWriter__H_
#include <mitkAbstractFileWriter.h>
#include <mitkDiffusionPropertyHelper.h>
namespace mitk
{
/**
* Writes diffusion volumes to a file
* @ingroup Process
*/
class DiffusionImageNrrdWriter : public mitk::AbstractFileWriter
{
public:
DiffusionImageNrrdWriter();
~DiffusionImageNrrdWriter() override;
using AbstractFileWriter::Write;
void Write() override;
ConfidenceLevel GetConfidenceLevel() const override;
typedef mitk::DiffusionPropertyHelper::ImageType VectorImageType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType;
typedef mitk::DiffusionPropertyHelper::MeasurementFrameType MeasurementFrameType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType;
protected:
DiffusionImageNrrdWriter(const DiffusionImageNrrdWriter& other);
mitk::DiffusionImageNrrdWriter* Clone() const override;
};
} // end of namespace mitk
#endif
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleDicomReader.cpp b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleDicomReader.cpp
index 9fb11a6..0de308d 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleDicomReader.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleDicomReader.cpp
@@ -1,180 +1,180 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkFiberBundleDicomReader.h"
#include <itkMetaDataObject.h>
#include <vtkPolyData.h>
#include <vtkDataReader.h>
#include <vtkPolyDataReader.h>
#include <vtkMatrix4x4.h>
#include <vtkPolyLine.h>
#include <vtkCellArray.h>
#include <vtkDataArray.h>
#include <vtkFloatArray.h>
#include <vtkCellData.h>
#include <vtkPointData.h>
#include <itksys/SystemTools.hxx>
#include <tinyxml.h>
#include <vtkCleanPolyData.h>
#include <mitkTrackvis.h>
#include <mitkCustomMimeType.h>
#include "mitkDiffusionIOMimeTypes.h"
#include <vtkTransformPolyDataFilter.h>
#include <mitkLexicalCast.h>
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
#include "dcmtk/dcmtract/trctractographyresults.h"
#include "dcmtk/dcmtract/trctrack.h"
mitk::FiberBundleDicomReader::FiberBundleDicomReader()
: mitk::AbstractFileReader( mitk::DiffusionIOMimeTypes::FIBERBUNDLE_DICOM_MIMETYPE_NAME(), "DICOM Fiber Bundle Reader" )
{
m_ServiceReg = this->RegisterService();
}
mitk::FiberBundleDicomReader::FiberBundleDicomReader(const FiberBundleDicomReader &other)
:mitk::AbstractFileReader(other)
{
}
mitk::FiberBundleDicomReader * mitk::FiberBundleDicomReader::Clone() const
{
return new FiberBundleDicomReader(*this);
}
std::vector<itk::SmartPointer<mitk::BaseData> > mitk::FiberBundleDicomReader::Read()
{
std::vector<itk::SmartPointer<mitk::BaseData> > output_fibs;
try
{
const std::string& locale = "C";
const std::string& currLocale = setlocale( LC_ALL, nullptr );
setlocale(LC_ALL, locale.c_str());
std::string filename = this->GetInputLocation();
OFCondition result;
TrcTractographyResults *trc = nullptr;
result = TrcTractographyResults::loadFile(filename.c_str(), trc);
if (result.bad())
mitkThrow() << "Unable to load tractography dicom file: " << result.text();
OFString val = "-";
trc->getPatient().getPatientName(val);
MITK_INFO << "Patient Name: " << val; val = "-";
trc->getStudy().getStudyInstanceUID(val);
MITK_INFO << "Study : " << val; val = "-";
trc->getSeries().getSeriesInstanceUID(val);
MITK_INFO << "Series : " << val; val = "-";
trc->getSOPCommon().getSOPInstanceUID(val);
MITK_INFO << "Instance : " << val; val = "-";
MITK_INFO << "-------------------------------------------------------------------------";
size_t numTrackSets = trc->getNumberOfTrackSets();
OFVector<TrcTrackSet*>& sets = trc->getTrackSets();
for (size_t ts = 0; ts < numTrackSets; ts++)
{
size_t numTracks = sets[ts]->getNumberOfTracks();
MITK_INFO << " Track Set #" << ts << ": " << numTracks << " Tracks, "
<< sets[ts]->getNumberOfTrackSetStatistics() << " Track Set Statistics, "
<< sets[ts]->getNumberOfTrackStatistics() << " Track Statistics, "
<< sets[ts]->getNumberOfMeasurements() << " Measurements ";
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
for (size_t t = 0; t < numTracks; t++)
{
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
TrcTrack* track = sets[ts]->getTracks()[t];
const Float32* vals = nullptr;
size_t numPoints = track->getTrackData(vals);
for (size_t v = 0; v < numPoints; ++v)
{
vtkIdType id = vtkNewPoints->InsertNextPoint(vals[v*3],vals[v*3+1],vals[v*3+2]);
container->GetPointIds()->InsertNextId(id);
}
vtkNewCells->InsertNextCell(container);
}
vtkSmartPointer<vtkPolyData> fiberPolyData = vtkSmartPointer<vtkPolyData>::New();
fiberPolyData->SetPoints(vtkNewPoints);
fiberPolyData->SetLines(vtkNewCells);
// // transform polydata from RAS (MRtrix) to LPS (MITK)
// mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New();
// vtkSmartPointer< vtkMatrix4x4 > matrix = vtkSmartPointer< vtkMatrix4x4 >::New();
// matrix->Identity();
// matrix->SetElement(0,0,-matrix->GetElement(0,0));
// matrix->SetElement(1,1,-matrix->GetElement(1,1));
// geometry->SetIndexToWorldTransformByVtkMatrix(matrix);
// vtkSmartPointer<vtkTransformPolyDataFilter> transformFilter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
// transformFilter->SetInputData(fiberPolyData);
// transformFilter->SetTransform(geometry->GetVtkTransform());
// transformFilter->Update();
FiberBundle::Pointer fib = FiberBundle::New(fiberPolyData);
CodeSequenceMacro* algoCode = sets[ts]->getTrackingAlgorithmIdentification().at(0);
val = "-"; algoCode->getCodeValue(val);
fib->GetPropertyList()->SetStringProperty("DICOM.algo_code.value",val.c_str());
val = "-"; algoCode->getCodeMeaning(val);
fib->GetPropertyList()->SetStringProperty("DICOM.algo_code.meaning",val.c_str());
CodeSequenceMacro modelCode = sets[ts]->getDiffusionModelCode();
val = "-"; modelCode.getCodeValue(val);
fib->GetPropertyList()->SetStringProperty("DICOM.model_code.value",val.c_str());
val = "-"; modelCode.getCodeMeaning(val);
fib->GetPropertyList()->SetStringProperty("DICOM.model_code.meaning",val.c_str());
CodeWithModifiers anatomy = sets[ts]->getTrackSetAnatomy();
val = "-"; anatomy.getCodeValue(val);
fib->GetPropertyList()->SetStringProperty("DICOM.anatomy.value",val.c_str());
val = "-"; anatomy.getCodeMeaning(val);
fib->GetPropertyList()->SetStringProperty("DICOM.anatomy.meaning",val.c_str());
val = "-"; trc->getPatient().getPatientID(val);
fib->GetPropertyList()->SetStringProperty("DICOM.patient_id",val.c_str());
val = "-"; trc->getPatient().getPatientName(val);
fib->GetPropertyList()->SetStringProperty("DICOM.patient_name",val.c_str());
val = "-"; trc->getStudy().getStudyInstanceUID(val);
fib->GetPropertyList()->SetStringProperty("DICOM.study_instance_uid",val.c_str());
val = "-"; trc->getSeries().getSeriesInstanceUID(val);
fib->GetPropertyList()->SetStringProperty("DICOM.series_instance_uid",val.c_str());
val = "-"; trc->getSOPCommon().getSOPInstanceUID(val);
fib->GetPropertyList()->SetStringProperty("DICOM.sop_instance_uid",val.c_str());
val = "-"; trc->getSOPCommon().getSOPClassUID(val);
fib->GetPropertyList()->SetStringProperty("DICOM.sop_class_uid",val.c_str());
val = "-"; trc->getFrameOfReference().getFrameOfReferenceUID(val);
fib->GetPropertyList()->SetStringProperty("DICOM.frame_of_reference_uid",val.c_str());
output_fibs.push_back(fib.GetPointer());
MITK_INFO << "Fiber bundle read";
}
delete trc;
setlocale(LC_ALL, currLocale.c_str());
return output_fibs;
}
catch(...)
{
throw;
}
return output_fibs;
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleDicomReader.h b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleDicomReader.h
index 8f24783..a9e4465 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleDicomReader.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleDicomReader.h
@@ -1,52 +1,52 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkFiberBundleDicomReader_h
#define __mitkFiberBundleDicomReader_h
#include <mitkCommon.h>
#include <mitkFileReader.h>
#include <mitkFiberBundle.h>
#include <vtkSmartPointer.h>
#include <mitkAbstractFileReader.h>
namespace mitk
{
/** \brief
*/
class FiberBundleDicomReader : public AbstractFileReader
{
public:
FiberBundleDicomReader();
~FiberBundleDicomReader() override{}
FiberBundleDicomReader(const FiberBundleDicomReader& other);
FiberBundleDicomReader * Clone() const override;
using mitk::AbstractFileReader::Read;
std::vector<itk::SmartPointer<BaseData> > Read() override;
private:
us::ServiceRegistration<mitk::IFileReader> m_ServiceReg;
};
} //namespace MITK
#endif // __mitkFiberBundleReader_h
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleDicomWriter.cpp b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleDicomWriter.cpp
index 87870b3..c9c7829 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleDicomWriter.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleDicomWriter.cpp
@@ -1,187 +1,187 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkFiberBundleDicomWriter.h"
#include <vtkSmartPointer.h>
#include <itksys/SystemTools.hxx>
#include <itkSize.h>
#include <vtkFloatArray.h>
#include <vtkCellData.h>
#include <vtkPointData.h>
#include <mitkAbstractFileWriter.h>
#include <mitkCustomMimeType.h>
#include "mitkDiffusionIOMimeTypes.h"
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
#include "dcmtk/dcmtract/trctractographyresults.h"
mitk::FiberBundleDicomWriter::FiberBundleDicomWriter()
: mitk::AbstractFileWriter(mitk::FiberBundle::GetStaticNameOfClass(), mitk::DiffusionIOMimeTypes::FIBERBUNDLE_DICOM_MIMETYPE_NAME(), "DICOM Fiber Bundle Writer")
{
RegisterService();
}
mitk::FiberBundleDicomWriter::FiberBundleDicomWriter(const mitk::FiberBundleDicomWriter & other)
:mitk::AbstractFileWriter(other)
{}
mitk::FiberBundleDicomWriter::~FiberBundleDicomWriter()
{}
mitk::FiberBundleDicomWriter * mitk::FiberBundleDicomWriter::Clone() const
{
return new mitk::FiberBundleDicomWriter(*this);
}
void mitk::FiberBundleDicomWriter::Write()
{
try
{
mitk::FiberBundle::ConstPointer fib = dynamic_cast<const mitk::FiberBundle*>(this->GetInput());
vtkPolyData* poly = fib->GetFiberPolyData();
mitk::PropertyList* p_list = fib->GetPropertyList();
std::string patient_id = "";
if (!p_list->GetStringProperty("DICOM.patient_id", patient_id))
patient_id = "-";
std::string patient_name = "";
if (!p_list->GetStringProperty("DICOM.patient_name", patient_name))
patient_name = "-";
std::string study_instance_uid = "";
if (!p_list->GetStringProperty("DICOM.study_instance_uid", study_instance_uid))
study_instance_uid = "-";
std::string series_instance_uid = "";
if (!p_list->GetStringProperty("DICOM.series_instance_uid", series_instance_uid))
series_instance_uid = "-";
std::string sop_instance_uid = "";
if (!p_list->GetStringProperty("DICOM.sop_instance_uid", sop_instance_uid))
sop_instance_uid = "-";
std::string frame_of_reference_uid = "";
if (!p_list->GetStringProperty("DICOM.frame_of_reference_uid", frame_of_reference_uid))
frame_of_reference_uid = "-";
std::string algo_code_value = "";
if (!p_list->GetStringProperty("DICOM.algo_code.value", algo_code_value))
algo_code_value = "-";
std::string algo_code_meaning = "";
if (!p_list->GetStringProperty("DICOM.algo_code.meaning", algo_code_meaning))
algo_code_meaning = "-";
std::string model_code_value = "";
if (!p_list->GetStringProperty("DICOM.model_code.value", model_code_value))
model_code_value = "-";
std::string model_code_meaning = "";
if (!p_list->GetStringProperty("DICOM.model_code.meaning", model_code_meaning))
model_code_meaning = "-";
std::string anatomy_value = "";
if (!p_list->GetStringProperty("DICOM.anatomy.value", anatomy_value))
anatomy_value = "-";
std::string anatomy_meaning = "";
if (!p_list->GetStringProperty("DICOM.anatomy.meaning", anatomy_meaning))
anatomy_meaning = "-";
const std::string& locale = "C";
const std::string& currLocale = setlocale( LC_ALL, nullptr );
setlocale(LC_ALL, locale.c_str());
// Instance Number, Label, Description, Creator's Name
ContentIdentificationMacro id("1", "TRACTOGRAM", "Tractogram processed with MITK Diffusion", "MIC@DKFZ");
// Manufacturer, model name, serial number, software version(s)
IODEnhGeneralEquipmentModule::EquipmentInfo equipment("MIC@DKFZ", "dcmtract library", "0815", OFFIS_DCMTK_VERSION_STRING);
IODReferences refs;
// We need at least one image reference this Tractography Results object is based on.
// We provide: Patient ID, Study Instance UID, Series Instance UID, SOP Instance UID, SOP Class UID
IODImageReference* ref = new IODImageReference(patient_id.c_str(), study_instance_uid.c_str(), series_instance_uid.c_str(), sop_instance_uid.c_str(), UID_MRImageStorage);
refs.add(ref);
std::time_t t = std::time(nullptr);
char date_buffer[20];
std::strftime(date_buffer, sizeof(date_buffer), "%Y%m%d", std::gmtime(&t));
char time_buffer[20];
std::strftime(time_buffer, sizeof(time_buffer), "%H%M%S", std::gmtime(&t));
OFString contentDate(date_buffer);
OFString contentTime(time_buffer);
OFString val = "-";
TrcTractographyResults *trc = nullptr;
TrcTractographyResults::create(id, contentDate, contentTime, equipment, refs, trc);
trc->getStudy().setStudyInstanceUID(study_instance_uid.c_str());
trc->getSeries().setSeriesInstanceUID(series_instance_uid.c_str());
trc->getSOPCommon().setSOPInstanceUID(sop_instance_uid.c_str());
trc->getSeries().getSeriesInstanceUID(val);
// Create track set
CodeWithModifiers anatomy("");
anatomy.set(anatomy_value.c_str(), "SRT", anatomy_meaning.c_str());
// Every CodeSequenceMacro has: Code Value, Coding Scheme Designator, Code Meaning
CodeSequenceMacro diffusionModel(model_code_value.c_str(), "DCM", model_code_meaning.c_str());
CodeSequenceMacro algorithmId(algo_code_value.c_str(), "DCM", algo_code_meaning.c_str());
TrcTrackSet *set = nullptr;
trc->addTrackSet("TRACTOGRAM", "Tractogram processed with MITK Diffusion", anatomy, diffusionModel, algorithmId, set);
// Create trackset
Uint16 cieLabColor[3]; // color the whole track with this color; we use some blue
cieLabColor[0] = 30000; // L
cieLabColor[1] = 0 ; // a
cieLabColor[2] = 0 ; // b
std::vector< Float32* > tracts;
for (unsigned int i=0; i<fib->GetNumFibers(); i++)
{
vtkCell* cell = poly->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
Float32* pointData = new Float32[numPoints*3];
for(int i=0; i<numPoints ;i++)
{
double* p = points->GetPoint(i);
pointData[i*3] = p[0];
pointData[i*3+1] = p[1];
pointData[i*3+2] = p[2];
}
tracts.push_back(pointData);
TrcTrack* track = nullptr;
set->addTrack(pointData, numPoints, cieLabColor, 1 /* numColors */, track);
}
// Frame of Reference is required; could be the same as from related MR series
trc->getFrameOfReference().setFrameOfReferenceUID(frame_of_reference_uid.c_str());
// Set some optional data
trc->getPatient().setPatientID(patient_id.c_str());
trc->getPatient().setPatientName(patient_name.c_str());
trc->getSeries().setSeriesDescription("Tractogram processed with MITK Diffusion");
// Save file
OFCondition result = trc->saveFile(this->GetOutputLocation().c_str());
delete trc;
if (result.bad())
mitkThrow() << "Unable to save tractography as DICOM file: " << result.text();
for (Float32* tract : tracts)
delete [] tract;
setlocale(LC_ALL, currLocale.c_str());
MITK_INFO << "DICOM Fiber bundle written to " << this->GetOutputLocation();
}
catch(...)
{
throw;
}
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleDicomWriter.h b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleDicomWriter.h
index 1d1f3ee..ef8573c 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleDicomWriter.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleDicomWriter.h
@@ -1,47 +1,47 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkFiberBundleDicomWriter_h
#define __mitkFiberBundleDicomWriter_h
#include <mitkAbstractFileWriter.h>
#include "mitkFiberBundle.h"
namespace mitk
{
/**
* Writes fiber bundles to a DICOM file
* @ingroup Process
*/
class FiberBundleDicomWriter : public mitk::AbstractFileWriter
{
public:
FiberBundleDicomWriter();
FiberBundleDicomWriter(const FiberBundleDicomWriter & other);
FiberBundleDicomWriter * Clone() const override;
~FiberBundleDicomWriter() override;
using mitk::AbstractFileWriter::Write;
void Write() override;
};
} // end of namespace mitk
#endif //__mitkFiberBundleWriter_h
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleSerializer.cpp b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleSerializer.cpp
index bff7d59..9ca80cb 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleSerializer.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleSerializer.cpp
@@ -1,72 +1,72 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkFiberBundleSerializer.h"
#include "mitkFiberBundle.h"
#include "mitkFiberBundleVtkWriter.h"
#include <itksys/SystemTools.hxx>
#include <mitkIOUtil.h>
MITK_REGISTER_SERIALIZER(FiberBundleSerializer)
mitk::FiberBundleSerializer::FiberBundleSerializer()
{
}
mitk::FiberBundleSerializer::~FiberBundleSerializer()
{
}
std::string mitk::FiberBundleSerializer::Serialize()
{
const FiberBundle* fb = dynamic_cast<const FiberBundle*>( m_Data.GetPointer() );
if (fb == nullptr)
{
MITK_ERROR << " Object at " << (const void*) this->m_Data
<< " is not an mitk::FiberBundle. Cannot serialize as FiberBundle.";
return "";
}
std::string filename( this->GetUniqueFilenameInWorkingDirectory() );
filename += "_";
filename += m_FilenameHint;
filename += ".fib";
std::string fullname(m_WorkingDirectory);
fullname += "/";
fullname += itksys::SystemTools::ConvertToOutputPath(filename.c_str());
try
{
mitk::IOUtil::Save(const_cast<FiberBundle*>(fb),fullname);
}
catch (std::exception& e)
{
MITK_ERROR << " Error serializing object at " << (const void*) this->m_Data
<< " to "
<< fullname
<< ": "
<< e.what();
return "";
}
return filename;
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleSerializer.h b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleSerializer.h
index 38a1b83..194ee23 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleSerializer.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleSerializer.h
@@ -1,39 +1,39 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkFiberBundleSerializer_h_included
#define mitkFiberBundleSerializer_h_included
#include "mitkBaseDataSerializer.h"
namespace mitk
{
/**
\brief Serializes mitk::Surface for mitk::SceneIO
*/
class FiberBundleSerializer : public BaseDataSerializer
{
public:
mitkClassMacro( FiberBundleSerializer, BaseDataSerializer );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
std::string Serialize() override;
protected:
FiberBundleSerializer();
~FiberBundleSerializer() override;
};
} // namespace
#endif
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTckReader.cpp b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTckReader.cpp
index 08bf28a..f1aeeca 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTckReader.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTckReader.cpp
@@ -1,164 +1,164 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkFiberBundleTckReader.h"
#include <itkMetaDataObject.h>
#include <vtkPolyData.h>
#include <vtkDataReader.h>
#include <vtkPolyDataReader.h>
#include <vtkMatrix4x4.h>
#include <vtkPolyLine.h>
#include <vtkCellArray.h>
#include <vtkDataArray.h>
#include <vtkFloatArray.h>
#include <vtkCellData.h>
#include <vtkPointData.h>
#include <itksys/SystemTools.hxx>
#include <tinyxml.h>
#include <vtkCleanPolyData.h>
#include <mitkTrackvis.h>
#include <mitkCustomMimeType.h>
#include "mitkDiffusionIOMimeTypes.h"
#include <vtkTransformPolyDataFilter.h>
#include <mitkLexicalCast.h>
mitk::FiberBundleTckReader::FiberBundleTckReader()
: mitk::AbstractFileReader( mitk::DiffusionIOMimeTypes::FIBERBUNDLE_TCK_MIMETYPE_NAME(), "tck Fiber Bundle Reader (MRtrix format)" )
{
m_ServiceReg = this->RegisterService();
}
mitk::FiberBundleTckReader::FiberBundleTckReader(const FiberBundleTckReader &other)
:mitk::AbstractFileReader(other)
{
}
mitk::FiberBundleTckReader * mitk::FiberBundleTckReader::Clone() const
{
return new FiberBundleTckReader(*this);
}
std::vector<itk::SmartPointer<mitk::BaseData> > mitk::FiberBundleTckReader::Read()
{
std::vector<itk::SmartPointer<mitk::BaseData> > result;
try
{
const std::string& locale = "C";
const std::string& currLocale = setlocale( LC_ALL, nullptr );
setlocale(LC_ALL, locale.c_str());
std::string filename = this->GetInputLocation();
std::string ext = itksys::SystemTools::GetFilenameLastExtension(filename);
ext = itksys::SystemTools::LowerCase(ext);
if (ext==".tck")
{
MITK_INFO << "Loading tractogram (MRtrix format): " << itksys::SystemTools::GetFilenameName(filename);
std::FILE* filePointer = std::fopen(filename.c_str(),"r+b");
std::string header = "";
bool header_end = false;
int count = 0;
while (!header_end)
{
char c;
count += std::fread(&c, 1, 1, filePointer);
header += c;
if (header.size() >= 3 && header.compare(header.size() - 3, 3, "END") == 0)
header_end = true;
}
MITK_INFO << "TCK Header:";
MITK_INFO << header;
int header_size = -1;
try
{
std::string delimiter = "file: . ";
size_t pos = 0;
pos = header.find(delimiter);
header.erase(0, pos + delimiter.length());
pos = header.find("\n");
header_size = boost::lexical_cast<int>(header.substr(0, pos));
}
catch(...)
{
}
if (header_size==-1)
mitkThrow() << "Could not parse header size from " << filename;
std::fseek ( filePointer , header_size , SEEK_SET );
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
float tmp[3];
count = 1;
int fiber_length = 0;
while (std::fread((char*)tmp, 1, 12, filePointer)==12)
{
if (std::isinf(tmp[0]) || std::isinf(tmp[1]) || std::isinf(tmp[1]))
break;
else if (std::isnan(tmp[0]) || std::isnan(tmp[1]) || std::isnan(tmp[2]))
{
count++;
fiber_length = 0;
vtkNewCells->InsertNextCell(container);
container = vtkSmartPointer<vtkPolyLine>::New();
}
else
{
fiber_length++;
vtkIdType id = vtkNewPoints->InsertNextPoint(tmp);
container->GetPointIds()->InsertNextId(id);
}
}
vtkSmartPointer<vtkPolyData> fiberPolyData = vtkSmartPointer<vtkPolyData>::New();
fiberPolyData->SetPoints(vtkNewPoints);
fiberPolyData->SetLines(vtkNewCells);
// transform polydata from RAS (MRtrix) to LPS (MITK)
mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New();
vtkSmartPointer< vtkMatrix4x4 > matrix = vtkSmartPointer< vtkMatrix4x4 >::New();
matrix->Identity();
matrix->SetElement(0,0,-matrix->GetElement(0,0));
matrix->SetElement(1,1,-matrix->GetElement(1,1));
geometry->SetIndexToWorldTransformByVtkMatrix(matrix);
vtkSmartPointer<vtkTransformPolyDataFilter> transformFilter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
transformFilter->SetInputData(fiberPolyData);
transformFilter->SetTransform(geometry->GetVtkTransform());
transformFilter->Update();
FiberBundle::Pointer fib = FiberBundle::New(transformFilter->GetOutput());
result.push_back(fib.GetPointer());
}
setlocale(LC_ALL, currLocale.c_str());
MITK_INFO << "Fiber bundle read";
return result;
}
catch(...)
{
throw;
}
return result;
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTckReader.h b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTckReader.h
index 0b20a1e..513a6ca 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTckReader.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTckReader.h
@@ -1,52 +1,52 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkFiberBundleTckReader_h
#define __mitkFiberBundleTckReader_h
#include <mitkCommon.h>
#include <mitkFileReader.h>
#include <mitkFiberBundle.h>
#include <vtkSmartPointer.h>
#include <mitkAbstractFileReader.h>
namespace mitk
{
/** \brief
*/
class FiberBundleTckReader : public AbstractFileReader
{
public:
FiberBundleTckReader();
~FiberBundleTckReader() override{}
FiberBundleTckReader(const FiberBundleTckReader& other);
FiberBundleTckReader * Clone() const override;
using mitk::AbstractFileReader::Read;
std::vector<itk::SmartPointer<BaseData> > Read() override;
private:
us::ServiceRegistration<mitk::IFileReader> m_ServiceReg;
};
} //namespace MITK
#endif // __mitkFiberBundleReader_h
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTrackVisReader.cpp b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTrackVisReader.cpp
index 7a4af2e..1b655a6 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTrackVisReader.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTrackVisReader.cpp
@@ -1,95 +1,95 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkFiberBundleTrackVisReader.h"
#include <itkMetaDataObject.h>
#include <vtkPolyData.h>
#include <vtkDataReader.h>
#include <vtkPolyDataReader.h>
#include <vtkMatrix4x4.h>
#include <vtkPolyLine.h>
#include <vtkCellArray.h>
#include <vtkDataArray.h>
#include <vtkFloatArray.h>
#include <vtkCellData.h>
#include <vtkPointData.h>
#include <itksys/SystemTools.hxx>
#include <tinyxml.h>
#include <vtkCleanPolyData.h>
#include <mitkTrackvis.h>
#include <mitkCustomMimeType.h>
#include "mitkDiffusionIOMimeTypes.h"
mitk::FiberBundleTrackVisReader::FiberBundleTrackVisReader()
: mitk::AbstractFileReader( mitk::DiffusionIOMimeTypes::FIBERBUNDLE_TRK_MIMETYPE_NAME(), "TrackVis Fiber Bundle Reader" )
{
Options defaultOptions;
defaultOptions["Apply index to world transform stored in the TRK header"] = true;
defaultOptions["Print header"] = false;
this->SetDefaultOptions(defaultOptions);
m_ServiceReg = this->RegisterService();
}
mitk::FiberBundleTrackVisReader::FiberBundleTrackVisReader(const FiberBundleTrackVisReader &other)
:mitk::AbstractFileReader(other)
{
}
mitk::FiberBundleTrackVisReader * mitk::FiberBundleTrackVisReader::Clone() const
{
return new FiberBundleTrackVisReader(*this);
}
std::vector<itk::SmartPointer<mitk::BaseData> > mitk::FiberBundleTrackVisReader::Read()
{
std::vector<itk::SmartPointer<mitk::BaseData> > result;
try
{
const std::string& locale = "C";
const std::string& currLocale = setlocale( LC_ALL, nullptr );
setlocale(LC_ALL, locale.c_str());
std::string filename = this->GetInputLocation();
MITK_INFO << "Loading tractogram (TrackVis format): " << itksys::SystemTools::GetFilenameName(filename);
std::string ext = itksys::SystemTools::GetFilenameLastExtension(filename);
ext = itksys::SystemTools::LowerCase(ext);
if (ext==".trk")
{
Options options = this->GetOptions();
bool apply_matrix = us::any_cast<bool>(options["Apply index to world transform stored in the TRK header"]);
bool print_header = us::any_cast<bool>(options["Print header"]);
FiberBundle::Pointer mitk_fib = FiberBundle::New();
TrackVisFiberReader reader;
reader.open(this->GetInputLocation().c_str());
reader.read(mitk_fib.GetPointer(), apply_matrix, print_header);
result.push_back(mitk_fib.GetPointer());
return result;
}
setlocale(LC_ALL, currLocale.c_str());
MITK_INFO << "Fiber bundle read";
}
catch(...)
{
throw;
}
return result;
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTrackVisReader.h b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTrackVisReader.h
index 5cc6a71..eb0bdd6 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTrackVisReader.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTrackVisReader.h
@@ -1,52 +1,52 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkFiberBundleTrackVisReader_h
#define __mitkFiberBundleTrackVisReader_h
#include <mitkCommon.h>
#include <mitkFileReader.h>
#include <mitkFiberBundle.h>
#include <vtkSmartPointer.h>
#include <mitkAbstractFileReader.h>
namespace mitk
{
/** \brief
*/
class FiberBundleTrackVisReader : public AbstractFileReader
{
public:
FiberBundleTrackVisReader();
~FiberBundleTrackVisReader() override{}
FiberBundleTrackVisReader(const FiberBundleTrackVisReader& other);
FiberBundleTrackVisReader * Clone() const override;
using mitk::AbstractFileReader::Read;
std::vector<itk::SmartPointer<BaseData> > Read() override;
private:
us::ServiceRegistration<mitk::IFileReader> m_ServiceReg;
};
} //namespace MITK
#endif // __mitkFiberBundleReader_h
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTrackVisWriter.cpp b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTrackVisWriter.cpp
index 62a2686..bcd6abb 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTrackVisWriter.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTrackVisWriter.cpp
@@ -1,108 +1,108 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkFiberBundleTrackVisWriter.h"
#include <vtkSmartPointer.h>
#include <vtkCleanPolyData.h>
#include <itksys/SystemTools.hxx>
#include <mitkTrackvis.h>
#include <itkSize.h>
#include <vtkFloatArray.h>
#include <vtkCellData.h>
#include <vtkPointData.h>
#include <mitkAbstractFileWriter.h>
#include <mitkCustomMimeType.h>
#include "mitkDiffusionIOMimeTypes.h"
mitk::FiberBundleTrackVisWriter::FiberBundleTrackVisWriter()
: mitk::AbstractFileWriter(mitk::FiberBundle::GetStaticNameOfClass(), mitk::DiffusionIOMimeTypes::FIBERBUNDLE_TRK_MIMETYPE_NAME(), "TrackVis Fiber Bundle Reader")
{
Options defaultOptions;
defaultOptions["Print header"] = false;
this->SetDefaultOptions(defaultOptions);
RegisterService();
}
mitk::FiberBundleTrackVisWriter::FiberBundleTrackVisWriter(const mitk::FiberBundleTrackVisWriter & other)
:mitk::AbstractFileWriter(other)
{}
mitk::FiberBundleTrackVisWriter::~FiberBundleTrackVisWriter()
{}
mitk::FiberBundleTrackVisWriter * mitk::FiberBundleTrackVisWriter::Clone() const
{
return new mitk::FiberBundleTrackVisWriter(*this);
}
void mitk::FiberBundleTrackVisWriter::Write()
{
std::ostream* out;
std::ofstream outStream;
if( this->GetOutputStream() )
{
out = this->GetOutputStream();
}else{
outStream.open( this->GetOutputLocation().c_str() );
out = &outStream;
}
if ( !out->good() )
{
mitkThrow() << "Stream not good.";
}
try
{
const std::string& locale = "C";
const std::string& currLocale = setlocale( LC_ALL, nullptr );
setlocale(LC_ALL, locale.c_str());
std::locale I("C");
out->imbue(I);
std::string filename = this->GetOutputLocation().c_str();
mitk::FiberBundle::ConstPointer input = dynamic_cast<const mitk::FiberBundle*>(this->GetInput());
std::string ext = itksys::SystemTools::GetFilenameLastExtension(this->GetOutputLocation().c_str());
// default extension is .fib
if(ext == "")
{
ext = ".trk";
this->SetOutputLocation(this->GetOutputLocation() + ext);
}
Options options = this->GetOptions();
bool print_header = us::any_cast<bool>(options["Print header"]);
MITK_INFO << "Writing fiber bundle as TRK";
TrackVisFiberReader trk;
trk.create(filename, const_cast<mitk::FiberBundle*>(input.GetPointer()), print_header);
trk.writeHdr();
trk.write(input.GetPointer());
setlocale(LC_ALL, currLocale.c_str());
MITK_INFO << "TrackVis Fiber bundle written to " << filename;
}
catch(...)
{
throw;
}
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTrackVisWriter.h b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTrackVisWriter.h
index 1712765..eb0cfa0 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTrackVisWriter.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleTrackVisWriter.h
@@ -1,118 +1,118 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkFiberBundleTrackVisWriter_h
#define __mitkFiberBundleTrackVisWriter_h
#include <mitkAbstractFileWriter.h>
#include "mitkFiberBundle.h"
#include <vtkPolyDataWriter.h>
namespace mitk
{
/**
* Writes fiber bundles to a file
* @ingroup Process
*/
class FiberBundleTrackVisWriter : public mitk::AbstractFileWriter
{
public:
FiberBundleTrackVisWriter();
FiberBundleTrackVisWriter(const FiberBundleTrackVisWriter & other);
FiberBundleTrackVisWriter * Clone() const override;
~FiberBundleTrackVisWriter() override;
using mitk::AbstractFileWriter::Write;
void Write() override;
static const char* XML_GEOMETRY;
static const char* XML_MATRIX_XX;
static const char* XML_MATRIX_XY;
static const char* XML_MATRIX_XZ;
static const char* XML_MATRIX_YX;
static const char* XML_MATRIX_YY;
static const char* XML_MATRIX_YZ;
static const char* XML_MATRIX_ZX;
static const char* XML_MATRIX_ZY;
static const char* XML_MATRIX_ZZ;
static const char* XML_ORIGIN_X;
static const char* XML_ORIGIN_Y;
static const char* XML_ORIGIN_Z;
static const char* XML_SPACING_X;
static const char* XML_SPACING_Y;
static const char* XML_SPACING_Z;
static const char* XML_SIZE_X;
static const char* XML_SIZE_Y;
static const char* XML_SIZE_Z;
static const char* XML_FIBER_BUNDLE;
static const char* XML_FIBER;
static const char* XML_PARTICLE;
static const char* XML_ID;
static const char* XML_POS_X;
static const char* XML_POS_Y;
static const char* XML_POS_Z;
static const char* VERSION_STRING;
static const char* XML_FIBER_BUNDLE_FILE;
static const char* XML_FILE_VERSION;
static const char* XML_NUM_FIBERS;
static const char* XML_NUM_PARTICLES;
static const char* ASCII_FILE;
static const char* FILE_NAME;
};
} // end of namespace mitk
#endif //__mitkFiberBundleWriter_h
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleVtkReader.cpp b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleVtkReader.cpp
index f5672ed..30a5ace 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleVtkReader.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleVtkReader.cpp
@@ -1,284 +1,284 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkFiberBundleVtkReader.h"
#include <itkMetaDataObject.h>
#include <vtkPolyData.h>
#include <vtkDataReader.h>
#include <vtkPolyDataReader.h>
#include <vtkMatrix4x4.h>
#include <vtkPolyLine.h>
#include <vtkCellArray.h>
#include <vtkDataArray.h>
#include <vtkFloatArray.h>
#include <vtkCellData.h>
#include <vtkPointData.h>
#include <itksys/SystemTools.hxx>
#include <tinyxml.h>
#include <vtkCleanPolyData.h>
#include <mitkTrackvis.h>
#include <mitkCustomMimeType.h>
#include <vtkXMLPolyDataReader.h>
#include <vtkXMLDataReader.h>
#include "mitkDiffusionIOMimeTypes.h"
mitk::FiberBundleVtkReader::FiberBundleVtkReader()
: mitk::AbstractFileReader( mitk::DiffusionIOMimeTypes::FIBERBUNDLE_VTK_MIMETYPE_NAME(), "VTK Fiber Bundle Reader" )
{
m_ServiceReg = this->RegisterService();
}
mitk::FiberBundleVtkReader::FiberBundleVtkReader(const FiberBundleVtkReader &other)
:mitk::AbstractFileReader(other)
{
}
mitk::FiberBundleVtkReader * mitk::FiberBundleVtkReader::Clone() const
{
return new FiberBundleVtkReader(*this);
}
std::vector<itk::SmartPointer<mitk::BaseData> > mitk::FiberBundleVtkReader::Read()
{
std::vector<itk::SmartPointer<mitk::BaseData> > result;
const std::string& locale = "C";
const std::string& currLocale = setlocale( LC_ALL, nullptr );
setlocale(LC_ALL, locale.c_str());
std::string filename = this->GetInputLocation();
std::string ext = itksys::SystemTools::GetFilenameLastExtension(filename);
ext = itksys::SystemTools::LowerCase(ext);
try
{
MITK_INFO << "Loading tractogram (VTK format): " << itksys::SystemTools::GetFilenameName(filename);
vtkSmartPointer<vtkPolyDataReader> reader = vtkSmartPointer<vtkPolyDataReader>::New();
reader->SetFileName( this->GetInputLocation().c_str() );
if (reader->IsFilePolyData())
{
reader->Update();
if ( reader->GetOutput() != nullptr )
{
vtkSmartPointer<vtkPolyData> fiberPolyData = reader->GetOutput();
FiberBundle::Pointer fiberBundle = FiberBundle::New(fiberPolyData);
vtkSmartPointer<vtkFloatArray> weights = vtkFloatArray::SafeDownCast(fiberPolyData->GetCellData()->GetArray("FIBER_WEIGHTS"));
if (weights!=nullptr)
{
// float weight=0;
for (int i=0; i<weights->GetNumberOfValues(); i++)
{
if (weights->GetValue(i)<0.0)
{
MITK_ERROR << "Fiber weight<0 detected! Setting value to 0.";
weights->SetValue(i,0);
}
}
// if (!mitk::Equal(weights->GetValue(i),weight,0.00001))
// {
// MITK_INFO << "Weight: " << weights->GetValue(i);
// weight = weights->GetValue(i);
// }
fiberBundle->SetFiberWeights(weights);
}
vtkSmartPointer<vtkUnsignedCharArray> fiberColors = vtkUnsignedCharArray::SafeDownCast(fiberPolyData->GetPointData()->GetArray("FIBER_COLORS"));
if (fiberColors!=nullptr)
fiberBundle->SetFiberColors(fiberColors);
result.push_back(fiberBundle.GetPointer());
return result;
}
}
else
MITK_INFO << "File is not VTK format.";
}
catch(...)
{
throw;
}
try
{
MITK_INFO << "Trying to load fiber file as VTP format.";
vtkSmartPointer<vtkXMLPolyDataReader> reader = vtkSmartPointer<vtkXMLPolyDataReader>::New();
reader->SetFileName( this->GetInputLocation().c_str() );
if ( reader->CanReadFile(this->GetInputLocation().c_str()) )
{
reader->Update();
if ( reader->GetOutput() != nullptr )
{
vtkSmartPointer<vtkPolyData> fiberPolyData = reader->GetOutput();
FiberBundle::Pointer fiberBundle = FiberBundle::New(fiberPolyData);
vtkSmartPointer<vtkFloatArray> weights = vtkFloatArray::SafeDownCast(fiberPolyData->GetCellData()->GetArray("FIBER_WEIGHTS"));
if (weights!=nullptr)
{
// float weight=0;
// for (int i=0; i<weights->GetSize(); i++)
// if (!mitk::Equal(weights->GetValue(i),weight,0.00001))
// {
// MITK_INFO << "Weight: " << weights->GetValue(i);
// weight = weights->GetValue(i);
// }
fiberBundle->SetFiberWeights(weights);
}
vtkSmartPointer<vtkUnsignedCharArray> fiberColors = vtkUnsignedCharArray::SafeDownCast(fiberPolyData->GetPointData()->GetArray("FIBER_COLORS"));
if (fiberColors!=nullptr)
fiberBundle->SetFiberColors(fiberColors);
result.push_back(fiberBundle.GetPointer());
return result;
}
}
else
MITK_INFO << "File is not VTP format.";
}
catch(...)
{
throw;
}
try
{
MITK_INFO << "Trying to load fiber file as deprecated XML format.";
vtkSmartPointer<vtkPolyData> fiberPolyData = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkCellArray> cellArray = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
TiXmlDocument doc( this->GetInputLocation().c_str() );
if(doc.LoadFile())
{
TiXmlHandle hDoc(&doc);
TiXmlElement* pElem;
TiXmlHandle hRoot(nullptr);
pElem = hDoc.FirstChildElement().Element();
// save this for later
hRoot = TiXmlHandle(pElem);
pElem = hRoot.FirstChildElement("geometry").Element();
// read geometry
mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New();
// read origin
mitk::Point3D origin;
double temp = 0;
pElem->Attribute("origin_x", &temp);
origin[0] = temp;
pElem->Attribute("origin_y", &temp);
origin[1] = temp;
pElem->Attribute("origin_z", &temp);
origin[2] = temp;
geometry->SetOrigin(origin);
// read spacing
ScalarType spacing[3];
pElem->Attribute("spacing_x", &temp);
spacing[0] = temp;
pElem->Attribute("spacing_y", &temp);
spacing[1] = temp;
pElem->Attribute("spacing_z", &temp);
spacing[2] = temp;
geometry->SetSpacing(spacing);
// read transform
vtkMatrix4x4* m = vtkMatrix4x4::New();
pElem->Attribute("xx", &temp);
m->SetElement(0,0,temp);
pElem->Attribute("xy", &temp);
m->SetElement(1,0,temp);
pElem->Attribute("xz", &temp);
m->SetElement(2,0,temp);
pElem->Attribute("yx", &temp);
m->SetElement(0,1,temp);
pElem->Attribute("yy", &temp);
m->SetElement(1,1,temp);
pElem->Attribute("yz", &temp);
m->SetElement(2,1,temp);
pElem->Attribute("zx", &temp);
m->SetElement(0,2,temp);
pElem->Attribute("zy", &temp);
m->SetElement(1,2,temp);
pElem->Attribute("zz", &temp);
m->SetElement(2,2,temp);
m->SetElement(0,3,origin[0]);
m->SetElement(1,3,origin[1]);
m->SetElement(2,3,origin[2]);
m->SetElement(3,3,1);
geometry->SetIndexToWorldTransformByVtkMatrix(m);
// read bounds
float bounds[] = {0, 0, 0, 0, 0, 0};
pElem->Attribute("size_x", &temp);
bounds[1] = temp;
pElem->Attribute("size_y", &temp);
bounds[3] = temp;
pElem->Attribute("size_z", &temp);
bounds[5] = temp;
geometry->SetFloatBounds(bounds);
geometry->SetImageGeometry(true);
pElem = hRoot.FirstChildElement("fiber_bundle").FirstChild().Element();
for( ; pElem ; pElem=pElem->NextSiblingElement())
{
TiXmlElement* pElem2 = pElem->FirstChildElement();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for( ; pElem2; pElem2=pElem2->NextSiblingElement())
{
Point3D point;
pElem2->Attribute("pos_x", &temp);
point[0] = temp;
pElem2->Attribute("pos_y", &temp);
point[1] = temp;
pElem2->Attribute("pos_z", &temp);
point[2] = temp;
geometry->IndexToWorld(point, point);
vtkIdType id = points->InsertNextPoint(point.GetDataPointer());
container->GetPointIds()->InsertNextId(id);
}
cellArray->InsertNextCell(container);
}
fiberPolyData->SetPoints(points);
fiberPolyData->SetLines(cellArray);
vtkSmartPointer<vtkCleanPolyData> cleaner = vtkSmartPointer<vtkCleanPolyData>::New();
cleaner->SetInputData(fiberPolyData);
cleaner->Update();
fiberPolyData = cleaner->GetOutput();
FiberBundle::Pointer image = FiberBundle::New(fiberPolyData);
result.push_back(image.GetPointer());
return result;
}
else
{
MITK_INFO << "File is not deprectaed XML format.";
}
setlocale(LC_ALL, currLocale.c_str());
MITK_INFO << "Fiber bundle read";
}
catch(...)
{
throw;
}
throw "Selected file is no vtk readable fiber format (binary or ascii vtk or vtp file).";
return result;
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleVtkReader.h b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleVtkReader.h
index c2b7afc..ac2d9be 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleVtkReader.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleVtkReader.h
@@ -1,52 +1,52 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkFiberBundleVtkReader_h
#define __mitkFiberBundleVtkReader_h
#include <mitkCommon.h>
#include <mitkFileReader.h>
#include <mitkFiberBundle.h>
#include <vtkSmartPointer.h>
#include <mitkAbstractFileReader.h>
namespace mitk
{
/** \brief
*/
class FiberBundleVtkReader : public AbstractFileReader
{
public:
FiberBundleVtkReader();
~FiberBundleVtkReader() override{}
FiberBundleVtkReader(const FiberBundleVtkReader& other);
FiberBundleVtkReader * Clone() const override;
using mitk::AbstractFileReader::Read;
std::vector<itk::SmartPointer<BaseData> > Read() override;
private:
us::ServiceRegistration<mitk::IFileReader> m_ServiceReg;
};
} //namespace MITK
#endif // __mitkFiberBundleReader_h
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleVtkWriter.cpp b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleVtkWriter.cpp
index 287140b..c7654c4 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleVtkWriter.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleVtkWriter.cpp
@@ -1,171 +1,171 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkFiberBundleVtkWriter.h"
#include <vtkSmartPointer.h>
#include <vtkCleanPolyData.h>
#include <itksys/SystemTools.hxx>
#include <mitkTrackvis.h>
#include <itkSize.h>
#include <vtkFloatArray.h>
#include <vtkCellData.h>
#include <vtkPointData.h>
#include <mitkAbstractFileWriter.h>
#include <mitkCustomMimeType.h>
#include <vtkXMLPolyDataWriter.h>
#include "mitkDiffusionIOMimeTypes.h"
mitk::FiberBundleVtkWriter::FiberBundleVtkWriter()
: mitk::AbstractFileWriter(mitk::FiberBundle::GetStaticNameOfClass(), mitk::DiffusionIOMimeTypes::FIBERBUNDLE_VTK_MIMETYPE_NAME(), "VTK Fiber Bundle Writer")
{
Options defaultOptions;
defaultOptions["Save as binary file"] = true;
defaultOptions["Save as xml file (vtp style)"] = false;
defaultOptions["Save color information"] = true;
defaultOptions["Save fiber weights"] = true;
this->SetDefaultOptions(defaultOptions);
RegisterService();
}
mitk::FiberBundleVtkWriter::FiberBundleVtkWriter(const mitk::FiberBundleVtkWriter & other)
:mitk::AbstractFileWriter(other)
{}
mitk::FiberBundleVtkWriter::~FiberBundleVtkWriter()
{}
mitk::FiberBundleVtkWriter * mitk::FiberBundleVtkWriter::Clone() const
{
return new mitk::FiberBundleVtkWriter(*this);
}
void mitk::FiberBundleVtkWriter::Write()
{
std::ostream* out;
std::ofstream outStream;
if( this->GetOutputStream() )
{
out = this->GetOutputStream();
}else{
outStream.open( this->GetOutputLocation().c_str() );
out = &outStream;
}
if ( !out->good() )
{
mitkThrow() << "Stream not good.";
}
try
{
const std::string& locale = "C";
const std::string& currLocale = setlocale( LC_ALL, nullptr );
setlocale(LC_ALL, locale.c_str());
std::locale I("C");
out->imbue(I);
std::string filename = this->GetOutputLocation().c_str();
mitk::FiberBundle::ConstPointer input = dynamic_cast<const mitk::FiberBundle*>(this->GetInput());
std::string ext = itksys::SystemTools::GetFilenameLastExtension(this->GetOutputLocation().c_str());
Options options = this->GetOptions();
vtkSmartPointer<vtkFloatArray> weights = nullptr;
vtkSmartPointer<vtkUnsignedCharArray> fiberColors = nullptr;
vtkSmartPointer<vtkPolyData> fibPoly = input->GetFiberPolyData();
if (us::any_cast<bool>(options["Save fiber weights"]))
{
MITK_INFO << "Adding fiber weight information";
fibPoly->GetCellData()->AddArray(input->GetFiberWeights());
}
else if (fibPoly->GetCellData()->HasArray("FIBER_WEIGHTS"))
{
weights = input->GetFiberWeights();
fibPoly->GetCellData()->RemoveArray("FIBER_WEIGHTS");
}
if (us::any_cast<bool>(options["Save color information"]))
{
MITK_INFO << "Adding color information";
fibPoly->GetPointData()->AddArray(input->GetFiberColors());
}
else if (fibPoly->GetPointData()->HasArray("FIBER_COLORS"))
{
fiberColors = input->GetFiberColors();
fibPoly->GetPointData()->RemoveArray("FIBER_COLORS");
}
// default extension is .fib
if(ext == "")
{
ext = ".fib";
this->SetOutputLocation(this->GetOutputLocation() + ext);
}
if (us::any_cast<bool>(options["Save as xml file (vtp style)"]))
{
vtkSmartPointer<vtkXMLPolyDataWriter> writer = vtkSmartPointer<vtkXMLPolyDataWriter>::New();
writer->SetInputData(fibPoly);
writer->SetFileName(filename.c_str());
if (us::any_cast<bool>(options["Save as binary file"]))
{
MITK_INFO << "Writing fiber bundle as vtk binary file";
writer->SetDataModeToBinary();
}
else
{
MITK_INFO << "Writing fiber bundle as vtk ascii file";
writer->SetDataModeToAscii();
}
writer->Write();
}
else
{
vtkSmartPointer<vtkPolyDataWriter> writer = vtkSmartPointer<vtkPolyDataWriter>::New();
writer->SetInputData(fibPoly);
writer->SetFileName(filename.c_str());
if (us::any_cast<bool>(options["Save as binary file"]))
{
MITK_INFO << "Writing fiber bundle as vtk binary file";
writer->SetFileTypeToBinary();
}
else
{
MITK_INFO << "Writing fiber bundle as vtk ascii file";
writer->SetFileTypeToASCII();
}
writer->Write();
}
// restore arrays
if ( weights!=nullptr )
fibPoly->GetPointData()->AddArray(weights);
if (fiberColors != nullptr)
fibPoly->GetPointData()->AddArray(fiberColors);
setlocale(LC_ALL, currLocale.c_str());
MITK_INFO << "VTK Fiber bundle written to " << filename;
}
catch(...)
{
throw;
}
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleVtkWriter.h b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleVtkWriter.h
index a761f57..7ed450a 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleVtkWriter.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkFiberBundleVtkWriter.h
@@ -1,118 +1,118 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkFiberBundleVtkWriter_h
#define __mitkFiberBundleVtkWriter_h
#include <mitkAbstractFileWriter.h>
#include "mitkFiberBundle.h"
#include <vtkPolyDataWriter.h>
namespace mitk
{
/**
* Writes fiber bundles to a file
* @ingroup Process
*/
class FiberBundleVtkWriter : public mitk::AbstractFileWriter
{
public:
FiberBundleVtkWriter();
FiberBundleVtkWriter(const FiberBundleVtkWriter & other);
FiberBundleVtkWriter * Clone() const override;
~FiberBundleVtkWriter() override;
using mitk::AbstractFileWriter::Write;
void Write() override;
static const char* XML_GEOMETRY;
static const char* XML_MATRIX_XX;
static const char* XML_MATRIX_XY;
static const char* XML_MATRIX_XZ;
static const char* XML_MATRIX_YX;
static const char* XML_MATRIX_YY;
static const char* XML_MATRIX_YZ;
static const char* XML_MATRIX_ZX;
static const char* XML_MATRIX_ZY;
static const char* XML_MATRIX_ZZ;
static const char* XML_ORIGIN_X;
static const char* XML_ORIGIN_Y;
static const char* XML_ORIGIN_Z;
static const char* XML_SPACING_X;
static const char* XML_SPACING_Y;
static const char* XML_SPACING_Z;
static const char* XML_SIZE_X;
static const char* XML_SIZE_Y;
static const char* XML_SIZE_Z;
static const char* XML_FIBER_BUNDLE;
static const char* XML_FIBER;
static const char* XML_PARTICLE;
static const char* XML_ID;
static const char* XML_POS_X;
static const char* XML_POS_Y;
static const char* XML_POS_Z;
static const char* VERSION_STRING;
static const char* XML_FIBER_BUNDLE_FILE;
static const char* XML_FILE_VERSION;
static const char* XML_NUM_FIBERS;
static const char* XML_NUM_PARTICLES;
static const char* ASCII_FILE;
static const char* FILE_NAME;
};
} // end of namespace mitk
#endif //__mitkFiberBundleWriter_h
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkNrrdOdfImageReader.cpp b/Modules/DiffusionIO/ReaderWriter/mitkNrrdOdfImageReader.cpp
index 94c9129..2c45539 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkNrrdOdfImageReader.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkNrrdOdfImageReader.cpp
@@ -1,118 +1,118 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkNrrdOdfImageReader.h"
#include <mitkCustomMimeType.h>
#include "mitkDiffusionIOMimeTypes.h"
#include "itkImageFileReader.h"
#include "itkImageRegionIterator.h"
#include "itkMetaDataObject.h"
#include "itkNrrdImageIO.h"
#include "mitkITKImageImport.h"
#include "mitkImageDataItem.h"
#include <mitkLocaleSwitch.h>
namespace mitk
{
NrrdOdfImageReader::NrrdOdfImageReader(const NrrdOdfImageReader& other)
: mitk::AbstractFileReader(other)
{
}
NrrdOdfImageReader::NrrdOdfImageReader()
: mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::ODF_MIMETYPE() ), mitk::DiffusionIOMimeTypes::ODF_MIMETYPE_DESCRIPTION() )
{
m_ServiceReg = this->RegisterService();
}
NrrdOdfImageReader::~NrrdOdfImageReader()
{
}
std::vector<itk::SmartPointer<BaseData> > NrrdOdfImageReader::Read()
{
std::vector<itk::SmartPointer<mitk::BaseData> > result;
std::string location = GetInputLocation();
if ( location == "")
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, the filename of the ODF image to be read is empty!");
}
else
{
try
{
mitk::LocaleSwitch localeSwitch("C");
typedef itk::VectorImage<float,3> ImageType;
itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New();
typedef itk::ImageFileReader<ImageType> FileReaderType;
FileReaderType::Pointer reader = FileReaderType::New();
reader->SetImageIO(io);
reader->SetFileName(location);
reader->Update();
ImageType::Pointer img = reader->GetOutput();
typedef itk::Image<itk::Vector<float,ODF_SAMPLING_SIZE>,3> VecImgType;
VecImgType::Pointer vecImg = VecImgType::New();
vecImg->SetSpacing( img->GetSpacing() ); // Set the image spacing
vecImg->SetOrigin( img->GetOrigin() ); // Set the image origin
vecImg->SetDirection( img->GetDirection() ); // Set the image direction
vecImg->SetLargestPossibleRegion( img->GetLargestPossibleRegion());
vecImg->SetBufferedRegion( img->GetLargestPossibleRegion() );
vecImg->Allocate();
itk::ImageRegionIterator<VecImgType> ot (vecImg, vecImg->GetLargestPossibleRegion() );
ot.GoToBegin();
itk::ImageRegionIterator<ImageType> it (img, img->GetLargestPossibleRegion() );
typedef ImageType::PixelType VarPixType;
typedef VecImgType::PixelType FixPixType;
for (it.GoToBegin(); !it.IsAtEnd(); ++it)
{
VarPixType vec = it.Get();
FixPixType fixVec(vec.GetDataPointer());
ot.Set(fixVec);
++ot;
}
OutputType::Pointer resultImage = OutputType::New();
resultImage->InitializeByItk( vecImg.GetPointer() );
resultImage->SetVolume( vecImg->GetBufferPointer() );
result.push_back( resultImage.GetPointer() );
}
catch(std::exception& e)
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, e.what());
}
catch(...)
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, an error occurred while reading the requested vessel tree file!");
}
}
return result;
}
} //namespace MITK
mitk::NrrdOdfImageReader* mitk::NrrdOdfImageReader::Clone() const
{
return new NrrdOdfImageReader(*this);
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkNrrdOdfImageReader.h b/Modules/DiffusionIO/ReaderWriter/mitkNrrdOdfImageReader.h
index a596f6f..c1be9d6 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkNrrdOdfImageReader.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkNrrdOdfImageReader.h
@@ -1,60 +1,60 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkNrrdOdfImageReader_h
#define __mitkNrrdOdfImageReader_h
#include "mitkCommon.h"
#include "itkVectorContainer.h"
#include "vnl/vnl_vector_fixed.h"
#include "mitkOdfImage.h"
#include "itkVectorImage.h"
#include <mitkAbstractFileReader.h>
#include <mitkBaseData.h>
#include <mitkMimeType.h>
namespace mitk
{
/** \brief
*/
class NrrdOdfImageReader : public mitk::AbstractFileReader
{
public:
typedef mitk::OdfImage OutputType;
NrrdOdfImageReader(const NrrdOdfImageReader& other);
NrrdOdfImageReader();
~NrrdOdfImageReader() override;
using AbstractFileReader::Read;
std::vector<itk::SmartPointer<BaseData> > Read() override;
protected:
private:
private:
NrrdOdfImageReader* Clone() const override;
us::ServiceRegistration<mitk::IFileReader> m_ServiceReg;
};
} //namespace MITK
#endif // __mitkNrrdOdfImageReader_h
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkNrrdOdfImageWriter.cpp b/Modules/DiffusionIO/ReaderWriter/mitkNrrdOdfImageWriter.cpp
index 3135eb8..ab1a79c 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkNrrdOdfImageWriter.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkNrrdOdfImageWriter.cpp
@@ -1,129 +1,129 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkNrrdOdfImageWriter.h"
#include "itkMetaDataDictionary.h"
#include "itkMetaDataObject.h"
#include "itkNrrdImageIO.h"
#include "itkImageFileWriter.h"
#include "mitkImageCast.h"
#include "mitkIOMimeTypes.h"
#include "mitkDiffusionIOMimeTypes.h"
#include <mitkLocaleSwitch.h>
mitk::NrrdOdfImageWriter::NrrdOdfImageWriter()
: AbstractFileWriter(mitk::OdfImage::GetStaticNameOfClass(), CustomMimeType( mitk::DiffusionIOMimeTypes::ODF_MIMETYPE() ), mitk::DiffusionIOMimeTypes::ODF_MIMETYPE_DESCRIPTION())
{
RegisterService();
}
mitk::NrrdOdfImageWriter::NrrdOdfImageWriter(const mitk::NrrdOdfImageWriter& other)
: AbstractFileWriter(other)
{
}
mitk::NrrdOdfImageWriter::~NrrdOdfImageWriter()
{}
void mitk::NrrdOdfImageWriter::Write()
{
InputType::ConstPointer input = dynamic_cast<const InputType*>(this->GetInput());
if (input.IsNull())
{
MITK_ERROR <<"Sorry, input to NrrdOdfImageWriter is nullptr!";
return;
}
if ( this->GetOutputLocation().empty() )
{
MITK_ERROR << "Sorry, filename has not been set!";
return ;
}
mitk::LocaleSwitch localeSwitch("C");
itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New();
io->SetFileType( itk::ImageIOBase::Binary );
io->UseCompressionOn();
typedef itk::VectorImage<float, 3> VecImgType;
typedef itk::Image<itk::Vector<float,ODF_SAMPLING_SIZE>,3> ImageType;
typedef itk::ImageFileWriter<VecImgType> WriterType;
WriterType::Pointer nrrdWriter = WriterType::New();
ImageType::Pointer outimage = ImageType::New();
CastToItkImage(input, outimage);
VecImgType::Pointer vecImg = VecImgType::New();
vecImg->SetSpacing( outimage->GetSpacing() ); // Set the image spacing
vecImg->SetOrigin( outimage->GetOrigin() ); // Set the image origin
vecImg->SetDirection( outimage->GetDirection() ); // Set the image direction
vecImg->SetLargestPossibleRegion( outimage->GetLargestPossibleRegion());
vecImg->SetBufferedRegion( outimage->GetLargestPossibleRegion() );
vecImg->SetVectorLength(ODF_SAMPLING_SIZE);
vecImg->Allocate();
itk::ImageRegionIterator<VecImgType> ot (vecImg, vecImg->GetLargestPossibleRegion() );
ot.GoToBegin();
itk::ImageRegionIterator<ImageType> it (outimage, outimage->GetLargestPossibleRegion() );
typedef ImageType::PixelType VecPixType;
typedef VecImgType::PixelType VarVecType;
for (it.GoToBegin(); !it.IsAtEnd(); ++it)
{
VecPixType vec = it.Get();
VarVecType varVec(vec.GetVnlVector().data_block(), ODF_SAMPLING_SIZE);
ot.Set(varVec);
++ot;
}
nrrdWriter->SetInput( vecImg );
nrrdWriter->SetImageIO(io);
nrrdWriter->SetFileName(this->GetOutputLocation().c_str());
nrrdWriter->UseCompressionOn();
try
{
nrrdWriter->Update();
}
catch (const itk::ExceptionObject& e)
{
MITK_INFO << e.what();
}
}
mitk::NrrdOdfImageWriter* mitk::NrrdOdfImageWriter::Clone() const
{
return new NrrdOdfImageWriter(*this);
}
mitk::IFileWriter::ConfidenceLevel mitk::NrrdOdfImageWriter::GetConfidenceLevel() const
{
InputType::ConstPointer input = dynamic_cast<const InputType*>(this->GetInput());
if (input.IsNull() )
{
return Unsupported;
}
else
{
return Supported;
}
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkNrrdOdfImageWriter.h b/Modules/DiffusionIO/ReaderWriter/mitkNrrdOdfImageWriter.h
index 7788ded..16e00d1 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkNrrdOdfImageWriter.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkNrrdOdfImageWriter.h
@@ -1,54 +1,54 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_NRRDODF_WRITER__H_
#define _MITK_NRRDODF_WRITER__H_
#include <mitkAbstractFileWriter.h>
#include <mitkOdfImage.h>
namespace mitk
{
/**
* Writes diffusion volumes to a file
* @ingroup Process
*/
class NrrdOdfImageWriter : public mitk::AbstractFileWriter
{
public:
typedef mitk::OdfImage InputType;
NrrdOdfImageWriter();
~NrrdOdfImageWriter() override;
using AbstractFileWriter::Write;
void Write() override;
ConfidenceLevel GetConfidenceLevel() const override;
protected:
NrrdOdfImageWriter(const NrrdOdfImageWriter& other);
mitk::NrrdOdfImageWriter* Clone() const override;
};
} // end of namespace mitk
#endif //_MITK_NRRDODF_WRITER__H_
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkNrrdTensorImageReader.cpp b/Modules/DiffusionIO/ReaderWriter/mitkNrrdTensorImageReader.cpp
index e1478d9..dba88f9 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkNrrdTensorImageReader.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkNrrdTensorImageReader.cpp
@@ -1,428 +1,428 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkNrrdTensorImageReader.h"
#include <mitkCustomMimeType.h>
#include "mitkDiffusionIOMimeTypes.h"
#include "itkImageFileReader.h"
#include "itkImageRegionIterator.h"
#include "itkMetaDataObject.h"
#include "itkNrrdImageIO.h"
#include <itkNiftiImageIO.h>
#include "mitkITKImageImport.h"
#include "mitkImageDataItem.h"
#include <mitkLocaleSwitch.h>
#include <mitkIOUtil.h>
#include <mitkLexicalCast.h>
namespace mitk
{
NrrdTensorImageReader::NrrdTensorImageReader(const NrrdTensorImageReader& other)
: mitk::AbstractFileReader(other)
{
}
NrrdTensorImageReader::NrrdTensorImageReader()
: mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::DTI_MIMETYPE() ), mitk::DiffusionIOMimeTypes::DTI_MIMETYPE_DESCRIPTION() )
{
m_ServiceReg = this->RegisterService();
}
NrrdTensorImageReader::~NrrdTensorImageReader()
{
}
std::vector<itk::SmartPointer<BaseData> > NrrdTensorImageReader::Read()
{
std::vector<itk::SmartPointer<mitk::BaseData> > result;
std::string location = GetInputLocation();
if ( location == "")
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, the filename is empty!");
}
else
{
try
{
mitk::LocaleSwitch localeSwitch("C");
try
{
std::string fname3 = mitk::IOUtil::GetTempPath()+"/temp_dti.nii.gz";
int c = 0;
while( itksys::SystemTools::FileExists(fname3) )
{
fname3 = mitk::IOUtil::GetTempPath()+"/temp_dti_" + boost::lexical_cast<std::string>(c) + ".nii.gz";
++c;
}
itksys::SystemTools::CopyAFile(location.c_str(), fname3.c_str());
typedef itk::VectorImage<float,3> ImageType;
itk::NiftiImageIO::Pointer io = itk::NiftiImageIO::New();
typedef itk::ImageFileReader<ImageType> FileReaderType;
FileReaderType::Pointer reader = FileReaderType::New();
reader->SetImageIO(io);
reader->SetFileName(fname3);
reader->Update();
ImageType::Pointer img = reader->GetOutput();
TensorImage::ItkTensorImageType::Pointer vecImg = TensorImage::ItkTensorImageType::New();
vecImg->SetSpacing( img->GetSpacing() ); // Set the image spacing
vecImg->SetOrigin( img->GetOrigin() ); // Set the image origin
vecImg->SetDirection( img->GetDirection() ); // Set the image direction
vecImg->SetRegions( img->GetLargestPossibleRegion());
vecImg->Allocate();
itk::ImageRegionIterator<TensorImage::ItkTensorImageType> ot (vecImg, vecImg->GetLargestPossibleRegion() );
ot.GoToBegin();
itk::ImageRegionIterator<ImageType> it (img, img->GetLargestPossibleRegion() );
it.GoToBegin();
typedef ImageType::PixelType VarPixType;
typedef TensorImage::PixelType FixPixType;
int numComponents = img->GetNumberOfComponentsPerPixel();
if (numComponents==6)
{
MITK_INFO << "Trying to load dti as 6-comp nifti ...";
while (!it.IsAtEnd())
{
VarPixType vec = it.Get();
FixPixType fixVec(vec.GetDataPointer());
TensorImage::PixelType tensor;
tensor.SetElement(0, vec.GetElement(0));
tensor.SetElement(1, vec.GetElement(1));
tensor.SetElement(2, vec.GetElement(2));
tensor.SetElement(3, vec.GetElement(3));
tensor.SetElement(4, vec.GetElement(4));
tensor.SetElement(5, vec.GetElement(5));
fixVec = tensor;
ot.Set(fixVec);
++ot;
++it;
}
}
else if(numComponents==9)
{
MITK_INFO << "Trying to load dti as 9-comp nifti ...";
while (!it.IsAtEnd())
{
VarPixType vec = it.Get();
TensorImage::PixelType tensor;
tensor.SetElement(0, vec.GetElement(0));
tensor.SetElement(1, vec.GetElement(1));
tensor.SetElement(2, vec.GetElement(2));
tensor.SetElement(3, vec.GetElement(4));
tensor.SetElement(4, vec.GetElement(5));
tensor.SetElement(5, vec.GetElement(8));
FixPixType fixVec(tensor);
ot.Set(fixVec);
++ot;
++it;
}
}
else if (numComponents==1)
{
MITK_INFO << "Trying to load dti as 4D nifti ...";
typedef itk::Image<float,4> ImageType;
typedef itk::ImageFileReader<ImageType> FileReaderType;
FileReaderType::Pointer reader = FileReaderType::New();
reader->SetImageIO(io);
reader->SetFileName(fname3);
reader->Update();
ImageType::Pointer img = reader->GetOutput();
itk::Size<4> size = img->GetLargestPossibleRegion().GetSize();
while (!ot.IsAtEnd())
{
TensorImage::PixelType tensor;
ImageType::IndexType idx;
idx[0] = ot.GetIndex()[0]; idx[1] = ot.GetIndex()[1]; idx[2] = ot.GetIndex()[2];
if (size[3]==6)
{
for (unsigned int te=0; te<size[3]; te++)
{
idx[3] = te;
tensor.SetElement(te, img->GetPixel(idx));
}
}
else if (size[3]==9)
{
idx[3] = 0;
tensor.SetElement(0, img->GetPixel(idx));
idx[3] = 1;
tensor.SetElement(1, img->GetPixel(idx));
idx[3] = 2;
tensor.SetElement(2, img->GetPixel(idx));
idx[3] = 4;
tensor.SetElement(3, img->GetPixel(idx));
idx[3] = 5;
tensor.SetElement(4, img->GetPixel(idx));
idx[3] = 8;
tensor.SetElement(5, img->GetPixel(idx));
}
else
throw itk::ImageFileReaderException(__FILE__, __LINE__, "Unknown number of components for DTI file. Should be 6 or 9!");
FixPixType fixVec(tensor);
ot.Set(fixVec);
++ot;
}
}
OutputType::Pointer resultImage = OutputType::New();
resultImage->InitializeByItk( vecImg.GetPointer() );
resultImage->SetVolume( vecImg->GetBufferPointer() );
result.push_back( resultImage.GetPointer() );
}
catch(...)
{
MITK_INFO << "Trying to load dti as nrrd ...";
typedef itk::VectorImage<float,3> ImageType;
itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New();
typedef itk::ImageFileReader<ImageType> FileReaderType;
FileReaderType::Pointer reader = FileReaderType::New();
reader->SetImageIO(io);
reader->SetFileName(location);
reader->Update();
ImageType::Pointer img = reader->GetOutput();
TensorImage::ItkTensorImageType::Pointer vecImg = TensorImage::ItkTensorImageType::New();
vecImg->SetSpacing( img->GetSpacing() ); // Set the image spacing
vecImg->SetOrigin( img->GetOrigin() ); // Set the image origin
vecImg->SetDirection( img->GetDirection() ); // Set the image direction
vecImg->SetRegions( img->GetLargestPossibleRegion());
vecImg->Allocate();
itk::ImageRegionIterator<TensorImage::ItkTensorImageType> ot (vecImg, vecImg->GetLargestPossibleRegion() );
ot.GoToBegin();
itk::ImageRegionIterator<ImageType> it (img, img->GetLargestPossibleRegion() );
it.GoToBegin();
typedef ImageType::PixelType VarPixType;
typedef TensorImage::PixelType FixPixType;
int numComponents = img->GetNumberOfComponentsPerPixel();
itk::MetaDataDictionary imgMetaDictionary = img->GetMetaDataDictionary();
std::vector<std::string> imgMetaKeys = imgMetaDictionary.GetKeys();
std::vector<std::string>::const_iterator itKey = imgMetaKeys.begin();
std::string metaString;
bool readFrame = false;
double xx, xy, xz, yx, yy, yz, zx, zy, zz;
MeasurementFrameType measFrame;
measFrame.SetIdentity();
MeasurementFrameType measFrameTransp;
measFrameTransp.SetIdentity();
for (; itKey != imgMetaKeys.end(); itKey ++)
{
itk::ExposeMetaData<std::string> (imgMetaDictionary, *itKey, metaString);
if (itKey->find("measurement frame") != std::string::npos)
{
sscanf(metaString.c_str(), " ( %lf , %lf , %lf ) ( %lf , %lf , %lf ) ( %lf , %lf , %lf ) \n", &xx, &xy, &xz, &yx, &yy, &yz, &zx, &zy, &zz);
if (xx>10e-10 || xy>10e-10 || xz>10e-10 ||
yx>10e-10 || yy>10e-10 || yz>10e-10 ||
zx>10e-10 || zy>10e-10 || zz>10e-10 )
{
readFrame = true;
measFrame(0,0) = xx;
measFrame(0,1) = xy;
measFrame(0,2) = xz;
measFrame(1,0) = yx;
measFrame(1,1) = yy;
measFrame(1,2) = yz;
measFrame(2,0) = zx;
measFrame(2,1) = zy;
measFrame(2,2) = zz;
measFrameTransp = measFrame.GetTranspose();
}
}
}
if (numComponents==6)
{
while (!it.IsAtEnd())
{
// T'=RTR'
VarPixType vec = it.Get();
FixPixType fixVec(vec.GetDataPointer());
if(readFrame)
{
TensorImage::PixelType tensor;
tensor.SetElement(0, vec.GetElement(0));
tensor.SetElement(1, vec.GetElement(1));
tensor.SetElement(2, vec.GetElement(2));
tensor.SetElement(3, vec.GetElement(3));
tensor.SetElement(4, vec.GetElement(4));
tensor.SetElement(5, vec.GetElement(5));
tensor = ConvertMatrixTypeToFixedArrayType(tensor.PreMultiply(measFrame));
tensor = ConvertMatrixTypeToFixedArrayType(tensor.PostMultiply(measFrameTransp));
fixVec = tensor;
}
ot.Set(fixVec);
++ot;
++it;
}
}
else if(numComponents==9)
{
while (!it.IsAtEnd())
{
VarPixType vec = it.Get();
TensorImage::PixelType tensor;
tensor.SetElement(0, vec.GetElement(0));
tensor.SetElement(1, vec.GetElement(1));
tensor.SetElement(2, vec.GetElement(2));
tensor.SetElement(3, vec.GetElement(4));
tensor.SetElement(4, vec.GetElement(5));
tensor.SetElement(5, vec.GetElement(8));
if(readFrame)
{
tensor = ConvertMatrixTypeToFixedArrayType(tensor.PreMultiply(measFrame));
tensor = ConvertMatrixTypeToFixedArrayType(tensor.PostMultiply(measFrameTransp));
}
FixPixType fixVec(tensor);
ot.Set(fixVec);
++ot;
++it;
}
}
else if (numComponents==1)
{
typedef itk::Image<float,4> ImageType;
itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New();
typedef itk::ImageFileReader<ImageType> FileReaderType;
FileReaderType::Pointer reader = FileReaderType::New();
reader->SetImageIO(io);
reader->SetFileName(location);
reader->Update();
ImageType::Pointer img = reader->GetOutput();
itk::Size<4> size = img->GetLargestPossibleRegion().GetSize();
while (!ot.IsAtEnd())
{
TensorImage::PixelType tensor;
ImageType::IndexType idx;
idx[0] = ot.GetIndex()[0]; idx[1] = ot.GetIndex()[1]; idx[2] = ot.GetIndex()[2];
if (size[3]==6)
{
for (unsigned int te=0; te<size[3]; te++)
{
idx[3] = te;
tensor.SetElement(te, img->GetPixel(idx));
}
}
else if (size[3]==9)
{
idx[3] = 0;
tensor.SetElement(0, img->GetPixel(idx));
idx[3] = 1;
tensor.SetElement(1, img->GetPixel(idx));
idx[3] = 2;
tensor.SetElement(2, img->GetPixel(idx));
idx[3] = 4;
tensor.SetElement(3, img->GetPixel(idx));
idx[3] = 5;
tensor.SetElement(4, img->GetPixel(idx));
idx[3] = 8;
tensor.SetElement(5, img->GetPixel(idx));
}
else
throw itk::ImageFileReaderException(__FILE__, __LINE__, "Unknown number of komponents for DTI file. Should be 6 or 9!");
if(readFrame)
{
tensor = ConvertMatrixTypeToFixedArrayType(tensor.PreMultiply(measFrame));
tensor = ConvertMatrixTypeToFixedArrayType(tensor.PostMultiply(measFrameTransp));
}
FixPixType fixVec(tensor);
ot.Set(fixVec);
++ot;
}
}
else
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, "Image has wrong number of pixel components!");
}
OutputType::Pointer resultImage = OutputType::New();
resultImage->InitializeByItk( vecImg.GetPointer() );
resultImage->SetVolume( vecImg->GetBufferPointer() );
result.push_back( resultImage.GetPointer() );
}
}
catch(std::exception& e)
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, e.what());
}
catch(...)
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, an error occurred while reading the requested DTI file!");
}
}
return result;
}
TensorImage::PixelType NrrdTensorImageReader
::ConvertMatrixTypeToFixedArrayType(const TensorImage::PixelType::Superclass::MatrixType & matrix)
{
/* | 0 1 2 |
* | X 3 4 |
* | X X 5 |
*/
TensorImage::PixelType arr;
arr.SetElement(0,matrix(0,0));
arr.SetElement(1,matrix(0,1));
arr.SetElement(2,matrix(0,2));
arr.SetElement(3,matrix(1,3));
arr.SetElement(4,matrix(1,4));
arr.SetElement(5,matrix(2,5));
return arr;
}
} //namespace MITK
mitk::NrrdTensorImageReader* mitk::NrrdTensorImageReader::Clone() const
{
return new NrrdTensorImageReader(*this);
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkNrrdTensorImageReader.h b/Modules/DiffusionIO/ReaderWriter/mitkNrrdTensorImageReader.h
index 770a804..be5eefd 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkNrrdTensorImageReader.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkNrrdTensorImageReader.h
@@ -1,63 +1,63 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkNrrdTensorImageReader_h
#define __mitkNrrdTensorImageReader_h
#include "mitkCommon.h"
#include "itkVectorContainer.h"
#include "vnl/vnl_vector_fixed.h"
#include "mitkTensorImage.h"
#include "itkVectorImage.h"
#include "itkDiffusionTensor3D.h"
#include <mitkAbstractFileReader.h>
#include <mitkBaseData.h>
#include <mitkMimeType.h>
namespace mitk
{
/** \brief
*/
class NrrdTensorImageReader : public mitk::AbstractFileReader
{
public:
typedef mitk::TensorImage OutputType;
typedef itk::Matrix< float, 3, 3 > MeasurementFrameType;
NrrdTensorImageReader(const NrrdTensorImageReader& other);
NrrdTensorImageReader();
~NrrdTensorImageReader() override;
using AbstractFileReader::Read;
std::vector<itk::SmartPointer<BaseData> > Read() override;
protected:
private:
NrrdTensorImageReader* Clone() const override;
us::ServiceRegistration<mitk::IFileReader> m_ServiceReg;
TensorImage::PixelType ConvertMatrixTypeToFixedArrayType(const TensorImage::PixelType::Superclass::MatrixType & matrix);
};
} //namespace MITK
#endif // __mitkNrrdTensorImageReader_h
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkNrrdTensorImageWriter.cpp b/Modules/DiffusionIO/ReaderWriter/mitkNrrdTensorImageWriter.cpp
index 0b35ea2..5324db5 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkNrrdTensorImageWriter.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkNrrdTensorImageWriter.cpp
@@ -1,100 +1,100 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkNrrdTensorImageWriter.h"
#include "itkMetaDataDictionary.h"
#include "itkMetaDataObject.h"
#include "itkNrrdImageIO.h"
#include "itkImageFileWriter.h"
#include "itkDiffusionTensor3D.h"
#include "mitkImageCast.h"
#include "mitkDiffusionIOMimeTypes.h"
#include <mitkLocaleSwitch.h>
mitk::NrrdTensorImageWriter::NrrdTensorImageWriter()
: AbstractFileWriter(mitk::TensorImage::GetStaticNameOfClass(), CustomMimeType( mitk::DiffusionIOMimeTypes::DTI_MIMETYPE() ), mitk::DiffusionIOMimeTypes::DTI_MIMETYPE_DESCRIPTION() )
{
RegisterService();
}
mitk::NrrdTensorImageWriter::NrrdTensorImageWriter(const mitk::NrrdTensorImageWriter& other)
: AbstractFileWriter(other)
{
}
mitk::NrrdTensorImageWriter::~NrrdTensorImageWriter()
{}
void mitk::NrrdTensorImageWriter::Write()
{
InputType::ConstPointer input = dynamic_cast<const InputType*>(this->GetInput());
if (input.IsNull() )
{
MITK_ERROR <<"Sorry, input to NrrdTensorImageWriter is nullptr!";
return;
}
if ( this->GetOutputLocation().empty() )
{
MITK_ERROR << "Sorry, filename has not been set!" ;
return ;
}
mitk::LocaleSwitch localeSwitch("C");
itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New();
io->SetFileType( itk::ImageIOBase::Binary );
io->UseCompressionOn();
typedef itk::ImageFileWriter<TensorImage::ItkTensorImageType> WriterType;
WriterType::Pointer nrrdWriter = WriterType::New();
TensorImage::ItkTensorImageType::Pointer outimage = TensorImage::ItkTensorImageType::New();
CastToItkImage(input, outimage);
nrrdWriter->SetInput( outimage );
nrrdWriter->SetImageIO(io);
nrrdWriter->SetFileName(this->GetOutputLocation().c_str());
nrrdWriter->UseCompressionOn();
try
{
nrrdWriter->Update();
}
catch (const itk::ExceptionObject& e)
{
std::cout << e.GetDescription() << std::endl;
}
}
mitk::NrrdTensorImageWriter* mitk::NrrdTensorImageWriter::Clone() const
{
return new NrrdTensorImageWriter(*this);
}
mitk::IFileWriter::ConfidenceLevel mitk::NrrdTensorImageWriter::GetConfidenceLevel() const
{
InputType::ConstPointer input = dynamic_cast<const InputType*>(this->GetInput());
if (input.IsNull() )
{
return Unsupported;
}
else
{
return Supported;
}
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkNrrdTensorImageWriter.h b/Modules/DiffusionIO/ReaderWriter/mitkNrrdTensorImageWriter.h
index 5ae8f0e..7cc05f4 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkNrrdTensorImageWriter.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkNrrdTensorImageWriter.h
@@ -1,54 +1,54 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_NRRDDTI_WRITER__H_
#define _MITK_NRRDDTI_WRITER__H_
#include <mitkAbstractFileWriter.h>
#include <mitkTensorImage.h>
namespace mitk
{
/**
* Writes diffusion volumes to a file
* @ingroup Process
*/
class NrrdTensorImageWriter : public mitk::AbstractFileWriter
{
public:
typedef mitk::TensorImage InputType;
NrrdTensorImageWriter();
~NrrdTensorImageWriter() override;
using AbstractFileWriter::Write;
void Write() override;
ConfidenceLevel GetConfidenceLevel() const override;
protected:
NrrdTensorImageWriter(const NrrdTensorImageWriter& other);
mitk::NrrdTensorImageWriter* Clone() const override;
};
} // end of namespace mitk
#endif //_MITK_NRRDDTI_WRITER__H_
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkOdfImageSerializer.cpp b/Modules/DiffusionIO/ReaderWriter/mitkOdfImageSerializer.cpp
index d507056..485b0c6 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkOdfImageSerializer.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkOdfImageSerializer.cpp
@@ -1,74 +1,74 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkOdfImageSerializer.h"
#include "mitkOdfImage.h"
#include "mitkNrrdOdfImageWriter.h"
#include <itksys/SystemTools.hxx>
MITK_REGISTER_SERIALIZER(OdfImageSerializer)
mitk::OdfImageSerializer::OdfImageSerializer()
{
}
mitk::OdfImageSerializer::~OdfImageSerializer()
{
}
std::string mitk::OdfImageSerializer::Serialize()
{
const OdfImage* image = dynamic_cast<const OdfImage*>( m_Data.GetPointer() );
if (image == nullptr)
{
MITK_ERROR << " Object at " << (const void*) this->m_Data
<< " is not an mitk::NrrdOdfImage. Cannot serialize as NrrdOdfImage.";
return "";
}
std::string filename( this->GetUniqueFilenameInWorkingDirectory() );
filename += "_";
filename += m_FilenameHint;
filename += ".odf";
std::string fullname(m_WorkingDirectory);
fullname += "/";
fullname += itksys::SystemTools::ConvertToOutputPath(filename.c_str());
try
{
NrrdOdfImageWriter writer;
writer.SetOutputLocation(fullname);
writer.SetInput(image);
writer.Write();
}
catch (std::exception& e)
{
MITK_ERROR << " Error serializing object at " << (const void*) this->m_Data
<< " to "
<< fullname
<< ": "
<< e.what();
return "";
}
return filename;
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkOdfImageSerializer.h b/Modules/DiffusionIO/ReaderWriter/mitkOdfImageSerializer.h
index ad8557c..983c7ac 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkOdfImageSerializer.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkOdfImageSerializer.h
@@ -1,39 +1,39 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkOdfImageSerializer_h_included
#define mitkOdfImageSerializer_h_included
#include "mitkBaseDataSerializer.h"
namespace mitk
{
/**
\brief Serializes mitk::Surface for mitk::SceneIO
*/
class OdfImageSerializer : public BaseDataSerializer
{
public:
mitkClassMacro( OdfImageSerializer, BaseDataSerializer );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
std::string Serialize() override;
protected:
OdfImageSerializer();
~OdfImageSerializer() override;
};
} // namespace
#endif
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkPeakImageReader.cpp b/Modules/DiffusionIO/ReaderWriter/mitkPeakImageReader.cpp
index 9c32bf9..14d838a 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkPeakImageReader.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkPeakImageReader.cpp
@@ -1,85 +1,85 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPeakImageReader.h"
#include <mitkCustomMimeType.h>
#include <mitkDiffusionIOMimeTypes.h>
#include <mitkPeakImage.h>
#include <mitkIOUtil.h>
#include <mitkPreferenceListReaderOptionsFunctor.h>
#include <itkImageFileReader.h>
#include <itksys/SystemTools.hxx>
#include <itkNiftiImageIO.h>
#include <itkNrrdImageIO.h>
#include <mitkITKImageImport.h>
#include <mitkImageCast.h>
#include <mitkLocaleSwitch.h>
namespace mitk
{
PeakImageReader::PeakImageReader(const PeakImageReader& other)
: mitk::AbstractFileReader(other)
{
}
PeakImageReader::PeakImageReader()
: mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::PEAK_MIMETYPE() ), mitk::DiffusionIOMimeTypes::PEAK_MIMETYPE_DESCRIPTION() )
{
m_ServiceReg = this->RegisterService();
}
PeakImageReader::~PeakImageReader()
{
}
std::vector<itk::SmartPointer<BaseData> > PeakImageReader::Read()
{
mitk::LocaleSwitch localeSwitch("C");
std::vector<itk::SmartPointer<mitk::BaseData> > result;
std::string location = GetInputLocation();
std::string ext = itksys::SystemTools::GetFilenameExtension(location);
MITK_INFO << "Reading " << location;
typedef itk::ImageFileReader<PeakImage::ItkPeakImageType> FileReaderType;
FileReaderType::Pointer reader = FileReaderType::New();
reader->SetFileName(location);
if (ext==".peak")
{
itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New();
reader->SetImageIO(io);
}
reader->Update();
Image::Pointer resultImage = dynamic_cast<Image*>(PeakImage::New().GetPointer());
mitk::CastToMitkImage(reader->GetOutput(), resultImage);
resultImage->SetVolume(reader->GetOutput()->GetBufferPointer());
StringProperty::Pointer nameProp;
nameProp = StringProperty::New(itksys::SystemTools::GetFilenameWithoutExtension(GetInputLocation()));
resultImage->SetProperty("name", nameProp);
dynamic_cast<PeakImage*>(resultImage.GetPointer())->ConstructPolydata();
result.push_back( resultImage.GetPointer() );
return result;
}
} //namespace MITK
mitk::PeakImageReader* mitk::PeakImageReader::Clone() const
{
return new PeakImageReader(*this);
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkPeakImageReader.h b/Modules/DiffusionIO/ReaderWriter/mitkPeakImageReader.h
index 8ebaed2..5fac1a0 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkPeakImageReader.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkPeakImageReader.h
@@ -1,53 +1,53 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkPeakImageReader_h
#define __mitkPeakImageReader_h
#include "mitkCommon.h"
#include <mitkAbstractFileReader.h>
#include <mitkBaseData.h>
#include <mitkMimeType.h>
namespace mitk
{
/** \brief
*/
class PeakImageReader : public mitk::AbstractFileReader
{
public:
PeakImageReader(const PeakImageReader& other);
PeakImageReader();
~PeakImageReader() override;
using AbstractFileReader::Read;
std::vector<itk::SmartPointer<BaseData> > Read() override;
protected:
private:
PeakImageReader* Clone() const override;
us::ServiceRegistration<mitk::IFileReader> m_ServiceReg;
};
} //namespace MITK
#endif // __mitkPeakImageReader_h
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkPeakImageSerializer.cpp b/Modules/DiffusionIO/ReaderWriter/mitkPeakImageSerializer.cpp
index 136c091..cf834a9 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkPeakImageSerializer.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkPeakImageSerializer.cpp
@@ -1,86 +1,86 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPeakImageSerializer.h"
#include "mitkPeakImage.h"
#include "itkImageFileWriter.h"
#include <mitkImageToItk.h>
#include <itksys/SystemTools.hxx>
#include <itkNrrdImageIO.h>
#include <mitkLocaleSwitch.h>
MITK_REGISTER_SERIALIZER(PeakImageSerializer)
mitk::PeakImageSerializer::PeakImageSerializer()
{
}
mitk::PeakImageSerializer::~PeakImageSerializer()
{
}
std::string mitk::PeakImageSerializer::Serialize()
{
mitk::LocaleSwitch localeSwitch("C");
const PeakImage* image = dynamic_cast<const PeakImage*>( m_Data.GetPointer() );
if (image == nullptr)
{
MITK_ERROR << " Object at " << (const void*) this->m_Data
<< " is not an mitk::PeakImage. Cannot serialize as Nrrd.";
return "";
}
std::string filename( this->GetUniqueFilenameInWorkingDirectory() );
filename += "_";
filename += m_FilenameHint;
filename += ".peak";
std::string fullname(m_WorkingDirectory);
fullname += "/";
fullname += itksys::SystemTools::ConvertToOutputPath(filename.c_str());
try
{
typedef mitk::ImageToItk< PeakImage::ItkPeakImageType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(image);
caster->Update();
mitk::PeakImage::ItkPeakImageType::Pointer itk_image = caster->GetOutput();
itk::ImageFileWriter< PeakImage::ItkPeakImageType >::Pointer writer = itk::ImageFileWriter< PeakImage::ItkPeakImageType >::New();
writer->SetInput(itk_image);
writer->SetFileName(fullname);
itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New();
io->SetFileType( itk::ImageIOBase::Binary );
io->UseCompressionOn();
writer->SetImageIO(io);
writer->Update();
}
catch (std::exception& e)
{
MITK_ERROR << " Error serializing object at " << (const void*) this->m_Data
<< " to "
<< fullname
<< ": "
<< e.what();
return "";
}
return filename;
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkPeakImageSerializer.h b/Modules/DiffusionIO/ReaderWriter/mitkPeakImageSerializer.h
index a0b87b9..3f8ebcb 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkPeakImageSerializer.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkPeakImageSerializer.h
@@ -1,39 +1,39 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkPeakImageSerializer_h_included
#define mitkPeakImageSerializer_h_included
#include "mitkBaseDataSerializer.h"
namespace mitk
{
/**
\brief Serializes mitk::Surface for mitk::SceneIO
*/
class PeakImageSerializer : public BaseDataSerializer
{
public:
mitkClassMacro( PeakImageSerializer, BaseDataSerializer );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
std::string Serialize() override;
protected:
PeakImageSerializer();
~PeakImageSerializer() override;
};
} // namespace
#endif
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeReader.cpp b/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeReader.cpp
index d205051..de4063c 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeReader.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeReader.cpp
@@ -1,100 +1,100 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPlanarFigureCompositeReader.h"
#include <itkMetaDataObject.h>
#include <itksys/SystemTools.hxx>
#include <tinyxml.h>
#include <vtkCleanPolyData.h>
#include <mitkTrackvis.h>
#include <mitkCustomMimeType.h>
#include "mitkDiffusionIOMimeTypes.h"
#include <boost/property_tree/ptree.hpp>
#define RAPIDXML_NO_EXCEPTIONS
#include <boost/property_tree/xml_parser.hpp>
#include <boost/foreach.hpp>
#include <mitkLexicalCast.h>
#include <mitkPlanarFigureComposite.h>
mitk::PlanarFigureCompositeReader::PlanarFigureCompositeReader()
: mitk::AbstractFileReader( mitk::DiffusionIOMimeTypes::PLANARFIGURECOMPOSITE_MIMETYPE(), "Planar Figure Composite Reader" )
{
m_ServiceReg = this->RegisterService();
}
mitk::PlanarFigureCompositeReader::PlanarFigureCompositeReader(const PlanarFigureCompositeReader &other)
:mitk::AbstractFileReader(other)
{
}
mitk::PlanarFigureCompositeReader * mitk::PlanarFigureCompositeReader::Clone() const
{
return new PlanarFigureCompositeReader(*this);
}
std::vector<itk::SmartPointer<mitk::BaseData> > mitk::PlanarFigureCompositeReader::Read()
{
std::vector<itk::SmartPointer<mitk::BaseData> > result;
try
{
const std::string& locale = "C";
const std::string& currLocale = setlocale( LC_ALL, nullptr );
setlocale(LC_ALL, locale.c_str());
std::string filename = this->GetInputLocation();
std::string ext = itksys::SystemTools::GetFilenameLastExtension(filename);
ext = itksys::SystemTools::LowerCase(ext);
boost::property_tree::ptree tree;
boost::property_tree::xml_parser::read_xml(filename, tree);
int comptype = tree.get<int>("comptype");
mitk::PlanarFigureComposite::Pointer pfc = mitk::PlanarFigureComposite::New();
switch(comptype)
{
case 0:
pfc->setOperationType(mitk::PlanarFigureComposite::AND);
MITK_INFO << "loading AND composition";
break;
case 1:
pfc->setOperationType(mitk::PlanarFigureComposite::OR);
MITK_INFO << "loading OR composition";
break;
case 2:
pfc->setOperationType(mitk::PlanarFigureComposite::NOT);
MITK_INFO << "loading NOT composition";
break;
default:
MITK_ERROR << filename << " contains no valid composition type!";
}
std::vector<itk::SmartPointer<mitk::BaseData> > result;
result.push_back(pfc.GetPointer());
setlocale(LC_ALL, currLocale.c_str());
return result;
}
catch(...)
{
throw;
}
return result;
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeReader.h b/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeReader.h
index 740e10b..1bac895 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeReader.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeReader.h
@@ -1,52 +1,52 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkPlanarFigureCompositeReader_h
#define __mitkPlanarFigureCompositeReader_h
#include <mitkCommon.h>
#include <mitkFileReader.h>
#include <mitkFiberBundle.h>
#include <vtkSmartPointer.h>
#include <mitkAbstractFileReader.h>
namespace mitk
{
/** \brief
*/
class PlanarFigureCompositeReader : public AbstractFileReader
{
public:
PlanarFigureCompositeReader();
~PlanarFigureCompositeReader() override{}
PlanarFigureCompositeReader(const PlanarFigureCompositeReader& other);
PlanarFigureCompositeReader * Clone() const override;
using mitk::AbstractFileReader::Read;
std::vector<itk::SmartPointer<BaseData> > Read() override;
private:
us::ServiceRegistration<mitk::IFileReader> m_ServiceReg;
};
} //namespace MITK
#endif // __mitkFiberBundleReader_h
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeSerializer.cpp b/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeSerializer.cpp
index 956b070..6d625ec 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeSerializer.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeSerializer.cpp
@@ -1,73 +1,73 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPlanarFigureCompositeSerializer.h"
#include "mitkPlanarFigureComposite.h"
#include "mitkPlanarFigureCompositeWriter.h"
#include <mitkPlanarFigureComposite.h>
#include <itksys/SystemTools.hxx>
#include <mitkIOUtil.h>
MITK_REGISTER_SERIALIZER(PlanarFigureCompositeSerializer)
mitk::PlanarFigureCompositeSerializer::PlanarFigureCompositeSerializer()
{
}
mitk::PlanarFigureCompositeSerializer::~PlanarFigureCompositeSerializer()
{
}
std::string mitk::PlanarFigureCompositeSerializer::Serialize()
{
const PlanarFigureComposite* fb = dynamic_cast<const PlanarFigureComposite*>( m_Data.GetPointer() );
if (fb == nullptr)
{
MITK_ERROR << " Object at " << (const void*) this->m_Data
<< " is not an mitk::PlanarFigureComposite. Cannot serialize as PlanarFigureComposite.";
return "";
}
std::string filename( this->GetUniqueFilenameInWorkingDirectory() );
filename += "_";
filename += m_FilenameHint;
filename += ".pfc";
std::string fullname(m_WorkingDirectory);
fullname += "/";
fullname += itksys::SystemTools::ConvertToOutputPath(filename.c_str());
try
{
mitk::IOUtil::Save(fb,fullname);
}
catch (std::exception& e)
{
MITK_ERROR << " Error serializing object at " << (const void*) this->m_Data
<< " to "
<< fullname
<< ": "
<< e.what();
return "";
}
return filename;
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeSerializer.h b/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeSerializer.h
index e9655a8..916a3a2 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeSerializer.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeSerializer.h
@@ -1,39 +1,39 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkPlanarFigureCompositeSerializer_h_included
#define mitkPlanarFigureCompositeSerializer_h_included
#include "mitkBaseDataSerializer.h"
namespace mitk
{
/**
\brief Serializes mitk::PlanarFigureComposite for mitk::SceneIO
*/
class PlanarFigureCompositeSerializer : public BaseDataSerializer
{
public:
mitkClassMacro( PlanarFigureCompositeSerializer, BaseDataSerializer );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
std::string Serialize() override;
protected:
PlanarFigureCompositeSerializer();
~PlanarFigureCompositeSerializer() override;
};
} // namespace
#endif
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeWriter.cpp b/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeWriter.cpp
index ea7dedc..32eb34c 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeWriter.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeWriter.cpp
@@ -1,90 +1,90 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPlanarFigureCompositeWriter.h"
#include <itksys/SystemTools.hxx>
#include <mitkAbstractFileWriter.h>
#include <mitkCustomMimeType.h>
#include "mitkDiffusionIOMimeTypes.h"
#include <boost/property_tree/ptree.hpp>
#define RAPIDXML_NO_EXCEPTIONS
#include <boost/property_tree/xml_parser.hpp>
#include <mitkPlanarFigureComposite.h>
mitk::PlanarFigureCompositeWriter::PlanarFigureCompositeWriter()
: mitk::AbstractFileWriter(mitk::PlanarFigureComposite::GetStaticNameOfClass(), mitk::DiffusionIOMimeTypes::PLANARFIGURECOMPOSITE_MIMETYPE(), "Planar Figure Composite Writer")
{
RegisterService();
}
mitk::PlanarFigureCompositeWriter::PlanarFigureCompositeWriter(const mitk::PlanarFigureCompositeWriter & other)
:mitk::AbstractFileWriter(other)
{}
mitk::PlanarFigureCompositeWriter::~PlanarFigureCompositeWriter()
{}
mitk::PlanarFigureCompositeWriter * mitk::PlanarFigureCompositeWriter::Clone() const
{
return new mitk::PlanarFigureCompositeWriter(*this);
}
void mitk::PlanarFigureCompositeWriter::Write()
{
std::ostream* out;
std::ofstream outStream;
if( this->GetOutputStream() )
{
out = this->GetOutputStream();
}else{
outStream.open( this->GetOutputLocation().c_str() );
out = &outStream;
}
if ( !out->good() )
{
mitkThrow() << "Stream not good.";
}
try
{
const std::string& locale = "C";
const std::string& currLocale = setlocale( LC_ALL, nullptr );
setlocale(LC_ALL, locale.c_str());
std::locale previousLocale(out->getloc());
std::locale I("C");
out->imbue(I);
std::string filename = this->GetOutputLocation().c_str();
mitk::PlanarFigureComposite::ConstPointer input = dynamic_cast<const mitk::PlanarFigureComposite*>(this->GetInput());
std::string ext = itksys::SystemTools::GetFilenameLastExtension(this->GetOutputLocation().c_str());
boost::property_tree::ptree type;
type.put("comptype", input->getOperationType());
boost::property_tree::xml_writer_settings<std::string> writerSettings(' ', 2);
boost::property_tree::xml_parser::write_xml(filename, type, std::locale(), writerSettings);
setlocale(LC_ALL, currLocale.c_str());
}
catch(...)
{
throw;
}
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeWriter.h b/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeWriter.h
index 3368abb..68fd2dc 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeWriter.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkPlanarFigureCompositeWriter.h
@@ -1,47 +1,47 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkPlanarFigureCompositeWriter_h
#define __mitkPlanarFigureCompositeWriter_h
#include <mitkAbstractFileWriter.h>
namespace mitk
{
/**
* Writes fiber bundles to a file
* @ingroup Process
*/
class PlanarFigureCompositeWriter : public mitk::AbstractFileWriter
{
public:
PlanarFigureCompositeWriter();
PlanarFigureCompositeWriter(const PlanarFigureCompositeWriter & other);
PlanarFigureCompositeWriter * Clone() const override;
~PlanarFigureCompositeWriter() override;
using mitk::AbstractFileWriter::Write;
void Write() override;
};
} // end of namespace mitk
#endif //__mitkFiberBundleWriter_h
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkShImageReader.cpp b/Modules/DiffusionIO/ReaderWriter/mitkShImageReader.cpp
index cd165b1..4cb4884 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkShImageReader.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkShImageReader.cpp
@@ -1,141 +1,141 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkShImageReader.h"
#include <mitkCustomMimeType.h>
#include "mitkDiffusionIOMimeTypes.h"
#include "itkImageFileReader.h"
#include "itkImageRegionIterator.h"
#include "itkMetaDataObject.h"
#include "itkNrrdImageIO.h"
#include "itkNiftiImageIO.h"
#include "mitkITKImageImport.h"
#include "mitkImageDataItem.h"
#include <mitkLocaleSwitch.h>
#include <itkShCoefficientImageImporter.h>
#include <mitkImageCast.h>
namespace mitk
{
ShImageReader::ShImageReader(const ShImageReader& other)
: mitk::AbstractFileReader(other)
{
}
ShImageReader::ShImageReader()
: mitk::AbstractFileReader( CustomMimeType( mitk::DiffusionIOMimeTypes::SH_MIMETYPE() ), mitk::DiffusionIOMimeTypes::SH_MIMETYPE_DESCRIPTION() )
{
Options defaultOptions;
defaultOptions["Assume MRtrix/MITK style SH convention (else FSL/Dipy)"] = true;
this->SetDefaultOptions(defaultOptions);
m_ServiceReg = this->RegisterService();
}
ShImageReader::~ShImageReader()
{
}
template <int shOrder>
mitk::Image::Pointer ShImageReader::ConvertShImage(ShImage::ShOnDiskType::Pointer img)
{
typedef itk::ShCoefficientImageImporter< float, shOrder > ImporterType;
typename ImporterType::Pointer importer = ImporterType::New();
importer->SetInputImage(img);
importer->GenerateData();
mitk::ShImage::Pointer shImage = mitk::ShImage::New();
Options options = this->GetOptions();
bool mrtrix_sh = us::any_cast<bool>(options["Assume MRtrix/MITK style SH convention (else FSL/Dipy)"]);
if (!mrtrix_sh)
shImage->SetShConvention(mitk::ShImage::SH_CONVENTION::FSL);
mitk::Image::Pointer resultImage = dynamic_cast<mitk::Image*>(shImage.GetPointer());
mitk::CastToMitkImage(importer->GetCoefficientImage(), resultImage);
resultImage->SetVolume(importer->GetCoefficientImage()->GetBufferPointer());
return resultImage;
}
std::vector<itk::SmartPointer<BaseData> > ShImageReader::Read()
{
mitk::LocaleSwitch localeSwitch("C");
std::vector<itk::SmartPointer<mitk::BaseData> > result;
std::string location = GetInputLocation();
if ( location == "")
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, the filename is empty!");
}
else
{
try
{
std::string ext = itksys::SystemTools::GetFilenameExtension(location);
typedef itk::ImageFileReader< ShImage::ShOnDiskType > FileReaderType;
FileReaderType::Pointer reader = FileReaderType::New();
reader->SetFileName(location);
if (ext==".shi")
{
itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New();
reader->SetImageIO(io);
}
reader->Update();
ShImage::ShOnDiskType::Pointer img = reader->GetOutput();
switch (img->GetLargestPossibleRegion().GetSize()[3])
{
case 6:
result.push_back( ConvertShImage<2>(img).GetPointer() );
break;
case 15:
result.push_back( ConvertShImage<4>(img).GetPointer() );
break;
case 28:
result.push_back( ConvertShImage<6>(img).GetPointer() );
break;
case 45:
result.push_back( ConvertShImage<8>(img).GetPointer() );
break;
case 66:
result.push_back( ConvertShImage<10>(img).GetPointer() );
break;
case 91:
result.push_back( ConvertShImage<12>(img).GetPointer() );
break;
default :
mitkThrow() << "SH order larger 12 not supported";
}
}
catch(std::exception& e)
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, e.what());
}
catch(...)
{
throw itk::ImageFileReaderException(__FILE__, __LINE__, "Sorry, an error occurred while reading the requested vessel tree file!");
}
}
return result;
}
} //namespace MITK
mitk::ShImageReader* mitk::ShImageReader::Clone() const
{
return new ShImageReader(*this);
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkShImageReader.h b/Modules/DiffusionIO/ReaderWriter/mitkShImageReader.h
index 2b4d17c..fbf86bf 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkShImageReader.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkShImageReader.h
@@ -1,63 +1,63 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkNrrdShImageReader_h
#define __mitkNrrdShImageReader_h
#include "mitkCommon.h"
#include "itkVectorContainer.h"
#include "vnl/vnl_vector_fixed.h"
#include "mitkShImage.h"
#include "itkVectorImage.h"
#include <mitkAbstractFileReader.h>
#include <mitkBaseData.h>
#include <mitkMimeType.h>
namespace mitk
{
/** \brief
*/
class ShImageReader : public mitk::AbstractFileReader
{
public:
typedef mitk::ShImage OutputType;
typedef itk::VectorImage<float,3> VectorImageType;
ShImageReader(const ShImageReader& other);
ShImageReader();
~ShImageReader() override;
using AbstractFileReader::Read;
std::vector<itk::SmartPointer<BaseData> > Read() override;
protected:
private:
ShImageReader* Clone() const override;
template <int sh_order>
mitk::Image::Pointer ConvertShImage(ShImage::ShOnDiskType::Pointer img);
us::ServiceRegistration<mitk::IFileReader> m_ServiceReg;
};
} //namespace MITK
#endif // __mitkNrrdShImageReader_h
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkShImageSerializer.cpp b/Modules/DiffusionIO/ReaderWriter/mitkShImageSerializer.cpp
index fbe137f..769fc42 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkShImageSerializer.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkShImageSerializer.cpp
@@ -1,74 +1,74 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkShImageSerializer.h"
#include "mitkShImage.h"
#include "mitkShImageWriter.h"
#include <itksys/SystemTools.hxx>
MITK_REGISTER_SERIALIZER(ShImageSerializer)
mitk::ShImageSerializer::ShImageSerializer()
{
}
mitk::ShImageSerializer::~ShImageSerializer()
{
}
std::string mitk::ShImageSerializer::Serialize()
{
const ShImage* image = dynamic_cast<const ShImage*>( m_Data.GetPointer() );
if (image == nullptr)
{
MITK_ERROR << " Object at " << (const void*) this->m_Data
<< " is not an mitk::NrrdShImage. Cannot serialize as NrrdShImage.";
return "";
}
std::string filename( this->GetUniqueFilenameInWorkingDirectory() );
filename += "_";
filename += m_FilenameHint;
filename += ".shi";
std::string fullname(m_WorkingDirectory);
fullname += "/";
fullname += itksys::SystemTools::ConvertToOutputPath(filename.c_str());
try
{
mitk::ShImageWriter writer;
writer.SetOutputLocation(fullname);
writer.SetInput(image);
writer.Write();
}
catch (std::exception& e)
{
MITK_ERROR << " Error serializing object at " << (const void*) this->m_Data
<< " to "
<< fullname
<< ": "
<< e.what();
return "";
}
return filename;
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkShImageSerializer.h b/Modules/DiffusionIO/ReaderWriter/mitkShImageSerializer.h
index 9d04377..60a5ab8 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkShImageSerializer.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkShImageSerializer.h
@@ -1,39 +1,39 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkShImageSerializer_h_included
#define mitkShImageSerializer_h_included
#include "mitkBaseDataSerializer.h"
namespace mitk
{
/**
\brief Serializes mitk::Surface for mitk::SceneIO
*/
class ShImageSerializer : public BaseDataSerializer
{
public:
mitkClassMacro( ShImageSerializer, BaseDataSerializer );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
std::string Serialize() override;
protected:
ShImageSerializer();
~ShImageSerializer() override;
};
} // namespace
#endif
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkShImageWriter.cpp b/Modules/DiffusionIO/ReaderWriter/mitkShImageWriter.cpp
index d65e071..6351d07 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkShImageWriter.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkShImageWriter.cpp
@@ -1,138 +1,138 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkShImageWriter.h"
#include "itkMetaDataDictionary.h"
#include "itkMetaDataObject.h"
#include "itkImageFileWriter.h"
#include "mitkImageCast.h"
#include "mitkIOMimeTypes.h"
#include "mitkDiffusionIOMimeTypes.h"
#include <mitkLocaleSwitch.h>
#include <itkShCoefficientImageExporter.h>
#include <itksys/SystemTools.hxx>
#include <itkNrrdImageIO.h>
mitk::ShImageWriter::ShImageWriter()
: AbstractFileWriter(mitk::ShImage::GetStaticNameOfClass(), CustomMimeType( mitk::DiffusionIOMimeTypes::SH_MIMETYPE() ), mitk::DiffusionIOMimeTypes::SH_MIMETYPE_DESCRIPTION())
{
RegisterService();
}
mitk::ShImageWriter::ShImageWriter(const mitk::ShImageWriter& other)
: AbstractFileWriter(other)
{
}
mitk::ShImageWriter::~ShImageWriter()
{}
template <int shOrder>
void mitk::ShImageWriter::WriteShImage(InputType::ConstPointer input)
{
mitk::LocaleSwitch localeSwitch("C");
typename itk::ShCoefficientImageExporter< float, shOrder >::InputImageType::Pointer itk_image = itk::ShCoefficientImageExporter< float, shOrder >::InputImageType::New();
CastToItkImage(input, itk_image);
typedef itk::ShCoefficientImageExporter< float, shOrder > ExporterType;
typename ExporterType::Pointer exporter = ExporterType::New();
exporter->SetInputImage(itk_image);
exporter->GenerateData();
std::string ext = itksys::SystemTools::GetFilenameExtension(this->GetOutputLocation());
typedef itk::ImageFileWriter<ShImage::ShOnDiskType> WriterType;
WriterType::Pointer writer = WriterType::New();
ShImage::ShOnDiskType::Pointer image = exporter->GetOutputImage();
writer->SetInput( image );
if (ext==".shi")
{
itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New();
io->SetFileType( itk::ImageIOBase::Binary );
io->UseCompressionOn();
writer->SetImageIO(io);
}
writer->SetFileName(this->GetOutputLocation().c_str());
writer->SetUseCompression(true);
try
{
writer->Update();
}
catch (const itk::ExceptionObject& e)
{
MITK_INFO << e.what();
}
}
void mitk::ShImageWriter::Write()
{
InputType::ConstPointer input = dynamic_cast<const InputType*>(this->GetInput());
if (input.IsNull())
{
MITK_ERROR <<"Sorry, input to ShImageWriter is nullptr!";
return;
}
if ( this->GetOutputLocation().empty() )
{
MITK_ERROR << "Sorry, filename has not been set!";
return ;
}
switch (input->GetImageDescriptor()->GetChannelTypeById(0).GetNumberOfComponents())
{
case 6:
WriteShImage<2>(input);
break;
case 15:
WriteShImage<4>(input);
break;
case 28:
WriteShImage<6>(input);
break;
case 45:
WriteShImage<8>(input);
break;
case 66:
WriteShImage<10>(input);
break;
case 91:
WriteShImage<12>(input);
break;
default :
mitkThrow() << "SH order larger 12 not supported";
}
}
mitk::ShImageWriter* mitk::ShImageWriter::Clone() const
{
return new ShImageWriter(*this);
}
mitk::IFileWriter::ConfidenceLevel mitk::ShImageWriter::GetConfidenceLevel() const
{
InputType::ConstPointer input = dynamic_cast<const InputType*>(this->GetInput());
if (input.IsNull() )
{
return Unsupported;
}
else
{
return Supported;
}
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkShImageWriter.h b/Modules/DiffusionIO/ReaderWriter/mitkShImageWriter.h
index 140c0ad..4a89761 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkShImageWriter.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkShImageWriter.h
@@ -1,58 +1,58 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_SH_WRITER__H_
#define _MITK_SH_WRITER__H_
#include <mitkAbstractFileWriter.h>
#include <mitkShImage.h>
namespace mitk
{
/**
* Writes diffusion volumes to a file
* @ingroup Process
*/
class ShImageWriter : public mitk::AbstractFileWriter
{
public:
typedef itk::VectorImage<float, 3> VecImgType;
typedef mitk::ShImage InputType;
ShImageWriter();
~ShImageWriter() override;
using AbstractFileWriter::Write;
void Write() override;
ConfidenceLevel GetConfidenceLevel() const override;
protected:
ShImageWriter(const ShImageWriter& other);
mitk::ShImageWriter* Clone() const override;
template <int shOrder>
void WriteShImage(InputType::ConstPointer input);
};
} // end of namespace mitk
#endif //_MITK_NRRDODF_WRITER__H_
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkTensorImageSerializer.cpp b/Modules/DiffusionIO/ReaderWriter/mitkTensorImageSerializer.cpp
index c92fd08..6d5ab84 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkTensorImageSerializer.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkTensorImageSerializer.cpp
@@ -1,74 +1,74 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkTensorImageSerializer.h"
#include "mitkTensorImage.h"
#include "mitkNrrdTensorImageWriter.h"
#include <itksys/SystemTools.hxx>
MITK_REGISTER_SERIALIZER(TensorImageSerializer)
mitk::TensorImageSerializer::TensorImageSerializer()
{
}
mitk::TensorImageSerializer::~TensorImageSerializer()
{
}
std::string mitk::TensorImageSerializer::Serialize()
{
const TensorImage* image = dynamic_cast<const TensorImage*>( m_Data.GetPointer() );
if (image == nullptr)
{
MITK_ERROR << " Object at " << (const void*) this->m_Data
<< " is not an mitk::NrrdTensorImage. Cannot serialize as NrrdTensorImage.";
return "";
}
std::string filename( this->GetUniqueFilenameInWorkingDirectory() );
filename += "_";
filename += m_FilenameHint;
filename += ".dti";
std::string fullname(m_WorkingDirectory);
fullname += "/";
fullname += itksys::SystemTools::ConvertToOutputPath(filename.c_str());
try
{
NrrdTensorImageWriter writer;
writer.SetOutputLocation(fullname);
writer.SetInput(image);
writer.Write();
}
catch (std::exception& e)
{
MITK_ERROR << " Error serializing object at " << (const void*) this->m_Data
<< " to "
<< fullname
<< ": "
<< e.what();
return "";
}
return filename;
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkTensorImageSerializer.h b/Modules/DiffusionIO/ReaderWriter/mitkTensorImageSerializer.h
index 407e6e8..70d544d 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkTensorImageSerializer.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkTensorImageSerializer.h
@@ -1,39 +1,39 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkTensorImageSerializer_h_included
#define mitkTensorImageSerializer_h_included
#include "mitkBaseDataSerializer.h"
namespace mitk
{
/**
\brief Serializes mitk::Surface for mitk::SceneIO
*/
class TensorImageSerializer : public BaseDataSerializer
{
public:
mitkClassMacro( TensorImageSerializer, BaseDataSerializer );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
std::string Serialize() override;
protected:
TensorImageSerializer();
~TensorImageSerializer() override;
};
} // namespace
#endif
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestReader.cpp b/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestReader.cpp
index fd12596..b5eb907 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestReader.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestReader.cpp
@@ -1,77 +1,77 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkTractographyForestReader.h"
#include <itkMetaDataObject.h>
#include <mitkCustomMimeType.h>
#include "mitkDiffusionIOMimeTypes.h"
#undef DIFFERENCE
#define VIGRA_STATIC_LIB
#include <vigra/random_forest.hxx>
#include <vigra/random_forest_hdf5_impex.hxx>
mitk::TractographyForestReader::TractographyForestReader()
: mitk::AbstractFileReader( mitk::DiffusionIOMimeTypes::TRACTOGRAPHYFOREST_MIMETYPE_NAME(), "Tractography Forest" )
{
m_ServiceReg = this->RegisterService();
}
mitk::TractographyForestReader::TractographyForestReader(const TractographyForestReader &other)
:mitk::AbstractFileReader(other)
{
}
mitk::TractographyForestReader * mitk::TractographyForestReader::Clone() const
{
return new TractographyForestReader(*this);
}
std::vector<itk::SmartPointer<mitk::BaseData> > mitk::TractographyForestReader::Read()
{
std::vector<itk::SmartPointer<mitk::BaseData> > result;
std::shared_ptr< vigra::RandomForest<int> > forest;
const std::string& locale = "C";
const std::string& currLocale = setlocale( LC_ALL, nullptr );
setlocale(LC_ALL, locale.c_str());
std::string filename = this->GetInputLocation();
try
{
MITK_INFO << "Trying to load random forest file.";
forest = std::make_shared< vigra::RandomForest<int> >();
vigra::rf_import_HDF5( *forest, filename);
mitk::TractographyForest::Pointer mitkForest = mitk::TractographyForest::New(forest);
result.push_back(mitkForest.GetPointer());
}
catch(...)
{
setlocale(LC_ALL, currLocale.c_str());
MITK_INFO << "Reading random forest failed";
throw;
}
setlocale(LC_ALL, currLocale.c_str());
MITK_INFO << "Random forest read";
return result;
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestReader.h b/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestReader.h
index e53d6d5..470e934 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestReader.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestReader.h
@@ -1,50 +1,50 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkTractographyForestReader_h
#define __mitkTractographyForestReader_h
#include <mitkCommon.h>
#include <mitkFileReader.h>
#include <mitkAbstractFileReader.h>
#include <mitkTractographyForest.h>
namespace mitk
{
/** \brief
*/
class TractographyForestReader : public AbstractFileReader
{
public:
TractographyForestReader();
~TractographyForestReader() override{}
TractographyForestReader(const TractographyForestReader& other);
TractographyForestReader * Clone() const override;
using mitk::AbstractFileReader::Read;
std::vector<itk::SmartPointer<BaseData> > Read() override;
private:
us::ServiceRegistration<mitk::IFileReader> m_ServiceReg;
};
} //namespace MITK
#endif // __mitkFiberBundleReader_h
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestSerializer.cpp b/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestSerializer.cpp
index 19e56b3..6070e3a 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestSerializer.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestSerializer.cpp
@@ -1,73 +1,73 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkTractographyForestSerializer.h"
#include "mitkTractographyForest.h"
#include "mitkTractographyForestWriter.h"
#include <mitkTractographyForest.h>
#include <itksys/SystemTools.hxx>
#include <mitkIOUtil.h>
MITK_REGISTER_SERIALIZER(TractographyForestSerializer)
mitk::TractographyForestSerializer::TractographyForestSerializer()
{
}
mitk::TractographyForestSerializer::~TractographyForestSerializer()
{
}
std::string mitk::TractographyForestSerializer::Serialize()
{
const TractographyForest* fb = dynamic_cast<const TractographyForest*>( m_Data.GetPointer() );
if (fb == nullptr)
{
MITK_ERROR << " Object at " << (const void*) this->m_Data
<< " is not an mitk::TractographyForest. Cannot serialize as TractographyForest.";
return "";
}
std::string filename( this->GetUniqueFilenameInWorkingDirectory() );
filename += "_";
filename += m_FilenameHint;
filename += ".rf";
std::string fullname(m_WorkingDirectory);
fullname += "/";
fullname += itksys::SystemTools::ConvertToOutputPath(filename.c_str());
try
{
mitk::IOUtil::Save(fb,fullname);
}
catch (std::exception& e)
{
MITK_ERROR << " Error serializing object at " << (const void*) this->m_Data
<< " to "
<< fullname
<< ": "
<< e.what();
return "";
}
return filename;
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestSerializer.h b/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestSerializer.h
index 93eec63..8fa0063 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestSerializer.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestSerializer.h
@@ -1,39 +1,39 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 mitkTractographyForestSerializer_h_included
#define mitkTractographyForestSerializer_h_included
#include "mitkBaseDataSerializer.h"
namespace mitk
{
/**
\brief Serializes mitk::TractographyForest for mitk::SceneIO
*/
class TractographyForestSerializer : public BaseDataSerializer
{
public:
mitkClassMacro( TractographyForestSerializer, BaseDataSerializer );
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
std::string Serialize() override;
protected:
TractographyForestSerializer();
~TractographyForestSerializer() override;
};
} // namespace
#endif
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestWriter.cpp b/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestWriter.cpp
index 0e5769d..16286bb 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestWriter.cpp
+++ b/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestWriter.cpp
@@ -1,91 +1,91 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkTractographyForestWriter.h"
#include <mitkAbstractFileWriter.h>
#include <mitkCustomMimeType.h>
#include <mitkDiffusionIOMimeTypes.h>
#include <mitkTractographyForest.h>
//#undef DIFFERENCE
//#define VIGRA_STATIC_LIB
//#include <vigra/random_forest.hxx>
#include <vigra/random_forest_hdf5_impex.hxx>
mitk::TractographyForestWriter::TractographyForestWriter()
: mitk::AbstractFileWriter(mitk::TractographyForest::GetStaticNameOfClass(), mitk::DiffusionIOMimeTypes::TRACTOGRAPHYFOREST_MIMETYPE_NAME(), "Tractography Forest")
{
RegisterService();
}
mitk::TractographyForestWriter::TractographyForestWriter(const mitk::TractographyForestWriter & other)
:mitk::AbstractFileWriter(other)
{}
mitk::TractographyForestWriter::~TractographyForestWriter()
{}
mitk::TractographyForestWriter * mitk::TractographyForestWriter::Clone() const
{
return new mitk::TractographyForestWriter(*this);
}
void mitk::TractographyForestWriter::Write()
{
std::ostream* out;
std::ofstream outStream;
if( this->GetOutputStream() )
{
out = this->GetOutputStream();
}else{
outStream.open( this->GetOutputLocation().c_str() );
out = &outStream;
}
if ( !out->good() )
{
mitkThrow() << "Stream not good.";
}
const std::string& locale = "C";
const std::string& currLocale = setlocale( LC_ALL, nullptr );
setlocale(LC_ALL, locale.c_str());
std::locale previousLocale(out->getloc());
std::locale I("C");
out->imbue(I);
try
{
std::string filename = this->GetOutputLocation().c_str();
mitk::TractographyForest::ConstPointer input = dynamic_cast<const mitk::TractographyForest*>(this->GetInput());
MITK_INFO << "Saving forest to " << filename;
vigra::rf_export_HDF5( *input->GetForest(), filename, "" );
setlocale(LC_ALL, currLocale.c_str());
MITK_INFO << "Forest saved successfully.";
}
catch(...)
{
setlocale(LC_ALL, currLocale.c_str());
MITK_INFO << "Forest could not be saved.";
throw;
}
}
diff --git a/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestWriter.h b/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestWriter.h
index 2715b6b..a44c182 100644
--- a/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestWriter.h
+++ b/Modules/DiffusionIO/ReaderWriter/mitkTractographyForestWriter.h
@@ -1,52 +1,52 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __mitkTractographyForestWriter_h
#define __mitkTractographyForestWriter_h
#include <mitkAbstractFileWriter.h>
#include "mitkFiberBundle.h"
#include <vtkPolyDataWriter.h>
namespace mitk
{
/**
* Writes random forests used for fiber tractography
* @ingroup Process
*/
class TractographyForestWriter : public mitk::AbstractFileWriter
{
public:
TractographyForestWriter();
TractographyForestWriter(const TractographyForestWriter & other);
TractographyForestWriter * Clone() const override;
~TractographyForestWriter() override;
using mitk::AbstractFileWriter::Write;
void Write() override;
};
} // end of namespace mitk
#endif //__mitkFiberBundleWriter_h
diff --git a/Modules/DiffusionIO/mitkDiffusionIOMimeTypes.cpp b/Modules/DiffusionIO/mitkDiffusionIOMimeTypes.cpp
index a45be0d..774a216 100644
--- a/Modules/DiffusionIO/mitkDiffusionIOMimeTypes.cpp
+++ b/Modules/DiffusionIO/mitkDiffusionIOMimeTypes.cpp
@@ -1,796 +1,796 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkDiffusionIOMimeTypes.h"
#include "mitkIOMimeTypes.h"
#include <itksys/SystemTools.hxx>
#include <itkNrrdImageIO.h>
#include <itkMetaDataDictionary.h>
#include <itkMetaDataObject.h>
#include <mitkLogMacros.h>
#include <dcmtk/dcmtract/trctractographyresults.h>
#include <mitkDICOMDCMTKTagScanner.h>
#include <itkGDCMImageIO.h>
#include <itkNiftiImageIO.h>
namespace mitk
{
std::vector<CustomMimeType*> DiffusionIOMimeTypes::Get()
{
std::vector<CustomMimeType*> mimeTypes;
// order matters here (descending rank for mime types)
mimeTypes.push_back(FIBERBUNDLE_VTK_MIMETYPE().Clone());
mimeTypes.push_back(FIBERBUNDLE_TRK_MIMETYPE().Clone());
mimeTypes.push_back(FIBERBUNDLE_TCK_MIMETYPE().Clone());
mimeTypes.push_back(FIBERBUNDLE_DICOM_MIMETYPE().Clone());
mimeTypes.push_back(CONNECTOMICS_MIMETYPE().Clone());
mimeTypes.push_back(TRACTOGRAPHYFOREST_MIMETYPE().Clone());
mimeTypes.push_back(PLANARFIGURECOMPOSITE_MIMETYPE().Clone());
mimeTypes.push_back(DWI_NRRD_MIMETYPE().Clone());
mimeTypes.push_back(DWI_NIFTI_MIMETYPE().Clone());
mimeTypes.push_back(DWI_DICOM_MIMETYPE().Clone());
mimeTypes.push_back(DTI_MIMETYPE().Clone());
mimeTypes.push_back(ODF_MIMETYPE().Clone());
mimeTypes.push_back(PEAK_MIMETYPE().Clone());
mimeTypes.push_back(SH_MIMETYPE().Clone());
return mimeTypes;
}
// Mime Types
CustomMimeType DiffusionIOMimeTypes::PLANARFIGURECOMPOSITE_MIMETYPE()
{
CustomMimeType mimeType(PLANARFIGURECOMPOSITE_MIMETYPE_NAME());
std::string category = "Planar Figure Composite";
mimeType.SetComment("Planar Figure Composite");
mimeType.SetCategory(category);
mimeType.AddExtension("pfc");
return mimeType;
}
CustomMimeType DiffusionIOMimeTypes::TRACTOGRAPHYFOREST_MIMETYPE()
{
CustomMimeType mimeType(TRACTOGRAPHYFOREST_MIMETYPE_NAME());
std::string category = "Tractography Forest";
mimeType.SetComment("Tractography Forest");
mimeType.SetCategory(category);
mimeType.AddExtension("rf");
return mimeType;
}
CustomMimeType DiffusionIOMimeTypes::FIBERBUNDLE_VTK_MIMETYPE()
{
CustomMimeType mimeType(FIBERBUNDLE_VTK_MIMETYPE_NAME());
std::string category = "VTK Fibers";
mimeType.SetComment("VTK Fibers");
mimeType.SetCategory(category);
mimeType.AddExtension("fib");
mimeType.AddExtension("vtk");
return mimeType;
}
CustomMimeType DiffusionIOMimeTypes::FIBERBUNDLE_TCK_MIMETYPE()
{
CustomMimeType mimeType(FIBERBUNDLE_TCK_MIMETYPE_NAME());
std::string category = "MRtrix Fibers";
mimeType.SetComment("MRtrix Fibers");
mimeType.SetCategory(category);
mimeType.AddExtension("tck");
return mimeType;
}
CustomMimeType DiffusionIOMimeTypes::FIBERBUNDLE_TRK_MIMETYPE()
{
CustomMimeType mimeType(FIBERBUNDLE_TRK_MIMETYPE_NAME());
std::string category = "TrackVis Fibers";
mimeType.SetComment("TrackVis Fibers");
mimeType.SetCategory(category);
mimeType.AddExtension("trk");
return mimeType;
}
DiffusionIOMimeTypes::FiberBundleDicomMimeType::FiberBundleDicomMimeType()
: CustomMimeType(FIBERBUNDLE_DICOM_MIMETYPE_NAME())
{
std::string category = "DICOM Fibers";
this->SetCategory(category);
this->SetComment("DICOM Fibers");
this->AddExtension("dcm");
this->AddExtension("DCM");
this->AddExtension("gdcm");
this->AddExtension("dc3");
this->AddExtension("DC3");
this->AddExtension("ima");
this->AddExtension("img");
}
bool DiffusionIOMimeTypes::FiberBundleDicomMimeType::AppliesTo(const std::string &path) const
{
try
{
std::ifstream myfile;
myfile.open (path, std::ios::binary);
// myfile.seekg (128);
char *buffer = new char [128];
myfile.read (buffer,128);
myfile.read (buffer,4);
if (std::string(buffer).compare("DICM")!=0)
{
delete[] buffer;
return false;
}
delete[] buffer;
mitk::DICOMDCMTKTagScanner::Pointer scanner = mitk::DICOMDCMTKTagScanner::New();
mitk::DICOMTag SOPInstanceUID(0x0008, 0x0016);
mitk::StringList relevantFiles;
relevantFiles.push_back(path);
scanner->AddTag(SOPInstanceUID);
scanner->SetInputFiles(relevantFiles);
scanner->Scan();
mitk::DICOMTagCache::Pointer tagCache = scanner->GetScanCache();
mitk::DICOMImageFrameList imageFrameList = mitk::ConvertToDICOMImageFrameList(tagCache->GetFrameInfoList());
if (imageFrameList.empty())
return false;
mitk::DICOMImageFrameInfo *firstFrame = imageFrameList.begin()->GetPointer();
std::string tag_value = tagCache->GetTagValue(firstFrame, SOPInstanceUID).value;
if (tag_value.empty()) {
return false;
}
if (tag_value.compare(UID_TractographyResultsStorage)!=0)
return false;
return true;
}
catch (std::exception& e)
{
MITK_INFO << e.what();
}
return false;
}
DiffusionIOMimeTypes::FiberBundleDicomMimeType* DiffusionIOMimeTypes::FiberBundleDicomMimeType::Clone() const
{
return new FiberBundleDicomMimeType(*this);
}
DiffusionIOMimeTypes::FiberBundleDicomMimeType DiffusionIOMimeTypes::FIBERBUNDLE_DICOM_MIMETYPE()
{
return FiberBundleDicomMimeType();
}
CustomMimeType DiffusionIOMimeTypes::CONNECTOMICS_MIMETYPE()
{
CustomMimeType mimeType(CONNECTOMICS_MIMETYPE_NAME());
std::string category = "Connectomics Networks";
mimeType.SetComment("Connectomics Networks Files");
mimeType.SetCategory(category);
mimeType.AddExtension("cnf");
return mimeType;
}
CustomMimeType DiffusionIOMimeTypes::CONNECTOMICS_MATRIX_MIMETYPE()
{
CustomMimeType mimeType(CONNECTOMICS_MATRIX_MIMETYPE_NAME());
std::string category = "Connectomics Networks export";
mimeType.SetComment("Connectomics Matrix Files");
mimeType.SetCategory(category);
mimeType.AddExtension("mat");
return mimeType;
}
CustomMimeType DiffusionIOMimeTypes::CONNECTOMICS_LIST_MIMETYPE()
{
CustomMimeType mimeType(CONNECTOMICS_LIST_MIMETYPE_NAME());
std::string category = "Connectomics Networks export";
mimeType.SetComment("Connectomics Connection Lists");
mimeType.SetCategory(category);
mimeType.AddExtension("txt");
return mimeType;
}
DiffusionIOMimeTypes::DiffusionImageNrrdMimeType::DiffusionImageNrrdMimeType()
: CustomMimeType(DWI_NRRD_MIMETYPE_NAME())
{
std::string category = "Diffusion Weighted Images";
this->SetCategory(category);
this->SetComment("Diffusion Weighted Images");
this->AddExtension("dwi");
//this->AddExtension("hdwi"); // saving with detached header does not work out of the box
this->AddExtension("nrrd");
}
bool DiffusionIOMimeTypes::DiffusionImageNrrdMimeType::AppliesTo(const std::string &path) const
{
bool canRead( CustomMimeType::AppliesTo(path) );
// fix for bug 18572
// Currently this function is called for writing as well as reading, in that case
// the image information can of course not be read
// This is a bug, this function should only be called for reading.
if( ! itksys::SystemTools::FileExists( path.c_str() ) )
{
return canRead;
}
//end fix for bug 18572
itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New();
// Simple NRRD files should only be considered for this mime type if they contain
// corresponding tags
if( io->CanReadFile(path.c_str()))
{
io->SetFileName(path);
try
{
io->ReadImageInformation();
itk::MetaDataDictionary imgMetaDictionary = io->GetMetaDataDictionary();
std::vector<std::string> imgMetaKeys = imgMetaDictionary.GetKeys();
std::vector<std::string>::const_iterator itKey = imgMetaKeys.begin();
std::string metaString;
for (; itKey != imgMetaKeys.end(); itKey ++)
{
itk::ExposeMetaData<std::string> (imgMetaDictionary, *itKey, metaString);
if (itKey->find("modality") != std::string::npos)
{
if (metaString.find("DWMRI") != std::string::npos)
{
return canRead;
}
}
}
}
catch( const itk::ExceptionObject &e )
{
MITK_ERROR << "ITK Exception: " << e.what();
}
canRead = false;
}
return canRead;
}
DiffusionIOMimeTypes::DiffusionImageNrrdMimeType* DiffusionIOMimeTypes::DiffusionImageNrrdMimeType::Clone() const
{
return new DiffusionImageNrrdMimeType(*this);
}
DiffusionIOMimeTypes::DiffusionImageNrrdMimeType DiffusionIOMimeTypes::DWI_NRRD_MIMETYPE()
{
return DiffusionImageNrrdMimeType();
}
DiffusionIOMimeTypes::DiffusionImageNiftiMimeType::DiffusionImageNiftiMimeType()
: CustomMimeType(DWI_NIFTI_MIMETYPE_NAME())
{
std::string category = "Diffusion Weighted Images";
this->SetCategory(category);
this->SetComment("Diffusion Weighted Images");
this->AddExtension("nii.gz");
this->AddExtension("nii");
}
bool DiffusionIOMimeTypes::DiffusionImageNiftiMimeType::AppliesTo(const std::string &path) const
{
bool canRead(CustomMimeType::AppliesTo(path));
// fix for bug 18572
// Currently this function is called for writing as well as reading, in that case
// the image information can of course not be read
// This is a bug, this function should only be called for reading.
if (!itksys::SystemTools::FileExists(path.c_str()))
{
return canRead;
}
//end fix for bug 18572
std::string ext = this->GetExtension(path);
ext = itksys::SystemTools::LowerCase(ext);
// Nifti files should only be considered for this mime type if they are
// accompanied by bvecs and bvals files defining the diffusion information
if (ext == ".nii" || ext == ".nii.gz")
{
std::string base_path = itksys::SystemTools::GetFilenamePath(path);
std::string base = this->GetFilenameWithoutExtension(path);
std::string filename = base;
if (!base_path.empty())
{
base = base_path + "/" + base;
base_path += "/";
}
if (itksys::SystemTools::FileExists(std::string(base + ".bvec").c_str())
&& itksys::SystemTools::FileExists(std::string(base + ".bval").c_str())
)
{
return canRead;
}
if (itksys::SystemTools::FileExists(std::string(base + ".bvecs").c_str())
&& itksys::SystemTools::FileExists(std::string(base + ".bvals").c_str())
)
{
return canRead;
}
// hack for HCP data
if ( filename=="data" && itksys::SystemTools::FileExists(std::string(base_path + "bvec").c_str()) && itksys::SystemTools::FileExists(std::string(base_path + "bval").c_str()) )
{
return canRead;
}
if ( filename=="data" && itksys::SystemTools::FileExists(std::string(base_path + "bvecs").c_str()) && itksys::SystemTools::FileExists(std::string(base_path + "bvals").c_str()) )
{
return canRead;
}
canRead = false;
}
return canRead;
}
DiffusionIOMimeTypes::DiffusionImageNiftiMimeType* DiffusionIOMimeTypes::DiffusionImageNiftiMimeType::Clone() const
{
return new DiffusionImageNiftiMimeType(*this);
}
DiffusionIOMimeTypes::DiffusionImageNiftiMimeType DiffusionIOMimeTypes::DWI_NIFTI_MIMETYPE()
{
return DiffusionImageNiftiMimeType();
}
DiffusionIOMimeTypes::DiffusionImageDicomMimeType::DiffusionImageDicomMimeType()
: CustomMimeType(DWI_DICOM_MIMETYPE_NAME())
{
std::string category = "Diffusion Weighted Images";
this->SetCategory(category);
this->SetComment("Diffusion Weighted Images");
this->AddExtension("gdcm");
this->AddExtension("dcm");
this->AddExtension("DCM");
this->AddExtension("dc3");
this->AddExtension("DC3");
this->AddExtension("ima");
this->AddExtension("img");
}
bool DiffusionIOMimeTypes::DiffusionImageDicomMimeType::AppliesTo(const std::string &path) const
{
itk::GDCMImageIO::Pointer gdcmIO = itk::GDCMImageIO::New();
bool canRead = gdcmIO->CanReadFile(path.c_str());
if (!canRead)
return canRead;
mitk::DICOMDCMTKTagScanner::Pointer scanner = mitk::DICOMDCMTKTagScanner::New();
mitk::DICOMTag ImageTypeTag(0x0008, 0x0008);
mitk::DICOMTag SeriesDescriptionTag(0x0008, 0x103E);
mitk::StringList relevantFiles;
relevantFiles.push_back(path);
scanner->AddTag(ImageTypeTag);
scanner->AddTag(SeriesDescriptionTag);
scanner->SetInputFiles(relevantFiles);
scanner->Scan();
mitk::DICOMTagCache::Pointer tagCache = scanner->GetScanCache();
mitk::DICOMImageFrameList imageFrameList = mitk::ConvertToDICOMImageFrameList(tagCache->GetFrameInfoList());
mitk::DICOMImageFrameInfo *firstFrame = imageFrameList.begin()->GetPointer();
std::string byteString = tagCache->GetTagValue(firstFrame, ImageTypeTag).value;
if (byteString.empty())
return false;
std::string byteString2 = tagCache->GetTagValue(firstFrame, SeriesDescriptionTag).value;
if (byteString2.empty())
return false;
if (byteString.find("DIFFUSION")==std::string::npos &&
byteString2.find("diff")==std::string::npos &&
byteString2.find("DWI")==std::string::npos)
return false;
return canRead;
}
DiffusionIOMimeTypes::DiffusionImageDicomMimeType* DiffusionIOMimeTypes::DiffusionImageDicomMimeType::Clone() const
{
return new DiffusionImageDicomMimeType(*this);
}
DiffusionIOMimeTypes::DiffusionImageDicomMimeType DiffusionIOMimeTypes::DWI_DICOM_MIMETYPE()
{
return DiffusionImageDicomMimeType();
}
DiffusionIOMimeTypes::PeakImageMimeType::PeakImageMimeType() : CustomMimeType(PEAK_MIMETYPE_NAME())
{
std::string category = "Peak Image";
this->SetCategory(category);
this->SetComment("Peak Image");
this->AddExtension("nrrd");
this->AddExtension("nii");
this->AddExtension("nii.gz");
this->AddExtension("peak");
}
bool DiffusionIOMimeTypes::PeakImageMimeType::AppliesTo(const std::string &path) const
{
std::string ext = itksys::SystemTools::GetFilenameExtension(path);
if (ext==".peak")
return true;
try
{
itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New();
if ( io->CanReadFile( path.c_str() ) )
{
io->SetFileName( path.c_str() );
io->ReadImageInformation();
if ( io->GetPixelType() == itk::ImageIOBase::SCALAR && io->GetNumberOfDimensions()==4 && io->GetDimensions(3)%3==0)
return true;
}
}
catch(...)
{}
try
{
itk::NiftiImageIO::Pointer io = itk::NiftiImageIO::New();
if ( io->CanReadFile( path.c_str() ) )
{
io->SetFileName( path.c_str() );
io->ReadImageInformation();
if ( io->GetPixelType() == itk::ImageIOBase::SCALAR && io->GetNumberOfDimensions()==4 && io->GetDimensions(3)%3==0)
return true;
}
}
catch(...)
{}
return false;
}
DiffusionIOMimeTypes::PeakImageMimeType* DiffusionIOMimeTypes::PeakImageMimeType::Clone() const
{
return new PeakImageMimeType(*this);
}
DiffusionIOMimeTypes::PeakImageMimeType DiffusionIOMimeTypes::PEAK_MIMETYPE()
{
return PeakImageMimeType();
}
DiffusionIOMimeTypes::SHImageMimeType::SHImageMimeType() : CustomMimeType(SH_MIMETYPE_NAME())
{
std::string category = "SH Image";
this->SetCategory(category);
this->SetComment("SH Image");
this->AddExtension("nii.gz");
this->AddExtension("nii");
this->AddExtension("nrrd");
this->AddExtension("shi");
}
bool DiffusionIOMimeTypes::SHImageMimeType::AppliesTo(const std::string &path) const
{
std::string ext = itksys::SystemTools::GetFilenameExtension(path);
if (ext==".shi")
return true;
{
try
{
itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New();
if (io->CanReadFile(path.c_str()))
{
io->SetFileName(path.c_str());
io->ReadImageInformation();
if (io->GetPixelType() == itk::ImageIOBase::SCALAR && io->GetNumberOfDimensions() == 4)
{
switch (io->GetDimensions(3))
{
case 6:
return true;
break;
case 15:
return true;
break;
case 28:
return true;
break;
case 45:
return true;
break;
case 66:
return true;
break;
case 91:
return true;
break;
default:
return false;
}
}
}
}
catch(...)
{}
}
{
itk::NiftiImageIO::Pointer io = itk::NiftiImageIO::New();
if ( io->CanReadFile( path.c_str() ) )
{
io->SetFileName( path.c_str() );
io->ReadImageInformation();
if ( io->GetPixelType() == itk::ImageIOBase::SCALAR && io->GetNumberOfDimensions()==4)
{
switch (io->GetDimensions(3))
{
case 6:
return true;
break;
case 15:
return true;
break;
case 28:
return true;
break;
case 45:
return true;
break;
case 66:
return true;
break;
case 91:
return true;
break;
default :
return false;
}
}
}
}
return false;
}
DiffusionIOMimeTypes::SHImageMimeType* DiffusionIOMimeTypes::SHImageMimeType::Clone() const
{
return new SHImageMimeType(*this);
}
DiffusionIOMimeTypes::SHImageMimeType DiffusionIOMimeTypes::SH_MIMETYPE()
{
return SHImageMimeType();
}
CustomMimeType DiffusionIOMimeTypes::DTI_MIMETYPE()
{
CustomMimeType mimeType(DTI_MIMETYPE_NAME());
std::string category = "Tensor Image";
mimeType.SetComment("Diffusion Tensor Image");
mimeType.SetCategory(category);
mimeType.AddExtension("dti");
return mimeType;
}
CustomMimeType DiffusionIOMimeTypes::ODF_MIMETYPE()
{
CustomMimeType mimeType(ODF_MIMETYPE_NAME());
std::string category = "ODF Image";
mimeType.SetComment("Diffusion ODF Image");
mimeType.SetCategory(category);
mimeType.AddExtension("odf");
mimeType.AddExtension("qbi"); // legacy support
return mimeType;
}
// Names
std::string DiffusionIOMimeTypes::FIBERBUNDLE_VTK_MIMETYPE_NAME()
{
static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".FiberBundle.vtk";
return name;
}
std::string DiffusionIOMimeTypes::FIBERBUNDLE_TCK_MIMETYPE_NAME()
{
static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".FiberBundle.tck";
return name;
}
std::string DiffusionIOMimeTypes::FIBERBUNDLE_TRK_MIMETYPE_NAME()
{
static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".FiberBundle.trk";
return name;
}
std::string DiffusionIOMimeTypes::FIBERBUNDLE_DICOM_MIMETYPE_NAME()
{
static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".FiberBundle.dcm";
return name;
}
std::string DiffusionIOMimeTypes::CONNECTOMICS_MIMETYPE_NAME()
{
static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".cnf";
return name;
}
std::string DiffusionIOMimeTypes::CONNECTOMICS_MATRIX_MIMETYPE_NAME()
{
static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".mat";
return name;
}
std::string DiffusionIOMimeTypes::CONNECTOMICS_LIST_MIMETYPE_NAME()
{
static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".txt";
return name;
}
std::string DiffusionIOMimeTypes::PLANARFIGURECOMPOSITE_MIMETYPE_NAME()
{
static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".pfc";
return name;
}
std::string DiffusionIOMimeTypes::TRACTOGRAPHYFOREST_MIMETYPE_NAME()
{
static std::string name = IOMimeTypes::DEFAULT_BASE_NAME() + ".rf";
return name;
}
std::string DiffusionIOMimeTypes::PEAK_MIMETYPE_NAME()
{
static std::string name ="ODF_PEAKS";
return name;
}
std::string DiffusionIOMimeTypes::DWI_NRRD_MIMETYPE_NAME()
{
static std::string name = "DWI_NRRD";
return name;
}
std::string DiffusionIOMimeTypes::DWI_NIFTI_MIMETYPE_NAME()
{
static std::string name = "DWI_NIFTI";
return name;
}
std::string DiffusionIOMimeTypes::DWI_DICOM_MIMETYPE_NAME()
{
static std::string name = "DWI_DICOM";
return name;
}
std::string DiffusionIOMimeTypes::DTI_MIMETYPE_NAME()
{
static std::string name = "DT_IMAGE";
return name;
}
std::string DiffusionIOMimeTypes::ODF_MIMETYPE_NAME()
{
static std::string name = "ODF_IMAGE";
return name;
}
std::string DiffusionIOMimeTypes::SH_MIMETYPE_NAME()
{
static std::string name = "SH_IMAGE";
return name;
}
// Descriptions
std::string DiffusionIOMimeTypes::FIBERBUNDLE_MIMETYPE_DESCRIPTION()
{
static std::string description = "Fiberbundles";
return description;
}
std::string DiffusionIOMimeTypes::CONNECTOMICS_MIMETYPE_DESCRIPTION()
{
static std::string description = "Connectomics Networks";
return description;
}
std::string DiffusionIOMimeTypes::PLANARFIGURECOMPOSITE_MIMETYPE_DESCRIPTION()
{
static std::string description = "Planar Figure Composite";
return description;
}
std::string DiffusionIOMimeTypes::TRACTOGRAPHYFOREST_MIMETYPE_DESCRIPTION()
{
static std::string description = "Tractography Forest";
return description;
}
std::string DiffusionIOMimeTypes::PEAK_MIMETYPE_DESCRIPTION()
{
static std::string description = "Peak Image";
return description;
}
std::string DiffusionIOMimeTypes::DWI_NRRD_MIMETYPE_DESCRIPTION()
{
static std::string description = "Diffusion Weighted Images";
return description;
}
std::string DiffusionIOMimeTypes::DWI_NIFTI_MIMETYPE_DESCRIPTION()
{
static std::string description = "Diffusion Weighted Images";
return description;
}
std::string DiffusionIOMimeTypes::DWI_DICOM_MIMETYPE_DESCRIPTION()
{
static std::string description = "Diffusion Weighted Images";
return description;
}
std::string DiffusionIOMimeTypes::DTI_MIMETYPE_DESCRIPTION()
{
static std::string description = "Diffusion Tensor Image";
return description;
}
std::string DiffusionIOMimeTypes::ODF_MIMETYPE_DESCRIPTION()
{
static std::string description = "ODF Image";
return description;
}
std::string DiffusionIOMimeTypes::SH_MIMETYPE_DESCRIPTION()
{
static std::string description = "SH Image";
return description;
}
}
diff --git a/Modules/DiffusionIO/mitkDiffusionIOMimeTypes.h b/Modules/DiffusionIO/mitkDiffusionIOMimeTypes.h
index 0be13c4..2745d36 100644
--- a/Modules/DiffusionIO/mitkDiffusionIOMimeTypes.h
+++ b/Modules/DiffusionIO/mitkDiffusionIOMimeTypes.h
@@ -1,156 +1,156 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKDiffusionIOMimeTypes_H
#define MITKDiffusionIOMimeTypes_H
#include "mitkCustomMimeType.h"
#include <string>
namespace mitk {
class DiffusionIOMimeTypes
{
public:
class DiffusionImageNrrdMimeType : public CustomMimeType
{
public:
DiffusionImageNrrdMimeType();
bool AppliesTo(const std::string &path) const override;
DiffusionImageNrrdMimeType* Clone() const override;
};
class DiffusionImageNiftiMimeType : public CustomMimeType
{
public:
DiffusionImageNiftiMimeType();
bool AppliesTo(const std::string &path) const override;
DiffusionImageNiftiMimeType* Clone() const override;
};
// Get all Diffusion Mime Types
static std::vector<CustomMimeType*> Get();
class DiffusionImageDicomMimeType : public CustomMimeType
{
public:
DiffusionImageDicomMimeType();
bool AppliesTo(const std::string &path) const override;
DiffusionImageDicomMimeType* Clone() const override;
};
class PeakImageMimeType : public CustomMimeType
{
public:
PeakImageMimeType();
bool AppliesTo(const std::string &path) const override;
PeakImageMimeType* Clone() const override;
};
class SHImageMimeType : public CustomMimeType
{
public:
SHImageMimeType();
bool AppliesTo(const std::string &path) const override;
SHImageMimeType* Clone() const override;
};
// ------------------------------ VTK formats ----------------------------------
static CustomMimeType FIBERBUNDLE_VTK_MIMETYPE();
static std::string FIBERBUNDLE_VTK_MIMETYPE_NAME();
static std::string FIBERBUNDLE_MIMETYPE_DESCRIPTION();
// ------------------------------ MRtrix formats ----------------------------------
static CustomMimeType FIBERBUNDLE_TCK_MIMETYPE();
static std::string FIBERBUNDLE_TCK_MIMETYPE_NAME();
// ------------------------------ TrackVis formats ----------------------------------
static CustomMimeType FIBERBUNDLE_TRK_MIMETYPE();
static std::string FIBERBUNDLE_TRK_MIMETYPE_NAME();
// ------------------------------ DICOM formats ----------------------------------
class FiberBundleDicomMimeType : public CustomMimeType
{
public:
FiberBundleDicomMimeType();
bool AppliesTo(const std::string &path) const override;
FiberBundleDicomMimeType* Clone() const override;
};
static FiberBundleDicomMimeType FIBERBUNDLE_DICOM_MIMETYPE();
static std::string FIBERBUNDLE_DICOM_MIMETYPE_NAME();
// ------------------------- Image formats (ITK based) --------------------------
static DiffusionImageNrrdMimeType DWI_NRRD_MIMETYPE();
static DiffusionImageNiftiMimeType DWI_NIFTI_MIMETYPE();
static DiffusionImageDicomMimeType DWI_DICOM_MIMETYPE();
static PeakImageMimeType PEAK_MIMETYPE();
static CustomMimeType DTI_MIMETYPE(); // dti
static CustomMimeType ODF_MIMETYPE(); // odf, qbi
static SHImageMimeType SH_MIMETYPE(); // spherical harmonics coefficients
static std::string PEAK_MIMETYPE_NAME();
static std::string DWI_NRRD_MIMETYPE_NAME();
static std::string DWI_NIFTI_MIMETYPE_NAME();
static std::string DWI_DICOM_MIMETYPE_NAME();
static std::string DTI_MIMETYPE_NAME();
static std::string ODF_MIMETYPE_NAME();
static std::string SH_MIMETYPE_NAME();
static std::string PEAK_MIMETYPE_DESCRIPTION();
static std::string DWI_NRRD_MIMETYPE_DESCRIPTION();
static std::string DWI_NIFTI_MIMETYPE_DESCRIPTION();
static std::string DWI_DICOM_MIMETYPE_DESCRIPTION();
static std::string DTI_MIMETYPE_DESCRIPTION();
static std::string ODF_MIMETYPE_DESCRIPTION();
static std::string SH_MIMETYPE_DESCRIPTION();
// ------------------------------ MITK formats ----------------------------------
static CustomMimeType CONNECTOMICS_MIMETYPE(); // cnf
static CustomMimeType CONNECTOMICS_MATRIX_MIMETYPE(); // mat
static CustomMimeType CONNECTOMICS_LIST_MIMETYPE(); // txt
static std::string CONNECTOMICS_MIMETYPE_NAME();
static std::string CONNECTOMICS_MATRIX_MIMETYPE_NAME();
static std::string CONNECTOMICS_LIST_MIMETYPE_NAME();
static std::string CONNECTOMICS_MIMETYPE_DESCRIPTION();
static CustomMimeType PLANARFIGURECOMPOSITE_MIMETYPE();
static std::string PLANARFIGURECOMPOSITE_MIMETYPE_NAME();
static std::string PLANARFIGURECOMPOSITE_MIMETYPE_DESCRIPTION();
static CustomMimeType TRACTOGRAPHYFOREST_MIMETYPE();
static std::string TRACTOGRAPHYFOREST_MIMETYPE_NAME();
static std::string TRACTOGRAPHYFOREST_MIMETYPE_DESCRIPTION();
private:
// purposely not implemented
DiffusionIOMimeTypes();
DiffusionIOMimeTypes(const DiffusionIOMimeTypes&);
};
}
#endif // MITKDiffusionIOMimeTypes_H
diff --git a/Modules/DiffusionIO/mitkDiffusionServiceActivator.cpp b/Modules/DiffusionIO/mitkDiffusionServiceActivator.cpp
index 30e1a21..25e2de2 100644
--- a/Modules/DiffusionIO/mitkDiffusionServiceActivator.cpp
+++ b/Modules/DiffusionIO/mitkDiffusionServiceActivator.cpp
@@ -1,204 +1,204 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <usModuleActivator.h>
#include <usModuleContext.h>
#include <mitkFiberBundleVtkReader.h>
#include <mitkFiberBundleTckReader.h>
#include <mitkFiberBundleTrackVisReader.h>
#include <mitkConnectomicsNetworkReader.h>
#include <mitkPlanarFigureCompositeReader.h>
#include <mitkTractographyForestReader.h>
#include <mitkFiberBundleDicomReader.h>
#include <mitkFiberBundleVtkWriter.h>
#include <mitkFiberBundleTrackVisWriter.h>
#include <mitkFiberBundleDicomWriter.h>
#include <mitkConnectomicsNetworkWriter.h>
#include <mitkConnectomicsNetworkCSVWriter.h>
#include <mitkConnectomicsNetworkMatrixWriter.h>
#include <mitkPlanarFigureCompositeWriter.h>
#include <mitkTractographyForestWriter.h>
#include <mitkDiffusionImageNrrdReader.h>
#include <mitkDiffusionImageNiftiReader.h>
#include <mitkDiffusionImageDicomReader.h>
#include <mitkNrrdTensorImageReader.h>
#include <mitkNrrdOdfImageReader.h>
#include <mitkShImageReader.h>
#include <mitkPeakImageReader.h>
#include <mitkDiffusionImageNrrdWriter.h>
#include <mitkDiffusionImageNiftiWriter.h>
#include <mitkNrrdTensorImageWriter.h>
#include <mitkNrrdOdfImageWriter.h>
#include <mitkShImageWriter.h>
#include <mitkDiffusionPropertyHelper.h>
#include <mitkCoreServices.h>
#include <mitkIPropertyDescriptions.h>
#include <mitkIPropertyPersistence.h>
#include "mitkDiffusionIOMimeTypes.h"
namespace mitk
{
/**
\brief Registers reader and writer services.
*/
class DiffusionServiceActivator : public us::ModuleActivator
{
public:
void Load(us::ModuleContext* context) override
{
m_MimeTypes = mitk::DiffusionIOMimeTypes::Get();
for (std::vector<mitk::CustomMimeType*>::const_iterator mimeTypeIter = m_MimeTypes.begin(),
iterEnd = m_MimeTypes.end(); mimeTypeIter != iterEnd; ++mimeTypeIter)
{
us::ServiceProperties props;
mitk::CustomMimeType* mt = *mimeTypeIter;
if (mt->GetName()==mitk::DiffusionIOMimeTypes::FIBERBUNDLE_VTK_MIMETYPE_NAME())
props[ us::ServiceConstants::SERVICE_RANKING() ] = -1;
else if (mt->GetName()==mitk::DiffusionIOMimeTypes::FIBERBUNDLE_TRK_MIMETYPE_NAME())
props[ us::ServiceConstants::SERVICE_RANKING() ] = -2;
else if (mt->GetName()==mitk::DiffusionIOMimeTypes::FIBERBUNDLE_TCK_MIMETYPE_NAME())
props[ us::ServiceConstants::SERVICE_RANKING() ] = -3;
else if (mt->GetName()==mitk::DiffusionIOMimeTypes::FIBERBUNDLE_DICOM_MIMETYPE_NAME())
props[ us::ServiceConstants::SERVICE_RANKING() ] = -4;
else
props[ us::ServiceConstants::SERVICE_RANKING() ] = 10;
context->RegisterService(*mimeTypeIter, props);
}
m_FiberBundleVtkReader = new FiberBundleVtkReader();
m_FiberBundleVtkWriter = new FiberBundleVtkWriter();
m_FiberBundleTrackVisReader = new FiberBundleTrackVisReader();
m_FiberBundleTrackVisWriter = new FiberBundleTrackVisWriter();
m_FiberBundleTckReader = new FiberBundleTckReader();
m_FiberBundleDicomReader = new FiberBundleDicomReader();
m_FiberBundleDicomWriter = new FiberBundleDicomWriter();
m_ConnectomicsNetworkReader = new ConnectomicsNetworkReader();
m_ConnectomicsNetworkWriter = new ConnectomicsNetworkWriter();
m_ConnectomicsNetworkCSVWriter = new ConnectomicsNetworkCSVWriter();
m_ConnectomicsNetworkMatrixWriter = new ConnectomicsNetworkMatrixWriter();
m_PlanarFigureCompositeReader = new PlanarFigureCompositeReader();
m_PlanarFigureCompositeWriter = new PlanarFigureCompositeWriter();
m_TractographyForestReader = new TractographyForestReader();
m_TractographyForestWriter = new TractographyForestWriter();
m_DiffusionImageNrrdReader = new DiffusionImageNrrdReader();
m_DiffusionImageNrrdWriter = new DiffusionImageNrrdWriter();
m_DiffusionImageNiftiReader = new DiffusionImageNiftiReader();
m_DiffusionImageNiftiWriter = new DiffusionImageNiftiWriter();
m_DiffusionImageDicomReader = new DiffusionImageDicomReader();
m_NrrdTensorImageReader = new NrrdTensorImageReader();
m_NrrdOdfImageReader = new NrrdOdfImageReader();
m_PeakImageReader = new PeakImageReader();
m_ShImageReader = new ShImageReader();
m_NrrdTensorImageWriter = new NrrdTensorImageWriter();
m_NrrdOdfImageWriter = new NrrdOdfImageWriter();
m_ShImageWriter = new ShImageWriter();
mitk::DiffusionPropertyHelper::SetupProperties();
}
void Unload(us::ModuleContext*) override
{
for (unsigned int loop(0); loop < m_MimeTypes.size(); ++loop)
{
delete m_MimeTypes.at(loop);
}
delete m_FiberBundleVtkReader;
delete m_FiberBundleTckReader;
delete m_FiberBundleTrackVisReader;
delete m_ConnectomicsNetworkReader;
delete m_PlanarFigureCompositeReader;
delete m_TractographyForestReader;
delete m_FiberBundleDicomReader;
delete m_FiberBundleDicomWriter;
delete m_FiberBundleVtkWriter;
delete m_FiberBundleTrackVisWriter;
delete m_ConnectomicsNetworkWriter;
delete m_ConnectomicsNetworkCSVWriter;
delete m_ConnectomicsNetworkMatrixWriter;
delete m_PlanarFigureCompositeWriter;
delete m_TractographyForestWriter;
delete m_DiffusionImageNrrdReader;
delete m_DiffusionImageNiftiReader;
delete m_DiffusionImageDicomReader;
delete m_NrrdTensorImageReader;
delete m_NrrdOdfImageReader;
delete m_PeakImageReader;
delete m_ShImageReader;
delete m_DiffusionImageNrrdWriter;
delete m_DiffusionImageNiftiWriter;
delete m_NrrdTensorImageWriter;
delete m_NrrdOdfImageWriter;
delete m_ShImageWriter;
}
private:
FiberBundleVtkReader * m_FiberBundleVtkReader;
FiberBundleTckReader * m_FiberBundleTckReader;
FiberBundleTrackVisReader * m_FiberBundleTrackVisReader;
FiberBundleDicomReader * m_FiberBundleDicomReader;
ConnectomicsNetworkReader * m_ConnectomicsNetworkReader;
PlanarFigureCompositeReader* m_PlanarFigureCompositeReader;
TractographyForestReader* m_TractographyForestReader;
FiberBundleDicomWriter * m_FiberBundleDicomWriter;
FiberBundleVtkWriter * m_FiberBundleVtkWriter;
FiberBundleTrackVisWriter * m_FiberBundleTrackVisWriter;
ConnectomicsNetworkWriter * m_ConnectomicsNetworkWriter;
ConnectomicsNetworkCSVWriter * m_ConnectomicsNetworkCSVWriter;
ConnectomicsNetworkMatrixWriter * m_ConnectomicsNetworkMatrixWriter;
PlanarFigureCompositeWriter* m_PlanarFigureCompositeWriter;
TractographyForestWriter* m_TractographyForestWriter;
DiffusionImageNrrdReader * m_DiffusionImageNrrdReader;
DiffusionImageNiftiReader * m_DiffusionImageNiftiReader;
DiffusionImageDicomReader * m_DiffusionImageDicomReader;
NrrdTensorImageReader * m_NrrdTensorImageReader;
NrrdOdfImageReader * m_NrrdOdfImageReader;
PeakImageReader * m_PeakImageReader;
ShImageReader * m_ShImageReader;
DiffusionImageNrrdWriter * m_DiffusionImageNrrdWriter;
DiffusionImageNiftiWriter * m_DiffusionImageNiftiWriter;
NrrdTensorImageWriter * m_NrrdTensorImageWriter;
NrrdOdfImageWriter * m_NrrdOdfImageWriter;
ShImageWriter * m_ShImageWriter;
std::vector<mitk::CustomMimeType*> m_MimeTypes;
};
}
US_EXPORT_MODULE_ACTIVATOR(mitk::DiffusionServiceActivator)
diff --git a/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetric.h b/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetric.h
index 422ab1d..5fd32ab 100644
--- a/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetric.h
+++ b/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetric.h
@@ -1,61 +1,61 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _ClusteringMetric
#define _ClusteringMetric
#include <mitkDiffusionFunctionCollection.h>
namespace mitk
{
/**
* \brief Base class for fiber clustering metrics */
class ClusteringMetric
{
public:
ClusteringMetric()
: m_Scale(1.0)
{}
virtual ~ClusteringMetric(){}
virtual float CalculateDistance(vnl_matrix<float>& s, vnl_matrix<float>& t, bool &flipped) = 0;
float GetScale() const;
void SetScale(float Scale);
protected:
float m_Scale;
};
float ClusteringMetric::GetScale() const
{
return m_Scale;
}
void ClusteringMetric::SetScale(float Scale)
{
m_Scale = Scale;
}
}
#endif
diff --git a/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricAnatomic.h b/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricAnatomic.h
index d761ac0..6654948 100644
--- a/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricAnatomic.h
+++ b/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricAnatomic.h
@@ -1,199 +1,199 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _ClusteringMetricAnatomic
#define _ClusteringMetricAnatomic
#include <mitkClusteringMetric.h>
#include <itkImage.h>
#include <itkImageRegionConstIterator.h>
#include <itkNumericTraits.h>
namespace mitk
{
/**
* \brief Fiber clustering metric based on white matter parcellation histograms along the tracts (Siless et al. https://www.ncbi.nlm.nih.gov/pubmed/29100937) */
class ClusteringMetricAnatomic : public ClusteringMetric
{
public:
typedef itk::Image<short, 3> ItkShortImgType;
ClusteringMetricAnatomic()
: m_Radius(1)
{}
virtual ~ClusteringMetricAnatomic(){}
float CalculateDistance(vnl_matrix<float>& s, vnl_matrix<float>& t, bool &flipped)
{
vnl_matrix<float> hist1; hist1.set_size( (2*m_Radius+1)*(2*m_Radius+1)*(2*m_Radius+1), m_NumLabels ); hist1.fill(0);
vnl_matrix<float> hist2; hist2.set_size( (2*m_Radius+1)*(2*m_Radius+1)*(2*m_Radius+1), m_NumLabels ); hist2.fill(0);
float d_direct = 0;
float d_flipped = 0;
vnl_vector<float> dists_d; dists_d.set_size(s.cols());
vnl_vector<float> dists_f; dists_f.set_size(s.cols());
for (unsigned int i=0; i<s.cols(); ++i)
{
itk::Point<float, 3> p;
p[0] = s[0][i];
p[1] = s[1][i];
p[2] = s[2][i];
GetHistogramAtPoint(p, hist1);
p[0] = t[0][i];
p[1] = t[1][i];
p[2] = t[2][i];
GetHistogramAtPoint(p, hist2);
d_direct += (s.get_column(i)-t.get_column(i)).magnitude();
d_flipped += (s.get_column(i)-t.get_column(s.cols()-i-1)).magnitude();
}
// float eudist = 0;
if (d_direct>d_flipped)
{
flipped = true;
// eudist = d_flipped/s.cols();
}
else
{
flipped = false;
// eudist = d_direct/s.cols();
}
float label_intersection = 0;
for (unsigned int c=0; c<hist1.cols(); ++c)
{
bool l1 = false;
bool l2 = false;
for (unsigned int r=0; r<hist1.rows(); ++r)
{
if (hist1[r][c]>0)
l1 = true;
if (hist2[r][c]>0)
l2 = true;
if (l1 && l2)
{
label_intersection += 1;
break;
}
}
}
float similarity = 0;
if (label_intersection>0)
{
hist1.normalize_rows();
hist2.normalize_rows();
label_intersection /= m_NumLabels;
for (unsigned int l=0; l<hist1.rows(); ++l)
similarity += dot_product( hist1.get_row(l), hist2.get_row(l) );
similarity /= hist1.rows();
similarity *= label_intersection;
}
if (similarity>0)
return m_Scale*0.2/similarity;
else
return 9999;
}
void GetHistogramAtPoint(itk::Point<float, 3>& itkP, vnl_matrix<float>& hist)
{
int parc_idx = 0;
for (auto parc : m_Parcellations)
{
int dir_idx=0;
itk::Index<3> tmp_idx;
itk::Index<3> idx;
parc->TransformPhysicalPointToIndex(itkP, idx);
if (!parc->GetLargestPossibleRegion().IsInside(idx))
continue;
short label = parc->GetPixel(idx);
short S0 = label;
hist[dir_idx][m_LabelMaps.at(parc_idx).at(label)] += 1;
for (int x=-m_Radius; x<=m_Radius; ++x)
for (int y=-m_Radius; y<=m_Radius; ++y)
for (int z=-m_Radius; z<=m_Radius; ++z)
{
if (x==0 && y==0 && z==0)
continue;
++dir_idx;
for (int d=1; d<5; ++d)
{
tmp_idx[0] = idx[0] + x*d;
tmp_idx[1] = idx[1] + y*d;
tmp_idx[2] = idx[2] + z*d;
if (!parc->GetLargestPossibleRegion().IsInside(tmp_idx))
break;
label = parc->GetPixel(tmp_idx);
if (label!=S0)
{
hist[dir_idx][m_LabelMaps.at(parc_idx).at(label)] += 1;
break;
}
}
}
++parc_idx;
}
}
void SetParcellations(const std::vector<ItkShortImgType::Pointer> &Parcellations)
{
m_Parcellations = Parcellations;
m_NumLabels = 0;
for (auto parc : m_Parcellations)
{
std::map< short, short > label_map;
itk::ImageRegionConstIterator<ItkShortImgType> it(parc, parc->GetLargestPossibleRegion());
while (!it.IsAtEnd())
{
if (label_map.count(it.Get())==0)
{
label_map.insert( std::pair< short, short >( it.Get(), m_NumLabels) );
++m_NumLabels;
}
++it;
}
m_LabelMaps.push_back(label_map);
}
}
protected:
std::vector< ItkShortImgType::Pointer > m_Parcellations;
short m_NumLabels;
int m_Radius;
std::vector< std::map< short, short > > m_LabelMaps;
};
}
#endif
diff --git a/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricEuclideanMax.h b/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricEuclideanMax.h
index 62cfb91..8762abc 100644
--- a/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricEuclideanMax.h
+++ b/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricEuclideanMax.h
@@ -1,71 +1,71 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _ClusteringMetricEuMax
#define _ClusteringMetricEuMax
#include <mitkClusteringMetric.h>
namespace mitk
{
/**
* \brief Fiber clustering metric based on the euclidean maximum distance between tracts */
class ClusteringMetricEuclideanMax : public ClusteringMetric
{
public:
ClusteringMetricEuclideanMax(){}
virtual ~ClusteringMetricEuclideanMax(){}
float CalculateDistance(vnl_matrix<float>& s, vnl_matrix<float>& t, bool &flipped)
{
float d_direct = 0;
float d_flipped = 0;
vnl_vector<float> dists_d; dists_d.set_size(s.cols());
vnl_vector<float> dists_f; dists_f.set_size(s.cols());
for (unsigned int i=0; i<s.cols(); ++i)
{
dists_d[i] = (s.get_column(i)-t.get_column(i)).magnitude();
d_direct += dists_d[i];
dists_f[i] = (s.get_column(i)-t.get_column(s.cols()-i-1)).magnitude();
d_flipped += dists_f[i];
}
if (d_direct>d_flipped)
{
float d = dists_f.max_value();
flipped = true;
return m_Scale*d;
}
float d = dists_d.max_value();
flipped = false;
return m_Scale*d;
}
protected:
};
}
#endif
diff --git a/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricEuclideanMean.h b/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricEuclideanMean.h
index c786f9b..6ca9b8d 100644
--- a/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricEuclideanMean.h
+++ b/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricEuclideanMean.h
@@ -1,62 +1,62 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _ClusteringMetricEuMean
#define _ClusteringMetricEuMean
#include <mitkClusteringMetric.h>
namespace mitk
{
/**
* \brief Fiber clustering metric based on the mean euclidean distance between tracts */
class ClusteringMetricEuclideanMean : public ClusteringMetric
{
public:
ClusteringMetricEuclideanMean(){}
virtual ~ClusteringMetricEuclideanMean(){}
float CalculateDistance(vnl_matrix<float>& s, vnl_matrix<float>& t, bool &flipped)
{
float d_direct = 0;
float d_flipped = 0;
for (unsigned int i=0; i<s.cols(); ++i)
{
d_direct += (s.get_column(i)-t.get_column(i)).magnitude();
d_flipped += (s.get_column(i)-t.get_column(s.cols()-i-1)).magnitude();
}
if (d_direct>d_flipped)
{
flipped = true;
return m_Scale*d_flipped/s.cols();
}
flipped = false;
return m_Scale*d_direct/s.cols();
}
protected:
};
}
#endif
diff --git a/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricEuclideanStd.h b/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricEuclideanStd.h
index f71c2f6..c1a6f62 100644
--- a/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricEuclideanStd.h
+++ b/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricEuclideanStd.h
@@ -1,77 +1,77 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _ClusteringMetricEuStd
#define _ClusteringMetricEuStd
#include <mitkClusteringMetric.h>
namespace mitk
{
/**
* \brief Fiber clustering metric based on the euclidean distance between tracts and the corresponding standard deviation of the distances */
class ClusteringMetricEuclideanStd : public ClusteringMetric
{
public:
ClusteringMetricEuclideanStd(){}
virtual ~ClusteringMetricEuclideanStd(){}
float CalculateDistance(vnl_matrix<float>& s, vnl_matrix<float>& t, bool &flipped)
{
float d_direct = 0;
float d_flipped = 0;
vnl_vector<float> dists_d; dists_d.set_size(s.cols());
vnl_vector<float> dists_f; dists_f.set_size(s.cols());
for (unsigned int i=0; i<s.cols(); ++i)
{
dists_d[i] = (s.get_column(i)-t.get_column(i)).magnitude();
d_direct += dists_d[i];
dists_f[i] = (s.get_column(i)-t.get_column(s.cols()-i-1)).magnitude();
d_flipped += dists_f[i];
}
if (d_direct>d_flipped)
{
float d = d_flipped/s.cols();
dists_f -= d;
d += dists_f.magnitude();
flipped = true;
return m_Scale*d/2;
}
float d = d_direct/s.cols();
dists_d -= d;
d += dists_d.magnitude();
flipped = false;
return m_Scale*d/2;
}
protected:
};
}
#endif
diff --git a/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricInnerAngles.h b/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricInnerAngles.h
index a5f52f7..2bd9613 100644
--- a/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricInnerAngles.h
+++ b/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricInnerAngles.h
@@ -1,125 +1,125 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _ClusteringMetricInnerAngles
#define _ClusteringMetricInnerAngles
#include <mitkClusteringMetric.h>
namespace mitk
{
/**
* \brief Fiber clustering metric based on the angles between certain parts of the streamline */
class ClusteringMetricInnerAngles : public ClusteringMetric
{
public:
ClusteringMetricInnerAngles(){}
virtual ~ClusteringMetricInnerAngles(){}
float CalculateDistance(vnl_matrix<float>& s, vnl_matrix<float>& t, bool &flipped)
{
int p1 = 0;
int p2 = s.cols()/4;
int p3 = s.cols()/2;
int p4 = 3*s.cols()/4;
int p5 = s.cols()-1;
float a1_s = 0;
float a2_s = 0;
float a3_s = 0;
float a1_t = 0;
float a2_t = 0;
float a3_t = 0;
{
vnl_vector<float> v1 = s.get_column(p1)-s.get_column(p2); v1.normalize();
vnl_vector<float> v2 = s.get_column(p3)-s.get_column(p2); v2.normalize();
a1_s = dot_product(v1,v2);
a1_s = std::acos( a1_s ) * 180.0/itk::Math::pi;
}
{
vnl_vector<float> v1 = s.get_column(p1)-s.get_column(p3); v1.normalize();
vnl_vector<float> v2 = s.get_column(p5)-s.get_column(p3); v2.normalize();
a2_s = dot_product(v1,v2);
a2_s = std::acos( a2_s ) * 180.0/itk::Math::pi;
}
{
vnl_vector<float> v1 = s.get_column(p3)-s.get_column(p4); v1.normalize();
vnl_vector<float> v2 = s.get_column(p5)-s.get_column(p4); v2.normalize();
a3_s = dot_product(v1,v2);
a3_s = std::acos( a3_s ) * 180.0/itk::Math::pi;
}
//
{
vnl_vector<float> v1 = t.get_column(p1)-t.get_column(p2); v1.normalize();
vnl_vector<float> v2 = t.get_column(p3)-t.get_column(p2); v2.normalize();
a1_t = dot_product(v1,v2);
a1_t = std::acos( a1_t ) * 180.0/itk::Math::pi;
}
{
vnl_vector<float> v1 = t.get_column(p1)-t.get_column(p3); v1.normalize();
vnl_vector<float> v2 = t.get_column(p5)-t.get_column(p3); v2.normalize();
a2_t = dot_product(v1,v2);
a2_t = std::acos( a2_t ) * 180.0/itk::Math::pi;
}
{
vnl_vector<float> v1 = t.get_column(p3)-t.get_column(p4); v1.normalize();
vnl_vector<float> v2 = t.get_column(p5)-t.get_column(p4); v2.normalize();
a3_t = dot_product(v1,v2);
a3_t = std::acos( a3_t ) * 180.0/itk::Math::pi;
}
float d_direct = 0;
float d_flipped = 0;
int inc = s.cols()/4;
for (unsigned int i=0; i<s.cols(); i += inc)
{
d_direct += (s.get_column(i)-t.get_column(i)).magnitude();
d_flipped += (s.get_column(i)-t.get_column(s.cols()-i-1)).magnitude();
}
if (d_direct>d_flipped)
{
flipped = true;
float d1 = std::fabs(a1_s-a3_t);
float d2 = std::fabs(a2_s-a2_t);
float d3 = std::fabs(a3_s-a1_t);
return m_Scale * std::max( d1, std::max(d2,d3) );
}
flipped = false;
float d1 = std::fabs(a1_s-a1_t);
float d2 = std::fabs(a2_s-a2_t);
float d3 = std::fabs(a3_s-a3_t);
return m_Scale * std::max( d1, std::max(d2,d3) );
}
protected:
};
}
#endif
diff --git a/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricLength.h b/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricLength.h
index e6bfc3e..b123059 100644
--- a/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricLength.h
+++ b/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricLength.h
@@ -1,72 +1,72 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _ClusteringMetricLength
#define _ClusteringMetricLength
#include <mitkClusteringMetric.h>
namespace mitk
{
/**
* \brief Fiber clustering metric based on the angles between certain parts of the streamline */
class ClusteringMetricLength : public ClusteringMetric
{
public:
ClusteringMetricLength(){}
virtual ~ClusteringMetricLength(){}
float CalculateDistance(vnl_matrix<float>& s, vnl_matrix<float>& t, bool &flipped)
{
float l1 = 0;
float l2 = 0;
float d_direct = 0;
float d_flipped = 0;
int inc = s.cols()/4;
for (unsigned int i=0; i<s.cols(); i += inc)
{
d_direct += (s.get_column(i)-t.get_column(i)).magnitude();
d_flipped += (s.get_column(i)-t.get_column(s.cols()-i-1)).magnitude();
if (i<s.cols()-1)
{
l1 += (s.get_column(i+1)-s.get_column(i)).magnitude();
l2 += (t.get_column(i+1)-t.get_column(i)).magnitude();
}
}
if (d_direct>d_flipped)
{
flipped = true;
return m_Scale * std::fabs(l1-l2);
}
flipped = false;
return m_Scale * std::fabs(l1-l2);
}
protected:
};
}
#endif
diff --git a/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricScalarMap.h b/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricScalarMap.h
index 9ca37cf..4e53457 100644
--- a/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricScalarMap.h
+++ b/Modules/FiberTracking/Algorithms/ClusteringMetrics/mitkClusteringMetricScalarMap.h
@@ -1,132 +1,132 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _ClusteringMetricScalarMap
#define _ClusteringMetricScalarMap
#include <mitkClusteringMetric.h>
#include <itkImage.h>
#include <itkImageRegionConstIterator.h>
#include <itkNumericTraits.h>
#include <mitkTrackingDataHandler.h>
namespace mitk
{
/**
* \brief Fiber clustering metric based on the scalar image values along a tract */
class ClusteringMetricScalarMap : public ClusteringMetric
{
public:
typedef itk::Image<float, 3> ItkFloatImgType;
ClusteringMetricScalarMap()
{
m_Interpolator = itk::LinearInterpolateImageFunction< ItkFloatImgType, float >::New();
this->m_Scale = 30;
}
virtual ~ClusteringMetricScalarMap(){}
float CalculateDistance(vnl_matrix<float>& s, vnl_matrix<float>& t, bool &flipped)
{
float d_direct = 0;
float d_flipped = 0;
float map_distance = 0;
vnl_vector<float> dists_d; dists_d.set_size(s.cols());
vnl_vector<float> dists_f; dists_f.set_size(s.cols());
int inc = s.cols()/4;
for (unsigned int i=0; i<s.cols(); i += inc)
{
d_direct += (s.get_column(i)-t.get_column(i)).magnitude();
d_flipped += (s.get_column(i)-t.get_column(s.cols()-i-1)).magnitude();
}
if (d_direct>d_flipped)
{
flipped = true;
for (unsigned int i=0; i<s.cols(); ++i)
{
itk::Point<float, 3> p;
p[0] = s[0][i];
p[1] = s[1][i];
p[2] = s[2][i];
vnl_vector<float> vals1 = GetImageValuesAtPoint(p);
p[0] = t[0][s.cols()-i-1];
p[1] = t[1][s.cols()-i-1];
p[2] = t[2][s.cols()-i-1];
vnl_vector<float> vals2 = GetImageValuesAtPoint(p);
map_distance += (vals1-vals2).magnitude();
}
}
else
{
flipped = false;
for (unsigned int i=0; i<s.cols(); ++i)
{
itk::Point<float, 3> p;
p[0] = s[0][i];
p[1] = s[1][i];
p[2] = s[2][i];
vnl_vector<float> vals1 = GetImageValuesAtPoint(p);
p[0] = t[0][i];
p[1] = t[1][i];
p[2] = t[2][i];
vnl_vector<float> vals2 = GetImageValuesAtPoint(p);
map_distance += (vals1-vals2).magnitude();
}
}
return m_Scale*map_distance;
}
vnl_vector<float> GetImageValuesAtPoint(itk::Point<float, 3>& itkP)
{
vnl_vector<float> vals; vals.set_size(m_ScalarMaps.size());
int c = 0;
for (auto map : m_ScalarMaps)
{
m_Interpolator->SetInputImage(map);
vals[c] = mitk::imv::GetImageValue<float>(itkP, true, m_Interpolator);
++c;
}
return vals;
}
void SetImages(const std::vector<ItkFloatImgType::Pointer> &Parcellations)
{
m_ScalarMaps = Parcellations;
}
protected:
std::vector< ItkFloatImgType::Pointer > m_ScalarMaps;
itk::LinearInterpolateImageFunction< ItkFloatImgType, float >::Pointer m_Interpolator;
};
}
#endif
diff --git a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkEnergyComputer.cpp b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkEnergyComputer.cpp
index 71f8d8a..a96835e 100644
--- a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkEnergyComputer.cpp
+++ b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkEnergyComputer.cpp
@@ -1,170 +1,170 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkEnergyComputer.h"
#include <vnl/vnl_copy.h>
#include <itkNumericTraits.h>
using namespace mitk;
EnergyComputer::EnergyComputer(ItkFloatImageType* mask, ParticleGrid* particleGrid, SphereInterpolator* interpolator, ItkRandGenType* randGen)
: m_UseTrilinearInterpolation(true)
{
m_ParticleGrid = particleGrid;
m_RandGen = randGen;
m_SphereInterpolator = interpolator;
m_Mask = mask;
m_ParticleLength = m_ParticleGrid->m_ParticleLength;
m_SquaredParticleLength = m_ParticleLength*m_ParticleLength;
m_Size[0] = mask->GetLargestPossibleRegion().GetSize()[0];
m_Size[1] = mask->GetLargestPossibleRegion().GetSize()[1];
m_Size[2] = mask->GetLargestPossibleRegion().GetSize()[2];
if (m_Size[0]<3 || m_Size[1]<3 || m_Size[2]<3)
m_UseTrilinearInterpolation = false;
m_Spacing[0] = mask->GetSpacing()[0];
m_Spacing[1] = mask->GetSpacing()[1];
m_Spacing[2] = mask->GetSpacing()[2];
// get rotation matrix
vnl_matrix<double> temp = mask->GetDirection().GetVnlMatrix();
vnl_matrix<float> directionMatrix; directionMatrix.set_size(3,3);
vnl_copy(temp, directionMatrix);
vnl_matrix_fixed<float, 3, 3> I = directionMatrix*directionMatrix.transpose();
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
I[i][j] = fabs(I[i][j]);
if(!I.is_identity(0.001))
{
fprintf(stderr,"EnergyComputer: image direction is not a rotation matrix. Tracking not possible!\n");
std::cout << directionMatrix << std::endl;
}
m_RotationMatrix = directionMatrix;
if (ODF_SAMPLING_SIZE != m_SphereInterpolator->nverts)
fprintf(stderr,"EnergyComputer: error during init: data does not match with interpolation scheme\n");
int totsz = m_Size[0]*m_Size[1]*m_Size[2];
m_CumulatedSpatialProbability.resize(totsz + 1, 0.0);
m_ActiveIndices.resize(totsz, 0);
// calculate active voxels and cumulate probabilities
m_NumActiveVoxels = 0;
m_CumulatedSpatialProbability[0] = 0;
for (int x = 0; x < m_Size[0];x++)
for (int y = 0; y < m_Size[1];y++)
for (int z = 0; z < m_Size[2];z++)
{
int idx = x+(y+z*m_Size[1])*m_Size[0];
ItkFloatImageType::IndexType index;
index[0] = x; index[1] = y; index[2] = z;
if (m_Mask->GetPixel(index) > 0.5)
{
m_CumulatedSpatialProbability[m_NumActiveVoxels+1] = m_CumulatedSpatialProbability[m_NumActiveVoxels] + m_Mask->GetPixel(index);
m_ActiveIndices[m_NumActiveVoxels] = idx;
m_NumActiveVoxels++;
}
}
for (int k = 0; k < m_NumActiveVoxels; k++)
m_CumulatedSpatialProbability[k] /= m_CumulatedSpatialProbability[m_NumActiveVoxels];
std::cout << "EnergyComputer: " << m_NumActiveVoxels << " active voxels found" << std::endl;
}
void EnergyComputer::SetParameters(float particleWeight, float particleWidth, float connectionPotential, float curvThres, float inexBalance, float particlePotential)
{
m_ParticleChemicalPotential = particlePotential;
m_ConnectionPotential = connectionPotential;
m_ParticleWeight = particleWeight;
float bal = 1/(1+exp(-inexBalance));
m_ExtStrength = 2*bal;
m_IntStrength = 2*(1-bal)/m_SquaredParticleLength;
m_CurvatureThreshold = curvThres;
float sigma_s = particleWidth;
m_SigmaInv = 1/(2*sigma_s*sigma_s);
}
// draw random position from active voxels
void EnergyComputer::DrawRandomPosition(vnl_vector_fixed<float, 3>& R)
{
float r = static_cast<float>(m_RandGen->GetVariate());
int j;
int rl = 1;
int rh = m_NumActiveVoxels;
while(rh != rl)
{
j = rl + (rh-rl)/2;
if (r < m_CumulatedSpatialProbability[j])
{
rh = j;
continue;
}
if (r > m_CumulatedSpatialProbability[j])
{
rl = j+1;
continue;
}
break;
}
R[0] = m_Spacing[0]*((float)(m_ActiveIndices[rh-1] % m_Size[0]) + m_RandGen->GetVariate());
R[1] = m_Spacing[1]*((float)((m_ActiveIndices[rh-1]/m_Size[0]) % m_Size[1]) + m_RandGen->GetVariate());
R[2] = m_Spacing[2]*((float)(m_ActiveIndices[rh-1]/(m_Size[0]*m_Size[1])) + m_RandGen->GetVariate());
}
// return spatial probability of position
float EnergyComputer::SpatProb(vnl_vector_fixed<float, 3> pos)
{
ItkFloatImageType::IndexType index;
index[0] = floor(pos[0]/m_Spacing[0]);
index[1] = floor(pos[1]/m_Spacing[1]);
index[2] = floor(pos[2]/m_Spacing[2]);
if (m_Mask->GetLargestPossibleRegion().IsInside(index)) // is inside image?
return m_Mask->GetPixel(index);
else
return 0;
}
float EnergyComputer::CalcI0(float x)
{
// BESSEL_APPROXCOEFF[0] = -0.1714;
// BESSEL_APPROXCOEFF[1] = 0.5332;
// BESSEL_APPROXCOEFF[2] = -1.4889;
// BESSEL_APPROXCOEFF[3] = 2.0389;
float y = x*x;
float erg = -0.1714;
erg += y*0.5332;
erg += y*y*-1.4889;
erg += y*y*y*2.0389;
return erg;
}
float EnergyComputer::mexp(float x)
{
return((x>=7.0) ? 0 : ((x>=5.0) ? (-0.0029*x+0.0213) : ((x>=3.0) ? (-0.0215*x+0.1144) : ((x>=2.0) ? (-0.0855*x+0.3064) : ((x>=1.0) ? (-0.2325*x+0.6004) : ((x>=0.5) ? (-0.4773*x+0.8452) : ((x>=0.0) ? (-0.7869*x+1.0000) : 1 )))))));
// return exp(-x);
}
int EnergyComputer::GetNumActiveVoxels()
{
return m_NumActiveVoxels;
}
diff --git a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkEnergyComputer.h b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkEnergyComputer.h
index 472c114..2b2eb99 100644
--- a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkEnergyComputer.h
+++ b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkEnergyComputer.h
@@ -1,85 +1,85 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _ENCOMP
#define _ENCOMP
#include <MitkFiberTrackingExports.h>
#include <itkOrientationDistributionFunction.h>
#include <mitkParticleGrid.h>
#include <mitkSphereInterpolator.h>
#include <itkMersenneTwisterRandomVariateGenerator.h>
using namespace mitk;
/**
* \brief Calculates internal and external energy of the new particle configuration proposal. */
class MITKFIBERTRACKING_EXPORT EnergyComputer
{
public:
typedef itk::Image<float, 3> ItkFloatImageType;
typedef itk::Statistics::MersenneTwisterRandomVariateGenerator ItkRandGenType;
EnergyComputer(ItkFloatImageType* mask, ParticleGrid* particleGrid, SphereInterpolator* interpolator, ItkRandGenType* randGen);
void SetParameters(float particleWeight, float particleWidth, float connectionPotential, float curvThres, float inexBalance, float particlePotential);
// get random position inside mask
void DrawRandomPosition(vnl_vector_fixed<float, 3>& R);
// external energy calculation
virtual float ComputeExternalEnergy(vnl_vector_fixed<float, 3>& R, vnl_vector_fixed<float, 3>& N, Particle* dp) =0;
// internal energy calculation
virtual float ComputeInternalEnergyConnection(Particle *p1,int ep1) = 0;
virtual float ComputeInternalEnergyConnection(Particle *p1,int ep1, Particle *p2, int ep2) = 0;
virtual float ComputeInternalEnergy(Particle *dp) = 0;
int GetNumActiveVoxels();
protected:
vnl_matrix_fixed<float, 3, 3> m_RotationMatrix;
SphereInterpolator* m_SphereInterpolator;
ParticleGrid* m_ParticleGrid;
ItkRandGenType* m_RandGen;
ItkFloatImageType* m_Mask;
vnl_vector_fixed<int, 3> m_Size;
vnl_vector_fixed<float, 3> m_Spacing;
std::vector< float > m_CumulatedSpatialProbability;
std::vector< int > m_ActiveIndices; // indices inside mask
bool m_UseTrilinearInterpolation; // is deactivated if less than 3 image slices are available
int m_NumActiveVoxels; // voxels inside mask
float m_ConnectionPotential; // larger value results in larger energy value -> higher proposal acceptance probability
float m_ParticleChemicalPotential; // larger value results in larger energy value -> higher proposal acceptance probability
float m_SigmaInv;
float m_ParticleWeight; // defines how much one particle contributes to the artificial signal
float m_ExtStrength; // weighting factor for external energy
float m_IntStrength; // weighting factor for internal energy
float m_ParticleLength; // particle length
float m_SquaredParticleLength; // squared particle length
float m_CurvatureThreshold; // maximum angle accepted between two connected particles
float SpatProb(vnl_vector_fixed<float, 3> pos);
float EvaluateOdf(vnl_vector_fixed<float, 3> &pos, vnl_vector_fixed<float, 3> dir);
float CalcI0(float x);
float mexp(float x);
};
#endif
diff --git a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkFiberBuilder.cpp b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkFiberBuilder.cpp
index b80f0a4..1b69d8f 100644
--- a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkFiberBuilder.cpp
+++ b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkFiberBuilder.cpp
@@ -1,138 +1,138 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkFiberBuilder.h"
using namespace mitk;
FiberBuilder::FiberBuilder(ParticleGrid* grid, ItkFloatImageType* image)
{
m_Grid = grid;
m_Image = image;
m_FiberLength = 0;
}
FiberBuilder::~FiberBuilder()
{
}
vtkSmartPointer<vtkPolyData> FiberBuilder::iterate(int minFiberLength)
{
m_VtkCellArray = vtkSmartPointer<vtkCellArray>::New();
m_VtkPoints = vtkSmartPointer<vtkPoints>::New();
int cur_label = 1;
int numFibers = 0;
m_FiberLength = 0;
for (int k = 0; k < m_Grid->m_NumParticles;k++)
{
Particle *dp = m_Grid->GetParticle(k);
if (dp->label == 0)
{
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
dp->label = cur_label;
LabelPredecessors(dp, -1, container);
LabelSuccessors(dp, 1, container);
cur_label++;
if(m_FiberLength >= minFiberLength)
{
m_VtkCellArray->InsertNextCell(container);
numFibers++;
}
m_FiberLength = 0;
}
}
for (int k = 0; k < m_Grid->m_NumParticles;k++)
{
Particle *dp = m_Grid->GetParticle(k);
dp->label = 0;
}
vtkSmartPointer<vtkPolyData> fiberPolyData = vtkSmartPointer<vtkPolyData>::New();
fiberPolyData->SetPoints(m_VtkPoints);
fiberPolyData->SetLines(m_VtkCellArray);
return fiberPolyData;
}
void FiberBuilder::LabelPredecessors(Particle* p, int ep, vtkPolyLine* container)
{
Particle* p2 = nullptr;
if (ep==1)
p2 = m_Grid->GetParticle(p->pID);
else
p2 = m_Grid->GetParticle(p->mID);
if (p2!=nullptr && p2->label==0)
{
p2->label = 1; // assign particle to current fiber
if (p2->pID==p->ID)
LabelPredecessors(p2, -1, container);
else if (p2->mID==p->ID)
LabelPredecessors(p2, 1, container);
else
std::cout << "FiberBuilder: connection inconsistent (LabelPredecessors)" << std::endl;
}
AddPoint(p, container);
}
void FiberBuilder::LabelSuccessors(Particle* p, int ep, vtkPolyLine* container)
{
AddPoint(p, container);
Particle* p2 = nullptr;
if (ep==1)
p2 = m_Grid->GetParticle(p->pID);
else
p2 = m_Grid->GetParticle(p->mID);
if (p2!=nullptr && p2->label==0)
{
p2->label = 1; // assign particle to current fiber
if (p2->pID==p->ID)
LabelSuccessors(p2, -1, container);
else if (p2->mID==p->ID)
LabelSuccessors(p2, 1, container);
else
std::cout << "FiberBuilder: connection inconsistent (LabelPredecessors)" << std::endl;
}
}
void FiberBuilder::AddPoint(Particle *dp, vtkSmartPointer<vtkPolyLine> container)
{
if (dp->label!=1)
return;
dp->label = 2;
itk::ContinuousIndex<float, 3> index;
index[0] = dp->GetPos()[0]/m_Image->GetSpacing()[0]-0.5;
index[1] = dp->GetPos()[1]/m_Image->GetSpacing()[1]-0.5;
index[2] = dp->GetPos()[2]/m_Image->GetSpacing()[2]-0.5;
itk::Point<float> point;
m_Image->TransformContinuousIndexToPhysicalPoint( index, point );
vtkIdType id = m_VtkPoints->InsertNextPoint(point.GetDataPointer());
container->GetPointIds()->InsertNextId(id);
if(container->GetNumberOfPoints()>1)
m_FiberLength += m_LastPoint.EuclideanDistanceTo(point);
m_LastPoint = point;
}
diff --git a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkFiberBuilder.h b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkFiberBuilder.h
index 9e2ea5a..db4d557 100644
--- a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkFiberBuilder.h
+++ b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkFiberBuilder.h
@@ -1,68 +1,68 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _BUILDFIBRES
#define _BUILDFIBRES
// MITK
#include <MitkFiberTrackingExports.h>
#include <mitkParticleGrid.h>
// VTK
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkCellArray.h>
#include <vtkPoints.h>
#include <vtkPolyLine.h>
#include <vtkCleanPolyData.h>
#include <itkImage.h>
namespace mitk
{
/**
* \brief Gnerates actual fiber structure (vtkPolyData) from the particle grid content. */
class MITKFIBERTRACKING_EXPORT FiberBuilder
{
public:
typedef itk::Image<float, 3> ItkFloatImageType;
FiberBuilder(ParticleGrid* grid, ItkFloatImageType* image);
~FiberBuilder();
vtkSmartPointer<vtkPolyData> iterate(int minFiberLength);
protected:
void AddPoint(Particle *dp, vtkSmartPointer<vtkPolyLine> container);
void LabelPredecessors(Particle* p, int ep, vtkPolyLine* container);
void LabelSuccessors(Particle* p, int ep, vtkPolyLine* container);
itk::Point<float> m_LastPoint;
float m_FiberLength;
ItkFloatImageType::Pointer m_Image;
ParticleGrid* m_Grid;
vtkSmartPointer<vtkCellArray> m_VtkCellArray;
vtkSmartPointer<vtkPoints> m_VtkPoints;
};
}
#endif
diff --git a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkMetropolisHastingsSampler.cpp b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkMetropolisHastingsSampler.cpp
index abe2966..6053c7a 100644
--- a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkMetropolisHastingsSampler.cpp
+++ b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkMetropolisHastingsSampler.cpp
@@ -1,499 +1,499 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkMetropolisHastingsSampler.h"
using namespace mitk;
MetropolisHastingsSampler::MetropolisHastingsSampler(ParticleGrid* grid, EnergyComputer* enComp, ItkRandGenType* randGen, float curvThres)
: m_ExTemp(0.01)
, m_BirthProb(0.25)
, m_DeathProb(0.05)
, m_ShiftProb(0.15)
, m_OptShiftProb(0.1)
, m_ConnectionProb(0.45)
, m_TractProb(0.5)
, m_DelProb(0.1)
, m_ChempotParticle(0.0)
, m_AcceptedProposals(0)
{
m_RandGen = randGen;
m_ParticleGrid = grid;
m_EnergyComputer = enComp;
m_ParticleLength = m_ParticleGrid->m_ParticleLength;
m_DistanceThreshold = m_ParticleLength*m_ParticleLength;
m_Sigma = m_ParticleLength/8.0;
m_Gamma = 1/(m_Sigma*m_Sigma*2);
m_Z = pow(2*itk::Math::pi*m_Sigma,3.0/2.0)*(itk::Math::pi*m_Sigma/m_ParticleLength);
m_CurvatureThreshold = curvThres;
m_StopProb = exp(-1/m_TractProb);
}
void MetropolisHastingsSampler::SetProbabilities(float birth, float death, float shift, float optShift, float connect)
{
m_BirthProb = birth;
m_DeathProb = death;
m_ShiftProb = shift;
m_OptShiftProb = optShift;
m_ConnectionProb = connect;
float sum = m_BirthProb+m_DeathProb+m_ShiftProb+m_OptShiftProb+m_ConnectionProb;
if (sum!=1 && sum>mitk::eps)
{
m_BirthProb /= sum;
m_DeathProb /= sum;
m_ShiftProb /= sum;
m_OptShiftProb /= sum;
m_ConnectionProb /= sum;
}
std::cout << "Update proposal probabilities" << std::endl;
std::cout << "Birth: " << m_BirthProb << std::endl;
std::cout << "Death: " << m_DeathProb << std::endl;
std::cout << "Shift: " << m_ShiftProb << std::endl;
std::cout << "Optimal shift: " << m_OptShiftProb << std::endl;
std::cout << "Connection: " << m_ConnectionProb << std::endl;
}
// print proposal times
void MetropolisHastingsSampler::PrintProposalTimes()
{
double sum = m_BirthTime.GetTotal()+m_DeathTime.GetTotal()+m_ShiftTime.GetTotal()+m_OptShiftTime.GetTotal()+m_ConnectionTime.GetTotal();
std::cout << "Proposal time probes (toal%/mean)" << std::endl;
std::cout << "Birth: " << 100*m_BirthTime.GetTotal()/sum << "/" << m_BirthTime.GetMean()*1000 << std::endl;
std::cout << "Death: " << 100*m_DeathTime.GetTotal()/sum << "/" << m_DeathTime.GetMean()*1000 << std::endl;
std::cout << "Shift: " << 100*m_ShiftTime.GetTotal()/sum << "/" << m_ShiftTime.GetMean()*1000 << std::endl;
std::cout << "Optimal shift: " << 100*m_OptShiftTime.GetTotal()/sum << " - " << m_OptShiftTime.GetMean()*1000 << std::endl;
std::cout << "Connection: " << 100*m_ConnectionTime.GetTotal()/sum << "/" << m_ConnectionTime.GetMean()*1000 << std::endl;
}
// update temperature of simulated annealing process
void MetropolisHastingsSampler::SetTemperature(float val)
{
m_InTemp = val;
m_Density = exp(-m_ChempotParticle/m_InTemp);
}
// add small random number drawn from gaussian to each vector element
void MetropolisHastingsSampler::DistortVector(float sigma, vnl_vector_fixed<float, 3>& vec)
{
vec[0] += m_RandGen->GetNormalVariate(0.0, sigma);
vec[1] += m_RandGen->GetNormalVariate(0.0, sigma);
vec[2] += m_RandGen->GetNormalVariate(0.0, sigma);
}
// generate normalized random vector
vnl_vector_fixed<float, 3> MetropolisHastingsSampler::GetRandomDirection()
{
vnl_vector_fixed<float, 3> vec;
vec[0] = m_RandGen->GetNormalVariate();
vec[1] = m_RandGen->GetNormalVariate();
vec[2] = m_RandGen->GetNormalVariate();
vec.normalize();
return vec;
}
// generate actual proposal (birth, death, shift and connection of particle)
void MetropolisHastingsSampler::MakeProposal()
{
float randnum = m_RandGen->GetVariate();
// Birth Proposal
if (randnum < m_BirthProb)
{
m_BirthTime.Start();
vnl_vector_fixed<float, 3> R;
m_EnergyComputer->DrawRandomPosition(R);
vnl_vector_fixed<float, 3> N = GetRandomDirection();
Particle prop;
prop.GetPos() = R;
prop.GetDir() = N;
float prob = m_Density * m_DeathProb /((m_BirthProb)*(m_ParticleGrid->m_NumParticles+1));
float ex_energy = m_EnergyComputer->ComputeExternalEnergy(R,N,nullptr);
float in_energy = m_EnergyComputer->ComputeInternalEnergy(&prop);
prob *= exp((in_energy/m_InTemp+ex_energy/m_ExTemp)) ;
if (prob > 1 || m_RandGen->GetVariate() < prob)
{
Particle *p = m_ParticleGrid->NewParticle(R);
if (p!=nullptr)
{
p->GetPos() = R;
p->GetDir() = N;
m_AcceptedProposals++;
}
}
m_BirthTime.Stop();
}
// Death Proposal
else if (randnum < m_BirthProb+m_DeathProb)
{
m_DeathTime.Start();
if (m_ParticleGrid->m_NumParticles > 0)
{
int pnum = m_RandGen->GetIntegerVariate()%m_ParticleGrid->m_NumParticles;
Particle *dp = m_ParticleGrid->GetParticle(pnum);
if (dp->pID == -1 && dp->mID == -1)
{
float ex_energy = m_EnergyComputer->ComputeExternalEnergy(dp->GetPos(),dp->GetDir(),dp);
float in_energy = m_EnergyComputer->ComputeInternalEnergy(dp);
float prob = m_ParticleGrid->m_NumParticles * (m_BirthProb) /(m_Density*m_DeathProb); //*SpatProb(dp->R);
prob *= exp(-(in_energy/m_InTemp+ex_energy/m_ExTemp)) ;
if (prob > 1 || m_RandGen->GetVariate() < prob)
{
m_ParticleGrid->RemoveParticle(pnum);
m_AcceptedProposals++;
}
}
}
m_DeathTime.Stop();
}
// Shift Proposal
else if (randnum < m_BirthProb+m_DeathProb+m_ShiftProb)
{
if (m_ParticleGrid->m_NumParticles > 0)
{
m_ShiftTime.Start();
int pnum = m_RandGen->GetIntegerVariate()%m_ParticleGrid->m_NumParticles;
Particle *p = m_ParticleGrid->GetParticle(pnum);
Particle prop_p = *p;
DistortVector(m_Sigma, prop_p.GetPos());
DistortVector(m_Sigma/(2*m_ParticleLength), prop_p.GetDir());
prop_p.GetDir().normalize();
float ex_energy = m_EnergyComputer->ComputeExternalEnergy(prop_p.GetPos(),prop_p.GetDir(),p)
- m_EnergyComputer->ComputeExternalEnergy(p->GetPos(),p->GetDir(),p);
float in_energy = m_EnergyComputer->ComputeInternalEnergy(&prop_p) - m_EnergyComputer->ComputeInternalEnergy(p);
float prob = exp(ex_energy/m_ExTemp+in_energy/m_InTemp);
if (m_RandGen->GetVariate() < prob)
{
vnl_vector_fixed<float, 3> Rtmp = p->GetPos();
vnl_vector_fixed<float, 3> Ntmp = p->GetDir();
p->GetPos() = prop_p.GetPos();
p->GetDir() = prop_p.GetDir();
if (!m_ParticleGrid->TryUpdateGrid(pnum))
{
p->GetPos() = Rtmp;
p->GetDir() = Ntmp;
}
m_AcceptedProposals++;
}
m_ShiftTime.Stop();
}
}
// Optimal Shift Proposal
else if (randnum < m_BirthProb+m_DeathProb+m_ShiftProb+m_OptShiftProb)
{
if (m_ParticleGrid->m_NumParticles > 0)
{
m_OptShiftTime.Start();
int pnum = m_RandGen->GetIntegerVariate()%m_ParticleGrid->m_NumParticles;
Particle *p = m_ParticleGrid->GetParticle(pnum);
bool no_proposal = false;
Particle prop_p = *p;
if (p->pID != -1 && p->mID != -1)
{
Particle *plus = m_ParticleGrid->GetParticle(p->pID);
int ep_plus = (plus->pID == p->ID)? 1 : -1;
Particle *minus = m_ParticleGrid->GetParticle(p->mID);
int ep_minus = (minus->pID == p->ID)? 1 : -1;
prop_p.GetPos() = (plus->GetPos() + plus->GetDir() * (m_ParticleLength * ep_plus) + minus->GetPos() + minus->GetDir() * (m_ParticleLength * ep_minus));
prop_p.GetPos() *= 0.5;
prop_p.GetDir() = plus->GetPos() - minus->GetPos();
prop_p.GetDir().normalize();
}
else if (p->pID != -1)
{
Particle *plus = m_ParticleGrid->GetParticle(p->pID);
int ep_plus = (plus->pID == p->ID)? 1 : -1;
prop_p.GetPos() = plus->GetPos() + plus->GetDir() * (m_ParticleLength * ep_plus * 2);
prop_p.GetDir() = plus->GetDir();
}
else if (p->mID != -1)
{
Particle *minus = m_ParticleGrid->GetParticle(p->mID);
int ep_minus = (minus->pID == p->ID)? 1 : -1;
prop_p.GetPos() = minus->GetPos() + minus->GetDir() * (m_ParticleLength * ep_minus * 2);
prop_p.GetDir() = minus->GetDir();
}
else
no_proposal = true;
if (!no_proposal)
{
float cos = dot_product(prop_p.GetDir(), p->GetDir());
float p_rev = exp(-((prop_p.GetPos()-p->GetPos()).squared_magnitude() + (1-cos*cos))*m_Gamma)/m_Z;
float ex_energy = m_EnergyComputer->ComputeExternalEnergy(prop_p.GetPos(),prop_p.GetDir(),p)
- m_EnergyComputer->ComputeExternalEnergy(p->GetPos(),p->GetDir(),p);
float in_energy = m_EnergyComputer->ComputeInternalEnergy(&prop_p) - m_EnergyComputer->ComputeInternalEnergy(p);
float prob = exp(ex_energy/m_ExTemp+in_energy/m_InTemp)*m_ShiftProb*p_rev/(m_OptShiftProb+m_ShiftProb*p_rev);
if (m_RandGen->GetVariate() < prob)
{
vnl_vector_fixed<float, 3> Rtmp = p->GetPos();
vnl_vector_fixed<float, 3> Ntmp = p->GetDir();
p->GetPos() = prop_p.GetPos();
p->GetDir() = prop_p.GetDir();
if (!m_ParticleGrid->TryUpdateGrid(pnum))
{
p->GetPos() = Rtmp;
p->GetDir() = Ntmp;
}
m_AcceptedProposals++;
}
}
m_OptShiftTime.Stop();
}
}
// Connection Proposal
else
{
if (m_ParticleGrid->m_NumParticles > 0)
{
m_ConnectionTime.Start();
int pnum = m_RandGen->GetIntegerVariate()%m_ParticleGrid->m_NumParticles;
Particle *p = m_ParticleGrid->GetParticle(pnum);
EndPoint P;
P.p = p;
P.ep = (m_RandGen->GetVariate() > 0.5)? 1 : -1; // direction of the new tract
RemoveAndSaveTrack(P); // remove old tract and save it for later
if (m_BackupTrack.m_Probability != 0)
{
MakeTrackProposal(P); // propose new tract starting from P
float prob = (m_ProposalTrack.m_Energy-m_BackupTrack.m_Energy)/m_InTemp ;
prob = exp(prob)*(m_BackupTrack.m_Probability * pow(m_DelProb,m_ProposalTrack.m_Length))
/(m_ProposalTrack.m_Probability * pow(m_DelProb,m_BackupTrack.m_Length));
if (m_RandGen->GetVariate() < prob)
{
ImplementTrack(m_ProposalTrack); // accept proposed tract
m_AcceptedProposals++;
}
else
{
ImplementTrack(m_BackupTrack); // reject proposed tract and restore old one
}
}
else
ImplementTrack(m_BackupTrack);
m_ConnectionTime.Stop();
}
}
}
// establish connections between particles stored in input Track
void MetropolisHastingsSampler::ImplementTrack(Track &T)
{
for (int k = 1; k < T.m_Length;k++)
m_ParticleGrid->CreateConnection(T.track[k-1].p,T.track[k-1].ep,T.track[k].p,-T.track[k].ep);
}
// remove pending track from random particle, save it in m_BackupTrack and calculate its probability
void MetropolisHastingsSampler::RemoveAndSaveTrack(EndPoint P)
{
EndPoint Current = P;
int cnt = 0;
float energy = 0;
float AccumProb = 1.0;
m_BackupTrack.track[cnt] = Current;
EndPoint Next;
for (;;)
{
Next.p = nullptr;
if (Current.ep == 1)
{
if (Current.p->pID != -1)
{
Next.p = m_ParticleGrid->GetParticle(Current.p->pID);
Current.p->pID = -1;
m_ParticleGrid->m_NumConnections--;
}
}
else if (Current.ep == -1)
{
if (Current.p->mID != -1)
{
Next.p = m_ParticleGrid->GetParticle(Current.p->mID);
Current.p->mID = -1;
m_ParticleGrid->m_NumConnections--;
}
}
else
{ fprintf(stderr,"MetropolisHastingsSampler_randshift: Connection inconsistent 3\n"); break; }
if (Next.p == nullptr) // no successor
{
Next.ep = 0; // mark as empty successor
break;
}
else
{
if (Next.p->pID == Current.p->ID)
{
Next.p->pID = -1;
Next.ep = 1;
}
else if (Next.p->mID == Current.p->ID)
{
Next.p->mID = -1;
Next.ep = -1;
}
else
{ fprintf(stderr,"MetropolisHastingsSampler_randshift: Connection inconsistent 4\n"); break; }
}
ComputeEndPointProposalDistribution(Current);
AccumProb *= (m_SimpSamp.probFor(Next));
if (Next.p == nullptr) // no successor -> break
break;
energy += m_EnergyComputer->ComputeInternalEnergyConnection(Current.p,Current.ep,Next.p,Next.ep);
Current = Next;
Current.ep *= -1;
cnt++;
m_BackupTrack.track[cnt] = Current;
if (m_RandGen->GetVariate() > m_DelProb)
break;
}
m_BackupTrack.m_Energy = energy;
m_BackupTrack.m_Probability = AccumProb;
m_BackupTrack.m_Length = cnt+1;
}
// generate new track using kind of a local tracking starting from P in the given direction, store it in m_ProposalTrack and calculate its probability
void MetropolisHastingsSampler::MakeTrackProposal(EndPoint P)
{
EndPoint Current = P;
int cnt = 0;
float energy = 0;
float AccumProb = 1.0;
m_ProposalTrack.track[cnt++] = Current;
Current.p->label = 1;
for (;;)
{
// next candidate is already connected
if ((Current.ep == 1 && Current.p->pID != -1) || (Current.ep == -1 && Current.p->mID != -1))
break;
// track too long
// if (cnt > 250)
// break;
ComputeEndPointProposalDistribution(Current);
int k = m_SimpSamp.draw(m_RandGen->GetVariate());
// stop tracking proposed
if (k==0)
break;
EndPoint Next = m_SimpSamp.objs[k];
float probability = m_SimpSamp.probFor(k);
// accumulate energy and proposal distribution
energy += m_EnergyComputer->ComputeInternalEnergyConnection(Current.p,Current.ep,Next.p,Next.ep);
AccumProb *= probability;
// track to next endpoint
Current = Next;
Current.ep *= -1;
Current.p->label = 1; // put label to avoid loops
m_ProposalTrack.track[cnt++] = Current;
}
m_ProposalTrack.m_Energy = energy;
m_ProposalTrack.m_Probability = AccumProb;
m_ProposalTrack.m_Length = cnt;
// clear labels
for (int j = 0; j < m_ProposalTrack.m_Length;j++)
m_ProposalTrack.track[j].p->label = 0;
}
// get neigbouring particles of P and calculate the according connection probabilities
void MetropolisHastingsSampler::ComputeEndPointProposalDistribution(EndPoint P)
{
Particle *p = P.p;
int ep = P.ep;
float dist,dot;
vnl_vector_fixed<float, 3> R = p->GetPos() + (p->GetDir() * (ep*m_ParticleLength) );
m_ParticleGrid->ComputeNeighbors(R);
m_SimpSamp.clear();
m_SimpSamp.add(m_StopProb,EndPoint(nullptr,0));
for (;;)
{
Particle *p2 = m_ParticleGrid->GetNextNeighbor();
if (p2 == nullptr) break;
if (p!=p2 && p2->label == 0)
{
if (p2->mID == -1)
{
dist = (p2->GetPos() - p2->GetDir() * m_ParticleLength - R).squared_magnitude();
if (dist < m_DistanceThreshold)
{
dot = dot_product(p2->GetDir(),p->GetDir()) * ep;
if (dot > m_CurvatureThreshold)
{
float en = m_EnergyComputer->ComputeInternalEnergyConnection(p,ep,p2,-1);
m_SimpSamp.add(exp(en/m_TractProb),EndPoint(p2,-1));
}
}
}
if (p2->pID == -1)
{
dist = (p2->GetPos() + p2->GetDir() * m_ParticleLength - R).squared_magnitude();
if (dist < m_DistanceThreshold)
{
dot = dot_product(p2->GetDir(),p->GetDir()) * (-ep);
if (dot > m_CurvatureThreshold)
{
float en = m_EnergyComputer->ComputeInternalEnergyConnection(p,ep,p2,+1);
m_SimpSamp.add(exp(en/m_TractProb),EndPoint(p2,+1));
}
}
}
}
}
}
// return number of accepted proposals
int MetropolisHastingsSampler::GetNumAcceptedProposals()
{
return m_AcceptedProposals;
}
diff --git a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkMetropolisHastingsSampler.h b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkMetropolisHastingsSampler.h
index 00b6dc3..ff10cb5 100644
--- a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkMetropolisHastingsSampler.h
+++ b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkMetropolisHastingsSampler.h
@@ -1,110 +1,110 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _SAMPLER
#define _SAMPLER
// MITK
#include <MitkFiberTrackingExports.h>
#include <mitkParticleGrid.h>
#include <mitkEnergyComputer.h>
#include <mitkSimpSamp.h>
// ITK
#include <itkImage.h>
#include <itkTimeProbe.h>
#include <itkMersenneTwisterRandomVariateGenerator.h>
// MISC
#include <fstream>
namespace mitk
{
/**
* \brief Generates ne proposals of particle configurations. */
class MITKFIBERTRACKING_EXPORT MetropolisHastingsSampler
{
public:
typedef itk::Image< float, 3 > ItkFloatImageType;
typedef itk::Statistics::MersenneTwisterRandomVariateGenerator ItkRandGenType;
MetropolisHastingsSampler(ParticleGrid* grid, EnergyComputer* enComp, ItkRandGenType* randGen, float curvThres);
void SetTemperature(float val);
void MakeProposal(); ///< make proposal for birth/death/shift/connection of particles
int GetNumAcceptedProposals();
void SetProbabilities(float birth, float death, float shift, float optShift, float connect); ///< update the probabilities of the single proposals
void PrintProposalTimes(); ///< print the state of the proposal time probes
protected:
/** connection proposal related methods */
void ImplementTrack(Track& T);
void RemoveAndSaveTrack(EndPoint P);
void MakeTrackProposal(EndPoint P);
void ComputeEndPointProposalDistribution(EndPoint P);
/** generate random vectors */
void DistortVector(float sigma, vnl_vector_fixed<float, 3>& vec);
vnl_vector_fixed<float, 3> GetRandomDirection();
ItkRandGenType* m_RandGen; ///< random generator
Track m_ProposalTrack; ///< stores proposal track
Track m_BackupTrack; ///< stores track removed for new proposal traCK
SimpSamp m_SimpSamp; ///< neighbouring particles and their probabilities for the local tracking
float m_InTemp; ///< simulated annealing temperature
float m_ExTemp; ///< simulated annealing temperature
float m_Density;
float m_BirthProb; ///< probability for particle birth
float m_DeathProb; ///< probability for particle death
float m_ShiftProb; ///< probability for particle shift
float m_OptShiftProb; ///< probability for optimal particle shift
float m_ConnectionProb; ///< probability for particle connection proposal
float m_Sigma;
float m_Gamma;
float m_Z;
float m_DistanceThreshold; ///< threshold for maximum distance between connected particles
float m_CurvatureThreshold; ///< threshold for maximum angle between connected particles
float m_TractProb;
float m_StopProb;
float m_DelProb;
float m_ParticleLength;
float m_ChempotParticle;
ParticleGrid* m_ParticleGrid; ///< storest all particles
EnergyComputer* m_EnergyComputer; ///< computes internal and external energy of particles
unsigned int m_AcceptedProposals; ///< counts accepted proposals
/** Time probes for the single proposals */
itk::TimeProbe m_BirthTime;
itk::TimeProbe m_DeathTime;
itk::TimeProbe m_ShiftTime;
itk::TimeProbe m_OptShiftTime;
itk::TimeProbe m_ConnectionTime;
};
}
#endif
diff --git a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkParticle.h b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkParticle.h
index 5dde094..2b812d9 100644
--- a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkParticle.h
+++ b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkParticle.h
@@ -1,90 +1,90 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _PARTICLE
#define _PARTICLE
#include <MitkFiberTrackingExports.h>
#include <vnl/vnl_vector_fixed.h>
namespace mitk
{
/**
* \brief A particle is the basic element of the Gibbs fiber tractography method. */
class MITKFIBERTRACKING_EXPORT Particle
{
public:
Particle()
{
label = 0;
pID = -1;
mID = -1;
}
~Particle()
{
}
int gridindex; // index in the grid where it is living
int ID; // particle ID
int pID; // successor ID
int mID; // predecessor ID
unsigned char label; // label used in the fiber building process
vnl_vector_fixed<float, 3>& GetPos()
{
return pos;
}
vnl_vector_fixed<float, 3>& GetDir()
{
return dir;
}
private:
// this pragma ignores the following warning:
// warning C4251: 'mitk::Particle::pos' : class 'ATL::CStringT' needs to have dll-interface to be used by clients of class 'Particle'
vnl_vector_fixed<float, 3> pos; // particle position (world coordinates. corner based voxels. not accounted for image rotation.
vnl_vector_fixed<float, 3> dir; // normalized direction vector
};
class MITKFIBERTRACKING_EXPORT EndPoint
{
public:
EndPoint()
{}
EndPoint(Particle *p,int ep)
{
this->p = p;
this->ep = ep;
}
Particle *p;
int ep;
inline bool operator==(EndPoint P)
{
return (P.p == p) && (P.ep == ep);
}
};
}
#endif
diff --git a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkParticleGrid.cpp b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkParticleGrid.cpp
index 78b8623..dfdac11 100644
--- a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkParticleGrid.cpp
+++ b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkParticleGrid.cpp
@@ -1,420 +1,420 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkParticleGrid.h"
#include <cstdlib>
#include <cstdio>
using namespace mitk;
ParticleGrid::ParticleGrid(ItkFloatImageType* image, float particleLength, int cellCapacity)
{
// initialize counters
m_NumParticles = 0;
m_NumConnections = 0;
m_NumCellOverflows = 0;
m_ParticleLength = particleLength;
// define isotropic grid from voxel spacing and particle length
float cellSize = 2*m_ParticleLength;
m_GridSize[0] = image->GetLargestPossibleRegion().GetSize()[0]*image->GetSpacing()[0]/cellSize +1;
m_GridSize[1] = image->GetLargestPossibleRegion().GetSize()[1]*image->GetSpacing()[1]/cellSize +1;
m_GridSize[2] = image->GetLargestPossibleRegion().GetSize()[2]*image->GetSpacing()[2]/cellSize +1;
m_GridScale[0] = 1/cellSize;
m_GridScale[1] = 1/cellSize;
m_GridScale[2] = 1/cellSize;
m_CellCapacity = cellCapacity; // maximum number of particles per grid cell
m_ContainerCapacity = 100000; // initial particle container capacity
unsigned long numCells = m_GridSize[0]*m_GridSize[1]*m_GridSize[2]; // number of grid cells
unsigned long gridSize = numCells*m_CellCapacity;
if ( (unsigned long)itk::NumericTraits<int>::max()<gridSize )
throw std::bad_alloc();
m_Particles.resize(m_ContainerCapacity); // allocate and initialize particles
m_Grid.resize(gridSize, nullptr); // allocate and initialize particle grid
m_OccupationCount.resize(numCells, 0); // allocate and initialize occupation counter array
m_NeighbourTracker.cellidx.resize(8, 0); // allocate and initialize neighbour tracker
m_NeighbourTracker.cellidx_c.resize(8, 0);
for (int i = 0;i < m_ContainerCapacity;i++) // initialize particle IDs
m_Particles[i].ID = i;
std::cout << "ParticleGrid: allocated " << (sizeof(Particle)*m_ContainerCapacity + sizeof(Particle*)*m_GridSize[0]*m_GridSize[1]*m_GridSize[2])/1048576 << "mb for " << m_ContainerCapacity/1000 << "k particles." << std::endl;
}
ParticleGrid::~ParticleGrid()
{
}
// remove all particles
void ParticleGrid::ResetGrid()
{
// initialize counters
m_NumParticles = 0;
m_NumConnections = 0;
m_NumCellOverflows = 0;
m_Particles.clear();
m_Grid.clear();
m_OccupationCount.clear();
m_NeighbourTracker.cellidx.clear();
m_NeighbourTracker.cellidx_c.clear();
int numCells = m_GridSize[0]*m_GridSize[1]*m_GridSize[2]; // number of grid cells
m_Particles.resize(m_ContainerCapacity); // allocate and initialize particles
m_Grid.resize(numCells*m_CellCapacity, nullptr); // allocate and initialize particle grid
m_OccupationCount.resize(numCells, 0); // allocate and initialize occupation counter array
m_NeighbourTracker.cellidx.resize(8, 0); // allocate and initialize neighbour tracker
m_NeighbourTracker.cellidx_c.resize(8, 0);
for (int i = 0;i < m_ContainerCapacity;i++) // initialize particle IDs
m_Particles[i].ID = i;
}
bool ParticleGrid::ReallocateGrid()
{
int new_capacity = m_ContainerCapacity + 100000; // increase container capacity by 100k particles
try
{
m_Particles.resize(new_capacity); // reallocate particles
for (int i = 0; i<m_ContainerCapacity; i++) // update particle addresses (changed during reallocation)
m_Grid[m_Particles[i].gridindex] = &m_Particles[i];
for (int i = m_ContainerCapacity; i < new_capacity; i++) // initialize IDs of ne particles
m_Particles[i].ID = i;
m_ContainerCapacity = new_capacity; // update member variable
//std::cout << "ParticleGrid: allocated " << (sizeof(Particle)*m_ContainerCapacity + sizeof(Particle*)*m_GridSize[0]*m_GridSize[1]*m_GridSize[2])/1048576 << "mb for " << m_ContainerCapacity/1000 << "k particles." << std::endl;
}
catch(...)
{
std::cout << "ParticleGrid: allocation of " << (sizeof(Particle)*new_capacity + sizeof(Particle*)*m_GridSize[0]*m_GridSize[1]*m_GridSize[2])/1048576 << "mb for " << new_capacity/1000 << "k particles failed!" << std::endl;
return false;
}
return true;
}
Particle* ParticleGrid::GetParticle(int ID)
{
if (ID!=-1)
return &m_Particles[ID];
return nullptr;
}
Particle* ParticleGrid::NewParticle(vnl_vector_fixed<float, 3> R)
{
if (m_NumParticles >= m_ContainerCapacity)
{
if (!ReallocateGrid())
return nullptr;
}
int xint = int(R[0]*m_GridScale[0]);
if (xint < 0)
return nullptr;
if (xint >= m_GridSize[0])
return nullptr;
int yint = int(R[1]*m_GridScale[1]);
if (yint < 0)
return nullptr;
if (yint >= m_GridSize[1])
return nullptr;
int zint = int(R[2]*m_GridScale[2]);
if (zint < 0)
return nullptr;
if (zint >= m_GridSize[2])
return nullptr;
int idx = xint + m_GridSize[0]*(yint + m_GridSize[1]*zint);
if (m_OccupationCount[idx] < m_CellCapacity)
{
Particle *p = &(m_Particles[m_NumParticles]);
p->GetPos() = R;
p->mID = -1;
p->pID = -1;
m_NumParticles++;
p->gridindex = m_CellCapacity*idx + m_OccupationCount[idx];
m_Grid[p->gridindex] = p;
m_OccupationCount[idx]++;
return p;
}
else
{
m_NumCellOverflows++;
return nullptr;
}
}
bool ParticleGrid::TryUpdateGrid(int k)
{
Particle* p = &(m_Particles[k]);
int xint = int(p->GetPos()[0]*m_GridScale[0]);
if (xint < 0)
return false;
if (xint >= m_GridSize[0])
return false;
int yint = int(p->GetPos()[1]*m_GridScale[1]);
if (yint < 0)
return false;
if (yint >= m_GridSize[1])
return false;
int zint = int(p->GetPos()[2]*m_GridScale[2]);
if (zint < 0)
return false;
if (zint >= m_GridSize[2])
return false;
int idx = xint + m_GridSize[0]*(yint+ zint*m_GridSize[1]);
int cellidx = p->gridindex/m_CellCapacity;
if (idx != cellidx) // cell has changed
{
if (m_OccupationCount[idx] < m_CellCapacity)
{
// remove from old position in grid;
int grdindex = p->gridindex;
m_Grid[grdindex] = m_Grid[cellidx*m_CellCapacity + m_OccupationCount[cellidx]-1];
m_Grid[grdindex]->gridindex = grdindex;
m_OccupationCount[cellidx]--;
// insert at new position in grid
p->gridindex = idx*m_CellCapacity + m_OccupationCount[idx];
m_Grid[p->gridindex] = p;
m_OccupationCount[idx]++;
return true;
}
else
{
m_NumCellOverflows++;
return false;
}
}
return true;
}
void ParticleGrid::RemoveParticle(int k)
{
Particle* p = &(m_Particles[k]);
int gridIndex = p->gridindex;
int cellIdx = gridIndex/m_CellCapacity;
int idx = gridIndex%m_CellCapacity;
// remove pending connections
if (p->mID != -1)
DestroyConnection(p,-1);
if (p->pID != -1)
DestroyConnection(p,+1);
// remove from grid
if (idx < m_OccupationCount[cellIdx]-1)
{
m_Grid[gridIndex] = m_Grid[cellIdx*m_CellCapacity+m_OccupationCount[cellIdx]-1];
m_Grid[cellIdx*m_CellCapacity+m_OccupationCount[cellIdx]-1] = nullptr;
m_Grid[gridIndex]->gridindex = gridIndex;
}
m_OccupationCount[cellIdx]--;
// remove from container
if (k < m_NumParticles-1)
{
Particle* last = &m_Particles[m_NumParticles-1]; // last particle
// update connections of last particle because its index is changing
if (last->mID!=-1)
{
if ( m_Particles[last->mID].mID == m_NumParticles-1 )
m_Particles[last->mID].mID = k;
else if ( m_Particles[last->mID].pID == m_NumParticles-1 )
m_Particles[last->mID].pID = k;
}
if (last->pID!=-1)
{
if ( m_Particles[last->pID].mID == m_NumParticles-1 )
m_Particles[last->pID].mID = k;
else if ( m_Particles[last->pID].pID == m_NumParticles-1 )
m_Particles[last->pID].pID = k;
}
m_Particles[k] = m_Particles[m_NumParticles-1]; // move very last particle to empty slot
m_Particles[m_NumParticles-1].ID = m_NumParticles-1; // update ID of removed particle to match the index
m_Particles[k].ID = k; // update ID of moved particle
m_Grid[m_Particles[k].gridindex] = &m_Particles[k]; // update address of moved particle
}
m_NumParticles--;
}
void ParticleGrid::ComputeNeighbors(vnl_vector_fixed<float, 3> &R)
{
float xfrac = R[0]*m_GridScale[0];
float yfrac = R[1]*m_GridScale[1];
float zfrac = R[2]*m_GridScale[2];
int xint = int(xfrac);
int yint = int(yfrac);
int zint = int(zfrac);
int dx = -1;
if (xfrac-xint > 0.5) dx = 1;
if (xint <= 0) { xint = 0; dx = 1; }
if (xint >= m_GridSize[0]-1) { xint = m_GridSize[0]-1; dx = -1; }
if (m_GridSize[0] <= 1) { dx = 0; } // Necessary with 2d images (bug 15416)
int dy = -1;
if (yfrac-yint > 0.5) dy = 1;
if (yint <= 0) {yint = 0; dy = 1; }
if (yint >= m_GridSize[1]-1) {yint = m_GridSize[1]-1; dy = -1;}
if (m_GridSize[1] <= 1) { dy = 0; } // Necessary with 2d images (bug 15416)
int dz = -1;
if (zfrac-zint > 0.5) dz = 1;
if (zint <= 0) {zint = 0; dz = 1; }
if (zint >= m_GridSize[2]-1) {zint = m_GridSize[2]-1; dz = -1;}
if (m_GridSize[2] <= 1) { dz = 0; } // Necessary with 2d images (bug 15416)
m_NeighbourTracker.cellidx[0] = xint + m_GridSize[0]*(yint+zint*m_GridSize[1]);
m_NeighbourTracker.cellidx[1] = m_NeighbourTracker.cellidx[0] + dx;
m_NeighbourTracker.cellidx[2] = m_NeighbourTracker.cellidx[1] + dy*m_GridSize[0];
m_NeighbourTracker.cellidx[3] = m_NeighbourTracker.cellidx[2] - dx;
m_NeighbourTracker.cellidx[4] = m_NeighbourTracker.cellidx[0] + dz*m_GridSize[0]*m_GridSize[1];
m_NeighbourTracker.cellidx[5] = m_NeighbourTracker.cellidx[4] + dx;
m_NeighbourTracker.cellidx[6] = m_NeighbourTracker.cellidx[5] + dy*m_GridSize[0];
m_NeighbourTracker.cellidx[7] = m_NeighbourTracker.cellidx[6] - dx;
m_NeighbourTracker.cellidx_c[0] = m_CellCapacity*m_NeighbourTracker.cellidx[0];
m_NeighbourTracker.cellidx_c[1] = m_CellCapacity*m_NeighbourTracker.cellidx[1];
m_NeighbourTracker.cellidx_c[2] = m_CellCapacity*m_NeighbourTracker.cellidx[2];
m_NeighbourTracker.cellidx_c[3] = m_CellCapacity*m_NeighbourTracker.cellidx[3];
m_NeighbourTracker.cellidx_c[4] = m_CellCapacity*m_NeighbourTracker.cellidx[4];
m_NeighbourTracker.cellidx_c[5] = m_CellCapacity*m_NeighbourTracker.cellidx[5];
m_NeighbourTracker.cellidx_c[6] = m_CellCapacity*m_NeighbourTracker.cellidx[6];
m_NeighbourTracker.cellidx_c[7] = m_CellCapacity*m_NeighbourTracker.cellidx[7];
m_NeighbourTracker.cellcnt = 0;
m_NeighbourTracker.pcnt = 0;
}
Particle* ParticleGrid::GetNextNeighbor()
{
if (m_NeighbourTracker.pcnt < m_OccupationCount[m_NeighbourTracker.cellidx[m_NeighbourTracker.cellcnt]])
{
return m_Grid[m_NeighbourTracker.cellidx_c[m_NeighbourTracker.cellcnt] + (m_NeighbourTracker.pcnt++)];
}
else
{
for(;;)
{
m_NeighbourTracker.cellcnt++;
if (m_NeighbourTracker.cellcnt >= 8)
return nullptr;
if (m_OccupationCount[m_NeighbourTracker.cellidx[m_NeighbourTracker.cellcnt]] > 0)
break;
}
m_NeighbourTracker.pcnt = 1;
return m_Grid[m_NeighbourTracker.cellidx_c[m_NeighbourTracker.cellcnt]];
}
}
void ParticleGrid::CreateConnection(Particle *P1,int ep1, Particle *P2, int ep2)
{
if (ep1 == -1)
P1->mID = P2->ID;
else
P1->pID = P2->ID;
if (ep2 == -1)
P2->mID = P1->ID;
else
P2->pID = P1->ID;
m_NumConnections++;
}
void ParticleGrid::DestroyConnection(Particle *P1,int ep1, Particle *P2, int ep2)
{
if (ep1 == -1)
P1->mID = -1;
else
P1->pID = -1;
if (ep2 == -1)
P2->mID = -1;
else
P2->pID = -1;
m_NumConnections--;
}
void ParticleGrid::DestroyConnection(Particle *P1,int ep1)
{
Particle *P2 = nullptr;
if (ep1 == 1)
{
P2 = &m_Particles[P1->pID];
P1->pID = -1;
}
else
{
P2 = &m_Particles[P1->mID];
P1->mID = -1;
}
if (P2->mID == P1->ID)
P2->mID = -1;
else
P2->pID = -1;
m_NumConnections--;
}
bool ParticleGrid::CheckConsistency()
{
for (int i=0; i<m_NumParticles; i++)
{
Particle* p = &m_Particles[i];
if (p->ID != i)
{
std::cout << "Particle ID error!" << std::endl;
return false;
}
if (p->mID!=-1)
{
Particle* p2 = &m_Particles[p->mID];
if (p2->mID!=p->ID && p2->pID!=p->ID)
{
std::cout << "Connection inconsistent!" << std::endl;
return false;
}
}
if (p->pID!=-1)
{
Particle* p2 = &m_Particles[p->pID];
if (p2->mID!=p->ID && p2->pID!=p->ID)
{
std::cout << "Connection inconsistent!" << std::endl;
return false;
}
}
}
return true;
}
diff --git a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkParticleGrid.h b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkParticleGrid.h
index 2858b93..e98979a 100644
--- a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkParticleGrid.h
+++ b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkParticleGrid.h
@@ -1,124 +1,124 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _PARTICLEGRID
#define _PARTICLEGRID
// MITK
#include <MitkFiberTrackingExports.h>
#include <mitkParticle.h>
// ITK
#include <itkImage.h>
namespace mitk
{
/**
* \brief Contains and manages particles. */
class MITKFIBERTRACKING_EXPORT ParticleGrid
{
public:
typedef itk::Image< float, 3 > ItkFloatImageType;
int m_NumParticles; // number of particles
int m_NumConnections; // number of connections
int m_NumCellOverflows; // number of cell overflows
float m_ParticleLength;
ParticleGrid(ItkFloatImageType* image, float particleLength, int cellCapacity);
~ParticleGrid();
Particle* GetParticle(int ID);
Particle* NewParticle(vnl_vector_fixed<float, 3> R);
bool TryUpdateGrid(int k);
void RemoveParticle(int k);
void ComputeNeighbors(vnl_vector_fixed<float, 3> &R);
Particle* GetNextNeighbor();
void CreateConnection(Particle *P1,int ep1, Particle *P2, int ep2);
void DestroyConnection(Particle *P1,int ep1, Particle *P2, int ep2);
void DestroyConnection(Particle *P1,int ep1);
bool CheckConsistency();
void ResetGrid();
protected:
bool ReallocateGrid();
std::vector< Particle* > m_Grid; // the grid
std::vector< Particle > m_Particles; // particle container
std::vector< int > m_OccupationCount; // number of particles per grid cell
int m_ContainerCapacity; // maximal number of particles
vnl_vector_fixed< int, 3 > m_GridSize; // grid dimensions
vnl_vector_fixed< float, 3 > m_GridScale; // scaling factor for grid
int m_CellCapacity; // particle capacity of single cell in grid
struct NeighborTracker // to run over the neighbors
{
std::vector< int > cellidx;
std::vector< int > cellidx_c;
int cellcnt;
int pcnt;
} m_NeighbourTracker;
};
class MITKFIBERTRACKING_EXPORT Track
{
public:
std::vector< EndPoint > track;
float m_Energy;
float m_Probability;
int m_Length;
Track()
{
track.resize(1000);
}
~Track(){}
void clear()
{
m_Length = 0;
m_Energy = 0;
m_Probability = 1;
}
bool isequal(Track& t)
{
for (int i = 0; i < m_Length;i++)
{
if (track[i].p != t.track[i].p || track[i].ep != t.track[i].ep)
return false;
}
return true;
}
};
}
#endif
diff --git a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkSimpSamp.h b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkSimpSamp.h
index 35a5caf..57ca01d 100644
--- a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkSimpSamp.h
+++ b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkSimpSamp.h
@@ -1,122 +1,122 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _SIMPSAMP
#define _SIMPSAMP
#include <MitkFiberTrackingExports.h>
#include <mitkParticle.h>
#include <cstdlib>
namespace mitk
{
/**
* \brief Samples new tract from surrounding fiber segments. */
class MITKFIBERTRACKING_EXPORT SimpSamp
{
float *P;
int cnt;
public:
EndPoint* objs;
SimpSamp()
{
P = (float*) malloc(sizeof(float)*1000);
objs = (EndPoint*) malloc(sizeof(EndPoint)*1000);
}
~SimpSamp()
{
free(P);
free(objs);
}
inline void clear()
{
cnt = 1;
P[0] = 0;
}
inline void add(float p, EndPoint obj)
{
P[cnt] = P[cnt-1] + p;
objs[cnt-1] = obj;
cnt++;
}
inline int draw(float prob)
{
float r = prob*P[cnt-1];
int j;
int rl = 1;
int rh = cnt-1;
while(rh != rl)
{
j = rl + (rh-rl)/2;
if (r < P[j])
{
rh = j;
continue;
}
if (r > P[j])
{
rl = j+1;
continue;
}
break;
}
return rh-1;
}
inline EndPoint drawObj(float prob)
{
return objs[draw(prob)];
}
inline bool isempty()
{
if (cnt == 1)
return true;
else
return false;
}
float probFor(int idx)
{
return (P[idx+1]-P[idx])/P[cnt-1];
}
float probFor(EndPoint& t)
{
for (int i = 1; i< cnt;i++)
{
if (t == objs[i-1])
return probFor(i-1);
}
return 0;
}
};
}
#endif
diff --git a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkSphereInterpolator.cpp b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkSphereInterpolator.cpp
index 40d2b44..bec1b21 100644
--- a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkSphereInterpolator.cpp
+++ b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkSphereInterpolator.cpp
@@ -1,173 +1,173 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkSphereInterpolator.h"
#include <usGetModuleContext.h>
#include <usModuleContext.h>
#include <usModule.h>
#include <usModuleResource.h>
#include <usModuleResourceStream.h>
#include <mitkOdfImage.h>
#include <fstream>
#include <exception>
static const std::string BaryCoordsFileName = "FiberTrackingLUTBaryCoords.bin";
static const std::string IndicesFileName = "FiberTrackingLUTIndices.bin";
SphereInterpolator::SphereInterpolator(const std::string& lutPath)
{
m_ValidState = true;
if (lutPath.length()==0)
{
if (!LoadLookuptables())
{
m_ValidState = false;
return;
}
}
else
{
if (!LoadLookuptables(lutPath))
{
m_ValidState = false;
return;
}
}
size = 301;
sN = (size-1)/2;
nverts = ODF_SAMPLING_SIZE;
beta = 0.5;
inva = (sqrt(1+beta)-sqrt(beta));
b = 1/(1-sqrt(1/beta + 1));
}
SphereInterpolator::~SphereInterpolator()
{
}
bool SphereInterpolator::LoadLookuptables(const std::string& lutPath)
{
MITK_INFO << "SphereInterpolator: loading lookuptables from custom path: " << lutPath;
std::string path = lutPath; path.append(BaryCoordsFileName);
std::ifstream BaryCoordsStream;
BaryCoordsStream.open(path.c_str(), ios::in | ios::binary);
MITK_INFO << "SphereInterpolator: 1 " << path;
if (!BaryCoordsStream.is_open())
{
MITK_INFO << "SphereInterpolator: could not load FiberTrackingLUTBaryCoords.bin from " << path;
return false;
}
ifstream IndicesStream;
path = lutPath; path.append("FiberTrackingLUTIndices.bin");
IndicesStream.open(path.c_str(), ios::in | ios::binary);
MITK_INFO << "SphereInterpolator: 1 " << path;
if (!IndicesStream.is_open())
{
MITK_INFO << "SphereInterpolator: could not load FiberTrackingLUTIndices.bin from " << path;
return false;
}
if (LoadLookuptables(BaryCoordsStream, IndicesStream))
{
MITK_INFO << "SphereInterpolator: first and second lut loaded successfully";
return true;
}
return false;
}
bool SphereInterpolator::LoadLookuptables()
{
MITK_INFO << "SphereInterpolator: loading lookuptables";
us::Module* module = us::GetModuleContext()->GetModule();
us::ModuleResource BaryCoordsRes = module->GetResource(BaryCoordsFileName);
if (!BaryCoordsRes.IsValid())
{
MITK_INFO << "Could not retrieve resource " << BaryCoordsFileName;
return false;
}
us::ModuleResource IndicesRes = module->GetResource(IndicesFileName);
if (!IndicesRes)
{
MITK_INFO << "Could not retrieve resource " << IndicesFileName;
return false;
}
us::ModuleResourceStream BaryCoordsStream(BaryCoordsRes, std::ios_base::binary);
us::ModuleResourceStream IndicesStream(IndicesRes, std::ios_base::binary);
return LoadLookuptables(BaryCoordsStream, IndicesStream);
}
bool SphereInterpolator::LoadLookuptables(std::istream& BaryCoordsStream, std::istream& IndicesStream)
{
if (BaryCoordsStream)
{
try
{
float tmp;
BaryCoordsStream.seekg (0, ios::beg);
while (!BaryCoordsStream.eof())
{
BaryCoordsStream.read((char *)&tmp, sizeof(tmp));
barycoords.push_back(tmp);
}
}
catch (const std::exception& e)
{
MITK_INFO << e.what();
}
}
else
{
MITK_INFO << "SphereInterpolator: could not load FiberTrackingLUTBaryCoords.bin";
return false;
}
if (IndicesStream)
{
try
{
int tmp;
IndicesStream.seekg (0, ios::beg);
while (!IndicesStream.eof())
{
IndicesStream.read((char *)&tmp, sizeof(tmp));
indices.push_back(tmp);
}
}
catch (const std::exception& e)
{
MITK_INFO << e.what();
}
}
else
{
MITK_INFO << "SphereInterpolator: could not load FiberTrackingLUTIndices.bin";
return false;
}
return true;
}
diff --git a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkSphereInterpolator.h b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkSphereInterpolator.h
index c250be9..17a12b3 100644
--- a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkSphereInterpolator.h
+++ b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkSphereInterpolator.h
@@ -1,164 +1,164 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _SPHEREINTERPOLATOR
#define _SPHEREINTERPOLATOR
#include <MitkFiberTrackingExports.h>
#include <vnl/vnl_vector_fixed.h>
#include <vector>
/**
* \brief Lookuptable based trilinear interpolation of spherically arranged scalar values.
*/
class MITKFIBERTRACKING_EXPORT SphereInterpolator
{
public:
int size; // size of LUT
int sN; // (sizeofLUT-1)/2
int nverts; // number of data vertices
float beta;
float inva;
float b;
bool m_ValidState;
std::vector< float > barycoords;
std::vector< int > indices;
vnl_vector_fixed< int, 3 > idx;
vnl_vector_fixed< float, 3 > interpw;
SphereInterpolator(const std::string& lutPath);
inline bool IsInValidState() const
{
return m_ValidState;
}
~SphereInterpolator();
inline void getInterpolation(const vnl_vector_fixed<float, 3>& N)
{
float nx = N[0];
float ny = N[1];
float nz = N[2];
if (nz > 0.5)
{
int x = float2int(nx);
int y = float2int(ny);
int i = 3*6*(x+y*size); // (:,1,x,y)
idx[0] = indices[i];
idx[1] = indices[i+1];
idx[2] = indices[i+2];
interpw[0] = barycoords[i];
interpw[1] = barycoords[i+1];
interpw[2] = barycoords[i+2];
return;
}
if (nz < -0.5)
{
int x = float2int(nx);
int y = float2int(ny);
int i = 3*(1+6*(x+y*size)); // (:,2,x,y)
idx[0] = indices[i];
idx[1] = indices[i+1];
idx[2] = indices[i+2];
interpw[0] = barycoords[i];
interpw[1] = barycoords[i+1];
interpw[2] = barycoords[i+2];
return;
}
if (nx > 0.5)
{
int z = float2int(nz);
int y = float2int(ny);
int i = 3*(2+6*(z+y*size)); // (:,2,x,y)
idx[0] = indices[i];
idx[1] = indices[i+1];
idx[2] = indices[i+2];
interpw[0] = barycoords[i];
interpw[1] = barycoords[i+1];
interpw[2] = barycoords[i+2];
return;
}
if (nx < -0.5)
{
int z = float2int(nz);
int y = float2int(ny);
int i = 3*(3+6*(z+y*size)); // (:,2,x,y)
idx[0] = indices[i];
idx[1] = indices[i+1];
idx[2] = indices[i+2];
interpw[0] = barycoords[i];
interpw[1] = barycoords[i+1];
interpw[2] = barycoords[i+2];
return;
}
if (ny > 0)
{
int x = float2int(nx);
int z = float2int(nz);
int i = 3*(4+6*(x+z*size)); // (:,1,x,y)
idx[0] = indices[i];
idx[1] = indices[i+1];
idx[2] = indices[i+2];
interpw[0] = barycoords[i];
interpw[1] = barycoords[i+1];
interpw[2] = barycoords[i+2];
return;
}
else
{
int x = float2int(nx);
int z = float2int(nz);
int i = 3*(5+6*(x+z*size)); // (:,1,x,y)
idx[0] = indices[i];
idx[1] = indices[i+1];
idx[2] = indices[i+2];
interpw[0] = barycoords[i];
interpw[1] = barycoords[i+1];
interpw[2] = barycoords[i+2];
return;
}
}
protected:
bool LoadLookuptables(const std::string& lutPath);
bool LoadLookuptables();
bool LoadLookuptables(std::istream& BaryCoordsStream, std::istream& IndicesStream);
inline float invrescale(float f) const
{
float x = (fabs(f)-b)*inva;
if (f>0)
return (x*x-beta);
else
return beta - x*x;
}
inline int float2int(float x) const
{
return int((invrescale(x)+1)*sN-0.5);
}
};
#endif
diff --git a/Modules/FiberTracking/Algorithms/StochasticTracking/itkSlowPolyLineParametricPath.h b/Modules/FiberTracking/Algorithms/StochasticTracking/itkSlowPolyLineParametricPath.h
index 3afea4c..54ff123 100644
--- a/Modules/FiberTracking/Algorithms/StochasticTracking/itkSlowPolyLineParametricPath.h
+++ b/Modules/FiberTracking/Algorithms/StochasticTracking/itkSlowPolyLineParametricPath.h
@@ -1,128 +1,128 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _itkSlowPolyLineParametricPathPath_h
#define _itkSlowPolyLineParametricPathPath_h
#include "itkPolyLineParametricPath.h"
#include "itkVectorContainer.h"
#include "itkContinuousIndex.h"
#include "itkIndex.h"
#include "itkOffset.h"
#include "itkVector.h"
namespace itk
{
/** \class SlowPolyLineParametricPath
* \brief Represent a path of line segments through ND Space
*
* This class is intended to represent parametric paths through an image, where
* the paths are composed of line segments. Each line segment traverses one
* unit of input. A classic application of this class is the representation of
* contours in 2D images, especially when the contours only need to be
* approximately correct. Another use of a path is to guide the movement of an
* iterator through an image.
*
* \sa EllipseParametricPath
* \sa FourierSeriesPath
* \sa OrthogonallyCorrectedParametricPath
* \sa ParametricPath
* \sa ChainCodePath
* \sa Path
* \sa ContinuousIndex
* \sa Index
* \sa Offset
* \sa Vector
*
* \ingroup PathObjects
*/
template <unsigned int VDimension>
class ITK_EXPORT SlowPolyLineParametricPath : public
PolyLineParametricPath< VDimension >
{
public:
/** Standard class typedefs. */
typedef SlowPolyLineParametricPath Self;
typedef PolyLineParametricPath<VDimension> Superclass;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
/** Run-time type information (and related methods). */
itkTypeMacro(SlowPolyLineParametricPath, PolyLineParametricPath);
/** Input type */
typedef typename Superclass::InputType InputType;
/** Output type */
typedef typename Superclass::OutputType OutputType;
/** Basic data-structure types used */
typedef typename Superclass::ContinuousIndexType ContinuousIndexType;
typedef typename Superclass::IndexType IndexType;
typedef typename Superclass::OffsetType OffsetType;
typedef typename Superclass::PointType PointType;
typedef typename Superclass::VectorType VectorType;
typedef typename Superclass::VertexType VertexType;
typedef typename Superclass::VertexListType VertexListType;
typedef typename Superclass::VertexListPointer VertexListPointer;
/** Increment the input variable passed by reference such that the ND index of
* the path moves to its next vertex-connected (8-connected in 2D) neighbor.
* Return the Index-space offset of the path from its prior input to its new
* input. If the path is unable to increment, input is not changed and an
* offset of Zero is returned. Children are not required to implement bounds
* checking.
*
* This is a fairly slow, iterative algorithm that numerically converges to
* the next index along the path, in a vertex-connected (8-connected in 2D)
* fashion. When possible, children of this class should overload this
* function with something more efficient.
*
* WARNING: This default implementation REQUIRES that the ND endpoint of
* the path be either unique or coincident only with the startpoint, since it
* uses the endpoint as a stopping condition. */
virtual OffsetType IncrementInput(InputType & input) const;
///** Evaluate the first derivative of the ND output with respect to the 1D
// * input. This is an exact, algebraic function. */
//virtual VectorType EvaluateDerivative(const InputType & input) const;
/** New() method for dynamic construction */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
protected:
SlowPolyLineParametricPath();
~SlowPolyLineParametricPath(){}
void PrintSelf(std::ostream& os, Indent indent) const;
private:
SlowPolyLineParametricPath(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
};
} // namespace itk
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkSlowPolyLineParametricPath.txx"
#endif
#endif
diff --git a/Modules/FiberTracking/Algorithms/StochasticTracking/itkSlowPolyLineParametricPath.txx b/Modules/FiberTracking/Algorithms/StochasticTracking/itkSlowPolyLineParametricPath.txx
index c951a3e..d41b295 100644
--- a/Modules/FiberTracking/Algorithms/StochasticTracking/itkSlowPolyLineParametricPath.txx
+++ b/Modules/FiberTracking/Algorithms/StochasticTracking/itkSlowPolyLineParametricPath.txx
@@ -1,130 +1,130 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _itkSlowPolyLineParametricPath_txx
#define _itkSlowPolyLineParametricPath_txx
#include "itkSlowPolyLineParametricPath.h"
#include <math.h>
namespace itk
{
//template<unsigned int VDimension>
//typename SlowPolyLineParametricPath<VDimension>::VectorType
//SlowPolyLineParametricPath<VDimension>
//::EvaluateDerivative(const InputType & input) const
//{
//}
/**
* Constructor
*/
template <unsigned int VDimension>
SlowPolyLineParametricPath<VDimension>
::SlowPolyLineParametricPath()
{
this->SetDefaultInputStepSize( 0.3 );
}
template<unsigned int VDimension>
typename SlowPolyLineParametricPath<VDimension>::OffsetType
SlowPolyLineParametricPath<VDimension>
::IncrementInput(InputType & input) const
{
int iterationCount;
bool tooSmall;
bool tooBig;
InputType inputStepSize;
InputType finalInputValue;
OffsetType offset;
IndexType currentImageIndex;
IndexType nextImageIndex;
IndexType finalImageIndex;
iterationCount = 0;
inputStepSize = this->GetDefaultInputStepSize();
// Are we already at (or past) the end of the input?
finalInputValue = this->EndOfInput();
currentImageIndex = this->EvaluateToIndex( input );
finalImageIndex = this->EvaluateToIndex( finalInputValue );
offset = finalImageIndex - currentImageIndex;
if( ( offset == this->GetZeroOffset() && input != this->StartOfInput() ) ||
( input >=finalInputValue ) )
{
return this->GetZeroOffset();
}
do
{
if( iterationCount++ > 10000 ) {return this->GetZeroOffset(); itkExceptionMacro(<<"Too many iterations");}
nextImageIndex = this->EvaluateToIndex( input + inputStepSize );
offset = nextImageIndex - currentImageIndex;
tooBig = false;
tooSmall = ( offset == this->GetZeroOffset() );
if( tooSmall )
{
// increase the input step size, but don't go past the end of the input
inputStepSize *= 2;
if( (input + inputStepSize) >= finalInputValue ){
//inputStepSize = finalInputValue - input;
inputStepSize += this->GetDefaultInputStepSize();
}
}
else
{
// Search for an offset dimension that is too big
for( unsigned int i=0; i<VDimension && !tooBig; i++ )
{
tooBig = ( offset[i] >= 2 || offset[i] <= -2 );
}
if( tooBig ){
//inputStepSize /= 1.5;
inputStepSize -= (this->GetDefaultInputStepSize()/0.5);
}
}
}
while( tooSmall || tooBig );
input += inputStepSize;
return offset;
}
/**
* Standard "PrintSelf" method
*/
template <unsigned int VDimension>
void
SlowPolyLineParametricPath<VDimension>
::PrintSelf( std::ostream& os, Indent indent) const
{
Superclass::PrintSelf( os, indent );
}
} // end namespaceitk
#endif
diff --git a/Modules/FiberTracking/Algorithms/StochasticTracking/itkStochasticTractographyFilter_SD.txx b/Modules/FiberTracking/Algorithms/StochasticTracking/itkStochasticTractographyFilter_SD.txx
index cfe4982..1110c92 100644
--- a/Modules/FiberTracking/Algorithms/StochasticTracking/itkStochasticTractographyFilter_SD.txx
+++ b/Modules/FiberTracking/Algorithms/StochasticTracking/itkStochasticTractographyFilter_SD.txx
@@ -1,2601 +1,2601 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "itkStochasticTractographyFilter.h"
namespace itk{
template< class TInputDWIImage, class TInputMaskImage, class TOutputConnectivityImage >
void
StochasticTractographyFilter< TInputDWIImage, TInputMaskImage, TOutputConnectivityImage >
::LoadDefaultSampleDirections( void ){
const unsigned int totalsd = 2562;
double sdarray[totalsd][3] = {
{0.850651, 0.525731, 6.12323e-17},
{-0.850651, 0.525731, 6.12323e-17},
{-0.850651 , -0.525731, 6.12323e-17},
{0.850651, -0.525731, 6.12323e-17},
{0.525731, 0, 0.850651},
{0.525731, 0, -0.850651},
{-0.525731, 6.43835e-17, -0.850651},
{-0.525731, 6.43835e-17, 0.850651},
{5.20873e-17, 0.850651, 0.525731},
{5.20873e-17, -0.850651, 0.525731},
{5.20873e-17, -0.850651, -0.525731},
{5.20873e-17, 0.850651, -0.525731},
{0, 0, 1},
{-0.309017, 0.5, 0.809017 },
{0.309017, 0.5, 0.809017},
{0.309017, -0.5, 0.809017},
{-0.309017, -0.5, 0.809017},
{0.309017, 0.5, -0.809017},
{-0.309017, 0.5, -0.809017},
{1.22465e-16, 0, -1},
{-0.309017 , -0.5, -0.809017},
{0.309017, -0.5, -0.809017},
{1, 0, 6.12323e-17},
{0.809017, -0.309017, 0.5},
{0.809017, 0.309017, 0.5},
{0.809017, 0.309017, -0.5},
{0.809017, -0.309017, -0.5 },
{-1, 1.22465e-16, 6.12323e-17},
{-0.809017, 0.309017, 0.5},
{-0.809017, -0.309017, 0.5},
{-0.809017, -0.309017, -0.5},
{-0.809017, 0.309017, -0.5},
{6.12323e-17, 1, 6.12323e-17 },
{0.5, 0.809017, -0.309017},
{0.5, 0.809017, 0.309017},
{-0.5, 0.809017, 0.309017},
{-0.5, 0.809017, -0.309017},
{0.5, -0.809017, 0.309017},
{0.5, -0.809017, -0.309017},
{ 6.12323e-17, -1, 6.12323e-17},
{-0.5, -0.809017, -0.309017},
{-0.5, -0.809017, 0.309017},
{0.273267, 0, 0.961938},
{0.16246, 0.262866, 0.951057},
{0.433889, 0.259892, 0.862668},
{- 0.273267, 3.34655e-17, 0.961938},
{-0.433889, 0.259892, 0.862668},
{-0.16246, 0.262866, 0.951057},
{-8.4544e-17, 0.525731, 0.850651},
{-0.160622, 0.702046, 0.69378},
{0.160622, 0.702046, 0.69378},
{0.433889, -0.259892, 0.862668},
{0.16246, -0.262866, 0.951057},
{0.160622, -0.702046, 0.69378},
{-0.160622, -0.702046, 0.69378},
{-8.4544e-17, -0.525731, 0.850651},
{-0.16246 , -0.262866, 0.951057},
{-0.433889, -0.259892, 0.862668},
{0.433889, 0.259892, -0.862668},
{0.16246, 0.262866, -0.951057},
{0.273267, 0, -0.961938},
{0.160622, 0.702046, -0.69378},
{- 0.160622, 0.702046, -0.69378},
{-8.4544e-17, 0.525731, -0.850651},
{-0.16246, 0.262866, -0.951057},
{-0.433889, 0.259892, -0.862668},
{-0.273267, 3.34655e-17, -0.961938},
{0.16246, -0.262866 , -0.951057},
{0.433889, -0.259892, -0.862668},
{-0.433889, -0.259892, -0.862668},
{-0.16246, -0.262866, -0.951057},
{-8.4544e-17, -0.525731, -0.850651},
{-0.160622, -0.702046, -0.69378},
{0.160622, -0.702046, -0.69378},
{0.961938, 0.273267, 6.12323e-17},
{0.951057, 0.16246, 0.262866},
{0.862668, 0.433889, 0.259892},
{0.961938, -0.273267, 6.12323e-17},
{0.862668, - 0.433889, 0.259892},
{0.951057, -0.16246, 0.262866},
{0.850651, 0, 0.525731},
{0.69378, -0.160622, 0.702046},
{0.69378, 0.160622, 0.702046},
{0.862668, 0.433889, -0.259892},
{0.951057 , 0.16246, -0.262866},
{0.69378, 0.160622, -0.702046},
{0.69378, -0.160622, -0.702046},
{0.850651, 0, -0.525731},
{0.951057, -0.16246, -0.262866},
{0.862668, -0.433889, -0.259892},
{- 0.961938, -0.273267, 6.12323e-17},
{-0.951057, -0.16246, 0.262866},
{-0.862668, -0.433889, 0.259892},
{-0.961938, 0.273267, 6.12323e-17},
{-0.862668, 0.433889, 0.259892},
{-0.951057, 0.16246 , 0.262866},
{-0.850651, 1.04175e-16, 0.525731},
{-0.69378, 0.160622, 0.702046},
{-0.69378, -0.160622, 0.702046},
{-0.862668, -0.433889, -0.259892},
{-0.951057, -0.16246, -0.262866},
{-0.69378, -0.160622, -0.702046},
{-0.69378, 0.160622, -0.702046},
{-0.850651, 1.04175e-16, -0.525731},
{-0.951057, 0.16246, -0.262866},
{-0.862668, 0.433889, -0.259892},
{5.89017e-17 , 0.961938, 0.273267},
{0.262866, 0.951057, 0.16246},
{0.259892, 0.862668, 0.433889},
{5.89017e-17, 0.961938, -0.273267},
{0.259892, 0.862668, -0.433889},
{0.262866, 0.951057, -0.16246},
{0.525731, 0.850651, -1.60812e-16},
{0.702046, 0.69378, -0.160622},
{0.702046, 0.69378, 0.160622},
{-0.259892, 0.862668, 0.433889},
{-0.262866, 0.951057, 0.16246},
{-0.702046, 0.69378 , 0.160622},
{-0.702046, 0.69378, -0.160622},
{-0.525731, 0.850651, -1.60812e-16},
{-0.262866, 0.951057, -0.16246},
{-0.259892, 0.862668, -0.433889},
{0.259892, -0.862668, 0.433889},
{0.262866, -0.951057, 0.16246},
{5.89017e-17, -0.961938, 0.273267},
{0.702046, -0.69378, 0.160622},
{0.702046, -0.69378, -0.160622},
{0.525731, -0.850651, -1.60812e-16},
{0.262866, - 0.951057, -0.16246},
{0.259892, -0.862668, -0.433889},
{5.89017e-17, -0.961938, -0.273267},
{-0.262866, -0.951057, 0.16246},
{-0.259892, -0.862668, 0.433889},
{-0.259892, -0.862668, -0.433889 },
{-0.262866, -0.951057, -0.16246},
{-0.525731, -0.850651, -1.60812e-16},
{-0.702046, -0.69378, -0.160622},
{-0.702046, -0.69378, 0.160622},
{0.425325, 0.688191, 0.587785},
{0.688191 , 0.587785, 0.425325},
{0.587785, 0.425325, 0.688191},
{0.425325, 0.688191, -0.587785},
{0.587785, 0.425325, -0.688191},
{0.688191, 0.587785, -0.425325},
{0.587785, -0.425325, 0.688191},
{0.688191, -0.587785, 0.425325},
{0.425325, -0.688191, 0.587785},
{0.587785, -0.425325, -0.688191},
{0.425325, -0.688191, -0.587785},
{0.688191, -0.587785, -0.425325},
{-0.587785 , 0.425325, 0.688191},
{-0.688191, 0.587785, 0.425325},
{-0.425325, 0.688191, 0.587785},
{-0.587785, 0.425325, -0.688191},
{-0.425325, 0.688191, -0.587785},
{-0.688191, 0.587785, -0.425325 },
{-0.587785, -0.425325, 0.688191},
{-0.425325, -0.688191, 0.587785},
{-0.688191, -0.587785, 0.425325},
{-0.587785, -0.425325, -0.688191},
{-0.688191, -0.587785, -0.425325},
{-0.425325 , -0.688191, -0.587785},
{0.403355, 0, 0.915043},
{0.358229, 0.131655, 0.924305},
{0.484442, 0.1312, 0.864929},
{0.137952, 0, 0.990439},
{0.0822425, 0.133071, 0.987688},
{0.220117 , 0.132792, 0.966393},
{0.301259, 0.264083, 0.916244},
{0.238677, 0.386187, 0.891007},
{0.375039, 0.383614, 0.843911},
{-0.137952, 1.68943e-17, 0.990439},
{-0.220117, 0.132792, 0.966393},
{-0.0822425, 0.133071, 0.987688},
{-0.403355, 4.93968e-17, 0.915043},
{-0.484442, 0.1312, 0.864929},
{-0.358229, 0.131655, 0.924305},
{-0.301259, 0.264083, 0.916244},
{-0.375039, 0.383614, 0.843911},
{-0.238677, 0.386187, 0.891007},
{0.156434, 0.519258, 0.840178},
{0.0811419, 0.62024, 0.780204},
{0.237086, 0.606825, 0.758652},
{-0.156434, 0.519258, 0.840178},
{-0.237086, 0.606825, 0.758652},
{-0.0811419, 0.62024, 0.780204},
{-1.14383e-16, 0.711282, 0.702907},
{-0.0810863, 0.783843, 0.615642},
{0.0810863, 0.783843, 0.615642},
{-4.28411e-17 , 0.266405, 0.963861},
{-0.0823236, 0.399607, 0.912982},
{0.0823236, 0.399607, 0.912982},
{0.484442, -0.1312, 0.864929},
{0.358229, -0.131655, 0.924305},
{0.375039, -0.383614, 0.843911},
{0.238677, -0.386187, 0.891007},
{0.301259, -0.264083, 0.916244},
{0.220117, -0.132792, 0.966393},
{0.0822425, -0.133071, 0.987688},
{0.237086, -0.606825, 0.758652},
{0.0811419, - 0.62024, 0.780204},
{0.156434, -0.519258, 0.840178},
{0.0810863, -0.783843, 0.615642},
{-0.0810863, -0.783843, 0.615642},
{-1.14383e-16, -0.711282, 0.702907},
{-0.0811419, -0.62024, 0.780204 },
{-0.237086, -0.606825, 0.758652},
{-0.156434, -0.519258, 0.840178},
{-0.0822425, -0.133071, 0.987688},
{-0.220117, -0.132792, 0.966393},
{-0.238677, -0.386187, 0.891007},
{-0.375039 , -0.383614, 0.843911},
{-0.301259, -0.264083, 0.916244},
{-0.358229, -0.131655, 0.924305},
{-0.484442, -0.1312, 0.864929},
{0.0823236, -0.399607, 0.912982},
{-0.0823236, -0.399607, 0.912982 },
{-4.28411e-17, -0.266405, 0.963861},
{0.484442, 0.1312, -0.864929},
{0.358229, 0.131655, -0.924305},
{0.403355, 0, -0.915043},
{0.375039, 0.383614, -0.843911},
{0.238677, 0.386187 , -0.891007},
{0.301259, 0.264083, -0.916244},
{0.220117, 0.132792, -0.966393},
{0.0822425, 0.133071, -0.987688},
{0.137952, 0, -0.990439},
{0.237086, 0.606825, -0.758652},
{0.0811419 , 0.62024, -0.780204},
{0.156434, 0.519258, -0.840178},
{0.0810863, 0.783843, -0.615642},
{-0.0810863, 0.783843, -0.615642},
{4.35534e-17, 0.711282, -0.702907},
{-0.0811419, 0.62024, -0.780204 },
{-0.237086, 0.606825, -0.758652},
{-0.156434, 0.519258, -0.840178},
{-0.0822425, 0.133071, -0.987688},
{-0.220117, 0.132792, -0.966393},
{-0.137952, 1.68943e-17, -0.990439},
{- 0.238677, 0.386187, -0.891007},
{-0.375039, 0.383614, -0.843911},
{-0.301259, 0.264083, -0.916244},
{-0.358229, 0.131655, -0.924305},
{-0.484442, 0.1312, -0.864929},
{-0.403355, 4.93968e-17 , -0.915043},
{0.0823236, 0.399607, -0.912982},
{-0.0823236, 0.399607, -0.912982},
{1.63126e-17, 0.266405, -0.963861},
{0.358229, -0.131655, -0.924305},
{0.484442, -0.1312, -0.864929},
{0.0822425, -0.133071, -0.987688},
{0.220117, -0.132792, -0.966393},
{0.301259, -0.264083, -0.916244},
{0.238677, -0.386187, -0.891007},
{0.375039, -0.383614, -0.843911},
{-0.220117, - 0.132792, -0.966393},
{-0.0822425, -0.133071, -0.987688},
{-0.484442, -0.1312, -0.864929},
{-0.358229, -0.131655, -0.924305},
{-0.301259, -0.264083, -0.916244},
{-0.375039, -0.383614, -0.843911 },
{-0.238677, -0.386187, -0.891007},
{0.156434, -0.519258, -0.840178},
{0.0811419, -0.62024, -0.780204},
{0.237086, -0.606825, -0.758652},
{-0.156434, -0.519258, -0.840178},
{-0.237086 , -0.606825, -0.758652},
{-0.0811419, -0.62024, -0.780204},
{4.35534e-17, -0.711282, -0.702907},
{-0.0810863, -0.783843, -0.615642},
{0.0810863, -0.783843, -0.615642},
{1.63126e-17, -0.266405 , -0.963861},
{-0.0823236, -0.399607, -0.912982},
{0.0823236, -0.399607, -0.912982},
{0.915043, 0.403355, 6.12323e-17},
{0.924305, 0.358229, 0.131655},
{0.864929, 0.484442, 0.1312},
{ 0.990439, 0.137952, 6.12323e-17},
{0.987688, 0.0822425, 0.133071},
{0.966393, 0.220117, 0.132792},
{0.916244, 0.301259, 0.264083},
{0.891007, 0.238677, 0.386187},
{0.843911, 0.375039, 0.383614 },
{0.990439, -0.137952, 6.12323e-17},
{0.966393, -0.220117, 0.132792},
{0.987688, -0.0822425, 0.133071},
{0.915043, -0.403355, 6.12323e-17},
{0.864929, -0.484442, 0.1312},
{0.924305 , -0.358229, 0.131655},
{0.916244, -0.301259, 0.264083},
{0.843911, -0.375039, 0.383614},
{0.891007, -0.238677, 0.386187},
{0.840178, 0.156434, 0.519258},
{0.780204, 0.0811419, 0.62024},
{0.758652, 0.237086, 0.606825},
{0.840178, -0.156434, 0.519258},
{0.758652, -0.237086, 0.606825},
{0.780204, -0.0811419, 0.62024},
{0.702907, 0, 0.711282},
{0.615642, -0.0810863, 0.783843},
{0.615642, 0.0810863, 0.783843},
{0.963861, 0, 0.266405},
{0.912982, -0.0823236, 0.399607},
{0.912982, 0.0823236, 0.399607},
{0.864929, 0.484442, -0.1312},
{0.924305, 0.358229 , -0.131655},
{0.843911, 0.375039, -0.383614},
{0.891007, 0.238677, -0.386187},
{0.916244, 0.301259, -0.264083},
{0.966393, 0.220117, -0.132792},
{0.987688, 0.0822425, -0.133071},
{ 0.758652, 0.237086, -0.606825},
{0.780204, 0.0811419, -0.62024},
{0.840178, 0.156434, -0.519258},
{0.615642, 0.0810863, -0.783843},
{0.615642, -0.0810863, -0.783843},
{0.702907, 0, -0.711282 },
{0.780204, -0.0811419, -0.62024},
{0.758652, -0.237086, -0.606825},
{0.840178, -0.156434, -0.519258},
{0.987688, -0.0822425, -0.133071},
{0.966393, -0.220117, -0.132792},
{0.891007 , -0.238677, -0.386187},
{0.843911, -0.375039, -0.383614},
{0.916244, -0.301259, -0.264083},
{0.924305, -0.358229, -0.131655},
{0.864929, -0.484442, -0.1312},
{0.912982, 0.0823236, -0.399607 },
{0.912982, -0.0823236, -0.399607},
{0.963861, 0, -0.266405},
{-0.915043, -0.403355, 6.12323e-17},
{-0.924305, -0.358229, 0.131655},
{-0.864929, -0.484442, 0.1312},
{-0.990439, - 0.137952, 6.12323e-17},
{-0.987688, -0.0822425, 0.133071},
{-0.966393, -0.220117, 0.132792},
{-0.916244, -0.301259, 0.264083},
{-0.891007, -0.238677, 0.386187},
{-0.843911, -0.375039, 0.383614 },
{-0.990439, 0.137952, 6.12323e-17},
{-0.966393, 0.220117, 0.132792},
{-0.987688, 0.0822425, 0.133071},
{-0.915043, 0.403355, 6.12323e-17},
{-0.864929, 0.484442, 0.1312},
{-0.924305 , 0.358229, 0.131655},
{-0.916244, 0.301259, 0.264083},
{-0.843911, 0.375039, 0.383614},
{-0.891007, 0.238677, 0.386187},
{-0.840178, -0.156434, 0.519258},
{-0.780204, -0.0811419, 0.62024 },
{-0.758652, -0.237086, 0.606825},
{-0.840178, 0.156434, 0.519258},
{-0.758652, 0.237086, 0.606825},
{-0.780204, 0.0811419, 0.62024},
{-0.702907, 8.60813e-17, 0.711282},
{-0.615642 , 0.0810863, 0.783843},
{-0.615642, -0.0810863, 0.783843},
{-0.963861, 1.18039e-16, 0.266405},
{-0.912982, 0.0823236, 0.399607},
{-0.912982, -0.0823236, 0.399607},
{-0.864929, -0.484442, - 0.1312},
{-0.924305, -0.358229, -0.131655},
{-0.843911, -0.375039, -0.383614},
{-0.891007, -0.238677, -0.386187},
{-0.916244, -0.301259, -0.264083},
{-0.966393, -0.220117, -0.132792},
{-0.987688, -0.0822425, -0.133071},
{-0.758652, -0.237086, -0.606825},
{-0.780204, -0.0811419, -0.62024},
{-0.840178, -0.156434, -0.519258},
{-0.615642, -0.0810863, -0.783843},
{-0.615642 , 0.0810863, -0.783843},
{-0.702907, 8.60813e-17, -0.711282},
{-0.780204, 0.0811419, -0.62024},
{-0.758652, 0.237086, -0.606825},
{-0.840178, 0.156434, -0.519258},
{-0.987688, 0.0822425, - 0.133071},
{-0.966393, 0.220117, -0.132792},
{-0.891007, 0.238677, -0.386187},
{-0.843911, 0.375039, -0.383614},
{-0.916244, 0.301259, -0.264083},
{-0.924305, 0.358229, -0.131655},
{- 0.864929, 0.484442, -0.1312},
{-0.912982, -0.0823236, -0.399607},
{-0.912982, 0.0823236, -0.399607},
{-0.963861, 1.18039e-16, -0.266405},
{5.60302e-17, 0.915043, 0.403355},
{0.131655, 0.924305 , 0.358229},
{0.1312, 0.864929, 0.484442},
{6.06469e-17, 0.990439, 0.137952},
{0.133071, 0.987688, 0.0822425},
{0.132792, 0.966393, 0.220117},
{0.264083, 0.916244, 0.301259},
{0.386187 , 0.891007, 0.238677},
{0.383614, 0.843911, 0.375039},
{6.06469e-17, 0.990439, -0.137952},
{0.132792, 0.966393, -0.220117},
{0.133071, 0.987688, -0.0822425},
{5.60302e-17, 0.915043, -0.403355 },
{0.1312, 0.864929, -0.484442},
{0.131655, 0.924305, -0.358229},
{0.264083, 0.916244, -0.301259},
{0.383614, 0.843911, -0.375039},
{0.386187, 0.891007, -0.238677},
{0.519258, 0.840178 , 0.156434},
{0.62024, 0.780204, 0.0811419},
{0.606825, 0.758652, 0.237086},
{0.519258, 0.840178, -0.156434},
{0.606825, 0.758652, -0.237086},
{0.62024, 0.780204, -0.0811419},
{0.711282 , 0.702907, -1.60812e-16},
{0.783843, 0.615642, -0.0810863},
{0.783843, 0.615642, 0.0810863},
{0.266405, 0.963861, -1.60812e-16},
{0.399607, 0.912982, -0.0823236},
{0.399607, 0.912982, 0.0823236 },
{-0.1312, 0.864929, 0.484442},
{-0.131655, 0.924305, 0.358229},
{-0.383614, 0.843911, 0.375039},
{-0.386187, 0.891007, 0.238677},
{-0.264083, 0.916244, 0.301259},
{-0.132792, 0.966393 , 0.220117},
{-0.133071, 0.987688, 0.0822425},
{-0.606825, 0.758652, 0.237086},
{-0.62024, 0.780204, 0.0811419},
{-0.519258, 0.840178, 0.156434},
{-0.783843, 0.615642, 0.0810863},
{- 0.783843, 0.615642, -0.0810863},
{-0.711282, 0.702907, -1.60812e-16},
{-0.62024, 0.780204, -0.0811419},
{-0.606825, 0.758652, -0.237086},
{-0.519258, 0.840178, -0.156434},
{-0.133071, 0.987688 , -0.0822425},
{-0.132792, 0.966393, -0.220117},
{-0.386187, 0.891007, -0.238677},
{-0.383614, 0.843911, -0.375039},
{-0.264083, 0.916244, -0.301259},
{-0.131655, 0.924305, -0.358229},
{-0.1312, 0.864929, -0.484442},
{-0.399607, 0.912982, 0.0823236},
{-0.399607, 0.912982, -0.0823236},
{-0.266405, 0.963861, -1.60812e-16},
{0.1312, -0.864929, 0.484442},
{0.131655, -0.924305 , 0.358229},
{5.60302e-17, -0.915043, 0.403355},
{0.383614, -0.843911, 0.375039},
{0.386187, -0.891007, 0.238677},
{0.264083, -0.916244, 0.301259},
{0.132792, -0.966393, 0.220117},
{ 0.133071, -0.987688, 0.0822425},
{6.06469e-17, -0.990439, 0.137952},
{0.606825, -0.758652, 0.237086},
{0.62024, -0.780204, 0.0811419},
{0.519258, -0.840178, 0.156434},
{0.783843, -0.615642 , 0.0810863},
{0.783843, -0.615642, -0.0810863},
{0.711282, -0.702907, -1.60812e-16},
{0.62024, -0.780204, -0.0811419},
{0.606825, -0.758652, -0.237086},
{0.519258, -0.840178, -0.156434},
{0.133071, -0.987688, -0.0822425},
{0.132792, -0.966393, -0.220117},
{6.06469e-17, -0.990439, -0.137952},
{0.386187, -0.891007, -0.238677},
{0.383614, -0.843911, -0.375039},
{0.264083 , -0.916244, -0.301259},
{0.131655, -0.924305, -0.358229},
{0.1312, -0.864929, -0.484442},
{5.60302e-17, -0.915043, -0.403355},
{0.399607, -0.912982, 0.0823236},
{0.399607, -0.912982, -0.0823236 },
{0.266405, -0.963861, -1.60812e-16},
{-0.131655, -0.924305, 0.358229},
{-0.1312, -0.864929, 0.484442},
{-0.133071, -0.987688, 0.0822425},
{-0.132792, -0.966393, 0.220117},
{-0.264083 , -0.916244, 0.301259},
{-0.386187, -0.891007, 0.238677},
{-0.383614, -0.843911, 0.375039},
{-0.132792, -0.966393, -0.220117},
{-0.133071, -0.987688, -0.0822425},
{-0.1312, -0.864929, -0.484442 },
{-0.131655, -0.924305, -0.358229},
{-0.264083, -0.916244, -0.301259},
{-0.383614, -0.843911, -0.375039},
{-0.386187, -0.891007, -0.238677},
{-0.519258, -0.840178, 0.156434},
{- 0.62024, -0.780204, 0.0811419},
{-0.606825, -0.758652, 0.237086},
{-0.519258, -0.840178, -0.156434},
{-0.606825, -0.758652, -0.237086},
{-0.62024, -0.780204, -0.0811419},
{-0.711282, -0.702907 , -1.60812e-16},
{-0.783843, -0.615642, -0.0810863},
{-0.783843, -0.615642, 0.0810863},
{-0.266405, -0.963861, -1.60812e-16},
{-0.399607, -0.912982, -0.0823236},
{-0.399607, -0.912982, 0.0823236 },
{0.213023, 0.792649, 0.571252},
{0.46843, 0.757935, 0.453991},
{0.346153, 0.783452, 0.516122},
{0.296005, 0.70231, 0.647412},
{0.371748, 0.601501, 0.707107},
{0.70231, 0.647412 , 0.296005},
{0.601501, 0.707107, 0.371748},
{0.792649, 0.571252, 0.213023},
{0.783452, 0.516122, 0.346153},
{0.757935, 0.453991, 0.46843},
{0.453991, 0.46843, 0.757935},
{0.516122 , 0.346153, 0.783452},
{0.707107, 0.371748, 0.601501},
{0.647412, 0.296005, 0.70231},
{0.571252, 0.213023, 0.792649},
{0.564254, 0.646578, 0.513375},
{0.646578, 0.513375, 0.564254},
{ 0.513375, 0.564254, 0.646578},
{0.213023, 0.792649, -0.571252},
{0.371748, 0.601501, -0.707107},
{0.296005, 0.70231, -0.647412},
{0.346153, 0.783452, -0.516122},
{0.46843, 0.757935, -0.453991 },
{0.516122, 0.346153, -0.783452},
{0.453991, 0.46843, -0.757935},
{0.571252, 0.213023, -0.792649},
{0.647412, 0.296005, -0.70231},
{0.707107, 0.371748, -0.601501},
{0.601501, 0.707107 , -0.371748},
{0.70231, 0.647412, -0.296005},
{0.757935, 0.453991, -0.46843},
{0.783452, 0.516122, -0.346153},
{0.792649, 0.571252, -0.213023},
{0.513375, 0.564254, -0.646578},
{0.646578 , 0.513375, -0.564254},
{0.564254, 0.646578, -0.513375},
{0.571252, -0.213023, 0.792649},
{0.707107, -0.371748, 0.601501},
{0.647412, -0.296005, 0.70231},
{0.516122, -0.346153, 0.783452},
{0.453991, -0.46843, 0.757935},
{0.783452, -0.516122, 0.346153},
{0.757935, -0.453991, 0.46843},
{0.792649, -0.571252, 0.213023},
{0.70231, -0.647412, 0.296005},
{0.601501, -0.707107 , 0.371748},
{0.371748, -0.601501, 0.707107},
{0.296005, -0.70231, 0.647412},
{0.46843, -0.757935, 0.453991},
{0.346153, -0.783452, 0.516122},
{0.213023, -0.792649, 0.571252},
{0.646578 , -0.513375, 0.564254},
{0.564254, -0.646578, 0.513375},
{0.513375, -0.564254, 0.646578},
{0.571252, -0.213023, -0.792649},
{0.453991, -0.46843, -0.757935},
{0.516122, -0.346153, -0.783452 },
{0.647412, -0.296005, -0.70231},
{0.707107, -0.371748, -0.601501},
{0.296005, -0.70231, -0.647412},
{0.371748, -0.601501, -0.707107},
{0.213023, -0.792649, -0.571252},
{0.346153 , -0.783452, -0.516122},
{0.46843, -0.757935, -0.453991},
{0.757935, -0.453991, -0.46843},
{0.783452, -0.516122, -0.346153},
{0.601501, -0.707107, -0.371748},
{0.70231, -0.647412, -0.296005 },
{0.792649, -0.571252, -0.213023},
{0.513375, -0.564254, -0.646578},
{0.564254, -0.646578, -0.513375},
{0.646578, -0.513375, -0.564254},
{-0.571252, 0.213023, 0.792649},
{-0.707107 , 0.371748, 0.601501},
{-0.647412, 0.296005, 0.70231},
{-0.516122, 0.346153, 0.783452},
{-0.453991, 0.46843, 0.757935},
{-0.783452, 0.516122, 0.346153},
{-0.757935, 0.453991, 0.46843},
{-0.792649, 0.571252, 0.213023},
{-0.70231, 0.647412, 0.296005},
{-0.601501, 0.707107, 0.371748},
{-0.371748, 0.601501, 0.707107},
{-0.296005, 0.70231, 0.647412},
{-0.46843, 0.757935 , 0.453991},
{-0.346153, 0.783452, 0.516122},
{-0.213023, 0.792649, 0.571252},
{-0.646578, 0.513375, 0.564254},
{-0.564254, 0.646578, 0.513375},
{-0.513375, 0.564254, 0.646578},
{- 0.571252, 0.213023, -0.792649},
{-0.453991, 0.46843, -0.757935},
{-0.516122, 0.346153, -0.783452},
{-0.647412, 0.296005, -0.70231},
{-0.707107, 0.371748, -0.601501},
{-0.296005, 0.70231, - 0.647412},
{-0.371748, 0.601501, -0.707107},
{-0.213023, 0.792649, -0.571252},
{-0.346153, 0.783452, -0.516122},
{-0.46843, 0.757935, -0.453991},
{-0.757935, 0.453991, -0.46843},
{- 0.783452, 0.516122, -0.346153},
{-0.601501, 0.707107, -0.371748},
{-0.70231, 0.647412, -0.296005},
{-0.792649, 0.571252, -0.213023},
{-0.513375, 0.564254, -0.646578},
{-0.564254, 0.646578 , -0.513375},
{-0.646578, 0.513375, -0.564254},
{-0.571252, -0.213023, 0.792649},
{-0.453991, -0.46843, 0.757935},
{-0.516122, -0.346153, 0.783452},
{-0.647412, -0.296005, 0.70231},
{- 0.707107, -0.371748, 0.601501},
{-0.296005, -0.70231, 0.647412},
{-0.371748, -0.601501, 0.707107},
{-0.213023, -0.792649, 0.571252},
{-0.346153, -0.783452, 0.516122},
{-0.46843, -0.757935 , 0.453991},
{-0.757935, -0.453991, 0.46843},
{-0.783452, -0.516122, 0.346153},
{-0.601501, -0.707107, 0.371748},
{-0.70231, -0.647412, 0.296005},
{-0.792649, -0.571252, 0.213023},
{- 0.513375, -0.564254, 0.646578},
{-0.564254, -0.646578, 0.513375},
{-0.646578, -0.513375, 0.564254},
{-0.571252, -0.213023, -0.792649},
{-0.707107, -0.371748, -0.601501},
{-0.647412, -0.296005 , -0.70231},
{-0.516122, -0.346153, -0.783452},
{-0.453991, -0.46843, -0.757935},
{-0.783452, -0.516122, -0.346153},
{-0.757935, -0.453991, -0.46843},
{-0.792649, -0.571252, -0.213023},
{-0.70231, -0.647412, -0.296005},
{-0.601501, -0.707107, -0.371748},
{-0.371748, -0.601501, -0.707107},
{-0.296005, -0.70231, -0.647412},
{-0.46843, -0.757935, -0.453991},
{-0.346153 , -0.783452, -0.516122},
{-0.213023, -0.792649, -0.571252},
{-0.646578, -0.513375, -0.564254},
{-0.564254, -0.646578, -0.513375},
{-0.513375, -0.564254, -0.646578},
{0.465658, 0, 0.884965 },
{0.445365, 0.0658169, 0.892927},
{0.506298, 0.0657576, 0.859848},
{0.339123, 0, 0.940742},
{0.316778, 0.0660424, 0.946198},
{0.381722, 0.0659884, 0.921919},
{0.422364, 0.131749 , 0.896801},
{0.397351, 0.196412, 0.896401},
{0.460267, 0.196015, 0.865871},
{0.206103, 0, 0.97853},
{0.179596, 0.0666044, 0.981483},
{0.247326, 0.0665669, 0.966643},
{0.0691416, 0, 0.997607},
{0.0412484, 0.0667413, 0.996917},
{0.110385, 0.0667094, 0.991648},
{0.151549, 0.133256, 0.979426},
{0.122729, 0.19858, 0.97237},
{0.19178, 0.198337, 0.961188},
{0.368518 , 0.262661, 0.891742},
{0.339209, 0.324864, 0.882837},
{0.405434, 0.322525, 0.855337},
{0.232455, 0.264151, 0.93605},
{0.201189, 0.32553, 0.92388},
{0.270627, 0.325929, 0.905832},
{ 0.307659, 0.385906, 0.869725},
{0.274694, 0.444464, 0.85264},
{0.342848, 0.442867, 0.828447},
{0.289929, 0.13257, 0.947822},
{0.26155, 0.199094, 0.944433},
{0.330607, 0.198387, 0.922682},
{-0.0691416, 8.4674e-18, 0.997607},
{-0.110385, 0.0667094, 0.991648},
{-0.0412484, 0.0667413, 0.996917},
{-0.206103, 2.52403e-17, 0.97853},
{-0.247326, 0.0665669, 0.966643},
{-0.179596 , 0.0666044, 0.981483},
{-0.151549, 0.133256, 0.979426},
{-0.19178, 0.198337, 0.961188},
{-0.122729, 0.19858, 0.97237},
{-0.339123, 4.15305e-17, 0.940742},
{-0.381722, 0.0659884, 0.921919 },
{-0.316778, 0.0660424, 0.946198},
{-0.465658, 5.70266e-17, 0.884965},
{-0.506298, 0.0657576, 0.859848},
{-0.445365, 0.0658169, 0.892927},
{-0.422364, 0.131749, 0.896801},
{-0.460267 , 0.196015, 0.865871},
{-0.397351, 0.196412, 0.896401},
{-0.232455, 0.264151, 0.93605},
{-0.270627, 0.325929, 0.905832},
{-0.201189, 0.32553, 0.92388},
{-0.368518, 0.262661, 0.891742},
{-0.405434, 0.322525, 0.855337},
{-0.339209, 0.324864, 0.882837},
{-0.307659, 0.385906, 0.869725},
{-0.342848, 0.442867, 0.828447},
{-0.274694, 0.444464, 0.85264},
{-0.289929, 0.13257 , 0.947822},
{-0.330607, 0.198387, 0.922682},
{-0.26155, 0.199094, 0.944433},
{0.233445, 0.511205, 0.827147},
{0.197274, 0.564513, 0.801504},
{0.273707, 0.55474, 0.785715},
{0.0784591 , 0.52411, 0.848029},
{0.0406752, 0.574458, 0.817523},
{0.119078, 0.57114, 0.812169},
{0.159613, 0.615456, 0.771841},
{0.121193, 0.662842, 0.738886},
{0.199331, 0.656006, 0.727958},
{- 0.0784591, 0.52411, 0.848029},
{-0.119078, 0.57114, 0.812169},
{-0.0406752, 0.574458, 0.817523},
{-0.233445, 0.511205, 0.827147},
{-0.273707, 0.55474, 0.785715},
{-0.197274, 0.564513, 0.801504 },
{-0.159613, 0.615456, 0.771841},
{-0.199331, 0.656006, 0.727958},
{-0.121193, 0.662842, 0.738886},
{0.080573, 0.708969, 0.700622},
{0.0406421, 0.749387, 0.660884},
{0.121144, 0.744727 , 0.656282},
{-0.080573, 0.708969, 0.700622},
{-0.121144, 0.744727, 0.656282},
{-0.0406421, 0.749387, 0.660884},
{-1.26468e-16, 0.786433, 0.617676},
{-0.0406404, 0.819207, 0.572056},
{0.0406404, 0.819207, 0.572056},
{-1.00072e-16, 0.622292, 0.782786},
{-0.0406771, 0.667502, 0.743496},
{0.0406771, 0.667502, 0.743496},
{-2.14722e-17, 0.133523, 0.991046},
{-0.0815011 , 0.265518, 0.960655},
{-0.0412509, 0.200368, 0.978852},
{0.0412509, 0.200368, 0.978852},
{0.0815011, 0.265518, 0.960655},
{-0.161006, 0.394136, 0.904839},
{-0.1228, 0.332342, 0.93513},
{-0.198227, 0.454262, 0.868534},
{-0.119755, 0.460882, 0.879345},
{-0.0412992, 0.464213, 0.88476},
{0.1228, 0.332342, 0.93513},
{0.161006, 0.394136, 0.904839},
{0.0412992, 0.464213, 0.88476},
{0.119755, 0.460882, 0.879345},
{0.198227, 0.454262, 0.868534},
{-0.041302, 0.33414, 0.941618},
{-6.44806e-17, 0.400968, 0.916092},
{0.041302, 0.33414, 0.941618},
{0.506298 , -0.0657576, 0.859848},
{0.445365, -0.0658169, 0.892927},
{0.460267, -0.196015, 0.865871},
{0.397351, -0.196412, 0.896401},
{0.422364, -0.131749, 0.896801},
{0.381722, -0.0659884, 0.921919 },
{0.316778, -0.0660424, 0.946198},
{0.405434, -0.322525, 0.855337},
{0.339209, -0.324864, 0.882837},
{0.368518, -0.262661, 0.891742},
{0.342848, -0.442867, 0.828447},
{0.274694, - 0.444464, 0.85264},
{0.307659, -0.385906, 0.869725},
{0.270627, -0.325929, 0.905832},
{0.201189, -0.32553, 0.92388},
{0.232455, -0.264151, 0.93605},
{0.247326, -0.0665669, 0.966643},
{0.179596, -0.0666044, 0.981483},
{0.19178, -0.198337, 0.961188},
{0.122729, -0.19858, 0.97237},
{0.151549, -0.133256, 0.979426},
{0.110385, -0.0667094, 0.991648},
{0.0412484, -0.0667413 , 0.996917},
{0.330607, -0.198387, 0.922682},
{0.26155, -0.199094, 0.944433},
{0.289929, -0.13257, 0.947822},
{0.273707, -0.55474, 0.785715},
{0.197274, -0.564513, 0.801504},
{0.233445 , -0.511205, 0.827147},
{0.199331, -0.656006, 0.727958},
{0.121193, -0.662842, 0.738886},
{0.159613, -0.615456, 0.771841},
{0.119078, -0.57114, 0.812169},
{0.0406752, -0.574458, 0.817523 },
{0.0784591, -0.52411, 0.848029},
{0.121144, -0.744727, 0.656282},
{0.0406421, -0.749387, 0.660884},
{0.080573, -0.708969, 0.700622},
{0.0406404, -0.819207, 0.572056},
{-0.0406404 , -0.819207, 0.572056},
{-1.26468e-16, -0.786433, 0.617676},
{-0.0406421, -0.749387, 0.660884},
{-0.121144, -0.744727, 0.656282},
{-0.080573, -0.708969, 0.700622},
{-0.0406752, -0.574458 , 0.817523},
{-0.119078, -0.57114, 0.812169},
{-0.0784591, -0.52411, 0.848029},
{-0.121193, -0.662842, 0.738886},
{-0.199331, -0.656006, 0.727958},
{-0.159613, -0.615456, 0.771841},
{- 0.197274, -0.564513, 0.801504},
{-0.273707, -0.55474, 0.785715},
{-0.233445, -0.511205, 0.827147},
{0.0406771, -0.667502, 0.743496},
{-0.0406771, -0.667502, 0.743496},
{-1.00072e-16, -0.622292 , 0.782786},
{-0.0412484, -0.0667413, 0.996917},
{-0.110385, -0.0667094, 0.991648},
{-0.122729, -0.19858, 0.97237},
{-0.19178, -0.198337, 0.961188},
{-0.151549, -0.133256, 0.979426},
{-0.179596, -0.0666044, 0.981483},
{-0.247326, -0.0665669, 0.966643},
{-0.201189, -0.32553, 0.92388},
{-0.270627, -0.325929, 0.905832},
{-0.232455, -0.264151, 0.93605},
{-0.274694, - 0.444464, 0.85264},
{-0.342848, -0.442867, 0.828447},
{-0.307659, -0.385906, 0.869725},
{-0.339209, -0.324864, 0.882837},
{-0.405434, -0.322525, 0.855337},
{-0.368518, -0.262661, 0.891742 },
{-0.316778, -0.0660424, 0.946198},
{-0.381722, -0.0659884, 0.921919},
{-0.397351, -0.196412, 0.896401},
{-0.460267, -0.196015, 0.865871},
{-0.422364, -0.131749, 0.896801},
{-0.445365 , -0.0658169, 0.892927},
{-0.506298, -0.0657576, 0.859848},
{-0.26155, -0.199094, 0.944433},
{-0.330607, -0.198387, 0.922682},
{-0.289929, -0.13257, 0.947822},
{0.198227, -0.454262, 0.868534 },
{0.0412992, -0.464213, 0.88476},
{0.119755, -0.460882, 0.879345},
{0.161006, -0.394136, 0.904839},
{0.1228, -0.332342, 0.93513},
{-0.119755, -0.460882, 0.879345},
{-0.0412992, - 0.464213, 0.88476},
{-0.198227, -0.454262, 0.868534},
{-0.161006, -0.394136, 0.904839},
{-0.1228, -0.332342, 0.93513},
{0.0815011, -0.265518, 0.960655},
{0.0412509, -0.200368, 0.978852},
{-0.0815011, -0.265518, 0.960655},
{-0.0412509, -0.200368, 0.978852},
{-2.14722e-17, -0.133523, 0.991046},
{-6.44806e-17, -0.400968, 0.916092},
{-0.041302, -0.33414, 0.941618},
{ 0.041302, -0.33414, 0.941618},
{0.506298, 0.0657576, -0.859848},
{0.445365, 0.0658169, -0.892927},
{0.465658, 0, -0.884965},
{0.460267, 0.196015, -0.865871},
{0.397351, 0.196412, -0.896401 },
{0.422364, 0.131749, -0.896801},
{0.381722, 0.0659884, -0.921919},
{0.316778, 0.0660424, -0.946198},
{0.339123, 0, -0.940742},
{0.405434, 0.322525, -0.855337},
{0.339209, 0.324864 , -0.882837},
{0.368518, 0.262661, -0.891742},
{0.342848, 0.442867, -0.828447},
{0.274694, 0.444464, -0.85264},
{0.307659, 0.385906, -0.869725},
{0.270627, 0.325929, -0.905832},
{ 0.201189, 0.32553, -0.92388},
{0.232455, 0.264151, -0.93605},
{0.247326, 0.0665669, -0.966643},
{0.179596, 0.0666044, -0.981483},
{0.206103, 0, -0.97853},
{0.19178, 0.198337, -0.961188},
{0.122729, 0.19858, -0.97237},
{0.151549, 0.133256, -0.979426},
{0.110385, 0.0667094, -0.991648},
{0.0412484, 0.0667413, -0.996917},
{0.0691416, 0, -0.997607},
{0.330607, 0.198387 , -0.922682},
{0.26155, 0.199094, -0.944433},
{0.289929, 0.13257, -0.947822},
{0.273707, 0.55474, -0.785715},
{0.197274, 0.564513, -0.801504},
{0.233445, 0.511205, -0.827147},
{0.199331 , 0.656006, -0.727958},
{0.121193, 0.662842, -0.738886},
{0.159613, 0.615456, -0.771841},
{0.119078, 0.57114, -0.812169},
{0.0406752, 0.574458, -0.817523},
{0.0784591, 0.52411, -0.848029 },
{0.121144, 0.744727, -0.656282},
{0.0406421, 0.749387, -0.660884},
{0.080573, 0.708969, -0.700622},
{0.0406404, 0.819207, -0.572056},
{-0.0406404, 0.819207, -0.572056},
{-1.26468e-16 , 0.786433, -0.617676},
{-0.0406421, 0.749387, -0.660884},
{-0.121144, 0.744727, -0.656282},
{-0.080573, 0.708969, -0.700622},
{-0.0406752, 0.574458, -0.817523},
{-0.119078, 0.57114, -0.812169 },
{-0.0784591, 0.52411, -0.848029},
{-0.121193, 0.662842, -0.738886},
{-0.199331, 0.656006, -0.727958},
{-0.159613, 0.615456, -0.771841},
{-0.197274, 0.564513, -0.801504},
{-0.273707 , 0.55474, -0.785715},
{-0.233445, 0.511205, -0.827147},
{0.0406771, 0.667502, -0.743496},
{-0.0406771, 0.667502, -0.743496},
{-1.00072e-16, 0.622292, -0.782786},
{-0.0412484, 0.0667413, - 0.996917},
{-0.110385, 0.0667094, -0.991648},
{-0.0691416, 8.4674e-18, -0.997607},
{-0.122729, 0.19858, -0.97237},
{-0.19178, 0.198337, -0.961188},
{-0.151549, 0.133256, -0.979426},
{- 0.179596, 0.0666044, -0.981483},
{-0.247326, 0.0665669, -0.966643},
{-0.206103, 2.52403e-17, -0.97853},
{-0.201189, 0.32553, -0.92388},
{-0.270627, 0.325929, -0.905832},
{-0.232455, 0.264151 , -0.93605},
{-0.274694, 0.444464, -0.85264},
{-0.342848, 0.442867, -0.828447},
{-0.307659, 0.385906, -0.869725},
{-0.339209, 0.324864, -0.882837},
{-0.405434, 0.322525, -0.855337},
{- 0.368518, 0.262661, -0.891742},
{-0.316778, 0.0660424, -0.946198},
{-0.381722, 0.0659884, -0.921919},
{-0.339123, 4.15305e-17, -0.940742},
{-0.397351, 0.196412, -0.896401},
{-0.460267, 0.196015 , -0.865871},
{-0.422364, 0.131749, -0.896801},
{-0.445365, 0.0658169, -0.892927},
{-0.506298, 0.0657576, -0.859848},
{-0.465658, 5.70266e-17, -0.884965},
{-0.26155, 0.199094, -0.944433},
{-0.330607, 0.198387, -0.922682},
{-0.289929, 0.13257, -0.947822},
{0.198227, 0.454262, -0.868534},
{0.0412992, 0.464213, -0.88476},
{0.119755, 0.460882, -0.879345},
{0.161006, 0.394136 , -0.904839},
{0.1228, 0.332342, -0.93513},
{-0.119755, 0.460882, -0.879345},
{-0.0412992, 0.464213, -0.88476},
{-0.198227, 0.454262, -0.868534},
{-0.161006, 0.394136, -0.904839},
{- 0.1228, 0.332342, -0.93513},
{0.0815011, 0.265518, -0.960655},
{0.0412509, 0.200368, -0.978852},
{-0.0815011, 0.265518, -0.960655},
{-0.0412509, 0.200368, -0.978852},
{3.78241e-17, 0.133523 , -0.991046},
{-6.44806e-17, 0.400968, -0.916092},
{-0.041302, 0.33414, -0.941618},
{0.041302, 0.33414, -0.941618},
{0.445365, -0.0658169, -0.892927},
{0.506298, -0.0657576, -0.859848},
{0.316778, -0.0660424, -0.946198},
{0.381722, -0.0659884, -0.921919},
{0.422364, -0.131749, -0.896801},
{0.397351, -0.196412, -0.896401},
{0.460267, -0.196015, -0.865871},
{0.179596, - 0.0666044, -0.981483},
{0.247326, -0.0665669, -0.966643},
{0.0412484, -0.0667413, -0.996917},
{0.110385, -0.0667094, -0.991648},
{0.151549, -0.133256, -0.979426},
{0.122729, -0.19858, -0.97237 },
{0.19178, -0.198337, -0.961188},
{0.368518, -0.262661, -0.891742},
{0.339209, -0.324864, -0.882837},
{0.405434, -0.322525, -0.855337},
{0.232455, -0.264151, -0.93605},
{0.201189 , -0.32553, -0.92388},
{0.270627, -0.325929, -0.905832},
{0.307659, -0.385906, -0.869725},
{0.274694, -0.444464, -0.85264},
{0.342848, -0.442867, -0.828447},
{0.289929, -0.13257, -0.947822 },
{0.26155, -0.199094, -0.944433},
{0.330607, -0.198387, -0.922682},
{-0.110385, -0.0667094, -0.991648},
{-0.0412484, -0.0667413, -0.996917},
{-0.247326, -0.0665669, -0.966643},
{- 0.179596, -0.0666044, -0.981483},
{-0.151549, -0.133256, -0.979426},
{-0.19178, -0.198337, -0.961188},
{-0.122729, -0.19858, -0.97237},
{-0.381722, -0.0659884, -0.921919},
{-0.316778, -0.0660424 , -0.946198},
{-0.506298, -0.0657576, -0.859848},
{-0.445365, -0.0658169, -0.892927},
{-0.422364, -0.131749, -0.896801},
{-0.460267, -0.196015, -0.865871},
{-0.397351, -0.196412, -0.896401 },
{-0.232455, -0.264151, -0.93605},
{-0.270627, -0.325929, -0.905832},
{-0.201189, -0.32553, -0.92388},
{-0.368518, -0.262661, -0.891742},
{-0.405434, -0.322525, -0.855337},
{-0.339209 , -0.324864, -0.882837},
{-0.307659, -0.385906, -0.869725},
{-0.342848, -0.442867, -0.828447},
{-0.274694, -0.444464, -0.85264},
{-0.289929, -0.13257, -0.947822},
{-0.330607, -0.198387, - 0.922682},
{-0.26155, -0.199094, -0.944433},
{0.233445, -0.511205, -0.827147},
{0.197274, -0.564513, -0.801504},
{0.273707, -0.55474, -0.785715},
{0.0784591, -0.52411, -0.848029},
{ 0.0406752, -0.574458, -0.817523},
{0.119078, -0.57114, -0.812169},
{0.159613, -0.615456, -0.771841},
{0.121193, -0.662842, -0.738886},
{0.199331, -0.656006, -0.727958},
{-0.0784591, -0.52411 , -0.848029},
{-0.119078, -0.57114, -0.812169},
{-0.0406752, -0.574458, -0.817523},
{-0.233445, -0.511205, -0.827147},
{-0.273707, -0.55474, -0.785715},
{-0.197274, -0.564513, -0.801504},
{-0.159613, -0.615456, -0.771841},
{-0.199331, -0.656006, -0.727958},
{-0.121193, -0.662842, -0.738886},
{0.080573, -0.708969, -0.700622},
{0.0406421, -0.749387, -0.660884},
{0.121144 , -0.744727, -0.656282},
{-0.080573, -0.708969, -0.700622},
{-0.121144, -0.744727, -0.656282},
{-0.0406421, -0.749387, -0.660884},
{-1.26468e-16, -0.786433, -0.617676},
{-0.0406404, -0.819207 , -0.572056},
{0.0406404, -0.819207, -0.572056},
{-1.00072e-16, -0.622292, -0.782786},
{-0.0406771, -0.667502, -0.743496},
{0.0406771, -0.667502, -0.743496},
{3.78241e-17, -0.133523, -0.991046 },
{-0.0815011, -0.265518, -0.960655},
{-0.0412509, -0.200368, -0.978852},
{0.0412509, -0.200368, -0.978852},
{0.0815011, -0.265518, -0.960655},
{-0.161006, -0.394136, -0.904839},
{- 0.1228, -0.332342, -0.93513},
{-0.198227, -0.454262, -0.868534},
{-0.119755, -0.460882, -0.879345},
{-0.0412992, -0.464213, -0.88476},
{0.1228, -0.332342, -0.93513},
{0.161006, -0.394136 , -0.904839},
{0.0412992, -0.464213, -0.88476},
{0.119755, -0.460882, -0.879345},
{0.198227, -0.454262, -0.868534},
{-0.041302, -0.33414, -0.941618},
{-6.44806e-17, -0.400968, -0.916092},
{0.041302, -0.33414, -0.941618},
{0.884965, 0.465658, 6.12323e-17},
{0.892927, 0.445365, 0.0658169},
{0.859848, 0.506298, 0.0657576},
{0.940742, 0.339123, 6.12323e-17},
{0.946198 , 0.316778, 0.0660424},
{0.921919, 0.381722, 0.0659884},
{0.896801, 0.422364, 0.131749},
{0.896401, 0.397351, 0.196412},
{0.865871, 0.460267, 0.196015},
{0.97853, 0.206103, 6.12323e-17},
{0.981483, 0.179596, 0.0666044},
{0.966643, 0.247326, 0.0665669},
{0.997607, 0.0691416, 6.12323e-17},
{0.996917, 0.0412484, 0.0667413},
{0.991648, 0.110385, 0.0667094},
{0.979426 , 0.151549, 0.133256},
{0.97237, 0.122729, 0.19858},
{0.961188, 0.19178, 0.198337},
{0.891742, 0.368518, 0.262661},
{0.882837, 0.339209, 0.324864},
{0.855337, 0.405434, 0.322525},
{ 0.93605, 0.232455, 0.264151},
{0.92388, 0.201189, 0.32553},
{0.905832, 0.270627, 0.325929},
{0.869725, 0.307659, 0.385906},
{0.85264, 0.274694, 0.444464},
{0.828447, 0.342848, 0.442867},
{0.947822, 0.289929, 0.13257},
{0.944433, 0.26155, 0.199094},
{0.922682, 0.330607, 0.198387},
{0.997607, -0.0691416, 6.12323e-17},
{0.991648, -0.110385, 0.0667094},
{0.996917, -0.0412484 , 0.0667413},
{0.97853, -0.206103, 6.12323e-17},
{0.966643, -0.247326, 0.0665669},
{0.981483, -0.179596, 0.0666044},
{0.979426, -0.151549, 0.133256},
{0.961188, -0.19178, 0.198337},
{ 0.97237, -0.122729, 0.19858},
{0.940742, -0.339123, 6.12323e-17},
{0.921919, -0.381722, 0.0659884},
{0.946198, -0.316778, 0.0660424},
{0.884965, -0.465658, 6.12323e-17},
{0.859848, -0.506298 , 0.0657576},
{0.892927, -0.445365, 0.0658169},
{0.896801, -0.422364, 0.131749},
{0.865871, -0.460267, 0.196015},
{0.896401, -0.397351, 0.196412},
{0.93605, -0.232455, 0.264151},
{ 0.905832, -0.270627, 0.325929},
{0.92388, -0.201189, 0.32553},
{0.891742, -0.368518, 0.262661},
{0.855337, -0.405434, 0.322525},
{0.882837, -0.339209, 0.324864},
{0.869725, -0.307659, 0.385906 },
{0.828447, -0.342848, 0.442867},
{0.85264, -0.274694, 0.444464},
{0.947822, -0.289929, 0.13257},
{0.922682, -0.330607, 0.198387},
{0.944433, -0.26155, 0.199094},
{0.827147, 0.233445 , 0.511205},
{0.801504, 0.197274, 0.564513},
{0.785715, 0.273707, 0.55474},
{0.848029, 0.0784591, 0.52411},
{0.817523, 0.0406752, 0.574458},
{0.812169, 0.119078, 0.57114},
{0.771841 , 0.159613, 0.615456},
{0.738886, 0.121193, 0.662842},
{0.727958, 0.199331, 0.656006},
{0.848029, -0.0784591, 0.52411},
{0.812169, -0.119078, 0.57114},
{0.817523, -0.0406752, 0.574458},
{0.827147, -0.233445, 0.511205},
{0.785715, -0.273707, 0.55474},
{0.801504, -0.197274, 0.564513},
{0.771841, -0.159613, 0.615456},
{0.727958, -0.199331, 0.656006},
{0.738886, -0.121193 , 0.662842},
{0.700622, 0.080573, 0.708969},
{0.660884, 0.0406421, 0.749387},
{0.656282, 0.121144, 0.744727},
{0.700622, -0.080573, 0.708969},
{0.656282, -0.121144, 0.744727},
{0.660884 , -0.0406421, 0.749387},
{0.617676, 0, 0.786433},
{0.572056, -0.0406404, 0.819207},
{0.572056, 0.0406404, 0.819207},
{0.782786, 0, 0.622292},
{0.743496, -0.0406771, 0.667502},
{0.743496 , 0.0406771, 0.667502},
{0.991046, 0, 0.133523},
{0.960655, -0.0815011, 0.265518},
{0.978852, -0.0412509, 0.200368},
{0.978852, 0.0412509, 0.200368},
{0.960655, 0.0815011, 0.265518},
{0.904839, -0.161006, 0.394136},
{0.93513, -0.1228, 0.332342},
{0.868534, -0.198227, 0.454262},
{0.879345, -0.119755, 0.460882},
{0.88476, -0.0412992, 0.464213},
{0.93513, 0.1228, 0.332342 },
{0.904839, 0.161006, 0.394136},
{0.88476, 0.0412992, 0.464213},
{0.879345, 0.119755, 0.460882},
{0.868534, 0.198227, 0.454262},
{0.941618, -0.041302, 0.33414},
{0.916092, 0, 0.400968 },
{0.941618, 0.041302, 0.33414},
{0.859848, 0.506298, -0.0657576},
{0.892927, 0.445365, -0.0658169},
{0.865871, 0.460267, -0.196015},
{0.896401, 0.397351, -0.196412},
{0.896801, 0.422364, -0.131749},
{0.921919, 0.381722, -0.0659884},
{0.946198, 0.316778, -0.0660424},
{0.855337, 0.405434, -0.322525},
{0.882837, 0.339209, -0.324864},
{0.891742, 0.368518, -0.262661 },
{0.828447, 0.342848, -0.442867},
{0.85264, 0.274694, -0.444464},
{0.869725, 0.307659, -0.385906},
{0.905832, 0.270627, -0.325929},
{0.92388, 0.201189, -0.32553},
{0.93605, 0.232455 , -0.264151},
{0.966643, 0.247326, -0.0665669},
{0.981483, 0.179596, -0.0666044},
{0.961188, 0.19178, -0.198337},
{0.97237, 0.122729, -0.19858},
{0.979426, 0.151549, -0.133256},
{ 0.991648, 0.110385, -0.0667094},
{0.996917, 0.0412484, -0.0667413},
{0.922682, 0.330607, -0.198387},
{0.944433, 0.26155, -0.199094},
{0.947822, 0.289929, -0.13257},
{0.785715, 0.273707, - 0.55474},
{0.801504, 0.197274, -0.564513},
{0.827147, 0.233445, -0.511205},
{0.727958, 0.199331, -0.656006},
{0.738886, 0.121193, -0.662842},
{0.771841, 0.159613, -0.615456},
{0.812169 , 0.119078, -0.57114},
{0.817523, 0.0406752, -0.574458},
{0.848029, 0.0784591, -0.52411},
{0.656282, 0.121144, -0.744727},
{0.660884, 0.0406421, -0.749387},
{0.700622, 0.080573, -0.708969 },
{0.572056, 0.0406404, -0.819207},
{0.572056, -0.0406404, -0.819207},
{0.617676, 0, -0.786433},
{0.660884, -0.0406421, -0.749387},
{0.656282, -0.121144, -0.744727},
{0.700622, - 0.080573, -0.708969},
{0.817523, -0.0406752, -0.574458},
{0.812169, -0.119078, -0.57114},
{0.848029, -0.0784591, -0.52411},
{0.738886, -0.121193, -0.662842},
{0.727958, -0.199331, -0.656006 },
{0.771841, -0.159613, -0.615456},
{0.801504, -0.197274, -0.564513},
{0.785715, -0.273707, -0.55474},
{0.827147, -0.233445, -0.511205},
{0.743496, 0.0406771, -0.667502},
{0.743496 , -0.0406771, -0.667502},
{0.782786, 0, -0.622292},
{0.996917, -0.0412484, -0.0667413},
{0.991648, -0.110385, -0.0667094},
{0.97237, -0.122729, -0.19858},
{0.961188, -0.19178, -0.198337},
{0.979426, -0.151549, -0.133256},
{0.981483, -0.179596, -0.0666044},
{0.966643, -0.247326, -0.0665669},
{0.92388, -0.201189, -0.32553},
{0.905832, -0.270627, -0.325929},
{0.93605 , -0.232455, -0.264151},
{0.85264, -0.274694, -0.444464},
{0.828447, -0.342848, -0.442867},
{0.869725, -0.307659, -0.385906},
{0.882837, -0.339209, -0.324864},
{0.855337, -0.405434, -0.322525 },
{0.891742, -0.368518, -0.262661},
{0.946198, -0.316778, -0.0660424},
{0.921919, -0.381722, -0.0659884},
{0.896401, -0.397351, -0.196412},
{0.865871, -0.460267, -0.196015},
{0.896801 , -0.422364, -0.131749},
{0.892927, -0.445365, -0.0658169},
{0.859848, -0.506298, -0.0657576},
{0.944433, -0.26155, -0.199094},
{0.922682, -0.330607, -0.198387},
{0.947822, -0.289929, -0.13257 },
{0.868534, 0.198227, -0.454262},
{0.88476, 0.0412992, -0.464213},
{0.879345, 0.119755, -0.460882},
{0.904839, 0.161006, -0.394136},
{0.93513, 0.1228, -0.332342},
{0.879345, -0.119755 , -0.460882},
{0.88476, -0.0412992, -0.464213},
{0.868534, -0.198227, -0.454262},
{0.904839, -0.161006, -0.394136},
{0.93513, -0.1228, -0.332342},
{0.960655, 0.0815011, -0.265518},
{ 0.978852, 0.0412509, -0.200368},
{0.960655, -0.0815011, -0.265518},
{0.978852, -0.0412509, -0.200368},
{0.991046, 0, -0.133523},
{0.916092, 0, -0.400968},
{0.941618, -0.041302, -0.33414},
{0.941618, 0.041302, -0.33414},
{-0.884965, -0.465658, 6.12323e-17},
{-0.892927, -0.445365, 0.0658169},
{-0.859848, -0.506298, 0.0657576},
{-0.940742, -0.339123, 6.12323e-17},
{- 0.946198, -0.316778, 0.0660424},
{-0.921919, -0.381722, 0.0659884},
{-0.896801, -0.422364, 0.131749},
{-0.896401, -0.397351, 0.196412},
{-0.865871, -0.460267, 0.196015},
{-0.97853, -0.206103 , 6.12323e-17},
{-0.981483, -0.179596, 0.0666044},
{-0.966643, -0.247326, 0.0665669},
{-0.997607, -0.0691416, 6.12323e-17},
{-0.996917, -0.0412484, 0.0667413},
{-0.991648, -0.110385, 0.0667094 },
{-0.979426, -0.151549, 0.133256},
{-0.97237, -0.122729, 0.19858},
{-0.961188, -0.19178, 0.198337},
{-0.891742, -0.368518, 0.262661},
{-0.882837, -0.339209, 0.324864},
{-0.855337 , -0.405434, 0.322525},
{-0.93605, -0.232455, 0.264151},
{-0.92388, -0.201189, 0.32553},
{-0.905832, -0.270627, 0.325929},
{-0.869725, -0.307659, 0.385906},
{-0.85264, -0.274694, 0.444464 },
{-0.828447, -0.342848, 0.442867},
{-0.947822, -0.289929, 0.13257},
{-0.944433, -0.26155, 0.199094},
{-0.922682, -0.330607, 0.198387},
{-0.997607, 0.0691416, 6.12323e-17},
{-0.991648 , 0.110385, 0.0667094},
{-0.996917, 0.0412484, 0.0667413},
{-0.97853, 0.206103, 6.12323e-17},
{-0.966643, 0.247326, 0.0665669},
{-0.981483, 0.179596, 0.0666044},
{-0.979426, 0.151549, 0.133256 },
{-0.961188, 0.19178, 0.198337},
{-0.97237, 0.122729, 0.19858},
{-0.940742, 0.339123, 6.12323e-17},
{-0.921919, 0.381722, 0.0659884},
{-0.946198, 0.316778, 0.0660424},
{-0.884965 , 0.465658, 6.12323e-17},
{-0.859848, 0.506298, 0.0657576},
{-0.892927, 0.445365, 0.0658169},
{-0.896801, 0.422364, 0.131749},
{-0.865871, 0.460267, 0.196015},
{-0.896401, 0.397351, 0.196412 },
{-0.93605, 0.232455, 0.264151},
{-0.905832, 0.270627, 0.325929},
{-0.92388, 0.201189, 0.32553},
{-0.891742, 0.368518, 0.262661},
{-0.855337, 0.405434, 0.322525},
{-0.882837, 0.339209 , 0.324864},
{-0.869725, 0.307659, 0.385906},
{-0.828447, 0.342848, 0.442867},
{-0.85264, 0.274694, 0.444464},
{-0.947822, 0.289929, 0.13257},
{-0.922682, 0.330607, 0.198387},
{-0.944433 , 0.26155, 0.199094},
{-0.827147, -0.233445, 0.511205},
{-0.801504, -0.197274, 0.564513},
{-0.785715, -0.273707, 0.55474},
{-0.848029, -0.0784591, 0.52411},
{-0.817523, -0.0406752, 0.574458 },
{-0.812169, -0.119078, 0.57114},
{-0.771841, -0.159613, 0.615456},
{-0.738886, -0.121193, 0.662842},
{-0.727958, -0.199331, 0.656006},
{-0.848029, 0.0784591, 0.52411},
{-0.812169 , 0.119078, 0.57114},
{-0.817523, 0.0406752, 0.574458},
{-0.827147, 0.233445, 0.511205},
{-0.785715, 0.273707, 0.55474},
{-0.801504, 0.197274, 0.564513},
{-0.771841, 0.159613, 0.615456},
{-0.727958, 0.199331, 0.656006},
{-0.738886, 0.121193, 0.662842},
{-0.700622, -0.080573, 0.708969},
{-0.660884, -0.0406421, 0.749387},
{-0.656282, -0.121144, 0.744727},
{-0.700622 , 0.080573, 0.708969},
{-0.656282, 0.121144, 0.744727},
{-0.660884, 0.0406421, 0.749387},
{-0.617676, 7.56435e-17, 0.786433},
{-0.572056, 0.0406404, 0.819207},
{-0.572056, -0.0406404, 0.819207 },
{-0.782786, 9.58636e-17, 0.622292},
{-0.743496, 0.0406771, 0.667502},
{-0.743496, -0.0406771, 0.667502},
{-0.991046, 1.21368e-16, 0.133523},
{-0.960655, 0.0815011, 0.265518},
{- 0.978852, 0.0412509, 0.200368},
{-0.978852, -0.0412509, 0.200368},
{-0.960655, -0.0815011, 0.265518},
{-0.904839, 0.161006, 0.394136},
{-0.93513, 0.1228, 0.332342},
{-0.868534, 0.198227, 0.454262},
{-0.879345, 0.119755, 0.460882},
{-0.88476, 0.0412992, 0.464213},
{-0.93513, -0.1228, 0.332342},
{-0.904839, -0.161006, 0.394136},
{-0.88476, -0.0412992, 0.464213},
{-0.879345 , -0.119755, 0.460882},
{-0.868534, -0.198227, 0.454262},
{-0.941618, 0.041302, 0.33414},
{-0.916092, 1.12189e-16, 0.400968},
{-0.941618, -0.041302, 0.33414},
{-0.859848, -0.506298, -0.0657576 },
{-0.892927, -0.445365, -0.0658169},
{-0.865871, -0.460267, -0.196015},
{-0.896401, -0.397351, -0.196412},
{-0.896801, -0.422364, -0.131749},
{-0.921919, -0.381722, -0.0659884},
{- 0.946198, -0.316778, -0.0660424},
{-0.855337, -0.405434, -0.322525},
{-0.882837, -0.339209, -0.324864},
{-0.891742, -0.368518, -0.262661},
{-0.828447, -0.342848, -0.442867},
{-0.85264, - 0.274694, -0.444464},
{-0.869725, -0.307659, -0.385906},
{-0.905832, -0.270627, -0.325929},
{-0.92388, -0.201189, -0.32553},
{-0.93605, -0.232455, -0.264151},
{-0.966643, -0.247326, -0.0665669 },
{-0.981483, -0.179596, -0.0666044},
{-0.961188, -0.19178, -0.198337},
{-0.97237, -0.122729, -0.19858},
{-0.979426, -0.151549, -0.133256},
{-0.991648, -0.110385, -0.0667094},
{- 0.996917, -0.0412484, -0.0667413},
{-0.922682, -0.330607, -0.198387},
{-0.944433, -0.26155, -0.199094},
{-0.947822, -0.289929, -0.13257},
{-0.785715, -0.273707, -0.55474},
{-0.801504, -0.197274 , -0.564513},
{-0.827147, -0.233445, -0.511205},
{-0.727958, -0.199331, -0.656006},
{-0.738886, -0.121193, -0.662842},
{-0.771841, -0.159613, -0.615456},
{-0.812169, -0.119078, -0.57114},
{-0.817523, -0.0406752, -0.574458},
{-0.848029, -0.0784591, -0.52411},
{-0.656282, -0.121144, -0.744727},
{-0.660884, -0.0406421, -0.749387},
{-0.700622, -0.080573, -0.708969},
{- 0.572056, -0.0406404, -0.819207},
{-0.572056, 0.0406404, -0.819207},
{-0.617676, 7.56435e-17, -0.786433},
{-0.660884, 0.0406421, -0.749387},
{-0.656282, 0.121144, -0.744727},
{-0.700622, 0.080573, -0.708969},
{-0.817523, 0.0406752, -0.574458},
{-0.812169, 0.119078, -0.57114},
{-0.848029, 0.0784591, -0.52411},
{-0.738886, 0.121193, -0.662842},
{-0.727958, 0.199331, -0.656006 },
{-0.771841, 0.159613, -0.615456},
{-0.801504, 0.197274, -0.564513},
{-0.785715, 0.273707, -0.55474},
{-0.827147, 0.233445, -0.511205},
{-0.743496, -0.0406771, -0.667502},
{-0.743496 , 0.0406771, -0.667502},
{-0.782786, 9.58636e-17, -0.622292},
{-0.996917, 0.0412484, -0.0667413},
{-0.991648, 0.110385, -0.0667094},
{-0.97237, 0.122729, -0.19858},
{-0.961188, 0.19178, - 0.198337},
{-0.979426, 0.151549, -0.133256},
{-0.981483, 0.179596, -0.0666044},
{-0.966643, 0.247326, -0.0665669},
{-0.92388, 0.201189, -0.32553},
{-0.905832, 0.270627, -0.325929},
{- 0.93605, 0.232455, -0.264151},
{-0.85264, 0.274694, -0.444464},
{-0.828447, 0.342848, -0.442867},
{-0.869725, 0.307659, -0.385906},
{-0.882837, 0.339209, -0.324864},
{-0.855337, 0.405434 , -0.322525},
{-0.891742, 0.368518, -0.262661},
{-0.946198, 0.316778, -0.0660424},
{-0.921919, 0.381722, -0.0659884},
{-0.896401, 0.397351, -0.196412},
{-0.865871, 0.460267, -0.196015},
{-0.896801, 0.422364, -0.131749},
{-0.892927, 0.445365, -0.0658169},
{-0.859848, 0.506298, -0.0657576},
{-0.944433, 0.26155, -0.199094},
{-0.922682, 0.330607, -0.198387},
{-0.947822, 0.289929, -0.13257},
{-0.868534, -0.198227, -0.454262},
{-0.88476, -0.0412992, -0.464213},
{-0.879345, -0.119755, -0.460882},
{-0.904839, -0.161006, -0.394136},
{-0.93513, -0.1228, -0.332342 },
{-0.879345, 0.119755, -0.460882},
{-0.88476, 0.0412992, -0.464213},
{-0.868534, 0.198227, -0.454262},
{-0.904839, 0.161006, -0.394136},
{-0.93513, 0.1228, -0.332342},
{-0.960655 , -0.0815011, -0.265518},
{-0.978852, -0.0412509, -0.200368},
{-0.960655, 0.0815011, -0.265518},
{-0.978852, 0.0412509, -0.200368},
{-0.991046, 1.21368e-16, -0.133523},
{-0.916092, 1.12189e-16 , -0.400968},
{-0.941618, 0.041302, -0.33414},
{-0.941618, -0.041302, -0.33414},
{5.41885e-17, 0.884965, 0.465658},
{0.0658169, 0.892927, 0.445365},
{0.0657576, 0.859848, 0.506298},
{ 5.76038e-17, 0.940742, 0.339123},
{0.0660424, 0.946198, 0.316778},
{0.0659884, 0.921919, 0.381722},
{0.131749, 0.896801, 0.422364},
{0.196412, 0.896401, 0.397351},
{0.196015, 0.865871, 0.460267 },
{5.99177e-17, 0.97853, 0.206103},
{0.0666044, 0.981483, 0.179596},
{0.0665669, 0.966643, 0.247326},
{6.10858e-17, 0.997607, 0.0691416},
{0.0667413, 0.996917, 0.0412484},
{0.0667094 , 0.991648, 0.110385},
{0.133256, 0.979426, 0.151549},
{0.19858, 0.97237, 0.122729},
{0.198337, 0.961188, 0.19178},
{0.262661, 0.891742, 0.368518},
{0.324864, 0.882837, 0.339209},
{ 0.322525, 0.855337, 0.405434},
{0.264151, 0.93605, 0.232455},
{0.32553, 0.92388, 0.201189},
{0.325929, 0.905832, 0.270627},
{0.385906, 0.869725, 0.307659},
{0.444464, 0.85264, 0.274694},
{0.442867, 0.828447, 0.342848},
{0.13257, 0.947822, 0.289929},
{0.199094, 0.944433, 0.26155},
{0.198387, 0.922682, 0.330607},
{6.10858e-17, 0.997607, -0.0691416},
{0.0667094, 0.991648 , -0.110385},
{0.0667413, 0.996917, -0.0412484},
{5.99177e-17, 0.97853, -0.206103},
{0.0665669, 0.966643, -0.247326},
{0.0666044, 0.981483, -0.179596},
{0.133256, 0.979426, -0.151549},
{0.198337, 0.961188, -0.19178},
{0.19858, 0.97237, -0.122729},
{5.76038e-17, 0.940742, -0.339123},
{0.0659884, 0.921919, -0.381722},
{0.0660424, 0.946198, -0.316778},
{5.41885e-17, 0.884965 , -0.465658},
{0.0657576, 0.859848, -0.506298},
{0.0658169, 0.892927, -0.445365},
{0.131749, 0.896801, -0.422364},
{0.196015, 0.865871, -0.460267},
{0.196412, 0.896401, -0.397351},
{ 0.264151, 0.93605, -0.232455},
{0.325929, 0.905832, -0.270627},
{0.32553, 0.92388, -0.201189},
{0.262661, 0.891742, -0.368518},
{0.322525, 0.855337, -0.405434},
{0.324864, 0.882837, -0.339209 },
{0.385906, 0.869725, -0.307659},
{0.442867, 0.828447, -0.342848},
{0.444464, 0.85264, -0.274694},
{0.13257, 0.947822, -0.289929},
{0.198387, 0.922682, -0.330607},
{0.199094, 0.944433 , -0.26155},
{0.511205, 0.827147, 0.233445},
{0.564513, 0.801504, 0.197274},
{0.55474, 0.785715, 0.273707},
{0.52411, 0.848029, 0.0784591},
{0.574458, 0.817523, 0.0406752},
{0.57114 , 0.812169, 0.119078},
{0.615456, 0.771841, 0.159613},
{0.662842, 0.738886, 0.121193},
{0.656006, 0.727958, 0.199331},
{0.52411, 0.848029, -0.0784591},
{0.57114, 0.812169, -0.119078},
{0.574458, 0.817523, -0.0406752},
{0.511205, 0.827147, -0.233445},
{0.55474, 0.785715, -0.273707},
{0.564513, 0.801504, -0.197274},
{0.615456, 0.771841, -0.159613},
{0.656006, 0.727958 , -0.199331},
{0.662842, 0.738886, -0.121193},
{0.708969, 0.700622, 0.080573},
{0.749387, 0.660884, 0.0406421},
{0.744727, 0.656282, 0.121144},
{0.708969, 0.700622, -0.080573},
{0.744727 , 0.656282, -0.121144},
{0.749387, 0.660884, -0.0406421},
{0.786433, 0.617676, -1.60812e-16},
{0.819207, 0.572056, -0.0406404},
{0.819207, 0.572056, 0.0406404},
{0.622292, 0.782786, -1.60812e-16 },
{0.667502, 0.743496, -0.0406771},
{0.667502, 0.743496, 0.0406771},
{0.133523, 0.991046, -1.60812e-16},
{0.265518, 0.960655, -0.0815011},
{0.200368, 0.978852, -0.0412509},
{0.200368 , 0.978852, 0.0412509},
{0.265518, 0.960655, 0.0815011},
{0.394136, 0.904839, -0.161006},
{0.332342, 0.93513, -0.1228},
{0.454262, 0.868534, -0.198227},
{0.460882, 0.879345, -0.119755},
{0.464213, 0.88476, -0.0412992},
{0.332342, 0.93513, 0.1228},
{0.394136, 0.904839, 0.161006},
{0.464213, 0.88476, 0.0412992},
{0.460882, 0.879345, 0.119755},
{0.454262, 0.868534, 0.198227 },
{0.33414, 0.941618, -0.041302},
{0.400968, 0.916092, -1.60812e-16},
{0.33414, 0.941618, 0.041302},
{-0.0657576, 0.859848, 0.506298},
{-0.0658169, 0.892927, 0.445365},
{-0.196015 , 0.865871, 0.460267},
{-0.196412, 0.896401, 0.397351},
{-0.131749, 0.896801, 0.422364},
{-0.0659884, 0.921919, 0.381722},
{-0.0660424, 0.946198, 0.316778},
{-0.322525, 0.855337, 0.405434 },
{-0.324864, 0.882837, 0.339209},
{-0.262661, 0.891742, 0.368518},
{-0.442867, 0.828447, 0.342848},
{-0.444464, 0.85264, 0.274694},
{-0.385906, 0.869725, 0.307659},
{-0.325929, 0.905832, 0.270627},
{-0.32553, 0.92388, 0.201189},
{-0.264151, 0.93605, 0.232455},
{-0.0665669, 0.966643, 0.247326},
{-0.0666044, 0.981483, 0.179596},
{-0.198337, 0.961188, 0.19178},
{-0.19858, 0.97237, 0.122729},
{-0.133256, 0.979426, 0.151549},
{-0.0667094, 0.991648, 0.110385},
{-0.0667413, 0.996917, 0.0412484},
{-0.198387, 0.922682, 0.330607},
{-0.199094, 0.944433 , 0.26155},
{-0.13257, 0.947822, 0.289929},
{-0.55474, 0.785715, 0.273707},
{-0.564513, 0.801504, 0.197274},
{-0.511205, 0.827147, 0.233445},
{-0.656006, 0.727958, 0.199331},
{-0.662842 , 0.738886, 0.121193},
{-0.615456, 0.771841, 0.159613},
{-0.57114, 0.812169, 0.119078},
{-0.574458, 0.817523, 0.0406752},
{-0.52411, 0.848029, 0.0784591},
{-0.744727, 0.656282, 0.121144},
{-0.749387, 0.660884, 0.0406421},
{-0.708969, 0.700622, 0.080573},
{-0.819207, 0.572056, 0.0406404},
{-0.819207, 0.572056, -0.0406404},
{-0.786433, 0.617676, -1.60812e-16},
{-0.749387 , 0.660884, -0.0406421},
{-0.744727, 0.656282, -0.121144},
{-0.708969, 0.700622, -0.080573},
{-0.574458, 0.817523, -0.0406752},
{-0.57114, 0.812169, -0.119078},
{-0.52411, 0.848029, -0.0784591 },
{-0.662842, 0.738886, -0.121193},
{-0.656006, 0.727958, -0.199331},
{-0.615456, 0.771841, -0.159613},
{-0.564513, 0.801504, -0.197274},
{-0.55474, 0.785715, -0.273707},
{-0.511205 , 0.827147, -0.233445},
{-0.667502, 0.743496, 0.0406771},
{-0.667502, 0.743496, -0.0406771},
{-0.622292, 0.782786, -1.60812e-16},
{-0.0667413, 0.996917, -0.0412484},
{-0.0667094, 0.991648 , -0.110385},
{-0.19858, 0.97237, -0.122729},
{-0.198337, 0.961188, -0.19178},
{-0.133256, 0.979426, -0.151549},
{-0.0666044, 0.981483, -0.179596},
{-0.0665669, 0.966643, -0.247326},
{-0.32553, 0.92388, -0.201189},
{-0.325929, 0.905832, -0.270627},
{-0.264151, 0.93605, -0.232455},
{-0.444464, 0.85264, -0.274694},
{-0.442867, 0.828447, -0.342848},
{-0.385906, 0.869725 , -0.307659},
{-0.324864, 0.882837, -0.339209},
{-0.322525, 0.855337, -0.405434},
{-0.262661, 0.891742, -0.368518},
{-0.0660424, 0.946198, -0.316778},
{-0.0659884, 0.921919, -0.381722},
{-0.196412, 0.896401, -0.397351},
{-0.196015, 0.865871, -0.460267},
{-0.131749, 0.896801, -0.422364},
{-0.0658169, 0.892927, -0.445365},
{-0.0657576, 0.859848, -0.506298},
{-0.199094 , 0.944433, -0.26155},
{-0.198387, 0.922682, -0.330607},
{-0.13257, 0.947822, -0.289929},
{-0.454262, 0.868534, 0.198227},
{-0.464213, 0.88476, 0.0412992},
{-0.460882, 0.879345, 0.119755 },
{-0.394136, 0.904839, 0.161006},
{-0.332342, 0.93513, 0.1228},
{-0.460882, 0.879345, -0.119755},
{-0.464213, 0.88476, -0.0412992},
{-0.454262, 0.868534, -0.198227},
{-0.394136, 0.904839, -0.161006},
{-0.332342, 0.93513, -0.1228},
{-0.265518, 0.960655, 0.0815011},
{-0.200368, 0.978852, 0.0412509},
{-0.265518, 0.960655, -0.0815011},
{-0.200368, 0.978852, -0.0412509 },
{-0.133523, 0.991046, -1.60812e-16},
{-0.400968, 0.916092, -1.60812e-16},
{-0.33414, 0.941618, -0.041302},
{-0.33414, 0.941618, 0.041302},
{0.0657576, -0.859848, 0.506298},
{0.0658169 , -0.892927, 0.445365},
{5.41885e-17, -0.884965, 0.465658},
{0.196015, -0.865871, 0.460267},
{0.196412, -0.896401, 0.397351},
{0.131749, -0.896801, 0.422364},
{0.0659884, -0.921919, 0.381722 },
{0.0660424, -0.946198, 0.316778},
{5.76038e-17, -0.940742, 0.339123},
{0.322525, -0.855337, 0.405434},
{0.324864, -0.882837, 0.339209},
{0.262661, -0.891742, 0.368518},
{0.442867 , -0.828447, 0.342848},
{0.444464, -0.85264, 0.274694},
{0.385906, -0.869725, 0.307659},
{0.325929, -0.905832, 0.270627},
{0.32553, -0.92388, 0.201189},
{0.264151, -0.93605, 0.232455},
{0.0665669, -0.966643, 0.247326},
{0.0666044, -0.981483, 0.179596},
{5.99177e-17, -0.97853, 0.206103},
{0.198337, -0.961188, 0.19178},
{0.19858, -0.97237, 0.122729},
{0.133256, -0.979426 , 0.151549},
{0.0667094, -0.991648, 0.110385},
{0.0667413, -0.996917, 0.0412484},
{6.10858e-17, -0.997607, 0.0691416},
{0.198387, -0.922682, 0.330607},
{0.199094, -0.944433, 0.26155},
{0.13257, -0.947822, 0.289929},
{0.55474, -0.785715, 0.273707},
{0.564513, -0.801504, 0.197274},
{0.511205, -0.827147, 0.233445},
{0.656006, -0.727958, 0.199331},
{0.662842, -0.738886 , 0.121193},
{0.615456, -0.771841, 0.159613},
{0.57114, -0.812169, 0.119078},
{0.574458, -0.817523, 0.0406752},
{0.52411, -0.848029, 0.0784591},
{0.744727, -0.656282, 0.121144},
{ 0.749387, -0.660884, 0.0406421},
{0.708969, -0.700622, 0.080573},
{0.819207, -0.572056, 0.0406404},
{0.819207, -0.572056, -0.0406404},
{0.786433, -0.617676, -1.60812e-16},
{0.749387, -0.660884 , -0.0406421},
{0.744727, -0.656282, -0.121144},
{0.708969, -0.700622, -0.080573},
{0.574458, -0.817523, -0.0406752},
{0.57114, -0.812169, -0.119078},
{0.52411, -0.848029, -0.0784591},
{0.662842, -0.738886, -0.121193},
{0.656006, -0.727958, -0.199331},
{0.615456, -0.771841, -0.159613},
{0.564513, -0.801504, -0.197274},
{0.55474, -0.785715, -0.273707},
{0.511205, -0.827147 , -0.233445},
{0.667502, -0.743496, 0.0406771},
{0.667502, -0.743496, -0.0406771},
{0.622292, -0.782786, -1.60812e-16},
{0.0667413, -0.996917, -0.0412484},
{0.0667094, -0.991648, -0.110385 },
{6.10858e-17, -0.997607, -0.0691416},
{0.19858, -0.97237, -0.122729},
{0.198337, -0.961188, -0.19178},
{0.133256, -0.979426, -0.151549},
{0.0666044, -0.981483, -0.179596},
{0.0665669 , -0.966643, -0.247326},
{5.99177e-17, -0.97853, -0.206103},
{0.32553, -0.92388, -0.201189},
{0.325929, -0.905832, -0.270627},
{0.264151, -0.93605, -0.232455},
{0.444464, -0.85264, -0.274694 },
{0.442867, -0.828447, -0.342848},
{0.385906, -0.869725, -0.307659},
{0.324864, -0.882837, -0.339209},
{0.322525, -0.855337, -0.405434},
{0.262661, -0.891742, -0.368518},
{0.0660424 , -0.946198, -0.316778},
{0.0659884, -0.921919, -0.381722},
{5.76038e-17, -0.940742, -0.339123},
{0.196412, -0.896401, -0.397351},
{0.196015, -0.865871, -0.460267},
{0.131749, -0.896801, - 0.422364},
{0.0658169, -0.892927, -0.445365},
{0.0657576, -0.859848, -0.506298},
{5.41885e-17, -0.884965, -0.465658},
{0.199094, -0.944433, -0.26155},
{0.198387, -0.922682, -0.330607},
{0.13257, -0.947822, -0.289929},
{0.454262, -0.868534, 0.198227},
{0.464213, -0.88476, 0.0412992},
{0.460882, -0.879345, 0.119755},
{0.394136, -0.904839, 0.161006},
{0.332342, -0.93513 , 0.1228},
{0.460882, -0.879345, -0.119755},
{0.464213, -0.88476, -0.0412992},
{0.454262, -0.868534, -0.198227},
{0.394136, -0.904839, -0.161006},
{0.332342, -0.93513, -0.1228},
{ 0.265518, -0.960655, 0.0815011},
{0.200368, -0.978852, 0.0412509},
{0.265518, -0.960655, -0.0815011},
{0.200368, -0.978852, -0.0412509},
{0.133523, -0.991046, -1.60812e-16},
{0.400968, - 0.916092, -1.60812e-16},
{0.33414, -0.941618, -0.041302},
{0.33414, -0.941618, 0.041302},
{-0.0658169, -0.892927, 0.445365},
{-0.0657576, -0.859848, 0.506298},
{-0.0660424, -0.946198, 0.316778 },
{-0.0659884, -0.921919, 0.381722},
{-0.131749, -0.896801, 0.422364},
{-0.196412, -0.896401, 0.397351},
{-0.196015, -0.865871, 0.460267},
{-0.0666044, -0.981483, 0.179596},
{-0.0665669 , -0.966643, 0.247326},
{-0.0667413, -0.996917, 0.0412484},
{-0.0667094, -0.991648, 0.110385},
{-0.133256, -0.979426, 0.151549},
{-0.19858, -0.97237, 0.122729},
{-0.198337, -0.961188, 0.19178 },
{-0.262661, -0.891742, 0.368518},
{-0.324864, -0.882837, 0.339209},
{-0.322525, -0.855337, 0.405434},
{-0.264151, -0.93605, 0.232455},
{-0.32553, -0.92388, 0.201189},
{-0.325929 , -0.905832, 0.270627},
{-0.385906, -0.869725, 0.307659},
{-0.444464, -0.85264, 0.274694},
{-0.442867, -0.828447, 0.342848},
{-0.13257, -0.947822, 0.289929},
{-0.199094, -0.944433, 0.26155 },
{-0.198387, -0.922682, 0.330607},
{-0.0667094, -0.991648, -0.110385},
{-0.0667413, -0.996917, -0.0412484},
{-0.0665669, -0.966643, -0.247326},
{-0.0666044, -0.981483, -0.179596},
{- 0.133256, -0.979426, -0.151549},
{-0.198337, -0.961188, -0.19178},
{-0.19858, -0.97237, -0.122729},
{-0.0659884, -0.921919, -0.381722},
{-0.0660424, -0.946198, -0.316778},
{-0.0657576, - 0.859848, -0.506298},
{-0.0658169, -0.892927, -0.445365},
{-0.131749, -0.896801, -0.422364},
{-0.196015, -0.865871, -0.460267},
{-0.196412, -0.896401, -0.397351},
{-0.264151, -0.93605, - 0.232455},
{-0.325929, -0.905832, -0.270627},
{-0.32553, -0.92388, -0.201189},
{-0.262661, -0.891742, -0.368518},
{-0.322525, -0.855337, -0.405434},
{-0.324864, -0.882837, -0.339209},
{-0.385906, -0.869725, -0.307659},
{-0.442867, -0.828447, -0.342848},
{-0.444464, -0.85264, -0.274694},
{-0.13257, -0.947822, -0.289929},
{-0.198387, -0.922682, -0.330607},
{-0.199094 , -0.944433, -0.26155},
{-0.511205, -0.827147, 0.233445},
{-0.564513, -0.801504, 0.197274},
{-0.55474, -0.785715, 0.273707},
{-0.52411, -0.848029, 0.0784591},
{-0.574458, -0.817523, 0.0406752 },
{-0.57114, -0.812169, 0.119078},
{-0.615456, -0.771841, 0.159613},
{-0.662842, -0.738886, 0.121193},
{-0.656006, -0.727958, 0.199331},
{-0.52411, -0.848029, -0.0784591},
{-0.57114 , -0.812169, -0.119078},
{-0.574458, -0.817523, -0.0406752},
{-0.511205, -0.827147, -0.233445},
{-0.55474, -0.785715, -0.273707},
{-0.564513, -0.801504, -0.197274},
{-0.615456, -0.771841 , -0.159613},
{-0.656006, -0.727958, -0.199331},
{-0.662842, -0.738886, -0.121193},
{-0.708969, -0.700622, 0.080573},
{-0.749387, -0.660884, 0.0406421},
{-0.744727, -0.656282, 0.121144},
{-0.708969, -0.700622, -0.080573},
{-0.744727, -0.656282, -0.121144},
{-0.749387, -0.660884, -0.0406421},
{-0.786433, -0.617676, -1.60812e-16},
{-0.819207, -0.572056, -0.0406404},
{- 0.819207, -0.572056, 0.0406404},
{-0.622292, -0.782786, -1.60812e-16},
{-0.667502, -0.743496, -0.0406771},
{-0.667502, -0.743496, 0.0406771},
{-0.133523, -0.991046, -1.60812e-16},
{-0.265518 , -0.960655, -0.0815011},
{-0.200368, -0.978852, -0.0412509},
{-0.200368, -0.978852, 0.0412509},
{-0.265518, -0.960655, 0.0815011},
{-0.394136, -0.904839, -0.161006},
{-0.332342, -0.93513 , -0.1228},
{-0.454262, -0.868534, -0.198227},
{-0.460882, -0.879345, -0.119755},
{-0.464213, -0.88476, -0.0412992},
{-0.332342, -0.93513, 0.1228},
{-0.394136, -0.904839, 0.161006},
{- 0.464213, -0.88476, 0.0412992},
{-0.460882, -0.879345, 0.119755},
{-0.454262, -0.868534, 0.198227},
{-0.33414, -0.941618, -0.041302},
{-0.400968, -0.916092, -1.60812e-16},
{-0.33414, -0.941618 , 0.041302},
{0.106494, 0.82711, 0.551859},
{0.237229, 0.830359, 0.504209},
{0.172532, 0.830812, 0.529135},
{0.147414, 0.79017, 0.594895},
{0.187432, 0.749786, 0.634579},
{0.366027 , 0.816233, 0.446977},
{0.303801, 0.825175, 0.476226},
{0.485712, 0.785899, 0.382683},
{0.427135, 0.803016, 0.415597},
{0.408286, 0.772575, 0.48624},
{0.448259, 0.725299, 0.522499},
{ 0.38673, 0.737712, 0.553372},
{0.2289, 0.703983, 0.672319},
{0.267381, 0.65662, 0.705236},
{0.361592, 0.697037, 0.619186},
{0.399769, 0.64684, 0.649448},
{0.334692, 0.653497, 0.678913},
{0.305212, 0.605741, 0.734794},
{0.341435, 0.552454, 0.760406},
{0.280319, 0.790112, 0.545109},
{0.322141, 0.745338, 0.583691},
{0.25518, 0.749435, 0.610926},
{0.605741, 0.734794, 0.305212 },
{0.552454, 0.760406, 0.341435},
{0.703983, 0.672319, 0.2289},
{0.65662, 0.705236, 0.267381},
{0.653497, 0.678913, 0.334692},
{0.697037, 0.619186, 0.361592},
{0.64684, 0.649448, 0.399769},
{0.79017, 0.594895, 0.147414},
{0.749786, 0.634579, 0.187432},
{0.82711, 0.551859, 0.106494},
{0.830812, 0.529135, 0.172532},
{0.830359, 0.504209, 0.237229},
{0.737712, 0.553372, 0.38673},
{0.772575, 0.48624, 0.408286},
{0.725299, 0.522499, 0.448259},
{0.825175, 0.476226, 0.303801},
{0.816233, 0.446977, 0.366027},
{0.803016, 0.415597, 0.427135},
{ 0.785899, 0.382683, 0.485712},
{0.749435, 0.610926, 0.25518},
{0.790112, 0.545109, 0.280319},
{0.745338, 0.583691, 0.322141},
{0.382683, 0.485712, 0.785899},
{0.415597, 0.427135, 0.803016 },
{0.522499, 0.448259, 0.725299},
{0.553372, 0.38673, 0.737712},
{0.48624, 0.408286, 0.772575},
{0.446977, 0.366027, 0.816233},
{0.476226, 0.303801, 0.825175},
{0.649448, 0.399769 , 0.64684},
{0.678913, 0.334692, 0.653497},
{0.619186, 0.361592, 0.697037},
{0.760406, 0.341435, 0.552454},
{0.734794, 0.305212, 0.605741},
{0.705236, 0.267381, 0.65662},
{0.672319 , 0.2289, 0.703983},
{0.504209, 0.237229, 0.830359},
{0.529135, 0.172532, 0.830812},
{0.634579, 0.187432, 0.749786},
{0.594895, 0.147414, 0.79017},
{0.551859, 0.106494, 0.82711},
{ 0.583691, 0.322141, 0.745338},
{0.610926, 0.25518, 0.749435},
{0.545109, 0.280319, 0.790112},
{0.536784, 0.735011, 0.414273},
{0.628313, 0.619242, 0.470917},
{0.584716, 0.678977, 0.443957 },
{0.51797, 0.704471, 0.485208},
{0.496441, 0.669612, 0.552418},
{0.704471, 0.485208, 0.51797},
{0.669612, 0.552418, 0.496441},
{0.735011, 0.414273, 0.536784},
{0.678977, 0.443957 , 0.584716},
{0.619242, 0.470917, 0.628313},
{0.470917, 0.628313, 0.619242},
{0.443957, 0.584716, 0.678977},
{0.552418, 0.496441, 0.669612},
{0.485208, 0.51797, 0.704471},
{0.414273 , 0.536784, 0.735011},
{0.607478, 0.581952, 0.54065},
{0.581952, 0.54065, 0.607478},
{0.54065, 0.607478, 0.581952},
{0.106494, 0.82711, -0.551859},
{0.187432, 0.749786, -0.634579},
{ 0.147414, 0.79017, -0.594895},
{0.172532, 0.830812, -0.529135},
{0.237229, 0.830359, -0.504209},
{0.267381, 0.65662, -0.705236},
{0.2289, 0.703983, -0.672319},
{0.341435, 0.552454, -0.760406 },
{0.305212, 0.605741, -0.734794},
{0.334692, 0.653497, -0.678913},
{0.399769, 0.64684, -0.649448},
{0.361592, 0.697037, -0.619186},
{0.303801, 0.825175, -0.476226},
{0.366027, 0.816233 , -0.446977},
{0.38673, 0.737712, -0.553372},
{0.448259, 0.725299, -0.522499},
{0.408286, 0.772575, -0.48624},
{0.427135, 0.803016, -0.415597},
{0.485712, 0.785899, -0.382683},
{0.25518 , 0.749435, -0.610926},
{0.322141, 0.745338, -0.583691},
{0.280319, 0.790112, -0.545109},
{0.415597, 0.427135, -0.803016},
{0.382683, 0.485712, -0.785899},
{0.476226, 0.303801, -0.825175 },
{0.446977, 0.366027, -0.816233},
{0.48624, 0.408286, -0.772575},
{0.553372, 0.38673, -0.737712},
{0.522499, 0.448259, -0.725299},
{0.529135, 0.172532, -0.830812},
{0.504209, 0.237229 , -0.830359},
{0.551859, 0.106494, -0.82711},
{0.594895, 0.147414, -0.79017},
{0.634579, 0.187432, -0.749786},
{0.619186, 0.361592, -0.697037},
{0.678913, 0.334692, -0.653497},
{0.649448 , 0.399769, -0.64684},
{0.672319, 0.2289, -0.703983},
{0.705236, 0.267381, -0.65662},
{0.734794, 0.305212, -0.605741},
{0.760406, 0.341435, -0.552454},
{0.545109, 0.280319, -0.790112},
{0.610926, 0.25518, -0.749435},
{0.583691, 0.322141, -0.745338},
{0.552454, 0.760406, -0.341435},
{0.605741, 0.734794, -0.305212},
{0.64684, 0.649448, -0.399769},
{0.697037, 0.619186 , -0.361592},
{0.653497, 0.678913, -0.334692},
{0.65662, 0.705236, -0.267381},
{0.703983, 0.672319, -0.2289},
{0.725299, 0.522499, -0.448259},
{0.772575, 0.48624, -0.408286},
{0.737712 , 0.553372, -0.38673},
{0.785899, 0.382683, -0.485712},
{0.803016, 0.415597, -0.427135},
{0.816233, 0.446977, -0.366027},
{0.825175, 0.476226, -0.303801},
{0.749786, 0.634579, -0.187432},
{0.79017, 0.594895, -0.147414},
{0.830359, 0.504209, -0.237229},
{0.830812, 0.529135, -0.172532},
{0.82711, 0.551859, -0.106494},
{0.745338, 0.583691, -0.322141},
{0.790112, 0.545109 , -0.280319},
{0.749435, 0.610926, -0.25518},
{0.414273, 0.536784, -0.735011},
{0.552418, 0.496441, -0.669612},
{0.485208, 0.51797, -0.704471},
{0.443957, 0.584716, -0.678977},
{0.470917 , 0.628313, -0.619242},
{0.678977, 0.443957, -0.584716},
{0.619242, 0.470917, -0.628313},
{0.735011, 0.414273, -0.536784},
{0.704471, 0.485208, -0.51797},
{0.669612, 0.552418, -0.496441},
{0.496441, 0.669612, -0.552418},
{0.51797, 0.704471, -0.485208},
{0.628313, 0.619242, -0.470917},
{0.584716, 0.678977, -0.443957},
{0.536784, 0.735011, -0.414273},
{0.581952, 0.54065 , -0.607478},
{0.607478, 0.581952, -0.54065},
{0.54065, 0.607478, -0.581952},
{0.551859, -0.106494, 0.82711},
{0.634579, -0.187432, 0.749786},
{0.594895, -0.147414, 0.79017},
{0.529135 , -0.172532, 0.830812},
{0.504209, -0.237229, 0.830359},
{0.705236, -0.267381, 0.65662},
{0.672319, -0.2289, 0.703983},
{0.760406, -0.341435, 0.552454},
{0.734794, -0.305212, 0.605741},
{0.678913, -0.334692, 0.653497},
{0.649448, -0.399769, 0.64684},
{0.619186, -0.361592, 0.697037},
{0.476226, -0.303801, 0.825175},
{0.446977, -0.366027, 0.816233},
{0.553372, -0.38673 , 0.737712},
{0.522499, -0.448259, 0.725299},
{0.48624, -0.408286, 0.772575},
{0.415597, -0.427135, 0.803016},
{0.382683, -0.485712, 0.785899},
{0.610926, -0.25518, 0.749435},
{0.583691 , -0.322141, 0.745338},
{0.545109, -0.280319, 0.790112},
{0.803016, -0.415597, 0.427135},
{0.785899, -0.382683, 0.485712},
{0.825175, -0.476226, 0.303801},
{0.816233, -0.446977, 0.366027 },
{0.772575, -0.48624, 0.408286},
{0.737712, -0.553372, 0.38673},
{0.725299, -0.522499, 0.448259},
{0.830812, -0.529135, 0.172532},
{0.830359, -0.504209, 0.237229},
{0.82711, -0.551859 , 0.106494},
{0.79017, -0.594895, 0.147414},
{0.749786, -0.634579, 0.187432},
{0.697037, -0.619186, 0.361592},
{0.653497, -0.678913, 0.334692},
{0.64684, -0.649448, 0.399769},
{0.703983 , -0.672319, 0.2289},
{0.65662, -0.705236, 0.267381},
{0.605741, -0.734794, 0.305212},
{0.552454, -0.760406, 0.341435},
{0.790112, -0.545109, 0.280319},
{0.749435, -0.610926, 0.25518},
{0.745338, -0.583691, 0.322141},
{0.341435, -0.552454, 0.760406},
{0.305212, -0.605741, 0.734794},
{0.399769, -0.64684, 0.649448},
{0.361592, -0.697037, 0.619186},
{0.334692, -0.653497 , 0.678913},
{0.267381, -0.65662, 0.705236},
{0.2289, -0.703983, 0.672319},
{0.448259, -0.725299, 0.522499},
{0.408286, -0.772575, 0.48624},
{0.38673, -0.737712, 0.553372},
{0.485712 , -0.785899, 0.382683},
{0.427135, -0.803016, 0.415597},
{0.366027, -0.816233, 0.446977},
{0.303801, -0.825175, 0.476226},
{0.187432, -0.749786, 0.634579},
{0.147414, -0.79017, 0.594895},
{0.237229, -0.830359, 0.504209},
{0.172532, -0.830812, 0.529135},
{0.106494, -0.82711, 0.551859},
{0.322141, -0.745338, 0.583691},
{0.280319, -0.790112, 0.545109},
{0.25518, -0.749435 , 0.610926},
{0.735011, -0.414273, 0.536784},
{0.669612, -0.552418, 0.496441},
{0.704471, -0.485208, 0.51797},
{0.678977, -0.443957, 0.584716},
{0.619242, -0.470917, 0.628313},
{0.584716 , -0.678977, 0.443957},
{0.628313, -0.619242, 0.470917},
{0.536784, -0.735011, 0.414273},
{0.51797, -0.704471, 0.485208},
{0.496441, -0.669612, 0.552418},
{0.552418, -0.496441, 0.669612},
{0.485208, -0.51797, 0.704471},
{0.470917, -0.628313, 0.619242},
{0.443957, -0.584716, 0.678977},
{0.414273, -0.536784, 0.735011},
{0.607478, -0.581952, 0.54065},
{0.54065, -0.607478 , 0.581952},
{0.581952, -0.54065, 0.607478},
{0.551859, -0.106494, -0.82711},
{0.504209, -0.237229, -0.830359},
{0.529135, -0.172532, -0.830812},
{0.594895, -0.147414, -0.79017},
{ 0.634579, -0.187432, -0.749786},
{0.446977, -0.366027, -0.816233},
{0.476226, -0.303801, -0.825175},
{0.382683, -0.485712, -0.785899},
{0.415597, -0.427135, -0.803016},
{0.48624, -0.408286 , -0.772575},
{0.522499, -0.448259, -0.725299},
{0.553372, -0.38673, -0.737712},
{0.672319, -0.2289, -0.703983},
{0.705236, -0.267381, -0.65662},
{0.619186, -0.361592, -0.697037},
{ 0.649448, -0.399769, -0.64684},
{0.678913, -0.334692, -0.653497},
{0.734794, -0.305212, -0.605741},
{0.760406, -0.341435, -0.552454},
{0.545109, -0.280319, -0.790112},
{0.583691, -0.322141 , -0.745338},
{0.610926, -0.25518, -0.749435},
{0.305212, -0.605741, -0.734794},
{0.341435, -0.552454, -0.760406},
{0.2289, -0.703983, -0.672319},
{0.267381, -0.65662, -0.705236},
{ 0.334692, -0.653497, -0.678913},
{0.361592, -0.697037, -0.619186},
{0.399769, -0.64684, -0.649448},
{0.147414, -0.79017, -0.594895},
{0.187432, -0.749786, -0.634579},
{0.106494, -0.82711 , -0.551859},
{0.172532, -0.830812, -0.529135},
{0.237229, -0.830359, -0.504209},
{0.38673, -0.737712, -0.553372},
{0.408286, -0.772575, -0.48624},
{0.448259, -0.725299, -0.522499},
{ 0.303801, -0.825175, -0.476226},
{0.366027, -0.816233, -0.446977},
{0.427135, -0.803016, -0.415597},
{0.485712, -0.785899, -0.382683},
{0.25518, -0.749435, -0.610926},
{0.280319, -0.790112 , -0.545109},
{0.322141, -0.745338, -0.583691},
{0.785899, -0.382683, -0.485712},
{0.803016, -0.415597, -0.427135},
{0.725299, -0.522499, -0.448259},
{0.737712, -0.553372, -0.38673},
{0.772575, -0.48624, -0.408286},
{0.816233, -0.446977, -0.366027},
{0.825175, -0.476226, -0.303801},
{0.64684, -0.649448, -0.399769},
{0.653497, -0.678913, -0.334692},
{0.697037, -0.619186 , -0.361592},
{0.552454, -0.760406, -0.341435},
{0.605741, -0.734794, -0.305212},
{0.65662, -0.705236, -0.267381},
{0.703983, -0.672319, -0.2289},
{0.830359, -0.504209, -0.237229},
{ 0.830812, -0.529135, -0.172532},
{0.749786, -0.634579, -0.187432},
{0.79017, -0.594895, -0.147414},
{0.82711, -0.551859, -0.106494},
{0.745338, -0.583691, -0.322141},
{0.749435, -0.610926 , -0.25518},
{0.790112, -0.545109, -0.280319},
{0.414273, -0.536784, -0.735011},
{0.470917, -0.628313, -0.619242},
{0.443957, -0.584716, -0.678977},
{0.485208, -0.51797, -0.704471},
{ 0.552418, -0.496441, -0.669612},
{0.51797, -0.704471, -0.485208},
{0.496441, -0.669612, -0.552418},
{0.536784, -0.735011, -0.414273},
{0.584716, -0.678977, -0.443957},
{0.628313, -0.619242 , -0.470917},
{0.619242, -0.470917, -0.628313},
{0.678977, -0.443957, -0.584716},
{0.669612, -0.552418, -0.496441},
{0.704471, -0.485208, -0.51797},
{0.735011, -0.414273, -0.536784},
{0.54065, -0.607478, -0.581952},
{0.607478, -0.581952, -0.54065},
{0.581952, -0.54065, -0.607478},
{-0.551859, 0.106494, 0.82711},
{-0.634579, 0.187432, 0.749786},
{-0.594895, 0.147414 , 0.79017},
{-0.529135, 0.172532, 0.830812},
{-0.504209, 0.237229, 0.830359},
{-0.705236, 0.267381, 0.65662},
{-0.672319, 0.2289, 0.703983},
{-0.760406, 0.341435, 0.552454},
{-0.734794 , 0.305212, 0.605741},
{-0.678913, 0.334692, 0.653497},
{-0.649448, 0.399769, 0.64684},
{-0.619186, 0.361592, 0.697037},
{-0.476226, 0.303801, 0.825175},
{-0.446977, 0.366027, 0.816233},
{-0.553372, 0.38673, 0.737712},
{-0.522499, 0.448259, 0.725299},
{-0.48624, 0.408286, 0.772575},
{-0.415597, 0.427135, 0.803016},
{-0.382683, 0.485712, 0.785899},
{-0.610926, 0.25518 , 0.749435},
{-0.583691, 0.322141, 0.745338},
{-0.545109, 0.280319, 0.790112},
{-0.803016, 0.415597, 0.427135},
{-0.785899, 0.382683, 0.485712},
{-0.825175, 0.476226, 0.303801},
{- 0.816233, 0.446977, 0.366027},
{-0.772575, 0.48624, 0.408286},
{-0.737712, 0.553372, 0.38673},
{-0.725299, 0.522499, 0.448259},
{-0.830812, 0.529135, 0.172532},
{-0.830359, 0.504209, 0.237229 },
{-0.82711, 0.551859, 0.106494},
{-0.79017, 0.594895, 0.147414},
{-0.749786, 0.634579, 0.187432},
{-0.697037, 0.619186, 0.361592},
{-0.653497, 0.678913, 0.334692},
{-0.64684, 0.649448 , 0.399769},
{-0.703983, 0.672319, 0.2289},
{-0.65662, 0.705236, 0.267381},
{-0.605741, 0.734794, 0.305212},
{-0.552454, 0.760406, 0.341435},
{-0.790112, 0.545109, 0.280319},
{-0.749435 , 0.610926, 0.25518},
{-0.745338, 0.583691, 0.322141},
{-0.341435, 0.552454, 0.760406},
{-0.305212, 0.605741, 0.734794},
{-0.399769, 0.64684, 0.649448},
{-0.361592, 0.697037, 0.619186},
{-0.334692, 0.653497, 0.678913},
{-0.267381, 0.65662, 0.705236},
{-0.2289, 0.703983, 0.672319},
{-0.448259, 0.725299, 0.522499},
{-0.408286, 0.772575, 0.48624},
{-0.38673, 0.737712, 0.553372},
{-0.485712, 0.785899, 0.382683},
{-0.427135, 0.803016, 0.415597},
{-0.366027, 0.816233, 0.446977},
{-0.303801, 0.825175, 0.476226},
{-0.187432, 0.749786, 0.634579},
{-0.147414 , 0.79017, 0.594895},
{-0.237229, 0.830359, 0.504209},
{-0.172532, 0.830812, 0.529135},
{-0.106494, 0.82711, 0.551859},
{-0.322141, 0.745338, 0.583691},
{-0.280319, 0.790112, 0.545109},
{-0.25518, 0.749435, 0.610926},
{-0.735011, 0.414273, 0.536784},
{-0.669612, 0.552418, 0.496441},
{-0.704471, 0.485208, 0.51797},
{-0.678977, 0.443957, 0.584716},
{-0.619242, 0.470917 , 0.628313},
{-0.584716, 0.678977, 0.443957},
{-0.628313, 0.619242, 0.470917},
{-0.536784, 0.735011, 0.414273},
{-0.51797, 0.704471, 0.485208},
{-0.496441, 0.669612, 0.552418},
{- 0.552418, 0.496441, 0.669612},
{-0.485208, 0.51797, 0.704471},
{-0.470917, 0.628313, 0.619242},
{-0.443957, 0.584716, 0.678977},
{-0.414273, 0.536784, 0.735011},
{-0.607478, 0.581952, 0.54065 },
{-0.54065, 0.607478, 0.581952},
{-0.581952, 0.54065, 0.607478},
{-0.551859, 0.106494, -0.82711},
{-0.504209, 0.237229, -0.830359},
{-0.529135, 0.172532, -0.830812},
{-0.594895, 0.147414, -0.79017},
{-0.634579, 0.187432, -0.749786},
{-0.446977, 0.366027, -0.816233},
{-0.476226, 0.303801, -0.825175},
{-0.382683, 0.485712, -0.785899},
{-0.415597, 0.427135, -0.803016 },
{-0.48624, 0.408286, -0.772575},
{-0.522499, 0.448259, -0.725299},
{-0.553372, 0.38673, -0.737712},
{-0.672319, 0.2289, -0.703983},
{-0.705236, 0.267381, -0.65662},
{-0.619186, 0.361592, -0.697037},
{-0.649448, 0.399769, -0.64684},
{-0.678913, 0.334692, -0.653497},
{-0.734794, 0.305212, -0.605741},
{-0.760406, 0.341435, -0.552454},
{-0.545109, 0.280319, -0.790112 },
{-0.583691, 0.322141, -0.745338},
{-0.610926, 0.25518, -0.749435},
{-0.305212, 0.605741, -0.734794},
{-0.341435, 0.552454, -0.760406},
{-0.2289, 0.703983, -0.672319},
{-0.267381 , 0.65662, -0.705236},
{-0.334692, 0.653497, -0.678913},
{-0.361592, 0.697037, -0.619186},
{-0.399769, 0.64684, -0.649448},
{-0.147414, 0.79017, -0.594895},
{-0.187432, 0.749786, -0.634579 },
{-0.106494, 0.82711, -0.551859},
{-0.172532, 0.830812, -0.529135},
{-0.237229, 0.830359, -0.504209},
{-0.38673, 0.737712, -0.553372},
{-0.408286, 0.772575, -0.48624},
{-0.448259 , 0.725299, -0.522499},
{-0.303801, 0.825175, -0.476226},
{-0.366027, 0.816233, -0.446977},
{-0.427135, 0.803016, -0.415597},
{-0.485712, 0.785899, -0.382683},
{-0.25518, 0.749435, -0.610926 },
{-0.280319, 0.790112, -0.545109},
{-0.322141, 0.745338, -0.583691},
{-0.785899, 0.382683, -0.485712},
{-0.803016, 0.415597, -0.427135},
{-0.725299, 0.522499, -0.448259},
{-0.737712 , 0.553372, -0.38673},
{-0.772575, 0.48624, -0.408286},
{-0.816233, 0.446977, -0.366027},
{-0.825175, 0.476226, -0.303801},
{-0.64684, 0.649448, -0.399769},
{-0.653497, 0.678913, -0.334692 },
{-0.697037, 0.619186, -0.361592},
{-0.552454, 0.760406, -0.341435},
{-0.605741, 0.734794, -0.305212},
{-0.65662, 0.705236, -0.267381},
{-0.703983, 0.672319, -0.2289},
{-0.830359 , 0.504209, -0.237229},
{-0.830812, 0.529135, -0.172532},
{-0.749786, 0.634579, -0.187432},
{-0.79017, 0.594895, -0.147414},
{-0.82711, 0.551859, -0.106494},
{-0.745338, 0.583691, -0.322141 },
{-0.749435, 0.610926, -0.25518},
{-0.790112, 0.545109, -0.280319},
{-0.414273, 0.536784, -0.735011},
{-0.470917, 0.628313, -0.619242},
{-0.443957, 0.584716, -0.678977},
{-0.485208 , 0.51797, -0.704471},
{-0.552418, 0.496441, -0.669612},
{-0.51797, 0.704471, -0.485208},
{-0.496441, 0.669612, -0.552418},
{-0.536784, 0.735011, -0.414273},
{-0.584716, 0.678977, -0.443957 },
{-0.628313, 0.619242, -0.470917},
{-0.619242, 0.470917, -0.628313},
{-0.678977, 0.443957, -0.584716},
{-0.669612, 0.552418, -0.496441},
{-0.704471, 0.485208, -0.51797},
{-0.735011 , 0.414273, -0.536784},
{-0.54065, 0.607478, -0.581952},
{-0.607478, 0.581952, -0.54065},
{-0.581952, 0.54065, -0.607478},
{-0.551859, -0.106494, 0.82711},
{-0.504209, -0.237229, 0.830359 },
{-0.529135, -0.172532, 0.830812},
{-0.594895, -0.147414, 0.79017},
{-0.634579, -0.187432, 0.749786},
{-0.446977, -0.366027, 0.816233},
{-0.476226, -0.303801, 0.825175},
{-0.382683 , -0.485712, 0.785899},
{-0.415597, -0.427135, 0.803016},
{-0.48624, -0.408286, 0.772575},
{-0.522499, -0.448259, 0.725299},
{-0.553372, -0.38673, 0.737712},
{-0.672319, -0.2289, 0.703983 },
{-0.705236, -0.267381, 0.65662},
{-0.619186, -0.361592, 0.697037},
{-0.649448, -0.399769, 0.64684},
{-0.678913, -0.334692, 0.653497},
{-0.734794, -0.305212, 0.605741},
{-0.760406 , -0.341435, 0.552454},
{-0.545109, -0.280319, 0.790112},
{-0.583691, -0.322141, 0.745338},
{-0.610926, -0.25518, 0.749435},
{-0.305212, -0.605741, 0.734794},
{-0.341435, -0.552454, 0.760406 },
{-0.2289, -0.703983, 0.672319},
{-0.267381, -0.65662, 0.705236},
{-0.334692, -0.653497, 0.678913},
{-0.361592, -0.697037, 0.619186},
{-0.399769, -0.64684, 0.649448},
{-0.147414 , -0.79017, 0.594895},
{-0.187432, -0.749786, 0.634579},
{-0.106494, -0.82711, 0.551859},
{-0.172532, -0.830812, 0.529135},
{-0.237229, -0.830359, 0.504209},
{-0.38673, -0.737712, 0.553372 },
{-0.408286, -0.772575, 0.48624},
{-0.448259, -0.725299, 0.522499},
{-0.303801, -0.825175, 0.476226},
{-0.366027, -0.816233, 0.446977},
{-0.427135, -0.803016, 0.415597},
{-0.485712 , -0.785899, 0.382683},
{-0.25518, -0.749435, 0.610926},
{-0.280319, -0.790112, 0.545109},
{-0.322141, -0.745338, 0.583691},
{-0.785899, -0.382683, 0.485712},
{-0.803016, -0.415597, 0.427135 },
{-0.725299, -0.522499, 0.448259},
{-0.737712, -0.553372, 0.38673},
{-0.772575, -0.48624, 0.408286},
{-0.816233, -0.446977, 0.366027},
{-0.825175, -0.476226, 0.303801},
{-0.64684 , -0.649448, 0.399769},
{-0.653497, -0.678913, 0.334692},
{-0.697037, -0.619186, 0.361592},
{-0.552454, -0.760406, 0.341435},
{-0.605741, -0.734794, 0.305212},
{-0.65662, -0.705236, 0.267381 },
{-0.703983, -0.672319, 0.2289},
{-0.830359, -0.504209, 0.237229},
{-0.830812, -0.529135, 0.172532},
{-0.749786, -0.634579, 0.187432},
{-0.79017, -0.594895, 0.147414},
{-0.82711 , -0.551859, 0.106494},
{-0.745338, -0.583691, 0.322141},
{-0.749435, -0.610926, 0.25518},
{-0.790112, -0.545109, 0.280319},
{-0.414273, -0.536784, 0.735011},
{-0.470917, -0.628313, 0.619242 },
{-0.443957, -0.584716, 0.678977},
{-0.485208, -0.51797, 0.704471},
{-0.552418, -0.496441, 0.669612},
{-0.51797, -0.704471, 0.485208},
{-0.496441, -0.669612, 0.552418},
{-0.536784 , -0.735011, 0.414273},
{-0.584716, -0.678977, 0.443957},
{-0.628313, -0.619242, 0.470917},
{-0.619242, -0.470917, 0.628313},
{-0.678977, -0.443957, 0.584716},
{-0.669612, -0.552418, 0.496441 },
{-0.704471, -0.485208, 0.51797},
{-0.735011, -0.414273, 0.536784},
{-0.54065, -0.607478, 0.581952},
{-0.607478, -0.581952, 0.54065},
{-0.581952, -0.54065, 0.607478},
{-0.551859 , -0.106494, -0.82711},
{-0.634579, -0.187432, -0.749786},
{-0.594895, -0.147414, -0.79017},
{-0.529135, -0.172532, -0.830812},
{-0.504209, -0.237229, -0.830359},
{-0.705236, -0.267381, - 0.65662},
{-0.672319, -0.2289, -0.703983},
{-0.760406, -0.341435, -0.552454},
{-0.734794, -0.305212, -0.605741},
{-0.678913, -0.334692, -0.653497},
{-0.649448, -0.399769, -0.64684},
{- 0.619186, -0.361592, -0.697037},
{-0.476226, -0.303801, -0.825175},
{-0.446977, -0.366027, -0.816233},
{-0.553372, -0.38673, -0.737712},
{-0.522499, -0.448259, -0.725299},
{-0.48624, -0.408286 , -0.772575},
{-0.415597, -0.427135, -0.803016},
{-0.382683, -0.485712, -0.785899},
{-0.610926, -0.25518, -0.749435},
{-0.583691, -0.322141, -0.745338},
{-0.545109, -0.280319, -0.790112},
{-0.803016, -0.415597, -0.427135},
{-0.785899, -0.382683, -0.485712},
{-0.825175, -0.476226, -0.303801},
{-0.816233, -0.446977, -0.366027},
{-0.772575, -0.48624, -0.408286},
{-0.737712 , -0.553372, -0.38673},
{-0.725299, -0.522499, -0.448259},
{-0.830812, -0.529135, -0.172532},
{-0.830359, -0.504209, -0.237229},
{-0.82711, -0.551859, -0.106494},
{-0.79017, -0.594895, - 0.147414},
{-0.749786, -0.634579, -0.187432},
{-0.697037, -0.619186, -0.361592},
{-0.653497, -0.678913, -0.334692},
{-0.64684, -0.649448, -0.399769},
{-0.703983, -0.672319, -0.2289},
{-0.65662, -0.705236, -0.267381},
{-0.605741, -0.734794, -0.305212},
{-0.552454, -0.760406, -0.341435},
{-0.790112, -0.545109, -0.280319},
{-0.749435, -0.610926, -0.25518},
{-0.745338 , -0.583691, -0.322141},
{-0.341435, -0.552454, -0.760406},
{-0.305212, -0.605741, -0.734794},
{-0.399769, -0.64684, -0.649448},
{-0.361592, -0.697037, -0.619186},
{-0.334692, -0.653497, - 0.678913},
{-0.267381, -0.65662, -0.705236},
{-0.2289, -0.703983, -0.672319},
{-0.448259, -0.725299, -0.522499},
{-0.408286, -0.772575, -0.48624},
{-0.38673, -0.737712, -0.553372},
{- 0.485712, -0.785899, -0.382683},
{-0.427135, -0.803016, -0.415597},
{-0.366027, -0.816233, -0.446977},
{-0.303801, -0.825175, -0.476226},
{-0.187432, -0.749786, -0.634579},
{-0.147414, - 0.79017, -0.594895},
{-0.237229, -0.830359, -0.504209},
{-0.172532, -0.830812, -0.529135},
{-0.106494, -0.82711, -0.551859},
{-0.322141, -0.745338, -0.583691},
{-0.280319, -0.790112, -0.545109 },
{-0.25518, -0.749435, -0.610926},
{-0.735011, -0.414273, -0.536784},
{-0.669612, -0.552418, -0.496441},
{-0.704471, -0.485208, -0.51797},
{-0.678977, -0.443957, -0.584716},
{-0.619242 , -0.470917, -0.628313},
{-0.584716, -0.678977, -0.443957},
{-0.628313, -0.619242, -0.470917},
{-0.536784, -0.735011, -0.414273},
{-0.51797, -0.704471, -0.485208},
{-0.496441, -0.669612, - 0.552418},
{-0.552418, -0.496441, -0.669612},
{-0.485208, -0.51797, -0.704471},
{-0.470917, -0.628313, -0.619242},
{-0.443957, -0.584716, -0.678977},
{-0.414273, -0.536784, -0.735011},
{-0.607478, -0.581952, -0.54065},
{-0.54065, -0.607478, -0.581952},
{-0.581952, -0.54065, -0.607478}
};
TractOrientationContainerType::Pointer sdcontainerptr =
TractOrientationContainerType::New();
for(unsigned int i = 0; i<totalsd; i++){
TractOrientationContainerType::Element dir(
sdarray[i][0], sdarray[i][1], sdarray[i][2]);
sdcontainerptr->InsertElement(i, dir);
}
this->SetSampleDirections( sdcontainerptr );
}
}
diff --git a/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingDataHandler.cpp b/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingDataHandler.cpp
index 77d4cf0..58962c6 100644
--- a/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingDataHandler.cpp
+++ b/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingDataHandler.cpp
@@ -1,27 +1,27 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkTrackingDataHandler.h"
namespace mitk
{
TrackingDataHandler::TrackingDataHandler()
: m_RngItk(ItkRngType::New())
, m_NeedsDataInit(true)
{
}
}
diff --git a/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingDataHandler.h b/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingDataHandler.h
index ee74aff..66f86e2 100644
--- a/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingDataHandler.h
+++ b/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingDataHandler.h
@@ -1,116 +1,116 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _TrackingDataHandler
#define _TrackingDataHandler
#include <MitkFiberTrackingExports.h>
#include <boost/random/discrete_distribution.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/variate_generator.hpp>
#include <deque>
#include <itkImage.h>
#include <itkLinearInterpolateImageFunction.h>
#include <itkMersenneTwisterRandomVariateGenerator.h>
#include <itkPoint.h>
#include <mitkBaseData.h>
#include <mitkDiffusionFunctionCollection.h>
#include <mitkStreamlineTractographyParameters.h>
namespace mitk
{
/**
* \brief Abstract class for tracking handler. A tracking handler deals with determining the next progression
* direction of a streamline fiber. There are different handlers for tensor images, peak images, ... */
class MITKFIBERTRACKING_EXPORT TrackingDataHandler
{
public:
TrackingDataHandler();
virtual ~TrackingDataHandler() {}
typedef itk::Statistics::MersenneTwisterRandomVariateGenerator ItkRngType;
typedef boost::mt19937 BoostRngType;
typedef itk::Image<unsigned char, 3> ItkUcharImgType;
typedef itk::Image<short, 3> ItkShortImgType;
typedef itk::Image<float, 3> ItkFloatImgType;
typedef itk::Image<double, 3> ItkDoubleImgType;
typedef vnl_vector_fixed<float, 3> TrackingDirectionType;
typedef mitk::StreamlineTractographyParameters::MODE MODE;
virtual TrackingDirectionType ProposeDirection(
const itk::Point<float, 3> &pos,
std::deque<TrackingDirectionType> &olddirs,
itk::Index<3> &oldIndex) = 0; ///< predicts next progression direction at the given position
virtual void InitForTracking() = 0;
virtual itk::Vector<double, 3> GetSpacing() = 0;
virtual itk::Point<float, 3> GetOrigin() = 0;
virtual itk::Matrix<double, 3, 3> GetDirection() = 0;
virtual itk::ImageRegion<3> GetLargestPossibleRegion() = 0;
virtual bool WorldToIndex(itk::Point<float, 3> &pos, itk::Index<3> &index) = 0;
void SetParameters(std::shared_ptr<mitk::StreamlineTractographyParameters> parameters)
{
m_Parameters = parameters;
if (m_Parameters->m_FixRandomSeed)
{
m_Rng.seed(0);
std::srand(0);
m_RngItk->SetSeed(0);
}
else
{
m_Rng.seed();
m_RngItk->SetSeed();
std::srand(std::time(nullptr));
}
}
double GetRandDouble(const double &a, const double &b) { return m_RngItk->GetUniformVariate(a, b); }
protected:
void CalculateMinVoxelSize()
{
itk::Vector<double, 3> imageSpacing = this->GetSpacing();
float minVoxelSize = 0;
if (imageSpacing[0] < imageSpacing[1] && imageSpacing[0] < imageSpacing[2])
minVoxelSize = static_cast<float>(imageSpacing[0]);
else if (imageSpacing[1] < imageSpacing[2])
minVoxelSize = static_cast<float>(imageSpacing[1]);
else
minVoxelSize = static_cast<float>(imageSpacing[2]);
if (m_Parameters == nullptr)
mitkThrow() << "No tractography parameter opbect set!";
m_Parameters->SetMinVoxelSizeMm(minVoxelSize);
}
BoostRngType m_Rng;
ItkRngType::Pointer m_RngItk;
bool m_NeedsDataInit;
std::shared_ptr<mitk::StreamlineTractographyParameters> m_Parameters;
void DataModified() { m_NeedsDataInit = true; }
vnl_matrix_fixed<float, 3, 3> m_FloatImageRotation;
};
} // namespace mitk
#endif
diff --git a/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerOdf.cpp b/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerOdf.cpp
index 6dbf0b3..9f275c7 100644
--- a/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerOdf.cpp
+++ b/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerOdf.cpp
@@ -1,307 +1,307 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkTrackingHandlerOdf.h"
#include <itkDiffusionOdfGeneralizedFaImageFilter.h>
#include <itkImageRegionIterator.h>
#include <itkPointShell.h>
#include <omp.h>
#include <cmath>
namespace mitk
{
TrackingHandlerOdf::TrackingHandlerOdf()
: m_NumProbSamples(1)
, m_OdfFromTensor(false)
{
m_GfaInterpolator = itk::LinearInterpolateImageFunction< itk::Image< float, 3 >, float >::New();
m_OdfInterpolator = itk::LinearInterpolateImageFunction< itk::Image< ItkOdfImageType::PixelType, 3 >, float >::New();
}
TrackingHandlerOdf::~TrackingHandlerOdf()
{
}
bool TrackingHandlerOdf::WorldToIndex(itk::Point<float, 3>& pos, itk::Index<3>& index)
{
m_OdfImage->TransformPhysicalPointToIndex(pos, index);
return m_OdfImage->GetLargestPossibleRegion().IsInside(index);
}
void TrackingHandlerOdf::InitForTracking()
{
MITK_INFO << "Initializing ODF tracker.";
if (m_NeedsDataInit)
{
m_OdfHemisphereIndices.clear();
itk::OrientationDistributionFunction< float, ODF_SAMPLING_SIZE > odf;
vnl_vector_fixed<double,3> ref; ref.fill(0); ref[0]=1;
for (int i=0; i<ODF_SAMPLING_SIZE; i++)
if (dot_product(ref, odf.GetDirection(i))>0)
m_OdfHemisphereIndices.push_back(i);
m_OdfFloatDirs.set_size(m_OdfHemisphereIndices.size(), 3);
auto double_dir = m_OdfImage->GetDirection().GetVnlMatrix();
for (int r=0; r<3; r++)
for (int c=0; c<3; c++)
{
m_FloatImageRotation[r][c] = double_dir[r][c];
}
for (unsigned int i=0; i<m_OdfHemisphereIndices.size(); i++)
{
m_OdfFloatDirs[i][0] = odf.GetDirection(m_OdfHemisphereIndices[i])[0];
m_OdfFloatDirs[i][1] = odf.GetDirection(m_OdfHemisphereIndices[i])[1];
m_OdfFloatDirs[i][2] = odf.GetDirection(m_OdfHemisphereIndices[i])[2];
}
if (m_GfaImage.IsNull())
{
MITK_INFO << "Calculating GFA image.";
typedef itk::DiffusionOdfGeneralizedFaImageFilter<float,float,ODF_SAMPLING_SIZE> GfaFilterType;
GfaFilterType::Pointer gfaFilter = GfaFilterType::New();
gfaFilter->SetInput(m_OdfImage);
gfaFilter->SetComputationMethod(GfaFilterType::GFA_STANDARD);
gfaFilter->Update();
m_GfaImage = gfaFilter->GetOutput();
}
this->CalculateMinVoxelSize();
m_NeedsDataInit = false;
}
if (m_OdfFromTensor)
{
m_Parameters->m_OdfCutoff = 0;
m_Parameters->m_SharpenOdfs = false;
}
m_GfaInterpolator->SetInputImage(m_GfaImage);
m_OdfInterpolator->SetInputImage(m_OdfImage);
std::cout << "TrackingHandlerOdf - GFA threshold: " << m_Parameters->m_Cutoff << std::endl;
std::cout << "TrackingHandlerOdf - ODF threshold: " << m_Parameters->m_OdfCutoff << std::endl;
if (m_Parameters->m_SharpenOdfs)
std::cout << "TrackingHandlerOdf - Sharpening ODfs" << std::endl;
}
int TrackingHandlerOdf::SampleOdf(vnl_vector< float >& probs, vnl_vector< float >& angles)
{
boost::random::discrete_distribution<int, float> dist(probs.begin(), probs.end());
int sampled_idx = 0;
int max_sample_idx = -1;
float max_prob = 0;
int trials = 0;
for (int i=0; i<m_NumProbSamples; i++) // we sample m_NumProbSamples times and retain the sample with maximum probabilty
{
trials++;
#pragma omp critical
{
boost::random::variate_generator<boost::random::mt19937&, boost::random::discrete_distribution<int,float>> sampler(m_Rng, dist);
sampled_idx = sampler();
}
if (probs[sampled_idx]>max_prob && probs[sampled_idx]>m_Parameters->m_OdfCutoff && fabs(angles[sampled_idx])>=m_Parameters->GetAngularThresholdDot())
{
max_prob = probs[sampled_idx];
max_sample_idx = sampled_idx;
}
else if ( (probs[sampled_idx]<=m_Parameters->m_OdfCutoff || fabs(angles[sampled_idx])<m_Parameters->GetAngularThresholdDot()) && trials<50) // we allow 50 trials to exceed the ODF threshold
i--;
}
return max_sample_idx;
}
void TrackingHandlerOdf::SetIsOdfFromTensor(bool OdfFromTensor)
{
m_OdfFromTensor = OdfFromTensor;
}
bool TrackingHandlerOdf::GetIsOdfFromTensor() const
{
return m_OdfFromTensor;
}
vnl_vector_fixed<float,3> TrackingHandlerOdf::ProposeDirection(const itk::Point<float, 3>& pos, std::deque<vnl_vector_fixed<float, 3> >& olddirs, itk::Index<3>& oldIndex)
{
vnl_vector_fixed<float,3> output_direction; output_direction.fill(0);
itk::Index<3> idx;
m_OdfImage->TransformPhysicalPointToIndex(pos, idx);
if ( !m_OdfImage->GetLargestPossibleRegion().IsInside(idx) )
return output_direction;
// check GFA threshold for termination
float gfa = mitk::imv::GetImageValue<float>(pos, m_Parameters->m_InterpolateTractographyData, m_GfaInterpolator);
if (gfa<m_Parameters->m_Cutoff)
return output_direction;
vnl_vector_fixed<float,3> last_dir;
if (!olddirs.empty())
last_dir = olddirs.back();
if (!m_Parameters->m_InterpolateTractographyData && oldIndex==idx)
return last_dir;
ItkOdfImageType::PixelType odf_values = mitk::imv::GetImageValue<ItkOdfImageType::PixelType>(pos, m_Parameters->m_InterpolateTractographyData, m_OdfInterpolator);
vnl_vector< float > probs; probs.set_size(m_OdfHemisphereIndices.size());
vnl_vector< float > angles; angles.set_size(m_OdfHemisphereIndices.size()); angles.fill(1.0);
// Find ODF maximum and remove <0 values
float max_odf_val = 0;
float min_odf_val = 999;
int max_idx_d = -1;
int c = 0;
for (int i : m_OdfHemisphereIndices)
{
if (odf_values[i]<0)
odf_values[i] = 0;
if (odf_values[i]>max_odf_val)
{
max_odf_val = odf_values[i];
max_idx_d = c;
}
if (odf_values[i]<min_odf_val)
min_odf_val = odf_values[i];
probs[c] = odf_values[i];
c++;
}
if (m_Parameters->m_SharpenOdfs)
{
// sharpen ODF
probs -= min_odf_val;
probs /= (max_odf_val-min_odf_val);
for (unsigned int i=0; i<probs.size(); i++)
probs[i] = pow(probs[i], 4);
float odf_sum = probs.sum();
if (odf_sum>0)
{
probs /= odf_sum;
max_odf_val /= odf_sum;
}
}
// no previous direction
if (max_odf_val>m_Parameters->m_OdfCutoff && (olddirs.empty() || last_dir.magnitude()<=0.5))
{
if (m_Parameters->m_Mode==MODE::DETERMINISTIC) // return maximum peak
{
output_direction = m_OdfFloatDirs.get_row(max_idx_d);
return output_direction * max_odf_val;
}
else if (m_Parameters->m_Mode==MODE::PROBABILISTIC) // sample from complete ODF
{
int max_sample_idx = SampleOdf(probs, angles);
if (max_sample_idx>=0)
output_direction = m_OdfFloatDirs.get_row(max_sample_idx) * probs[max_sample_idx];
return output_direction;
}
}
else if (max_odf_val<=m_Parameters->m_OdfCutoff) // return (0,0,0)
{
return output_direction;
}
// correct previous direction
if (m_Parameters->m_FlipX)
last_dir[0] *= -1;
if (m_Parameters->m_FlipY)
last_dir[1] *= -1;
if (m_Parameters->m_FlipZ)
last_dir[2] *= -1;
// calculate angles between previous direction and ODF directions
angles = m_OdfFloatDirs*last_dir;
float probs_sum = 0;
float max_prob = 0;
for (unsigned int i=0; i<m_OdfHemisphereIndices.size(); i++)
{
float odf_val = probs[i];
float angle = angles[i];
float abs_angle = fabs(angle);
odf_val *= abs_angle; // weight probabilities according to deviation from last direction
if (m_Parameters->m_Mode==MODE::DETERMINISTIC && odf_val>max_prob && odf_val>m_Parameters->m_OdfCutoff)
{
// use maximum peak of the ODF weighted with the directional prior
max_prob = odf_val;
vnl_vector_fixed<float,3> d = m_OdfFloatDirs.get_row(i);
if (angle<0)
d *= -1;
output_direction = odf_val*d;
}
else if (m_Parameters->m_Mode==MODE::PROBABILISTIC)
{
// update ODF probabilties with the ODF values pow(abs_angle, m_DirPriorPower)
probs[i] = odf_val;
probs_sum += probs[i];
}
}
// do probabilistic sampling
if (m_Parameters->m_Mode==MODE::PROBABILISTIC && probs_sum>0.0001)
{
int max_sample_idx = SampleOdf(probs, angles);
if (max_sample_idx>=0)
{
output_direction = m_OdfFloatDirs.get_row(max_sample_idx);
if (angles[max_sample_idx]<0)
output_direction *= -1;
output_direction *= probs[max_sample_idx];
}
}
// check hard angular threshold
float mag = output_direction.magnitude();
if (mag>=0.0001)
{
output_direction.normalize();
float a = dot_product(output_direction, last_dir);
if (a<m_Parameters->GetAngularThresholdDot())
output_direction.fill(0);
}
else
output_direction.fill(0);
if (m_Parameters->m_FlipX)
output_direction[0] *= -1;
if (m_Parameters->m_FlipY)
output_direction[1] *= -1;
if (m_Parameters->m_FlipZ)
output_direction[2] *= -1;
if (m_Parameters->m_ApplyDirectionMatrix)
output_direction = m_FloatImageRotation*output_direction;
return output_direction;
}
void TrackingHandlerOdf::SetNumProbSamples(int NumProbSamples)
{
m_NumProbSamples = NumProbSamples;
}
}
diff --git a/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerOdf.h b/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerOdf.h
index 4adf191..1a6d96e 100644
--- a/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerOdf.h
+++ b/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerOdf.h
@@ -1,80 +1,80 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _TrackingHandlerOdf
#define _TrackingHandlerOdf
#include "mitkTrackingDataHandler.h"
#include <mitkOdfImage.h>
#include <mitkTensorImage.h>
#include <itkOrientationDistributionFunction.h>
#include <MitkFiberTrackingExports.h>
namespace mitk
{
/**
* \brief Enables streamline tracking on sampled ODF images. */
class MITKFIBERTRACKING_EXPORT TrackingHandlerOdf : public TrackingDataHandler
{
public:
TrackingHandlerOdf();
~TrackingHandlerOdf() override;
typedef OdfImage::ItkOdfImageType ItkOdfImageType;
typedef itk::Image< vnl_vector_fixed<float,3>, 3> ItkPDImgType;
void InitForTracking() override; ///< calls InputDataValidForTracking() and creates feature images
vnl_vector_fixed<float,3> ProposeDirection(const itk::Point<float, 3>& pos, std::deque< vnl_vector_fixed<float,3> >& olddirs, itk::Index<3>& oldIndex) override; ///< predicts next progression direction at the given position
bool WorldToIndex(itk::Point<float, 3>& pos, itk::Index<3>& index) override;
void SetOdfImage( ItkOdfImageType::Pointer img ){ m_OdfImage = img; DataModified(); }
void SetGfaImage( ItkFloatImgType::Pointer img ){ m_GfaImage = img; DataModified(); }
ItkUcharImgType::SpacingType GetSpacing() override{ return m_OdfImage->GetSpacing(); }
itk::Point<float,3> GetOrigin() override{ return m_OdfImage->GetOrigin(); }
ItkUcharImgType::DirectionType GetDirection() override{ return m_OdfImage->GetDirection(); }
ItkUcharImgType::RegionType GetLargestPossibleRegion() override{ return m_OdfImage->GetLargestPossibleRegion(); }
int OdfPower() const;
void SetNumProbSamples(int NumProbSamples);
bool GetIsOdfFromTensor() const;
void SetIsOdfFromTensor(bool OdfFromTensor);
protected:
int SampleOdf(vnl_vector< float >& probs, vnl_vector< float >& angles);
ItkFloatImgType::Pointer m_GfaImage; ///< GFA image used to determine streamline termination.
ItkOdfImageType::Pointer m_OdfImage; ///< Input odf image.
ItkOdfImageType::Pointer m_WorkingOdfImage; ///< Modified odf image.
std::vector< int > m_OdfHemisphereIndices;
vnl_matrix< float > m_OdfFloatDirs;
int m_NumProbSamples;
bool m_OdfFromTensor;
itk::LinearInterpolateImageFunction< itk::Image< float, 3 >, float >::Pointer m_GfaInterpolator;
itk::LinearInterpolateImageFunction< itk::Image< ItkOdfImageType::PixelType, 3 >, float >::Pointer m_OdfInterpolator;
};
}
#endif
diff --git a/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerPeaks.cpp b/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerPeaks.cpp
index 6ccffc4..71c9ebe 100644
--- a/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerPeaks.cpp
+++ b/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerPeaks.cpp
@@ -1,306 +1,306 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkTrackingHandlerPeaks.h"
namespace mitk
{
TrackingHandlerPeaks::TrackingHandlerPeaks()
{
}
TrackingHandlerPeaks::~TrackingHandlerPeaks()
{
}
bool TrackingHandlerPeaks::WorldToIndex(itk::Point<float, 3>& pos, itk::Index<3>& index)
{
m_DummyImage->TransformPhysicalPointToIndex(pos, index);
return m_DummyImage->GetLargestPossibleRegion().IsInside(index);
}
void TrackingHandlerPeaks::InitForTracking()
{
MITK_INFO << "Initializing peak tracker.";
if (m_NeedsDataInit)
{
itk::Vector<double, 4> spacing4 = m_PeakImage->GetSpacing();
itk::Point<float, 4> origin4 = m_PeakImage->GetOrigin();
itk::Matrix<double, 4, 4> direction4 = m_PeakImage->GetDirection();
itk::ImageRegion<4> imageRegion4 = m_PeakImage->GetLargestPossibleRegion();
spacing3[0] = spacing4[0]; spacing3[1] = spacing4[1]; spacing3[2] = spacing4[2];
origin3[0] = origin4[0]; origin3[1] = origin4[1]; origin3[2] = origin4[2];
for (int r=0; r<3; r++)
for (int c=0; c<3; c++)
{
direction3[r][c] = direction4[r][c];
m_FloatImageRotation[r][c] = direction4[r][c];
}
imageRegion3.SetSize(0, imageRegion4.GetSize()[0]);
imageRegion3.SetSize(1, imageRegion4.GetSize()[1]);
imageRegion3.SetSize(2, imageRegion4.GetSize()[2]);
m_DummyImage = ItkUcharImgType::New();
m_DummyImage->SetSpacing( spacing3 );
m_DummyImage->SetOrigin( origin3 );
m_DummyImage->SetDirection( direction3 );
m_DummyImage->SetRegions( imageRegion3 );
m_DummyImage->Allocate();
m_DummyImage->FillBuffer(0.0);
m_NumDirs = imageRegion4.GetSize(3)/3;
this->CalculateMinVoxelSize();
m_NeedsDataInit = false;
}
std::cout << "TrackingHandlerPeaks - Peak threshold: " << m_Parameters->m_Cutoff << std::endl;
if (m_Parameters->m_Mode == MODE::PROBABILISTIC)
std::cout << "TrackingHandlerPeaks - Peak jitter: " << m_Parameters->m_PeakJitter << std::endl;
}
vnl_vector_fixed<float,3> TrackingHandlerPeaks::GetMatchingDirection(itk::Index<3> idx3, vnl_vector_fixed<float,3>& oldDir)
{
vnl_vector_fixed<float,3> out_dir; out_dir.fill(0);
float angle = 0;
float mag = oldDir.magnitude();
if (mag<mitk::eps)
{
bool found = false;
if (!m_Parameters->m_FixRandomSeed)
{
// try m_NumDirs times to get a non-zero random direction
for (int j=0; j<m_NumDirs; j++)
{
int i = 0;
#pragma omp critical
i = m_RngItk->GetIntegerVariate(m_NumDirs-1);
out_dir = GetDirection(idx3, i);
if (out_dir.magnitude()>mitk::eps)
{
oldDir[0] = out_dir[0];
oldDir[1] = out_dir[1];
oldDir[2] = out_dir[2];
found = true;
break;
}
}
}
if (!found)
{
// if you didn't find a non-zero random direction, take first non-zero direction you find
for (int i=0; i<m_NumDirs; i++)
{
out_dir = GetDirection(idx3, i);
if (out_dir.magnitude()>mitk::eps)
{
oldDir[0] = out_dir[0];
oldDir[1] = out_dir[1];
oldDir[2] = out_dir[2];
break;
}
}
}
}
else
{
for (int i=0; i<m_NumDirs; i++)
{
vnl_vector_fixed<float,3> dir = GetDirection(idx3, i);
mag = dir.magnitude();
if (mag>mitk::eps)
dir.normalize();
float a = dot_product(dir, oldDir);
if (fabs(a)>angle)
{
angle = fabs(a);
if (a<0)
out_dir = -dir;
else
out_dir = dir;
out_dir *= mag;
out_dir *= angle; // shrink contribution of direction if is less parallel to previous direction
}
}
}
return out_dir;
}
vnl_vector_fixed<float,3> TrackingHandlerPeaks::GetDirection(itk::Index<3> idx3, int dirIdx)
{
vnl_vector_fixed<float,3> dir; dir.fill(0.0);
if ( !m_DummyImage->GetLargestPossibleRegion().IsInside(idx3) )
return dir;
PeakImgType::IndexType idx4;
idx4.SetElement(0,idx3[0]);
idx4.SetElement(1,idx3[1]);
idx4.SetElement(2,idx3[2]);
for (int k=0; k<3; k++)
{
idx4.SetElement(3, dirIdx*3 + k);
dir[k] = m_PeakImage->GetPixel(idx4);
}
if (m_Parameters->m_FlipX)
dir[0] *= -1;
if (m_Parameters->m_FlipY)
dir[1] *= -1;
if (m_Parameters->m_FlipZ)
dir[2] *= -1;
if (m_Parameters->m_ApplyDirectionMatrix)
dir = m_FloatImageRotation*dir;
return dir;
}
vnl_vector_fixed<float,3> TrackingHandlerPeaks::GetDirection(itk::Point<float, 3> itkP, bool interpolate, vnl_vector_fixed<float,3> oldDir){
// transform physical point to index coordinates
itk::Index<3> idx3;
itk::ContinuousIndex< float, 3> cIdx;
m_DummyImage->TransformPhysicalPointToIndex(itkP, idx3);
m_DummyImage->TransformPhysicalPointToContinuousIndex(itkP, cIdx);
vnl_vector_fixed<float,3> dir; dir.fill(0.0);
if ( !m_DummyImage->GetLargestPossibleRegion().IsInside(idx3) )
return dir;
if (interpolate)
{
float frac_x = cIdx[0] - idx3[0];
float frac_y = cIdx[1] - idx3[1];
float frac_z = cIdx[2] - idx3[2];
if (frac_x<0)
{
idx3[0] -= 1;
frac_x += 1;
}
if (frac_y<0)
{
idx3[1] -= 1;
frac_y += 1;
}
if (frac_z<0)
{
idx3[2] -= 1;
frac_z += 1;
}
frac_x = 1-frac_x;
frac_y = 1-frac_y;
frac_z = 1-frac_z;
// int coordinates inside image?
if (idx3[0] >= 0 && idx3[0] < static_cast<itk::IndexValueType>(m_DummyImage->GetLargestPossibleRegion().GetSize(0) - 1) &&
idx3[1] >= 0 && idx3[1] < static_cast<itk::IndexValueType>(m_DummyImage->GetLargestPossibleRegion().GetSize(1) - 1) &&
idx3[2] >= 0 && idx3[2] < static_cast<itk::IndexValueType>(m_DummyImage->GetLargestPossibleRegion().GetSize(2) - 1))
{
// trilinear interpolation
vnl_vector_fixed<float, 8> interpWeights;
interpWeights[0] = ( frac_x)*( frac_y)*( frac_z);
interpWeights[1] = (1-frac_x)*( frac_y)*( frac_z);
interpWeights[2] = ( frac_x)*(1-frac_y)*( frac_z);
interpWeights[3] = ( frac_x)*( frac_y)*(1-frac_z);
interpWeights[4] = (1-frac_x)*(1-frac_y)*( frac_z);
interpWeights[5] = ( frac_x)*(1-frac_y)*(1-frac_z);
interpWeights[6] = (1-frac_x)*( frac_y)*(1-frac_z);
interpWeights[7] = (1-frac_x)*(1-frac_y)*(1-frac_z);
dir = GetMatchingDirection(idx3, oldDir) * interpWeights[0];
itk::Index<3> tmpIdx = idx3; tmpIdx[0]++;
dir += GetMatchingDirection(tmpIdx, oldDir) * interpWeights[1];
tmpIdx = idx3; tmpIdx[1]++;
dir += GetMatchingDirection(tmpIdx, oldDir) * interpWeights[2];
tmpIdx = idx3; tmpIdx[2]++;
dir += GetMatchingDirection(tmpIdx, oldDir) * interpWeights[3];
tmpIdx = idx3; tmpIdx[0]++; tmpIdx[1]++;
dir += GetMatchingDirection(tmpIdx, oldDir) * interpWeights[4];
tmpIdx = idx3; tmpIdx[1]++; tmpIdx[2]++;
dir += GetMatchingDirection(tmpIdx, oldDir) * interpWeights[5];
tmpIdx = idx3; tmpIdx[2]++; tmpIdx[0]++;
dir += GetMatchingDirection(tmpIdx, oldDir) * interpWeights[6];
tmpIdx = idx3; tmpIdx[0]++; tmpIdx[1]++; tmpIdx[2]++;
dir += GetMatchingDirection(tmpIdx, oldDir) * interpWeights[7];
}
}
else
dir = GetMatchingDirection(idx3, oldDir);
return dir;
}
vnl_vector_fixed<float,3> TrackingHandlerPeaks::ProposeDirection(const itk::Point<float, 3>& pos, std::deque<vnl_vector_fixed<float, 3> >& olddirs, itk::Index<3>& oldIndex)
{
// CHECK: wann wird wo normalisiert
vnl_vector_fixed<float,3> output_direction; output_direction.fill(0);
itk::Index<3> index;
m_DummyImage->TransformPhysicalPointToIndex(pos, index);
vnl_vector_fixed<float,3> oldDir; oldDir.fill(0.0);
if (!olddirs.empty())
oldDir = olddirs.back();
float old_mag = oldDir.magnitude();
if (!m_Parameters->m_InterpolateTractographyData && oldIndex==index)
return oldDir;
output_direction = GetDirection(pos, m_Parameters->m_InterpolateTractographyData, oldDir);
float mag = output_direction.magnitude();
if (mag>=m_Parameters->m_Cutoff)
{
if (m_Parameters->m_Mode == MODE::PROBABILISTIC)
{
output_direction[0] += this->m_RngItk->GetNormalVariate(0, fabs(output_direction[0])*m_Parameters->m_PeakJitter);
output_direction[1] += this->m_RngItk->GetNormalVariate(0, fabs(output_direction[1])*m_Parameters->m_PeakJitter);
output_direction[2] += this->m_RngItk->GetNormalVariate(0, fabs(output_direction[2])*m_Parameters->m_PeakJitter);
mag = output_direction.magnitude();
}
output_direction.normalize();
float a = 1;
if (old_mag>0.5)
a = dot_product(output_direction, oldDir);
if (a>=m_Parameters->GetAngularThresholdDot())
output_direction *= mag;
else
output_direction.fill(0);
}
else
output_direction.fill(0);
return output_direction;
}
}
diff --git a/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerPeaks.h b/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerPeaks.h
index 65afafe..887953b 100644
--- a/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerPeaks.h
+++ b/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerPeaks.h
@@ -1,71 +1,71 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _TrackingHandlerPeaks
#define _TrackingHandlerPeaks
#include "mitkTrackingDataHandler.h"
#include <itkDiffusionTensor3D.h>
#include <MitkFiberTrackingExports.h>
namespace mitk
{
/**
* \brief Enables deterministic streamline tracking on MRtrix style peak images (4D float images) */
class MITKFIBERTRACKING_EXPORT TrackingHandlerPeaks : public TrackingDataHandler
{
public:
TrackingHandlerPeaks();
~TrackingHandlerPeaks() override;
typedef itk::Image< float, 4 > PeakImgType; ///< MRtrix peak image type
void InitForTracking() override; ///< calls InputDataValidForTracking() and creates feature images
vnl_vector_fixed<float,3> ProposeDirection(const itk::Point<float, 3>& pos, std::deque< vnl_vector_fixed<float,3> >& olddirs, itk::Index<3>& oldIndex) override; ///< predicts next progression direction at the given position
bool WorldToIndex(itk::Point<float, 3>& pos, itk::Index<3>& index) override;
void SetPeakImage( PeakImgType::Pointer image ){ m_PeakImage = image; DataModified(); }
itk::Vector<double, 3> GetSpacing() override{ return spacing3; }
itk::Point<float,3> GetOrigin() override{ return origin3; }
itk::Matrix<double, 3, 3> GetDirection() override{ return direction3; }
itk::ImageRegion<3> GetLargestPossibleRegion() override{ return imageRegion3; }
protected:
vnl_vector_fixed<float,3> GetDirection(itk::Point<float, 3> itkP, bool interpolate, vnl_vector_fixed<float,3> oldDir);
vnl_vector_fixed<float,3> GetMatchingDirection(itk::Index<3> idx3, vnl_vector_fixed<float,3>& oldDir);
vnl_vector_fixed<float,3> GetDirection(itk::Index<3> idx3, int dirIdx);
PeakImgType::ConstPointer m_PeakImage;
int m_NumDirs;
itk::Vector<double, 3> spacing3;
itk::Point<float, 3> origin3;
itk::Matrix<double, 3, 3> direction3;
itk::ImageRegion<3> imageRegion3;
ItkUcharImgType::Pointer m_DummyImage;
};
}
#endif
diff --git a/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerRandomForest.cpp b/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerRandomForest.cpp
index 457c018..bd995e7 100644
--- a/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerRandomForest.cpp
+++ b/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerRandomForest.cpp
@@ -1,909 +1,909 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _TrackingForestHandler_cpp
#define _TrackingForestHandler_cpp
#include "mitkTrackingHandlerRandomForest.h"
#include <itkTractDensityImageFilter.h>
#include <mitkDiffusionPropertyHelper.h>
namespace mitk
{
template< int ShOrder, int NumberOfSignalFeatures >
TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::TrackingHandlerRandomForest()
: m_WmSampleDistance(-1)
, m_NumTrees(30)
, m_MaxTreeDepth(25)
, m_SampleFraction(1.0)
, m_NumberOfSamples(0)
, m_GmSamplesPerVoxel(-1)
, m_BidirectionalFiberSampling(false)
, m_ZeroDirWmFeatures(true)
, m_MaxNumWmSamples(-1)
{
vnl_vector_fixed<float,3> ref; ref.fill(0); ref[0]=1;
itk::OrientationDistributionFunction< float, 200 > odf;
m_DirectionContainer.clear();
for (unsigned int i = 0; i<odf.GetNumberOfComponents(); i++)
{
vnl_vector_fixed<float,3> odf_dir;
odf_dir[0] = odf.GetDirection(i)[0];
odf_dir[1] = odf.GetDirection(i)[1];
odf_dir[2] = odf.GetDirection(i)[2];
if (dot_product(ref, odf_dir)>0) // only used directions on one hemisphere
m_DirectionContainer.push_back(odf_dir); // store indices for later mapping the classifier output to the actual direction
}
m_OdfFloatDirs.set_size(m_DirectionContainer.size(), 3);
for (unsigned int i=0; i<m_DirectionContainer.size(); i++)
{
m_OdfFloatDirs[i][0] = m_DirectionContainer.at(i)[0];
m_OdfFloatDirs[i][1] = m_DirectionContainer.at(i)[1];
m_OdfFloatDirs[i][2] = m_DirectionContainer.at(i)[2];
}
}
template< int ShOrder, int NumberOfSignalFeatures >
TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::~TrackingHandlerRandomForest()
{
}
template< int ShOrder, int NumberOfSignalFeatures >
bool TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::WorldToIndex(itk::Point<float, 3>& pos, itk::Index<3>& index)
{
m_DwiFeatureImages.at(0)->TransformPhysicalPointToIndex(pos, index);
return m_DwiFeatureImages.at(0)->GetLargestPossibleRegion().IsInside(index);
}
template< int ShOrder, int NumberOfSignalFeatures >
void TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::InputDataValidForTracking()
{
if (m_InputDwis.empty())
mitkThrow() << "No diffusion-weighted images set!";
if (!IsForestValid())
mitkThrow() << "No or invalid random forest detected!";
}
template< int ShOrder, int NumberOfSignalFeatures>
template<typename T>
typename std::enable_if< NumberOfSignalFeatures <=99, T >::type TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::InitDwiImageFeatures(mitk::Image::Pointer mitk_dwi)
{
MITK_INFO << "Calculating spherical harmonics features";
typedef itk::AnalyticalDiffusionQballReconstructionImageFilter<short,short,float,ShOrder, 2*NumberOfSignalFeatures> InterpolationFilterType;
typename InterpolationFilterType::Pointer filter = InterpolationFilterType::New();
filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(mitk_dwi));
filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetOriginalGradientContainer(mitk_dwi), mitk::DiffusionPropertyHelper::GetItkVectorImage(mitk_dwi) );
filter->SetLambda(0.006);
filter->SetNormalizationMethod(InterpolationFilterType::QBAR_RAW_SIGNAL);
filter->Update();
m_DwiFeatureImages.push_back(filter->GetCoefficientImage());
return true;
}
template< int ShOrder, int NumberOfSignalFeatures>
template<typename T>
typename std::enable_if< NumberOfSignalFeatures >=100, T >::type TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::InitDwiImageFeatures(mitk::Image::Pointer mitk_dwi)
{
MITK_INFO << "Interpolating raw dwi signal features";
typedef itk::AnalyticalDiffusionQballReconstructionImageFilter<short,short,float,ShOrder, 2*NumberOfSignalFeatures> InterpolationFilterType;
typename InterpolationFilterType::Pointer filter = InterpolationFilterType::New();
filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(mitk_dwi));
filter->SetGradientImage( mitk::DiffusionPropertyHelper::GetOriginalGradientContainer(mitk_dwi), mitk::DiffusionPropertyHelper::GetItkVectorImage(mitk_dwi) );
filter->SetLambda(0.006);
filter->SetNormalizationMethod(InterpolationFilterType::QBAR_RAW_SIGNAL);
filter->Update();
typename DwiFeatureImageType::Pointer dwiFeatureImage = DwiFeatureImageType::New();
dwiFeatureImage->SetSpacing(filter->GetOutput()->GetSpacing());
dwiFeatureImage->SetOrigin(filter->GetOutput()->GetOrigin());
dwiFeatureImage->SetDirection(filter->GetOutput()->GetDirection());
dwiFeatureImage->SetLargestPossibleRegion(filter->GetOutput()->GetLargestPossibleRegion());
dwiFeatureImage->SetBufferedRegion(filter->GetOutput()->GetLargestPossibleRegion());
dwiFeatureImage->SetRequestedRegion(filter->GetOutput()->GetLargestPossibleRegion());
dwiFeatureImage->Allocate();
// get signal values and store them in the feature image
vnl_vector_fixed<double,3> ref; ref.fill(0); ref[0]=1;
itk::OrientationDistributionFunction< float, 2*NumberOfSignalFeatures > odf;
itk::ImageRegionIterator< typename InterpolationFilterType::OutputImageType > it(filter->GetOutput(), filter->GetOutput()->GetLargestPossibleRegion());
while(!it.IsAtEnd())
{
typename DwiFeatureImageType::PixelType pix;
int f = 0;
for (unsigned int i = 0; i<odf.GetNumberOfComponents(); i++)
{
if (dot_product(ref, odf.GetDirection(i))>0) // only used directions on one hemisphere
{
pix[f] = it.Get()[i];
f++;
}
}
dwiFeatureImage->SetPixel(it.GetIndex(), pix);
++it;
}
m_DwiFeatureImages.push_back(dwiFeatureImage);
return true;
}
template< int ShOrder, int NumberOfSignalFeatures >
void TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::InitForTracking()
{
MITK_INFO << "Initializing random forest tracker.";
if (m_NeedsDataInit)
{
InputDataValidForTracking();
m_DwiFeatureImages.clear();
InitDwiImageFeatures<>(m_InputDwis.at(0));
// initialize interpolators
m_DwiFeatureImageInterpolator = DwiFeatureImageInterpolatorType::New();
m_DwiFeatureImageInterpolator->SetInputImage(m_DwiFeatureImages.at(0));
m_AdditionalFeatureImageInterpolators.clear();
for (auto afi_vec : m_AdditionalFeatureImages)
{
std::vector< FloatImageInterpolatorType::Pointer > v;
for (auto img : afi_vec)
{
FloatImageInterpolatorType::Pointer interp = FloatImageInterpolatorType::New();
interp->SetInputImage(img);
v.push_back(interp);
}
m_AdditionalFeatureImageInterpolators.push_back(v);
}
auto double_dir = m_DwiFeatureImages.at(0)->GetDirection().GetVnlMatrix();
for (int r=0; r<3; r++)
for (int c=0; c<3; c++)
{
m_FloatImageRotation[r][c] = double_dir[r][c];
}
this->CalculateMinVoxelSize();
m_NeedsDataInit = false;
}
}
template< int ShOrder, int NumberOfSignalFeatures >
vnl_vector_fixed<float,3> TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::ProposeDirection(const itk::Point<float, 3>& pos, std::deque<vnl_vector_fixed<float, 3> >& olddirs, itk::Index<3>& oldIndex)
{
vnl_vector_fixed<float,3> output_direction; output_direction.fill(0);
itk::Index<3> idx;
m_DwiFeatureImages.at(0)->TransformPhysicalPointToIndex(pos, idx);
bool check_last_dir = false;
vnl_vector_fixed<float,3> last_dir;
if (!olddirs.empty())
{
last_dir = olddirs.back();
if (last_dir.magnitude()>0.5)
check_last_dir = true;
}
if (!m_Parameters->m_InterpolateTractographyData && oldIndex==idx)
return last_dir;
// store feature pixel values in a vigra data type
vigra::MultiArray<2, float> featureData = vigra::MultiArray<2, float>( vigra::Shape2(1,m_Forest->GetNumFeatures()) );
featureData.init(0.0);
typename DwiFeatureImageType::PixelType dwiFeaturePixel = mitk::imv::GetImageValue< typename DwiFeatureImageType::PixelType >(pos, m_Parameters->m_InterpolateTractographyData, m_DwiFeatureImageInterpolator);
for (unsigned int f=0; f<NumberOfSignalFeatures; f++)
featureData(0,f) = dwiFeaturePixel[f];
vnl_matrix_fixed<double,3,3> direction_matrix = m_DwiFeatureImages.at(0)->GetDirection().GetVnlMatrix();
vnl_matrix_fixed<double,3,3> inverse_direction_matrix = m_DwiFeatureImages.at(0)->GetInverseDirection().GetVnlMatrix();
// append normalized previous direction(s) to feature vector
int i = 0;
vnl_vector_fixed<double,3> ref; ref.fill(0); ref[0]=1;
for (auto d : olddirs)
{
vnl_vector_fixed<double,3> tempD;
tempD[0] = d[0]; tempD[1] = d[1]; tempD[2] = d[2];
if (m_Parameters->m_FlipX)
tempD[0] *= -1;
if (m_Parameters->m_FlipY)
tempD[1] *= -1;
if (m_Parameters->m_FlipZ)
tempD[2] *= -1;
tempD = inverse_direction_matrix * tempD;
last_dir[0] = tempD[0];
last_dir[1] = tempD[1];
last_dir[2] = tempD[2];
int c = 0;
for (int f=NumberOfSignalFeatures+3*i; f<NumberOfSignalFeatures+3*(i+1); f++)
{
if (dot_product(ref, tempD)<0)
featureData(0,f) = -tempD[c];
else
featureData(0,f) = tempD[c];
c++;
}
i++;
}
// additional feature images
if (m_AdditionalFeatureImages.size()>0)
{
int c = 0;
for (auto interpolator : m_AdditionalFeatureImageInterpolators.at(0))
{
float v = mitk::imv::GetImageValue<float>(pos, false, interpolator);
featureData(0,NumberOfSignalFeatures+m_Parameters->m_NumPreviousDirections*3+c) = v;
c++;
}
}
// perform classification
vigra::MultiArray<2, float> probs(vigra::Shape2(1, m_Forest->GetNumClasses()));
m_Forest->PredictProbabilities(featureData, probs);
vnl_vector< float > angles = m_OdfFloatDirs*last_dir;
vnl_vector< float > probs2; probs2.set_size(m_DirectionContainer.size()); probs2.fill(0.0); // used for probabilistic direction sampling
float probs_sum = 0;
float pNonFib = 0; // probability that we left the white matter
float w = 0; // weight of the predicted direction
for (int i=0; i<m_Forest->GetNumClasses(); i++) // for each class (number of possible directions + out-of-wm class)
{
if (probs(0,i)>0) // if probability of respective class is 0, do nothing
{
// get label of class (does not correspond to the loop variable i)
unsigned int classLabel = m_Forest->IndexToClassLabel(i);
if (classLabel<m_DirectionContainer.size()) // does class label correspond to a direction or to the out-of-wm class?
{
float angle = angles[classLabel];
float abs_angle = fabs(angle);
if (m_Parameters->m_Mode==MODE::PROBABILISTIC)
{
probs2[classLabel] = probs(0,i);
if (check_last_dir)
probs2[classLabel] *= abs_angle;
probs_sum += probs2[classLabel];
}
else if (m_Parameters->m_Mode==MODE::DETERMINISTIC)
{
vnl_vector_fixed<float,3> d = m_DirectionContainer.at(classLabel); // get direction vector assiciated with the respective direction index
if (check_last_dir) // do we have a previous streamline direction or did we just start?
{
if (abs_angle>=m_Parameters->GetAngularThresholdDot()) // is angle between the directions smaller than our hard threshold?
{
if (angle<0) // make sure we don't walk backwards
d *= -1;
float w_i = probs(0,i)*abs_angle;
output_direction += w_i*d; // weight contribution to output direction with its probability and the angular deviation from the previous direction
w += w_i; // increase output weight of the final direction
}
}
else
{
output_direction += probs(0,i)*d;
w += probs(0,i);
}
}
}
else
pNonFib += probs(0,i); // probability that we are not in the white matter anymore
}
}
if (m_Parameters->m_Mode==MODE::PROBABILISTIC && pNonFib<0.5)
{
boost::random::discrete_distribution<int, float> dist(probs2.begin(), probs2.end());
int sampled_idx = 0;
for (int i=0; i<50; i++) // we allow 50 trials to exceed m_AngularThreshold
{
#pragma omp critical
{
boost::random::variate_generator<boost::random::mt19937&, boost::random::discrete_distribution<int,float>> sampler(m_Rng, dist);
sampled_idx = sampler();
}
if ( probs2[sampled_idx]>0.1 && (!check_last_dir || (check_last_dir && fabs(angles[sampled_idx])>=m_Parameters->GetAngularThresholdDot())) )
break;
}
output_direction = m_DirectionContainer.at(sampled_idx);
w = probs2[sampled_idx];
if (check_last_dir && angles[sampled_idx]<0) // make sure we don't walk backwards
output_direction *= -1;
}
// if we did not find a suitable direction, make sure that we return (0,0,0)
if (pNonFib>w && w>0)
output_direction.fill(0.0);
else
{
vnl_vector_fixed<double,3> tempD;
tempD[0] = output_direction[0]; tempD[1] = output_direction[1]; tempD[2] = output_direction[2];
tempD = direction_matrix * tempD;
output_direction[0] = tempD[0];
output_direction[1] = tempD[1];
output_direction[2] = tempD[2];
if (m_Parameters->m_FlipX)
output_direction[0] *= -1;
if (m_Parameters->m_FlipY)
output_direction[1] *= -1;
if (m_Parameters->m_FlipZ)
output_direction[2] *= -1;
if (m_Parameters->m_ApplyDirectionMatrix)
output_direction = m_FloatImageRotation*output_direction;
}
return output_direction * w;
}
template< int ShOrder, int NumberOfSignalFeatures >
void TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::StartTraining()
{
m_StartTime = std::chrono::system_clock::now();
InputDataValidForTraining();
InitForTraining();
CalculateTrainingSamples();
MITK_INFO << "Maximum tree depths: " << m_MaxTreeDepth;
MITK_INFO << "Sample fraction per tree: " << m_SampleFraction;
MITK_INFO << "Number of trees: " << m_NumTrees;
DefaultSplitType splitter;
splitter.UsePointBasedWeights(true);
splitter.SetWeights(m_Weights);
splitter.UseRandomSplit(false);
splitter.SetPrecision(mitk::eps);
splitter.SetMaximumTreeDepth(m_MaxTreeDepth);
std::vector< std::shared_ptr< vigra::RandomForest<int> > > trees;
int count = 0;
#pragma omp parallel for
for (int i = 0; i < m_NumTrees; ++i)
{
std::shared_ptr< vigra::RandomForest<int> > lrf = std::make_shared< vigra::RandomForest<int> >();
lrf->set_options().use_stratification(vigra::RF_NONE); // How the data should be made equal
lrf->set_options().sample_with_replacement(true); // if sampled with replacement or not
lrf->set_options().samples_per_tree(m_SampleFraction); // Fraction of samples that are used to train a tree
lrf->set_options().tree_count(1); // Number of trees that are calculated;
lrf->set_options().min_split_node_size(5); // Minimum number of datapoints that must be in a node
lrf->ext_param_.max_tree_depth = m_MaxTreeDepth;
lrf->learn(m_FeatureData, m_LabelData,vigra::rf::visitors::VisitorBase(),splitter);
#pragma omp critical
{
count++;
MITK_INFO << "Tree " << count << " finished training.";
trees.push_back(lrf);
}
}
for (int i = 1; i < m_NumTrees; ++i)
trees.at(0)->trees_.push_back(trees.at(i)->trees_[0]);
std::shared_ptr< vigra::RandomForest<int> > forest = trees.at(0);
forest->options_.tree_count_ = m_NumTrees;
m_Forest = mitk::TractographyForest::New(forest);
MITK_INFO << "Training finsihed";
m_EndTime = std::chrono::system_clock::now();
std::chrono::hours hh = std::chrono::duration_cast<std::chrono::hours>(m_EndTime - m_StartTime);
std::chrono::minutes mm = std::chrono::duration_cast<std::chrono::minutes>(m_EndTime - m_StartTime);
mm %= 60;
MITK_INFO << "Training took " << hh.count() << "h and " << mm.count() << "m";
}
template< int ShOrder, int NumberOfSignalFeatures >
void TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::InputDataValidForTraining()
{
if (m_InputDwis.empty())
mitkThrow() << "No diffusion-weighted images set!";
if (m_Tractograms.empty())
mitkThrow() << "No tractograms set!";
if (m_InputDwis.size()!=m_Tractograms.size())
mitkThrow() << "Unequal number of diffusion-weighted images and tractograms detected!";
}
template< int ShOrder, int NumberOfSignalFeatures >
bool TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::IsForestValid()
{
int additional_features = 0;
if (m_AdditionalFeatureImages.size()>0)
additional_features = m_AdditionalFeatureImages.at(0).size();
if (!m_Forest)
MITK_INFO << "No forest available!";
else
{
if (m_Forest->GetNumTrees() <= 0)
MITK_ERROR << "Forest contains no trees!";
if ( m_Forest->GetNumFeatures() != static_cast<int>(NumberOfSignalFeatures+3*m_Parameters->m_NumPreviousDirections+additional_features) )
MITK_ERROR << "Wrong number of features in forest: got " << m_Forest->GetNumFeatures() << ", expected " << (NumberOfSignalFeatures+3*m_Parameters->m_NumPreviousDirections+additional_features);
}
if(m_Forest && m_Forest->GetNumTrees()>0 && m_Forest->GetNumFeatures() == static_cast<int>(NumberOfSignalFeatures+3*m_Parameters->m_NumPreviousDirections+additional_features))
return true;
return false;
}
template< int ShOrder, int NumberOfSignalFeatures >
void TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::InitForTraining()
{
MITK_INFO << "Spherical signal interpolation and sampling ...";
for (unsigned int i=0; i<m_InputDwis.size(); i++)
{
InitDwiImageFeatures<>(m_InputDwis.at(i));
if (i>=m_AdditionalFeatureImages.size())
{
m_AdditionalFeatureImages.push_back(std::vector< ItkFloatImgType::Pointer >());
}
if (i>=m_FiberVolumeModImages.size())
{
ItkFloatImgType::Pointer img = ItkFloatImgType::New();
img->SetSpacing( m_DwiFeatureImages.at(i)->GetSpacing() );
img->SetOrigin( m_DwiFeatureImages.at(i)->GetOrigin() );
img->SetDirection( m_DwiFeatureImages.at(i)->GetDirection() );
img->SetLargestPossibleRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() );
img->SetBufferedRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() );
img->SetRequestedRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() );
img->Allocate();
img->FillBuffer(1);
m_FiberVolumeModImages.push_back(img);
}
if (m_FiberVolumeModImages.at(i)==nullptr)
{
m_FiberVolumeModImages.at(i) = ItkFloatImgType::New();
m_FiberVolumeModImages.at(i)->SetSpacing( m_DwiFeatureImages.at(i)->GetSpacing() );
m_FiberVolumeModImages.at(i)->SetOrigin( m_DwiFeatureImages.at(i)->GetOrigin() );
m_FiberVolumeModImages.at(i)->SetDirection( m_DwiFeatureImages.at(i)->GetDirection() );
m_FiberVolumeModImages.at(i)->SetLargestPossibleRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() );
m_FiberVolumeModImages.at(i)->SetBufferedRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() );
m_FiberVolumeModImages.at(i)->SetRequestedRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() );
m_FiberVolumeModImages.at(i)->Allocate();
m_FiberVolumeModImages.at(i)->FillBuffer(1);
}
if (i>=m_MaskImages.size())
{
ItkUcharImgType::Pointer newMask = ItkUcharImgType::New();
newMask->SetSpacing( m_DwiFeatureImages.at(i)->GetSpacing() );
newMask->SetOrigin( m_DwiFeatureImages.at(i)->GetOrigin() );
newMask->SetDirection( m_DwiFeatureImages.at(i)->GetDirection() );
newMask->SetLargestPossibleRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() );
newMask->SetBufferedRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() );
newMask->SetRequestedRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() );
newMask->Allocate();
newMask->FillBuffer(1);
m_MaskImages.push_back(newMask);
}
if (m_MaskImages.at(i)==nullptr)
{
m_MaskImages.at(i) = ItkUcharImgType::New();
m_MaskImages.at(i)->SetSpacing( m_DwiFeatureImages.at(i)->GetSpacing() );
m_MaskImages.at(i)->SetOrigin( m_DwiFeatureImages.at(i)->GetOrigin() );
m_MaskImages.at(i)->SetDirection( m_DwiFeatureImages.at(i)->GetDirection() );
m_MaskImages.at(i)->SetLargestPossibleRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() );
m_MaskImages.at(i)->SetBufferedRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() );
m_MaskImages.at(i)->SetRequestedRegion( m_DwiFeatureImages.at(i)->GetLargestPossibleRegion() );
m_MaskImages.at(i)->Allocate();
m_MaskImages.at(i)->FillBuffer(1);
}
}
// initialize interpolators
m_AdditionalFeatureImageInterpolators.clear();
for (auto afi_vec : m_AdditionalFeatureImages)
{
std::vector< FloatImageInterpolatorType::Pointer > v;
for (auto img : afi_vec)
{
FloatImageInterpolatorType::Pointer interp = FloatImageInterpolatorType::New();
interp->SetInputImage(img);
v.push_back(interp);
}
m_AdditionalFeatureImageInterpolators.push_back(v);
}
MITK_INFO << "Resampling fibers and calculating number of samples ...";
m_NumberOfSamples = 0;
m_SampleUsage.clear();
for (unsigned int t=0; t<m_Tractograms.size(); t++)
{
ItkUcharImgType::Pointer mask = m_MaskImages.at(t);
ItkUcharImgType::Pointer wmmask;
if (t<m_WhiteMatterImages.size() && m_WhiteMatterImages.at(t)!=nullptr)
wmmask = m_WhiteMatterImages.at(t);
else
{
MITK_INFO << "No white-matter mask found. Using fiber envelope.";
itk::TractDensityImageFilter< ItkUcharImgType >::Pointer env = itk::TractDensityImageFilter< ItkUcharImgType >::New();
env->SetFiberBundle(m_Tractograms.at(t));
env->SetInputImage(mask);
env->SetBinaryOutput(true);
env->SetUseImageGeometry(true);
env->Update();
wmmask = env->GetOutput();
if (t>=m_WhiteMatterImages.size())
m_WhiteMatterImages.push_back(wmmask);
else
m_WhiteMatterImages.at(t) = wmmask;
}
// Calculate white-matter samples
if (m_WmSampleDistance<0)
{
typename DwiFeatureImageType::Pointer image = m_DwiFeatureImages.at(t);
float minSpacing = 1;
if(image->GetSpacing()[0]<image->GetSpacing()[1] && image->GetSpacing()[0]<image->GetSpacing()[2])
minSpacing = image->GetSpacing()[0];
else if (image->GetSpacing()[1] < image->GetSpacing()[2])
minSpacing = image->GetSpacing()[1];
else
minSpacing = image->GetSpacing()[2];
m_WmSampleDistance = minSpacing*0.5;
}
m_Tractograms.at(t)->ResampleLinear(m_WmSampleDistance);
int wmSamples = m_Tractograms.at(t)->GetNumberOfPoints()-2*m_Tractograms.at(t)->GetNumFibers();
if (m_BidirectionalFiberSampling)
wmSamples *= 2;
if (m_ZeroDirWmFeatures)
wmSamples *= (m_Parameters->m_NumPreviousDirections+1);
MITK_INFO << "White matter samples available: " << wmSamples;
// upper limit for samples
if (m_MaxNumWmSamples>0 && wmSamples>m_MaxNumWmSamples)
{
if ((float)m_MaxNumWmSamples/wmSamples > 0.8)
{
m_SampleUsage.push_back(std::vector<bool>(wmSamples, true));
m_NumberOfSamples += wmSamples;
}
else
{
m_SampleUsage.push_back(std::vector<bool>(wmSamples, false));
m_NumberOfSamples += m_MaxNumWmSamples;
wmSamples = m_MaxNumWmSamples;
MITK_INFO << "Limiting white matter samples to: " << m_MaxNumWmSamples;
itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer randgen = itk::Statistics::MersenneTwisterRandomVariateGenerator::New();
randgen->SetSeed();
int c = 0;
while (c<m_MaxNumWmSamples)
{
int idx = randgen->GetIntegerVariate(m_MaxNumWmSamples-1);
if (m_SampleUsage[t][idx]==false)
{
m_SampleUsage[t][idx]=true;
++c;
}
}
}
}
else
{
m_SampleUsage.push_back(std::vector<bool>(wmSamples, true));
m_NumberOfSamples += wmSamples;
}
// calculate gray-matter samples
itk::ImageRegionConstIterator<ItkUcharImgType> it(wmmask, wmmask->GetLargestPossibleRegion());
int OUTOFWM = 0;
while(!it.IsAtEnd())
{
if (it.Get()==0 && mask->GetPixel(it.GetIndex())>0)
OUTOFWM++;
++it;
}
MITK_INFO << "Non-white matter voxels: " << OUTOFWM;
if (m_GmSamplesPerVoxel>0)
{
m_GmSamples.push_back(m_GmSamplesPerVoxel);
m_NumberOfSamples += m_GmSamplesPerVoxel*OUTOFWM;
}
else if (OUTOFWM>0)
{
int gm_per_voxel = 0.5+(float)wmSamples/(float)OUTOFWM;
if (gm_per_voxel<=0)
gm_per_voxel = 1;
m_GmSamples.push_back(gm_per_voxel);
m_NumberOfSamples += m_GmSamples.back()*OUTOFWM;
MITK_INFO << "Non-white matter samples per voxel: " << m_GmSamples.back();
}
else
{
m_GmSamples.push_back(0);
}
MITK_INFO << "Non-white matter samples: " << m_GmSamples.back()*OUTOFWM;
}
MITK_INFO << "Number of samples: " << m_NumberOfSamples;
}
template< int ShOrder, int NumberOfSignalFeatures >
void TrackingHandlerRandomForest< ShOrder, NumberOfSignalFeatures >::CalculateTrainingSamples()
{
vnl_vector_fixed<float,3> ref; ref.fill(0); ref[0]=1;
m_FeatureData.reshape( vigra::Shape2(m_NumberOfSamples, NumberOfSignalFeatures+m_Parameters->m_NumPreviousDirections*3+m_AdditionalFeatureImages.at(0).size()) );
m_LabelData.reshape( vigra::Shape2(m_NumberOfSamples,1) );
m_Weights.reshape( vigra::Shape2(m_NumberOfSamples,1) );
MITK_INFO << "Number of features: " << m_FeatureData.shape(1);
itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer m_RandGen = itk::Statistics::MersenneTwisterRandomVariateGenerator::New();
m_RandGen->SetSeed();
MITK_INFO << "Creating training data ...";
unsigned int sampleCounter = 0;
for (unsigned int t=0; t<m_Tractograms.size(); t++)
{
ItkFloatImgType::Pointer fiber_folume = m_FiberVolumeModImages.at(t);
FloatImageInterpolatorType::Pointer volume_interpolator = FloatImageInterpolatorType::New();
volume_interpolator->SetInputImage(fiber_folume);
typename DwiFeatureImageType::Pointer image = m_DwiFeatureImages.at(t);
typename DwiFeatureImageInterpolatorType::Pointer dwi_interp = DwiFeatureImageInterpolatorType::New();
dwi_interp->SetInputImage(image);
ItkUcharImgType::Pointer wmMask = m_WhiteMatterImages.at(t);
ItkUcharImgType::Pointer mask;
if (t<m_MaskImages.size())
mask = m_MaskImages.at(t);
// non-white matter samples
itk::ImageRegionConstIterator<ItkUcharImgType> it(wmMask, wmMask->GetLargestPossibleRegion());
while(!it.IsAtEnd())
{
if (it.Get()==0 && (mask.IsNull() || (mask.IsNotNull() && mask->GetPixel(it.GetIndex())>0)))
{
typename DwiFeatureImageType::PixelType pix = image->GetPixel(it.GetIndex());
// random directions
for (unsigned int i=0; i<m_GmSamples.at(t); i++)
{
// diffusion signal features
for (unsigned int f=0; f<NumberOfSignalFeatures; f++)
{
m_FeatureData(sampleCounter,f) = pix[f];
if(m_FeatureData(sampleCounter,f)!=m_FeatureData(sampleCounter,f))
m_FeatureData(sampleCounter,f) = 0;
}
// direction feature
int num_zero_dirs = m_RandGen->GetIntegerVariate(m_Parameters->m_NumPreviousDirections); // how many directions should be zero?
for (unsigned int i=0; i<m_Parameters->m_NumPreviousDirections; i++)
{
int c=0;
vnl_vector_fixed<float,3> probe;
if (static_cast<int>(i)<num_zero_dirs)
probe.fill(0.0);
else
{
probe[0] = m_RandGen->GetVariate()*2-1;
probe[1] = m_RandGen->GetVariate()*2-1;
probe[2] = m_RandGen->GetVariate()*2-1;
probe.normalize();
if (dot_product(ref, probe)<0)
probe *= -1;
}
for (unsigned int f=NumberOfSignalFeatures+3*i; f<NumberOfSignalFeatures+3*(i+1); f++)
{
m_FeatureData(sampleCounter,f) = probe[c];
c++;
}
}
// additional feature images
int add_feat_c = 0;
for (auto interpolator : m_AdditionalFeatureImageInterpolators.at(t))
{
itk::Point<float, 3> itkP;
image->TransformIndexToPhysicalPoint(it.GetIndex(), itkP);
float v = mitk::imv::GetImageValue<float>(itkP, false, interpolator);
m_FeatureData(sampleCounter,NumberOfSignalFeatures+m_Parameters->m_NumPreviousDirections*3+add_feat_c) = v;
add_feat_c++;
}
// label and sample weight
m_LabelData(sampleCounter,0) = m_DirectionContainer.size();
m_Weights(sampleCounter,0) = 1.0;
sampleCounter++;
}
}
++it;
}
unsigned int num_gm_samples = sampleCounter;
// white matter samples
mitk::FiberBundle::Pointer fib = m_Tractograms.at(t);
vtkSmartPointer< vtkPolyData > polyData = fib->GetFiberPolyData();
vnl_vector_fixed<float,3> zero_dir; zero_dir.fill(0.0);
for (unsigned int i=0; i<fib->GetNumFibers(); i++)
{
vtkCell* cell = polyData->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
float fiber_weight = fib->GetFiberWeight(i);
for (int n = 0; n <= static_cast<int>(m_Parameters->m_NumPreviousDirections); ++n)
{
if (!m_ZeroDirWmFeatures)
n = m_Parameters->m_NumPreviousDirections;
for (bool reverse : {false, true})
{
for (int j=1; j<numPoints-1; j++)
{
if (!m_SampleUsage[t][sampleCounter-num_gm_samples])
continue;
itk::Point<float, 3> itkP1, itkP2;
int num_nonzero_dirs = m_Parameters->m_NumPreviousDirections;
if (!reverse)
num_nonzero_dirs = std::min(n, j);
else
num_nonzero_dirs = std::min(n, numPoints-j-1);
vnl_vector_fixed<float,3> dir;
// zero directions
for (unsigned int k=0; k<m_Parameters->m_NumPreviousDirections-num_nonzero_dirs; k++)
{
dir.fill(0.0);
int c = 0;
for (unsigned int f=NumberOfSignalFeatures+3*k; f<NumberOfSignalFeatures+3*(k+1); f++)
{
m_FeatureData(sampleCounter,f) = dir[c];
c++;
}
}
// nonzero directions
for (int k=0; k<num_nonzero_dirs; k++)
{
double* p = nullptr;
int n_idx = num_nonzero_dirs-k;
if (!reverse)
{
p = points->GetPoint(j-n_idx);
itkP1[0] = p[0]; itkP1[1] = p[1]; itkP1[2] = p[2];
p = points->GetPoint(j-n_idx+1);
itkP2[0] = p[0]; itkP2[1] = p[1]; itkP2[2] = p[2];
}
else
{
p = points->GetPoint(j+n_idx);
itkP1[0] = p[0]; itkP1[1] = p[1]; itkP1[2] = p[2];
p = points->GetPoint(j+n_idx-1);
itkP2[0] = p[0]; itkP2[1] = p[1]; itkP2[2] = p[2];
}
dir[0]=itkP1[0]-itkP2[0];
dir[1]=itkP1[1]-itkP2[1];
dir[2]=itkP1[2]-itkP2[2];
if (dir.magnitude()<0.0001)
mitkThrow() << "streamline error!";
dir.normalize();
if (dir[0]!=dir[0] || dir[1]!=dir[1] || dir[2]!=dir[2])
mitkThrow() << "ERROR: NaN direction!";
if (dot_product(ref, dir)<0)
dir *= -1;
int c = 0;
for (unsigned int f=NumberOfSignalFeatures+3*(k+m_Parameters->m_NumPreviousDirections-num_nonzero_dirs); f<NumberOfSignalFeatures+3*(k+1+m_Parameters->m_NumPreviousDirections-num_nonzero_dirs); f++)
{
m_FeatureData(sampleCounter,f) = dir[c];
c++;
}
}
// get target direction
double* p = points->GetPoint(j);
itkP1[0] = p[0]; itkP1[1] = p[1]; itkP1[2] = p[2];
if (reverse)
{
p = points->GetPoint(j-1);
itkP2[0] = p[0]; itkP2[1] = p[1]; itkP2[2] = p[2];
}
else
{
p = points->GetPoint(j+1);
itkP2[0] = p[0]; itkP2[1] = p[1]; itkP2[2] = p[2];
}
dir[0]=itkP2[0]-itkP1[0];
dir[1]=itkP2[1]-itkP1[1];
dir[2]=itkP2[2]-itkP1[2];
if (dir.magnitude()<0.0001)
mitkThrow() << "streamline error!";
dir.normalize();
if (dir[0]!=dir[0] || dir[1]!=dir[1] || dir[2]!=dir[2])
mitkThrow() << "ERROR: NaN direction!";
if (dot_product(ref, dir)<0)
dir *= -1;
// image features
float volume_mod = mitk::imv::GetImageValue<float>(itkP1, false, volume_interpolator);
// diffusion signal features
typename DwiFeatureImageType::PixelType pix = mitk::imv::GetImageValue< typename DwiFeatureImageType::PixelType >(itkP1, m_Parameters->m_InterpolateTractographyData, dwi_interp);
for (unsigned int f=0; f<NumberOfSignalFeatures; f++)
m_FeatureData(sampleCounter,f) = pix[f];
// additional feature images
int add_feat_c = 0;
for (auto interpolator : m_AdditionalFeatureImageInterpolators.at(t))
{
float v = mitk::imv::GetImageValue<float>(itkP1, false, interpolator);
add_feat_c++;
m_FeatureData(sampleCounter,NumberOfSignalFeatures+2+add_feat_c) = v;
}
// set label values
float angle = 0;
float m = dir.magnitude();
if (m>0.0001)
{
int l = 0;
for (auto d : m_DirectionContainer)
{
float a = fabs(dot_product(dir, d));
if (a>angle)
{
m_LabelData(sampleCounter,0) = l;
m_Weights(sampleCounter,0) = fiber_weight*volume_mod;
angle = a;
}
l++;
}
}
sampleCounter++;
}
if (!m_BidirectionalFiberSampling) // don't sample fibers backward
break;
}
}
}
}
m_Tractograms.clear();
MITK_INFO << "done";
}
}
#endif
diff --git a/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerRandomForest.h b/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerRandomForest.h
index 5599384..5d7769c 100644
--- a/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerRandomForest.h
+++ b/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerRandomForest.h
@@ -1,163 +1,163 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _TrackingForestHandler
#define _TrackingForestHandler
#include <mitkTrackingDataHandler.h>
#include <mitkFiberBundle.h>
#include <itkAnalyticalDiffusionQballReconstructionImageFilter.h>
#include <itkOrientationDistributionFunction.h>
#include <itkMersenneTwisterRandomVariateGenerator.h>
#include <itkOrientationDistributionFunction.h>
#include <chrono>
#include <mitkTractographyForest.h>
#undef DIFFERENCE
#define VIGRA_STATIC_LIB
#include <vigra/random_forest.hxx>
#include <vigra/multi_array.hxx>
#include <vigra/random_forest_hdf5_impex.hxx>
#include <mitkLinearSplitting.h>
#include <mitkThresholdSplit.h>
#include <mitkImpurityLoss.h>
#define _USE_MATH_DEFINES
#include <cmath>
namespace mitk
{
/**
* \brief Manages random forests for fiber tractography. The preparation of the features from the inputa data and the training process are handled here. The data preprocessing and actual prediction for the tracking process is also performed here. The tracking itself is performed in MLBSTrackingFilter. */
template< int ShOrder, int NumberOfSignalFeatures >
class TrackingHandlerRandomForest : public TrackingDataHandler
{
public:
TrackingHandlerRandomForest();
~TrackingHandlerRandomForest() override;
typedef itk::Image< itk::Vector< float, NumberOfSignalFeatures > , 3 > DwiFeatureImageType;
typedef itk::LinearInterpolateImageFunction< DwiFeatureImageType, float > DwiFeatureImageInterpolatorType;
typedef itk::LinearInterpolateImageFunction< ItkFloatImgType, float > FloatImageInterpolatorType;
typedef mitk::ThresholdSplit<mitk::LinearSplitting< mitk::ImpurityLoss<> >,int,vigra::ClassificationTag> DefaultSplitType;
void SetDwis( std::vector< Image::Pointer > images ){ m_InputDwis = images; DataModified(); }
void AddDwi( Image::Pointer img ){ m_InputDwis.push_back(img); DataModified(); }
void SetTractograms( std::vector< FiberBundle::Pointer > tractograms )
{
m_Tractograms.clear();
for (auto fib : tractograms)
m_Tractograms.push_back(fib);
DataModified();
}
void SetMaskImages( std::vector< ItkUcharImgType::Pointer > images ){ m_MaskImages = images; DataModified(); }
void SetWhiteMatterImages( std::vector< ItkUcharImgType::Pointer > images ){ m_WhiteMatterImages = images; DataModified(); }
void SetFiberVolumeModImages( std::vector< ItkFloatImgType::Pointer > images ){ m_FiberVolumeModImages = images; DataModified(); }
void SetAdditionalFeatureImages( std::vector< std::vector< ItkFloatImgType::Pointer > > images ){ m_AdditionalFeatureImages = images; DataModified(); }
void StartTraining();
void SetForest(mitk::TractographyForest::Pointer forest){ m_Forest = forest; }
void SetMaxNumWmSamples(int num){ m_MaxNumWmSamples=num; }
void SetNumTrees(int num){ m_NumTrees = num; }
void SetMaxTreeDepth(int depth){ m_MaxTreeDepth = depth; }
void SetFiberSamplingStep(float step){ m_WmSampleDistance = step; }
void SetGrayMatterSamplesPerVoxel(int samples){ m_GmSamplesPerVoxel = samples; }
void SetSampleFraction(float fraction){ m_SampleFraction = fraction; }
void SetBidirectionalFiberSampling(bool val) { m_BidirectionalFiberSampling = val; }
void SetZeroDirWmFeatures(bool val) { m_ZeroDirWmFeatures = val; }
void InitForTracking() override; ///< calls InputDataValidForTracking() and creates feature images
vnl_vector_fixed<float,3> ProposeDirection(const itk::Point<float, 3>& pos, std::deque< vnl_vector_fixed<float,3> >& olddirs, itk::Index<3>& oldIndex) override; ///< predicts next progression direction at the given position
bool WorldToIndex(itk::Point<float, 3>& pos, itk::Index<3>& index) override;
bool IsForestValid(); ///< true is forest is not null, has more than 0 trees and the correct number of features (NumberOfSignalFeatures + 3)
mitk::TractographyForest::Pointer GetForest(){ return m_Forest; }
ItkUcharImgType::SpacingType GetSpacing() override{ return m_DwiFeatureImages.at(0)->GetSpacing(); }
itk::Point<float,3> GetOrigin() override{ return m_DwiFeatureImages.at(0)->GetOrigin(); }
ItkUcharImgType::DirectionType GetDirection() override{ return m_DwiFeatureImages.at(0)->GetDirection(); }
ItkUcharImgType::RegionType GetLargestPossibleRegion() override{ return m_DwiFeatureImages.at(0)->GetLargestPossibleRegion(); }
protected:
void InputDataValidForTracking(); ///< check if raw data is set and tracking forest is valid
template<typename T=bool>
typename std::enable_if<NumberOfSignalFeatures <= 99, T>::type InitDwiImageFeatures(mitk::Image::Pointer mitk_dwi);
template<typename T=bool>
typename std::enable_if<NumberOfSignalFeatures >= 100, T>::type InitDwiImageFeatures(mitk::Image::Pointer mitk_dwi);
void InputDataValidForTraining(); ///< Check if everything is tehere for training (raw datasets, fiber tracts)
void InitForTraining(); ///< Generate masks if necessary, resample fibers, spherically interpolate raw DWIs
void CalculateTrainingSamples(); ///< Calculate GM and WM features using the interpolated raw data, the WM masks and the fibers
std::vector< Image::Pointer > m_InputDwis; ///< original input DWI data
mitk::TractographyForest::Pointer m_Forest; ///< random forest classifier
std::chrono::time_point<std::chrono::system_clock> m_StartTime;
std::chrono::time_point<std::chrono::system_clock> m_EndTime;
std::vector< typename DwiFeatureImageType::Pointer > m_DwiFeatureImages;
std::vector< std::vector< ItkFloatImgType::Pointer > > m_AdditionalFeatureImages;
std::vector< ItkFloatImgType::Pointer > m_FiberVolumeModImages; ///< used to correct the fiber density
std::vector< FiberBundle::Pointer > m_Tractograms; ///< training tractograms
std::vector< ItkUcharImgType::Pointer > m_MaskImages; ///< binary mask images to constrain training to a certain area (e.g. brain mask)
std::vector< ItkUcharImgType::Pointer > m_WhiteMatterImages; ///< defines white matter voxels. if not set, theses mask images are automatically generated from the input tractograms
float m_WmSampleDistance; ///< deterines the number of white matter samples (distance of sampling points on each fiber).
int m_NumTrees; ///< number of trees in random forest
int m_MaxTreeDepth; ///< limits the tree depth
float m_SampleFraction; ///< fraction of samples used to train each tree
unsigned int m_NumberOfSamples; ///< stores overall number of samples used for training
std::vector< unsigned int > m_GmSamples; ///< number of gray matter samples
int m_GmSamplesPerVoxel; ///< number of gray matter samplees per voxel. if -1, then the number is automatically chosen to gain an overall number of GM samples close to the number of WM samples.
vigra::MultiArray<2, float> m_FeatureData; ///< vigra container for training features
// only for tracking
vigra::MultiArray<2, float> m_LabelData; ///< vigra container for training labels
vigra::MultiArray<2, double> m_Weights; ///< vigra container for training sample weights
std::vector< vnl_vector_fixed<float,3> > m_DirectionContainer;
vnl_matrix< float > m_OdfFloatDirs;
bool m_BidirectionalFiberSampling;
bool m_ZeroDirWmFeatures;
int m_MaxNumWmSamples;
std::vector< std::vector< bool > > m_SampleUsage;
vnl_matrix_fixed<float,3,3> m_ImageDirection;
vnl_matrix_fixed<float,3,3> m_ImageDirectionInverse;
typename DwiFeatureImageInterpolatorType::Pointer m_DwiFeatureImageInterpolator;
std::vector< std::vector< FloatImageInterpolatorType::Pointer > > m_AdditionalFeatureImageInterpolators;
};
}
#include "mitkTrackingHandlerRandomForest.cpp"
#endif
diff --git a/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerTensor.cpp b/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerTensor.cpp
index 9848416..df65766 100644
--- a/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerTensor.cpp
+++ b/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerTensor.cpp
@@ -1,378 +1,378 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkTrackingHandlerTensor.h"
namespace mitk
{
TrackingHandlerTensor::TrackingHandlerTensor()
: m_InterpolateTensors(true)
, m_NumberOfInputs(0)
{
m_FaInterpolator = itk::LinearInterpolateImageFunction< itk::Image< float, 3 >, float >::New();
}
TrackingHandlerTensor::~TrackingHandlerTensor()
{
}
void TrackingHandlerTensor::InitForTracking()
{
MITK_INFO << "Initializing tensor tracker.";
if (m_NeedsDataInit)
{
m_NumberOfInputs = m_TensorImages.size();
for (int i=0; i<m_NumberOfInputs; i++)
{
ItkPDImgType::Pointer pdImage = ItkPDImgType::New();
pdImage->SetSpacing( m_TensorImages.at(0)->GetSpacing() );
pdImage->SetOrigin( m_TensorImages.at(0)->GetOrigin() );
pdImage->SetDirection( m_TensorImages.at(0)->GetDirection() );
pdImage->SetRegions( m_TensorImages.at(0)->GetLargestPossibleRegion() );
pdImage->Allocate();
m_PdImage.push_back(pdImage);
ItkDoubleImgType::Pointer emaxImage = ItkDoubleImgType::New();
emaxImage->SetSpacing( m_TensorImages.at(0)->GetSpacing() );
emaxImage->SetOrigin( m_TensorImages.at(0)->GetOrigin() );
emaxImage->SetDirection( m_TensorImages.at(0)->GetDirection() );
emaxImage->SetRegions( m_TensorImages.at(0)->GetLargestPossibleRegion() );
emaxImage->Allocate();
emaxImage->FillBuffer(1.0);
m_EmaxImage.push_back(emaxImage);
}
bool useUserFaImage = true;
if (m_FaImage.IsNull())
{
m_FaImage = ItkFloatImgType::New();
m_FaImage->SetSpacing( m_TensorImages.at(0)->GetSpacing() );
m_FaImage->SetOrigin( m_TensorImages.at(0)->GetOrigin() );
m_FaImage->SetDirection( m_TensorImages.at(0)->GetDirection() );
m_FaImage->SetRegions( m_TensorImages.at(0)->GetLargestPossibleRegion() );
m_FaImage->Allocate();
m_FaImage->FillBuffer(0.0);
useUserFaImage = false;
}
typedef itk::DiffusionTensor3D<float> TensorType;
for (int x=0; x<(int)m_TensorImages.at(0)->GetLargestPossibleRegion().GetSize()[0]; x++)
for (int y=0; y<(int)m_TensorImages.at(0)->GetLargestPossibleRegion().GetSize()[1]; y++)
for (int z=0; z<(int)m_TensorImages.at(0)->GetLargestPossibleRegion().GetSize()[2]; z++)
{
ItkTensorImageType::IndexType index;
index[0] = x; index[1] = y; index[2] = z;
for (int i=0; i<m_NumberOfInputs; i++)
{
TensorType::EigenValuesArrayType eigenvalues;
TensorType::EigenVectorsMatrixType eigenvectors;
ItkTensorImageType::PixelType tensor;
vnl_vector_fixed<float,3> dir;
tensor = m_TensorImages.at(i)->GetPixel(index);
tensor.ComputeEigenAnalysis(eigenvalues, eigenvectors);
dir[0] = eigenvectors(2, 0);
dir[1] = eigenvectors(2, 1);
dir[2] = eigenvectors(2, 2);
if (dir.magnitude()>mitk::eps)
dir.normalize();
else
dir.fill(0.0);
m_PdImage.at(i)->SetPixel(index, dir);
if (!useUserFaImage)
m_FaImage->SetPixel(index, m_FaImage->GetPixel(index)+tensor.GetFractionalAnisotropy());
m_EmaxImage.at(i)->SetPixel(index, 2/eigenvalues[2]);
}
if (!useUserFaImage)
m_FaImage->SetPixel(index, m_FaImage->GetPixel(index)/m_NumberOfInputs);
}
auto double_dir = m_TensorImages.at(0)->GetDirection().GetVnlMatrix();
for (int r=0; r<3; r++)
for (int c=0; c<3; c++)
{
m_FloatImageRotation[r][c] = double_dir[r][c];
}
this->CalculateMinVoxelSize();
m_NeedsDataInit = false;
}
if (m_Parameters->m_F+m_Parameters->m_G>1.0)
{
float temp = m_Parameters->m_F+m_Parameters->m_G;
m_Parameters->m_F /= temp;
m_Parameters->m_G /= temp;
}
m_FaInterpolator->SetInputImage(m_FaImage);
std::cout << "TrackingHandlerTensor - FA threshold: " << m_Parameters->m_Cutoff << std::endl;
std::cout << "TrackingHandlerTensor - f: " << m_Parameters->m_F << std::endl;
std::cout << "TrackingHandlerTensor - g: " << m_Parameters->m_G << std::endl;
}
vnl_vector_fixed<float,3> TrackingHandlerTensor::GetMatchingDirection(itk::Index<3> idx, vnl_vector_fixed<float,3>& oldDir, int& image_num)
{
vnl_vector_fixed<float,3> out_dir; out_dir.fill(0);
float angle = 0;
float mag = oldDir.magnitude();
if (mag<mitk::eps)
{
for (unsigned int i=0; i<m_PdImage.size(); i++)
{
out_dir = m_PdImage.at(i)->GetPixel(idx);
if (out_dir.magnitude()>0.5)
{
image_num = i;
oldDir[0] = out_dir[0];
oldDir[1] = out_dir[1];
oldDir[2] = out_dir[2];
break;
}
}
}
else
{
for (unsigned int i=0; i<m_PdImage.size(); i++)
{
vnl_vector_fixed<float,3> dir = m_PdImage.at(i)->GetPixel(idx);
float a = dot_product(dir, oldDir);
if (fabs(a)>angle)
{
image_num = i;
angle = fabs(a);
if (a<0)
out_dir = -dir;
else
out_dir = dir;
out_dir *= angle; // shrink contribution of direction if is less parallel to previous direction
}
}
}
return out_dir;
}
bool TrackingHandlerTensor::WorldToIndex(itk::Point<float, 3>& pos, itk::Index<3>& index)
{
m_TensorImages.at(0)->TransformPhysicalPointToIndex(pos, index);
return m_TensorImages.at(0)->GetLargestPossibleRegion().IsInside(index);
}
vnl_vector_fixed<float,3> TrackingHandlerTensor::GetDirection(itk::Point<float, 3> itkP, vnl_vector_fixed<float,3> oldDir, TensorType& tensor)
{
// transform physical point to index coordinates
itk::Index<3> idx;
itk::ContinuousIndex< float, 3> cIdx;
m_FaImage->TransformPhysicalPointToIndex(itkP, idx);
m_FaImage->TransformPhysicalPointToContinuousIndex(itkP, cIdx);
vnl_vector_fixed<float,3> dir; dir.fill(0.0);
if ( !m_FaImage->GetLargestPossibleRegion().IsInside(idx) )
return dir;
int image_num = -1;
if (!m_Parameters->m_InterpolateTractographyData)
{
dir = GetMatchingDirection(idx, oldDir, image_num);
if (image_num>=0)
tensor = m_TensorImages[image_num]->GetPixel(idx) * m_EmaxImage[image_num]->GetPixel(idx);
}
else
{
float frac_x = cIdx[0] - idx[0];
float frac_y = cIdx[1] - idx[1];
float frac_z = cIdx[2] - idx[2];
if (frac_x<0)
{
idx[0] -= 1;
frac_x += 1;
}
if (frac_y<0)
{
idx[1] -= 1;
frac_y += 1;
}
if (frac_z<0)
{
idx[2] -= 1;
frac_z += 1;
}
frac_x = 1-frac_x;
frac_y = 1-frac_y;
frac_z = 1-frac_z;
// int coordinates inside image?
if (idx[0] >= 0 && idx[0] < static_cast<itk::IndexValueType>(m_FaImage->GetLargestPossibleRegion().GetSize(0) - 1) &&
idx[1] >= 0 && idx[1] < static_cast<itk::IndexValueType>(m_FaImage->GetLargestPossibleRegion().GetSize(1) - 1) &&
idx[2] >= 0 && idx[2] < static_cast<itk::IndexValueType>(m_FaImage->GetLargestPossibleRegion().GetSize(2) - 1))
{
// trilinear interpolation
vnl_vector_fixed<float, 8> interpWeights;
interpWeights[0] = ( frac_x)*( frac_y)*( frac_z);
interpWeights[1] = (1-frac_x)*( frac_y)*( frac_z);
interpWeights[2] = ( frac_x)*(1-frac_y)*( frac_z);
interpWeights[3] = ( frac_x)*( frac_y)*(1-frac_z);
interpWeights[4] = (1-frac_x)*(1-frac_y)*( frac_z);
interpWeights[5] = ( frac_x)*(1-frac_y)*(1-frac_z);
interpWeights[6] = (1-frac_x)*( frac_y)*(1-frac_z);
interpWeights[7] = (1-frac_x)*(1-frac_y)*(1-frac_z);
dir = GetMatchingDirection(idx, oldDir, image_num) * interpWeights[0];
if (image_num>=0)
tensor += m_TensorImages[image_num]->GetPixel(idx) * m_EmaxImage[image_num]->GetPixel(idx) * interpWeights[0];
itk::Index<3> tmpIdx = idx; tmpIdx[0]++;
dir += GetMatchingDirection(tmpIdx, oldDir, image_num) * interpWeights[1];
if (image_num>=0)
tensor += m_TensorImages[image_num]->GetPixel(tmpIdx) * m_EmaxImage[image_num]->GetPixel(tmpIdx) * interpWeights[1];
tmpIdx = idx; tmpIdx[1]++;
dir += GetMatchingDirection(tmpIdx, oldDir, image_num) * interpWeights[2];
if (image_num>=0)
tensor += m_TensorImages[image_num]->GetPixel(tmpIdx) * m_EmaxImage[image_num]->GetPixel(tmpIdx) * interpWeights[2];
tmpIdx = idx; tmpIdx[2]++;
dir += GetMatchingDirection(tmpIdx, oldDir, image_num) * interpWeights[3];
if (image_num>=0)
tensor += m_TensorImages[image_num]->GetPixel(tmpIdx) * m_EmaxImage[image_num]->GetPixel(tmpIdx) * interpWeights[3];
tmpIdx = idx; tmpIdx[0]++; tmpIdx[1]++;
dir += GetMatchingDirection(tmpIdx, oldDir, image_num) * interpWeights[4];
if (image_num>=0)
tensor += m_TensorImages[image_num]->GetPixel(tmpIdx) * m_EmaxImage[image_num]->GetPixel(tmpIdx) * interpWeights[4];
tmpIdx = idx; tmpIdx[1]++; tmpIdx[2]++;
dir += GetMatchingDirection(tmpIdx, oldDir, image_num) * interpWeights[5];
if (image_num>=0)
tensor += m_TensorImages[image_num]->GetPixel(tmpIdx) * m_EmaxImage[image_num]->GetPixel(tmpIdx) * interpWeights[5];
tmpIdx = idx; tmpIdx[2]++; tmpIdx[0]++;
dir += GetMatchingDirection(tmpIdx, oldDir, image_num) * interpWeights[6];
if (image_num>=0)
tensor += m_TensorImages[image_num]->GetPixel(tmpIdx) * m_EmaxImage[image_num]->GetPixel(tmpIdx) * interpWeights[6];
tmpIdx = idx; tmpIdx[0]++; tmpIdx[1]++; tmpIdx[2]++;
dir += GetMatchingDirection(tmpIdx, oldDir, image_num) * interpWeights[7];
if (image_num>=0)
tensor += m_TensorImages[image_num]->GetPixel(tmpIdx) * m_EmaxImage[image_num]->GetPixel(tmpIdx) * interpWeights[7];
}
}
return dir;
}
vnl_vector_fixed<float,3> TrackingHandlerTensor::GetLargestEigenvector(TensorType& tensor)
{
vnl_vector_fixed<float,3> dir;
TensorType::EigenValuesArrayType eigenvalues;
TensorType::EigenVectorsMatrixType eigenvectors;
tensor.ComputeEigenAnalysis(eigenvalues, eigenvectors);
dir[0] = eigenvectors(2, 0);
dir[1] = eigenvectors(2, 1);
dir[2] = eigenvectors(2, 2);
if (dir.magnitude()<mitk::eps)
dir.fill(0.0);
return dir;
}
vnl_vector_fixed<float,3> TrackingHandlerTensor::ProposeDirection(const itk::Point<float, 3>& pos, std::deque<vnl_vector_fixed<float, 3> >& olddirs, itk::Index<3>& oldIndex)
{
vnl_vector_fixed<float,3> output_direction; output_direction.fill(0);
TensorType tensor; tensor.Fill(0);
try
{
itk::Index<3> index;
m_TensorImages.at(0)->TransformPhysicalPointToIndex(pos, index);
float fa = mitk::imv::GetImageValue<float>(pos, m_Parameters->m_InterpolateTractographyData, m_FaInterpolator);
if (fa<m_Parameters->m_Cutoff)
return output_direction;
vnl_vector_fixed<float,3> oldDir; oldDir.fill(0.0);
if (!olddirs.empty())
oldDir = olddirs.back();
if (m_Parameters->m_FlipX)
oldDir[0] *= -1;
if (m_Parameters->m_FlipY)
oldDir[1] *= -1;
if (m_Parameters->m_FlipZ)
oldDir[2] *= -1;
float old_mag = oldDir.magnitude();
if (!m_Parameters->m_InterpolateTractographyData && oldIndex==index)
return oldDir;
output_direction = GetDirection(pos, oldDir, tensor);
float mag = output_direction.magnitude();
if (mag>=mitk::eps)
{
output_direction.normalize();
if (old_mag>0.5 && m_Parameters->m_G>mitk::eps) // TEND tracking
{
output_direction[0] = m_Parameters->m_F*output_direction[0] + (1-m_Parameters->m_F)*( (1-m_Parameters->m_G)*oldDir[0] + m_Parameters->m_G*(tensor[0]*oldDir[0] + tensor[1]*oldDir[1] + tensor[2]*oldDir[2]));
output_direction[1] = m_Parameters->m_F*output_direction[1] + (1-m_Parameters->m_F)*( (1-m_Parameters->m_G)*oldDir[1] + m_Parameters->m_G*(tensor[1]*oldDir[0] + tensor[3]*oldDir[1] + tensor[4]*oldDir[2]));
output_direction[2] = m_Parameters->m_F*output_direction[2] + (1-m_Parameters->m_F)*( (1-m_Parameters->m_G)*oldDir[2] + m_Parameters->m_G*(tensor[2]*oldDir[0] + tensor[4]*oldDir[1] + tensor[5]*oldDir[2]));
output_direction.normalize();
}
float a = 1;
if (old_mag>0.5)
a = dot_product(output_direction, oldDir);
if (a>=m_Parameters->GetAngularThresholdDot())
output_direction *= mag;
else
output_direction.fill(0);
}
else
output_direction.fill(0);
}
catch(...)
{
}
if (m_Parameters->m_FlipX)
output_direction[0] *= -1;
if (m_Parameters->m_FlipY)
output_direction[1] *= -1;
if (m_Parameters->m_FlipZ)
output_direction[2] *= -1;
if (m_Parameters->m_ApplyDirectionMatrix)
output_direction = m_FloatImageRotation*output_direction;
return output_direction;
}
}
diff --git a/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerTensor.h b/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerTensor.h
index 309bee5..f8567fb 100644
--- a/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerTensor.h
+++ b/Modules/FiberTracking/Algorithms/TrackingHandlers/mitkTrackingHandlerTensor.h
@@ -1,80 +1,80 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _TrackingHandlerTensor
#define _TrackingHandlerTensor
#include "mitkTrackingDataHandler.h"
#include <itkDiffusionTensor3D.h>
#include <MitkFiberTrackingExports.h>
#include <mitkTensorImage.h>
#include <itkLinearInterpolateImageFunction.h>
namespace mitk
{
/**
* \brief Enables streamline tracking on tensor images. Supports multi tensor tracking by adding multiple tensor images. */
class MITKFIBERTRACKING_EXPORT TrackingHandlerTensor : public TrackingDataHandler
{
public:
TrackingHandlerTensor();
~TrackingHandlerTensor() override;
typedef TensorImage::PixelType TensorType;
typedef TensorImage::ItkTensorImageType ItkTensorImageType;
typedef itk::Image< vnl_vector_fixed<float,3>, 3> ItkPDImgType;
void InitForTracking() override; ///< calls InputDataValidForTracking() and creates feature images
vnl_vector_fixed<float,3> ProposeDirection(const itk::Point<float, 3>& pos, std::deque< vnl_vector_fixed<float,3> >& olddirs, itk::Index<3>& oldIndex) override; ///< predicts next progression direction at the given position
bool WorldToIndex(itk::Point<float, 3>& pos, itk::Index<3>& index) override;
void AddTensorImage( ItkTensorImageType::ConstPointer img ){ m_TensorImages.push_back(img); DataModified(); }
void SetTensorImage( ItkTensorImageType::ConstPointer img ){ m_TensorImages.clear(); m_TensorImages.push_back(img); DataModified(); }
void ClearTensorImages(){ m_TensorImages.clear(); DataModified(); }
void SetFaImage( ItkFloatImgType::Pointer img ){ m_FaImage = img; DataModified(); }
void SetInterpolateTensors( bool interpolateTensors ){ m_InterpolateTensors = interpolateTensors; }
int GetNumTensorImages() const { return m_TensorImages.size(); }
ItkUcharImgType::SpacingType GetSpacing() override{ return m_FaImage->GetSpacing(); }
itk::Point<float,3> GetOrigin() override{ return m_FaImage->GetOrigin(); }
ItkUcharImgType::DirectionType GetDirection() override{ return m_FaImage->GetDirection(); }
ItkUcharImgType::RegionType GetLargestPossibleRegion() override{ return m_FaImage->GetLargestPossibleRegion(); }
protected:
vnl_vector_fixed<float,3> GetMatchingDirection(itk::Index<3> idx, vnl_vector_fixed<float,3>& oldDir, int& image_num);
vnl_vector_fixed<float,3> GetDirection(itk::Point<float, 3> itkP, vnl_vector_fixed<float,3> oldDir, TensorType& tensor);
vnl_vector_fixed<float,3> GetLargestEigenvector(TensorType& tensor);
std::vector< ItkDoubleImgType::Pointer > m_EmaxImage; ///< Stores largest eigenvalues per voxel (one for each tensor)
ItkFloatImgType::Pointer m_FaImage; ///< FA image used to determine streamline termination.
std::vector< ItkPDImgType::Pointer > m_PdImage; ///< Stores principal direction of each tensor in each voxel.
std::vector< ItkTensorImageType::ConstPointer > m_TensorImages; ///< Input tensor images. For multi tensor tracking provide multiple tensor images.
bool m_InterpolateTensors; ///< If false, then the peaks are interpolated. Otherwiese, The tensors are interpolated.
int m_NumberOfInputs;
itk::LinearInterpolateImageFunction< itk::Image< float, 3 >, float >::Pointer m_FaInterpolator;
};
}
#endif
diff --git a/Modules/FiberTracking/Algorithms/itkEvaluateDirectionImagesFilter.cpp b/Modules/FiberTracking/Algorithms/itkEvaluateDirectionImagesFilter.cpp
index 3525a98..3500735 100644
--- a/Modules/FiberTracking/Algorithms/itkEvaluateDirectionImagesFilter.cpp
+++ b/Modules/FiberTracking/Algorithms/itkEvaluateDirectionImagesFilter.cpp
@@ -1,332 +1,332 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkEvaluateDirectionImagesFilter_cpp
#define __itkEvaluateDirectionImagesFilter_cpp
#include "itkEvaluateDirectionImagesFilter.h"
#include <itkImageRegionConstIterator.h>
#include <itkImageRegionIterator.h>
#include <itkImageDuplicator.h>
#include <boost/progress.hpp>
namespace itk {
template< class PixelType >
ComparePeakImagesFilter< PixelType >
::ComparePeakImagesFilter():
m_IgnoreMissingRefDirections(false),
m_IgnoreMissingTestDirections(false),
m_Eps(0.0001)
{
this->SetNumberOfIndexedOutputs(2);
}
template< class PixelType >
void ComparePeakImagesFilter< PixelType >::GenerateData()
{
if (m_TestImage.IsNull() || m_ReferenceImage.IsNull())
mitkThrow() << "Test or reference image not set!";
// if (m_TestImage->GetLargestPossibleRegion().GetSize()!=m_ReferenceImage->GetLargestPossibleRegion().GetSize())
// mitkThrow() << "Test and reference image need to have same sizes!";
Vector<float, 4> spacing4 = m_TestImage->GetSpacing();
Point<float, 4> origin4 = m_TestImage->GetOrigin();
Matrix<double, 4, 4> direction4 = m_TestImage->GetDirection();
ImageRegion<4> imageRegion4 = m_TestImage->GetLargestPossibleRegion();
Vector<double, 3> spacing3;
Point<float, 3> origin3;
Matrix<double, 3, 3> direction3;
ImageRegion<3> imageRegion3;
spacing3[0] = spacing4[0]; spacing3[1] = spacing4[1]; spacing3[2] = spacing4[2];
origin3[0] = origin4[0]; origin3[1] = origin4[1]; origin3[2] = origin4[2];
for (int r=0; r<3; r++)
for (int c=0; c<3; c++)
direction3[r][c] = direction4[r][c];
imageRegion3.SetSize(0, imageRegion4.GetSize()[0]);
imageRegion3.SetSize(1, imageRegion4.GetSize()[1]);
imageRegion3.SetSize(2, imageRegion4.GetSize()[2]);
// angular error image
typename OutputImageType::Pointer outputImage = OutputImageType::New();
outputImage->SetOrigin( origin3 );
outputImage->SetRegions( imageRegion3 );
outputImage->SetSpacing( spacing3 );
outputImage->SetDirection( direction3 );
outputImage->Allocate();
outputImage->FillBuffer(0.0);
this->SetNthOutput(0, outputImage);
// length error image
outputImage = OutputImageType::New();
outputImage->SetOrigin( origin3 );
outputImage->SetRegions( imageRegion3 );
outputImage->SetSpacing( spacing3 );
outputImage->SetDirection( direction3 );
outputImage->Allocate();
outputImage->FillBuffer(0.0);
this->SetNthOutput(1, outputImage);
if (m_MaskImage.IsNull())
{
m_MaskImage = UCharImageType::New();
m_MaskImage->SetOrigin( origin3 );
m_MaskImage->SetRegions( imageRegion3 );
m_MaskImage->SetSpacing( spacing3 );
m_MaskImage->SetDirection( direction3 );
m_MaskImage->Allocate();
m_MaskImage->FillBuffer(1);
}
m_MeanAngularError = 0.0;
m_MedianAngularError = 0;
m_MaxAngularError = 0.0;
m_MinAngularError = itk::NumericTraits<float>::max();
m_VarAngularError = 0.0;
m_AngularErrorVector.clear();
m_MeanLengthError = 0.0;
m_MedianLengthError = 0;
m_MaxLengthError = 0.0;
m_MinLengthError = itk::NumericTraits<float>::max();
m_VarLengthError = 0.0;
m_LengthErrorVector.clear();
outputImage = static_cast< OutputImageType* >(this->ProcessObject::GetOutput(0));
typename OutputImageType::Pointer outputImage2 = static_cast< OutputImageType* >(this->ProcessObject::GetOutput(1));
ImageRegionIterator< OutputImageType > oit(outputImage, outputImage->GetLargestPossibleRegion());
ImageRegionIterator< OutputImageType > oit2(outputImage2, outputImage2->GetLargestPossibleRegion());
ImageRegionIterator< UCharImageType > mit(m_MaskImage, m_MaskImage->GetLargestPossibleRegion());
boost::progress_display disp(outputImage->GetLargestPossibleRegion().GetSize()[0]*outputImage->GetLargestPossibleRegion().GetSize()[1]*outputImage->GetLargestPossibleRegion().GetSize()[2]);
while( !oit.IsAtEnd() )
{
++disp;
if( mit.Get()!=1 )
{
++oit;
++oit2;
++mit;
continue;
}
typename OutputImageType::IndexType index = oit.GetIndex();
itk::Index<4> idx4;
idx4[0] = index[0];
idx4[1] = index[1];
idx4[2] = index[2];
std::vector< PixelType > ref_magnitudes;
std::vector< PeakType > ref_peaks;
for (unsigned int i=0; i<m_ReferenceImage->GetLargestPossibleRegion().GetSize()[3]/3; i++)
{
PeakType ref_peak;
idx4[3] = i*3;
ref_peak[0] = m_ReferenceImage->GetPixel(idx4);
idx4[3] = i*3 + 1;
ref_peak[1] = m_ReferenceImage->GetPixel(idx4);
idx4[3] = i*3 + 2;
ref_peak[2] = m_ReferenceImage->GetPixel(idx4);
PixelType ref_mag = ref_peak.magnitude();
if (ref_mag > m_Eps )
{
ref_peak.normalize();
ref_peaks.push_back(ref_peak);
ref_magnitudes.push_back(ref_mag);
}
}
std::vector< PixelType > test_magnitudes;
std::vector< PeakType > test_peaks;
for (unsigned int j=0; j<m_TestImage->GetLargestPossibleRegion().GetSize()[3]/3; j++)
{
PeakType test_peak;
idx4[3] = j*3;
test_peak[0] = m_TestImage->GetPixel(idx4);
idx4[3] = j*3 + 1;
test_peak[1] = m_TestImage->GetPixel(idx4);
idx4[3] = j*3 + 2;
test_peak[2] = m_TestImage->GetPixel(idx4);
PixelType test_mag = test_peak.magnitude();
if (test_mag > m_Eps )
{
test_peak.normalize();
test_peaks.push_back(test_peak);
test_magnitudes.push_back(test_mag);
}
}
if (test_peaks.empty() && ref_peaks.empty())
{
++oit;
++oit2;
++mit;
continue;
}
else if (test_peaks.empty())
{
if (!m_IgnoreMissingTestDirections)
{
PixelType length_sum = 0;
for (auto l : ref_magnitudes)
{
length_sum += l;
m_AngularErrorVector.push_back(90);
m_LengthErrorVector.push_back(l);
m_MeanAngularError += m_AngularErrorVector.back();
m_MeanLengthError += m_LengthErrorVector.back();
}
oit2.Set(length_sum/ref_magnitudes.size());
oit.Set(90);
}
}
else if (ref_peaks.empty())
{
if (!m_IgnoreMissingRefDirections)
{
PixelType length_sum = 0;
for (auto l : test_magnitudes)
{
length_sum += l;
m_AngularErrorVector.push_back(90);
m_LengthErrorVector.push_back(length_sum);
m_MeanAngularError += m_AngularErrorVector.back();
m_MeanLengthError += m_LengthErrorVector.back();
}
oit2.Set(length_sum/test_magnitudes.size());
oit.Set(90);
}
}
else
{
PixelType error_a = 0;
PixelType error_l = 0;
for (unsigned int i=0; i<ref_peaks.size(); ++i)
{
PixelType max_a = 0;
PixelType max_l = 0;
for (unsigned int j=0; j<test_peaks.size(); ++j)
{
auto a = fabs(dot_product(test_peaks[j], ref_peaks[i]));
if (a>1.0)
a = 1.0;
if (a>max_a)
{
max_a = a;
max_l = fabs(ref_magnitudes[i]-test_magnitudes[j]);
}
}
m_LengthErrorVector.push_back( max_l );
m_AngularErrorVector.push_back( acos(max_a)*180.0/itk::Math::pi );
m_MeanAngularError += m_AngularErrorVector.back();
m_MeanLengthError += m_LengthErrorVector.back();
error_a += m_AngularErrorVector.back();
error_l += m_LengthErrorVector.back();
}
for (unsigned int i=0; i<test_peaks.size(); ++i)
{
PixelType max_a = 0;
PixelType max_l = 0;
for (unsigned int j=0; j<ref_peaks.size(); ++j)
{
auto a = fabs(dot_product(test_peaks[i], ref_peaks[j]));
if (a>1.0)
a = 1.0;
if (a>max_a)
{
max_a = a;
max_l = fabs(ref_magnitudes[j]-test_magnitudes[i]);
}
}
m_LengthErrorVector.push_back( max_l );
m_AngularErrorVector.push_back( acos(max_a)*180.0/itk::Math::pi );
m_MeanAngularError += m_AngularErrorVector.back();
m_MeanLengthError += m_LengthErrorVector.back();
error_a += m_AngularErrorVector.back();
error_l += m_LengthErrorVector.back();
}
error_a /= (test_peaks.size() + ref_peaks.size());
error_l /= (test_peaks.size() + ref_peaks.size());
oit2.Set(error_l);
oit.Set(error_a);
}
++oit;
++oit2;
++mit;
}
std::sort( m_AngularErrorVector.begin(), m_AngularErrorVector.end() );
if (!m_AngularErrorVector.empty())
m_MeanAngularError /= m_AngularErrorVector.size(); // mean
for (unsigned int i=0; i<m_AngularErrorVector.size(); i++)
{
float temp = m_AngularErrorVector.at(i) - m_MeanAngularError;
m_VarAngularError += temp*temp;
if ( m_AngularErrorVector.at(i)>m_MaxAngularError )
m_MaxAngularError = m_AngularErrorVector.at(i);
if ( m_AngularErrorVector.at(i)<m_MinAngularError )
m_MinAngularError = m_AngularErrorVector.at(i);
}
if (m_AngularErrorVector.size()>1)
{
m_VarAngularError /= (m_AngularErrorVector.size()-1); // variance
// median
if (m_AngularErrorVector.size()%2 == 0)
m_MedianAngularError = 0.5*( m_AngularErrorVector.at( m_AngularErrorVector.size()/2 ) + m_AngularErrorVector.at( m_AngularErrorVector.size()/2+1 ) );
else
m_MedianAngularError = m_AngularErrorVector.at( (m_AngularErrorVector.size()+1)/2 ) ;
}
std::sort( m_LengthErrorVector.begin(), m_LengthErrorVector.end() );
m_MeanLengthError /= m_LengthErrorVector.size(); // mean
for (unsigned int i=0; i<m_LengthErrorVector.size(); i++)
{
float temp = m_LengthErrorVector.at(i) - m_MeanLengthError;
m_VarLengthError += temp*temp;
if ( m_LengthErrorVector.at(i)>m_MaxLengthError )
m_MaxLengthError = m_LengthErrorVector.at(i);
if ( m_LengthErrorVector.at(i)<m_MinLengthError )
m_MinLengthError = m_LengthErrorVector.at(i);
}
if (m_LengthErrorVector.size()>1)
{
m_VarLengthError /= (m_LengthErrorVector.size()-1); // variance
// median
if (m_LengthErrorVector.size()%2 == 0)
m_MedianLengthError = 0.5*( m_LengthErrorVector.at( m_LengthErrorVector.size()/2 ) + m_LengthErrorVector.at( m_LengthErrorVector.size()/2+1 ) );
else
m_MedianLengthError = m_LengthErrorVector.at( (m_LengthErrorVector.size()+1)/2 ) ;
}
}
}
#endif // __itkEvaluateDirectionImagesFilter_cpp
diff --git a/Modules/FiberTracking/Algorithms/itkEvaluateDirectionImagesFilter.h b/Modules/FiberTracking/Algorithms/itkEvaluateDirectionImagesFilter.h
index 6e6ae6d..41f39b9 100644
--- a/Modules/FiberTracking/Algorithms/itkEvaluateDirectionImagesFilter.h
+++ b/Modules/FiberTracking/Algorithms/itkEvaluateDirectionImagesFilter.h
@@ -1,115 +1,115 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*===================================================================
This file is based heavily on a corresponding ITK filter.
===================================================================*/
#ifndef __itkEvaluateDirectionImagesFilter_h_
#define __itkEvaluateDirectionImagesFilter_h_
#include <itkProcessObject.h>
#include <itkVectorContainer.h>
#include <itkImageSource.h>
#include <mitkPeakImage.h>
namespace itk{
/** \brief Evaluates the voxel-wise angular error between two sets of peak images.
*/
template< class PixelType >
class ComparePeakImagesFilter : public ImageSource< Image< PixelType, 3 > >
{
public:
typedef ComparePeakImagesFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageSource< Image< PixelType, 3 > > Superclass;
typedef typename Superclass::OutputImageRegionType OutputImageRegionType;
typedef typename Superclass::OutputImageType OutputImageType;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(EvaluateDirectionImagesFilter, ImageToImageFilter)
typedef Image< float, 3 > FloatImageType;
typedef Image< bool, 3 > BoolImageType;
typedef Image< unsigned char, 3 > UCharImageType;
typedef mitk::PeakImage::ItkPeakImageType PeakImageType;
typedef vnl_vector_fixed< PixelType, 3 > PeakType;
itkSetMacro( TestImage , PeakImageType::Pointer)
itkSetMacro( ReferenceImage , PeakImageType::Pointer)
itkSetMacro( MaskImage , UCharImageType::Pointer) ///< Calculation is only performed inside of the mask image.
itkSetMacro( IgnoreMissingTestDirections , bool)
itkSetMacro( IgnoreMissingRefDirections , bool)
/** Output statistics of the measured angular errors. */
itkGetMacro( MeanAngularError, float)
itkGetMacro( MinAngularError, float)
itkGetMacro( MaxAngularError, float)
itkGetMacro( VarAngularError, float)
itkGetMacro( MedianAngularError, float)
/** Output statistics of the measured peak length errors. */
itkGetMacro( MeanLengthError, float)
itkGetMacro( MinLengthError, float)
itkGetMacro( MaxLengthError, float)
itkGetMacro( VarLengthError, float)
itkGetMacro( MedianLengthError, float)
protected:
ComparePeakImagesFilter();
~ComparePeakImagesFilter() override {}
void GenerateData() override;
UCharImageType::Pointer m_MaskImage;
PeakImageType::Pointer m_TestImage;
PeakImageType::Pointer m_ReferenceImage;
bool m_IgnoreMissingRefDirections;
bool m_IgnoreMissingTestDirections;
double m_MeanAngularError;
double m_MedianAngularError;
double m_MaxAngularError;
double m_MinAngularError;
double m_VarAngularError;
std::vector< double > m_AngularErrorVector;
double m_MeanLengthError;
double m_MedianLengthError;
double m_MaxLengthError;
double m_MinLengthError;
double m_VarLengthError;
std::vector< double > m_LengthErrorVector;
double m_Eps;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkEvaluateDirectionImagesFilter.cpp"
#endif
#endif //__itkEvaluateDirectionImagesFilter_h_
diff --git a/Modules/FiberTracking/Algorithms/itkEvaluateTractogramDirectionsFilter.cpp b/Modules/FiberTracking/Algorithms/itkEvaluateTractogramDirectionsFilter.cpp
index c9fd68f..097efe8 100644
--- a/Modules/FiberTracking/Algorithms/itkEvaluateTractogramDirectionsFilter.cpp
+++ b/Modules/FiberTracking/Algorithms/itkEvaluateTractogramDirectionsFilter.cpp
@@ -1,339 +1,339 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkEvaluateTractogramDirectionsFilter_cpp
#define __itkEvaluateTractogramDirectionsFilter_cpp
#include "itkEvaluateTractogramDirectionsFilter.h"
#include <itkImageRegionConstIterator.h>
#include <itkImageRegionIterator.h>
#include <itkImageDuplicator.h>
#include <boost/progress.hpp>
#include <mitkDiffusionFunctionCollection.h>
namespace itk {
template< class PixelType >
EvaluateTractogramDirectionsFilter< PixelType >
::EvaluateTractogramDirectionsFilter():
m_ReferenceImageSet(nullptr),
m_IgnoreMissingDirections(false),
m_Eps(0.0001),
m_UseInterpolation(false)
{
this->SetNumberOfOutputs(1);
}
template< class PixelType >
itk::Vector<PixelType, 3> EvaluateTractogramDirectionsFilter< PixelType >::GetItkVector(double point[3])
{
itk::Vector<PixelType, 3> itkVector;
itkVector[0] = point[0];
itkVector[1] = point[1];
itkVector[2] = point[2];
return itkVector;
}
template< class PixelType >
vnl_vector_fixed<PixelType, 3> EvaluateTractogramDirectionsFilter< PixelType >::GetVnlVector(double point[3])
{
vnl_vector_fixed<PixelType, 3> vnlVector;
vnlVector[0] = point[0];
vnlVector[1] = point[1];
vnlVector[2] = point[2];
return vnlVector;
}
template< class PixelType >
vnl_vector_fixed<PixelType, 3> EvaluateTractogramDirectionsFilter< PixelType >::GetVnlVector(Vector<PixelType,3>& vector)
{
vnl_vector_fixed<PixelType, 3> vnlVector;
vnlVector[0] = vector[0];
vnlVector[1] = vector[1];
vnlVector[2] = vector[2];
return vnlVector;
}
template< class PixelType >
void EvaluateTractogramDirectionsFilter< PixelType >::GenerateData()
{
if (m_Tractogram.IsNull() || m_ReferenceImageSet.IsNull())
return;
if (m_UseInterpolation)
MITK_INFO << "Using trilinear interpolation";
else
MITK_INFO << "Using nearest neighbor interpolation";
if (m_IgnoreMissingDirections)
MITK_INFO << "Ignoring missing directions";
else
MITK_INFO << "Penalizing missing directions";
// angular error image
typename OutputImageType::Pointer outputImage = OutputImageType::New();
outputImage->SetOrigin( m_ReferenceImageSet->GetElement(0)->GetOrigin() );
outputImage->SetRegions( m_ReferenceImageSet->GetElement(0)->GetLargestPossibleRegion() );
outputImage->SetSpacing( m_ReferenceImageSet->GetElement(0)->GetSpacing() );
outputImage->SetDirection( m_ReferenceImageSet->GetElement(0)->GetDirection() );
outputImage->Allocate();
outputImage->FillBuffer(0.0);
DoubleImageType::Pointer counterImage = DoubleImageType::New();
counterImage->SetOrigin( m_ReferenceImageSet->GetElement(0)->GetOrigin() );
counterImage->SetRegions( m_ReferenceImageSet->GetElement(0)->GetLargestPossibleRegion() );
counterImage->SetSpacing( m_ReferenceImageSet->GetElement(0)->GetSpacing() );
counterImage->SetDirection( m_ReferenceImageSet->GetElement(0)->GetDirection() );
counterImage->Allocate();
counterImage->FillBuffer(0.0);
std::vector< DoubleImageType::Pointer > directionFound;
for (int i=0; i<m_ReferenceImageSet->Size(); i++)
{
DoubleImageType::Pointer check = DoubleImageType::New();
check->SetOrigin( m_ReferenceImageSet->GetElement(0)->GetOrigin() );
check->SetRegions( m_ReferenceImageSet->GetElement(0)->GetLargestPossibleRegion() );
check->SetSpacing( m_ReferenceImageSet->GetElement(0)->GetSpacing() );
check->SetDirection( m_ReferenceImageSet->GetElement(0)->GetDirection() );
check->Allocate();
check->FillBuffer(90);
directionFound.push_back(check);
}
if (m_MaskImage.IsNull())
{
m_MaskImage = UCharImageType::New();
m_MaskImage->SetOrigin( outputImage->GetOrigin() );
m_MaskImage->SetRegions( outputImage->GetLargestPossibleRegion() );
m_MaskImage->SetSpacing( outputImage->GetSpacing() );
m_MaskImage->SetDirection( outputImage->GetDirection() );
m_MaskImage->Allocate();
m_MaskImage->FillBuffer(1);
}
m_MeanAngularError = 0.0;
m_MedianAngularError = 0;
m_MaxAngularError = 0.0;
m_MinAngularError = itk::NumericTraits<float>::max();
m_VarAngularError = 0.0;
m_AngularErrorVector.clear();
float minSpacing = 1;
if(outputImage->GetSpacing()[0]<outputImage->GetSpacing()[1] && outputImage->GetSpacing()[0]<outputImage->GetSpacing()[2])
minSpacing = outputImage->GetSpacing()[0];
else if (outputImage->GetSpacing()[1] < outputImage->GetSpacing()[2])
minSpacing = outputImage->GetSpacing()[1];
else
minSpacing = outputImage->GetSpacing()[2];
FiberBundleType::Pointer fiberBundle = m_Tractogram->GetDeepCopy();
fiberBundle->ResampleFibers(minSpacing/10);
MITK_INFO << "Evaluating tractogram";
vtkSmartPointer<vtkPolyData> fiberPolyData = fiberBundle->GetFiberPolyData();
boost::progress_display disp( fiberBundle->GetNumFibers() );
for( int i=0; i<fiberBundle->GetNumFibers(); i++ )
{
vtkCell* cell = fiberPolyData->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
if (numPoints<2)
continue;
for( int j=0; j<numPoints; j++)
{
double* temp = points->GetPoint(j);
itk::Point<PixelType, 3> vertex = mitk::imv::GetItkPoint<PixelType>(temp);
itk::Vector<PixelType> v = GetItkVector(temp);
itk::Vector<PixelType, 3> dir(3);
if (j<numPoints-1)
dir = GetItkVector(points->GetPoint(j+1))-v;
else
dir = v-GetItkVector(points->GetPoint(j-1));
vnl_vector_fixed< PixelType, 3 > fiberDir = GetVnlVector(dir);
fiberDir.normalize();
itk::Index<3> idx;
itk::ContinuousIndex<float, 3> contIndex;
m_MaskImage->TransformPhysicalPointToIndex(vertex, idx);
m_MaskImage->TransformPhysicalPointToContinuousIndex(vertex, contIndex);
if (!m_UseInterpolation) // use nearest neighbour interpolation
{
if (!m_MaskImage->GetLargestPossibleRegion().IsInside(idx) || m_MaskImage->GetPixel(idx)<=0)
continue;
double angle = 90;
int usedIndex = -1;
for (int k=0; k<m_ReferenceImageSet->Size(); k++) // and each test direction
{
vnl_vector_fixed< PixelType, 3 > refDir = m_ReferenceImageSet->GetElement(k)->GetPixel(idx).GetVnlVector();
if (refDir.magnitude()>m_Eps) // normalize if not null
refDir.normalize();
else
continue;
// calculate angle between directions
double tempAngle = acos(fabs(dot_product(refDir, fiberDir)))*180.0/itk::Math::pi;
directionFound.at(k)->SetPixel(idx, tempAngle);
if (tempAngle < angle)
{
angle = tempAngle;
usedIndex = k;
}
}
if (usedIndex>=0)
directionFound.at(usedIndex)->SetPixel(idx, -1);
else if (m_IgnoreMissingDirections)
angle = 0;
counterImage->SetPixel(idx, counterImage->GetPixel(idx)+1);
outputImage->SetPixel(idx, outputImage->GetPixel(idx)+angle);
continue;
}
double frac_x = contIndex[0] - idx[0];
double frac_y = contIndex[1] - idx[1];
double frac_z = contIndex[2] - idx[2];
if (frac_x<0)
{
idx[0] -= 1;
frac_x += 1;
}
if (frac_y<0)
{
idx[1] -= 1;
frac_y += 1;
}
if (frac_z<0)
{
idx[2] -= 1;
frac_z += 1;
}
// use trilinear interpolation
itk::Index<3> newIdx;
for (int x=0; x<2; x++)
{
frac_x = 1-frac_x;
for (int y=0; y<2; y++)
{
frac_y = 1-frac_y;
for (int z=0; z<2; z++)
{
frac_z = 1-frac_z;
newIdx[0] = idx[0]+x;
newIdx[1] = idx[1]+y;
newIdx[2] = idx[2]+z;
double frac = frac_x*frac_y*frac_z;
// is position valid?
if (!m_MaskImage->GetLargestPossibleRegion().IsInside(newIdx) || m_MaskImage->GetPixel(newIdx)<=0)
continue;
double angle = 90;
int usedIndex = -1;
for (int k=0; k<m_ReferenceImageSet->Size(); k++) // and each test direction
{
vnl_vector_fixed< PixelType, 3 > refDir = m_ReferenceImageSet->GetElement(k)->GetPixel(newIdx).GetVnlVector();
if (refDir.magnitude()>m_Eps) // normalize if not null
refDir.normalize();
else
continue;
// calculate angle between directions
double tempAngle = acos(fabs(dot_product(refDir, fiberDir)))*180.0/itk::Math::pi;
directionFound.at(k)->SetPixel(newIdx, tempAngle);
if (tempAngle < angle)
{
angle = tempAngle;
usedIndex = k;
}
}
if (usedIndex>=0)
directionFound.at(usedIndex)->SetPixel(newIdx, -1);
else if (m_IgnoreMissingDirections)
angle = 0;
counterImage->SetPixel(newIdx, counterImage->GetPixel(newIdx)+1);
outputImage->SetPixel(newIdx, outputImage->GetPixel(newIdx)+frac*angle);
}
}
}
}
++disp;
}
ImageRegionIterator< OutputImageType > oit(outputImage, outputImage->GetLargestPossibleRegion());
ImageRegionIterator< UCharImageType > mit(m_MaskImage, m_MaskImage->GetLargestPossibleRegion());
ImageRegionIterator< DoubleImageType > cit(counterImage, counterImage->GetLargestPossibleRegion());
if (!m_IgnoreMissingDirections)
MITK_INFO << "Creatings statistics and accounting for missing directions";
else
MITK_INFO << "Creatings statistics";
boost::progress_display disp2(outputImage->GetLargestPossibleRegion().GetNumberOfPixels());
while( !oit.IsAtEnd() )
{
if ( mit.Get()>0)
{
if ( cit.Get()>m_Eps )
oit.Set(oit.Get()/cit.Get());
if (!m_IgnoreMissingDirections)
{
int missingCount = 0;
if ( cit.Get()>m_Eps )
missingCount++;
for (int i=0; i<directionFound.size(); i++)
{
if ( directionFound.at(i)->GetPixel(oit.GetIndex())>0 && m_ReferenceImageSet->GetElement(i)->GetPixel(oit.GetIndex()).GetVnlVector().magnitude()>m_Eps )
{
oit.Set(oit.Get()+directionFound.at(i)->GetPixel(oit.GetIndex()));
missingCount++;
}
}
if (missingCount>1)
oit.Set(oit.Get()/missingCount);
}
if (oit.Get()>m_MaxAngularError)
m_MaxAngularError = oit.Get();
if (oit.Get()<m_MinAngularError)
m_MinAngularError = oit.Get();
}
++oit;
++cit;
++mit;
++disp2;
}
this->SetNthOutput(0, outputImage);
}
}
#endif // __itkEvaluateTractogramDirectionsFilter_cpp
diff --git a/Modules/FiberTracking/Algorithms/itkEvaluateTractogramDirectionsFilter.h b/Modules/FiberTracking/Algorithms/itkEvaluateTractogramDirectionsFilter.h
index bf06166..699891b 100644
--- a/Modules/FiberTracking/Algorithms/itkEvaluateTractogramDirectionsFilter.h
+++ b/Modules/FiberTracking/Algorithms/itkEvaluateTractogramDirectionsFilter.h
@@ -1,107 +1,107 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*===================================================================
This file is based heavily on a corresponding ITK filter.
===================================================================*/
#ifndef __itkEvaluateTractogramDirectionsFilter_h_
#define __itkEvaluateTractogramDirectionsFilter_h_
#include <itkProcessObject.h>
#include <itkVectorContainer.h>
#include <mitkFiberBundle.h>
#include <itkImageSource.h>
namespace itk{
/** \brief Calculates the voxel-wise angular error of the input tractogram to a set of voxel-wise directions.
*/
template< class PixelType >
class EvaluateTractogramDirectionsFilter : public ImageSource< Image< PixelType, 3 > >
{
public:
typedef EvaluateTractogramDirectionsFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageSource< Image< PixelType, 3 > > Superclass;
typedef typename Superclass::OutputImageRegionType OutputImageRegionType;
typedef typename Superclass::OutputImageType OutputImageType;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(EvaluateTractogramDirectionsFilter, ImageToImageFilter)
typedef mitk::FiberBundle FiberBundleType;
typedef Vector< float, 3 > DirectionType;
typedef Image< DirectionType, 3 > DirectionImageType;
typedef VectorContainer< int, DirectionImageType::Pointer > DirectionImageContainerType;
typedef Image< float, 3 > FloatImageType;
typedef Image< bool, 3 > BoolImageType;
typedef Image< unsigned char, 3 > UCharImageType;
typedef Image< double, 3 > DoubleImageType;
itkSetMacro( Tractogram, FiberBundleType::Pointer) ///< Input tractogram
itkSetMacro( ReferenceImageSet , DirectionImageContainerType::Pointer) ///< Input images containing one reference direction per voxel.
itkSetMacro( MaskImage , UCharImageType::Pointer) ///< Calculation is only performed inside of the mask image.
itkSetMacro( IgnoreMissingDirections , bool) ///< If in one voxel, the number of directions differs between the input tractogram and the reference, the excess directions are ignored. Otherwise, the error to the next closest direction is calculated.
itkSetMacro( UseInterpolation , bool) ///< Use trilinear interpolation.
/** Output statistics. */
itkGetMacro( MeanAngularError, float)
itkGetMacro( MinAngularError, float)
itkGetMacro( MaxAngularError, float)
itkGetMacro( VarAngularError, float)
itkGetMacro( MedianAngularError, float)
protected:
EvaluateTractogramDirectionsFilter();
~EvaluateTractogramDirectionsFilter() {}
void GenerateData();
itk::Vector<PixelType, 3> GetItkVector(double point[3]);
vnl_vector_fixed<PixelType, 3> GetVnlVector(double point[3]);
vnl_vector_fixed<PixelType, 3> GetVnlVector(Vector< PixelType, 3 >& vector);
UCharImageType::Pointer m_MaskImage;
DirectionImageContainerType::Pointer m_ReferenceImageSet;
bool m_IgnoreMissingDirections;
double m_MeanAngularError;
double m_MedianAngularError;
double m_MaxAngularError;
double m_MinAngularError;
double m_VarAngularError;
std::vector< double > m_AngularErrorVector;
double m_Eps;
FiberBundleType::Pointer m_Tractogram;
bool m_UseInterpolation;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkEvaluateTractogramDirectionsFilter.cpp"
#endif
#endif //__itkEvaluateTractogramDirectionsFilter_h_
diff --git a/Modules/FiberTracking/Algorithms/itkFiberCurvatureFilter.cpp b/Modules/FiberTracking/Algorithms/itkFiberCurvatureFilter.cpp
index 188e7a4..b5f7a86 100644
--- a/Modules/FiberTracking/Algorithms/itkFiberCurvatureFilter.cpp
+++ b/Modules/FiberTracking/Algorithms/itkFiberCurvatureFilter.cpp
@@ -1,167 +1,167 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "itkFiberCurvatureFilter.h"
#include <vtkDoubleArray.h>
#include <vtkPointData.h>
#include <boost/progress.hpp>
namespace itk{
FiberCurvatureFilter::FiberCurvatureFilter()
: m_AngularDeviation(30)
, m_Distance(10.0)
, m_RemoveFibers(false)
, m_UseMedian(false)
{
}
FiberCurvatureFilter::~FiberCurvatureFilter()
{
}
void FiberCurvatureFilter::GenerateData()
{
vtkSmartPointer<vtkPolyData> inputPoly = m_InputFiberBundle->GetFiberPolyData();
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
MITK_INFO << "Applying curvature threshold";
boost::progress_display disp(inputPoly->GetNumberOfCells());
#pragma omp parallel for
for (int i=0; i<inputPoly->GetNumberOfCells(); i++)
{
std::vector< vnl_vector_fixed< double, 3 > > vertices;
#pragma omp critical
{
++disp;
vtkCell* cell = inputPoly->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
for (int j=0; j<numPoints; j++)
{
double p[3];
points->GetPoint(j, p);
vnl_vector_fixed< double, 3 > p_vec;
p_vec[0]=p[0]; p_vec[1]=p[1]; p_vec[2]=p[2];
vertices.push_back(p_vec);
}
}
// calculate curvatures
int numPoints = vertices.size();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
for (int j=0; j<numPoints; j++)
{
double dist = 0;
int c = j;
std::vector< vnl_vector_fixed< double, 3 > > vectors;
vnl_vector_fixed< double, 3 > meanV; meanV.fill(0.0);
while(dist<m_Distance/2 && c>1)
{
vnl_vector_fixed< double, 3 > p1 = vertices.at(c-1);
vnl_vector_fixed< double, 3 > p2 = vertices.at(c);
vnl_vector_fixed< double, 3 > v = p2-p1;
dist += v.magnitude();
v.normalize();
vectors.push_back(v);
if (m_UseMedian && c==j)
meanV += v;
else if (!m_UseMedian)
meanV += v;
c--;
}
c = j;
dist = 0;
while(dist<m_Distance/2 && c<numPoints-1)
{
vnl_vector_fixed< double, 3 > p1 = vertices.at(c);
vnl_vector_fixed< double, 3 > p2 = vertices.at(c+1);
vnl_vector_fixed< double, 3 > v = p2-p1;
dist += v.magnitude();
v.normalize();
vectors.push_back(v);
if (m_UseMedian && c==j)
meanV += v;
else if (!m_UseMedian)
meanV += v;
c++;
}
meanV.normalize();
double dev = 0;
for (auto vec : vectors)
{
double angle = dot_product(meanV, vec);
if (angle>1.0)
angle = 1.0;
if (angle<-1.0)
angle = -1.0;
dev += acos(angle)*180/itk::Math::pi;
}
if (vectors.size()>0)
dev /= vectors.size();
if (dev<m_AngularDeviation)
{
#pragma omp critical
{
vtkIdType id = vtkNewPoints->InsertNextPoint(vertices.at(j).data_block());
container->GetPointIds()->InsertNextId(id);
}
}
else
{
if (m_RemoveFibers)
{
container = vtkSmartPointer<vtkPolyLine>::New();
break;
}
if (container->GetNumberOfPoints()>0)
{
#pragma omp critical
vtkNewCells->InsertNextCell(container);
}
container = vtkSmartPointer<vtkPolyLine>::New();
}
}
#pragma omp critical
{
if (container->GetNumberOfPoints()>0)
vtkNewCells->InsertNextCell(container);
}
}
vtkSmartPointer<vtkPolyData> outputPoly = vtkSmartPointer<vtkPolyData>::New();
outputPoly->SetPoints(vtkNewPoints);
outputPoly->SetLines(vtkNewCells);
m_OutputFiberBundle = mitk::FiberBundle::New(outputPoly);
m_OutputFiberBundle->SetTrackVisHeader(m_InputFiberBundle->GetTrackVisHeader());
}
}
diff --git a/Modules/FiberTracking/Algorithms/itkFiberCurvatureFilter.h b/Modules/FiberTracking/Algorithms/itkFiberCurvatureFilter.h
index 5b1b1b8..329b7ff 100644
--- a/Modules/FiberTracking/Algorithms/itkFiberCurvatureFilter.h
+++ b/Modules/FiberTracking/Algorithms/itkFiberCurvatureFilter.h
@@ -1,82 +1,82 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 itkFiberCurvatureFilter_h
#define itkFiberCurvatureFilter_h
// MITK
#include <mitkPlanarEllipse.h>
#include <mitkFiberBundle.h>
// ITK
#include <itkProcessObject.h>
// VTK
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkCellArray.h>
#include <vtkPoints.h>
#include <vtkPolyLine.h>
namespace itk{
/**
* \brief */
class FiberCurvatureFilter : public ProcessObject
{
public:
typedef FiberCurvatureFilter Self;
typedef ProcessObject Superclass;
typedef SmartPointer< Self > Pointer;
typedef SmartPointer< const Self > ConstPointer;
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
itkTypeMacro( FiberCurvatureFilter, ProcessObject )
void Update() override{
this->GenerateData();
}
itkSetMacro( Distance, double )
itkSetMacro( AngularDeviation, double )
itkSetMacro( RemoveFibers, bool )
itkSetMacro( UseMedian, bool )
itkSetMacro( InputFiberBundle, mitk::FiberBundle::Pointer )
itkGetMacro( OutputFiberBundle, mitk::FiberBundle::Pointer )
protected:
void GenerateData() override;
FiberCurvatureFilter();
~FiberCurvatureFilter() override;
mitk::FiberBundle::Pointer m_InputFiberBundle;
mitk::FiberBundle::Pointer m_OutputFiberBundle;
double m_AngularDeviation;
double m_Distance;
bool m_RemoveFibers;
bool m_UseMedian;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkFiberCurvatureFilter.cpp"
#endif
#endif
diff --git a/Modules/FiberTracking/Algorithms/itkFiberExtractionFilter.cpp b/Modules/FiberTracking/Algorithms/itkFiberExtractionFilter.cpp
index db6266f..3fad301 100644
--- a/Modules/FiberTracking/Algorithms/itkFiberExtractionFilter.cpp
+++ b/Modules/FiberTracking/Algorithms/itkFiberExtractionFilter.cpp
@@ -1,505 +1,505 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkFiberExtractionFilter_cpp
#define __itkFiberExtractionFilter_cpp
#include "itkFiberExtractionFilter.h"
#define _USE_MATH_DEFINES
#include <cmath>
#include <boost/progress.hpp>
#include <mitkDiffusionFunctionCollection.h>
#include <boost/lexical_cast.hpp>
namespace itk{
template< class PixelType >
FiberExtractionFilter< PixelType >::FiberExtractionFilter()
: m_DontResampleFibers(false)
, m_Mode(MODE::OVERLAP)
, m_InputType(INPUT::SCALAR_MAP)
, m_BothEnds(true)
, m_OverlapFraction(0.8)
, m_NoNegatives(false)
, m_NoPositives(false)
, m_Interpolate(false)
, m_Threshold(0.5)
, m_Labels()
, m_SkipSelfConnections(false)
, m_OnlySelfConnections(false)
, m_SplitByRoi(false)
, m_SplitLabels(false)
, m_MinFibersPerTract(0)
, m_PairedStartEndLabels(false)
{
m_Interpolator = itk::LinearInterpolateImageFunction< itk::Image< PixelType, 3 >, float >::New();
}
template< class PixelType >
FiberExtractionFilter< PixelType >::~FiberExtractionFilter()
{
}
template< class PixelType >
void FiberExtractionFilter< PixelType >::SetRoiImages(const std::vector<ItkInputImgType*> &rois)
{
for (auto roi : rois)
{
if (roi==nullptr)
{
MITK_INFO << "ROI image is NULL!";
return;
}
}
m_RoiImages = rois;
}
template< class PixelType >
void FiberExtractionFilter< PixelType >::SetRoiImageNames(const std::vector< std::string > roi_names)
{
m_RoiImageNames = roi_names;
}
template< class PixelType >
mitk::FiberBundle::Pointer FiberExtractionFilter< PixelType >::CreateFib(std::vector< unsigned int >& ids)
{
vtkSmartPointer<vtkFloatArray> weights = vtkSmartPointer<vtkFloatArray>::New();
vtkSmartPointer<vtkPolyData> pTmp = m_InputFiberBundle->GeneratePolyDataByIds(ids, weights);
mitk::FiberBundle::Pointer fib = mitk::FiberBundle::New(pTmp);
fib->SetFiberWeights(weights);
return fib;
}
template< class PixelType >
bool FiberExtractionFilter< PixelType >::IsPositive(const itk::Point<float, 3>& itkP)
{
if( m_InputType == INPUT::SCALAR_MAP )
return mitk::imv::IsInsideMask<PixelType>(itkP, m_Interpolate, m_Interpolator, m_Threshold);
else if( m_InputType == INPUT::LABEL_MAP )
{
auto val = mitk::imv::GetImageValue<PixelType>(itkP, false, m_Interpolator);
for (auto l : m_Labels)
if (l==val)
return true;
}
else
mitkThrow() << "No valid input type selected!";
return false;
}
template< class PixelType >
std::vector< std::string > FiberExtractionFilter< PixelType >::GetPositiveLabels() const
{
return m_PositiveLabels;
}
template< class PixelType >
void FiberExtractionFilter< PixelType >::ExtractOverlap(mitk::FiberBundle::Pointer fib)
{
MITK_INFO << "Extracting fibers (min. overlap " << m_OverlapFraction << ")";
vtkSmartPointer<vtkPolyData> polydata = fib->GetFiberPolyData();
std::vector< std::vector< unsigned int > > positive_ids; // one ID vector per ROI
positive_ids.resize(m_RoiImages.size());
std::vector< unsigned int > negative_ids; // fibers not overlapping with ANY mask
boost::progress_display disp(m_InputFiberBundle->GetNumFibers());
for (unsigned int i=0; i<m_InputFiberBundle->GetNumFibers(); i++)
{
++disp;
vtkCell* cell = polydata->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
float best_ol = 0;
int best_ol_idx = -1;
for (unsigned int m=0; m<m_RoiImages.size(); ++m)
{
auto roi = m_RoiImages.at(m);
m_Interpolator->SetInputImage(roi);
PixelType inside = 0;
PixelType outside = 0;
for (int j=0; j<numPoints-1; j++)
{
itk::Point<float, 3> startVertex = mitk::imv::GetItkPoint(points->GetPoint(j));
itk::Index<3> startIndex;
itk::ContinuousIndex<float, 3> startIndexCont;
roi->TransformPhysicalPointToIndex(startVertex, startIndex);
roi->TransformPhysicalPointToContinuousIndex(startVertex, startIndexCont);
itk::Point<float, 3> endVertex = mitk::imv::GetItkPoint(points->GetPoint(j + 1));
itk::Index<3> endIndex;
itk::ContinuousIndex<float, 3> endIndexCont;
roi->TransformPhysicalPointToIndex(endVertex, endIndex);
roi->TransformPhysicalPointToContinuousIndex(endVertex, endIndexCont);
std::vector< std::pair< itk::Index<3>, double > > segments = mitk::imv::IntersectImage(roi->GetSpacing(), startIndex, endIndex, startIndexCont, endIndexCont);
for (std::pair< itk::Index<3>, double > segment : segments)
{
if (!roi->GetLargestPossibleRegion().IsInside(segment.first))
continue;
if (roi->GetPixel(segment.first)>=m_Threshold)
inside += segment.second;
else
outside += segment.second;
}
}
float overlap = (float)inside/(inside+outside);
if (overlap > best_ol && overlap >= m_OverlapFraction)
{
best_ol_idx = m;
best_ol = overlap;
}
}
if (best_ol_idx<0)
negative_ids.push_back(i);
else
positive_ids.at(best_ol_idx).push_back(i);
}
if (!m_NoNegatives)
m_Negatives.push_back(CreateFib(negative_ids));
if (!m_NoPositives)
{
for (unsigned int i=0; i<positive_ids.size(); ++i)
{
std::string name;
if (i<m_RoiImageNames.size())
name = m_RoiImageNames.at(i);
else
name = "Roi" + boost::lexical_cast<std::string>(i);
if (positive_ids.at(i).size()>=m_MinFibersPerTract)
{
m_Positives.push_back(CreateFib(positive_ids.at(i)));
m_PositiveLabels.push_back(name);
}
}
if (!m_SplitByRoi)
{
mitk::FiberBundle::Pointer output = mitk::FiberBundle::New(nullptr);
output = output->AddBundles(m_Positives);
m_Positives.clear();
m_Positives.push_back(output);
m_PositiveLabels.clear();
m_PositiveLabels.push_back("");
}
}
}
template< class PixelType >
void FiberExtractionFilter< PixelType >::ExtractEndpoints(mitk::FiberBundle::Pointer fib)
{
MITK_INFO << "Extracting fibers (endpoints in mask)";
vtkSmartPointer<vtkPolyData> polydata = fib->GetFiberPolyData();
std::vector< std::vector< unsigned int > > positive_ids; // one ID vector per ROI
positive_ids.resize(m_RoiImages.size());
std::vector< unsigned int > negative_ids; // fibers not overlapping with ANY mask
boost::progress_display disp(m_InputFiberBundle->GetNumFibers());
for (unsigned int i=0; i<m_InputFiberBundle->GetNumFibers(); i++)
{
++disp;
vtkCell* cell = polydata->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
bool positive = false;
if (numPoints>1)
for (unsigned int m=0; m<m_RoiImages.size(); ++m)
{
auto roi = m_RoiImages.at(m);
m_Interpolator->SetInputImage(roi);
int inside = 0;
// check first fiber point
{
double* p = points->GetPoint(0);
itk::Point<float, 3> itkP = mitk::imv::GetItkPoint(p);
if ( IsPositive(itkP) )
inside++;
}
// check second fiber point
{
double* p = points->GetPoint(numPoints-1);
itk::Point<float, 3> itkP = mitk::imv::GetItkPoint(p);
if ( IsPositive(itkP) )
inside++;
}
if (inside==2 || (inside==1 && !m_BothEnds))
{
positive = true;
positive_ids[m].push_back(i);
}
}
if (!positive)
negative_ids.push_back(i);
}
if (!m_NoNegatives)
m_Negatives.push_back(CreateFib(negative_ids));
if (!m_NoPositives)
{
for (unsigned int i=0; i<positive_ids.size(); ++i)
{
std::string name;
if (i<m_RoiImageNames.size())
name = m_RoiImageNames.at(i);
else
name = "Roi" + boost::lexical_cast<std::string>(i);
if (positive_ids.at(i).size()>=m_MinFibersPerTract)
{
m_Positives.push_back(CreateFib(positive_ids.at(i)));
m_PositiveLabels.push_back(name);
}
}
if (!m_SplitByRoi)
{
mitk::FiberBundle::Pointer output = mitk::FiberBundle::New(nullptr);
output = output->AddBundles(m_Positives);
m_Positives.clear();
m_Positives.push_back(output);
m_PositiveLabels.clear();
m_PositiveLabels.push_back("");
}
}
}
template< class PixelType >
void FiberExtractionFilter< PixelType >::ExtractLabels(mitk::FiberBundle::Pointer fib)
{
MITK_INFO << "Extracting fibers by labels";
vtkSmartPointer<vtkPolyData> polydata = fib->GetFiberPolyData();
std::map< std::string, std::vector< unsigned int > > positive_ids;
std::vector< unsigned int > negative_ids; // fibers not overlapping with ANY label
boost::progress_display disp(m_InputFiberBundle->GetNumFibers());
for (unsigned int i=0; i<m_InputFiberBundle->GetNumFibers(); i++)
{
++disp;
vtkCell* cell = polydata->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
bool positive = false;
if (numPoints>1)
for (unsigned int m=0; m<m_RoiImages.size(); ++m)
{
auto roi = m_RoiImages.at(m);
m_Interpolator->SetInputImage(roi);
int inside = 0;
double* p1 = points->GetPoint(0);
itk::Point<float, 3> itkP1 = mitk::imv::GetItkPoint(p1);
short label1 = mitk::imv::GetImageValue<PixelType>(itkP1, false, m_Interpolator);
double* p2 = points->GetPoint(numPoints-1);
itk::Point<float, 3> itkP2 = mitk::imv::GetItkPoint(p2);
short label2 = mitk::imv::GetImageValue<PixelType>(itkP2, false, m_Interpolator);
if (!m_Labels.empty()) // extract fibers from all pairwise label combinations
{
for (auto l : m_Labels)
{
if (l==label1)
inside++;
if (l==label2)
inside++;
if (inside==2)
break;
}
}
else if (!m_StartLabels.empty() || !m_EndLabels.empty()) // extract fibers between start and end labels
{
if (!m_StartLabels.empty() && !m_EndLabels.empty())
m_BothEnds = true; // if we have start and end labels it does not make sense to not use both endpoints
if (m_PairedStartEndLabels)
{
if (m_StartLabels.size()!=m_EndLabels.size())
mitkThrow() << "Start and end label lists must have same size if paired labels are used";
for (unsigned int ii=0; ii<m_StartLabels.size(); ++ii)
if ( (m_StartLabels.at(ii)==label1 && m_EndLabels.at(ii)==label2) || (m_StartLabels.at(ii)==label2 && m_EndLabels.at(ii)==label1) )
{
inside = 2;
break;
}
}
else
{
for (unsigned int ii=0; ii<m_StartLabels.size(); ++ii)
{
if ( m_StartLabels.at(ii)==label1 || m_StartLabels.at(ii)==label2 )
{
++inside;
break;
}
}
for (unsigned int jj=0; jj<m_EndLabels.size(); ++jj)
{
if ( m_EndLabels.at(jj)==label1 || m_EndLabels.at(jj)==label2 )
{
++inside;
break;
}
}
}
}
else // use all labels
{
if (label1!=0)
++inside;
if (label2!=0)
++inside;
}
std::string key = "";
if (m_SplitLabels)
{
if (label1<label2)
key = boost::lexical_cast<std::string>(label1) + "-" + boost::lexical_cast<std::string>(label2);
else
key = boost::lexical_cast<std::string>(label2) + "-" + boost::lexical_cast<std::string>(label1);
}
if (m_SplitByRoi)
{
if (m<m_RoiImageNames.size())
key = m_RoiImageNames.at(m) + "_" + key;
else
key = "Roi" + boost::lexical_cast<std::string>(m) + "_" + key;
}
if (m_BothEnds)
{
if ( (inside==2 && (!m_SkipSelfConnections || label1!=label2)) || (inside==2 && m_OnlySelfConnections && label1==label2) )
{
positive = true;
if ( positive_ids.count(key)==0 )
positive_ids.insert( std::pair< std::string, std::vector< unsigned int > >( key, {i}) );
else
positive_ids[key].push_back(i);
}
}
else
{
if ( (inside>=1 && (!m_SkipSelfConnections || label1!=label2)) || (inside==2 && m_OnlySelfConnections && label1==label2) )
{
positive = true;
if ( positive_ids.count(key)==0 )
positive_ids.insert( std::pair< std::string, std::vector< unsigned int > >( key, {i}) );
else
positive_ids[key].push_back(i);
}
}
}
if (!positive)
negative_ids.push_back(i);
}
if (!m_NoNegatives)
m_Negatives.push_back(CreateFib(negative_ids));
if (!m_NoPositives)
{
for (auto label : positive_ids)
{
if (label.second.size()>=m_MinFibersPerTract)
{
m_Positives.push_back(CreateFib(label.second));
m_PositiveLabels.push_back(label.first);
}
}
}
}
template< class PixelType >
void FiberExtractionFilter< PixelType >::SetLabels(const std::vector<unsigned short> &Labels)
{
m_Labels = Labels;
}
template< class PixelType >
void FiberExtractionFilter< PixelType >::SetStartLabels(const std::vector<unsigned short> &Labels)
{
m_StartLabels = Labels;
}
template< class PixelType >
void FiberExtractionFilter< PixelType >::SetEndLabels(const std::vector<unsigned short> &Labels)
{
m_EndLabels = Labels;
}
template< class PixelType >
std::vector<mitk::FiberBundle::Pointer> FiberExtractionFilter< PixelType >::GetNegatives() const
{
return m_Negatives;
}
template< class PixelType >
std::vector<mitk::FiberBundle::Pointer> FiberExtractionFilter< PixelType >::GetPositives() const
{
return m_Positives;
}
template< class PixelType >
void FiberExtractionFilter< PixelType >::GenerateData()
{
mitk::FiberBundle::Pointer fib = m_InputFiberBundle;
if (fib->GetNumFibers()<=0)
{
MITK_INFO << "No fibers in tractogram!";
return;
}
if (m_Mode == MODE::OVERLAP)
ExtractOverlap(fib);
else if (m_Mode == MODE::ENDPOINTS)
{
if (m_InputType==INPUT::LABEL_MAP)
ExtractLabels(fib);
else
ExtractEndpoints(fib);
}
for (auto f : m_Negatives)
f->SetTrackVisHeader(fib->GetTrackVisHeader());
for (auto f : m_Positives)
f->SetTrackVisHeader(fib->GetTrackVisHeader());
}
}
#endif // __itkFiberExtractionFilter_cpp
diff --git a/Modules/FiberTracking/Algorithms/itkFiberExtractionFilter.h b/Modules/FiberTracking/Algorithms/itkFiberExtractionFilter.h
index b2fa4b0..750fc54 100644
--- a/Modules/FiberTracking/Algorithms/itkFiberExtractionFilter.h
+++ b/Modules/FiberTracking/Algorithms/itkFiberExtractionFilter.h
@@ -1,133 +1,133 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 itkFiberExtractionFilter_h
#define itkFiberExtractionFilter_h
// MITK
#include <mitkFiberBundle.h>
// ITK
#include <itkProcessObject.h>
#include <itkLinearInterpolateImageFunction.h>
namespace itk{
/**
* \brief Extract streamlines from tractograms using ROI images */
template< class PixelType >
class FiberExtractionFilter : public ProcessObject
{
public:
enum MODE {
OVERLAP,
ENDPOINTS
};
enum INPUT {
SCALAR_MAP, ///< In this case, positive means roi image vlaue > threshold
LABEL_MAP ///< In this case, positive means roi image value in labels vector
};
typedef FiberExtractionFilter Self;
typedef ProcessObject Superclass;
typedef SmartPointer< Self > Pointer;
typedef SmartPointer< const Self > ConstPointer;
typedef itk::Image< PixelType , 3> ItkInputImgType;
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
itkTypeMacro( FiberExtractionFilter, ProcessObject )
void Update() override{
this->GenerateData();
}
itkSetMacro( InputFiberBundle, mitk::FiberBundle::Pointer )
itkSetMacro( Mode, MODE ) ///< Overlap or endpoints
itkSetMacro( InputType, INPUT ) ///< Scalar map or label image
itkSetMacro( BothEnds, bool ) ///< Both streamline ends need to be inside of the ROI for the streamline to be considered positive
itkSetMacro( OverlapFraction, float ) ///< Necessary fraction of streamline points inside the ROI for the streamline to be considered positive
itkSetMacro( DontResampleFibers, bool ) ///< Don't resample input fibers to ensure coverage
itkSetMacro( NoNegatives, bool ) ///< Don't create output tractograms from negative streamlines (save the computation)
itkSetMacro( NoPositives, bool ) ///< Don't create output tractograms from positive streamlines (save the computation)
itkSetMacro( Interpolate, bool ) ///< Interpolate input ROI image (only relevant for ENDPOINTS mode
itkSetMacro( Threshold, float ) ///< Threshold on input ROI image value to determine positives/negatives
itkSetMacro( SkipSelfConnections, bool ) ///< Ignore streamlines between two identical labels
itkSetMacro( OnlySelfConnections, bool ) ///< Only keep streamlines between two identical labels
itkSetMacro( SplitLabels, bool ) ///< Output a separate tractogram for each label-->label tract
itkSetMacro( SplitByRoi, bool ) ///< Output a separate tractogram for each ROI image
itkSetMacro( MinFibersPerTract, unsigned int ) ///< Discard positives with less fibers
itkSetMacro( PairedStartEndLabels, bool )
void SetRoiImages(const std::vector< ItkInputImgType* > &rois);
void SetRoiImageNames(const std::vector< std::string > roi_names);
void SetLabels(const std::vector<unsigned short> &Labels);
void SetStartLabels(const std::vector<unsigned short> &Labels);
void SetEndLabels(const std::vector<unsigned short> &Labels);
std::vector<mitk::FiberBundle::Pointer> GetPositives() const; ///< Get positive tracts (filtered by the input ROIs)
std::vector<mitk::FiberBundle::Pointer> GetNegatives() const; ///< Get negative tracts (not filtered by the ROIs)
std::vector< std::string > GetPositiveLabels() const; ///< In case of label extraction, this vector contains the labels corresponding to the positive tracts
protected:
void GenerateData() override;
FiberExtractionFilter();
~FiberExtractionFilter() override;
mitk::FiberBundle::Pointer CreateFib(std::vector< unsigned int >& ids);
void ExtractOverlap(mitk::FiberBundle::Pointer fib);
void ExtractEndpoints(mitk::FiberBundle::Pointer fib);
void ExtractLabels(mitk::FiberBundle::Pointer fib);
bool IsPositive(const itk::Point<float, 3>& itkP);
mitk::FiberBundle::Pointer m_InputFiberBundle;
std::vector< mitk::FiberBundle::Pointer > m_Positives;
std::vector< mitk::FiberBundle::Pointer > m_Negatives;
std::vector< ItkInputImgType* > m_RoiImages;
std::vector< std::string > m_RoiImageNames;
bool m_DontResampleFibers;
MODE m_Mode;
INPUT m_InputType;
bool m_BothEnds;
float m_OverlapFraction;
bool m_NoNegatives;
bool m_NoPositives;
bool m_Interpolate;
float m_Threshold;
std::vector< unsigned short > m_Labels;
bool m_SkipSelfConnections;
bool m_OnlySelfConnections;
bool m_SplitByRoi;
bool m_SplitLabels;
unsigned int m_MinFibersPerTract;
std::vector< unsigned short > m_StartLabels;
std::vector< unsigned short > m_EndLabels;
bool m_PairedStartEndLabels;
std::vector< std::string > m_PositiveLabels;
typename itk::LinearInterpolateImageFunction< itk::Image< PixelType, 3 >, float >::Pointer m_Interpolator;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkFiberExtractionFilter.cpp"
#endif
#endif
diff --git a/Modules/FiberTracking/Algorithms/itkGibbsTrackingFilter.cpp b/Modules/FiberTracking/Algorithms/itkGibbsTrackingFilter.cpp
index 679b58e..7ac296a 100644
--- a/Modules/FiberTracking/Algorithms/itkGibbsTrackingFilter.cpp
+++ b/Modules/FiberTracking/Algorithms/itkGibbsTrackingFilter.cpp
@@ -1,515 +1,515 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "itkGibbsTrackingFilter.h"
// MITK
#include <itkOrientationDistributionFunction.h>
#include <itkDiffusionOdfGeneralizedFaImageFilter.h>
#include <mitkStandardFileLocations.h>
#include <mitkFiberBuilder.h>
#include <mitkMetropolisHastingsSampler.h>
//#include <mitkEnergyComputer.h>
#include <itkTensorImageToOdfImageFilter.h>
#include <mitkGibbsEnergyComputer.h>
// ITK
#include <itkImageDuplicator.h>
#include <itkResampleImageFilter.h>
#include <itkTimeProbe.h>
// MISC
#include <fstream>
// #include <QFile>
#include <tinyxml.h>
#include <boost/progress.hpp>
#include <mitkLexicalCast.h>
#include <boost/algorithm/string.hpp>
namespace itk{
template< class ItkOdfImageType >
GibbsTrackingFilter< ItkOdfImageType >::GibbsTrackingFilter():
m_StartTemperature(0.1),
m_EndTemperature(0.001),
m_Iterations(1e9),
m_CurrentIteration(0.0),
m_CurrentStep(0),
m_ParticleWeight(0),
m_ParticleWidth(0),
m_ParticleLength(0),
m_ConnectionPotential(10),
m_InexBalance(0),
m_ParticlePotential(0.2),
m_MinFiberLength(10),
m_AbortTracking(false),
m_NumAcceptedFibers(0),
m_BuildFibers(false),
m_ProposalAcceptance(0),
m_CurvatureThreshold(0.7),
m_DuplicateImage(true),
m_NumParticles(0),
m_NumConnections(0),
m_RandomSeed(-1),
m_LoadParameterFile(""),
m_LutPath(""),
m_IsInValidState(true)
{
}
template< class ItkOdfImageType >
GibbsTrackingFilter< ItkOdfImageType >::~GibbsTrackingFilter()
{
}
// fill output fiber bundle datastructure
template< class ItkOdfImageType >
typename GibbsTrackingFilter< ItkOdfImageType >::FiberPolyDataType GibbsTrackingFilter< ItkOdfImageType >::GetFiberBundle()
{
if (!m_AbortTracking)
{
m_BuildFibers = true;
while (m_BuildFibers){}
}
return m_FiberPolyData;
}
template< class ItkOdfImageType >
void
GibbsTrackingFilter< ItkOdfImageType >
::EstimateParticleWeight()
{
MITK_INFO << "GibbsTrackingFilter: estimating particle weight";
float minSpacing;
if(m_OdfImage->GetSpacing()[0]<m_OdfImage->GetSpacing()[1] && m_OdfImage->GetSpacing()[0]<m_OdfImage->GetSpacing()[2])
minSpacing = m_OdfImage->GetSpacing()[0];
else if (m_OdfImage->GetSpacing()[1] < m_OdfImage->GetSpacing()[2])
minSpacing = m_OdfImage->GetSpacing()[1];
else
minSpacing = m_OdfImage->GetSpacing()[2];
float m_ParticleLength = 1.5*minSpacing;
float m_ParticleWidth = 0.5*minSpacing;
// seed random generators
Statistics::MersenneTwisterRandomVariateGenerator::Pointer randGen = Statistics::MersenneTwisterRandomVariateGenerator::New();
if (m_RandomSeed>-1)
randGen->SetSeed(m_RandomSeed);
else
randGen->SetSeed();
// instantiate all necessary components
SphereInterpolator* interpolator = new SphereInterpolator(m_LutPath);
// handle lookup table not found cases
if( !interpolator->IsInValidState() )
{
m_IsInValidState = false;
m_AbortTracking = true;
m_BuildFibers = false;
mitkThrow() << "Unable to load lookup tables.";
}
ParticleGrid* particleGrid = new ParticleGrid(m_MaskImage, m_ParticleLength, m_ParticleGridCellCapacity);
GibbsEnergyComputer* encomp = new GibbsEnergyComputer(m_OdfImage, m_MaskImage, particleGrid, interpolator, randGen);
// EnergyComputer* encomp = new EnergyComputer(m_OdfImage, m_MaskImage, particleGrid, interpolator, randGen);
MetropolisHastingsSampler* sampler = new MetropolisHastingsSampler(particleGrid, encomp, randGen, m_CurvatureThreshold);
float alpha = log(m_EndTemperature/m_StartTemperature);
m_ParticleWeight = 0.01;
int ppv = 0;
// main loop
int neededParts = 3000;
while (ppv<neededParts)
{
if (ppv<1000)
m_ParticleWeight /= 2;
else
m_ParticleWeight = ppv*m_ParticleWeight/neededParts;
encomp->SetParameters(m_ParticleWeight,m_ParticleWidth,m_ConnectionPotential*m_ParticleLength*m_ParticleLength,m_CurvatureThreshold,m_InexBalance,m_ParticlePotential);
for( int step = 0; step < 10; step++ )
{
// update temperatur for simulated annealing process
float temperature = m_StartTemperature * exp(alpha*(((1.0)*step)/((1.0)*10)));
sampler->SetTemperature(temperature);
for (unsigned long i=0; i<10000; i++)
sampler->MakeProposal();
}
ppv = particleGrid->m_NumParticles;
particleGrid->ResetGrid();
}
delete sampler;
delete encomp;
delete particleGrid;
delete interpolator;
MITK_INFO << "GibbsTrackingFilter: finished estimating particle weight";
}
// perform global tracking
template< class ItkOdfImageType >
void GibbsTrackingFilter< ItkOdfImageType >::GenerateData()
{
TimeProbe preClock; preClock.Start();
// check if input is Odf or tensor image and generate Odf if necessary
if (m_OdfImage.IsNull() && m_TensorImage.IsNotNull())
{
TensorImageToOdfImageFilter<float,float>::Pointer filter = TensorImageToOdfImageFilter<float,float>::New();
filter->SetInput( m_TensorImage );
filter->Update();
m_OdfImage = filter->GetOutput();
}
else if (m_DuplicateImage) // generate local working copy of Odf image (if not disabled)
{
typedef itk::ImageDuplicator< ItkOdfImageType > DuplicateFilterType;
typename DuplicateFilterType::Pointer duplicator = DuplicateFilterType::New();
duplicator->SetInputImage( m_OdfImage );
duplicator->Update();
m_OdfImage = duplicator->GetOutput();
}
// perform mean subtraction on odfs
typedef ImageRegionIterator< ItkOdfImageType > InputIteratorType;
InputIteratorType it(m_OdfImage, m_OdfImage->GetLargestPossibleRegion() );
it.GoToBegin();
while (!it.IsAtEnd())
{
itk::OrientationDistributionFunction<float, ODF_SAMPLING_SIZE> odf(it.Get().GetDataPointer());
float mean = odf.GetMeanValue();
odf -= mean;
it.Set(odf.GetDataPointer());
++it;
}
// check if mask image is given if it needs resampling
PrepareMaskImage();
// load parameter file
LoadParameters();
// prepare parameters
float minSpacing;
if(m_OdfImage->GetSpacing()[0]<m_OdfImage->GetSpacing()[1] && m_OdfImage->GetSpacing()[0]<m_OdfImage->GetSpacing()[2])
minSpacing = m_OdfImage->GetSpacing()[0];
else if (m_OdfImage->GetSpacing()[1] < m_OdfImage->GetSpacing()[2])
minSpacing = m_OdfImage->GetSpacing()[1];
else
minSpacing = m_OdfImage->GetSpacing()[2];
if(m_ParticleLength == 0)
m_ParticleLength = 1.5*minSpacing;
if(m_ParticleWidth == 0)
m_ParticleWidth = 0.5*minSpacing;
if(m_ParticleWeight == 0)
EstimateParticleWeight();
float alpha = log(m_EndTemperature/m_StartTemperature);
if (m_CurvatureThreshold < mitk::eps)
m_CurvatureThreshold = 0;
// seed random generators
Statistics::MersenneTwisterRandomVariateGenerator::Pointer randGen = Statistics::MersenneTwisterRandomVariateGenerator::New();
if (m_RandomSeed>-1)
randGen->SetSeed(m_RandomSeed);
else
randGen->SetSeed();
// load sphere interpolator to evaluate the ODFs
SphereInterpolator* interpolator = new SphereInterpolator(m_LutPath);
// handle lookup table not found cases
if( !interpolator->IsInValidState() )
{
m_IsInValidState = false;
m_AbortTracking = true;
m_BuildFibers = false;
mitkThrow() << "Unable to load lookup tables.";
}
// initialize the actual tracking components (ParticleGrid, Metropolis Hastings Sampler and Energy Computer)
ParticleGrid* particleGrid;
GibbsEnergyComputer* encomp;
MetropolisHastingsSampler* sampler;
try{
particleGrid = new ParticleGrid(m_MaskImage, m_ParticleLength, m_ParticleGridCellCapacity);
encomp = new GibbsEnergyComputer(m_OdfImage, m_MaskImage, particleGrid, interpolator, randGen);
encomp->SetParameters(m_ParticleWeight,m_ParticleWidth,m_ConnectionPotential*m_ParticleLength*m_ParticleLength,m_CurvatureThreshold,m_InexBalance,m_ParticlePotential);
sampler = new MetropolisHastingsSampler(particleGrid, encomp, randGen, m_CurvatureThreshold);
}
catch(...)
{
MITK_ERROR << "Particle grid allocation failed. Not enough memory? Try to increase the particle length.";
m_IsInValidState = false;
m_AbortTracking = true;
m_BuildFibers = false;
return;
}
MITK_INFO << "----------------------------------------";
MITK_INFO << "Iterations: " << m_Iterations;
MITK_INFO << "Particle length: " << m_ParticleLength;
MITK_INFO << "Particle width: " << m_ParticleWidth;
MITK_INFO << "Particle weight: " << m_ParticleWeight;
MITK_INFO << "Start temperature: " << m_StartTemperature;
MITK_INFO << "End temperature: " << m_EndTemperature;
MITK_INFO << "In/Ex balance: " << m_InexBalance;
MITK_INFO << "Min. fiber length: " << m_MinFiberLength;
MITK_INFO << "Curvature threshold: " << m_CurvatureThreshold;
MITK_INFO << "Random seed: " << m_RandomSeed;
MITK_INFO << "----------------------------------------";
// main loop
preClock.Stop();
TimeProbe clock; clock.Start();
m_NumAcceptedFibers = 0;
m_CurrentIteration = 0;
bool just_built_fibers = false;
boost::progress_display disp(m_Iterations);
if (!m_AbortTracking)
while (m_CurrentIteration<m_Iterations)
{
just_built_fibers = false;
++disp;
m_CurrentIteration++;
if (m_AbortTracking)
break;
// update temperatur for simulated annealing process
float temperature = m_StartTemperature * exp(alpha*m_CurrentIteration/m_Iterations);
sampler->SetTemperature(temperature);
sampler->MakeProposal();
m_ProposalAcceptance = (float)sampler->GetNumAcceptedProposals()/m_CurrentIteration;
m_NumParticles = particleGrid->m_NumParticles;
m_NumConnections = particleGrid->m_NumConnections;
if (m_AbortTracking)
break;
if (m_BuildFibers)
{
FiberBuilder fiberBuilder(particleGrid, m_MaskImage);
m_FiberPolyData = fiberBuilder.iterate(m_MinFiberLength);
m_NumAcceptedFibers = m_FiberPolyData->GetNumberOfLines();
m_BuildFibers = false;
just_built_fibers = true;
}
}
if (!just_built_fibers)
{
FiberBuilder fiberBuilder(particleGrid, m_MaskImage);
m_FiberPolyData = fiberBuilder.iterate(m_MinFiberLength);
m_NumAcceptedFibers = m_FiberPolyData->GetNumberOfLines();
}
clock.Stop();
delete sampler;
delete encomp;
delete interpolator;
delete particleGrid;
m_AbortTracking = true;
m_BuildFibers = false;
int h = clock.GetTotal()/3600;
int m = ((int)clock.GetTotal()%3600)/60;
int s = (int)clock.GetTotal()%60;
MITK_INFO << "GibbsTrackingFilter: finished gibbs tracking in " << h << "h, " << m << "m and " << s << "s";
m = (int)preClock.GetTotal()/60;
s = (int)preClock.GetTotal()%60;
MITK_INFO << "GibbsTrackingFilter: preparation of the data took " << m << "m and " << s << "s";
MITK_INFO << "GibbsTrackingFilter: " << m_NumAcceptedFibers << " fibers accepted";
// sampler->PrintProposalTimes();
SaveParameters();
}
template< class ItkOdfImageType >
void GibbsTrackingFilter< ItkOdfImageType >::PrepareMaskImage()
{
if(m_MaskImage.IsNull())
{
MITK_INFO << "GibbsTrackingFilter: generating default mask image";
m_MaskImage = ItkFloatImageType::New();
m_MaskImage->SetSpacing( m_OdfImage->GetSpacing() );
m_MaskImage->SetOrigin( m_OdfImage->GetOrigin() );
m_MaskImage->SetDirection( m_OdfImage->GetDirection() );
m_MaskImage->SetRegions( m_OdfImage->GetLargestPossibleRegion() );
m_MaskImage->Allocate();
m_MaskImage->FillBuffer(1.0);
}
else if ( m_MaskImage->GetLargestPossibleRegion().GetSize()[0]!=m_OdfImage->GetLargestPossibleRegion().GetSize()[0] ||
m_MaskImage->GetLargestPossibleRegion().GetSize()[1]!=m_OdfImage->GetLargestPossibleRegion().GetSize()[1] ||
m_MaskImage->GetLargestPossibleRegion().GetSize()[2]!=m_OdfImage->GetLargestPossibleRegion().GetSize()[2] ||
m_MaskImage->GetSpacing()[0]!=m_OdfImage->GetSpacing()[0] ||
m_MaskImage->GetSpacing()[1]!=m_OdfImage->GetSpacing()[1] ||
m_MaskImage->GetSpacing()[2]!=m_OdfImage->GetSpacing()[2] )
{
MITK_INFO << "GibbsTrackingFilter: resampling mask image";
typedef itk::ResampleImageFilter< ItkFloatImageType, ItkFloatImageType, float > ResamplerType;
ResamplerType::Pointer resampler = ResamplerType::New();
resampler->SetOutputSpacing( m_OdfImage->GetSpacing() );
resampler->SetOutputOrigin( m_OdfImage->GetOrigin() );
resampler->SetOutputDirection( m_OdfImage->GetDirection() );
resampler->SetSize( m_OdfImage->GetLargestPossibleRegion().GetSize() );
resampler->SetInput( m_MaskImage );
resampler->SetDefaultPixelValue(0.0);
resampler->Update();
m_MaskImage = resampler->GetOutput();
MITK_INFO << "GibbsTrackingFilter: resampling finished";
}
}
// load tracking paramters from xml file (.gtp)
template< class ItkOdfImageType >
bool GibbsTrackingFilter< ItkOdfImageType >::LoadParameters()
{
m_AbortTracking = true;
try
{
if( m_LoadParameterFile.length()==0 )
{
m_AbortTracking = false;
return true;
}
MITK_INFO << "GibbsTrackingFilter: loading parameter file " << m_LoadParameterFile;
TiXmlDocument doc( m_LoadParameterFile );
doc.LoadFile();
TiXmlHandle hDoc(&doc);
TiXmlElement* pElem;
TiXmlHandle hRoot(nullptr);
pElem = hDoc.FirstChildElement().Element();
hRoot = TiXmlHandle(pElem);
pElem = hRoot.FirstChildElement("parameter_set").Element();
std::string iterations(pElem->Attribute("iterations"));
m_Iterations = boost::lexical_cast<double>(iterations);
std::string particleLength(pElem->Attribute("particle_length"));
m_ParticleLength = boost::lexical_cast<float>(particleLength);
std::string particleWidth(pElem->Attribute("particle_width"));
m_ParticleWidth = boost::lexical_cast<float>(particleWidth);
std::string partWeight(pElem->Attribute("particle_weight"));
m_ParticleWeight = boost::lexical_cast<float>(partWeight);
std::string startTemp(pElem->Attribute("temp_start"));
m_StartTemperature = boost::lexical_cast<float>(startTemp);
std::string endTemp(pElem->Attribute("temp_end"));
m_EndTemperature = boost::lexical_cast<float>(endTemp);
std::string inExBalance(pElem->Attribute("inexbalance"));
m_InexBalance = boost::lexical_cast<float>(inExBalance);
std::string fiberLength(pElem->Attribute("fiber_length"));
m_MinFiberLength = boost::lexical_cast<float>(fiberLength);
std::string curvThres(pElem->Attribute("curvature_threshold"));
m_CurvatureThreshold = cos(boost::lexical_cast<float>(curvThres)*itk::Math::pi/180);
m_AbortTracking = false;
MITK_INFO << "GibbsTrackingFilter: parameter file loaded successfully";
return true;
}
catch(...)
{
MITK_INFO << "GibbsTrackingFilter: could not load parameter file";
return false;
}
}
// save current tracking paramters to xml file (.gtp)
template< class ItkOdfImageType >
bool GibbsTrackingFilter< ItkOdfImageType >::SaveParameters()
{
try
{
if( m_SaveParameterFile.length()==0 )
{
MITK_INFO << "GibbsTrackingFilter: no filename specified to save parameters";
return true;
}
MITK_INFO << "GibbsTrackingFilter: saving parameter file " << m_SaveParameterFile;
TiXmlDocument documentXML;
TiXmlDeclaration* declXML = new TiXmlDeclaration( "1.0", "", "" );
documentXML.LinkEndChild( declXML );
TiXmlElement* mainXML = new TiXmlElement("global_tracking_parameter_file");
mainXML->SetAttribute("file_version", "0.1");
documentXML.LinkEndChild(mainXML);
TiXmlElement* paramXML = new TiXmlElement("parameter_set");
paramXML->SetAttribute("iterations", boost::lexical_cast<std::string>(m_Iterations));
paramXML->SetAttribute("particle_length", boost::lexical_cast<std::string>(m_ParticleLength));
paramXML->SetAttribute("particle_width", boost::lexical_cast<std::string>(m_ParticleWidth));
paramXML->SetAttribute("particle_weight", boost::lexical_cast<std::string>(m_ParticleWeight));
paramXML->SetAttribute("temp_start", boost::lexical_cast<std::string>(m_StartTemperature));
paramXML->SetAttribute("temp_end", boost::lexical_cast<std::string>(m_EndTemperature));
paramXML->SetAttribute("inexbalance", boost::lexical_cast<std::string>(m_InexBalance));
paramXML->SetAttribute("fiber_length", boost::lexical_cast<std::string>(m_MinFiberLength));
paramXML->SetAttribute("curvature_threshold", boost::lexical_cast<std::string>(m_CurvatureThreshold));
mainXML->LinkEndChild(paramXML);
if(!boost::algorithm::ends_with(m_SaveParameterFile, ".gtp"))
m_SaveParameterFile.append(".gtp");
documentXML.SaveFile( m_SaveParameterFile );
MITK_INFO << "GibbsTrackingFilter: parameter file saved successfully";
return true;
}
catch(...)
{
MITK_INFO << "GibbsTrackingFilter: could not save parameter file";
return false;
}
}
template< class ItkOdfImageType >
void GibbsTrackingFilter< ItkOdfImageType >::SetDicomProperties(mitk::FiberBundle::Pointer fib)
{
std::string model_code_value = "-";
std::string model_code_meaning = "-";
std::string algo_code_value = "sup181_ee03";
std::string algo_code_meaning = "Global";
fib->SetProperty("DICOM.anatomy.value", mitk::StringProperty::New("T-A0095"));
fib->SetProperty("DICOM.anatomy.meaning", mitk::StringProperty::New("White matter of brain and spinal cord"));
fib->SetProperty("DICOM.algo_code.value", mitk::StringProperty::New(algo_code_value));
fib->SetProperty("DICOM.algo_code.meaning", mitk::StringProperty::New(algo_code_meaning));
fib->SetProperty("DICOM.model_code.value", mitk::StringProperty::New(model_code_value));
fib->SetProperty("DICOM.model_code.meaning", mitk::StringProperty::New(model_code_meaning));
}
}
diff --git a/Modules/FiberTracking/Algorithms/itkGibbsTrackingFilter.h b/Modules/FiberTracking/Algorithms/itkGibbsTrackingFilter.h
index 34a0a5e..e62dfaf 100644
--- a/Modules/FiberTracking/Algorithms/itkGibbsTrackingFilter.h
+++ b/Modules/FiberTracking/Algorithms/itkGibbsTrackingFilter.h
@@ -1,156 +1,156 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 itkGibbsTrackingFilter_h
#define itkGibbsTrackingFilter_h
// MITK
#include <mitkSphereInterpolator.h>
#include <mitkFiberBundle.h>
// ITK
#include <itkProcessObject.h>
#include <itkImage.h>
#include <itkDiffusionTensor3D.h>
#include <itkMersenneTwisterRandomVariateGenerator.h>
// VTK
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkCellArray.h>
#include <vtkPoints.h>
#include <vtkPolyLine.h>
namespace itk{
/**
* \brief Performes global fiber tractography on the input ODF or tensor image (Gibbs tracking, Reisert 2010). */
template< class ItkOdfImageType >
class GibbsTrackingFilter : public ProcessObject
{
public:
typedef GibbsTrackingFilter Self;
typedef ProcessObject Superclass;
typedef SmartPointer< Self > Pointer;
typedef SmartPointer< const Self > ConstPointer;
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
itkTypeMacro( GibbsTrackingFilter, ProcessObject )
typedef Image< DiffusionTensor3D<float>, 3 > ItkTensorImage;
typedef typename ItkOdfImageType::Pointer ItkOdfImageTypePointer;
typedef Image< float, 3 > ItkFloatImageType;
typedef vtkSmartPointer< vtkPolyData > FiberPolyDataType;
/** Setter. */
itkSetMacro( StartTemperature, float ) ///< Start temperature of simulated annealing process.
itkSetMacro( EndTemperature, float ) ///< End temperature of simulated annealing process.
itkSetMacro( Iterations, double ) ///< Number of iterations. More iterations usually mean better results.
itkSetMacro( ParticleWeight, float ) ///< Smaller particle weights result in a higher sensitivity if the method.
itkSetMacro( ParticleWidth, float ) ///< Thinner particles cause more reconstructed fibers.
itkSetMacro( ParticleLength, float )
itkSetMacro( ConnectionPotential, float )
itkSetMacro( InexBalance, float ) ///< Values < 0 result in a stronger weighting of the internal energy, values > 0 cause a stronger weighting of the external energy,
itkSetMacro( ParticlePotential, float )
itkSetMacro( MinFiberLength, int ) ///< Shorter fibers are discarded
itkSetMacro( AbortTracking, bool ) ///< Set flag to prematurely abort tracking.
itkSetMacro( CurvatureThreshold, float) ///< Absolute angular threshold between two particles (in radians).
itkSetMacro( DuplicateImage, bool ) ///< Work on copy of input image.
itkSetMacro( RandomSeed, int ) ///< Seed for random generator.
itkSetMacro( LoadParameterFile, std::string ) ///< Parameter file.
itkSetMacro( SaveParameterFile, std::string )
itkSetMacro( LutPath, std::string ) ///< Path to lookuptables. Default is binary directory.
/** Getter. */
itkGetMacro( ParticleWeight, float )
itkGetMacro( ParticleWidth, float )
itkGetMacro( ParticleLength, float )
itkGetMacro( NumParticles, int )
itkGetMacro( NumConnections, int )
itkGetMacro( NumAcceptedFibers, int )
itkGetMacro( ProposalAcceptance, float )
itkGetMacro( CurrentIteration, double)
itkGetMacro( Iterations, double)
itkGetMacro( IsInValidState, bool)
FiberPolyDataType GetFiberBundle(); ///< Output fibers
void SetDicomProperties(mitk::FiberBundle::Pointer fib);
/** Input images. */
itkSetMacro(OdfImage, typename ItkOdfImageType::Pointer)
itkSetMacro(MaskImage, ItkFloatImageType::Pointer)
itkSetMacro(TensorImage, ItkTensorImage::Pointer)
void Update() override{
this->GenerateData();
}
protected:
void GenerateData() override;
GibbsTrackingFilter();
~GibbsTrackingFilter() override;
void EstimateParticleWeight();
void PrepareMaskImage();
bool LoadParameters();
bool SaveParameters();
// Input Images
typename ItkOdfImageType::Pointer m_OdfImage;
typename ItkFloatImageType::Pointer m_MaskImage;
typename ItkTensorImage::Pointer m_TensorImage;
// Tracking parameters
float m_StartTemperature; ///< Start temperature
float m_EndTemperature; ///< End temperature
double m_Iterations; ///< Total number of iterations
double m_CurrentIteration; ///< Current iteration
unsigned long m_CurrentStep; ///< current tracking step
float m_ParticleWeight; ///< w (unitless)
float m_ParticleWidth; ///< sigma (mm)
float m_ParticleLength; ///< l (mm)
float m_ConnectionPotential; ///< gross L (chemisches potential, default 10)
float m_InexBalance; ///< gewichtung zwischen den lambdas; -5 ... 5 -> nur intern ... nur extern,default 0
float m_ParticlePotential; ///< default 0.2
int m_MinFiberLength; ///< discard all fibers shortan than the specified length in mm
bool m_AbortTracking; ///< set flag to abort tracking
int m_NumAcceptedFibers; ///< number of reconstructed fibers generated by the FiberBuilder
volatile bool m_BuildFibers; ///< set flag to generate fibers from particle grid
float m_ProposalAcceptance; ///< proposal acceptance rate (0-1)
float m_CurvatureThreshold; ///< curvature threshold in radians (1 -> no curvature is accepted, -1 all curvature angles are accepted)
bool m_DuplicateImage; ///< generates a working copy of the Odf image so that the original image won't be changed by the mean subtraction
int m_NumParticles; ///< current number of particles in grid
int m_NumConnections; ///< current number of connections between particles in grid
int m_RandomSeed; ///< seed value for random generator (-1 for standard seeding)
std::string m_LoadParameterFile; ///< filename of parameter file (reader)
std::string m_SaveParameterFile; ///< filename of parameter file (writer)
std::string m_LutPath; ///< path to lookuptables used by the sphere interpolator
bool m_IsInValidState; ///< Whether the filter is in a valid state, false if error occured
FiberPolyDataType m_FiberPolyData; ///< container for reconstructed fibers
//Constant values
static const int m_ParticleGridCellCapacity = 1024;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkGibbsTrackingFilter.cpp"
#endif
#endif
diff --git a/Modules/FiberTracking/Algorithms/itkStochasticTractographyFilter.h b/Modules/FiberTracking/Algorithms/itkStochasticTractographyFilter.h
index 141b262..cda1ae4 100644
--- a/Modules/FiberTracking/Algorithms/itkStochasticTractographyFilter.h
+++ b/Modules/FiberTracking/Algorithms/itkStochasticTractographyFilter.h
@@ -1,316 +1,316 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkStochasticTractographyFilter_h__
#define __itkStochasticTractographyFilter_h__
#include "itkImageToImageFilter.h"
#include "vnl/vnl_random.h"
#include "vnl/vnl_vector_fixed.h"
#include "vnl/vnl_matrix.h"
#include "itkArray.h"
#include "itkVectorContainer.h"
#include "vnl/algo/vnl_qr.h"
#include "itkVariableLengthVector.h"
#include "StochasticTracking/itkSlowPolyLineParametricPath.h"
#include "itkSimpleFastMutexLock.h"
#include "itkRealTimeClock.h"
#include "itkDiffusionTensor3D.h"
#include <vector>
namespace itk{
/**
* \brief Performs probabilistic streamline tracking on the input dwi. */
/**Types for Probability Distribution **/
typedef Image< Array< double >, 3 > ProbabilityDistributionImageType;
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage,
class TOutputConnectivityImage >
class ITK_EXPORT StochasticTractographyFilter :
public ImageToImageFilter< TInputDWIImage,
TOutputConnectivityImage >{
public:
typedef StochasticTractographyFilter Self;
typedef ImageToImageFilter< TInputDWIImage,
TOutputConnectivityImage > Superclass;
typedef SmartPointer< Self > Pointer;
typedef SmartPointer< const Self > ConstPointer;
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
itkTypeMacro( StochasticTractographyFilter,
ImageToImageFilter )
/** Types for the DWI Input Image **/
typedef TInputDWIImage InputDWIImageType;
/** Types for the Connectivity Output Image**/
typedef TOutputConnectivityImage OutputConnectivityImageType;
/** Types for the Mask Image **/
typedef TInputWhiteMatterProbabilityImage InputWhiteMatterProbabilityImageType;
/** Tract Types **/
typedef SlowPolyLineParametricPath< 3 > TractType;
/** Types for the TractContainer **/
typedef VectorContainer< unsigned int, typename TractType::Pointer >
TractContainerType;
/** Types for Tensor Output Image **/
typedef Image< DiffusionTensor3D< double >, 3 > OutputTensorImageType;
/** Types for the Image-wide Magnetic Field Gradient Directions **/
typedef VectorContainer< unsigned int, vnl_vector_fixed< double, 3 > >
GradientDirectionContainerType;
/** Types for the Image-wide bValues **/
typedef double bValueType;
typedef VectorContainer< unsigned int, bValueType > bValueContainerType;
/** Types for the Measurement Frame of the Gradients **/
typedef vnl_matrix_fixed< double, 3, 3 > MeasurementFrameType;
/** Type for the sample directions **/
typedef VectorContainer< unsigned int, vnl_vector_fixed< double, 3 > >
TractOrientationContainerType;
/** the number of Tracts to generate **/
itkSetMacro( TotalTracts, unsigned int)
itkGetMacro( TotalTracts, unsigned int)
/** the maximum length of Tract **/
itkSetMacro( MaxTractLength, unsigned int )
itkGetMacro( MaxTractLength, unsigned int )
/** Set/Get bvalues **/
itkSetConstObjectMacro( bValues, bValueContainerType )
itkGetConstObjectMacro( bValues, bValueContainerType )
/** Set/Get of gradient directions **/
itkSetConstObjectMacro( Gradients, GradientDirectionContainerType )
itkGetConstObjectMacro( Gradients, GradientDirectionContainerType )
/** Set/Get the White Matter Probability Input image **/
/* At each voxel specifies the probability of a mylinated fiber existing
at that location. This probability is interpreted to be the probability
that a fiber tract passes through that region.
*/
itkSetInputMacro(WhiteMatterProbabilityImage, InputWhiteMatterProbabilityImageType)
itkGetInputMacro(WhiteMatterProbabilityImage, InputWhiteMatterProbabilityImageType)
//overide the built in set input function
//we need to create a new cache everytime we change the input image
//but we need to preserve it when the input image is the same
void SetPrimaryInput(DataObject *input)
{
typename InputDWIImageType::Pointer dwiimagePtr;
try
{
dwiimagePtr = dynamic_cast<InputDWIImageType*>( input );
}
catch(itk::ExceptionObject &e)
{
MITK_INFO << "wrong image type: " << e.what();
throw;
}
Superclass::SetPrimaryInput( input );
//update the likelihood cache
this->m_LikelihoodCachePtr = ProbabilityDistributionImageType::New();
this->m_LikelihoodCachePtr->CopyInformation( this->GetInput() );
this->m_LikelihoodCachePtr->SetBufferedRegion( this->GetInput()->GetBufferedRegion() );
this->m_LikelihoodCachePtr->SetRequestedRegion( this->GetInput()->GetRequestedRegion() );
this->m_LikelihoodCachePtr->Allocate();
this->m_CurrentLikelihoodCacheElements = 0;
//update the likelihoodcache mutex image
this->m_LikelihoodCacheMutexImagePtr = LikelihoodCacheMutexImageType::New();
this->m_LikelihoodCacheMutexImagePtr->CopyInformation( this->GetInput() );
this->m_LikelihoodCacheMutexImagePtr->SetBufferedRegion( this->GetInput()->GetBufferedRegion() );
this->m_LikelihoodCacheMutexImagePtr->SetRequestedRegion( this->GetInput()->GetRequestedRegion() );
this->m_LikelihoodCacheMutexImagePtr->Allocate();
}
/** Set/Get the seed index **/
itkSetMacro( SeedIndex, typename InputDWIImageType::IndexType )
itkGetMacro( SeedIndex, typename InputDWIImageType::IndexType )
/** Set/Get the list of directions to sample **/
itkSetConstObjectMacro( SampleDirections, TractOrientationContainerType )
itkGetConstObjectMacro( SampleDirections, TractOrientationContainerType )
/** Set/Get the Measurement Frame **/
itkSetMacro( MeasurementFrame, MeasurementFrameType )
itkGetMacro( MeasurementFrame, MeasurementFrameType )
/** Set/Get the Maximum Likelihood Cache Size, the max num. of cached voxels **/
itkSetMacro( MaxLikelihoodCacheSize, unsigned int )
itkGetMacro( MaxLikelihoodCacheSize, unsigned int )
/** Get the Tracts that are generated **/
itkGetObjectMacro( OutputTractContainer, TractContainerType )
/** Get TensorImage **/
itkGetObjectMacro( OutputTensorImage, OutputTensorImageType )
void GenerateData();
void GenerateTractContainerOutput( void );
void GenerateTensorImageOutput( void );
protected:
/** Convenience Types used only inside the filter **/
/**Types for the parameters of the Tensor Model **/
typedef vnl_vector_fixed< double, 7 > TensorModelParamType;
/**Types for the parameters of the Constrained Model **/
typedef vnl_vector_fixed< double, 6 > ConstrainedModelParamType;
/**Type to hold generated DWI values**/
typedef Image< VariableLengthVector< double >, 3 > DWIVectorImageType;
/**Types for Probability Distribution **/
typedef Image< Array< double >, 3 > ProbabilityDistributionImageType;
/** Types for the Image of Mutexes of the Likelihood distribution **/
typedef Image< SimpleFastMutexLock, 3 > LikelihoodCacheMutexImageType;
StochasticTractographyFilter();
virtual ~StochasticTractographyFilter();
/** Load the default Sample Directions**/
void LoadDefaultSampleDirections( void );
/** Randomly chose a neighboring pixel weighted on distance **/
void ProbabilisticallyInterpolate( vnl_random& randomgenerator,
const TractType::ContinuousIndexType& cindex,
typename InputDWIImageType::IndexType& index);
/** Functions and data related to fitting the tensor model at each pixel **/
void UpdateGradientDirections(void);
void UpdateTensorModelFittingMatrices( void );
void CalculateTensorModelParameters( const DWIVectorImageType::PixelType& dwivalues,
vnl_diag_matrix<double>& W,
TensorModelParamType& tensormodelparams);
void CalculateConstrainedModelParameters( const TensorModelParamType& tensormodelparams,
ConstrainedModelParamType& constrainedmodelparams);
void CalculateNoiseFreeDWIFromConstrainedModel( const ConstrainedModelParamType& constrainedmodelparams,
DWIVectorImageType::PixelType& noisefreedwi);
void CalculateResidualVariance( const DWIVectorImageType::PixelType& noisydwi,
const DWIVectorImageType::PixelType& noisefreedwi,
const vnl_diag_matrix< double >& W,
const unsigned int numberofparameters,
double& residualvariance);
void CalculateLikelihood( const DWIVectorImageType::PixelType &dwipixel,
TractOrientationContainerType::ConstPointer orientations,
ProbabilityDistributionImageType::PixelType& likelihood);
void CalculatePrior( TractOrientationContainerType::Element v_prev,
TractOrientationContainerType::ConstPointer orientations,
ProbabilityDistributionImageType::PixelType& prior );
void CalculatePosterior( const ProbabilityDistributionImageType::PixelType& likelihood,
const ProbabilityDistributionImageType::PixelType& prior,
ProbabilityDistributionImageType::PixelType& posterior);
void SampleTractOrientation( vnl_random& randomgenerator,
const ProbabilityDistributionImageType::PixelType& posterior,
TractOrientationContainerType::ConstPointer orientations,
TractOrientationContainerType::Element& choosendirection );
void StochasticTractGeneration( typename InputDWIImageType::ConstPointer dwiimagePtr,
typename InputWhiteMatterProbabilityImageType::ConstPointer maskimagePtr,
typename InputDWIImageType::IndexType seedindex,
unsigned long randomseed,
TractType::Pointer tract );
/** Callback routine used by the threading library. This routine just calls
the ThreadedGenerateData method after setting the correct region for this
thread. **/
static ITK_THREAD_RETURN_TYPE StochasticTractGenerationCallback( void *arg );
struct StochasticTractGenerationCallbackStruct{
Pointer Filter;
};
/** Thread Safe Function to check/update an entry in the likelihood cache **/
ProbabilityDistributionImageType::PixelType&
AccessLikelihoodCache( typename InputDWIImageType::IndexType index );
/** Thread Safe Function to delegate a tract and obtain a randomseed to start tracking **/
bool DelegateTract(unsigned long& randomseed);
/** Function to write a tract to the connectivity map **/
void TractContainerToConnectivityMap(TractContainerType::Pointer tractcontainer);
/** Thread Safe Function to store a tract to a TractContainer **/
void StoreTract(TractType::Pointer tract);
/** Randomly samples the existence of a fiber tract in the current voxel **/
bool FiberExistenceTest( vnl_random& randomgenerator,
typename InputWhiteMatterProbabilityImageType::ConstPointer wmpimage,
typename InputWhiteMatterProbabilityImageType::IndexType index );
MeasurementFrameType m_MeasurementFrame;
LikelihoodCacheMutexImageType::Pointer m_LikelihoodCacheMutexImagePtr;
unsigned int m_TotalTracts;
unsigned int m_MaxTractLength;
GradientDirectionContainerType::ConstPointer m_Gradients;
GradientDirectionContainerType::Pointer m_TransformedGradients;
bValueContainerType::ConstPointer m_bValues;
typename InputDWIImageType::IndexType m_SeedIndex;
TractOrientationContainerType::ConstPointer m_SampleDirections;
//these will be the same for every pixel in the image so
//go ahead and do a QR decomposition to optimize the
//LS fitting process for estimating the weighing matrix W
//in this case we solve instead:
//R*Beta = Q'logPhi
vnl_matrix< double >* m_A;
vnl_qr< double >* m_Aqr;
ProbabilityDistributionImageType::Pointer m_LikelihoodCachePtr;
unsigned long m_MaxLikelihoodCacheSize; //in Megabytes
unsigned long m_MaxLikelihoodCacheElements; //in Elements (Voxels)
unsigned long m_CurrentLikelihoodCacheElements;
SimpleFastMutexLock m_LikelihoodCacheMutex;
RealTimeClock::Pointer m_ClockPtr;
unsigned int m_TotalDelegatedTracts;
SimpleFastMutexLock m_TotalDelegatedTractsMutex;
//unsigned long m_RandomSeed;
SimpleFastMutexLock m_OutputImageMutex;
TractContainerType::Pointer m_OutputTractContainer;
SimpleFastMutexLock m_OutputTractContainerMutex;
OutputTensorImageType::Pointer m_OutputTensorImage;
vnl_random m_RandomGenerator;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkStochasticTractographyFilter.txx"
#include "StochasticTracking/itkStochasticTractographyFilter_SD.txx"
#endif
#endif
diff --git a/Modules/FiberTracking/Algorithms/itkStochasticTractographyFilter.txx b/Modules/FiberTracking/Algorithms/itkStochasticTractographyFilter.txx
index ffedcb0..b54a776 100644
--- a/Modules/FiberTracking/Algorithms/itkStochasticTractographyFilter.txx
+++ b/Modules/FiberTracking/Algorithms/itkStochasticTractographyFilter.txx
@@ -1,700 +1,700 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "itkStochasticTractographyFilter.h"
#include "vnl/vnl_math.h"
#include "vnl/vnl_matrix_fixed.h"
#include "vnl/vnl_vector_fixed.h"
#include "vnl/vnl_matrix.h"
#include "vnl/vnl_sym_matrix.h"
#include "vnl/vnl_vector.h"
#include "vnl/vnl_diag_matrix.h"
#include "vnl/algo/vnl_qr.h"
//#include "vnl/algo/vnl_svd.h"
#include "vnl/algo/vnl_matrix_inverse.h"
//#include "vnl/algo/vnl_symmetric_eigensystem.h"
#include "itkSymmetricEigenAnalysis.h"
#include "vnl/vnl_transpose.h"
#include "itkVariableSizeMatrix.h"
#include "itkPathIterator.h"
#include "itkImageRegionIterator.h"
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionConstIteratorWithIndex.h"
namespace itk{
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::StochasticTractographyFilter():
m_TotalTracts(0),m_MaxTractLength(0),m_Gradients(NULL), m_TransformedGradients(NULL),m_bValues(NULL),
m_SampleDirections(NULL), m_A(NULL), m_Aqr(NULL), m_LikelihoodCachePtr(NULL),
m_MaxLikelihoodCacheSize(0), m_CurrentLikelihoodCacheElements(0),
m_ClockPtr(NULL), m_TotalDelegatedTracts(0), m_OutputTractContainer(NULL){
this->m_SeedIndex[0]=0;
this->m_SeedIndex[1]=0;
this->m_SeedIndex[2]=0;
this->m_MeasurementFrame.set_identity();
this->SetNumberOfRequiredInputs(1); //Filter needs a DWI image and a Mask Image, but check will be outside itkProcessObject and inside GenerateData()
m_ClockPtr = RealTimeClock::New();
this->m_RandomGenerator.reseed( ((unsigned long) this->m_ClockPtr->GetTimeInSeconds()) );
//load in default sample directions
this->LoadDefaultSampleDirections();
}
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::~StochasticTractographyFilter(){
delete this->m_A;
delete this->m_Aqr;
}
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
void
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::ProbabilisticallyInterpolate( vnl_random& randomgenerator,
const TractType::ContinuousIndexType& cindex,
typename InputDWIImageType::IndexType& index){
for(int i=0; i<3; i++){
if ((vcl_ceil(cindex[i]+vnl_math::eps)-cindex[i]) < randomgenerator.drand64())
index[i]=(int)vcl_ceil(cindex[i]);
else index[i]=(int)vcl_floor(cindex[i]);
}
}
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
void
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::UpdateGradientDirections(void){
//the gradient direction is transformed into IJK space
//by moving into the image space and then to IJK space
this->m_TransformedGradients = GradientDirectionContainerType::New();
unsigned int N = this->m_Gradients->Size();
for(unsigned int i=0; i<N; i++){
GradientDirectionContainerType::Element g_i =
this->m_MeasurementFrame *
this->m_Gradients->GetElement(i);
/** The correction to LPS space is not neccessary as of itk 3.2 **/
//g_i[0] = -g_i[0];
//g_i[1] = -g_i[1];
g_i = this->GetInput()->GetDirection().GetInverse() * g_i;
this->m_TransformedGradients->InsertElement(i, g_i);
}
}
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
void
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::UpdateTensorModelFittingMatrices( void ){
//std::cout<<"UpdateTensorFittingMatrix\n";
//estimate the parameters using linear LS estimation
//using convention specified by Salvador
//solve for Beta in: logPhi=X*Beta
//number of rows of the matrix depends on the number of inputs,
//i.e. the number of measurements of the voxel (n)
unsigned int N = this->m_TransformedGradients->Size();
if(this->m_A!=NULL)
delete this->m_A;
this->m_A = new vnl_matrix< double >(N, 7); //potential memory leak here
vnl_matrix< double >& A = *(this->m_A);
for(unsigned int j=0; j< N ; j++){
GradientDirectionContainerType::Element g = m_TransformedGradients->GetElement(j);
const bValueType& b_i = m_bValues->GetElement(j);
A(j,0)=1.0;
A(j,1)=-1*b_i*(g[0]*g[0]);
A(j,2)=-1*b_i*(g[1]*g[1]);
A(j,3)=-1*b_i*(g[2]*g[2]);
A(j,4)=-1*b_i*(2*g[0]*g[1]);
A(j,5)=-1*b_i*(2*g[0]*g[2]);
A(j,6)=-1*b_i*(2*g[1]*g[2]);
}
//Store a QR decomposition to quickly estimate
//the weighing matrix for each voxel
if(this->m_Aqr!=NULL)
delete this->m_Aqr;
this->m_Aqr = new vnl_qr< double >(A); //potential memory leak here
}
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
void
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::CalculateTensorModelParameters( const DWIVectorImageType::PixelType& dwivalues,
vnl_diag_matrix<double>& W,
TensorModelParamType& tensormodelparams){
unsigned int N = this->m_TransformedGradients->Size();
//setup const references for code clarity
const vnl_matrix< double >& A = *(this->m_A);
const vnl_qr< double >& Aqr = *(this->m_Aqr);
//vnl_vector is used because the itk vector is limited in its methods and does not
//contain an internal vnl class like VariableSizematrix
//also itk_matrix has methods which are compatible with vnl_vectors
vnl_vector< double > logPhi( N );
for(unsigned int j=0; j< N ; j++){
//fill up the logPhi vector using log(dwi) values
logPhi.put(j, vcl_log(static_cast<double>(dwivalues[j]) + vnl_math::eps));
}
/** Find WLS estimate of the parameters of the Tensor model **/
// First estimate W by LS estimation of the intensities
//vnl_matrix< double > Q = Aqr.Q();
//vnl_vector< double > QtB = Aqr.Q().transpose()*logPhi;
//vnl_vector< double > QTB = Aqr.QtB(logPhi);
//vnl_matrix< double > R = Aqr.R();
W = A* vnl_qr< double >(Aqr.R()).solve(Aqr.QtB(logPhi));
//W = A * Aqr.solve(logPhi);
for(vnl_diag_matrix< double >::iterator i = W.begin();i!=W.end(); i++){
*i = vcl_exp( *i );
}
// Now solve for parameters using the estimated weighing matrix
tensormodelparams = vnl_qr< double >((W*A).transpose()*W*A).solve(
(W*A).transpose()*W*logPhi);
//int a;
//tensormodelparams = vnl_qr< double >((W*A)).solve(W*logPhi);
}
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
void
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::CalculateConstrainedModelParameters( const TensorModelParamType& tensormodelparams,
ConstrainedModelParamType& constrainedmodelparams){
vnl_sym_matrix< double > D( 3, 0 );
double alpha =0;
double beta=0;
//set the tensor model parameters into a Diffusion tensor
D(0,0) = tensormodelparams[1];
D(0,1) = tensormodelparams[4];
D(0,2) = tensormodelparams[5];
D(1,0) = tensormodelparams[4];
D(1,1) = tensormodelparams[2];
D(1,2) = tensormodelparams[6];
D(2,0) = tensormodelparams[5];
D(2,1) = tensormodelparams[6];
D(2,2) = tensormodelparams[3];
//pass through the no gradient intensity Z_0 and
//calculate alpha, beta and v hat (the eigenvector
//associated with the largest eigenvalue)
vnl_matrix_fixed< double, 3, 3 > S(0.0);
vnl_vector_fixed< double, 3 > Lambda(0.0);
SymmetricEigenAnalysis< vnl_sym_matrix< double >,
vnl_vector_fixed< double, 3 >, vnl_matrix_fixed< double, 3, 3 > >
eigensystem( 3 );
eigensystem.ComputeEigenValuesAndVectors( D, Lambda, S );
//need to take abs to get rid of negative eigenvalues
alpha = (vcl_abs(Lambda[0]) + vcl_abs(Lambda[1])) / 2;
beta = vcl_abs(Lambda[2]) - alpha;
constrainedmodelparams[0] = tensormodelparams[0];
constrainedmodelparams[1] = alpha;
constrainedmodelparams[2] = beta;
constrainedmodelparams[3] = S[2][0];
constrainedmodelparams[4] = S[2][1];
constrainedmodelparams[5] = S[2][2];
}
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
void
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::CalculateNoiseFreeDWIFromConstrainedModel( const ConstrainedModelParamType& constrainedmodelparams,
DWIVectorImageType::PixelType& noisefreedwi){
unsigned int N = this->m_TransformedGradients->Size();
const double& z_0 = constrainedmodelparams[0];
const double& alpha = constrainedmodelparams[1];
const double& beta = constrainedmodelparams[2];
TractOrientationContainerType::Element v_hat( constrainedmodelparams[3],
constrainedmodelparams[4],
constrainedmodelparams[5]);
for(unsigned int i=0; i < N ; i++ ){
const double& b_i = this->m_bValues->GetElement(i);
const GradientDirectionContainerType::Element& g_i =
this->m_TransformedGradients->GetElement(i);
noisefreedwi.SetElement(i,
vcl_exp(z_0-(alpha*b_i+beta*b_i*vnl_math_sqr(dot_product(g_i, v_hat)))));
}
}
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
void
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::CalculateResidualVariance( const DWIVectorImageType::PixelType& noisydwi,
const DWIVectorImageType::PixelType& noisefreedwi,
const vnl_diag_matrix< double >& W,
const unsigned int numberofparameters,
double& residualvariance){
unsigned int N = this->m_TransformedGradients->Size();
residualvariance=0;
/** Not sure if we should be taking difference of log or nonlog intensities **/
/** residual variance is too low if we take the difference of log intensities **/
/** perhaps using WLS will correct this problem **/
for(unsigned int i=0; i<N; i++)
residualvariance+=vnl_math_sqr(W(i,i) * (vcl_log(noisydwi[i]/noisefreedwi[i])));
residualvariance/=(N-numberofparameters);
}
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
void
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::CalculateLikelihood( const DWIVectorImageType::PixelType &dwipixel,
TractOrientationContainerType::ConstPointer orientations,
ProbabilityDistributionImageType::PixelType& likelihood){
unsigned int N = this->m_TransformedGradients->Size();
TensorModelParamType tensorparams( 0.0 );
vnl_diag_matrix< double > W(N,0);
ConstrainedModelParamType constrainedparams( 0.0 );
DWIVectorImageType::PixelType noisefreedwi(N);
double residualvariance=0;
double jointlikelihood=1;
CalculateTensorModelParameters( dwipixel, W, tensorparams );
CalculateConstrainedModelParameters( tensorparams, constrainedparams );
CalculateNoiseFreeDWIFromConstrainedModel( constrainedparams, noisefreedwi );
CalculateResidualVariance( dwipixel, noisefreedwi, W, 6, residualvariance );
for(unsigned int i=0; i < orientations->Size(); i++){
/** Vary the entry corresponding to the estimated
Tract orientation over the selected sample directions,
while preserving the best estimate for the other parameters **/
TractOrientationContainerType::Element currentdir = orientations->GetElement(i);
/** Incorporate the current sample direction into the secondary parameters **/
constrainedparams[3]=currentdir[0];
constrainedparams[4]=currentdir[1];
constrainedparams[5]=currentdir[2];
/** Obtain the estimated
intensity for this choice of Tract direction **/
CalculateNoiseFreeDWIFromConstrainedModel(constrainedparams, noisefreedwi);
jointlikelihood = 1.0;
for(unsigned int j=0; j<N; j++){
/** Calculate the likelihood given the residualvariance,
estimated intensity and the actual intensity (refer to Friman) **/
jointlikelihood *=
(noisefreedwi[j]/vcl_sqrt(2*vnl_math::pi*residualvariance))*
vcl_exp(-vnl_math_sqr(noisefreedwi[j]*vcl_log(dwipixel[j]/noisefreedwi[j]))/
(2*residualvariance));
}
likelihood[i]=jointlikelihood;
}
}
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
void
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::CalculatePrior( TractOrientationContainerType::Element v_prev,
TractOrientationContainerType::ConstPointer orientations,
ProbabilityDistributionImageType::PixelType& prior ){
const double gamma = 1;
for(unsigned int i=0; i < orientations->Size(); i++){
if(v_prev.squared_magnitude()==0){
prior[i]=1.0;
}
else{
prior[i] = dot_product(orientations->GetElement(i),v_prev);;
if(prior[i]<0){
prior[i]=0;
}
else{
prior[i]=vcl_pow(prior[i],gamma);
}
}
}
}
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
void
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::CalculatePosterior( const ProbabilityDistributionImageType::PixelType& likelihood,
const ProbabilityDistributionImageType::PixelType& prior,
ProbabilityDistributionImageType::PixelType& posterior){
double sum=0;
for(unsigned int i=0; i<likelihood.Size(); i++){
sum+=likelihood[i]*prior[i];
}
for(unsigned int i=0; i<likelihood.Size(); i++){
posterior[i] = (likelihood[i]*prior[i])/sum;
}
}
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
void
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::SampleTractOrientation( vnl_random& randomgenerator,
const ProbabilityDistributionImageType::PixelType& posterior,
TractOrientationContainerType::ConstPointer orientations,
TractOrientationContainerType::Element& choosendirection ){
double randomnum = randomgenerator.drand64();
int i=0;
double cumsum=0;
//will crash in the unlikely case that 0 was choosen as the randomnum
while(cumsum < randomnum){
cumsum+=posterior[i];
i++;
}
choosendirection = orientations->GetElement(i-1);
//std::cout<< "cumsum: " << cumsum<<std::endl;
//std::cout<<"selected orientation:( " << (i-1)
// <<") "<<choosendirection<< std::endl;
}
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
bool
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::FiberExistenceTest( vnl_random& randomgenerator,
typename InputWhiteMatterProbabilityImageType::ConstPointer wmpimage,
typename InputWhiteMatterProbabilityImageType::IndexType index ){
double randomnum = randomgenerator.drand64();
if( randomnum < wmpimage->GetPixel( index ) )
return true;
else
return false;
}
//the seedindex is in continuous IJK coordinates
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
void
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::StochasticTractGeneration( typename InputDWIImageType::ConstPointer dwiimagePtr,
typename InputWhiteMatterProbabilityImageType::ConstPointer wmpimagePtr,
typename InputDWIImageType::IndexType seedindex,
unsigned long randomseed,
TractType::Pointer tract){
TractType::ContinuousIndexType cindex_curr = seedindex;
typename InputDWIImageType::IndexType index_curr = {{0,0,0}};
ProbabilityDistributionImageType::PixelType
prior_curr(this->m_SampleDirections->Size());
ProbabilityDistributionImageType::PixelType
posterior_curr(this->m_SampleDirections->Size());
TractOrientationContainerType::Element v_curr(0,0,0);
TractOrientationContainerType::Element v_prev(0,0,0);
tract->Initialize();
vnl_random randomgenerator(randomseed);
//std::cout<<randomseed<<std::endl;
for(unsigned int j=0; j<this->m_MaxTractLength; j++){
this->ProbabilisticallyInterpolate( randomgenerator, cindex_curr, index_curr );
if(!dwiimagePtr->GetLargestPossibleRegion().IsInside(index_curr)){
break;
}
if( FiberExistenceTest( randomgenerator, wmpimagePtr, index_curr ) ){
tract->AddVertex(cindex_curr);
this->CalculatePrior( v_prev, this->m_SampleDirections, prior_curr);
const ProbabilityDistributionImageType::PixelType&
cachelikelihood_curr = this->AccessLikelihoodCache(index_curr);
if( cachelikelihood_curr.GetSize() != 0){
//use the cached direction
this->CalculatePosterior( cachelikelihood_curr, prior_curr, posterior_curr);
}
else{
//do the likelihood calculation and discard
//std::cout<<"Cache Miss!\n";
ProbabilityDistributionImageType::PixelType
likelihood_curr_temp(this->m_SampleDirections->Size());
this->CalculateLikelihood(static_cast< DWIVectorImageType::PixelType >(
dwiimagePtr->GetPixel(index_curr)),
this->m_SampleDirections,
likelihood_curr_temp);
this->CalculatePosterior( likelihood_curr_temp, prior_curr, posterior_curr);
}
this->SampleTractOrientation(randomgenerator, posterior_curr,
this->m_SampleDirections, v_curr);
//takes into account voxels of different sizes
//converts from a step length of 1 mm to the corresponding length in IJK space
const typename InputDWIImageType::SpacingType& spacing = dwiimagePtr->GetSpacing();
cindex_curr[0]+=v_curr[0]/spacing[0];
cindex_curr[1]+=v_curr[1]/spacing[1];
cindex_curr[2]+=v_curr[2]/spacing[2];
v_prev=v_curr;
}
else{
//fiber doesn't exist in this voxel
//std::cout<<"Stopped Tracking: No Fiber in this Voxel\n";
break;
}
}
}
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
void
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::GenerateTractContainerOutput(){
//allocate tractcontainer
this->m_OutputTractContainer = TractContainerType::New();
this->UpdateGradientDirections();
this->UpdateTensorModelFittingMatrices();
this->m_TotalDelegatedTracts = 0;
//calculate the number of voxels to cache from Megabyte memory size limit
ProbabilityDistributionImageType::PixelType
element(this->GetSampleDirections()->Size());
unsigned long elementsize = sizeof(ProbabilityDistributionImageType::PixelType) +
sizeof(double)*element.Size();
this->m_MaxLikelihoodCacheElements =
(this->m_MaxLikelihoodCacheSize*1048576)/elementsize;
std::cout << "MaxLikelhoodCacheElements: "
<< this->m_MaxLikelihoodCacheElements
<< std::endl;
//setup the multithreader
StochasticTractGenerationCallbackStruct data;
data.Filter = this;
this->GetMultiThreader()->SetSingleMethod( StochasticTractGenerationCallback,
&data );
this->GetMultiThreader()->SetNumberOfThreads(this->GetNumberOfThreads());
std::cout<<"Number of Threads: " << this->GetMultiThreader()->GetNumberOfThreads() << std::endl;
//start the multithreaded execution
this->GetMultiThreader()->SingleMethodExecute();
std::cout<< "CurrentLikelihoodCacheElements: " <<
this->m_CurrentLikelihoodCacheElements << std::endl;
}
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
void
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::GenerateData(){
//Generate the tracts
this->GenerateTractContainerOutput();
//allocate outputs
this->AllocateOutputs();
//write tracts to output image
this->TractContainerToConnectivityMap(this->m_OutputTractContainer);
}
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
ITK_THREAD_RETURN_TYPE
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::StochasticTractGenerationCallback( void *arg )
{
StochasticTractGenerationCallbackStruct* str=
(StochasticTractGenerationCallbackStruct *)
(((MultiThreader::ThreadInfoStruct *)(arg))->UserData);
typename InputDWIImageType::ConstPointer inputDWIImagePtr = str->Filter->GetInput();
typename InputWhiteMatterProbabilityImageType::ConstPointer inputWMPImage =
str->Filter->GetWhiteMatterProbabilityImage();
unsigned long randomseed=0;
while(str->Filter->DelegateTract(randomseed)){
//std::cout<<randomseed<<std::endl;
//generate the tract
TractType::Pointer tract = TractType::New();
str->Filter->StochasticTractGeneration( inputDWIImagePtr,
inputWMPImage,
str->Filter->GetSeedIndex(),
randomseed,
tract);
//only store tract if it is of nonzero length
if( tract->GetVertexList()->Size() > 4 ){
//std::cout<<"Storing tract\n";
str->Filter->StoreTract(tract);
}
else{
//std::cout<<"Not Storing Tract\n";
}
}
return ITK_THREAD_RETURN_VALUE;
}
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
ProbabilityDistributionImageType::PixelType&
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::AccessLikelihoodCache( typename InputDWIImageType::IndexType index )
{
this->m_LikelihoodCacheMutexImagePtr->GetPixel(index).Lock();
ProbabilityDistributionImageType::PixelType& likelihood =
m_LikelihoodCachePtr->GetPixel( index );
typename InputDWIImageType::ConstPointer inputDWIImagePtr = this->GetInput();
if( likelihood.GetSize() !=0){
//entry found in cache
this->m_LikelihoodCacheMutexImagePtr->GetPixel(index).Unlock();
return likelihood;
}
//we need to lock m_CurrentLikelihoodCacheElements as well but not crucial right now
else if( this->m_CurrentLikelihoodCacheElements < this->m_MaxLikelihoodCacheElements ){
//entry not found in cache but we have space to store it
likelihood.SetSize(this->m_SampleDirections->Size());
this->CalculateLikelihood(static_cast< DWIVectorImageType::PixelType >(
inputDWIImagePtr->GetPixel(index)),
this->m_SampleDirections,
likelihood);
this->m_CurrentLikelihoodCacheElements++;
this->m_LikelihoodCacheMutexImagePtr->GetPixel(index).Unlock();
return likelihood;
}
else{
//entry not found in cache and no space to store it
this->m_LikelihoodCacheMutexImagePtr->GetPixel(index).Unlock();
return likelihood;
}
this->m_LikelihoodCacheMutexImagePtr->GetPixel(index).Unlock();
// dummy
return likelihood;
}
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
bool
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::DelegateTract(unsigned long& randomseed){
bool success = false;
this->m_TotalDelegatedTractsMutex.Lock();
if(this->m_TotalDelegatedTracts < this->m_TotalTracts){
randomseed = this->m_RandomGenerator.lrand32();
this->m_TotalDelegatedTracts++;
success = true;
//a tract was successfully delegated
}
else success = false; //all tracts have been delegated
this->m_TotalDelegatedTractsMutex.Unlock();
return success;
}
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
void
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::TractContainerToConnectivityMap(TractContainerType::Pointer tractcontainer){
//zero the output image
typename OutputConnectivityImageType::Pointer outputPtr = this->GetOutput();
outputPtr->FillBuffer(0);
typedef PathIterator< OutputConnectivityImageType, TractType > OutputTractIteratorType;
for(unsigned int i=0; i<tractcontainer->Size(); i++ ){
TractType::Pointer tract = tractcontainer->GetElement(i);
//std::cout<< tract->EndOfInput() <<std::endl;
OutputTractIteratorType outputtractIt( outputPtr,
tract );
for(outputtractIt.GoToBegin(); !outputtractIt.IsAtEnd(); ++outputtractIt){
/* there is an issue using outputtractIt.Value() */
// outputtractIt.Set(outputtractIt.Get()+1);
}
}
}
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
void
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::StoreTract(TractType::Pointer tract){
this->m_OutputTractContainerMutex.Lock();
this->m_OutputTractContainer->InsertElement(
this->m_OutputTractContainer->Size(),
tract);
this->m_OutputTractContainerMutex.Unlock();
}
template< class TInputDWIImage, class TInputWhiteMatterProbabilityImage, class TOutputConnectivityImage >
void
StochasticTractographyFilter< TInputDWIImage, TInputWhiteMatterProbabilityImage, TOutputConnectivityImage >
::GenerateTensorImageOutput(void){
this->UpdateGradientDirections();
this->UpdateTensorModelFittingMatrices();
//allocate the tensor image
this->m_OutputTensorImage = OutputTensorImageType::New();
m_OutputTensorImage->CopyInformation( this->GetInput() );
m_OutputTensorImage->SetBufferedRegion( this->GetInput()->GetBufferedRegion() );
m_OutputTensorImage->SetRequestedRegion( this->GetInput()->GetRequestedRegion() );
m_OutputTensorImage->Allocate();
//define an iterator for the input and output images
typedef itk::ImageRegionConstIterator< InputDWIImageType > DWIImageIteratorType;
typedef itk::ImageRegionIterator< OutputTensorImageType > TensorImageIteratorType;
DWIImageIteratorType
inputDWIit( this->GetInput(), m_OutputTensorImage->GetRequestedRegion() );
TensorImageIteratorType outputtensorit
( m_OutputTensorImage, m_OutputTensorImage->GetRequestedRegion() );
unsigned int N = this->m_TransformedGradients->Size();
TensorModelParamType tensormodelparams( 0.0 );
vnl_diag_matrix< double > W(N,0);
for(inputDWIit.GoToBegin(), outputtensorit.GoToBegin();
!outputtensorit.IsAtEnd(); ++inputDWIit, ++outputtensorit){
CalculateTensorModelParameters( inputDWIit.Get(),
W, tensormodelparams);
OutputTensorImageType::PixelType& D = outputtensorit.Value();
//set the tensor model parameters into a Diffusion tensor
D(0,0) = tensormodelparams[1];
D(0,1) = tensormodelparams[4];
D(0,2) = tensormodelparams[5];
D(1,0) = tensormodelparams[4];
D(1,1) = tensormodelparams[2];
D(1,2) = tensormodelparams[6];
D(2,0) = tensormodelparams[5];
D(2,1) = tensormodelparams[6];
D(2,2) = tensormodelparams[3];
//std::cout<<D;
}
}
}
diff --git a/Modules/FiberTracking/Algorithms/itkStreamlineTrackingFilter.cpp b/Modules/FiberTracking/Algorithms/itkStreamlineTrackingFilter.cpp
index bbf27c2..ec64f08 100644
--- a/Modules/FiberTracking/Algorithms/itkStreamlineTrackingFilter.cpp
+++ b/Modules/FiberTracking/Algorithms/itkStreamlineTrackingFilter.cpp
@@ -1,980 +1,980 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <ctime>
#include <cstdio>
#include <cstdlib>
#include <omp.h>
#include "itkStreamlineTrackingFilter.h"
#include <itkImageRegionConstIterator.h>
#include <itkImageRegionConstIteratorWithIndex.h>
#include <itkImageRegionIterator.h>
#include "itkPointShell.h"
#include <itkRescaleIntensityImageFilter.h>
#include <mitkLexicalCast.h>
#include <TrackingHandlers/mitkTrackingDataHandler.h>
#include <TrackingHandlers/mitkTrackingHandlerOdf.h>
#include <TrackingHandlers/mitkTrackingHandlerPeaks.h>
#include <TrackingHandlers/mitkTrackingHandlerTensor.h>
#include <TrackingHandlers/mitkTrackingHandlerRandomForest.h>
#include <mitkDiffusionFunctionCollection.h>
namespace itk {
StreamlineTrackingFilter
::StreamlineTrackingFilter()
: m_PauseTracking(false)
, m_AbortTracking(false)
, m_BuildFibersFinished(false)
, m_BuildFibersReady(0)
, m_FiberPolyData(nullptr)
, m_Points(nullptr)
, m_Cells(nullptr)
, m_StoppingRegions(nullptr)
, m_TargetRegions(nullptr)
, m_SeedImage(nullptr)
, m_MaskImage(nullptr)
, m_ExclusionRegions(nullptr)
, m_OutputProbabilityMap(nullptr)
, m_Verbose(true)
, m_DemoMode(false)
, m_CurrentTracts(0)
, m_Progress(0)
, m_StopTracking(false)
, m_TrackingPriorHandler(nullptr)
{
this->SetNumberOfRequiredInputs(0);
}
std::string StreamlineTrackingFilter::GetStatusText()
{
std::string status = "Seedpoints processed: " + boost::lexical_cast<std::string>(m_Progress) + "/" + boost::lexical_cast<std::string>(m_SeedPoints.size());
if (m_SeedPoints.size()>0)
status += " (" + boost::lexical_cast<std::string>(100*m_Progress/m_SeedPoints.size()) + "%)";
if (m_Parameters->m_MaxNumFibers>0)
status += "\nFibers accepted: " + boost::lexical_cast<std::string>(m_CurrentTracts) + "/" + boost::lexical_cast<std::string>(m_Parameters->m_MaxNumFibers);
else
status += "\nFibers accepted: " + boost::lexical_cast<std::string>(m_CurrentTracts);
return status;
}
void StreamlineTrackingFilter::BeforeTracking()
{
m_StopTracking = false;
m_TrackingHandler->SetParameters(m_Parameters);
m_TrackingHandler->InitForTracking();
m_FiberPolyData = PolyDataType::New();
m_Points = vtkSmartPointer< vtkPoints >::New();
m_Cells = vtkSmartPointer< vtkCellArray >::New();
if (m_TrackingPriorHandler!=nullptr)
{
m_TrackingPriorHandler->InitForTracking();
}
m_PolyDataContainer.clear();
for (unsigned int i=0; i<this->GetNumberOfThreads(); i++)
{
PolyDataType poly = PolyDataType::New();
m_PolyDataContainer.push_back(poly);
}
auto imageSpacing = m_TrackingHandler->GetSpacing();
if (m_Parameters->m_OutputProbMap)
{
m_OutputProbabilityMap = ItkDoubleImgType::New();
m_OutputProbabilityMap->SetSpacing(imageSpacing);
m_OutputProbabilityMap->SetOrigin(m_TrackingHandler->GetOrigin());
m_OutputProbabilityMap->SetDirection(m_TrackingHandler->GetDirection());
m_OutputProbabilityMap->SetRegions(m_TrackingHandler->GetLargestPossibleRegion());
m_OutputProbabilityMap->Allocate();
m_OutputProbabilityMap->FillBuffer(0);
}
m_MaskInterpolator = itk::LinearInterpolateImageFunction< ItkFloatImgType, float >::New();
m_StopInterpolator = itk::LinearInterpolateImageFunction< ItkFloatImgType, float >::New();
m_SeedInterpolator = itk::LinearInterpolateImageFunction< ItkFloatImgType, float >::New();
m_TargetInterpolator = itk::LinearInterpolateImageFunction< ItkFloatImgType, float >::New();
m_ExclusionInterpolator = itk::LinearInterpolateImageFunction< ItkFloatImgType, float >::New();
if (m_StoppingRegions.IsNull())
{
m_StoppingRegions = ItkFloatImgType::New();
m_StoppingRegions->SetSpacing( imageSpacing );
m_StoppingRegions->SetOrigin( m_TrackingHandler->GetOrigin() );
m_StoppingRegions->SetDirection( m_TrackingHandler->GetDirection() );
m_StoppingRegions->SetRegions( m_TrackingHandler->GetLargestPossibleRegion() );
m_StoppingRegions->Allocate();
m_StoppingRegions->FillBuffer(0);
}
else
std::cout << "StreamlineTracking - Using stopping region image" << std::endl;
m_StopInterpolator->SetInputImage(m_StoppingRegions);
if (m_ExclusionRegions.IsNotNull())
{
std::cout << "StreamlineTracking - Using exclusion region image" << std::endl;
m_ExclusionInterpolator->SetInputImage(m_ExclusionRegions);
}
if (m_TargetRegions.IsNull())
{
m_TargetImageSet = false;
m_TargetRegions = ItkFloatImgType::New();
m_TargetRegions->SetSpacing( imageSpacing );
m_TargetRegions->SetOrigin( m_TrackingHandler->GetOrigin() );
m_TargetRegions->SetDirection( m_TrackingHandler->GetDirection() );
m_TargetRegions->SetRegions( m_TrackingHandler->GetLargestPossibleRegion() );
m_TargetRegions->Allocate();
m_TargetRegions->FillBuffer(1);
}
else
{
m_TargetImageSet = true;
m_TargetInterpolator->SetInputImage(m_TargetRegions);
std::cout << "StreamlineTracking - Using target region image" << std::endl;
}
if (m_SeedImage.IsNull())
{
m_SeedImageSet = false;
m_SeedImage = ItkFloatImgType::New();
m_SeedImage->SetSpacing( imageSpacing );
m_SeedImage->SetOrigin( m_TrackingHandler->GetOrigin() );
m_SeedImage->SetDirection( m_TrackingHandler->GetDirection() );
m_SeedImage->SetRegions( m_TrackingHandler->GetLargestPossibleRegion() );
m_SeedImage->Allocate();
m_SeedImage->FillBuffer(1);
}
else
{
m_SeedImageSet = true;
std::cout << "StreamlineTracking - Using seed image" << std::endl;
}
m_SeedInterpolator->SetInputImage(m_SeedImage);
if (m_MaskImage.IsNull())
{
// initialize mask image
m_MaskImage = ItkFloatImgType::New();
m_MaskImage->SetSpacing( imageSpacing );
m_MaskImage->SetOrigin( m_TrackingHandler->GetOrigin() );
m_MaskImage->SetDirection( m_TrackingHandler->GetDirection() );
m_MaskImage->SetRegions( m_TrackingHandler->GetLargestPossibleRegion() );
m_MaskImage->Allocate();
m_MaskImage->FillBuffer(1);
}
else
std::cout << "StreamlineTracking - Using mask image" << std::endl;
m_MaskInterpolator->SetInputImage(m_MaskImage);
// Autosettings for endpoint constraints
if (m_Parameters->m_EpConstraints==EndpointConstraints::NONE && m_TargetImageSet && m_SeedImageSet)
{
MITK_INFO << "No endpoint constraint chosen but seed and target image set --> setting constraint to EPS_IN_SEED_AND_TARGET";
m_Parameters->m_EpConstraints = EndpointConstraints::EPS_IN_SEED_AND_TARGET;
}
else if (m_Parameters->m_EpConstraints==EndpointConstraints::NONE && m_TargetImageSet)
{
MITK_INFO << "No endpoint constraint chosen but target image set --> setting constraint to EPS_IN_TARGET";
m_Parameters->m_EpConstraints = EndpointConstraints::EPS_IN_TARGET;
}
// Check if endpoint constraints are valid
FiberType test_fib; itk::Point<float> p; p.Fill(0);
test_fib.push_back(p); test_fib.push_back(p);
IsValidFiber(&test_fib);
if (m_SeedPoints.empty())
GetSeedPointsFromSeedImage();
m_BuildFibersReady = 0;
m_BuildFibersFinished = false;
m_Tractogram.clear();
m_SamplingPointset = mitk::PointSet::New();
m_AlternativePointset = mitk::PointSet::New();
m_StopVotePointset = mitk::PointSet::New();
m_StartTime = std::chrono::system_clock::now();
if (m_DemoMode)
omp_set_num_threads(1);
if (m_Parameters->m_Mode==mitk::TrackingDataHandler::MODE::DETERMINISTIC)
std::cout << "StreamlineTracking - Mode: deterministic" << std::endl;
else if(m_Parameters->m_Mode==mitk::TrackingDataHandler::MODE::PROBABILISTIC)
{
std::cout << "StreamlineTracking - Mode: probabilistic" << std::endl;
std::cout << "StreamlineTracking - Trials per seed: " << m_Parameters->m_TrialsPerSeed << std::endl;
}
else
std::cout << "StreamlineTracking - Mode: ???" << std::endl;
if (m_Parameters->m_EpConstraints==EndpointConstraints::NONE)
std::cout << "StreamlineTracking - Endpoint constraint: NONE" << std::endl;
else if (m_Parameters->m_EpConstraints==EndpointConstraints::EPS_IN_TARGET)
std::cout << "StreamlineTracking - Endpoint constraint: EPS_IN_TARGET" << std::endl;
else if (m_Parameters->m_EpConstraints==EndpointConstraints::EPS_IN_TARGET_LABELDIFF)
std::cout << "StreamlineTracking - Endpoint constraint: EPS_IN_TARGET_LABELDIFF" << std::endl;
else if (m_Parameters->m_EpConstraints==EndpointConstraints::EPS_IN_SEED_AND_TARGET)
std::cout << "StreamlineTracking - Endpoint constraint: EPS_IN_SEED_AND_TARGET" << std::endl;
else if (m_Parameters->m_EpConstraints==EndpointConstraints::MIN_ONE_EP_IN_TARGET)
std::cout << "StreamlineTracking - Endpoint constraint: MIN_ONE_EP_IN_TARGET" << std::endl;
else if (m_Parameters->m_EpConstraints==EndpointConstraints::ONE_EP_IN_TARGET)
std::cout << "StreamlineTracking - Endpoint constraint: ONE_EP_IN_TARGET" << std::endl;
else if (m_Parameters->m_EpConstraints==EndpointConstraints::NO_EP_IN_TARGET)
std::cout << "StreamlineTracking - Endpoint constraint: NO_EP_IN_TARGET" << std::endl;
std::cout << "StreamlineTracking - Angular threshold: " << m_Parameters->GetAngularThresholdDot() << "°" << std::endl;
std::cout << "StreamlineTracking - Stepsize: " << m_Parameters->GetStepSizeMm() << "mm (" << m_Parameters->GetStepSizeMm()/m_Parameters->GetMinVoxelSizeMm() << "*vox)" << std::endl;
std::cout << "StreamlineTracking - Seeds per voxel: " << m_Parameters->m_SeedsPerVoxel << std::endl;
std::cout << "StreamlineTracking - Max. tract length: " << m_Parameters->m_MaxTractLengthMm << "mm" << std::endl;
std::cout << "StreamlineTracking - Min. tract length: " << m_Parameters->m_MinTractLengthMm << "mm" << std::endl;
std::cout << "StreamlineTracking - Max. num. tracts: " << m_Parameters->m_MaxNumFibers << std::endl;
std::cout << "StreamlineTracking - Loop check: " << m_Parameters->GetLoopCheckDeg() << "°" << std::endl;
std::cout << "StreamlineTracking - Num. neighborhood samples: " << m_Parameters->m_NumSamples << std::endl;
std::cout << "StreamlineTracking - Max. sampling distance: " << m_Parameters->GetSamplingDistanceMm() << "mm (" << m_Parameters->GetSamplingDistanceMm()/m_Parameters->GetMinVoxelSizeMm() << "*vox)" << std::endl;
std::cout << "StreamlineTracking - Deflection modifier: " << m_Parameters->m_DeflectionMod << std::endl;
std::cout << "StreamlineTracking - Use stop votes: " << m_Parameters->m_StopVotes << std::endl;
std::cout << "StreamlineTracking - Only frontal samples: " << m_Parameters->m_OnlyForwardSamples << std::endl;
if (m_TrackingPriorHandler!=nullptr)
std::cout << "StreamlineTracking - Using directional prior for tractography (w=" << m_Parameters->m_Weight << ")" << std::endl;
if (m_DemoMode)
{
std::cout << "StreamlineTracking - Running in demo mode";
std::cout << "StreamlineTracking - Starting streamline tracking using 1 thread" << std::endl;
}
else
std::cout << "StreamlineTracking - Starting streamline tracking using " << omp_get_max_threads() << " threads" << std::endl;
}
void StreamlineTrackingFilter::CalculateNewPosition(itk::Point<float, 3>& pos, vnl_vector_fixed<float, 3>& dir)
{
pos[0] += dir[0]*m_Parameters->GetStepSizeMm();
pos[1] += dir[1]*m_Parameters->GetStepSizeMm();
pos[2] += dir[2]*m_Parameters->GetStepSizeMm();
}
std::vector< vnl_vector_fixed<float,3> > StreamlineTrackingFilter::CreateDirections(unsigned int NPoints)
{
std::vector< vnl_vector_fixed<float,3> > pointshell;
if (NPoints<2)
return pointshell;
std::vector< double > theta; theta.resize(NPoints);
std::vector< double > phi; phi.resize(NPoints);
auto C = sqrt(4*itk::Math::pi);
phi[0] = 0.0;
phi[NPoints-1] = 0.0;
for(unsigned int i=0; i<NPoints; i++)
{
theta[i] = acos(-1.0+2.0*i/(NPoints-1.0)) - itk::Math::pi / 2.0;
if( i>0 && i<NPoints-1)
{
phi[i] = (phi[i-1] + C / sqrt(NPoints*(1-(-1.0+2.0*i/(NPoints-1.0))*(-1.0+2.0*i/(NPoints-1.0)))));
// % (2*DIST_POINTSHELL_PI);
}
}
for(unsigned int i=0; i<NPoints; i++)
{
vnl_vector_fixed<float,3> d;
d[0] = static_cast<float>(cos(theta[i]) * cos(phi[i]));
d[1] = static_cast<float>(cos(theta[i]) * sin(phi[i]));
d[2] = static_cast<float>(sin(theta[i]));
pointshell.push_back(d);
}
return pointshell;
}
vnl_vector_fixed<float,3> StreamlineTrackingFilter::GetNewDirection(const itk::Point<float, 3> &pos, std::deque<vnl_vector_fixed<float, 3> >& olddirs, itk::Index<3> &oldIndex)
{
if (m_DemoMode)
{
m_SamplingPointset->Clear();
m_AlternativePointset->Clear();
m_StopVotePointset->Clear();
}
vnl_vector_fixed<float,3> direction; direction.fill(0);
if (mitk::imv::IsInsideMask<float>(pos, m_Parameters->m_InterpolateRoiImages, m_MaskInterpolator) && !mitk::imv::IsInsideMask<float>(pos, m_Parameters->m_InterpolateRoiImages, m_StopInterpolator))
direction = m_TrackingHandler->ProposeDirection(pos, olddirs, oldIndex); // get direction proposal at current streamline position
else
return direction;
int stop_votes = 0;
int possible_stop_votes = 0;
if (!olddirs.empty())
{
vnl_vector_fixed<float,3> olddir = olddirs.back();
std::vector< vnl_vector_fixed<float,3> > probeVecs = CreateDirections(m_Parameters->m_NumSamples);
itk::Point<float, 3> sample_pos;
unsigned int alternatives = 1;
for (unsigned int i=0; i<probeVecs.size(); i++)
{
vnl_vector_fixed<float,3> d;
bool is_stop_voter = false;
if (!m_Parameters->m_FixRandomSeed && m_Parameters->m_RandomSampling)
{
d[0] = static_cast<float>(m_TrackingHandler->GetRandDouble(-0.5, 0.5));
d[1] = static_cast<float>(m_TrackingHandler->GetRandDouble(-0.5, 0.5));
d[2] = static_cast<float>(m_TrackingHandler->GetRandDouble(-0.5, 0.5));
d.normalize();
d *= static_cast<float>(m_TrackingHandler->GetRandDouble(0, static_cast<double>(m_Parameters->GetSamplingDistanceMm())));
}
else
{
d = probeVecs.at(i);
float dot = dot_product(d, olddir);
if (m_Parameters->m_StopVotes && dot>0.7f)
{
is_stop_voter = true;
possible_stop_votes++;
}
else if (m_Parameters->m_OnlyForwardSamples && dot<0)
continue;
d *= m_Parameters->GetSamplingDistanceMm();
}
sample_pos[0] = pos[0] + d[0];
sample_pos[1] = pos[1] + d[1];
sample_pos[2] = pos[2] + d[2];
vnl_vector_fixed<float,3> tempDir; tempDir.fill(0.0);
if (mitk::imv::IsInsideMask<float>(sample_pos, m_Parameters->m_InterpolateRoiImages, m_MaskInterpolator))
tempDir = m_TrackingHandler->ProposeDirection(sample_pos, olddirs, oldIndex); // sample neighborhood
if (tempDir.magnitude()>static_cast<float>(mitk::eps))
{
direction += tempDir;
if(m_DemoMode)
m_SamplingPointset->InsertPoint(i, sample_pos);
}
else if (m_Parameters->m_AvoidStop && olddir.magnitude()>0.5f) // out of white matter
{
if (is_stop_voter)
stop_votes++;
if (m_DemoMode)
m_StopVotePointset->InsertPoint(i, sample_pos);
float dot = dot_product(d, olddir);
if (dot >= 0.0f) // in front of plane defined by pos and olddir
d = -d + 2*dot*olddir; // reflect
else
d = -d; // invert
// look a bit further into the other direction
sample_pos[0] = pos[0] + d[0];
sample_pos[1] = pos[1] + d[1];
sample_pos[2] = pos[2] + d[2];
alternatives++;
vnl_vector_fixed<float,3> tempDir; tempDir.fill(0.0);
if (mitk::imv::IsInsideMask<float>(sample_pos, m_Parameters->m_InterpolateRoiImages, m_MaskInterpolator))
tempDir = m_TrackingHandler->ProposeDirection(sample_pos, olddirs, oldIndex); // sample neighborhood
if (tempDir.magnitude()>static_cast<float>(mitk::eps)) // are we back in the white matter?
{
direction += d * m_Parameters->m_DeflectionMod; // go into the direction of the white matter
direction += tempDir; // go into the direction of the white matter direction at this location
if(m_DemoMode)
m_AlternativePointset->InsertPoint(alternatives, sample_pos);
}
else
{
if (m_DemoMode)
m_StopVotePointset->InsertPoint(i, sample_pos);
}
}
else
{
if (m_DemoMode)
m_StopVotePointset->InsertPoint(i, sample_pos);
if (is_stop_voter)
stop_votes++;
}
}
}
bool valid = false;
if (direction.magnitude()>0.001f && (possible_stop_votes==0 || static_cast<float>(stop_votes)/possible_stop_votes<0.5f) )
{
direction.normalize();
valid = true;
}
else
direction.fill(0);
if (m_TrackingPriorHandler!=nullptr && (m_Parameters->m_NewDirectionsFromPrior || valid))
{
vnl_vector_fixed<float,3> prior = m_TrackingPriorHandler->ProposeDirection(pos, olddirs, oldIndex);
if (prior.magnitude()>0.001f)
{
prior.normalize();
if (dot_product(prior,direction)<0)
prior *= -1;
direction = (1.0f-m_Parameters->m_Weight) * direction + m_Parameters->m_Weight * prior;
direction.normalize();
}
else if (m_Parameters->m_RestrictToPrior)
direction.fill(0.0);
}
return direction;
}
float StreamlineTrackingFilter::FollowStreamline(itk::Point<float, 3> pos, vnl_vector_fixed<float,3> dir, FiberType* fib, DirectionContainer* container, float tractLength, bool front, bool &exclude)
{
vnl_vector_fixed<float,3> zero_dir; zero_dir.fill(0.0);
std::deque< vnl_vector_fixed<float,3> > last_dirs;
for (unsigned int i=0; i<m_Parameters->m_NumPreviousDirections-1; i++)
last_dirs.push_back(zero_dir);
for (int step=0; step< 5000; step++)
{
itk::Index<3> oldIndex;
m_TrackingHandler->WorldToIndex(pos, oldIndex);
// get new position
CalculateNewPosition(pos, dir);
if (m_ExclusionRegions.IsNotNull() && mitk::imv::IsInsideMask<float>(pos, m_Parameters->m_InterpolateRoiImages, m_ExclusionInterpolator))
{
exclude = true;
return tractLength;
}
if (m_AbortTracking)
return tractLength;
// if yes, add new point to streamline
dir.normalize();
if (front)
{
fib->push_front(pos);
container->push_front(dir);
}
else
{
fib->push_back(pos);
container->push_back(dir);
}
tractLength += m_Parameters->GetStepSizeMm();
if (m_Parameters->GetLoopCheckDeg()>=0 && CheckCurvature(container, front)>m_Parameters->GetLoopCheckDeg())
return tractLength;
if (tractLength>m_Parameters->m_MaxTractLengthMm)
return tractLength;
if (m_DemoMode && !m_Parameters->m_OutputProbMap) // CHECK: warum sind die samplingpunkte der streamline in der visualisierung immer einen schritt voras?
{
#pragma omp critical
{
m_BuildFibersReady++;
m_Tractogram.push_back(*fib);
BuildFibers(true);
m_Stop = true;
while (m_Stop){
}
}
}
last_dirs.push_back(dir);
if (last_dirs.size()>m_Parameters->m_NumPreviousDirections)
last_dirs.pop_front();
dir = GetNewDirection(pos, last_dirs, oldIndex);
while (m_PauseTracking){}
if (dir.magnitude()<0.0001f)
return tractLength;
}
return tractLength;
}
float StreamlineTrackingFilter::CheckCurvature(DirectionContainer* fib, bool front)
{
if (fib->size()<8)
return 0;
float m_Distance = std::max(m_Parameters->GetMinVoxelSizeMm()*4, m_Parameters->GetStepSizeMm()*8);
float dist = 0;
std::vector< vnl_vector_fixed< float, 3 > > vectors;
vnl_vector_fixed< float, 3 > meanV; meanV.fill(0);
float dev = 0;
if (front)
{
int c = 0;
while(dist<m_Distance && c<static_cast<int>(fib->size())-1)
{
dist += m_Parameters->GetStepSizeMm();
vnl_vector_fixed< float, 3 > v = fib->at(static_cast<unsigned int>(c));
if (dot_product(v,meanV)<0)
v = -v;
vectors.push_back(v);
meanV += v;
c++;
}
}
else
{
int c = static_cast<int>(fib->size())-1;
while(dist<m_Distance && c>=0)
{
dist += m_Parameters->GetStepSizeMm();
vnl_vector_fixed< float, 3 > v = fib->at(static_cast<unsigned int>(c));
if (dot_product(v,meanV)<0)
v = -v;
vectors.push_back(v);
meanV += v;
c--;
}
}
meanV.normalize();
for (unsigned int c=0; c<vectors.size(); c++)
{
float angle = std::fabs(dot_product(meanV, vectors.at(c)));
if (angle>1.0f)
angle = 1.0;
dev += acos(angle)*180.0f/static_cast<float>(itk::Math::pi);
}
if (vectors.size()>0)
dev /= vectors.size();
return dev;
}
std::shared_ptr<mitk::StreamlineTractographyParameters> StreamlineTrackingFilter::GetParameters() const
{
return m_Parameters;
}
void StreamlineTrackingFilter::SetParameters(std::shared_ptr< mitk::StreamlineTractographyParameters > Parameters)
{
m_Parameters = Parameters;
}
void StreamlineTrackingFilter::SetTrackingPriorHandler(mitk::TrackingDataHandler *TrackingPriorHandler)
{
m_TrackingPriorHandler = TrackingPriorHandler;
}
void StreamlineTrackingFilter::GetSeedPointsFromSeedImage()
{
MITK_INFO << "StreamlineTracking - Calculating seed points.";
m_SeedPoints.clear();
typedef ImageRegionConstIterator< ItkFloatImgType > MaskIteratorType;
MaskIteratorType sit(m_SeedImage, m_SeedImage->GetLargestPossibleRegion());
sit.GoToBegin();
while (!sit.IsAtEnd())
{
if (sit.Value()>0)
{
ItkFloatImgType::IndexType index = sit.GetIndex();
itk::ContinuousIndex<float, 3> start;
start[0] = index[0];
start[1] = index[1];
start[2] = index[2];
itk::Point<float> worldPos;
m_SeedImage->TransformContinuousIndexToPhysicalPoint(start, worldPos);
if ( mitk::imv::IsInsideMask<float>(worldPos, m_Parameters->m_InterpolateRoiImages, m_MaskInterpolator) )
{
m_SeedPoints.push_back(worldPos);
for (unsigned int s = 1; s < m_Parameters->m_SeedsPerVoxel; s++)
{
start[0] = index[0] + static_cast<float>(m_TrackingHandler->GetRandDouble(-0.5, 0.5));
start[1] = index[1] + static_cast<float>(m_TrackingHandler->GetRandDouble(-0.5, 0.5));
start[2] = index[2] + static_cast<float>(m_TrackingHandler->GetRandDouble(-0.5, 0.5));
itk::Point<float> worldPos;
m_SeedImage->TransformContinuousIndexToPhysicalPoint(start, worldPos);
m_SeedPoints.push_back(worldPos);
}
}
}
++sit;
}
if (m_SeedPoints.empty())
mitkThrow() << "No valid seed point in seed image! Is your seed image registered with the image you are tracking on?";
}
void StreamlineTrackingFilter::GenerateData()
{
this->BeforeTracking();
if (!m_Parameters->m_FixRandomSeed)
std::random_shuffle(m_SeedPoints.begin(), m_SeedPoints.end());
m_CurrentTracts = 0;
int num_seeds = static_cast<int>(m_SeedPoints.size());
itk::Index<3> zeroIndex; zeroIndex.Fill(0);
m_Progress = 0;
int i = 0;
int print_interval = num_seeds/100;
if (print_interval<100)
m_Verbose=false;
unsigned int trials_per_seed = 1;
if(m_Parameters->m_Mode==mitk::TrackingDataHandler::MODE::PROBABILISTIC)
trials_per_seed = m_Parameters->m_TrialsPerSeed;
#pragma omp parallel
while (i<num_seeds && !m_StopTracking)
{
int temp_i = 0;
#pragma omp critical
{
temp_i = i;
i++;
}
if (temp_i>=num_seeds || m_StopTracking)
continue;
else if (m_Verbose && i%print_interval==0)
#pragma omp critical
{
m_Progress += static_cast<unsigned int>(print_interval);
std::cout << " \r";
if (m_Parameters->m_MaxNumFibers>0)
std::cout << "Tried: " << m_Progress << "/" << num_seeds << " | Accepted: " << m_CurrentTracts << "/" << m_Parameters->m_MaxNumFibers << '\r';
else
std::cout << "Tried: " << m_Progress << "/" << num_seeds << " | Accepted: " << m_CurrentTracts << '\r';
cout.flush();
}
const itk::Point<float> worldPos = m_SeedPoints.at(static_cast<unsigned int>(temp_i));
for (unsigned int trials=0; trials<trials_per_seed; ++trials)
{
FiberType fib;
DirectionContainer direction_container;
float tractLength = 0;
unsigned long counter = 0;
// get starting direction
vnl_vector_fixed<float,3> dir; dir.fill(0.0);
std::deque< vnl_vector_fixed<float,3> > olddirs;
dir = GetNewDirection(worldPos, olddirs, zeroIndex) * 0.5f;
bool exclude = false;
if (m_ExclusionRegions.IsNotNull() && mitk::imv::IsInsideMask<float>(worldPos, m_Parameters->m_InterpolateRoiImages, m_ExclusionInterpolator))
exclude = true;
bool success = false;
if (dir.magnitude()>0.0001f && !exclude)
{
// forward tracking
tractLength = FollowStreamline(worldPos, dir, &fib, &direction_container, 0, false, exclude);
fib.push_front(worldPos);
// backward tracking
if (!exclude)
tractLength = FollowStreamline(worldPos, -dir, &fib, &direction_container, tractLength, true, exclude);
counter = fib.size();
if (tractLength>=m_Parameters->m_MinTractLengthMm && counter>=2 && !exclude)
{
#pragma omp critical
if ( IsValidFiber(&fib) )
{
if (!m_StopTracking)
{
if (!m_Parameters->m_OutputProbMap)
m_Tractogram.push_back(fib);
else
FiberToProbmap(&fib);
m_CurrentTracts++;
success = true;
}
if (m_Parameters->m_MaxNumFibers > 0 && m_CurrentTracts>=static_cast<unsigned int>(m_Parameters->m_MaxNumFibers))
{
if (!m_StopTracking)
{
std::cout << " \r";
MITK_INFO << "Reconstructed maximum number of tracts (" << m_CurrentTracts << "). Stopping tractography.";
}
m_StopTracking = true;
}
}
}
}
if (success || m_Parameters->m_Mode!=MODE::PROBABILISTIC)
break; // we only try one seed point multiple times if we use a probabilistic tracker and have not found a valid streamline yet
}// trials per seed
}// seed points
this->AfterTracking();
}
bool StreamlineTrackingFilter::IsValidFiber(FiberType* fib)
{
if (m_Parameters->m_EpConstraints==EndpointConstraints::NONE)
{
return true;
}
else if (m_Parameters->m_EpConstraints==EndpointConstraints::EPS_IN_TARGET)
{
if (m_TargetImageSet)
{
if ( mitk::imv::IsInsideMask<float>(fib->front(), m_Parameters->m_InterpolateRoiImages, m_TargetInterpolator)
&& mitk::imv::IsInsideMask<float>(fib->back(), m_Parameters->m_InterpolateRoiImages, m_TargetInterpolator) )
return true;
return false;
}
else
mitkThrow() << "No target image set but endpoint constraint EPS_IN_TARGET chosen!";
}
else if (m_Parameters->m_EpConstraints==EndpointConstraints::EPS_IN_TARGET_LABELDIFF)
{
if (m_TargetImageSet)
{
float v1 = mitk::imv::GetImageValue<float>(fib->front(), false, m_TargetInterpolator);
float v2 = mitk::imv::GetImageValue<float>(fib->back(), false, m_TargetInterpolator);
if ( v1>0.0f && v2>0.0f && v1!=v2 )
return true;
return false;
}
else
mitkThrow() << "No target image set but endpoint constraint EPS_IN_TARGET_LABELDIFF chosen!";
}
else if (m_Parameters->m_EpConstraints==EndpointConstraints::EPS_IN_SEED_AND_TARGET)
{
if (m_TargetImageSet && m_SeedImageSet)
{
if ( mitk::imv::IsInsideMask<float>(fib->front(), m_Parameters->m_InterpolateRoiImages, m_SeedInterpolator)
&& mitk::imv::IsInsideMask<float>(fib->back(), m_Parameters->m_InterpolateRoiImages, m_TargetInterpolator) )
return true;
if ( mitk::imv::IsInsideMask<float>(fib->back(), m_Parameters->m_InterpolateRoiImages, m_SeedInterpolator)
&& mitk::imv::IsInsideMask<float>(fib->front(), m_Parameters->m_InterpolateRoiImages, m_TargetInterpolator) )
return true;
return false;
}
else
mitkThrow() << "No target or seed image set but endpoint constraint EPS_IN_SEED_AND_TARGET chosen!";
}
else if (m_Parameters->m_EpConstraints==EndpointConstraints::MIN_ONE_EP_IN_TARGET)
{
if (m_TargetImageSet)
{
if ( mitk::imv::IsInsideMask<float>(fib->front(), m_Parameters->m_InterpolateRoiImages, m_TargetInterpolator)
|| mitk::imv::IsInsideMask<float>(fib->back(), m_Parameters->m_InterpolateRoiImages, m_TargetInterpolator) )
return true;
return false;
}
else
mitkThrow() << "No target image set but endpoint constraint MIN_ONE_EP_IN_TARGET chosen!";
}
else if (m_Parameters->m_EpConstraints==EndpointConstraints::ONE_EP_IN_TARGET)
{
if (m_TargetImageSet)
{
if ( mitk::imv::IsInsideMask<float>(fib->front(), m_Parameters->m_InterpolateRoiImages, m_TargetInterpolator)
&& !mitk::imv::IsInsideMask<float>(fib->back(), m_Parameters->m_InterpolateRoiImages, m_TargetInterpolator) )
return true;
if ( !mitk::imv::IsInsideMask<float>(fib->back(), m_Parameters->m_InterpolateRoiImages, m_TargetInterpolator)
&& mitk::imv::IsInsideMask<float>(fib->front(), m_Parameters->m_InterpolateRoiImages, m_TargetInterpolator) )
return true;
return false;
}
else
mitkThrow() << "No target image set but endpoint constraint ONE_EP_IN_TARGET chosen!";
}
else if (m_Parameters->m_EpConstraints==EndpointConstraints::NO_EP_IN_TARGET)
{
if (m_TargetImageSet)
{
if ( mitk::imv::IsInsideMask<float>(fib->front(), m_Parameters->m_InterpolateRoiImages, m_TargetInterpolator)
|| mitk::imv::IsInsideMask<float>(fib->back(), m_Parameters->m_InterpolateRoiImages, m_TargetInterpolator) )
return false;
return true;
}
else
mitkThrow() << "No target image set but endpoint constraint NO_EP_IN_TARGET chosen!";
}
return true;
}
void StreamlineTrackingFilter::FiberToProbmap(FiberType* fib)
{
ItkDoubleImgType::IndexType last_idx; last_idx.Fill(0);
for (auto p : *fib)
{
ItkDoubleImgType::IndexType idx;
m_OutputProbabilityMap->TransformPhysicalPointToIndex(p, idx);
if (idx != last_idx)
{
if (m_OutputProbabilityMap->GetLargestPossibleRegion().IsInside(idx))
m_OutputProbabilityMap->SetPixel(idx, m_OutputProbabilityMap->GetPixel(idx)+1);
last_idx = idx;
}
}
}
void StreamlineTrackingFilter::BuildFibers(bool check)
{
if (m_BuildFibersReady<omp_get_num_threads() && check)
return;
m_FiberPolyData = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkCellArray> vNewLines = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkPoints> vNewPoints = vtkSmartPointer<vtkPoints>::New();
for (unsigned int i=0; i<m_Tractogram.size(); i++)
{
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
FiberType fib = m_Tractogram.at(i);
for (FiberType::iterator it = fib.begin(); it!=fib.end(); ++it)
{
vtkIdType id = vNewPoints->InsertNextPoint((*it).GetDataPointer());
container->GetPointIds()->InsertNextId(id);
}
vNewLines->InsertNextCell(container);
}
if (check)
for (int i=0; i<m_BuildFibersReady; i++)
m_Tractogram.pop_back();
m_BuildFibersReady = 0;
m_FiberPolyData->SetPoints(vNewPoints);
m_FiberPolyData->SetLines(vNewLines);
m_BuildFibersFinished = true;
}
void StreamlineTrackingFilter::AfterTracking()
{
if (m_Verbose)
std::cout << " \r";
if (!m_Parameters->m_OutputProbMap)
{
MITK_INFO << "Reconstructed " << m_Tractogram.size() << " fibers.";
MITK_INFO << "Generating polydata ";
BuildFibers(false);
}
else
{
itk::RescaleIntensityImageFilter< ItkDoubleImgType, ItkDoubleImgType >::Pointer filter = itk::RescaleIntensityImageFilter< ItkDoubleImgType, ItkDoubleImgType >::New();
filter->SetInput(m_OutputProbabilityMap);
filter->SetOutputMaximum(1.0);
filter->SetOutputMinimum(0.0);
filter->Update();
m_OutputProbabilityMap = filter->GetOutput();
}
MITK_INFO << "done";
m_EndTime = std::chrono::system_clock::now();
std::chrono::hours hh = std::chrono::duration_cast<std::chrono::hours>(m_EndTime - m_StartTime);
std::chrono::minutes mm = std::chrono::duration_cast<std::chrono::minutes>(m_EndTime - m_StartTime);
std::chrono::seconds ss = std::chrono::duration_cast<std::chrono::seconds>(m_EndTime - m_StartTime);
mm %= 60;
ss %= 60;
MITK_INFO << "Tracking took " << hh.count() << "h, " << mm.count() << "m and " << ss.count() << "s";
m_SeedPoints.clear();
}
void StreamlineTrackingFilter::SetDicomProperties(mitk::FiberBundle::Pointer fib)
{
std::string model_code_value = "-";
std::string model_code_meaning = "-";
std::string algo_code_value = "-";
std::string algo_code_meaning = "-";
if ( m_Parameters->m_Mode==MODE::DETERMINISTIC && dynamic_cast<mitk::TrackingHandlerTensor*>(m_TrackingHandler) && !m_Parameters->m_InterpolateTractographyData)
{
algo_code_value = "sup181_ee04";
algo_code_meaning = "FACT";
}
else if (m_Parameters->m_Mode==MODE::DETERMINISTIC)
{
algo_code_value = "sup181_ee01";
algo_code_meaning = "Deterministic";
}
else if (m_Parameters->m_Mode==MODE::PROBABILISTIC)
{
algo_code_value = "sup181_ee02";
algo_code_meaning = "Probabilistic";
}
if (dynamic_cast<mitk::TrackingHandlerTensor*>(m_TrackingHandler) || (dynamic_cast<mitk::TrackingHandlerOdf*>(m_TrackingHandler) && dynamic_cast<mitk::TrackingHandlerOdf*>(m_TrackingHandler)->GetIsOdfFromTensor() ) )
{
if ( dynamic_cast<mitk::TrackingHandlerTensor*>(m_TrackingHandler) && dynamic_cast<mitk::TrackingHandlerTensor*>(m_TrackingHandler)->GetNumTensorImages()>1 )
{
model_code_value = "sup181_bb02";
model_code_meaning = "Multi Tensor";
}
else
{
model_code_value = "sup181_bb01";
model_code_meaning = "Single Tensor";
}
}
else if (dynamic_cast<mitk::TrackingHandlerRandomForest<6, 28>*>(m_TrackingHandler) || dynamic_cast<mitk::TrackingHandlerRandomForest<6, 100>*>(m_TrackingHandler))
{
model_code_value = "sup181_bb03";
model_code_meaning = "Model Free";
}
else if (dynamic_cast<mitk::TrackingHandlerOdf*>(m_TrackingHandler))
{
model_code_value = "-";
model_code_meaning = "ODF";
}
else if (dynamic_cast<mitk::TrackingHandlerPeaks*>(m_TrackingHandler))
{
model_code_value = "-";
model_code_meaning = "Peaks";
}
fib->SetProperty("DICOM.anatomy.value", mitk::StringProperty::New("T-A0095"));
fib->SetProperty("DICOM.anatomy.meaning", mitk::StringProperty::New("White matter of brain and spinal cord"));
fib->SetProperty("DICOM.algo_code.value", mitk::StringProperty::New(algo_code_value));
fib->SetProperty("DICOM.algo_code.meaning", mitk::StringProperty::New(algo_code_meaning));
fib->SetProperty("DICOM.model_code.value", mitk::StringProperty::New(model_code_value));
fib->SetProperty("DICOM.model_code.meaning", mitk::StringProperty::New(model_code_meaning));
}
}
diff --git a/Modules/FiberTracking/Algorithms/itkStreamlineTrackingFilter.h b/Modules/FiberTracking/Algorithms/itkStreamlineTrackingFilter.h
index dab8157..0c7586f 100644
--- a/Modules/FiberTracking/Algorithms/itkStreamlineTrackingFilter.h
+++ b/Modules/FiberTracking/Algorithms/itkStreamlineTrackingFilter.h
@@ -1,195 +1,195 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkMLBSTrackingFilter_h_
#define __itkMLBSTrackingFilter_h_
#include <itkImageToImageFilter.h>
#include <itkVectorContainer.h>
#include <itkVectorImage.h>
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkCellArray.h>
#include <vtkPoints.h>
#include <vtkPolyLine.h>
#include <vtkCleanPolyData.h>
#include <itkOrientationDistributionFunction.h>
#include <itkMersenneTwisterRandomVariateGenerator.h>
#include <itkAnalyticalDiffusionQballReconstructionImageFilter.h>
#include <itkSimpleFastMutexLock.h>
#include <mitkDiffusionPropertyHelper.h>
#include <mitkPointSet.h>
#include <chrono>
#include <TrackingHandlers/mitkTrackingDataHandler.h>
#include <MitkFiberTrackingExports.h>
#include <mitkFiberBundle.h>
#include <mitkPeakImage.h>
#include <mitkStreamlineTractographyParameters.h>
namespace itk{
/**
* \brief Performs streamline tracking on the input image. Depending on the tracking handler this can be a tensor, peak or machine learning based tracking. */
class MITKFIBERTRACKING_EXPORT StreamlineTrackingFilter : public ProcessObject
{
public:
typedef StreamlineTrackingFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ProcessObject Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(MLBSTrackingFilter, ImageToImageFilter)
typedef itk::Image<unsigned char, 3> ItkUcharImgType;
typedef itk::Image<unsigned int, 3> ItkUintImgType;
typedef itk::Image<double, 3> ItkDoubleImgType;
typedef itk::Image<float, 3> ItkFloatImgType;
typedef vtkSmartPointer< vtkPolyData > PolyDataType;
typedef mitk::StreamlineTractographyParameters::EndpointConstraints EndpointConstraints;
typedef mitk::StreamlineTractographyParameters::MODE MODE;
typedef std::deque< vnl_vector_fixed<float,3> > DirectionContainer;
typedef std::deque< itk::Point<float> > FiberType;
typedef std::vector< FiberType > BundleType;
volatile bool m_PauseTracking;
bool m_AbortTracking;
bool m_BuildFibersFinished;
int m_BuildFibersReady;
volatile bool m_Stop;
mitk::PointSet::Pointer m_SamplingPointset;
mitk::PointSet::Pointer m_StopVotePointset;
mitk::PointSet::Pointer m_AlternativePointset;
void SetDicomProperties(mitk::FiberBundle::Pointer fib);
itkGetMacro( OutputProbabilityMap, ItkDoubleImgType::Pointer) ///< Output probability map
itkGetMacro( FiberPolyData, PolyDataType ) ///< Output fibers
itkSetMacro( SeedImage, ItkFloatImgType::Pointer) ///< Seeds are only placed inside of this mask.
itkSetMacro( MaskImage, ItkFloatImgType::Pointer) ///< Tracking is only performed inside of this mask image.
itkSetMacro( ExclusionRegions, ItkFloatImgType::Pointer)///< Fibers passing any of the ROIs in this image are discarded.
itkSetMacro( StoppingRegions, ItkFloatImgType::Pointer) ///< Streamlines entering a stopping region will stop immediately
itkSetMacro( TargetRegions, ItkFloatImgType::Pointer) ///< Only streamline starting and ending in this mask are retained
itkSetMacro( DemoMode, bool )
itkSetMacro( Verbose, bool ) ///< If true, output tracking progress (might be slower)
itkSetMacro( StopTracking, bool )
///< Use manually defined points in physical space as seed points instead of seed image
void SetSeedPoints( const std::vector< itk::Point<float> >& sP) {
m_SeedPoints = sP;
}
void SetTrackingHandler( mitk::TrackingDataHandler* h ) ///<
{
m_TrackingHandler = h;
}
void Update() override{
this->GenerateData();
}
std::string GetStatusText();
void SetTrackingPriorHandler(mitk::TrackingDataHandler *TrackingPriorHandler);
std::shared_ptr< mitk::StreamlineTractographyParameters > GetParameters() const;
void SetParameters(std::shared_ptr< mitk::StreamlineTractographyParameters > Parameters);
protected:
void GenerateData() override;
StreamlineTrackingFilter();
~StreamlineTrackingFilter() override {}
bool IsValidFiber(FiberType* fib); ///< Check endpoints
void FiberToProbmap(FiberType* fib);
void GetSeedPointsFromSeedImage();
void CalculateNewPosition(itk::Point<float, 3>& pos, vnl_vector_fixed<float,3>& dir); ///< Calculate next integration step.
float FollowStreamline(itk::Point<float, 3> start_pos, vnl_vector_fixed<float,3> dir, FiberType* fib, DirectionContainer* container, float tractLength, bool front, bool& exclude); ///< Start streamline in one direction.
vnl_vector_fixed<float,3> GetNewDirection(const itk::Point<float, 3>& pos, std::deque< vnl_vector_fixed<float,3> >& olddirs, itk::Index<3>& oldIndex); ///< Determine new direction by sample voting at the current position taking the last progression direction into account.
std::vector< vnl_vector_fixed<float,3> > CreateDirections(unsigned int NPoints);
void BeforeTracking();
void AfterTracking();
PolyDataType m_FiberPolyData;
vtkSmartPointer<vtkPoints> m_Points;
vtkSmartPointer<vtkCellArray> m_Cells;
BundleType m_Tractogram;
BundleType m_GmStubs;
ItkFloatImgType::Pointer m_StoppingRegions;
ItkFloatImgType::Pointer m_TargetRegions;
ItkFloatImgType::Pointer m_SeedImage;
ItkFloatImgType::Pointer m_MaskImage;
ItkFloatImgType::Pointer m_ExclusionRegions;
ItkDoubleImgType::Pointer m_OutputProbabilityMap;
bool m_Verbose;
bool m_DemoMode;
std::vector< itk::Point<float> > m_SeedPoints;
unsigned int m_CurrentTracts;
unsigned int m_Progress;
bool m_StopTracking;
void BuildFibers(bool check);
float CheckCurvature(DirectionContainer *fib, bool front);
// decision forest
mitk::TrackingDataHandler* m_TrackingHandler;
std::vector< PolyDataType > m_PolyDataContainer;
std::chrono::time_point<std::chrono::system_clock> m_StartTime;
std::chrono::time_point<std::chrono::system_clock> m_EndTime;
itk::LinearInterpolateImageFunction< ItkFloatImgType, float >::Pointer m_MaskInterpolator;
itk::LinearInterpolateImageFunction< ItkFloatImgType, float >::Pointer m_StopInterpolator;
itk::LinearInterpolateImageFunction< ItkFloatImgType, float >::Pointer m_TargetInterpolator;
itk::LinearInterpolateImageFunction< ItkFloatImgType, float >::Pointer m_SeedInterpolator;
itk::LinearInterpolateImageFunction< ItkFloatImgType, float >::Pointer m_ExclusionInterpolator;
bool m_SeedImageSet;
bool m_TargetImageSet;
std::shared_ptr< mitk::StreamlineTractographyParameters > m_Parameters;
// Directional priors
mitk::TrackingDataHandler* m_TrackingPriorHandler;
private:
};
}
//#ifndef ITK_MANUAL_INSTANTIATION
//#include "itkMLBSTrackingFilter.cpp"
//#endif
#endif //__itkMLBSTrackingFilter_h_
diff --git a/Modules/FiberTracking/Algorithms/itkTdiToVolumeFractionFilter.cpp b/Modules/FiberTracking/Algorithms/itkTdiToVolumeFractionFilter.cpp
index d707c70..97af599 100644
--- a/Modules/FiberTracking/Algorithms/itkTdiToVolumeFractionFilter.cpp
+++ b/Modules/FiberTracking/Algorithms/itkTdiToVolumeFractionFilter.cpp
@@ -1,156 +1,156 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkTdiToVolumeFractionFilter_txx
#define __itkTdiToVolumeFractionFilter_txx
#include "itkTdiToVolumeFractionFilter.h"
#include <itkImageRegionConstIterator.h>
#include <itkImageRegionConstIteratorWithIndex.h>
#include <itkImageRegionIterator.h>
#include <math.h>
namespace itk {
template< class TPixelType >
TdiToVolumeFractionFilter< TPixelType >::TdiToVolumeFractionFilter()
: m_TdiThreshold(0.3)
, m_Sqrt(1.0)
{
this->SetNumberOfRequiredInputs(5);
this->SetNumberOfRequiredOutputs(4);
}
template< class TPixelType >
void TdiToVolumeFractionFilter< TPixelType >::BeforeThreadedGenerateData()
{
typename InputImageType::Pointer input_tdi = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
for (int i=0; i<4; ++i)
{
typename OutputImageType::Pointer outputImage = OutputImageType::New();
outputImage->SetOrigin( input_tdi->GetOrigin() );
outputImage->SetRegions( input_tdi->GetLargestPossibleRegion() );
outputImage->SetSpacing( input_tdi->GetSpacing() );
outputImage->SetDirection( input_tdi->GetDirection() );
outputImage->Allocate();
outputImage->FillBuffer(0.0);
this->SetNthOutput(i, outputImage);
}
}
template< class TPixelType >
void TdiToVolumeFractionFilter< TPixelType >::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, ThreadIdType)
{
typename OutputImageType::Pointer o_intra_ax = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0));
typename OutputImageType::Pointer o_inter_ax = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(1));
typename OutputImageType::Pointer o_gray_matter = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(2));
typename OutputImageType::Pointer o_csf = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(3));
ImageRegionIterator< OutputImageType > oit0(o_intra_ax, outputRegionForThread);
ImageRegionIterator< OutputImageType > oit1(o_inter_ax, outputRegionForThread);
ImageRegionIterator< OutputImageType > oit2(o_gray_matter, outputRegionForThread);
ImageRegionIterator< OutputImageType > oit3(o_csf, outputRegionForThread);
typename InputImageType::Pointer i_wm = static_cast< InputImageType * >(this->ProcessObject::GetInput(1));
typename InputImageType::Pointer i_gm = static_cast< InputImageType * >(this->ProcessObject::GetInput(2));
typename InputImageType::Pointer i_dgm = static_cast< InputImageType * >(this->ProcessObject::GetInput(3));
typename InputImageType::Pointer i_csf = static_cast< InputImageType * >(this->ProcessObject::GetInput(4));
ImageRegionIterator< OutputImageType > iit0(i_wm, outputRegionForThread);
ImageRegionIterator< OutputImageType > iit1(i_gm, outputRegionForThread);
ImageRegionIterator< OutputImageType > iit2(i_dgm, outputRegionForThread);
ImageRegionIterator< OutputImageType > iit3(i_csf, outputRegionForThread);
typename InputImageType::Pointer input_tdi = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
ImageRegionConstIterator< InputImageType > tdi_it(input_tdi, outputRegionForThread);
while( !tdi_it.IsAtEnd() )
{
TPixelType intra_ax_val = tdi_it.Get();
intra_ax_val = std::pow(intra_ax_val, 1.0/m_Sqrt);
if (intra_ax_val>m_TdiThreshold)
intra_ax_val = m_TdiThreshold;
intra_ax_val /= m_TdiThreshold;
if (intra_ax_val<0)
intra_ax_val = 0;
TPixelType inter_ax_val = 0.0;
TPixelType wm_val = iit0.Get();
TPixelType gm_val = iit1.Get();
TPixelType dgm_val = iit2.Get();
TPixelType csf_val = iit3.Get();
if (dgm_val>0)
{
TPixelType ex = 1.0 - intra_ax_val;
gm_val += dgm_val * ex;
}
if (intra_ax_val < 0.0001 && wm_val > 0.0001)
{
if (csf_val+gm_val == 0 )
gm_val += wm_val;
else
{
if (csf_val>gm_val)
csf_val += wm_val;
else
gm_val += wm_val;
}
}
else if ( intra_ax_val>0.0001 )
{
auto comp_sum = csf_val+gm_val+intra_ax_val;
if (comp_sum<1.0)
inter_ax_val = 1.0 - comp_sum;
else if (comp_sum>1)
intra_ax_val = 1.0 - (csf_val+gm_val);
if (intra_ax_val<-0.01)
MITK_INFO << "Corrupted volume fraction. intra_ax_val=" << intra_ax_val;
if (intra_ax_val<0)
intra_ax_val = 0;
}
auto comp_sum = csf_val+gm_val+intra_ax_val+inter_ax_val;
if (std::fabs(comp_sum-1.0)>0.00001 && comp_sum > 0.0001)
{
csf_val /= comp_sum;
gm_val /= comp_sum;
intra_ax_val /= comp_sum;
inter_ax_val /= comp_sum;
}
oit0.Set(intra_ax_val);
oit1.Set(inter_ax_val);
oit2.Set(gm_val);
oit3.Set(csf_val);
++tdi_it;
++iit0;
++iit1;
++iit2;
++iit3;
++oit0;
++oit1;
++oit2;
++oit3;
}
}
}
#endif
diff --git a/Modules/FiberTracking/Algorithms/itkTdiToVolumeFractionFilter.h b/Modules/FiberTracking/Algorithms/itkTdiToVolumeFractionFilter.h
index f16d1ab..cef9aca 100644
--- a/Modules/FiberTracking/Algorithms/itkTdiToVolumeFractionFilter.h
+++ b/Modules/FiberTracking/Algorithms/itkTdiToVolumeFractionFilter.h
@@ -1,78 +1,78 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*===================================================================
This file is based heavily on a corresponding ITK filter.
===================================================================*/
#ifndef __itkTdiToVolumeFractionFilter_h_
#define __itkTdiToVolumeFractionFilter_h_
#include <MitkFiberTrackingExports.h>
#include <itkImageToImageFilter.h>
namespace itk{
/**
* \brief */
template< class TPixelType >
class TdiToVolumeFractionFilter : public ImageToImageFilter< Image< TPixelType, 3 >, Image< TPixelType, 3 > >
{
public:
typedef TdiToVolumeFractionFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< Image< TPixelType, 3 >, Image< TPixelType, 3 > > Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(TdiToVolumeFractionFilter, ImageToImageFilter)
typedef typename Superclass::InputImageType InputImageType;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename Superclass::OutputImageRegionType OutputImageRegionType;
itkSetMacro( TdiThreshold, TPixelType )
itkSetMacro( Sqrt, TPixelType )
protected:
TdiToVolumeFractionFilter();
~TdiToVolumeFractionFilter() override {}
void BeforeThreadedGenerateData() override;
void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType threadId) override;
private:
TPixelType m_TdiThreshold;
TPixelType m_Sqrt;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkTdiToVolumeFractionFilter.cpp"
#endif
#endif //__itkTdiToVolumeFractionFilter_h_
diff --git a/Modules/FiberTracking/Algorithms/itkTractClusteringFilter.cpp b/Modules/FiberTracking/Algorithms/itkTractClusteringFilter.cpp
index 9871933..38318b1 100644
--- a/Modules/FiberTracking/Algorithms/itkTractClusteringFilter.cpp
+++ b/Modules/FiberTracking/Algorithms/itkTractClusteringFilter.cpp
@@ -1,558 +1,558 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "itkTractClusteringFilter.h"
#define _USE_MATH_DEFINES
#include <math.h>
#include <boost/progress.hpp>
#include <vnl/vnl_sparse_matrix.h>
namespace itk{
TractClusteringFilter::TractClusteringFilter()
: m_NumPoints(12)
, m_InCentroids(nullptr)
, m_MinClusterSize(1)
, m_MaxClusters(0)
, m_MergeDuplicateThreshold(-1)
, m_DoResampling(true)
, m_FilterMask(nullptr)
, m_OverlapThreshold(0.0)
{
}
TractClusteringFilter::~TractClusteringFilter()
{
for (auto m : m_Metrics)
delete m;
}
std::vector<std::vector<unsigned int> > TractClusteringFilter::GetOutFiberIndices() const
{
return m_OutFiberIndices;
}
void TractClusteringFilter::SetMetrics(const std::vector<mitk::ClusteringMetric *> &Metrics)
{
m_Metrics = Metrics;
}
std::vector<TractClusteringFilter::Cluster> TractClusteringFilter::GetOutClusters() const
{
return m_OutClusters;
}
std::vector<mitk::FiberBundle::Pointer> TractClusteringFilter::GetOutCentroids() const
{
return m_OutCentroids;
}
std::vector<mitk::FiberBundle::Pointer> TractClusteringFilter::GetOutTractograms() const
{
return m_OutTractograms;
}
void TractClusteringFilter::SetDistances(const std::vector<float> &Distances)
{
m_Distances = Distances;
}
float TractClusteringFilter::CalcOverlap(vnl_matrix<float>& t)
{
float overlap = 0;
if (m_FilterMask.IsNotNull())
{
for (unsigned int i=0; i<m_NumPoints; ++i)
{
vnl_vector<float> p = t.get_column(i);
itk::Point<float,3> point;
point[0] = p[0];
point[1] = p[1];
point[2] = p[2];
itk::Index<3> idx;
m_FilterMask->TransformPhysicalPointToIndex(point, idx);
if (m_FilterMask->GetLargestPossibleRegion().IsInside(idx) && m_FilterMask->GetPixel(idx)>0)
overlap += 1;
}
overlap /= m_NumPoints;
}
else
return 1.0;
return overlap;
}
std::vector<vnl_matrix<float> > TractClusteringFilter::ResampleFibers(mitk::FiberBundle::Pointer tractogram)
{
mitk::FiberBundle::Pointer temp_fib = tractogram->GetDeepCopy();
if (m_DoResampling)
temp_fib->ResampleToNumPoints(m_NumPoints);
std::vector< vnl_matrix<float> > out_fib;
for (int i=0; i<temp_fib->GetFiberPolyData()->GetNumberOfCells(); i++)
{
vtkCell* cell = temp_fib->GetFiberPolyData()->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vnl_matrix<float> streamline;
streamline.set_size(3, m_NumPoints);
streamline.fill(0.0);
for (int j=0; j<numPoints; j++)
{
double cand[3];
points->GetPoint(j, cand);
vnl_vector_fixed< float, 3 > candV;
candV[0]=cand[0]; candV[1]=cand[1]; candV[2]=cand[2];
streamline.set_column(j, candV);
}
out_fib.push_back(streamline);
}
return out_fib;
}
std::vector< TractClusteringFilter::Cluster > TractClusteringFilter::ClusterStep(std::vector< unsigned int > f_indices, std::vector<float> distances)
{
float dist_thres = distances.back();
distances.pop_back();
std::vector< Cluster > C;
int N = f_indices.size();
Cluster c1;
c1.I.push_back(f_indices.at(0));
c1.h = T[f_indices.at(0)];
c1.n = 1;
C.push_back(c1);
if (f_indices.size()==1)
return C;
for (int i=1; i<N; ++i)
{
vnl_matrix<float> t = T.at(f_indices.at(i));
int min_cluster_index = -1;
float min_cluster_distance = 99999;
bool flip = false;
for (unsigned int k=0; k<C.size(); ++k)
{
vnl_matrix<float> v = C.at(k).h / C.at(k).n;
bool f = false;
float d = 0;
for (auto m : m_Metrics)
d += m->CalculateDistance(t, v, f);
d /= m_Metrics.size();
if (d<min_cluster_distance)
{
min_cluster_distance = d;
min_cluster_index = k;
flip = f;
}
}
if (min_cluster_index>=0 && min_cluster_distance<dist_thres)
{
C[min_cluster_index].I.push_back(f_indices.at(i));
if (!flip)
C[min_cluster_index].h += t;
else
C[min_cluster_index].h += t.fliplr();
C[min_cluster_index].n += 1;
}
else
{
Cluster c;
c.I.push_back(f_indices.at(i));
c.h = t;
c.n = 1;
C.push_back(c);
}
}
if (!distances.empty())
{
std::vector< Cluster > outC;
#pragma omp parallel for
for (int c=0; c<(int)C.size(); c++)
{
std::vector< Cluster > tempC = ClusterStep(C.at(c).I, distances);
#pragma omp critical
AppendCluster(outC, tempC);
}
return outC;
}
else
return C;
}
void TractClusteringFilter::AppendCluster(std::vector< Cluster >& a, std::vector< Cluster >&b)
{
for (auto c : b)
a.push_back(c);
}
std::vector< TractClusteringFilter::Cluster > TractClusteringFilter::MergeDuplicateClusters2(std::vector< TractClusteringFilter::Cluster >& clusters)
{
if (m_MergeDuplicateThreshold<0)
m_MergeDuplicateThreshold = m_Distances.at(0)/2;
else if (m_MergeDuplicateThreshold==0)
return clusters;
MITK_INFO << "Merging duplicate clusters with distance threshold " << m_MergeDuplicateThreshold;
std::vector< TractClusteringFilter::Cluster > new_clusters;
for (Cluster c1 : clusters)
{
vnl_matrix<float> t = c1.h / c1.n;
int min_idx = -1;
float min_d = 99999;
bool flip = false;
#pragma omp parallel for
for (int k2=0; k2<(int)new_clusters.size(); ++k2)
{
Cluster c2 = new_clusters.at(k2);
vnl_matrix<float> v = c2.h / c2.n;
bool f = false;
float d = 0;
for (auto m : m_Metrics)
d += m->CalculateDistance(t, v, f);
d /= m_Metrics.size();
#pragma omp critical
if (d<min_d && d<m_MergeDuplicateThreshold)
{
min_d = d;
min_idx = k2;
flip = f;
}
}
if (min_idx<0)
new_clusters.push_back(c1);
else
{
for (int i=0; i<c1.n; ++i)
{
new_clusters[min_idx].I.push_back(c1.I.at(i));
new_clusters[min_idx].n += 1;
}
if (!flip)
new_clusters[min_idx].h += c1.h;
else
new_clusters[min_idx].h += c1.h.fliplr();
}
}
MITK_INFO << "\nNumber of clusters after merging duplicates: " << new_clusters.size();
return new_clusters;
}
void TractClusteringFilter::MergeDuplicateClusters(std::vector< TractClusteringFilter::Cluster >& clusters)
{
if (m_MergeDuplicateThreshold<0)
m_MergeDuplicateThreshold = m_Distances.at(0)/2;
bool found = true;
MITK_INFO << "Merging duplicate clusters with distance threshold " << m_MergeDuplicateThreshold;
int start = 0;
while (found && m_MergeDuplicateThreshold>mitk::eps)
{
std::cout << " \r";
std::cout << "Number of clusters: " << clusters.size() << '\r';
cout.flush();
found = false;
for (int k1=start; k1<(int)clusters.size(); ++k1)
{
Cluster c1 = clusters.at(k1);
vnl_matrix<float> t = c1.h / c1.n;
std::vector< int > merge_indices;
std::vector< bool > flip_indices;
#pragma omp parallel for
for (int k2=start+1; k2<(int)clusters.size(); ++k2)
{
if (k1!=k2)
{
Cluster c2 = clusters.at(k2);
vnl_matrix<float> v = c2.h / c2.n;
bool f = false;
float d = 0;
for (auto m : m_Metrics)
d += m->CalculateDistance(t, v, f);
d /= m_Metrics.size();
#pragma omp critical
if (d<m_MergeDuplicateThreshold)
{
merge_indices.push_back(k2);
flip_indices.push_back(f);
}
}
}
for (unsigned int i=0; i<merge_indices.size(); ++i)
{
Cluster c2 = clusters.at(merge_indices.at(i));
for (int i=0; i<c2.n; ++i)
{
clusters[k1].I.push_back(c2.I.at(i));
clusters[k1].n += 1;
}
if (!flip_indices.at(i))
clusters[k1].h += c2.h;
else
clusters[k1].h += c2.h.fliplr();
}
std::sort(merge_indices.begin(), merge_indices.end());
for (unsigned int i=0; i<merge_indices.size(); ++i)
{
clusters.erase (clusters.begin()+merge_indices.at(i)-i);
found = true;
}
if (found)
break;
}
++start;
}
MITK_INFO << "\nNumber of clusters after merging duplicates: " << clusters.size();
}
std::vector<TractClusteringFilter::Cluster> TractClusteringFilter::AddToKnownClusters(std::vector< unsigned int > f_indices, std::vector<vnl_matrix<float> >& centroids)
{
float dist_thres = m_Distances.at(0);
int N = f_indices.size();
std::vector< Cluster > C;
vnl_matrix<float> zero_h; zero_h.set_size(T.at(0).rows(), T.at(0).cols()); zero_h.fill(0.0);
Cluster no_fit;
no_fit.h = zero_h;
for (unsigned int i=0; i<centroids.size(); ++i)
{
Cluster c;
c.h.set_size(T.at(0).rows(), T.at(0).cols()); c.h.fill(0.0);
c.f_id = i;
C.push_back(c);
}
#pragma omp parallel for
for (int i=0; i<N; ++i)
{
vnl_matrix<float> t = T.at(f_indices.at(i));
int min_cluster_index = -1;
float min_cluster_distance = 99999;
bool flip = false;
if (CalcOverlap(t)>=m_OverlapThreshold)
{
int c_idx = 0;
for (vnl_matrix<float> centroid : centroids)
{
bool f = false;
float d = 0;
for (auto m : m_Metrics)
d += m->CalculateDistance(t, centroid, f);
d /= m_Metrics.size();
if (d<min_cluster_distance)
{
min_cluster_distance = d;
min_cluster_index = c_idx;
flip = f;
}
++c_idx;
}
}
if (min_cluster_index>=0 && min_cluster_distance<dist_thres)
{
#pragma omp critical
{
C[min_cluster_index].I.push_back(f_indices.at(i));
if (!flip)
C[min_cluster_index].h += t;
else
C[min_cluster_index].h += t.fliplr();
C[min_cluster_index].n += 1;
}
}
else
{
#pragma omp critical
{
no_fit.I.push_back(f_indices.at(i));
no_fit.n++;
}
}
}
C.push_back(no_fit);
return C;
}
void TractClusteringFilter::GenerateData()
{
m_OutTractograms.clear();
m_OutCentroids.clear();
m_OutClusters.clear();
if (m_Metrics.empty())
{
mitkThrow() << "No metric selected!";
return;
}
T = ResampleFibers(m_Tractogram);
if (T.empty())
{
MITK_INFO << "No fibers in tractogram!";
return;
}
std::vector< unsigned int > f_indices;
for (unsigned int i=0; i<T.size(); ++i)
f_indices.push_back(i);
// std::random_shuffle(f_indices.begin(), f_indices.end());
Cluster no_match;
std::vector< Cluster > clusters;
if (m_InCentroids.IsNull())
{
MITK_INFO << "Clustering fibers";
clusters = ClusterStep(f_indices, m_Distances);
MITK_INFO << "Number of clusters: " << clusters.size();
clusters = MergeDuplicateClusters2(clusters);
std::sort(clusters.begin(),clusters.end());
}
else
{
std::vector<vnl_matrix<float> > centroids = ResampleFibers(m_InCentroids);
if (centroids.empty())
{
MITK_INFO << "No fibers in centroid tractogram!";
return;
}
MITK_INFO << "Clustering with input centroids";
clusters = AddToKnownClusters(f_indices, centroids);
no_match = clusters.back();
clusters.pop_back();
MITK_INFO << "Number of clusters: " << clusters.size();
clusters = MergeDuplicateClusters2(clusters);
}
MITK_INFO << "Clustering finished";
int max = clusters.size()-1;
if (m_MaxClusters>0 && clusters.size()-1>m_MaxClusters)
max = m_MaxClusters;
int skipped = 0;
for (int i=clusters.size()-1; i>=0; --i)
{
Cluster c = clusters.at(i);
if ( c.n>=(int)m_MinClusterSize && !(m_MaxClusters>0 && clusters.size()-i>m_MaxClusters) )
{
m_OutClusters.push_back(c);
vtkSmartPointer<vtkFloatArray> weights = vtkSmartPointer<vtkFloatArray>::New();
vtkSmartPointer<vtkPolyData> pTmp = m_Tractogram->GeneratePolyDataByIds(c.I, weights);
mitk::FiberBundle::Pointer fib = mitk::FiberBundle::New(pTmp);
if (max>0)
fib->SetFiberWeights((float)i/max);
m_OutTractograms.push_back(fib);
m_OutFiberIndices.push_back(c.I);
// create centroid
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> vtkNewCells = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
vnl_matrix<float> centroid_points = c.h / c.n;
for (unsigned int j=0; j<centroid_points.cols(); j++)
{
double p[3];
p[0] = centroid_points.get(0,j);
p[1] = centroid_points.get(1,j);
p[2] = centroid_points.get(2,j);
vtkIdType id = vtkNewPoints->InsertNextPoint(p);
container->GetPointIds()->InsertNextId(id);
}
vtkNewCells->InsertNextCell(container);
polyData->SetPoints(vtkNewPoints);
polyData->SetLines(vtkNewCells);
mitk::FiberBundle::Pointer centroid = mitk::FiberBundle::New(polyData);
centroid->SetFiberColors(255, 255, 255);
m_OutCentroids.push_back(centroid);
}
else
{
skipped++;
}
}
MITK_INFO << "Final number of clusters: " << m_OutTractograms.size() << " (discarded " << skipped << " clusters)";
int w = 0;
for (auto fib : m_OutTractograms)
{
if (m_OutTractograms.size()>1)
{
fib->SetFiberWeights((float)w/(m_OutTractograms.size()-1));
m_OutCentroids.at(w)->SetFiberWeights((float)w/(m_OutTractograms.size()-1));
}
else
{
fib->SetFiberWeights(1);
m_OutCentroids.at(w)->SetFiberWeights(1);
}
fib->ColorFibersByFiberWeights(false, false);
++w;
}
if (no_match.n>0)
{
vtkSmartPointer<vtkFloatArray> weights = vtkSmartPointer<vtkFloatArray>::New();
vtkSmartPointer<vtkPolyData> pTmp = m_Tractogram->GeneratePolyDataByIds(no_match.I, weights);
mitk::FiberBundle::Pointer fib = mitk::FiberBundle::New(pTmp);
fib->SetFiberColors(0, 0, 0);
m_OutFiberIndices.push_back(no_match.I);
m_OutTractograms.push_back(fib);
}
}
}
diff --git a/Modules/FiberTracking/Algorithms/itkTractClusteringFilter.h b/Modules/FiberTracking/Algorithms/itkTractClusteringFilter.h
index 7479c11..b18e2bb 100644
--- a/Modules/FiberTracking/Algorithms/itkTractClusteringFilter.h
+++ b/Modules/FiberTracking/Algorithms/itkTractClusteringFilter.h
@@ -1,140 +1,140 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 itkTractClusteringFilter_h
#define itkTractClusteringFilter_h
// MITK
#include <mitkPlanarEllipse.h>
#include <mitkFiberBundle.h>
#include <mitkFiberfoxParameters.h>
#include <mitkClusteringMetric.h>
// ITK
#include <itkProcessObject.h>
// VTK
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkCellArray.h>
#include <vtkPoints.h>
#include <vtkPolyLine.h>
namespace itk{
/**
* \brief */
class TractClusteringFilter : public ProcessObject
{
public:
struct Cluster
{
Cluster() : n(0), f_id(-1) {}
vnl_matrix<float> h;
std::vector< unsigned int > I;
int n;
int f_id;
bool operator <(Cluster const& b) const
{
return this->n < b.n;
}
};
typedef TractClusteringFilter Self;
typedef ProcessObject Superclass;
typedef SmartPointer< Self > Pointer;
typedef SmartPointer< const Self > ConstPointer;
typedef itk::Image< float, 3 > FloatImageType;
typedef itk::Image< unsigned char, 3 > UcharImageType;
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
itkTypeMacro( TractClusteringFilter, ProcessObject )
itkSetMacro(NumPoints, unsigned int) ///< Fibers are resampled to the specified number of points. If scalar maps are used, a larger number of points is recommended.
itkGetMacro(NumPoints, unsigned int) ///< Fibers are resampled to the specified number of points. If scalar maps are used, a larger number of points is recommended.
itkSetMacro(MinClusterSize, unsigned int) ///< Clusters with too few fibers are discarded
itkGetMacro(MinClusterSize, unsigned int) ///< Clusters with too few fibers are discarded
itkSetMacro(MaxClusters, unsigned int) ///< Only the N largest clusters are kept
itkGetMacro(MaxClusters, unsigned int) ///< Only the N largest clusters are kept
itkSetMacro(MergeDuplicateThreshold, float) ///< Clusters with centroids very close to each other are merged. Set to 0 to avoid merging and to -1 to use the original cluster size.
itkGetMacro(MergeDuplicateThreshold, float) ///< Clusters with centroids very close to each other are merged. Set to 0 to avoid merging and to -1 to use the original cluster size.
itkSetMacro(DoResampling, bool) ///< Resample fibers to equal number of points. This is mandatory, but can be performed outside of the filter if desired.
itkGetMacro(DoResampling, bool) ///< Resample fibers to equal number of points. This is mandatory, but can be performed outside of the filter if desired.
itkSetMacro(OverlapThreshold, float) ///< Overlap threshold used in conjunction with the filter mask when clustering around known centroids.
itkGetMacro(OverlapThreshold, float) ///< Overlap threshold used in conjunction with the filter mask when clustering around known centroids.
itkSetMacro(Tractogram, mitk::FiberBundle::Pointer) ///< The streamlines to be clustered
itkSetMacro(InCentroids, mitk::FiberBundle::Pointer) ///< If a tractogram containing known tract centroids is set, the input fibers are assigned to the closest centroid. If no centroid is found within the specified smallest clustering distance, the fiber is assigned to the no-fit cluster.
itkSetMacro(FilterMask, UcharImageType::Pointer) ///< If fibers are clustered around the nearest input centroids (see SetInCentroids), the complete input tractogram can additionally be pre-filtered with this binary mask and a given overlap threshold (see SetOverlapThreshold).
virtual void Update() override{
this->GenerateData();
}
void SetDistances(const std::vector<float> &Distances); ///< Set clustering distances that are traversed recoursively. The distances have to be sorted in an ascending manner. The actual cluster size is determined by the smallest entry in the distance-list (index 0).
std::vector<mitk::FiberBundle::Pointer> GetOutTractograms() const;
std::vector<mitk::FiberBundle::Pointer> GetOutCentroids() const;
std::vector<Cluster> GetOutClusters() const;
void SetMetrics(const std::vector<mitk::ClusteringMetric *> &Metrics);
std::vector<std::vector<unsigned int> > GetOutFiberIndices() const;
protected:
void GenerateData() override;
std::vector< vnl_matrix<float> > ResampleFibers(FiberBundle::Pointer tractogram);
float CalcOverlap(vnl_matrix<float>& t);
std::vector< Cluster > ClusterStep(std::vector< unsigned int > f_indices, std::vector< float > distances);
std::vector< TractClusteringFilter::Cluster > MergeDuplicateClusters2(std::vector< TractClusteringFilter::Cluster >& clusters);
void MergeDuplicateClusters(std::vector< TractClusteringFilter::Cluster >& clusters);
std::vector< Cluster > AddToKnownClusters(std::vector< unsigned int > f_indices, std::vector<vnl_matrix<float> > &centroids);
void AppendCluster(std::vector< Cluster >& a, std::vector< Cluster >&b);
TractClusteringFilter();
virtual ~TractClusteringFilter();
unsigned int m_NumPoints;
std::vector< float > m_Distances;
mitk::FiberBundle::Pointer m_Tractogram;
mitk::FiberBundle::Pointer m_InCentroids;
std::vector< mitk::FiberBundle::Pointer > m_OutTractograms;
std::vector< mitk::FiberBundle::Pointer > m_OutCentroids;
std::vector<vnl_matrix<float> > T;
unsigned int m_MinClusterSize;
unsigned int m_MaxClusters;
float m_MergeDuplicateThreshold;
std::vector< Cluster > m_OutClusters;
bool m_DoResampling;
UcharImageType::Pointer m_FilterMask;
float m_OverlapThreshold;
std::vector< mitk::ClusteringMetric* > m_Metrics;
std::vector< std::vector< unsigned int > > m_OutFiberIndices;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkTractClusteringFilter.cpp"
#endif
#endif
diff --git a/Modules/FiberTracking/Algorithms/itkTractDensityImageFilter.cpp b/Modules/FiberTracking/Algorithms/itkTractDensityImageFilter.cpp
index 0938492..c5f54d9 100644
--- a/Modules/FiberTracking/Algorithms/itkTractDensityImageFilter.cpp
+++ b/Modules/FiberTracking/Algorithms/itkTractDensityImageFilter.cpp
@@ -1,179 +1,179 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
Coindex[1]right (c) German Cancer Research Center,
-Division of Medical Image Computing.
+
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 "itkTractDensityImageFilter.h"
// VTK
#include <vtkPolyLine.h>
#include <vtkCellArray.h>
#include <vtkCellData.h>
#include <vtkCell.h>
// misc
#include <cmath>
#include <boost/progress.hpp>
#include <vtkBox.h>
#include <mitkDiffusionFunctionCollection.h>
namespace itk{
template< class OutputImageType >
TractDensityImageFilter< OutputImageType >::TractDensityImageFilter()
: m_UpsamplingFactor(1)
, m_InvertImage(false)
, m_BinaryOutput(false)
, m_UseImageGeometry(false)
, m_OutputAbsoluteValues(false)
, m_MaxDensity(0)
, m_NumCoveredVoxels(0)
{
}
template< class OutputImageType >
TractDensityImageFilter< OutputImageType >::~TractDensityImageFilter()
{
}
template< class OutputImageType >
void TractDensityImageFilter< OutputImageType >::GenerateData()
{
// generate upsampled image
mitk::BaseGeometry::Pointer geometry = m_FiberBundle->GetGeometry();
typename OutputImageType::Pointer outImage = this->GetOutput();
// calculate new image parameters
itk::Vector<double,3> newSpacing;
mitk::Point3D newOrigin;
itk::Matrix<double, 3, 3> newDirection;
ImageRegion<3> upsampledRegion;
if (m_UseImageGeometry && !m_InputImage.IsNull())
{
MITK_INFO << "TractDensityImageFilter: using image geometry";
newSpacing = m_InputImage->GetSpacing()/m_UpsamplingFactor;
upsampledRegion = m_InputImage->GetLargestPossibleRegion();
newOrigin = m_InputImage->GetOrigin();
typename OutputImageType::RegionType::SizeType size = upsampledRegion.GetSize();
size[0] *= m_UpsamplingFactor;
size[1] *= m_UpsamplingFactor;
size[2] *= m_UpsamplingFactor;
upsampledRegion.SetSize(size);
newDirection = m_InputImage->GetDirection();
}
else
{
MITK_INFO << "TractDensityImageFilter: using fiber bundle geometry";
newSpacing = geometry->GetSpacing()/m_UpsamplingFactor;
newOrigin = geometry->GetOrigin();
mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds();
// we retrieve the origin from a vtk-polydata (corner-based) and hance have to translate it to an image geometry
// i.e. center-based
newOrigin[0] += bounds.GetElement(0) + 0.5 * newSpacing[0];
newOrigin[1] += bounds.GetElement(2) + 0.5 * newSpacing[1];
newOrigin[2] += bounds.GetElement(4) + 0.5 * newSpacing[2];
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
newDirection[j][i] = geometry->GetMatrixColumn(i)[j];
upsampledRegion.SetSize(0, ceil( geometry->GetExtent(0)*m_UpsamplingFactor ) );
upsampledRegion.SetSize(1, ceil( geometry->GetExtent(1)*m_UpsamplingFactor ) );
upsampledRegion.SetSize(2, ceil( geometry->GetExtent(2)*m_UpsamplingFactor ) );
}
typename OutputImageType::RegionType::SizeType upsampledSize = upsampledRegion.GetSize();
// apply new image parameters
outImage->SetSpacing( newSpacing );
outImage->SetOrigin( newOrigin );
outImage->SetDirection( newDirection );
outImage->SetLargestPossibleRegion( upsampledRegion );
outImage->SetBufferedRegion( upsampledRegion );
outImage->SetRequestedRegion( upsampledRegion );
outImage->Allocate();
outImage->FillBuffer(0.0);
int w = upsampledSize[0];
int h = upsampledSize[1];
int d = upsampledSize[2];
// set/initialize output
OutPixelType* outImageBufferPointer = (OutPixelType*)outImage->GetBufferPointer();
MITK_INFO << "TractDensityImageFilter: starting image generation";
vtkSmartPointer<vtkPolyData> fiberPolyData = m_FiberBundle->GetFiberPolyData();
int numFibers = m_FiberBundle->GetNumFibers();
boost::progress_display disp(numFibers);
for( int i=0; i<numFibers; i++ )
{
++disp;
vtkCell* cell = fiberPolyData->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
float weight = m_FiberBundle->GetFiberWeight(i);
// fill output image
for( int j=0; j<numPoints-1; j++)
{
itk::Point<float, 3> startVertex = mitk::imv::GetItkPoint(points->GetPoint(j));
itk::Index<3> startIndex;
itk::ContinuousIndex<float, 3> startIndexCont;
outImage->TransformPhysicalPointToIndex(startVertex, startIndex);
outImage->TransformPhysicalPointToContinuousIndex(startVertex, startIndexCont);
itk::Point<float, 3> endVertex = mitk::imv::GetItkPoint(points->GetPoint(j + 1));
itk::Index<3> endIndex;
itk::ContinuousIndex<float, 3> endIndexCont;
outImage->TransformPhysicalPointToIndex(endVertex, endIndex);
outImage->TransformPhysicalPointToContinuousIndex(endVertex, endIndexCont);
std::vector< std::pair< itk::Index<3>, double > > segments = mitk::imv::IntersectImage(newSpacing, startIndex, endIndex, startIndexCont, endIndexCont);
for (std::pair< itk::Index<3>, double > segment : segments)
{
if (!outImage->GetLargestPossibleRegion().IsInside(segment.first))
continue;
if (outImage->GetPixel(segment.first)==0)
m_NumCoveredVoxels++;
if (m_BinaryOutput)
outImage->SetPixel(segment.first, 1);
else
outImage->SetPixel(segment.first, outImage->GetPixel(segment.first)+segment.second * weight);
}
}
}
m_MaxDensity = 0;
for (int i=0; i<w*h*d; i++)
if (m_MaxDensity < outImageBufferPointer[i])
m_MaxDensity = outImageBufferPointer[i];
if (!m_OutputAbsoluteValues && !m_BinaryOutput)
{
MITK_INFO << "TractDensityImageFilter: max-normalizing output image";
if (m_MaxDensity>0)
for (int i=0; i<w*h*d; i++)
{
outImageBufferPointer[i] /= m_MaxDensity;
}
}
if (m_InvertImage)
{
MITK_INFO << "TractDensityImageFilter: inverting image";
for (int i=0; i<w*h*d; i++)
outImageBufferPointer[i] = 1-outImageBufferPointer[i];
}
MITK_INFO << "TractDensityImageFilter: finished processing";
}
}
diff --git a/Modules/FiberTracking/Algorithms/itkTractDensityImageFilter.h b/Modules/FiberTracking/Algorithms/itkTractDensityImageFilter.h
index 73916a5..3887168 100644
--- a/Modules/FiberTracking/Algorithms/itkTractDensityImageFilter.h
+++ b/Modules/FiberTracking/Algorithms/itkTractDensityImageFilter.h
@@ -1,88 +1,88 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkTractDensityImageFilter_h__
#define __itkTractDensityImageFilter_h__
#include <itkImageSource.h>
#include <itkImage.h>
#include <itkVectorContainer.h>
#include <itkRGBAPixel.h>
#include <mitkFiberBundle.h>
namespace itk{
/**
* \brief Generates tract density images from input fiberbundles (Calamante 2010). */
template< class OutputImageType >
class TractDensityImageFilter : public ImageSource< OutputImageType >
{
public:
typedef TractDensityImageFilter Self;
typedef ProcessObject Superclass;
typedef SmartPointer< Self > Pointer;
typedef SmartPointer< const Self > ConstPointer;
typedef typename OutputImageType::PixelType OutPixelType;
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
itkTypeMacro( TractDensityImageFilter, ImageSource )
itkSetMacro( UpsamplingFactor, float) ///< use higher resolution for ouput image
itkGetMacro( UpsamplingFactor, float) ///< use higher resolution for ouput image
itkSetMacro( InvertImage, bool) ///< voxelvalue = 1-voxelvalue
itkGetMacro( InvertImage, bool) ///< voxelvalue = 1-voxelvalue
itkSetMacro( BinaryOutput, bool) ///< generate binary fiber envelope
itkGetMacro( BinaryOutput, bool) ///< generate binary fiber envelope
itkSetMacro( OutputAbsoluteValues, bool) ///< output absolute values of the number of fibers per voxel
itkGetMacro( OutputAbsoluteValues, bool) ///< output absolute values of the number of fibers per voxel
itkSetMacro( UseImageGeometry, bool) ///< use input image geometry to initialize output image
itkGetMacro( UseImageGeometry, bool) ///< use input image geometry to initialize output image
itkSetMacro( FiberBundle, mitk::FiberBundle::Pointer) ///< input fiber bundle
itkSetMacro( InputImage, typename OutputImageType::Pointer) ///< use input image geometry to initialize output image
itkGetMacro( MaxDensity, OutPixelType)
itkGetMacro( NumCoveredVoxels, unsigned int)
void GenerateData() override;
protected:
TractDensityImageFilter();
~TractDensityImageFilter() override;
typename OutputImageType::Pointer m_InputImage; ///< use input image geometry to initialize output image
mitk::FiberBundle::Pointer m_FiberBundle; ///< input fiber bundle
float m_UpsamplingFactor; ///< use higher resolution for ouput image
bool m_InvertImage; ///< voxelvalue = 1-voxelvalue
bool m_BinaryOutput; ///< generate binary fiber envelope
bool m_UseImageGeometry; ///< use input image geometry to initialize output image
bool m_OutputAbsoluteValues; ///< do not normalize image values to 0-1
bool m_UseTrilinearInterpolation;
bool m_DoFiberResampling;
bool m_WorkOnFiberCopy;
OutPixelType m_MaxDensity;
unsigned int m_NumCoveredVoxels;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkTractDensityImageFilter.cpp"
#endif
#endif // __itkTractDensityImageFilter_h__
diff --git a/Modules/FiberTracking/Algorithms/itkTractDistanceFilter.cpp b/Modules/FiberTracking/Algorithms/itkTractDistanceFilter.cpp
index cdea4df..3eafa8f 100644
--- a/Modules/FiberTracking/Algorithms/itkTractDistanceFilter.cpp
+++ b/Modules/FiberTracking/Algorithms/itkTractDistanceFilter.cpp
@@ -1,189 +1,189 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "itkTractDistanceFilter.h"
#define _USE_MATH_DEFINES
#include <math.h>
#include <vnl/vnl_sparse_matrix.h>
namespace itk{
TractDistanceFilter::TractDistanceFilter()
: m_NumPoints(12)
, disp(0)
{
}
TractDistanceFilter::~TractDistanceFilter()
{
for (auto m : m_Metrics)
delete m;
}
vnl_matrix<float> TractDistanceFilter::GetAllDistances() const
{
return m_AllDistances;
}
vnl_vector<int> TractDistanceFilter::GetMinIndices() const
{
return m_MinIndices;
}
vnl_vector<float> TractDistanceFilter::GetMinDistances() const
{
return m_MinDistances;
}
void TractDistanceFilter::SetTracts2(const std::vector<FiberBundle::Pointer> &Tracts2)
{
m_Tracts2 = Tracts2;
}
void TractDistanceFilter::SetTracts1(const std::vector<FiberBundle::Pointer> &Tracts1)
{
m_Tracts1 = Tracts1;
}
void TractDistanceFilter::SetMetrics(const std::vector<mitk::ClusteringMetric *> &Metrics)
{
m_Metrics = Metrics;
}
std::vector<vnl_matrix<float> > TractDistanceFilter::ResampleFibers(mitk::FiberBundle::Pointer tractogram)
{
std::streambuf *old = cout.rdbuf(); // <-- save
std::stringstream ss;
std::cout.rdbuf (ss.rdbuf()); // <-- redirect
mitk::FiberBundle::Pointer temp_fib = tractogram->GetDeepCopy();
temp_fib->ResampleToNumPoints(m_NumPoints);
std::vector< vnl_matrix<float> > out_fib;
for (int i=0; i<temp_fib->GetFiberPolyData()->GetNumberOfCells(); i++)
{
vtkCell* cell = temp_fib->GetFiberPolyData()->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
vnl_matrix<float> streamline;
streamline.set_size(3, m_NumPoints);
streamline.fill(0.0);
for (int j=0; j<numPoints; j++)
{
double cand[3];
points->GetPoint(j, cand);
vnl_vector_fixed< float, 3 > candV;
candV[0]=cand[0]; candV[1]=cand[1]; candV[2]=cand[2];
streamline.set_column(j, candV);
}
out_fib.push_back(streamline);
}
std::cout.rdbuf (old); // <-- restore
return out_fib;
}
float TractDistanceFilter::calc_distance(const std::vector<vnl_matrix<float> >& T1, const std::vector<vnl_matrix<float> >& T2)
{
float distance = 0;
for (auto metric : m_Metrics)
{
unsigned int r = 0;
for (auto f1 : T1)
{
unsigned int c = 0;
float min_d = 99999;
for (auto f2 : T2)
{
#pragma omp critical
++disp;
bool flipped = false;
float d = metric->CalculateDistance(f1, f2, flipped);
if (d < min_d)
min_d = d;
++c;
}
distance += min_d;
++r;
}
}
distance /= (T1.size() * m_Metrics.size());
return distance;
}
void TractDistanceFilter::GenerateData()
{
if (m_Metrics.empty())
{
mitkThrow() << "No metric selected!";
return;
}
m_MinIndices.clear();
m_MinDistances.clear();
std::vector<std::vector<vnl_matrix<float>>> T1;
std::vector<std::vector<vnl_matrix<float>>> T2;
unsigned int num_fibs1 = 0;
unsigned int num_fibs2 = 0;
for (auto t : m_Tracts1)
{
T1.push_back(ResampleFibers(t));
num_fibs1 += T1.back().size();
}
for (auto t : m_Tracts2)
{
T2.push_back(ResampleFibers(t));
num_fibs2 += T2.back().size();
}
disp.restart(m_Metrics.size() * num_fibs1 * num_fibs2);
m_AllDistances.set_size(T1.size(), T2.size());
m_MinIndices.set_size(T1.size());
m_MinDistances.set_size(T1.size());
#pragma omp parallel for
for (int i=0; i<(int)T1.size(); ++i)
{
auto tracto1 = T1.at(i);
m_MinDistances[i] = 99999;
for (unsigned int j=0; j<T2.size(); ++j)
{
auto tracto2 = T2.at(j);
float d = calc_distance(tracto1, tracto2);
m_AllDistances[i][j] = d;
if (d < m_MinDistances[i])
{
m_MinDistances[i] = d;
m_MinIndices[i] = j;
}
}
}
}
}
diff --git a/Modules/FiberTracking/Algorithms/itkTractDistanceFilter.h b/Modules/FiberTracking/Algorithms/itkTractDistanceFilter.h
index 41fc0e3..a660bc7 100644
--- a/Modules/FiberTracking/Algorithms/itkTractDistanceFilter.h
+++ b/Modules/FiberTracking/Algorithms/itkTractDistanceFilter.h
@@ -1,93 +1,93 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 itkTractDistanceFilter_h
#define itkTractDistanceFilter_h
#include <mitkPlanarEllipse.h>
#include <mitkFiberBundle.h>
#include <mitkFiberfoxParameters.h>
#include <mitkClusteringMetric.h>
#include <itkProcessObject.h>
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkCellArray.h>
#include <vtkPoints.h>
#include <vtkPolyLine.h>
#include <boost/progress.hpp>
namespace itk{
/**
* \brief */
class TractDistanceFilter : public ProcessObject
{
public:
typedef TractDistanceFilter Self;
typedef ProcessObject Superclass;
typedef SmartPointer< Self > Pointer;
typedef SmartPointer< const Self > ConstPointer;
typedef itk::Image< float, 3 > FloatImageType;
typedef itk::Image< unsigned char, 3 > UcharImageType;
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
itkTypeMacro( TractDistanceFilter, ProcessObject )
itkSetMacro(NumPoints, unsigned int) ///< Fibers are resampled to the specified number of points. If scalar maps are used, a larger number of points is recommended.
virtual void Update() override{
this->GenerateData();
}
void SetMetrics(const std::vector<mitk::ClusteringMetric *> &Metrics);
void SetTracts1(const std::vector<FiberBundle::Pointer> &Tracts1);
void SetTracts2(const std::vector<FiberBundle::Pointer> &Tracts2);
vnl_vector<float> GetMinDistances() const;
vnl_vector<int> GetMinIndices() const;
vnl_matrix<float> GetAllDistances() const;
protected:
void GenerateData() override;
std::vector< vnl_matrix<float> > ResampleFibers(FiberBundle::Pointer tractogram);
float calc_distance(const std::vector<vnl_matrix<float> > &T1, const std::vector<vnl_matrix<float> > &T2);
TractDistanceFilter();
virtual ~TractDistanceFilter();
std::vector<FiberBundle::Pointer> m_Tracts1;
std::vector<FiberBundle::Pointer> m_Tracts2;
unsigned int m_NumPoints;
std::vector<mitk::ClusteringMetric*> m_Metrics;
vnl_vector<float> m_MinDistances;
vnl_vector<int> m_MinIndices;
vnl_matrix<float> m_AllDistances;
boost::progress_display disp;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkTractDistanceFilter.cpp"
#endif
#endif
diff --git a/Modules/FiberTracking/Algorithms/itkTractsToFiberEndingsImageFilter.cpp b/Modules/FiberTracking/Algorithms/itkTractsToFiberEndingsImageFilter.cpp
index 309d8b4..131af89 100644
--- a/Modules/FiberTracking/Algorithms/itkTractsToFiberEndingsImageFilter.cpp
+++ b/Modules/FiberTracking/Algorithms/itkTractsToFiberEndingsImageFilter.cpp
@@ -1,155 +1,155 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "itkTractsToFiberEndingsImageFilter.h"
// VTK
#include <vtkPolyLine.h>
#include <vtkCellArray.h>
#include <vtkCellData.h>
#include <boost/progress.hpp>
#include <mitkDiffusionFunctionCollection.h>
namespace itk{
template< class OutputImageType >
TractsToFiberEndingsImageFilter< OutputImageType >::TractsToFiberEndingsImageFilter()
: m_UpsamplingFactor(1)
, m_InvertImage(false)
, m_UseImageGeometry(false)
, m_BinaryOutput(false)
, m_InputImage(nullptr)
{
}
template< class OutputImageType >
TractsToFiberEndingsImageFilter< OutputImageType >::~TractsToFiberEndingsImageFilter()
{
}
template< class OutputImageType >
void TractsToFiberEndingsImageFilter< OutputImageType >::GenerateData()
{
// generate upsampled image
mitk::BaseGeometry::Pointer geometry = m_FiberBundle->GetGeometry();
typename OutputImageType::Pointer outImage = this->GetOutput();
// calculate new image parameters
itk::Vector<double, 3> newSpacing;
mitk::Point3D newOrigin;
itk::Matrix<double, 3, 3> newDirection;
ImageRegion<3> upsampledRegion;
if (m_UseImageGeometry && !m_InputImage.IsNull())
{
newSpacing = m_InputImage->GetSpacing()/m_UpsamplingFactor;
upsampledRegion = m_InputImage->GetLargestPossibleRegion();
newOrigin = m_InputImage->GetOrigin();
typename OutputImageType::RegionType::SizeType size = upsampledRegion.GetSize();
size[0] *= m_UpsamplingFactor;
size[1] *= m_UpsamplingFactor;
size[2] *= m_UpsamplingFactor;
upsampledRegion.SetSize(size);
newDirection = m_InputImage->GetDirection();
}
else
{
newSpacing = geometry->GetSpacing()/m_UpsamplingFactor;
newOrigin = geometry->GetOrigin();
mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds();
newOrigin[0] += bounds.GetElement(0);
newOrigin[1] += bounds.GetElement(2);
newOrigin[2] += bounds.GetElement(4);
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
newDirection[j][i] = geometry->GetMatrixColumn(i)[j];
upsampledRegion.SetSize(0, geometry->GetExtent(0)*m_UpsamplingFactor);
upsampledRegion.SetSize(1, geometry->GetExtent(1)*m_UpsamplingFactor);
upsampledRegion.SetSize(2, geometry->GetExtent(2)*m_UpsamplingFactor);
}
typename OutputImageType::RegionType::SizeType upsampledSize = upsampledRegion.GetSize();
// apply new image parameters
outImage->SetSpacing( newSpacing );
outImage->SetOrigin( newOrigin );
outImage->SetDirection( newDirection );
outImage->SetRegions( upsampledRegion );
outImage->Allocate();
int w = upsampledSize[0];
int h = upsampledSize[1];
int d = upsampledSize[2];
// set/initialize output
OutPixelType* outImageBufferPointer = (OutPixelType*)outImage->GetBufferPointer();
for (int i=0; i<w*h*d; i++)
outImageBufferPointer[i] = 0;
// resample fiber bundle
vtkSmartPointer<vtkPolyData> fiberPolyData = m_FiberBundle->GetFiberPolyData();
int numFibers = m_FiberBundle->GetNumFibers();
boost::progress_display disp(numFibers);
for( int i=0; i<numFibers; i++ )
{
++disp;
vtkCell* cell = fiberPolyData->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
// fill output image
if (numPoints>0)
{
itk::Point<float, 3> vertex = mitk::imv::GetItkPoint(points->GetPoint(0));
itk::Index<3> index;
outImage->TransformPhysicalPointToIndex(vertex, index);
if (upsampledRegion.IsInside(index))
{
if (m_BinaryOutput)
{
outImage->SetPixel(index, 1);
}
else
{
outImage->SetPixel(index, outImage->GetPixel(index)+1);
}
}
}
if (numPoints>=2)
{
itk::Point<float, 3> vertex = mitk::imv::GetItkPoint(points->GetPoint(numPoints-1));
itk::Index<3> index;
outImage->TransformPhysicalPointToIndex(vertex, index);
if (upsampledRegion.IsInside(index))
{
if (m_BinaryOutput)
{
outImage->SetPixel(index, 1);
}
else
{
outImage->SetPixel(index, outImage->GetPixel(index)+1);
}
}
}
}
if (m_InvertImage)
for (int i=0; i<w*h*d; i++)
outImageBufferPointer[i] = 1-outImageBufferPointer[i];
}
}
diff --git a/Modules/FiberTracking/Algorithms/itkTractsToFiberEndingsImageFilter.h b/Modules/FiberTracking/Algorithms/itkTractsToFiberEndingsImageFilter.h
index b262ef0..5f0a9ae 100644
--- a/Modules/FiberTracking/Algorithms/itkTractsToFiberEndingsImageFilter.h
+++ b/Modules/FiberTracking/Algorithms/itkTractsToFiberEndingsImageFilter.h
@@ -1,84 +1,84 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkTractsToFiberEndingsImageFilter_h__
#define __itkTractsToFiberEndingsImageFilter_h__
#include <itkImageSource.h>
#include <itkImage.h>
#include <itkVectorContainer.h>
#include <itkRGBAPixel.h>
#include <mitkFiberBundle.h>
namespace itk{
/**
* \brief Generates image where the pixel values are set according to the number of fibers ending in the voxel. */
template< class OutputImageType >
class TractsToFiberEndingsImageFilter : public ImageSource< OutputImageType >
{
public:
typedef TractsToFiberEndingsImageFilter Self;
typedef ProcessObject Superclass;
typedef SmartPointer< Self > Pointer;
typedef SmartPointer< const Self > ConstPointer;
typedef typename OutputImageType::PixelType OutPixelType;
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
itkTypeMacro( TractsToFiberEndingsImageFilter, ImageSource )
/** Upsampling factor **/
itkSetMacro( UpsamplingFactor, float)
itkGetMacro( UpsamplingFactor, float)
/** Invert Image **/
itkSetMacro( InvertImage, bool)
itkGetMacro( InvertImage, bool)
itkSetMacro( FiberBundle, mitk::FiberBundle::Pointer)
itkSetMacro( InputImage, typename OutputImageType::Pointer)
/** Use input image geometry to initialize output image **/
itkSetMacro( UseImageGeometry, bool)
itkGetMacro( UseImageGeometry, bool)
itkSetMacro( BinaryOutput, bool)
void GenerateData() override;
protected:
TractsToFiberEndingsImageFilter();
virtual ~TractsToFiberEndingsImageFilter();
mitk::FiberBundle::Pointer m_FiberBundle; ///< input fiber bundle
float m_UpsamplingFactor; ///< use higher resolution for ouput image
bool m_InvertImage; ///< voxelvalue = 1-voxelvalue
bool m_UseImageGeometry; ///< output image is given other geometry than fiberbundle (input image geometry)
bool m_BinaryOutput;
typename OutputImageType::Pointer m_InputImage;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkTractsToFiberEndingsImageFilter.cpp"
#endif
#endif // __itkTractsToFiberEndingsImageFilter_h__
diff --git a/Modules/FiberTracking/Algorithms/itkTractsToRgbaImageFilter.cpp b/Modules/FiberTracking/Algorithms/itkTractsToRgbaImageFilter.cpp
index 59cffe9..93f2e1d 100644
--- a/Modules/FiberTracking/Algorithms/itkTractsToRgbaImageFilter.cpp
+++ b/Modules/FiberTracking/Algorithms/itkTractsToRgbaImageFilter.cpp
@@ -1,187 +1,187 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "itkTractsToRgbaImageFilter.h"
// VTK
#include <vtkPolyLine.h>
#include <vtkCellArray.h>
#include <vtkCellData.h>
// misc
#include <math.h>
#include <boost/progress.hpp>
#include <mitkDiffusionFunctionCollection.h>
namespace itk{
template< class OutputImageType >
TractsToRgbaImageFilter< OutputImageType >::TractsToRgbaImageFilter()
: m_UpsamplingFactor(1)
, m_UseImageGeometry(false)
, m_InputImage(nullptr)
{
}
template< class OutputImageType >
TractsToRgbaImageFilter< OutputImageType >::~TractsToRgbaImageFilter()
{
}
template< class OutputImageType >
void TractsToRgbaImageFilter< OutputImageType >::GenerateData()
{
if(&typeid(OutPixelType) != &typeid(itk::RGBAPixel<unsigned char>))
return;
// generate upsampled image
mitk::BaseGeometry::Pointer geometry = m_FiberBundle->GetGeometry();
typename OutputImageType::Pointer outImage = this->GetOutput();
// calculate new image parameters
itk::Vector<double,3> newSpacing;
mitk::Point3D newOrigin;
itk::Matrix<double, 3, 3> newDirection;
ImageRegion<3> upsampledRegion;
if (m_UseImageGeometry && !m_InputImage.IsNull())
{
newSpacing = m_InputImage->GetSpacing()/m_UpsamplingFactor;
upsampledRegion = m_InputImage->GetLargestPossibleRegion();
newOrigin = m_InputImage->GetOrigin();
typename OutputImageType::RegionType::SizeType size = upsampledRegion.GetSize();
size[0] *= m_UpsamplingFactor;
size[1] *= m_UpsamplingFactor;
size[2] *= m_UpsamplingFactor;
upsampledRegion.SetSize(size);
newDirection = m_InputImage->GetDirection();
}
else
{
newSpacing = geometry->GetSpacing()/m_UpsamplingFactor;
newOrigin = geometry->GetOrigin();
mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds();
newOrigin[0] += bounds.GetElement(0);
newOrigin[1] += bounds.GetElement(2);
newOrigin[2] += bounds.GetElement(4);
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
newDirection[j][i] = geometry->GetMatrixColumn(i)[j];
upsampledRegion.SetSize(0, geometry->GetExtent(0)*m_UpsamplingFactor);
upsampledRegion.SetSize(1, geometry->GetExtent(1)*m_UpsamplingFactor);
upsampledRegion.SetSize(2, geometry->GetExtent(2)*m_UpsamplingFactor);
}
typename OutputImageType::RegionType::SizeType upsampledSize = upsampledRegion.GetSize();
// apply new image parameters
outImage->SetSpacing( newSpacing );
outImage->SetOrigin( newOrigin );
outImage->SetDirection( newDirection );
outImage->SetRegions( upsampledRegion );
outImage->Allocate();
outImage->FillBuffer(0.0);
itk::Image< itk::RGBAPixel<double>, 3 >::Pointer double_out = itk::Image< itk::RGBAPixel<double>, 3 >::New();
double_out->SetSpacing( newSpacing );
double_out->SetOrigin( newOrigin );
double_out->SetDirection( newDirection );
double_out->SetRegions( upsampledRegion );
double_out->Allocate();
double_out->FillBuffer(0.0);
vtkSmartPointer<vtkPolyData> fiberPolyData = m_FiberBundle->GetFiberPolyData();
int numFibers = m_FiberBundle->GetNumFibers();
float scale = 100 * pow((float)m_UpsamplingFactor,3);
boost::progress_display disp(numFibers);
for( int i=0; i<numFibers; ++i )
{
++disp;
vtkCell* cell = fiberPolyData->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
for( int j=0; j<numPoints-1; ++j)
{
Point<float, 3> startVertex = mitk::imv::GetItkPoint(points->GetPoint(j));
Index<3> startIndex;
ContinuousIndex<float, 3> startIndexCont;
double_out->TransformPhysicalPointToIndex(startVertex, startIndex);
double_out->TransformPhysicalPointToContinuousIndex(startVertex, startIndexCont);
Point<float, 3> endVertex = mitk::imv::GetItkPoint(points->GetPoint(j + 1));
Index<3> endIndex;
ContinuousIndex<float, 3> endIndexCont;
double_out->TransformPhysicalPointToIndex(endVertex, endIndex);
double_out->TransformPhysicalPointToContinuousIndex(endVertex, endIndexCont);
Vector<float, 3> dir;
dir[0] = fabs(endVertex[0]-startVertex[0]);
dir[1] = fabs(endVertex[1]-startVertex[1]);
dir[2] = fabs(endVertex[2]-startVertex[2]);
dir.Normalize();
std::vector< std::pair< itk::Index<3>, double > > segments = mitk::imv::IntersectImage(newSpacing, startIndex, endIndex, startIndexCont, endIndexCont);
for (std::pair< itk::Index<3>, double > segment : segments)
{
if (!double_out->GetLargestPossibleRegion().IsInside(segment.first))
continue;
itk::RGBAPixel<double> pix = double_out->GetPixel(segment.first);
pix[0] += dir[0] * scale;
pix[1] += dir[1] * scale;
pix[2] += dir[2] * scale;
pix[3] += segment.second * scale;
double_out->SetPixel(segment.first, pix);
}
}
float maxRgb = 0.000000001;
float maxInt = 0.000000001;
int w = upsampledSize[0];
int h = upsampledSize[1];
int d = upsampledSize[2];
int numPix = w*h*d*4;
double* buffer = (double*)double_out->GetBufferPointer();
// calc maxima
for(int i=0; i<numPix; i++)
{
if((i-3)%4 != 0)
{
if(buffer[i] > maxRgb)
maxRgb = buffer[i];
}
else
{
if(buffer[i] > maxInt)
maxInt = buffer[i];
}
}
// write output, normalized uchar 0..255
unsigned char* outImageBufferPointer = (unsigned char*)outImage->GetBufferPointer();
for(int i=0; i<numPix; i++)
{
if((i-3)%4 != 0)
outImageBufferPointer[i] = (unsigned char) (255.0 * buffer[i] / maxRgb);
else
outImageBufferPointer[i] = (unsigned char) (255.0 * buffer[i] / maxInt);
}
}
}
}
diff --git a/Modules/FiberTracking/Algorithms/itkTractsToRgbaImageFilter.h b/Modules/FiberTracking/Algorithms/itkTractsToRgbaImageFilter.h
index e181dda..5674da5 100644
--- a/Modules/FiberTracking/Algorithms/itkTractsToRgbaImageFilter.h
+++ b/Modules/FiberTracking/Algorithms/itkTractsToRgbaImageFilter.h
@@ -1,78 +1,78 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkTractsToRgbaImageFilter_h__
#define __itkTractsToRgbaImageFilter_h__
#include <itkImageSource.h>
#include <itkImage.h>
#include <itkVectorContainer.h>
#include <itkRGBAPixel.h>
#include <mitkFiberBundle.h>
namespace itk{
/**
* \brief Generates RGBA image from the input fibers where color values are set according to the local fiber directions. */
template< class OutputImageType >
class TractsToRgbaImageFilter : public ImageSource< OutputImageType >
{
public:
typedef TractsToRgbaImageFilter Self;
typedef ProcessObject Superclass;
typedef SmartPointer< Self > Pointer;
typedef SmartPointer< const Self > ConstPointer;
typedef typename OutputImageType::PixelType OutPixelType;
typedef itk::Image<unsigned char, 3> InputImageType;
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
itkTypeMacro( TractsToRgbaImageFilter, ImageSource )
/** Upsampling factor **/
itkSetMacro( UpsamplingFactor, float)
itkGetMacro( UpsamplingFactor, float)
itkSetMacro( FiberBundle, mitk::FiberBundle::Pointer)
itkSetMacro( InputImage, typename InputImageType::Pointer)
/** Use input image geometry to initialize output image **/
itkSetMacro( UseImageGeometry, bool)
itkGetMacro( UseImageGeometry, bool)
void GenerateData();
protected:
TractsToRgbaImageFilter();
virtual ~TractsToRgbaImageFilter();
mitk::FiberBundle::Pointer m_FiberBundle; ///< input fiber bundle
float m_UpsamplingFactor; ///< use higher resolution for ouput image
bool m_UseImageGeometry; ///< output image is given other geometry than fiberbundle (input image geometry)
typename InputImageType::Pointer m_InputImage;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkTractsToRgbaImageFilter.cpp"
#endif
#endif // __itkTractsToRgbaImageFilter_h__
diff --git a/Modules/FiberTracking/Testing/mitkFiberBundleReaderWriterTest.cpp b/Modules/FiberTracking/Testing/mitkFiberBundleReaderWriterTest.cpp
index 85eeb86..b07d5c0 100644
--- a/Modules/FiberTracking/Testing/mitkFiberBundleReaderWriterTest.cpp
+++ b/Modules/FiberTracking/Testing/mitkFiberBundleReaderWriterTest.cpp
@@ -1,71 +1,71 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkTestingMacros.h"
#include <mitkFiberBundle.h>
#include <mitkBaseData.h>
#include <itksys/SystemTools.hxx>
#include <mitkTestingConfig.h>
#include <mitkIOUtil.h>
#include "mitkTestFixture.h"
class mitkFiberBundleReaderWriterTestSuite : public mitk::TestFixture
{
CPPUNIT_TEST_SUITE(mitkFiberBundleReaderWriterTestSuite);
MITK_TEST(Equal_SaveLoad_ReturnsTrue);
CPPUNIT_TEST_SUITE_END();
private:
/** Members used inside the different (sub-)tests. All members are initialized via setUp().*/
mitk::FiberBundle::Pointer fib1;
mitk::FiberBundle::Pointer fib2;
public:
void setUp() override
{
fib1 = nullptr;
fib2 = nullptr;
std::string filename = GetTestDataFilePath("DiffusionImaging/fiberBundleX.fib");
std::vector<mitk::BaseData::Pointer> fibInfile = mitk::IOUtil::Load( filename);
mitk::BaseData::Pointer baseData = fibInfile.at(0);
fib1 = dynamic_cast<mitk::FiberBundle*>(baseData.GetPointer());
}
void tearDown() override
{
fib1 = nullptr;
fib2 = nullptr;
}
void Equal_SaveLoad_ReturnsTrue()
{
mitk::IOUtil::Save(fib1.GetPointer(), std::string(MITK_TEST_OUTPUT_DIR)+"/writerTest.fib");
std::vector<mitk::BaseData::Pointer> baseData = mitk::IOUtil::Load(std::string(MITK_TEST_OUTPUT_DIR)+"/writerTest.fib");
fib2 = dynamic_cast<mitk::FiberBundle*>(baseData[0].GetPointer());
CPPUNIT_ASSERT_MESSAGE("Should be equal", fib1->Equals(fib2));
//MITK_ASSERT_EQUAL(fib1, fib2, "A saved and re-loaded file should be equal");
}
};
MITK_TEST_SUITE_REGISTRATION(mitkFiberBundleReaderWriter)
diff --git a/Modules/FiberTracking/Testing/mitkFiberExtractionTest.cpp b/Modules/FiberTracking/Testing/mitkFiberExtractionTest.cpp
index abe5053..765b990 100644
--- a/Modules/FiberTracking/Testing/mitkFiberExtractionTest.cpp
+++ b/Modules/FiberTracking/Testing/mitkFiberExtractionTest.cpp
@@ -1,143 +1,143 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkTestingMacros.h>
#include <mitkIOUtil.h>
#include <mitkFiberBundle.h>
#include <mitkPlanarFigure.h>
#include <mitkPlanarFigureComposite.h>
#include <mitkImageCast.h>
#include <mitkStandaloneDataStorage.h>
#include <vtkDebugLeaks.h>
#include <omp.h>
#include <itkFiberExtractionFilter.h>
/**Documentation
* Test if fiber transfortaiom methods work correctly
*/
int mitkFiberExtractionTest(int argc, char* argv[])
{
MITK_TEST_BEGIN("mitkFiberExtractionTest");
/// \todo Fix VTK memory leaks. Bug 18097.
vtkDebugLeaks::SetExitError(0);
MITK_INFO << "argc: " << argc;
MITK_TEST_CONDITION_REQUIRED(argc==13,"check for input data");
omp_set_num_threads(1);
try{
mitk::FiberBundle::Pointer groundTruthFibs = mitk::IOUtil::Load<mitk::FiberBundle>(argv[1]);
mitk::FiberBundle::Pointer testFibs = mitk::IOUtil::Load<mitk::FiberBundle>(argv[2]);
// test planar figure based extraction
auto data = mitk::IOUtil::Load(argv[3])[0];
auto pf1 = mitk::DataNode::New();
pf1->SetData(data);
data = mitk::IOUtil::Load(argv[4])[0];
auto pf2 = mitk::DataNode::New();
pf2->SetData(data);
data = mitk::IOUtil::Load(argv[5])[0];
auto pf3 = mitk::DataNode::New();
pf3->SetData(data);
mitk::StandaloneDataStorage::Pointer storage = mitk::StandaloneDataStorage::New();
mitk::PlanarFigureComposite::Pointer pfc2 = mitk::PlanarFigureComposite::New();
pfc2->setOperationType(mitk::PlanarFigureComposite::OR);
mitk::DataNode::Pointer pfcNode2 = mitk::DataNode::New();
pfcNode2->SetData(pfc2);
mitk::DataStorage::SetOfObjects::Pointer set2 = mitk::DataStorage::SetOfObjects::New();
set2->push_back(pfcNode2);
mitk::PlanarFigureComposite::Pointer pfc1 = mitk::PlanarFigureComposite::New();
pfc1->setOperationType(mitk::PlanarFigureComposite::AND);
mitk::DataNode::Pointer pfcNode1 = mitk::DataNode::New();
pfcNode1->SetData(pfc1);
mitk::DataStorage::SetOfObjects::Pointer set1 = mitk::DataStorage::SetOfObjects::New();
set1->push_back(pfcNode1);
storage->Add(pfcNode2);
storage->Add(pf1, set2);
storage->Add(pfcNode1, set2);
storage->Add(pf2, set1);
storage->Add(pf3, set1);
MITK_INFO << "TEST1";
mitk::FiberBundle::Pointer extractedFibs = groundTruthFibs->ExtractFiberSubset(pfcNode2, storage);
MITK_INFO << "TEST2";
MITK_TEST_CONDITION_REQUIRED(extractedFibs->Equals(testFibs),"check planar figure extraction");
MITK_INFO << "TEST3";
// test subtraction and addition
mitk::FiberBundle::Pointer notExtractedFibs = groundTruthFibs->SubtractBundle(extractedFibs);
MITK_INFO << argv[11];
testFibs = mitk::IOUtil::Load<mitk::FiberBundle>(argv[11]);
MITK_TEST_CONDITION_REQUIRED(notExtractedFibs->Equals(testFibs),"check bundle subtraction");
mitk::FiberBundle::Pointer joinded = extractedFibs->AddBundle(notExtractedFibs);
testFibs = mitk::IOUtil::Load<mitk::FiberBundle>(argv[12]);
MITK_TEST_CONDITION_REQUIRED(joinded->Equals(testFibs),"check bundle addition");
// test binary image based extraction
mitk::Image::Pointer mitkRoiImage = mitk::IOUtil::Load<mitk::Image>(argv[6]);
typedef itk::Image< unsigned char, 3 > itkUCharImageType;
itkUCharImageType::Pointer itkRoiImage = itkUCharImageType::New();
mitk::CastToItkImage(mitkRoiImage, itkRoiImage);
{
testFibs = mitk::IOUtil::Load<mitk::FiberBundle>(argv[9]);
itk::FiberExtractionFilter<unsigned char>::Pointer extractor = itk::FiberExtractionFilter<unsigned char>::New();
extractor->SetInputFiberBundle(groundTruthFibs);
extractor->SetRoiImages({itkRoiImage});
extractor->SetOverlapFraction(0.0);
extractor->SetMode(itk::FiberExtractionFilter<unsigned char>::MODE::OVERLAP);
extractor->Update();
mitk::FiberBundle::Pointer passing = extractor->GetPositives().at(0);
bool ok = passing->Equals(testFibs);
if(!ok)
mitk::IOUtil::Save(passing, mitk::IOUtil::GetTempPath()+"passing_mask.fib");
MITK_TEST_CONDITION_REQUIRED(ok,"check passing mask extraction");
}
{
testFibs = mitk::IOUtil::Load<mitk::FiberBundle>(argv[10]);
itk::FiberExtractionFilter<unsigned char>::Pointer extractor = itk::FiberExtractionFilter<unsigned char>::New();
extractor->SetInputFiberBundle(groundTruthFibs);
extractor->SetRoiImages({itkRoiImage});
extractor->SetOverlapFraction(0.0);
extractor->SetBothEnds(true);
extractor->SetMode(itk::FiberExtractionFilter<unsigned char>::MODE::ENDPOINTS);
extractor->Update();
mitk::FiberBundle::Pointer ending = extractor->GetPositives().at(0);
bool ok = ending->Equals(testFibs);
if(!ok)
mitk::IOUtil::Save(ending, mitk::IOUtil::GetTempPath()+"ending_mask.fib");
MITK_TEST_CONDITION_REQUIRED(ending->Equals(testFibs),"check ending in mask extraction");
}
}
catch(...) {
return EXIT_FAILURE;
}
// always end with this!
MITK_TEST_END();
}
diff --git a/Modules/FiberTracking/Testing/mitkFiberMapper3DTest.cpp b/Modules/FiberTracking/Testing/mitkFiberMapper3DTest.cpp
index 3bf80da..209d692 100644
--- a/Modules/FiberTracking/Testing/mitkFiberMapper3DTest.cpp
+++ b/Modules/FiberTracking/Testing/mitkFiberMapper3DTest.cpp
@@ -1,165 +1,165 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkNodePredicateDataType.h>
#include <mitkRenderingTestHelper.h>
#include <mitkSmartPointerProperty.h>
#include <mitkTestingMacros.h>
#include <vtkSmartPointer.h>
#include <vtkRenderLargeImage.h>
#include "mitkTestingMacros.h"
#include <mitkFiberBundle.h>
#include <itksys/SystemTools.hxx>
#include <mitkTestingConfig.h>
#include <mitkIOUtil.h>
#include <mitkTestFixture.h>
#include <vtkTesting.h>
#include <thread>
#include <chrono>
class mitkFiberMapper3DTestSuite : public mitk::TestFixture
{
CPPUNIT_TEST_SUITE(mitkFiberMapper3DTestSuite);
MITK_TEST(Default3D);
MITK_TEST(Color3D);
MITK_TEST(Ribbon3D);
MITK_TEST(Tubes3D);
MITK_TEST(Default2D);
CPPUNIT_TEST_SUITE_END();
typedef itk::Image<float, 3> ItkFloatImgType;
private:
/** Members used inside the different (sub-)tests. All members are initialized via setUp().*/
mitk::FiberBundle::Pointer fib;
mitk::DataNode::Pointer node;
public:
void setUp() override
{
fib = mitk::IOUtil::Load<mitk::FiberBundle>(GetTestDataFilePath("DiffusionImaging/Rendering/test_fibers.fib"));
MITK_INFO << fib->GetNumFibers();
node = mitk::DataNode::New();
node->SetData(fib);
}
void tearDown() override
{
}
void AddGeneratedDataToStorage(mitk::DataStorage *dataStorage)
{
auto node = mitk::DataNode::New();
node->SetData(fib);
dataStorage->Add(node);
}
void Default2D()
{
mitk::RenderingTestHelper renderingHelper(640, 480);
renderingHelper.AddNodeToStorage(node);
renderingHelper.SetViewDirection(mitk::SliceNavigationController::Frontal);
renderingHelper.SetMapperIDToRender2D();
std::this_thread::sleep_for(std::chrono::seconds(1));
renderingHelper.SaveReferenceScreenShot(mitk::IOUtil::GetTempPath()+"fib_2D.png");
mitk::Image::Pointer test_image = mitk::IOUtil::Load<mitk::Image>(mitk::IOUtil::GetTempPath()+"fib_2D.png");
mitk::Image::Pointer ref_image = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/Rendering/fib_2D.png"));
MITK_ASSERT_EQUAL(test_image, ref_image, "Check if images are equal.");
}
void Default3D()
{
mitk::RenderingTestHelper renderingHelper(640, 480);
renderingHelper.AddNodeToStorage(node);
renderingHelper.SetMapperIDToRender3D();
std::this_thread::sleep_for(std::chrono::seconds(1));
renderingHelper.SaveReferenceScreenShot(mitk::IOUtil::GetTempPath()+"fib_3D.png");
mitk::Image::Pointer test_image = mitk::IOUtil::Load<mitk::Image>(mitk::IOUtil::GetTempPath()+"fib_3D.png");
mitk::Image::Pointer ref_image = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/Rendering/fib_3D.png"));
MITK_ASSERT_EQUAL(test_image, ref_image, "Check if images are equal.");
}
void Tubes3D()
{
node->SetFloatProperty("shape.tuberadius", 1);
mitk::RenderingTestHelper renderingHelper(640, 480);
renderingHelper.AddNodeToStorage(node);
renderingHelper.SetMapperIDToRender3D();
std::this_thread::sleep_for(std::chrono::seconds(1));
renderingHelper.SaveReferenceScreenShot(mitk::IOUtil::GetTempPath()+"fib_tubes_3D.png");
mitk::Image::Pointer test_image = mitk::IOUtil::Load<mitk::Image>(mitk::IOUtil::GetTempPath()+"fib_tubes_3D.png");
mitk::Image::Pointer ref_image = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/Rendering/fib_tubes_3D.png"));
MITK_ASSERT_EQUAL(test_image, ref_image, "Check if images are equal.");
}
void Ribbon3D()
{
node->SetFloatProperty("shape.ribbonwidth", 1);
mitk::RenderingTestHelper renderingHelper(640, 480);
renderingHelper.AddNodeToStorage(node);
renderingHelper.SetMapperIDToRender3D();
std::this_thread::sleep_for(std::chrono::seconds(1));
renderingHelper.SaveReferenceScreenShot(mitk::IOUtil::GetTempPath()+"fib_ribbon_3D.png");
mitk::Image::Pointer test_image = mitk::IOUtil::Load<mitk::Image>(mitk::IOUtil::GetTempPath()+"fib_ribbon_3D.png");
mitk::Image::Pointer ref_image = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/Rendering/fib_ribbon_3D.png"));
MITK_ASSERT_EQUAL(test_image, ref_image, "Check if images are equal.");
}
void Line3D()
{
node->SetFloatProperty("shape.linewidth", 1);
mitk::RenderingTestHelper renderingHelper(640, 480);
renderingHelper.AddNodeToStorage(node);
renderingHelper.SetMapperIDToRender3D();
std::this_thread::sleep_for(std::chrono::seconds(1));
renderingHelper.SaveReferenceScreenShot(mitk::IOUtil::GetTempPath()+"fib_line_3D.png");
mitk::Image::Pointer test_image = mitk::IOUtil::Load<mitk::Image>(mitk::IOUtil::GetTempPath()+"fib_line_3D.png");
mitk::Image::Pointer ref_image = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/Rendering/fib_line_3D.png"));
MITK_ASSERT_EQUAL(test_image, ref_image, "Check if images are equal.");
}
void Color3D()
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
fib->SetFiberColors(255, 255, 255);
mitk::RenderingTestHelper renderingHelper(640, 480);
renderingHelper.AddNodeToStorage(node);
renderingHelper.SetMapperIDToRender3D();
std::this_thread::sleep_for(std::chrono::seconds(1));
renderingHelper.SaveReferenceScreenShot(mitk::IOUtil::GetTempPath()+"fib_color_3D.png");
mitk::Image::Pointer test_image = mitk::IOUtil::Load<mitk::Image>(mitk::IOUtil::GetTempPath()+"fib_color_3D.png");
mitk::Image::Pointer ref_image = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/Rendering/fib_color_3D.png"));
MITK_ASSERT_EQUAL(test_image, ref_image, "Check if images are equal.");
}
};
MITK_TEST_SUITE_REGISTRATION(mitkFiberMapper3D)
diff --git a/Modules/FiberTracking/Testing/mitkFiberProcessingTest.cpp b/Modules/FiberTracking/Testing/mitkFiberProcessingTest.cpp
index 48f1244..f4ad800 100644
--- a/Modules/FiberTracking/Testing/mitkFiberProcessingTest.cpp
+++ b/Modules/FiberTracking/Testing/mitkFiberProcessingTest.cpp
@@ -1,304 +1,304 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkTestingMacros.h"
#include <mitkFiberBundle.h>
#include <mitkBaseData.h>
#include <itksys/SystemTools.hxx>
#include <mitkTestingConfig.h>
#include <mitkIOUtil.h>
#include <itkFiberCurvatureFilter.h>
#include <omp.h>
#include "mitkTestFixture.h"
class mitkFiberProcessingTestSuite : public mitk::TestFixture
{
CPPUNIT_TEST_SUITE(mitkFiberProcessingTestSuite);
MITK_TEST(Test1);
MITK_TEST(Test2);
MITK_TEST(Test3);
MITK_TEST(Test4);
MITK_TEST(Test5);
MITK_TEST(Test6);
MITK_TEST(Test7);
MITK_TEST(Test8);
MITK_TEST(Test9);
MITK_TEST(Test10);
MITK_TEST(Test11);
MITK_TEST(Test12);
MITK_TEST(Test13);
MITK_TEST(Test14);
MITK_TEST(Test15);
MITK_TEST(Test16);
MITK_TEST(Test17);
MITK_TEST(Test18);
CPPUNIT_TEST_SUITE_END();
typedef itk::Image<unsigned char, 3> ItkUcharImgType;
private:
/** Members used inside the different (sub-)tests. All members are initialized via setUp().*/
mitk::FiberBundle::Pointer original;
ItkUcharImgType::Pointer mask;
public:
void setUp() override
{
omp_set_num_threads(1);
original = nullptr;
original = mitk::IOUtil::Load<mitk::FiberBundle>(GetTestDataFilePath("DiffusionImaging/FiberProcessing/original.fib"));
mitk::Image::Pointer img = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/FiberProcessing/MASK.nrrd"));
mask = ItkUcharImgType::New();
mitk::CastToItkImage(img, mask);
}
void tearDown() override
{
original = nullptr;
}
void Test1()
{
MITK_INFO << "TEST 1: Remove by direction";
mitk::FiberBundle::Pointer fib = original->GetDeepCopy();
vnl_vector_fixed<double,3> dir;
dir[0] = 0;
dir[1] = 1;
dir[2] = 0;
fib->RemoveDir(dir,cos(5.0*itk::Math::pi/180));
mitk::FiberBundle::Pointer ref = mitk::IOUtil::Load<mitk::FiberBundle>(GetTestDataFilePath("DiffusionImaging/FiberProcessing/remove_direction.fib"));
CPPUNIT_ASSERT_MESSAGE("Should be equal", ref->Equals(fib));
}
void Test2()
{
MITK_INFO << "TEST 2: Remove by length";
mitk::FiberBundle::Pointer fib = original->GetDeepCopy();
fib->RemoveShortFibers(30);
fib->RemoveLongFibers(40);
mitk::FiberBundle::Pointer ref = mitk::IOUtil::Load<mitk::FiberBundle>(GetTestDataFilePath("DiffusionImaging/FiberProcessing/remove_length.fib"));
CPPUNIT_ASSERT_MESSAGE("Should be equal", ref->Equals(fib));
}
void Test3()
{
MITK_INFO << "TEST 3: Remove by curvature 1";
mitk::FiberBundle::Pointer fib = original->GetDeepCopy();
auto filter = itk::FiberCurvatureFilter::New();
filter->SetInputFiberBundle(fib);
filter->SetAngularDeviation(30);
filter->SetDistance(5);
filter->SetRemoveFibers(false);
filter->SetUseMedian(true);
filter->Update();
mitk::FiberBundle::Pointer ref = mitk::IOUtil::Load<mitk::FiberBundle>(GetTestDataFilePath("DiffusionImaging/FiberProcessing/remove_curvature1.fib"));
CPPUNIT_ASSERT_MESSAGE("Should be equal", ref->Equals(filter->GetOutputFiberBundle()));
}
void Test4()
{
MITK_INFO << "TEST 4: Remove by curvature 2";
mitk::FiberBundle::Pointer fib = original->GetDeepCopy();
auto filter = itk::FiberCurvatureFilter::New();
filter->SetInputFiberBundle(fib);
filter->SetAngularDeviation(30);
filter->SetDistance(5);
filter->SetRemoveFibers(true);
filter->SetUseMedian(true);
filter->Update();
mitk::FiberBundle::Pointer ref = mitk::IOUtil::Load<mitk::FiberBundle>(GetTestDataFilePath("DiffusionImaging/FiberProcessing/remove_curvature2.fib"));
CPPUNIT_ASSERT_MESSAGE("Should be equal", ref->Equals(filter->GetOutputFiberBundle()));
}
void Test5()
{
MITK_INFO << "TEST 5: Remove outside mask";
mitk::FiberBundle::Pointer fib = original->GetDeepCopy();
fib = fib->RemoveFibersOutside(mask);
mitk::FiberBundle::Pointer ref = mitk::IOUtil::Load<mitk::FiberBundle>(GetTestDataFilePath("DiffusionImaging/FiberProcessing/remove_outside.fib"));
// mitk::IOUtil::Save(fib, mitk::IOUtil::GetTempPath()+"remove_outside.fib");
CPPUNIT_ASSERT_MESSAGE("Should be equal", ref->Equals(fib));
}
void Test6()
{
MITK_INFO << "TEST 6: Remove inside mask";
mitk::FiberBundle::Pointer fib = original->GetDeepCopy();
fib = fib->RemoveFibersOutside(mask, true);
mitk::FiberBundle::Pointer ref = mitk::IOUtil::Load<mitk::FiberBundle>(GetTestDataFilePath("DiffusionImaging/FiberProcessing/remove_inside.fib"));
CPPUNIT_ASSERT_MESSAGE("Should be equal", ref->Equals(fib));
}
void Test7()
{
MITK_INFO << "TEST 7: Modify resample spline";
mitk::FiberBundle::Pointer fib = original->GetDeepCopy();
fib->ResampleSpline(5);
mitk::FiberBundle::Pointer ref = mitk::IOUtil::Load<mitk::FiberBundle>(GetTestDataFilePath("DiffusionImaging/FiberProcessing/modify_resample.fib"));
CPPUNIT_ASSERT_MESSAGE("Should be equal", ref->Equals(fib));
}
void Test8()
{
MITK_INFO << "TEST 8: Modify compress";
mitk::FiberBundle::Pointer fib = original->GetDeepCopy();
fib->Compress(0.1f);
mitk::FiberBundle::Pointer ref = mitk::IOUtil::Load<mitk::FiberBundle>(GetTestDataFilePath("DiffusionImaging/FiberProcessing/modify_compress.fib"));
CPPUNIT_ASSERT_MESSAGE("Should be equal", ref->Equals(fib));
}
void Test9()
{
MITK_INFO << "TEST 9: Modify sagittal mirror";
mitk::FiberBundle::Pointer fib = original->GetDeepCopy();
fib->MirrorFibers(0);
mitk::FiberBundle::Pointer ref = mitk::IOUtil::Load<mitk::FiberBundle>(GetTestDataFilePath("DiffusionImaging/FiberProcessing/modify_sagittal_mirror.fib"));
CPPUNIT_ASSERT_MESSAGE("Should be equal", ref->Equals(fib));
}
void Test10()
{
MITK_INFO << "TEST 10: Modify coronal mirror";
mitk::FiberBundle::Pointer fib = original->GetDeepCopy();
fib->MirrorFibers(1);
mitk::FiberBundle::Pointer ref = mitk::IOUtil::Load<mitk::FiberBundle>(GetTestDataFilePath("DiffusionImaging/FiberProcessing/modify_coronal_mirror.fib"));
CPPUNIT_ASSERT_MESSAGE("Should be equal", ref->Equals(fib));
}
void Test11()
{
MITK_INFO << "TEST 11: Modify axial mirror";
mitk::FiberBundle::Pointer fib = original->GetDeepCopy();
fib->MirrorFibers(2);
mitk::FiberBundle::Pointer ref = mitk::IOUtil::Load<mitk::FiberBundle>(GetTestDataFilePath("DiffusionImaging/FiberProcessing/modify_axial_mirror.fib"));
CPPUNIT_ASSERT_MESSAGE("Should be equal", ref->Equals(fib));
}
void Test12()
{
MITK_INFO << "TEST 12: Weight and join";
mitk::FiberBundle::Pointer fib = original->GetDeepCopy();
fib->SetFiberWeights(0.1f);
mitk::FiberBundle::Pointer fib2 = original->GetDeepCopy();
fib2->SetFiberWeight(3, 0.5);
fib = fib->AddBundle(fib2);
mitk::FiberBundle::Pointer ref = mitk::IOUtil::Load<mitk::FiberBundle>(GetTestDataFilePath("DiffusionImaging/FiberProcessing/modify_weighted_joined.fib"));
CPPUNIT_ASSERT_MESSAGE("Number of fibers", ref->GetNumFibers() == fib->GetNumFibers());
for (unsigned int i=0; i<ref->GetNumFibers(); i++)
CPPUNIT_ASSERT_MESSAGE("Fiber weights", ref->GetFiberWeight(i) == fib->GetFiberWeight(i));
}
void Test13()
{
MITK_INFO << "TEST 13: Subtract";
mitk::FiberBundle::Pointer fib = original->GetDeepCopy();
mitk::FiberBundle::Pointer fib2 = mitk::IOUtil::Load<mitk::FiberBundle>(GetTestDataFilePath("DiffusionImaging/FiberProcessing/remove_length.fib"));
fib = fib->SubtractBundle(fib2);
mitk::FiberBundle::Pointer ref = mitk::IOUtil::Load<mitk::FiberBundle>(GetTestDataFilePath("DiffusionImaging/FiberProcessing/subtracted.fib"));
CPPUNIT_ASSERT_MESSAGE("Should be equal", ref->Equals(fib));
}
void Test14()
{
MITK_INFO << "TEST 14: rotate";
mitk::FiberBundle::Pointer fib = original->GetDeepCopy();
fib->TransformFibers(1,2,3,0,0,0);
mitk::FiberBundle::Pointer ref = mitk::IOUtil::Load<mitk::FiberBundle>(GetTestDataFilePath("DiffusionImaging/FiberProcessing/transform_rotate.fib"));
CPPUNIT_ASSERT_MESSAGE("Should be equal", ref->Equals(fib));
}
void Test15()
{
MITK_INFO << "TEST 15: translate";
mitk::FiberBundle::Pointer fib = original->GetDeepCopy();
fib->TransformFibers(0,0,0,1,2,3);
mitk::FiberBundle::Pointer ref = mitk::IOUtil::Load<mitk::FiberBundle>(GetTestDataFilePath("DiffusionImaging/FiberProcessing/transform_translate.fib"));
CPPUNIT_ASSERT_MESSAGE("Should be equal", ref->Equals(fib));
}
void Test16()
{
MITK_INFO << "TEST 16: scale 1";
mitk::FiberBundle::Pointer fib = original->GetDeepCopy();
fib->ScaleFibers(0.1, 0.2, 0.3);
mitk::FiberBundle::Pointer ref = mitk::IOUtil::Load<mitk::FiberBundle>(GetTestDataFilePath("DiffusionImaging/FiberProcessing/transform_scale1.fib"));
CPPUNIT_ASSERT_MESSAGE("Should be equal", ref->Equals(fib));
}
void Test17()
{
MITK_INFO << "TEST 17: scale 2";
mitk::FiberBundle::Pointer fib = original->GetDeepCopy();
fib->ScaleFibers(0.1, 0.2, 0.3, false);
mitk::FiberBundle::Pointer ref = mitk::IOUtil::Load<mitk::FiberBundle>(GetTestDataFilePath("DiffusionImaging/FiberProcessing/transform_scale2.fib"));
CPPUNIT_ASSERT_MESSAGE("Should be equal", ref->Equals(fib));
}
void Test18()
{
MITK_INFO << "TEST 18: Modify resample linear";
mitk::FiberBundle::Pointer fib = original->GetDeepCopy();
fib->ResampleLinear();
mitk::FiberBundle::Pointer ref = mitk::IOUtil::Load<mitk::FiberBundle>(GetTestDataFilePath("DiffusionImaging/FiberProcessing/modify_resample_linear.fib"));
// mitk::IOUtil::Save(fib, mitk::IOUtil::GetTempPath()+"modify_resample_linear.fib");
CPPUNIT_ASSERT_MESSAGE("Should be equal", ref->Equals(fib));
}
};
MITK_TEST_SUITE_REGISTRATION(mitkFiberProcessing)
diff --git a/Modules/FiberTracking/Testing/mitkFiberTransformationTest.cpp b/Modules/FiberTracking/Testing/mitkFiberTransformationTest.cpp
index 05ccce0..78b563f 100644
--- a/Modules/FiberTracking/Testing/mitkFiberTransformationTest.cpp
+++ b/Modules/FiberTracking/Testing/mitkFiberTransformationTest.cpp
@@ -1,55 +1,55 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkTestingMacros.h>
#include <mitkIOUtil.h>
#include <mitkFiberBundle.h>
#include <omp.h>
/**Documentation
* Test if fiber transfortaiom methods work correctly
*/
int mitkFiberTransformationTest(int argc, char* argv[])
{
omp_set_num_threads(1);
MITK_TEST_BEGIN("mitkFiberTransformationTest");
MITK_TEST_CONDITION_REQUIRED(argc==3,"check for input data")
try{
mitk::FiberBundle::Pointer groundTruthFibs = mitk::IOUtil::Load<mitk::FiberBundle>(argv[1]);
mitk::FiberBundle::Pointer transformedFibs = mitk::IOUtil::Load<mitk::FiberBundle>(argv[2]);
groundTruthFibs->RotateAroundAxis(90, 45, 10);
groundTruthFibs->TranslateFibers(2, 3, 5);
groundTruthFibs->ScaleFibers(1, 0.1, 1.3);
groundTruthFibs->RemoveLongFibers(150);
groundTruthFibs->RemoveShortFibers(20);
groundTruthFibs->ResampleSpline(1.0);
groundTruthFibs->ApplyCurvatureThreshold(3.0, true);
groundTruthFibs->MirrorFibers(0);
groundTruthFibs->MirrorFibers(1);
groundTruthFibs->MirrorFibers(2);
MITK_TEST_CONDITION_REQUIRED(groundTruthFibs->Equals(transformedFibs),"check transformation")
}
catch(...) {
return EXIT_FAILURE;
}
// always end with this!
MITK_TEST_END();
}
diff --git a/Modules/FiberTracking/Testing/mitkGibbsTrackingTest.cpp b/Modules/FiberTracking/Testing/mitkGibbsTrackingTest.cpp
index ecb41b3..fbdcbec 100644
--- a/Modules/FiberTracking/Testing/mitkGibbsTrackingTest.cpp
+++ b/Modules/FiberTracking/Testing/mitkGibbsTrackingTest.cpp
@@ -1,92 +1,92 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkTestingMacros.h>
#include <mitkImageCast.h>
#include <mitkOdfImage.h>
#include <itkGibbsTrackingFilter.h>
#include <mitkFiberBundle.h>
#include <mitkIOUtil.h>
using namespace mitk;
/**Documentation
* Test for gibbs tracking filter
*/
int mitkGibbsTrackingTest(int argc, char* argv[])
{
MITK_TEST_BEGIN("mitkGibbsTrackingTest");
MITK_TEST_CONDITION_REQUIRED(argc>4,"check for input data")
OdfImage::Pointer mitkOdfImage;
Image::Pointer mitkMaskImage;
mitk::FiberBundle::Pointer fib1;
try{
MITK_INFO << "ODF image: " << argv[1];
MITK_INFO << "Mask image: " << argv[2];
MITK_INFO << "Parameter file: " << argv[3];
MITK_INFO << "Reference bundle: " << argv[4];
std::vector<mitk::BaseData::Pointer> infile = mitk::IOUtil::Load( argv[1]);
mitkOdfImage = dynamic_cast<mitk::OdfImage*>(infile.at(0).GetPointer());
MITK_TEST_CONDITION_REQUIRED(mitkOdfImage.IsNotNull(),"check Odf image")
infile = mitk::IOUtil::Load( argv[2] );
mitkMaskImage = dynamic_cast<mitk::Image*>(infile.at(0).GetPointer());
MITK_TEST_CONDITION_REQUIRED(mitkMaskImage.IsNotNull(),"check mask image")
infile = mitk::IOUtil::Load( argv[4]);
fib1 = dynamic_cast<mitk::FiberBundle*>(infile.at(0).GetPointer());
MITK_TEST_CONDITION_REQUIRED(fib1.IsNotNull(),"check fiber bundle")
typedef itk::Vector<float, ODF_SAMPLING_SIZE> OdfVectorType;
typedef itk::Image<OdfVectorType,3> OdfVectorImgType;
typedef itk::Image<float,3> MaskImgType;
typedef itk::GibbsTrackingFilter<OdfVectorImgType> GibbsTrackingFilterType;
OdfVectorImgType::Pointer itk_odf = OdfVectorImgType::New();
mitk::CastToItkImage(mitkOdfImage, itk_odf);
MaskImgType::Pointer itk_mask = MaskImgType::New();
mitk::CastToItkImage(mitkMaskImage, itk_mask);
GibbsTrackingFilterType::Pointer gibbsTracker = GibbsTrackingFilterType::New();
gibbsTracker->SetOdfImage(itk_odf.GetPointer());
gibbsTracker->SetMaskImage(itk_mask);
gibbsTracker->SetDuplicateImage(false);
gibbsTracker->SetRandomSeed(1);
gibbsTracker->SetLoadParameterFile(argv[3]);
gibbsTracker->Update();
mitk::FiberBundle::Pointer fib2 = mitk::FiberBundle::New(gibbsTracker->GetFiberBundle());
MITK_TEST_CONDITION_REQUIRED(fib1->Equals(fib2), "check if gibbs tracking has changed");
gibbsTracker->SetRandomSeed(0);
gibbsTracker->Update();
fib2 = mitk::FiberBundle::New(gibbsTracker->GetFiberBundle());
MITK_TEST_CONDITION_REQUIRED(!fib1->Equals(fib2), "check if gibbs tracking has changed after wrong seed");
}
catch(...)
{
return EXIT_FAILURE;
}
// always end with this!
MITK_TEST_END();
}
diff --git a/Modules/FiberTracking/Testing/mitkMachineLearningTrackingTest.cpp b/Modules/FiberTracking/Testing/mitkMachineLearningTrackingTest.cpp
index 2dc7824..5db0591 100644
--- a/Modules/FiberTracking/Testing/mitkMachineLearningTrackingTest.cpp
+++ b/Modules/FiberTracking/Testing/mitkMachineLearningTrackingTest.cpp
@@ -1,110 +1,110 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkTestingMacros.h"
#include <mitkFiberBundle.h>
#include <mitkBaseData.h>
#include <itksys/SystemTools.hxx>
#include <mitkTestingConfig.h>
#include <mitkIOUtil.h>
#include <itkStreamlineTrackingFilter.h>
#include <mitkTrackingHandlerRandomForest.h>
#include <mitkImageCast.h>
#include <mitkImageToItk.h>
#include <omp.h>
#include <mitkTractographyForest.h>
#include <mitkStreamlineTractographyParameters.h>
#include "mitkTestFixture.h"
class mitkMachineLearningTrackingTestSuite : public mitk::TestFixture
{
CPPUNIT_TEST_SUITE(mitkMachineLearningTrackingTestSuite);
MITK_TEST(Track1);
CPPUNIT_TEST_SUITE_END();
typedef itk::Image<float, 3> ItkFloatImgType;
private:
/** Members used inside the different (sub-)tests. All members are initialized via setUp().*/
mitk::FiberBundle::Pointer ref;
mitk::TrackingHandlerRandomForest<6, 100>* tfh;
mitk::Image::Pointer dwi;
ItkFloatImgType::Pointer seed;
public:
void setUp() override
{
ref = nullptr;
tfh = new mitk::TrackingHandlerRandomForest<6,100>();
std::vector<mitk::BaseData::Pointer> fibInfile = mitk::IOUtil::Load(GetTestDataFilePath("DiffusionImaging/MachineLearningTracking/ReferenceTracts.fib"));
mitk::BaseData::Pointer baseData = fibInfile.at(0);
ref = dynamic_cast<mitk::FiberBundle*>(baseData.GetPointer());
dwi = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/MachineLearningTracking/DiffusionImage.dwi"));
mitk::Image::Pointer img = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/MachineLearningTracking/seed.nrrd"));
seed = ItkFloatImgType::New();
mitk::CastToItkImage(img, seed);
mitk::TractographyForest::Pointer forest = mitk::IOUtil::Load<mitk::TractographyForest>(GetTestDataFilePath("DiffusionImaging/MachineLearningTracking/forest.rf"));
tfh->SetForest(forest);
tfh->AddDwi(dwi);
}
void tearDown() override
{
delete tfh;
ref = nullptr;
}
void Track1()
{
std::shared_ptr<mitk::StreamlineTractographyParameters> params = std::make_shared<mitk::StreamlineTractographyParameters>();
params->m_RandomSampling = false;
params->SetSamplingDistanceVox(0.5);
params->m_AvoidStop = true;
params->SetAngularThresholdDeg(45);
params->SetStepSizeVox(-1);
params->m_SeedsPerVoxel = 1;
params->m_InterpolateRoiImages = false;
omp_set_num_threads(1);
typedef itk::StreamlineTrackingFilter TrackerType;
TrackerType::Pointer tracker = TrackerType::New();
tracker->SetDemoMode(false);
tracker->SetSeedImage(seed);
tracker->SetTrackingHandler(tfh);
tracker->SetParameters(params);
tracker->Update();
vtkSmartPointer< vtkPolyData > poly = tracker->GetFiberPolyData();
mitk::FiberBundle::Pointer outFib = mitk::FiberBundle::New(poly);
//MITK_INFO << mitk::IOUtil::GetTempPath() << "ReferenceTracts.fib";
if (!ref->Equals(outFib))
mitk::IOUtil::Save(outFib, mitk::IOUtil::GetTempPath()+"ML_Track1.fib");
CPPUNIT_ASSERT_MESSAGE("Should be equal", ref->Equals(outFib));
}
};
MITK_TEST_SUITE_REGISTRATION(mitkMachineLearningTracking)
diff --git a/Modules/FiberTracking/Testing/mitkPeakShImageReaderTest.cpp b/Modules/FiberTracking/Testing/mitkPeakShImageReaderTest.cpp
index 49335b3..7d5b9af 100644
--- a/Modules/FiberTracking/Testing/mitkPeakShImageReaderTest.cpp
+++ b/Modules/FiberTracking/Testing/mitkPeakShImageReaderTest.cpp
@@ -1,127 +1,127 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkNodePredicateDataType.h>
#include <mitkRenderingTestHelper.h>
#include <mitkSmartPointerProperty.h>
#include <mitkTestingMacros.h>
#include <vtkSmartPointer.h>
#include "mitkTestingMacros.h"
#include <itksys/SystemTools.hxx>
#include <mitkTestingConfig.h>
#include <mitkIOUtil.h>
#include <mitkTestFixture.h>
#include <vtkTesting.h>
#include <mitkPeakImage.h>
#include <mitkShImage.h>
#include <mitkPreferenceListReaderOptionsFunctor.h>
#include <mitkImagePixelReadAccessor.h>
class mitkPeakShImageReaderTestSuite : public mitk::TestFixture
{
CPPUNIT_TEST_SUITE(mitkPeakShImageReaderTestSuite);
MITK_TEST(PeakReader);
MITK_TEST(ShReader);
CPPUNIT_TEST_SUITE_END();
typedef itk::Image<float, 3> ItkFloatImgType;
private:
/** Members used inside the different (sub-)tests. All members are initialized via setUp().*/
public:
void setUp() override
{
}
void tearDown() override
{
}
void PeakReader()
{
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Peak Image"}, {});
auto inputData = mitk::IOUtil::Load<mitk::PeakImage>(GetTestDataFilePath("DiffusionImaging/peak_image_test.nii.gz"), &functor);
std::string class_name = "PeakImage";
bool ok = true;
if (class_name.compare(inputData->GetNameOfClass())!=0)
ok = false;
MITK_TEST_CONDITION_REQUIRED(ok, "Check class name = PeakImage");
mitk::Vector3D sp;
sp[0] = 1.23;
sp[1] = 2.001;
sp[2] = 1.409;
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(sp, inputData->GetGeometry()->GetSpacing(), 0.0001, true), "Check spacing ok");
mitk::Point3D o;
o[0] = 0.615;
o[1] = 1.0005;
o[2] = 0.7045;
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(o, inputData->GetGeometry()->GetOrigin(), 0.0001, true), "Check origin ok");
mitk::ImagePixelReadAccessor<mitk::PeakImage::PixelType, 4> readAccess(inputData);
itk::Index<4> idx;
idx[0] = 5;
idx[1] = 4;
idx[2] = 1;
idx[3] = 0;
MITK_TEST_CONDITION_REQUIRED(fabs(-0.997147f-readAccess.GetPixelByIndex(idx))<0.0001f, "Check pixel value ok");
}
void ShReader()
{
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"SH Image"}, {});
auto inputData = mitk::IOUtil::Load<mitk::ShImage>(GetTestDataFilePath("DiffusionImaging/sh_image_test.nii.gz"), &functor);
std::string class_name = "ShImage";
bool ok = true;
if (class_name.compare(inputData->GetNameOfClass())!=0)
ok = false;
MITK_TEST_CONDITION_REQUIRED(ok, "Check class name = ShImage");
mitk::Vector3D sp;
sp[0] = 1.23;
sp[1] = 2.001;
sp[2] = 1.409;
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(sp, inputData->GetGeometry()->GetSpacing(), 0.0001, true), "Check spacing ok");
mitk::Point3D o;
o[0] = 0.615;
o[1] = 1.0005;
o[2] = 0.7045;
MITK_TEST_CONDITION_REQUIRED(mitk::Equal(o, inputData->GetGeometry()->GetOrigin(), 0.0001, true), "Check origin ok");
mitk::ImagePixelReadAccessor<itk::Vector<float, 15>, 3> readAccess(inputData);
itk::Index<3> idx;
idx[0] = 5;
idx[1] = 4;
idx[2] = 1;
itk::Vector<float, 15> pixel = readAccess.GetPixelByIndex(idx);
MITK_TEST_CONDITION_REQUIRED(fabs(0.282095f-pixel[0])<0.000001f, "Check SH coeff value 0 ok");
MITK_TEST_CONDITION_REQUIRED(fabs(-0.00900571f-pixel[2])<0.000001f, "Check SH coeff value 2 ok");
MITK_TEST_CONDITION_REQUIRED(fabs(0.0513185f-pixel[6])<0.000001f, "Check SH coeff value 6 ok");
}
};
MITK_TEST_SUITE_REGISTRATION(mitkPeakShImageReader)
diff --git a/Modules/FiberTracking/Testing/mitkStreamlineTractographyTest.cpp b/Modules/FiberTracking/Testing/mitkStreamlineTractographyTest.cpp
index 0b39b98..8922705 100644
--- a/Modules/FiberTracking/Testing/mitkStreamlineTractographyTest.cpp
+++ b/Modules/FiberTracking/Testing/mitkStreamlineTractographyTest.cpp
@@ -1,438 +1,438 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkImageCast.h>
#include <mitkImageToItk.h>
#include <mitkTensorImage.h>
#include <mitkOdfImage.h>
#include <mitkIOUtil.h>
#include <mitkFiberBundle.h>
#include <itkStreamlineTrackingFilter.h>
#include <Algorithms/TrackingHandlers/mitkTrackingDataHandler.h>
#include <Algorithms/TrackingHandlers/mitkTrackingHandlerOdf.h>
#include <Algorithms/TrackingHandlers/mitkTrackingHandlerPeaks.h>
#include <Algorithms/TrackingHandlers/mitkTrackingHandlerTensor.h>
#include <itkDiffusionTensor3D.h>
#include <mitkTestingMacros.h>
#include <mitkTestFixture.h>
#include <mitkFiberBundle.h>
#include <omp.h>
#include <itksys/SystemTools.hxx>
#include <mitkEqual.h>
#include <mitkStreamlineTractographyParameters.h>
class mitkStreamlineTractographyTestSuite : public mitk::TestFixture
{
CPPUNIT_TEST_SUITE(mitkStreamlineTractographyTestSuite);
MITK_TEST(Test_Peak1);
MITK_TEST(Test_Peak2);
MITK_TEST(Test_Tensor1);
MITK_TEST(Test_Tensor2);
MITK_TEST(Test_Tensor3);
MITK_TEST(Test_Odf1);
MITK_TEST(Test_Odf2);
MITK_TEST(Test_Odf3);
MITK_TEST(Test_Odf4);
MITK_TEST(Test_Odf5);
MITK_TEST(Test_Odf6);
CPPUNIT_TEST_SUITE_END();
typedef itk::VectorImage< short, 3> ItkDwiType;
private:
public:
/** Members used inside the different (sub-)tests. All members are initialized via setUp().*/
typedef itk::Image<float, 3> ItkFloatImgType;
mitk::TrackingHandlerOdf::ItkOdfImageType::Pointer itk_odf_image;
mitk::TrackingHandlerTensor::ItkTensorImageType::ConstPointer itk_tensor_image;
mitk::TrackingHandlerPeaks::PeakImgType::Pointer itk_peak_image;
ItkFloatImgType::Pointer itk_seed_image;
ItkFloatImgType::Pointer itk_mask_image;
ItkFloatImgType::Pointer itk_gfa_image;
float gfa_threshold;
float odf_threshold;
float peak_threshold;
std::shared_ptr<mitk::StreamlineTractographyParameters> params;
itk::StreamlineTrackingFilter::Pointer tracker;
void setUp() override
{
omp_set_num_threads(1);
gfa_threshold = 0.2f;
odf_threshold = 0.1f;
peak_threshold = 0.1f;
mitk::Image::Pointer odf_image = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/StreamlineTractography/qball_image.qbi"));
mitk::Image::Pointer tensor_image = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/StreamlineTractography/tensor_image.dti"));
mitk::Image::Pointer peak_image = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/StreamlineTractography/qball_peak_image.nii.gz"));
mitk::Image::Pointer seed_image = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/StreamlineTractography/seed_image.nii.gz"));
mitk::Image::Pointer mask_image = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/StreamlineTractography/mask_image.nii.gz"));
mitk::Image::Pointer gfa_image = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/StreamlineTractography/gfa_image.nii.gz"));
params = std::make_shared<mitk::StreamlineTractographyParameters>();
params->m_FixRandomSeed = true;
params->m_InterpolateRoiImages = false;
{
typedef mitk::ImageToItk< mitk::TrackingHandlerPeaks::PeakImgType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(peak_image);
caster->Update();
itk_peak_image = caster->GetOutput();
}
{
typedef mitk::ImageToItk< mitk::TrackingHandlerTensor::ItkTensorImageType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(tensor_image);
caster->Update();
itk_tensor_image = caster->GetOutput();
}
{
typedef mitk::ImageToItk< mitk::TrackingHandlerOdf::ItkOdfImageType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(odf_image);
caster->Update();
itk_odf_image = caster->GetOutput();
}
itk_gfa_image = ItkFloatImgType::New();
mitk::CastToItkImage(gfa_image, itk_gfa_image);
itk_seed_image = ItkFloatImgType::New();
mitk::CastToItkImage(seed_image, itk_seed_image);
itk_mask_image = ItkFloatImgType::New();
mitk::CastToItkImage(mask_image, itk_mask_image);
}
mitk::FiberBundle::Pointer LoadReferenceFib(std::string filename)
{
mitk::FiberBundle::Pointer fib = nullptr;
if (itksys::SystemTools::FileExists(GetTestDataFilePath("DiffusionImaging/StreamlineTractography/ReferenceFibs/" + filename)))
{
mitk::BaseData::Pointer baseData = mitk::IOUtil::Load(GetTestDataFilePath("DiffusionImaging/StreamlineTractography/ReferenceFibs/" + filename)).at(0);
fib = dynamic_cast<mitk::FiberBundle*>(baseData.GetPointer());
}
return fib;
}
mitk::Image::Pointer LoadReferenceImage(std::string filename)
{
mitk::Image::Pointer img = nullptr;
if (itksys::SystemTools::FileExists(GetTestDataFilePath("DiffusionImaging/StreamlineTractography/ReferenceFibs/" + filename)))
{
img = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/StreamlineTractography/ReferenceFibs/" + filename));
}
return img;
}
void SetupTracker(mitk::TrackingDataHandler* handler)
{
tracker = itk::StreamlineTrackingFilter::New();
// tracker->SetInterpolateMasks(false);
// tracker->SetNumberOfSamples(0);
// tracker->SetAngularThreshold(-1);
tracker->SetMaskImage(itk_mask_image);
tracker->SetSeedImage(itk_seed_image);
tracker->SetStoppingRegions(nullptr);
// tracker->SetSeedsPerVoxel(1);
// tracker->SetStepSize(0.5);
// tracker->SetSamplingDistance(0.25);
// tracker->SetUseStopVotes(true);
// tracker->SetOnlyForwardSamples(true);
// tracker->SetMinTractLength(20);
// tracker->SetMaxNumTracts(-1);
tracker->SetTrackingHandler(handler);
// tracker->SetUseOutputProbabilityMap(false);
tracker->SetParameters(params);
}
void tearDown() override
{
}
void CheckFibResult(std::string ref_file, mitk::FiberBundle::Pointer test_fib)
{
mitk::FiberBundle::Pointer ref = LoadReferenceFib(ref_file);
if (ref.IsNull())
{
mitk::IOUtil::Save(test_fib, mitk::IOUtil::GetTempPath()+ref_file);
CPPUNIT_FAIL("Reference file not found. Saving test file to " + mitk::IOUtil::GetTempPath() + ref_file);
}
else
{
bool is_equal = ref->Equals(test_fib);
if (!is_equal)
{
mitk::IOUtil::Save(test_fib, mitk::IOUtil::GetTempPath()+ref_file);
CPPUNIT_FAIL("Tractograms are not equal! Saving test file to " + mitk::IOUtil::GetTempPath() + ref_file);
}
}
}
void CheckImageResult(std::string ref_file, mitk::Image::Pointer test_img)
{
mitk::Image::Pointer ref = LoadReferenceImage(ref_file);
if (ref.IsNull())
{
mitk::IOUtil::Save(test_img, mitk::IOUtil::GetTempPath()+ref_file);
CPPUNIT_FAIL("Reference file not found. Saving test file to " + mitk::IOUtil::GetTempPath() + ref_file);
}
else
{
MITK_ASSERT_EQUAL(test_img, ref, "Images should be equal");
}
}
void Test_Peak1()
{
mitk::TrackingHandlerPeaks* handler = new mitk::TrackingHandlerPeaks();
handler->SetPeakImage(itk_peak_image);
params->m_Cutoff = peak_threshold;
SetupTracker(handler);
tracker->Update();
vtkSmartPointer< vtkPolyData > poly = tracker->GetFiberPolyData();
mitk::FiberBundle::Pointer outFib = mitk::FiberBundle::New(poly);
CheckFibResult("Test_Peak1.fib", outFib);
delete handler;
}
void Test_Peak2()
{
mitk::TrackingHandlerPeaks* handler = new mitk::TrackingHandlerPeaks();
handler->SetPeakImage(itk_peak_image);
params->m_Cutoff = peak_threshold;
params->m_InterpolateTractographyData = false;
SetupTracker(handler);
tracker->Update();
vtkSmartPointer< vtkPolyData > poly = tracker->GetFiberPolyData();
mitk::FiberBundle::Pointer outFib = mitk::FiberBundle::New(poly);
CheckFibResult("Test_Peak2.fib", outFib);
delete handler;
}
void Test_Tensor1()
{
mitk::TrackingHandlerTensor* handler = new mitk::TrackingHandlerTensor();
handler->SetTensorImage(itk_tensor_image);
params->m_Cutoff = gfa_threshold;
SetupTracker(handler);
tracker->Update();
vtkSmartPointer< vtkPolyData > poly = tracker->GetFiberPolyData();
mitk::FiberBundle::Pointer outFib = mitk::FiberBundle::New(poly);
CheckFibResult("Test_Tensor1.fib", outFib);
delete handler;
}
void Test_Tensor2()
{
mitk::TrackingHandlerTensor* handler = new mitk::TrackingHandlerTensor();
handler->SetTensorImage(itk_tensor_image);
params->m_Cutoff = gfa_threshold;
params->m_InterpolateTractographyData = false;
SetupTracker(handler);
tracker->Update();
vtkSmartPointer< vtkPolyData > poly = tracker->GetFiberPolyData();
mitk::FiberBundle::Pointer outFib = mitk::FiberBundle::New(poly);
CheckFibResult("Test_Tensor2.fib", outFib);
delete handler;
}
void Test_Tensor3()
{
mitk::TrackingHandlerTensor* handler = new mitk::TrackingHandlerTensor();
handler->SetTensorImage(itk_tensor_image);
params->m_Cutoff = gfa_threshold;
params->m_InterpolateTractographyData = false;
params->m_F = 0;
params->m_G = 1;
SetupTracker(handler);
tracker->Update();
vtkSmartPointer< vtkPolyData > poly = tracker->GetFiberPolyData();
mitk::FiberBundle::Pointer outFib = mitk::FiberBundle::New(poly);
CheckFibResult("Test_Tensor3.fib", outFib);
delete handler;
}
void Test_Odf1()
{
mitk::TrackingHandlerOdf* handler = new mitk::TrackingHandlerOdf();
handler->SetOdfImage(itk_odf_image);
params->m_Cutoff = gfa_threshold;
params->m_OdfCutoff = 0;
params->m_SharpenOdfs = true;
SetupTracker(handler);
tracker->Update();
vtkSmartPointer< vtkPolyData > poly = tracker->GetFiberPolyData();
mitk::FiberBundle::Pointer outFib = mitk::FiberBundle::New(poly);
CheckFibResult("Test_Odf1.fib", outFib);
delete handler;
}
void Test_Odf2()
{
mitk::TrackingHandlerOdf* handler = new mitk::TrackingHandlerOdf();
handler->SetOdfImage(itk_odf_image);
params->m_Cutoff = gfa_threshold;
params->m_OdfCutoff = 0;
params->m_SharpenOdfs = false;
SetupTracker(handler);
tracker->Update();
vtkSmartPointer< vtkPolyData > poly = tracker->GetFiberPolyData();
mitk::FiberBundle::Pointer outFib = mitk::FiberBundle::New(poly);
CheckFibResult("Test_Odf2.fib", outFib);
delete handler;
}
void Test_Odf3()
{
mitk::TrackingHandlerOdf* handler = new mitk::TrackingHandlerOdf();
handler->SetOdfImage(itk_odf_image);
params->m_Cutoff = gfa_threshold;
params->m_OdfCutoff = 0;
params->m_SharpenOdfs = true;
params->m_InterpolateTractographyData = false;
SetupTracker(handler);
tracker->Update();
vtkSmartPointer< vtkPolyData > poly = tracker->GetFiberPolyData();
mitk::FiberBundle::Pointer outFib = mitk::FiberBundle::New(poly);
CheckFibResult("Test_Odf3.fib", outFib);
delete handler;
}
void Test_Odf4()
{
mitk::TrackingHandlerOdf* handler = new mitk::TrackingHandlerOdf();
handler->SetOdfImage(itk_odf_image);
params->m_Cutoff = gfa_threshold;
params->m_OdfCutoff = 0;
params->m_SharpenOdfs = true;
params->m_SeedsPerVoxel = 3;
SetupTracker(handler);
tracker->Update();
vtkSmartPointer< vtkPolyData > poly = tracker->GetFiberPolyData();
mitk::FiberBundle::Pointer outFib = mitk::FiberBundle::New(poly);
CheckFibResult("Test_Odf4.fib", outFib);
delete handler;
}
void Test_Odf5()
{
mitk::TrackingHandlerOdf* handler = new mitk::TrackingHandlerOdf();
handler->SetOdfImage(itk_odf_image);
params->m_Cutoff = gfa_threshold;
params->m_OdfCutoff = 0;
params->m_SharpenOdfs = true;
params->m_SeedsPerVoxel = 3;
params->m_Mode = mitk::TrackingDataHandler::MODE::PROBABILISTIC;
SetupTracker(handler);
tracker->Update();
vtkSmartPointer< vtkPolyData > poly = tracker->GetFiberPolyData();
mitk::FiberBundle::Pointer outFib = mitk::FiberBundle::New(poly);
CheckFibResult("Test_Odf5.fib", outFib);
delete handler;
}
void Test_Odf6()
{
mitk::TrackingHandlerOdf* handler = new mitk::TrackingHandlerOdf();
handler->SetOdfImage(itk_odf_image);
params->m_Cutoff = gfa_threshold;
params->m_OdfCutoff = 0;
params->m_SharpenOdfs = true;
params->m_SeedsPerVoxel = 10;
params->m_Mode = mitk::TrackingDataHandler::MODE::PROBABILISTIC;
params->m_OutputProbMap = true;
SetupTracker(handler);
tracker->Update();
itk::StreamlineTrackingFilter::ItkDoubleImgType::Pointer outImg = tracker->GetOutputProbabilityMap();
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk(outImg.GetPointer());
img->SetVolume(outImg->GetBufferPointer());
mitk::IOUtil::Save(img, mitk::IOUtil::GetTempPath()+"Test_Odf6.nrrd");
CheckImageResult("Test_Odf6.nrrd", img);
delete handler;
}
};
MITK_TEST_SUITE_REGISTRATION(mitkStreamlineTractography)
diff --git a/Modules/FiberTracking/mitkStreamlineTractographyParameters.cpp b/Modules/FiberTracking/mitkStreamlineTractographyParameters.cpp
index 709ddf5..ff02297 100644
--- a/Modules/FiberTracking/mitkStreamlineTractographyParameters.cpp
+++ b/Modules/FiberTracking/mitkStreamlineTractographyParameters.cpp
@@ -1,367 +1,367 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <boost/foreach.hpp>
#include <mitkLexicalCast.h>
#include <itkImageFileWriter.h>
#include <itkImageFileReader.h>
#include <mitkLog.h>
#include <algorithm>
#include <string>
#include <mitkStreamlineTractographyParameters.h>
#include <mitkDiffusionFunctionCollection.h>
mitk::StreamlineTractographyParameters::StreamlineTractographyParameters()
{
AutoAdjust();
}
mitk::StreamlineTractographyParameters::~StreamlineTractographyParameters()
{
}
void mitk::StreamlineTractographyParameters::SaveParameters(std::string filename)
{
if(filename.empty())
return;
if(".stp"!=filename.substr(filename.size()-4, 4))
filename += ".stp";
const std::string& locale = "C";
const std::string& currLocale = setlocale( LC_ALL, nullptr );
if ( locale.compare(currLocale)!=0 )
{
try
{
setlocale(LC_ALL, locale.c_str());
}
catch(...)
{
MITK_INFO << "Could not set locale " << locale;
}
}
boost::property_tree::ptree parameters;
parameters.put("seeding.seeds_per_voxel", m_SeedsPerVoxel);
parameters.put("seeding.trials_per_seed", m_TrialsPerSeed);
parameters.put("seeding.max_num_fibers", m_MaxNumFibers);
parameters.put("seeding.interactive_radius_mm", m_InteractiveRadiusMm);
parameters.put("seeding.num_interactive_seeds", m_NumInteractiveSeeds);
parameters.put("seeding.enable_interactive", m_EnableInteractive);
parameters.put("roi_constraints.ep_constraints", m_EpConstraints);
parameters.put("tractography.mode", m_Mode);
parameters.put("tractography.sharpen_odfs", m_SharpenOdfs);
parameters.put("tractography.cutoff", m_Cutoff);
parameters.put("tractography.odf_cutoff", m_OdfCutoff);
parameters.put("tractography.step_size_vox", m_StepSizeVox);
parameters.put("tractography.min_tract_length_mm", m_MinTractLengthMm);
parameters.put("tractography.max_tract_length_mm", m_MaxTractLengthMm);
parameters.put("tractography.angluar_threshold_deg", m_AngularThresholdDeg);
parameters.put("tractography.loop_check_deg", m_LoopCheckDeg);
parameters.put("tractography.f", m_F);
parameters.put("tractography.g", m_G);
parameters.put("tractography.fix_seed", m_FixRandomSeed);
parameters.put("tractography.peak_jitter", m_PeakJitter);
parameters.put("prior.weight", m_Weight);
parameters.put("prior.restrict_to_prior", m_RestrictToPrior);
parameters.put("prior.new_directions", m_NewDirectionsFromPrior);
parameters.put("prior.flip_x", m_PriorFlipX);
parameters.put("prior.flip_y", m_PriorFlipY);
parameters.put("prior.flip_z", m_PriorFlipZ);
parameters.put("nsampling.num_samples", m_NumSamples);
parameters.put("nsampling.sampling_distance_vox", m_SamplingDistanceVox);
parameters.put("nsampling.only_frontal", m_OnlyForwardSamples);
parameters.put("nsampling.stop_votes", m_StopVotes);
parameters.put("data_handling.flip_x", m_FlipX);
parameters.put("data_handling.flip_y", m_FlipY);
parameters.put("data_handling.flip_z", m_FlipZ);
parameters.put("data_handling.interpolate_tracto_data", m_InterpolateTractographyData);
parameters.put("data_handling.interpolate_roi_images", m_InterpolateRoiImages);
parameters.put("output.compress", m_CompressFibers);
parameters.put("output.compression", m_Compression);
parameters.put("output.prob_map", m_OutputProbMap);
boost::property_tree::json_parser::write_json(filename, parameters, std::locale(), true);
// try{
// itk::ImageFileWriter<ItkFloatImgType>::Pointer writer = itk::ImageFileWriter<ItkFloatImgType>::New();
// writer->SetFileName(filename+"_FMAP.nii.gz");
// writer->SetInput(m_SignalGen.m_FrequencyMap);
// writer->Update();
// }
// catch(...)
// {
// MITK_INFO << "No frequency map saved.";
// }
setlocale(LC_ALL, currLocale.c_str());
}
template< class ParameterType >
ParameterType mitk::StreamlineTractographyParameters::ReadVal(boost::property_tree::ptree::value_type const& v, std::string tag, ParameterType defaultValue, bool essential)
{
try
{
return v.second.get<ParameterType>(tag);
}
catch (...)
{
if (essential)
{
mitkThrow() << "Parameter file corrupted. Essential tag is missing: '" << tag << "'";
}
MITK_INFO << "Tag '" << tag << "' not found. Using default value '" << defaultValue << "'.";
return defaultValue;
}
}
void mitk::StreamlineTractographyParameters::LoadParameters(std::string filename)
{
if(filename.empty()) { return; }
const std::string& locale = "C";
const std::string& currLocale = setlocale( LC_ALL, nullptr );
if ( locale.compare(currLocale)!=0 )
{
try
{
setlocale(LC_ALL, locale.c_str());
}
catch(...)
{
MITK_INFO << "Could not set locale " << locale;
}
}
boost::property_tree::ptree parameterTree;
boost::property_tree::json_parser::read_json( filename, parameterTree );
BOOST_FOREACH( boost::property_tree::ptree::value_type const& v1, parameterTree )
{
if( v1.first == "seeding" )
{
m_SeedsPerVoxel = ReadVal<unsigned int>(v1,"seeds_per_voxel", m_SeedsPerVoxel);
m_TrialsPerSeed = ReadVal<unsigned int>(v1,"trials_per_seed", m_TrialsPerSeed);
m_MaxNumFibers = ReadVal<int>(v1,"max_num_fibers", m_MaxNumFibers);
m_InteractiveRadiusMm = ReadVal<float>(v1,"interactive_radius_mm", m_InteractiveRadiusMm);
m_NumInteractiveSeeds = ReadVal<unsigned int>(v1,"num_interactive_seeds", m_NumInteractiveSeeds);
m_EnableInteractive = ReadVal<bool>(v1,"enable_interactive", m_EnableInteractive);
}
else if( v1.first == "roi_constraints" )
{
switch( ReadVal<int>(v1,"ep_constraints", 0) )
{
default:
m_EpConstraints = EndpointConstraints::NONE;
break;
case 1:
m_EpConstraints = EndpointConstraints::EPS_IN_TARGET;
break;
case 2:
m_EpConstraints = EndpointConstraints::EPS_IN_TARGET_LABELDIFF;
break;
case 3:
m_EpConstraints = EndpointConstraints::EPS_IN_SEED_AND_TARGET;
break;
case 4:
m_EpConstraints = EndpointConstraints::MIN_ONE_EP_IN_TARGET;
break;
case 5:
m_EpConstraints = EndpointConstraints::ONE_EP_IN_TARGET;
break;
case 6:
m_EpConstraints = EndpointConstraints::NO_EP_IN_TARGET;
break;
}
}
else if( v1.first == "tractography" )
{
if(ReadVal<int>(v1,"mode", 0) == 0)
m_Mode = MODE::DETERMINISTIC;
else
m_Mode = MODE::PROBABILISTIC;
m_SharpenOdfs = ReadVal<bool>(v1,"sharpen_odfs", m_SharpenOdfs);
m_Cutoff = ReadVal<float>(v1,"cutoff", m_Cutoff);
m_OdfCutoff = ReadVal<float>(v1,"odf_cutoff", m_OdfCutoff);
SetStepSizeVox(ReadVal<float>(v1,"step_size_vox", m_StepSizeVox));
m_MinTractLengthMm = ReadVal<float>(v1,"min_tract_length_mm", m_MinTractLengthMm);
m_MaxTractLengthMm = ReadVal<float>(v1,"max_tract_length_mm", m_MaxTractLengthMm);
SetAngularThresholdDeg(ReadVal<float>(v1,"angluar_threshold_deg", m_AngularThresholdDeg));
SetLoopCheckDeg(ReadVal<float>(v1,"loop_check_deg", m_LoopCheckDeg));
m_F = ReadVal<float>(v1,"f", m_F);
m_G = ReadVal<float>(v1,"g", m_G);
m_FixRandomSeed = ReadVal<bool>(v1,"fix_seed", m_FixRandomSeed);
m_PeakJitter = ReadVal<float>(v1,"peak_jitter", m_PeakJitter);
}
else if( v1.first == "prior" )
{
m_Weight = ReadVal<float>(v1,"weight", m_Weight);
m_RestrictToPrior = ReadVal<bool>(v1,"restrict_to_prior", m_RestrictToPrior);
m_NewDirectionsFromPrior = ReadVal<bool>(v1,"new_directions", m_NewDirectionsFromPrior);
m_PriorFlipX = ReadVal<bool>(v1,"flip_x", m_PriorFlipX);
m_PriorFlipY = ReadVal<bool>(v1,"flip_y", m_PriorFlipY);
m_PriorFlipZ = ReadVal<bool>(v1,"flip_z", m_PriorFlipZ);
}
else if( v1.first == "nsampling" )
{
m_NumSamples = ReadVal<unsigned int>(v1,"num_samples", m_NumSamples);
m_SamplingDistanceVox = ReadVal<float>(v1,"sampling_distance_vox", m_SamplingDistanceVox);
m_OnlyForwardSamples = ReadVal<bool>(v1,"only_frontal", m_OnlyForwardSamples);
m_StopVotes = ReadVal<bool>(v1,"stop_votes", m_StopVotes);
}
else if( v1.first == "data_handling" )
{
m_FlipX = ReadVal<bool>(v1,"flip_x", m_FlipX);
m_FlipY = ReadVal<bool>(v1,"flip_y", m_FlipY);
m_FlipZ = ReadVal<bool>(v1,"flip_z", m_FlipZ);
m_InterpolateTractographyData = ReadVal<bool>(v1,"interpolate_tracto_data", m_InterpolateTractographyData);
m_InterpolateRoiImages = ReadVal<bool>(v1,"interpolate_roi_images", m_InterpolateRoiImages);
}
else if( v1.first == "output" )
{
m_CompressFibers = ReadVal<bool>(v1,"compress", m_CompressFibers);
m_Compression = ReadVal<float>(v1,"compression", m_Compression);
m_OutputProbMap = ReadVal<bool>(v1,"prob_map", m_OutputProbMap);
}
}
// try
// {
// itk::ImageFileReader<ItkFloatImgType>::Pointer reader = itk::ImageFileReader<ItkFloatImgType>::New();
// reader->SetFileName(filename+"_FMAP.nrrd");
// if ( itksys::SystemTools::FileExists(filename+"_FMAP.nii.gz") )
// reader->SetFileName(filename+"_FMAP.nii.gz");
// else if ( itksys::SystemTools::FileExists(filename+"_FMAP.nii") )
// reader->SetFileName(filename+"_FMAP.nii");
// else
// reader->SetFileName(filename+"_FMAP.nrrd");
// reader->Update();
// m_SignalGen.m_FrequencyMap = reader->GetOutput();
// MITK_INFO << "Frequency map loaded.";
// }
// catch(...)
// {
// MITK_INFO << "No frequency map found.";
// }
setlocale(LC_ALL, currLocale.c_str());
}
float mitk::StreamlineTractographyParameters::GetSamplingDistanceMm() const
{
return m_SamplingDistanceMm;
}
void mitk::StreamlineTractographyParameters::SetSamplingDistanceVox(float sampling_distance_vox)
{
m_SamplingDistanceVox = sampling_distance_vox;
AutoAdjust();
}
void mitk::StreamlineTractographyParameters::AutoAdjust()
{
if (m_StepSizeVox<static_cast<float>(mitk::eps))
m_StepSizeVox = 0.5;
m_StepSizeMm = m_StepSizeVox*m_MinVoxelSizeMm;
if (m_AngularThresholdDeg<0)
{
if (m_StepSizeMm/m_MinVoxelSizeMm<=0.966f) // minimum 15° for automatic estimation
m_AngularThresholdDot = static_cast<float>(std::cos( 0.5 * itk::Math::pi * static_cast<double>(m_StepSizeMm/m_MinVoxelSizeMm) ));
else
m_AngularThresholdDot = static_cast<float>(std::cos( 0.5 * itk::Math::pi * 0.966 ));
m_AngularThresholdDeg = std::acos(m_AngularThresholdDot)*180.0/itk::Math::pi;
}
else
m_AngularThresholdDot = static_cast<float>(std::cos( static_cast<double>(m_AngularThresholdDeg)*itk::Math::pi/180.0 ));
if (m_SamplingDistanceVox<static_cast<float>(mitk::eps))
m_SamplingDistanceVox = m_MinVoxelSizeMm*0.25f;
m_SamplingDistanceMm = m_SamplingDistanceVox*m_MinVoxelSizeMm;
}
float mitk::StreamlineTractographyParameters::GetStepSizeVox() const
{
return m_StepSizeVox;
}
float mitk::StreamlineTractographyParameters::GetAngularThresholdDeg() const
{
return m_AngularThresholdDeg;
}
float mitk::StreamlineTractographyParameters::GetSamplingDistanceVox() const
{
return m_SamplingDistanceVox;
}
float mitk::StreamlineTractographyParameters::GetMinVoxelSizeMm() const
{
return m_MinVoxelSizeMm;
}
float mitk::StreamlineTractographyParameters::GetStepSizeMm() const
{
return m_StepSizeMm;
}
void mitk::StreamlineTractographyParameters::SetMinVoxelSizeMm(float min_voxel_size_mm)
{
m_MinVoxelSizeMm = min_voxel_size_mm;
AutoAdjust();
}
float mitk::StreamlineTractographyParameters::GetAngularThresholdDot() const
{
return m_AngularThresholdDot;
}
void mitk::StreamlineTractographyParameters::SetStepSizeVox(float step_size_vox)
{
m_StepSizeVox = step_size_vox;
AutoAdjust();
}
float mitk::StreamlineTractographyParameters::GetLoopCheckDeg() const
{
return m_LoopCheckDeg;
}
void mitk::StreamlineTractographyParameters::SetLoopCheckDeg(float loop_check_deg)
{
m_LoopCheckDeg = loop_check_deg;
}
void mitk::StreamlineTractographyParameters::SetAngularThresholdDeg(float angular_threshold_deg)
{
m_AngularThresholdDeg = angular_threshold_deg;
AutoAdjust();
}
diff --git a/Modules/FiberTracking/mitkStreamlineTractographyParameters.h b/Modules/FiberTracking/mitkStreamlineTractographyParameters.h
index 77af66a..96fe4a8 100644
--- a/Modules/FiberTracking/mitkStreamlineTractographyParameters.h
+++ b/Modules/FiberTracking/mitkStreamlineTractographyParameters.h
@@ -1,163 +1,163 @@
#pragma once
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkDiffusionPropertyHelper.h>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <MitkFiberTrackingExports.h>
namespace mitk
{
/**
* \brief Datastructure to manage streamline tractography parameters.
*
*/
class MITKFIBERTRACKING_EXPORT StreamlineTractographyParameters
{
public:
enum EndpointConstraints {
NONE, ///< No constraints on endpoint locations
EPS_IN_TARGET, ///< Both EPs are required to be located in the target image
EPS_IN_TARGET_LABELDIFF, ///< Both EPs are required to be located in the target image and the image values at the respective position needs to be distinct
EPS_IN_SEED_AND_TARGET, ///< One EP is required to be located in the seed image and one in the target image
MIN_ONE_EP_IN_TARGET, ///< At least one EP is required to be located in the target image
ONE_EP_IN_TARGET, ///< Exactly one EP is required to be located in the target image
NO_EP_IN_TARGET ///< No EP is allowed to be located in the target image
};
enum MODE {
DETERMINISTIC,
PROBABILISTIC
};
typedef itk::Image<float, 3> ItkFloatImgType;
typedef itk::Image<double, 3> ItkDoubleImgType;
typedef itk::Image<unsigned char, 3> ItkUcharImgType;
StreamlineTractographyParameters();
StreamlineTractographyParameters(const StreamlineTractographyParameters &params) = default;
~StreamlineTractographyParameters();
void SaveParameters(std::string filename); ///< Save image generation parameters to .stp file.
void LoadParameters(std::string filename); ///< Load image generation parameters from .stp file.
template< class ParameterType >
ParameterType ReadVal(boost::property_tree::ptree::value_type const& v, std::string tag, ParameterType defaultValue, bool essential=false);
// seeding
unsigned int m_SeedsPerVoxel = 1;
unsigned int m_TrialsPerSeed = 10;
int m_MaxNumFibers = -1;
// - seed image
// interactive
float m_InteractiveRadiusMm = 2;
unsigned int m_NumInteractiveSeeds = 50;
bool m_EnableInteractive = false;
// ROI constraints
EndpointConstraints m_EpConstraints;
// - mask image
// - stop image
// - exclusion image
// - target image
// tractography
MODE m_Mode= MODE::DETERMINISTIC;
bool m_SharpenOdfs = false;
float m_Cutoff = 0.1;
// - fa/gfa image
float m_OdfCutoff = 0.00025;
float m_MinTractLengthMm = 20;
float m_MaxTractLengthMm = 400;
float m_F = 1;
float m_G = 0;
bool m_FixRandomSeed = false;
unsigned int m_NumPreviousDirections = 1;
float m_PeakJitter = 0.01; // actual jitter is drawn from a normal distribution with m_PeakJitter*fabs(direction_value) as standard deviation
// prior
// - peak image
float m_Weight = 0.5;
bool m_RestrictToPrior = true;
bool m_NewDirectionsFromPrior = true;
bool m_PriorFlipX = false;
bool m_PriorFlipY = false;
bool m_PriorFlipZ = false;
// neighborhood sampling
unsigned int m_NumSamples = 0;
bool m_OnlyForwardSamples = false;
bool m_StopVotes = false;
bool m_AvoidStop = true;
bool m_RandomSampling = false;
float m_DeflectionMod = 1.0;
// data handling
bool m_FlipX = false;
bool m_FlipY = false;
bool m_FlipZ = false;
bool m_InterpolateTractographyData = true;
bool m_InterpolateRoiImages;
bool m_ApplyDirectionMatrix = false;
// output and postprocessing
bool m_CompressFibers = true;
float m_Compression = 0.1;
bool m_OutputProbMap = false;
float GetAngularThresholdDot() const;
float GetAngularThresholdDeg() const;
void SetAngularThresholdDeg(float angular_threshold_deg);
float GetLoopCheckDeg() const;
void SetLoopCheckDeg(float loop_check_deg);
float GetStepSizeMm() const;
float GetStepSizeVox() const;
void SetStepSizeVox(float step_size_vox);
float GetSamplingDistanceMm() const;
float GetSamplingDistanceVox() const;
void SetSamplingDistanceVox(float sampling_distance_vox);
void SetMinVoxelSizeMm(float min_voxel_size_mm);
float GetMinVoxelSizeMm() const;
private:
void AutoAdjust();
float m_SamplingDistanceVox = -1;
float m_SamplingDistanceMm;
float m_AngularThresholdDeg = -1;
float m_AngularThresholdDot;
float m_LoopCheckDeg = -1;
float m_StepSizeVox = -1;
float m_StepSizeMm;
float m_MinVoxelSizeMm = 1.0;
};
}
diff --git a/Modules/MriSimulation/Algorithms/itkDftImageFilter.cpp b/Modules/MriSimulation/Algorithms/itkDftImageFilter.cpp
index 3d8371a..4e5210a 100644
--- a/Modules/MriSimulation/Algorithms/itkDftImageFilter.cpp
+++ b/Modules/MriSimulation/Algorithms/itkDftImageFilter.cpp
@@ -1,94 +1,94 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkDftImageFilter_txx
#define __itkDftImageFilter_txx
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include "itkDftImageFilter.h"
#include <itkImageRegionConstIterator.h>
#include <itkImageRegionConstIteratorWithIndex.h>
#include <itkImageRegionIterator.h>
namespace itk {
template< class TPixelType >
DftImageFilter< TPixelType >
::DftImageFilter()
{
this->SetNumberOfRequiredInputs( 1 );
}
template< class TPixelType >
void DftImageFilter< TPixelType >
::BeforeThreadedGenerateData()
{
}
template< class TPixelType >
void DftImageFilter< TPixelType >
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, ThreadIdType)
{
typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0));
ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread);
typedef ImageRegionConstIterator< InputImageType > InputIteratorType;
typename InputImageType::Pointer inputImage = static_cast< InputImageType * >( this->ProcessObject::GetInput(0) );
float szx = outputImage->GetLargestPossibleRegion().GetSize(0);
float szy = outputImage->GetLargestPossibleRegion().GetSize(1);
float x_shift = 0;
float y_shift = 0;
if (static_cast<int>(szx)%2==1)
x_shift = (szx-1)/2;
else
x_shift = szx/2;
if (static_cast<int>(szy)%2==1)
y_shift = (szy-1)/2;
else
y_shift = szy/2;
while( !oit.IsAtEnd() )
{
float kx = oit.GetIndex()[0] - x_shift;
float ky = oit.GetIndex()[1] - y_shift;
kx /= szx;
ky /= szy;
vcl_complex<TPixelType> s(0,0);
InputIteratorType it(inputImage, inputImage->GetLargestPossibleRegion() );
while( !it.IsAtEnd() )
{
float x = it.GetIndex()[0] - x_shift;
float y = it.GetIndex()[1] - y_shift;
s += it.Get() * exp( std::complex<TPixelType>(0, -itk::Math::twopi * (kx*x + ky*y) ) );
++it;
}
oit.Set(s);
++oit;
}
}
}
#endif
diff --git a/Modules/MriSimulation/Algorithms/itkDftImageFilter.h b/Modules/MriSimulation/Algorithms/itkDftImageFilter.h
index fb6523c..c58226e 100644
--- a/Modules/MriSimulation/Algorithms/itkDftImageFilter.h
+++ b/Modules/MriSimulation/Algorithms/itkDftImageFilter.h
@@ -1,79 +1,79 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*===================================================================
This file is based heavily on a corresponding ITK filter.
===================================================================*/
#ifndef __itkDftImageFilter_h_
#define __itkDftImageFilter_h_
#include <itkImageToImageFilter.h>
#include <itkDiffusionTensor3D.h>
#include <vcl_complex.h>
#include <mitkFiberfoxParameters.h>
namespace itk{
/**
* \brief 2D Discrete Fourier Transform Filter (complex to real). Special issue for Fiberfox -> rearranges slice. */
template< class TPixelType >
class DftImageFilter :
public ImageToImageFilter< Image< vcl_complex< TPixelType > >, Image< vcl_complex< TPixelType > > >
{
public:
typedef DftImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageToImageFilter< Image< vcl_complex< TPixelType > >, Image< vcl_complex< TPixelType > > > Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(DftImageFilter, ImageToImageFilter)
typedef typename Superclass::InputImageType InputImageType;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename Superclass::OutputImageRegionType OutputImageRegionType;
void SetParameters( FiberfoxParameters& param ){ m_Parameters = param; }
protected:
DftImageFilter();
~DftImageFilter() override {}
void BeforeThreadedGenerateData() override;
void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType threadId) override;
private:
FiberfoxParameters m_Parameters;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkDftImageFilter.cpp"
#endif
#endif //__itkDftImageFilter_h_
diff --git a/Modules/MriSimulation/Algorithms/itkFibersFromPlanarFiguresFilter.cpp b/Modules/MriSimulation/Algorithms/itkFibersFromPlanarFiguresFilter.cpp
index e64c69d..cbe3356 100644
--- a/Modules/MriSimulation/Algorithms/itkFibersFromPlanarFiguresFilter.cpp
+++ b/Modules/MriSimulation/Algorithms/itkFibersFromPlanarFiguresFilter.cpp
@@ -1,245 +1,245 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkibersFromPlanarFiguresFilter_cpp
#define __itkibersFromPlanarFiguresFilter_cpp
#include "itkFibersFromPlanarFiguresFilter.h"
#include <itkOrientationDistributionFunction.h>
#include <itkDiffusionOdfGeneralizedFaImageFilter.h>
#include <mitkStandardFileLocations.h>
#include <itkTensorImageToOdfImageFilter.h>
#include <mitkRotationOperation.h>
#include <mitkInteractionConst.h>
#include <itkImageDuplicator.h>
#include <itkResampleImageFilter.h>
#include <itkTimeProbe.h>
#include <itkMersenneTwisterRandomVariateGenerator.h>
#include <cmath>
namespace itk{
FibersFromPlanarFiguresFilter::FibersFromPlanarFiguresFilter()
: m_FixSeed(false)
{
}
FibersFromPlanarFiguresFilter::~FibersFromPlanarFiguresFilter()
{
}
void FibersFromPlanarFiguresFilter::GeneratePoints()
{
Statistics::MersenneTwisterRandomVariateGenerator::Pointer randGen = Statistics::MersenneTwisterRandomVariateGenerator::New();
if (m_FixSeed)
randGen->SetSeed(0);
else
randGen->SetSeed();
m_2DPoints.clear();
unsigned int count = 0;
while (count < m_Parameters.m_Density)
{
mitk::Vector2D p;
switch (m_Parameters.m_Distribution) {
case FiberGenerationParameters::DISTRIBUTE_GAUSSIAN:
p[0] = randGen->GetNormalVariate(0, m_Parameters.m_Variance);
p[1] = randGen->GetNormalVariate(0, m_Parameters.m_Variance);
break;
default:
p[0] = randGen->GetUniformVariate(-1, 1);
p[1] = randGen->GetUniformVariate(-1, 1);
}
if (sqrt(p[0]*p[0]+p[1]*p[1]) <= 1)
{
m_2DPoints.push_back(p);
count++;
}
}
}
void FibersFromPlanarFiguresFilter::SetFixSeed(bool FixSeed)
{
m_FixSeed = FixSeed;
}
void FibersFromPlanarFiguresFilter::GenerateData()
{
// check if enough fiducials are available
for (unsigned int i=0; i<m_Parameters.m_Fiducials.size(); i++)
if (m_Parameters.m_Fiducials.at(i).size()<2)
itkExceptionMacro("At least 2 fiducials needed per fiber bundle!");
for (unsigned int i=0; i<m_Parameters.m_Fiducials.size(); i++)
{
vtkSmartPointer<vtkCellArray> m_VtkCellArray = vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkPoints> m_VtkPoints = vtkSmartPointer<vtkPoints>::New();
std::vector< mitk::PlanarEllipse::Pointer > bundle = m_Parameters.m_Fiducials.at(i);
std::vector< unsigned int > fliplist;
if (i<m_Parameters.m_FlipList.size())
fliplist = m_Parameters.m_FlipList.at(i);
else
fliplist.resize(bundle.size(), 0);
if (fliplist.size()<bundle.size())
fliplist.resize(bundle.size(), 0);
GeneratePoints();
for (unsigned int j = 0; j < m_Parameters.m_Density; ++j)
{
vtkSmartPointer<vtkPolyLine> container = vtkSmartPointer<vtkPolyLine>::New();
mitk::PlanarEllipse::Pointer figure = bundle.at(0);
mitk::Point2D p0 = figure->GetControlPoint(0);
mitk::Point2D p1 = figure->GetControlPoint(1);
mitk::Point2D p2 = figure->GetControlPoint(2);
mitk::Point2D p3 = figure->GetControlPoint(3);
double r1 = p0.EuclideanDistanceTo(p1);
double r2 = p0.EuclideanDistanceTo(p2);
mitk::Vector2D eDir = p1-p0; eDir.Normalize();
mitk::Vector2D tDir = p3-p0; tDir.Normalize();
// apply twist
vnl_matrix_fixed<double, 2, 2> tRot;
tRot[0][0] = tDir[0];
tRot[1][1] = tRot[0][0];
tRot[1][0] = sin(acos(tRot[0][0]));
tRot[0][1] = -tRot[1][0];
if (tDir[1]<0)
tRot.inplace_transpose();
m_2DPoints[j].SetVnlVector(tRot*m_2DPoints[j].GetVnlVector());
// apply new ellipse shape
vnl_vector_fixed< double, 2 > newP;
newP[0] = m_2DPoints.at(j)[0];
newP[1] = m_2DPoints.at(j)[1];
double alpha = acos(eDir[0]);
if (eDir[1]>0)
alpha = 2*itk::Math::pi-alpha;
vnl_matrix_fixed<double, 2, 2> eRot;
eRot[0][0] = cos(alpha);
eRot[1][1] = eRot[0][0];
eRot[1][0] = sin(alpha);
eRot[0][1] = -eRot[1][0];
newP = eRot*newP;
newP[0] *= r1;
newP[1] *= r2;
newP = eRot.transpose()*newP;
p0[0] += newP[0];
p0[1] += newP[1];
const mitk::PlaneGeometry* planeGeo = figure->GetPlaneGeometry();
mitk::Point3D w, wc;
planeGeo->Map(p0, w);
wc = figure->GetWorldControlPoint(0);
vtkIdType id = m_VtkPoints->InsertNextPoint(w.GetDataPointer());
container->GetPointIds()->InsertNextId(id);
vnl_vector_fixed< double, 3 > n = planeGeo->GetNormalVnl();
for (unsigned int k=1; k<bundle.size(); k++)
{
figure = bundle.at(k);
p0 = figure->GetControlPoint(0);
p1 = figure->GetControlPoint(1);
p2 = figure->GetControlPoint(2);
p3 = figure->GetControlPoint(3);
r1 = p0.EuclideanDistanceTo(p1);
r2 = p0.EuclideanDistanceTo(p2);
eDir = p1-p0; eDir.Normalize();
mitk::Vector2D tDir2 = p3-p0; tDir2.Normalize();
mitk::Vector2D temp; temp.Fill(0);
temp.SetVnlVector(tRot.transpose() * tDir2.GetVnlVector());
// apply twist
tRot[0][0] = tDir[0]*tDir2[0] + tDir[1]*tDir2[1];
if (tRot[0][0]>1.0)
tRot[0][0] = 1.0;
tRot[1][1] = tRot[0][0];
tRot[1][0] = sin(acos(tRot[0][0]));
tRot[0][1] = -tRot[1][0];
if (temp[1]<0)
tRot.inplace_transpose();
m_2DPoints[j].SetVnlVector(tRot*m_2DPoints[j].GetVnlVector());
tDir = tDir2;
// apply new ellipse shape
newP[0] = m_2DPoints.at(j)[0];
newP[1] = m_2DPoints.at(j)[1];
// calculate normal
mitk::PlaneGeometry* planeGeo = const_cast<mitk::PlaneGeometry*>(figure->GetPlaneGeometry());
mitk::Vector3D perp = wc-planeGeo->ProjectPointOntoPlane(wc); perp.Normalize();
vnl_vector_fixed< double, 3 > n2 = planeGeo->GetNormalVnl();
wc = figure->GetWorldControlPoint(0);
// is flip needed?
if (dot_product(perp.GetVnlVector(),n2)>0 && dot_product(n,n2)<=0.00001)
newP[0] *= -1;
if (fliplist.at(k)>0)
newP[0] *= -1;
n = n2;
alpha = acos(eDir[0]);
if (eDir[1]>0)
alpha = 2*itk::Math::pi-alpha;
eRot[0][0] = cos(alpha);
eRot[1][1] = eRot[0][0];
eRot[1][0] = sin(alpha);
eRot[0][1] = -eRot[1][0];
newP = eRot*newP;
newP[0] *= r1;
newP[1] *= r2;
newP = eRot.transpose()*newP;
p0[0] += newP[0];
p0[1] += newP[1];
mitk::Point3D w;
planeGeo->Map(p0, w);
vtkIdType id = m_VtkPoints->InsertNextPoint(w.GetDataPointer());
container->GetPointIds()->InsertNextId(id);
}
m_VtkCellArray->InsertNextCell(container);
}
vtkSmartPointer<vtkPolyData> fiberPolyData = vtkSmartPointer<vtkPolyData>::New();
fiberPolyData->SetPoints(m_VtkPoints);
fiberPolyData->SetLines(m_VtkCellArray);
mitk::FiberBundle::Pointer mitkFiberBundle = mitk::FiberBundle::New(fiberPolyData);
mitkFiberBundle->ResampleSpline(m_Parameters.m_Sampling, m_Parameters.m_Tension, m_Parameters.m_Continuity, m_Parameters.m_Bias);
m_FiberBundles.push_back(mitkFiberBundle);
}
}
}
#endif // __itkFibersFromPlanarFiguresFilter_cpp
diff --git a/Modules/MriSimulation/Algorithms/itkFibersFromPlanarFiguresFilter.h b/Modules/MriSimulation/Algorithms/itkFibersFromPlanarFiguresFilter.h
index 5158b0e..72d3355 100644
--- a/Modules/MriSimulation/Algorithms/itkFibersFromPlanarFiguresFilter.h
+++ b/Modules/MriSimulation/Algorithms/itkFibersFromPlanarFiguresFilter.h
@@ -1,88 +1,88 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 itkFibersFromPlanarFiguresFilter_h
#define itkFibersFromPlanarFiguresFilter_h
// MITK
#include <mitkPlanarEllipse.h>
#include <mitkFiberBundle.h>
#include <mitkFiberfoxParameters.h>
// ITK
#include <itkProcessObject.h>
// VTK
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkCellArray.h>
#include <vtkPoints.h>
#include <vtkPolyLine.h>
namespace itk{
/**
* \brief Generates artificial fibers distributed in and interpolated between the input planar figures. */
class FibersFromPlanarFiguresFilter : public ProcessObject
{
public:
typedef FibersFromPlanarFiguresFilter Self;
typedef ProcessObject Superclass;
typedef SmartPointer< Self > Pointer;
typedef SmartPointer< const Self > ConstPointer;
typedef mitk::FiberBundle::Pointer FiberType;
typedef std::vector< mitk::FiberBundle::Pointer > FiberContainerType;
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
itkTypeMacro( FibersFromPlanarFiguresFilter, ProcessObject )
void Update() override{
this->GenerateData();
}
// input
void SetParameters( FiberGenerationParameters param ) ///< Simulation parameters.
{
m_Parameters = param;
}
// output
FiberContainerType GetFiberBundles(){ return m_FiberBundles; }
void SetFixSeed(bool FixSeed);
protected:
void GenerateData() override;
FibersFromPlanarFiguresFilter();
~FibersFromPlanarFiguresFilter() override;
void GeneratePoints();
FiberContainerType m_FiberBundles; ///< container for the output fiber bundles
std::vector< mitk::Vector2D > m_2DPoints; ///< container for the 2D fiber waypoints
FiberGenerationParameters m_Parameters;
bool m_FixSeed;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkFibersFromPlanarFiguresFilter.cpp"
#endif
#endif
diff --git a/Modules/MriSimulation/Algorithms/itkFieldmapGeneratorFilter.cpp b/Modules/MriSimulation/Algorithms/itkFieldmapGeneratorFilter.cpp
index 6d05c31..997bc65 100644
--- a/Modules/MriSimulation/Algorithms/itkFieldmapGeneratorFilter.cpp
+++ b/Modules/MriSimulation/Algorithms/itkFieldmapGeneratorFilter.cpp
@@ -1,79 +1,79 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
Coindex[1]right (c) German Cancer Research Center,
-Division of Medical Image Computing.
+
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 "itkFieldmapGeneratorFilter.h"
#include <itkImageRegionIterator.h>
#include <math.h>
#include <itkPoint.h>
namespace itk{
template< class OutputImageType >
FieldmapGeneratorFilter< OutputImageType >::FieldmapGeneratorFilter()
{
m_Gradient.fill(0.0);
m_Offset.fill(0.0);
}
template< class OutputImageType >
FieldmapGeneratorFilter< OutputImageType >::~FieldmapGeneratorFilter()
{
}
template< class OutputImageType >
void FieldmapGeneratorFilter< OutputImageType >::BeforeThreadedGenerateData()
{
typename OutputImageType::Pointer outImage = OutputImageType::New();
outImage->SetSpacing( m_Spacing );
outImage->SetOrigin( m_Origin );
outImage->SetDirection( m_DirectionMatrix );
outImage->SetLargestPossibleRegion( m_ImageRegion );
outImage->SetBufferedRegion( m_ImageRegion );
outImage->SetRequestedRegion( m_ImageRegion );
outImage->Allocate();
outImage->FillBuffer(0);
this->SetNthOutput(0, outImage);
}
template< class OutputImageType >
void FieldmapGeneratorFilter< OutputImageType >::ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType threadId)
{
typename OutputImageType::Pointer outImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0));
ImageRegionIterator< OutputImageType > oit(outImage, outputRegionForThread);
while( !oit.IsAtEnd() )
{
double value = 0;
IndexType idx = oit.GetIndex();
for (int i=0; i<3; i++)
value += idx[i]*m_Gradient[i] + m_Offset[i];
for (unsigned int i=0; i<m_WorldPositions.size(); i++)
{
mitk::Point3D c = m_WorldPositions.at(i);
itk::Point<double, 3> vertex;
outImage->TransformIndexToPhysicalPoint(idx, vertex);
double dist = c.EuclideanDistanceTo(vertex);
value += m_Heights.at(i)*exp(-dist*dist/(2*m_Variances.at(i)));
}
oit.Set(value);
++oit;
}
MITK_INFO << "Thread " << threadId << "finished processing";
}
}
diff --git a/Modules/MriSimulation/Algorithms/itkFieldmapGeneratorFilter.h b/Modules/MriSimulation/Algorithms/itkFieldmapGeneratorFilter.h
index e539569..9f5dc11 100644
--- a/Modules/MriSimulation/Algorithms/itkFieldmapGeneratorFilter.h
+++ b/Modules/MriSimulation/Algorithms/itkFieldmapGeneratorFilter.h
@@ -1,93 +1,93 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkFieldmapGeneratorFilter_h__
#define __itkFieldmapGeneratorFilter_h__
#include <itkImageSource.h>
#include <itkImage.h>
#include <itkImageRegion.h>
#include <itkVector.h>
#include <mitkNumericTypes.h>
#include <itkMatrix.h>
#include <vector>
namespace itk{
/**
* \brief Generate float image with artificial frequency maps used by Fiberfox. Simulates additional frequencies at (possibly multiple) positions based on 3D gaussians with the specified variance and amplitude and/or as a linear gradient in the image.
* See "Fiberfox: Facilitating the creation of realistic white matter software phantoms" (DOI: 10.1002/mrm.25045) for details.
*/
template< class OutputImageType >
class FieldmapGeneratorFilter : public ImageSource< OutputImageType >
{
public:
typedef FieldmapGeneratorFilter Self;
typedef ProcessObject Superclass;
typedef SmartPointer< Self > Pointer;
typedef SmartPointer< const Self > ConstPointer;
typedef typename OutputImageType::PixelType PixelType;
typedef typename OutputImageType::IndexType IndexType;
typedef itk::ImageRegion<3> OutputImageRegionType;
typedef itk::Matrix<double, 3, 3> MatrixType;
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
itkTypeMacro( FieldmapGeneratorFilter, ImageSource )
/** Output image parameters. */
itkSetMacro( Spacing, itk::Vector<double> )
itkSetMacro( Origin, mitk::Point3D )
itkSetMacro( DirectionMatrix, MatrixType )
itkSetMacro( ImageRegion, OutputImageRegionType )
/** Gradient direction and offset. */
void SetGradient( vnl_vector_fixed< double, 3 > gradient ) { m_Gradient=gradient; }
void SetOffset( vnl_vector_fixed< double, 3 > offset ) { m_Offset=offset; }
/** Parameters of gaussian frequency sources. */
void SetVariances( std::vector< double > variances ) { m_Variances=variances; }
void SetHeights( std::vector< double > heights ) { m_Heights=heights; }
void SetWorldPositions( std::vector< mitk::Point3D > worldPositions ) { m_WorldPositions=worldPositions; }
protected:
void BeforeThreadedGenerateData();
void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType threadId);
FieldmapGeneratorFilter();
virtual ~FieldmapGeneratorFilter();
itk::Vector<double> m_Spacing; ///< output image spacing
mitk::Point3D m_Origin; ///< output image origin
MatrixType m_DirectionMatrix; ///< output image rotation
OutputImageRegionType m_ImageRegion; ///< output image size
std::vector< double > m_Variances;
std::vector< double > m_Heights;
std::vector< mitk::Point3D > m_WorldPositions;
vnl_vector_fixed< double, 3 > m_Gradient;
vnl_vector_fixed< double, 3 > m_Offset;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkFieldmapGeneratorFilter.cpp"
#endif
#endif // __itkFieldmapGeneratorFilter_h__
diff --git a/Modules/MriSimulation/Algorithms/itkKspaceImageFilter.cpp b/Modules/MriSimulation/Algorithms/itkKspaceImageFilter.cpp
index d6e0fe3..0c5f7bc 100644
--- a/Modules/MriSimulation/Algorithms/itkKspaceImageFilter.cpp
+++ b/Modules/MriSimulation/Algorithms/itkKspaceImageFilter.cpp
@@ -1,512 +1,512 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkKspaceImageFilter_txx
#define __itkKspaceImageFilter_txx
//#endif
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <math.h>
#include "itkKspaceImageFilter.h"
#include <itkImageRegionConstIterator.h>
#include <itkImageRegionConstIteratorWithIndex.h>
#include <itkImageRegionIterator.h>
#include <mitkSingleShotEpi.h>
#include <mitkConventionalSpinEcho.h>
#include <mitkFastSpinEcho.h>
#include <mitkDiffusionFunctionCollection.h>
#include <itkImageFileWriter.h>
namespace itk {
template< class ScalarType >
KspaceImageFilter< ScalarType >::KspaceImageFilter()
: m_Z(0)
, m_RandSeed(-1)
, m_SpikesPerSlice(0)
, m_IsBaseline(true)
, m_StoreTimings(false)
{
m_DiffusionGradientDirection.Fill(0.0);
m_CoilPosition.Fill(0.0);
}
template< class ScalarType >
void KspaceImageFilter< ScalarType >
::BeforeThreadedGenerateData()
{
m_Spike = vcl_complex<ScalarType>(0,0);
m_SpikeLog = "";
m_TransX = -m_Translation[0];
m_TransY = -m_Translation[1];
m_TransZ = -m_Translation[2];
kxMax = m_Parameters->m_SignalGen.m_CroppedRegion.GetSize(0);
kyMax = m_Parameters->m_SignalGen.m_CroppedRegion.GetSize(1);
xMax = m_CompartmentImages.at(0)->GetLargestPossibleRegion().GetSize(0); // scanner coverage in x-direction
yMax = m_CompartmentImages.at(0)->GetLargestPossibleRegion().GetSize(1); // scanner coverage in y-direction
yMaxFov = yMax;
if (m_Parameters->m_Misc.m_DoAddAliasing)
{
// actual FOV in y-direction (in x-direction FOV=xMax)
yMaxFov = static_cast<int>(yMaxFov * m_Parameters->m_SignalGen.m_CroppingFactor);
}
yMaxFov_half = (yMaxFov-1)/2;
numPix = kxMax*kyMax;
float ringing_factor = static_cast<float>(m_Parameters->m_SignalGen.m_ZeroRinging)/100.0;
ringing_lines_x = static_cast<int>(ceil(kxMax/2 * ringing_factor));
ringing_lines_y = static_cast<int>(ceil(kyMax/2 * ringing_factor));
// Adjust noise variance since it is the intended variance in physical space and not in k-space:
float noiseVar = m_Parameters->m_SignalGen.m_PartialFourier*m_Parameters->m_SignalGen.m_NoiseVariance/(kyMax*kxMax);
m_RandGen = itk::Statistics::MersenneTwisterRandomVariateGenerator::New();
if (m_RandSeed>=0) // always generate the same random numbers?
m_RandGen->SetSeed(m_RandSeed);
else
m_RandGen->SetSeed();
typename OutputImageType::Pointer outputImage = OutputImageType::New();
itk::ImageRegion<2> region;
region.SetSize(0, m_Parameters->m_SignalGen.m_CroppedRegion.GetSize(0));
region.SetSize(1, m_Parameters->m_SignalGen.m_CroppedRegion.GetSize(1));
outputImage->SetLargestPossibleRegion( region );
outputImage->SetBufferedRegion( region );
outputImage->SetRequestedRegion( region );
outputImage->Allocate();
vcl_complex<ScalarType> zero = vcl_complex<ScalarType>(0, 0);
outputImage->FillBuffer(zero);
if (m_Parameters->m_SignalGen.m_NoiseVariance>0 && m_Parameters->m_Misc.m_DoAddNoise)
{
ImageRegionIterator< OutputImageType > oit(outputImage, outputImage->GetLargestPossibleRegion());
while( !oit.IsAtEnd() )
{
oit.Set(vcl_complex<ScalarType>(m_RandGen->GetNormalVariate(0, noiseVar), m_RandGen->GetNormalVariate(0, noiseVar)));
++oit;
}
}
m_KSpaceImage = InputImageType::New();
m_KSpaceImage->SetLargestPossibleRegion( region );
m_KSpaceImage->SetBufferedRegion( region );
m_KSpaceImage->SetRequestedRegion( region );
m_KSpaceImage->Allocate();
m_KSpaceImage->FillBuffer(0.0);
if (m_StoreTimings)
{
m_TickImage = InputImageType::New();
m_TickImage->SetLargestPossibleRegion( region );
m_TickImage->SetBufferedRegion( region );
m_TickImage->SetRequestedRegion( region );
m_TickImage->Allocate();
m_TickImage->FillBuffer(-1.0);
m_RfImage = InputImageType::New();
m_RfImage->SetLargestPossibleRegion( region );
m_RfImage->SetBufferedRegion( region );
m_RfImage->SetRequestedRegion( region );
m_RfImage->Allocate();
m_RfImage->FillBuffer(-1.0);
}
else
{
m_TickImage = nullptr;
m_RfImage = nullptr;
}
m_Gamma = 42576000*itk::Math::twopi; // Gyromagnetic ratio in Hz/T
if ( m_Parameters->m_SignalGen.m_EddyStrength>0 && m_DiffusionGradientDirection.GetNorm()>0.001)
{
m_DiffusionGradientDirection = m_DiffusionGradientDirection * m_Parameters->m_SignalGen.m_EddyStrength/1000 * m_Gamma;
m_IsBaseline = false;
}
else {
m_IsBaseline = true;
}
this->SetNthOutput(0, outputImage);
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
m_Transform[i][j] = m_Parameters->m_SignalGen.m_ImageDirection[i][j] * m_Parameters->m_SignalGen.m_ImageSpacing[j]/1000;
float a = m_Parameters->m_SignalGen.m_ImageRegion.GetSize(0)*m_Parameters->m_SignalGen.m_ImageSpacing[0];
float b = m_Parameters->m_SignalGen.m_ImageRegion.GetSize(1)*m_Parameters->m_SignalGen.m_ImageSpacing[1];
float diagonal = sqrt(a*a+b*b)/1000; // image diagonal in m
switch (m_Parameters->m_SignalGen.m_CoilSensitivityProfile)
{
case SignalGenerationParameters::COIL_CONSTANT:
{
m_CoilSensitivityFactor = 1; // same signal everywhere
break;
}
case SignalGenerationParameters::COIL_LINEAR:
{
m_CoilSensitivityFactor = -1/diagonal; // about 50% of the signal in the image center remaining
break;
}
case SignalGenerationParameters::COIL_EXPONENTIAL:
{
m_CoilSensitivityFactor = -log(0.1)/diagonal; // about 32% of the signal in the image center remaining
break;
}
}
switch (m_Parameters->m_SignalGen.m_AcquisitionType)
{
case SignalGenerationParameters::SingleShotEpi:
m_ReadoutScheme = new mitk::SingleShotEpi(m_Parameters);
break;
case SignalGenerationParameters::ConventionalSpinEcho:
m_ReadoutScheme = new mitk::ConventionalSpinEcho(m_Parameters);
break;
case SignalGenerationParameters::FastSpinEcho:
m_ReadoutScheme = new mitk::FastSpinEcho(m_Parameters);
break;
default:
m_ReadoutScheme = new mitk::SingleShotEpi(m_Parameters);
}
m_ReadoutScheme->AdjustEchoTime();
m_MovedFmap = nullptr;
if (m_Parameters->m_Misc.m_DoAddDistortions && m_Parameters->m_SignalGen.m_FrequencyMap.IsNotNull() && m_Parameters->m_SignalGen.m_DoAddMotion)
{
// we have to account for the head motion since this also moves our frequency map
itk::LinearInterpolateImageFunction< itk::Image< float, 3 >, float >::Pointer fmapInterpolator;
fmapInterpolator = itk::LinearInterpolateImageFunction< itk::Image< float, 3 >, float >::New();
fmapInterpolator->SetInputImage(m_Parameters->m_SignalGen.m_FrequencyMap);
m_MovedFmap = itk::Image< ScalarType, 2 >::New();
m_MovedFmap->SetLargestPossibleRegion( m_CompartmentImages.at(0)->GetLargestPossibleRegion() );
m_MovedFmap->SetBufferedRegion( m_CompartmentImages.at(0)->GetLargestPossibleRegion() );
m_MovedFmap->SetRequestedRegion( m_CompartmentImages.at(0)->GetLargestPossibleRegion() );
m_MovedFmap->Allocate();
m_MovedFmap->FillBuffer(0);
ImageRegionIterator< InputImageType > it(m_MovedFmap, m_MovedFmap->GetLargestPossibleRegion() );
while( !it.IsAtEnd() )
{
itk::Image<float, 3>::IndexType index;
index[0] = it.GetIndex()[0];
index[1] = it.GetIndex()[1];
index[2] = m_Zidx;
itk::Point<float, 3> point3D;
m_Parameters->m_SignalGen.m_FrequencyMap->TransformIndexToPhysicalPoint(index, point3D);
m_FiberBundle->TransformPoint<float>( point3D, m_RotationMatrix, m_TransX, m_TransY, m_TransZ );
it.Set(mitk::imv::GetImageValue<float>(point3D, true, fmapInterpolator));
++it;
}
}
// calculate T1 relaxation (independent of actual readout)
m_T1Relax.clear();
if ( m_Parameters->m_SignalGen.m_DoSimulateRelaxation)
for (unsigned int i=0; i<m_CompartmentImages.size(); i++)
{
// account for T1 relaxation (how much magnetization is available since last excitation?)
float relaxation = (1.0-std::exp(-m_Parameters->m_SignalGen.m_tRep/m_T1[i]));
// account for inversion pulse and TI
if (m_Parameters->m_SignalGen.m_tInv > 0)
relaxation *= (1.0-std::exp(std::log(2) - m_Parameters->m_SignalGen.m_tInv/m_T1[i]));
m_T1Relax.push_back(relaxation);
}
}
template< class ScalarType >
float KspaceImageFilter< ScalarType >::CoilSensitivity(VectorType& pos)
{
// *************************************************************************
// Coil ring is moving with excited slice (FIX THIS SOMETIME)
m_CoilPosition[2] = pos[2];
// *************************************************************************
switch (m_Parameters->m_SignalGen.m_CoilSensitivityProfile)
{
case SignalGenerationParameters::COIL_CONSTANT:
return 1;
case SignalGenerationParameters::COIL_LINEAR:
{
VectorType diff = pos-m_CoilPosition;
float sens = diff.GetNorm()*m_CoilSensitivityFactor + 1;
if (sens<0)
sens = 0;
return sens;
}
case SignalGenerationParameters::COIL_EXPONENTIAL:
{
VectorType diff = pos-m_CoilPosition;
float dist = static_cast<float>(diff.GetNorm());
return std::exp(-dist*m_CoilSensitivityFactor);
}
default:
return 1;
}
}
template< class ScalarType >
void KspaceImageFilter< ScalarType >
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, ThreadIdType )
{
typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0));
ImageRegionIterator< OutputImageType > oit(outputImage, outputRegionForThread);
typedef ImageRegionConstIterator< InputImageType > InputIteratorType;
// precalculate shifts for DFT
float x_shift = 0;
float y_shift = 0;
if (static_cast<int>(xMax)%2==1)
x_shift = (xMax-1)/2;
else
x_shift = xMax/2;
if (static_cast<int>(yMax)%2==1)
y_shift = (yMax-1)/2;
else
y_shift = yMax/2;
float kx_shift = 0;
float ky_shift = 0;
if (static_cast<int>(kxMax)%2==1)
kx_shift = (kxMax-1)/2;
else
kx_shift = kxMax/2;
if (static_cast<int>(kyMax)%2==1)
ky_shift = (kyMax-1)/2;
else
ky_shift = kyMax/2;
vcl_complex<ScalarType> zero = vcl_complex<ScalarType>(0, 0);
while( !oit.IsAtEnd() )
{
int tick = oit.GetIndex()[1] * kxMax + oit.GetIndex()[0];
// get current k-space index (depends on the chosen k-space readout scheme)
itk::Index< 2 > kIdx = m_ReadoutScheme->GetActualKspaceIndex(tick);
// we have to adjust the ticks to obtain correct times since the DFT is not completely symmetric in the even number of lines case
if (static_cast<int>(kyMax)%2 == 0 && !m_Parameters->m_SignalGen.m_ReversePhase)
{
tick += kxMax;
tick %= static_cast<int>(numPix);
}
// partial fourier
// two cases because we always want to skip the "later" parts of k-space
// in "normal" phase direction, the higher k-space indices are acquired first
// in reversed phase direction, the higher k-space indices are acquired later
// if the image has an even number of lines, never skip line zero since it is missing on the other side (DFT not completely syymetric in even case)
if ((m_Parameters->m_SignalGen.m_ReversePhase && kIdx[1]>std::ceil(kyMax*m_Parameters->m_SignalGen.m_PartialFourier)) ||
(!m_Parameters->m_SignalGen.m_ReversePhase && kIdx[1]<std::floor(kyMax*(1.0 - m_Parameters->m_SignalGen.m_PartialFourier)) &&
(kIdx[1]>0 || static_cast<int>(kyMax)%2 == 1)))
{
outputImage->SetPixel(kIdx, zero);
++oit;
continue;
}
if (m_StoreTimings)
m_TickImage->SetPixel(kIdx, tick);
// gibbs ringing by setting high frequencies to zero (alternative to using smaller k-space than input image space)
if (m_Parameters->m_SignalGen.m_DoAddGibbsRinging && m_Parameters->m_SignalGen.m_ZeroRinging>0)
{
if (kIdx[0] < ringing_lines_x || kIdx[1] < ringing_lines_y ||
kIdx[0] >= kxMax - ringing_lines_x || kIdx[1] >= kyMax - ringing_lines_y)
{
outputImage->SetPixel(kIdx, zero);
++oit;
continue;
}
}
// time from maximum echo
float t = m_ReadoutScheme->GetTimeFromMaxEcho(tick);
// calculate eddy current decay factor
float eddyDecay = 0;
if ( m_Parameters->m_Misc.m_DoAddEddyCurrents && m_Parameters->m_SignalGen.m_EddyStrength>0 && !m_IsBaseline)
{
// time passed since k-space readout started
float tRead = m_ReadoutScheme->GetTimeFromLastDiffusionGradient(tick);
eddyDecay = std::exp(-tRead/m_Parameters->m_SignalGen.m_Tau ) * t/1000; // time in seconds here
}
// calcualte signal relaxation factors
std::vector< float > relaxFactor;
if ( m_Parameters->m_SignalGen.m_DoSimulateRelaxation)
{
// time passes since application of the RF pulse
float tRf = m_ReadoutScheme->GetTimeFromRf(tick);
if (m_StoreTimings)
m_RfImage->SetPixel(kIdx, tRf);
for (unsigned int i=0; i<m_CompartmentImages.size(); i++)
{
// account for T2 relaxation (how much transverse magnetization is left since applicatiohn of RF pulse?)
relaxFactor.push_back(m_T1Relax[i] * std::exp(-tRf/m_T2[i] -fabs(t)/ m_Parameters->m_SignalGen.m_tInhom));
}
}
// shift k for DFT: (0 -- N) --> (-N/2 -- N/2)
float kx = kIdx[0] - kx_shift;
float ky = kIdx[1] - ky_shift;
// add ghosting by adding gradient delay induced offset
if (m_Parameters->m_Misc.m_DoAddGhosts)
{
if (kIdx[1]%2 == 1)
kx -= m_Parameters->m_SignalGen.m_KspaceLineOffset;
else
kx += m_Parameters->m_SignalGen.m_KspaceLineOffset;
}
// pull stuff out of inner loop
t /= 1000; // time in seconds
kx /= xMax;
ky /= yMaxFov;
// calculate signal s at k-space position (kx, ky)
vcl_complex<ScalarType> s(0,0);
InputIteratorType it(m_CompartmentImages[0], m_CompartmentImages[0]->GetLargestPossibleRegion() );
while( !it.IsAtEnd() )
{
typename InputImageType::IndexType input_idx = it.GetIndex();
// shift x,y for DFT: (0 -- N) --> (-N/2 -- N/2)
float x = input_idx[0] - x_shift;
float y = input_idx[1] - y_shift;
// sum compartment signals and simulate relaxation
ScalarType f_real = 0;
for (unsigned int i=0; i<m_CompartmentImages.size(); i++)
if ( m_Parameters->m_SignalGen.m_DoSimulateRelaxation)
f_real += m_CompartmentImages[i]->GetPixel(input_idx) * relaxFactor[i];
else
f_real += m_CompartmentImages[i]->GetPixel(input_idx);
// vector from image center to current position (in meter)
// only necessary for eddy currents and non-constant coil sensitivity
VectorType pos;
if ((m_Parameters->m_Misc.m_DoAddEddyCurrents && m_Parameters->m_SignalGen.m_EddyStrength>0 && !m_IsBaseline) ||
m_Parameters->m_SignalGen.m_CoilSensitivityProfile!=SignalGenerationParameters::COIL_CONSTANT)
{
pos[0] = x; pos[1] = y; pos[2] = m_Z;
pos = m_Transform*pos;
}
if (m_Parameters->m_SignalGen.m_CoilSensitivityProfile!=SignalGenerationParameters::COIL_CONSTANT)
f_real *= CoilSensitivity(pos);
// simulate eddy currents and other distortions
float phi = 0; // phase shift
if ( m_Parameters->m_Misc.m_DoAddEddyCurrents && m_Parameters->m_SignalGen.m_EddyStrength>0 && !m_IsBaseline)
{
// duration (tRead) already included in "eddyDecay"
phi += (m_DiffusionGradientDirection[0]*pos[0]+m_DiffusionGradientDirection[1]*pos[1]+m_DiffusionGradientDirection[2]*pos[2]) * eddyDecay;
}
// simulate distortions
if (m_Parameters->m_Misc.m_DoAddDistortions)
{
if (m_MovedFmap.IsNotNull()) // if we have headmotion, use moved map
phi += m_MovedFmap->GetPixel(input_idx) * t;
else if (m_Parameters->m_SignalGen.m_FrequencyMap.IsNotNull())
{
itk::Image<float, 3>::IndexType index; index[0] = input_idx[0]; index[1] = input_idx[1]; index[2] = m_Zidx;
phi += m_Parameters->m_SignalGen.m_FrequencyMap->GetPixel(index) * t;
}
}
// if signal comes from outside FOV, mirror it back (wrap-around artifact - aliasing
if (m_Parameters->m_Misc.m_DoAddAliasing)
{
if (y<-yMaxFov_half)
y += yMaxFov;
else if (y>yMaxFov_half)
y -= yMaxFov;
}
// actual DFT term
vcl_complex<ScalarType> f(f_real * m_Parameters->m_SignalGen.m_SignalScale, 0);
s += f * std::exp( std::complex<ScalarType>(0, itk::Math::twopi * (kx*x + ky*y + phi )) );
++it;
}
s /= numPix;
if (m_SpikesPerSlice>0 && sqrt(s.imag()*s.imag()+s.real()*s.real()) > sqrt(m_Spike.imag()*m_Spike.imag()+m_Spike.real()*m_Spike.real()) )
m_Spike = s;
s += outputImage->GetPixel(kIdx); // add precalculated noise
outputImage->SetPixel(kIdx, s);
m_KSpaceImage->SetPixel(kIdx, sqrt(s.imag()*s.imag()+s.real()*s.real()) );
++oit;
}
}
template< class ScalarType >
void KspaceImageFilter< ScalarType >
::AfterThreadedGenerateData()
{
typename OutputImageType::Pointer outputImage = static_cast< OutputImageType * >(this->ProcessObject::GetOutput(0));
int kxMax = outputImage->GetLargestPossibleRegion().GetSize(0); // k-space size in x-direction
int kyMax = outputImage->GetLargestPossibleRegion().GetSize(1); // k-space size in y-direction
ImageRegionIterator< OutputImageType > oit(outputImage, outputImage->GetLargestPossibleRegion());
while( !oit.IsAtEnd() ) // use hermitian k-space symmetry to fill empty k-space parts resulting from partial fourier acquisition
{
int tick = oit.GetIndex()[1] * kxMax + oit.GetIndex()[0];
auto kIdx = m_ReadoutScheme->GetActualKspaceIndex(tick);
if ((m_Parameters->m_SignalGen.m_ReversePhase && kIdx[1]>std::ceil(kyMax*m_Parameters->m_SignalGen.m_PartialFourier)) ||
(!m_Parameters->m_SignalGen.m_ReversePhase && kIdx[1]<std::floor(kyMax*(1.0 - m_Parameters->m_SignalGen.m_PartialFourier)) &&
(kIdx[1]>0 || static_cast<int>(kyMax)%2 == 1)))
{
// calculate symmetric index
auto sym = m_ReadoutScheme->GetSymmetricIndex(kIdx);
// use complex conjugate of symmetric index value at current index
vcl_complex<ScalarType> s = outputImage->GetPixel(sym);
s = vcl_complex<ScalarType>(s.real(), -s.imag());
outputImage->SetPixel(kIdx, s);
m_KSpaceImage->SetPixel(kIdx, sqrt(s.imag()*s.imag()+s.real()*s.real()) );
}
++oit;
}
m_Spike *= m_Parameters->m_SignalGen.m_SpikeAmplitude;
itk::Index< 2 > spikeIdx;
for (unsigned int i=0; i<m_SpikesPerSlice; i++)
{
spikeIdx[0] = m_RandGen->GetIntegerVariate()%kxMax;
spikeIdx[1] = m_RandGen->GetIntegerVariate()%kyMax;
outputImage->SetPixel(spikeIdx, m_Spike);
m_SpikeLog += "[" + boost::lexical_cast<std::string>(spikeIdx[0]) + "," + boost::lexical_cast<std::string>(spikeIdx[1]) + "," + boost::lexical_cast<std::string>(m_Zidx) + "] Magnitude: " + boost::lexical_cast<std::string>(m_Spike.real()) + "+" + boost::lexical_cast<std::string>(m_Spike.imag()) + "i\n";
}
delete m_ReadoutScheme;
}
}
#endif
diff --git a/Modules/MriSimulation/Algorithms/itkKspaceImageFilter.h b/Modules/MriSimulation/Algorithms/itkKspaceImageFilter.h
index 08ad75b..0fa0b02 100644
--- a/Modules/MriSimulation/Algorithms/itkKspaceImageFilter.h
+++ b/Modules/MriSimulation/Algorithms/itkKspaceImageFilter.h
@@ -1,160 +1,160 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
/*===================================================================
This file is based heavily on a corresponding ITK filter.
===================================================================*/
#ifndef __itkKspaceImageFilter_h_
#define __itkKspaceImageFilter_h_
#include <itkImageSource.h>
#include <vcl_complex.h>
#include <vector>
#include <itkMersenneTwisterRandomVariateGenerator.h>
#include <mitkFiberfoxParameters.h>
#include <mitkFiberBundle.h>
#include <mitkAcquisitionType.h>
namespace itk{
/**
* \brief Simulates k-space acquisition of one slice with a single shot EPI sequence. Enables the simulation of various effects occuring during real MR acquisitions:
* - T2 signal relaxation
* - Spikes
* - N/2 Ghosts
* - Aliasing (wrap around)
* - Image distortions (off-frequency effects)
* - Gibbs ringing
* - Eddy current effects
* Based on a discrete fourier transformation.
* See "Fiberfox: Facilitating the creation of realistic white matter software phantoms" (DOI: 10.1002/mrm.25045) for details.
*/
template< class ScalarType >
class KspaceImageFilter :
public ImageSource< Image< vcl_complex< ScalarType >, 2 > >
{
public:
typedef KspaceImageFilter Self;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
typedef ImageSource< Image< vcl_complex< ScalarType >, 2 > > Superclass;
/** Method for creation through the object factory. */
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/** Runtime information support. */
itkTypeMacro(KspaceImageFilter, ImageToImageFilter)
typedef typename itk::Image< ScalarType, 2 > InputImageType;
typedef typename InputImageType::Pointer InputImagePointerType;
typedef typename Superclass::OutputImageType OutputImageType;
typedef typename Superclass::OutputImageRegionType OutputImageRegionType;
typedef itk::Matrix<float, 3, 3> MatrixType;
typedef itk::Point<float,2> Point2D;
typedef itk::Vector< float,3> VectorType;
itkSetMacro( SpikesPerSlice, unsigned int ) ///< Number of spikes per slice. Corresponding parameter in fiberfox parameter object specifies the number of spikes for the whole image and can thus not be used here.
itkSetMacro( Z, double ) ///< Slice position, necessary for eddy current simulation.
itkSetMacro( RandSeed, int ) ///< Use constant seed for random generator for reproducible results.
itkSetMacro( Translation, VectorType )
itkSetMacro( RotationMatrix, MatrixType )
itkSetMacro( Zidx, int )
itkSetMacro( StoreTimings, bool )
itkSetMacro( FiberBundle, FiberBundle::Pointer )
itkSetMacro( CoilPosition, VectorType )
itkGetMacro( KSpaceImage, typename InputImageType::Pointer ) ///< k-space magnitude image
itkGetMacro( TickImage, typename InputImageType::Pointer ) ///< k-space readout ordering encoded in the voxels
itkGetMacro( RfImage, typename InputImageType::Pointer ) ///< time passed since last RF pulse encoded per voxel
itkGetMacro( SpikeLog, std::string )
void SetParameters( FiberfoxParameters* param ){ m_Parameters = param; }
void SetCompartmentImages( std::vector< InputImagePointerType > cImgs ) { m_CompartmentImages=cImgs; } ///< One signal image per compartment.
void SetT2( std::vector< float > t2Vector ) { m_T2=t2Vector; } ///< One T2 relaxation constant per compartment image.
void SetT1( std::vector< float > t1Vector ) { m_T1=t1Vector; } ///< One T1 relaxation constant per compartment image.
void SetDiffusionGradientDirection(itk::Vector<double,3> g) { m_DiffusionGradientDirection=g; } ///< Gradient direction is needed for eddy current simulation.
protected:
KspaceImageFilter();
~KspaceImageFilter() override {}
float CoilSensitivity(VectorType& pos);
void BeforeThreadedGenerateData() override;
void ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType threadID) override;
void AfterThreadedGenerateData() override;
VectorType m_CoilPosition;
FiberfoxParameters* m_Parameters;
std::vector< float > m_T2;
std::vector< float > m_T1;
std::vector< float > m_T1Relax;
std::vector< InputImagePointerType > m_CompartmentImages;
itk::Vector<double,3> m_DiffusionGradientDirection;
float m_Z;
int m_Zidx;
int m_RandSeed;
itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer m_RandGen;
unsigned int m_SpikesPerSlice;
FiberBundle::Pointer m_FiberBundle;
float m_Gamma;
VectorType m_Translation; ///< used to find correct point in frequency map (head motion)
MatrixType m_RotationMatrix;
float m_TransX;
float m_TransY;
float m_TransZ;
bool m_IsBaseline;
vcl_complex<ScalarType> m_Spike;
MatrixType m_Transform;
std::string m_SpikeLog;
float m_CoilSensitivityFactor;
typename InputImageType::Pointer m_KSpaceImage;
typename InputImageType::Pointer m_TickImage;
typename InputImageType::Pointer m_RfImage;
AcquisitionType* m_ReadoutScheme;
typename itk::Image< ScalarType, 2 >::Pointer m_MovedFmap;
int ringing_lines_x;
int ringing_lines_y;
float kxMax;
float kyMax;
float xMax;
float yMax;
float yMaxFov;
float yMaxFov_half;
float numPix;
bool m_StoreTimings;
private:
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkKspaceImageFilter.cpp"
#endif
#endif //__itkKspaceImageFilter_h_
diff --git a/Modules/MriSimulation/Algorithms/itkRandomPhantomFilter.cpp b/Modules/MriSimulation/Algorithms/itkRandomPhantomFilter.cpp
index d9184da..2990e06 100644
--- a/Modules/MriSimulation/Algorithms/itkRandomPhantomFilter.cpp
+++ b/Modules/MriSimulation/Algorithms/itkRandomPhantomFilter.cpp
@@ -1,457 +1,457 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkRandomPhantomFilter_cpp
//#define __itkRandomPhantomFilter_cpp
#include "itkRandomPhantomFilter.h"
#include <itkFibersFromPlanarFiguresFilter.h>
#include <cmath>
namespace itk{
RandomPhantomFilter::RandomPhantomFilter()
: m_NumTracts(1)
, m_MinStreamlineDensity(25)
, m_MaxStreamlineDensity(200)
, m_StartRadiusMin(5)
, m_StartRadiusMax(30)
, m_CurvynessMin(10)
, m_CurvynessMax(45)
, m_StepSizeMin(15)
, m_StepSizeMax(30)
, m_MinTwist(10)
, m_MaxTwist(30)
, m_FixSeed(-1)
{
m_VolumeSize[0] = 500;
m_VolumeSize[1] = 500;
m_VolumeSize[2] = 500;
}
RandomPhantomFilter::~RandomPhantomFilter()
{
}
void RandomPhantomFilter::TransformPlanarFigure(mitk::PlanarEllipse* pe, mitk::Vector3D translation, mitk::Vector3D rotation, double twistangle, double radius1, double radius2)
{
mitk::BaseGeometry* geom = pe->GetGeometry();
// translate
geom->Translate(translation);
// calculate rotation matrix
double x = rotation[0]*itk::Math::pi/180;
double y = rotation[1]*itk::Math::pi/180;
double z = rotation[2]*itk::Math::pi/180;
itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity();
rotX[1][1] = cos(x);
rotX[2][2] = rotX[1][1];
rotX[1][2] = -sin(x);
rotX[2][1] = -rotX[1][2];
itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity();
rotY[0][0] = cos(y);
rotY[2][2] = rotY[0][0];
rotY[0][2] = sin(y);
rotY[2][0] = -rotY[0][2];
itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity();
rotZ[0][0] = cos(z);
rotZ[1][1] = rotZ[0][0];
rotZ[0][1] = -sin(z);
rotZ[1][0] = -rotZ[0][1];
itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX;
// rotate fiducial
geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix());
// adjust control points
auto p0 = pe->GetControlPoint(0);
auto p1 = pe->GetControlPoint(1);
auto p2 = pe->GetControlPoint(2);
auto p3 = pe->GetControlPoint(3);
auto v1 = p1 - p0;
auto v2 = p2 - p0;
auto dot = std::cos(itk::Math::pi*twistangle/180.0);
vnl_matrix_fixed<double, 2, 2> tRot;
tRot[0][0] = dot;
tRot[1][1] = tRot[0][0];
tRot[1][0] = sin(acos(tRot[0][0]));
tRot[0][1] = -tRot[1][0];
if (twistangle<0)
tRot = tRot.transpose();
vnl_vector_fixed<double, 2> vt; vt[0]=1; vt[1]=0;
vnl_vector_fixed<double, 2> v3 = tRot*vt;
v1.Normalize();
v2.Normalize();
p1 = p0 + radius1;
p2 = p0 + radius2;
p3 = p0 + mitk::Vector2D(v3);
pe->SetControlPoint(1, p1);
pe->SetControlPoint(2, p2);
pe->SetControlPoint(3, p3);
pe->Modified();
}
mitk::PlanarEllipse::Pointer RandomPhantomFilter::CreatePlanarFigure()
{
mitk::PlaneGeometry::Pointer pl = mitk::PlaneGeometry::New();
pl->SetIdentity();
// mitk::Point3D o; o.Fill(10.0);
// pl->SetOrigin(o);
mitk::PlanarEllipse::Pointer figure = mitk::PlanarEllipse::New();
figure->ResetNumberOfControlPoints(0);
figure->SetPlaneGeometry(pl);
mitk::Point2D p0; p0.Fill(0.0);
mitk::Point2D p1; p1.Fill(0.0); p1[0] = 1;
mitk::Point2D p2; p2.Fill(0.0); p2[1] = 1;
figure->PlaceFigure(p0);
figure->AddControlPoint(p0);
figure->AddControlPoint(p1);
figure->AddControlPoint(p2);
figure->AddControlPoint(p2);
figure->SetProperty("initiallyplaced", mitk::BoolProperty::New(true));
return figure;
}
void RandomPhantomFilter::SetNumTracts(unsigned int NumTracts)
{
m_NumTracts = NumTracts;
}
void RandomPhantomFilter::GetPfOnBoundingPlane(mitk::Vector3D& pos, mitk::Vector3D& rot)
{
auto plane = randGen->GetIntegerVariate(5) + 1;
MITK_INFO << "Plane: " << plane;
switch(plane)
{
case 1:
{
pos[0] = randGen->GetUniformVariate(0, m_VolumeSize[0]);
pos[1] = randGen->GetUniformVariate(0, m_VolumeSize[1]);
pos[2] = 0;
rot[0] = 0;
rot[1] = 0;
rot[2] = 0;
break;
}
case 2:
{
pos[0] = 0;
pos[1] = randGen->GetUniformVariate(0, m_VolumeSize[1]);
pos[2] = randGen->GetUniformVariate(0, m_VolumeSize[2]);
rot[0] = 0;
rot[1] = 90;
rot[2] = 0;
break;
}
case 3:
{
pos[0] = randGen->GetUniformVariate(0, m_VolumeSize[0]);
pos[1] = 0;
pos[2] = randGen->GetUniformVariate(0, m_VolumeSize[2]);
rot[0] = -90;
rot[1] = 0;
rot[2] = 0;
break;
}
case 4:
{
pos[0] = randGen->GetUniformVariate(0, m_VolumeSize[0]);
pos[1] = m_VolumeSize[1];
pos[2] = randGen->GetUniformVariate(0, m_VolumeSize[2]);
rot[0] = 90;
rot[1] = 0;
rot[2] = 0;
break;
}
case 5:
{
pos[0] = m_VolumeSize[0];
pos[1] = randGen->GetUniformVariate(0, m_VolumeSize[1]);
pos[2] = randGen->GetUniformVariate(0, m_VolumeSize[2]);
rot[0] = 0;
rot[1] = -90;
rot[2] = 0;
break;
}
case 6:
{
pos[0] = randGen->GetUniformVariate(0, m_VolumeSize[0]);
pos[1] = randGen->GetUniformVariate(0, m_VolumeSize[1]);
pos[2] = m_VolumeSize[2];
rot[0] = 180;
rot[1] = 0;
rot[2] = 0;
break;
}
}
}
bool RandomPhantomFilter::IsInVolume(mitk::Vector3D pos)
{
if (pos[0]>=0 &&
pos[0]<=m_VolumeSize[0] &&
pos[1]>=0 &&
pos[1]<=m_VolumeSize[1] &&
pos[2]>=0 &&
pos[2]<=m_VolumeSize[2])
return true;
return false;
}
void RandomPhantomFilter::SetFixSeed(int FixSeed)
{
m_FixSeed = FixSeed;
}
void RandomPhantomFilter::SetMinTwist(unsigned int MinTwist)
{
m_MinTwist = MinTwist;
}
void RandomPhantomFilter::SetMaxStreamlineDensity(unsigned int MaxStreamlineDensity)
{
m_MaxStreamlineDensity = MaxStreamlineDensity;
}
void RandomPhantomFilter::SetMinStreamlineDensity(unsigned int MinStreamlinDensity)
{
m_MinStreamlineDensity = MinStreamlinDensity;
}
void RandomPhantomFilter::SetMaxTwist(unsigned int MaxTwist)
{
m_MaxTwist = MaxTwist;
}
void RandomPhantomFilter::SetVolumeSize(const mitk::Vector3D &VolumeSize)
{
m_VolumeSize = VolumeSize;
}
void RandomPhantomFilter::SetStepSizeMax(unsigned int StepSizeMax)
{
m_StepSizeMax = StepSizeMax;
}
void RandomPhantomFilter::SetStepSizeMin(unsigned int StepSizeMin)
{
m_StepSizeMin = StepSizeMin;
}
void RandomPhantomFilter::SetCurvynessMax(unsigned int CurvynessMax)
{
m_CurvynessMax = CurvynessMax;
}
void RandomPhantomFilter::SetCurvynessMin(unsigned int CurvynessMin)
{
m_CurvynessMin = CurvynessMin;
}
void RandomPhantomFilter::SetStartRadiusMax(unsigned int StartRadiusMax)
{
m_StartRadiusMax = StartRadiusMax;
}
void RandomPhantomFilter::SetStartRadiusMin(unsigned int StartRadiusMin)
{
m_StartRadiusMin = StartRadiusMin;
}
void RandomPhantomFilter::GenerateData()
{
randGen = Statistics::MersenneTwisterRandomVariateGenerator::New();
if (m_FixSeed>=0)
randGen->SetSeed(m_FixSeed);
else
randGen->SetSeed();
for (unsigned int i=0; i<m_NumTracts; ++i)
{
MITK_INFO << "Generating Bundle_" << i+1;
FiberGenerationParameters fiber_params;
std::vector< mitk::PlanarEllipse::Pointer > bundle_waypoints;
double curvyness = randGen->GetUniformVariate(m_CurvynessMin, m_CurvynessMax);
int twistdir = static_cast<int>(randGen->GetIntegerVariate(2)) - 1;
double dtwist = randGen->GetUniformVariate(m_MinTwist, m_MaxTwist);
mitk::Vector3D pos; pos.Fill(0.0);
mitk::Vector3D rot; rot.Fill(0.0);
double twist = 0;
double radius1 = randGen->GetUniformVariate(m_StartRadiusMin, m_StartRadiusMax);
double radius2 = randGen->GetUniformVariate(m_StartRadiusMin, m_StartRadiusMax);
GetPfOnBoundingPlane(pos, rot);
rot[0] += randGen->GetUniformVariate(-curvyness, curvyness);
rot[1] += randGen->GetUniformVariate(-curvyness, curvyness);
rot[2] += randGen->GetUniformVariate(-curvyness, curvyness);
mitk::PlanarEllipse::Pointer start = CreatePlanarFigure();
TransformPlanarFigure(start, pos, rot, twist, radius1, radius2);
bundle_waypoints.push_back(start);
double c_area = itk::Math::pi*radius1*radius2;
int sizestrategy = static_cast<int>(randGen->GetIntegerVariate(2)) - 1;
MITK_INFO << "Twist: " << dtwist;
MITK_INFO << "Twist direction: " << twistdir;
MITK_INFO << "Curvyness: " << curvyness;
MITK_INFO << "Size strategy: " << sizestrategy;
int c = 1;
while(IsInVolume(pos))
{
pos += bundle_waypoints.at(c-1)->GetPlaneGeometry()->GetNormal() * randGen->GetUniformVariate(m_StepSizeMin, m_StepSizeMax);
rot[0] += randGen->GetUniformVariate(-curvyness, curvyness);
rot[1] += randGen->GetUniformVariate(-curvyness, curvyness);
rot[2] += randGen->GetUniformVariate(-curvyness, curvyness);
twist += dtwist * twistdir;
if (randGen->GetUniformVariate(0.0, 1.0) < 0.25)
{
int temp = static_cast<int>(randGen->GetIntegerVariate(2)) - 1;
if (temp!=twistdir)
{
twistdir = temp;
MITK_INFO << "Twist direction change: " << twistdir;
}
}
if (randGen->GetUniformVariate(0.0, 1.0) < 0.25)
{
int temp = static_cast<int>(randGen->GetIntegerVariate(2)) - 1;
if (temp!=sizestrategy)
{
sizestrategy = temp;
MITK_INFO << "Size strategy change: " << sizestrategy;
}
}
double minradius = 0.5*static_cast<double>(m_StartRadiusMin);
double dsize = 0.5*minradius;
double maxradius = 2.0*static_cast<double>(m_StartRadiusMax);
if (sizestrategy==0)
{
radius1 += randGen->GetUniformVariate(-dsize, dsize);
radius2 += randGen->GetUniformVariate(-dsize, dsize);
while (radius1 < 5)
radius1 += randGen->GetUniformVariate(-dsize, dsize);
while (radius2 < 5)
radius2 += randGen->GetUniformVariate(-dsize, dsize);
}
else if (sizestrategy==1)
{
radius1 += randGen->GetUniformVariate(0, dsize);
radius2 += randGen->GetUniformVariate(0, dsize);
if (radius1 > maxradius)
{
radius1 = maxradius;
sizestrategy = static_cast<int>(randGen->GetIntegerVariate(1)) - 1;
}
if (radius2 > maxradius)
{
radius2 = maxradius;
sizestrategy = static_cast<int>(randGen->GetIntegerVariate(1)) - 1;
}
}
else if (sizestrategy==-1)
{
radius1 += randGen->GetUniformVariate(-dsize, 0);
radius2 += randGen->GetUniformVariate(-dsize, 0);
if (radius1 < minradius)
{
radius1 = minradius;
sizestrategy = static_cast<int>(randGen->GetIntegerVariate(1));
}
if (radius2 < minradius)
{
radius2 = minradius;
sizestrategy = static_cast<int>(randGen->GetIntegerVariate(1));
}
}
c_area += itk::Math::pi*radius1*radius2;
mitk::PlanarEllipse::Pointer pf = CreatePlanarFigure();
TransformPlanarFigure(pf, pos, rot, twist, radius1, radius2);
bundle_waypoints.push_back(pf);
++c;
}
c_area /= c;
c_area /= 100;
MITK_INFO << "Average crossectional area: " << c_area << "cm²";
fiber_params.m_Fiducials.push_back(bundle_waypoints);
auto density = randGen->GetUniformVariate(m_MinStreamlineDensity, m_MaxStreamlineDensity);
MITK_INFO << "Density: " << density;
MITK_INFO << "Num. fibers: " << fiber_params.m_Density;
fiber_params.m_Density = static_cast<unsigned int>(std::ceil(c_area*density));
if (randGen->GetIntegerVariate(1)==0)
{
fiber_params.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM;
MITK_INFO << "Distribution: uniform";
}
else
{
fiber_params.m_Distribution = FiberGenerationParameters::DISTRIBUTE_GAUSSIAN;
MITK_INFO << "Distribution: Gaussian";
}
MITK_INFO << "Num. fiducials: " << c;
MITK_INFO << "------------\n";
std::streambuf *old = cout.rdbuf(); // <-- save
std::stringstream ss;
std::cout.rdbuf (ss.rdbuf()); // <-- redirect
itk::FibersFromPlanarFiguresFilter::Pointer filter = itk::FibersFromPlanarFiguresFilter::New();
filter->SetParameters(fiber_params);
filter->SetFixSeed(m_FixSeed);
filter->Update();
m_FiberBundles.push_back(filter->GetFiberBundles().at(0));
std::cout.rdbuf (old); // <-- restore
}
}
}
//#endif // __itkRandomPhantomFilter_cpp
diff --git a/Modules/MriSimulation/Algorithms/itkRandomPhantomFilter.h b/Modules/MriSimulation/Algorithms/itkRandomPhantomFilter.h
index 37fa59b..b62a7f1 100644
--- a/Modules/MriSimulation/Algorithms/itkRandomPhantomFilter.h
+++ b/Modules/MriSimulation/Algorithms/itkRandomPhantomFilter.h
@@ -1,114 +1,114 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 itkRandomPhantomFilter_h
#define itkRandomPhantomFilter_h
// MITK
#include <mitkPlanarEllipse.h>
#include <mitkFiberBundle.h>
#include <mitkFiberfoxParameters.h>
// ITK
#include <itkProcessObject.h>
#include <itkMersenneTwisterRandomVariateGenerator.h>
namespace itk{
/**
* \brief */
class RandomPhantomFilter : public ProcessObject
{
public:
typedef RandomPhantomFilter Self;
typedef ProcessObject Superclass;
typedef SmartPointer< Self > Pointer;
typedef SmartPointer< const Self > ConstPointer;
typedef mitk::FiberBundle::Pointer FiberType;
typedef std::vector< mitk::FiberBundle::Pointer > FiberContainerType;
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
itkTypeMacro( RandomPhantomFilter, ProcessObject )
void Update() override{
this->GenerateData();
}
// output
FiberContainerType GetFiberBundles(){ return m_FiberBundles; }
void SetNumTracts(unsigned int NumTracts);
void SetStartRadiusMin(unsigned int StartRadiusMin);
void SetStartRadiusMax(unsigned int StartRadiusMax);
void SetCurvynessMin(unsigned int CurvynessMin);
void SetCurvynessMax(unsigned int CurvynessMax);
void SetStepSizeMin(unsigned int StepSizeMin);
void SetStepSizeMax(unsigned int StepSizeMax);
void SetVolumeSize(const mitk::Vector3D &VolumeSize);
void SetMaxTwist(unsigned int MaxTwist);
void SetMinStreamlineDensity(unsigned int MinStreamlinDensity);
void SetMaxStreamlineDensity(unsigned int MaxStreamlineDensity);
void SetMinTwist(unsigned int MinTwist);
void SetFixSeed(int FixSeed);
protected:
void GenerateData() override;
RandomPhantomFilter();
~RandomPhantomFilter() override;
void TransformPlanarFigure(mitk::PlanarEllipse* pe, mitk::Vector3D translation, mitk::Vector3D rotation, double twistangle, double radius1, double radius2);
mitk::PlanarEllipse::Pointer CreatePlanarFigure();
void GetPfOnBoundingPlane(mitk::Vector3D& pos, mitk::Vector3D& rot);
bool IsInVolume(mitk::Vector3D pos);
FiberContainerType m_FiberBundles; ///< container for the output fiber bundles
unsigned int m_NumTracts;
unsigned int m_MinStreamlineDensity;
unsigned int m_MaxStreamlineDensity;
unsigned int m_StartRadiusMin;
unsigned int m_StartRadiusMax;
unsigned int m_CurvynessMin;
unsigned int m_CurvynessMax;
unsigned int m_StepSizeMin;
unsigned int m_StepSizeMax;
unsigned int m_MinTwist;
unsigned int m_MaxTwist;
mitk::Vector3D m_VolumeSize;
int m_FixSeed;
Statistics::MersenneTwisterRandomVariateGenerator::Pointer randGen;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkRandomPhantomFilter.cpp"
#endif
#endif
diff --git a/Modules/MriSimulation/Algorithms/itkTractsToDWIImageFilter.cpp b/Modules/MriSimulation/Algorithms/itkTractsToDWIImageFilter.cpp
index 97d5f59..319aa61 100644
--- a/Modules/MriSimulation/Algorithms/itkTractsToDWIImageFilter.cpp
+++ b/Modules/MriSimulation/Algorithms/itkTractsToDWIImageFilter.cpp
@@ -1,1767 +1,1767 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "itkTractsToDWIImageFilter.h"
#include <boost/progress.hpp>
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <vtkCellArray.h>
#include <vtkPoints.h>
#include <vtkPolyLine.h>
#include <itkImageRegionIteratorWithIndex.h>
#include <itkResampleImageFilter.h>
#include <itkNearestNeighborInterpolateImageFunction.h>
#include <itkBSplineInterpolateImageFunction.h>
#include <itkCastImageFilter.h>
#include <itkImageFileWriter.h>
#include <itkRescaleIntensityImageFilter.h>
#include <itkWindowedSincInterpolateImageFunction.h>
#include <itkResampleDwiImageFilter.h>
#include <itkKspaceImageFilter.h>
#include <itkDftImageFilter.h>
#include <itkAddImageFilter.h>
#include <itkConstantPadImageFilter.h>
#include <itkCropImageFilter.h>
#include <mitkAstroStickModel.h>
#include <vtkTransform.h>
#include <iostream>
#include <fstream>
#include <exception>
#include <itkImageDuplicator.h>
#include <itksys/SystemTools.hxx>
#include <mitkIOUtil.h>
#include <itkDiffusionTensor3DReconstructionImageFilter.h>
#include <itkDiffusionTensor3D.h>
#include <itkTractDensityImageFilter.h>
#include <mitkLexicalCast.h>
#include <itkTractsToVectorImageFilter.h>
#include <itkInvertIntensityImageFilter.h>
#include <itkShiftScaleImageFilter.h>
#include <itkExtractImageFilter.h>
#include <itkResampleDwiImageFilter.h>
#include <boost/algorithm/string/replace.hpp>
#include <omp.h>
#include <cmath>
#include <thread>
namespace itk
{
template< class PixelType >
TractsToDWIImageFilter< PixelType >::TractsToDWIImageFilter()
: m_StatusText("")
, m_UseConstantRandSeed(false)
, m_RandGen(itk::Statistics::MersenneTwisterRandomVariateGenerator::New())
{
m_DoubleInterpolator = itk::LinearInterpolateImageFunction< ItkDoubleImgType, float >::New();
m_NullDir.Fill(0);
}
template< class PixelType >
TractsToDWIImageFilter< PixelType >::~TractsToDWIImageFilter()
{
}
template< class PixelType >
TractsToDWIImageFilter< PixelType >::DoubleDwiType::Pointer TractsToDWIImageFilter< PixelType >::
SimulateKspaceAcquisition( std::vector< DoubleDwiType::Pointer >& compartment_images )
{
unsigned int numFiberCompartments = m_Parameters.m_FiberModelList.size();
// create slice object
ImageRegion<2> sliceRegion;
sliceRegion.SetSize(0, m_WorkingImageRegion.GetSize()[0]);
sliceRegion.SetSize(1, m_WorkingImageRegion.GetSize()[1]);
Vector< double, 2 > sliceSpacing;
sliceSpacing[0] = m_WorkingSpacing[0];
sliceSpacing[1] = m_WorkingSpacing[1];
DoubleDwiType::PixelType nullPix; nullPix.SetSize(compartment_images.at(0)->GetVectorLength()); nullPix.Fill(0.0);
auto magnitudeDwiImage = DoubleDwiType::New();
magnitudeDwiImage->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing );
magnitudeDwiImage->SetOrigin( m_Parameters.m_SignalGen.m_ImageOrigin );
magnitudeDwiImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection );
magnitudeDwiImage->SetLargestPossibleRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
magnitudeDwiImage->SetBufferedRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
magnitudeDwiImage->SetRequestedRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
magnitudeDwiImage->SetVectorLength( compartment_images.at(0)->GetVectorLength() );
magnitudeDwiImage->Allocate();
magnitudeDwiImage->FillBuffer(nullPix);
m_PhaseImage = DoubleDwiType::New();
m_PhaseImage->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing );
m_PhaseImage->SetOrigin( m_Parameters.m_SignalGen.m_ImageOrigin );
m_PhaseImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection );
m_PhaseImage->SetLargestPossibleRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
m_PhaseImage->SetBufferedRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
m_PhaseImage->SetRequestedRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
m_PhaseImage->SetVectorLength( compartment_images.at(0)->GetVectorLength() );
m_PhaseImage->Allocate();
m_PhaseImage->FillBuffer(nullPix);
m_KspaceImage = DoubleDwiType::New();
m_KspaceImage->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing );
m_KspaceImage->SetOrigin( m_Parameters.m_SignalGen.m_ImageOrigin );
m_KspaceImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection );
m_KspaceImage->SetLargestPossibleRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
m_KspaceImage->SetBufferedRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
m_KspaceImage->SetRequestedRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
m_KspaceImage->SetVectorLength( m_Parameters.m_SignalGen.m_NumberOfCoils );
m_KspaceImage->Allocate();
m_KspaceImage->FillBuffer(nullPix);
// calculate coil positions
double a = m_Parameters.m_SignalGen.m_ImageRegion.GetSize(0)*m_Parameters.m_SignalGen.m_ImageSpacing[0];
double b = m_Parameters.m_SignalGen.m_ImageRegion.GetSize(1)*m_Parameters.m_SignalGen.m_ImageSpacing[1];
double c = m_Parameters.m_SignalGen.m_ImageRegion.GetSize(2)*m_Parameters.m_SignalGen.m_ImageSpacing[2];
double diagonal = sqrt(a*a+b*b)/1000; // image diagonal in m
m_CoilPointset = mitk::PointSet::New();
std::vector< itk::Vector<double, 3> > coilPositions;
itk::Vector<double, 3> pos; pos.Fill(0.0); pos[1] = -diagonal/2;
itk::Vector<double, 3> center;
center[0] = a/2-m_Parameters.m_SignalGen.m_ImageSpacing[0]/2;
center[1] = b/2-m_Parameters.m_SignalGen.m_ImageSpacing[2]/2;
center[2] = c/2-m_Parameters.m_SignalGen.m_ImageSpacing[1]/2;
for (unsigned int c=0; c<m_Parameters.m_SignalGen.m_NumberOfCoils; c++)
{
coilPositions.push_back(pos);
m_CoilPointset->InsertPoint(c, pos*1000 + m_Parameters.m_SignalGen.m_ImageOrigin.GetVectorFromOrigin() + center );
double rz = 360.0/m_Parameters.m_SignalGen.m_NumberOfCoils * itk::Math::pi/180;
vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity();
rotZ[0][0] = cos(rz);
rotZ[1][1] = rotZ[0][0];
rotZ[0][1] = -sin(rz);
rotZ[1][0] = -rotZ[0][1];
pos.SetVnlVector(rotZ*pos.GetVnlVector());
}
auto num_slices = compartment_images.at(0)->GetLargestPossibleRegion().GetSize(2);
auto num_gradient_volumes = static_cast<int>(compartment_images.at(0)->GetVectorLength());
auto max_threads = omp_get_max_threads();
int out_threads = Math::ceil(std::sqrt(max_threads));
int in_threads = Math::floor(std::sqrt(max_threads));
if (out_threads > num_gradient_volumes)
{
out_threads = num_gradient_volumes;
in_threads = Math::floor(static_cast<float>(max_threads/out_threads));
}
PrintToLog("Parallel volumes: " + boost::lexical_cast<std::string>(out_threads), false, true, true);
PrintToLog("Threads per slice: " + boost::lexical_cast<std::string>(in_threads), false, true, true);
std::list< std::tuple<unsigned int, unsigned int, unsigned int> > spikes;
if (m_Parameters.m_Misc.m_DoAddSpikes)
for (unsigned int i=0; i<m_Parameters.m_SignalGen.m_Spikes; i++)
{
// gradient volume and slice index
auto spike = std::tuple<unsigned int, unsigned int, unsigned int>(
m_RandGen->GetIntegerVariate()%num_gradient_volumes,
m_RandGen->GetIntegerVariate()%num_slices,
m_RandGen->GetIntegerVariate()%m_Parameters.m_SignalGen.m_NumberOfCoils);
spikes.push_back(spike);
}
bool output_timing = m_Parameters.m_Misc.m_OutputAdditionalImages;
PrintToLog("0% 10 20 30 40 50 60 70 80 90 100%", false, true, false);
PrintToLog("|----|----|----|----|----|----|----|----|----|----|\n*", false, false, false);
unsigned long lastTick = 0;
boost::progress_display disp(static_cast<unsigned long>(num_gradient_volumes)*compartment_images.at(0)->GetLargestPossibleRegion().GetSize(2));
#pragma omp parallel for num_threads(out_threads)
for (int g=0; g<num_gradient_volumes; g++)
{
if (this->GetAbortGenerateData())
continue;
std::list< std::tuple<unsigned int, unsigned int> > spikeSlice;
#pragma omp critical
{
for (auto spike : spikes)
if (std::get<0>(spike) == static_cast<unsigned int>(g))
spikeSlice.push_back(std::tuple<unsigned int, unsigned int>(std::get<1>(spike), std::get<2>(spike)));
}
for (unsigned int z=0; z<num_slices; z++)
{
std::vector< Float2DImageType::Pointer > compartment_slices;
std::vector< float > t2Vector;
std::vector< float > t1Vector;
for (unsigned int i=0; i<compartment_images.size(); i++)
{
DiffusionSignalModel<double>* signalModel;
if (i<numFiberCompartments)
signalModel = m_Parameters.m_FiberModelList.at(i);
else
signalModel = m_Parameters.m_NonFiberModelList.at(i-numFiberCompartments);
auto slice = Float2DImageType::New();
slice->SetLargestPossibleRegion( sliceRegion );
slice->SetBufferedRegion( sliceRegion );
slice->SetRequestedRegion( sliceRegion );
slice->SetSpacing(sliceSpacing);
slice->Allocate();
slice->FillBuffer(0.0);
// extract slice from channel g
for (unsigned int y=0; y<compartment_images.at(0)->GetLargestPossibleRegion().GetSize(1); y++)
for (unsigned int x=0; x<compartment_images.at(0)->GetLargestPossibleRegion().GetSize(0); x++)
{
Float2DImageType::IndexType index2D; index2D[0]=x; index2D[1]=y;
DoubleDwiType::IndexType index3D; index3D[0]=x; index3D[1]=y; index3D[2]=z;
slice->SetPixel(index2D, compartment_images.at(i)->GetPixel(index3D)[g]);
}
compartment_slices.push_back(slice);
t2Vector.push_back(signalModel->GetT2());
t1Vector.push_back(signalModel->GetT1());
}
if (this->GetAbortGenerateData())
continue;
for (unsigned int c=0; c<m_Parameters.m_SignalGen.m_NumberOfCoils; c++)
{
int numSpikes = 0;
for (auto ss : spikeSlice)
if (std::get<0>(ss) == z && std::get<1>(ss) == c)
++numSpikes;
// create k-sapce (inverse fourier transform slices)
auto idft = itk::KspaceImageFilter< Float2DImageType::PixelType >::New();
idft->SetCompartmentImages(compartment_slices);
idft->SetT2(t2Vector);
idft->SetT1(t1Vector);
if (m_UseConstantRandSeed)
{
int linear_seed = g + num_gradient_volumes*z + num_gradient_volumes*compartment_images.at(0)->GetLargestPossibleRegion().GetSize(2)*c;
idft->SetRandSeed(linear_seed);
}
idft->SetParameters(&m_Parameters);
idft->SetZ((float)z-(float)( compartment_images.at(0)->GetLargestPossibleRegion().GetSize(2)
-compartment_images.at(0)->GetLargestPossibleRegion().GetSize(2)%2 ) / 2.0);
idft->SetZidx(z);
idft->SetCoilPosition(coilPositions.at(c));
idft->SetFiberBundle(m_FiberBundle);
idft->SetTranslation(m_Translations.at(g));
idft->SetRotationMatrix(m_RotationsInv.at(g));
idft->SetDiffusionGradientDirection(m_Parameters.m_SignalGen.GetGradientDirection(g)*m_Parameters.m_SignalGen.GetBvalue()/1000.0);
idft->SetSpikesPerSlice(numSpikes);
idft->SetNumberOfThreads(in_threads);
#pragma omp critical
if (output_timing)
{
idft->SetStoreTimings(true);
output_timing = false;
}
idft->Update();
#pragma omp critical
if (numSpikes>0)
{
m_SpikeLog += "Volume " + boost::lexical_cast<std::string>(g) + " Coil " + boost::lexical_cast<std::string>(c) + "\n";
m_SpikeLog += idft->GetSpikeLog();
}
Complex2DImageType::Pointer fSlice;
fSlice = idft->GetOutput();
if (idft->GetTickImage().IsNotNull())
m_TickImage = idft->GetTickImage();
if (idft->GetRfImage().IsNotNull())
m_RfImage = idft->GetRfImage();
// fourier transform slice
Complex2DImageType::Pointer newSlice;
auto dft = itk::DftImageFilter< Float2DImageType::PixelType >::New();
dft->SetInput(fSlice);
dft->SetParameters(m_Parameters);
dft->SetNumberOfThreads(in_threads);
dft->Update();
newSlice = dft->GetOutput();
// put slice back into channel g
for (unsigned int y=0; y<fSlice->GetLargestPossibleRegion().GetSize(1); y++)
for (unsigned int x=0; x<fSlice->GetLargestPossibleRegion().GetSize(0); x++)
{
DoubleDwiType::IndexType index3D; index3D[0]=x; index3D[1]=y; index3D[2]=z;
Complex2DImageType::IndexType index2D; index2D[0]=x; index2D[1]=y;
Complex2DImageType::PixelType cPix = newSlice->GetPixel(index2D);
double magn = sqrt(cPix.real()*cPix.real()+cPix.imag()*cPix.imag());
double phase = 0;
if (cPix.real()!=0)
phase = atan( cPix.imag()/cPix.real() );
DoubleDwiType::PixelType real_pix = m_OutputImagesReal.at(c)->GetPixel(index3D);
real_pix[g] = cPix.real();
m_OutputImagesReal.at(c)->SetPixel(index3D, real_pix);
DoubleDwiType::PixelType imag_pix = m_OutputImagesImag.at(c)->GetPixel(index3D);
imag_pix[g] = cPix.imag();
m_OutputImagesImag.at(c)->SetPixel(index3D, imag_pix);
DoubleDwiType::PixelType dwiPix = magnitudeDwiImage->GetPixel(index3D);
DoubleDwiType::PixelType phasePix = m_PhaseImage->GetPixel(index3D);
if (m_Parameters.m_SignalGen.m_NumberOfCoils>1)
{
dwiPix[g] += magn*magn;
phasePix[g] += phase*phase;
}
else
{
dwiPix[g] = magn;
phasePix[g] = phase;
}
//#pragma omp critical
{
magnitudeDwiImage->SetPixel(index3D, dwiPix);
m_PhaseImage->SetPixel(index3D, phasePix);
// k-space image
if (g==0)
{
DoubleDwiType::PixelType kspacePix = m_KspaceImage->GetPixel(index3D);
kspacePix[c] = idft->GetKSpaceImage()->GetPixel(index2D);
m_KspaceImage->SetPixel(index3D, kspacePix);
}
}
}
}
if (m_Parameters.m_SignalGen.m_NumberOfCoils>1)
{
for (int y=0; y<static_cast<int>(magnitudeDwiImage->GetLargestPossibleRegion().GetSize(1)); y++)
for (int x=0; x<static_cast<int>(magnitudeDwiImage->GetLargestPossibleRegion().GetSize(0)); x++)
{
DoubleDwiType::IndexType index3D; index3D[0]=x; index3D[1]=y; index3D[2]=z;
DoubleDwiType::PixelType magPix = magnitudeDwiImage->GetPixel(index3D);
magPix[g] = sqrt(magPix[g]/m_Parameters.m_SignalGen.m_NumberOfCoils);
DoubleDwiType::PixelType phasePix = m_PhaseImage->GetPixel(index3D);
phasePix[g] = sqrt(phasePix[g]/m_Parameters.m_SignalGen.m_NumberOfCoils);
//#pragma omp critical
{
magnitudeDwiImage->SetPixel(index3D, magPix);
m_PhaseImage->SetPixel(index3D, phasePix);
}
}
}
++disp;
unsigned long newTick = 50*disp.count()/disp.expected_count();
for (unsigned long tick = 0; tick<(newTick-lastTick); tick++)
PrintToLog("*", false, false, false);
lastTick = newTick;
}
}
PrintToLog("\n", false);
return magnitudeDwiImage;
}
template< class PixelType >
TractsToDWIImageFilter< PixelType >::ItkDoubleImgType::Pointer TractsToDWIImageFilter< PixelType >::
NormalizeInsideMask(ItkDoubleImgType::Pointer image)
{
double max = itk::NumericTraits< double >::min();
double min = itk::NumericTraits< double >::max();
itk::ImageRegionIterator< ItkDoubleImgType > it(image, image->GetLargestPossibleRegion());
while(!it.IsAtEnd())
{
if (m_Parameters.m_SignalGen.m_MaskImage.IsNotNull() && m_Parameters.m_SignalGen.m_MaskImage->GetPixel(it.GetIndex())<=0)
{
it.Set(0.0);
++it;
continue;
}
if (it.Get()>max)
max = it.Get();
if (it.Get()<min)
min = it.Get();
++it;
}
auto scaler = itk::ShiftScaleImageFilter< ItkDoubleImgType, ItkDoubleImgType >::New();
scaler->SetInput(image);
scaler->SetShift(-min);
scaler->SetScale(1.0/(max-min));
scaler->Update();
return scaler->GetOutput();
}
template< class PixelType >
void TractsToDWIImageFilter< PixelType >::CheckVolumeFractionImages()
{
m_UseRelativeNonFiberVolumeFractions = false;
// check for fiber volume fraction maps
unsigned int fibVolImages = 0;
for (std::size_t i=0; i<m_Parameters.m_FiberModelList.size(); i++)
{
if (m_Parameters.m_FiberModelList[i]->GetVolumeFractionImage().IsNotNull())
{
PrintToLog("Using volume fraction map for fiber compartment " + boost::lexical_cast<std::string>(i+1), false);
fibVolImages++;
}
}
// check for non-fiber volume fraction maps
unsigned int nonfibVolImages = 0;
for (std::size_t i=0; i<m_Parameters.m_NonFiberModelList.size(); i++)
{
if (m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage().IsNotNull())
{
PrintToLog("Using volume fraction map for non-fiber compartment " + boost::lexical_cast<std::string>(i+1), false);
nonfibVolImages++;
}
}
// not all fiber compartments are using volume fraction maps
// --> non-fiber volume fractions are assumed to be relative to the
// non-fiber volume and not absolute voxel-volume fractions.
// this means if two non-fiber compartments are used but only one of them
// has an associated volume fraction map, the repesctive other volume fraction map
// can be determined as inverse (1-val) of the present volume fraction map-
if ( fibVolImages<m_Parameters.m_FiberModelList.size() && nonfibVolImages==1 && m_Parameters.m_NonFiberModelList.size()==2)
{
PrintToLog("Calculating missing non-fiber volume fraction image by inverting the other.\n"
"Assuming non-fiber volume fraction images to contain values relative to the"
" remaining non-fiber volume, not absolute values.", false);
auto inverter = itk::InvertIntensityImageFilter< ItkDoubleImgType, ItkDoubleImgType >::New();
inverter->SetMaximum(1.0);
if ( m_Parameters.m_NonFiberModelList[0]->GetVolumeFractionImage().IsNull()
&& m_Parameters.m_NonFiberModelList[1]->GetVolumeFractionImage().IsNotNull() )
{
// m_Parameters.m_NonFiberModelList[1]->SetVolumeFractionImage(
// NormalizeInsideMask( m_Parameters.m_NonFiberModelList[1]->GetVolumeFractionImage() ) );
inverter->SetInput( m_Parameters.m_NonFiberModelList[1]->GetVolumeFractionImage() );
inverter->Update();
m_Parameters.m_NonFiberModelList[0]->SetVolumeFractionImage(inverter->GetOutput());
}
else if ( m_Parameters.m_NonFiberModelList[1]->GetVolumeFractionImage().IsNull()
&& m_Parameters.m_NonFiberModelList[0]->GetVolumeFractionImage().IsNotNull() )
{
// m_Parameters.m_NonFiberModelList[0]->SetVolumeFractionImage(
// NormalizeInsideMask( m_Parameters.m_NonFiberModelList[0]->GetVolumeFractionImage() ) );
inverter->SetInput( m_Parameters.m_NonFiberModelList[0]->GetVolumeFractionImage() );
inverter->Update();
m_Parameters.m_NonFiberModelList[1]->SetVolumeFractionImage(inverter->GetOutput());
}
else
{
itkExceptionMacro("Something went wrong in automatically calculating the missing non-fiber volume fraction image!"
" Did you use two non fiber compartments but only one volume fraction image?"
" Then it should work and this error is really strange.");
}
m_UseRelativeNonFiberVolumeFractions = true;
nonfibVolImages++;
}
// Up to two fiber compartments are allowed without volume fraction maps since the volume fractions can then be determined automatically
if (m_Parameters.m_FiberModelList.size()>2
&& fibVolImages!=m_Parameters.m_FiberModelList.size())
itkExceptionMacro("More than two fiber compartment selected but no corresponding volume fraction maps set!");
// One non-fiber compartment is allowed without volume fraction map since the volume fraction can then be determined automatically
if (m_Parameters.m_NonFiberModelList.size()>1
&& nonfibVolImages!=m_Parameters.m_NonFiberModelList.size())
itkExceptionMacro("More than one non-fiber compartment selected but no volume fraction maps set!");
if (fibVolImages<m_Parameters.m_FiberModelList.size() && nonfibVolImages>0)
{
PrintToLog("Not all fiber compartments are using an associated volume fraction image.\n"
"Assuming non-fiber volume fraction images to contain values relative to the"
" remaining non-fiber volume, not absolute values.", false);
m_UseRelativeNonFiberVolumeFractions = true;
// mitk::LocaleSwitch localeSwitch("C");
// itk::ImageFileWriter<ItkDoubleImgType>::Pointer wr = itk::ImageFileWriter<ItkDoubleImgType>::New();
// wr->SetInput(m_Parameters.m_NonFiberModelList[1]->GetVolumeFractionImage());
// wr->SetFileName("/local/volumefraction.nrrd");
// wr->Update();
}
// initialize the images that store the output volume fraction of each compartment
m_VolumeFractions.clear();
for (std::size_t i=0; i<m_Parameters.m_FiberModelList.size()+m_Parameters.m_NonFiberModelList.size(); i++)
{
auto doubleImg = ItkDoubleImgType::New();
doubleImg->SetSpacing( m_WorkingSpacing );
doubleImg->SetOrigin( m_WorkingOrigin );
doubleImg->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection );
doubleImg->SetLargestPossibleRegion( m_WorkingImageRegion );
doubleImg->SetBufferedRegion( m_WorkingImageRegion );
doubleImg->SetRequestedRegion( m_WorkingImageRegion );
doubleImg->Allocate();
doubleImg->FillBuffer(0);
m_VolumeFractions.push_back(doubleImg);
}
}
template< class PixelType >
void TractsToDWIImageFilter< PixelType >::InitializeData()
{
m_Rotations.clear();
m_Translations.clear();
m_MotionLog = "";
m_SpikeLog = "";
m_TickImage = nullptr;
m_RfImage = nullptr;
// initialize output dwi image
m_Parameters.m_SignalGen.m_CroppedRegion = m_Parameters.m_SignalGen.m_ImageRegion;
if (m_Parameters.m_Misc.m_DoAddAliasing)
m_Parameters.m_SignalGen.m_CroppedRegion.SetSize( 1, m_Parameters.m_SignalGen.m_CroppedRegion.GetSize(1)
*m_Parameters.m_SignalGen.m_CroppingFactor);
itk::Point<double,3> shiftedOrigin = m_Parameters.m_SignalGen.m_ImageOrigin;
shiftedOrigin[1] += (m_Parameters.m_SignalGen.m_ImageRegion.GetSize(1)
-m_Parameters.m_SignalGen.m_CroppedRegion.GetSize(1))*m_Parameters.m_SignalGen.m_ImageSpacing[1]/2;
m_OutputImage = OutputImageType::New();
m_OutputImage->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing );
m_OutputImage->SetOrigin( shiftedOrigin );
m_OutputImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection );
m_OutputImage->SetLargestPossibleRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
m_OutputImage->SetBufferedRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
m_OutputImage->SetRequestedRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
m_OutputImage->SetVectorLength( m_Parameters.m_SignalGen.GetNumVolumes() );
m_OutputImage->Allocate();
typename OutputImageType::PixelType temp;
temp.SetSize(m_Parameters.m_SignalGen.GetNumVolumes());
temp.Fill(0.0);
m_OutputImage->FillBuffer(temp);
PrintToLog("Output image spacing: [" + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_ImageSpacing[0]) + "," + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_ImageSpacing[1]) + "," + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_ImageSpacing[2]) + "]", false);
PrintToLog("Output image size: [" + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_CroppedRegion.GetSize(0)) + "," + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_CroppedRegion.GetSize(1)) + "," + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_CroppedRegion.GetSize(2)) + "]", false);
// images containing real and imaginary part of the dMRI signal for each coil
m_OutputImagesReal.clear();
m_OutputImagesImag.clear();
for (unsigned int i=0; i<m_Parameters.m_SignalGen.m_NumberOfCoils; ++i)
{
typename DoubleDwiType::Pointer outputImageReal = DoubleDwiType::New();
outputImageReal->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing );
outputImageReal->SetOrigin( shiftedOrigin );
outputImageReal->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection );
outputImageReal->SetLargestPossibleRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
outputImageReal->SetBufferedRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
outputImageReal->SetRequestedRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
outputImageReal->SetVectorLength( m_Parameters.m_SignalGen.GetNumVolumes() );
outputImageReal->Allocate();
outputImageReal->FillBuffer(temp);
m_OutputImagesReal.push_back(outputImageReal);
typename DoubleDwiType::Pointer outputImageImag = DoubleDwiType::New();
outputImageImag->SetSpacing( m_Parameters.m_SignalGen.m_ImageSpacing );
outputImageImag->SetOrigin( shiftedOrigin );
outputImageImag->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection );
outputImageImag->SetLargestPossibleRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
outputImageImag->SetBufferedRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
outputImageImag->SetRequestedRegion( m_Parameters.m_SignalGen.m_CroppedRegion );
outputImageImag->SetVectorLength( m_Parameters.m_SignalGen.GetNumVolumes() );
outputImageImag->Allocate();
outputImageImag->FillBuffer(temp);
m_OutputImagesImag.push_back(outputImageImag);
}
// Apply in-plane upsampling for Gibbs ringing artifact
double upsampling = 1;
if (m_Parameters.m_SignalGen.m_DoAddGibbsRinging && m_Parameters.m_SignalGen.m_ZeroRinging==0)
upsampling = 2;
m_WorkingSpacing = m_Parameters.m_SignalGen.m_ImageSpacing;
m_WorkingSpacing[0] /= upsampling;
m_WorkingSpacing[1] /= upsampling;
m_WorkingImageRegion = m_Parameters.m_SignalGen.m_ImageRegion;
m_WorkingImageRegion.SetSize(0, m_Parameters.m_SignalGen.m_ImageRegion.GetSize()[0]*upsampling);
m_WorkingImageRegion.SetSize(1, m_Parameters.m_SignalGen.m_ImageRegion.GetSize()[1]*upsampling);
m_WorkingOrigin = m_Parameters.m_SignalGen.m_ImageOrigin;
m_WorkingOrigin[0] -= m_Parameters.m_SignalGen.m_ImageSpacing[0]/2;
m_WorkingOrigin[0] += m_WorkingSpacing[0]/2;
m_WorkingOrigin[1] -= m_Parameters.m_SignalGen.m_ImageSpacing[1]/2;
m_WorkingOrigin[1] += m_WorkingSpacing[1]/2;
m_WorkingOrigin[2] -= m_Parameters.m_SignalGen.m_ImageSpacing[2]/2;
m_WorkingOrigin[2] += m_WorkingSpacing[2]/2;
m_VoxelVolume = m_WorkingSpacing[0]*m_WorkingSpacing[1]*m_WorkingSpacing[2];
PrintToLog("Working image spacing: [" + boost::lexical_cast<std::string>(m_WorkingSpacing[0]) + "," + boost::lexical_cast<std::string>(m_WorkingSpacing[1]) + "," + boost::lexical_cast<std::string>(m_WorkingSpacing[2]) + "]", false);
PrintToLog("Working image size: [" + boost::lexical_cast<std::string>(m_WorkingImageRegion.GetSize(0)) + "," + boost::lexical_cast<std::string>(m_WorkingImageRegion.GetSize(1)) + "," + boost::lexical_cast<std::string>(m_WorkingImageRegion.GetSize(2)) + "]", false);
// generate double images to store the individual compartment signals
m_CompartmentImages.clear();
int numFiberCompartments = m_Parameters.m_FiberModelList.size();
int numNonFiberCompartments = m_Parameters.m_NonFiberModelList.size();
for (int i=0; i<numFiberCompartments+numNonFiberCompartments; i++)
{
auto doubleDwi = DoubleDwiType::New();
doubleDwi->SetSpacing( m_WorkingSpacing );
doubleDwi->SetOrigin( m_WorkingOrigin );
doubleDwi->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection );
doubleDwi->SetLargestPossibleRegion( m_WorkingImageRegion );
doubleDwi->SetBufferedRegion( m_WorkingImageRegion );
doubleDwi->SetRequestedRegion( m_WorkingImageRegion );
doubleDwi->SetVectorLength( m_Parameters.m_SignalGen.GetNumVolumes() );
doubleDwi->Allocate();
DoubleDwiType::PixelType pix;
pix.SetSize(m_Parameters.m_SignalGen.GetNumVolumes());
pix.Fill(0.0);
doubleDwi->FillBuffer(pix);
m_CompartmentImages.push_back(doubleDwi);
}
if (m_FiberBundle.IsNull() && m_InputImage.IsNotNull())
{
m_CompartmentImages.clear();
m_Parameters.m_SignalGen.m_DoAddMotion = false;
m_Parameters.m_SignalGen.m_DoSimulateRelaxation = false;
PrintToLog("Simulating acquisition for input diffusion-weighted image.", false);
auto caster = itk::CastImageFilter< OutputImageType, DoubleDwiType >::New();
caster->SetInput(m_InputImage);
caster->Update();
if (m_Parameters.m_SignalGen.m_DoAddGibbsRinging && m_Parameters.m_SignalGen.m_ZeroRinging==0)
{
PrintToLog("Upsampling input diffusion-weighted image for Gibbs ringing simulation.", false);
auto resampler = itk::ResampleDwiImageFilter< double >::New();
resampler->SetInput(caster->GetOutput());
itk::Vector< double, 3 > samplingFactor;
samplingFactor[0] = upsampling;
samplingFactor[1] = upsampling;
samplingFactor[2] = 1;
resampler->SetSamplingFactor(samplingFactor);
resampler->SetInterpolation(itk::ResampleDwiImageFilter< double >::Interpolate_WindowedSinc);
resampler->Update();
m_CompartmentImages.push_back(resampler->GetOutput());
}
else
m_CompartmentImages.push_back(caster->GetOutput());
VectorType translation; translation.Fill(0.0);
MatrixType rotation; rotation.SetIdentity();
for (unsigned int g=0; g<m_Parameters.m_SignalGen.GetNumVolumes(); g++)
{
m_Rotations.push_back(rotation);
m_RotationsInv.push_back(rotation);
m_Translations.push_back(translation);
}
}
// resample mask image and frequency map to fit upsampled geometry
if (m_Parameters.m_SignalGen.m_MaskImage.IsNotNull() && m_Parameters.m_SignalGen.m_MaskImage->GetLargestPossibleRegion()!=m_WorkingImageRegion)
{
PrintToLog("Resampling tissue mask", false);
// rescale mask image (otherwise there are problems with the resampling)
auto rescaler = itk::RescaleIntensityImageFilter<ItkUcharImgType,ItkUcharImgType>::New();
rescaler->SetInput(0,m_Parameters.m_SignalGen.m_MaskImage);
rescaler->SetOutputMaximum(100);
rescaler->SetOutputMinimum(0);
rescaler->Update();
// resample mask image
auto resampler = itk::ResampleImageFilter<ItkUcharImgType, ItkUcharImgType>::New();
resampler->SetInput(rescaler->GetOutput());
resampler->SetSize(m_WorkingImageRegion.GetSize());
resampler->SetOutputSpacing(m_WorkingSpacing);
resampler->SetOutputOrigin(m_WorkingOrigin);
resampler->SetOutputDirection(m_Parameters.m_SignalGen.m_ImageDirection);
resampler->SetOutputStartIndex ( m_WorkingImageRegion.GetIndex() );
auto nn_interpolator = itk::NearestNeighborInterpolateImageFunction<ItkUcharImgType, double>::New();
resampler->SetInterpolator(nn_interpolator);
resampler->Update();
m_Parameters.m_SignalGen.m_MaskImage = resampler->GetOutput();
}
// resample frequency map
if (m_Parameters.m_SignalGen.m_FrequencyMap.IsNotNull() && m_Parameters.m_SignalGen.m_FrequencyMap->GetLargestPossibleRegion()!=m_WorkingImageRegion)
{
PrintToLog("Resampling frequency map", false);
auto resampler = itk::ResampleImageFilter<ItkFloatImgType, ItkFloatImgType>::New();
resampler->SetInput(m_Parameters.m_SignalGen.m_FrequencyMap);
resampler->SetSize(m_WorkingImageRegion.GetSize());
resampler->SetOutputSpacing(m_WorkingSpacing);
resampler->SetOutputOrigin(m_WorkingOrigin);
resampler->SetOutputDirection(m_Parameters.m_SignalGen.m_ImageDirection);
resampler->SetOutputStartIndex ( m_WorkingImageRegion.GetIndex() );
auto nn_interpolator = itk::NearestNeighborInterpolateImageFunction<ItkFloatImgType, double>::New();
resampler->SetInterpolator(nn_interpolator);
resampler->Update();
m_Parameters.m_SignalGen.m_FrequencyMap = resampler->GetOutput();
}
m_MaskImageSet = true;
if (m_Parameters.m_SignalGen.m_MaskImage.IsNull())
{
// no input tissue mask is set -> create default
PrintToLog("No tissue mask set", false);
m_Parameters.m_SignalGen.m_MaskImage = ItkUcharImgType::New();
m_Parameters.m_SignalGen.m_MaskImage->SetSpacing( m_WorkingSpacing );
m_Parameters.m_SignalGen.m_MaskImage->SetOrigin( m_WorkingOrigin );
m_Parameters.m_SignalGen.m_MaskImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection );
m_Parameters.m_SignalGen.m_MaskImage->SetLargestPossibleRegion( m_WorkingImageRegion );
m_Parameters.m_SignalGen.m_MaskImage->SetBufferedRegion( m_WorkingImageRegion );
m_Parameters.m_SignalGen.m_MaskImage->SetRequestedRegion( m_WorkingImageRegion );
m_Parameters.m_SignalGen.m_MaskImage->Allocate();
m_Parameters.m_SignalGen.m_MaskImage->FillBuffer(100);
m_MaskImageSet = false;
}
else
{
PrintToLog("Using tissue mask", false);
}
if (m_Parameters.m_SignalGen.m_DoAddMotion)
{
if (m_Parameters.m_SignalGen.m_DoRandomizeMotion)
{
PrintToLog("Random motion artifacts:", false);
PrintToLog("Maximum rotation: +/-" + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_Rotation) + "°", false);
PrintToLog("Maximum translation: +/-" + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_Translation) + "mm", false);
}
else
{
PrintToLog("Linear motion artifacts:", false);
PrintToLog("Maximum rotation: " + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_Rotation) + "°", false);
PrintToLog("Maximum translation: " + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_Translation) + "mm", false);
}
}
if ( m_Parameters.m_SignalGen.m_MotionVolumes.empty() )
{
// no motion in first volume
m_Parameters.m_SignalGen.m_MotionVolumes.push_back(false);
// motion in all other volumes
while ( m_Parameters.m_SignalGen.m_MotionVolumes.size() < m_Parameters.m_SignalGen.GetNumVolumes() )
{
m_Parameters.m_SignalGen.m_MotionVolumes.push_back(true);
}
}
// we need to know for every volume if there is motion. if this information is missing, then set corresponding fal to false
while ( m_Parameters.m_SignalGen.m_MotionVolumes.size()<m_Parameters.m_SignalGen.GetNumVolumes() )
{
m_Parameters.m_SignalGen.m_MotionVolumes.push_back(false);
}
m_NumMotionVolumes = 0;
for (unsigned int i=0; i<m_Parameters.m_SignalGen.GetNumVolumes(); ++i)
{
if (m_Parameters.m_SignalGen.m_MotionVolumes[i])
++m_NumMotionVolumes;
}
m_MotionCounter = 0;
// creat image to hold transformed mask (motion artifact)
m_TransformedMaskImage = ItkUcharImgType::New();
auto duplicator = itk::ImageDuplicator<ItkUcharImgType>::New();
duplicator->SetInputImage(m_Parameters.m_SignalGen.m_MaskImage);
duplicator->Update();
m_TransformedMaskImage = duplicator->GetOutput();
// second upsampling needed for motion artifacts
ImageRegion<3> upsampledImageRegion = m_WorkingImageRegion;
VectorType upsampledSpacing = m_WorkingSpacing;
upsampledSpacing[0] /= 4;
upsampledSpacing[1] /= 4;
upsampledSpacing[2] /= 4;
upsampledImageRegion.SetSize(0, m_WorkingImageRegion.GetSize()[0]*4);
upsampledImageRegion.SetSize(1, m_WorkingImageRegion.GetSize()[1]*4);
upsampledImageRegion.SetSize(2, m_WorkingImageRegion.GetSize()[2]*4);
itk::Point<double,3> upsampledOrigin = m_WorkingOrigin;
upsampledOrigin[0] -= m_WorkingSpacing[0]/2;
upsampledOrigin[0] += upsampledSpacing[0]/2;
upsampledOrigin[1] -= m_WorkingSpacing[1]/2;
upsampledOrigin[1] += upsampledSpacing[1]/2;
upsampledOrigin[2] -= m_WorkingSpacing[2]/2;
upsampledOrigin[2] += upsampledSpacing[2]/2;
m_UpsampledMaskImage = ItkUcharImgType::New();
auto upsampler = itk::ResampleImageFilter<ItkUcharImgType, ItkUcharImgType>::New();
upsampler->SetInput(m_Parameters.m_SignalGen.m_MaskImage);
upsampler->SetOutputParametersFromImage(m_Parameters.m_SignalGen.m_MaskImage);
upsampler->SetSize(upsampledImageRegion.GetSize());
upsampler->SetOutputSpacing(upsampledSpacing);
upsampler->SetOutputOrigin(upsampledOrigin);
auto nn_interpolator = itk::NearestNeighborInterpolateImageFunction<ItkUcharImgType, double>::New();
upsampler->SetInterpolator(nn_interpolator);
upsampler->Update();
m_UpsampledMaskImage = upsampler->GetOutput();
}
template< class PixelType >
void TractsToDWIImageFilter< PixelType >::InitializeFiberData()
{
m_mmRadius = m_Parameters.m_SignalGen.m_AxonRadius/1000;
auto caster = itk::CastImageFilter< itk::Image<unsigned char, 3>, itk::Image<double, 3> >::New();
caster->SetInput(m_TransformedMaskImage);
caster->Update();
vtkSmartPointer<vtkFloatArray> weights = m_FiberBundle->GetFiberWeights();
float mean_weight = 0;
for (int i=0; i<weights->GetSize(); i++)
mean_weight += weights->GetValue(i);
mean_weight /= weights->GetSize();
if (mean_weight>0.000001)
for (int i=0; i<weights->GetSize(); i++)
m_FiberBundle->SetFiberWeight(i, weights->GetValue(i)/mean_weight);
else
PrintToLog("\nWarning: streamlines have VERY low weights. Average weight: " + boost::lexical_cast<std::string>(mean_weight) + ". Possible source of calculation errors.", false, true, true);
auto density_calculator = itk::TractDensityImageFilter< itk::Image<double, 3> >::New();
density_calculator->SetFiberBundle(m_FiberBundle);
density_calculator->SetInputImage(caster->GetOutput());
density_calculator->SetBinaryOutput(false);
density_calculator->SetUseImageGeometry(true);
density_calculator->SetOutputAbsoluteValues(true);
density_calculator->Update();
double max_density = density_calculator->GetMaxDensity();
double voxel_volume = m_WorkingSpacing[0]*m_WorkingSpacing[1]*m_WorkingSpacing[2];
if (m_mmRadius>0)
{
std::stringstream stream;
stream << std::fixed << setprecision(2) << itk::Math::pi*m_mmRadius*m_mmRadius*max_density;
std::string s = stream.str();
PrintToLog("\nMax. fiber volume: " + s + "mm².", false, true, true);
{
double full_radius = 1000*std::sqrt(voxel_volume/(max_density*itk::Math::pi));
std::stringstream stream;
stream << std::fixed << setprecision(2) << full_radius;
std::string s = stream.str();
PrintToLog("\nA full fiber voxel corresponds to a fiber radius of ~" + s + "µm, given the current fiber configuration.", false, true, true);
}
}
else
{
m_mmRadius = std::sqrt(voxel_volume/(max_density*itk::Math::pi));
std::stringstream stream;
stream << std::fixed << setprecision(2) << m_mmRadius*1000;
std::string s = stream.str();
PrintToLog("\nSetting fiber radius to " + s + "µm to obtain full voxel.", false, true, true);
}
// a second fiber bundle is needed to store the transformed version of the m_FiberBundleWorkingCopy
m_FiberBundleTransformed = m_FiberBundle->GetDeepCopy();
}
template< class PixelType >
bool TractsToDWIImageFilter< PixelType >::PrepareLogFile()
{
if(m_Logfile.is_open())
m_Logfile.close();
std::string filePath;
std::string fileName;
// Get directory name:
if (m_Parameters.m_Misc.m_OutputPath.size() > 0)
{
filePath = m_Parameters.m_Misc.m_OutputPath;
if( *(--(filePath.cend())) != '/')
{
filePath.push_back('/');
}
}
else
return false;
// Get file name:
if( ! m_Parameters.m_Misc.m_ResultNode->GetName().empty() )
{
fileName = m_Parameters.m_Misc.m_ResultNode->GetName();
}
else
{
fileName = "";
}
if( ! m_Parameters.m_Misc.m_OutputPrefix.empty() )
{
fileName = m_Parameters.m_Misc.m_OutputPrefix + fileName;
}
try
{
m_Logfile.open( ( filePath + '/' + fileName + ".log" ).c_str() );
}
catch (const std::ios_base::failure &fail)
{
MITK_ERROR << "itkTractsToDWIImageFilter.cpp: Exception " << fail.what()
<< " while trying to open file" << filePath << '/' << fileName << ".log";
return false;
}
if ( m_Logfile.is_open() )
{
PrintToLog( "Logfile: " + filePath + '/' + fileName + ".log", false );
return true;
}
else
return false;
}
template< class PixelType >
void TractsToDWIImageFilter< PixelType >::GenerateData()
{
PrintToLog("\n**********************************************", false);
// prepare logfile
PrepareLogFile();
PrintToLog("Starting Fiberfox dMRI simulation");
m_TimeProbe.Start();
// check input data
if (m_FiberBundle.IsNull() && m_InputImage.IsNull())
itkExceptionMacro("Input fiber bundle and input diffusion-weighted image is nullptr!");
if (m_Parameters.m_FiberModelList.empty() && m_InputImage.IsNull())
itkExceptionMacro("No diffusion model for fiber compartments defined and input diffusion-weighted"
" image is nullptr! At least one fiber compartment is necessary to simulate diffusion.");
if (m_Parameters.m_NonFiberModelList.empty() && m_InputImage.IsNull())
itkExceptionMacro("No diffusion model for non-fiber compartments defined and input diffusion-weighted"
" image is nullptr! At least one non-fiber compartment is necessary to simulate diffusion.");
if (m_Parameters.m_SignalGen.m_DoDisablePartialVolume) // no partial volume? remove all but first fiber compartment
while (m_Parameters.m_FiberModelList.size()>1)
m_Parameters.m_FiberModelList.pop_back();
if (!m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition) // No upsampling of input image needed if no k-space simulation is performed
m_Parameters.m_SignalGen.m_DoAddGibbsRinging = false;
if (m_UseConstantRandSeed) // always generate the same random numbers?
m_RandGen->SetSeed(0);
else
m_RandGen->SetSeed();
InitializeData();
if ( m_FiberBundle.IsNotNull() ) // if no fiber bundle is found, we directly proceed to the k-space acquisition simulation
{
CheckVolumeFractionImages();
InitializeFiberData();
int numFiberCompartments = m_Parameters.m_FiberModelList.size();
int numNonFiberCompartments = m_Parameters.m_NonFiberModelList.size();
double maxVolume = 0;
unsigned long lastTick = 0;
int signalModelSeed = m_RandGen->GetIntegerVariate();
PrintToLog("\n", false, false);
PrintToLog("Generating " + boost::lexical_cast<std::string>(numFiberCompartments+numNonFiberCompartments)
+ "-compartment diffusion-weighted signal.");
std::vector< int > bVals = m_Parameters.m_SignalGen.GetBvalues();
PrintToLog("b-values: ", false, false, true);
for (auto v : bVals)
PrintToLog(boost::lexical_cast<std::string>(v) + " ", false, false, true);
PrintToLog("\nVolumes: " + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.GetNumVolumes()), false, true, true);
PrintToLog("\n", false, false, true);
PrintToLog("\n", false, false, true);
unsigned int image_size_x = m_WorkingImageRegion.GetSize(0);
unsigned int region_size_y = m_WorkingImageRegion.GetSize(1);
unsigned int num_gradients = m_Parameters.m_SignalGen.GetNumVolumes();
int numFibers = m_FiberBundle->GetNumFibers();
boost::progress_display disp(numFibers*num_gradients);
if (m_FiberBundle->GetMeanFiberLength()<5.0)
omp_set_num_threads(2);
PrintToLog("0% 10 20 30 40 50 60 70 80 90 100%", false, true, false);
PrintToLog("|----|----|----|----|----|----|----|----|----|----|\n*", false, false, false);
for (unsigned int g=0; g<num_gradients; ++g)
{
// move fibers
SimulateMotion(g);
// Set signal model random generator seeds to get same configuration in each voxel
for (std::size_t i=0; i<m_Parameters.m_FiberModelList.size(); i++)
m_Parameters.m_FiberModelList.at(i)->SetSeed(signalModelSeed);
for (std::size_t i=0; i<m_Parameters.m_NonFiberModelList.size(); i++)
m_Parameters.m_NonFiberModelList.at(i)->SetSeed(signalModelSeed);
// storing voxel-wise intra-axonal volume in mm³
auto intraAxonalVolumeImage = ItkDoubleImgType::New();
intraAxonalVolumeImage->SetSpacing( m_WorkingSpacing );
intraAxonalVolumeImage->SetOrigin( m_WorkingOrigin );
intraAxonalVolumeImage->SetDirection( m_Parameters.m_SignalGen.m_ImageDirection );
intraAxonalVolumeImage->SetLargestPossibleRegion( m_WorkingImageRegion );
intraAxonalVolumeImage->SetBufferedRegion( m_WorkingImageRegion );
intraAxonalVolumeImage->SetRequestedRegion( m_WorkingImageRegion );
intraAxonalVolumeImage->Allocate();
intraAxonalVolumeImage->FillBuffer(0);
maxVolume = 0;
double* intraAxBuffer = intraAxonalVolumeImage->GetBufferPointer();
if (this->GetAbortGenerateData())
continue;
vtkPolyData* fiberPolyData = m_FiberBundleTransformed->GetFiberPolyData();
// generate fiber signal (if there are any fiber models present)
if (!m_Parameters.m_FiberModelList.empty())
{
std::vector< double* > buffers;
for (unsigned int i=0; i<m_CompartmentImages.size(); ++i)
buffers.push_back(m_CompartmentImages.at(i)->GetBufferPointer());
#pragma omp parallel for
for( int i=0; i<numFibers; ++i )
{
if (this->GetAbortGenerateData())
continue;
float fiberWeight = m_FiberBundleTransformed->GetFiberWeight(i);
if (fiberWeight == 0)
continue;
int numPoints = -1;
std::vector< itk::Vector<double, 3> > points_copy;
#pragma omp critical
{
vtkCell* cell = fiberPolyData->GetCell(i);
numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
for (int j=0; j<numPoints; j++)
points_copy.push_back(GetItkVector(points->GetPoint(j)));
}
if (numPoints<2)
continue;
double seg_volume = fiberWeight*itk::Math::pi*m_mmRadius*m_mmRadius;
for( int j=0; j<numPoints - 1; ++j)
{
if (this->GetAbortGenerateData())
{
j=numPoints;
continue;
}
itk::Vector<double> v = points_copy.at(j);
itk::Vector<double, 3> dir = points_copy.at(j+1)-v;
if ( dir.GetSquaredNorm()<0.0001 || dir[0]!=dir[0] || dir[1]!=dir[1] || dir[2]!=dir[2] )
continue;
dir.Normalize();
itk::Point<float, 3> startVertex = points_copy.at(j);
itk::Index<3> startIndex;
itk::ContinuousIndex<float, 3> startIndexCont;
m_TransformedMaskImage->TransformPhysicalPointToIndex(startVertex, startIndex);
m_TransformedMaskImage->TransformPhysicalPointToContinuousIndex(startVertex, startIndexCont);
itk::Point<float, 3> endVertex = points_copy.at(j+1);
itk::Index<3> endIndex;
itk::ContinuousIndex<float, 3> endIndexCont;
m_TransformedMaskImage->TransformPhysicalPointToIndex(endVertex, endIndex);
m_TransformedMaskImage->TransformPhysicalPointToContinuousIndex(endVertex, endIndexCont);
std::vector< std::pair< itk::Index<3>, double > > segments = mitk::imv::IntersectImage(m_WorkingSpacing, startIndex, endIndex, startIndexCont, endIndexCont);
// generate signal for each fiber compartment
for (int k=0; k<numFiberCompartments; ++k)
{
double signal_add = m_Parameters.m_FiberModelList[k]->SimulateMeasurement(g, dir)*seg_volume;
for (std::pair< itk::Index<3>, double > seg : segments)
{
if (!m_TransformedMaskImage->GetLargestPossibleRegion().IsInside(seg.first) || m_TransformedMaskImage->GetPixel(seg.first)<=0)
continue;
double seg_signal = seg.second*signal_add;
unsigned int linear_index = g + num_gradients*seg.first[0] + num_gradients*image_size_x*seg.first[1] + num_gradients*image_size_x*region_size_y*seg.first[2];
// update dMRI volume
#pragma omp atomic
buffers[k][linear_index] += seg_signal;
// update fiber volume image
if (k==0)
{
linear_index = seg.first[0] + image_size_x*seg.first[1] + image_size_x*region_size_y*seg.first[2];
#pragma omp atomic
intraAxBuffer[linear_index] += seg.second*seg_volume;
double vol = intraAxBuffer[linear_index];
if (vol>maxVolume) { maxVolume = vol; }
}
}
}
}
#pragma omp critical
{
// progress report
++disp;
unsigned long newTick = 50*disp.count()/disp.expected_count();
for (unsigned int tick = 0; tick<(newTick-lastTick); ++tick)
PrintToLog("*", false, false, false);
lastTick = newTick;
}
}
}
// axon radius not manually defined --> set fullest voxel (maxVolume) to full fiber voxel
double density_correctiony_global = 1.0;
if (m_Parameters.m_SignalGen.m_AxonRadius<0.0001)
density_correctiony_global = m_VoxelVolume/maxVolume;
// generate non-fiber signal
ImageRegionIterator<ItkUcharImgType> it3(m_TransformedMaskImage, m_TransformedMaskImage->GetLargestPossibleRegion());
while(!it3.IsAtEnd())
{
if (it3.Get()>0)
{
DoubleDwiType::IndexType index = it3.GetIndex();
double iAxVolume = intraAxonalVolumeImage->GetPixel(index);
// get non-transformed point (remove headmotion tranformation)
// this point lives in the volume fraction image space
itk::Point<float, 3> volume_fraction_point;
if ( m_Parameters.m_SignalGen.m_DoAddMotion )
volume_fraction_point = GetMovedPoint(index, false);
else
m_TransformedMaskImage->TransformIndexToPhysicalPoint(index, volume_fraction_point);
if (m_Parameters.m_SignalGen.m_DoDisablePartialVolume)
{
if (iAxVolume>0.0001) // scale fiber compartment to voxel
{
DoubleDwiType::PixelType pix = m_CompartmentImages.at(0)->GetPixel(index);
pix[g] *= m_VoxelVolume/iAxVolume;
m_CompartmentImages.at(0)->SetPixel(index, pix);
if (g==0)
m_VolumeFractions.at(0)->SetPixel(index, 1);
}
else
{
DoubleDwiType::PixelType pix = m_CompartmentImages.at(0)->GetPixel(index);
pix[g] = 0;
m_CompartmentImages.at(0)->SetPixel(index, pix);
SimulateExtraAxonalSignal(index, volume_fraction_point, 0, g);
}
}
else
{
// manually defined axon radius and voxel overflow --> rescale to voxel volume
if ( m_Parameters.m_SignalGen.m_AxonRadius>=0.0001 && iAxVolume>m_VoxelVolume )
{
for (int i=0; i<numFiberCompartments; ++i)
{
DoubleDwiType::PixelType pix = m_CompartmentImages.at(i)->GetPixel(index);
pix[g] *= m_VoxelVolume/iAxVolume;
m_CompartmentImages.at(i)->SetPixel(index, pix);
}
iAxVolume = m_VoxelVolume;
}
// if volume fraction image is set use it, otherwise use global scaling factor
double density_correction_voxel = density_correctiony_global;
if ( m_Parameters.m_FiberModelList[0]->GetVolumeFractionImage()!=nullptr && iAxVolume>0.0001 )
{
m_DoubleInterpolator->SetInputImage(m_Parameters.m_FiberModelList[0]->GetVolumeFractionImage());
double volume_fraction = mitk::imv::GetImageValue<double>(volume_fraction_point, true, m_DoubleInterpolator);
if (volume_fraction<0)
mitkThrow() << "Volume fraction image (index 1) contains negative values (intra-axonal compartment)!";
density_correction_voxel = m_VoxelVolume*volume_fraction/iAxVolume; // remove iAxVolume sclaing and scale to volume_fraction
}
else if (m_Parameters.m_FiberModelList[0]->GetVolumeFractionImage()!=nullptr)
density_correction_voxel = 0.0;
// adjust intra-axonal compartment volume by density correction factor
DoubleDwiType::PixelType pix = m_CompartmentImages.at(0)->GetPixel(index);
pix[g] *= density_correction_voxel;
m_CompartmentImages.at(0)->SetPixel(index, pix);
// normalize remaining fiber volume fractions (they are rescaled in SimulateExtraAxonalSignal)
if (iAxVolume>0.0001)
{
for (int i=1; i<numFiberCompartments; i++)
{
DoubleDwiType::PixelType pix = m_CompartmentImages.at(i)->GetPixel(index);
pix[g] /= iAxVolume;
m_CompartmentImages.at(i)->SetPixel(index, pix);
}
}
else
{
for (int i=1; i<numFiberCompartments; i++)
{
DoubleDwiType::PixelType pix = m_CompartmentImages.at(i)->GetPixel(index);
pix[g] = 0;
m_CompartmentImages.at(i)->SetPixel(index, pix);
}
}
iAxVolume = density_correction_voxel*iAxVolume; // new intra-axonal volume = old intra-axonal volume * correction factor
// simulate other compartments
SimulateExtraAxonalSignal(index, volume_fraction_point, iAxVolume, g);
}
}
++it3;
}
}
PrintToLog("\n", false);
}
if (this->GetAbortGenerateData())
{
PrintToLog("\n", false, false);
PrintToLog("Simulation aborted");
return;
}
DoubleDwiType::Pointer doubleOutImage;
double signalScale = m_Parameters.m_SignalGen.m_SignalScale;
if ( m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition ) // do k-space stuff
{
PrintToLog("\n", false, false);
PrintToLog("Simulating k-space acquisition using "
+boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_NumberOfCoils)
+" coil(s)");
switch (m_Parameters.m_SignalGen.m_AcquisitionType)
{
case SignalGenerationParameters::SingleShotEpi:
{
PrintToLog("Acquisition type: single shot EPI", false);
break;
}
case SignalGenerationParameters::ConventionalSpinEcho:
{
PrintToLog("Acquisition type: conventional spin echo (one RF pulse per line) with cartesian k-space trajectory", false);
break;
}
case SignalGenerationParameters::FastSpinEcho:
{
PrintToLog("Acquisition type: fast spin echo (one RF pulse per ETL lines) with cartesian k-space trajectory (ETL: " + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_EchoTrainLength) + ")", false);
break;
}
default:
{
PrintToLog("Acquisition type: single shot EPI", false);
break;
}
}
if(m_Parameters.m_SignalGen.m_tInv>0)
PrintToLog("Using inversion pulse with TI " + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_tInv) + "ms", false);
if (m_Parameters.m_SignalGen.m_DoSimulateRelaxation)
PrintToLog("Simulating signal relaxation", false);
if (m_Parameters.m_SignalGen.m_NoiseVariance>0 && m_Parameters.m_Misc.m_DoAddNoise)
PrintToLog("Simulating complex Gaussian noise: " + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_NoiseVariance), false);
if (m_Parameters.m_SignalGen.m_FrequencyMap.IsNotNull() && m_Parameters.m_Misc.m_DoAddDistortions)
PrintToLog("Simulating distortions", false);
if (m_Parameters.m_SignalGen.m_DoAddGibbsRinging)
{
if (m_Parameters.m_SignalGen.m_ZeroRinging > 0)
PrintToLog("Simulating ringing artifacts by zeroing " + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_ZeroRinging) + "% of k-space frequencies", false);
else
PrintToLog("Simulating ringing artifacts by cropping high resolution inputs during k-space simulation", false);
}
if (m_Parameters.m_Misc.m_DoAddEddyCurrents && m_Parameters.m_SignalGen.m_EddyStrength>0)
PrintToLog("Simulating eddy currents: " + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_EddyStrength), false);
if (m_Parameters.m_Misc.m_DoAddSpikes && m_Parameters.m_SignalGen.m_Spikes>0)
PrintToLog("Simulating spikes: " + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_Spikes), false);
if (m_Parameters.m_Misc.m_DoAddAliasing && m_Parameters.m_SignalGen.m_CroppingFactor<1.0)
PrintToLog("Simulating aliasing: " + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_CroppingFactor), false);
if (m_Parameters.m_Misc.m_DoAddGhosts && m_Parameters.m_SignalGen.m_KspaceLineOffset>0)
PrintToLog("Simulating ghosts: " + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_KspaceLineOffset), false);
doubleOutImage = SimulateKspaceAcquisition(m_CompartmentImages);
signalScale = 1; // already scaled in SimulateKspaceAcquisition()
}
else // don't do k-space stuff, just sum compartments
{
PrintToLog("Summing compartments");
doubleOutImage = m_CompartmentImages.at(0);
for (unsigned int i=1; i<m_CompartmentImages.size(); i++)
{
auto adder = itk::AddImageFilter< DoubleDwiType, DoubleDwiType, DoubleDwiType>::New();
adder->SetInput1(doubleOutImage);
adder->SetInput2(m_CompartmentImages.at(i));
adder->Update();
doubleOutImage = adder->GetOutput();
}
}
if (this->GetAbortGenerateData())
{
PrintToLog("\n", false, false);
PrintToLog("Simulation aborted");
return;
}
PrintToLog("Finalizing image");
if (m_Parameters.m_SignalGen.m_DoAddDrift && m_Parameters.m_SignalGen.m_Drift>0.0)
PrintToLog("Adding signal drift: " + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_Drift), false);
if (signalScale>1)
PrintToLog("Scaling signal", false);
if (m_Parameters.m_NoiseModel)
PrintToLog("Adding noise: " + boost::lexical_cast<std::string>(m_Parameters.m_SignalGen.m_NoiseVariance), false);
ImageRegionIterator<OutputImageType> it4 (m_OutputImage, m_OutputImage->GetLargestPossibleRegion());
DoubleDwiType::PixelType signal; signal.SetSize(m_Parameters.m_SignalGen.GetNumVolumes());
boost::progress_display disp2(m_OutputImage->GetLargestPossibleRegion().GetNumberOfPixels());
PrintToLog("0% 10 20 30 40 50 60 70 80 90 100%", false, true, false);
PrintToLog("|----|----|----|----|----|----|----|----|----|----|\n*", false, false, false);
int lastTick = 0;
while(!it4.IsAtEnd())
{
if (this->GetAbortGenerateData())
{
PrintToLog("\n", false, false);
PrintToLog("Simulation aborted");
return;
}
++disp2;
unsigned long newTick = 50*disp2.count()/disp2.expected_count();
for (unsigned long tick = 0; tick<(newTick-lastTick); tick++)
PrintToLog("*", false, false, false);
lastTick = newTick;
typename OutputImageType::IndexType index = it4.GetIndex();
signal = doubleOutImage->GetPixel(index)*signalScale;
for (unsigned int i=0; i<signal.Size(); i++)
{
if (m_Parameters.m_SignalGen.m_DoAddDrift)
{
double df = -m_Parameters.m_SignalGen.m_Drift/(signal.Size()*signal.Size());
signal[i] += signal[i]*df*i*i;
}
}
if (m_Parameters.m_NoiseModel)
m_Parameters.m_NoiseModel->AddNoise(signal);
for (unsigned int i=0; i<signal.Size(); i++)
{
if (signal[i]>0)
signal[i] = floor(signal[i]+0.5);
else
signal[i] = ceil(signal[i]-0.5);
}
it4.Set(signal);
++it4;
}
this->SetNthOutput(0, m_OutputImage);
PrintToLog("\n", false);
PrintToLog("Finished simulation");
m_TimeProbe.Stop();
if (m_Parameters.m_SignalGen.m_DoAddMotion)
{
PrintToLog("\nHead motion log:", false);
PrintToLog(m_MotionLog, false, false);
}
if (m_Parameters.m_Misc.m_DoAddSpikes && m_Parameters.m_SignalGen.m_Spikes>0)
{
PrintToLog("\nSpike log:", false);
PrintToLog(m_SpikeLog, false, false);
}
if (m_Logfile.is_open())
m_Logfile.close();
}
template< class PixelType >
void TractsToDWIImageFilter< PixelType >::PrintToLog(std::string m, bool addTime, bool linebreak, bool stdOut)
{
// timestamp
if (addTime)
{
if ( m_Logfile.is_open() )
m_Logfile << this->GetTime() << " > ";
m_StatusText += this->GetTime() + " > ";
if (stdOut)
std::cout << this->GetTime() << " > ";
}
// message
if (m_Logfile.is_open())
m_Logfile << m;
m_StatusText += m;
if (stdOut)
std::cout << m;
// new line
if (linebreak)
{
if (m_Logfile.is_open())
m_Logfile << "\n";
m_StatusText += "\n";
if (stdOut)
std::cout << "\n";
}
if ( m_Logfile.is_open() )
m_Logfile.flush();
}
template< class PixelType >
void TractsToDWIImageFilter< PixelType >::SimulateMotion(int g)
{
if ( m_Parameters.m_SignalGen.m_DoAddMotion &&
m_Parameters.m_SignalGen.m_DoRandomizeMotion &&
g>0 &&
m_Parameters.m_SignalGen.m_MotionVolumes[g-1])
{
// The last volume was randomly moved, so we have to reset to fiberbundle and the mask.
// Without motion or with linear motion, we keep the last position --> no reset.
m_FiberBundleTransformed = m_FiberBundle->GetDeepCopy();
if (m_MaskImageSet)
{
auto duplicator = itk::ImageDuplicator<ItkUcharImgType>::New();
duplicator->SetInputImage(m_Parameters.m_SignalGen.m_MaskImage);
duplicator->Update();
m_TransformedMaskImage = duplicator->GetOutput();
}
}
VectorType rotation;
VectorType translation;
// is motion artifact enabled?
// is the current volume g affected by motion?
if ( m_Parameters.m_SignalGen.m_DoAddMotion
&& m_Parameters.m_SignalGen.m_MotionVolumes[g]
&& g<static_cast<int>(m_Parameters.m_SignalGen.GetNumVolumes()) )
{
// adjust motion transforms
if ( m_Parameters.m_SignalGen.m_DoRandomizeMotion )
{
// randomly
rotation[0] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Rotation[0]*2)
-m_Parameters.m_SignalGen.m_Rotation[0];
rotation[1] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Rotation[1]*2)
-m_Parameters.m_SignalGen.m_Rotation[1];
rotation[2] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Rotation[2]*2)
-m_Parameters.m_SignalGen.m_Rotation[2];
translation[0] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Translation[0]*2)
-m_Parameters.m_SignalGen.m_Translation[0];
translation[1] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Translation[1]*2)
-m_Parameters.m_SignalGen.m_Translation[1];
translation[2] = m_RandGen->GetVariateWithClosedRange(m_Parameters.m_SignalGen.m_Translation[2]*2)
-m_Parameters.m_SignalGen.m_Translation[2];
m_FiberBundleTransformed->TransformFibers(rotation[0], rotation[1], rotation[2], translation[0], translation[1], translation[2]);
}
else
{
// linearly
rotation = m_Parameters.m_SignalGen.m_Rotation / m_NumMotionVolumes;
translation = m_Parameters.m_SignalGen.m_Translation / m_NumMotionVolumes;
m_MotionCounter++;
m_FiberBundleTransformed->TransformFibers(rotation[0], rotation[1], rotation[2], translation[0], translation[1], translation[2]);
rotation *= m_MotionCounter;
translation *= m_MotionCounter;
}
MatrixType rotationMatrix = mitk::imv::GetRotationMatrixItk(rotation[0], rotation[1], rotation[2]);
MatrixType rotationMatrixInv = mitk::imv::GetRotationMatrixItk(-rotation[0], -rotation[1], -rotation[2]);
m_Rotations.push_back(rotationMatrix);
m_RotationsInv.push_back(rotationMatrixInv);
m_Translations.push_back(translation);
// move mask image accoring to new transform
if (m_MaskImageSet)
{
ImageRegionIterator<ItkUcharImgType> maskIt(m_UpsampledMaskImage, m_UpsampledMaskImage->GetLargestPossibleRegion());
m_TransformedMaskImage->FillBuffer(0);
while(!maskIt.IsAtEnd())
{
if (maskIt.Get()<=0)
{
++maskIt;
continue;
}
DoubleDwiType::IndexType index = maskIt.GetIndex();
m_TransformedMaskImage->TransformPhysicalPointToIndex(GetMovedPoint(index, true), index);
if (m_TransformedMaskImage->GetLargestPossibleRegion().IsInside(index))
m_TransformedMaskImage->SetPixel(index, 100);
++maskIt;
}
}
}
else
{
if (m_Parameters.m_SignalGen.m_DoAddMotion && !m_Parameters.m_SignalGen.m_DoRandomizeMotion && g>0)
{
rotation = m_Parameters.m_SignalGen.m_Rotation / m_NumMotionVolumes;
rotation *= m_MotionCounter;
m_Rotations.push_back(m_Rotations.back());
m_RotationsInv.push_back(m_RotationsInv.back());
m_Translations.push_back(m_Translations.back());
}
else
{
rotation.Fill(0.0);
VectorType translation; translation.Fill(0.0);
MatrixType rotation_matrix; rotation_matrix.SetIdentity();
m_Rotations.push_back(rotation_matrix);
m_RotationsInv.push_back(rotation_matrix);
m_Translations.push_back(translation);
}
}
if (m_Parameters.m_SignalGen.m_DoAddMotion)
{
m_MotionLog += boost::lexical_cast<std::string>(g) + " rotation: " + boost::lexical_cast<std::string>(rotation[0])
+ "," + boost::lexical_cast<std::string>(rotation[1])
+ "," + boost::lexical_cast<std::string>(rotation[2]) + ";";
m_MotionLog += " translation: " + boost::lexical_cast<std::string>(m_Translations.back()[0])
+ "," + boost::lexical_cast<std::string>(m_Translations.back()[1])
+ "," + boost::lexical_cast<std::string>(m_Translations.back()[2]) + "\n";
}
}
template< class PixelType >
itk::Point<float, 3> TractsToDWIImageFilter< PixelType >::GetMovedPoint(itk::Index<3>& index, bool forward)
{
itk::Point<float, 3> transformed_point;
float tx = m_Translations.back()[0];
float ty = m_Translations.back()[1];
float tz = m_Translations.back()[2];
if (forward)
{
m_UpsampledMaskImage->TransformIndexToPhysicalPoint(index, transformed_point);
m_FiberBundle->TransformPoint<>(transformed_point, m_Rotations.back(), tx, ty, tz);
}
else
{
tx *= -1; ty *= -1; tz *= -1;
m_TransformedMaskImage->TransformIndexToPhysicalPoint(index, transformed_point);
m_FiberBundle->TransformPoint<>(transformed_point, m_RotationsInv.back(), tx, ty, tz);
}
return transformed_point;
}
template< class PixelType >
void TractsToDWIImageFilter< PixelType >::
SimulateExtraAxonalSignal(ItkUcharImgType::IndexType& index, itk::Point<float, 3>& volume_fraction_point, double intraAxonalVolume, int g)
{
int numFiberCompartments = m_Parameters.m_FiberModelList.size();
int numNonFiberCompartments = m_Parameters.m_NonFiberModelList.size();
if (m_Parameters.m_SignalGen.m_DoDisablePartialVolume)
{
// simulate signal for largest non-fiber compartment
int max_compartment_index = 0;
double max_fraction = 0;
if (numNonFiberCompartments>1)
{
for (int i=0; i<numNonFiberCompartments; ++i)
{
m_DoubleInterpolator->SetInputImage(m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage());
double compartment_fraction = mitk::imv::GetImageValue<double>(volume_fraction_point, true, m_DoubleInterpolator);
if (compartment_fraction<0)
mitkThrow() << "Volume fraction image (index " << i << ") contains values less than zero!";
if (compartment_fraction>max_fraction)
{
max_fraction = compartment_fraction;
max_compartment_index = i;
}
}
}
DoubleDwiType::Pointer doubleDwi = m_CompartmentImages.at(max_compartment_index+numFiberCompartments);
DoubleDwiType::PixelType pix = doubleDwi->GetPixel(index);
pix[g] += m_Parameters.m_NonFiberModelList[max_compartment_index]->SimulateMeasurement(g, m_NullDir)*m_VoxelVolume;
doubleDwi->SetPixel(index, pix);
if (g==0)
m_VolumeFractions.at(max_compartment_index+numFiberCompartments)->SetPixel(index, 1);
}
else
{
std::vector< double > fractions;
if (g==0)
m_VolumeFractions.at(0)->SetPixel(index, intraAxonalVolume/m_VoxelVolume);
double extraAxonalVolume = m_VoxelVolume-intraAxonalVolume; // non-fiber volume
if (extraAxonalVolume<0)
{
if (extraAxonalVolume<-0.001)
MITK_ERROR << "Corrupted intra-axonal signal voxel detected. Fiber volume larger voxel volume! " << m_VoxelVolume << "<" << intraAxonalVolume;
extraAxonalVolume = 0;
}
double interAxonalVolume = 0;
if (numFiberCompartments>1)
interAxonalVolume = extraAxonalVolume * intraAxonalVolume/m_VoxelVolume; // inter-axonal fraction of non fiber compartment
double nonFiberVolume = extraAxonalVolume - interAxonalVolume; // rest of compartment
if (nonFiberVolume<0)
{
if (nonFiberVolume<-0.001)
MITK_ERROR << "Corrupted signal voxel detected. Fiber volume larger voxel volume!";
nonFiberVolume = 0;
interAxonalVolume = extraAxonalVolume;
}
double compartmentSum = intraAxonalVolume;
fractions.push_back(intraAxonalVolume/m_VoxelVolume);
// rescale extra-axonal fiber signal
for (int i=1; i<numFiberCompartments; ++i)
{
if (m_Parameters.m_FiberModelList[i]->GetVolumeFractionImage()!=nullptr)
{
m_DoubleInterpolator->SetInputImage(m_Parameters.m_FiberModelList[i]->GetVolumeFractionImage());
interAxonalVolume = mitk::imv::GetImageValue<double>(volume_fraction_point, true, m_DoubleInterpolator)*m_VoxelVolume;
if (interAxonalVolume<0)
mitkThrow() << "Volume fraction image (index " << i+1 << ") contains negative values!";
}
DoubleDwiType::PixelType pix = m_CompartmentImages.at(i)->GetPixel(index);
pix[g] *= interAxonalVolume;
m_CompartmentImages.at(i)->SetPixel(index, pix);
compartmentSum += interAxonalVolume;
fractions.push_back(interAxonalVolume/m_VoxelVolume);
if (g==0)
m_VolumeFractions.at(i)->SetPixel(index, interAxonalVolume/m_VoxelVolume);
}
for (int i=0; i<numNonFiberCompartments; ++i)
{
double volume = nonFiberVolume;
if (m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()!=nullptr)
{
m_DoubleInterpolator->SetInputImage(m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage());
volume = mitk::imv::GetImageValue<double>(volume_fraction_point, true, m_DoubleInterpolator)*m_VoxelVolume;
if (volume<0)
mitkThrow() << "Volume fraction image (index " << numFiberCompartments+i+1 << ") contains negative values (non-fiber compartment)!";
if (m_UseRelativeNonFiberVolumeFractions)
volume *= nonFiberVolume/m_VoxelVolume;
}
DoubleDwiType::PixelType pix = m_CompartmentImages.at(i+numFiberCompartments)->GetPixel(index);
pix[g] += m_Parameters.m_NonFiberModelList[i]->SimulateMeasurement(g, m_NullDir)*volume;
m_CompartmentImages.at(i+numFiberCompartments)->SetPixel(index, pix);
compartmentSum += volume;
fractions.push_back(volume/m_VoxelVolume);
if (g==0)
m_VolumeFractions.at(i+numFiberCompartments)->SetPixel(index, volume/m_VoxelVolume);
}
if (compartmentSum/m_VoxelVolume>1.05)
{
MITK_ERROR << "Compartments do not sum to 1 in voxel " << index << " (" << compartmentSum/m_VoxelVolume << ")";
for (auto val : fractions)
MITK_ERROR << val;
}
}
}
template< class PixelType >
itk::Vector<double, 3> TractsToDWIImageFilter< PixelType >::GetItkVector(double point[3])
{
itk::Vector<double, 3> itkVector;
itkVector[0] = point[0];
itkVector[1] = point[1];
itkVector[2] = point[2];
return itkVector;
}
template< class PixelType >
vnl_vector_fixed<double, 3> TractsToDWIImageFilter< PixelType >::GetVnlVector(double point[3])
{
vnl_vector_fixed<double, 3> vnlVector;
vnlVector[0] = point[0];
vnlVector[1] = point[1];
vnlVector[2] = point[2];
return vnlVector;
}
template< class PixelType >
vnl_vector_fixed<double, 3> TractsToDWIImageFilter< PixelType >::GetVnlVector(Vector<float,3>& vector)
{
vnl_vector_fixed<double, 3> vnlVector;
vnlVector[0] = vector[0];
vnlVector[1] = vector[1];
vnlVector[2] = vector[2];
return vnlVector;
}
template< class PixelType >
double TractsToDWIImageFilter< PixelType >::RoundToNearest(double num) {
return (num > 0.0) ? floor(num + 0.5) : ceil(num - 0.5);
}
template< class PixelType >
std::string TractsToDWIImageFilter< PixelType >::GetTime()
{
m_TimeProbe.Stop();
unsigned long total = RoundToNearest(m_TimeProbe.GetTotal());
unsigned long hours = total/3600;
unsigned long minutes = (total%3600)/60;
unsigned long seconds = total%60;
std::string out = "";
out.append(boost::lexical_cast<std::string>(hours));
out.append(":");
out.append(boost::lexical_cast<std::string>(minutes));
out.append(":");
out.append(boost::lexical_cast<std::string>(seconds));
m_TimeProbe.Start();
return out;
}
}
diff --git a/Modules/MriSimulation/Algorithms/itkTractsToDWIImageFilter.h b/Modules/MriSimulation/Algorithms/itkTractsToDWIImageFilter.h
index 0434762..5607ba4 100644
--- a/Modules/MriSimulation/Algorithms/itkTractsToDWIImageFilter.h
+++ b/Modules/MriSimulation/Algorithms/itkTractsToDWIImageFilter.h
@@ -1,177 +1,177 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 __itkTractsToDWIImageFilter_h__
#define __itkTractsToDWIImageFilter_h__
#include <mitkFiberBundle.h>
#include <itkVnlForwardFFTImageFilter.h>
#include <itkVectorImage.h>
#include <cmath>
#include <mitkFiberfoxParameters.h>
#include <itkTimeProbe.h>
#include <mitkRawShModel.h>
#include <itkAnalyticalDiffusionQballReconstructionImageFilter.h>
#include <mitkPointSet.h>
#include <itkLinearInterpolateImageFunction.h>
namespace itk
{
/**
* \brief Generates artificial diffusion weighted image volume from the input fiberbundle using a generic multicompartment model.
* See "Fiberfox: Facilitating the creation of realistic white matter software phantoms" (DOI: 10.1002/mrm.25045) for details.
*/
template< class PixelType >
class TractsToDWIImageFilter : public ImageSource< itk::VectorImage< PixelType, 3 > >
{
public:
typedef TractsToDWIImageFilter Self;
typedef ImageSource< itk::VectorImage< PixelType, 3 > > Superclass;
typedef SmartPointer< Self > Pointer;
typedef SmartPointer< const Self > ConstPointer;
typedef typename Superclass::OutputImageType OutputImageType;
typedef itk::Image<double, 4> ItkDoubleImgType4D;
typedef itk::Image<double, 3> ItkDoubleImgType;
typedef itk::Image<float, 3> ItkFloatImgType;
typedef itk::Image<unsigned char, 3> ItkUcharImgType;
typedef mitk::FiberBundle::Pointer FiberBundleType;
typedef itk::VectorImage< double, 3 > DoubleDwiType;
typedef itk::Matrix<float, 3, 3> MatrixType;
typedef itk::Image< float, 2 > Float2DImageType;
typedef itk::Image< vcl_complex< float >, 2 > Complex2DImageType;
typedef itk::Vector< float, 3> VectorType;
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
itkTypeMacro( TractsToDWIImageFilter, ImageSource )
/** Input */
itkSetMacro( FiberBundle, FiberBundleType ) ///< Input fiber bundle
itkSetMacro( InputImage, typename OutputImageType::Pointer ) ///< Input diffusion-weighted image. If no fiber bundle is set, then the acquisition is simulated for this image without a new diffusion simulation.
itkSetMacro( UseConstantRandSeed, bool ) ///< Seed for random generator.
void SetParameters( FiberfoxParameters param ) ///< Simulation parameters.
{ m_Parameters = param; }
/** Output */
FiberfoxParameters GetParameters(){ return m_Parameters; }
std::vector< ItkDoubleImgType::Pointer > GetVolumeFractions() ///< one double image for each compartment containing the corresponding volume fraction per voxel
{ return m_VolumeFractions; }
itkGetMacro( StatusText, std::string )
itkGetMacro( PhaseImage, DoubleDwiType::Pointer )
itkGetMacro( KspaceImage, DoubleDwiType::Pointer )
itkGetMacro( CoilPointset, mitk::PointSet::Pointer )
itkGetMacro( TickImage, typename Float2DImageType::Pointer ) ///< k-space readout ordering encoded in the voxels
itkGetMacro( RfImage, typename Float2DImageType::Pointer ) ///< time passed since last RF pulse encoded per voxel
void GenerateData() override;
std::vector<DoubleDwiType::Pointer> GetOutputImagesReal() const
{
return m_OutputImagesReal;
}
std::vector<DoubleDwiType::Pointer> GetOutputImagesImag() const
{
return m_OutputImagesImag;
}
protected:
TractsToDWIImageFilter();
~TractsToDWIImageFilter() override;
itk::Vector<double, 3> GetItkVector(double point[3]);
vnl_vector_fixed<double, 3> GetVnlVector(double point[3]);
vnl_vector_fixed<double, 3> GetVnlVector(Vector< float, 3 >& vector);
double RoundToNearest(double num);
std::string GetTime();
bool PrepareLogFile(); /** Prepares the log file and returns true if successful or false if failed. */
void PrintToLog(std::string m, bool addTime=true, bool linebreak=true, bool stdOut=true);
/** Transform generated image compartment by compartment, channel by channel and slice by slice using DFT and add k-space artifacts/effects. */
DoubleDwiType::Pointer SimulateKspaceAcquisition(std::vector< DoubleDwiType::Pointer >& images);
/** Generate signal of non-fiber compartments. */
void SimulateExtraAxonalSignal(ItkUcharImgType::IndexType& index, itk::Point<float, 3>& volume_fraction_point, double intraAxonalVolume, int g);
/** Move fibers to simulate headmotion */
void SimulateMotion(int g=-1);
void CheckVolumeFractionImages();
ItkDoubleImgType::Pointer NormalizeInsideMask(ItkDoubleImgType::Pointer image);
void InitializeData();
void InitializeFiberData();
itk::Point<float, 3> GetMovedPoint(itk::Index<3>& index, bool forward);
// input
mitk::FiberfoxParameters m_Parameters;
FiberBundleType m_FiberBundle;
typename OutputImageType::Pointer m_InputImage;
// output
typename OutputImageType::Pointer m_OutputImage;
typename DoubleDwiType::Pointer m_PhaseImage;
typename DoubleDwiType::Pointer m_KspaceImage;
std::vector < typename DoubleDwiType::Pointer > m_OutputImagesReal;
std::vector < typename DoubleDwiType::Pointer > m_OutputImagesImag;
std::vector< ItkDoubleImgType::Pointer > m_VolumeFractions;
std::string m_StatusText;
// MISC
itk::TimeProbe m_TimeProbe;
bool m_UseConstantRandSeed;
bool m_MaskImageSet;
ofstream m_Logfile;
std::string m_MotionLog;
std::string m_SpikeLog;
// signal generation
FiberBundleType m_FiberBundleTransformed; ///< transformed bundle simulating headmotion
itk::Vector<double,3> m_WorkingSpacing;
itk::Point<double,3> m_WorkingOrigin;
ImageRegion<3> m_WorkingImageRegion;
double m_VoxelVolume;
std::vector< DoubleDwiType::Pointer > m_CompartmentImages;
ItkUcharImgType::Pointer m_TransformedMaskImage; ///< copy of mask image (changes for each motion step)
ItkUcharImgType::Pointer m_UpsampledMaskImage; ///< helper image for motion simulation
std::vector< MatrixType > m_RotationsInv;
std::vector< MatrixType > m_Rotations; ///<stores the individual rotation of each volume (needed for k-space simulation to obtain correct frequency map position)
std::vector< VectorType > m_Translations; ///<stores the individual translation of each volume (needed for k-space simulation to obtain correct frequency map position)
double m_mmRadius;
double m_SegmentVolume;
bool m_UseRelativeNonFiberVolumeFractions;
mitk::PointSet::Pointer m_CoilPointset;
int m_MotionCounter;
int m_NumMotionVolumes;
itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer m_RandGen;
itk::LinearInterpolateImageFunction< ItkDoubleImgType, float >::Pointer m_DoubleInterpolator;
itk::Vector<double,3> m_NullDir;
Float2DImageType::Pointer m_TickImage;
Float2DImageType::Pointer m_RfImage;
};
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkTractsToDWIImageFilter.cpp"
#endif
#endif
diff --git a/Modules/MriSimulation/Sequences/mitkAcquisitionType.h b/Modules/MriSimulation/Sequences/mitkAcquisitionType.h
index 1700b97..3315c10 100644
--- a/Modules/MriSimulation/Sequences/mitkAcquisitionType.h
+++ b/Modules/MriSimulation/Sequences/mitkAcquisitionType.h
@@ -1,67 +1,67 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_KspaceReadout_H
#define _MITK_KspaceReadout_H
#include <mitkFiberfoxParameters.h>
#include <itkSize.h>
namespace mitk {
/**
* \brief Abstract class for k-space acquisiton type (k-space trajectory and echo placement)
*
*/
class AcquisitionType
{
public:
AcquisitionType(FiberfoxParameters* parameters)
{
m_Parameters = parameters;
kxMax = static_cast<int>(m_Parameters->m_SignalGen.m_CroppedRegion.GetSize(0));
kyMax = static_cast<int>(m_Parameters->m_SignalGen.m_CroppedRegion.GetSize(1));
}
virtual ~AcquisitionType(){}
virtual float GetTimeFromMaxEcho(const int& tick) = 0; ///< Time from maximum echo intensity in milliseconds
virtual float GetTimeFromLastDiffusionGradient(const int& tick) = 0; ///< Time passed since readout started in milliseconds
virtual float GetTimeFromRf(const int& tick) = 0; ///< Time passed since RF pulse was applied in milliseconds
virtual itk::Index< 2 > GetActualKspaceIndex(const int& tick) = 0; ///< Transfer simple image iterator index to desired k-space index (depends on k-space readout scheme)
virtual void AdjustEchoTime() = 0; ///< Depending on the k-space readout scheme and acquisition parameters the minimum TE varies. This has to be checked and adjusted in this method.
itk::Index< 2 > GetSymmetricIndex(const itk::Index< 2 >& index)
{
itk::Index< 2 > sym;
sym[0] = (kxMax-kxMax%2-index[0])%kxMax;
sym[1] = (kyMax-kyMax%2-index[1])%kyMax;
return sym;
}
protected:
FiberfoxParameters* m_Parameters;
itk::Size< 2 > m_Size;
float dt; // time to read one k-space voxe
int kxMax;
int kyMax;
};
}
#endif
diff --git a/Modules/MriSimulation/Sequences/mitkConventionalSpinEcho.h b/Modules/MriSimulation/Sequences/mitkConventionalSpinEcho.h
index e3ca424..1071cf7 100644
--- a/Modules/MriSimulation/Sequences/mitkConventionalSpinEcho.h
+++ b/Modules/MriSimulation/Sequences/mitkConventionalSpinEcho.h
@@ -1,90 +1,90 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_ConventionalSpinEcho_H
#define _MITK_ConventionalSpinEcho_H
#include <mitkAcquisitionType.h>
namespace mitk {
/**
* \brief Conventional spin echo sequence. Cartesian readout. One echo and one excitation per k-space line.
*
*/
class ConventionalSpinEcho : public AcquisitionType
{
public:
float half_read_time;
ConventionalSpinEcho(FiberfoxParameters* parameters) : AcquisitionType(parameters)
{
dt = m_Parameters->m_SignalGen.m_tLine/kxMax; // time to read one k-space voxel
half_read_time = kxMax * dt/2;
}
~ConventionalSpinEcho() override
{}
// one echo per k-space line
float GetTimeFromMaxEcho(const int& tick) override
{
float t = dt*(tick % kxMax + 0.5f) - half_read_time;
return t;
}
float GetTimeFromLastDiffusionGradient(const int& tick) override
{
return (tick % kxMax)*dt;
}
// time from max-echo + TE
float GetTimeFromRf(const int& tick) override
{
return m_Parameters->m_SignalGen.m_tEcho + GetTimeFromMaxEcho(tick);
}
itk::Index< 2 > GetActualKspaceIndex(const int& tick) override
{
itk::Index< 2 > out_idx;
out_idx[0] = tick % kxMax;
out_idx[1] = tick / kxMax;
// reverse phase
if (!m_Parameters->m_SignalGen.m_ReversePhase)
out_idx[1] = kyMax-1-out_idx[1];
return out_idx;
}
void AdjustEchoTime() override
{
if ( m_Parameters->m_SignalGen.m_tEcho < m_Parameters->m_SignalGen.m_tLine )
{
m_Parameters->m_SignalGen.m_tEcho = m_Parameters->m_SignalGen.m_tLine;
MITK_WARN << "Echo time is too short! Time not sufficient to read slice. Automatically adjusted to " << m_Parameters->m_SignalGen.m_tEcho << " ms";
m_Parameters->m_Misc.m_AfterSimulationMessage += "Echo time was chosen too short! Time not sufficient to read slice. Internally adjusted to " + boost::lexical_cast<std::string>(m_Parameters->m_SignalGen.m_tEcho) + " ms\n";
}
}
protected:
};
}
#endif
diff --git a/Modules/MriSimulation/Sequences/mitkFastSpinEcho.h b/Modules/MriSimulation/Sequences/mitkFastSpinEcho.h
index ab166f1..6341300 100644
--- a/Modules/MriSimulation/Sequences/mitkFastSpinEcho.h
+++ b/Modules/MriSimulation/Sequences/mitkFastSpinEcho.h
@@ -1,96 +1,96 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_FastSpinEcho_H
#define _MITK_FastSpinEcho_H
#include <mitkAcquisitionType.h>
namespace mitk {
/**
* \brief Fast spin echo sequence. Cartesian readout.
* Echo spacing = TE
*/
class FastSpinEcho : public AcquisitionType
{
public:
unsigned int linesWithSameTime;
float half_read_time;
FastSpinEcho(FiberfoxParameters* parameters)
: AcquisitionType(parameters)
{
linesWithSameTime = static_cast<unsigned int>(std::ceil(static_cast<float>(kyMax)/m_Parameters->m_SignalGen.m_EchoTrainLength));
dt = m_Parameters->m_SignalGen.m_tLine/kxMax; // time to read one k-space voxel
half_read_time = kxMax * dt/2;
}
~FastSpinEcho() override
{}
// one echo per k-space line
float GetTimeFromMaxEcho(const int& tick) override
{
float t = dt*(tick % kxMax + 0.5f) - half_read_time;
return t;
}
float GetTimeFromLastDiffusionGradient(const int& tick) override
{
return (tick % kxMax)*dt;
}
// depends on ETL
float GetTimeFromRf(const int& tick) override
{
float echo_nr = std::ceil(static_cast<float>(tick/kxMax+1)/linesWithSameTime);
echo_nr -= std::ceil(static_cast<float>(m_Parameters->m_SignalGen.m_EchoTrainLength)/2);
return m_Parameters->m_SignalGen.m_tEcho + echo_nr*m_Parameters->m_SignalGen.m_tLine + GetTimeFromMaxEcho(tick);
}
itk::Index< 2 > GetActualKspaceIndex(const int& tick) override
{
itk::Index< 2 > out_idx;
out_idx[0] = tick % kxMax;
out_idx[1] = tick / kxMax;
// reverse phase
if (!m_Parameters->m_SignalGen.m_ReversePhase)
out_idx[1] = kyMax-1-out_idx[1];
return out_idx;
}
void AdjustEchoTime() override
{
if ( m_Parameters->m_SignalGen.m_tEcho < m_Parameters->m_SignalGen.m_EchoTrainLength*m_Parameters->m_SignalGen.m_tLine )
{
m_Parameters->m_SignalGen.m_tEcho = m_Parameters->m_SignalGen.m_EchoTrainLength*m_Parameters->m_SignalGen.m_tLine;
MITK_WARN << "Echo time is too short! Time not sufficient to read slice. Automatically adjusted to " << m_Parameters->m_SignalGen.m_tEcho << " ms";
m_Parameters->m_Misc.m_AfterSimulationMessage += "Echo time was chosen too short! Time not sufficient to read slice. Internally adjusted to " + boost::lexical_cast<std::string>(m_Parameters->m_SignalGen.m_tEcho) + " ms\n";
}
}
protected:
};
}
#endif
diff --git a/Modules/MriSimulation/Sequences/mitkSingleShotEpi.h b/Modules/MriSimulation/Sequences/mitkSingleShotEpi.h
index fd8f49c..908b395 100644
--- a/Modules/MriSimulation/Sequences/mitkSingleShotEpi.h
+++ b/Modules/MriSimulation/Sequences/mitkSingleShotEpi.h
@@ -1,102 +1,102 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_SingleShotEpi_H
#define _MITK_SingleShotEpi_H
#include <mitkAcquisitionType.h>
namespace mitk {
/**
* \brief Realizes EPI readout: one echo, maximum intensity in the k-space center, zig-zag trajectory
*
*/
class SingleShotEpi : public AcquisitionType
{
public:
/*
TE
| dt | dt | dt | ... |
Total read time: Nvox*dt = kxMax*kyMax*dt
*/
float half_read_time;
SingleShotEpi(FiberfoxParameters* parameters) : AcquisitionType(parameters)
{
dt = m_Parameters->m_SignalGen.m_tLine/kxMax; // time to read one k-space voxel
half_read_time = (kxMax*kyMax) * dt/2;
}
~SingleShotEpi() override
{}
// one echo per slice
float GetTimeFromMaxEcho(const int& tick) override
{
float t = dt*(static_cast<float>(tick) + 0.5f) - half_read_time;
return t;
}
// we simply assume that readout starts directly after the last diffusion gradient
float GetTimeFromLastDiffusionGradient(const int& tick) override
{
return tick*dt + dt/2;
}
float GetTimeFromRf(const int& tick) override
{
return m_Parameters->m_SignalGen.m_tEcho + GetTimeFromMaxEcho(tick);
}
itk::Index< 2 > GetActualKspaceIndex(const int& tick) override
{
itk::Index< 2 > out_idx;
out_idx[0] = tick % kxMax;
out_idx[1] = tick / kxMax;
if (!m_Parameters->m_SignalGen.m_ReversePhase)
{
out_idx[1] = kyMax-1-out_idx[1]; // in the not reversed case we start at the maximum k-space line
if (out_idx[1]%2 == 1) // reverse frequency encoding direction
out_idx[0] = kxMax-out_idx[0]-1;
}
else if (out_idx[1]%2) // reverse frequency encoding direction
out_idx[0] = kxMax-out_idx[0]-1;
return out_idx;
}
void AdjustEchoTime() override
{
if ( m_Parameters->m_SignalGen.m_tEcho < kyMax*m_Parameters->m_SignalGen.m_tLine )
{
m_Parameters->m_SignalGen.m_tEcho = kyMax*m_Parameters->m_SignalGen.m_tLine;
MITK_WARN << "Echo time is too short! Time not sufficient to read slice. Automatically adjusted to " << m_Parameters->m_SignalGen.m_tEcho << " ms";
m_Parameters->m_Misc.m_AfterSimulationMessage += "Echo time was chosen too short! Time not sufficient to read slice. Internally adjusted to " + boost::lexical_cast<std::string>(m_Parameters->m_SignalGen.m_tEcho) + " ms\n";
}
}
protected:
};
}
#endif
diff --git a/Modules/MriSimulation/SignalModels/mitkAstroStickModel.cpp b/Modules/MriSimulation/SignalModels/mitkAstroStickModel.cpp
index 9f13d2f..7db993a 100644
--- a/Modules/MriSimulation/SignalModels/mitkAstroStickModel.cpp
+++ b/Modules/MriSimulation/SignalModels/mitkAstroStickModel.cpp
@@ -1,122 +1,122 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <vnl/vnl_cross.h>
#include <vnl/vnl_quaternion.h>
#include <mitkAstroStickModel.h>
using namespace mitk;
template< class ScalarType >
AstroStickModel< ScalarType >::AstroStickModel()
: m_Diffusivity(0.001)
, m_NumSticks(42)
, m_RandomizeSticks(false)
{
this->m_RandGen = itk::Statistics::MersenneTwisterRandomVariateGenerator::New();
this->m_RandGen->SetSeed();
vnl_matrix_fixed<double,3,42>* sticks = itk::PointShell<42, vnl_matrix_fixed<double, 3, 42> >::DistributePointShell();
for (unsigned int i=0; i<m_NumSticks; i++)
{
GradientType stick;
stick[0] = sticks->get(0,i); stick[1] = sticks->get(1,i); stick[2] = sticks->get(2,i);
stick.Normalize();
m_Sticks.push_back(stick);
}
}
template< class ScalarType >
AstroStickModel< ScalarType >::~AstroStickModel()
{
}
template< class ScalarType >
ScalarType AstroStickModel< ScalarType >::SimulateMeasurement(unsigned int dir, GradientType& )
{
ScalarType signal = 0;
if (dir>=this->m_GradientList.size())
return signal;
ScalarType b = -this->m_BValue*m_Diffusivity;
if (m_RandomizeSticks) // random number of sticks
m_NumSticks = 30 + this->m_RandGen->GetIntegerVariate()%31;
GradientType g = this->m_GradientList[dir];
if (g.GetNorm()>0.0001) // is weighted direction
{
for (unsigned int j=0; j<m_NumSticks; j++)
{
ScalarType dot = 0;
if(m_RandomizeSticks)
dot = GetRandomDirection()*g;
else
dot = m_Sticks[j]*g;
signal += std::exp( (double)(b*dot*dot) ); // skip * bVal becaus bVal is already encoded in the dot product (norm of g encodes b-value relative to baseline b-value m_BValue)
}
signal /= m_NumSticks;
}
else // is baseline direction
signal = 1;
return signal;
}
template< class ScalarType >
typename AstroStickModel< ScalarType >::GradientType AstroStickModel< ScalarType >::GetRandomDirection()
{
GradientType vec;
vec[0] = this->m_RandGen->GetNormalVariate();
vec[1] = this->m_RandGen->GetNormalVariate();
vec[2] = this->m_RandGen->GetNormalVariate();
vec.Normalize();
return vec;
}
template< class ScalarType >
typename AstroStickModel< ScalarType >::PixelType AstroStickModel< ScalarType >::SimulateMeasurement(GradientType& )
{
PixelType signal;
signal.SetSize(this->m_GradientList.size());
ScalarType b = -this->m_BValue*m_Diffusivity;
if (m_RandomizeSticks)
m_NumSticks = 30 + this->m_RandGen->GetIntegerVariate()%31;
for( unsigned int i=0; i<this->m_GradientList.size(); i++)
{
GradientType g = this->m_GradientList[i];
if (g.GetNorm()>0.0001)
{
for (unsigned int j=0; j<m_NumSticks; j++)
{
ScalarType dot = 0;
if(m_RandomizeSticks)
dot = GetRandomDirection()*g;
else
dot = m_Sticks[j]*g;
signal[i] += std::exp( (double)(b*dot*dot) ); // skip * bVal becaus bVal is already encoded in the dot product (norm of g encodes b-value relative to baseline b-value m_BValue)
}
signal[i] /= m_NumSticks;
}
else
signal[i] = 1;
}
return signal;
}
diff --git a/Modules/MriSimulation/SignalModels/mitkAstroStickModel.h b/Modules/MriSimulation/SignalModels/mitkAstroStickModel.h
index e1c53db..064b96c 100644
--- a/Modules/MriSimulation/SignalModels/mitkAstroStickModel.h
+++ b/Modules/MriSimulation/SignalModels/mitkAstroStickModel.h
@@ -1,122 +1,122 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_AstroStickModel_H
#define _MITK_AstroStickModel_H
#include <mitkDiffusionSignalModel.h>
#include <itkPointShell.h>
namespace mitk {
/**
* \brief Generates the diffusion signal using a collection of idealised cylinder with zero radius: e^(-bd(ng)²)
*
*/
template< class ScalarType = double >
class AstroStickModel : public DiffusionSignalModel< ScalarType >
{
public:
AstroStickModel();
template< class OtherType >AstroStickModel(AstroStickModel<OtherType>* model)
{
this->m_CompartmentId = model->m_CompartmentId;
this->m_T1 = model->GetT1();
this->m_T2 = model->GetT2();
this->m_GradientList = model->GetGradientList();
this->m_VolumeFractionImage = model->GetVolumeFractionImage();
this->m_RandGen = model->GetRandomGenerator();
this->m_BValue = model->GetBvalue();
this->m_Diffusivity = model->GetDiffusivity();
this->m_Sticks = model->GetSticks();
this->m_NumSticks = model->GetNumSticks();
this->m_RandomizeSticks = model->GetRandomizeSticks();
}
~AstroStickModel();
typedef typename DiffusionSignalModel< ScalarType >::PixelType PixelType;
typedef typename DiffusionSignalModel< ScalarType >::GradientType GradientType;
typedef typename DiffusionSignalModel< ScalarType >::GradientListType GradientListType;
/** Actual signal generation **/
PixelType SimulateMeasurement(GradientType& fiberDirection) override;
ScalarType SimulateMeasurement(unsigned int dir, GradientType& fiberDirection) override;
void SetRandomizeSticks(bool randomize=true){ m_RandomizeSticks=randomize; } ///< Random stick configuration in each voxel
bool GetRandomizeSticks() { return m_RandomizeSticks; }
void SetDiffusivity(double diffusivity) { m_Diffusivity = diffusivity; } ///< Scalar diffusion constant
double GetDiffusivity() { return m_Diffusivity; }
void SetNumSticks(unsigned int order)
{
vnl_matrix<double> sticks;
switch (order)
{
case 1:
m_NumSticks = 12;
sticks = itk::PointShell<12, vnl_matrix_fixed<double, 3, 12> >::DistributePointShell()->as_matrix();
break;
case 2:
m_NumSticks = 42;
sticks = itk::PointShell<42, vnl_matrix_fixed<double, 3, 42> >::DistributePointShell()->as_matrix();
break;
case 3:
m_NumSticks = 92;
sticks = itk::PointShell<92, vnl_matrix_fixed<double, 3, 92> >::DistributePointShell()->as_matrix();
break;
case 4:
m_NumSticks = 162;
sticks = itk::PointShell<162, vnl_matrix_fixed<double, 3, 162> >::DistributePointShell()->as_matrix();
break;
case 5:
m_NumSticks = 252;
sticks = itk::PointShell<252, vnl_matrix_fixed<double, 3, 252> >::DistributePointShell()->as_matrix();
break;
default:
m_NumSticks = 42;
sticks = itk::PointShell<42, vnl_matrix_fixed<double, 3, 42> >::DistributePointShell()->as_matrix();
break;
}
for (int i=0; i<m_NumSticks; i++)
{
GradientType stick;
stick[0] = sticks.get(0,i); stick[1] = sticks.get(1,i); stick[2] = sticks.get(2,i);
stick.Normalize();
m_Sticks.push_back(stick);
}
}
unsigned int GetNumSticks(){ return m_NumSticks; }
GradientListType GetSticks(){ return m_Sticks; }
protected:
GradientType GetRandomDirection();
double m_Diffusivity; ///< Scalar diffusion constant
GradientListType m_Sticks; ///< Stick container
unsigned int m_NumSticks; ///< Number of sticks
bool m_RandomizeSticks;
};
}
#include "mitkAstroStickModel.cpp"
#endif
diff --git a/Modules/MriSimulation/SignalModels/mitkBallModel.cpp b/Modules/MriSimulation/SignalModels/mitkBallModel.cpp
index 5d71412..8f52c70 100644
--- a/Modules/MriSimulation/SignalModels/mitkBallModel.cpp
+++ b/Modules/MriSimulation/SignalModels/mitkBallModel.cpp
@@ -1,72 +1,72 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <vnl/vnl_cross.h>
#include <vnl/vnl_quaternion.h>
#include <mitkBallModel.h>
using namespace mitk;
template< class ScalarType >
BallModel< ScalarType >::BallModel()
: m_Diffusivity(0.001)
{
}
template< class ScalarType >
BallModel< ScalarType >::~BallModel()
{
}
template< class ScalarType >
ScalarType BallModel< ScalarType >::SimulateMeasurement(unsigned int dir, GradientType& )
{
ScalarType signal = 0;
if (dir>=this->m_GradientList.size())
return signal;
GradientType g = this->m_GradientList[dir];
ScalarType bVal = g.GetNorm(); bVal *= bVal;
if (bVal>0.0001)
signal = std::exp( -this->m_BValue * bVal * m_Diffusivity );
else
signal = 1;
return signal;
}
template< class ScalarType >
typename BallModel< ScalarType >::PixelType BallModel< ScalarType >::SimulateMeasurement(GradientType& )
{
PixelType signal;
signal.SetSize(this->m_GradientList.size());
for( unsigned int i=0; i<this->m_GradientList.size(); i++)
{
GradientType g = this->m_GradientList[i];
ScalarType bVal = g.GetNorm(); bVal *= bVal;
if (bVal>0.0001)
signal[i] = std::exp( -this->m_BValue * bVal * m_Diffusivity );
else
signal[i] = 1;
}
return signal;
}
diff --git a/Modules/MriSimulation/SignalModels/mitkBallModel.h b/Modules/MriSimulation/SignalModels/mitkBallModel.h
index 516d35b..339e98a 100644
--- a/Modules/MriSimulation/SignalModels/mitkBallModel.h
+++ b/Modules/MriSimulation/SignalModels/mitkBallModel.h
@@ -1,71 +1,71 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_BallModel_H
#define _MITK_BallModel_H
#include <mitkDiffusionSignalModel.h>
namespace mitk {
/**
* \brief Generates direction independent diffusion measurement employing a scalar diffusion constant d: e^(-bd)
*
*/
template< class ScalarType = double >
class BallModel : public DiffusionSignalModel< ScalarType >
{
public:
BallModel();
template< class OtherType >BallModel(BallModel<OtherType>* model)
{
this->m_CompartmentId = model->m_CompartmentId;
this->m_T1 = model->GetT1();
this->m_T2 = model->GetT2();
this->m_GradientList = model->GetGradientList();
this->m_VolumeFractionImage = model->GetVolumeFractionImage();
this->m_RandGen = model->GetRandomGenerator();
this->m_BValue = model->GetBvalue();
this->m_Diffusivity = model->GetDiffusivity();
}
~BallModel();
typedef typename DiffusionSignalModel< ScalarType >::PixelType PixelType;
typedef typename DiffusionSignalModel< ScalarType >::GradientType GradientType;
typedef typename DiffusionSignalModel< ScalarType >::GradientListType GradientListType;
/** Actual signal generation **/
PixelType SimulateMeasurement(GradientType& fiberDirection) override;
ScalarType SimulateMeasurement(unsigned int dir, GradientType& fiberDirection) override;
void SetDiffusivity(double D) { m_Diffusivity = D; }
double GetDiffusivity() { return m_Diffusivity; }
protected:
double m_Diffusivity; ///< Scalar diffusion constant
};
}
#include "mitkBallModel.cpp"
#endif
diff --git a/Modules/MriSimulation/SignalModels/mitkChiSquareNoiseModel.cpp b/Modules/MriSimulation/SignalModels/mitkChiSquareNoiseModel.cpp
index 5b4a87b..ce779a9 100644
--- a/Modules/MriSimulation/SignalModels/mitkChiSquareNoiseModel.cpp
+++ b/Modules/MriSimulation/SignalModels/mitkChiSquareNoiseModel.cpp
@@ -1,48 +1,48 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <vnl/vnl_cross.h>
#include <vnl/vnl_quaternion.h>
#include <mitkChiSquareNoiseModel.h>
using namespace mitk;
template< class ScalarType >
ChiSquareNoiseModel< ScalarType >::ChiSquareNoiseModel()
{
m_RandGen.seed();
}
template< class ScalarType >
ChiSquareNoiseModel< ScalarType >::~ChiSquareNoiseModel()
{
}
template< class ScalarType >
void ChiSquareNoiseModel< ScalarType >::SetSeed(int seed)
{
if (seed>=0)
m_RandGen.seed(seed);
else
m_RandGen.seed();
}
template< class ScalarType >
void ChiSquareNoiseModel< ScalarType >::AddNoise(PixelType& pixel)
{
for( unsigned int i=0; i<pixel.Size(); i++)
pixel[i] += (ScalarType)(m_Distribution(m_RandGen)-m_Distribution.n());
}
diff --git a/Modules/MriSimulation/SignalModels/mitkChiSquareNoiseModel.h b/Modules/MriSimulation/SignalModels/mitkChiSquareNoiseModel.h
index 33f845a..649f099 100644
--- a/Modules/MriSimulation/SignalModels/mitkChiSquareNoiseModel.h
+++ b/Modules/MriSimulation/SignalModels/mitkChiSquareNoiseModel.h
@@ -1,58 +1,58 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_ChiSquareNoiseModel_H
#define _MITK_ChiSquareNoiseModel_H
#include <mitkDiffusionNoiseModel.h>
#include <itkMersenneTwisterRandomVariateGenerator.h>
namespace mitk {
/**
* \brief Implementation of noise following a chi-squared distribution
*
*/
template< class ScalarType = double >
class ChiSquareNoiseModel : public DiffusionNoiseModel< ScalarType >
{
public:
ChiSquareNoiseModel();
~ChiSquareNoiseModel() override;
typedef typename DiffusionNoiseModel< ScalarType >::PixelType PixelType;
/** Adds rician noise to the input pixel **/
void AddNoise(PixelType& pixel) override;
void SetNoiseVariance(double var) override{ m_Distribution = boost::random::chi_squared_distribution<double>(var/2); }
double GetNoiseVariance() override{ return m_Distribution.n()*2; }
void SetSeed(int seed) override; ///< seed for random number generator
protected:
boost::random::mt19937 m_RandGen;
boost::random::chi_squared_distribution<double> m_Distribution;
};
}
#include "mitkChiSquareNoiseModel.cpp"
#endif
diff --git a/Modules/MriSimulation/SignalModels/mitkDiffusionNoiseModel.h b/Modules/MriSimulation/SignalModels/mitkDiffusionNoiseModel.h
index 39735b3..8bcbe28 100644
--- a/Modules/MriSimulation/SignalModels/mitkDiffusionNoiseModel.h
+++ b/Modules/MriSimulation/SignalModels/mitkDiffusionNoiseModel.h
@@ -1,58 +1,58 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_DiffusionNoiseModel_H
#define _MITK_DiffusionNoiseModel_H
#include <itkVariableLengthVector.h>
#include <itkVector.h>
#include <vnl/vnl_vector_fixed.h>
#include <boost/random.hpp>
namespace mitk {
/**
* \brief Abstract class for diffusion noise models
*
*/
template< class ScalarType = double >
class DiffusionNoiseModel
{
public:
DiffusionNoiseModel(){}
virtual ~DiffusionNoiseModel(){}
typedef itk::VariableLengthVector< ScalarType > PixelType;
/** Adds noise according to model to the input pixel. Has to be implemented in subclass. **/
virtual void AddNoise(PixelType& pixel) = 0;
/** Seed for random generator. Has to be implemented in subclass. **/
virtual void SetSeed(int seed) = 0;
virtual double GetNoiseVariance() = 0;
virtual void SetNoiseVariance(double var) = 0;
protected:
};
}
#endif
diff --git a/Modules/MriSimulation/SignalModels/mitkDiffusionSignalModel.h b/Modules/MriSimulation/SignalModels/mitkDiffusionSignalModel.h
index c9856d4..a08aaba 100644
--- a/Modules/MriSimulation/SignalModels/mitkDiffusionSignalModel.h
+++ b/Modules/MriSimulation/SignalModels/mitkDiffusionSignalModel.h
@@ -1,112 +1,112 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_DiffusionSignalModel_H
#define _MITK_DiffusionSignalModel_H
#include <itkVariableLengthVector.h>
#include <itkVector.h>
#include <itkImage.h>
#include <itkMersenneTwisterRandomVariateGenerator.h>
#include <vnl/vnl_vector_fixed.h>
#include <mitkDiffusionPropertyHelper.h>
namespace mitk {
/**
* \brief Abstract class for diffusion signal models
*
*/
template< class ScalarType = double >
class DiffusionSignalModel
{
public:
DiffusionSignalModel()
: m_T2(100)
, m_T1(0)
, m_BValue(1000)
{}
~DiffusionSignalModel(){}
typedef itk::Image<double, 3> ItkDoubleImgType;
typedef itk::VariableLengthVector< ScalarType > PixelType;
typedef itk::Vector<double,3> GradientType;
typedef std::vector<GradientType> GradientListType;
typedef itk::Statistics::MersenneTwisterRandomVariateGenerator ItkRandGenType;
typedef mitk::DiffusionPropertyHelper DPH;
/** Realizes actual signal generation. Has to be implemented in subclass. **/
virtual PixelType SimulateMeasurement(GradientType& fiberDirection) = 0;
virtual ScalarType SimulateMeasurement(unsigned int dir, GradientType& fiberDirection) = 0;
void SetGradientList(DPH::GradientDirectionsContainerType* gradients)
{
m_GradientList.clear();
for ( unsigned int i=0; i<gradients->Size(); ++i )
{
DPH::GradientDirectionType g_vnl = gradients->GetElement(i);
GradientType g_itk;
g_itk[0] = g_vnl[0];
g_itk[1] = g_vnl[1];
g_itk[2] = g_vnl[2];
m_GradientList.push_back(g_itk);
}
}
void SetGradientList(GradientListType gradientList) { this->m_GradientList = gradientList; }
GradientListType GetGradientList(){ return m_GradientList; }
GradientType GetGradientDirection(int i) { return m_GradientList.at(i); }
void SetT2(double T2) { m_T2 = T2; }
double GetT2() { return m_T2; }
void SetT1(double T1) { m_T1 = T1; }
double GetT1() { return m_T1; }
void SetVolumeFractionImage(ItkDoubleImgType::Pointer img){ m_VolumeFractionImage = img; }
ItkDoubleImgType::Pointer GetVolumeFractionImage(){ return m_VolumeFractionImage; }
void SetRandomGenerator(ItkRandGenType::Pointer randgen){ m_RandGen = randgen; }
ItkRandGenType::Pointer GetRandomGenerator(){ return m_RandGen; }
void SetSeed(int s) ///< set seed for random generator
{
if (m_RandGen.IsNull())
m_RandGen = itk::Statistics::MersenneTwisterRandomVariateGenerator::New();
m_RandGen->SetSeed(s);
}
void SetBvalue(double bValue) { m_BValue = bValue; } ///< b-value used to generate the artificial signal
double GetBvalue() { return m_BValue; }
unsigned int m_CompartmentId; ///< GUI flag. Which compartment is this model assigned to?
protected:
GradientListType m_GradientList; ///< Diffusion gradient direction container
double m_T2; ///< Tissue specific transversal relaxation time
double m_T1; ///< Tissue specific longitudinal relaxation time
ItkDoubleImgType::Pointer m_VolumeFractionImage; ///< Tissue specific volume fraction for each voxel (only relevant for non fiber compartments)
ItkRandGenType::Pointer m_RandGen; ///< Random number generator
double m_BValue;
};
}
#endif
diff --git a/Modules/MriSimulation/SignalModels/mitkDotModel.cpp b/Modules/MriSimulation/SignalModels/mitkDotModel.cpp
index 7a7b0d6..ff873be 100644
--- a/Modules/MriSimulation/SignalModels/mitkDotModel.cpp
+++ b/Modules/MriSimulation/SignalModels/mitkDotModel.cpp
@@ -1,47 +1,47 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <vnl/vnl_cross.h>
#include <vnl/vnl_quaternion.h>
#include <mitkDotModel.h>
using namespace mitk;
template< class ScalarType >
DotModel< ScalarType >::DotModel()
{
}
template< class ScalarType >
DotModel< ScalarType >::~DotModel()
{
}
template< class ScalarType >
ScalarType DotModel< ScalarType >::SimulateMeasurement(unsigned int /*dir*/, GradientType& )
{
return 1;
}
template< class ScalarType >
typename DotModel< ScalarType >::PixelType DotModel< ScalarType >::SimulateMeasurement(GradientType& )
{
PixelType signal;
signal.SetSize(this->m_GradientList.size());
signal.Fill(1);
return signal;
}
diff --git a/Modules/MriSimulation/SignalModels/mitkDotModel.h b/Modules/MriSimulation/SignalModels/mitkDotModel.h
index d1ba3b4..7983b5b 100644
--- a/Modules/MriSimulation/SignalModels/mitkDotModel.h
+++ b/Modules/MriSimulation/SignalModels/mitkDotModel.h
@@ -1,63 +1,63 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_DotModel_H
#define _MITK_DotModel_H
#include <mitkDiffusionSignalModel.h>
namespace mitk {
/**
* \brief Generates constant direction independent signal.
*
*/
template< class ScalarType = double >
class DotModel : public DiffusionSignalModel< ScalarType >
{
public:
DotModel();
template< class OtherType >DotModel(DotModel<OtherType>* model)
{
this->m_CompartmentId = model->m_CompartmentId;
this->m_T1 = model->GetT1();
this->m_T2 = model->GetT2();
this->m_GradientList = model->GetGradientList();
this->m_VolumeFractionImage = model->GetVolumeFractionImage();
this->m_RandGen = model->GetRandomGenerator();
}
~DotModel();
typedef typename DiffusionSignalModel< ScalarType >::PixelType PixelType;
typedef typename DiffusionSignalModel< ScalarType >::GradientType GradientType;
typedef typename DiffusionSignalModel< ScalarType >::GradientListType GradientListType;
/** Actual signal generation **/
PixelType SimulateMeasurement(GradientType& fiberDirection) override;
ScalarType SimulateMeasurement(unsigned int dir, GradientType& fiberDirection) override;
protected:
};
}
#include "mitkDotModel.cpp"
#endif
diff --git a/Modules/MriSimulation/SignalModels/mitkRawShModel.cpp b/Modules/MriSimulation/SignalModels/mitkRawShModel.cpp
index 3c3d6e6..ce830a0 100644
--- a/Modules/MriSimulation/SignalModels/mitkRawShModel.cpp
+++ b/Modules/MriSimulation/SignalModels/mitkRawShModel.cpp
@@ -1,394 +1,394 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <vnl/vnl_cross.h>
#include <vnl/vnl_quaternion.h>
#include <mitkRawShModel.h>
#include <boost/math/special_functions.hpp>
#include <itkOrientationDistributionFunction.h>
#include <mitkFiberfoxParameters.h>
#include <itkDiffusionTensor3DReconstructionImageFilter.h>
#include <itkAdcImageFilter.h>
#include <itkAnalyticalDiffusionQballReconstructionImageFilter.h>
#include <mitkDiffusionPropertyHelper.h>
#include <mitkImageCast.h>
#include <mitkProperties.h>
using namespace mitk;
using namespace boost::math;
template< class ScalarType >
RawShModel< ScalarType >::RawShModel()
: m_ShOrder(0)
, m_ModelIndex(-1)
, m_MaxNumKernels(1000)
{
this->m_RandGen = itk::Statistics::MersenneTwisterRandomVariateGenerator::New();
this->m_RandGen->SetSeed();
m_AdcRange.first = 0;
m_AdcRange.second = 0.004;
m_FaRange.first = 0;
m_FaRange.second = 1;
}
template< class ScalarType >
RawShModel< ScalarType >::~RawShModel()
{
}
template< class ScalarType >
void RawShModel< ScalarType >::Clear()
{
m_ShCoefficients.clear();
m_PrototypeMaxDirection.clear();
m_B0Signal.clear();
}
template< class ScalarType >
void RawShModel< ScalarType >::RandomModel()
{
m_ModelIndex = this->m_RandGen->GetIntegerVariate(m_B0Signal.size()-1);
}
template< class ScalarType >
unsigned int RawShModel< ScalarType >::GetNumberOfKernels()
{
return m_B0Signal.size();
}
template< class ScalarType >
bool RawShModel< ScalarType >::SampleKernels(Image::Pointer diffImg, ItkUcharImageType::Pointer maskImage, TensorImageType::Pointer tensorImage, QballFilterType::CoefficientImageType::Pointer itkFeatureImage, ItkDoubleImageType::Pointer adcImage)
{
if (diffImg.IsNull())
return false;
typedef itk::VectorImage<short, 3> ITKDiffusionImageType;
ITKDiffusionImageType::Pointer itkVectorImagePointer = ITKDiffusionImageType::New();
mitk::CastToItkImage(diffImg, itkVectorImagePointer);
const int shOrder = 2;
if (tensorImage.IsNull())
{
typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, double > TensorReconstructionImageFilterType;
TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New();
filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImg));
filter->SetGradientImage(mitk::DiffusionPropertyHelper::GetGradientContainer(diffImg), itkVectorImagePointer );
filter->Update();
tensorImage = filter->GetOutput();
}
const int NumCoeffs = (shOrder*shOrder + shOrder + 2)/2 + shOrder;
if (itkFeatureImage.IsNull())
{
QballFilterType::Pointer qballfilter = QballFilterType::New();
qballfilter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImg));
qballfilter->SetGradientImage(mitk::DiffusionPropertyHelper::GetGradientContainer(diffImg), itkVectorImagePointer );
qballfilter->SetLambda(0.006);
qballfilter->SetNormalizationMethod(QballFilterType::QBAR_RAW_SIGNAL);
qballfilter->Update();
itkFeatureImage = qballfilter->GetCoefficientImage();
}
if (adcImage.IsNull())
{
itk::AdcImageFilter< short, double >::Pointer adcFilter = itk::AdcImageFilter< short, double >::New();
adcFilter->SetInput(itkVectorImagePointer);
adcFilter->SetGradientDirections(mitk::DiffusionPropertyHelper::GetGradientContainer(diffImg));
adcFilter->SetB_value(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImg));
adcFilter->Update();
adcImage = adcFilter->GetOutput();
}
int b0Index = 0;
for (unsigned int i=0; i<mitk::DiffusionPropertyHelper::GetOriginalGradientContainer(diffImg)->Size(); i++)
if (mitk::DiffusionPropertyHelper::GetOriginalGradientContainer(diffImg)->GetElement(i).magnitude()<0.001 )
{
b0Index = i;
break;
}
double max = 0;
{
itk::ImageRegionIterator< itk::VectorImage< short, 3 > > it(itkVectorImagePointer, itkVectorImagePointer->GetLargestPossibleRegion());
while(!it.IsAtEnd())
{
if (maskImage.IsNotNull() && maskImage->GetPixel(it.GetIndex())<=0)
{
++it;
continue;
}
if (it.Get()[b0Index]>max)
max = it.Get()[b0Index];
++it;
}
}
MITK_INFO << "Sampling signal kernels.";
unsigned int count = 0;
itk::ImageRegionIterator< itk::Image< itk::DiffusionTensor3D< double >, 3 > > it(tensorImage, tensorImage->GetLargestPossibleRegion());
while(!it.IsAtEnd())
{
bool skipPixel = false;
if (maskImage.IsNotNull() && maskImage->GetPixel(it.GetIndex())<=0)
{
++it;
continue;
}
for (unsigned int i=0; i<mitk::DiffusionPropertyHelper::GetGradientContainer(diffImg)->Size(); i++)
{
if (itkVectorImagePointer->GetPixel(it.GetIndex())[i]!=itkVectorImagePointer->GetPixel(it.GetIndex())[i] || itkVectorImagePointer->GetPixel(it.GetIndex())[i]<=0 || itkVectorImagePointer->GetPixel(it.GetIndex())[i]>itkVectorImagePointer->GetPixel(it.GetIndex())[b0Index])
{
skipPixel = true;
break;
}
}
if (skipPixel)
{
++it;
continue;
}
typedef itk::DiffusionTensor3D<double> TensorType;
TensorType::EigenValuesArrayType eigenvalues;
TensorType::EigenVectorsMatrixType eigenvectors;
TensorType tensor = it.Get();
double FA = tensor.GetFractionalAnisotropy();
double ADC = adcImage->GetPixel(it.GetIndex());
QballFilterType::CoefficientImageType::PixelType itkv = itkFeatureImage->GetPixel(it.GetIndex());
vnl_vector_fixed< double, NumCoeffs > coeffs;
for (unsigned int c=0; c<itkv.Size(); c++)
coeffs[c] = itkv[c]/max;
if ( this->GetMaxNumKernels()>this->GetNumberOfKernels() && FA>m_FaRange.first && FA<m_FaRange.second && ADC>m_AdcRange.first && ADC<m_AdcRange.second)
{
if (this->SetShCoefficients( coeffs, (double)itkVectorImagePointer->GetPixel(it.GetIndex())[b0Index]/max ))
{
tensor.ComputeEigenAnalysis(eigenvalues, eigenvectors);
itk::Vector<double,3> dir;
dir[0] = eigenvectors(2, 0);
dir[1] = eigenvectors(2, 1);
dir[2] = eigenvectors(2, 2);
m_PrototypeMaxDirection.push_back(dir);
count++;
MITK_INFO << "KERNEL: " << it.GetIndex() << " (" << count << ")";
}
}
++it;
}
if (m_ShCoefficients.size()>0)
return true;
return false;
}
// convert cartesian to spherical coordinates
template< class ScalarType >
vnl_matrix<double> RawShModel<ScalarType>::Cart2Sph(GradientListType &gradients )
{
vnl_matrix<double> sphCoords;
sphCoords.set_size(gradients.size(), 2);
sphCoords.fill(0.0);
for (unsigned int i=0; i<gradients.size(); i++)
{
GradientType g = gradients[i];
if( g.GetNorm() > 0.0001 )
{
gradients[i].Normalize();
sphCoords(i,0) = acos(gradients[i][2]); // theta
sphCoords(i,1) = atan2(gradients[i][1], gradients[i][0]); // phi
}
}
return sphCoords;
}
template< class ScalarType >
vnl_matrix<double> RawShModel< ScalarType >::SetFiberDirection(GradientType& fiberDirection)
{
RandomModel();
GradientType axis = itk::CrossProduct(fiberDirection, m_PrototypeMaxDirection.at(m_ModelIndex));
axis.Normalize();
vnl_quaternion<double> rotation(axis.GetVnlVector(), acos(dot_product(fiberDirection.GetVnlVector(), m_PrototypeMaxDirection.at(m_ModelIndex).GetVnlVector())));
rotation.normalize();
GradientListType gradients;
for (unsigned int i=0; i<this->m_GradientList.size(); i++)
{
GradientType dir = this->m_GradientList.at(i);
if( dir.GetNorm() > 0.0001 )
{
dir.Normalize();
vnl_vector_fixed< double, 3 > vnlDir = rotation.rotate(dir.GetVnlVector());
dir[0] = vnlDir[0]; dir[1] = vnlDir[1]; dir[2] = vnlDir[2];
dir.Normalize();
}
gradients.push_back(dir);
}
return Cart2Sph( gradients );
}
template< class ScalarType >
bool RawShModel< ScalarType >::SetShCoefficients(vnl_vector< double > shCoefficients, double b0 )
{
m_ShOrder = 2;
while ( (m_ShOrder*m_ShOrder + m_ShOrder + 2)/2 + m_ShOrder <= shCoefficients.size() )
m_ShOrder += 2;
m_ShOrder -= 2;
m_ModelIndex = m_B0Signal.size();
m_B0Signal.push_back(b0);
m_ShCoefficients.push_back(shCoefficients);
// itk::OrientationDistributionFunction<double, 10000> odf;
// GradientListType gradients;
// for (unsigned int i=0; i<odf.GetNumberOfComponents(); i++)
// {
// GradientType dir; dir[0]=odf.GetDirection(i)[0]; dir[1]=odf.GetDirection(i)[1]; dir[2]=odf.GetDirection(i)[2];
// dir.Normalize();
// gradients.push_back(dir);
// }
// Cart2Sph( this->m_GradientList );
// PixelType signal = SimulateMeasurement();
// int minDirIdx = 0;
// double min = itk::NumericTraits<double>::max();
// for (unsigned int i=0; i<signal.GetSize(); i++)
// {
// if (signal[i]>b0 || signal[i]<0)
// {
// MITK_INFO << "Corrupted signal value detected. Kernel rejected.";
// m_B0Signal.pop_back();
// m_ShCoefficients.pop_back();
// return false;
// }
// if (signal[i]<min)
// {
// min = signal[i];
// minDirIdx = i;
// }
// }
// GradientType maxDir = this->m_GradientList.at(minDirIdx);
// maxDir.Normalize();
// m_PrototypeMaxDirection.push_back(maxDir);
Cart2Sph( this->m_GradientList );
m_ModelIndex = -1;
return true;
}
template< class ScalarType >
ScalarType RawShModel< ScalarType >::SimulateMeasurement(unsigned int dir, GradientType& fiberDirection)
{
ScalarType signal = 0;
if (m_ModelIndex==-1)
RandomModel();
vnl_matrix<double> sphCoords = this->SetFiberDirection(fiberDirection);
if (dir>=this->m_GradientList.size())
return signal;
int j, m; double mag, plm;
if (this->m_GradientList[dir].GetNorm()>0.001)
{
j=0;
for (int l=0; l<=static_cast<int>(m_ShOrder); l=l+2)
for (m=-l; m<=l; m++)
{
plm = legendre_p<double>(l,abs(m),cos(sphCoords(dir,0)));
mag = sqrt((double)(2*l+1)/(4.0*itk::Math::pi)*factorial<double>(l-abs(m))/factorial<double>(l+abs(m)))*plm;
double basis;
if (m<0)
basis = sqrt(2.0)*mag*cos(fabs((double)m)*sphCoords(dir,1));
else if (m==0)
basis = mag;
else
basis = pow(-1.0, m)*sqrt(2.0)*mag*sin(m*sphCoords(dir,1));
signal += m_ShCoefficients.at(m_ModelIndex)[j]*basis;
j++;
}
}
else
signal = m_B0Signal.at(m_ModelIndex);
m_ModelIndex = -1;
return signal;
}
template< class ScalarType >
typename RawShModel< ScalarType >::PixelType RawShModel< ScalarType >::SimulateMeasurement(GradientType& fiberDirection)
{
if (m_ModelIndex==-1)
RandomModel();
PixelType signal;
signal.SetSize(this->m_GradientList.size());
int M = this->m_GradientList.size();
int j, m; double mag, plm;
vnl_matrix< double > shBasis;
shBasis.set_size(M, m_ShCoefficients.at(m_ModelIndex).size());
shBasis.fill(0.0);
vnl_matrix<double> sphCoords = this->SetFiberDirection(fiberDirection);
for (int p=0; p<M; p++)
{
if (this->m_GradientList[p].GetNorm()>0.001)
{
j=0;
for (int l=0; l<=static_cast<int>(m_ShOrder); l=l+2)
for (m=-l; m<=l; m++)
{
plm = legendre_p<double>(l,abs(m),cos(sphCoords(p,0)));
mag = sqrt((double)(2*l+1)/(4.0*itk::Math::pi)*factorial<double>(l-abs(m))/factorial<double>(l+abs(m)))*plm;
if (m<0)
shBasis(p,j) = sqrt(2.0)*mag*cos(fabs((double)m)*sphCoords(p,1));
else if (m==0)
shBasis(p,j) = mag;
else
shBasis(p,j) = pow(-1.0, m)*sqrt(2.0)*mag*sin(m*sphCoords(p,1));
j++;
}
double val = 0;
for (unsigned int cidx=0; cidx<m_ShCoefficients.at(m_ModelIndex).size(); cidx++)
val += m_ShCoefficients.at(m_ModelIndex)[cidx]*shBasis(p,cidx);
signal[p] = val;
}
else
signal[p] = m_B0Signal.at(m_ModelIndex);
}
m_ModelIndex = -1;
return signal;
}
diff --git a/Modules/MriSimulation/SignalModels/mitkRawShModel.h b/Modules/MriSimulation/SignalModels/mitkRawShModel.h
index 256439e..b7b8e7f 100644
--- a/Modules/MriSimulation/SignalModels/mitkRawShModel.h
+++ b/Modules/MriSimulation/SignalModels/mitkRawShModel.h
@@ -1,110 +1,110 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_RawShModel_H
#define _MITK_RawShModel_H
#include <mitkDiffusionSignalModel.h>
#include <mitkImage.h>
#include <itkAnalyticalDiffusionQballReconstructionImageFilter.h>
namespace mitk {
/**
* \brief The spherical harmonic representation of a prototype diffusion weighted MR signal is used to obtain the direction dependent signal.
*
*/
template< class ScalarType = double >
class RawShModel : public DiffusionSignalModel< ScalarType >
{
public:
RawShModel();
template< class OtherType >RawShModel(RawShModel<OtherType>* model)
{
this->m_CompartmentId = model->m_CompartmentId;
this->m_T1 = model->GetT1();
this->m_T2 = model->GetT2();
this->m_GradientList = model->GetGradientList();
this->m_VolumeFractionImage = model->GetVolumeFractionImage();
this->m_RandGen = model->GetRandomGenerator();
this->m_AdcRange = model->GetAdcRange();
this->m_FaRange = model->GetFaRange();
this->m_ShCoefficients = model->GetShCoefficients();
this->m_B0Signal = model->GetB0Signals();
this->m_ShOrder = model->GetShOrder();
this->m_ModelIndex = model->GetModelIndex();
this->m_MaxNumKernels = model->GetMaxNumKernels();
}
~RawShModel();
typedef itk::Image< double, 3 > ItkDoubleImageType;
typedef itk::Image< unsigned char, 3 > ItkUcharImageType;
typedef itk::Image< itk::DiffusionTensor3D< double >, 3 > TensorImageType;
typedef itk::AnalyticalDiffusionQballReconstructionImageFilter<short,short,float,2,ODF_SAMPLING_SIZE> QballFilterType;
typedef typename DiffusionSignalModel< ScalarType >::PixelType PixelType;
typedef typename DiffusionSignalModel< ScalarType >::GradientType GradientType;
typedef typename DiffusionSignalModel< ScalarType >::GradientListType GradientListType;
typedef itk::Matrix< double, 3, 3 > MatrixType;
/** Actual signal generation **/
PixelType SimulateMeasurement(GradientType& fiberDirection) override;
ScalarType SimulateMeasurement(unsigned int dir, GradientType& fiberDirection) override;
bool SetShCoefficients(vnl_vector< double > shCoefficients, double b0);
vnl_matrix<double> SetFiberDirection(GradientType& fiberDirection);
void SetFaRange(double min, double max){ m_FaRange.first = min; m_FaRange.second = max; }
void SetAdcRange(double min, double max){ m_AdcRange.first = min; m_AdcRange.second = max; }
void SetMaxNumKernels(unsigned int max){ m_MaxNumKernels = max; }
unsigned int GetNumberOfKernels();
std::pair< double, double > GetFaRange(){ return m_FaRange; }
std::pair< double, double > GetAdcRange(){ return m_AdcRange; }
unsigned int GetMaxNumKernels(){ return m_MaxNumKernels; }
void Clear();
std::vector< vnl_vector< double > > GetShCoefficients(){ return m_ShCoefficients; }
std::vector< double > GetB0Signals(){ return m_B0Signal; }
unsigned int GetShOrder(){ return m_ShOrder; }
int GetModelIndex(){ return m_ModelIndex; }
double GetBaselineSignal(int index){ return m_B0Signal.at(index); }
vnl_vector< double > GetCoefficients(int listIndex){ return m_ShCoefficients.at(listIndex); }
bool SampleKernels(Image::Pointer diffImg, ItkUcharImageType::Pointer maskImage, TensorImageType::Pointer tensorImage=nullptr, QballFilterType::CoefficientImageType::Pointer coeffImage=nullptr, ItkDoubleImageType::Pointer adcImage=nullptr);
protected:
vnl_matrix<double> Cart2Sph( GradientListType& gradients );
void RandomModel();
std::vector< vnl_vector< double > > m_ShCoefficients;
std::vector< double > m_B0Signal;
std::vector< GradientType > m_PrototypeMaxDirection;
std::pair< double, double > m_AdcRange;
std::pair< double, double > m_FaRange;
unsigned int m_ShOrder;
int m_ModelIndex;
unsigned int m_MaxNumKernels;
};
}
#include "mitkRawShModel.cpp"
#endif
diff --git a/Modules/MriSimulation/SignalModels/mitkRicianNoiseModel.cpp b/Modules/MriSimulation/SignalModels/mitkRicianNoiseModel.cpp
index e1f61c8..f77c991 100644
--- a/Modules/MriSimulation/SignalModels/mitkRicianNoiseModel.cpp
+++ b/Modules/MriSimulation/SignalModels/mitkRicianNoiseModel.cpp
@@ -1,53 +1,53 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <vnl/vnl_cross.h>
#include <vnl/vnl_quaternion.h>
#include <mitkRicianNoiseModel.h>
using namespace mitk;
template< class ScalarType >
RicianNoiseModel< ScalarType >::RicianNoiseModel()
{
m_RandGen = itk::Statistics::MersenneTwisterRandomVariateGenerator::New();
m_RandGen->SetSeed();
this->m_NoiseVariance = 0;
}
template< class ScalarType >
RicianNoiseModel< ScalarType >::~RicianNoiseModel()
{
}
template< class ScalarType >
void RicianNoiseModel< ScalarType >::SetSeed(int seed)
{
if (seed>=0)
m_RandGen->SetSeed(seed);
else
m_RandGen->SetSeed();
}
template< class ScalarType >
void RicianNoiseModel< ScalarType >::AddNoise(PixelType& pixel)
{
for( unsigned int i=0; i<pixel.Size(); i++)
{
double signal = pixel[i];
pixel[i] = sqrt(pow(signal + m_RandGen->GetNormalVariate(0.0, this->m_NoiseVariance), 2) + pow(m_RandGen->GetNormalVariate(0.0, this->m_NoiseVariance),2));
}
}
diff --git a/Modules/MriSimulation/SignalModels/mitkRicianNoiseModel.h b/Modules/MriSimulation/SignalModels/mitkRicianNoiseModel.h
index 3a6da0d..6ce8c2d 100644
--- a/Modules/MriSimulation/SignalModels/mitkRicianNoiseModel.h
+++ b/Modules/MriSimulation/SignalModels/mitkRicianNoiseModel.h
@@ -1,59 +1,59 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_RicianNoiseModel_H
#define _MITK_RicianNoiseModel_H
#include <mitkDiffusionNoiseModel.h>
#include <itkMersenneTwisterRandomVariateGenerator.h>
namespace mitk {
/**
* \brief Implementation of noise following a rician distribution
*
*/
template< class ScalarType = double >
class RicianNoiseModel : public DiffusionNoiseModel< ScalarType >
{
public:
RicianNoiseModel();
~RicianNoiseModel() override;
typedef typename DiffusionNoiseModel< ScalarType >::PixelType PixelType;
/** Adds rician noise to the input pixel **/
void AddNoise(PixelType& pixel) override;
void SetNoiseVariance(double var) override{ m_NoiseVariance = var; }
double GetNoiseVariance() override{ return m_NoiseVariance; }
void SetSeed(int seed) override; ///< Set seed for random number generator
protected:
itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer m_RandGen;
double m_NoiseVariance; ///< variance of underlying distribution
};
}
#include "mitkRicianNoiseModel.cpp"
#endif
diff --git a/Modules/MriSimulation/SignalModels/mitkStickModel.cpp b/Modules/MriSimulation/SignalModels/mitkStickModel.cpp
index d1a8d88..e95ad6a 100644
--- a/Modules/MriSimulation/SignalModels/mitkStickModel.cpp
+++ b/Modules/MriSimulation/SignalModels/mitkStickModel.cpp
@@ -1,74 +1,74 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <vnl/vnl_cross.h>
#include <vnl/vnl_quaternion.h>
#include <mitkStickModel.h>
using namespace mitk;
template< class ScalarType >
StickModel< ScalarType >::StickModel()
: m_Diffusivity(0.001)
{
}
template< class ScalarType >
StickModel< ScalarType >::~StickModel()
{
}
template< class ScalarType >
ScalarType StickModel< ScalarType >::SimulateMeasurement(unsigned int dir, GradientType& fiberDirection)
{
ScalarType signal = 0;
if (dir>=this->m_GradientList.size())
return signal;
GradientType g = this->m_GradientList[dir];
if (g.GetNorm()>0.0001)
{
ScalarType dot = fiberDirection*g;
signal = std::exp( -this->m_BValue*m_Diffusivity*dot*dot ); // skip * bVal becaus bVal is already encoded in the dot product (norm of g encodes b-value relative to baseline b-value m_BValue)
}
else
signal = 1;
return signal;
}
template< class ScalarType >
typename StickModel< ScalarType >::PixelType StickModel< ScalarType >::SimulateMeasurement(GradientType &fiberDirection)
{
PixelType signal;
signal.SetSize(this->m_GradientList.size());
for( unsigned int i=0; i<this->m_GradientList.size(); i++)
{
GradientType g = this->m_GradientList[i];
if (g.GetNorm()>0.0001)
{
ScalarType dot = fiberDirection*g;
signal[i] = std::exp( -this->m_BValue*m_Diffusivity*dot*dot ); // skip * bVal becaus bVal is already encoded in the dot product (norm of g encodes b-value relative to baseline b-value m_BValue)
}
else
signal[i] = 1;
}
return signal;
}
diff --git a/Modules/MriSimulation/SignalModels/mitkStickModel.h b/Modules/MriSimulation/SignalModels/mitkStickModel.h
index b8c16d4..736db48 100644
--- a/Modules/MriSimulation/SignalModels/mitkStickModel.h
+++ b/Modules/MriSimulation/SignalModels/mitkStickModel.h
@@ -1,70 +1,70 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_StickModel_H
#define _MITK_StickModel_H
#include <mitkDiffusionSignalModel.h>
namespace mitk {
/**
* \brief Generates the diffusion signal using an idealised cylinder with zero radius: e^(-bd(ng)²)
*
*/
template< class ScalarType = double >
class StickModel : public DiffusionSignalModel< ScalarType >
{
public:
StickModel();
template< class OtherType >StickModel(StickModel<OtherType>* model)
{
this->m_CompartmentId = model->m_CompartmentId;
this->m_T1 = model->GetT1();
this->m_T2 = model->GetT2();
this->m_GradientList = model->GetGradientList();
this->m_VolumeFractionImage = model->GetVolumeFractionImage();
this->m_RandGen = model->GetRandomGenerator();
this->m_BValue = model->GetBvalue();
this->m_Diffusivity = model->GetDiffusivity();
}
~StickModel();
typedef typename DiffusionSignalModel< ScalarType >::PixelType PixelType;
typedef typename DiffusionSignalModel< ScalarType >::GradientType GradientType;
typedef typename DiffusionSignalModel< ScalarType >::GradientListType GradientListType;
/** Actual signal generation **/
PixelType SimulateMeasurement(GradientType& fiberDirection) override;
ScalarType SimulateMeasurement(unsigned int dir, GradientType& fiberDirection) override;
void SetDiffusivity(double diffusivity) { m_Diffusivity = diffusivity; } ///< Scalar diffusion constant
double GetDiffusivity() { return m_Diffusivity; }
protected:
double m_Diffusivity; ///< Scalar diffusion constant
};
}
#include "mitkStickModel.cpp"
#endif
diff --git a/Modules/MriSimulation/SignalModels/mitkTensorModel.cpp b/Modules/MriSimulation/SignalModels/mitkTensorModel.cpp
index 9d833fa..47444d4 100644
--- a/Modules/MriSimulation/SignalModels/mitkTensorModel.cpp
+++ b/Modules/MriSimulation/SignalModels/mitkTensorModel.cpp
@@ -1,124 +1,124 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <vnl/vnl_cross.h>
#include <vnl/vnl_quaternion.h>
#include <mitkTensorModel.h>
using namespace mitk;
template< class ScalarType >
TensorModel< ScalarType >::TensorModel()
{
m_KernelDirection[0]=1; m_KernelDirection[1]=0; m_KernelDirection[2]=0;
m_KernelTensorMatrix.fill(0.0);
m_KernelTensorMatrix[0][0] = 0.002;
m_KernelTensorMatrix[1][1] = 0.0005;
m_KernelTensorMatrix[2][2] = 0.0005;
}
template< class ScalarType >
TensorModel< ScalarType >::~TensorModel()
{
}
template< class ScalarType >
ScalarType TensorModel< ScalarType >::SimulateMeasurement(unsigned int dir, GradientType &fiberDirection)
{
ScalarType signal = 0;
if (dir>=this->m_GradientList.size())
return signal;
ItkTensorType tensor; tensor.Fill(0.0);
vnl_vector_fixed<double, 3> axis = itk::CrossProduct(m_KernelDirection, fiberDirection).GetVnlVector(); axis.normalize();
vnl_quaternion<double> rotation(axis, acos(m_KernelDirection*fiberDirection));
rotation.normalize();
vnl_matrix_fixed<double, 3, 3> matrix = rotation.rotation_matrix_transpose();
vnl_matrix_fixed<double, 3, 3> tensorMatrix = matrix.transpose()*m_KernelTensorMatrix*matrix;
tensor[0] = tensorMatrix[0][0]; tensor[1] = tensorMatrix[0][1]; tensor[2] = tensorMatrix[0][2];
tensor[3] = tensorMatrix[1][1]; tensor[4] = tensorMatrix[1][2]; tensor[5] = tensorMatrix[2][2];
GradientType g = this->m_GradientList[dir];
if (g.GetNorm()>0.0001)
{
// calc g^T * D * g
itk::DiffusionTensor3D< ScalarType > S;
S[0] = g[0]*g[0];
S[1] = g[1]*g[0];
S[2] = g[2]*g[0];
S[3] = g[1]*g[1];
S[4] = g[2]*g[1];
S[5] = g[2]*g[2];
ScalarType D_scalar = tensor[0]*S[0] + tensor[1]*S[1] + tensor[2]*S[2] +
tensor[1]*S[1] + tensor[3]*S[3] + tensor[4]*S[4] +
tensor[2]*S[2] + tensor[4]*S[4] + tensor[5]*S[5];
// check for corrupted tensor and generate signal
if (D_scalar>=0)
signal = std::exp ( -this->m_BValue * D_scalar ); // skip * bVal becaus bVal is already encoded in g^T*g (norm of g encodes b-value relative to baseline b-value m_BValue)
}
else
signal = 1;
return signal;
}
template< class ScalarType >
typename TensorModel< ScalarType >::PixelType TensorModel< ScalarType >::SimulateMeasurement(GradientType& fiberDirection)
{
PixelType signal; signal.SetSize(this->m_GradientList.size()); signal.Fill(0.0);
ItkTensorType tensor; tensor.Fill(0.0);
vnl_vector_fixed<double, 3> axis = itk::CrossProduct(m_KernelDirection, fiberDirection).GetVnlVector(); axis.normalize();
vnl_quaternion<double> rotation(axis, acos(m_KernelDirection*fiberDirection));
rotation.normalize();
vnl_matrix_fixed<double, 3, 3> matrix = rotation.rotation_matrix_transpose();
vnl_matrix_fixed<double, 3, 3> tensorMatrix = matrix.transpose()*m_KernelTensorMatrix*matrix;
tensor[0] = tensorMatrix[0][0]; tensor[1] = tensorMatrix[0][1]; tensor[2] = tensorMatrix[0][2];
tensor[3] = tensorMatrix[1][1]; tensor[4] = tensorMatrix[1][2]; tensor[5] = tensorMatrix[2][2];
for( unsigned int i=0; i<this->m_GradientList.size(); i++)
{
GradientType g = this->m_GradientList[i];
if (g.GetNorm()>0.0001)
{
// calc g^T * D * g
itk::DiffusionTensor3D< ScalarType > S;
S[0] = g[0]*g[0];
S[1] = g[1]*g[0];
S[2] = g[2]*g[0];
S[3] = g[1]*g[1];
S[4] = g[2]*g[1];
S[5] = g[2]*g[2];
ScalarType D_scalar = tensor[0]*S[0] + tensor[1]*S[1] + tensor[2]*S[2] +
tensor[1]*S[1] + tensor[3]*S[3] + tensor[4]*S[4] +
tensor[2]*S[2] + tensor[4]*S[4] + tensor[5]*S[5];
// check for corrupted tensor and generate signal
if (D_scalar>=0)
signal[i] = std::exp ( -this->m_BValue * D_scalar ); // skip * bVal becaus bVal is already encoded in g^T*g (norm of g encodes b-value relative to baseline b-value m_BValue)
}
else
signal[i] = 1;
}
return signal;
}
diff --git a/Modules/MriSimulation/SignalModels/mitkTensorModel.h b/Modules/MriSimulation/SignalModels/mitkTensorModel.h
index b961fd2..e60a806 100644
--- a/Modules/MriSimulation/SignalModels/mitkTensorModel.h
+++ b/Modules/MriSimulation/SignalModels/mitkTensorModel.h
@@ -1,83 +1,83 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_TensorModel_H
#define _MITK_TensorModel_H
#include <mitkDiffusionSignalModel.h>
#include <itkDiffusionTensor3D.h>
namespace mitk {
/**
* \brief Generates diffusion measurement employing a second rank tensor model: e^(-bg^TDg)
*
*/
template< class ScalarType = double >
class TensorModel : public DiffusionSignalModel< ScalarType >
{
public:
TensorModel();
template< class OtherType >TensorModel(TensorModel<OtherType>* model)
{
this->m_CompartmentId = model->m_CompartmentId;
this->m_T1 = model->GetT1();
this->m_T2 = model->GetT2();
this->m_GradientList = model->GetGradientList();
this->m_VolumeFractionImage = model->GetVolumeFractionImage();
this->m_RandGen = model->GetRandomGenerator();
this->m_BValue = model->GetBvalue();
this->m_KernelDirection = model->GetKernelDirection();
this->m_KernelTensorMatrix = model->GetKernelTensorMatrix();
}
~TensorModel();
typedef typename DiffusionSignalModel< ScalarType >::PixelType PixelType;
typedef itk::DiffusionTensor3D< ScalarType > ItkTensorType;
typedef typename DiffusionSignalModel< ScalarType >::GradientType GradientType;
typedef typename DiffusionSignalModel< ScalarType >::GradientListType GradientListType;
/** Actual signal generation **/
PixelType SimulateMeasurement(GradientType& fiberDirection) override;
ScalarType SimulateMeasurement(unsigned int dir, GradientType& fiberDirection) override;
void SetDiffusivity1(double d1){ m_KernelTensorMatrix[0][0] = d1; }
void SetDiffusivity2(double d2){ m_KernelTensorMatrix[1][1] = d2; }
void SetDiffusivity3(double d3){ m_KernelTensorMatrix[2][2] = d3; }
double GetDiffusivity1() { return m_KernelTensorMatrix[0][0]; }
double GetDiffusivity2() { return m_KernelTensorMatrix[1][1]; }
double GetDiffusivity3() { return m_KernelTensorMatrix[2][2]; }
GradientType GetKernelDirection(){ return m_KernelDirection; }
vnl_matrix_fixed<double, 3, 3> GetKernelTensorMatrix(){ return m_KernelTensorMatrix; }
protected:
/** Calculates tensor matrix from FA and ADC **/
void UpdateKernelTensor();
GradientType m_KernelDirection; ///< Direction of the kernel tensors principal eigenvector
vnl_matrix_fixed<double, 3, 3> m_KernelTensorMatrix; ///< 3x3 matrix containing the kernel tensor values
};
}
#include "mitkTensorModel.cpp"
#endif
diff --git a/Modules/MriSimulation/Testing/mitkFiberFitTest.cpp b/Modules/MriSimulation/Testing/mitkFiberFitTest.cpp
index bac0b6b..b49846b 100644
--- a/Modules/MriSimulation/Testing/mitkFiberFitTest.cpp
+++ b/Modules/MriSimulation/Testing/mitkFiberFitTest.cpp
@@ -1,277 +1,277 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkTestingMacros.h"
#include <mitkFiberBundle.h>
#include <mitkBaseData.h>
#include <itksys/SystemTools.hxx>
#include <mitkTestingConfig.h>
#include <mitkIOUtil.h>
#include <omp.h>
#include <itkFitFibersToImageFilter.h>
#include <mitkTestFixture.h>
#include <mitkPeakImage.h>
#include <mitkPreferenceListReaderOptionsFunctor.h>
#include <mitkImageToItk.h>
#include <mitkImageCast.h>
#include <itkImageFileWriter.h>
#include <mitkLocaleSwitch.h>
class mitkFiberFitTestSuite : public mitk::TestFixture
{
CPPUNIT_TEST_SUITE(mitkFiberFitTestSuite);
MITK_TEST(Fit1);
MITK_TEST(Fit2);
MITK_TEST(Fit3);
MITK_TEST(Fit4);
MITK_TEST(Fit5);
MITK_TEST(Fit6);
CPPUNIT_TEST_SUITE_END();
typedef itk::Image<float, 3> ItkFloatImgType;
private:
/** Members used inside the different (sub-)tests. All members are initialized via setUp().*/
typedef itk::FitFibersToImageFilter FitterType;
FitterType::Pointer fitter;
public:
mitk::FiberBundle::Pointer LoadFib(std::string fib_name)
{
std::vector<mitk::BaseData::Pointer> fibInfile = mitk::IOUtil::Load(GetTestDataFilePath("DiffusionImaging/FiberFit/" + fib_name));
mitk::BaseData::Pointer baseData = fibInfile.at(0);
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(baseData.GetPointer());
return fib;
}
void setUp() override
{
std::vector<mitk::FiberBundle::Pointer> tracts;
tracts.push_back(LoadFib("Cluster_0.fib"));
tracts.push_back(LoadFib("Cluster_1.fib"));
tracts.push_back(LoadFib("Cluster_2.fib"));
tracts.push_back(LoadFib("Cluster_3.fib"));
tracts.push_back(LoadFib("Cluster_4.fib"));
mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Peak Image"}, {});
mitk::PeakImage::Pointer peaks = mitk::IOUtil::Load<mitk::PeakImage>(GetTestDataFilePath("DiffusionImaging/FiberFit/csd_peak_image.nii.gz"), &functor);
typedef mitk::ImageToItk< mitk::PeakImage::ItkPeakImageType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(peaks);
caster->Update();
mitk::PeakImage::ItkPeakImageType::Pointer peak_image = caster->GetOutput();
fitter = FitterType::New();
fitter->SetPeakImage(peak_image);
fitter->SetTractograms(tracts);
}
void tearDown() override
{
}
void CompareFibs(mitk::FiberBundle::Pointer test, mitk::FiberBundle::Pointer ref, std::string out_name)
{
vtkSmartPointer<vtkFloatArray> weights = test->GetFiberWeights();
vtkSmartPointer<vtkFloatArray> ref_weights = ref->GetFiberWeights();
CPPUNIT_ASSERT_MESSAGE("Number of weights should be equal", weights->GetSize()==ref_weights->GetSize());
for (int i=0; i<weights->GetSize(); ++i)
{
if (ref_weights->GetValue(i)>0)
{
if (fabs( weights->GetValue(i)/ref_weights->GetValue(i)-1 )>0.01)
{
mitk::IOUtil::Save(test, mitk::IOUtil::GetTempPath()+out_name);
CPPUNIT_ASSERT_MESSAGE("Weights should be equal", false);
}
}
else if (weights->GetValue(i)>0)
{
mitk::IOUtil::Save(test, mitk::IOUtil::GetTempPath()+out_name);
CPPUNIT_ASSERT_MESSAGE("Weights should be equal", false);
}
}
}
void CompareImages(mitk::PeakImage::ItkPeakImageType::Pointer testImage, std::string name)
{
mitk::LocaleSwitch localeSwitch("C");
typedef mitk::ImageToItk< mitk::PeakImage::ItkPeakImageType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/FiberFit/out/" + name)));
caster->Update();
mitk::PeakImage::ItkPeakImageType::Pointer refImage = caster->GetOutput();
itk::ImageRegionConstIterator< mitk::PeakImage::ItkPeakImageType > it1(testImage, testImage->GetLargestPossibleRegion());
itk::ImageRegionConstIterator< mitk::PeakImage::ItkPeakImageType > it2(refImage, refImage->GetLargestPossibleRegion());
while(!it1.IsAtEnd())
{
if (it2.Get()>0.0001)
{
if (fabs( it1.Get()/it2.Get()-1 )>0.01)
{
itk::ImageFileWriter< mitk::PeakImage::ItkPeakImageType >::Pointer writer = itk::ImageFileWriter< mitk::PeakImage::ItkPeakImageType >::New();
writer->SetInput(testImage);
writer->SetFileName(mitk::IOUtil::GetTempPath()+name);
writer->Update();
MITK_INFO << it1.Get() << " - " << it2.Get();
CPPUNIT_ASSERT_MESSAGE("Peak images should be equal 1", false);
}
}
else if (it1.Get()>0.0001)
{
itk::ImageFileWriter< mitk::PeakImage::ItkPeakImageType >::Pointer writer = itk::ImageFileWriter< mitk::PeakImage::ItkPeakImageType >::New();
writer->SetInput(testImage);
writer->SetFileName(mitk::IOUtil::GetTempPath()+name);
writer->Update();
CPPUNIT_ASSERT_MESSAGE("Peak images should be equal 2", false);
}
++it1;
++it2;
}
}
void Fit1()
{
omp_set_num_threads(1);
// fitter->SetLambda(0.1);
fitter->SetFilterOutliers(false);
fitter->SetRegularization(VnlCostFunction::NONE);
fitter->Update();
std::vector< mitk::FiberBundle::Pointer > output_tracts = fitter->GetTractograms();
mitk::FiberBundle::Pointer test = mitk::FiberBundle::New();
test = test->AddBundles(output_tracts);
mitk::FiberBundle::Pointer ref = LoadFib("out/NONE_fitted.fib");
CompareFibs(test, ref, "NONE_fitted.fib");
CompareImages(fitter->GetFittedImage(), "NONE_fitted_image.nrrd");
CompareImages(fitter->GetResidualImage(), "NONE_residual_image.nrrd");
CompareImages(fitter->GetOverexplainedImage(), "NONE_underexplained_image.nrrd");
CompareImages(fitter->GetUnderexplainedImage(), "NONE_overexplained_image.nrrd");
}
void Fit2()
{
omp_set_num_threads(1);
// fitter->SetLambda(0.1);
fitter->SetFilterOutliers(false);
fitter->SetRegularization(VnlCostFunction::MSM);
fitter->Update();
std::vector< mitk::FiberBundle::Pointer > output_tracts = fitter->GetTractograms();
mitk::FiberBundle::Pointer test = mitk::FiberBundle::New();
test = test->AddBundles(output_tracts);
mitk::FiberBundle::Pointer ref = LoadFib("out/MSM_fitted.fib");
CompareFibs(test, ref, "MSM_fitted.fib");
CompareImages(fitter->GetFittedImage(), "MSM_fitted_image.nrrd");
CompareImages(fitter->GetResidualImage(), "MSM_residual_image.nrrd");
CompareImages(fitter->GetOverexplainedImage(), "MSM_underexplained_image.nrrd");
CompareImages(fitter->GetUnderexplainedImage(), "MSM_overexplained_image.nrrd");
}
void Fit3()
{
omp_set_num_threads(1);
// fitter->SetLambda(0.1);
fitter->SetFilterOutliers(false);
fitter->SetRegularization(VnlCostFunction::VARIANCE);
fitter->Update();
std::vector< mitk::FiberBundle::Pointer > output_tracts = fitter->GetTractograms();
mitk::FiberBundle::Pointer test = mitk::FiberBundle::New();
test = test->AddBundles(output_tracts);
mitk::FiberBundle::Pointer ref = LoadFib("out/MSE_fitted.fib");
CompareFibs(test, ref, "MSE_fitted.fib");
CompareImages(fitter->GetFittedImage(), "MSE_fitted_image.nrrd");
CompareImages(fitter->GetResidualImage(), "MSE_residual_image.nrrd");
CompareImages(fitter->GetOverexplainedImage(), "MSE_underexplained_image.nrrd");
CompareImages(fitter->GetUnderexplainedImage(), "MSE_overexplained_image.nrrd");
}
void Fit4()
{
omp_set_num_threads(1);
fitter->SetLambda(100);
fitter->SetFilterOutliers(false);
fitter->SetRegularization(VnlCostFunction::VOXEL_VARIANCE);
fitter->Update();
std::vector< mitk::FiberBundle::Pointer > output_tracts = fitter->GetTractograms();
mitk::FiberBundle::Pointer test = mitk::FiberBundle::New();
test = test->AddBundles(output_tracts);
mitk::FiberBundle::Pointer ref = LoadFib("out/LocalMSE_fitted.fib");
CompareFibs(test, ref, "LocalMSE_fitted.fib");
CompareImages(fitter->GetFittedImage(), "LocalMSE_fitted_image.nrrd");
CompareImages(fitter->GetResidualImage(), "LocalMSE_residual_image.nrrd");
CompareImages(fitter->GetOverexplainedImage(), "LocalMSE_underexplained_image.nrrd");
CompareImages(fitter->GetUnderexplainedImage(), "LocalMSE_overexplained_image.nrrd");
}
void Fit5()
{
omp_set_num_threads(1);
fitter->SetFilterOutliers(false);
fitter->SetRegularization(VnlCostFunction::GROUP_VARIANCE);
fitter->Update();
std::vector< mitk::FiberBundle::Pointer > output_tracts = fitter->GetTractograms();
mitk::FiberBundle::Pointer test = mitk::FiberBundle::New();
test = test->AddBundles(output_tracts);
mitk::FiberBundle::Pointer ref = LoadFib("out/GroupMSE_fitted.fib");
CompareFibs(test, ref, "GroupMSE_fitted.fib");
CompareImages(fitter->GetFittedImage(), "GroupMSE_fitted_image.nrrd");
CompareImages(fitter->GetResidualImage(), "GroupMSE_residual_image.nrrd");
CompareImages(fitter->GetOverexplainedImage(), "GroupMSE_underexplained_image.nrrd");
CompareImages(fitter->GetUnderexplainedImage(), "GroupMSE_overexplained_image.nrrd");
}
void Fit6()
{
omp_set_num_threads(1);
fitter->SetLambda(1000);
fitter->SetFilterOutliers(false);
fitter->SetRegularization(VnlCostFunction::GROUP_LASSO);
fitter->Update();
std::vector< mitk::FiberBundle::Pointer > output_tracts = fitter->GetTractograms();
mitk::FiberBundle::Pointer test = mitk::FiberBundle::New();
test = test->AddBundles(output_tracts);
mitk::FiberBundle::Pointer ref = LoadFib("out/GroupLasso_fitted.fib");
CompareFibs(test, ref, "GroupLasso_fitted.fib");
CompareImages(fitter->GetFittedImage(), "GroupLasso_fitted_image.nrrd");
CompareImages(fitter->GetResidualImage(), "GroupLasso_residual_image.nrrd");
CompareImages(fitter->GetOverexplainedImage(), "GroupLasso_underexplained_image.nrrd");
CompareImages(fitter->GetUnderexplainedImage(), "GroupLasso_overexplained_image.nrrd");
}
};
MITK_TEST_SUITE_REGISTRATION(mitkFiberFit)
diff --git a/Modules/MriSimulation/Testing/mitkFiberGenerationTest.cpp b/Modules/MriSimulation/Testing/mitkFiberGenerationTest.cpp
index 348281f..d3e7df5 100644
--- a/Modules/MriSimulation/Testing/mitkFiberGenerationTest.cpp
+++ b/Modules/MriSimulation/Testing/mitkFiberGenerationTest.cpp
@@ -1,81 +1,81 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkTestingMacros.h>
#include <mitkIOUtil.h>
#include <mitkFiberBundle.h>
#include <mitkPlanarEllipse.h>
#include <itkFibersFromPlanarFiguresFilter.h>
#include <omp.h>
/**Documentation
* Test if fiber transfortaiom methods work correctly
*/
int mitkFiberGenerationTest(int argc, char* argv[])
{
omp_set_num_threads(1);
MITK_TEST_BEGIN("mitkFiberGenerationTest");
MITK_TEST_CONDITION_REQUIRED(argc==6,"check for input data")
try{
mitk::PlanarEllipse::Pointer pf1 = mitk::IOUtil::Load<mitk::PlanarEllipse>(argv[1]);
mitk::PlanarEllipse::Pointer pf2 = mitk::IOUtil::Load<mitk::PlanarEllipse>(argv[2]);
mitk::PlanarEllipse::Pointer pf3 = mitk::IOUtil::Load<mitk::PlanarEllipse>(argv[3]);
mitk::FiberBundle::Pointer uniform = mitk::IOUtil::Load<mitk::FiberBundle>(argv[4]);
mitk::FiberBundle::Pointer gaussian = mitk::IOUtil::Load<mitk::FiberBundle>(argv[5]);
FiberGenerationParameters parameters;
std::vector< mitk::PlanarEllipse::Pointer > fid; fid.push_back(pf1); fid.push_back(pf2); fid.push_back(pf3);
std::vector< unsigned int > flip; flip.push_back(0); flip.push_back(0); flip.push_back(0);
parameters.m_Fiducials.push_back(fid); parameters.m_FlipList.push_back(flip);
parameters.m_Density = 50;
parameters.m_Tension = 0;
parameters.m_Continuity = 0;
parameters.m_Bias = 0;
parameters.m_Sampling = 1;
parameters.m_Variance = 0.1;
// check uniform fiber distribution
{
itk::FibersFromPlanarFiguresFilter::Pointer filter = itk::FibersFromPlanarFiguresFilter::New();
parameters.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM;
filter->SetParameters(parameters);
filter->SetFixSeed(true);
filter->Update();
std::vector< mitk::FiberBundle::Pointer > fiberBundles = filter->GetFiberBundles();
MITK_TEST_CONDITION_REQUIRED(uniform->Equals(fiberBundles.at(0)),"check uniform bundle")
}
// check gaussian fiber distribution
{
itk::FibersFromPlanarFiguresFilter::Pointer filter = itk::FibersFromPlanarFiguresFilter::New();
parameters.m_Distribution = FiberGenerationParameters::DISTRIBUTE_GAUSSIAN;
filter->SetParameters(parameters);
filter->SetFixSeed(true);
filter->Update();
std::vector< mitk::FiberBundle::Pointer > fiberBundles = filter->GetFiberBundles();
MITK_TEST_CONDITION_REQUIRED(gaussian->Equals(fiberBundles.at(0)),"check gaussian bundle")
}
}
catch(...) {
return EXIT_FAILURE;
}
// always end with this!
MITK_TEST_END();
}
diff --git a/Modules/MriSimulation/Testing/mitkFiberfoxSignalGenerationBrainSliceTest.cpp b/Modules/MriSimulation/Testing/mitkFiberfoxSignalGenerationBrainSliceTest.cpp
index 95ffd93..de2eb40 100644
--- a/Modules/MriSimulation/Testing/mitkFiberfoxSignalGenerationBrainSliceTest.cpp
+++ b/Modules/MriSimulation/Testing/mitkFiberfoxSignalGenerationBrainSliceTest.cpp
@@ -1,206 +1,206 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkTestingMacros.h>
#include <mitkIOUtil.h>
#include <mitkFiberBundle.h>
#include <itkTractsToDWIImageFilter.h>
#include <mitkFiberfoxParameters.h>
#include <mitkStickModel.h>
#include <mitkTensorModel.h>
#include <mitkBallModel.h>
#include <mitkDotModel.h>
#include <mitkAstroStickModel.h>
#include <mitkImage.h>
#include <itkTestingComparisonImageFilter.h>
#include <itkImageRegionConstIterator.h>
#include <mitkRicianNoiseModel.h>
#include <mitkChiSquareNoiseModel.h>
#include <mitkIOUtil.h>
#include <mitkDiffusionPropertyHelper.h>
#include <mitkProperties.h>
#include <mitkITKImageImport.h>
#include <mitkImageCast.h>
#include <itkVectorImage.h>
#include "mitkTestFixture.h"
class mitkFiberfoxSignalGenerationBrainSliceTestSuite : public mitk::TestFixture
{
CPPUNIT_TEST_SUITE(mitkFiberfoxSignalGenerationBrainSliceTestSuite);
MITK_TEST(Test1);
MITK_TEST(Test2);
MITK_TEST(Test3);
MITK_TEST(Test4);
MITK_TEST(Test5);
CPPUNIT_TEST_SUITE_END();
typedef itk::VectorImage< short, 3> ItkDwiType;
private:
public:
/** Members used inside the different (sub-)tests. All members are initialized via setUp().*/
FiberBundle::Pointer m_FiberBundle;
mitk::Image::Pointer m_Template;
void setUp() override
{
m_FiberBundle = mitk::IOUtil::Load<FiberBundle>(GetTestDataFilePath("DiffusionImaging/Fiberfox/SignalGen_BrainSlice.fib"));
m_Template = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/Fiberfox/SignalGen_BrainSliceTemplate.nii.gz"));
}
void adjust_to_template(mitk::FiberfoxParameters& parameters)
{
typedef itk::Image< short, 3 > ItkImageType;
ItkImageType::Pointer itkImagePointer = ItkImageType::New();
mitk::CastToItkImage(m_Template, itkImagePointer);
parameters.m_SignalGen.m_ImageRegion = itkImagePointer->GetLargestPossibleRegion();
parameters.m_SignalGen.m_ImageSpacing = itkImagePointer->GetSpacing();
parameters.m_SignalGen.m_ImageOrigin = itkImagePointer->GetOrigin();
parameters.m_SignalGen.m_ImageDirection = itkImagePointer->GetDirection();
}
void tearDown() override
{
}
bool CompareDwi(itk::VectorImage< short, 3 >* dwi1, itk::VectorImage< short, 3 >* dwi2)
{
bool out = true;
typedef itk::VectorImage< short, 3 > DwiImageType;
try{
itk::ImageRegionIterator< DwiImageType > it1(dwi1, dwi1->GetLargestPossibleRegion());
itk::ImageRegionIterator< DwiImageType > it2(dwi2, dwi2->GetLargestPossibleRegion());
int count = 0;
while(!it1.IsAtEnd())
{
for (unsigned int i=0; i<dwi1->GetVectorLength(); ++i)
{
short d = abs(it1.Get()[i]-it2.Get()[i]);
if (d>1)
{
if (count<10)
{
MITK_INFO << "**************************************";
MITK_INFO << "Test value: " << it1.GetIndex() << ":" << it1.Get()[i];
MITK_INFO << "Ref. value: " << it2.GetIndex() << ":" << it2.Get()[i];
}
out = false;
count++;
}
}
++it1;
++it2;
}
if (count>=10)
MITK_INFO << "Skipping errors.";
MITK_INFO << "Errors detected: " << count;
}
catch(...)
{
return false;
}
return out;
}
void StartSimulation(FiberfoxParameters parameters, mitk::Image::Pointer refImage, std::string out)
{
itk::TractsToDWIImageFilter< short >::Pointer tractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New();
tractsToDwiFilter->SetUseConstantRandSeed(true);
tractsToDwiFilter->SetParameters(parameters);
tractsToDwiFilter->SetFiberBundle(m_FiberBundle);
tractsToDwiFilter->Update();
mitk::Image::Pointer testImage = mitk::GrabItkImageMemory( tractsToDwiFilter->GetOutput() );
mitk::DiffusionPropertyHelper::SetGradientContainer(testImage, parameters.m_SignalGen.GetItkGradientContainer());
mitk::DiffusionPropertyHelper::SetReferenceBValue(testImage, parameters.m_SignalGen.GetBvalue());
mitk::DiffusionPropertyHelper::InitializeImage( testImage );
if (refImage.IsNotNull())
{
if(mitk::DiffusionPropertyHelper::GetGradientContainer(refImage).IsNotNull() )
{
ItkDwiType::Pointer itkTestImagePointer = ItkDwiType::New();
mitk::CastToItkImage(testImage, itkTestImagePointer);
ItkDwiType::Pointer itkRefImagePointer = ItkDwiType::New();
mitk::CastToItkImage(refImage, itkRefImagePointer);
bool cond = CompareDwi(itkTestImagePointer, itkRefImagePointer);
if (!cond)
{
MITK_INFO << "Saving test image to " << mitk::IOUtil::GetTempPath()+out;
mitk::IOUtil::Save(testImage, "DWI_NIFTI", mitk::IOUtil::GetTempPath()+out);
mitk::IOUtil::Save(refImage, "DWI_NIFTI", mitk::IOUtil::GetTempPath()+ "REF_" + out);
}
CPPUNIT_ASSERT_MESSAGE("Simulated images should be equal", cond);
}
}
}
void Test1()
{
FiberfoxParameters parameters;
parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/BrainSlice_1.ffp"), true);
adjust_to_template(parameters);
mitk::Image::Pointer refImage = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/BrainSlice_1_OUT.nii.gz"));
StartSimulation(parameters, refImage, "BrainSlice_1_OUT.nii.gz");
}
void Test2()
{
FiberfoxParameters parameters;
parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/BrainSlice_2.ffp"), true);
adjust_to_template(parameters);
mitk::Image::Pointer refImage = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/BrainSlice_2_OUT.nii.gz"));
StartSimulation(parameters, refImage, "BrainSlice_2_OUT.nii.gz");
}
void Test3()
{
FiberfoxParameters parameters;
parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/BrainSlice_3.ffp"), true);
adjust_to_template(parameters);
mitk::Image::Pointer refImage = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/BrainSlice_3_OUT.nii.gz"));
StartSimulation(parameters, refImage, "BrainSlice_3_OUT.nii.gz");
}
void Test4()
{
FiberfoxParameters parameters;
parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/BrainSlice_4.ffp"), true);
adjust_to_template(parameters);
mitk::Image::Pointer refImage = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/BrainSlice_4_OUT.nii.gz"));
StartSimulation(parameters, refImage, "BrainSlice_4_OUT.nii.gz");
}
void Test5()
{
FiberfoxParameters parameters;
parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/BrainSlice_5.ffp"), true);
adjust_to_template(parameters);
mitk::Image::Pointer refImage = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/BrainSlice_5_OUT.nii.gz"));
StartSimulation(parameters, refImage, "BrainSlice_5_OUT.nii.gz");
}
};
MITK_TEST_SUITE_REGISTRATION(mitkFiberfoxSignalGenerationBrainSlice)
diff --git a/Modules/MriSimulation/Testing/mitkFiberfoxSignalGenerationTest.cpp b/Modules/MriSimulation/Testing/mitkFiberfoxSignalGenerationTest.cpp
index 55f45d6..25c5747 100644
--- a/Modules/MriSimulation/Testing/mitkFiberfoxSignalGenerationTest.cpp
+++ b/Modules/MriSimulation/Testing/mitkFiberfoxSignalGenerationTest.cpp
@@ -1,226 +1,226 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <mitkTestingMacros.h>
#include <mitkIOUtil.h>
#include <mitkFiberBundle.h>
#include <itkTractsToDWIImageFilter.h>
#include <mitkFiberfoxParameters.h>
#include <mitkStickModel.h>
#include <mitkTensorModel.h>
#include <mitkBallModel.h>
#include <mitkDotModel.h>
#include <mitkAstroStickModel.h>
#include <mitkImage.h>
#include <itkTestingComparisonImageFilter.h>
#include <itkImageRegionConstIterator.h>
#include <mitkRicianNoiseModel.h>
#include <mitkChiSquareNoiseModel.h>
#include <mitkIOUtil.h>
#include <mitkDiffusionPropertyHelper.h>
#include <mitkProperties.h>
#include <mitkITKImageImport.h>
#include <mitkImageCast.h>
#include <itkVectorImage.h>
#include <omp.h>
#include "mitkTestFixture.h"
class mitkFiberfoxSignalGenerationTestSuite : public mitk::TestFixture
{
CPPUNIT_TEST_SUITE(mitkFiberfoxSignalGenerationTestSuite);
MITK_TEST(Test1);
MITK_TEST(Test2);
MITK_TEST(Test3);
MITK_TEST(Test4);
MITK_TEST(Test5);
MITK_TEST(Test6);
MITK_TEST(Test7);
MITK_TEST(Test8);
MITK_TEST(Test9);
CPPUNIT_TEST_SUITE_END();
typedef itk::VectorImage< short, 3> ItkDwiType;
private:
public:
/** Members used inside the different (sub-)tests. All members are initialized via setUp().*/
FiberBundle::Pointer m_FiberBundle;
void setUp() override
{
m_FiberBundle = mitk::IOUtil::Load<FiberBundle>(GetTestDataFilePath("DiffusionImaging/Fiberfox/Signalgen.fib"));
}
void tearDown() override
{
}
bool CompareDwi(itk::VectorImage< short, 3 >* dwi1, itk::VectorImage< short, 3 >* dwi2)
{
bool out = true;
typedef itk::VectorImage< short, 3 > DwiImageType;
try{
itk::ImageRegionIterator< DwiImageType > it1(dwi1, dwi1->GetLargestPossibleRegion());
itk::ImageRegionIterator< DwiImageType > it2(dwi2, dwi2->GetLargestPossibleRegion());
int count = 0;
while(!it1.IsAtEnd())
{
for (unsigned int i=0; i<dwi1->GetVectorLength(); ++i)
{
short d = abs(it1.Get()[i]-it2.Get()[i]);
if (d>1)
{
if (count<10)
{
MITK_INFO << "**************************************";
MITK_INFO << "Test value: " << it1.GetIndex() << ":" << it1.Get()[i];
MITK_INFO << "Ref. value: " << it2.GetIndex() << ":" << it2.Get()[i];
}
out = false;
count++;
}
}
++it1;
++it2;
}
if (count>=10)
MITK_INFO << "Skipping errors.";
MITK_INFO << "Errors detected: " << count;
}
catch(...)
{
return false;
}
return out;
}
void StartSimulation(FiberfoxParameters parameters, mitk::Image::Pointer refImage, std::string out)
{
itk::TractsToDWIImageFilter< short >::Pointer tractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New();
tractsToDwiFilter->SetUseConstantRandSeed(true);
tractsToDwiFilter->SetParameters(parameters);
tractsToDwiFilter->SetFiberBundle(m_FiberBundle);
tractsToDwiFilter->Update();
mitk::Image::Pointer testImage = mitk::GrabItkImageMemory( tractsToDwiFilter->GetOutput() );
mitk::DiffusionPropertyHelper::SetGradientContainer(testImage, parameters.m_SignalGen.GetItkGradientContainer());
mitk::DiffusionPropertyHelper::SetReferenceBValue(testImage, parameters.m_SignalGen.GetBvalue());
mitk::DiffusionPropertyHelper::InitializeImage( testImage );
if (refImage.IsNotNull())
{
if(mitk::DiffusionPropertyHelper::GetGradientContainer(refImage).IsNotNull() )
{
ItkDwiType::Pointer itkTestImagePointer = ItkDwiType::New();
mitk::CastToItkImage(testImage, itkTestImagePointer);
ItkDwiType::Pointer itkRefImagePointer = ItkDwiType::New();
mitk::CastToItkImage(refImage, itkRefImagePointer);
bool cond = CompareDwi(itkTestImagePointer, itkRefImagePointer);
if (!cond)
{
MITK_INFO << "Saving test image to " << mitk::IOUtil::GetTempPath()+out;
mitk::IOUtil::Save(testImage, mitk::IOUtil::GetTempPath()+out);
mitk::IOUtil::Save(refImage, mitk::IOUtil::GetTempPath()+ "REF_" + out);
}
CPPUNIT_ASSERT_MESSAGE("Simulated images should be equal", cond);
}
}
}
void Test1()
{
FiberfoxParameters parameters;
parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param1.ffp"), true);
mitk::Image::Pointer refImage = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param1.dwi"));
StartSimulation(parameters, refImage, "param1.dwi");
}
void Test2()
{
FiberfoxParameters parameters;
parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param2.ffp"), true);
mitk::Image::Pointer refImage = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param2.dwi"));
StartSimulation(parameters, refImage, "param2.dwi");
}
void Test3()
{
FiberfoxParameters parameters;
parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param3.ffp"), true);
mitk::Image::Pointer refImage = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param3.dwi"));
StartSimulation(parameters, refImage, "param3.dwi");
}
void Test4()
{
FiberfoxParameters parameters;
parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param4.ffp"), true);
mitk::Image::Pointer refImage = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param4.dwi"));
StartSimulation(parameters, refImage, "param4.dwi");
}
void Test5()
{
FiberfoxParameters parameters;
parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param5.ffp"), true);
mitk::Image::Pointer refImage = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param5.dwi"));
StartSimulation(parameters, refImage, "param5.dwi");
}
void Test6()
{
FiberfoxParameters parameters;
parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param6.ffp"), true);
mitk::Image::Pointer refImage = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param6.dwi"));
StartSimulation(parameters, refImage, "param6.dwi");
}
void Test7()
{
FiberfoxParameters parameters;
parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param7.ffp"), true);
mitk::Image::Pointer refImage = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param7.dwi"));
StartSimulation(parameters, refImage, "param7.dwi");
}
void Test8()
{
FiberfoxParameters parameters;
parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param8.ffp"), true);
mitk::Image::Pointer refImage = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param8.dwi"));
StartSimulation(parameters, refImage, "param8.dwi");
}
void Test9()
{
FiberfoxParameters parameters;
parameters.LoadParameters(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param9.ffp"), true);
mitk::Image::Pointer refImage = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("DiffusionImaging/Fiberfox/params/param9.dwi"));
StartSimulation(parameters, refImage, "param9.dwi");
}
};
MITK_TEST_SUITE_REGISTRATION(mitkFiberfoxSignalGeneration)
diff --git a/Modules/MriSimulation/mitkFiberfoxParameters.cpp b/Modules/MriSimulation/mitkFiberfoxParameters.cpp
index 17e86b9..25ec943 100644
--- a/Modules/MriSimulation/mitkFiberfoxParameters.cpp
+++ b/Modules/MriSimulation/mitkFiberfoxParameters.cpp
@@ -1,1083 +1,1083 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
#define RAPIDXML_NO_EXCEPTIONS
#include <boost/foreach.hpp>
#include <mitkLexicalCast.h>
#include <itkImageFileWriter.h>
#include <itkImageFileReader.h>
#include <mitkLog.h>
#include <algorithm>
#include <string>
#include <mitkFiberfoxParameters.h>
#include <mitkDiffusionFunctionCollection.h>
mitk::FiberfoxParameters::FiberfoxParameters()
: m_NoiseModel(nullptr)
{
mitk::StickModel<ScalarType>* model_aniso = new mitk::StickModel<ScalarType>();
model_aniso->m_CompartmentId = 1;
m_FiberModelList.push_back(model_aniso);
mitk::BallModel<ScalarType>* model_iso = new mitk::BallModel<ScalarType>();
model_iso->m_CompartmentId = 3;
m_NonFiberModelList.push_back(model_iso);
}
mitk::FiberfoxParameters::FiberfoxParameters(const mitk::FiberfoxParameters& params)
: m_NoiseModel(nullptr)
{
m_FiberGen = params.m_FiberGen;
m_SignalGen = params.m_SignalGen;
m_Misc = params.m_Misc;
if (params.m_NoiseModel!=nullptr)
{
if (dynamic_cast<mitk::RicianNoiseModel<>*>(params.m_NoiseModel.get()))
m_NoiseModel = std::make_shared< mitk::RicianNoiseModel<> >();
else if (dynamic_cast<mitk::ChiSquareNoiseModel<>*>(params.m_NoiseModel.get()))
m_NoiseModel = std::make_shared< mitk::ChiSquareNoiseModel<> >();
m_NoiseModel->SetNoiseVariance(params.m_NoiseModel->GetNoiseVariance());
}
for (unsigned int i=0; i<params.m_FiberModelList.size()+params.m_NonFiberModelList.size(); i++)
{
mitk::DiffusionSignalModel<>* outModel = nullptr;
mitk::DiffusionSignalModel<>* signalModel = nullptr;
if (i<params.m_FiberModelList.size())
signalModel = params.m_FiberModelList.at(i);
else
signalModel = params.m_NonFiberModelList.at(i-params.m_FiberModelList.size());
if (dynamic_cast<mitk::StickModel<>*>(signalModel))
outModel = new mitk::StickModel<>(dynamic_cast<mitk::StickModel<>*>(signalModel));
else if (dynamic_cast<mitk::TensorModel<>*>(signalModel))
outModel = new mitk::TensorModel<>(dynamic_cast<mitk::TensorModel<>*>(signalModel));
else if (dynamic_cast<mitk::RawShModel<>*>(signalModel))
outModel = new mitk::RawShModel<>(dynamic_cast<mitk::RawShModel<>*>(signalModel));
else if (dynamic_cast<mitk::BallModel<>*>(signalModel))
outModel = new mitk::BallModel<>(dynamic_cast<mitk::BallModel<>*>(signalModel));
else if (dynamic_cast<mitk::AstroStickModel<>*>(signalModel))
outModel = new mitk::AstroStickModel<>(dynamic_cast<mitk::AstroStickModel<>*>(signalModel));
else if (dynamic_cast<mitk::DotModel<>*>(signalModel))
outModel = new mitk::DotModel<>(dynamic_cast<mitk::DotModel<>*>(signalModel));
if (i<params.m_FiberModelList.size())
m_FiberModelList.push_back(outModel);
else
m_NonFiberModelList.push_back(outModel);
}
}
void mitk::FiberfoxParameters::ClearFiberParameters()
{
m_Misc = MiscFiberfoxParameters();
m_FiberGen = FiberGenerationParameters();
}
void mitk::FiberfoxParameters::ClearSignalParameters()
{
m_Misc = MiscFiberfoxParameters();
m_SignalGen = SignalGenerationParameters();
m_FiberModelList.clear();
m_NonFiberModelList.clear();
m_NoiseModel = nullptr;
m_MissingTags = "";
}
mitk::FiberfoxParameters::~FiberfoxParameters()
{
}
void mitk::SignalGenerationParameters::GenerateGradientHalfShell()
{
int NPoints = 2*m_NumGradients;
m_GradientDirections.clear();
m_NumBaseline = NPoints/20;
if (m_NumBaseline==0)
m_NumBaseline=1;
GradientType g;
g.Fill(0.0);
for (unsigned int i=0; i<m_NumBaseline; i++)
m_GradientDirections.push_back(g);
if (NPoints==0)
return;
vnl_vector<double> theta; theta.set_size(NPoints);
vnl_vector<double> phi; phi.set_size(NPoints);
double C = sqrt(4*itk::Math::pi);
phi(0) = 0.0;
phi(NPoints-1) = 0.0;
for(int i=0; i<NPoints; i++)
{
theta(i) = acos(-1.0+2.0*i/(NPoints-1.0)) - itk::Math::pi / 2.0;
if( i>0 && i<NPoints-1)
{
phi(i) = (phi(i-1) + C /
sqrt(NPoints*(1-(-1.0+2.0*i/(NPoints-1.0))*(-1.0+2.0*i/(NPoints-1.0)))));
}
}
for(int i=0; i<NPoints; i++)
{
g[2] = sin(theta(i));
if (g[2]<0)
continue;
g[0] = cos(theta(i)) * cos(phi(i));
g[1] = cos(theta(i)) * sin(phi(i));
m_GradientDirections.push_back(g);
}
}
std::vector< int > mitk::SignalGenerationParameters::GetBaselineIndices()
{
std::vector< int > result;
for( unsigned int i=0; i<this->m_GradientDirections.size(); i++)
if (m_GradientDirections.at(i).GetNorm()<0.0001)
result.push_back(i);
return result;
}
unsigned int mitk::SignalGenerationParameters::GetFirstBaselineIndex()
{
for( unsigned int i=0; i<this->m_GradientDirections.size(); i++)
if (m_GradientDirections.at(i).GetNorm()<0.0001)
return i;
return -1;
}
bool mitk::SignalGenerationParameters::IsBaselineIndex(unsigned int idx)
{
if (m_GradientDirections.size()>idx && m_GradientDirections.at(idx).GetNorm()<0.0001)
return true;
return false;
}
unsigned int mitk::SignalGenerationParameters::GetNumWeightedVolumes()
{
return m_NumGradients;
}
unsigned int mitk::SignalGenerationParameters::GetNumBaselineVolumes()
{
return m_NumBaseline;
}
unsigned int mitk::SignalGenerationParameters::GetNumVolumes()
{
return m_GradientDirections.size();
}
mitk::SignalGenerationParameters::GradientListType mitk::SignalGenerationParameters::GetGradientDirections()
{
return m_GradientDirections;
}
mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer mitk::SignalGenerationParameters::GetItkGradientContainer()
{
int c = 0;
mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer out = mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::New();
for (auto g : m_GradientDirections)
{
mitk::DiffusionPropertyHelper::GradientDirectionType vnl_dir;
vnl_dir[0] = g[0];
vnl_dir[1] = g[1];
vnl_dir[2] = g[2];
out->InsertElement(c, vnl_dir);
++c;
}
return out;
}
mitk::SignalGenerationParameters::GradientType mitk::SignalGenerationParameters::GetGradientDirection(unsigned int i)
{
return m_GradientDirections.at(i);
}
void mitk::SignalGenerationParameters::SetNumWeightedVolumes(int numGradients)
{
m_NumGradients = numGradients;
GenerateGradientHalfShell();
}
std::vector< int > mitk::SignalGenerationParameters::GetBvalues()
{
std::vector< int > bVals;
for( GradientType g : m_GradientDirections)
{
float norm = g.GetNorm();
int bVal = std::round(norm*norm*m_Bvalue);
if ( std::find(bVals.begin(), bVals.end(), bVal) == bVals.end() )
bVals.push_back(bVal);
}
return bVals;
}
double mitk::SignalGenerationParameters::GetBvalue()
{
return m_Bvalue;
}
void mitk::SignalGenerationParameters::SetGradienDirections(GradientListType gradientList)
{
m_GradientDirections = gradientList;
m_NumGradients = 0;
m_NumBaseline = 0;
for( unsigned int i=0; i<this->m_GradientDirections.size(); i++)
{
float norm = m_GradientDirections.at(i).GetNorm();
if (norm>0.0001)
m_NumGradients++;
else
m_NumBaseline++;
}
}
void mitk::SignalGenerationParameters::SetGradienDirections(mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradientList)
{
m_NumGradients = 0;
m_NumBaseline = 0;
m_GradientDirections.clear();
for( unsigned int i=0; i<gradientList->Size(); i++)
{
GradientType g;
g[0] = gradientList->at(i)[0];
g[1] = gradientList->at(i)[1];
g[2] = gradientList->at(i)[2];
m_GradientDirections.push_back(g);
float norm = m_GradientDirections.at(i).GetNorm();
if (norm>0.0001)
m_NumGradients++;
else
m_NumBaseline++;
}
}
void mitk::SignalGenerationParameters::ApplyDirectionMatrix()
{
auto imageRotationMatrix = m_ImageDirection.GetVnlMatrix();
GradientListType rotated_gradients;
for(auto g : m_GradientDirections)
{
vnl_vector<double> vec = g.GetVnlVector();
vec = vec.pre_multiply(imageRotationMatrix);
GradientType g2;
g2[0] = vec[0];
g2[1] = vec[1];
g2[2] = vec[2];
rotated_gradients.push_back(g2);
}
m_GradientDirections = rotated_gradients;
}
void mitk::FiberfoxParameters::ApplyDirectionMatrix()
{
m_SignalGen.ApplyDirectionMatrix();
UpdateSignalModels();
}
void mitk::FiberfoxParameters::SaveParameters(std::string filename)
{
if(filename.empty())
return;
if(".ffp"!=filename.substr(filename.size()-4, 4))
filename += ".ffp";
const std::string& locale = "C";
const std::string& currLocale = setlocale( LC_ALL, nullptr );
if ( locale.compare(currLocale)!=0 )
{
try
{
setlocale(LC_ALL, locale.c_str());
}
catch(...)
{
MITK_INFO << "Could not set locale " << locale;
}
}
boost::property_tree::ptree parameters;
// fiber generation parameters
parameters.put("fiberfox.fibers.distribution", m_FiberGen.m_Distribution);
parameters.put("fiberfox.fibers.variance", m_FiberGen.m_Variance);
parameters.put("fiberfox.fibers.density", m_FiberGen.m_Density);
parameters.put("fiberfox.fibers.spline.sampling", m_FiberGen.m_Sampling);
parameters.put("fiberfox.fibers.spline.tension", m_FiberGen.m_Tension);
parameters.put("fiberfox.fibers.spline.continuity", m_FiberGen.m_Continuity);
parameters.put("fiberfox.fibers.spline.bias", m_FiberGen.m_Bias);
parameters.put("fiberfox.fibers.rotation.x", m_FiberGen.m_Rotation[0]);
parameters.put("fiberfox.fibers.rotation.y", m_FiberGen.m_Rotation[1]);
parameters.put("fiberfox.fibers.rotation.z", m_FiberGen.m_Rotation[2]);
parameters.put("fiberfox.fibers.translation.x", m_FiberGen.m_Translation[0]);
parameters.put("fiberfox.fibers.translation.y", m_FiberGen.m_Translation[1]);
parameters.put("fiberfox.fibers.translation.z", m_FiberGen.m_Translation[2]);
parameters.put("fiberfox.fibers.scale.x", m_FiberGen.m_Scale[0]);
parameters.put("fiberfox.fibers.scale.y", m_FiberGen.m_Scale[1]);
parameters.put("fiberfox.fibers.scale.z", m_FiberGen.m_Scale[2]);
// image generation parameters
parameters.put("fiberfox.image.basic.size.x", m_SignalGen.m_ImageRegion.GetSize(0));
parameters.put("fiberfox.image.basic.size.y", m_SignalGen.m_ImageRegion.GetSize(1));
parameters.put("fiberfox.image.basic.size.z", m_SignalGen.m_ImageRegion.GetSize(2));
parameters.put("fiberfox.image.basic.spacing.x", m_SignalGen.m_ImageSpacing[0]);
parameters.put("fiberfox.image.basic.spacing.y", m_SignalGen.m_ImageSpacing[1]);
parameters.put("fiberfox.image.basic.spacing.z", m_SignalGen.m_ImageSpacing[2]);
parameters.put("fiberfox.image.basic.origin.x", m_SignalGen.m_ImageOrigin[0]);
parameters.put("fiberfox.image.basic.origin.y", m_SignalGen.m_ImageOrigin[1]);
parameters.put("fiberfox.image.basic.origin.z", m_SignalGen.m_ImageOrigin[2]);
parameters.put("fiberfox.image.basic.direction.d1", m_SignalGen.m_ImageDirection[0][0]);
parameters.put("fiberfox.image.basic.direction.d2", m_SignalGen.m_ImageDirection[0][1]);
parameters.put("fiberfox.image.basic.direction.d3", m_SignalGen.m_ImageDirection[0][2]);
parameters.put("fiberfox.image.basic.direction.d4", m_SignalGen.m_ImageDirection[1][0]);
parameters.put("fiberfox.image.basic.direction.d5", m_SignalGen.m_ImageDirection[1][1]);
parameters.put("fiberfox.image.basic.direction.d6", m_SignalGen.m_ImageDirection[1][2]);
parameters.put("fiberfox.image.basic.direction.d7", m_SignalGen.m_ImageDirection[2][0]);
parameters.put("fiberfox.image.basic.direction.d8", m_SignalGen.m_ImageDirection[2][1]);
parameters.put("fiberfox.image.basic.direction.d9", m_SignalGen.m_ImageDirection[2][2]);
mitk::gradients::WriteBvalsBvecs(filename+".bvals", filename+".bvecs", m_SignalGen.GetItkGradientContainer(), m_SignalGen.m_Bvalue);
parameters.put("fiberfox.image.acquisitiontype", m_SignalGen.m_AcquisitionType);
parameters.put("fiberfox.image.coilsensitivityprofile", m_SignalGen.m_CoilSensitivityProfile);
parameters.put("fiberfox.image.numberofcoils", m_SignalGen.m_NumberOfCoils);
parameters.put("fiberfox.image.reversephase", m_SignalGen.m_ReversePhase);
parameters.put("fiberfox.image.partialfourier", m_SignalGen.m_PartialFourier);
parameters.put("fiberfox.image.noisevariance", m_SignalGen.m_NoiseVariance);
parameters.put("fiberfox.image.trep", m_SignalGen.m_tRep);
parameters.put("fiberfox.image.tinv", m_SignalGen.m_tInv);
parameters.put("fiberfox.image.signalScale", m_SignalGen.m_SignalScale);
parameters.put("fiberfox.image.tEcho", m_SignalGen.m_tEcho);
parameters.put("fiberfox.image.tLine", m_SignalGen.m_tLine);
parameters.put("fiberfox.image.tInhom", m_SignalGen.m_tInhom);
parameters.put("fiberfox.image.echoTrainLength", m_SignalGen.m_EchoTrainLength);
parameters.put("fiberfox.image.simulatekspace", m_SignalGen.m_SimulateKspaceAcquisition);
parameters.put("fiberfox.image.axonRadius", m_SignalGen.m_AxonRadius);
parameters.put("fiberfox.image.doSimulateRelaxation", m_SignalGen.m_DoSimulateRelaxation);
parameters.put("fiberfox.image.doDisablePartialVolume", m_SignalGen.m_DoDisablePartialVolume);
parameters.put("fiberfox.image.artifacts.spikesnum", m_SignalGen.m_Spikes);
parameters.put("fiberfox.image.artifacts.spikesscale", m_SignalGen.m_SpikeAmplitude);
parameters.put("fiberfox.image.artifacts.kspaceLineOffset", m_SignalGen.m_KspaceLineOffset);
parameters.put("fiberfox.image.artifacts.eddyStrength", m_SignalGen.m_EddyStrength);
parameters.put("fiberfox.image.artifacts.eddyTau", m_SignalGen.m_Tau);
parameters.put("fiberfox.image.artifacts.aliasingfactor", m_SignalGen.m_CroppingFactor);
parameters.put("fiberfox.image.artifacts.drift", m_SignalGen.m_Drift);
parameters.put("fiberfox.image.artifacts.doAddMotion", m_SignalGen.m_DoAddMotion);
parameters.put("fiberfox.image.artifacts.randomMotion", m_SignalGen.m_DoRandomizeMotion);
parameters.put("fiberfox.image.artifacts.translation0", m_SignalGen.m_Translation[0]);
parameters.put("fiberfox.image.artifacts.translation1", m_SignalGen.m_Translation[1]);
parameters.put("fiberfox.image.artifacts.translation2", m_SignalGen.m_Translation[2]);
parameters.put("fiberfox.image.artifacts.rotation0", m_SignalGen.m_Rotation[0]);
parameters.put("fiberfox.image.artifacts.rotation1", m_SignalGen.m_Rotation[1]);
parameters.put("fiberfox.image.artifacts.rotation2", m_SignalGen.m_Rotation[2]);
parameters.put("fiberfox.image.artifacts.motionvolumes", m_Misc.m_MotionVolumesBox);
parameters.put("fiberfox.image.artifacts.addringing", m_SignalGen.m_DoAddGibbsRinging);
parameters.put("fiberfox.image.artifacts.zeroringing", m_SignalGen.m_ZeroRinging);
parameters.put("fiberfox.image.artifacts.addnoise", m_Misc.m_DoAddNoise);
parameters.put("fiberfox.image.artifacts.addghosts", m_Misc.m_DoAddGhosts);
parameters.put("fiberfox.image.artifacts.addaliasing", m_Misc.m_DoAddAliasing);
parameters.put("fiberfox.image.artifacts.addspikes", m_Misc.m_DoAddSpikes);
parameters.put("fiberfox.image.artifacts.addeddycurrents", m_Misc.m_DoAddEddyCurrents);
parameters.put("fiberfox.image.artifacts.doAddDistortions", m_Misc.m_DoAddDistortions);
parameters.put("fiberfox.image.artifacts.doAddDrift", m_SignalGen.m_DoAddDrift);
parameters.put("fiberfox.image.outputvolumefractions", m_Misc.m_OutputAdditionalImages);
parameters.put("fiberfox.image.showadvanced", m_Misc.m_CheckAdvancedSignalOptionsBox);
parameters.put("fiberfox.image.signalmodelstring", m_Misc.m_SignalModelString);
parameters.put("fiberfox.image.artifactmodelstring", m_Misc.m_ArtifactModelString);
parameters.put("fiberfox.image.outpath", m_Misc.m_OutputPath);
parameters.put("fiberfox.fibers.realtime", m_Misc.m_CheckRealTimeFibersBox);
parameters.put("fiberfox.fibers.showadvanced", m_Misc.m_CheckAdvancedFiberOptionsBox);
parameters.put("fiberfox.fibers.constantradius", m_Misc.m_CheckConstantRadiusBox);
parameters.put("fiberfox.fibers.includeFiducials", m_Misc.m_CheckIncludeFiducialsBox);
if (m_NoiseModel!=nullptr)
{
parameters.put("fiberfox.image.artifacts.noisevariance", m_NoiseModel->GetNoiseVariance());
if (dynamic_cast<mitk::RicianNoiseModel<>*>(m_NoiseModel.get()))
parameters.put("fiberfox.image.artifacts.noisetype", "rice");
else if (dynamic_cast<mitk::ChiSquareNoiseModel<>*>(m_NoiseModel.get()))
parameters.put("fiberfox.image.artifacts.noisetype", "chisquare");
}
for (std::size_t i=0; i<m_FiberModelList.size()+m_NonFiberModelList.size(); i++)
{
mitk::DiffusionSignalModel<>* signalModel = nullptr;
if (i<m_FiberModelList.size())
{
signalModel = m_FiberModelList.at(i);
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".type", "fiber");
}
else
{
signalModel = m_NonFiberModelList.at(i-m_FiberModelList.size());
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".type", "non-fiber");
}
if (dynamic_cast<mitk::StickModel<>*>(signalModel))
{
mitk::StickModel<>* model = dynamic_cast<mitk::StickModel<>*>(signalModel);
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".model", "stick");
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".d", model->GetDiffusivity());
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".t2", model->GetT2());
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".t1", model->GetT1());
}
else if (dynamic_cast<mitk::TensorModel<>*>(signalModel))
{
mitk::TensorModel<>* model = dynamic_cast<mitk::TensorModel<>*>(signalModel);
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".model", "tensor");
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".d1", model->GetDiffusivity1());
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".d2", model->GetDiffusivity2());
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".d3", model->GetDiffusivity3());
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".t2", model->GetT2());
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".t1", model->GetT1());
}
else if (dynamic_cast<mitk::RawShModel<>*>(signalModel))
{
mitk::RawShModel<>* model = dynamic_cast<mitk::RawShModel<>*>(signalModel);
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".model", "prototype");
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".minFA", model->GetFaRange().first);
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".maxFA", model->GetFaRange().second);
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".minADC", model->GetAdcRange().first);
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".maxADC", model->GetAdcRange().second);
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".maxNumSamples", model->GetMaxNumKernels());
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".numSamples", model->GetNumberOfKernels());
int shOrder = model->GetShOrder();
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".numCoeffs", (shOrder*shOrder + shOrder + 2)/2 + shOrder);
for (unsigned int j=0; j<model->GetNumberOfKernels(); j++)
{
vnl_vector< double > coeffs = model->GetCoefficients(j);
for (unsigned int k=0; k<coeffs.size(); k++)
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".kernels."+boost::lexical_cast<std::string>(j)+".coeffs."+boost::lexical_cast<std::string>(k), coeffs[k]);
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".kernels."+boost::lexical_cast<std::string>(j)+".B0", model->GetBaselineSignal(j));
}
}
else if (dynamic_cast<mitk::BallModel<>*>(signalModel))
{
mitk::BallModel<>* model = dynamic_cast<mitk::BallModel<>*>(signalModel);
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".model", "ball");
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".d", model->GetDiffusivity());
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".t2", model->GetT2());
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".t1", model->GetT1());
}
else if (dynamic_cast<mitk::AstroStickModel<>*>(signalModel))
{
mitk::AstroStickModel<>* model = dynamic_cast<mitk::AstroStickModel<>*>(signalModel);
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".model", "astrosticks");
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".d", model->GetDiffusivity());
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".t2", model->GetT2());
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".t1", model->GetT1());
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".randomize", model->GetRandomizeSticks());
}
else if (dynamic_cast<mitk::DotModel<>*>(signalModel))
{
mitk::DotModel<>* model = dynamic_cast<mitk::DotModel<>*>(signalModel);
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".model", "dot");
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".t2", model->GetT2());
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".t1", model->GetT1());
}
if (signalModel!=nullptr)
{
parameters.put("fiberfox.image.compartments.c"+boost::lexical_cast<std::string>(i)+".ID", signalModel->m_CompartmentId);
if (signalModel->GetVolumeFractionImage().IsNotNull())
{
try{
itk::ImageFileWriter<ItkDoubleImgType>::Pointer writer = itk::ImageFileWriter<ItkDoubleImgType>::New();
writer->SetFileName(filename+"_VOLUME"+boost::lexical_cast<std::string>(signalModel->m_CompartmentId)+".nii.gz");
writer->SetInput(signalModel->GetVolumeFractionImage());
writer->Update();
MITK_INFO << "Volume fraction image for compartment "+boost::lexical_cast<std::string>(signalModel->m_CompartmentId)+" saved.";
}
catch(...)
{
}
}
}
}
boost::property_tree::xml_writer_settings<std::string> writerSettings(' ', 2);
boost::property_tree::xml_parser::write_xml(filename, parameters, std::locale(), writerSettings);
try{
itk::ImageFileWriter<ItkFloatImgType>::Pointer writer = itk::ImageFileWriter<ItkFloatImgType>::New();
writer->SetFileName(filename+"_FMAP.nii.gz");
writer->SetInput(m_SignalGen.m_FrequencyMap);
writer->Update();
}
catch(...)
{
MITK_INFO << "No frequency map saved.";
}
try{
itk::ImageFileWriter<ItkUcharImgType>::Pointer writer = itk::ImageFileWriter<ItkUcharImgType>::New();
writer->SetFileName(filename+"_MASK.nii.gz");
writer->SetInput(m_SignalGen.m_MaskImage);
writer->Update();
}
catch(...)
{
MITK_INFO << "No mask image saved.";
}
setlocale(LC_ALL, currLocale.c_str());
}
template< class ParameterType >
ParameterType mitk::FiberfoxParameters::ReadVal(boost::property_tree::ptree::value_type const& v, std::string tag, ParameterType defaultValue, bool essential)
{
try
{
return v.second.get<ParameterType>(tag);
}
catch (...)
{
if (essential)
{
mitkThrow() << "Parameter file corrupted. Essential tag is missing: '" << tag << "'";
}
if (tag!="artifacts.noisetype")
{
MITK_INFO << "Tag '" << tag << "' not found. Using default value '" << defaultValue << "'.";
m_MissingTags += "\n- ";
m_MissingTags += tag;
}
return defaultValue;
}
}
void mitk::FiberfoxParameters::UpdateSignalModels()
{
for (mitk::DiffusionSignalModel<>* m : m_FiberModelList)
{
m->SetGradientList(m_SignalGen.m_GradientDirections);
m->SetBvalue(m_SignalGen.m_Bvalue);
}
for (mitk::DiffusionSignalModel<>* m : m_NonFiberModelList)
{
m->SetGradientList(m_SignalGen.m_GradientDirections);
m->SetBvalue(m_SignalGen.m_Bvalue);
}
}
void mitk::FiberfoxParameters::SetNumWeightedVolumes(int numGradients)
{
m_SignalGen.SetNumWeightedVolumes(numGradients);
UpdateSignalModels();
}
void mitk::FiberfoxParameters::SetGradienDirections(mitk::SignalGenerationParameters::GradientListType gradientList)
{
m_SignalGen.SetGradienDirections(gradientList);
UpdateSignalModels();
}
void mitk::FiberfoxParameters::SetGradienDirections(mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradientList)
{
m_SignalGen.SetGradienDirections(gradientList);
UpdateSignalModels();
}
void mitk::FiberfoxParameters::SetBvalue(double Bvalue)
{
m_SignalGen.m_Bvalue = Bvalue;
UpdateSignalModels();
}
void mitk::FiberfoxParameters::GenerateGradientHalfShell()
{
m_SignalGen.GenerateGradientHalfShell();
UpdateSignalModels();
}
void mitk::FiberfoxParameters::LoadParameters(std::string filename, bool fix_seed)
{
itk::Statistics::MersenneTwisterRandomVariateGenerator::Pointer randgen = itk::Statistics::MersenneTwisterRandomVariateGenerator::New();
if (fix_seed)
{
srand(0);
randgen->SetSeed(0);
}
else
{
srand(time(0));
randgen->SetSeed();
}
m_MissingTags = "";
if(filename.empty()) { return; }
const std::string& locale = "C";
const std::string& currLocale = setlocale( LC_ALL, nullptr );
if ( locale.compare(currLocale)!=0 )
{
try
{
setlocale(LC_ALL, locale.c_str());
}
catch(...)
{
MITK_INFO << "Could not set locale " << locale;
}
}
boost::property_tree::ptree parameterTree;
boost::property_tree::xml_parser::read_xml( filename, parameterTree );
m_FiberModelList.clear();
m_NonFiberModelList.clear();
if (m_NoiseModel) { m_NoiseModel = nullptr; }
BOOST_FOREACH( boost::property_tree::ptree::value_type const& v1, parameterTree.get_child("fiberfox") )
{
if( v1.first == "fibers" )
{
m_Misc.m_CheckRealTimeFibersBox = ReadVal<bool>(v1,"realtime", m_Misc.m_CheckRealTimeFibersBox);
m_Misc.m_CheckAdvancedFiberOptionsBox = ReadVal<bool>(v1,"showadvanced", m_Misc.m_CheckAdvancedFiberOptionsBox);
m_Misc.m_CheckConstantRadiusBox = ReadVal<bool>(v1,"constantradius", m_Misc.m_CheckConstantRadiusBox);
m_Misc.m_CheckIncludeFiducialsBox = ReadVal<bool>(v1,"includeFiducials", m_Misc.m_CheckIncludeFiducialsBox);
switch (ReadVal<unsigned int>(v1,"distribution", 0))
{
case 0:
m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM;
break;
case 1:
m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_GAUSSIAN;
break;
default:
m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM;
}
m_FiberGen.m_Variance = ReadVal<double>(v1,"variance", m_FiberGen.m_Variance);
m_FiberGen.m_Density = ReadVal<unsigned int>(v1,"density", m_FiberGen.m_Density);
m_FiberGen.m_Sampling = ReadVal<double>(v1,"spline.sampling", m_FiberGen.m_Sampling);
m_FiberGen.m_Tension = ReadVal<double>(v1,"spline.tension", m_FiberGen.m_Tension);
m_FiberGen.m_Continuity = ReadVal<double>(v1,"spline.continuity", m_FiberGen.m_Continuity);
m_FiberGen.m_Bias = ReadVal<double>(v1,"spline.bias", m_FiberGen.m_Bias);
m_FiberGen.m_Rotation[0] = ReadVal<double>(v1,"rotation.x", m_FiberGen.m_Rotation[0]);
m_FiberGen.m_Rotation[1] = ReadVal<double>(v1,"rotation.y", m_FiberGen.m_Rotation[1]);
m_FiberGen.m_Rotation[2] = ReadVal<double>(v1,"rotation.z", m_FiberGen.m_Rotation[2]);
m_FiberGen.m_Translation[0] = ReadVal<double>(v1,"translation.x", m_FiberGen.m_Translation[0]);
m_FiberGen.m_Translation[1] = ReadVal<double>(v1,"translation.y", m_FiberGen.m_Translation[1]);
m_FiberGen.m_Translation[2] = ReadVal<double>(v1,"translation.z", m_FiberGen.m_Translation[2]);
m_FiberGen.m_Scale[0] = ReadVal<double>(v1,"scale.x", m_FiberGen.m_Scale[0]);
m_FiberGen.m_Scale[1] = ReadVal<double>(v1,"scale.y", m_FiberGen.m_Scale[1]);
m_FiberGen.m_Scale[2] = ReadVal<double>(v1,"scale.z", m_FiberGen.m_Scale[2]);
}
else if ( v1.first == "image" )
{
m_Misc.m_SignalModelString = ReadVal<std::string>(v1,"signalmodelstring", m_Misc.m_SignalModelString);
m_Misc.m_ArtifactModelString = ReadVal<std::string>(v1,"artifactmodelstring", m_Misc.m_ArtifactModelString);
m_Misc.m_OutputPath = ReadVal<std::string>(v1,"outpath", m_Misc.m_OutputPath);
m_Misc.m_OutputAdditionalImages = ReadVal<bool>(v1,"outputvolumefractions", m_Misc.m_OutputAdditionalImages);
m_Misc.m_CheckAdvancedSignalOptionsBox = ReadVal<bool>(v1,"showadvanced", m_Misc.m_CheckAdvancedSignalOptionsBox);
m_Misc.m_DoAddDistortions = ReadVal<bool>(v1,"artifacts.doAddDistortions", m_Misc.m_DoAddDistortions);
m_Misc.m_DoAddNoise = ReadVal<bool>(v1,"artifacts.addnoise", m_Misc.m_DoAddNoise);
m_Misc.m_DoAddGhosts = ReadVal<bool>(v1,"artifacts.addghosts", m_Misc.m_DoAddGhosts);
m_Misc.m_DoAddAliasing = ReadVal<bool>(v1,"artifacts.addaliasing", m_Misc.m_DoAddAliasing);
m_Misc.m_DoAddSpikes = ReadVal<bool>(v1,"artifacts.addspikes", m_Misc.m_DoAddSpikes);
m_Misc.m_DoAddEddyCurrents = ReadVal<bool>(v1,"artifacts.addeddycurrents", m_Misc.m_DoAddEddyCurrents);
m_SignalGen.m_ImageRegion.SetSize(0, ReadVal<int>(v1,"basic.size.x",m_SignalGen.m_ImageRegion.GetSize(0)));
m_SignalGen.m_ImageRegion.SetSize(1, ReadVal<int>(v1,"basic.size.y",m_SignalGen.m_ImageRegion.GetSize(1)));
m_SignalGen.m_ImageRegion.SetSize(2, ReadVal<int>(v1,"basic.size.z",m_SignalGen.m_ImageRegion.GetSize(2)));
m_SignalGen.m_ImageSpacing[0] = ReadVal<float>(v1,"basic.spacing.x",m_SignalGen.m_ImageSpacing[0]);
m_SignalGen.m_ImageSpacing[1] = ReadVal<float>(v1,"basic.spacing.y",m_SignalGen.m_ImageSpacing[1]);
m_SignalGen.m_ImageSpacing[2] = ReadVal<float>(v1,"basic.spacing.z",m_SignalGen.m_ImageSpacing[2]);
m_SignalGen.m_ImageOrigin[0] = ReadVal<float>(v1,"basic.origin.x",m_SignalGen.m_ImageOrigin[0]);
m_SignalGen.m_ImageOrigin[1] = ReadVal<float>(v1,"basic.origin.y",m_SignalGen.m_ImageOrigin[1]);
m_SignalGen.m_ImageOrigin[2] = ReadVal<float>(v1,"basic.origin.z",m_SignalGen.m_ImageOrigin[2]);
int i = 0;
int j = 0;
for(auto v : v1.second.get_child("basic.direction"))
{
m_SignalGen.m_ImageDirection[i][j] = boost::lexical_cast<float>(v.second.data());
++j;
if (j==3)
{
j = 0;
++i;
}
}
m_SignalGen.m_AcquisitionType = (SignalGenerationParameters::AcquisitionType)ReadVal<int>(v1,"acquisitiontype", m_SignalGen.m_AcquisitionType);
m_SignalGen.m_CoilSensitivityProfile = (SignalGenerationParameters::CoilSensitivityProfile)ReadVal<int>(v1,"coilsensitivityprofile", m_SignalGen.m_CoilSensitivityProfile);
m_SignalGen.m_NumberOfCoils = ReadVal<unsigned int>(v1,"numberofcoils", m_SignalGen.m_NumberOfCoils);
m_SignalGen.m_ReversePhase = ReadVal<bool>(v1,"reversephase", m_SignalGen.m_ReversePhase);
m_SignalGen.m_PartialFourier = ReadVal<float>(v1,"partialfourier", m_SignalGen.m_PartialFourier);
m_SignalGen.m_NoiseVariance = ReadVal<float>(v1,"noisevariance", m_SignalGen.m_NoiseVariance);
m_SignalGen.m_tRep = ReadVal<float>(v1,"trep", m_SignalGen.m_tRep);
m_SignalGen.m_tInv = ReadVal<float>(v1,"tinv", m_SignalGen.m_tInv);
m_SignalGen.m_SignalScale = ReadVal<float>(v1,"signalScale", m_SignalGen.m_SignalScale);
m_SignalGen.m_tEcho = ReadVal<float>(v1,"tEcho", m_SignalGen.m_tEcho);
m_SignalGen.m_tLine = ReadVal<float>(v1,"tLine", m_SignalGen.m_tLine);
m_SignalGen.m_tInhom = ReadVal<float>(v1,"tInhom", m_SignalGen.m_tInhom);
m_SignalGen.m_EchoTrainLength = ReadVal<unsigned int>(v1,"echoTrainLength", m_SignalGen.m_EchoTrainLength);
m_SignalGen.m_SimulateKspaceAcquisition = ReadVal<bool>(v1,"simulatekspace", m_SignalGen.m_SimulateKspaceAcquisition);
m_SignalGen.m_AxonRadius = ReadVal<double>(v1,"axonRadius", m_SignalGen.m_AxonRadius);
m_SignalGen.m_Spikes = ReadVal<unsigned int>(v1,"artifacts.spikesnum", m_SignalGen.m_Spikes);
m_SignalGen.m_SpikeAmplitude = ReadVal<float>(v1,"artifacts.spikesscale", m_SignalGen.m_SpikeAmplitude);
m_SignalGen.m_KspaceLineOffset = ReadVal<float>(v1,"artifacts.kspaceLineOffset", m_SignalGen.m_KspaceLineOffset);
m_SignalGen.m_EddyStrength = ReadVal<float>(v1,"artifacts.eddyStrength", m_SignalGen.m_EddyStrength);
m_SignalGen.m_Tau = ReadVal<float>(v1,"artifacts.eddyTau", m_SignalGen.m_Tau);
m_SignalGen.m_CroppingFactor = ReadVal<float>(v1,"artifacts.aliasingfactor", m_SignalGen.m_CroppingFactor);
m_SignalGen.m_Drift = ReadVal<float>(v1,"artifacts.drift", m_SignalGen.m_Drift);
m_SignalGen.m_DoAddGibbsRinging = ReadVal<bool>(v1,"artifacts.addringing", m_SignalGen.m_DoAddGibbsRinging);
m_SignalGen.m_ZeroRinging = ReadVal<int>(v1,"artifacts.zeroringing", m_SignalGen.m_ZeroRinging);
m_SignalGen.m_DoSimulateRelaxation = ReadVal<bool>(v1,"doSimulateRelaxation", m_SignalGen.m_DoSimulateRelaxation);
m_SignalGen.m_DoDisablePartialVolume = ReadVal<bool>(v1,"doDisablePartialVolume", m_SignalGen.m_DoDisablePartialVolume);
m_SignalGen.m_DoAddMotion = ReadVal<bool>(v1,"artifacts.doAddMotion", m_SignalGen.m_DoAddMotion);
m_SignalGen.m_DoRandomizeMotion = ReadVal<bool>(v1,"artifacts.randomMotion", m_SignalGen.m_DoRandomizeMotion);
m_SignalGen.m_DoAddDrift = ReadVal<bool>(v1,"artifacts.doAddDrift", m_SignalGen.m_DoAddDrift);
m_SignalGen.m_Translation[0] = ReadVal<float>(v1,"artifacts.translation0", m_SignalGen.m_Translation[0]);
m_SignalGen.m_Translation[1] = ReadVal<float>(v1,"artifacts.translation1", m_SignalGen.m_Translation[1]);
m_SignalGen.m_Translation[2] = ReadVal<float>(v1,"artifacts.translation2", m_SignalGen.m_Translation[2]);
m_SignalGen.m_Rotation[0] = ReadVal<float>(v1,"artifacts.rotation0", m_SignalGen.m_Rotation[0]);
m_SignalGen.m_Rotation[1] = ReadVal<float>(v1,"artifacts.rotation1", m_SignalGen.m_Rotation[1]);
m_SignalGen.m_Rotation[2] = ReadVal<float>(v1,"artifacts.rotation2", m_SignalGen.m_Rotation[2]);
if (itksys::SystemTools::FileExists(filename+".bvals") && itksys::SystemTools::FileExists(filename+".bvecs"))
{
m_Misc.m_BvalsFile = filename+".bvals";
m_Misc.m_BvecsFile = filename+".bvecs";
m_SignalGen.SetGradienDirections( mitk::gradients::ReadBvalsBvecs(m_Misc.m_BvalsFile, m_Misc.m_BvecsFile, m_SignalGen.m_Bvalue) );
}
else
{
m_SignalGen.m_Bvalue = ReadVal<double>(v1,"bvalue", m_SignalGen.m_Bvalue);
SignalGenerationParameters::GradientListType gradients;
try
{
BOOST_FOREACH( boost::property_tree::ptree::value_type const& v2, v1.second.get_child("gradients") )
{
SignalGenerationParameters::GradientType g;
g[0] = ReadVal<double>(v2,"x",0);
g[1] = ReadVal<double>(v2,"y",0);
g[2] = ReadVal<double>(v2,"z",0);
gradients.push_back(g);
}
}
catch(...)
{
MITK_INFO << "WARNING: Fiberfox parameters without any gradient directions loaded.";
}
m_SignalGen.SetGradienDirections(gradients);
}
m_Misc.m_MotionVolumesBox = ReadVal<std::string>(v1,"artifacts.motionvolumes", m_Misc.m_MotionVolumesBox);
m_SignalGen.m_MotionVolumes.clear();
if ( m_Misc.m_MotionVolumesBox == "random" )
{
m_SignalGen.m_MotionVolumes.push_back(0);
for ( size_t i=1; i < m_SignalGen.GetNumVolumes(); ++i )
{
m_SignalGen.m_MotionVolumes.push_back( bool( randgen->GetIntegerVariate()%2 ) );
}
MITK_DEBUG << "mitkFiberfoxParameters.cpp: Case m_Misc.m_MotionVolumesBox == \"random\".";
}
else if ( ! m_Misc.m_MotionVolumesBox.empty() )
{
std::stringstream stream( m_Misc.m_MotionVolumesBox );
std::vector<int> numbers;
int nummer = std::numeric_limits<int>::max();
while( stream >> nummer )
{
if( nummer < std::numeric_limits<int>::max() )
{
numbers.push_back( nummer );
}
}
// If a list of negative numbers is given:
if( *(std::min_element( numbers.begin(), numbers.end() )) < 0
&& *(std::max_element( numbers.begin(), numbers.end() )) <= 0 ) // cave: -0 == +0
{
for ( size_t i=0; i<m_SignalGen.GetNumVolumes(); ++i )
{
m_SignalGen.m_MotionVolumes.push_back( true );
}
// set all true except those given.
for (auto number : numbers)
{
if (-number < static_cast<int>(m_SignalGen.GetNumVolumes()) && -number >= 0 )
m_SignalGen.m_MotionVolumes.at(-number) = false;
}
MITK_DEBUG << "mitkFiberfoxParameters.cpp: Case list of negative numbers.";
}
// If a list of positive numbers is given:
else if( *(std::min_element( numbers.begin(), numbers.end() )) >= 0
&& *(std::max_element( numbers.begin(), numbers.end() )) >= 0 )
{
for ( size_t i=0; i<m_SignalGen.GetNumVolumes(); ++i )
{
m_SignalGen.m_MotionVolumes.push_back( false );
}
// set all false except those given.
for (auto number : numbers)
{
if (number < static_cast<int>(m_SignalGen.GetNumVolumes()) && number >= 0)
m_SignalGen.m_MotionVolumes.at(number) = true;
}
MITK_DEBUG << "mitkFiberfoxParameters.cpp: Case list of positive numbers.";
}
else
{
MITK_WARN << "mitkFiberfoxParameters.cpp: Inconsistent list of numbers in m_MotionVolumesBox.";
break;
}
}
else
{
MITK_WARN << "mitkFiberfoxParameters.cpp: Cannot make sense of string in m_MotionVolumesBox.";
break;
}
try
{
if (ReadVal<std::string>(v1,"artifacts.noisetype","")=="rice")
{
m_NoiseModel = std::make_shared< mitk::RicianNoiseModel<> >();
m_NoiseModel->SetNoiseVariance(ReadVal<float>(v1,"artifacts.noisevariance",m_NoiseModel->GetNoiseVariance()));
}
}
catch(...)
{
MITK_DEBUG << "mitkFiberfoxParameters.cpp: caught some error while trying m_NoiseModel->SetNoiseVariance()";
// throw;
}
try
{
if (ReadVal<std::string>(v1,"artifacts.noisetype","")=="chisquare")
{
m_NoiseModel = std::make_shared< mitk::ChiSquareNoiseModel<> >();
m_NoiseModel->SetNoiseVariance(ReadVal<float>(v1,"artifacts.noisevariance",m_NoiseModel->GetNoiseVariance()));
}
}
catch(...)
{
MITK_DEBUG << "mitkFiberfoxParameters.cpp: caught some error while trying m_NoiseModel->SetNoiseVariance()";
// throw;
}
BOOST_FOREACH( boost::property_tree::ptree::value_type const& v2, v1.second.get_child("compartments") )
{
mitk::DiffusionSignalModel<>* signalModel = nullptr;
std::string model = ReadVal<std::string>(v2,"model","",true);
if (model=="stick")
{
mitk::StickModel<>* model = new mitk::StickModel<>();
model->SetDiffusivity(ReadVal<double>(v2,"d",model->GetDiffusivity()));
model->SetT2(ReadVal<double>(v2,"t2",model->GetT2()));
model->SetT1(ReadVal<double>(v2,"t1",model->GetT1()));
model->SetBvalue(m_SignalGen.m_Bvalue);
model->m_CompartmentId = ReadVal<unsigned int>(v2,"ID",0,true);
if (ReadVal<std::string>(v2,"type","",true)=="fiber")
m_FiberModelList.push_back(model);
else if (ReadVal<std::string>(v2,"type","",true)=="non-fiber")
m_NonFiberModelList.push_back(model);
signalModel = model;
}
else if (model=="tensor")
{
mitk::TensorModel<>* model = new mitk::TensorModel<>();
model->SetDiffusivity1(ReadVal<double>(v2,"d1",model->GetDiffusivity1()));
model->SetDiffusivity2(ReadVal<double>(v2,"d2",model->GetDiffusivity2()));
model->SetDiffusivity3(ReadVal<double>(v2,"d3",model->GetDiffusivity3()));
model->SetT2(ReadVal<double>(v2,"t2",model->GetT2()));
model->SetT1(ReadVal<double>(v2,"t1",model->GetT1()));
model->SetBvalue(m_SignalGen.m_Bvalue);
model->m_CompartmentId = ReadVal<unsigned int>(v2,"ID",0,true);
if (ReadVal<std::string>(v2,"type","",true)=="fiber")
m_FiberModelList.push_back(model);
else if (ReadVal<std::string>(v2,"type","",true)=="non-fiber")
m_NonFiberModelList.push_back(model);
signalModel = model;
}
else if (model=="ball")
{
mitk::BallModel<>* model = new mitk::BallModel<>();
model->SetDiffusivity(ReadVal<double>(v2,"d",model->GetDiffusivity()));
model->SetT2(ReadVal<double>(v2,"t2",model->GetT2()));
model->SetT1(ReadVal<double>(v2,"t1",model->GetT1()));
model->SetBvalue(m_SignalGen.m_Bvalue);
model->m_CompartmentId = ReadVal<unsigned int>(v2,"ID",0,true);
if (ReadVal<std::string>(v2,"type","",true)=="fiber")
m_FiberModelList.push_back(model);
else if (ReadVal<std::string>(v2,"type","",true)=="non-fiber")
m_NonFiberModelList.push_back(model);
signalModel = model;
}
else if (model=="astrosticks")
{
mitk::AstroStickModel<>* model = new AstroStickModel<>();
model->SetDiffusivity(ReadVal<double>(v2,"d",model->GetDiffusivity()));
model->SetT2(ReadVal<double>(v2,"t2",model->GetT2()));
model->SetT1(ReadVal<double>(v2,"t1",model->GetT1()));
model->SetBvalue(m_SignalGen.m_Bvalue);
model->SetRandomizeSticks(ReadVal<bool>(v2,"randomize",model->GetRandomizeSticks()));
model->m_CompartmentId = ReadVal<unsigned int>(v2,"ID",0,true);
if (ReadVal<std::string>(v2,"type","",true)=="fiber")
m_FiberModelList.push_back(model);
else if (ReadVal<std::string>(v2,"type","",true)=="non-fiber")
m_NonFiberModelList.push_back(model);
signalModel = model;
}
else if (model=="dot")
{
mitk::DotModel<>* model = new mitk::DotModel<>();
model->SetT2(ReadVal<double>(v2,"t2",model->GetT2()));
model->SetT1(ReadVal<double>(v2,"t1",model->GetT1()));
model->m_CompartmentId = ReadVal<unsigned int>(v2,"ID",0,true);
if (ReadVal<std::string>(v2,"type","",true)=="fiber")
m_FiberModelList.push_back(model);
else if (ReadVal<std::string>(v2,"type","",true)=="non-fiber")
m_NonFiberModelList.push_back(model);
signalModel = model;
}
else if (model=="prototype")
{
mitk::RawShModel<>* model = new mitk::RawShModel<>();
model->SetMaxNumKernels(ReadVal<unsigned int>(v2,"maxNumSamples",model->GetMaxNumKernels()));
model->SetFaRange(ReadVal<double>(v2,"minFA",model->GetFaRange().first), ReadVal<double>(v2,"maxFA",model->GetFaRange().second));
model->SetAdcRange(ReadVal<double>(v2,"minADC",model->GetAdcRange().first), ReadVal<double>(v2,"maxADC",model->GetAdcRange().second));
model->m_CompartmentId = ReadVal<unsigned int>(v2,"ID",0,true);
unsigned int numCoeffs = ReadVal<unsigned int>(v2,"numCoeffs",0,true);
unsigned int numSamples = ReadVal<unsigned int>(v2,"numSamples",0,true);
for (unsigned int j=0; j<numSamples; j++)
{
vnl_vector< double > coeffs(numCoeffs);
for (unsigned int k=0; k<numCoeffs; k++)
{
coeffs[k] = ReadVal<double>(v2,"kernels."+boost::lexical_cast<std::string>(j)+".coeffs."+boost::lexical_cast<std::string>(k),0,true);
}
model->SetShCoefficients( coeffs, ReadVal<double>(v2,"kernels."+boost::lexical_cast<std::string>(j)+".B0",0,true) );
}
if (ReadVal<std::string>(v2,"type","",true)=="fiber")
{ m_FiberModelList.push_back(model); }
else if (ReadVal<std::string>(v2,"type","",true)=="non-fiber")
{ m_NonFiberModelList.push_back(model); }
// else ?
signalModel = model;
}
if (signalModel!=nullptr)
{
try
{
itk::ImageFileReader<ItkDoubleImgType>::Pointer reader = itk::ImageFileReader<ItkDoubleImgType>::New();
if ( itksys::SystemTools::FileExists(filename+"_VOLUME"+ReadVal<std::string>(v2,"ID","")+".nii.gz") )
reader->SetFileName(filename+"_VOLUME"+ReadVal<std::string>(v2,"ID","")+".nii.gz");
else if ( itksys::SystemTools::FileExists(filename+"_VOLUME"+ReadVal<std::string>(v2,"ID","")+".nii") )
reader->SetFileName(filename+"_VOLUME"+ReadVal<std::string>(v2,"ID","")+".nii");
else
reader->SetFileName(filename+"_VOLUME"+ReadVal<std::string>(v2,"ID","")+".nrrd");
reader->Update();
signalModel->SetVolumeFractionImage(reader->GetOutput());
MITK_INFO << "Volume fraction image loaded for compartment " << signalModel->m_CompartmentId;
}
catch(...)
{
MITK_INFO << "No volume fraction image found for compartment " << signalModel->m_CompartmentId;
}
}
}
}
else
{
}
}
UpdateSignalModels();
try
{
itk::ImageFileReader<ItkFloatImgType>::Pointer reader = itk::ImageFileReader<ItkFloatImgType>::New();
reader->SetFileName(filename+"_FMAP.nrrd");
if ( itksys::SystemTools::FileExists(filename+"_FMAP.nii.gz") )
reader->SetFileName(filename+"_FMAP.nii.gz");
else if ( itksys::SystemTools::FileExists(filename+"_FMAP.nii") )
reader->SetFileName(filename+"_FMAP.nii");
else
reader->SetFileName(filename+"_FMAP.nrrd");
reader->Update();
m_SignalGen.m_FrequencyMap = reader->GetOutput();
MITK_INFO << "Frequency map loaded.";
}
catch(...)
{
MITK_INFO << "No frequency map found.";
}
try
{
itk::ImageFileReader<ItkUcharImgType>::Pointer reader = itk::ImageFileReader<ItkUcharImgType>::New();
if ( itksys::SystemTools::FileExists(filename+"_MASK.nii.gz") )
reader->SetFileName(filename+"_MASK.nii.gz");
else if ( itksys::SystemTools::FileExists(filename+"_MASK.nii") )
reader->SetFileName(filename+"_MASK.nii");
else
reader->SetFileName(filename+"_MASK.nrrd");
reader->Update();
m_SignalGen.m_MaskImage = reader->GetOutput();
m_SignalGen.m_ImageRegion = m_SignalGen.m_MaskImage->GetLargestPossibleRegion();
m_SignalGen.m_ImageSpacing = m_SignalGen.m_MaskImage->GetSpacing();
m_SignalGen.m_ImageOrigin = m_SignalGen.m_MaskImage->GetOrigin();
m_SignalGen.m_ImageDirection = m_SignalGen.m_MaskImage->GetDirection();
MITK_INFO << "Mask image loaded.";
}
catch(...)
{
MITK_INFO << "No mask image found.";
}
setlocale(LC_ALL, currLocale.c_str());
}
void mitk::FiberfoxParameters::PrintSelf()
{
MITK_INFO << "Not implemented :(";
}
diff --git a/Modules/MriSimulation/mitkFiberfoxParameters.h b/Modules/MriSimulation/mitkFiberfoxParameters.h
index 2079828..055e2dd 100644
--- a/Modules/MriSimulation/mitkFiberfoxParameters.h
+++ b/Modules/MriSimulation/mitkFiberfoxParameters.h
@@ -1,339 +1,339 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _MITK_FiberfoxParameters_H
#define _MITK_FiberfoxParameters_H
#include <itkImageRegion.h>
#include <itkMatrix.h>
#include <mitkDiffusionNoiseModel.h>
#include <mitkDiffusionSignalModel.h>
#include <mitkDataNode.h>
#include <mitkRicianNoiseModel.h>
#include <mitkChiSquareNoiseModel.h>
#include <mitkImage.h>
#include <mitkDiffusionPropertyHelper.h>
#include <mitkPlanarEllipse.h>
#include <mitkStickModel.h>
#include <mitkTensorModel.h>
#include <mitkAstroStickModel.h>
#include <mitkBallModel.h>
#include <mitkDotModel.h>
#include <mitkRawShModel.h>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <limits>
#include <MitkMriSimulationExports.h>
#include <itkMersenneTwisterRandomVariateGenerator.h>
namespace mitk
{
class MITKMRISIMULATION_EXPORT FiberfoxParameters;
/** Signal generation */
class MITKMRISIMULATION_EXPORT SignalGenerationParameters
{
friend FiberfoxParameters;
public:
typedef itk::Image<float, 3> ItkFloatImgType;
typedef itk::Image<unsigned char, 3> ItkUcharImgType;
typedef itk::Vector<double,3> GradientType;
typedef std::vector<GradientType> GradientListType;
enum CoilSensitivityProfile : int {
COIL_CONSTANT,
COIL_LINEAR,
COIL_EXPONENTIAL
};
enum AcquisitionType : int
{
SingleShotEpi,
ConventionalSpinEcho,
FastSpinEcho,
};
SignalGenerationParameters()
: m_AcquisitionType(SignalGenerationParameters::SingleShotEpi)
, m_SignalScale(100)
, m_tEcho(100)
, m_tRep(4000)
, m_tInv(0)
, m_tLine(1)
, m_tInhom(50)
, m_EchoTrainLength(8)
, m_ReversePhase(false)
, m_PartialFourier(1.0)
, m_NoiseVariance(0.001f)
, m_NumberOfCoils(1)
, m_CoilSensitivityProfile(SignalGenerationParameters::COIL_CONSTANT)
, m_CoilSensitivity(0.3f)
, m_SimulateKspaceAcquisition(false)
, m_AxonRadius(0)
, m_DoDisablePartialVolume(false)
, m_Spikes(0)
, m_SpikeAmplitude(1)
, m_KspaceLineOffset(0)
, m_EddyStrength(0.002f)
, m_Tau(70)
, m_CroppingFactor(1)
, m_Drift(0.06)
, m_DoAddGibbsRinging(false)
, m_ZeroRinging(0)
, m_DoSimulateRelaxation(true)
, m_DoAddMotion(false)
, m_DoRandomizeMotion(true)
, m_DoAddDrift(false)
, m_FrequencyMap(nullptr)
, m_MaskImage(nullptr)
, m_Bvalue(1000)
{
m_ImageRegion.SetSize(0, 12);
m_ImageRegion.SetSize(1, 12);
m_ImageRegion.SetSize(2, 3);
m_ImageSpacing.Fill(2.0);
m_ImageOrigin.Fill(0.0);
m_ImageDirection.SetIdentity();
m_Translation.Fill(0.0);
m_Rotation.Fill(0.0);
SetNumWeightedVolumes(6);
}
/** input/output image specifications */
itk::ImageRegion<3> m_CroppedRegion; ///< Image size with reduced FOV.
itk::ImageRegion<3> m_ImageRegion; ///< Image size.
itk::Vector<float,3> m_ImageSpacing; ///< Image voxel size.
itk::Point<float,3> m_ImageOrigin; ///< Image origin.
itk::Matrix<double, 3, 3> m_ImageDirection; ///< Image rotation matrix.
/** Other acquisitions parameters */
AcquisitionType m_AcquisitionType; ///< determines k-space trajectory and maximum echo position(s)
float m_SignalScale; ///< Scaling factor for output signal (before noise is added).
float m_tEcho; ///< Echo time TE.
float m_tRep; ///< Echo time TR.
float m_tInv; ///< Inversion time
float m_tLine; ///< k-space line readout time (dwell time).
float m_tInhom; ///< T2'
unsigned int m_EchoTrainLength; ///< Only relevant for Fast Spin Echo sequence (number of k-space lines acquired with one RF pulse)
bool m_ReversePhase; ///< If true, the phase readout direction will be inverted (-y instead of y)
float m_PartialFourier; ///< Partial fourier factor (0.5-1)
float m_NoiseVariance; ///< Variance of complex gaussian noise
unsigned int m_NumberOfCoils; ///< Number of coils in multi-coil acquisition
CoilSensitivityProfile m_CoilSensitivityProfile; ///< Choose between constant, linear or exponential sensitivity profile of the used coils
float m_CoilSensitivity; ///< signal remaining in slice center
bool m_SimulateKspaceAcquisition;///< Flag to enable/disable k-space acquisition simulation
double m_AxonRadius; ///< Determines compartment volume fractions (0 == automatic axon radius estimation)
bool m_DoDisablePartialVolume; ///< Disable partial volume effects. Each voxel is either all fiber or all non-fiber.
/** Artifacts and other effects */
unsigned int m_Spikes; ///< Number of spikes randomly appearing in the image
float m_SpikeAmplitude; ///< amplitude of spikes relative to the largest signal intensity (magnitude of complex)
float m_KspaceLineOffset; ///< Causes N/2 ghosts. Larger offset means stronger ghost.
float m_EddyStrength; ///< Strength of eddy current induced gradients in mT/m.
float m_Tau; ///< Eddy current decay constant (in ms)
float m_CroppingFactor; ///< FOV size in y-direction is multiplied by this factor. Causes aliasing artifacts.
float m_Drift; ///< Global signal decrease by the end of the acquisition.
bool m_DoAddGibbsRinging; ///< Add Gibbs ringing artifact
int m_ZeroRinging; ///< If > 0, ringing is simulated by by setting the defined percentage of higher frequencies to 0 in k-space. Otherwise, the input to the k-space simulation is generated with twice the resolution and cropped during k-space simulation (much slower).
bool m_DoSimulateRelaxation; ///< Add T2 relaxation effects
bool m_DoAddMotion; ///< Enable motion artifacts.
bool m_DoRandomizeMotion; ///< Toggles between random and linear motion.
bool m_DoAddDrift; ///< Add quadratic signal drift.
std::vector< bool > m_MotionVolumes; ///< Indicates the image volumes that are affected by motion
///< with positive numbers, inverted logic with negative numbers.
itk::Vector<float,3> m_Translation; ///< Maximum translational motion.
itk::Vector<float,3> m_Rotation; ///< Maximum rotational motion.
ItkFloatImgType::Pointer m_FrequencyMap; ///< If != nullptr, distortions are added to the image using this frequency map.
ItkUcharImgType::Pointer m_MaskImage; ///< Signal is only genrated inside of the mask image.
std::vector< int > GetBaselineIndices(); ///< Returns list of nun-diffusion-weighted image volume indices
unsigned int GetFirstBaselineIndex(); ///< Returns index of first non-diffusion-weighted image volume
bool IsBaselineIndex(unsigned int idx); ///< Checks if image volume with given index is non-diffusion-weighted volume or not.
unsigned int GetNumWeightedVolumes(); ///< Get number of diffusion-weighted image volumes
unsigned int GetNumBaselineVolumes(); ///< Get number of non-diffusion-weighted image volumes
unsigned int GetNumVolumes(); ///< Get number of baseline and diffusion-weighted image volumes
GradientListType GetGradientDirections(); ///< Return gradient direction container
mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer GetItkGradientContainer();
GradientType GetGradientDirection(unsigned int i);
std::vector< int > GetBvalues(); ///< Returns a vector with all unique b-values (determined by the gradient magnitudes)
double GetBvalue();
void ApplyDirectionMatrix();
protected:
unsigned int m_NumGradients; ///< Number of diffusion-weighted image volumes.
unsigned int m_NumBaseline; ///< Number of non-diffusion-weighted image volumes.
GradientListType m_GradientDirections; ///< Total number of image volumes.
double m_Bvalue; ///< Acquisition b-value
void SetNumWeightedVolumes(int numGradients); ///< Automaticall calls GenerateGradientHalfShell() afterwards.
void SetGradienDirections(GradientListType gradientList);
void SetGradienDirections(mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradientList);
void GenerateGradientHalfShell(); ///< Generates half shell of gradient directions (with m_NumGradients non-zero directions)
};
/** Fiber generation */
class MITKMRISIMULATION_EXPORT FiberGenerationParameters
{
public:
enum FiberDistribution
{
DISTRIBUTE_UNIFORM, // distribute fibers uniformly in the ROIs
DISTRIBUTE_GAUSSIAN // distribute fibers using a 2D gaussian
};
typedef std::vector< std::vector< mitk::PlanarEllipse::Pointer > > FiducialListType;
typedef std::vector< std::vector< unsigned int > > FlipListType;
FiberGenerationParameters()
: m_Distribution(DISTRIBUTE_UNIFORM)
, m_Density(100)
, m_Variance(100)
, m_Sampling(1)
, m_Tension(0)
, m_Continuity(0)
, m_Bias(0)
{
m_Rotation.Fill(0.0);
m_Translation.Fill(0.0);
m_Scale.Fill(1.0);
}
FiberDistribution m_Distribution;
unsigned int m_Density;
double m_Variance;
double m_Sampling;
double m_Tension;
double m_Continuity;
double m_Bias;
mitk::Vector3D m_Rotation;
mitk::Vector3D m_Translation;
mitk::Vector3D m_Scale;
FlipListType m_FlipList; ///< contains flags indicating a flip of the 2D fiber x-coordinates (needed to resolve some unwanted fiber twisting)
FiducialListType m_Fiducials; ///< container of the planar ellipses used as fiducials for the fiber generation process
};
/** GUI persistence, input, output, ... */
class MITKMRISIMULATION_EXPORT MiscFiberfoxParameters
{
public:
MiscFiberfoxParameters()
: m_ResultNode(DataNode::New())
, m_ParentNode(nullptr)
, m_SignalModelString("")
, m_ArtifactModelString("")
, m_OutputPath("/tmp/")
, m_OutputPrefix("fiberfox")
, m_AfterSimulationMessage("")
, m_BvalsFile("")
, m_BvecsFile("")
, m_OutputAdditionalImages(false)
, m_CheckAdvancedSignalOptionsBox(false)
, m_DoAddNoise(false)
, m_DoAddGhosts(false)
, m_DoAddAliasing(false)
, m_DoAddSpikes(false)
, m_DoAddEddyCurrents(false)
, m_DoAddDistortions(false)
, m_MotionVolumesBox("random")
, m_CheckRealTimeFibersBox(true)
, m_CheckAdvancedFiberOptionsBox(false)
, m_CheckConstantRadiusBox(false)
, m_CheckIncludeFiducialsBox(true)
{}
DataNode::Pointer m_ResultNode; ///< Stores resulting image.
DataNode::Pointer m_ParentNode; ///< Parent node of result node.
std::string m_SignalModelString; ///< Appendet to the name of the result node
std::string m_ArtifactModelString; ///< Appendet to the name of the result node
std::string m_OutputPath; ///< Image is automatically saved to the specified folder after simulation is finished.
std::string m_OutputPrefix; /** Prefix for filename of output files and logfile. */
std::string m_AfterSimulationMessage; ///< Store messages that are displayed after the simulation has finished (e.g. warnings, automatic parameter adjustments etc.)
std::string m_BvalsFile;
std::string m_BvecsFile;
/** member variables that store the check-state of GUI checkboxes */
// image generation
bool m_OutputAdditionalImages;
bool m_CheckAdvancedSignalOptionsBox;
bool m_DoAddNoise;
bool m_DoAddGhosts;
bool m_DoAddAliasing;
bool m_DoAddSpikes;
bool m_DoAddEddyCurrents;
bool m_DoAddDistortions;
std::string m_MotionVolumesBox;
// fiber generation
bool m_CheckRealTimeFibersBox;
bool m_CheckAdvancedFiberOptionsBox;
bool m_CheckConstantRadiusBox;
bool m_CheckIncludeFiducialsBox;
};
/**
* \brief Datastructure to manage the Fiberfox signal generation parameters.
*
*/
class MITKMRISIMULATION_EXPORT FiberfoxParameters
{
public:
typedef itk::Image<float, 3> ItkFloatImgType;
typedef itk::Image<double, 3> ItkDoubleImgType;
typedef itk::Image<unsigned char, 3> ItkUcharImgType;
typedef DiffusionSignalModel<double> DiffusionModelType;
typedef std::vector< DiffusionModelType* > DiffusionModelListType;
typedef DiffusionNoiseModel<double> NoiseModelType;
FiberfoxParameters();
FiberfoxParameters(const FiberfoxParameters &params);
~FiberfoxParameters();
/** Not templated parameters */
FiberGenerationParameters m_FiberGen; ///< Fiber generation parameters
SignalGenerationParameters m_SignalGen; ///< Signal generation parameters
MiscFiberfoxParameters m_Misc; ///< GUI realted and I/O parameters
/** Templated parameters */
DiffusionModelListType m_FiberModelList; ///< Intra- and inter-axonal compartments.
DiffusionModelListType m_NonFiberModelList; ///< Extra-axonal compartments.
std::shared_ptr< NoiseModelType > m_NoiseModel; ///< If != nullptr, noise is added to the image.
void GenerateGradientHalfShell();
void SetNumWeightedVolumes(int numGradients); ///< Automaticall calls GenerateGradientHalfShell() afterwards.
void SetGradienDirections(mitk::SignalGenerationParameters::GradientListType gradientList);
void SetGradienDirections(mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradientList);
void SetBvalue(double Bvalue);
void UpdateSignalModels();
void ClearFiberParameters();
void ClearSignalParameters();
void ApplyDirectionMatrix();
void PrintSelf(); ///< Print parameters to stdout.
void SaveParameters(std::string filename); ///< Save image generation parameters to .ffp file.
void LoadParameters(std::string filename, bool fix_seed=false); ///< Load image generation parameters from .ffp file.
template< class ParameterType >
ParameterType ReadVal(boost::property_tree::ptree::value_type const& v, std::string tag, ParameterType defaultValue, bool essential=false);
std::string m_MissingTags;
};
}
#endif
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationHandler.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationHandler.cpp
index fd0072c..6d9c065 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationHandler.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationHandler.cpp
@@ -1,138 +1,138 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkFreeSurferParcellationHandler.h"
#include <mitkBaseRenderer.h>
#include <mitkDataStorage.h>
#include <mitkDataNode.h>
#include <mitkImage.h>
#include <mitkImagePixelReadAccessor.h>
#include <mitkInteractionPositionEvent.h>
#include <mitkNodePredicateDataType.h>
#include <mitkMousePressEvent.h>
#include <mitkMouseWheelEvent.h>
#include <usGetModuleContext.h>
#include <usModule.h>
#include <usModuleRegistry.h>
#include <usServiceProperties.h>
#include <string>
US_USE_NAMESPACE
QmitkFreeSurferParcellationHandler::QmitkFreeSurferParcellationHandler() :
m_LastPixelvalue( 0 ),
m_Translator( mitk::FreeSurferParcellationTranslator::New() )
{
us::ServiceProperties props;
props["name"] = std::string("ParcellationHandler");
us::ModuleContext* context = us::ModuleRegistry::GetModule(1)->GetModuleContext();
m_ServiceRegistration = context->RegisterService<InteractionEventObserver>( this, props);
}
QmitkFreeSurferParcellationHandler::~QmitkFreeSurferParcellationHandler()
{
m_ServiceRegistration.Unregister();
}
void QmitkFreeSurferParcellationHandler::Notify(InteractionEvent *interactionEvent, bool isHandled)
{
Q_UNUSED( isHandled )
BaseRenderer* sender = interactionEvent->GetSender();
InteractionPositionEvent* positionEvent = static_cast<InteractionPositionEvent*>(interactionEvent);
TNodePredicateDataType<Image>::Pointer isImageData = TNodePredicateDataType<Image>::New();
DataStorage::SetOfObjects::ConstPointer nodes = sender->GetDataStorage()->GetSubset(isImageData).GetPointer();
if(nodes.IsNull() || nodes->size() <= 0)
return;
Point3D worldposition = positionEvent->GetPositionInWorld();
for (unsigned int x = 0; x < nodes->size(); x++)
{
DataNode::Pointer node = static_cast<DataNode::Pointer>( nodes->at(x) );
if(node.IsNotNull())
{
Image::Pointer image = dynamic_cast<Image*>( node->GetData() );
if( image.IsNotNull() && image->GetGeometry()->IsInside(worldposition) )
{
std::string typeStr = image->GetPixelType().GetComponentTypeAsString();
int value = 0;
try
{
if( typeStr == "int" )
{
ImagePixelReadAccessor<int, 3> readAccess( image );
value = static_cast<int>( readAccess.GetPixelByWorldCoordinates( worldposition ) );
}
else if( typeStr == "unsigned_int" )
{
ImagePixelReadAccessor<unsigned int, 3> readAccess( image );
value = static_cast<int>( readAccess.GetPixelByWorldCoordinates( worldposition ) );
}
else if( typeStr == "unsigned_char" )
{
ImagePixelReadAccessor<unsigned char, 3> readAccess( image );
value = static_cast<int>( readAccess.GetPixelByWorldCoordinates( worldposition ) );
}
else if( typeStr == "short" )
{
ImagePixelReadAccessor<short, 3> readAccess( image );
value = static_cast<int>( readAccess.GetPixelByWorldCoordinates( worldposition ) );
}
else if( typeStr == "float" )
{
ImagePixelReadAccessor<float, 3> readAccess( image );
value = static_cast<int>( readAccess.GetPixelByWorldCoordinates( worldposition ) );
}
else if( typeStr == "double" )
{
ImagePixelReadAccessor<double, 3> readAccess( image );
value = static_cast<int>( readAccess.GetPixelByWorldCoordinates( worldposition ) );
}
else if( typeStr == "unsigned_short" )
{
ImagePixelReadAccessor<unsigned short, 3> readAccess( image );
value = static_cast<int>( readAccess.GetPixelByWorldCoordinates( worldposition ) );
}
else
{
MITK_WARN("QmitkFreeSurferParcellationHandler") << "Pixeltype '" << typeStr << "' is not implemented yet.";
return;
}
emit this->changed( value );
QString name( QString::fromStdString( this->m_Translator->GetName( value ) ) );
emit this->changed( name );
MousePressEvent::Pointer mouseEvent = dynamic_cast<MousePressEvent*>( interactionEvent );
MouseWheelEvent::Pointer wheelEvent = dynamic_cast<MouseWheelEvent*>( interactionEvent );
if(mouseEvent.IsNotNull())
{
emit this->clicked( value );
emit this->clicked( name );
}
if( wheelEvent.IsNotNull() )
{
emit this->scrolled( value );
emit this->scrolled( name );
}
return; // exit loop
}
catch( const Exception& ex )
{
MITK_WARN("QmitkFreeSurferParcellationHandler") << "Could not access image for reading pixelvalue due to: " << ex.GetDescription();
}
catch(...)
{
MITK_WARN("QmitkFreeSurferParcellationHandler") << "Could not access image for reading pixelvalue.";
}
}
}
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationHandler.h b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationHandler.h
index fd10673..5d8d6b0 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationHandler.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationHandler.h
@@ -1,97 +1,97 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkFreeSurferParcellationHandler_h
#define QmitkFreeSurferParcellationHandler_h
// MITK
#include <mitkEventStateMachine.h>
#include <mitkFreeSurferParcellationTranslator.h>
#include <mitkInteractionEventObserver.h>
// Qt
#include <QObject>
/**
* @brief This handler returns either the pixelvalue or anatomical label of the current position of the crosshair inside a visible parcellation.
* If no parcellation is visible no data is thrown.
*/
class QmitkFreeSurferParcellationHandler : public QObject, public EventStateMachine, public InteractionEventObserver
{
Q_OBJECT
public:
mitkClassMacro(QmitkFreeSurferParcellationHandler, DataInteractor)
itkNewMacro(QmitkFreeSurferParcellationHandler)
QmitkFreeSurferParcellationHandler();
~QmitkFreeSurferParcellationHandler();
// Signals
Q_SIGNALS:
/**
* @brief Emitted when pixelValue has changed
* @param value of the current selected pixel
*/
void changed(int);
/**
* @brief Emitted when pixelValue has changed
* @param anatomical label
*/
void changed(const QString &);
/**
* @brief Thrown if and only if the left mousebutton is pressed and pixelValue has changed
* @param value of the selected pixel
*/
void clicked(int);
/**
* @brief Thrown if and only if the left mousebutton is pressed and pixelValue has changed
* @param anatomical label
*/
void clicked(const QString &);
/**
* @brief Thrown if mouse scrolled and pixelvalue changed
* @param value of the selected pixel
*/
void scrolled(int);
/**
* @brief Thrown if mouse scrolled and anatomcial labl changed
* @param anatomical label
*/
void scrolled(const QString &);
// Methods
protected:
virtual void Notify(InteractionEvent* interactionEvent,bool isHandled);
// Members
protected:
/**
* @brief The current pixelvalue
*/
int m_LastPixelvalue;
/**
* @brief Translator for coverting pixelvalue into anatomical label
*/
mitk::FreeSurferParcellationTranslator::Pointer m_Translator;
/**
* Reference to the service registration of the observer,
* it is needed to unregister the observer on unload.
*/
us::ServiceRegistration<InteractionEventObserver> m_ServiceRegistration;
};
#endif //QmitkPixelvalueHandler_h
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationWidget.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationWidget.cpp
index be53e85..235ae9a 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationWidget.cpp
@@ -1,49 +1,49 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkFreeSurferParcellationWidget.h"
QmitkFreeSurferParcellationWidget::QmitkFreeSurferParcellationWidget(QWidget *parent) :
QWidget( parent ),
m_Handler( new QmitkFreeSurferParcellationHandler() )
{
this->m_View.setupUi( this );
this->connect( this->m_Handler, SIGNAL(clicked(QString)), this, SLOT(OnHandlerClicked(QString)) );
this->connect( this->m_Handler, SIGNAL(changed(QString)), this, SLOT(OnHandlerHovered(QString)) );
}
QmitkFreeSurferParcellationWidget::~QmitkFreeSurferParcellationWidget()
{
if( m_Handler )
{
this->disconnect( this->m_Handler, SIGNAL(clicked(QString)), this, SLOT(OnHandlerClicked(QString)) );
this->disconnect( this->m_Handler, SIGNAL(changed(QString)), this, SLOT(OnHandlerHovered(QString)) );
delete m_Handler;
m_Handler = nullptr;
}
}
void QmitkFreeSurferParcellationWidget::OnHandlerClicked(const QString &name)
{
this->m_View.clickedLabel->setText( name );
emit this->Clicked( name );
}
void QmitkFreeSurferParcellationWidget::OnHandlerHovered(const QString &name)
{
this->m_View.hoveredLabel->setText( name + " hovered" );
emit this->Hovered( name );
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationWidget.h
index b58c46a..c7ac275 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationWidget.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/QmitkFreeSurferParcellationWidget.h
@@ -1,66 +1,66 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkFreeSurferParcellationWidget_h
#define QmitkFreeSurferParcellationWidget_h
// Qmitk
#include "ui_QmitkFreeSurferParcellationWidgetControls.h"
#include <QmitkFreeSurferParcellationHandler.h>
// Qt
#include <QObject>
#include <QString>
#include <QWidget>
class QmitkFreeSurferParcellationWidget;
class QmitkFreeSurferParcellationWidget : public QWidget
{
Q_OBJECT
public:
typedef Ui::QmitkFreeSurferParcellationWidgetControls ViewType;
typedef QmitkFreeSurferParcellationHandler HandlerType;
// Constructors
QmitkFreeSurferParcellationWidget( QWidget* parent = 0 );
~QmitkFreeSurferParcellationWidget();
// Signals
Q_SIGNALS:
/**
* @brief Emitted when anatomical region is clicked
*/
void Clicked( const QString & );
/**
* @brief Emitted when anatomical region is hovered
*/
void Hovered( const QString & );
// Slots
protected slots:
void OnHandlerClicked( const QString & name );
void OnHandlerHovered( const QString & name );
protected:
// Members:
ViewType m_View;
HandlerType* m_Handler;
};
#endif //QmitkFreeSurferParcellationWidget_h
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/Perspectives/QmitkConnectomicsPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/Perspectives/QmitkConnectomicsPerspective.cpp
index ede510f..cc618ba 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/Perspectives/QmitkConnectomicsPerspective.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/Perspectives/QmitkConnectomicsPerspective.cpp
@@ -1,47 +1,47 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkConnectomicsPerspective.h"
#include "berryIViewLayout.h"
void QmitkConnectomicsPerspective::CreateInitialLayout(berry::IPageLayout::Pointer layout)
{
/////////////////////////////////////////////////////
// all di-app perspectives should have the following:
/////////////////////////////////////////////////////
QString editorArea = layout->GetEditorArea();
layout->AddStandaloneViewPlaceholder("org.mitk.views.viewnavigatorview", berry::IPageLayout::LEFT, 0.3f, editorArea, false);
layout->AddStandaloneView("org.mitk.views.datamanager", false, berry::IPageLayout::LEFT, 0.3f, editorArea);
layout->AddStandaloneView("org.mitk.views.controlvisualizationpropertiesview", false, berry::IPageLayout::BOTTOM, .15f, "org.mitk.views.datamanager");
berry::IFolderLayout::Pointer left =
layout->CreateFolder("org.mbi.diffusionimaginginternal.leftcontrols", berry::IPageLayout::BOTTOM, 0.15f, "org.mitk.views.controlvisualizationpropertiesview");
layout->AddStandaloneViewPlaceholder("org.mitk.views.imagenavigator", berry::IPageLayout::BOTTOM, .7f, "org.mbi.diffusionimaginginternal.leftcontrols", false);
/////////////////////////////////////////////
// here goes the perspective specific stuff
/////////////////////////////////////////////
left->AddView("org.mitk.views.connectomicsdata");
left->AddView("org.mitk.views.connectomicsstatistics");
left->AddView("org.mitk.views.connectomicsnetworkoperations");
left->AddView("org.mitk.views.randomparcellationview");
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/Perspectives/QmitkConnectomicsPerspective.h b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/Perspectives/QmitkConnectomicsPerspective.h
index 0e9bbb7..6be6d98 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/Perspectives/QmitkConnectomicsPerspective.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/Perspectives/QmitkConnectomicsPerspective.h
@@ -1,36 +1,36 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkConnectomicsPerspective_H_
#define QmitkConnectomicsPerspective_H_
#include <berryIPerspectiveFactory.h>
class QmitkConnectomicsPerspective : public QObject, public berry::IPerspectiveFactory
{
Q_OBJECT
Q_INTERFACES(berry::IPerspectiveFactory)
public:
QmitkConnectomicsPerspective() {}
~QmitkConnectomicsPerspective() {}
void CreateInitialLayout(berry::IPageLayout::Pointer layout) override;
};
#endif /* QmitkConnectomicsPerspective_H_ */
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsDataView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsDataView.cpp
index 8345854..7c90103 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsDataView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsDataView.cpp
@@ -1,522 +1,522 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// ####### Blueberry includes #######
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// ####### Qmitk includes #######
#include "QmitkConnectomicsDataView.h"
// ####### Qt includes #######
#include <QMessageBox>
// ####### ITK includes #######
#include <itkRGBAPixel.h>
// ####### MITK includes #######
#include <mitkConnectomicsConstantsManager.h>
#include "mitkConnectomicsSyntheticNetworkGenerator.h"
#include "mitkConnectomicsSimulatedAnnealingManager.h"
#include "mitkConnectomicsSimulatedAnnealingPermutationModularity.h"
#include "mitkConnectomicsSimulatedAnnealingCostFunctionModularity.h"
#include <mitkCorrelationCalculator.h>
// Includes for image casting between ITK and MITK
#include "mitkImageCast.h"
#include "mitkITKImageImport.h"
#include "mitkImageAccessByItk.h"
const std::string QmitkConnectomicsDataView::VIEW_ID = "org.mitk.views.connectomicsdata";
QmitkConnectomicsDataView::QmitkConnectomicsDataView()
: QmitkAbstractView()
, m_Controls( 0 )
, m_ConnectomicsNetworkCreator( mitk::ConnectomicsNetworkCreator::New() )
, m_demomode( false )
, m_currentIndex( 0 )
{
}
QmitkConnectomicsDataView::~QmitkConnectomicsDataView()
{
}
void QmitkConnectomicsDataView::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::QmitkConnectomicsDataViewControls;
m_Controls->setupUi( parent );
QObject::connect( m_Controls->networkifyPushButton, SIGNAL(clicked()), this, SLOT(OnNetworkifyPushButtonClicked()) );
QObject::connect( m_Controls->syntheticNetworkCreationPushButton, SIGNAL(clicked()), this, SLOT(OnSyntheticNetworkCreationPushButtonClicked()) );
QObject::connect( (QObject*)( m_Controls->syntheticNetworkComboBox ), SIGNAL(currentIndexChanged (int)), this, SLOT(OnSyntheticNetworkComboBoxCurrentIndexChanged(int)) );
QObject::connect( m_Controls->createCorrelationMatrixPushButton, SIGNAL(clicked()), this, SLOT(OnCreateCorrelationMatrixPushButtonClicked()) );
}
// GUI is different for developer and demo mode
m_demomode = true;
if( m_demomode )
{
this->m_Controls->networkifyPushButton->show();
this->m_Controls->networkifyPushButton->setText( "Create Network" );
this->m_Controls->syntheticNetworkOptionsGroupBox->show();
//--------------------------- fill comboBox---------------------------
this->m_Controls->syntheticNetworkComboBox->insertItem(0,"Regular lattice");
this->m_Controls->syntheticNetworkComboBox->insertItem(1,"Heterogenic sphere");
this->m_Controls->syntheticNetworkComboBox->insertItem(2,"Random network");
this->m_Controls->mappingStrategyComboBox->insertItem(m_ConnectomicsNetworkCreator->EndElementPosition, "Use label of end position of fibers");
this->m_Controls->mappingStrategyComboBox->insertItem(m_ConnectomicsNetworkCreator->EndElementPositionAvoidingWhiteMatter, "Extrapolate label");
}
else
{
this->m_Controls->networkifyPushButton->show();
this->m_Controls->networkifyPushButton->setText( "Networkify" );
this->m_Controls->syntheticNetworkOptionsGroupBox->show();
//--------------------------- fill comboBox---------------------------
this->m_Controls->syntheticNetworkComboBox->insertItem(0,"Regular lattice");
this->m_Controls->syntheticNetworkComboBox->insertItem(1,"Heterogenic sphere");
this->m_Controls->syntheticNetworkComboBox->insertItem(2,"Random network");
this->m_Controls->syntheticNetworkComboBox->insertItem(3,"Scale free network");
this->m_Controls->syntheticNetworkComboBox->insertItem(4,"Small world network");
this->m_Controls->mappingStrategyComboBox->insertItem(m_ConnectomicsNetworkCreator->EndElementPosition, "Use label of end position of fibers");
this->m_Controls->mappingStrategyComboBox->insertItem(m_ConnectomicsNetworkCreator->EndElementPositionAvoidingWhiteMatter, "Extrapolate label");
this->m_Controls->mappingStrategyComboBox->insertItem(m_ConnectomicsNetworkCreator->JustEndPointVerticesNoLabel, "Use end position of fibers, no label");
}
this->WipeDisplay();
}
void QmitkConnectomicsDataView::SetFocus()
{
m_Controls->mappingStrategyComboBox->setFocus();
}
void QmitkConnectomicsDataView::WipeDisplay()
{
m_Controls->lblWarning->setVisible( true );
m_Controls->inputImageOneNameLabel->setText( mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_DASH );
m_Controls->inputImageOneNameLabel->setVisible( false );
m_Controls->inputImageOneLabel->setVisible( false );
m_Controls->inputImageTwoNameLabel->setText( mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_DASH );
m_Controls->inputImageTwoNameLabel->setVisible( false );
m_Controls->inputImageTwoLabel->setVisible( false );
}
void QmitkConnectomicsDataView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList<mitk::DataNode::Pointer>& nodes)
{
this->WipeDisplay();
// Valid options are either
// 1 image (parcellation)
//
// 1 image (parcellation)
// 1 fiber bundle
//
// 1 network
if( nodes.size() > 2 )
{
return;
}
bool alreadyFiberBundleSelected( false ), alreadyImageSelected( false ), currentFormatUnknown( true );
// iterate all selected objects, adjust warning visibility
for (mitk::DataNode::Pointer node: nodes)
{
currentFormatUnknown = true;
if( node.IsNotNull() && dynamic_cast<mitk::Image*>(node->GetData()) )
{
currentFormatUnknown = false;
if( alreadyImageSelected )
{
this->WipeDisplay();
return;
}
alreadyImageSelected = true;
m_Controls->lblWarning->setVisible( false );
m_Controls->inputImageOneNameLabel->setText(node->GetName().c_str());
m_Controls->inputImageOneNameLabel->setVisible( true );
m_Controls->inputImageOneLabel->setVisible( true );
}
if( node.IsNotNull() && dynamic_cast<mitk::FiberBundle*>(node->GetData()) )
{
currentFormatUnknown = false;
// a fiber bundle has to be in conjunction with a parcellation
if( nodes.size() != 2 || alreadyFiberBundleSelected )
{
this->WipeDisplay();
return;
}
alreadyFiberBundleSelected = true;
m_Controls->lblWarning->setVisible( false );
m_Controls->inputImageTwoNameLabel->setText(node->GetName().c_str());
m_Controls->inputImageTwoNameLabel->setVisible( true );
m_Controls->inputImageTwoLabel->setVisible( true );
}
{ // network section
mitk::ConnectomicsNetwork* network = dynamic_cast<mitk::ConnectomicsNetwork*>( node->GetData() );
if( node.IsNotNull() && network )
{
currentFormatUnknown = false;
if( nodes.size() != 1 )
{
// only valid option is a single network
this->WipeDisplay();
return;
}
m_Controls->lblWarning->setVisible( false );
m_Controls->inputImageOneNameLabel->setText(node->GetName().c_str());
m_Controls->inputImageOneNameLabel->setVisible( true );
m_Controls->inputImageOneLabel->setVisible( true );
}
} // end network section
if ( currentFormatUnknown )
{
this->WipeDisplay();
return;
}
} // end for loop
}
void QmitkConnectomicsDataView::OnSyntheticNetworkComboBoxCurrentIndexChanged(int currentIndex)
{
m_currentIndex = currentIndex;
switch (m_currentIndex) {
case 0:
this->m_Controls->parameterOneLabel->setText( "Nodes per side" );
this->m_Controls->parameterTwoLabel->setText( "Internode distance" );
this->m_Controls->parameterOneSpinBox->setEnabled( true );
this->m_Controls->parameterOneSpinBox->setValue( 5 );
this->m_Controls->parameterTwoDoubleSpinBox->setEnabled( true );
this->m_Controls->parameterTwoDoubleSpinBox->setMaximum( 999.999 );
this->m_Controls->parameterTwoDoubleSpinBox->setValue( 10.0 );
break;
case 1:
this->m_Controls->parameterOneLabel->setText( "Number of nodes" );
this->m_Controls->parameterTwoLabel->setText( "Radius" );
this->m_Controls->parameterOneSpinBox->setEnabled( true );
this->m_Controls->parameterOneSpinBox->setValue( 1000 );
this->m_Controls->parameterTwoDoubleSpinBox->setEnabled( true );
this->m_Controls->parameterTwoDoubleSpinBox->setMaximum( 999.999 );
this->m_Controls->parameterTwoDoubleSpinBox->setValue( 50.0 );
break;
case 2:
this->m_Controls->parameterOneLabel->setText( "Number of nodes" );
this->m_Controls->parameterTwoLabel->setText( "Edge percentage" );
this->m_Controls->parameterOneSpinBox->setEnabled( true );
this->m_Controls->parameterOneSpinBox->setValue( 100 );
this->m_Controls->parameterTwoDoubleSpinBox->setEnabled( true );
this->m_Controls->parameterTwoDoubleSpinBox->setMaximum( 1.0 );
this->m_Controls->parameterTwoDoubleSpinBox->setValue( 0.5 );
break;
case 3:
//GenerateSyntheticScaleFreeNetwork( network, 1000 );
break;
case 4:
//GenerateSyntheticSmallWorldNetwork( network, 1000 );
break;
default:
this->m_Controls->parameterOneLabel->setText( "Parameter 1" );
this->m_Controls->parameterTwoLabel->setText( "Paramater 2" );
this->m_Controls->parameterOneSpinBox->setEnabled( false );
this->m_Controls->parameterOneSpinBox->setValue( 0 );
this->m_Controls->parameterTwoDoubleSpinBox->setEnabled( false );
this->m_Controls->parameterTwoDoubleSpinBox->setValue( 0.0 );
}
}
void QmitkConnectomicsDataView::OnSyntheticNetworkCreationPushButtonClicked()
{
// warn if trying to create a very big network
// big network is a network with > 5000 nodes (estimate)
// this might fill up the memory to the point it freezes
int numberOfNodes( 0 );
switch (m_currentIndex) {
case 0:
numberOfNodes = this->m_Controls->parameterOneSpinBox->value()
* this->m_Controls->parameterOneSpinBox->value()
* this->m_Controls->parameterOneSpinBox->value();
break;
case 1:
numberOfNodes = this->m_Controls->parameterOneSpinBox->value();
break;
case 2:
numberOfNodes = this->m_Controls->parameterOneSpinBox->value();
break;
case 3:
// not implemented yet
break;
case 4:
// not implemented yet
break;
default:
break;
}
if( numberOfNodes > 5000 )
{
QMessageBox msgBox;
msgBox.setText("Trying to generate very large network.");
msgBox.setIcon( QMessageBox::Warning );
msgBox.setInformativeText("You are trying to generate a network with more than 5000 nodes, this is very resource intensive and might lead to program instability. Proceed with network generation?");
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::No);
int ret = msgBox.exec();
switch (ret) {
case QMessageBox::Yes:
// continue
break;
case QMessageBox::No:
// stop
return;
break;
default:
// should never be reached
break;
}
}
// proceed
mitk::ConnectomicsSyntheticNetworkGenerator::Pointer generator = mitk::ConnectomicsSyntheticNetworkGenerator::New();
mitk::DataNode::Pointer networkNode = mitk::DataNode::New();
int parameterOne = this->m_Controls->parameterOneSpinBox->value();
double parameterTwo = this->m_Controls->parameterTwoDoubleSpinBox->value();
//add network to datastorage
networkNode->SetData( generator->CreateSyntheticNetwork( m_currentIndex, parameterOne, parameterTwo ) );
networkNode->SetName( mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_DEFAULT_CNF_NAME );
if( generator->WasGenerationSuccessfull() )
{
this->GetDataStorage()->Add( networkNode );
}
else
{
MITK_WARN << "Problem occured during synthetic network generation.";
}
mitk::RenderingManager::GetInstance()->InitializeViews(
networkNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
return;
}
void QmitkConnectomicsDataView::OnNetworkifyPushButtonClicked()
{
QList<mitk::DataNode::Pointer> nodes = this->GetDataManagerSelection();
if ( nodes.empty() )
{
QMessageBox::information( nullptr, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS_CREATION, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_SELECTION_WARNING);
return;
}
if (! ( nodes.size() == 2 ) )
{
QMessageBox::information( nullptr, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS_CREATION, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_SELECTION_WARNING);
return;
}
mitk::DataNode* firstNode = nodes.front();
mitk::DataNode* secondNode = nodes.at(1);
if (!firstNode)
{
// Nothing selected. Inform the user and return
QMessageBox::information( nullptr, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS_CREATION, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_SELECTION_WARNING);
return;
}
// here we have a valid mitk::DataNode
// a node itself is not very useful, we need its data item (the image)
mitk::BaseData* firstData = firstNode->GetData();
mitk::BaseData* secondData = secondNode->GetData();
if (firstData && secondData)
{
// test if this data item is an image or not (could also be a surface or something totally different)
mitk::Image* image = dynamic_cast<mitk::Image*>( firstData );
mitk::FiberBundle* fiberBundle = dynamic_cast<mitk::FiberBundle*>( secondData );
// check whether order was switched
if (! (image && fiberBundle) )
{
image = dynamic_cast<mitk::Image*>( secondData );
fiberBundle = dynamic_cast<mitk::FiberBundle*>( firstData );
}
if (image && fiberBundle)
{
mitk::ConnectomicsNetworkCreator::MappingStrategy mappingStrategy =
static_cast<mitk::ConnectomicsNetworkCreator::MappingStrategy>(this->m_Controls->mappingStrategyComboBox->currentIndex());
m_ConnectomicsNetworkCreator->SetSegmentation( image );
m_ConnectomicsNetworkCreator->SetFiberBundle( fiberBundle );
m_ConnectomicsNetworkCreator->CalculateCenterOfMass();
m_ConnectomicsNetworkCreator->SetEndPointSearchRadius( 15 );
m_ConnectomicsNetworkCreator->SetMappingStrategy( mappingStrategy );
m_ConnectomicsNetworkCreator->CreateNetworkFromFibersAndSegmentation();
mitk::DataNode::Pointer networkNode = mitk::DataNode::New();
//add network to datastorage
networkNode->SetData( m_ConnectomicsNetworkCreator->GetNetwork() );
networkNode->SetName( mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_DEFAULT_CNF_NAME );
this->GetDataStorage()->Add( networkNode );
}
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkConnectomicsDataView::OnCreateCorrelationMatrixPushButtonClicked()
{
QList<mitk::DataNode::Pointer> nodes = this->GetDataManagerSelection();
if ( nodes.empty() )
{
QMessageBox::information( nullptr, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_FMRI_CORRELATION_SELECTION_WARNING);
return;
}
if( nodes.size() == 1 )
{
mitk::DataNode* firstNode = nodes.front();
if (!firstNode)
{
// Nothing selected. Inform the user and return
QMessageBox::information( nullptr, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_FMRI_CORRELATION_SELECTION_WARNING);
return;
}
// here we have a valid mitk::DataNode
// a node itself is not very useful, we need its data item (the image)
mitk::BaseData* firstData = firstNode->GetData();
if (firstData)
{
// test if this data item is an image or not (could also be a surface or something totally different)
mitk::Image* image = dynamic_cast<mitk::Image*>( firstData );
if(image && image->GetDimension() == 4)
{
AccessFixedDimensionByItk(image, DoWholeCorrelation, 4);
}
}
}
else if( nodes.size() == 2 )
{
mitk::DataNode* firstNode = nodes.front();
mitk::DataNode* secondNode = nodes.at(1);
if (!firstNode)
{
// Nothing selected. Inform the user and return
QMessageBox::information( nullptr, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_FMRI_CORRELATION_SELECTION_WARNING);
return;
}
if (!secondNode)
{
// Nothing selected. Inform the user and return
QMessageBox::information( nullptr, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_FMRI_CORRELATION_SELECTION_WARNING);
return;
}
// here we have a valid mitk::DataNode
// a node itself is not very useful, we need its data item (the image)
mitk::BaseData* firstData = firstNode->GetData();
mitk::BaseData* secondData = secondNode->GetData();
if (firstData && secondData)
{
// test if this data item is an image or not (could also be a surface or something totally different)
mitk::Image* firstImage = dynamic_cast<mitk::Image*>( firstData );
mitk::Image* secondImage = dynamic_cast<mitk::Image*>( secondData );
if(firstImage && secondImage)
{
if( firstImage->GetDimension() == 4 && secondImage->GetDimension() == 3 )
{
AccessFixedDimensionByItk_n(firstImage, DoParcelCorrelation, 4, ( secondImage));
}
else if( firstImage->GetDimension() == 3 && secondImage->GetDimension() == 4 )
{
AccessFixedDimensionByItk_n(secondImage, DoParcelCorrelation, 4, ( firstImage));
}
else
{
QMessageBox::information( nullptr, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_FMRI_CORRELATION_SELECTION_WARNING);
return;
}
}
}
}
}
template< typename TPixel, unsigned int VImageDimension >
void QmitkConnectomicsDataView::DoWholeCorrelation( itk::Image<TPixel, VImageDimension>* itkTimeSeriesImage )
{
typename mitk::CorrelationCalculator<TPixel>::Pointer correlationCalculator = mitk::CorrelationCalculator<TPixel>::New();
mitk::Image::Pointer timeSeriesImage = mitk::Image::New();
mitk::CastToMitkImage(itkTimeSeriesImage, timeSeriesImage);
correlationCalculator->SetTimeSeriesImage( timeSeriesImage );
correlationCalculator->SetParcellationImage( nullptr );
correlationCalculator->DoWholeCorrelation();
const vnl_matrix< double >* vnlmat = correlationCalculator->GetCorrelationMatrix();
std::stringstream output;
for(unsigned int i(0); i < (*vnlmat).rows(); ++i)
{
for(unsigned int j(0); j < (*vnlmat).cols(); ++j)
{
output << (*vnlmat)[i][j] << " ";
}
output << "\n";
}
MITK_INFO << "\n" << output.str();
}
template< typename TPixel, unsigned int VImageDimension >
void QmitkConnectomicsDataView::DoParcelCorrelation( itk::Image<TPixel, VImageDimension>* itkTimeSeriesImage, mitk::Image::Pointer parcelImage )
{
typename mitk::CorrelationCalculator<TPixel>::Pointer correlationCalculator = mitk::CorrelationCalculator<TPixel>::New();
mitk::Image::Pointer timeSeriesImage = mitk::Image::New();
mitk::CastToMitkImage(itkTimeSeriesImage, timeSeriesImage);
correlationCalculator->SetTimeSeriesImage( timeSeriesImage );
correlationCalculator->SetParcellationImage( parcelImage );
correlationCalculator->DoParcelCorrelation();
mitk::DataNode::Pointer networkNode = mitk::DataNode::New();
networkNode->SetData( correlationCalculator->GetConnectomicsNetwork() );
networkNode->SetName("ParcelCorrelationNetwork");
this->GetDataStorage()->Add(networkNode);
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsDataView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsDataView.h
index ae60200..e43c573 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsDataView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsDataView.h
@@ -1,109 +1,109 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkConnectomicsDataView_h
#define QmitkConnectomicsDataView_h
#include <berryISelectionListener.h>
#include <QmitkAbstractView.h>
#include "ui_QmitkConnectomicsDataViewControls.h"
#include "mitkConnectomicsNetworkCreator.h"
#include "mitkConnectomicsNetworkMapper3D.h"
// ####### ITK includes #######
#include <itkImage.h>
/*!
\brief QmitkConnectomicsDataView
This view provides functionality for the generation of networks. Either from parcellation and fiber bundle or synthetically.
*/
class QmitkConnectomicsDataView : public QmitkAbstractView
{
// 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;
QmitkConnectomicsDataView();
virtual ~QmitkConnectomicsDataView();
virtual void CreateQtPartControl(QWidget *parent) override;
///
/// Sets the focus to an internal widget.
///
virtual void SetFocus() override;
protected slots:
/// \brief Align two images by copying the geometry
void OnNetworkifyPushButtonClicked();
/// \brief Create synthetic networks
void OnSyntheticNetworkCreationPushButtonClicked();
/// \brief Adjust parameters depending on synthetic network type
void OnSyntheticNetworkComboBoxCurrentIndexChanged(int currentIndex);
/// \brief Create #voxel x #voxel correlation matrix of a timeseries image
void OnCreateCorrelationMatrixPushButtonClicked();
protected:
// ####### Functions #######
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
/// \brief Converts an image into a RGBA image
template < typename TPixel, unsigned int VImageDimension >
void TurnIntoRGBA( itk::Image<TPixel, VImageDimension>* inputImage);
/// \brief Wipe display and empty statistics
void WipeDisplay();
template< typename TPixel, unsigned int VImageDimension >
void DoWholeCorrelation( itk::Image<TPixel, VImageDimension>* itkTimeSeriesImage );
template< typename TPixel, unsigned int VImageDimension >
void DoParcelCorrelation( itk::Image<TPixel, VImageDimension>* itkTimeSeriesImage, mitk::Image::Pointer parcelImage );
// ####### Variables #######
Ui::QmitkConnectomicsDataViewControls* m_Controls;
mitk::ConnectomicsNetworkCreator::Pointer m_ConnectomicsNetworkCreator;
mitk::ConnectomicsNetworkMapper3D::Pointer m_NetworkMapper;
// Demo/Developer mode toggle
bool m_demomode;
// The selected synthetic network type
int m_currentIndex;
};
#endif // _QMITKBRAINNETWORKANALYSISVIEW_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsNetworkOperationsView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsNetworkOperationsView.cpp
index 2ebd762..e3b1532 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsNetworkOperationsView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsNetworkOperationsView.cpp
@@ -1,564 +1,564 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// ####### Blueberry includes #######
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// ####### Qmitk includes #######
#include "QmitkConnectomicsNetworkOperationsView.h"
// ####### Qt includes #######
#include <QMessageBox>
// ####### ITK includes #######
#include <itkRGBAPixel.h>
// ####### MITK includes #######
#include <mitkConnectomicsConstantsManager.h>
#include "mitkConnectomicsSimulatedAnnealingManager.h"
#include "mitkConnectomicsSimulatedAnnealingPermutationModularity.h"
#include "mitkConnectomicsSimulatedAnnealingCostFunctionModularity.h"
#include <itkConnectomicsNetworkToConnectivityMatrixImageFilter.h>
#include <mitkConnectomicsNetworkThresholder.h>
#include <mitkFreeSurferParcellationTranslator.h>
#include <mitkRenderingModeProperty.h>
// Includes for image casting between ITK and MITK
#include "mitkImageCast.h"
#include "mitkITKImageImport.h"
#include "mitkImageAccessByItk.h"
const std::string QmitkConnectomicsNetworkOperationsView::VIEW_ID = "org.mitk.views.connectomicsnetworkoperations";
QmitkConnectomicsNetworkOperationsView::QmitkConnectomicsNetworkOperationsView()
: QmitkAbstractView()
, m_Controls( 0 )
, m_demomode( false )
, m_currentIndex( 0 )
{
}
QmitkConnectomicsNetworkOperationsView::~QmitkConnectomicsNetworkOperationsView()
{
}
void QmitkConnectomicsNetworkOperationsView::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::QmitkConnectomicsNetworkOperationsViewControls;
m_Controls->setupUi( parent );
QObject::connect( m_Controls->convertToRGBAImagePushButton, SIGNAL(clicked()), this, SLOT(OnConvertToRGBAImagePushButtonClicked()) );
QObject::connect( m_Controls->assignFreeSurferColorsPushButton, SIGNAL(clicked()), this, SLOT(OnAssignFreeSurferColorsPushButtonClicked()) );
QObject::connect( (QObject*)( m_Controls->modularizePushButton ), SIGNAL(clicked()), this, SLOT(OnModularizePushButtonClicked()) );
QObject::connect( (QObject*)( m_Controls->prunePushButton ), SIGNAL(clicked()), this, SLOT(OnPrunePushButtonClicked()) );
QObject::connect( (QObject*)( m_Controls->createConnectivityMatrixImagePushButton ), SIGNAL(clicked()), this, SLOT(OnCreateConnectivityMatrixImagePushButtonClicked()) );
}
// GUI is different for developer and demo mode
m_demomode = true;
if( m_demomode )
{
this->m_Controls->convertToRGBAImagePushButton->show();
this->m_Controls->assignFreeSurferColorsPushButton->show();
this->m_Controls->modularizePushButton->hide();
this->m_Controls->pruneOptionsGroupBox->show();
}
else
{
this->m_Controls->convertToRGBAImagePushButton->show();
this->m_Controls->assignFreeSurferColorsPushButton->show();
this->m_Controls->modularizePushButton->show();
this->m_Controls->pruneOptionsGroupBox->show();
}
this->WipeDisplay();
}
void QmitkConnectomicsNetworkOperationsView::SetFocus()
{
m_Controls->convertToRGBAImagePushButton->setFocus();
}
void QmitkConnectomicsNetworkOperationsView::WipeDisplay()
{
m_Controls->lblWarning->setVisible( true );
m_Controls->inputImageOneNameLabel->setText( mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_DASH );
m_Controls->inputImageOneNameLabel->setVisible( false );
m_Controls->inputImageOneLabel->setVisible( false );
}
void QmitkConnectomicsNetworkOperationsView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList<mitk::DataNode::Pointer>& nodes)
{
this->WipeDisplay();
// Valid options are either
if( nodes.size() > 2 )
{
return;
}
bool currentFormatUnknown(true), alreadyImageSelected(false);
// iterate all selected objects, adjust warning visibility
for (mitk::DataNode::Pointer node: nodes)
{
currentFormatUnknown = true;
if( node.IsNotNull() && dynamic_cast<mitk::Image*>(node->GetData()) )
{
currentFormatUnknown = false;
if( alreadyImageSelected )
{
this->WipeDisplay();
return;
}
alreadyImageSelected = true;
m_Controls->lblWarning->setVisible( false );
m_Controls->inputImageOneNameLabel->setText(node->GetName().c_str());
m_Controls->inputImageOneNameLabel->setVisible( true );
m_Controls->inputImageOneLabel->setVisible( true );
}
if( node.IsNotNull() )
{ // network section
mitk::ConnectomicsNetwork* network = dynamic_cast<mitk::ConnectomicsNetwork*>( node->GetData() );
if( network )
{
currentFormatUnknown = false;
if( nodes.size() != 1 )
{
// only valid option is a single network
this->WipeDisplay();
return;
}
m_Controls->lblWarning->setVisible( false );
m_Controls->inputImageOneNameLabel->setText(node->GetName().c_str());
m_Controls->inputImageOneNameLabel->setVisible( true );
m_Controls->inputImageOneLabel->setVisible( true );
}
} // end network section
if ( currentFormatUnknown )
{
this->WipeDisplay();
return;
}
} // end for loop
}
void QmitkConnectomicsNetworkOperationsView::OnConvertToRGBAImagePushButtonClicked()
{
QList<mitk::DataNode::Pointer> nodes = this->GetDataManagerSelection();
if (nodes.empty()) return;
mitk::DataNode* node = nodes.front();
if (!node)
{
// Nothing selected. Inform the user and return
QMessageBox::information( nullptr, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_ONLY_PARCELLATION_SELECTION_WARNING);
return;
}
// here we have a valid mitk::DataNode
// a node itself is not very useful, we need its data item (the image)
mitk::BaseData* data = node->GetData();
if (data)
{
// test if this data item is an image or not (could also be a surface or something totally different)
mitk::Image* image = dynamic_cast<mitk::Image*>( data );
if (image)
{
std::stringstream message;
std::string name;
message << mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_PERFORMING_IMAGE_PROCESSING_FOR_IMAGE;
if (node->GetName(name))
{
// a property called "name" was found for this DataNode
message << "'" << name << "'";
}
message << ".";
MITK_INFO << message.str();
// Convert to RGBA
AccessByItk( image, TurnIntoRGBA );
this->GetDataStorage()->GetNamedNode( mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_DEFAULT_RGBA_NAME )->GetData()->SetGeometry( node->GetData()->GetGeometry() );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
else
{
QMessageBox::information( nullptr, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_ONLY_PARCELLATION_SELECTION_WARNING);
return;
}
}
else
{
QMessageBox::information( nullptr, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_ONLY_PARCELLATION_SELECTION_WARNING);
return;
}
}
void QmitkConnectomicsNetworkOperationsView::OnAssignFreeSurferColorsPushButtonClicked()
{
QList<mitk::DataNode::Pointer> nodes = this->GetDataManagerSelection();
if (nodes.empty()) return;
mitk::DataNode* node = nodes.front();
if (!node)
{
// Nothing selected. Inform the user and return
QMessageBox::information( nullptr, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_ONLY_PARCELLATION_SELECTION_WARNING);
return;
}
// here we have a valid mitk::DataNode
// a node itself is not very useful, we need its data item (the image)
mitk::BaseData* data = node->GetData();
if (data)
{
// test if this data item is an image or not (could also be a surface or something totally different)
mitk::Image* image = dynamic_cast<mitk::Image*>( data );
if (image)
{
std::stringstream message;
std::string name;
message << mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_PERFORMING_IMAGE_PROCESSING_FOR_IMAGE;
if (node->GetName(name))
{
// a property called "name" was found for this DataNode
message << "'" << name << "'";
}
message << ".";
MITK_INFO << message.str();
// Convert to RGBA
AssignFreeSurferColors( node );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
else
{
QMessageBox::information( nullptr, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_ONLY_PARCELLATION_SELECTION_WARNING);
return;
}
}
else
{
QMessageBox::information( nullptr, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_CONNECTOMICS, mitk::ConnectomicsConstantsManager::CONNECTOMICS_GUI_ONLY_PARCELLATION_SELECTION_WARNING);
return;
}
}
void QmitkConnectomicsNetworkOperationsView::AssignFreeSurferColors( mitk::DataNode::Pointer node )
{
mitk::FreeSurferParcellationTranslator::Pointer translator = mitk::FreeSurferParcellationTranslator::New();
//translator->AssignLookupTable(node);
translator->AssignTransferFunction(node);
node->SetProperty("Image Rendering.Mode", mitk::RenderingModeProperty::New(mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_COLOR));
}
template < typename TPixel, unsigned int VImageDimension >
void QmitkConnectomicsNetworkOperationsView::TurnIntoRGBA( itk::Image<TPixel, VImageDimension>* inputImage)
{
typedef itk::RGBAPixel< unsigned char > RGBAPixelType;
typedef itk::Image< TPixel, VImageDimension > TemplateImageType;
typedef itk::Image< RGBAPixelType, VImageDimension > RGBAImageType;
itk::ImageRegionIterator<TemplateImageType> it_inputImage(inputImage, inputImage->GetLargestPossibleRegion());
TPixel minimumValue, maximumValue;
it_inputImage.GoToBegin();
maximumValue = minimumValue = it_inputImage.Value();
for(it_inputImage.GoToBegin(); !it_inputImage.IsAtEnd(); ++it_inputImage)
{
if ( it_inputImage.Value() < minimumValue )
{
minimumValue = it_inputImage.Value();
}
else
{
if ( it_inputImage.Value() > maximumValue )
{
maximumValue = it_inputImage.Value();
}
}
}
int range = int ( maximumValue - minimumValue ); //needs to be castable to int
int offset = int ( minimumValue );
if ( range < 0 ) //error
{
return;
}
std::vector< unsigned int > histogram;
histogram.resize( range + 1, 0 );
for(it_inputImage.GoToBegin(); !it_inputImage.IsAtEnd(); ++it_inputImage)
{
histogram[ int ( it_inputImage.Value() ) - offset ] += 1;
}
int gapCounter = 0; //this variable will be used to count the empty labels
//stores how much has to be subtracted from the image to remove gaps
std::vector< TPixel > subtractionStorage;
subtractionStorage.resize( range + 1, 0 );
for( int index = 0; index <= range; index++ )
{
if( histogram[ index ] == 0 )
{
gapCounter++; //if the label is empty, increase gapCounter
}
else
{
subtractionStorage[ index ] = TPixel ( gapCounter );
}
}
//remove gaps from label image
//for(it_inputImage.GoToBegin(); !it_inputImage.IsAtEnd(); ++it_inputImage)
//{
// it_inputImage.Value() = it_inputImage.Value() - subtractionStorage[int ( it_inputImage.Value() ) - offset ];
//}
// create colour vector
std::vector< RGBAPixelType > lookupTable;
{
RGBAPixelType backgroundColour;
for( int elementIndex = 0; elementIndex < 4; ++elementIndex )
{
backgroundColour.SetElement( elementIndex, 0 );
}
lookupTable.push_back( backgroundColour );
for(int colourNumber = 0; colourNumber < range ; ++colourNumber)
{
RGBAPixelType colour;
for( int elementIndex = 0; elementIndex < 3; ++elementIndex )
{
colour.SetElement( elementIndex, rand() % 256 );
}
colour.SetAlpha( 255 );
lookupTable.push_back( colour );
}
}
// create RGBA image
typename RGBAImageType::Pointer rgbaImage = RGBAImageType::New();
rgbaImage->SetRegions(inputImage->GetLargestPossibleRegion().GetSize());
rgbaImage->SetSpacing(inputImage->GetSpacing());
rgbaImage->SetOrigin(inputImage->GetOrigin());
rgbaImage->Allocate();
//fill with appropriate colours
itk::ImageRegionIterator<RGBAImageType> it_rgbaImage(rgbaImage, rgbaImage->GetLargestPossibleRegion());
for(it_inputImage.GoToBegin(), it_rgbaImage.GoToBegin(); !it_inputImage.IsAtEnd(); ++it_inputImage, ++it_rgbaImage)
{
it_rgbaImage.Value() = lookupTable[ int ( it_inputImage.Value() - subtractionStorage[int ( it_inputImage.Value() ) - offset ] ) - offset ];
}
mitk::Image::Pointer mitkRGBAImage = mitk::ImportItkImage( rgbaImage )->Clone();
mitk::DataNode::Pointer rgbaImageNode = mitk::DataNode::New();
rgbaImageNode->SetData(mitkRGBAImage);
rgbaImageNode->SetProperty(mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_NAME, mitk::StringProperty::New(mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_DEFAULT_RGBA_NAME));
rgbaImageNode->SetBoolProperty( mitk::ConnectomicsConstantsManager::CONNECTOMICS_PROPERTY_VOLUMERENDERING, true);
this->GetDataStorage()->Add( rgbaImageNode );
}
void QmitkConnectomicsNetworkOperationsView::OnModularizePushButtonClicked()
{
QList<mitk::DataNode::Pointer> nodes = this->GetDataManagerSelection();
if ( nodes.empty() )
{
QMessageBox::information( nullptr, "Modularization calculation", "Please select exactly one network.");
return;
}
for (auto node: nodes)
{
if( node.IsNotNull() && dynamic_cast<mitk::Image*>(node->GetData()) )
{
return;
}
{
mitk::ConnectomicsNetwork* network = dynamic_cast<mitk::ConnectomicsNetwork*>( node->GetData() );
if( node.IsNotNull() && network )
{
typedef mitk::ConnectomicsSimulatedAnnealingPermutationModularity::ToModuleMapType MappingType;
int depthOfModuleRecursive( 2 );
double startTemperature( 2.0 );
double stepSize( 4.0 );
mitk::ConnectomicsNetwork::Pointer connectomicsNetwork( network );
mitk::ConnectomicsSimulatedAnnealingManager::Pointer manager = mitk::ConnectomicsSimulatedAnnealingManager::New();
mitk::ConnectomicsSimulatedAnnealingPermutationModularity::Pointer permutation = mitk::ConnectomicsSimulatedAnnealingPermutationModularity::New();
mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::Pointer costFunction = mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::New();
permutation->SetCostFunction( costFunction.GetPointer() );
permutation->SetNetwork( connectomicsNetwork );
permutation->SetDepth( depthOfModuleRecursive );
permutation->SetStepSize( stepSize );
manager->SetPermutation( permutation.GetPointer() );
manager->RunSimulatedAnnealing( startTemperature, stepSize );
MappingType mapping = permutation->GetMapping();
MappingType::iterator iter = mapping.begin();
MappingType::iterator end = mapping.end();
while( iter != end )
{
MBI_DEBUG << "Vertex " << iter->first << " belongs to module " << iter->second ;
MBI_INFO << "Vertex " << iter->first << " belongs to module " << iter->second ;
iter++;
}
MBI_DEBUG << "Overall number of modules is " << permutation->getNumberOfModules( &mapping ) ;
MBI_DEBUG << "Cost is " << costFunction->Evaluate( network, &mapping ) ;
MBI_INFO << "Overall number of modules is " << permutation->getNumberOfModules( &mapping ) ;
MBI_INFO << "Cost is " << costFunction->Evaluate( network, &mapping ) ;
return;
}
}
}
}
void QmitkConnectomicsNetworkOperationsView::OnPrunePushButtonClicked()
{
QList<mitk::DataNode::Pointer> nodes = this->GetDataManagerSelection();
if ( nodes.empty() )
{
QMessageBox::information( nullptr, "Network pruning", "Please select one or more networks.");
return;
}
for (auto node: nodes)
{
if( node.IsNotNull() && dynamic_cast<mitk::Image*>(node->GetData()) )
{
return;
}
{
mitk::ConnectomicsNetwork* network = dynamic_cast<mitk::ConnectomicsNetwork*>( node->GetData() );
if( node.IsNotNull() && network )
{
mitk::ConnectomicsNetworkThresholder::Pointer thresholder = mitk::ConnectomicsNetworkThresholder::New();
thresholder->SetNetwork( network );
thresholder->SetTargetThreshold( this->m_Controls->targetThresholdSpinBox->value() );
thresholder->SetTargetDensity( this->m_Controls->densityThresholdDoubleSpinBox->value() );
if( this->m_Controls->thresholdBasedThresholdingCheckBox->isChecked() )
{
thresholder->SetThresholdingScheme( mitk::ConnectomicsNetworkThresholder::ThresholdBased );
mitk::DataNode::Pointer thresholdBasedNode = mitk::DataNode::New();
thresholdBasedNode->SetData ( thresholder->GetThresholdedNetwork() );
thresholdBasedNode->SetName( "Threshold based" );
this->GetDataStorage()->Add(thresholdBasedNode, node );
}
if( this->m_Controls->largestDensityLowerThanCheckBox->isChecked() )
{
thresholder->SetThresholdingScheme( mitk::ConnectomicsNetworkThresholder::LargestLowerThanDensity );
mitk::DataNode::Pointer thresholdBasedNode = mitk::DataNode::New();
thresholdBasedNode->SetData ( thresholder->GetThresholdedNetwork() );
thresholdBasedNode->SetName( "Largest density below threshold" );
this->GetDataStorage()->Add(thresholdBasedNode, node );
}
if( this->m_Controls->RandomRemovalThresholdingCheckBox->isChecked() )
{
thresholder->SetThresholdingScheme( mitk::ConnectomicsNetworkThresholder::RandomRemovalOfWeakest );
mitk::DataNode::Pointer thresholdBasedNode = mitk::DataNode::New();
thresholdBasedNode->SetData ( thresholder->GetThresholdedNetwork() );
thresholdBasedNode->SetName( "Random removal threshold" );
this->GetDataStorage()->Add(thresholdBasedNode, node );
}
}
}
}
}
void QmitkConnectomicsNetworkOperationsView::OnCreateConnectivityMatrixImagePushButtonClicked()
{
QList<mitk::DataNode::Pointer> nodes = this->GetDataManagerSelection();
if ( nodes.empty() )
{
QMessageBox::information( nullptr, "Connectivity Matrix Image creation", "Please select one or more networks.");
return;
}
for (auto node: nodes)
{
if( node.IsNotNull() && dynamic_cast<mitk::Image*>(node->GetData()) )
{
return;
}
{
mitk::ConnectomicsNetwork* network = dynamic_cast<mitk::ConnectomicsNetwork*>( node->GetData() );
if( node.IsNotNull() && network )
{
itk::ConnectomicsNetworkToConnectivityMatrixImageFilter::Pointer filter = itk::ConnectomicsNetworkToConnectivityMatrixImageFilter::New();
filter->SetInputNetwork( network );
filter->SetBinaryConnectivity(m_Controls->binaryCheckBox->isChecked());
filter->SetRescaleConnectivity(m_Controls->rescaleCheckBox->isChecked());
filter->Update();
mitk::Image::Pointer connectivityMatrixImage = mitk::ImportItkImage( filter->GetOutput())->Clone();
mitk::DataNode::Pointer connectivityMatrixImageNode = mitk::DataNode::New();
connectivityMatrixImageNode->SetData ( connectivityMatrixImage );
connectivityMatrixImageNode->SetName( "Connectivity matrix" );
this->GetDataStorage()->Add(connectivityMatrixImageNode, node );
}
}
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsNetworkOperationsView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsNetworkOperationsView.h
index a8b5f0e..31ce6e3 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsNetworkOperationsView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsNetworkOperationsView.h
@@ -1,107 +1,107 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkConnectomicsNetworkOperationsView_h
#define QmitkConnectomicsNetworkOperationsView_h
#include <berryISelectionListener.h>
#include <QmitkAbstractView.h>
#include "ui_QmitkConnectomicsNetworkOperationsViewControls.h"
#include "mitkConnectomicsNetworkMapper3D.h"
// ####### ITK includes #######
#include <itkImage.h>
/*!
\brief QmitkConnectomicsNetworkOperationsView
This bundle provides GUI for the brain network analysis algorithms.
*/
class QmitkConnectomicsNetworkOperationsView : public QmitkAbstractView
{
// 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;
QmitkConnectomicsNetworkOperationsView();
virtual ~QmitkConnectomicsNetworkOperationsView();
virtual void CreateQtPartControl(QWidget *parent) override;
///
/// Sets the focus to an internal widget.
///
virtual void SetFocus() override;
protected slots:
/// \brief Called when the user clicks the GUI button
void OnConvertToRGBAImagePushButtonClicked();
/// \brief Called when the user clicks the GUI button
void OnAssignFreeSurferColorsPushButtonClicked();
/// \brief Create modularization of network
void OnModularizePushButtonClicked();
/// \brief Prune network
void OnPrunePushButtonClicked();
/// \brief Create 2D Connecivity Matrix image from network
void OnCreateConnectivityMatrixImagePushButtonClicked();
protected:
// ####### Functions #######
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
/// \brief Converts an image into a RGBA image
template < typename TPixel, unsigned int VImageDimension >
void TurnIntoRGBA( itk::Image<TPixel, VImageDimension>* inputImage);
/// \brief Assigns an image the Freesurfer LUT
void AssignFreeSurferColors( mitk::DataNode::Pointer node );
/// \brief Wipe display and empty statistics
void WipeDisplay();
// ####### Variables #######
Ui::QmitkConnectomicsNetworkOperationsViewControls* m_Controls;
mitk::ConnectomicsNetworkMapper3D::Pointer m_NetworkMapper;
// Demo/Developer mode toggle
bool m_demomode;
// The selected synthetic network type
int m_currentIndex;
};
#endif // _QMITKBRAINNETWORKANALYSISVIEW_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsStatisticsView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsStatisticsView.cpp
index ab3b55e..1f10c8d 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsStatisticsView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsStatisticsView.cpp
@@ -1,212 +1,212 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
#include "QmitkConnectomicsStatisticsView.h"
#include <QMessageBox>
#include <QStringList>
#include <itkRGBAPixel.h>
#include <mbilog.h>
#include <mitkConnectomicsConstantsManager.h>
#include <mitkConnectomicsStatisticsCalculator.h>
#include <mitkConnectomicsRenderingProperties.h>
#include "mitkImageCast.h"
#include "mitkITKImageImport.h"
#include "mitkImageAccessByItk.h"
#include <mitkNodePredicateDataType.h>
#include <string>
const std::string QmitkConnectomicsStatisticsView::VIEW_ID = "org.mitk.views.connectomicsstatistics";
QmitkConnectomicsStatisticsView::QmitkConnectomicsStatisticsView()
: QmitkAbstractView()
, m_Controls( nullptr )
{
}
QmitkConnectomicsStatisticsView::~QmitkConnectomicsStatisticsView()
{
}
void QmitkConnectomicsStatisticsView::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::QmitkConnectomicsStatisticsViewControls;
m_Controls-> setupUi( parent );
connect( m_Controls-> networkBalloonsNodeLabelsComboBox, SIGNAL( currentIndexChanged( int ) ),
this, SLOT( OnNetworkBalloonsNodeLabelsComboBoxCurrentIndexChanged( ) ) );
m_Controls->m_NetworkBox->SetDataStorage(this->GetDataStorage());
mitk::TNodePredicateDataType<mitk::ConnectomicsNetwork>::Pointer isNetwork = mitk::TNodePredicateDataType<mitk::ConnectomicsNetwork>::New();
m_Controls->m_NetworkBox->SetPredicate( isNetwork );
connect( (QObject*)(m_Controls->m_NetworkBox), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()));
}
this-> WipeDisplay();
}
void QmitkConnectomicsStatisticsView::SetFocus()
{
m_Controls->networkStatisticsPlainTextEdit->setFocus();
}
void QmitkConnectomicsStatisticsView::WipeDisplay()
{
m_Controls->inputImageOneLabel->setVisible( false );
m_Controls->networkStatisticsPlainTextEdit->clear();
m_Controls->betweennessNetworkHistogramCanvas->SetHistogram( nullptr );
m_Controls->degreeNetworkHistogramCanvas->SetHistogram( nullptr );
m_Controls->shortestPathNetworkHistogramCanvas->SetHistogram( nullptr );
m_Controls->betweennessNetworkHistogramCanvas->update();
m_Controls->degreeNetworkHistogramCanvas->update();
m_Controls->shortestPathNetworkHistogramCanvas->update();
m_Controls->betweennessNetworkHistogramCanvas->Clear();
m_Controls->degreeNetworkHistogramCanvas->Clear();
m_Controls->shortestPathNetworkHistogramCanvas->Clear();
m_Controls->betweennessNetworkHistogramCanvas->Replot();
m_Controls->degreeNetworkHistogramCanvas->Replot();
m_Controls->shortestPathNetworkHistogramCanvas->Replot();
m_Controls-> networkBalloonsNodeLabelsComboBox-> QComboBox::clear();
m_Controls-> networkBalloonsPlainTextEdit-> clear();
}
void QmitkConnectomicsStatisticsView::OnNetworkBalloonsNodeLabelsComboBoxCurrentIndexChanged( )
{
QList<mitk::DataNode::Pointer> nodes = this->GetDataManagerSelection();
if( nodes.size() != 1 ) { return; }
mitk::DataNode::Pointer node = *nodes.begin();
if( node.IsNotNull() )
{
mitk::ConnectomicsNetwork* network =
dynamic_cast< mitk::ConnectomicsNetwork* >( node-> GetData() );
if( network )
{
std::string tempCurrentText = m_Controls-> networkBalloonsNodeLabelsComboBox->
QComboBox::currentText().toStdString(); // get text of currently selected item.
if( tempCurrentText.size() > 3 && tempCurrentText.rfind( ":" ) != tempCurrentText.npos )
{ // update chosenNode property.
tempCurrentText = tempCurrentText.substr( tempCurrentText.rfind( ":" ) + 2 );
node-> SetProperty( mitk::connectomicsRenderingNodeChosenNodeName.c_str(),
mitk::StringProperty::New( tempCurrentText.c_str() ) );
auto renderWindowPart = this->GetRenderWindowPart();
if (renderWindowPart)
{
renderWindowPart->ForceImmediateUpdate(); //RequestUpdate() is too slow.
}
}
std::stringstream balloonTextStream;
node-> Update();
if( node-> GetProperty( mitk::connectomicsRenderingBalloonTextName.c_str() ) != nullptr &&
node-> GetProperty( mitk::connectomicsRenderingBalloonNodeStatsName.c_str() ) != nullptr &&
tempCurrentText != "-1" )
{
balloonTextStream << node-> GetProperty( mitk::connectomicsRenderingBalloonTextName.c_str() )
-> GetValueAsString()
<< node-> GetProperty( mitk::connectomicsRenderingBalloonNodeStatsName.c_str() )
-> GetValueAsString() << std::endl;
QString balloonQString ( balloonTextStream.str().c_str() );
// setPlainText() overwrites, insertPlainText() appends.
m_Controls-> networkBalloonsPlainTextEdit-> setPlainText( balloonQString );
}
if( tempCurrentText == "-1" )
{
m_Controls-> networkBalloonsPlainTextEdit-> setPlainText( "" );
}
}
}
return;
}
void QmitkConnectomicsStatisticsView::UpdateGui()
{
this->WipeDisplay();
// iterate all selected objects, adjust warning visibility
if (m_Controls->m_NetworkBox->GetSelectedNode().IsNotNull())
{
mitk::ConnectomicsNetwork* network = dynamic_cast<mitk::ConnectomicsNetwork*>( m_Controls->m_NetworkBox->GetSelectedNode()->GetData() );
m_Controls->inputImageOneLabel->setVisible( true );
std::stringstream statisticsStream;
mitk::ConnectomicsStatisticsCalculator::Pointer calculator = mitk::ConnectomicsStatisticsCalculator::New();
calculator->SetNetwork( network );
calculator->Update();
statisticsStream << "# Vertices: " << calculator->GetNumberOfVertices() << "\n";
statisticsStream << "# Edges: " << calculator->GetNumberOfEdges() << "\n";
statisticsStream << "Average Degree: " << calculator->GetAverageDegree() << "\n";
statisticsStream << "Density: " << calculator->GetConnectionDensity() << "\n";
statisticsStream << "Small Worldness: " << calculator->GetSmallWorldness() << "\n";
statisticsStream << "Average Path Length: " << calculator->GetAveragePathLength() << "\n";
statisticsStream << "Efficiency: " << (1 / calculator->GetAveragePathLength() ) << "\n";
statisticsStream << "# Connected Components: " << calculator->GetNumberOfConnectedComponents() << "\n";
statisticsStream << "Average Component Size: " << calculator->GetAverageComponentSize() << "\n";
statisticsStream << "Largest Component Size: " << calculator->GetLargestComponentSize() << "\n";
statisticsStream << "Average Clustering Coefficient: " << calculator->GetAverageClusteringCoefficientsC() << "\n";
statisticsStream << "Average Vertex Betweenness Centrality: " << calculator->GetAverageVertexBetweennessCentrality() << "\n";
statisticsStream << "Average Edge Betweenness Centrality: " << calculator->GetAverageEdgeBetweennessCentrality() << "\n";
statisticsStream << "# Isolated Points: " << calculator->GetNumberOfIsolatedPoints() << "\n";
statisticsStream << "# End Points: " << calculator->GetNumberOfEndPoints() << "\n";
statisticsStream << "Diameter: " << calculator->GetDiameter() << "\n";
statisticsStream << "Radius: " << calculator->GetRadius() << "\n";
statisticsStream << "Average Eccentricity: " << calculator->GetAverageEccentricity() << "\n";
statisticsStream << "# Central Points: " << calculator->GetNumberOfCentralPoints() << "\n";
QString statisticsString( statisticsStream.str().c_str() );
m_Controls-> networkStatisticsPlainTextEdit-> setPlainText( statisticsString );
mitk::ConnectomicsNetwork::Pointer connectomicsNetwork( network );
mitk::ConnectomicsHistogramsContainer *histogramContainer = histogramCache[ connectomicsNetwork ];
if(histogramContainer)
{
m_Controls->betweennessNetworkHistogramCanvas->SetHistogram( histogramContainer->GetBetweennessHistogram() );
m_Controls->degreeNetworkHistogramCanvas->SetHistogram( histogramContainer->GetDegreeHistogram() );
m_Controls->shortestPathNetworkHistogramCanvas->SetHistogram( histogramContainer->GetShortestPathHistogram() );
m_Controls->betweennessNetworkHistogramCanvas->DrawProfiles();
m_Controls->degreeNetworkHistogramCanvas->DrawProfiles();
m_Controls->shortestPathNetworkHistogramCanvas->DrawProfiles();
}
// For the balloon overlay:
if( m_Controls->m_NetworkBox->GetSelectedNode()->GetProperty( mitk::connectomicsRenderingBalloonAllNodeLabelsName.c_str() ) != nullptr )
{ // QComboBox with node label names and numbers.
QString allNodesLabel = m_Controls->m_NetworkBox->GetSelectedNode()->
GetProperty( mitk::connectomicsRenderingBalloonAllNodeLabelsName.c_str() )->
GetValueAsString().c_str();
QStringList allNodesLabelList = allNodesLabel.simplified().split( "," );
allNodesLabelList.sort( Qt::CaseInsensitive );
m_Controls-> networkBalloonsNodeLabelsComboBox-> QComboBox::addItem( "no node chosen: -1" );
m_Controls-> networkBalloonsNodeLabelsComboBox-> QComboBox::addItems( allNodesLabelList );
}
}
}
void QmitkConnectomicsStatisticsView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList<mitk::DataNode::Pointer>& )
{
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsStatisticsView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsStatisticsView.h
index c1a2a25..effbc98 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsStatisticsView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkConnectomicsStatisticsView.h
@@ -1,81 +1,81 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkConnectomicsStatisticsView_h
#define QmitkConnectomicsStatisticsView_h
#include <berryISelectionListener.h>
#include <QmitkAbstractView.h>
#include "ui_QmitkConnectomicsStatisticsViewControls.h"
#include "mitkConnectomicsHistogramCache.h"
// ####### ITK includes #######
#include <itkImage.h>
/*!
\brief QmitkConnectomicsStatisticsView
This view provides the statistics GUI.
*/
class QmitkConnectomicsStatisticsView : public QmitkAbstractView
{
// 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;
QmitkConnectomicsStatisticsView();
virtual ~QmitkConnectomicsStatisticsView();
virtual void CreateQtPartControl(QWidget *parent) override;
///
/// Sets the focus to an internal widget.
///
virtual void SetFocus() override;
protected slots:
void OnNetworkBalloonsNodeLabelsComboBoxCurrentIndexChanged( );
void UpdateGui();
protected:
// ####### Functions #######
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
/// \brief Wipe display and empty statistics
void WipeDisplay();
// ####### Variables #######
Ui::QmitkConnectomicsStatisticsViewControls* m_Controls;
/// Cache for histograms
mitk::ConnectomicsHistogramCache histogramCache;
};
#endif // _QMITKBRAINNETWORKANALYSISVIEW_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkNetworkHistogramCanvas.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkNetworkHistogramCanvas.cpp
index 5389f2d..ef1adac 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkNetworkHistogramCanvas.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkNetworkHistogramCanvas.cpp
@@ -1,97 +1,97 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkNetworkHistogramCanvas.h"
#include <itkObject.h>
#include <QPainter>
#include <qwt_text.h>
#include <qwt_plot_grid.h>
#include <qwt_painter.h>
#include <qwt_legend.h>
#include <qwt_plot_marker.h>
QmitkNetworkHistogramCanvas::QmitkNetworkHistogramCanvas(QWidget * parent, Qt::WindowFlags )
: QmitkPlotWidget(parent)
{
setEnabled(false);
setFocusPolicy(Qt::ClickFocus);
}
QmitkNetworkHistogramCanvas::~QmitkNetworkHistogramCanvas()
{
}
void QmitkNetworkHistogramCanvas::DrawProfiles( )
{
this->Clear();
if( !(m_Histogram) || !( m_Histogram->IsValid() ))
{
return;
}
std::vector<double> histogramVector = m_Histogram->GetHistogramVector();
// create a data vector which contains the points to be drawn
// to create nice bars, the curve takes four points for each bar
std::vector< std::pair< double, double > > dataPointsVector;
std::pair< double, double > leftBottom, leftTop, rightTop, rightBottom;
// how wide the bar is, the gap to the next one will be 1 - barWidth
double barWidth( 0.95 );
const int range = histogramVector.size();
for(int i=0; i < range ; ++i)
{
leftBottom.first = ((double) i) ;
leftBottom.second = 0.0;
leftTop.first = ((double) i) ;
leftTop.second = histogramVector.at( i );
rightTop.first = ((double) i) + barWidth ;
rightTop.second = histogramVector.at( i );
rightBottom.first = ((double) i) + barWidth ;
rightBottom.second = 0.0;
dataPointsVector.push_back( leftBottom );
dataPointsVector.push_back( leftTop );
dataPointsVector.push_back( rightTop );
dataPointsVector.push_back( rightBottom );
}
this->SetPlotTitle( (m_Histogram->GetSubject()).c_str() );
QPen pen( Qt::NoPen );
QBrush brush( Qt::SolidPattern );
brush.setColor( Qt::blue );
int curveId = this->InsertCurve( (m_Histogram->GetSubject()).c_str() );
this->SetCurveData( curveId, dataPointsVector );
this->SetCurvePen( curveId, pen );
this->SetCurveBrush( curveId, brush );
// Axis 0 is the y axis, axis to the x axis
this->m_Plot->setAxisTitle(0, "n");
//this->m_Plot->setAxisTitle(2, "");
this->Replot();
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkNetworkHistogramCanvas.h b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkNetworkHistogramCanvas.h
index 813b0e8..a419aa9 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkNetworkHistogramCanvas.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkNetworkHistogramCanvas.h
@@ -1,73 +1,73 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkNetworkHistogramCanvas_H_INCLUDED
#define QmitkNetworkHistogramCanvas_H_INCLUDED
#include <mitkConnectomicsHistogramBase.h>
#include <mitkRenderingManager.h>
#include "QmitkPlotWidget.h"
#include <QStandardItemModel>
#include <qwt_plot.h>
#include <QPainter>
#include <qwt_plot_picker.h>
//##Documentation
//## @brief A widget for displaying the data in a ConnectomicsHistogramBase
class QmitkNetworkHistogramCanvas : public QmitkPlotWidget
{
Q_OBJECT
public:
QmitkNetworkHistogramCanvas( QWidget * parent=nullptr, Qt::WindowFlags f = nullptr );
~QmitkNetworkHistogramCanvas();
/** @brief Returns the histogram the canvas is using */
mitk::ConnectomicsHistogramBase* GetHistogram()
{
return m_Histogram;
}
/** @brief Set the histogram the canvas is to use */
void SetHistogram(mitk::ConnectomicsHistogramBase *histogram)
{
m_Histogram = histogram;
}
/** @brief Draw the histogram */
void DrawProfiles();
/** @brief Return the plot */
QwtPlot* GetPlot()
{
return m_Plot;
}
protected:
/** @brief The histogram to be plotted */
mitk::ConnectomicsHistogramBase *m_Histogram;
};
#endif
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkRandomParcellationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkRandomParcellationView.cpp
index b30f8b3..aa3f189 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkRandomParcellationView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkRandomParcellationView.cpp
@@ -1,358 +1,358 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// Qmitk
#include "QmitkRandomParcellationView.h"
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// Qt
#include <QMessageBox>
// Includes for image casting between ITK and MITK
#include "mitkImageCast.h"
#include "mitkImageAccessByItk.h"
#include "mitkITKImageImport.h"
//To convert integer to string
#include <stdlib.h>
#include <sstream>
//Itk Iterators
#include <itkNeighborhoodIterator.h>
#include <itkImageRegionIterator.h>
// mitk
#include <mitkRegionVoxelCounter.h>
#include <mitkRandomParcellationGenerator.h>
//Child
const std::string QmitkRandomParcellationView::PROPERTYNAME = "name";
const std::string QmitkRandomParcellationView::PROPERTYOPACITY = "opacity";
const std::string QmitkRandomParcellationView::m_NAMEFORRANDOMVOXELIMAGE = "Random Voxel Image";
const std::string QmitkRandomParcellationView::VIEW_ID = "org.mitk.views.randomparcellationview";
void QmitkRandomParcellationView::SetFocus()
{
m_Controls.buttonSelectRandomNodes->setFocus();
}
void QmitkRandomParcellationView::CreateQtPartControl( QWidget *parent )
{
// create GUI widgets from the Qt Designer's .ui file
m_Controls.setupUi( parent );
connect( m_Controls.buttonSelectRandomNodes, SIGNAL(clicked()), this, SLOT(SelectRandomNodes()) );
connect( m_Controls.checkBoxMerging, SIGNAL(stateChanged(int)),this, SLOT(OnMergingCheckboxChanged(int)));
connect( m_Controls.radioButtonNumberParcels, SIGNAL(clicked()), this, SLOT(OnRadioButtonNumberParcelsChanged(int)));
connect( m_Controls.radioButtonSmallestParcel, SIGNAL(clicked()), this, SLOT(OnRadioButtonSmallestParcelChanged(int)));
}
void QmitkRandomParcellationView::OnMergingCheckboxChanged(int )
{
if (m_Controls.checkBoxMerging->isChecked())
{
//Make the frame visible
m_Controls.frameMerging->setEnabled(true);
m_Controls.frameNumberParcels->setEnabled(true);
m_Controls.frameSmallestParcel->setEnabled(true);
}
else
{
m_Controls.frameMerging->setEnabled(false);
}
}
void QmitkRandomParcellationView::OnRadioButtonNumberParcelsChanged(int )
{
if (m_Controls.radioButtonNumberParcels->isChecked())
{
m_Controls.frameNumberParcels->setEnabled(true);
m_Controls.radioButtonSmallestParcel->setChecked(false);
}
else
{
m_Controls.frameNumberParcels->setEnabled(false);
}
}
void QmitkRandomParcellationView::OnRadioButtonSmallestParcelChanged(int )
{
if (m_Controls.radioButtonSmallestParcel->isChecked())
{
m_Controls.frameSmallestParcel->setEnabled(true);
m_Controls.radioButtonNumberParcels->setChecked(false);
}
else
{
m_Controls.frameSmallestParcel->setEnabled(false);
}
}
void QmitkRandomParcellationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList<mitk::DataNode::Pointer>& nodes)
{
// iterate all selected objects, adjust warning visibility
for (mitk::DataNode::Pointer node: nodes)
{
if( node.IsNotNull() && dynamic_cast<mitk::Image*>(node->GetData()) )
{
m_Controls.labelWarning->setVisible( false );
m_Controls.buttonSelectRandomNodes->setEnabled( true );
mitk::Image* imageDisplay = dynamic_cast<mitk::Image*>(node->GetData());
AccessFixedDimensionByItk(imageDisplay, ShowNumberOfVoxels, 3);
return;
}
}
m_Controls.labelWarning->setVisible( true );
m_Controls.buttonSelectRandomNodes->setEnabled( false );
}
template <typename TPixel, unsigned int VImageDimension>
void QmitkRandomParcellationView::ShowNumberOfVoxels( itk::Image<TPixel, VImageDimension> * inputImage)
{
mitk::RegionVoxelCounter<TPixel, VImageDimension> counter;
counter.SetRegion(inputImage->GetLargestPossibleRegion());
counter.SetImage(inputImage);
int numberVoxelsDisplay = counter.VoxelWithValue(1);
std::string stringDisplay = "Number of voxels with value 1: ";
std::ostringstream convertDisplay;
convertDisplay << numberVoxelsDisplay;
std::string stringNumberVoxels = convertDisplay.str();
stringDisplay += stringNumberVoxels;
QString textNumberVoxelsDisplay = QString::fromStdString(stringDisplay);
m_Controls.labelNumberVoxels->setText(textNumberVoxelsDisplay);
}
void QmitkRandomParcellationView::SelectRandomNodes()
{
QList<mitk::DataNode::Pointer> nodes = this->GetDataManagerSelection();
if (nodes.empty()) return;
mitk::DataNode* node = nodes.front();
if (!node)
{
// Nothing selected. Inform the user and return
QMessageBox::information( nullptr, "No image available", "Please load and select an image before starting image processing.");
return;
}
// here we have a valid mitk::DataNode
// a node itself is not very useful, we need its data item (the image)
mitk::BaseData* data = node->GetData();
if (data)
{
// test if this data item is an image or not (could also be a surface or something totally different)
mitk::Image* image = dynamic_cast<mitk::Image*>( data );
if (image)
{
//get numberNodes (number of nodes) with SpinBox
int numberNodes( 0 );
numberNodes = m_Controls.spinBoxNumberNodes->value();
std::stringstream message;
std::string name;
message << "Selecting " << numberNodes << " random nodes for ";
if (node->GetName(name))
{
// a property called "name" was found for this DataNode
message << "'" << name << "'";
}
message << ".";
MITK_INFO << message.str();
//MITK into ITK image, function GetRandomParcels gets executed, Dimension is 3
AccessFixedDimensionByItk(image, GetRandomParcels, 3);
}
}
}
template <typename TPixel, unsigned int VImageDimension>
void QmitkRandomParcellationView::GetRandomParcels( itk::Image<TPixel, VImageDimension> * inputImage)
{
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::Image< int, VImageDimension > IntegerImageType;
//new Image which will contain the parcellation
typename IntegerImageType::Pointer voxelImage = IntegerImageType::New();
voxelImage->SetRegions(inputImage->GetLargestPossibleRegion().GetSize());
voxelImage->SetSpacing(inputImage->GetSpacing());
voxelImage->SetOrigin(inputImage->GetOrigin());
voxelImage->Allocate();
//Voxel iterators
itk::ImageRegionIterator<ImageType> it_inputImage(inputImage, inputImage->GetLargestPossibleRegion());
itk::ImageRegionIterator<IntegerImageType> it_voxelImage(voxelImage, voxelImage->GetLargestPossibleRegion());
//Copy the inputImage -> voxelImage
for (it_inputImage.GoToBegin(), it_voxelImage.GoToBegin(); !it_inputImage.IsAtEnd(); ++it_inputImage, ++it_voxelImage)
{
it_voxelImage.Value() = it_inputImage.Value();
}
//Neighborhood Iterator
typedef itk::NeighborhoodIterator< IntegerImageType > NeighborhoodIteratorType;
typename NeighborhoodIteratorType::RadiusType radius;
radius.Fill(1);
//Counter for voxels with value 1
mitk::RegionVoxelCounter<int, 3> counter;
counter.SetImage(voxelImage);
counter.SetRegion(voxelImage->GetLargestPossibleRegion());
int numberVoxels = counter.VoxelWithValue(1);
//Get numberNodes with SpinBox
int numberNodes(0);
numberNodes = m_Controls.spinBoxNumberNodes->value();
//WARNINGS
if (numberNodes > numberVoxels )
{
QMessageBox::information( nullptr, "Smaller Number of Nodes", "The number of nodes is greater than the number of voxels. Please choose a smaller number!");
return;
}
if (m_Controls.checkBoxMerging->isChecked() && m_Controls.radioButtonNumberParcels->isChecked())
{
int numberParcels = m_Controls.spinBoxNumberParcels->value();
if (numberNodes<numberParcels )
{
QMessageBox::information( nullptr, "Smaller Number of Parcels", "The number of parcels is greater than the number of nodes. Please choose a smaller number of parcels!");
return;
}
}
if (m_Controls.checkBoxMerging->isChecked() && m_Controls.radioButtonSmallestParcel->isChecked())
{
int sizeSmallestParcel = m_Controls.spinBoxSmallestParcel->value();
if (sizeSmallestParcel > numberVoxels )
{
QMessageBox::information( nullptr, "Smaller Size", "The size of the smallest parcel is greater than the number of voxels. Please choose a smaller size!");
return;
}
}
//Get a RandomParcellationGenerator to generate the parcels
mitk::RandomParcellationGenerator<int, 3> generator;
generator.SetImage(voxelImage);
generator.SetNumberNodes(numberNodes);
//Chooses random initial voxels, with which we can start the parcellation growth
generator.GetRandomSeedVoxels();
//Now we add all the voxels (which share a face with one of the voxels of a region) to a region, particular constraints have to be fulfilled
generator.ParcelGrowthOverFaces();
//Because of the constraints or the position of some voxels we now add voxels to the regions which just share an edge or vertex with one region
generator.FillOverEdgeOrVertex();
//Isolated voxels also have to be allocated to the regions
generator.AllocateIsolatedVoxels();
//Show the sizeOfRegions in the window
MITK_DEBUG << "Without merging we get the following size of regions: " << endl;
generator.ShowSizeOfRegions();
//Check if the Merge-Buttons are chosen
int newNumberNodes = 0;
if (m_Controls.checkBoxMerging->isChecked())
{
int givenSizeOfSmallestRegion(0);
int desiredNumberOfParcels(0);
int givenSizeOfSmallestRegionBeginning = numberVoxels;
bool mergingWithNumberParcels(false);
bool mergingWithSmallestParcel(false);
bool justMergeSmallParcels(false);
if (m_Controls.radioButtonSmallestParcel->isChecked() )
{
mergingWithSmallestParcel = true;
givenSizeOfSmallestRegionBeginning = m_Controls.spinBoxSmallestParcel->value();
if( m_Controls.checkBoxJustMergeSmallParcels-> isChecked() )
{
//Spinbox: How many voxels should the smallest parcel have?
givenSizeOfSmallestRegion = m_Controls.spinBoxSmallestParcel->value();
justMergeSmallParcels = true;
}
else
{
givenSizeOfSmallestRegion = numberVoxels;
}
}
else if (m_Controls.radioButtonNumberParcels->isChecked())
{
givenSizeOfSmallestRegion = numberVoxels;
desiredNumberOfParcels = m_Controls.spinBoxNumberParcels->value();
mergingWithNumberParcels = true;
}
//Merge parcels according to a costfunction
generator.SetVariablesForMerging(givenSizeOfSmallestRegion, desiredNumberOfParcels, givenSizeOfSmallestRegionBeginning);
generator.SetBoolsForMerging(mergingWithNumberParcels, mergingWithSmallestParcel, justMergeSmallParcels);
newNumberNodes = generator.MergeParcels();
MITK_DEBUG << "After merging we get the following size of regions:" << endl;
generator.ShowSizeOfRegions();
}
//Show NumberOfNodes on the GUI
if (m_Controls.checkBoxMerging->isChecked()) //merging was used
{
ShowNumberOfNodes(newNumberNodes);
}
else
{
ShowNumberOfNodes(numberNodes);
}
//Change the values of the nodes, such that no gaps exist and the values starts with 1
generator.SetAppropriateValues();
//Get a new data node which contains the random parcellation
mitk::Image::Pointer mitkRandomVoxelImage = mitk::GrabItkImageMemory( voxelImage );
mitk::DataNode::Pointer newRandomVoxelImageNode = mitk::DataNode::New();
newRandomVoxelImageNode->SetData(mitkRandomVoxelImage);
newRandomVoxelImageNode->SetProperty(PROPERTYNAME.c_str(),
mitk::StringProperty::New(m_NAMEFORRANDOMVOXELIMAGE));
newRandomVoxelImageNode->SetProperty(PROPERTYOPACITY.c_str(),
mitk::FloatProperty::New(1.0));
this->GetDataStorage()->Add( newRandomVoxelImageNode );
return;
}
void QmitkRandomParcellationView::ShowNumberOfNodes(int numberNodes)
{
std::string string = "Number of nodes: ";
std::string stringNumberNodes;
std::ostringstream convert;
convert << numberNodes;
stringNumberNodes = convert.str();
string += stringNumberNodes;
QString textNumberNodes = QString::fromStdString(string);
m_Controls.labelNumberNodes->setText(textNumberNodes);
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkRandomParcellationView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkRandomParcellationView.h
index d034b58..d634e98 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkRandomParcellationView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/QmitkRandomParcellationView.h
@@ -1,98 +1,98 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 RandomParcellationView_h
#define RandomParcellationView_h
#include <berryISelectionListener.h>
#include <QmitkAbstractView.h>
#include "ui_QmitkRandomParcellationViewControls.h"
#include <vector>
#include <itkImage.h>
//To use pair
#include <utility>
/**
\brief QmitkRandomParcellationView for GUI Interactions
\ingroup ${plugin_target}_internal
*/
class QmitkRandomParcellationView : public QmitkAbstractView
{
Q_OBJECT
public:
static const std::string VIEW_ID;
virtual void CreateQtPartControl(QWidget *parent) override;
virtual void SetFocus() override;
/** \brief Interaction with GUI and mitkRandomParcellationGenerator to get random parcels.*/
template <typename TPixel, unsigned int VImageDimension>
void GetRandomParcels( itk::Image<TPixel, VImageDimension>* );
/** \brief Method to set the default data storage.*/
virtual void SetDataStorage(mitk::DataStorage* dataStorage)
{
m_DataStorage = dataStorage;
}
protected slots:
/** \brief Called when the user clicks the GUI button*/
void SelectRandomNodes();
/** \brief Called when the user checks the GUI checkbox*/
void OnMergingCheckboxChanged(int state);
/** \brief Called when the user ckecks the GUI radio button*/
void OnRadioButtonNumberParcelsChanged(int state);
/** \brief Called when the user ckecks the GUI radio button*/
void OnRadioButtonSmallestParcelChanged(int state);
protected:
mitk::DataStorage* m_DataStorage;
//to save an itk image
mitk::DataNode::Pointer m_InputImageNode;
/** \brief Shows the number of voxels with value one on the GUI*/
template <typename TPixel, unsigned int VImageDimension>
void ShowNumberOfVoxels( itk::Image<TPixel, VImageDimension> * inputImage);
/** \brief Shows the number of nodes on the GUI (may have changed after merging)*/
void ShowNumberOfNodes(int numberNodes);
/** \brief called by QmitkAbstractView when DataManager's selection has changed*/
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
Ui::QmitkRandomParcellationViewControls m_Controls;
static const std::string PROPERTYNAME;
static const std::string PROPERTYOPACITY;
static const std::string m_NAMEFORRANDOMVOXELIMAGE;
};
#endif // RandomParcellationView_h
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/mitkPluginActivator.cpp
index 4d2ef45..c04aa8d 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/mitkPluginActivator.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/mitkPluginActivator.cpp
@@ -1,47 +1,47 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPluginActivator.h"
#include "src/internal/QmitkConnectomicsDataView.h"
#include "src/internal/QmitkConnectomicsNetworkOperationsView.h"
#include "src/internal/QmitkConnectomicsStatisticsView.h"
#include "src/internal/QmitkRandomParcellationView.h"
#include "src/internal/Perspectives/QmitkConnectomicsPerspective.h"
ctkPluginContext* mitk::PluginActivator::m_Context = nullptr;
ctkPluginContext* mitk::PluginActivator::GetContext()
{
return m_Context;
}
void mitk::PluginActivator::start(ctkPluginContext* context)
{
BERRY_REGISTER_EXTENSION_CLASS(QmitkConnectomicsPerspective, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkConnectomicsDataView, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkConnectomicsNetworkOperationsView, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkConnectomicsStatisticsView, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkRandomParcellationView, context)
m_Context = context;
}
void mitk::PluginActivator::stop(ctkPluginContext* context)
{
Q_UNUSED(context)
m_Context = nullptr;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/mitkPluginActivator.h
index a239fd2..2c8641c 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/mitkPluginActivator.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.connectomics/src/internal/mitkPluginActivator.h
@@ -1,40 +1,40 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKPLUGINACTIVATOR_H
#define MITKPLUGINACTIVATOR_H
#include <ctkPluginActivator.h>
namespace mitk
{
class PluginActivator : public QObject, public ctkPluginActivator
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.mitk.gui.qt.diffusionimaging.connectomics")
Q_INTERFACES(ctkPluginActivator)
public:
static ctkPluginContext* GetContext();
void start(ctkPluginContext* context) override;
void stop(ctkPluginContext* context) override;
private:
static ctkPluginContext* m_Context;
};
}
#endif
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/src/internal/QmitkDenoisingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/src/internal/QmitkDenoisingView.cpp
index d26355c..91be44a 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/src/internal/QmitkDenoisingView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/src/internal/QmitkDenoisingView.cpp
@@ -1,232 +1,232 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// Qmitk
#include "QmitkDenoisingView.h"
#include <mitkImageCast.h>
#include <mitkDiffusionPropertyHelper.h>
#include <mitkITKImageImport.h>
#include <mitkDiffusionPropertyHelper.h>
#include <mitkNodePredicateDataType.h>
#include <mitkNodePredicateProperty.h>
#include <mitkNodePredicateAnd.h>
#include <itkTotalVariationDenoisingImageFilter.h>
#include <itkNonLocalMeansDenoisingFilter.h>
#include <itkDiscreteGaussianImageFilter.h>
#include <itkPatchBasedDenoisingImageFilter.h>
#include <itkMaskImageFilter.h>
#include <itkVectorImageToImageFilter.h>
#include <itkComposeImageFilter.h>
#include <itkGaussianRandomSpatialNeighborSubsampler.h>
#include <itkSpatialNeighborSubsampler.h>
#include <QMessageBox>
#include <mitkNodePredicateIsDWI.h>
const std::string QmitkDenoisingView::VIEW_ID = "org.mitk.views.denoisingview";
QmitkDenoisingView::QmitkDenoisingView()
: QmitkAbstractView()
, m_Controls( 0 )
, m_ImageNode(nullptr)
{
}
QmitkDenoisingView::~QmitkDenoisingView()
{
}
void QmitkDenoisingView::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::QmitkDenoisingViewControls;
m_Controls->setupUi( parent );
connect( (QObject*)(m_Controls->m_ApplyButton), SIGNAL(clicked()), this, SLOT(StartDenoising()));
connect( (QObject*)(m_Controls->m_SelectFilterComboBox), SIGNAL(activated(int)), this, SLOT(UpdateGui()));
connect( (QObject*)(m_Controls->m_InputImageBox), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()));
m_Controls->m_InputImageBox->SetDataStorage(this->GetDataStorage());
mitk::NodePredicateIsDWI::Pointer isImagePredicate = mitk::NodePredicateIsDWI::New();
m_Controls->m_InputImageBox->SetPredicate( isImagePredicate );
UpdateGui();
}
}
void QmitkDenoisingView::SetFocus()
{
m_Controls->m_SelectFilterComboBox->setFocus();
}
void QmitkDenoisingView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList<mitk::DataNode::Pointer>& )
{
}
void QmitkDenoisingView::StartDenoising()
{
typedef itk::DiscreteGaussianImageFilter < DwiVolumeType, DwiVolumeType > GaussianFilterType;
typedef itk::PatchBasedDenoisingImageFilter < DwiVolumeType, DwiVolumeType > NlmFilterType;
typedef itk::VectorImageToImageFilter < DiffusionPixelType > ExtractFilterType;
typedef itk::ComposeImageFilter < itk::Image<DiffusionPixelType, 3> > ComposeFilterType;
m_ImageNode = m_Controls->m_InputImageBox->GetSelectedNode();
mitk::Image::Pointer input_image = dynamic_cast<mitk::Image*>(m_ImageNode->GetData());
if (!mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(input_image))
{
QMessageBox::warning(nullptr, "Image not processed", "Input is not a diffusion-weighted image!");
return;
}
DwiImageType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::GetItkVectorImage(input_image);
mitk::Image::Pointer denoised_image = nullptr;
mitk::DataNode::Pointer denoised_image_node = mitk::DataNode::New();
switch (m_Controls->m_SelectFilterComboBox->currentIndex())
{
case 0:
{
ComposeFilterType::Pointer composer = ComposeFilterType::New();
for (unsigned int i=0; i<itkVectorImagePointer->GetVectorLength(); ++i)
{
ExtractFilterType::Pointer extractor = ExtractFilterType::New();
extractor->SetInput( itkVectorImagePointer );
extractor->SetIndex( i );
extractor->Update();
DwiVolumeType::Pointer gradient_volume = extractor->GetOutput();
itk::TotalVariationDenoisingImageFilter< DwiVolumeType, DwiVolumeType >::Pointer filter = itk::TotalVariationDenoisingImageFilter< DwiVolumeType, DwiVolumeType >::New();
filter->SetInput(gradient_volume);
filter->SetLambda(m_Controls->m_TvLambdaBox->value());
filter->SetNumberIterations(m_Controls->m_TvIterationsBox->value());
filter->Update();
composer->SetInput(i, filter->GetOutput());
}
composer->Update();
denoised_image = mitk::GrabItkImageMemory(composer->GetOutput());
denoised_image_node->SetName( "TotalVariation" );
break;
}
case 1:
{
ExtractFilterType::Pointer extractor = ExtractFilterType::New();
extractor->SetInput( itkVectorImagePointer );
ComposeFilterType::Pointer composer = ComposeFilterType::New();
for (unsigned int i = 0; i < itkVectorImagePointer->GetVectorLength(); ++i)
{
extractor->SetIndex(i);
extractor->Update();
GaussianFilterType::Pointer filter = GaussianFilterType::New();
filter->SetVariance(m_Controls->m_GaussVarianceBox->value());
filter->SetInput(extractor->GetOutput());
filter->Update();
composer->SetInput(i, filter->GetOutput());
}
composer->Update();
denoised_image = mitk::GrabItkImageMemory(composer->GetOutput());
denoised_image_node->SetName( "Gauss" );
break;
}
case 2:
{
typedef itk::Statistics::GaussianRandomSpatialNeighborSubsampler< NlmFilterType::PatchSampleType, DwiVolumeType::RegionType > SamplerType;
// sampling the image to find similar patches
SamplerType::Pointer sampler = SamplerType::New();
sampler->SetRadius( m_Controls->m_NlmSearchRadiusBox->value() );
sampler->SetVariance( m_Controls->m_NlmSearchRadiusBox->value()*m_Controls->m_NlmSearchRadiusBox->value() );
sampler->SetNumberOfResultsRequested( m_Controls->m_NlmNumPatchesBox->value() );
MITK_INFO << "Starting NLM denoising";
ExtractFilterType::Pointer extractor = ExtractFilterType::New();
extractor->SetInput( itkVectorImagePointer );
ComposeFilterType::Pointer composer = ComposeFilterType::New();
for (unsigned int i = 0; i < itkVectorImagePointer->GetVectorLength(); ++i)
{
extractor->SetIndex(i);
extractor->Update();
NlmFilterType::Pointer filter = NlmFilterType::New();
filter->SetInput(extractor->GetOutput());
filter->SetPatchRadius(m_Controls->m_NlmPatchSizeBox->value());
filter->SetNoiseModel(NlmFilterType::RICIAN);
filter->UseSmoothDiscPatchWeightsOn();
filter->UseFastTensorComputationsOn();
filter->SetNumberOfIterations(m_Controls->m_NlmIterationsBox->value());
filter->SetSmoothingWeight( 1 );
filter->SetKernelBandwidthEstimation(true);
filter->SetSampler( sampler );
filter->Update();
composer->SetInput(i, filter->GetOutput());
MITK_INFO << "Gradient " << i << " finished";
}
composer->Update();
denoised_image = mitk::GrabItkImageMemory(composer->GetOutput());
denoised_image_node->SetName( "NLM" );
break;
}
}
mitk::DiffusionPropertyHelper::CopyProperties(input_image, denoised_image, true);
mitk::DiffusionPropertyHelper::InitializeImage( denoised_image );
denoised_image_node->SetData( denoised_image );
GetDataStorage()->Add(denoised_image_node, m_ImageNode);
}
void QmitkDenoisingView::UpdateGui()
{
m_Controls->m_ApplyButton->setEnabled(false);
m_Controls->m_TvFrame->setVisible(false);
m_Controls->m_NlmFrame->setVisible(false);
m_Controls->m_GaussFrame->setVisible(false);
switch (m_Controls->m_SelectFilterComboBox->currentIndex())
{
case 0:
{
m_Controls->m_TvFrame->setVisible(true);
break;
}
case 1:
{
m_Controls->m_GaussFrame->setVisible(true);
break;
}
case 2:
{
m_Controls->m_NlmFrame->setVisible(true);
break;
}
}
if (m_Controls->m_InputImageBox->GetSelectedNode().IsNotNull())
m_Controls->m_ApplyButton->setEnabled(true);
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/src/internal/QmitkDenoisingView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/src/internal/QmitkDenoisingView.h
index 5856a78..ab48098 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/src/internal/QmitkDenoisingView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/src/internal/QmitkDenoisingView.h
@@ -1,78 +1,78 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _QMITKQmitkDenoisingView_H_INCLUDED
#define _QMITKQmitkDenoisingView_H_INCLUDED
#include <berryISelectionListener.h>
#include <QmitkAbstractView.h>
#include "ui_QmitkDenoisingViewControls.h"
#include <itkVectorImage.h>
#include <itkImage.h>
#include <mitkImage.h>
#include <QThread>
#include <QTimer>
/**
* \class QmitkDenoisingView
* \brief View for denoising diffusion-weighted images.
*/
class QmitkDenoisingView : public QmitkAbstractView
{
// 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;
QmitkDenoisingView();
virtual ~QmitkDenoisingView();
/** Typedefs */
typedef short DiffusionPixelType;
typedef itk::VectorImage<DiffusionPixelType, 3> DwiImageType;
typedef itk::Image<DiffusionPixelType, 3> DwiVolumeType;
virtual void CreateQtPartControl(QWidget *parent) override;
///
/// Sets the focus to an internal widget.
///
virtual void SetFocus() override;
private slots:
void StartDenoising();
void UpdateGui();
private:
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
Ui::QmitkDenoisingViewControls* m_Controls;
mitk::DataNode::Pointer m_ImageNode;
};
#endif // _QmitkDenoisingView_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/src/internal/mitkPluginActivator.cpp
index d5b90ac..9a7b502 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/src/internal/mitkPluginActivator.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/src/internal/mitkPluginActivator.cpp
@@ -1,39 +1,39 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPluginActivator.h"
#include "src/internal/QmitkDenoisingView.h"
ctkPluginContext* mitk::PluginActivator::m_Context = nullptr;
ctkPluginContext* mitk::PluginActivator::GetContext()
{
return m_Context;
}
void mitk::PluginActivator::start(ctkPluginContext* context)
{
BERRY_REGISTER_EXTENSION_CLASS(QmitkDenoisingView, context)
m_Context = context;
}
void mitk::PluginActivator::stop(ctkPluginContext* context)
{
Q_UNUSED(context)
m_Context = nullptr;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/src/internal/mitkPluginActivator.h
index 39e5939..6959f6e 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/src/internal/mitkPluginActivator.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.denoising/src/internal/mitkPluginActivator.h
@@ -1,40 +1,40 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKPLUGINACTIVATOR_H
#define MITKPLUGINACTIVATOR_H
#include <ctkPluginActivator.h>
namespace mitk
{
class PluginActivator : public QObject, public ctkPluginActivator
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.mitk.gui.qt.diffusionimaging.denoising")
Q_INTERFACES(ctkPluginActivator)
public:
static ctkPluginContext* GetContext();
void start(ctkPluginContext* context) override;
void stop(ctkPluginContext* context) override;
private:
static ctkPluginContext* m_Context;
};
}
#endif
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkAstrosticksModelParametersWidget.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkAstrosticksModelParametersWidget.cpp
index c18995c..c8005be 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkAstrosticksModelParametersWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkAstrosticksModelParametersWidget.cpp
@@ -1,42 +1,42 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
//Qmitk headers
#include "QmitkAstrosticksModelParametersWidget.h"
#include <itkDiffusionTensor3D.h>
const std::string QmitkAstrosticksModelParametersWidget::VIEW_ID = "org.mitk.views.AstrosticksModelParametersWidget";
QmitkAstrosticksModelParametersWidget::QmitkAstrosticksModelParametersWidget( QWidget * parent, Qt::WindowFlags )
: QWidget(parent)
{
m_Controls = nullptr;
this->CreateQtPartControl(this);
}
QmitkAstrosticksModelParametersWidget::~QmitkAstrosticksModelParametersWidget()
{
}
void QmitkAstrosticksModelParametersWidget::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
// create GUI widgets
m_Controls = new Ui::QmitkAstrosticksModelParametersWidgetControls;
m_Controls->setupUi(parent);
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkAstrosticksModelParametersWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkAstrosticksModelParametersWidget.h
index 6ee2ade..1b19c21 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkAstrosticksModelParametersWidget.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkAstrosticksModelParametersWidget.h
@@ -1,62 +1,62 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _QMITKAstrosticksModelParametersWidget_H_INCLUDED
#define _QMITKAstrosticksModelParametersWidget_H_INCLUDED
//QT headers
#include <QWidget>
#include <QString>
#include "ui_QmitkAstrosticksModelParametersWidgetControls.h"
#include <org_mitk_gui_qt_diffusionimaging_fiberfox_Export.h>
/** @brief
*/
class DIFFUSIONIMAGING_FIBERFOX_EXPORT QmitkAstrosticksModelParametersWidget : public QWidget
{
//this is needed for all Qt objects that should have a MOC object (everything that derives from QObject)
Q_OBJECT
public:
static const std::string VIEW_ID;
QmitkAstrosticksModelParametersWidget (QWidget* parent = nullptr, Qt::WindowFlags f = nullptr);
virtual ~QmitkAstrosticksModelParametersWidget();
virtual void CreateQtPartControl(QWidget *parent);
void SetT1(double t1){ m_Controls->m_T1box->setValue(t1); }
void SetT2(double t2){ m_Controls->m_T2box->setValue(t2); }
void SetD(double d){ m_Controls->m_D1box->setValue(d); }
void SetRandomizeSticks(bool r){ m_Controls->m_RandomCheck->setChecked(r); }
double GetD(){ return m_Controls->m_D1box->value(); }
unsigned int GetT2(){ return m_Controls->m_T2box->value(); }
unsigned int GetT1(){ return m_Controls->m_T1box->value(); }
bool GetRandomizeSticks(){ return m_Controls->m_RandomCheck->isChecked(); }
public slots:
protected:
// member variables
Ui::QmitkAstrosticksModelParametersWidgetControls* m_Controls;
private:
};
#endif // _QMITKAstrosticksModelParametersWidget_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkBallModelParametersWidget.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkBallModelParametersWidget.cpp
index aab410f..780928c 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkBallModelParametersWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkBallModelParametersWidget.cpp
@@ -1,42 +1,42 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
//Qmitk headers
#include "QmitkBallModelParametersWidget.h"
#include <itkDiffusionTensor3D.h>
const std::string QmitkBallModelParametersWidget::VIEW_ID = "org.mitk.views.BallModelParametersWidget";
QmitkBallModelParametersWidget::QmitkBallModelParametersWidget( QWidget * parent, Qt::WindowFlags )
: QWidget(parent)
{
m_Controls = nullptr;
this->CreateQtPartControl(this);
}
QmitkBallModelParametersWidget::~QmitkBallModelParametersWidget()
{
}
void QmitkBallModelParametersWidget::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
// create GUI widgets
m_Controls = new Ui::QmitkBallModelParametersWidgetControls;
m_Controls->setupUi(parent);
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkBallModelParametersWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkBallModelParametersWidget.h
index c08e4d6..af093b9 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkBallModelParametersWidget.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkBallModelParametersWidget.h
@@ -1,60 +1,60 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _QMITKBallModelParametersWidget_H_INCLUDED
#define _QMITKBallModelParametersWidget_H_INCLUDED
//QT headers
#include <QWidget>
#include <QString>
#include "ui_QmitkBallModelParametersWidgetControls.h"
#include <org_mitk_gui_qt_diffusionimaging_fiberfox_Export.h>
/** @brief
*/
class DIFFUSIONIMAGING_FIBERFOX_EXPORT QmitkBallModelParametersWidget : public QWidget
{
//this is needed for all Qt objects that should have a MOC object (everything that derives from QObject)
Q_OBJECT
public:
static const std::string VIEW_ID;
QmitkBallModelParametersWidget (QWidget* parent = nullptr, Qt::WindowFlags f = nullptr);
virtual ~QmitkBallModelParametersWidget();
virtual void CreateQtPartControl(QWidget *parent);
void SetT1(double t1){ m_Controls->m_T1box->setValue(t1); }
void SetT2(double t2){ m_Controls->m_T2box->setValue(t2); }
void SetD(double d){ m_Controls->m_D1box->setValue(d); }
double GetD(){ return m_Controls->m_D1box->value(); }
unsigned int GetT2(){ return m_Controls->m_T2box->value(); }
unsigned int GetT1(){ return m_Controls->m_T1box->value(); }
public slots:
protected:
// member variables
Ui::QmitkBallModelParametersWidgetControls* m_Controls;
private:
};
#endif // _QMITKBallModelParametersWidget_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkDotModelParametersWidget.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkDotModelParametersWidget.cpp
index e327ccd..9bedb19 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkDotModelParametersWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkDotModelParametersWidget.cpp
@@ -1,42 +1,42 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
//Qmitk headers
#include "QmitkDotModelParametersWidget.h"
#include <itkDiffusionTensor3D.h>
const std::string QmitkDotModelParametersWidget::VIEW_ID = "org.mitk.views.DotModelParametersWidget";
QmitkDotModelParametersWidget::QmitkDotModelParametersWidget( QWidget * parent, Qt::WindowFlags )
: QWidget(parent)
{
m_Controls = nullptr;
this->CreateQtPartControl(this);
}
QmitkDotModelParametersWidget::~QmitkDotModelParametersWidget()
{
}
void QmitkDotModelParametersWidget::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
// create GUI widgets
m_Controls = new Ui::QmitkDotModelParametersWidgetControls;
m_Controls->setupUi(parent);
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkDotModelParametersWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkDotModelParametersWidget.h
index 29fda38..21bb6b1 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkDotModelParametersWidget.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkDotModelParametersWidget.h
@@ -1,57 +1,57 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _QMITKDotModelParametersWidget_H_INCLUDED
#define _QMITKDotModelParametersWidget_H_INCLUDED
//QT headers
#include <QWidget>
#include <QString>
#include "ui_QmitkDotModelParametersWidgetControls.h"
#include <org_mitk_gui_qt_diffusionimaging_fiberfox_Export.h>
/** @brief
*/
class DIFFUSIONIMAGING_FIBERFOX_EXPORT QmitkDotModelParametersWidget : public QWidget
{
//this is needed for all Qt objects that should have a MOC object (everything that derives from QObject)
Q_OBJECT
public:
static const std::string VIEW_ID;
QmitkDotModelParametersWidget (QWidget* parent = nullptr, Qt::WindowFlags f = nullptr);
virtual ~QmitkDotModelParametersWidget();
virtual void CreateQtPartControl(QWidget *parent);
void SetT1(double t1){ m_Controls->m_T1box->setValue(t1); }
void SetT2(double t2){ m_Controls->m_T2box->setValue(t2); }
unsigned int GetT2(){ return m_Controls->m_T2box->value(); }
unsigned int GetT1(){ return m_Controls->m_T1box->value(); }
public slots:
protected:
// member variables
Ui::QmitkDotModelParametersWidgetControls* m_Controls;
private:
};
#endif // _QMITKDotModelParametersWidget_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkPrototypeSignalParametersWidget.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkPrototypeSignalParametersWidget.cpp
index 08871d5..27ca3a5 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkPrototypeSignalParametersWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkPrototypeSignalParametersWidget.cpp
@@ -1,43 +1,43 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
//Qmitk headers
#include "QmitkPrototypeSignalParametersWidget.h"
#include <itkDiffusionTensor3D.h>
const std::string QmitkPrototypeSignalParametersWidget::VIEW_ID = "org.mitk.views.prototypesignalparameterswidget";
QmitkPrototypeSignalParametersWidget::QmitkPrototypeSignalParametersWidget( QWidget * parent, Qt::WindowFlags )
: QWidget(parent)
{
m_Controls = nullptr;
this->CreateQtPartControl(this);
}
QmitkPrototypeSignalParametersWidget::~QmitkPrototypeSignalParametersWidget()
{
}
void QmitkPrototypeSignalParametersWidget::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
// create GUI widgets
m_Controls = new Ui::QmitkPrototypeSignalParametersWidgetControls;
m_Controls->setupUi(parent);
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkPrototypeSignalParametersWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkPrototypeSignalParametersWidget.h
index 76651cb..4d56834 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkPrototypeSignalParametersWidget.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkPrototypeSignalParametersWidget.h
@@ -1,64 +1,64 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _QmitkPrototypeSignalParametersWidget_H_INCLUDED
#define _QmitkPrototypeSignalParametersWidget_H_INCLUDED
//QT headers
#include <QWidget>
#include <QString>
#include "ui_QmitkPrototypeSignalParametersWidgetControls.h"
#include <org_mitk_gui_qt_diffusionimaging_fiberfox_Export.h>
/** @brief
*/
class DIFFUSIONIMAGING_FIBERFOX_EXPORT QmitkPrototypeSignalParametersWidget : public QWidget
{
//this is needed for all Qt objects that should have a MOC object (everything that derives from QObject)
Q_OBJECT
public:
static const std::string VIEW_ID;
QmitkPrototypeSignalParametersWidget (QWidget* parent = nullptr, Qt::WindowFlags f = nullptr);
virtual ~QmitkPrototypeSignalParametersWidget();
virtual void CreateQtPartControl(QWidget *parent);
void SetMinAdc(double min){ m_Controls->m_MinAdcBox->setValue(min); }
void SetMaxAdc(double max){ m_Controls->m_MaxAdcBox->setValue(max); }
void SetMinFa(double min){ m_Controls->m_MinFaBox->setValue(min); }
void SetMaxFa(double max){ m_Controls->m_MaxFaBox->setValue(max); }
void SetNumberOfSamples(int n){ m_Controls->m_NumSamplesBox->setValue(n); }
double GetMinAdc(){ return m_Controls->m_MinAdcBox->value(); }
double GetMaxAdc(){ return m_Controls->m_MaxAdcBox->value(); }
double GetMinFa(){ return m_Controls->m_MinFaBox->value(); }
double GetMaxFa(){ return m_Controls->m_MaxFaBox->value(); }
double GetNumberOfSamples(){ return m_Controls->m_NumSamplesBox->value(); }
public slots:
protected:
// member variables
Ui::QmitkPrototypeSignalParametersWidgetControls* m_Controls;
private:
};
#endif // _QmitkPrototypeSignalParametersWidget_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkStickModelParametersWidget.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkStickModelParametersWidget.cpp
index c78f527..7b00804 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkStickModelParametersWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkStickModelParametersWidget.cpp
@@ -1,42 +1,42 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
//Qmitk headers
#include "QmitkStickModelParametersWidget.h"
#include <itkDiffusionTensor3D.h>
const std::string QmitkStickModelParametersWidget::VIEW_ID = "org.mitk.views.StickModelParametersWidget";
QmitkStickModelParametersWidget::QmitkStickModelParametersWidget( QWidget * parent, Qt::WindowFlags )
: QWidget(parent)
{
m_Controls = nullptr;
this->CreateQtPartControl(this);
}
QmitkStickModelParametersWidget::~QmitkStickModelParametersWidget()
{
}
void QmitkStickModelParametersWidget::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
// create GUI widgets
m_Controls = new Ui::QmitkStickModelParametersWidgetControls;
m_Controls->setupUi(parent);
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkStickModelParametersWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkStickModelParametersWidget.h
index b0ad092..06e9f5a 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkStickModelParametersWidget.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkStickModelParametersWidget.h
@@ -1,60 +1,60 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _QMITKStickModelParametersWidget_H_INCLUDED
#define _QMITKStickModelParametersWidget_H_INCLUDED
//QT headers
#include <QWidget>
#include <QString>
#include "ui_QmitkStickModelParametersWidgetControls.h"
#include <org_mitk_gui_qt_diffusionimaging_fiberfox_Export.h>
/** @brief
*/
class DIFFUSIONIMAGING_FIBERFOX_EXPORT QmitkStickModelParametersWidget : public QWidget
{
//this is needed for all Qt objects that should have a MOC object (everything that derives from QObject)
Q_OBJECT
public:
static const std::string VIEW_ID;
QmitkStickModelParametersWidget (QWidget* parent = nullptr, Qt::WindowFlags f = nullptr);
virtual ~QmitkStickModelParametersWidget();
virtual void CreateQtPartControl(QWidget *parent);
void SetT1(double t1){ m_Controls->m_T1box->setValue(t1); }
void SetT2(double t2){ m_Controls->m_T2box->setValue(t2); }
void SetD(double d){ m_Controls->m_D1box->setValue(d); }
double GetD(){ return m_Controls->m_D1box->value(); }
unsigned int GetT2(){ return m_Controls->m_T2box->value(); }
unsigned int GetT1(){ return m_Controls->m_T1box->value(); }
public slots:
protected:
// member variables
Ui::QmitkStickModelParametersWidgetControls* m_Controls;
private:
};
#endif // _QMITKStickModelParametersWidget_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkTensorModelParametersWidget.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkTensorModelParametersWidget.cpp
index d448c25..a47ee1f 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkTensorModelParametersWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkTensorModelParametersWidget.cpp
@@ -1,63 +1,63 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
//Qmitk headers
#include "QmitkTensorModelParametersWidget.h"
#include <itkDiffusionTensor3D.h>
const std::string QmitkTensorModelParametersWidget::VIEW_ID = "org.mitk.views.tensormodelparameterswidget";
QmitkTensorModelParametersWidget::QmitkTensorModelParametersWidget( QWidget * parent, Qt::WindowFlags )
: QWidget(parent)
{
m_Controls = nullptr;
this->CreateQtPartControl(this);
}
QmitkTensorModelParametersWidget::~QmitkTensorModelParametersWidget()
{
}
void QmitkTensorModelParametersWidget::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
// create GUI widgets
m_Controls = new Ui::QmitkTensorModelParametersWidgetControls;
m_Controls->setupUi(parent);
connect((QObject*) m_Controls->m_D1box, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(DChanged(double)));
connect((QObject*) m_Controls->m_D2box, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(DChanged(double)));
connect((QObject*) m_Controls->m_D3box, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(DChanged(double)));
UpdateUi();
}
}
void QmitkTensorModelParametersWidget::UpdateUi()
{
itk::DiffusionTensor3D<float> tensor;
tensor.Fill(0);
tensor.SetElement(0,m_Controls->m_D1box->value());
tensor.SetElement(3,m_Controls->m_D2box->value());
tensor.SetElement(5,m_Controls->m_D3box->value());
m_Controls->m_FaLabel->setText(QString::number(tensor.GetFractionalAnisotropy()));
}
void QmitkTensorModelParametersWidget::DChanged( double )
{
UpdateUi();
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkTensorModelParametersWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkTensorModelParametersWidget.h
index 480e191..909dcb3 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkTensorModelParametersWidget.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkTensorModelParametersWidget.h
@@ -1,67 +1,67 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _QMITKTensorModelParametersWidget_H_INCLUDED
#define _QMITKTensorModelParametersWidget_H_INCLUDED
//QT headers
#include <QWidget>
#include <QString>
#include "ui_QmitkTensorModelParametersWidgetControls.h"
#include <org_mitk_gui_qt_diffusionimaging_fiberfox_Export.h>
/** @brief
*/
class DIFFUSIONIMAGING_FIBERFOX_EXPORT QmitkTensorModelParametersWidget : public QWidget
{
//this is needed for all Qt objects that should have a MOC object (everything that derives from QObject)
Q_OBJECT
public:
static const std::string VIEW_ID;
QmitkTensorModelParametersWidget (QWidget* parent = nullptr, Qt::WindowFlags f = nullptr);
virtual ~QmitkTensorModelParametersWidget();
virtual void CreateQtPartControl(QWidget *parent);
void SetT1(double t1){ m_Controls->m_T1box->setValue(t1); }
void SetT2(double t2){ m_Controls->m_T2box->setValue(t2); }
void SetD1(double d1){ m_Controls->m_D1box->setValue(d1); }
void SetD2(double d2){ m_Controls->m_D2box->setValue(d2); }
void SetD3(double d3){ m_Controls->m_D3box->setValue(d3); }
double GetD1(){ return m_Controls->m_D1box->value(); }
double GetD2(){ return m_Controls->m_D2box->value(); }
double GetD3(){ return m_Controls->m_D3box->value(); }
unsigned int GetT2(){ return m_Controls->m_T2box->value(); }
unsigned int GetT1(){ return m_Controls->m_T1box->value(); }
public slots:
void DChanged( double value );
protected:
// member variables
Ui::QmitkTensorModelParametersWidgetControls* m_Controls;
void UpdateUi();
private:
};
#endif // _QMITKTensorModelParametersWidget_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkZeppelinModelParametersWidget.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkZeppelinModelParametersWidget.cpp
index 3aa9974..0a56189 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkZeppelinModelParametersWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkZeppelinModelParametersWidget.cpp
@@ -1,62 +1,62 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
//Qmitk headers
#include "QmitkZeppelinModelParametersWidget.h"
#include <itkDiffusionTensor3D.h>
const std::string QmitkZeppelinModelParametersWidget::VIEW_ID = "org.mitk.views.ZeppelinModelParameterswidget";
QmitkZeppelinModelParametersWidget::QmitkZeppelinModelParametersWidget( QWidget * parent, Qt::WindowFlags )
: QWidget(parent)
{
m_Controls = nullptr;
this->CreateQtPartControl(this);
}
QmitkZeppelinModelParametersWidget::~QmitkZeppelinModelParametersWidget()
{
}
void QmitkZeppelinModelParametersWidget::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
// create GUI widgets
m_Controls = new Ui::QmitkZeppelinModelParametersWidgetControls;
m_Controls->setupUi(parent);
connect((QObject*) m_Controls->m_D1box, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(DChanged(double)));
connect((QObject*) m_Controls->m_D2box, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(DChanged(double)));
UpdateUi();
}
}
void QmitkZeppelinModelParametersWidget::UpdateUi()
{
itk::DiffusionTensor3D<float> tensor;
tensor.Fill(0);
tensor.SetElement(0,m_Controls->m_D1box->value());
tensor.SetElement(3,m_Controls->m_D2box->value());
tensor.SetElement(5,m_Controls->m_D2box->value());
m_Controls->m_FaLabel->setText(QString::number(tensor.GetFractionalAnisotropy()));
}
void QmitkZeppelinModelParametersWidget::DChanged( double )
{
UpdateUi();
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkZeppelinModelParametersWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkZeppelinModelParametersWidget.h
index 2ddc93e..ad2901f 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkZeppelinModelParametersWidget.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/QmitkZeppelinModelParametersWidget.h
@@ -1,65 +1,65 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _QMITKZeppelinModelParametersWidget_H_INCLUDED
#define _QMITKZeppelinModelParametersWidget_H_INCLUDED
//QT headers
#include <QWidget>
#include <QString>
#include "ui_QmitkZeppelinModelParametersWidgetControls.h"
#include <org_mitk_gui_qt_diffusionimaging_fiberfox_Export.h>
/** @brief
*/
class DIFFUSIONIMAGING_FIBERFOX_EXPORT QmitkZeppelinModelParametersWidget : public QWidget
{
//this is needed for all Qt objects that should have a MOC object (everything that derives from QObject)
Q_OBJECT
public:
static const std::string VIEW_ID;
QmitkZeppelinModelParametersWidget (QWidget* parent = nullptr, Qt::WindowFlags f = nullptr);
virtual ~QmitkZeppelinModelParametersWidget();
virtual void CreateQtPartControl(QWidget *parent);
void SetT1(double t1){ m_Controls->m_T1box->setValue(t1); }
void SetT2(double t2){ m_Controls->m_T2box->setValue(t2); }
void SetD1(double d1){ m_Controls->m_D1box->setValue(d1); }
void SetD2(double d2){ m_Controls->m_D2box->setValue(d2); }
double GetD1(){ return m_Controls->m_D1box->value(); }
double GetD2(){ return m_Controls->m_D2box->value(); }
unsigned int GetT2(){ return m_Controls->m_T2box->value(); }
unsigned int GetT1(){ return m_Controls->m_T1box->value(); }
public slots:
void DChanged( double value );
protected:
// member variables
Ui::QmitkZeppelinModelParametersWidgetControls* m_Controls;
void UpdateUi();
private:
};
#endif // _QMITKZeppelinModelParametersWidget_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/Perspectives/QmitkDIAppSyntheticDataGenerationPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/Perspectives/QmitkDIAppSyntheticDataGenerationPerspective.cpp
index 624a598..038d252 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/Perspectives/QmitkDIAppSyntheticDataGenerationPerspective.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/Perspectives/QmitkDIAppSyntheticDataGenerationPerspective.cpp
@@ -1,50 +1,50 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkDIAppSyntheticDataGenerationPerspective.h"
#include "berryIViewLayout.h"
void QmitkDIAppSyntheticDataGenerationPerspective::CreateInitialLayout(berry::IPageLayout::Pointer layout)
{
/////////////////////////////////////////////////////
// all di-app perspectives should have the following:
/////////////////////////////////////////////////////
QString editorArea = layout->GetEditorArea();
layout->AddStandaloneViewPlaceholder("org.mitk.views.viewnavigatorview", berry::IPageLayout::LEFT, 0.3f, editorArea, false);
layout->AddStandaloneView("org.mitk.views.datamanager",
false, berry::IPageLayout::LEFT, 0.3f, editorArea);
layout->AddStandaloneView("org.mitk.views.controlvisualizationpropertiesview",
false, berry::IPageLayout::BOTTOM, .15f, "org.mitk.views.datamanager");
berry::IFolderLayout::Pointer left =
layout->CreateFolder("org.mbi.diffusionimaginginternal.leftcontrols",
berry::IPageLayout::BOTTOM, 0.15f, "org.mitk.views.controlvisualizationpropertiesview");
layout->AddStandaloneViewPlaceholder("org.mitk.views.imagenavigator",
berry::IPageLayout::BOTTOM, .7f, "org.mbi.diffusionimaginginternal.leftcontrols", false);
/////////////////////////////////////////////
// here goes the perspective specific stuff
/////////////////////////////////////////////
left->AddView("org.mitk.views.fiberfoxview");
left->AddView("org.mitk.views.fibergenerationview");
left->AddView("org.mitk.views.fieldmapgenerator");
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/Perspectives/QmitkDIAppSyntheticDataGenerationPerspective.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/Perspectives/QmitkDIAppSyntheticDataGenerationPerspective.h
index a7fef04..f68a173 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/Perspectives/QmitkDIAppSyntheticDataGenerationPerspective.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/Perspectives/QmitkDIAppSyntheticDataGenerationPerspective.h
@@ -1,36 +1,36 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkDIAppSyntheticDataGenerationPerspective_H_
#define QmitkDIAppSyntheticDataGenerationPerspective_H_
#include <berryIPerspectiveFactory.h>
class QmitkDIAppSyntheticDataGenerationPerspective : public QObject, public berry::IPerspectiveFactory
{
Q_OBJECT
Q_INTERFACES(berry::IPerspectiveFactory)
public:
QmitkDIAppSyntheticDataGenerationPerspective() {}
~QmitkDIAppSyntheticDataGenerationPerspective() {}
void CreateInitialLayout(berry::IPageLayout::Pointer layout) override;
};
#endif /* QmitkDIAppSyntheticDataGenerationPerspective_H_ */
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.cpp
index c765fdb..3c2647c 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.cpp
@@ -1,1165 +1,1165 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// Qmitk
#include "QmitkFiberGenerationView.h"
// MITK
#include <mitkImage.h>
#include <mitkImageToItk.h>
#include <mitkImageCast.h>
#include <mitkProperties.h>
#include <mitkPlanarFigureInteractor.h>
#include <mitkDataStorage.h>
#include <itkFibersFromPlanarFiguresFilter.h>
#include <itkTractsToDWIImageFilter.h>
#include <mitkTensorImage.h>
#include <mitkILinkedRenderWindowPart.h>
#include <mitkImageToItk.h>
#include <mitkImageCast.h>
#include <mitkImageGenerator.h>
#include <mitkNodePredicateDataType.h>
#include <itkScalableAffineTransform.h>
#include <mitkLevelWindowProperty.h>
#include <mitkNodePredicateOr.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateProperty.h>
#include <mitkNodePredicateIsDWI.h>
#include <boost/property_tree/ptree.hpp>
#define RAPIDXML_NO_EXCEPTIONS
#include <boost/property_tree/xml_parser.hpp>
#include <boost/foreach.hpp>
#include <QFileDialog>
#include <QMessageBox>
#include "usModuleRegistry.h"
#include <mitkChiSquareNoiseModel.h>
#include <itksys/SystemTools.hxx>
#include <mitkIOUtil.h>
#include <QScrollBar>
#include <itkInvertIntensityImageFilter.h>
#include <QDialogButtonBox>
#include <itkAdcImageFilter.h>
#include <itkShiftScaleImageFilter.h>
#include <mitkITKImageImport.h>
#include <itkRandomPhantomFilter.h>
#include "mitkNodePredicateDataType.h"
#include <mitkNodePredicateProperty.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateOr.h>
#define _USE_MATH_DEFINES
#include <math.h>
const std::string QmitkFiberGenerationView::VIEW_ID = "org.mitk.views.fibergenerationview";
QmitkFiberGenerationView::QmitkFiberGenerationView()
: QmitkAbstractView()
, m_Controls( 0 )
, m_SelectedImageNode( nullptr )
{
}
// Destructor
QmitkFiberGenerationView::~QmitkFiberGenerationView()
{
}
void QmitkFiberGenerationView::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::QmitkFiberGenerationViewControls;
m_Controls->setupUi( parent );
m_ParameterFile = QDir::currentPath()+"/param.ffp";
connect(static_cast<QObject*>(m_Controls->m_RandomPhantomButton), SIGNAL(clicked()), static_cast<QObject*>(this), SLOT(RandomPhantom()));
connect(static_cast<QObject*>(m_Controls->m_GenerateFibersButton), SIGNAL(clicked()), static_cast<QObject*>(this), SLOT(GenerateFibers()));
connect(static_cast<QObject*>(m_Controls->m_CircleButton), SIGNAL(clicked()), static_cast<QObject*>(this), SLOT(OnDrawROI()));
connect(static_cast<QObject*>(m_Controls->m_FlipButton), SIGNAL(clicked()), static_cast<QObject*>(this), SLOT(OnFlipButton()));
connect(static_cast<QObject*>(m_Controls->m_JoinBundlesButton), SIGNAL(clicked()), static_cast<QObject*>(this), SLOT(JoinBundles()));
connect(static_cast<QObject*>(m_Controls->m_VarianceBox), SIGNAL(valueChanged(double)), static_cast<QObject*>(this), SLOT(OnVarianceChanged(double)));
connect(static_cast<QObject*>(m_Controls->m_DistributionBox), SIGNAL(currentIndexChanged(int)), static_cast<QObject*>(this), SLOT(OnDistributionChanged(int)));
connect(static_cast<QObject*>(m_Controls->m_FiberDensityBox), SIGNAL(valueChanged(int)), static_cast<QObject*>(this), SLOT(OnFiberDensityChanged(int)));
connect(static_cast<QObject*>(m_Controls->m_FiberSamplingBox), SIGNAL(valueChanged(double)), static_cast<QObject*>(this), SLOT(OnFiberSamplingChanged(double)));
connect(static_cast<QObject*>(m_Controls->m_TensionBox), SIGNAL(valueChanged(double)), static_cast<QObject*>(this), SLOT(OnTensionChanged(double)));
connect(static_cast<QObject*>(m_Controls->m_ContinuityBox), SIGNAL(valueChanged(double)), static_cast<QObject*>(this), SLOT(OnContinuityChanged(double)));
connect(static_cast<QObject*>(m_Controls->m_BiasBox), SIGNAL(valueChanged(double)), static_cast<QObject*>(this), SLOT(OnBiasChanged(double)));
connect(static_cast<QObject*>(m_Controls->m_ConstantRadiusBox), SIGNAL(stateChanged(int)), static_cast<QObject*>(this), SLOT(OnConstantRadius(int)));
connect(static_cast<QObject*>(m_Controls->m_CopyBundlesButton), SIGNAL(clicked()), static_cast<QObject*>(this), SLOT(CopyBundles()));
connect(static_cast<QObject*>(m_Controls->m_TransformBundlesButton), SIGNAL(clicked()), static_cast<QObject*>(this), SLOT(ApplyTransform()));
connect(static_cast<QObject*>(m_Controls->m_AlignOnGrid), SIGNAL(clicked()), static_cast<QObject*>(this), SLOT(AlignOnGrid()));
connect(static_cast<QObject*>(m_Controls->m_FidAxis1), SIGNAL(editingFinished()), static_cast<QObject*>(this), SLOT(UpdateFiducialPosition()));
connect(static_cast<QObject*>(m_Controls->m_FidAxis2), SIGNAL(editingFinished()), static_cast<QObject*>(this), SLOT(UpdateFiducialPosition()));
connect(static_cast<QObject*>(m_Controls->m_FidPosX), SIGNAL(editingFinished()), static_cast<QObject*>(this), SLOT(UpdateFiducialPosition()));
connect(static_cast<QObject*>(m_Controls->m_FidPosY), SIGNAL(editingFinished()), static_cast<QObject*>(this), SLOT(UpdateFiducialPosition()));
connect(static_cast<QObject*>(m_Controls->m_FidPosZ), SIGNAL(editingFinished()), static_cast<QObject*>(this), SLOT(UpdateFiducialPosition()));
connect(static_cast<QObject*>(m_Controls->m_FidTwist), SIGNAL(editingFinished()), static_cast<QObject*>(this), SLOT(UpdateFiducialPosition()));
connect(static_cast<QObject*>(m_Controls->m_AdvancedOptionsBox), SIGNAL( stateChanged(int)), static_cast<QObject*>(this), SLOT(ShowAdvancedOptions(int)));
connect(static_cast<QObject*>(m_Controls->m_SaveParametersButton), SIGNAL(clicked()), static_cast<QObject*>(this), SLOT(SaveParameters()));
connect(static_cast<QObject*>(m_Controls->m_LoadParametersButton), SIGNAL(clicked()), static_cast<QObject*>(this), SLOT(LoadParameters()));
OnDistributionChanged(0);
}
UpdateGui();
}
void QmitkFiberGenerationView::RandomPhantom()
{
itk::RandomPhantomFilter::Pointer filter = itk::RandomPhantomFilter::New();
filter->SetNumTracts(m_Controls->m_NumBundlesBox->value());
filter->SetMinStreamlineDensity(m_Controls->m_MinDensityBox->value());
filter->SetMaxStreamlineDensity(m_Controls->m_MaxDensityBox->value());
mitk::Vector3D vol;
vol[0] = m_Controls->m_VolumeSizeX->value();
vol[1] = m_Controls->m_VolumeSizeY->value();
vol[2] = m_Controls->m_VolumeSizeZ->value();
filter->SetVolumeSize(vol);
filter->SetStepSizeMin(m_Controls->m_StepSizeMinBox->value());
filter->SetStepSizeMax(m_Controls->m_StepSizeMaxBox->value());
filter->SetCurvynessMin(m_Controls->m_CurvyMinBox->value());
filter->SetCurvynessMax(m_Controls->m_CurvyMaxBox->value());
filter->SetStartRadiusMin(m_Controls->m_SizeMinBox->value());
filter->SetStartRadiusMax(m_Controls->m_SizeMaxBox->value());
filter->SetMinTwist(m_Controls->m_MinTwistBox->value());
filter->SetMaxTwist(m_Controls->m_MaxTwistBox->value());
filter->Update();
auto fibs = filter->GetFiberBundles();
std::vector< mitk::DataNode::Pointer > fiber_nodes;
int c = 1;
for (auto fib : fibs)
{
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( fib );
node->SetName("Bundle_" + boost::lexical_cast<std::string>(c));
GetDataStorage()->Add(node);
fiber_nodes.push_back(node);
++c;
}
// mitk::RenderingManager::GetInstance()->RequestUpdateAll();
mitk::RenderingManager::GetInstance()->InitializeViews(GetDataStorage()->ComputeVisibleBoundingGeometry3D());
}
void QmitkFiberGenerationView::UpdateParametersFromGui()
{
m_Parameters.ClearFiberParameters();
m_Parameters.m_Misc.m_CheckAdvancedFiberOptionsBox = m_Controls->m_AdvancedOptionsBox->isChecked();
switch(m_Controls->m_DistributionBox->currentIndex())
{
case 0:
m_Parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM;
break;
case 1:
m_Parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_GAUSSIAN;
break;
default:
m_Parameters.m_FiberGen.m_Distribution = FiberGenerationParameters::DISTRIBUTE_UNIFORM;
}
m_Parameters.m_FiberGen.m_Variance = m_Controls->m_VarianceBox->value();
m_Parameters.m_FiberGen.m_Density = m_Controls->m_FiberDensityBox->value();
m_Parameters.m_FiberGen.m_Sampling = m_Controls->m_FiberSamplingBox->value();
m_Parameters.m_FiberGen.m_Tension = m_Controls->m_TensionBox->value();
m_Parameters.m_FiberGen.m_Continuity = m_Controls->m_ContinuityBox->value();
m_Parameters.m_FiberGen.m_Bias = m_Controls->m_BiasBox->value();
m_Parameters.m_FiberGen.m_Rotation[0] = m_Controls->m_XrotBox->value();
m_Parameters.m_FiberGen.m_Rotation[1] = m_Controls->m_YrotBox->value();
m_Parameters.m_FiberGen.m_Rotation[2] = m_Controls->m_ZrotBox->value();
m_Parameters.m_FiberGen.m_Translation[0] = m_Controls->m_XtransBox->value();
m_Parameters.m_FiberGen.m_Translation[1] = m_Controls->m_YtransBox->value();
m_Parameters.m_FiberGen.m_Translation[2] = m_Controls->m_ZtransBox->value();
m_Parameters.m_FiberGen.m_Scale[0] = m_Controls->m_XscaleBox->value();
m_Parameters.m_FiberGen.m_Scale[1] = m_Controls->m_YscaleBox->value();
m_Parameters.m_FiberGen.m_Scale[2] = m_Controls->m_ZscaleBox->value();
m_Parameters.m_Misc.m_CheckRealTimeFibersBox = m_Controls->m_RealTimeFibers->isChecked();
m_Parameters.m_Misc.m_CheckAdvancedFiberOptionsBox = m_Controls->m_AdvancedOptionsBox->isChecked();
m_Parameters.m_Misc.m_CheckIncludeFiducialsBox = m_Controls->m_IncludeFiducials->isChecked();
m_Parameters.m_Misc.m_CheckConstantRadiusBox = m_Controls->m_ConstantRadiusBox->isChecked();
}
void QmitkFiberGenerationView::SaveParameters(QString filename)
{
UpdateParametersFromGui();
m_Parameters.SaveParameters(filename.toStdString());
m_ParameterFile = filename;
}
void QmitkFiberGenerationView::SaveParameters()
{
QString filename = QFileDialog::getSaveFileName(
0,
tr("Save Parameters"),
m_ParameterFile,
tr("Fiberfox Parameters (*.ffp)") );
SaveParameters(filename);
}
void QmitkFiberGenerationView::LoadParameters()
{
QString filename = QFileDialog::getOpenFileName(0, tr("Load Parameters"), QString(itksys::SystemTools::GetFilenamePath(m_ParameterFile.toStdString()).c_str()), tr("Fiberfox Parameters (*.ffp)") );
if(filename.isEmpty() || filename.isNull())
return;
m_ParameterFile = filename;
m_Parameters.LoadParameters(filename.toStdString());
if (m_Parameters.m_MissingTags.size()>0)
{
QString missing("Parameter file might be corrupted. The following parameters could not be read: ");
missing += QString(m_Parameters.m_MissingTags.c_str());
missing += "\nDefault values have been assigned to the missing parameters.";
QMessageBox::information( nullptr, "Warning!", missing);
}
m_Controls->m_RealTimeFibers->setChecked(m_Parameters.m_Misc.m_CheckRealTimeFibersBox);
m_Controls->m_AdvancedOptionsBox->setChecked(m_Parameters.m_Misc.m_CheckAdvancedFiberOptionsBox);
m_Controls->m_IncludeFiducials->setChecked(m_Parameters.m_Misc.m_CheckIncludeFiducialsBox);
m_Controls->m_ConstantRadiusBox->setChecked(m_Parameters.m_Misc.m_CheckConstantRadiusBox);
m_Controls->m_DistributionBox->setCurrentIndex(m_Parameters.m_FiberGen.m_Distribution);
m_Controls->m_VarianceBox->setValue(m_Parameters.m_FiberGen.m_Variance);
m_Controls->m_FiberDensityBox->setValue(m_Parameters.m_FiberGen.m_Density);
m_Controls->m_FiberSamplingBox->setValue(m_Parameters.m_FiberGen.m_Sampling);
m_Controls->m_TensionBox->setValue(m_Parameters.m_FiberGen.m_Tension);
m_Controls->m_ContinuityBox->setValue(m_Parameters.m_FiberGen.m_Continuity);
m_Controls->m_BiasBox->setValue(m_Parameters.m_FiberGen.m_Bias);
m_Controls->m_XrotBox->setValue(m_Parameters.m_FiberGen.m_Rotation[0]);
m_Controls->m_YrotBox->setValue(m_Parameters.m_FiberGen.m_Rotation[1]);
m_Controls->m_ZrotBox->setValue(m_Parameters.m_FiberGen.m_Rotation[2]);
m_Controls->m_XtransBox->setValue(m_Parameters.m_FiberGen.m_Translation[0]);
m_Controls->m_YtransBox->setValue(m_Parameters.m_FiberGen.m_Translation[1]);
m_Controls->m_ZtransBox->setValue(m_Parameters.m_FiberGen.m_Translation[2]);
m_Controls->m_XscaleBox->setValue(m_Parameters.m_FiberGen.m_Scale[0]);
m_Controls->m_YscaleBox->setValue(m_Parameters.m_FiberGen.m_Scale[1]);
m_Controls->m_ZscaleBox->setValue(m_Parameters.m_FiberGen.m_Scale[2]);
}
void QmitkFiberGenerationView::ShowAdvancedOptions(int state)
{
if (state)
{
m_Controls->m_AdvancedFiberOptionsFrame->setVisible(true);
m_Controls->m_AdvancedOptionsBox->setChecked(true);
}
else
{
m_Controls->m_AdvancedFiberOptionsFrame->setVisible(false);
m_Controls->m_AdvancedOptionsBox->setChecked(false);
}
}
void QmitkFiberGenerationView::OnConstantRadius(int value)
{
if (value>0 && m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
void QmitkFiberGenerationView::OnDistributionChanged(int value)
{
if (value==1)
m_Controls->m_VarianceBox->setVisible(true);
else
m_Controls->m_VarianceBox->setVisible(false);
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
void QmitkFiberGenerationView::OnVarianceChanged(double)
{
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
void QmitkFiberGenerationView::OnFiberDensityChanged(int)
{
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
void QmitkFiberGenerationView::OnFiberSamplingChanged(double)
{
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
void QmitkFiberGenerationView::OnTensionChanged(double)
{
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
void QmitkFiberGenerationView::OnContinuityChanged(double)
{
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
void QmitkFiberGenerationView::OnBiasChanged(double)
{
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
void QmitkFiberGenerationView::UpdateFiducialPosition()
{
if (m_SelectedFiducials.size()!=1)
return;
mitk::PlanarEllipse* pe = dynamic_cast<mitk::PlanarEllipse*>(m_SelectedFiducials.at(0)->GetData());
mitk::BaseGeometry* geom = pe->GetGeometry();
// translate
mitk::Point3D origin;
origin[0] = m_Controls->m_FidPosX->value();
origin[1] = m_Controls->m_FidPosY->value();
origin[2] = m_Controls->m_FidPosZ->value();
// transform control point coordinate into geometry translation
auto p0 = pe->GetControlPoint(0);
auto p1 = pe->GetControlPoint(1);
auto p2 = pe->GetControlPoint(2);
auto p3 = pe->GetControlPoint(3);
auto v1 = p1 - p0;
auto v2 = p2 - p0;
auto angle_deg = m_Controls->m_FidTwist->value();
auto dot = std::cos(itk::Math::pi*angle_deg/180.0);
vnl_matrix_fixed<double, 2, 2> tRot;
tRot[0][0] = dot;
tRot[1][1] = tRot[0][0];
tRot[1][0] = sin(acos(tRot[0][0]));
tRot[0][1] = -tRot[1][0];
if (angle_deg<0)
tRot = tRot.transpose();
vnl_vector_fixed<double, 2> vt; vt[0]=1; vt[1]=0;
vnl_vector_fixed<double, 2> v3 = tRot*vt;
if (v1.GetNorm()<0.0001 || v2.GetNorm()<0.0001)
{
QMessageBox::information( nullptr, "", "Please select exactly one fiducial.");
return;
}
v1.Normalize();
v2.Normalize();
p1 = p0 + v1*m_Controls->m_FidAxis1->value();
p2 = p0 + v2*m_Controls->m_FidAxis2->value();
p3 = p0 + mitk::Vector2D(v3);
pe->SetControlPoint(1, p1);
pe->SetControlPoint(2, p2);
pe->SetControlPoint(3, p3);
geom->SetOrigin(origin);
pe->Modified();
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
UpdateGui();
}
void QmitkFiberGenerationView::AlignOnGrid()
{
for (unsigned int i=0; i<m_SelectedFiducials.size(); i++)
{
mitk::PlanarEllipse::Pointer pe = dynamic_cast<mitk::PlanarEllipse*>(m_SelectedFiducials.at(i)->GetData());
mitk::Point3D wc0 = pe->GetWorldControlPoint(0);
mitk::DataStorage::SetOfObjects::ConstPointer parentFibs = GetDataStorage()->GetSources(m_SelectedFiducials.at(i));
for( mitk::DataStorage::SetOfObjects::const_iterator it = parentFibs->begin(); it != parentFibs->end(); ++it )
{
mitk::DataNode::Pointer pFibNode = *it;
if ( pFibNode.IsNotNull() && dynamic_cast<mitk::FiberBundle*>(pFibNode->GetData()) )
{
mitk::DataStorage::SetOfObjects::ConstPointer parentImgs = GetDataStorage()->GetSources(pFibNode);
for( mitk::DataStorage::SetOfObjects::const_iterator it2 = parentImgs->begin(); it2 != parentImgs->end(); ++it2 )
{
mitk::DataNode::Pointer pImgNode = *it2;
if ( pImgNode.IsNotNull() && dynamic_cast<mitk::Image*>(pImgNode->GetData()) )
{
mitk::Image::Pointer img = dynamic_cast<mitk::Image*>(pImgNode->GetData());
mitk::BaseGeometry::Pointer geom = img->GetGeometry();
itk::Index<3> idx;
geom->WorldToIndex(wc0, idx);
mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2];
mitk::Point3D world;
geom->IndexToWorld(cIdx,world);
mitk::Vector3D trans = world - wc0;
pe->GetGeometry()->Translate(trans);
break;
}
}
break;
}
}
}
for(unsigned int i=0; i<m_SelectedBundles2.size(); i++ )
{
mitk::DataNode::Pointer fibNode = m_SelectedBundles2.at(i);
mitk::DataStorage::SetOfObjects::ConstPointer sources = GetDataStorage()->GetSources(fibNode);
for( mitk::DataStorage::SetOfObjects::const_iterator it = sources->begin(); it != sources->end(); ++it )
{
mitk::DataNode::Pointer imgNode = *it;
if ( imgNode.IsNotNull() && dynamic_cast<mitk::Image*>(imgNode->GetData()) )
{
mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(fibNode);
for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 )
{
mitk::DataNode::Pointer fiducialNode = *it2;
if ( fiducialNode.IsNotNull() && dynamic_cast<mitk::PlanarEllipse*>(fiducialNode->GetData()) )
{
mitk::PlanarEllipse::Pointer pe = dynamic_cast<mitk::PlanarEllipse*>(fiducialNode->GetData());
mitk::Point3D wc0 = pe->GetWorldControlPoint(0);
mitk::Image::Pointer img = dynamic_cast<mitk::Image*>(imgNode->GetData());
mitk::BaseGeometry::Pointer geom = img->GetGeometry();
itk::Index<3> idx;
geom->WorldToIndex(wc0, idx);
mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2];
mitk::Point3D world;
geom->IndexToWorld(cIdx,world);
mitk::Vector3D trans = world - wc0;
pe->GetGeometry()->Translate(trans);
}
}
break;
}
}
}
for(unsigned int i=0; i<m_SelectedImages.size(); i++ )
{
mitk::Image::Pointer img = dynamic_cast<mitk::Image*>(m_SelectedImages.at(i)->GetData());
mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(m_SelectedImages.at(i));
for( mitk::DataStorage::SetOfObjects::const_iterator it = derivations->begin(); it != derivations->end(); ++it )
{
mitk::DataNode::Pointer fibNode = *it;
if ( fibNode.IsNotNull() && dynamic_cast<mitk::FiberBundle*>(fibNode->GetData()) )
{
mitk::DataStorage::SetOfObjects::ConstPointer derivations2 = GetDataStorage()->GetDerivations(fibNode);
for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations2->begin(); it2 != derivations2->end(); ++it2 )
{
mitk::DataNode::Pointer fiducialNode = *it2;
if ( fiducialNode.IsNotNull() && dynamic_cast<mitk::PlanarEllipse*>(fiducialNode->GetData()) )
{
mitk::PlanarEllipse::Pointer pe = dynamic_cast<mitk::PlanarEllipse*>(fiducialNode->GetData());
mitk::Point3D wc0 = pe->GetWorldControlPoint(0);
mitk::BaseGeometry::Pointer geom = img->GetGeometry();
itk::Index<3> idx;
geom->WorldToIndex(wc0, idx);
mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2];
mitk::Point3D world;
geom->IndexToWorld(cIdx,world);
mitk::Vector3D trans = world - wc0;
pe->GetGeometry()->Translate(trans);
}
}
}
}
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
void QmitkFiberGenerationView::OnFlipButton()
{
if (m_SelectedFiducial.IsNull())
return;
std::map<mitk::DataNode*, QmitkPlanarFigureData>::iterator it = m_DataNodeToPlanarFigureData.find(m_SelectedFiducial.GetPointer());
if( it != m_DataNodeToPlanarFigureData.end() )
{
QmitkPlanarFigureData& data = it->second;
data.m_Flipped += 1;
data.m_Flipped %= 2;
}
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
void QmitkFiberGenerationView::OnAddBundle()
{
if (m_SelectedImageNode.IsNull())
return;
mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedImageNode);
mitk::FiberBundle::Pointer bundle = mitk::FiberBundle::New();
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( bundle );
QString name = QString("Bundle_%1").arg(children->size());
node->SetName(name.toStdString());
m_SelectedBundles.push_back(node);
UpdateGui();
GetDataStorage()->Add(node, m_SelectedImageNode);
}
void QmitkFiberGenerationView::OnDrawROI()
{
if (m_SelectedBundles.empty())
OnAddBundle();
if (m_SelectedBundles.empty())
return;
mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedBundles.at(0));
mitk::PlanarEllipse::Pointer figure = mitk::PlanarEllipse::New();
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( figure );
node->SetBoolProperty("planarfigure.3drendering", true);
node->SetBoolProperty("planarfigure.3drendering.fill", true);
QList<mitk::DataNode::Pointer> nodes = this->GetDataManagerSelection();
for( int i=0; i<nodes.size(); i++)
nodes.at(i)->SetSelected(false);
m_SelectedFiducial = node;
QString name = QString("Fiducial_%1").arg(children->size());
node->SetName(name.toStdString());
node->SetSelected(true);
this->DisableCrosshairNavigation();
mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast<mitk::PlanarFigureInteractor*>(node->GetDataInteractor().GetPointer());
if(figureInteractor.IsNull())
{
figureInteractor = mitk::PlanarFigureInteractor::New();
us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" );
figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule );
figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule );
figureInteractor->SetDataNode( node );
}
UpdateGui();
GetDataStorage()->Add(node, m_SelectedBundles.at(0));
}
bool QmitkFiberGenerationView::CompareLayer(mitk::DataNode::Pointer i,mitk::DataNode::Pointer j)
{
int li = -1;
i->GetPropertyValue("layer", li);
int lj = -1;
j->GetPropertyValue("layer", lj);
return li<lj;
}
void QmitkFiberGenerationView::GenerateFibers()
{
UpdateGui();
if (m_SelectedBundles.empty())
{
if (m_SelectedFiducial.IsNull())
return;
mitk::DataStorage::SetOfObjects::ConstPointer parents = GetDataStorage()->GetSources(m_SelectedFiducial);
for( mitk::DataStorage::SetOfObjects::const_iterator it = parents->begin(); it != parents->end(); ++it )
if(dynamic_cast<mitk::FiberBundle*>((*it)->GetData()))
m_SelectedBundles.push_back(*it);
if (m_SelectedBundles.empty())
return;
}
UpdateParametersFromGui();
for (unsigned int i=0; i<m_SelectedBundles.size(); i++)
{
mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedBundles.at(i));
std::vector< mitk::DataNode::Pointer > childVector;
for( mitk::DataStorage::SetOfObjects::const_iterator it = children->begin(); it != children->end(); ++it )
childVector.push_back(*it);
std::sort(childVector.begin(), childVector.end(), CompareLayer);
std::vector< mitk::PlanarEllipse::Pointer > fib;
std::vector< unsigned int > flip;
float radius = 1;
int count = 0;
for( std::vector< mitk::DataNode::Pointer >::const_iterator it = childVector.begin(); it != childVector.end(); ++it )
{
mitk::DataNode::Pointer node = *it;
if ( node.IsNotNull() && dynamic_cast<mitk::PlanarEllipse*>(node->GetData()) )
{
mitk::PlanarEllipse* ellipse = dynamic_cast<mitk::PlanarEllipse*>(node->GetData());
if (m_Controls->m_ConstantRadiusBox->isChecked())
{
ellipse->SetTreatAsCircle(true);
mitk::Point2D c = ellipse->GetControlPoint(0);
mitk::Point2D p = ellipse->GetControlPoint(1);
mitk::Vector2D v = p-c;
if (count==0)
{
radius = v.GetVnlVector().magnitude();
ellipse->SetControlPoint(1, p);
ellipse->Modified();
}
else
{
v.Normalize();
v *= radius;
ellipse->SetControlPoint(1, c+v);
ellipse->Modified();
}
}
fib.push_back(ellipse);
std::map<mitk::DataNode*, QmitkPlanarFigureData>::iterator it = m_DataNodeToPlanarFigureData.find(node.GetPointer());
if( it != m_DataNodeToPlanarFigureData.end() )
{
QmitkPlanarFigureData& data = it->second;
flip.push_back(data.m_Flipped);
}
else
flip.push_back(0);
}
count++;
}
if (fib.size()>1)
{
m_Parameters.m_FiberGen.m_Fiducials.push_back(fib);
m_Parameters.m_FiberGen.m_FlipList.push_back(flip);
}
else if (fib.size()>0)
m_SelectedBundles.at(i)->SetData( mitk::FiberBundle::New() );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
itk::FibersFromPlanarFiguresFilter::Pointer filter = itk::FibersFromPlanarFiguresFilter::New();
filter->SetParameters(m_Parameters.m_FiberGen);
filter->Update();
std::vector< mitk::FiberBundle::Pointer > fiberBundles = filter->GetFiberBundles();
for (unsigned int i=0; i<fiberBundles.size(); i++)
{
m_SelectedBundles.at(i)->SetData( fiberBundles.at(i) );
if (fiberBundles.at(i)->GetNumFibers()>50000)
m_SelectedBundles.at(i)->SetVisibility(false);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkFiberGenerationView::ApplyTransform()
{
std::vector< mitk::DataNode::Pointer > selectedBundles;
for(unsigned int i=0; i<m_SelectedImages.size(); i++ )
{
mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(m_SelectedImages.at(i));
for( mitk::DataStorage::SetOfObjects::const_iterator it = derivations->begin(); it != derivations->end(); ++it )
{
mitk::DataNode::Pointer fibNode = *it;
if ( fibNode.IsNotNull() && dynamic_cast<mitk::FiberBundle*>(fibNode->GetData()) )
selectedBundles.push_back(fibNode);
}
}
if (selectedBundles.empty())
selectedBundles = m_SelectedBundles2;
if (!selectedBundles.empty())
{
for (std::vector<mitk::DataNode::Pointer>::const_iterator it = selectedBundles.begin(); it!=selectedBundles.end(); ++it)
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>((*it)->GetData());
fib->RotateAroundAxis(m_Controls->m_XrotBox->value(), m_Controls->m_YrotBox->value(), m_Controls->m_ZrotBox->value());
fib->TranslateFibers(m_Controls->m_XtransBox->value(), m_Controls->m_YtransBox->value(), m_Controls->m_ZtransBox->value());
fib->ScaleFibers(m_Controls->m_XscaleBox->value(), m_Controls->m_YscaleBox->value(), m_Controls->m_ZscaleBox->value());
// handle child fiducials
if (m_Controls->m_IncludeFiducials->isChecked())
{
mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(*it);
for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 )
{
mitk::DataNode::Pointer fiducialNode = *it2;
if ( fiducialNode.IsNotNull() && dynamic_cast<mitk::PlanarEllipse*>(fiducialNode->GetData()) )
{
mitk::PlanarEllipse* pe = dynamic_cast<mitk::PlanarEllipse*>(fiducialNode->GetData());
mitk::BaseGeometry* geom = pe->GetGeometry();
// translate
mitk::Vector3D world;
world[0] = m_Controls->m_XtransBox->value();
world[1] = m_Controls->m_YtransBox->value();
world[2] = m_Controls->m_ZtransBox->value();
geom->Translate(world);
// calculate rotation matrix
double x = m_Controls->m_XrotBox->value()*itk::Math::pi/180;
double y = m_Controls->m_YrotBox->value()*itk::Math::pi/180;
double z = m_Controls->m_ZrotBox->value()*itk::Math::pi/180;
itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity();
rotX[1][1] = cos(x);
rotX[2][2] = rotX[1][1];
rotX[1][2] = -sin(x);
rotX[2][1] = -rotX[1][2];
itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity();
rotY[0][0] = cos(y);
rotY[2][2] = rotY[0][0];
rotY[0][2] = sin(y);
rotY[2][0] = -rotY[0][2];
itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity();
rotZ[0][0] = cos(z);
rotZ[1][1] = rotZ[0][0];
rotZ[0][1] = -sin(z);
rotZ[1][0] = -rotZ[0][1];
itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX;
// transform control point coordinate into geometry translation
geom->SetOrigin(pe->GetWorldControlPoint(0));
mitk::Point2D cp; cp.Fill(0.0);
pe->SetControlPoint(0, cp);
// rotate fiducial
geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix());
// implicit translation
mitk::Vector3D trans;
trans[0] = geom->GetOrigin()[0]-fib->GetGeometry()->GetCenter()[0];
trans[1] = geom->GetOrigin()[1]-fib->GetGeometry()->GetCenter()[1];
trans[2] = geom->GetOrigin()[2]-fib->GetGeometry()->GetCenter()[2];
mitk::Vector3D newWc = rot*trans;
newWc = newWc-trans;
geom->Translate(newWc);
pe->Modified();
}
}
}
}
}
else
{
for (unsigned int i=0; i<m_SelectedFiducials.size(); i++)
{
mitk::PlanarEllipse* pe = dynamic_cast<mitk::PlanarEllipse*>(m_SelectedFiducials.at(i)->GetData());
mitk::BaseGeometry* geom = pe->GetGeometry();
// translate
mitk::Vector3D world;
world[0] = m_Controls->m_XtransBox->value();
world[1] = m_Controls->m_YtransBox->value();
world[2] = m_Controls->m_ZtransBox->value();
geom->Translate(world);
// calculate rotation matrix
double x = m_Controls->m_XrotBox->value()*itk::Math::pi/180;
double y = m_Controls->m_YrotBox->value()*itk::Math::pi/180;
double z = m_Controls->m_ZrotBox->value()*itk::Math::pi/180;
itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity();
rotX[1][1] = cos(x);
rotX[2][2] = rotX[1][1];
rotX[1][2] = -sin(x);
rotX[2][1] = -rotX[1][2];
itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity();
rotY[0][0] = cos(y);
rotY[2][2] = rotY[0][0];
rotY[0][2] = sin(y);
rotY[2][0] = -rotY[0][2];
itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity();
rotZ[0][0] = cos(z);
rotZ[1][1] = rotZ[0][0];
rotZ[0][1] = -sin(z);
rotZ[1][0] = -rotZ[0][1];
itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX;
// transform control point coordinate into geometry translation
geom->SetOrigin(pe->GetWorldControlPoint(0));
mitk::Point2D cp; cp.Fill(0.0);
pe->SetControlPoint(0, cp);
// rotate fiducial
geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix());
pe->Modified();
}
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkFiberGenerationView::CopyBundles()
{
if ( m_SelectedBundles.size()<1 ){
QMessageBox::information( nullptr, "Warning", "Select at least one fiber bundle!");
MITK_WARN("QmitkFiberGenerationView") << "Select at least one fiber bundle!";
return;
}
for (std::vector<mitk::DataNode::Pointer>::const_iterator it = m_SelectedBundles.begin(); it!=m_SelectedBundles.end(); ++it)
{
// find parent image
mitk::DataNode::Pointer parentNode;
mitk::DataStorage::SetOfObjects::ConstPointer parentImgs = GetDataStorage()->GetSources(*it);
for( mitk::DataStorage::SetOfObjects::const_iterator it2 = parentImgs->begin(); it2 != parentImgs->end(); ++it2 )
{
mitk::DataNode::Pointer pImgNode = *it2;
if ( pImgNode.IsNotNull() && dynamic_cast<mitk::Image*>(pImgNode->GetData()) )
{
parentNode = pImgNode;
break;
}
}
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>((*it)->GetData());
mitk::FiberBundle::Pointer newBundle = fib->GetDeepCopy();
QString name((*it)->GetName().c_str());
name += "_copy";
mitk::DataNode::Pointer fbNode = mitk::DataNode::New();
fbNode->SetData(newBundle);
fbNode->SetName(name.toStdString());
fbNode->SetVisibility(true);
if (parentNode.IsNotNull())
GetDataStorage()->Add(fbNode, parentNode);
else
GetDataStorage()->Add(fbNode);
// copy child fiducials
if (m_Controls->m_IncludeFiducials->isChecked())
{
mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(*it);
for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 )
{
mitk::DataNode::Pointer fiducialNode = *it2;
if ( fiducialNode.IsNotNull() && dynamic_cast<mitk::PlanarEllipse*>(fiducialNode->GetData()) )
{
mitk::PlanarEllipse::Pointer pe = dynamic_cast<mitk::PlanarEllipse*>(fiducialNode->GetData())->Clone();
mitk::DataNode::Pointer newNode = mitk::DataNode::New();
newNode->SetData(pe);
newNode->SetName(fiducialNode->GetName());
newNode->SetBoolProperty("planarfigure.3drendering", true);
GetDataStorage()->Add(newNode, fbNode);
}
}
}
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkFiberGenerationView::JoinBundles()
{
if ( m_SelectedBundles.size()<2 ){
QMessageBox::information( nullptr, "Warning", "Select at least two fiber bundles!");
MITK_WARN("QmitkFiberGenerationView") << "Select at least two fiber bundles!";
return;
}
std::vector< mitk::FiberBundle::Pointer > to_add;
std::vector<mitk::DataNode::Pointer>::const_iterator it = m_SelectedBundles.begin();
(*it)->SetVisibility(false);
mitk::FiberBundle::Pointer newBundle = dynamic_cast<mitk::FiberBundle*>((*it)->GetData());
QString name("");
name += QString((*it)->GetName().c_str());
++it;
for (; it!=m_SelectedBundles.end(); ++it)
{
(*it)->SetVisibility(false);
to_add.push_back(dynamic_cast<mitk::FiberBundle*>((*it)->GetData()));
}
newBundle = newBundle->AddBundles(to_add);
mitk::DataNode::Pointer fbNode = mitk::DataNode::New();
fbNode->SetData(newBundle);
fbNode->SetName("Joined");
fbNode->SetVisibility(true);
GetDataStorage()->Add(fbNode);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkFiberGenerationView::UpdateGui()
{
m_Controls->m_FiberGenMessage->setVisible(true);
m_Controls->m_TransformBundlesButton->setEnabled(false);
m_Controls->m_CopyBundlesButton->setEnabled(false);
m_Controls->m_GenerateFibersButton->setEnabled(false);
m_Controls->m_FlipButton->setEnabled(false);
m_Controls->m_CircleButton->setEnabled(false);
m_Controls->m_JoinBundlesButton->setEnabled(false);
m_Controls->m_AlignOnGrid->setEnabled(false);
m_Controls->m_FiducialAttributeBox->setEnabled(false);
// Fiber generation gui
if (m_SelectedFiducial.IsNotNull())
{
m_Controls->m_TransformBundlesButton->setEnabled(true);
m_Controls->m_FlipButton->setEnabled(true);
m_Controls->m_AlignOnGrid->setEnabled(true);
}
if (m_SelectedFiducials.size()==1)
{
m_Controls->m_FiducialAttributeBox->setEnabled(true);
mitk::PlanarEllipse* pe = dynamic_cast<mitk::PlanarEllipse*>(m_SelectedFiducials.at(0)->GetData());
auto origin = pe->GetGeometry()->GetOrigin();
m_Controls->m_FidPosX->setValue(origin[0]);
m_Controls->m_FidPosY->setValue(origin[1]);
m_Controls->m_FidPosZ->setValue(origin[2]);
auto p0 = pe->GetControlPoint(0);
auto p1 = pe->GetControlPoint(1);
auto p2 = pe->GetControlPoint(2);
auto p3 = pe->GetControlPoint(3);
auto v1 = p1 - p0;
auto v2 = p2 - p0;
m_Controls->m_FidAxis1->setValue(v1.GetNorm());
m_Controls->m_FidAxis2->setValue(v2.GetNorm());
vnl_vector_fixed<double, 2> vt; vt[0]=1; vt[1]=0;
auto v3 = p3-p0; v3.Normalize();
auto angle = dot_product(vt, v3.GetVnlVector());
angle = std::acos(angle)*180.0/itk::Math::pi;
if (v3[1]<0)
angle *= -1;
m_Controls->m_FidTwist->setValue(angle);
}
else
{
m_Controls->m_FidPosX->setValue(0);
m_Controls->m_FidPosY->setValue(0);
m_Controls->m_FidPosZ->setValue(0);
m_Controls->m_FidAxis1->setValue(1);
m_Controls->m_FidAxis2->setValue(1);
m_Controls->m_FidTwist->setValue(0);
}
if (m_SelectedImageNode.IsNotNull() || !m_SelectedBundles.empty())
{
m_Controls->m_CircleButton->setEnabled(true);
m_Controls->m_FiberGenMessage->setVisible(false);
}
if (m_SelectedImageNode.IsNotNull() && !m_SelectedBundles.empty())
m_Controls->m_AlignOnGrid->setEnabled(true);
if (!m_SelectedBundles.empty())
{
m_Controls->m_TransformBundlesButton->setEnabled(true);
m_Controls->m_CopyBundlesButton->setEnabled(true);
m_Controls->m_GenerateFibersButton->setEnabled(true);
if (m_SelectedBundles.size()>1)
m_Controls->m_JoinBundlesButton->setEnabled(true);
}
}
void QmitkFiberGenerationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList<mitk::DataNode::Pointer>& nodes)
{
m_SelectedBundles2.clear();
m_SelectedImages.clear();
m_SelectedFiducials.clear();
m_SelectedFiducial = nullptr;
m_SelectedBundles.clear();
m_SelectedImageNode = nullptr;
// iterate all selected objects, adjust warning visibility
for( int i=0; i<nodes.size(); i++)
{
mitk::DataNode::Pointer node = nodes.at(i);
if( node.IsNotNull() && dynamic_cast<mitk::Image*>(node->GetData()) )
{
m_SelectedImages.push_back(node);
m_SelectedImageNode = node;
}
else if ( node.IsNotNull() && dynamic_cast<mitk::FiberBundle*>(node->GetData()) )
{
m_SelectedBundles2.push_back(node);
if (m_Controls->m_RealTimeFibers->isChecked())
{
m_SelectedBundles.push_back(node);
mitk::FiberBundle::Pointer newFib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
if (newFib->GetNumFibers()!=static_cast<unsigned int>(m_Controls->m_FiberDensityBox->value()))
GenerateFibers();
}
else
m_SelectedBundles.push_back(node);
}
else if ( node.IsNotNull() && dynamic_cast<mitk::PlanarEllipse*>(node->GetData()) )
{
m_SelectedFiducials.push_back(node);
m_SelectedFiducial = node;
m_SelectedBundles.clear();
mitk::DataStorage::SetOfObjects::ConstPointer parents = GetDataStorage()->GetSources(node);
for( mitk::DataStorage::SetOfObjects::const_iterator it = parents->begin(); it != parents->end(); ++it )
{
mitk::DataNode::Pointer pNode = *it;
if ( pNode.IsNotNull() && dynamic_cast<mitk::FiberBundle*>(pNode->GetData()) )
m_SelectedBundles.push_back(pNode);
}
}
}
UpdateGui();
}
void QmitkFiberGenerationView::EnableCrosshairNavigation()
{
if (m_Controls->m_RealTimeFibers->isChecked())
GenerateFibers();
}
void QmitkFiberGenerationView::DisableCrosshairNavigation()
{
}
void QmitkFiberGenerationView::NodeRemoved(const mitk::DataNode* node)
{
mitk::DataNode* nonConstNode = const_cast<mitk::DataNode*>(node);
std::map<mitk::DataNode*, QmitkPlanarFigureData>::iterator it = m_DataNodeToPlanarFigureData.find(nonConstNode);
if (dynamic_cast<FiberBundle*>(node->GetData()))
{
m_SelectedBundles.clear();
m_SelectedBundles2.clear();
}
else if (dynamic_cast<Image*>(node->GetData()))
m_SelectedImages.clear();
if( it != m_DataNodeToPlanarFigureData.end() )
{
QmitkPlanarFigureData& data = it->second;
// remove observers
data.m_Figure->RemoveObserver( data.m_EndPlacementObserverTag );
data.m_Figure->RemoveObserver( data.m_SelectObserverTag );
data.m_Figure->RemoveObserver( data.m_StartInteractionObserverTag );
data.m_Figure->RemoveObserver( data.m_EndInteractionObserverTag );
m_DataNodeToPlanarFigureData.erase( it );
}
}
void QmitkFiberGenerationView::NodeAdded( const mitk::DataNode* node )
{
// add observer for selection in renderwindow
mitk::PlanarFigure* figure = dynamic_cast<mitk::PlanarFigure*>(node->GetData());
bool isPositionMarker (false);
node->GetBoolProperty("isContourMarker", isPositionMarker);
if( figure && !isPositionMarker )
{
MITK_DEBUG << "figure added. will add interactor if needed.";
mitk::PlanarFigureInteractor::Pointer figureInteractor
= dynamic_cast<mitk::PlanarFigureInteractor*>(node->GetDataInteractor().GetPointer());
mitk::DataNode* nonConstNode = const_cast<mitk::DataNode*>( node );
if(figureInteractor.IsNull())
{
figureInteractor = mitk::PlanarFigureInteractor::New();
us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" );
figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule );
figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule );
figureInteractor->SetDataNode( nonConstNode );
}
MITK_DEBUG << "will now add observers for planarfigure";
QmitkPlanarFigureData data;
data.m_Figure = figure;
// // add observer for event when figure has been placed
typedef itk::SimpleMemberCommand< QmitkFiberGenerationView > SimpleCommandType;
// SimpleCommandType::Pointer initializationCommand = SimpleCommandType::New();
// initializationCommand->SetCallbackFunction( this, &QmitkFiberGenerationView::PlanarFigureInitialized );
// data.m_EndPlacementObserverTag = figure->AddObserver( mitk::EndPlacementPlanarFigureEvent(), initializationCommand );
// add observer for event when figure is picked (selected)
typedef itk::MemberCommand< QmitkFiberGenerationView > MemberCommandType;
MemberCommandType::Pointer selectCommand = MemberCommandType::New();
selectCommand->SetCallbackFunction( this, &QmitkFiberGenerationView::PlanarFigureSelected );
data.m_SelectObserverTag = figure->AddObserver( mitk::SelectPlanarFigureEvent(), selectCommand );
// add observer for event when interaction with figure starts
SimpleCommandType::Pointer startInteractionCommand = SimpleCommandType::New();
startInteractionCommand->SetCallbackFunction( this, &QmitkFiberGenerationView::DisableCrosshairNavigation);
data.m_StartInteractionObserverTag = figure->AddObserver( mitk::StartInteractionPlanarFigureEvent(), startInteractionCommand );
// add observer for event when interaction with figure starts
SimpleCommandType::Pointer endInteractionCommand = SimpleCommandType::New();
endInteractionCommand->SetCallbackFunction( this, &QmitkFiberGenerationView::EnableCrosshairNavigation);
data.m_EndInteractionObserverTag = figure->AddObserver( mitk::EndInteractionPlanarFigureEvent(), endInteractionCommand );
m_DataNodeToPlanarFigureData[nonConstNode] = data;
}
}
void QmitkFiberGenerationView::PlanarFigureSelected( itk::Object* object, const itk::EventObject& )
{
mitk::TNodePredicateDataType<mitk::PlanarFigure>::Pointer isPf = mitk::TNodePredicateDataType<mitk::PlanarFigure>::New();
mitk::DataStorage::SetOfObjects::ConstPointer allPfs = this->GetDataStorage()->GetSubset( isPf );
for ( mitk::DataStorage::SetOfObjects::const_iterator it = allPfs->begin(); it!=allPfs->end(); ++it)
{
mitk::DataNode* node = *it;
if( node->GetData() == object )
{
node->SetSelected(true);
m_SelectedFiducial = node;
}
else
node->SetSelected(false);
}
UpdateGui();
this->RequestRenderWindowUpdate();
}
void QmitkFiberGenerationView::SetFocus()
{
m_Controls->m_CircleButton->setFocus();
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.h
index 15fd339..a25ebd3 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberGenerationView.h
@@ -1,148 +1,148 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <berryISelectionListener.h>
#include <berryIStructuredSelection.h>
#include <QmitkAbstractView.h>
#include "ui_QmitkFiberGenerationViewControls.h"
#include <itkVectorImage.h>
#include <itkVectorContainer.h>
#include <itkOrientationDistributionFunction.h>
#ifndef Q_MOC_RUN
#include <mitkFiberBundle.h>
#include <mitkPlanarEllipse.h>
#include <mitkDiffusionNoiseModel.h>
#include <mitkDiffusionSignalModel.h>
#include <mitkRicianNoiseModel.h>
#include <itkTractsToDWIImageFilter.h>
#include <mitkTensorModel.h>
#include <mitkBallModel.h>
#include <mitkStickModel.h>
#include <mitkAstroStickModel.h>
#include <mitkDotModel.h>
#include <mitkFiberfoxParameters.h>
#include <itkStatisticsImageFilter.h>
#include <mitkDiffusionPropertyHelper.h>
#endif
#include <QThread>
#include <QObject>
#include <QTimer>
#include <QTime>
class QmitkFiberGenerationView : public QmitkAbstractView
{
// 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;
QmitkFiberGenerationView();
virtual ~QmitkFiberGenerationView();
virtual void CreateQtPartControl(QWidget *parent) override;
void SetFocus() override;
typedef itk::Image<double, 3> ItkDoubleImgType;
typedef itk::Image<float, 3> ItkFloatImgType;
typedef itk::Image<unsigned char, 3> ItkUcharImgType;
protected slots:
void LoadParameters(); ///< load FiberGeneration parameters
void SaveParameters(); ///< save FiberGeneration parameters
void OnDrawROI(); ///< adds new ROI, handles interactors etc.
void OnAddBundle(); ///< adds new fiber bundle to datastorage
void OnFlipButton(); ///< negate one coordinate of the fiber waypoints in the selcted planar figure. needed in case of unresolvable twists
void GenerateFibers(); ///< generate fibers from the selected ROIs
void JoinBundles(); ///< merges selcted fiber bundles into one
void CopyBundles(); ///< add copy of the selected bundle to the datamanager
void ApplyTransform(); ///< rotate and shift selected bundles
void AlignOnGrid(); ///< shift selected fiducials to nearest voxel center
void RandomPhantom();
void ShowAdvancedOptions(int state);
/** update fibers if any parameter changes */
void OnFiberDensityChanged(int value);
void OnFiberSamplingChanged(double value);
void OnTensionChanged(double value);
void OnContinuityChanged(double value);
void OnBiasChanged(double value);
void OnVarianceChanged(double value);
void OnDistributionChanged(int value);
void OnConstantRadius(int value);
void UpdateFiducialPosition();
protected:
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
Ui::QmitkFiberGenerationViewControls* m_Controls;
void UpdateParametersFromGui();
void UpdateGui(); ///< enable/disbale buttons etc. according to current datamanager selection
void PlanarFigureSelected( itk::Object* object, const itk::EventObject& );
void EnableCrosshairNavigation(); ///< enable crosshair navigation if planar figure interaction ends
void DisableCrosshairNavigation(); ///< disable crosshair navigation if planar figure interaction starts
void NodeAdded( const mitk::DataNode* node ) override; ///< add observers
void NodeRemoved(const mitk::DataNode* node) override; ///< remove observers
void SaveParameters(QString filename);
static bool CompareLayer(mitk::DataNode::Pointer i,mitk::DataNode::Pointer j);
/** structure to keep track of planar figures and observers */
struct QmitkPlanarFigureData
{
QmitkPlanarFigureData()
: m_Figure(0)
, m_EndPlacementObserverTag(0)
, m_SelectObserverTag(0)
, m_StartInteractionObserverTag(0)
, m_EndInteractionObserverTag(0)
, m_Flipped(0)
{
}
mitk::PlanarFigure* m_Figure;
unsigned int m_EndPlacementObserverTag;
unsigned int m_SelectObserverTag;
unsigned int m_StartInteractionObserverTag;
unsigned int m_EndInteractionObserverTag;
unsigned int m_Flipped;
};
std::map<mitk::DataNode*, QmitkPlanarFigureData> m_DataNodeToPlanarFigureData; ///< map each planar figure uniquely to a QmitkPlanarFigureData
mitk::DataNode::Pointer m_SelectedFiducial; ///< selected planar ellipse
mitk::DataNode::Pointer m_SelectedImageNode;
std::vector< mitk::DataNode::Pointer > m_SelectedBundles;
std::vector< mitk::DataNode::Pointer > m_SelectedBundles2;
std::vector< mitk::DataNode::Pointer > m_SelectedFiducials;
std::vector< mitk::DataNode::Pointer > m_SelectedImages;
QString m_ParameterFile; ///< parameter file name
FiberfoxParameters m_Parameters;
};
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.cpp
index 8878199..b6fc585 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.cpp
@@ -1,2181 +1,2181 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// Qmitk
#include "QmitkFiberfoxView.h"
// MITK
#include <mitkImage.h>
#include <mitkImageToItk.h>
#include <mitkImageCast.h>
#include <mitkProperties.h>
#include <mitkPlanarFigureInteractor.h>
#include <mitkDataStorage.h>
#include <itkTractsToDWIImageFilter.h>
#include <mitkTensorImage.h>
#include <mitkILinkedRenderWindowPart.h>
#include <mitkImageToItk.h>
#include <mitkImageCast.h>
#include <mitkImageGenerator.h>
#include <mitkNodePredicateDataType.h>
#include <itkScalableAffineTransform.h>
#include <mitkLevelWindowProperty.h>
#include <mitkNodePredicateOr.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateProperty.h>
#include <mitkNodePredicateIsDWI.h>
#include <boost/property_tree/ptree.hpp>
#define RAPIDXML_NO_EXCEPTIONS
#include <boost/property_tree/xml_parser.hpp>
#include <boost/foreach.hpp>
#include <QFileDialog>
#include <QMessageBox>
#include "usModuleRegistry.h"
#include <mitkChiSquareNoiseModel.h>
#include <itksys/SystemTools.hxx>
#include <mitkIOUtil.h>
#include <QScrollBar>
#include <itkInvertIntensityImageFilter.h>
#include <QDialogButtonBox>
#include <itkAdcImageFilter.h>
#include <itkShiftScaleImageFilter.h>
#include <mitkITKImageImport.h>
#include "mitkNodePredicateDataType.h"
#include <mitkNodePredicateProperty.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateOr.h>
QmitkFiberfoxWorker::QmitkFiberfoxWorker(QmitkFiberfoxView* view)
: m_View(view)
{
}
void QmitkFiberfoxWorker::run()
{
try{
m_View->m_TractsToDwiFilter->Update();
}
catch( ... )
{
}
m_View->m_Thread.quit();
}
const std::string QmitkFiberfoxView::VIEW_ID = "org.mitk.views.fiberfoxview";
QmitkFiberfoxView::QmitkFiberfoxView()
: QmitkAbstractView()
, m_Controls( 0 )
, m_SelectedImageNode( nullptr )
, m_Worker(this)
, m_ThreadIsRunning(false)
{
m_Worker.moveToThread(&m_Thread);
connect(&m_Thread, SIGNAL(started()), this, SLOT(BeforeThread()));
connect(&m_Thread, SIGNAL(started()), &m_Worker, SLOT(run()));
connect(&m_Thread, SIGNAL(finished()), this, SLOT(AfterThread()));
// connect(&m_Thread, SIGNAL(terminated()), this, SLOT(AfterThread()));
m_SimulationTimer = new QTimer(this);
}
void QmitkFiberfoxView::KillThread()
{
MITK_INFO << "Aborting DWI simulation.";
m_TractsToDwiFilter->SetAbortGenerateData(true);
m_Controls->m_AbortSimulationButton->setEnabled(false);
m_Controls->m_AbortSimulationButton->setText("Aborting simulation ...");
}
void QmitkFiberfoxView::BeforeThread()
{
m_SimulationTime = QTime::currentTime();
m_SimulationTimer->start(100);
m_Controls->m_AbortSimulationButton->setVisible(true);
m_Controls->m_GenerateImageButton->setVisible(false);
m_Controls->m_SimulationStatusText->setVisible(true);
m_ThreadIsRunning = true;
}
void QmitkFiberfoxView::AfterThread()
{
UpdateSimulationStatus();
m_SimulationTimer->stop();
m_Controls->m_AbortSimulationButton->setVisible(false);
m_Controls->m_AbortSimulationButton->setEnabled(true);
m_Controls->m_AbortSimulationButton->setText("Abort simulation");
m_Controls->m_GenerateImageButton->setVisible(true);
m_ThreadIsRunning = false;
QString statusText;
FiberfoxParameters parameters;
mitk::Image::Pointer mitkImage = mitk::Image::New();
statusText = QString(m_TractsToDwiFilter->GetStatusText().c_str());
if (m_TractsToDwiFilter->GetAbortGenerateData())
{
MITK_INFO << "Simulation aborted.";
return;
}
parameters = m_TractsToDwiFilter->GetParameters();
mitkImage = mitk::GrabItkImageMemory( m_TractsToDwiFilter->GetOutput() );
if (parameters.m_SignalGen.GetNumWeightedVolumes() > 0)
{
mitk::DiffusionPropertyHelper::SetGradientContainer(mitkImage, parameters.m_SignalGen.GetItkGradientContainer());
mitk::DiffusionPropertyHelper::SetReferenceBValue(mitkImage, parameters.m_SignalGen.GetBvalue());
mitk::DiffusionPropertyHelper::InitializeImage( mitkImage );
}
parameters.m_Misc.m_ResultNode->SetData( mitkImage );
GetDataStorage()->Add(parameters.m_Misc.m_ResultNode, parameters.m_Misc.m_ParentNode);
if (m_Controls->m_VolumeFractionsBox->isChecked())
{
if (m_TractsToDwiFilter->GetTickImage().IsNotNull())
{
mitk::Image::Pointer mitkImage = mitk::Image::New();
itk::TractsToDWIImageFilter< short >::Float2DImageType::Pointer itkImage = m_TractsToDwiFilter->GetTickImage();
mitkImage = mitk::GrabItkImageMemory( itkImage.GetPointer() );
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( mitkImage );
node->SetName("Tick Image");
GetDataStorage()->Add(node, parameters.m_Misc.m_ResultNode);
}
if (m_TractsToDwiFilter->GetRfImage().IsNotNull())
{
mitk::Image::Pointer mitkImage = mitk::Image::New();
itk::TractsToDWIImageFilter< short >::Float2DImageType::Pointer itkImage = m_TractsToDwiFilter->GetRfImage();
mitkImage = mitk::GrabItkImageMemory( itkImage.GetPointer() );
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( mitkImage );
node->SetName("RF Image");
GetDataStorage()->Add(node, parameters.m_Misc.m_ResultNode);
}
if (m_TractsToDwiFilter->GetPhaseImage().IsNotNull())
{
mitk::Image::Pointer phaseImage = mitk::Image::New();
itk::TractsToDWIImageFilter< short >::DoubleDwiType::Pointer itkPhase = m_TractsToDwiFilter->GetPhaseImage();
phaseImage = mitk::GrabItkImageMemory( itkPhase.GetPointer() );
mitk::DataNode::Pointer phaseNode = mitk::DataNode::New();
phaseNode->SetData( phaseImage );
phaseNode->SetName("Phase Image");
GetDataStorage()->Add(phaseNode, parameters.m_Misc.m_ResultNode);
}
if (m_TractsToDwiFilter->GetKspaceImage().IsNotNull())
{
mitk::Image::Pointer image = mitk::Image::New();
itk::TractsToDWIImageFilter< short >::DoubleDwiType::Pointer itkImage = m_TractsToDwiFilter->GetKspaceImage();
image = mitk::GrabItkImageMemory( itkImage.GetPointer() );
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( image );
node->SetName("k-Space");
GetDataStorage()->Add(node, parameters.m_Misc.m_ResultNode);
}
{
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(m_TractsToDwiFilter->GetCoilPointset());
node->SetName("Coil Positions");
node->SetProperty("pointsize", mitk::FloatProperty::New(parameters.m_SignalGen.m_ImageSpacing[0]/4));
node->SetProperty("color", mitk::ColorProperty::New(0, 1, 0));
GetDataStorage()->Add(node, parameters.m_Misc.m_ResultNode);
}
int c = 1;
std::vector< itk::TractsToDWIImageFilter< short >::DoubleDwiType::Pointer > output_real = m_TractsToDwiFilter->GetOutputImagesReal();
for (auto real : output_real)
{
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk(real.GetPointer());
image->SetVolume(real->GetBufferPointer());
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( image );
node->SetName("Coil-"+QString::number(c).toStdString()+"-real");
GetDataStorage()->Add(node, parameters.m_Misc.m_ResultNode);
++c;
}
c = 1;
std::vector< itk::TractsToDWIImageFilter< short >::DoubleDwiType::Pointer > output_imag = m_TractsToDwiFilter->GetOutputImagesImag();
for (auto imag : output_imag)
{
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk(imag.GetPointer());
image->SetVolume(imag->GetBufferPointer());
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( image );
node->SetName("Coil-"+QString::number(c).toStdString()+"-imag");
GetDataStorage()->Add(node, parameters.m_Misc.m_ResultNode);
++c;
}
std::vector< itk::TractsToDWIImageFilter< short >::ItkDoubleImgType::Pointer > volumeFractions = m_TractsToDwiFilter->GetVolumeFractions();
for (unsigned int k=0; k<volumeFractions.size(); k++)
{
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk(volumeFractions.at(k).GetPointer());
image->SetVolume(volumeFractions.at(k)->GetBufferPointer());
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( image );
node->SetName("CompartmentVolume-"+QString::number(k).toStdString());
GetDataStorage()->Add(node, parameters.m_Misc.m_ResultNode);
}
}
m_TractsToDwiFilter = nullptr;
if (parameters.m_Misc.m_AfterSimulationMessage.size()>0)
QMessageBox::information( nullptr, "Warning", parameters.m_Misc.m_AfterSimulationMessage.c_str());
mitk::BaseData::Pointer basedata = parameters.m_Misc.m_ResultNode->GetData();
if (basedata.IsNotNull())
{
mitk::RenderingManager::GetInstance()->InitializeViews(
basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
if (!parameters.m_Misc.m_OutputPath.empty())
{
try{
QString outputFileName(parameters.m_Misc.m_OutputPath.c_str());
outputFileName += parameters.m_Misc.m_ResultNode->GetName().c_str();
outputFileName.replace(QString("."), QString("_"));
SaveParameters(outputFileName+".ffp");
outputFileName += ".dwi";
QString status("Saving output image to ");
status += outputFileName;
m_Controls->m_SimulationStatusText->append(status);
mitk::IOUtil::Save(mitkImage, outputFileName.toStdString());
m_Controls->m_SimulationStatusText->append("File saved successfully.");
}
catch (itk::ExceptionObject &e)
{
QString status("Exception during DWI writing: ");
status += e.GetDescription();
m_Controls->m_SimulationStatusText->append(status);
}
catch (...)
{
m_Controls->m_SimulationStatusText->append("Unknown exception during DWI writing!");
}
}
parameters.m_SignalGen.m_FrequencyMap = nullptr;
}
void QmitkFiberfoxView::UpdateSimulationStatus()
{
QString statusText = QString(m_TractsToDwiFilter->GetStatusText().c_str());
if (QString::compare(m_SimulationStatusText,statusText)!=0)
{
m_Controls->m_SimulationStatusText->clear();
m_Controls->m_SimulationStatusText->setText(statusText);
QScrollBar *vScrollBar = m_Controls->m_SimulationStatusText->verticalScrollBar();
vScrollBar->triggerAction(QScrollBar::SliderToMaximum);
}
}
// Destructor
QmitkFiberfoxView::~QmitkFiberfoxView()
{
delete m_SimulationTimer;
}
void QmitkFiberfoxView::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::QmitkFiberfoxViewControls;
m_Controls->setupUi( parent );
m_Controls->m_StickWidget1->setVisible(true);
m_Controls->m_StickWidget2->setVisible(false);
m_Controls->m_ZeppelinWidget1->setVisible(false);
m_Controls->m_ZeppelinWidget2->setVisible(false);
m_Controls->m_TensorWidget1->setVisible(false);
m_Controls->m_TensorWidget2->setVisible(false);
m_Controls->m_BallWidget1->setVisible(true);
m_Controls->m_BallWidget2->setVisible(false);
m_Controls->m_BallWidget2->SetT1(4658);
m_Controls->m_BallWidget2->SetT2(2200);
m_Controls->m_AstrosticksWidget1->setVisible(false);
m_Controls->m_AstrosticksWidget2->setVisible(false);
m_Controls->m_AstrosticksWidget2->SetT1(4658);
m_Controls->m_AstrosticksWidget2->SetT2(2200);
m_Controls->m_DotWidget1->setVisible(false);
m_Controls->m_DotWidget2->setVisible(false);
m_Controls->m_DotWidget2->SetT1(4658);
m_Controls->m_DotWidget2->SetT2(2200);
m_Controls->m_PrototypeWidget1->setVisible(false);
m_Controls->m_PrototypeWidget2->setVisible(false);
m_Controls->m_PrototypeWidget3->setVisible(false);
m_Controls->m_PrototypeWidget4->setVisible(false);
m_Controls->m_PrototypeWidget3->SetMinFa(0.0);
m_Controls->m_PrototypeWidget3->SetMaxFa(0.15);
m_Controls->m_PrototypeWidget4->SetMinFa(0.0);
m_Controls->m_PrototypeWidget4->SetMaxFa(0.15);
m_Controls->m_PrototypeWidget3->SetMinAdc(0.0);
m_Controls->m_PrototypeWidget3->SetMaxAdc(0.001);
m_Controls->m_PrototypeWidget4->SetMinAdc(0.003);
m_Controls->m_PrototypeWidget4->SetMaxAdc(0.004);
m_Controls->m_Comp2FractionFrame->setVisible(false);
m_Controls->m_Comp4FractionFrame->setVisible(false);
m_Controls->m_DiffusionPropsMessage->setVisible(false);
m_Controls->m_GeometryMessage->setVisible(false);
m_Controls->m_AdvancedSignalOptionsFrame->setVisible(false);
m_Controls->m_NoiseFrame->setVisible(false);
m_Controls->m_ZeroRinging->setVisible(false);
m_Controls->m_GhostFrame->setVisible(false);
m_Controls->m_DistortionsFrame->setVisible(false);
m_Controls->m_EddyFrame->setVisible(false);
m_Controls->m_SpikeFrame->setVisible(false);
m_Controls->m_AliasingFrame->setVisible(false);
m_Controls->m_MotionArtifactFrame->setVisible(false);
m_Controls->m_DriftFrame->setVisible(false);
m_ParameterFile = QDir::currentPath()+"/param.ffp";
m_Controls->m_AbortSimulationButton->setVisible(false);
m_Controls->m_SimulationStatusText->setVisible(false);
m_Controls->m_FrequencyMapBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_Comp1VolumeFraction->SetDataStorage(this->GetDataStorage());
m_Controls->m_Comp2VolumeFraction->SetDataStorage(this->GetDataStorage());
m_Controls->m_Comp3VolumeFraction->SetDataStorage(this->GetDataStorage());
m_Controls->m_Comp4VolumeFraction->SetDataStorage(this->GetDataStorage());
m_Controls->m_MaskComboBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_TemplateComboBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_FiberBundleComboBox->SetDataStorage(this->GetDataStorage());
mitk::TNodePredicateDataType<mitk::FiberBundle>::Pointer isFiberBundle = mitk::TNodePredicateDataType<mitk::FiberBundle>::New();
mitk::TNodePredicateDataType<mitk::Image>::Pointer isMitkImage = mitk::TNodePredicateDataType<mitk::Image>::New();
mitk::NodePredicateIsDWI::Pointer isDwi = mitk::NodePredicateIsDWI::New( );
mitk::NodePredicateDataType::Pointer isDti = mitk::NodePredicateDataType::New("TensorImage");
mitk::NodePredicateDataType::Pointer isOdf = mitk::NodePredicateDataType::New("Odfmage");
mitk::NodePredicateOr::Pointer isDiffusionImage = mitk::NodePredicateOr::New(isDwi, isDti);
isDiffusionImage = mitk::NodePredicateOr::New(isDiffusionImage, isOdf);
mitk::NodePredicateNot::Pointer noDiffusionImage = mitk::NodePredicateNot::New(isDiffusionImage);
mitk::NodePredicateAnd::Pointer isNonDiffMitkImage = mitk::NodePredicateAnd::New(isMitkImage, noDiffusionImage);
mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true));
mitk::NodePredicateAnd::Pointer isBinaryMitkImage = mitk::NodePredicateAnd::New( isNonDiffMitkImage, isBinaryPredicate );
m_Controls->m_FrequencyMapBox->SetPredicate(isNonDiffMitkImage);
m_Controls->m_Comp1VolumeFraction->SetPredicate(isNonDiffMitkImage);
m_Controls->m_Comp1VolumeFraction->SetZeroEntryText("--");
m_Controls->m_Comp2VolumeFraction->SetPredicate(isNonDiffMitkImage);
m_Controls->m_Comp2VolumeFraction->SetZeroEntryText("--");
m_Controls->m_Comp3VolumeFraction->SetPredicate(isNonDiffMitkImage);
m_Controls->m_Comp3VolumeFraction->SetZeroEntryText("--");
m_Controls->m_Comp4VolumeFraction->SetPredicate(isNonDiffMitkImage);
m_Controls->m_Comp4VolumeFraction->SetZeroEntryText("--");
m_Controls->m_MaskComboBox->SetPredicate(isBinaryMitkImage);
m_Controls->m_MaskComboBox->SetZeroEntryText("--");
m_Controls->m_TemplateComboBox->SetPredicate(isMitkImage);
m_Controls->m_TemplateComboBox->SetZeroEntryText("--");
m_Controls->m_FiberBundleComboBox->SetPredicate(isFiberBundle);
m_Controls->m_FiberBundleComboBox->SetZeroEntryText("--");
QFont font;
font.setFamily("Courier");
font.setStyleHint(QFont::Monospace);
font.setFixedPitch(true);
font.setPointSize(7);
m_Controls->m_SimulationStatusText->setFont(font);
connect( m_SimulationTimer, SIGNAL(timeout()), this, SLOT(UpdateSimulationStatus()) );
connect((QObject*) m_Controls->m_AbortSimulationButton, SIGNAL(clicked()), (QObject*) this, SLOT(KillThread()));
connect((QObject*) m_Controls->m_GenerateImageButton, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateImage()));
connect((QObject*) m_Controls->m_AddNoise, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddNoise(int)));
connect((QObject*) m_Controls->m_AddGhosts, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddGhosts(int)));
connect((QObject*) m_Controls->m_AddDistortions, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddDistortions(int)));
connect((QObject*) m_Controls->m_AddEddy, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddEddy(int)));
connect((QObject*) m_Controls->m_AddSpikes, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddSpikes(int)));
connect((QObject*) m_Controls->m_AddAliasing, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddAliasing(int)));
connect((QObject*) m_Controls->m_AddMotion, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddMotion(int)));
connect((QObject*) m_Controls->m_AddDrift, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddDrift(int)));
connect((QObject*) m_Controls->m_AddGibbsRinging, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddRinging(int)));
connect((QObject*) m_Controls->m_Compartment1Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp1ModelFrameVisibility(int)));
connect((QObject*) m_Controls->m_Compartment2Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp2ModelFrameVisibility(int)));
connect((QObject*) m_Controls->m_Compartment3Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp3ModelFrameVisibility(int)));
connect((QObject*) m_Controls->m_Compartment4Box, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(Comp4ModelFrameVisibility(int)));
connect((QObject*) m_Controls->m_AdvancedOptionsBox_2, SIGNAL( stateChanged(int)), (QObject*) this, SLOT(ShowAdvancedOptions(int)));
connect((QObject*) m_Controls->m_UseBvalsBvecsBox, SIGNAL( stateChanged(int)), (QObject*) this, SLOT(OnBvalsBvecsCheck(int)));
connect((QObject*) m_Controls->m_SaveParametersButton, SIGNAL(clicked()), (QObject*) this, SLOT(SaveParameters()));
connect((QObject*) m_Controls->m_LoadParametersButton, SIGNAL(clicked()), (QObject*) this, SLOT(LoadParameters()));
connect((QObject*) m_Controls->m_OutputPathButton, SIGNAL(clicked()), (QObject*) this, SLOT(SetOutputPath()));
connect((QObject*) m_Controls->m_LoadBvalsButton, SIGNAL(clicked()), (QObject*) this, SLOT(SetBvalsEdit()));
connect((QObject*) m_Controls->m_LoadBvecsButton, SIGNAL(clicked()), (QObject*) this, SLOT(SetBvecsEdit()));
connect((QObject*) m_Controls->m_MaskComboBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnMaskSelected(int)));
connect((QObject*) m_Controls->m_TemplateComboBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnTemplateSelected(int)));
connect((QObject*) m_Controls->m_FiberBundleComboBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnFibSelected(int)));
connect((QObject*) m_Controls->m_LineReadoutTimeBox, SIGNAL( valueChanged(double)), (QObject*) this, SLOT(OnTlineChanged()));
connect((QObject*) m_Controls->m_SizeX, SIGNAL( valueChanged(int)), (QObject*) this, SLOT(OnTlineChanged()));
}
OnTlineChanged();
UpdateGui();
}
void QmitkFiberfoxView::OnTlineChanged()
{
double num_pix_line = 0;
if (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull()) // use geometry of selected image
{
mitk::Image::Pointer img = dynamic_cast<mitk::Image*>(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData());
num_pix_line = img->GetDimension(0);
}
else if (m_Controls->m_MaskComboBox->GetSelectedNode().IsNotNull()) // use geometry of mask image
{
mitk::Image::Pointer img = dynamic_cast<mitk::Image*>(m_Controls->m_MaskComboBox->GetSelectedNode()->GetData());
num_pix_line = img->GetDimension(0);
}
else
{
num_pix_line = m_Controls->m_SizeX->value();
}
double value = static_cast<double>(m_Controls->m_LineReadoutTimeBox->value())/1000.0; // line readout time in seconds
double dweel_pp = value/num_pix_line; // pixel readout time in seconds
double bw = 1/dweel_pp;
double bw_pp = bw/num_pix_line;
std::string tt = "Bandwidth:\n" + boost::lexical_cast<std::string>(itk::Math::Round<int, double>(bw)) + "Hz\n" + boost::lexical_cast<std::string>(itk::Math::Round<int, double>(bw_pp)) + "Hz/Px";
m_Controls->m_LineReadoutTimeBox->setToolTip(tt.c_str());
}
void QmitkFiberfoxView::OnMaskSelected(int )
{
UpdateGui();
}
void QmitkFiberfoxView::OnTemplateSelected(int )
{
UpdateGui();
}
void QmitkFiberfoxView::OnFibSelected(int )
{
UpdateGui();
}
void QmitkFiberfoxView::OnBvalsBvecsCheck(int )
{
UpdateGui();
}
void QmitkFiberfoxView::UpdateParametersFromGui()
{
m_Parameters.ClearSignalParameters();
m_Parameters.m_Misc.m_CheckAdvancedSignalOptionsBox = m_Controls->m_AdvancedOptionsBox_2->isChecked();
m_Parameters.m_Misc.m_OutputAdditionalImages = m_Controls->m_VolumeFractionsBox->isChecked();
std::string outputPath = m_Controls->m_SavePathEdit->text().toStdString();
if (outputPath.compare("-")!=0)
{
m_Parameters.m_Misc.m_OutputPath = outputPath;
m_Parameters.m_Misc.m_OutputPath += "/";
}
else {
m_Parameters.m_Misc.m_OutputPath = "";
}
if (m_Controls->m_MaskComboBox->GetSelectedNode().IsNotNull())
{
mitk::Image::Pointer mitkMaskImage = dynamic_cast<mitk::Image*>(m_Controls->m_MaskComboBox->GetSelectedNode()->GetData());
mitk::CastToItkImage<ItkUcharImgType>(mitkMaskImage, m_Parameters.m_SignalGen.m_MaskImage);
itk::ImageDuplicator<ItkUcharImgType>::Pointer duplicator = itk::ImageDuplicator<ItkUcharImgType>::New();
duplicator->SetInputImage(m_Parameters.m_SignalGen.m_MaskImage);
duplicator->Update();
m_Parameters.m_SignalGen.m_MaskImage = duplicator->GetOutput();
}
if (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull() && mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( m_Controls->m_TemplateComboBox->GetSelectedNode())) // use parameters of selected DWI
{
mitk::Image::Pointer dwi = dynamic_cast<mitk::Image*>(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData());
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(dwi, itkVectorImagePointer);
m_Parameters.m_SignalGen.m_ImageRegion = itkVectorImagePointer->GetLargestPossibleRegion();
m_Parameters.m_SignalGen.m_ImageSpacing = itkVectorImagePointer->GetSpacing();
m_Parameters.m_SignalGen.m_ImageOrigin = itkVectorImagePointer->GetOrigin();
m_Parameters.m_SignalGen.m_ImageDirection = itkVectorImagePointer->GetDirection();
m_Parameters.SetBvalue(mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi));
m_Parameters.SetGradienDirections(mitk::DiffusionPropertyHelper::GetOriginalGradientContainer(dwi));
}
else if (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull()) // use geometry of selected image
{
mitk::Image::Pointer img = dynamic_cast<mitk::Image*>(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData());
itk::Image< float, 3 >::Pointer itkImg = itk::Image< float, 3 >::New();
CastToItkImage< itk::Image< float, 3 > >(img, itkImg);
m_Parameters.m_SignalGen.m_ImageRegion = itkImg->GetLargestPossibleRegion();
m_Parameters.m_SignalGen.m_ImageSpacing = itkImg->GetSpacing();
m_Parameters.m_SignalGen.m_ImageOrigin = itkImg->GetOrigin();
m_Parameters.m_SignalGen.m_ImageDirection = itkImg->GetDirection();
if (m_Controls->m_UseBvalsBvecsBox->isChecked())
{
double bval;
m_Parameters.SetGradienDirections( mitk::gradients::ReadBvalsBvecs(m_Controls->m_LoadBvalsEdit->text().toStdString(), m_Controls->m_LoadBvecsEdit->text().toStdString(), bval) );
m_Parameters.SetBvalue(bval);
}
else
{
m_Parameters.SetNumWeightedVolumes(m_Controls->m_NumGradientsBox->value());
m_Parameters.SetBvalue(m_Controls->m_BvalueBox->value());
m_Parameters.GenerateGradientHalfShell();
}
}
else if (m_Parameters.m_SignalGen.m_MaskImage.IsNotNull()) // use geometry of mask image
{
ItkUcharImgType::Pointer itkImg = m_Parameters.m_SignalGen.m_MaskImage;
m_Parameters.m_SignalGen.m_ImageRegion = itkImg->GetLargestPossibleRegion();
m_Parameters.m_SignalGen.m_ImageSpacing = itkImg->GetSpacing();
m_Parameters.m_SignalGen.m_ImageOrigin = itkImg->GetOrigin();
m_Parameters.m_SignalGen.m_ImageDirection = itkImg->GetDirection();
if (m_Controls->m_UseBvalsBvecsBox->isChecked())
{
double bval;
m_Parameters.SetGradienDirections( mitk::gradients::ReadBvalsBvecs(m_Controls->m_LoadBvalsEdit->text().toStdString(), m_Controls->m_LoadBvecsEdit->text().toStdString(), bval) );
m_Parameters.SetBvalue(bval);
}
else
{
m_Parameters.SetNumWeightedVolumes(m_Controls->m_NumGradientsBox->value());
m_Parameters.SetBvalue(m_Controls->m_BvalueBox->value());
m_Parameters.GenerateGradientHalfShell();
}
}
else // use GUI parameters
{
m_Parameters.m_SignalGen.m_ImageRegion.SetSize(0, m_Controls->m_SizeX->value());
m_Parameters.m_SignalGen.m_ImageRegion.SetSize(1, m_Controls->m_SizeY->value());
m_Parameters.m_SignalGen.m_ImageRegion.SetSize(2, m_Controls->m_SizeZ->value());
m_Parameters.m_SignalGen.m_ImageSpacing[0] = m_Controls->m_SpacingX->value();
m_Parameters.m_SignalGen.m_ImageSpacing[1] = m_Controls->m_SpacingY->value();
m_Parameters.m_SignalGen.m_ImageSpacing[2] = m_Controls->m_SpacingZ->value();
m_Parameters.m_SignalGen.m_ImageOrigin[0] = m_Parameters.m_SignalGen.m_ImageSpacing[0]/2;
m_Parameters.m_SignalGen.m_ImageOrigin[1] = m_Parameters.m_SignalGen.m_ImageSpacing[1]/2;
m_Parameters.m_SignalGen.m_ImageOrigin[2] = m_Parameters.m_SignalGen.m_ImageSpacing[2]/2;
m_Parameters.m_SignalGen.m_ImageDirection.SetIdentity();
if (m_Controls->m_UseBvalsBvecsBox->isChecked())
{
double bval;
m_Parameters.SetGradienDirections( mitk::gradients::ReadBvalsBvecs(m_Controls->m_LoadBvalsEdit->text().toStdString(), m_Controls->m_LoadBvecsEdit->text().toStdString(), bval) );
m_Parameters.SetBvalue(bval);
}
else
{
m_Parameters.SetNumWeightedVolumes(m_Controls->m_NumGradientsBox->value());
m_Parameters.SetBvalue(m_Controls->m_BvalueBox->value());
m_Parameters.GenerateGradientHalfShell();
}
}
// signal relaxation
m_Parameters.m_SignalGen.m_DoSimulateRelaxation = false;
if (m_Controls->m_RelaxationBox->isChecked())
{
m_Parameters.m_SignalGen.m_DoSimulateRelaxation = true;
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Relaxation", BoolProperty::New(true));
m_Parameters.m_Misc.m_ArtifactModelString += "_RELAX";
}
m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition = m_Parameters.m_SignalGen.m_DoSimulateRelaxation;
// N/2 ghosts
m_Parameters.m_Misc.m_DoAddGhosts = m_Controls->m_AddGhosts->isChecked();
m_Parameters.m_SignalGen.m_KspaceLineOffset = m_Controls->m_kOffsetBox->value();
if (m_Controls->m_AddGhosts->isChecked())
{
m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition = true;
m_Parameters.m_Misc.m_ArtifactModelString += "_GHOST";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Ghost", DoubleProperty::New(m_Parameters.m_SignalGen.m_KspaceLineOffset));
}
// Aliasing
m_Parameters.m_Misc.m_DoAddAliasing = m_Controls->m_AddAliasing->isChecked();
m_Parameters.m_SignalGen.m_CroppingFactor = (100-m_Controls->m_WrapBox->value())/100;
if (m_Controls->m_AddAliasing->isChecked())
{
m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition = true;
m_Parameters.m_Misc.m_ArtifactModelString += "_ALIASING";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Aliasing", DoubleProperty::New(m_Controls->m_WrapBox->value()));
}
// Spikes
m_Parameters.m_Misc.m_DoAddSpikes = m_Controls->m_AddSpikes->isChecked();
m_Parameters.m_SignalGen.m_Spikes = m_Controls->m_SpikeNumBox->value();
m_Parameters.m_SignalGen.m_SpikeAmplitude = m_Controls->m_SpikeScaleBox->value();
if (m_Controls->m_AddSpikes->isChecked())
{
m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition = true;
m_Parameters.m_Misc.m_ArtifactModelString += "_SPIKES";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Spikes.Number", IntProperty::New(m_Parameters.m_SignalGen.m_Spikes));
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Spikes.Amplitude", DoubleProperty::New(m_Parameters.m_SignalGen.m_SpikeAmplitude));
}
// Drift
m_Parameters.m_SignalGen.m_DoAddDrift = m_Controls->m_AddDrift->isChecked();
m_Parameters.m_SignalGen.m_Drift = static_cast<float>(m_Controls->m_DriftFactor->value())/100;
if (m_Controls->m_AddDrift->isChecked())
{
m_Parameters.m_Misc.m_ArtifactModelString += "_DRIFT";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Drift", FloatProperty::New(m_Parameters.m_SignalGen.m_Drift));
}
// gibbs ringing
m_Parameters.m_SignalGen.m_DoAddGibbsRinging = m_Controls->m_AddGibbsRinging->isChecked();
m_Parameters.m_SignalGen.m_ZeroRinging = m_Controls->m_ZeroRinging->value();
if (m_Controls->m_AddGibbsRinging->isChecked())
{
m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition = true;
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Ringing", BoolProperty::New(true));
m_Parameters.m_Misc.m_ArtifactModelString += "_RINGING";
}
// add distortions
m_Parameters.m_Misc.m_DoAddDistortions = m_Controls->m_AddDistortions->isChecked();
if (m_Controls->m_AddDistortions->isChecked() && m_Controls->m_FrequencyMapBox->GetSelectedNode().IsNotNull())
{
mitk::DataNode::Pointer fMapNode = m_Controls->m_FrequencyMapBox->GetSelectedNode();
mitk::Image* img = dynamic_cast<mitk::Image*>(fMapNode->GetData());
ItkFloatImgType::Pointer itkImg = ItkFloatImgType::New();
CastToItkImage< ItkFloatImgType >(img, itkImg);
if (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNull()) // use geometry of frequency map
{
m_Parameters.m_SignalGen.m_ImageRegion = itkImg->GetLargestPossibleRegion();
m_Parameters.m_SignalGen.m_ImageSpacing = itkImg->GetSpacing();
m_Parameters.m_SignalGen.m_ImageOrigin = itkImg->GetOrigin();
m_Parameters.m_SignalGen.m_ImageDirection = itkImg->GetDirection();
}
m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition = true;
itk::ImageDuplicator<ItkFloatImgType>::Pointer duplicator = itk::ImageDuplicator<ItkFloatImgType>::New();
duplicator->SetInputImage(itkImg);
duplicator->Update();
m_Parameters.m_SignalGen.m_FrequencyMap = duplicator->GetOutput();
m_Parameters.m_Misc.m_ArtifactModelString += "_DISTORTED";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Distortions", BoolProperty::New(true));
}
m_Parameters.m_SignalGen.m_EddyStrength = m_Controls->m_EddyGradientStrength->value();
m_Parameters.m_Misc.m_DoAddEddyCurrents = m_Controls->m_AddEddy->isChecked();
if (m_Controls->m_AddEddy->isChecked())
{
m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition = true;
m_Parameters.m_Misc.m_ArtifactModelString += "_EDDY";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Eddy-strength", DoubleProperty::New(m_Parameters.m_SignalGen.m_EddyStrength));
}
// Motion
m_Parameters.m_SignalGen.m_DoAddMotion = false;
m_Parameters.m_SignalGen.m_DoRandomizeMotion = m_Controls->m_RandomMotion->isChecked();
m_Parameters.m_SignalGen.m_Translation[0] = m_Controls->m_MaxTranslationBoxX->value();
m_Parameters.m_SignalGen.m_Translation[1] = m_Controls->m_MaxTranslationBoxY->value();
m_Parameters.m_SignalGen.m_Translation[2] = m_Controls->m_MaxTranslationBoxZ->value();
m_Parameters.m_SignalGen.m_Rotation[0] = m_Controls->m_MaxRotationBoxX->value();
m_Parameters.m_SignalGen.m_Rotation[1] = m_Controls->m_MaxRotationBoxY->value();
m_Parameters.m_SignalGen.m_Rotation[2] = m_Controls->m_MaxRotationBoxZ->value();
m_Parameters.m_SignalGen.m_MotionVolumes.clear();
m_Parameters.m_Misc.m_MotionVolumesBox = m_Controls->m_MotionVolumesBox->text().toStdString();
if ( m_Controls->m_AddMotion->isChecked())
{
m_Parameters.m_SignalGen.m_DoAddMotion = true;
m_Parameters.m_Misc.m_ArtifactModelString += "_MOTION";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Random", BoolProperty::New(m_Parameters.m_SignalGen.m_DoRandomizeMotion));
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-x", DoubleProperty::New(m_Parameters.m_SignalGen.m_Translation[0]));
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-y", DoubleProperty::New(m_Parameters.m_SignalGen.m_Translation[1]));
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Translation-z", DoubleProperty::New(m_Parameters.m_SignalGen.m_Translation[2]));
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-x", DoubleProperty::New(m_Parameters.m_SignalGen.m_Rotation[0]));
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-y", DoubleProperty::New(m_Parameters.m_SignalGen.m_Rotation[1]));
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Motion.Rotation-z", DoubleProperty::New(m_Parameters.m_SignalGen.m_Rotation[2]));
if ( m_Parameters.m_Misc.m_MotionVolumesBox == "random" )
{
for ( size_t i=0; i < m_Parameters.m_SignalGen.GetNumVolumes(); ++i )
{
m_Parameters.m_SignalGen.m_MotionVolumes.push_back( bool( rand()%2 ) );
}
MITK_DEBUG << "QmitkFiberfoxView.cpp: Case m_Misc.m_MotionVolumesBox == \"random\".";
}
else if ( ! m_Parameters.m_Misc.m_MotionVolumesBox.empty() )
{
std::stringstream stream( m_Parameters.m_Misc.m_MotionVolumesBox );
std::vector<int> numbers;
int number = std::numeric_limits<int>::max();
while( stream >> number )
{
if( number < std::numeric_limits<int>::max() )
{
numbers.push_back( number );
}
}
// If a list of negative numbers is given:
if( *(std::min_element( numbers.begin(), numbers.end() )) < 0
&& *(std::max_element( numbers.begin(), numbers.end() )) <= 0 ) // cave: -0 == +0
{
for ( size_t i=0; i < m_Parameters.m_SignalGen.GetNumVolumes(); ++i )
{
m_Parameters.m_SignalGen.m_MotionVolumes.push_back( true );
}
// set all true except those given.
for( auto iter = std::begin( numbers ); iter != std::end( numbers ); ++iter )
{
if ( -(*iter) < (int)m_Parameters.m_SignalGen.GetNumVolumes() && -(*iter) >= 0 )
{
m_Parameters.m_SignalGen.m_MotionVolumes.at( -(*iter) ) = false;
}
}
MITK_DEBUG << "QmitkFiberfoxView.cpp: Case list of negative numbers.";
}
// If a list of positive numbers is given:
else if( *(std::min_element( numbers.begin(), numbers.end() )) >= 0
&& *(std::max_element( numbers.begin(), numbers.end() )) >= 0 )
{
for ( size_t i=0; i < m_Parameters.m_SignalGen.GetNumVolumes(); ++i )
{
m_Parameters.m_SignalGen.m_MotionVolumes.push_back( false );
}
// set all false except those given.
for( auto iter = std::begin( numbers ); iter != std::end( numbers ); ++iter )
{
if ( *iter < (int)m_Parameters.m_SignalGen.GetNumVolumes() && *iter >= 0 )
{
m_Parameters.m_SignalGen.m_MotionVolumes.at( *iter ) = true;
}
}
MITK_DEBUG << "QmitkFiberfoxView.cpp: Case list of positive numbers.";
}
else
{
MITK_ERROR << "QmitkFiberfoxView.cpp: Inconsistent list of numbers in m_MotionVolumesBox.";
}
}
else
{
m_Parameters.m_Misc.m_MotionVolumesBox = ""; // set empty.
m_Controls->m_MotionVolumesBox->setText("");
for (unsigned int i=0; i<m_Parameters.m_SignalGen.GetNumVolumes(); i++)
{
m_Parameters.m_SignalGen.m_MotionVolumes.push_back(i);
}
}
}
// other imaging parameters
m_Parameters.m_SignalGen.m_AcquisitionType = (SignalGenerationParameters::AcquisitionType)m_Controls->m_AcquisitionTypeBox->currentIndex();
m_Parameters.m_SignalGen.m_CoilSensitivityProfile = (SignalGenerationParameters::CoilSensitivityProfile)m_Controls->m_CoilSensBox->currentIndex();
m_Parameters.m_SignalGen.m_NumberOfCoils = m_Controls->m_NumCoilsBox->value();
m_Parameters.m_SignalGen.m_PartialFourier = m_Controls->m_PartialFourier->value();
m_Parameters.m_SignalGen.m_ReversePhase = m_Controls->m_ReversePhaseBox->isChecked();
m_Parameters.m_SignalGen.m_tLine = m_Controls->m_LineReadoutTimeBox->value();
m_Parameters.m_SignalGen.m_tInhom = m_Controls->m_T2starBox->value();
m_Parameters.m_SignalGen.m_EchoTrainLength = m_Controls->m_EtlBox->value();
m_Parameters.m_SignalGen.m_tEcho = m_Controls->m_TEbox->value();
m_Parameters.m_SignalGen.m_tRep = m_Controls->m_TRbox->value();
m_Parameters.m_SignalGen.m_tInv = m_Controls->m_TIbox->value();
m_Parameters.m_SignalGen.m_DoDisablePartialVolume = m_Controls->m_EnforcePureFiberVoxelsBox->isChecked();
m_Parameters.m_SignalGen.m_AxonRadius = m_Controls->m_FiberRadius->value();
m_Parameters.m_SignalGen.m_SignalScale = m_Controls->m_SignalScaleBox->value();
// double voxelVolume = m_Parameters.m_SignalGen.m_ImageSpacing[0]
// * m_Parameters.m_SignalGen.m_ImageSpacing[1]
// * m_Parameters.m_SignalGen.m_ImageSpacing[2];
// if ( m_Parameters.m_SignalGen.m_SignalScale*voxelVolume > itk::NumericTraits<short>::max()*0.75 )
// {
// m_Parameters.m_SignalGen.m_SignalScale = itk::NumericTraits<short>::max()*0.75/voxelVolume;
// m_Controls->m_SignalScaleBox->setValue(m_Parameters.m_SignalGen.m_SignalScale);
// QMessageBox::information( nullptr, "Warning",
// "Maximum signal exceeding data type limits. Automatically adjusted to "
// + QString::number(m_Parameters.m_SignalGen.m_SignalScale)
// + " to obtain a maximum signal of 75% of the data type maximum."
// " Relaxation and other effects that affect the signal intensities are not accounted for.");
// }
// Noise
m_Parameters.m_Misc.m_DoAddNoise = m_Controls->m_AddNoise->isChecked();
m_Parameters.m_SignalGen.m_NoiseVariance = m_Controls->m_NoiseLevel->value();
if (m_Controls->m_AddNoise->isChecked())
{
switch (m_Controls->m_NoiseDistributionBox->currentIndex())
{
case 0:
{
if (m_Parameters.m_SignalGen.m_NoiseVariance>0)
{
m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition = true;
m_Parameters.m_Misc.m_ArtifactModelString += "_COMPLEX-GAUSSIAN-";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Complex Gaussian"));
}
break;
}
case 1:
{
if (m_Parameters.m_SignalGen.m_NoiseVariance>0)
{
m_Parameters.m_NoiseModel = std::make_shared< mitk::RicianNoiseModel<ScalarType> >();
m_Parameters.m_Misc.m_ArtifactModelString += "_RICIAN-";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Rician"));
m_Parameters.m_NoiseModel->SetNoiseVariance(m_Parameters.m_SignalGen.m_NoiseVariance);
}
break;
}
case 2:
{
if (m_Parameters.m_SignalGen.m_NoiseVariance>0)
{
m_Parameters.m_NoiseModel = std::make_shared< mitk::ChiSquareNoiseModel<ScalarType> >();
m_Parameters.m_Misc.m_ArtifactModelString += "_CHISQUARED-";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Chi-squared"));
m_Parameters.m_NoiseModel->SetNoiseVariance(m_Parameters.m_SignalGen.m_NoiseVariance);
}
break;
}
default:
{
if (m_Parameters.m_SignalGen.m_NoiseVariance>0)
{
m_Parameters.m_SignalGen.m_SimulateKspaceAcquisition = true;
m_Parameters.m_Misc.m_ArtifactModelString += "_COMPLEX-GAUSSIAN-";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Distribution", StringProperty::New("Complex Gaussian"));
}
break;
}
}
if (m_Parameters.m_SignalGen.m_NoiseVariance>0)
{
m_Parameters.m_Misc.m_ArtifactModelString += QString::number(m_Parameters.m_SignalGen.m_NoiseVariance).toStdString();
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Noise-Variance", DoubleProperty::New(m_Parameters.m_SignalGen.m_NoiseVariance));
}
}
// signal models
{
// compartment 1
switch (m_Controls->m_Compartment1Box->currentIndex())
{
case 0:
{
mitk::StickModel<ScalarType>* model = new mitk::StickModel<ScalarType>();
model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections());
model->SetBvalue(m_Parameters.m_SignalGen.GetBvalue());
model->SetDiffusivity(m_Controls->m_StickWidget1->GetD());
model->SetT2(m_Controls->m_StickWidget1->GetT2());
model->SetT1(m_Controls->m_StickWidget1->GetT1());
model->m_CompartmentId = 1;
m_Parameters.m_FiberModelList.push_back(model);
m_Parameters.m_Misc.m_SignalModelString += "Stick";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Stick") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D", DoubleProperty::New(m_Controls->m_StickWidget1->GetD()) );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(model->GetT2()) );
break;
}
case 1:
{
mitk::TensorModel<ScalarType>* model = new mitk::TensorModel<ScalarType>();
model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections());
model->SetBvalue(m_Parameters.m_SignalGen.GetBvalue());
model->SetDiffusivity1(m_Controls->m_ZeppelinWidget1->GetD1());
model->SetDiffusivity2(m_Controls->m_ZeppelinWidget1->GetD2());
model->SetDiffusivity3(m_Controls->m_ZeppelinWidget1->GetD2());
model->SetT2(m_Controls->m_ZeppelinWidget1->GetT2());
model->SetT1(m_Controls->m_ZeppelinWidget1->GetT1());
model->m_CompartmentId = 1;
m_Parameters.m_FiberModelList.push_back(model);
m_Parameters.m_Misc.m_SignalModelString += "Zeppelin";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Zeppelin") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD1()) );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget1->GetD2()) );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(model->GetT2()) );
break;
}
case 2:
{
mitk::TensorModel<ScalarType>* model = new mitk::TensorModel<ScalarType>();
model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections());
model->SetBvalue(m_Parameters.m_SignalGen.GetBvalue());
model->SetDiffusivity1(m_Controls->m_TensorWidget1->GetD1());
model->SetDiffusivity2(m_Controls->m_TensorWidget1->GetD2());
model->SetDiffusivity3(m_Controls->m_TensorWidget1->GetD3());
model->SetT2(m_Controls->m_TensorWidget1->GetT2());
model->SetT1(m_Controls->m_TensorWidget1->GetT1());
model->m_CompartmentId = 1;
m_Parameters.m_FiberModelList.push_back(model);
m_Parameters.m_Misc.m_SignalModelString += "Tensor";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Tensor") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D1", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD1()) );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D2", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD2()) );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.D3", DoubleProperty::New(m_Controls->m_TensorWidget1->GetD3()) );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.T2", DoubleProperty::New(model->GetT2()) );
break;
}
case 3:
{
mitk::RawShModel<ScalarType>* model = new mitk::RawShModel<ScalarType>();
m_Parameters.m_SignalGen.m_DoSimulateRelaxation = false;
model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections());
model->SetMaxNumKernels(m_Controls->m_PrototypeWidget1->GetNumberOfSamples());
model->SetFaRange(m_Controls->m_PrototypeWidget1->GetMinFa(), m_Controls->m_PrototypeWidget1->GetMaxFa());
model->SetAdcRange(m_Controls->m_PrototypeWidget1->GetMinAdc(), m_Controls->m_PrototypeWidget1->GetMaxAdc());
model->m_CompartmentId = 1;
m_Parameters.m_FiberModelList.push_back(model);
m_Parameters.m_Misc.m_SignalModelString += "Prototype";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Description", StringProperty::New("Intra-axonal compartment") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment1.Model", StringProperty::New("Prototype") );
break;
}
}
if (m_Controls->m_Comp1VolumeFraction->GetSelectedNode().IsNotNull())
{
mitk::DataNode::Pointer volumeNode = m_Controls->m_Comp1VolumeFraction->GetSelectedNode();
ItkDoubleImgType::Pointer comp1VolumeImage = ItkDoubleImgType::New();
mitk::Image* img = dynamic_cast<mitk::Image*>(volumeNode->GetData());
CastToItkImage< ItkDoubleImgType >(img, comp1VolumeImage);
m_Parameters.m_FiberModelList.back()->SetVolumeFractionImage(comp1VolumeImage);
}
// compartment 2
switch (m_Controls->m_Compartment2Box->currentIndex())
{
case 0:
break;
case 1:
{
mitk::StickModel<ScalarType>* model = new mitk::StickModel<ScalarType>();
model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections());
model->SetBvalue(m_Parameters.m_SignalGen.GetBvalue());
model->SetDiffusivity(m_Controls->m_StickWidget2->GetD());
model->SetT2(m_Controls->m_StickWidget2->GetT2());
model->SetT1(m_Controls->m_StickWidget2->GetT1());
model->m_CompartmentId = 2;
m_Parameters.m_FiberModelList.push_back(model);
m_Parameters.m_Misc.m_SignalModelString += "Stick";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Stick") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D", DoubleProperty::New(m_Controls->m_StickWidget2->GetD()) );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(model->GetT2()) );
break;
}
case 2:
{
mitk::TensorModel<ScalarType>* model = new mitk::TensorModel<ScalarType>();
model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections());
model->SetBvalue(m_Parameters.m_SignalGen.GetBvalue());
model->SetDiffusivity1(m_Controls->m_ZeppelinWidget2->GetD1());
model->SetDiffusivity2(m_Controls->m_ZeppelinWidget2->GetD2());
model->SetDiffusivity3(m_Controls->m_ZeppelinWidget2->GetD2());
model->SetT2(m_Controls->m_ZeppelinWidget2->GetT2());
model->SetT1(m_Controls->m_ZeppelinWidget2->GetT1());
model->m_CompartmentId = 2;
m_Parameters.m_FiberModelList.push_back(model);
m_Parameters.m_Misc.m_SignalModelString += "Zeppelin";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Zeppelin") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD1()) );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_ZeppelinWidget2->GetD2()) );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(model->GetT2()) );
break;
}
case 3:
{
mitk::TensorModel<ScalarType>* model = new mitk::TensorModel<ScalarType>();
model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections());
model->SetBvalue(m_Parameters.m_SignalGen.GetBvalue());
model->SetDiffusivity1(m_Controls->m_TensorWidget2->GetD1());
model->SetDiffusivity2(m_Controls->m_TensorWidget2->GetD2());
model->SetDiffusivity3(m_Controls->m_TensorWidget2->GetD3());
model->SetT2(m_Controls->m_TensorWidget2->GetT2());
model->SetT1(m_Controls->m_TensorWidget2->GetT1());
model->m_CompartmentId = 2;
m_Parameters.m_FiberModelList.push_back(model);
m_Parameters.m_Misc.m_SignalModelString += "Tensor";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Description", StringProperty::New("Inter-axonal compartment") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.Model", StringProperty::New("Tensor") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D1", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD1()) );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D2", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD2()) );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.D3", DoubleProperty::New(m_Controls->m_TensorWidget2->GetD3()) );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment2.T2", DoubleProperty::New(model->GetT2()) );
break;
}
}
if (m_Controls->m_Comp2VolumeFraction->GetSelectedNode().IsNotNull() && m_Parameters.m_FiberModelList.size()==2)
{
mitk::DataNode::Pointer volumeNode = m_Controls->m_Comp2VolumeFraction->GetSelectedNode();
ItkDoubleImgType::Pointer comp1VolumeImage = ItkDoubleImgType::New();
mitk::Image* img = dynamic_cast<mitk::Image*>(volumeNode->GetData());
CastToItkImage< ItkDoubleImgType >(img, comp1VolumeImage);
m_Parameters.m_FiberModelList.back()->SetVolumeFractionImage(comp1VolumeImage);
}
// compartment 3
switch (m_Controls->m_Compartment3Box->currentIndex())
{
case 0:
{
mitk::BallModel<ScalarType>* model = new mitk::BallModel<ScalarType>();
model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections());
model->SetBvalue(m_Parameters.m_SignalGen.GetBvalue());
model->SetDiffusivity(m_Controls->m_BallWidget1->GetD());
model->SetT2(m_Controls->m_BallWidget1->GetT2());
model->SetT1(m_Controls->m_BallWidget1->GetT1());
model->m_CompartmentId = 3;
m_Parameters.m_NonFiberModelList.push_back(model);
m_Parameters.m_Misc.m_SignalModelString += "Ball";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Ball") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_BallWidget1->GetD()) );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(model->GetT2()) );
break;
}
case 1:
{
mitk::AstroStickModel<ScalarType>* model = new mitk::AstroStickModel<ScalarType>();
model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections());
model->SetBvalue(m_Parameters.m_SignalGen.GetBvalue());
model->SetDiffusivity(m_Controls->m_AstrosticksWidget1->GetD());
model->SetT2(m_Controls->m_AstrosticksWidget1->GetT2());
model->SetT1(m_Controls->m_AstrosticksWidget1->GetT1());
model->SetRandomizeSticks(m_Controls->m_AstrosticksWidget1->GetRandomizeSticks());
model->m_CompartmentId = 3;
m_Parameters.m_NonFiberModelList.push_back(model);
m_Parameters.m_Misc.m_SignalModelString += "Astrosticks";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Astrosticks") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget1->GetD()) );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(model->GetT2()) );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget1->GetRandomizeSticks()) );
break;
}
case 2:
{
mitk::DotModel<ScalarType>* model = new mitk::DotModel<ScalarType>();
model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections());
model->SetT2(m_Controls->m_DotWidget1->GetT2());
model->SetT1(m_Controls->m_DotWidget1->GetT1());
model->m_CompartmentId = 3;
m_Parameters.m_NonFiberModelList.push_back(model);
m_Parameters.m_Misc.m_SignalModelString += "Dot";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Dot") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.T2", DoubleProperty::New(model->GetT2()) );
break;
}
case 3:
{
mitk::RawShModel<ScalarType>* model = new mitk::RawShModel<ScalarType>();
m_Parameters.m_SignalGen.m_DoSimulateRelaxation = false;
model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections());
model->SetMaxNumKernels(m_Controls->m_PrototypeWidget3->GetNumberOfSamples());
model->SetFaRange(m_Controls->m_PrototypeWidget3->GetMinFa(), m_Controls->m_PrototypeWidget3->GetMaxFa());
model->SetAdcRange(m_Controls->m_PrototypeWidget3->GetMinAdc(), m_Controls->m_PrototypeWidget3->GetMaxAdc());
model->m_CompartmentId = 3;
m_Parameters.m_NonFiberModelList.push_back(model);
m_Parameters.m_Misc.m_SignalModelString += "Prototype";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Description", StringProperty::New("Extra-axonal compartment 1") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment3.Model", StringProperty::New("Prototype") );
break;
}
}
if (m_Controls->m_Comp3VolumeFraction->GetSelectedNode().IsNotNull())
{
mitk::DataNode::Pointer volumeNode = m_Controls->m_Comp3VolumeFraction->GetSelectedNode();
ItkDoubleImgType::Pointer comp1VolumeImage = ItkDoubleImgType::New();
mitk::Image* img = dynamic_cast<mitk::Image*>(volumeNode->GetData());
CastToItkImage< ItkDoubleImgType >(img, comp1VolumeImage);
m_Parameters.m_NonFiberModelList.back()->SetVolumeFractionImage(comp1VolumeImage);
}
switch (m_Controls->m_Compartment4Box->currentIndex())
{
case 0:
break;
case 1:
{
mitk::BallModel<ScalarType>* model = new mitk::BallModel<ScalarType>();
model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections());
model->SetBvalue(m_Parameters.m_SignalGen.GetBvalue());
model->SetDiffusivity(m_Controls->m_BallWidget2->GetD());
model->SetT2(m_Controls->m_BallWidget2->GetT2());
model->SetT1(m_Controls->m_BallWidget2->GetT1());
model->m_CompartmentId = 4;
m_Parameters.m_NonFiberModelList.push_back(model);
m_Parameters.m_Misc.m_SignalModelString += "Ball";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Ball") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_BallWidget2->GetD()) );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) );
break;
}
case 2:
{
mitk::AstroStickModel<ScalarType>* model = new mitk::AstroStickModel<ScalarType>();
model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections());
model->SetBvalue(m_Parameters.m_SignalGen.GetBvalue());
model->SetDiffusivity(m_Controls->m_AstrosticksWidget2->GetD());
model->SetT2(m_Controls->m_AstrosticksWidget2->GetT2());
model->SetT1(m_Controls->m_AstrosticksWidget2->GetT1());
model->SetRandomizeSticks(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks());
model->m_CompartmentId = 4;
m_Parameters.m_NonFiberModelList.push_back(model);
m_Parameters.m_Misc.m_SignalModelString += "Astrosticks";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Astrosticks") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.D", DoubleProperty::New(m_Controls->m_AstrosticksWidget2->GetD()) );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.RandomSticks", BoolProperty::New(m_Controls->m_AstrosticksWidget2->GetRandomizeSticks()) );
break;
}
case 3:
{
mitk::DotModel<ScalarType>* model = new mitk::DotModel<ScalarType>();
model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections());
model->SetT2(m_Controls->m_DotWidget2->GetT2());
model->SetT1(m_Controls->m_DotWidget2->GetT1());
model->m_CompartmentId = 4;
m_Parameters.m_NonFiberModelList.push_back(model);
m_Parameters.m_Misc.m_SignalModelString += "Dot";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Dot") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.T2", DoubleProperty::New(model->GetT2()) );
break;
}
case 4:
{
mitk::RawShModel<ScalarType>* model = new mitk::RawShModel<ScalarType>();
m_Parameters.m_SignalGen.m_DoSimulateRelaxation = false;
model->SetGradientList(m_Parameters.m_SignalGen.GetGradientDirections());
model->SetMaxNumKernels(m_Controls->m_PrototypeWidget4->GetNumberOfSamples());
model->SetFaRange(m_Controls->m_PrototypeWidget4->GetMinFa(), m_Controls->m_PrototypeWidget4->GetMaxFa());
model->SetAdcRange(m_Controls->m_PrototypeWidget4->GetMinAdc(), m_Controls->m_PrototypeWidget4->GetMaxAdc());
model->m_CompartmentId = 4;
m_Parameters.m_NonFiberModelList.push_back(model);
m_Parameters.m_Misc.m_SignalModelString += "Prototype";
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Description", StringProperty::New("Extra-axonal compartment 2") );
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Compartment4.Model", StringProperty::New("Prototype") );
break;
}
}
if (m_Controls->m_Comp4VolumeFraction->GetSelectedNode().IsNotNull() && m_Parameters.m_NonFiberModelList.size()==2)
{
mitk::DataNode::Pointer volumeNode = m_Controls->m_Comp4VolumeFraction->GetSelectedNode();
ItkDoubleImgType::Pointer compVolumeImage = ItkDoubleImgType::New();
mitk::Image* img = dynamic_cast<mitk::Image*>(volumeNode->GetData());
CastToItkImage< ItkDoubleImgType >(img, compVolumeImage);
m_Parameters.m_NonFiberModelList.back()->SetVolumeFractionImage(compVolumeImage);
}
}
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.SignalScale", IntProperty::New(m_Parameters.m_SignalGen.m_SignalScale));
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.FiberRadius", IntProperty::New(m_Parameters.m_SignalGen.m_AxonRadius));
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Tinhom", DoubleProperty::New(m_Parameters.m_SignalGen.m_tInhom));
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.echoTrainLength", IntProperty::New(m_Parameters.m_SignalGen.m_EchoTrainLength));
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Tline", DoubleProperty::New(m_Parameters.m_SignalGen.m_tLine));
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.TE", DoubleProperty::New(m_Parameters.m_SignalGen.m_tEcho));
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.b-value", DoubleProperty::New(m_Parameters.m_SignalGen.GetBvalue()));
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.NoPartialVolume", BoolProperty::New(m_Parameters.m_SignalGen.m_DoDisablePartialVolume));
m_Parameters.m_Misc.m_ResultNode->AddProperty("Fiberfox.Relaxation", BoolProperty::New(m_Parameters.m_SignalGen.m_DoSimulateRelaxation));
m_Parameters.m_Misc.m_ResultNode->AddProperty("binary", BoolProperty::New(false));
}
void QmitkFiberfoxView::SaveParameters(QString filename)
{
UpdateParametersFromGui();
std::vector< int > bVals = m_Parameters.m_SignalGen.GetBvalues();
std::cout << "b-values: ";
for (auto v : bVals)
std::cout << v << " ";
std::cout << std::endl;
bool ok = true;
bool first = true;
bool dosampling = false;
mitk::Image::Pointer diffImg = nullptr;
itk::Image< itk::DiffusionTensor3D< double >, 3 >::Pointer tensorImage = nullptr;
const int shOrder = 2;
typedef itk::AnalyticalDiffusionQballReconstructionImageFilter<short,short,float,shOrder,ODF_SAMPLING_SIZE> QballFilterType;
QballFilterType::CoefficientImageType::Pointer itkFeatureImage = nullptr;
ItkDoubleImgType::Pointer adcImage = nullptr;
for (unsigned int i=0; i<m_Parameters.m_FiberModelList.size()+m_Parameters.m_NonFiberModelList.size(); i++)
{
mitk::RawShModel<>* model = nullptr;
if (i<m_Parameters.m_FiberModelList.size())
{
model = dynamic_cast< mitk::RawShModel<>* >(m_Parameters.m_FiberModelList.at(i));
}
else
{
model = dynamic_cast< mitk::RawShModel<>* >(m_Parameters.m_NonFiberModelList.at(i-m_Parameters.m_FiberModelList.size()));
}
if ( model!=nullptr && model->GetNumberOfKernels() <= 0 )
{
if (first==true)
{
if ( QMessageBox::question(nullptr, "Prototype signal sampling",
"Do you want to sample prototype signals from the selected diffusion-weighted imag and save them?",
QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes )
dosampling = true;
first = false;
if ( dosampling && (m_Controls->m_TemplateComboBox->GetSelectedNode().IsNull()
|| !mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(
dynamic_cast<mitk::Image*>(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()) ) ) )
{
QMessageBox::information(nullptr, "Parameter file not saved", "No diffusion-weighted image selected to sample signal from.");
return;
}
else if (dosampling)
{
diffImg = dynamic_cast<mitk::Image*>(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData());
typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, double > TensorReconstructionImageFilterType;
TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New();
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(diffImg, itkVectorImagePointer);
filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImg));
filter->SetGradientImage(mitk::DiffusionPropertyHelper::GetGradientContainer(diffImg),
itkVectorImagePointer );
filter->Update();
tensorImage = filter->GetOutput();
QballFilterType::Pointer qballfilter = QballFilterType::New();
qballfilter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImg));
qballfilter->SetGradientImage(mitk::DiffusionPropertyHelper::GetGradientContainer(diffImg),
itkVectorImagePointer );
qballfilter->SetLambda(0.006);
qballfilter->SetNormalizationMethod(QballFilterType::QBAR_RAW_SIGNAL);
qballfilter->Update();
itkFeatureImage = qballfilter->GetCoefficientImage();
itk::AdcImageFilter< short, double >::Pointer adcFilter = itk::AdcImageFilter< short, double >::New();
adcFilter->SetInput( itkVectorImagePointer );
adcFilter->SetGradientDirections(mitk::DiffusionPropertyHelper::GetGradientContainer(diffImg));
adcFilter->SetB_value(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImg));
adcFilter->Update();
adcImage = adcFilter->GetOutput();
}
}
typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, double > TensorReconstructionImageFilterType;
TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New();
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(diffImg, itkVectorImagePointer);
filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImg));
filter->SetGradientImage(mitk::DiffusionPropertyHelper::GetGradientContainer(diffImg), itkVectorImagePointer );
filter->Update();
tensorImage = filter->GetOutput();
QballFilterType::Pointer qballfilter = QballFilterType::New();
qballfilter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImg));
qballfilter->SetGradientImage(mitk::DiffusionPropertyHelper::GetGradientContainer(diffImg),
itkVectorImagePointer );
qballfilter->SetLambda(0.006);
qballfilter->SetNormalizationMethod(QballFilterType::QBAR_RAW_SIGNAL);
qballfilter->Update();
itkFeatureImage = qballfilter->GetCoefficientImage();
itk::AdcImageFilter< short, double >::Pointer adcFilter = itk::AdcImageFilter< short, double >::New();
adcFilter->SetInput( itkVectorImagePointer );
adcFilter->SetGradientDirections(mitk::DiffusionPropertyHelper::GetGradientContainer(diffImg));
adcFilter->SetB_value(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImg));
adcFilter->Update();
adcImage = adcFilter->GetOutput();
if (dosampling && diffImg.IsNotNull())
{
ok = model->SampleKernels(diffImg, m_Parameters.m_SignalGen.m_MaskImage, tensorImage, itkFeatureImage, adcImage);
if (!ok)
{
QMessageBox::information( nullptr, "Parameter file not saved", "No valid prototype signals could be sampled.");
return;
}
}
}
}
m_Parameters.SaveParameters(filename.toStdString());
m_ParameterFile = filename;
}
void QmitkFiberfoxView::SaveParameters()
{
QString filename = QFileDialog::getSaveFileName(
0,
tr("Save Parameters"),
m_ParameterFile,
tr("Fiberfox Parameters (*.ffp)") );
SaveParameters(filename);
}
void QmitkFiberfoxView::LoadParameters()
{
QString filename = QFileDialog::getOpenFileName(0, tr("Load Parameters"), QString(itksys::SystemTools::GetFilenamePath(m_ParameterFile.toStdString()).c_str()), tr("Fiberfox Parameters (*.ffp)") );
if(filename.isEmpty() || filename.isNull())
return;
m_ParameterFile = filename;
m_Parameters.LoadParameters(filename.toStdString());
if (m_Parameters.m_MissingTags.size()>0)
{
QString missing("Parameter file might be corrupted. The following parameters could not be read: ");
missing += QString(m_Parameters.m_MissingTags.c_str());
missing += "\nDefault values have been assigned to the missing parameters.";
QMessageBox::information( nullptr, "Warning!", missing);
}
// image generation parameters
m_Controls->m_SizeX->setValue(m_Parameters.m_SignalGen.m_ImageRegion.GetSize(0));
m_Controls->m_SizeY->setValue(m_Parameters.m_SignalGen.m_ImageRegion.GetSize(1));
m_Controls->m_SizeZ->setValue(m_Parameters.m_SignalGen.m_ImageRegion.GetSize(2));
m_Controls->m_SpacingX->setValue(m_Parameters.m_SignalGen.m_ImageSpacing[0]);
m_Controls->m_SpacingY->setValue(m_Parameters.m_SignalGen.m_ImageSpacing[1]);
m_Controls->m_SpacingZ->setValue(m_Parameters.m_SignalGen.m_ImageSpacing[2]);
m_Controls->m_NumGradientsBox->setValue(m_Parameters.m_SignalGen.GetNumWeightedVolumes());
m_Controls->m_BvalueBox->setValue(m_Parameters.m_SignalGen.GetBvalue());
m_Controls->m_SignalScaleBox->setValue(m_Parameters.m_SignalGen.m_SignalScale);
m_Controls->m_TEbox->setValue(m_Parameters.m_SignalGen.m_tEcho);
m_Controls->m_LineReadoutTimeBox->setValue(m_Parameters.m_SignalGen.m_tLine);
m_Controls->m_T2starBox->setValue(m_Parameters.m_SignalGen.m_tInhom);
m_Controls->m_EtlBox->setValue(m_Parameters.m_SignalGen.m_EchoTrainLength);
m_Controls->m_FiberRadius->setValue(m_Parameters.m_SignalGen.m_AxonRadius);
m_Controls->m_RelaxationBox->setChecked(m_Parameters.m_SignalGen.m_DoSimulateRelaxation);
m_Controls->m_EnforcePureFiberVoxelsBox->setChecked(m_Parameters.m_SignalGen.m_DoDisablePartialVolume);
m_Controls->m_ReversePhaseBox->setChecked(m_Parameters.m_SignalGen.m_ReversePhase);
m_Controls->m_PartialFourier->setValue(m_Parameters.m_SignalGen.m_PartialFourier);
m_Controls->m_TRbox->setValue(m_Parameters.m_SignalGen.m_tRep);
m_Controls->m_TIbox->setValue(m_Parameters.m_SignalGen.m_tInv);
m_Controls->m_NumCoilsBox->setValue(m_Parameters.m_SignalGen.m_NumberOfCoils);
m_Controls->m_CoilSensBox->setCurrentIndex(m_Parameters.m_SignalGen.m_CoilSensitivityProfile);
m_Controls->m_AcquisitionTypeBox->setCurrentIndex(m_Parameters.m_SignalGen.m_AcquisitionType);
if (!m_Parameters.m_Misc.m_BvalsFile.empty())
{
m_Controls->m_UseBvalsBvecsBox->setChecked(true);
m_Controls->m_LoadBvalsEdit->setText(QString(m_Parameters.m_Misc.m_BvalsFile.c_str()));
}
else
m_Controls->m_LoadBvalsEdit->setText("-");
if (!m_Parameters.m_Misc.m_BvecsFile.empty())
{
m_Controls->m_UseBvalsBvecsBox->setChecked(true);
m_Controls->m_LoadBvecsEdit->setText(QString(m_Parameters.m_Misc.m_BvecsFile.c_str()));
}
else
m_Controls->m_LoadBvecsEdit->setText("-");
if (m_Parameters.m_NoiseModel!=nullptr)
{
m_Controls->m_AddNoise->setChecked(m_Parameters.m_Misc.m_DoAddNoise);
if (dynamic_cast<mitk::RicianNoiseModel<double>*>(m_Parameters.m_NoiseModel.get()))
{
m_Controls->m_NoiseDistributionBox->setCurrentIndex(0);
}
else if (dynamic_cast<mitk::ChiSquareNoiseModel<double>*>(m_Parameters.m_NoiseModel.get()))
{
m_Controls->m_NoiseDistributionBox->setCurrentIndex(1);
}
m_Controls->m_NoiseLevel->setValue(m_Parameters.m_NoiseModel->GetNoiseVariance());
}
else
{
m_Controls->m_AddNoise->setChecked(m_Parameters.m_Misc.m_DoAddNoise);
m_Controls->m_NoiseLevel->setValue(m_Parameters.m_SignalGen.m_NoiseVariance);
}
m_Controls->m_VolumeFractionsBox->setChecked(m_Parameters.m_Misc.m_OutputAdditionalImages);
m_Controls->m_AdvancedOptionsBox_2->setChecked(m_Parameters.m_Misc.m_CheckAdvancedSignalOptionsBox);
m_Controls->m_AddGhosts->setChecked(m_Parameters.m_Misc.m_DoAddGhosts);
m_Controls->m_AddAliasing->setChecked(m_Parameters.m_Misc.m_DoAddAliasing);
m_Controls->m_AddDistortions->setChecked(m_Parameters.m_Misc.m_DoAddDistortions);
m_Controls->m_AddSpikes->setChecked(m_Parameters.m_Misc.m_DoAddSpikes);
m_Controls->m_AddEddy->setChecked(m_Parameters.m_Misc.m_DoAddEddyCurrents);
m_Controls->m_AddDrift->setChecked(m_Parameters.m_SignalGen.m_DoAddDrift);
m_Controls->m_kOffsetBox->setValue(m_Parameters.m_SignalGen.m_KspaceLineOffset);
m_Controls->m_WrapBox->setValue(100*(1-m_Parameters.m_SignalGen.m_CroppingFactor));
m_Controls->m_DriftFactor->setValue(100*m_Parameters.m_SignalGen.m_Drift);
m_Controls->m_SpikeNumBox->setValue(m_Parameters.m_SignalGen.m_Spikes);
m_Controls->m_SpikeScaleBox->setValue(m_Parameters.m_SignalGen.m_SpikeAmplitude);
m_Controls->m_EddyGradientStrength->setValue(m_Parameters.m_SignalGen.m_EddyStrength);
m_Controls->m_AddGibbsRinging->setChecked(m_Parameters.m_SignalGen.m_DoAddGibbsRinging);
m_Controls->m_ZeroRinging->setValue(m_Parameters.m_SignalGen.m_ZeroRinging);
m_Controls->m_AddMotion->setChecked(m_Parameters.m_SignalGen.m_DoAddMotion);
m_Controls->m_RandomMotion->setChecked(m_Parameters.m_SignalGen.m_DoRandomizeMotion);
m_Controls->m_MotionVolumesBox->setText(QString(m_Parameters.m_Misc.m_MotionVolumesBox.c_str()));
m_Controls->m_MaxTranslationBoxX->setValue(m_Parameters.m_SignalGen.m_Translation[0]);
m_Controls->m_MaxTranslationBoxY->setValue(m_Parameters.m_SignalGen.m_Translation[1]);
m_Controls->m_MaxTranslationBoxZ->setValue(m_Parameters.m_SignalGen.m_Translation[2]);
m_Controls->m_MaxRotationBoxX->setValue(m_Parameters.m_SignalGen.m_Rotation[0]);
m_Controls->m_MaxRotationBoxY->setValue(m_Parameters.m_SignalGen.m_Rotation[1]);
m_Controls->m_MaxRotationBoxZ->setValue(m_Parameters.m_SignalGen.m_Rotation[2]);
m_Controls->m_Compartment1Box->setCurrentIndex(0);
m_Controls->m_Compartment2Box->setCurrentIndex(0);
m_Controls->m_Compartment3Box->setCurrentIndex(0);
m_Controls->m_Compartment4Box->setCurrentIndex(0);
for (unsigned int i=0; i<m_Parameters.m_FiberModelList.size()+m_Parameters.m_NonFiberModelList.size(); i++)
{
mitk::DiffusionSignalModel<ScalarType>* signalModel = nullptr;
if (i<m_Parameters.m_FiberModelList.size())
signalModel = m_Parameters.m_FiberModelList.at(i);
else
signalModel = m_Parameters.m_NonFiberModelList.at(i-m_Parameters.m_FiberModelList.size());
mitk::DataNode::Pointer compVolNode;
if ( signalModel->GetVolumeFractionImage().IsNotNull() )
{
compVolNode = mitk::DataNode::New();
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk(signalModel->GetVolumeFractionImage().GetPointer());
image->SetVolume(signalModel->GetVolumeFractionImage()->GetBufferPointer());
compVolNode->SetData( image );
compVolNode->SetName("Compartment volume "+QString::number(signalModel->m_CompartmentId).toStdString());
GetDataStorage()->Add(compVolNode);
}
switch (signalModel->m_CompartmentId)
{
case 1:
{
if (compVolNode.IsNotNull())
m_Controls->m_Comp1VolumeFraction->SetSelectedNode(compVolNode);
if (dynamic_cast<mitk::StickModel<>*>(signalModel))
{
mitk::StickModel<>* model = dynamic_cast<mitk::StickModel<>*>(signalModel);
m_Controls->m_StickWidget1->SetT2(model->GetT2());
m_Controls->m_StickWidget1->SetT1(model->GetT1());
m_Controls->m_StickWidget1->SetD(model->GetDiffusivity());
m_Controls->m_Compartment1Box->setCurrentIndex(0);
break;
}
else if (dynamic_cast<mitk::TensorModel<>*>(signalModel))
{
mitk::TensorModel<>* model = dynamic_cast<mitk::TensorModel<>*>(signalModel);
m_Controls->m_TensorWidget1->SetT2(model->GetT2());
m_Controls->m_TensorWidget1->SetT1(model->GetT1());
m_Controls->m_TensorWidget1->SetD1(model->GetDiffusivity1());
m_Controls->m_TensorWidget1->SetD2(model->GetDiffusivity2());
m_Controls->m_TensorWidget1->SetD3(model->GetDiffusivity3());
m_Controls->m_Compartment1Box->setCurrentIndex(2);
break;
}
else if (dynamic_cast<mitk::RawShModel<>*>(signalModel))
{
mitk::RawShModel<>* model = dynamic_cast<mitk::RawShModel<>*>(signalModel);
m_Controls->m_PrototypeWidget1->SetNumberOfSamples(model->GetMaxNumKernels());
m_Controls->m_PrototypeWidget1->SetMinFa(model->GetFaRange().first);
m_Controls->m_PrototypeWidget1->SetMaxFa(model->GetFaRange().second);
m_Controls->m_PrototypeWidget1->SetMinAdc(model->GetAdcRange().first);
m_Controls->m_PrototypeWidget1->SetMaxAdc(model->GetAdcRange().second);
m_Controls->m_Compartment1Box->setCurrentIndex(3);
break;
}
break;
}
case 2:
{
if (compVolNode.IsNotNull())
m_Controls->m_Comp2VolumeFraction->SetSelectedNode(compVolNode);
if (dynamic_cast<mitk::StickModel<>*>(signalModel))
{
mitk::StickModel<>* model = dynamic_cast<mitk::StickModel<>*>(signalModel);
m_Controls->m_StickWidget2->SetT2(model->GetT2());
m_Controls->m_StickWidget2->SetT1(model->GetT1());
m_Controls->m_StickWidget2->SetD(model->GetDiffusivity());
m_Controls->m_Compartment2Box->setCurrentIndex(1);
break;
}
else if (dynamic_cast<mitk::TensorModel<>*>(signalModel))
{
mitk::TensorModel<>* model = dynamic_cast<mitk::TensorModel<>*>(signalModel);
m_Controls->m_TensorWidget2->SetT2(model->GetT2());
m_Controls->m_TensorWidget2->SetT1(model->GetT1());
m_Controls->m_TensorWidget2->SetD1(model->GetDiffusivity1());
m_Controls->m_TensorWidget2->SetD2(model->GetDiffusivity2());
m_Controls->m_TensorWidget2->SetD3(model->GetDiffusivity3());
m_Controls->m_Compartment2Box->setCurrentIndex(3);
break;
}
break;
}
case 3:
{
if (compVolNode.IsNotNull())
m_Controls->m_Comp3VolumeFraction->SetSelectedNode(compVolNode);
if (dynamic_cast<mitk::BallModel<>*>(signalModel))
{
mitk::BallModel<>* model = dynamic_cast<mitk::BallModel<>*>(signalModel);
m_Controls->m_BallWidget1->SetT2(model->GetT2());
m_Controls->m_BallWidget1->SetT1(model->GetT1());
m_Controls->m_BallWidget1->SetD(model->GetDiffusivity());
m_Controls->m_Compartment3Box->setCurrentIndex(0);
break;
}
else if (dynamic_cast<mitk::AstroStickModel<>*>(signalModel))
{
mitk::AstroStickModel<>* model = dynamic_cast<mitk::AstroStickModel<>*>(signalModel);
m_Controls->m_AstrosticksWidget1->SetT2(model->GetT2());
m_Controls->m_AstrosticksWidget1->SetT1(model->GetT1());
m_Controls->m_AstrosticksWidget1->SetD(model->GetDiffusivity());
m_Controls->m_AstrosticksWidget1->SetRandomizeSticks(model->GetRandomizeSticks());
m_Controls->m_Compartment3Box->setCurrentIndex(1);
break;
}
else if (dynamic_cast<mitk::DotModel<>*>(signalModel))
{
mitk::DotModel<>* model = dynamic_cast<mitk::DotModel<>*>(signalModel);
m_Controls->m_DotWidget1->SetT2(model->GetT2());
m_Controls->m_DotWidget1->SetT1(model->GetT1());
m_Controls->m_Compartment3Box->setCurrentIndex(2);
break;
}
else if (dynamic_cast<mitk::RawShModel<>*>(signalModel))
{
mitk::RawShModel<>* model = dynamic_cast<mitk::RawShModel<>*>(signalModel);
m_Controls->m_PrototypeWidget3->SetNumberOfSamples(model->GetMaxNumKernels());
m_Controls->m_PrototypeWidget3->SetMinFa(model->GetFaRange().first);
m_Controls->m_PrototypeWidget3->SetMaxFa(model->GetFaRange().second);
m_Controls->m_PrototypeWidget3->SetMinAdc(model->GetAdcRange().first);
m_Controls->m_PrototypeWidget3->SetMaxAdc(model->GetAdcRange().second);
m_Controls->m_Compartment3Box->setCurrentIndex(3);
break;
}
break;
}
case 4:
{
if (compVolNode.IsNotNull())
m_Controls->m_Comp4VolumeFraction->SetSelectedNode(compVolNode);
if (dynamic_cast<mitk::BallModel<>*>(signalModel))
{
mitk::BallModel<>* model = dynamic_cast<mitk::BallModel<>*>(signalModel);
m_Controls->m_BallWidget2->SetT2(model->GetT2());
m_Controls->m_BallWidget2->SetT1(model->GetT1());
m_Controls->m_BallWidget2->SetD(model->GetDiffusivity());
m_Controls->m_Compartment4Box->setCurrentIndex(1);
break;
}
else if (dynamic_cast<mitk::AstroStickModel<>*>(signalModel))
{
mitk::AstroStickModel<>* model = dynamic_cast<mitk::AstroStickModel<>*>(signalModel);
m_Controls->m_AstrosticksWidget2->SetT2(model->GetT2());
m_Controls->m_AstrosticksWidget2->SetT1(model->GetT1());
m_Controls->m_AstrosticksWidget2->SetD(model->GetDiffusivity());
m_Controls->m_AstrosticksWidget2->SetRandomizeSticks(model->GetRandomizeSticks());
m_Controls->m_Compartment4Box->setCurrentIndex(2);
break;
}
else if (dynamic_cast<mitk::DotModel<>*>(signalModel))
{
mitk::DotModel<>* model = dynamic_cast<mitk::DotModel<>*>(signalModel);
m_Controls->m_DotWidget2->SetT2(model->GetT2());
m_Controls->m_DotWidget2->SetT1(model->GetT1());
m_Controls->m_Compartment4Box->setCurrentIndex(3);
break;
}
else if (dynamic_cast<mitk::RawShModel<>*>(signalModel))
{
mitk::RawShModel<>* model = dynamic_cast<mitk::RawShModel<>*>(signalModel);
m_Controls->m_PrototypeWidget4->SetNumberOfSamples(model->GetMaxNumKernels());
m_Controls->m_PrototypeWidget4->SetMinFa(model->GetFaRange().first);
m_Controls->m_PrototypeWidget4->SetMaxFa(model->GetFaRange().second);
m_Controls->m_PrototypeWidget4->SetMinAdc(model->GetAdcRange().first);
m_Controls->m_PrototypeWidget4->SetMaxAdc(model->GetAdcRange().second);
m_Controls->m_Compartment4Box->setCurrentIndex(4);
break;
}
break;
}
}
}
if ( m_Parameters.m_SignalGen.m_MaskImage )
{
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk(m_Parameters.m_SignalGen.m_MaskImage.GetPointer());
image->SetVolume(m_Parameters.m_SignalGen.m_MaskImage->GetBufferPointer());
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( image );
node->SetName("Tissue mask");
GetDataStorage()->Add(node);
m_Controls->m_MaskComboBox->SetSelectedNode(node);
}
if ( m_Parameters.m_SignalGen.m_FrequencyMap )
{
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk(m_Parameters.m_SignalGen.m_FrequencyMap.GetPointer());
image->SetVolume(m_Parameters.m_SignalGen.m_FrequencyMap->GetBufferPointer());
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( image );
node->SetName("Frequency map");
GetDataStorage()->Add(node);
m_Controls->m_FrequencyMapBox->SetSelectedNode(node);
}
}
void QmitkFiberfoxView::ShowAdvancedOptions(int state)
{
if (state)
{
m_Controls->m_AdvancedSignalOptionsFrame->setVisible(true);
m_Controls->m_AdvancedOptionsBox_2->setChecked(true);
}
else
{
m_Controls->m_AdvancedSignalOptionsFrame->setVisible(false);
m_Controls->m_AdvancedOptionsBox_2->setChecked(false);
}
}
void QmitkFiberfoxView::Comp1ModelFrameVisibility(int index)
{
m_Controls->m_StickWidget1->setVisible(false);
m_Controls->m_ZeppelinWidget1->setVisible(false);
m_Controls->m_TensorWidget1->setVisible(false);
m_Controls->m_PrototypeWidget1->setVisible(false);
switch (index)
{
case 0:
m_Controls->m_StickWidget1->setVisible(true);
break;
case 1:
m_Controls->m_ZeppelinWidget1->setVisible(true);
break;
case 2:
m_Controls->m_TensorWidget1->setVisible(true);
break;
case 3:
m_Controls->m_PrototypeWidget1->setVisible(true);
break;
}
}
void QmitkFiberfoxView::Comp2ModelFrameVisibility(int index)
{
m_Controls->m_StickWidget2->setVisible(false);
m_Controls->m_ZeppelinWidget2->setVisible(false);
m_Controls->m_TensorWidget2->setVisible(false);
m_Controls->m_Comp2FractionFrame->setVisible(false);
switch (index)
{
case 0:
break;
case 1:
m_Controls->m_StickWidget2->setVisible(true);
m_Controls->m_Comp2FractionFrame->setVisible(true);
break;
case 2:
m_Controls->m_ZeppelinWidget2->setVisible(true);
m_Controls->m_Comp2FractionFrame->setVisible(true);
break;
case 3:
m_Controls->m_TensorWidget2->setVisible(true);
m_Controls->m_Comp2FractionFrame->setVisible(true);
break;
}
}
void QmitkFiberfoxView::Comp3ModelFrameVisibility(int index)
{
m_Controls->m_BallWidget1->setVisible(false);
m_Controls->m_AstrosticksWidget1->setVisible(false);
m_Controls->m_DotWidget1->setVisible(false);
m_Controls->m_PrototypeWidget3->setVisible(false);
switch (index)
{
case 0:
m_Controls->m_BallWidget1->setVisible(true);
break;
case 1:
m_Controls->m_AstrosticksWidget1->setVisible(true);
break;
case 2:
m_Controls->m_DotWidget1->setVisible(true);
break;
case 3:
m_Controls->m_PrototypeWidget3->setVisible(true);
break;
}
}
void QmitkFiberfoxView::Comp4ModelFrameVisibility(int index)
{
m_Controls->m_BallWidget2->setVisible(false);
m_Controls->m_AstrosticksWidget2->setVisible(false);
m_Controls->m_DotWidget2->setVisible(false);
m_Controls->m_PrototypeWidget4->setVisible(false);
m_Controls->m_Comp4FractionFrame->setVisible(false);
switch (index)
{
case 0:
break;
case 1:
m_Controls->m_BallWidget2->setVisible(true);
m_Controls->m_Comp4FractionFrame->setVisible(true);
break;
case 2:
m_Controls->m_AstrosticksWidget2->setVisible(true);
m_Controls->m_Comp4FractionFrame->setVisible(true);
break;
case 3:
m_Controls->m_DotWidget2->setVisible(true);
m_Controls->m_Comp4FractionFrame->setVisible(true);
break;
case 4:
m_Controls->m_PrototypeWidget4->setVisible(true);
m_Controls->m_Comp4FractionFrame->setVisible(true);
break;
}
}
void QmitkFiberfoxView::OnAddMotion(int value)
{
if (value>0)
m_Controls->m_MotionArtifactFrame->setVisible(true);
else
m_Controls->m_MotionArtifactFrame->setVisible(false);
}
void QmitkFiberfoxView::OnAddDrift(int value)
{
if (value>0)
m_Controls->m_DriftFrame->setVisible(true);
else
m_Controls->m_DriftFrame->setVisible(false);
}
void QmitkFiberfoxView::OnAddAliasing(int value)
{
if (value>0)
m_Controls->m_AliasingFrame->setVisible(true);
else
m_Controls->m_AliasingFrame->setVisible(false);
}
void QmitkFiberfoxView::OnAddSpikes(int value)
{
if (value>0)
m_Controls->m_SpikeFrame->setVisible(true);
else
m_Controls->m_SpikeFrame->setVisible(false);
}
void QmitkFiberfoxView::OnAddEddy(int value)
{
if (value>0)
m_Controls->m_EddyFrame->setVisible(true);
else
m_Controls->m_EddyFrame->setVisible(false);
}
void QmitkFiberfoxView::OnAddDistortions(int value)
{
if (value>0)
m_Controls->m_DistortionsFrame->setVisible(true);
else
m_Controls->m_DistortionsFrame->setVisible(false);
}
void QmitkFiberfoxView::OnAddGhosts(int value)
{
if (value>0)
m_Controls->m_GhostFrame->setVisible(true);
else
m_Controls->m_GhostFrame->setVisible(false);
}
void QmitkFiberfoxView::OnAddNoise(int value)
{
if (value>0)
m_Controls->m_NoiseFrame->setVisible(true);
else
m_Controls->m_NoiseFrame->setVisible(false);
}
void QmitkFiberfoxView::OnAddRinging(int value)
{
if (value>0)
m_Controls->m_ZeroRinging->setVisible(true);
else
m_Controls->m_ZeroRinging->setVisible(false);
}
QmitkFiberfoxView::GradientListType QmitkFiberfoxView::GenerateHalfShell(int NPoints)
{
NPoints *= 2;
GradientListType pointshell;
int numB0 = NPoints/20;
if (numB0==0)
numB0=1;
GradientType g;
g.Fill(0.0);
for (int i=0; i<numB0; i++)
pointshell.push_back(g);
if (NPoints==0)
return pointshell;
vnl_vector<double> theta; theta.set_size(NPoints);
vnl_vector<double> phi; phi.set_size(NPoints);
double C = sqrt(4*itk::Math::pi);
phi(0) = 0.0;
phi(NPoints-1) = 0.0;
for(int i=0; i<NPoints; i++)
{
theta(i) = acos(-1.0+2.0*i/(NPoints-1.0)) - itk::Math::pi / 2.0;
if( i>0 && i<NPoints-1)
{
phi(i) = (phi(i-1) + C /
sqrt(NPoints*(1-(-1.0+2.0*i/(NPoints-1.0))*(-1.0+2.0*i/(NPoints-1.0)))));
// % (2*DIST_POINTSHELL_PI);
}
}
for(int i=0; i<NPoints; i++)
{
g[2] = sin(theta(i));
if (g[2]<0)
continue;
g[0] = cos(theta(i)) * cos(phi(i));
g[1] = cos(theta(i)) * sin(phi(i));
pointshell.push_back(g);
}
return pointshell;
}
template<int ndirs>
std::vector<itk::Vector<double,3> > QmitkFiberfoxView::MakeGradientList()
{
std::vector<itk::Vector<double,3> > retval;
vnl_matrix_fixed<double, 3, ndirs>* U =
itk::PointShell<ndirs, vnl_matrix_fixed<double, 3, ndirs> >::DistributePointShell();
// Add 0 vector for B0
int numB0 = ndirs/10;
if (numB0==0)
numB0=1;
itk::Vector<double,3> v;
v.Fill(0.0);
for (int i=0; i<numB0; i++)
{
retval.push_back(v);
}
for(int i=0; i<ndirs;i++)
{
itk::Vector<double,3> v;
v[0] = U->get(0,i); v[1] = U->get(1,i); v[2] = U->get(2,i);
retval.push_back(v);
}
return retval;
}
void QmitkFiberfoxView::GenerateImage()
{
if (m_Controls->m_FiberBundleComboBox->GetSelectedNode().IsNull() && !mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( m_Controls->m_TemplateComboBox->GetSelectedNode()))
{
mitk::Image::Pointer image = mitk::ImageGenerator::GenerateGradientImage<unsigned int>(
m_Controls->m_SizeX->value(),
m_Controls->m_SizeY->value(),
m_Controls->m_SizeZ->value(),
m_Controls->m_SpacingX->value(),
m_Controls->m_SpacingY->value(),
m_Controls->m_SpacingZ->value());
mitk::Point3D origin;
origin[0] = m_Controls->m_SpacingX->value()/2;
origin[1] = m_Controls->m_SpacingY->value()/2;
origin[2] = m_Controls->m_SpacingZ->value()/2;
image->SetOrigin(origin);
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( image );
node->SetName("Dummy");
GetDataStorage()->Add(node);
m_SelectedImageNode = node;
mitk::BaseData::Pointer basedata = node->GetData();
if (basedata.IsNotNull())
{
mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
UpdateGui();
QMessageBox::information(nullptr, "Template image generated", "You have selected no fiber bundle or diffusion-weighted image, which can be used to simulate a new diffusion-weighted image. A template image with the specified geometry has been generated that can be used to draw artificial fibers (see view 'Fiber Generator').");
}
else if (m_Controls->m_FiberBundleComboBox->GetSelectedNode().IsNotNull())
SimulateImageFromFibers(m_Controls->m_FiberBundleComboBox->GetSelectedNode());
else if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( m_Controls->m_TemplateComboBox->GetSelectedNode()) )
SimulateForExistingDwi(m_Controls->m_TemplateComboBox->GetSelectedNode());
else
QMessageBox::information(nullptr, "No image generated", "You have selected no fiber bundle or diffusion-weighted image, which can be used to simulate a new diffusion-weighted image.");
}
void QmitkFiberfoxView::SetFocus()
{
}
void QmitkFiberfoxView::SimulateForExistingDwi(mitk::DataNode* imageNode)
{
bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast<mitk::Image *>(imageNode->GetData())) );
if ( !isDiffusionImage )
{
return;
}
UpdateParametersFromGui();
mitk::Image::Pointer diffImg = dynamic_cast<mitk::Image*>(imageNode->GetData());
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(diffImg, itkVectorImagePointer);
m_TractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New();
m_Parameters.m_Misc.m_ParentNode = imageNode;
m_Parameters.m_SignalGen.m_SignalScale = 1;
m_Parameters.m_Misc.m_ResultNode->SetName("b"+QString::number(m_Parameters.m_SignalGen.GetBvalue()).toStdString()
+"_"+m_Parameters.m_Misc.m_SignalModelString
+m_Parameters.m_Misc.m_ArtifactModelString);
m_Parameters.ApplyDirectionMatrix();
m_TractsToDwiFilter->SetParameters(m_Parameters);
m_TractsToDwiFilter->SetInputImage(itkVectorImagePointer);
m_Thread.start(QThread::LowestPriority);
}
void QmitkFiberfoxView::SimulateImageFromFibers(mitk::DataNode* fiberNode)
{
mitk::FiberBundle::Pointer fiberBundle = dynamic_cast<mitk::FiberBundle*>(fiberNode->GetData());
if (fiberBundle->GetNumFibers()<=0) { return; }
UpdateParametersFromGui();
m_TractsToDwiFilter = itk::TractsToDWIImageFilter< short >::New();
m_Parameters.m_Misc.m_ParentNode = fiberNode;
m_Parameters.m_Misc.m_ResultNode->SetName("b"+QString::number(m_Parameters.m_SignalGen.GetBvalue()).toStdString()
+"_"+m_Parameters.m_Misc.m_SignalModelString
+m_Parameters.m_Misc.m_ArtifactModelString);
if ( m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull()
&& mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast<mitk::Image*>
(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()) ) )
{
bool first = true;
bool ok = true;
mitk::Image::Pointer diffImg = dynamic_cast<mitk::Image*>(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData());
itk::Image< itk::DiffusionTensor3D< double >, 3 >::Pointer tensorImage = nullptr;
const int shOrder = 2;
typedef itk::AnalyticalDiffusionQballReconstructionImageFilter<short,short,float,shOrder,ODF_SAMPLING_SIZE> QballFilterType;
QballFilterType::CoefficientImageType::Pointer itkFeatureImage = nullptr;
ItkDoubleImgType::Pointer adcImage = nullptr;
for (unsigned int i=0; i<m_Parameters.m_FiberModelList.size()+m_Parameters.m_NonFiberModelList.size(); i++)
{
mitk::RawShModel<>* model = nullptr;
if (i<m_Parameters.m_FiberModelList.size())
model = dynamic_cast< mitk::RawShModel<>* >(m_Parameters.m_FiberModelList.at(i));
else
model = dynamic_cast< mitk::RawShModel<>* >(m_Parameters.m_NonFiberModelList.at(i-m_Parameters.m_FiberModelList.size()));
if (model!=0 && model->GetNumberOfKernels()<=0)
{
if (first==true)
{
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(diffImg, itkVectorImagePointer);
typedef itk::DiffusionTensor3DReconstructionImageFilter< short, short, double > TensorReconstructionImageFilterType;
TensorReconstructionImageFilterType::Pointer filter = TensorReconstructionImageFilterType::New();
filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImg));
filter->SetGradientImage(mitk::DiffusionPropertyHelper::GetGradientContainer(diffImg),
itkVectorImagePointer );
filter->Update();
tensorImage = filter->GetOutput();
QballFilterType::Pointer qballfilter = QballFilterType::New();
qballfilter->SetGradientImage(mitk::DiffusionPropertyHelper::GetGradientContainer(diffImg),
itkVectorImagePointer );
qballfilter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImg));
qballfilter->SetLambda(0.006);
qballfilter->SetNormalizationMethod(QballFilterType::QBAR_RAW_SIGNAL);
qballfilter->Update();
itkFeatureImage = qballfilter->GetCoefficientImage();
itk::AdcImageFilter< short, double >::Pointer adcFilter = itk::AdcImageFilter< short, double >::New();
adcFilter->SetInput( itkVectorImagePointer );
adcFilter->SetGradientDirections(mitk::DiffusionPropertyHelper::GetGradientContainer(diffImg));
adcFilter->SetB_value(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImg));
adcFilter->Update();
adcImage = adcFilter->GetOutput();
}
ok = model->SampleKernels(diffImg, m_Parameters.m_SignalGen.m_MaskImage, tensorImage, itkFeatureImage, adcImage);
if (!ok)
break;
}
}
if (!ok)
{
QMessageBox::information( nullptr, "Simulation cancelled", "No valid prototype signals could be sampled.");
return;
}
}
else if ( m_Controls->m_Compartment1Box->currentIndex()==3
|| m_Controls->m_Compartment3Box->currentIndex()==3
|| m_Controls->m_Compartment4Box->currentIndex()==4 )
{
QMessageBox::information( nullptr, "Simulation cancelled",
"Prototype signal but no diffusion-weighted image selected to sample signal from.");
return;
}
m_Parameters.ApplyDirectionMatrix();
m_TractsToDwiFilter->SetParameters(m_Parameters);
m_TractsToDwiFilter->SetFiberBundle(fiberBundle);
m_Thread.start(QThread::LowestPriority);
}
void QmitkFiberfoxView::SetBvalsEdit()
{
// SELECT FOLDER DIALOG
std::string filename;
filename = QFileDialog::getOpenFileName(nullptr, "Select bvals file", QString(filename.c_str())).toStdString();
if (filename.empty())
m_Controls->m_LoadBvalsEdit->setText("-");
else
m_Controls->m_LoadBvalsEdit->setText(QString(filename.c_str()));
}
void QmitkFiberfoxView::SetBvecsEdit()
{
// SELECT FOLDER DIALOG
std::string filename;
filename = QFileDialog::getOpenFileName(nullptr, "Select bvecs file", QString(filename.c_str())).toStdString();
if (filename.empty())
m_Controls->m_LoadBvecsEdit->setText("-");
else
m_Controls->m_LoadBvecsEdit->setText(QString(filename.c_str()));
}
void QmitkFiberfoxView::SetOutputPath()
{
// SELECT FOLDER DIALOG
std::string outputPath;
outputPath = QFileDialog::getExistingDirectory(nullptr, "Save images to...", QString(outputPath.c_str())).toStdString();
if (outputPath.empty())
m_Controls->m_SavePathEdit->setText("-");
else
{
outputPath += "/";
m_Controls->m_SavePathEdit->setText(QString(outputPath.c_str()));
}
}
void QmitkFiberfoxView::UpdateGui()
{
OnTlineChanged();
m_Controls->m_GeometryFrame->setEnabled(true);
m_Controls->m_GeometryMessage->setVisible(false);
m_Controls->m_DiffusionPropsMessage->setVisible(false);
m_Controls->m_LoadGradientsFrame->setVisible(false);
m_Controls->m_GenerateGradientsFrame->setVisible(false);
if (m_Controls->m_UseBvalsBvecsBox->isChecked())
m_Controls->m_LoadGradientsFrame->setVisible(true);
else
m_Controls->m_GenerateGradientsFrame->setVisible(true);
// Signal generation gui
if (m_Controls->m_MaskComboBox->GetSelectedNode().IsNotNull() || m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull())
{
m_Controls->m_GeometryMessage->setVisible(true);
m_Controls->m_GeometryFrame->setEnabled(false);
}
if ( m_Controls->m_TemplateComboBox->GetSelectedNode().IsNotNull()
&& mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(
dynamic_cast<mitk::Image*>(m_Controls->m_TemplateComboBox->GetSelectedNode()->GetData()) ) )
{
m_Controls->m_DiffusionPropsMessage->setVisible(true);
m_Controls->m_GeometryMessage->setVisible(true);
m_Controls->m_GeometryFrame->setEnabled(false);
m_Controls->m_LoadGradientsFrame->setVisible(false);
m_Controls->m_GenerateGradientsFrame->setVisible(false);
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.h
index 44bf38c..60e6aef 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFiberfoxView.h
@@ -1,173 +1,173 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <berryISelectionListener.h>
#include <berryIStructuredSelection.h>
#include <QmitkAbstractView.h>
#include "ui_QmitkFiberfoxViewControls.h"
#include <itkVectorImage.h>
#include <itkVectorContainer.h>
#include <itkOrientationDistributionFunction.h>
#ifndef Q_MOC_RUN
#include <mitkFiberBundle.h>
#include <mitkPlanarEllipse.h>
#include <mitkDiffusionNoiseModel.h>
#include <mitkDiffusionSignalModel.h>
#include <mitkRicianNoiseModel.h>
#include <itkTractsToDWIImageFilter.h>
#include <mitkTensorModel.h>
#include <mitkBallModel.h>
#include <mitkStickModel.h>
#include <mitkAstroStickModel.h>
#include <mitkDotModel.h>
#include <mitkFiberfoxParameters.h>
#include <itkStatisticsImageFilter.h>
#include <mitkDiffusionPropertyHelper.h>
#endif
#include <QThread>
#include <QObject>
#include <QTimer>
#include <QTime>
/*!
\brief View for fiber based diffusion software phantoms (Fiberfox). See "Fiberfox: Facilitating the creation of realistic white matter software phantoms" (DOI: 10.1002/mrm.25045) for details.
*/
// Forward Qt class declarations
class QmitkFiberfoxView;
class QmitkFiberfoxWorker : public QObject
{
Q_OBJECT
public:
QmitkFiberfoxWorker(QmitkFiberfoxView* view);
public slots:
void run();
private:
QmitkFiberfoxView* m_View;
};
class QmitkFiberfoxView : public QmitkAbstractView
{
// 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;
QmitkFiberfoxView();
virtual ~QmitkFiberfoxView();
virtual void CreateQtPartControl(QWidget *parent) override;
void SetFocus() override;
typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType;
typedef itk::Vector<double,3> GradientType;
typedef std::vector<GradientType> GradientListType;
typedef itk::VectorImage< short, 3 > ItkDwiType;
typedef itk::Image<double, 3> ItkDoubleImgType;
typedef itk::Image<float, 3> ItkFloatImgType;
typedef itk::Image<unsigned char, 3> ItkUcharImgType;
template<int ndirs> std::vector<itk::Vector<double,3> > MakeGradientList();
protected slots:
void SetOutputPath(); ///< path where image is automatically saved to after the simulation is finished
void LoadParameters(); ///< load fiberfox parameters
void SaveParameters(); ///< save fiberfox parameters
void SetBvalsEdit();
void SetBvecsEdit();
void BeforeThread();
void AfterThread();
void KillThread(); ///< abort simulation
void UpdateSimulationStatus(); ///< print simulation progress and satus messages
void GenerateImage(); ///< start image simulation
void Comp1ModelFrameVisibility(int index); ///< only show parameters of selected signal model for compartment 1
void Comp2ModelFrameVisibility(int index); ///< only show parameters of selected signal model for compartment 2
void Comp3ModelFrameVisibility(int index); ///< only show parameters of selected signal model for compartment 3
void Comp4ModelFrameVisibility(int index); ///< only show parameters of selected signal model for compartment 4
void ShowAdvancedOptions(int state);
/** update GUI elements */
void OnAddNoise(int value);
void OnAddGhosts(int value);
void OnAddDistortions(int value);
void OnAddEddy(int value);
void OnAddSpikes(int value);
void OnAddAliasing(int value);
void OnAddMotion(int value);
void OnAddDrift(int value);
void OnAddRinging(int value);
void OnMaskSelected(int value);
void OnFibSelected(int value);
void OnTemplateSelected(int value);
void OnBvalsBvecsCheck(int value);
void OnTlineChanged();
protected:
GradientListType GenerateHalfShell(int NPoints); ///< generate vectors distributed over the halfsphere
Ui::QmitkFiberfoxViewControls* m_Controls;
void SimulateForExistingDwi(mitk::DataNode* imageNode); ///< add artifacts to existing diffusion weighted image
void SimulateImageFromFibers(mitk::DataNode* fiberNode); ///< simulate new diffusion weighted image
void UpdateParametersFromGui(); ///< update fiberfox paramater object
void UpdateGui(); ///< enable/disbale buttons etc. according to current datamanager selection
void PlanarFigureSelected( itk::Object* object, const itk::EventObject& );
void EnableCrosshairNavigation(); ///< enable crosshair navigation if planar figure interaction ends
void DisableCrosshairNavigation(); ///< disable crosshair navigation if planar figure interaction starts
void SaveParameters(QString filename);
mitk::DataNode::Pointer m_SelectedImageNode;
QString m_ParameterFile; ///< parameter file name
// GUI thread
QmitkFiberfoxWorker m_Worker; ///< runs filter
QThread m_Thread; ///< worker thread
bool m_ThreadIsRunning;
QTimer* m_SimulationTimer;
QTime m_SimulationTime;
QString m_SimulationStatusText;
/** Image filters that do all the simulations. */
itk::TractsToDWIImageFilter< short >::Pointer m_TractsToDwiFilter;
friend class QmitkFiberfoxWorker;
FiberfoxParameters m_Parameters;
};
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFieldmapGeneratorView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFieldmapGeneratorView.cpp
index ae8196d..fa73f73 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFieldmapGeneratorView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFieldmapGeneratorView.cpp
@@ -1,274 +1,274 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// MITK
#include "QmitkFieldmapGeneratorView.h"
#include <QmitkDataStorageComboBox.h>
#include <mitkNodePredicateDataType.h>
#include <itkFieldmapGeneratorFilter.h>
#include <mitkImage.h>
#include <mitkSliceNavigationController.h>
#include <QmitkRenderWindow.h>
const std::string QmitkFieldmapGeneratorView::VIEW_ID = "org.mitk.views.fieldmapgenerator";
QmitkFieldmapGeneratorView::QmitkFieldmapGeneratorView()
: QmitkAbstractView()
, m_Controls( 0 )
{
}
QmitkFieldmapGeneratorView::~QmitkFieldmapGeneratorView()
{
}
void QmitkFieldmapGeneratorView::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::QmitkFieldmapGeneratorViewControls;
m_Controls->setupUi( parent );
m_Controls->m_SelectedImageBox->SetDataStorage(this->GetDataStorage());
mitk::TNodePredicateDataType<mitk::Image>::Pointer isMitkImage = mitk::TNodePredicateDataType<mitk::Image>::New();
m_Controls->m_SelectedImageBox->SetPredicate(isMitkImage);
m_SliceChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart());
connect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged()));
connect((QObject*) m_Controls->m_GenerateFieldmap, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateFieldmap()));
connect((QObject*) m_Controls->m_PlaceFieldSource, SIGNAL(clicked()), (QObject*) this, SLOT(PlaceFieldSource()));
connect((QObject*) m_Controls->m_SourceVarianceBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnVarianceChanged(double)));
connect((QObject*) m_Controls->m_SourceHeightBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnHeightChanged(double)));
}
}
void QmitkFieldmapGeneratorView::SetFocus()
{
m_Controls->m_SelectedImageBox->setFocus();
}
void QmitkFieldmapGeneratorView::OnVarianceChanged(double value)
{
if (m_SelectedSource.IsNotNull())
{
m_SelectedSource->SetProperty("pointsize", mitk::FloatProperty::New(value));
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkFieldmapGeneratorView::OnHeightChanged(double value)
{
if (m_SelectedSource.IsNotNull())
{
m_SelectedSource->SetProperty("color", mitk::ColorProperty::New(0, 0, value/100.0));
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkFieldmapGeneratorView::PlaceFieldSource()
{
if (m_Controls->m_SelectedImageBox->GetSelectedNode().IsNull() || !this->GetRenderWindowPart())
{
m_Controls->m_WorldPosLabel->setText("-");
m_Controls->m_IndexLabel->setText("-");
return;
}
mitk::Point3D index;
mitk::Image::Pointer img = dynamic_cast<mitk::Image*>(m_Controls->m_SelectedImageBox->GetSelectedNode()->GetData());
mitk::BaseGeometry* geom = img->GetGeometry();
if ( geom->IsInside(m_WorldPoint) )
{
img->GetGeometry()->WorldToIndex(m_WorldPoint, index);
mitk::PointSet::Pointer pointSet = mitk::PointSet::New();
pointSet->InsertPoint(0, m_WorldPoint);
mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_Controls->m_SelectedImageBox->GetSelectedNode());
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(pointSet);
QString name = QString("FieldSource_%1").arg(children->size());
node->SetName(name.toStdString());
node->SetVisibility(true);
float minSpacing;
if(geom->GetSpacing()[0]<geom->GetSpacing()[1] && geom->GetSpacing()[0]<geom->GetSpacing()[2])
minSpacing = geom->GetSpacing()[0];
else if (geom->GetSpacing()[1] < geom->GetSpacing()[2])
minSpacing = geom->GetSpacing()[1];
else
minSpacing = geom->GetSpacing()[2];
node->SetProperty("pointsize", mitk::FloatProperty::New(minSpacing*5));
node->SetProperty("color", mitk::ColorProperty::New(0, 0, 1));
GetDataStorage()->Add(node, m_Controls->m_SelectedImageBox->GetSelectedNode());
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkFieldmapGeneratorView::GenerateFieldmap()
{
if (m_Controls->m_SelectedImageBox->GetSelectedNode().IsNull())
return;
mitk::Image::Pointer img = dynamic_cast<mitk::Image*>(m_Controls->m_SelectedImageBox->GetSelectedNode()->GetData());
mitk::BaseGeometry* geom = img->GetGeometry();
typedef itk::Image< double, 3 > FieldMapType;
itk::Vector<double> spacing; ///< output image spacing
mitk::Point3D origin; ///< output image origin
itk::FieldmapGeneratorFilter< FieldMapType >::MatrixType directionMatrix; ///< output image rotation
itk::FieldmapGeneratorFilter< FieldMapType >::OutputImageRegionType imageRegion; ///< output image size
spacing = geom->GetSpacing();
origin = geom->GetOrigin();
imageRegion.SetSize(0, img->GetDimension(0));
imageRegion.SetSize(1, img->GetDimension(1));
imageRegion.SetSize(2, img->GetDimension(2));
for (int r=0; r<3; r++)
for (int c=0; c<3; c++)
directionMatrix[r][c]=geom->GetMatrixColumn(c)[r]/spacing[c];
std::vector< double > variances;
std::vector< double > heights;
std::vector< mitk::Point3D > worldPositions;
mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_Controls->m_SelectedImageBox->GetSelectedNode());
for( mitk::DataStorage::SetOfObjects::const_iterator it = children->begin(); it != children->end(); ++it )
if(dynamic_cast<mitk::PointSet*>((*it)->GetData()))
{
float var = 0; (*it)->GetPropertyValue("pointsize", var); variances.push_back(var);
float color[3]; (*it)->GetColor(color); heights.push_back(color[2]*100);
mitk::PointSet* ps = dynamic_cast<mitk::PointSet*>((*it)->GetData());
mitk::Point3D point;
ps->GetPointIfExists(0, &point);
worldPositions.push_back(point);
}
vnl_vector_fixed< double, 3 > gradient, offset;
gradient[0] = m_Controls->m_xGradientBox->value();
gradient[1] = m_Controls->m_yGradientBox->value();
gradient[2] = m_Controls->m_zGradientBox->value();
offset[0] = m_Controls->m_xOffsetBox->value();
offset[1] = m_Controls->m_yOffsetBox->value();
offset[2] = m_Controls->m_zOffsetBox->value();
itk::FieldmapGeneratorFilter< FieldMapType >::Pointer filter = itk::FieldmapGeneratorFilter< FieldMapType >::New();
filter->SetHeights(heights);
filter->SetVariances(variances);
filter->SetWorldPositions(worldPositions);
filter->SetSpacing(spacing);
filter->SetOrigin(origin);
filter->SetDirectionMatrix(directionMatrix);
filter->SetImageRegion(imageRegion);
filter->SetGradient(gradient);
filter->SetOffset(offset);
filter->Update();
mitk::DataNode::Pointer resultNode = mitk::DataNode::New();
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk(filter->GetOutput(0));
image->SetVolume(filter->GetOutput(0)->GetBufferPointer());
resultNode->SetData( image );
resultNode->SetName(m_Controls->m_SelectedImageBox->GetSelectedNode()->GetName()+"_Fieldmap");
GetDataStorage()->Add(resultNode);
}
void QmitkFieldmapGeneratorView::Visible()
{
}
void QmitkFieldmapGeneratorView::Hidden()
{
}
void QmitkFieldmapGeneratorView::Activated()
{
m_SliceChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart());
connect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged()));
}
void QmitkFieldmapGeneratorView::Deactivated()
{
}
void QmitkFieldmapGeneratorView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList<mitk::DataNode::Pointer>& nodes)
{
if (m_Controls->m_SelectedImageBox->GetSelectedNode().IsNotNull())
m_Controls->m_SelectedImageBox->GetSelectedNode()->RemoveObserver( m_PropertyObserverTag );
m_Controls->m_InputData->setTitle("Please Select Reference Image");
m_SelectedSource = nullptr;
// iterate selection
for (mitk::DataNode::Pointer node: nodes)
{
if ( node.IsNotNull() && (dynamic_cast<mitk::PointSet*>(node->GetData())) )
{
m_Controls->m_SourceNameLabel->setText(node->GetName().c_str());
m_SelectedSource = node;
float variance = 0; node->GetPropertyValue("pointsize", variance);
m_Controls->m_SourceVarianceBox->setValue(variance);
float color[3]; node->GetColor(color);
m_Controls->m_SourceHeightBox->setValue(color[2]*100);
}
}
if (m_Controls->m_SelectedImageBox->GetSelectedNode().IsNotNull())
{
m_Controls->m_InputData->setTitle("Reference Image");
}
}
void QmitkFieldmapGeneratorView::OnSliceChanged()
{
if (m_Controls->m_SelectedImageBox->GetSelectedNode().IsNull() || !this->GetRenderWindowPart())
{
m_Controls->m_WorldPosLabel->setText("-");
m_Controls->m_IndexLabel->setText("-");
return;
}
m_WorldPoint = this->GetRenderWindowPart()->GetSelectedPosition();
QString posSting = QString::number(m_WorldPoint[0]); posSting += ", "; posSting += QString::number(m_WorldPoint[1]); posSting += ", "; posSting += QString::number(m_WorldPoint[2]);
m_Controls->m_WorldPosLabel->setText(posSting.toStdString().c_str());
mitk::Point3D index;
mitk::Image::Pointer img = dynamic_cast<mitk::Image*>(m_Controls->m_SelectedImageBox->GetSelectedNode()->GetData());
if ( m_Controls->m_SelectedImageBox->GetSelectedNode()->GetData()->GetGeometry()->IsInside(m_WorldPoint) )
{
img->GetGeometry()->WorldToIndex(m_WorldPoint, index);
posSting = QString::number(index[0]); posSting += ", "; posSting += QString::number(index[1]); posSting += ", "; posSting += QString::number(index[2]);
m_Controls->m_IndexLabel->setText(posSting.toStdString().c_str());
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFieldmapGeneratorView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFieldmapGeneratorView.h
index 349ac32..c5db129 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFieldmapGeneratorView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/QmitkFieldmapGeneratorView.h
@@ -1,86 +1,86 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _QMITKQmitkFieldmapGeneratorView_H_INCLUDED
#define _QMITKQmitkFieldmapGeneratorView_H_INCLUDED
#include <berryISelectionListener.h>
#include <QmitkAbstractView.h>
#include <mitkIRenderWindowPartListener.h>
#include "ui_QmitkFieldmapGeneratorViewControls.h"
#include <mitkPointSet.h>
#include <itkImage.h>
#include "mitkILifecycleAwarePart.h"
#include <QmitkSliceNavigationListener.h>
/*!
\brief Generate float image with artificial frequency maps used by Fiberfox. Simulates additional frequencies at (possibly multiple) positions based on 3D gaussians with the specified variance and amplitude and/or as a linear gradient in the image.
* See "Fiberfox: Facilitating the creation of realistic white matter software phantoms" (DOI: 10.1002/mrm.25045) for details.
*/
class QmitkFieldmapGeneratorView : 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;
QmitkFieldmapGeneratorView();
virtual ~QmitkFieldmapGeneratorView();
virtual void CreateQtPartControl(QWidget *parent) override;
virtual void SetFocus() override;
virtual void Activated() override;
virtual void Deactivated() override;
virtual void Visible() override;
virtual void Hidden() override;
protected slots:
void GenerateFieldmap();
void PlaceFieldSource();
void OnVarianceChanged(double value);
void OnHeightChanged(double value);
void OnSliceChanged();
protected:
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
Ui::QmitkFieldmapGeneratorViewControls* m_Controls;
/** observer flags */
int m_SliceObserverTag1;
int m_SliceObserverTag2;
int m_SliceObserverTag3;
int m_PropertyObserverTag;
mitk::Point3D m_WorldPoint;
mitk::DataNode::Pointer m_SelectedSource;
QmitkSliceNavigationListener m_SliceChangeListener;
};
#endif // _QmitkFieldmapGeneratorView_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/mitkPluginActivator.cpp
index 6bcdb97..a7be007 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/mitkPluginActivator.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/mitkPluginActivator.cpp
@@ -1,46 +1,46 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPluginActivator.h"
#include "src/internal/Perspectives/QmitkDIAppSyntheticDataGenerationPerspective.h"
#include "src/internal/QmitkFiberfoxView.h"
#include "src/internal/QmitkFiberGenerationView.h"
#include "src/internal/QmitkFieldmapGeneratorView.h"
ctkPluginContext* mitk::PluginActivator::m_Context = nullptr;
ctkPluginContext* mitk::PluginActivator::GetContext()
{
return m_Context;
}
void mitk::PluginActivator::start(ctkPluginContext* context)
{
BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppSyntheticDataGenerationPerspective, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberfoxView, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkFieldmapGeneratorView, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberGenerationView, context)
m_Context = context;
}
void mitk::PluginActivator::stop(ctkPluginContext* context)
{
Q_UNUSED(context)
m_Context = nullptr;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/mitkPluginActivator.h
index d68a5f4..eee3d42 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/mitkPluginActivator.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberfox/src/internal/mitkPluginActivator.h
@@ -1,40 +1,40 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKPLUGINACTIVATOR_H
#define MITKPLUGINACTIVATOR_H
#include <ctkPluginActivator.h>
namespace mitk
{
class PluginActivator : public QObject, public ctkPluginActivator
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.mitk.gui.qt.diffusionimaging.fiberfox")
Q_INTERFACES(ctkPluginActivator)
public:
static ctkPluginContext* GetContext();
void start(ctkPluginContext* context) override;
void stop(ctkPluginContext* context) override;
private:
static ctkPluginContext* m_Context;
};
}
#endif
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/Perspectives/QmitkFiberProcessingPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/Perspectives/QmitkFiberProcessingPerspective.cpp
index 4f10e8d..5cea14d 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/Perspectives/QmitkFiberProcessingPerspective.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/Perspectives/QmitkFiberProcessingPerspective.cpp
@@ -1,51 +1,51 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkFiberProcessingPerspective.h"
#include "berryIViewLayout.h"
void QmitkFiberProcessingPerspective::CreateInitialLayout(berry::IPageLayout::Pointer layout)
{
/////////////////////////////////////////////////////
// all di-app perspectives should have the following:
/////////////////////////////////////////////////////
QString editorArea = layout->GetEditorArea();
layout->AddStandaloneViewPlaceholder("org.mitk.views.viewnavigatorview", berry::IPageLayout::LEFT, 0.3f, editorArea, false);
layout->AddStandaloneView("org.mitk.views.datamanager",
false, berry::IPageLayout::LEFT, 0.3f, editorArea);
layout->AddStandaloneView("org.mitk.views.controlvisualizationpropertiesview",
false, berry::IPageLayout::BOTTOM, .15f, "org.mitk.views.datamanager");
berry::IFolderLayout::Pointer left =
layout->CreateFolder("org.mbi.diffusionimaginginternal.leftcontrols",
berry::IPageLayout::BOTTOM, 0.15f, "org.mitk.views.controlvisualizationpropertiesview");
layout->AddStandaloneViewPlaceholder("org.mitk.views.imagenavigator",
berry::IPageLayout::BOTTOM, .7f, "org.mbi.diffusionimaginginternal.leftcontrols", false);
/////////////////////////////////////////////
// here goes the perspective specific stuff
/////////////////////////////////////////////
left->AddView("org.mitk.views.fiberprocessing");
left->AddView("org.mitk.views.fiberquantification");
left->AddView("org.mitk.views.fiberclustering");
left->AddView("org.mitk.views.fiberfit");
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/Perspectives/QmitkFiberProcessingPerspective.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/Perspectives/QmitkFiberProcessingPerspective.h
index 3795486..66b08f9 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/Perspectives/QmitkFiberProcessingPerspective.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/Perspectives/QmitkFiberProcessingPerspective.h
@@ -1,36 +1,36 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkFiberProcessingPerspective_H_
#define QmitkFiberProcessingPerspective_H_
#include <berryIPerspectiveFactory.h>
class QmitkFiberProcessingPerspective : public QObject, public berry::IPerspectiveFactory
{
Q_OBJECT
Q_INTERFACES(berry::IPerspectiveFactory)
public:
QmitkFiberProcessingPerspective() {}
~QmitkFiberProcessingPerspective() {}
void CreateInitialLayout(berry::IPageLayout::Pointer layout) override;
};
#endif /* QmitkFiberProcessingPerspective_H_ */
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringView.cpp
index 3a1cbc6..4a642f2 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringView.cpp
@@ -1,232 +1,232 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
#include "QmitkFiberClusteringView.h"
#include <mitkNodePredicateDataType.h>
#include <mitkNodePredicateDimension.h>
#include <mitkNodePredicateAnd.h>
#include <mitkImageCast.h>
#include <mitkImageAccessByItk.h>
#include <itkTractClusteringFilter.h>
#include <mitkFiberBundle.h>
#include <mitkClusteringMetricEuclideanMean.h>
#include <mitkClusteringMetricEuclideanMax.h>
#include <mitkClusteringMetricEuclideanStd.h>
#include <mitkClusteringMetricAnatomic.h>
#include <mitkClusteringMetricScalarMap.h>
#include <mitkClusteringMetricInnerAngles.h>
#include <mitkClusteringMetricLength.h>
#include <QMessageBox>
const std::string QmitkFiberClusteringView::VIEW_ID = "org.mitk.views.fiberclustering";
using namespace mitk;
QmitkFiberClusteringView::QmitkFiberClusteringView()
: QmitkAbstractView()
, m_Controls( nullptr )
{
}
// Destructor
QmitkFiberClusteringView::~QmitkFiberClusteringView()
{
}
void QmitkFiberClusteringView::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::QmitkFiberClusteringViewControls;
m_Controls->setupUi( parent );
connect( m_Controls->m_StartButton, SIGNAL(clicked()), this, SLOT(StartClustering()) );
connect( m_Controls->m_TractBox, SIGNAL(currentIndexChanged(int)), this, SLOT(FiberSelectionChanged()) );
mitk::TNodePredicateDataType<mitk::FiberBundle>::Pointer isFib = mitk::TNodePredicateDataType<mitk::FiberBundle>::New();
m_Controls->m_TractBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_TractBox->SetPredicate(isFib);
m_Controls->m_InCentroidsBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_InCentroidsBox->SetPredicate(isFib);
m_Controls->m_InCentroidsBox->SetZeroEntryText("--");
mitk::TNodePredicateDataType<mitk::Image>::Pointer imageP = mitk::TNodePredicateDataType<mitk::Image>::New();
mitk::NodePredicateDimension::Pointer dimP = mitk::NodePredicateDimension::New(3);
m_Controls->m_MapBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_MapBox->SetPredicate(mitk::NodePredicateAnd::New(imageP, dimP));
m_Controls->m_ParcellationBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_ParcellationBox->SetPredicate(mitk::NodePredicateAnd::New(imageP, dimP));
m_Controls->m_MetricBox6->setVisible(false);
m_Controls->m_MetricWeight6->setVisible(false);
FiberSelectionChanged();
}
}
void QmitkFiberClusteringView::SetFocus()
{
FiberSelectionChanged();
}
void QmitkFiberClusteringView::FiberSelectionChanged()
{
if (m_Controls->m_TractBox->GetSelectedNode().IsNull())
m_Controls->m_StartButton->setEnabled(false);
else
m_Controls->m_StartButton->setEnabled(true);
}
void QmitkFiberClusteringView::StartClustering()
{
if (m_Controls->m_TractBox->GetSelectedNode().IsNull())
return;
mitk::DataNode::Pointer node = m_Controls->m_TractBox->GetSelectedNode();
float clusterSize = m_Controls->m_ClusterSizeBox->value();
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
float max_d = 0;
int i=1;
std::vector< float > distances;
while (max_d < fib->GetGeometry()->GetDiagonalLength()/2)
{
distances.push_back(clusterSize*i);
max_d = clusterSize*i;
++i;
}
itk::TractClusteringFilter::Pointer clusterer = itk::TractClusteringFilter::New();
clusterer->SetDistances(distances);
clusterer->SetTractogram(fib);
if (m_Controls->m_InCentroidsBox->GetSelectedNode().IsNotNull())
{
mitk::FiberBundle::Pointer in_centroids = dynamic_cast<mitk::FiberBundle*>(m_Controls->m_InCentroidsBox->GetSelectedNode()->GetData());
clusterer->SetInCentroids(in_centroids);
}
std::vector< mitk::ClusteringMetric* > metrics;
if (m_Controls->m_MetricBox1->isChecked())
{
mitk::ClusteringMetricEuclideanMean* metric = new mitk::ClusteringMetricEuclideanMean();
metric->SetScale(m_Controls->m_MetricWeight1->value());
metrics.push_back(metric);
}
if (m_Controls->m_MetricBox2->isChecked())
{
mitk::ClusteringMetricEuclideanStd* metric = new mitk::ClusteringMetricEuclideanStd();
metric->SetScale(m_Controls->m_MetricWeight2->value());
metrics.push_back(metric);
}
if (m_Controls->m_MetricBox3->isChecked())
{
mitk::ClusteringMetricEuclideanMax* metric = new mitk::ClusteringMetricEuclideanMax();
metric->SetScale(m_Controls->m_MetricWeight3->value());
metrics.push_back(metric);
}
if (m_Controls->m_MetricBox6->isChecked())
{
mitk::ClusteringMetricInnerAngles* metric = new mitk::ClusteringMetricInnerAngles();
metric->SetScale(m_Controls->m_MetricWeight6->value());
metrics.push_back(metric);
}
if (m_Controls->m_MetricBox7->isChecked())
{
mitk::ClusteringMetricLength* metric = new mitk::ClusteringMetricLength();
metric->SetScale(m_Controls->m_MetricWeight7->value());
metrics.push_back(metric);
}
if (m_Controls->m_ParcellationBox->GetSelectedNode().IsNotNull() && m_Controls->m_MetricBox4->isChecked())
{
mitk::Image::Pointer mitk_map = dynamic_cast<mitk::Image*>(m_Controls->m_ParcellationBox->GetSelectedNode()->GetData());
ShortImageType::Pointer itk_map = ShortImageType::New();
mitk::CastToItkImage(mitk_map, itk_map);
mitk::ClusteringMetricAnatomic* metric = new mitk::ClusteringMetricAnatomic();
metric->SetParcellations({itk_map});
metric->SetScale(m_Controls->m_MetricWeight4->value());
metrics.push_back(metric);
}
if (m_Controls->m_MapBox->GetSelectedNode().IsNotNull() && m_Controls->m_MetricBox5->isChecked())
{
mitk::Image::Pointer mitk_map = dynamic_cast<mitk::Image*>(m_Controls->m_MapBox->GetSelectedNode()->GetData());
FloatImageType::Pointer itk_map = FloatImageType::New();
mitk::CastToItkImage(mitk_map, itk_map);
mitk::ClusteringMetricScalarMap* metric = new mitk::ClusteringMetricScalarMap();
metric->SetImages({itk_map});
metric->SetScale(m_Controls->m_MetricWeight5->value());
metrics.push_back(metric);
}
if (metrics.empty())
{
QMessageBox::warning(nullptr, "Warning", "No metric selected!");
return;
}
clusterer->SetMetrics(metrics);
clusterer->SetMergeDuplicateThreshold(m_Controls->m_MergeDuplicatesBox->value());
clusterer->SetNumPoints(m_Controls->m_FiberPointsBox->value());
clusterer->SetMaxClusters(m_Controls->m_MaxClustersBox->value());
clusterer->SetMinClusterSize(m_Controls->m_MinFibersBox->value());
clusterer->Update();
std::vector<mitk::FiberBundle::Pointer> tracts = clusterer->GetOutTractograms();
std::vector<mitk::FiberBundle::Pointer> centroids = clusterer->GetOutCentroids();
unsigned int c = 0;
for (auto f : tracts)
{
mitk::DataNode::Pointer new_node = mitk::DataNode::New();
new_node->SetData(f);
new_node->SetName("Cluster_" + boost::lexical_cast<std::string>(c));
if (m_Controls->m_InCentroidsBox->GetSelectedNode().IsNotNull())
this->GetDataStorage()->Add(new_node, m_Controls->m_InCentroidsBox->GetSelectedNode());
else
this->GetDataStorage()->Add(new_node, node);
node->SetVisibility(false);
if (m_Controls->m_CentroidsBox->isChecked())
{
mitk::DataNode::Pointer new_node2 = mitk::DataNode::New();
new_node2->SetData(centroids.at(c));
new_node2->SetName("Centroid_" + boost::lexical_cast<std::string>(c));
this->GetDataStorage()->Add(new_node2, new_node);
}
++c;
}
}
void QmitkFiberClusteringView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList<mitk::DataNode::Pointer>& )
{
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringView.h
index a1eb093..1d90d31 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberClusteringView.h
@@ -1,68 +1,68 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkFiberClusteringView_h
#define QmitkFiberClusteringView_h
#include <QmitkAbstractView.h>
#include "ui_QmitkFiberClusteringViewControls.h"
#include <itkImage.h>
/*!
\brief Cluster fibers by shape and image properties
*/
class QmitkFiberClusteringView : public QmitkAbstractView
{
// 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;
QmitkFiberClusteringView();
virtual ~QmitkFiberClusteringView();
virtual void CreateQtPartControl(QWidget *parent) override;
typedef itk::Image< float, 3 > FloatImageType;
typedef itk::Image< short, 3 > ShortImageType;
///
/// Sets the focus to an internal widget.
///
virtual void SetFocus() override;
protected slots:
void StartClustering();
void FiberSelectionChanged();
protected:
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
Ui::QmitkFiberClusteringViewControls* m_Controls;
};
#endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberFitView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberFitView.cpp
index c64ccad..6398aa7 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberFitView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberFitView.cpp
@@ -1,265 +1,265 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
#include "QmitkFiberFitView.h"
#include <mitkNodePredicateDataType.h>
#include <mitkImageCast.h>
#include <mitkImageAccessByItk.h>
#include <mitkImage.h>
#include <mitkPeakImage.h>
#include <mitkFiberBundle.h>
#include <itkFitFibersToImageFilter.h>
#include <mitkDiffusionPropertyHelper.h>
#include <mitkTensorModel.h>
#include <mitkITKImageImport.h>
#include <mitkNodePredicateDimension.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateOr.h>
const std::string QmitkFiberFitView::VIEW_ID = "org.mitk.views.fiberfit";
using namespace mitk;
QmitkFiberFitView::QmitkFiberFitView()
: QmitkAbstractView()
, m_Controls( nullptr )
{
}
// Destructor
QmitkFiberFitView::~QmitkFiberFitView()
{
}
void QmitkFiberFitView::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::QmitkFiberFitViewControls;
m_Controls->setupUi( parent );
connect( m_Controls->m_StartButton, SIGNAL(clicked()), this, SLOT(StartFit()) );
connect( m_Controls->m_ImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(DataSelectionChanged()) );
connect( m_Controls->m_TractBox, SIGNAL(currentIndexChanged(int)), this, SLOT(DataSelectionChanged()) );
mitk::TNodePredicateDataType<mitk::FiberBundle>::Pointer isFib = mitk::TNodePredicateDataType<mitk::FiberBundle>::New();
mitk::TNodePredicateDataType<mitk::Image>::Pointer isImage = mitk::TNodePredicateDataType<mitk::Image>::New();
mitk::NodePredicateDimension::Pointer is3D = mitk::NodePredicateDimension::New(3);
m_Controls->m_TractBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_TractBox->SetPredicate(isFib);
m_Controls->m_ImageBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_ImageBox->SetPredicate( mitk::NodePredicateOr::New( mitk::NodePredicateAnd::New(isImage, is3D), mitk::TNodePredicateDataType<mitk::PeakImage>::New()) );
DataSelectionChanged();
}
}
void QmitkFiberFitView::DataSelectionChanged()
{
if (m_Controls->m_TractBox->GetSelectedNode().IsNull() || m_Controls->m_ImageBox->GetSelectedNode().IsNull())
m_Controls->m_StartButton->setEnabled(false);
else
m_Controls->m_StartButton->setEnabled(true);
}
void QmitkFiberFitView::SetFocus()
{
DataSelectionChanged();
}
void QmitkFiberFitView::StartFit()
{
if (m_Controls->m_TractBox->GetSelectedNode().IsNull() || m_Controls->m_ImageBox->GetSelectedNode().IsNull())
return;
mitk::FiberBundle::Pointer input_tracts = dynamic_cast<mitk::FiberBundle*>(m_Controls->m_TractBox->GetSelectedNode()->GetData())->GetDeepCopy();
mitk::DataNode::Pointer node = m_Controls->m_ImageBox->GetSelectedNode();
itk::FitFibersToImageFilter::Pointer fitter = itk::FitFibersToImageFilter::New();
mitk::Image::Pointer mitk_image = dynamic_cast<mitk::Image*>(node->GetData());
mitk::PeakImage::Pointer mitk_peak_image = dynamic_cast<mitk::PeakImage*>(node->GetData());
if (mitk_peak_image.IsNotNull())
{
typedef mitk::ImageToItk< mitk::PeakImage::ItkPeakImageType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(mitk_peak_image);
caster->Update();
mitk::PeakImage::ItkPeakImageType::Pointer peak_image = caster->GetOutput();
fitter->SetPeakImage(peak_image);
}
else
{
if (mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(mitk_image))
{
fitter->SetDiffImage(mitk::DiffusionPropertyHelper::GetItkVectorImage(mitk_image));
mitk::TensorModel<>* model = new mitk::TensorModel<>();
model->SetBvalue(1000);
model->SetDiffusivity1(0.0010);
model->SetDiffusivity2(0.00015);
model->SetDiffusivity3(0.00015);
model->SetGradientList(mitk::DiffusionPropertyHelper::GetGradientContainer(mitk_image));
fitter->SetSignalModel(model);
}
else
{
itk::FitFibersToImageFilter::DoubleImgType::Pointer scalar_image = itk::FitFibersToImageFilter::DoubleImgType::New();
mitk::CastToItkImage(mitk_image, scalar_image);
fitter->SetScalarImage(scalar_image);
}
}
if (m_Controls->m_ReguTypeBox->currentIndex()==0)
fitter->SetRegularization(VnlCostFunction::REGU::VOXEL_VARIANCE);
else if (m_Controls->m_ReguTypeBox->currentIndex()==1)
fitter->SetRegularization(VnlCostFunction::REGU::VARIANCE);
else if (m_Controls->m_ReguTypeBox->currentIndex()==2)
fitter->SetRegularization(VnlCostFunction::REGU::MSM);
else if (m_Controls->m_ReguTypeBox->currentIndex()==3)
fitter->SetRegularization(VnlCostFunction::REGU::LASSO);
else if (m_Controls->m_ReguTypeBox->currentIndex()==4)
fitter->SetRegularization(VnlCostFunction::REGU::NONE);
fitter->SetTractograms({input_tracts});
fitter->SetFitIndividualFibers(true);
fitter->SetMaxIterations(20);
fitter->SetVerbose(true);
fitter->SetGradientTolerance(1e-5);
fitter->SetLambda(m_Controls->m_ReguBox->value());
fitter->SetFilterOutliers(m_Controls->m_OutliersBox->isChecked());
fitter->Update();
mitk::FiberBundle::Pointer output_tracts = fitter->GetTractograms().at(0);
output_tracts->ColorFibersByFiberWeights(false, true);
mitk::DataNode::Pointer new_node = mitk::DataNode::New();
new_node->SetData(output_tracts);
new_node->SetName("Fitted");
this->GetDataStorage()->Add(new_node, node);
m_Controls->m_TractBox->GetSelectedNode()->SetVisibility(false);
if (m_Controls->m_ResidualsBox->isChecked() && mitk_peak_image.IsNotNull())
{
{
mitk::PeakImage::ItkPeakImageType::Pointer itk_image = fitter->GetFittedImage();
mitk::Image::Pointer mitk_image = dynamic_cast<Image*>(PeakImage::New().GetPointer());
mitk::CastToMitkImage(itk_image, mitk_image);
mitk_image->SetVolume(itk_image->GetBufferPointer());
mitk::DataNode::Pointer new_node = mitk::DataNode::New();
new_node->SetData(mitk_image);
new_node->SetName("Fitted");
this->GetDataStorage()->Add(new_node, node);
}
{
mitk::PeakImage::ItkPeakImageType::Pointer itk_image = fitter->GetResidualImage();
mitk::Image::Pointer mitk_image = dynamic_cast<Image*>(PeakImage::New().GetPointer());
mitk::CastToMitkImage(itk_image, mitk_image);
mitk_image->SetVolume(itk_image->GetBufferPointer());
mitk::DataNode::Pointer new_node = mitk::DataNode::New();
new_node->SetData(mitk_image);
new_node->SetName("Residual");
this->GetDataStorage()->Add(new_node, node);
}
{
mitk::PeakImage::ItkPeakImageType::Pointer itk_image = fitter->GetUnderexplainedImage();
mitk::Image::Pointer mitk_image = dynamic_cast<Image*>(PeakImage::New().GetPointer());
mitk::CastToMitkImage(itk_image, mitk_image);
mitk_image->SetVolume(itk_image->GetBufferPointer());
mitk::DataNode::Pointer new_node = mitk::DataNode::New();
new_node->SetData(mitk_image);
new_node->SetName("Underexplained");
this->GetDataStorage()->Add(new_node, node);
}
{
mitk::PeakImage::ItkPeakImageType::Pointer itk_image = fitter->GetOverexplainedImage();
mitk::Image::Pointer mitk_image = dynamic_cast<Image*>(PeakImage::New().GetPointer());
mitk::CastToMitkImage(itk_image, mitk_image);
mitk_image->SetVolume(itk_image->GetBufferPointer());
mitk::DataNode::Pointer new_node = mitk::DataNode::New();
new_node->SetData(mitk_image);
new_node->SetName("Overexplained");
this->GetDataStorage()->Add(new_node, node);
}
}
else if (m_Controls->m_ResidualsBox->isChecked() && mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(mitk_image))
{
{
mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( fitter->GetFittedImageDiff().GetPointer() );
mitk::DiffusionPropertyHelper::CopyProperties(mitk_image, outImage, true);
mitk::DiffusionPropertyHelper::InitializeImage( outImage );
mitk::DataNode::Pointer new_node = mitk::DataNode::New();
new_node->SetData(outImage);
new_node->SetName("Fitted");
this->GetDataStorage()->Add(new_node, node);
}
{
mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( fitter->GetResidualImageDiff().GetPointer() );
mitk::DiffusionPropertyHelper::CopyProperties(mitk_image, outImage, true);
mitk::DiffusionPropertyHelper::InitializeImage( outImage );
mitk::DataNode::Pointer new_node = mitk::DataNode::New();
new_node->SetData(outImage);
new_node->SetName("Residual");
this->GetDataStorage()->Add(new_node, node);
}
}
else if (m_Controls->m_ResidualsBox->isChecked())
{
{
mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( fitter->GetFittedImageScalar().GetPointer() );
mitk::DataNode::Pointer new_node = mitk::DataNode::New();
new_node->SetData(outImage);
new_node->SetName("Fitted");
this->GetDataStorage()->Add(new_node, node);
}
{
mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( fitter->GetResidualImageScalar().GetPointer() );
mitk::DataNode::Pointer new_node = mitk::DataNode::New();
new_node->SetData(outImage);
new_node->SetName("Residual");
this->GetDataStorage()->Add(new_node, node);
}
}
}
void QmitkFiberFitView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList<mitk::DataNode::Pointer>& )
{
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberFitView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberFitView.h
index 4f39e23..4dfb5fd 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberFitView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberFitView.h
@@ -1,65 +1,65 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkFiberFitView_h
#define QmitkFiberFitView_h
#include <QmitkAbstractView.h>
#include "ui_QmitkFiberFitViewControls.h"
#include <itkImage.h>
/*!
\brief Weight fibers by linearly fitting them to the image data.
*/
class QmitkFiberFitView : public QmitkAbstractView
{
// 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;
QmitkFiberFitView();
virtual ~QmitkFiberFitView();
virtual void CreateQtPartControl(QWidget *parent) override;
///
/// Sets the focus to an internal widget.
///
virtual void SetFocus() override;
protected slots:
void StartFit();
void DataSelectionChanged();
protected:
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
Ui::QmitkFiberFitViewControls* m_Controls;
};
#endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingView.cpp
index b74865e..e2be804 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingView.cpp
@@ -1,1728 +1,1728 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchPart.h>
#include <berryIWorkbenchWindow.h>
// Qmitk
#include "QmitkFiberProcessingView.h"
#include <QMessageBox>
#include <mitkNodePredicateProperty.h>
#include <mitkImageCast.h>
#include <mitkPointSet.h>
#include <mitkPlanarCircle.h>
#include <mitkPlanarPolygon.h>
#include <mitkPlanarRectangle.h>
#include <mitkPlanarFigureInteractor.h>
#include <mitkImageAccessByItk.h>
#include <mitkDataNodeObject.h>
#include <mitkTensorImage.h>
#include "usModuleRegistry.h"
#include <itkFiberCurvatureFilter.h>
#include "mitkNodePredicateDataType.h"
#include <mitkNodePredicateProperty.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateOr.h>
#include <itkResampleImageFilter.h>
#include <itkGaussianInterpolateImageFunction.h>
#include <itkImageRegionIteratorWithIndex.h>
#include <itkTractsToFiberEndingsImageFilter.h>
#include <itkTractDensityImageFilter.h>
#include <itkImageRegion.h>
#include <itkTractsToRgbaImageFilter.h>
#include <itkFiberExtractionFilter.h>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
const std::string QmitkFiberProcessingView::VIEW_ID = "org.mitk.views.fiberprocessing";
const std::string id_DataManager = "org.mitk.views.datamanager";
using namespace mitk;
QmitkFiberProcessingView::QmitkFiberProcessingView()
: QmitkAbstractView()
, m_Controls( 0 )
, m_CircleCounter(0)
, m_PolygonCounter(0)
, m_UpsamplingFactor(1)
{
}
// Destructor
QmitkFiberProcessingView::~QmitkFiberProcessingView()
{
RemoveObservers();
}
void QmitkFiberProcessingView::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::QmitkFiberProcessingViewControls;
m_Controls->setupUi( parent );
connect( m_Controls->m_CircleButton, SIGNAL( clicked() ), this, SLOT( OnDrawCircle() ) );
connect( m_Controls->m_PolygonButton, SIGNAL( clicked() ), this, SLOT( OnDrawPolygon() ) );
connect(m_Controls->PFCompoANDButton, SIGNAL(clicked()), this, SLOT(GenerateAndComposite()) );
connect(m_Controls->PFCompoORButton, SIGNAL(clicked()), this, SLOT(GenerateOrComposite()) );
connect(m_Controls->PFCompoNOTButton, SIGNAL(clicked()), this, SLOT(GenerateNotComposite()) );
connect(m_Controls->m_GenerateRoiImage, SIGNAL(clicked()), this, SLOT(GenerateRoiImage()) );
connect(m_Controls->m_JoinBundles, SIGNAL(clicked()), this, SLOT(JoinBundles()) );
connect(m_Controls->m_SubstractBundles, SIGNAL(clicked()), this, SLOT(SubstractBundles()) );
connect(m_Controls->m_CopyBundle, SIGNAL(clicked()), this, SLOT(CopyBundles()) );
connect(m_Controls->m_ExtractFibersButton, SIGNAL(clicked()), this, SLOT(Extract()));
connect(m_Controls->m_RemoveButton, SIGNAL(clicked()), this, SLOT(Remove()));
connect(m_Controls->m_ModifyButton, SIGNAL(clicked()), this, SLOT(Modify()));
connect(m_Controls->m_ExtractionMethodBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()));
connect(m_Controls->m_RemovalMethodBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()));
connect(m_Controls->m_ModificationMethodBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()));
connect(m_Controls->m_ExtractionBoxMask, SIGNAL(currentIndexChanged(int)), this, SLOT(OnMaskExtractionChanged()));
m_Controls->m_ColorMapBox->SetDataStorage(this->GetDataStorage());
mitk::TNodePredicateDataType<mitk::Image>::Pointer isMitkImage = mitk::TNodePredicateDataType<mitk::Image>::New();
mitk::NodePredicateDataType::Pointer isDwi = mitk::NodePredicateDataType::New("DiffusionImage");
mitk::NodePredicateDataType::Pointer isDti = mitk::NodePredicateDataType::New("TensorImage");
mitk::NodePredicateDataType::Pointer isOdf = mitk::NodePredicateDataType::New("OdfImage");
mitk::NodePredicateOr::Pointer isDiffusionImage = mitk::NodePredicateOr::New(isDwi, isDti);
isDiffusionImage = mitk::NodePredicateOr::New(isDiffusionImage, isOdf);
mitk::NodePredicateNot::Pointer noDiffusionImage = mitk::NodePredicateNot::New(isDiffusionImage);
mitk::NodePredicateAnd::Pointer finalPredicate = mitk::NodePredicateAnd::New(isMitkImage, noDiffusionImage);
m_Controls->m_ColorMapBox->SetPredicate(finalPredicate);
}
UpdateGui();
OnMaskExtractionChanged();
}
void QmitkFiberProcessingView::OnMaskExtractionChanged()
{
m_Controls->m_FiberExtractionFractionLabel->setVisible(false);
m_Controls->m_FiberExtractionFractionBox->setVisible(false);
m_Controls->m_FiberExtractionThresholdLabel->setVisible(false);
m_Controls->m_FiberExtractionThresholdBox->setVisible(false);
m_Controls->m_InterpolateRoiBox->setVisible(false);
m_Controls->m_BothEnds->setVisible(false);
m_Controls->m_LabelsBox->setVisible(false);
m_Controls->m_LabelsLabel->setVisible(false);
if (m_Controls->m_ExtractionBoxMask->currentIndex() == 2 || m_Controls->m_ExtractionBoxMask->currentIndex() == 3)
{
m_Controls->m_FiberExtractionFractionLabel->setVisible(true);
m_Controls->m_FiberExtractionFractionBox->setVisible(true);
m_Controls->m_FiberExtractionThresholdLabel->setVisible(true);
m_Controls->m_FiberExtractionThresholdBox->setVisible(true);
m_Controls->m_InterpolateRoiBox->setVisible(true);
}
else if (m_Controls->m_ExtractionBoxMask->currentIndex() == 0 || m_Controls->m_ExtractionBoxMask->currentIndex() == 1)
{
if (m_Controls->m_ExtractionBoxMask->currentIndex() != 3)
m_Controls->m_BothEnds->setVisible(true);
m_Controls->m_InterpolateRoiBox->setVisible(true);
m_Controls->m_FiberExtractionThresholdLabel->setVisible(true);
m_Controls->m_FiberExtractionThresholdBox->setVisible(true);
}
else if (m_Controls->m_ExtractionBoxMask->currentIndex() == 4)
{
m_Controls->m_BothEnds->setVisible(true);
m_Controls->m_LabelsBox->setVisible(true);
m_Controls->m_LabelsLabel->setVisible(true);
}
}
void QmitkFiberProcessingView::SetFocus()
{
m_Controls->toolBoxx->setFocus();
}
void QmitkFiberProcessingView::Modify()
{
switch (m_Controls->m_ModificationMethodBox->currentIndex())
{
case 0:
{
ResampleSelectedBundlesSpline();
break;
}
case 1:
{
ResampleSelectedBundlesLinear();
break;
}
case 2:
{
CompressSelectedBundles();
break;
}
case 3:
{
DoImageColorCoding();
break;
}
case 4:
{
MirrorFibers();
break;
}
case 5:
{
WeightFibers();
break;
}
case 6:
{
DoCurvatureColorCoding();
break;
}
case 7:
{
DoWeightColorCoding();
break;
}
case 8:
{
DoLengthColorCoding();
break;
}
}
}
void QmitkFiberProcessingView::WeightFibers()
{
float weight = this->m_Controls->m_BundleWeightBox->value();
for (auto node : m_SelectedFB)
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
fib->SetFiberWeights(weight);
}
}
void QmitkFiberProcessingView::Remove()
{
switch (m_Controls->m_RemovalMethodBox->currentIndex())
{
case 0:
{
RemoveDir();
break;
}
case 1:
{
PruneBundle();
break;
}
case 2:
{
ApplyCurvatureThreshold();
break;
}
case 3:
{
RemoveWithMask(false);
break;
}
case 4:
{
RemoveWithMask(true);
break;
}
case 5:
{
ApplyWeightThreshold();
break;
}
case 6:
{
ApplyDensityThreshold();
break;
}
}
}
void QmitkFiberProcessingView::Extract()
{
switch (m_Controls->m_ExtractionMethodBox->currentIndex())
{
case 0:
{
ExtractWithPlanarFigure();
break;
}
case 1:
{
switch (m_Controls->m_ExtractionBoxMask->currentIndex())
{
{
case 0:
ExtractWithMask(true, false, false);
break;
}
{
case 1:
ExtractWithMask(true, true, false);
break;
}
{
case 2:
ExtractWithMask(false, false, false);
break;
}
{
case 3:
ExtractWithMask(false, true, false);
break;
}
{
case 4:
ExtractWithMask(true, false, true);
break;
}
}
break;
}
}
}
void QmitkFiberProcessingView::PruneBundle()
{
int minLength = this->m_Controls->m_PruneFibersMinBox->value();
int maxLength = this->m_Controls->m_PruneFibersMaxBox->value();
for (auto node : m_SelectedFB)
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
if (!fib->RemoveShortFibers(minLength))
QMessageBox::information(nullptr, "No output generated:", "The resulting fiber bundle contains no fibers.");
else if (!fib->RemoveLongFibers(maxLength))
QMessageBox::information(nullptr, "No output generated:", "The resulting fiber bundle contains no fibers.");
}
RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkFiberProcessingView::ApplyWeightThreshold()
{
float thr = this->m_Controls->m_WeightThresholdBox->value();
std::vector< DataNode::Pointer > nodes = m_SelectedFB;
for (auto node : nodes)
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
mitk::FiberBundle::Pointer newFib = fib->FilterByWeights(thr);
if (newFib->GetNumFibers()>0)
{
newFib->ColorFibersByFiberWeights(false, true);
node->SetData(newFib);
}
else
QMessageBox::information(nullptr, "No output generated:", "The resulting fiber bundle contains no fibers.");
}
RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkFiberProcessingView::ApplyDensityThreshold()
{
float thr = this->m_Controls->m_DensityThresholdBox->value();
float ol = this->m_Controls->m_DensityOverlapBox->value();
std::vector< DataNode::Pointer > nodes = m_SelectedFB;
for (auto node : nodes)
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
itk::TractDensityImageFilter< ItkFloatImageType >::Pointer generator = itk::TractDensityImageFilter< ItkFloatImageType >::New();
generator->SetFiberBundle(fib);
generator->SetBinaryOutput(false);
generator->SetOutputAbsoluteValues(false);
generator->Update();
itk::FiberExtractionFilter<float>::Pointer extractor = itk::FiberExtractionFilter<float>::New();
extractor->SetRoiImages({generator->GetOutput()});
extractor->SetInputFiberBundle(fib);
extractor->SetOverlapFraction(ol);
extractor->SetInterpolate(true);
extractor->SetThreshold(thr);
extractor->SetNoNegatives(true);
extractor->Update();
if (extractor->GetPositives().empty())
{
QMessageBox::information(nullptr, "No output generated:", "The resulting fiber bundle contains no fibers.");
continue;
}
mitk::FiberBundle::Pointer newFib = extractor->GetPositives().at(0);
if (newFib->GetNumFibers()>0)
node->SetData(newFib);
else
QMessageBox::information(nullptr, "No output generated:", "The resulting fiber bundle contains no fibers.");
}
RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkFiberProcessingView::ApplyCurvatureThreshold()
{
int angle = this->m_Controls->m_CurvSpinBox->value();
int dist = this->m_Controls->m_CurvDistanceSpinBox->value();
std::vector< DataNode::Pointer > nodes = m_SelectedFB;
for (auto node : nodes)
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
itk::FiberCurvatureFilter::Pointer filter = itk::FiberCurvatureFilter::New();
filter->SetInputFiberBundle(fib);
filter->SetAngularDeviation(angle);
filter->SetDistance(dist);
filter->SetRemoveFibers(m_Controls->m_RemoveCurvedFibersBox->isChecked());
filter->Update();
mitk::FiberBundle::Pointer newFib = filter->GetOutputFiberBundle();
if (newFib->GetNumFibers()>0)
{
newFib->ColorFibersByOrientation();
node->SetData(newFib);
}
else
QMessageBox::information(nullptr, "No output generated:", "The resulting fiber bundle contains no fibers.");
}
RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkFiberProcessingView::RemoveDir()
{
for (auto node : m_SelectedFB)
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
vnl_vector_fixed<double,3> dir;
dir[0] = m_Controls->m_ExtractDirX->value();
dir[1] = m_Controls->m_ExtractDirY->value();
dir[2] = m_Controls->m_ExtractDirZ->value();
fib->RemoveDir(dir,cos((float)m_Controls->m_ExtractAngle->value()*itk::Math::pi/180));
}
RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkFiberProcessingView::RemoveWithMask(bool removeInside)
{
if (m_RoiImageNode.IsNull())
return;
mitk::Image::Pointer mitkMask = dynamic_cast<mitk::Image*>(m_RoiImageNode->GetData());
for (auto node : m_SelectedFB)
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
ItkUCharImageType::Pointer mask = ItkUCharImageType::New();
mitk::CastToItkImage(mitkMask, mask);
mitk::FiberBundle::Pointer newFib = fib->RemoveFibersOutside(mask, removeInside);
if (newFib->GetNumFibers()<=0)
{
QMessageBox::information(nullptr, "No output generated:", "The resulting fiber bundle contains no fibers.");
continue;
}
node->SetData(newFib);
}
RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkFiberProcessingView::ExtractWithMask(bool onlyEnds, bool invert, bool labelmap)
{
if (m_RoiImageNode.IsNull())
return;
mitk::Image::Pointer mitkMask = dynamic_cast<mitk::Image*>(m_RoiImageNode->GetData());
for (auto node : m_SelectedFB)
{
std::string roi_name = m_RoiImageNode->GetName();
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
ItkFloatImageType::Pointer mask = ItkFloatImageType::New();
mitk::CastToItkImage(mitkMask, mask);
itk::FiberExtractionFilter<float>::Pointer extractor = itk::FiberExtractionFilter<float>::New();
extractor->SetInputFiberBundle(fib);
extractor->SetRoiImages({mask});
extractor->SetRoiImageNames({roi_name});
extractor->SetThreshold(m_Controls->m_FiberExtractionThresholdBox->value());
extractor->SetOverlapFraction(m_Controls->m_FiberExtractionFractionBox->value());
extractor->SetBothEnds(m_Controls->m_BothEnds->isChecked());
extractor->SetInterpolate(m_Controls->m_InterpolateRoiBox->isChecked());
extractor->SetMinFibersPerTract(m_Controls->m_MinExtractedFibersBox->value());
extractor->SetSplitByRoi(true);
if (invert)
extractor->SetNoPositives(true);
else
extractor->SetNoNegatives(true);
if (labelmap)
{
std::string labels_string = m_Controls->m_LabelsBox->text().toStdString();
if (labels_string!="ALL")
{
std::vector<std::string> strs;
boost::split(strs,labels_string,boost::is_any_of(" ,;\t"));
std::vector< unsigned short > labels_vector;
for (auto v : strs)
{
try{
unsigned short l = boost::lexical_cast<unsigned short>(v);
labels_vector.push_back(l);
}
catch(...)
{
}
}
extractor->SetLabels(labels_vector);
}
extractor->SetInterpolate(false);
extractor->SetInputType(itk::FiberExtractionFilter<float>::INPUT::LABEL_MAP);
extractor->SetSplitLabels(true);
onlyEnds = true;
}
if (onlyEnds)
extractor->SetMode(itk::FiberExtractionFilter<float>::MODE::ENDPOINTS);
extractor->Update();
std::vector< mitk::FiberBundle::Pointer > newFibs;
if (invert)
newFibs = extractor->GetNegatives();
else
newFibs = extractor->GetPositives();
if (newFibs.empty())
{
QMessageBox::information(nullptr, "No output generated:", "No fibers could be extracted.");
continue;
}
auto labels = extractor->GetPositiveLabels();
for (unsigned int i=0; i<newFibs.size(); ++i)
{
DataNode::Pointer newNode = DataNode::New();
auto fib = newFibs.at(i);
newNode->SetData(fib);
std::string name = roi_name;
if (i<labels.size())
name = labels.at(i);
if (invert)
{
if (onlyEnds)
name = "not-ending-in-" + name;
else
name = "not-passing-" + name;
}
else if (!labelmap)
{
if (onlyEnds)
name = "ending-in-" + name;
else
name = "passing-" + name;
}
newNode->SetName(name);
GetDataStorage()->Add(newNode, node);
}
node->SetVisibility(false);
}
}
void QmitkFiberProcessingView::GenerateRoiImage()
{
if (m_SelectedPF.empty())
return;
mitk::BaseGeometry::Pointer geometry;
if (!m_SelectedFB.empty())
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(m_SelectedFB.front()->GetData());
geometry = fib->GetGeometry();
}
else if (m_SelectedImage)
geometry = m_SelectedImage->GetGeometry();
else
return;
itk::Vector<double,3> spacing = geometry->GetSpacing();
spacing /= m_UpsamplingFactor;
mitk::Point3D newOrigin = geometry->GetOrigin();
mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds();
newOrigin[0] += bounds.GetElement(0);
newOrigin[1] += bounds.GetElement(2);
newOrigin[2] += bounds.GetElement(4);
itk::Matrix<double, 3, 3> direction;
itk::ImageRegion<3> imageRegion;
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
direction[j][i] = geometry->GetMatrixColumn(i)[j]/spacing[j];
imageRegion.SetSize(0, geometry->GetExtent(0)*m_UpsamplingFactor);
imageRegion.SetSize(1, geometry->GetExtent(1)*m_UpsamplingFactor);
imageRegion.SetSize(2, geometry->GetExtent(2)*m_UpsamplingFactor);
m_PlanarFigureImage = ItkUCharImageType::New();
m_PlanarFigureImage->SetSpacing( spacing ); // Set the image spacing
m_PlanarFigureImage->SetOrigin( newOrigin ); // Set the image origin
m_PlanarFigureImage->SetDirection( direction ); // Set the image direction
m_PlanarFigureImage->SetRegions( imageRegion );
m_PlanarFigureImage->Allocate();
m_PlanarFigureImage->FillBuffer( 0 );
Image::Pointer tmpImage = Image::New();
tmpImage->InitializeByItk(m_PlanarFigureImage.GetPointer());
tmpImage->SetVolume(m_PlanarFigureImage->GetBufferPointer());
std::string name = m_SelectedPF.at(0)->GetName();
WritePfToImage(m_SelectedPF.at(0), tmpImage);
for (unsigned int i=1; i<m_SelectedPF.size(); i++)
{
name += "+";
name += m_SelectedPF.at(i)->GetName();
WritePfToImage(m_SelectedPF.at(i), tmpImage);
}
DataNode::Pointer node = DataNode::New();
tmpImage = Image::New();
tmpImage->InitializeByItk(m_PlanarFigureImage.GetPointer());
tmpImage->SetVolume(m_PlanarFigureImage->GetBufferPointer());
node->SetData(tmpImage);
node->SetName(name);
this->GetDataStorage()->Add(node);
}
void QmitkFiberProcessingView::WritePfToImage(mitk::DataNode::Pointer node, mitk::Image* image)
{
if (dynamic_cast<mitk::PlanarFigure*>(node->GetData()))
{
m_PlanarFigure = dynamic_cast<mitk::PlanarFigure*>(node->GetData());
AccessFixedDimensionByItk_2(
image,
InternalReorientImagePlane, 3,
m_PlanarFigure->GetGeometry(), -1);
AccessFixedDimensionByItk_2(
m_InternalImage,
InternalCalculateMaskFromPlanarFigure,
3, 2, node->GetName() );
}
else if (dynamic_cast<mitk::PlanarFigureComposite*>(node->GetData()))
{
DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(node);
for (unsigned int i=0; i<children->Size(); i++)
{
WritePfToImage(children->at(i), image);
}
}
}
template < typename TPixel, unsigned int VImageDimension >
void QmitkFiberProcessingView::InternalReorientImagePlane( const itk::Image< TPixel, VImageDimension > *image, mitk::BaseGeometry* planegeo3D, int additionalIndex )
{
typedef itk::Image< TPixel, VImageDimension > ImageType;
typedef itk::Image< float, VImageDimension > FloatImageType;
typedef itk::ResampleImageFilter<ImageType, FloatImageType, double> ResamplerType;
typename ResamplerType::Pointer resampler = ResamplerType::New();
mitk::PlaneGeometry* planegeo = dynamic_cast<mitk::PlaneGeometry*>(planegeo3D);
float upsamp = m_UpsamplingFactor;
float gausssigma = 0.5;
// Spacing
typename ResamplerType::SpacingType spacing = planegeo->GetSpacing();
spacing[0] = image->GetSpacing()[0] / upsamp;
spacing[1] = image->GetSpacing()[1] / upsamp;
spacing[2] = image->GetSpacing()[2];
resampler->SetOutputSpacing( spacing );
// Size
typename ResamplerType::SizeType size;
size[0] = planegeo->GetExtentInMM(0) / spacing[0];
size[1] = planegeo->GetExtentInMM(1) / spacing[1];
size[2] = 1;
resampler->SetSize( size );
// Origin
typename mitk::Point3D orig = planegeo->GetOrigin();
typename mitk::Point3D corrorig;
planegeo3D->WorldToIndex(orig,corrorig);
corrorig[0] += 0.5/upsamp;
corrorig[1] += 0.5/upsamp;
corrorig[2] += 0;
planegeo3D->IndexToWorld(corrorig,corrorig);
resampler->SetOutputOrigin(corrorig );
// Direction
typename ResamplerType::DirectionType direction;
typename mitk::AffineTransform3D::MatrixType matrix = planegeo->GetIndexToWorldTransform()->GetMatrix();
for(unsigned int c=0; c<matrix.ColumnDimensions; c++)
{
double sum = 0;
for(unsigned int r=0; r<matrix.RowDimensions; r++)
sum += matrix(r,c)*matrix(r,c);
for(unsigned int r=0; r<matrix.RowDimensions; r++)
direction(r,c) = matrix(r,c)/sqrt(sum);
}
resampler->SetOutputDirection( direction );
// Gaussian interpolation
if(gausssigma != 0)
{
double sigma[3];
for( unsigned int d = 0; d < 3; d++ )
sigma[d] = gausssigma * image->GetSpacing()[d];
double alpha = 2.0;
typedef itk::GaussianInterpolateImageFunction<ImageType, double> GaussianInterpolatorType;
typename GaussianInterpolatorType::Pointer interpolator = GaussianInterpolatorType::New();
interpolator->SetInputImage( image );
interpolator->SetParameters( sigma, alpha );
resampler->SetInterpolator( interpolator );
}
else
{
typedef typename itk::LinearInterpolateImageFunction<ImageType, double> InterpolatorType;
typename InterpolatorType::Pointer interpolator = InterpolatorType::New();
interpolator->SetInputImage( image );
resampler->SetInterpolator( interpolator );
}
resampler->SetInput( image );
resampler->SetDefaultPixelValue(0);
resampler->Update();
if(additionalIndex < 0)
{
this->m_InternalImage = mitk::Image::New();
this->m_InternalImage->InitializeByItk( resampler->GetOutput() );
this->m_InternalImage->SetVolume( resampler->GetOutput()->GetBufferPointer() );
}
}
template < typename TPixel, unsigned int VImageDimension >
void QmitkFiberProcessingView::InternalCalculateMaskFromPlanarFigure( itk::Image< TPixel, VImageDimension > *image, unsigned int axis, std::string )
{
typedef itk::Image< TPixel, VImageDimension > ImageType;
// Generate mask image as new image with same header as input image and
// initialize with "1".
ItkUCharImageType::Pointer newMaskImage = ItkUCharImageType::New();
newMaskImage->SetSpacing( image->GetSpacing() ); // Set the image spacing
newMaskImage->SetOrigin( image->GetOrigin() ); // Set the image origin
newMaskImage->SetDirection( image->GetDirection() ); // Set the image direction
newMaskImage->SetRegions( image->GetLargestPossibleRegion() );
newMaskImage->Allocate();
newMaskImage->FillBuffer( 1 );
// Generate VTK polygon from (closed) PlanarFigure polyline
// (The polyline points are shifted by -0.5 in z-direction to make sure
// that the extrusion filter, which afterwards elevates all points by +0.5
// in z-direction, creates a 3D object which is cut by the the plane z=0)
const PlaneGeometry *planarFigurePlaneGeometry = m_PlanarFigure->GetPlaneGeometry();
const PlanarFigure::PolyLineType planarFigurePolyline = m_PlanarFigure->GetPolyLine( 0 );
const BaseGeometry *imageGeometry3D = m_InternalImage->GetGeometry( 0 );
vtkPolyData *polyline = vtkPolyData::New();
polyline->Allocate( 1, 1 );
// Determine x- and y-dimensions depending on principal axis
int i0, i1;
switch ( axis )
{
case 0:
i0 = 1;
i1 = 2;
break;
case 1:
i0 = 0;
i1 = 2;
break;
case 2:
default:
i0 = 0;
i1 = 1;
break;
}
// Create VTK polydata object of polyline contour
vtkPoints *points = vtkPoints::New();
PlanarFigure::PolyLineType::const_iterator it;
unsigned int numberOfPoints = 0;
for ( it = planarFigurePolyline.begin(); it != planarFigurePolyline.end(); ++it )
{
Point3D point3D;
// Convert 2D point back to the local index coordinates of the selected image
Point2D point2D = *it;
planarFigurePlaneGeometry->WorldToIndex(point2D, point2D);
point2D[0] -= 0.5/m_UpsamplingFactor;
point2D[1] -= 0.5/m_UpsamplingFactor;
planarFigurePlaneGeometry->IndexToWorld(point2D, point2D);
planarFigurePlaneGeometry->Map( point2D, point3D );
// Polygons (partially) outside of the image bounds can not be processed further due to a bug in vtkPolyDataToImageStencil
if ( !imageGeometry3D->IsInside( point3D ) )
{
float bounds[2] = {0,0};
bounds[0] =
this->m_InternalImage->GetLargestPossibleRegion().GetSize().GetElement(i0);
bounds[1] =
this->m_InternalImage->GetLargestPossibleRegion().GetSize().GetElement(i1);
imageGeometry3D->WorldToIndex( point3D, point3D );
if (point3D[i0]<0)
point3D[i0] = 0.0;
else if (point3D[i0]>bounds[0])
point3D[i0] = bounds[0]-0.001;
if (point3D[i1]<0)
point3D[i1] = 0.0;
else if (point3D[i1]>bounds[1])
point3D[i1] = bounds[1]-0.001;
points->InsertNextPoint( point3D[i0], point3D[i1], -0.5 );
numberOfPoints++;
}
else
{
imageGeometry3D->WorldToIndex( point3D, point3D );
// Add point to polyline array
points->InsertNextPoint( point3D[i0], point3D[i1], -0.5 );
numberOfPoints++;
}
}
polyline->SetPoints( points );
points->Delete();
vtkIdType *ptIds = new vtkIdType[numberOfPoints];
for ( vtkIdType i = 0; i < numberOfPoints; ++i )
ptIds[i] = i;
polyline->InsertNextCell( VTK_POLY_LINE, numberOfPoints, ptIds );
// Extrude the generated contour polygon
vtkLinearExtrusionFilter *extrudeFilter = vtkLinearExtrusionFilter::New();
extrudeFilter->SetInputData( polyline );
extrudeFilter->SetScaleFactor( 1 );
extrudeFilter->SetExtrusionTypeToNormalExtrusion();
extrudeFilter->SetVector( 0.0, 0.0, 1.0 );
// Make a stencil from the extruded polygon
vtkPolyDataToImageStencil *polyDataToImageStencil = vtkPolyDataToImageStencil::New();
polyDataToImageStencil->SetInputConnection( extrudeFilter->GetOutputPort() );
// Export from ITK to VTK (to use a VTK filter)
typedef itk::VTKImageImport< ItkUCharImageType > ImageImportType;
typedef itk::VTKImageExport< ItkUCharImageType > ImageExportType;
typename ImageExportType::Pointer itkExporter = ImageExportType::New();
itkExporter->SetInput( newMaskImage );
vtkImageImport *vtkImporter = vtkImageImport::New();
this->ConnectPipelines( itkExporter, vtkImporter );
vtkImporter->Update();
// Apply the generated image stencil to the input image
vtkImageStencil *imageStencilFilter = vtkImageStencil::New();
imageStencilFilter->SetInputConnection( vtkImporter->GetOutputPort() );
imageStencilFilter->SetStencilConnection(polyDataToImageStencil->GetOutputPort() );
imageStencilFilter->ReverseStencilOff();
imageStencilFilter->SetBackgroundValue( 0 );
imageStencilFilter->Update();
// Export from VTK back to ITK
vtkImageExport *vtkExporter = vtkImageExport::New();
vtkExporter->SetInputConnection( imageStencilFilter->GetOutputPort() );
vtkExporter->Update();
typename ImageImportType::Pointer itkImporter = ImageImportType::New();
this->ConnectPipelines( vtkExporter, itkImporter );
itkImporter->Update();
// calculate cropping bounding box
m_InternalImageMask3D = itkImporter->GetOutput();
m_InternalImageMask3D->SetDirection(image->GetDirection());
itk::ImageRegionConstIterator<ItkUCharImageType>
itmask(m_InternalImageMask3D, m_InternalImageMask3D->GetLargestPossibleRegion());
itk::ImageRegionIterator<ImageType>
itimage(image, image->GetLargestPossibleRegion());
itmask.GoToBegin();
itimage.GoToBegin();
typename ImageType::SizeType lowersize = {{itk::NumericTraits<unsigned long>::max(),itk::NumericTraits<unsigned long>::max(),itk::NumericTraits<unsigned long>::max()}};
typename ImageType::SizeType uppersize = {{0,0,0}};
while( !itmask.IsAtEnd() )
{
if(itmask.Get() == 0)
itimage.Set(0);
else
{
typename ImageType::IndexType index = itimage.GetIndex();
typename ImageType::SizeType signedindex;
signedindex[0] = index[0];
signedindex[1] = index[1];
signedindex[2] = index[2];
lowersize[0] = signedindex[0] < lowersize[0] ? signedindex[0] : lowersize[0];
lowersize[1] = signedindex[1] < lowersize[1] ? signedindex[1] : lowersize[1];
lowersize[2] = signedindex[2] < lowersize[2] ? signedindex[2] : lowersize[2];
uppersize[0] = signedindex[0] > uppersize[0] ? signedindex[0] : uppersize[0];
uppersize[1] = signedindex[1] > uppersize[1] ? signedindex[1] : uppersize[1];
uppersize[2] = signedindex[2] > uppersize[2] ? signedindex[2] : uppersize[2];
}
++itmask;
++itimage;
}
typename ImageType::IndexType index;
index[0] = lowersize[0];
index[1] = lowersize[1];
index[2] = lowersize[2];
typename ImageType::SizeType size;
size[0] = uppersize[0] - lowersize[0] + 1;
size[1] = uppersize[1] - lowersize[1] + 1;
size[2] = uppersize[2] - lowersize[2] + 1;
itk::ImageRegion<3> cropRegion = itk::ImageRegion<3>(index, size);
// crop internal mask
typedef itk::RegionOfInterestImageFilter< ItkUCharImageType, ItkUCharImageType > ROIMaskFilterType;
typename ROIMaskFilterType::Pointer roi2 = ROIMaskFilterType::New();
roi2->SetRegionOfInterest(cropRegion);
roi2->SetInput(m_InternalImageMask3D);
roi2->Update();
m_InternalImageMask3D = roi2->GetOutput();
Image::Pointer tmpImage = Image::New();
tmpImage->InitializeByItk(m_InternalImageMask3D.GetPointer());
tmpImage->SetVolume(m_InternalImageMask3D->GetBufferPointer());
Image::Pointer tmpImage2 = Image::New();
tmpImage2->InitializeByItk(m_PlanarFigureImage.GetPointer());
const BaseGeometry *pfImageGeometry3D = tmpImage2->GetGeometry( 0 );
const BaseGeometry *intImageGeometry3D = tmpImage->GetGeometry( 0 );
typedef itk::ImageRegionIteratorWithIndex<ItkUCharImageType> IteratorType;
IteratorType imageIterator (m_InternalImageMask3D, m_InternalImageMask3D->GetRequestedRegion());
imageIterator.GoToBegin();
while ( !imageIterator.IsAtEnd() )
{
unsigned char val = imageIterator.Value();
if (val>0)
{
itk::Index<3> index = imageIterator.GetIndex();
Point3D point;
point[0] = index[0];
point[1] = index[1];
point[2] = index[2];
intImageGeometry3D->IndexToWorld(point, point);
pfImageGeometry3D->WorldToIndex(point, point);
point[i0] += 0.5;
point[i1] += 0.5;
index[0] = point[0];
index[1] = point[1];
index[2] = point[2];
if (pfImageGeometry3D->IsIndexInside(index))
m_PlanarFigureImage->SetPixel(index, 1);
}
++imageIterator;
}
// Clean up VTK objects
polyline->Delete();
extrudeFilter->Delete();
polyDataToImageStencil->Delete();
vtkImporter->Delete();
imageStencilFilter->Delete();
//vtkExporter->Delete(); // TODO: crashes when outcommented; memory leak??
delete[] ptIds;
}
void QmitkFiberProcessingView::UpdateGui()
{
m_Controls->m_FibLabel->setText("<font color='red'>mandatory</font>");
m_Controls->m_PfLabel->setText("<font color='grey'>needed for extraction</font>");
m_Controls->m_InputData->setTitle("Please Select Input Data");
m_Controls->m_RemoveButton->setEnabled(false);
m_Controls->m_PlanarFigureButtonsFrame->setEnabled(false);
m_Controls->PFCompoANDButton->setEnabled(false);
m_Controls->PFCompoORButton->setEnabled(false);
m_Controls->PFCompoNOTButton->setEnabled(false);
m_Controls->m_GenerateRoiImage->setEnabled(false);
m_Controls->m_ExtractFibersButton->setEnabled(false);
m_Controls->m_ModifyButton->setEnabled(false);
m_Controls->m_CopyBundle->setEnabled(false);
m_Controls->m_JoinBundles->setEnabled(false);
m_Controls->m_SubstractBundles->setEnabled(false);
// disable alle frames
m_Controls->m_BundleWeightFrame->setVisible(false);
m_Controls->m_ExtactionFramePF->setVisible(false);
m_Controls->m_RemoveDirectionFrame->setVisible(false);
m_Controls->m_RemoveLengthFrame->setVisible(false);
m_Controls->m_RemoveCurvatureFrame->setVisible(false);
m_Controls->m_RemoveByWeightFrame->setVisible(false);
m_Controls->m_RemoveByDensityFrame->setVisible(false);
m_Controls->m_SmoothFibersFrame->setVisible(false);
m_Controls->m_CompressFibersFrame->setVisible(false);
m_Controls->m_ColorFibersFrame->setVisible(false);
m_Controls->m_MirrorFibersFrame->setVisible(false);
m_Controls->m_MaskExtractionFrame->setVisible(false);
m_Controls->m_ColorMapBox->setVisible(false);
bool pfSelected = !m_SelectedPF.empty();
bool fibSelected = !m_SelectedFB.empty();
bool multipleFibsSelected = (m_SelectedFB.size()>1);
bool maskSelected = m_RoiImageNode.IsNotNull();
bool imageSelected = m_SelectedImage.IsNotNull();
// toggle visibility of elements according to selected method
switch ( m_Controls->m_ExtractionMethodBox->currentIndex() )
{
case 0:
m_Controls->m_ExtactionFramePF->setVisible(true);
break;
case 1:
m_Controls->m_MaskExtractionFrame->setVisible(true);
break;
}
switch ( m_Controls->m_RemovalMethodBox->currentIndex() )
{
case 0:
m_Controls->m_RemoveDirectionFrame->setVisible(true);
if ( fibSelected )
m_Controls->m_RemoveButton->setEnabled(true);
break;
case 1:
m_Controls->m_RemoveLengthFrame->setVisible(true);
if ( fibSelected )
m_Controls->m_RemoveButton->setEnabled(true);
break;
case 2:
m_Controls->m_RemoveCurvatureFrame->setVisible(true);
if ( fibSelected )
m_Controls->m_RemoveButton->setEnabled(true);
break;
case 3:
break;
case 4:
break;
case 5:
m_Controls->m_RemoveByWeightFrame->setVisible(true);
if ( fibSelected )
m_Controls->m_RemoveButton->setEnabled(true);
break;
case 6:
m_Controls->m_RemoveByDensityFrame->setVisible(true);
if ( fibSelected )
m_Controls->m_RemoveButton->setEnabled(true);
break;
}
switch ( m_Controls->m_ModificationMethodBox->currentIndex() )
{
case 0:
m_Controls->m_SmoothFibersFrame->setVisible(true);
break;
case 1:
m_Controls->m_SmoothFibersFrame->setVisible(true);
break;
case 2:
m_Controls->m_CompressFibersFrame->setVisible(true);
break;
case 3:
m_Controls->m_ColorFibersFrame->setVisible(true);
m_Controls->m_ColorMapBox->setVisible(true);
break;
case 4:
m_Controls->m_MirrorFibersFrame->setVisible(true);
if (m_SelectedSurfaces.size()>0)
m_Controls->m_ModifyButton->setEnabled(true);
break;
case 5:
m_Controls->m_BundleWeightFrame->setVisible(true);
break;
case 6:
m_Controls->m_ColorFibersFrame->setVisible(true);
break;
case 7:
m_Controls->m_ColorFibersFrame->setVisible(true);
break;
case 8:
m_Controls->m_ColorFibersFrame->setVisible(true);
break;
}
// are fiber bundles selected?
if ( fibSelected )
{
m_Controls->m_CopyBundle->setEnabled(true);
m_Controls->m_ModifyButton->setEnabled(true);
m_Controls->m_PlanarFigureButtonsFrame->setEnabled(true);
m_Controls->m_FibLabel->setText(QString(m_SelectedFB.at(0)->GetName().c_str()));
// one bundle and one planar figure needed to extract fibers
if (pfSelected && m_Controls->m_ExtractionMethodBox->currentIndex()==0)
{
m_Controls->m_InputData->setTitle("Input Data");
m_Controls->m_PfLabel->setText(QString(m_SelectedPF.at(0)->GetName().c_str()));
m_Controls->m_ExtractFibersButton->setEnabled(true);
}
// more than two bundles needed to join/subtract
if (multipleFibsSelected)
{
m_Controls->m_FibLabel->setText("multiple bundles selected");
m_Controls->m_JoinBundles->setEnabled(true);
m_Controls->m_SubstractBundles->setEnabled(true);
}
if (maskSelected && m_Controls->m_ExtractionMethodBox->currentIndex()==1)
{
m_Controls->m_InputData->setTitle("Input Data");
m_Controls->m_PfLabel->setText(QString(m_RoiImageNode->GetName().c_str()));
m_Controls->m_ExtractFibersButton->setEnabled(true);
}
if (maskSelected && (m_Controls->m_RemovalMethodBox->currentIndex()==3 || m_Controls->m_RemovalMethodBox->currentIndex()==4) )
{
m_Controls->m_InputData->setTitle("Input Data");
m_Controls->m_PfLabel->setText(QString(m_RoiImageNode->GetName().c_str()));
m_Controls->m_RemoveButton->setEnabled(true);
}
}
// are planar figures selected?
if (pfSelected)
{
if ( fibSelected || m_SelectedImage.IsNotNull())
m_Controls->m_GenerateRoiImage->setEnabled(true);
if (m_SelectedPF.size() > 1)
{
m_Controls->PFCompoANDButton->setEnabled(true);
m_Controls->PFCompoORButton->setEnabled(true);
}
else
m_Controls->PFCompoNOTButton->setEnabled(true);
}
// is image selected
if (imageSelected || maskSelected)
{
m_Controls->m_PlanarFigureButtonsFrame->setEnabled(true);
}
}
void QmitkFiberProcessingView::NodeRemoved(const mitk::DataNode* node )
{
for (auto fnode: m_SelectedFB)
if (node == fnode)
{
m_SelectedFB.clear();
break;
}
berry::IWorkbenchPart::Pointer nullPart;
QList<mitk::DataNode::Pointer> nodes;
OnSelectionChanged(nullPart, nodes);
}
void QmitkFiberProcessingView::NodeAdded(const mitk::DataNode* )
{
if (!m_Controls->m_InteractiveBox->isChecked())
{
berry::IWorkbenchPart::Pointer nullPart;
QList<mitk::DataNode::Pointer> nodes;
OnSelectionChanged(nullPart, nodes);
}
}
void QmitkFiberProcessingView::OnEndInteraction()
{
if (m_Controls->m_InteractiveBox->isChecked())
ExtractWithPlanarFigure(true);
}
void QmitkFiberProcessingView::AddObservers()
{
typedef itk::SimpleMemberCommand< QmitkFiberProcessingView > SimpleCommandType;
for (auto node : m_SelectedPF)
{
mitk::PlanarFigure* figure = dynamic_cast<mitk::PlanarFigure*>(node->GetData());
if (figure!=nullptr)
{
figure->RemoveAllObservers();
// add observer for event when interaction with figure starts
SimpleCommandType::Pointer endInteractionCommand = SimpleCommandType::New();
endInteractionCommand->SetCallbackFunction( this, &QmitkFiberProcessingView::OnEndInteraction);
m_EndInteractionObserverTag = figure->AddObserver( mitk::EndInteractionPlanarFigureEvent(), endInteractionCommand );
}
}
}
void QmitkFiberProcessingView::RemoveObservers()
{
for (auto node : m_SelectedPF)
{
mitk::PlanarFigure* figure = dynamic_cast<mitk::PlanarFigure*>(node->GetData());
if (figure!=nullptr)
figure->RemoveAllObservers();
}
}
void QmitkFiberProcessingView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList<mitk::DataNode::Pointer>& nodes)
{
RemoveObservers();
//reset existing Vectors containing FiberBundles and PlanarFigures from a previous selection
std::vector<mitk::DataNode::Pointer> lastSelectedFB = m_SelectedFB;
m_SelectedFB.clear();
m_SelectedPF.clear();
m_SelectedSurfaces.clear();
m_SelectedImage = nullptr;
m_RoiImageNode = nullptr;
for (auto node: nodes)
{
if ( dynamic_cast<mitk::FiberBundle*>(node->GetData()) )
m_SelectedFB.push_back(node);
else if (dynamic_cast<mitk::PlanarPolygon*>(node->GetData()) || dynamic_cast<mitk::PlanarFigureComposite*>(node->GetData()) || dynamic_cast<mitk::PlanarCircle*>(node->GetData()))
m_SelectedPF.push_back(node);
else if (dynamic_cast<mitk::Image*>(node->GetData()))
{
m_SelectedImage = dynamic_cast<mitk::Image*>(node->GetData());
if (m_SelectedImage->GetDimension()==3)
m_RoiImageNode = node;
}
else if (dynamic_cast<mitk::Surface*>(node->GetData()))
m_SelectedSurfaces.push_back(dynamic_cast<mitk::Surface*>(node->GetData()));
}
// if we perform interactive fiber extraction, we want to avoid auto-selection of the extracted bundle
if (m_SelectedFB.empty() && m_Controls->m_InteractiveBox->isChecked())
m_SelectedFB = lastSelectedFB;
// if no fibers or surfaces are selected, select topmost
if (m_SelectedFB.empty() && m_SelectedSurfaces.empty())
{
int maxLayer = 0;
itk::VectorContainer<unsigned int, mitk::DataNode::Pointer>::ConstPointer nodes = this->GetDataStorage()->GetAll();
for (unsigned int i=0; i<nodes->Size(); i++)
if (dynamic_cast<mitk::FiberBundle*>(nodes->at(i)->GetData()))
{
mitk::DataStorage::SetOfObjects::ConstPointer sources = GetDataStorage()->GetSources(nodes->at(i));
if (sources->Size()>0)
continue;
int layer = 0;
nodes->at(i)->GetPropertyValue("layer", layer);
if (layer>=maxLayer)
{
maxLayer = layer;
m_SelectedFB.clear();
m_SelectedFB.push_back(nodes->at(i));
}
}
}
// if no plar figure is selected, select topmost
if (m_SelectedPF.empty())
{
int maxLayer = 0;
itk::VectorContainer<unsigned int, mitk::DataNode::Pointer>::ConstPointer nodes = this->GetDataStorage()->GetAll();
for (unsigned int i=0; i<nodes->Size(); i++)
if (dynamic_cast<mitk::PlanarPolygon*>(nodes->at(i)->GetData()) || dynamic_cast<mitk::PlanarFigureComposite*>(nodes->at(i)->GetData()) || dynamic_cast<mitk::PlanarCircle*>(nodes->at(i)->GetData()))
{
mitk::DataStorage::SetOfObjects::ConstPointer sources = GetDataStorage()->GetSources(nodes->at(i));
if (sources->Size()>0)
continue;
int layer = 0;
nodes->at(i)->GetPropertyValue("layer", layer);
if (layer>=maxLayer)
{
maxLayer = layer;
m_SelectedPF.clear();
m_SelectedPF.push_back(nodes->at(i));
}
}
}
AddObservers();
UpdateGui();
}
void QmitkFiberProcessingView::OnDrawPolygon()
{
mitk::PlanarPolygon::Pointer figure = mitk::PlanarPolygon::New();
figure->ClosedOn();
this->AddFigureToDataStorage(figure, QString("Polygon%1").arg(++m_PolygonCounter));
}
void QmitkFiberProcessingView::OnDrawCircle()
{
mitk::PlanarCircle::Pointer figure = mitk::PlanarCircle::New();
this->AddFigureToDataStorage(figure, QString("Circle%1").arg(++m_CircleCounter));
}
void QmitkFiberProcessingView::AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name, const char *, mitk::BaseProperty* )
{
// initialize figure's geometry with empty geometry
mitk::PlaneGeometry::Pointer emptygeometry = mitk::PlaneGeometry::New();
figure->SetPlaneGeometry( emptygeometry );
//set desired data to DataNode where Planarfigure is stored
mitk::DataNode::Pointer newNode = mitk::DataNode::New();
newNode->SetName(name.toStdString());
newNode->SetData(figure);
newNode->SetBoolProperty("planarfigure.3drendering", true);
newNode->SetBoolProperty("planarfigure.3drendering.fill", true);
mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast<mitk::PlanarFigureInteractor*>(newNode->GetDataInteractor().GetPointer());
if(figureInteractor.IsNull())
{
figureInteractor = mitk::PlanarFigureInteractor::New();
us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" );
figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule );
figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule );
figureInteractor->SetDataNode(newNode);
}
// figure drawn on the topmost layer / image
GetDataStorage()->Add(newNode );
RemoveObservers();
for(unsigned int i = 0; i < m_SelectedPF.size(); i++)
m_SelectedPF[i]->SetSelected(false);
newNode->SetSelected(true);
m_SelectedPF.clear();
m_SelectedPF.push_back(newNode);
AddObservers();
UpdateGui();
}
void QmitkFiberProcessingView::ExtractWithPlanarFigure(bool interactive)
{
if ( m_SelectedFB.empty() || m_SelectedPF.empty() ){
QMessageBox::information( nullptr, "Warning", "No fibe bundle selected!");
return;
}
try
{
std::vector<mitk::DataNode::Pointer> fiberBundles = m_SelectedFB;
mitk::DataNode::Pointer planarFigure = m_SelectedPF.at(0);
for (unsigned int i=0; i<fiberBundles.size(); i++)
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(fiberBundles.at(i)->GetData());
mitk::FiberBundle::Pointer extFB = fib->ExtractFiberSubset(planarFigure, GetDataStorage());
if (interactive && 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);
}
float op = 5.0/sqrt(fib->GetNumFibers());
float currentOp = 0;
fiberBundles.at(i)->GetFloatProperty("opacity", currentOp);
if (currentOp!=op)
{
fib->SetFiberColors(255, 255, 255);
fiberBundles.at(i)->SetFloatProperty("opacity", op);
fiberBundles.at(i)->SetBoolProperty("Fiber2DfadeEFX", false);
}
m_InteractiveNode->SetData(extFB);
}
else
{
if (extFB->GetNumFibers()<=0)
{
QMessageBox::information(nullptr, "No output generated:", "The resulting fiber bundle contains no fibers.");
continue;
}
mitk::DataNode::Pointer node;
node = mitk::DataNode::New();
node->SetData(extFB);
QString name(fiberBundles.at(i)->GetName().c_str());
name += "*";
node->SetName(name.toStdString());
fiberBundles.at(i)->SetVisibility(false);
GetDataStorage()->Add(node);
}
}
}
catch(const std::out_of_range& )
{
QMessageBox::warning( nullptr, "Fiber extraction failed", "Did you only create the planar figure, using the circle or polygon button, but forgot to actually place it in the image afterwards? \nAfter creating a planar figure, simply left-click at the desired position in the image or on the tractogram to place it.");
}
}
void QmitkFiberProcessingView::GenerateAndComposite()
{
mitk::PlanarFigureComposite::Pointer PFCAnd = mitk::PlanarFigureComposite::New();
PFCAnd->setOperationType(mitk::PlanarFigureComposite::AND);
mitk::DataNode::Pointer newPFCNode;
newPFCNode = mitk::DataNode::New();
newPFCNode->SetName("AND");
newPFCNode->SetData(PFCAnd);
AddCompositeToDatastorage(newPFCNode, m_SelectedPF);
RemoveObservers();
m_SelectedPF.clear();
m_SelectedPF.push_back(newPFCNode);
AddObservers();
UpdateGui();
}
void QmitkFiberProcessingView::GenerateOrComposite()
{
mitk::PlanarFigureComposite::Pointer PFCOr = mitk::PlanarFigureComposite::New();
PFCOr->setOperationType(mitk::PlanarFigureComposite::OR);
mitk::DataNode::Pointer newPFCNode;
newPFCNode = mitk::DataNode::New();
newPFCNode->SetName("OR");
newPFCNode->SetData(PFCOr);
RemoveObservers();
AddCompositeToDatastorage(newPFCNode, m_SelectedPF);
m_SelectedPF.clear();
m_SelectedPF.push_back(newPFCNode);
UpdateGui();
}
void QmitkFiberProcessingView::GenerateNotComposite()
{
mitk::PlanarFigureComposite::Pointer PFCNot = mitk::PlanarFigureComposite::New();
PFCNot->setOperationType(mitk::PlanarFigureComposite::NOT);
mitk::DataNode::Pointer newPFCNode;
newPFCNode = mitk::DataNode::New();
newPFCNode->SetName("NOT");
newPFCNode->SetData(PFCNot);
RemoveObservers();
AddCompositeToDatastorage(newPFCNode, m_SelectedPF);
m_SelectedPF.clear();
m_SelectedPF.push_back(newPFCNode);
AddObservers();
UpdateGui();
}
void QmitkFiberProcessingView::AddCompositeToDatastorage(mitk::DataNode::Pointer pfc, std::vector<mitk::DataNode::Pointer> children, mitk::DataNode::Pointer parentNode )
{
pfc->SetSelected(true);
if (parentNode.IsNotNull())
GetDataStorage()->Add(pfc, parentNode);
else
GetDataStorage()->Add(pfc);
for (auto child : children)
{
if (dynamic_cast<PlanarFigure*>(child->GetData()))
{
mitk::DataNode::Pointer newChild;
newChild = mitk::DataNode::New();
newChild->SetData(dynamic_cast<PlanarFigure*>(child->GetData()));
newChild->SetName( child->GetName() );
newChild->SetBoolProperty("planarfigure.3drendering", true);
newChild->SetBoolProperty("planarfigure.3drendering.fill", true);
GetDataStorage()->Add(newChild, pfc);
GetDataStorage()->Remove(child);
}
else if (dynamic_cast<PlanarFigureComposite*>(child->GetData()))
{
mitk::DataNode::Pointer newChild;
newChild = mitk::DataNode::New();
newChild->SetData(dynamic_cast<PlanarFigureComposite*>(child->GetData()));
newChild->SetName( child->GetName() );
std::vector< mitk::DataNode::Pointer > grandChildVector;
mitk::DataStorage::SetOfObjects::ConstPointer grandchildren = GetDataStorage()->GetDerivations(child);
for( mitk::DataStorage::SetOfObjects::const_iterator it = grandchildren->begin(); it != grandchildren->end(); ++it )
grandChildVector.push_back(*it);
AddCompositeToDatastorage(newChild, grandChildVector, pfc);
GetDataStorage()->Remove(child);
}
}
UpdateGui();
}
void QmitkFiberProcessingView::CopyBundles()
{
if ( m_SelectedFB.empty() ){
QMessageBox::information( nullptr, "Warning", "Select at least one fiber bundle!");
MITK_WARN("QmitkFiberProcessingView") << "Select at least one fiber bundle!";
return;
}
for (auto node : m_SelectedFB)
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
mitk::FiberBundle::Pointer newFib = fib->GetDeepCopy();
node->SetVisibility(false);
QString name("");
name += QString(m_SelectedFB.at(0)->GetName().c_str());
name += "_copy";
mitk::DataNode::Pointer fbNode = mitk::DataNode::New();
fbNode->SetData(newFib);
fbNode->SetName(name.toStdString());
fbNode->SetVisibility(true);
GetDataStorage()->Add(fbNode);
}
UpdateGui();
}
void QmitkFiberProcessingView::JoinBundles()
{
if ( m_SelectedFB.size()<2 ){
QMessageBox::information( nullptr, "Warning", "Select at least two fiber bundles!");
MITK_WARN("QmitkFiberProcessingView") << "Select at least two fiber bundles!";
return;
}
m_SelectedFB.at(0)->SetVisibility(false);
mitk::FiberBundle::Pointer newBundle = dynamic_cast<mitk::FiberBundle*>(m_SelectedFB.at(0)->GetData());
std::vector< mitk::FiberBundle::Pointer > tractograms;
for (unsigned int i=1; i<m_SelectedFB.size(); i++)
{
m_SelectedFB.at(i)->SetVisibility(false);
tractograms.push_back(dynamic_cast<mitk::FiberBundle*>(m_SelectedFB.at(i)->GetData()));
}
newBundle = newBundle->AddBundles(tractograms);
mitk::DataNode::Pointer fbNode = mitk::DataNode::New();
fbNode->SetData(newBundle);
fbNode->SetName("Joined_Tractograms");
fbNode->SetVisibility(true);
GetDataStorage()->Add(fbNode);
UpdateGui();
}
void QmitkFiberProcessingView::SubstractBundles()
{
if ( m_SelectedFB.size()<2 ){
QMessageBox::information( nullptr, "Warning", "Select at least two fiber bundles!");
MITK_WARN("QmitkFiberProcessingView") << "Select at least two fiber bundles!";
return;
}
mitk::FiberBundle::Pointer newBundle = dynamic_cast<mitk::FiberBundle*>(m_SelectedFB.at(0)->GetData());
m_SelectedFB.at(0)->SetVisibility(false);
QString name("");
name += QString(m_SelectedFB.at(0)->GetName().c_str());
for (unsigned int i=1; i<m_SelectedFB.size(); i++)
{
newBundle = newBundle->SubtractBundle(dynamic_cast<mitk::FiberBundle*>(m_SelectedFB.at(i)->GetData()));
if (newBundle.IsNull())
break;
name += "-"+QString(m_SelectedFB.at(i)->GetName().c_str());
m_SelectedFB.at(i)->SetVisibility(false);
}
if (newBundle.IsNull())
{
QMessageBox::information(nullptr, "No output generated:", "The resulting fiber bundle contains no fibers. Did you select the fiber bundles in the correct order? X-Y is not equal to Y-X!");
return;
}
mitk::DataNode::Pointer fbNode = mitk::DataNode::New();
fbNode->SetData(newBundle);
fbNode->SetName(name.toStdString());
fbNode->SetVisibility(true);
GetDataStorage()->Add(fbNode);
UpdateGui();
}
void QmitkFiberProcessingView::ResampleSelectedBundlesSpline()
{
double factor = this->m_Controls->m_SmoothFibersBox->value();
for (auto node : m_SelectedFB)
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
fib->ResampleSpline(factor);
}
RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkFiberProcessingView::ResampleSelectedBundlesLinear()
{
double factor = this->m_Controls->m_SmoothFibersBox->value();
for (auto node : m_SelectedFB)
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
fib->ResampleLinear(factor);
}
RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkFiberProcessingView::CompressSelectedBundles()
{
double factor = this->m_Controls->m_ErrorThresholdBox->value();
for (auto node : m_SelectedFB)
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
fib->Compress(factor);
fib->ColorFibersByOrientation();
}
RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkFiberProcessingView::DoImageColorCoding()
{
if (m_Controls->m_ColorMapBox->GetSelectedNode().IsNull())
{
QMessageBox::information(nullptr, "Bundle coloring aborted:", "No image providing the scalar values for coloring the selected bundle available.");
return;
}
for (auto node : m_SelectedFB)
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
fib->ColorFibersByScalarMap(dynamic_cast<mitk::Image*>(m_Controls->m_ColorMapBox->GetSelectedNode()->GetData()), m_Controls->m_FiberOpacityBox->isChecked(), m_Controls->m_NormalizeColorValues->isChecked());
}
if (auto renderWindowPart = this->GetRenderWindowPart())
{
renderWindowPart->RequestUpdate();
}
}
void QmitkFiberProcessingView::DoCurvatureColorCoding()
{
for (auto node : m_SelectedFB)
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
fib->ColorFibersByCurvature(m_Controls->m_FiberOpacityBox->isChecked(), m_Controls->m_NormalizeColorValues->isChecked());
}
if (auto renderWindowPart = this->GetRenderWindowPart())
{
renderWindowPart->RequestUpdate();
}
}
void QmitkFiberProcessingView::DoLengthColorCoding()
{
for (auto node : m_SelectedFB)
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
fib->ColorFibersByLength(m_Controls->m_FiberOpacityBox->isChecked(), m_Controls->m_NormalizeColorValues->isChecked());
}
if (auto renderWindowPart = this->GetRenderWindowPart())
{
renderWindowPart->RequestUpdate();
}
}
void QmitkFiberProcessingView::DoWeightColorCoding()
{
for (auto node : m_SelectedFB)
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
fib->ColorFibersByFiberWeights(m_Controls->m_FiberOpacityBox->isChecked(), m_Controls->m_NormalizeColorValues->isChecked());
}
if (auto renderWindowPart = this->GetRenderWindowPart())
{
renderWindowPart->RequestUpdate();
}
}
void QmitkFiberProcessingView::MirrorFibers()
{
unsigned int axis = this->m_Controls->m_MirrorFibersBox->currentIndex();
for (auto node : m_SelectedFB)
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
fib->MirrorFibers(axis);
}
for (auto surf : m_SelectedSurfaces)
{
vtkSmartPointer<vtkPolyData> poly = surf->GetVtkPolyData();
vtkSmartPointer<vtkPoints> vtkNewPoints = vtkSmartPointer<vtkPoints>::New();
for (int i=0; i<poly->GetNumberOfPoints(); i++)
{
double* point = poly->GetPoint(i);
point[axis] *= -1;
vtkNewPoints->InsertNextPoint(point);
}
poly->SetPoints(vtkNewPoints);
surf->CalculateBoundingBox();
}
if (auto renderWindowPart = this->GetRenderWindowPart())
{
renderWindowPart->RequestUpdate();
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingView.h
index cdc5e6d..eba1582 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberProcessingView.h
@@ -1,203 +1,203 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkFiberProcessingView_h
#define QmitkFiberProcessingView_h
#include <QmitkAbstractView.h>
#include "ui_QmitkFiberProcessingViewControls.h"
#include <mitkPlanarFigureComposite.h>
#include <mitkFiberBundle.h>
#include <mitkSurface.h>
#include <itkCastImageFilter.h>
#include <itkVTKImageImport.h>
#include <itkVTKImageExport.h>
#include <itkRegionOfInterestImageFilter.h>
#include <vtkLinearExtrusionFilter.h>
#include <vtkPolyDataToImageStencil.h>
#include <vtkSelectEnclosedPoints.h>
#include <vtkImageImport.h>
#include <vtkImageExport.h>
#include <vtkImageStencil.h>
#include <vtkSmartPointer.h>
#include <vtkSelection.h>
#include <vtkSelectionNode.h>
#include <vtkExtractSelectedThresholds.h>
#include <vtkFloatArray.h>
/*!
\brief View to process fiber bundles. Supplies methods to extract fibers from the bundle, fiber resampling, mirroring, join and subtract bundles and much more.
*/
class QmitkFiberProcessingView : public QmitkAbstractView
{
// 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:
typedef itk::Image< unsigned char, 3 > ItkUCharImageType;
typedef itk::Image< float, 3 > ItkFloatImageType;
static const std::string VIEW_ID;
QmitkFiberProcessingView();
virtual ~QmitkFiberProcessingView();
virtual void CreateQtPartControl(QWidget *parent) override;
///
/// Sets the focus to an internal widget.
///
virtual void SetFocus() override;
protected slots:
void OnDrawCircle(); ///< add circle interactors etc.
void OnDrawPolygon(); ///< add circle interactors etc.
void GenerateAndComposite();
void GenerateOrComposite();
void GenerateNotComposite();
void CopyBundles(); ///< add copies of selected bundles to data storage
void JoinBundles(); ///< merge selected fiber bundles
void SubstractBundles(); ///< subtract bundle A from bundle B. Not commutative! Defined by order of selection.
void GenerateRoiImage(); ///< generate binary image of selected planar figures.
void Remove();
void Extract();
void Modify();
void UpdateGui(); ///< update button activity etc. dpending on current datamanager selection
void OnMaskExtractionChanged();
virtual void AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name, const char *propertyKey = nullptr, mitk::BaseProperty *property = nullptr );
protected:
void MirrorFibers(); ///< mirror bundle on the specified plane
void ResampleSelectedBundlesSpline(); ///<
void ResampleSelectedBundlesLinear(); ///<
void DoImageColorCoding(); ///< color fibers by selected scalar image
void DoWeightColorCoding(); ///< color fibers by their respective weights
void DoLengthColorCoding(); ///< color fibers by length
void DoCurvatureColorCoding(); ///< color fibers by curvature
void CompressSelectedBundles(); ///< remove points below certain error threshold
void WeightFibers();
void ApplyWeightThreshold();
void ApplyDensityThreshold();
void RemoveWithMask(bool removeInside);
void RemoveDir();
void ApplyCurvatureThreshold(); ///< remove/split fibers with a too high curvature threshold
void PruneBundle(); ///< remove too short/too long fibers
void ExtractWithMask(bool onlyEnds, bool invert, bool labelmap);
void ExtractWithPlanarFigure(bool interactive=false);
void OnEndInteraction();
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
Ui::QmitkFiberProcessingViewControls* m_Controls;
/** Connection from VTK to ITK */
template <typename VTK_Exporter, typename ITK_Importer>
void ConnectPipelines(VTK_Exporter* exporter, ITK_Importer importer)
{
importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
importer->SetSpacingCallback(exporter->GetSpacingCallback());
importer->SetOriginCallback(exporter->GetOriginCallback());
importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback());
importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
importer->SetCallbackUserData(exporter->GetCallbackUserData());
}
template <typename ITK_Exporter, typename VTK_Importer>
void ConnectPipelines(ITK_Exporter exporter, VTK_Importer* importer)
{
importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
importer->SetSpacingCallback(exporter->GetSpacingCallback());
importer->SetOriginCallback(exporter->GetOriginCallback());
importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback());
importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
importer->SetCallbackUserData(exporter->GetCallbackUserData());
}
template < typename TPixel, unsigned int VImageDimension >
void InternalCalculateMaskFromPlanarFigure(
itk::Image< TPixel, VImageDimension > *image, unsigned int axis, std::string nodeName );
template < typename TPixel, unsigned int VImageDimension >
void InternalReorientImagePlane(
const itk::Image< TPixel, VImageDimension > *image, mitk::BaseGeometry* planegeo3D, int additionalIndex );
int m_CircleCounter; ///< used for data node naming
int m_PolygonCounter; ///< used for data node naming
std::vector<mitk::DataNode::Pointer> m_SelectedFB; ///< selected fiber bundle nodes
std::vector<mitk::DataNode::Pointer> m_SelectedPF; ///< selected planar figure nodes
std::vector<mitk::Surface::Pointer> m_SelectedSurfaces;
mitk::Image::Pointer m_SelectedImage;
mitk::Image::Pointer m_InternalImage;
mitk::PlanarFigure::Pointer m_PlanarFigure;
ItkUCharImageType::Pointer m_InternalImageMask3D;
ItkUCharImageType::Pointer m_PlanarFigureImage;
float m_UpsamplingFactor; ///< upsampling factor for all image generations
mitk::DataNode::Pointer m_RoiImageNode;
unsigned int m_StartInteractionObserverTag;
unsigned int m_EndInteractionObserverTag;
mitk::DataNode::Pointer m_InteractiveNode;
void AddCompositeToDatastorage(mitk::DataNode::Pointer pfc, std::vector<mitk::DataNode::Pointer> children, mitk::DataNode::Pointer parentNode=nullptr);
void debugPFComposition(mitk::PlanarFigureComposite::Pointer , int );
void WritePfToImage(mitk::DataNode::Pointer node, mitk::Image* image);
mitk::DataNode::Pointer GenerateTractDensityImage(mitk::FiberBundle::Pointer fib, bool binary, bool absolute);
mitk::DataNode::Pointer GenerateColorHeatmap(mitk::FiberBundle::Pointer fib);
mitk::DataNode::Pointer GenerateFiberEndingsImage(mitk::FiberBundle::Pointer fib);
mitk::DataNode::Pointer GenerateFiberEndingsPointSet(mitk::FiberBundle::Pointer fib);
void NodeAdded( const mitk::DataNode* node ) override;
void NodeRemoved(const mitk::DataNode* node) override;
void RemoveObservers();
void AddObservers();
};
#endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberQuantificationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberQuantificationView.cpp
index 2c0f941..1c622f4 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberQuantificationView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberQuantificationView.cpp
@@ -1,461 +1,461 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// Qmitk
#include "QmitkFiberQuantificationView.h"
// Qt
#include <QMessageBox>
// MITK
#include <mitkNodePredicateDataType.h>
#include <mitkNodePredicateDimension.h>
#include <mitkNodePredicateAnd.h>
#include <mitkImageCast.h>
#include <mitkPeakImage.h>
#include <mitkLabelSetImage.h>
#include <mitkDICOMSegmentationConstants.h>
#include <mitkDICOMSegmentationPropertyHelper.cpp>
#include <mitkDICOMQIPropertyHelper.h>
// ITK
#include <itkTractDensityImageFilter.h>
#include <itkTractsToRgbaImageFilter.h>
#include <itkTractsToVectorImageFilter.h>
#include <itkTractsToFiberEndingsImageFilter.h>
#include <mitkLexicalCast.h>
const std::string QmitkFiberQuantificationView::VIEW_ID = "org.mitk.views.fiberquantification";
using namespace mitk;
QmitkFiberQuantificationView::QmitkFiberQuantificationView()
: QmitkAbstractView()
, m_Controls( 0 )
, m_UpsamplingFactor(5)
, m_Visible(false)
{
}
// Destructor
QmitkFiberQuantificationView::~QmitkFiberQuantificationView()
{
}
void QmitkFiberQuantificationView::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::QmitkFiberQuantificationViewControls;
m_Controls->setupUi( parent );
connect( m_Controls->m_ProcessFiberBundleButton, SIGNAL(clicked()), this, SLOT(ProcessSelectedBundles()) );
connect( m_Controls->m_ExtractFiberPeaks, SIGNAL(clicked()), this, SLOT(CalculateFiberDirections()) );
m_Controls->m_TractBox->SetDataStorage(this->GetDataStorage());
mitk::TNodePredicateDataType<mitk::FiberBundle>::Pointer isFib = mitk::TNodePredicateDataType<mitk::FiberBundle>::New();
m_Controls->m_TractBox->SetPredicate( isFib );
m_Controls->m_ImageBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_ImageBox->SetZeroEntryText("--");
mitk::TNodePredicateDataType<mitk::Image>::Pointer isImagePredicate = mitk::TNodePredicateDataType<mitk::Image>::New();
mitk::NodePredicateDimension::Pointer is3D = mitk::NodePredicateDimension::New(3);
m_Controls->m_ImageBox->SetPredicate( mitk::NodePredicateAnd::New(isImagePredicate, is3D) );
connect( (QObject*)(m_Controls->m_TractBox), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()));
connect( (QObject*)(m_Controls->m_ImageBox), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()));
}
}
void QmitkFiberQuantificationView::Activated()
{
}
void QmitkFiberQuantificationView::Deactivated()
{
}
void QmitkFiberQuantificationView::Visible()
{
m_Visible = true;
}
void QmitkFiberQuantificationView::Hidden()
{
m_Visible = false;
}
void QmitkFiberQuantificationView::SetFocus()
{
m_Controls->m_ProcessFiberBundleButton->setFocus();
}
void QmitkFiberQuantificationView::CalculateFiberDirections()
{
typedef itk::Image<unsigned char, 3> ItkUcharImgType;
// load fiber bundle
mitk::FiberBundle::Pointer inputTractogram = dynamic_cast<mitk::FiberBundle*>(m_SelectedFB.back()->GetData());
itk::TractsToVectorImageFilter<float>::Pointer fOdfFilter = itk::TractsToVectorImageFilter<float>::New();
if (m_SelectedImage.IsNotNull())
{
ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New();
mitk::CastToItkImage<ItkUcharImgType>(m_SelectedImage, itkMaskImage);
fOdfFilter->SetMaskImage(itkMaskImage);
}
// extract directions from fiber bundle
fOdfFilter->SetFiberBundle(inputTractogram);
fOdfFilter->SetAngularThreshold(cos(m_Controls->m_AngularThreshold->value()*itk::Math::pi/180));
switch (m_Controls->m_FiberDirNormBox->currentIndex())
{
case 0:
fOdfFilter->SetNormalizationMethod(itk::TractsToVectorImageFilter<float>::NormalizationMethods::GLOBAL_MAX);
break;
case 1:
fOdfFilter->SetNormalizationMethod(itk::TractsToVectorImageFilter<float>::NormalizationMethods::SINGLE_VEC_NORM);
break;
case 2:
fOdfFilter->SetNormalizationMethod(itk::TractsToVectorImageFilter<float>::NormalizationMethods::MAX_VEC_NORM);
break;
}
fOdfFilter->SetSizeThreshold(m_Controls->m_PeakThreshold->value());
fOdfFilter->SetMaxNumDirections(m_Controls->m_MaxNumDirections->value());
fOdfFilter->Update();
QString name = m_SelectedFB.back()->GetName().c_str();
if (m_Controls->m_NumDirectionsBox->isChecked())
{
mitk::Image::Pointer mitkImage = mitk::Image::New();
mitkImage->InitializeByItk( fOdfFilter->GetNumDirectionsImage().GetPointer() );
mitkImage->SetVolume( fOdfFilter->GetNumDirectionsImage()->GetBufferPointer() );
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(mitkImage);
node->SetName((name+"_NUM_DIRECTIONS").toStdString().c_str());
GetDataStorage()->Add(node, m_SelectedFB.back());
}
Image::Pointer mitkImage = dynamic_cast<Image*>(PeakImage::New().GetPointer());
mitk::CastToMitkImage(fOdfFilter->GetDirectionImage(), mitkImage);
mitkImage->SetVolume(fOdfFilter->GetDirectionImage()->GetBufferPointer());
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(mitkImage);
node->SetName( (name+"_DIRECTIONS").toStdString().c_str());
GetDataStorage()->Add(node, m_SelectedFB.back());
}
void QmitkFiberQuantificationView::UpdateGui()
{
m_SelectedFB.clear();
if (m_Controls->m_TractBox->GetSelectedNode().IsNotNull())
m_SelectedFB.push_back(m_Controls->m_TractBox->GetSelectedNode());
m_SelectedImage = nullptr;
if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull())
m_SelectedImage = dynamic_cast<mitk::Image*>(m_Controls->m_ImageBox->GetSelectedNode()->GetData());
m_Controls->m_ProcessFiberBundleButton->setEnabled(!m_SelectedFB.empty());
m_Controls->m_ExtractFiberPeaks->setEnabled(!m_SelectedFB.empty());
}
void QmitkFiberQuantificationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList<mitk::DataNode::Pointer>& )
{
UpdateGui();
}
void QmitkFiberQuantificationView::ProcessSelectedBundles()
{
if ( m_SelectedFB.empty() ){
QMessageBox::information( nullptr, "Warning", "No fibe bundle selected!");
MITK_WARN("QmitkFiberQuantificationView") << "no fibe bundle selected";
return;
}
int generationMethod = m_Controls->m_GenerationBox->currentIndex();
for( unsigned int i=0; i<m_SelectedFB.size(); i++ )
{
mitk::DataNode::Pointer node = m_SelectedFB[i];
if (node.IsNotNull() && dynamic_cast<mitk::FiberBundle*>(node->GetData()))
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
QString name(node->GetName().c_str());
DataNode::Pointer newNode = nullptr;
switch(generationMethod){
case 0:
newNode = GenerateTractDensityImage(fib, false, true, node->GetName());
name += "_TDI";
break;
case 1:
newNode = GenerateTractDensityImage(fib, false, false, node->GetName());
name += "_TDI";
break;
case 2:
newNode = GenerateTractDensityImage(fib, true, false, node->GetName());
name += "_envelope";
break;
case 3:
newNode = GenerateColorHeatmap(fib);
break;
case 4:
newNode = GenerateFiberEndingsImage(fib);
name += "_fiber_endings";
break;
case 5:
newNode = GenerateFiberEndingsPointSet(fib);
name += "_fiber_endings";
break;
}
if (newNode.IsNotNull())
{
newNode->SetName(name.toStdString());
GetDataStorage()->Add(newNode);
}
}
}
}
// generate pointset displaying the fiber endings
mitk::DataNode::Pointer QmitkFiberQuantificationView::GenerateFiberEndingsPointSet(mitk::FiberBundle::Pointer fib)
{
mitk::PointSet::Pointer pointSet = mitk::PointSet::New();
vtkSmartPointer<vtkPolyData> fiberPolyData = fib->GetFiberPolyData();
int count = 0;
int numFibers = fib->GetNumFibers();
for( int i=0; i<numFibers; i++ )
{
vtkCell* cell = fiberPolyData->GetCell(i);
int numPoints = cell->GetNumberOfPoints();
vtkPoints* points = cell->GetPoints();
if (numPoints>0)
{
double* point = points->GetPoint(0);
itk::Point<float,3> itkPoint = mitk::imv::GetItkPoint(point);
pointSet->InsertPoint(count, itkPoint);
count++;
}
if (numPoints>2)
{
double* point = points->GetPoint(numPoints-1);
itk::Point<float,3> itkPoint = mitk::imv::GetItkPoint(point);
pointSet->InsertPoint(count, itkPoint);
count++;
}
}
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( pointSet );
return node;
}
// generate image displaying the fiber endings
mitk::DataNode::Pointer QmitkFiberQuantificationView::GenerateFiberEndingsImage(mitk::FiberBundle::Pointer fib)
{
typedef unsigned int OutPixType;
typedef itk::Image<OutPixType,3> OutImageType;
typedef itk::TractsToFiberEndingsImageFilter< OutImageType > ImageGeneratorType;
ImageGeneratorType::Pointer generator = ImageGeneratorType::New();
generator->SetFiberBundle(fib);
generator->SetUpsamplingFactor(m_Controls->m_UpsamplingSpinBox->value());
if (m_SelectedImage.IsNotNull())
{
OutImageType::Pointer itkImage = OutImageType::New();
CastToItkImage(m_SelectedImage, itkImage);
generator->SetInputImage(itkImage);
generator->SetUseImageGeometry(true);
}
generator->Update();
// get output image
OutImageType::Pointer outImg = generator->GetOutput();
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk(outImg.GetPointer());
img->SetVolume(outImg->GetBufferPointer());
// init data node
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(img);
return node;
}
// generate rgba heatmap from fiber bundle
mitk::DataNode::Pointer QmitkFiberQuantificationView::GenerateColorHeatmap(mitk::FiberBundle::Pointer fib)
{
typedef itk::RGBAPixel<unsigned char> OutPixType;
typedef itk::Image<OutPixType, 3> OutImageType;
typedef itk::TractsToRgbaImageFilter< OutImageType > ImageGeneratorType;
ImageGeneratorType::Pointer generator = ImageGeneratorType::New();
generator->SetFiberBundle(fib);
generator->SetUpsamplingFactor(m_Controls->m_UpsamplingSpinBox->value());
if (m_SelectedImage.IsNotNull())
{
itk::Image<unsigned char, 3>::Pointer itkImage = itk::Image<unsigned char, 3>::New();
CastToItkImage(m_SelectedImage, itkImage);
generator->SetInputImage(itkImage);
generator->SetUseImageGeometry(true);
}
generator->Update();
// get output image
typedef itk::Image<OutPixType,3> OutType;
OutType::Pointer outImg = generator->GetOutput();
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk(outImg.GetPointer());
img->SetVolume(outImg->GetBufferPointer());
// init data node
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(img);
return node;
}
// generate tract density image from fiber bundle
mitk::DataNode::Pointer QmitkFiberQuantificationView::GenerateTractDensityImage(mitk::FiberBundle::Pointer fib, bool binary, bool absolute, std::string name)
{
mitk::DataNode::Pointer node = mitk::DataNode::New();
if (binary)
{
typedef unsigned char OutPixType;
typedef itk::Image<OutPixType, 3> OutImageType;
itk::TractDensityImageFilter< OutImageType >::Pointer generator = itk::TractDensityImageFilter< OutImageType >::New();
generator->SetFiberBundle(fib);
generator->SetBinaryOutput(binary);
generator->SetOutputAbsoluteValues(absolute);
generator->SetUpsamplingFactor(m_Controls->m_UpsamplingSpinBox->value());
if (m_SelectedImage.IsNotNull())
{
OutImageType::Pointer itkImage = OutImageType::New();
CastToItkImage(m_SelectedImage, itkImage);
generator->SetInputImage(itkImage);
generator->SetUseImageGeometry(true);
}
generator->Update();
// get output image
typedef itk::Image<OutPixType,3> OutType;
OutType::Pointer outImg = generator->GetOutput();
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk(outImg.GetPointer());
img->SetVolume(outImg->GetBufferPointer());
if (m_SelectedImage.IsNotNull())
{
mitk::LabelSetImage::Pointer multilabelImage = mitk::LabelSetImage::New();
multilabelImage->InitializeByLabeledImage(img);
multilabelImage->GetActiveLabelSet()->SetActiveLabel(1);
mitk::Label::Pointer label = multilabelImage->GetActiveLabel();
label->SetName("Tractogram");
// Add Segmented Property Category Code Sequence tags (0062, 0003): Sequence defining the general category of this
// segment.
// (0008,0100) Code Value
label->SetProperty(
DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_CATEGORY_CODE_VALUE_PATH()).c_str(),
TemporoSpatialStringProperty::New("T-D000A"));
// (0008,0102) Coding Scheme Designator
label->SetProperty(
DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_CATEGORY_CODE_SCHEME_PATH()).c_str(),
TemporoSpatialStringProperty::New("SRT"));
// (0008,0104) Code Meaning
label->SetProperty(
DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_CATEGORY_CODE_MEANING_PATH()).c_str(),
TemporoSpatialStringProperty::New("Anatomical Structure"));
//------------------------------------------------------------
// Add Segmented Property Type Code Sequence (0062, 000F): Sequence defining the specific property type of this
// segment.
// (0008,0100) Code Value
label->SetProperty(
DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_TYPE_CODE_VALUE_PATH()).c_str(),
TemporoSpatialStringProperty::New("DUMMY"));
// (0008,0102) Coding Scheme Designator
label->SetProperty(
DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_TYPE_CODE_SCHEME_PATH()).c_str(),
TemporoSpatialStringProperty::New("SRT"));
// (0008,0104) Code Meaning
label->SetProperty(
DICOMTagPathToPropertyName(DICOMSegmentationConstants::SEGMENT_TYPE_CODE_MEANING_PATH()).c_str(),
TemporoSpatialStringProperty::New(name));
//Error: is undeclared// mitk::DICOMQIPropertyHandler::DeriveDICOMSourceProperties(m_SelectedImage, multilabelImage);
// init data node
node->SetData(multilabelImage);
}
else
{
// init data node
node->SetData(img);
}
}
else
{
typedef float OutPixType;
typedef itk::Image<OutPixType, 3> OutImageType;
itk::TractDensityImageFilter< OutImageType >::Pointer generator = itk::TractDensityImageFilter< OutImageType >::New();
generator->SetFiberBundle(fib);
generator->SetBinaryOutput(binary);
generator->SetOutputAbsoluteValues(absolute);
generator->SetUpsamplingFactor(m_Controls->m_UpsamplingSpinBox->value());
if (m_SelectedImage.IsNotNull())
{
OutImageType::Pointer itkImage = OutImageType::New();
CastToItkImage(m_SelectedImage, itkImage);
generator->SetInputImage(itkImage);
generator->SetUseImageGeometry(true);
}
//generator->SetDoFiberResampling(false);
generator->Update();
// get output image
typedef itk::Image<OutPixType,3> OutType;
OutType::Pointer outImg = generator->GetOutput();
mitk::Image::Pointer img = mitk::Image::New();
img->InitializeByItk(outImg.GetPointer());
img->SetVolume(outImg->GetBufferPointer());
// init data node
node->SetData(img);
}
return node;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberQuantificationView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberQuantificationView.h
index 36080de..5fb5380 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberQuantificationView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/QmitkFiberQuantificationView.h
@@ -1,86 +1,86 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkFiberQuantificationView_h
#define QmitkFiberQuantificationView_h
#include <QmitkAbstractView.h>
#include "ui_QmitkFiberQuantificationViewControls.h"
#include <mitkFiberBundle.h>
#include <mitkPointSet.h>
#include <itkCastImageFilter.h>
#include <mitkILifecycleAwarePart.h>
/*!
\brief Generation of images from fiber bundles (TDI, envelopes, endpoint distribution) and extraction of principal fiber directions from tractograms.
*/
class QmitkFiberQuantificationView : 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:
typedef itk::Image< unsigned char, 3 > itkUCharImageType;
static const std::string VIEW_ID;
QmitkFiberQuantificationView();
virtual ~QmitkFiberQuantificationView();
virtual void CreateQtPartControl(QWidget *parent) override;
///
/// Sets the focus to an internal widget.
///
virtual void SetFocus() override;
virtual void Activated() override;
virtual void Deactivated() override;
virtual void Visible() override;
virtual void Hidden() override;
protected slots:
void ProcessSelectedBundles(); ///< start selected operation on fiber bundle (e.g. tract density image generation)
void CalculateFiberDirections(); ///< Calculate main fiber directions from tractogram
void UpdateGui(); ///< update button activity etc. dpending on current datamanager selection
protected:
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
Ui::QmitkFiberQuantificationViewControls* m_Controls;
std::vector<mitk::DataNode::Pointer> m_SelectedFB; ///< selected fiber bundle nodes
mitk::Image::Pointer m_SelectedImage;
float m_UpsamplingFactor; ///< upsampling factor for all image generations
mitk::DataNode::Pointer GenerateTractDensityImage(mitk::FiberBundle::Pointer fib, bool binary, bool absolute, std::string name);
mitk::DataNode::Pointer GenerateColorHeatmap(mitk::FiberBundle::Pointer fib);
mitk::DataNode::Pointer GenerateFiberEndingsImage(mitk::FiberBundle::Pointer fib);
mitk::DataNode::Pointer GenerateFiberEndingsPointSet(mitk::FiberBundle::Pointer fib);
bool m_Visible;
};
#endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED
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 dc20806..7b5988e 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,352 +1,352 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
#include "QmitkTractometryView.h"
#include <mitkNodePredicateDataType.h>
#include <mitkNodePredicateDimension.h>
#include <mitkNodePredicateAnd.h>
#include <mitkImageCast.h>
#include <mitkImageAccessByItk.h>
#include <mitkImage.h>
#include <mitkFiberBundle.h>
#include <mitkDiffusionPropertyHelper.h>
#include <mitkITKImageImport.h>
#include <mitkPixelTypeMultiplex.h>
#include <mitkImagePixelReadAccessor.h>
#include <berryIPreferences.h>
#include <berryWorkbenchPlugin.h>
#include <berryQtPreferences.h>
#include <vtkLookupTable.h>
#include <QClipboard>
#include <mitkLexicalCast.h>
#include <QmitkChartWidget.h>
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_SamplingPointsBox, SIGNAL(valueChanged(int)), this, SLOT(UpdateGui()) );
connect( m_Controls->m_StDevBox, SIGNAL(stateChanged(int)), this, SLOT(UpdateGui()) );
mitk::TNodePredicateDataType<mitk::Image>::Pointer imageP = mitk::TNodePredicateDataType<mitk::Image>::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;
}
}
void QmitkTractometryView::SetFocus()
{
}
void QmitkTractometryView::UpdateGui()
{
berry::IWorkbenchPart::Pointer nullPart;
OnSelectionChanged(nullPart, QList<mitk::DataNode::Pointer>(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<itk::Point<double, 3>> ref_points;
for (int j=0; j<numPoints1; ++j)
{
double* p1 = points1->GetPoint(j);
itk::Point<double, 3> 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; j<numPoints1; ++j)
{
auto p1 = ref_points.at(j);
double* p2 = points2->GetPoint(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 <typename TPixel>
void QmitkTractometryView::ImageValuesAlongTract(const mitk::PixelType, mitk::Image::Pointer image, mitk::FiberBundle::Pointer fib, std::vector<std::vector<double> > &data, std::string& clipboard_string)
{
unsigned int num_points = m_Controls->m_SamplingPointsBox->value();
mitk::ImagePixelReadAccessor<TPixel,3> readimage(image, image->GetVolumeData(0));
mitk::FiberBundle::Pointer working_fib = fib->GetDeepCopy();
working_fib->ResampleToNumPoints(num_points);
vtkSmartPointer< vtkPolyData > polydata = working_fib->GetFiberPolyData();
std::vector<std::vector<double> > all_values;
std::vector< double > mean_values;
for (unsigned int i=0; i<num_points; ++i)
mean_values.push_back(0);
double min = 100000.0;
double max = 0;
double mean = 0;
for (unsigned int i=0; i<working_fib->GetNumFibers(); ++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; j<numPoints; j++)
{
double* p;
if (flip)
p = points->GetPoint(numPoints - j - 1);
else
p = points->GetPoint(j);
Point3D px;
px[0] = p[0];
px[1] = p[1];
px[2] = p[2];
double pixelValue = static_cast<double>(readimage.GetPixelByWorldCoordinates(px));
fib_vals.push_back(pixelValue);
mean += pixelValue;
if (pixelValue<min)
min = pixelValue;
else if (pixelValue>max)
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; i<num_points; ++i)
{
mean_values.at(i) /= working_fib->GetNumFibers();
double stdev = 0;
for (unsigned int j=0; j<all_values.size(); ++j)
{
double diff = mean_values.at(i) - all_values.at(j).at(i);
diff *= diff;
stdev += diff;
}
stdev /= all_values.size();
stdev = std::sqrt(stdev);
std_values1.push_back(mean_values.at(i) + stdev);
std_values2.push_back(mean_values.at(i) - stdev);
clipboard_string += boost::lexical_cast<std::string>(mean_values.at(i));
clipboard_string += " ";
clipboard_string += boost::lexical_cast<std::string>(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();
}
void QmitkTractometryView::Activated()
{
}
void QmitkTractometryView::Deactivated()
{
}
void QmitkTractometryView::Visible()
{
m_Visible = true;
QList<mitk::DataNode::Pointer> 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<int>(rgb[i] * 255);
}
return os.str();
}
void QmitkTractometryView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList<mitk::DataNode::Pointer>& nodes)
{
if (!m_Visible)
return;
m_CurrentSelection.clear();
if(m_Controls->m_ImageBox->GetSelectedNode().IsNull())
return;
std::string clipboardString = "";
m_ReferencePolyData = nullptr;
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(m_Controls->m_ImageBox->GetSelectedNode()->GetData());
vtkSmartPointer<vtkLookupTable> lookupTable = vtkSmartPointer<vtkLookupTable>::New();
lookupTable->SetTableRange(0.0, 1.0);
lookupTable->Build();
int num_tracts = 0;
for (auto node: nodes)
if ( dynamic_cast<mitk::FiberBundle*>(node->GetData()) )
num_tracts++;
int c = 1;
this->m_Controls->m_ChartWidget->Clear();
for (auto node: nodes)
{
if ( dynamic_cast<mitk::FiberBundle*>(node->GetData()) )
{
clipboardString += node->GetName() + "\n";
clipboardString += "mean stdev\n";
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
m_CurrentSelection.push_back(node);
std::vector< std::vector< double > > data;
mitkPixelTypeMultiplex4( ImageValuesAlongTract, image->GetPixelType(), image, fib, data, clipboardString );
m_Controls->m_ChartWidget->AddData1D(data.at(0), node->GetName() + " Mean", QmitkChartWidget::ChartType::line);
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);
}
double color[3];
if (num_tracts>1)
{
float scalar_color = ( (float)c/num_tracts - 1.0/num_tracts )/(1.0-1.0/num_tracts);
lookupTable->GetColor(1.0 - scalar_color, color);
}
else
lookupTable->GetColor(0, 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);
}
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 d1a6b4e..27ac1a0 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,81 +1,81 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <QmitkAbstractView.h>
#include "ui_QmitkTractometryViewControls.h"
#include <itkImage.h>
#include <mitkImage.h>
#include <mitkPixelType.h>
#include <mitkFiberBundle.h>
#include <mitkILifecycleAwarePart.h>
#include <QmitkChartWidget.h>
/*!
\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 <typename TPixel>
void ImageValuesAlongTract(const mitk::PixelType, mitk::Image::Pointer image, mitk::FiberBundle::Pointer fib, 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();
protected:
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
QmitkChartWidget::ColorTheme GetColorTheme();
Ui::QmitkTractometryViewControls* m_Controls;
bool Flip(vtkSmartPointer< vtkPolyData > polydata1, int i, vtkSmartPointer<vtkPolyData> ref_poly=nullptr);
std::string RGBToHexString(double *rgb);
vtkSmartPointer< vtkPolyData > m_ReferencePolyData;
QList<mitk::DataNode::Pointer> m_CurrentSelection;
bool m_Visible;
};
#endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/mitkPluginActivator.cpp
index 79b88cb..042b6c0 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/mitkPluginActivator.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/mitkPluginActivator.cpp
@@ -1,51 +1,51 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPluginActivator.h"
#include "src/internal/Perspectives/QmitkFiberProcessingPerspective.h"
#include "src/internal/QmitkFiberProcessingView.h"
#include "src/internal/QmitkFiberQuantificationView.h"
#include "src/internal/QmitkFiberClusteringView.h"
#include "src/internal/QmitkFiberFitView.h"
#include "src/internal/QmitkTractometryView.h"
ctkPluginContext* mitk::PluginActivator::m_Context = nullptr;
ctkPluginContext* mitk::PluginActivator::GetContext()
{
return m_Context;
}
void mitk::PluginActivator::start(ctkPluginContext* context)
{
BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberProcessingPerspective, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberQuantificationView, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberProcessingView, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberClusteringView, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkFiberFitView, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkTractometryView, context)
m_Context = context;
}
void mitk::PluginActivator::stop(ctkPluginContext* context)
{
Q_UNUSED(context)
m_Context = nullptr;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/mitkPluginActivator.h
index b19415a..436e913 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/mitkPluginActivator.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.fiberprocessing/src/internal/mitkPluginActivator.h
@@ -1,40 +1,40 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKPLUGINACTIVATOR_H
#define MITKPLUGINACTIVATOR_H
#include <ctkPluginActivator.h>
namespace mitk
{
class PluginActivator : public QObject, public ctkPluginActivator
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.mitk.gui.qt.diffusionimaging.fiberprocessing")
Q_INTERFACES(ctkPluginActivator)
public:
static ctkPluginContext* GetContext();
void start(ctkPluginContext* context) override;
void stop(ctkPluginContext* context) override;
private:
static ctkPluginContext* m_Context;
};
}
#endif
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/QmitkIVIMWidget.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/QmitkIVIMWidget.cpp
index a562180..5faa88e 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/QmitkIVIMWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/QmitkIVIMWidget.cpp
@@ -1,168 +1,168 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkIVIMWidget.h"
#include "mitkHistogramGenerator.h"
#include <qwt_scale_engine.h>
#include <qwt_legend.h>
QmitkIVIMWidget::QmitkIVIMWidget( QWidget * parent )
: QmitkPlotWidget(parent)
{
// this->SetAxisTitle( QwtPlot::xBottom, "Grayvalue" );
// this->SetAxisTitle( QwtPlot::yLeft, "Probability" );
// this->Replot();
QFrame* canvas = qobject_cast<QFrame*>(m_Plot->canvas());
if (canvas)
{
canvas->setLineWidth(0);
canvas->setContentsMargins(0,0,0,0);
}
auto linScale = new QwtLinearScaleEngine();
m_Plot->setAxisScaleEngine(1, linScale);
auto logScale = new QwtLogScaleEngine();
m_Plot->setAxisScaleEngine(0, logScale);
m_Plot->setAxisScale( 0, 0.15, 1.0 );
}
QmitkIVIMWidget::~QmitkIVIMWidget()
{
}
void QmitkIVIMWidget::DrawGauss()
{
}
void QmitkIVIMWidget::ClearItemModel()
{
}
std::vector<double> QmitkIVIMWidget::vec(const vnl_vector<double>& vector)
{
std::vector<double> retval(vector.size());
for(unsigned int i=0; i<vector.size(); i++)
{
retval.at(i) = vector[i];
}
return retval;
}
void QmitkIVIMWidget::SetParameters( IVIMFilterType::IVIMSnapshot snap )
{
this->Clear();
if (snap.bvalues.empty())
return;
QString s("f=%1, D=%2, D*=%3");
s = s.arg(snap.currentF,4);
s = s.arg(snap.currentD,4);
s = s.arg(snap.currentDStar,4);
int curveId = this->InsertCurve( s.toLatin1(), QColor(Qt::lightGray) );
this->SetCurvePen( curveId, QPen( Qt::NoPen ) );
QPen pen;
pen.setColor( QColor(Qt::cyan) );
pen.setStyle( Qt::DotLine );
pen.setWidth(2);
double maxb = snap.bvalues.max_value();
vnl_vector<double> xvals(2);
vnl_vector<double> yvals(2);
xvals[0] = 0;
xvals[1] = maxb;
yvals[0] = 1-snap.currentFunceiled;
yvals[1] = yvals[0]*exp(-maxb * snap.currentD);
curveId = this->InsertCurve( "contribution of D to the signal", QColor(Qt::lightGray) );
this->SetCurveData( curveId, vec(xvals), vec(yvals) );
this->SetCurvePen( curveId, pen );
this->SetCurveAntialiasingOn( curveId );
if(snap.currentDStar != 0)
{
pen.setStyle( Qt::SolidLine );
pen.setColor(Qt::red);
int nsampling = 50;
xvals.set_size(nsampling);
yvals.set_size(nsampling);
double f = 1-snap.currentFunceiled;
for(int i=0; i<nsampling; i++)
{
xvals[i] = (((1.0)*i)/(1.0*nsampling))*maxb;
yvals[i] = f*exp(- xvals[i] * snap.currentD) + (1-f)*exp(- xvals[i] * (snap.currentD+snap.currentDStar));
}
curveId = this->InsertCurve( "resulting fit of the model", QColor(Qt::lightGray) );
this->SetCurveData( curveId, vec(xvals), vec(yvals) );
this->SetCurvePen( curveId, pen );
this->SetCurveAntialiasingOn( curveId );
}
// plot points after all curves to force prettier legend formatting
// lines
// points
// curveId = this->InsertCurve( "ignored measurement points", QColor(Qt::lightGray) );
// this->SetCurveData( curveId, vec(snap.bvalues), vec(snap.allmeas) );
// this->SetCurvePen( curveId, QPen(Qt::NoPen) );
// QwtSymbol* blackSymbol = new QwtSymbol(QwtSymbol::Diamond, QColor(Qt::black), QColor(Qt::black), QSize(8,8));
// this->SetCurveSymbol(curveId, blackSymbol);
// QwtSymbol* redSymbol = new QwtSymbol(QwtSymbol::Diamond, QColor(Qt::red), QColor(Qt::red), QSize(8,8));
QwtSymbol* whiteDiamond = new QwtSymbol(QwtSymbol::Diamond, QColor(Qt::white), QColor(Qt::black), QSize(8,8));
QwtSymbol* whiteStar = new QwtSymbol(QwtSymbol::XCross, QColor(Qt::white), QColor(Qt::white), QSize(8,8));
curveId = this->InsertCurve( "points first fit", QColor(Qt::lightGray) );
this->SetCurveData( curveId, vec(snap.bvals1), vec(snap.meas1) );
this->SetCurvePen( curveId, QPen( Qt::NoPen ) );
this->SetCurveSymbol(curveId, whiteDiamond);
if(snap.currentDStar != 0 && !snap.high_indices.empty())
{
std::vector< double > additonal_bvals;
std::vector< double > additonal_meas;
for (int i=0; i<snap.high_indices[0]; ++i)
{
additonal_bvals.push_back(snap.bvals2[i]);
additonal_meas.push_back(snap.meas2[i]);
}
if (!additonal_bvals.empty())
{
curveId = this->InsertCurve( "additional points second fit", QColor(Qt::lightGray) );
this->SetCurveData( curveId, additonal_bvals, additonal_meas );
this->SetCurvePen( curveId, QPen( Qt::NoPen ) );
this->SetCurveSymbol(curveId, whiteStar);
}
}
auto legend = new QwtLegend();
m_Plot->insertLegend(legend, QwtPlot::BottomLegend);
m_Plot->setAxisTitle(0, "S/S0");
m_Plot->setAxisTitle(1, "b");
this->Replot();
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/QmitkIVIMWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/QmitkIVIMWidget.h
index 180bc36..31f3781 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/QmitkIVIMWidget.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/QmitkIVIMWidget.h
@@ -1,58 +1,58 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkIVIMWidget_H_
#define QmitkIVIMWidget_H_
#include "QmitkPlotWidget.h"
#include "mitkImage.h"
#include "itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.h"
/**
* \brief Widget for displaying image histograms based on the vtkQtChart
* framework
*/
class QmitkIVIMWidget : public QmitkPlotWidget
{
public:
typedef itk::DiffusionIntravoxelIncoherentMotionReconstructionImageFilter<short, float> IVIMFilterType;
typedef mitk::Image::HistogramType HistogramType;
typedef mitk::Image::HistogramType::ConstIterator HistogramConstIteratorType;
void SetParameters( IVIMFilterType::IVIMSnapshot snap );
QmitkIVIMWidget( QWidget * /*parent = 0 */);
virtual ~QmitkIVIMWidget();
void DrawGauss();
void ClearItemModel();
std::vector< std::vector<double>* > m_Vals;
private:
std::vector<double> vec(const vnl_vector<double>& vector);
};
#endif /* QmitkIVIMWidget_H_ */
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/QmitkKurtosisWidget.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/QmitkKurtosisWidget.cpp
index 7d7df55..2918173 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/QmitkKurtosisWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/QmitkKurtosisWidget.cpp
@@ -1,133 +1,133 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkKurtosisWidget.h"
#include <qwt_scale_engine.h>
#include <qwt_legend.h>
QmitkKurtosisWidget::QmitkKurtosisWidget(QWidget *parent)
: QmitkPlotWidget(parent)
{
QFrame* canvas = qobject_cast< QFrame* >( m_Plot->canvas() );
if( canvas )
{
canvas->setLineWidth(0);
canvas->setContentsMargins(0, 0, 0, 0);
}
}
QmitkKurtosisWidget::~QmitkKurtosisWidget()
{
}
void QmitkKurtosisWidget::SetData(KurtosisFilterType::KurtosisSnapshot snap)
{
this->Clear();
if( snap.bvalues.empty() )
return;
double max_y_val = 1.4 * fmax( snap.measurements[0], snap.m_BzeroFit );
auto logScale = new QwtLogScaleEngine();
m_Plot->setAxisScaleEngine(0, logScale );
m_Plot->setAxisScale(0, 0.1, max_y_val );
QString s("D=%1, K=%2");
s = s.arg( snap.m_D, 4); s = s.arg( snap.m_K, 4);
// insert formatted value string to legend (curve without pen)
int curveId = this->InsertCurve( s.toLatin1(), QColor( Qt::lightGray ) );
this->SetCurvePen( curveId, QPen( Qt::NoPen ) );
// get the x-axis maximum
const double max_bvalue = snap.bvalues.max_value();
//
// Data-points
//
auto measured_values = toStdVec( snap.measurements );
double y_bzero = measured_values[0];
MITK_INFO << "-------------";
MITK_INFO << y_bzero;
MITK_INFO << snap.m_D;
MITK_INFO << snap.m_K;
const unsigned int num_samples = 50;
vnl_vector<double> x_K_model(num_samples);
vnl_vector<double> y_K_model(num_samples);
vnl_vector<double> y_D_model(num_samples);
const double x_tics_offset = max_bvalue / static_cast<double>( num_samples );
for( unsigned int i=0; i<num_samples; ++i)
{
x_K_model[i] = i * x_tics_offset;
double bval = x_K_model[i];
y_K_model[i] = y_bzero * exp( -bval * snap.m_D + bval*bval * snap.m_D * snap.m_D * snap.m_K / 6.0 );
y_D_model[i] = y_bzero * exp( -bval * snap.m_D );
}
// Only D-modelled signal
QPen pen;
pen.setWidth(2);
pen.setColor( QColor(Qt::cyan) );
pen.setStyle( Qt::DotLine );
auto d_curve = this->InsertCurve( "D-part of the fitted model", QColor(Qt::lightGray) );
this->SetCurveData( d_curve, toStdVec( x_K_model ), toStdVec( y_D_model ) );
this->SetCurvePen( d_curve, pen );
this->SetCurveAntialiasingOn( d_curve );
// Kurtosis - full modelled signal
pen.setColor( QColor( Qt::red ));
pen.setStyle( Qt::SolidLine );
auto kurtosis_curve = this->InsertCurve( "Resulting fit of the model", QColor(Qt::lightGray) );
this->SetCurveData( kurtosis_curve, toStdVec( x_K_model ), toStdVec( y_K_model ) );
this->SetCurvePen( kurtosis_curve, pen );
this->SetCurveAntialiasingOn( kurtosis_curve );
auto measurements_curve = this->InsertCurve( "Measured values", QColor(Qt::lightGray) );
this->SetCurveData( measurements_curve, toStdVec( snap.fit_bvalues ), toStdVec( snap.fit_measurements) );
this->SetCurvePen( measurements_curve, QPen(Qt::NoPen) );
QwtSymbol* whiteDiamond = new QwtSymbol(QwtSymbol::Diamond, QColor(Qt::white), QColor(Qt::black), QSize(8,8));
this->SetCurveSymbol( measurements_curve, whiteDiamond );
// add Legend
auto legend = new QwtLegend();
legend->setMaxColumns(3);
m_Plot->insertLegend( legend, QwtPlot::BottomLegend );
m_Plot->setAxisTitle(0, "S");
this->Replot();
}
std::vector<double> QmitkKurtosisWidget::toStdVec(const vnl_vector<double>& vector)
{
std::vector<double> retval(vector.size());
for(unsigned int i=0; i<vector.size(); i++)
{
retval.at(i) = vector[i];
}
return retval;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/QmitkKurtosisWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/QmitkKurtosisWidget.h
index 4aa86d5..bdc80df 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/QmitkKurtosisWidget.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/QmitkKurtosisWidget.h
@@ -1,45 +1,45 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QMITKKURTOSISWIDGET_H
#define QMITKKURTOSISWIDGET_H
#include "QmitkPlotWidget.h"
#include "itkDiffusionKurtosisReconstructionImageFilter.h"
class QmitkKurtosisWidget : public QmitkPlotWidget
{
public:
typedef itk::DiffusionKurtosisReconstructionImageFilter<short, float> KurtosisFilterType;
QmitkKurtosisWidget( QWidget* /* parent */);
virtual ~QmitkKurtosisWidget();
void SetData( KurtosisFilterType::KurtosisSnapshot snap );
std::vector< std::vector<double>* > m_Vals;
private:
std::vector<double> toStdVec(const vnl_vector<double>& vector);
};
#endif // QMITKKURTOSISWIDGET_H
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/Perspectives/QmitkDIAppIVIMPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/Perspectives/QmitkDIAppIVIMPerspective.cpp
index d3ed62b..f7fcdae 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/Perspectives/QmitkDIAppIVIMPerspective.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/Perspectives/QmitkDIAppIVIMPerspective.cpp
@@ -1,46 +1,46 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkDIAppIVIMPerspective.h"
#include "berryIViewLayout.h"
void QmitkDIAppIVIMPerspective::CreateInitialLayout(berry::IPageLayout::Pointer layout)
{
/////////////////////////////////////////////////////
// all di-app perspectives should have the following:
/////////////////////////////////////////////////////
QString editorArea = layout->GetEditorArea();
layout->AddStandaloneViewPlaceholder("org.mitk.views.viewnavigatorview", berry::IPageLayout::LEFT, 0.3f, editorArea, false);
layout->AddStandaloneView("org.mitk.views.datamanager", false, berry::IPageLayout::LEFT, 0.3f, editorArea);
layout->AddStandaloneView("org.mitk.views.controlvisualizationpropertiesview", false, berry::IPageLayout::BOTTOM, .15f, "org.mitk.views.datamanager");
berry::IFolderLayout::Pointer left =
layout->CreateFolder("org.mbi.diffusionimaginginternal.leftcontrols", berry::IPageLayout::BOTTOM, 0.15f, "org.mitk.views.controlvisualizationpropertiesview");
layout->AddStandaloneViewPlaceholder("org.mitk.views.imagenavigator", berry::IPageLayout::BOTTOM, .7f, "org.mbi.diffusionimaginginternal.leftcontrols", false);
/////////////////////////////////////////////
// here goes the perspective specific stuff
/////////////////////////////////////////////
left->AddView("org.mitk.views.ivim");
left->AddView("org.mitk.views.segmentation");
left->AddView("org.mitk.views.imagestatistics");
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/Perspectives/QmitkDIAppIVIMPerspective.h b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/Perspectives/QmitkDIAppIVIMPerspective.h
index 630e26f..2a8aa8c 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/Perspectives/QmitkDIAppIVIMPerspective.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/Perspectives/QmitkDIAppIVIMPerspective.h
@@ -1,36 +1,36 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkDIAppIVIMPerspective_H_
#define QmitkDIAppIVIMPerspective_H_
#include <berryIPerspectiveFactory.h>
class QmitkDIAppIVIMPerspective : public QObject, public berry::IPerspectiveFactory
{
Q_OBJECT
Q_INTERFACES(berry::IPerspectiveFactory)
public:
QmitkDIAppIVIMPerspective() {}
~QmitkDIAppIVIMPerspective() {}
void CreateInitialLayout(berry::IPageLayout::Pointer layout) override;
};
#endif /* QmitkDIAppIVIMPerspective_H_ */
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMView.cpp
index 4b8acbe..99ca828 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMView.cpp
@@ -1,939 +1,939 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// Qmitk
#include "QmitkIVIMView.h"
// qt
#include "qmessagebox.h"
#include "qclipboard.h"
// mitk
#include "mitkImage.h"
#include "mitkImageCast.h"
#include "mitkLookupTable.h"
#include "mitkLookupTableProperty.h"
#include <mitkSliceNavigationController.h>
#include <QmitkRenderWindow.h>
// itk
#include "itkScalarImageToHistogramGenerator.h"
#include "itkRegionOfInterestImageFilter.h"
#include "itkImageRegionConstIteratorWithIndex.h"
// itk/mitk
#include "itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.h"
#include "itkRegularizedIVIMReconstructionFilter.h"
#include "mitkImageCast.h"
#include <mitkImageStatisticsHolder.h>
#include <mitkNodePredicateIsDWI.h>
#include <mitkNodePredicateDimension.h>
#include <mitkNodePredicateProperty.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateDataType.h>
const std::string QmitkIVIMView::VIEW_ID = "org.mitk.views.ivim";
QmitkIVIMView::QmitkIVIMView()
: QmitkAbstractView()
, m_Controls( 0 )
, m_Active(false)
, m_Visible(false)
, m_HoldUpdate(false)
{
}
QmitkIVIMView::~QmitkIVIMView()
{
}
void QmitkIVIMView::CreateQtPartControl( QWidget *parent )
{
// hold update untill all elements are set
this->m_HoldUpdate = true;
// build up qt view, unless already done
if ( !m_Controls )
{
// create GUI widgets from the Qt Designer's .ui file
m_Controls = new Ui::QmitkIVIMViewControls;
m_Controls->setupUi( parent );
connect( m_Controls->m_ButtonStart, SIGNAL(clicked()), this, SLOT(FittIVIMStart()) );
connect( m_Controls->m_ButtonAutoThres, SIGNAL(clicked()), this, SLOT(AutoThreshold()) );
connect( m_Controls->m_MethodCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(MethodCombo(int)) );
connect( m_Controls->m_DStarSlider, SIGNAL(valueChanged(int)), this, SLOT(DStarSlider(int)) );
connect( m_Controls->m_BThreshSlider, SIGNAL(valueChanged(int)), this, SLOT(BThreshSlider(int)) );
connect( m_Controls->m_S0ThreshSlider, SIGNAL(valueChanged(int)), this, SLOT(S0ThreshSlider(int)) );
connect( m_Controls->m_NumItSlider, SIGNAL(valueChanged(int)), this, SLOT(NumItsSlider(int)) );
connect( m_Controls->m_LambdaSlider, SIGNAL(valueChanged(int)), this, SLOT(LambdaSlider(int)) );
connect( m_Controls->m_CheckDStar, SIGNAL(clicked()), this, SLOT(Checkbox()) );
connect( m_Controls->m_CheckD, SIGNAL(clicked()), this, SLOT(Checkbox()) );
connect( m_Controls->m_Checkf, SIGNAL(clicked()), this, SLOT(Checkbox()) );
connect( m_Controls->m_ChooseMethod, SIGNAL(clicked()), this, SLOT(ChooseMethod()) );
connect( m_Controls->m_CurveClipboard, SIGNAL(clicked()), this, SLOT(ClipboardCurveButtonClicked()) );
connect( m_Controls->m_ValuesClipboard, SIGNAL(clicked()), this, SLOT(ClipboardStatisticsButtonClicked()) );
// connect all kurtosis actions to a recompute
connect( m_Controls->m_KurtosisRangeWidget, SIGNAL( rangeChanged(double, double)), this, SLOT(OnKurtosisParamsChanged() ) );
//connect( m_Controls->m_MaximalBValueWidget, SIGNAL( valueChanged(double)), this, SLOT( OnKurtosisParamsChanged() ) );
connect( m_Controls->m_OmitBZeroCB, SIGNAL( stateChanged(int) ), this, SLOT( OnKurtosisParamsChanged() ) );
connect( m_Controls->m_KurtosisFitScale, SIGNAL( currentIndexChanged(int)), this, SLOT( OnKurtosisParamsChanged() ) );
connect( m_Controls->m_UseKurtosisBoundsCB, SIGNAL(clicked() ), this, SLOT( OnKurtosisParamsChanged() ) );
m_SliceChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart());
connect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged()));
m_Controls->m_DwiBox->SetDataStorage(this->GetDataStorage());
mitk::NodePredicateIsDWI::Pointer isDwi = mitk::NodePredicateIsDWI::New();
m_Controls->m_DwiBox->SetPredicate( isDwi );
connect( (QObject*)(m_Controls->m_DwiBox), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()));
m_Controls->m_MaskBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_MaskBox->SetZeroEntryText("--");
mitk::TNodePredicateDataType<mitk::Image>::Pointer isImagePredicate = mitk::TNodePredicateDataType<mitk::Image>::New();
mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true));
mitk::NodePredicateDimension::Pointer is3D = mitk::NodePredicateDimension::New(3);
m_Controls->m_MaskBox->SetPredicate( mitk::NodePredicateAnd::New(isBinaryPredicate, mitk::NodePredicateAnd::New(isImagePredicate, is3D)) );
connect( (QObject*)(m_Controls->m_MaskBox), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()));
connect( (QObject*)(m_Controls->m_ModelTabSelectionWidget), SIGNAL(currentChanged(int)), this, SLOT(UpdateGui()));
}
QString dstar = QString::number(m_Controls->m_DStarSlider->value()/1000.0);
m_Controls->m_DStarLabel->setText(dstar);
QString bthresh = QString::number(m_Controls->m_BThreshSlider->value()*5.0);
m_Controls->m_BThreshLabel->setText(bthresh);
QString s0thresh = QString::number(m_Controls->m_S0ThreshSlider->value()*0.5);
m_Controls->m_S0ThreshLabel->setText(s0thresh);
QString numits = QString::number(m_Controls->m_NumItSlider->value());
m_Controls->m_NumItsLabel->setText(numits);
QString lambda = QString::number(m_Controls->m_LambdaSlider->value()*.00001);
m_Controls->m_LambdaLabel->setText(lambda);
m_Controls->m_MethodCombo->setVisible(m_Controls->m_ChooseMethod->isChecked());
m_Controls->m_Warning->setVisible(false);
MethodCombo(m_Controls->m_MethodCombo->currentIndex());
m_Controls->m_KurtosisRangeWidget->setSingleStep(0.1);
m_Controls->m_KurtosisRangeWidget->setRange( 0.0, 10.0 );
m_Controls->m_KurtosisRangeWidget->setMaximumValue( 5.0 );
// LogScale not working yet, have to fix that first
// m_Controls->m_KurtosisFitScale->setEnabled(false);
//m_Controls->m_MaximalBValueWidget->setVisible( false );
// release update block after the UI-elements were all set
this->m_HoldUpdate = false;
}
void QmitkIVIMView::SetFocus()
{
m_Controls->m_ButtonAutoThres->setFocus();
}
void QmitkIVIMView::Checkbox()
{
OnSliceChanged();
}
void QmitkIVIMView::MethodCombo(int val)
{
switch(val)
{
case 0:
m_Controls->m_DstarFrame->setVisible(false);
m_Controls->m_NeglSiFrame->setVisible(true);
m_Controls->m_NeglBframe->setVisible(false);
m_Controls->m_IterationsFrame->setVisible(false);
m_Controls->m_LambdaFrame->setVisible(false);
break;
case 1:
m_Controls->m_DstarFrame->setVisible(true);
m_Controls->m_NeglSiFrame->setVisible(true);
m_Controls->m_NeglBframe->setVisible(false);
m_Controls->m_IterationsFrame->setVisible(false);
m_Controls->m_LambdaFrame->setVisible(false);
break;
case 2:
m_Controls->m_DstarFrame->setVisible(false);
m_Controls->m_NeglSiFrame->setVisible(true);
m_Controls->m_NeglBframe->setVisible(true);
m_Controls->m_IterationsFrame->setVisible(false);
m_Controls->m_LambdaFrame->setVisible(false);
break;
case 3:
m_Controls->m_DstarFrame->setVisible(false);
m_Controls->m_NeglSiFrame->setVisible(true);
m_Controls->m_NeglBframe->setVisible(true);
m_Controls->m_IterationsFrame->setVisible(false);
m_Controls->m_LambdaFrame->setVisible(false);
break;
case 4:
m_Controls->m_DstarFrame->setVisible(false);
m_Controls->m_NeglSiFrame->setVisible(false);
m_Controls->m_NeglBframe->setVisible(false);
m_Controls->m_IterationsFrame->setVisible(false);
m_Controls->m_LambdaFrame->setVisible(false);
break;
}
OnSliceChanged();
}
void QmitkIVIMView::DStarSlider (int val)
{
QString sval = QString::number(val/1000.0);
m_Controls->m_DStarLabel->setText(sval);
OnSliceChanged();
}
void QmitkIVIMView::BThreshSlider (int val)
{
QString sval = QString::number(val*5.0);
m_Controls->m_BThreshLabel->setText(sval);
OnSliceChanged();
}
void QmitkIVIMView::S0ThreshSlider (int val)
{
QString sval = QString::number(val*0.5);
m_Controls->m_S0ThreshLabel->setText(sval);
OnSliceChanged();
}
void QmitkIVIMView::NumItsSlider (int val)
{
QString sval = QString::number(val);
m_Controls->m_NumItsLabel->setText(sval);
OnSliceChanged();
}
void QmitkIVIMView::LambdaSlider (int val)
{
QString sval = QString::number(val*.00001);
m_Controls->m_LambdaLabel->setText(sval);
OnSliceChanged();
}
void QmitkIVIMView::UpdateGui()
{
if (m_Controls->m_DwiBox->GetSelectedNode().IsNotNull())
{
m_Controls->m_VisualizeResultsWidget->setVisible(true);
m_Controls->m_KurtosisVisualizationWidget->setVisible(true);
m_HoldUpdate = false;
}
else
{
m_Controls->m_VisualizeResultsWidget->setVisible(false);
m_Controls->m_KurtosisVisualizationWidget->setVisible(false);
}
m_Controls->m_ButtonStart->setEnabled( m_Controls->m_DwiBox->GetSelectedNode().IsNotNull() );
m_Controls->m_ButtonAutoThres->setEnabled( m_Controls->m_DwiBox->GetSelectedNode().IsNotNull() );
m_Controls->m_ControlsFrame->setEnabled( m_Controls->m_DwiBox->GetSelectedNode().IsNotNull() );
m_Controls->m_BottomControlsFrame->setEnabled( m_Controls->m_DwiBox->GetSelectedNode().IsNotNull() );
OnSliceChanged();
}
void QmitkIVIMView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList<mitk::DataNode::Pointer>& )
{
UpdateGui();
}
void QmitkIVIMView::AutoThreshold()
{
if (m_Controls->m_DwiBox->GetSelectedNode().IsNull())
{
// Nothing selected. Inform the user and return
QMessageBox::information( nullptr, "Template", "Please load and select a diffusion image before starting image processing.");
return;
}
mitk::Image* dimg = dynamic_cast<mitk::Image*>(m_Controls->m_DwiBox->GetSelectedNode()->GetData());
if (!dimg)
{
// Nothing selected. Inform the user and return
QMessageBox::information( nullptr, "Template", "No valid diffusion image was found.");
return;
}
// find bzero index
int index = -1;
auto directions = mitk::DiffusionPropertyHelper::GetGradientContainer(dimg);
for(DirContainerType::ConstIterator it = directions->Begin();
it != directions->End(); ++it)
{
index++;
GradientDirectionType g = it.Value();
if(g[0] == 0 && g[1] == 0 && g[2] == 0 )
break;
}
VecImgType::Pointer vecimg = VecImgType::New();
mitk::CastToItkImage(dimg, vecimg);
int vecLength = vecimg->GetVectorLength();
index = index > vecLength-1 ? vecLength-1 : index;
MITK_INFO << "Performing Histogram Analysis on Channel" << index;
typedef itk::Image<short,3> ImgType;
ImgType::Pointer img = ImgType::New();
mitk::CastToItkImage(dimg, img);
itk::ImageRegionIterator<ImgType> itw (img, img->GetLargestPossibleRegion() );
itw.GoToBegin();
itk::ImageRegionConstIterator<VecImgType> itr (vecimg, vecimg->GetLargestPossibleRegion() );
itr.GoToBegin();
while(!itr.IsAtEnd())
{
itw.Set(itr.Get().GetElement(index));
++itr;
++itw;
}
typedef itk::Statistics::ScalarImageToHistogramGenerator< ImgType >
HistogramGeneratorType;
typedef HistogramGeneratorType::HistogramType HistogramType;
HistogramGeneratorType::Pointer histogramGenerator = HistogramGeneratorType::New();
histogramGenerator->SetInput( img );
histogramGenerator->SetMarginalScale( 10 ); // Defines y-margin width of histogram
histogramGenerator->SetNumberOfBins( 100 ); // CT range [-1024, +2048] --> bin size 4 values
histogramGenerator->SetHistogramMin( dimg->GetStatistics()->GetScalarValueMin() );
histogramGenerator->SetHistogramMax( dimg->GetStatistics()->GetScalarValueMax() * .5 );
histogramGenerator->Compute();
HistogramType::ConstIterator iter = histogramGenerator->GetOutput()->Begin();
float maxFreq = 0;
float maxValue = 0;
while ( iter != histogramGenerator->GetOutput()->End() )
{
if(iter.GetFrequency() > maxFreq)
{
maxFreq = iter.GetFrequency();
maxValue = iter.GetMeasurementVector()[0];
}
++iter;
}
maxValue *= 2;
int sliderPos = maxValue * 2;
m_Controls->m_S0ThreshSlider->setValue(sliderPos);
S0ThreshSlider(sliderPos);
}
void QmitkIVIMView::FittIVIMStart()
{
if (m_Controls->m_DwiBox->GetSelectedNode().IsNull())
{
QMessageBox::information( nullptr, "Template", "No valid diffusion-weighted image selected.");
return;
}
mitk::Image* img = dynamic_cast<mitk::Image*>(m_Controls->m_DwiBox->GetSelectedNode()->GetData());
VecImgType::Pointer vecimg = VecImgType::New();
mitk::CastToItkImage(img, vecimg);
OutImgType::IndexType dummy;
if( m_Controls->m_ModelTabSelectionWidget->currentIndex() )
{
// KURTOSIS
KurtosisFilterType::Pointer filter = KurtosisFilterType::New();
filter->SetInput(vecimg);
filter->SetReferenceBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(img));
filter->SetGradientDirections(mitk::DiffusionPropertyHelper::GetGradientContainer(img));
filter->SetSmoothingSigma( this->m_Controls->m_SigmaSpinBox->value() );
if( this->m_Controls->m_UseKurtosisBoundsCB->isChecked() )
filter->SetBoundariesForKurtosis( this->m_Controls->m_KurtosisRangeWidget->minimumValue(), this->m_Controls->m_KurtosisRangeWidget->maximumValue() );
filter->SetFittingScale( static_cast<itk::FitScale>(this->m_Controls->m_KurtosisFitScale->currentIndex() ) );
if( m_Controls->m_MaskBox->GetSelectedNode().IsNotNull() )
{
mitk::Image::Pointer maskImg = dynamic_cast<mitk::Image*>(m_Controls->m_MaskBox->GetSelectedNode()->GetData());
typedef itk::Image<short, 3> MaskImgType;
MaskImgType::Pointer maskItk;
CastToItkImage( maskImg, maskItk );
filter->SetImageMask( maskItk );
}
filter->Update();
mitk::LookupTable::Pointer kurt_map_lut = mitk::LookupTable::New();
kurt_map_lut->SetType( mitk::LookupTable::JET );
mitk::LookupTableProperty::Pointer kurt_lut_prop =
mitk::LookupTableProperty::New();
kurt_lut_prop->SetLookupTable( kurt_map_lut );
mitk::Image::Pointer dimage = mitk::Image::New();
dimage->InitializeByItk( filter->GetOutput(0) );
dimage->SetVolume( filter->GetOutput(0)->GetBufferPointer());
mitk::Image::Pointer kimage = mitk::Image::New();
kimage->InitializeByItk( filter->GetOutput(1) );
kimage->SetVolume( filter->GetOutput(1)->GetBufferPointer());
QString new_dname = "Kurtosis_DMap";
new_dname.append("_Method-"+m_Controls->m_KurtosisFitScale->currentText());
QString new_kname = "Kurtosis_KMap";
new_kname.append("_Method-"+m_Controls->m_KurtosisFitScale->currentText());
if( this->m_Controls->m_CheckKurtD->isChecked() )
{
mitk::DataNode::Pointer dnode = mitk::DataNode::New();
dnode->SetData( dimage );
dnode->SetName(new_dname.toLatin1());
dnode->SetProperty("LookupTable", kurt_lut_prop );
GetDataStorage()->Add(dnode, m_Controls->m_DwiBox->GetSelectedNode());
}
if( this->m_Controls->m_CheckKurtK->isChecked() )
{
mitk::DataNode::Pointer knode = mitk::DataNode::New();
knode->SetData( kimage );
knode->SetName(new_kname.toLatin1());
knode->SetProperty("LookupTable", kurt_lut_prop );
GetDataStorage()->Add(knode, m_Controls->m_DwiBox->GetSelectedNode());
}
}
else
{
FittIVIM(vecimg, mitk::DiffusionPropertyHelper::GetGradientContainer(img), mitk::DiffusionPropertyHelper::GetReferenceBValue(img), true, dummy);
OutputToDatastorage(m_Controls->m_DwiBox->GetSelectedNode());
}
}
void QmitkIVIMView::OnKurtosisParamsChanged()
{
OnSliceChanged();
}
void QmitkIVIMView::OnSliceChanged()
{
if(m_HoldUpdate || !m_Visible)
return;
m_Controls->m_Warning->setVisible(false);
if(!m_Controls || m_Controls->m_DwiBox->GetSelectedNode().IsNull())
return;
m_Controls->m_VisualizeResultsWidget->setVisible(false);
m_Controls->m_KurtosisVisualizationWidget->setVisible(false);
mitk::Image::Pointer diffusionImg = dynamic_cast<mitk::Image*>(m_Controls->m_DwiBox->GetSelectedNode()->GetData());
mitk::Image::Pointer maskImg = nullptr;
if (m_Controls->m_MaskBox->GetSelectedNode().IsNotNull())
maskImg = dynamic_cast<mitk::Image*>(m_Controls->m_MaskBox->GetSelectedNode()->GetData());
if (!this->GetRenderWindowPart()) return;
VecImgType::Pointer vecimg = VecImgType::New();
mitk::CastToItkImage(diffusionImg, vecimg);
VecImgType::Pointer roiImage = VecImgType::New();
bool success = false;
if(maskImg.IsNull())
{
int roisize = 0;
if(m_Controls->m_MethodCombo->currentIndex() == 4)
roisize = 5;
mitk::Point3D pos = this->GetRenderWindowPart()->GetSelectedPosition();
VecImgType::IndexType crosspos;
diffusionImg->GetGeometry()->WorldToIndex(pos, crosspos);
if (!vecimg->GetLargestPossibleRegion().IsInside(crosspos))
{
m_Controls->m_Warning->setText(QString("Crosshair position not inside of selected diffusion weighted image. Reinit needed!"));
m_Controls->m_Warning->setVisible(true);
return;
}
else
m_Controls->m_Warning->setVisible(false);
VecImgType::IndexType index;
index[0] = crosspos[0] - roisize; index[0] = index[0] < 0 ? 0 : index[0];
index[1] = crosspos[1] - roisize; index[1] = index[1] < 0 ? 0 : index[1];
index[2] = crosspos[2] - roisize; index[2] = index[2] < 0 ? 0 : index[2];
VecImgType::SizeType size;
size[0] = roisize*2+1;
size[1] = roisize*2+1;
size[2] = roisize*2+1;
VecImgType::SizeType maxSize = vecimg->GetLargestPossibleRegion().GetSize();
size[0] = index[0]+size[0] > maxSize[0] ? maxSize[0]-index[0] : size[0];
size[1] = index[1]+size[1] > maxSize[1] ? maxSize[1]-index[1] : size[1];
size[2] = index[2]+size[2] > maxSize[2] ? maxSize[2]-index[2] : size[2];
VecImgType::RegionType region;
region.SetSize( size );
region.SetIndex( index );
vecimg->SetRequestedRegion( region );
VecImgType::IndexType newstart;
newstart.Fill(0);
VecImgType::RegionType newregion;
newregion.SetSize( size );
newregion.SetIndex( newstart );
roiImage->CopyInformation( vecimg );
roiImage->SetRegions( newregion );
roiImage->SetOrigin( pos );
roiImage->Allocate();
roiImage->SetPixel(newstart, vecimg->GetPixel(index));
if( m_Controls->m_ModelTabSelectionWidget->currentIndex() )
{
success = FitKurtosis(roiImage,
mitk::DiffusionPropertyHelper::GetGradientContainer(diffusionImg),
mitk::DiffusionPropertyHelper::GetReferenceBValue(diffusionImg),
newstart);
}
else
{
success = FittIVIM(roiImage,
mitk::DiffusionPropertyHelper::GetGradientContainer(diffusionImg),
mitk::DiffusionPropertyHelper::GetReferenceBValue(diffusionImg),
false,
crosspos);
}
}
else
{
typedef itk::Image<float,3> MaskImgType;
MaskImgType::Pointer maskItk;
CastToItkImage( maskImg, maskItk );
mitk::Point3D pos;
pos[0] = 0;
pos[1] = 0;
pos[2] = 0;
VecImgType::IndexType index;
index[0] = 0;
index[1] = 0;
index[2] = 0;
VecImgType::SizeType size;
size[0] = 1;
size[1] = 1;
size[2] = 1;
VecImgType::RegionType region;
region.SetSize( size );
region.SetIndex( index );
vecimg->SetRequestedRegion( region );
// iterators over output and input
itk::ImageRegionConstIteratorWithIndex<VecImgType>
vecit(vecimg, vecimg->GetLargestPossibleRegion());
itk::VariableLengthVector<double> avg(vecimg->GetVectorLength());
avg.Fill(0);
float numPixels = 0;
while ( ! vecit.IsAtEnd() )
{
VecImgType::PointType point;
vecimg->TransformIndexToPhysicalPoint(vecit.GetIndex(), point);
MaskImgType::IndexType index;
maskItk->TransformPhysicalPointToIndex(point, index);
if(maskItk->GetPixel(index) != 0)
{
avg += vecit.Get();
numPixels += 1.0;
}
// update iterators
++vecit;
}
avg /= numPixels;
m_Controls->m_Warning->setText(QString("Averaging ")+QString::number((int)numPixels)+QString(" voxels!"));
m_Controls->m_Warning->setVisible(true);
roiImage->CopyInformation( vecimg );
roiImage->SetRegions( region );
roiImage->SetOrigin( pos );
roiImage->Allocate();
roiImage->SetPixel(index, avg);
if( m_Controls->m_ModelTabSelectionWidget->currentIndex() )
{
success = FitKurtosis(roiImage,
mitk::DiffusionPropertyHelper::GetGradientContainer(diffusionImg),
mitk::DiffusionPropertyHelper::GetReferenceBValue(diffusionImg),
index);
}
else
{
success = FittIVIM(roiImage,
mitk::DiffusionPropertyHelper::GetGradientContainer(diffusionImg),
mitk::DiffusionPropertyHelper::GetReferenceBValue(diffusionImg),
false,
index);
}
// do not update until selection changed, the values will remain the same as long as the mask is selected!
m_HoldUpdate = true;
}
vecimg->SetRegions( vecimg->GetLargestPossibleRegion() );
if (success)
{
// 0 - IVIM, 1 - Kurtosis
if( m_Controls->m_ModelTabSelectionWidget->currentIndex() )
{
m_Controls->m_KurtosisVisualizationWidget->setVisible(true);
m_Controls->m_KurtosisVisualizationWidget->SetData(m_KurtosisSnap);
}
else
{
m_Controls->m_VisualizeResultsWidget->setVisible(true);
m_Controls->m_VisualizeResultsWidget->SetParameters(m_Snap);
}
}
}
bool QmitkIVIMView::FitKurtosis( itk::VectorImage<short, 3> *vecimg, DirContainerType *dirs, float bval, OutImgType::IndexType &crosspos )
{
KurtosisFilterType::Pointer filter = KurtosisFilterType::New();
itk::KurtosisFitConfiguration fit_config;
fit_config.omit_bzero = this->m_Controls->m_OmitBZeroCB->isChecked();
if( this->m_Controls->m_UseKurtosisBoundsCB->isChecked() )
{
fit_config.use_K_limits = true;
vnl_vector_fixed<double, 2> k_limits;
k_limits[0] = this->m_Controls->m_KurtosisRangeWidget->minimumValue();
k_limits[1] = this->m_Controls->m_KurtosisRangeWidget->maximumValue();
fit_config.K_limits = k_limits;
}
fit_config.fit_scale = static_cast<itk::FitScale>(this->m_Controls->m_KurtosisFitScale->currentIndex() );
m_KurtosisSnap = filter->GetSnapshot( vecimg->GetPixel( crosspos ), dirs, bval, fit_config );
return true;
}
bool QmitkIVIMView::FittIVIM(itk::VectorImage<short,3>* vecimg, DirContainerType* dirs, float bval, bool multivoxel, OutImgType::IndexType &crosspos)
{
IVIMFilterType::Pointer filter = IVIMFilterType::New();
filter->SetInput(vecimg);
filter->SetGradientDirections(dirs);
filter->SetBValue(bval);
switch(m_Controls->m_MethodCombo->currentIndex())
{
case 0:
filter->SetMethod(IVIMFilterType::IVIM_FIT_ALL);
filter->SetS0Thres(m_Controls->m_S0ThreshLabel->text().toDouble());
break;
case 1:
filter->SetMethod(IVIMFilterType::IVIM_DSTAR_FIX);
filter->SetDStar(m_Controls->m_DStarLabel->text().toDouble());
filter->SetS0Thres(m_Controls->m_S0ThreshLabel->text().toDouble());
break;
case 2:
filter->SetMethod(IVIMFilterType::IVIM_D_THEN_DSTAR);
filter->SetBThres(m_Controls->m_BThreshLabel->text().toDouble());
filter->SetS0Thres(m_Controls->m_S0ThreshLabel->text().toDouble());
filter->SetFitDStar(m_Controls->m_CheckDStar->isChecked());
break;
case 3:
filter->SetMethod(IVIMFilterType::IVIM_LINEAR_D_THEN_F);
filter->SetBThres(m_Controls->m_BThreshLabel->text().toDouble());
filter->SetS0Thres(m_Controls->m_S0ThreshLabel->text().toDouble());
filter->SetFitDStar(m_Controls->m_CheckDStar->isChecked());
break;
case 4:
filter->SetMethod(IVIMFilterType::IVIM_REGULARIZED);
filter->SetBThres(m_Controls->m_BThreshLabel->text().toDouble());
filter->SetS0Thres(m_Controls->m_S0ThreshLabel->text().toDouble());
filter->SetNumberIterations(m_Controls->m_NumItsLabel->text().toInt());
filter->SetLambda(m_Controls->m_LambdaLabel->text().toDouble());
filter->SetFitDStar(m_Controls->m_CheckDStar->isChecked());
break;
}
if(!multivoxel)
{
filter->SetFitDStar(true);
}
filter->SetNumberOfThreads(1);
filter->SetVerbose(false);
filter->SetCrossPosition(crosspos);
try{
filter->Update();
m_Snap = filter->GetSnapshot();
m_DStarMap = filter->GetOutput(2);
m_DMap = filter->GetOutput(1);
m_fMap = filter->GetOutput();
}
catch (itk::ExceptionObject &ex)
{
MITK_INFO << ex ;
m_Controls->m_Warning->setText(QString("IVIM fit not possible: ")+ex.GetDescription());
m_Controls->m_Warning->setVisible(true);
return false;
}
return true;
}
void QmitkIVIMView::OutputToDatastorage(mitk::DataNode::Pointer node)
{
mitk::LookupTable::Pointer lut = mitk::LookupTable::New();
lut->SetType( mitk::LookupTable::JET );
mitk::LookupTableProperty::Pointer lut_prop = mitk::LookupTableProperty::New();
lut_prop->SetLookupTable( lut );
if(m_Controls->m_CheckDStar->isChecked())
{
mitk::Image::Pointer dstarimage = mitk::Image::New();
dstarimage->InitializeByItk(m_DStarMap.GetPointer());
dstarimage->SetVolume(m_DStarMap->GetBufferPointer());
QString newname2 = ""; newname2 = newname2.append("IVIM_DStarMap_Method-%1").arg(m_Controls->m_MethodCombo->currentText());
mitk::DataNode::Pointer node2=mitk::DataNode::New();
node2->SetData( dstarimage );
node2->SetName(newname2.toLatin1());
node2->SetProperty("LookupTable", lut_prop );
GetDataStorage()->Add(node2, node);
}
if(m_Controls->m_CheckD->isChecked())
{
mitk::Image::Pointer dimage = mitk::Image::New();
dimage->InitializeByItk(m_DMap.GetPointer());
dimage->SetVolume(m_DMap->GetBufferPointer());
QString newname1 = ""; newname1 = newname1.append("IVIM_DMap_Method-%1").arg(m_Controls->m_MethodCombo->currentText());
mitk::DataNode::Pointer node1=mitk::DataNode::New();
node1->SetData( dimage );
node1->SetName(newname1.toLatin1());
node1->SetProperty("LookupTable", lut_prop );
GetDataStorage()->Add(node1, node);
}
if(m_Controls->m_Checkf->isChecked())
{
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk(m_fMap.GetPointer());
image->SetVolume(m_fMap->GetBufferPointer());
QString newname0 = ""; newname0 = newname0.append("IVIM_fMap_Method-%1").arg(m_Controls->m_MethodCombo->currentText());
mitk::DataNode::Pointer node3=mitk::DataNode::New();
node3->SetData( image );
node3->SetName(newname0.toLatin1());
node3->SetProperty("LookupTable", lut_prop );
GetDataStorage()->Add(node3, node);
}
this->GetRenderWindowPart()->RequestUpdate();
}
void QmitkIVIMView::ChooseMethod()
{
m_Controls->m_MethodCombo->setVisible(m_Controls->m_ChooseMethod->isChecked());
}
void QmitkIVIMView::ClipboardCurveButtonClicked()
{
// Kurtosis
if ( m_Controls->m_ModelTabSelectionWidget->currentIndex() )
{
std::stringstream ss;
QString clipboard("Measurement Points\n");
ss << m_KurtosisSnap.bvalues << "\n" << m_KurtosisSnap.measurements << "\n\n";
ss << "Fitted Values ( D K [b_0] ) \n" << m_KurtosisSnap.m_D << " " << m_KurtosisSnap.m_K;
if( m_KurtosisSnap.m_fittedBZero )
ss << " " << m_KurtosisSnap.m_BzeroFit;
ss << "\n\n";
clipboard.append( QString( ss.str().c_str() ));
ss.str( std::string() );
ss.clear();
QApplication::clipboard()->setText(
clipboard, QClipboard::Clipboard );
}
else
{
QString clipboard("Measurement Points\n");
for ( unsigned int i=0; i<m_Snap.bvalues.size(); i++)
{
clipboard = clipboard.append( "%L1 \t" )
.arg( m_Snap.bvalues[i], 0, 'f', 2 );
}
clipboard = clipboard.append( "\n" );
for ( unsigned int i=0; i<m_Snap.allmeas.size(); i++)
{
clipboard = clipboard.append( "%L1 \t" )
.arg( m_Snap.allmeas[i], 0, 'f', 2 );
}
clipboard = clipboard.append( "\n" );
clipboard = clipboard.append( "1st Linear Fit of D and f \n" );
double maxb = m_Snap.bvalues.max_value();
clipboard = clipboard.append( "%L1 \t %L2 \n %L3 \t %L4 \n" )
.arg( (float) 0, 0, 'f', 2 )
.arg( maxb, 0, 'f', 2 )
.arg(1-m_Snap.currentFunceiled, 0, 'f', 2 )
.arg((1-m_Snap.currentFunceiled)*exp(-maxb * m_Snap.currentD), 0, 'f', 2 );
int nsampling = 50;
double f = 1-m_Snap.currentFunceiled;
clipboard = clipboard.append("Final Model\n");
for(int i=0; i<nsampling; i++)
{
double x = (((1.0)*i)/(1.0*nsampling))*maxb;
clipboard = clipboard.append( "%L1 \t" )
.arg( x, 0, 'f', 2 );
}
clipboard = clipboard.append( "\n" );
for(int i=0; i<nsampling; i++)
{
double x = (((1.0)*i)/(1.0*nsampling))*maxb;
double y = f*exp(- x * m_Snap.currentD) + (1-f)*exp(- x * (m_Snap.currentD+m_Snap.currentDStar));
clipboard = clipboard.append( "%L1 \t" )
.arg( y, 0, 'f', 2 );
}
clipboard = clipboard.append( "\n" );
QApplication::clipboard()->setText(
clipboard, QClipboard::Clipboard );
}
}
void QmitkIVIMView::ClipboardStatisticsButtonClicked()
{
// Kurtosis
if ( m_Controls->m_ModelTabSelectionWidget->currentIndex() )
{
QString clipboard( "D \t K \n" );
clipboard = clipboard.append( "%L1 \t %L2" )
.arg( m_KurtosisSnap.m_D, 0, 'f', 10 )
.arg( m_KurtosisSnap.m_K, 0, 'f', 10 ) ;
QApplication::clipboard()->setText(
clipboard, QClipboard::Clipboard );
}
else
{
QString clipboard( "f \t D \t D* \n" );
clipboard = clipboard.append( "%L1 \t %L2 \t %L3" )
.arg( m_Snap.currentF, 0, 'f', 10 )
.arg( m_Snap.currentD, 0, 'f', 10 )
.arg( m_Snap.currentDStar, 0, 'f', 10 ) ;
QApplication::clipboard()->setText(
clipboard, QClipboard::Clipboard );
}
}
void QmitkIVIMView::Activated()
{
m_Active = true;
}
void QmitkIVIMView::Deactivated()
{
m_Active = false;
}
void QmitkIVIMView::Visible()
{
m_Visible = true;
QList<mitk::DataNode::Pointer> selection = GetDataManagerSelection();
berry::IWorkbenchPart::Pointer nullPart;
OnSelectionChanged(nullPart, selection);
}
void QmitkIVIMView::Hidden()
{
m_Visible = false;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMView.h
index 7c1d090..3b4e060 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMView.h
@@ -1,127 +1,127 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _QMITKIVIMVIEW_H_INCLUDED
#define _QMITKIVIMVIEW_H_INCLUDED
#include <berryISelectionListener.h>
#include <QmitkAbstractView.h>
#include <mitkILifecycleAwarePart.h>
#include <mitkIRenderWindowPartListener.h>
#include "ui_QmitkIVIMViewControls.h"
#include "itkVectorImage.h"
#include "itkImage.h"
#include <mitkDiffusionPropertyHelper.h>
#include "itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.h"
#include "itkDiffusionKurtosisReconstructionImageFilter.h"
#include <QmitkSliceNavigationListener.h>
/*!
\brief QmitkIVIMView
\warning This application module is not yet documented. Use "svn blame/praise/annotate" and ask the author to provide basic documentation.
*/
class QmitkIVIMView : 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;
QmitkIVIMView();
virtual ~QmitkIVIMView();
typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType DirContainerType;
typedef itk::DiffusionIntravoxelIncoherentMotionReconstructionImageFilter<short, float> IVIMFilterType;
typedef itk::DiffusionKurtosisReconstructionImageFilter<short, float> KurtosisFilterType;
typedef itk::VectorImage<short,3> VecImgType;
typedef itk::Image<float,3> OutImgType;
virtual void CreateQtPartControl(QWidget *parent) override;
///
/// Sets the focus to an internal widget.
///
virtual void SetFocus() override;
void OutputToDatastorage(mitk::DataNode::Pointer node);
bool FittIVIM(itk::VectorImage<short,3>* vecimg, DirContainerType* dirs, float bval, bool multivoxel, OutImgType::IndexType &crosspos);
void Activated() override;
void Deactivated() override;
void Visible() override;
void Hidden() override;
protected slots:
void OnSliceChanged();
/// \brief Called when the user clicks the GUI button
void FittIVIMStart();
void AutoThreshold();
void MethodCombo(int val);
void Checkbox();
void DStarSlider(int val);
void BThreshSlider(int val);
void S0ThreshSlider(int val);
void NumItsSlider(int val);
void LambdaSlider(int val);
void ChooseMethod();
void ClipboardStatisticsButtonClicked();
void ClipboardCurveButtonClicked();
void OnKurtosisParamsChanged();
void UpdateGui();
protected:
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
bool FitKurtosis( itk::VectorImage<short, 3> *vecimg, DirContainerType *dirs, float bval, OutImgType::IndexType &crosspos);
Ui::QmitkIVIMViewControls* m_Controls;
OutImgType::Pointer m_DStarMap;
OutImgType::Pointer m_DMap;
OutImgType::Pointer m_fMap;
IVIMFilterType::IVIMSnapshot m_Snap;
KurtosisFilterType::KurtosisSnapshot m_KurtosisSnap;
bool m_Active;
bool m_Visible;
bool m_HoldUpdate;
QmitkSliceNavigationListener m_SliceChangeListener;
};
#endif // _QMITKIVIMVIEW_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/mitkPluginActivator.cpp
index cf8bad0..1557fe7 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/mitkPluginActivator.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/mitkPluginActivator.cpp
@@ -1,43 +1,43 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPluginActivator.h"
#include "src/internal/Perspectives/QmitkDIAppIVIMPerspective.h"
#include "src/internal/QmitkIVIMView.h"
ctkPluginContext* mitk::PluginActivator::m_Context = nullptr;
ctkPluginContext* mitk::PluginActivator::GetContext()
{
return m_Context;
}
void mitk::PluginActivator::start(ctkPluginContext* context)
{
BERRY_REGISTER_EXTENSION_CLASS(QmitkDIAppIVIMPerspective, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkIVIMView, context)
m_Context = context;
}
void mitk::PluginActivator::stop(ctkPluginContext* context)
{
Q_UNUSED(context)
m_Context = nullptr;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/mitkPluginActivator.h
index ffa9eb5..fcd5adc 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/mitkPluginActivator.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/mitkPluginActivator.h
@@ -1,40 +1,40 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKPLUGINACTIVATOR_H
#define MITKPLUGINACTIVATOR_H
#include <ctkPluginActivator.h>
namespace mitk
{
class PluginActivator : public QObject, public ctkPluginActivator
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.mitk.gui.qt.diffusionimaging.ivim")
Q_INTERFACES(ctkPluginActivator)
public:
static ctkPluginContext* GetContext();
void start(ctkPluginContext* context) override;
void stop(ctkPluginContext* context) override;
private:
static ctkPluginContext* m_Context;
};
}
#endif
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/QmitkOdfMaximaExtractionView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/QmitkOdfMaximaExtractionView.cpp
index f046029..4a8c699 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/QmitkOdfMaximaExtractionView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/QmitkOdfMaximaExtractionView.cpp
@@ -1,382 +1,382 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
//misc
#include <QFileDialog>
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// Qmitk
#include "QmitkOdfMaximaExtractionView.h"
#include <mitkImageCast.h>
#include <mitkFiberBundle.h>
#include <mitkImage.h>
#include <mitkImageToItk.h>
#include <mitkTensorImage.h>
#include <itkVectorImage.h>
#include <itkOdfMaximaExtractionFilter.h>
#include <itkOdfMaximaExtractionFilter.h>
#include <itkShCoefficientImageImporter.h>
#include <itkDiffusionTensorPrincipalDirectionImageFilter.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateDimension.h>
#include <mitkNodePredicateOr.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateDataType.h>
#include <mitkNodePredicateProperty.h>
#include <mitkNodePredicateIsDWI.h>
#include <mitkPeakImage.h>
#include <mitkShImage.h>
// Qt
#include <QMessageBox>
const std::string QmitkOdfMaximaExtractionView::VIEW_ID = "org.mitk.views.odfmaximaextractionview";
using namespace mitk;
QmitkOdfMaximaExtractionView::QmitkOdfMaximaExtractionView()
: m_Controls(nullptr)
{
}
// Destructor
QmitkOdfMaximaExtractionView::~QmitkOdfMaximaExtractionView()
{
}
void QmitkOdfMaximaExtractionView::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::QmitkOdfMaximaExtractionViewControls;
m_Controls->setupUi(parent);
connect((QObject*)m_Controls->m_StartPeakExtractionButton, SIGNAL(clicked()), (QObject*) this, SLOT(StartPeakExtraction()));
connect((QObject*)m_Controls->m_ImportShCoeffs, SIGNAL(clicked()), (QObject*) this, SLOT(ConvertShCoeffs()));
m_Controls->m_MaskBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_ImageBox->SetDataStorage(this->GetDataStorage());
mitk::TNodePredicateDataType<mitk::ShImage>::Pointer isShImage = mitk::TNodePredicateDataType<mitk::ShImage>::New();
mitk::TNodePredicateDataType<mitk::TensorImage>::Pointer isTensorImage = mitk::TNodePredicateDataType<mitk::TensorImage>::New();
mitk::NodePredicateNot::Pointer isDwi = mitk::NodePredicateNot::New(mitk::NodePredicateIsDWI::New());
mitk::NodePredicateNot::Pointer isOdf = mitk::NodePredicateNot::New(mitk::NodePredicateDataType::New("OdfImage"));
mitk::NodePredicateAnd::Pointer unwanted = mitk::NodePredicateAnd::New(isOdf, isDwi);
mitk::NodePredicateDimension::Pointer dim3 = mitk::NodePredicateDimension::New(3);
mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true));
m_Controls->m_MaskBox->SetPredicate(mitk::NodePredicateAnd::New(mitk::NodePredicateAnd::New(unwanted, dim3), isBinaryPredicate));
m_Controls->m_ImageBox->SetPredicate(mitk::NodePredicateOr::New(isTensorImage, isShImage));
m_Controls->m_MaskBox->SetZeroEntryText("--");
connect( (QObject*)(m_Controls->m_ImageBox), SIGNAL(OnSelectionChanged(const mitk::DataNode*)), this, SLOT(OnImageSelectionChanged()) );
m_Controls->m_StartPeakExtractionButton->setVisible(false);
m_Controls->m_ImportShCoeffs->setVisible(false);
}
}
void QmitkOdfMaximaExtractionView::SetFocus()
{
}
void QmitkOdfMaximaExtractionView::StartPeakExtraction()
{
if (dynamic_cast<TensorImage*>(m_Controls->m_ImageBox->GetSelectedNode()->GetData()) != nullptr)
{
StartTensorPeakExtraction(dynamic_cast<TensorImage*>(m_Controls->m_ImageBox->GetSelectedNode()->GetData()));
}
else
{
StartMaximaExtraction(dynamic_cast<Image*>(m_Controls->m_ImageBox->GetSelectedNode()->GetData()));
}
}
template<int shOrder>
void QmitkOdfMaximaExtractionView::TemplatedConvertShCoeffs(mitk::Image* mitkImg)
{
typedef itk::ShCoefficientImageImporter< float, shOrder > FilterType;
typedef mitk::ImageToItk< itk::Image< float, 4 > > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(mitkImg);
caster->Update();
typename FilterType::Pointer filter = FilterType::New();
filter->SetInputImage(caster->GetOutput());
filter->GenerateData();
typename FilterType::CoefficientImageType::Pointer itkCi = filter->GetCoefficientImage();
{
mitk::Image::Pointer img = dynamic_cast<mitk::Image*>(mitk::ShImage::New().GetPointer());
img->InitializeByItk(itkCi.GetPointer());
img->SetVolume(itkCi->GetBufferPointer());
DataNode::Pointer node = DataNode::New();
node->SetData(img);
QString name(m_Controls->m_ImageBox->GetSelectedNode()->GetName().c_str());
name += "_ShImage_Imported";
node->SetName(name.toStdString().c_str());
GetDataStorage()->Add(node, m_Controls->m_ImageBox->GetSelectedNode());
}
}
void QmitkOdfMaximaExtractionView::ConvertShCoeffs()
{
if (m_Controls->m_ImageBox->GetSelectedNode().IsNull())
return;
Image::Pointer mitkImg = dynamic_cast<Image*>(m_Controls->m_ImageBox->GetSelectedNode()->GetData());
if (mitkImg->GetDimension() != 4 && mitkImg->GetLargestPossibleRegion().GetSize()[3]<6)
{
MITK_INFO << "wrong image type (need 4 dimensions)";
return;
}
int nrCoeffs = mitkImg->GetLargestPossibleRegion().GetSize()[3];
switch (nrCoeffs)
{
case 6:
TemplatedConvertShCoeffs<2>(mitkImg);
break;
case 15:
TemplatedConvertShCoeffs<4>(mitkImg);
break;
case 28:
TemplatedConvertShCoeffs<6>(mitkImg);
break;
case 45:
TemplatedConvertShCoeffs<8>(mitkImg);
break;
case 66:
TemplatedConvertShCoeffs<10>(mitkImg);
break;
case 91:
TemplatedConvertShCoeffs<12>(mitkImg);
break;
default :
QMessageBox::warning(nullptr, "Error", "Only spherical harmonics orders 2-12 are supported.", QMessageBox::Ok);
}
}
void QmitkOdfMaximaExtractionView::StartTensorPeakExtraction(mitk::TensorImage* img)
{
typedef itk::DiffusionTensorPrincipalDirectionImageFilter< float > MaximaExtractionFilterType;
MaximaExtractionFilterType::Pointer filter = MaximaExtractionFilterType::New();
filter->SetUsePolarCoordinates(false);
mitk::BaseGeometry::Pointer geometry;
try{
ItkTensorImage::Pointer itkImage = ItkTensorImage::New();
CastToItkImage(img, itkImage);
filter->SetInput(itkImage);
geometry = img->GetGeometry();
}
catch (itk::ExceptionObject &e)
{
MITK_INFO << "wrong image type: " << e.what();
QMessageBox::warning(nullptr, "Wrong pixel type", "Could not perform Tensor Principal Direction Extraction due to Image has wrong pixel type.", QMessageBox::Ok);
return;
}
if (m_Controls->m_MaskBox->GetSelectedNode().IsNotNull())
{
ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New();
Image::Pointer mitkMaskImg = dynamic_cast<Image*>(m_Controls->m_MaskBox->GetSelectedNode()->GetData());
CastToItkImage(mitkMaskImg, itkMaskImage);
filter->SetMaskImage(itkMaskImage);
}
if (m_Controls->m_NormalizationBox->currentIndex() == 0)
filter->SetNormalizeVectors(false);
filter->SetFaThreshold(m_Controls->m_AbsoluteThresholdBox->value());
filter->Update();
MaximaExtractionFilterType::PeakImageType::Pointer itkImg = filter->GetPeakImage();
mitk::Image::Pointer mitkPeakImage = dynamic_cast<Image*>(PeakImage::New().GetPointer());
CastToMitkImage(itkImg, mitkPeakImage);
DataNode::Pointer node = DataNode::New();
node->SetData(mitkPeakImage);
QString name(m_Controls->m_ImageBox->GetSelectedNode()->GetName().c_str());
name += "_PrincipalDirection";
node->SetName(name.toStdString().c_str());
GetDataStorage()->Add(node, m_Controls->m_ImageBox->GetSelectedNode());
if (m_Controls->m_OutputNumDirectionsBox->isChecked())
{
ItkUcharImgType::Pointer numDirImage = filter->GetOutput();
mitk::Image::Pointer image2 = mitk::Image::New();
image2->InitializeByItk(numDirImage.GetPointer());
image2->SetVolume(numDirImage->GetBufferPointer());
DataNode::Pointer node2 = DataNode::New();
node2->SetData(image2);
QString name(m_Controls->m_ImageBox->GetSelectedNode()->GetName().c_str());
name += "_NumDirections";
node2->SetName(name.toStdString().c_str());
GetDataStorage()->Add(node2, m_Controls->m_ImageBox->GetSelectedNode());
}
}
template<int shOrder>
void QmitkOdfMaximaExtractionView::StartMaximaExtraction(Image *image)
{
typedef itk::OdfMaximaExtractionFilter< float, shOrder, ODF_SAMPLING_SIZE > MaximaExtractionFilterType;
typename MaximaExtractionFilterType::Pointer filter = MaximaExtractionFilterType::New();
switch (m_Controls->m_ToolkitBox->currentIndex())
{
case 0:
filter->SetToolkit(MaximaExtractionFilterType::MRTRIX);
break;
case 1:
filter->SetToolkit(MaximaExtractionFilterType::FSL);
break;
default:
filter->SetToolkit(MaximaExtractionFilterType::MRTRIX);
}
mitk::BaseGeometry::Pointer geometry;
try{
typedef ImageToItk< typename MaximaExtractionFilterType::CoefficientImageType > CasterType;
typename CasterType::Pointer caster = CasterType::New();
caster->SetInput(image);
caster->Update();
filter->SetInput(caster->GetOutput());
geometry = image->GetGeometry();
}
catch (itk::ExceptionObject &e)
{
MITK_INFO << "wrong image type: " << e.what();
QMessageBox::warning(nullptr, "Wrong pixel type", "Could not perform Finite Differences Extraction due to Image has wrong pixel type.", QMessageBox::Ok);
return;
}
filter->SetAngularThreshold(cos((float)m_Controls->m_AngularThreshold->value()*itk::Math::pi / 180));
filter->SetMaxNumPeaks(m_Controls->m_MaxNumPeaksBox->value());
filter->SetRelativePeakThreshold(m_Controls->m_PeakThresholdBox->value());
filter->SetAbsolutePeakThreshold(m_Controls->m_AbsoluteThresholdBox->value());
filter->SetScaleByGfa(m_Controls->m_ScaleByGfaBox->isChecked());
if (m_Controls->m_MaskBox->GetSelectedNode().IsNotNull())
{
ItkUcharImgType::Pointer itkMaskImage = ItkUcharImgType::New();
Image::Pointer mitkMaskImg = dynamic_cast<Image*>(m_Controls->m_MaskBox->GetSelectedNode()->GetData());
CastToItkImage(mitkMaskImg, itkMaskImage);
filter->SetMaskImage(itkMaskImage);
}
switch (m_Controls->m_NormalizationBox->currentIndex())
{
case 0:
filter->SetNormalizationMethod(MaximaExtractionFilterType::NO_NORM);
break;
case 1:
filter->SetNormalizationMethod(MaximaExtractionFilterType::MAX_VEC_NORM);
break;
case 2:
filter->SetNormalizationMethod(MaximaExtractionFilterType::SINGLE_VEC_NORM);
break;
}
filter->Update();
typename MaximaExtractionFilterType::PeakImageType::Pointer itkImg = filter->GetPeakImage();
mitk::Image::Pointer img = dynamic_cast<Image*>(PeakImage::New().GetPointer());
CastToMitkImage(itkImg, img);
DataNode::Pointer node = DataNode::New();
node->SetData(img);
QString name(m_Controls->m_ImageBox->GetSelectedNode()->GetName().c_str());
name += "_PEAKS";
node->SetName(name.toStdString().c_str());
GetDataStorage()->Add(node, m_Controls->m_ImageBox->GetSelectedNode());
if (m_Controls->m_OutputNumDirectionsBox->isChecked())
{
ItkUcharImgType::Pointer numDirImage = filter->GetNumDirectionsImage();
mitk::Image::Pointer image2 = mitk::Image::New();
CastToMitkImage(numDirImage, image2);
DataNode::Pointer node2 = DataNode::New();
node2->SetData(image2);
QString name(m_Controls->m_ImageBox->GetSelectedNode()->GetName().c_str());
name += "_NUM_DIRECTIONS";
node2->SetName(name.toStdString().c_str());
GetDataStorage()->Add(node2, m_Controls->m_ImageBox->GetSelectedNode());
}
}
void QmitkOdfMaximaExtractionView::StartMaximaExtraction(Image* img)
{
mitk::PixelType pixT = img->GetPixelType();
switch (pixT.GetNumberOfComponents())
{
case 6:
StartMaximaExtraction<2>(img);
break;
case 15:
StartMaximaExtraction<4>(img);
break;
case 28:
StartMaximaExtraction<6>(img);
break;
case 45:
StartMaximaExtraction<8>(img);
break;
case 66:
StartMaximaExtraction<10>(img);
break;
case 91:
StartMaximaExtraction<12>(img);
break;
default :
QMessageBox::warning(nullptr, "Error", "Only spherical harmonics orders 2-12 are supported.", QMessageBox::Ok);
}
}
void QmitkOdfMaximaExtractionView::OnSelectionChanged(berry::IWorkbenchPart::Pointer , const QList<mitk::DataNode::Pointer>& nodes)
{
(void) nodes;
this->OnImageSelectionChanged();
}
void QmitkOdfMaximaExtractionView::OnImageSelectionChanged()
{
m_Controls->m_StartPeakExtractionButton->setVisible(false);
m_Controls->m_ImportShCoeffs->setVisible(false);
mitk::DataNode::Pointer node = m_Controls->m_ImageBox->GetSelectedNode();
if (node.IsNull())
return;
Image::Pointer img = dynamic_cast<Image*>(node->GetData());
if (img->GetDimension()==4)
m_Controls->m_ImportShCoeffs->setVisible(true);
else
m_Controls->m_StartPeakExtractionButton->setVisible(true);
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/QmitkOdfMaximaExtractionView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/QmitkOdfMaximaExtractionView.h
index 474bb4e..0bcd9f2 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/QmitkOdfMaximaExtractionView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/QmitkOdfMaximaExtractionView.h
@@ -1,87 +1,87 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <berryISelectionListener.h>
#include <berryIStructuredSelection.h>
#include <QmitkAbstractView.h>
#include "ui_QmitkOdfMaximaExtractionViewControls.h"
#include <itkVectorImage.h>
#include <itkVectorContainer.h>
#include <itkOrientationDistributionFunction.h>
#include <QmitkDataStorageComboBoxWithSelectNone.h>
#include <mitkTensorImage.h>
/*!
\brief View providing several methods to extract peaks from the spherical harmonic representation of ODFs or from tensors
*/
// Forward Qt class declarations
class QmitkOdfMaximaExtractionView : public QmitkAbstractView
{
// 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;
QmitkOdfMaximaExtractionView();
virtual ~QmitkOdfMaximaExtractionView();
virtual void CreateQtPartControl(QWidget *parent) override;
///
/// Sets the focus to an internal widget.
///
virtual void SetFocus() override;
typedef itk::Image<unsigned char, 3> ItkUcharImgType;
typedef itk::Image< itk::DiffusionTensor3D< float >, 3 > ItkTensorImage;
typedef itk::Image< itk::Vector< float, 3>, 3 > ItkDirectionImage3DType; ///< contains a 3D vector in each voxel
protected slots:
void ConvertShCoeffs(); ///< convert spherical harmonic coefficients to the according mitk datatype
void StartPeakExtraction();
void OnImageSelectionChanged();
protected:
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
void StartMaximaExtraction(mitk::Image* img); ///< ODF maxima extraction using finite differences on the densely sampled sphere
void StartTensorPeakExtraction(mitk::TensorImage* img); ///< extract principal eigenvectors from tensor image
/// \brief called by QmitkAbstractView when DataManager's selection has changed
Ui::QmitkOdfMaximaExtractionViewControls* m_Controls;
template<int shOrder> void TemplatedConvertShCoeffs(mitk::Image* mitkImg);
template<int shOrder> void StartMaximaExtraction(mitk::Image* image); ///< ODF maxima extraction using finite differences on the densely sampled sphere
private:
};
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/mitkPluginActivator.cpp
index 4085a18..a127c6f 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/mitkPluginActivator.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/mitkPluginActivator.cpp
@@ -1,38 +1,38 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPluginActivator.h"
#include "src/internal/QmitkOdfMaximaExtractionView.h"
ctkPluginContext* mitk::PluginActivator::m_Context = nullptr;
ctkPluginContext* mitk::PluginActivator::GetContext()
{
return m_Context;
}
void mitk::PluginActivator::start(ctkPluginContext* context)
{
BERRY_REGISTER_EXTENSION_CLASS(QmitkOdfMaximaExtractionView, context)
m_Context = context;
}
void mitk::PluginActivator::stop(ctkPluginContext* context)
{
Q_UNUSED(context)
m_Context = nullptr;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/mitkPluginActivator.h
index 637e0d1..b9cb73e 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/mitkPluginActivator.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.odfpeaks/src/internal/mitkPluginActivator.h
@@ -1,40 +1,40 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKPLUGINACTIVATOR_H
#define MITKPLUGINACTIVATOR_H
#include <ctkPluginActivator.h>
namespace mitk
{
class PluginActivator : public QObject, public ctkPluginActivator
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.mitk.gui.qt.diffusionimaging.odfpeaks")
Q_INTERFACES(ctkPluginActivator)
public:
static ctkPluginContext* GetContext();
void start(ctkPluginContext* context) override;
void stop(ctkPluginContext* context) override;
private:
static ctkPluginContext* m_Context;
};
}
#endif
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/QmitkPartialVolumeAnalysisWidget.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/QmitkPartialVolumeAnalysisWidget.cpp
index dc62828..3941273 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/QmitkPartialVolumeAnalysisWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/QmitkPartialVolumeAnalysisWidget.cpp
@@ -1,144 +1,144 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkPartialVolumeAnalysisWidget.h"
#include <QPen>
#include <QFrame>
QmitkPartialVolumeAnalysisWidget::QmitkPartialVolumeAnalysisWidget( QWidget * parent )
: QmitkPlotWidget(parent)
{
// this->SetAxisTitle( QwtPlot::xBottom, "Grayvalue" );
// this->SetAxisTitle( QwtPlot::yLeft, "Probability" );
// this->Replot();
QFrame* canvas = qobject_cast<QFrame*>(m_Plot->canvas());
if (canvas)
{
canvas->setLineWidth(0);
canvas->setContentsMargins(0,0,0,0);
}
}
QmitkPartialVolumeAnalysisWidget::~QmitkPartialVolumeAnalysisWidget()
{
}
void QmitkPartialVolumeAnalysisWidget::DrawGauss()
{
}
void QmitkPartialVolumeAnalysisWidget::ClearItemModel()
{
}
void QmitkPartialVolumeAnalysisWidget::SetParameters( ParamsType *params, ResultsType *results, HistType *hist )
{
this->Clear();
if(params != nullptr && results != nullptr)
{
for(unsigned int i=0; i<m_Vals.size(); i++)
{
delete m_Vals[i];
}
m_Vals.clear();
m_Vals.push_back(hist->GetXVals());
m_Vals.push_back(hist->GetHVals());
std::vector<double> *xVals = hist->GetXVals();
std::vector<double> *fiberVals = new std::vector<double>(results->GetFiberVals());
std::vector<double> *nonFiberVals = new std::vector<double>(results->GetNonFiberVals());
std::vector<double> *mixedVals = new std::vector<double>(results->GetMixedVals());
std::vector<double> *combiVals = new std::vector<double>(results->GetCombiVals());
double fiberFA = 0.0;
double weights = 0.0;
for(unsigned int i=0; i<xVals->size(); ++i)
{
fiberFA += xVals->at(i) * fiberVals->at(i);
weights += fiberVals->at(i);
}
fiberFA = fiberFA / weights;
QPen pen( Qt::SolidLine );
pen.setWidth(1);
QwtText plot_title("Compartment Histograms " );
plot_title.setFont( QFont("Helvetica", 10, QFont::Bold) );
this->SetPlotTitle( plot_title );
pen.setColor(Qt::black);
int curveId = this->InsertCurve( "Histogram" );
this->SetCurveData( curveId, (*m_Vals[0]), (*m_Vals[1]) );
this->SetCurvePen( curveId, pen );
this->SetCurveAntialiasingOn( curveId );
// this->SetCurveTitle( curveId, "Image Histogram" );
pen.setColor(Qt::blue);
pen.setWidth(2);
curveId = this->InsertCurve( "Combined" );
this->SetCurveData( curveId, (*hist->GetXVals()), (*combiVals) );
this->SetCurvePen( curveId, pen );
m_Vals.push_back(combiVals);
this->SetCurveAntialiasingOn( curveId );
curveId = this->InsertCurve( "Tissue class" );
this->SetCurveData(curveId, (*hist->GetXVals()), (*fiberVals));
this->SetCurvePen( curveId, QPen( Qt::NoPen ) );
this->SetCurveBrush(curveId, QBrush(QColor::fromRgbF(1,0,0,.5), Qt::SolidPattern));
m_Vals.push_back(fiberVals);
curveId = this->InsertCurve( "Non-tissue class" );
this->SetCurveData( curveId, (*hist->GetXVals()), (*nonFiberVals) );
this->SetCurvePen( curveId, QPen( Qt::NoPen ) );
this->SetCurveBrush(curveId, QBrush(QColor::fromRgbF(0,1,0,.5), Qt::SolidPattern));
m_Vals.push_back(nonFiberVals);
curveId = this->InsertCurve( "Mixed (PV) class" );
this->SetCurveData( curveId, (*hist->GetXVals()), (*mixedVals) );
this->SetCurvePen( curveId, QPen( Qt::NoPen ) );
this->SetCurveBrush(curveId, QBrush(QColor::fromRgbF(.7,.7,.7,.5), Qt::SolidPattern));
m_Vals.push_back(mixedVals);
auto legend = new QwtLegend();
m_Plot->insertLegend( legend, QwtPlot::TopLegend );
this->Replot();
}
this->Replot();
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/QmitkPartialVolumeAnalysisWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/QmitkPartialVolumeAnalysisWidget.h
index 2b415cb..b9e29d1 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/QmitkPartialVolumeAnalysisWidget.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/QmitkPartialVolumeAnalysisWidget.h
@@ -1,57 +1,57 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkPartialVolumeAnalysisWidget_H_
#define QmitkPartialVolumeAnalysisWidget_H_
#include "QmitkPlotWidget.h"
#include <org_mitk_gui_qt_diffusionimaging_partialvolume_Export.h>
#include "mitkImage.h"
#include "mitkPartialVolumeAnalysisClusteringCalculator.h"
/**
* \brief Widget for displaying image histograms based on the vtkQtChart
* framework
*/
class DIFFUSIONIMAGING_PARTIALVOLUME_EXPORT QmitkPartialVolumeAnalysisWidget : public QmitkPlotWidget
{
Q_OBJECT
public:
typedef mitk::Image::HistogramType HistogramType;
typedef mitk::Image::HistogramType::ConstIterator HistogramConstIteratorType;
typedef mitk::PartialVolumeAnalysisClusteringCalculator ClusteringType;
typedef ClusteringType::ParamsType ParamsType;
typedef ClusteringType::ClusterResultType ResultsType;
typedef ClusteringType::HistType HistType;
/** \brief Set histogram to be displayed directly. */
void SetParameters( ParamsType *params, ResultsType *results, HistType *hist );
QmitkPartialVolumeAnalysisWidget( QWidget * /*parent = 0 */);
virtual ~QmitkPartialVolumeAnalysisWidget();
void DrawGauss();
void ClearItemModel();
std::vector< std::vector<double>* > m_Vals;
};
#endif /* QmitkPartialVolumeAnalysisWidget_H_ */
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/internal/QmitkPartialVolumeAnalysisView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/internal/QmitkPartialVolumeAnalysisView.cpp
index cd2035d..c808f0d 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/internal/QmitkPartialVolumeAnalysisView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/internal/QmitkPartialVolumeAnalysisView.cpp
@@ -1,2139 +1,2139 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkPartialVolumeAnalysisView.h"
#include <limits>
#include <qlabel.h>
#include <qspinbox.h>
#include <qpushbutton.h>
#include <qcheckbox.h>
#include <qgroupbox.h>
#include <qradiobutton.h>
#include <qlineedit.h>
#include <qclipboard.h>
#include <qfiledialog.h>
#include <berryIEditorPart.h>
#include <berryIWorkbenchPage.h>
#include <berryPlatform.h>
#include "QmitkSliderNavigatorWidget.h"
#include <QMessageBox>
#include "mitkNodePredicateDataType.h"
#include "mitkNodePredicateOr.h"
#include "mitkImageTimeSelector.h"
#include "mitkProperties.h"
#include "mitkProgressBar.h"
#include "mitkImageCast.h"
#include "mitkImageToItk.h"
#include "mitkITKImageImport.h"
#include "mitkDataNodeObject.h"
#include "mitkNodePredicateData.h"
#include "mitkPlanarFigureInteractor.h"
#include "mitkTensorImage.h"
#include "mitkPlanarCircle.h"
#include "mitkPlanarRectangle.h"
#include "mitkPlanarPolygon.h"
#include "mitkPartialVolumeAnalysisClusteringCalculator.h"
#include "usModuleRegistry.h"
#include <itkVectorImage.h>
#include "itkTensorDerivedMeasurementsFilter.h"
#include "itkDiffusionTensor3D.h"
#include "itkCartesianToPolarVectorImageFilter.h"
#include "itkPolarToCartesianVectorImageFilter.h"
#include "itkBinaryThresholdImageFilter.h"
#include "itkMaskImageFilter.h"
#include "itkCastImageFilter.h"
#include "itkImageMomentsCalculator.h"
#include <itkResampleImageFilter.h>
#include <itkGaussianInterpolateImageFunction.h>
#include <itkNearestNeighborInterpolateImageFunction.h>
#include <itkImageDuplicator.h>
#include <vnl/vnl_vector.h>
const std::string QmitkPartialVolumeAnalysisView::VIEW_ID =
"org.mitk.views.partialvolumeanalysisview";
class QmitkRequestStatisticsUpdateEvent : public QEvent
{
public:
enum Type
{
StatisticsUpdateRequest = QEvent::MaxUser - 1025
};
QmitkRequestStatisticsUpdateEvent()
: QEvent( (QEvent::Type) StatisticsUpdateRequest ) {};
};
typedef itk::Image<short, 3> ImageType;
typedef itk::Image<float, 3> FloatImageType;
typedef itk::Image<itk::Vector<float,3>, 3> VectorImageType;
inline bool my_isnan(float x)
{
volatile float d = x;
if(d!=d)
return true;
if(d==d)
return false;
return d != d;
}
QmitkPartialVolumeAnalysisView::QmitkPartialVolumeAnalysisView(QObject * /*parent*/, const char * /*name*/)
: QmitkAbstractView(),
m_Controls(nullptr),
m_TimeStepperAdapter(nullptr),
m_MeasurementInfoRenderer(nullptr),
m_MeasurementInfoAnnotation(nullptr),
m_IsTensorImage(false),
m_SelectedRenderWindow(nullptr),
m_LastRenderWindow(nullptr),
m_ImageObserverTag(-1),
m_ImageMaskObserverTag(-1),
m_PlanarFigureObserverTag(-1),
m_CurrentStatisticsValid(false),
m_StatisticsUpdatePending(false),
m_GaussianSigmaChangedSliding(false),
m_NumberBinsSliding(false),
m_UpsamplingChangedSliding(false),
m_EllipseCounter(0),
m_RectangleCounter(0),
m_PolygonCounter(0),
m_CurrentFigureNodeInitialized(false),
m_QuantifyClass(2),
m_IconTexOFF(new QIcon(":/QmitkPartialVolumeAnalysisView/texIntOFFIcon.png")),
m_IconTexON(new QIcon(":/QmitkPartialVolumeAnalysisView/texIntONIcon.png")),
m_TexIsOn(true),
m_Visible(false)
{
}
QmitkPartialVolumeAnalysisView::~QmitkPartialVolumeAnalysisView()
{
if ( m_SelectedImage.IsNotNull() )
m_SelectedImage->RemoveObserver( m_ImageObserverTag );
if ( m_SelectedImageMask.IsNotNull() )
m_SelectedImageMask->RemoveObserver( m_ImageMaskObserverTag );
if ( m_SelectedPlanarFigure.IsNotNull() )
{
m_SelectedPlanarFigure->RemoveObserver( m_PlanarFigureObserverTag );
m_SelectedPlanarFigure->RemoveObserver( m_InitializedObserverTag );
}
this->GetDataStorage()->AddNodeEvent -= mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeAddedInDataStorage );
m_SelectedPlanarFigureNodes->NodeChanged.RemoveListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeChanged ) );
m_SelectedPlanarFigureNodes->NodeRemoved.RemoveListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeRemoved ) );
m_SelectedPlanarFigureNodes->PropertyChanged.RemoveListener( mitk::MessageDelegate2<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*, const mitk::BaseProperty*>( this, &QmitkPartialVolumeAnalysisView::PropertyChanged ) );
m_SelectedImageNodes->NodeChanged.RemoveListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeChanged ) );
m_SelectedImageNodes->NodeRemoved.RemoveListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeRemoved ) );
m_SelectedImageNodes->PropertyChanged.RemoveListener( mitk::MessageDelegate2<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*, const mitk::BaseProperty*>( this, &QmitkPartialVolumeAnalysisView::PropertyChanged ) );
}
void QmitkPartialVolumeAnalysisView::CreateQtPartControl(QWidget *parent)
{
if (m_Controls == nullptr)
{
m_Controls = new Ui::QmitkPartialVolumeAnalysisViewControls;
m_Controls->setupUi(parent);
this->CreateConnections();
}
SetHistogramVisibility();
m_Controls->m_TextureIntON->setIcon(*m_IconTexON);
m_Controls->m_SimilarAnglesFrame->setVisible(false);
m_Controls->m_SimilarAnglesLabel->setVisible(false);
vtkTextProperty *textProp = vtkTextProperty::New();
textProp->SetColor(1.0, 1.0, 1.0);
m_MeasurementInfoAnnotation = vtkCornerAnnotation::New();
m_MeasurementInfoAnnotation->SetMaximumFontSize(12);
m_MeasurementInfoAnnotation->SetTextProperty(textProp);
m_MeasurementInfoRenderer = vtkRenderer::New();
m_MeasurementInfoRenderer->AddActor(m_MeasurementInfoAnnotation);
m_SelectedPlanarFigureNodes = mitk::DataStorageSelection::New(this->GetDataStorage(), false);
m_SelectedPlanarFigureNodes->NodeChanged.AddListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeChanged ) );
m_SelectedPlanarFigureNodes->NodeRemoved.AddListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeRemoved ) );
m_SelectedPlanarFigureNodes->PropertyChanged.AddListener( mitk::MessageDelegate2<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*, const mitk::BaseProperty*>( this, &QmitkPartialVolumeAnalysisView::PropertyChanged ) );
m_SelectedImageNodes = mitk::DataStorageSelection::New(this->GetDataStorage(), false);
m_SelectedImageNodes->PropertyChanged.AddListener( mitk::MessageDelegate2<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*, const mitk::BaseProperty*>( this, &QmitkPartialVolumeAnalysisView::PropertyChanged ) );
m_SelectedImageNodes->NodeChanged.AddListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeChanged ) );
m_SelectedImageNodes->NodeRemoved.AddListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeRemoved ) );
this->GetDataStorage()->AddNodeEvent.AddListener( mitk::MessageDelegate1<QmitkPartialVolumeAnalysisView
, const mitk::DataNode*>( this, &QmitkPartialVolumeAnalysisView::NodeAddedInDataStorage ) );
Select(nullptr,true,true);
SetAdvancedVisibility();
}
void QmitkPartialVolumeAnalysisView::SetFocus()
{
m_Controls->m_CircleButton->setFocus();
}
void QmitkPartialVolumeAnalysisView::SetHistogramVisibility()
{
m_Controls->m_HistogramWidget->setVisible(m_Controls->m_DisplayHistogramCheckbox->isChecked());
}
void QmitkPartialVolumeAnalysisView::SetAdvancedVisibility()
{
m_Controls->frame_7->setVisible(m_Controls->m_AdvancedCheckbox->isChecked());
}
void QmitkPartialVolumeAnalysisView::CreateConnections()
{
if ( m_Controls )
{
connect( m_Controls->m_DisplayHistogramCheckbox, SIGNAL( clicked() )
, this, SLOT( SetHistogramVisibility() ) );
connect( m_Controls->m_AdvancedCheckbox, SIGNAL( clicked() )
, this, SLOT( SetAdvancedVisibility() ) );
connect( m_Controls->m_NumberBinsSlider, SIGNAL( sliderReleased () ),
this, SLOT( NumberBinsReleasedSlider( ) ) );
connect( m_Controls->m_UpsamplingSlider, SIGNAL( sliderReleased( ) ),
this, SLOT( UpsamplingReleasedSlider( ) ) );
connect( m_Controls->m_GaussianSigmaSlider, SIGNAL( sliderReleased( ) ),
this, SLOT( GaussianSigmaReleasedSlider( ) ) );
connect( m_Controls->m_SimilarAnglesSlider, SIGNAL( sliderReleased( ) ),
this, SLOT( SimilarAnglesReleasedSlider( ) ) );
connect( m_Controls->m_NumberBinsSlider, SIGNAL( valueChanged (int) ),
this, SLOT( NumberBinsChangedSlider( int ) ) );
connect( m_Controls->m_UpsamplingSlider, SIGNAL( valueChanged( int ) ),
this, SLOT( UpsamplingChangedSlider( int ) ) );
connect( m_Controls->m_GaussianSigmaSlider, SIGNAL( valueChanged( int ) ),
this, SLOT( GaussianSigmaChangedSlider( int ) ) );
connect( m_Controls->m_SimilarAnglesSlider, SIGNAL( valueChanged( int ) ),
this, SLOT( SimilarAnglesChangedSlider(int) ) );
connect( m_Controls->m_OpacitySlider, SIGNAL( valueChanged( int ) ),
this, SLOT( OpacityChangedSlider(int) ) );
connect( (QObject*)(m_Controls->m_ButtonCopyHistogramToClipboard), SIGNAL(clicked()),(QObject*) this, SLOT(ToClipBoard()));
connect( m_Controls->m_CircleButton, SIGNAL( clicked() )
, this, SLOT( ActionDrawEllipseTriggered() ) );
connect( m_Controls->m_RectangleButton, SIGNAL( clicked() )
, this, SLOT( ActionDrawRectangleTriggered() ) );
connect( m_Controls->m_PolygonButton, SIGNAL( clicked() )
, this, SLOT( ActionDrawPolygonTriggered() ) );
connect( m_Controls->m_GreenRadio, SIGNAL( clicked(bool) )
, this, SLOT( GreenRadio(bool) ) );
connect( m_Controls->m_PartialVolumeRadio, SIGNAL( clicked(bool) )
, this, SLOT( PartialVolumeRadio(bool) ) );
connect( m_Controls->m_BlueRadio, SIGNAL( clicked(bool) )
, this, SLOT( BlueRadio(bool) ) );
connect( m_Controls->m_AllRadio, SIGNAL( clicked(bool) )
, this, SLOT( AllRadio(bool) ) );
connect( m_Controls->m_EstimateCircle, SIGNAL( clicked() )
, this, SLOT( EstimateCircle() ) );
connect( (QObject*)(m_Controls->m_TextureIntON), SIGNAL(clicked()), this, SLOT(TextIntON()) );
connect( m_Controls->m_ExportClusteringResultsButton, SIGNAL(clicked()), this, SLOT(ExportClusteringResults()));
}
}
void QmitkPartialVolumeAnalysisView::ExportClusteringResults()
{
if (m_ClusteringResult.IsNull() || m_SelectedImage.IsNull())
return;
mitk::BaseGeometry* geometry = m_SelectedImage->GetGeometry();
itk::Image< short, 3>::Pointer referenceImage = itk::Image< short, 3>::New();
itk::Vector<double,3> newSpacing = geometry->GetSpacing();
mitk::Point3D newOrigin = geometry->GetOrigin();
mitk::Geometry3D::BoundsArrayType bounds = geometry->GetBounds();
newOrigin[0] += bounds.GetElement(0);
newOrigin[1] += bounds.GetElement(2);
newOrigin[2] += bounds.GetElement(4);
itk::Matrix<double, 3, 3> newDirection;
itk::ImageRegion<3> imageRegion;
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
newDirection[j][i] = geometry->GetMatrixColumn(i)[j]/newSpacing[j];
imageRegion.SetSize(0, geometry->GetExtent(0));
imageRegion.SetSize(1, geometry->GetExtent(1));
imageRegion.SetSize(2, geometry->GetExtent(2));
// apply new image parameters
referenceImage->SetSpacing( newSpacing );
referenceImage->SetOrigin( newOrigin );
referenceImage->SetDirection( newDirection );
referenceImage->SetRegions( imageRegion );
referenceImage->Allocate();
typedef itk::Image< float, 3 > OutType;
mitk::Image::Pointer mitkInImage = dynamic_cast<mitk::Image*>(m_ClusteringResult->GetData());
typedef itk::Image< itk::RGBAPixel<unsigned char>, 3 > ItkRgbaImageType;
typedef mitk::ImageToItk< ItkRgbaImageType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(mitkInImage);
caster->Update();
ItkRgbaImageType::Pointer itkInImage = caster->GetOutput();
typedef itk::ExtractChannelFromRgbaImageFilter< itk::Image< short, 3>, OutType > ExtractionFilterType;
ExtractionFilterType::Pointer filter = ExtractionFilterType::New();
filter->SetInput(itkInImage);
filter->SetChannel(ExtractionFilterType::ALPHA);
filter->SetReferenceImage(referenceImage);
filter->Update();
OutType::Pointer outImg = filter->GetOutput();
mitk::Image::Pointer img = mitk::Image::New(); img->InitializeByItk(outImg.GetPointer());
img->SetVolume(outImg->GetBufferPointer());
// init data node
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData(img);
node->SetName("Clustering Result");
GetDataStorage()->Add(node);
}
void QmitkPartialVolumeAnalysisView::EstimateCircle()
{
typedef itk::Image<unsigned char, 3> SegImageType;
SegImageType::Pointer mask_itk = SegImageType::New();
typedef mitk::ImageToItk<SegImageType> CastType;
CastType::Pointer caster = CastType::New();
caster->SetInput(m_SelectedImageMask);
caster->Update();
typedef itk::ImageMomentsCalculator< SegImageType > MomentsType;
MomentsType::Pointer momentsCalc = MomentsType::New();
momentsCalc->SetImage(caster->GetOutput());
momentsCalc->Compute();
MomentsType::VectorType cog = momentsCalc->GetCenterOfGravity();
MomentsType::MatrixType axes = momentsCalc->GetPrincipalAxes();
// moments-coord conversion
// third coordinate min oder max?
// max-min = extent
MomentsType::AffineTransformPointer trafo = momentsCalc->GetPhysicalAxesToPrincipalAxesTransform();
itk::ImageRegionIterator<SegImageType>
itimage(caster->GetOutput(), caster->GetOutput()->GetLargestPossibleRegion());
itimage.GoToBegin();
double max = -9999999999.0;
double min = 9999999999.0;
while( !itimage.IsAtEnd() )
{
if(itimage.Get())
{
ImageType::IndexType index = itimage.GetIndex();
itk::Point<float,3> point;
caster->GetOutput()->TransformIndexToPhysicalPoint(index,point);
itk::Point<float,3> newPoint;
newPoint = trafo->TransformPoint(point);
if(newPoint[2]<min)
min = newPoint[2];
if(newPoint[2]>max)
max = newPoint[2];
}
++itimage;
}
double extent = max - min;
MITK_DEBUG << "EXTENT = " << extent;
mitk::Point3D origin;
mitk::Vector3D right, bottom, normal;
double factor = 1000.0;
mitk::FillVector3D(origin, cog[0]-factor*axes[1][0]-factor*axes[2][0],
cog[1]-factor*axes[1][1]-factor*axes[2][1],
cog[2]-factor*axes[1][2]-factor*axes[2][2]);
// mitk::FillVector3D(normal, axis[0][0],axis[0][1],axis[0][2]);
mitk::FillVector3D(bottom, 2*factor*axes[1][0], 2*factor*axes[1][1], 2*factor*axes[1][2]);
mitk::FillVector3D(right, 2*factor*axes[2][0], 2*factor*axes[2][1], 2*factor*axes[2][2]);
mitk::PlaneGeometry::Pointer planegeometry = mitk::PlaneGeometry::New();
planegeometry->InitializeStandardPlane(right.GetVnlVector(), bottom.GetVnlVector());
planegeometry->SetOrigin(origin);
double len1 = sqrt(axes[1][0]*axes[1][0] + axes[1][1]*axes[1][1] + axes[1][2]*axes[1][2]);
double len2 = sqrt(axes[2][0]*axes[2][0] + axes[2][1]*axes[2][1] + axes[2][2]*axes[2][2]);
mitk::Point2D point1;
point1[0] = factor*len1;
point1[1] = factor*len2;
mitk::Point2D point2;
point2[0] = factor*len1+extent*.5;
point2[1] = factor*len2;
mitk::PlanarCircle::Pointer circle = mitk::PlanarCircle::New();
circle->SetPlaneGeometry(planegeometry);
circle->PlaceFigure( point1 );
circle->SetControlPoint(0,point1);
circle->SetControlPoint(1,point2);
//circle->SetCurrentControlPoint( point2 );
mitk::PlanarFigure::PolyLineType polyline = circle->GetPolyLine( 0 );
MITK_DEBUG << "SIZE of planar figure polyline: " << polyline.size();
AddFigureToDataStorage(circle, "Circle");
}
bool QmitkPartialVolumeAnalysisView::AssertDrawingIsPossible(bool checked)
{
if (m_SelectedImageNodes->GetNode().IsNull())
{
checked = false;
this->HandleException("Please select an image!", dynamic_cast<QWidget *>(this->parent()), true);
return false;
}
//this->GetRenderWindowPart(OPEN)->EnableSlicingPlanes(false);
return checked;
}
void QmitkPartialVolumeAnalysisView::ActionDrawEllipseTriggered()
{
bool checked = m_Controls->m_CircleButton->isChecked();
if(!this->AssertDrawingIsPossible(checked))
return;
mitk::PlanarCircle::Pointer figure = mitk::PlanarCircle::New();
// using PV_ prefix for planar figures from this view
// to distinguish them from that ones created throught the measurement view
this->AddFigureToDataStorage(figure, QString("PV_Circle%1").arg(++m_EllipseCounter));
MITK_DEBUG << "PlanarCircle created ...";
}
void QmitkPartialVolumeAnalysisView::ActionDrawRectangleTriggered()
{
bool checked = m_Controls->m_RectangleButton->isChecked();
if(!this->AssertDrawingIsPossible(checked))
return;
mitk::PlanarRectangle::Pointer figure = mitk::PlanarRectangle::New();
// using PV_ prefix for planar figures from this view
// to distinguish them from that ones created throught the measurement view
this->AddFigureToDataStorage(figure, QString("PV_Rectangle%1").arg(++m_RectangleCounter));
MITK_DEBUG << "PlanarRectangle created ...";
}
void QmitkPartialVolumeAnalysisView::ActionDrawPolygonTriggered()
{
bool checked = m_Controls->m_PolygonButton->isChecked();
if(!this->AssertDrawingIsPossible(checked))
return;
mitk::PlanarPolygon::Pointer figure = mitk::PlanarPolygon::New();
figure->ClosedOn();
// using PV_ prefix for planar figures from this view
// to distinguish them from that ones created throught the measurement view
this->AddFigureToDataStorage(figure, QString("PV_Polygon%1").arg(++m_PolygonCounter));
MITK_DEBUG << "PlanarPolygon created ...";
}
void QmitkPartialVolumeAnalysisView::AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name,
const char *propertyKey, mitk::BaseProperty *property )
{
mitk::DataNode::Pointer newNode = mitk::DataNode::New();
newNode->SetName(name.toStdString());
newNode->SetData(figure);
// Add custom property, if available
if ( (propertyKey != nullptr) && (property != nullptr) )
{
newNode->AddProperty( propertyKey, property );
}
// figure drawn on the topmost layer / image
this->GetDataStorage()->Add(newNode, m_SelectedImageNodes->GetNode() );
QList<mitk::DataNode::Pointer> selectedNodes = this->GetDataManagerSelection();
for(int i = 0; i < selectedNodes.size(); ++i)
{
selectedNodes[i]->SetSelected(false);
}
std::vector<mitk::DataNode *> selectedPFNodes = m_SelectedPlanarFigureNodes->GetNodes();
for(std::size_t i = 0; i < selectedPFNodes.size(); ++i)
{
selectedPFNodes[i]->SetSelected(false);
}
newNode->SetSelected(true);
Select(newNode);
}
void QmitkPartialVolumeAnalysisView::PlanarFigureInitialized()
{
if(m_SelectedPlanarFigureNodes->GetNode().IsNull())
return;
m_CurrentFigureNodeInitialized = true;
this->Select(m_SelectedPlanarFigureNodes->GetNode());
m_Controls->m_CircleButton->setChecked(false);
m_Controls->m_RectangleButton->setChecked(false);
m_Controls->m_PolygonButton->setChecked(false);
//this->GetRenderWindowPart(OPEN)->EnableSlicingPlanes(true);
this->RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::PlanarFigureFocus(mitk::DataNode* node)
{
mitk::PlanarFigure* _PlanarFigure = 0;
_PlanarFigure = dynamic_cast<mitk::PlanarFigure*> (node->GetData());
if (_PlanarFigure)
{
FindRenderWindow(node);
const mitk::PlaneGeometry* _PlaneGeometry = _PlanarFigure->GetPlaneGeometry();
// make node visible
if (m_SelectedRenderWindow)
{
mitk::Point3D centerP = _PlaneGeometry->GetOrigin();
m_SelectedRenderWindow->GetSliceNavigationController()->ReorientSlices(
centerP, _PlaneGeometry->GetNormal());
m_SelectedRenderWindow->GetSliceNavigationController()->SelectSliceByPoint(
centerP);
}
}
}
void QmitkPartialVolumeAnalysisView::FindRenderWindow(mitk::DataNode* node)
{
if (node && dynamic_cast<mitk::PlanarFigure*> (node->GetData()))
{
m_SelectedRenderWindow = 0;
bool PlanarFigureInitializedWindow = false;
foreach(QmitkRenderWindow * window, this->GetRenderWindowPart()->GetQmitkRenderWindows().values())
{
if (!m_SelectedRenderWindow && node->GetBoolProperty("PlanarFigureInitializedWindow", PlanarFigureInitializedWindow, window->GetRenderer()))
{
m_SelectedRenderWindow = window;
}
}
}
}
void QmitkPartialVolumeAnalysisView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList<mitk::DataNode::Pointer> &nodes)
{
m_Controls->m_InputData->setTitle("Please Select Input Data");
if (!m_Visible)
return;
if ( nodes.empty() )
{
if (m_ClusteringResult.IsNotNull())
{
this->GetDataStorage()->Remove(m_ClusteringResult);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
Select(nullptr, true, true);
}
for (int i=0; i<nodes.size(); i++)
Select(nodes.at(i));
}
void QmitkPartialVolumeAnalysisView::Select( mitk::DataNode::Pointer node, bool clearMaskOnFirstArgnullptr, bool clearImageOnFirstArgnullptr )
{
// Clear any unreferenced images
this->RemoveOrphanImages();
bool somethingChanged = false;
if(node.IsNull())
{
somethingChanged = true;
if(clearMaskOnFirstArgnullptr)
{
if ( (m_SelectedImageMask.IsNotNull()) && (m_ImageMaskObserverTag >= 0) )
{
m_SelectedImageMask->RemoveObserver( m_ImageMaskObserverTag );
m_ImageMaskObserverTag = -1;
}
if ( (m_SelectedPlanarFigure.IsNotNull()) && (m_PlanarFigureObserverTag >= 0) )
{
m_SelectedPlanarFigure->RemoveObserver( m_PlanarFigureObserverTag );
m_PlanarFigureObserverTag = -1;
}
if ( (m_SelectedPlanarFigure.IsNotNull()) && (m_InitializedObserverTag >= 0) )
{
m_SelectedPlanarFigure->RemoveObserver( m_InitializedObserverTag );
m_InitializedObserverTag = -1;
}
m_SelectedPlanarFigure = nullptr;
m_SelectedPlanarFigureNodes->RemoveAllNodes();
m_CurrentFigureNodeInitialized = false;
m_SelectedRenderWindow = 0;
m_SelectedMaskNode = nullptr;
m_SelectedImageMask = nullptr;
}
if(clearImageOnFirstArgnullptr)
{
if ( (m_SelectedImage.IsNotNull()) && (m_ImageObserverTag >= 0) )
{
m_SelectedImage->RemoveObserver( m_ImageObserverTag );
m_ImageObserverTag = -1;
}
m_SelectedImageNodes->RemoveAllNodes();
m_SelectedImage = nullptr;
m_IsTensorImage = false;
m_FAImage = nullptr;
m_RDImage = nullptr;
m_ADImage = nullptr;
m_MDImage = nullptr;
m_CAImage = nullptr;
m_DirectionComp1Image = nullptr;
m_DirectionComp2Image = nullptr;
m_AngularErrorImage = nullptr;
m_Controls->m_SimilarAnglesFrame->setVisible(false);
m_Controls->m_SimilarAnglesLabel->setVisible(false);
}
}
else
{
typedef itk::SimpleMemberCommand< QmitkPartialVolumeAnalysisView > ITKCommandType;
ITKCommandType::Pointer changeListener;
changeListener = ITKCommandType::New();
changeListener->SetCallbackFunction( this, &QmitkPartialVolumeAnalysisView::RequestStatisticsUpdate );
// Get selected element
mitk::TensorImage *selectedTensorImage = dynamic_cast< mitk::TensorImage * >( node->GetData() );
mitk::Image *selectedImage = dynamic_cast< mitk::Image * >( node->GetData() );
mitk::PlanarFigure *selectedPlanar = dynamic_cast< mitk::PlanarFigure * >( node->GetData() );
bool isMask = false;
bool isImage = false;
bool isPlanar = false;
bool isTensorImage = false;
if (selectedTensorImage != nullptr)
{
isTensorImage = true;
}
else if(selectedImage != nullptr)
{
node->GetPropertyValue("binary", isMask);
isImage = !isMask;
}
else if ( (selectedPlanar != nullptr) )
{
isPlanar = true;
}
// image
if(isImage && selectedImage->GetDimension()==3)
{
if(selectedImage != m_SelectedImage.GetPointer())
{
somethingChanged = true;
if ( (m_SelectedImage.IsNotNull()) && (m_ImageObserverTag >= 0) )
{
m_SelectedImage->RemoveObserver( m_ImageObserverTag );
m_ImageObserverTag = -1;
}
*m_SelectedImageNodes = node;
m_SelectedImage = selectedImage;
m_IsTensorImage = false;
m_FAImage = nullptr;
m_RDImage = nullptr;
m_ADImage = nullptr;
m_MDImage = nullptr;
m_CAImage = nullptr;
m_DirectionComp1Image = nullptr;
m_DirectionComp2Image = nullptr;
m_AngularErrorImage = nullptr;
// Add change listeners to selected objects
m_ImageObserverTag = m_SelectedImage->AddObserver(
itk::ModifiedEvent(), changeListener );
m_Controls->m_SimilarAnglesFrame->setVisible(false);
m_Controls->m_SimilarAnglesLabel->setVisible(false);
m_Controls->m_SelectedImageLabel->setText( m_SelectedImageNodes->GetNode()->GetName().c_str() );
}
}
//planar
if(isPlanar)
{
if(selectedPlanar != m_SelectedPlanarFigure.GetPointer())
{
MITK_DEBUG << "Planar selection changed";
somethingChanged = true;
// Possibly previous change listeners
if ( (m_SelectedPlanarFigure.IsNotNull()) && (m_PlanarFigureObserverTag >= 0) )
{
m_SelectedPlanarFigure->RemoveObserver( m_PlanarFigureObserverTag );
m_PlanarFigureObserverTag = -1;
}
if ( (m_SelectedPlanarFigure.IsNotNull()) && (m_InitializedObserverTag >= 0) )
{
m_SelectedPlanarFigure->RemoveObserver( m_InitializedObserverTag );
m_InitializedObserverTag = -1;
}
m_SelectedPlanarFigure = selectedPlanar;
*m_SelectedPlanarFigureNodes = node;
m_CurrentFigureNodeInitialized = selectedPlanar->IsPlaced();
m_SelectedMaskNode = nullptr;
m_SelectedImageMask = nullptr;
m_PlanarFigureObserverTag = m_SelectedPlanarFigure->AddObserver(
mitk::EndInteractionPlanarFigureEvent(), changeListener );
if(!m_CurrentFigureNodeInitialized)
{
typedef itk::SimpleMemberCommand< QmitkPartialVolumeAnalysisView > ITKCommandType;
ITKCommandType::Pointer initializationCommand;
initializationCommand = ITKCommandType::New();
// set the callback function of the member command
initializationCommand->SetCallbackFunction( this, &QmitkPartialVolumeAnalysisView::PlanarFigureInitialized );
// add an observer
m_InitializedObserverTag = selectedPlanar->AddObserver( mitk::EndPlacementPlanarFigureEvent(), initializationCommand );
}
m_Controls->m_SelectedMaskLabel->setText( m_SelectedPlanarFigureNodes->GetNode()->GetName().c_str() );
PlanarFigureFocus(node);
}
}
//mask
this->m_Controls->m_EstimateCircle->setEnabled(isMask && selectedImage->GetDimension()==3);
if(isMask && selectedImage->GetDimension()==3)
{
if(selectedImage != m_SelectedImage.GetPointer())
{
somethingChanged = true;
if ( (m_SelectedImageMask.IsNotNull()) && (m_ImageMaskObserverTag >= 0) )
{
m_SelectedImageMask->RemoveObserver( m_ImageMaskObserverTag );
m_ImageMaskObserverTag = -1;
}
m_SelectedMaskNode = node;
m_SelectedImageMask = selectedImage;
m_SelectedPlanarFigure = nullptr;
m_SelectedPlanarFigureNodes->RemoveAllNodes();
m_ImageMaskObserverTag = m_SelectedImageMask->AddObserver(
itk::ModifiedEvent(), changeListener );
m_Controls->m_SelectedMaskLabel->setText( m_SelectedMaskNode->GetName().c_str() );
}
}
//tensor image
if(isTensorImage && selectedTensorImage->GetDimension()==3)
{
if(selectedImage != m_SelectedImage.GetPointer())
{
somethingChanged = true;
if ( (m_SelectedImage.IsNotNull()) && (m_ImageObserverTag >= 0) )
{
m_SelectedImage->RemoveObserver( m_ImageObserverTag );
m_ImageObserverTag = -1;
}
*m_SelectedImageNodes = node;
m_SelectedImage = selectedImage;
m_IsTensorImage = true;
ExtractTensorImages(selectedImage);
// Add change listeners to selected objects
m_ImageObserverTag = m_SelectedImage->AddObserver(
itk::ModifiedEvent(), changeListener );
m_Controls->m_SimilarAnglesFrame->setVisible(true);
m_Controls->m_SimilarAnglesLabel->setVisible(true);
m_Controls->m_SelectedImageLabel->setText( m_SelectedImageNodes->GetNode()->GetName().c_str() );
}
}
}
if(somethingChanged)
{
this->SetMeasurementInfoToRenderWindow("");
if(m_SelectedPlanarFigure.IsNull() && m_SelectedImageMask.IsNull() )
{
m_Controls->m_SelectedMaskLabel->setText("<font color='red'>mandatory</font>");
m_Controls->m_ResampleOptionsFrame->setEnabled(false);
m_Controls->m_HistogramWidget->setEnabled(false);
m_Controls->m_ClassSelector->setEnabled(false);
m_Controls->m_DisplayHistogramCheckbox->setEnabled(false);
m_Controls->m_AdvancedCheckbox->setEnabled(false);
m_Controls->frame_7->setEnabled(false);
}
else
{
m_Controls->m_ResampleOptionsFrame->setEnabled(true);
m_Controls->m_HistogramWidget->setEnabled(true);
m_Controls->m_ClassSelector->setEnabled(true);
m_Controls->m_DisplayHistogramCheckbox->setEnabled(true);
m_Controls->m_AdvancedCheckbox->setEnabled(true);
m_Controls->frame_7->setEnabled(true);
}
// Clear statistics / histogram GUI if nothing is selected
if ( m_SelectedImage.IsNull() )
{
m_Controls->m_PlanarFigureButtonsFrame->setEnabled(false);
m_Controls->m_OpacityFrame->setEnabled(false);
m_Controls->m_SelectedImageLabel->setText("<font color='red'>mandatory</font>");
}
else
{
m_Controls->m_PlanarFigureButtonsFrame->setEnabled(true);
m_Controls->m_OpacityFrame->setEnabled(true);
}
if( !m_Visible || m_SelectedImage.IsNull()
|| (m_SelectedPlanarFigure.IsNull() && m_SelectedImageMask.IsNull()) )
{
m_Controls->m_InputData->setTitle("Please Select Input Data");
m_Controls->m_HistogramWidget->ClearItemModel();
m_CurrentStatisticsValid = false;
}
else
{
m_Controls->m_InputData->setTitle("Input Data");
this->RequestStatisticsUpdate();
}
}
}
void QmitkPartialVolumeAnalysisView::ShowClusteringResults()
{
typedef itk::Image<unsigned char, 3> MaskImageType;
mitk::Image::Pointer mask = 0;
MaskImageType::Pointer itkmask = 0;
if(m_IsTensorImage && m_Controls->m_SimilarAnglesSlider->value() != 0)
{
typedef itk::Image<float, 3> AngularErrorImageType;
typedef mitk::ImageToItk<AngularErrorImageType> CastType;
CastType::Pointer caster = CastType::New();
caster->SetInput(m_AngularErrorImage);
caster->Update();
typedef itk::BinaryThresholdImageFilter< AngularErrorImageType, MaskImageType > ThreshType;
ThreshType::Pointer thresh = ThreshType::New();
thresh->SetUpperThreshold((90-m_Controls->m_SimilarAnglesSlider->value())*(itk::Math::pi/180.0));
thresh->SetInsideValue(1.0);
thresh->SetInput(caster->GetOutput());
thresh->Update();
itkmask = thresh->GetOutput();
mask = mitk::Image::New();
mask->InitializeByItk(itkmask.GetPointer());
mask->SetVolume(itkmask->GetBufferPointer());
// GetDataStorage()->Remove(m_newnode);
// m_newnode = mitk::DataNode::New();
// m_newnode->SetData(mask);
// m_newnode->SetName("masking node");
// m_newnode->SetIntProperty( "layer", 1002 );
// GetDataStorage()->Add(m_newnode, m_SelectedImageNodes->GetNode());
}
mitk::Image::Pointer clusteredImage;
ClusteringType::Pointer clusterer = ClusteringType::New();
if(m_QuantifyClass==3)
{
if(m_IsTensorImage)
{
double *green_fa, *green_rd, *green_ad, *green_md;
//double *greengray_fa, *greengray_rd, *greengray_ad, *greengray_md;
double *gray_fa, *gray_rd, *gray_ad, *gray_md;
//double *redgray_fa, *redgray_rd, *redgray_ad, *redgray_md;
double *red_fa, *red_rd, *red_ad, *red_md;
mitk::Image* tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(0);
mitk::Image::ConstPointer imgToCluster = tmpImg;
red_fa = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->r, mask);
green_fa = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->g, mask);
gray_fa = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->b, mask);
tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(3);
mitk::Image::ConstPointer imgToCluster3 = tmpImg;
red_rd = clusterer->PerformQuantification(imgToCluster3, m_CurrentRGBClusteringResults->rgbChannels->r, mask);
green_rd = clusterer->PerformQuantification(imgToCluster3, m_CurrentRGBClusteringResults->rgbChannels->g, mask);
gray_rd = clusterer->PerformQuantification(imgToCluster3, m_CurrentRGBClusteringResults->rgbChannels->b, mask);
tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(4);
mitk::Image::ConstPointer imgToCluster4 = tmpImg;
red_ad = clusterer->PerformQuantification(imgToCluster4, m_CurrentRGBClusteringResults->rgbChannels->r, mask);
green_ad = clusterer->PerformQuantification(imgToCluster4, m_CurrentRGBClusteringResults->rgbChannels->g, mask);
gray_ad = clusterer->PerformQuantification(imgToCluster4, m_CurrentRGBClusteringResults->rgbChannels->b, mask);
tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(5);
mitk::Image::ConstPointer imgToCluster5 = tmpImg;
red_md = clusterer->PerformQuantification(imgToCluster5, m_CurrentRGBClusteringResults->rgbChannels->r, mask);
green_md = clusterer->PerformQuantification(imgToCluster5, m_CurrentRGBClusteringResults->rgbChannels->g, mask);
gray_md = clusterer->PerformQuantification(imgToCluster5, m_CurrentRGBClusteringResults->rgbChannels->b, mask);
// clipboard
QString clipboardText("FA\t%1\t%2\t\t%3\t%4\t\t%5\t%6\t");
clipboardText = clipboardText
.arg(red_fa[0]).arg(red_fa[1])
.arg(gray_fa[0]).arg(gray_fa[1])
.arg(green_fa[0]).arg(green_fa[1]);
QString clipboardText3("RD\t%1\t%2\t\t%3\t%4\t\t%5\t%6\t");
clipboardText3 = clipboardText3
.arg(red_rd[0]).arg(red_rd[1])
.arg(gray_rd[0]).arg(gray_rd[1])
.arg(green_rd[0]).arg(green_rd[1]);
QString clipboardText4("AD\t%1\t%2\t\t%3\t%4\t\t%5\t%6\t");
clipboardText4 = clipboardText4
.arg(red_ad[0]).arg(red_ad[1])
.arg(gray_ad[0]).arg(gray_ad[1])
.arg(green_ad[0]).arg(green_ad[1]);
QString clipboardText5("MD\t%1\t%2\t\t%3\t%4\t\t%5\t%6");
clipboardText5 = clipboardText5
.arg(red_md[0]).arg(red_md[1])
.arg(gray_md[0]).arg(gray_md[1])
.arg(green_md[0]).arg(green_md[1]);
QApplication::clipboard()->setText(clipboardText+clipboardText3+clipboardText4+clipboardText5, QClipboard::Clipboard);
// now paint infos also on renderwindow
QString plainInfoText("%1 %2 %3 \n");
plainInfoText = plainInfoText
.arg("Red ", 20)
.arg("Gray ", 20)
.arg("Green", 20);
QString plainInfoText0("FA:%1 ± %2%3 ± %4%5 ± %6\n");
plainInfoText0 = plainInfoText0
.arg(red_fa[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(red_fa[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(gray_fa[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(gray_fa[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(green_fa[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(green_fa[1], -10, 'g', 2, QLatin1Char( ' ' ));
QString plainInfoText3("RDx10³:%1 ± %2%3 ± %4%5 ± %6\n");
plainInfoText3 = plainInfoText3
.arg(1000.0 * red_rd[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_rd[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(1000.0 * gray_rd[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * gray_rd[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(1000.0 * green_rd[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * green_rd[1], -10, 'g', 2, QLatin1Char( ' ' ));
QString plainInfoText4("ADx10³:%1 ± %2%3 ± %4%5 ± %6\n");
plainInfoText4 = plainInfoText4
.arg(1000.0 * red_ad[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_ad[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(1000.0 * gray_ad[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * gray_ad[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(1000.0 * green_ad[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * green_ad[1], -10, 'g', 2, QLatin1Char( ' ' ));
QString plainInfoText5("MDx10³:%1 ± %2%3 ± %4%5 ± %6");
plainInfoText5 = plainInfoText5
.arg(1000.0 * red_md[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_md[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(1000.0 * gray_md[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * gray_md[1], -10, 'g', 2, QLatin1Char( ' ' ))
.arg(1000.0 * green_md[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * green_md[1], -10, 'g', 2, QLatin1Char( ' ' ));
this->SetMeasurementInfoToRenderWindow(plainInfoText+plainInfoText0+plainInfoText3+plainInfoText4+plainInfoText5);
}
else
{
double* green;
double* gray;
double* red;
mitk::Image* tmpImg = m_CurrentStatisticsCalculator->GetInternalImage();
mitk::Image::ConstPointer imgToCluster = tmpImg;
red = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->r);
green = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->g);
gray = clusterer->PerformQuantification(imgToCluster, m_CurrentRGBClusteringResults->rgbChannels->b);
// clipboard
QString clipboardText("%1\t%2\t\t%3\t%4\t\t%5\t%6");
clipboardText = clipboardText.arg(red[0]).arg(red[1])
.arg(gray[0]).arg(gray[1])
.arg(green[0]).arg(green[1]);
QApplication::clipboard()->setText(clipboardText, QClipboard::Clipboard);
// now paint infos also on renderwindow
QString plainInfoText("Red: %1 ± %2\nGray: %3 ± %4\nGreen: %5 ± %6");
plainInfoText = plainInfoText.arg(red[0]).arg(red[1])
.arg(gray[0]).arg(gray[1])
.arg(green[0]).arg(green[1]);
this->SetMeasurementInfoToRenderWindow(plainInfoText);
}
clusteredImage = m_CurrentRGBClusteringResults->rgb;
}
else
{
if(m_IsTensorImage)
{
double *red_fa, *red_rd, *red_ad, *red_md;
mitk::Image* tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(0);
mitk::Image::ConstPointer imgToCluster = tmpImg;
red_fa = clusterer->PerformQuantification(imgToCluster, m_CurrentPerformClusteringResults->clusteredImage, mask);
tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(3);
mitk::Image::ConstPointer imgToCluster3 = tmpImg;
red_rd = clusterer->PerformQuantification(imgToCluster3, m_CurrentPerformClusteringResults->clusteredImage, mask);
tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(4);
mitk::Image::ConstPointer imgToCluster4 = tmpImg;
red_ad = clusterer->PerformQuantification(imgToCluster4, m_CurrentPerformClusteringResults->clusteredImage, mask);
tmpImg = m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(5);
mitk::Image::ConstPointer imgToCluster5 = tmpImg;
red_md = clusterer->PerformQuantification(imgToCluster5, m_CurrentPerformClusteringResults->clusteredImage, mask);
// clipboard
QString clipboardText("FA\t%1\t%2\t");
clipboardText = clipboardText
.arg(red_fa[0]).arg(red_fa[1]);
QString clipboardText3("RD\t%1\t%2\t");
clipboardText3 = clipboardText3
.arg(red_rd[0]).arg(red_rd[1]);
QString clipboardText4("AD\t%1\t%2\t");
clipboardText4 = clipboardText4
.arg(red_ad[0]).arg(red_ad[1]);
QString clipboardText5("MD\t%1\t%2\t");
clipboardText5 = clipboardText5
.arg(red_md[0]).arg(red_md[1]);
QApplication::clipboard()->setText(clipboardText+clipboardText3+clipboardText4+clipboardText5, QClipboard::Clipboard);
// now paint infos also on renderwindow
QString plainInfoText("%1 \n");
plainInfoText = plainInfoText
.arg("Red ", 20);
QString plainInfoText0("FA:%1 ± %2\n");
plainInfoText0 = plainInfoText0
.arg(red_fa[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(red_fa[1], -10, 'g', 2, QLatin1Char( ' ' ));
QString plainInfoText3("RDx10³:%1 ± %2\n");
plainInfoText3 = plainInfoText3
.arg(1000.0 * red_rd[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_rd[1], -10, 'g', 2, QLatin1Char( ' ' ));
QString plainInfoText4("ADx10³:%1 ± %2\n");
plainInfoText4 = plainInfoText4
.arg(1000.0 * red_ad[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_ad[1], -10, 'g', 2, QLatin1Char( ' ' ));
QString plainInfoText5("MDx10³:%1 ± %2");
plainInfoText5 = plainInfoText5
.arg(1000.0 * red_md[0], 10, 'g', 2, QLatin1Char( ' ' )).arg(1000.0 * red_md[1], -10, 'g', 2, QLatin1Char( ' ' ));
this->SetMeasurementInfoToRenderWindow(plainInfoText+plainInfoText0+plainInfoText3+plainInfoText4+plainInfoText5);
}
else
{
double* quant;
mitk::Image* tmpImg = m_CurrentStatisticsCalculator->GetInternalImage();
mitk::Image::ConstPointer imgToCluster = tmpImg;
quant = clusterer->PerformQuantification(imgToCluster, m_CurrentPerformClusteringResults->clusteredImage);
// clipboard
QString clipboardText("%1\t%2");
clipboardText = clipboardText.arg(quant[0]).arg(quant[1]);
QApplication::clipboard()->setText(clipboardText, QClipboard::Clipboard);
// now paint infos also on renderwindow
QString plainInfoText("Measurement: %1 ± %2");
plainInfoText = plainInfoText.arg(quant[0]).arg(quant[1]);
this->SetMeasurementInfoToRenderWindow(plainInfoText);
}
clusteredImage = m_CurrentPerformClusteringResults->displayImage;
}
if(mask.IsNotNull())
{
typedef itk::Image<itk::RGBAPixel<unsigned char>,3> RGBImageType;
typedef mitk::ImageToItk<RGBImageType> ClusterCasterType;
ClusterCasterType::Pointer clCaster = ClusterCasterType::New();
clCaster->SetInput(clusteredImage);
clCaster->Update();
clCaster->GetOutput();
typedef itk::MaskImageFilter< RGBImageType, MaskImageType, RGBImageType > MaskType;
MaskType::Pointer masker = MaskType::New();
masker->SetInput1(clCaster->GetOutput());
masker->SetInput2(itkmask);
masker->Update();
clusteredImage = mitk::Image::New();
clusteredImage->InitializeByItk(masker->GetOutput());
clusteredImage->SetVolume(masker->GetOutput()->GetBufferPointer());
}
if(m_ClusteringResult.IsNotNull())
{
this->GetDataStorage()->Remove(m_ClusteringResult);
}
m_ClusteringResult = mitk::DataNode::New();
m_ClusteringResult->SetBoolProperty("helper object", true);
m_ClusteringResult->SetIntProperty( "layer", 1000 );
m_ClusteringResult->SetBoolProperty("texture interpolation", m_TexIsOn);
m_ClusteringResult->SetData(clusteredImage);
m_ClusteringResult->SetName("Clusterprobs");
this->GetDataStorage()->Add(m_ClusteringResult, m_SelectedImageNodes->GetNode());
if(m_SelectedPlanarFigure.IsNotNull() && m_SelectedPlanarFigureNodes->GetNode().IsNotNull())
{
m_SelectedPlanarFigureNodes->GetNode()->SetIntProperty( "layer", 1001 );
}
this->RequestRenderWindowUpdate();
}
void QmitkPartialVolumeAnalysisView::UpdateStatistics()
{
if(!m_CurrentFigureNodeInitialized && m_SelectedPlanarFigure.IsNotNull())
{
MITK_DEBUG << "Selected planar figure not initialized. No stats calculation performed.";
return;
}
// Remove any cached images that are no longer referenced elsewhere
this->RemoveOrphanImages();
if ( m_SelectedImage.IsNotNull() )
{
// Check if a the selected image is a multi-channel image. If yes, statistics
// cannot be calculated currently.
if ( !m_IsTensorImage && m_SelectedImage->GetPixelType().GetNumberOfComponents() > 1 )
{
QMessageBox::information( nullptr, "Warning", "Non-tensor multi-component images not supported.");
m_Controls->m_HistogramWidget->ClearItemModel();
m_CurrentStatisticsValid = false;
return;
}
m_CurrentStatisticsCalculator = nullptr;
if(!m_IsTensorImage)
{
// Retrieve HistogramStatisticsCalculator from has map (or create a new one
// for this image if non-existant)
PartialVolumeAnalysisMapType::iterator it =
m_PartialVolumeAnalysisMap.find( m_SelectedImage );
if ( it != m_PartialVolumeAnalysisMap.end() )
{
m_CurrentStatisticsCalculator = it->second;
}
}
if(m_CurrentStatisticsCalculator.IsNull())
{
m_CurrentStatisticsCalculator = mitk::PartialVolumeAnalysisHistogramCalculator::New();
m_CurrentStatisticsCalculator->SetPlanarFigureThickness(m_Controls->m_PlanarFiguresThickness->value());
if(m_IsTensorImage)
{
m_CurrentStatisticsCalculator->SetImage( m_CAImage );
m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_FAImage );
m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_DirectionComp1Image );
m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_DirectionComp2Image );
m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_RDImage );
m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_ADImage );
m_CurrentStatisticsCalculator->AddAdditionalResamplingImage( m_MDImage );
}
else
{
m_CurrentStatisticsCalculator->SetImage( m_SelectedImage );
}
m_PartialVolumeAnalysisMap[m_SelectedImage] = m_CurrentStatisticsCalculator;
MITK_DEBUG << "Creating StatisticsCalculator";
}
std::string maskName;
std::string maskType;
unsigned int maskDimension;
if ( m_SelectedImageMask.IsNotNull() )
{
mitk::PixelType pixelType = m_SelectedImageMask->GetPixelType();
MITK_DEBUG << pixelType.GetPixelTypeAsString();
if(pixelType.GetComponentTypeAsString() == "char")
{
MITK_DEBUG << "Pixel type is char instead of uchar";
return;
}
if(pixelType.GetBitsPerComponent() == 16)
{
//convert from ushort to uchar
typedef itk::Image<unsigned char, 3> UCharImageType;
UCharImageType::Pointer charImage;
if(pixelType.GetComponentTypeAsString() == "short" )
{
typedef itk::Image<short, 3> ShortImageType;
ShortImageType::Pointer shortImage;
mitk::CastToItkImage( m_SelectedImageMask, shortImage );
typedef itk::ImageDuplicator< ShortImageType > DuplicatorType;
DuplicatorType::Pointer duplicator = DuplicatorType::New();
duplicator->SetInputImage( shortImage );
duplicator->Update();
typedef itk::CastImageFilter<ShortImageType, UCharImageType> ImageCasterType;
ImageCasterType::Pointer caster = ImageCasterType::New();
caster->SetInput( duplicator->GetOutput() );
caster->Update();
charImage = caster->GetOutput();
}
else
{
typedef itk::Image<unsigned short, 3> UShortImageType;
UShortImageType::Pointer shortImage;
mitk::CastToItkImage( m_SelectedImageMask, shortImage );
typedef itk::ImageDuplicator< UShortImageType > DuplicatorType;
DuplicatorType::Pointer duplicator = DuplicatorType::New();
duplicator->SetInputImage( shortImage );
duplicator->Update();
typedef itk::CastImageFilter<UShortImageType, UCharImageType> ImageCasterType;
ImageCasterType::Pointer caster = ImageCasterType::New();
caster->SetInput( duplicator->GetOutput() );
caster->Update();
charImage = caster->GetOutput();
}
m_SelectedImageMask = nullptr;
m_SelectedImageMask = mitk::Image::New();
m_SelectedImageMask->InitializeByItk( charImage.GetPointer() );
m_SelectedImageMask->SetVolume( charImage->GetBufferPointer() );
mitk::CastToMitkImage(charImage, m_SelectedImageMask);
}
m_CurrentStatisticsCalculator->SetImageMask( m_SelectedImageMask );
m_CurrentStatisticsCalculator->SetMaskingModeToImage();
maskName = m_SelectedMaskNode->GetName();
maskType = m_SelectedImageMask->GetNameOfClass();
maskDimension = 3;
std::stringstream maskLabel;
maskLabel << maskName;
if ( maskDimension > 0 )
{
maskLabel << " [" << maskDimension << "D " << maskType << "]";
}
m_Controls->m_SelectedMaskLabel->setText( maskLabel.str().c_str() );
}
else if ( m_SelectedPlanarFigure.IsNotNull() && m_SelectedPlanarFigureNodes->GetNode().IsNotNull())
{
m_CurrentStatisticsCalculator->SetPlanarFigure( m_SelectedPlanarFigure );
m_CurrentStatisticsCalculator->SetMaskingModeToPlanarFigure();
maskName = m_SelectedPlanarFigureNodes->GetNode()->GetName();
maskType = m_SelectedPlanarFigure->GetNameOfClass();
maskDimension = 2;
}
else
{
m_CurrentStatisticsCalculator->SetMaskingModeToNone();
maskName = "-";
maskType = "";
maskDimension = 0;
}
bool statisticsChanged = false;
bool statisticsCalculationSuccessful = false;
// Initialize progress bar
mitk::ProgressBar::GetInstance()->AddStepsToDo( 100 );
// Install listener for progress events and initialize progress bar
typedef itk::SimpleMemberCommand< QmitkPartialVolumeAnalysisView > ITKCommandType;
ITKCommandType::Pointer progressListener;
progressListener = ITKCommandType::New();
progressListener->SetCallbackFunction( this, &QmitkPartialVolumeAnalysisView::UpdateProgressBar );
unsigned long progressObserverTag = m_CurrentStatisticsCalculator
->AddObserver( itk::ProgressEvent(), progressListener );
ClusteringType::ParamsType *cparams = 0;
ClusteringType::ClusterResultType *cresult = 0;
ClusteringType::HistType *chist = 0;
try
{
m_CurrentStatisticsCalculator->SetNumberOfBins(m_Controls->m_NumberBins->text().toInt());
m_CurrentStatisticsCalculator->SetUpsamplingFactor(m_Controls->m_Upsampling->text().toDouble());
m_CurrentStatisticsCalculator->SetGaussianSigma(m_Controls->m_GaussianSigma->text().toDouble());
// Compute statistics
statisticsChanged =
m_CurrentStatisticsCalculator->ComputeStatistics( );
mitk::Image* tmpImg = m_CurrentStatisticsCalculator->GetInternalImage();
mitk::Image::ConstPointer imgToCluster = tmpImg;
if(imgToCluster.IsNotNull())
{
// perform clustering
const HistogramType *histogram = m_CurrentStatisticsCalculator->GetHistogram( );
if(histogram != nullptr)
{
ClusteringType::Pointer clusterer = ClusteringType::New();
clusterer->SetStepsNumIntegration(200);
clusterer->SetMaxIt(1000);
mitk::Image::Pointer pFiberImg;
if(m_QuantifyClass==3)
{
if(m_Controls->m_Quantiles->isChecked())
{
m_CurrentRGBClusteringResults = clusterer->PerformRGBQuantiles(imgToCluster, histogram, m_Controls->m_q1->value(),m_Controls->m_q2->value());
}
else
{
m_CurrentRGBClusteringResults = clusterer->PerformRGBClustering(imgToCluster, histogram);
}
pFiberImg = m_CurrentRGBClusteringResults->rgbChannels->r;
cparams = m_CurrentRGBClusteringResults->params;
cresult = m_CurrentRGBClusteringResults->result;
chist = m_CurrentRGBClusteringResults->hist;
}
else
{
if(m_Controls->m_Quantiles->isChecked())
{
m_CurrentPerformClusteringResults =
clusterer->PerformQuantiles(imgToCluster, histogram, m_Controls->m_q1->value(),m_Controls->m_q2->value());
}
else
{
m_CurrentPerformClusteringResults =
clusterer->PerformClustering(imgToCluster, histogram, m_QuantifyClass);
}
pFiberImg = m_CurrentPerformClusteringResults->clusteredImage;
cparams = m_CurrentPerformClusteringResults->params;
cresult = m_CurrentPerformClusteringResults->result;
chist = m_CurrentPerformClusteringResults->hist;
}
if(m_IsTensorImage)
{
m_AngularErrorImage = clusterer->CaculateAngularErrorImage(
m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(1),
m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(2),
pFiberImg);
// GetDataStorage()->Remove(m_newnode2);
// m_newnode2 = mitk::DataNode::New();
// m_newnode2->SetData(m_AngularErrorImage);
// m_newnode2->SetName(("AngularError"));
// m_newnode2->SetIntProperty( "layer", 1003 );
// GetDataStorage()->Add(m_newnode2, m_SelectedImageNodes->GetNode());
// newnode = mitk::DataNode::New();
// newnode->SetData(m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(1));
// newnode->SetName(("Comp1"));
// GetDataStorage()->Add(newnode, m_SelectedImageNodes->GetNode());
// newnode = mitk::DataNode::New();
// newnode->SetData(m_CurrentStatisticsCalculator->GetInternalAdditionalResampledImage(2));
// newnode->SetName(("Comp2"));
// GetDataStorage()->Add(newnode, m_SelectedImageNodes->GetNode());
}
ShowClusteringResults();
}
}
statisticsCalculationSuccessful = true;
}
catch ( const std::runtime_error &e )
{
QMessageBox::information( nullptr, "Warning", e.what());
}
catch ( const std::exception &e )
{
MITK_ERROR << "Caught exception: " << e.what();
QMessageBox::information( nullptr, "Warning", e.what());
}
m_CurrentStatisticsCalculator->RemoveObserver( progressObserverTag );
// Make sure that progress bar closes
mitk::ProgressBar::GetInstance()->Progress( 100 );
if ( statisticsCalculationSuccessful )
{
if ( statisticsChanged )
{
// Do not show any error messages
m_CurrentStatisticsValid = true;
}
// m_Controls->m_HistogramWidget->SetHistogramModeToDirectHistogram();
m_Controls->m_HistogramWidget->SetParameters(
cparams, cresult, chist );
// m_Controls->m_HistogramWidget->UpdateItemModelFromHistogram();
}
else
{
m_Controls->m_SelectedMaskLabel->setText("<font color='red'>mandatory</font>");
// Clear statistics and histogram
m_Controls->m_HistogramWidget->ClearItemModel();
m_CurrentStatisticsValid = false;
// If a (non-closed) PlanarFigure is selected, display a line profile widget
if ( m_SelectedPlanarFigure.IsNotNull() )
{
// TODO: enable line profile widget
//m_Controls->m_StatisticsWidgetStack->setCurrentIndex( 1 );
//m_Controls->m_LineProfileWidget->SetImage( m_SelectedImage );
//m_Controls->m_LineProfileWidget->SetPlanarFigure( m_SelectedPlanarFigure );
//m_Controls->m_LineProfileWidget->UpdateItemModelFromPath();
}
}
}
}
void QmitkPartialVolumeAnalysisView::SetMeasurementInfoToRenderWindow(const QString& text)
{
FindRenderWindow(m_SelectedPlanarFigureNodes->GetNode());
if(m_LastRenderWindow != m_SelectedRenderWindow)
{
if(m_LastRenderWindow)
{
QObject::disconnect( m_LastRenderWindow, SIGNAL( destroyed(QObject*) )
, this, SLOT( OnRenderWindowDelete(QObject*) ) );
}
m_LastRenderWindow = m_SelectedRenderWindow;
if(m_LastRenderWindow)
{
QObject::connect( m_LastRenderWindow, SIGNAL( destroyed(QObject*) )
, this, SLOT( OnRenderWindowDelete(QObject*) ) );
}
}
if(m_LastRenderWindow && m_SelectedPlanarFigureNodes->GetNode().IsNotNull())
{
if (!text.isEmpty())
{
m_MeasurementInfoAnnotation->SetText(1, text.toLatin1().data());
mitk::VtkLayerController::GetInstance(m_LastRenderWindow->GetRenderWindow())->InsertForegroundRenderer(
m_MeasurementInfoRenderer, true);
}
else
{
if (mitk::VtkLayerController::GetInstance(
m_LastRenderWindow->GetRenderWindow()) ->IsRendererInserted(
m_MeasurementInfoRenderer))
mitk::VtkLayerController::GetInstance(m_LastRenderWindow->GetRenderWindow())->RemoveRenderer(
m_MeasurementInfoRenderer);
}
}
else
{
mitk::IRenderWindowPart* renderWindowPart = this->GetRenderWindowPart();
if ( renderWindowPart == nullptr )
{
return;
}
if (!text.isEmpty())
{
m_MeasurementInfoAnnotation->SetText(1, text.toLatin1().data());
mitk::VtkLayerController::GetInstance(renderWindowPart->GetQmitkRenderWindow("axial")->GetRenderWindow())->InsertForegroundRenderer(
m_MeasurementInfoRenderer, true);
}
else
{
if (mitk::VtkLayerController::GetInstance(
renderWindowPart->GetQmitkRenderWindow("axial")->GetRenderWindow()) ->IsRendererInserted(
m_MeasurementInfoRenderer))
mitk::VtkLayerController::GetInstance(renderWindowPart->GetQmitkRenderWindow("axial")->GetRenderWindow())->RemoveRenderer(
m_MeasurementInfoRenderer);
}
}
}
void QmitkPartialVolumeAnalysisView::UpdateProgressBar()
{
mitk::ProgressBar::GetInstance()->Progress();
}
void QmitkPartialVolumeAnalysisView::RequestStatisticsUpdate()
{
if ( !m_StatisticsUpdatePending )
{
QApplication::postEvent( this, new QmitkRequestStatisticsUpdateEvent );
m_StatisticsUpdatePending = true;
}
}
void QmitkPartialVolumeAnalysisView::RemoveOrphanImages()
{
PartialVolumeAnalysisMapType::iterator it = m_PartialVolumeAnalysisMap.begin();
while ( it != m_PartialVolumeAnalysisMap.end() )
{
mitk::Image *image = it->first;
mitk::PartialVolumeAnalysisHistogramCalculator *calculator = it->second;
++it;
mitk::NodePredicateData::Pointer hasImage = mitk::NodePredicateData::New( image );
if ( this->GetDataStorage()->GetNode( hasImage ) == nullptr )
{
if ( m_SelectedImage == image )
{
m_SelectedImage = nullptr;
m_SelectedImageNodes->RemoveAllNodes();
}
if ( m_CurrentStatisticsCalculator == calculator )
{
m_CurrentStatisticsCalculator = nullptr;
}
m_PartialVolumeAnalysisMap.erase( image );
it = m_PartialVolumeAnalysisMap.begin();
}
}
}
void QmitkPartialVolumeAnalysisView::ExtractTensorImages(
mitk::Image::Pointer tensorimage)
{
typedef itk::Image< itk::DiffusionTensor3D<float>, 3> TensorImageType;
typedef mitk::ImageToItk<TensorImageType> CastType;
CastType::Pointer caster = CastType::New();
caster->SetInput(tensorimage);
caster->Update();
TensorImageType::Pointer image = caster->GetOutput();
typedef itk::TensorDerivedMeasurementsFilter<float> MeasurementsType;
MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New();
measurementsCalculator->SetInput(image );
measurementsCalculator->SetMeasure(MeasurementsType::FA);
measurementsCalculator->Update();
MeasurementsType::OutputImageType::Pointer fa = measurementsCalculator->GetOutput();
m_FAImage = mitk::Image::New();
m_FAImage->InitializeByItk(fa.GetPointer());
m_FAImage->SetVolume(fa->GetBufferPointer());
// mitk::DataNode::Pointer node = mitk::DataNode::New();
// node->SetData(m_FAImage);
// GetDataStorage()->Add(node);
measurementsCalculator = MeasurementsType::New();
measurementsCalculator->SetInput(image );
measurementsCalculator->SetMeasure(MeasurementsType::CA);
measurementsCalculator->Update();
MeasurementsType::OutputImageType::Pointer ca = measurementsCalculator->GetOutput();
m_CAImage = mitk::Image::New();
m_CAImage->InitializeByItk(ca.GetPointer());
m_CAImage->SetVolume(ca->GetBufferPointer());
// node = mitk::DataNode::New();
// node->SetData(m_CAImage);
// GetDataStorage()->Add(node);
measurementsCalculator = MeasurementsType::New();
measurementsCalculator->SetInput(image );
measurementsCalculator->SetMeasure(MeasurementsType::RD);
measurementsCalculator->Update();
MeasurementsType::OutputImageType::Pointer rd = measurementsCalculator->GetOutput();
m_RDImage = mitk::Image::New();
m_RDImage->InitializeByItk(rd.GetPointer());
m_RDImage->SetVolume(rd->GetBufferPointer());
// node = mitk::DataNode::New();
// node->SetData(m_CAImage);
// GetDataStorage()->Add(node);
measurementsCalculator = MeasurementsType::New();
measurementsCalculator->SetInput(image );
measurementsCalculator->SetMeasure(MeasurementsType::AD);
measurementsCalculator->Update();
MeasurementsType::OutputImageType::Pointer ad = measurementsCalculator->GetOutput();
m_ADImage = mitk::Image::New();
m_ADImage->InitializeByItk(ad.GetPointer());
m_ADImage->SetVolume(ad->GetBufferPointer());
// node = mitk::DataNode::New();
// node->SetData(m_CAImage);
// GetDataStorage()->Add(node);
measurementsCalculator = MeasurementsType::New();
measurementsCalculator->SetInput(image );
measurementsCalculator->SetMeasure(MeasurementsType::RA);
measurementsCalculator->Update();
MeasurementsType::OutputImageType::Pointer md = measurementsCalculator->GetOutput();
m_MDImage = mitk::Image::New();
m_MDImage->InitializeByItk(md.GetPointer());
m_MDImage->SetVolume(md->GetBufferPointer());
// node = mitk::DataNode::New();
// node->SetData(m_CAImage);
// GetDataStorage()->Add(node);
typedef DirectionsFilterType::PeakImageType DirImageType;
DirectionsFilterType::Pointer dirFilter = DirectionsFilterType::New();
dirFilter->SetInput(image );
dirFilter->SetUsePolarCoordinates(true);
dirFilter->Update();
ItkUcharImgType::Pointer numDirImage = dirFilter->GetOutput();
DirImageType::Pointer dirImage = dirFilter->GetPeakImage();
itk::ImageRegionIterator<DirImageType> itd(dirImage, dirImage->GetLargestPossibleRegion());
itd.GoToBegin();
while( !itd.IsAtEnd() )
{
DirImageType::PixelType direction = itd.Get();
direction = fabs(direction);
itd.Set(direction);
++itd;
}
typedef itk::Image<float, 3> CompImageType;
CompImageType::Pointer comp1 = CompImageType::New();
comp1->SetSpacing( numDirImage->GetSpacing() ); // Set the image spacing
comp1->SetOrigin( numDirImage->GetOrigin() ); // Set the image origin
comp1->SetDirection( numDirImage->GetDirection() ); // Set the image direction
comp1->SetRegions( numDirImage->GetLargestPossibleRegion() );
comp1->Allocate();
CompImageType::Pointer comp2 = CompImageType::New();
comp2->SetSpacing( numDirImage->GetSpacing() ); // Set the image spacing
comp2->SetOrigin( numDirImage->GetOrigin() ); // Set the image origin
comp2->SetDirection( numDirImage->GetDirection() ); // Set the image direction
comp2->SetRegions( numDirImage->GetLargestPossibleRegion() );
comp2->Allocate();
itk::ImageRegionIterator<CompImageType> it1(comp1, comp1->GetLargestPossibleRegion());
itk::ImageRegionIterator<CompImageType> it2(comp2, comp2->GetLargestPossibleRegion());
it1.GoToBegin();
it2.GoToBegin();
while( !it2.IsAtEnd() )
{
DirImageType::IndexType peakIndex;
peakIndex[0] = it1.GetIndex()[0];
peakIndex[1] = it1.GetIndex()[1];
peakIndex[2] = it1.GetIndex()[2];
peakIndex[3] = 1;
it1.Set(dirImage->GetPixel(peakIndex));
peakIndex[3] = 2;
it2.Set(dirImage->GetPixel(peakIndex));
++it1;
++it2;
}
m_DirectionComp1Image = mitk::Image::New();
m_DirectionComp1Image->InitializeByItk(comp1.GetPointer());
m_DirectionComp1Image->SetVolume(comp1->GetBufferPointer());
m_DirectionComp2Image = mitk::Image::New();
m_DirectionComp2Image->InitializeByItk(comp2.GetPointer());
m_DirectionComp2Image->SetVolume(comp2->GetBufferPointer());
}
void QmitkPartialVolumeAnalysisView::OnRenderWindowDelete(QObject * obj)
{
if(obj == m_LastRenderWindow)
m_LastRenderWindow = 0;
if(obj == m_SelectedRenderWindow)
m_SelectedRenderWindow = 0;
}
bool QmitkPartialVolumeAnalysisView::event( QEvent *event )
{
if ( event->type() == (QEvent::Type) QmitkRequestStatisticsUpdateEvent::StatisticsUpdateRequest )
{
// Update statistics
m_StatisticsUpdatePending = false;
this->UpdateStatistics();
return true;
}
return false;
}
void QmitkPartialVolumeAnalysisView::Activated()
{
mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = this->GetDataStorage()->GetAll();
mitk::DataNode* node = 0;
mitk::PlanarFigure* figure = 0;
mitk::PlanarFigureInteractor::Pointer figureInteractor = 0;
// finally add all nodes to the model
for(mitk::DataStorage::SetOfObjects::ConstIterator it=_NodeSet->Begin(); it!=_NodeSet->End()
; it++)
{
node = const_cast<mitk::DataNode*>(it->Value().GetPointer());
figure = dynamic_cast<mitk::PlanarFigure*>(node->GetData());
if(figure)
{
figureInteractor = dynamic_cast<mitk::PlanarFigureInteractor*>(node->GetDataInteractor().GetPointer());
if(figureInteractor.IsNull())
{
figureInteractor = mitk::PlanarFigureInteractor::New();
us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" );
figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule );
figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule );
figureInteractor->SetDataNode( node );
}
}
}
}
void QmitkPartialVolumeAnalysisView::Deactivated()
{
}
void QmitkPartialVolumeAnalysisView::ActivatedZombieView(berry::IWorkbenchPartReference::Pointer)
{
this->SetMeasurementInfoToRenderWindow("");
mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = this->GetDataStorage()->GetAll();
mitk::DataNode* node = 0;
mitk::PlanarFigure* figure = 0;
mitk::PlanarFigureInteractor::Pointer figureInteractor = 0;
// finally add all nodes to the model
for(mitk::DataStorage::SetOfObjects::ConstIterator it=_NodeSet->Begin(); it!=_NodeSet->End()
; it++)
{
node = const_cast<mitk::DataNode*>(it->Value().GetPointer());
figure = dynamic_cast<mitk::PlanarFigure*>(node->GetData());
if(figure)
{
figureInteractor = dynamic_cast<mitk::PlanarFigureInteractor*>(node->GetDataInteractor().GetPointer());
if(figureInteractor)
figureInteractor->SetDataNode( nullptr );
}
}
}
void QmitkPartialVolumeAnalysisView::Hidden()
{
if (m_ClusteringResult.IsNotNull())
{
this->GetDataStorage()->Remove(m_ClusteringResult);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
Select(nullptr, true, true);
m_Visible = false;
}
void QmitkPartialVolumeAnalysisView::Visible()
{
m_Visible = true;
berry::IWorkbenchPart::Pointer bla;
if (!this->GetCurrentSelection().empty())
{
this->OnSelectionChanged(bla, this->GetCurrentSelection());
}
else
{
this->OnSelectionChanged(bla, this->GetDataManagerSelection());
}
}
void QmitkPartialVolumeAnalysisView::GreenRadio(bool checked)
{
if(checked)
{
m_Controls->m_PartialVolumeRadio->setChecked(false);
m_Controls->m_BlueRadio->setChecked(false);
m_Controls->m_AllRadio->setChecked(false);
m_Controls->m_ExportClusteringResultsButton->setEnabled(true);
}
m_QuantifyClass = 0;
RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::PartialVolumeRadio(bool checked)
{
if(checked)
{
m_Controls->m_GreenRadio->setChecked(false);
m_Controls->m_BlueRadio->setChecked(false);
m_Controls->m_AllRadio->setChecked(false);
m_Controls->m_ExportClusteringResultsButton->setEnabled(true);
}
m_QuantifyClass = 1;
RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::BlueRadio(bool checked)
{
if(checked)
{
m_Controls->m_PartialVolumeRadio->setChecked(false);
m_Controls->m_GreenRadio->setChecked(false);
m_Controls->m_AllRadio->setChecked(false);
m_Controls->m_ExportClusteringResultsButton->setEnabled(true);
}
m_QuantifyClass = 2;
RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::AllRadio(bool checked)
{
if(checked)
{
m_Controls->m_BlueRadio->setChecked(false);
m_Controls->m_PartialVolumeRadio->setChecked(false);
m_Controls->m_GreenRadio->setChecked(false);
m_Controls->m_ExportClusteringResultsButton->setEnabled(false);
}
m_QuantifyClass = 3;
RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::NumberBinsChangedSlider(int)
{
m_Controls->m_NumberBins->setText(QString("%1").arg(m_Controls->m_NumberBinsSlider->value()*5.0));
}
void QmitkPartialVolumeAnalysisView::UpsamplingChangedSlider(int)
{
m_Controls->m_Upsampling->setText(QString("%1").arg(m_Controls->m_UpsamplingSlider->value()/10.0));
}
void QmitkPartialVolumeAnalysisView::GaussianSigmaChangedSlider(int)
{
m_Controls->m_GaussianSigma->setText(QString("%1").arg(m_Controls->m_GaussianSigmaSlider->value()/100.0));
}
void QmitkPartialVolumeAnalysisView::SimilarAnglesChangedSlider(int)
{
m_Controls->m_SimilarAngles->setText(QString("%1°").arg(90-m_Controls->m_SimilarAnglesSlider->value()));
ShowClusteringResults();
}
void QmitkPartialVolumeAnalysisView::OpacityChangedSlider(int v )
{
if(m_SelectedImageNodes->GetNode().IsNotNull())
{
float opacImag = 1.0f-(v-5)/5.0f;
opacImag = opacImag < 0 ? 0 : opacImag;
m_SelectedImageNodes->GetNode()->SetFloatProperty("opacity", opacImag);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
if(m_ClusteringResult.IsNotNull())
{
float opacClust = v/5.0f;
opacClust = opacClust > 1 ? 1 : opacClust;
m_ClusteringResult->SetFloatProperty("opacity", opacClust);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkPartialVolumeAnalysisView::NumberBinsReleasedSlider( )
{
RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::UpsamplingReleasedSlider( )
{
RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::GaussianSigmaReleasedSlider( )
{
RequestStatisticsUpdate();
}
void QmitkPartialVolumeAnalysisView::SimilarAnglesReleasedSlider( )
{
}
void QmitkPartialVolumeAnalysisView::ToClipBoard()
{
std::vector<std::vector<double>* > vals = m_Controls->m_HistogramWidget->m_Vals;
QString clipboardText;
for (std::vector<std::vector<double>* >::iterator it = vals.begin(); it
!= vals.end(); ++it)
{
for (std::vector<double>::iterator it2 = (**it).begin(); it2 != (**it).end(); ++it2)
{
clipboardText.append(QString("%1 \t").arg(*it2));
}
clipboardText.append(QString("\n"));
}
QApplication::clipboard()->setText(clipboardText, QClipboard::Clipboard);
}
void QmitkPartialVolumeAnalysisView::PropertyChanged(const mitk::DataNode* /*node*/, const mitk::BaseProperty* /*prop*/)
{
}
void QmitkPartialVolumeAnalysisView::NodeChanged(const mitk::DataNode* /*node*/)
{
}
void QmitkPartialVolumeAnalysisView::NodeRemoved(const mitk::DataNode* node)
{
if (dynamic_cast<mitk::PlanarFigure*>(node->GetData()))
this->GetDataStorage()->Remove(m_ClusteringResult);
if( node == m_SelectedPlanarFigureNodes->GetNode().GetPointer()
|| node == m_SelectedMaskNode.GetPointer() )
{
this->Select(nullptr,true,false);
SetMeasurementInfoToRenderWindow("");
}
if( node == m_SelectedImageNodes->GetNode().GetPointer() )
{
this->Select(nullptr,false,true);
SetMeasurementInfoToRenderWindow("");
}
}
void QmitkPartialVolumeAnalysisView::NodeAddedInDataStorage(const mitk::DataNode* node)
{
if(!m_Visible)
return;
mitk::DataNode* nonConstNode = const_cast<mitk::DataNode*>(node);
mitk::PlanarFigure* figure = dynamic_cast<mitk::PlanarFigure*>(nonConstNode->GetData());
if(figure)
{
// set interactor for new node (if not already set)
mitk::PlanarFigureInteractor::Pointer figureInteractor
= dynamic_cast<mitk::PlanarFigureInteractor*>(node->GetDataInteractor().GetPointer());
if(figureInteractor.IsNull())
{
figureInteractor = mitk::PlanarFigureInteractor::New();
us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" );
figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule );
figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule );
figureInteractor->SetDataNode( nonConstNode );
}
// remove uninitialized old planars
if( m_SelectedPlanarFigureNodes->GetNode().IsNotNull() && m_CurrentFigureNodeInitialized == false )
{
this->GetDataStorage()->Remove(m_SelectedPlanarFigureNodes->GetNode());
}
}
}
void QmitkPartialVolumeAnalysisView::TextIntON()
{
if(m_ClusteringResult.IsNotNull())
{
if(m_TexIsOn)
{
m_Controls->m_TextureIntON->setIcon(*m_IconTexOFF);
}
else
{
m_Controls->m_TextureIntON->setIcon(*m_IconTexON);
}
m_ClusteringResult->SetBoolProperty("texture interpolation", !m_TexIsOn);
m_TexIsOn = !m_TexIsOn;
this->RequestRenderWindowUpdate();
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/internal/QmitkPartialVolumeAnalysisView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/internal/QmitkPartialVolumeAnalysisView.h
index 818e385..d33b5e2 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/internal/QmitkPartialVolumeAnalysisView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/internal/QmitkPartialVolumeAnalysisView.h
@@ -1,269 +1,269 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
#if !defined(QmitkPartialVolumeAnalysisView_H__INCLUDED)
#define QmitkPartialVolumeAnalysisView_H__INCLUDED
#include "ui_QmitkPartialVolumeAnalysisViewControls.h"
#include <QmitkAbstractView.h>
#include <berryIWorkbenchPartReference.h>
#include <mitkIZombieViewPart.h>
// berry
#include <berryISelectionListener.h>
#include <berryIStructuredSelection.h>
// itk
#include <itkTimeStamp.h>
#include <itkDiffusionTensorPrincipalDirectionImageFilter.h>
#include <itkExtractChannelFromRgbaImageFilter.h>
// qmitk
#include "QmitkStepperAdapter.h"
#include "QmitkRenderWindow.h"
// mitk
#include "mitkPartialVolumeAnalysisHistogramCalculator.h"
#include "mitkPlanarLine.h"
#include "mitkDataStorageSelection.h"
#include <mitkVtkLayerController.h>
// vtk
#include <vtkTextProperty.h>
#include <vtkRenderer.h>
#include <vtkCornerAnnotation.h>
//#include "itkProcessObject.h"
/*!
\brief QmitkPartialVolumeAnalysis
*/
class QmitkPartialVolumeAnalysisView : public QmitkAbstractView, public mitk::IZombieViewPart//, public itk::ProcessObject
{
Q_OBJECT
public:
/*!
\ Convenient typedefs
*/
typedef mitk::DataStorage::SetOfObjects ConstVector;
typedef ConstVector::ConstPointer ConstVectorPointer;
typedef ConstVector::ConstIterator ConstVectorIterator;
typedef mitk::PartialVolumeAnalysisHistogramCalculator HistogramCalculatorType;
typedef HistogramCalculatorType::HistogramType HistogramType;
typedef mitk::PartialVolumeAnalysisClusteringCalculator ClusteringType;
typedef itk::DiffusionTensorPrincipalDirectionImageFilter<float> DirectionsFilterType;
typedef itk::Image<unsigned char, 3> ItkUcharImgType;
/*!
\brief default constructor
*/
QmitkPartialVolumeAnalysisView(QObject *parent=0, const char *name=0);
/*!
\brief default destructor
*/
virtual ~QmitkPartialVolumeAnalysisView();
/*!
\brief method for creating the widget containing the application controls, like sliders, buttons etc.
*/
virtual void CreateQtPartControl(QWidget *parent) override;
/*!
\brief method for creating the connections of main and control widget
*/
virtual void CreateConnections();
virtual bool event( QEvent *event ) override;
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
virtual void Activated() override;
virtual void Deactivated() override;
virtual void ActivatedZombieView(berry::IWorkbenchPartReference::Pointer reference) override;
virtual void Hidden() override;
virtual void Visible() override;
virtual void SetFocus() override;
bool AssertDrawingIsPossible(bool checked);
virtual void NodeChanged(const mitk::DataNode* node) override;
virtual void PropertyChanged(const mitk::DataNode* node, const mitk::BaseProperty* prop);
virtual void NodeRemoved(const mitk::DataNode* node) override;
virtual void NodeAddedInDataStorage(const mitk::DataNode* node);
virtual void AddFigureToDataStorage(mitk::PlanarFigure* figure, const QString& name,
const char *propertyKey = nullptr, mitk::BaseProperty *property = nullptr );
void PlanarFigureInitialized();
void PlanarFigureFocus(mitk::DataNode* node);
void ShowClusteringResults();
static const std::string VIEW_ID;
protected slots:
void EstimateCircle();
void SetHistogramVisibility();
void SetAdvancedVisibility();
void NumberBinsChangedSlider(int v );
void UpsamplingChangedSlider( int v );
void GaussianSigmaChangedSlider( int v );
void SimilarAnglesChangedSlider(int v );
void OpacityChangedSlider(int v );
void NumberBinsReleasedSlider( );
void UpsamplingReleasedSlider( );
void GaussianSigmaReleasedSlider( );
void SimilarAnglesReleasedSlider( );
void ActionDrawEllipseTriggered();
void ActionDrawRectangleTriggered();
void ActionDrawPolygonTriggered();
void ToClipBoard();
void GreenRadio(bool checked);
void PartialVolumeRadio(bool checked);
void BlueRadio(bool checked);
void AllRadio(bool checked);
void OnRenderWindowDelete(QObject * obj);
void TextIntON();
void ExportClusteringResults();
protected:
/** \brief Issues a request to update statistics by sending an event to the
* Qt event processing queue.
*
* Statistics update should only be executed after program execution returns
* to the Qt main loop. This mechanism also prevents multiple execution of
* updates where only one is required.*/
void RequestStatisticsUpdate();
/** \brief Recalculate statistics for currently selected image and mask and
* update the GUI. */
void UpdateStatistics();
/** \brief Listener for progress events to update progress bar. */
void UpdateProgressBar();
/** \brief Removes any cached images which are no longer referenced elsewhere. */
void RemoveOrphanImages();
void Select( mitk::DataNode::Pointer node, bool clearMaskOnFirstArgnullptr=false, bool clearImageOnFirstArgnullptr=false );
void SetMeasurementInfoToRenderWindow(const QString& text);
void FindRenderWindow(mitk::DataNode* node);
void ExtractTensorImages(
mitk::Image::Pointer tensorimage);
typedef std::map< mitk::Image *, mitk::PartialVolumeAnalysisHistogramCalculator::Pointer >
PartialVolumeAnalysisMapType;
/*!
* controls containing sliders for scrolling through the slices
*/
Ui::QmitkPartialVolumeAnalysisViewControls *m_Controls;
QmitkStepperAdapter* m_TimeStepperAdapter;
unsigned int m_CurrentTime;
QString m_Clipboard;
// result text rendering
vtkRenderer * m_MeasurementInfoRenderer;
vtkCornerAnnotation *m_MeasurementInfoAnnotation;
// Image and mask data
mitk::DataStorageSelection::Pointer m_SelectedImageNodes;
mitk::Image::Pointer m_SelectedImage;
mitk::DataNode::Pointer m_SelectedMaskNode;
mitk::Image::Pointer m_SelectedImageMask;
mitk::DataStorageSelection::Pointer m_SelectedPlanarFigureNodes;
mitk::PlanarFigure::Pointer m_SelectedPlanarFigure;
bool m_IsTensorImage;
mitk::Image::Pointer m_FAImage;
mitk::Image::Pointer m_CAImage;
mitk::Image::Pointer m_RDImage;
mitk::Image::Pointer m_ADImage;
mitk::Image::Pointer m_MDImage;
mitk::Image::Pointer m_DirectionComp1Image;
mitk::Image::Pointer m_DirectionComp2Image;
mitk::Image::Pointer m_AngularErrorImage;
QmitkRenderWindow* m_SelectedRenderWindow;
QmitkRenderWindow* m_LastRenderWindow;
long m_ImageObserverTag;
long m_ImageMaskObserverTag;
long m_PlanarFigureObserverTag;
// Hash map for associating one image statistics calculator with each iamge
// (so that previously calculated histograms / statistics can be recovered
// if a recalculation is not required)
PartialVolumeAnalysisMapType m_PartialVolumeAnalysisMap;
HistogramCalculatorType::Pointer m_CurrentStatisticsCalculator;
bool m_CurrentStatisticsValid;
bool m_StatisticsUpdatePending;
bool m_GaussianSigmaChangedSliding;
bool m_NumberBinsSliding;
bool m_UpsamplingChangedSliding;
mitk::DataNode::Pointer m_ClusteringResult;
int m_EllipseCounter;
int m_RectangleCounter;
int m_PolygonCounter;
long m_InitializedObserverTag;
bool m_CurrentFigureNodeInitialized;
int m_QuantifyClass;
ClusteringType::HelperStructPerformRGBClusteringRetval* m_CurrentRGBClusteringResults;
ClusteringType::HelperStructPerformClusteringRetval *m_CurrentPerformClusteringResults;
QIcon* m_IconTexOFF;
QIcon* m_IconTexON;
bool m_TexIsOn;
bool m_Visible;
};
#endif
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/internal/mitkPluginActivator.cpp
index 7826fd7..9ccfa94 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/internal/mitkPluginActivator.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/internal/mitkPluginActivator.cpp
@@ -1,38 +1,38 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPluginActivator.h"
#include "src/internal/QmitkPartialVolumeAnalysisView.h"
ctkPluginContext* mitk::PluginActivator::m_Context = nullptr;
ctkPluginContext* mitk::PluginActivator::GetContext()
{
return m_Context;
}
void mitk::PluginActivator::start(ctkPluginContext* context)
{
BERRY_REGISTER_EXTENSION_CLASS(QmitkPartialVolumeAnalysisView, context)
m_Context = context;
}
void mitk::PluginActivator::stop(ctkPluginContext* context)
{
Q_UNUSED(context)
m_Context = nullptr;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/internal/mitkPluginActivator.h
index ff7d548..7dce09b 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/internal/mitkPluginActivator.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.partialvolume/src/internal/mitkPluginActivator.h
@@ -1,40 +1,40 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKPLUGINACTIVATOR_H
#define MITKPLUGINACTIVATOR_H
#include <ctkPluginActivator.h>
namespace mitk
{
class PluginActivator : public QObject, public ctkPluginActivator
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.mitk.gui.qt.diffusionimaging.partialvolume")
Q_INTERFACES(ctkPluginActivator)
public:
static ctkPluginContext* GetContext();
void start(ctkPluginContext* context) override;
void stop(ctkPluginContext* context) override;
private:
static ctkPluginContext* m_Context;
};
}
#endif
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkDwiPreprocessingPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkDwiPreprocessingPerspective.cpp
index e93488f..bf6db8f 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkDwiPreprocessingPerspective.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkDwiPreprocessingPerspective.cpp
@@ -1,52 +1,52 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkDwiPreprocessingPerspective.h"
#include "berryIViewLayout.h"
void QmitkDwiPreprocessingPerspective::CreateInitialLayout(berry::IPageLayout::Pointer layout)
{
/////////////////////////////////////////////////////
// all di-app perspectives should have the following:
/////////////////////////////////////////////////////
QString editorArea = layout->GetEditorArea();
layout->AddStandaloneViewPlaceholder("org.mitk.views.viewnavigatorview", berry::IPageLayout::LEFT, 0.3f, editorArea, false);
layout->AddStandaloneView("org.mitk.views.datamanager",
false, berry::IPageLayout::LEFT, 0.3f, editorArea);
layout->AddStandaloneView("org.mitk.views.controlvisualizationpropertiesview",
false, berry::IPageLayout::BOTTOM, .15f, "org.mitk.views.datamanager");
berry::IFolderLayout::Pointer left =
layout->CreateFolder("org.mbi.diffusionimaginginternal.leftcontrols",
berry::IPageLayout::BOTTOM, 0.15f, "org.mitk.views.controlvisualizationpropertiesview");
layout->AddStandaloneViewPlaceholder("org.mitk.views.imagenavigator",
berry::IPageLayout::BOTTOM, .7f, "org.mbi.diffusionimaginginternal.leftcontrols", false);
/////////////////////////////////////////////
// here goes the perspective specific stuff
/////////////////////////////////////////////
left->AddView("org.mitk.views.diffusionpreprocessing");
left->AddView("org.mitk.views.brainextraction");
left->AddView("org.mitk.views.denoisingview");
left->AddView("org.mitk.views.simpleregistrationview");
left->AddView("org.mitk.views.headmotioncorrectionview");
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkDwiPreprocessingPerspective.h b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkDwiPreprocessingPerspective.h
index 9cad805..2df1d99 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkDwiPreprocessingPerspective.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkDwiPreprocessingPerspective.h
@@ -1,36 +1,36 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkDwiPreprocessingPerspective_H_
#define QmitkDwiPreprocessingPerspective_H_
#include <berryIPerspectiveFactory.h>
class QmitkDwiPreprocessingPerspective : public QObject, public berry::IPerspectiveFactory
{
Q_OBJECT
Q_INTERFACES(berry::IPerspectiveFactory)
public:
QmitkDwiPreprocessingPerspective() {}
~QmitkDwiPreprocessingPerspective() {}
void CreateInitialLayout(berry::IPageLayout::Pointer layout) override;
};
#endif /* QmitkFiberProcessingPerspective_H_ */
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingView.cpp
index 6ee520d..b865c30 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingView.cpp
@@ -1,1951 +1,1951 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
//#define MBILOG_ENABLE_DEBUG
#include "QmitkPreprocessingView.h"
#include "mitkDiffusionImagingConfigure.h"
// qt includes
#include <QMessageBox>
// itk includes
#include "itkTimeProbe.h"
#include "itkB0ImageExtractionImageFilter.h"
#include "itkB0ImageExtractionToSeparateImageFilter.h"
#include "itkBrainMaskExtractionImageFilter.h"
#include "itkCastImageFilter.h"
#include "itkVectorContainer.h"
#include <itkElectrostaticRepulsionDiffusionGradientReductionFilter.h>
#include <itkMergeDiffusionImagesFilter.h>
#include <itkDwiGradientLengthCorrectionFilter.h>
#include <itkDwiNormilzationFilter.h>
#include <mitkTensorImage.h>
#include <mitkOdfImage.h>
// Multishell includes
#include <itkRadialMultishellToSingleshellImageFilter.h>
// Multishell Functors
#include <itkADCAverageFunctor.h>
#include <itkKurtosisFitFunctor.h>
#include <itkBiExpFitFunctor.h>
#include <itkADCFitFunctor.h>
// mitk includes
#include "QmitkDataStorageComboBox.h"
#include "mitkProgressBar.h"
#include "mitkStatusBar.h"
#include "mitkNodePredicateDataType.h"
#include "mitkProperties.h"
#include "mitkVtkResliceInterpolationProperty.h"
#include "mitkLookupTable.h"
#include "mitkLookupTableProperty.h"
#include "mitkTransferFunction.h"
#include "mitkTransferFunctionProperty.h"
#include "mitkDataNodeObject.h"
#include "mitkOdfNormalizationMethodProperty.h"
#include "mitkOdfScaleByProperty.h"
#include <mitkPointSet.h>
#include <itkAdcImageFilter.h>
#include <itkBrainMaskExtractionImageFilter.h>
#include <mitkImageCast.h>
#include <mitkRotationOperation.h>
#include <QTableWidgetItem>
#include <QTableWidget>
#include <mitkInteractionConst.h>
#include <mitkImageAccessByItk.h>
#include <itkResampleDwiImageFilter.h>
#include <itkResampleImageFilter.h>
#include <itkImageDuplicator.h>
#include <itkMaskImageFilter.h>
#include <mitkNodePredicateProperty.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateOr.h>
#include <itkCropImageFilter.h>
#include <itkDiffusionTensor3DReconstructionImageFilter.h>
#include <itkRemoveDwiChannelFilter.h>
#include <itkExtractDwiChannelFilter.h>
#include <mitkBValueMapProperty.h>
#include <mitkGradientDirectionsProperty.h>
#include <mitkMeasurementFrameProperty.h>
#include <itkImageDuplicator.h>
#include <itkFlipImageFilter.h>
#include <mitkITKImageImport.h>
const std::string QmitkPreprocessingView::VIEW_ID =
"org.mitk.views.diffusionpreprocessing";
#define DI_INFO MITK_INFO("DiffusionImaging")
typedef float TTensorPixelType;
QmitkPreprocessingView::QmitkPreprocessingView()
: QmitkAbstractView(),
m_Controls(nullptr)
{
}
QmitkPreprocessingView::~QmitkPreprocessingView()
{
}
void QmitkPreprocessingView::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
// create GUI widgets
m_Controls = new Ui::QmitkPreprocessingViewControls;
m_Controls->setupUi(parent);
this->CreateConnections();
m_Controls->m_MeasurementFrameTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
m_Controls->m_MeasurementFrameTable->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
m_Controls->m_DirectionMatrixTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
m_Controls->m_DirectionMatrixTable->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
}
}
void QmitkPreprocessingView::SetFocus()
{
m_Controls->m_MirrorGradientToHalfSphereButton->setFocus();
}
void QmitkPreprocessingView::CreateConnections()
{
if ( m_Controls )
{
m_Controls->m_NormalizationMaskBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_SelctedImageComboBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_MergeDwiBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_AlignImageBox->SetDataStorage(this->GetDataStorage());
mitk::TNodePredicateDataType<mitk::Image>::Pointer isMitkImage = mitk::TNodePredicateDataType<mitk::Image>::New();
mitk::NodePredicateDataType::Pointer isDti = mitk::NodePredicateDataType::New("TensorImage");
mitk::NodePredicateDataType::Pointer isOdf = mitk::NodePredicateDataType::New("OdfImage");
mitk::NodePredicateOr::Pointer isDiffusionImage = mitk::NodePredicateOr::New(isOdf, isDti);
mitk::NodePredicateAnd::Pointer noDiffusionImage = mitk::NodePredicateAnd::New(isMitkImage, mitk::NodePredicateNot::New(isDiffusionImage));
mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true));
mitk::NodePredicateAnd::Pointer binaryNoDiffusionImage = mitk::NodePredicateAnd::New(noDiffusionImage, isBinaryPredicate);
m_Controls->m_NormalizationMaskBox->SetPredicate(binaryNoDiffusionImage);
m_Controls->m_SelctedImageComboBox->SetPredicate(isMitkImage);
m_Controls->m_MergeDwiBox->SetPredicate(isMitkImage);
m_Controls->m_AlignImageBox->SetPredicate(isMitkImage);
m_Controls->m_ExtractBrainMask->setVisible(false);
m_Controls->m_BrainMaskIterationsBox->setVisible(false);
m_Controls->m_ResampleIntFrame->setVisible(false);
connect( (QObject*)(m_Controls->m_ButtonAverageGradients), SIGNAL(clicked()), this, SLOT(AverageGradients()) );
connect( (QObject*)(m_Controls->m_ButtonExtractB0), SIGNAL(clicked()), this, SLOT(ExtractB0()) );
connect( (QObject*)(m_Controls->m_ReduceGradientsButton), SIGNAL(clicked()), this, SLOT(DoReduceGradientDirections()) );
connect( (QObject*)(m_Controls->m_ShowGradientsButton), SIGNAL(clicked()), this, SLOT(DoShowGradientDirections()) );
connect( (QObject*)(m_Controls->m_MirrorGradientToHalfSphereButton), SIGNAL(clicked()), this, SLOT(DoHalfSphereGradientDirections()) );
connect( (QObject*)(m_Controls->m_MergeDwisButton), SIGNAL(clicked()), this, SLOT(MergeDwis()) );
connect( (QObject*)(m_Controls->m_ProjectSignalButton), SIGNAL(clicked()), this, SLOT(DoProjectSignal()) );
connect( (QObject*)(m_Controls->m_B_ValueMap_Rounder_SpinBox), SIGNAL(valueChanged(int)), this, SLOT(UpdateDwiBValueMapRounder(int)));
connect( (QObject*)(m_Controls->m_CreateLengthCorrectedDwi), SIGNAL(clicked()), this, SLOT(DoLengthCorrection()) );
connect( (QObject*)(m_Controls->m_NormalizeImageValuesButton), SIGNAL(clicked()), this, SLOT(DoDwiNormalization()) );
connect( (QObject*)(m_Controls->m_ResampleImageButton), SIGNAL(clicked()), this, SLOT(DoResampleImage()) );
connect( (QObject*)(m_Controls->m_ResampleTypeBox), SIGNAL(currentIndexChanged(int)), this, SLOT(DoUpdateInterpolationGui(int)) );
connect( (QObject*)(m_Controls->m_CropImageButton), SIGNAL(clicked()), this, SLOT(DoCropImage()) );
connect( (QObject*)(m_Controls->m_RemoveGradientButton), SIGNAL(clicked()), this, SLOT(DoRemoveGradient()) );
connect( (QObject*)(m_Controls->m_ExtractGradientButton), SIGNAL(clicked()), this, SLOT(DoExtractGradient()) );
connect( (QObject*)(m_Controls->m_FlipAxis), SIGNAL(clicked()), this, SLOT(DoFlipAxis()) );
connect( (QObject*)(m_Controls->m_FlipGradientsButton), SIGNAL(clicked()), this, SLOT(DoFlipGradientDirections()) );
connect( (QObject*)(m_Controls->m_ClearRotationButton), SIGNAL(clicked()), this, SLOT(DoClearRotationOfGradients()) );
connect( (QObject*)(m_Controls->m_ModifyHeader), SIGNAL(clicked()), this, SLOT(DoApplyHeader()) );
connect( (QObject*)(m_Controls->m_AlignImageButton), SIGNAL(clicked()), this, SLOT(DoAlignImages()) );
connect( (QObject*)(m_Controls->m_SelctedImageComboBox), SIGNAL(OnSelectionChanged(const mitk::DataNode*)), this, SLOT(OnImageSelectionChanged()) );
m_Controls->m_NormalizationMaskBox->SetZeroEntryText("--");
QFont f("monospace");
f.setStyleHint(QFont::Monospace);
m_Controls->m_OriginalGradientsText->setFont(f);
m_Controls->m_WorkingGradientsText->setFont(f);
}
}
void QmitkPreprocessingView::DoAlignImages()
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
mitk::DataNode::Pointer target_node = m_Controls->m_AlignImageBox->GetSelectedNode();
if (target_node.IsNull()) { return; }
mitk::Image::Pointer target_image = dynamic_cast<mitk::Image*>(target_node->GetData());
if ( target_image == nullptr ) { return; }
image->SetOrigin(target_image->GetGeometry()->GetOrigin());
mitk::RenderingManager::GetInstance()->InitializeViews( image->GetTimeGeometry(),
mitk::RenderingManager::REQUEST_UPDATE_ALL,
true );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkPreprocessingView::DoFlipAxis()
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(node) );
if (isDiffusionImage)
{
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(image, itkVectorImagePointer);
itk::FixedArray<bool, 3> flipAxes;
flipAxes[0] = m_Controls->m_FlipX->isChecked();
flipAxes[1] = m_Controls->m_FlipY->isChecked();
flipAxes[2] = m_Controls->m_FlipZ->isChecked();
itk::FlipImageFilter< ItkDwiType >::Pointer flipper = itk::FlipImageFilter< ItkDwiType >::New();
flipper->SetInput(itkVectorImagePointer);
flipper->SetFlipAxes(flipAxes);
flipper->Update();
auto oldGradients = PropHelper::GetGradientContainer(image);
auto newGradients = GradProp::GradientDirectionsContainerType::New();
for (unsigned int i=0; i<oldGradients->Size(); i++)
{
GradProp::GradientDirectionType g = oldGradients->GetElement(i);
GradProp::GradientDirectionType newG = g;
if (flipAxes[0]) { newG[0] *= -1; }
if (flipAxes[1]) { newG[1] *= -1; }
if (flipAxes[2]) { newG[2] *= -1; }
newGradients->InsertElement(i, newG);
}
mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( flipper->GetOutput() );
PropHelper::CopyProperties(image, newImage, true);
PropHelper::SetGradientContainer(newImage, newGradients);
PropHelper::InitializeImage(newImage);
newImage->GetGeometry()->SetOrigin(image->GetGeometry()->GetOrigin());
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( newImage );
QString name = node->GetName().c_str();
imageNode->SetName((name+"_flipped").toStdString().c_str());
GetDataStorage()->Add(imageNode, node);
mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
else if( image->GetPixelType().GetNumberOfComponents() == 1 )
{
AccessFixedDimensionByItk(image, TemplatedFlipAxis,3);
}
else
{
QMessageBox::warning(nullptr,"Warning", QString("Operation not supported in multi-component images") );
}
}
template < typename TPixel, unsigned int VImageDimension >
void QmitkPreprocessingView::TemplatedFlipAxis(itk::Image<TPixel, VImageDimension>* itkImage)
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
itk::FixedArray<bool, 3> flipAxes;
flipAxes[0] = m_Controls->m_FlipX->isChecked();
flipAxes[1] = m_Controls->m_FlipY->isChecked();
flipAxes[2] = m_Controls->m_FlipZ->isChecked();
typename itk::FlipImageFilter< itk::Image<TPixel, VImageDimension> >::Pointer flipper
= itk::FlipImageFilter< itk::Image<TPixel, VImageDimension> >::New();
flipper->SetInput(itkImage);
flipper->SetFlipAxes(flipAxes);
flipper->Update();
mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( flipper->GetOutput() );
newImage->GetGeometry()->SetOrigin(image->GetGeometry()->GetOrigin());
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( newImage );
QString name = node->GetName().c_str();
imageNode->SetName((name+"_flipped").toStdString().c_str());
GetDataStorage()->Add(imageNode, node);
mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(),
mitk::RenderingManager::REQUEST_UPDATE_ALL,
true );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkPreprocessingView::DoRemoveGradient()
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) );
if ( !isDiffusionImage )
{
return;
}
std::vector< unsigned int > channelsToRemove;
channelsToRemove.push_back(m_Controls->m_RemoveGradientBox->value());
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(image, itkVectorImagePointer);
itk::RemoveDwiChannelFilter< short >::Pointer filter = itk::RemoveDwiChannelFilter< short >::New();
filter->SetInput(itkVectorImagePointer);
filter->SetChannelIndices(channelsToRemove);
filter->SetDirections(PropHelper::GetGradientContainer(image));
filter->Update();
mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( filter->GetOutput() );
PropHelper::CopyProperties(image, newImage, true);
PropHelper::SetGradientContainer(newImage, filter->GetNewDirections());
PropHelper::InitializeImage( newImage );
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( newImage );
QString name = node->GetName().c_str();
imageNode->SetName((name+"_removedgradients").toStdString().c_str());
GetDataStorage()->Add(imageNode, node);
mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(),
mitk::RenderingManager::REQUEST_UPDATE_ALL,
true );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkPreprocessingView::DoExtractGradient()
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) );
if ( !isDiffusionImage ) { return; }
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(image, itkVectorImagePointer);
unsigned int channel = m_Controls->m_ExtractGradientBox->value();
itk::ExtractDwiChannelFilter< short >::Pointer filter = itk::ExtractDwiChannelFilter< short >::New();
filter->SetInput( itkVectorImagePointer);
filter->SetChannelIndex(channel);
filter->Update();
mitk::Image::Pointer newImage = mitk::Image::New();
newImage->InitializeByItk( filter->GetOutput() );
newImage->SetImportChannel( filter->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( newImage );
QString name = node->GetName().c_str();
imageNode->SetName( (name+"_direction-"+QString::number(channel)).toStdString().c_str() );
GetDataStorage()->Add(imageNode, node);
mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(),
mitk::RenderingManager::REQUEST_UPDATE_ALL,
true);
}
void QmitkPreprocessingView::DoCropImage()
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) );
if ( isDiffusionImage )
{
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(image, itkVectorImagePointer);
ItkDwiType::SizeType lower;
ItkDwiType::SizeType upper;
lower[0] = m_Controls->m_XstartBox->value();
lower[1] = m_Controls->m_YstartBox->value();
lower[2] = m_Controls->m_ZstartBox->value();
upper[0] = m_Controls->m_XendBox->value();
upper[1] = m_Controls->m_YendBox->value();
upper[2] = m_Controls->m_ZendBox->value();
itk::CropImageFilter< ItkDwiType, ItkDwiType >::Pointer cropper = itk::CropImageFilter< ItkDwiType, ItkDwiType >::New();
cropper->SetLowerBoundaryCropSize(lower);
cropper->SetUpperBoundaryCropSize(upper);
cropper->SetInput( itkVectorImagePointer );
cropper->Update();
ItkDwiType::Pointer itkOutImage = cropper->GetOutput();
ItkDwiType::DirectionType dir = itkOutImage->GetDirection();
itk::Point<double,3> origin = itkOutImage->GetOrigin();
itk::Point<double,3> t; t[0] = lower[0]*itkOutImage->GetSpacing()[0]; t[1] = lower[1]*itkOutImage->GetSpacing()[1]; t[2] = lower[2]*itkOutImage->GetSpacing()[2];
t= dir*t;
origin[0] += t[0];
origin[1] += t[1];
origin[2] += t[2];
itkOutImage->SetOrigin(origin);
mitk::Image::Pointer newimage = mitk::GrabItkImageMemory( itkOutImage );
PropHelper::CopyProperties(image, newimage, false);
PropHelper::InitializeImage( newimage );
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( newimage );
QString name = node->GetName().c_str();
imageNode->SetName((name+"_cropped").toStdString().c_str());
GetDataStorage()->Add(imageNode, node);
mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(),
mitk::RenderingManager::REQUEST_UPDATE_ALL,
true );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(),
mitk::RenderingManager::REQUEST_UPDATE_ALL,
true );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
else if( image->GetPixelType().GetNumberOfComponents() )
{
AccessFixedDimensionByItk(image, TemplatedCropImage,3);
}
else
{
QMessageBox::warning(nullptr,"Warning", QString("Operation not supported in multi-component images") );
}
}
template < typename TPixel, unsigned int VImageDimension >
void QmitkPreprocessingView::TemplatedCropImage( itk::Image<TPixel, VImageDimension>* itkImage)
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
ItkDwiType::SizeType lower;
ItkDwiType::SizeType upper;
lower[0] = m_Controls->m_XstartBox->value();
lower[1] = m_Controls->m_YstartBox->value();
lower[2] = m_Controls->m_ZstartBox->value();
upper[0] = m_Controls->m_XendBox->value();
upper[1] = m_Controls->m_YendBox->value();
upper[2] = m_Controls->m_ZendBox->value();
typedef itk::Image<TPixel, VImageDimension> ImageType;
typename itk::CropImageFilter< ImageType, ImageType >::Pointer cropper
= itk::CropImageFilter< ImageType, ImageType >::New();
cropper->SetLowerBoundaryCropSize(lower);
cropper->SetUpperBoundaryCropSize(upper);
cropper->SetInput(itkImage);
cropper->Update();
typename ImageType::Pointer itkOutImage = cropper->GetOutput();
typename ImageType::DirectionType dir = itkOutImage->GetDirection();
itk::Point<double,3> origin = itkOutImage->GetOrigin();
itk::Point<double,3> t; t[0] = lower[0]*itkOutImage->GetSpacing()[0]; t[1] = lower[1]*itkOutImage->GetSpacing()[1]; t[2] = lower[2]*itkOutImage->GetSpacing()[2];
t= dir*t;
origin[0] += t[0];
origin[1] += t[1];
origin[2] += t[2];
itkOutImage->SetOrigin(origin);
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk( itkOutImage.GetPointer() );
image->SetVolume( itkOutImage->GetBufferPointer() );
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( image );
QString name = node->GetName().c_str();
imageNode->SetName((name+"_cropped").toStdString().c_str());
GetDataStorage()->Add(imageNode, node);
mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(),
mitk::RenderingManager::REQUEST_UPDATE_ALL,
true );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkPreprocessingView::DoUpdateInterpolationGui(int i)
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
switch (i)
{
case 0:
{
m_Controls->m_ResampleIntFrame->setVisible(false);
m_Controls->m_ResampleDoubleFrame->setVisible(true);
break;
}
case 1:
{
m_Controls->m_ResampleIntFrame->setVisible(false);
m_Controls->m_ResampleDoubleFrame->setVisible(true);
mitk::BaseGeometry* geom = image->GetGeometry();
m_Controls->m_ResampleDoubleX->setValue(geom->GetSpacing()[0]);
m_Controls->m_ResampleDoubleY->setValue(geom->GetSpacing()[1]);
m_Controls->m_ResampleDoubleZ->setValue(geom->GetSpacing()[2]);
break;
}
case 2:
{
m_Controls->m_ResampleIntFrame->setVisible(true);
m_Controls->m_ResampleDoubleFrame->setVisible(false);
mitk::BaseGeometry* geom = image->GetGeometry();
m_Controls->m_ResampleIntX->setValue(geom->GetExtent(0));
m_Controls->m_ResampleIntY->setValue(geom->GetExtent(1));
m_Controls->m_ResampleIntZ->setValue(geom->GetExtent(2));
break;
}
default:
{
m_Controls->m_ResampleIntFrame->setVisible(false);
m_Controls->m_ResampleDoubleFrame->setVisible(true);
}
}
}
void QmitkPreprocessingView::DoExtractBrainMask()
{
}
void QmitkPreprocessingView::DoResampleImage()
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) );
if ( isDiffusionImage )
{
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(image, itkVectorImagePointer);
typedef itk::ResampleDwiImageFilter< short > ResampleFilter;
ResampleFilter::Pointer resampler = ResampleFilter::New();
resampler->SetInput( itkVectorImagePointer );
switch (m_Controls->m_ResampleTypeBox->currentIndex())
{
case 0:
{
itk::Vector< double, 3 > samplingFactor;
samplingFactor[0] = m_Controls->m_ResampleDoubleX->value();
samplingFactor[1] = m_Controls->m_ResampleDoubleY->value();
samplingFactor[2] = m_Controls->m_ResampleDoubleZ->value();
resampler->SetSamplingFactor(samplingFactor);
break;
}
case 1:
{
itk::Vector< double, 3 > newSpacing;
newSpacing[0] = m_Controls->m_ResampleDoubleX->value();
newSpacing[1] = m_Controls->m_ResampleDoubleY->value();
newSpacing[2] = m_Controls->m_ResampleDoubleZ->value();
resampler->SetNewSpacing(newSpacing);
break;
}
case 2:
{
itk::ImageRegion<3> newRegion;
newRegion.SetSize(0, m_Controls->m_ResampleIntX->value());
newRegion.SetSize(1, m_Controls->m_ResampleIntY->value());
newRegion.SetSize(2, m_Controls->m_ResampleIntZ->value());
resampler->SetNewImageSize(newRegion);
break;
}
default:
{
MITK_WARN << "Unknown resampling parameters!";
return;
}
}
QString outAdd;
switch (m_Controls->m_InterpolatorBox->currentIndex())
{
case 0:
{
resampler->SetInterpolation(ResampleFilter::Interpolate_NearestNeighbour);
outAdd = "NearestNeighbour";
break;
}
case 1:
{
resampler->SetInterpolation(ResampleFilter::Interpolate_Linear);
outAdd = "Linear";
break;
}
case 2:
{
resampler->SetInterpolation(ResampleFilter::Interpolate_BSpline);
outAdd = "BSpline";
break;
}
case 3:
{
resampler->SetInterpolation(ResampleFilter::Interpolate_WindowedSinc);
outAdd = "WindowedSinc";
break;
}
default:
{
resampler->SetInterpolation(ResampleFilter::Interpolate_NearestNeighbour);
outAdd = "NearestNeighbour";
}
}
resampler->Update();
mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( resampler->GetOutput() );
PropHelper::CopyProperties(image, newImage, false);
PropHelper::InitializeImage( newImage );
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( newImage );
QString name = node->GetName().c_str();
imageNode->SetName((name+"_resampled_"+outAdd).toStdString().c_str());
imageNode->SetVisibility(false);
GetDataStorage()->Add(imageNode, node);
}
else if( image->GetPixelType().GetNumberOfComponents() )
{
AccessFixedDimensionByItk(image, TemplatedResampleImage,3);
}
else
{
QMessageBox::warning(nullptr,"Warning", QString("Operation not supported in multi-component images") );
}
}
template < typename TPixel, unsigned int VImageDimension >
void QmitkPreprocessingView::TemplatedResampleImage( itk::Image<TPixel, VImageDimension>* itkImage)
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
itk::Vector< double, 3 > newSpacing;
itk::ImageRegion<3> newRegion;
switch (m_Controls->m_ResampleTypeBox->currentIndex())
{
case 0:
{
itk::Vector< double, 3 > sampling;
sampling[0] = m_Controls->m_ResampleDoubleX->value();
sampling[1] = m_Controls->m_ResampleDoubleY->value();
sampling[2] = m_Controls->m_ResampleDoubleZ->value();
newSpacing = itkImage->GetSpacing();
newSpacing[0] /= sampling[0];
newSpacing[1] /= sampling[1];
newSpacing[2] /= sampling[2];
newRegion = itkImage->GetLargestPossibleRegion();
newRegion.SetSize(0, newRegion.GetSize(0)*sampling[0]);
newRegion.SetSize(1, newRegion.GetSize(1)*sampling[1]);
newRegion.SetSize(2, newRegion.GetSize(2)*sampling[2]);
break;
}
case 1:
{
newSpacing[0] = m_Controls->m_ResampleDoubleX->value();
newSpacing[1] = m_Controls->m_ResampleDoubleY->value();
newSpacing[2] = m_Controls->m_ResampleDoubleZ->value();
itk::Vector< double, 3 > oldSpacing = itkImage->GetSpacing();
itk::Vector< double, 3 > sampling;
sampling[0] = oldSpacing[0]/newSpacing[0];
sampling[1] = oldSpacing[1]/newSpacing[1];
sampling[2] = oldSpacing[2]/newSpacing[2];
newRegion = itkImage->GetLargestPossibleRegion();
newRegion.SetSize(0, newRegion.GetSize(0)*sampling[0]);
newRegion.SetSize(1, newRegion.GetSize(1)*sampling[1]);
newRegion.SetSize(2, newRegion.GetSize(2)*sampling[2]);
break;
}
case 2:
{
newRegion.SetSize(0, m_Controls->m_ResampleIntX->value());
newRegion.SetSize(1, m_Controls->m_ResampleIntY->value());
newRegion.SetSize(2, m_Controls->m_ResampleIntZ->value());
itk::ImageRegion<3> oldRegion = itkImage->GetLargestPossibleRegion();
itk::Vector< double, 3 > sampling;
sampling[0] = (double)newRegion.GetSize(0)/oldRegion.GetSize(0);
sampling[1] = (double)newRegion.GetSize(1)/oldRegion.GetSize(1);
sampling[2] = (double)newRegion.GetSize(2)/oldRegion.GetSize(2);
newSpacing = itkImage->GetSpacing();
newSpacing[0] /= sampling[0];
newSpacing[1] /= sampling[1];
newSpacing[2] /= sampling[2];
break;
}
default:
{
MITK_WARN << "Unknown resampling parameters!";
return;
}
}
itk::Point<double,3> origin = itkImage->GetOrigin();
origin[0] -= itkImage->GetSpacing()[0]/2;
origin[1] -= itkImage->GetSpacing()[1]/2;
origin[2] -= itkImage->GetSpacing()[2]/2;
origin[0] += newSpacing[0]/2;
origin[1] += newSpacing[1]/2;
origin[2] += newSpacing[2]/2;
typedef itk::Image<TPixel, VImageDimension> ImageType;
typename ImageType::Pointer outImage = ImageType::New();
outImage->SetSpacing( newSpacing );
outImage->SetOrigin( origin );
outImage->SetDirection( itkImage->GetDirection() );
outImage->SetLargestPossibleRegion( newRegion );
outImage->SetBufferedRegion( newRegion );
outImage->SetRequestedRegion( newRegion );
outImage->Allocate();
typedef itk::ResampleImageFilter<ImageType, ImageType> ResampleFilter;
typename ResampleFilter::Pointer resampler = ResampleFilter::New();
resampler->SetInput(itkImage);
resampler->SetOutputParametersFromImage(outImage);
QString outAdd;
switch (m_Controls->m_InterpolatorBox->currentIndex())
{
case 0:
{
typename itk::NearestNeighborInterpolateImageFunction<ImageType>::Pointer interp
= itk::NearestNeighborInterpolateImageFunction<ImageType>::New();
resampler->SetInterpolator(interp);
outAdd = "NearestNeighbour";
break;
}
case 1:
{
typename itk::LinearInterpolateImageFunction<ImageType>::Pointer interp
= itk::LinearInterpolateImageFunction<ImageType>::New();
resampler->SetInterpolator(interp);
outAdd = "Linear";
break;
}
case 2:
{
typename itk::BSplineInterpolateImageFunction<ImageType>::Pointer interp
= itk::BSplineInterpolateImageFunction<ImageType>::New();
resampler->SetInterpolator(interp);
outAdd = "BSpline";
break;
}
case 3:
{
typename itk::WindowedSincInterpolateImageFunction<ImageType, 3>::Pointer interp
= itk::WindowedSincInterpolateImageFunction<ImageType, 3>::New();
resampler->SetInterpolator(interp);
outAdd = "WindowedSinc";
break;
}
default:
{
typename itk::NearestNeighborInterpolateImageFunction<ImageType>::Pointer interp
= itk::NearestNeighborInterpolateImageFunction<ImageType>::New();
resampler->SetInterpolator(interp);
outAdd = "NearestNeighbour";
}
}
resampler->Update();
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk( resampler->GetOutput() );
image->SetVolume( resampler->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( image );
QString name = node->GetName().c_str();
imageNode->SetName((name+"_resampled_"+outAdd).toStdString().c_str());
GetDataStorage()->Add(imageNode, node);
}
void QmitkPreprocessingView::DoApplyHeader()
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) );
bool isDti = false;
bool isOdf = false;
bool isPeak = false;
if (!isDiffusionImage)
{
if ( dynamic_cast<mitk::TensorImage*>(node->GetData()) )
isDti = true;
else if ( dynamic_cast<mitk::OdfImage*>(node->GetData()) )
isOdf = true;
else if ( dynamic_cast<mitk::PeakImage*>(node->GetData()) )
isPeak = true;
}
mitk::Image::Pointer newImage = image->Clone();
mitk::Vector3D spacing;
spacing[0] = m_Controls->m_HeaderSpacingX->value();
spacing[1] = m_Controls->m_HeaderSpacingY->value();
spacing[2] = m_Controls->m_HeaderSpacingZ->value();
newImage->GetGeometry()->SetSpacing( spacing );
mitk::Point3D origin;
origin[0] = m_Controls->m_HeaderOriginX->value();
origin[1] = m_Controls->m_HeaderOriginY->value();
origin[2] = m_Controls->m_HeaderOriginZ->value();
newImage->GetGeometry()->SetOrigin(origin);
vtkSmartPointer< vtkMatrix4x4 > matrix = vtkSmartPointer< vtkMatrix4x4 >::New();
matrix->SetElement(0,3,newImage->GetGeometry()->GetOrigin()[0]);
matrix->SetElement(1,3,newImage->GetGeometry()->GetOrigin()[1]);
matrix->SetElement(2,3,newImage->GetGeometry()->GetOrigin()[2]);
for (int r=0; r<3; r++)
{
for (int c=0; c<3; c++)
{
QTableWidgetItem* item = m_Controls->m_DirectionMatrixTable->item(r,c);
if (!item)
continue;
matrix->SetElement(r,c,item->text().toDouble());
}
}
newImage->GetGeometry()->SetIndexToWorldTransformByVtkMatrixWithoutChangingSpacing(matrix);
if ( isDiffusionImage )
{
vnl_matrix_fixed< double, 3, 3 > mf;
for (int r=0; r<3; r++)
{
for (int c=0; c<3; c++)
{
QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item(r,c);
if (!item)
continue;
mf[r][c] = item->text().toDouble();
}
}
PropHelper::SetMeasurementFrame(newImage, mf);
PropHelper::InitializeImage( newImage );
}
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
if (isOdf)
{
mitk::OdfImage::ItkOdfImageType::Pointer itk_img = mitk::OdfImage::ItkOdfImageType::New();
mitk::CastToItkImage(newImage, itk_img);
mitk::Image::Pointer odfImage = dynamic_cast<mitk::Image*>(mitk::OdfImage::New().GetPointer());
mitk::CastToMitkImage(itk_img, odfImage);
odfImage->SetVolume(itk_img->GetBufferPointer());
imageNode->SetData( odfImage );
}
else if (isDti)
{
mitk::TensorImage::ItkTensorImageType::Pointer itk_img = mitk::ImageToItkImage<mitk::TensorImage::PixelType,3>(newImage);
mitk::Image::Pointer tensorImage = dynamic_cast<mitk::Image*>(mitk::TensorImage::New().GetPointer());
mitk::CastToMitkImage(itk_img, tensorImage);
tensorImage->SetVolume(itk_img->GetBufferPointer());
imageNode->SetData( tensorImage );
}
else if (isPeak)
{
mitk::PeakImage::ItkPeakImageType::Pointer itk_img = mitk::ImageToItkImage<float,4>(newImage);
mitk::Image::Pointer peakImage = dynamic_cast<mitk::Image*>(mitk::PeakImage::New().GetPointer());
mitk::CastToMitkImage(itk_img, peakImage);
peakImage->SetVolume(itk_img->GetBufferPointer());
imageNode->SetData( peakImage );
}
else
imageNode->SetData( newImage );
QString name = node->GetName().c_str();
imageNode->SetName((name+"_newheader").toStdString().c_str());
GetDataStorage()->Add(imageNode, node);
mitk::RenderingManager::GetInstance()->InitializeViews( imageNode->GetData()->GetTimeGeometry(),
mitk::RenderingManager::REQUEST_UPDATE_ALL,
true );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkPreprocessingView::DoProjectSignal()
{
switch(m_Controls->m_ProjectionMethodBox->currentIndex())
{
case 0:
DoADCAverage();
break;
case 1:
DoAKCFit();
break;
case 2:
DoBiExpFit();
break;
default:
DoADCAverage();
}
}
void QmitkPreprocessingView::DoDwiNormalization()
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) );
if ( ! isDiffusionImage ) { return; }
auto gradientContainer = PropHelper::GetGradientContainer(image);
int b0Index = -1;
for (unsigned int i=0; i<gradientContainer->size(); i++)
{
GradientDirectionType g = gradientContainer->GetElement(i);
if (g.magnitude()<0.001)
{
b0Index = i;
break;
}
}
if (b0Index==-1) { return; }
typedef itk::DwiNormilzationFilter<short> FilterType;
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(image, itkVectorImagePointer);
FilterType::Pointer filter = FilterType::New();
filter->SetInput( itkVectorImagePointer );
filter->SetGradientDirections(PropHelper::GetGradientContainer(image));
filter->SetNewMean(m_Controls->m_NewMean->value());
filter->SetNewStdev(m_Controls->m_NewStdev->value());
UcharImageType::Pointer itkImage = nullptr;
if (m_Controls->m_NormalizationMaskBox->GetSelectedNode().IsNotNull())
{
itkImage = UcharImageType::New();
if ( dynamic_cast<mitk::Image*>(m_Controls->m_NormalizationMaskBox->GetSelectedNode()->GetData()) != nullptr )
{
mitk::CastToItkImage( dynamic_cast<mitk::Image*>(m_Controls->m_NormalizationMaskBox->GetSelectedNode()->GetData()), itkImage );
}
filter->SetMaskImage(itkImage);
}
filter->Update();
mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( filter->GetOutput() );
PropHelper::CopyProperties(image, newImage, false);
PropHelper::InitializeImage( newImage );
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( newImage );
QString name = node->GetName().c_str();
imageNode->SetName((name+"_normalized").toStdString().c_str());
GetDataStorage()->Add(imageNode, node);
}
void QmitkPreprocessingView::DoLengthCorrection()
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull())
return;
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if (image == nullptr )
return;
if (!PropHelper::IsDiffusionWeightedImage(image))
return;
typedef itk::DwiGradientLengthCorrectionFilter FilterType;
ItkDwiType::Pointer itkVectorImagePointer = PropHelper::GetItkVectorImage(image);
FilterType::Pointer filter = FilterType::New();
filter->SetRoundingValue( m_Controls->m_B_ValueMap_Rounder_SpinBox->value());
filter->SetReferenceBValue(PropHelper::GetReferenceBValue(image));
filter->SetReferenceGradientDirectionContainer(PropHelper::GetGradientContainer(image));
filter->Update();
mitk::Image::Pointer newImage = mitk::Image::New();
newImage->InitializeByItk( itkVectorImagePointer.GetPointer() );
newImage->SetImportVolume( itkVectorImagePointer->GetBufferPointer(), 0, 0, mitk::Image::CopyMemory);
itkVectorImagePointer->GetPixelContainer()->ContainerManageMemoryOff();
PropHelper::CopyProperties(image, newImage, true);
PropHelper::SetGradientContainer(newImage, filter->GetOutputGradientDirectionContainer());
PropHelper::SetReferenceBValue(newImage, filter->GetNewBValue());
PropHelper::InitializeImage( newImage );
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( newImage );
QString name = node->GetName().c_str();
imageNode->SetName((name+"_rounded").toStdString().c_str());
GetDataStorage()->Add(imageNode, node);
}
void QmitkPreprocessingView::UpdateDwiBValueMapRounder(int i)
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(node) );
if ( ! isDiffusionImage ) { return; }
UpdateBValueTableWidget(i);
UpdateGradientDetails();
}
void QmitkPreprocessingView::
CallMultishellToSingleShellFilter( itk::DWIVoxelFunctor * functor,
mitk::Image::Pointer image,
QString imageName,
mitk::DataNode* parent )
{
typedef itk::RadialMultishellToSingleshellImageFilter<DiffusionPixelType, DiffusionPixelType> FilterType;
// filter input parameter
const mitk::BValueMapProperty::BValueMap& originalShellMap = PropHelper::GetBValueMap(image);
ItkDwiType::Pointer itkVectorImagePointer = PropHelper::GetItkVectorImage(image);
ItkDwiType* vectorImage = itkVectorImagePointer.GetPointer();
const GradProp::GradientDirectionsContainerType::Pointer gradientContainer = PropHelper::GetGradientContainer(image);
const unsigned int& bValue = PropHelper::GetReferenceBValue(image);
mitk::DataNode::Pointer imageNode = 0;
// filter call
FilterType::Pointer filter = FilterType::New();
filter->SetInput(vectorImage);
filter->SetOriginalGradientDirections(gradientContainer);
filter->SetOriginalBValueMap(originalShellMap);
filter->SetOriginalBValue(bValue);
filter->SetFunctor(functor);
filter->Update();
// create new DWI image
mitk::Image::Pointer outImage = mitk::GrabItkImageMemory( filter->GetOutput() );
PropHelper::CopyProperties(image, outImage, true);
PropHelper::SetGradientContainer(outImage, filter->GetTargetGradientDirections());
PropHelper::SetReferenceBValue(outImage, m_Controls->m_targetBValueSpinBox->value());
PropHelper::InitializeImage( outImage );
imageNode = mitk::DataNode::New();
imageNode->SetData( outImage );
imageNode->SetName(imageName.toStdString().c_str());
GetDataStorage()->Add(imageNode, parent);
}
void QmitkPreprocessingView::DoBiExpFit()
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) );
if ( ! isDiffusionImage ) { return; }
itk::BiExpFitFunctor::Pointer functor = itk::BiExpFitFunctor::New();
QString name(node->GetName().c_str());
const mitk::BValueMapProperty::BValueMap& originalShellMap = PropHelper::GetBValueMap(image);
mitk::BValueMapProperty::BValueMap::const_iterator it = originalShellMap.begin();
++it;/* skip b=0*/ unsigned int s = 0; /*shell index */
vnl_vector<double> bValueList(originalShellMap.size()-1);
while( it != originalShellMap.end() ) { bValueList.put(s++,(it++)->first); }
const double targetBValue = m_Controls->m_targetBValueSpinBox->value();
functor->setListOfBValues(bValueList);
functor->setTargetBValue(targetBValue);
CallMultishellToSingleShellFilter(functor,image,name + "_BiExp", node);
}
void QmitkPreprocessingView::DoAKCFit()
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) );
if ( ! isDiffusionImage ) { return; }
itk::KurtosisFitFunctor::Pointer functor = itk::KurtosisFitFunctor::New();
QString name(node->GetName().c_str());
const mitk::BValueMapProperty::BValueMap& originalShellMap = PropHelper::GetBValueMap(image);
mitk::BValueMapProperty::BValueMap::const_iterator it = originalShellMap.begin();
++it;/* skip b=0*/ unsigned int s = 0; /*shell index */
vnl_vector<double> bValueList(originalShellMap.size()-1);
while(it != originalShellMap.end())
bValueList.put(s++,(it++)->first);
const double targetBValue = m_Controls->m_targetBValueSpinBox->value();
functor->setListOfBValues(bValueList);
functor->setTargetBValue(targetBValue);
CallMultishellToSingleShellFilter(functor,image,name + "_AKC", node);
}
void QmitkPreprocessingView::DoADCFit()
{
// later
}
void QmitkPreprocessingView::DoADCAverage()
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) );
if ( ! isDiffusionImage )
return;
itk::ADCAverageFunctor::Pointer functor = itk::ADCAverageFunctor::New();
QString name(node->GetName().c_str());
const mitk::BValueMapProperty::BValueMap &originalShellMap = PropHelper::GetBValueMap(image);
mitk::BValueMapProperty::BValueMap::const_iterator it = originalShellMap.begin();
++it;/* skip b=0*/ unsigned int s = 0; /*shell index */
vnl_vector<double> bValueList(originalShellMap.size()-1);
while(it != originalShellMap.end())
bValueList.put(s++,(it++)->first);
const double targetBValue = m_Controls->m_targetBValueSpinBox->value();
functor->setListOfBValues(bValueList);
functor->setTargetBValue(targetBValue);
CallMultishellToSingleShellFilter(functor,image,name + "_ADC", node);
}
void QmitkPreprocessingView::CleanBValueTableWidget()
{
m_Controls->m_B_ValueMap_TableWidget->clear();
m_Controls->m_B_ValueMap_TableWidget->setRowCount(1);
QStringList headerList;
headerList << "b-Value" << "Number of gradients";
m_Controls->m_B_ValueMap_TableWidget->setHorizontalHeaderLabels(headerList);
m_Controls->m_B_ValueMap_TableWidget->setItem(0,0,new QTableWidgetItem("-"));
m_Controls->m_B_ValueMap_TableWidget->setItem(0,1,new QTableWidgetItem("-"));
}
void QmitkPreprocessingView::UpdateGradientDetails()
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
bool isDiffusionImage(false);
isDiffusionImage = PropHelper::IsDiffusionWeightedImage(image);
if ( ! isDiffusionImage )
{
m_Controls->m_WorkingGradientsText->clear();
m_Controls->m_OriginalGradientsText->clear();
return;
}
auto gradientContainer = PropHelper::GetGradientContainer(image);
QString text = "";
for (unsigned int j=0; j<gradientContainer->Size(); j++)
{
auto g = gradientContainer->at(j);
g = g.normalize();
if (g[0]>=0)
text += " ";
text += QString::number(g[0]);
if (j<gradientContainer->Size()-1)
text += " ";
else
text += "\n";
}
for (unsigned int j=0; j<gradientContainer->Size(); j++)
{
auto g = gradientContainer->at(j);
g = g.normalize();
if (g[1]>=0)
text += " ";
text += QString::number(g[1]);
if (j<gradientContainer->Size()-1)
text += " ";
else
text += "\n";
}
for (unsigned int j=0; j<gradientContainer->Size(); j++)
{
auto g = gradientContainer->at(j);
g = g.normalize();
if (g[2]>=0)
text += " ";
text += QString::number(g[2]);
if (j<gradientContainer->Size()-1)
text += " ";
else
text += "\n";
}
m_Controls->m_WorkingGradientsText->setPlainText(text);
gradientContainer = PropHelper::GetOriginalGradientContainer(image);
text = "";
for (unsigned int j=0; j<gradientContainer->Size(); j++)
{
auto g = gradientContainer->at(j);
g = g.normalize();
if (g[0]>=0)
text += " ";
text += QString::number(g[0]);
if (j<gradientContainer->Size()-1)
text += " ";
else
text += "\n";
}
for (unsigned int j=0; j<gradientContainer->Size(); j++)
{
auto g = gradientContainer->at(j);
g = g.normalize();
if (g[1]>=0)
text += " ";
text += QString::number(g[1]);
if (j<gradientContainer->Size()-1)
text += " ";
else
text += "\n";
}
for (unsigned int j=0; j<gradientContainer->Size(); j++)
{
auto g = gradientContainer->at(j);
g = g.normalize();
if (g[2]>=0)
text += " ";
text += QString::number(g[2]);
if (j<gradientContainer->Size()-1)
text += " ";
else
text += "\n";
}
m_Controls->m_OriginalGradientsText->setPlainText(text);
}
void QmitkPreprocessingView::UpdateBValueTableWidget(int)
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull())
{
CleanBValueTableWidget();
return;
}
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
bool isDiffusionImage(false);
isDiffusionImage = PropHelper::IsDiffusionWeightedImage(image);
if ( ! isDiffusionImage )
{
CleanBValueTableWidget();
}
else
{
typedef mitk::BValueMapProperty::BValueMap BValueMap;
typedef mitk::BValueMapProperty::BValueMap::iterator BValueMapIterator;
BValueMapIterator it;
BValueMap roundedBValueMap = PropHelper::GetBValueMap(image);
m_Controls->m_B_ValueMap_TableWidget->clear();
m_Controls->m_B_ValueMap_TableWidget->setRowCount(roundedBValueMap.size() );
QStringList headerList;
headerList << "b-Value" << "Number of gradients";
m_Controls->m_B_ValueMap_TableWidget->setHorizontalHeaderLabels(headerList);
int i = 0 ;
for(it = roundedBValueMap.begin() ;it != roundedBValueMap.end(); it++)
{
m_Controls->m_B_ValueMap_TableWidget->setItem(i,0,new QTableWidgetItem(QString::number(it->first)));
QTableWidgetItem* item = m_Controls->m_B_ValueMap_TableWidget->item(i,0);
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
m_Controls->m_B_ValueMap_TableWidget->setItem(i,1,new QTableWidgetItem(QString::number(it->second.size())));
i++;
}
}
}
void QmitkPreprocessingView::OnSelectionChanged(berry::IWorkbenchPart::Pointer , const QList<mitk::DataNode::Pointer>& nodes)
{
(void) nodes;
this->OnImageSelectionChanged();
}
void QmitkPreprocessingView::OnImageSelectionChanged()
{
for (int r=0; r<3; r++)
for (int c=0; c<3; c++)
{
{
QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item( r, c );
delete item;
item = new QTableWidgetItem();
m_Controls->m_MeasurementFrameTable->setItem( r, c, item );
}
{
QTableWidgetItem* item = m_Controls->m_DirectionMatrixTable->item( r, c );
delete item;
item = new QTableWidgetItem();
m_Controls->m_DirectionMatrixTable->setItem( r, c, item );
}
}
bool foundImageVolume = true;
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
bool foundDwiVolume( PropHelper::IsDiffusionWeightedImage( node ) );
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
bool multiComponentVolume = (image->GetPixelType().GetNumberOfComponents() > 1);
bool threeDplusTVolume = (image->GetTimeSteps() > 1);
m_Controls->m_ButtonAverageGradients->setEnabled(foundDwiVolume);
m_Controls->m_ButtonExtractB0->setEnabled(foundDwiVolume);
m_Controls->m_CheckExtractAll->setEnabled(foundDwiVolume);
m_Controls->m_MeasurementFrameTable->setEnabled(foundDwiVolume);
m_Controls->m_ReduceGradientsButton->setEnabled(foundDwiVolume);
m_Controls->m_ShowGradientsButton->setEnabled(foundDwiVolume);
m_Controls->m_MirrorGradientToHalfSphereButton->setEnabled(foundDwiVolume);
m_Controls->m_MergeDwisButton->setEnabled(foundDwiVolume);
m_Controls->m_B_ValueMap_Rounder_SpinBox->setEnabled(foundDwiVolume);
m_Controls->m_ProjectSignalButton->setEnabled(foundDwiVolume);
m_Controls->m_CreateLengthCorrectedDwi->setEnabled(foundDwiVolume);
m_Controls->m_targetBValueSpinBox->setEnabled(foundDwiVolume);
m_Controls->m_NormalizeImageValuesButton->setEnabled(foundDwiVolume);
m_Controls->m_RemoveGradientButton->setEnabled(foundDwiVolume);
m_Controls->m_ExtractGradientButton->setEnabled(foundDwiVolume);
m_Controls->m_FlipGradientsButton->setEnabled(foundDwiVolume);
m_Controls->m_ClearRotationButton->setEnabled(foundDwiVolume);
m_Controls->m_DirectionMatrixTable->setEnabled(foundImageVolume);
m_Controls->m_ModifyHeader->setEnabled(foundImageVolume);
m_Controls->m_AlignImageBox->setEnabled(foundImageVolume);
// we do not support multi-component and 3D+t images for certain operations
bool foundSingleImageVolume = foundDwiVolume || (foundImageVolume && !(multiComponentVolume || threeDplusTVolume));
m_Controls->m_FlipAxis->setEnabled(foundSingleImageVolume);
m_Controls->m_CropImageButton->setEnabled(foundSingleImageVolume);
m_Controls->m_ExtractBrainMask->setEnabled(foundSingleImageVolume);
m_Controls->m_ResampleImageButton->setEnabled(foundSingleImageVolume);
// reset sampling frame to 1 and update all ealted components
m_Controls->m_B_ValueMap_Rounder_SpinBox->setValue(1);
UpdateBValueTableWidget(m_Controls->m_B_ValueMap_Rounder_SpinBox->value());
DoUpdateInterpolationGui(m_Controls->m_ResampleTypeBox->currentIndex());
UpdateGradientDetails();
m_Controls->m_HeaderSpacingX->setValue(image->GetGeometry()->GetSpacing()[0]);
m_Controls->m_HeaderSpacingY->setValue(image->GetGeometry()->GetSpacing()[1]);
m_Controls->m_HeaderSpacingZ->setValue(image->GetGeometry()->GetSpacing()[2]);
m_Controls->m_HeaderOriginX->setValue(image->GetGeometry()->GetOrigin()[0]);
m_Controls->m_HeaderOriginY->setValue(image->GetGeometry()->GetOrigin()[1]);
m_Controls->m_HeaderOriginZ->setValue(image->GetGeometry()->GetOrigin()[2]);
m_Controls->m_XstartBox->setMaximum(image->GetGeometry()->GetExtent(0)-1);
m_Controls->m_YstartBox->setMaximum(image->GetGeometry()->GetExtent(1)-1);
m_Controls->m_ZstartBox->setMaximum(image->GetGeometry()->GetExtent(2)-1);
m_Controls->m_XendBox->setMaximum(image->GetGeometry()->GetExtent(0)-1);
m_Controls->m_YendBox->setMaximum(image->GetGeometry()->GetExtent(1)-1);
m_Controls->m_ZendBox->setMaximum(image->GetGeometry()->GetExtent(2)-1);
for (int r=0; r<3; r++)
for (int c=0; c<3; c++)
{
// Direction matrix
QTableWidgetItem* item = m_Controls->m_DirectionMatrixTable->item( r, c );
delete item;
item = new QTableWidgetItem();
item->setTextAlignment(Qt::AlignCenter | Qt::AlignVCenter);
double val = image->GetGeometry()->GetVtkMatrix()->GetElement(r,c)/image->GetGeometry()->GetSpacing()[c];
item->setText(QString::number(val));
m_Controls->m_DirectionMatrixTable->setItem( r, c, item );
}
if (foundDwiVolume)
{
m_Controls->m_InputData->setTitle("Input Data");
vnl_matrix_fixed< double, 3, 3 > mf = PropHelper::GetMeasurementFrame(image);
for (int r=0; r<3; r++)
for (int c=0; c<3; c++)
{
// Measurement frame
QTableWidgetItem* item = m_Controls->m_MeasurementFrameTable->item( r, c );
delete item;
item = new QTableWidgetItem();
item->setTextAlignment(Qt::AlignCenter | Qt::AlignVCenter);
item->setText(QString::number(mf.get(r,c)));
m_Controls->m_MeasurementFrameTable->setItem( r, c, item );
}
//calculate target bValue for MultishellToSingleShellfilter
const mitk::BValueMapProperty::BValueMap & bValMap = PropHelper::GetBValueMap(image);
mitk::BValueMapProperty::BValueMap::const_iterator it = bValMap.begin();
unsigned int targetBVal = 0;
while(it != bValMap.end()) { targetBVal += (it++)->first; }
targetBVal /= (float)bValMap.size()-1;
m_Controls->m_targetBValueSpinBox->setValue(targetBVal);
m_Controls->m_RemoveGradientBox->setMaximum(PropHelper::GetGradientContainer(image)->Size()-1);
m_Controls->m_ExtractGradientBox->setMaximum(PropHelper::GetGradientContainer(image)->Size()-1);
}
}
void QmitkPreprocessingView::Activated()
{
}
void QmitkPreprocessingView::Deactivated()
{
OnImageSelectionChanged();
}
void QmitkPreprocessingView::Visible()
{
OnImageSelectionChanged();
}
void QmitkPreprocessingView::Hidden()
{
}
void QmitkPreprocessingView::DoClearRotationOfGradients()
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull())
return;
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if (image == nullptr)
return;
if(!PropHelper::IsDiffusionWeightedImage(image))
return;
mitk::Image::Pointer newDwi = image->Clone();
PropHelper::SetApplyMatrixToGradients(newDwi, false);
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( newDwi );
QString name = node->GetName().c_str();
imageNode->SetName( (name+"_OriginalGradients").toStdString().c_str() );
GetDataStorage()->Add( imageNode, node );
}
void QmitkPreprocessingView::DoFlipGradientDirections()
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
mitk::Image::Pointer newDwi = image->Clone();
auto gradientContainer = PropHelper::GetGradientContainer(newDwi);
for (unsigned int j=0; j<gradientContainer->Size(); j++)
{
if (m_Controls->m_FlipGradBoxX->isChecked()) { gradientContainer->at(j)[0] *= -1; }
if (m_Controls->m_FlipGradBoxY->isChecked()) { gradientContainer->at(j)[1] *= -1; }
if (m_Controls->m_FlipGradBoxZ->isChecked()) { gradientContainer->at(j)[2] *= -1; }
}
PropHelper::CopyProperties(image, newDwi, true);
PropHelper::SetGradientContainer(newDwi, gradientContainer);
PropHelper::InitializeImage( newDwi );
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( newDwi );
QString name = node->GetName().c_str();
imageNode->SetName( (name+"_GradientFlip").toStdString().c_str() );
GetDataStorage()->Add( imageNode, node );
}
void QmitkPreprocessingView::DoHalfSphereGradientDirections()
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
mitk::Image::Pointer newDwi = image->Clone();
auto gradientContainer = PropHelper::GetGradientContainer(newDwi);
for (unsigned int j=0; j<gradientContainer->Size(); j++)
{
if (gradientContainer->at(j)[0]<0) { gradientContainer->at(j) = -gradientContainer->at(j); }
}
PropHelper::CopyProperties(image, newDwi, true);
PropHelper::SetGradientContainer(newDwi, gradientContainer);
PropHelper::InitializeImage( newDwi );
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( newDwi );
QString name = node->GetName().c_str();
imageNode->SetName( (name+"_halfsphere").toStdString().c_str() );
GetDataStorage()->Add( imageNode, node );
}
void QmitkPreprocessingView::DoShowGradientDirections()
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) );
if ( !isDiffusionImage ) { return; }
int maxIndex = 0;
unsigned int maxSize = image->GetDimension(0);
if (maxSize<image->GetDimension(1))
{
maxSize = image->GetDimension(1);
maxIndex = 1;
}
if (maxSize<image->GetDimension(2))
{
maxSize = image->GetDimension(2);
maxIndex = 2;
}
mitk::Point3D origin = image->GetGeometry()->GetOrigin();
mitk::PointSet::Pointer originSet = mitk::PointSet::New();
typedef mitk::BValueMapProperty::BValueMap BValueMap;
typedef mitk::BValueMapProperty::BValueMap::iterator BValueMapIterator;
BValueMap bValMap = PropHelper::GetBValueMap(image);
auto gradientContainer = PropHelper::GetGradientContainer(image);
mitk::BaseGeometry::Pointer geometry = image->GetGeometry();
int shellCount = 1;
for(BValueMapIterator it = bValMap.begin(); it!=bValMap.end(); ++it)
{
mitk::PointSet::Pointer pointset = mitk::PointSet::New();
for (unsigned int j=0; j<it->second.size(); j++)
{
mitk::Point3D ip;
vnl_vector_fixed< double, 3 > v = gradientContainer->at(it->second[j]);
if (v.magnitude()>mitk::eps)
{
ip[0] = v[0]*maxSize*geometry->GetSpacing()[maxIndex]/2
+ origin[0]-0.5*geometry->GetSpacing()[0]
+ geometry->GetSpacing()[0]*image->GetDimension(0)/2;
ip[1] = v[1]*maxSize*geometry->GetSpacing()[maxIndex]/2
+ origin[1]-0.5*geometry->GetSpacing()[1]
+ geometry->GetSpacing()[1]*image->GetDimension(1)/2;
ip[2] = v[2]*maxSize*geometry->GetSpacing()[maxIndex]/2
+ origin[2]-0.5*geometry->GetSpacing()[2]
+ geometry->GetSpacing()[2]*image->GetDimension(2)/2;
pointset->InsertPoint(j, ip);
}
else if (originSet->IsEmpty())
{
ip[0] = v[0]*maxSize*geometry->GetSpacing()[maxIndex]/2
+ origin[0]-0.5*geometry->GetSpacing()[0]
+ geometry->GetSpacing()[0]*image->GetDimension(0)/2;
ip[1] = v[1]*maxSize*geometry->GetSpacing()[maxIndex]/2
+ origin[1]-0.5*geometry->GetSpacing()[1]
+ geometry->GetSpacing()[1]*image->GetDimension(1)/2;
ip[2] = v[2]*maxSize*geometry->GetSpacing()[maxIndex]/2
+ origin[2]-0.5*geometry->GetSpacing()[2]
+ geometry->GetSpacing()[2]*image->GetDimension(2)/2;
originSet->InsertPoint(j, ip);
}
}
if ( it->first < mitk::eps ) { continue; }
// add shell to datastorage
mitk::DataNode::Pointer newNode = mitk::DataNode::New();
newNode->SetData(pointset);
QString name = node->GetName().c_str();
name += "_Shell_";
name += QString::number( it->first );
newNode->SetName( name.toStdString().c_str() );
newNode->SetProperty( "pointsize", mitk::FloatProperty::New((float)maxSize / 50) );
int b0 = shellCount % 2;
int b1 = 0;
int b2 = 0;
if (shellCount>4) { b2 = 1; }
if (shellCount%4 >= 2) { b1 = 1; }
newNode->SetProperty("color", mitk::ColorProperty::New( b2, b1, b0 ));
GetDataStorage()->Add( newNode, node );
shellCount++;
}
// add origin to datastorage
mitk::DataNode::Pointer newNode = mitk::DataNode::New();
newNode->SetData(originSet);
QString name = node->GetName().c_str();
name += "_Origin";
newNode->SetName(name.toStdString().c_str());
newNode->SetProperty("pointsize", mitk::FloatProperty::New((float)maxSize/50));
newNode->SetProperty("color", mitk::ColorProperty::New(1,1,1));
GetDataStorage()->Add(newNode, node);
}
void QmitkPreprocessingView::DoReduceGradientDirections()
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) );
if ( !isDiffusionImage ) { return; }
typedef itk::ElectrostaticRepulsionDiffusionGradientReductionFilter<DiffusionPixelType, DiffusionPixelType> FilterType;
typedef mitk::BValueMapProperty::BValueMap BValueMap;
// GetShellSelection from GUI
BValueMap shellSlectionMap;
BValueMap originalShellMap = PropHelper::GetBValueMap(image);
std::vector<unsigned int> newNumGradientDirections;
int shellCounter = 0;
QString name = node->GetName().c_str();
for (int i=0; i<m_Controls->m_B_ValueMap_TableWidget->rowCount(); i++)
{
double BValue = m_Controls->m_B_ValueMap_TableWidget->item(i,0)->text().toDouble();
shellSlectionMap[BValue] = originalShellMap[BValue];
unsigned int num = m_Controls->m_B_ValueMap_TableWidget->item(i,1)->text().toUInt();
newNumGradientDirections.push_back(num);
name += "_";
name += QString::number(num);
shellCounter++;
}
if (newNumGradientDirections.empty()) { return; }
auto gradientContainer = PropHelper::GetGradientContainer(image);
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(image, itkVectorImagePointer);
FilterType::Pointer filter = FilterType::New();
filter->SetInput( itkVectorImagePointer );
filter->SetOriginalGradientDirections(gradientContainer);
filter->SetNumGradientDirections(newNumGradientDirections);
filter->SetOriginalBValueMap(originalShellMap);
filter->SetShellSelectionBValueMap(shellSlectionMap);
filter->SetUseFirstN(m_Controls->m_KeepFirstNBox->isChecked());
filter->Update();
mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( filter->GetOutput() );
PropHelper::CopyProperties(image, newImage, true);
PropHelper::SetGradientContainer(newImage, filter->GetGradientDirections());
PropHelper::InitializeImage(newImage);
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( newImage );
imageNode->SetName(name.toStdString().c_str());
GetDataStorage()->Add(imageNode, node);
// update the b-value widget to remove the modified number of gradients used for extraction
this->CleanBValueTableWidget();
this->UpdateBValueTableWidget(0);
this->UpdateGradientDetails();
}
void QmitkPreprocessingView::MergeDwis()
{
typedef GradProp::GradientDirectionsContainerType GradientContainerType;
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) );
if ( !isDiffusionImage ) { return; }
mitk::DataNode::Pointer node2 = m_Controls->m_MergeDwiBox->GetSelectedNode();
if (node2.IsNull()) { return; }
mitk::Image::Pointer image2 = dynamic_cast<mitk::Image*>(node2->GetData());
if ( image2 == nullptr ) { return; }
typedef itk::VectorImage<DiffusionPixelType,3> DwiImageType;
typedef std::vector< DwiImageType::Pointer > DwiImageContainerType;
typedef std::vector< GradientContainerType::Pointer > GradientListContainerType;
DwiImageContainerType imageContainer;
GradientListContainerType gradientListContainer;
std::vector< double > bValueContainer;
QString name = "";
{
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(image, itkVectorImagePointer);
imageContainer.push_back( itkVectorImagePointer );
gradientListContainer.push_back(PropHelper::GetGradientContainer(image));
bValueContainer.push_back(PropHelper::GetReferenceBValue(image));
name += node->GetName().c_str();
}
{
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(image2, itkVectorImagePointer);
imageContainer.push_back( itkVectorImagePointer );
gradientListContainer.push_back(PropHelper::GetGradientContainer(image2));
bValueContainer.push_back(PropHelper::GetReferenceBValue(image2));
name += "+";
name += node2->GetName().c_str();
}
typedef itk::MergeDiffusionImagesFilter<short> FilterType;
FilterType::Pointer filter = FilterType::New();
filter->SetImageVolumes(imageContainer);
filter->SetGradientLists(gradientListContainer);
filter->SetBValues(bValueContainer);
filter->Update();
vnl_matrix_fixed< double, 3, 3 > mf; mf.set_identity();
mitk::Image::Pointer newImage = mitk::GrabItkImageMemory( filter->GetOutput() );
PropHelper::SetGradientContainer(newImage, filter->GetOutputGradients());
PropHelper::SetMeasurementFrame(newImage, mf);
PropHelper::SetReferenceBValue(newImage, filter->GetB_Value());
PropHelper::InitializeImage( newImage );
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( newImage );
imageNode->SetName(name.toStdString().c_str());
GetDataStorage()->Add(imageNode);
}
void QmitkPreprocessingView::ExtractB0()
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) );
if ( !isDiffusionImage ) { return; }
// call the extraction withou averaging if the check-box is checked
if( this->m_Controls->m_CheckExtractAll->isChecked() )
{
DoExtractBOWithoutAveraging();
return;
}
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(image, itkVectorImagePointer);
// Extract image using found index
typedef itk::B0ImageExtractionImageFilter<short, short> FilterType;
FilterType::Pointer filter = FilterType::New();
filter->SetInput( itkVectorImagePointer );
filter->SetDirections(PropHelper::GetGradientContainer(image));
filter->Update();
mitk::Image::Pointer mitkImage = mitk::Image::New();
mitkImage->InitializeByItk( filter->GetOutput() );
mitkImage->SetVolume( filter->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer newNode=mitk::DataNode::New();
newNode->SetData( mitkImage );
newNode->SetProperty( "name", mitk::StringProperty::New(node->GetName() + "_B0"));
GetDataStorage()->Add(newNode, node);
}
void QmitkPreprocessingView::DoExtractBOWithoutAveraging()
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) );
if ( !isDiffusionImage ) { return; }
// typedefs
typedef itk::B0ImageExtractionToSeparateImageFilter< short, short> FilterType;
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(image, itkVectorImagePointer);
// Extract image using found index
FilterType::Pointer filter = FilterType::New();
filter->SetInput( itkVectorImagePointer );
filter->SetDirections(PropHelper::GetGradientContainer(image));
filter->Update();
mitk::Image::Pointer mitkImage = mitk::Image::New();
mitkImage->InitializeByItk( filter->GetOutput() );
mitkImage->SetImportChannel( filter->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer newNode=mitk::DataNode::New();
newNode->SetData( mitkImage );
newNode->SetProperty( "name", mitk::StringProperty::New(node->GetName() + "_B0_ALL"));
GetDataStorage()->Add(newNode, node);
/*A reinitialization is needed to access the time channels via the ImageNavigationController
The Global-Geometry can not recognize the time channel without a re-init.
(for a new selection in datamanger a automatically updated of the Global-Geometry should be done
- if it contains the time channel)*/
mitk::RenderingManager::GetInstance()->InitializeViews( newNode->GetData()->GetTimeGeometry(),
mitk::RenderingManager::REQUEST_UPDATE_ALL,
true);
}
void QmitkPreprocessingView::AverageGradients()
{
mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode();
if (node.IsNull()) { return; }
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
if ( image == nullptr ) { return; }
bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) );
if ( !isDiffusionImage )
return;
mitk::Image::Pointer newDwi = image->Clone();
PropHelper::AverageRedundantGradients(newDwi, m_Controls->m_Blur->value());
PropHelper::InitializeImage(newDwi);
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( newDwi );
QString name = node->GetName().c_str();
imageNode->SetName((name+"_averaged").toStdString().c_str());
GetDataStorage()->Add(imageNode, node);
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingView.h
index 814d39a..90f462f 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingView.h
@@ -1,159 +1,159 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _QMITKPREPROCESSINGVIEW_H_INCLUDED
#define _QMITKPREPROCESSINGVIEW_H_INCLUDED
#include <QmitkAbstractView.h>
#include <mitkILifecycleAwarePart.h>
#include "ui_QmitkPreprocessingViewControls.h"
// st includes
#include <string>
// itk includes
#include <itkImage.h>
#include <itkVectorImage.h>
// mitk includes
#include <mitkImage.h>
#include "itkDWIVoxelFunctor.h"
#include <mitkDiffusionPropertyHelper.h>
#include <vtkMatrix4x4.h>
#include <vtkSmartPointer.h>
#include <mitkPeakImage.h>
#include <mitkImageToItk.h>
typedef short DiffusionPixelType;
struct PrpSelListener;
/*!
* \ingroup org_mitk_gui_qt_preprocessing_internal
*
* \brief Viewing and modifying diffusion weighted images (gradient reduction, resampling, b-value projection, ...)
*
*/
class QmitkPreprocessingView : public QmitkAbstractView, public mitk::ILifecycleAwarePart
{
friend struct PrpSelListener;
// this is needed for all Qt objects that should have a MOC object (everything that derives from QObject)
Q_OBJECT
public:
static const std::string VIEW_ID;
typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType;
typedef itk::VectorImage< short, 3 > ItkDwiType;
typedef itk::Image< unsigned char, 3 > UcharImageType;
typedef itk::Image< double, 3 > ItkDoubleImageType;
typedef mitk::DiffusionPropertyHelper PropHelper;
typedef mitk::GradientDirectionsProperty GradProp;
QmitkPreprocessingView();
virtual ~QmitkPreprocessingView();
virtual void CreateQtPartControl(QWidget *parent) override;
/// \brief Creation of the connections of main and control widget
virtual void CreateConnections();
virtual void Activated() override;
virtual void Deactivated() override;
virtual void Visible() override;
virtual void Hidden() override;
///
/// Sets the focus to an internal widget.
///
virtual void SetFocus() override;
static const int nrconvkernels;
protected slots:
void AverageGradients();
void ExtractB0();
void MergeDwis();
void DoApplyHeader();
void DoReduceGradientDirections();
void DoShowGradientDirections();
void DoHalfSphereGradientDirections();
void UpdateDwiBValueMapRounder(int i);
void DoLengthCorrection();
void DoDwiNormalization();
void DoProjectSignal();
void DoExtractBrainMask();
void DoResampleImage();
void DoCropImage();
void DoUpdateInterpolationGui(int i);
void DoRemoveGradient();
void DoExtractGradient();
void DoFlipAxis();
void OnImageSelectionChanged();
void DoFlipGradientDirections();
void DoClearRotationOfGradients();
void DoAlignImages();
protected:
void DoADCFit();
void DoAKCFit();
void DoBiExpFit();
void DoADCAverage();
template < typename TPixel, unsigned int VImageDimension >
void TemplatedFlipAxis( itk::Image<TPixel, VImageDimension>* itkImage);
template < typename TPixel, unsigned int VImageDimension >
void TemplatedCropImage( itk::Image<TPixel, VImageDimension>* itkImage);
template < typename TPixel, unsigned int VImageDimension >
void TemplatedResampleImage( itk::Image<TPixel, VImageDimension>* itkImage);
/** Called by ExtractB0 if check-box activated, extracts all b0 images without averaging */
void DoExtractBOWithoutAveraging();
void UpdateBValueTableWidget(int);
void UpdateGradientDetails();
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
Ui::QmitkPreprocessingViewControls* m_Controls;
void SetDefaultNodeProperties(mitk::DataNode::Pointer node, std::string name);
void CallMultishellToSingleShellFilter( itk::DWIVoxelFunctor * functor,
mitk::Image::Pointer ImPtr, QString imageName,
mitk::DataNode* parent );
void CleanBValueTableWidget();
};
#endif // _QMITKPREPROCESSINGVIEW_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/mitkPluginActivator.cpp
index 287318c..248f386 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/mitkPluginActivator.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/mitkPluginActivator.cpp
@@ -1,44 +1,44 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPluginActivator.h"
#include "src/internal/QmitkPreprocessingView.h"
#include "src/internal/QmitkDwiPreprocessingPerspective.h"
#include <usModuleInitialization.h>
ctkPluginContext* mitk::PluginActivator::m_Context = nullptr;
US_INITIALIZE_MODULE
ctkPluginContext* mitk::PluginActivator::GetContext()
{
return m_Context;
}
void mitk::PluginActivator::start(ctkPluginContext* context)
{
BERRY_REGISTER_EXTENSION_CLASS(QmitkDwiPreprocessingPerspective, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkPreprocessingView, context)
m_Context = context;
}
void mitk::PluginActivator::stop(ctkPluginContext* context)
{
Q_UNUSED(context)
m_Context = nullptr;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/mitkPluginActivator.h
index 975d65b..58e583a 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/mitkPluginActivator.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/mitkPluginActivator.h
@@ -1,40 +1,40 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKPLUGINACTIVATOR_H
#define MITKPLUGINACTIVATOR_H
#include <ctkPluginActivator.h>
namespace mitk
{
class PluginActivator : public QObject, public ctkPluginActivator
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.mitk.gui.qt.diffusionimaging.preprocessing")
Q_INTERFACES(ctkPluginActivator)
public:
static ctkPluginContext* GetContext();
void start(ctkPluginContext* context) override;
void stop(ctkPluginContext* context) override;
private:
static ctkPluginContext* m_Context;
};
}
#endif
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkBrainExtractionView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkBrainExtractionView.cpp
index 5b49ff0..5fcd486 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkBrainExtractionView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkBrainExtractionView.cpp
@@ -1,253 +1,253 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
//misc
#define _USE_MATH_DEFINES
#include <math.h>
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// Qmitk
#include "QmitkBrainExtractionView.h"
// MITK
#include <mitkNodePredicateDataType.h>
// Qt
#include <QMessageBox>
#include <QFileDialog>
#include <QDir>
#include <QDirIterator>
#include <QTimer>
#include <mitkNodePredicateDimension.h>
#include <mitkNodePredicateAnd.h>
#include <mitkIOUtil.h>
#include <mitkIPythonService.h>
#include <itkResampleImageFilter.h>
#include <mitkImageCast.h>
#include <itkBSplineInterpolateImageFunction.h>
#include <itkLinearInterpolateImageFunction.h>
#include <itkThresholdImageFilter.h>
#include <itksys/SystemTools.hxx>
#include <itkB0ImageExtractionToSeparateImageFilter.h>
#include <usGetModuleContext.h>
#include <usModuleContext.h>
#include <usModule.h>
#include <usModuleResource.h>
#include <usModuleResourceStream.h>
#include <boost/algorithm/string.hpp>
#include <BetData.h>
#define _USE_MATH_DEFINES
#include <math.h>
typedef itksys::SystemTools ist;
const std::string QmitkBrainExtractionView::VIEW_ID = "org.mitk.views.brainextraction";
QmitkBrainExtractionView::QmitkBrainExtractionView()
: QmitkAbstractView()
, m_Controls( nullptr )
, m_DiffusionImage( nullptr )
{
}
// Destructor
QmitkBrainExtractionView::~QmitkBrainExtractionView()
{
}
void QmitkBrainExtractionView::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::QmitkBrainExtractionViewControls;
m_Controls->setupUi( parent );
connect( m_Controls->m_ImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGUI()) );
connect( m_Controls->m_StartButton, SIGNAL(clicked()), this, SLOT(StartBrainExtraction()) );
this->m_Parent = parent;
m_Controls->m_ImageBox->SetDataStorage(this->GetDataStorage());
mitk::NodePredicateDimension::Pointer dimPred = mitk::NodePredicateDimension::New(3);
mitk::TNodePredicateDataType<mitk::Image>::Pointer isImagePredicate = mitk::TNodePredicateDataType<mitk::Image>::New();
m_Controls->m_ImageBox->SetPredicate(isImagePredicate);
UpdateGUI();
}
}
void QmitkBrainExtractionView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList<mitk::DataNode::Pointer>& )
{
}
void QmitkBrainExtractionView::UpdateGUI()
{
if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull())
m_Controls->m_StartButton->setEnabled(true);
else
m_Controls->m_StartButton->setEnabled(false);
}
void QmitkBrainExtractionView::SetFocus()
{
UpdateGUI();
m_Controls->m_StartButton->setFocus();
}
std::string QmitkBrainExtractionView::GetPythonFile(std::string filename)
{
std::string out = "";
std::string exec_dir = QCoreApplication::applicationDirPath().toStdString();
for (auto dir : mitk::bet::relative_search_dirs)
{
if ( ist::FileExists( ist::GetCurrentWorkingDirectory() + dir + filename) )
{
out = ist::GetCurrentWorkingDirectory() + dir + filename;
return out;
}
if ( ist::FileExists( exec_dir + dir + filename) )
{
out = exec_dir + dir + filename;
return out;
}
}
for (auto dir : mitk::bet::absolute_search_dirs)
{
if ( ist::FileExists( dir + filename) )
{
out = dir + filename;
return out;
}
}
return out;
}
void QmitkBrainExtractionView::StartBrainExtraction()
{
mitk::DataNode::Pointer node = m_Controls->m_ImageBox->GetSelectedNode();
mitk::Image::Pointer mitk_image = dynamic_cast<mitk::Image*>(node->GetData());
bool missing_file = false;
std::string missing_file_string = "";
if ( GetPythonFile("run_mitk.py").empty() )
{
missing_file_string += "Brain extraction script file missing: run_mitk.py\n\n";
missing_file = true;
}
if ( GetPythonFile("model_final.model").empty() )
{
missing_file_string += "Brain extraction model file missing: model_final.model\n\n";
missing_file = true;
}
if ( GetPythonFile("basic_config_just_like_braintumor.py").empty() )
{
missing_file_string += "Config file missing: basic_config_just_like_braintumor.py\n\n";
missing_file = true;
}
if (missing_file)
{
QMessageBox::warning(nullptr, "Error", (missing_file_string).c_str(), QMessageBox::Ok);
return;
}
try
{
us::ModuleContext* context = us::GetModuleContext();
us::ServiceReference<mitk::IPythonService> m_PythonServiceRef = context->GetServiceReference<mitk::IPythonService>();
mitk::IPythonService* m_PythonService = dynamic_cast<mitk::IPythonService*> ( context->GetService<mitk::IPythonService>(m_PythonServiceRef) );
mitk::IPythonService::ForceLoadModule();
// extend python search path
m_PythonService->AddAbsoluteSearchDirs(mitk::bet::absolute_search_dirs);
m_PythonService->AddRelativeSearchDirs(mitk::bet::relative_search_dirs);
// legacy (can be romved when BetData is updated accordingly)
m_PythonService->Execute("paths=list()");
// set input files (model and config)
m_PythonService->Execute("model_file=\""+GetPythonFile("model_final.model")+"\"");
m_PythonService->Execute("config_file=\""+GetPythonFile("basic_config_just_like_braintumor.py")+"\"");
// copy input image to python
m_PythonService->CopyToPythonAsSimpleItkImage( mitk_image, "in_image");
// run segmentation script
m_PythonService->ExecuteScript( GetPythonFile("run_mitk.py") );
// clean up after running script (better way than deleting individual variables?)
if(m_PythonService->DoesVariableExist("in_image"))
m_PythonService->Execute("del in_image");
// 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;
}
// get output images and add to datastorage
std::string output_variables = m_PythonService->GetVariable("output_variables");
std::vector<std::string> outputs;
boost::split(outputs, output_variables, boost::is_any_of(","));
std::string output_types = m_PythonService->GetVariable("output_types");
std::vector<std::string> types;
boost::split(types, output_types, boost::is_any_of(","));
for (unsigned int i=0; i<outputs.size(); ++i)
{
if (m_PythonService->DoesVariableExist(outputs.at(i)))
{
mitk::Image::Pointer image = m_PythonService->CopySimpleItkImageFromPython(outputs.at(i));
if(types.at(i)=="input" && mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(mitk_image))
{
mitk::DiffusionPropertyHelper::CopyProperties(mitk_image, image, true);
mitk::DiffusionPropertyHelper::InitializeImage(image);
}
mitk::DataNode::Pointer corrected_node = mitk::DataNode::New();
corrected_node->SetData( image );
std::string name = node->GetName();
name += "_";
name += outputs.at(i);
corrected_node->SetName(name);
GetDataStorage()->Add(corrected_node, node);
m_PythonService->Execute("del " + outputs.at(i));
mitk::RenderingManager::GetInstance()->InitializeViews( corrected_node->GetData()->GetTimeGeometry(),
mitk::RenderingManager::REQUEST_UPDATE_ALL,
true);
}
}
}
catch(...)
{
QMessageBox::warning(nullptr, "Error", "File could not be processed.\nIs pytorch installed on your system?\nDoes your script use the correct input and output variable names (in: in_image & model, out: brain_mask & brain_extracted)?", QMessageBox::Ok);
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkBrainExtractionView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkBrainExtractionView.h
index bdab3c6..439b97c 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkBrainExtractionView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkBrainExtractionView.h
@@ -1,77 +1,77 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <berryISelectionListener.h>
#include <berryIStructuredSelection.h>
#include <QmitkAbstractView.h>
#include "ui_QmitkBrainExtractionViewControls.h"
#include <mitkImage.h>
#include <mitkDiffusionPropertyHelper.h>
/*!
\brief
*/
class QmitkBrainExtractionView : public QmitkAbstractView
{
// 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;
typedef itk::VectorImage< short, 3 > ItkDwiType;
typedef mitk::GradientDirectionsProperty GradProp;
QmitkBrainExtractionView();
virtual ~QmitkBrainExtractionView();
virtual void CreateQtPartControl(QWidget *parent) override;
void SetFocus() override;
protected slots:
void StartBrainExtraction();
void UpdateGUI(); ///< update button activity etc. dpending on current datamanager selection
std::string GetPythonFile(std::string filename);
protected:
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
Ui::QmitkBrainExtractionViewControls* m_Controls;
mitk::Image::Pointer m_DiffusionImage;
std::vector< mitk::DataNode::Pointer > m_SelectedDiffusionNodes;
private:
void UpdateRegistrationStatus(); ///< update textual status display of the Registration process
// the Qt parent of our GUI (NOT of this object)
QWidget* m_Parent;
};
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkDipyReconstructionsView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkDipyReconstructionsView.cpp
index c9cfb14..6795a40 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkDipyReconstructionsView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkDipyReconstructionsView.cpp
@@ -1,410 +1,410 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// Qmitk
#include "QmitkDipyReconstructionsView.h"
#include <mitkNodePredicateIsDWI.h>
#include <mitkIPythonService.h>
#include <boost/lexical_cast.hpp>
#include <QFile>
#include <QMessageBox>
#include <usModuleContext.h>
#include <usGetModuleContext.h>
#include <mitkDiffusionPropertyHelper.h>
#include <mitkOdfImage.h>
#include <mitkShImage.h>
#include <mitkImageCast.h>
#include <itkVectorImageToFourDImageFilter.h>
#include <mitkPeakImage.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateDataType.h>
#include <mitkNodePredicateProperty.h>
#include <mitkNodePredicateDimension.h>
#include <itkShCoefficientImageImporter.h>
const std::string QmitkDipyReconstructionsView::VIEW_ID = "org.mitk.views.dipyreconstruction";
QmitkDipyReconstructionsView::QmitkDipyReconstructionsView()
: QmitkAbstractView()
, m_Controls( 0 )
{
}
// Destructor
QmitkDipyReconstructionsView::~QmitkDipyReconstructionsView()
{
}
void QmitkDipyReconstructionsView::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::QmitkDipyReconstructionsViewControls;
m_Controls->setupUi( parent );
connect( m_Controls->m_ImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGUI()) );
connect( m_Controls->m_StartButton, SIGNAL(clicked()), this, SLOT(StartFit()) );
connect( m_Controls->m_ModelBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGUI()) );
this->m_Parent = parent;
m_Controls->m_ImageBox->SetDataStorage(this->GetDataStorage());
mitk::NodePredicateIsDWI::Pointer isDwi = mitk::NodePredicateIsDWI::New();
m_Controls->m_ImageBox->SetPredicate( isDwi );
mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true));
mitk::TNodePredicateDataType<mitk::Image>::Pointer isImagePredicate = mitk::TNodePredicateDataType<mitk::Image>::New();
mitk::NodePredicateAnd::Pointer isBinary3dImage = mitk::NodePredicateAnd::New( mitk::NodePredicateAnd::New( isImagePredicate, isBinaryPredicate ), mitk::NodePredicateDimension::New(3));
m_Controls->m_MaskBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_MaskBox->SetPredicate( isBinary3dImage );
m_Controls->m_MaskBox->SetZeroEntryText("--");
UpdateGUI();
}
}
void QmitkDipyReconstructionsView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList<mitk::DataNode::Pointer>& )
{
}
void QmitkDipyReconstructionsView::UpdateGUI()
{
if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull())
m_Controls->m_StartButton->setEnabled(true);
else
m_Controls->m_StartButton->setEnabled(false);
m_Controls->m_ShoreBox->setVisible(false);
m_Controls->m_SfmBox->setVisible(false);
m_Controls->m_CsdBox->setVisible(false);
m_Controls->m_CsaBox->setVisible(false);
m_Controls->m_OpdtBox->setVisible(false);
switch(m_Controls->m_ModelBox->currentIndex())
{
case 0:
{
m_Controls->m_ShoreBox->setVisible(true);
break;
}
case 1:
{
m_Controls->m_SfmBox->setVisible(true);
break;
}
case 2:
{
m_Controls->m_CsdBox->setVisible(true);
break;
}
case 3:
{
m_Controls->m_CsaBox->setVisible(true);
break;
}
case 4:
{
m_Controls->m_OpdtBox->setVisible(true);
break;
}
}
}
void QmitkDipyReconstructionsView::SetFocus()
{
UpdateGUI();
m_Controls->m_StartButton->setFocus();
}
void QmitkDipyReconstructionsView::StartFit()
{
mitk::DataNode::Pointer node = m_Controls->m_ImageBox->GetSelectedNode();
mitk::Image::Pointer input_image = dynamic_cast<mitk::Image*>(node->GetData());
// get python script as string
QString data;
QString fileName(":/QmitkDiffusionPython/dipy_reconstructions.py");
QFile file(fileName);
if(!file.open(QIODevice::ReadOnly)) {
MITK_INFO << "Dipy reconstruction code not found!";
}
else
{
data = file.readAll();
}
file.close();
// get bvals and bvecs
std::locale::global(std::locale::classic());
std::string bvals = "[";
std::string bvecs = "[";
auto gcont = mitk::DiffusionPropertyHelper::GetGradientContainer(input_image);
auto bvaluevector = mitk::DiffusionPropertyHelper::GetBValueVector(input_image);
int b0_count = 0;
for (unsigned int i=0; i<gcont->Size(); ++i)
{
bvals += boost::lexical_cast<std::string>(bvaluevector.at(i));
if (bvaluevector.at(i)==0)
b0_count++;
auto g = gcont->GetElement(i);
if (g.two_norm()>0.000001)
g /= g.two_norm();
bvecs += "[" + boost::lexical_cast<std::string>(g[0]) + "," + boost::lexical_cast<std::string>(g[1]) + "," + boost::lexical_cast<std::string>(g[2]) + "]";
if (i<gcont->Size()-1)
{
bvals += ", ";
bvecs += ", ";
}
}
bvals += "]";
bvecs += "]";
if (b0_count==0)
{
QMessageBox::warning(nullptr, "Error", "No b=0 volume found. Do your b-values need rounding? Use the Preprocessing View for rounding b-values,", QMessageBox::Ok);
return;
}
us::ModuleContext* context = us::GetModuleContext();
us::ServiceReference<mitk::IPythonService> m_PythonServiceRef = context->GetServiceReference<mitk::IPythonService>();
mitk::IPythonService* m_PythonService = dynamic_cast<mitk::IPythonService*> ( context->GetService<mitk::IPythonService>(m_PythonServiceRef) );
mitk::IPythonService::ForceLoadModule();
m_PythonService->CopyToPythonAsSimpleItkImage( input_image, "in_image");
m_PythonService->Execute("mask=None");
if (m_Controls->m_MaskBox->GetSelectedNode().IsNotNull())
{
auto mitk_mask = dynamic_cast<mitk::Image*>(m_Controls->m_MaskBox->GetSelectedNode()->GetData());
if (mitk_mask->GetLargestPossibleRegion().GetSize()==input_image->GetLargestPossibleRegion().GetSize())
m_PythonService->CopyToPythonAsSimpleItkImage( mitk_mask, "mask");
else
MITK_INFO << "Mask image not used. Does not match data size: " << mitk_mask->GetLargestPossibleRegion().GetSize() << " vs. "
<< input_image->GetLargestPossibleRegion().GetSize();
}
m_PythonService->Execute("normalize_peaks=False");
if (m_Controls->m_NormalizePeaks->isChecked())
m_PythonService->Execute("normalize_peaks=True");
std::string model = "3D-SHORE";
int sh_order = 0;
switch(m_Controls->m_ModelBox->currentIndex())
{
case 0:
{
model = "3D-SHORE";
m_PythonService->Execute("radial_order=" + boost::lexical_cast<std::string>(m_Controls->m_RadialOrder->value()));
m_PythonService->Execute("zeta=" + boost::lexical_cast<std::string>(m_Controls->m_Zeta->value()));
m_PythonService->Execute("lambdaN=" + m_Controls->m_LambdaN->text().toStdString());
m_PythonService->Execute("lambdaL=" + m_Controls->m_LambdaL->text().toStdString());
break;
}
case 1:
{
model = "SFM";
m_PythonService->Execute("fa_thr=" + boost::lexical_cast<std::string>(m_Controls->m_FaThresholdSfm->value()));
break;
}
case 2:
{
model = "CSD";
sh_order = m_Controls->m_ShOrderCsd->value();
m_PythonService->Execute("sh_order=" + boost::lexical_cast<std::string>(sh_order));
m_PythonService->Execute("fa_thr=" + boost::lexical_cast<std::string>(m_Controls->m_FaThresholdCsd->value()));
break;
}
case 3:
{
model = "CSA-QBALL";
sh_order = m_Controls->m_ShOrderCsa->value();
m_PythonService->Execute("sh_order=" + boost::lexical_cast<std::string>(sh_order));
m_PythonService->Execute("smooth=" + boost::lexical_cast<std::string>(m_Controls->m_LambdaCsa->value()));
break;
}
case 4:
{
model = "Opdt";
sh_order = m_Controls->m_ShOrderOpdt->value();
m_PythonService->Execute("sh_order=" + boost::lexical_cast<std::string>(sh_order));
m_PythonService->Execute("smooth=" + boost::lexical_cast<std::string>(m_Controls->m_LambdaOpdt->value()));
break;
}
}
m_PythonService->Execute("model_type='"+model+"'");
m_PythonService->Execute("num_peaks=0");
if (m_Controls->m_DoCalculatePeaks->isChecked())
{
m_PythonService->Execute("num_peaks=" + boost::lexical_cast<std::string>(m_Controls->m_NumPeaks->value()));
m_PythonService->Execute("min_separation_angle=" + boost::lexical_cast<std::string>(m_Controls->m_SepAngle->value()));
m_PythonService->Execute("relative_peak_threshold=" + boost::lexical_cast<std::string>(m_Controls->m_RelativeThreshold->value()));
}
m_PythonService->Execute("data=False");
m_PythonService->Execute("bvals=" + bvals);
m_PythonService->Execute("bvecs=" + bvecs);
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");
// 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;
}
if (m_PythonService->DoesVariableExist("odf_image"))
{
mitk::OdfImage::ItkOdfImageType::Pointer itkImg = mitk::OdfImage::ItkOdfImageType::New();
mitk::Image::Pointer out_image = m_PythonService->CopySimpleItkImageFromPython("odf_image");
mitk::CastToItkImage(out_image, itkImg);
mitk::OdfImage::Pointer image = mitk::OdfImage::New();
image->InitializeByItk( itkImg.GetPointer() );
image->SetVolume( itkImg->GetBufferPointer() );
mitk::DataNode::Pointer odfs = mitk::DataNode::New();
odfs->SetData( image );
QString name(node->GetName().c_str());
odfs->SetName(name.toStdString() + "_" + model);
GetDataStorage()->Add(odfs, node);
m_PythonService->Execute("del odf_image");
}
else if (m_PythonService->DoesVariableExist("sh_image"))
{
mitk::Image::Pointer out_image = m_PythonService->CopySimpleItkImageFromPython("sh_image");
itk::VectorImage<float>::Pointer vectorImage = itk::VectorImage<float>::New();
mitk::CastToItkImage(out_image, vectorImage);
itk::VectorImageToFourDImageFilter< float >::Pointer converter = itk::VectorImageToFourDImageFilter< float >::New();
converter->SetInputImage(vectorImage);
converter->GenerateData();
mitk::ShImage::ShOnDiskType::Pointer itkImg = converter->GetOutputImage();
mitk::ShImage::Pointer shImage = mitk::ShImage::New();
shImage->SetShConvention(mitk::ShImage::SH_CONVENTION::FSL);
mitk::Image::Pointer mitkImage = dynamic_cast<mitk::Image*>(shImage.GetPointer());
switch(sh_order)
{
case 2:
{
typedef itk::ShCoefficientImageImporter< float, 2 > ImporterType;
typename ImporterType::Pointer importer = ImporterType::New();
importer->SetInputImage(itkImg);
importer->GenerateData();
mitk::CastToMitkImage(importer->GetCoefficientImage(), mitkImage);
mitkImage->SetVolume(importer->GetCoefficientImage()->GetBufferPointer());
break;
}
case 4:
{
typedef itk::ShCoefficientImageImporter< float, 4 > ImporterType;
typename ImporterType::Pointer importer = ImporterType::New();
importer->SetInputImage(itkImg);
importer->GenerateData();
mitk::CastToMitkImage(importer->GetCoefficientImage(), mitkImage);
mitkImage->SetVolume(importer->GetCoefficientImage()->GetBufferPointer());
break;
}
case 6:
{
typedef itk::ShCoefficientImageImporter< float, 6 > ImporterType;
typename ImporterType::Pointer importer = ImporterType::New();
importer->SetInputImage(itkImg);
importer->GenerateData();
mitk::CastToMitkImage(importer->GetCoefficientImage(), mitkImage);
mitkImage->SetVolume(importer->GetCoefficientImage()->GetBufferPointer());
break;
}
case 8:
{
typedef itk::ShCoefficientImageImporter< float, 8 > ImporterType;
typename ImporterType::Pointer importer = ImporterType::New();
importer->SetInputImage(itkImg);
importer->GenerateData();
mitk::CastToMitkImage(importer->GetCoefficientImage(), mitkImage);
mitkImage->SetVolume(importer->GetCoefficientImage()->GetBufferPointer());
break;
}
case 10:
{
typedef itk::ShCoefficientImageImporter< float, 10 > ImporterType;
typename ImporterType::Pointer importer = ImporterType::New();
importer->SetInputImage(itkImg);
importer->GenerateData();
mitk::CastToMitkImage(importer->GetCoefficientImage(), mitkImage);
mitkImage->SetVolume(importer->GetCoefficientImage()->GetBufferPointer());
break;
}
case 12:
{
typedef itk::ShCoefficientImageImporter< float, 12 > ImporterType;
typename ImporterType::Pointer importer = ImporterType::New();
importer->SetInputImage(itkImg);
importer->GenerateData();
mitk::CastToMitkImage(importer->GetCoefficientImage(), mitkImage);
mitkImage->SetVolume(importer->GetCoefficientImage()->GetBufferPointer());
break;
}
default:
mitkThrow() << "SH order not supported";
}
mitk::DataNode::Pointer shNode = mitk::DataNode::New();
shNode->SetData( mitkImage );
QString name(node->GetName().c_str());
shNode->SetName(name.toStdString() + "_" + model);
GetDataStorage()->Add(shNode, node);
m_PythonService->Execute("del sh_image");
}
if (m_Controls->m_DoCalculatePeaks->isChecked() && m_PythonService->DoesVariableExist("peak_image"))
{
mitk::Image::Pointer out_image = m_PythonService->CopySimpleItkImageFromPython("peak_image");
itk::VectorImage<float>::Pointer vectorImage = itk::VectorImage<float>::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::Image*>(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 );
seg->SetName("Peaks");
GetDataStorage()->Add(seg, node);
m_PythonService->Execute("del peak_image");
}
mitk::IPythonService::ForceLoadModule(); // just included here because it flushes the python stdout
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkDipyReconstructionsView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkDipyReconstructionsView.h
index c3e5fc7..666238d 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkDipyReconstructionsView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkDipyReconstructionsView.h
@@ -1,72 +1,72 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <berryISelectionListener.h>
#include <berryIStructuredSelection.h>
#include <QmitkAbstractView.h>
#include "ui_QmitkDipyReconstructionsViewControls.h"
#include <mitkImage.h>
#include <mitkDiffusionPropertyHelper.h>
#include <QmitkDataStorageComboBoxWithSelectNone.h>
/*!
\brief
*/
class QmitkDipyReconstructionsView : public QmitkAbstractView
{
// 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;
typedef itk::VectorImage< short, 3 > ItkDwiType;
typedef mitk::GradientDirectionsProperty GradProp;
QmitkDipyReconstructionsView();
virtual ~QmitkDipyReconstructionsView();
virtual void CreateQtPartControl(QWidget *parent) override;
void SetFocus() override;
protected slots:
void StartFit();
void UpdateGUI(); ///< update button activity etc. dpending on current datamanager selection
protected:
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
Ui::QmitkDipyReconstructionsViewControls* m_Controls;
private:
void UpdateRegistrationStatus(); ///< update textual status display of the Registration process
// the Qt parent of our GUI (NOT of this object)
QWidget* m_Parent;
};
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 1083013..c92337f 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,359 +1,359 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// Qmitk
#include "QmitkTractSegView.h"
#include <mitkNodePredicateDataType.h>
#include <mitkIPythonService.h>
#include <boost/lexical_cast.hpp>
#include <QFile>
#include <QMessageBox>
#include <usModuleContext.h>
#include <usGetModuleContext.h>
#include <mitkPeakImage.h>
#include <mitkImageCast.h>
#include <mitkImageToItk.h>
#include <mitkITKImageImport.h>
#include <itkFourDToVectorImageFilter.h>
#include <itkVectorImageToFourDImageFilter.h>
#include <itkSplitVectorImageFilter.h>
#include <itkFlipPeaksFilter.h>
#include <mitkLookupTable.h>
#include <mitkLookupTableProperty.h>
#include <mitkLevelWindow.h>
#include <mitkLevelWindowProperty.h>
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_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<mitk::DataNode::Pointer>& )
{
}
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<mitk::Image*>(node->GetData());
// get python script as string
QString data;
QString fileName(":/QmitkDiffusionPython/tractseg.py");
QFile file(fileName);
if(!file.open(QIODevice::ReadOnly)) {
qDebug()<<"filenot opened"<<endl;
}
else
{
qDebug()<<"file opened"<<endl;
data = file.readAll();
}
file.close();
if (data.size()==0)
mitkThrow() << fileName << " could not be read!";
us::ModuleContext* context = us::GetModuleContext();
us::ServiceReference<mitk::IPythonService> m_PythonServiceRef = context->GetServiceReference<mitk::IPythonService>();
mitk::IPythonService* m_PythonService = dynamic_cast<mitk::IPythonService*> ( context->GetService<mitk::IPythonService>(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(false);
flipper->SetFlipZ(true);
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->CopyToPythonAsSimpleItkImage( mitk_vec_img, "in_image");
m_PythonService->Execute("sx=" + boost::lexical_cast<std::string>(itk_peaks->GetLargestPossibleRegion().GetSize()[0]));
m_PythonService->Execute("sy=" + boost::lexical_cast<std::string>(itk_peaks->GetLargestPossibleRegion().GetSize()[1]));
m_PythonService->Execute("sz=" + boost::lexical_cast<std::string>(itk_peaks->GetLargestPossibleRegion().GetSize()[2]));
if (m_PythonService->DoesVariableExist("segmentation"))
m_PythonService->Execute("del segmentation");
if(m_Controls->m_ModeBox->currentIndex()==0)
m_PythonService->Execute("output_type=\"tract_segmentation\"");
else if(m_Controls->m_ModeBox->currentIndex()==1)
m_PythonService->Execute("output_type=\"endings_segmentation\"");
if(m_Controls->m_OutputBox->currentIndex()==3)
m_PythonService->Execute("output_type=\"TOM\"");
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<std::string>(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())
{
mitk::IPythonService::ForceLoadModule();
QMessageBox::warning(nullptr, "Error", QString(m_PythonService->GetVariable("error_string").c_str()), QMessageBox::Ok);
return;
}
std::vector<std::string> 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<std::string> 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() || m_Controls->m_OutputBox->currentIndex()>0)
{
if (m_Controls->m_OutputBox->currentIndex()>0)
{
itk::VectorImage<float>::Pointer vectorImage = itk::VectorImage<float>::New();
mitk::CastToItkImage(out_image, vectorImage);
itk::SplitVectorImageFilter<float>::Pointer splitter = itk::SplitVectorImageFilter<float>::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) );
seg->SetName(large_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<unsigned char>::Pointer vectorImage = itk::VectorImage<unsigned char>::New();
mitk::CastToItkImage(out_image, vectorImage);
itk::SplitVectorImageFilter<unsigned char>::Pointer splitter = itk::SplitVectorImageFilter<unsigned char>::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(large_name_list.at(c));
}
GetDataStorage()->Add(seg, node);
++c;
}
}
}
else
{
mitk::DataNode::Pointer seg = mitk::DataNode::New();
seg->SetData(out_image);
mitk::LevelWindow lw;
if (m_Controls->m_ModeBox->currentIndex()==0)
{
seg->SetName("TractLabels");
lw.SetRangeMinMax(0, 72);
}
else
{
seg->SetName("TractEndpointRegionLabels");
lw.SetRangeMinMax(0, 144);
}
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<72; ++i)
if (m_PythonService->DoesVariableExist("tom" + boost::lexical_cast<std::string>(i)))
{
mitk::Image::Pointer out_image = m_PythonService->CopySimpleItkImageFromPython("tom" + boost::lexical_cast<std::string>(i));
itk::VectorImage<float>::Pointer vectorImage = itk::VectorImage<float>::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();
itk::FlipPeaksFilter< float >::Pointer flipper = itk::FlipPeaksFilter< float >::New();
flipper->SetInput(itk_peaks);
flipper->SetFlipX(false);
flipper->SetFlipY(false);
flipper->SetFlipZ(true);
flipper->Update();
itk_peaks = flipper->GetOutput();
mitk::Image::Pointer mitk_peaks = dynamic_cast<mitk::Image*>(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(large_name_list.at(i) + "_TOM");
else
seg->SetName("Collapsed_TOM");
GetDataStorage()->Add(seg, node);
m_PythonService->Execute("del tom" + boost::lexical_cast<std::string>(i));
}
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkTractSegView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkTractSegView.h
index 8d6239c..1fddc3e 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkTractSegView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/QmitkTractSegView.h
@@ -1,65 +1,65 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <berryISelectionListener.h>
#include <berryIStructuredSelection.h>
#include <QmitkAbstractView.h>
#include "ui_QmitkTractSegViewControls.h"
/*!
\brief
*/
class QmitkTractSegView : public QmitkAbstractView
{
// 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;
QmitkTractSegView();
virtual ~QmitkTractSegView();
virtual void CreateQtPartControl(QWidget *parent) override;
void SetFocus() override;
protected slots:
void Start();
void UpdateGUI(); ///< update button activity etc. dpending on current datamanager selection
protected:
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
Ui::QmitkTractSegViewControls* m_Controls;
private:
void UpdateRegistrationStatus(); ///< update textual status display of the Registration process
// the Qt parent of our GUI (NOT of this object)
QWidget* m_Parent;
};
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/mitkPluginActivator.cpp
index 1f0a1a1..3c7e5f3 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/mitkPluginActivator.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/mitkPluginActivator.cpp
@@ -1,46 +1,46 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPluginActivator.h"
#include "src/internal/QmitkBrainExtractionView.h"
#include "src/internal/QmitkDipyReconstructionsView.h"
#include "src/internal/QmitkTractSegView.h"
#include <usModuleInitialization.h>
ctkPluginContext* mitk::PluginActivator::m_Context = nullptr;
US_INITIALIZE_MODULE
ctkPluginContext* mitk::PluginActivator::GetContext()
{
return m_Context;
}
void mitk::PluginActivator::start(ctkPluginContext* context)
{
BERRY_REGISTER_EXTENSION_CLASS(QmitkBrainExtractionView, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkDipyReconstructionsView, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkTractSegView, context)
m_Context = context;
}
void mitk::PluginActivator::stop(ctkPluginContext* context)
{
Q_UNUSED(context)
m_Context = nullptr;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/mitkPluginActivator.h
index 975d65b..58e583a 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/mitkPluginActivator.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.python/src/internal/mitkPluginActivator.h
@@ -1,40 +1,40 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKPLUGINACTIVATOR_H
#define MITKPLUGINACTIVATOR_H
#include <ctkPluginActivator.h>
namespace mitk
{
class PluginActivator : public QObject, public ctkPluginActivator
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.mitk.gui.qt.diffusionimaging.preprocessing")
Q_INTERFACES(ctkPluginActivator)
public:
static ctkPluginContext* GetContext();
void start(ctkPluginContext* context) override;
void stop(ctkPluginContext* context) override;
private:
static ctkPluginContext* m_Context;
};
}
#endif
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFDetailsWidget.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFDetailsWidget.cpp
index 3c825f8..fad7a50 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFDetailsWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFDetailsWidget.cpp
@@ -1,39 +1,39 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkODFDetailsWidget.h"
#include <qwt_scale_engine.h>
QmitkODFDetailsWidget::QmitkODFDetailsWidget( QWidget * parent )
: QmitkPlotWidget(parent)
{
QFrame* canvas = qobject_cast<QFrame*>(m_Plot->canvas());
if (canvas)
{
canvas->setLineWidth(0);
canvas->setContentsMargins(0,0,0,0);
}
auto scale = new QwtLinearScaleEngine();
m_Plot->setAxisScaleEngine(0, scale);
m_Plot->setAxisScale ( 0, -0.5, 0.5 );
}
QmitkODFDetailsWidget::~QmitkODFDetailsWidget()
{
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFDetailsWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFDetailsWidget.h
index f8654c4..f96f61d 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFDetailsWidget.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFDetailsWidget.h
@@ -1,74 +1,74 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkODFDetailsWidget_H_
#define QmitkODFDetailsWidget_H_
#include "QmitkPlotWidget.h"
#include <org_mitk_gui_qt_diffusionimaging_reconstruction_Export.h>
#include <itkOrientationDistributionFunction.h>
/**
* \brief Widget for displaying image histograms based on the vtkQtChart
* framework
*/
class DIFFUSIONIMAGING_RECONSTRUCTION_EXPORT QmitkODFDetailsWidget : public QmitkPlotWidget
{
Q_OBJECT
public:
template< unsigned int ODF_SIZE=ODF_SAMPLING_SIZE >
void SetParameters( itk::OrientationDistributionFunction<float, ODF_SIZE> odf )
{
this->Clear();
std::vector<double> xVals;
std::vector<double> yVals;
double max = itk::NumericTraits<double>::NonpositiveMin();
double min = itk::NumericTraits<double>::max();
for (unsigned int i=0; i<ODF_SIZE; i++){
xVals.push_back(i);
yVals.push_back(odf[i]);
if (odf[i]>max)
max = odf[i];
if (odf[i]<min)
min = odf[i];
}
if(min>0)
m_Plot->setAxisScale ( 0, 0, max );
else
m_Plot->setAxisScale ( 0, min, max );
auto curveId = this->InsertCurve( "ODF Values" );
this->SetCurveData( curveId, xVals, yVals );
this->SetCurvePen( curveId, QPen(Qt::blue, 0.5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin) );
this->Replot();
}
QmitkODFDetailsWidget( QWidget * /*parent = 0 */);
virtual ~QmitkODFDetailsWidget();
std::vector<double> m_Vals;
private:
};
#endif /* QmitkODFDetailsWidget_H_ */
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFRenderWidget.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFRenderWidget.cpp
index 95f6292..9f92bf3 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFRenderWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFRenderWidget.cpp
@@ -1,44 +1,44 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkODFRenderWidget.h"
#include <mitkLookupTable.h>
#include <mitkLookupTableProperty.h>
#include <vtkSmartPointer.h>
#include <mitkPlaneGeometry.h>
QmitkODFRenderWidget::QmitkODFRenderWidget(QWidget* parent, Qt::WindowFlags f): QWidget(parent, f)
{
//create Layouts
QmitkODFRenderWidgetLayout = new QHBoxLayout( this );
//Set Layout to widget
this->setLayout(QmitkODFRenderWidgetLayout);
//Create RenderWindow
m_RenderWindow = new QmitkRenderWindow(this, "odf render widget");
m_RenderWindow->setMaximumSize(300,300);
m_RenderWindow->GetRenderer()->SetMapperID( mitk::BaseRenderer::Standard3D );
//m_RenderWindow->SetLayoutIndex( 3 );
QmitkODFRenderWidgetLayout->addWidget( m_RenderWindow );
}
QmitkODFRenderWidget::~QmitkODFRenderWidget()
{
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFRenderWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFRenderWidget.h
index 00d87f3..6e34526 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFRenderWidget.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkODFRenderWidget.h
@@ -1,168 +1,168 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkODFRenderWidget_H_
#define QmitkODFRenderWidget_H_
#include <org_mitk_gui_qt_diffusionimaging_reconstruction_Export.h>
#include <QWidget>
#include <QmitkRenderWindow.h>
#include <QBoxLayout>
#include <vtkPolyData.h>
#include <mitkSurface.h>
#include <mitkDataNode.h>
#include <itkOrientationDistributionFunction.h>
#include <mitkStandaloneDataStorage.h>
#include <vtkFloatArray.h>
#include <vtkPointData.h>
#include <vtkLookupTable.h>
#include <vtkDoubleArray.h>
#include <vtkCellData.h>
#include <vtkSphereSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkCamera.h>
#include <mitkLookupTable.h>
#include <mitkLookupTableProperty.h>
class DIFFUSIONIMAGING_RECONSTRUCTION_EXPORT QmitkODFRenderWidget : public QWidget
{
Q_OBJECT
public:
QmitkODFRenderWidget( QWidget* parent = nullptr, Qt::WindowFlags f = nullptr );
virtual ~QmitkODFRenderWidget();
template<unsigned int ODF_SIZE=ODF_SAMPLING_SIZE>
void GenerateODF( itk::OrientationDistributionFunction<float, ODF_SIZE> odf, int normalization, bool dir_color)
{
try
{
switch(normalization)
{
case 0:
odf = odf.MinMaxNormalize();
break;
case 1:
odf = odf.MaxNormalize();
break;
case 2:
odf = odf.MaxNormalize();
break;
default:
odf = odf.MinMaxNormalize();
}
m_Surface = mitk::Surface::New();
m_ds = mitk::StandaloneDataStorage::New();
m_Node = mitk::DataNode::New();
vtkPolyData* m_TemplateOdf = itk::OrientationDistributionFunction<float,ODF_SIZE>::GetBaseMesh();
vtkPolyData *polyData = vtkPolyData::New();
vtkPoints *points = vtkPoints::New();
vtkFloatArray *scalars = vtkFloatArray::New();
for (unsigned int i=0; i<ODF_SIZE; i++){
double p[3];
m_TemplateOdf->GetPoints()->GetPoint(i,p);
double val = odf[i];
p[0] *= val;
p[1] *= val;
p[2] *= val;
points->InsertPoint(i,p);
scalars->InsertTuple1(i, 1-val);
}
polyData->SetPoints(points);
vtkCellArray* polys = m_TemplateOdf->GetPolys();
polyData->SetPolys(polys);
polyData->GetPointData()->SetScalars(scalars);
polys->Delete();
scalars->Delete();
points->Delete();
m_Surface->SetVtkPolyData(polyData);
m_Node->SetData(m_Surface);
mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New();
// assign an empty vtk lookup table to the odf renderer, it is the same
// the ODF 2D Mapper has
vtkSmartPointer<vtkLookupTable> lut = vtkSmartPointer<vtkLookupTable>::New();
mitkLut->SetVtkLookupTable( lut );
mitk::LookupTableProperty::Pointer mitkLutProp = mitk::LookupTableProperty::New();
mitkLutProp->SetLookupTable(mitkLut);
m_Node->SetProperty( "LookupTable", mitkLutProp );
m_Node->SetProperty("scalar visibility", mitk::BoolProperty::New(true));
m_Node->SetProperty("color mode", mitk::BoolProperty::New(true));
m_Node->SetProperty("material.specularCoefficient", mitk::FloatProperty::New(0.5));
if (dir_color)
{
m_Node->SetProperty("scalar visibility", mitk::BoolProperty::New(false));
m_Node->SetProperty("color mode", mitk::BoolProperty::New(false));
vnl_vector_fixed<double,3> d = odf.GetPrincipalDiffusionDirection();
mitk::Color c;
c.SetRed(fabs(static_cast<float>(d[0])));
c.SetGreen(fabs(static_cast<float>(d[1])));
c.SetBlue(fabs(static_cast<float>(d[2])));
m_Node->SetColor(c);
}
m_ds->Add(m_Node);
m_RenderWindow->GetRenderer()->SetDataStorage( m_ds );
// adjust camera to current plane rotation
mitk::PlaneGeometry::ConstPointer worldPlaneGeometry = mitk::BaseRenderer::GetInstance(m_RenderWindow->GetVtkRenderWindow())->GetCurrentWorldPlaneGeometry();
mitk::Vector3D normal = worldPlaneGeometry->GetNormal();
mitk::Vector3D up = worldPlaneGeometry->GetAxisVector(1);
normal.Normalize();
up.Normalize();
vtkSmartPointer<vtkCamera> cam = vtkSmartPointer<vtkCamera>::New();
const double camPos[3] = {normal[0],normal[1],normal[2]};
const double camUp[3] = {up[0],up[1],up[2]};
cam->SetPosition(camPos);
cam->SetViewUp(camUp);
cam->SetParallelProjection(1);
m_RenderWindow->GetRenderer()->GetVtkRenderer()->SetActiveCamera(cam);
m_RenderWindow->update();
}
catch (...)
{
}
}
protected:
QHBoxLayout* QmitkODFRenderWidgetLayout;
QmitkRenderWindow* m_RenderWindow;
mitk::Surface::Pointer m_Surface;
mitk::StandaloneDataStorage::Pointer m_ds;
mitk::DataNode::Pointer m_Node;
};
#endif /*QmitkODFRenderWidget_H_*/
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkResidualAnalysisWidget.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkResidualAnalysisWidget.cpp
index 2bd918c..e287e27 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkResidualAnalysisWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkResidualAnalysisWidget.cpp
@@ -1,117 +1,117 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkResidualAnalysisWidget.h"
#include <QPen>
#include <qwt_legend.h>
#include <qwt_plot_picker.h>
#include <qwt_picker_machine.h>
QmitkResidualAnalysisWidget::QmitkResidualAnalysisWidget( QWidget * parent )
: QmitkPlotWidget(parent)
{
m_PlotPicker = new QwtPlotPicker(m_Plot->canvas());
m_PlotPicker->setStateMachine(new QwtPickerDragPointMachine());
m_PlotPicker->setTrackerMode(QwtPicker::ActiveOnly);
}
QmitkResidualAnalysisWidget::~QmitkResidualAnalysisWidget()
{
delete m_PlotPicker;
}
void QmitkResidualAnalysisWidget::DrawMeans()
{
this->Clear();
this->SetPlotTitle("mean residual per volume");
QPen pen( Qt::SolidLine );
pen.setWidth(1);
// Create values for x-axis
std::vector<double> xAxis;
for(unsigned int i=0; i<m_Means.size(); ++i)
{
xAxis.push_back((double)i);
}
pen.setColor(Qt::black);
int curveId = this->InsertCurve( "Mean" );
this->SetCurveData( curveId, xAxis, m_Means );
this->SetCurvePen( curveId, pen );
this->SetCurveStyle( curveId, QwtPlotCurve::Dots);
pen.setColor(Qt::blue);
curveId = this->InsertCurve( "Q1" );
this->SetCurveData( curveId, xAxis, m_Q1 );
this->SetCurvePen( curveId, pen );
this->SetCurveStyle( curveId, QwtPlotCurve::Dots);
pen.setColor(Qt::red);
curveId = this->InsertCurve( "Q3" );
this->SetCurveData( curveId, xAxis, m_Q3 );
this->SetCurvePen( curveId, pen );
this->SetCurveStyle( curveId, QwtPlotCurve::Dots);
this->m_Plot->setAxisTitle(0, "Residual");
this->m_Plot->setAxisTitle(3, "DWI Volume");
auto legend = new QwtLegend;
this->SetLegend(legend, QwtPlot::RightLegend, 0.5);
this->Replot();
}
void QmitkResidualAnalysisWidget::DrawPercentagesOfOutliers()
{
this->Clear();
this->SetPlotTitle("Percentage of outliers");
QPen pen( Qt::SolidLine );
pen.setWidth(1);
// Create values for x-axis
std::vector<double> xAxis;
for(unsigned int i=0; i<m_PercentagesOfOutliers.size(); ++i)
{
xAxis.push_back((double)i);
}
pen.setColor(Qt::black);
int curveId = this->InsertCurve( "Outliers" );
this->SetCurveData( curveId, xAxis, m_PercentagesOfOutliers );
this->SetCurvePen( curveId, pen );
//this->SetCurveStyle( curveId, QwtPlotCurve::Fitted);
this->m_Plot->setAxisTitle(0, "Percentage of outliers");
this->m_Plot->setAxisTitle(3, "DWI Volume");
auto legend = new QwtLegend;
this->SetLegend(legend, QwtPlot::RightLegend, 0.5);
this->Replot();
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkResidualAnalysisWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkResidualAnalysisWidget.h
index 80bc249..f927902 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkResidualAnalysisWidget.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkResidualAnalysisWidget.h
@@ -1,84 +1,84 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkResidualAnalysisWidget_H_
#define QmitkResidualAnalysisWidget_H_
#include "QmitkPlotWidget.h"
#include <org_mitk_gui_qt_diffusionimaging_reconstruction_Export.h>
class QwtPlotPicker;
/**
* \brief Widget for displaying boxplots
* framework
*/
class DIFFUSIONIMAGING_RECONSTRUCTION_EXPORT QmitkResidualAnalysisWidget : public QmitkPlotWidget
{
Q_OBJECT
public:
QmitkResidualAnalysisWidget( QWidget * parent);
virtual ~QmitkResidualAnalysisWidget();
QwtPlot* GetPlot()
{
return m_Plot;
}
QwtPlotPicker* m_PlotPicker;
void SetMeans(std::vector< double > means)
{
m_Means = means;
}
void SetQ1(std::vector< double > q1)
{
m_Q1 = q1;
}
void SetQ3(std::vector< double > q3)
{
m_Q3 = q3;
}
void SetPercentagesOfOutliers(std::vector< double > perc)
{
m_PercentagesOfOutliers = perc;
}
void DrawMeans();
void DrawPercentagesOfOutliers();
protected:
std::vector< double > m_Means;
std::vector< double > m_Q1;
std::vector< double > m_Q3;
std::vector< double > m_PercentagesOfOutliers;
};
#endif
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkResidualViewWidget.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkResidualViewWidget.cpp
index bb2130b..8e00507 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkResidualViewWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkResidualViewWidget.cpp
@@ -1,170 +1,170 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkResidualViewWidget.h"
#include <iostream>
#include <QToolTip>
QmitkResidualViewWidget::QmitkResidualViewWidget( QWidget * parent )
: QGraphicsView(parent)
{
}
QmitkResidualViewWidget::QmitkResidualViewWidget(QGraphicsScene *scene, QWidget *parent)
: QGraphicsView(scene, parent)
{
}
void QmitkResidualViewWidget::mousePressEvent(QMouseEvent* event) {
// Panning
m_LastPanPoint = event->pos();
setCursor(Qt::ClosedHandCursor);
QGraphicsItem *item = this->itemAt(event->pos());
if(item == m_ResidualPixmapItem)
{
QPointF sceneCoord(mapToScene(event->pos()));
QPointF imageCoord(item->mapFromParent(sceneCoord));
int volume = (int)imageCoord.y();
int slice = (int)imageCoord.x();
emit pointSelected(slice, volume);
}
}
void QmitkResidualViewWidget::mouseReleaseEvent(QMouseEvent*) {
setCursor(Qt::OpenHandCursor);
m_LastPanPoint = QPoint();
}
void QmitkResidualViewWidget::mouseMoveEvent(QMouseEvent *event)
{
if(!m_LastPanPoint.isNull()) {
QPointF delta = mapToScene(m_LastPanPoint) - mapToScene(event->pos());
m_LastPanPoint = event->pos();
SetCenter(m_CurrentCenterPoint + delta);
}
}
void QmitkResidualViewWidget::wheelEvent(QWheelEvent *event)
{
// Position of the mouse in scene coordinates
QPointF before(mapToScene(event->pos()));
QPointF screenCenter = m_CurrentCenterPoint;
double factor = 1.15;
if(event->delta() > 0)
{
scale(factor, factor);
}
else
{
scale(1.0 / factor, 1.0 / factor);
}
//Get the position after scaling, in scene coords
QPointF after(mapToScene(event->pos()));
//Get the offset of how the screen moved
QPointF offset = before - after;
//Adjust to the new center for correct zooming
QPointF newCenter = screenCenter + offset;
SetCenter(newCenter);
}
/**
* Sets the current centerpoint. Also updates the scene's center point.
* Unlike centerOn, which has no way of getting the floating point center
* back, SetCenter() stores the center point. It also handles the special
* sidebar case. This function will claim the centerPoint to sceneRec ie.
* the centerPoint must be within the sceneRec.
*/
void QmitkResidualViewWidget::SetCenter(const QPointF& center) {
QRectF visibleArea = mapToScene(rect()).boundingRect();
QRectF sceneBounds = sceneRect();
double boundX = visibleArea.width() / 2.0 ;
double boundY = visibleArea.height() / 2.0;
double boundWidth = sceneBounds.width() -2.0 * boundX;
double boundHeight = sceneBounds.height() - 2.0 * boundY;
//The max boundary that the centerPoint can be to
QRectF bounds(boundX, boundY, boundWidth, boundHeight);
if(bounds.contains(center))
{
m_CurrentCenterPoint = center;
}
else
{
//We need to clamp or use the center of the screen
if(visibleArea.contains(sceneBounds))
{
//Use the center of scene ie. we can see the whole scene
m_CurrentCenterPoint = sceneBounds.center();
}
else{
m_CurrentCenterPoint = center;
//We need to clamp the center. The centerPoint is too large
if(center.x() > bounds.x() + bounds.width())
{
m_CurrentCenterPoint.setX(bounds.x() + bounds.width());
}
else if(center.x() < bounds.x()) {
m_CurrentCenterPoint.setX(bounds.x());
}
if(center.y() > bounds.y() + bounds.height())
{
m_CurrentCenterPoint.setY(bounds.y() + bounds.height());
}
else if(center.y() < bounds.y())
{
m_CurrentCenterPoint.setY(bounds.y());
}
}
}
// Update the scrollbars
centerOn(m_CurrentCenterPoint);
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkResidualViewWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkResidualViewWidget.h
index 5afe0a1..1440e33 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkResidualViewWidget.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/QmitkResidualViewWidget.h
@@ -1,80 +1,80 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkResidualViewWidget_H_
#define QmitkResidualViewWidget_H_
//#include <QObject>
#include <QGraphicsView>
#include <QWheelEvent>
#include <QMouseEvent>
#include <QGraphicsPixmapItem>
#include <org_mitk_gui_qt_diffusionimaging_reconstruction_Export.h>
/**
* \brief Widget for displaying the residual between an original dwi image and the dwi estimated from a tensor image
*
*/
class DIFFUSIONIMAGING_RECONSTRUCTION_EXPORT QmitkResidualViewWidget : public QGraphicsView
{
Q_OBJECT
public:
QmitkResidualViewWidget(QWidget *parent = nullptr);
QmitkResidualViewWidget(QGraphicsScene *scene, QWidget *parent = nullptr);
// ~QmitkResidualViewWidget();
void SetResidualPixmapItem(QGraphicsPixmapItem* item)
{
m_ResidualPixmapItem = item;
}
signals:
void pointSelected(int slice, int volume);
protected:
void wheelEvent(QWheelEvent *event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
QPointF m_CurrentCenterPoint;
QGraphicsPixmapItem* m_ResidualPixmapItem;
QPoint m_LastPanPoint;
void SetCenter(const QPointF& centerPoint);
};
#endif
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkQuantificationPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkQuantificationPerspective.cpp
index 74c532b..0a2df23 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkQuantificationPerspective.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkQuantificationPerspective.cpp
@@ -1,51 +1,51 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkQuantificationPerspective.h"
#include "berryIViewLayout.h"
void QmitkQuantificationPerspective::CreateInitialLayout(berry::IPageLayout::Pointer layout)
{
/////////////////////////////////////////////////////
// all di-app perspectives should have the following:
/////////////////////////////////////////////////////
QString editorArea = layout->GetEditorArea();
layout->AddStandaloneViewPlaceholder("org.mitk.views.viewnavigatorview", berry::IPageLayout::LEFT, 0.3f, editorArea, false);
layout->AddStandaloneView("org.mitk.views.datamanager",
false, berry::IPageLayout::LEFT, 0.3f, editorArea);
layout->AddStandaloneView("org.mitk.views.controlvisualizationpropertiesview",
false, berry::IPageLayout::BOTTOM, .15f, "org.mitk.views.datamanager");
berry::IFolderLayout::Pointer left =
layout->CreateFolder("org.mbi.diffusionimaginginternal.leftcontrols",
berry::IPageLayout::BOTTOM, 0.15f, "org.mitk.views.controlvisualizationpropertiesview");
layout->AddStandaloneViewPlaceholder("org.mitk.views.imagenavigator",
berry::IPageLayout::BOTTOM, .7f, "org.mbi.diffusionimaginginternal.leftcontrols", false);
/////////////////////////////////////////////
// here goes the perspective specific stuff
/////////////////////////////////////////////
left->AddView("org.mitk.views.diffusionquantification");
left->AddView("org.mitk.views.imagestatistics");
left->AddView("org.mitk.views.segmentation");
left->AddView("org.mitk.views.odfdetails");
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkQuantificationPerspective.h b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkQuantificationPerspective.h
index 097fac1..7871347 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkQuantificationPerspective.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkQuantificationPerspective.h
@@ -1,36 +1,36 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkQuantificationPerspective_H_
#define QmitkQuantificationPerspective_H_
#include <berryIPerspectiveFactory.h>
class QmitkQuantificationPerspective : public QObject, public berry::IPerspectiveFactory
{
Q_OBJECT
Q_INTERFACES(berry::IPerspectiveFactory)
public:
QmitkQuantificationPerspective() {}
~QmitkQuantificationPerspective() {}
void CreateInitialLayout(berry::IPageLayout::Pointer layout) override;
};
#endif /* QmitkQuantificationPerspective_H_ */
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkReconstructionPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkReconstructionPerspective.cpp
index 0619c30..621461c 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkReconstructionPerspective.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkReconstructionPerspective.cpp
@@ -1,52 +1,52 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkReconstructionPerspective.h"
#include "berryIViewLayout.h"
void QmitkReconstructionPerspective::CreateInitialLayout(berry::IPageLayout::Pointer layout)
{
/////////////////////////////////////////////////////
// all di-app perspectives should have the following:
/////////////////////////////////////////////////////
QString editorArea = layout->GetEditorArea();
layout->AddStandaloneViewPlaceholder("org.mitk.views.viewnavigatorview", berry::IPageLayout::LEFT, 0.3f, editorArea, false);
layout->AddStandaloneView("org.mitk.views.datamanager",
false, berry::IPageLayout::LEFT, 0.3f, editorArea);
layout->AddStandaloneView("org.mitk.views.controlvisualizationpropertiesview",
false, berry::IPageLayout::BOTTOM, .15f, "org.mitk.views.datamanager");
berry::IFolderLayout::Pointer left =
layout->CreateFolder("org.mbi.diffusionimaginginternal.leftcontrols",
berry::IPageLayout::BOTTOM, 0.15f, "org.mitk.views.controlvisualizationpropertiesview");
layout->AddStandaloneViewPlaceholder("org.mitk.views.imagenavigator",
berry::IPageLayout::BOTTOM, .7f, "org.mbi.diffusionimaginginternal.leftcontrols", false);
/////////////////////////////////////////////
// here goes the perspective specific stuff
/////////////////////////////////////////////
left->AddView("org.mitk.views.tensorreconstruction");
left->AddView("org.mitk.views.qballreconstruction");
left->AddView("org.mitk.views.odfmaximaextraction");
left->AddView("org.mitk.views.dipyreconstruction");
left->AddView("org.mitk.views.odfdetails");
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkReconstructionPerspective.h b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkReconstructionPerspective.h
index 90779f0..0c0ee8d 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkReconstructionPerspective.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/Perspectives/QmitkReconstructionPerspective.h
@@ -1,36 +1,36 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkReconstructionPerspective_H_
#define QmitkReconstructionPerspective_H_
#include <berryIPerspectiveFactory.h>
class QmitkReconstructionPerspective : public QObject, public berry::IPerspectiveFactory
{
Q_OBJECT
Q_INTERFACES(berry::IPerspectiveFactory)
public:
QmitkReconstructionPerspective() {}
~QmitkReconstructionPerspective() {}
void CreateInitialLayout(berry::IPageLayout::Pointer layout) override;
};
#endif /* QmitkReconstructionPerspective_H_ */
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkDiffusionQuantificationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkDiffusionQuantificationView.cpp
index 9307536..0eed5b0 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkDiffusionQuantificationView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkDiffusionQuantificationView.cpp
@@ -1,606 +1,606 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkDiffusionQuantificationView.h"
#include "mitkDiffusionImagingConfigure.h"
#include "itkTimeProbe.h"
#include "itkImage.h"
#include "mitkNodePredicateDataType.h"
#include "mitkDataNodeObject.h"
#include "mitkOdfImage.h"
#include <mitkTensorImage.h>
#include "mitkImageCast.h"
#include "mitkStatusBar.h"
#include "itkDiffusionOdfGeneralizedFaImageFilter.h"
#include "itkShiftScaleImageFilter.h"
#include "itkTensorFractionalAnisotropyImageFilter.h"
#include "itkTensorRelativeAnisotropyImageFilter.h"
#include "itkTensorDerivedMeasurementsFilter.h"
#include "QmitkDataStorageComboBox.h"
#include <QMessageBox>
#include "berryIWorkbenchWindow.h"
#include "berryISelectionService.h"
#include <mitkDiffusionPropertyHelper.h>
#include <itkAdcImageFilter.h>
#include <itkBallAndSticksImageFilter.h>
#include <itkMultiTensorImageFilter.h>
#include <mitkLookupTable.h>
#include <mitkLookupTableProperty.h>
#include <mitkITKImageImport.h>
#include <mitkLexicalCast.h>
#include <mitkNodePredicateIsDWI.h>
#include <mitkNodePredicateDataType.h>
#include <mitkNodePredicateOr.h>
#include <QmitkStyleManager.h>
#include <mitkLevelWindowProperty.h>
#include <mitkDiffusionFunctionCollection.h>
const std::string QmitkDiffusionQuantificationView::VIEW_ID = "org.mitk.views.diffusionquantification";
QmitkDiffusionQuantificationView::QmitkDiffusionQuantificationView()
: QmitkAbstractView(),
m_Controls(nullptr)
{
}
QmitkDiffusionQuantificationView::~QmitkDiffusionQuantificationView()
{
}
void QmitkDiffusionQuantificationView::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
// create GUI widgets
m_Controls = new Ui::QmitkDiffusionQuantificationViewControls;
m_Controls->setupUi(parent);
m_Controls->m_BallStickButton->setVisible(false);
m_Controls->m_MultiTensorButton->setVisible(false);
connect( static_cast<QObject*>(m_Controls->m_GFAButton), SIGNAL(clicked()), this, SLOT(GFA()) );
connect( static_cast<QObject*>(m_Controls->m_FAButton), SIGNAL(clicked()), this, SLOT(FA()) );
connect( static_cast<QObject*>(m_Controls->m_RAButton), SIGNAL(clicked()), this, SLOT(RA()) );
connect( static_cast<QObject*>(m_Controls->m_ADButton), SIGNAL(clicked()), this, SLOT(AD()) );
connect( static_cast<QObject*>(m_Controls->m_RDButton), SIGNAL(clicked()), this, SLOT(RD()) );
connect( static_cast<QObject*>(m_Controls->m_MDButton), SIGNAL(clicked()), this, SLOT(MD()) );
connect( static_cast<QObject*>(m_Controls->m_MdDwiButton), SIGNAL(clicked()), this, SLOT(MD_DWI()) );
connect( static_cast<QObject*>(m_Controls->m_AdcDwiButton), SIGNAL(clicked()), this, SLOT(ADC_DWI()) );
connect( static_cast<QObject*>(m_Controls->m_ClusteringAnisotropy), SIGNAL(clicked()), this, SLOT(ClusterAnisotropy()) );
connect( static_cast<QObject*>(m_Controls->m_BallStickButton), SIGNAL(clicked()), this, SLOT(DoBallStickCalculation()) );
connect( static_cast<QObject*>(m_Controls->m_MultiTensorButton), SIGNAL(clicked()), this, SLOT(DoMultiTensorCalculation()) );
m_Controls->m_ImageBox->SetDataStorage(this->GetDataStorage());
mitk::TNodePredicateDataType<mitk::TensorImage>::Pointer isDti = mitk::TNodePredicateDataType<mitk::TensorImage>::New();
mitk::TNodePredicateDataType<mitk::OdfImage>::Pointer isOdf = mitk::TNodePredicateDataType<mitk::OdfImage>::New();
mitk::TNodePredicateDataType<mitk::ShImage>::Pointer isSh = mitk::TNodePredicateDataType<mitk::ShImage>::New();
mitk::NodePredicateIsDWI::Pointer isDwi = mitk::NodePredicateIsDWI::New();
m_Controls->m_ImageBox->SetPredicate( mitk::NodePredicateOr::New(isSh, mitk::NodePredicateOr::New(isDti, mitk::NodePredicateOr::New(isOdf, isDwi))) );
connect( static_cast<QObject*>(m_Controls->m_ImageBox), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()));
}
}
void QmitkDiffusionQuantificationView::SetFocus()
{
m_Controls->m_ScaleImageValuesBox->setFocus();
}
void QmitkDiffusionQuantificationView::UpdateGui()
{
bool foundOdfVolume = false;
bool foundTensorVolume = false;
bool foundDwVolume = false;
mitk::DataNode::Pointer selNode = m_Controls->m_ImageBox->GetSelectedNode();
if( selNode.IsNotNull() && (dynamic_cast<mitk::OdfImage*>(selNode->GetData()) || dynamic_cast<mitk::ShImage*>(selNode->GetData())) )
foundOdfVolume = true;
else if( selNode.IsNotNull() && dynamic_cast<mitk::TensorImage*>(selNode->GetData()) )
foundTensorVolume = true;
else if( selNode.IsNotNull())
foundDwVolume = true;
m_Controls->m_GFAButton->setEnabled(foundOdfVolume);
m_Controls->m_FAButton->setEnabled(foundTensorVolume);
m_Controls->m_RAButton->setEnabled(foundTensorVolume);
m_Controls->m_ADButton->setEnabled(foundTensorVolume);
m_Controls->m_RDButton->setEnabled(foundTensorVolume);
m_Controls->m_MDButton->setEnabled(foundTensorVolume);
m_Controls->m_ClusteringAnisotropy->setEnabled(foundTensorVolume);
m_Controls->m_AdcDwiButton->setEnabled(foundDwVolume);
m_Controls->m_MdDwiButton->setEnabled(foundDwVolume);
m_Controls->m_BallStickButton->setEnabled(foundDwVolume);
m_Controls->m_MultiTensorButton->setEnabled(foundDwVolume);
}
void QmitkDiffusionQuantificationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList<mitk::DataNode::Pointer>& )
{
UpdateGui();
}
void QmitkDiffusionQuantificationView::ADC_DWI()
{
DoAdcCalculation(true);
}
void QmitkDiffusionQuantificationView::MD_DWI()
{
DoAdcCalculation(false);
}
void QmitkDiffusionQuantificationView::DoBallStickCalculation()
{
if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull())
{
mitk::DataNode* node = m_Controls->m_ImageBox->GetSelectedNode();
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
typedef itk::BallAndSticksImageFilter< short, double > FilterType;
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(image, itkVectorImagePointer);
FilterType::Pointer filter = FilterType::New();
filter->SetInput( itkVectorImagePointer );
filter->SetGradientDirections(mitk::DiffusionPropertyHelper::GetGradientContainer(image));
filter->SetB_value(static_cast<double>(mitk::DiffusionPropertyHelper::GetReferenceBValue(image)));
filter->Update();
mitk::Image::Pointer newImage = mitk::Image::New();
newImage->InitializeByItk( filter->GetOutput() );
newImage->SetVolume( filter->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( newImage );
QString name = node->GetName().c_str();
imageNode->SetName((name+"_f").toStdString().c_str());
GetDataStorage()->Add(imageNode, node);
{
FilterType::PeakImageType::Pointer itkImg = filter->GetPeakImage();
mitk::Image::Pointer newImage = mitk::Image::New();
CastToMitkImage(itkImg, newImage);
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( newImage );
QString name = node->GetName().c_str();
imageNode->SetName((name+"_Sticks").toStdString().c_str());
GetDataStorage()->Add(imageNode, node);
}
{
mitk::Image::Pointer dOut = mitk::GrabItkImageMemory( filter->GetOutDwi().GetPointer() );
mitk::DiffusionPropertyHelper::SetGradientContainer(dOut, mitk::DiffusionPropertyHelper::GetGradientContainer(image) );
mitk::DiffusionPropertyHelper::SetReferenceBValue(dOut, mitk::DiffusionPropertyHelper::GetReferenceBValue(image) );
mitk::DiffusionPropertyHelper::InitializeImage(dOut);
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData(dOut);
QString name = node->GetName().c_str();
imageNode->SetName((name+"_Estimated-DWI").toStdString().c_str());
GetDataStorage()->Add(imageNode, node);
}
}
}
void QmitkDiffusionQuantificationView::DoMultiTensorCalculation()
{
if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull()) // for all items
{
mitk::DataNode* node = m_Controls->m_ImageBox->GetSelectedNode();
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
typedef itk::MultiTensorImageFilter< short, double > FilterType;
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(image, itkVectorImagePointer);
FilterType::Pointer filter = FilterType::New();
filter->SetInput( itkVectorImagePointer );
filter->SetGradientDirections(mitk::DiffusionPropertyHelper::GetGradientContainer(image));
filter->SetB_value(static_cast<double>(mitk::DiffusionPropertyHelper::GetReferenceBValue(image)));
filter->Update();
typedef mitk::TensorImage::ItkTensorImageType TensorImageType;
for (unsigned int i=0; i<NUM_TENSORS; i++)
{
TensorImageType::Pointer tensorImage = filter->GetTensorImages().at(i);
mitk::TensorImage::Pointer image = mitk::TensorImage::New();
image->InitializeByItk( tensorImage.GetPointer() );
image->SetVolume( tensorImage->GetBufferPointer() );
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( image );
QString name = node->GetName().c_str();
name.append("_Tensor");
name.append(boost::lexical_cast<std::string>(i).c_str());
imageNode->SetName(name.toStdString().c_str());
GetDataStorage()->Add(imageNode, node);
}
}
}
void QmitkDiffusionQuantificationView::DoAdcCalculation(bool fit)
{
if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull())
{
mitk::DataNode* node = m_Controls->m_ImageBox->GetSelectedNode();
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(node->GetData());
typedef itk::AdcImageFilter< short, double > FilterType;
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(image, itkVectorImagePointer);
FilterType::Pointer filter = FilterType::New();
filter->SetInput( itkVectorImagePointer );
filter->SetGradientDirections( mitk::DiffusionPropertyHelper::GetGradientContainer(image) );
filter->SetB_value( static_cast<double>(mitk::DiffusionPropertyHelper::GetReferenceBValue(image)) );
filter->SetFitSignal(fit);
filter->Update();
typedef itk::ShiftScaleImageFilter<itk::AdcImageFilter< short, double >::OutputImageType, itk::AdcImageFilter< short, double >::OutputImageType> ShiftScaleFilterType;
ShiftScaleFilterType::Pointer multi = ShiftScaleFilterType::New();
multi->SetShift(0.0);
multi->SetScale(m_Controls->m_ScaleImageValuesBox->value());
multi->SetInput(filter->GetOutput());
multi->Update();
mitk::Image::Pointer newImage = mitk::Image::New();
newImage->InitializeByItk( multi->GetOutput() );
newImage->SetVolume( multi->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer imageNode = mitk::DataNode::New();
imageNode->SetData( newImage );
QString name = node->GetName().c_str();
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 );
imageNode->SetProperty("LookupTable", lut_prop );
if (fit)
imageNode->SetName((name+"_ADC").toStdString().c_str());
else
imageNode->SetName((name+"_MD").toStdString().c_str());
mitk::LevelWindow lw;
lw.SetLevelWindow(0.0015, 0.003);
imageNode->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( lw ) );
GetDataStorage()->Add(imageNode, node);
}
}
void QmitkDiffusionQuantificationView::GFA()
{
OdfQuantify(0);
}
void QmitkDiffusionQuantificationView::FA()
{
TensorQuantify(0);
}
void QmitkDiffusionQuantificationView::RA()
{
TensorQuantify(1);
}
void QmitkDiffusionQuantificationView::AD()
{
TensorQuantify(2);
}
void QmitkDiffusionQuantificationView::RD()
{
TensorQuantify(3);
}
void QmitkDiffusionQuantificationView::ClusterAnisotropy()
{
TensorQuantify(4);
}
void QmitkDiffusionQuantificationView::MD()
{
TensorQuantify(5);
}
void QmitkDiffusionQuantificationView::OdfQuantify(int method)
{
OdfQuantification(method);
}
void QmitkDiffusionQuantificationView::TensorQuantify(int method)
{
TensorQuantification(method);
}
void QmitkDiffusionQuantificationView::OdfQuantification(int method)
{
QString status;
if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull())
{
mitk::DataNode* node = m_Controls->m_ImageBox->GetSelectedNode();
typedef float TOdfPixelType;
typedef itk::Vector<TOdfPixelType,ODF_SAMPLING_SIZE> OdfVectorType;
typedef itk::Image<OdfVectorType,3> OdfVectorImgType;
mitk::Image::Pointer vol = dynamic_cast<mitk::Image*>(node->GetData());
OdfVectorImgType::Pointer itkvol;
if (dynamic_cast<mitk::ShImage*>(vol.GetPointer()))
itkvol = mitk::convert::GetItkOdfFromShImage(vol);
else
itkvol = mitk::convert::GetItkOdfFromOdfImage(vol);
std::string nodename = node->GetName();
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Computing GFA for %s", nodename.c_str()).toLatin1());
typedef itk::DiffusionOdfGeneralizedFaImageFilter<TOdfPixelType,TOdfPixelType,ODF_SAMPLING_SIZE> GfaFilterType;
GfaFilterType::Pointer gfaFilter = GfaFilterType::New();
gfaFilter->SetInput(itkvol);
std::string newname;
newname.append(nodename);
switch(method)
{
case 0:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_STANDARD);
newname.append("GFA");
break;
}
case 1:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_QUANTILES_HIGH_LOW);
newname.append("01");
break;
}
case 2:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_QUANTILE_HIGH);
newname.append("02");
break;
}
case 3:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_MAX_ODF_VALUE);
newname.append("03");
break;
}
case 4:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_DECONVOLUTION_COEFFS);
newname.append("04");
break;
}
case 5:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_MIN_MAX_NORMALIZED_STANDARD);
newname.append("05");
break;
}
case 6:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_NORMALIZED_ENTROPY);
newname.append("06");
break;
}
case 7:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_NEMATIC_ORDER_PARAMETER);
newname.append("07");
break;
}
case 8:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_QUANTILES_LOW_HIGH);
newname.append("08");
break;
}
case 9:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_QUANTILE_LOW);
newname.append("09");
break;
}
case 10:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_MIN_ODF_VALUE);
newname.append("10");
break;
}
case 11:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_STD_BY_MAX);
newname.append("11");
break;
}
default:
{
newname.append("0");
gfaFilter->SetComputationMethod(GfaFilterType::GFA_STANDARD);
}
}
gfaFilter->Update();
typedef itk::Image<TOdfPixelType, 3> ImgType;
ImgType::Pointer img = ImgType::New();
img->SetSpacing( gfaFilter->GetOutput()->GetSpacing() ); // Set the image spacing
img->SetOrigin( gfaFilter->GetOutput()->GetOrigin() ); // Set the image origin
img->SetDirection( gfaFilter->GetOutput()->GetDirection() ); // Set the image direction
img->SetLargestPossibleRegion( gfaFilter->GetOutput()->GetLargestPossibleRegion());
img->SetBufferedRegion( gfaFilter->GetOutput()->GetLargestPossibleRegion() );
img->Allocate();
itk::ImageRegionIterator<ImgType> ot (img, img->GetLargestPossibleRegion() );
ot.GoToBegin();
itk::ImageRegionConstIterator<GfaFilterType::OutputImageType> it
(gfaFilter->GetOutput(), gfaFilter->GetOutput()->GetLargestPossibleRegion() );
for (it.GoToBegin(); !it.IsAtEnd(); ++it)
{
GfaFilterType::OutputImageType::PixelType val = it.Get();
ot.Set(val * m_Controls->m_ScaleImageValuesBox->value());
++ot;
}
// GFA TO DATATREE
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk( img.GetPointer() );
image->SetVolume( img->GetBufferPointer() );
mitk::DataNode::Pointer new_node=mitk::DataNode::New();
new_node->SetData( image );
new_node->SetProperty( "name", mitk::StringProperty::New(newname) );
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 );
new_node->SetProperty("LookupTable", lut_prop );
mitk::LevelWindow lw;
lw.SetLevelWindow(0.5, 1.0);
new_node->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( lw ) );
GetDataStorage()->Add(new_node, node);
mitk::StatusBar::GetInstance()->DisplayText("Computation complete.");
}
this->GetRenderWindowPart()->RequestUpdate();
}
void QmitkDiffusionQuantificationView::TensorQuantification(int method)
{
QString status;
if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull())
{
mitk::DataNode* node = m_Controls->m_ImageBox->GetSelectedNode();
typedef mitk::TensorImage::ScalarPixelType TTensorPixelType;
typedef mitk::TensorImage::ItkTensorImageType TensorImageType;
mitk::Image* vol = static_cast<mitk::Image*>(node->GetData());
TensorImageType::Pointer itkvol = TensorImageType::New();
mitk::CastToItkImage(vol, itkvol);
std::string nodename = node->GetName();
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Computing FA for %s", nodename.c_str()).toLatin1());
typedef itk::Image< TTensorPixelType, 3 > FAImageType;
typedef itk::ShiftScaleImageFilter<FAImageType, FAImageType> ShiftScaleFilterType;
ShiftScaleFilterType::Pointer multi = ShiftScaleFilterType::New();
multi->SetShift(0.0);
multi->SetScale(m_Controls->m_ScaleImageValuesBox->value());
typedef itk::TensorDerivedMeasurementsFilter<TTensorPixelType> MeasurementsType;
mitk::LevelWindow lw;
if(method == 0) //FA
{
MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New();
measurementsCalculator->SetInput(itkvol.GetPointer() );
measurementsCalculator->SetMeasure(MeasurementsType::FA);
measurementsCalculator->Update();
multi->SetInput(measurementsCalculator->GetOutput());
nodename = QString(nodename.c_str()).append("_FA").toStdString();
lw.SetLevelWindow(0.5, 1.0);
}
else if(method == 1) //RA
{
MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New();
measurementsCalculator->SetInput(itkvol.GetPointer() );
measurementsCalculator->SetMeasure(MeasurementsType::RA);
measurementsCalculator->Update();
multi->SetInput(measurementsCalculator->GetOutput());
nodename = QString(nodename.c_str()).append("_RA").toStdString();
lw.SetLevelWindow(0.015, 0.03);
}
else if(method == 2) // AD (Axial diffusivity)
{
MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New();
measurementsCalculator->SetInput(itkvol.GetPointer() );
measurementsCalculator->SetMeasure(MeasurementsType::AD);
measurementsCalculator->Update();
multi->SetInput(measurementsCalculator->GetOutput());
nodename = QString(nodename.c_str()).append("_AD").toStdString();
lw.SetLevelWindow(0.0015, 0.003);
}
else if(method == 3) // RD (Radial diffusivity, (Lambda2+Lambda3)/2
{
MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New();
measurementsCalculator->SetInput(itkvol.GetPointer() );
measurementsCalculator->SetMeasure(MeasurementsType::RD);
measurementsCalculator->Update();
multi->SetInput(measurementsCalculator->GetOutput());
nodename = QString(nodename.c_str()).append("_RD").toStdString();
lw.SetLevelWindow(0.0015, 0.003);
}
else if(method == 4) // 1-(Lambda2+Lambda3)/(2*Lambda1)
{
MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New();
measurementsCalculator->SetInput(itkvol.GetPointer() );
measurementsCalculator->SetMeasure(MeasurementsType::CA);
measurementsCalculator->Update();
multi->SetInput(measurementsCalculator->GetOutput());
nodename = QString(nodename.c_str()).append("_CA").toStdString();
lw.SetLevelWindow(0.5, 1.0);
}
else if(method == 5) // MD (Mean Diffusivity, (Lambda1+Lambda2+Lambda3)/3 )
{
MeasurementsType::Pointer measurementsCalculator = MeasurementsType::New();
measurementsCalculator->SetInput(itkvol.GetPointer() );
measurementsCalculator->SetMeasure(MeasurementsType::MD);
measurementsCalculator->Update();
multi->SetInput(measurementsCalculator->GetOutput());
nodename = QString(nodename.c_str()).append("_MD").toStdString();
lw.SetLevelWindow(0.0015, 0.003);
}
multi->Update();
// FA TO DATATREE
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk( multi->GetOutput() );
image->SetVolume( multi->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer new_node=mitk::DataNode::New();
new_node->SetData( image );
new_node->SetProperty( "name", mitk::StringProperty::New(nodename) );
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 );
new_node->SetProperty("LookupTable", lut_prop );
new_node->SetProperty( "levelwindow", mitk::LevelWindowProperty::New( lw ) );
GetDataStorage()->Add(new_node, node);
mitk::StatusBar::GetInstance()->DisplayText("Computation complete.");
}
this->GetRenderWindowPart()->RequestUpdate();
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkDiffusionQuantificationView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkDiffusionQuantificationView.h
index a2ee861..1176fb6 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkDiffusionQuantificationView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkDiffusionQuantificationView.h
@@ -1,90 +1,90 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _QMITKDIFFUSIONQUANTIFICATIONVIEW_H_INCLUDED
#define _QMITKDIFFUSIONQUANTIFICATIONVIEW_H_INCLUDED
#include <QmitkAbstractView.h>
#include <string>
#include <itkVectorImage.h>
#include "ui_QmitkDiffusionQuantificationViewControls.h"
/*!
* \ingroup org_mitk_gui_qt_diffusionquantification_internal
*
* \brief QmitkDiffusionQuantificationView
*
* Document your class here.
*/
class QmitkDiffusionQuantificationView : public QmitkAbstractView
{
friend struct DqSelListener;
// this is needed for all Qt objects that should have a MOC object (everything that derives from QObject)
Q_OBJECT
public:
static const std::string VIEW_ID;
QmitkDiffusionQuantificationView();
virtual ~QmitkDiffusionQuantificationView();
typedef itk::VectorImage< short, 3 > ItkDwiType;
virtual void CreateQtPartControl(QWidget *parent) override;
virtual void SetFocus() override;
protected slots:
void GFA();
void FA();
void RA();
void AD();
void RD();
void ClusterAnisotropy();
void MD();
void ADC_DWI();
void MD_DWI();
void OdfQuantify(int method);
void OdfQuantification(int method) ;
void TensorQuantify(int method);
void TensorQuantification(int method) ;
void DoBallStickCalculation();
void DoMultiTensorCalculation();
void UpdateGui();
protected:
void DoAdcCalculation(bool fit);
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
Ui::QmitkDiffusionQuantificationViewControls* m_Controls;
static const float m_ScaleDAIValues;
};
#endif // _QMITKDIFFUSIONQUANTIFICATIONVIEW_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsView.cpp
index 06124be..c539c8c 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsView.cpp
@@ -1,405 +1,405 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
#include "QmitkODFDetailsView.h"
#include <QTableWidgetItem>
#include <vtkFloatArray.h>
#include <vtkPointData.h>
#include <vtkCellData.h>
#include <vtkLookupTable.h>
#include <mitkOdfNormalizationMethodProperty.h>
#include <QTextEdit>
#include <mitkTensorImage.h>
#include <QMessageBox>
#include <QmitkRenderingManager.h>
#include <mitkShImage.h>
#include <mitkImageReadAccessor.h>
#include <mitkImagePixelReadAccessor.h>
#include <mitkDiffusionFunctionCollection.h>
#include <vtkRenderWindowInteractor.h>
const std::string QmitkODFDetailsView::VIEW_ID = "org.mitk.views.odfdetails";
QmitkODFDetailsView::QmitkODFDetailsView()
: QmitkAbstractView()
, m_Controls(nullptr)
, m_OdfNormalization(0)
, m_ImageNode(nullptr)
{
}
QmitkODFDetailsView::~QmitkODFDetailsView()
{
}
void QmitkODFDetailsView::Activated()
{
}
void QmitkODFDetailsView::Deactivated()
{
}
void QmitkODFDetailsView::Visible()
{
}
void QmitkODFDetailsView::Hidden()
{
}
void QmitkODFDetailsView::SetFocus()
{
this->m_Controls->m_OverviewTextEdit->setFocus();
}
void QmitkODFDetailsView::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::QmitkODFDetailsViewControls;
m_Controls->setupUi( parent );
m_Controls->m_OdfBox->setVisible(false);
m_Controls->m_ODFRenderWidget->setVisible(false);
m_SliceChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart());
connect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged()));
}
}
void QmitkODFDetailsView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList<mitk::DataNode::Pointer>& nodes)
{
m_Controls->m_InputData->setTitle("Please Select Input Data");
m_Controls->m_InputImageLabel->setText("<font color='red'>mandatory</font>");
m_ImageNode = nullptr;
// iterate selection
for (mitk::DataNode::Pointer node: nodes)
{
if( node.IsNotNull() && (dynamic_cast<mitk::OdfImage*>(node->GetData()) || dynamic_cast<mitk::TensorImage*>(node->GetData()) || dynamic_cast<mitk::ShImage*>(node->GetData())) )
{
m_Controls->m_InputImageLabel->setText(node->GetName().c_str());
m_ImageNode = node;
}
}
UpdateOdf();
if (m_ImageNode.IsNotNull())
{
m_Controls->m_InputData->setTitle("Input Data");
}
}
void QmitkODFDetailsView::UpdateOdf()
{
try
{
m_Controls->m_OverviewBox->setVisible(true);
if (m_ImageNode.IsNull() || !this->GetRenderWindowPart())
{
m_Controls->m_ODFRenderWidget->setVisible(false);
m_Controls->m_OdfBox->setVisible(false);
m_Controls->m_OverviewBox->setVisible(false);
return;
}
// restore the input image label ( needed in case the last run resulted into an exception )
m_Controls->m_InputImageLabel->setText(m_ImageNode->GetName().c_str());
// ODF Normalization Property
mitk::OdfNormalizationMethodProperty* nmp = dynamic_cast<mitk::OdfNormalizationMethodProperty*>(m_ImageNode->GetProperty( "Normalization" ));
if(nmp)
m_OdfNormalization = nmp->GetNormalization();
bool dir_color = false;
m_ImageNode->GetBoolProperty( "DiffusionCore.Rendering.OdfVtkMapper.ColourisationModeBit", dir_color );
bool toggle_tensor = false;
m_ImageNode->GetBoolProperty( "DiffusionCore.Rendering.OdfVtkMapper.SwitchTensorView", toggle_tensor );
mitk::Point3D world = this->GetRenderWindowPart()->GetSelectedPosition();
mitk::Point3D cont_index;
mitk::Image::Pointer img = dynamic_cast<mitk::Image*>(m_ImageNode->GetData());
img->GetGeometry()->WorldToIndex(world, cont_index);
itk::Index<3> index;
index[0] = static_cast<int>(cont_index[0]+0.5);
index[1] = static_cast<int>(cont_index[1]+0.5);
index[2] = static_cast<int>(cont_index[2]+0.5);
float sum = 0;
float max = itk::NumericTraits<float>::NonpositiveMin();
float min = itk::NumericTraits<float>::max();
QString values;
QString overviewText;
// check if dynamic_cast successfull and if the crosshair position is inside of the geometry of the ODF data
// otherwise possible crash for a scenario with multiple nodes
if (dynamic_cast<mitk::OdfImage*>(m_ImageNode->GetData()) && ( m_ImageNode->GetData()->GetGeometry()->IsInside(world) ) )
{
itk::OrientationDistributionFunction<float, ODF_SAMPLING_SIZE> odf;
m_Controls->m_ODFRenderWidget->setVisible(true);
m_Controls->m_OdfBox->setVisible(true);
try
{
const mitk::OdfImage* Odf_image = dynamic_cast< mitk::OdfImage* >( m_ImageNode->GetData() );
mitk::ImagePixelReadAccessor<mitk::OdfImage::PixelType, 3> pixel_read(Odf_image, Odf_image->GetVolumeData(0));
auto pixel_data = pixel_read.GetPixelByIndex(index);
for (unsigned int i=0; i<odf.GetNumberOfComponents(); i++)
{
auto val = pixel_data[i];
odf[i] = val;
values += QString::number(i)+": "+QString::number(static_cast<double>(val))+"\n";
sum += val;
if (val>max)
max = val;
if (val<min)
min = val;
}
float mean = sum/odf.GetNumberOfComponents();
float stdev = 0;
for (unsigned int i=0; i<odf.GetNumberOfComponents(); i++)
{
float diff = odf[i] - mean;
stdev += diff*diff;
}
stdev = std::sqrt(stdev/(odf.GetNumberOfComponents()-1));
QString pos = QString::number(index[0])+", "+QString::number(index[1])+", "+QString::number(index[2]);
overviewText += "Coordinates: "+pos+"\n";
overviewText += "GFA: "+QString::number(static_cast<double>(odf.GetGeneralizedFractionalAnisotropy()))+"\n";
overviewText += "Sum: "+QString::number(static_cast<double>(sum))+"\n";
overviewText += "Mean: "+QString::number(static_cast<double>(mean))+"\n";
overviewText += "Stdev: "+QString::number(static_cast<double>(stdev))+"\n";
overviewText += "Min: "+QString::number(static_cast<double>(min))+"\n";
overviewText += "Max: "+QString::number(static_cast<double>(max))+"\n";
vnl_vector_fixed<double, 3> pd = odf.GetDirection(odf.GetPrincipalDiffusionDirectionIndex());
overviewText += "Main Diffusion:\n "+QString::number(pd[0])+"\n "+QString::number(pd[1])+"\n "+QString::number(pd[2])+"\n";
m_Controls->m_OdfValuesTextEdit->setText(values);
m_Controls->m_OverviewTextEdit->setVisible(true);
m_Controls->m_ODFDetailsWidget->SetParameters<ODF_SAMPLING_SIZE>(odf);
m_Controls->m_ODFRenderWidget->GenerateODF<ODF_SAMPLING_SIZE>(odf, m_OdfNormalization, dir_color);
m_Controls->m_OverviewTextEdit->setText(overviewText.toStdString().c_str());
}
catch( mitk::Exception &e )
{
MITK_WARN << "LOCKED : " << e.what();
m_Controls->m_ODFRenderWidget->setVisible(false);
m_Controls->m_OdfBox->setVisible(false);
m_Controls->m_OverviewTextEdit->setVisible(false);
// reset the selection
m_Controls->m_InputImageLabel->setText("<font color='green'>Click image to restore rendering!</font>");
}
}
else if (dynamic_cast<mitk::TensorImage*>(m_ImageNode->GetData()) && ( m_ImageNode->GetData()->GetGeometry()->IsInside(world) ) )
{
itk::OrientationDistributionFunction<float, 5000> odf;
m_Controls->m_ODFRenderWidget->setVisible(true);
m_Controls->m_OdfBox->setVisible(false);
const mitk::TensorImage* Odf_image = dynamic_cast< mitk::TensorImage*>(m_ImageNode->GetData());
// pixel access block
try
{
mitk::ImagePixelReadAccessor<mitk::TensorImage::PixelType, 3> pixel_read(Odf_image, Odf_image->GetVolumeData(0));
auto tensorelems = pixel_read.GetPixelByIndex(index);
TensorPixelType tensor(tensorelems);
if (!toggle_tensor)
odf.InitFromTensor(tensor);
else
{
odf.InitFromEllipsoid(tensor);
m_OdfNormalization = 1;
}
/** Array of eigen-values. */
typedef itk::FixedArray<float, 3> EigenValuesArrayType;
/** Matrix of eigen-vectors. */
typedef itk::Matrix<float, 3, 3> EigenVectorsMatrixType;
EigenValuesArrayType eigenValues;
EigenVectorsMatrixType eigenvectors;
QString pos = QString::number(index[0])+", "+QString::number(index[1])+", "+QString::number(index[2]);
overviewText += "Coordinates: "+pos+"\n";
overviewText += "FA: "+QString::number(tensor.GetFractionalAnisotropy())+"\n";
overviewText += "RA: "+QString::number(tensor.GetRelativeAnisotropy())+"\n";
overviewText += "Trace: "+QString::number(tensor.GetTrace())+"\n";
tensor.ComputeEigenAnalysis(eigenValues,eigenvectors);
overviewText += "Eigenvalues:\n "+QString::number(static_cast<double>(eigenValues[2]))+"\n "+QString::number(static_cast<double>(eigenValues[1]))+"\n "+QString::number(static_cast<double>(eigenValues[0]))+"\n";
overviewText += "Main Diffusion:\n "+QString::number(static_cast<double>(eigenvectors(2, 0)))+"\n "+QString::number(static_cast<double>(eigenvectors(2, 1)))+"\n "+QString::number(static_cast<double>(eigenvectors(2, 2)))+"\n";
overviewText += "Values:\n "+QString::number(static_cast<double>(tensorelems[0]))+"\n "+QString::number(static_cast<double>(tensorelems[1]))+"\n "+QString::number(static_cast<double>(tensorelems[2]))+"\n "+QString::number(static_cast<double>(tensorelems[3]))+"\n "+QString::number(static_cast<double>(tensorelems[4]))+"\n "+QString::number(static_cast<double>(tensorelems[5]))+"\n "+"\n";
m_Controls->m_OverviewTextEdit->setVisible(true);
m_Controls->m_ODFDetailsWidget->SetParameters<5000>(odf);
m_Controls->m_ODFRenderWidget->GenerateODF<5000>(odf, m_OdfNormalization, dir_color);
m_Controls->m_OverviewTextEdit->setText(overviewText.toStdString().c_str());
}
// end pixel access block
catch(mitk::Exception &e )
{
MITK_WARN << "LOCKED : " << e.what();
m_Controls->m_ODFRenderWidget->setVisible(false);
m_Controls->m_OdfBox->setVisible(false);
m_Controls->m_OverviewTextEdit->setVisible(false);
// reset the selection
m_Controls->m_InputImageLabel->setText("<font color='green'>Click image to restore rendering!</font>");
}
}
else if (dynamic_cast<mitk::ShImage*>(m_ImageNode->GetData()) && ( m_ImageNode->GetData()->GetGeometry()->IsInside(world) ) )
{
itk::OrientationDistributionFunction<float, 5000> odf;
m_Controls->m_ODFRenderWidget->setVisible(true);
m_Controls->m_OdfBox->setVisible(false);
mitk::ShImage::Pointer Odf_image = dynamic_cast< mitk::ShImage*>(m_ImageNode->GetData());
mitk::Image::Pointer image = dynamic_cast< mitk::ShImage*>(m_ImageNode->GetData());
QString coeff_string = "";
switch (Odf_image->ShOrder())
{
case 2:
{
auto img = mitk::convert::GetItkShFromShImage<6>(image);
auto coeffs = img->GetPixel(index);
for (unsigned int i=0; i<coeffs.Size(); ++i)
coeff_string += QString::number(static_cast<double>(coeffs[i])) + " ";
mitk::sh::SampleOdf(coeffs.GetVnlVector(), odf);
break;
}
case 4:
{
auto img = mitk::convert::GetItkShFromShImage<15>(image);
auto coeffs = img->GetPixel(index);
for (unsigned int i=0; i<coeffs.Size(); ++i)
coeff_string += QString::number(static_cast<double>(coeffs[i])) + " ";
mitk::sh::SampleOdf(coeffs.GetVnlVector(), odf);
break;
}
case 6:
{
auto img = mitk::convert::GetItkShFromShImage<28>(image);
auto coeffs = img->GetPixel(index);
for (unsigned int i=0; i<coeffs.Size(); ++i)
coeff_string += QString::number(static_cast<double>(coeffs[i])) + " ";
mitk::sh::SampleOdf(coeffs.GetVnlVector(), odf);
break;
}
case 8:
{
auto img = mitk::convert::GetItkShFromShImage<45>(image);
auto coeffs = img->GetPixel(index);
for (unsigned int i=0; i<coeffs.Size(); ++i)
coeff_string += QString::number(static_cast<double>(coeffs[i])) + " ";
mitk::sh::SampleOdf(coeffs.GetVnlVector(), odf);
break;
}
case 10:
{
auto img = mitk::convert::GetItkShFromShImage<66>(image);
auto coeffs = img->GetPixel(index);
for (unsigned int i=0; i<coeffs.Size(); ++i)
coeff_string += QString::number(static_cast<double>(coeffs[i])) + " ";
mitk::sh::SampleOdf(coeffs.GetVnlVector(), odf);
break;
}
case 12:
{
auto img = mitk::convert::GetItkShFromShImage<91>(image);
auto coeffs = img->GetPixel(index);
for (unsigned int i=0; i<coeffs.Size(); ++i)
coeff_string += QString::number(static_cast<double>(coeffs[i])) + " ";
mitk::sh::SampleOdf(coeffs.GetVnlVector(), odf);
break;
}
default :
mitkThrow() << "SH order larger 12 not supported";
}
for (unsigned int i=0; i<odf.GetNumberOfComponents(); i++)
{
auto val = odf[i];
values += QString::number(i)+": "+QString::number(static_cast<double>(val))+"\n";
sum += val;
if (val>max)
max = val;
if (val<min)
min = val;
}
float mean = sum/odf.GetNumberOfComponents();
float stdev = 0;
for (unsigned int i=0; i<odf.GetNumberOfComponents(); i++)
{
float val = odf[i];
float diff = val - mean;
stdev += diff*diff;
}
stdev = std::sqrt(stdev/(odf.GetNumberOfComponents()-1));
QString pos = QString::number(index[0])+", "+QString::number(index[1])+", "+QString::number(index[2]);
overviewText += "Coordinates: "+pos+"\n";
overviewText += "SH order: "+QString::number(static_cast<double>(Odf_image->ShOrder()))+"\n";
overviewText += "Num. Coefficients: "+QString::number(static_cast<double>(Odf_image->NumCoefficients()))+"\n";
overviewText += "Coefficients: "+coeff_string+"\n";
overviewText += "GFA: "+QString::number(static_cast<double>(odf.GetGeneralizedFractionalAnisotropy()))+"\n";
overviewText += "Sum: "+QString::number(static_cast<double>(sum))+"\n";
overviewText += "Mean: "+QString::number(static_cast<double>(mean))+"\n";
overviewText += "Stdev: "+QString::number(static_cast<double>(stdev))+"\n";
overviewText += "Min: "+QString::number(static_cast<double>(min))+"\n";
overviewText += "Max: "+QString::number(static_cast<double>(max))+"\n";
vnl_vector_fixed<double, 3> pd = odf.GetDirection(odf.GetPrincipalDiffusionDirectionIndex());
overviewText += "Main Diffusion:\n "+QString::number(pd[0])+"\n "+QString::number(pd[1])+"\n "+QString::number(pd[2])+"\n";
m_Controls->m_OdfValuesTextEdit->setText(values);
m_Controls->m_OverviewTextEdit->setVisible(true);
m_Controls->m_ODFDetailsWidget->SetParameters<5000>(odf);
m_Controls->m_ODFRenderWidget->GenerateODF<5000>(odf, m_OdfNormalization, dir_color);
m_Controls->m_OverviewTextEdit->setText(overviewText.toStdString().c_str());
}
else
{
m_Controls->m_ODFRenderWidget->setVisible(false);
m_Controls->m_OdfBox->setVisible(false);
overviewText += "Please reinit image geometry.\n";
}
}
catch(...)
{
QMessageBox::critical(nullptr, "Error", "Data could not be analyzed. The image might be corrupted.");
}
}
void QmitkODFDetailsView::OnSliceChanged()
{
UpdateOdf();
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsView.h
index 133f8c4..f5a71d8 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkODFDetailsView.h
@@ -1,98 +1,98 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _QMITKQmitkODFDetailsView_H_INCLUDED
#define _QMITKQmitkODFDetailsView_H_INCLUDED
#include <berryISelectionListener.h>
#include <QmitkAbstractView.h>
#include "mitkILifecycleAwarePart.h"
#include "ui_QmitkODFDetailsViewControls.h"
#include <itkVectorImage.h>
#include <itkImage.h>
#include <itkOrientationDistributionFunction.h>
#include <mitkOdfImage.h>
#include <vtkTransform.h>
#include <vtkDoubleArray.h>
#include <vtkOdfSource.h>
#include <vtkSmartPointer.h>
#include <QmitkRenderWindow.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderer.h>
#include <vtkCamera.h>
#include <itkDiffusionTensor3D.h>
#include <QmitkSliceNavigationListener.h>
#include <mitkTensorImage.h>
/*!
\brief View displaying details of the orientation distribution function in the voxel at the current crosshair position.
*/
class QmitkODFDetailsView : 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;
QmitkODFDetailsView();
virtual ~QmitkODFDetailsView();
typedef mitk::OdfImage::ScalarPixelType TOdfPixelType;
typedef mitk::OdfImage::PixelType OdfVectorType;
typedef mitk::OdfImage::ItkOdfImageType OdfVectorImgType;
typedef mitk::TensorImage::PixelType TensorPixelType;
typedef mitk::TensorImage::ItkTensorImageType TensorImageType;
virtual void CreateQtPartControl(QWidget *parent) override;
protected slots:
void OnSliceChanged();
protected:
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
virtual void SetFocus() override;
virtual void Activated() override;
virtual void Deactivated() override;
virtual void Visible() override;
virtual void Hidden() override;
void UpdateOdf(); ///< called if slice position or datamanager selection has changed
Ui::QmitkODFDetailsViewControls* m_Controls;
int m_OdfNormalization; ///< normalization method defined in the visualization view
mitk::DataNode::Pointer m_ImageNode;
QmitkSliceNavigationListener m_SliceChangeListener;
};
#endif // _QmitkODFDetailsView_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkQBallReconstructionView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkQBallReconstructionView.cpp
index 9050fe3..38859e1 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkQBallReconstructionView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkQBallReconstructionView.cpp
@@ -1,808 +1,808 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
//#define MBILOG_ENABLE_DEBUG
#include "QmitkQBallReconstructionView.h"
// qt includes
#include <QMessageBox>
// itk includes
#include "itkTimeProbe.h"
// mitk includes
#include "mitkProgressBar.h"
#include "mitkStatusBar.h"
#include "mitkNodePredicateDataType.h"
#include "QmitkDataStorageComboBox.h"
#include "itkDiffusionQballReconstructionImageFilter.h"
#include "itkAnalyticalDiffusionQballReconstructionImageFilter.h"
#include "itkDiffusionMultiShellQballReconstructionImageFilter.h"
#include "itkVectorContainer.h"
#include "itkB0ImageExtractionImageFilter.h"
#include <itkBinaryThresholdImageFilter.h>
#include "mitkOdfImage.h"
#include "mitkProperties.h"
#include "mitkVtkResliceInterpolationProperty.h"
#include "mitkLookupTable.h"
#include "mitkLookupTableProperty.h"
#include "mitkTransferFunction.h"
#include "mitkTransferFunctionProperty.h"
#include "mitkDataNodeObject.h"
#include "mitkOdfNormalizationMethodProperty.h"
#include "mitkOdfScaleByProperty.h"
#include <mitkImageCast.h>
#include "mitkDiffusionImagingConfigure.h"
#include <mitkNodePredicateIsDWI.h>
#include "berryIStructuredSelection.h"
#include "berryIWorkbenchWindow.h"
#include "berryISelectionService.h"
#include <mitkShImage.h>
#include <boost/version.hpp>
#include <itkShToOdfImageFilter.h>
#include <mitkImageCast.h>
#include <mitkDiffusionFunctionCollection.h>
const std::string QmitkQBallReconstructionView::VIEW_ID = "org.mitk.views.qballreconstruction";
typedef float TTensorPixelType;
const int QmitkQBallReconstructionView::nrconvkernels = 252;
struct QbrShellSelection
{
typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType;
typedef mitk::DiffusionPropertyHelper::BValueMapType BValueMapType;
typedef itk::VectorImage< DiffusionPixelType, 3 > ITKDiffusionImageType;
QmitkQBallReconstructionView* m_View;
mitk::DataNode * m_Node;
std::string m_NodeName;
std::vector<QCheckBox *> m_CheckBoxes;
QLabel * m_Label;
mitk::Image * m_Image;
QbrShellSelection(QmitkQBallReconstructionView* view, mitk::DataNode * node)
: m_View(view),
m_Node(node),
m_NodeName(node->GetName())
{
m_Image = dynamic_cast<mitk::Image * > (node->GetData());
if(!m_Image)
{
MITK_ERROR << "QmitkQBallReconstructionView::QbrShellSelection : no image selected";
return;
}
bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast<mitk::Image *>(m_Node->GetData())) );
if( !isDiffusionImage )
{
MITK_ERROR <<
"QmitkQBallReconstructionView::QbrShellSelection : selected image contains no diffusion information";
return;
}
GenerateCheckboxes();
}
void GenerateCheckboxes()
{
BValueMapType origMap = mitk::DiffusionPropertyHelper::GetBValueMap(m_Image);
BValueMapType::iterator itStart = origMap.begin();
itStart++;
BValueMapType::iterator itEnd = origMap.end();
m_Label = new QLabel(m_NodeName.c_str());
m_Label->setVisible(true);
m_View->m_Controls->m_QBallSelectionBox->layout()->addWidget(m_Label);
for(BValueMapType::iterator it = itStart ; it!= itEnd; it++)
{
QCheckBox * box = new QCheckBox(QString::number(it->first));
m_View->m_Controls->m_QBallSelectionBox->layout()->addWidget(box);
box->setChecked(true);
box->setCheckable(true);
// box->setVisible(true);
m_CheckBoxes.push_back(box);
}
}
void SetVisible(bool vis)
{
foreach(QCheckBox * box, m_CheckBoxes)
{
box->setVisible(vis);
}
}
BValueMapType GetBValueSelctionMap()
{
BValueMapType inputMap = mitk::DiffusionPropertyHelper::GetBValueMap(m_Image);
BValueMapType outputMap;
unsigned int val = 0;
if(inputMap.find(0) == inputMap.end()){
return outputMap;
}else{
outputMap[val] = inputMap[val];
}
foreach(QCheckBox * box, m_CheckBoxes)
{
if(box->isChecked()){
val = box->text().toUInt();
outputMap[val] = inputMap[val];
MITK_INFO << val;
}
}
return outputMap;
}
~QbrShellSelection()
{
m_View->m_Controls->m_QBallSelectionBox->layout()->removeWidget(m_Label);
delete m_Label;
for(std::vector<QCheckBox *>::iterator it = m_CheckBoxes.begin() ; it!= m_CheckBoxes.end(); it++)
{
m_View->m_Controls->m_QBallSelectionBox->layout()->removeWidget((*it));
delete (*it);
}
m_CheckBoxes.clear();
}
};
QmitkQBallReconstructionView::QmitkQBallReconstructionView()
: QmitkAbstractView(),
m_Controls(nullptr)
{
}
QmitkQBallReconstructionView::~QmitkQBallReconstructionView()
{
}
void QmitkQBallReconstructionView::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
// create GUI widgets
m_Controls = new Ui::QmitkQBallReconstructionViewControls;
m_Controls->setupUi(parent);
this->CreateConnections();
QStringList items;
items << "2" << "4" << "6" << "8" << "10" << "12";
m_Controls->m_QBallReconstructionMaxLLevelComboBox->addItems(items);
m_Controls->m_QBallReconstructionMaxLLevelComboBox->setCurrentIndex(1);
MethodChoosen(m_Controls->m_QBallReconstructionMethodComboBox->currentIndex());
}
}
void QmitkQBallReconstructionView::SetFocus()
{
}
void QmitkQBallReconstructionView::CreateConnections()
{
if ( m_Controls )
{
connect( static_cast<QObject*>(m_Controls->m_ButtonStandard), SIGNAL(clicked()), this, SLOT(ReconstructStandard()) );
connect( static_cast<QObject*>(m_Controls->m_QBallReconstructionMethodComboBox), SIGNAL(currentIndexChanged(int)), this, SLOT(MethodChoosen(int)) );
connect( static_cast<QObject*>(m_Controls->m_QBallReconstructionThreasholdEdit), SIGNAL(valueChanged(int)), this, SLOT(PreviewThreshold(int)) );
connect( static_cast<QObject*>(m_Controls->m_ConvertButton), SIGNAL(clicked()), this, SLOT(ConvertShImage()) );
m_Controls->m_ImageBox->SetDataStorage(this->GetDataStorage());
mitk::NodePredicateIsDWI::Pointer isDwi = mitk::NodePredicateIsDWI::New();
m_Controls->m_ImageBox->SetPredicate( isDwi );
m_Controls->m_ShImageBox->SetDataStorage(this->GetDataStorage());
mitk::TNodePredicateDataType<mitk::ShImage>::Pointer isSh = mitk::TNodePredicateDataType<mitk::ShImage>::New();
m_Controls->m_ShImageBox->SetPredicate( isSh );
connect( static_cast<QObject*>(m_Controls->m_ImageBox), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()));
connect( static_cast<QObject*>(m_Controls->m_ShImageBox), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()));
UpdateGui();
}
}
void QmitkQBallReconstructionView::ConvertShImage()
{
if (m_Controls->m_ShImageBox->GetSelectedNode().IsNotNull())
{
mitk::Image::Pointer mitkImg = dynamic_cast<mitk::Image*>(m_Controls->m_ShImageBox->GetSelectedNode()->GetData());
auto img = mitk::convert::GetOdfFromShImage(mitkImg);
mitk::DataNode::Pointer node= mitk::DataNode::New();
node->SetData( img );
node->SetName(m_Controls->m_ShImageBox->GetSelectedNode()->GetName());
GetDataStorage()->Add(node, m_Controls->m_ShImageBox->GetSelectedNode());
}
}
void QmitkQBallReconstructionView::UpdateGui()
{
m_Controls->m_ButtonStandard->setEnabled(false);
if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull())
{
m_Controls->m_ButtonStandard->setEnabled(true);
GenerateShellSelectionUI(m_Controls->m_ImageBox->GetSelectedNode());
}
m_Controls->m_ConvertButton->setEnabled(m_Controls->m_ShImageBox->GetSelectedNode().IsNotNull());
}
void QmitkQBallReconstructionView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList<mitk::DataNode::Pointer>& /*nodes*/)
{
UpdateGui();
}
void QmitkQBallReconstructionView::Activated()
{
}
void QmitkQBallReconstructionView::Deactivated()
{
}
void QmitkQBallReconstructionView::Visible()
{
}
void QmitkQBallReconstructionView::Hidden()
{
}
void QmitkQBallReconstructionView::ReconstructStandard()
{
int index = m_Controls->m_QBallReconstructionMethodComboBox->currentIndex();
switch(index)
{
case 0:
{
// Numerical
Reconstruct(0,0);
break;
}
case 1:
{
// Standard
Reconstruct(1,0);
break;
}
case 2:
{
// Solid Angle
Reconstruct(1,6);
break;
}
case 3:
{
// ADC
Reconstruct(1,4);
break;
}
case 4:
{
// Raw Signal
Reconstruct(1,5);
break;
}
case 5:
{
// Q-Ball reconstruction
Reconstruct(2,0);
break;
}
}
}
void QmitkQBallReconstructionView::MethodChoosen(int method)
{
m_Controls->m_QBallSelectionBox->setHidden(true);
m_Controls->m_OutputOdfImage->setHidden(true);
if (method==0)
m_Controls->m_ShFrame->setVisible(false);
else
m_Controls->m_ShFrame->setVisible(true);
switch(method)
{
case 0:
m_Controls->m_Description->setText("Numerical recon. (Tuch 2004)");
break;
case 1:
m_Controls->m_Description->setText("Spherical harmonics recon. (Descoteaux 2007)");
m_Controls->m_OutputOdfImage->setHidden(false);
break;
case 2:
m_Controls->m_Description->setText("SH recon. with solid angle consideration (Aganj 2009)");
m_Controls->m_OutputOdfImage->setHidden(false);
break;
case 3:
m_Controls->m_Description->setText("SH solid angle with non-neg. constraint (Goh 2009)");
m_Controls->m_OutputOdfImage->setHidden(false);
break;
case 4:
m_Controls->m_Description->setText("SH recon. of the plain ADC-profiles");
m_Controls->m_OutputOdfImage->setHidden(false);
break;
case 5:
m_Controls->m_Description->setText("SH recon. of the raw diffusion signal");
m_Controls->m_OutputOdfImage->setHidden(false);
break;
case 6:
m_Controls->m_Description->setText("SH recon. of the multi shell diffusion signal (Aganj 2010)");
m_Controls->m_QBallSelectionBox->setHidden(false);
m_Controls->m_OutputOdfImage->setHidden(false);
break;
}
}
void QmitkQBallReconstructionView::Reconstruct(int method, int normalization)
{
if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull())
{
if(method == 0)
{
NumericalQBallReconstruction(m_Controls->m_ImageBox->GetSelectedNode(), normalization);
}
else if(method == 1)
{
AnalyticalQBallReconstruction(m_Controls->m_ImageBox->GetSelectedNode(), normalization);
}
else if(method == 2)
{
MultiQBallReconstruction(m_Controls->m_ImageBox->GetSelectedNode());
}
}
}
void QmitkQBallReconstructionView::NumericalQBallReconstruction(mitk::DataNode::Pointer node, int normalization)
{
try
{
mitk::Image* vols = static_cast<mitk::Image*>(node->GetData());
std::string nodename = node->GetName();
typedef itk::DiffusionQballReconstructionImageFilter
<DiffusionPixelType, DiffusionPixelType, TTensorPixelType, ODF_SAMPLING_SIZE>
QballReconstructionImageFilterType;
ITKDiffusionImageType::Pointer itkVectorImagePointer = ITKDiffusionImageType::New();
mitk::CastToItkImage(vols, itkVectorImagePointer);
QballReconstructionImageFilterType::Pointer filter = QballReconstructionImageFilterType::New();
filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(vols));
filter->SetGradientImage(mitk::DiffusionPropertyHelper::GetGradientContainer(vols), itkVectorImagePointer);
filter->SetThreshold( static_cast<short>(m_Controls->m_QBallReconstructionThreasholdEdit->value()) );
std::string nodePostfix;
switch(normalization)
{
case 0:
{
filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_STANDARD);
nodePostfix = "_Numerical_Qball";
break;
}
case 1:
{
filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_B_ZERO_B_VALUE);
nodePostfix = "_Numerical_ZeroBvalueNormalization_Qball";
break;
}
case 2:
{
filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_B_ZERO);
nodePostfix = "_NumericalQball_ZeroNormalization_Qball";
break;
}
case 3:
{
filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_NONE);
nodePostfix = "_NumericalQball_NoNormalization_Qball";
break;
}
default:
{
filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_STANDARD);
nodePostfix = "_NumericalQball_Qball";
}
}
filter->Update();
// ODFs TO DATATREE
mitk::OdfImage::Pointer image = mitk::OdfImage::New();
image->InitializeByItk( filter->GetOutput() );
image->SetVolume( filter->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer new_node = mitk::DataNode::New();
new_node->SetData( image );
new_node->SetName(nodename+nodePostfix);
mitk::ProgressBar::GetInstance()->Progress();
GetDataStorage()->Add(new_node, node);
this->GetRenderWindowPart()->RequestUpdate();
}
catch (itk::ExceptionObject &ex)
{
MITK_INFO << ex ;
QMessageBox::information(nullptr, "Reconstruction not possible:", ex.GetDescription());
return ;
}
}
void QmitkQBallReconstructionView::AnalyticalQBallReconstruction( mitk::DataNode::Pointer node, int normalization)
{
try
{
auto lambda = m_Controls->m_QBallReconstructionLambdaLineEdit->value();
switch(m_Controls->m_QBallReconstructionMaxLLevelComboBox->currentIndex())
{
case 0:
{
TemplatedAnalyticalQBallReconstruction<2>(node, lambda, normalization);
break;
}
case 1:
{
TemplatedAnalyticalQBallReconstruction<4>(node, lambda, normalization);
break;
}
case 2:
{
TemplatedAnalyticalQBallReconstruction<6>(node, lambda, normalization);
break;
}
case 3:
{
TemplatedAnalyticalQBallReconstruction<8>(node, lambda, normalization);
break;
}
case 4:
{
TemplatedAnalyticalQBallReconstruction<10>(node, lambda, normalization);
break;
}
case 5:
{
TemplatedAnalyticalQBallReconstruction<12>(node, lambda, normalization);
break;
}
}
this->GetRenderWindowPart()->RequestUpdate();
}
catch (itk::ExceptionObject &ex)
{
MITK_INFO << ex;
QMessageBox::information(nullptr, "Reconstruction not possible:", ex.GetDescription());
return;
}
}
template<int L>
void QmitkQBallReconstructionView::TemplatedAnalyticalQBallReconstruction(mitk::DataNode* dataNodePointer, double lambda, int normalization)
{
typedef itk::AnalyticalDiffusionQballReconstructionImageFilter
<DiffusionPixelType,DiffusionPixelType,TTensorPixelType,L,ODF_SAMPLING_SIZE> FilterType;
typename FilterType::Pointer filter = FilterType::New();
mitk::Image* vols = dynamic_cast<mitk::Image*>(dataNodePointer->GetData());
ITKDiffusionImageType::Pointer itkVectorImagePointer = ITKDiffusionImageType::New();
mitk::CastToItkImage(vols, itkVectorImagePointer);
filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(vols));
filter->SetGradientImage(mitk::DiffusionPropertyHelper::GetGradientContainer(vols), itkVectorImagePointer);
filter->SetThreshold( static_cast<short>(m_Controls->m_QBallReconstructionThreasholdEdit->value()) );
filter->SetLambda(lambda);
std::string nodePostfix;
switch(normalization)
{
case 0:
{
filter->SetNormalizationMethod(FilterType::QBAR_STANDARD);
nodePostfix = "_Qball";
break;
}
case 1:
{
filter->SetNormalizationMethod(FilterType::QBAR_B_ZERO_B_VALUE);
nodePostfix = "_1_Qball";
break;
}
case 2:
{
filter->SetNormalizationMethod(FilterType::QBAR_B_ZERO);
nodePostfix = "_2_Qball";
break;
}
case 3:
{
filter->SetNormalizationMethod(FilterType::QBAR_NONE);
nodePostfix = "_3_Qball";
break;
}
case 4:
{
filter->SetNormalizationMethod(FilterType::QBAR_ADC_ONLY);
nodePostfix = "_AdcProfile";
break;
}
case 5:
{
filter->SetNormalizationMethod(FilterType::QBAR_RAW_SIGNAL);
nodePostfix = "_RawSignal";
break;
}
case 6:
{
filter->SetNormalizationMethod(FilterType::QBAR_SOLID_ANGLE);
nodePostfix = "_CSA_Qball";
break;
}
case 7:
{
filter->SetNormalizationMethod(FilterType::QBAR_NONNEG_SOLID_ANGLE);
nodePostfix = "_NonNegCSA_Qball";
break;
}
default:
{
filter->SetNormalizationMethod(FilterType::QBAR_STANDARD);
}
}
filter->Update();
mitk::Image::Pointer coeffsImage = dynamic_cast<mitk::Image*>(mitk::ShImage::New().GetPointer());
coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() );
coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() );
mitk::DataNode::Pointer coeffsNode = mitk::DataNode::New();
coeffsNode->SetData( coeffsImage );
coeffsNode->SetProperty( "name", mitk::StringProperty::New(dataNodePointer->GetName() + nodePostfix + "_SH") );
GetDataStorage()->Add(coeffsNode, dataNodePointer);
// ODFs TO DATATREE
if(m_Controls->m_OutputOdfImage->isChecked())
{
mitk::OdfImage::Pointer image = mitk::OdfImage::New();
image->InitializeByItk( filter->GetOutput() );
image->SetVolume( filter->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( image );
node->SetName(dataNodePointer->GetName() + nodePostfix + "_Sampeld");
GetDataStorage()->Add(node, coeffsNode);
}
}
void QmitkQBallReconstructionView::MultiQBallReconstruction(mitk::DataNode::Pointer node)
{
try
{
auto lambda = m_Controls->m_QBallReconstructionLambdaLineEdit->value();
switch(m_Controls->m_QBallReconstructionMaxLLevelComboBox->currentIndex())
{
case 0:
{
TemplatedMultiQBallReconstruction<2>(lambda, node);
break;
}
case 1:
{
TemplatedMultiQBallReconstruction<4>(lambda, node);
break;
}
case 2:
{
TemplatedMultiQBallReconstruction<6>(lambda, node);
break;
}
case 3:
{
TemplatedMultiQBallReconstruction<8>(lambda, node);
break;
}
case 4:
{
TemplatedMultiQBallReconstruction<10>(lambda, node);
break;
}
case 5:
{
TemplatedMultiQBallReconstruction<12>(lambda, node);
break;
}
}
}
catch (itk::ExceptionObject &ex)
{
MITK_INFO << ex ;
QMessageBox::information(nullptr, "Reconstruction not possible:", ex.GetDescription());
return ;
}
}
template<int L>
void QmitkQBallReconstructionView::TemplatedMultiQBallReconstruction(double lambda, mitk::DataNode* dataNodePointer)
{
typedef itk::DiffusionMultiShellQballReconstructionImageFilter
<DiffusionPixelType,DiffusionPixelType,TTensorPixelType,L,ODF_SAMPLING_SIZE> FilterType;
typename FilterType::Pointer filter = FilterType::New();
std::string nodename;
dataNodePointer->GetStringProperty("name",nodename);
mitk::Image* dwi = dynamic_cast<mitk::Image*>(dataNodePointer->GetData());
BValueMapType currSelectionMap = m_ShellSelectorMap[dataNodePointer]->GetBValueSelctionMap();
if(currSelectionMap.size() != 4)// || currSelectionMap.find(0) != currSelectionMap.end())
{
QMessageBox::information(nullptr, "Reconstruction not possible:" ,QString("Only three equidistant shells are supported. (ImageName: " + QString(nodename.c_str()) + ")"));
return;
}
BValueMapType::reverse_iterator it1 = currSelectionMap.rbegin();
BValueMapType::reverse_iterator it2 = currSelectionMap.rbegin();
++it2;
// Get average distance
int avdistance = 0;
for(; it2 != currSelectionMap.rend(); ++it1,++it2)
avdistance += static_cast<int>(it1->first - it2->first);
avdistance /= currSelectionMap.size()-1;
// Check if all shells are using the same averae distance
it1 = currSelectionMap.rbegin();
it2 = currSelectionMap.rbegin();
++it2;
for(; it2 != currSelectionMap.rend(); ++it1,++it2)
{
if(avdistance != static_cast<int>(it1->first - it2->first))
{
QMessageBox::information(nullptr, "Reconstruction not possible:" ,QString("Selected Shells are not in a equidistant configuration. (ImageName: " + QString(nodename.c_str()) + ")"));
return;
}
}
ITKDiffusionImageType::Pointer itkVectorImagePointer = ITKDiffusionImageType::New();
mitk::CastToItkImage(dwi, itkVectorImagePointer);
filter->SetBValueMap(m_ShellSelectorMap[dataNodePointer]->GetBValueSelctionMap());
filter->SetGradientImage(mitk::DiffusionPropertyHelper::GetGradientContainer(dwi), itkVectorImagePointer, mitk::DiffusionPropertyHelper::GetReferenceBValue(dwi));
filter->SetThreshold( static_cast<short>(m_Controls->m_QBallReconstructionThreasholdEdit->value()) );
filter->SetLambda(lambda);
filter->Update();
mitk::Image::Pointer coeffsImage = dynamic_cast<mitk::Image*>(mitk::ShImage::New().GetPointer());
coeffsImage->InitializeByItk( filter->GetCoefficientImage().GetPointer() );
coeffsImage->SetVolume( filter->GetCoefficientImage()->GetBufferPointer() );
mitk::DataNode::Pointer coeffsNode=mitk::DataNode::New();
coeffsNode->SetData( coeffsImage );
coeffsNode->SetProperty( "name", mitk::StringProperty::New(dataNodePointer->GetName() + "_SH_MultiShell_Qball_SH") );
GetDataStorage()->Add(coeffsNode, dataNodePointer);
if(m_Controls->m_OutputOdfImage->isChecked())
{
// ODFs TO DATATREE
mitk::OdfImage::Pointer image = mitk::OdfImage::New();
image->InitializeByItk( filter->GetOutput() );
image->SetVolume( filter->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( image );
node->SetName(dataNodePointer->GetName() + "_SH_MultiShell_Qball_Sampled");
GetDataStorage()->Add(node, coeffsNode);
}
}
void QmitkQBallReconstructionView::GenerateShellSelectionUI(mitk::DataNode::Pointer node)
{
std::map<const mitk::DataNode * , QbrShellSelection * > tempMap;
if(m_ShellSelectorMap.find( node.GetPointer() ) != m_ShellSelectorMap.end())
{
tempMap[node.GetPointer()] = m_ShellSelectorMap[node.GetPointer()];
m_ShellSelectorMap.erase(node.GetPointer());
}
else
{
tempMap[node.GetPointer()] = new QbrShellSelection(this, node );
tempMap[node.GetPointer()]->SetVisible(true);
}
for(std::map<const mitk::DataNode * , QbrShellSelection * >::iterator it = m_ShellSelectorMap.begin(); it != m_ShellSelectorMap.end();it ++)
{
delete it->second;
}
m_ShellSelectorMap.clear();
m_ShellSelectorMap = tempMap;
}
void QmitkQBallReconstructionView::PreviewThreshold(short threshold)
{
if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull())
{
mitk::Image* vols = static_cast<mitk::Image*>(m_Controls->m_ImageBox->GetSelectedNode()->GetData());
// Extract b0 image
ITKDiffusionImageType::Pointer itkVectorImagePointer = ITKDiffusionImageType::New();
mitk::CastToItkImage(vols, itkVectorImagePointer);
typedef itk::B0ImageExtractionImageFilter<short, short> FilterType;
FilterType::Pointer filterB0 = FilterType::New();
filterB0->SetInput( itkVectorImagePointer );
filterB0->SetDirections(mitk::DiffusionPropertyHelper::GetGradientContainer(vols));
filterB0->Update();
mitk::Image::Pointer mitkImage = mitk::Image::New();
typedef itk::Image<short, 3> ImageType;
typedef itk::Image<short, 3> SegmentationType;
typedef itk::BinaryThresholdImageFilter<ImageType, SegmentationType> ThresholdFilterType;
// apply threshold
ThresholdFilterType::Pointer filterThreshold = ThresholdFilterType::New();
filterThreshold->SetInput(filterB0->GetOutput());
filterThreshold->SetLowerThreshold(threshold);
filterThreshold->SetInsideValue(0);
filterThreshold->SetOutsideValue(1); // mark cut off values red
filterThreshold->Update();
mitkImage->InitializeByItk( filterThreshold->GetOutput() );
mitkImage->SetVolume( filterThreshold->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer node;
if (this->GetDataStorage()->GetNamedDerivedNode("ThresholdOverlay", m_Controls->m_ImageBox->GetSelectedNode()))
{
node = this->GetDataStorage()->GetNamedDerivedNode("ThresholdOverlay", m_Controls->m_ImageBox->GetSelectedNode());
}
else
{
// create a new node, to show thresholded values
node = mitk::DataNode::New();
GetDataStorage()->Add( node, m_Controls->m_ImageBox->GetSelectedNode() );
node->SetProperty( "name", mitk::StringProperty::New("ThresholdOverlay"));
node->SetBoolProperty("helper object", true);
}
node->SetData( mitkImage );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkQBallReconstructionView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkQBallReconstructionView.h
index 9740b21..206967e 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkQBallReconstructionView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkQBallReconstructionView.h
@@ -1,133 +1,133 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _QMITKQBALLRECONSTRUCTIONVIEW_H_INCLUDED
#define _QMITKQBALLRECONSTRUCTIONVIEW_H_INCLUDED
#include <QmitkAbstractView.h>
#include <mitkILifecycleAwarePart.h>
#include <string>
#include "ui_QmitkQBallReconstructionViewControls.h"
#include <mitkImage.h>
#include <mitkDiffusionPropertyHelper.h>
#include <itkVectorImage.h>
#include <mitkShImage.h>
typedef short DiffusionPixelType;
struct QbrSelListener;
struct QbrShellSelection;
/*!
* \ingroup org_mitk_gui_qt_qballreconstruction_internal
*
* \brief QmitkQBallReconstructionView
*
* Document your class here.
*/
class QmitkQBallReconstructionView : public QmitkAbstractView, public mitk::ILifecycleAwarePart
{
friend struct QbrSelListener;
friend struct QbrShellSelection;
typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType;
typedef mitk::DiffusionPropertyHelper::BValueMapType BValueMapType;
typedef itk::VectorImage< DiffusionPixelType, 3 > ITKDiffusionImageType;
// this is needed for all Qt objects that should have a MOC object (everything that derives from QObject)
Q_OBJECT
public:
static const std::string VIEW_ID;
QmitkQBallReconstructionView();
virtual ~QmitkQBallReconstructionView();
virtual void CreateQtPartControl(QWidget *parent) override;
/// \brief Creation of the connections of main and control widget
virtual void CreateConnections();
///
/// Sets the focus to an internal widget.
///
virtual void SetFocus() override;
/// \brief Called when the view gets activated
virtual void Activated() override;
/// \brief Called when the view gets deactivated
virtual void Deactivated() override;
/// \brief Called when the view becomes visible
virtual void Visible() override;
/// \brief Called when the view becomes hidden
virtual void Hidden() override;
static const int nrconvkernels;
protected slots:
void UpdateGui();
void ReconstructStandard();
void ConvertShImage();
void MethodChoosen(int method);
void Reconstruct(int method, int normalization);
void NumericalQBallReconstruction(mitk::DataNode::Pointer node, int normalization);
void AnalyticalQBallReconstruction(mitk::DataNode::Pointer node, int normalization);
void MultiQBallReconstruction(mitk::DataNode::Pointer node);
/**
* @brief PreviewThreshold Generates a preview of the values that are cut off by the thresholds
* @param threshold
*/
void PreviewThreshold(short threshold);
protected:
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
Ui::QmitkQBallReconstructionViewControls* m_Controls;
template<int L>
void TemplatedAnalyticalQBallReconstruction(mitk::DataNode* dataNodePointer, double lambda, int normalization);
template<int L>
void TemplatedMultiQBallReconstruction(double lambda, mitk::DataNode*);
private:
std::map< const mitk::DataNode *, QbrShellSelection * > m_ShellSelectorMap;
void GenerateShellSelectionUI(mitk::DataNode::Pointer node);
};
#endif // _QMITKQBALLRECONSTRUCTIONVIEW_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkTensorReconstructionView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkTensorReconstructionView.cpp
index b7c44b9..5952e52 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkTensorReconstructionView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkTensorReconstructionView.cpp
@@ -1,931 +1,931 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkTensorReconstructionView.h"
#include "mitkDiffusionImagingConfigure.h"
// qt includes
#include <QMessageBox>
#include <QImage>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
#include <QGraphicsLinearLayout>
// itk includes
#include "itkTimeProbe.h"
//#include "itkTensor.h"
// mitk includes
#include "mitkProgressBar.h"
#include "mitkStatusBar.h"
#include "mitkNodePredicateDataType.h"
#include "QmitkDataStorageComboBox.h"
#include "mitkTeemDiffusionTensor3DReconstructionImageFilter.h"
#include "itkDiffusionTensor3DReconstructionImageFilter.h"
#include "itkTensorImageToDiffusionImageFilter.h"
#include "itkPointShell.h"
#include "itkVector.h"
#include "itkB0ImageExtractionImageFilter.h"
#include "itkTensorReconstructionWithEigenvalueCorrectionFilter.h"
#include "mitkImageCast.h"
#include "mitkImageAccessByItk.h"
#include <itkBinaryThresholdImageFilter.h>
#include <mitkImageVtkMapper2D.h>
#include "mitkProperties.h"
#include "mitkDataNodeObject.h"
#include "mitkOdfNormalizationMethodProperty.h"
#include "mitkOdfScaleByProperty.h"
#include "mitkLookupTableProperty.h"
#include "mitkLookupTable.h"
#include "mitkImageStatisticsHolder.h"
#include <mitkITKImageImport.h>
#include <itkTensorImageToOdfImageFilter.h>
#include <itkResidualImageFilter.h>
#include <berryIWorkbenchWindow.h>
#include <berryISelectionService.h>
#include <mitkImageVtkMapper2D.h>
#include <mitkNodePredicateIsDWI.h>
#include <mitkNodePredicateDataType.h>
const std::string QmitkTensorReconstructionView::VIEW_ID = "org.mitk.views.tensorreconstruction";
typedef mitk::TensorImage::ScalarPixelType TTensorPixelType;
typedef mitk::TensorImage::PixelType TensorPixelType;
typedef mitk::TensorImage::ItkTensorImageType TensorImageType;
using namespace berry;
QmitkTensorReconstructionView::QmitkTensorReconstructionView()
: QmitkAbstractView(),
m_Controls(nullptr)
{
}
QmitkTensorReconstructionView::~QmitkTensorReconstructionView()
{
}
void QmitkTensorReconstructionView::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
// create GUI widgets
m_Controls = new Ui::QmitkTensorReconstructionViewControls;
m_Controls->setupUi(parent);
this->CreateConnections();
Advanced1CheckboxClicked();
}
}
void QmitkTensorReconstructionView::SetFocus()
{
m_Controls->m_Advanced1->setFocus();
}
void QmitkTensorReconstructionView::CreateConnections()
{
if ( m_Controls )
{
connect( (QObject*)(m_Controls->m_StartReconstruction), SIGNAL(clicked()), this, SLOT(Reconstruct()) );
connect( (QObject*)(m_Controls->m_Advanced1), SIGNAL(clicked()), this, SLOT(Advanced1CheckboxClicked()) );
connect( (QObject*)(m_Controls->m_TensorsToDWIButton), SIGNAL(clicked()), this, SLOT(TensorsToDWI()) );
connect( (QObject*)(m_Controls->m_TensorsToOdfButton), SIGNAL(clicked()), this, SLOT(TensorsToOdf()) );
connect( (QObject*)(m_Controls->m_ResidualButton), SIGNAL(clicked()), this, SLOT(ResidualCalculation()) );
connect( (QObject*)(m_Controls->m_PerSliceView), SIGNAL(pointSelected(int, int)), this, SLOT(ResidualClicked(int, int)) );
connect( (QObject*)(m_Controls->m_TensorReconstructionThreshold), SIGNAL(valueChanged(int)), this, SLOT(PreviewThreshold(int)) );
m_Controls->m_ResidualTab->setVisible(false);
m_Controls->m_PercentagesOfOutliers->setVisible(false);
m_Controls->m_DwiBox->SetDataStorage(this->GetDataStorage());
mitk::NodePredicateIsDWI::Pointer isDwi = mitk::NodePredicateIsDWI::New();
m_Controls->m_DwiBox->SetPredicate( isDwi );
connect( (QObject*)(m_Controls->m_DwiBox), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()));
m_Controls->m_OdfBox->SetDataStorage(this->GetDataStorage());
mitk::TNodePredicateDataType<mitk::TensorImage>::Pointer isDti = mitk::TNodePredicateDataType<mitk::TensorImage>::New();
m_Controls->m_OdfBox->SetPredicate( isDti );
connect( (QObject*)(m_Controls->m_OdfBox), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()));
m_Controls->m_DtiBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_DtiBox->SetPredicate( isDti );
connect( (QObject*)(m_Controls->m_DtiBox), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()));
m_Controls->m_ResBox1->SetDataStorage(this->GetDataStorage());
m_Controls->m_ResBox1->SetPredicate( isDwi );
connect( (QObject*)(m_Controls->m_ResBox1), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()));
m_Controls->m_ResBox2->SetDataStorage(this->GetDataStorage());
m_Controls->m_ResBox2->SetPredicate( isDti );
connect( (QObject*)(m_Controls->m_ResBox2), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGui()));
}
}
void QmitkTensorReconstructionView::ResidualClicked(int slice, int volume)
{
mitk::Image* diffImage;
mitk::DataNode::Pointer correctNode;
mitk::BaseGeometry* geometry;
if (m_Controls->m_ResBox1->GetSelectedNode().IsNotNull())
{
diffImage = static_cast<mitk::Image*>(m_Controls->m_ResBox1->GetSelectedNode()->GetData());
geometry = m_Controls->m_ResBox1->GetSelectedNode()->GetData()->GetGeometry();
// Remember the node whose display index must be updated
correctNode = mitk::DataNode::New();
correctNode = m_Controls->m_ResBox1->GetSelectedNode();
GradientDirectionContainerType::Pointer dirs = mitk::DiffusionPropertyHelper::GetGradientContainer(diffImage);
for(itk::SizeValueType i=0; i<dirs->Size() && i<=(itk::SizeValueType)volume; i++)
{
GradientDirectionType grad = dirs->ElementAt(i);
// check if image is b0 weighted
if(fabs(grad[0]) < 0.001 && fabs(grad[1]) < 0.001 && fabs(grad[2]) < 0.001)
{
volume++;
}
}
QString pos = "Volume: ";
pos.append(QString::number(volume));
pos.append(", Slice: ");
pos.append(QString::number(slice));
m_Controls->m_PositionLabel->setText(pos);
if(correctNode)
{
int oldDisplayVal;
correctNode->GetIntProperty("DisplayChannel", oldDisplayVal);
QString oldVal = QString::number(oldDisplayVal);
QString newVal = QString::number(volume);
correctNode->SetIntProperty("DisplayChannel",volume);
correctNode->SetSelected(true);
this->FirePropertyChanged("DisplayChannel", oldVal, newVal);
correctNode->UpdateOutputInformation();
mitk::Point3D p3 = this->GetRenderWindowPart()->GetSelectedPosition();
itk::Index<3> ix;
geometry->WorldToIndex(p3, ix);
// ix[2] = slice;
mitk::Vector3D vec;
vec[0] = ix[0];
vec[1] = ix[1];
vec[2] = slice;
mitk::Vector3D v3New;
geometry->IndexToWorld(vec, v3New);
mitk::Point3D origin = geometry->GetOrigin();
mitk::Point3D p3New;
p3New[0] = v3New[0] + origin[0];
p3New[1] = v3New[1] + origin[1];
p3New[2] = v3New[2] + origin[2];
this->GetRenderWindowPart()->SetSelectedPosition(p3New);
this->GetRenderWindowPart()->RequestUpdate();
}
}
}
void QmitkTensorReconstructionView::Advanced1CheckboxClicked()
{
bool check = m_Controls->
m_Advanced1->isChecked();
m_Controls->frame->setVisible(check);
}
void QmitkTensorReconstructionView::Activated()
{
}
void QmitkTensorReconstructionView::Deactivated()
{
// Get all current nodes
mitk::DataStorage::SetOfObjects::ConstPointer objects = this->GetDataStorage()->GetAll();
mitk::DataStorage::SetOfObjects::const_iterator itemiter( objects->begin() );
mitk::DataStorage::SetOfObjects::const_iterator itemiterend( objects->end() );
while ( itemiter != itemiterend ) // for all items
{
mitk::DataNode::Pointer node = *itemiter;
if (node.IsNull())
continue;
// only look at interesting types
if( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(dynamic_cast<mitk::Image*>(node->GetData())))
{
if (this->GetDataStorage()->GetNamedDerivedNode("ThresholdOverlay", *itemiter))
{
node = this->GetDataStorage()->GetNamedDerivedNode("ThresholdOverlay", *itemiter);
this->GetDataStorage()->Remove(node);
}
}
itemiter++;
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkTensorReconstructionView::Visible()
{
}
void QmitkTensorReconstructionView::Hidden()
{
}
void QmitkTensorReconstructionView::ResidualCalculation()
{
// Extract dwi and dti from current selection
// In case of multiple selections, take the first one, since taking all combinations is not meaningful
mitk::DataStorage::SetOfObjects::Pointer set =
mitk::DataStorage::SetOfObjects::New();
mitk::Image::Pointer diffImage
= mitk::Image::New();
TensorImageType::Pointer tensorImage;
std::string nodename;
if(m_Controls->m_ResBox1->GetSelectedNode())
{
diffImage = static_cast<mitk::Image*>(m_Controls->m_ResBox1->GetSelectedNode()->GetData());
}
else
return;
if(m_Controls->m_ResBox2->GetSelectedNode().IsNotNull())
{
mitk::TensorImage* mitkVol;
mitkVol = static_cast<mitk::TensorImage*>(m_Controls->m_ResBox2->GetSelectedNode()->GetData());
mitk::CastToItkImage(mitkVol, tensorImage);
m_Controls->m_ResBox2->GetSelectedNode()->GetStringProperty("name", nodename);
}
else
return;
typedef itk::TensorImageToDiffusionImageFilter<
TTensorPixelType, DiffusionPixelType > FilterType;
GradientDirectionContainerType* gradients
= mitk::DiffusionPropertyHelper::GetGradientContainer(diffImage);
// Find the min and the max values from a baseline image
mitk::ImageStatisticsHolder *stats = diffImage->GetStatistics();
//Initialize filter that calculates the modeled diffusion weighted signals
FilterType::Pointer filter = FilterType::New();
filter->SetInput( tensorImage );
filter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(diffImage));
filter->SetGradientList(gradients);
filter->SetMin(stats->GetScalarValueMin());
filter->SetMax(stats->GetScalarValueMax());
filter->Update();
// TENSORS TO DATATREE
mitk::Image::Pointer image = mitk::GrabItkImageMemory( filter->GetOutput() );
mitk::DiffusionPropertyHelper::CopyProperties(diffImage, image, true);
mitk::DiffusionPropertyHelper::SetGradientContainer(image, gradients);
mitk::DiffusionPropertyHelper::InitializeImage( image );
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( image );
mitk::ImageVtkMapper2D::SetDefaultProperties(node);
QString newname;
newname = newname.append(nodename.c_str());
newname = newname.append("_Estimated DWI");
node->SetName(newname.toLatin1());
GetDataStorage()->Add(node, m_Controls->m_ResBox2->GetSelectedNode());
BValueMapType map = mitk::DiffusionPropertyHelper::GetBValueMap(image);
std::vector< unsigned int > b0Indices = map[0];
typedef itk::ResidualImageFilter<DiffusionPixelType, float> ResidualImageFilterType;
ITKDiffusionImageType::Pointer itkVectorImagePointer = ITKDiffusionImageType::New();
mitk::CastToItkImage(diffImage, itkVectorImagePointer);
ITKDiffusionImageType::Pointer itkSecondVectorImagePointer = ITKDiffusionImageType::New();
mitk::CastToItkImage(image, itkSecondVectorImagePointer);
ResidualImageFilterType::Pointer residualFilter = ResidualImageFilterType::New();
residualFilter->SetInput( itkVectorImagePointer );
residualFilter->SetSecondDiffusionImage( itkSecondVectorImagePointer );
residualFilter->SetGradients(gradients);
residualFilter->SetB0Index(b0Indices[0]);
residualFilter->SetB0Threshold(30);
residualFilter->Update();
itk::Image<float, 3>::Pointer residualImage = itk::Image<float, 3>::New();
residualImage = residualFilter->GetOutput();
mitk::Image::Pointer mitkResImg = mitk::Image::New();
mitk::CastToMitkImage(residualImage, mitkResImg);
stats = mitkResImg->GetStatistics();
float min = stats->GetScalarValueMin();
float max = stats->GetScalarValueMax();
mitk::LookupTableProperty::Pointer lutProp = mitk::LookupTableProperty::New();
mitk::LookupTable::Pointer lut = mitk::LookupTable::New();
vtkSmartPointer<vtkLookupTable> lookupTable =
vtkSmartPointer<vtkLookupTable>::New();
lookupTable->SetTableRange(min, max);
// If you don't want to use the whole color range, you can use
// SetValueRange, SetHueRange, and SetSaturationRange
lookupTable->Build();
vtkSmartPointer<vtkLookupTable> reversedlookupTable =
vtkSmartPointer<vtkLookupTable>::New();
reversedlookupTable->SetTableRange(min+1, max);
reversedlookupTable->Build();
for(int i=0; i<256; i++)
{
double* rgba = reversedlookupTable->GetTableValue(255-i);
lookupTable->SetTableValue(i, rgba[0], rgba[1], rgba[2], rgba[3]);
}
lut->SetVtkLookupTable(lookupTable);
lutProp->SetLookupTable(lut);
// Create lookuptable
mitk::DataNode::Pointer resNode=mitk::DataNode::New();
resNode->SetData( mitkResImg );
resNode->SetName("Residuals");
resNode->SetProperty("LookupTable", lutProp);
bool b;
resNode->GetBoolProperty("use color", b);
resNode->SetBoolProperty("use color", false);
GetDataStorage()->Add(resNode, m_Controls->m_ResBox2->GetSelectedNode());
this->GetRenderWindowPart()->RequestUpdate();
// Draw Graph
std::vector<double> means = residualFilter->GetMeans();
std::vector<double> q1s = residualFilter->GetQ1();
std::vector<double> q3s = residualFilter->GetQ3();
std::vector<double> percentagesOfOUtliers = residualFilter->GetPercentagesOfOutliers();
m_Controls->m_ResidualAnalysis->SetMeans(means);
m_Controls->m_ResidualAnalysis->SetQ1(q1s);
m_Controls->m_ResidualAnalysis->SetQ3(q3s);
m_Controls->m_ResidualAnalysis->SetPercentagesOfOutliers(percentagesOfOUtliers);
if(m_Controls->m_PercentagesOfOutliers->isChecked())
{
m_Controls->m_ResidualAnalysis->DrawPercentagesOfOutliers();
}
else
{
m_Controls->m_ResidualAnalysis->DrawMeans();
}
// Draw Graph for volumes per slice in the QGraphicsView
std::vector< std::vector<double> > outliersPerSlice = residualFilter->GetOutliersPerSlice();
int xSize = outliersPerSlice.size();
if(xSize == 0)
{
return;
}
int ySize = outliersPerSlice[0].size();
// Find maximum in outliersPerSlice
double maxOutlier= 0.0;
for(int i=0; i<xSize; i++)
{
for(int j=0; j<ySize; j++)
{
if(outliersPerSlice[i][j]>maxOutlier)
{
maxOutlier = outliersPerSlice[i][j];
}
}
}
// Create some QImage
QImage qImage(xSize, ySize, QImage::Format_RGB32);
QImage legend(1, 256, QImage::Format_RGB32);
QRgb value;
vtkSmartPointer<vtkLookupTable> lookup =
vtkSmartPointer<vtkLookupTable>::New();
lookup->SetTableRange(0.0, maxOutlier);
lookup->Build();
reversedlookupTable->SetTableRange(0, maxOutlier);
reversedlookupTable->Build();
for(int i=0; i<256; i++)
{
double* rgba = reversedlookupTable->GetTableValue(255-i);
lookup->SetTableValue(i, rgba[0], rgba[1], rgba[2], rgba[3]);
}
// Fill qImage
for(int i=0; i<xSize; i++)
{
for(int j=0; j<ySize; j++)
{
double out = outliersPerSlice[i][j];
unsigned char *_rgba = lookup->MapValue(out);
int r, g, b;
r = _rgba[0];
g = _rgba[1];
b = _rgba[2];
value = qRgb(r, g, b);
qImage.setPixel(i,j,value);
}
}
for(int i=0; i<256; i++)
{
double* rgba = lookup->GetTableValue(i);
int r, g, b;
r = rgba[0]*255;
g = rgba[1]*255;
b = rgba[2]*255;
value = qRgb(r, g, b);
legend.setPixel(0,255-i,value);
}
QString upper = QString::number(maxOutlier, 'g', 3);
upper.append(" %");
QString lower = QString::number(0.0);
lower.append(" %");
m_Controls->m_UpperLabel->setText(upper);
m_Controls->m_LowerLabel->setText(lower);
QPixmap pixmap(QPixmap::fromImage(qImage));
QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap);
item->setTransform(QTransform::fromScale(10.0, 3.0), true);
QPixmap pixmap2(QPixmap::fromImage(legend));
QGraphicsPixmapItem *item2 = new QGraphicsPixmapItem(pixmap2);
item2->setTransform(QTransform::fromScale(20.0, 1.0), true);
m_Controls->m_PerSliceView->SetResidualPixmapItem(item);
QGraphicsScene* scene = new QGraphicsScene;
QGraphicsScene* scene2 = new QGraphicsScene;
scene->addItem(item);
scene2->addItem(item2);
m_Controls->m_PerSliceView->setScene(scene);
m_Controls->m_LegendView->setScene(scene2);
m_Controls->m_PerSliceView->show();
m_Controls->m_PerSliceView->repaint();
m_Controls->m_LegendView->setHorizontalScrollBarPolicy ( Qt::ScrollBarAlwaysOff );
m_Controls->m_LegendView->setVerticalScrollBarPolicy ( Qt::ScrollBarAlwaysOff );
m_Controls->m_LegendView->show();
m_Controls->m_LegendView->repaint();
}
void QmitkTensorReconstructionView::Reconstruct()
{
int method = m_Controls->m_ReconctructionMethodBox->currentIndex();
switch (method)
{
case 0:
ItkTensorReconstruction();
break;
case 1:
TensorReconstructionWithCorr();
break;
default:
ItkTensorReconstruction();
}
}
void QmitkTensorReconstructionView::TensorReconstructionWithCorr()
{
try
{
if ( m_Controls->m_DwiBox->GetSelectedNode().IsNotNull() ) // for all items
{
mitk::Image* vols = static_cast<mitk::Image*>(m_Controls->m_DwiBox->GetSelectedNode()->GetData());
std::string nodename = m_Controls->m_DwiBox->GetSelectedNode()->GetName();
typedef itk::TensorReconstructionWithEigenvalueCorrectionFilter< DiffusionPixelType, TTensorPixelType > ReconstructionFilter;
float b0Threshold = m_Controls->m_TensorReconstructionThreshold->value();
mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradientContainerCopy = mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::New();
for(auto it = mitk::DiffusionPropertyHelper::GetGradientContainer(vols)->Begin(); it != mitk::DiffusionPropertyHelper::GetGradientContainer(vols)->End(); it++)
gradientContainerCopy->push_back(it.Value());
ITKDiffusionImageType::Pointer itkVectorImagePointer = ITKDiffusionImageType::New();
mitk::CastToItkImage(vols, itkVectorImagePointer);
ReconstructionFilter::Pointer reconFilter = ReconstructionFilter::New();
reconFilter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(vols));
reconFilter->SetGradientImage( gradientContainerCopy, itkVectorImagePointer);
reconFilter->SetB0Threshold(b0Threshold);
reconFilter->Update();
typedef mitk::TensorImage::ItkTensorImageType TensorImageType;
TensorImageType::Pointer outputTensorImg = reconFilter->GetOutput();
typedef itk::ImageRegionIterator<TensorImageType> TensorImageIteratorType;
TensorImageIteratorType tensorIt(outputTensorImg, outputTensorImg->GetRequestedRegion());
tensorIt.GoToBegin();
int negatives = 0;
while(!tensorIt.IsAtEnd())
{
typedef mitk::TensorImage::PixelType TensorType;
TensorType tensor = tensorIt.Get();
TensorType::EigenValuesArrayType ev;
tensor.ComputeEigenValues(ev);
for(unsigned int i=0; i<ev.Size(); i++)
{
if(ev[i] < 0.0)
{
tensor.Fill(0.0);
tensorIt.Set(tensor);
negatives++;
break;
}
}
++tensorIt;
}
MITK_INFO << negatives << " tensors with negative eigenvalues" << std::endl;
mitk::TensorImage::Pointer image = mitk::TensorImage::New();
image->InitializeByItk( outputTensorImg.GetPointer() );
image->SetVolume( outputTensorImg->GetBufferPointer() );
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( image );
node->SetName(nodename+"_EigenvalueCorrected_DT");
GetDataStorage()->Add(node, m_Controls->m_DwiBox->GetSelectedNode());
}
this->GetRenderWindowPart()->RequestUpdate();
}
catch (itk::ExceptionObject &ex)
{
MITK_INFO << ex ;
QMessageBox::information(0, "Reconstruction not possible:", ex.GetDescription());
}
}
void QmitkTensorReconstructionView::ItkTensorReconstruction()
{
try
{
if ( m_Controls->m_DwiBox->GetSelectedNode().IsNotNull() ) // for all items
{
mitk::Image* vols = static_cast<mitk::Image*>(m_Controls->m_DwiBox->GetSelectedNode()->GetData());
std::string nodename = m_Controls->m_DwiBox->GetSelectedNode()->GetName();
typedef itk::DiffusionTensor3DReconstructionImageFilter<DiffusionPixelType, DiffusionPixelType, TTensorPixelType > TensorReconstructionImageFilterType;
TensorReconstructionImageFilterType::Pointer tensorReconstructionFilter = TensorReconstructionImageFilterType::New();
GradientDirectionContainerType::Pointer gradientContainerCopy = GradientDirectionContainerType::New();
for(GradientDirectionContainerType::ConstIterator it = mitk::DiffusionPropertyHelper::GetGradientContainer(vols)->Begin();
it != mitk::DiffusionPropertyHelper::GetGradientContainer(vols)->End(); it++)
{
gradientContainerCopy->push_back(it.Value());
}
ITKDiffusionImageType::Pointer itkVectorImagePointer = ITKDiffusionImageType::New();
mitk::CastToItkImage(vols, itkVectorImagePointer);
tensorReconstructionFilter->SetBValue(mitk::DiffusionPropertyHelper::GetReferenceBValue(vols));
tensorReconstructionFilter->SetGradientImage( gradientContainerCopy, itkVectorImagePointer );
tensorReconstructionFilter->SetThreshold( m_Controls->m_TensorReconstructionThreshold->value() );
tensorReconstructionFilter->Update();
// TENSORS TO DATATREE
mitk::TensorImage::Pointer image = mitk::TensorImage::New();
typedef mitk::TensorImage::ItkTensorImageType TensorImageType;
TensorImageType::Pointer tensorImage;
tensorImage = tensorReconstructionFilter->GetOutput();
// Check the tensor for negative eigenvalues
if(m_Controls->m_CheckNegativeEigenvalues->isChecked())
{
typedef itk::ImageRegionIterator<TensorImageType> TensorImageIteratorType;
TensorImageIteratorType tensorIt(tensorImage, tensorImage->GetRequestedRegion());
tensorIt.GoToBegin();
while(!tensorIt.IsAtEnd())
{
typedef mitk::TensorImage::PixelType TensorType;
//typedef itk::Tensor<TTensorPixelType, 3> TensorType2;
TensorType tensor = tensorIt.Get();
TensorType::EigenValuesArrayType ev;
tensor.ComputeEigenValues(ev);
for(unsigned int i=0; i<ev.Size(); i++)
{
if(ev[i] < 0.0)
{
tensor.Fill(0.0);
tensorIt.Set(tensor);
break;
}
}
++tensorIt;
}
}
tensorImage->SetDirection( itkVectorImagePointer->GetDirection() );
image->InitializeByItk( tensorImage.GetPointer() );
image->SetVolume( tensorReconstructionFilter->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( image );
node->SetName(nodename+"_LinearLeastSquares_DT");
GetDataStorage()->Add(node, m_Controls->m_DwiBox->GetSelectedNode());
}
this->GetRenderWindowPart()->RequestUpdate();
}
catch (itk::ExceptionObject &ex)
{
MITK_INFO << ex ;
QMessageBox::information(0, "Reconstruction not possible:", ex.GetDescription());
return;
}
}
void QmitkTensorReconstructionView::TensorsToDWI()
{
DoTensorsToDWI();
}
void QmitkTensorReconstructionView::TensorsToOdf()
{
if (m_Controls->m_OdfBox->GetSelectedNode().IsNotNull())
{
mitk::DataNode::Pointer tensorImageNode = m_Controls->m_OdfBox->GetSelectedNode();
typedef mitk::TensorImage::ScalarPixelType TTensorPixelType;
typedef mitk::TensorImage::ItkTensorImageType TensorImageType;
TensorImageType::Pointer itkvol = TensorImageType::New();
mitk::CastToItkImage(dynamic_cast<mitk::TensorImage*>(tensorImageNode->GetData()), itkvol);
typedef itk::TensorImageToOdfImageFilter< TTensorPixelType, TTensorPixelType > FilterType;
FilterType::Pointer filter = FilterType::New();
filter->SetInput( itkvol );
filter->Update();
typedef itk::Vector<TTensorPixelType,ODF_SAMPLING_SIZE> OutputPixelType;
typedef itk::Image<OutputPixelType,3> OutputImageType;
mitk::OdfImage::Pointer image = mitk::OdfImage::New();
OutputImageType::Pointer outimg = filter->GetOutput();
image->InitializeByItk( outimg.GetPointer() );
image->SetVolume( outimg->GetBufferPointer() );
mitk::DataNode::Pointer node = mitk::DataNode::New();
node->SetData( image );
node->SetName(tensorImageNode->GetName()+"_Odf");
GetDataStorage()->Add(node, tensorImageNode);
}
}
void QmitkTensorReconstructionView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList<mitk::DataNode::Pointer>& )
{
UpdateGui();
}
void QmitkTensorReconstructionView::UpdateGui()
{
m_Controls->m_StartReconstruction->setEnabled(m_Controls->m_DwiBox->GetSelectedNode().IsNotNull());
m_Controls->m_TensorsToDWIButton->setEnabled(m_Controls->m_DtiBox->GetSelectedNode().IsNotNull());
m_Controls->m_TensorsToOdfButton->setEnabled(m_Controls->m_OdfBox->GetSelectedNode().IsNotNull());
m_Controls->m_ResidualButton->setEnabled(m_Controls->m_ResBox1->GetSelectedNode().IsNotNull() && m_Controls->m_ResBox2->GetSelectedNode().IsNotNull());
m_Controls->m_PercentagesOfOutliers->setEnabled(m_Controls->m_ResBox1->GetSelectedNode().IsNotNull() && m_Controls->m_ResBox2->GetSelectedNode().IsNotNull());
m_Controls->m_PerSliceView->setEnabled(m_Controls->m_ResBox1->GetSelectedNode().IsNotNull() && m_Controls->m_ResBox2->GetSelectedNode().IsNotNull());
}
template<int ndirs>
itk::VectorContainer<unsigned int, vnl_vector_fixed<double, 3> >::Pointer
QmitkTensorReconstructionView::MakeGradientList()
{
itk::VectorContainer<unsigned int, vnl_vector_fixed<double,3> >::Pointer retval =
itk::VectorContainer<unsigned int, vnl_vector_fixed<double,3> >::New();
vnl_matrix_fixed<double, 3, ndirs>* U =
itk::PointShell<ndirs, vnl_matrix_fixed<double, 3, ndirs> >::DistributePointShell();
for(int i=0; i<ndirs;i++)
{
vnl_vector_fixed<double,3> v;
v[0] = U->get(0,i); v[1] = U->get(1,i); v[2] = U->get(2,i);
retval->push_back(v);
}
// Add 0 vector for B0
vnl_vector_fixed<double,3> v;
v.fill(0.0);
retval->push_back(v);
return retval;
}
void QmitkTensorReconstructionView::DoTensorsToDWI()
{
try
{
if (m_Controls->m_DtiBox->GetSelectedNode().IsNotNull())
{
std::string nodename = m_Controls->m_DtiBox->GetSelectedNode()->GetName();
mitk::TensorImage* vol = static_cast<mitk::TensorImage*>(m_Controls->m_DtiBox->GetSelectedNode()->GetData());
typedef mitk::TensorImage::ScalarPixelType TTensorPixelType;
typedef mitk::TensorImage::ItkTensorImageType TensorImageType;
TensorImageType::Pointer itkvol = TensorImageType::New();
mitk::CastToItkImage(vol, itkvol);
typedef itk::TensorImageToDiffusionImageFilter<
TTensorPixelType, DiffusionPixelType > FilterType;
FilterType::GradientListPointerType gradientList = FilterType::GradientListType::New();
switch(m_Controls->m_TensorsToDWINumDirsSelect->currentIndex())
{
case 0:
gradientList = MakeGradientList<12>();
break;
case 1:
gradientList = MakeGradientList<42>();
break;
case 2:
gradientList = MakeGradientList<92>();
break;
case 3:
gradientList = MakeGradientList<162>();
break;
case 4:
gradientList = MakeGradientList<252>();
break;
case 5:
gradientList = MakeGradientList<362>();
break;
case 6:
gradientList = MakeGradientList<492>();
break;
case 7:
gradientList = MakeGradientList<642>();
break;
case 8:
gradientList = MakeGradientList<812>();
break;
case 9:
gradientList = MakeGradientList<1002>();
break;
default:
gradientList = MakeGradientList<92>();
}
double bVal = m_Controls->m_TensorsToDWIBValueEdit->text().toDouble();
FilterType::Pointer filter = FilterType::New();
filter->SetInput( itkvol );
filter->SetBValue(bVal);
filter->SetGradientList(gradientList);
filter->Update();
mitk::Image::Pointer image = mitk::GrabItkImageMemory( filter->GetOutput() );
mitk::DiffusionPropertyHelper::SetGradientContainer(image, gradientList);
mitk::DiffusionPropertyHelper::SetReferenceBValue(image, bVal);
mitk::DiffusionPropertyHelper::InitializeImage( image );
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( image );
mitk::ImageVtkMapper2D::SetDefaultProperties(node);
node->SetName(nodename+"_DWI");
GetDataStorage()->Add(node, m_Controls->m_DtiBox->GetSelectedNode());
}
this->GetRenderWindowPart()->RequestUpdate();
}
catch (itk::ExceptionObject &ex)
{
MITK_INFO << ex ;
QMessageBox::information(0, "DWI estimation failed:", ex.GetDescription());
return ;
}
}
void QmitkTensorReconstructionView::PreviewThreshold(int threshold)
{
if (m_Controls->m_DwiBox->GetSelectedNode().IsNotNull())
{
mitk::Image* vols = static_cast<mitk::Image*>(m_Controls->m_DwiBox->GetSelectedNode()->GetData());
ITKDiffusionImageType::Pointer itkVectorImagePointer = ITKDiffusionImageType::New();
mitk::CastToItkImage(vols, itkVectorImagePointer);
// Extract b0 image
typedef itk::B0ImageExtractionImageFilter<short, short> FilterType;
FilterType::Pointer filterB0 = FilterType::New();
filterB0->SetInput(itkVectorImagePointer);
filterB0->SetDirections(mitk::DiffusionPropertyHelper::GetGradientContainer(vols));
filterB0->Update();
mitk::Image::Pointer mitkImage = mitk::Image::New();
typedef itk::Image<short, 3> ImageType;
typedef itk::Image<short, 3> SegmentationType;
typedef itk::BinaryThresholdImageFilter<ImageType, SegmentationType> ThresholdFilterType;
// apply threshold
ThresholdFilterType::Pointer filterThreshold = ThresholdFilterType::New();
filterThreshold->SetInput(filterB0->GetOutput());
filterThreshold->SetLowerThreshold(threshold);
filterThreshold->SetInsideValue(0);
filterThreshold->SetOutsideValue(1); // mark cut off values red
filterThreshold->Update();
mitkImage->InitializeByItk( filterThreshold->GetOutput() );
mitkImage->SetVolume( filterThreshold->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer node;
if (this->GetDataStorage()->GetNamedDerivedNode("ThresholdOverlay", m_Controls->m_DwiBox->GetSelectedNode()))
{
node = this->GetDataStorage()->GetNamedDerivedNode("ThresholdOverlay", m_Controls->m_DwiBox->GetSelectedNode());
}
else
{
// create a new node, to show thresholded values
node = mitk::DataNode::New();
GetDataStorage()->Add( node, m_Controls->m_DwiBox->GetSelectedNode() );
node->SetProperty( "name", mitk::StringProperty::New("ThresholdOverlay"));
node->SetBoolProperty("helper object", true);
}
node->SetData( mitkImage );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkTensorReconstructionView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkTensorReconstructionView.h
index 15c28bf..e6644f0 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkTensorReconstructionView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/QmitkTensorReconstructionView.h
@@ -1,124 +1,124 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _QMITKTENSORRECONSTRUCTIONVIEW_H_INCLUDED
#define _QMITKTENSORRECONSTRUCTIONVIEW_H_INCLUDED
#include <QmitkAbstractView.h>
#include <mitkILifecycleAwarePart.h>
#include <string>
#include "ui_QmitkTensorReconstructionViewControls.h"
#include <mitkTensorImage.h>
#include <mitkImage.h>
#include <mitkDiffusionPropertyHelper.h>
#include <itkVectorImage.h>
typedef short DiffusionPixelType;
struct TrSelListener;
/*!
* \ingroup org_mitk_gui_qt_tensorreconstruction_internal
*
* \brief QmitkTensorReconstructionView
*
* Document your class here.
*/
class QmitkTensorReconstructionView : public QmitkAbstractView, public mitk::ILifecycleAwarePart
{
friend struct TrSelListener;
// this is needed for all Qt objects that should have a MOC object (everything that derives from QObject)
Q_OBJECT
public:
typedef mitk::DiffusionPropertyHelper::GradientDirectionType GradientDirectionType;
typedef mitk::DiffusionPropertyHelper::GradientDirectionsContainerType GradientDirectionContainerType;
typedef mitk::DiffusionPropertyHelper::BValueMapType BValueMapType;
typedef itk::VectorImage< DiffusionPixelType, 3 > ITKDiffusionImageType;
static const std::string VIEW_ID;
QmitkTensorReconstructionView();
virtual ~QmitkTensorReconstructionView();
virtual void CreateQtPartControl(QWidget *parent) override;
/// \brief Creation of the connections of main and control widget
virtual void CreateConnections();
///
/// Sets the focus to an internal widget.
///
virtual void SetFocus() override;
/// \brief Called when the view gets activated
virtual void Activated() override;
/// \brief Called when the view gets deactivated
virtual void Deactivated() override;
/// \brief Called when the view becomes visible
virtual void Visible() override;
/// \brief Called when the view becomes hidden
virtual void Hidden() override;
static const int nrconvkernels;
protected slots:
void UpdateGui();
void TensorsToOdf();
void TensorsToDWI();
void DoTensorsToDWI();
void Advanced1CheckboxClicked();
void Reconstruct();
void ResidualCalculation();
void ResidualClicked(int slice, int volume);
/**
* @brief PreviewThreshold Generates a preview of the values that are cut off by the thresholds
* @param threshold
*/
void PreviewThreshold(int threshold);
protected:
void ItkTensorReconstruction();
void TeemTensorReconstruction();
void TensorReconstructionWithCorr();
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
Ui::QmitkTensorReconstructionViewControls* m_Controls;
template<int ndirs> itk::VectorContainer<unsigned int, vnl_vector_fixed<double,3> >::Pointer MakeGradientList();
template<int L>
void TemplatedAnalyticalTensorReconstruction(mitk::Image* vols,
float lambda, std::string nodename, std::vector<mitk::DataNode::Pointer>* nodes, int normalization);
};
#endif // _QMITKTENSORRECONSTRUCTIONVIEW_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/mitkPluginActivator.cpp
index 342358c..13663e5 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/mitkPluginActivator.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/mitkPluginActivator.cpp
@@ -1,49 +1,49 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPluginActivator.h"
#include "src/internal/QmitkQBallReconstructionView.h"
#include "src/internal/QmitkTensorReconstructionView.h"
#include "src/internal/QmitkDiffusionQuantificationView.h"
#include "src/internal/QmitkODFDetailsView.h"
#include "src/internal/Perspectives/QmitkReconstructionPerspective.h"
#include "src/internal/Perspectives/QmitkQuantificationPerspective.h"
ctkPluginContext* mitk::PluginActivator::m_Context = nullptr;
ctkPluginContext* mitk::PluginActivator::GetContext()
{
return m_Context;
}
void mitk::PluginActivator::start(ctkPluginContext* context)
{
BERRY_REGISTER_EXTENSION_CLASS(QmitkReconstructionPerspective, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkQuantificationPerspective, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkQBallReconstructionView, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionQuantificationView, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkTensorReconstructionView, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkODFDetailsView, context)
m_Context = context;
}
void mitk::PluginActivator::stop(ctkPluginContext* context)
{
Q_UNUSED(context)
m_Context = nullptr;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/mitkPluginActivator.h
index f2aa997..df422e7 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/mitkPluginActivator.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.reconstruction/src/internal/mitkPluginActivator.h
@@ -1,40 +1,40 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKPLUGINACTIVATOR_H
#define MITKPLUGINACTIVATOR_H
#include <ctkPluginActivator.h>
namespace mitk
{
class PluginActivator : public QObject, public ctkPluginActivator
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.mitk.gui.qt.diffusionimaging.reconstruction")
Q_INTERFACES(ctkPluginActivator)
public:
static ctkPluginContext* GetContext();
void start(ctkPluginContext* context) override;
void stop(ctkPluginContext* context) override;
private:
static ctkPluginContext* m_Context;
};
}
#endif
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionView.cpp
index 9b46a97..e6c577c 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionView.cpp
@@ -1,124 +1,124 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
//misc
#define _USE_MATH_DEFINES
#include <math.h>
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// Qmitk
#include "QmitkHeadMotionCorrectionView.h"
// MITK
#include <mitkDiffusionPropertyHelper.h>
#include <mitkNodePredicateDataType.h>
// Qt
#include <QMessageBox>
#include <QFileDialog>
#include <QDir>
#include <QDirIterator>
#include <QTimer>
#include <mitkDWIHeadMotionCorrectionFilter.h>
#define _USE_MATH_DEFINES
#include <math.h>
const std::string QmitkHeadMotionCorrectionView::VIEW_ID = "org.mitk.views.headmotioncorrectionview";
QmitkHeadMotionCorrectionView::QmitkHeadMotionCorrectionView()
: QmitkAbstractView()
, m_Controls( 0 )
, m_DiffusionImage( nullptr )
{
}
// Destructor
QmitkHeadMotionCorrectionView::~QmitkHeadMotionCorrectionView()
{
}
void QmitkHeadMotionCorrectionView::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::QmitkHeadMotionCorrectionViewControls;
m_Controls->setupUi( parent );
connect( m_Controls->m_ImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGUI()) );
connect( m_Controls->m_RegistrationStartButton, SIGNAL(clicked()), this, SLOT(StartCorrection()) );
this->m_Parent = parent;
m_Controls->m_ImageBox->SetDataStorage(this->GetDataStorage());
mitk::TNodePredicateDataType<mitk::Image>::Pointer isImagePredicate = mitk::TNodePredicateDataType<mitk::Image>::New();
m_Controls->m_ImageBox->SetPredicate(isImagePredicate);
UpdateGUI();
}
}
void QmitkHeadMotionCorrectionView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList<mitk::DataNode::Pointer>& )
{
}
void QmitkHeadMotionCorrectionView::UpdateGUI()
{
if (m_Controls->m_ImageBox->GetSelectedNode().IsNotNull())
{
m_Controls->m_RegistrationStartButton->setEnabled(true);
m_Controls->m_RegistrationStartButton->setToolTip("Start Registration");
}
else
{
m_Controls->m_RegistrationStartButton->setEnabled(false);
m_Controls->m_RegistrationStartButton->setToolTip("No Diffusion image selected.");
}
}
void QmitkHeadMotionCorrectionView::SetFocus()
{
UpdateGUI();
m_Controls->m_RegistrationStartButton->setFocus();
}
void QmitkHeadMotionCorrectionView::StartCorrection()
{
mitk::DataNode::Pointer node = m_Controls->m_ImageBox->GetSelectedNode();
mitk::Image::Pointer inImage = dynamic_cast<mitk::Image*>(node->GetData());
if (!mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(inImage))
{
QMessageBox::warning(nullptr, "Image not processed", "Input is not a diffusion-weighted image!");
return;
}
mitk::DWIHeadMotionCorrectionFilter::Pointer registerer = mitk::DWIHeadMotionCorrectionFilter::New();
registerer->SetInput(inImage);
registerer->Update();
mitk::Image::Pointer image = registerer->GetCorrectedImage();
mitk::DataNode::Pointer corrected_node = mitk::DataNode::New();
corrected_node->SetData( image );
QString name(node->GetName().c_str());
name += "_Corrected";
corrected_node->SetName(name.toStdString());
GetDataStorage()->Add(corrected_node, node);
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionView.h
index 177f0f8..2cb7d77 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkHeadMotionCorrectionView.h
@@ -1,75 +1,75 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <berryISelectionListener.h>
#include <berryIStructuredSelection.h>
#include <QmitkAbstractView.h>
#include "ui_QmitkHeadMotionCorrectionViewControls.h"
#include <mitkImage.h>
#include <QThread>
#include <QTime>
typedef short DiffusionPixelType;
/*!
\brief View for diffusion image registration / head motion correction
*/
class QmitkHeadMotionCorrectionView : public QmitkAbstractView
{
// 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;
QmitkHeadMotionCorrectionView();
virtual ~QmitkHeadMotionCorrectionView();
virtual void CreateQtPartControl(QWidget *parent) override;
void SetFocus() override;
protected slots:
void StartCorrection();
void UpdateGUI(); ///< update button activity etc. dpending on current datamanager selection
protected:
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
Ui::QmitkHeadMotionCorrectionViewControls* m_Controls;
mitk::Image::Pointer m_DiffusionImage;
std::vector< mitk::DataNode::Pointer > m_SelectedDiffusionNodes;
private:
void UpdateRegistrationStatus(); ///< update textual status display of the Registration process
// the Qt parent of our GUI (NOT of this object)
QWidget* m_Parent;
};
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.cpp
index 49921ee..da87097 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.cpp
@@ -1,403 +1,403 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
//misc
#define _USE_MATH_DEFINES
#include <math.h>
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// Qmitk
#include "QmitkSimpleRegistrationView.h"
// MITK
#include <mitkNodePredicateDataType.h>
#include <mitkDiffusionPropertyHelper.h>
#include <mitkImageMappingHelper.h>
#include <mitkITKImageImport.h>
#include <mitkImageCast.h>
#include <itkExtractDwiChannelFilter.h>
#include <mitkMultiModalRigidDefaultRegistrationAlgorithm.h>
#include <mitkMultiModalAffineDefaultRegistrationAlgorithm.h>
#include <itkComposeImageFilter.h>
#include <mitkFiberBundle.h>
#include <mitkRegistrationHelper.h>
#include <mitkDiffusionImageCorrectionFilter.h>
// Qt
#include <QThreadPool>
#define _USE_MATH_DEFINES
#include <math.h>
const std::string QmitkSimpleRegistrationView::VIEW_ID = "org.mitk.views.simpleregistrationview";
QmitkSimpleRegistrationView::QmitkSimpleRegistrationView()
: QmitkAbstractView()
, m_Controls( 0 )
, m_RegistrationType(0)
{
}
// Destructor
QmitkSimpleRegistrationView::~QmitkSimpleRegistrationView()
{
}
void QmitkSimpleRegistrationView::StartRegistration()
{
QmitkRegistrationJob* pJob;
if (m_Controls->m_RegBox->currentIndex()==0)
{
mitk::MultiModalRigidDefaultRegistrationAlgorithm< ItkFloatImageType >::Pointer algo = mitk::MultiModalRigidDefaultRegistrationAlgorithm< ItkFloatImageType >::New();
pJob = new QmitkRegistrationJob(algo);
m_RegistrationType = 0;
}
else
{
mitk::MultiModalAffineDefaultRegistrationAlgorithm< ItkFloatImageType >::Pointer algo = mitk::MultiModalAffineDefaultRegistrationAlgorithm< ItkFloatImageType >::New();
pJob = new QmitkRegistrationJob(algo);
m_RegistrationType = 1;
}
pJob->setAutoDelete(true);
m_MovingImageNode = m_Controls->m_MovingImageBox->GetSelectedNode();
mitk::Image::Pointer movingImage = dynamic_cast<mitk::Image*>(m_MovingImageNode->GetData());
if (mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(movingImage))
{
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(movingImage, itkVectorImagePointer);
itk::ExtractDwiChannelFilter< short >::Pointer filter = itk::ExtractDwiChannelFilter< short >::New();
filter->SetInput( itkVectorImagePointer);
filter->SetChannelIndex(m_Controls->m_MovingChannelBox->value());
filter->Update();
mitk::Image::Pointer newImage = mitk::Image::New();
newImage->InitializeByItk( filter->GetOutput() );
newImage->SetImportChannel( filter->GetOutput()->GetBufferPointer() );
pJob->m_spMovingData = newImage;
}
else
pJob->m_spMovingData = movingImage;
mitk::Image::Pointer fixedImage = dynamic_cast<mitk::Image*>(m_Controls->m_FixedImageBox->GetSelectedNode()->GetData());
if (mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(fixedImage))
{
ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New();
mitk::CastToItkImage(fixedImage, itkVectorImagePointer);
itk::ExtractDwiChannelFilter< short >::Pointer filter = itk::ExtractDwiChannelFilter< short >::New();
filter->SetInput( itkVectorImagePointer);
filter->SetChannelIndex(m_Controls->m_MovingChannelBox->value());
filter->Update();
mitk::Image::Pointer newImage = mitk::Image::New();
newImage->InitializeByItk( filter->GetOutput() );
newImage->SetImportChannel( filter->GetOutput()->GetBufferPointer() );
pJob->m_spTargetData = newImage;
}
else
pJob->m_spTargetData = fixedImage;
pJob->m_TargetDataUID = mitk::EnsureUID(m_Controls->m_FixedImageBox->GetSelectedNode()->GetData());
pJob->m_MovingDataUID = mitk::EnsureUID(m_Controls->m_MovingImageBox->GetSelectedNode()->GetData());
connect(pJob, SIGNAL(RegResultIsAvailable(mitk::MAPRegistrationWrapper::Pointer, const QmitkRegistrationJob*)), this,
SLOT(OnRegResultIsAvailable(mitk::MAPRegistrationWrapper::Pointer, const QmitkRegistrationJob*)),
Qt::BlockingQueuedConnection);
QThreadPool* threadPool = QThreadPool::globalInstance();
threadPool->start(pJob);
m_Controls->m_RegistrationStartButton->setEnabled(false);
m_Controls->m_RegistrationStartButton->setText("Registration in progress ...");
}
void QmitkSimpleRegistrationView::OnRegResultIsAvailable(mitk::MAPRegistrationWrapper::Pointer spResultRegistration, const QmitkRegistrationJob* job)
{
mitk::Image::Pointer movingImage = dynamic_cast<mitk::Image*>(m_MovingImageNode->GetData());
mitk::Image::Pointer image;
if (m_RegistrationType==0 && !m_Controls->m_ResampleBox->isChecked())
{
image = mitk::ImageMappingHelper::refineGeometry(movingImage, spResultRegistration, true);
mitk::DiffusionPropertyHelper::CopyProperties(movingImage, image, true);
auto reg = spResultRegistration->GetRegistration();
typedef mitk::DiffusionImageCorrectionFilter CorrectionFilterType;
CorrectionFilterType::Pointer corrector = CorrectionFilterType::New();
corrector->SetImage( image );
corrector->CorrectDirections( mitk::MITKRegistrationHelper::getAffineMatrix(reg, false)->GetMatrix().GetVnlMatrix() );
}
else
{
if (!mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(movingImage))
{
image = mitk::ImageMappingHelper::map(movingImage, spResultRegistration, false, 0, job->m_spTargetData->GetGeometry(), false, 0, mitk::ImageMappingInterpolator::BSpline_3);
}
else
{
typedef itk::ComposeImageFilter < ITKDiffusionVolumeType > ComposeFilterType;
ComposeFilterType::Pointer composer = ComposeFilterType::New();
ItkDwiType::Pointer itkVectorImagePointer = mitk::DiffusionPropertyHelper::GetItkVectorImage(movingImage);
for (unsigned int i=0; i<itkVectorImagePointer->GetVectorLength(); ++i)
{
itk::ExtractDwiChannelFilter< short >::Pointer filter = itk::ExtractDwiChannelFilter< short >::New();
filter->SetInput( itkVectorImagePointer);
filter->SetChannelIndex(i);
filter->Update();
mitk::Image::Pointer gradientVolume = mitk::Image::New();
gradientVolume->InitializeByItk( filter->GetOutput() );
gradientVolume->SetImportChannel( filter->GetOutput()->GetBufferPointer() );
mitk::Image::Pointer registered_mitk_image = mitk::ImageMappingHelper::map(gradientVolume, spResultRegistration, false, 0, job->m_spTargetData->GetGeometry(), false, 0, mitk::ImageMappingInterpolator::BSpline_3);
ITKDiffusionVolumeType::Pointer registered_itk_image = ITKDiffusionVolumeType::New();
mitk::CastToItkImage(registered_mitk_image, registered_itk_image);
composer->SetInput(i, registered_itk_image);
}
composer->Update();
image = mitk::GrabItkImageMemory( composer->GetOutput() );
mitk::DiffusionPropertyHelper::CopyProperties(movingImage, image, true);
auto reg = spResultRegistration->GetRegistration();
typedef mitk::DiffusionImageCorrectionFilter CorrectionFilterType;
CorrectionFilterType::Pointer corrector = CorrectionFilterType::New();
corrector->SetImage( image );
corrector->CorrectDirections( mitk::MITKRegistrationHelper::getAffineMatrix(reg, false)->GetMatrix().GetVnlMatrix() );
}
}
if (mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image))
mitk::DiffusionPropertyHelper::InitializeImage( image );
mitk::DataNode::Pointer resultNode = mitk::DataNode::New();
resultNode->SetData(image);
if (m_MovingImageNode.IsNotNull())
{
m_MovingImageNode->SetVisibility(false);
QString name = m_MovingImageNode->GetName().c_str();
if (m_RegistrationType==0)
resultNode->SetName((name+"_registered (rigid)").toStdString().c_str());
else
resultNode->SetName((name+"_registered (affine)").toStdString().c_str());
}
else
{
if (m_RegistrationType==0)
resultNode->SetName("Registered (rigid)");
else
resultNode->SetName("Registered (affine)");
}
// resultNode->SetOpacity(0.6);
// resultNode->SetColor(0.0, 0.0, 1.0);
GetDataStorage()->Add(resultNode);
mitk::RenderingManager::GetInstance()->InitializeViews( resultNode->GetData()->GetTimeGeometry(),
mitk::RenderingManager::REQUEST_UPDATE_ALL,
true);
if (m_Controls->m_RegOutputBox->isChecked())
{
mitk::DataNode::Pointer registration_node = mitk::DataNode::New();
registration_node->SetData(spResultRegistration);
if (m_RegistrationType==0)
registration_node->SetName("Registration Object (rigid)");
else
registration_node->SetName("Registration Object (affine)");
GetDataStorage()->Add(registration_node, resultNode);
}
this->GetRenderWindowPart()->RequestUpdate();
m_Controls->m_RegistrationStartButton->setEnabled(true);
m_Controls->m_RegistrationStartButton->setText("Start Registration");
m_MovingImageNode = nullptr;
TractoChanged();
}
void QmitkSimpleRegistrationView::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::QmitkSimpleRegistrationViewControls;
m_Controls->setupUi( parent );
m_Controls->m_FixedImageBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_MovingImageBox->SetDataStorage(this->GetDataStorage());
mitk::TNodePredicateDataType<mitk::Image>::Pointer isImagePredicate = mitk::TNodePredicateDataType<mitk::Image>::New();
m_Controls->m_FixedImageBox->SetPredicate(isImagePredicate);
m_Controls->m_MovingImageBox->SetPredicate(isImagePredicate);
mitk::TNodePredicateDataType<mitk::FiberBundle>::Pointer isFib = mitk::TNodePredicateDataType<mitk::FiberBundle>::New();
mitk::TNodePredicateDataType<mitk::MAPRegistrationWrapper>::Pointer isReg = mitk::TNodePredicateDataType<mitk::MAPRegistrationWrapper>::New();
m_Controls->m_TractoBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_RegObjectBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_TractoBox->SetPredicate(isFib);
m_Controls->m_RegObjectBox->SetPredicate(isReg);
connect( m_Controls->m_FixedImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(FixedImageChanged()) );
connect( m_Controls->m_MovingImageBox, SIGNAL(currentIndexChanged(int)), this, SLOT(MovingImageChanged()) );
connect( m_Controls->m_TractoBox, SIGNAL(currentIndexChanged(int)), this, SLOT(TractoChanged()) );
connect( m_Controls->m_RegObjectBox, SIGNAL(currentIndexChanged(int)), this, SLOT(TractoChanged()) );
connect( m_Controls->m_RegistrationStartButton, SIGNAL(clicked()), this, SLOT(StartRegistration()) );
connect( m_Controls->m_TractoRegistrationStartButton, SIGNAL(clicked()), this, SLOT(StartTractoRegistration()) );
FixedImageChanged();
MovingImageChanged();
TractoChanged();
}
}
void QmitkSimpleRegistrationView::StartTractoRegistration()
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(m_Controls->m_TractoBox->GetSelectedNode()->GetData());
mitk::MAPRegistrationWrapper::Pointer reg = dynamic_cast<mitk::MAPRegistrationWrapper*>(m_Controls->m_RegObjectBox->GetSelectedNode()->GetData());
mitk::MITKRegistrationHelper::Affine3DTransformType::Pointer affine = mitk::MITKRegistrationHelper::getAffineMatrix(reg, false);
mitk::FiberBundle::Pointer fib_copy = fib->GetDeepCopy();
fib_copy->TransformFibers(affine);
mitk::DataNode::Pointer registration_node = mitk::DataNode::New();
registration_node->SetData(fib_copy);
QString name = m_Controls->m_TractoBox->GetSelectedNode()->GetName().c_str();
registration_node->SetName((name+"_registered").toStdString().c_str());
GetDataStorage()->Add(registration_node, m_Controls->m_TractoBox->GetSelectedNode());
}
void QmitkSimpleRegistrationView::TractoChanged()
{
if (m_Controls->m_RegObjectBox->GetSelectedNode().IsNotNull() && m_Controls->m_TractoBox->GetSelectedNode().IsNotNull())
m_Controls->m_TractoRegistrationStartButton->setEnabled(true);
else
m_Controls->m_TractoRegistrationStartButton->setEnabled(false);
}
void QmitkSimpleRegistrationView::FixedImageChanged()
{
if (m_Controls->m_FixedImageBox->GetSelectedNode().IsNotNull())
{
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(m_Controls->m_FixedImageBox->GetSelectedNode()->GetData());
int channels = image->GetNumberOfChannels();
int dims = image->GetDimension();
int fourth_dim_size = image->GetTimeSteps();
bool isdiff = mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image);
if (dims==4 || channels>1)
{
m_Controls->m_FixedChannelBox->setEnabled(false);
m_Controls->m_RegistrationStartButton->setEnabled(false);
}
if (isdiff)
{
m_Controls->m_FixedChannelBox->setEnabled(true);
if (fourth_dim_size>1)
m_Controls->m_FixedChannelBox->setMaximum(fourth_dim_size-1);
else if (isdiff)
m_Controls->m_FixedChannelBox->setMaximum(mitk::DiffusionPropertyHelper::GetGradientContainer(image)->Size()-1);
}
else
{
m_Controls->m_FixedChannelBox->setEnabled(false);
}
m_Controls->m_RegistrationStartButton->setEnabled(true);
}
else
{
m_Controls->m_FixedChannelBox->setEnabled(false);
m_Controls->m_RegistrationStartButton->setEnabled(false);
}
}
void QmitkSimpleRegistrationView::MovingImageChanged()
{
if (m_Controls->m_MovingImageBox->GetSelectedNode().IsNotNull())
{
mitk::Image::Pointer image = dynamic_cast<mitk::Image*>(m_Controls->m_MovingImageBox->GetSelectedNode()->GetData());
int channels = image->GetNumberOfChannels();
int dims = image->GetDimension();
int fourth_dim_size = image->GetTimeSteps();
bool isdiff = mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage(image);
if (dims==4 || channels>1)
{
m_Controls->m_MovingChannelBox->setEnabled(false);
m_Controls->m_RegistrationStartButton->setEnabled(false);
}
if (isdiff)
{
m_Controls->m_MovingChannelBox->setEnabled(true);
if (fourth_dim_size>1)
m_Controls->m_MovingChannelBox->setMaximum(fourth_dim_size-1);
else if (isdiff)
m_Controls->m_MovingChannelBox->setMaximum(mitk::DiffusionPropertyHelper::GetGradientContainer(image)->Size()-1);
}
else
{
m_Controls->m_MovingChannelBox->setEnabled(false);
}
m_Controls->m_RegistrationStartButton->setEnabled(true);
}
else
{
m_Controls->m_MovingChannelBox->setEnabled(false);
m_Controls->m_RegistrationStartButton->setEnabled(false);
}
}
void QmitkSimpleRegistrationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList<mitk::DataNode::Pointer>& )
{
FixedImageChanged();
MovingImageChanged();
TractoChanged();
}
void QmitkSimpleRegistrationView::SetFocus()
{
m_Controls->m_RegistrationStartButton->setFocus();
FixedImageChanged();
MovingImageChanged();
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.h
index bee2b0a..33a9180 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/QmitkSimpleRegistrationView.h
@@ -1,75 +1,75 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 <berryISelectionListener.h>
#include <berryIStructuredSelection.h>
#include <QmitkAbstractView.h>
#include "ui_QmitkSimpleRegistrationViewControls.h"
#include <mitkImage.h>
#include <QmitkRegistrationJob.h>
typedef short DiffusionPixelType;
/*!
\brief View for diffusion image registration / head motion correction
*/
// Forward Qt class declarations
class QmitkSimpleRegistrationView : public QmitkAbstractView
{
// 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:
typedef itk::Image< float, 3 > ItkFloatImageType;
typedef itk::Image<DiffusionPixelType, 3> ITKDiffusionVolumeType;
typedef itk::VectorImage< short, 3 > ItkDwiType;
static const std::string VIEW_ID;
QmitkSimpleRegistrationView();
virtual ~QmitkSimpleRegistrationView();
virtual void CreateQtPartControl(QWidget *parent) override;
void SetFocus() override;
protected slots:
void MovingImageChanged();
void FixedImageChanged();
void TractoChanged();
void StartRegistration();
void StartTractoRegistration();
void OnRegResultIsAvailable(mitk::MAPRegistrationWrapper::Pointer spResultRegistration, const QmitkRegistrationJob* pRegJob);
protected:
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
Ui::QmitkSimpleRegistrationViewControls* m_Controls;
mitk::DataNode::Pointer m_MovingImageNode;
int m_RegistrationType;
private:
};
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/mitkPluginActivator.cpp
index 31c32b0..0502f16 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/mitkPluginActivator.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/mitkPluginActivator.cpp
@@ -1,41 +1,41 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPluginActivator.h"
#include "src/internal/QmitkHeadMotionCorrectionView.h"
#include "src/internal/QmitkSimpleRegistrationView.h"
ctkPluginContext* mitk::PluginActivator::m_Context = nullptr;
ctkPluginContext* mitk::PluginActivator::GetContext()
{
return m_Context;
}
void mitk::PluginActivator::start(ctkPluginContext* context)
{
BERRY_REGISTER_EXTENSION_CLASS(QmitkHeadMotionCorrectionView, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkSimpleRegistrationView, context)
m_Context = context;
}
void mitk::PluginActivator::stop(ctkPluginContext* context)
{
Q_UNUSED(context)
m_Context = nullptr;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/mitkPluginActivator.h
index d5484a0..1e611e0 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/mitkPluginActivator.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.registration/src/internal/mitkPluginActivator.h
@@ -1,40 +1,40 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKPLUGINACTIVATOR_H
#define MITKPLUGINACTIVATOR_H
#include <ctkPluginActivator.h>
namespace mitk
{
class PluginActivator : public QObject, public ctkPluginActivator
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.mitk.gui.qt.diffusionimaging.registration")
Q_INTERFACES(ctkPluginActivator)
public:
static ctkPluginContext* GetContext();
void start(ctkPluginContext* context) override;
void stop(ctkPluginContext* context) override;
private:
static ctkPluginContext* m_Context;
};
}
#endif
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/QmitkTbssRoiAnalysisWidget.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/QmitkTbssRoiAnalysisWidget.cpp
index 2686ec8..f6f2383 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/QmitkTbssRoiAnalysisWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/QmitkTbssRoiAnalysisWidget.cpp
@@ -1,967 +1,967 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkTbssRoiAnalysisWidget.h"
#include "mitkImagePixelReadAccessor.h"
#include "mitkPixelTypeMultiplex.h"
#include <qwt_plot_marker.h>
#include <qwt_plot_picker.h>
#include <qwt_picker_machine.h>
#include <vtkCellArray.h>
QmitkTbssRoiAnalysisWidget::QmitkTbssRoiAnalysisWidget( QWidget * parent )
: QmitkPlotWidget(parent)
{
m_PlotPicker = new QwtPlotPicker(m_Plot->canvas());
m_PlotPicker->setStateMachine(new QwtPickerDragPointMachine());
m_PlotPicker->setTrackerMode(QwtPicker::ActiveOnly);
m_PlottingFiberBundle = false;
}
void QmitkTbssRoiAnalysisWidget::DoPlotFiberBundles(mitk::FiberBundle *fib, mitk::Image* img,
mitk::DataNode* startRoi, mitk::DataNode* endRoi, bool avg, int number)
{
TractContainerType tracts = CreateTracts(fib, startRoi, endRoi);
TractContainerType resampledTracts = ParameterizeTracts(tracts, number);
// Now we have the resampled tracts. Next we should use these points to read out the values
mitkPixelTypeMultiplex3(PlotFiberBundles,img->GetImageDescriptor()->GetChannelTypeById(0),resampledTracts, img, avg);
m_CurrentTracts = resampledTracts;
}
TractContainerType QmitkTbssRoiAnalysisWidget::CreateTracts(mitk::FiberBundle *fib,
mitk::DataNode *startRoi,
mitk::DataNode *endRoi)
{
mitk::PlaneGeometry* startGeometry2D = const_cast<mitk::PlaneGeometry*>(dynamic_cast<mitk::PlanarFigure*>(startRoi->GetData())->GetPlaneGeometry());
mitk::PlaneGeometry* endGeometry2D = const_cast<mitk::PlaneGeometry*>(dynamic_cast<mitk::PlanarFigure*>(endRoi->GetData())->GetPlaneGeometry());
mitk::Point3D startCenter = dynamic_cast<mitk::PlanarFigure*>(startRoi->GetData())->GetWorldControlPoint(0); //center Point of start roi
mitk::Point3D endCenter = dynamic_cast<mitk::PlanarFigure*>(startRoi->GetData())->GetWorldControlPoint(0); //center Point of end roi
mitk::FiberBundle::Pointer inStart = fib->ExtractFiberSubset(startRoi, nullptr);
mitk::FiberBundle::Pointer inBoth = inStart->ExtractFiberSubset(endRoi, nullptr);
int num = inBoth->GetNumFibers();
TractContainerType tracts;
vtkSmartPointer<vtkPolyData> fiberPolyData = inBoth->GetFiberPolyData();
vtkCellArray* lines = fiberPolyData->GetLines();
lines->InitTraversal();
// Now find out for each fiber which ROI is encountered first. If this is the startRoi, the direction is ok
// Otherwise the plot should be in the reverse direction
for( int fiberID( 0 ); fiberID < num; fiberID++ )
{
vtkIdType numPointsInCell(0);
vtkIdType* pointsInCell(nullptr);
lines->GetNextCell ( numPointsInCell, pointsInCell );
int startId = 0;
int endId = 0;
mitk::ScalarType minDistStart = std::numeric_limits<mitk::ScalarType>::max();
mitk::ScalarType minDistEnd = std::numeric_limits<mitk::ScalarType>::max();
for( int pointInCellID( 0 ); pointInCellID < numPointsInCell ; pointInCellID++)
{
mitk::ScalarType *p = fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] );
mitk::Point3D point;
point[0] = p[0];
point[1] = p[1];
point[2] = p[2];
mitk::ScalarType distanceToStart = point.EuclideanDistanceTo(startCenter);
mitk::ScalarType distanceToEnd = point.EuclideanDistanceTo(endCenter);
if(distanceToStart < minDistStart)
{
minDistStart = distanceToStart;
startId = pointInCellID;
}
if(distanceToEnd < minDistEnd)
{
minDistEnd = distanceToEnd;
endId = pointInCellID;
}
}
/* We found the start and end points of of the part that should be plottet for
the current fiber. now we need to plot them. If the endId is smaller than the startId the plot order
must be reversed*/
TractType singleTract;
PointType point;
if(startId < endId)
{
// Calculate the intersection of the ROI with the startRoi and decide if the startId is part of the roi or must be cut of
mitk::ScalarType *p = fiberPolyData->GetPoint( pointsInCell[ startId ] );
mitk::Vector3D p0;
p0[0] = p[0]; p0[1] = p[1]; p0[2] = p[2];
p = fiberPolyData->GetPoint( pointsInCell[ startId+1 ] );
mitk::Vector3D p1;
p1[0] = p[0]; p1[1] = p[1]; p1[2] = p[2];
// Check if p and p2 are both on the same side of the plane
mitk::Vector3D normal = startGeometry2D->GetNormal();
mitk::Point3D pStart;
pStart[0] = p0[0]; pStart[1] = p0[1]; pStart[2] = p0[2];
mitk::Point3D pSecond;
pSecond[0] = p1[0]; pSecond[1] = p1[1]; pSecond[2] = p1[2];
bool startOnPositive = startGeometry2D->IsAbove(pStart);
bool secondOnPositive = startGeometry2D->IsAbove(pSecond);
mitk::Vector3D onPlane;
onPlane[0] = startCenter[0]; onPlane[1] = startCenter[1]; onPlane[2] = startCenter[2];
if(! (secondOnPositive ^ startOnPositive) )
{
/* startId and startId+1 lie on the same side of the plane, so we need
need startId-1 to calculate the intersection with the planar figure*/
p = fiberPolyData->GetPoint( pointsInCell[ startId-1 ] );
p1[0] = p[0]; p1[1] = p[1]; p1[2] = p[2];
}
mitk::ScalarType d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal );
mitk::Vector3D newPoint = (p0-p1);
point[0] = d*newPoint[0] + p0[0];
point[1] = d*newPoint[1] + p0[1];
point[2] = d*newPoint[2] + p0[2];
singleTract.push_back(point);
if(! (secondOnPositive ^ startOnPositive) )
{
/* StartId and startId+1 lie on the same side of the plane
so startId is also part of the ROI*/
mitk::ScalarType *start = fiberPolyData->GetPoint( pointsInCell[startId] );
point[0] = start[0]; point[1] = start[1]; point[2] = start[2];
singleTract.push_back(point);
}
for( int pointInCellID( startId+1 ); pointInCellID < endId ; pointInCellID++)
{
// push back point
mitk::ScalarType *p = fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] );
point[0] = p[0]; point[1] = p[1]; point[2] = p[2];
singleTract.push_back( point );
}
/* endId must be included if endId and endId-1 lie on the same side of the
plane defined by endRoi*/
p = fiberPolyData->GetPoint( pointsInCell[ endId ] );
p0[0] = p[0]; p0[1] = p[1]; p0[2] = p[2];
p = fiberPolyData->GetPoint( pointsInCell[ endId-1 ] );
p1[0] = p[0]; p1[1] = p[1]; p1[2] = p[2];
mitk::Point3D pLast;
pLast[0] = p0[0]; pLast[1] = p0[1]; pLast[2] = p0[2];
mitk::Point3D pBeforeLast;
pBeforeLast[0] = p1[0]; pBeforeLast[1] = p1[1]; pBeforeLast[2] = p1[2];
normal = endGeometry2D->GetNormal();
bool lastOnPositive = endGeometry2D->IsAbove(pLast);
bool secondLastOnPositive = endGeometry2D->IsAbove(pBeforeLast);
onPlane[0] = endCenter[0];
onPlane[1] = endCenter[1];
onPlane[2] = endCenter[2];
if(! (lastOnPositive ^ secondLastOnPositive) )
{
/* endId and endId-1 lie on the same side of the plane, so we need
need endId+1 to calculate the intersection with the planar figure.
this should exist since we know that the fiber crosses the planar figure
endId is also part of the tract and can be inserted here */
p = fiberPolyData->GetPoint( pointsInCell[ endId ] );
point[0] = p[0]; point[1] = p[1]; point[2] = p[2];
singleTract.push_back( point );
p = fiberPolyData->GetPoint( pointsInCell[ endId+1 ] );
}
d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal );
newPoint = (p0-p1);
point[0] = d*newPoint[0] + p0[0];
point[1] = d*newPoint[1] + p0[1];
point[2] = d*newPoint[2] + p0[2];
singleTract.push_back(point);
}
else{
// Calculate the intersection of the ROI with the startRoi and decide if the startId is part of the roi or must be cut of
mitk::ScalarType *p = fiberPolyData->GetPoint( pointsInCell[ startId ] );
mitk::Vector3D p0;
p0[0] = p[0]; p0[1] = p[1]; p0[2] = p[2];
p = fiberPolyData->GetPoint( pointsInCell[ startId-1 ] );
mitk::Vector3D p1;
p1[0] = p[0]; p1[1] = p[1]; p1[2] = p[2];
// Check if p and p2 are both on the same side of the plane
mitk::Vector3D normal = startGeometry2D->GetNormal();
mitk::Point3D pStart;
pStart[0] = p0[0]; pStart[1] = p0[1]; pStart[2] = p0[2];
mitk::Point3D pSecond;
pSecond[0] = p1[0]; pSecond[1] = p1[1]; pSecond[2] = p1[2];
bool startOnPositive = startGeometry2D->IsAbove(pStart);
bool secondOnPositive = startGeometry2D->IsAbove(pSecond);
mitk::Vector3D onPlane;
onPlane[0] = startCenter[0]; onPlane[1] = startCenter[1]; onPlane[2] = startCenter[2];
if(! (secondOnPositive ^ startOnPositive) )
{
/* startId and startId+1 lie on the same side of the plane, so we need
need startId-1 to calculate the intersection with the planar figure*/
p = fiberPolyData->GetPoint( pointsInCell[ startId-1 ] );
p1[0] = p[0]; p1[1] = p[1]; p1[2] = p[2];
}
mitk::ScalarType d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal );
mitk::Vector3D newPoint = (p0-p1);
point[0] = d*newPoint[0] + p0[0];
point[1] = d*newPoint[1] + p0[1];
point[2] = d*newPoint[2] + p0[2];
singleTract.push_back(point);
if(! (secondOnPositive ^ startOnPositive) )
{
/* StartId and startId+1 lie on the same side of the plane
so startId is also part of the ROI*/
mitk::ScalarType *start = fiberPolyData->GetPoint( pointsInCell[startId] );
point[0] = start[0]; point[1] = start[1]; point[2] = start[2];
singleTract.push_back(point);
}
for( int pointInCellID( startId-1 ); pointInCellID > endId ; pointInCellID--)
{
// push back point
mitk::ScalarType *p = fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] );
point[0] = p[0]; point[1] = p[1]; point[2] = p[2];
singleTract.push_back( point );
}
/* endId must be included if endId and endI+1 lie on the same side of the
plane defined by endRoi*/
p = fiberPolyData->GetPoint( pointsInCell[ endId ] );
p0[0] = p[0]; p0[1] = p[1]; p0[2] = p[2];
p = fiberPolyData->GetPoint( pointsInCell[ endId+1 ] );
p1[0] = p[0]; p1[1] = p[1]; p1[2] = p[2];
mitk::Point3D pLast;
pLast[0] = p0[0]; pLast[1] = p0[1]; pLast[2] = p0[2];
mitk::Point3D pBeforeLast;
pBeforeLast[0] = p1[0]; pBeforeLast[1] = p1[1]; pBeforeLast[2] = p1[2];
bool lastOnPositive = endGeometry2D->IsAbove(pLast);
bool secondLastOnPositive = endGeometry2D->IsAbove(pBeforeLast);
normal = endGeometry2D->GetNormal();
onPlane[0] = endCenter[0];
onPlane[1] = endCenter[1];
onPlane[2] = endCenter[2];
if(! (lastOnPositive ^ secondLastOnPositive) )
{
/* endId and endId+1 lie on the same side of the plane, so we need
need endId-1 to calculate the intersection with the planar figure.
this should exist since we know that the fiber crosses the planar figure
endId is also part of the tract and can be inserted here */
p = fiberPolyData->GetPoint( pointsInCell[ endId ] );
point[0] = p[0]; point[1] = p[1]; point[2] = p[2];
singleTract.push_back( point );
p = fiberPolyData->GetPoint( pointsInCell[ endId-1 ] );
}
d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal );
newPoint = (p0-p1);
point[0] = d*newPoint[0] + p0[0];
point[1] = d*newPoint[1] + p0[1];
point[2] = d*newPoint[2] + p0[2];
singleTract.push_back(point);
}
tracts.push_back(singleTract);
}
return tracts;
}
void QmitkTbssRoiAnalysisWidget::PlotFiberBetweenRois(mitk::FiberBundle *fib, mitk::Image* img,
mitk::DataNode* startRoi, mitk::DataNode* endRoi, bool avg, int number)
{
if(fib == nullptr || img == nullptr || startRoi == nullptr || endRoi == nullptr)
return;
m_Fib = fib;
m_CurrentImage = img;
m_CurrentStartRoi = startRoi;
m_CurrentEndRoi = endRoi;
DoPlotFiberBundles(fib, img, startRoi, endRoi, avg, number);
}
void QmitkTbssRoiAnalysisWidget::ModifyPlot(int number, bool avg)
{
if(m_Fib == nullptr || m_CurrentTbssImage == nullptr || m_CurrentStartRoi == nullptr || m_CurrentEndRoi == nullptr)
return;
if(m_PlottingFiberBundle)
{
DoPlotFiberBundles(m_Fib, m_CurrentImage, m_CurrentStartRoi, m_CurrentEndRoi, avg, number);
}
else
{
PlotFiber4D(m_CurrentTbssImage, m_Fib, m_CurrentStartRoi, m_CurrentEndRoi, number);
}
}
TractContainerType QmitkTbssRoiAnalysisWidget::ParameterizeTracts(TractContainerType tracts, int number)
{
TractContainerType resampledTracts;
for(auto it = tracts.begin(); it != tracts.end(); ++it)
{
TractType resampledTract;
TractType tract = *it;
// Calculate the total length
mitk::ScalarType totalLength = 0;
if(tract.size() < 2)
continue;
PointType p0 = tract.at(0);
for(unsigned int i = 1; i<tract.size(); i++)
{
PointType p1 = tract.at(i);
mitk::ScalarType length = p0.EuclideanDistanceTo(p1);
totalLength += length;
p0 = p1;
}
mitk::ScalarType stepSize = totalLength / number;
p0 = tract.at(0);
PointType p1 = tract.at(1);
unsigned int tractCounter = 2;
mitk::ScalarType distance = p0.EuclideanDistanceTo(p1);
mitk::ScalarType locationBetween = 0;
for(mitk::ScalarType position = 0;
position <= totalLength+0.001 && static_cast<int>(resampledTract.size()) <= (number+1);
position+=stepSize)
{
/* In case we walked to far we need to find the next segment we are on and on what relative position on that
tract we are on. Small correction for rounding errors */
while(locationBetween > distance+0.001)
{
if(tractCounter == tract.size())
std::cout << "problem";
// Determine by what distance we are no on the next segment
locationBetween = locationBetween - distance;
p0 = p1;
p1 = tract.at(tractCounter);
tractCounter++;
distance = p0.EuclideanDistanceTo(p1);
}
// Direction
PointType::VectorType direction = p1-p0;
direction.Normalize();
PointType newSample = p0 + direction*locationBetween;
resampledTract.push_back(newSample);
locationBetween += stepSize;
}
resampledTracts.push_back(resampledTract);
}
return resampledTracts;
}
mitk::Point3D QmitkTbssRoiAnalysisWidget::GetPositionInWorld(int index)
{
mitk::ScalarType xSum = 0.0;
mitk::ScalarType ySum = 0.0;
mitk::ScalarType zSum = 0.0;
for(auto it = m_CurrentTracts.begin();
it!=m_CurrentTracts.end(); ++it)
{
TractType tract = *it;
PointType p = tract.at(index);
xSum += p[0];
ySum += p[1];
zSum += p[2];
}
int number = m_CurrentTracts.size();
mitk::ScalarType xPos = xSum / number;
mitk::ScalarType yPos = ySum / number;
mitk::ScalarType zPos = zSum / number;
mitk::Point3D pos;
pos[0] = xPos;
pos[1] = yPos;
pos[2] = zPos;
return pos;
}
std::vector< std::vector<mitk::ScalarType> > QmitkTbssRoiAnalysisWidget::CalculateGroupProfiles()
{
MITK_INFO << "make profiles!";
std::vector< std::vector<mitk::ScalarType> > profiles;
int size = m_Projections->GetVectorLength();
for(int s=0; s<size; s++)
{
// Iterate trough the roi
std::vector<mitk::ScalarType> profile;
RoiType::iterator it;
it = m_Roi.begin();
while(it != m_Roi.end())
{
itk::Index<3> ix = *it;
profile.push_back(m_Projections->GetPixel(ix).GetElement(s));
it++;
}
profiles.push_back(profile);
}
m_IndividualProfiles = profiles;
// Calculate the averages
// Here a check could be build in to check whether all profiles have
// the same length, but this should normally be the case if the input
// data were corrected with the TBSS Module.
std::vector< std::vector<mitk::ScalarType> > groupProfiles;
std::vector< std::pair<std::string, int> >::iterator it;
it = m_Groups.begin();
int c = 0; //the current profile number
while(it != m_Groups.end() && profiles.size() > 0)
{
std::pair<std::string, int> p = *it;
int size = p.second;
//initialize a vector of the right length with zeroes
std::vector<mitk::ScalarType> averageProfile;
for(unsigned int i=0; i<profiles.at(0).size(); i++)
{
averageProfile.push_back(0.0);
}
// Average the right number of profiles
for(int i=0; i<size; i++)
{
for(unsigned int j=0; j<averageProfile.size(); ++j)
{
averageProfile.at(j) = averageProfile.at(j) + profiles.at(c).at(j);
}
c++;
}
// Divide by the number of profiles to get group average
for(unsigned int i=0; i<averageProfile.size(); i++)
{
averageProfile.at(i) = averageProfile.at(i) / size;
}
groupProfiles.push_back(averageProfile);
++it;
}
return groupProfiles;
}
void QmitkTbssRoiAnalysisWidget::DrawProfiles()
{
std::vector <std::vector<mitk::ScalarType> > groupProfiles = CalculateGroupProfiles();
Plot(groupProfiles);
}
void QmitkTbssRoiAnalysisWidget::Plot(std::vector <std::vector<mitk::ScalarType> > groupProfiles)
{
this->Clear();
m_Vals.clear();
std::vector<mitk::ScalarType> v1;
std::vector<mitk::ScalarType> xAxis;
for(unsigned int i=0; i<groupProfiles.at(0).size(); ++i)
{
xAxis.push_back((mitk::ScalarType)i);
}
// fill m_Vals. This might be used by the user to copy data to the clipboard
for(unsigned int i=0; i<groupProfiles.size(); i++)
{
v1.clear();
for(unsigned int j=0; j<groupProfiles.at(i).size(); j++)
{
v1.push_back(groupProfiles.at(i).at(j));
}
m_Vals.push_back(v1);
}
std::string title = m_Measure + " profiles on the ";
title.append(m_Structure);
this->SetPlotTitle( title.c_str() );
QPen pen( Qt::SolidLine );
pen.setWidth(2);
std::vector< std::pair<std::string, int> >::iterator it;
it = m_Groups.begin();
int c = 0; //the current profile number
QColor colors[4] = {Qt::green, Qt::blue, Qt::yellow, Qt::red};
while(it != m_Groups.end() && groupProfiles.size() > 0)
{
std::pair< std::string, int > group = *it;
pen.setColor(colors[c]);
int curveId = this->InsertCurve( group.first.c_str() );
this->SetCurveData( curveId, xAxis, groupProfiles.at(c) );
this->SetCurvePen( curveId, pen );
c++;
it++;
}
auto legend = new QwtLegend;
this->SetLegend(legend, QwtPlot::RightLegend, 0.5);
std::cout << m_Measure << std::endl;
this->m_Plot->setAxisTitle(0, m_Measure.c_str());
this->m_Plot->setAxisTitle(3, "Position");
this->Replot();
}
std::vector< std::vector<mitk::ScalarType> > QmitkTbssRoiAnalysisWidget::CalculateGroupProfilesFibers(mitk::TbssImage::Pointer tbssImage,
mitk::FiberBundle *fib,
mitk::DataNode* startRoi,
mitk::DataNode* endRoi,
int number)
{
TractContainerType tracts = CreateTracts(fib, startRoi, endRoi);
TractContainerType resampledTracts = ParameterizeTracts(tracts, number);
int nTracts = resampledTracts.size();
this->Clear();
// For every group we have m fibers * n subjects of profiles to fill
std::vector< std::vector<mitk::ScalarType> > profiles;
// calculate individual profiles by going through all n subjects
int size = m_Projections->GetVectorLength();
for(int s=0; s<size; s++)
{
// Iterate through all tracts
for(int t=0; t<nTracts; t++)
{
// Iterate trough the tract
std::vector<mitk::ScalarType> profile;
auto it = resampledTracts[t].begin();
while(it != resampledTracts[t].end())
{
PointType p = *it;
PointType index;
tbssImage->GetGeometry()->WorldToIndex(p, index);
itk::Index<3> ix;
ix[0] = index[0];
ix[1] = index[1];
ix[2] = index[2];
// Get value from image
profile.push_back(m_Projections->GetPixel(ix).GetElement(s));
it++;
}
profiles.push_back(profile);
}
}
m_IndividualProfiles = profiles;
// Now create the group averages (every group contains m fibers * n_i group members
std::vector< std::pair<std::string, int> >::iterator it;
it = m_Groups.begin();
int c = 0; //the current profile number
// Calculate the group averages
std::vector< std::vector<mitk::ScalarType> > groupProfiles;
while(it != m_Groups.end() && profiles.size() > 0)
{
std::pair<std::string, int> p = *it;
int size = p.second;
//initialize a vector of the right length with zeroes
std::vector<mitk::ScalarType> averageProfile;
for(unsigned int i=0; i<profiles.at(0).size(); i++)
{
averageProfile.push_back(0.0);
}
// Average the right number of profiles
for(int i=0; i<size*nTracts; i++)
{
for(unsigned int j=0; j<averageProfile.size(); ++j)
{
averageProfile.at(j) = averageProfile.at(j) + profiles.at(c).at(j);
}
c++;
}
// Divide by the number of profiles to get group average
for(unsigned int i=0; i<averageProfile.size(); i++)
{
averageProfile.at(i) = averageProfile.at(i) / (size*nTracts);
}
groupProfiles.push_back(averageProfile);
++it;
}
return groupProfiles;
}
void QmitkTbssRoiAnalysisWidget::PlotFiber4D(mitk::TbssImage::Pointer tbssImage,
mitk::FiberBundle *fib,
mitk::DataNode* startRoi,
mitk::DataNode* endRoi,
int number)
{
m_PlottingFiberBundle = false;
m_Fib = fib;
m_CurrentStartRoi = startRoi;
m_CurrentEndRoi = endRoi;
m_CurrentTbssImage = tbssImage;
std::vector <std::vector<mitk::ScalarType> > groupProfiles = CalculateGroupProfilesFibers(tbssImage, fib, startRoi, endRoi, number);
Plot(groupProfiles);
}
template <typename T>
void QmitkTbssRoiAnalysisWidget::PlotFiberBundles(const mitk::PixelType, TractContainerType tracts, mitk::Image *img, bool avg)
{
m_PlottingFiberBundle = true;
this->Clear();
auto it = tracts.begin();
std::vector< std::vector <mitk::ScalarType > > profiles;
mitk::ImagePixelReadAccessor<T,3> imAccess(img,img->GetVolumeData(0));
it = tracts.begin();
while(it != tracts.end())
{
TractType tract = *it;
auto tractIt = tract.begin();
std::vector<mitk::ScalarType> profile;
while(tractIt != tract.end())
{
PointType p = *tractIt;
// Get value from image
profile.push_back( (mitk::ScalarType) imAccess.GetPixelByWorldCoordinates(p) );
++tractIt;
}
profiles.push_back(profile);
std::cout << std::endl;
++it;
}
if(profiles.size() == 0)
return;
m_IndividualProfiles = profiles;
std::string title = "Fiber bundle plot";
this->SetPlotTitle( title.c_str() );
// initialize average profile
std::vector<mitk::ScalarType> averageProfile;
std::vector<mitk::ScalarType> profile = profiles.at(0); // can do this because we checked the size of profiles before
for(unsigned int i=0; i<profile.size(); ++i)
{
averageProfile.push_back(0.0);
}
auto profit = profiles.begin();
int id=0;
while(profit != profiles.end())
{
std::vector<mitk::ScalarType> profile = *profit;
std::vector<mitk::ScalarType> xAxis;
for(unsigned int i=0; i<profile.size(); ++i)
{
xAxis.push_back((mitk::ScalarType)i);
averageProfile.at(i) += profile.at(i) / profiles.size();
}
int curveId = this->InsertCurve( "" );
this->SetCurveData( curveId, xAxis, profile );
++profit;
id++;
}
m_Average = averageProfile;
if(avg)
{
// Draw the average profile
std::vector<mitk::ScalarType> xAxis;
for(unsigned int i=0; i<averageProfile.size(); ++i)
{
xAxis.push_back((mitk::ScalarType)i);
}
int curveId = this->InsertCurve( "" );
this->SetCurveData( curveId, xAxis, averageProfile );
QPen pen( Qt::SolidLine );
pen.setWidth(3);
pen.setColor(Qt::red);
this->SetCurvePen( curveId, pen );
id++;
}
this->Replot();
}
void QmitkTbssRoiAnalysisWidget::drawBar(int x)
{
m_Plot->detachItems(QwtPlotItem::Rtti_PlotMarker, true);
QwtPlotMarker *mX = new QwtPlotMarker();
//mX->setLabel(QString::fromLatin1("selected point"));
mX->setLabelAlignment(Qt::AlignLeft | Qt::AlignBottom);
mX->setLabelOrientation(Qt::Vertical);
mX->setLineStyle(QwtPlotMarker::VLine);
mX->setLinePen(QPen(Qt::black, 0, Qt::SolidLine));
mX->setXValue(x);
mX->attach(m_Plot);
this->Replot();
}
QmitkTbssRoiAnalysisWidget::~QmitkTbssRoiAnalysisWidget()
{
delete m_PlotPicker;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/QmitkTbssRoiAnalysisWidget.h b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/QmitkTbssRoiAnalysisWidget.h
index 159b3f4..0c52ac0 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/QmitkTbssRoiAnalysisWidget.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/QmitkTbssRoiAnalysisWidget.h
@@ -1,230 +1,230 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkTbssRoiAnalysisWidget_H_
#define QmitkTbssRoiAnalysisWidget_H_
#include "QmitkPlotWidget.h"
#include <org_mitk_gui_qt_diffusionimaging_tbss_Export.h>
#include <mitkFiberBundle.h>
#include <mitkTbssImage.h>
#include <itkVectorImage.h>
typedef itk::VectorImage<float,3> VectorImageType;
typedef std::vector< itk::Index<3> > RoiType;
typedef mitk::Point3D PointType;
typedef std::vector< PointType> TractType;
typedef std::vector< TractType > TractContainerType;
class QwtPlotPicker;
/**
* \brief Plot widget for TBSS Data
* This widget can plot regions of interest on TBSS projection data. The projection data is created by importing FSL TBSS subject data and
* completing it with patient data using the QmitkTractbasedSpatialStatisticsView.
* The region of interest is a vector of indices from which data for plotting should be obtained.
*/
class DIFFUSIONIMAGING_TBSS_EXPORT QmitkTbssRoiAnalysisWidget : public QmitkPlotWidget
{
Q_OBJECT
public:
QmitkTbssRoiAnalysisWidget( QWidget * parent);
virtual ~QmitkTbssRoiAnalysisWidget();
/* \brief Set group information as a vector of pairs of group name and number of group members */
void SetGroups(std::vector< std::pair<std::string, int> > groups)
{
m_Groups = groups;
}
/* \brief Draws the group averaged profiles */
void DrawProfiles();
void PlotFiber4D(mitk::TbssImage::Pointer tbssImage,
mitk::FiberBundle *fib,
mitk::DataNode *startRoi,
mitk::DataNode *endRoi,
int number);
template <typename T>
void PlotFiberBundles(const mitk::PixelType, TractContainerType tracts, mitk::Image* img, bool avg=false);
/* \brief Sets the projections of the individual subjects */
void SetProjections(VectorImageType::Pointer projections)
{
m_Projections = projections;
}
/* \brief Set the region of interest*/
void SetRoi(RoiType roi)
{
m_Roi = roi;
}
/* \brief Set structure information to display in the plot */
void SetStructure(std::string structure)
{
m_Structure = structure;
}
/* \brief Set measurement type for display in the plot */
void SetMeasure(std::string measure)
{
m_Measure = measure;
}
/* \brief Draws a bar to indicate were the user clicked in the plot */
void drawBar(int x);
/* \brief Returns the values of the group averaged profiles */
std::vector <std::vector<double> > GetVals()
{
return m_Vals;
}
/* \brief Returns the values of the individual subjects profiles */
std::vector <std::vector<double> > GetIndividualProfiles()
{
return m_IndividualProfiles;
}
std::vector<double> GetAverageProfile()
{
return m_Average;
}
void SetPlottingFiber(bool b)
{
m_PlottingFiberBundle = b;
}
bool IsPlottingFiber()
{
return m_PlottingFiberBundle;
}
void PlotFiberBetweenRois(mitk::FiberBundle *fib, mitk::Image* img,
mitk::DataNode *startRoi, mitk::DataNode *endRoi, bool avg=-1, int number=25);
// Takes an index which is an x coordinate from the plot and finds the corresponding position in world space
mitk::Point3D GetPositionInWorld(int index);
void ModifyPlot(int number, bool avg);
QwtPlotPicker* m_PlotPicker;
protected:
mitk::FiberBundle* m_Fib;
std::vector< std::vector<double> > m_Vals;
std::vector< std::vector<double> > m_IndividualProfiles;
std::vector< double > m_Average;
std::vector< std::vector<double> > CalculateGroupProfiles();
std::vector< std::vector<double> > CalculateGroupProfilesFibers(mitk::TbssImage::Pointer tbssImage,
mitk::FiberBundle *fib,
mitk::DataNode* startRoi,
mitk::DataNode* endRoi,
int number);
void Plot(std::vector <std::vector<double> > groupProfiles);
void Tokenize(const std::string& str,
std::vector<std::string>& tokens,
const std::string& delimiters = " ")
{
// Skip delimiters at beginning.
std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
// Find first "non-delimiter".
std::string::size_type pos = str.find_first_of(delimiters, lastPos);
while (std::string::npos != pos || std::string::npos != lastPos)
{
// Found a token, add it to the vector.
tokens.push_back(str.substr(lastPos, pos - lastPos));
// Skip delimiters. Note the "not_of"
lastPos = str.find_first_not_of(delimiters, pos);
// Find next "non-delimiter"
pos = str.find_first_of(delimiters, lastPos);
}
}
std::vector< std::pair<std::string, int> > m_Groups;
VectorImageType::Pointer m_Projections;
RoiType m_Roi;
std::string m_Structure;
std::string m_Measure;
bool m_PlottingFiberBundle; // true when the plot results from a fiber tracking result (vtk .fib file)
// Resample a collection of tracts so that every tract contains #number equidistant samples
TractContainerType ParameterizeTracts(TractContainerType tracts, int number);
TractContainerType m_CurrentTracts;
mitk::Image* m_CurrentImage;
mitk::TbssImage* m_CurrentTbssImage;
mitk::DataNode* m_CurrentStartRoi;
mitk::DataNode* m_CurrentEndRoi;
void DoPlotFiberBundles(mitk::FiberBundle *fib, mitk::Image* img,
mitk::DataNode* startRoi, mitk::DataNode* endRoi, bool avg=false, int number=25);
/* \brief Creates tracts from a mitk::FiberBundle and two planar figures indicating the start end end point */
TractContainerType CreateTracts(mitk::FiberBundle *fib, mitk::DataNode* startRoi, mitk::DataNode* endRoi);
};
#endif
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssMetaTableModel.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssMetaTableModel.cpp
index 6eecce3..d086393 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssMetaTableModel.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssMetaTableModel.cpp
@@ -1,149 +1,149 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkTbssMetaTableModel.h"
QmitkTbssMetaTableModel::QmitkTbssMetaTableModel(QObject *parent)
: QAbstractTableModel(parent)
{
}
QmitkTbssMetaTableModel::QmitkTbssMetaTableModel(QList< QPair<QString, QString> > pairs, QObject *parent)
: QAbstractTableModel(parent)
{
listOfPairs=pairs;
}
int QmitkTbssMetaTableModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return listOfPairs.size();
}
int QmitkTbssMetaTableModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return 2;
}
QVariant QmitkTbssMetaTableModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (index.row() >= listOfPairs.size() || index.row() < 0)
return QVariant();
if (role == Qt::DisplayRole) {
QPair<QString, QString> pair = listOfPairs.at(index.row());
if (index.column() == 0)
return pair.first;
else if (index.column() == 1)
return pair.second;
}
return QVariant();
}
QVariant QmitkTbssMetaTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Horizontal) {
switch (section) {
case 0:
return tr("Image");
case 1:
return tr("Filename");
default:
return QVariant();
}
}
return QVariant();
}
bool QmitkTbssMetaTableModel::insertRows(int position, int rows, const QModelIndex &index)
{
Q_UNUSED(index);
beginInsertRows(QModelIndex(), position, position+rows-1);
for (int row=0; row < rows; row++) {
QPair<QString, QString> pair("Image ", "Filename");
listOfPairs.insert(position, pair);
}
endInsertRows();
return true;
}
bool QmitkTbssMetaTableModel::removeRows(int position, int rows, const QModelIndex &index)
{
Q_UNUSED(index);
beginRemoveRows(QModelIndex(), position, position+rows-1);
for (int row=0; row < rows; ++row) {
listOfPairs.removeAt(position);
}
endRemoveRows();
return true;
}
bool QmitkTbssMetaTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (index.isValid() && role == Qt::EditRole) {
int row = index.row();
QPair<QString, QString> p = listOfPairs.value(row);
if (index.column() == 0)
p.first = value.toString();
else if (index.column() == 1)
p.second = value.toString();
else
return false;
listOfPairs.replace(row, p);
emit(dataChanged(index, index));
return true;
}
return false;
}
Qt::ItemFlags QmitkTbssMetaTableModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::ItemIsEnabled;
return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
}
QList< QPair<QString, QString> > QmitkTbssMetaTableModel::getList()
{
return listOfPairs;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssMetaTableModel.h b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssMetaTableModel.h
index 6e0d7f6..b0ff0c5 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssMetaTableModel.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssMetaTableModel.h
@@ -1,54 +1,54 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkTbssMetaTableModel_h
#define QmitkTbssMetaTableModel_h
#include <QAbstractTableModel>
#include <QPair>
#include <QList>
#include <QObject>
#include <QString>
class QmitkTbssMetaTableModel : public QAbstractTableModel
{
// TableModel to model pairs of group description and group number
public:
QmitkTbssMetaTableModel(QObject *parent=nullptr);
QmitkTbssMetaTableModel(QList< QPair<QString, QString> > listofPairs, QObject *parent=nullptr);
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override;
bool insertRows(int position, int rows, const QModelIndex &index=QModelIndex()) override;
bool removeRows(int position, int rows, const QModelIndex &index=QModelIndex()) override;
QList< QPair<QString, QString> > getList();
private:
QList< QPair<QString, QString> > listOfPairs;
};
#endif
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssSkeletonizationView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssSkeletonizationView.cpp
index 74cc4aa..2013b33 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssSkeletonizationView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssSkeletonizationView.cpp
@@ -1,502 +1,502 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// Qmitk
#include "QmitkTbssSkeletonizationView.h"
#include <itkSkeletonizationFilter.h>
#include <itkProjectionFilter.h>
#include <itkDistanceMapFilter.h>
#include <itkBinaryThresholdImageFilter.h>
#include <itkImageFileReader.h>
// mitk
#include <mitkImagePixelReadAccessor.h>
#include <mitkImagePixelWriteAccessor.h>
#include <mitkPixelTypeMultiplex.h>
#include <mitkImage.h>
// Qt
#include <QInputDialog>
#include <QMessageBox>
//vtk
#include <vtkLinearTransform.h>
#include <vtkMatrix4x4.h>
// Boost
#include <mitkLexicalCast.h>
const std::string QmitkTbssSkeletonizationView::VIEW_ID = "org.mitk.views.tbssskeletonization";
using namespace berry;
QmitkTbssSkeletonizationView::QmitkTbssSkeletonizationView()
: QmitkAbstractView()
, m_Controls( 0 )
, m_Activated(false)
{
}
QmitkTbssSkeletonizationView::~QmitkTbssSkeletonizationView()
{
}
void QmitkTbssSkeletonizationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList<mitk::DataNode::Pointer>& nodes)
{
//datamanager selection changed
if (!this->IsActivated())
return;
bool found3dImage = false;
bool found4dImage = false;
this->m_Controls->m_TubularName->setText(QString("Tubular Structure Mask: "));
this->m_Controls->m_TubularName->setEnabled(false);
this->m_Controls->m_MeanLabel->setText(QString("Mean: "));
this->m_Controls->m_MeanLabel->setEnabled(false);
this->m_Controls->m_PatientDataLabel->setText(QString("Patient Data: "));
this->m_Controls->m_PatientDataLabel->setEnabled(false);
// iterate selection
for (mitk::DataNode::Pointer node: nodes)
{
// only look at interesting types from valid nodes
mitk::BaseData* nodeData = node->GetData();
std::string name = "";
node->GetStringProperty("name", name);
if(nodeData)
{
if(QString("Image").compare(nodeData->GetNameOfClass())==0)
{
mitk::Image* img = static_cast<mitk::Image*>(nodeData);
if(img->GetDimension() == 3)
{
bool isBinary(false);
node->GetBoolProperty("binary", isBinary);
if(isBinary)
{
QString label("Tubular Structure Mask: ");
label.append(QString(name.c_str()));
this->m_Controls->m_TubularName->setText(label);
this->m_Controls->m_TubularName->setEnabled(true);
}
else
{
found3dImage = true;
QString label("Mean: ");
label.append(QString(name.c_str()));
this->m_Controls->m_MeanLabel->setText(label);
this->m_Controls->m_MeanLabel->setEnabled(true);
}
}
else if(img->GetDimension() == 4)
{
found4dImage = true;
QString label("Patient Data: ");
label.append(QString(name.c_str()));
this->m_Controls->m_PatientDataLabel->setText(label);
this->m_Controls->m_PatientDataLabel->setEnabled(true);
}
}
}
}
this->m_Controls->m_Skeletonize->setEnabled(found3dImage);
this->m_Controls->m_Project->setEnabled(found3dImage && found4dImage);
this->m_Controls->m_OutputMask->setEnabled(found3dImage && found4dImage);
this->m_Controls->m_OutputDistanceMap->setEnabled(found3dImage && found4dImage);
}
void QmitkTbssSkeletonizationView::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::QmitkTbssSkeletonizationViewControls;
m_Controls->setupUi( parent );
this->CreateConnections();
}
}
void QmitkTbssSkeletonizationView::SetFocus()
{
m_Controls->m_Skeletonize->setFocus();
}
void QmitkTbssSkeletonizationView::Activated()
{
m_Activated = true;
}
void QmitkTbssSkeletonizationView::Deactivated()
{
m_Activated = false;
}
bool QmitkTbssSkeletonizationView::IsActivated() const
{
return m_Activated;
}
void QmitkTbssSkeletonizationView::Visible()
{
}
void QmitkTbssSkeletonizationView::Hidden()
{
}
void QmitkTbssSkeletonizationView::CreateConnections()
{
if ( m_Controls )
{
connect( (QObject*)(m_Controls->m_Skeletonize), SIGNAL(clicked()), this, SLOT(Skeletonize() ));
connect( (QObject*)(m_Controls->m_Project), SIGNAL(clicked()), this, SLOT(Project() ));
}
}
void QmitkTbssSkeletonizationView::Skeletonize()
{
typedef itk::SkeletonizationFilter<FloatImageType, FloatImageType> SkeletonisationFilterType;
SkeletonisationFilterType::Pointer skeletonizer = SkeletonisationFilterType::New();
QList<mitk::DataNode::Pointer> nodes = this->GetDataManagerSelection();
mitk::Image::Pointer meanImage = mitk::Image::New();
std::string name = "";
for (auto node: nodes)
{
// process only on valid nodes
mitk::BaseData* nodeData = node->GetData();
if(nodeData)
{
if(QString("Image").compare(nodeData->GetNameOfClass())==0)
{
bool isBinary(false);
node->GetBoolProperty("binary", isBinary);
mitk::Image* img = static_cast<mitk::Image*>(nodeData);
if(img->GetDimension() == 3 && !isBinary)
{
meanImage = img;
name = node->GetName();
}
}
}
}
// Calculate skeleton
FloatImageType::Pointer itkImg = FloatImageType::New();
mitk::CastToItkImage(meanImage, itkImg);
skeletonizer->SetInput(itkImg);
skeletonizer->Update();
FloatImageType::Pointer output = skeletonizer->GetOutput();
mitk::Image::Pointer mitkOutput = mitk::Image::New();
mitk::CastToMitkImage(output, mitkOutput);
name += "_skeleton";
AddToDataStorage(mitkOutput, name);
}
void QmitkTbssSkeletonizationView::Project()
{
typedef itk::SkeletonizationFilter<FloatImageType, FloatImageType> SkeletonisationFilterType;
typedef itk::ProjectionFilter ProjectionFilterType;
typedef itk::DistanceMapFilter<FloatImageType, FloatImageType> DistanceMapFilterType;
SkeletonisationFilterType::Pointer skeletonizer = SkeletonisationFilterType::New();
QList<mitk::DataNode::Pointer> nodes = this->GetDataManagerSelection();
mitk::Image::Pointer meanImage = mitk::Image::New();
mitk::Image::Pointer subjects = mitk::Image::New();
mitk::Image::Pointer tubular = mitk::Image::New();
for (auto node: nodes)
{
// process only on valid nodes
mitk::BaseData* nodeData = node->GetData();
if(nodeData)
{
if(QString("Image").compare(nodeData->GetNameOfClass())==0)
{
mitk::Image* img = static_cast<mitk::Image*>(nodeData);
if(img->GetDimension() == 3)
{
bool isBinary(false);
node->GetBoolProperty("binary", isBinary);
if(isBinary)
{
tubular = img;
}
else
{
meanImage = img;
}
}
else if(img->GetDimension() == 4)
{
subjects = img;
}
}
}
}
Float4DImageType::Pointer allFA;
mitkPixelTypeMultiplex2(ConvertToItk,subjects->GetChannelDescriptor().GetPixelType(),subjects, allFA);
// Calculate skeleton
FloatImageType::Pointer itkImg = FloatImageType::New();
mitk::CastToItkImage(meanImage, itkImg);
skeletonizer->SetInput(itkImg);
skeletonizer->Update();
FloatImageType::Pointer output = skeletonizer->GetOutput();
mitk::Image::Pointer mitkOutput = mitk::Image::New();
mitk::CastToMitkImage(output, mitkOutput);
AddToDataStorage(mitkOutput, "mean_FA_skeletonised");
// Retrieve direction image needed later by the projection filter
DirectionImageType::Pointer directionImg = skeletonizer->GetVectorImage();
// Calculate distance image
DistanceMapFilterType::Pointer distanceMapFilter = DistanceMapFilterType::New();
distanceMapFilter->SetInput(output);
distanceMapFilter->Update();
FloatImageType::Pointer distanceMap = distanceMapFilter->GetOutput();
if(m_Controls->m_OutputDistanceMap->isChecked())
{
mitk::Image::Pointer mitkDistance = mitk::Image::New();
mitk::CastToMitkImage(distanceMap, mitkDistance);
AddToDataStorage(mitkDistance, "distance map");
}
// Do projection
// Ask a threshold to create a skeleton mask
double threshold = -1.0;
while(threshold == -1.0)
{
threshold = QInputDialog::getDouble(m_Controls->m_Skeletonize, tr("Specify the FA threshold"),
tr("Threshold:"), QLineEdit::Normal,
0.2);
if(threshold < 0.0 || threshold > 1.0)
{
QMessageBox msgBox;
msgBox.setText("Please choose a value between 0 and 1");
msgBox.exec();
threshold = -1.0;
}
}
typedef itk::BinaryThresholdImageFilter<FloatImageType, CharImageType> ThresholdFilterType;
ThresholdFilterType::Pointer thresholder = ThresholdFilterType::New();
thresholder->SetInput(output);
thresholder->SetLowerThreshold(threshold);
thresholder->SetUpperThreshold(std::numeric_limits<float>::max());
thresholder->SetOutsideValue(0);
thresholder->SetInsideValue(1);
thresholder->Update();
CharImageType::Pointer thresholdedImg = thresholder->GetOutput();
if(m_Controls->m_OutputMask->isChecked())
{
mitk::Image::Pointer mitkThresholded = mitk::Image::New();
mitk::CastToMitkImage(thresholdedImg, mitkThresholded);
std::string maskName = "skeleton_mask_at_" + boost::lexical_cast<std::string>(threshold);
AddToDataStorage(mitkThresholded, maskName);
}
CharImageType::Pointer itkTubular = CharImageType::New();
mitk::CastToItkImage(tubular, itkTubular);
ProjectionFilterType::Pointer projectionFilter = ProjectionFilterType::New();
projectionFilter->SetDistanceMap(distanceMap);
projectionFilter->SetDirections(directionImg);
projectionFilter->SetAllFA(allFA);
projectionFilter->SetTube(itkTubular);
projectionFilter->SetSkeleton(thresholdedImg);
projectionFilter->Project();
Float4DImageType::Pointer projected = projectionFilter->GetProjections();
mitk::Image::Pointer mitkProjections = mitk::Image::New();
mitk::CastToMitkImage(projected, mitkProjections);
AddToDataStorage(mitkProjections, "all_FA_projected");
}
void QmitkTbssSkeletonizationView::AddToDataStorage(mitk::Image* img, std::string name)
{
mitk::DataNode::Pointer result = mitk::DataNode::New();
result->SetProperty( "name", mitk::StringProperty::New(name) );
result->SetData( img );
// add new image to data storage and set as active to ease further processing
GetDataStorage()->Add( result );
}
template <class TPixel>
void QmitkTbssSkeletonizationView::ConvertToItk(mitk::PixelType, mitk::Image* image, Float4DImageType::Pointer output)
{
output = Float4DImageType::New();
mitk::BaseGeometry* geo = image->GetGeometry();
mitk::Vector3D mitkSpacing = geo->GetSpacing();
mitk::Point3D mitkOrigin = geo->GetOrigin();
Float4DImageType::SpacingType spacing;
spacing[0] = mitkSpacing[0];
spacing[1] = mitkSpacing[1];
spacing[2] = mitkSpacing[2];
spacing[3] = 1.0; // todo: check if spacing has length 4
Float4DImageType::PointType origin;
origin[0] = mitkOrigin[0];
origin[1] = mitkOrigin[1];
origin[2] = mitkOrigin[2];
origin[3] = 0;
Float4DImageType::SizeType size;
size[0] = image->GetDimension(0);
size[1] = image->GetDimension(1);
size[2] = image->GetDimension(2);
size[3] = image->GetDimension(3);
Float4DImageType::DirectionType dir;
vtkLinearTransform* lin = geo->GetVtkTransform();
vtkMatrix4x4 *m = lin->GetMatrix();
dir.Fill(0.0);
for(int x=0; x<3; x++)
{
for(int y=0; y<3; y++)
{
dir[x][y] = m->GetElement(x,y);
}
}
dir[3][3] = 1;
output->SetSpacing(spacing);
output->SetOrigin(origin);
output->SetRegions(size);
output->SetDirection(dir);
output->Allocate();
if(image->GetDimension() == 4)
{
unsigned int timesteps = image->GetDimension(3);
try{
// REPLACE THIS METHODE()ConvertToItk) WITH mitk::CastToItk
// iterate through the subjects and copy data to output
for(unsigned int t=0; t<timesteps; t++)
{
mitk::ImagePixelReadAccessor <TPixel,3> inAcc(image,image->GetVolumeData(t));
for(unsigned int x=0; x<image->GetDimension(0); x++)
{
for(unsigned int y=0; y<image->GetDimension(1); y++)
{
for(unsigned int z=0; z<image->GetDimension(2); z++)
{
itk::Index<3> ix = {{x, y, z}};
itk::Index<4> ix4 = {{x, y, z, t}};
output->SetPixel(ix4, inAcc.GetPixelByIndex(ix));
}
}
}
}
}
catch(const std::exception & e)
{
MITK_INFO << e.what();
}
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssSkeletonizationView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssSkeletonizationView.h
index 2182f2e..b8e7824 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssSkeletonizationView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssSkeletonizationView.h
@@ -1,114 +1,114 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkTbssSkeletonizationView_h
#define QmitkTbssSkeletonizationView_h
#include <QmitkAbstractView.h>
#include <mitkILifecycleAwarePart.h>
#include "ui_QmitkTbssSkeletonizationViewControls.h"
#include "itkImage.h"
#include "mitkPixelType.h"
namespace mitk {
class Image;
}
typedef itk::Image<float, 3> FloatImageType;
typedef itk::Image<char, 3> CharImageType;
typedef itk::Image<float, 4> Float4DImageType;
typedef itk::CovariantVector<int,3> VectorType;
typedef itk::Image<VectorType, 3> DirectionImageType;
/*!
* \brief Implementation of the core functionality of TBSS.
* This plugin provides the core functionality of TBSS (see Smith et al., 2009. http://dx.doi.org/10.1016/j.neuroimage.2006.02.024)
* It can skeletonize a mean FA image and calculate the projection of all individual subjects to this skeleton.
*/
class QmitkTbssSkeletonizationView : public QmitkAbstractView, public mitk::ILifecycleAwarePart
{
Q_OBJECT
public:
static const std::string VIEW_ID;
QmitkTbssSkeletonizationView();
virtual ~QmitkTbssSkeletonizationView();
virtual void CreateQtPartControl(QWidget *parent) override;
//Creation of the connections of main and control widget
virtual void CreateConnections();
///
/// Sets the focus to an internal widget.
///
virtual void SetFocus() override;
/// \brief Called when the view gets activated
virtual void Activated() override;
/// \brief Called when the view gets deactivated
virtual void Deactivated() override;
bool IsActivated() const;
/// \brief Called when the view gets visible
virtual void Visible() override;
/// \brief Called when the view gets hidden
virtual void Hidden() override;
protected slots:
/* \brief Perform skeletonization only */
void Skeletonize();
// Perform skeletonization and Projection of subject data to the skeleton
void Project();
protected:
//brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
Ui::QmitkTbssSkeletonizationViewControls* m_Controls;
void AddToDataStorage(mitk::Image* img, std::string name);
template <class TPixel>
void ConvertToItk(mitk::PixelType, mitk::Image* image, Float4DImageType::Pointer);
private:
bool m_Activated;
};
#endif // _QMITKTbssSkeletonizationVIEW_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssTableModel.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssTableModel.cpp
index 7bf6c59..5f6fc77 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssTableModel.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssTableModel.cpp
@@ -1,149 +1,149 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkTbssTableModel.h"
QmitkTbssTableModel::QmitkTbssTableModel(QObject *parent)
: QAbstractTableModel(parent)
{
}
QmitkTbssTableModel::QmitkTbssTableModel(QList< QPair<QString, int> > pairs, QObject *parent)
: QAbstractTableModel(parent)
{
listOfPairs=pairs;
}
int QmitkTbssTableModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return listOfPairs.size();
}
int QmitkTbssTableModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return 2;
}
QVariant QmitkTbssTableModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (index.row() >= listOfPairs.size() || index.row() < 0)
return QVariant();
if (role == Qt::DisplayRole) {
QPair<QString, int> pair = listOfPairs.at(index.row());
if (index.column() == 0)
return pair.first;
else if (index.column() == 1)
return pair.second;
}
return QVariant();
}
QVariant QmitkTbssTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Horizontal) {
switch (section) {
case 0:
return tr("Group");
case 1:
return tr("Size");
default:
return QVariant();
}
}
return QVariant();
}
bool QmitkTbssTableModel::insertRows(int position, int rows, const QModelIndex &index)
{
Q_UNUSED(index);
beginInsertRows(QModelIndex(), position, position+rows-1);
for (int row=0; row < rows; row++) {
QPair<QString, int> pair(" ", 0);
listOfPairs.insert(position, pair);
}
endInsertRows();
return true;
}
bool QmitkTbssTableModel::removeRows(int position, int rows, const QModelIndex &index)
{
Q_UNUSED(index);
beginRemoveRows(QModelIndex(), position, position+rows-1);
for (int row=0; row < rows; ++row) {
listOfPairs.removeAt(position);
}
endRemoveRows();
return true;
}
bool QmitkTbssTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (index.isValid() && role == Qt::EditRole) {
int row = index.row();
QPair<QString, int> p = listOfPairs.value(row);
if (index.column() == 0)
p.first = value.toString();
else if (index.column() == 1)
p.second = value.toInt();
else
return false;
listOfPairs.replace(row, p);
emit(dataChanged(index, index));
return true;
}
return false;
}
Qt::ItemFlags QmitkTbssTableModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::ItemIsEnabled;
return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
}
QList< QPair<QString, int> > QmitkTbssTableModel::getList()
{
return listOfPairs;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssTableModel.h b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssTableModel.h
index 2dbfce7..443b6bb 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssTableModel.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTbssTableModel.h
@@ -1,52 +1,52 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkTbssTableModel_h
#define QmitkTbssTableModel_h
#include <QAbstractTableModel>
#include <QPair>
#include <QList>
#include <QObject>
class QmitkTbssTableModel : public QAbstractTableModel
{
//Q_OBJECT
public:
QmitkTbssTableModel(QObject *parent=nullptr);
QmitkTbssTableModel(QList< QPair<QString, int> > listofPairs, QObject *parent=nullptr);
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override;
bool insertRows(int position, int rows, const QModelIndex &index=QModelIndex()) override;
bool removeRows(int position, int rows, const QModelIndex &index=QModelIndex()) override;
QList< QPair<QString, int> > getList();
private:
QList< QPair<QString, int> > listOfPairs;
};
#endif
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTractbasedSpatialStatisticsView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTractbasedSpatialStatisticsView.cpp
index 95d070c..47e0da0 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTractbasedSpatialStatisticsView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTractbasedSpatialStatisticsView.cpp
@@ -1,1142 +1,1142 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// Qmitk
#include "QmitkTractbasedSpatialStatisticsView.h"
#include "mitkDataNodeObject.h"
#include <itkCastImageFilter.h>
// Qt
#include <QMessageBox>
#include <QInputDialog>
#include <QClipboard>
#include <qwt_plot_picker.h>
#include <mitkTractAnalyzer.h>
#include <mitkTbssImporter.h>
#include <mitkPlanarCircle.h>
#include <mitkPlanarFigureInteractor.h>
#include "vtkPoints.h"
#include <vtkCellArray.h>
#include <vtkPolyLine.h>
#include <mitkWorkbenchUtil.h>
const std::string QmitkTractbasedSpatialStatisticsView::VIEW_ID = "org.mitk.views.tractbasedspatialstatistics";
using namespace berry;
QmitkTractbasedSpatialStatisticsView::QmitkTractbasedSpatialStatisticsView()
: QmitkAbstractView()
, m_Controls( 0 )
, m_Activated(false)
{
}
QmitkTractbasedSpatialStatisticsView::~QmitkTractbasedSpatialStatisticsView()
{
}
void QmitkTractbasedSpatialStatisticsView::PerformChange()
{
m_Controls->m_RoiPlotWidget->ModifyPlot(m_Controls->m_Segments->value(), m_Controls->m_Average->isChecked());
}
void QmitkTractbasedSpatialStatisticsView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList<mitk::DataNode::Pointer>& nodes)
{
//datamanager selection changed
if (!this->IsActivated())
return;
// Check which datatypes are selected in the datamanager and enable/disable widgets accordingly
bool foundTbssRoi = false;
bool foundTbss = false;
bool found3dImage = false;
bool found4dImage = false;
bool foundFiberBundle = false;
bool foundStartRoi = false;
bool foundEndRoi = false;
mitk::TbssRoiImage* roiImage = nullptr;
mitk::TbssImage* image = nullptr;
mitk::Image* img = nullptr;
mitk::FiberBundle* fib = nullptr;
mitk::DataNode* start = nullptr;
mitk::DataNode* end = nullptr;
m_CurrentStartRoi = nullptr;
m_CurrentEndRoi = nullptr;
for (mitk::DataNode::Pointer node: nodes)
{
// only look at interesting types
// check for valid data
mitk::BaseData* nodeData = node->GetData();
if( nodeData )
{
if(QString("TbssRoiImage").compare(nodeData->GetNameOfClass())==0)
{
foundTbssRoi = true;
roiImage = static_cast<mitk::TbssRoiImage*>(nodeData);
}
else if (QString("TbssImage").compare(nodeData->GetNameOfClass())==0)
{
foundTbss = true;
image = static_cast<mitk::TbssImage*>(nodeData);
}
else if(QString("Image").compare(nodeData->GetNameOfClass())==0)
{
img = static_cast<mitk::Image*>(nodeData);
if(img->GetDimension() == 3)
{
found3dImage = true;
}
else if(img->GetDimension() == 4)
{
found4dImage = true;
}
}
else if (QString("FiberBundle").compare(nodeData->GetNameOfClass())==0)
{
foundFiberBundle = true;
fib = static_cast<mitk::FiberBundle*>(nodeData);
this->m_CurrentFiberNode = node;
}
if(QString("PlanarCircle").compare(nodeData->GetNameOfClass())==0)
{
if(!foundStartRoi)
{
start = node;
this->m_CurrentStartRoi = node;
foundStartRoi = true;
}
else
{
end = node;
this->m_CurrentEndRoi = node;
foundEndRoi = true;
}
}
}
}
this->m_Controls->m_CreateRoi->setEnabled(found3dImage);
this->m_Controls->m_ImportFsl->setEnabled(found4dImage);
if(foundTbss && foundTbssRoi)
{
this->Plot(image, roiImage);
}
else if(found3dImage && foundFiberBundle && foundStartRoi && foundEndRoi)
{
this->PlotFiberBundle(fib, img, start, end);
}
else if(found3dImage && foundFiberBundle)
{
this->PlotFiberBundle(fib, img);
}
else if(foundTbss && foundStartRoi && foundEndRoi && foundFiberBundle)
{
this->PlotFiber4D(image, fib, start, end);
}
if(found3dImage)
{
this->InitPointsets();
}
this->m_Controls->m_Cut->setEnabled(foundFiberBundle && foundStartRoi && foundEndRoi);
this->m_Controls->m_SegmentLabel->setEnabled(foundFiberBundle && foundStartRoi && foundEndRoi && (found3dImage || foundTbss));
this->m_Controls->m_Segments->setEnabled(foundFiberBundle && foundStartRoi && foundEndRoi && (found3dImage || foundTbss));
this->m_Controls->m_Average->setEnabled(foundFiberBundle && foundStartRoi && foundEndRoi && found3dImage);
}
void QmitkTractbasedSpatialStatisticsView::InitPointsets()
{
// Check if PointSetStart exsits, if not create it.
m_P1 = this->GetDataStorage()->GetNamedNode("PointSetNode");
if (m_PointSetNode)
{
//m_PointSetNode = dynamic_cast<mitk::PointSet*>(m_P1->GetData());
return;
}
if ((!m_P1) || (!m_PointSetNode))
{
// create new ones
m_PointSetNode = mitk::PointSet::New();
m_P1 = mitk::DataNode::New();
m_P1->SetData( m_PointSetNode );
m_P1->SetProperty( "name", mitk::StringProperty::New( "PointSet" ) );
m_P1->SetProperty( "opacity", mitk::FloatProperty::New( 1 ) );
m_P1->SetProperty( "helper object", mitk::BoolProperty::New(true) ); // CHANGE if wanted
m_P1->SetProperty( "pointsize", mitk::FloatProperty::New( 0.1 ) );
m_P1->SetColor( 1.0, 0.0, 0.0 );
this->GetDataStorage()->Add(m_P1);
m_Controls->m_PointWidget->SetPointSetNode(m_P1);
auto renderWindowPart = this->GetRenderWindowPart(mitk::WorkbenchUtil::IRenderWindowPartStrategy::OPEN);
auto axialSnc = renderWindowPart->GetQmitkRenderWindow("axial")->GetSliceNavigationController();
auto sagittalSnc = renderWindowPart->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController();
auto coronalSnc = renderWindowPart->GetQmitkRenderWindow("coronal")->GetSliceNavigationController();
m_Controls->m_PointWidget->AddSliceNavigationController(axialSnc);
m_Controls->m_PointWidget->AddSliceNavigationController(sagittalSnc);
m_Controls->m_PointWidget->AddSliceNavigationController(coronalSnc);
}
}
void QmitkTractbasedSpatialStatisticsView::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::QmitkTractbasedSpatialStatisticsViewControls;
m_Controls->setupUi( parent );
this->CreateConnections();
}
// Table for the FSL TBSS import
m_GroupModel = new QmitkTbssTableModel();
m_Controls->m_GroupInfo->setModel(m_GroupModel);
}
void QmitkTractbasedSpatialStatisticsView::SetFocus()
{
m_Controls->m_AddGroup->setFocus();
}
void QmitkTractbasedSpatialStatisticsView::Activated()
{
m_Activated = true;
}
void QmitkTractbasedSpatialStatisticsView::Deactivated()
{
m_Activated = false;
}
bool QmitkTractbasedSpatialStatisticsView::IsActivated() const
{
return m_Activated;
}
void QmitkTractbasedSpatialStatisticsView::Visible()
{
}
void QmitkTractbasedSpatialStatisticsView::Hidden()
{
}
void QmitkTractbasedSpatialStatisticsView::CreateConnections()
{
if ( m_Controls )
{
connect( (QObject*)(m_Controls->m_CreateRoi), SIGNAL(clicked()), this, SLOT(CreateRoi()) );
connect( (QObject*)(m_Controls->m_ImportFsl), SIGNAL(clicked()), this, SLOT(TbssImport()) );
connect( (QObject*)(m_Controls->m_AddGroup), SIGNAL(clicked()), this, SLOT(AddGroup()) );
connect( (QObject*)(m_Controls->m_RemoveGroup), SIGNAL(clicked()), this, SLOT(RemoveGroup()) );
connect( (QObject*)(m_Controls->m_Clipboard), SIGNAL(clicked()), this, SLOT(CopyToClipboard()) );
connect( m_Controls->m_RoiPlotWidget->m_PlotPicker, SIGNAL(selected(const QPointF&)), SLOT(Clicked(const QPointF&) ) );
connect( m_Controls->m_RoiPlotWidget->m_PlotPicker, SIGNAL(moved(const QPointF&)), SLOT(Clicked(const QPointF&) ) );
connect( (QObject*)(m_Controls->m_Cut), SIGNAL(clicked()), this, SLOT(Cut()) );
connect( (QObject*)(m_Controls->m_Average), SIGNAL(stateChanged(int)), this, SLOT(PerformChange()) );
connect( (QObject*)(m_Controls->m_Segments), SIGNAL(valueChanged(int)), this, SLOT(PerformChange()) );
}
}
void QmitkTractbasedSpatialStatisticsView::CopyToClipboard()
{
if(m_Controls->m_RoiPlotWidget->IsPlottingFiber())
{
// Working with fiber bundles
std::vector <std::vector<double> > profiles = m_Controls->m_RoiPlotWidget->GetIndividualProfiles();
QString clipboardText;
for (std::vector<std::vector<double> >::iterator it = profiles.begin(); it
!= profiles.end(); ++it)
{
for (std::vector<double>::iterator it2 = (*it).begin(); it2 !=
(*it).end(); ++it2)
{
clipboardText.append(QString("%1 \t").arg(*it2));
}
clipboardText.append(QString("\n"));
}
if(m_Controls->m_Average->isChecked())
{
std::vector<double> averages = m_Controls->m_RoiPlotWidget->GetAverageProfile();
clipboardText.append(QString("\nAverage\n"));
for (std::vector<double>::iterator it2 = averages.begin(); it2 !=
averages.end(); ++it2)
{
clipboardText.append(QString("%1 \t").arg(*it2));
}
}
QApplication::clipboard()->setText(clipboardText, QClipboard::Clipboard);
}
else{
// Working with TBSS Data
if(m_Controls->m_Average->isChecked())
{
std::vector<std::vector<double> > vals = m_Controls->m_RoiPlotWidget->GetVals();
QString clipboardText;
for (std::vector<std::vector<double> >::iterator it = vals.begin(); it
!= vals.end(); ++it)
{
for (std::vector<double>::iterator it2 = (*it).begin(); it2 !=
(*it).end(); ++it2)
{
clipboardText.append(QString("%1 \t").arg(*it2));
double d = *it2;
std::cout << d <<std::endl;
}
clipboardText.append(QString("\n"));
}
QApplication::clipboard()->setText(clipboardText, QClipboard::Clipboard);
}
else
{
std::vector<std::vector<double> > vals = m_Controls->m_RoiPlotWidget->GetIndividualProfiles();
QString clipboardText;
for (std::vector<std::vector<double> >::iterator it = vals.begin(); it
!= vals.end(); ++it)
{
for (std::vector<double>::iterator it2 = (*it).begin(); it2 !=
(*it).end(); ++it2)
{
clipboardText.append(QString("%1 \t").arg(*it2));
double d = *it2;
std::cout << d <<std::endl;
}
clipboardText.append(QString("\n"));
}
QApplication::clipboard()->setText(clipboardText, QClipboard::Clipboard);
}
}
}
void QmitkTractbasedSpatialStatisticsView::RemoveGroup()
{
QTableView *temp = static_cast<QTableView*>(m_Controls->m_GroupInfo);
QItemSelectionModel *selectionModel = temp->selectionModel();
QModelIndexList indices = selectionModel->selectedRows();
QModelIndex index;
foreach(index, indices)
{
int row = index.row();
m_GroupModel->removeRows(row, 1, QModelIndex());
}
}
void QmitkTractbasedSpatialStatisticsView::AddGroup()
{
QString group("Group");
int number = 0;
QPair<QString, int> pair(group, number);
QList< QPair<QString, int> >list = m_GroupModel->getList();
if(!list.contains(pair))
{
m_GroupModel->insertRows(0, 1, QModelIndex());
QModelIndex index = m_GroupModel->index(0, 0, QModelIndex());
m_GroupModel->setData(index, group, Qt::EditRole);
index = m_GroupModel->index(0, 1, QModelIndex());
m_GroupModel->setData(index, number, Qt::EditRole);
}
}
void QmitkTractbasedSpatialStatisticsView::TbssImport()
{
// Read groups from the interface
mitk::TbssImporter::Pointer importer = mitk::TbssImporter::New();
QList< QPair<QString, int> >list = m_GroupModel->getList();
if(list.size() == 0)
{
QMessageBox msgBox;
msgBox.setText("No study group information has been set yet.");
msgBox.exec();
return;
}
std::vector < std::pair<std::string, int> > groups;
for(int i=0; i<list.size(); i++)
{
QPair<QString, int> pair = list.at(i);
std::string s = pair.first.toStdString();
int n = pair.second;
std::pair<std::string, int> p;
p.first = s;
p.second = n;
groups.push_back(p);
}
importer->SetGroupInfo(groups);
std::string minfo = m_Controls->m_MeasurementInfo->text().toStdString();
importer->SetMeasurementInfo(minfo);
std::string name = "";
QList<mitk::DataNode::Pointer> nodes = this->GetDataManagerSelection();
for (auto node: nodes)
{
if(QString("Image").compare(node->GetData()->GetNameOfClass())==0)
{
mitk::Image* img = static_cast<mitk::Image*>(node->GetData());
if(img->GetDimension() == 4)
{
importer->SetImportVolume(img);
name = node->GetName();
}
}
}
mitk::TbssImage::Pointer tbssImage;
tbssImage = importer->Import();
name += "_tbss";
AddTbssToDataStorage(tbssImage, name);
}
void QmitkTractbasedSpatialStatisticsView::AddTbssToDataStorage(mitk::Image* image, std::string name)
{
mitk::LevelWindow levelwindow;
levelwindow.SetAuto( image );
mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New();
levWinProp->SetLevelWindow( levelwindow );
mitk::DataNode::Pointer result = mitk::DataNode::New();
result->SetProperty( "name", mitk::StringProperty::New(name) );
result->SetData( image );
result->SetProperty( "levelwindow", levWinProp );
// add new image to data storage and set as active to ease further processing
GetDataStorage()->Add( result );
// show the results
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkTractbasedSpatialStatisticsView::Clicked(const QPointF& pos)
{
int index = (int)pos.x();
if(m_Roi.size() > 0 && m_CurrentGeometry != nullptr && !m_Controls->m_RoiPlotWidget->IsPlottingFiber() )
{
index = std::min( (int)m_Roi.size()-1, std::max(0, index) );
itk::Index<3> ix = m_Roi.at(index);
mitk::Vector3D i;
i[0] = ix[0];
i[1] = ix[1];
i[2] = ix[2];
mitk::Vector3D w;
m_CurrentGeometry->IndexToWorld(i, w);
mitk::Point3D origin = m_CurrentGeometry->GetOrigin();
mitk::Point3D p;
p[0] = w[0] + origin[0];
p[1] = w[1] + origin[1];
p[2] = w[2] + origin[2];
this->GetRenderWindowPart()->SetSelectedPosition(p);
m_Controls->m_RoiPlotWidget->drawBar(index);
}
else if(m_Controls->m_RoiPlotWidget->IsPlottingFiber() )
{
mitk::Point3D point = m_Controls->m_RoiPlotWidget->GetPositionInWorld(index);
this->GetRenderWindowPart()->SetSelectedPosition(point);
}
}
void QmitkTractbasedSpatialStatisticsView::Cut()
{
mitk::BaseData* fibData = m_CurrentFiberNode->GetData();
mitk::FiberBundle* fib = static_cast<mitk::FiberBundle*>(fibData);
mitk::PlaneGeometry* startGeometry2D = const_cast<mitk::PlaneGeometry*>(dynamic_cast<mitk::PlanarFigure*>(m_CurrentStartRoi->GetData())->GetPlaneGeometry());
mitk::PlaneGeometry* endGeometry2D = const_cast<mitk::PlaneGeometry*>(dynamic_cast<mitk::PlanarFigure*>(m_CurrentEndRoi->GetData())->GetPlaneGeometry());
mitk::Point3D startCenter = dynamic_cast<mitk::PlanarFigure*>(m_CurrentStartRoi->GetData())->GetWorldControlPoint(0); //center Point of start roi
mitk::Point3D endCenter = dynamic_cast<mitk::PlanarFigure*>(m_CurrentEndRoi->GetData())->GetWorldControlPoint(0); //center Point of end roi
mitk::FiberBundle::Pointer inStart = fib->ExtractFiberSubset(m_CurrentStartRoi, nullptr);
mitk::FiberBundle::Pointer inBoth = inStart->ExtractFiberSubset(m_CurrentEndRoi, nullptr);
int num = inBoth->GetNumFibers();
vtkSmartPointer<vtkPolyData> fiberPolyData = inBoth->GetFiberPolyData();
vtkCellArray* lines = fiberPolyData->GetLines();
lines->InitTraversal();
// initialize new vtk polydata
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
int pointIndex=0;
// find start and endpoint
for( int fiberID( 0 ); fiberID < num; fiberID++ )
{
vtkIdType numPointsInCell(0);
vtkIdType* pointsInCell(nullptr);
lines->GetNextCell ( numPointsInCell, pointsInCell );
int startId = 0;
int endId = 0;
float minDistStart = std::numeric_limits<float>::max();
float minDistEnd = std::numeric_limits<float>::max();
vtkSmartPointer<vtkPolyLine> polyLine = vtkSmartPointer<vtkPolyLine>::New();
int lineIndex=0;
for( int pointInCellID( 0 ); pointInCellID < numPointsInCell ; pointInCellID++)
{
double *p = fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] );
mitk::Point3D point;
point[0] = p[0];
point[1] = p[1];
point[2] = p[2];
float distanceToStart = point.EuclideanDistanceTo(startCenter);
float distanceToEnd = point.EuclideanDistanceTo(endCenter);
if(distanceToStart < minDistStart)
{
minDistStart = distanceToStart;
startId = pointInCellID;
}
if(distanceToEnd < minDistEnd)
{
minDistEnd = distanceToEnd;
endId = pointInCellID;
}
}
/* We found the start and end points of of the part that should be plottet for
the current fiber. now we need to plot them. If the endId is smaller than the startId the plot order
must be reversed*/
if(startId < endId)
{
double *p = fiberPolyData->GetPoint( pointsInCell[ startId ] );
mitk::Vector3D p0;
p0[0] = p[0];
p0[1] = p[1];
p0[2] = p[2];
p = fiberPolyData->GetPoint( pointsInCell[ startId+1 ] );
mitk::Vector3D p1;
p1[0] = p[0];
p1[1] = p[1];
p1[2] = p[2];
// Check if p and p2 are both on the same side of the plane
mitk::Vector3D normal = startGeometry2D->GetNormal();
mitk::Point3D pStart;
pStart[0] = p0[0];
pStart[1] = p0[1];
pStart[2] = p0[2];
bool startOnPositive = startGeometry2D->IsAbove(pStart);
mitk::Point3D pSecond;
pSecond[0] = p1[0];
pSecond[1] = p1[1];
pSecond[2] = p1[2];
bool secondOnPositive = startGeometry2D->IsAbove(pSecond);
// Calculate intersection with the plane
mitk::Vector3D onPlane;
onPlane[0] = startCenter[0];
onPlane[1] = startCenter[1];
onPlane[2] = startCenter[2];
if(! (secondOnPositive ^ startOnPositive) )
{
/* startId and startId+1 lie on the same side of the plane, so we need
need startId-1 to calculate the intersection with the planar figure*/
p = fiberPolyData->GetPoint( pointsInCell[ startId-1 ] );
p1[0] = p[0];
p1[1] = p[1];
p1[2] = p[2];
}
double d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal );
mitk::Vector3D newPoint = (p0-p1);
newPoint[0] = d*newPoint[0] + p0[0];
newPoint[1] = d*newPoint[1] + p0[1];
newPoint[2] = d*newPoint[2] + p0[2];
double insertPoint[3];
insertPoint[0] = newPoint[0];
insertPoint[1] = newPoint[1];
insertPoint[2] = newPoint[2];
// First insert the intersection with the start roi
points->InsertNextPoint(insertPoint);
polyLine->GetPointIds()->InsertId(lineIndex,pointIndex);
lineIndex++;
pointIndex++;
if(! (secondOnPositive ^ startOnPositive) )
{
/* StartId and startId+1 lie on the same side of the plane
so startId is also part of the ROI*/
double *start = fiberPolyData->GetPoint( pointsInCell[startId] );
points->InsertNextPoint(start);
polyLine->GetPointIds()->InsertId(lineIndex,pointIndex);
lineIndex++;
pointIndex++;
}
// Insert the rest up and to including endId-1
for( int pointInCellID( startId+1 ); pointInCellID < endId ; pointInCellID++)
{
// create new polyline for new polydata
double *p = fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] );
points->InsertNextPoint(p);
// add point to line
polyLine->GetPointIds()->InsertId(lineIndex,pointIndex);
lineIndex++;
pointIndex++;
}
/* endId must be included if endId and endId-1 lie on the same side of the
plane defined by endRoi*/
p = fiberPolyData->GetPoint( pointsInCell[ endId ] );
p0[0] = p[0]; p0[1] = p[1]; p0[2] = p[2];
p = fiberPolyData->GetPoint( pointsInCell[ endId-1 ] );
p1[0] = p[0]; p1[1] = p[1]; p1[2] = p[2];
mitk::Point3D pLast;
pLast[0] = p0[0]; pLast[1] = p0[1]; pLast[2] = p0[2];
mitk::Point3D pBeforeLast;
pBeforeLast[0] = p1[0]; pBeforeLast[1] = p1[1]; pBeforeLast[2] = p1[2];
bool lastOnPositive = endGeometry2D->IsAbove(pLast);
bool secondLastOnPositive = endGeometry2D->IsAbove(pBeforeLast);
normal = endGeometry2D->GetNormal();
onPlane[0] = endCenter[0];
onPlane[1] = endCenter[1];
onPlane[2] = endCenter[2];
if(! (lastOnPositive ^ secondLastOnPositive) )
{
/* endId and endId-1 lie on the same side of the plane, so we need
need endId+1 to calculate the intersection with the planar figure.
this should exist since we know that the fiber crosses the planar figure
endId is part of the roi so can also be included here*/
p = fiberPolyData->GetPoint( pointsInCell[ endId+1 ] );
p1[0] = p[0];
p1[1] = p[1];
p1[2] = p[2];
double *end = fiberPolyData->GetPoint( pointsInCell[endId] );
points->InsertNextPoint(end);
polyLine->GetPointIds()->InsertId(lineIndex,pointIndex);
lineIndex++;
pointIndex++;
}
d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal );
newPoint = (p0-p1);
newPoint[0] = d*newPoint[0] + p0[0];
newPoint[1] = d*newPoint[1] + p0[1];
newPoint[2] = d*newPoint[2] + p0[2];
insertPoint[0] = newPoint[0];
insertPoint[1] = newPoint[1];
insertPoint[2] = newPoint[2];
//Insert the Last Point (intersection with the end roi)
points->InsertNextPoint(insertPoint);
polyLine->GetPointIds()->InsertId(lineIndex,pointIndex);
lineIndex++;
pointIndex++;
}
// Need to reverse walking order
else{
double *p = fiberPolyData->GetPoint( pointsInCell[ startId ] );
mitk::Vector3D p0;
p0[0] = p[0];
p0[1] = p[1];
p0[2] = p[2];
p = fiberPolyData->GetPoint( pointsInCell[ startId-1 ] );
mitk::Vector3D p1;
p1[0] = p[0];
p1[1] = p[1];
p1[2] = p[2];
// Check if p and p2 are both on the same side of the plane
mitk::Vector3D normal = startGeometry2D->GetNormal();
mitk::Point3D pStart;
pStart[0] = p0[0];
pStart[1] = p0[1];
pStart[2] = p0[2];
bool startOnPositive = startGeometry2D->IsAbove(pStart);
mitk::Point3D pSecond;
pSecond[0] = p1[0];
pSecond[1] = p1[1];
pSecond[2] = p1[2];
bool secondOnPositive = startGeometry2D->IsAbove(pSecond);
// Calculate intersection with the plane
mitk::Vector3D onPlane;
onPlane[0] = startCenter[0];
onPlane[1] = startCenter[1];
onPlane[2] = startCenter[2];
if(! (secondOnPositive ^ startOnPositive) )
{
/* startId and startId-1 lie on the same side of the plane, so we need
need startId+1 to calculate the intersection with the planar figure*/
p = fiberPolyData->GetPoint( pointsInCell[ startId+1 ] );
p1[0] = p[0];
p1[1] = p[1];
p1[2] = p[2];
}
double d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal );
mitk::Vector3D newPoint = (p0-p1);
newPoint[0] = d*newPoint[0] + p0[0];
newPoint[1] = d*newPoint[1] + p0[1];
newPoint[2] = d*newPoint[2] + p0[2];
double insertPoint[3];
insertPoint[0] = newPoint[0];
insertPoint[1] = newPoint[1];
insertPoint[2] = newPoint[2];
// First insert the intersection with the start roi
points->InsertNextPoint(insertPoint);
polyLine->GetPointIds()->InsertId(lineIndex,pointIndex);
lineIndex++;
pointIndex++;
if(! (secondOnPositive ^ startOnPositive) )
{
/* startId and startId-1 lie on the same side of the plane
so endId is also part of the ROI*/
double *start = fiberPolyData->GetPoint( pointsInCell[startId] );
points->InsertNextPoint(start);
polyLine->GetPointIds()->InsertId(lineIndex,pointIndex);
lineIndex++;
pointIndex++;
}
// Insert the rest up and to including endId-1
for( int pointInCellID( startId-1 ); pointInCellID > endId ; pointInCellID--)
{
// create new polyline for new polydata
double *p = fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] );
points->InsertNextPoint(p);
// add point to line
polyLine->GetPointIds()->InsertId(lineIndex,pointIndex);
lineIndex++;
pointIndex++;
}
/* startId must be included if startId and startId+ lie on the same side of the
plane defined by endRoi*/
p = fiberPolyData->GetPoint( pointsInCell[ endId ] );
p0[0] = p[0];
p0[1] = p[1];
p0[2] = p[2];
p = fiberPolyData->GetPoint( pointsInCell[ endId+1 ] );
p1[0] = p[0];
p1[1] = p[1];
p1[2] = p[2];
mitk::Point3D pLast;
pLast[0] = p0[0];
pLast[1] = p0[1];
pLast[2] = p0[2];
bool lastOnPositive = endGeometry2D->IsAbove(pLast);
mitk::Point3D pBeforeLast;
pBeforeLast[0] = p1[0];
pBeforeLast[1] = p1[1];
pBeforeLast[2] = p1[2];
bool secondLastOnPositive = endGeometry2D->IsAbove(pBeforeLast);
onPlane[0] = endCenter[0];
onPlane[1] = endCenter[1];
onPlane[2] = endCenter[2];
if(! (lastOnPositive ^ secondLastOnPositive) )
{
/* endId and endId+1 lie on the same side of the plane, so we need
need endId-1 to calculate the intersection with the planar figure.
this should exist since we know that the fiber crosses the planar figure*/
p = fiberPolyData->GetPoint( pointsInCell[ endId-1 ] );
p1[0] = p[0];
p1[1] = p[1];
p1[2] = p[2];
/* endId and endId+1 lie on the same side of the plane
so startId is also part of the ROI*/
double *end = fiberPolyData->GetPoint( pointsInCell[endId] );
points->InsertNextPoint(end);
polyLine->GetPointIds()->InsertId(lineIndex,pointIndex);
lineIndex++;
pointIndex++;
}
d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal );
newPoint = (p0-p1);
newPoint[0] = d*newPoint[0] + p0[0];
newPoint[1] = d*newPoint[1] + p0[1];
newPoint[2] = d*newPoint[2] + p0[2];
insertPoint[0] = newPoint[0];
insertPoint[1] = newPoint[1];
insertPoint[2] = newPoint[2];
//Insert the Last Point (intersection with the end roi)
points->InsertNextPoint(insertPoint);
polyLine->GetPointIds()->InsertId(lineIndex,pointIndex);
lineIndex++;
pointIndex++;
}
// add polyline to vtk cell array
cells->InsertNextCell(polyLine);
}
// Add the points to the dataset
polyData->SetPoints(points);
// Add the lines to the dataset
polyData->SetLines(cells);
mitk::FiberBundle::Pointer cutBundle = mitk::FiberBundle::New(polyData);
mitk::DataNode::Pointer cutNode = mitk::DataNode::New();
cutNode->SetData(cutBundle);
std::string name = "fiberCut";
cutNode->SetName(name);
GetDataStorage()->Add(cutNode);
}
void QmitkTractbasedSpatialStatisticsView::CreateRoi()
{
bool ok;
double threshold = QInputDialog::getDouble(m_Controls->m_CreateRoi, tr("Set an FA threshold"),
tr("Threshold:"), 0.2, 0.0, 1.0, 2, &ok);
if(!ok)
return;
mitk::Image::Pointer image;
QList<mitk::DataNode::Pointer> nodes = this->GetDataManagerSelection();
for (auto node: nodes)
{
if(QString("Image").compare(node->GetData()->GetNameOfClass())==0)
{
mitk::Image* img = static_cast<mitk::Image*>(node->GetData());
if(img->GetDimension() == 3)
{
image = img;
}
}
}
if(image.IsNull())
{
return;
}
mitk::TractAnalyzer analyzer;
analyzer.SetInputImage(image);
analyzer.SetThreshold(threshold);
m_PointSetNode = this->m_Controls->m_PointWidget->GetPointSet();
// Set Pointset to analyzer
analyzer.SetPointSet(m_PointSetNode);
// Run Analyzer
try
{
analyzer.MakeRoi();
}
catch (const mitk::Exception& e)
{
QMessageBox msgBox;
msgBox.setText(QString::fromStdString(e.what()));
msgBox.exec();
}
// Obtain tbss roi image from analyzer
mitk::TbssRoiImage::Pointer tbssRoi = analyzer.GetRoiImage();
tbssRoi->SetStructure(m_Controls->m_Structure->text().toStdString());
// get path description and set to interface
std::string pathDescription = analyzer.GetPathDescription();
m_Controls->m_PathTextEdit->setPlainText(QString(pathDescription.c_str()));
// Add roi image to datastorage
AddTbssToDataStorage(tbssRoi, m_Controls->m_RoiName->text().toStdString());
}
void QmitkTractbasedSpatialStatisticsView::PlotFiber4D(mitk::TbssImage* image,
mitk::FiberBundle* fib,
mitk::DataNode* startRoi,
mitk::DataNode* endRoi)
{
if(m_Controls->m_TabWidget->currentWidget() == m_Controls->m_MeasureTAB)
{
m_CurrentGeometry = image->GetGeometry();
m_Controls->m_RoiPlotWidget->SetGroups(image->GetGroupInfo());
m_Controls->m_RoiPlotWidget->SetProjections(image->GetImage());
m_Controls->m_RoiPlotWidget->SetMeasure( image->GetMeasurementInfo() );
m_Controls->m_RoiPlotWidget->PlotFiber4D(image, fib, startRoi, endRoi, m_Controls->m_Segments->value());
}
}
void QmitkTractbasedSpatialStatisticsView:: PlotFiberBundle(mitk::FiberBundle *fib, mitk::Image* img,
mitk::DataNode* startRoi, mitk::DataNode* endRoi)
{
bool avg = m_Controls->m_Average->isChecked();
int segments = m_Controls->m_Segments->value();
m_Controls->m_RoiPlotWidget->PlotFiberBetweenRois(fib, img, startRoi ,endRoi, avg, segments);
m_Controls->m_RoiPlotWidget->SetPlottingFiber(true);
mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll();
}
void QmitkTractbasedSpatialStatisticsView::Plot(mitk::TbssImage* image, mitk::TbssRoiImage* roiImage)
{
if(m_Controls->m_TabWidget->currentWidget() == m_Controls->m_MeasureTAB)
{
std::vector< itk::Index<3> > roi = roiImage->GetRoi();
m_Roi = roi;
m_CurrentGeometry = image->GetGeometry();
std::string structure = roiImage->GetStructure();
m_Controls->m_RoiPlotWidget->SetGroups(image->GetGroupInfo());
m_Controls->m_RoiPlotWidget->SetProjections(image->GetImage());
m_Controls->m_RoiPlotWidget->SetRoi(roi);
m_Controls->m_RoiPlotWidget->SetStructure(structure);
m_Controls->m_RoiPlotWidget->SetMeasure( image->GetMeasurementInfo() );
m_Controls->m_RoiPlotWidget->DrawProfiles();
}
m_Controls->m_RoiPlotWidget->SetPlottingFiber(false);
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTractbasedSpatialStatisticsView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTractbasedSpatialStatisticsView.h
index 0e74104..8aad8c6 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTractbasedSpatialStatisticsView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/QmitkTractbasedSpatialStatisticsView.h
@@ -1,184 +1,184 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkTractbasedSpatialStatisticsView_h
#define QmitkTractbasedSpatialStatisticsView_h
#include <QmitkAbstractView.h>
#include <mitkILifecycleAwarePart.h>
#include "ui_QmitkTractbasedSpatialStatisticsViewControls.h"
#include <QListWidgetItem>
#include <itkImageFileReader.h>
#include <itkImageFileWriter.h>
#include <itkDiffusionTensor3D.h>
#include <mitkTbssImage.h>
#include <mitkTbssRoiImage.h>
#include "QmitkTbssTableModel.h"
#include "QmitkTbssMetaTableModel.h"
#include <mitkFiberBundle.h>
// Image types
typedef short DiffusionPixelType;
typedef itk::Image<char, 3> CharImageType;
typedef itk::Image<unsigned char, 3> UCharImageType;
typedef itk::Image<float, 4> Float4DImageType;
typedef itk::Image<float, 3> FloatImageType;
typedef itk::VectorImage<float, 3> VectorImageType;
// Readers/Writers
typedef itk::ImageFileReader< CharImageType > CharReaderType;
typedef itk::ImageFileReader< UCharImageType > UCharReaderType;
typedef itk::ImageFileWriter< CharImageType > CharWriterType;
typedef itk::ImageFileReader< FloatImageType > FloatReaderType;
typedef itk::ImageFileWriter< FloatImageType > FloatWriterType;
typedef itk::ImageFileReader< Float4DImageType > Float4DReaderType;
typedef itk::ImageFileWriter< Float4DImageType > Float4DWriterType;
/*!
* \brief This plugin provides an extension for Tract-based spatial statistics (see Smith et al., 2009. http://dx.doi.org/10.1016/j.neuroimage.2006.02.024)
* TBSS enables analyzing the brain by a pipeline of registration, skeletonization, and projection that results in a white matter skeleton
* for all subjects that are analyzed statistically in a whole-brain manner.
* This plugin provides functionality to select single tracts and analyze them separately.
*
* Prerequisites: the mean_FA_skeleton and all_FA_skeletonised datasets produced by the FSL TBSS pipeline: http://fsl.fmrib.ox.ac.uk/fsl/fsl4.0/tbss/index
*/
class QmitkTractbasedSpatialStatisticsView : public QmitkAbstractView, public mitk::ILifecycleAwarePart
{
Q_OBJECT
public:
static const std::string VIEW_ID;
QmitkTractbasedSpatialStatisticsView();
virtual ~QmitkTractbasedSpatialStatisticsView();
virtual void CreateQtPartControl(QWidget *parent) override;
/// \brief Creation of the connections of main and control widget
virtual void CreateConnections();
///
/// Sets the focus to an internal widget.
///
virtual void SetFocus() override;
/// \brief Called when the view gets activated
virtual void Activated() override;
/// \brief Called when the view gets deactivated
virtual void Deactivated() override;
bool IsActivated() const;
/// \brief Called when the view gets visible
virtual void Visible() override;
/// \brief Called when the view gets hidden
virtual void Hidden() override;
protected slots:
// Creates Roi
void CreateRoi();
void Clicked(const QPointF& pos);
// Import of FSL TBSS data
void TbssImport();
// Add a group as metadata. This metadata is required by the plotting functionality
void AddGroup();
// Remove a group
void RemoveGroup();
// Copies the values displayed in the plot widget to clipboard, i.e. exports the data
void CopyToClipboard();
// Method to cut away parts of fiber bundles that should not be plotted.
void Cut();
// Adjust plot widget
void PerformChange();
protected:
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
// Creates a plot using a 4D image containing the projections of all subjects and a region of interest
void Plot(mitk::TbssImage*, mitk::TbssRoiImage*);
void PlotFiberBundle(mitk::FiberBundle* fib, mitk::Image* img, mitk::DataNode* startRoi=nullptr, mitk::DataNode* endRoi=nullptr);
void PlotFiber4D(mitk::TbssImage*, mitk::FiberBundle* fib, mitk::DataNode *startRoi=nullptr, mitk::DataNode *endRoi=nullptr);
// Create a point set. This point set defines the points through which a region of interest should go
void InitPointsets();
// Pointset and DataNode to contain the PointSet used in ROI creation
mitk::PointSet::Pointer m_PointSetNode;
mitk::DataNode::Pointer m_P1;
// GUI widgets
Ui::QmitkTractbasedSpatialStatisticsViewControls* m_Controls;
// Used to save the region of interest in a vector of itk::index.
std::vector< itk::Index<3> > m_Roi;
mitk::FiberBundle* m_Fib;
mitk::BaseGeometry* m_CurrentGeometry;
// A table model for saving group information in a name,number pair.
QmitkTbssTableModel* m_GroupModel;
// Convenience function for adding a new image to the datastorage and giving it a name.
void AddTbssToDataStorage(mitk::Image* image, std::string name);
mitk::DataNode::Pointer m_CurrentFiberNode; // needed for the index property when interacting with the plot widget
// needed when a plot should only show values between a start end end roi
mitk::DataNode::Pointer m_CurrentStartRoi;
mitk::DataNode::Pointer m_CurrentEndRoi;
private:
bool m_Activated;
};
#endif // _QMITKTRACTBASEDSPATIALSTATISTICSVIEW_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/mitkPluginActivator.cpp
index 96884f2..1fe957c 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/mitkPluginActivator.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/mitkPluginActivator.cpp
@@ -1,40 +1,40 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPluginActivator.h"
#include "src/internal/QmitkTractbasedSpatialStatisticsView.h"
#include "src/internal/QmitkTbssSkeletonizationView.h"
ctkPluginContext* mitk::PluginActivator::m_Context = nullptr;
ctkPluginContext* mitk::PluginActivator::GetContext()
{
return m_Context;
}
void mitk::PluginActivator::start(ctkPluginContext* context)
{
BERRY_REGISTER_EXTENSION_CLASS(QmitkTractbasedSpatialStatisticsView, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkTbssSkeletonizationView, context)
m_Context = context;
}
void mitk::PluginActivator::stop(ctkPluginContext* context)
{
Q_UNUSED(context)
m_Context = nullptr;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/mitkPluginActivator.h
index 929bc13..3142fe2 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/mitkPluginActivator.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tbss/src/internal/mitkPluginActivator.h
@@ -1,40 +1,40 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKPLUGINACTIVATOR_H
#define MITKPLUGINACTIVATOR_H
#include <ctkPluginActivator.h>
namespace mitk
{
class PluginActivator : public QObject, public ctkPluginActivator
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.mitk.gui.qt.diffusionimaging.tbss")
Q_INTERFACES(ctkPluginActivator)
public:
static ctkPluginContext* GetContext();
void start(ctkPluginContext* context) override;
void stop(ctkPluginContext* context) override;
private:
static ctkPluginContext* m_Context;
};
}
#endif
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/Perspectives/QmitkGibbsTractographyPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/Perspectives/QmitkGibbsTractographyPerspective.cpp
index 630dc8c..21ff189 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/Perspectives/QmitkGibbsTractographyPerspective.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/Perspectives/QmitkGibbsTractographyPerspective.cpp
@@ -1,48 +1,48 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkGibbsTractographyPerspective.h"
#include "berryIViewLayout.h"
void QmitkGibbsTractographyPerspective::CreateInitialLayout(berry::IPageLayout::Pointer layout)
{
/////////////////////////////////////////////////////
// all di-app perspectives should have the following:
/////////////////////////////////////////////////////
QString editorArea = layout->GetEditorArea();
layout->AddStandaloneViewPlaceholder("org.mitk.views.viewnavigatorview", berry::IPageLayout::LEFT, 0.3f, editorArea, false);
layout->AddStandaloneView("org.mitk.views.datamanager",
false, berry::IPageLayout::LEFT, 0.3f, editorArea);
layout->AddStandaloneView("org.mitk.views.controlvisualizationpropertiesview",
false, berry::IPageLayout::BOTTOM, .15f, "org.mitk.views.datamanager");
berry::IFolderLayout::Pointer left =
layout->CreateFolder("org.mbi.diffusionimaginginternal.leftcontrols",
berry::IPageLayout::BOTTOM, 0.15f, "org.mitk.views.controlvisualizationpropertiesview");
layout->AddStandaloneViewPlaceholder("org.mitk.views.imagenavigator",
berry::IPageLayout::BOTTOM, .7f, "org.mbi.diffusionimaginginternal.leftcontrols", false);
/////////////////////////////////////////////
// here goes the perspective specific stuff
/////////////////////////////////////////////
left->AddView("org.mitk.views.gibbstracking");
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/Perspectives/QmitkGibbsTractographyPerspective.h b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/Perspectives/QmitkGibbsTractographyPerspective.h
index 7ee4a1c..f81c233 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/Perspectives/QmitkGibbsTractographyPerspective.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/Perspectives/QmitkGibbsTractographyPerspective.h
@@ -1,36 +1,36 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkGibbsTractographyPerspective_H_
#define QmitkGibbsTractographyPerspective_H_
#include <berryIPerspectiveFactory.h>
class QmitkGibbsTractographyPerspective : public QObject, public berry::IPerspectiveFactory
{
Q_OBJECT
Q_INTERFACES(berry::IPerspectiveFactory)
public:
QmitkGibbsTractographyPerspective() {}
~QmitkGibbsTractographyPerspective() {}
void CreateInitialLayout(berry::IPageLayout::Pointer layout) override;
};
#endif /* QmitkGibbsTractographyPerspective_H_ */
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/Perspectives/QmitkStreamlineTractographyPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/Perspectives/QmitkStreamlineTractographyPerspective.cpp
index 3225dde..7f01654 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/Perspectives/QmitkStreamlineTractographyPerspective.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/Perspectives/QmitkStreamlineTractographyPerspective.cpp
@@ -1,49 +1,49 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkStreamlineTractographyPerspective.h"
#include "berryIViewLayout.h"
void QmitkStreamlineTractographyPerspective::CreateInitialLayout(berry::IPageLayout::Pointer layout)
{
/////////////////////////////////////////////////////
// all di-app perspectives should have the following:
/////////////////////////////////////////////////////
QString editorArea = layout->GetEditorArea();
layout->AddStandaloneViewPlaceholder("org.mitk.views.viewnavigatorview", berry::IPageLayout::LEFT, 0.3f, editorArea, false);
layout->AddStandaloneView("org.mitk.views.datamanager",
false, berry::IPageLayout::LEFT, 0.3f, editorArea);
layout->AddStandaloneView("org.mitk.views.controlvisualizationpropertiesview",
false, berry::IPageLayout::BOTTOM, .15f, "org.mitk.views.datamanager");
berry::IFolderLayout::Pointer left =
layout->CreateFolder("org.mbi.diffusionimaginginternal.leftcontrols",
berry::IPageLayout::BOTTOM, 0.15f, "org.mitk.views.controlvisualizationpropertiesview");
layout->AddStandaloneViewPlaceholder("org.mitk.views.imagenavigator",
berry::IPageLayout::BOTTOM, .7f, "org.mbi.diffusionimaginginternal.leftcontrols", false);
/////////////////////////////////////////////
// here goes the perspective specific stuff
/////////////////////////////////////////////
left->AddView("org.mitk.views.streamlinetracking");
left->AddView("org.mitk.views.segmentation");
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/Perspectives/QmitkStreamlineTractographyPerspective.h b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/Perspectives/QmitkStreamlineTractographyPerspective.h
index 87d9a06..3061afc 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/Perspectives/QmitkStreamlineTractographyPerspective.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/Perspectives/QmitkStreamlineTractographyPerspective.h
@@ -1,36 +1,36 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkStreamlineTractographyPerspective_H_
#define QmitkStreamlineTractographyPerspective_H_
#include <berryIPerspectiveFactory.h>
class QmitkStreamlineTractographyPerspective : public QObject, public berry::IPerspectiveFactory
{
Q_OBJECT
Q_INTERFACES(berry::IPerspectiveFactory)
public:
QmitkStreamlineTractographyPerspective() {}
~QmitkStreamlineTractographyPerspective() {}
void CreateInitialLayout(berry::IPageLayout::Pointer layout) override;
};
#endif /* QmitkStreamlineTractographyPerspective_H_ */
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkGibbsTrackingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkGibbsTrackingView.cpp
index 91193b6..150ddb3 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkGibbsTrackingView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkGibbsTrackingView.cpp
@@ -1,608 +1,608 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
// Qmitk
#include "QmitkGibbsTrackingView.h"
// Qt
#include <QMessageBox>
#include <QFileDialog>
#include <QDir>
#include <QTimer>
// MITK
#include <mitkImageCast.h>
#include <mitkImageToItk.h>
#include <mitkImageAccessByItk.h>
#include <mitkProgressBar.h>
#include <mitkIOUtil.h>
#include <mitkNodePredicateDataType.h>
#include <mitkNodePredicateDimension.h>
#include <mitkNodePredicateOr.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateProperty.h>
// ITK
#include <itkGibbsTrackingFilter.h>
#include <itkResampleImageFilter.h>
#include <itksys/SystemTools.hxx>
// MISC
#include <tinyxml.h>
QmitkTrackingWorker::QmitkTrackingWorker(QmitkGibbsTrackingView* view)
: m_View(view)
{
}
void QmitkTrackingWorker::run()
{
m_View->m_GlobalTracker = QmitkGibbsTrackingView::GibbsTrackingFilterType::New();
m_View->m_GlobalTracker->SetOdfImage(m_View->m_ItkOdfImage);
m_View->m_GlobalTracker->SetTensorImage(m_View->m_ItkTensorImage);
m_View->m_GlobalTracker->SetMaskImage(m_View->m_MaskImage);
m_View->m_GlobalTracker->SetStartTemperature((float)m_View->m_Controls->m_StartTempSlider->value()/100);
m_View->m_GlobalTracker->SetEndTemperature((float)m_View->m_Controls->m_EndTempSlider->value()/10000);
m_View->m_GlobalTracker->SetIterations(m_View->m_Controls->m_IterationsBox->text().toDouble());
m_View->m_GlobalTracker->SetParticleWeight((float)m_View->m_Controls->m_ParticleWeightSlider->value()/10000);
m_View->m_GlobalTracker->SetParticleWidth((float)(m_View->m_Controls->m_ParticleWidthSlider->value())/10);
m_View->m_GlobalTracker->SetParticleLength((float)(m_View->m_Controls->m_ParticleLengthSlider->value())/10);
m_View->m_GlobalTracker->SetInexBalance((float)m_View->m_Controls->m_InExBalanceSlider->value()/10);
m_View->m_GlobalTracker->SetMinFiberLength(m_View->m_Controls->m_FiberLengthSlider->value());
m_View->m_GlobalTracker->SetCurvatureThreshold(cos((float)m_View->m_Controls->m_CurvatureThresholdSlider->value()*itk::Math::pi/180));
m_View->m_GlobalTracker->SetRandomSeed(m_View->m_Controls->m_RandomSeedSlider->value());
try{
m_View->m_GlobalTracker->Update();
}
catch( mitk::Exception& e )
{
MITK_ERROR << "Internal error occured: " << e.what() << "\nAborting";
}
m_View->m_TrackingThread.quit();
}
const std::string QmitkGibbsTrackingView::VIEW_ID = "org.mitk.views.gibbstracking";
QmitkGibbsTrackingView::QmitkGibbsTrackingView()
: QmitkAbstractView()
, m_Controls( 0 )
, m_TrackingNode(nullptr)
, m_FiberBundle(nullptr)
, m_MaskImage(nullptr)
, m_TensorImage(nullptr)
, m_OdfImage(nullptr)
, m_ItkOdfImage(nullptr)
, m_ItkTensorImage(nullptr)
, m_ImageNode(nullptr)
, m_MaskImageNode(nullptr)
, m_FiberBundleNode(nullptr)
, m_ThreadIsRunning(false)
, m_ElapsedTime(0)
, m_GlobalTracker(nullptr)
, m_TrackingWorker(this)
{
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);
}
QmitkGibbsTrackingView::~QmitkGibbsTrackingView()
{
if (m_GlobalTracker.IsNull())
return;
m_GlobalTracker->SetAbortTracking(true);
m_TrackingThread.wait();
}
// update tracking status and generate fiber bundle
void QmitkGibbsTrackingView::TimerUpdate()
{
UpdateTrackingStatus();
GenerateFiberBundle();
}
// tell global tractography filter to stop after current step
void QmitkGibbsTrackingView::StopGibbsTracking()
{
if (m_GlobalTracker.IsNull())
return;
m_GlobalTracker->SetAbortTracking(true);
m_Controls->m_TrackingStop->setEnabled(false);
m_Controls->m_TrackingStop->setText("Stopping Tractography ...");
m_TrackingNode = nullptr;
}
// update gui elements and generate fiber bundle after tracking is finished
void QmitkGibbsTrackingView::AfterThread()
{
m_ThreadIsRunning = false;
m_TrackingTimer->stop();
UpdateGUI();
if( !m_GlobalTracker->GetIsInValidState() )
{
QMessageBox::critical( nullptr, "Gibbs Tracking", "An internal error occured. Tracking aborted.\n Please check the log for details." );
m_FiberBundleNode = nullptr;
return;
}
UpdateTrackingStatus();
if(m_Controls->m_ParticleWeightSlider->value()==0)
{
m_Controls->m_ParticleWeightLabel->setText(QString::number(m_GlobalTracker->GetParticleWeight()));
m_Controls->m_ParticleWeightSlider->setValue(m_GlobalTracker->GetParticleWeight()*10000);
}
if(m_Controls->m_ParticleWidthSlider->value()==0)
{
m_Controls->m_ParticleWidthLabel->setText(QString::number(m_GlobalTracker->GetParticleWidth()));
m_Controls->m_ParticleWidthSlider->setValue(m_GlobalTracker->GetParticleWidth()*10);
}
if(m_Controls->m_ParticleLengthSlider->value()==0)
{
m_Controls->m_ParticleLengthLabel->setText(QString::number(m_GlobalTracker->GetParticleLength()));
m_Controls->m_ParticleLengthSlider->setValue(m_GlobalTracker->GetParticleLength()*10);
}
GenerateFiberBundle();
m_FiberBundleNode = 0;
m_GlobalTracker = 0;
// images not needed anymore ( relevant only for computation )
// we need to release them to remove the memory access block created through CastToItk<> calls
this->m_ItkOdfImage = 0;
this->m_ItkTensorImage = 0;
}
// start tracking timer and update gui elements before tracking is started
void QmitkGibbsTrackingView::BeforeThread()
{
m_ThreadIsRunning = true;
m_TrackingTime = QTime::currentTime();
m_ElapsedTime = 0;
m_TrackingTimer->start(1000);
UpdateGUI();
}
// setup gui elements and signal/slot connections
void QmitkGibbsTrackingView::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::QmitkGibbsTrackingViewControls;
m_Controls->setupUi( parent );
AdvancedSettings();
connect( m_TrackingTimer, SIGNAL(timeout()), this, SLOT(TimerUpdate()) );
connect( m_Controls->m_TrackingStop, SIGNAL(clicked()), this, SLOT(StopGibbsTracking()) );
connect( m_Controls->m_TrackingStart, SIGNAL(clicked()), this, SLOT(StartGibbsTracking()) );
connect( m_Controls->m_AdvancedSettingsCheckbox, SIGNAL(clicked()), this, SLOT(AdvancedSettings()) );
connect( m_Controls->m_SaveTrackingParameters, SIGNAL(clicked()), this, SLOT(SaveTrackingParameters()) );
connect( m_Controls->m_LoadTrackingParameters, SIGNAL(clicked()), this, SLOT(LoadTrackingParameters()) );
connect( m_Controls->m_ParticleWidthSlider, SIGNAL(valueChanged(int)), this, SLOT(SetParticleWidth(int)) );
connect( m_Controls->m_ParticleLengthSlider, SIGNAL(valueChanged(int)), this, SLOT(SetParticleLength(int)) );
connect( m_Controls->m_InExBalanceSlider, SIGNAL(valueChanged(int)), this, SLOT(SetInExBalance(int)) );
connect( m_Controls->m_FiberLengthSlider, SIGNAL(valueChanged(int)), this, SLOT(SetFiberLength(int)) );
connect( m_Controls->m_ParticleWeightSlider, SIGNAL(valueChanged(int)), this, SLOT(SetParticleWeight(int)) );
connect( m_Controls->m_StartTempSlider, SIGNAL(valueChanged(int)), this, SLOT(SetStartTemp(int)) );
connect( m_Controls->m_EndTempSlider, SIGNAL(valueChanged(int)), this, SLOT(SetEndTemp(int)) );
connect( m_Controls->m_CurvatureThresholdSlider, SIGNAL(valueChanged(int)), this, SLOT(SetCurvatureThreshold(int)) );
connect( m_Controls->m_RandomSeedSlider, SIGNAL(valueChanged(int)), this, SLOT(SetRandomSeed(int)) );
connect( m_Controls->m_OutputFileButton, SIGNAL(clicked()), this, SLOT(SetOutputFile()) );
m_Controls->m_InputImageBox->SetDataStorage(this->GetDataStorage());
mitk::TNodePredicateDataType<mitk::OdfImage>::Pointer isOdfImagePredicate = mitk::TNodePredicateDataType<mitk::OdfImage>::New();
mitk::TNodePredicateDataType<mitk::TensorImage>::Pointer isTensorImagePredicate = mitk::TNodePredicateDataType<mitk::TensorImage>::New();
m_Controls->m_InputImageBox->SetPredicate( mitk::NodePredicateOr::New(isOdfImagePredicate, isTensorImagePredicate) );
m_Controls->m_MaskImageBox->SetDataStorage(this->GetDataStorage());
m_Controls->m_MaskImageBox->SetZeroEntryText("--");
mitk::TNodePredicateDataType<mitk::Image>::Pointer isImagePredicate = mitk::TNodePredicateDataType<mitk::Image>::New();
mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true));
mitk::NodePredicateDimension::Pointer is3D = mitk::NodePredicateDimension::New(3);
m_Controls->m_MaskImageBox->SetPredicate( mitk::NodePredicateAnd::New(isBinaryPredicate, mitk::NodePredicateAnd::New(isImagePredicate, is3D)) );
connect( (QObject*)(m_Controls->m_MaskImageBox), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGUI()));
connect( (QObject*)(m_Controls->m_InputImageBox), SIGNAL(currentIndexChanged(int)), this, SLOT(UpdateGUI()));
}
}
void QmitkGibbsTrackingView::SetFocus()
{
m_Controls->m_TrackingStart->setFocus();
}
void QmitkGibbsTrackingView::SetInExBalance(int value)
{
m_Controls->m_InExBalanceLabel->setText(QString::number((float)value/10));
}
void QmitkGibbsTrackingView::SetFiberLength(int value)
{
m_Controls->m_FiberLengthLabel->setText(QString::number(value)+"mm");
}
void QmitkGibbsTrackingView::SetRandomSeed(int value)
{
if (value>=0)
m_Controls->m_RandomSeedLabel->setText(QString::number(value));
else
m_Controls->m_RandomSeedLabel->setText("auto");
}
void QmitkGibbsTrackingView::SetParticleWeight(int value)
{
if (value>0)
m_Controls->m_ParticleWeightLabel->setText(QString::number((float)value/10000));
else
m_Controls->m_ParticleWeightLabel->setText("auto");
}
void QmitkGibbsTrackingView::SetStartTemp(int value)
{
m_Controls->m_StartTempLabel->setText(QString::number((float)value/100));
}
void QmitkGibbsTrackingView::SetEndTemp(int value)
{
m_Controls->m_EndTempLabel->setText(QString::number((float)value/10000));
}
void QmitkGibbsTrackingView::SetParticleWidth(int value)
{
if (value>0)
m_Controls->m_ParticleWidthLabel->setText(QString::number((float)value/10)+" mm");
else
m_Controls->m_ParticleWidthLabel->setText("auto");
}
void QmitkGibbsTrackingView::SetParticleLength(int value)
{
if (value>0)
m_Controls->m_ParticleLengthLabel->setText(QString::number((float)value/10)+" mm");
else
m_Controls->m_ParticleLengthLabel->setText("auto");
}
void QmitkGibbsTrackingView::SetCurvatureThreshold(int value)
{
m_Controls->m_CurvatureThresholdLabel->setText(QString::number(value)+"°");
}
// called if datamanager selection changes
void QmitkGibbsTrackingView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList<mitk::DataNode::Pointer>& )
{
UpdateGUI();
}
void QmitkGibbsTrackingView::NodeRemoved(const mitk::DataNode * node)
{
if (m_ThreadIsRunning)
{
if (node==m_TrackingNode.GetPointer())
{
StopGibbsTracking();
}
}
}
// update gui elements displaying trackings status
void QmitkGibbsTrackingView::UpdateTrackingStatus()
{
if (m_GlobalTracker.IsNull())
return;
m_ElapsedTime += m_TrackingTime.elapsed()/1000;
m_TrackingTime.restart();
unsigned long hours = m_ElapsedTime/3600;
unsigned long minutes = (m_ElapsedTime%3600)/60;
unsigned long seconds = m_ElapsedTime%60;
m_Controls->m_ProposalAcceptance->setText(QString::number(m_GlobalTracker->GetProposalAcceptance()*100)+"%");
m_Controls->m_TrackingTimeLabel->setText( QString::number(hours)+QString("h ")+QString::number(minutes)+QString("m ")+QString::number(seconds)+QString("s") );
m_Controls->m_NumConnectionsLabel->setText( QString::number(m_GlobalTracker->GetNumConnections()) );
m_Controls->m_NumParticlesLabel->setText( QString::number(m_GlobalTracker->GetNumParticles()) );
m_Controls->m_CurrentStepLabel->setText( QString::number(100*m_GlobalTracker->GetCurrentIteration()/m_GlobalTracker->GetIterations())+"%" );
m_Controls->m_AcceptedFibersLabel->setText( QString::number(m_GlobalTracker->GetNumAcceptedFibers()) );
}
// update gui elements (enable/disable elements and set tooltips)
void QmitkGibbsTrackingView::UpdateGUI()
{
if (!m_ThreadIsRunning && m_Controls->m_InputImageBox->GetSelectedNode().IsNotNull())
{
m_Controls->m_TrackingStop->setEnabled(false);
m_Controls->m_TrackingStart->setEnabled(true);
m_Controls->m_LoadTrackingParameters->setEnabled(true);
m_Controls->m_IterationsBox->setEnabled(true);
m_Controls->m_AdvancedFrame->setEnabled(true);
m_Controls->m_TrackingStop->setText("Stop Tractography");
m_Controls->m_TrackingStart->setToolTip("Start tractography. No further change of parameters possible.");
m_Controls->m_TrackingStop->setToolTip("");
m_Controls->m_MaskImageBox->setEnabled(true);
m_Controls->m_InputImageBox->setEnabled(true);
}
else if (!m_ThreadIsRunning)
{
m_Controls->m_TrackingStop->setEnabled(false);
m_Controls->m_TrackingStart->setEnabled(false);
m_Controls->m_LoadTrackingParameters->setEnabled(true);
m_Controls->m_IterationsBox->setEnabled(true);
m_Controls->m_AdvancedFrame->setEnabled(true);
m_Controls->m_TrackingStop->setText("Stop Tractography");
m_Controls->m_TrackingStart->setToolTip("No ODF image selected.");
m_Controls->m_TrackingStop->setToolTip("");
m_Controls->m_MaskImageBox->setEnabled(true);
m_Controls->m_InputImageBox->setEnabled(true);
}
else
{
m_Controls->m_TrackingStop->setEnabled(true);
m_Controls->m_TrackingStart->setEnabled(false);
m_Controls->m_LoadTrackingParameters->setEnabled(false);
m_Controls->m_IterationsBox->setEnabled(false);
m_Controls->m_AdvancedFrame->setEnabled(false);
m_Controls->m_AdvancedFrame->setVisible(false);
m_Controls->m_AdvancedSettingsCheckbox->setChecked(false);
m_Controls->m_TrackingStart->setToolTip("Tracking in progress.");
m_Controls->m_TrackingStop->setToolTip("Stop tracking and display results.");
m_Controls->m_MaskImageBox->setEnabled(false);
m_Controls->m_InputImageBox->setEnabled(false);
}
}
// show/hide advanced settings frame
void QmitkGibbsTrackingView::AdvancedSettings()
{
m_Controls->m_AdvancedFrame->setVisible(m_Controls->m_AdvancedSettingsCheckbox->isChecked());
}
// check for mask and odf and start tracking thread
void QmitkGibbsTrackingView::StartGibbsTracking()
{
if(m_ThreadIsRunning)
{
MITK_WARN("QmitkGibbsTrackingView")<<"Thread already running!";
return;
}
m_GlobalTracker = nullptr;
if (m_Controls->m_InputImageBox->GetSelectedNode().IsNull())
{
QMessageBox::information( nullptr, "Warning", "Please load and select a Odf image before starting image processing.");
return;
}
m_ImageNode = m_Controls->m_InputImageBox->GetSelectedNode();
if (dynamic_cast<mitk::OdfImage*>(m_ImageNode->GetData()))
m_OdfImage = dynamic_cast<mitk::OdfImage*>(m_ImageNode->GetData());
else if (dynamic_cast<mitk::TensorImage*>(m_ImageNode->GetData()))
m_TensorImage = dynamic_cast<mitk::TensorImage*>(m_ImageNode->GetData());
if (m_OdfImage.IsNull() && m_TensorImage.IsNull())
return;
// cast odf to itk
m_TrackingNode = m_ImageNode;
m_ItkTensorImage = nullptr;
m_ItkOdfImage = nullptr;
m_MaskImage = nullptr;
if (m_OdfImage.IsNotNull())
{
m_ItkOdfImage = ItkOdfImgType::New();
mitk::CastToItkImage(m_OdfImage, m_ItkOdfImage);
}
else
{
m_ItkTensorImage = ItkTensorImage::New();
mitk::CastToItkImage(m_TensorImage, m_ItkTensorImage);
}
// mask image found?
// catch exceptions thrown by the itkAccess macros
try{
if(m_Controls->m_MaskImageBox->GetSelectedNode().IsNotNull())
{
m_MaskImageNode = m_Controls->m_MaskImageBox->GetSelectedNode();
if (dynamic_cast<mitk::Image*>(m_MaskImageNode->GetData()))
mitk::CastToItkImage(dynamic_cast<mitk::Image*>(m_MaskImageNode->GetData()), m_MaskImage);
}
}
catch(...){};
// start worker thread
m_TrackingThread.start(QThread::LowestPriority);
}
// generate mitkFiberBundle from tracking filter output
void QmitkGibbsTrackingView::GenerateFiberBundle()
{
if (m_GlobalTracker.IsNull() || (!(m_Controls->m_VisualizationCheckbox->isChecked() || m_Controls->m_VisualizeOnceButton->isChecked()) && m_ThreadIsRunning))
return;
if (m_Controls->m_VisualizeOnceButton->isChecked())
m_Controls->m_VisualizeOnceButton->setChecked(false);
vtkSmartPointer<vtkPolyData> fiberBundle = m_GlobalTracker->GetFiberBundle();
if ( m_GlobalTracker->GetNumAcceptedFibers()==0 )
return;
m_FiberBundle = mitk::FiberBundle::New(fiberBundle);
m_FiberBundle->SetTrackVisHeader(dynamic_cast<mitk::Image*>(m_ImageNode->GetData())->GetGeometry());
if (m_FiberBundleNode.IsNotNull()){
GetDataStorage()->Remove(m_FiberBundleNode);
m_FiberBundleNode = 0;
}
m_GlobalTracker->SetDicomProperties(m_FiberBundle);
m_FiberBundleNode = mitk::DataNode::New();
m_FiberBundleNode->SetData(m_FiberBundle);
QString name("FiberBundle_");
name += m_ImageNode->GetName().c_str();
name += "_Gibbs";
m_FiberBundleNode->SetName(name.toStdString());
m_FiberBundleNode->SetVisibility(true);
if (!m_OutputFileName.isEmpty() && !m_ThreadIsRunning)
{
try
{
mitk::IOUtil::Save(m_FiberBundle.GetPointer(),m_OutputFileName.toStdString());
QMessageBox::information(nullptr, "Fiber bundle saved to", m_OutputFileName);
}
catch (itk::ExceptionObject &ex)
{
QMessageBox::information(nullptr, "Fiber bundle could not be saved", QString("%1\n%2\n%3\n%4\n%5\n%6").arg(ex.GetNameOfClass()).arg(ex.GetFile()).arg(ex.GetLine()).arg(ex.GetLocation()).arg(ex.what()).arg(ex.GetDescription()));
}
}
if(m_ImageNode.IsNull())
GetDataStorage()->Add(m_FiberBundleNode);
else
GetDataStorage()->Add(m_FiberBundleNode, m_ImageNode);
}
void QmitkGibbsTrackingView::SetOutputFile()
{
// SELECT FOLDER DIALOG
m_OutputFileName = QFileDialog::getSaveFileName(0,
tr("Set file name"),
QDir::currentPath()+"/FiberBundle.fib",
tr("Fiber Bundle (*.fib)") );
if (m_OutputFileName.isEmpty())
m_Controls->m_OutputFileLabel->setText("N/A");
else
m_Controls->m_OutputFileLabel->setText(m_OutputFileName);
}
// save current tracking paramters as xml file (.gtp)
void QmitkGibbsTrackingView::SaveTrackingParameters()
{
TiXmlDocument documentXML;
TiXmlDeclaration* declXML = new TiXmlDeclaration( "1.0", "", "" );
documentXML.LinkEndChild( declXML );
TiXmlElement* mainXML = new TiXmlElement("global_tracking_parameter_file");
mainXML->SetAttribute("file_version", "0.1");
documentXML.LinkEndChild(mainXML);
TiXmlElement* paramXML = new TiXmlElement("parameter_set");
paramXML->SetAttribute("iterations", m_Controls->m_IterationsBox->text().toStdString());
paramXML->SetAttribute("particle_length", QString::number((float)m_Controls->m_ParticleLengthSlider->value()/10).toStdString());
paramXML->SetAttribute("particle_width", QString::number((float)m_Controls->m_ParticleWidthSlider->value()/10).toStdString());
paramXML->SetAttribute("particle_weight", QString::number((float)m_Controls->m_ParticleWeightSlider->value()/10000).toStdString());
paramXML->SetAttribute("temp_start", QString::number((float)m_Controls->m_StartTempSlider->value()/100).toStdString());
paramXML->SetAttribute("temp_end", QString::number((float)m_Controls->m_EndTempSlider->value()/10000).toStdString());
paramXML->SetAttribute("inexbalance", QString::number((float)m_Controls->m_InExBalanceSlider->value()/10).toStdString());
paramXML->SetAttribute("fiber_length", QString::number(m_Controls->m_FiberLengthSlider->value()).toStdString());
paramXML->SetAttribute("curvature_threshold", QString::number(m_Controls->m_CurvatureThresholdSlider->value()).toStdString());
mainXML->LinkEndChild(paramXML);
QString filename = QFileDialog::getSaveFileName(
0,
tr("Save Parameters"),
QDir::currentPath()+"/param.gtp",
tr("Global Tracking Parameters (*.gtp)") );
if(filename.isEmpty() || filename.isNull())
return;
if(!filename.endsWith(".gtp"))
filename += ".gtp";
documentXML.SaveFile( filename.toStdString() );
}
// load current tracking paramters from xml file (.gtp)
void QmitkGibbsTrackingView::LoadTrackingParameters()
{
QString filename = QFileDialog::getOpenFileName(0, tr("Load Parameters"), QDir::currentPath(), tr("Global Tracking Parameters (*.gtp)") );
if(filename.isEmpty() || filename.isNull())
return;
TiXmlDocument doc( filename.toStdString() );
doc.LoadFile();
TiXmlHandle hDoc(&doc);
TiXmlElement* pElem;
TiXmlHandle hRoot(0);
pElem = hDoc.FirstChildElement().Element();
hRoot = TiXmlHandle(pElem);
pElem = hRoot.FirstChildElement("parameter_set").Element();
QString iterations(pElem->Attribute("iterations"));
m_Controls->m_IterationsBox->setText(iterations);
QString particleLength(pElem->Attribute("particle_length"));
float pLength = particleLength.toFloat();
QString particleWidth(pElem->Attribute("particle_width"));
float pWidth = particleWidth.toFloat();
if (pLength==0)
m_Controls->m_ParticleLengthLabel->setText("auto");
else
m_Controls->m_ParticleLengthLabel->setText(particleLength+" mm");
if (pWidth==0)
m_Controls->m_ParticleWidthLabel->setText("auto");
else
m_Controls->m_ParticleWidthLabel->setText(particleWidth+" mm");
m_Controls->m_ParticleWidthSlider->setValue(pWidth*10);
m_Controls->m_ParticleLengthSlider->setValue(pLength*10);
QString partWeight(pElem->Attribute("particle_weight"));
m_Controls->m_ParticleWeightSlider->setValue(partWeight.toFloat()*10000);
m_Controls->m_ParticleWeightLabel->setText(partWeight);
QString startTemp(pElem->Attribute("temp_start"));
m_Controls->m_StartTempSlider->setValue(startTemp.toFloat()*100);
m_Controls->m_StartTempLabel->setText(startTemp);
QString endTemp(pElem->Attribute("temp_end"));
m_Controls->m_EndTempSlider->setValue(endTemp.toFloat()*10000);
m_Controls->m_EndTempLabel->setText(endTemp);
QString inExBalance(pElem->Attribute("inexbalance"));
m_Controls->m_InExBalanceSlider->setValue(inExBalance.toFloat()*10);
m_Controls->m_InExBalanceLabel->setText(inExBalance);
QString fiberLength(pElem->Attribute("fiber_length"));
m_Controls->m_FiberLengthSlider->setValue(fiberLength.toInt());
m_Controls->m_FiberLengthLabel->setText(fiberLength+"mm");
QString curvThres(pElem->Attribute("curvature_threshold"));
m_Controls->m_CurvatureThresholdSlider->setValue(curvThres.toInt());
m_Controls->m_CurvatureThresholdLabel->setText(curvThres+"°");
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkGibbsTrackingView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkGibbsTrackingView.h
index 9657ad5..c8373d6 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkGibbsTrackingView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkGibbsTrackingView.h
@@ -1,162 +1,162 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkGibbsTrackingView_h
#define QmitkGibbsTrackingView_h
#include <berryISelectionListener.h>
#include <QmitkAbstractView.h>
#include "ui_QmitkGibbsTrackingViewControls.h"
#include <mitkOdfImage.h>
#include <QThread>
#include <mitkFiberBundle.h>
#include <QTime>
#include <itkImage.h>
#include <vtkSmartPointer.h>
#include <vtkPolyData.h>
#include <itkDiffusionTensor3D.h>
#include <mitkTensorImage.h>
class QmitkGibbsTrackingView;
class QmitkTrackingWorker : public QObject
{
Q_OBJECT
public:
QmitkTrackingWorker(QmitkGibbsTrackingView* view);
public slots:
void run();
private:
QmitkGibbsTrackingView* m_View;
};
/*!
\brief View for global fiber tracking (Gibbs tracking)
*/
typedef itk::Image< float, 3 > FloatImageType;
namespace itk
{
template<class X>
class GibbsTrackingFilter;
}
class QmitkGibbsTrackingView : public QmitkAbstractView
{
// 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:
typedef itk::Image<float,3> ItkFloatImageType;
typedef itk::Vector<float, ODF_SAMPLING_SIZE> OdfVectorType;
typedef mitk::OdfImage::ItkOdfImageType ItkOdfImgType;
typedef mitk::TensorImage::ItkTensorImageType ItkTensorImage;
typedef itk::GibbsTrackingFilter< ItkOdfImgType > GibbsTrackingFilterType;
static const std::string VIEW_ID;
QmitkGibbsTrackingView();
virtual ~QmitkGibbsTrackingView();
virtual void CreateQtPartControl(QWidget *parent) override;
///
/// Sets the focus to an internal widget.
///
virtual void SetFocus() override;
signals:
protected slots:
void StartGibbsTracking();
void StopGibbsTracking();
void AfterThread(); ///< update gui etc. after tracking has finished
void BeforeThread(); ///< start timer etc.
void TimerUpdate();
void AdvancedSettings(); ///< show/hide advanced tracking options
void SaveTrackingParameters(); ///< save tracking parameters to xml file
void LoadTrackingParameters(); ///< load tracking parameters from xml file
/** update labels if parameters have changed */
void SetParticleWidth(int value);
void SetParticleLength(int value);
void SetInExBalance(int value);
void SetFiberLength(int value);
void SetParticleWeight(int value);
void SetStartTemp(int value);
void SetEndTemp(int value);
void SetCurvatureThreshold(int value);
void SetRandomSeed(int value);
void SetOutputFile();
void UpdateGUI(); ///< update button activity etc. dpending on current datamanager selection
private:
// Visualization & GUI
void GenerateFiberBundle(); ///< generate fiber bundle from tracking output and add to datanode
void UpdateTrackingStatus(); ///< update textual status display of the tracking process
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
/// \brief called when DataNode is removed to stop gibbs tracking after node is removed
virtual void NodeRemoved(const mitk::DataNode * node) override;
void UpdateIteraionsGUI(unsigned long iterations); ///< update iterations label text
Ui::QmitkGibbsTrackingViewControls* m_Controls;
/** data objects */
mitk::DataNode::Pointer m_TrackingNode; ///< actual node that is tracked
mitk::FiberBundle::Pointer m_FiberBundle; ///< tracking output
ItkFloatImageType::Pointer m_MaskImage; ///< used to reduce the algorithms search space. tracking only inside of the mask.
mitk::TensorImage::Pointer m_TensorImage; ///< actual image that is tracked
mitk::OdfImage::Pointer m_OdfImage; ///< actual image that is tracked
ItkOdfImgType::Pointer m_ItkOdfImage; ///< actual image that is tracked
ItkTensorImage::Pointer m_ItkTensorImage; ///< actual image that is tracked
/** data nodes */
mitk::DataNode::Pointer m_ImageNode;
mitk::DataNode::Pointer m_MaskImageNode;
mitk::DataNode::Pointer m_FiberBundleNode;
/** flags etc. */
bool m_ThreadIsRunning;
QTimer* m_TrackingTimer;
QTime m_TrackingTime;
unsigned long m_ElapsedTime;
QString m_OutputFileName;
/** global tracker and friends */
itk::SmartPointer<GibbsTrackingFilterType> m_GlobalTracker;
QmitkTrackingWorker m_TrackingWorker;
QThread m_TrackingThread;
friend class QmitkTrackingWorker;
};
#endif // _QMITKGibbsTrackingVIEW_H_INCLUDED
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 1504087..d9633cb 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,1159 +1,1159 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
#include <berryIStructuredSelection.h>
// Qmitk
#include "QmitkStreamlineTrackingView.h"
#include "QmitkStdMultiWidget.h"
// Qt
#include <QMessageBox>
#include <QFileDialog>
// MITK
#include <mitkLookupTable.h>
#include <mitkLookupTableProperty.h>
#include <mitkImageToItk.h>
#include <mitkFiberBundle.h>
#include <mitkImageCast.h>
#include <mitkImageToItk.h>
#include <mitkNodePredicateDataType.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateProperty.h>
#include <mitkNodePredicateDimension.h>
#include <mitkOdfImage.h>
#include <mitkShImage.h>
#include <mitkSliceNavigationController.h>
// VTK
#include <vtkRenderWindowInteractor.h>
#include <vtkPolyData.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkSmartPointer.h>
#include <vtkPolyLine.h>
#include <vtkCellData.h>
#include <itkTensorImageToOdfImageFilter.h>
#include <omp.h>
#include <mitkLexicalCast.h>
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(nullptr)
, 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_FaImageSelectionWidget->SetDataStorage(this->GetDataStorage());
m_Controls->m_SeedImageSelectionWidget->SetDataStorage(this->GetDataStorage());
m_Controls->m_MaskImageSelectionWidget->SetDataStorage(this->GetDataStorage());
m_Controls->m_TargetImageSelectionWidget->SetDataStorage(this->GetDataStorage());
m_Controls->m_PriorImageSelectionWidget->SetDataStorage(this->GetDataStorage());
m_Controls->m_StopImageSelectionWidget->SetDataStorage(this->GetDataStorage());
m_Controls->m_ForestSelectionWidget->SetDataStorage(this->GetDataStorage());
m_Controls->m_ExclusionImageSelectionWidget->SetDataStorage(this->GetDataStorage());
mitk::TNodePredicateDataType<mitk::PeakImage>::Pointer isPeakImagePredicate = mitk::TNodePredicateDataType<mitk::PeakImage>::New();
mitk::TNodePredicateDataType<mitk::Image>::Pointer isImagePredicate = mitk::TNodePredicateDataType<mitk::Image>::New();
mitk::TNodePredicateDataType<mitk::TractographyForest>::Pointer isTractographyForest = mitk::TNodePredicateDataType<mitk::TractographyForest>::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_ForestSelectionWidget->SetNodePredicate(isTractographyForest);
m_Controls->m_FaImageSelectionWidget->SetNodePredicate( mitk::NodePredicateAnd::New(isNotABinaryImagePredicate, dimensionPredicate) );
m_Controls->m_FaImageSelectionWidget->SetEmptyInfo("--");
m_Controls->m_FaImageSelectionWidget->SetSelectionIsOptional(true);
m_Controls->m_SeedImageSelectionWidget->SetNodePredicate( mitk::NodePredicateAnd::New(isImagePredicate, dimensionPredicate) );
m_Controls->m_SeedImageSelectionWidget->SetEmptyInfo("--");
m_Controls->m_SeedImageSelectionWidget->SetSelectionIsOptional(true);
m_Controls->m_MaskImageSelectionWidget->SetNodePredicate( mitk::NodePredicateAnd::New(isImagePredicate, dimensionPredicate) );
m_Controls->m_MaskImageSelectionWidget->SetEmptyInfo("--");
m_Controls->m_MaskImageSelectionWidget->SetSelectionIsOptional(true);
m_Controls->m_StopImageSelectionWidget->SetNodePredicate( mitk::NodePredicateAnd::New(isImagePredicate, dimensionPredicate) );
m_Controls->m_StopImageSelectionWidget->SetEmptyInfo("--");
m_Controls->m_StopImageSelectionWidget->SetSelectionIsOptional(true);
m_Controls->m_TargetImageSelectionWidget->SetNodePredicate( mitk::NodePredicateAnd::New(isImagePredicate, dimensionPredicate) );
m_Controls->m_TargetImageSelectionWidget->SetEmptyInfo("--");
m_Controls->m_TargetImageSelectionWidget->SetSelectionIsOptional(true);
m_Controls->m_PriorImageSelectionWidget->SetNodePredicate( isPeakImagePredicate );
m_Controls->m_PriorImageSelectionWidget->SetEmptyInfo("--");
m_Controls->m_PriorImageSelectionWidget->SetSelectionIsOptional(true);
m_Controls->m_ExclusionImageSelectionWidget->SetNodePredicate( mitk::NodePredicateAnd::New(isImagePredicate, dimensionPredicate) );
m_Controls->m_ExclusionImageSelectionWidget->SetEmptyInfo("--");
m_Controls->m_ExclusionImageSelectionWidget->SetSelectionIsOptional(true);
connect( m_TrackingTimer, SIGNAL(timeout()), this, SLOT(TimerUpdate()) );
connect( m_Controls->m_SaveParametersButton, SIGNAL(clicked()), this, SLOT(SaveParameters()) );
connect( m_Controls->m_LoadParametersButton, SIGNAL(clicked()), this, SLOT(LoadParameters()) );
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_FaImageSelectionWidget, SIGNAL(CurrentSelectionChanged(QList<mitk::DataNode::Pointer>)), 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_SeedImageSelectionWidget, SIGNAL(CurrentSelectionChanged(QList<mitk::DataNode::Pointer>)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_ModeBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_StopImageSelectionWidget, SIGNAL(CurrentSelectionChanged(QList<mitk::DataNode::Pointer>)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_TargetImageSelectionWidget, SIGNAL(CurrentSelectionChanged(QList<mitk::DataNode::Pointer>)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_PriorImageSelectionWidget, SIGNAL(CurrentSelectionChanged(QList<mitk::DataNode::Pointer>)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_ExclusionImageSelectionWidget, SIGNAL(CurrentSelectionChanged(QList<mitk::DataNode::Pointer>)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_MaskImageSelectionWidget, SIGNAL(CurrentSelectionChanged(QList<mitk::DataNode::Pointer>)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_FaImageSelectionWidget, SIGNAL(CurrentSelectionChanged(QList<mitk::DataNode::Pointer>)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_ForestSelectionWidget, SIGNAL(CurrentSelectionChanged(QList<mitk::DataNode::Pointer>)), this, SLOT(ForestSwitched()) );
connect( m_Controls->m_ForestSelectionWidget, SIGNAL(CurrentSelectionChanged(QList<mitk::DataNode::Pointer>)), 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_MaxTractLengthBox, 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_PriorFlipXBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_PriorFlipYBox, SIGNAL(stateChanged(int)), this, SLOT(OnParameterChanged()) );
connect( m_Controls->m_PriorFlipZBox, 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()) );
connect( m_Controls->m_PeakJitterBox, SIGNAL(editingFinished()), 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_MaxTractLengthBox->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();
m_Controls->m_PeakJitterBox->editingFinished();
StartStopTrackingGui(false);
}
m_ParameterFile = QDir::currentPath()+"/param.stp";
UpdateGui();
}
void QmitkStreamlineTrackingView::ParametersToGui(mitk::StreamlineTractographyParameters& params)
{
m_Controls->m_SeedRadiusBox->setValue(params.m_InteractiveRadiusMm);
m_Controls->m_NumSeedsBox->setValue(params.m_NumInteractiveSeeds);
m_Controls->m_InteractiveBox->setChecked(params.m_EnableInteractive);
m_Controls->m_FiberErrorBox->setValue(params.m_Compression);
m_Controls->m_ResampleFibersBox->setChecked(params.m_CompressFibers);
m_Controls->m_SeedRadiusBox->setValue(params.m_InteractiveRadiusMm);
m_Controls->m_NumFibersBox->setValue(params.m_MaxNumFibers);
m_Controls->m_ScalarThresholdBox->setValue(params.m_Cutoff);
m_Controls->m_fBox->setValue(params.m_F);
m_Controls->m_gBox->setValue(params.m_G);
m_Controls->m_OdfCutoffBox->setValue(params.m_OdfCutoff);
m_Controls->m_SharpenOdfsBox->setChecked(params.m_SharpenOdfs);
m_Controls->m_PriorWeightBox->setValue(params.m_Weight);
m_Controls->m_PriorAsMaskBox->setChecked(params.m_RestrictToPrior);
m_Controls->m_NewDirectionsFromPriorBox->setChecked(params.m_NewDirectionsFromPrior);
m_Controls->m_PriorFlipXBox->setChecked(params.m_PriorFlipX);
m_Controls->m_PriorFlipYBox->setChecked(params.m_PriorFlipY);
m_Controls->m_PriorFlipZBox->setChecked(params.m_PriorFlipZ);
m_Controls->m_FlipXBox->setChecked(params.m_FlipX);
m_Controls->m_FlipYBox->setChecked(params.m_FlipY);
m_Controls->m_FlipZBox->setChecked(params.m_FlipZ);
m_Controls->m_InterpolationBox->setChecked(params.m_InterpolateTractographyData);
m_Controls->m_MaskInterpolationBox->setChecked(params.m_InterpolateRoiImages);
m_Controls->m_SeedsPerVoxelBox->setValue(params.m_SeedsPerVoxel);
m_Controls->m_StepSizeBox->setValue(params.GetStepSizeVox());
m_Controls->m_SamplingDistanceBox->setValue(params.GetSamplingDistanceVox());
m_Controls->m_StopVotesBox->setChecked(params.m_StopVotes);
m_Controls->m_FrontalSamplesBox->setChecked(params.m_OnlyForwardSamples);
m_Controls->m_TrialsPerSeedBox->setValue(params.m_TrialsPerSeed);
m_Controls->m_NumSamplesBox->setValue(params.m_NumSamples);
m_Controls->m_LoopCheckBox->setValue(params.GetLoopCheckDeg());
m_Controls->m_AngularThresholdBox->setValue(params.GetAngularThresholdDeg());
m_Controls->m_MinTractLengthBox->setValue(params.m_MinTractLengthMm);
m_Controls->m_MaxTractLengthBox->setValue(params.m_MaxTractLengthMm);
m_Controls->m_OutputProbMap->setChecked(params.m_OutputProbMap);
m_Controls->m_FixSeedBox->setChecked(params.m_FixRandomSeed);
m_Controls->m_PeakJitterBox->setValue(params.m_PeakJitter);
switch (params.m_Mode)
{
case mitk::TrackingDataHandler::MODE::DETERMINISTIC:
m_Controls->m_ModeBox->setCurrentIndex(0);
break;
case mitk::TrackingDataHandler::MODE::PROBABILISTIC:
m_Controls->m_ModeBox->setCurrentIndex(1);
break;
}
switch (params.m_EpConstraints)
{
case itk::StreamlineTrackingFilter::EndpointConstraints::NONE:
m_Controls->m_EpConstraintsBox->setCurrentIndex(0);
break;
case itk::StreamlineTrackingFilter::EndpointConstraints::EPS_IN_TARGET:
m_Controls->m_EpConstraintsBox->setCurrentIndex(1);
break;
case itk::StreamlineTrackingFilter::EndpointConstraints::EPS_IN_TARGET_LABELDIFF:
m_Controls->m_EpConstraintsBox->setCurrentIndex(2);
break;
case itk::StreamlineTrackingFilter::EndpointConstraints::EPS_IN_SEED_AND_TARGET:
m_Controls->m_EpConstraintsBox->setCurrentIndex(3);
break;
case itk::StreamlineTrackingFilter::EndpointConstraints::MIN_ONE_EP_IN_TARGET:
m_Controls->m_EpConstraintsBox->setCurrentIndex(4);
break;
case itk::StreamlineTrackingFilter::EndpointConstraints::ONE_EP_IN_TARGET:
m_Controls->m_EpConstraintsBox->setCurrentIndex(5);
break;
case itk::StreamlineTrackingFilter::EndpointConstraints::NO_EP_IN_TARGET:
m_Controls->m_EpConstraintsBox->setCurrentIndex(6);
break;
}
}
std::shared_ptr<mitk::StreamlineTractographyParameters> QmitkStreamlineTrackingView::GetParametersFromGui()
{
// NOT IN GUI
// unsigned int m_NumPreviousDirections = 1;
// bool m_AvoidStop = true;
// bool m_RandomSampling = false;
// float m_DeflectionMod = 1.0;
// bool m_ApplyDirectionMatrix = false;
std::shared_ptr<mitk::StreamlineTractographyParameters> params = std::make_shared<mitk::StreamlineTractographyParameters>();
params->m_InteractiveRadiusMm = m_Controls->m_SeedRadiusBox->value();
params->m_NumInteractiveSeeds = m_Controls->m_NumSeedsBox->value();
params->m_EnableInteractive = m_Controls->m_InteractiveBox->isChecked();
params->m_Compression = m_Controls->m_FiberErrorBox->value();
params->m_CompressFibers = m_Controls->m_ResampleFibersBox->isChecked();
params->m_InteractiveRadiusMm = m_Controls->m_SeedRadiusBox->value();
params->m_MaxNumFibers = m_Controls->m_NumFibersBox->value();
params->m_Cutoff = static_cast<float>(m_Controls->m_ScalarThresholdBox->value());
params->m_F = static_cast<float>(m_Controls->m_fBox->value());
params->m_G = static_cast<float>(m_Controls->m_gBox->value());
params->m_OdfCutoff = static_cast<float>(m_Controls->m_OdfCutoffBox->value());
params->m_SharpenOdfs = m_Controls->m_SharpenOdfsBox->isChecked();
params->m_Weight = static_cast<float>(m_Controls->m_PriorWeightBox->value());
params->m_RestrictToPrior = m_Controls->m_PriorAsMaskBox->isChecked();
params->m_NewDirectionsFromPrior = m_Controls->m_NewDirectionsFromPriorBox->isChecked();
params->m_PriorFlipX = m_Controls->m_PriorFlipXBox->isChecked();
params->m_PriorFlipY = m_Controls->m_PriorFlipYBox->isChecked();
params->m_PriorFlipZ = m_Controls->m_PriorFlipZBox->isChecked();
params->m_FlipX = m_Controls->m_FlipXBox->isChecked();
params->m_FlipY = m_Controls->m_FlipYBox->isChecked();
params->m_FlipZ = m_Controls->m_FlipZBox->isChecked();
params->m_InterpolateTractographyData = m_Controls->m_InterpolationBox->isChecked();
params->m_InterpolateRoiImages = m_Controls->m_MaskInterpolationBox->isChecked();
params->m_SeedsPerVoxel = m_Controls->m_SeedsPerVoxelBox->value();
params->SetStepSizeVox(m_Controls->m_StepSizeBox->value());
params->SetSamplingDistanceVox(m_Controls->m_SamplingDistanceBox->value());
params->m_StopVotes = m_Controls->m_StopVotesBox->isChecked();
params->m_OnlyForwardSamples = m_Controls->m_FrontalSamplesBox->isChecked();
params->m_TrialsPerSeed = m_Controls->m_TrialsPerSeedBox->value();
params->m_NumSamples = m_Controls->m_NumSamplesBox->value();
params->SetLoopCheckDeg(m_Controls->m_LoopCheckBox->value());
params->SetAngularThresholdDeg(m_Controls->m_AngularThresholdBox->value());
params->m_MinTractLengthMm = m_Controls->m_MinTractLengthBox->value();
params->m_MaxTractLengthMm = m_Controls->m_MaxTractLengthBox->value();
params->m_OutputProbMap = m_Controls->m_OutputProbMap->isChecked();
params->m_FixRandomSeed = m_Controls->m_FixSeedBox->isChecked();
params->m_PeakJitter = static_cast<float>(m_Controls->m_PeakJitterBox->value());
switch (m_Controls->m_ModeBox->currentIndex())
{
case 0:
params->m_Mode = mitk::TrackingDataHandler::MODE::DETERMINISTIC;
break;
case 1:
params->m_Mode = mitk::TrackingDataHandler::MODE::PROBABILISTIC;
break;
default:
params->m_Mode = mitk::TrackingDataHandler::MODE::DETERMINISTIC;
}
switch (m_Controls->m_EpConstraintsBox->currentIndex())
{
case 0:
params->m_EpConstraints = itk::StreamlineTrackingFilter::EndpointConstraints::NONE;
break;
case 1:
params->m_EpConstraints = itk::StreamlineTrackingFilter::EndpointConstraints::EPS_IN_TARGET;
break;
case 2:
params->m_EpConstraints = itk::StreamlineTrackingFilter::EndpointConstraints::EPS_IN_TARGET_LABELDIFF;
break;
case 3:
params->m_EpConstraints = itk::StreamlineTrackingFilter::EndpointConstraints::EPS_IN_SEED_AND_TARGET;
break;
case 4:
params->m_EpConstraints = itk::StreamlineTrackingFilter::EndpointConstraints::MIN_ONE_EP_IN_TARGET;
break;
case 5:
params->m_EpConstraints = itk::StreamlineTrackingFilter::EndpointConstraints::ONE_EP_IN_TARGET;
break;
case 6:
params->m_EpConstraints = itk::StreamlineTrackingFilter::EndpointConstraints::NO_EP_IN_TARGET;
break;
}
return params;
}
void QmitkStreamlineTrackingView::SaveParameters()
{
QString filename = QFileDialog::getSaveFileName(
0,
tr("Save Tractography Parameters"),
m_ParameterFile,
tr("Streamline Tractography Parameters (*.stp)") );
if(filename.isEmpty() || filename.isNull())
return;
m_ParameterFile = filename;
auto params = GetParametersFromGui();
params->SaveParameters(m_ParameterFile.toStdString());
}
void QmitkStreamlineTrackingView::LoadParameters()
{
QString filename = QFileDialog::getOpenFileName(
0,
tr("Load Tractography Parameters"),
m_ParameterFile,
tr("Streamline Tractography Parameters (*.stp)") );
if(filename.isEmpty() || filename.isNull())
return;
m_ParameterFile = filename;
mitk::StreamlineTractographyParameters params;
params.LoadParameters(m_ParameterFile.toStdString());
ParametersToGui(params);
}
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()
{
auto params = m_Tracker->GetParameters();
m_TrackingTimer->stop();
if (!params->m_OutputProbMap)
{
vtkSmartPointer<vtkPolyData> 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->SetTrackVisHeader(dynamic_cast<mitk::Image*>(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", params->GetMinVoxelSizeMm()/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", params->GetMinVoxelSizeMm()/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", params->GetMinVoxelSizeMm()/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<float> 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<num; i++)
{
itk::Vector<float> 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<QDoubleSpinBox*>(obj)!=nullptr)
new_val = boost::lexical_cast<std::string>(qobject_cast<QDoubleSpinBox*>(obj)->value());
else if (qobject_cast<QSpinBox*>(obj)!=nullptr)
new_val = boost::lexical_cast<std::string>(qobject_cast<QSpinBox*>(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_SeedImageSelectionWidget->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)
{
if (m_TrackingPriorHandler != nullptr)
{
delete m_TrackingPriorHandler;
m_TrackingPriorHandler = nullptr;
}
delete m_TrackingHandler;
m_TrackingHandler = nullptr;
m_DeleteTrackingHandler = false;
m_LastPrior = nullptr;
}
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<mitk::DataNode::Pointer>& nodes )
{
std::vector< mitk::DataNode::Pointer > last_nodes = m_InputImageNodes;
m_InputImageNodes.clear();
m_AdditionalInputImages.clear();
bool retrack = false;
for( auto node : nodes )
{
if( node.IsNotNull() && dynamic_cast<mitk::Image*>(node->GetData()) )
{
if( dynamic_cast<mitk::TensorImage*>(node->GetData()) ||
dynamic_cast<mitk::OdfImage*>(node->GetData()) ||
dynamic_cast<mitk::ShImage*>(node->GetData()) ||
dynamic_cast<mitk::PeakImage*>(node->GetData()) ||
mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast<mitk::Image *>(node->GetData())))
{
m_InputImageNodes.push_back(node);
retrack = true;
}
else
{
mitk::Image* img = dynamic_cast<mitk::Image*>(node->GetData());
if (img!=nullptr && img->GetDimension()==3)
m_AdditionalInputImages.push_back(dynamic_cast<mitk::Image*>(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; i<m_InputImageNodes.size(); i++)
if (last_nodes.at(i)!=m_InputImageNodes.at(i))
{
same_nodes = false;
break;
}
if (same_nodes)
return;
}
DeleteTrackingHandler();
UpdateGui();
if (retrack)
OnParameterChanged();
}
void QmitkStreamlineTrackingView::UpdateGui()
{
m_Controls->m_TensorImageLabel->setText("<font color='red'>select in data-manager</font>");
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_FaImageSelectionWidget->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_ForestSelectionWidget->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_TargetImageSelectionWidget->setEnabled(false);
m_Controls->m_TargetImageLabel->setEnabled(false);
m_Controls->m_PeakJitterBox->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_TargetImageSelectionWidget->setEnabled(true);
m_Controls->m_TargetImageLabel->setEnabled(true);
}
// stuff that is only important for probabilistic tractography
if (m_Controls->m_ModeBox->currentIndex()==1)
{
m_Controls->m_TrialsPerSeedBox->setEnabled(true);
m_Controls->m_TrialsPerSeedLabel->setEnabled(true);
m_Controls->m_PeakJitterBox->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<mitk::TensorImage*>(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<mitk::OdfImage*>(m_InputImageNodes.at(0)->GetData()) ||
dynamic_cast<mitk::ShImage*>(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<mitk::Image *>(m_InputImageNodes.at(0)->GetData())) )
{
m_Controls->m_ForestSelectionWidget->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()
{
auto params = GetParametersFromGui();
if (m_InputImageNodes.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 (params->m_EpConstraints == itk::StreamlineTrackingFilter::EndpointConstraints::NONE)
m_Tracker->SetTargetRegions(nullptr);
if( dynamic_cast<mitk::TensorImage*>(m_InputImageNodes.at(0)->GetData()) )
{
if (m_Controls->m_ModeBox->currentIndex()==1)
{
if (m_InputImageNodes.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();
typedef itk::TensorImageToOdfImageFilter< float, float > FilterType;
FilterType::Pointer filter = FilterType::New();
filter->SetInput( mitk::convert::GetItkTensorFromTensorImage(dynamic_cast<mitk::Image*>(m_InputImageNodes.at(0)->GetData())) );
filter->Update();
dynamic_cast<mitk::TrackingHandlerOdf*>(m_TrackingHandler)->SetOdfImage(filter->GetOutput());
if (m_Controls->m_FaImageSelectionWidget->GetSelectedNode().IsNotNull())
{
ItkFloatImageType::Pointer itkImg = ItkFloatImageType::New();
mitk::CastToItkImage(dynamic_cast<mitk::Image*>(m_Controls->m_FaImageSelectionWidget->GetSelectedNode()->GetData()), itkImg);
dynamic_cast<mitk::TrackingHandlerOdf*>(m_TrackingHandler)->SetGfaImage(itkImg);
}
}
dynamic_cast<mitk::TrackingHandlerOdf*>(m_TrackingHandler)->SetIsOdfFromTensor(true);
}
else
{
if (m_TrackingHandler==nullptr)
{
m_TrackingHandler = new mitk::TrackingHandlerTensor();
for (unsigned int i=0; i<m_InputImageNodes.size(); ++i)
dynamic_cast<mitk::TrackingHandlerTensor*>(m_TrackingHandler)->AddTensorImage(mitk::convert::GetItkTensorFromTensorImage(dynamic_cast<mitk::Image*>(m_InputImageNodes.at(i)->GetData())).GetPointer());
if (m_Controls->m_FaImageSelectionWidget->GetSelectedNode().IsNotNull())
{
ItkFloatImageType::Pointer itkImg = ItkFloatImageType::New();
mitk::CastToItkImage(dynamic_cast<mitk::Image*>(m_Controls->m_FaImageSelectionWidget->GetSelectedNode()->GetData()), itkImg);
dynamic_cast<mitk::TrackingHandlerTensor*>(m_TrackingHandler)->SetFaImage(itkImg);
}
}
}
}
else if ( dynamic_cast<mitk::OdfImage*>(m_InputImageNodes.at(0)->GetData()) ||
dynamic_cast<mitk::ShImage*>(m_InputImageNodes.at(0)->GetData()))
{
if (m_TrackingHandler==nullptr)
{
m_TrackingHandler = new mitk::TrackingHandlerOdf();
if (dynamic_cast<mitk::ShImage*>(m_InputImageNodes.at(0)->GetData()))
dynamic_cast<mitk::TrackingHandlerOdf*>(m_TrackingHandler)->SetOdfImage(mitk::convert::GetItkOdfFromShImage(dynamic_cast<mitk::ShImage*>(m_InputImageNodes.at(0)->GetData())));
else
dynamic_cast<mitk::TrackingHandlerOdf*>(m_TrackingHandler)->SetOdfImage(mitk::convert::GetItkOdfFromOdfImage(dynamic_cast<mitk::OdfImage*>(m_InputImageNodes.at(0)->GetData())));
if (m_Controls->m_FaImageSelectionWidget->GetSelectedNode().IsNotNull())
{
ItkFloatImageType::Pointer itkImg = ItkFloatImageType::New();
mitk::CastToItkImage(dynamic_cast<mitk::Image*>(m_Controls->m_FaImageSelectionWidget->GetSelectedNode()->GetData()), itkImg);
dynamic_cast<mitk::TrackingHandlerOdf*>(m_TrackingHandler)->SetGfaImage(itkImg);
}
}
}
else if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast<mitk::Image*>(m_InputImageNodes.at(0)->GetData())) )
{
if ( m_Controls->m_ForestSelectionWidget->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<mitk::TractographyForest*>(m_Controls->m_ForestSelectionWidget->GetSelectedNode()->GetData());
mitk::Image::Pointer dwi = dynamic_cast<mitk::Image*>(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)
{
params->m_NumPreviousDirections = static_cast<unsigned int>((forest->GetNumFeatures() - (100 + additionalFeatureImages.at(0).size()))/3);
m_TrackingHandler = new mitk::TrackingHandlerRandomForest<6, 100>();
dynamic_cast<mitk::TrackingHandlerRandomForest<6, 100>*>(m_TrackingHandler)->AddDwi(dwi);
dynamic_cast<mitk::TrackingHandlerRandomForest<6, 100>*>(m_TrackingHandler)->SetAdditionalFeatureImages(additionalFeatureImages);
dynamic_cast<mitk::TrackingHandlerRandomForest<6, 100>*>(m_TrackingHandler)->SetForest(forest);
forest_valid = dynamic_cast<mitk::TrackingHandlerRandomForest<6, 100>*>(m_TrackingHandler)->IsForestValid();
}
else
{
params->m_NumPreviousDirections = static_cast<unsigned int>((forest->GetNumFeatures() - (28 + additionalFeatureImages.at(0).size()))/3);
m_TrackingHandler = new mitk::TrackingHandlerRandomForest<6, 28>();
dynamic_cast<mitk::TrackingHandlerRandomForest<6, 28>*>(m_TrackingHandler)->AddDwi(dwi);
dynamic_cast<mitk::TrackingHandlerRandomForest<6, 28>*>(m_TrackingHandler)->SetAdditionalFeatureImages(additionalFeatureImages);
dynamic_cast<mitk::TrackingHandlerRandomForest<6, 28>*>(m_TrackingHandler)->SetForest(forest);
forest_valid = dynamic_cast<mitk::TrackingHandlerRandomForest<6, 28>*>(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_TrackingHandler==nullptr)
{
m_TrackingHandler = new mitk::TrackingHandlerPeaks();
dynamic_cast<mitk::TrackingHandlerPeaks*>(m_TrackingHandler)->SetPeakImage(mitk::convert::GetItkPeakFromPeakImage(dynamic_cast<mitk::Image*>(m_InputImageNodes.at(0)->GetData())));
}
}
if (m_Controls->m_InteractiveBox->isChecked())
{
m_Tracker->SetSeedPoints(m_SeedPoints);
}
else if (m_Controls->m_SeedImageSelectionWidget->GetSelectedNode().IsNotNull())
{
ItkFloatImageType::Pointer mask = ItkFloatImageType::New();
mitk::CastToItkImage(dynamic_cast<mitk::Image*>(m_Controls->m_SeedImageSelectionWidget->GetSelectedNode()->GetData()), mask);
m_Tracker->SetSeedImage(mask);
}
if (m_Controls->m_MaskImageSelectionWidget->GetSelectedNode().IsNotNull())
{
ItkFloatImageType::Pointer mask = ItkFloatImageType::New();
mitk::CastToItkImage(dynamic_cast<mitk::Image*>(m_Controls->m_MaskImageSelectionWidget->GetSelectedNode()->GetData()), mask);
m_Tracker->SetMaskImage(mask);
}
if (m_Controls->m_StopImageSelectionWidget->GetSelectedNode().IsNotNull())
{
ItkFloatImageType::Pointer mask = ItkFloatImageType::New();
mitk::CastToItkImage(dynamic_cast<mitk::Image*>(m_Controls->m_StopImageSelectionWidget->GetSelectedNode()->GetData()), mask);
m_Tracker->SetStoppingRegions(mask);
}
if (m_Controls->m_TargetImageSelectionWidget->GetSelectedNode().IsNotNull())
{
ItkFloatImageType::Pointer mask = ItkFloatImageType::New();
mitk::CastToItkImage(dynamic_cast<mitk::Image*>(m_Controls->m_TargetImageSelectionWidget->GetSelectedNode()->GetData()), mask);
m_Tracker->SetTargetRegions(mask);
}
if (m_Controls->m_PriorImageSelectionWidget->GetSelectedNode().IsNotNull())
{
auto prior_params = GetParametersFromGui();
if (m_LastPrior!=m_Controls->m_PriorImageSelectionWidget->GetSelectedNode() || m_TrackingPriorHandler==nullptr)
{
typedef mitk::ImageToItk< mitk::TrackingHandlerPeaks::PeakImgType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(dynamic_cast<mitk::PeakImage*>(m_Controls->m_PriorImageSelectionWidget->GetSelectedNode()->GetData()));
caster->SetCopyMemFlag(true);
caster->Update();
mitk::TrackingHandlerPeaks::PeakImgType::Pointer itkImg = caster->GetOutput();
m_TrackingPriorHandler = new mitk::TrackingHandlerPeaks();
dynamic_cast<mitk::TrackingHandlerPeaks*>(m_TrackingPriorHandler)->SetPeakImage(itkImg);
m_LastPrior = m_Controls->m_PriorImageSelectionWidget->GetSelectedNode();
}
prior_params->m_FlipX = m_Controls->m_PriorFlipXBox->isChecked();
prior_params->m_FlipY = m_Controls->m_PriorFlipYBox->isChecked();
prior_params->m_FlipZ = m_Controls->m_PriorFlipZBox->isChecked();
m_TrackingPriorHandler->SetParameters(prior_params);
m_Tracker->SetTrackingPriorHandler(m_TrackingPriorHandler);
}
else if (m_Controls->m_PriorImageSelectionWidget->GetSelectedNode().IsNull())
m_Tracker->SetTrackingPriorHandler(nullptr);
if (m_Controls->m_ExclusionImageSelectionWidget->GetSelectedNode().IsNotNull())
{
ItkFloatImageType::Pointer mask = ItkFloatImageType::New();
mitk::CastToItkImage(dynamic_cast<mitk::Image*>(m_Controls->m_ExclusionImageSelectionWidget->GetSelectedNode()->GetData()), mask);
m_Tracker->SetExclusionRegions(mask);
}
if (params->m_EpConstraints!=itk::StreamlineTrackingFilter::EndpointConstraints::NONE && m_Controls->m_TargetImageSelectionWidget->GetSelectedNode().IsNull())
{
QMessageBox::information(nullptr, "Error", "Endpoint constraints are used but no target image is set!");
StartStopTrackingGui(false);
return;
}
else if (params->m_EpConstraints==itk::StreamlineTrackingFilter::EndpointConstraints::EPS_IN_SEED_AND_TARGET
&& (m_Controls->m_SeedImageSelectionWidget->GetSelectedNode().IsNull()|| m_Controls->m_TargetImageSelectionWidget->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->SetParameters(params);
m_Tracker->SetTrackingHandler(m_TrackingHandler);
m_Tracker->SetVerbose(!m_Controls->m_InteractiveBox->isChecked());
m_ParentNode = m_InputImageNodes.at(0);
m_TrackingThread.start(QThread::LowestPriority);
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingView.h b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingView.h
index cfaafd0..7727d20 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/QmitkStreamlineTrackingView.h
@@ -1,160 +1,160 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkStreamlineTrackingView_h
#define QmitkStreamlineTrackingView_h
#include <QmitkAbstractView.h>
#include "ui_QmitkStreamlineTrackingViewControls.h"
#include <mitkTensorImage.h>
#include <mitkDataStorage.h>
#include <mitkDataNode.h>
#include <mitkImage.h>
#include <itkImage.h>
#include <itkStreamlineTrackingFilter.h>
#include <Algorithms/TrackingHandlers/mitkTrackingHandlerTensor.h>
#include <Algorithms/TrackingHandlers/mitkTrackingHandlerPeaks.h>
#include <Algorithms/TrackingHandlers/mitkTrackingHandlerOdf.h>
#include <Algorithms/TrackingHandlers/mitkTrackingHandlerRandomForest.h>
#include <random>
#include <mitkPointSet.h>
#include <mitkPointSetShapeProperty.h>
#include <mitkTractographyForest.h>
#include <QThread>
#include <QTimer>
#include <QmitkStdMultiWidget.h>
#include <QmitkSliceNavigationListener.h>
#include <mitkILifecycleAwarePart.h>
#include <mitkStreamlineTractographyParameters.h>
class QmitkStreamlineTrackingView;
class QmitkStreamlineTrackingWorker : public QObject
{
Q_OBJECT
public:
QmitkStreamlineTrackingWorker(QmitkStreamlineTrackingView* view);
public slots:
void run();
private:
QmitkStreamlineTrackingView* m_View;
};
/*!
\brief View for tensor based deterministic streamline fiber tracking.
*/
class QmitkStreamlineTrackingView : 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;
typedef itk::Image< unsigned int, 3 > ItkUintImgType;
typedef itk::Image< unsigned char, 3 > ItkUCharImageType;
typedef itk::Image< float, 3 > ItkFloatImageType;
typedef itk::StreamlineTrackingFilter TrackerType;
QmitkStreamlineTrackingView();
virtual ~QmitkStreamlineTrackingView();
virtual void CreateQtPartControl(QWidget *parent) override;
///
/// Sets the focus to an internal widget.
///
virtual void SetFocus() override;
TrackerType::Pointer m_Tracker;
QmitkStreamlineTrackingWorker m_TrackingWorker;
QThread m_TrackingThread;
virtual void Activated() override;
virtual void Deactivated() override;
virtual void Visible() override;
virtual void Hidden() override;
protected slots:
void DoFiberTracking(); ///< start fiber tracking
void UpdateGui();
void ToggleInteractive();
void DeleteTrackingHandler();
void OnParameterChanged();
void InteractiveSeedChanged(bool posChanged=false);
void ForestSwitched();
void OutputStyleSwitched();
void AfterThread(); ///< update gui etc. after tracking has finished
void BeforeThread(); ///< start timer etc.
void TimerUpdate();
void StopTractography();
void OnSliceChanged();
void SaveParameters();
void LoadParameters();
protected:
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
Ui::QmitkStreamlineTrackingViewControls* m_Controls;
protected slots:
private:
bool CheckAndStoreLastParams(QObject* obj);
void StartStopTrackingGui(bool start);
std::shared_ptr< mitk::StreamlineTractographyParameters > GetParametersFromGui();
void ParametersToGui(mitk::StreamlineTractographyParameters& params);
std::vector< itk::Point<float> > m_SeedPoints;
mitk::DataNode::Pointer m_ParentNode;
mitk::DataNode::Pointer m_InteractiveNode;
mitk::DataNode::Pointer m_InteractivePointSetNode;
std::vector< mitk::DataNode::Pointer > m_InputImageNodes; ///< input image nodes
std::vector< mitk::Image::ConstPointer > m_AdditionalInputImages;
bool m_FirstTensorProbRun;
bool m_FirstInteractiveRun;
mitk::TrackingDataHandler* m_TrackingHandler;
bool m_ThreadIsRunning;
QTimer* m_TrackingTimer;
bool m_DeleteTrackingHandler;
QmitkSliceNavigationListener m_SliceChangeListener;
bool m_Visible;
mitk::DataNode::Pointer m_LastPrior;
mitk::TrackingDataHandler* m_TrackingPriorHandler;
std::map< QString, std::string > m_LastTractoParams;
QString m_ParameterFile;
};
#endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/mitkPluginActivator.cpp
index 82c401f..80977ca 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/mitkPluginActivator.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/mitkPluginActivator.cpp
@@ -1,47 +1,47 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPluginActivator.h"
#include "src/internal/Perspectives/QmitkGibbsTractographyPerspective.h"
#include "src/internal/Perspectives/QmitkStreamlineTractographyPerspective.h"
#include "src/internal/QmitkGibbsTrackingView.h"
#include "src/internal/QmitkStreamlineTrackingView.h"
ctkPluginContext* mitk::PluginActivator::m_Context = nullptr;
ctkPluginContext* mitk::PluginActivator::GetContext()
{
return m_Context;
}
void mitk::PluginActivator::start(ctkPluginContext* context)
{
BERRY_REGISTER_EXTENSION_CLASS(QmitkGibbsTractographyPerspective, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkStreamlineTractographyPerspective, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkGibbsTrackingView, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkStreamlineTrackingView, context)
m_Context = context;
}
void mitk::PluginActivator::stop(ctkPluginContext* context)
{
Q_UNUSED(context)
m_Context = nullptr;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/mitkPluginActivator.h
index ebef166..b97342a 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/mitkPluginActivator.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging.tractography/src/internal/mitkPluginActivator.h
@@ -1,40 +1,40 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKPLUGINACTIVATOR_H
#define MITKPLUGINACTIVATOR_H
#include <ctkPluginActivator.h>
namespace mitk
{
class PluginActivator : public QObject, public ctkPluginActivator
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.mitk.gui.qt.diffusionimaging.tractography")
Q_INTERFACES(ctkPluginActivator)
public:
static ctkPluginContext* GetContext();
void start(ctkPluginContext* context) override;
void stop(ctkPluginContext* context) override;
private:
static ctkPluginContext* m_Context;
};
}
#endif
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Perspectives/QmitkDiffusionDefaultPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Perspectives/QmitkDiffusionDefaultPerspective.cpp
index c9dcd1a..a79b9d9 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Perspectives/QmitkDiffusionDefaultPerspective.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Perspectives/QmitkDiffusionDefaultPerspective.cpp
@@ -1,46 +1,46 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkDiffusionDefaultPerspective.h"
#include "berryIViewLayout.h"
void QmitkDiffusionDefaultPerspective::CreateInitialLayout(berry::IPageLayout::Pointer layout)
{
/////////////////////////////////////////////////////
// all di-app perspectives should have the following:
/////////////////////////////////////////////////////
QString editorArea = layout->GetEditorArea();
layout->AddStandaloneViewPlaceholder("org.mitk.views.viewnavigatorview", berry::IPageLayout::LEFT, 0.3f, editorArea, false);
layout->AddStandaloneView("org.mitk.views.datamanager", false, berry::IPageLayout::LEFT, 0.3f, editorArea);
layout->AddStandaloneView("org.mitk.views.controlvisualizationpropertiesview", false, berry::IPageLayout::BOTTOM, .15f, "org.mitk.views.datamanager");
berry::IFolderLayout::Pointer left =
layout->CreateFolder("org.mbi.diffusionimaginginternal.leftcontrols", berry::IPageLayout::BOTTOM, 0.15f, "org.mitk.views.controlvisualizationpropertiesview");
layout->AddStandaloneViewPlaceholder("org.mitk.views.imagenavigator", berry::IPageLayout::BOTTOM, .7f, "org.mbi.diffusionimaginginternal.leftcontrols", false);
/////////////////////////////////////////////
// here goes the perspective specific stuff
/////////////////////////////////////////////
left->AddView("org.mitk.views.diffusiondicomimport");
left->AddView("org.mitk.views.diffusionpreprocessing");
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Perspectives/QmitkDiffusionDefaultPerspective.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Perspectives/QmitkDiffusionDefaultPerspective.h
index 8dc9c2f..d044cda 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Perspectives/QmitkDiffusionDefaultPerspective.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Perspectives/QmitkDiffusionDefaultPerspective.h
@@ -1,36 +1,36 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkDiffusionDefaultPerspective_H_
#define QmitkDiffusionDefaultPerspective_H_
#include <berryIPerspectiveFactory.h>
class QmitkDiffusionDefaultPerspective : public QObject, public berry::IPerspectiveFactory
{
Q_OBJECT
Q_INTERFACES(berry::IPerspectiveFactory)
public:
QmitkDiffusionDefaultPerspective() {}
~QmitkDiffusionDefaultPerspective() {}
void CreateInitialLayout(berry::IPageLayout::Pointer layout) override;
};
#endif /* QmitkDiffusionDefaultPerspective_H_ */
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Perspectives/QmitkSegmentationPerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Perspectives/QmitkSegmentationPerspective.cpp
index c3ab70e..0da96b0 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Perspectives/QmitkSegmentationPerspective.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Perspectives/QmitkSegmentationPerspective.cpp
@@ -1,51 +1,51 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkSegmentationPerspective.h"
#include "berryIViewLayout.h"
void QmitkSegmentationPerspective::CreateInitialLayout(berry::IPageLayout::Pointer layout)
{
/////////////////////////////////////////////////////
// all di-app perspectives should have the following:
/////////////////////////////////////////////////////
QString editorArea = layout->GetEditorArea();
layout->AddStandaloneViewPlaceholder("org.mitk.views.viewnavigatorview", berry::IPageLayout::LEFT, 0.3f, editorArea, false);
layout->AddStandaloneView("org.mitk.views.datamanager",
false, berry::IPageLayout::LEFT, 0.3f, editorArea);
layout->AddStandaloneView("org.mitk.views.controlvisualizationpropertiesview",
false, berry::IPageLayout::BOTTOM, .15f, "org.mitk.views.datamanager");
berry::IFolderLayout::Pointer left =
layout->CreateFolder("org.mbi.diffusionimaginginternal.leftcontrols",
berry::IPageLayout::BOTTOM, 0.15f, "org.mitk.views.controlvisualizationpropertiesview");
layout->AddStandaloneViewPlaceholder("org.mitk.views.imagenavigator",
berry::IPageLayout::BOTTOM, .7f, "org.mbi.diffusionimaginginternal.leftcontrols", false);
/////////////////////////////////////////////
// here goes the perspective specific stuff
/////////////////////////////////////////////
left->AddView("org.mitk.views.tractseg");
left->AddView("org.mitk.views.segmentation");
left->AddView("org.mitk.views.segmentationutilities");
left->AddView("org.mitk.views.measurement");
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Perspectives/QmitkSegmentationPerspective.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Perspectives/QmitkSegmentationPerspective.h
index 37eb347..30d88a9 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Perspectives/QmitkSegmentationPerspective.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/Perspectives/QmitkSegmentationPerspective.h
@@ -1,36 +1,36 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkSegmentationPerspective_H_
#define QmitkSegmentationPerspective_H_
#include <berryIPerspectiveFactory.h>
class QmitkSegmentationPerspective : public QObject, public berry::IPerspectiveFactory
{
Q_OBJECT
Q_INTERFACES(berry::IPerspectiveFactory)
public:
QmitkSegmentationPerspective() {}
~QmitkSegmentationPerspective() {}
void CreateInitialLayout(berry::IPageLayout::Pointer layout) override;
};
#endif /* QmitkSegmentationPerspective_H_ */
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.cpp
index 441f54f..e9aac96 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.cpp
@@ -1,1250 +1,1250 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkControlVisualizationPropertiesView.h"
#include "mitkNodePredicateDataType.h"
#include "mitkDataNodeObject.h"
#include "mitkOdfNormalizationMethodProperty.h"
#include "mitkOdfScaleByProperty.h"
#include "mitkResliceMethodProperty.h"
#include "mitkRenderingManager.h"
#include "mitkImageCast.h"
#include "mitkShImage.h"
#include "mitkPlanarFigure.h"
#include "mitkFiberBundle.h"
#include "QmitkDataStorageComboBox.h"
#include "mitkPlanarFigureInteractor.h"
#include <mitkOdfImage.h>
#include <mitkTensorImage.h>
#include <mitkImage.h>
#include <mitkDiffusionPropertyHelper.h>
#include <mitkConnectomicsNetwork.h>
#include "usModuleRegistry.h"
#include <mitkPeakImage.h>
#include <mitkBaseRenderer.h>
#include "mitkPlaneGeometry.h"
#include <QmitkRenderWindow.h>
#include <itkFlipPeaksFilter.h>
#include <mitkImageToItk.h>
#include <mitkWorkbenchUtil.h>
#include "berryIWorkbenchWindow.h"
#include "berryIWorkbenchPage.h"
#include "berryISelectionService.h"
#include "berryConstants.h"
#include "berryPlatformUI.h"
#include "itkRGBAPixel.h"
#include <itkTractDensityImageFilter.h>
#include "qwidgetaction.h"
#include "qcolordialog.h"
#include <QRgb>
#include <itkMultiThreader.h>
#include <mitkClippingProperty.h>
#include <ciso646>
#define ROUND(a) ((a)>0 ? (int)((a)+0.5) : -(int)(0.5-(a)))
const std::string QmitkControlVisualizationPropertiesView::VIEW_ID = "org.mitk.views.controlvisualizationpropertiesview";
using namespace berry;
QmitkControlVisualizationPropertiesView::QmitkControlVisualizationPropertiesView()
: QmitkAbstractView(),
m_Controls(nullptr),
m_CurrentSelection(nullptr),
m_IconTexOFF(new QIcon(":/QmitkDiffusionImaging/texIntOFFIcon.png")),
m_IconTexON(new QIcon(":/QmitkDiffusionImaging/texIntONIcon.png")),
m_IconGlyOFF_T(new QIcon(":/QmitkDiffusionImaging/glyphsoff_T.png")),
m_IconGlyON_T(new QIcon(":/QmitkDiffusionImaging/glyphson_T.png")),
m_IconGlyOFF_C(new QIcon(":/QmitkDiffusionImaging/glyphsoff_C.png")),
m_IconGlyON_C(new QIcon(":/QmitkDiffusionImaging/glyphson_C.png")),
m_IconGlyOFF_S(new QIcon(":/QmitkDiffusionImaging/glyphsoff_S.png")),
m_IconGlyON_S(new QIcon(":/QmitkDiffusionImaging/glyphson_S.png")),
m_GlyIsOn_T(false),
m_GlyIsOn_C(false),
m_GlyIsOn_S(false),
m_CurrentThickSlicesMode(1),
m_CurrentThickSlicesNum(0),
m_CurrentPickingNode(nullptr),
m_ColorPropertyObserverTag(0),
m_OpacityPropertyObserverTag(0)
{
m_MyMenu = nullptr;
auto numThread = itk::MultiThreader::GetGlobalMaximumNumberOfThreads();
itk::MultiThreader::SetGlobalDefaultNumberOfThreads(numThread);
}
QmitkControlVisualizationPropertiesView::~QmitkControlVisualizationPropertiesView()
{
}
void QmitkControlVisualizationPropertiesView::SetTs(int currentThickSlicesMode, int num, std::string render_window)
{
if (auto renderWindowPart = this->GetRenderWindowPart(mitk::WorkbenchUtil::IRenderWindowPartStrategy::OPEN))
{
mitk::BaseRenderer::Pointer renderer = renderWindowPart->GetQmitkRenderWindow(QString(render_window.c_str()))->GetRenderer();
renderer->GetCurrentWorldPlaneGeometryNode()->SetProperty("reslice.thickslices.num", mitk::IntProperty::New(num));
if(num>0)
{
renderer->GetCurrentWorldPlaneGeometryNode()->SetProperty("reslice.thickslices", mitk::ResliceMethodProperty::New(currentThickSlicesMode));
renderer->GetCurrentWorldPlaneGeometryNode()->SetProperty("reslice.thickslices.showarea", mitk::BoolProperty::New(true));
}
else
{
renderer->GetCurrentWorldPlaneGeometryNode()->SetProperty("reslice.thickslices", mitk::ResliceMethodProperty::New(0));
renderer->GetCurrentWorldPlaneGeometryNode()->SetProperty("reslice.thickslices.showarea", mitk::BoolProperty::New(false));
}
renderer->SendUpdateSlice();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkControlVisualizationPropertiesView::OnThickSlicesModeSelected( QAction* action )
{
m_CurrentThickSlicesMode = action->data().toInt();
switch( m_CurrentThickSlicesMode )
{
case 0:
return;
case 1:
this->m_Controls->m_TSMenu->setText("MIP");
break;
case 2:
this->m_Controls->m_TSMenu->setText("SUM");
break;
case 3:
this->m_Controls->m_TSMenu->setText("WEIGH");
break;
default:
return;
}
SetTs(m_CurrentThickSlicesMode, m_CurrentThickSlicesNum, "axial");
SetTs(m_CurrentThickSlicesMode, m_CurrentThickSlicesNum, "sagittal");
SetTs(m_CurrentThickSlicesMode, m_CurrentThickSlicesNum, "coronal");
}
void QmitkControlVisualizationPropertiesView::OnTSNumChanged( int num )
{
m_CurrentThickSlicesNum = num;
SetTs(m_CurrentThickSlicesMode, m_CurrentThickSlicesNum, "axial");
SetTs(m_CurrentThickSlicesMode, m_CurrentThickSlicesNum, "sagittal");
SetTs(m_CurrentThickSlicesMode, m_CurrentThickSlicesNum, "coronal");
m_TSLabel->setText(QString::number( num*2 + 1 ));
}
void QmitkControlVisualizationPropertiesView::CreateQtPartControl(QWidget *parent)
{
if (!m_Controls)
{
// create GUI widgets
m_Controls = new Ui::QmitkControlVisualizationPropertiesViewControls;
m_Controls->setupUi(parent);
this->CreateConnections();
// hide warning (ODFs in rotated planes)
m_Controls->m_lblRotatedPlanesWarning->hide();
m_MyMenu = new QMenu(parent);
m_Controls->m_TSMenu->setMenu( m_MyMenu );
QIcon iconFiberFade(":/QmitkDiffusionImaging/MapperEfx2D.png");
m_Controls->m_FiberFading2D->setIcon(iconFiberFade);
m_Controls->m_NormalizationFrame->setVisible(false);
m_Controls->m_Crosshair->setVisible(false);
mitk::IRenderWindowPart* renderWindow = this->GetRenderWindowPart();
if (renderWindow)
{
m_SliceChangeListener.RenderWindowPartActivated(renderWindow);
connect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged()));
}
connect(m_Controls->m_SetColor1, SIGNAL(clicked()), this, SLOT(SetColor()));
connect(m_Controls->m_SetColor2, SIGNAL(clicked()), this, SLOT(SetColor()));
}
}
void QmitkControlVisualizationPropertiesView::SetColor()
{
if(m_SelectedNode)
{
QColor c = QColorDialog::getColor();
if (c.isValid())
{
float rgb[3];
rgb[0] = static_cast<float>(c.redF());
rgb[1] = static_cast<float>(c.greenF());
rgb[2] = static_cast<float>(c.blueF());
m_SelectedNode->SetColor(rgb);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
}
void QmitkControlVisualizationPropertiesView::SetFocus()
{
m_Controls->m_TSMenu->setFocus();
}
void QmitkControlVisualizationPropertiesView::SliceRotation(const itk::EventObject&)
{
// test if plane rotated
if( m_GlyIsOn_T || m_GlyIsOn_C || m_GlyIsOn_S )
{
if( this->IsPlaneRotated() )
{
// show label
m_Controls->m_lblRotatedPlanesWarning->show();
}
else
{
//hide label
m_Controls->m_lblRotatedPlanesWarning->hide();
}
}
}
void QmitkControlVisualizationPropertiesView::NodeRemoved(const mitk::DataNode* /*node*/)
{
}
#include <mitkMessage.h>
void QmitkControlVisualizationPropertiesView::CreateConnections()
{
if ( m_Controls )
{
connect( static_cast<QObject*>(m_Controls->m_VisibleOdfsON_T), SIGNAL(clicked()), this, SLOT(VisibleOdfsON_T()) );
connect( static_cast<QObject*>(m_Controls->m_VisibleOdfsON_S), SIGNAL(clicked()), this, SLOT(VisibleOdfsON_S()) );
connect( static_cast<QObject*>(m_Controls->m_VisibleOdfsON_C), SIGNAL(clicked()), this, SLOT(VisibleOdfsON_C()) );
connect( static_cast<QObject*>(m_Controls->m_ShowMaxNumber), SIGNAL(editingFinished()), this, SLOT(ShowMaxNumberChanged()) );
connect( static_cast<QObject*>(m_Controls->m_NormalizationDropdown), SIGNAL(currentIndexChanged(int)), this, SLOT(NormalizationDropdownChanged(int)) );
connect( static_cast<QObject*>(m_Controls->m_ScalingFactor), SIGNAL(valueChanged(double)), this, SLOT(ScalingFactorChanged(double)) );
connect( static_cast<QObject*>(m_Controls->m_AdditionalScaling), SIGNAL(currentIndexChanged(int)), this, SLOT(AdditionalScaling(int)) );
connect(static_cast<QObject*>(m_Controls->m_ResetColoring), SIGNAL(clicked()), static_cast<QObject*>(this), SLOT(ResetColoring()));
connect(static_cast<QObject*>(m_Controls->m_ResetColoring2), SIGNAL(clicked()), static_cast<QObject*>(this), SLOT(ResetColoring()));
connect(static_cast<QObject*>(m_Controls->m_FiberFading2D), SIGNAL(clicked()), static_cast<QObject*>(this), SLOT( Fiber2DfadingEFX() ) );
connect(static_cast<QObject*>(m_Controls->m_FiberThicknessSlider), SIGNAL(sliderReleased()), static_cast<QObject*>(this), SLOT( FiberSlicingThickness2D() ) );
connect(static_cast<QObject*>(m_Controls->m_FiberThicknessSlider), SIGNAL(valueChanged(int)), static_cast<QObject*>(this), SLOT( FiberSlicingUpdateLabel(int) ));
connect(static_cast<QObject*>(m_Controls->m_Crosshair), SIGNAL(clicked()), static_cast<QObject*>(this), SLOT(SetInteractor()));
connect(static_cast<QObject*>(m_Controls->m_LineWidth), SIGNAL(editingFinished()), static_cast<QObject*>(this), SLOT(LineWidthChanged()));
connect(static_cast<QObject*>(m_Controls->m_TubeWidth), SIGNAL(editingFinished()), static_cast<QObject*>(this), SLOT(TubeRadiusChanged()));
connect(static_cast<QObject*>(m_Controls->m_RibbonWidth), SIGNAL(editingFinished()), static_cast<QObject*>(this), SLOT(RibbonWidthChanged()));
connect( static_cast<QObject*>(m_Controls->m_OdfColorBox), SIGNAL(currentIndexChanged(int)), static_cast<QObject*>(this), SLOT(OnColourisationModeChanged() ) );
connect(static_cast<QObject*>(m_Controls->m_Clip0), SIGNAL(toggled(bool)), static_cast<QObject*>(this), SLOT(Toggle3DClipping(bool)));
connect(static_cast<QObject*>(m_Controls->m_Clip1), SIGNAL(toggled(bool)), static_cast<QObject*>(this), SLOT(Toggle3DClipping(bool)));
connect(static_cast<QObject*>(m_Controls->m_Clip2), SIGNAL(toggled(bool)), static_cast<QObject*>(this), SLOT(Toggle3DClipping(bool)));
connect(static_cast<QObject*>(m_Controls->m_Clip3), SIGNAL(toggled(bool)), static_cast<QObject*>(this), SLOT(Toggle3DClipping(bool)));
connect(static_cast<QObject*>(m_Controls->m_FlipClipBox), SIGNAL(stateChanged(int)), static_cast<QObject*>(this), SLOT(Toggle3DClipping()));
connect(static_cast<QObject*>(m_Controls->m_Enable3dPeaks), SIGNAL(stateChanged(int)), static_cast<QObject*>(this), SLOT(Toggle3DPeaks()));
connect(static_cast<QObject*>(m_Controls->m_FlipPeaksButton), SIGNAL(clicked()), static_cast<QObject*>(this), SLOT(FlipPeaks()));
m_Controls->m_BundleControlsFrame->setVisible(false);
m_Controls->m_ImageControlsFrame->setVisible(false);
m_Controls->m_PeakImageFrame->setVisible(false);
m_Controls->m_lblRotatedPlanesWarning->setVisible(false);
m_Controls->m_3DClippingBox->setVisible(false);
}
}
// set diffusion image channel to b0 volume
void QmitkControlVisualizationPropertiesView::NodeAdded(const mitk::DataNode *node)
{
mitk::DataNode* notConst = const_cast<mitk::DataNode*>(node);
bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast<mitk::Image *>(node->GetData())) );
if (isDiffusionImage)
{
mitk::Image::Pointer dimg = dynamic_cast<mitk::Image*>(notConst->GetData());
// if there is no b0 image in the dataset, the GetB0Indices() returns a vector of size 0
// and hence we cannot set the Property directly to .front()
int displayChannelPropertyValue = 0;
mitk::DiffusionPropertyHelper::BValueMapType map = mitk::DiffusionPropertyHelper::GetBValueMap(dimg);
if( map[0].size() > 0) { displayChannelPropertyValue = map[0].front(); }
notConst->SetIntProperty("DisplayChannel", displayChannelPropertyValue );
}
}
/* OnSelectionChanged is registered to SelectionService, therefore no need to
implement SelectionService Listener explicitly */
void QmitkControlVisualizationPropertiesView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList<mitk::DataNode::Pointer>& nodes)
{
m_Controls->m_BundleControlsFrame->setVisible(false);
m_Controls->m_ImageControlsFrame->setVisible(false);
m_Controls->m_PeakImageFrame->setVisible(false);
m_Controls->m_3DClippingBox->setVisible(false);
m_Controls->m_FlipClipBox->setVisible(false);
m_Controls->m_Enable3dPeaks->setVisible(false);
if (nodes.size()>1) // only do stuff if one node is selected
return;
m_Controls->m_NumberGlyphsFrame->setVisible(false);
m_Controls->m_GlyphFrame->setVisible(false);
m_Controls->m_TSMenu->setVisible(false);
m_SelectedNode = nullptr;
int numOdfImages = 0;
for (mitk::DataNode::Pointer node: nodes)
{
if(node.IsNull())
continue;
mitk::BaseData* nodeData = node->GetData();
if(nodeData == nullptr)
continue;
m_SelectedNode = node;
if (dynamic_cast<mitk::PeakImage*>(nodeData))
{
m_Controls->m_PeakImageFrame->setVisible(true);
if (m_Color.IsNotNull())
m_Color->RemoveObserver(m_ColorPropertyObserverTag);
itk::ReceptorMemberCommand<QmitkControlVisualizationPropertiesView>::Pointer command = itk::ReceptorMemberCommand<QmitkControlVisualizationPropertiesView>::New();
command->SetCallbackFunction( this, &QmitkControlVisualizationPropertiesView::SetCustomColor );
m_Color = dynamic_cast<mitk::ColorProperty*>(node->GetProperty("color", nullptr));
if (m_Color.IsNotNull())
m_ColorPropertyObserverTag = m_Color->AddObserver( itk::ModifiedEvent(), command );
int ClippingPlaneId = -1;
m_SelectedNode->GetPropertyValue("3DClippingPlaneId",ClippingPlaneId);
switch(ClippingPlaneId)
{
case 0:
m_Controls->m_Clip0->setChecked(1);
break;
case 1:
m_Controls->m_Clip1->setChecked(1);
break;
case 2:
m_Controls->m_Clip2->setChecked(1);
break;
case 3:
m_Controls->m_Clip3->setChecked(1);
break;
default :
m_Controls->m_Clip0->setChecked(1);
}
m_Controls->m_Enable3dPeaks->setVisible(true);
m_Controls->m_3DClippingBox->setVisible(true);
}
else if (dynamic_cast<mitk::FiberBundle*>(nodeData))
{
int ClippingPlaneId = -1;
m_SelectedNode->GetPropertyValue("3DClippingPlaneId",ClippingPlaneId);
switch(ClippingPlaneId)
{
case 0:
m_Controls->m_Clip0->setChecked(1);
break;
case 1:
m_Controls->m_Clip1->setChecked(1);
break;
case 2:
m_Controls->m_Clip2->setChecked(1);
break;
case 3:
m_Controls->m_Clip3->setChecked(1);
break;
default :
m_Controls->m_Clip0->setChecked(1);
}
// handle fiber property observers
if (m_Color.IsNotNull())
m_Color->RemoveObserver(m_ColorPropertyObserverTag);
itk::ReceptorMemberCommand<QmitkControlVisualizationPropertiesView>::Pointer command = itk::ReceptorMemberCommand<QmitkControlVisualizationPropertiesView>::New();
command->SetCallbackFunction( this, &QmitkControlVisualizationPropertiesView::SetCustomColor );
m_Color = dynamic_cast<mitk::ColorProperty*>(node->GetProperty("color", nullptr));
if (m_Color.IsNotNull())
m_ColorPropertyObserverTag = m_Color->AddObserver( itk::ModifiedEvent(), command );
m_Controls->m_FlipClipBox->setVisible(true);
m_Controls->m_3DClippingBox->setVisible(true);
m_Controls->m_BundleControlsFrame->setVisible(true);
if(m_CurrentPickingNode != 0 && node.GetPointer() != m_CurrentPickingNode)
{ m_Controls->m_Crosshair->setEnabled(false); }
else
{ m_Controls->m_Crosshair->setEnabled(true); }
int width;
node->GetIntProperty("shape.linewidth", width);
m_Controls->m_LineWidth->setValue(width);
float radius;
node->GetFloatProperty("shape.tuberadius", radius);
m_Controls->m_TubeWidth->setValue(radius);
float range;
node->GetFloatProperty("Fiber2DSliceThickness",range);
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(node->GetData());
mitk::BaseGeometry::Pointer geo = fib->GetGeometry();
mitk::ScalarType max = geo->GetExtentInMM(0);
max = std::max(max, geo->GetExtentInMM(1));
max = std::max(max, geo->GetExtentInMM(2));
m_Controls->m_FiberThicknessSlider->setMaximum(max * 10);
m_Controls->m_FiberThicknessSlider->setValue(range * 10);
}
else if(dynamic_cast<mitk::OdfImage*>(nodeData) || dynamic_cast<mitk::TensorImage*>(nodeData) || dynamic_cast<mitk::ShImage*>(nodeData))
{
m_Controls->m_ImageControlsFrame->setVisible(true);
m_Controls->m_NumberGlyphsFrame->setVisible(true);
m_Controls->m_GlyphFrame->setVisible(true);
m_Controls->m_NormalizationFrame->setVisible(true);
if(m_NodeUsedForOdfVisualization.IsNotNull())
{
m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_S", false);
m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_C", false);
m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_T", false);
}
m_NodeUsedForOdfVisualization = node;
m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_S", m_GlyIsOn_S);
m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_C", m_GlyIsOn_C);
m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_T", m_GlyIsOn_T);
if (dynamic_cast<mitk::TensorImage*>(nodeData))
{
m_Controls->m_NormalizationDropdown->setVisible(false);
m_Controls->m_NormalizationLabel->setVisible(false);
}
else
{
m_Controls->m_NormalizationDropdown->setVisible(true);
m_Controls->m_NormalizationLabel->setVisible(true);
}
int val;
node->GetIntProperty("ShowMaxNumber", val);
m_Controls->m_ShowMaxNumber->setValue(val);
m_Controls->m_NormalizationDropdown->setCurrentIndex(dynamic_cast<mitk::EnumerationProperty*>(node->GetProperty("Normalization"))->GetValueAsId());
float fval;
node->GetFloatProperty("Scaling",fval);
m_Controls->m_ScalingFactor->setValue(fval);
m_Controls->m_AdditionalScaling->setCurrentIndex(dynamic_cast<mitk::EnumerationProperty*>(node->GetProperty("ScaleBy"))->GetValueAsId());
bool switchTensorViewValue = false;
node->GetBoolProperty( "DiffusionCore.Rendering.OdfVtkMapper.SwitchTensorView", switchTensorViewValue );
bool colourisationModeBit = false;
node->GetBoolProperty("DiffusionCore.Rendering.OdfVtkMapper.ColourisationModeBit", colourisationModeBit );
m_Controls->m_OdfColorBox->setCurrentIndex(colourisationModeBit);
numOdfImages++;
}
else if(dynamic_cast<mitk::PlanarFigure*>(nodeData))
{
PlanarFigureFocus();
}
else if( dynamic_cast<mitk::Image*>(nodeData) )
{
m_Controls->m_ImageControlsFrame->setVisible(true);
m_Controls->m_TSMenu->setVisible(true);
}
}
if( nodes.empty() ) { return; }
mitk::DataNode::Pointer node = nodes.at(0);
if( node.IsNull() ) { return; }
QMenu *myMenu = m_MyMenu;
myMenu->clear();
QActionGroup* thickSlicesActionGroup = new QActionGroup(myMenu);
thickSlicesActionGroup->setExclusive(true);
int currentTSMode = 0;
{
mitk::ResliceMethodProperty::Pointer m = dynamic_cast<mitk::ResliceMethodProperty*>(node->GetProperty( "reslice.thickslices" ));
if( m.IsNotNull() )
currentTSMode = m->GetValueAsId();
}
int maxTS = 30;
for (auto node: nodes)
{
mitk::Image* image = dynamic_cast<mitk::Image*>(node->GetData());
if (image)
{
int size = std::max(image->GetDimension(0), std::max(image->GetDimension(1), image->GetDimension(2)));
if (size>maxTS) { maxTS=size; }
}
}
maxTS /= 2;
int currentNum = 0;
{
mitk::IntProperty::Pointer m = dynamic_cast<mitk::IntProperty*>(node->GetProperty( "reslice.thickslices.num" ));
if( m.IsNotNull() )
{
currentNum = m->GetValue();
if(currentNum < 0) { currentNum = 0; }
if(currentNum > maxTS) { currentNum = maxTS; }
}
}
if(currentTSMode==0) { currentNum=0; }
QSlider *m_TSSlider = new QSlider(myMenu);
m_TSSlider->setMinimum(0);
m_TSSlider->setMaximum(maxTS-1);
m_TSSlider->setValue(currentNum);
m_TSSlider->setOrientation(Qt::Horizontal);
connect( m_TSSlider, SIGNAL( valueChanged(int) ), this, SLOT( OnTSNumChanged(int) ) );
QHBoxLayout* _TSLayout = new QHBoxLayout;
_TSLayout->setContentsMargins(4,4,4,4);
_TSLayout->addWidget(m_TSSlider);
_TSLayout->addWidget(m_TSLabel=new QLabel(QString::number(currentNum*2+1),myMenu));
QWidget* _TSWidget = new QWidget;
_TSWidget->setLayout(_TSLayout);
QActionGroup* thickSliceModeActionGroup = new QActionGroup(myMenu);
thickSliceModeActionGroup->setExclusive(true);
QWidgetAction *m_TSSliderAction = new QWidgetAction(myMenu);
m_TSSliderAction->setDefaultWidget(_TSWidget);
myMenu->addAction(m_TSSliderAction);
QAction* mipThickSlicesAction = new QAction(myMenu);
mipThickSlicesAction->setActionGroup(thickSliceModeActionGroup);
mipThickSlicesAction->setText("MIP (max. intensity proj.)");
mipThickSlicesAction->setCheckable(true);
mipThickSlicesAction->setChecked(m_CurrentThickSlicesMode==1);
mipThickSlicesAction->setData(1);
myMenu->addAction( mipThickSlicesAction );
QAction* sumThickSlicesAction = new QAction(myMenu);
sumThickSlicesAction->setActionGroup(thickSliceModeActionGroup);
sumThickSlicesAction->setText("SUM (sum intensity proj.)");
sumThickSlicesAction->setCheckable(true);
sumThickSlicesAction->setChecked(m_CurrentThickSlicesMode==2);
sumThickSlicesAction->setData(2);
myMenu->addAction( sumThickSlicesAction );
QAction* weightedThickSlicesAction = new QAction(myMenu);
weightedThickSlicesAction->setActionGroup(thickSliceModeActionGroup);
weightedThickSlicesAction->setText("WEIGHTED (gaussian proj.)");
weightedThickSlicesAction->setCheckable(true);
weightedThickSlicesAction->setChecked(m_CurrentThickSlicesMode==3);
weightedThickSlicesAction->setData(3);
myMenu->addAction( weightedThickSlicesAction );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
connect( thickSliceModeActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(OnThickSlicesModeSelected(QAction*)) );
}
void QmitkControlVisualizationPropertiesView::VisibleOdfsON_S()
{
m_GlyIsOn_S = m_Controls->m_VisibleOdfsON_S->isChecked();
if (m_NodeUsedForOdfVisualization.IsNull())
{
MITK_WARN << "ODF visualization activated but m_NodeUsedForOdfVisualization is nullptr";
return;
}
m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_S", m_GlyIsOn_S);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkControlVisualizationPropertiesView::Visible()
{
mitk::IRenderWindowPart* renderWindow = this->GetRenderWindowPart();
if (renderWindow)
{
m_SliceChangeListener.RenderWindowPartActivated(renderWindow);
connect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged()));
}
}
void QmitkControlVisualizationPropertiesView::Hidden()
{
}
void QmitkControlVisualizationPropertiesView::Activated()
{
mitk::IRenderWindowPart* renderWindow = this->GetRenderWindowPart();
if (renderWindow)
{
m_SliceChangeListener.RenderWindowPartActivated(renderWindow);
connect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged()));
}
}
void QmitkControlVisualizationPropertiesView::Deactivated()
{
}
void QmitkControlVisualizationPropertiesView::FlipPeaks()
{
if (m_SelectedNode.IsNull() || dynamic_cast<mitk::PeakImage*>(m_SelectedNode->GetData())==nullptr)
return;
std::string name = m_SelectedNode->GetName();
mitk::Image::Pointer image = dynamic_cast<mitk::PeakImage*>(m_SelectedNode->GetData());
typedef mitk::ImageToItk< mitk::PeakImage::ItkPeakImageType > CasterType;
CasterType::Pointer caster = CasterType::New();
caster->SetInput(image);
caster->Update();
mitk::PeakImage::ItkPeakImageType::Pointer itkImg = caster->GetOutput();
itk::FlipPeaksFilter< float >::Pointer flipper = itk::FlipPeaksFilter< float >::New();
flipper->SetInput(itkImg);
flipper->SetFlipX(m_Controls->m_FlipPeaksX->isChecked());
flipper->SetFlipY(m_Controls->m_FlipPeaksY->isChecked());
flipper->SetFlipZ(m_Controls->m_FlipPeaksZ->isChecked());
flipper->Update();
mitk::Image::Pointer resultImage = dynamic_cast<mitk::Image*>(mitk::PeakImage::New().GetPointer());
mitk::CastToMitkImage(flipper->GetOutput(), resultImage);
resultImage->SetVolume(flipper->GetOutput()->GetBufferPointer());
m_SelectedNode->SetData(resultImage);
m_SelectedNode->SetName(name);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkControlVisualizationPropertiesView::Toggle3DPeaks()
{
if (m_SelectedNode.IsNull() || dynamic_cast<mitk::PeakImage*>(m_SelectedNode->GetData())==nullptr)
return;
bool enabled = false;
m_SelectedNode->GetBoolProperty("Enable3DPeaks", enabled);
m_SelectedNode->SetBoolProperty( "Enable3DPeaks", !enabled );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkControlVisualizationPropertiesView::Toggle3DClipping(bool enabled)
{
if (!enabled || m_SelectedNode.IsNull() || (dynamic_cast<mitk::FiberBundle*>(m_SelectedNode->GetData())==nullptr && dynamic_cast<mitk::PeakImage*>(m_SelectedNode->GetData())==nullptr))
return;
m_SelectedNode->SetBoolProperty( "3DClippingPlaneFlip", m_Controls->m_FlipClipBox->isChecked() );
if (m_Controls->m_Clip0->isChecked())
{
m_SelectedNode->SetIntProperty( "3DClippingPlaneId", 0 );
Set3DClippingPlane(true, m_SelectedNode, "");
}
else if (m_Controls->m_Clip1->isChecked())
{
m_SelectedNode->SetIntProperty( "3DClippingPlaneId", 1 );
Set3DClippingPlane(false, m_SelectedNode, "axial");
}
else if (m_Controls->m_Clip2->isChecked())
{
m_SelectedNode->SetIntProperty( "3DClippingPlaneId", 2 );
Set3DClippingPlane(false, m_SelectedNode, "sagittal");
}
else if (m_Controls->m_Clip3->isChecked())
{
m_SelectedNode->SetIntProperty( "3DClippingPlaneId", 3 );
Set3DClippingPlane(false, m_SelectedNode, "coronal");
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkControlVisualizationPropertiesView::OnSliceChanged()
{
mitk::DataStorage::SetOfObjects::ConstPointer nodes = this->GetDataStorage()->GetAll();
for (unsigned int i=0; i<nodes->Size(); ++i)
{
mitk::DataNode::Pointer node = nodes->GetElement(i);
int plane_id = -1;
node->GetIntProperty("3DClippingPlaneId", plane_id);
if (plane_id==1)
Set3DClippingPlane(false, node, "axial");
else if (plane_id==2)
Set3DClippingPlane(false, node, "sagittal");
else if (plane_id==3)
Set3DClippingPlane(false, node, "coronal");
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkControlVisualizationPropertiesView::Set3DClippingPlane(bool disable, mitk::DataNode* node, std::string plane)
{
mitk::IRenderWindowPart* renderWindow = this->GetRenderWindowPart();
if (renderWindow && node && (dynamic_cast<mitk::FiberBundle*>(node->GetData()) || dynamic_cast<mitk::PeakImage*>(node->GetData())))
{
mitk::Vector3D planeNormal; planeNormal.Fill(0.0);
mitk::Point3D planeOrigin; planeOrigin.Fill(0.0);
if (!disable)
{
mitk::SliceNavigationController* slicer = renderWindow->GetQmitkRenderWindow(QString(plane.c_str()))->GetSliceNavigationController();
mitk::PlaneGeometry::ConstPointer planeGeo = slicer->GetCurrentPlaneGeometry();
planeOrigin = this->GetRenderWindowPart()->GetSelectedPosition();
planeNormal = planeGeo->GetNormal();
}
node->SetProperty( "3DClipping", mitk::ClippingProperty::New( planeOrigin, planeNormal ) );
if (dynamic_cast<mitk::FiberBundle*>(node->GetData()))
dynamic_cast<mitk::FiberBundle*>(node->GetData())->RequestUpdate();
else
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkControlVisualizationPropertiesView::VisibleOdfsON_T()
{
m_GlyIsOn_T = m_Controls->m_VisibleOdfsON_T->isChecked();
if (m_NodeUsedForOdfVisualization.IsNull())
{
MITK_WARN << "ODF visualization activated but m_NodeUsedForOdfVisualization is nullptr";
return;
}
m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_T", m_GlyIsOn_T);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkControlVisualizationPropertiesView::VisibleOdfsON_C()
{
m_GlyIsOn_C = m_Controls->m_VisibleOdfsON_C->isChecked();
if (m_NodeUsedForOdfVisualization.IsNull())
{
MITK_WARN << "ODF visualization activated but m_NodeUsedForOdfVisualization is nullptr";
return;
}
m_NodeUsedForOdfVisualization->SetBoolProperty("VisibleOdfs_C", m_GlyIsOn_C);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
bool QmitkControlVisualizationPropertiesView::IsPlaneRotated()
{
mitk::Image* currentImage = dynamic_cast<mitk::Image* >( m_NodeUsedForOdfVisualization->GetData() );
if( currentImage == nullptr )
{
MITK_ERROR << " Casting problems. Returning false";
return false;
}
mitk::Vector3D imageNormal0 = currentImage->GetSlicedGeometry()->GetAxisVector(0);
mitk::Vector3D imageNormal1 = currentImage->GetSlicedGeometry()->GetAxisVector(1);
mitk::Vector3D imageNormal2 = currentImage->GetSlicedGeometry()->GetAxisVector(2);
imageNormal0.Normalize();
imageNormal1.Normalize();
imageNormal2.Normalize();
auto renderWindowPart = this->GetRenderWindowPart();
double eps = 0.000001;
// for all 2D renderwindows of the render window part check alignment
{
mitk::PlaneGeometry::ConstPointer displayPlane
= dynamic_cast<const mitk::PlaneGeometry*>
( renderWindowPart->GetQmitkRenderWindow("axial")->GetRenderer()->GetCurrentWorldPlaneGeometry() );
if (displayPlane.IsNull()) { return false; }
mitk::Vector3D normal = displayPlane->GetNormal();
normal.Normalize();
int test = 0;
if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal0.GetVnlVector()))-1) > eps ) { test++; }
if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal1.GetVnlVector()))-1) > eps ) { test++; }
if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal2.GetVnlVector()))-1) > eps ) { test++; }
if (test==3) { return true; }
}
{
mitk::PlaneGeometry::ConstPointer displayPlane
= dynamic_cast<const mitk::PlaneGeometry*>
( renderWindowPart->GetQmitkRenderWindow("sagittal")->GetRenderer()->GetCurrentWorldPlaneGeometry() );
if (displayPlane.IsNull()) { return false; }
mitk::Vector3D normal = displayPlane->GetNormal();
normal.Normalize();
int test = 0;
if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal0.GetVnlVector()))-1) > eps ) { test++; }
if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal1.GetVnlVector()))-1) > eps ) { test++; }
if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal2.GetVnlVector()))-1) > eps ) { test++; }
if (test==3) { return true; }
}
{
mitk::PlaneGeometry::ConstPointer displayPlane
= dynamic_cast<const mitk::PlaneGeometry*>
( renderWindowPart->GetQmitkRenderWindow("coronal")->GetRenderer()->GetCurrentWorldPlaneGeometry() );
if (displayPlane.IsNull()) { return false; }
mitk::Vector3D normal = displayPlane->GetNormal();
normal.Normalize();
int test = 0;
if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal0.GetVnlVector()))-1) > eps ) { test++; }
if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal1.GetVnlVector()))-1) > eps ) { test++; }
if( fabs(fabs(dot_product(normal.GetVnlVector(),imageNormal2.GetVnlVector()))-1) > eps ) { test++; }
if (test==3) { return true; }
}
return false;
}
void QmitkControlVisualizationPropertiesView::ShowMaxNumberChanged()
{
int maxNr = m_Controls->m_ShowMaxNumber->value();
if ( maxNr < 1 )
{
m_Controls->m_ShowMaxNumber->setValue( 1 );
maxNr = 1;
}
if ( dynamic_cast<mitk::OdfImage*>(m_SelectedNode->GetData())
|| dynamic_cast<mitk::TensorImage*>(m_SelectedNode->GetData())
|| dynamic_cast<mitk::ShImage*>(m_SelectedNode->GetData()) )
{
m_SelectedNode->SetIntProperty("ShowMaxNumber", maxNr);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkControlVisualizationPropertiesView::NormalizationDropdownChanged(int normDropdown)
{
typedef mitk::OdfNormalizationMethodProperty PropType;
PropType::Pointer normMeth = PropType::New();
switch(normDropdown)
{
case 0:
normMeth->SetNormalizationToMinMax();
break;
case 1:
normMeth->SetNormalizationToMax();
break;
case 2:
normMeth->SetNormalizationToNone();
break;
case 3:
normMeth->SetNormalizationToGlobalMax();
break;
default:
normMeth->SetNormalizationToMinMax();
}
if ( dynamic_cast<mitk::OdfImage*>(m_SelectedNode->GetData())
|| dynamic_cast<mitk::TensorImage*>(m_SelectedNode->GetData())
|| dynamic_cast<mitk::ShImage*>(m_SelectedNode->GetData()) )
{
m_SelectedNode->SetProperty("Normalization", normMeth.GetPointer());
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkControlVisualizationPropertiesView::ScalingFactorChanged(double scalingFactor)
{
if ( dynamic_cast<mitk::OdfImage*>(m_SelectedNode->GetData())
|| dynamic_cast<mitk::TensorImage*>(m_SelectedNode->GetData())
|| dynamic_cast<mitk::ShImage*>(m_SelectedNode->GetData()) )
{
m_SelectedNode->SetFloatProperty("Scaling", scalingFactor);
}
if (auto renderWindowPart = this->GetRenderWindowPart())
{
renderWindowPart->RequestUpdate();
}
}
void QmitkControlVisualizationPropertiesView::AdditionalScaling(int additionalScaling)
{
typedef mitk::OdfScaleByProperty PropType;
PropType::Pointer scaleBy = PropType::New();
switch(additionalScaling)
{
case 0:
scaleBy->SetScaleByNothing();
break;
case 1:
scaleBy->SetScaleByGFA();
//m_Controls->params_frame->setVisible(true);
break;
default:
scaleBy->SetScaleByNothing();
}
if ( dynamic_cast<mitk::OdfImage*>(m_SelectedNode->GetData())
|| dynamic_cast<mitk::TensorImage*>(m_SelectedNode->GetData())
|| dynamic_cast<mitk::ShImage*>(m_SelectedNode->GetData()) )
{
m_SelectedNode->SetProperty("ScaleBy", scaleBy.GetPointer());
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkControlVisualizationPropertiesView::Fiber2DfadingEFX()
{
if (m_SelectedNode && dynamic_cast<mitk::FiberBundle*>(m_SelectedNode->GetData()) )
{
bool currentMode;
m_SelectedNode->GetBoolProperty("Fiber2DfadeEFX", currentMode);
m_SelectedNode->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(!currentMode));
dynamic_cast<mitk::FiberBundle*>(m_SelectedNode->GetData())->RequestUpdate2D();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkControlVisualizationPropertiesView::FiberSlicingThickness2D()
{
if (m_SelectedNode && dynamic_cast<mitk::FiberBundle*>(m_SelectedNode->GetData()))
{
float fibThickness = m_Controls->m_FiberThicknessSlider->value() * 0.1;
float currentThickness = 0;
m_SelectedNode->GetFloatProperty("Fiber2DSliceThickness", currentThickness);
if ( fabs(fibThickness-currentThickness) < 0.001 )
{
return;
}
m_SelectedNode->SetProperty("Fiber2DSliceThickness", mitk::FloatProperty::New(fibThickness));
dynamic_cast<mitk::FiberBundle*>(m_SelectedNode->GetData())->RequestUpdate2D();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkControlVisualizationPropertiesView::FiberSlicingUpdateLabel(int value)
{
QString label = "Range %1 mm";
label = label.arg(value * 0.1);
m_Controls->label_range->setText(label);
FiberSlicingThickness2D();
}
void QmitkControlVisualizationPropertiesView::SetCustomColor(const itk::EventObject& /*e*/)
{
if(m_SelectedNode && dynamic_cast<mitk::FiberBundle*>(m_SelectedNode->GetData()))
{
float color[3];
m_SelectedNode->GetColor(color);
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(m_SelectedNode->GetData());
fib->SetFiberColors(color[0]*255, color[1]*255, color[2]*255);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
else if (m_SelectedNode && dynamic_cast<mitk::PeakImage*>(m_SelectedNode->GetData()))
{
float color[3];
m_SelectedNode->GetColor(color);
mitk::PeakImage::Pointer img = dynamic_cast<mitk::PeakImage*>(m_SelectedNode->GetData());
img->SetCustomColor(color[0]*255, color[1]*255, color[2]*255);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkControlVisualizationPropertiesView::ResetColoring()
{
if(m_SelectedNode && dynamic_cast<mitk::FiberBundle*>(m_SelectedNode->GetData()))
{
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(m_SelectedNode->GetData());
fib->ColorFibersByOrientation();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
else if(m_SelectedNode && dynamic_cast<mitk::PeakImage*>(m_SelectedNode->GetData()))
{
mitk::PeakImage::Pointer fib = dynamic_cast<mitk::PeakImage*>(m_SelectedNode->GetData());
fib->ColorByOrientation();
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkControlVisualizationPropertiesView::PlanarFigureFocus()
{
if(m_SelectedNode)
{
mitk::PlanarFigure* _PlanarFigure = 0;
_PlanarFigure = dynamic_cast<mitk::PlanarFigure*> (m_SelectedNode->GetData());
if (_PlanarFigure && _PlanarFigure->GetPlaneGeometry())
{
QmitkRenderWindow* selectedRenderWindow = 0;
bool PlanarFigureInitializedWindow = false;
auto renderWindowPart = this->GetRenderWindowPart(mitk::WorkbenchUtil::IRenderWindowPartStrategy::OPEN);
QmitkRenderWindow* axialRenderWindow =
renderWindowPart->GetQmitkRenderWindow("axial");
if (m_SelectedNode->GetBoolProperty("PlanarFigureInitializedWindow",
PlanarFigureInitializedWindow, axialRenderWindow->GetRenderer()))
{
selectedRenderWindow = axialRenderWindow;
}
QmitkRenderWindow* sagittalRenderWindow =
renderWindowPart->GetQmitkRenderWindow("sagittal");
if (!selectedRenderWindow && m_SelectedNode->GetBoolProperty(
"PlanarFigureInitializedWindow", PlanarFigureInitializedWindow,
sagittalRenderWindow->GetRenderer()))
{
selectedRenderWindow = sagittalRenderWindow;
}
QmitkRenderWindow* coronalRenderWindow =
renderWindowPart->GetQmitkRenderWindow("coronal");
if (!selectedRenderWindow && m_SelectedNode->GetBoolProperty(
"PlanarFigureInitializedWindow", PlanarFigureInitializedWindow,
coronalRenderWindow->GetRenderer()))
{
selectedRenderWindow = coronalRenderWindow;
}
QmitkRenderWindow* _3DRenderWindow =
renderWindowPart->GetQmitkRenderWindow("3d");
if (!selectedRenderWindow && m_SelectedNode->GetBoolProperty(
"PlanarFigureInitializedWindow", PlanarFigureInitializedWindow,
_3DRenderWindow->GetRenderer()))
{
selectedRenderWindow = _3DRenderWindow;
}
const mitk::PlaneGeometry* _PlaneGeometry = _PlanarFigure->GetPlaneGeometry();
mitk::VnlVector normal = _PlaneGeometry->GetNormalVnl();
mitk::PlaneGeometry::ConstPointer worldGeometry1 =
axialRenderWindow->GetRenderer()->GetCurrentWorldPlaneGeometry();
mitk::PlaneGeometry::ConstPointer _Plane1 =
dynamic_cast<const mitk::PlaneGeometry*>( worldGeometry1.GetPointer() );
mitk::VnlVector normal1 = _Plane1->GetNormalVnl();
mitk::PlaneGeometry::ConstPointer worldGeometry2 =
sagittalRenderWindow->GetRenderer()->GetCurrentWorldPlaneGeometry();
mitk::PlaneGeometry::ConstPointer _Plane2 =
dynamic_cast<const mitk::PlaneGeometry*>( worldGeometry2.GetPointer() );
mitk::VnlVector normal2 = _Plane2->GetNormalVnl();
mitk::PlaneGeometry::ConstPointer worldGeometry3 =
coronalRenderWindow->GetRenderer()->GetCurrentWorldPlaneGeometry();
mitk::PlaneGeometry::ConstPointer _Plane3 =
dynamic_cast<const mitk::PlaneGeometry*>( worldGeometry3.GetPointer() );
mitk::VnlVector normal3 = _Plane3->GetNormalVnl();
normal[0] = fabs(normal[0]); normal[1] = fabs(normal[1]); normal[2] = fabs(normal[2]);
normal1[0] = fabs(normal1[0]); normal1[1] = fabs(normal1[1]); normal1[2] = fabs(normal1[2]);
normal2[0] = fabs(normal2[0]); normal2[1] = fabs(normal2[1]); normal2[2] = fabs(normal2[2]);
normal3[0] = fabs(normal3[0]); normal3[1] = fabs(normal3[1]); normal3[2] = fabs(normal3[2]);
double ang1 = angle(normal, normal1);
double ang2 = angle(normal, normal2);
double ang3 = angle(normal, normal3);
if(ang1 < ang2 && ang1 < ang3)
{
selectedRenderWindow = axialRenderWindow;
}
else
{
if(ang2 < ang3)
{
selectedRenderWindow = sagittalRenderWindow;
}
else
{
selectedRenderWindow = coronalRenderWindow;
}
}
// make node visible
if (selectedRenderWindow)
{
const mitk::Point3D& centerP = _PlaneGeometry->GetOrigin();
selectedRenderWindow->GetSliceNavigationController()->ReorientSlices(
centerP, _PlaneGeometry->GetNormal());
}
}
// set interactor for new node (if not already set)
mitk::PlanarFigureInteractor::Pointer figureInteractor
= dynamic_cast<mitk::PlanarFigureInteractor*>(m_SelectedNode->GetDataInteractor().GetPointer());
if(figureInteractor.IsNull())
{
figureInteractor = mitk::PlanarFigureInteractor::New();
us::Module* planarFigureModule = us::ModuleRegistry::GetModule( "MitkPlanarFigure" );
figureInteractor->LoadStateMachine("PlanarFigureInteraction.xml", planarFigureModule );
figureInteractor->SetEventConfig( "PlanarFigureConfig.xml", planarFigureModule );
figureInteractor->SetDataNode( m_SelectedNode );
}
m_SelectedNode->SetProperty("planarfigure.iseditable",mitk::BoolProperty::New(true));
}
}
void QmitkControlVisualizationPropertiesView::SetInteractor()
{
// BUG 19179
// typedef std::vector<mitk::DataNode*> Container;
// Container _NodeSet = this->GetDataManagerSelection();
// mitk::DataNode* node = 0;
// mitk::FiberBundle* bundle = 0;
// mitk::FiberBundleInteractor::Pointer bundleInteractor = 0;
// // finally add all nodes to the model
// for(Container::const_iterator it=_NodeSet.begin(); it!=_NodeSet.end()
// ; it++)
// {
// node = const_cast<mitk::DataNode*>(*it);
// bundle = dynamic_cast<mitk::FiberBundle*>(node->GetData());
// if(bundle)
// {
// bundleInteractor = dynamic_cast<mitk::FiberBundleInteractor*>(node->GetInteractor());
// if(bundleInteractor.IsNotNull())
// mitk::GlobalInteraction::GetInstance()->RemoveInteractor(bundleInteractor);
// if(!m_Controls->m_Crosshair->isChecked())
// {
// m_Controls->m_Crosshair->setChecked(false);
// this->GetActiveStdMultiWidget()->GetRenderWindow4()->setCursor(Qt::ArrowCursor);
// m_CurrentPickingNode = 0;
// }
// else
// {
// m_Controls->m_Crosshair->setChecked(true);
// bundleInteractor = mitk::FiberBundleInteractor::New("FiberBundleInteractor", node);
// mitk::GlobalInteraction::GetInstance()->AddInteractor(bundleInteractor);
// this->GetActiveStdMultiWidget()->GetRenderWindow4()->setCursor(Qt::CrossCursor);
// m_CurrentPickingNode = node;
// }
// }
// }
}
void QmitkControlVisualizationPropertiesView::TubeRadiusChanged()
{
if(m_SelectedNode && dynamic_cast<mitk::FiberBundle*>(m_SelectedNode->GetData()))
{
float newRadius = m_Controls->m_TubeWidth->value();
m_SelectedNode->SetFloatProperty("shape.tuberadius", newRadius);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkControlVisualizationPropertiesView::RibbonWidthChanged()
{
if(m_SelectedNode && dynamic_cast<mitk::FiberBundle*>(m_SelectedNode->GetData()))
{
float newWidth = m_Controls->m_RibbonWidth->value();
m_SelectedNode->SetFloatProperty("shape.ribbonwidth", newWidth);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkControlVisualizationPropertiesView::LineWidthChanged()
{
if(m_SelectedNode && dynamic_cast<mitk::PeakImage*>(m_SelectedNode->GetData()))
{
auto newWidth = m_Controls->m_LineWidth->value();
float currentWidth = 0;
m_SelectedNode->SetFloatProperty("shape.linewidth", currentWidth);
if (currentWidth==newWidth)
return;
m_SelectedNode->SetFloatProperty("shape.linewidth", newWidth);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
}
void QmitkControlVisualizationPropertiesView::Welcome()
{
berry::PlatformUI::GetWorkbench()->GetIntroManager()
->ShowIntro(GetSite()->GetWorkbenchWindow(), false);
}
void QmitkControlVisualizationPropertiesView::OnColourisationModeChanged()
{
if( m_SelectedNode && m_NodeUsedForOdfVisualization.IsNotNull() )
{
m_SelectedNode->SetProperty( "DiffusionCore.Rendering.OdfVtkMapper.ColourisationModeBit", mitk::BoolProperty::New( m_Controls->m_OdfColorBox->currentIndex() ) );
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
else
{
MITK_DEBUG << "QmitkControlVisualizationPropertiesView::OnColourisationModeChanged() was called but m_NodeUsedForOdfVisualization was Null.";
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.h
index 04736dd..177c7fc 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.h
@@ -1,155 +1,155 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _QMITKControlVisualizationPropertiesView_H_INCLUDED
#define _QMITKControlVisualizationPropertiesView_H_INCLUDED
#include <QmitkAbstractView.h>
#include <string>
#include "berryISelectionListener.h"
#include "berryIStructuredSelection.h"
#include "berryISizeProvider.h"
#include "ui_QmitkControlVisualizationPropertiesViewControls.h"
#include "mitkEnumerationProperty.h"
#include <mitkILifecycleAwarePart.h>
#include <QmitkSliceNavigationListener.h>
/*!
* \ingroup org_mitk_gui_qt_diffusionquantification_internal
*
* \brief QmitkControlVisualizationPropertiesView
*
* Document your class here.
*/
class QmitkControlVisualizationPropertiesView : public QmitkAbstractView, public mitk::ILifecycleAwarePart
{
friend struct CvpSelListener;
// this is needed for all Qt objects that should have a MOC object (everything that derives from QObject)
Q_OBJECT
public:
static const std::string VIEW_ID;
QmitkControlVisualizationPropertiesView();
virtual ~QmitkControlVisualizationPropertiesView();
virtual void CreateQtPartControl(QWidget *parent) override;
/// \brief Creation of the connections of main and control widget
virtual void CreateConnections();
protected slots:
void VisibleOdfsON_S();
void VisibleOdfsON_T();
void VisibleOdfsON_C();
void ShowMaxNumberChanged();
void NormalizationDropdownChanged(int);
void ScalingFactorChanged(double);
void AdditionalScaling(int);
void OnThickSlicesModeSelected( QAction* action );
void OnTSNumChanged(int num);
void ResetColoring();
void PlanarFigureFocus();
void Fiber2DfadingEFX();
void FiberSlicingThickness2D();
void FiberSlicingUpdateLabel(int);
void LineWidthChanged();
void TubeRadiusChanged();
void RibbonWidthChanged();
void SetInteractor();
void Toggle3DClipping(bool enabled=true);
void FlipPeaks();
void Welcome();
void OnSliceChanged();
void SetColor();
void Toggle3DPeaks();
/// \brief Slot function for switching colourisation mode of glyphs.
void OnColourisationModeChanged();
protected:
virtual void SetFocus() override;
virtual void Activated() override;
virtual void Deactivated() override;
virtual void Visible() override;
virtual void Hidden() override;
virtual void NodeRemoved(const mitk::DataNode* node) override;
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
virtual void NodeAdded(const mitk::DataNode *node) override;
void SetCustomColor(const itk::EventObject& /*e*/);
bool IsPlaneRotated();
void SliceRotation(const itk::EventObject&);
void Set3DClippingPlane(bool disable, mitk::DataNode *node, std::string plane);
void SetTs(int m_CurrentThickSlicesMode, int num, std::string render_window);
Ui::QmitkControlVisualizationPropertiesViewControls* m_Controls;
QScopedPointer<berry::ISelectionListener> m_SelListener;
berry::IStructuredSelection::ConstPointer m_CurrentSelection;
mitk::DataNode::Pointer m_NodeUsedForOdfVisualization;
QIcon* m_IconTexOFF;
QIcon* m_IconTexON;
QIcon* m_IconGlyOFF_T;
QIcon* m_IconGlyON_T;
QIcon* m_IconGlyOFF_C;
QIcon* m_IconGlyON_C;
QIcon* m_IconGlyOFF_S;
QIcon* m_IconGlyON_S;
bool m_TexIsOn;
bool m_GlyIsOn_T;
bool m_GlyIsOn_C;
bool m_GlyIsOn_S;
int m_CurrentThickSlicesMode;
int m_CurrentThickSlicesNum;
QLabel* m_TSLabel;
QMenu* m_MyMenu;
// for planarfigure and bundle handling:
mitk::DataNode::Pointer m_SelectedNode;
mitk::DataNode* m_CurrentPickingNode;
unsigned long m_ColorPropertyObserverTag;
unsigned long m_OpacityPropertyObserverTag;
mitk::ColorProperty::Pointer m_Color;
mitk::FloatProperty::Pointer m_Opacity;
QmitkSliceNavigationListener m_SliceChangeListener;
};
#endif // _QMITKControlVisualizationPropertiesView_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDicomTractogramTagEditorView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDicomTractogramTagEditorView.cpp
index 3b9417e..c4d8dba 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDicomTractogramTagEditorView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDicomTractogramTagEditorView.cpp
@@ -1,201 +1,201 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>
#include <berryIStructuredSelection.h>
// Qmitk
#include "QmitkDicomTractogramTagEditorView.h"
#include "QmitkStdMultiWidget.h"
// Qt
#include <QMessageBox>
// MITK
#include <mitkNodePredicateDataType.h>
#include <mitkNodePredicateNot.h>
#include <mitkNodePredicateAnd.h>
#include <mitkNodePredicateProperty.h>
const std::string QmitkDicomTractogramTagEditorView::VIEW_ID = "org.mitk.views.dicomtractogramtageditor";
const std::string id_DataManager = "org.mitk.views.datamanager";
using namespace berry;
QmitkDicomTractogramTagEditorView::QmitkDicomTractogramTagEditorView()
: m_Controls(nullptr)
{
m_TagList = {"DICOM.patient_id",
"DICOM.patient_name",
"DICOM.study_instance_uid",
"DICOM.series_instance_uid",
"DICOM.sop_instance_uid",
"DICOM.frame_of_reference_uid",
"DICOM.algo_code.value",
"DICOM.algo_code.meaning",
"DICOM.model_code.value",
"DICOM.model_code.meaning",
"DICOM.anatomy.value",
"DICOM.anatomy.meaning"};
m_ImageTagList = {"DICOM.patient_id",
"DICOM.patient_name",
"DICOM.study_instance_uid",
"DICOM.series_instance_uid",
"DICOM.sop_instance_uid",
"DICOM.frame_of_reference_uid"};
}
// Destructor
QmitkDicomTractogramTagEditorView::~QmitkDicomTractogramTagEditorView()
{
}
void QmitkDicomTractogramTagEditorView::CreateQtPartControl( QWidget *parent )
{
if ( !m_Controls )
{
// create GUI widgets from the Qt Designer's .ui file
m_Controls = new Ui::QmitkDicomTractogramTagEditorViewControls;
m_Controls->setupUi( parent );
m_Controls->m_TractogramBox->SetDataStorage(this->GetDataStorage());
mitk::TNodePredicateDataType<mitk::FiberBundle>::Pointer isFibPredicate = mitk::TNodePredicateDataType<mitk::FiberBundle>::New();
m_Controls->m_TractogramBox->SetPredicate( isFibPredicate );
m_Controls->m_TractogramBox->SetZeroEntryText("--");
m_Controls->m_TagTable->setColumnCount(2);
m_Controls->m_TagTable->setRowCount(m_TagList.size());
m_Controls->m_TagTable->verticalHeader()->setVisible(false);
m_Controls->m_TagTable->setSelectionMode(QAbstractItemView::SingleSelection);
QStringList tableHeader;
tableHeader <<"Tag"<<"Value";
m_Controls->m_TagTable->setHorizontalHeaderLabels(tableHeader);
m_Controls->m_TagTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
m_Controls->m_CopyPropsButton->setEnabled(false);
connect( (QObject*)(m_Controls->m_TractogramBox), SIGNAL(OnSelectionChanged(const mitk::DataNode*)), this, SLOT(OnTractSelectionChanged()) );
connect( (QObject*)(m_Controls->m_TagTable), SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(OnItemChanged(QTableWidgetItem*)) );
connect( m_Controls->m_CopyPropsButton, SIGNAL(clicked()), this, SLOT(CopyProperties()));
UpdateGui();
}
}
void QmitkDicomTractogramTagEditorView::CopyProperties()
{
if (m_Controls->m_TractogramBox->GetSelectedNode()==nullptr)
return;
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(m_Controls->m_TractogramBox->GetSelectedNode()->GetData());
if (fib.IsNull())
return;
if (m_Image.IsNull())
return;
mitk::PropertyList* source_p_list = m_Image->GetPropertyList();
mitk::PropertyList* target_p_list = fib->GetPropertyList();
for (std::string tag : m_ImageTagList)
{
std::string val = "-";
source_p_list->GetStringProperty(tag.c_str(), val);
target_p_list->SetStringProperty(tag.c_str(), val.c_str());
}
UpdateGui();
}
void QmitkDicomTractogramTagEditorView::OnItemChanged(QTableWidgetItem* item)
{
if (m_Controls->m_TractogramBox->GetSelectedNode()==nullptr)
{
UpdateGui();
return;
}
int col = item->column();
if (col==1)
{
std::string tag = m_TagList.at(item->row());
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(m_Controls->m_TractogramBox->GetSelectedNode()->GetData());
mitk::PropertyList* p_list = fib->GetPropertyList();
p_list->SetStringProperty(tag.c_str(), item->text().toStdString().c_str());
}
UpdateGui();
}
void QmitkDicomTractogramTagEditorView::OnTractSelectionChanged()
{
UpdateGui();
}
void QmitkDicomTractogramTagEditorView::UpdateGui()
{
m_Controls->m_CopyPropsButton->setEnabled(false);
m_Controls->m_TagTable->blockSignals(true);
if (m_Controls->m_TractogramBox->GetSelectedNode()==nullptr)
{
int row = 0;
for (std::string tag : m_TagList)
{
m_Controls->m_TagTable->setItem(row, 0, new QTableWidgetItem(tag.c_str()));
m_Controls->m_TagTable->setItem(row, 1, new QTableWidgetItem("-"));
++row;
}
m_Controls->m_TagTable->blockSignals(false);
return;
}
mitk::FiberBundle::Pointer fib = dynamic_cast<mitk::FiberBundle*>(m_Controls->m_TractogramBox->GetSelectedNode()->GetData());
mitk::PropertyList* p_list = fib->GetPropertyList();
int row = 0;
for (std::string tag : m_TagList)
{
std::string val = "-";
p_list->GetStringProperty(tag.c_str(), val);
m_Controls->m_TagTable->setItem(row, 0, new QTableWidgetItem(tag.c_str()));
m_Controls->m_TagTable->setItem(row, 1, new QTableWidgetItem(val.c_str()));
++row;
}
if (m_Image.IsNotNull())
m_Controls->m_CopyPropsButton->setEnabled(true);
m_Controls->m_TagTable->blockSignals(false);
}
void QmitkDicomTractogramTagEditorView::OnSelectionChanged( berry::IWorkbenchPart::Pointer , const QList<mitk::DataNode::Pointer>& nodes)
{
m_Image = nullptr;
for (auto node : nodes)
{
mitk::Image::Pointer img = dynamic_cast<mitk::Image*>(node->GetData());
if (img.IsNotNull())
{
m_Image = img;
}
}
UpdateGui();
}
void QmitkDicomTractogramTagEditorView::SetFocus()
{
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDicomTractogramTagEditorView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDicomTractogramTagEditorView.h
index f84cc05..786c811 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDicomTractogramTagEditorView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDicomTractogramTagEditorView.h
@@ -1,75 +1,75 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkDicomTractogramTagEditorView_h
#define QmitkDicomTractogramTagEditorView_h
#include <QmitkAbstractView.h>
#include "ui_QmitkDicomTractogramTagEditorViewControls.h"
#include <mitkFiberBundle.h>
/*!
\brief View for tensor based deterministic streamline fiber tracking.
*/
class QmitkDicomTractogramTagEditorView : public QmitkAbstractView
{
// 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;
QmitkDicomTractogramTagEditorView();
virtual ~QmitkDicomTractogramTagEditorView();
virtual void CreateQtPartControl(QWidget *parent) override;
///
/// Sets the focus to an internal widget.
///
virtual void SetFocus() override;
protected slots:
void OnTractSelectionChanged();
void CopyProperties();
void OnItemChanged(QTableWidgetItem * item);
protected:
void UpdateGui();
/// \brief called by QmitkAbstractView when DataManager's selection has changed
virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList<mitk::DataNode::Pointer>& nodes) override;
Ui::QmitkDicomTractogramTagEditorViewControls* m_Controls;
std::vector< std::string > m_TagList;
std::vector< std::string > m_ImageTagList;
mitk::Image::Pointer m_Image;
protected slots:
private:
};
#endif // _QMITKFIBERTRACKINGVIEW_H_INCLUDED
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDiffusionDicomImportView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDiffusionDicomImportView.cpp
index 235f725..62f9652 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDiffusionDicomImportView.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDiffusionDicomImportView.cpp
@@ -1,600 +1,600 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkDiffusionDicomImportView.h"
// qt includes
#include <QFileDialog>
// itk includes
#include "itkTimeProbesCollectorBase.h"
#include "itkGDCMSeriesFileNames.h"
#include "itksys/SystemTools.hxx"
// mitk includes
#include "mitkProgressBar.h"
#include "mitkStatusBar.h"
#include "mitkProperties.h"
#include "mitkRenderingManager.h"
#include "mitkMemoryUtilities.h"
#include "mitkIOUtil.h"
// diffusion module includes
#include "mitkDicomDiffusionImageHeaderReader.h"
#include "mitkDicomDiffusionImageReader.h"
#include "mitkImage.h"
#include <mitkDiffusionPropertyHelper.h>
#include "mitkDiffusionDICOMFileReader.h"
#include "mitkDICOMTagBasedSorter.h"
#include "mitkDICOMSortByTag.h"
#include "mitkSortByImagePositionPatient.h"
#include "gdcmDirectory.h"
#include "gdcmScanner.h"
#include "gdcmSorter.h"
#include "gdcmIPPSorter.h"
#include "gdcmAttribute.h"
#include "gdcmVersion.h"
#include <itksys/SystemTools.hxx>
#include <itksys/Directory.hxx>
#include <QMessageBox>
#include <QTreeView>
#include <mitkStringProperty.h>
const std::string QmitkDiffusionDicomImport::VIEW_ID = "org.mitk.views.diffusiondicomimport";
QmitkDiffusionDicomImport::QmitkDiffusionDicomImport(QObject* /*parent*/, const char* /*name*/)
: m_Controls(nullptr)
, m_OutputFolderName("")
, m_OutputFolderNameSet(false)
{
}
QmitkDiffusionDicomImport::~QmitkDiffusionDicomImport()
{}
void QmitkDiffusionDicomImport::CreateQtPartControl(QWidget *parent)
{
m_Parent = parent;
if (m_Controls == nullptr)
{
m_Controls = new Ui::QmitkDiffusionDicomImportControls;
m_Controls->setupUi(parent);
this->CreateConnections();
m_Controls->m_DicomLoadRecursiveCheckbox->setChecked(false);
m_Controls->m_DicomLoadAverageDuplicatesCheckbox->setChecked(false);
m_Controls->m_DicomLoadRecursiveCheckbox->setVisible(true);
m_Controls->m_OverrideOptionCheckbox->setVisible(false);
m_Controls->m_SubdirPrefixLineEdit->setVisible(false);
m_Controls->m_SetPrefixButton->setVisible(false);
m_Controls->m_ResetPrefixButton->setVisible(false);
AverageClicked();
}
}
void QmitkDiffusionDicomImport::CreateConnections()
{
if ( m_Controls )
{
connect( m_Controls->m_AddFoldersButton, SIGNAL(clicked()), this, SLOT(DicomLoadAddFolderNames()) );
connect( m_Controls->m_DeleteFoldersButton, SIGNAL(clicked()), this, SLOT(DicomLoadDeleteFolderNames()) );
//connect( m_Controls->m_DicomLoadStartLoadButton, SIGNAL(clicked()), this, SLOT(DicomLoadStartLoad()) );
connect( m_Controls->m_DicomLoadStartLoadButton, SIGNAL(clicked()), this, SLOT(NewDicomLoadStartLoad()) );
connect( m_Controls->m_DicomLoadAverageDuplicatesCheckbox, SIGNAL(clicked()), this, SLOT(AverageClicked()) );
connect( m_Controls->m_OutputSetButton, SIGNAL(clicked()), this, SLOT(OutputSet()) );
connect( m_Controls->m_OutputClearButton, SIGNAL(clicked()), this, SLOT(OutputClear()) );
connect( m_Controls->m_Remove, SIGNAL(clicked()), this, SLOT(Remove()) );
connect( m_Controls->m_SetPrefixButton, SIGNAL(clicked()), this, SLOT(SetPrefixButtonPushed()));
connect( m_Controls->m_ResetPrefixButton, SIGNAL(clicked()), this, SLOT(ResetPrefixButtonPushed()));
connect( m_Controls->m_DicomLoadRecursiveCheckbox, SIGNAL(clicked()), this, SLOT(RecursiveSettingsChanged()) );
}
}
void QmitkDiffusionDicomImport::SetFocus()
{
m_Controls->textBrowser->setFocus();
}
void QmitkDiffusionDicomImport::RecursiveSettingsChanged()
{
m_Controls->m_SubdirPrefixLineEdit->setVisible( m_Controls->m_DicomLoadRecursiveCheckbox->isChecked() );
m_Controls->m_SetPrefixButton->setVisible( m_Controls->m_DicomLoadRecursiveCheckbox->isChecked() );
m_Controls->m_SubdirPrefixLineEdit->clear();
this->m_Controls->m_SubdirPrefixLineEdit->setEnabled(true);
}
void QmitkDiffusionDicomImport::SetPrefixButtonPushed()
{
m_Prefix = this->m_Controls->m_SubdirPrefixLineEdit->text().toStdString();
if( !this->m_Controls->m_ResetPrefixButton->isVisible() )
this->m_Controls->m_ResetPrefixButton->setVisible(true);
this->m_Controls->m_SubdirPrefixLineEdit->setEnabled(false);
this->m_Controls->m_ResetPrefixButton->setEnabled(true);
this->m_Controls->m_SetPrefixButton->setEnabled(false);
}
void QmitkDiffusionDicomImport::ResetPrefixButtonPushed()
{
m_Controls->m_SubdirPrefixLineEdit->clear();
this->m_Controls->m_SubdirPrefixLineEdit->setEnabled(true);
this->m_Controls->m_ResetPrefixButton->setEnabled(false);
this->m_Controls->m_SetPrefixButton->setEnabled(true);
}
void QmitkDiffusionDicomImport::Remove()
{
int i = m_Controls->listWidget->currentRow();
m_Controls->listWidget->takeItem(i);
}
void QmitkDiffusionDicomImport::OutputSet()
{
// SELECT FOLDER DIALOG
QFileDialog* w = new QFileDialog( m_Parent, QString("Select folders containing DWI data") );
w->setFileMode( QFileDialog::Directory );
// RETRIEVE SELECTION
if ( w->exec() != QDialog::Accepted )
return;
m_OutputFolderName = w->selectedFiles()[0];
m_OutputFolderNameSet = true;
m_Controls->m_OutputLabel->setText(m_OutputFolderName);
// show file override option checkbox
m_Controls->m_OverrideOptionCheckbox->setVisible(true);
}
void QmitkDiffusionDicomImport::OutputClear()
{
m_OutputFolderName = "";
m_OutputFolderNameSet = false;
m_Controls->m_OutputLabel->setText("... optional out-folder ...");
// hide file override option checkbox - no output specified
m_Controls->m_OverrideOptionCheckbox->setVisible(false);
}
void QmitkDiffusionDicomImport::AverageClicked()
{
m_Controls->m_Blur->setEnabled(m_Controls->m_DicomLoadAverageDuplicatesCheckbox->isChecked());
}
void QmitkDiffusionDicomImport::DicomLoadDeleteFolderNames()
{
m_Controls->listWidget->clear();
}
void QmitkDiffusionDicomImport::DicomLoadAddFolderNames()
{
// SELECT FOLDER DIALOG
QFileDialog w( m_Parent, QString("Select folders containing DWI data") );
w.setFileMode( QFileDialog::DirectoryOnly );
w.setOption(QFileDialog::DontUseNativeDialog,true);
QListView *l = w.findChild<QListView*>("listView");
if (l) {
l->setSelectionMode(QAbstractItemView::MultiSelection);
}
QTreeView *t = w.findChild<QTreeView*>();
if (t) {
t->setSelectionMode(QAbstractItemView::MultiSelection);
}
// RETRIEVE SELECTION
if ( w.exec() != QDialog::Accepted )
return;
m_Controls->listWidget->addItems(w.selectedFiles());
}
bool SortBySeriesUID(gdcm::DataSet const & ds1, gdcm::DataSet const & ds2 )
{
gdcm::Attribute<0x0020,0x000e> at1;
at1.Set( ds1 );
gdcm::Attribute<0x0020,0x000e> at2;
at2.Set( ds2 );
return at1 < at2;
}
bool SortByAcquisitionNumber(gdcm::DataSet const & ds1, gdcm::DataSet const & ds2 )
{
gdcm::Attribute<0x0020,0x0012> at1;
at1.Set( ds1 );
gdcm::Attribute<0x0020,0x0012> at2;
at2.Set( ds2 );
return at1 < at2;
}
bool SortBySeqName(gdcm::DataSet const & ds1, gdcm::DataSet const & ds2 )
{
gdcm::Attribute<0x0018, 0x0024> at1;
at1.Set( ds1 );
gdcm::Attribute<0x0018, 0x0024> at2;
at2.Set( ds2 );
std::string str1 = at1.GetValue().Trim();
std::string str2 = at2.GetValue().Trim();
return std::lexicographical_compare(str1.begin(), str1.end(),
str2.begin(), str2.end() );
}
void QmitkDiffusionDicomImport::Status(QString status)
{
mitk::StatusBar::GetInstance()->DisplayText(status.toLatin1());
MITK_INFO << status.toStdString().c_str();
}
void QmitkDiffusionDicomImport::Status(std::string status)
{
mitk::StatusBar::GetInstance()->DisplayText(status.c_str());
MITK_INFO << status.c_str();
}
void QmitkDiffusionDicomImport::Status(const char* status)
{
mitk::StatusBar::GetInstance()->DisplayText(status);
MITK_INFO << status;
}
void QmitkDiffusionDicomImport::Error(QString status)
{
mitk::StatusBar::GetInstance()->DisplayErrorText(status.toLatin1());
MITK_ERROR << status.toStdString().c_str();
}
void QmitkDiffusionDicomImport::Error(std::string status)
{
mitk::StatusBar::GetInstance()->DisplayErrorText(status.c_str());
MITK_ERROR << status.c_str();
}
void QmitkDiffusionDicomImport::Error(const char* status)
{
mitk::StatusBar::GetInstance()->DisplayErrorText(status);
MITK_ERROR << status;
}
void QmitkDiffusionDicomImport::PrintMemoryUsage()
{
size_t processSize = mitk::MemoryUtilities::GetProcessMemoryUsage();
size_t totalSize = mitk::MemoryUtilities::GetTotalSizeOfPhysicalRam();
float percentage = ( (float) processSize / (float) totalSize ) * 100.0;
MITK_INFO << "Current memory usage: " << GetMemoryDescription( processSize, percentage );
}
std::string QmitkDiffusionDicomImport::FormatMemorySize( size_t size )
{
double val = size;
std::string descriptor("B");
if ( val >= 1000.0 )
{
val /= 1024.0;
descriptor = "KB";
}
if ( val >= 1000.0 )
{
val /= 1024.0;
descriptor = "MB";
}
if ( val >= 1000.0 )
{
val /= 1024.0;
descriptor = "GB";
}
std::ostringstream str;
str << std::fixed << std::setprecision(2) << val << " " << descriptor;
return str.str();
}
std::string QmitkDiffusionDicomImport::FormatPercentage( double val )
{
std::ostringstream str;
str << std::fixed << std::setprecision(2) << val << " " << "%";
return str.str();
}
std::string QmitkDiffusionDicomImport::GetMemoryDescription( size_t processSize, float percentage )
{
std::ostringstream str;
str << FormatMemorySize(processSize) << " (" << FormatPercentage( percentage ) <<")" ;
return str.str();
}
void QmitkDiffusionDicomImport::NewDicomLoadStartLoad()
{
itk::TimeProbesCollectorBase clock;
bool imageSuccessfullySaved = true;
bool has_prefix = true;
try
{
const std::string& locale = "C";
const std::string& currLocale = setlocale( LC_ALL, nullptr );
if ( locale.compare(currLocale)!=0 )
{
try
{
MITK_INFO << " ** Changing locale from " << setlocale(LC_ALL, nullptr) << " to '" << locale << "'";
setlocale(LC_ALL, locale.c_str());
}
catch(...)
{
MITK_INFO << "Could not set locale " << locale;
}
}
int nrFolders = m_Controls->listWidget->count();
if(!nrFolders)
{
Error(QString("No input folders were selected. ABORTING."));
return;
}
Status(QString("GDCM %1 used for DICOM parsing and sorting!").arg(gdcm::Version::GetVersion()));
PrintMemoryUsage();
QString status;
mitk::DataNode::Pointer node;
mitk::ProgressBar::GetInstance()->AddStepsToDo(2*nrFolders);
gdcm::Directory::FilenamesType complete_list;
while(m_Controls->listWidget->count())
{
// RETREIVE FOLDERNAME
QListWidgetItem * item = m_Controls->listWidget->takeItem(0);
QString folderName = item->text();
if( this->m_Controls->m_DicomLoadRecursiveCheckbox->isChecked() )
{
std::string subdir_prefix = "";
if( has_prefix )
{
subdir_prefix = this->m_Prefix;
}
itksys::Directory rootdir;
rootdir.Load( folderName.toStdString().c_str() );
for( unsigned int idx=0; idx<rootdir.GetNumberOfFiles(); idx++)
{
std::string current_path = rootdir.GetFile(idx);
std::string directory_path = std::string(rootdir.GetPath()) + std::string("/") + current_path;
MITK_INFO("dicom.loader.inputrootdir.test") << "ProbePath: " << current_path;
MITK_INFO("dicom.loader.inputrootdir.test") << "IsDirectory: " << itksys::SystemTools::FileIsDirectory( itksys::SystemTools::ConvertToOutputPath( directory_path.c_str() ).c_str() )
<< " StartsWith: " << itksys::SystemTools::StringStartsWith( current_path.c_str(), subdir_prefix.c_str() );
// test for prefix
if( itksys::SystemTools::FileIsDirectory( itksys::SystemTools::ConvertToOutputPath( directory_path.c_str() ).c_str() )
&& itksys::SystemTools::StringStartsWith( current_path.c_str(), subdir_prefix.c_str() )
)
{
gdcm::Directory d;
d.Load( itksys::SystemTools::ConvertToOutputPath( directory_path.c_str() ) , false);
MITK_INFO("dicom.load.subdir.attempt") << "In directory " << itksys::SystemTools::ConvertToOutputPath( directory_path.c_str() );
const gdcm::Directory::FilenamesType &l1 = d.GetFilenames();
const unsigned int ntotalfiles = l1.size();
Status(QString(" ... found %1 different files").arg(ntotalfiles));
for( unsigned int i=0; i< ntotalfiles; i++)
{
complete_list.push_back( l1.at(i) );
}
}
}
}
else
{
gdcm::Directory d;
d.Load( folderName.toStdString().c_str(), this->m_Controls->m_DicomLoadRecursiveCheckbox->isChecked() ); // recursive !
const gdcm::Directory::FilenamesType &l1 = d.GetFilenames();
const unsigned int ntotalfiles = l1.size();
Status(QString(" ... found %1 different files").arg(ntotalfiles));
for( unsigned int i=0; i< ntotalfiles; i++)
{
complete_list.push_back( l1.at(i) );
}
}
}
{
mitk::DiffusionDICOMFileReader::Pointer gdcmReader = mitk::DiffusionDICOMFileReader::New();
mitk::DICOMTagBasedSorter::Pointer tagSorter = mitk::DICOMTagBasedSorter::New();
// Use tags as in Qmitk
// all the things that split by tag in DicomSeriesReader
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0010) ); // Number of Rows
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0011) ); // Number of Columns
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0030) ); // Pixel Spacing
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0018, 0x1164) ); // Imager Pixel Spacing
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0020, 0x0037) ); // Image Orientation (Patient) // TODO add tolerance parameter (l. 1572 of original code)
// TODO handle as real vectors! cluster with configurable errors!
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0020, 0x000e) ); // Series Instance UID
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0018, 0x0050) ); // Slice Thickness
tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0028, 0x0008) ); // Number of Frames
//tagSorter->AddDistinguishingTag( mitk::DICOMTag(0x0020, 0x0052) ); // Frame of Reference UID
// gdcmReader->AddSortingElement( tagSorter );
//mitk::DICOMFileReaderTestHelper::TestOutputsContainInputs( gdcmReader );
mitk::DICOMSortCriterion::ConstPointer sorting =
mitk::SortByImagePositionPatient::New( // Image Position (Patient)
//mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0020, 0x0013), // instance number
mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0020, 0x0012), // aqcuisition number
mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0008, 0x0032), // aqcuisition time
mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0018, 0x1060), // trigger time
mitk::DICOMSortByTag::New( mitk::DICOMTag(0x0008, 0x0018) // SOP instance UID (last resort, not really meaningful but decides clearly)
).GetPointer()
).GetPointer()
).GetPointer()
).GetPointer()
// ).GetPointer()
).GetPointer();
tagSorter->SetSortCriterion( sorting );
// mosaic
gdcmReader->SetResolveMosaic( this->m_Controls->m_SplitMosaicCheckBox->isChecked() );
gdcmReader->AddSortingElement( tagSorter );
gdcmReader->SetInputFiles( complete_list );
try
{
gdcmReader->AnalyzeInputFiles();
}
catch( const itk::ExceptionObject &e)
{
MITK_ERROR << "Failed to analyze data. " << e.what();
}
catch( const std::exception &se)
{
MITK_ERROR << "Std Exception " << se.what();
}
gdcmReader->LoadImages();
for( unsigned int o = 0; o < gdcmReader->GetNumberOfOutputs(); o++ )
{
mitk::Image::Pointer loaded_image = gdcmReader->GetOutput(o).GetMitkImage();
std::string outname;
if (gdcmReader->GetSeriesName(o)!="-")
outname = gdcmReader->GetSeriesName(o);
else if (gdcmReader->GetStudyName(o)!="-")
outname = gdcmReader->GetStudyName(o);
else
loaded_image->GetPropertyList()->GetStringProperty("diffusion.dicom.importname", outname );
std::string val = "-";
if (gdcmReader->patient_ids().size()>o)
{
val = gdcmReader->patient_ids().at(o);
loaded_image->GetPropertyList()->SetStringProperty("DICOM.patient_id",val.c_str());
}
if (gdcmReader->patient_names().size()>o)
{
val = gdcmReader->patient_names().at(o);
loaded_image->GetPropertyList()->SetStringProperty("DICOM.patient_name",val.c_str());
}
if (gdcmReader->study_instance_uids().size()>o)
{
val = gdcmReader->study_instance_uids().at(o);
loaded_image->GetPropertyList()->SetStringProperty("DICOM.study_instance_uid",val.c_str());
}
if (gdcmReader->series_instance_uids().size()>o)
{
val = gdcmReader->series_instance_uids().at(o);
loaded_image->GetPropertyList()->SetStringProperty("DICOM.series_instance_uid",val.c_str());
}
if (gdcmReader->sop_instance_uids().size()>o)
{
val = gdcmReader->sop_instance_uids().at(o);
loaded_image->GetPropertyList()->SetStringProperty("DICOM.sop_instance_uid",val.c_str());
}
if (gdcmReader->frame_of_reference_uids().size()>o)
{
val = gdcmReader->frame_of_reference_uids().at(o);
loaded_image->GetPropertyList()->SetStringProperty("DICOM.frame_of_reference_uid",val.c_str());
}
node = mitk::DataNode::New();
node->SetData( loaded_image );
node->SetName( outname.c_str() );
GetDataStorage()->Add(node);
}
}
Status("Timing information");
clock.Report();
if(!m_OutputFolderNameSet && node.IsNotNull())
{
mitk::BaseData::Pointer basedata = node->GetData();
if (basedata.IsNotNull())
{
mitk::RenderingManager::GetInstance()->InitializeViews(
basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true );
}
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
try
{
MITK_INFO << " ** Changing locale back from " << setlocale(LC_ALL, nullptr) << " to '" << currLocale << "'";
setlocale(LC_ALL, currLocale.c_str());
}
catch(...)
{
MITK_INFO << "Could not reset locale " << currLocale;
}
}
catch (itk::ExceptionObject &ex)
{
Error(QString("%1\n%2\n%3\n%4\n%5\n%6").arg(ex.GetNameOfClass()).arg(ex.GetFile()).arg(ex.GetLine()).arg(ex.GetLocation()).arg(ex.what()).arg(ex.GetDescription()));
return ;
}
if (!imageSuccessfullySaved)
QMessageBox::warning(nullptr,"WARNING","One or more files could not be saved! The according files where moved to the datastorage.");
Status(QString("Finished import with memory:"));
PrintMemoryUsage();
}
void QmitkDiffusionDicomImport::SetDwiNodeProperties(mitk::DataNode::Pointer node, std::string name)
{
node->SetProperty( "IsDWIRawVolume", mitk::BoolProperty::New( true ) );
// set foldername as string property
mitk::StringProperty::Pointer nameProp = mitk::StringProperty::New( name );
node->SetProperty( "name", nameProp );
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDiffusionDicomImportView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDiffusionDicomImportView.h
index 6a1143c..b653ba7 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDiffusionDicomImportView.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkDiffusionDicomImportView.h
@@ -1,112 +1,112 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QmitkDiffusionDicomImportView_H__INCLUDED
#define QmitkDiffusionDicomImportView_H__INCLUDED
#include <QmitkAbstractView.h>
#include "ui_QmitkDiffusionDicomImportViewControls.h"
/*!
\brief QmitkDiffusionDicomImport
*/
class QmitkDiffusionDicomImport : public QmitkAbstractView
{
Q_OBJECT
public:
static const std::string VIEW_ID;
/*!
\ Convenient typedefs
*/
typedef mitk::DataStorage::SetOfObjects ConstVector;
typedef ConstVector::ConstPointer ConstVectorPointer;
typedef ConstVector::ConstIterator ConstVectorIterator;
/*!
\brief default constructor
*/
QmitkDiffusionDicomImport(QObject *parent=0, const char *name=0);
/*!
\brief default destructor
*/
virtual ~QmitkDiffusionDicomImport();
/*!
\brief method for creating the widget containing the application controls, like sliders, buttons etc.
*/
virtual void CreateQtPartControl(QWidget *parent) override;
/*!
\brief method for creating the connections of main and control widget
*/
virtual void CreateConnections();
///
/// Sets the focus to an internal widget.
///
virtual void SetFocus() override;
void SetDwiNodeProperties(mitk::DataNode::Pointer node, std::string name);
protected slots:
void DicomLoadAddFolderNames();
void DicomLoadDeleteFolderNames();
void NewDicomLoadStartLoad() ;
void AverageClicked();
void OutputSet();
void OutputClear();
void Remove();
void RecursiveSettingsChanged();
void SetPrefixButtonPushed();
void ResetPrefixButtonPushed();
protected:
void Status(QString status);
void Status(std::string status);
void Status(const char* status);
void Error(QString status);
void Error(std::string status);
void Error(const char* status);
void PrintMemoryUsage();
std::string FormatMemorySize( size_t size );
std::string FormatPercentage( double val );
std::string GetMemoryDescription( size_t processSize, float percentage );
/*!
* controls containing sliders for scrolling through the slices
*/
Ui::QmitkDiffusionDicomImportControls *m_Controls;
QWidget *m_Parent;
QString m_OutputFolderName;
bool m_OutputFolderNameSet;
std::string m_Prefix;
};
#endif // !defined(QmitkDiffusionDicomImport_H__INCLUDED)
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/deprecated/QmitkDiffusionTensorEstimation.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/deprecated/QmitkDiffusionTensorEstimation.cpp
index c388b4a..40417b5 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/deprecated/QmitkDiffusionTensorEstimation.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/deprecated/QmitkDiffusionTensorEstimation.cpp
@@ -1,2493 +1,2493 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "itkTimeProbe.h"
#include "QmitkDiffusionTensorEstimation.h"
#include "QmitkDiffusionTensorEstimationControls.h"
#include <qaction.h>
#include "QmitkDataTreeComboBox.h"
#include "QmitkDataTreeListView.h"
#include "QmitkDiffusionTensorIcon.h"
#include <qfiledialog.h>
#include "QmitkPropertyViewFactory.h"
#include <qobjectlist.h>
#include <qlistbox.h>
#include <qpushbutton.h>
#include <qprogressbar.h>
#include <qspinbox.h>
#include <qlineedit.h>
#include <qcheckbox.h>
// properties
#include "mitkStringProperty.h"
#include "mitkProperties.h"
#include "mitkMaterialProperty.h"
#include "mitkLevelWindowProperty.h"
#include "mitkVtkRepresentationProperty.h"
#include "mitkVtkInterpolationProperty.h"
#include "mitkVtkScalarModeProperty.h"
#include "mitkLookupTableProperty.h"
#include "mitkLookupTable.h"
#include "mitkTransferFunctionProperty.h"
#include "mitkGridRepresentationProperty.h"
#include "mitkGridVolumeMapperProperty.h"
#include "mitkVtkResliceInterpolationProperty.h"
#include "mitkVectorImageMapper2D.h"
#include "mitkOdfVtkMapper2D.h"
#include "itkOrientedImage.h"
#include "itkVectorImage.h"
#include "itkImageSeriesReader.h"
#include "itkImageFileWriter.h"
#include "itkExceptionObject.h"
#include "itkDiffusionTensor3DReconstructionImageFilter.h"
#include "itkDiffusionTensor3D.h"
#include "itkTensorFractionalAnisotropyImageFilter.h"
#include "itkTensorRelativeAnisotropyImageFilter.h"
#include "itkGDCMSeriesFileNames.h"
#include "itkImageRegionConstIterator.h"
#include "itkRescaleIntensityImageFilter.h"
#include "itkDiffusionQballReconstructionImageFilter.h"
#include "itkAnalyticalDiffusionQballReconstructionImageFilter.h"
#include "itkPointShell.h"
#include "itkRGBPixel.h"
#include "itkOrientationDistributionFunction.h"
#include "itkDiffusionOdfPrincipleDirectionsImageFilter.h"
#include "itkDiffusionOdfGeneralizedFaImageFilter.h"
#include "itkShiftScaleImageFilter.h"
#include "itkDiffusionOdfPrepareVisualizationImageFilter.h"
#include "itkDiffusionTensorPrincipleDirectionImageFilter.h"
#include "itkDiffusionOdfSphericalDeconvolutionImageFilter.h"
#include "itkVectorImagesAngularErrorImageFilter.h"
#include "mitkDicomDiffusionVolumeHeaderReader.h"
#include "mitkGroupDiffusionHeadersFilter.h"
#include "mitkDicomDiffusionVolumesReader.h"
#include "mitkNrrdDiffusionVolumesWriter.h"
#include "mitkNrrdDiffusionVolumesReader.h"
#include "mitkDiffusionVolumes.h"
#include "mitkDataTreeFilterFunctions.h"
#include "mitkProgressBar.h"
#include "mitkStatusBar.h"
#include "mitkTeemDiffusionTensor3DReconstructionImageFilter.h"
#include "mitkSurface.h"
#include "vtkPolyData.h"
#include "vtkPoints.h"
#include "vtkCellArray.h"
#include "vtkDelaunay2D.h"
#include "vtkCleanPolyData.h"
#include "vtkAppendPolyData.h"
#include "mitkImageCast.h"
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
typedef float TTensorPixelType;
typedef itk::DiffusionTensor3D< TTensorPixelType > TensorPixelType;
typedef itk::Image< TensorPixelType, 3 > TensorImageType;
typedef itk::VectorImage< DiffusionPixelType, 3 > DiffusionImageType;
//CAST_N_VEC(3)
//CAST_N_VEC(42)
//CAST_N_VEC(92)
//CAST_N_VEC(162)
//CAST_N_VEC(252)
//CAST_N_VEC(362)
//CAST_N_VEC(492)
//CAST_N_VEC(642)
//CAST_N_VEC(812)
//CAST_N_VEC(1002)
const int QmitkDiffusionTensorEstimation::odfsize = 252;
const int QmitkDiffusionTensorEstimation::nrconvkernels = 252;
// Compile-time Square Root Computation: ceil(sqrt(N))
template <int Size, int Low = 1, int High = Size>
struct Root;
template <int Size, int Mid>
struct Root<Size,Mid,Mid> {
static const int root = Mid;
};
template <int Size, int Low, int High>
struct Root {
static const int mean = (Low + High)/2;
static const bool down = (mean * mean >= Size);
static const int root = Root<Size,
(down ? Low : mean+1),
(down ? mean : High) >::root;
};
QmitkDiffusionTensorEstimation::QmitkDiffusionTensorEstimation(QObject *parent, const char *name, mitk::DataTreeIteratorBase* it)
: QmitkAbstractView(parent, name, it), m_Controls(nullptr)
{
SetAvailability(true);
m_FilterInitialized = false;
}
QmitkDiffusionTensorEstimation::~QmitkDiffusionTensorEstimation()
{}
QWidget * QmitkDiffusionTensorEstimation::CreateControlWidget(QWidget *parent)
{
if (m_Controls == nullptr)
{
m_Controls = new QmitkDiffusionTensorEstimationControls(parent);
}
m_Controls->m_TensorEstimationTeemErrorImage->setChecked(false);
m_Controls->m_TensorEstimationTeemSigmaEdit->setText("NaN");
m_Controls->m_TensorEstimationTeemEstimationMethodCombo->insertItem("LLS (Linear Least Squares)");
m_Controls->m_TensorEstimationTeemEstimationMethodCombo->insertItem("MLE (Maximum Likelihood)");
m_Controls->m_TensorEstimationTeemEstimationMethodCombo->insertItem("NLS (Nonlinear Least Squares)");
m_Controls->m_TensorEstimationTeemEstimationMethodCombo->insertItem("WLS (Weighted Least Squares)");
m_Controls->m_TensorEstimationTeemNumItsSpin->setValue(1);
m_Controls->m_TensorEstimationTeemConfThresholdEdit->setText("NaN");
m_Controls->m_TensorEstimationTeemFuzzyEdit->setText("0.0");
m_Controls->m_TensorEstimationTeemMinValEdit->setText("1.0");
m_Controls->m_OdfReconstructionThreasholdEdit->setText("0.0");
m_Controls->m_OdfStandardAlgorithmsOrderSpinbox->setValue(0);
m_Controls->m_OdfStandardAlgorithmsProbThreshEdit->setText(QString::number(1.0/double(odfsize)));
m_Controls->m_OdfReconstructionNumberThreadsSpinbox->setValue(4);
m_Controls->m_OdfReconstructionMaxLLevelComboBox->insertItem( QString("2") );
m_Controls->m_OdfReconstructionMaxLLevelComboBox->insertItem( QString("4") );
m_Controls->m_OdfReconstructionMaxLLevelComboBox->insertItem( QString("6") );
m_Controls->m_OdfReconstructionMaxLLevelComboBox->insertItem( QString("8") );
m_Controls->m_OdfReconstructionMaxLLevelComboBox->setCurrentItem( 3 );
m_Controls->m_OdfReconstructionNumberThreadsAnalyticalSpinbox->setValue(4);
m_Controls->m_OdfReconstructionThreasholdAnalyticalEdit->setText("0.0");
m_Controls->m_OdfReconstructionLambdaLineEdit->setText("0.006");
m_Controls->m_OdfStandardAlgorithmsNumberThreadsSpinbox->setValue(4);
m_Controls->m_OdfStandardAlgorithmsDeconvNumberThreadsSpinbox->setValue(4);
m_Controls->m_OdfStandardAlgorithmsDeconvolutionThreshEdit->setText("0.1");
m_Controls->m_OdfStandardAlgorithmsDeconvolutionAngResThresholdEdit->setText("15");
m_Controls->m_OdfStandardAlgorithmsGFAParam1->setText("2");
m_Controls->m_OdfStandardAlgorithmsGFAParam2->setText("1");
return m_Controls;
}
void QmitkDiffusionTensorEstimation::CreateConnections()
{
if ( m_Controls )
{
connect( (QObject*)(m_Controls->m_TensorEstimationButton), SIGNAL(clicked()),(QObject*) this, SLOT(TensorEstimationButton()));
connect( (QObject*)(m_Controls->m_OdfReconstructionButton), SIGNAL(clicked()),(QObject*) this, SLOT(OdfReconstructionButton()));
connect( (QObject*)(m_Controls->m_OdfReconstructionAnalyticalButton), SIGNAL(clicked()),(QObject*) this, SLOT(OdfReconstructionAnalyticalButton()));
connect( (QObject*)(m_Controls->m_TensorEstimationTeemEstimateButton), SIGNAL(clicked()),(QObject*) this, SLOT(TensorEstimationTeemEstimateButton()));
connect( (QObject*)(m_Controls->m_TensorVolumesSaveButton), SIGNAL(clicked()),(QObject*) this, SLOT(TensorVolumesSaveButton()));
connect( (QObject*)(m_Controls->m_TensorVolumesLoadButton), SIGNAL(clicked()),(QObject*) this, SLOT(TensorVolumesLoadButton()));
connect( (QObject*)(m_Controls->m_TensorVolumesRemoveButton), SIGNAL(clicked()),(QObject*) this, SLOT(TensorVolumesRemoveButton()));
connect( (QObject*)(m_Controls->m_StandardAlgorithmsFAButton), SIGNAL(clicked()),(QObject*) this, SLOT(StandardAlgorithmsFAButton()));
connect( (QObject*)(m_Controls->m_StandardAlgorithmsRAButton), SIGNAL(clicked()),(QObject*) this, SLOT(StandardAlgorithmsRAButton()));
connect( (QObject*)(m_Controls->m_StandardAlgorithmsDirectionButton), SIGNAL(clicked()),(QObject*) this, SLOT(StandardAlgorithmsDirectionButton()));
connect( (QObject*)(m_Controls->m_OdfVolumesSaveButton), SIGNAL(clicked()),(QObject*) this, SLOT(OdfVolumesSaveButton()));
connect( (QObject*)(m_Controls->m_OdfVolumesLoadButton), SIGNAL(clicked()),(QObject*) this, SLOT(OdfVolumesLoadButton()));
connect( (QObject*)(m_Controls->m_OdfVolumesRemoveButton), SIGNAL(clicked()),(QObject*) this, SLOT(OdfVolumesRemoveButton()));
connect( (QObject*)(m_Controls->m_OdfStandardAlgorithmsDirectionButton), SIGNAL(clicked()),(QObject*) this, SLOT(OdfStandardAlgorithmsDirectionButton()));
connect( (QObject*)(m_Controls->m_OdfStandardAlgorithmsDeconvolutionButton), SIGNAL(clicked()),(QObject*) this, SLOT(OdfStandardAlgorithmsDeconvolutionButton()));
connect( (QObject*)(m_Controls->m_OdfStandardAlgorithmsGFAButton), SIGNAL(clicked()),(QObject*) this, SLOT(OdfStandardAlgorithmsGFAButton()));
connect( (QObject*)(m_Controls->m_OdfVolumesVisualizeSelectedButton), SIGNAL(clicked()),(QObject*) this, SLOT(OdfVolumesVisualizeSelectedButton()));
connect( (QObject*)(m_Controls->m_DirectionVolumesSaveButton), SIGNAL(clicked()),(QObject*) this, SLOT(DirectionVolumesSaveButton()));
connect( (QObject*)(m_Controls->m_DirectionVolumesLoadButton), SIGNAL(clicked()),(QObject*) this, SLOT(DirectionVolumesLoadButton()));
connect( (QObject*)(m_Controls->m_DirectionVolumesRemoveButton), SIGNAL(clicked()),(QObject*) this, SLOT(DirectionVolumesRemoveButton()));
connect( (QObject*)(m_Controls->m_DirectionVolumesAngularErrorButton), SIGNAL(clicked()),(QObject*) this, SLOT(DirectionVolumesAngularErrorButton()));
connect( (QObject*)(m_Controls->m_DiffusionVolumesLoadButton), SIGNAL(clicked()),(QObject*) this, SLOT(DiffusionVolumesLoadButton()));
connect( (QObject*)(m_Controls->m_DiffusionVolumeSaveButton), SIGNAL(clicked()),(QObject*) this, SLOT(DiffusionVolumeSaveButton()));
connect( (QObject*)(m_Controls->m_DiffusionVolumesRemoveButton), SIGNAL(clicked()),(QObject*) this, SLOT(DiffusionVolumesRemoveButton()));
connect( (QObject*)(m_Controls->m_TensorEstimationDiffusionVolumesSelectAllButton), SIGNAL(clicked()),(QObject*) this, SLOT(DiffusionVolumesSelectAll()));
}
}
QAction * QmitkDiffusionTensorEstimation::CreateAction(QActionGroup *parent)
{
//action = new QAction( tr( "Brain Atrophy" ), pixmap, tr( "BrainAtrophy" ), 0, parent, "BrainAtrophy" );
QImage icon = qembed_findImage("QmitkDiffusionTensorEstimation");
QPixmap pixmap(icon);
QAction* action;
action = new QAction( tr( "Diffusion Tensor Estimation" ), pixmap, tr( "QmitkDiffusionTensorEstimation menu" ), 0, parent, "QmitkDiffusionTensorEstimation" );
return action;
}
void QmitkDiffusionTensorEstimation::TreeChanged()
{
m_Controls->m_TensorEstimationDiffusionVolumesSelector->Update();
m_Controls->m_TensorVolumesSelector->Update();
m_Controls->m_OdfVolumesSelector->Update();
m_Controls->m_DirectionVolumesSelector->Update();
if(m_DiffusionVolumesDataTreeFilter
&&m_DiffusionVolumesDataTreeFilter->GetItems()->Size() > 0)
{
m_Controls->m_TensorEstimationButton->setEnabled(true);
m_Controls->m_OdfReconstructionButton->setEnabled(true);
m_Controls->m_OdfReconstructionAnalyticalButton->setEnabled(true);
}
else
{
m_Controls->m_OdfReconstructionButton->setEnabled(false);
m_Controls->m_OdfReconstructionAnalyticalButton->setEnabled(false);
m_Controls->m_TensorEstimationButton->setEnabled(false);
}
if(m_TensorVolumesDataTreeFilter
&& m_TensorVolumesDataTreeFilter->GetItems()->Size() > 0)
{
m_Controls->m_TensorVolumesSaveButton->setEnabled(true);
m_Controls->m_TensorVolumesRemoveButton->setEnabled(true);
}
else
{
m_Controls->m_TensorVolumesSaveButton->setEnabled(false);
m_Controls->m_TensorVolumesRemoveButton->setEnabled(false);
}
if(m_OdfVolumesDataTreeFilter
&& m_OdfVolumesDataTreeFilter->GetItems()->Size() > 0)
{
m_Controls->m_OdfVolumesSaveButton->setEnabled(true);
m_Controls->m_OdfVolumesRemoveButton->setEnabled(true);
m_Controls->m_OdfVolumesVisualizeSelectedButton->setEnabled(true);
}
else
{
m_Controls->m_OdfVolumesSaveButton->setEnabled(false);
m_Controls->m_OdfVolumesRemoveButton->setEnabled(false);
m_Controls->m_OdfVolumesVisualizeSelectedButton->setEnabled(false);
}
if(m_DirectionVolumesDataTreeFilter
&& m_DirectionVolumesDataTreeFilter->GetItems()->Size() > 0)
{
m_Controls->m_DirectionVolumesSaveButton->setEnabled(true);
m_Controls->m_DirectionVolumesRemoveButton->setEnabled(true);
}
else
{
m_Controls->m_DirectionVolumesSaveButton->setEnabled(false);
m_Controls->m_DirectionVolumesRemoveButton->setEnabled(false);
}
if(m_DirectionVolumesDataTreeFilter
&& m_DirectionVolumesDataTreeFilter->GetItems()->Size() > 1)
{
m_Controls->m_DirectionVolumesAngularErrorButton->setEnabled(true);
}
else
{
m_Controls->m_DirectionVolumesAngularErrorButton->setEnabled(false);
}
}
void QmitkDiffusionTensorEstimation::Activated()
{
if (m_FilterInitialized)
return;
// diffusion volumes filter
m_DiffusionVolumesDataTreeFilter = mitk::DataTreeFilter::New( GetDataTreeIterator()->GetTree() );
m_DiffusionVolumesDataTreeFilter->SetSelectionMode(mitk::DataTreeFilter::MULTI_SELECT);
m_DiffusionVolumesDataTreeFilter->SetHierarchyHandling(mitk::DataTreeFilter::FLATTEN_HIERARCHY);
m_DiffusionVolumesDataTreeFilter->SetFilter( mitk::IsBaseDataType<mitk::DiffusionVolumes<short> >() ); // show diffusion volumes
mitk::DataTreeFilter::PropertyList visible_props;
visible_props.push_back("name");
m_DiffusionVolumesDataTreeFilter->SetVisibleProperties(visible_props);
mitk::DataTreeFilter::PropertyList property_labels;
property_labels.push_back("Diffusion Volumes");
m_DiffusionVolumesDataTreeFilter->SetPropertiesLabels(property_labels);
m_Controls->m_TensorEstimationDiffusionVolumesSelector->SetDataTree( GetDataTreeIterator()->GetTree() );
m_Controls->m_TensorEstimationDiffusionVolumesSelector->SetFilter( m_DiffusionVolumesDataTreeFilter );
m_Controls->m_TensorEstimationDiffusionVolumesSelector->SetAutoUpdate( false );
m_Controls->m_TensorEstimationDiffusionVolumesSelector->setStretchedColumn(1);
// tensor volumes filter
m_TensorVolumesDataTreeFilter = mitk::DataTreeFilter::New( GetDataTreeIterator()->GetTree() );
m_TensorVolumesDataTreeFilter->SetSelectionMode(mitk::DataTreeFilter::SINGLE_SELECT);
m_TensorVolumesDataTreeFilter->SetHierarchyHandling(mitk::DataTreeFilter::FLATTEN_HIERARCHY);
m_TensorVolumesDataTreeFilter->SetFilter( mitk::IsBaseDataTypeWithBoolProperty<mitk::Image>("IsTensorVolume") ); // show tensor volumes
m_TensorVolumesDataTreeFilter->SetVisibleProperties(visible_props);
mitk::DataTreeFilter::PropertyList tensor_property_labels;
tensor_property_labels.push_back("Tensor Volumes");
m_TensorVolumesDataTreeFilter->SetPropertiesLabels(tensor_property_labels);
m_Controls->m_TensorVolumesSelector->SetDataTree( GetDataTreeIterator()->GetTree() );
m_Controls->m_TensorVolumesSelector->SetFilter( m_TensorVolumesDataTreeFilter );
m_Controls->m_TensorVolumesSelector->SetAutoUpdate( false );
m_Controls->m_TensorVolumesSelector->setStretchedColumn(1);
// Odf volumes filter
m_OdfVolumesDataTreeFilter = mitk::DataTreeFilter::New( GetDataTreeIterator()->GetTree() );
m_OdfVolumesDataTreeFilter->SetSelectionMode(mitk::DataTreeFilter::MULTI_SELECT);
m_OdfVolumesDataTreeFilter->SetHierarchyHandling(mitk::DataTreeFilter::FLATTEN_HIERARCHY);
m_OdfVolumesDataTreeFilter->SetFilter( mitk::IsBaseDataTypeWithBoolProperty<mitk::Image>("IsOdfVolume") );
m_OdfVolumesDataTreeFilter->SetVisibleProperties(visible_props);
mitk::DataTreeFilter::PropertyList Odf_property_labels;
Odf_property_labels.push_back("ODF Volumes");
m_OdfVolumesDataTreeFilter->SetPropertiesLabels(Odf_property_labels);
m_Controls->m_OdfVolumesSelector->SetDataTree( GetDataTreeIterator()->GetTree() );
m_Controls->m_OdfVolumesSelector->SetFilter( m_OdfVolumesDataTreeFilter );
m_Controls->m_OdfVolumesSelector->SetAutoUpdate( false );
m_Controls->m_OdfVolumesSelector->setStretchedColumn(1);
// direction volumes filter
m_DirectionVolumesDataTreeFilter = mitk::DataTreeFilter::New( GetDataTreeIterator()->GetTree() );
m_DirectionVolumesDataTreeFilter->SetSelectionMode(mitk::DataTreeFilter::MULTI_SELECT);
m_DirectionVolumesDataTreeFilter->SetHierarchyHandling(mitk::DataTreeFilter::FLATTEN_HIERARCHY);
m_DirectionVolumesDataTreeFilter->SetFilter( mitk::IsBaseDataTypeWithBoolProperty<mitk::Image>("IsDirectionVolume") );
m_DirectionVolumesDataTreeFilter->SetVisibleProperties(visible_props);
mitk::DataTreeFilter::PropertyList direction_property_labels;
direction_property_labels.push_back("Direction Volumes");
m_DirectionVolumesDataTreeFilter->SetPropertiesLabels(direction_property_labels);
m_Controls->m_DirectionVolumesSelector->SetDataTree( GetDataTreeIterator()->GetTree() );
m_Controls->m_DirectionVolumesSelector->SetFilter( m_DirectionVolumesDataTreeFilter );
m_Controls->m_DirectionVolumesSelector->SetAutoUpdate( false );
m_Controls->m_DirectionVolumesSelector->setStretchedColumn(1);
m_FilterInitialized = true;
TreeChanged();
}
void QmitkDiffusionTensorEstimation::Deactivated()
{
}
void QmitkDiffusionTensorEstimation::Visible()
{
}
void QmitkDiffusionTensorEstimation::Hidden()
{
}
void QmitkDiffusionTensorEstimation::TensorVolumesSaveButton()
{
// GET SELECTED ITEM
const mitk::DataTreeFilter::Item* selectedItem
= m_TensorVolumesDataTreeFilter->GetSelectedItem();
if( !selectedItem )
return;
mitk::Image::Pointer tensorVol =
static_cast<mitk::Image*>(selectedItem->GetNode()->GetData());
TensorImageType::Pointer itkTensorVol =
TensorImageType::New();
mitk::CastToItkImage<TensorImageType>(tensorVol, itkTensorVol);
// SELECT FILE DIALOG
std::string sName = selectedItem->GetNode()->GetName();
QString qName;
qName.sprintf("%s.nhdr",sName.c_str());
QString filename = QFileDialog::getSaveFileName(
qName,
"Nrrd Images (*.nrrd *.nhdr)",
this->m_Controls,
"save file dialog",
"Select Nrrd Outputfile" );
if ( !filename )
return;
// WRITING TENSORS TO FILE
MBI_INFO << "Writing tensors ";
typedef itk::ImageFileWriter<TensorImageType> TensorWriterType;
TensorWriterType::Pointer tensorWriter = TensorWriterType::New();
tensorWriter->SetFileName(filename.ascii());
tensorWriter->SetInput(itkTensorVol);
tensorWriter->Update();
}
void QmitkDiffusionTensorEstimation::TensorVolumesLoadButton()
{
// SELECT FOLDER DIALOG
QFileDialog* w = new QFileDialog( this->m_Controls, "Select DWI data file", TRUE );
w->setMode( QFileDialog::ExistingFiles );
w->setFilter( "Nrrd Images (*.nrrd *.nhdr)" );
// RETRIEVE SELECTION
if ( w->exec() != QDialog::Accepted )
return;
QStringList filenames = w->selectedFiles();
QStringList::Iterator it = filenames.begin();
while( it != filenames.end() ) {
std::string filename = ( *it ).ascii();
++it;
// READING TENSOR VOLUME
typedef itk::ImageFileReader<TensorImageType> ReaderType;
ReaderType::Pointer tensorReader = ReaderType::New();
tensorReader->SetFileName(filename);
try
{
tensorReader->Update();
}
catch (const itk::ExceptionObject& e)
{
std::cout << e << std::endl;
}
// Tensorvolume
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk( tensorReader->GetOutput() );
image->SetVolume( tensorReader->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( image );
mitk::DataStorage::GetInstance()->Add(node);
SetDefaultNodeProperties(node, itksys::SystemTools::GetFilenameName(filename));
node->SetProperty( "IsTensorVolume", mitk::BoolProperty::New( true ) );
TreeChanged();
}
}
void QmitkDiffusionTensorEstimation::TensorVolumesRemoveButton()
{
m_TensorVolumesDataTreeFilter->DeleteSelectedItems();
}
void QmitkDiffusionTensorEstimation::OdfVolumesSaveButton()
{
// GET SELECTED ITEM
const mitk::DataTreeFilter::Item* selectedItem
= m_OdfVolumesDataTreeFilter->GetSelectedItem();
if( !selectedItem ) return;
mitk::Image::Pointer OdfVol =
static_cast<mitk::Image*>(selectedItem->GetNode()->GetData());
if( !OdfVol)return;
typedef itk::Image<itk::Vector<TTensorPixelType,odfsize>,3 > IType;
IType::Pointer itkOdfVol = IType::New();
mitk::CastToItkImage<IType>(OdfVol, itkOdfVol);
typedef itk::VectorImage<TTensorPixelType, 3> VarVecImgType;
VarVecImgType::Pointer vecImg = VarVecImgType::New();
vecImg->SetSpacing( itkOdfVol->GetSpacing() ); // Set the image spacing
vecImg->SetOrigin( itkOdfVol->GetOrigin() ); // Set the image origin
vecImg->SetDirection( itkOdfVol->GetDirection() ); // Set the image direction
vecImg->SetLargestPossibleRegion( itkOdfVol->GetLargestPossibleRegion());
vecImg->SetBufferedRegion( itkOdfVol->GetLargestPossibleRegion() );
vecImg->SetVectorLength(odfsize);
vecImg->Allocate();
itk::ImageRegionIterator<VarVecImgType> ot (vecImg, vecImg->GetLargestPossibleRegion() );
ot = ot.Begin();
itk::ImageRegionIterator<IType> it (itkOdfVol, itkOdfVol->GetLargestPossibleRegion() );
it = it.Begin();
MBI_DEBUG << it.Get();
for (it = it.Begin(); !it.IsAtEnd(); ++it)
{
itk::Vector<TTensorPixelType,odfsize> vec = it.Get();
VarVecImgType::PixelType varvec(vec.GetDataPointer(), odfsize);
ot.Set(varvec);
++ot;
}
// SELECT FILE DIALOG
std::string sName = selectedItem->GetNode()->GetName();
QString qName;
qName.sprintf("%s.nhdr",sName.c_str());
QString filename = QFileDialog::getSaveFileName(
qName,
"Nrrd Images (*.nrrd *.nhdr)",
this->m_Controls,
"save file dialog",
"Select Nrrd Outputfile" );
if ( !filename )
return;
// WRITING TENSORS TO FILE
MBI_INFO << "Writing data ";
typedef itk::ImageFileWriter<VarVecImgType> OdfWriterType;
OdfWriterType::Pointer OdfWriter = OdfWriterType::New();
OdfWriter->SetFileName(filename.ascii());
OdfWriter->SetInput(vecImg);
OdfWriter->Update();
}
void QmitkDiffusionTensorEstimation::OdfVolumesLoadButton()
{
// SELECT FOLDER DIALOG
QFileDialog* w = new QFileDialog( this->m_Controls, "Select DWI data file", TRUE );
w->setMode( QFileDialog::ExistingFiles );
w->setFilter( "Nrrd Images (*.nrrd *.nhdr)" );
// RETRIEVE SELECTION
if ( w->exec() != QDialog::Accepted )
return;
QStringList filenames = w->selectedFiles();
QStringList::Iterator it = filenames.begin();
while( it != filenames.end() ) {
std::string filename = ( *it ).ascii();
++it;
// READING TENSOR VOLUME
typedef itk::Image<itk::Vector<TTensorPixelType,odfsize>,3 > IVType;
typedef itk::ImageFileReader<IVType> ReaderType;
ReaderType::Pointer OdfReader = ReaderType::New();
OdfReader->SetFileName(filename);
try
{
OdfReader->Update();
}
catch (const itk::ExceptionObject& e)
{
MBI_LOG << e;
}
//itk::ImageRegionConstIterator<IVType> it (OdfReader->GetOutput(), OdfReader->GetOutput()->GetLargestPossibleRegion() );
//it = it.Begin();
//std::cout << it.Get() << std::endl;
// Tensorvolume
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk( OdfReader->GetOutput() );
image->SetVolume( OdfReader->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( image );
mitk::DataStorage::GetInstance()->Add(node);
SetDefaultNodeProperties(node, itksys::SystemTools::GetFilenameName(filename));
node->SetProperty( "IsOdfVolume", mitk::BoolProperty::New( true ) );
node->SetProperty( "visible", mitk::BoolProperty::New( false ) );
TreeChanged();
}
}
void QmitkDiffusionTensorEstimation::OdfVolumesRemoveButton()
{
m_OdfVolumesDataTreeFilter->DeleteSelectedItems();
}
void QmitkDiffusionTensorEstimation::OdfVolumesVisualizeSelectedButton()
{
itk::TimeProbe clock;
QString status;
const mitk::DataTreeFilter::Item* item
= m_OdfVolumesDataTreeFilter->GetSelectedItem();
if(!item)return;
typedef itk::Vector<TTensorPixelType,odfsize> OdfVectorType;
typedef itk::Image<OdfVectorType,3> OdfVectorImgType;
mitk::Image* vol =
static_cast<mitk::Image*>(item->GetNode()->GetData());
OdfVectorImgType::Pointer itkvol = OdfVectorImgType::New();
mitk::CastToItkImage<OdfVectorImgType>(vol, itkvol);
std::string nodename = item->GetProperty("name");
// PREPARE FOR VISUALIZATION
clock.Start();
MBI_INFO << "Preparing for Visualization ";
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf(
"Preparing for Visualization of %s", nodename.c_str()));
typedef itk::DiffusionOdfPrepareVisualizationImageFilter<TTensorPixelType,odfsize>
FilterType;
FilterType::Pointer filter = FilterType::New();
filter->SetInput(itkvol);
filter->SetNumberOfThreads(4);
switch(m_Controls->m_OdfVolumesVisualizeNormalizationMethod->currentItem())
{
case 0:
{
filter->SetNormalizationMethod(FilterType::PV_MIN_MAX);
break;
}
case 1:
{
filter->SetNormalizationMethod(FilterType::PV_NONE);
break;
}
case 2:
{
filter->SetNormalizationMethod(FilterType::PV_MAX);
break;
}
case 3:
{
filter->SetNormalizationMethod(FilterType::PV_GLOBAL_MAX);
break;
}
case 4:
{
filter->SetNormalizationMethod(FilterType::PV_MIN_MAX_INVERT);
break;
}
default:
{
filter->SetNormalizationMethod(FilterType::PV_MIN_MAX);
break;
}
}
if(m_Controls->m_OdfVolumesVisualizeScaleGfaCheckbox->isChecked() )
{
typedef itk::DiffusionOdfGeneralizedFaImageFilter<TTensorPixelType,TTensorPixelType,odfsize>
GfaFilterType;
filter->SetDoScaleGfa(true);
float p1 = m_Controls->m_OdfStandardAlgorithmsGFAParam1->text().toFloat();
float p2 = m_Controls->m_OdfStandardAlgorithmsGFAParam2->text().toFloat();
switch(m_Controls->m_OdfStandardAlgorithmsGFAMethod->currentItem())
{
case 0:
filter->SetScaleByGfaType(GfaFilterType::GFA_STANDARD);
break;
case 1:
filter->SetScaleByGfaType(GfaFilterType::GFA_QUANTILES_HIGH_LOW);
break;
case 2:
filter->SetScaleByGfaType(GfaFilterType::GFA_QUANTILE_HIGH);
break;
case 3:
filter->SetScaleByGfaType(GfaFilterType::GFA_MAX_ODF_VALUE);
break;
case 4:
filter->SetScaleByGfaType(GfaFilterType::GFA_DECONVOLUTION_COEFFS);
break;
case 5:
filter->SetScaleByGfaType(GfaFilterType::GFA_MIN_MAX_NORMALIZED_STANDARD);
break;
case 6:
filter->SetScaleByGfaType(GfaFilterType::GFA_NORMALIZED_ENTROPY);
break;
case 7:
filter->SetScaleByGfaType(GfaFilterType::GFA_NEMATIC_ORDER_PARAMETER);
break;
case 8:
filter->SetScaleByGfaType(GfaFilterType::GFA_QUANTILES_LOW_HIGH);
break;
case 9:
filter->SetScaleByGfaType(GfaFilterType::GFA_QUANTILE_LOW);
break;
case 10:
filter->SetScaleByGfaType(GfaFilterType::GFA_MIN_ODF_VALUE);
break;
case 11:
filter->SetScaleByGfaType(GfaFilterType::GFA_STD_BY_MAX);
break;
case 12:
filter->SetScaleByGfaType(GfaFilterType::GFA_PRINCIPLE_CURVATURE);
filter->SetGfaParam1(p1);
break;
case 13:
filter->SetScaleByGfaType(GfaFilterType::GFA_GENERALIZED_GFA);
filter->SetGfaParam1(p1);
filter->SetGfaParam2(p2);
break;
default:
filter->SetScaleByGfaType(GfaFilterType::GFA_STANDARD);
}
}
filter->Update();
clock.Stop();
MBI_DEBUG << "took " << clock.GetMeanTime() << "s.";
// VIZ TO DATATREE
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk( filter->GetOutput() );
image->SetVolume( filter->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( image );
mitk::DataStorage::GetInstance()->Add(node);
SetDefaultNodeProperties(node, nodename.append(" Viz"));
node->SetProperty( "IsOdfVolume", mitk::BoolProperty::New( true ) );
node->SetProperty( "ShowMaxNumber", mitk::IntProperty::New( 1500 ) );
node->SetProperty( "DoRefresh", mitk::BoolProperty::New( true ) );
node->SetProperty( "layer", mitk::IntProperty::New( 1 ) );
node->SetProperty( "global_scaling", mitk::FloatProperty::New( 1.0 ) );
mitk::OdfVtkMapper2D<TTensorPixelType,odfsize>::Pointer odfMapper =
mitk::OdfVtkMapper2D<TTensorPixelType,odfsize>::New();
node->SetMapper(1,odfMapper);
mitk::StatusBar::GetInstance()->DisplayText("Computation complete.");
m_DataTreeIterator->GetTree()->Modified();
this->GetRenderWindowPart()->RequestUpdate();
TreeChanged();
m_Controls->update();
}
void QmitkDiffusionTensorEstimation::DirectionVolumesSaveButton()
{
// GET SELECTED ITEM
const mitk::DataTreeFilter::Item* selectedItem
= m_DirectionVolumesDataTreeFilter->GetSelectedItem();
if( !selectedItem ) return;
mitk::Image::Pointer vol =
static_cast<mitk::Image*>(selectedItem->GetNode()->GetData());
if( !vol)return;
typedef itk::Image<itk::Vector<TTensorPixelType,3>,3 > IType;
IType::Pointer itkVol = IType::New();
mitk::CastToItkImage<IType>(vol, itkVol);
typedef itk::VectorImage<TTensorPixelType, 3> VarVecImgType;
VarVecImgType::Pointer vecImg = VarVecImgType::New();
vecImg->SetSpacing( itkVol->GetSpacing() ); // Set the image spacing
vecImg->SetOrigin( itkVol->GetOrigin() ); // Set the image origin
vecImg->SetDirection( itkVol->GetDirection() ); // Set the image direction
vecImg->SetLargestPossibleRegion( itkVol->GetLargestPossibleRegion());
vecImg->SetBufferedRegion( itkVol->GetLargestPossibleRegion() );
vecImg->SetVectorLength(3);
vecImg->Allocate();
itk::ImageRegionIterator<VarVecImgType> ot (vecImg, vecImg->GetLargestPossibleRegion() );
ot = ot.Begin();
itk::ImageRegionIterator<IType> it (itkVol, itkVol->GetLargestPossibleRegion() );
it = it.Begin();
for (it = it.Begin(); !it.IsAtEnd(); ++it)
{
itk::Vector<TTensorPixelType,3> vec = it.Get();
VarVecImgType::PixelType varvec(vec.GetDataPointer(), 3);
ot.Set(varvec);
++ot;
}
// SELECT FILE DIALOG
std::string sName = selectedItem->GetNode()->GetName();
QString qName;
qName.sprintf("%s.nhdr",sName.c_str());
QString filename = QFileDialog::getSaveFileName(
qName,
"Nrrd Images (*.nrrd *.nhdr)",
this->m_Controls,
"save file dialog",
"Select Nrrd Outputfile" );
if ( !filename )
return;
// WRITING TENSORS TO FILE
MBI_INFO << "Writing data ";
typedef itk::ImageFileWriter<VarVecImgType> WriterType;
WriterType::Pointer writer = WriterType::New();
writer->SetFileName(filename.ascii());
writer->SetInput(vecImg);
writer->Update();
}
void QmitkDiffusionTensorEstimation::DirectionVolumesLoadButton()
{
// SELECT FOLDER DIALOG
QFileDialog* w = new QFileDialog( this->m_Controls, "Select DWI data file", TRUE );
w->setMode( QFileDialog::ExistingFiles );
w->setFilter( "Nrrd Images (*.nrrd *.nhdr)" );
// RETRIEVE SELECTION
if ( w->exec() != QDialog::Accepted )
return;
QStringList filenames = w->selectedFiles();
QStringList::Iterator it = filenames.begin();
while( it != filenames.end() ) {
std::string filename = ( *it ).ascii();
++it;
// READING VOLUME
typedef itk::Image<itk::Vector<TTensorPixelType,3>,3 > IType;
typedef itk::ImageFileReader<IType> ReaderType;
ReaderType::Pointer reader = ReaderType::New();
reader->SetFileName(filename);
try
{
reader->Update();
}
catch (const itk::ExceptionObject& e)
{
MBI_INFO << e << std::endl;
}
// Tensorvolume
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk( reader->GetOutput() );
image->SetVolume( reader->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( image );
mitk::DataStorage::GetInstance()->Add(node);
SetDefaultNodeProperties(node, itksys::SystemTools::GetFilenameName(filename));
node->SetProperty( "IsDirectionVolume", mitk::BoolProperty::New( true ) );
mitk::VectorImageMapper2D::Pointer mapper =
mitk::VectorImageMapper2D::New();
node->SetMapper(1,mapper);
TreeChanged();
}
}
void QmitkDiffusionTensorEstimation::DirectionVolumesRemoveButton()
{
m_DirectionVolumesDataTreeFilter->DeleteSelectedItems();
}
void QmitkDiffusionTensorEstimation::TensorEstimationTeemEstimateButton()
{
try
{
itk::TimeProbe clock;
const mitk::DataTreeFilter::ItemSet* selectedItems
= m_DiffusionVolumesDataTreeFilter->GetSelectedItems();
int nrFiles = selectedItems->size();
if (!nrFiles) return;
QString status;
mitk::ProgressBar::GetInstance()->AddStepsToDo(nrFiles);
mitk::DataTreeFilter::ItemSet::const_iterator itemiter( selectedItems->begin() );
mitk::DataTreeFilter::ItemSet::const_iterator itemiterend( selectedItems->end() );
std::vector<mitk::DataNode::Pointer> nodes;
while ( itemiter != itemiterend ) // for all items
{
mitk::DiffusionVolumes<DiffusionPixelType>* vols =
static_cast<mitk::DiffusionVolumes<DiffusionPixelType>*>(
(*itemiter)->GetNode()->GetData());
std::string nodename = (*itemiter)->GetProperty("name");
itemiter++;
// TENSOR RECONSTRUCTION
clock.Start();
MBI_INFO << "Teem Tensor reconstruction ";
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf(
"Teem Tensor reconstruction for %s", nodename.c_str()));
typedef mitk::TeemDiffusionTensor3DReconstructionImageFilter<
DiffusionPixelType, TTensorPixelType > TensorReconstructionImageFilterType;
TensorReconstructionImageFilterType::Pointer tensorReconstructionFilter =
TensorReconstructionImageFilterType::New();
tensorReconstructionFilter->SetInput( vols );
tensorReconstructionFilter->SetEstimateErrorImage( m_Controls->m_TensorEstimationTeemErrorImage->isChecked() );
if(!m_Controls->m_TensorEstimationTeemSigmaEdit->text().contains(QString("NaN")))
tensorReconstructionFilter->SetSigma( m_Controls->m_TensorEstimationTeemSigmaEdit->text().toFloat() );
switch(m_Controls->m_TensorEstimationTeemEstimationMethodCombo->currentItem())
{
case 0:
tensorReconstructionFilter->SetEstimationMethod(mitk::TeemTensorEstimationMethodsLLS);
break;
case 1:
tensorReconstructionFilter->SetEstimationMethod(mitk::TeemTensorEstimationMethodsNLS);
break;
case 2:
tensorReconstructionFilter->SetEstimationMethod(mitk::TeemTensorEstimationMethodsWLS);
break;
case 3:
tensorReconstructionFilter->SetEstimationMethod(mitk::TeemTensorEstimationMethodsMLE);
break;
default:
tensorReconstructionFilter->SetEstimationMethod(mitk::TeemTensorEstimationMethodsLLS);
}
tensorReconstructionFilter->SetNumIterations( m_Controls->m_TensorEstimationTeemNumItsSpin->value() );
if(!m_Controls->m_TensorEstimationTeemConfThresholdEdit->text().contains(QString("NaN")))
tensorReconstructionFilter->SetConfidenceThreshold( m_Controls->m_TensorEstimationTeemConfThresholdEdit->text().toDouble() );
tensorReconstructionFilter->SetConfidenceFuzzyness( m_Controls->m_TensorEstimationTeemFuzzyEdit->text().toFloat() );
tensorReconstructionFilter->SetMinPlausibleValue( m_Controls->m_TensorEstimationTeemMinValEdit->text().toDouble() );
tensorReconstructionFilter->Update();
clock.Stop();
MBI_DEBUG << "took " << clock.GetMeanTime() << "s.";
// TENSORS TO DATATREE
//mitk::DataNode::Pointer node=mitk::DataNode::New();
//node->SetData( tensorReconstructionFilter->GetOutput() );
//mitk::DataStorage::GetInstance()->Add(node);
//SetDefaultNodeProperties(node, nodename.append(" tensors"));
//node->SetProperty( "IsConfidenceTensorVolume", mitk::BoolProperty::New( true ) );
mitk::DataNode::Pointer node2=mitk::DataNode::New();
node2->SetData( tensorReconstructionFilter->GetOutputItk() );
SetDefaultNodeProperties(node2, nodename.append(" (itk)"));
node2->SetProperty( "IsTensorVolume", mitk::BoolProperty::New( true ) );
nodes.push_back(node2);
mitk::ProgressBar::GetInstance()->Progress();
}
std::vector<mitk::DataNode::Pointer>::iterator nodeIt;
for(nodeIt = nodes.begin(); nodeIt != nodes.end(); ++nodeIt)
mitk::DataStorage::GetInstance()->Add(*nodeIt);
mitk::ProgressBar::GetInstance()->Progress();
TreeChanged();
m_Controls->update();
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished Processing %d Files", nrFiles));
}
catch (itk::ExceptionObject &ex)
{
MBI_INFO << ex;
return ;
}
}
void QmitkDiffusionTensorEstimation::TensorEstimationButton()
{
try
{
itk::TimeProbe clock;
const mitk::DataTreeFilter::ItemSet* selectedItems
= m_DiffusionVolumesDataTreeFilter->GetSelectedItems();
int nrFiles = selectedItems->size();
if (!nrFiles) return;
QString status;
mitk::ProgressBar::GetInstance()->AddStepsToDo(nrFiles);
mitk::DataTreeFilter::ItemSet::const_iterator itemiter( selectedItems->begin() );
mitk::DataTreeFilter::ItemSet::const_iterator itemiterend( selectedItems->end() );
std::vector<mitk::DataNode::Pointer> nodes;
while ( itemiter != itemiterend ) // for all items
{
mitk::DiffusionVolumes<DiffusionPixelType>* vols =
static_cast<mitk::DiffusionVolumes<DiffusionPixelType>*>(
(*itemiter)->GetNode()->GetData());
std::string nodename = (*itemiter)->GetProperty("name");
itemiter++;
// TENSOR RECONSTRUCTION
clock.Start();
MBI_INFO << "Tensor reconstruction ";
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf(
"Tensor reconstruction for %s", nodename.c_str()));
typedef itk::DiffusionTensor3DReconstructionImageFilter<
DiffusionPixelType, DiffusionPixelType, TTensorPixelType > TensorReconstructionImageFilterType;
TensorReconstructionImageFilterType::Pointer tensorReconstructionFilter =
TensorReconstructionImageFilterType::New();
tensorReconstructionFilter->SetGradientImage( vols->GetDirections(), vols->GetImage() );
tensorReconstructionFilter->SetNumberOfThreads( m_Controls->m_TensorEstimationNumberThreadsSpinbox->value() );
tensorReconstructionFilter->SetBValue(vols->GetB_Value());
tensorReconstructionFilter->SetThreshold( m_Controls->m_TensorEstimationThreasholdEdit->text().toFloat() );
tensorReconstructionFilter->Update();
clock.Stop();
MBI_DEBUG << "took " << clock.GetMeanTime() << "s.";
// TENSORS TO DATATREE
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk( tensorReconstructionFilter->GetOutput() );
image->SetVolume( tensorReconstructionFilter->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( image );
SetDefaultNodeProperties(node, nodename.append(" tensors"));
node->SetProperty( "IsTensorVolume", mitk::BoolProperty::New( true ) );
nodes.push_back(node);
mitk::ProgressBar::GetInstance()->Progress();
}
std::vector<mitk::DataNode::Pointer>::iterator nodeIt;
for(nodeIt = nodes.begin(); nodeIt != nodes.end(); ++nodeIt)
mitk::DataStorage::GetInstance()->Add(*nodeIt);
mitk::ProgressBar::GetInstance()->Progress();
TreeChanged();
m_Controls->update();
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished Processing %d Files", nrFiles));
}
catch (itk::ExceptionObject &ex)
{
MBI_INFO << ex;
return ;
}
}
void QmitkDiffusionTensorEstimation::OdfReconstructionButton()
{
try
{
itk::TimeProbe clock;
const mitk::DataTreeFilter::ItemSet* selectedItems
= m_DiffusionVolumesDataTreeFilter->GetSelectedItems();
int nrFiles = selectedItems->size();
if (!nrFiles) return;
QString status;
mitk::ProgressBar::GetInstance()->AddStepsToDo(nrFiles);
mitk::DataTreeFilter::ItemSet::const_iterator itemiter( selectedItems->begin() );
mitk::DataTreeFilter::ItemSet::const_iterator itemiterend( selectedItems->end() );
std::vector<mitk::DataNode::Pointer> nodes;
while ( itemiter != itemiterend ) // for all items
{
mitk::DiffusionVolumes<DiffusionPixelType>* vols =
static_cast<mitk::DiffusionVolumes<DiffusionPixelType>*>(
(*itemiter)->GetNode()->GetData());
std::string nodename = (*itemiter)->GetProperty("name");
++itemiter;
// Odf RECONSTRUCTION
clock.Start();
MBI_INFO << "Odf reconstruction ";
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf(
"Odf reconstruction for %s", nodename.c_str()));
typedef itk::DiffusionQballReconstructionImageFilter<
DiffusionPixelType, DiffusionPixelType, TTensorPixelType, odfsize>
//int NOdfDirections = 162,
QballReconstructionImageFilterType;
QballReconstructionImageFilterType::Pointer filter =
QballReconstructionImageFilterType::New();
filter->SetGradientImage( vols->GetDirections(), vols->GetImage() );
filter->SetNumberOfThreads( m_Controls->m_OdfReconstructionNumberThreadsSpinbox->value() );
filter->SetBValue(vols->GetB_Value());
filter->SetThreshold( m_Controls->m_OdfReconstructionThreasholdEdit->text().toFloat() );
int normalization = m_Controls->m_OdfReconstructionPostprocessingMethod->currentItem();
switch(normalization)
{
case 0:
{
filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_STANDARD);
break;
}
case 1:
{
filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_B_ZERO_B_VALUE);
break;
}
case 2:
{
filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_B_ZERO);
break;
}
case 3:
{
filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_NONE);
break;
}
default:
{
filter->SetNormalizationMethod(QballReconstructionImageFilterType::QBR_STANDARD);
}
}
filter->Update();
clock.Stop();
MBI_DEBUG << "took " << clock.GetMeanTime() << "s." << std::endl;
// ODFs TO DATATREE
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk( filter->GetOutput() );
//image->SetImportVolume( filter->GetOutput()->GetBufferPointer(), 0, 0, mitk::Image::ImportMemoryManagementType::ManageMemory );
image->SetVolume( filter->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( image );
QString newname;
newname = newname.append(nodename.c_str());
newname = newname.append("_QN%1").arg(normalization);
SetDefaultNodeProperties(node, newname.ascii());
node->SetProperty( "IsOdfVolume", mitk::BoolProperty::New( true ) );
nodes.push_back(node);
// B-Zero TO DATATREE
mitk::Image::Pointer image4 = mitk::Image::New();
image4->InitializeByItk( filter->GetBZeroImage().GetPointer() );
image4->SetVolume( filter->GetBZeroImage()->GetBufferPointer() );
mitk::DataNode::Pointer node4=mitk::DataNode::New();
node4->SetData( image4 );
SetDefaultNodeProperties(node4, nodename.append("B0"));
nodes.push_back(node4);
mitk::ProgressBar::GetInstance()->Progress();
}
std::vector<mitk::DataNode::Pointer>::iterator nodeIt;
for(nodeIt = nodes.begin(); nodeIt != nodes.end(); ++nodeIt)
mitk::DataStorage::GetInstance()->Add(*nodeIt);
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished Processing %d Files", nrFiles));
m_DataTreeIterator->GetTree()->Modified();
this->GetRenderWindowPart()->RequestUpdate();
TreeChanged();
m_Controls->update();
}
catch (itk::ExceptionObject &ex)
{
MBI_INFO << ex;
return ;
}
}
template<int L>
void QmitkDiffusionTensorEstimation::ReconstructAnalytically(
mitk::DiffusionVolumes<DiffusionPixelType>* vols, float lambda,
std::string nodename, std::vector<mitk::DataNode::Pointer>* nodes)
{
typedef itk::AnalyticalDiffusionQballReconstructionImageFilter
<DiffusionPixelType,DiffusionPixelType,TTensorPixelType,L,odfsize> FilterType;
typename FilterType::Pointer filter = FilterType::New();
filter->SetGradientImage( vols->GetDirections(), vols->GetImage() );
filter->SetNumberOfThreads( m_Controls->m_OdfReconstructionNumberThreadsAnalyticalSpinbox->value() );
filter->SetBValue(vols->GetB_Value());
filter->SetThreshold( m_Controls->m_OdfReconstructionThreasholdAnalyticalEdit->text().toFloat() );
filter->SetLambda(lambda);
filter->SetAdcProfileOnly(m_Controls->m_OdfReconstructionAdcOnlyCheckbox->isChecked());
int normalization = m_Controls->m_OdfReconstructionPostprocessingMethodAnalytical->currentItem();
switch(normalization)
{
case 0:
{
filter->SetNormalizationMethod(FilterType::QBAR_STANDARD);
break;
}
case 1:
{
filter->SetNormalizationMethod(FilterType::QBAR_B_ZERO_B_VALUE);
break;
}
case 2:
{
filter->SetNormalizationMethod(FilterType::QBAR_B_ZERO);
break;
}
case 3:
{
filter->SetNormalizationMethod(FilterType::QBAR_NONE);
break;
}
default:
{
filter->SetNormalizationMethod(FilterType::QBAR_STANDARD);
}
}
filter->Update();
// ODFs TO DATATREE
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk( filter->GetOutput() );
image->SetVolume( filter->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( image );
nodes->push_back(node);
QString newname;
newname = newname.append(nodename.c_str());
newname = newname.append("_QA%1").arg(normalization);
SetDefaultNodeProperties(node, newname.ascii());
node->SetProperty( "IsOdfVolume", mitk::BoolProperty::New( true ) );
// B-Zero TO DATATREE
mitk::Image::Pointer image4 = mitk::Image::New();
image4->InitializeByItk( filter->GetBZeroImage().GetPointer() );
image4->SetVolume( filter->GetBZeroImage()->GetBufferPointer() );
mitk::DataNode::Pointer node4=mitk::DataNode::New();
node4->SetData( image4 );
nodes->push_back(node4);
SetDefaultNodeProperties(node4, nodename.append("B0"));
}
void QmitkDiffusionTensorEstimation::OdfReconstructionAnalyticalButton()
{
try
{
itk::TimeProbe clock;
const mitk::DataTreeFilter::ItemSet* selectedItems
= m_DiffusionVolumesDataTreeFilter->GetSelectedItems();
int nrFiles = selectedItems->size();
if (!nrFiles) return;
std::vector<float> lambdas;
float minLambda = m_Controls->m_OdfReconstructionLambdaLineEdit->text().toFloat();
if(m_Controls->m_OdfReconstructionLambdaMultiCheckbox->isChecked())
{
float stepLambda = m_Controls->m_OdfReconstructionLambdaStepLineEdit->text().toFloat();
float maxLambda = m_Controls->m_QBallReconstructionLambdaMaxLineEdit->text().toFloat();
for(float l=minLambda; l<maxLambda; l+=stepLambda)
{
lambdas.push_back(l);
}
}
int nLambdas = lambdas.size();
if(nLambdas == 0)
{
lambdas.push_back(minLambda);
nLambdas = 1;
}
QString status;
mitk::ProgressBar::GetInstance()->AddStepsToDo(nrFiles*nLambdas);
mitk::DataTreeFilter::ItemSet::const_iterator itemiter( selectedItems->begin() );
mitk::DataTreeFilter::ItemSet::const_iterator itemiterend( selectedItems->end() );
std::vector<mitk::DataNode::Pointer>* nodes
= new std::vector<mitk::DataNode::Pointer>();
while ( itemiter != itemiterend ) // for all items
{
mitk::DiffusionVolumes<DiffusionPixelType>* vols =
static_cast<mitk::DiffusionVolumes<DiffusionPixelType>*>(
(*itemiter)->GetNode()->GetData());
std::string nodename = (*itemiter)->GetProperty("name");
itemiter++;
// Odf RECONSTRUCTION
clock.Start();
MBI_INFO << "Odf reconstruction ";
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf(
"Odf reconstruction for %s", nodename.c_str()));
for(int i=0; i<nLambdas; i++)
{
float currentLambda = lambdas[i];
switch(m_Controls->m_OdfReconstructionMaxLLevelComboBox->currentItem())
{
case 0:
{
ReconstructAnalytically<2>(vols, currentLambda, nodename, nodes);
break;
}
case 1:
{
ReconstructAnalytically<4>(vols, currentLambda, nodename, nodes);
break;
}
case 2:
{
ReconstructAnalytically<6>(vols, currentLambda, nodename, nodes);
break;
}
case 3:
{
ReconstructAnalytically<8>(vols, currentLambda, nodename, nodes);
break;
}
}
clock.Stop();
MBI_DEBUG << "took " << clock.GetMeanTime() << "s.";
mitk::ProgressBar::GetInstance()->Progress();
}
}
std::vector<mitk::DataNode::Pointer>::iterator nodeIt;
for(nodeIt = nodes->begin(); nodeIt != nodes->end(); ++nodeIt)
mitk::DataStorage::GetInstance()->Add(*nodeIt);
m_DataTreeIterator->GetTree()->Modified();
this->GetRenderWindowPart()->RequestUpdate();
TreeChanged();
m_Controls->update();
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished Processing %d Files", nrFiles));
}
catch (itk::ExceptionObject &ex)
{
MBI_INFO << ex;
return ;
}
}
void QmitkDiffusionTensorEstimation::StandardAlgorithmsFAButton()
{
itk::TimeProbe clock;
QString status;
const mitk::DataTreeFilter::Item* item
= m_TensorVolumesDataTreeFilter->GetSelectedItem();
if(!item)return;
mitk::Image* vol =
static_cast<mitk::Image*>(item->GetNode()->GetData());
itk::Image<TensorPixelType, 3>::Pointer itkvol = itk::Image<TensorPixelType, 3>::New();
mitk::CastToItkImage<TensorImageType>(vol, itkvol);
std::string nodename = item->GetProperty("name");
// COMPUTE FA
clock.Start();
MBI_INFO << "Computing FA ";
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf(
"Computing FA for %s", nodename.c_str()));
typedef TensorPixelType::RealValueType RealValueType;
typedef itk::Image< RealValueType, 3 > FAImageType;
typedef itk::TensorFractionalAnisotropyImageFilter<
TensorImageType, FAImageType > FAFilterType;
FAFilterType::Pointer fractionalAnisotropyFilter = FAFilterType::New();
fractionalAnisotropyFilter->SetInput( itkvol );
typedef itk::ShiftScaleImageFilter<FAImageType, FAImageType>
ShiftScaleFilterType;
ShiftScaleFilterType::Pointer multi =
ShiftScaleFilterType::New();
multi->SetShift(0);
multi->SetScale(200);//itk::NumericTraits<RealValueType>::max()
multi->SetInput(fractionalAnisotropyFilter->GetOutput());
multi->Update();
clock.Stop();
MBI_DEBUG << "took " << clock.GetMeanTime() << "s.";
// FA TO DATATREE
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk( multi->GetOutput() );
image->SetVolume( multi->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( image );
mitk::DataStorage::GetInstance()->Add(node);
SetDefaultNodeProperties(node, nodename.append(" FA"));
node->SetProperty( "IsFAVolume", mitk::BoolProperty::New( true ) );
mitk::StatusBar::GetInstance()->DisplayText("Computation complete.");
m_DataTreeIterator->GetTree()->Modified();
this->GetRenderWindowPart()->RequestUpdate();
TreeChanged();
m_Controls->update();
}
void QmitkDiffusionTensorEstimation::StandardAlgorithmsRAButton()
{
itk::TimeProbe clock;
QString status;
const mitk::DataTreeFilter::Item* item
= m_TensorVolumesDataTreeFilter->GetSelectedItem();
if(!item)return;
mitk::Image* vol =
static_cast<mitk::Image*>(item->GetNode()->GetData());
itk::Image<TensorPixelType, 3>::Pointer itkvol = itk::Image<TensorPixelType, 3>::New();
mitk::CastToItkImage<TensorImageType>(vol, itkvol);
std::string nodename = item->GetProperty("name");
// COMPUTE RA
clock.Start();
MBI_INFO << "Computing RA ";
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf(
"Computing RA for %s", nodename.c_str()));
typedef TensorPixelType::RealValueType RealValueType;
typedef itk::Image< RealValueType, 3 > RAImageType;
typedef itk::TensorRelativeAnisotropyImageFilter<
TensorImageType, RAImageType > RAFilterType;
RAFilterType::Pointer relativeAnisotropyFilter = RAFilterType::New();
relativeAnisotropyFilter->SetInput( itkvol );
relativeAnisotropyFilter->Update();
clock.Stop();
MBI_DEBUG << "took " << clock.GetMeanTime() << "s.";
// FA TO DATATREE
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk( relativeAnisotropyFilter->GetOutput() );
image->SetVolume( relativeAnisotropyFilter->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( image );
mitk::DataStorage::GetInstance()->Add(node);
SetDefaultNodeProperties(node, nodename.append(" RA"));
node->SetProperty( "IsRAVolume", mitk::BoolProperty::New( true ) );
mitk::StatusBar::GetInstance()->DisplayText("Computation complete.");
m_DataTreeIterator->GetTree()->Modified();
this->GetRenderWindowPart()->RequestUpdate();
TreeChanged();
m_Controls->update();
}
void QmitkDiffusionTensorEstimation::StandardAlgorithmsDirectionButton()
{
itk::TimeProbe clock;
QString status;
const mitk::DataTreeFilter::Item* item
= m_TensorVolumesDataTreeFilter->GetSelectedItem();
if(!item)return;
typedef itk::DiffusionTensor3D<TTensorPixelType> TensorType;
typedef itk::Image<TensorType,3> TensorImgType;
mitk::Image* vol =
static_cast<mitk::Image*>(item->GetNode()->GetData());
TensorImgType::Pointer itkvol = TensorImgType::New();
mitk::CastToItkImage<TensorImgType>(vol, itkvol);
std::string nodename = item->GetProperty("name");
clock.Start();
MBI_INFO << "Computing Diffusion Direction ";
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf(
"Computing Diffusion Direction for %s", nodename.c_str()));
typedef itk::DiffusionTensorPrincipleDirectionImageFilter<TTensorPixelType,TTensorPixelType>
FilterType;
FilterType::Pointer filter
= FilterType::New();
filter->SetInput(itkvol);
filter->SetNumberOfThreads(4);
filter->Update();
itk::ImageRegionIterator<FilterType::OutputImageType>
it (filter->GetOutput(),
filter->GetOutput()->GetLargestPossibleRegion() );
it = it.Begin();
// VECTORFIELD
MBI_DEBUG << "Converting to Vectorfield";
typedef itk::Image<itk::Vector<TTensorPixelType,3>, 3> VecImgType2;
VecImgType2::Pointer vecImg5 = VecImgType2::New();
vecImg5->SetSpacing( itkvol->GetSpacing() ); // Set the image spacing
vecImg5->SetOrigin( itkvol->GetOrigin() ); // Set the image origin
vecImg5->SetDirection( itkvol->GetDirection() ); // Set the image direction
vecImg5->SetLargestPossibleRegion( itkvol->GetLargestPossibleRegion());
vecImg5->SetBufferedRegion( vecImg5->GetLargestPossibleRegion() );
vecImg5->Allocate();
itk::ImageRegionIterator<VecImgType2> ot5 (vecImg5, vecImg5->GetLargestPossibleRegion() );
ot5 = ot5.Begin();
typedef FilterType::OutputImageType::PixelType VecPixType;
for (it = it.Begin(); !it.IsAtEnd(); ++it)
{
VecPixType vec = it.Get();
itk::Vector<TTensorPixelType,3> pix;
TTensorPixelType uvec[3] = {(TTensorPixelType)(vec[0]),(TTensorPixelType)(vec[1]),(TTensorPixelType)(vec[2])};
//TTensorPixelType uvec[3] = {(TTensorPixelType)(vec[1]),(TTensorPixelType)(-vec[0]),(TTensorPixelType)(vec[2])};
pix = uvec;
ot5.Set(pix);
++ot5;
}
// Vectors TO DATATREE
mitk::Image::Pointer image5 = mitk::Image::New();
image5->InitializeByItk( vecImg5.GetPointer() );
image5->SetVolume( vecImg5->GetBufferPointer() );
mitk::DataNode::Pointer node5=mitk::DataNode::New();
node5->SetData( image5 );
node5->SetName( nodename.append(" vecs").c_str());
mitk::DataStorage::GetInstance()->Add(node5);
node5->SetProperty( "IsDirectionVolume", mitk::BoolProperty::New( true ) );
node5->SetProperty( "NormalizeVecs", mitk::BoolProperty::New( true ) );
node5->SetProperty( "Scale", mitk::FloatProperty::New( 1.0 ) );
node5->SetProperty( "LineWidth", mitk::FloatProperty::New( 1 ) );
mitk::VectorImageMapper2D::Pointer vecMapper5 =
mitk::VectorImageMapper2D::New();
node5->SetMapper(1,vecMapper5);
m_DataTreeIterator->GetTree()->Modified();
this->GetRenderWindowPart()->RequestUpdate();
TreeChanged();
m_Controls->update();
}
void QmitkDiffusionTensorEstimation::OdfStandardAlgorithmsGFAButton()
{
itk::TimeProbe clock;
QString status;
const mitk::DataTreeFilter::ItemSet* selectedItems
= m_OdfVolumesDataTreeFilter->GetSelectedItems();
int nrFiles = selectedItems->size();
if (!nrFiles) return;
mitk::DataTreeFilter::ItemSet::const_iterator itemiter( selectedItems->begin() );
mitk::DataTreeFilter::ItemSet::const_iterator itemiterend( selectedItems->end() );
std::vector<mitk::DataNode::Pointer> nodes;
while ( itemiter != itemiterend ) // for all items
{
typedef itk::Vector<TTensorPixelType,odfsize> OdfVectorType;
typedef itk::Image<OdfVectorType,3> OdfVectorImgType;
mitk::Image* vol =
static_cast<mitk::Image*>((*itemiter)->GetNode()->GetData());
OdfVectorImgType::Pointer itkvol = OdfVectorImgType::New();
mitk::CastToItkImage<OdfVectorImgType>(vol, itkvol);
std::string nodename = (*itemiter)->GetProperty("name");
++itemiter;
float p1 = m_Controls->m_OdfStandardAlgorithmsGFAParam1->text().toFloat();
float p2 = m_Controls->m_OdfStandardAlgorithmsGFAParam2->text().toFloat();
// COMPUTE RA
clock.Start();
MBI_INFO << "Computing GFA ";
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf(
"Computing GFA for %s", nodename.c_str()));
typedef OdfVectorType::ValueType RealValueType;
typedef itk::Image< RealValueType, 3 > RAImageType;
typedef itk::DiffusionOdfGeneralizedFaImageFilter<TTensorPixelType,TTensorPixelType,odfsize>
GfaFilterType;
GfaFilterType::Pointer gfaFilter = GfaFilterType::New();
gfaFilter->SetInput(itkvol);
gfaFilter->SetNumberOfThreads(4);
double scale = 1;
std::string newname;
newname.append(nodename);
newname.append(" GFA");
switch(m_Controls->m_OdfStandardAlgorithmsGFAMethod->currentItem())
{
case 0:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_STANDARD);
newname.append("00");
scale = 200.0;
break;
}
case 1:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_QUANTILES_HIGH_LOW);
newname.append("01");
scale = 200.0;
break;
}
case 2:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_QUANTILE_HIGH);
newname.append("02");
scale = 200.0;
break;
}
case 3:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_MAX_ODF_VALUE);
newname.append("03");
scale = 200.0;
break;
}
case 4:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_DECONVOLUTION_COEFFS);
newname.append("04");
scale = 200.0;
break;
}
case 5:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_MIN_MAX_NORMALIZED_STANDARD);
newname.append("05");
scale = 200.0;
break;
}
case 6:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_NORMALIZED_ENTROPY);
newname.append("06");
break;
}
case 7:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_NEMATIC_ORDER_PARAMETER);
newname.append("07");
scale = 200.0;
break;
}
case 8:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_QUANTILES_LOW_HIGH);
newname.append("08");
scale = 200.0;
break;
}
case 9:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_QUANTILE_LOW);
newname.append("09");
scale = 200.0;
break;
}
case 10:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_MIN_ODF_VALUE);
newname.append("10");
scale = 200.0;
break;
}
case 11:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_STD_BY_MAX);
newname.append("11");
scale = 200.0;
break;
}
case 12:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_PRINCIPLE_CURVATURE);
newname.append("12");
gfaFilter->SetParam1(p1);
scale = 200.0;
break;
}
case 13:
{
gfaFilter->SetComputationMethod(GfaFilterType::GFA_GENERALIZED_GFA);
QString paramString;
paramString = paramString.append(" K%1P%2").arg(p1).arg(p2);
newname.append("13").append(paramString.ascii());
gfaFilter->SetParam1(p1);
gfaFilter->SetParam2(p2);
scale = 200.0;
break;
}
default:
{
newname.append("0");
gfaFilter->SetComputationMethod(GfaFilterType::GFA_STANDARD);
scale = 200.0;
}
}
gfaFilter->Update();
clock.Stop();
MBI_DEBUG << "took " << clock.GetMeanTime() << "s.";
typedef itk::Image<TTensorPixelType, 3> ImgType;
ImgType::Pointer img = ImgType::New();
img->SetSpacing( gfaFilter->GetOutput()->GetSpacing() ); // Set the image spacing
img->SetOrigin( gfaFilter->GetOutput()->GetOrigin() ); // Set the image origin
img->SetDirection( gfaFilter->GetOutput()->GetDirection() ); // Set the image direction
img->SetLargestPossibleRegion( gfaFilter->GetOutput()->GetLargestPossibleRegion());
img->SetBufferedRegion( gfaFilter->GetOutput()->GetLargestPossibleRegion() );
img->Allocate();
itk::ImageRegionIterator<ImgType> ot (img, img->GetLargestPossibleRegion() );
ot = ot.Begin();
itk::ImageRegionConstIterator<GfaFilterType::OutputImageType> it
(gfaFilter->GetOutput(), gfaFilter->GetOutput()->GetLargestPossibleRegion() );
it = it.Begin();
for (it = it.Begin(); !it.IsAtEnd(); ++it)
{
GfaFilterType::OutputImageType::PixelType val = it.Get();
ot.Set(val * scale);
++ot;
}
// GFA TO DATATREE
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk( img.GetPointer() );
image->SetVolume( img->GetBufferPointer() );
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( image );
nodes.push_back(node);
SetDefaultNodeProperties(node, newname.c_str());
node->SetProperty( "IsGFAVolume", mitk::BoolProperty::New( true ) );
mitk::StatusBar::GetInstance()->DisplayText("Computation complete.");
}
std::vector<mitk::DataNode::Pointer>::iterator nodeIt;
for(nodeIt = nodes.begin(); nodeIt != nodes.end(); ++nodeIt)
mitk::DataStorage::GetInstance()->Add(*nodeIt);
m_DataTreeIterator->GetTree()->Modified();
this->GetRenderWindowPart()->RequestUpdate();
TreeChanged();
m_Controls->update();
}
void QmitkDiffusionTensorEstimation::OdfStandardAlgorithmsDirectionButton()
{
itk::TimeProbe clock;
QString status;
const mitk::DataTreeFilter::Item* item
= m_OdfVolumesDataTreeFilter->GetSelectedItem();
if(!item)return;
typedef itk::Vector<TTensorPixelType,odfsize> OdfVectorType;
typedef itk::Image<OdfVectorType,3> OdfVectorImgType;
mitk::Image* vol =
static_cast<mitk::Image*>(item->GetNode()->GetData());
OdfVectorImgType::Pointer itkvol = OdfVectorImgType::New();
mitk::CastToItkImage<OdfVectorImgType>(vol, itkvol);
std::string nodename = item->GetProperty("name");
clock.Start();
MBI_INFO << "Computing Diffusion Direction ";
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf(
"Computing Diffusion Direction for %s", nodename.c_str()));
typedef itk::DiffusionOdfGeneralizedFaImageFilter<TTensorPixelType,TTensorPixelType,odfsize>
GfaFilterType;
GfaFilterType::Pointer gfaFilter = GfaFilterType::New();
gfaFilter->SetInput(itkvol);
gfaFilter->SetNumberOfThreads(4);
gfaFilter->Update();
itk::ImageRegionIterator<GfaFilterType::OutputImageType>
itGfa (gfaFilter->GetOutput(),
gfaFilter->GetOutput()->GetLargestPossibleRegion() );
itGfa = itGfa.Begin();
int numdir = m_Controls->m_OdfStandardAlgorithmsOrderSpinbox->value();
typedef itk::DiffusionOdfPrincipleDirectionsImageFilter<TTensorPixelType,TTensorPixelType,odfsize>
PrincipleDirectionsFilterType;
PrincipleDirectionsFilterType::Pointer principleDirectionsFilter
= PrincipleDirectionsFilterType::New();
principleDirectionsFilter->SetThreshold(m_Controls->m_OdfStandardAlgorithmsProbThreshEdit->text().toFloat());
principleDirectionsFilter->SetNrDirectionToExtract(numdir);
principleDirectionsFilter->SetInput(itkvol);
principleDirectionsFilter->SetNumberOfThreads(m_Controls->m_OdfStandardAlgorithmsNumberThreadsSpinbox->value());
principleDirectionsFilter->SetMultiplyGfa(false);
principleDirectionsFilter->Update();
itk::ImageRegionIterator<PrincipleDirectionsFilterType::OutputImageType>
it (principleDirectionsFilter->GetOutput(),
principleDirectionsFilter->GetOutput()->GetLargestPossibleRegion() );
if(numdir == 0)
{
MBI_INFO << "Converting to RGB";
typedef itk::Image<itk::RGBPixel<uchar>, 3> VecImgType;
VecImgType::Pointer vecImg = VecImgType::New();
vecImg->SetSpacing( itkvol->GetSpacing() ); // Set the image spacing
vecImg->SetOrigin( itkvol->GetOrigin() ); // Set the image origin
vecImg->SetDirection( itkvol->GetDirection() ); // Set the image direction
vecImg->SetLargestPossibleRegion( itkvol->GetLargestPossibleRegion());
vecImg->SetBufferedRegion( vecImg->GetLargestPossibleRegion() );
vecImg->Allocate();
itk::ImageRegionIterator<VecImgType> ot (vecImg, vecImg->GetLargestPossibleRegion() );
ot = ot.Begin();
typedef PrincipleDirectionsFilterType::OutputImageType::PixelType VecPixType;
for (it = it.Begin(); !it.IsAtEnd(); ++it)
{
VecPixType vec = it.Get();
itk::RGBPixel<uchar> pix;
vec*=200*itGfa.Get();
vec[0] = abs(vec[0]);
vec[1] = abs(vec[1]);
vec[2] = abs(vec[2]);
if(vec[0] > 255 || vec[1] > 255 || vec[2] > 255)
{
// should never get in here
double max = vec[0];
max = max<vec[1] ? vec[1] : max;
max = max<vec[2] ? vec[2] : max;
vec /= max/255;
}
uchar uvec[3] = {(uchar)(vec[0]),(uchar)(vec[1]),(uchar)(vec[2])};
pix = uvec;
ot.Set(pix);
++ot;
++itGfa;
}
// RGB TO DATATREE
mitk::Image::Pointer image2 = mitk::Image::New();
image2->InitializeByItk( vecImg.GetPointer() );
image2->SetVolume( vecImg->GetBufferPointer() );
mitk::DataNode::Pointer node2=mitk::DataNode::New();
node2->SetData( image2 );
mitk::DataStorage::GetInstance()->Add(node2);
switch(numdir)
{
case 0:
{
SetDefaultNodeProperties(node2, nodename.append(" PD0"));
break;
}
case 1:
{
SetDefaultNodeProperties(node2, nodename.append(" PD1"));
}
case 2:
{
SetDefaultNodeProperties(node2, nodename.append(" PD2"));
}
default:
{
SetDefaultNodeProperties(node2, nodename.append(" PDn"));
}
}
node2->SetProperty( "IsRGBVolume", mitk::BoolProperty::New( true ) );
}
// VECTORFIELD
MBI_DEBUG << "Converting to Vectorfield";
typedef itk::Image<itk::Vector<TTensorPixelType,3>, 3> VecImgType2;
VecImgType2::Pointer vecImg5 = VecImgType2::New();
vecImg5->SetSpacing( itkvol->GetSpacing() ); // Set the image spacing
vecImg5->SetOrigin( itkvol->GetOrigin() ); // Set the image origin
vecImg5->SetDirection( itkvol->GetDirection() ); // Set the image direction
vecImg5->SetLargestPossibleRegion( itkvol->GetLargestPossibleRegion());
vecImg5->SetBufferedRegion( vecImg5->GetLargestPossibleRegion() );
vecImg5->Allocate();
itk::ImageRegionIterator<VecImgType2> ot5 (vecImg5, vecImg5->GetLargestPossibleRegion() );
ot5 = ot5.Begin();
typedef PrincipleDirectionsFilterType::OutputImageType::PixelType VecPixType;
for (it = it.Begin(); !it.IsAtEnd(); ++it)
{
VecPixType vec = it.Get();
itk::Vector<TTensorPixelType,3> pix;
TTensorPixelType uvec[3] = {(TTensorPixelType)(vec[0]),(TTensorPixelType)(vec[1]),(TTensorPixelType)(vec[2])};
pix = uvec;
ot5.Set(pix);
++ot5;
}
// Vectors TO DATATREE
mitk::Image::Pointer image5 = mitk::Image::New();
image5->InitializeByItk( vecImg5.GetPointer() );
image5->SetVolume( vecImg5->GetBufferPointer() );
mitk::DataNode::Pointer node5=mitk::DataNode::New();
node5->SetData( image5 );
mitk::DataStorage::GetInstance()->Add(node5);
switch(numdir)
{
case 0:
{
SetDefaultNodeProperties(node5, nodename.append(" Vec0"));
break;
}
case 1:
{
SetDefaultNodeProperties(node5, nodename.append(" Vec1"));
}
case 2:
{
SetDefaultNodeProperties(node5, nodename.append(" Vec2"));
}
default:
{
SetDefaultNodeProperties(node5, nodename.append(" Vecn"));
}
}
node5->SetProperty( "IsDirectionVolume", mitk::BoolProperty::New( true ) );
node5->SetProperty( "NormalizeVecs", mitk::BoolProperty::New( true ) );
node5->SetProperty( "Scale", mitk::FloatProperty::New( 0.8 ) );
node5->SetProperty( "LineWidth", mitk::FloatProperty::New( 3 ) );
mitk::VectorImageMapper2D::Pointer vecMapper5 =
mitk::VectorImageMapper2D::New();
node5->SetMapper(1,vecMapper5);
m_DataTreeIterator->GetTree()->Modified();
this->GetRenderWindowPart()->RequestUpdate();
TreeChanged();
m_Controls->update();
}
void QmitkDiffusionTensorEstimation::OdfStandardAlgorithmsDeconvolutionButton()
{
itk::TimeProbe clock;
QString status;
const mitk::DataTreeFilter::Item* item
= m_OdfVolumesDataTreeFilter->GetSelectedItem();
if(!item)return;
typedef itk::Vector<TTensorPixelType,odfsize> OdfVectorType;
typedef itk::Image<OdfVectorType,3> OdfVectorImgType;
mitk::Image* vol =
static_cast<mitk::Image*>(item->GetNode()->GetData());
OdfVectorImgType::Pointer itkvol = OdfVectorImgType::New();
mitk::CastToItkImage<OdfVectorImgType>(vol, itkvol);
std::string nodename = item->GetProperty("name");
clock.Start();
MBI_INFO << "Computing Diffusion Direction ";
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf(
"Computing Diffusion Direction for %s", nodename.c_str()));
typedef itk::DiffusionOdfGeneralizedFaImageFilter<TTensorPixelType,TTensorPixelType,odfsize>
GfaFilterType;
GfaFilterType::Pointer gfaFilter = GfaFilterType::New();
gfaFilter->SetInput(itkvol);
gfaFilter->SetNumberOfThreads(4);
gfaFilter->Update();
itk::ImageRegionIterator<GfaFilterType::OutputImageType>
itGfa (gfaFilter->GetOutput(),
gfaFilter->GetOutput()->GetLargestPossibleRegion() );
itGfa = itGfa.Begin();
int numdirs = m_Controls->m_OdfStandardAlgorithmsDeconvolutionSpinbox->value();
//vnl_matrix_fixed<double, nrconvkernels, odfsize>* kernels
// = new vnl_matrix_fixed<double, nrconvkernels, odfsize>();
//itk::ImageRegionIterator<OdfVectorImgType> inIt(itkvol, itkvol->GetLargestPossibleRegion());
//inIt.GoToBegin();
//for(int i=0; i<nrconvkernels; i++)
//{
// OdfVectorImgType::PixelType vec = inIt.Get();
// for(int j=0; j<odfsize; j++)
// {
// (*kernels)(i,j) = vec[j];
// }
// ++inIt;
//}
typedef itk::DiffusionOdfSphericalDeconvolutionImageFilter<TTensorPixelType,TTensorPixelType,odfsize,nrconvkernels>
DeconvolutionFilterType;
DeconvolutionFilterType::Pointer devonvolutionFilter
= DeconvolutionFilterType::New();
devonvolutionFilter->SetFractionalThreshold(m_Controls->m_OdfStandardAlgorithmsDeconvolutionThreshEdit->text().toFloat());
if(!m_Controls->m_OdfStandardAlgorithmsDeconvolutionAngResThresholdEdit->text().contains(QString("NaN")))
{
float angRes = m_Controls->m_OdfStandardAlgorithmsDeconvolutionAngResThresholdEdit->text().toFloat();
angRes /= 360/itk::Math::pi;
devonvolutionFilter->SetAngularResolutionThreshold(angRes);
}
devonvolutionFilter->SetSamplingQuantileStart(m_Controls->m_OdfStandardAlgorithmsDeconvQuantStart->text().toFloat());
devonvolutionFilter->SetSamplingQuantileStep(m_Controls->m_OdfStandardAlgorithmsDeconvQuantStep->text().toFloat());
devonvolutionFilter->SetMinimumNumberOfSamples(m_Controls->m_OdfStandardAlgorithmsDeconvQuantMinNr->text().toInt());
devonvolutionFilter->SetIterateQuantiles(m_Controls->m_OdfStandardAlgorithmsDeconvQuantMulti->isChecked());
devonvolutionFilter->SetNrDirectionsToExtract(numdirs);
devonvolutionFilter->SetInput(itkvol);
devonvolutionFilter->SetNumberOfThreads(m_Controls->m_OdfStandardAlgorithmsDeconvNumberThreadsSpinbox->value());
devonvolutionFilter->SetGfaImage(gfaFilter->GetOutput());
//devonvolutionFilter->SetPresetConvolutionKernels(kernels);
devonvolutionFilter->Update();
for(int i=0; i<numdirs; i++)
{
itk::ImageRegionIterator<DeconvolutionFilterType::OutputImageType>
it (devonvolutionFilter->GetOutput(i),
devonvolutionFilter->GetOutput()->GetLargestPossibleRegion() );
it = it.Begin();
if(i==0)
{
MBI_INFO << "Converting to RGB";
typedef itk::Image<itk::RGBPixel<uchar>, 3> VecImgType;
VecImgType::Pointer vecImg = VecImgType::New();
vecImg->SetSpacing( itkvol->GetSpacing() ); // Set the image spacing
vecImg->SetOrigin( itkvol->GetOrigin() ); // Set the image origin
vecImg->SetDirection( itkvol->GetDirection() ); // Set the image direction
vecImg->SetLargestPossibleRegion( itkvol->GetLargestPossibleRegion());
vecImg->SetBufferedRegion( vecImg->GetLargestPossibleRegion() );
vecImg->Allocate();
itk::ImageRegionIterator<VecImgType> ot (vecImg, vecImg->GetLargestPossibleRegion() );
ot = ot.Begin();
typedef DeconvolutionFilterType::OutputImageType::PixelType VecPixType;
for (it = it.Begin(); !it.IsAtEnd(); ++it)
{
VecPixType vec = it.Get();
vnl_vector_fixed<TTensorPixelType, 3> vnlvec = vec.GetVnlVector();
TTensorPixelType len = vnlvec.two_norm();
vnlvec = vnlvec.normalize();
itk::RGBPixel<uchar> pix;
vnlvec*=200*itGfa.Get();
vnlvec[0] = abs(vnlvec[0]);
vnlvec[1] = abs(vnlvec[1]);
vnlvec[2] = abs(vnlvec[2]);
if(vnlvec[0] > 255 || vnlvec[1] > 255 || vnlvec[2] > 255)
{
//should never get in here
double max = vnlvec[0];
max = max<vnlvec[1] ? vnlvec[1] : max;
max = max<vnlvec[2] ? vnlvec[2] : max;
vnlvec /= max/255;
}
uchar uvec[3] = {(uchar)(vnlvec[0]),(uchar)(vnlvec[1]),(uchar)(vnlvec[2])};
pix = uvec;
ot.Set(pix);
++ot;
++itGfa;
}
// RGB TO DATATREE
mitk::Image::Pointer image2 = mitk::Image::New();
image2->InitializeByItk( vecImg.GetPointer() );
image2->SetVolume( vecImg->GetBufferPointer() );
mitk::DataNode::Pointer node2=mitk::DataNode::New();
node2->SetData( image2 );
mitk::DataStorage::GetInstance()->Add(node2);
switch(i)
{
case 0:
{
SetDefaultNodeProperties(node2, nodename.append(" PD0"));
break;
}
case 1:
{
SetDefaultNodeProperties(node2, nodename.append(" PD1"));
break;
}
case 2:
{
SetDefaultNodeProperties(node2, nodename.append(" PD2"));
break;
}
default:
{
SetDefaultNodeProperties(node2, nodename.append(" PDn"));
break;
}
}
node2->SetProperty( "IsRGBVolume", mitk::BoolProperty::New( true ) );
}
// VECTORFIELD
MBI_INFO << "Converting to Vectorfield";
typedef itk::Image<itk::Vector<TTensorPixelType,3>, 3> VecImgType2;
VecImgType2::Pointer vecImg5 = VecImgType2::New();
vecImg5->SetSpacing( itkvol->GetSpacing() ); // Set the image spacing
vecImg5->SetOrigin( itkvol->GetOrigin() ); // Set the image origin
vecImg5->SetDirection( itkvol->GetDirection() ); // Set the image direction
vecImg5->SetLargestPossibleRegion( itkvol->GetLargestPossibleRegion());
vecImg5->SetBufferedRegion( vecImg5->GetLargestPossibleRegion() );
vecImg5->Allocate();
itk::ImageRegionIterator<VecImgType2> ot5 (vecImg5, vecImg5->GetLargestPossibleRegion() );
ot5 = ot5.Begin();
typedef DeconvolutionFilterType::OutputImageType::PixelType VecPixType;
for (it = it.Begin(); !it.IsAtEnd(); ++it)
{
VecPixType vec = it.Get();
vnl_vector_fixed<TTensorPixelType, 3> vnlvec = vec.GetVnlVector();
vnlvec = vnlvec.normalize();
itk::Vector<TTensorPixelType,3> pix;
TTensorPixelType uvec[3] = {(TTensorPixelType)(vnlvec[0]),(TTensorPixelType)(vnlvec[1]),(TTensorPixelType)(vnlvec[2])};
pix = uvec;
ot5.Set(pix);
++ot5;
}
// Vectors TO DATATREE
mitk::Image::Pointer image5 = mitk::Image::New();
image5->InitializeByItk( vecImg5.GetPointer() );
image5->SetVolume( vecImg5->GetBufferPointer() );
mitk::DataNode::Pointer node5=mitk::DataNode::New();
node5->SetData( image5 );
mitk::DataStorage::GetInstance()->Add(node5);
switch(i)
{
case 0:
{
SetDefaultNodeProperties(node5, nodename.append(" Vec0"));
break;
}
case 1:
{
SetDefaultNodeProperties(node5, nodename.append(" Vec1"));
break;
}
case 2:
{
SetDefaultNodeProperties(node5, nodename.append(" Vec2"));
break;
}
default:
{
SetDefaultNodeProperties(node5, nodename.append(" Vecn"));
break;
}
}
node5->SetProperty( "IsDirectionVolume", mitk::BoolProperty::New( true ) );
node5->SetProperty( "NormalizeVecs", mitk::BoolProperty::New( true ) );
node5->SetProperty( "Scale", mitk::FloatProperty::New( 0.8 ) );
node5->SetProperty( "LineWidth", mitk::FloatProperty::New( 3 ) );
mitk::VectorImageMapper2D::Pointer vecMapper5 =
mitk::VectorImageMapper2D::New();
node5->SetMapper(1,vecMapper5);
}
m_DataTreeIterator->GetTree()->Modified();
this->GetRenderWindowPart()->RequestUpdate();
TreeChanged();
m_Controls->update();
}
void QmitkDiffusionTensorEstimation::SetDefaultNodeProperties(mitk::DataNode::Pointer node, std::string name)
{
node->SetProperty( "volumerendering", mitk::BoolProperty::New( false ) );
node->SetProperty( "use color", mitk::BoolProperty::New( true ) );
node->SetProperty( "texture interpolation", mitk::BoolProperty::New( true ) );
node->SetProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New() );
node->SetProperty( "layer", mitk::IntProperty::New(0));
node->SetProperty( "in plane resample extent by geometry", mitk::BoolProperty::New( false ) );
node->SetOpacity(1.0f);
node->SetColor(1.0,1.0,1.0);
node->SetVisibility(true);
mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New();
mitk::LevelWindow levelwindow;
// levelwindow.SetAuto( image );
levWinProp->SetLevelWindow( levelwindow );
node->GetPropertyList()->SetProperty( "levelwindow", levWinProp );
// add a default rainbow lookup table for color mapping
if(!node->GetProperty("LookupTable"))
{
mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New();
vtkLookupTable* vtkLut = mitkLut->GetVtkLookupTable();
vtkLut->SetHueRange(0.6667, 0.0);
vtkLut->SetTableRange(0.0, 20.0);
vtkLut->Build();
mitk::LookupTableProperty::Pointer mitkLutProp = mitk::LookupTableProperty::New();
mitkLutProp->SetLookupTable(mitkLut);
node->SetProperty( "LookupTable", mitkLutProp );
}
if(!node->GetProperty("binary"))
node->SetProperty( "binary", mitk::BoolProperty::New( false ) );
// add a default transfer function
mitk::TransferFunction::Pointer tf = mitk::TransferFunction::New();
node->SetProperty ( "TransferFunction", mitk::TransferFunctionProperty::New ( tf.GetPointer() ) );
// set foldername as string property
mitk::StringProperty::Pointer nameProp = mitk::StringProperty::New( name );
node->SetProperty( "name", nameProp );
}
void QmitkDiffusionTensorEstimation::DirectionVolumesAngularErrorButton()
{
try
{
const mitk::DataTreeFilter::ItemSet* selectedItems
= m_DirectionVolumesDataTreeFilter->GetSelectedItems();
int nrFiles = selectedItems->size();
if (nrFiles != 2) return;
mitk::DataTreeFilter::ItemSet::const_iterator itemiter( selectedItems->begin() );
mitk::Image::Pointer vol1 =
static_cast<mitk::Image*>((*itemiter)->GetNode()->GetData());
if( !vol1)return;
std::string nodename1 = (*itemiter)->GetProperty("name");
itemiter++;
mitk::Image::Pointer vol2 =
static_cast<mitk::Image*>((*itemiter)->GetNode()->GetData());
if( !vol2)return;
std::string nodename2 = (*itemiter)->GetProperty("name");
typedef itk::Image<itk::Vector<TTensorPixelType,3>,3 > IType;
IType::Pointer itkVol1 = IType::New();
mitk::CastToItkImage<IType>(vol1, itkVol1);
IType::Pointer itkVol2 = IType::New();
mitk::CastToItkImage<IType>(vol2, itkVol2);
typedef itk::VectorImagesAngularErrorImageFilter<TTensorPixelType,3> FilterType;
FilterType::Pointer filter = FilterType::New();
filter->SetInput(itkVol1);
filter->SetImage2(itkVol2.GetPointer());
filter->SetNumberOfThreads(4);
filter->Update();
// Angluar Error TO DATATREE
mitk::Image::Pointer image = mitk::Image::New();
image->InitializeByItk( filter->GetOutput() );
image->SetVolume( filter->GetOutput()->GetBufferPointer() );
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( image );
mitk::DataStorage::GetInstance()->Add(node);
SetDefaultNodeProperties(node, nodename1.append(" ").append(nodename2).append(" ERR"));
node->SetProperty( "IsErrorVolume", mitk::BoolProperty::New( true ) );
TreeChanged();
m_Controls->update();
QString status;
mitk::StatusBar::GetInstance()->DisplayText(status.sprintf("Finished computing Angular Error"));
}
catch (itk::ExceptionObject &ex)
{
MBI_INFO << ex;
return ;
}
}
//void QmitkDiffusionTensorEstimation::DwiStandardAlgorithmsGFAButton()
//{
//
// itk::TimeProbe clock;
// QString status;
// const mitk::DataTreeFilter::Item* item
// = m_DiffusionVolumesDataTreeFilter->GetSelectedItem();
// if(!item)return;
//
// typedef itk::Vector<TTensorPixelType,odfsize> OdfVectorType;
// typedef itk::Image<OdfVectorType,3> OdfVectorImgType;
// mitk::Image* vol =
// static_cast<mitk::Image*>(item->GetNode()->GetData());
// OdfVectorImgType::Pointer itkvol = OdfVectorImgType::New();
// mitk::CastToItkImage<OdfVectorImgType>(vol, itkvol);
// std::string nodename = item->GetProperty("name");
//
// // COMPUTE RA
// clock.Start();
// std::cout << "Computing GFA ";
// mitk::StatusBar::GetInstance()->DisplayText(status.sprintf(
// "Computing GFA for %s", nodename.c_str()));
// typedef OdfVectorType::ValueType RealValueType;
// typedef itk::Image< RealValueType, 3 > RAImageType;
// typedef itk::DiffusionOdfGeneralizedFaImageFilter<TTensorPixelType,TTensorPixelType,odfsize>
// GfaFilterType;
// GfaFilterType::Pointer gfaFilter = GfaFilterType::New();
// gfaFilter->SetInput(itkvol);
// gfaFilter->SetNumberOfThreads(4);
// switch(m_Controls->m_OdfStandardAlgorithmsGFAMethodSpinbox->value())
// {
// case 1:
// {
// gfaFilter->SetComputationMethod(GfaFilterType::STANDARD);
// break;
// }
// case 2:
// {
// gfaFilter->SetComputationMethod(GfaFilterType::QUANTILES_HIGH_LOW);
// break;
// }
// case 3:
// {
// gfaFilter->SetComputationMethod(GfaFilterType::QUANTILES_MIDDLE);
// break;
// }
// case 4:
// {
// gfaFilter->SetComputationMethod(GfaFilterType::MAX_ODF_VALUE);
// break;
// }
// case 5:
// {
// gfaFilter->SetComputationMethod(GfaFilterType::DECONVOLUTION_COEFFS);
// break;
// }
// default:
// {
// gfaFilter->SetComputationMethod(GfaFilterType::STANDARD);
// }
// }
// gfaFilter->Update();
// clock.Stop();
// std::cout << "took " << clock.GetMeanTime() << "s." << std::endl;
//
// typedef itk::Image<TTensorPixelType, 3> ImgType;
// ImgType::Pointer img = ImgType::New();
// img->SetSpacing( gfaFilter->GetOutput()->GetSpacing() ); // Set the image spacing
// img->SetOrigin( gfaFilter->GetOutput()->GetOrigin() ); // Set the image origin
// img->SetDirection( gfaFilter->GetOutput()->GetDirection() ); // Set the image direction
// img->SetLargestPossibleRegion( gfaFilter->GetOutput()->GetLargestPossibleRegion());
// img->SetBufferedRegion( gfaFilter->GetOutput()->GetLargestPossibleRegion() );
// img->Allocate();
// itk::ImageRegionIterator<ImgType> ot (img, img->GetLargestPossibleRegion() );
// ot = ot.Begin();
// itk::ImageRegionConstIterator<GfaFilterType::OutputImageType> it
// (gfaFilter->GetOutput(), gfaFilter->GetOutput()->GetLargestPossibleRegion() );
// it = it.Begin();
//
// for (it = it.Begin(); !it.IsAtEnd(); ++it)
// {
// GfaFilterType::OutputImageType::PixelType val = it.Get();
// ot.Set(val * 200);
// ++ot;
// }
//
//
// // GFA TO DATATREE
// mitk::Image::Pointer image = mitk::Image::New();
// image->InitializeByItk( img.GetPointer() );
// image->SetVolume( img->GetBufferPointer() );
// mitk::DataNode::Pointer node=mitk::DataNode::New();
// node->SetData( image );
// mitk::DataStorage::GetInstance()->Add(node);
// SetDefaultNodeProperties(node, nodename.append(" GFA"));
// node->SetProperty( "IsGFAVolume", mitk::BoolProperty::New( true ) );
//
// mitk::StatusBar::GetInstance()->DisplayText("Computation complete.");
//
// m_DataTreeIterator->GetTree()->Modified();
// this->GetRenderWindowPart()->RequestUpdate();
// TreeChanged();
// m_Controls->update();
//
//}
void QmitkDiffusionTensorEstimation::DiffusionVolumeSaveButton()
{
// GET SELECTED ITEM
const mitk::DataTreeFilter::Item* selectedItem
= m_DiffusionVolumesDataTreeFilter->GetSelectedItem();
if( !selectedItem )
return;
mitk::DiffusionVolumes<DiffusionPixelType>::Pointer diffVolumes =
static_cast<mitk::DiffusionVolumes<DiffusionPixelType>*>(selectedItem->GetNode()->GetData());
std::string sName = selectedItem->GetNode()->GetName();
QString qName;
qName.sprintf("%s.nhdr",sName.c_str());
// SELECT FILE DIALOG
//QFileDialog::getSaveFileName()
//QFileDialog* w = new QFileDialog( this->m_Controls, "Select Nrrd Outputfile", TRUE );
//w->setMode( QFileDialog::AnyFile );
//w->setFilter( "Nrrd Images (*.nrrd *.nhdr)" );
//w->setName(qName);
//if ( w->exec() != QDialog::Accepted )
// return;
//QString filename = w->selectedFile();
QString filename = QFileDialog::getSaveFileName(
qName,
"Nrrd Images (*.nrrd *.nhdr)",
this->m_Controls,
"save file dialog",
"Select Nrrd Outputfile" );
if ( !filename )
return;
// WRITING DWIs TO NRRD VOLUME
typedef mitk::NrrdDiffusionVolumesWriter<DiffusionImageType> WriterType;
WriterType::Pointer nrrdWriter = WriterType::New();
nrrdWriter->SetInput( diffVolumes->GetImage() );
nrrdWriter->SetDirections(diffVolumes->GetDirections());
nrrdWriter->SetB_Value(diffVolumes->GetB_Value());
nrrdWriter->SetFileName(filename.ascii());
try
{
nrrdWriter->Update();
}
catch (const itk::ExceptionObject& e)
{
MBI_INFO << e;
}
}
void QmitkDiffusionTensorEstimation::DiffusionVolumesLoadButton()
{
// SELECT FOLDER DIALOG
QFileDialog* w = new QFileDialog( this->m_Controls, "Select DWI data file", TRUE );
w->setMode( QFileDialog::ExistingFiles );
w->setFilter( "Nrrd Images (*.nrrd *.nhdr)" );
// RETRIEVE SELECTION
if ( w->exec() != QDialog::Accepted )
return;
QStringList filenames = w->selectedFiles();
QStringList::Iterator it = filenames.begin();
while( it != filenames.end() ) {
std::string filename = ( *it ).ascii();
++it;
// READING NRRD DWI VOLUMES
typedef mitk::NrrdDiffusionVolumesReader<DiffusionImageType> ReaderType;
ReaderType::Pointer nrrdReader = ReaderType::New();
nrrdReader->SetFileName(filename);
try
{
nrrdReader->Update();
// DWI TO DATATREE
typedef mitk::DiffusionVolumes<DiffusionPixelType> DiffVolumesType;
DiffVolumesType::Pointer diffVolumes = DiffVolumesType::New();
diffVolumes->SetDirections(nrrdReader->GetDiffusionVectors());
diffVolumes->SetB_Value(nrrdReader->GetB_Value());
diffVolumes->SetImage(nrrdReader->GetOutput());
mitk::DataNode::Pointer node=mitk::DataNode::New();
node->SetData( diffVolumes );
mitk::DataStorage::GetInstance()->Add(node);
SetDefaultNodeProperties(node, itksys::SystemTools::GetFilenameName(filename));
TreeChanged();
}
catch (const itk::ExceptionObject& e)
{
MBI_INFO << e;
}
}
}
void QmitkDiffusionTensorEstimation::DiffusionVolumesRemoveButton()
{
m_DiffusionVolumesDataTreeFilter->DeleteSelectedItems();
}
void QmitkDiffusionTensorEstimation::DiffusionVolumesSelectAll()
{
const mitk::DataTreeFilter::ItemList* items = m_DiffusionVolumesDataTreeFilter->GetItems();
mitk::DataTreeFilter::ConstItemIterator itemiter( items->Begin() );
mitk::DataTreeFilter::ConstItemIterator itemiterend( items->End() );
while ( itemiter != itemiterend )
{
m_DiffusionVolumesDataTreeFilter->SelectItem(*itemiter);
++itemiter;
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/deprecated/QmitkDiffusionTensorEstimation.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/deprecated/QmitkDiffusionTensorEstimation.h
index 721a3a8..1fe3f2f 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/deprecated/QmitkDiffusionTensorEstimation.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/deprecated/QmitkDiffusionTensorEstimation.h
@@ -1,158 +1,158 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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.
===================================================================*/
#if !defined(QmitkDiffusionTensorEstimation_H__INCLUDED)
#define QmitkDiffusionTensorEstimation_H__INCLUDED
#include <QmitkAbstractView.h>
#include <mitkILifecycleAwarePart.h>
#include "mitkDiffusionVolumes.h"
class QmitkDiffusionTensorEstimationControls;
typedef short DiffusionPixelType;
/*!
\brief QmitkDiffusionTensorEstimation
One needs to reimplement the methods CreateControlWidget(..),
and CreateAction(..).
*/
class QmitkDiffusionTensorEstimation : public QmitkAbstractView, public mitk::ILifecycleAwarePart
{
Q_OBJECT
public:
/*!
\brief default constructor
*/
QmitkDiffusionTensorEstimation(QObject *parent=0, const char *name=0, mitk::DataTreeIteratorBase* dataIt = nullptr);
/*!
\brief default destructor
*/
virtual ~QmitkDiffusionTensorEstimation();
/*!
\brief method for creating the widget containing the application controls, like sliders, buttons etc.
*/
virtual QWidget * CreateControlWidget(QWidget *parent);
/*!
\brief method for creating the connections of main and control widget
*/
virtual void CreateConnections();
///
/// Sets the focus to an internal widget.
///
virtual void SetFocus() override;
/*!
\brief method for creating an QAction object, i.e. button & menu entry @param parent the parent QWidget
*/
virtual QAction * CreateAction(QActionGroup *parent);
virtual void Activated() override;
virtual void Deactivated() override;
virtual void Visible() override;
virtual void Hidden() override;
protected slots:
void TreeChanged();
void TensorVolumesSaveButton();
void TensorVolumesLoadButton();
void TensorVolumesRemoveButton();
void OdfVolumesSaveButton();
void OdfVolumesLoadButton();
void OdfVolumesRemoveButton();
void DirectionVolumesSaveButton();
void DirectionVolumesLoadButton();
void DirectionVolumesRemoveButton();
void DirectionVolumesAngularErrorButton();
void TensorEstimationTeemEstimateButton();
void OdfReconstructionButton();
void OdfReconstructionAnalyticalButton();
void TensorEstimationButton();
void StandardAlgorithmsFAButton();
void StandardAlgorithmsRAButton();
void StandardAlgorithmsDirectionButton();
void OdfStandardAlgorithmsDirectionButton();
void OdfStandardAlgorithmsDeconvolutionButton();
void OdfStandardAlgorithmsGFAButton();
void OdfVolumesVisualizeSelectedButton();
void DiffusionVolumeSaveButton();
void DiffusionVolumesLoadButton();
void DiffusionVolumesRemoveButton();
void DiffusionVolumesSelectAll();
//void DwiStandardAlgorithmsGFAButton();
void SetDefaultNodeProperties(mitk::DataNode::Pointer node, std::string name);
protected:
/*!
* controls containing sliders for scrolling through the slices
*/
QmitkDiffusionTensorEstimationControls * m_Controls;
mitk::DataTreeFilter::Pointer m_DiffusionVolumesDataTreeFilter;
mitk::DataTreeFilter::Pointer m_TensorVolumesDataTreeFilter;
mitk::DataTreeFilter::Pointer m_OdfVolumesDataTreeFilter;
mitk::DataTreeFilter::Pointer m_DirectionVolumesDataTreeFilter;
bool m_FilterInitialized;
static const int odfsize;
static const int nrconvkernels;
template<int L>
void ReconstructAnalytically(mitk::DiffusionVolumes<DiffusionPixelType>* vols,
float lambda, std::string nodename, std::vector<mitk::DataNode::Pointer>* nodes);
};
#endif // !defined(QmitkDiffusionTensorEstimation_H__INCLUDED)
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/deprecated/QmitkDiffusionTensorIcon.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/deprecated/QmitkDiffusionTensorIcon.h
index bc02fef..403209c 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/deprecated/QmitkDiffusionTensorIcon.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/deprecated/QmitkDiffusionTensorIcon.h
@@ -1,109 +1,109 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 _QEMBED_1804289383
#define _QEMBED_1804289383
#include <qimage.h>
#include <qdict.h>
static const QRgb QmitkDiffusionTensorEstimation_data[] = {
0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,
0x3aaff00,0x3aaff00,0x3c001eea,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,
0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x1a0a1d00,0x611a1800,0x8c311200,0x883c000d,0x55300051,
0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,
0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x621a1700,0xdd171200,0xfe341600,0xfe6b1400,0xf9960d00,0xf6b21600,0x6eb01000,0x3aaff00,0x3aaff00,
0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x1ace0014,0x27d10d00,0x3aaff00,0x3aaff00,
0x3aaff00,0x8a110f00,0xf40d0f00,0xf7341400,0xef6b0f00,0xf19d1200,0xf3c51200,0xf2e60c00,0xefe91000,0x40c70c00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,
0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3fca0c00,0x3aaff00,0x3aaff00,0x81121000,0xfb0f1100,0xf1251100,
0xf05b1000,0xf38c1600,0xf2b80e00,0xf6df1800,0xedfc0400,0xf5ff1400,0xb3f41100,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,
0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x35f10e00,0x561b1800,0xf40d0f00,0xf0181000,0xee451000,0xef761100,0xeea30c00,0xeece0a00,
0xdef40e00,0xd7ff1400,0xf5ff1400,0xebfd1700,0x1ded2300,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,
0x3aaff00,0x3aaff00,0x3aaff00,0x38760e00,0xe51a1000,0xf6131400,0xf2331200,0xf4651300,0xf38c1600,0xf5b31700,0xffd11a11,0xfff52d21,0xffff3928,0xffff1d0a,
0xf5ff1400,0x44ec1a00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,
0x86110f00,0xfa0e1100,0xee190f00,0xf24d1100,0xf0751100,0xf19d1200,0xf6c30f00,0xffdf1e12,0xffff5749,0xffff6f5f,0xffff2016,0xf5ff1400,0x55fc0f00,0x3aaff00,
0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x23071600,0xe7121300,0xf6131400,0xf2331200,
0xef5c1000,0xee850e00,0xf1a91400,0xeece0a00,0xffee251c,0xfffe8272,0xfffe9080,0xffff2d1f,0xf5ff1400,0x5fff1500,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,
0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x7a131100,0xfb0f1100,0xee190f00,0xef430f00,0xee6b0f00,0xef911000,0xf4b41700,
0xf3d41600,0xfff62f22,0xffff8575,0xffff7d6b,0xffff2016,0xf5ff1400,0x47ff0700,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,
0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0xc70e1200,0xfc161600,0xef251000,0xee510e00,0xee7a0c00,0xf19d1200,0xf0bb1000,0xeddd0d00,0xfffa3325,0xfffe6d5d,
0xffff5543,0xffff2016,0xf5ff1400,0x35f10e00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,
0x2e270600,0xf0111200,0xf2151100,0xf0361000,0xed600c00,0xee850e00,0xf4a71500,0xf3c51200,0xf4e40b00,0xffff2d1f,0xffff4639,0xffff3021,0xffff1d0a,0xe0ff1000,
0x9c61c00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x5339900,0x1000df10,0x180bd400,0x70093b00,0xf9101700,0xf0181000,
0xef430f00,0xef6b0f00,0xf1900f00,0xefae0e00,0xeece0a00,0xefe91000,0xeaff0a00,0xe9ff0b00,0xf5ff1400,0xf5ff1400,0xcbf11d00,0x3912ce00,0x3912ce00,0x3912ce00,
0x3005c500,0x3812d100,0x3c00d50d,0x3005c500,0x2e06d300,0x2e06d300,0x2e06d300,0x2c06dc00,0x9e0d3f00,0xf70b1700,0xf1251100,0xef4e1100,0xf0751100,0xf39a1100,
0xf3b80e00,0xf6d01400,0xefe91000,0xeaff0a00,0xf5ff1400,0xf5ff1400,0xf5ff1400,0x7ef71000,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,
0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0xa90c0c00,0xf70d1100,0xf32f1400,0xf15b1000,0xf2801200,0xf09d1200,0xf0bb1000,0xf1d80800,0xefe91000,
0xf5ff1400,0xf5ff1400,0xf5ff1400,0xf5ff1400,0x2ffa1b00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,
0x3aaff00,0x3aaff00,0xb9151100,0xfc161600,0xef361000,0xf2651200,0xee850e00,0xf4a71500,0xf4c41100,0xeedc0c00,0xf5f10f00,0xf5ff1400,0xf5ff1400,0xf5ff1400,
0xb6ff1400,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0xb8151100,
0xfa181400,0xf2401300,0xef6a0e00,0xf28e0f00,0xf0ad0d00,0xf3c51200,0xf6df1800,0xf4f21100,0xf5ff1400,0xf5ff1400,0xf5ff1400,0x45fb1200,0x3aaff00,0x3aaff00,
0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0xa4191400,0xfd1a1500,0xef430f00,0xf3701500,
0xef911000,0xefae0e00,0xeece0a00,0xf6df1800,0xf4f21100,0xf0fa0100,0xfcfa0c00,0xa7f91200,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,
0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x7c131000,0xff1b1600,0xf54a1600,0xf1741100,0xf49a1100,0xf4b41700,0xeece0a00,
0xf2e60c00,0xf4f21100,0xf5ff1400,0xeaf10400,0x27f80007,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,
0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x37050e00,0xf2151100,0xf54a1600,0xf0751100,0xf29b1200,0xf2b80e00,0xf6d01400,0xf2e60c00,0xf5f10f00,0xf1f51200,
0x68f00c00,0x2cb90600,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,
0x3aaff00,0x3aaff00,0xb4171200,0xfb421100,0xf0751100,0xf29b1200,0xf1b90f00,0xf6d01400,0xf4e40b00,0xfce91a00,0x66eb1400,0x3aaff00,0x31c60005,0x1ace0014,
0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x2b061200,
0xd8321100,0xfa6f0e00,0xf7970e00,0xf5b50b00,0xfbcc0f00,0xdbd91500,0x50d20d00,0x3aaff00,0x3aaff00,0x3aaff00,0x3fca0c00,0x3aaff00,0x3aaff00,0x3aaff00,
0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x23330700,0xa3430010,0xbc890e00,
0xbaaa1600,0x6dbd0c00,0x1bd03900,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x21d11700,0x2ed30006,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,
0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x56600cc,0x2b002af9,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,
0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x37cc0009,0xab31900,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,
0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x2d0600d2,0x18002adf,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,
0x3aaff00,0x3aaff00,0xeed0000,0x3cd50d00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00,0x3aaff00
};
/* Generated by qembed */
static struct EmbedImage {
int width, height, depth;
const unsigned char *data;
int numColors;
const QRgb *colorTable;
bool alpha;
const char *name;
} embed_image_vec[] = {
{ 25, 25, 32, (const unsigned char*)QmitkDiffusionTensorEstimation_data, 0, 0, TRUE, "QmitkDiffusionTensorEstimation" },
{ 0, 0, 0, 0, 0, 0, 0, 0 }
};
static const QImage& qembed_findImage( const QString& name )
{
static QDict<QImage> dict;
QImage* img = dict.find( name );
if ( !img ) {
for ( int i = 0; embed_image_vec[i].data; i++ ) {
if ( strcmp(embed_image_vec[i].name, name.latin1()) == 0 ) {
img = new QImage((uchar*)embed_image_vec[i].data,
embed_image_vec[i].width,
embed_image_vec[i].height,
embed_image_vec[i].depth,
(QRgb*)embed_image_vec[i].colorTable,
embed_image_vec[i].numColors,
QImage::BigEndian );
if ( embed_image_vec[i].alpha )
img->setAlphaBuffer( TRUE );
dict.insert( name, img );
break;
}
}
if ( !img ) {
static QImage dummy;
return dummy;
}
}
return *img;
}
#endif
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.cpp
index 3e13de1..4c5ab45 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.cpp
@@ -1,78 +1,78 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "mitkPluginActivator.h"
#include "src/internal/Perspectives/QmitkDiffusionDefaultPerspective.h"
#include "src/internal/Perspectives/QmitkSegmentationPerspective.h"
#include "src/internal/QmitkDiffusionDicomImportView.h"
#include "src/internal/QmitkDicomTractogramTagEditorView.h"
#include "src/internal/QmitkControlVisualizationPropertiesView.h"
#include "QmitkNodeDescriptorManager.h"
#include "mitkNodePredicateDataType.h"
#include "mitkNodePredicateProperty.h"
#include "mitkNodePredicateIsDWI.h"
#include <mitkDiffusionPropertyHelper.h>
namespace mitk {
void PluginActivator::start(ctkPluginContext* context)
{
BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionDefaultPerspective, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkSegmentationPerspective, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionDicomImport, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkDicomTractogramTagEditorView, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkControlVisualizationPropertiesView, context)
// Q_UNUSED(context)
QmitkNodeDescriptorManager* manager = QmitkNodeDescriptorManager::GetInstance();
mitk::NodePredicateIsDWI::Pointer isDiffusionImage = mitk::NodePredicateIsDWI::New();
QmitkNodeDescriptor* desc = new QmitkNodeDescriptor(QObject::tr("DiffusionImage"), QString(":/QmitkDiffusionImaging/DiffData24.png"), isDiffusionImage, manager);
manager->AddDescriptor(desc);
mitk::NodePredicateDataType::Pointer isTensorImage = mitk::NodePredicateDataType::New("TensorImage");
manager->AddDescriptor(new QmitkNodeDescriptor(QObject::tr("TensorImage"), QString(":/QmitkDiffusionImaging/tensor.png"), isTensorImage, manager));
mitk::NodePredicateDataType::Pointer isOdfImage = mitk::NodePredicateDataType::New("OdfImage");
manager->AddDescriptor(new QmitkNodeDescriptor(QObject::tr("OdfImage"), QString(":/QmitkDiffusionImaging/odf.png"), isOdfImage, manager));
mitk::NodePredicateDataType::Pointer isShImage = mitk::NodePredicateDataType::New("ShImage");
manager->AddDescriptor(new QmitkNodeDescriptor(QObject::tr("ShImage"), QString(":/QmitkDiffusionImaging/sh.png"), isShImage, manager));
mitk::NodePredicateDataType::Pointer isFiberBundle = mitk::NodePredicateDataType::New("FiberBundle");
manager->AddDescriptor(new QmitkNodeDescriptor(QObject::tr("FiberBundle"), QString(":/QmitkDiffusionImaging/tractogram.png"), isFiberBundle, manager));
mitk::NodePredicateDataType::Pointer isPeakImage = mitk::NodePredicateDataType::New("PeakImage");
manager->AddDescriptor(new QmitkNodeDescriptor(QObject::tr("PeakImage"), QString(":/QmitkDiffusionImaging/odf_peaks.png"), isPeakImage, manager));
mitk::NodePredicateDataType::Pointer isConnectomicsNetwork = mitk::NodePredicateDataType::New("ConnectomicsNetwork");
manager->AddDescriptor(new QmitkNodeDescriptor(QObject::tr("ConnectomicsNetwork"), QString(":/QmitkDiffusionImaging/ConnectomicsNetwork.png"), isConnectomicsNetwork, manager));
mitk::NodePredicateDataType::Pointer isTractographyForestNetwork = mitk::NodePredicateDataType::New("TractographyForest");
manager->AddDescriptor(new QmitkNodeDescriptor(QObject::tr("TractographyForest"), QString(":/QmitkDiffusionImaging/ml_tractogram.png"), isTractographyForestNetwork, manager));
}
void PluginActivator::stop(ctkPluginContext* context)
{
Q_UNUSED(context)
}
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.h
index ad2e7cb..7a2c3e5 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/mitkPluginActivator.h
@@ -1,39 +1,39 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 MITKPLUGINACTIVATOR_H
#define MITKPLUGINACTIVATOR_H
#include <ctkPluginActivator.h>
namespace mitk {
class PluginActivator :
public QObject, public ctkPluginActivator
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_diffusionimaging")
Q_INTERFACES(ctkPluginActivator)
public:
void start(ctkPluginContext* context) override;
void stop(ctkPluginContext* context) override;
}; // PluginActivator
}
#endif // MITKPLUGINACTIVATOR_H
diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/QmitkDiffusionImagingAppApplication.cpp b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/QmitkDiffusionImagingAppApplication.cpp
index a560df2..c96db3c 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/QmitkDiffusionImagingAppApplication.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/QmitkDiffusionImagingAppApplication.cpp
@@ -1,37 +1,37 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkDiffusionImagingAppApplication.h"
#include <berryPlatformUI.h>
#include "QmitkDiffusionImagingAppWorkbenchAdvisor.h"
QVariant QmitkDiffusionImagingAppApplication::Start(berry::IApplicationContext*)
{
berry::Display* display = berry::PlatformUI::CreateDisplay();
int code = berry::PlatformUI::CreateAndRunWorkbench(display, new QmitkDiffusionImagingAppWorkbenchAdvisor());
// exit the application with an appropriate return code
return code == berry::PlatformUI::RETURN_RESTART
? EXIT_RESTART : EXIT_OK;
}
void QmitkDiffusionImagingAppApplication::Stop()
{
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/QmitkDiffusionImagingAppApplication.h b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/QmitkDiffusionImagingAppApplication.h
index a69ec21..8e23eca 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/QmitkDiffusionImagingAppApplication.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/QmitkDiffusionImagingAppApplication.h
@@ -1,36 +1,36 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QMITKDiffusionImagingAppAPPLICATION_H_
#define QMITKDiffusionImagingAppAPPLICATION_H_
#include <berryIApplication.h>
class QmitkDiffusionImagingAppApplication : public QObject, public berry::IApplication
{
Q_OBJECT
Q_INTERFACES(berry::IApplication)
public:
QmitkDiffusionImagingAppApplication() {}
~QmitkDiffusionImagingAppApplication() {}
QVariant Start(berry::IApplicationContext*) override;
void Stop() override;
};
#endif /*QMITKDiffusionImagingAppAPPLICATION_H_*/
diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/QmitkDiffusionImagingAppWorkbenchAdvisor.cpp b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/QmitkDiffusionImagingAppWorkbenchAdvisor.cpp
index 2726bf6..766aae6 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/QmitkDiffusionImagingAppWorkbenchAdvisor.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/QmitkDiffusionImagingAppWorkbenchAdvisor.cpp
@@ -1,103 +1,103 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkDiffusionImagingAppWorkbenchAdvisor.h"
#include "internal/QmitkDiffusionApplicationPlugin.h"
#include <berryPlatform.h>
#include <berryIPreferencesService.h>
#include <berryWorkbenchPreferenceConstants.h>
#include <QmitkExtWorkbenchWindowAdvisor.h>
#include <QApplication>
#include <QPoint>
#include <QRect>
#include <QDesktopWidget>
#include <QMainWindow>
const QString QmitkDiffusionImagingAppWorkbenchAdvisor::WELCOME_PERSPECTIVE_ID = "org.mitk.diffusionimagingapp.perspectives.welcome";
class QmitkDiffusionImagingAppWorkbenchWindowAdvisor : public QmitkExtWorkbenchWindowAdvisor
{
public:
QmitkDiffusionImagingAppWorkbenchWindowAdvisor(berry::WorkbenchAdvisor* wbAdvisor,
berry::IWorkbenchWindowConfigurer::Pointer configurer)
: QmitkExtWorkbenchWindowAdvisor(wbAdvisor, configurer)
{
}
void PostWindowOpen() override
{
QmitkExtWorkbenchWindowAdvisor::PostWindowOpen();
berry::IWorkbenchWindowConfigurer::Pointer configurer = GetWindowConfigurer();
configurer->GetWindow()->GetWorkbench()->GetIntroManager()->ShowIntro(configurer->GetWindow(), false);
berry::IWorkbenchWindow::Pointer window =
this->GetWindowConfigurer()->GetWindow();
QMainWindow* mainWindow =
qobject_cast<QMainWindow*> (window->GetShell()->GetControl());
mainWindow->showMaximized();
}
};
void
QmitkDiffusionImagingAppWorkbenchAdvisor::Initialize(berry::IWorkbenchConfigurer::Pointer configurer)
{
berry::QtWorkbenchAdvisor::Initialize(configurer);
configurer->SetSaveAndRestore(true);
}
berry::WorkbenchWindowAdvisor*
QmitkDiffusionImagingAppWorkbenchAdvisor::CreateWorkbenchWindowAdvisor(
berry::IWorkbenchWindowConfigurer::Pointer configurer)
{
QList<QString> perspExcludeList;
perspExcludeList.push_back( "org.blueberry.uitest.util.EmptyPerspective" );
perspExcludeList.push_back( "org.blueberry.uitest.util.EmptyPerspective2" );
perspExcludeList.push_back("org.blueberry.perspectives.help");
QList<QString> viewExcludeList;
viewExcludeList.push_back( "org.mitk.views.controlvisualizationpropertiesview" );
viewExcludeList.push_back( "org.mitk.views.modules" );
QmitkDiffusionImagingAppWorkbenchWindowAdvisor* advisor = new QmitkDiffusionImagingAppWorkbenchWindowAdvisor(this, configurer);
advisor->ShowViewMenuItem(true);
advisor->ShowNewWindowMenuItem(true);
advisor->ShowClosePerspectiveMenuItem(true);
advisor->SetPerspectiveExcludeList(perspExcludeList);
advisor->SetViewExcludeList(viewExcludeList);
advisor->ShowViewToolbar(false);
advisor->ShowPerspectiveToolbar(true);
advisor->ShowVersionInfo(false);
advisor->ShowMitkVersionInfo(true);
advisor->ShowMemoryIndicator(false);
advisor->SetProductName("MITK Diffusion");
advisor->SetWindowIcon(":/org.mitk.gui.qt.diffusionimagingapp/MitkDiffusion.ico");
return advisor;
}
QString QmitkDiffusionImagingAppWorkbenchAdvisor::GetInitialWindowPerspectiveId()
{
return WELCOME_PERSPECTIVE_ID;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/QmitkDiffusionImagingAppWorkbenchAdvisor.h b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/QmitkDiffusionImagingAppWorkbenchAdvisor.h
index 76b18c6..3ce6a64 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/QmitkDiffusionImagingAppWorkbenchAdvisor.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/QmitkDiffusionImagingAppWorkbenchAdvisor.h
@@ -1,39 +1,39 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QMITKDIFFUSIONIMAGINGAPPWORKBENCHADVISOR_H_
#define QMITKDIFFUSIONIMAGINGAPPWORKBENCHADVISOR_H_
#include <berryQtWorkbenchAdvisor.h>
class QmitkDiffusionImagingAppWorkbenchAdvisor : public berry::QtWorkbenchAdvisor
{
public:
static const QString WELCOME_PERSPECTIVE_ID; // = "org.mitk.qt.diffusionimagingapp.defaultperspective"
void Initialize(berry::IWorkbenchConfigurer::Pointer configurer) override;
berry::WorkbenchWindowAdvisor* CreateWorkbenchWindowAdvisor(
berry::IWorkbenchWindowConfigurer::Pointer configurer) override;
QString GetInitialWindowPerspectiveId() override;
};
#endif /* QMITKDIFFUSIONIMAGINGAPPWORKBENCHADVISOR_H_ */
diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkWelcomePerspective.cpp b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkWelcomePerspective.cpp
index 1fa8062..665b4e8 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkWelcomePerspective.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkWelcomePerspective.cpp
@@ -1,21 +1,21 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkWelcomePerspective.h"
void QmitkWelcomePerspective::CreateInitialLayout(berry::IPageLayout::Pointer /*layout*/)
{
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkWelcomePerspective.h b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkWelcomePerspective.h
index c234036..8e32bea 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkWelcomePerspective.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/Perspectives/QmitkWelcomePerspective.h
@@ -1,36 +1,36 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QMITKWelcomePERSPECTIVE_H_
#define QMITKWelcomePERSPECTIVE_H_
#include <berryIPerspectiveFactory.h>
class QmitkWelcomePerspective : public QObject, public berry::IPerspectiveFactory
{
Q_OBJECT
Q_INTERFACES(berry::IPerspectiveFactory)
public:
QmitkWelcomePerspective() {}
~QmitkWelcomePerspective() {}
void CreateInitialLayout(berry::IPageLayout::Pointer /*layout*/) override;
};
#endif /* QMITKWelcomePERSPECTIVE_H_ */
diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionApplicationPlugin.cpp b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionApplicationPlugin.cpp
index dfa5b5b..8f0e199 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionApplicationPlugin.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionApplicationPlugin.cpp
@@ -1,85 +1,85 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkDiffusionApplicationPlugin.h"
#include "src/QmitkDiffusionImagingAppApplication.h"
#include "src/internal/Perspectives/QmitkWelcomePerspective.h"
#include "src/internal/QmitkDiffusionImagingAppIntroPart.h"
#include <mitkVersion.h>
#include <mitkLogMacros.h>
#include <service/cm/ctkConfigurationAdmin.h>
#include <service/cm/ctkConfiguration.h>
#include <QFileInfo>
#include <QDateTime>
QmitkDiffusionApplicationPlugin* QmitkDiffusionApplicationPlugin::inst = nullptr;
QmitkDiffusionApplicationPlugin::QmitkDiffusionApplicationPlugin()
{
inst = this;
}
QmitkDiffusionApplicationPlugin::~QmitkDiffusionApplicationPlugin()
{
}
QmitkDiffusionApplicationPlugin* QmitkDiffusionApplicationPlugin::GetDefault()
{
return inst;
}
void QmitkDiffusionApplicationPlugin::start(ctkPluginContext* context)
{
berry::AbstractUICTKPlugin::start(context);
this->context = context;
BERRY_REGISTER_EXTENSION_CLASS(QmitkWelcomePerspective, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionImagingAppApplication, context)
BERRY_REGISTER_EXTENSION_CLASS(QmitkDiffusionImagingAppIntroPart, context)
ctkServiceReference cmRef = context->getServiceReference<ctkConfigurationAdmin>();
ctkConfigurationAdmin* configAdmin = nullptr;
if (cmRef)
{
configAdmin = context->getService<ctkConfigurationAdmin>(cmRef);
}
// Use the CTK Configuration Admin service to configure the BlueBerry help system
if (configAdmin)
{
ctkConfigurationPtr conf = configAdmin->getConfiguration("org.blueberry.services.help", QString());
ctkDictionary helpProps;
helpProps.insert("homePage", "qthelp://org.mitk.gui.qt.diffusionimagingapp/bundle/index.html");
conf->update(helpProps);
context->ungetService(cmRef);
}
else
{
MITK_WARN << "Configuration Admin service unavailable, cannot set home page url.";
}
}
ctkPluginContext* QmitkDiffusionApplicationPlugin::GetPluginContext() const
{
return context;
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionApplicationPlugin.h b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionApplicationPlugin.h
index 2b3f3ce..9a8779d 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionApplicationPlugin.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionApplicationPlugin.h
@@ -1,51 +1,51 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QMITKDIFFUSIONAPPLICATIONPLUGIN_H_
#define QMITKDIFFUSIONAPPLICATIONPLUGIN_H_
#include <berryAbstractUICTKPlugin.h>
#include <QString>
class QmitkDiffusionApplicationPlugin : public berry::AbstractUICTKPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_diffusionimagingapp")
Q_INTERFACES(ctkPluginActivator)
public:
QmitkDiffusionApplicationPlugin();
~QmitkDiffusionApplicationPlugin();
static QmitkDiffusionApplicationPlugin* GetDefault();
ctkPluginContext* GetPluginContext() const;
void start(ctkPluginContext*) override;
QString GetQtHelpCollectionFile() const;
private:
static QmitkDiffusionApplicationPlugin* inst;
ctkPluginContext* context;
};
#endif /* QMITKDIFFUSIONAPPLICATIONPLUGIN_H_ */
diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionImagingAppIntroPart.cpp b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionImagingAppIntroPart.cpp
index ba07ba0..a99638b 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionImagingAppIntroPart.cpp
+++ b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionImagingAppIntroPart.cpp
@@ -1,202 +1,202 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 "QmitkDiffusionImagingAppIntroPart.h"
#include "mitkNodePredicateDataType.h"
#include <berryIWorkbenchWindow.h>
#include <berryIWorkbench.h>
#include <berryIWorkbenchPage.h>
#include <berryIPerspectiveRegistry.h>
#include <berryWorkbenchPreferenceConstants.h>
#include <berryIPreferences.h>
#include <berryIPreferencesService.h>
#include <berryIEditorReference.h>
#include <berryIEditorInput.h>
#include <mitkIDataStorageService.h>
#include <mitkDataStorageEditorInput.h>
#include <mitkLogMacros.h>
#include <QLabel>
#include <QMessageBox>
#include <QtCore/qconfig.h>
#include <QWebEngineView>
#include <QWebEnginePage>
#include <QUrlQuery>
#include <QString>
#include <QStringList>
#include <QRegExp>
#include <QChar>
#include <QByteArray>
#include <QDesktopServices>
#include "QmitkDiffusionApplicationPlugin.h"
#include "mitkDataStorageEditorInput.h"
#include <string>
#include "mitkProgressBar.h"
#include "mitkNodePredicateNot.h"
#include "mitkNodePredicateProperty.h"
namespace
{
class QmitkDiffusionWebEnginePage final : public QWebEnginePage
{
public:
explicit QmitkDiffusionWebEnginePage(QmitkDiffusionImagingAppIntroPart* introPart, QObject* parent = nullptr);
~QmitkDiffusionWebEnginePage() override;
private:
bool acceptNavigationRequest(const QUrl& url, NavigationType type, bool isMainFrame) override;
QmitkDiffusionImagingAppIntroPart* m_IntroPart;
};
QmitkDiffusionWebEnginePage::QmitkDiffusionWebEnginePage(QmitkDiffusionImagingAppIntroPart* introPart, QObject* parent)
: QWebEnginePage(parent),
m_IntroPart(introPart)
{
}
QmitkDiffusionWebEnginePage::~QmitkDiffusionWebEnginePage()
{
}
bool QmitkDiffusionWebEnginePage::acceptNavigationRequest(const QUrl& url, NavigationType, bool)
{
QString scheme = url.scheme();
if (scheme.contains("mitk"))
{
if (url.path().isEmpty())
return false;
if (url.host().contains("perspectives"))
{
QString id = url.path().simplified().replace("/", "");
auto introSite = m_IntroPart->GetIntroSite();
auto workbenchWindow = introSite->GetWorkbenchWindow();
auto workbench = workbenchWindow->GetWorkbench();
workbench->ShowPerspective(id, workbenchWindow);
auto context = QmitkDiffusionApplicationPlugin::GetDefault()->GetPluginContext();
auto serviceReference = context->getServiceReference<mitk::IDataStorageService>();
mitk::IDataStorageService* service = serviceReference
? context->getService<mitk::IDataStorageService>(serviceReference)
: nullptr;
if (service)
{
berry::IEditorInput::Pointer editorInput(new mitk::DataStorageEditorInput(service->GetActiveDataStorage()));
auto page = introSite->GetPage();
auto editors = page->FindEditors(editorInput, "org.mitk.editors.stdmultiwidget", 1);
if (!editors.isEmpty())
page->Activate(editors[0]->GetPart(true));
}
}
}
else if (scheme.contains("http"))
{
QDesktopServices::openUrl(url);
}
else
{
return true;
}
return false;
}
}
QmitkDiffusionImagingAppIntroPart::QmitkDiffusionImagingAppIntroPart()
: m_Controls(nullptr)
{
berry::IPreferences::Pointer workbenchPrefs = QmitkDiffusionApplicationPlugin::GetDefault()->GetPreferencesService()->GetSystemPreferences();
workbenchPrefs->PutBool(berry::WorkbenchPreferenceConstants::SHOW_INTRO, true);
workbenchPrefs->Flush();
}
QmitkDiffusionImagingAppIntroPart::~QmitkDiffusionImagingAppIntroPart()
{
// if the workbench is not closing (that means, welcome screen was closed explicitly), set "Show_intro" false
if (!this->GetIntroSite()->GetPage()->GetWorkbenchWindow()->GetWorkbench()->IsClosing())
{
berry::IPreferences::Pointer workbenchPrefs = QmitkDiffusionApplicationPlugin::GetDefault()->GetPreferencesService()->GetSystemPreferences();
workbenchPrefs->PutBool(berry::WorkbenchPreferenceConstants::SHOW_INTRO, false);
workbenchPrefs->Flush();
}
else
{
berry::IPreferences::Pointer workbenchPrefs = QmitkDiffusionApplicationPlugin::GetDefault()->GetPreferencesService()->GetSystemPreferences();
workbenchPrefs->PutBool(berry::WorkbenchPreferenceConstants::SHOW_INTRO, true);
workbenchPrefs->Flush();
}
// if workbench is not closing (Just welcome screen closing), open last used perspective
if (this->GetIntroSite()->GetPage()->GetPerspective()->GetId()
== "org.mitk.diffusionimagingapp.perspectives.welcome"
&& !this->GetIntroSite()->GetPage()->GetWorkbenchWindow()->GetWorkbench()->IsClosing())
{
berry::IPerspectiveDescriptor::Pointer perspective = this->GetIntroSite()->GetWorkbenchWindow()->GetWorkbench()->GetPerspectiveRegistry()->FindPerspectiveWithId("org.mitk.perspectives.diffusiondefault");
if (perspective)
{
this->GetIntroSite()->GetPage()->SetPerspective(perspective);
}
}
}
void QmitkDiffusionImagingAppIntroPart::CreateQtPartControl(QWidget* parent)
{
if (!m_Controls)
{
// create GUI widgets
m_Controls = new Ui::QmitkWelcomeScreenViewControls;
m_Controls->setupUi(parent);
m_view = new QWebEngineView(parent);
auto page = new QmitkDiffusionWebEnginePage(this, parent);
m_view->setPage(page);
QUrl urlQtResource(QString("qrc:/org.mitk.gui.qt.welcomescreen/mitkdiffusionimagingappwelcomeview.html"), QUrl::TolerantMode );
m_view->load( urlQtResource );
// adds the webview as a widget
parent->layout()->addWidget(m_view);
this->CreateConnections();
}
}
void QmitkDiffusionImagingAppIntroPart::CreateConnections()
{
}
void QmitkDiffusionImagingAppIntroPart::StandbyStateChanged(bool)
{
}
void QmitkDiffusionImagingAppIntroPart::SetFocus()
{
}
diff --git a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionImagingAppIntroPart.h b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionImagingAppIntroPart.h
index 1db5cfe..8eef703 100644
--- a/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionImagingAppIntroPart.h
+++ b/Plugins/org.mitk.gui.qt.diffusionimagingapp/src/internal/QmitkDiffusionImagingAppIntroPart.h
@@ -1,82 +1,82 @@
/*===================================================================
The Medical Imaging Interaction Toolkit (MITK)
-Copyright (c) German Cancer Research Center,
-Division of Medical Image Computing.
+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 QMITKDIFFUSIONIMAGINGAPPINTROPART_H_
#define QMITKDIFFUSIONIMAGINGAPPINTROPART_H_
#include <QtCore/qconfig.h>
#include <berryQtIntroPart.h>
#include <ui_QmitkWelcomeScreenViewControls.h>
/**
* \ingroup org_mitk_gui_qt_welcomescreen_internal
* \brief QmitkWelcomeScreenView
* The WelcomeView Module is an helpful feature to people new to MITK. The main idea is to provide first
* information about the particular working modes of the 3 M-3 application suited to specific medical working task.
* Links to external documentation or information pages such as the mitk.org homepage are thinkable but have
* not been implemented yet. The WelcomeView is realized by making use of the QTWebKit Module. The Qt WebKit module
* provides an HTML browser engine that makes it easy to embed web content into native applications, and to enhance
* web content with native controls.
* For the welcome view of the application the QWebView, QWebPage classes have been used. The shown WelcomeView
* html start page is styled by an external css stylesheet. The required resources as well as the html pages are integrated
* into the QtResource system. The QT resource system allows the storage of files like html pages, css pages, jpgs etc.
* as binaries within the executable.
* This minimizes the risk of loosing resource files as well as the risk of getting files deleted. In order to use the Qt
* resource system the resource files have to be added to the associated qrt resource file list.
* Due to time issues the html pages of the welcome view do make use of jpegs with hotspots to switch
* into the particular working modes. <
* Nevertheless the foundation is set to design more complex html pages. The Q::WebPage gives options to set a
* LinkDelegationPolicy. The used policy defines how links to external or internal resources are handled. To fit our needs
* the delegate all links policy is used. This requires all external as well as internal links of the html pages to be handle
* explicitly. In order to change mitk working modes (perspectives) a mitk url scheme has been designed. The url scheme
* is set to mitk. The url host provides information about what's next to do. In our case, the case of switching to a
* particular working mode the host is set to perspectives. The followed path provides information about the perspective id.
* (e.g. mitk//::mitk.perspectives/org.mitk.qt.defaultperspective) The the generic design of the mitk url scheme allows to * execute other task depending on the mitk url host.
* \sa QmitkWelcomePage Editor
*/
class QWebEngineView;
class QmitkDiffusionImagingAppIntroPart : public berry::QtIntroPart
{
// this is needed for all Qt objects that should have a MOC object (everything that derives from QObject)
Q_OBJECT
public:
QmitkDiffusionImagingAppIntroPart();
~QmitkDiffusionImagingAppIntroPart();
virtual void CreateQtPartControl(QWidget *parent) override;
void StandbyStateChanged(bool standby) override;
void SetFocus() override;
virtual void CreateConnections();
protected:
Ui::QmitkWelcomeScreenViewControls* m_Controls;
QWebEngineView* m_view;
};
#endif /* QMITKDIFFUSIONIMAGINGAPPINTROPART_H_ */

File Metadata

Mime Type
application/octet-stream
Expires
Mon, Apr 22, 1:55 AM (1 d, 23 h)
Storage Engine
chunks
Storage Format
Chunks
Storage Handle
bUYcsVyRRuZZ
Default Alt Text
(5 MB)

Event Timeline