// // This applet is based on code which was kindly provided by Matt Roughan // It uses Matt's PlotCanvas class which extends Canvas // Last updated 06/08/98 // import java.util.*; import java.applet.*; import java.awt.*; import MyUtil.*; public class PlotDistribution extends Applet { Panel cardStack = null; CardLayout c1 = null; DistributionCard currentCard; int N = 15; DistributionCard[] theCards = new DistributionCard[N]; Button[] SelectionButtons = new Button[N]; String[] DistributionNames = {"Normal", "Beta", "Gamma", "Erlang", "Exponential", "Chi-squared", "Student-t", "Laplace", "Pareto", "Cauchy", "Anon", "Weibull","Lognormal", "Inverse-Gaussian","Uniform"}; String startCard; MyDialog helpDialog; static Frame theFrame; //this array of strings is what is displayed by the help button String[] helpText = { "This applet is designed to plot the distribution function F(x)", "and the associated probability density function f(x) for several", "of the standard continuous distributions.", "", "The various parameters are controlled using the scrollbars", "and the scale of the plot can be enlarged using + (plus) or", "reduced using - (minus). Pressing h brings up this message.", "" }; public void init(){ // BorderLayout new_BorderLayout = new BorderLayout(0,8); BorderLayout new_BorderLayout = new BorderLayout(0,0); setLayout(new_BorderLayout); cardStack = new Panel(); c1 = new CardLayout(); cardStack.setBackground(Color.white); cardStack.setLayout(c1); add("Center", cardStack); //create the cards for plotting each distribution theCards[0] = new GaussianCard(); cardStack.add(DistributionNames[0], theCards[0]); theCards[1] = new BetaCard(); cardStack.add(DistributionNames[1], theCards[1]); theCards[2] = new GammaCard(); cardStack.add(DistributionNames[2], theCards[2]); theCards[3] = new ErlangCard(); cardStack.add(DistributionNames[3], theCards[3]); theCards[4] = new ExponentialCard(); cardStack.add(DistributionNames[4], theCards[4]); theCards[5] = new ChiSquaredCard(); cardStack.add(DistributionNames[5], theCards[5]); theCards[6] = new StudentTCard(); cardStack.add(DistributionNames[6], theCards[6]); theCards[7] = new LaplaceCard(); cardStack.add(DistributionNames[7], theCards[7]); theCards[8] = new ParetoCard(); cardStack.add(DistributionNames[8], theCards[8]); theCards[9] = new CauchyCard(); cardStack.add(DistributionNames[9], theCards[9]); theCards[10] = new AnonCard(); cardStack.add(DistributionNames[10], theCards[10]); theCards[11] = new WeibullCard(); cardStack.add(DistributionNames[11], theCards[11]); theCards[12] = new LognormalCard(); cardStack.add(DistributionNames[12], theCards[12]); theCards[13] = new InverseGaussianCard(); cardStack.add(DistributionNames[13], theCards[13]); theCards[14] = new UniformCard(); cardStack.add(DistributionNames[14], theCards[14]); //put selection buttons on the bottom of the page Panel SelectionBar = new Panel(); SelectionBar.setBackground(Color.white); GridLayout new_GridLayout = new GridLayout(5,4, 3,3); SelectionBar.setLayout(new_GridLayout); SelectionBar.add(new Label()); SelectionBar.add(new Label()); SelectionBar.add(new Label()); SelectionBar.add(new Label()); for (int i=0; i= low) & (par_value <= high)) { ParameterValues[i] = par_value; // ParameterLabels[i].setText(ParameterStrings[i]+" = "+ParameterDefaults[i]); ParameterLabels[i].setText(ParameterStrings[i]+" = "+ParameterValues[i]); recalculate(); } else { System.out.println("Error: Parameter outside acceptible range!"); } } //define a method for resizing the graph public void scale(boolean enlarge) { double scaleFactor; if (enlarge) { theScale--; if (theScale < 0) { theScale = 0; scaleFactor = 1.0; } else scaleFactor = scales[theScale]/scales[theScale+1]; } else { theScale++; if (theScale >= scales.length) { theScale = scales.length-1; scaleFactor = 1.0; } else scaleFactor = scales[theScale]/scales[theScale-1]; } //rescale the axes for (int i=0; i1) return (x-1)*Gamma(x-1); if (x==1 | x==0) return 1.0; } else if (2*x == Math.round(2*x)) { if (x>0.5) return (x-1)*Gamma(x-1); if (x==0.5) return Math.sqrt(Math.PI); } return 0.0; } //define the function which recalculates the values of the density //and distribution - it calls the three abstract functions void recalculate() { normalisationFactor = normalisation(); F[0] = startingValue(); for (int i=0; i0) F[i] = F[i-1] + BinSize*p[i-1]; } } // define a function which finds the first value of the distribution // function over the range specified abstract double startingValue(); // define an abstract method for calculating the Normalisation factor // of the distribution. This is really just a computational // convenience, to prevent the same calculations being made on every // call to density(x) abstract double normalisation(); // define an abstract method for calculating the probability density, // any calculation which are repeated in this function should go in // the normalisationFactor abstract double density(double x); }//end DistributionCard // // define some real instances of the abstract class above // // define a Gaussian distribution card class GaussianCard extends DistributionCard { static String[] parameterNames = {"mu","sigma^2"}; static double[] parameterDefaults = {0.0, 1.0}; static double[][] parameterRanges = {{-10.0,10.0,0.2},{0.2, 10.0,0.2}}; static double[] r = {-10.0, 10.0}; static double[] d = {0.0, 1.0}; GaussianCard() { super("Normal (or Gaussian)", "f(x) = ( 2 Pi sigma^2 )^( -1/2 ) exp( - ( 1/2 ) ( ( x - mu ) / sigma )^2 )", parameterNames, parameterDefaults, parameterRanges, r, d, 0.1); } double startingValue() { double value = 0.0; double SVBinSize = BinSize; double SVNoofBins = x.length; for (int j=1; j<=SVNoofBins; j++) { value += SVBinSize*density(range[0] - SVBinSize*j); } return value; } double normalisation() { double variance = ParameterValues[1]; return Math.sqrt(2*Math.PI*variance); } double density(double x) { double mean = ParameterValues[0]; double variance = ParameterValues[1]; return Math.exp( -(x-mean)*(x-mean)/(2*variance) )/normalisationFactor; } } //define a beta distribution card class BetaCard extends DistributionCard { static String[] parameterNames = {"mu","nu"}; static double[] parameterDefaults = {1.5, 1.5}; static double[][] parameterRanges = {{0.5,20.0,0.5},{0.5,20.0,0.5}}; static double[] r = {0.0, 1.0}; static double[] d = {0.0, 10.0}; BetaCard() { super("Beta", "f(x)= Gam(mu+nu)/(Gam(mu) Gam(nu)) x^(mu-1) (1-x)^(nu-1)", parameterNames, parameterDefaults, parameterRanges, r, d, 0.01); } double startingValue() { return 0.0; } double normalisation() { double mu = ParameterValues[0]; double nu = ParameterValues[1]; return Gamma(mu)*Gamma(nu)/Gamma(mu+nu); } double density(double x) { double mu = ParameterValues[0]; double nu = ParameterValues[1]; if (x>0) { return Math.pow(x, mu-1)*Math.pow((1-x), nu-1)/ normalisationFactor; } else if (x==0) { double ee = BinSize/2.0; return Math.pow(ee, mu-1)*Math.pow((1-ee), nu-1)/ normalisationFactor; } else return 0.0; } } //define gamma distribution card class GammaCard extends DistributionCard { static String[] parameterNames = {"alpha","lambda"}; static double[] parameterDefaults = {1.0, 1.0}; static double[][] parameterRanges = {{0.5,5.0,0.5},{0.1,10.0,0.1}}; static double[] r = {0.0, 10.0}; static double[] d = {0.0, 2.0}; GammaCard() { super("Gamma", "f(x) = lambda exp( - lambda x) (lambda x)^(alpha - 1) / Gam(alpha)", parameterNames, parameterDefaults, parameterRanges, r, d, 0.01); } double startingValue() { return 0.0; } double normalisation() { double alpha = ParameterValues[0]; double beta = ParameterValues[1]; return Gamma(alpha)/Math.pow(beta, alpha); } double density(double x) { double alpha = ParameterValues[0]; double beta = ParameterValues[1]; if (x>0) { return Math.pow(x, alpha-1)*Math.exp(-beta*x)/normalisationFactor; } else if (x==0) { double ee = BinSize/2.0; return Math.pow(ee, alpha-1)*Math.exp(-beta*ee)/normalisationFactor; } else return 0.0; } //override the method for calculating the distribution function to //use a more accurate integral void recalculate() { normalisationFactor = normalisation(); F[0] = startingValue(); for (int i=0; i0) F[i] = F[i-1] + BinSize*(p[i-1] + p[i])/2.0; } } } //define Erlang distribution card class ErlangCard extends DistributionCard { static String[] parameterNames = {"n","lambda"}; static double[] parameterDefaults = {1.0, 1.0}; static double[][] parameterRanges = {{1.0,80.0,1.0},{0.5,10.0,0.5}}; static double[] r = {0.0, 10.0}; static double[] d = {0.0, 1.0}; ErlangCard() { super("Erlang", "f(x) = lambda exp( - lambda x) (lambda x)^(alpha - 1) / Gam(alpha)", parameterNames, parameterDefaults, parameterRanges, r, d, 0.01); } double startingValue() { return 0.0; } double normalisation() { double alpha = ParameterValues[0]; double beta = ParameterValues[1]; return Gamma(alpha)/Math.pow(beta, alpha); } double density(double x) { double alpha = ParameterValues[0]; double beta = ParameterValues[1]; return Math.pow(x, alpha-1)*Math.exp(-beta*x)/normalisationFactor; } //override the method for calculating the distribution function to //use a more accurate integral void recalculate() { normalisationFactor = normalisation(); F[0] = startingValue(); for (int i=0; i0) F[i] = F[i-1] + BinSize*(p[i-1] + p[i])/2.0; } } } //define exponential distribution card class ExponentialCard extends DistributionCard { static String[] parameterNames = {"lambda"}; static double[] parameterDefaults = {2.0}; static double[][] parameterRanges = {{0.2, 10.0, 0.2}}; static double[] r = {0.0, 2.0}; static double[] d = {0.0, 5.0}; ExponentialCard() { super("(Negative) Exponential", "f(x) = lambda exp( -lambda x)", parameterNames, parameterDefaults, parameterRanges, r, d, 0.01); } double startingValue() { return 0.0; } double normalisation() { return 1.0; } double density(double x) { double lambda = ParameterValues[0]; return lambda*Math.exp(-lambda*x); } double distribution(double x) { double lambda = ParameterValues[0]; return (1 - Math.exp(-lambda*x)); } //override this function to use an analytic expresion for F void recalculate() { normalisationFactor = normalisation(); F[0] = startingValue(); for (int i=0; i0) return Math.pow(x,(nu-2)/2.0)*Math.exp(-x/2.0)/normalisationFactor; else if (x==0) { double ee = BinSize/2.0; return Math.pow(ee,(nu-2)/2.0)*Math.exp(-ee/2.0)/normalisationFactor; } else return 0.0; } } //define Student-t distribution card class StudentTCard extends DistributionCard { static String[] parameterNames = {"n (d.f.)"}; static double[] parameterDefaults = {1.0}; static double[][] parameterRanges = {{1.0,60.0,1.0}}; static double[] r = {-10.0, 10.0}; static double[] d = {0.0, 1.0}; StudentTCard() { super("Student-t", "f(x) = (1+x^2)^(-(n+1)/2) (n Pi)^(-1/2) Gam((n+1)/2) / Gamma(n/2) ", parameterNames, parameterDefaults, parameterRanges, r, d, 0.1); } double startingValue() { double value = 0.0; double SVBinSize = BinSize/2.0; double SVNoofBins = 5*x.length; for (int j=1; j<=SVNoofBins; j++) { value += SVBinSize*density(range[0] - SVBinSize*j); } return value; } double normalisation() { double nu = ParameterValues[0]; return Gamma(nu/2.0)*Math.sqrt(nu*Math.PI)/Gamma((nu+1)/2.0); } double density(double x) { double nu = ParameterValues[0]; return Math.pow(1 + x*x/nu, -(nu+1)/2.0 )/normalisationFactor; } } //define Laplace distribution card class LaplaceCard extends DistributionCard { static String[] parameterNames = {"mu","a"}; static double[] parameterDefaults = {0.0, 1.0}; static double[][] parameterRanges = {{-10.0,10.0,1.0},{0.5,10.0,0.5}}; static double[] r = {-10.0, 10.0}; static double[] d = {0.0, 1.0}; LaplaceCard() { super("Laplace (or Double Exponential)", "f(x) = 2 a exp( - | x - mu | / a )", parameterNames, parameterDefaults, parameterRanges, r, d, 0.1); } double startingValue() { double value = 0.0; double SVBinSize = BinSize; double SVNoofBins = 2*x.length; for (int j=1; j<=SVNoofBins; j++) { value += SVBinSize*density(range[0] - SVBinSize*j); } return value; } double normalisation() { return 2*ParameterValues[1]; } double density(double x) { double mean = ParameterValues[0]; double scale = ParameterValues[1]; return Math.exp(-Math.abs(x - mean)/scale)/normalisationFactor; } } class ParetoCard extends DistributionCard { static String[] parameterNames = {"a","c"}; static double[] parameterDefaults = {1.0, 2.0}; static double[][] parameterRanges = {{0.1,10.0,0.1},{0.1, 10.0,0.1}}; static double[] r = {0.0, 10.0}; static double[] d = {0.0, 5.0}; ParetoCard() { super("Pareto", "f(x) = c a^c / x^( c + 1 ), x > a ( and 0 otherwise )", parameterNames, parameterDefaults, parameterRanges, r, d, 0.01); } double startingValue() { double a = ParameterValues[0]; double c = ParameterValues[1]; if (r[0]>=a) return 1 - Math.pow(a/r[0],c); else return 0; } double normalisation() { double a = ParameterValues[0]; double c = ParameterValues[1]; return 1.0/(c*Math.pow(a,c)); } double density(double x) { double a = ParameterValues[0]; double c = ParameterValues[1]; if (x>=a) return 1/ (Math.pow(x,c+1)*normalisationFactor); else return 0; } double distribution(double x) { double a = ParameterValues[0]; double c = ParameterValues[1]; if (x>=a) return 1 - Math.pow(a/x,c); else return 0; } //override this function to use an analytic expresion for F void recalculate() { normalisationFactor = normalisation(); F[0] = startingValue(); for (int i=0; ie1) { double lx2 = Math.pow(Math.log(x)-mu,2); return Math.exp( -lx2/(2.0*vv) )/(x*Math.sqrt(2.0*Math.PI*vv)); } else { double lx2 = Math.pow(Math.log(e1)-mu,2); return Math.exp( -lx2/(2.0*vv) )/(e1*Math.sqrt(2.0*Math.PI*vv)); } } } // define an Inverse Gaussian distribution card class InverseGaussianCard extends DistributionCard { static String[] parameterNames = {"mu","a"}; static double[] parameterDefaults = {1.0, 1.0}; static double[][] parameterRanges = {{0.1,9.0,0.1},{0.1,20.0,0.1}}; static double[] r = {0.005, 5.0}; static double[] d = {0.0, 2.0}; static double e1 = 1.0E-10; InverseGaussianCard() { super("Inverse Gaussian", "f(x) = ( a / ( 2 Pi x^3 ) )^( 1/2 ) exp( - a ( x - mu )^2 / ( 2 mu^2 x ) )", parameterNames, parameterDefaults, parameterRanges, r, d, 0.005); } double startingValue() { return 0.005; } double normalisation() { return 1.0; } double density(double x) { double mu = ParameterValues[0]; double a = ParameterValues[1]; if (x>e1) { return Math.sqrt(a/(2.0*Math.PI*Math.pow(x,3)))*Math.exp(-a*Math.pow(x-mu,2)/(2.0*Math.pow(mu,2)*x)); } else { return 0.0; } } } // define a Uniform distribution card class UniformCard extends DistributionCard { static String[] parameterNames = {"a","d"}; static double[] parameterDefaults = {0.0, 1.0}; static double[][] parameterRanges = {{-4.8,4.8,0.2},{0.2,9.8,0.2}}; static double[] r = {-5.0, 5.0}; static double[] d = {0.0, 2.0}; UniformCard() { super("Uniform", "f(x) = 1 / d for a < x < a + d ( and 0 otherwise )", parameterNames, parameterDefaults, parameterRanges, r, d, 0.01); } double startingValue() { return r[0]; } double normalisation() { double d = ParameterValues[1]; return Math.sqrt(d); } double density(double x) { double a = ParameterValues[0]; double d = ParameterValues[1]; if ((x(a+d))) return 0; else return 1/normalisationFactor; } double distribution(double x) { double a = ParameterValues[0]; double d = ParameterValues[1]; if (x(a+d)) return 1; else return ((x-a)/d); } //override this function to use an analytic expresion for F void recalculate() { normalisationFactor = normalisation(); F[0] = startingValue(); for (int i=0; i