计算分段采样区间中的平均值,标准差,中位数,积分值等的类

SampleFits.java

 

package org.eso.fits;

import java.util.Arrays;


public class SampleFits {
	/*本类完成的功能:对输入的的初始样本lamda, flux,根据整个采样区间的边界值如[3900 9000]以及采样间隔50进行分段,
	 * 在例子中,lambda和flux的长度应该从小到大有序而且一致,并且lambda的区间范围应该包括边界值[3900 9000];
	对于每段,可以计算每段flux对应的平均值,标准差,中位数,积分值等方法。*/
	//错误定义
	private final int ERROR_NOTFOUND = 0;
	private final int ERROR_BOUND = 1;
	private final int ERROR_LENGTH = 2;
	private final int ERROR_SAMPLESIZE = 3;
	
	//类成员变量
	private double sampleSize;//采样间隔
	private double sampleLowArea;//整个采样区间的左边界
	private double sampleUpArea;//整个采样区间的右边界
	private double[] lambda; //初始数据X
	private double[] flux;   //初始数据Y

	//初始化类成员变量
	public SampleFits(double[] dataX, double[] dataY) {
		
		sampleSize = 50;
		sampleLowArea = 3900;
		sampleUpArea = 9000;
		
		lambda = new double[dataX.length];
		flux = new double[dataY.length];
		System.arraycopy(dataX, 0, lambda, 0, dataX.length);
		System.arraycopy(dataY, 0, flux, 0, dataY.length);		
		
		if (ErrorCheck() != ERROR_NOTFOUND) {
			System.out.println("Please take care of the argvs!");
		}
	}

	public SampleFits(int sampleSize, int sampleLowArea, int sampleUpArea, double[] dataX, double[] dataY) {
		this.sampleSize = sampleSize;
		this.sampleLowArea = sampleLowArea;
		this.sampleUpArea = sampleUpArea;

		lambda = new double[dataX.length];
		flux = new double[dataY.length];
		System.arraycopy(dataX, 0, lambda, 0, dataX.length);
		System.arraycopy(dataY, 0, flux, 0, dataY.length);			
		
		if (ErrorCheck() != ERROR_NOTFOUND) {
			System.out.println("Please take care of the argvs!");
		}
	}

	//获取相关成员变量的值
	public double GetSampleSize(){
		return sampleSize;
	}
	
	public double GetsampleLowArea(){
		return sampleLowArea;
	}
	
	public double GetsampleUpArea(){
		return sampleUpArea;
	}
	
	//通过整个采样区间以及采样间隔,计算划分的区间个数
	public int GetRangNum() {
		double n = (double) (sampleUpArea - sampleLowArea) / (double) sampleSize;
		return (int) Math.floor(n);
	}

    //获取整个采样区间中每段的平均值
	public void GetMeanValue(double[] meanValue) {
		int rangNum = GetRangNum();
		int[] pointNums = new int[rangNum];
		CalcPointNums(pointNums);
		int start_pos = CalcPos(sampleLowArea);

		for (int i = 0; i < rangNum; i++) {
			double sum = 0;
			if (pointNums[i] != 0) {
				for (int j = 0; j < pointNums[i]; j++) {
					sum += flux[start_pos++];
				}
				meanValue[i] = sum / pointNums[i];
			} else {
				meanValue[i] = 0;
			}

		}
	}

	//获取整个采样区间中每段的标准差
	public void GetStdValue(double[] stdValue) {
		int rangNum = GetRangNum();
		int[] pointNums = new int[rangNum];
		CalcPointNums(pointNums);
		int start_pos = CalcPos(sampleLowArea);
		double[] meanValue = new double[rangNum];
		GetMeanValue(meanValue);

		for (int i = 0; i < rangNum; i++) {
			double sum = 0;
			if (pointNums[i] != 0) {
				for (int j = 0; j < pointNums[i]; j++) {
					sum += Math.pow((flux[start_pos++] - meanValue[i]), 2);
				}
				stdValue[i] = (double) Math.sqrt(sum / pointNums[i]);
			} else {
				stdValue[i] = 0;
			}
		}
	}
	
	//获取整个采样区间中每段的中位数
    public void GetMedianValue(double[] midValue) {
    
		int rangNum = GetRangNum();
		int[] pointNums = new int[rangNum];
		CalcPointNums(pointNums);
		int start_pos = CalcPos(sampleLowArea);
		
		int srcPos = start_pos;
		for (int i = 0; i < rangNum; i++) {
			double[] flux_rang = new double[pointNums[i]];
			System.arraycopy(flux, srcPos, flux_rang, 0, pointNums[i]);
			midValue[i] = CalcMedian(flux_rang);
			srcPos += pointNums[i];
		}
    }
    
    //获取整个采样区间的积分值
    public double GetRangIntergral(double[] area){
    	int left_pos = CalcPos(area[0]);
    	int right_pos = CalcPos(area[1]);
    	int len = right_pos - left_pos;
    	double[] lambda_Rang = new double[len];
    	double[] flux_Rang = new double[len];
    	System.arraycopy(lambda, left_pos, lambda_Rang, 0, len);
    	System.arraycopy(flux, left_pos, flux_Rang, 0, len);
    	return CalcIntergral(lambda_Rang, flux_Rang);
    	
    }
    
    //对于给定的arrX和对应的arrY,计算积分值,在x轴上方为正,下方为负进行累加。每一小段通过梯形(或三角形)的面积计算
	private double CalcIntergral(double[] arrX, double[] arrY){

		double sum = 0;
		for (int i = 0; i < arrX.length-1; i++) {
			if (arrY[i] * arrY[i+1] >= 0) {
				sum += (arrY[i+1] + arrY[i]) * (arrX[i+1] - arrX[i]) / 2;
			}
			else {
				double k = (arrY[i+1] - arrY[i]) / (arrX[i+1] - arrX[i]);
				double x_0 = arrX[i] - (arrY[i] / k);
				sum += (arrY[i] * (x_0 - arrX[i]) / 2);
				sum += (arrY[i+1] * (arrX[i+1] - x_0) / 2);
			}
			
		}
		return sum;
	}
	
	//错误检测,主要是边界,x,y的长度是否一致,采样间隔设置是否有问题
	private int ErrorCheck() {
		double leftBound = lambda[0];
		double rightBound = lambda[lambda.length - 1];

		if (sampleLowArea < leftBound || sampleUpArea > rightBound) {
			System.out.println("The bound is error!");
			return ERROR_BOUND;
		}
		else if (lambda.length != flux.length) {
			System.out.println("The length of lambda and flux is error!");
			return ERROR_LENGTH;
		}
		else if (0 == sampleSize || GetRangNum() < 1) {
			System.out.println("sampleSize is too large!");
			return ERROR_SAMPLESIZE;
		}
		return ERROR_NOTFOUND;
		
	}

	//计算整个采样区间中每段的点的个数
	private void CalcPointNums(int[] pointNums) {
		for (int i = 0; i < pointNums.length; i++) {
			int startPos = CalcPos(sampleLowArea + i * sampleSize);
			int endPos = CalcPos(sampleLowArea + (i + 1) * sampleSize);
			pointNums[i] = endPos - startPos;

		}

	}

	//计算某个x坐标的值val在整个全区间中的位置,这里注意的是位置索引是第一个大于val的值的下标
	private int CalcPos(double val) {
		int pos = 0;
		for (int i = 0; i < lambda.length; i++) {
			if (val < lambda[i]) {
				pos = i;
				break;
			}
		}
		return pos;
	}
	
	//对于数组arrY,求中位数,这里是用先排序的方法求中位数
    private double CalcMedian(double[] arrY) {
    	double[] b = new double[arrY.length];
        System.arraycopy(arrY, 0, b, 0, b.length);
        Arrays.sort(b);

        if (arrY.length % 2 == 0) {
            return (b[(b.length / 2) - 1] + b[b.length / 2]) / 2.0;
        } else {
            return b[b.length / 2];
        }
    }
    
}


Test

 

 

  	//-----------------------------Test SampleFits----------------------------
    	double[] xx = {1, 2.1, 3.3, 5.4, 7, 9.4, 10, 12.3, 14, 16.5, 17.3, 20};
    	double[] yy = {3, 3, 4, -4, -5, -5, 6, 6, 7, 7, 8, 8};
    	SampleFits testFits = new SampleFits(4, 2, 18, xx, yy);
    	int num = testFits.GetRangNum();
    	System.out.println("num--"+num);
    	
    	double[] mv = new double[num];
    	testFits.GetMeanValue(mv);
    	double[] std = new double[num];
    	testFits.GetStdValue(std);
    	double[] mid = new double[num];
    	testFits.GetMedianValue(mid); 
    	double[] area = {4, 15};
    	double intergal = testFits.GetRangIntergral(area);
    	
    	for (int i = 0; i < std.length; i++) {
			System.out.println("mean--"+mv[i]);
			System.out.println("std--"+std[i]);
			System.out.println("mid--"+mid[i]);
			System.out.println("intergal--"+intergal);
		}
    	//-----------------------------------------------------------------------
    	System.out.println("----end ---");


Output:

 

 

num--4
mean--1.0
std--3.559026084010437
mid--3.0
intergal--5.949999999999994
mean---1.3333333333333333
std--5.185449728701348
mid---5.0
intergal--5.949999999999994
mean--6.5
std--0.5
mid--6.5
intergal--5.949999999999994
mean--7.5
std--0.5
mid--7.5
intergal--5.949999999999994
----end ---


 


 

posted @ 2013-06-06 23:07  jlins  阅读(990)  评论(0编辑  收藏  举报