| Now that we have a framework of classes for drawing functions on 
              our PlotPanel 
              subclasses and for data fitting, we can use it with our histograms. 
              In Chapter 8: Tech: 
              Errors we used the class HistogramStatR1 
              to obtain errors for each bin and we plotted it on an instance of 
              HistErrPanel. 
              As with the DrawPanel 
              from Chapter 6: Tech, 
              the HistErrPanel 
              class loops through a list of DrawFunction 
              instances to draw on top of the histogram. Here we take advantage 
              of that drawing capability.  The applet below derives from the demo program RanDistAnglesApplet.java 
              from Chapter 7: Physics: 
              Custom Distribution except that here we create a distribution 
              that follows a quadratic polynominal shape. In addition, we fit 
              a polynominal to the distribution and draw the line over the data 
              points.  The DrawPoly 
              instance of  
              DrawFunction draws the polynominal using the data 
              obtained with FitPoly.java. 
              Since we may want to do similar fitting in the future, we create 
              the class HistogramFit 
              that holds a static method for fitting data to the binned data of 
              a histogram. 
  
              
                 
                 
                  |  
                      HistFitApplet.java 
                        - Create a random distribution of values 
                        and then fit a polynominal to the bin values.
 + New 
                        classes:HistogramFit.java 
                        - provides a static class that takes a histogram as an 
                        argument and fits the distribution of values to a polynominal 
                        of a given degree.
 
 + Previous classes:
 Ch.8:Physics: 
                        FitPoly.java 
                         DrawPoly.java
 Ch.8:Physics: 
                        Fit.java
 Ch.8:Tech: HistErrPanel.java
 Ch.8:Tech: 
                        HistogramStatR1.java
 Ch.6:Tech: 
                        Histogram.java, 
                        HistPanel.java
 Ch.6:Tech: 
                        DrawFunction.java,DrawLine.java,DrawPoints.java, 
                         DrawPanel.java
 Ch.6:Tech: 
                        PlotPanel.java, 
                        PlotFormat.java
   |   
                  | /** *  Provides a static method for fitting 
                    a polynominal to the
 *  distribution of values in a histogram. 
                    The middle of each
 *  bin is taken as the "x" value and 
                    the bin contents as the
 *  "y" for a fit of y vs. x. If bin 
                    errors are available, they
 *  are used in the fit.
 **/
 public class HistogramFit
 {
 
 /**
 *  Fit the histogram data. 
                    If available, use bin errors from histogram.
 *  Assume no error on horizontal 
                    variable.
 *
 **/
 public static double [] fit (Histogram histogram, 
                    int degree) {
 
 // Get data from histogram.
 int [] bins = histogram.getBins ();
 double lo = histogram.getLo ();
 double hi = histogram.getHi ();
 
 // Need arrays for fit.
 double [] y = new double[bins.length];
 double [] x = new double[bins.length];
 
 double x_del =  (hi-lo)/bins.length;
 double x_start = lo + x_del/2.0;
 
 // Make floating point arrays for 
                    the fit.
 for (int i=0; i < bins.length; i++) 
                    {
 
 // Convert 
                    to FP array for bins
 y[i] = bins[i];
 // Use middle 
                    of bin as the x value.
 x[i] = i * 
                    x_del + x_start;
 }
 
 // Create an array to hold the polynominal 
                    coefficients in
 // bottom half and their error estimates 
                    in top half.
 double [] parameters = new double[2*degree];
 
 //
 if (histogram instanceof HistogramStatR1) 
                    {
 double [] 
                    err = ((HistogramStatR1)histogram).getBinErrors ();
 FitPoly.fit 
                    (parameters, x, y,null,err,bins.length);
 } else{
 FitPoly.fit 
                    (parameters, x,y,null,null,bins.length);
 }
 
 return parameters;
 
 } // fit
 
 } // HistogramFit
 |   
                  | import 
                    javax.swing.*; import java.awt.*;
 import java.awt.event.*;
 
 /**
 *  Create a random distribution of values 
                    and then fit a
 *  polynominal to the bin values.
 *
 *  The applet uses the HistPanel to 
                    display contents of
 *  an instance of Histogram. HistFormat 
                    used by HistPanel to
 *  format the scale values.
 *
 *  This program will run as an applet 
                    inside
 *  an application frame.
 *
 *  Includes "Go" button to add random 
                    values from a Gaussian
 *  distribution to the histogram. The 
                    number of values taken from
 *  entry in a JTextField. "Clear"  button 
                    clears the histogram.
 *  In standalone mode, the Exit button 
                    closes the program.
 *
 **/
 public class HistFitApplet extends JApplet
 implements ActionListener
 {
 // Use the HistPanel JPanel subclass here
 HistErrPanel fOutputPanel;
 
 HistogramStatR1 fHistogram;
 
 DrawFunction [] fDrawFunctions;
 
 double [] fFitParameters;
 
 int fNumDataPoints = 10000;
 
 // Set the angular range for scattered tracks
 double fMinAngle;
 double fMaxAngle;
 
 // Random number generator
 java.util.Random fRan;
 
 // A text field for input strings
 JTextField fTextField;
 
 // Flag for whether the applet is in a browser
 // or running via the main () below.
 boolean fInBrowser = true;
 
 //Buttons
 JButton fGoButton;
 JButton fClearButton;
 JButton fExitButton;
 
 /**
 * Create a User Interface with histograms 
                    and buttons to
 * control the program. A textfield 
                    holds number of entries
 * to be generated for the histogram.
 **/
 public void init ()  {
 
 JPanel panel = new JPanel (new BorderLayout 
                    ());
 
 // Create a histogram with Gaussian 
                    distribution.
 makeHist ();
 
 // Create the Histogram drawing panel 
                    and include
 // drawing objects.
 fDrawFunctions = new DrawFunction[1];
 fDrawFunctions[0] = new DrawPoly ();
 fOutputPanel = new HistErrPanel (fHistogram, 
                    fDrawFunctions);
 fOutputPanel.setDrawType (HistErrPanel.DRAW_PTS_ERRS);
 
 // Fit the line to the histogram.
 fitHist ();
 
 panel.add (fOutputPanel,"Center");
 
 // Use a textfield for an input parameter.
 fTextField =
 new JTextField (Integer.toString 
                    (fNumDataPoints), 10);
 
 // If return hit after entering text, 
                    the
 // actionPerformed will be invoked.
 fTextField.addActionListener (this);
 
 fGoButton = new JButton ("Go");
 fGoButton.addActionListener (this);
 
 fClearButton = new JButton ("Clear");
 fClearButton.addActionListener (this);
 
 fExitButton = new JButton ("Exit");
 fExitButton.addActionListener (this);
 
 JPanel controlPanel = new JPanel ();
 
 controlPanel.add (fTextField);
 controlPanel.add (fGoButton);
 controlPanel.add (fClearButton);
 controlPanel.add (fExitButton);
 
 if (fInBrowser) fExitButton.setEnabled 
                    (false);
 
 panel.add (controlPanel,"South");
 
 // Add text area with scrolling to 
                    the contentPane.
 add (panel);
 
 } // init
 
 /**
 * Respond to the buttons.
 **/
 public void actionPerformed (ActionEvent e) {
 Object source = e.getSource ();
 if (source == fGoButton || source 
                    == fTextField) {
 String strNumDataPoints 
                    = fTextField.getText ();
 try {
 fNumDataPoints 
                    = Integer.parseInt (strNumDataPoints);
 }
 catch (NumberFormatException 
                    ex) {
 // Could open 
                    an error dialog here but just
 // display 
                    a message on the browser status line.
 showStatus 
                    ("Bad input value");
 return;
 }
 makeHist ();
 fitHist ();
 repaint ();
 }
 else if (source == fClearButton) {
 fHistogram.clear 
                    ();
 repaint ();
 }
 else if (!fInBrowser)
 System.exit 
                    (0);
 
 } // actionPeformed
 
 /**
 * Create a random distribution of 
                    angles to
 * simulate the tracks in a particle 
                    scattering
 * experiment entering a detector element.
 **/
 void makeHist () {
 // Create an instance of the Random 
                    class for
 // producing our random values.
 fRan = new java.util.Random ();
 
 // Could modify the program to select 
                    these via the GUI
 fMinAngle = 25.0;
 fMaxAngle = 50.0;
 
 // Create an instance of our basic 
                    histogram class.
 // Make it wide enough enough to include 
                    most of the
 // gaussian values.
 if (fHistogram == null)
 fHistogram 
                    = new HistogramStatR1 ("Scatter Angles into a Detector",
 "Degrees",
 25,fMinAngle,fMaxAngle);
 
 // Use the method to generate a
 // quadratic distribution.
 for (int i=0; i < fNumDataPoints; 
                    i++) {
 // Generate 
                    random vals 0.0 to 1.0
 double r1 
                    = fRan.nextDouble ();
 double angle 
                    = fMinAngle + (fMaxAngle-fMinAngle)*r1;
 if ( acceptAngle 
                    (angle)){
 fHistogram.add 
                    (angle);
 }
 }
 
 // Make the errors from the bin contents
 fHistogram.makeBinErrors ();
 
 } // makeHist
 
 /**
 * This rejection function uses a quadratic
 * function to determine the acceptance 
                    of the
 * angle.
 **/
 boolean acceptAngle (double angle){
 if ( angle < fMinAngle || angle > 
                    fMaxAngle) return false;
 double c = 0.2;
 double slope = 0.020;
 double non_lin_factor = 0.0007;
 
 double limit = c +  (angle 
                    - fMinAngle) * slope -
 (angle - 
                    fMinAngle) *  (angle - fMinAngle) * non_lin_factor;
 double r2 = fRan.nextDouble ();
 if ( r2 <= limit) return true;
 return false;
 
 } // acceptAngle
 
 /**
 * Fit a polynominal to the hist data.
 **/
 void fitHist () {
 
 // Use it to fit the histogram data.
 fFitParameters = HistogramFit.fit 
                    (fHistogram, 3);
 
 // Pass the parameters to the drawing 
                    function object.
 fDrawFunctions[0].setParameters (fFitParameters,null);
 } // fitHist
 
 public static void main (String[] args)
 {
 //
 int frame_width=450;
 int frame_height=300;
 
 //
 HistFitApplet applet = new HistFitApplet 
                    ();
 applet.fInBrowser = false;
 applet.init ();
 
 // Following anonymous class used 
                    to close window & exit program
 JFrame f = new JFrame ("Demo");
 f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
 
 // Add applet to the frame
 f.getContentPane ().add ( applet);
 f.setSize (new Dimension (frame_width,frame_height));
 f.setVisible (true);
 
 } // main
 
 } // HistFitApplet
 
 |    References 
              & Web Resources Last update: Sept. 20, 2005 |