histogram.hpp

Back to Histograms

pastel/sys/

#ifndef PASTELSYS_HISTOGRAM_HPP
#define PASTELSYS_HISTOGRAM_HPP

#include "pastel/sys/histogram.h"
#include "pastel/sys/math_functions.h"
#include "pastel/sys/view/view_tools.h"

namespace Pastel
{

    template <typename Real_ConstRange, typename Real_OutputIterator>
    void computeHistogram(
        const Real_ConstRange& dataSet,
        const typename boost::range_value<Real_ConstRange>::type& min,
        const typename boost::range_value<Real_ConstRange>::type& max,
        integer bins,
        const Real_OutputIterator& outputBegin)
    {
        ENSURE_OP(bins, >, 0);

        typedef typename boost::range_iterator<Real_ConstRange>::type
            Real_ConstIterator;
        typedef typename boost::range_value<Real_ConstRange>::type
            Real;

        Real rangeDelta = max - min;

        std::vector<Real> hitSet(bins, 0);

        Real_ConstIterator iter = dataSet.begin();
        Real_ConstIterator iterEnd = dataSet.end();
        integer samples = 0;

        while(iter != iterEnd)
        {

            Real value = *iter;

            if (value >= min && value <= max)
            {
                value -= min;
                value /= rangeDelta;

                integer bin  =
                    quantizeUnsigned(value, bins);

                ++hitSet[bin];
            }

            ++iter;
            ++samples;
        }

        // Normalize the pdf to 1.

        Real binSize = (max - min) / bins;

        const Real factor = (Real)1 / (samples * binSize);
        for (integer i = 0;i < bins;++i)
        {
            hitSet[i] *= factor;
        }

        std::copy(hitSet.begin(), hitSet.end(),
            outputBegin);
    }

    template <typename Real, typename ConstIterator, typename OutputView>
    void computeJointHistogram(
        const ConstIterator& xBegin,
        const ConstIterator& xEnd,
        const NoDeduction<Real>& xMin,
        const NoDeduction<Real>& xMax,
        const ConstIterator& yBegin,
        const ConstIterator& yEnd,
        const NoDeduction<Real>& yMin,
        const NoDeduction<Real>& yMax,
        const View<2, Real, OutputView>& output)
    {
        ENSURE_OP(output.width(), >, 0);
        ENSURE_OP(output.height(), >, 0);

        Real xRangeDelta = xMax - xMin;
        Real yRangeDelta = yMax - yMin;

        integer xBins = output.width();
        integer yBins = output.height();

        clear(0, output);

        ConstIterator xIter = xBegin;
        ConstIterator yIter = yBegin;
        integer samples = 0;

        while(xIter != xEnd)
        {
            ENSURE(yIter != yEnd);

            Real xValue = *xIter;

            if (xValue >= xMin && xValue <= xMax)
            {
                Real yValue = *yIter;

                if (yValue >= yMin && yValue <= yMax)
                {
                    xValue -= xMin;
                    xValue /= xRangeDelta;

                    integer xBin = 
                        quantizeUnsigned(xValue, xBins);

                    yValue -= yMin;
                    yValue /= yRangeDelta;

                    integer yBin = 
                        quantizeUnsigned(yValue, yBins);

                    ++output(xBin, yBin);
                }
            }

            ++xIter;
            ++yIter;
            ++samples;
        }

        ENSURE(yIter == yEnd);

        // Normalize the pdf to 1.

        const Real binSize = (xRangeDelta * yRangeDelta) / (xBins * yBins);
        const Real factor = (Real)1 / (samples * binSize);

        for (integer y = 0;y < yBins;++y)
        {
            for (integer x = 0;x < xBins;++x)
            {
                output(x, y) *= factor;
            }
        }
    }

}

#endif