计算分段采样区间中的平均值,标准差,中位数,积分值等的类
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 ---