WSL/SLF GitLab Repository

Commit 3ec508db authored by Mathias Bavay's avatar Mathias Bavay
Browse files

The median computations were relying on std::nth_element and wrongly assuming...

The median computations were relying on std::nth_element and wrongly assuming that the output would be sorted. This is non-standard behavior and is not the case with more recent versions of the STL. This has been fixed.

The ProcessingStack constructor has been optimized by using new methods of Config to remove some now redundant code.
parent b489efef
......@@ -57,17 +57,21 @@ double FilterMedianAvg::calc_median(const std::vector<MeteoData>& ivec, const un
vecTemp.push_back(value);
}
const size_t size_of_vec = vecTemp.size();
if (size_of_vec == 0)
const size_t vecSize = vecTemp.size();
if (vecSize == 0)
return IOUtils::nodata;
const int middle = (int)(size_of_vec/2);
nth_element(vecTemp.begin(), vecTemp.begin()+middle, vecTemp.end());
if ((size_of_vec % 2) == 1){ //uneven
if ((vecSize % 2) == 1){ //uneven
const int middle = (int)(vecSize/2);
nth_element(vecTemp.begin(), vecTemp.begin()+middle, vecTemp.end());
return *(vecTemp.begin()+middle);
} else { //use arithmetic mean of element n/2 and n/2-1
return Interpol1D::weightedMean( *(vecTemp.begin()+middle), *(vecTemp.begin()+middle-1), 0.5);
const int middle = (int)(vecSize/2);
nth_element(vecTemp.begin(), vecTemp.begin()+middle-1, vecTemp.end());
const double m1 = *(vecTemp.begin()+middle-1);
nth_element(vecTemp.begin(), vecTemp.begin()+middle, vecTemp.end());
const double m2 = *(vecTemp.begin()+middle);
return Interpol1D::weightedMean( m1, m2, 0.5);
}
}
......
......@@ -23,12 +23,12 @@ namespace mio {
ProcessingStack::ProcessingStack(const Config& cfg, const std::string& parname) : filter_stack(), param_name(parname)
{
vector<string> vec_filters;
const size_t nr_of_filters = getFiltersForParameter(cfg, param_name, vec_filters);
vector<string> vecFilters;
cfg.getValues(parname+"::filter", "Filters", vecFilters);
const size_t nr_of_filters = vecFilters.size();
for (size_t ii=0; ii<nr_of_filters; ii++){
//create a processing block for each filter
string block_name = vec_filters[ii];
IOUtils::toUpper(block_name);
const string block_name = IOUtils::strToUpper( vecFilters[ii] );
std::vector<std::string> vec_args;
std::ostringstream tmp;
tmp << param_name << "::arg" << (ii+1);
......@@ -67,24 +67,6 @@ void ProcessingStack::getWindowSize(ProcessingProperties& o_properties)
}
}
size_t ProcessingStack::getFiltersForParameter(const Config& cfg, const std::string& parname, std::vector<std::string>& vecFilters)
{
/*
* This function retrieves the filter sequence for parameter 'parname'
* by querying the Config object
*/
std::vector<std::string> vecKeys;
cfg.findKeys(vecKeys, parname+"::filter", "Filters");
for (size_t ii=0; ii<vecKeys.size(); ii++){
std::string tmp;
cfg.getValue(vecKeys[ii], "Filters", tmp, IOUtils::nothrow);
vecFilters.push_back(tmp);
}
return vecFilters.size();
}
size_t ProcessingStack::getArgumentsForFilter(const Config& cfg, const std::string& keyname,
std::vector<std::string>& vecArguments)
{
......@@ -102,7 +84,6 @@ void ProcessingStack::process(const std::vector< std::vector<MeteoData> >& ivec,
if (!ivec[ii].empty()){
//pick one element and check whether the param_name parameter exists
const size_t param = ivec[ii].front().getParameterIndex(param_name);
if (param != IOUtils::npos){
std::vector<MeteoData> tmp = ivec[ii];
......
......@@ -48,8 +48,7 @@ class ProcessingStack {
const std::string toString() const;
private:
size_t getFiltersForParameter(const Config& cfg, const std::string& parname, std::vector<std::string>& vecFilters);
size_t getArgumentsForFilter(const Config& cfg, const std::string& keyname, std::vector<std::string>& vecArguments);
static size_t getArgumentsForFilter(const Config& cfg, const std::string& keyname, std::vector<std::string>& vecArguments);
std::vector<ProcessingBlock*> filter_stack; //for now: strictly linear chain of processing blocks
std::string param_name;
......
......@@ -164,7 +164,6 @@ bool Interpol1D::pair_comparator(const std::pair<double, double>& l, const std::
double Interpol1D::weightedMean(const double& d1, const double& d2, const double& weight)
{
const double tmp = abs(d1 - d2);
if (d1 < d2) {
return (d1 + tmp*weight);
} else {
......@@ -247,13 +246,17 @@ double Interpol1D::getMedian(const std::vector<double>& vecData)
if (vecSize == 0)
return IOUtils::nodata;
const int middle = (int)(vecSize/2);
nth_element(vecTemp.begin(), vecTemp.begin()+middle, vecTemp.end());
if ((vecSize % 2) == 1){ //uneven
const int middle = (int)(vecSize/2);
nth_element(vecTemp.begin(), vecTemp.begin()+middle, vecTemp.end());
return *(vecTemp.begin()+middle);
} else { //use arithmetic mean of element n/2 and n/2-1
return weightedMean( *(vecTemp.begin()+middle), *(vecTemp.begin()+middle-1), 0.5);
const int middle = (int)(vecSize/2);
nth_element(vecTemp.begin(), vecTemp.begin()+middle-1, vecTemp.end());
const double m1 = *(vecTemp.begin()+middle-1);
nth_element(vecTemp.begin(), vecTemp.begin()+middle, vecTemp.end());
const double m2 = *(vecTemp.begin()+middle);
return weightedMean( m1, m2, 0.5);
}
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment