diff --git a/Modules/DiffusionCmdApps/ImageQuantification/DiffusionIndices.cpp b/Modules/DiffusionCmdApps/ImageQuantification/DiffusionIndices.cpp index 7a84b41..f6aca5c 100644 --- a/Modules/DiffusionCmdApps/ImageQuantification/DiffusionIndices.cpp +++ b/Modules/DiffusionCmdApps/ImageQuantification/DiffusionIndices.cpp @@ -1,195 +1,194 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include -#include #include #include #include #include #include #include "mitkDiffusionCommandLineParser.h" #include #include #include #include #include #include #include #include #include #include #include #include /** * */ 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 parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; std::string inFileName = us::any_cast(parsedArgs["i"]); std::string index = us::any_cast(parsedArgs["index"]); std::string outFileName = us::any_cast(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"}, std::vector()); auto input = mitk::IOUtil::Load(inFileName, &functor); bool is_odf = (dynamic_cast(input.GetPointer()) || dynamic_cast(input.GetPointer())); bool is_dt = dynamic_cast(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 OdfVectorType; typedef itk::Image OdfVectorImgType; OdfVectorImgType::Pointer itkvol; if (dynamic_cast(input.GetPointer())) { MITK_INFO << "Assuming MITK/MRtrix style SH convention!"; itkvol = mitk::convert::GetItkOdfFromShImage(input); } else itkvol = mitk::convert::GetItkOdfFromOdfImage(input); typedef itk::DiffusionOdfGeneralizedFaImageFilter GfaFilterType; GfaFilterType::Pointer gfaFilter = GfaFilterType::New(); gfaFilter->SetInput(itkvol); gfaFilter->SetComputationMethod(GfaFilterType::GFA_STANDARD); gfaFilter->Update(); itk::ImageFileWriter< itk::Image >::Pointer fileWriter = itk::ImageFileWriter< itk::Image >::New(); fileWriter->SetInput(gfaFilter->GetOutput()); fileWriter->SetFileName(outFileName); fileWriter->Update(); } else if( is_dt ) { typedef itk::Image< itk::DiffusionTensor3D, 3 > ItkTensorImage; mitk::TensorImage::Pointer mitkTensorImage = dynamic_cast(input.GetPointer()); ItkTensorImage::Pointer itk_dti = ItkTensorImage::New(); mitk::CastToItkImage(mitkTensorImage, itk_dti); typedef itk::TensorDerivedMeasurementsFilter 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 >::Pointer fileWriter = itk::ImageFileWriter< itk::Image >::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(mitk::DiffusionPropertyHelper::GetReferenceBValue(input)) ); if (index=="adc") filter->SetFitSignal(true); else filter->SetFitSignal(false); filter->Update(); itk::ImageFileWriter< itk::Image >::Pointer fileWriter = itk::ImageFileWriter< itk::Image >::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/ImageQuantification/MultishellMethods.cpp b/Modules/DiffusionCmdApps/ImageQuantification/MultishellMethods.cpp index 6e5e7e2..3a80792 100644 --- a/Modules/DiffusionCmdApps/ImageQuantification/MultishellMethods.cpp +++ b/Modules/DiffusionCmdApps/ImageQuantification/MultishellMethods.cpp @@ -1,215 +1,214 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include -#include #include #include #include #include #include #include #include "mitkDiffusionCommandLineParser.h" #include #include #include #include #include #include #include #include #include #include #include #include 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 parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size()==0) return EXIT_FAILURE; // mandatory arguments std::string inName = us::any_cast(parsedArgs["i"]); std::string outName = us::any_cast(parsedArgs["o"]); bool applyADC = us::any_cast(parsedArgs["adc"]); bool applyAKC = us::any_cast(parsedArgs["akc"]); bool applyBiExp = us::any_cast(parsedArgs["biexp"]); std::string targetType = us::any_cast(parsedArgs["targetbvalue"]); try { std::cout << "Loading " << inName; mitk::PreferenceListReaderOptionsFunctor functor = mitk::PreferenceListReaderOptionsFunctor({"Diffusion Weighted Images"}, std::vector()); mitk::Image::Pointer dwi = mitk::IOUtil::Load(inName, &functor); if ( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dwi ) ) { typedef itk::RadialMultishellToSingleshellImageFilter 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::ConstPointer gradientContainer = mitk::DiffusionPropertyHelper::GetGradientContainer(dwi); const unsigned int &bValue = mitk::DiffusionPropertyHelper::GetReferenceBValue( dwi ); // filter call vnl_vector 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/DiffusionCore/Algorithms/Reconstruction/itkOrientationDistributionFunction.txx b/Modules/DiffusionCore/Algorithms/Reconstruction/itkOrientationDistributionFunction.txx index 11e0847..94975d0 100644 --- a/Modules/DiffusionCore/Algorithms/Reconstruction/itkOrientationDistributionFunction.txx +++ b/Modules/DiffusionCore/Algorithms/Reconstruction/itkOrientationDistributionFunction.txx @@ -1,1367 +1,1360 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _itkOrientationDistributionFunction_txx #define _itkOrientationDistributionFunction_txx #include #include #include #include #include #include -#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 #include #include #include #include #include #include -#include +#include +#include +#include namespace itk { template vtkPolyData* itk::OrientationDistributionFunction::m_BaseMesh = nullptr; template double itk::OrientationDistributionFunction::m_MaxChordLength = -1.0; template vnl_matrix_fixed* itk::OrientationDistributionFunction::m_Directions = itk::PointShell >::DistributePointShell(); template std::vector< std::vector* >* itk::OrientationDistributionFunction::m_NeighborIdxs = nullptr; template std::vector< std::vector* >* itk::OrientationDistributionFunction::m_AngularRangeIdxs = nullptr; template std::vector* itk::OrientationDistributionFunction::m_HalfSphereIdxs = nullptr; template std::mutex itk::OrientationDistributionFunction::m_MutexBaseMesh; template std::mutex itk::OrientationDistributionFunction::m_MutexHalfSphereIdxs; template std::mutex itk::OrientationDistributionFunction::m_MutexNeighbors; template std::mutex itk::OrientationDistributionFunction::m_MutexAngularRange; /** * Assignment Operator */ template OrientationDistributionFunction& OrientationDistributionFunction ::operator= (const Self& r) { BaseArray::operator=(r); return *this; } /** * Assignment Operator from a scalar constant */ template OrientationDistributionFunction& OrientationDistributionFunction ::operator= (const ComponentType & r) { BaseArray::operator=(&r); return *this; } /** * Assigment from a plain array */ template OrientationDistributionFunction& OrientationDistributionFunction ::operator= (const ComponentArrayType r ) { BaseArray::operator=(r); return *this; } /** * Returns a temporary copy of a vector */ template OrientationDistributionFunction OrientationDistributionFunction ::operator+(const Self & r) const { Self result; for( unsigned int i=0; i OrientationDistributionFunction OrientationDistributionFunction ::operator-(const Self & r) const { Self result; for( unsigned int i=0; i const OrientationDistributionFunction & OrientationDistributionFunction ::operator+=(const Self & r) { for( unsigned int i=0; i const OrientationDistributionFunction & OrientationDistributionFunction ::operator-=(const Self & r) { for( unsigned int i=0; i const OrientationDistributionFunction & OrientationDistributionFunction ::operator*=(const RealValueType & r) { for( unsigned int i=0; i const OrientationDistributionFunction & OrientationDistributionFunction ::operator/=(const RealValueType & r) { for( unsigned int i=0; i OrientationDistributionFunction OrientationDistributionFunction ::operator*(const RealValueType & r) const { Self result; for( unsigned int i=0; i OrientationDistributionFunction OrientationDistributionFunction ::operator/(const RealValueType & r) const { Self result; for( unsigned int i=0; i const typename OrientationDistributionFunction::ValueType & OrientationDistributionFunction ::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 typename OrientationDistributionFunction::ValueType & OrientationDistributionFunction ::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 void OrientationDistributionFunction ::SetIsotropic() { this->Fill(NumericTraits< T >::One / NOdfDirections); } /** * InitFromTensor() */ template void OrientationDistributionFunction ::InitFromTensor(itk::DiffusionTensor3D tensor) { m_EigenAnalysisCalculated = false; for(unsigned int i=0; i void OrientationDistributionFunction:: InitFromEllipsoid( itk::DiffusionTensor3D tensor ) { m_EigenAnalysisCalculated = false; FixedArray 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 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= [" < 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::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 void OrientationDistributionFunction ::L2Normalize() { T sum = 0; for( unsigned int i=0; i void OrientationDistributionFunction ::Normalize() { T sum = 0; for( unsigned int i=0; i0) { for( unsigned int i=0; i OrientationDistributionFunction OrientationDistributionFunction ::MinMaxNormalize() const { T max = NumericTraits::NonpositiveMin(); T min = NumericTraits::max(); for( unsigned int i=0; i max ? (*this)[i] : max; min = (*this)[i] < min ? (*this)[i] : min; } Self retval; for( unsigned int i=0; i OrientationDistributionFunction OrientationDistributionFunction ::MaxNormalize() const { T max = NumericTraits::NonpositiveMin(); for( unsigned int i=0; i max ? (*this)[i] : max; } Self retval; for( unsigned int i=0; i T OrientationDistributionFunction ::GetMaxValue() const { T max = NumericTraits::NonpositiveMin(); for( unsigned int i=0; i= max ) { max = (*this)[i]; } } return max; } template T OrientationDistributionFunction ::GetMinValue() const { T min = NumericTraits::max(); for( unsigned int i=0; i= min ) { min = (*this)[i]; } } return min; } template T OrientationDistributionFunction ::GetMeanValue() const { T sum = 0; for( unsigned int i=0; i double OrientationDistributionFunction ::GetMaxChordLength() { if(m_MaxChordLength<0.0) { ComputeBaseMesh(); double max_dist = -1; vtkPoints* points = m_BaseMesh->GetPoints(); for(int i=0; iGetPoint(i,p); std::vector neighbors = GetNeighbors(i); for(std::size_t j=0; jGetPoint(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 void OrientationDistributionFunction ::ComputeBaseMesh() { m_MutexBaseMesh.lock(); if(m_BaseMesh == nullptr) { vtkPoints* points = vtkPoints::New(); for(unsigned int j=0; jInsertNextPoint(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 const *pts; while(vtkpolys->GetNextCell(npts,pts)) { bool insert = true; for(int i=0; iGetPoint(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; jInsertNextPoint(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; iGetPoint(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 int OrientationDistributionFunction::GetPrincipalDiffusionDirectionIndex() const { T max = NumericTraits::NonpositiveMin(); int maxidx = -1; for( unsigned int i=0; i= max ) { max = (*this)[i]; maxidx = i; } } return maxidx; } /** * Extract the principal diffusion direction */ template vnl_vector_fixed OrientationDistributionFunction::GetPrincipalDiffusionDirection() const { if (m_EigenAnalysisCalculated) { vnl_vector_fixed 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::GetDirection(idx); vnl_vector_fixed vec; vec.fill(0); return vec; } } template std::vector OrientationDistributionFunction ::GetNeighbors(int idx) { ComputeBaseMesh(); m_MutexNeighbors.lock(); if(m_NeighborIdxs == nullptr) { m_NeighborIdxs = new std::vector< std::vector* >(); vtkCellArray* polys = m_BaseMesh->GetPolys(); for(unsigned int i=0; i(); polys->InitTraversal(); vtkIdType npts; vtkIdType const *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 int OrientationDistributionFunction ::GetNthDiffusionDirection(int n, vnl_vector_fixed rndVec) const { if( n == 0 ) return GetPrincipalDiffusionDirectionIndex(); m_MutexHalfSphereIdxs.lock(); if( !m_HalfSphereIdxs ) { m_HalfSphereIdxs = new std::vector(); for( unsigned int i=0; iget_column(i),rndVec) > 0.0) { m_HalfSphereIdxs->push_back(i); } } } m_MutexHalfSphereIdxs.unlock(); // collect indices of directions // that are local maxima std::vector localMaxima; std::vector::iterator it; for( it=m_HalfSphereIdxs->begin(); it!=m_HalfSphereIdxs->end(); it++) { std::vector nbs = GetNeighbors(*it); std::vector::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::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 itk::OrientationDistributionFunction ::GetDirection( int i ) { return m_Directions->get_column(i); } /** * Interpolate a position between sampled directions */ template T OrientationDistributionFunction ::GetInterpolatedComponent(vnl_vector_fixed 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::max(); int current_min_idx = -1; for(int i=0; i P(points->GetPoint(i)); double dist = (dir-P).two_norm(); current_min_idx = distGetNthComponent(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 const *pts; double current_min = NumericTraits::max(); polys->InitTraversal(); while(polys->GetNextCell(npts,pts)) { vnl_vector_fixed A(points->GetPoint(pts[0])); vnl_vector_fixed B(points->GetPoint(pts[1])); vnl_vector_fixed C(points->GetPoint(pts[2])); vnl_vector_fixed 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 v0 = C - A; vnl_vector_fixed v1 = B - A; // Project direction to plane ABC vnl_vector_fixed v6 = dir; vnl_vector_fixed 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 mat; mat.set_column(0, v0); mat.set_column(1, v1); vnl_matrix_inverse inv(mat); vnl_matrix_fixed inver = inv.pinverse(); vnl_vector 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 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 contrib; contrib.set_size(NOdfDirections); vtkPoints* points = m_BaseMesh->GetPoints(); double sum = 0; for(int i=0; i 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; iGetNthComponent(i); } break; } } if(retval==-1) { std::cout << "Interpolation failed" << std::endl; return 0; } return retval; } /** * Calculate Generalized Fractional Anisotropy */ template T OrientationDistributionFunction ::GetGeneralizedFractionalAnisotropy() const { double mean = 0; double std = 0; double rms = 0; for( unsigned int i=0; i T itk::OrientationDistributionFunction ::GetGeneralizedGFA( int k, int p ) const { double mean = 0; double std = 0; double rms = 0; double max = NumericTraits::NonpositiveMin(); for( unsigned int i=0; i max ? val : max; } max = pow(max,(double)p); mean /= N; for( unsigned int i=0; i0) { 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 ::GetNematicOrderParameter() const { // not yet implemented return 0; } /** * Calculate StdDev by MaxValue */ template < typename T, unsigned int N > T itk::OrientationDistributionFunction ::GetStdDevByMaxValue() const { double mean = 0; double std = 0; T max = NumericTraits::NonpositiveMin(); for( unsigned int i=0; i max ? (*this)[i] : max; } mean /= InternalDimension; for( unsigned int i=0; i T itk::OrientationDistributionFunction ::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* >(); for(unsigned int i=0; i pDir = GetDirection(i); auto idxs = new std::vector(); for(unsigned int j=0; j 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::max(); for( unsigned int i=0; i nbs = GetNeighbors(pIdx); //////std::vector modeAndNeighborVals; //////modeAndNeighborVals.push_back(mode); //////int numNeighbors = nbs.size(); //////for(int i=0; i odfValuesInAngularRange; int numInRange = m_AngularRangeIdxs->at(pIdx)->size(); for(int i=0; iat(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 ::GetNormalizedEntropy() const { double mean = 0; for( unsigned int i=0; i OrientationDistributionFunction OrientationDistributionFunction ::PreMultiply( const MatrixType & m ) const { Self result; typedef typename NumericTraits::AccumulateType AccumulateType; for(unsigned int r=0; r::ZeroValue(); for(unsigned int t=0; t( sum ); } } return result; } /** * Post-multiply the Tensor by a Matrix */ template OrientationDistributionFunction OrientationDistributionFunction ::PostMultiply( const MatrixType & m ) const { Self result; typedef typename NumericTraits::AccumulateType AccumulateType; for(unsigned int r=0; r::ZeroValue(); for(unsigned int t=0; t( sum ); } } return result; } /** * Print content to an ostream */ template std::ostream & operator<<(std::ostream& os,const OrientationDistributionFunction & c ) { for(unsigned int i=0; i::PrintType>(c[i]) << " "; } return os; } /** * Read content from an istream */ template std::istream & operator>>(std::istream& is, OrientationDistributionFunction & 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 fa82c50..60c165a 100644 --- a/Modules/DiffusionCore/Algorithms/Reconstruction/itkPointShell.h +++ b/Modules/DiffusionCore/Algorithms/Reconstruction/itkPointShell.h @@ -1,53 +1,46 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __itkPointShell_h__ #define __itkPointShell_h__ -#include "mitkOdfImage.h" #include -#include -#include namespace itk { // generate by n-fold subdivisions of an icosahedron template - class PointShell + class MITKDIFFUSIONCORE_EXPORT PointShell { public: static TMatrixType *DistributePointShell(); }; template class ThreeLayerPointShell { public: static TMatrixTypeshell1 *DistributePointShell1(); static TMatrixTypeshell2 *DistributePointShell2(); static TMatrixTypeshell3 *DistributePointShell3(); }; } - - -#ifndef ITK_MANUAL_INSTANTIATION #include "itkPointShell.txx" -#endif #endif //__itkPointShell_h__ diff --git a/Modules/DiffusionCore/Algorithms/Reconstruction/itkPointShell.txx b/Modules/DiffusionCore/Algorithms/Reconstruction/itkPointShell.txx index f1bdd90..9cc939f 100644 --- a/Modules/DiffusionCore/Algorithms/Reconstruction/itkPointShell.txx +++ b/Modules/DiffusionCore/Algorithms/Reconstruction/itkPointShell.txx @@ -1,5238 +1,5241 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __itkPointShell_txx__ #define __itkPointShell_txx__ +#include +#include + namespace itk { template TMatrixType* PointShell ::DistributePointShell() { auto theta = new vnl_vector_fixed(); auto phi = new vnl_vector_fixed(); double C = sqrt(4*itk::Math::pi); (*phi)(0) = 0.0; (*phi)(NPoints-1) = 0.0; for(int i=0; i0 && i(); for(int i=0; i class PointShell<12, vnl_matrix_fixed > { public: static vnl_matrix_fixed* 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(coords); return pointshell; } }; template<> class PointShell<42, vnl_matrix_fixed > { public: static vnl_matrix_fixed* 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(coords); return pointshell; } }; template<> class PointShell<92, vnl_matrix_fixed > { public: static vnl_matrix_fixed* 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(coords); return pointshell; } }; template<> class PointShell<162, vnl_matrix_fixed > { public: static vnl_matrix_fixed* 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(coords); return pointshell; } }; template<> class PointShell<252, vnl_matrix_fixed > { public: static vnl_matrix_fixed* 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(coords); return pointshell; } }; template<> class PointShell<362, vnl_matrix_fixed > { public: static vnl_matrix_fixed* 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(coords); return pointshell; } }; template<> class PointShell<492, vnl_matrix_fixed > { public: static vnl_matrix_fixed* 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(coords); return pointshell; } }; template<> class PointShell<642, vnl_matrix_fixed > { public: static vnl_matrix_fixed* 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(coords); return pointshell; } }; template<> class PointShell<812, vnl_matrix_fixed > { public: static vnl_matrix_fixed* 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(coords); return pointshell; } }; template<> class PointShell<1002, vnl_matrix_fixed > { public: static vnl_matrix_fixed* 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(coords); return pointshell; } }; // ThreeLayerPointShell using a staggered-distribution #include template 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 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 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,vnl_matrix_fixed,vnl_matrix_fixed > { public: static vnl_matrix_fixed* 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(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* 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(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* 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(); // 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,vnl_matrix_fixed,vnl_matrix_fixed > { public: static vnl_matrix_fixed* 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(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* 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(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* 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(); // 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,vnl_matrix_fixed,vnl_matrix_fixed > { public: static vnl_matrix_fixed* 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(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* 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(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* 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(); // 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,vnl_matrix_fixed,vnl_matrix_fixed > { public: static vnl_matrix_fixed* 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(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* 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(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* 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(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,vnl_matrix_fixed,vnl_matrix_fixed > { public: static vnl_matrix_fixed* 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(); // 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* 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(); // 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* 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(); // 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/itkDiffusionOdfGeneralizedFaImageFilter.txx b/Modules/DiffusionCore/Algorithms/itkDiffusionOdfGeneralizedFaImageFilter.txx index f7f3f34..2131f85 100644 --- a/Modules/DiffusionCore/Algorithms/itkDiffusionOdfGeneralizedFaImageFilter.txx +++ b/Modules/DiffusionCore/Algorithms/itkDiffusionOdfGeneralizedFaImageFilter.txx @@ -1,221 +1,222 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __itkDiffusionOdfGeneralizedFaImageFilter_txx #define __itkDiffusionOdfGeneralizedFaImageFilter_txx #include #include #include #define _USE_MATH_DEFINES #include #include "itkImageRegionConstIterator.h" #include "itkImageRegionConstIteratorWithIndex.h" #include "itkImageRegionIterator.h" #include "itkArray.h" #include "vnl/vnl_vector.h" #include "vnl/vnl_vector_fixed.h" +#include #include "itkOrientationDistributionFunction.h" namespace itk { template< class TOdfPixelType, class TGfaPixelType, unsigned 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, unsigned int NrOdfDirections> void DiffusionOdfGeneralizedFaImageFilter< TOdfPixelType, TGfaPixelType, NrOdfDirections> ::BeforeThreadedGenerateData() { } template< class TOdfPixelType, class TGfaPixelType, unsigned 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 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 sorted; for(unsigned int i=0; i sorted; for(unsigned int i=0; i sorted; for(unsigned int i=0; i sorted; for(unsigned int i=0; i 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/itkResampleDwiImageFilter.h b/Modules/DiffusionCore/Algorithms/itkResampleDwiImageFilter.h index c4b70d0..a2b6a41 100644 --- a/Modules/DiffusionCore/Algorithms/itkResampleDwiImageFilter.h +++ b/Modules/DiffusionCore/Algorithms/itkResampleDwiImageFilter.h @@ -1,146 +1,144 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ /*========================================================================= 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 #include #include namespace itk { /** * \brief Resample DWI channel by channel. */ template class ResampleDwiImageFilter : public ImageToImageFilter, itk::VectorImage > { public: enum Interpolation { Interpolate_NearestNeighbour, Interpolate_Linear, Interpolate_BSpline, Interpolate_WindowedSinc }; typedef ResampleDwiImageFilter Self; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; typedef ImageToImageFilter< itk::VectorImage, itk::VectorImage > Superclass; typedef itk::Vector< double, 3 > DoubleVectorType; typedef itk::VectorImage DwiImageType; typedef itk::Image 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/CMakeLists.txt b/Modules/DiffusionCore/CMakeLists.txt index ded455b..ef824f2 100644 --- a/Modules/DiffusionCore/CMakeLists.txt +++ b/Modules/DiffusionCore/CMakeLists.txt @@ -1,28 +1,28 @@ # With apple gcc 4.2.1 the following waring leads to an build error if boost is enabled if(APPLE) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=empty-body" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() MITK_CREATE_MODULE( SUBPROJECTS MITK-Diffusion INCLUDE_DIRS Algorithms Algorithms/Reconstruction Algorithms/Registration Algorithms/Reconstruction/MultishellProcessing Algorithms/Reconstruction/FittingFunctions DicomImport IODataStructures/DiffusionWeightedImages IODataStructures/Properties IODataStructures Rendering ${CMAKE_CURRENT_BINARY_DIR} DEPENDS MitkMapperExt MitkPlanarFigure MitkImageExtraction MitkDICOM MitkMatchPointRegistration PACKAGE_DEPENDS - PUBLIC VTK|FiltersProgrammable+IOImage+CommonComputationalGeometry Vigra HDF5 + PUBLIC VTK|FiltersProgrammable+IOImage+CommonComputationalGeometry Vigra HDF5 ITK|VNL ) if(TARGET ${MODULE_TARGET} AND MITK_USE_OpenMP) target_link_libraries(${MODULE_TARGET} PUBLIC OpenMP::OpenMP_CXX) endif() if(MSVC) mitkFunctionCheckCAndCXXCompilerFlags("/wd4005" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() add_subdirectory(Testing) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/mitkDiffusionImagingConfigure.h.in ${CMAKE_CURRENT_BINARY_DIR}/mitkDiffusionImagingConfigure.h) mitkFunctionGetVersion(${CMAKE_CURRENT_SOURCE_DIR} MITKDIFFUSION) mitkFunctionGetVersionDescription(${CMAKE_CURRENT_SOURCE_DIR} MITKDIFFUSION) configure_file(mitkDiffusionVersion.h.in ${MITK_BINARY_DIR}/mitkDiffusionVersion.h) diff --git a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkMetropolisHastingsSampler.cpp b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkMetropolisHastingsSampler.cpp index 6053c7a..71154f5 100644 --- a/Modules/FiberTracking/Algorithms/GibbsTracking/mitkMetropolisHastingsSampler.cpp +++ b/Modules/FiberTracking/Algorithms/GibbsTracking/mitkMetropolisHastingsSampler.cpp @@ -1,499 +1,500 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkMetropolisHastingsSampler.h" +#include 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& 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 MetropolisHastingsSampler::GetRandomDirection() { vnl_vector_fixed 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 R; m_EnergyComputer->DrawRandomPosition(R); vnl_vector_fixed 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 Rtmp = p->GetPos(); vnl_vector_fixed 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 Rtmp = p->GetPos(); vnl_vector_fixed 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 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/Testing/mitkPeakShImageReaderTest.cpp b/Modules/FiberTracking/Testing/mitkPeakShImageReaderTest.cpp index 24fa53e..71c4581 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. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include "mitkTestingMacros.h" #include #include #include #include #include #include #include #include #include class mitkPeakShImageReaderTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkPeakShImageReaderTestSuite); MITK_TEST(PeakReader); MITK_TEST(ShReader); CPPUNIT_TEST_SUITE_END(); typedef itk::Image 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"}, std::vector()); auto inputData = mitk::IOUtil::Load(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 readAccess(inputData); + mitk::ImagePixelReadAccessor readAccess(dynamic_cast(inputData.GetPointer())); 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"}, std::vector()); auto inputData = mitk::IOUtil::Load(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, 3> readAccess(inputData); + mitk::ImagePixelReadAccessor, 3> readAccess(dynamic_cast(inputData.GetPointer())); itk::Index<3> idx; idx[0] = 5; idx[1] = 4; idx[2] = 1; itk::Vector 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/MriSimulation/Algorithms/itkDftImageFilter.cpp b/Modules/MriSimulation/Algorithms/itkDftImageFilter.cpp index 4e5210a..bccf227 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. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; 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 #include #include #include "itkDftImageFilter.h" #include #include #include 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(szx)%2==1) x_shift = (szx-1)/2; else x_shift = szx/2; if (static_cast(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 s(0,0); + std::complex 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(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 c58226e..faefbba 100644 --- a/Modules/MriSimulation/Algorithms/itkDftImageFilter.h +++ b/Modules/MriSimulation/Algorithms/itkDftImageFilter.h @@ -1,79 +1,78 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ /*=================================================================== This file is based heavily on a corresponding ITK filter. ===================================================================*/ #ifndef __itkDftImageFilter_h_ #define __itkDftImageFilter_h_ #include #include -#include #include 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 ImageToImageFilter< Image< std::complex< TPixelType > >, Image< std::complex< TPixelType > > > { public: typedef DftImageFilter Self; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; - typedef ImageToImageFilter< Image< vcl_complex< TPixelType > >, Image< vcl_complex< TPixelType > > > Superclass; + typedef ImageToImageFilter< Image< std::complex< TPixelType > >, Image< std::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/itkKspaceImageFilter.cpp b/Modules/MriSimulation/Algorithms/itkKspaceImageFilter.cpp index 0c5f7bc..d550202 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. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; 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 #include #include #include #include "itkKspaceImageFilter.h" #include #include #include #include #include #include #include #include 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(0,0); + m_Spike = std::complex(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(yMaxFov * m_Parameters->m_SignalGen.m_CroppingFactor); } yMaxFov_half = (yMaxFov-1)/2; numPix = kxMax*kyMax; float ringing_factor = static_cast(m_Parameters->m_SignalGen.m_ZeroRinging)/100.0; ringing_lines_x = static_cast(ceil(kxMax/2 * ringing_factor)); ringing_lines_y = static_cast(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 zero = vcl_complex(0, 0); + std::complex zero = std::complex(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(m_RandGen->GetNormalVariate(0, noiseVar), m_RandGen->GetNormalVariate(0, noiseVar))); + oit.Set(std::complex(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::IndexType index; index[0] = it.GetIndex()[0]; index[1] = it.GetIndex()[1]; index[2] = m_Zidx; itk::Point point3D; m_Parameters->m_SignalGen.m_FrequencyMap->TransformIndexToPhysicalPoint(index, point3D); m_FiberBundle->TransformPoint( point3D, m_RotationMatrix, m_TransX, m_TransY, m_TransZ ); it.Set(mitk::imv::GetImageValue(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; im_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(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(xMax)%2==1) x_shift = (xMax-1)/2; else x_shift = xMax/2; if (static_cast(yMax)%2==1) y_shift = (yMax-1)/2; else y_shift = yMax/2; float kx_shift = 0; float ky_shift = 0; if (static_cast(kxMax)%2==1) kx_shift = (kxMax-1)/2; else kx_shift = kxMax/2; if (static_cast(kyMax)%2==1) ky_shift = (kyMax-1)/2; else ky_shift = kyMax/2; - vcl_complex zero = vcl_complex(0, 0); + std::complex zero = std::complex(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(kyMax)%2 == 0 && !m_Parameters->m_SignalGen.m_ReversePhase) { tick += kxMax; tick %= static_cast(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]m_SignalGen.m_PartialFourier)) && (kIdx[1]>0 || static_cast(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; im_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 s(0,0); + std::complex 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; im_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::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 f(f_real * m_Parameters->m_SignalGen.m_SignalScale, 0); + std::complex f(f_real * m_Parameters->m_SignalGen.m_SignalScale, 0); s += f * std::exp( std::complex(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]m_SignalGen.m_PartialFourier)) && (kIdx[1]>0 || static_cast(kyMax)%2 == 1))) { // calculate symmetric index auto sym = m_ReadoutScheme->GetSymmetricIndex(kIdx); // use complex conjugate of symmetric index value at current index - vcl_complex s = outputImage->GetPixel(sym); - s = vcl_complex(s.real(), -s.imag()); + std::complex s = outputImage->GetPixel(sym); + s = std::complex(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; iGetIntegerVariate()%kxMax; spikeIdx[1] = m_RandGen->GetIntegerVariate()%kyMax; outputImage->SetPixel(spikeIdx, m_Spike); m_SpikeLog += "[" + boost::lexical_cast(spikeIdx[0]) + "," + boost::lexical_cast(spikeIdx[1]) + "," + boost::lexical_cast(m_Zidx) + "] Magnitude: " + boost::lexical_cast(m_Spike.real()) + "+" + boost::lexical_cast(m_Spike.imag()) + "i\n"; } delete m_ReadoutScheme; } } #endif diff --git a/Modules/MriSimulation/Algorithms/itkKspaceImageFilter.h b/Modules/MriSimulation/Algorithms/itkKspaceImageFilter.h index 0fa0b02..9ab858e 100644 --- a/Modules/MriSimulation/Algorithms/itkKspaceImageFilter.h +++ b/Modules/MriSimulation/Algorithms/itkKspaceImageFilter.h @@ -1,160 +1,159 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ /*=================================================================== This file is based heavily on a corresponding ITK filter. ===================================================================*/ #ifndef __itkKspaceImageFilter_h_ #define __itkKspaceImageFilter_h_ #include -#include #include #include #include #include #include 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 ImageSource< Image< std::complex< ScalarType >, 2 > > { public: typedef KspaceImageFilter Self; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; - typedef ImageSource< Image< vcl_complex< ScalarType >, 2 > > Superclass; + typedef ImageSource< Image< std::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 MatrixType; typedef itk::Point 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 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 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 m_Spike; + std::complex 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/itkTractsToDWIImageFilter.cpp b/Modules/MriSimulation/Algorithms/itkTractsToDWIImageFilter.cpp index 2cd0113..69e6f20 100644 --- a/Modules/MriSimulation/Algorithms/itkTractsToDWIImageFilter.cpp +++ b/Modules/MriSimulation/Algorithms/itkTractsToDWIImageFilter.cpp @@ -1,1772 +1,1772 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "itkTractsToDWIImageFilter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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 > coilPositions; itk::Vector pos; pos.Fill(0.0); pos[1] = -diagonal/2; itk::Vector 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 temp_p; temp_p[0] = temp_v[0]; temp_p[1] = temp_v[1]; temp_p[2] = temp_v[2]; m_CoilPointset->InsertPoint(c, temp_p); 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(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(max_threads/out_threads)); } PrintToLog("Parallel volumes: " + boost::lexical_cast(out_threads), false, true, true); PrintToLog("Threads per slice: " + boost::lexical_cast(in_threads), false, true, true); std::list< std::tuple > spikes; if (m_Parameters.m_Misc.m_DoAddSpikes) for (unsigned int i=0; i( 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(num_gradient_volumes)*compartment_images.at(0)->GetLargestPossibleRegion().GetSize(2)); #pragma omp parallel for num_threads(out_threads) for (int g=0; gGetAbortGenerateData()) continue; std::list< std::tuple > spikeSlice; #pragma omp critical { for (auto spike : spikes) if (std::get<0>(spike) == static_cast(g)) spikeSlice.push_back(std::tuple(std::get<1>(spike), std::get<2>(spike))); } for (unsigned int z=0; z compartment_slices; std::vector< float > t2Vector; std::vector< float > t1Vector; for (unsigned int i=0; i* signalModel; if (iSetLargestPossibleRegion( 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; yGetLargestPossibleRegion().GetSize(1); y++) for (unsigned int x=0; xGetLargestPossibleRegion().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(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); + idft->SetNumberOfWorkUnits(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(g) + " Coil " + boost::lexical_cast(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->SetNumberOfWorkUnits(in_threads); dft->Update(); newSlice = dft->GetOutput(); // put slice back into channel g for (unsigned int y=0; yGetLargestPossibleRegion().GetSize(1); y++) for (unsigned int x=0; xGetLargestPossibleRegion().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(magnitudeDwiImage->GetLargestPossibleRegion().GetSize(1)); y++) for (int x=0; x(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()::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; iGetVolumeFractionImage().IsNotNull()) { PrintToLog("Using volume fraction map for fiber compartment " + boost::lexical_cast(i+1), false); fibVolImages++; } } // check for non-fiber volume fraction maps unsigned int nonfibVolImages = 0; for (std::size_t i=0; iGetVolumeFractionImage().IsNotNull()) { PrintToLog("Using volume fraction map for non-fiber compartment " + boost::lexical_cast(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::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 (fibVolImages0) { 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::Pointer wr = itk::ImageFileWriter::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; iSetSpacing( 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 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(m_Parameters.m_SignalGen.m_ImageSpacing[0]) + "," + boost::lexical_cast(m_Parameters.m_SignalGen.m_ImageSpacing[1]) + "," + boost::lexical_cast(m_Parameters.m_SignalGen.m_ImageSpacing[2]) + "]", false); PrintToLog("Output image size: [" + boost::lexical_cast(m_Parameters.m_SignalGen.m_CroppedRegion.GetSize(0)) + "," + boost::lexical_cast(m_Parameters.m_SignalGen.m_CroppedRegion.GetSize(1)) + "," + boost::lexical_cast(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; iSetSpacing( 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(m_WorkingSpacing[0]) + "," + boost::lexical_cast(m_WorkingSpacing[1]) + "," + boost::lexical_cast(m_WorkingSpacing[2]) + "]", false); PrintToLog("Working image size: [" + boost::lexical_cast(m_WorkingImageRegion.GetSize(0)) + "," + boost::lexical_cast(m_WorkingImageRegion.GetSize(1)) + "," + boost::lexical_cast(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; iSetSpacing( 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; gGetLargestPossibleRegion()!=m_WorkingImageRegion) { PrintToLog("Resampling tissue mask", false); // rescale mask image (otherwise there are problems with the resampling) auto rescaler = itk::RescaleIntensityImageFilter::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::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::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::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::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(m_Parameters.m_SignalGen.m_Rotation) + "°", false); PrintToLog("Maximum translation: +/-" + boost::lexical_cast(m_Parameters.m_SignalGen.m_Translation) + "mm", false); } else { PrintToLog("Linear motion artifacts:", false); PrintToLog("Maximum rotation: " + boost::lexical_cast(m_Parameters.m_SignalGen.m_Rotation) + "°", false); PrintToLog("Maximum translation: " + boost::lexical_cast(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()::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 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::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::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, itk::Image >::New(); caster->SetInput(m_TransformedMaskImage); caster->Update(); vtkSmartPointer weights = m_FiberBundle->GetFiberWeights(); float mean_weight = 0; for (int i=0; iGetSize(); i++) mean_weight += weights->GetValue(i); mean_weight /= weights->GetSize(); if (mean_weight>0.000001) for (int i=0; iGetSize(); i++) m_FiberBundle->SetFiberWeight(i, weights->GetValue(i)/mean_weight); else PrintToLog("\nWarning: streamlines have VERY low weights. Average weight: " + boost::lexical_cast(mean_weight) + ". Possible source of calculation errors.", false, true, true); auto density_calculator = itk::TractDensityImageFilter< itk::Image >::New(); density_calculator->SetFiberBundle(m_FiberBundle); density_calculator->SetInputImage(caster->GetOutput()); density_calculator->SetMode(TDI_MODE::DENSITY); 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(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(v) + " ", false, false, true); PrintToLog("\nVolumes: " + boost::lexical_cast(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; gSetSeed(signalModelSeed); for (std::size_t i=0; iSetSeed(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; iGetBufferPointer()); #pragma omp parallel for for( int i=0; iGetAbortGenerateData()) continue; float fiberWeight = m_FiberBundleTransformed->GetFiberWeight(i); if (fiberWeight == 0) continue; int numPoints = -1; std::vector< itk::Vector > points_copy; #pragma omp critical { vtkCell* cell = fiberPolyData->GetCell(i); numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); for (int j=0; jGetPoint(j))); } if (numPoints<2) continue; double seg_volume = fiberWeight*itk::Math::pi*m_mmRadius*m_mmRadius; for( int j=0; jGetAbortGenerateData()) { j=numPoints; continue; } itk::Vector v = points_copy.at(j); itk::Vector 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 startVertex = points_copy.at(j); itk::Index<3> startIndex; itk::ContinuousIndex startIndexCont; m_TransformedMaskImage->TransformPhysicalPointToIndex(startVertex, startIndex); m_TransformedMaskImage->TransformPhysicalPointToContinuousIndex(startVertex, startIndexCont); itk::Point endVertex = points_copy.at(j+1); itk::Index<3> endIndex; itk::ContinuousIndex 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; kSimulateMeasurement(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 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 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; iGetPixel(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(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; iGetPixel(index); pix[g] /= iAxVolume; m_CompartmentImages.at(i)->SetPixel(index, pix); } } else { for (int i=1; iGetPixel(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(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(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(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(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(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(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(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(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(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::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(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(m_Parameters.m_SignalGen.m_NoiseVariance), false); ImageRegionIterator 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; iAddNoise(signal); for (unsigned int i=0; i0) 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::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(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 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(g) + " rotation: " + boost::lexical_cast(rotation[0]) + "," + boost::lexical_cast(rotation[1]) + "," + boost::lexical_cast(rotation[2]) + ";"; m_MotionLog += " translation: " + boost::lexical_cast(m_Translations.back()[0]) + "," + boost::lexical_cast(m_Translations.back()[1]) + "," + boost::lexical_cast(m_Translations.back()[2]) + "\n"; } } template< class PixelType > itk::Point TractsToDWIImageFilter< PixelType >::GetMovedPoint(itk::Index<3>& index, bool forward) { itk::Point 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& 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; iSetInputImage(m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()); double compartment_fraction = mitk::imv::GetImageValue(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; iGetVolumeFractionImage()!=nullptr) { m_DoubleInterpolator->SetInputImage(m_Parameters.m_FiberModelList[i]->GetVolumeFractionImage()); interAxonalVolume = mitk::imv::GetImageValue(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; iGetVolumeFractionImage()!=nullptr) { m_DoubleInterpolator->SetInputImage(m_Parameters.m_NonFiberModelList[i]->GetVolumeFractionImage()); volume = mitk::imv::GetImageValue(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 TractsToDWIImageFilter< PixelType >::GetItkVector(double point[3]) { itk::Vector itkVector; itkVector[0] = point[0]; itkVector[1] = point[1]; itkVector[2] = point[2]; return itkVector; } template< class PixelType > vnl_vector_fixed TractsToDWIImageFilter< PixelType >::GetVnlVector(double point[3]) { vnl_vector_fixed vnlVector; vnlVector[0] = point[0]; vnlVector[1] = point[1]; vnlVector[2] = point[2]; return vnlVector; } template< class PixelType > vnl_vector_fixed TractsToDWIImageFilter< PixelType >::GetVnlVector(Vector& vector) { vnl_vector_fixed 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(hours)); out.append(":"); out.append(boost::lexical_cast(minutes)); out.append(":"); out.append(boost::lexical_cast(seconds)); m_TimeProbe.Start(); return out; } } diff --git a/Modules/MriSimulation/Algorithms/itkTractsToDWIImageFilter.h b/Modules/MriSimulation/Algorithms/itkTractsToDWIImageFilter.h index da734ad..1d66c4d 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. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; 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 #include #include #include #include #include #include #include #include #include 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 ItkDoubleImgType4D; typedef itk::Image ItkDoubleImgType; typedef itk::Image ItkFloatImgType; typedef itk::Image ItkUcharImgType; typedef mitk::FiberBundle::Pointer FiberBundleType; typedef itk::VectorImage< double, 3 > DoubleDwiType; typedef itk::Matrix MatrixType; typedef itk::Image< float, 2 > Float2DImageType; - typedef itk::Image< vcl_complex< float >, 2 > Complex2DImageType; + typedef itk::Image< std::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 GetOutputImagesReal() const { return m_OutputImagesReal; } std::vector GetOutputImagesImag() const { return m_OutputImagesImag; } protected: TractsToDWIImageFilter(); ~TractsToDWIImageFilter() override; itk::Vector GetItkVector(double point[3]); vnl_vector_fixed GetVnlVector(double point[3]); vnl_vector_fixed 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& 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 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; std::ofstream m_Logfile; std::string m_MotionLog; std::string m_SpikeLog; // signal generation FiberBundleType m_FiberBundleTransformed; ///< transformed bundle simulating headmotion itk::Vector m_WorkingSpacing; itk::Point 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; /// m_Translations; ///::Pointer m_DoubleInterpolator; itk::Vector m_NullDir; Float2DImageType::Pointer m_TickImage; Float2DImageType::Pointer m_RfImage; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "itkTractsToDWIImageFilter.cpp" #endif #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 91be44a..d85452d 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. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkDenoisingView.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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& ) { } 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 > ComposeFilterType; m_ImageNode = m_Controls->m_InputImageBox->GetSelectedNode(); mitk::Image::Pointer input_image = dynamic_cast(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; iGetVectorLength(); ++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->SetNoiseModel(NlmFilterType::NoiseModelEnum::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.ivim/src/internal/QmitkIVIMView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.ivim/src/internal/QmitkIVIMView.cpp index 283253f..3176bce 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,1095 +1,1095 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include // 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 #include // itk #include "itkScalarImageToHistogramGenerator.h" #include "itkRegionOfInterestImageFilter.h" #include "itkImageRegionConstIteratorWithIndex.h" // itk/mitk #include "itkDiffusionIntravoxelIncoherentMotionReconstructionImageFilter.h" #include "itkRegularizedIVIMReconstructionFilter.h" #include "mitkImageCast.h" #include #include #include #include #include #include #include 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(OnIvimFitChanged(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_CurveClipboard, SIGNAL(clicked()), this, SLOT(ClipboardCurveButtonClicked()) ); connect( m_Controls->m_ValuesClipboard, SIGNAL(clicked()), this, SLOT(ClipboardStatisticsButtonClicked()) ); connect( m_Controls->m_SavePlot, SIGNAL(clicked()), this, SLOT(SavePlotButtonClicked()) ); // connect all kurtosis actions to a recompute connect( m_Controls->m_KurtosisRangeWidget, SIGNAL( rangeChanged(double, 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_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::Pointer isImagePredicate = mitk::TNodePredicateDataType::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(OnModelTabChanged(int))); } 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_Warning->setVisible(false); OnIvimFitChanged(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; QmitkIVIMView::InitChartIvim(); m_ListenerActive = false; if (this->GetRenderWindowPart()) { m_SliceChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart()); connect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged())); m_ListenerActive = true; } } void QmitkIVIMView::OnModelTabChanged(int tab) { if (tab==0) InitChartIvim(); else if (tab==1) InitChartKurtosis(); UpdateGui(); } void QmitkIVIMView::AddSecondFitPlot() { if (m_Controls->m_ChartWidget->GetDataElementByLabel("signal values (used for second fit)") == nullptr) { std::vector< std::pair > init_data; m_Controls->m_ChartWidget->AddData2D(init_data, "signal values (used for second fit)", QmitkChartWidget::ChartType::scatter); m_Controls->m_ChartWidget->SetColor("signal values (used for second fit)", "white"); m_Controls->m_ChartWidget->SetMarkerSymbol("signal values (used for second fit)", QmitkChartWidget::MarkerSymbol::x_thin); m_Controls->m_ChartWidget->Show(true); m_Controls->m_ChartWidget->SetShowDataPoints(false); m_Controls->m_ChartWidget->SetShowSubchart(false); } } void QmitkIVIMView::RemoveSecondFitPlot() { if (m_Controls->m_ChartWidget->GetDataElementByLabel("signal values (used for second fit)") != nullptr) { m_Controls->m_ChartWidget->RemoveData("signal values (used for second fit)"); m_Controls->m_ChartWidget->Show(true); m_Controls->m_ChartWidget->SetShowDataPoints(false); m_Controls->m_ChartWidget->SetShowSubchart(false); } } void QmitkIVIMView::InitChartIvim() { m_Controls->m_ChartWidget->Clear(); std::vector< std::pair > init_data; m_Controls->m_ChartWidget->AddData2D(init_data, "D-part of fitted model", QmitkChartWidget::ChartType::line); m_Controls->m_ChartWidget->AddData2D(init_data, "fitted model", QmitkChartWidget::ChartType::line); m_Controls->m_ChartWidget->AddData2D(init_data, "signal values", QmitkChartWidget::ChartType::scatter); m_Controls->m_ChartWidget->SetColor("fitted model", "red"); m_Controls->m_ChartWidget->SetColor("signal values", "white"); m_Controls->m_ChartWidget->SetColor("D-part of fitted model", "cyan"); m_Controls->m_ChartWidget->SetYAxisScale(QmitkChartWidget::AxisScale::log); m_Controls->m_ChartWidget->SetYAxisLabel("S/S0"); m_Controls->m_ChartWidget->SetXAxisLabel("b-value"); m_Controls->m_ChartWidget->SetLineStyle("fitted model", QmitkChartWidget::LineStyle::solid); m_Controls->m_ChartWidget->SetLineStyle("D-part of fitted model", QmitkChartWidget::LineStyle::dashed); m_Controls->m_ChartWidget->SetMarkerSymbol("signal values", QmitkChartWidget::MarkerSymbol::diamond); m_Controls->m_ChartWidget->Show(true); m_Controls->m_ChartWidget->SetShowDataPoints(false); m_Controls->m_ChartWidget->SetShowSubchart(false); } void QmitkIVIMView::InitChartKurtosis() { m_Controls->m_ChartWidget->Clear(); std::vector< std::pair > init_data; m_Controls->m_ChartWidget->AddData2D(init_data, "D-part of fitted model", QmitkChartWidget::ChartType::line); m_Controls->m_ChartWidget->AddData2D(init_data, "fitted model", QmitkChartWidget::ChartType::line); m_Controls->m_ChartWidget->AddData2D(init_data, "signal values", QmitkChartWidget::ChartType::scatter); m_Controls->m_ChartWidget->SetColor("fitted model", "red"); m_Controls->m_ChartWidget->SetColor("signal values", "white"); m_Controls->m_ChartWidget->SetColor("D-part of fitted model", "cyan"); m_Controls->m_ChartWidget->SetYAxisScale(QmitkChartWidget::AxisScale::log); m_Controls->m_ChartWidget->SetYAxisLabel("S"); m_Controls->m_ChartWidget->SetXAxisLabel("b-value"); m_Controls->m_ChartWidget->SetLineStyle("fitted model", QmitkChartWidget::LineStyle::solid); m_Controls->m_ChartWidget->SetLineStyle("D-part of fitted model", QmitkChartWidget::LineStyle::dashed); m_Controls->m_ChartWidget->SetMarkerSymbol("signal values", QmitkChartWidget::MarkerSymbol::diamond); m_Controls->m_ChartWidget->Show(true); m_Controls->m_ChartWidget->SetShowDataPoints(false); m_Controls->m_ChartWidget->SetShowSubchart(false); } void QmitkIVIMView::SetFocus() { m_Controls->m_ButtonAutoThres->setFocus(); } void QmitkIVIMView::Checkbox() { OnSliceChanged(); } void QmitkIVIMView::OnIvimFitChanged(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() { m_Controls->m_FittedParamsLabel->setText(""); if (m_Controls->m_DwiBox->GetSelectedNode().IsNotNull()) { m_Controls->m_ChartWidget->setVisible(true); m_HoldUpdate = false; } else { m_Controls->m_ChartWidget->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& ) { // 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(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 ImgType; ImgType::Pointer img = ImgType::New(); mitk::CastToItkImage(dimg, img); itk::ImageRegionIterator itw (img, img->GetLargestPossibleRegion() ); itw.GoToBegin(); itk::ImageRegionConstIterator 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(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( m_Controls->m_SigmaSpinBox->value() ); if( m_Controls->m_UseKurtosisBoundsCB->isChecked() ) filter->SetBoundariesForKurtosis( m_Controls->m_KurtosisRangeWidget->minimumValue(), m_Controls->m_KurtosisRangeWidget->maximumValue() ); filter->SetFittingScale( static_cast(m_Controls->m_KurtosisFitScale->currentIndex() ) ); if( m_Controls->m_MaskBox->GetSelectedNode().IsNotNull() ) { mitk::Image::Pointer maskImg = dynamic_cast(m_Controls->m_MaskBox->GetSelectedNode()->GetData()); typedef itk::Image 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( 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( 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_DwiBox->GetSelectedNode().IsNull()) return; mitk::Image::Pointer diffusionImg = dynamic_cast(m_Controls->m_DwiBox->GetSelectedNode()->GetData()); mitk::Image::Pointer maskImg = nullptr; if (m_Controls->m_MaskBox->GetSelectedNode().IsNotNull()) maskImg = dynamic_cast(m_Controls->m_MaskBox->GetSelectedNode()->GetData()); if (!this->GetRenderWindowPart()) return; if (!m_ListenerActive) { m_SliceChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart()); connect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged())); m_ListenerActive = true; } VecImgType::Pointer vecimg = VecImgType::New(); mitk::CastToItkImage(diffusionImg, vecimg); VecImgType::Pointer roiImage = VecImgType::New(); if(maskImg.IsNull()) { int roisize = 0; if(m_Controls->m_MethodCombo->currentIndex() == 4) roisize = 3; 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)); typedef itk::ImageRegionIterator VectorIteratorType; VectorIteratorType vecit(vecimg, vecimg->GetRequestedRegion() ); vecit.GoToBegin(); typedef itk::ImageRegionIterator VectorIteratorType; VectorIteratorType vecit2(roiImage, roiImage->GetLargestPossibleRegion() ); vecit2.GoToBegin(); while( !vecit.IsAtEnd() ) { vecit2.Set(vecit.Get()); ++vecit; ++vecit2; } if( m_Controls->m_ModelTabSelectionWidget->currentIndex() ) { FitKurtosis(roiImage, mitk::DiffusionPropertyHelper::GetGradientContainer(diffusionImg), mitk::DiffusionPropertyHelper::GetReferenceBValue(diffusionImg), newstart); } else { FittIVIM(roiImage, mitk::DiffusionPropertyHelper::GetGradientContainer(diffusionImg), mitk::DiffusionPropertyHelper::GetReferenceBValue(diffusionImg), false, crosspos); } } else { typedef itk::Image 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 vecit(vecimg, vecimg->GetLargestPossibleRegion()); itk::VariableLengthVector 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() ) { FitKurtosis(roiImage, mitk::DiffusionPropertyHelper::GetGradientContainer(diffusionImg), mitk::DiffusionPropertyHelper::GetReferenceBValue(diffusionImg), index); } else { 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() ); } bool QmitkIVIMView::FitKurtosis( itk::VectorImage *vecimg, DirContainerType::ConstPointer dirs, float bval, OutImgType::IndexType &crosspos ) { KurtosisFilterType::Pointer filter = KurtosisFilterType::New(); itk::KurtosisFitConfiguration fit_config; fit_config.omit_bzero = m_Controls->m_OmitBZeroCB->isChecked(); if( m_Controls->m_UseKurtosisBoundsCB->isChecked() ) { fit_config.use_K_limits = true; vnl_vector_fixed k_limits; k_limits[0] = m_Controls->m_KurtosisRangeWidget->minimumValue(); k_limits[1] = m_Controls->m_KurtosisRangeWidget->maximumValue(); fit_config.K_limits = k_limits; } fit_config.fit_scale = static_cast(m_Controls->m_KurtosisFitScale->currentIndex() ); m_KurtosisSnap = filter->GetSnapshot( vecimg->GetPixel( crosspos ), dirs, bval, fit_config ); QString param_label_text("K=%2, D=%1"); param_label_text = param_label_text.arg( m_KurtosisSnap.m_K, 4); param_label_text = param_label_text.arg( m_KurtosisSnap.m_D, 4); m_Controls->m_FittedParamsLabel->setText(param_label_text); const double maxb = m_KurtosisSnap.bvalues.max_value(); double S0 = m_KurtosisSnap.m_Bzero; if (m_KurtosisSnap.m_fittedBZero) S0 = m_KurtosisSnap.m_BzeroFit; std::vector< std::pair > d_line; d_line.emplace_back(0, S0); d_line.emplace_back(maxb, S0*exp(-maxb * m_KurtosisSnap.m_D)); m_Controls->m_ChartWidget->UpdateData2D(d_line, "D-part of fitted model"); const unsigned int num_samples = 50; std::vector< std::pair > y; for( unsigned int i=0; i<=num_samples; ++i) { double b = (((1.0)*i)/(1.0*num_samples))*maxb; y.emplace_back(b, S0 * exp( -b * m_KurtosisSnap.m_D + b*b * m_KurtosisSnap.m_D * m_KurtosisSnap.m_D * m_KurtosisSnap.m_K / 6.0 )); } m_Controls->m_ChartWidget->UpdateData2D(y, "fitted model"); std::vector< std::pair > y_meas; for (unsigned int i=0; im_OmitBZeroCB->isChecked() || m_KurtosisSnap.bvalues[i] > 0.01) y_meas.emplace_back(m_KurtosisSnap.bvalues[i], m_KurtosisSnap.measurements[i]); } m_Controls->m_ChartWidget->UpdateData2D(y_meas, "signal values"); return true; } bool QmitkIVIMView::FittIVIM(itk::VectorImage* vecimg, DirContainerType::ConstPointer 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->SetNumberOfWorkUnits(1); filter->SetVerbose(false); filter->SetCrossPosition(crosspos); try{ filter->Update(); m_IvimSnap = filter->GetSnapshot(); m_DStarMap = filter->GetOutput(2); m_DMap = filter->GetOutput(1); m_fMap = filter->GetOutput(); QString param_label_text("f=%1, D=%2, D*=%3"); param_label_text = param_label_text.arg(m_IvimSnap.currentF,4); param_label_text = param_label_text.arg(m_IvimSnap.currentD,4); param_label_text = param_label_text.arg(m_IvimSnap.currentDStar,4); m_Controls->m_FittedParamsLabel->setText(param_label_text); double maxb = m_IvimSnap.bvalues.max_value(); std::vector< std::pair > d_line; d_line.emplace_back(0, 1-m_IvimSnap.currentFunceiled); d_line.emplace_back(maxb, d_line[0].second*exp(-maxb * m_IvimSnap.currentD)); m_Controls->m_ChartWidget->UpdateData2D(d_line, "D-part of fitted model"); std::vector< std::pair > y; int nsampling = 50; double f = 1-m_IvimSnap.currentFunceiled; for(int i=0; i<=nsampling; i++) { double x = (((1.0)*i)/(1.0*nsampling))*maxb; y.emplace_back(x, f*exp(- x * m_IvimSnap.currentD) + (1-f)*exp(- x * (m_IvimSnap.currentD+m_IvimSnap.currentDStar))); } m_Controls->m_ChartWidget->UpdateData2D(y, "fitted model"); std::vector< std::pair > y_meas; for (unsigned int i=0; im_ChartWidget->UpdateData2D(y_meas, "signal values"); if(m_IvimSnap.bvals2.size() > 0) { AddSecondFitPlot(); std::vector< std::pair > additonal_meas; for (int i=0; i(m_IvimSnap.bvals2.size()); ++i) additonal_meas.emplace_back(m_IvimSnap.bvals2[i], m_IvimSnap.meas2[i]); m_Controls->m_ChartWidget->UpdateData2D(additonal_meas, "signal values (used for second fit)"); } else { RemoveSecondFitPlot(); } } 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("D* Fit-%1").arg(m_Controls->m_MethodCombo->currentIndex()+1); mitk::DataNode::Pointer node2=mitk::DataNode::New(); node2->SetData( dstarimage ); node2->SetName(newname2.toLatin1()); node2->SetProperty("LookupTable", lut_prop ); mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); mitk::LevelWindow levelwindow; levelwindow.SetRangeMinMax(0, 0.2); levWinProp->SetLevelWindow(levelwindow); node2->SetProperty("levelwindow", levWinProp); 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("D Fit-%1").arg(m_Controls->m_MethodCombo->currentIndex()+1); mitk::DataNode::Pointer node1=mitk::DataNode::New(); node1->SetData( dimage ); node1->SetName(newname1.toLatin1()); node1->SetProperty("LookupTable", lut_prop ); mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); mitk::LevelWindow levelwindow; levelwindow.SetRangeMinMax(0, 0.003); levWinProp->SetLevelWindow(levelwindow); node1->SetProperty("levelwindow", levWinProp); 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("f Fit-%1").arg(m_Controls->m_MethodCombo->currentIndex()+1); mitk::DataNode::Pointer node3=mitk::DataNode::New(); node3->SetData( image ); node3->SetName(newname0.toLatin1()); node3->SetProperty("LookupTable", lut_prop ); mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); mitk::LevelWindow levelwindow; levelwindow.SetRangeMinMax(0, 1); levWinProp->SetLevelWindow(levelwindow); node3->SetProperty("levelwindow", levWinProp); GetDataStorage()->Add(node3, node); } this->GetRenderWindowPart()->RequestUpdate(); } 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 { std::stringstream ss; QString clipboard("Normalized Measurement Points\n"); ss << m_IvimSnap.bvalues << "\n" << m_IvimSnap.allmeas << "\n\n"; ss << "Fitted Values ( f D D* ) \n" << m_IvimSnap.currentF << " " << m_IvimSnap.currentD << " " << m_IvimSnap.currentDStar; ss << "\n\n"; clipboard.append( QString( ss.str().c_str() )); ss.str( std::string() ); ss.clear(); QApplication::clipboard()->setText(clipboard, QClipboard::Clipboard ); } } void QmitkIVIMView::SavePlotButtonClicked() { m_Controls->m_ChartWidget->SavePlotAsImage(); } 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_IvimSnap.currentF, 0, 'f', 10 ) .arg( m_IvimSnap.currentD, 0, 'f', 10 ) .arg( m_IvimSnap.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; if (this->GetRenderWindowPart() && !m_ListenerActive) { m_SliceChangeListener.RenderWindowPartActivated(this->GetRenderWindowPart()); connect(&m_SliceChangeListener, SIGNAL(SliceChanged()), this, SLOT(OnSliceChanged())); m_ListenerActive = true; } } void QmitkIVIMView::Hidden() { m_Visible = false; } 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 88e6e71..6491926 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. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; 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 #include #include #include #include #include #include #include #include #include #include #include #include #include "QmitkSliderNavigatorWidget.h" #include #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 #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 #include #include #include #include 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 ImageType; typedef itk::Image FloatImageType; typedef itk::Image, 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( this, &QmitkPartialVolumeAnalysisView::NodeAddedInDataStorage ); m_SelectedPlanarFigureNodes->NodeChanged.RemoveListener( mitk::MessageDelegate1( this, &QmitkPartialVolumeAnalysisView::NodeChanged ) ); m_SelectedPlanarFigureNodes->NodeRemoved.RemoveListener( mitk::MessageDelegate1( this, &QmitkPartialVolumeAnalysisView::NodeRemoved ) ); m_SelectedPlanarFigureNodes->PropertyChanged.RemoveListener( mitk::MessageDelegate2( this, &QmitkPartialVolumeAnalysisView::PropertyChanged ) ); m_SelectedImageNodes->NodeChanged.RemoveListener( mitk::MessageDelegate1( this, &QmitkPartialVolumeAnalysisView::NodeChanged ) ); m_SelectedImageNodes->NodeRemoved.RemoveListener( mitk::MessageDelegate1( this, &QmitkPartialVolumeAnalysisView::NodeRemoved ) ); m_SelectedImageNodes->PropertyChanged.RemoveListener( mitk::MessageDelegate2( 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( this, &QmitkPartialVolumeAnalysisView::NodeChanged ) ); m_SelectedPlanarFigureNodes->NodeRemoved.AddListener( mitk::MessageDelegate1( this, &QmitkPartialVolumeAnalysisView::NodeRemoved ) ); m_SelectedPlanarFigureNodes->PropertyChanged.AddListener( mitk::MessageDelegate2( this, &QmitkPartialVolumeAnalysisView::PropertyChanged ) ); m_SelectedImageNodes = mitk::DataStorageSelection::New(this->GetDataStorage(), false); m_SelectedImageNodes->PropertyChanged.AddListener( mitk::MessageDelegate2( this, &QmitkPartialVolumeAnalysisView::PropertyChanged ) ); m_SelectedImageNodes->NodeChanged.AddListener( mitk::MessageDelegate1( this, &QmitkPartialVolumeAnalysisView::NodeChanged ) ); m_SelectedImageNodes->NodeRemoved.AddListener( mitk::MessageDelegate1( this, &QmitkPartialVolumeAnalysisView::NodeRemoved ) ); this->GetDataStorage()->AddNodeEvent.AddListener( mitk::MessageDelegate1( 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 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 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(m_ClusteringResult->GetData()); typedef itk::Image< itk::RGBAPixel, 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 SegImageType; SegImageType::Pointer mask_itk = SegImageType::New(); typedef mitk::ImageToItk 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 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 point; caster->GetOutput()->TransformIndexToPhysicalPoint(index,point); itk::Point newPoint; newPoint = trafo->TransformPoint(point); 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(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 selectedNodes = this->GetDataManagerSelection(); for(int i = 0; i < selectedNodes.size(); ++i) { selectedNodes[i]->SetSelected(false); } std::vector 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 (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 (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 &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; iRemoveOrphanImages(); 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("mandatory"); 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("mandatory"); } 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 MaskImageType; - mitk::Image::Pointer mask = 0; - MaskImageType::Pointer itkmask = 0; + mitk::Image::Pointer mask; + MaskImageType::Pointer itkmask; if(m_IsTensorImage && m_Controls->m_SimilarAnglesSlider->value() != 0) { typedef itk::Image AngularErrorImageType; typedef mitk::ImageToItk 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,3> RGBImageType; typedef mitk::ImageToItk 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 UCharImageType; UCharImageType::Pointer charImage; if(pixelType.GetComponentTypeAsString() == "short" ) { typedef itk::Image 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 ImageCasterType; ImageCasterType::Pointer caster = ImageCasterType::New(); caster->SetInput( duplicator->GetOutput() ); caster->Update(); charImage = caster->GetOutput(); } else { typedef itk::Image 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 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("mandatory"); // 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->GetVtkRenderWindow())->InsertForegroundRenderer( m_MeasurementInfoRenderer, true); } else { if (mitk::VtkLayerController::GetInstance( m_LastRenderWindow->GetVtkRenderWindow()) ->IsRendererInserted( m_MeasurementInfoRenderer)) mitk::VtkLayerController::GetInstance(m_LastRenderWindow->GetVtkRenderWindow())->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")->GetVtkRenderWindow())->InsertForegroundRenderer( m_MeasurementInfoRenderer, true); } else { if (mitk::VtkLayerController::GetInstance( renderWindowPart->GetQmitkRenderWindow("axial")->GetVtkRenderWindow()) ->IsRendererInserted( m_MeasurementInfoRenderer)) mitk::VtkLayerController::GetInstance(renderWindowPart->GetQmitkRenderWindow("axial")->GetVtkRenderWindow())->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, 3> TensorImageType; typedef mitk::ImageToItk CastType; CastType::Pointer caster = CastType::New(); caster->SetInput(tensorimage); caster->Update(); TensorImageType::Pointer image = caster->GetOutput(); typedef itk::TensorDerivedMeasurementsFilter 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 itd(dirImage, dirImage->GetLargestPossibleRegion()); itd.GoToBegin(); while( !itd.IsAtEnd() ) { DirImageType::PixelType direction = itd.Get(); direction = fabs(direction); itd.Set(direction); ++itd; } typedef itk::Image 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 it1(comp1, comp1->GetLargestPossibleRegion()); itk::ImageRegionIterator 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; + mitk::PlanarFigureInteractor::Pointer figureInteractor; // finally add all nodes to the model for(mitk::DataStorage::SetOfObjects::ConstIterator it=_NodeSet->Begin(); it!=_NodeSet->End() ; it++) { node = const_cast(it->Value().GetPointer()); figure = dynamic_cast(node->GetData()); if(figure) { figureInteractor = dynamic_cast(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; + mitk::PlanarFigureInteractor::Pointer figureInteractor; // finally add all nodes to the model for(mitk::DataStorage::SetOfObjects::ConstIterator it=_NodeSet->Begin(); it!=_NodeSet->End() ; it++) { node = const_cast(it->Value().GetPointer()); figure = dynamic_cast(node->GetData()); if(figure) { figureInteractor = dynamic_cast(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* > vals = m_Controls->m_HistogramWidget->m_Vals; QString clipboardText; for (std::vector* >::iterator it = vals.begin(); it != vals.end(); ++it) { for (std::vector::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(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(node); mitk::PlanarFigure* figure = dynamic_cast(nonConstNode->GetData()); if(figure) { // set interactor for new node (if not already set) mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(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.preprocessing/src/internal/QmitkPreprocessingView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging.preprocessing/src/internal/QmitkPreprocessingView.cpp index ae57c25..d8bd713 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,2024 +1,2022 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //#define MBILOG_ENABLE_DEBUG #include "QmitkPreprocessingView.h" #include "mitkDiffusionImagingConfigure.h" // qt includes #include // itk includes #include "itkTimeProbe.h" #include "itkB0ImageExtractionImageFilter.h" #include "itkB0ImageExtractionToSeparateImageFilter.h" #include "itkBrainMaskExtractionImageFilter.h" #include "itkCastImageFilter.h" #include "itkVectorContainer.h" #include #include #include #include #include #include // Multishell includes #include // Multishell Functors #include #include #include #include // 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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::Pointer isMitkImage = mitk::TNodePredicateDataType::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_SwapGradientsButton), SIGNAL(clicked()), this, SLOT(DoSwapGradientDimensions()) ); 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(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(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(node->GetData()); if ( image == nullptr ) { return; } bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(node) ); if (isDiffusionImage) { ItkDwiType::Pointer itkVectorImagePointer = ItkDwiType::New(); mitk::CastToItkImage(image, itkVectorImagePointer); itk::FixedArray 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; iSize(); 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* itkImage) { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } itk::FixedArray 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 >::Pointer flipper = itk::FlipImageFilter< itk::Image >::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(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(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(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 origin = itkOutImage->GetOrigin(); itk::Point 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* 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 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 origin = itkOutImage->GetOrigin(); itk::Point 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(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(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(true); 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* 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 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 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 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::Pointer interp = itk::NearestNeighborInterpolateImageFunction::New(); resampler->SetInterpolator(interp); outAdd = "NearestNeighbour"; break; } case 1: { typename itk::LinearInterpolateImageFunction::Pointer interp = itk::LinearInterpolateImageFunction::New(); resampler->SetInterpolator(interp); outAdd = "Linear"; break; } case 2: { typename itk::BSplineInterpolateImageFunction::Pointer interp = itk::BSplineInterpolateImageFunction::New(); resampler->SetInterpolator(interp); outAdd = "BSpline"; break; } case 3: { typename itk::WindowedSincInterpolateImageFunction::Pointer interp = itk::WindowedSincInterpolateImageFunction::New(); resampler->SetInterpolator(interp); outAdd = "WindowedSinc"; break; } default: { typename itk::NearestNeighborInterpolateImageFunction::Pointer interp = itk::NearestNeighborInterpolateImageFunction::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(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(node->GetData()) ) isDti = true; else if ( dynamic_cast(node->GetData()) ) isOdf = true; else if ( dynamic_cast(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::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(newImage); mitk::Image::Pointer tensorImage = dynamic_cast(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(newImage); mitk::Image::Pointer peakImage = dynamic_cast(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(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; isize(); i++) { GradientDirectionType g = gradientContainer->GetElement(i); if (g.magnitude()<0.001) { b0Index = i; break; } } if (b0Index==-1) { return; } typedef itk::DwiNormilzationFilter 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(m_Controls->m_NormalizationMaskBox->GetSelectedNode()->GetData()) != nullptr ) { mitk::CastToItkImage( dynamic_cast(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(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 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::ConstPointer 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(); + mitk::DataNode::Pointer 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(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 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(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 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(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 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(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; jSize(); j++) { auto g = gradientContainer->at(j); g = g.normalize(); if (g[0]>=0) text += " "; text += QString::number(g[0]); if (jSize()-1) text += " "; else text += "\n"; } for (unsigned int j=0; jSize(); j++) { auto g = gradientContainer->at(j); g = g.normalize(); if (g[1]>=0) text += " "; text += QString::number(g[1]); if (jSize()-1) text += " "; else text += "\n"; } for (unsigned int j=0; jSize(); j++) { auto g = gradientContainer->at(j); g = g.normalize(); if (g[2]>=0) text += " "; text += QString::number(g[2]); if (jSize()-1) text += " "; else text += "\n"; } m_Controls->m_WorkingGradientsText->setPlainText(text); gradientContainer = PropHelper::GetOriginalGradientContainer(image); text = ""; for (unsigned int j=0; jSize(); j++) { auto g = gradientContainer->at(j); g = g.normalize(); if (g[0]>=0) text += " "; text += QString::number(g[0]); if (jSize()-1) text += " "; else text += "\n"; } for (unsigned int j=0; jSize(); j++) { auto g = gradientContainer->at(j); g = g.normalize(); if (g[1]>=0) text += " "; text += QString::number(g[1]); if (jSize()-1) text += " "; else text += "\n"; } for (unsigned int j=0; jSize(); j++) { auto g = gradientContainer->at(j); g = g.normalize(); if (g[2]>=0) text += " "; text += QString::number(g[2]); if (jSize()-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(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& 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(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_SwapGradientsButton->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(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(node->GetData()); if ( image == nullptr ) { return; } mitk::Image::Pointer newDwi = image->Clone(); auto gradientContainer = PropHelper::GetGradientContainer(newDwi); auto newGradientContainer = PropHelper::GradientDirectionsContainerType::New(); for (unsigned int j=0; jSize(); j++) { PropHelper::GradientDirectionType g; g[0] = gradientContainer->at(j)[0]; g[1] = gradientContainer->at(j)[1]; g[2] = gradientContainer->at(j)[2]; if (m_Controls->m_FlipGradBoxX->isChecked()) { g[0] *= -1; } if (m_Controls->m_FlipGradBoxY->isChecked()) { g[1] *= -1; } if (m_Controls->m_FlipGradBoxZ->isChecked()) { g[2] *= -1; } newGradientContainer->push_back(g); } PropHelper::CopyProperties(image, newDwi, true); PropHelper::SetGradientContainer(newDwi, newGradientContainer); 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::DoSwapGradientDimensions() { mitk::DataNode::Pointer node = m_Controls->m_SelctedImageComboBox->GetSelectedNode(); if (node.IsNull()) { return; } mitk::Image::Pointer image = dynamic_cast(node->GetData()); if ( image == nullptr ) { return; } mitk::Image::Pointer newDwi = image->Clone(); auto gradientContainer = PropHelper::GetGradientContainer(newDwi); auto newGradientContainer = PropHelper::GradientDirectionsContainerType::New(); std::vector dims_split; std::string swap_string = m_Controls->m_SwapGradientsEdit->text().toStdString(); boost::split(dims_split, swap_string, boost::is_any_of(" "), boost::token_compress_on); std::vector dims_split_clean; for (auto s : dims_split) { if (s=="x") dims_split_clean.push_back(0); else if (s=="y") dims_split_clean.push_back(1); else if (s=="z") dims_split_clean.push_back(2); } if (dims_split_clean.size()!=3) { QMessageBox::warning(nullptr,"Warning", QString("String should contain x, y and z in arbitrary order separated by a space.") ); return; } for (unsigned int j=0; jSize(); j++) { PropHelper::GradientDirectionType g; g[0] = gradientContainer->at(j)[dims_split_clean.at(0)]; g[1] = gradientContainer->at(j)[dims_split_clean.at(1)]; g[2] = gradientContainer->at(j)[dims_split_clean.at(2)]; newGradientContainer->push_back(g); } PropHelper::CopyProperties(image, newDwi, true); PropHelper::SetGradientContainer(newDwi, newGradientContainer); PropHelper::InitializeImage( newDwi ); mitk::DataNode::Pointer imageNode = mitk::DataNode::New(); imageNode->SetData( newDwi ); QString name = node->GetName().c_str(); imageNode->SetName( (name+"_GradientDimSwapped").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(node->GetData()); if ( image == nullptr ) { return; } mitk::Image::Pointer newDwi = image->Clone(); auto gradientContainer = PropHelper::GetGradientContainer(newDwi); auto newGradientContainer = PropHelper::GradientDirectionsContainerType::New(); for (unsigned int j=0; jSize(); j++) { PropHelper::GradientDirectionType g; g[0] = gradientContainer->at(j)[0]; g[1] = gradientContainer->at(j)[1]; g[2] = gradientContainer->at(j)[2]; if (g[0]<0) { g = -g; } newGradientContainer->push_back(g); } PropHelper::CopyProperties(image, newDwi, true); PropHelper::SetGradientContainer(newDwi, newGradientContainer); 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(node->GetData()); if ( image == nullptr ) { return; } bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( !isDiffusionImage ) { return; } int maxIndex = 0; unsigned int maxSize = image->GetDimension(0); if (maxSizeGetDimension(1)) { maxSize = image->GetDimension(1); maxIndex = 1; } if (maxSizeGetDimension(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; jsecond.size(); j++) { mitk::Point3D ip; vnl_vector_fixed< double, 3 > v = gradientContainer->at(it->second[j]); if (v.magnitude()>mitk::eps) { ip[0] = v[0]*maxSize*geometry->GetSpacing()[maxIndex]/2 + origin[0]-0.5*geometry->GetSpacing()[0] + geometry->GetSpacing()[0]*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(node->GetData()); if ( image == nullptr ) { return; } bool isDiffusionImage( PropHelper::IsDiffusionWeightedImage(image) ); if ( !isDiffusionImage ) { return; } typedef itk::ElectrostaticRepulsionDiffusionGradientReductionFilter FilterType; typedef mitk::BValueMapProperty::BValueMap BValueMap; // GetShellSelection from GUI BValueMap shellSlectionMap; BValueMap originalShellMap = PropHelper::GetBValueMap(image); std::vector newNumGradientDirections; int shellCounter = 0; QString name = node->GetName().c_str(); for (int i=0; im_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(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(node2->GetData()); if ( image2 == nullptr ) { return; } typedef itk::VectorImage DwiImageType; typedef std::vector< DwiImageType::Pointer > DwiImageContainerType; typedef std::vector< GradientContainerType::ConstPointer > 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 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(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 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(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(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/src/internal/QmitkControlVisualizationPropertiesView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.cpp index 83a010e..9bb2ae0 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkControlVisualizationPropertiesView.cpp @@ -1,1238 +1,1238 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "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 #include #include #include #include #include "usModuleRegistry.h" #include #include #include "mitkPlaneGeometry.h" #include #include #include #include #include "berryIWorkbenchWindow.h" #include "berryIWorkbenchPage.h" #include "berryISelectionService.h" #include "berryConstants.h" #include "berryPlatformUI.h" #include "itkRGBAPixel.h" #include #include "qwidgetaction.h" #include "qcolordialog.h" #include -#include +#include #include #include #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); + auto numThread = itk::MultiThreaderBase::GetGlobalMaximumNumberOfThreads(); + itk::MultiThreaderBase::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(c.redF()); rgb[1] = static_cast(c.greenF()); rgb[2] = static_cast(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 void QmitkControlVisualizationPropertiesView::CreateConnections() { if ( m_Controls ) { connect( static_cast(m_Controls->m_VisibleOdfsON_T), SIGNAL(clicked()), this, SLOT(VisibleOdfsON_T()) ); connect( static_cast(m_Controls->m_VisibleOdfsON_S), SIGNAL(clicked()), this, SLOT(VisibleOdfsON_S()) ); connect( static_cast(m_Controls->m_VisibleOdfsON_C), SIGNAL(clicked()), this, SLOT(VisibleOdfsON_C()) ); connect( static_cast(m_Controls->m_ShowMaxNumber), SIGNAL(editingFinished()), this, SLOT(ShowMaxNumberChanged()) ); connect( static_cast(m_Controls->m_NormalizationDropdown), SIGNAL(currentIndexChanged(int)), this, SLOT(NormalizationDropdownChanged(int)) ); connect( static_cast(m_Controls->m_ScalingFactor), SIGNAL(valueChanged(double)), this, SLOT(ScalingFactorChanged(double)) ); connect( static_cast(m_Controls->m_AdditionalScaling), SIGNAL(currentIndexChanged(int)), this, SLOT(AdditionalScaling(int)) ); connect(static_cast(m_Controls->m_ResetColoring), SIGNAL(clicked()), static_cast(this), SLOT(ResetColoring())); connect(static_cast(m_Controls->m_ResetColoring2), SIGNAL(clicked()), static_cast(this), SLOT(ResetColoring())); connect(static_cast(m_Controls->m_FiberFading2D), SIGNAL(clicked()), static_cast(this), SLOT( Fiber2DfadingEFX() ) ); connect(static_cast(m_Controls->m_FiberClippingBox), SIGNAL(editingFinished()), static_cast(this), SLOT( FiberSlicingThickness2D() ) ); connect(static_cast(m_Controls->m_Crosshair), SIGNAL(clicked()), static_cast(this), SLOT(SetInteractor())); connect(static_cast(m_Controls->m_LineWidth), SIGNAL(editingFinished()), static_cast(this), SLOT(LineWidthChanged())); connect(static_cast(m_Controls->m_TubeWidth), SIGNAL(editingFinished()), static_cast(this), SLOT(TubeRadiusChanged())); connect(static_cast(m_Controls->m_RibbonWidth), SIGNAL(editingFinished()), static_cast(this), SLOT(RibbonWidthChanged())); connect( static_cast(m_Controls->m_OdfColorBox), SIGNAL(currentIndexChanged(int)), static_cast(this), SLOT(OnColourisationModeChanged() ) ); connect(static_cast(m_Controls->m_Clip0), SIGNAL(toggled(bool)), static_cast(this), SLOT(Toggle3DClipping(bool))); connect(static_cast(m_Controls->m_Clip1), SIGNAL(toggled(bool)), static_cast(this), SLOT(Toggle3DClipping(bool))); connect(static_cast(m_Controls->m_Clip2), SIGNAL(toggled(bool)), static_cast(this), SLOT(Toggle3DClipping(bool))); connect(static_cast(m_Controls->m_Clip3), SIGNAL(toggled(bool)), static_cast(this), SLOT(Toggle3DClipping(bool))); connect(static_cast(m_Controls->m_FlipClipBox), SIGNAL(stateChanged(int)), static_cast(this), SLOT(Toggle3DClipping())); connect(static_cast(m_Controls->m_Enable3dPeaks), SIGNAL(stateChanged(int)), static_cast(this), SLOT(Toggle3DPeaks())); connect(static_cast(m_Controls->m_FlipPeaksButton), SIGNAL(clicked()), static_cast(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(node); bool isDiffusionImage( mitk::DiffusionPropertyHelper::IsDiffusionWeightedImage( dynamic_cast(node->GetData())) ); if (isDiffusionImage) { mitk::Image::Pointer dimg = dynamic_cast(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& 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(nodeData)) { m_Controls->m_PeakImageFrame->setVisible(true); if (m_Color.IsNotNull()) m_Color->RemoveObserver(m_ColorPropertyObserverTag); itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkControlVisualizationPropertiesView::SetCustomColor ); m_Color = dynamic_cast(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(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::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkControlVisualizationPropertiesView::SetCustomColor ); m_Color = dynamic_cast(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(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_FiberClippingBox->setMaximum(max); m_Controls->m_FiberClippingBox->setValue(range); } else if(dynamic_cast(nodeData) || dynamic_cast(nodeData) || dynamic_cast(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(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(node->GetProperty("Normalization"))->GetValueAsId()); float fval; node->GetFloatProperty("Scaling",fval); m_Controls->m_ScalingFactor->setValue(fval); m_Controls->m_AdditionalScaling->setCurrentIndex(dynamic_cast(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(nodeData)) { PlanarFigureFocus(); } else if( dynamic_cast(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(node->GetProperty( "reslice.thickslices" )); if( m.IsNotNull() ) currentTSMode = m->GetValueAsId(); } int maxTS = 30; for (auto node: nodes) { mitk::Image* image = dynamic_cast(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(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(m_SelectedNode->GetData())==nullptr) return; std::string name = m_SelectedNode->GetName(); mitk::Image::Pointer image = dynamic_cast(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::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(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(m_SelectedNode->GetData())==nullptr && dynamic_cast(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; iSize(); ++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(node->GetData()) || dynamic_cast(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(node->GetData())) dynamic_cast(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( 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 ( 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 ( 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 ( 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(m_SelectedNode->GetData()) || dynamic_cast(m_SelectedNode->GetData()) || dynamic_cast(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(m_SelectedNode->GetData()) || dynamic_cast(m_SelectedNode->GetData()) || dynamic_cast(m_SelectedNode->GetData()) ) { m_SelectedNode->SetProperty("Normalization", normMeth.GetPointer()); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkControlVisualizationPropertiesView::ScalingFactorChanged(double scalingFactor) { if ( dynamic_cast(m_SelectedNode->GetData()) || dynamic_cast(m_SelectedNode->GetData()) || dynamic_cast(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(m_SelectedNode->GetData()) || dynamic_cast(m_SelectedNode->GetData()) || dynamic_cast(m_SelectedNode->GetData()) ) { m_SelectedNode->SetProperty("ScaleBy", scaleBy.GetPointer()); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkControlVisualizationPropertiesView::Fiber2DfadingEFX() { if (m_SelectedNode && dynamic_cast(m_SelectedNode->GetData()) ) { bool currentMode; m_SelectedNode->GetBoolProperty("Fiber2DfadeEFX", currentMode); m_SelectedNode->SetProperty("Fiber2DfadeEFX", mitk::BoolProperty::New(!currentMode)); dynamic_cast(m_SelectedNode->GetData())->RequestUpdate2D(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkControlVisualizationPropertiesView::FiberSlicingThickness2D() { if (m_SelectedNode && dynamic_cast(m_SelectedNode->GetData())) { float fibThickness = m_Controls->m_FiberClippingBox->value(); 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(m_SelectedNode->GetData())->RequestUpdate2D(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkControlVisualizationPropertiesView::SetCustomColor(const itk::EventObject& /*e*/) { if(m_SelectedNode && dynamic_cast(m_SelectedNode->GetData())) { float color[3]; m_SelectedNode->GetColor(color); mitk::FiberBundle::Pointer fib = dynamic_cast(m_SelectedNode->GetData()); fib->SetFiberColors(color[0]*255, color[1]*255, color[2]*255); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } else if (m_SelectedNode && dynamic_cast(m_SelectedNode->GetData())) { float color[3]; m_SelectedNode->GetColor(color); mitk::PeakImage::Pointer img = dynamic_cast(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(m_SelectedNode->GetData())) { mitk::FiberBundle::Pointer fib = dynamic_cast(m_SelectedNode->GetData()); fib->ColorFibersByOrientation(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } else if(m_SelectedNode && dynamic_cast(m_SelectedNode->GetData())) { mitk::PeakImage::Pointer fib = dynamic_cast(m_SelectedNode->GetData()); fib->ColorByOrientation(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkControlVisualizationPropertiesView::PlanarFigureFocus() { if(m_SelectedNode) { mitk::PlanarFigure* _PlanarFigure = 0; _PlanarFigure = dynamic_cast (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( worldGeometry1.GetPointer() ); mitk::VnlVector normal1 = _Plane1->GetNormalVnl(); mitk::PlaneGeometry::ConstPointer worldGeometry2 = sagittalRenderWindow->GetRenderer()->GetCurrentWorldPlaneGeometry(); mitk::PlaneGeometry::ConstPointer _Plane2 = dynamic_cast( worldGeometry2.GetPointer() ); mitk::VnlVector normal2 = _Plane2->GetNormalVnl(); mitk::PlaneGeometry::ConstPointer worldGeometry3 = coronalRenderWindow->GetRenderer()->GetCurrentWorldPlaneGeometry(); mitk::PlaneGeometry::ConstPointer _Plane3 = dynamic_cast( 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(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 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(*it); // bundle = dynamic_cast(node->GetData()); // if(bundle) // { // bundleInteractor = dynamic_cast(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(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(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(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."; } }