Java source code of 'jhplot.F1D'

/**
 *    Copyright (C)  DataMelt project. The jHPLot package by S.Chekanov and Work.ORG
 *    All rights reserved.
 *
 *    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 3 of the License, or 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, see .
 *
 *    Additional permission under GNU GPL version 3 section 7:
 *    If you have received this program as a library with written permission from the DataMelt team,
 *    you can link or combine this library with your non-GPL project to convey the resulting work.
 *    In this case, this library should be considered as released under the terms of
 *    GNU Lesser public license (see ),
 *    provided you include this license notice and a URL through which recipients can access the
 *    Corresponding Source.
 **/
package jhplot;

import jplot.LinePars;
import hep.aida.*;
import jhplot.gui.HelpBrowser;
import jhplot.math.exp4j.*;

/**
 * Create a function in one dimension using "x" as a variable. The function name
 * could have parameters named in unique way as P0, P1, P2. In this case, the
 * function should not be parsed. Parameters have to be replaced with values
 * using setPar(x) method for evaluation.
 * 

* One can enabled fast math calculation using @see jhplot.HParam. * For example, setting jhplot.HParam.setMath(true) makes calculation of elementary functions * a factot 4-5 faster than using the standard Java Math, with precision of E-14. *

* The function may have one independent variable: x *

* Operators and functions

* the following operators are supported: *

    *
  • Addition: '2 + 2'
  • *
  • Subtraction: '2 - 2'
  • *
  • Multiplication: '2 * 2'
  • *
  • Division: '2 / 2'
  • *
  • Exponential: '2 ^ 2' or ** (raise to a power)
  • *
  • Unary Minus,Plus (Sign Operators): '+2 - (-2)'
  • *
  • Modulo: '2 % 2'
  • *
* the following functions are supported: *
    *
  • abs: absolute value
  • *
  • acos: arc cosine
  • *
  • asin: arc sine
  • *
  • atan: arc tangent
  • *
  • cbrt: cubic root
  • *
  • ceil: nearest upper integer
  • *
  • cos: cosine
  • *
  • cosh: hyperbolic cosine
  • *
  • exp: euler's number raised to the power (e^x)
  • *
  • floor: nearest lower integer
  • *
  • log: logarithm natural (base e)
  • *
  • log10: logarithm (base 10)
  • *
  • sin: sine
  • *
  • sinh: hyperbolic sine
  • *
  • sqrt: square root
  • *
  • tan: tangent
  • *
  • tanh: hyperbolic tangent
  • *
* It also recognizes the pi (or Pi) values. * * * @author S.Chekanov * */ public class F1D extends DrawOptions { /** * */ private static final long serialVersionUID = 1L; private double[] x = null; private double[] y = null; private Expression calc = null; private ExpressionBuilder function = null; private String lastException = ""; final int maxpoints = 500; private FProxy proxy; /** * Create a function in 1D. 500 points are used between Min and Max for * evaluation. The title is set to the function's definition. *

* A function can be ranged (range min and max is included) or unranged (min * and max are not defined). Ranged function determines the plot ranges, * integration range etc. * * The function may have one independent variable: x. Example: x*x * * Operators and functions *

* the following operators are supported: *

    *
  • Addition: '2 + 2'
  • *
  • Subtraction: '2 - 2'
  • *
  • Multiplication: '2 * 2'
  • *
  • Division: '2 / 2'
  • *
  • Exponential: '2 ^ 2' or ** (raise to a power)
  • *
  • Unary Minus,Plus (Sign Operators): '+2 - (-2)'
  • *
  • Modulo: '2 % 2'
  • *
* the following functions are supported: *
    *
  • abs: absolute value
  • *
  • acos: arc cosine
  • *
  • asin: arc sine
  • *
  • atan: arc tangent
  • *
  • cbrt: cubic root
  • *
  • ceil: nearest upper integer
  • *
  • cos: cosine
  • *
  • cosh: hyperbolic cosine
  • *
  • exp: euler's number raised to the power (e^x)
  • *
  • floor: nearest lower integer
  • *
  • log: logarithm natural (base e)
  • *
  • sin: sine
  • *
  • sinh: hyperbolic sine
  • *
  • sqrt: square root
  • *
  • tan: tangent
  • *
  • tanh: hyperbolic tangent
  • *
* It also recognizes the pi (or Pi) values; * * * @param name * String representing the function's definition */ public F1D(String name) { this(name, name, 0, 0, true); } /** * Initialize function from proxy. * * @param f */ public F1D(FProxy f) { if (f.getType() != 1) { jhplot.utils.Util.ErrorMessage("Error in parsing F1D. Wrong type! " + f.getName()); return; } proxy = f; setTitle(proxy.getTitle()); lpp.setType(LinePars.F1D); } /** * Create new function. The function is unranged (nor range is defined). * * @param title * title * @param name * definition */ public F1D(String title, String name) { this(title, name, 0, 0, true); } /** * Create a new function. Do not parse it when using parameters. You should * apply substitution first and create a function with one variable "x". If * min=0 and max=0, the ranges are determined by plotting canvases. The * function is ranged. The function is parsed. * * The function may have one independent variable: x *

* Operators and functions *

* the following operators are supported: *

    *
  • Addition: '2 + 2'
  • *
  • Subtraction: '2 - 2'
  • *
  • Multiplication: '2 * 2'
  • *
  • Division: '2 / 2'
  • *
  • Exponential: '2 ^ 2' or ** (raise to a power)
  • *
  • Unary Minus,Plus (Sign Operators): '+2 - (-2)'
  • *
  • Modulo: '2 % 2'
  • *
* the following functions are supported: *
    *
  • abs: absolute value
  • *
  • acos: arc cosine
  • *
  • asin: arc sine
  • *
  • atan: arc tangent
  • *
  • cbrt: cubic root
  • *
  • ceil: nearest upper integer
  • *
  • cos: cosine
  • *
  • cosh: hyperbolic cosine
  • *
  • exp: euler's number raised to the power (e^x)
  • *
  • floor: nearest lower integer
  • *
  • log: logarithm natural (base e)
  • *
  • log10: logarithm 10 natural(base e)
  • *
  • sin: sine
  • *
  • sinh: hyperbolic sine
  • *
  • sqrt: square root
  • *
  • tan: tangent
  • *
  • tanh: hyperbolic tangent
  • *
* It also recognizes the pi (or Pi) values. * * @param title * title * @param name * definition * @param min * minimum value for plotting * @param max * maximum value for plotting */ public F1D(String title, String name, double min, double max) { this(title, name, min, max, true); } /** * Define a ranged function. * * @param name * name * @param min * min value * @param max * max value * @param parsed * is parsed? */ public F1D(String name, double min, double max, boolean parsed) { this(name, name, min, max, parsed); } /** * Create F1D function from JAIDA IFunction. By default 500 points are used. * The function is ranged. * * @param title * Title * @param iname * input IFunction * @param min * Min X values * @param max * Max X values */ public F1D(String title, IFunction iname, double min, double max) { proxy = new FProxy(1, title, iname.title(), iname, new double[] { min, max, 0, 0, 0, 0 }, maxpoints, false); setTitle(title); lpp.setType(LinePars.F1D); } /** * Get the proxy of this function used for serialization and non-graphical * representations. * * @param proxy * proxy of this function. */ public FProxy get() { return proxy; } /** * Create a new function. Do not parse it when using parameters. You should * apply substitution first and create a function with one variable "x". If * min=0 and max=0, the ranges are determined by plotting canvases. The * function is ranged. * * The function may have one independent variable: x *

* Operators and functions *

* the following operators are supported: *

    *
  • Addition: '2 + 2'
  • *
  • Subtraction: '2 - 2'
  • *
  • Multiplication: '2 * 2'
  • *
  • Division: '2 / 2'
  • *
  • Exponential: '2 ^ 2' or ** (raise to a power)
  • *
  • Unary Minus,Plus (Sign Operators): '+2 - (-2)'
  • *
  • Modulo: '2 % 2'
  • *
* the following functions are supported: *
    *
  • abs: absolute value
  • *
  • acos: arc cosine
  • *
  • asin: arc sine
  • *
  • atan: arc tangent
  • *
  • cbrt: cubic root
  • *
  • ceil: nearest upper integer
  • *
  • cos: cosine
  • *
  • cosh: hyperbolic cosine
  • *
  • exp: euler's number raised to the power (e^x)
  • *
  • floor: nearest lower integer
  • *
  • log: logarithm natural (base e)
  • *
  • log10: logarithm 10 natural(base e)
  • *
  • sin: sine
  • *
  • sinh: hyperbolic sine
  • *
  • sqrt: square root
  • *
  • tan: tangent
  • *
  • tanh: hyperbolic tangent
  • *
* It also recognizes the pi (or Pi) values. * * * @param title * title * @param name * definition * @param min * minimum value for plotting * @param max * maximum value for plotting * @param parse * parse or not. Do not parse when using parameters. */ public F1D(String title, String name, double min, double max, boolean parse) { proxy = new FProxy(1, title, name, null, new double[] { min, max, 0, 0, 0, 0 }, maxpoints, parse); setTitle(title); lpp.setType(LinePars.F1D); function = new ExpressionBuilder(proxy.getName()); if (parse == true) { try { function.variables("x"); calc = function.build(); } catch (IllegalArgumentException e) { proxy.setParsed(false); jhplot.utils.Util.ErrorMessage("Failed to parse function " + name + " Error:" + e.toString()); } } } /** * Create a F1D function from JAIDA IFunction in ranges. By default, 500 * points for evaluation are used * * @param iname * input IFunction * @param min * Min value * @param max * Max value */ public F1D(IFunction iname, double min, double max) { proxy = new FProxy(1, iname.title(), iname.title(), iname, new double[] { min, max }, maxpoints, false); setTitle(iname.title()); lpp.setType(LinePars.F1D); } /** * Create a new function in pre-defined range for plotting. Do not parse it * when using parameters. You should apply substitution first and create a * function with one variable "x". If min=0 and max=0, ranges are determined * by plotting canvaces. * * The function may have one independent variable: x *

* Operators and functions *

* the following operators are supported: *

    *
  • Addition: '2 + 2'
  • *
  • Subtraction: '2 - 2'
  • *
  • Multiplication: '2 * 2'
  • *
  • Division: '2 / 2'
  • *
  • Exponential: '2 ^ 2' or ** (raise to a power)
  • *
  • Unary Minus,Plus (Sign Operators): '+2 - (-2)'
  • *
  • Modulo: '2 % 2'
  • *
* the following functions are supported: *
    *
  • abs: absolute value
  • *
  • acos: arc cosine
  • *
  • asin: arc sine
  • *
  • atan: arc tangent
  • *
  • cbrt: cubic root
  • *
  • ceil: nearest upper integer
  • *
  • cos: cosine
  • *
  • cosh: hyperbolic cosine
  • *
  • exp: euler's number raised to the power (e^x)
  • *
  • floor: nearest lower integer
  • *
  • log: logarithm natural (base e)
  • *
  • log10: logarithm 10 natural(base e)
  • *
  • sin: sine
  • *
  • sinh: hyperbolic sine
  • *
  • sqrt: square root
  • *
  • tan: tangent
  • *
  • tanh: hyperbolic tangent
  • *
* It also recognizes the pi (or Pi) values. * * * @param name * definition * @param min * min value for plotting * @param max * max value for plotting * @param parse * parse or not. Do not parse when using parameters. */ public F1D(String name, double min, double max) { this(name, name, min, max, true); } /** * Create a new function in pre-defined range for plotting. Do not parse it * when using parameters. You should apply substitution first and create a * function with one variable "x". Ranges for the function are not defined. * * The function may have one independent variable: x *

* Operators and functions *

* the following operators are supported: *

    *
  • Addition: '2 + 2'
  • *
  • Subtraction: '2 - 2'
  • *
  • Multiplication: '2 * 2'
  • *
  • Division: '2 / 2'
  • *
  • Exponential: '2 ^ 2' or ** (raise to a power)
  • *
  • Unary Minus,Plus (Sign Operators): '+2 - (-2)'
  • *
  • Modulo: '2 % 2'
  • *
* the following functions are supported: *
    *
  • abs: absolute value
  • *
  • acos: arc cosine
  • *
  • asin: arc sine
  • *
  • atan: arc tangent
  • *
  • cbrt: cubic root
  • *
  • ceil: nearest upper integer
  • *
  • cos: cosine
  • *
  • cosh: hyperbolic cosine
  • *
  • exp: euler's number raised to the power (e^x)
  • *
  • floor: nearest lower integer
  • *
  • log: logarithm natural (base e)
  • *
  • log10: logarithm 10 natural(base e)
  • *
  • sin: sine
  • *
  • sinh: hyperbolic sine
  • *
  • sqrt: square root
  • *
  • tan: tangent
  • *
  • tanh: hyperbolic tangent
  • *
* It also recognizes the pi (or Pi) values. * * @param title * title * * @param name * definition * * @param parse * parse or not. Do not parse when using parameters. */ public F1D(String title, String name, boolean parsed) { this(title, name, 0, 0, parsed); } /** * Create a polynomial analytical function using a list of values. Example: * pars[0]+pars[1]*x+pars[2]*x*x +pars[3]*x*x*x * * @param title * Title of this function * @param pars * array of coefficients for polynomial function * @param parse * set true if it should be parsed */ public F1D(String title, double[] pars, boolean parse) { if (pars == null || pars.length < 1) System.err.println("Failed to evaluate this polynomial"); String name = Double.toString(pars[0]); proxy = new FProxy(1, title, name, null, new double[] { 0, 0, 0, 0, 0, 0 }, maxpoints, parse); for (int i = 1; i < pars.length; i++) { String sig = "+"; if (pars[i] < 0) sig = "-"; double val = Math.abs(pars[i]); String X = "*x"; for (int j = 1; j < i; j++) X = X + "*x"; name = name + sig + Double.toString(val) + X; } setTitle(title); lpp.setType(LinePars.F1D); function = new ExpressionBuilder(name); if (parse == true) { try { calc = (function.variables("x")).build(); } catch (IllegalArgumentException e) { proxy.setParsed(false); // System.err.println("Failed to parse function " + // this.name+" Error:"+e1.toString()); jhplot.utils.Util.ErrorMessage("Failed to parse function " + name + " Error:" + e.toString()); } } } /** * Build a function. The function may have one independent variable: x. * Function can have parameters, in which case set parsing to false. You can * parse this function later after substitution of numeric parameter. *

* Operators and functions *

* the following operators are supported: *

    *
  • Addition: '2 + 2'
  • *
  • Subtraction: '2 - 2'
  • *
  • Multiplication: '2 * 2'
  • *
  • Division: '2 / 2'
  • *
  • Exponential: '2 ^ 2' or ** (raise to a power)
  • *
  • Unary Minus,Plus (Sign Operators): '+2 - (-2)'
  • *
  • Modulo: '2 % 2'
  • *
* the following functions are supported: *
    *
  • abs: absolute value
  • *
  • acos: arc cosine
  • *
  • asin: arc sine
  • *
  • atan: arc tangent
  • *
  • cbrt: cubic root
  • *
  • ceil: nearest upper integer
  • *
  • cos: cosine
  • *
  • cosh: hyperbolic cosine
  • *
  • exp: euler's number raised to the power (e^x)
  • *
  • floor: nearest lower integer
  • *
  • log: logarithm natural (base e)
  • *
  • sin: sine
  • *
  • sinh: hyperbolic sine
  • *
  • sqrt: square root
  • *
  • tan: tangent
  • *
  • tanh: hyperbolic tangent
  • *
* * @param name * name * @param parse * is parsed or not? */ public F1D(String name, boolean parse) { this(name, name, 999, 999, parse); } /** * Parse the function. * To speed up calculation of repertitive tasks, you can parse the function first. * @return true if parsed without problems. **/ public boolean parse() { try { function = new ExpressionBuilder(proxy.getName()); function.variables("x"); calc = function.build(); proxy.setParsed(true); } catch (IllegalArgumentException e) { proxy.setParsed(false); // System.err.println("Failed to parse function " + // this.name+" Error:"+e.toString()); jhplot.utils.Util.ErrorMessage("Failed to parse function " + proxy.getName() + " Error:" + e.toString()); return false; } return true; } /** * Create a function in 1D. 500 points are used between Min and Max for * evaluation. * * The function may have x as independent variable. * * * @param title * Title * @param function * ExpressionBuilder * @param min * Min value * @param max * Max value */ public F1D(String title, ExpressionBuilder function) { proxy = new FProxy(1, title, null, null, new double[] { 0, 0, 0, 0, 0, 0 }, maxpoints, false); this.function = function; lpp.setType(LinePars.F1D); boolean isParsed = parse(); if (isParsed == false) jhplot.utils.Util.ErrorMessage("Failed to parse function " + title); } /** * Create a function from the expression. The function is in the range. * * @param calc * expression * @param min * Min value * @param max * Max value */ public F1D(Expression calc, double min, double max) { this("F1D",calc,min,max); } /** * Create a function in 1D. 500 points are used between Min and Max for * evaluation. The function may have x as independent variable. * * * @param title * Title * @param function * Expression after parsing and building */ public F1D(String title, Expression calc, double min, double max) { proxy = new FProxy(1, title, title, null, new double[] { min, max, 0, 0, 0, 0 }, maxpoints, true); this.calc = calc; setTitle(title); lpp.setType(LinePars.F1D); } /** * Create a function in 1D. 500 points are used between Min and Max for * evaluation. The function may have x as independent variable. * * * @param title * Title * @param function * Expression after parsing and building */ public F1D(String title, Expression calc) { this(title,calc,0,0); } /** * Create a function in 1D. The function may have x as independent variable. * * @param function * expression */ public F1D(Expression calc) { this("F1D", calc,0,0); } /** * Build a function. * * @param function * input of expression */ public F1D(ExpressionBuilder function) { this("F1D", function); } /** * Evaluate a function at a specific point in x * * @param x * value in x for evaluation * @return function value at x */ public double eval(double x) { double y = 0; IFunction iname = proxy.getIFunction(); // jPlot function first if (iname == null && (calc == null || proxy.isParsed() == false)) { jhplot.utils.Util .ErrorMessage("eval(): Function was not parsed correctly!"); return y; } // evaluate function if (iname == null && calc != null && proxy.isParsed() == true) { try { calc.setVariable("x", x); y = calc.evaluate(); } catch (Exception e) { lastException = e.getMessage().toString(); String ss1 = Double.toString(x); System.err.println("Failed to evaluate function:" + proxy.getName() + " at x=" + ss1 + "\n" + e.toString()); } return y; } // end of the standard jPlot function // start AIDA function if (iname != null && iname.dimension() == 1) { try { double[] xx = new double[iname.dimension()]; xx[0] = x; y = iname.value(xx); } catch (Exception e) { // System.out.println("Failed to evaluate function!"); lastException = e.getMessage().toString(); String ss1 = Double.toString(x); System.err.println("Failed to evaluate function:" + proxy.getName() + " at x=" + ss1 + "\n" + e.toString()); } return y; } // end IFunction return y; } /** * Evaluate a function for an array of x-values * * @param x * array of values in x for evaluation * @return array of function values */ public double[] eval(double[] x) { double[] y = new double[x.length]; IFunction iname = proxy.getIFunction(); // jPlot function first if (iname == null && (calc == null || proxy.isParsed() == false)) { jhplot.utils.Util .ErrorMessage("eval(): Function was not parsed correctly!"); return y; } // evaluate function if (iname == null && calc != null && proxy.isParsed() == true) { for (int i = 0; i < x.length; i++) { try { calc.setVariable("x", x[i]); y[i] = calc.evaluate(); } catch (Exception e) { String ss = Integer.toString(i); lastException = e.getMessage().toString() + " at position=" + ss; jhplot.utils.Util .ErrorMessage("eval(): Failed to evaluate:" + proxy.getName() + " at position=" + ss); return null; } } return y; } // end of the standard jPlot function // start AIDA function if (iname != null) { for (int i = 0; i < x.length; i++) { try { double[] xx = new double[iname.dimension()]; xx[0] = x[i]; y[i] = iname.value(xx); } catch (Exception e) { String ss = Integer.toString(i); lastException = e.getMessage().toString() + " at position=" + ss; jhplot.utils.Util.ErrorMessage("Failed to evaluate:" + proxy.getName() + " at position=" + ss); } } return y; } // end IFunction return y; } /** * Evaluate a function for graphic representation. Number of points for * evaluations is 500. * * @param XMin * value in x * @param XMax * value in x */ public void eval(double xMin, double xMax) { eval(xMin, xMax, maxpoints); } /** * Evaluate a function for graphic representation. The function is assumed * to me ranged (the range is defined during the initialization). * */ public void eval() { double d[] = proxy.getLimits(); eval(d[0], d[1], maxpoints); } /** * Evaluate a function for graphic representation. Number of points for * evaluations is 500. * * @param Min * value in x * @param Max * value in x * @param Number * of evaluation points */ public void eval(double min, double max, int Npoints) { int points = Npoints; IFunction iname = proxy.getIFunction(); boolean isParsed = proxy.isParsed(); if (iname == null && (calc == null || isParsed == false)) { jhplot.utils.Util .ErrorMessage("eval(): Function was not parsed correctly! Not parsed?"); return; } if (iname == null && isParsed == true) { x = new double[points]; y = new double[points]; double d = (max - min) / (points - 1); for (int i = 0; i < points; i++) { x[i] = min + i * d; try { calc.setVariable("x", x[i]); y[i] = calc.evaluate(); // System.out.println(x[i]); // System.out.println(y[i]); } catch (Exception e) { String ss = Double.toString(x[i]); System.err.println("Failed to evaluate:" + proxy.getName() + " at position=" + ss); return; } } } // end of the standard jPlot function // start AIDA function if (iname != null) { x = new double[points]; y = new double[points]; double d = (max - min) / (points - 1); for (int i = 0; i < points; i++) { x[i] = min + i * d; double[] xx = new double[iname.dimension()]; try { xx[0] = x[i]; y[i] = iname.value(xx); } catch (Exception e) { String ss = Double.toString(x[i]); System.err.println("Failed to evaluate at x=" + ss); return; } } } // end IFunction } /** * Show online documentation. */ public void doc() { String a = this.getClass().getName(); a = a.replace(".", "/") + ".html"; new HelpBrowser(HelpBrowser.JHPLOT_HTTP + a); } /** * Create a F1D function from JAIDA IFunction. By default, 500 points for * evaluation are used. No ranges are set. * * @param iname * input IFunction */ public F1D(IFunction iname) { proxy = new FProxy(1, iname.title(), null, iname, new double[] { 0, 0, 0, 0, 0, 0 }, maxpoints, true); setTitle(iname.title()); lpp.setType(LinePars.F1D); } /** * Create F1D function from JAIDA IFunction. By default 500 points are used * * @param title * Title * @param iname * input IFunction * @param min * Min X values * @param max * Max X values */ public F1D(String title, IFunction iname) { proxy = new FProxy(1, title, null, iname, new double[] { 0, 0, 0, 0, 0, 0 }, maxpoints, true); setTitle(title); lpp.setType(LinePars.F1D); } /** * Print the F1D function to a Table in a separate Frame. The numbers are * formatted to scientific format. One can sort and search the data in this * table (data cannot be modified) * * @param min * @param max */ public void toTable() { new HTable(this); } /** * Replace abstract parameter with the value (double). Case sensitive! * * @param parameter * parameter name * @param value * value to be inserted */ public void setPar(String parameter, double value) { String s1 = Double.toString(value); String name = proxy.getName(); proxy.setName(name.replaceAll(parameter, s1)); } /** * Return H1D histogram from F1D function. The number of points are given by * setPoints() method, but the default 500 is used if not given. Min and Max * values are given during the function initialisation (ranged function) The * number of points is 500 by default. * * @return histogram */ public H1D getH1D() { double[] d = proxy.getLimits(); return getH1D(d[0], d[1]); } /** * Return H1D histogram from F1D function. The number of points are given by * setPoints() method, but the default 500 is used if not given. Min and Max * values are given by the values used to parse the function. * * @param min * value * @param max * value * * @return histogram */ public H1D getH1D(double min, double max) { int bins = getPoints(); eval(min, max, bins); H1D h = new H1D(getTitle(), bins, min, max); int ibins = bins + 2; double[] newHeights = new double[ibins]; double[] newErrors = new double[ibins]; double[] newMeans = new double[ibins]; double[] newRmss = new double[ibins]; int[] newEntries = new int[ibins]; newHeights[0] = 0; newHeights[ibins - 1] = 0; for (int i = 0; i < ibins - 2; i++) { newHeights[i + 1] = y[i]; newErrors[i + 1] = 0; newEntries[i + 1] = (int) y[i]; newMeans[i + 1] = y[i]; newRmss[i + 1] = 0; } h.setContents(newHeights, newErrors, newEntries, newMeans, newRmss); h.setMeanAndRms(0, 0); /* * for (int i = 0; i < bins; i++) { h.fill(x[i]+0.5*d, y[i] ); } */ return h; } /** * Return a Histogram given by the F1D function. All statistical * characteristics of such histogram are meaningless. Bins and Min and Max * values are user defined. The function is evaluated at the bin center * which is important for small number of bins. * * @param hname * Name of the histogram * @param bins * number of bins for histogram * @param hmin * min value of histogram * @param hmax * max value of histogram * @return H1D histogram */ public H1D getH1D(String hname, int bins, double hmin, double hmax) { double d = (hmax - hmin) / (double) bins; double[] xx = new double[bins]; for (int i = 0; i < bins; i++) { xx[i] = hmin + i * d + 0.5 * d; } double[] yy = eval(xx); H1D h = new H1D(hname, bins, hmin, hmax); int ibins = bins + 2; double[] newHeights = new double[ibins]; double[] newErrors = new double[ibins]; double[] newMeans = new double[ibins]; double[] newRmss = new double[ibins]; int[] newEntries = new int[ibins]; newHeights[0] = 0; newHeights[ibins - 1] = 0; for (int i = 0; i < ibins - 2; i++) { newHeights[i + 1] = yy[i]; newErrors[i + 1] = 0; newEntries[i + 1] = (int) yy[i]; newMeans[i + 1] = yy[i]; newRmss[i + 1] = 0; } h.setContents(newHeights, newErrors, newEntries, newMeans, newRmss); h.setMeanAndRms(0, 0); return h; } /** * Replace abstract parameter with the value (integer). Case sensitive. You * will need to call parse() to finish this function. * * @param parameter * parameter name * @param value * integer value to be inserted. */ public void setPar(String parameter, int value) { String s1 = Integer.toString(value); String name = proxy.getName(); proxy.setName(name.replaceAll(parameter, s1)); } /** * Get value in X-axis * * @param i * index * * @return value in X */ public double getX(int i) { return this.x[i]; } /** * Get value in Y-axis * * @param i * index * * @return value in Y */ public double getY(int i) { return this.y[i]; } /** * Sets a name of the function, i.e. what will be used for evaluation * * @param name * Name */ public void setName(String name) { proxy.setName(name); } /** * Get the name of the function used for evaluation * * @return Name */ public String getName() { return proxy.getName(); } /** * Return parsed function. One can evaluate Y as: y =function.getResult(x), * where function is what returned by this method. * * @return function **/ public Expression getParse() { return calc; } /** * Sets the number points between Min and Max for evaluation * * @param bins * Number of points */ public void setPoints(int bins) { proxy.setPoints(bins); } /** * Integral using fastest trapezium rule method. This function return * non-zero if it the range was defined during the initialization. The * default number of points is 500. Increase it if needed more pecision. * * @return integral in the range defined during the initisliazation. * */ public double integral() { int points = proxy.getPoints(); double[] d = proxy.getLimits(); return integral("trapezium", points, d[0], d[1]); } /** * Integral using fastest trapezium rule method. It uses the default number * of points (500). * * @param min * the first ordinate. * @param max * the last ordinate. */ public double integral(double min, double max) { int points = proxy.getPoints(); return integral("trapezium", points, min, max); } /** * Numerical integration. Define types as:
* type="gauss4" - Gaussian integration formula (4 points)
* type="gauss8" - Gaussian integration formula (8 points)
* type="richardson" - Richardson extrapolation
* type="simpson" - using Simpson's rule.
* type="trapezium" - trapezium rule.
* * @param type * type of algorithm. Can be: * "gauss4","gauss8","richardson","simpson","trapezium". * @param N * the number of strips to use for integration * @param min * the first ordinate. * @param max * the last ordinate. * @return integral */ public double integral(String type, final int N, double min, final double max) { if (type == "gauss4") { return jhplot.math.Numeric.gaussian4(N, this, min, max); } else if (type == "gauss8") { return jhplot.math.Numeric.gaussian8(N, this, min, max); } else if (type == "richardson") { return jhplot.math.Numeric.richardson(N, this, min, max); } else if (type == "simpson") { return jhplot.math.Numeric.simpson(N, this, min, max); } else if (type == "trapezium") { return jhplot.math.Numeric.trapezium(N, this, min, max); } else { return jhplot.math.Numeric.gaussian4(N, this, min, max); } } /** * Numerical integration using trapezium rule. * * @param N * the number of strips to use for integration * @param min * the first ordinate. * @param max * the last ordinate. * @return integral */ public double integral(final int N, double min, final double max) { return jhplot.math.Numeric.trapezium(N, this, min, max); } /** * Get Jaida function * * @return */ public IFunction getIFunction() { return proxy.getIFunction(); } /** * Get array of X-values after function after evaluation using the default * number of points * * @return X-values */ public double[] getArrayX() { return x; } /** * Get array of Y-values after function after evaluation using the default * number of points * * @return Y-values */ public double[] getArrayY() { return y; } /** * If the function is parsed correctly, return true. Use this check before * drawing it. * * @return true if parsed. */ public boolean isParsed() { return proxy.isParsed(); } /** * Convert the function into MathML form. * * @return String representing this function in MathML. */ public String toMathML() { try { return jscl.math.Expression.valueOf(proxy.getName()).toMathML(); } catch (Exception e) { lastException = e.getMessage().toString(); return ""; } } /** * Convert the function into Java code. * * @return String representing this function in Java. */ public String toJava() { try { return jscl.math.Expression.valueOf(proxy.getName()).toJava(); } catch (Exception e) { lastException = e.getMessage().toString(); return ""; } } /** * Try to simplify this function. It is often useful to rewrite an * expression in term of elementary functions (log, exp, frac, sqrt, * implicit roots), using the "elementary()" before simplifying it. Retrieve * the simplified name as a string using getName() method. * * @return false if error occurs. Retrieve this error as a string using * getException(). */ public boolean simplify() { String name = proxy.getName(); try { name = jscl.math.Expression.valueOf(name).simplify().toString(); proxy.setName(name); } catch (Exception e) { lastException = e.getMessage().toString(); return false; } return true; } /** * Convert this function rewrite in term of elementary functions (log, exp, * frac, sqrt, implicit roots) This is useful before simplifying function. * Retrieve the simplified name as a string using getName() method. * * @return false if error occurs. Retrieve this error as a string using * getException(). */ public boolean elementary() { String name = proxy.getName(); try { name = jscl.math.Expression.valueOf(name).elementary().toString(); proxy.setName(name); } catch (Exception e) { lastException = e.getMessage().toString(); return false; } return true; } /** * Convert this function rewrite in expanded form. Retrieve the expanded * name as a string using getName() method. * * @return false if error occurs. Retrieve this error as a string using * getException(). */ public boolean expand() { String name = proxy.getName(); try { name = jscl.math.Expression.valueOf(name).expand().toString(); proxy.setName(name); } catch (Exception e) { lastException = e.getMessage().toString(); return false; } return true; } /** * Convert this function rewrite in factorized form (if can). Retrieve the * expanded name as a string using getName() method. * * @return false if error occurs. Retrieve this error as a string using * getException(). */ public boolean factorize() { String name = proxy.getName(); try { name = jscl.math.Expression.valueOf(name).factorize().toString(); proxy.setName(name); } catch (Exception e) { lastException = e.getMessage().toString(); return false; } return true; } /** * Perform some numeric substitutions. Examples: exp(1) should be * 2.71828182, "pi" should be 3.14159 etc. Retrieve the expanded name as a * string using getName() method. * * @return false if error occurs. Retrieve this error as a string using * getException(). */ public boolean numeric() { String name = proxy.getName(); try { name = jscl.math.Expression.valueOf(name).numeric().toString(); proxy.setName(name); } catch (Exception e) { lastException = e.getMessage().toString(); return false; } return true; } /** * Numerical differentiation. * * @param N * the number of points to use. * @param min * the first ordinate. * @param max * the last ordinate. * @return array with differentials */ public double[] differentiate(final int N, final double min, final double max) { return jhplot.math.Numeric.differentiate(N, this, min, max); } /** * Numerical differentiation of a function. Range of the function is given * during the initisalisation (ranged function) * * @return array with differentials */ public double[] differentiate() { int points = proxy.getPoints(); double[] d = proxy.getLimits(); return jhplot.math.Numeric.differentiate(points, this, d[0], d[1]); } /** * Get the number of points used for plotting, integration and * differentiation. * * @return Number of points */ public int getPoints() { return proxy.getPoints(); } /** * If error occurs at some step, this is the way to retrieve it. * * @return last exception happened in any method of this class. */ public String getException() { return lastException; } /** * Set Min value in X * * @param min * Minimum value */ public void setMin(double min) { proxy.setLimit(0, min); } /** * Get the minimum value in X * * @return min Minimum value */ public double getMin() { double[] d = proxy.getLimits(); if (d != null) return d[0]; return 0; } /** * Set the maximum value in X * * @param max * Maximal value */ public void setMax(double max) { proxy.setLimit(1, max); } /** * Set proxy function * * @param f */ public void set(FProxy f) { proxy = f; } /** * Get the maximum value in X * * @return Maximal value */ public double getMax() { double[] d = proxy.getLimits(); if (d != null) return d[1]; return 0; } /** * Get this function as a string. * * @return Convert to string. */ public String toString() { String tmp = "F1D:" + proxy.getName(); tmp = tmp + " (title=" + proxy.getTitle() + ", n=" + Integer.toString(proxy.getPoints()) + ", " + Boolean.toString(proxy.isParsed()) + ")"; return tmp; } }