예제 #1
0
  /**
   * Utility to facilitate fitting data plotted in JFreeChart Provide data in JFReeChart format
   * (XYSeries), and retrieve univariate function parameters that best fit (using least squares) the
   * data. All data points will be weighted equally.
   *
   * <p>TODO: investigate whether weighting (possibly automatic weighting) can improve accuracy
   *
   * @param data xy series in JFReeChart format
   * @param type one of the Fitter.FunctionType predefined functions
   * @param guess initial guess for the fit. The number and meaning of these parameters depends on
   *     the FunctionType. Implemented: Gaussian: 0: Normalization, 1: Mean 2: Sigma
   * @return array with parameters, whose meaning depends on the FunctionType. Use the function
   *     getXYSeries to retrieve the XYDataset predicted by this fit
   */
  public static double[] fit(XYSeries data, FunctionType type, double[] guess) {

    if (type == FunctionType.NoFit) {
      return null;
    }
    // create the commons math data object from the JFreeChart data object
    final WeightedObservedPoints obs = new WeightedObservedPoints();
    for (int i = 0; i < data.getItemCount(); i++) {
      obs.add(1.0, data.getX(i).doubleValue(), data.getY(i).doubleValue());
    }

    double[] result = null;
    switch (type) {
      case Pol1:
        final PolynomialCurveFitter fitter1 = PolynomialCurveFitter.create(1);
        result = fitter1.fit(obs.toList());
        break;
      case Pol2:
        final PolynomialCurveFitter fitter2 = PolynomialCurveFitter.create(2);
        result = fitter2.fit(obs.toList());
        break;
      case Pol3:
        final PolynomialCurveFitter fitter3 = PolynomialCurveFitter.create(3);
        result = fitter3.fit(obs.toList());
        break;
      case Gaussian:
        final GaussianWithOffsetCurveFitter gf = GaussianWithOffsetCurveFitter.create();
        if (guess != null) {
          gf.withStartPoint(guess);
        }
        result = gf.fit(obs.toList());
    }

    return result;
  }
예제 #2
0
 /**
  * Approximate an already fitted model to polynomial only terms.
  *
  * <p>This method is mainly used in order to combine the large amplitude long periods with the
  * secular part as a new approximate polynomial model over some time range. This should be used
  * rather than simply extracting the polynomial coefficients from {@link #getFittedParameters()}
  * when some periodic terms amplitudes are large (for example Sun resonance effects on local solar
  * time in sun synchronous orbits). In theses cases, the pure polynomial secular part in the
  * coefficients may be far from the mean model.
  *
  * @param combinedDegree desired degree for the combined polynomial
  * @param combinedReference desired reference date for the combined polynomial
  * @param meanDegree degree of polynomial secular part to consider
  * @param meanHarmonics number of harmonics terms to consider
  * @param start start date of the approximation time range
  * @param end end date of the approximation time range
  * @param step sampling step
  * @return coefficients of the approximate polynomial (in increasing degree order), using the user
  *     provided reference date
  */
 public double[] approximateAsPolynomialOnly(
     final int combinedDegree,
     final AbsoluteDate combinedReference,
     final int meanDegree,
     final int meanHarmonics,
     final AbsoluteDate start,
     final AbsoluteDate end,
     final double step) {
   final List<WeightedObservedPoint> points = new ArrayList<WeightedObservedPoint>();
   for (AbsoluteDate date = start; date.compareTo(end) < 0; date = date.shiftedBy(step)) {
     points.add(
         new WeightedObservedPoint(
             1.0,
             date.durationFrom(combinedReference),
             meanValue(date, meanDegree, meanHarmonics)));
   }
   return PolynomialCurveFitter.create(combinedDegree).fit(points);
 }
예제 #3
0
  public static void main(String[] args) {
    //////////////////////////
    // The values in following 4 lines should be user input
    int startPos = 200;
    int endPos = 1000;
    int totalNumPixel = 1044;
    double threshhold = 0.0001;
    /////////////////////////
    int numPixel = endPos - startPos;
    double wavelength[] = new double[totalNumPixel];
    double photonCount[] = new double[totalNumPixel];
    double SpecNoBk[] = new double[numPixel];
    double ThisSpectrum[] = new double[numPixel];
    double ThisXaxis[] = new double[numPixel];
    double Po[] = new double[numPixel];
    double Re[] = new double[numPixel];
    double P[] = new double[6];
    double Re2[] = new double[numPixel - 1];
    double mySUM[] = new double[numPixel];
    int ind[];
    double DEV;
    double prevDEV;
    Connection connection = null;
    Statement stmt = null;
    String pattern = "##.##";

    try {
      Scanner in = new Scanner(new FileReader(args[0]));
      int i = 0;
      while (in.hasNextDouble()) {
        wavelength[i] = in.nextDouble();
        photonCount[i] = in.nextDouble();
        ++i;
      }
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }

    ThisSpectrum = Arrays.copyOfRange(photonCount, startPos, endPos);
    ThisXaxis = Arrays.copyOfRange(wavelength, startPos, endPos);
    final WeightedObservedPoints obs = new WeightedObservedPoints();

    for (int i = 0; i < numPixel; i++) {
      obs.add(ThisXaxis[i], ThisSpectrum[i]);
    }

    final PolynomialCurveFitter fitter = PolynomialCurveFitter.create(5);
    P = fitter.fit(obs.toList());
    Polyval pVal = new Polyval(P, ThisXaxis, numPixel);
    Po = pVal.evl();

    for (int i = 0; i < numPixel; i++) {
      Re[i] = ThisSpectrum[i] - Po[i];
    }

    for (int i = 0; i < numPixel - 1; i++) {
      Re2[i] = Re[i + 1] - Re[i];
    }

    DEV = Math.sqrt(StatUtils.populationVariance(Re2, 0, Re2.length));
    for (int i = 0; i < numPixel; i++) {
      mySUM[i] = Po[i] + DEV;
    }

    int jj = 0; // jj is the length of points to be removed
    for (int i = 0; i < numPixel; i++) {
      if (ThisSpectrum[i] > mySUM[i]) {
        jj++;
        ;
      }
    }
    ind = new int[jj];

    int jjj = 0;
    for (int i = 0; i < numPixel; i++) {
      if (ThisSpectrum[i] > mySUM[i]) {
        ind[jjj] = i;
        jjj++;
      }
    }

    int indKeepLength = numPixel - ind.length;
    int indKeep[] = new int[indKeepLength];
    int k = 0;
    for (int i = 0; i < numPixel; i++) {
      if (!ArrayUtils.contains(ind, i)) {
        indKeep[k] = i;
        k++;
      }
    }
    double ThisSpectrumKeep[] = new double[indKeepLength];
    double ThisXaxisKeep[] = new double[indKeepLength];
    double PoKeep[] = new double[indKeepLength];
    double ReKeep[] = new double[indKeepLength];
    double Re2Keep[] = new double[indKeepLength - 1];
    double mySUMKeep[] = new double[indKeepLength];

    for (int i = 0; i < indKeepLength; i++) {
      ThisSpectrumKeep[i] = ThisSpectrum[indKeep[i]];
      ThisXaxisKeep[i] = ThisXaxis[indKeep[i]];
    }

    prevDEV = DEV;

    // at the point, ThisSpectrum and ThisXaxis should have reduced size
    final WeightedObservedPoints obs1 = new WeightedObservedPoints();

    for (int i = 0; i < indKeepLength; i++) {
      obs1.add(ThisXaxisKeep[i], ThisSpectrumKeep[i]);
    }

    while (true) {
      final PolynomialCurveFitter fitter1 = PolynomialCurveFitter.create(5);
      P = fitter1.fit(obs1.toList());
      Polyval pVal1 = new Polyval(P, ThisXaxisKeep, indKeepLength);
      PoKeep = pVal1.evl();

      for (int i = 0; i < indKeepLength; i++) {
        ReKeep[i] = ThisSpectrumKeep[i] - PoKeep[i];
      }

      for (int i = 0; i < indKeepLength - 1; i++) {
        Re2Keep[i] = ReKeep[i + 1] - ReKeep[i];
      }

      DEV = Math.sqrt(StatUtils.populationVariance(Re2Keep, 0, Re2Keep.length));

      for (int i = 0; i < indKeepLength; i++) {
        mySUMKeep[i] = PoKeep[i] + DEV;
      }

      for (int i = 0; i < indKeepLength; i++) {
        if (ThisSpectrumKeep[i] > mySUMKeep[i]) ThisSpectrumKeep[i] = mySUMKeep[i];
      }
      if ((Math.abs(DEV - prevDEV) / DEV) < threshhold) break;
      prevDEV = DEV;

      obs1.clear();
      for (int i = 0; i < indKeepLength; i++) {
        obs1.add(ThisXaxisKeep[i], ThisSpectrumKeep[i]);
      }
    }
    Polyval pVal2 = new Polyval(P, ThisXaxis, numPixel);
    double FLbk[] = pVal2.evl();
    for (int i = 0; i < ThisXaxis.length; i++) {
      SpecNoBk[i] = ThisSpectrum[i] - FLbk[i];
    }

    // the write-to-file part is only for testing purpose, ThisXaxis and SpecNoBk are two outputs
    try {
      FileWriter fr = new FileWriter(args[1]);
      BufferedWriter br = new BufferedWriter(fr);
      PrintWriter out = new PrintWriter(br);
      DecimalFormat df = new DecimalFormat(pattern);
      for (int j = 0; j < ThisXaxis.length; j++) {
        if (Double.toString(wavelength[j]) != null) out.write(ThisXaxis[j] + "\t" + SpecNoBk[j]);
        out.write("\r\n");
      }
      out.close();
    } catch (IOException e) {
      System.out.println(e);
    }
  }