/*! \file BinningObject.cc
    \brief Implementation of the Template class BinningObject.
    
    Magics Team - ECMWF 2011
    
    Started: Thu 7-Apr-2011
    
    Changes:
    
*/



#include "BinningObject.h"


using namespace magics;



BinningObject::BinningObject() 
{

	binners_x_["count"] = &BinningObject::countx;
	binners_x_["list"] = &BinningObject::listx;
	binners_x_["interval"] = &BinningObject::intervalx;

	binners_y_["count"] = &BinningObject::county;
	binners_y_["list"] = &BinningObject::listy;
	binners_y_["interval"] = &BinningObject::intervaly;

}


BinningObject::~BinningObject() 
{
}

/*!
 Class information are given to the output-stream.
*/		
void BinningObject::print(ostream& out)  const
{
	out << "BinningObject[";
	out << "]";
}

void BinningObject::build(vector<double>& vals, IntervalMap<int>& binns)
{
	vector<double>::iterator from = vals.begin();
	vector<double>::iterator to  = vals.begin();
	++to;
	int index = 0;
	while ( to != vals.end() ) {
		binns.insert(make_pair(Interval(*from, *to), index));
		index++;
		++to;
		++from;
	}
}

/*


*/
static double mindef = -1.0e+21;
static double maxdef = 1.0e+21;

void  BinningObject::countx(vector<double>& vals, double min, double max)
{
	double vmin = ( x_min_ == mindef) ? min : std::max(min, x_min_);
	double vmax = ( x_max_ == maxdef) ? max : std::min(max, x_max_);

	double step = (max-min)/x_count_;

	int index = 0;
	for (double val = vmin; val <= vmax; val+=step) {
		vals.push_back(val);
		index++;
	}

}

void  BinningObject::county(vector<double>& vals, double min, double max)
{
	double vmin = ( y_min_ == mindef) ? min : std::max(min, y_min_);
	double vmax = ( y_max_ == maxdef) ? max : std::min(max, y_max_);
	double step = (max-min)/y_count_;

	int index = 0;
	for (double val = vmin; val <= vmax; val+=step) {
		vals.push_back(val);
		index++;
	}
}

void  BinningObject::listx(vector<double>& vals, double min, double max)
{
	double vmin = ( y_min_ == mindef) ? min : std::max(min, y_min_);
	double vmax = ( y_max_ == maxdef) ? max : std::min(max, y_max_);

	for (vector<double>::iterator val = x_list_.begin(); val != x_list_.end(); ++val) {
		if ( *val >=vmin && *val <=vmax )
			vals.push_back(*val);
	}


}
void  BinningObject::listy(vector<double>& vals, double min, double max)
{
	double vmin = ( y_min_ == mindef) ? min : std::max(min, y_min_);
	double vmax = ( y_max_ == maxdef) ? max : std::min(max, y_max_);

	for (vector<double>::iterator val = x_list_.begin(); val != x_list_.end(); ++val) {
		if ( *val >=vmin && *val <=vmax )
			vals.push_back(*val);
	}

}

void  BinningObject::intervalx(vector<double>& vals, double min, double max)
{
	double vmin = ( x_min_ == mindef) ? min : std::max(min, x_min_);
	double vmax = ( x_max_ == maxdef) ? max : std::min(max, x_max_);

	for (double val = x_reference_; val <= vmax; val+= x_interval_)
		vals.push_back(val);
	for (double val = x_reference_ - x_interval_; val >= vmin; val -= x_interval_)
		vals.push_back(val);

	std::sort(vals.begin(), vals.end());

}
void  BinningObject::intervaly(vector<double>& vals, double min, double max)
{
	double vmin = ( y_min_ == mindef) ? min : std::max(min, y_min_);
	double vmax = ( y_max_ == maxdef) ? max : std::min(max, y_max_);

	for (double val = y_reference_; val <= vmax; val+= y_interval_)
		vals.push_back(val);
	for (double val = y_reference_ - y_interval_; val >= vmin; val -= y_interval_)
		vals.push_back(val);

	std::sort(vals.begin(), vals.end());
}

