MedianFunc.hh 3.48 KB
/*
 * MedianFunc.hh
 *
 *  Created on: Jun 23, 2018
 *      Author: benjamin
 */

#ifndef MEDIANFUNC_HH_
#define MEDIANFUNC_HH_

#include "AbstractFunc.hh"
#include "Toolbox.hh"

namespace AMDA {
namespace Parameters {
namespace StatisticFunctions {

template <typename Type>
bool getMedian(std::list<Type>& list, Type& result) {
	result << NotANumber();

	if (list.empty()) {
		return false;
	}

	std::vector<Type> sorted_list;
	for (typename std::list<Type>::iterator it = list.begin(); it != list.end(); ++it) {
		if (isNAN(*it)) {
			continue;
		}
		sorted_list.push_back(*it);
	}
	std::sort(sorted_list.begin(), sorted_list.end());

	if (sorted_list.empty()) {
		return false;
	}

	if (sorted_list.size() % 2 == 0) {
		//even
		int index = (sorted_list.size() / 2);
		result = sorted_list[index];
	}
	else {
		//odd
		int index = (sorted_list.size() / 2);
		result = (sorted_list[index] + sorted_list[index+1]) / 2.;
	}
	return true;
}

template <typename Type>
bool getMedian(std::list<std::vector<Type>>& list, std::vector<Type>& result) {
	if (list.empty()) {
		return false;
	}
	result = list.front();
	result << NotANumber();
	int eltSize = result.size();
	for (int i = 0; i < eltSize; ++i) {
		std::list<Type> compList;
		for (typename std::list<std::vector<Type>>::iterator it = list.begin(); it != list.end(); ++it) {
			if ((int)it->size() != eltSize) {
				continue;
			}
			compList.push_back((*it)[i]);
		}
		Type compRes;
		getMedian(compList, compRes);
		result[i] = compRes;
	}
	return true;
}

template <typename Type>
bool getMedian(std::list<Tab2DData<Type>>& list, Tab2DData<Type>& result) {
	if (list.empty()) {
		return false;
	}
	Tab2DData<Type> nanVal(list.front());
	nanVal << NotANumber();
	result = nanVal;
	int eltDim1Size = result.getDim1Size();
	int eltDim2Size = result.getDim2Size();
	for (int i = 0; i < eltDim1Size; ++i) {
		for (int j = 0; j < eltDim2Size; ++j) {
			std::list<Type> compList;
			for (typename std::list<Tab2DData<Type>>::iterator it = list.begin(); it != list.end(); ++it) {
				if (it->getDim1Size() != eltDim1Size || it->getDim2Size() != eltDim2Size) {
					continue;
				}
				compList.push_back((*it)[i][j]);
			}
			Type compRes;
			getMedian(compList, compRes);
			result[i][j] = compRes;
		}
	}
	return true;
}

template <typename InputElemType, typename OutputElemType>
OutputElemType computeMedian(std::list<std::pair<double,InputElemType>>& mem, OutputElemType& nanVal) {
	OutputElemType result = nanVal;
	if (mem.empty()) {
		return result;
	}
	std::list<InputElemType> list;
	for (typename std::list<std::pair<double,InputElemType>>::iterator it = mem.begin(); it != mem.end(); ++it) {
		list.push_back(it->second);
	}
	getMedian(list, result);
	return result;
}

/**
 * @class MedianFunc
 * @brief 
 * @details This class implements AbstractFunc.
 */
template <typename InputElemType, typename OutputElemType> 
class MedianFunc : public ClassicAbstractFunc<InputElemType,OutputElemType> {
public:
	/**
	 * @brief Constructor.
	 */
	MedianFunc(Process& pProcess, TimeIntervalListSPtr pTimeIntervalList, ParamDataSpec<InputElemType>& paramInput, double windowtime)
	: ClassicAbstractFunc<InputElemType,OutputElemType>(pProcess, pTimeIntervalList, paramInput, windowtime) {
	}

	virtual ~MedianFunc() {
	}

	OutputElemType compute() {
		return computeMedian(ClassicAbstractFunc<InputElemType,OutputElemType>::_mem, ClassicAbstractFunc<InputElemType,OutputElemType>::_nanVal);
	}
};  

} /* namespace StatisticFunctions */
} /* namespace Parameters */
} /* namespace AMDA */
#endif /* MEDIANFUNC_HH_ */