Lecture 11B
Physics Model
Simulation Design
Physics Simulator
Experiment Design
Expt. Simulator
Expt.SimulatorCode
Detector Interface
Sim T vs Real T
Analysis
Exercises

Lectures

1A: Introduction
1B: Java Intro
2A: BuildingBlocks
2B: Objects
3A: More Objects
3B: Exceptions
       & Threads
4A: Waves
4B: Nuclear &
       Particle
5A: AWT
5B: More AWT
      & Graphics
6A:Detectors &
      Simulation
6B: LHC/Atlas &
     RandomSims    
7A: Swing
7B: Java2D
8A: Java Apps
8B: Dialogs &
    MoreClasses
9A: Java I/O
9B: Utilities,
        Unicode
10A: More
    Threading
10B: File
    Handling
11A: Array,Print,
    Images
11B: SimplePhysics
    Simulation
12A: Tips &
    Techniques
12B: More Tips &
    Techniques
13A: Satellite
    
Simulations
13B: Intro to Java
    Networking
14A: Java Servers
14B: HTTP Server
15A: ServerClient
15B: ServerClient
   Expt.Simulation
16A: Course
          Review
16B: ExerciseTest
        Discussion

    Contacts
    Description
    Exercises
    Index
    Outline
    Q&A
    Resources
    StudentInfoForm
    Student Pages
    What's New

 

Home : Lectures : Lecture 11B : The Experiment Simulation Code
The Experiment Simulation Code

The detector and physics simulations combined code is shown here:

FallingObject.java

The top level class that controls the user interface and the program flow. Red shows the main changes from the physics only simulation code.

/*
  This applet simulates an object falling with
  a constant gravitational acceleration.
*/
/*
<applet code = "FallingObject" height=400 width=340>
</applet>
*/

import java.applet.*;
import java.awt.*;
import java.awt.event.*;

/*--------------------------------------------------*/
public class FallingObject extends Applet implements ActionListener{
  BoxShoot shoot;

  Button    startBt;
  TextField nDropsText;
  TextField gText;
  TextField speedUpText;
  TextField elevationText;

  int nDropsDefault      =     1;
  double gDefault        = 980.0;
  double speedUpDefault  =   1.0;
  double elevationDefault= 200.0;

  int nDrops;
  int dropCount=0;
  double g;
  double speedUp;
  double elevation;

// Add detector setup here
  G_Detector detector=null;

/*--------------------------------------------------*/
//

  public void init(){

    // Most of this is just setting up the interface
    // using panels within panels.

    setBackground(Color.blue);
    setLayout(new BorderLayout());

    nDrops = nDropsDefault;
    g = gDefault;
    speedUp = speedUpDefault;
    elevation = elevationDefault;

    shoot = new BoxShoot(nDrops, speedUp, g, elevation,this);
    add("West",shoot);

    Panel controls = new Panel(new BorderLayout());
    controls.setBackground(Color.white);

    startBt = new Button("Start");
    startBt.addActionListener(this);
    Panel bp0 = new Panel();
    bp0.add(startBt);
    controls.add("West",bp0);

    Panel entriesPane = new Panel();
    entriesPane.setLayout(new GridLayout(4,2));

    Panel lp0 = new Panel(new FlowLayout(FlowLayout.RIGHT));
    lp0.add(new Label("N-drops:"));
    entriesPane.add(lp0);

    nDropsText = new TextField(""+nDrops,4);
    nDropsText.addActionListener(this);
    Panel pt0 = new Panel(new FlowLayout(FlowLayout.LEFT));
    pt0.add(nDropsText);
    entriesPane.add(pt0);

    Panel lp1 = new Panel(new FlowLayout(FlowLayout.RIGHT));
    lp1.add(new Label("g(cm/s**2)="));
    entriesPane.add(lp1);

    gText = new TextField(""+g,4);
    gText.addActionListener(this);
    Panel pt1 = new Panel(new FlowLayout(FlowLayout.LEFT));
    pt1.add(gText);
    entriesPane.add(pt1);

    Panel lp2 = new Panel(new FlowLayout(FlowLayout.RIGHT));
    lp2.add(new Label("FrameRate:"));
    entriesPane.add(lp2);

    speedUpText = new TextField(""+speedUp,4);
    speedUpText.addActionListener(this);
    Panel pt2 = new Panel(new FlowLayout(FlowLayout.LEFT));
    pt2.add(speedUpText);
    entriesPane.add(pt2);

    Panel lp3 = new Panel(new FlowLayout(FlowLayout.RIGHT));
    lp3.add(new Label("Height(cm):"));
    entriesPane.add(lp3);

    elevationText = new TextField(""+elevation,4);
    elevationText.addActionListener(this);
    Panel pt3 = new Panel(new FlowLayout(FlowLayout.LEFT));
    pt3.add(elevationText);
    entriesPane.add(pt3);

    controls.add("East",entriesPane);

    add("South",controls);

    // Add the detector
    detector = new G_Detector( shoot.dY, shoot.dX);
    add("East",detector);
    detector.init();

 
  }
/*--------------------------------------------------*/
// Called by BallShoot whenever the drop, i.e. the event
// has finished. Provides for multiple drops

  public void dropDone () {
    detector.eventDone();
    dropCount--;
    if(dropCount > 0){
       detector.eventStart();
       shoot.start();

    }
  }
/*--------------------------------------------------*/
  public void actionPerformed ( ActionEvent e) {
    Object src = e.getSource();
    String str;

    if( src == startBt) {
      checkTextFields();
      dropCount = nDrops;
      detector.eventStart();
      shoot.start();

    } else if(src == nDropsText){
      str = nDropsText.getText();
     try{
        nDrops = Integer.valueOf(str).intValue();
      } catch ( NumberFormatException ex){
        nDrops = nDropsDefault;
        nDropsText.setText(""+nDropsDefault);
      }
      shoot.setnDrops(nDrops);

    } else if(src == gText){
      str = gText.getText();
      try{
        g = Double.valueOf(str).doubleValue();
      } catch ( NumberFormatException ex){
        g = gDefault;
        gText.setText(""+gDefault);
      }
      shoot.setGrav(g);

    } else if(src == speedUpText){
      str = speedUpText.getText();
      try{
        speedUp = Double.valueOf(str).doubleValue();
      } catch ( NumberFormatException ex){
        speedUp = speedUpDefault;
        speedUpText.setText(""+speedUpDefault);
      }
      shoot.setSpeedUp(speedUp);

    } else if(src == elevationText){
      str = elevationText.getText();
      try{
        elevation = Double.valueOf(str).doubleValue();
      } catch ( NumberFormatException ex){
        elevation = elevationDefault;
        elevationText.setText(""+elevationDefault);
      }
      shoot.setElevation(elevation);
    }
  }
/*--------------------------------------------------*/
// This code looks at all text fields and reads in all
// values. Called whenever start button is pushed in case
// changes were made without pushing enter key.

  void checkTextFields(){

  String str = nDropsText.getText();
  try{
        nDrops = Integer.valueOf(str).intValue();
  } catch ( NumberFormatException ex){
    nDrops = nDropsDefault;
    nDropsText.setText(""+nDropsDefault);
  }
  shoot.setnDrops(nDrops);

  str = gText.getText();
  try{
     g = Double.valueOf(str).doubleValue();
  } catch ( NumberFormatException ex){
     g = gDefault;
     gText.setText(""+gDefault);
  }
  shoot.setGrav(g);

  str = speedUpText.getText();
  try{
     speedUp = Double.valueOf(str).doubleValue();
  } catch ( NumberFormatException ex){
     speedUp = speedUpDefault;
     speedUpText.setText(""+speedUpDefault);
  }
  shoot.setSpeedUp(speedUp);
 
  str = elevationText.getText();
  try{
     elevation = Double.valueOf(str).doubleValue();
  } catch ( NumberFormatException ex){
     elevation = elevationDefault;
     elevationText.setText(""+elevationDefault);
  }
  shoot.setElevation(elevation);
 
}
/*--------------------------------------------------*/
  public Insets getInsets(){
    return new Insets(2,2,2,2);
  }
}

BoxShoot.java

The threaded class (Runnable) that controls the drop, i.e. the animation of the dropping object.

Detector related code shown in red. Only a few changes needed from the physics only simulation.

import java.awt.*;
import java.awt.event.*;

public class BoxShoot extends Canvas implements Runnable{
  int dY,dX;
  Thread drawThread;
  Image offScrImg;
  Circle ball;
  int radius;
  boolean initCanvas=true;

  FallingObject parent=null;

  int nDrops;
  int frameRate;
  double deltaT;
  double speedUp;
  double gPhysical;
  double physicalHeight;

/*--------------------------------------------------*/
//

  public BoxShoot(int nDrops, double speedUp, double grav,
                  double elevation, FallingObject fo){

    parent = fo;

    this.nDrops = nDrops;

    setBackground(Color.white);
    dY=240;
    dX=150;
    setSize(dX,dY);

    // Choose some parameter for the size of the object to drop
    radius = dY/40;

    // These parameters separate thread animation
    // frame rates from the physical time of the
    // falling object.

    frameRate = 10;
    this.speedUp = speedUp;

    gPhysical = grav;// = 9.8cm/s**2
    physicalHeight = elevation;
    init();
  }
/*--------------------------------------------------*/
  public Dimension getPreferredSize(){
    return new Dimension(dX,dY);
  }
/*--------------------------------------------------*/
//

  public void init(){

    deltaT = frameRate/1000.0;
    deltaT *= speedUp;

    // Scale physical g units to the graphical pixel units
    // Let the frame represent a 200cm in height.

    double g = gPhysical * ( dY/physicalHeight);

    // Create the object to drop
    int x0 = 2 * radius;
    int y0 = 2 * radius;
    ball = new Circle(x0,y0,radius,dX,dY,g);

    // set it's initial velocity
    ball.VxInit   = 0.0;
    ball.VyInit   = 0.0;

    initCanvas=true;

}
/*--------------------------------------------------*/

  public void start() {
    if (drawThread != null){
      stop();
    }
    init();
    ball.reset();
    initCanvas=true;
    drawThread = new Thread(this);
    drawThread.start();
  }
/*--------------------------------------------------*/
  public void stop() {
    drawThread = null;
    // Give this thread time to jump out of its loop in run()
    try {
      Thread.sleep(250);
    } catch (InterruptedException e)
    {}
  }
/*--------------------------------------------------*/
  public void run() {
    repaint();
    while (drawThread != null) {
      // Use sleep to pause between movements
      try {
        Thread.sleep(frameRate);
      } catch (InterruptedException e)
      {}
      // If all movement stopped then stop animation

      if( ball.xStop && ball.yStop){
        stop();
        break;
      }

      ball.move(deltaT);
      repaint();

      // Send sensor readings
      parent.detector.sensor(ball.y,frameRate);

    }
    parent.dropDone();
  }
/*--------------------------------------------------*/
  public synchronized void update( Graphics g ) {
    // Create an offscreen image and then get its graphics context
    if ( offScrImg == null )
      offScrImg = createImage( dX, dY );
    Graphics og = offScrImg.getGraphics();

    // Now draw on the offscreen image.
    paint( og );

    // Don't bother to call paint, just draw the offscreen image
    // to the screen.

    g.drawImage(offScrImg, 0, 0, this);

    // Get rid of the offscreen graphics context.
    // Can't unclip a graphics
    // context so have to get a new one next time around.

    og.dispose();
  }
/*--------------------------------------------------*/
  public synchronized void paint(Graphics g) {
    if( initCanvas ){
      g.setColor(Color.white);
      g.fillRect(0,0,dX,dY);
      // Here the detector class will draw itself
      parent.detector.draw(g);
      initCanvas=false;
    } if( drawThread != null)// Draw ball
                            
// only during drop
    ball.draw(g);
  }
/*--------------------------------------------------*/
  public void setnDrops(int n) {
    nDrops = n;
  }
/*--------------------------------------------------*/
  public void setGrav(double g) {
    gPhysical = g;
  }
/*--------------------------------------------------*/
  public void setElevation(double ht) {
    physicalHeight = ht;
  }
/*--------------------------------------------------*/
  public void setSpeedUp(double s) {
    speedUp = s;
  }
}

Circle.java , ObjectToDraw.java

Unchanged from the previous physics only simulation.

G_Detector.java

import java.awt.*;
import java.util.*;
import ThirdParty.BarChart.*;

public class G_Detector extends Panel implements Runnable{

  Thread analyzeThread;
  DataChart chart = null;
  Histogram hist = null;

  int ySensorTop,ySensorBot,shootWidth;
  boolean passedTop,passedBot;

  int tClock=0;
  int topTime=0;
  int botTime=0;
  double TimeResolution = 10.0;
 
  Random ran = new Random();

  //---------------------------------------------------------
  public G_Detector(int detHeight,int detWidth){
    // Add sub-panels with readouts, histograms and controls

    setBackground(Color.cyan);

    int _width= 175;
    int _height = 200;

    Panel p1 = new Panel();
    p1.setLayout(new BorderLayout());
    hist = new Histogram(40,120.0,320.0,_width,_height-50);
    p1.add("North",new Label("Drop Delta-T times"));
    p1.add("Center",hist.chart._barChart);
    p1.add("South",new Label(
         "Bin Range: 120-320ms",Label.CENTER));
 
    add(p1);

    ySensorTop = (int)(0.40 * detHeight);
    ySensorBot = (int)(0.90 * detHeight);
    shootWidth = detWidth;

  }
  //---------------------------------------------------------
  public void init(){
    passedTop = false;
    passedBot = false;
    hist.reset();
    repaint();
  }
  //----------------------------------------------------------
  public void start() {
    analyzeThread = new Thread(this);
    analyzeThread.start();
  }
  //---------------------------------------------------------
  public void stop() {
    analyzeThread = null;
  }
  //---------------------------------------------------------
  public void eventStart(){
    passedTop = false;
    passedBot = false;
    tClock = 0;
  }
  //---------------------------------------------------------
  public void eventDone(){
    repaint();
  }
  //---------------------------------------------------------
  // Called by the BoxShoot run() after each animation
  // step to give how far the object has dropped.

  public void sensor(double y, int t){
    tClock += t;
    if(!passedTop){
      if( y >= ySensorTop){
        topTime = tClock;
        passedTop=true;
      }
      return;
    }
    if(!passedBot){
      if( y >= ySensorBot){
        botTime = tClock;
        passedBot=true;

        // Data is ready so start detector thread
        start();
      }
      return;
    }
  }
  //--------------------------------------------------------
  //

  public void analyze(){
    double dt = botTime - topTime;
    // This simulates the finite resolution of the
    // detectors. Just use a simple Gaussian spread.
    // Could also add in systematic effects here such
    // as fixed offsets, different resolution for top
    // and bottom sensors, etc.

    dt += (int)(TimeResolution * ran.nextGaussian());

    recordData(dt);

    stop();
  }
  //---------------------------------------------------------
  public void run() {
    // Set at lower priority so that the animation will
    // be at top priority.

    analyzeThread.setPriority(Thread.NORM_PRIORITY - 1);

    // Do analysis when animation no busy.
    while (analyzeThread != null) {
      analyze();
    }
  }
  //---------------------------------------------------------
  // Display the message, data, data event and histogram
  // displays.

  public void paint(Graphics g){
    hist.graphIt();
  }
  //---------------------------------------------------------
  // Draw the sensors on the drop shoot

  public void draw(Graphics g){
    Color c = g.getColor();
    g.setColor(Color.green);
    g.drawLine(0,ySensorTop,shootWidth,ySensorTop);
    g.drawLine(0,ySensorBot,shootWidth,ySensorBot);
    g.setColor(c);
  }
  //---------------------------------------------------------
  public void recordData(double dataPt){
    hist.setData(dataPt);
  }
}

This code for the histogram chart is not discussed here:
Histogram.java, BarChart.java, NumericSet.java

 

Home Lectures Resources Index Contacts Students


Physics Simulations with JavaTM
KTH, Kurskod: 5A1418
Curator: Clark S. Lindsey