Skip to content

Commit

Permalink
Add Z score functions to Stats namespace.
Browse files Browse the repository at this point in the history
Refs #7891
  • Loading branch information
martyngigg committed Jan 31, 2014
1 parent 518bf17 commit 6adb3a2
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 18 deletions.
Expand Up @@ -61,6 +61,57 @@ namespace
// Define an overload to handle the default argument
BOOST_PYTHON_FUNCTION_OVERLOADS(getStatisticsOverloads, getStatisticsNumpy, 1, 2);

//============================ Z score ============================================
// Function pointer to real implementation of Zscore functions
typedef std::vector<double> (*ZScoreFunction)(const std::vector<double>& data, const bool sorted);

/**
* The implementation for getMomentsAboutOrigin & getMomentsAboutOriginMean for using
* numpy arrays are identical. This encapsulates that behaviour an additional parameter for
* specifying the actual function called along.
* @param momentsFunc A function pointer to the required moments function
* @param data Numpy array of data
* @param sorted True if the input data is already sorted
*/
std::vector<double> getZScoreNumpyImpl(ZScoreFunction zscoreFunc, const numeric::array& data,
const bool sorted)
{
using Converters::NDArrayToVector;

auto *dataPtr = data.ptr();
if(PyArray_ISFLOAT(dataPtr))
{
return zscoreFunc(NDArrayToVector<double>(data)(), sorted);
}
else
{
throw UnknownDataType();
}
}

/**
* Proxy for @see Mantid::Kernel::getZscore so that it can accept numpy arrays,
*/
std::vector<double> getZscoreNumpy(const numeric::array & data, const bool sorted = false)
{
using Mantid::Kernel::getZscore;
return getZScoreNumpyImpl(&getZscore, data, sorted);
}
// Define an overload to handle the default argument
BOOST_PYTHON_FUNCTION_OVERLOADS(getZscoreOverloads, getZscoreNumpy, 1, 2);

/**
* Proxy for @see Mantid::Kernel::getModifiedZscore so that it can accept numpy arrays,
*/
std::vector<double> getModifiedZscoreNumpy(const numeric::array & data, const bool sorted = false)
{
using Mantid::Kernel::getModifiedZscore;
return getZScoreNumpyImpl(&getModifiedZscore, data, sorted);
}
// Define an overload to handle the default argument
BOOST_PYTHON_FUNCTION_OVERLOADS(getModifiedZscoreOverloads, getModifiedZscoreNumpy, 1, 2);


//============================ getMoments ============================================

// Function pointer to real implementation of getMoments
Expand Down Expand Up @@ -138,25 +189,35 @@ void export_Statistics()
// define a new "Statistics" scope so that everything is called as Statistics.getXXX
// this affects everything defined within the lifetime of the scope object
scope stats = class_<Stats>("Stats",no_init)
.def("getStatistics", &getStatisticsNumpy,
getStatisticsOverloads(args("data", "sorted"),
"Determine the statistics for an array of data")
.def("getStatistics", &getStatisticsNumpy,
getStatisticsOverloads(args("data", "sorted"),
"Determine the statistics for an array of data")
)
.staticmethod("getStatistics")

.def("getMomentsAboutOrigin", &getMomentsAboutOriginNumpy,
getMomentsAboutOriginOverloads(args("indep", "depend", "maxMoment"),
"Calculate the first n-moments (inclusive) about the origin"
)[ReturnNumpyArray()])
.staticmethod("getMomentsAboutOrigin")

.def("getMomentsAboutMean", &getMomentsAboutMeanNumpy,
getMomentsAboutMeanOverloads(args("indep", "depend", "maxMoment"),
"Calculate the first n-moments (inclusive) about the mean"
)[ReturnNumpyArray()])
.staticmethod("getMomentsAboutMean")


.staticmethod("getStatistics")

.def("getZscore", &getZscoreNumpy,
getZscoreOverloads(args("data", "sorted"),
"Determine the Z score for an array of data")
)
.staticmethod("getZscore")

.def("getModifiedZscore", &getModifiedZscoreNumpy,
getModifiedZscoreOverloads(args("data", "sorted"),
"Determine the modified Z score for an array of data")
)
.staticmethod("getModifiedZscore")

.def("getMomentsAboutOrigin", &getMomentsAboutOriginNumpy,
getMomentsAboutOriginOverloads(args("indep", "depend", "maxMoment"),
"Calculate the first n-moments (inclusive) about the origin"
)[ReturnNumpyArray()])
.staticmethod("getMomentsAboutOrigin")

.def("getMomentsAboutMean", &getMomentsAboutMeanNumpy,
getMomentsAboutMeanOverloads(args("indep", "depend", "maxMoment"),
"Calculate the first n-moments (inclusive) about the mean"
)[ReturnNumpyArray()])
.staticmethod("getMomentsAboutMean")
;

//------------------------------ Statistics values -----------------------------------------------------
Expand Down
Expand Up @@ -34,6 +34,20 @@ def test_getStatistics_accepts_sorted_arg(self):
self.assertEquals(18.3, stats.maximum)
self.assertEquals(17.2, stats.median)


def test_getZScores(self):
"""Data taken from C++ test"""
values = [12,13,9,18,7,9,14,16,10,12,7,13,14,19,10,16,12,16,19,11]
arr = numpy.array(values,dtype=numpy.float64)

zscore = Stats.getZscore(arr)
self.assertAlmostEqual(1.63977, zscore[4], places = 4)
self.assertAlmostEqual(0.32235, zscore[6], places = 4)

modZ = Stats.getModifiedZscore(arr)
self.assertAlmostEqual(1.23658, modZ[4], places = 4)
self.assertAlmostEqual(0.33725, modZ[6], places = 4)

def test_getMoments(self):
mean = 5.
sigma = 4.
Expand Down

0 comments on commit 6adb3a2

Please sign in to comment.