<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "MiniAppManager.h"

#include <itkImageFileWriter.h>
#include <itkResampleImageFilter.h>
#include <itkFiniteDiffOdfMaximaExtractionFilter.h>

#include <mitkBaseDataIOFactory.h>
#include <mitkDiffusionImage.h>
#include <mitkQBallImage.h>
#include <mitkImageCast.h>
#include <mitkImageToItk.h>
#include <mitkTensorImage.h>

#include <mitkDiffusionCoreObjectFactory.h>
#include <mitkCoreExtObjectFactory.h>
#include <mitkCoreObjectFactory.h>
#include "ctkCommandLineParser.h"
#include <mitkFiberBundleXWriter.h>
#include <itkShCoefficientImageImporter.h>
#include <mitkNrrdQBallImageWriter.h>
#include <itkFlipImageFilter.h>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>

mitk::Image::Pointer LoadData(std::string filename)
{
    if( filename.empty() )
        return NULL;

    const std::string s1="", s2="";
    std::vector<mitk::BaseData::Pointer> infile = mitk::BaseDataIO::LoadBaseDataFromFile( filename, s1, s2, false );
    if( infile.empty() )
    {
        MITK_INFO << "File " << filename << " could not be read!";
        return NULL;
    }

    mitk::BaseData::Pointer baseData = infile.at(0);
    return dynamic_cast<mitk::Image*>(baseData.GetPointer());
}

int PeakExtraction(int argc, char* argv[])
{
    ctkCommandLineParser parser;
    parser.setArgumentPrefix("--", "-");
    parser.addArgument("image", "i", ctkCommandLineParser::String, "sh coefficient image", us::Any(), false);
    parser.addArgument("outroot", "o", ctkCommandLineParser::String, "output root", us::Any(), false);
    parser.addArgument("mask", "m", ctkCommandLineParser::String, "mask image");
    parser.addArgument("normalization", "n", ctkCommandLineParser::Int, "0=no norm, 1=max norm, 2=single vec norm", 1, true);
    parser.addArgument("numpeaks", "p", ctkCommandLineParser::Int, "maximum number of extracted peaks", 2, true);
    parser.addArgument("peakthres", "r", ctkCommandLineParser::Float, "peak threshold relative to largest peak", 0.4, true);
    parser.addArgument("abspeakthres", "a", ctkCommandLineParser::Float, "absolute peak threshold weighted with local GFA value", 0.06, true);
    parser.addArgument("shConvention", "s", ctkCommandLineParser::String, "use specified SH-basis (MITK, FSL, MRtrix)", string("MITK"), true);
    parser.addArgument("noFlip", "f", ctkCommandLineParser::Bool, "do not flip input image to match MITK coordinate convention");

    map<string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
    if (parsedArgs.size()==0)
        return EXIT_FAILURE;

    // mandatory arguments
    string imageName = us::any_cast<string>(parsedArgs["image"]);
    string outRoot = us::any_cast<string>(parsedArgs["outroot"]);

    // optional arguments
    string maskImageName("");
    if (parsedArgs.count("mask"))
        maskImageName = us::any_cast<string>(parsedArgs["mask"]);

    int normalization = 1;
    if (parsedArgs.count("normalization"))
        normalization = us::any_cast<int>(parsedArgs["normalization"]);

    int numPeaks = 2;
    if (parsedArgs.count("numpeaks"))
        numPeaks = us::any_cast<int>(parsedArgs["numpeaks"]);

    float peakThres = 0.4;
    if (parsedArgs.count("peakthres"))
        peakThres = us::any_cast<float>(parsedArgs["peakthres"]);

    float absPeakThres = 0.06;
    if (parsedArgs.count("abspeakthres"))
        absPeakThres = us::any_cast<float>(parsedArgs["abspeakthres"]);

    bool noFlip = false;
    if (parsedArgs.count("noFlip"))
        noFlip = us::any_cast<bool>(parsedArgs["noFlip"]);

    MITK_INFO << "image: " << imageName;
    MITK_INFO << "outroot: " << outRoot;
    if (!maskImageName.empty())
        MITK_INFO << "mask: " << maskImageName;
    else
        MITK_INFO << "no mask image selected";
    MITK_INFO << "numpeaks: " << numPeaks;
    MITK_INFO << "peakthres: " << peakThres;
    MITK_INFO << "abspeakthres: " << absPeakThres;

    try
    {
        mitk::CoreObjectFactory::GetInstance();

        RegisterDiffusionCoreObjectFactory();

        mitk::Image::Pointer image = LoadData(imageName);
        mitk::Image::Pointer mask = LoadData(maskImageName);

        typedef itk::Image<unsigned char, 3>  ItkUcharImgType;
        typedef itk::FiniteDiffOdfMaximaExtractionFilter< float, 4, 20242 > MaximaExtractionFilterType;
        MaximaExtractionFilterType::Pointer filter = MaximaExtractionFilterType::New();

        int toolkitConvention = 0;

        if (parsedArgs.count("shConvention"))
        {
            string convention = us::any_cast<string>(parsedArgs["shConvention"]).c_str();
            if ( boost::algorithm::equals(convention, "FSL") )
            {
                toolkitConvention = 1;
                MITK_INFO << "Using FSL SH-basis";
            }
            else if ( boost::algorithm::equals(convention, "MRtrix") )
            {
                toolkitConvention = 2;
                MITK_INFO << "Using MRtrix SH-basis";
            }
            else
                MITK_INFO << "Using MITK SH-basis";
        }
        else
            MITK_INFO << "Using MITK SH-basis";

        ItkUcharImgType::Pointer itkMaskImage = NULL;
        if (mask.IsNotNull())
        {
            try{
                itkMaskImage = ItkUcharImgType::New();
                mitk::CastToItkImage<ItkUcharImgType>(mask, itkMaskImage);
                filter->SetMaskImage(itkMaskImage);
            }
            catch(...)
            {

            }
        }

        if (toolkitConvention>0)
        {
            MITK_INFO << "Converting coefficient image to MITK format";
            typedef itk::ShCoefficientImageImporter< float, 4 > ConverterType;
            typedef mitk::ImageToItk< itk::Image< float, 4 > > CasterType;
            CasterType::Pointer caster = CasterType::New();
            caster->SetInput(image);
            caster->Update();
            itk::Image< float, 4 >::Pointer itkImage = caster->GetOutput();

            ConverterType::Pointer converter = ConverterType::New();

            if (noFlip)
            {
                converter->SetInputImage(itkImage);
            }
            else
            {
                MITK_INFO << "Flipping image";
                itk::FixedArray<bool, 4> flipAxes;
                flipAxes[0] = true;
                flipAxes[1] = true;
                flipAxes[2] = false;
                flipAxes[3] = false;
                itk::FlipImageFilter< itk::Image< float, 4 > >::Pointer flipper = itk::FlipImageFilter< itk::Image< float, 4 > >::New();
                flipper->SetInput(itkImage);
                flipper->SetFlipAxes(flipAxes);
                flipper->Update();
                itk::Image< float, 4 >::Pointer flipped = flipper->GetOutput();
                flipped->SetDirection(itkImage->GetDirection());
                flipped->SetOrigin(itkImage->GetOrigin());

                converter->SetInputImage(flipped);
            }

            MITK_INFO << "Starting conversion";
            switch (toolkitConvention)
            {
            case 1:
                converter->SetToolkit(ConverterType::FSL);
                filter->SetToolkit(MaximaExtractionFilterType::FSL);
                break;
            case 2:
                converter->SetToolkit(ConverterType::MRTRIX);
                filter->SetToolkit(MaximaExtractionFilterType::MRTRIX);
                break;
            default:
                converter->SetToolkit(ConverterType::FSL);
                filter->SetToolkit(MaximaExtractionFilterType::FSL);
                break;
            }
            converter->GenerateData();
            filter->SetInput(converter->GetCoefficientImage());

//            // write qbi
//            ConverterType::QballImageType::Pointer itkQbi = converter->GetQballImage();

//            if (itkMaskImage.IsNotNull())
//            {
//                itkQbi->SetDirection(itkMaskImage->GetDirection());
//                itkQbi->SetOrigin(itkMaskImage->GetOrigin());
//            }

//            mitk::QBallImage::Pointer mitkQbi = mitk::QBallImage::New();
//            mitkQbi->InitializeByItk( itkQbi.GetPointer() );
//            mitkQbi->SetVolume( itkQbi->GetBufferPointer() );

//            string outfilename = outRoot;
//            outfilename.append("_QBI.qbi");
//            MITK_INFO << "writing " << outfilename;

//            mitk::NrrdQBallImageWriter::Pointer writer = mitk::NrrdQBallImageWriter::New();
//            writer->SetFileName(outfilename.c_str());
//            writer->DoWrite(mitkQbi.GetPointer());
        }
        else
        {
            try{
                typedef mitk::ImageToItk< MaximaExtractionFilterType::CoefficientImageType > CasterType;
                CasterType::Pointer caster = CasterType::New();
                caster->SetInput(image);
                caster->Update();
                filter->SetInput(caster->GetOutput());
            }
            catch(...)
            {
                MITK_INFO << "wrong image type";
                return EXIT_FAILURE;
            }
        }

        filter->SetMaxNumPeaks(numPeaks);
        filter->SetPeakThreshold(peakThres);
        filter->SetAbsolutePeakThreshold(absPeakThres);
        filter->SetAngularThreshold(1);

        switch (normalization)
        {
        case 0:
            filter->SetNormalizationMethod(MaximaExtractionFilterType::NO_NORM);
            break;
        case 1:
            filter->SetNormalizationMethod(MaximaExtractionFilterType::MAX_VEC_NORM);
            break;
        case 2:
            filter->SetNormalizationMethod(MaximaExtractionFilterType::SINGLE_VEC_NORM);
            break;
        }

        MITK_INFO << "Starting extraction";
        filter->Update();

        // write direction images
        {
            typedef MaximaExtractionFilterType::ItkDirectionImageContainer ItkDirectionImageContainer;
            ItkDirectionImageContainer::Pointer container = filter->GetDirectionImageContainer();
            for (int i=0; i<container->Size(); i++)
            {
                MaximaExtractionFilterType::ItkDirectionImage::Pointer itkImg = container->GetElement(i);

                if (itkMaskImage.IsNotNull())
                {
                    itkImg->SetDirection(itkMaskImage->GetDirection());
                    itkImg->SetOrigin(itkMaskImage->GetOrigin());
                }

                string outfilename = outRoot;
                outfilename.append("_DIRECTION_");
                outfilename.append(boost::lexical_cast<string>(i));
                outfilename.append(".nrrd");

                MITK_INFO << "writing " << outfilename;
                typedef itk::ImageFileWriter< MaximaExtractionFilterType::ItkDirectionImage > WriterType;
                WriterType::Pointer writer = WriterType::New();
                writer->SetFileName(outfilename);
                writer->SetInput(itkImg);
                writer->Update();
            }
        }

        // write num directions image
        {
            ItkUcharImgType::Pointer numDirImage = filter->GetNumDirectionsImage();

            if (itkMaskImage.IsNotNull())
            {
                numDirImage->SetDirection(itkMaskImage->GetDirection());
                numDirImage->SetOrigin(itkMaskImage->GetOrigin());
            }

            string outfilename = outRoot.c_str();
            outfilename.append("_NUM_DIRECTIONS.nrrd");
            MITK_INFO << "writing " << outfilename;
            typedef itk::ImageFileWriter< ItkUcharImgType > WriterType;
            WriterType::Pointer writer = WriterType::New();
            writer->SetFileName(outfilename);
            writer->SetInput(numDirImage);
            writer->Update();
        }

        // write vector field
        {
            mitk::FiberBundleX::Pointer directions = filter->GetOutputFiberBundle();

            string outfilename = outRoot.c_str();
            outfilename.append("_VECTOR_FIELD.fib");

            mitk::FiberBundleXWriter::Pointer fibWriter = mitk::FiberBundleXWriter::New();
            fibWriter->SetFileName(outfilename.c_str());
            fibWriter->DoWrite(directions.GetPointer());
        }
    }
    catch (itk::ExceptionObject e)
    {
        MITK_INFO << e;
        return EXIT_FAILURE;
    }
    catch (std::exception e)
    {
        MITK_INFO << e.what();
        return EXIT_FAILURE;
    }
    catch (...)
    {
        MITK_INFO << "ERROR!?!";
        return EXIT_FAILURE;
    }
    MITK_INFO << "DONE";
    return EXIT_SUCCESS;
}
RegisterFiberTrackingMiniApp(PeakExtraction);
<commit_msg>sh not hardcoded anymore in peak extraction<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "MiniAppManager.h"

#include <itkImageFileWriter.h>
#include <itkResampleImageFilter.h>
#include <itkFiniteDiffOdfMaximaExtractionFilter.h>

#include <mitkBaseDataIOFactory.h>
#include <mitkDiffusionImage.h>
#include <mitkQBallImage.h>
#include <mitkImageCast.h>
#include <mitkImageToItk.h>
#include <mitkTensorImage.h>

#include <mitkDiffusionCoreObjectFactory.h>
#include <mitkCoreExtObjectFactory.h>
#include <mitkCoreObjectFactory.h>
#include "ctkCommandLineParser.h"
#include <mitkFiberBundleXWriter.h>
#include <itkShCoefficientImageImporter.h>
#include <mitkNrrdQBallImageWriter.h>
#include <itkFlipImageFilter.h>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>

mitk::Image::Pointer LoadData(std::string filename)
{
    if( filename.empty() )
        return NULL;

    const std::string s1="", s2="";
    std::vector<mitk::BaseData::Pointer> infile = mitk::BaseDataIO::LoadBaseDataFromFile( filename, s1, s2, false );
    if( infile.empty() )
    {
        MITK_INFO << "File " << filename << " could not be read!";
        return NULL;
    }

    mitk::BaseData::Pointer baseData = infile.at(0);
    return dynamic_cast<mitk::Image*>(baseData.GetPointer());
}

template<int shOrder>
int Start(int argc, char* argv[])
{
    ctkCommandLineParser parser;
    parser.setArgumentPrefix("--", "-");
    parser.addArgument("image", "i", ctkCommandLineParser::String, "sh coefficient image", us::Any(), false);
    parser.addArgument("outroot", "o", ctkCommandLineParser::String, "output root", us::Any(), false);
    parser.addArgument("mask", "m", ctkCommandLineParser::String, "mask image");
    parser.addArgument("normalization", "n", ctkCommandLineParser::Int, "0=no norm, 1=max norm, 2=single vec norm", 1, true);
    parser.addArgument("numpeaks", "p", ctkCommandLineParser::Int, "maximum number of extracted peaks", 2, true);
    parser.addArgument("peakthres", "r", ctkCommandLineParser::Float, "peak threshold relative to largest peak", 0.4, true);
    parser.addArgument("abspeakthres", "a", ctkCommandLineParser::Float, "absolute peak threshold weighted with local GFA value", 0.06, true);
    parser.addArgument("shConvention", "s", ctkCommandLineParser::String, "use specified SH-basis (MITK, FSL, MRtrix)", string("MITK"), true);
    parser.addArgument("noFlip", "f", ctkCommandLineParser::Bool, "do not flip input image to match MITK coordinate convention");

    map<string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
    if (parsedArgs.size()==0)
        return EXIT_FAILURE;

    // mandatory arguments
    string imageName = us::any_cast<string>(parsedArgs["image"]);
    string outRoot = us::any_cast<string>(parsedArgs["outroot"]);

    // optional arguments
    string maskImageName("");
    if (parsedArgs.count("mask"))
        maskImageName = us::any_cast<string>(parsedArgs["mask"]);

    int normalization = 1;
    if (parsedArgs.count("normalization"))
        normalization = us::any_cast<int>(parsedArgs["normalization"]);

    int numPeaks = 2;
    if (parsedArgs.count("numpeaks"))
        numPeaks = us::any_cast<int>(parsedArgs["numpeaks"]);

    float peakThres = 0.4;
    if (parsedArgs.count("peakthres"))
        peakThres = us::any_cast<float>(parsedArgs["peakthres"]);

    float absPeakThres = 0.06;
    if (parsedArgs.count("abspeakthres"))
        absPeakThres = us::any_cast<float>(parsedArgs["abspeakthres"]);

    bool noFlip = false;
    if (parsedArgs.count("noFlip"))
        noFlip = us::any_cast<bool>(parsedArgs["noFlip"]);

    MITK_INFO << "image: " << imageName;
    MITK_INFO << "outroot: " << outRoot;
    if (!maskImageName.empty())
        MITK_INFO << "mask: " << maskImageName;
    else
        MITK_INFO << "no mask image selected";
    MITK_INFO << "numpeaks: " << numPeaks;
    MITK_INFO << "peakthres: " << peakThres;
    MITK_INFO << "abspeakthres: " << absPeakThres;
    MITK_INFO << "shOrder: " << shOrder;

    try
    {
        mitk::CoreObjectFactory::GetInstance();

        RegisterDiffusionCoreObjectFactory();

        mitk::Image::Pointer image = LoadData(imageName);
        mitk::Image::Pointer mask = LoadData(maskImageName);

        typedef itk::Image<unsigned char, 3>  ItkUcharImgType;
        typedef itk::FiniteDiffOdfMaximaExtractionFilter< float, shOrder, 20242 > MaximaExtractionFilterType;
        typename MaximaExtractionFilterType::Pointer filter = MaximaExtractionFilterType::New();

        int toolkitConvention = 0;

        if (parsedArgs.count("shConvention"))
        {
            string convention = us::any_cast<string>(parsedArgs["shConvention"]).c_str();
            if ( boost::algorithm::equals(convention, "FSL") )
            {
                toolkitConvention = 1;
                MITK_INFO << "Using FSL SH-basis";
            }
            else if ( boost::algorithm::equals(convention, "MRtrix") )
            {
                toolkitConvention = 2;
                MITK_INFO << "Using MRtrix SH-basis";
            }
            else
                MITK_INFO << "Using MITK SH-basis";
        }
        else
            MITK_INFO << "Using MITK SH-basis";

        ItkUcharImgType::Pointer itkMaskImage = NULL;
        if (mask.IsNotNull())
        {
            try{
                itkMaskImage = ItkUcharImgType::New();
                mitk::CastToItkImage<ItkUcharImgType>(mask, itkMaskImage);
                filter->SetMaskImage(itkMaskImage);
            }
            catch(...)
            {

            }
        }

        if (toolkitConvention>0)
        {
            MITK_INFO << "Converting coefficient image to MITK format";
            typedef itk::ShCoefficientImageImporter< float, shOrder > ConverterType;
            typedef mitk::ImageToItk< itk::Image< float, 4 > > CasterType;
            CasterType::Pointer caster = CasterType::New();
            caster->SetInput(image);
            caster->Update();
            itk::Image< float, 4 >::Pointer itkImage = caster->GetOutput();

            typename ConverterType::Pointer converter = ConverterType::New();

            if (noFlip)
            {
                converter->SetInputImage(itkImage);
            }
            else
            {
                MITK_INFO << "Flipping image";
                itk::FixedArray<bool, 4> flipAxes;
                flipAxes[0] = true;
                flipAxes[1] = true;
                flipAxes[2] = false;
                flipAxes[3] = false;
                itk::FlipImageFilter< itk::Image< float, 4 > >::Pointer flipper = itk::FlipImageFilter< itk::Image< float, 4 > >::New();
                flipper->SetInput(itkImage);
                flipper->SetFlipAxes(flipAxes);
                flipper->Update();
                itk::Image< float, 4 >::Pointer flipped = flipper->GetOutput();
                flipped->SetDirection(itkImage->GetDirection());
                flipped->SetOrigin(itkImage->GetOrigin());

                converter->SetInputImage(flipped);
            }

            MITK_INFO << "Starting conversion";
            switch (toolkitConvention)
            {
            case 1:
                converter->SetToolkit(ConverterType::FSL);
                filter->SetToolkit(MaximaExtractionFilterType::FSL);
                break;
            case 2:
                converter->SetToolkit(ConverterType::MRTRIX);
                filter->SetToolkit(MaximaExtractionFilterType::MRTRIX);
                break;
            default:
                converter->SetToolkit(ConverterType::FSL);
                filter->SetToolkit(MaximaExtractionFilterType::FSL);
                break;
            }
            converter->GenerateData();
            filter->SetInput(converter->GetCoefficientImage());
        }
        else
        {
            try{
                typedef mitk::ImageToItk< typename MaximaExtractionFilterType::CoefficientImageType > CasterType;
                typename CasterType::Pointer caster = CasterType::New();
                caster->SetInput(image);
                caster->Update();
                filter->SetInput(caster->GetOutput());
            }
            catch(...)
            {
                MITK_INFO << "wrong image type";
                return EXIT_FAILURE;
            }
        }

        filter->SetMaxNumPeaks(numPeaks);
        filter->SetPeakThreshold(peakThres);
        filter->SetAbsolutePeakThreshold(absPeakThres);
        filter->SetAngularThreshold(1);

        switch (normalization)
        {
        case 0:
            filter->SetNormalizationMethod(MaximaExtractionFilterType::NO_NORM);
            break;
        case 1:
            filter->SetNormalizationMethod(MaximaExtractionFilterType::MAX_VEC_NORM);
            break;
        case 2:
            filter->SetNormalizationMethod(MaximaExtractionFilterType::SINGLE_VEC_NORM);
            break;
        }

        MITK_INFO << "Starting extraction";
        filter->Update();

        // write direction images
        {
            typedef typename MaximaExtractionFilterType::ItkDirectionImageContainer ItkDirectionImageContainer;
            typename ItkDirectionImageContainer::Pointer container = filter->GetDirectionImageContainer();
            for (int i=0; i<container->Size(); i++)
            {
                typename MaximaExtractionFilterType::ItkDirectionImage::Pointer itkImg = container->GetElement(i);

                if (itkMaskImage.IsNotNull())
                {
                    itkImg->SetDirection(itkMaskImage->GetDirection());
                    itkImg->SetOrigin(itkMaskImage->GetOrigin());
                }

                string outfilename = outRoot;
                outfilename.append("_DIRECTION_");
                outfilename.append(boost::lexical_cast<string>(i));
                outfilename.append(".nrrd");

                MITK_INFO << "writing " << outfilename;
                typedef itk::ImageFileWriter< typename MaximaExtractionFilterType::ItkDirectionImage > WriterType;
                typename WriterType::Pointer writer = WriterType::New();
                writer->SetFileName(outfilename);
                writer->SetInput(itkImg);
                writer->Update();
            }
        }

        // write num directions image
        {
            ItkUcharImgType::Pointer numDirImage = filter->GetNumDirectionsImage();

            if (itkMaskImage.IsNotNull())
            {
                numDirImage->SetDirection(itkMaskImage->GetDirection());
                numDirImage->SetOrigin(itkMaskImage->GetOrigin());
            }

            string outfilename = outRoot.c_str();
            outfilename.append("_NUM_DIRECTIONS.nrrd");
            MITK_INFO << "writing " << outfilename;
            typedef itk::ImageFileWriter< ItkUcharImgType > WriterType;
            WriterType::Pointer writer = WriterType::New();
            writer->SetFileName(outfilename);
            writer->SetInput(numDirImage);
            writer->Update();
        }

        // write vector field
        {
            mitk::FiberBundleX::Pointer directions = filter->GetOutputFiberBundle();

            string outfilename = outRoot.c_str();
            outfilename.append("_VECTOR_FIELD.fib");

            mitk::FiberBundleXWriter::Pointer fibWriter = mitk::FiberBundleXWriter::New();
            fibWriter->SetFileName(outfilename.c_str());
            fibWriter->DoWrite(directions.GetPointer());
        }
    }
    catch (itk::ExceptionObject e)
    {
        MITK_INFO << e;
        return EXIT_FAILURE;
    }
    catch (std::exception e)
    {
        MITK_INFO << e.what();
        return EXIT_FAILURE;
    }
    catch (...)
    {
        MITK_INFO << "ERROR!?!";
        return EXIT_FAILURE;
    }
    MITK_INFO << "DONE";
    return EXIT_SUCCESS;
}

int PeakExtraction(int argc, char* argv[])
{
    ctkCommandLineParser parser;
    parser.setArgumentPrefix("--", "-");
    parser.addArgument("image", "i", ctkCommandLineParser::String, "sh coefficient image", us::Any(), false);
    parser.addArgument("shOrder", "sh", ctkCommandLineParser::Int, "spherical harmonics order");
    parser.addArgument("outroot", "o", ctkCommandLineParser::String, "output root", us::Any(), false);
    parser.addArgument("mask", "m", ctkCommandLineParser::String, "mask image");
    parser.addArgument("normalization", "n", ctkCommandLineParser::Int, "0=no norm, 1=max norm, 2=single vec norm", 1, true);
    parser.addArgument("numpeaks", "p", ctkCommandLineParser::Int, "maximum number of extracted peaks", 2, true);
    parser.addArgument("peakthres", "r", ctkCommandLineParser::Float, "peak threshold relative to largest peak", 0.4, true);
    parser.addArgument("abspeakthres", "a", ctkCommandLineParser::Float, "absolute peak threshold weighted with local GFA value", 0.06, true);
    parser.addArgument("shConvention", "s", ctkCommandLineParser::String, "use specified SH-basis (MITK, FSL, MRtrix)", string("MITK"), true);
    parser.addArgument("noFlip", "f", ctkCommandLineParser::Bool, "do not flip input image to match MITK coordinate convention");

    map<string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
    if (parsedArgs.size()==0)
        return EXIT_FAILURE;

    int shOrder = -1;
    if (parsedArgs.count("shOrder"))
        shOrder = us::any_cast<int>(parsedArgs["shOrder"]);

    switch (shOrder)
    {
    case 4:
        return Start<4>(argc, argv);
    case 6:
        return Start<6>(argc, argv);
    case 8:
        return Start<8>(argc, argv);
    case 10:
        return Start<10>(argc, argv);
    case 12:
        return Start<12>(argc, argv);
    }
    return EXIT_FAILURE;
}
RegisterFiberTrackingMiniApp(PeakExtraction);
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <dbaccess/dataview.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <comphelper/types.hxx>
#include <comphelper/namedvaluecollection.hxx>
#include <sfx2/app.hxx>
#include <sfx2/imgmgr.hxx>
#include <dbaccess/IController.hxx>
#include "UITools.hxx"
#include <sfx2/sfx.hrc>
#include <svtools/imgdef.hxx>
#include <tools/diagnose_ex.h>
#include <vcl/settings.hxx>

namespace dbaui
{
    using namespace ::com::sun::star::uno;
    using namespace ::com::sun::star::beans;
    using namespace ::com::sun::star::util;
    using namespace ::com::sun::star::lang;
    using namespace ::com::sun::star::frame;

    // ColorChanger
    class ColorChanger
    {
    protected:
        OutputDevice*   m_pDev;

    public:
        ColorChanger( OutputDevice* _pDev, const ::Color& _rNewLineColor, const ::Color& _rNewFillColor )
            :m_pDev( _pDev )
        {
            m_pDev->Push( PushFlags::LINECOLOR | PushFlags::FILLCOLOR );
            m_pDev->SetLineColor( _rNewLineColor );
            m_pDev->SetFillColor( _rNewFillColor );
        }

        ~ColorChanger()
        {
            m_pDev->Pop();
        }
    };

    ODataView::ODataView(   vcl::Window* pParent,
                            IController& _rController,
                            const Reference< XComponentContext >& _rxContext,
                            WinBits nStyle)
        :Window(pParent,nStyle)
        ,m_xContext(_rxContext)
        ,m_rController( _rController )
        ,m_aSeparator( this )
    {
        m_rController.acquire();
        m_pAccel.reset(::svt::AcceleratorExecute::createAcceleratorHelper());
        m_aSeparator.Show();
    }

    void ODataView::Construct()
    {
    }

    ODataView::~ODataView()
    {

        m_rController.release();
    }

    void ODataView::resizeDocumentView( Rectangle& /*_rPlayground*/ )
    {
    }

    void ODataView::Paint( const Rectangle& _rRect )
    {
        // draw the background
        {
            ColorChanger aColors( this, COL_TRANSPARENT, GetSettings().GetStyleSettings().GetFaceColor() );
            DrawRect( _rRect );
        }

        // let the base class do anything it needs
        Window::Paint( _rRect );
    }

    void ODataView::resizeAll( const Rectangle& _rPlayground )
    {
        Rectangle aPlayground( _rPlayground );

        // position the separator
        const Size aSeparatorSize = Size( aPlayground.GetWidth(), 2 );
        m_aSeparator.SetPosSizePixel( aPlayground.TopLeft(), aSeparatorSize );
        aPlayground.Top() += aSeparatorSize.Height() + 1;

        // position the controls of the document's view
        resizeDocumentView( aPlayground );
    }

    void ODataView::Resize()
    {
        Window::Resize();
        resizeAll( Rectangle( Point( 0, 0), GetSizePixel() ) );
    }
    bool ODataView::PreNotify( NotifyEvent& _rNEvt )
    {
        bool bHandled = false;
        switch ( _rNEvt.GetType() )
        {
            case MouseNotifyEvent::KEYINPUT:
            {
                const KeyEvent* pKeyEvent = _rNEvt.GetKeyEvent();
                const vcl::KeyCode& aKeyCode = pKeyEvent->GetKeyCode();
                if ( m_pAccel.get() && m_pAccel->execute( aKeyCode ) )
                    // the accelerator consumed the event
                    return true;
            }
            // NO break
            case MouseNotifyEvent::KEYUP:
            case MouseNotifyEvent::MOUSEBUTTONDOWN:
            case MouseNotifyEvent::MOUSEBUTTONUP:
                bHandled = m_rController.interceptUserInput( _rNEvt );
                break;
        }
        return bHandled || Window::PreNotify( _rNEvt );
    }
    void ODataView::StateChanged( StateChangedType nType )
    {
        Window::StateChanged( nType );

        if ( nType == StateChangedType::CONTROLBACKGROUND )
        {
            // Check if we need to get new images for normal/high contrast mode
            m_rController.notifyHiContrastChanged();
        }

        if ( nType == StateChangedType::INITSHOW )
        {
            // now that there's a view which is finally visible, remove the "Hidden" value from the
            // model's arguments.
            try
            {
                Reference< XController > xController( m_rController.getXController(), UNO_SET_THROW );
                Reference< XModel > xModel( xController->getModel(), UNO_QUERY );
                if ( xModel.is() )
                {
                    ::comphelper::NamedValueCollection aArgs( xModel->getArgs() );
                    aArgs.remove( "Hidden" );
                    xModel->attachResource( xModel->getURL(), aArgs.getPropertyValues() );
                }
            }
            catch( const Exception& )
            {
                DBG_UNHANDLED_EXCEPTION();
            }
        }
    }
    void ODataView::DataChanged( const DataChangedEvent& rDCEvt )
    {
        Window::DataChanged( rDCEvt );

        if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
            (rDCEvt.GetType() == DATACHANGED_DISPLAY) ||
            (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
            ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
            (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
        {
            // Check if we need to get new images for normal/high contrast mode
            m_rController.notifyHiContrastChanged();
        }
    }
    void ODataView::attachFrame(const Reference< XFrame >& _xFrame)
    {
        m_pAccel->init(m_xContext, _xFrame);
    }
}

// namespace dbaui

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>-Werror,-Wswitch<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <dbaccess/dataview.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <comphelper/types.hxx>
#include <comphelper/namedvaluecollection.hxx>
#include <sfx2/app.hxx>
#include <sfx2/imgmgr.hxx>
#include <dbaccess/IController.hxx>
#include "UITools.hxx"
#include <sfx2/sfx.hrc>
#include <svtools/imgdef.hxx>
#include <tools/diagnose_ex.h>
#include <vcl/settings.hxx>

namespace dbaui
{
    using namespace ::com::sun::star::uno;
    using namespace ::com::sun::star::beans;
    using namespace ::com::sun::star::util;
    using namespace ::com::sun::star::lang;
    using namespace ::com::sun::star::frame;

    // ColorChanger
    class ColorChanger
    {
    protected:
        OutputDevice*   m_pDev;

    public:
        ColorChanger( OutputDevice* _pDev, const ::Color& _rNewLineColor, const ::Color& _rNewFillColor )
            :m_pDev( _pDev )
        {
            m_pDev->Push( PushFlags::LINECOLOR | PushFlags::FILLCOLOR );
            m_pDev->SetLineColor( _rNewLineColor );
            m_pDev->SetFillColor( _rNewFillColor );
        }

        ~ColorChanger()
        {
            m_pDev->Pop();
        }
    };

    ODataView::ODataView(   vcl::Window* pParent,
                            IController& _rController,
                            const Reference< XComponentContext >& _rxContext,
                            WinBits nStyle)
        :Window(pParent,nStyle)
        ,m_xContext(_rxContext)
        ,m_rController( _rController )
        ,m_aSeparator( this )
    {
        m_rController.acquire();
        m_pAccel.reset(::svt::AcceleratorExecute::createAcceleratorHelper());
        m_aSeparator.Show();
    }

    void ODataView::Construct()
    {
    }

    ODataView::~ODataView()
    {

        m_rController.release();
    }

    void ODataView::resizeDocumentView( Rectangle& /*_rPlayground*/ )
    {
    }

    void ODataView::Paint( const Rectangle& _rRect )
    {
        // draw the background
        {
            ColorChanger aColors( this, COL_TRANSPARENT, GetSettings().GetStyleSettings().GetFaceColor() );
            DrawRect( _rRect );
        }

        // let the base class do anything it needs
        Window::Paint( _rRect );
    }

    void ODataView::resizeAll( const Rectangle& _rPlayground )
    {
        Rectangle aPlayground( _rPlayground );

        // position the separator
        const Size aSeparatorSize = Size( aPlayground.GetWidth(), 2 );
        m_aSeparator.SetPosSizePixel( aPlayground.TopLeft(), aSeparatorSize );
        aPlayground.Top() += aSeparatorSize.Height() + 1;

        // position the controls of the document's view
        resizeDocumentView( aPlayground );
    }

    void ODataView::Resize()
    {
        Window::Resize();
        resizeAll( Rectangle( Point( 0, 0), GetSizePixel() ) );
    }
    bool ODataView::PreNotify( NotifyEvent& _rNEvt )
    {
        bool bHandled = false;
        switch ( _rNEvt.GetType() )
        {
            case MouseNotifyEvent::KEYINPUT:
            {
                const KeyEvent* pKeyEvent = _rNEvt.GetKeyEvent();
                const vcl::KeyCode& aKeyCode = pKeyEvent->GetKeyCode();
                if ( m_pAccel.get() && m_pAccel->execute( aKeyCode ) )
                    // the accelerator consumed the event
                    return true;
            }
            // NO break
            case MouseNotifyEvent::KEYUP:
            case MouseNotifyEvent::MOUSEBUTTONDOWN:
            case MouseNotifyEvent::MOUSEBUTTONUP:
                bHandled = m_rController.interceptUserInput( _rNEvt );
                break;
            default:
                break;
        }
        return bHandled || Window::PreNotify( _rNEvt );
    }
    void ODataView::StateChanged( StateChangedType nType )
    {
        Window::StateChanged( nType );

        if ( nType == StateChangedType::CONTROLBACKGROUND )
        {
            // Check if we need to get new images for normal/high contrast mode
            m_rController.notifyHiContrastChanged();
        }

        if ( nType == StateChangedType::INITSHOW )
        {
            // now that there's a view which is finally visible, remove the "Hidden" value from the
            // model's arguments.
            try
            {
                Reference< XController > xController( m_rController.getXController(), UNO_SET_THROW );
                Reference< XModel > xModel( xController->getModel(), UNO_QUERY );
                if ( xModel.is() )
                {
                    ::comphelper::NamedValueCollection aArgs( xModel->getArgs() );
                    aArgs.remove( "Hidden" );
                    xModel->attachResource( xModel->getURL(), aArgs.getPropertyValues() );
                }
            }
            catch( const Exception& )
            {
                DBG_UNHANDLED_EXCEPTION();
            }
        }
    }
    void ODataView::DataChanged( const DataChangedEvent& rDCEvt )
    {
        Window::DataChanged( rDCEvt );

        if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
            (rDCEvt.GetType() == DATACHANGED_DISPLAY) ||
            (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
            ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
            (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
        {
            // Check if we need to get new images for normal/high contrast mode
            m_rController.notifyHiContrastChanged();
        }
    }
    void ODataView::attachFrame(const Reference< XFrame >& _xFrame)
    {
        m_pAccel->init(m_xContext, _xFrame);
    }
}

// namespace dbaui

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2009-present, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id$
 *
 */

#ifndef PCL_COMMON_IMPL_CENTROID_H_
#define PCL_COMMON_IMPL_CENTROID_H_

#include "pcl/ros/conversions.h"

/////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::compute3DCentroid (const pcl::PointCloud<PointT> &cloud, Eigen::Vector4f &centroid)
{
  // Initialize to 0
  centroid.setZero ();
  if (cloud.points.empty ())
    return;
  // For each point in the cloud
  int cp = 0;

  // If the data is dense, we don't need to check for NaN
  if (cloud.is_dense)
  {
    for (size_t i = 0; i < cloud.points.size (); ++i)
      centroid += cloud.points[i].getVector4fMap ();
    centroid[3] = 0;
    centroid /= cloud.points.size ();
  }
  // NaN or Inf values could exist => check for them
  else
  {
    for (size_t i = 0; i < cloud.points.size (); ++i)
    {
      // Check if the point is invalid
      if (!pcl_isfinite (cloud.points[i].x) ||
          !pcl_isfinite (cloud.points[i].y) ||
          !pcl_isfinite (cloud.points[i].z))
        continue;

      centroid += cloud.points[i].getVector4fMap ();
      cp++;
    }
    centroid[3] = 0;
    centroid /= cp;
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::compute3DCentroid (const pcl::PointCloud<PointT> &cloud, const std::vector<int> &indices,
                        Eigen::Vector4f &centroid)
{
  // Initialize to 0
  centroid.setZero ();
  if (indices.empty ())
    return;
  // For each point in the cloud
  int cp = 0;

  // If the data is dense, we don't need to check for NaN
  if (cloud.is_dense)
  {
    for (size_t i = 0; i < indices.size (); ++i)
      centroid += cloud.points[indices[i]].getVector4fMap ();
    centroid[3] = 0;
    centroid /= indices.size ();
  }
  // NaN or Inf values could exist => check for them
  else
  {
    for (size_t i = 0; i < indices.size (); ++i)
    {
      // Check if the point is invalid
      if (!pcl_isfinite (cloud.points[indices[i]].x) ||
          !pcl_isfinite (cloud.points[indices[i]].y) ||
          !pcl_isfinite (cloud.points[indices[i]].z))
        continue;

      centroid += cloud.points[indices[i]].getVector4fMap ();
      cp++;
    }
    centroid[3] = 0;
    centroid /= cp;
  }
}

/////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::compute3DCentroid (const pcl::PointCloud<PointT> &cloud,
                        const pcl::PointIndices &indices, Eigen::Vector4f &centroid)
{
  return (pcl::compute3DCentroid<PointT> (cloud, indices.indices, centroid));
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
                              const Eigen::Vector4f &centroid,
                              Eigen::Matrix3f &covariance_matrix)
{
  // Initialize to 0
  covariance_matrix.setZero ();

  if (cloud.points.empty ())
    return;
  // If the data is dense, we don't need to check for NaN
  if (cloud.is_dense)
  {
    // For each point in the cloud
    for (size_t i = 0; i < cloud.points.size (); ++i)
    {
      Eigen::Vector4f pt = cloud.points[i].getVector4fMap () - centroid;

      covariance_matrix (1, 1) += pt.y () * pt.y ();
      covariance_matrix (1, 2) += pt.y () * pt.z ();

      covariance_matrix (2, 2) += pt.z () * pt.z ();

      pt *= pt.x ();
      covariance_matrix (0, 0) += pt.x ();
      covariance_matrix (0, 1) += pt.y ();
      covariance_matrix (0, 2) += pt.z ();
    }
  }
  // NaN or Inf values could exist => check for them
  else
  {
    // For each point in the cloud
    for (size_t i = 0; i < cloud.points.size (); ++i)
    {
      // Check if the point is invalid
      if (!pcl_isfinite (cloud.points[i].x) ||
          !pcl_isfinite (cloud.points[i].y) ||
          !pcl_isfinite (cloud.points[i].z))
        continue;

      Eigen::Vector4f pt = cloud.points[i].getVector4fMap () - centroid;

      covariance_matrix (1, 1) += pt.y () * pt.y ();
      covariance_matrix (1, 2) += pt.y () * pt.z ();

      covariance_matrix (2, 2) += pt.z () * pt.z ();

      pt *= pt.x ();
      covariance_matrix (0, 0) += pt.x ();
      covariance_matrix (0, 1) += pt.y ();
      covariance_matrix (0, 2) += pt.z ();
    }
  }
  covariance_matrix (1, 0) = covariance_matrix (0, 1);
  covariance_matrix (2, 0) = covariance_matrix (0, 2);
  covariance_matrix (2, 1) = covariance_matrix (1, 2);
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrixNormalized (const pcl::PointCloud<PointT> &cloud,
                                        const Eigen::Vector4f &centroid,
                                        Eigen::Matrix3f &covariance_matrix)
{
  pcl::computeCovarianceMatrix (cloud, centroid, covariance_matrix);
  covariance_matrix /= cloud.points.size ();
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
                              const std::vector<int> &indices,
                              const Eigen::Vector4f &centroid,
                              Eigen::Matrix3f &covariance_matrix)
{
  // Initialize to 0
  covariance_matrix.setZero ();

  if (indices.empty ())
    return;
  // If the data is dense, we don't need to check for NaN
  if (cloud.is_dense)
  {
    // For each point in the cloud
    for (size_t i = 0; i < indices.size (); ++i)
    {
      Eigen::Vector4f pt = cloud.points[indices[i]].getVector4fMap () - centroid;

      covariance_matrix (1, 1) += pt.y () * pt.y ();
      covariance_matrix (1, 2) += pt.y () * pt.z ();

      covariance_matrix (2, 2) += pt.z () * pt.z ();

      pt *= pt.x ();
      covariance_matrix (0, 0) += pt.x ();
      covariance_matrix (0, 1) += pt.y ();
      covariance_matrix (0, 2) += pt.z ();
    }
  }
  // NaN or Inf values could exist => check for them
  else
  {
    // For each point in the cloud
    for (size_t i = 0; i < indices.size (); ++i)
    {
      // Check if the point is invalid
      if (!pcl_isfinite (cloud.points[indices[i]].x) ||
          !pcl_isfinite (cloud.points[indices[i]].y) ||
          !pcl_isfinite (cloud.points[indices[i]].z))
        continue;

      Eigen::Vector4f pt = cloud.points[indices[i]].getVector4fMap () - centroid;

      covariance_matrix (1, 1) += pt.y () * pt.y ();
      covariance_matrix (1, 2) += pt.y () * pt.z ();

      covariance_matrix (2, 2) += pt.z () * pt.z ();

      pt *= pt.x ();
      covariance_matrix (0, 0) += pt.x ();
      covariance_matrix (0, 1) += pt.y ();
      covariance_matrix (0, 2) += pt.z ();
    }
  }
  covariance_matrix (1, 0) = covariance_matrix (0, 1);
  covariance_matrix (2, 0) = covariance_matrix (0, 2);
  covariance_matrix (2, 1) = covariance_matrix (1, 2);
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
                              const pcl::PointIndices &indices,
                              const Eigen::Vector4f &centroid,
                              Eigen::Matrix3f &covariance_matrix)
{
  return (pcl::computeCovarianceMatrix<PointT> (cloud, indices.indices, centroid));
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrixNormalized (const pcl::PointCloud<PointT> &cloud,
                                        const std::vector<int> &indices,
                                        const Eigen::Vector4f &centroid,
                                        Eigen::Matrix3f &covariance_matrix)
{
  pcl::computeCovarianceMatrix (cloud, indices, centroid, covariance_matrix);
  covariance_matrix /= indices.size ();
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrixNormalized (const pcl::PointCloud<PointT> &cloud,
                                        const pcl::PointIndices &indices,
                                        const Eigen::Vector4f &centroid,
                                        Eigen::Matrix3f &covariance_matrix)
{
  return (pcl::computeCovarianceMatrix (cloud, indices.indices, centroid, covariance_matrix));
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
pcl::demeanPointCloud (const pcl::PointCloud<PointT> &cloud_in,
                       const Eigen::Vector4f &centroid,
                       pcl::PointCloud<PointT> &cloud_out)
{
  cloud_out = cloud_in;

  // Subtract the centroid from cloud_in
  for (size_t i = 0; i < cloud_in.points.size (); ++i)
    cloud_out.points[i].getVector4fMap () -= centroid;
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
pcl::demeanPointCloud (const pcl::PointCloud<PointT> &cloud_in,
                       const std::vector<int> &indices,
                       const Eigen::Vector4f &centroid,
                       pcl::PointCloud<PointT> &cloud_out)
{
  cloud_out.header = cloud_in.header;
  cloud_out.is_dense = cloud_in.is_dense;
  if (indices.size () == cloud_in.points.size ())
  {
    cloud_out.width    = cloud_in.width;
    cloud_out.height   = cloud_in.height;
  }
  else
  {
    cloud_out.width    = indices.size ();
    cloud_out.height   = 1;
  }
  cloud_out.points.resize (indices.size ());

  // Subtract the centroid from cloud_in
  for (size_t i = 0; i < indices.size (); ++i)
    cloud_out.points[i].getVector4fMap () = cloud_in.points[indices[i]].getVector4fMap () -
                                            centroid;
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
pcl::demeanPointCloud (const pcl::PointCloud<PointT> &cloud_in,
                       const Eigen::Vector4f &centroid,
                       Eigen::MatrixXf &cloud_out)
{
  size_t npts = cloud_in.points.size ();

  cloud_out = Eigen::MatrixXf::Zero (4, npts);        // keep the data aligned

  for (size_t i = 0; i < npts; ++i)
    // One column at a time
    cloud_out.block<4, 1> (0, i) = cloud_in.points[i].getVector4fMap () - centroid;

  // Make sure we zero the 4th dimension out (1 row, N columns)
  cloud_out.block (3, 0, 1, npts).setZero ();
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
pcl::demeanPointCloud (const pcl::PointCloud<PointT> &cloud_in,
                       const std::vector<int> &indices,
                       const Eigen::Vector4f &centroid,
                       Eigen::MatrixXf &cloud_out)
{
  size_t npts = indices.size ();

  cloud_out = Eigen::MatrixXf::Zero (4, npts);        // keep the data aligned

  for (size_t i = 0; i < npts; ++i)
    // One column at a time
    cloud_out.block<4, 1> (0, i) = cloud_in.points[indices[i]].getVector4fMap () - centroid;

  // Make sure we zero the 4th dimension out (1 row, N columns)
  cloud_out.block (3, 0, 1, npts).setZero ();
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeNDCentroid (const pcl::PointCloud<PointT> &cloud, Eigen::VectorXf &centroid)
{
  typedef typename pcl::traits::fieldList<PointT>::type FieldList;

  // Get the size of the fields
  centroid.setZero (boost::mpl::size<FieldList>::value);

  if (cloud.points.empty ())
    return;
  // Iterate over each point
  int size = cloud.points.size ();
  for (int i = 0; i < size; ++i)
  {
    // Iterate over each dimension
    pcl::for_each_type <FieldList> (NdCentroidFunctor <PointT> (cloud.points[i], centroid));
  }
  centroid /= size;
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeNDCentroid (const pcl::PointCloud<PointT> &cloud, const std::vector<int> &indices,
                        Eigen::VectorXf &centroid)
{
  typedef typename pcl::traits::fieldList<PointT>::type FieldList;

  // Get the size of the fields
  centroid.setZero (boost::mpl::size<FieldList>::value);

  if (indices.empty ())
    return;
  // Iterate over each point
  int nr_points = indices.size ();
  for (int i = 0; i < nr_points; ++i)
  {
    // Iterate over each dimension
    pcl::for_each_type <FieldList> (NdCentroidFunctor <PointT> (cloud.points[indices[i]], centroid));
  }
  centroid /= nr_points;
}

/////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeNDCentroid (const pcl::PointCloud<PointT> &cloud,
                        const pcl::PointIndices &indices, Eigen::VectorXf &centroid)
{
  return (pcl::computeNDCentroid<PointT> (cloud, indices.indices, centroid));
}

#endif  //#ifndef PCL_COMMON_IMPL_CENTROID_H_

<commit_msg>Fix: add missing header boost/mpl/size<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2009-present, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id$
 *
 */

#ifndef PCL_COMMON_IMPL_CENTROID_H_
#define PCL_COMMON_IMPL_CENTROID_H_

#include "pcl/ros/conversions.h"
#include <boost/mpl/size.hpp>

/////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::compute3DCentroid (const pcl::PointCloud<PointT> &cloud, Eigen::Vector4f &centroid)
{
  // Initialize to 0
  centroid.setZero ();
  if (cloud.points.empty ())
    return;
  // For each point in the cloud
  int cp = 0;

  // If the data is dense, we don't need to check for NaN
  if (cloud.is_dense)
  {
    for (size_t i = 0; i < cloud.points.size (); ++i)
      centroid += cloud.points[i].getVector4fMap ();
    centroid[3] = 0;
    centroid /= cloud.points.size ();
  }
  // NaN or Inf values could exist => check for them
  else
  {
    for (size_t i = 0; i < cloud.points.size (); ++i)
    {
      // Check if the point is invalid
      if (!pcl_isfinite (cloud.points[i].x) ||
          !pcl_isfinite (cloud.points[i].y) ||
          !pcl_isfinite (cloud.points[i].z))
        continue;

      centroid += cloud.points[i].getVector4fMap ();
      cp++;
    }
    centroid[3] = 0;
    centroid /= cp;
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::compute3DCentroid (const pcl::PointCloud<PointT> &cloud, const std::vector<int> &indices,
                        Eigen::Vector4f &centroid)
{
  // Initialize to 0
  centroid.setZero ();
  if (indices.empty ())
    return;
  // For each point in the cloud
  int cp = 0;

  // If the data is dense, we don't need to check for NaN
  if (cloud.is_dense)
  {
    for (size_t i = 0; i < indices.size (); ++i)
      centroid += cloud.points[indices[i]].getVector4fMap ();
    centroid[3] = 0;
    centroid /= indices.size ();
  }
  // NaN or Inf values could exist => check for them
  else
  {
    for (size_t i = 0; i < indices.size (); ++i)
    {
      // Check if the point is invalid
      if (!pcl_isfinite (cloud.points[indices[i]].x) ||
          !pcl_isfinite (cloud.points[indices[i]].y) ||
          !pcl_isfinite (cloud.points[indices[i]].z))
        continue;

      centroid += cloud.points[indices[i]].getVector4fMap ();
      cp++;
    }
    centroid[3] = 0;
    centroid /= cp;
  }
}

/////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::compute3DCentroid (const pcl::PointCloud<PointT> &cloud,
                        const pcl::PointIndices &indices, Eigen::Vector4f &centroid)
{
  return (pcl::compute3DCentroid<PointT> (cloud, indices.indices, centroid));
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
                              const Eigen::Vector4f &centroid,
                              Eigen::Matrix3f &covariance_matrix)
{
  // Initialize to 0
  covariance_matrix.setZero ();

  if (cloud.points.empty ())
    return;
  // If the data is dense, we don't need to check for NaN
  if (cloud.is_dense)
  {
    // For each point in the cloud
    for (size_t i = 0; i < cloud.points.size (); ++i)
    {
      Eigen::Vector4f pt = cloud.points[i].getVector4fMap () - centroid;

      covariance_matrix (1, 1) += pt.y () * pt.y ();
      covariance_matrix (1, 2) += pt.y () * pt.z ();

      covariance_matrix (2, 2) += pt.z () * pt.z ();

      pt *= pt.x ();
      covariance_matrix (0, 0) += pt.x ();
      covariance_matrix (0, 1) += pt.y ();
      covariance_matrix (0, 2) += pt.z ();
    }
  }
  // NaN or Inf values could exist => check for them
  else
  {
    // For each point in the cloud
    for (size_t i = 0; i < cloud.points.size (); ++i)
    {
      // Check if the point is invalid
      if (!pcl_isfinite (cloud.points[i].x) ||
          !pcl_isfinite (cloud.points[i].y) ||
          !pcl_isfinite (cloud.points[i].z))
        continue;

      Eigen::Vector4f pt = cloud.points[i].getVector4fMap () - centroid;

      covariance_matrix (1, 1) += pt.y () * pt.y ();
      covariance_matrix (1, 2) += pt.y () * pt.z ();

      covariance_matrix (2, 2) += pt.z () * pt.z ();

      pt *= pt.x ();
      covariance_matrix (0, 0) += pt.x ();
      covariance_matrix (0, 1) += pt.y ();
      covariance_matrix (0, 2) += pt.z ();
    }
  }
  covariance_matrix (1, 0) = covariance_matrix (0, 1);
  covariance_matrix (2, 0) = covariance_matrix (0, 2);
  covariance_matrix (2, 1) = covariance_matrix (1, 2);
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrixNormalized (const pcl::PointCloud<PointT> &cloud,
                                        const Eigen::Vector4f &centroid,
                                        Eigen::Matrix3f &covariance_matrix)
{
  pcl::computeCovarianceMatrix (cloud, centroid, covariance_matrix);
  covariance_matrix /= cloud.points.size ();
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
                              const std::vector<int> &indices,
                              const Eigen::Vector4f &centroid,
                              Eigen::Matrix3f &covariance_matrix)
{
  // Initialize to 0
  covariance_matrix.setZero ();

  if (indices.empty ())
    return;
  // If the data is dense, we don't need to check for NaN
  if (cloud.is_dense)
  {
    // For each point in the cloud
    for (size_t i = 0; i < indices.size (); ++i)
    {
      Eigen::Vector4f pt = cloud.points[indices[i]].getVector4fMap () - centroid;

      covariance_matrix (1, 1) += pt.y () * pt.y ();
      covariance_matrix (1, 2) += pt.y () * pt.z ();

      covariance_matrix (2, 2) += pt.z () * pt.z ();

      pt *= pt.x ();
      covariance_matrix (0, 0) += pt.x ();
      covariance_matrix (0, 1) += pt.y ();
      covariance_matrix (0, 2) += pt.z ();
    }
  }
  // NaN or Inf values could exist => check for them
  else
  {
    // For each point in the cloud
    for (size_t i = 0; i < indices.size (); ++i)
    {
      // Check if the point is invalid
      if (!pcl_isfinite (cloud.points[indices[i]].x) ||
          !pcl_isfinite (cloud.points[indices[i]].y) ||
          !pcl_isfinite (cloud.points[indices[i]].z))
        continue;

      Eigen::Vector4f pt = cloud.points[indices[i]].getVector4fMap () - centroid;

      covariance_matrix (1, 1) += pt.y () * pt.y ();
      covariance_matrix (1, 2) += pt.y () * pt.z ();

      covariance_matrix (2, 2) += pt.z () * pt.z ();

      pt *= pt.x ();
      covariance_matrix (0, 0) += pt.x ();
      covariance_matrix (0, 1) += pt.y ();
      covariance_matrix (0, 2) += pt.z ();
    }
  }
  covariance_matrix (1, 0) = covariance_matrix (0, 1);
  covariance_matrix (2, 0) = covariance_matrix (0, 2);
  covariance_matrix (2, 1) = covariance_matrix (1, 2);
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrix (const pcl::PointCloud<PointT> &cloud,
                              const pcl::PointIndices &indices,
                              const Eigen::Vector4f &centroid,
                              Eigen::Matrix3f &covariance_matrix)
{
  return (pcl::computeCovarianceMatrix<PointT> (cloud, indices.indices, centroid));
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrixNormalized (const pcl::PointCloud<PointT> &cloud,
                                        const std::vector<int> &indices,
                                        const Eigen::Vector4f &centroid,
                                        Eigen::Matrix3f &covariance_matrix)
{
  pcl::computeCovarianceMatrix (cloud, indices, centroid, covariance_matrix);
  covariance_matrix /= indices.size ();
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeCovarianceMatrixNormalized (const pcl::PointCloud<PointT> &cloud,
                                        const pcl::PointIndices &indices,
                                        const Eigen::Vector4f &centroid,
                                        Eigen::Matrix3f &covariance_matrix)
{
  return (pcl::computeCovarianceMatrix (cloud, indices.indices, centroid, covariance_matrix));
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
pcl::demeanPointCloud (const pcl::PointCloud<PointT> &cloud_in,
                       const Eigen::Vector4f &centroid,
                       pcl::PointCloud<PointT> &cloud_out)
{
  cloud_out = cloud_in;

  // Subtract the centroid from cloud_in
  for (size_t i = 0; i < cloud_in.points.size (); ++i)
    cloud_out.points[i].getVector4fMap () -= centroid;
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
pcl::demeanPointCloud (const pcl::PointCloud<PointT> &cloud_in,
                       const std::vector<int> &indices,
                       const Eigen::Vector4f &centroid,
                       pcl::PointCloud<PointT> &cloud_out)
{
  cloud_out.header = cloud_in.header;
  cloud_out.is_dense = cloud_in.is_dense;
  if (indices.size () == cloud_in.points.size ())
  {
    cloud_out.width    = cloud_in.width;
    cloud_out.height   = cloud_in.height;
  }
  else
  {
    cloud_out.width    = indices.size ();
    cloud_out.height   = 1;
  }
  cloud_out.points.resize (indices.size ());

  // Subtract the centroid from cloud_in
  for (size_t i = 0; i < indices.size (); ++i)
    cloud_out.points[i].getVector4fMap () = cloud_in.points[indices[i]].getVector4fMap () -
                                            centroid;
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
pcl::demeanPointCloud (const pcl::PointCloud<PointT> &cloud_in,
                       const Eigen::Vector4f &centroid,
                       Eigen::MatrixXf &cloud_out)
{
  size_t npts = cloud_in.points.size ();

  cloud_out = Eigen::MatrixXf::Zero (4, npts);        // keep the data aligned

  for (size_t i = 0; i < npts; ++i)
    // One column at a time
    cloud_out.block<4, 1> (0, i) = cloud_in.points[i].getVector4fMap () - centroid;

  // Make sure we zero the 4th dimension out (1 row, N columns)
  cloud_out.block (3, 0, 1, npts).setZero ();
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> void
pcl::demeanPointCloud (const pcl::PointCloud<PointT> &cloud_in,
                       const std::vector<int> &indices,
                       const Eigen::Vector4f &centroid,
                       Eigen::MatrixXf &cloud_out)
{
  size_t npts = indices.size ();

  cloud_out = Eigen::MatrixXf::Zero (4, npts);        // keep the data aligned

  for (size_t i = 0; i < npts; ++i)
    // One column at a time
    cloud_out.block<4, 1> (0, i) = cloud_in.points[indices[i]].getVector4fMap () - centroid;

  // Make sure we zero the 4th dimension out (1 row, N columns)
  cloud_out.block (3, 0, 1, npts).setZero ();
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeNDCentroid (const pcl::PointCloud<PointT> &cloud, Eigen::VectorXf &centroid)
{
  typedef typename pcl::traits::fieldList<PointT>::type FieldList;

  // Get the size of the fields
  centroid.setZero (boost::mpl::size<FieldList>::value);

  if (cloud.points.empty ())
    return;
  // Iterate over each point
  int size = cloud.points.size ();
  for (int i = 0; i < size; ++i)
  {
    // Iterate over each dimension
    pcl::for_each_type <FieldList> (NdCentroidFunctor <PointT> (cloud.points[i], centroid));
  }
  centroid /= size;
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeNDCentroid (const pcl::PointCloud<PointT> &cloud, const std::vector<int> &indices,
                        Eigen::VectorXf &centroid)
{
  typedef typename pcl::traits::fieldList<PointT>::type FieldList;

  // Get the size of the fields
  centroid.setZero (boost::mpl::size<FieldList>::value);

  if (indices.empty ())
    return;
  // Iterate over each point
  int nr_points = indices.size ();
  for (int i = 0; i < nr_points; ++i)
  {
    // Iterate over each dimension
    pcl::for_each_type <FieldList> (NdCentroidFunctor <PointT> (cloud.points[indices[i]], centroid));
  }
  centroid /= nr_points;
}

/////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointT> inline void
pcl::computeNDCentroid (const pcl::PointCloud<PointT> &cloud,
                        const pcl::PointIndices &indices, Eigen::VectorXf &centroid)
{
  return (pcl::computeNDCentroid<PointT> (cloud, indices.indices, centroid));
}

#endif  //#ifndef PCL_COMMON_IMPL_CENTROID_H_

<|endoftext|>


<commit_before>// Kernel.cpp (Oclgrind)
// Copyright (c) 2013-2014, James Price and Simon McIntosh-Smith,
// University of Bristol. All rights reserved.
//
// This program is provided under a three-clause BSD license. For full
// license terms please see the LICENSE file distributed with this
// source code.

#include "common.h"
#include <sstream>

#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Support/raw_os_ostream.h"

#include "Kernel.h"
#include "Program.h"
#include "Memory.h"

using namespace oclgrind;
using namespace std;

Kernel::Kernel(const Program *program,
               const llvm::Function *function, const llvm::Module *module)
 : m_program(program), m_function(function), m_name(function->getName())
{
  m_localMemory = new Memory(AddrSpaceLocal, program->getContext());

  // Set-up global variables
  llvm::Module::const_global_iterator itr;
  for (itr = module->global_begin(); itr != module->global_end(); itr++)
  {
    llvm::PointerType *type = itr->getType();
    switch (type->getPointerAddressSpace())
    {
    case AddrSpacePrivate:
      m_globalVariables.push_back(itr);
      break;
    case AddrSpaceConstant:
      m_constants.push_back(itr);
      break;
    case AddrSpaceLocal:
    {
      // Allocate buffer
      size_t size = getTypeSize(itr->getInitializer()->getType());
      TypedValue v = {
        sizeof(size_t),
        1,
        new unsigned char[sizeof(size_t)]
      };
      v.setPointer(m_localMemory->allocateBuffer(size));
      m_arguments[itr] = v;
      break;
    }
    default:
      FATAL_ERROR("Unsupported GlobalVariable address space: %d",
                  type->getPointerAddressSpace());
    }
  }

  // Get metadata node containing kernel arg info
  m_metadata = NULL;
  llvm::NamedMDNode *md = module->getNamedMetadata("opencl.kernels");
  if (md)
  {
    for (int i = 0; i < md->getNumOperands(); i++)
    {
      llvm::MDNode *node = md->getOperand(i);
      if (node->getOperand(0)->getName() == m_name)
      {
        m_metadata = node;
        break;
      }
    }
  }
}

Kernel::Kernel(const Kernel& kernel)
 : m_program(kernel.m_program)
{
  m_function = kernel.m_function;
  m_constants = kernel.m_constants;
  m_globalVariables = kernel.m_globalVariables;
  m_constantBuffers = kernel.m_constantBuffers;
  m_localMemory = kernel.m_localMemory->clone();
  m_name = kernel.m_name;
  m_metadata = kernel.m_metadata;

  TypedValueMap::const_iterator itr;
  for (itr = kernel.m_arguments.begin();
       itr != kernel.m_arguments.end(); itr++)
  {
    m_arguments[itr->first] = itr->second.clone();
  }
}

Kernel::~Kernel()
{
  delete m_localMemory;

  TypedValueMap::iterator itr;
  for (itr = m_arguments.begin(); itr != m_arguments.end(); itr++)
  {
    delete[] itr->second.data;
  }
}

bool Kernel::allArgumentsSet() const
{
  llvm::Function::const_arg_iterator itr;
  for (itr = m_function->arg_begin(); itr != m_function->arg_end(); itr++)
  {
    if (!m_arguments.count(itr))
    {
      return false;
    }
  }
  return true;
}

void Kernel::allocateConstants(Memory *memory)
{
  list<const llvm::GlobalVariable*>::const_iterator itr;
  for (itr = m_constants.begin(); itr != m_constants.end(); itr++)
  {
    const llvm::Constant *initializer = (*itr)->getInitializer();
    const llvm::Type *type = initializer->getType();

    // Allocate buffer
    size_t size = getTypeSize(type);
    TypedValue v = {
      sizeof(size_t),
      1,
      new unsigned char[sizeof(size_t)]
    };
    size_t address = memory->allocateBuffer(size);
    v.setPointer(address);
    m_constantBuffers.push_back(address);
    m_arguments[*itr] = v;

    // Initialise buffer contents
    unsigned char *data = new unsigned char[size];
    getConstantData(data, (const llvm::Constant*)initializer);
    memory->store(data, address, size);
    delete[] data;
  }
}

void Kernel::deallocateConstants(Memory *memory)
{
  list<size_t>::const_iterator itr;
  for (itr = m_constantBuffers.begin(); itr != m_constantBuffers.end(); itr++)
  {
    memory->deallocateBuffer(*itr);
  }
  m_constantBuffers.clear();
}

const llvm::Argument* Kernel::getArgument(unsigned int index) const
{
  assert(index < getNumArguments());

  llvm::Function::const_arg_iterator argItr = m_function->arg_begin();
  for (int i = 0; i < index; i++)
  {
    argItr++;
  }
  return argItr;
}

unsigned int Kernel::getArgumentAccessQualifier(unsigned int index) const
{
  assert(index < getNumArguments());

  // Get metadata node
  const llvm::MDNode *node = getArgumentMetadata("kernel_arg_access_qual");
  if (!node)
  {
    return -1;
  }

  // Get qualifier string
  string str = node->getOperand(index+1)->getName();
  if (str == "read_only")
  {
    return CL_KERNEL_ARG_ACCESS_READ_ONLY;
  }
  else if (str == "write_only")
  {
    return CL_KERNEL_ARG_ACCESS_WRITE_ONLY;
  }
  else if (str == "read_write")
  {
    return CL_KERNEL_ARG_ACCESS_READ_WRITE;
  }
  return CL_KERNEL_ARG_ACCESS_NONE;
}

unsigned int Kernel::getArgumentAddressQualifier(unsigned int index) const
{
  assert(index < getNumArguments());

  // Get metadata node
  const llvm::MDNode *node = getArgumentMetadata("kernel_arg_addr_space");
  if (!node)
  {
    return -1;
  }

  // TODO: Remove this when kernel arg info metadata fixed in compiler
  // This has been fixed by Pedro's clang patch in r198868, llvm bug 18419
  if (getArgumentTypeName(index).startswith("image"))
  {
    return CL_KERNEL_ARG_ADDRESS_GLOBAL;
  }

  // Get address space
  switch(((llvm::ConstantInt*)node->getOperand(index+1))->getZExtValue())
  {
    case AddrSpacePrivate:
      return CL_KERNEL_ARG_ADDRESS_PRIVATE;
    case AddrSpaceGlobal:
      return CL_KERNEL_ARG_ADDRESS_GLOBAL;
    case AddrSpaceConstant:
      return CL_KERNEL_ARG_ADDRESS_CONSTANT;
    case AddrSpaceLocal:
      return CL_KERNEL_ARG_ADDRESS_LOCAL;
    default:
      return -1;
  }
}

const llvm::MDNode* Kernel::getArgumentMetadata(string name) const
{
  if (!m_metadata)
  {
    return NULL;
  }

  // Loop over all metadata nodes for this kernel
  for (int i = 0; i < m_metadata->getNumOperands(); i++)
  {
    const llvm::Value *value = m_metadata->getOperand(i);
    if (value->getType()->getTypeID() == llvm::Type::MetadataTyID)
    {
      // Check if node matches target name
      const llvm::MDNode *node = (llvm::MDNode*)value;
      if (node->getNumOperands() > 0 && node->getOperand(0)->getName() == name)
      {
        return node;
      }
    }
  }
  return NULL;
}

const llvm::StringRef Kernel::getArgumentName(unsigned int index) const
{
  return getArgument(index)->getName();
}

const llvm::StringRef Kernel::getArgumentTypeName(unsigned int index) const
{
  assert(index < getNumArguments());

  // Get metadata node
  const llvm::MDNode *node = getArgumentMetadata("kernel_arg_type");
  if (!node)
  {
    return "";
  }

  return node->getOperand(index+1)->getName();
}

unsigned int Kernel::getArgumentTypeQualifier(unsigned int index) const
{
  assert(index < getNumArguments());

  // Get metadata node
  const llvm::MDNode *node = getArgumentMetadata("kernel_arg_type_qual");
  if (!node)
  {
    return -1;
  }

  // Get qualifiers
  istringstream iss(node->getOperand(index+1)->getName().str());

  unsigned int result = CL_KERNEL_ARG_TYPE_NONE;
  while (!iss.eof())
  {
    string tok;
    iss >> tok;
    if (tok == "const")
    {
      result |= CL_KERNEL_ARG_TYPE_CONST;
    }
    else if (tok == "restrict")
    {
      result |= CL_KERNEL_ARG_TYPE_RESTRICT;
    }
    else if (tok == "volatile")
    {
      result |= CL_KERNEL_ARG_TYPE_VOLATILE;
    }
  }

  return result;
}

size_t Kernel::getArgumentSize(unsigned int index) const
{
  const llvm::Argument *argument = getArgument(index);
  const llvm::Type *type = argument->getType();

  // Check if pointer argument
  if (type->isPointerTy() && argument->hasByValAttr())
  {
    return getTypeSize(type->getPointerElementType());
  }

  return getTypeSize(type);
}

string Kernel::getAttributes() const
{
  ostringstream attributes("");
  for (int i = 0; i < m_metadata->getNumOperands(); i++)
  {
    llvm::Value *op = m_metadata->getOperand(i);
    if (op->getValueID() == llvm::Value::MDNodeVal)
    {
      llvm::MDNode *val = ((llvm::MDNode*)op);
      string name = val->getOperand(0)->getName().str();

      if (name == "reqd_work_group_size" ||
          name == "work_group_size_hint")
      {
        attributes << name << "("
                   <<
          ((const llvm::ConstantInt*)val->getOperand(1))->getZExtValue()
                   << "," <<
          ((const llvm::ConstantInt*)val->getOperand(2))->getZExtValue()
                   << "," <<
          ((const llvm::ConstantInt*)val->getOperand(3))->getZExtValue()
                   << ") ";
      }
      else if (name == "vec_type_hint")
      {
        // Get type hint
        size_t n = 1;
        const llvm::Type *type = val->getOperand(1)->getType();
        if (type->isVectorTy())
        {
          n = type->getVectorNumElements();
          type = type->getVectorElementType();
        }

        // Generate attribute string
        attributes << name << "(" << flush;
        llvm::raw_os_ostream out(attributes);
        type->print(out);
        out.flush();
        attributes << n << ") ";
      }
    }
  }
  return attributes.str();
}

const llvm::Function* Kernel::getFunction() const
{
  return m_function;
}

const Memory* Kernel::getLocalMemory() const
{
  return m_localMemory;
}

size_t Kernel::getLocalMemorySize() const
{
  return m_localMemory->getTotalAllocated();
}

const std::string& Kernel::getName() const
{
  return m_name;
}

unsigned int Kernel::getNumArguments() const
{
  return m_function->arg_size();
}

const Program* Kernel::getProgram() const
{
  return m_program;
}

void Kernel::getRequiredWorkGroupSize(size_t reqdWorkGroupSize[3]) const
{
  memset(reqdWorkGroupSize, 0, 3*sizeof(size_t));
  for (int i = 0; i < m_metadata->getNumOperands(); i++)
  {
    llvm::Value *op = m_metadata->getOperand(i);
    if (op->getValueID() == llvm::Value::MDNodeVal)
    {
      llvm::MDNode *val = ((llvm::MDNode*)op);
      string name = val->getOperand(0)->getName().str();
      if (name == "reqd_work_group_size")
      {
        for (int j = 0; j < 3; j++)
        {
          reqdWorkGroupSize[j] =
            ((const llvm::ConstantInt*)val->getOperand(j+1))->getZExtValue();
        }
      }
    }
  }
}

void Kernel::setArgument(unsigned int index, TypedValue value)
{
  assert(index < m_function->arg_size());

  unsigned int type = getArgumentAddressQualifier(index);
  if (type == CL_KERNEL_ARG_ADDRESS_LOCAL)
  {
    const llvm::Value *arg = getArgument(index);

    // Deallocate existing argument
    if (m_arguments.count(arg))
    {
      m_localMemory->deallocateBuffer(m_arguments[arg].getPointer());
    }

    // Allocate local memory buffer
    TypedValue v = {
      sizeof(size_t),
      1,
      new unsigned char[sizeof(size_t)]
    };
    v.setPointer(m_localMemory->allocateBuffer(value.size));
    m_arguments[arg] = v;
  }
  else
  {
    const llvm::Type *type = getArgument(index)->getType();
    if (type->isVectorTy())
    {
      value.num = type->getVectorNumElements();
      value.size = getTypeSize(type->getVectorElementType());
    }
    m_arguments[getArgument(index)] = value.clone();
  }
}

TypedValueMap::const_iterator Kernel::args_begin() const
{
  return m_arguments.begin();
}

TypedValueMap::const_iterator Kernel::args_end() const
{
  return m_arguments.end();
}

list<const llvm::GlobalVariable*>::const_iterator Kernel::vars_begin() const
{
  return m_globalVariables.begin();
}

list<const llvm::GlobalVariable*>::const_iterator Kernel::vars_end() const
{
  return m_globalVariables.end();
}
<commit_msg>Release local memory arguments properly.<commit_after>// Kernel.cpp (Oclgrind)
// Copyright (c) 2013-2014, James Price and Simon McIntosh-Smith,
// University of Bristol. All rights reserved.
//
// This program is provided under a three-clause BSD license. For full
// license terms please see the LICENSE file distributed with this
// source code.

#include "common.h"
#include <sstream>

#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Support/raw_os_ostream.h"

#include "Kernel.h"
#include "Program.h"
#include "Memory.h"

using namespace oclgrind;
using namespace std;

Kernel::Kernel(const Program *program,
               const llvm::Function *function, const llvm::Module *module)
 : m_program(program), m_function(function), m_name(function->getName())
{
  m_localMemory = new Memory(AddrSpaceLocal, program->getContext());

  // Set-up global variables
  llvm::Module::const_global_iterator itr;
  for (itr = module->global_begin(); itr != module->global_end(); itr++)
  {
    llvm::PointerType *type = itr->getType();
    switch (type->getPointerAddressSpace())
    {
    case AddrSpacePrivate:
      m_globalVariables.push_back(itr);
      break;
    case AddrSpaceConstant:
      m_constants.push_back(itr);
      break;
    case AddrSpaceLocal:
    {
      // Allocate buffer
      size_t size = getTypeSize(itr->getInitializer()->getType());
      TypedValue v = {
        sizeof(size_t),
        1,
        new unsigned char[sizeof(size_t)]
      };
      v.setPointer(m_localMemory->allocateBuffer(size));
      m_arguments[itr] = v;
      break;
    }
    default:
      FATAL_ERROR("Unsupported GlobalVariable address space: %d",
                  type->getPointerAddressSpace());
    }
  }

  // Get metadata node containing kernel arg info
  m_metadata = NULL;
  llvm::NamedMDNode *md = module->getNamedMetadata("opencl.kernels");
  if (md)
  {
    for (int i = 0; i < md->getNumOperands(); i++)
    {
      llvm::MDNode *node = md->getOperand(i);
      if (node->getOperand(0)->getName() == m_name)
      {
        m_metadata = node;
        break;
      }
    }
  }
}

Kernel::Kernel(const Kernel& kernel)
 : m_program(kernel.m_program)
{
  m_function = kernel.m_function;
  m_constants = kernel.m_constants;
  m_globalVariables = kernel.m_globalVariables;
  m_constantBuffers = kernel.m_constantBuffers;
  m_localMemory = kernel.m_localMemory->clone();
  m_name = kernel.m_name;
  m_metadata = kernel.m_metadata;

  TypedValueMap::const_iterator itr;
  for (itr = kernel.m_arguments.begin();
       itr != kernel.m_arguments.end(); itr++)
  {
    m_arguments[itr->first] = itr->second.clone();
  }
}

Kernel::~Kernel()
{
  delete m_localMemory;

  TypedValueMap::iterator itr;
  for (itr = m_arguments.begin(); itr != m_arguments.end(); itr++)
  {
    delete[] itr->second.data;
  }
}

bool Kernel::allArgumentsSet() const
{
  llvm::Function::const_arg_iterator itr;
  for (itr = m_function->arg_begin(); itr != m_function->arg_end(); itr++)
  {
    if (!m_arguments.count(itr))
    {
      return false;
    }
  }
  return true;
}

void Kernel::allocateConstants(Memory *memory)
{
  list<const llvm::GlobalVariable*>::const_iterator itr;
  for (itr = m_constants.begin(); itr != m_constants.end(); itr++)
  {
    const llvm::Constant *initializer = (*itr)->getInitializer();
    const llvm::Type *type = initializer->getType();

    // Allocate buffer
    size_t size = getTypeSize(type);
    TypedValue v = {
      sizeof(size_t),
      1,
      new unsigned char[sizeof(size_t)]
    };
    size_t address = memory->allocateBuffer(size);
    v.setPointer(address);
    m_constantBuffers.push_back(address);
    m_arguments[*itr] = v;

    // Initialise buffer contents
    unsigned char *data = new unsigned char[size];
    getConstantData(data, (const llvm::Constant*)initializer);
    memory->store(data, address, size);
    delete[] data;
  }
}

void Kernel::deallocateConstants(Memory *memory)
{
  list<size_t>::const_iterator itr;
  for (itr = m_constantBuffers.begin(); itr != m_constantBuffers.end(); itr++)
  {
    memory->deallocateBuffer(*itr);
  }
  m_constantBuffers.clear();
}

const llvm::Argument* Kernel::getArgument(unsigned int index) const
{
  assert(index < getNumArguments());

  llvm::Function::const_arg_iterator argItr = m_function->arg_begin();
  for (int i = 0; i < index; i++)
  {
    argItr++;
  }
  return argItr;
}

unsigned int Kernel::getArgumentAccessQualifier(unsigned int index) const
{
  assert(index < getNumArguments());

  // Get metadata node
  const llvm::MDNode *node = getArgumentMetadata("kernel_arg_access_qual");
  if (!node)
  {
    return -1;
  }

  // Get qualifier string
  string str = node->getOperand(index+1)->getName();
  if (str == "read_only")
  {
    return CL_KERNEL_ARG_ACCESS_READ_ONLY;
  }
  else if (str == "write_only")
  {
    return CL_KERNEL_ARG_ACCESS_WRITE_ONLY;
  }
  else if (str == "read_write")
  {
    return CL_KERNEL_ARG_ACCESS_READ_WRITE;
  }
  return CL_KERNEL_ARG_ACCESS_NONE;
}

unsigned int Kernel::getArgumentAddressQualifier(unsigned int index) const
{
  assert(index < getNumArguments());

  // Get metadata node
  const llvm::MDNode *node = getArgumentMetadata("kernel_arg_addr_space");
  if (!node)
  {
    return -1;
  }

  // TODO: Remove this when kernel arg info metadata fixed in compiler
  // This has been fixed by Pedro's clang patch in r198868, llvm bug 18419
  if (getArgumentTypeName(index).startswith("image"))
  {
    return CL_KERNEL_ARG_ADDRESS_GLOBAL;
  }

  // Get address space
  switch(((llvm::ConstantInt*)node->getOperand(index+1))->getZExtValue())
  {
    case AddrSpacePrivate:
      return CL_KERNEL_ARG_ADDRESS_PRIVATE;
    case AddrSpaceGlobal:
      return CL_KERNEL_ARG_ADDRESS_GLOBAL;
    case AddrSpaceConstant:
      return CL_KERNEL_ARG_ADDRESS_CONSTANT;
    case AddrSpaceLocal:
      return CL_KERNEL_ARG_ADDRESS_LOCAL;
    default:
      return -1;
  }
}

const llvm::MDNode* Kernel::getArgumentMetadata(string name) const
{
  if (!m_metadata)
  {
    return NULL;
  }

  // Loop over all metadata nodes for this kernel
  for (int i = 0; i < m_metadata->getNumOperands(); i++)
  {
    const llvm::Value *value = m_metadata->getOperand(i);
    if (value->getType()->getTypeID() == llvm::Type::MetadataTyID)
    {
      // Check if node matches target name
      const llvm::MDNode *node = (llvm::MDNode*)value;
      if (node->getNumOperands() > 0 && node->getOperand(0)->getName() == name)
      {
        return node;
      }
    }
  }
  return NULL;
}

const llvm::StringRef Kernel::getArgumentName(unsigned int index) const
{
  return getArgument(index)->getName();
}

const llvm::StringRef Kernel::getArgumentTypeName(unsigned int index) const
{
  assert(index < getNumArguments());

  // Get metadata node
  const llvm::MDNode *node = getArgumentMetadata("kernel_arg_type");
  if (!node)
  {
    return "";
  }

  return node->getOperand(index+1)->getName();
}

unsigned int Kernel::getArgumentTypeQualifier(unsigned int index) const
{
  assert(index < getNumArguments());

  // Get metadata node
  const llvm::MDNode *node = getArgumentMetadata("kernel_arg_type_qual");
  if (!node)
  {
    return -1;
  }

  // Get qualifiers
  istringstream iss(node->getOperand(index+1)->getName().str());

  unsigned int result = CL_KERNEL_ARG_TYPE_NONE;
  while (!iss.eof())
  {
    string tok;
    iss >> tok;
    if (tok == "const")
    {
      result |= CL_KERNEL_ARG_TYPE_CONST;
    }
    else if (tok == "restrict")
    {
      result |= CL_KERNEL_ARG_TYPE_RESTRICT;
    }
    else if (tok == "volatile")
    {
      result |= CL_KERNEL_ARG_TYPE_VOLATILE;
    }
  }

  return result;
}

size_t Kernel::getArgumentSize(unsigned int index) const
{
  const llvm::Argument *argument = getArgument(index);
  const llvm::Type *type = argument->getType();

  // Check if pointer argument
  if (type->isPointerTy() && argument->hasByValAttr())
  {
    return getTypeSize(type->getPointerElementType());
  }

  return getTypeSize(type);
}

string Kernel::getAttributes() const
{
  ostringstream attributes("");
  for (int i = 0; i < m_metadata->getNumOperands(); i++)
  {
    llvm::Value *op = m_metadata->getOperand(i);
    if (op->getValueID() == llvm::Value::MDNodeVal)
    {
      llvm::MDNode *val = ((llvm::MDNode*)op);
      string name = val->getOperand(0)->getName().str();

      if (name == "reqd_work_group_size" ||
          name == "work_group_size_hint")
      {
        attributes << name << "("
                   <<
          ((const llvm::ConstantInt*)val->getOperand(1))->getZExtValue()
                   << "," <<
          ((const llvm::ConstantInt*)val->getOperand(2))->getZExtValue()
                   << "," <<
          ((const llvm::ConstantInt*)val->getOperand(3))->getZExtValue()
                   << ") ";
      }
      else if (name == "vec_type_hint")
      {
        // Get type hint
        size_t n = 1;
        const llvm::Type *type = val->getOperand(1)->getType();
        if (type->isVectorTy())
        {
          n = type->getVectorNumElements();
          type = type->getVectorElementType();
        }

        // Generate attribute string
        attributes << name << "(" << flush;
        llvm::raw_os_ostream out(attributes);
        type->print(out);
        out.flush();
        attributes << n << ") ";
      }
    }
  }
  return attributes.str();
}

const llvm::Function* Kernel::getFunction() const
{
  return m_function;
}

const Memory* Kernel::getLocalMemory() const
{
  return m_localMemory;
}

size_t Kernel::getLocalMemorySize() const
{
  return m_localMemory->getTotalAllocated();
}

const std::string& Kernel::getName() const
{
  return m_name;
}

unsigned int Kernel::getNumArguments() const
{
  return m_function->arg_size();
}

const Program* Kernel::getProgram() const
{
  return m_program;
}

void Kernel::getRequiredWorkGroupSize(size_t reqdWorkGroupSize[3]) const
{
  memset(reqdWorkGroupSize, 0, 3*sizeof(size_t));
  for (int i = 0; i < m_metadata->getNumOperands(); i++)
  {
    llvm::Value *op = m_metadata->getOperand(i);
    if (op->getValueID() == llvm::Value::MDNodeVal)
    {
      llvm::MDNode *val = ((llvm::MDNode*)op);
      string name = val->getOperand(0)->getName().str();
      if (name == "reqd_work_group_size")
      {
        for (int j = 0; j < 3; j++)
        {
          reqdWorkGroupSize[j] =
            ((const llvm::ConstantInt*)val->getOperand(j+1))->getZExtValue();
        }
      }
    }
  }
}

void Kernel::setArgument(unsigned int index, TypedValue value)
{
  assert(index < m_function->arg_size());

  unsigned int type = getArgumentAddressQualifier(index);
  if (type == CL_KERNEL_ARG_ADDRESS_LOCAL)
  {
    const llvm::Value *arg = getArgument(index);

    // Deallocate existing argument
    if (m_arguments.count(arg))
    {
      m_localMemory->deallocateBuffer(m_arguments[arg].getPointer());
      delete[] m_arguments[arg].data;
    }

    // Allocate local memory buffer
    TypedValue v = {
      sizeof(size_t),
      1,
      new unsigned char[sizeof(size_t)]
    };
    v.setPointer(m_localMemory->allocateBuffer(value.size));
    m_arguments[arg] = v;
  }
  else
  {
    const llvm::Type *type = getArgument(index)->getType();
    if (type->isVectorTy())
    {
      value.num = type->getVectorNumElements();
      value.size = getTypeSize(type->getVectorElementType());
    }
    m_arguments[getArgument(index)] = value.clone();
  }
}

TypedValueMap::const_iterator Kernel::args_begin() const
{
  return m_arguments.begin();
}

TypedValueMap::const_iterator Kernel::args_end() const
{
  return m_arguments.end();
}

list<const llvm::GlobalVariable*>::const_iterator Kernel::vars_begin() const
{
  return m_globalVariables.begin();
}

list<const llvm::GlobalVariable*>::const_iterator Kernel::vars_end() const
{
  return m_globalVariables.end();
}
<|endoftext|>