/* * Application: GaussianFit * * USAGE: An application for fitting examination marks to a Gaussian distribution * This application illustrates the class, Regression. * * WRITTEN BY: Dr Michael Thomas Flanagan * * DATE: December 2010 * UPDATE: 1 February 2015 * * DOCUMENTATION: * See Michael Thomas Flanagan's Java library on-line web pages: * http://www.ee.ucl.ac.uk/~mflanaga/java/GaussianFit.html * http://www.ee.ucl.ac.uk/~mflanaga/java/Regression.html * * Copyright (c) 2010 - 2015 * * PERMISSION TO USE: * * Redistributions of this source code, or parts of, must retain the above * copyright notice, this list of conditions and the following disclaimer. * * Public listing of the source codes on the internet is not permitted. * * Redistribution of the source codes or of the flanagan.jar file is not permitted. * * Redistribution in binary form of all or parts of these classes is not permitted. * * Permission to use, copy and modify this software and its documentation for * NON-COMMERCIAL purposes is granted, without fee, provided that an acknowledgement * to the author, Michael Thomas Flanagan at www.ee.ucl.ac.uk/~mflanaga, appears in all * copies and associated documentation or publications. * * Dr Michael Thomas Flanagan makes no representations about the suitability * or fitness of the software for any or for a particular purpose. * Michael Thomas Flanagan shall not be liable for any damages suffered * as a result of using, modifying or distributing this software or its derivatives. * ***************************************************************************************/ import flanagan.math.Fmath; import flanagan.io.Db; import flanagan.io.FileChooser; import flanagan.io.FileOutput; import flanagan.analysis.Regression; import flanagan.analysis.RegressionFunction; import flanagan.analysis.ProbabilityPlot; import flanagan.analysis.Stat; import flanagan.plot.PlotGraph; import flanagan.interpolation.CubicSpline; import javax.swing.JOptionPane; import java.util.*; import java.text.*; public class GaussianFit{ private int numberOfLines = 0; // number of lines in the in the data file private String title = null; // data title private String inputFileName = null; // input file name private String outputFileName = null; // output file name private int outputFileOption = 0; // .txt or .xls file private int numberOfStudents = 0; // number of students registered for the examination private int numberPresent = 0; // number of students present at the examination private int numberAbsent = 0; // number of students absent from the examination private double[] examMarks = null; // examination marks used private double[] examMarksEntered = null; // entered examination marks private double[] marks = null; // the centre of the marks for each histogram bin private double[] frequency = null; // the number of marks in each histogram bin private int nBins = 0; // number of bins in the data histogram private double peakValue = -1; // frequency value for peak bin private double peakPosition = -1; // position of peak bin private double binWidth = 0; // histogram bin width private int nBinPoints = 0; // number of histogram coordinates private double[] binXpoints = null; // histogram x-coordinates private double[] binYpoints = null; // histogram y-coordinates private boolean checkLimits = true; // = false if no check on negative or >100 values required private ArrayList abs = new ArrayList(); // list of indices of and input word for missing marks private int scalingOption = 0; // = 0 no rescaling // = 1 scaling factor // = 2 new mean and standard deviation private double scalingFactor = 1.0; // Scaling factor private double meanCalc = 0.0; // calculated mean of the marks private double standardDeviationCalc = 0.0; // calculated standard deviation of the marks private double momentSkewness = 0.0; // calculated moment skewness; private double medianSkewness = 0.0; // calculated median skewness; private double quartileSkewness = 0.0; // calculated quartile skewness; private double excessKurtosis = 0.0; // calculated excess kurtosis; private double meanScaled = 0.0; // scaled mean of the marks private double standardDeviationScaled = 0.0; // scaled standard deviation of the marks private double momentSkewnessScaled= 0.0; // scaled moment skewness; private double medianSkewnessScaled = 0.0; // scaled median skewness; private double quartileSkewnessScaled = 0.0; // scaled quartile skewness; private double excessKurtosisScaled = 0.0; // scaled excess kurtosis; private boolean scaledCheck = false; // = true if scaling performed private double meanUsed = 0.0; // used mean of the marks private double standardDeviationUsed = 0.0; // used standard deviation of the marks private ProbabilityPlot probPlot = null; // instance of probabilityPlot private double meanProbPlot = 0.0; // best estimate mean from a probability plot private double standardDeviationProbPlot = 0.0; // best estimate standard deviation from a probability plot private Regression reg = null; // instance of Regression private double meanFit = 0.0; // best estimate mean (mu) from non-linear regression private double standardDeviationFit = 0.0; // best estimate standard deviation (sigma) from non-linear regression private double scaleConstantFit = 0.0; // best estimate scale constant (Ao) from non-linear regression private double[] calculatedFrequency = null; // frequency values calculated for best estimates private double[] residuals = null; // residuals private int trunc = 2; // precision (number of decimal places) in the output files private int field = 14; // output file field width // Read in and store the marks private void enterMarks(){ // Choose data file FileChooser fin = new FileChooser(); this.inputFileName = fin.selectFile(); this.numberOfLines = fin.numberOfLines(); ArrayList marksAL = new ArrayList(); double holdD = 0.0; String holdS = null; if(this.numberOfLines==2){ // individual marks on the same line in the data file this.title = fin.readLine(); String line = fin.readLine(); int lineLength = line.length(); int ii = 0; int iStart = -1; int iLast = -1; this.numberOfStudents = 0; boolean test = true; if(line.charAt(ii)==' ' || line.charAt(ii)==',' || line.charAt(ii)==';' || line.charAt(ii)==':' || line.charAt(ii)=='\t' || ii==lineLength-1){ iStart = 0; iLast = 0; } ii++; while(test){ if(line.charAt(ii)==' ' || line.charAt(ii)==',' || line.charAt(ii)==';' || line.charAt(ii)==':' || line.charAt(ii)=='\t' || ii==lineLength-1){ iStart = ii; } if((iStart-iLast)>1){ if(ii==lineLength-1){ holdS = line.substring(iLast+1); } else{ holdS = line.substring(iLast+1,iStart); } try{ holdD = Double.parseDouble(holdS.trim()); marksAL.add(new Double(holdD)); this.numberPresent++; this.numberOfStudents++; } catch(NumberFormatException e){ abs.add(new Integer(this.numberOfStudents)); abs.add(holdS); this.numberAbsent++; this.numberOfStudents++; } iLast = iStart; } ii++; if(ii>=lineLength)test=false; } } else{ // individual marks on separate lines in the data file this.title = fin.readLine(); this.numberOfStudents = numberOfLines - 1; for(int i=0; i100.0)flag2++; } if(flag1>0)flag3 = 1; if(flag2>0)flag3 = 2; if(flag1>0 && flag2>0)flag3 = 3; String question = null; if(flag3>0 && this.checkLimits){ if(flag0==0){ switch(flag3){ case 1: question = "You have entered data in which there are negative values\n\n"; break; case 2: question = "You have entered data in which there are values greater than 100.0\n\n"; break; case 3: question = "You have entered data in which there are both negative values\n"; question += "and values greater than 100.0\n\n"; break; } } else{ switch(flag3){ case 1: question = "You have introduced negative values on rescaling\n\n"; break; case 2: question = "You have introduced values greater than 100.0 on rescaling\n\n"; break; case 3: question = "You have introduced both negative values\n"; question += "and values greater than 100.0 on rescaling\n\n"; break; } } question += "Do you wish to set all negative values to zero\n"; question += "and all values greater than 100.0 to 100.0\n\n"; boolean answer = Db.yesNo(question); if(answer){ for(int i=0; i100.0)this.examMarks[i] = 100.0; } } else{ this.checkLimits = false; } } return flag3; } // Calculate statistics private void statistics(int flag){ Stat st = new Stat(this.examMarks); if(flag==1){ // unscaled data this.meanCalc = st.mean(); this.meanUsed = this.meanCalc; this.standardDeviationCalc = st.standardDeviation(); this.standardDeviationUsed = this.standardDeviationCalc; this.momentSkewness = st.momentSkewness(); this.medianSkewness = st.medianSkewness(); this.quartileSkewness = st.quartileSkewness(); this.excessKurtosis = st.excessKurtosis(); } else{ // scaled data this.meanScaled = st.mean(); this.meanUsed = this.meanScaled; this.standardDeviationScaled = st.standardDeviation(); this.standardDeviationUsed = this.standardDeviationScaled; this.momentSkewnessScaled = st.momentSkewness(); this.medianSkewnessScaled = st.medianSkewness(); this.quartileSkewnessScaled = st.quartileSkewness(); this.excessKurtosisScaled = st.excessKurtosis(); } } // Offer scaling option private void scale(){ String question = "The mean of the marks is " + Fmath.truncate(this.meanCalc, this.trunc) + "\n"; question += "The standard deviation of the marks is " + Fmath.truncate(this.standardDeviationCalc, trunc) + "\n\n"; question += "Do you want to rescale the examination marks?\n\n"; boolean answer = Db.noYes(question); if(answer){ String headerComment = "You may rescale by"; String[] comments1 = {"a multiplicative scaling factor\n", "an additive or subtractive scaling factor\n", "entering a new mean and standard deviation\n"}; String[] boxTitles1 = {"multiplicative factor", "additive or subtractive factor", "new mean and sd"}; int defaultBox1 = 1; this.scalingOption = Db.optionBox(headerComment, comments1, boxTitles1, defaultBox1); String message = null; switch(this.scalingOption){ case 1: // Multiplicative scaling factor message = "Enter the multiplicative scaling factor"; this.scalingFactor = Db.readDouble(message, 1.0); for(int i=0; i=binStart[i] && this.examMarks[j] |t|"); double muError = this.probPlot.gaussianMuError(); fout.printtab("mu", this.field); fout.printtab(Fmath.truncate(this.meanProbPlot, this.trunc), this.field); fout.printtab(Fmath.truncate(muError, this.trunc), this.field); fout.printtab(Fmath.truncate(Math.abs(100.0*muError/this.meanProbPlot), this.trunc), this.field); double tVal = this.meanProbPlot/muError; fout.printtab(Fmath.truncate(tVal, this.trunc), this.field); double pVal = 1.0 - Stat.studentTcdf(-tVal, tVal, this.nBins-2); fout.println(Fmath.truncate(pVal, this.trunc)); double sigmaError = this.probPlot.gaussianSigmaError(); fout.printtab("sigma", this.field); fout.printtab(Fmath.truncate(this.standardDeviationProbPlot, this.trunc), this.field); fout.printtab(Fmath.truncate(sigmaError, this.trunc), this.field); fout.printtab(Fmath.truncate(Math.abs(100.0*sigmaError/this.standardDeviationProbPlot), this.trunc), this.field); tVal = this.standardDeviationProbPlot/sigmaError; fout.printtab(Fmath.truncate(tVal, this.trunc), this.field); pVal = 1.0 - Stat.studentTcdf(-tVal, tVal, this.nBins-2); fout.println(Fmath.truncate(pVal, this.trunc)); fout.println(); fout.printtab("Ordered data", this.field); fout.printtab("Gaussian order", this.field); fout.printtab("Residuals", this.field); fout.printtab("Ordered data", this.field); fout.printtab("Gaussian order", this.field); fout.printtab("Residuals", this.field); fout.printtab("Ordered data", this.field); fout.printtab("Gaussian order", this.field); fout.println("Residuals"); fout.printtab("values", this.field); fout.printtab("statistic", this.field); fout.printtab(" ", this.field); fout.printtab("values", this.field); fout.printtab("statistic", this.field); fout.printtab(" ", this.field); fout.printtab("values", this.field); fout.printtab("statistic", this.field); fout.println(); fout.printtab(" ", this.field); fout.printtab("medians", this.field); fout.printtab(" ", this.field); fout.printtab(" ", this.field); fout.printtab("medians", this.field); fout.printtab(" ", this.field); fout.printtab(" ", this.field); fout.printtab("medians", this.field); fout.println(); double[] odv = this.probPlot.gaussianOrderStatisticMedians(); double[] oda = this.probPlot.orderedData(); int ii = 0; for(int i=0; i |t|"); fout.printtab("mu", this.field); fout.printtab(Fmath.truncate(this.meanFit, this.trunc), this.field); fout.printtab(Fmath.truncate(errors[0], this.trunc), this.field); fout.printtab(Fmath.truncate(Math.abs(100.0*errors[0]/this.meanFit), this.trunc), this.field); fout.printtab(Fmath.truncate(tValF[0], this.trunc), this.field); fout.println(Fmath.truncate(pValF[0], this.trunc)); fout.printtab("sigma", this.field); fout.printtab(Fmath.truncate(this.standardDeviationFit, this.trunc), this.field); fout.printtab(Fmath.truncate(errors[1], this.trunc), this.field); fout.printtab(Fmath.truncate(Math.abs(100.0*errors[1]/this.standardDeviationFit), this.trunc), this.field); fout.printtab(Fmath.truncate(tValF[1], this.trunc), this.field); fout.println(Fmath.truncate(pValF[1], this.trunc)); fout.printtab("Ao", this.field); fout.printtab(Fmath.truncate(this.scaleConstantFit, this.trunc), this.field); fout.printtab(Fmath.truncate(errors[2], this.trunc), this.field); fout.printtab(Fmath.truncate(Math.abs(100.0*errors[2]/this.scaleConstantFit), this.trunc), this.field); fout.printtab(Fmath.truncate(tValF[2], this.trunc), this.field); fout.println(Fmath.truncate(pValF[2], this.trunc)); fout.println(); fout.println("Binned marks"); fout.println("Bin width: " + this.binWidth); fout.printtab("Bin", this.field); fout.printtab("Experimental", this.field); fout.printtab("Calculated", this.field); fout.println("Residuals"); fout.printtab("centre", this.field); fout.printtab("frequency", this.field); fout.println("frequency"); for(int i=0; i