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
|