// Simulator of hydrostatic pressure across a HOH permiable membrane // R. Bowen 5/97 import java.awt.*; public class hydrostatic extends java.applet.Applet { LabCanvas lab; TextField textR = new TextField("0."), textL = new TextField("0."); Label labelR = new Label("", Label.CENTER), labelL = new Label("", Label.CENTER); Choice chRSolute = new Choice(), chLSolute = new Choice(); Choice chRConc = new Choice(), chLConc = new Choice(); Button btRun = new Button(" Run "); public void init() { setBackground(Color.white); setLayout(new BorderLayout()); Color colorL = new Color(255,255,192); Color colorR = new Color(192,255,192); chLSolute.setBackground(colorL); chLConc.setBackground(colorL); textL.setBackground(colorL); labelL.setBackground(colorL); chRSolute.setBackground(colorR); chRConc.setBackground(colorR); textR.setBackground(colorR); labelR.setBackground(colorR); chLSolute.addItem("NaCl (58 g/mole)"); chLSolute.addItem("sucrose (342 g/mole)"); chLSolute.addItem("albumin (66000 g/mole)"); chRSolute.addItem("NaCl (58 g/mole)"); chRSolute.addItem("sucrose (342 g/mole)"); chRSolute.addItem("albumin (66000 g/mole)"); chLConc.addItem("grams/liter"); chLConc.addItem("molar"); chRConc.addItem("grams/liter"); chRConc.addItem("molar"); Panel rPanel = new Panel(); rPanel.setLayout(new GridLayout(1,2)); rPanel.add(textR); rPanel.add(chRConc); Panel lPanel = new Panel(); lPanel.setLayout(new GridLayout(1,2)); lPanel.add(textL); lPanel.add(chLConc); Panel rightPanel = new Panel(); rightPanel.setLayout(new GridLayout(3,1)); rightPanel.add(chRSolute); rightPanel.add(rPanel); rightPanel.add(labelR); Panel leftPanel = new Panel(); leftPanel.setLayout(new GridLayout(3,1)); leftPanel.add(chLSolute); leftPanel.add(lPanel); leftPanel.add(labelL); Panel bottom = new Panel(); bottom.setLayout(new FlowLayout()); bottom.add(leftPanel); bottom.add(btRun); bottom.add(rightPanel); lab = new LabCanvas(400,270,this.size().width); add("South", bottom); add("North", lab); } public boolean action(Event evt, Object arg) { if (arg.equals(" Run ")) { btRun.setLabel("Reset"); flow(); } else if (arg.equals("Reset")) { labelR.setText(""); labelL.setText(""); btRun.setLabel(" Run "); lab.reset(); } return true; } private String dString(double d, int n) { // converts double to string with max of n digits after decimal point String s = Double.toString(d); String stemp; int length = s.length(); int pindex = s.indexOf('.'); int eindex = s.indexOf('E'); if (eindex == -1) eindex = s.indexOf('e'); if (eindex != -1) { stemp = s.substring(0, Math.min(pindex+3,length)) + s.substring(eindex); s = stemp; } else if (d == 0.) s = "0.0"; else if (d >= 1.0) s = s.substring(0, Math.min(pindex+3,length)); else { // convert to sci notation int i = pindex + 1; while (i < length && s.charAt(i) == '0') ++i; int exponent = i - pindex; stemp = s.substring(i,i+1) + "."; ++i; for (int k = 0; k < n && i < length; ++k) { stemp += s.charAt(i); ++i; } stemp += "E-" + Integer.toString(exponent); s = stemp; } return s; } public void flow() { double concR, concL, molarityR = 0., molarityL = 0., mw = -1; int iR = 1, iL = 1, index; int cmHOH; String moleculeR, moleculeL; boolean flow_to_right, badLeft = false, badRight = false; try { concR = Double.valueOf(textR.getText()).doubleValue(); if (concR < 0.) badRight = true; else { index = chRSolute.getSelectedIndex(); if (index == 0) mw = 58.44; else if (index == 1) mw = 342.3; else if (index == 2) mw = 66000.; if (chRConc.getSelectedItem().equals("molar")) { molarityR = concR; labelR.setText(dString(molarityR * mw, 2) + " g/l"); } else { molarityR = concR/mw; labelR.setText(dString(molarityR, 2) + " M"); } } } catch (NumberFormatException e) { badRight = true; } if (badRight) labelR.setText("Bad value"); try { concL = Double.valueOf(textL.getText()).doubleValue(); if (concL < 0.) badLeft = true; else { index = chLSolute.getSelectedIndex(); if (index == 0) mw = 58.44; else if (index == 1) mw = 342.3; else if (index == 2) mw = 66000.; if (chLConc.getSelectedItem().equals("molar")) { molarityL = concL; labelL.setText(dString(molarityL * mw, 2) + " g/l"); } else { molarityL = concL/mw; labelL.setText(dString(molarityL, 2) + " M"); } } } catch (NumberFormatException e) { badLeft = true; } if (badLeft) labelL.setText("Bad value"); if (badRight || badLeft) return; if (chRSolute.getSelectedIndex() == 0) iR = 2; if (chLSolute.getSelectedIndex() == 0) iL = 2; System.out.println("About to execute"); lab.execute(molarityR, iR, molarityL, iL); } } class LabCanvas extends Canvas implements Runnable { int cmHOH, nLines, paintRow, xoffset; double molarityR, molarityL; double effect_molR, effect_molL; // effective molarity (1 except NaCl which is 2) String errorStr; boolean error = false; boolean running = false; boolean flow_to_right; Thread runner; LabCanvas(int width, int height, int applet_width) { resize(width, height); xoffset = (applet_width - width)/2; System.out.println("Offset = " + xoffset); } public void start() { if (runner == null) { runner = new Thread(this); runner.start(); } } public void stop() { if (runner != null) { runner.stop(); runner = null; } } public void run() { for (int i = 0; i < nLines; ++i) { paintRow = i; repaint(); try { Thread.sleep(50); } catch (InterruptedException e) { } } } public void execute(double molR, int iR, double molL, int iL) { effect_molR = (double) iR * molR; effect_molL = (double) iL * molL; // 1 molar dif == 23974.6 cm HOH pressure cmHOH = (int) (23974.6 * (effect_molR - effect_molL)); if (cmHOH < 0) { flow_to_right = false; cmHOH = -cmHOH; } else flow_to_right = true; if (cmHOH < 1) { errorStr = "Pressure < 1 cm water"; error = true; nLines = 0; } else if (cmHOH <= 10) nLines = (int) (((float) cmHOH)/0.1); else if (cmHOH <= 100) nLines = cmHOH; else if (cmHOH <= 1000) nLines = cmHOH/10; else if (cmHOH <= 10000) nLines = cmHOH/100; else { errorStr = "Pressure > 10000 cm !"; error = true; nLines = 0; } if (nLines != 0) { running = true; start(); } else repaint(); } public void reset() { running = false; stop(); repaint(); } public void update(Graphics g) { paint(g); } public void paint(Graphics g) { int rowY, xpos; String str; Font f = new Font("TimesRoman", Font.BOLD, 12); FontMetrics fm = g.getFontMetrics(f); g.setFont(f); if (error) { g.setColor(Color.red); xpos = (this.size().width - fm.stringWidth(errorStr))/2; // xpos = xoffset + 100 + ((200 - fm.stringWidth(errorStr))/2); g.drawString(errorStr, xpos, 115); error = false; return; } if (running) { if (paintRow == 0) { // graphically open the membrane g.setColor(Color.cyan); g.drawLine(xoffset+200,210,xoffset+200,260); g.setColor(Color.black); for (int k = 212; k < 260; k += 10) g.drawLine(xoffset+200,k,xoffset+200,k+5); //str = Double.toString(molarityL) + " M"; //xpos = xoffset + 50 + ((150 - fm.stringWidth(str))/2); //g.drawString(str,xpos,250); //str = Double.toString(molarityR) + " M"; //xpos = xoffset + 200 + ((150 - fm.stringWidth(str))/2); //g.drawString(str,xpos,250); } else if (paintRow == nLines - 1) { g.setColor(Color.blue); rowY = 110 - paintRow; g.drawLine(xoffset+101, rowY, xoffset+299, rowY); rowY = 110 + paintRow; g.drawLine(xoffset+101, rowY, xoffset+299, rowY); str = "P = " + Integer.toString(cmHOH) + " cm water"; xpos = xoffset + 100 + ((200 - fm.stringWidth(str))/2); g.drawString(str,xpos,115); } if (flow_to_right) { g.setColor(Color.cyan); rowY = 110 - paintRow; g.drawLine(xoffset+300, rowY, xoffset+350, rowY); g.setColor(Color.white); rowY = 110 + paintRow; g.drawLine(xoffset+50, rowY, xoffset+100, rowY); } else { g.setColor(Color.cyan); rowY = 110 - paintRow; g.drawLine(xoffset+50, rowY, xoffset+100, rowY); g.setColor(Color.white); rowY = 110 + paintRow; g.drawLine(xoffset+300, rowY, xoffset+350, rowY); } } else { // reset g.setColor(Color.white); g.fillRect(xoffset+0, 0, xoffset+this.size().width, this.size().height); g.setColor(Color.cyan); g.fillRect(xoffset+50, 210, 300, 50); g.fillRect(xoffset+50, 110, 50, 100); g.fillRect(xoffset+300 ,110, 50, 100); g.setColor(Color.black); g.drawLine(xoffset+49,5,xoffset+49,261); g.drawLine(xoffset+49,261,xoffset+351,261); g.drawLine(xoffset+351,261,xoffset+351,5); g.drawLine(xoffset+101,5,xoffset+101,209); g.drawLine(xoffset+101,209,xoffset+299,209); g.drawLine(xoffset+299,209,xoffset+299,5); g.drawLine(xoffset+200,210,xoffset+200,260); } } }