/*------------------------------------------------------------------------------*
 * File Name: MedianFilter.c 													*
 * Creation: ER (05/19/04)														*
 * Purpose: Perform median filtering on a dataset								*
 * Copyright (c) OriginLab Corp.2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010	*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *------------------------------------------------------------------------------*/
 
////////////////////////////////////////////////////////////////////////////////////
#include <Origin.h>
////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////
// This function performs median filtering on a dataset. At each point in the dataset,
// n neighboring points on each side are considered, and the median of all those points
// is assigned as the filtered result for that point. At the edges, where enough neighbors
// are not present, the median is computed with the available number of points.
// Parameters:
//			strSrc: 	Name of source dataset
//			strDest:	Name of destination dataset
//			iNumPts:	Number of points on either side, to consider for computing median
//
// Return:
//			0:			success
//			non-zero:	failure
int median_filter(string strSrc, string strDest, int iNumPts, double dPerc = 50)
{
	// Declare datasets and check for validity
	Dataset dsSrc(strSrc);
	Dataset dsDest(strDest);
	if(!dsSrc || !dsDest)
	{
		printf("Invalid Dataset(s)!\n");
		return -1;
	}
	// Check size of number of neighbors for computing median
	int iSize = dsSrc.GetSize();
	if( (iNumPts < 1) || ((iNumPts * 2) >= iSize/2) )
	{
		printf("Invalid group size!\n");
		return -2;
	}
	// Set size of result to be same as source
	dsDest.SetSize(iSize);
	
	// Loop over all points in source and find median of neighboring points
	waitCursor wCursor;
	for(int ii = 0; ii < iSize - 1; ii++)
	{
		// Set lower and upper bounds on source data to only include current neighbors for computing median
		dsSrc.SetLowerBound(ii - iNumPts);
		dsSrc.SetUpperBound(ii + iNumPts);
		// Compute median and store to result
		double dMedian;
		Data_percentiles(&dsSrc, &dPerc, &dMedian, 1);
		dsDest[ii] = dMedian;
	}
	
	// Reset lower and upper bounds of soure dataset
	dsSrc.SetLowerBound(0);
	dsSrc.SetUpperBound(iSize - 1);
	
	// Return success
	return 0;
}
// end