| The program DropDataAnalysisCalSysErr 
               analyzes the output of the program DropGenCalSysErr 
              discussed on the previous page. The program 
              is quite similar to DropDataAnalysis 
              from Chapter 10: Physics except 
              that it allows the user to enter a "calibration" constant 
              that will be subtracted from the position data. Also the program 
              displays the full polynominal fit to the y vs. time data. The DropDataAnalysisCalSysErr 
              class mainly deals with the GUI and with reading in the data from 
              the file. It lets an instance of DropAnalyzerCalSysErr, 
              which is a subclass of DropAnalyzer 
              , do most of the actual analysis. This class fits the data points 
              and then plots the data and fitted polynominal line on a panel displayed 
              on the GUI. Before the fit, DropAnalyzerCalSysErr 
              subtract from the position data values the value given in the calibration 
              field on the user interface.  
              
                 
                  | DropDataAnalysisCalSysErr
 
 
  
                      DropDataAnalysisCalSysErr 
                        - 
                        Developed from from the Chapter 
                        9: Physics: Experiment Simulation with Analysis Module 
                        and Chapter 10: Simulated 
                        Data Generation and Analysis Demo, this program examines 
                        the data produced by DropGenCalSysErr. It 
                        allows the user to enter an "calibration" constant 
                        to subtract from the position values. It also displays 
                        the whole fit to the position vs time data. The 
                        drop down menu allows the user to select a file chooser 
                        to find the data file. The first text field shows the 
                        data file selected. The 
                        second text field allows the user to enter the calibration 
                        value to subtract from the position data.  The 
                        blue dots in the above plot are the position of the dropped 
                        mass for each time step during the drop averaged over 
                        the number of drops in the data file. Vertical red lines, 
                        just barely visible in this plot, represent the error 
                        on these y position averages. (The time step values are 
                        considered exact.)  DropAnalyzerCalSysErr 
                        - subclass of DropAnalyzer 
                        that allows for subtraction of a calibration constant 
                        from the position values. It also displays the whole polynominal 
                        fit to the y vs t data.   
                        + Previous Classes:Chapter 
                        9: Physics: DropAnalyzer
 Ch. 
                        8: Physics: 
                        Fit.java, 
                        FitPoly.java, 
                        DrawPoly.java
 Ch. 
                        6: Tech:  
                        DrawPanel.java, 
                        DrawPoints.java, 
                        DrawFunction.java
 Chapter 
                        6: Tech: PlotPanel.java, 
                        PlotFormat.java
   |   
                  | import 
                    javax.swing.*; import java.awt.*;
 import java.awt.event.*;
 import java.io.*;
 import java.util.*;
 import java.text.*;
 
 /**
 * This program reads in data from a file created 
                    by DropGenerator.
 * For each drop event the data is sent to an instance 
                    of DropAnalyzer.
 * When all the data is read, a fit is made to 
                    the average y vs t curve
 * to determine the g parameter as before.
 **/
 public class DropDataAnalysisCalSysErr extends JFrame
 implements 
                    ActionListener
 {
 // Constants to identify type of data according 
                    to the
 // bits set.
 final static int RUN_SIM    = 
                    0x1;  // Simulation
 final static int RUN_ADDCAL = 0x2;  // 
                    Include instrument constants
 final static int RUN_RUNCAL = 0x4;  // 
                    Calibration run
 final static int RUN_SYSERR = 0x8;  // 
                    Simulate systematic error
 
 int fRunType = RUN_SIM; // Default to simulation 
                    data.
 
 // UI control variables
 JMenuItem fMenuOpen;
 JMenuItem fMenuSave;
 JMenuItem fMenuClose;
 
 JTextField fFileTextField;    // 
                    Input data file name
 JTextField fCalPosTextField;  // Calibration 
                    constant user input
 double fCalPosConstant = 0.0; // Calibration constant
 
 DropAnalyzerCalSysErr fDropAnalyzer;
 
 JButton fGoButton;
 
 // Change these names as needed
 String fButtonName1 = "Go";
 
 // Filter and File object for fFile chooser
 DataFilter fDataFilter = new DataFilter ();
 File fInFile;
 String fInFileName = "[select input file]";
 // DataInputStream is used to read the data.
 DataInputStream fInData;
 
 // 2-D array to hold position and time data for
 // each drop.
 double [][] fData;
 
 // The data file includes the time for when it
 // was made.
 Date dateOfData;
 
 // Enumerated type used to direct output operations
 public enum InputCmd {IN_SETUP, IN_READ, OUT_CLOSE}
 
 // Enumerated type used to direct output operations
 public enum InputStatus {OK, EVENT_READ, EOF, 
                    ERROR}
 InputStatus fInputStatus;
 
 // Maximum number of measurements along each drop 
                    trajectory
 int fMaxNumMeasurements;
 // Number of measurements on current drop
 int fNumMeasures;
 // Drop number in the file
 int fNumDrops;
 // Max number of drops in the file
 int fMaxNumDrops;
 
 // The following experimental settings could be 
                    allowed
 // to vary and then recorded in the data header 
                    for a given
 // run. However, this program assumes they are 
                    constant.
 
 // 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
 
 /** Create a frame for displaying the GUI.**/
 public static void main (String [] args) {
 String title="Drop Data Analysis";
 DropDataAnalysisCalSysErr f = new 
                    DropDataAnalysisCalSysErr (title);
 f.setVisible (true);
 } // main
 
 /**
 * The GUI is built in the constructore. 
                    Pass a title
 * to the frame via the constructor  argument.
 **/
 DropDataAnalysisCalSysErr (String title) {
 super (title);
 
 // Create a user interface.
 setLayout (new BorderLayout ());
 
 // Create an analyzer and add its 
                    panel to the frame.
 fDropAnalyzer = new DropAnalyzerCalSysErr 
                    (
 fYBallEnd, 
                    fYBallStart,
 fTStart, 
                    fTEnd);
 
 add (fDropAnalyzer.getPanel (), "Center");
 
 // Create a panel with a textfield 
                    and two buttons
 fFileTextField = new JTextField (fInFileName);
 
 fGoButton = new JButton (fButtonName1);
 fGoButton.addActionListener (this);
 
 fCalPosTextField = new JTextField 
                    ("0.0");
 
 JPanel panel = new JPanel (new GridLayout 
                    (1,3));
 panel.add (fFileTextField);
 panel.add (fCalPosTextField);
 panel.add (fGoButton);
 
 add (panel, "South");
 
 // Use the helper method makeMenuItem
 // for making the menu items and registering
 // their listener.
 JMenu m = new JMenu ("File");
 
 // the particular program.
 m.add (fMenuOpen  = makeMenuItem 
                    ("Open"));
 m.add (fMenuClose = makeMenuItem ("Quit"));
 
 JMenuBar mb = new JMenuBar ();
 mb.add (m);
 
 setJMenuBar (mb);
 setSize (550,400);
 setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE);
 
 } // ctor
 
 /**
 * Process events from the frame menu 
                    and the chooser.
 **/
 public void actionPerformed ( ActionEvent e ) 
                    {
 boolean status = false;
 
 String command = e.getActionCommand 
                    ();
 
 if (command.equals (fButtonName1)) 
                    {
 if (fInputStatus == InputStatus.OK) 
                    analyzeData ();
 else
 JOptionPane.showMessageDialog 
                    (
 null,
 "File 
                    not ready", "File Read Error",
 JOptionPane.ERROR_MESSAGE);
 }
 else if (command.equals ("Open")) 
                    {
 // Open a fFile
 status = openFile ();
 if (!status) {
 JOptionPane.showMessageDialog 
                    (
 null,
 "Error 
                    opening fFile!", "File Open Error",
 JOptionPane.ERROR_MESSAGE);
 fInputStatus 
                    = InputStatus.ERROR;
 } else {
 fInputStatus 
                    = InputStatus.OK;
 }
 
 } else if (command.equals ("Quit")) 
                    {
 dispose ();
 }
 } // actionPerformed
 
 /**
 * This "helper method" makes a menu 
                    item and then
 * registers this object as a listener 
                    to it.
 **/
 private JMenuItem makeMenuItem (String name) {
 JMenuItem m = new JMenuItem ( name 
                    );
 m.addActionListener ( this );
 return m;
 }
 
 /** Carry out the analysis of the data in the 
                    chosen file. **/
 void analyzeData () {
 int evt = 0;
 while (true) {
 // Read an event
 inputFromFile (InputCmd.IN_READ);
 // and analyze it.
 if (fInputStatus == InputStatus.EVENT_READ) 
                    {
 fDropAnalyzer.analyzeDrop 
                    (fData[0], fData[1], fNumMeasures);
 } else
 if (fInputStatus == InputStatus.EOF) 
                    {
 // Analyze 
                    the full run data now.
 fDropAnalyzer.analyzeRun 
                    ();
 break;
 } else
 if (fInputStatus == InputStatus.ERROR) 
                    {
 JOptionPane.showMessageDialog 
                    (
 null,
 "Read 
                    failure", "File Read Error",
 JOptionPane.ERROR_MESSAGE);
 break;
 }
 }
 
 } // analyzeData
 
 /**
 *  This method handles the 
                    input from the data file.
 *  The ennumerated type 
                    InputCmd indicates which
 *  operation: setup, writing 
                    each drop data set, and
 *  stream closeing should 
                    be executed.
 **/
 void inputFromFile (InputCmd input_cmd) {
 
 switch (input_cmd) {
 
 case IN_SETUP:
 try {
 // 
                    Wrap the FileInputStream with a DataInputStream
 FileInputStream 
                    file_input = new FileInputStream (fInFile);
 fInData 
                    = new DataInputStream (file_input );
 
 // 
                    Read header
 
 // 
                    First get the type of the run data
 fRunType 
                    = fInData.readInt ();
 // 
                    Then get the time of the run (in millisecs since 1970)
 long 
                    data_time = fInData.readLong ();
 // 
                    And convert to a date object.
 dateOfData 
                    = new Date (data_time);
 // 
                    Then convert this date to a string with date and time
 DateFormat 
                    df =
 DateFormat.getDateTimeInstance(DateFormat.SHORT,DateFormat.SHORT);
 String 
                    run_date = df.format(dateOfData);
 String 
                    plot_title = "";
 if 
                    ((fRunType & RUN_RUNCAL) != 0)
 plot_title 
                    += "Cal run,";
 else
 plot_title 
                    = "Sim Data,";
 if 
                    ((fRunType & RUN_ADDCAL) != 0) plot_title += "cal offset,";
 if 
                    ((fRunType & RUN_SYSERR) != 0) plot_title += "sys error," 
                    ;
 
 fDropAnalyzer.fDrawPanel.setTitle 
                    (plot_title + run_date);
 
 // 
                    Now get the other data in the header
 fMaxNumDrops 
                    = fInData.readInt ();
 fMaxNumMeasurements 
                    = fInData.readInt ();
 
 // 
                    Check the calibration constant input from the user
 try 
                    {
 fCalPosConstant 
                    = Double.parseDouble (fCalPosTextField.getText ());
 }
 catch 
                    (NumberFormatException ex) {
 System.out.println ("Bad input value");
 fCalPosConstant = 0.0;
 }
 
 // 
                    Tell the analyzer how the max number of drop events to
 // 
                    expect and the max number of measurements for a drop.
 fDropAnalyzer.initRun 
                    (fMaxNumDrops, fMaxNumMeasurements, fCalPosConstant);
 
 // 
                    Need an array to hold data for a single drop
 fData 
                    = new double[2][fMaxNumMeasurements];
 }
 catch (FileNotFoundException 
                    fnfe) {
 JOptionPane.showMessageDialog 
                    (
 null,
 "Cannot 
                    open file!", "File Open Failure",
 JOptionPane.ERROR_MESSAGE);
 fInputStatus 
                    = InputStatus.ERROR;
 }
 catch (IOException 
                    ioe) {
 JOptionPane.showMessageDialog 
                    (
 null,
 "I/O 
                    failure", "File Read Error",
 JOptionPane.ERROR_MESSAGE);
 fInputStatus = InputStatus.ERROR;
 }
 break;
 
 case IN_READ:
 // Now read 
                    the data and analze.
 try {
 fNumDrops 
                    = fInData.readInt ();    // drop number
 fNumMeasures 
                    = fInData.readInt (); // Number of measurements
 // 
                    Write the data as an position/time pair
 for 
                    (int i=0; i < fNumMeasures; i++) {
 fData[0][i] 
                    = fInData.readDouble (); // positions
 fData[1][i] 
                    = fInData.readDouble (); // times
 }
 fInputStatus 
                    = InputStatus.EVENT_READ;
 }
 catch (EOFException 
                    eof) {
 fInputStatus 
                    = InputStatus.EOF;
 inputFromFile 
                    (InputCmd.OUT_CLOSE);
 }
 catch (IOException 
                    e) {
 JOptionPane.showMessageDialog 
                    (
 null,
 "I/O 
                    failure", "File Read Error",
 JOptionPane.ERROR_MESSAGE);
 fInputStatus 
                    = InputStatus.ERROR;
 inputFromFile 
                    (InputCmd.OUT_CLOSE);
 }
 break;
 
 case OUT_CLOSE:
 // Close file 
                    when finished with it.
 try {
 fInData.close 
                    ();
 }
 catch (IOException 
                    e) {
 JOptionPane.showMessageDialog 
                    (
 null,
 "I/O 
                    failure on file close!", "File Read Error",
 JOptionPane.ERROR_MESSAGE);
 }
 break;
 }
 
 } // inputFromFile
 
 
 /**
 * Use a JFileChooser in Open mode 
                    to select fFiles
 * to open. Use a filter for FileFilter 
                    subclass to select
 * for *.dat fFiles. If a file is selected 
                    then read the
 * file and place the string into the 
                    textarea.
 **/
 boolean openFile () {
 
 JFileChooser fc = new JFileChooser 
                    ();
 fc.setDialogTitle ("Open File");
 
 // Choose only fFiles, not directories
 fc.setFileSelectionMode ( JFileChooser.FILES_ONLY);
 
 // Start in current directory
 fc.setCurrentDirectory (new File ("."));
 
 // Set filter for web pages.
 fc.setFileFilter (fDataFilter);
 
 // Now open chooser
 int result = fc.showOpenDialog (this);
 
 if (result == JFileChooser.CANCEL_OPTION) 
                    {
 return true;
 } else if ( result == JFileChooser.APPROVE_OPTION) 
                    {
 fInFile = 
                    fc.getSelectedFile ();
 String fInFileName 
                    = fInFile.getName ();
 if (fInFileName 
                    != null) {
 fFileTextField.setText (fInFileName);
 inputFromFile (InputCmd.IN_SETUP);
 } else
 return false;
 
 } else {
 return false;
 }
 return true;
 
 } // openfFile
 
 
 } // class DropDataAnalysis
 
 
 /** Class to use with JFileChooser for selecting hypertext 
                    fFiles.*/
 class DataFilter extends javax.swing.filechooser.FileFilter 
                    {
 
 public boolean accept (File f) {
 return f.getName ().toLowerCase ().endsWith 
                    (".dat")
 || f.isDirectory 
                    ();
 }
 public String getDescription () {
 return "Data files  (*.data)";
 }
 } // class DataFilter
 |   
                  | import 
                      java.awt.*;import javax.swing.*;
 
 /**
 *  This class carries out the analysis 
                      of the drop experiment.
 *  It is similar to the DropAnalyzer 
                      class but allows for subtraction
 *  of calibration constant from the 
                      position data. It also displays
 *  the whole polynominal fit to the position 
                      vs time curve.
 **/
 public class DropAnalyzerCalSysErr extends DropAnalyzer
 {
 // Allow for a calibration constant to be subtracted
 // from the position data.
 double fCalPosConstant = 0.0;
 
 /**
 *  The constructor receives 
                      the limits to the
 *  vertical range of the 
                      drop and the times.
 **/
 public DropAnalyzerCalSysErr (double y_data_min, 
                      double y_data_max,
 double 
                      t_data_min, double t_data_max) {
 
 super (y_data_min, y_data_max, t_data_min, 
                      t_data_max);
 
 } // DropAnalyzerCalSysErr
 
 
 /**
 *  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.
 *  Subtract the calibration 
                      constant from the position 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] - fCalPosConstant;
 }
 
 fNumDrops++;
 } // analyzeDrop
 
 
 /**
 *  Analyze the data from 
                      a set of drops.
 *  Find the average position 
                      at each time step.
 *  Also calculate the 
                      sigma on the position.
 *  Show the fitted polynominal 
                      along with the
 *  error on the parameters 
                      of the fit.
 **/
 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 parameters from the fit
 // to the data.  (FitPoly 
                      uses the covariance matrix diagonal elements
 // to estimate the parameter errors.)
 double y0 = parameters[0];
 double y0_err = parameters[3];
 
 double v0 = parameters[1];
 double v0_err = parameters[4];
 
 double g  = parameters[2]*2.0;
 double g_err = parameters[5]*2.0;
 String fit_result =
 "y0 = " +
 PlotFormat.getFormatted 
                      (y0,1100.0,0.0,3)     + "+/-" +
 PlotFormat.getFormatted 
                      (y0_err,1100.0,0.0,3) + "cm"
 + ", v0 = " +
 PlotFormat.getFormatted 
                      (v0,1100.0,0.0,4)     + "+/-" +
 PlotFormat.getFormatted 
                      (v0_err,1100.0,0.0,3) + "cm/s"
 + ", g = " +
 PlotFormat.getFormatted 
                      (g,1100.0,0.0,4)     + "+/-" +
 PlotFormat.getFormatted 
                      (g_err,1100.0,0.0,3) + "cm/s^2";
 
 fResultsField.setText (fit_result);
 
 // 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, 
                      double cal_pos) {
 fMaxNumMeasurements = max_num_measurements;
 fNumMeasurements = max_num_measurements;
 fMaxNumDrops = max_drops;
 fCalPosConstant = cal_pos;
 
 // Create the data buffers.
 if (fDyData == null || fDyData.length 
                      < fMaxNumDrops)
 fDyData = new double[fMaxNumDrops][fMaxNumMeasurements];
 
 reset ();
 } // initRun
 
 } // DropAnalyzerCalSysErr
 |    Most recent update: Nov. 8, 2005 |