import java.applet.*; import java.awt.*; import java.awt.image.MemoryImageSource; public class spectrometer extends Applet implements Runnable { Thread m_spectrometer = null; private Graphics offScreenGraphics; private Image offScreen; private Image box, neg_box, gas_cell, neg_gas_cell, lamp, neg_lamp; private int rainbowPixels[] = new int[400]; private double absorbance[] = new double[400]; private Color beamColor, absdColor; private boolean lightOn = true; private boolean running = false; private boolean paused = false; private Button Light = new Button("Light"); private Button Start = new Button("Start"); private Button Pause = new Button("Pause"); private Button Stop = new Button("Stop"); private Label blank1 = new Label(" ",Label.CENTER); private Label blank2 = new Label(" ",Label.CENTER); private Label blank3 = new Label(" ",Label.CENTER); private Label blank4 = new Label("Stopped",Label.CENTER); private Label blank5 = new Label(" ",Label.CENTER); private Label blank6 = new Label(" ",Label.CENTER); private Panel Controls = new Panel(); public spectrometer() { } public String getAppletInfo() { return "Name: spectrometer\r\n" + "Author: Dr. P. Bird\r\n" + "Copyright, September 1997\r\n" + "Created with Microsoft Visual J++ Version 1.0"; } public void init() { // resize(630, 310); setLayout(new BorderLayout()); Controls.setLayout(new GridLayout(1,8,0,0)); Controls.add(Light); Controls.add(blank3); Controls.add(Start); Controls.add(Pause); Controls.add(Stop); Controls.add(blank4); Controls.add(blank5); Light.enable(); Start.disable(); Pause.disable(); Stop.disable(); add("South",Controls); generateRainbow(); generateSpectrum(); offScreen = createImage(630,250); offScreenGraphics = offScreen.getGraphics(); MediaTracker tracker = new MediaTracker(this); //Get .gifs box = getImage(getDocumentBase(), "box.gif"); tracker.addImage(box,1); neg_box = getImage(getDocumentBase(), "neg-box.gif"); tracker.addImage(neg_box,2); gas_cell = getImage(getDocumentBase(), "gas-cell.gif"); tracker.addImage(gas_cell,3); neg_gas_cell = getImage(getDocumentBase(), "neg-gas-cell.gif"); tracker.addImage(neg_gas_cell,4); lamp = getImage(getDocumentBase(), "lamp.gif"); tracker.addImage(lamp,5); neg_lamp = getImage(getDocumentBase(), "neg-lamp.gif"); tracker.addImage(neg_lamp,6); try { tracker.waitForAll(); if (tracker.isErrorAny()) { showStatus("Error loading the images"); stop(); } } catch(InterruptedException e) { showStatus("InterruptedException (Tracker)"); stop(); } } // calculate the virtual spectrum public void generateRainbow() { int red = 0; int green = 0; int blue = 0; for (int i = 0; i < 400; i++) //construct a rainbow { if (i < 60) { red = (int)(255.0D*0.4D* (0.5D - 0.5D*Math.cos(Math.PI*(double)(i)/55.0D)) ); green = 0; blue = (int)(255.0D* (0.5D - 0.5D*Math.cos(Math.PI*(double)(i)/110.0D)) ); } if ((i >= 60) & (i < 120)) { red = (int)(255.0D*0.4D* (0.5D*Math.cos(Math.PI*(double)(i - 60)/55.0D) + 0.5D) ); green = (int)(255.0D* (0.5D - 0.5D*Math.cos(Math.PI*(double)(i - 60)/110.0D)) ); blue = (int)(255.0D* (0.5D - 0.5D*Math.cos(Math.PI*(double)(i)/110.0D)) ); } if ((i >= 120) & (i < 180)) { red = 0; green = (int)(255.0D* (0.5D - 0.5D*Math.cos(Math.PI*(double)(i - 60)/110.0D)) ); blue = (int)(255.0D* (0.5D*Math.cos(Math.PI*(double)(i - 110)/110.0D) + 0.5D) ); } if ((i >= 180) & (i < 240)) { red = (int)(255.0D* (0.5D - 0.5D*Math.cos(Math.PI*(double)(i - 180)/110.0D)) ); green = 255; blue = (int)(255.0D* (0.5D*Math.cos(Math.PI*(double)(i - 110)/110.0D) + 0.5D) ); } if ((i >= 240) & (i < 290)) { red = (int)(255.0D* (0.5D - 0.5D*Math.cos(Math.PI*(double)(i - 180)/110.0D)) ); green = (int)(255.0D* (0.5D*Math.cos(Math.PI*(double)(i - 240)/110.0D) + 0.5D) ); } if ((i >= 290) & (i < 350)) { red = (int)(255.0D* (0.5D*Math.cos(Math.PI*(double)(i - 290)/110.0D) + 0.5D) ); green = (int)(255.0D* (0.5D*Math.cos(Math.PI*(double)(i - 240)/110.0D) + 0.5D) ); blue = 0; } if ((i >= 350) & (i < 400)) { red = (int)(255.0D* (0.5D*Math.cos(Math.PI*(double)(i - 290)/110.0D) + 0.5D) ); green = 0; blue = 0; } rainbowPixels[i] = 255 << 24 | red << 16 | green << 8 | blue; } } public void generateSpectrum() { double x; for (int i = 0; i < 400; i++) { x = i; absorbance[i] = //two Gaussians 0.8*Math.exp(-(6-x/20.0)*(6-x/20.0)) + 0.5*Math.exp(-(13.0-x/20.0)*(13.0-x/20.0)); } } public void destroy() { } public void paint(Graphics g) { } public synchronized void update(Graphics g) { g.drawImage(offScreen,0,0,null); } public void start() { if (m_spectrometer == null) { m_spectrometer = new Thread(this); m_spectrometer.start(); } } public void stop() { if (m_spectrometer != null) { m_spectrometer.stop(); m_spectrometer = null; } } public void run() { int index=40; int j; double rd, gr, bl; double rd_absd, gr_absd, bl_absd; double transmission; int plotter_x1 = 470, plotter_x2 = 540, plotter_y = 130; int graph_x = 0, graph_y = 0; int w = 110; int h = 60; int[] pixels = new int[w * h]; while (true) { try { if (!running) //refresh while waiting { drawApparatus(); Thread.sleep(20); pen(535,130,540,470,130,false); index = 40; } while (!running) { Thread.sleep(100); repaint(); } beamColor = new Color(rainbowPixels[index]); rd = beamColor.getRed(); gr = beamColor.getGreen(); bl = beamColor.getBlue(); offScreenGraphics.setColor(beamColor); offScreenGraphics.fillRect(130,107,70,11); //draw incident beam if (lightOn) offScreenGraphics.setColor(Color.black); else offScreenGraphics.setColor(Color.white); offScreenGraphics.drawLine(192,107,192,117); //patches cell (left) for (int i = 0; i < 36; i++) //draw beam in sample { transmission = 1.0 - (double)(i)*(absorbance[index])/36.0; rd_absd = rd*transmission; gr_absd = gr*transmission; bl_absd = bl*transmission; absdColor = new Color (255 << 24 | (int)rd_absd << 16 | (int)gr_absd << 8 | (int)bl_absd); offScreenGraphics.setColor(absdColor); offScreenGraphics.drawLine(i+200,107,i+200,117); } offScreenGraphics.fillRect(236,107,60,11); //draw exit beam if (lightOn) offScreenGraphics.setColor(Color.black); else offScreenGraphics.setColor(Color.white); offScreenGraphics.drawLine(229,107,229,117); //patch cell (right) // repaint(130,107,266,11); repaint(); if(lightOn) //re-draw lamp area { offScreenGraphics.setColor(Color.white); //this code is not called offScreenGraphics.fillRect(420,0,256,205); //(no scan with light on) offScreenGraphics.drawImage(lamp,370,0,null); offScreenGraphics.setColor(Color.black); offScreenGraphics.drawLine(400,133,450,150); // wire to recorder } else { offScreenGraphics.drawImage(neg_lamp,370,0,null); offScreenGraphics.setColor(Color.black); offScreenGraphics.drawLine(430,143,450,150); //wire to recorder offScreenGraphics.setColor(Color.white); offScreenGraphics.drawLine(400,133,430,143); } for (int i = 36; i <= index; i++) //plot curve so far { offScreenGraphics.setColor(Color.red); j = (i-36)/5; graph_x = 535-(int)(absorbance[i]*80.0) - 15*j/45; graph_y = 130+j; plotter_y = graph_y; plotter_x1 = 540 - 15*j/60; plotter_x2 = 470 - 37*j/60; offScreenGraphics.drawLine (graph_x,graph_y,graph_x,graph_y); //plot point } pen(graph_x,graph_y, plotter_x1, plotter_x2, plotter_y,true); //plot pen repaint(370,0,260,200); Thread.sleep(50); //controls plot speed if (running & !paused) index++; if (index == 340) { index = 40; blank4.setText("Restarting"); // for (int k = 60; k >= 0; k--) //run pen back to beginning { graph_y = 130+k; graph_x = 535 - 15*k/45; plotter_y = graph_y; plotter_x1 = 540 - 15*k/60; plotter_x2 = 470 - 37*k/60; offScreenGraphics.drawImage(neg_lamp,370,0,null); offScreenGraphics.setColor(Color.black); offScreenGraphics.drawLine(430,143,450,150); //wire to recorder offScreenGraphics.setColor(Color.white); offScreenGraphics.drawLine(400,133,430,143); pen(graph_x, graph_y, plotter_x1, plotter_x2, plotter_y,false); repaint(370,0,200,260); Thread.sleep(30); //controls flyback speed } Thread.sleep(500); blank4.setText("Running"); } } catch (InterruptedException e) { stop(); } } } private void drawApparatus() { if (lightOn) { offScreenGraphics.setColor(Color.white); //draw gif's offScreenGraphics.fillRect(0,0,629,249); offScreenGraphics.drawImage(box,10,70,null); offScreenGraphics.drawImage(gas_cell,180,80,null); offScreenGraphics.drawImage(box,280,70,null); offScreenGraphics.drawImage(lamp,370,0,null); offScreenGraphics.setColor(Color.black); offScreenGraphics.drawLine(400,133,450,150); // wire to recorder offScreenGraphics.drawLine(129,107,129,119); offScreenGraphics.drawLine(130,106,130,118); offScreenGraphics.drawLine(131,105,131,117); offScreenGraphics.setColor(Color.green.darker().darker()); offScreenGraphics.drawString("Source",55,165); //labels offScreenGraphics.drawString("Sample",194,153); offScreenGraphics.drawString("Detector",320,165); offScreenGraphics.drawString("Recorder",460,220); offScreenGraphics.setColor(Color.gray); offScreenGraphics.drawString("Copyright 1998, Peter H. Bird",10,235); offScreenGraphics.setColor(Color.black); } else { offScreenGraphics.setColor(Color.black); offScreenGraphics.fillRect(0,0,629,249); offScreenGraphics.drawImage(neg_box,10,70,null); //draw gif's offScreenGraphics.drawImage(neg_gas_cell,180,80,null); offScreenGraphics.drawImage(neg_box,280,70,null); offScreenGraphics.drawImage(neg_lamp,370,0,null); offScreenGraphics.setColor(Color.black); offScreenGraphics.drawLine(129,107,129,119); offScreenGraphics.drawLine(130,106,130,118); offScreenGraphics.drawLine(131,105,131,117); offScreenGraphics.drawLine(430,143,450,150); //wire to recorder offScreenGraphics.setColor(Color.white); offScreenGraphics.drawLine(400,133,430,143); } } public synchronized boolean action(Event evt, Object obj) { String sButtonLabel; Object oTarget = evt.target; if (oTarget instanceof Button) //Only handles buttons clicked { Button buttonHit = (Button)oTarget; sButtonLabel = buttonHit.getLabel(); if (sButtonLabel.compareTo("Light") == 0) { lightOn = !lightOn; //light button if(lightOn) { running = false; paused = false; Start.disable(); Stop.disable(); Pause.disable(); blank4.setText("Stopped"); } else { running = false; paused = false; Start.enable(); Stop.disable(); Pause.disable(); blank4.setText("Stopped"); } drawApparatus(); pen(535,130,540,470,130,false); repaint(); } if (sButtonLabel.compareTo("Start") == 0) //start button { running = true; paused = false; Start.disable(); Pause.enable(); Stop.enable(); blank4.setText("Running"); } if (sButtonLabel.compareTo("Pause") == 0) //pause button { paused = true; Start.enable(); Pause.disable(); Stop.enable(); blank4.setText("Paused"); } if (sButtonLabel.compareTo("Stop") == 0) //stop button { running = false; paused = false; Start.enable(); Pause.disable(); Stop.disable(); drawApparatus(); repaint(); blank4.setText("Stopped"); } return true; } return true; // return super.action(evt, obj); } private void pen(int x, int y, int px1, int px2, int py, boolean pp) { offScreenGraphics.setColor(Color.black); //draw pen carrier offScreenGraphics.drawLine(px1,py-2,px2,py-2); offScreenGraphics.drawLine(px1,py-3,px2,py-3); offScreenGraphics.drawLine(px1,py,px1,py-2); offScreenGraphics.drawLine(px2,py,px2,py-2); offScreenGraphics.drawLine(x-1,y-2,x-1,y-11); //draw pen if (pp) offScreenGraphics.drawLine(x,y,x,y-12); else offScreenGraphics.drawLine(x,y-2,x,y-12); offScreenGraphics.drawLine(x+1,y-2,x+1,y-11); } }