Home : Map : Chapter 9 : Java : Tech : Physics :
Experiment Simulation with Analysis Module
JavaTech
Course Map
Chapter 9

Introduction
Overview
Streams
Wrappers,Buffers
Console I/O
  Text Output 
     Demo 1

  Formatter/printf()
     Demo 2

  Tex 2t Input
     Demo 3

  Scanner
     
Demo 4
File Class
  File I/O
  File Output-Text
     Demo 5

  Formatter to File
     Demo 6

  File Input - Text
    Demo 7

  Scanner - Files
     Demo 8

  File I/O - Binary
     Demo 9
   Demo 10
File Chooser Dialog
  Demo 11

Character Codes
  Demo 12
   Demo13
Object I/O
Types to Bytes
Stream Filters
Other I/O Topics
Exercises

     About JavaTech
     Codes List
     Exercises
     Feedback
     References
     Resources
     Tips
     Topic Index
     Course Guide
     What's New

In our first demonstration program of this chapter, the "analysis" consisted of a histogram of the acceleration values and the code for this lay inside the applet class. Similarly, for the experiment demonstration, which included a simulated detector, the analysis consisted merely of calculating the acceleration from the detector "measurements" and displaying the values in a histogram. As before, the analysis code remained in the applet.

In our simple falling mass demonstration program, we separate the analysis code into its own class. The program uses many of the same classes as in the previous experiment simulation but we put the analysis into a class called DropAnalysis. It includes all of the calculation code and displays the results in its own panel.

Note: In Chapter 10: Phyiscs: Generation & Analysis of Simulated Data , we continue from this example by separating the data generation from the analysis. Simulated data is written to a file by the generator for each run. The data is read by the analysis programs. In a real world experiment, the same analysis program would run on the real data files, which should have the same format as the simulated data.

We create the DropAnalysis object in the applet and display its panel on the applet's planel. However, DropAnalysis could easily go into its own application program and operate on data files rather than getting the data directly from the simulator as done here in the applet. These options are left as exercises.

The applet differs from the previous demo by measuring the positions of the mass at fixed intervals in time from the start of the drop rather than measuring the times at fixed positions. This simulates the common undergraduate lab experiments that use a spark chart setup. The ball drops and a high voltage applied every DT time interval causes a spark to the ball that leaves a mark on a strip of paper. For a each time period after the drop starts, the plot averages the position measurements over N runs. The error bars come from the standard deviation to these distributions. A fit to a polynominal

   y = c + b*T + a*T2

determines the gravitational acceleration using g= a*2.0.


DropTestAnalysisApplet - simulate a experiment in which a dropped ball leaves marks every DT interval, as in a spark chart experiment. Include fitting of data points to represent the analysis of the experiment. The code is modularized with several other classes listed here:

+ New classes:
DropAnalyzer.java - analyzes data from a single run and from a set of runs. Plots averaged measured position vs. time during the drop and fits to a quadratic to determing the acceleration constant. Includes its on panel for its plot and output. So could be included in another program, such as one to analyzed actual experiment data.

DropDetector2.java - an implementation of Detector. This class simulates a detector that measures the position of the dropped mass every DT time interval. This could represent, for example, the common spark chart type of detector used in introductory physics experiments. The class also will draw the detector on the instance of DropPanelDetect.

+ Previous classes:
Ch. 9: Physics:
DropPanelDetect.java, DropModelDetect.java, Detector.java

Ch. 8: Physics:
Fit.java, FitPoly.java, DrawPoly.java
Ch. 6: Tech: DrawPanel.java, DrawPoints.java, DrawFunction.java
Ch. 6: Tech: PlotPanel.java, PlotFormat.java

 

The path of the dropping ball is now marked by circles indicating the position of the ball after each DT step. This is similar to the marks on the paper in a spark chart setup.

Examine the diagram in figure 9.5 to see the process followed by the program.


Figure Phy.9.5: Similar sequence as in Figure Phy.9.3 but with the DropAnalyzer class added. For each step in the simulation of the fall by DropModelDetect, the DropDetector2 object is called and it records the position for each DT increment.. The detector also paints itself on the animation frame. When the drop finishes, the DropAnalyzer object gets the drop data arrays (times and positions along the drop). At the end of the set of drops (i.e. the "run"), the analyser calculates the average position for each DT time step and plots Y vs Time. A fit to this plot with a polynominal gives a measure of the gravitational acceleration constant.

Note that the DrawPanel uses instances of DrawPoints and DrawPoly classes to make the plot.

This set of classes provides a highly modular approach to the simulation and analysis that allows for great flexibility. For example, you can add additional capabilities to each class, such as drag effects to the drop model or additional plots in the analysis class, without affecting the other parts.

DropTestAnalysisApplet

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

/**
  * This program simulates an experiment in which measurements
  * are made during the fall of a mass in a constant gravitational
  * field that will be used to determine the acceleration constant.
  * It illustrates the basic components involved with a simulation
  * of any physics experiment.
  *
  * The applet uses DropPanelDetect to display the experiment setup
  * and the falling mass. The DropDetector object draws the detector
  * on this panel.
  *
  * Data for each drop is passed to an instance of DropAnalyzer,
  * which saves the data. At the end of the run  (a set of drops),
  * the analyzer plots Yaverage vs. Time and fits the points to
  * a polynominal c + bT + cT^2. From the c coefficient the gravitational
  * value can be determined.
  *
  * The java.util.Timer and java.util.TimerTask are used
  * to update the animation of the drop.
  *
  * Includes "Drop" button to initiate the dropping.
  *
  *
  * The number of drops and a speed factor taken from 2 text fields.
  * "Reset"  button clears the histogram.
  * In standalone mode, the Exit button closes the program.
  *
  *
  * This program will run as an applet inside
  * an application frame.
  *
 **/
public class DropTestAnalysisApplet extends JApplet
             implements ActionListener
{
  // The DropPanel displays the animation of the
  // falling mass.
  DropPanelDetect fDropPanel;

  // The DropModel generates the physics data.
  DropModelDetect fDropModel;

  // The DropAnalyzer examines the data.
  DropAnalyzer fDropAnalyzer;

  // Use a detector to measure the drop times.
  Detector fDetector;

  // Use the java.util Timer and TimerTask combo
  // for timing events.
  java.util.Timer fTimer;

  // A text field for getting number of drops per
  // run and the position smearing std.dev. in cm.
  JTextField fMaxNumDropsField;
  JTextField fPosSigmaFactorField;

  // Flag for whether the applet is in a browser
  // or running via the main () below.
  boolean fInBrowser = true;

  //Buttons
  JButton fGoButton;   // start drop
  JButton fClearButton;// resets histogram
  JButton fExitButton;

   // Starting coordinates of drop
  double fXBallStart =  25.0; // cm
  double fYBallStart = 200.0; // cm
  double fYBallEnd   =   0.0; // cm

  // Range of the drop time.
  double fTStart = 0.00; // sec
  double fTEnd   = 0.75; // sec

  // SD in the measured values for the marker positions and t (sec).
  //  (Allow for smearing of marker position for further experimentation.)
  double [] fMeasurementSigmas = {  2.0, 0.0};

  // Integer and double arrays to pass info to the detector
  int []    fDetectorSetup;
  double [] fDetectorParameters;

  // Coordinate of ball.
  double fXBall;
  double fYBall;

  // Initial velocity.
  double fVyBallStart = 0.0;
  double fVxBallStart = 0.0;

  // Time in millisecs for the drop
  double fTDropTotal;
  double fTFrame = 0.020; // in secs

  // Speed up or slow down factor for animation:
  double fTFactor = 1.0;

  // Allow for multiple drops per "run"
  int fMaxNumDrops = 10;
  int fNumDrops = 0;

  // Number of times to measure the position during the drop.
  int fMaxNumMeasurements = 40;

  /**
    *  Initialize the display. Create Detector and Model
    *  objects to use for the physics and experiment simulation.
    *  DropPanelDetect displays the dropping ball and the
    *  detector. Add a analysis panel to display the data.
   **/
  public void init () {

    // Create a detector
    fDetector = new DropDetector2 ();

    // Need arrays to pass setup info to the detector.
    fDetectorSetup = new int[1];
    fDetectorSetup[0] = fMaxNumMeasurements;

    // Do a measurement for every frame
    fDetectorParameters = new double[1];
    fDetectorParameters[0] = fTFrame;

    // Pass the detector the necesary setup info
    fDetector.init (fDetectorSetup, fDetectorParameters, fMeasurementSigmas);

    // Create the drop physics model
    fDropModel = new DropModelDetect (fDetector);
    fDropModel.reset (fYBallStart, fVyBallStart);

    // Create the analyzer
    fDropAnalyzer = new DropAnalyzer (fYBallEnd, fYBallStart,
                                      fTStart, fTEnd);

    JPanel panel = new JPanel (new BorderLayout ());

    // Use a textfield to get the number of drops per run.
    fMaxNumDropsField =
      new JTextField (Integer.toString (fMaxNumDrops), 10);

    // Use a textfield to get smearing  (std.dev. in cm) of the position.
    fPosSigmaFactorField =
      new JTextField (Double.toString (fMeasurementSigmas[0]), 10);

    // If return hit after entering text, the
    // actionPerformed will be invoked.
    fMaxNumDropsField.addActionListener (this);
    fPosSigmaFactorField.addActionListener (this);

    fGoButton = new JButton ("Drop");
    fGoButton.addActionListener (this);

    // Here the clear button will reset the plots
    fClearButton = new JButton ("Reset");
    fClearButton.addActionListener (this);

    fExitButton = new JButton ("Exit");
    fExitButton.addActionListener (this);

    JPanel control_panel = new JPanel (new GridLayout (1,2));
    JPanel panel1 = new JPanel (new GridLayout (1,2));
    JPanel panel2 = new JPanel (new GridLayout (1,3));

    panel1.add (fMaxNumDropsField);
    panel1.add (fPosSigmaFactorField);

    panel2.add (fGoButton);
    panel2.add (fClearButton);
    panel2.add (fExitButton);

    control_panel.add (panel1);
    control_panel.add (panel2);

    // Create an instance of the DropPanel
    // Make the panel 10% taller than starting position.
    fDropPanel = new DropPanelDetect (fYBallStart*1.1, 0.0, fDetector);

    // Get the DrawPanel from the analyzer
    JPanel analyzePanel = fDropAnalyzer.getPanel ();

    JPanel holder_panel = new JPanel (new GridLayout (1,2));
    holder_panel.add (fDropPanel);
    holder_panel.add (analyzePanel);

    panel.add (holder_panel,"Center");
    panel.add (control_panel,"South");

    // Add text area with scrolling to the content pane.
    add (panel);

  } // init

  /** Stop the timer if the browser page unloaded. */
  public void stop () {
    runDone ();
  } // stop

  /**
    *  Respond to the buttons. For a click on "Drop" button,
    *  execute the number of drops in the text field.
    *  Also, obtain the smearing factor for the y measurements
    *  from the other text field. The Reset button will clear the
    *  plots and reset the drop stats.
   **/
  public void actionPerformed (ActionEvent e) {
    Object source = e.getSource ();
    if (source == fGoButton) {
      if (fGoButton.getText ().equals ("Drop")) {
        try {
          fMaxNumDrops =
            Integer.parseInt (fMaxNumDropsField.getText ());

          // Get new sigma for position smearing
          fMeasurementSigmas[0] =
            Double.parseDouble (fPosSigmaFactorField.getText ());

          // Update the position smearing
          fDetector.init (fDetectorSetup, fDetectorParameters,
                        fMeasurementSigmas);
        }
        catch (NumberFormatException ex) {
          // Could open an error dialog here but just
          // display a message on the browser status line.
          if ( fInBrowser)
              showStatus ("Bad input value");
          else
              System.out.println ("Bad input value");
          return;
        }
        dropReset ();
        fGoButton.setText ("Stop");
        fClearButton.setEnabled (false);

      } else {
          // Stop without finishing the current drop.
          runDone ();
      }
    } else if (source == fClearButton) {
        fDropAnalyzer.reset ();
        repaint ();
    } else if (!fInBrowser)
        System.exit (0);
  } // actionPerformed


  /**
    * Use the inner class technique to define the
    * TimerTask subclass for stepping through the
    * drop calculation and the frame refresh.
    * Use the real time in the drop calculation instead
    * of the given frame rate times in case there were
    * delays from thread interruptions, the processing
    * in the parts of the program take extra time, etc.
   **/
  class PaintHistTask extends java.util.TimerTask {
    public void run () {
      // Drop the ball
      fYBall = fDropModel.step (fTFactor * fTFrame);

      // Update the position of the ball in the
      // animation and redraw the frame.
      fDropPanel.updatePosition (fXBall, fYBall);

      // Check if ball has crossed the finish line.
      if ( fYBall <= fYBallEnd) dropDone ();
    } // run
  } // PaintHistTask

  /**
    *  Before each set of drops, need to create a new timer,
    *  and set up its schedule. The PaintHistTask innner class
    *  object will do the setup for each frame of a drop animation.
   **/
  void dropReset () {
    // Before starting the drop, create the timer task
    // that will cause the histogram display to update
    // during the filling.
    // Create a timer. TimerTask created in MakeHist ()
    fTimer = new java.util.Timer ();

    fDropModel.reset (fYBallStart, fVyBallStart);
    fDropPanel.reset (fXBallStart, fYBallStart);

    // Reset time sum
    fTDropTotal = 0.0;
    fNumDrops = 0;
    fYBall = fYBallStart;
    fXBall = fXBallStart;

    // Tell the analyzer how many drops will be made and how many
    // measurements per drop.
    fDropAnalyzer.initRun (fMaxNumDrops, fMaxNumMeasurements);

    // Reset the detector.
    fDetector.reset ();

    repaint ();

    // Start the timer after 20ms and then repeat calls
    // to run in PaintHistTask object by the rate set by
    // the fTFrame value.
    fTimer.schedule (new PaintHistTask (), 20, (int) (fTFrame*1000));

  } // dropReset

  /**
    *  Invoked after a drop ends bottom. Reset
    *  all the parameters to set up for another drop.
   **/
  public void dropDone () {
    // Get the data  (times and positions during the drop)
    // from the detector and analyze it
    double data[][] = fDetector.getResults ();
    int numMeasures = fDetector.getNumMeasurements ();
    fDropAnalyzer.analyzeDrop (data[0], data[1], numMeasures);

    ++fNumDrops;

    // Check if all drops completed.
    if (fNumDrops == fMaxNumDrops){
      // If so then finish up the data recording
      // for this run and return.
      runDone ();
      return;
    }

    // Reset time sum
    fTDropTotal = 0.0;
    fYBall = fYBallStart;
    fXBall = fXBallStart;

    fDropPanel.reset (fXBallStart, fYBallStart);
    fDropModel.reset (fYBallStart, fVyBallStart);
    fDetector.reset ();

  } // dropDone


  /**
    *  Invoked when all the drops in a run  (set of drops) are done.
    *  Kills the timer to stop the animation.  (A new timer will be
    *  created in the dropReset () for the next run.)
    *  Tell the DropAnalyser instance to do its job on the run data.
   **/
  public void runDone () {

    // Stop the animation.
    fTimer.cancel ();

    // Update histogram
    fDropAnalyzer.analyzeRun ();

    // Reset the buttons.
    fGoButton.setText ("Drop");
    fClearButton.setEnabled (true);

  } // runDone

  /** Offer the option of running the applet in an app frame. */
  public static void main (String[] args) {
    //
    int frame_width=450;
    int frame_height=300;

    //
    DropTestAnalysisApplet applet = new DropTestAnalysisApplet ();
    applet.fInBrowser = false;
    applet.init ();

    // Following anonymous class used to close window & exit program
    JFrame f = new JFrame ("Drop Test");
    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

} // DropTestAnalysisApplet

 DropAnalyzer
import java.awt.*;
import javax.swing.*;

/**
  *  This class carries out the analysis of the
  *  drop experiment. It would work with either
  *  simulated or "real" data.
 **/
public class DropAnalyzer
{
  // These DrawFunction objects will draw data and fitted
  // curves on the DrawPanel instance.
  DrawPoly fDrawPoly;
  DrawPoints fDrawPoints;

  // Panel and components for displaying analysis results
  JPanel fAnalysisPanel;
  DrawPanel fDrawPanel;
  JTextField fResultsField;

  // Drop accounting
  int fNumDrops = 0;
  int fMaxNumDrops = 1;
  int fMaxNumMeasurements = 10;
  int fNumMeasurements = 10;

  DrawFunction [] fDrawFunctions;

  // Data array to recorded position data
  // for each drop.
  double [][] fDyData;

  // Drop times assumed same in each drop.
  double [] fDtData;

  // Array for passing data to DrawPoints object.
  double [][] fPointsData = new double[4][];

  /**
    *  The constructor receives the limits to the
    *  vertical range of the drop and the times.
   **/
  public DropAnalyzer (double y_data_min, double y_data_max,
                       double t_data_min, double t_data_max){

    // Create the DrawFunctions for passing to the
    // instance of DrawPanel.
    fDrawPoly   = new DrawPoly ();
    fDrawPoints = new DrawPoints ();

    fDrawFunctions = new DrawFunction[2];

    fDrawFunctions[0] = fDrawPoints;
    fDrawFunctions[1] = fDrawPoly;

    // Build the display panel and its components

    // Create an instance of DrawPanel. The GUI program
    // using this class can obtain a reference to the fDrawPanel
    // via the getPanel () method.
    fDrawPanel =
       new DrawPanel (y_data_min, y_data_max,
                      t_data_min, t_data_max,
                      fDrawFunctions);

    fDrawPanel.setXLabel ("y vs. time");
    fDrawPanel.setTitle ("Data Fit");

    fResultsField = new JTextField ("Expt. results");
    fResultsField.setEditable (false);

    fAnalysisPanel = new JPanel (new BorderLayout ());

    fAnalysisPanel.add (fDrawPanel, "Center");
    fAnalysisPanel.add (fResultsField, "South");

  } // DropAnalyzer


  /**
    *  Get the data measurements from the detector for a
    *  single drop. The time and positions are recorded from
    *  the first measurement point. The arrays may not be full
    *  so the fNumMeasurements variable keeps track of the number
    *  of elements with data.
   **/
  public void analyzeDrop (double [] measured_pos,
                           double [] measured_times,
                           int n_measures ){

    // Restrict the number drops to the fixed size of the data array.
    if (fNumDrops >= fMaxNumDrops ) return;

    // Use the given number of elements in the array but don't exceed
    // the size of the fDyData.
    fNumMeasurements = n_measures;
    if (fNumMeasurements > fMaxNumMeasurements)
        fNumMeasurements = fMaxNumMeasurements;

    // Make sure that the buffer size equals that of the time data array
    if (fDtData == null || fDtData.length < n_measures)
        fDtData = new double[fNumMeasurements];


    for (int j=0; j < fNumMeasurements; j++){

        // Save the time data. Assume it does not change
        // significantly from drop to drop.
        fDtData[j] = measured_times[j];

        // Record the position data for every drop so that
        // we can do averaging and error calculations at the
        // end of the run.
        fDyData[fNumDrops][j] = measured_pos[j];
     }

     fNumDrops++;
  } // analyzeDrop


  /**
    *  Let top class get access to panel with the components
    *  showing the analysis results.
   **/
  public JPanel getPanel () {
    return fAnalysisPanel;
  } // getPanel


  /**
    *  Analyze the data from a set of drops.
    *  Find the average position at each time step.
    *  Also calculate the sigma on the position.
   **/
  public void analyzeRun () {

    if (fNumDrops == 0) return;

    // Create the arrays needed for the averaging
    // and std.dev. calculation.
    double [] dyAvg  = new double[fNumMeasurements];
    double [] dySq   = new double[fNumMeasurements];
    double [] sigmaY = new double[fNumMeasurements];


    // Accumulate the sums for the averaging
    for (int i=0; i < fNumDrops; i++) {
      for (int j=0; j < fNumMeasurements; j++){
          dyAvg[j] += fDyData[i][j];
          dySq[j]  += fDyData[i][j] * fDyData[i][j];
      }
    }

    // Get the average position and its std.dev.
    for (int j=0; j < fNumMeasurements; j++){

      // Get the average velocity over the top gap
      dyAvg[j] /= fNumDrops;
      dySq[j]  /= fNumDrops;
      // Calculate the std.dev.
      double err = dySq[j] - dyAvg[j]*dyAvg[j];
      // Roundoff might result in a neg value for case of
      //  very small or zero smearing of the position data.
      if ( err < 1.0E-10)
          sigmaY[j]=0.0;
      else
          sigmaY[j] = Math.sqrt (err);
    }

    fPointsData[0] = dyAvg;
    fPointsData[1] = fDtData;
    fPointsData[2] = sigmaY;
    fPointsData[3] = null;  // assume no error on the time values

    // Pass the data points info to the fDrawPoints object
    fDrawPoints.setParameters ( null, fPointsData);

    // Fit points to a quadratic. Make parameters array twice as big
    // to make room for error values.
    double [] parameters = new double[6];
    FitPoly.fit (parameters, fDtData, dyAvg, null, sigmaY, fNumMeasurements);

    // Pass the fitted parameters to the DrawPoly object to draw the
    // quadratic.
    fDrawPoly.setParameters (parameters, null);

    // Use the PlotFormat static method to format the acceleration constant
    // and its error  (FitPoly uses the covariance matrix diagonal elements
    // to estimate the parameter errors.)
    double g = parameters[2]*2.0;
    double g_err = parameters[5]*2.0;
    fResultsField.setText (
       "g = "+
       PlotFormat.getFormatted (g,1100.0,0.0,4) +
       " +/-" +
       PlotFormat.getFormatted (g_err,1100.0,0.0,4) +
       " cm/s^2");

    // Cause the  curve to be redrawn.
    fDrawPanel.repaint ();

  } // analyzeRun


  /**
    *  Before each experiment  (i.e. set of drops), indicate here the number
    *  of measurements per drop and the maximum number of drops per run.
   **/
  public void initRun (int max_drops, int max_num_measurements) {
    fMaxNumMeasurements = max_num_measurements;
    fNumMeasurements = max_num_measurements;
    fMaxNumDrops = max_drops;

    // Create the data buffers.
    if (fDyData == null || fDyData.length < fMaxNumDrops)
      fDyData = new double[fMaxNumDrops][fMaxNumMeasurements];

    reset ();
  } // initRun


  /**
    *  Data accumulated or stored elsewhere and passed
    *  here for analysis.
   **/
  public void setData (double [][] pos_data, double[] time_data) {
    fMaxNumDrops = pos_data.length;
    fNumMeasurements = time_data.length;
    fMaxNumMeasurements = time_data.length;
    fDyData = pos_data;
    fDtData = time_data;
  } // setData


  /** Reset parameters and clear the DrawPanel instance. **/
  public void reset () {
    fNumDrops = 0;
    fNumMeasurements = fMaxNumMeasurements;

    // Clear the DrawFunction parameters to prevent drawing
    // on the panel
    fDrawPoly.setParameters (null,null);

    fPointsData[0] = null;
    fPointsData[1] = null;
    fPointsData[2] = null;
    fPointsData[3] = null;

    fDrawPoints.setParameters (null,fPointsData);
    fResultsField.setText ("");

  } // reset

  /**
    * Change the limits on the ranges of the position and
    * time data
   **/
  void setScaleLimits (double y_data_min, double y_data_max,
                      double t_data_min, double t_data_max) {

    fDrawPanel.setScaleLimits (y_data_min, y_data_max,
                               t_data_min, t_data_max);
  } // setScaleLimits

} // DropAnalyzer
DropDetector2
import java.awt.*;

/**
  *  This class simulates a detector measuring the
  *  the position of a mass drops. Could be a spark
  *  strip recorder for example.
 **/
public class DropDetector2 implements Detector
{
  // Error on the position measurements.
  double [] fSigmas;

  double [] fTimes;
  double [] fPositions;
  double fDetectTime; // Time in detector sensitive region
  double fTimeStep; // Time between measurements

  int fMaxNumMeasurements = 1;
  int fNumMeasurements    = 0;

  double [][] data = new double[2][];;

  // Sensitive region limits
  double fYTopLimit   = 190.0; //cm
  double fYBotLimit   =  10.0; //cm
  double fXLeftLimit  =  15.0; //cm
  double fXRightLimit =  35.0; //cm

  // Create an instance of the Random class for
  // producing our random values.
  static java.util.Random fRan = new java.util.Random ();

  /**
    *  Setup the detector. Parameters argument not used.
    *
    *  @param fSigmas - fSigmas array gives the error on each measurement
    *  of position and time.
   **/
  public void init (int[] setup, double [] parameters, double [] sigmas) {

     // Get the S.D. for the time and position values.
     fSigmas = sigmas;
     fTimeStep = parameters[0];
     fDetectTime = 0.0;

     if (fMaxNumMeasurements != setup[0] || fTimes == null){
         fMaxNumMeasurements = setup[0];
         fPositions = new double[fMaxNumMeasurements];
         fTimes    = new double[fMaxNumMeasurements];
     }

     data[0] = fPositions;
     data[1] = fTimes;

     reset ();

  }  //init

  /** Initialize for each drop. **/
  public void reset (){
    fNumMeasurements = 0;
    fDetectTime = 0.0;

    for (int i=0; i < fMaxNumMeasurements; i++) {
      fPositions[i] = 0.0;
      fTimes[i] = 0.0;
    }
  } // reset

  /**
    *  For the y and accumulated drop time, obtain the
    *  simulated measured time by a Gaussian smearing.
    *  @param vals - 2 element array with the y and time values.
    *
   **/
  public void measure (double [] vals) {

    if (fNumMeasurements >= fMaxNumMeasurements) return;
    double time = vals[1];

    // Wait for measurement to cross threshold marker.
    if (time >= fDetectTime) {

      // Set new time threshold
      fDetectTime = fNumMeasurements * fTimeStep;

      // Only record points in the sensitive area.
      if (vals[0] > fYTopLimit || vals[0] < fYBotLimit) return;

      // Smear position by he given sigma
      fPositions[fNumMeasurements] = vals[0] +
                          fSigmas[0] * fRan.nextGaussian ();

      // Can smear time as well.
      fTimes[fNumMeasurements++] = vals[1] +
                          fSigmas[1] * fRan.nextGaussian ();
    }
  } // measure

  /** Return the position and time arrays with a single 2D array. **/
  public double [][] getResults (){
    return data;
  }  // getResults

  /**
    * Number of measured points can be less than the
    * maximum. So need access to this value.
   **/
  public int getNumMeasurements () {
    return fNumMeasurements;
  }

  /**
    *  Draw the detector markers as horizonatal lines.
    *  Also draw some vertical lines it indicate a drop
    *  area.
   **/
  public void draw (Graphics g, int x0, int y0, int dx, int dy,
                   double x_convert, double y_convert) {

    Color orig_color = g.getColor ();
    g.setColor (Color.BLUE);

    // Draw the vertical sides of detector
    int xSideLeft = x0 +  (int) (fXLeftLimit  * x_convert);
    int xSideRite = x0 +  (int) (fXRightLimit * x_convert);
    int yBot      = y0 + dy -  (int) (fYBotLimit * y_convert);
    int yTop      = y0 + dy -  (int) (fYTopLimit * y_convert);

    g.drawLine (xSideLeft,yTop,xSideLeft,yBot);
    g.drawLine (xSideRite,yTop,xSideRite,yBot);

    // Draw the ball at the points where it is measured.
    g.setColor (Color.ORANGE);
    int xMark      = x0 +  (int) (0.48 * dx);
    int markWidth  = (int) (0.04 * dx);
    int markHeight = (int) (0.04 * dx);

    for (int i=0; i < fNumMeasurements; i++){
      int yMark = y0 + dy -  (int) (fPositions[i]*y_convert);
      g.drawOval (xMark,yMark,markWidth,markHeight);
    }

    // Return to previous color.
    g.setColor (orig_color);

  } // draw

} // DropDetector2

 

 

References & Web Resources

 

Most recent update: Oct. 29, 2005

              Tech
Histogram I/O
Hist I/O - Get/Set
  Demo 1
Hist I/O - Objects
  Demo 2
HistogramStream
  Demo 3
Filtering Data
  Demo 4
Exercises

           Physics
Physics Model
Simulation Design
Physics Simulator
  Demo 1
Experiment Design
Experiment Sim.
  Demo 2
Analysis
Expt. + Analysis
  Demo 3
Exercises

  Part I Part II Part III
Java Core 1  2  3  4  5  6  7  8  9  10  11  12 13 14 15 16 17
18 19 20
21
22 23 24
Supplements

1  2  3  4  5  6  7  8  9  10  11  12

Tech 1  2  3  4  5  6  7  8  9  10  11  12
Physics 1  2  3  4  5  6  7  8  9  10  11  12

Java is a trademark of Sun Microsystems, Inc.