/* ImLib3D
 * Copyright (c) 2001, ULP-IPB Strasbourg.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
/*! \file Signal1D.hpp */


#ifndef _Signal1D_hpp
#define _Signal1D_hpp

#include<ImLib3D/CppTools.hpp>
#include<math.h>

//! One dimensional signal containing floating point values. New samples can be (log-time) added.
/*! Signal values can be addressed as samples, or as being defined on a floating point segment (x0-x1)*/
class Signal1Df
{
	int size;
	float x0,x1;
	vector<float> values;
public:
	int NbSambles(){return size;}
	int Size(){return size;}
	void GnuPlot()
	{
		vector<float> coords(size);
		for(int i=0;i<size;i++){coords[i]=ISampleToX(i);}
		::GnuPlot(coords,values);
	}
	float XToFSample(float x){return      (((x-x0)/(x1-x0))*size);}
	int   XToISample(float x){return (int)(((x-x0)/(x1-x0))*size);}
	float ISampleToX(int   i){return (i*(x1-x0)/size)+x0;}
	float &operator[](int i){return(values[i]);}
	float  operator()(float x){return ValueL(x);}
	float &SafeSample(int i)
	{
		if(i<0){return values[0];}
		else
		if(i>=size){return values[size-1];}
		else
		{return values[i];}
	}
	//! linear interpolation
	float ValueL(float x)
	{
		x=XToFSample(x);
		int i0=(int)x;
		float dx=x-i0;
		return(SafeSample(i0)*(1-dx)+SafeSample(i0+1)*dx);
	}
	float &Value(float rx){return SafeSample(XToISample(rx));}
	void Stats2ndOrder(float &avg,float &sigma)
	{
		float tot=0;
		float tot2=0;
		for(uint i=0;i<values.size();i++)
		{
			tot +=values[i];
			tot2+=values[i]*values[i];
		}
		avg=tot/size;
		sigma=sqrt(tot2/size-avg*avg);
	}
	void Smooth(int fradius=3)
	{
		// smooth this a bit
		vector<float> v0=values;
		for(int x=0;x<size;x++)
		{
			double s=0;
			int ct=0;
			for(int xx=x-fradius;xx<=x+fradius;xx++)
			{
				if(xx<0 || xx>=size){continue;}
				s+=v0[xx];
				ct++;
			}
			values[x]=(ct>0 ? s/ct :0);
		}
	}

	void AddSampleAtBegining(float val)
	{
		x0-=(x1-x0)/size;
		size++;
		values.insert(values.begin(),val);
	}
	void AddSampleAtEnd(float val)
	{
		x1+=(x1-x0)/size;
		size++;
		values.push_back(val);
	}
	Signal1Df(int _size,float _x0=0,float _x1=1):
		size(_size),x0(_x0),x1(_x1)
	{
		values.assign(size,0);
	}
};
//! Linearly fill up regions in a fct that have low confidence measure 
void LinearCompleteLowConfidence(Signal1Df &fct,vector<double> &confidence,float minconf);

#endif// _Signal1D_hpp
