import java.applet.*; import java.awt.*; import sansmodels.SANSResolution; public class SANSPlan extends Applet { Font font = new Font("TimesRoman",Font.PLAIN,12); TextField lambdaField, sampleDetField, sampleApField, offsetField; TextField sampleApSampleField; Choice delLambdaChoice, numGuidesChoice, sourceApChoice; Choice positionChoice; Panel instPanel; Label[] instrumentLabels; Checkbox[] sansInstr; CheckboxGroup which; SANSResolution resolution = new SANSResolution(); TextArea results; int guides, instrumentChosen; double idmax, sampleAp_upper, d_upper, bs_factor, det_width; double offset, del_r, t1, t2, t3, DDet, aPixel, phi0, lambdaT; double l2r_lower, l2r_upper, lambda_lower, lambda_upper; double guide_width, l_gap, b, c2, S12; public void init() { //setLayout( new GridLayout(0,2) ); setLayout( new BorderLayout() ); setBackground(Color.white); instPanel = new Panel(); Label title = new Label("Instrument Configuration", Label.CENTER); Panel panel = new Panel(); Panel boxPanel = new Panel(); boxPanel.setLayout( new FlowLayout()); title.setFont(new Font("TimesRoman",Font.PLAIN,20)); add("North", title); add("Center", panel); GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); panel.setLayout(gridbag); which = new CheckboxGroup(); sansInstr = new Checkbox[3]; sansInstr[0] = new Checkbox("NG1, 8M", which, false); sansInstr[1] = new Checkbox("NG3, 30M", which, false); sansInstr[2] = new Checkbox("NG7, 30M", which, true); sansInstr[0].setFont(font); sansInstr[1].setFont(font); sansInstr[2].setFont(font); boxPanel.add(sansInstr[0]); boxPanel.add(sansInstr[1]); boxPanel.add(sansInstr[2]); c.ipadx = 5; c.weightx = 1.0; c.weighty = 1.0; c.gridwidth = 2; c.gridwidth = GridBagConstraints.REMAINDER; c.fill = GridBagConstraints.NONE; gridbag.setConstraints(boxPanel,c); panel.add(boxPanel); delLambdaChoice = new Choice(); delLambdaChoice.addItem("0.09"); delLambdaChoice.addItem("0.11"); delLambdaChoice.addItem("0.22"); delLambdaChoice.setFont(font); numGuidesChoice = new Choice(); numGuidesChoice.addItem("0"); numGuidesChoice.addItem("1"); numGuidesChoice.addItem("2"); numGuidesChoice.addItem("3"); numGuidesChoice.addItem("4"); numGuidesChoice.addItem("5"); numGuidesChoice.addItem("6"); numGuidesChoice.addItem("7"); numGuidesChoice.addItem("8"); numGuidesChoice.setFont(font); sourceApChoice = new Choice(); sourceApChoice.addItem("1.43"); sourceApChoice.addItem("2.22"); sourceApChoice.addItem("3.81"); sourceApChoice.setFont(font); positionChoice = new Choice(); positionChoice.addItem("Huber"); positionChoice.addItem("Chamber"); positionChoice.setFont(font); positionChoice.select(1); instPanel.setLayout( new GridLayout(0,2) ); instrumentLabels = new Label[9]; instrumentLabels[0] = new Label("Lambda (A): ", Label.RIGHT); instrumentLabels[1] = new Label("dLam/Lam (FWHM): ", Label.RIGHT); instrumentLabels[2] = new Label("Num guides: ", Label.RIGHT); instrumentLabels[3] = new Label("Source Ap (cm): ", Label.RIGHT); instrumentLabels[4] = new Label("Sample Position: ", Label.RIGHT); instrumentLabels[5] = new Label("Sample-Det (cm): ", Label.RIGHT); instrumentLabels[6] = new Label("Sample Ap (cm): ", Label.RIGHT); instrumentLabels[7] = new Label("Det offset (cm): ", Label.RIGHT); instrumentLabels[8] = new Label("SamAp-Sam (cm): ", Label.RIGHT); double[] resValues = resolution.getParameters(); resValues[1] = 0.22; resValues[3] = 1530.0; resValues[5] = 1.27; resValues[7] = 0.5; resValues[8] = 10.0; resolution.setParameters(resValues); instrumentChosen=2; idmax = 100; sampleAp_upper = 2.5; d_upper = 25.0; bs_factor = 1.05; det_width = 64.0; offset = 0.0; del_r = 0.5; t1 = 0.63; t2 = 0.7; t3 = 0.75; DDet = 0.5; aPixel = 0.5; phi0 = 1.82e13; lambdaT = 6.05; l2r_lower = 100.0; l2r_upper = 1531.0; lambda_lower = 4.0; lambda_upper = 20.0; guide_width = 5.0; l_gap = 188.0; b = 0.04472; c2 = 0.04504; S12 = 54.8; lambdaField = new TextField(String.valueOf(resValues[0]),8); lambdaField.setFont(font); sampleDetField = new TextField(String.valueOf(resValues[3]),8); sampleDetField.setFont(font); sampleApField = new TextField(String.valueOf(resValues[5]),8); sampleApField.setFont(font); offsetField = new TextField("0.0",8); offsetField.setFont(font); sampleApSampleField = new TextField(String.valueOf(resValues[8]),8); sampleApSampleField.setFont(font); for(int i=0;i<9;i++) { instrumentLabels[i].setFont(font); } instPanel.add(instrumentLabels[0]); instPanel.add(lambdaField); instPanel.add(instrumentLabels[1]); instPanel.add(delLambdaChoice); instPanel.add(instrumentLabels[2]); instPanel.add(numGuidesChoice); instPanel.add(instrumentLabels[3]); instPanel.add(sourceApChoice); instPanel.add(instrumentLabels[4]); instPanel.add(positionChoice); instPanel.add(instrumentLabels[5]); instPanel.add(sampleDetField); instPanel.add(instrumentLabels[6]); instPanel.add(sampleApField); instPanel.add(instrumentLabels[7]); instPanel.add(offsetField); instPanel.add(instrumentLabels[8]); instPanel.add(sampleApSampleField); results = new TextArea(17,45); results.setFont(font); results.setEditable(false); c.weightx=0.0; c.weighty=0.0; c.gridheight=1; c.gridwidth=1; c.fill = GridBagConstraints.HORIZONTAL; c.anchor = GridBagConstraints.NORTH; gridbag.setConstraints(instPanel,c); panel.add(instPanel); c.gridwidth = GridBagConstraints.REMAINDER; gridbag.setConstraints(results,c); panel.add(results); writeOutput(); validate(); } public void writeOutput() { double[] resValues = resolution.getParameters(); double sampleAp = 1.27; try { sampleAp = Double.valueOf(sampleApField.getText()).doubleValue(); } catch (NumberFormatException exc) { } if (sampleAp < 0.0) { sampleAp = 0.00; sampleApField.setText(String.valueOf(sampleAp)); } if (sampleAp > sampleAp_upper) { sampleAp = sampleAp_upper; sampleApField.setText(String.valueOf(sampleAp)); } try { offset = Double.valueOf(offsetField.getText()).doubleValue(); } catch (NumberFormatException exc) { } if (offset > d_upper) { offset = d_upper; offsetField.setText(String.valueOf(d_upper)); } double sampleDet = 1.0; try { sampleDet = Double.valueOf(sampleDetField.getText()).doubleValue(); } catch (NumberFormatException exc) { } if (sampleDet < l2r_lower) { sampleDet = l2r_lower; sampleDetField.setText(String.valueOf(sampleDet)); } if (sampleDet >= l2r_upper) { sampleDet = l2r_upper - 1.0; sampleDetField.setText(String.valueOf(sampleDet)); } double lambda = 0.0; try { lambda = Double.valueOf(lambdaField.getText()).doubleValue(); } catch (NumberFormatException exc) { } if (lambda <= lambda_lower) { lambda = lambda_lower; lambdaField.setText(String.valueOf(lambda)); } if (lambda >= lambda_upper) { lambda = lambda_upper; lambdaField.setText(String.valueOf(lambda)); } double apOff = 10.0; try { apOff = Double.valueOf(sampleApSampleField.getText()).doubleValue(); } catch (NumberFormatException exc) { } if (apOff < 0.0) { apOff = 0.0; sampleApSampleField.setText(String.valueOf(apOff)); } double lambdaWidth = Double.valueOf(delLambdaChoice.getSelectedItem()).doubleValue(); double sourceAp = Double.valueOf(sourceApChoice.getSelectedItem()).doubleValue(); double L1 = 450; double L2S = 360.0; double L2 = L2S + apOff; double bs = 0.0; guides = Integer.parseInt(numGuidesChoice.getSelectedItem()); double pos_table = (double)positionChoice.getSelectedIndex(); double[] stopSizes; if(instrumentChosen == 0) { stopSizes = new double[1]; stopSizes[0] = 5.72; } else { stopSizes = new double[4]; stopSizes[0] = 2.54; stopSizes[1] = 5.08; stopSizes[2] = 7.62; stopSizes[3] = 10.16; L1 = 1632.0 - 155.0*(double)guides - S12*(1.0-pos_table) - apOff; L2S = sampleDet + S12*(1.0-pos_table); L2 = L2S + apOff; } double d1 = sourceAp*L2/L1; double d2 = sampleAp*(L1+L2)/L1; double bh = d1+d2; double umbra = Math.abs(d1-d2); double bv = bh + 1.25e-8*(L1+L2)*L2*lambda*lambda*lambdaWidth; double bm; if ( bs_factor*bh > bv) { bm = bs_factor*bh; } else { bm = bv; } int useStop = -1; for(int i=stopSizes.length-1;i>=0;i--) { if(bm < stopSizes[i]) useStop = i; } if(useStop == -1) { results.setText("Beam is too large for the available beamstops!"); return; } else { bs = stopSizes[useStop]; } resValues[0] = lambda; resValues[1] = lambdaWidth; resValues[2] = L1/100.0; resValues[3] = L2/100.0; resValues[4] = sourceAp*10.0; resValues[5] = sampleAp*10.0; resValues[6] = bs*10.0; resValues[7] = DDet; resValues[8] = apOff; resolution.setParameters(resValues); double qmin = (Math.PI/lambda) *( bs + DDet + aPixel) / L2S; double qmaxV = 4.0*Math.PI/lambda *Math.sin(0.5*Math.atan(0.5*det_width/L2S)); double qmaxH = 4.0*Math.PI/lambda *Math.sin(0.5*Math.atan((0.5*det_width+offset)/L2S)); double radial = Math.sqrt(0.25*det_width*det_width + (0.5*det_width+offset)*(0.5*det_width+offset)); double qmax = 4.0*Math.PI/lambda*Math.sin(0.5*Math.atan(radial/L2S)); double sigmaQmin = resolution.getResolution(qmin)[0]; sigmaQmin *= 100.0/qmin; double sigmaQmax = resolution.getResolution(qmax)[0]; sigmaQmax *= 100.0/qmax; double alpha = (sourceAp+sampleAp)/(2.0*L1); double f = l_gap * alpha / (2.0* guide_width); double t4 = (1.0-f)*(1.0-f); double t5 = Math.exp((double)guides * Math.log(0.96)); double t6 = 1.0 - lambda *( b - (double)guides/8.0*(b-c2)); double as = Math.PI/4.0 *sampleAp*sampleAp; double t = t1*t2*t3*t4*t5*t6; double d2Phi = phi0/2.0/Math.PI*Math.exp(4.0*Math.log(lambdaT/lambda)) * Math.exp(-1.0*lambdaT*lambdaT/lambda/lambda); double solid_angle = Math.PI/4.0*sourceAp*sourceAp/L1/L1; double intensity = as*d2Phi*lambdaWidth*solid_angle * t; if (instrumentChosen == 0) intensity = 1.0; double num_pixels_beam = Math.PI/4.0*0.25*(sampleAp+bh)*(sampleAp+bh) /aPixel/aPixel; double id = intensity/num_pixels_beam; double atten; if(id <= idmax) { atten = 1.0; } else { atten = idmax/id; } double af = 0.498 + 0.0792*lambda - 1.66e-3*lambda*lambda; double nr = -1.0*Math.log(atten)/af; int num_atten = (int)nr + 1; if (num_atten > 6) num_atten = 7 + (num_atten-6)/2; double sa_det = 64.0*64.0/L2S/L2S; double cd_h2O = 1.0*0.1*0.5*0.6*intensity*sa_det; String positionText = "The Huber table"; if(pos_table == 1) positionText = "The sample chamber"; //assemble text of result. String whichInstr = which.getCurrent().getLabel(); String outputString = "This configuration for " + whichInstr +" yields:\n"; outputString += (new Format("Lambda: %4.1f").format(lambda)) +" A " +(new Format("dLam/Lam: %4.2f").format(lambdaWidth)) +" (FWHM)\n"; outputString += (new Format("Number of guides: %2d").format(guides)) +"\n"; outputString += (new Format("Intensity at sample: %9.4G").format(intensity)) +" Counts/sec\n"; outputString += (new Format("Detector Offset: %7.2f").format(offset)) +" cm\n"; outputString += (new Format("Total Qmin: %9.4G").format(qmin)) +" A^-1 " +(new Format("Resolution: %9.4f").format(sigmaQmin))+"%" +"\n"; outputString += (new Format("Total Qmax: %9.4G").format(qmax)) +" A^-1 " +(new Format("Resolution: %9.4f").format(sigmaQmax))+"%" +"\n"; outputString += (new Format("Horizontal Qmax: %9.4G").format(qmaxH)) +" A^-1" +"\n"; outputString += (new Format("Vertical Qmax: %9.4G").format(qmaxV)) +" A^-1" +"\n"; outputString += (new Format("Beam diameter: %7.2f").format(bm)) +" cm " +(new Format("Umbra/Penumbra: %4.3f").format(umbra/bh)) +"\n"; outputString += (new Format("Beamstop diameter: %7.2f").format(bs)) +" cm, (" +(new Format("%4.2f").format((bs/2.54))) +" in)\n"; outputString += (new Format("Source aperture diameter: %7.2f").format(sourceAp)) +" cm\n"; outputString += (new Format("Sample Aperture diameter: %7.2f").format(sampleAp)) +" cm\n"; outputString += positionText+" is set as the sample position.\n"; outputString += "Source aperture to sample aperture distance:\n"; outputString += (new Format("%7.1f").format(L1)) +" cm\n"; outputString += "Sample aperture to sample distance:\n"; outputString += (new Format("%7.1f").format(apOff)) +" cm\n"; outputString += "Sample aperture to detector distance:\n"; outputString += (new Format("%7.1f").format(L2)) +" cm\n"; outputString += "Sample to detector distance:\n"; outputString += (new Format("%7.1f").format(sampleDet)) +" cm\n"; outputString += (new Format("Attenuator transmission: %8.4G").format(atten)) +"\n"; outputString += (new Format("(Position number: %2d").format(num_atten)) +" for transmission runs.)" +"\n"; outputString += (new Format("Countrate through 1mm of water: %9.3G").format(cd_h2O)) +" Counts/sec"; results.setText(outputString); validate(); } public void updateInstrument() { String whichInstr = which.getCurrent().getLabel(); //calculate source to sample distance double sampleDet = 360.0; try { sampleDet = Double.valueOf(sampleDetField.getText()).doubleValue(); } catch (NumberFormatException exc) { } if (sampleDet == 0.0) sampleDet = 360.0; if( whichInstr.equalsIgnoreCase("NG1, 8M") ) { instrumentChosen = 0; DDet = 2.3; aPixel = 0.5; phi0 = 1.82e13; lambdaT = 6.05; l2r_lower = 203.0; l2r_upper = 360.5; lambda_lower = 5.0; guide_width = 5.0; l_gap = 188.0; b = 0.04472; c2 = 0.04504; S12 = 0.0; positionChoice.enable(false); updateDelLambda(); updateNumGuides(); updateSourceAp(); } else if( whichInstr.equalsIgnoreCase("NG3, 30M") ) { instrumentChosen = 1; DDet = 1.0; aPixel = 1.0; phi0 = 2.58e13; lambdaT = 5.70; l2r_lower = 130.0; l2r_upper = 1317.0; lambda_lower = 4.0; guide_width = 6.0; l_gap = 100.0; b = 0.0465; c2 = 0.0438; S12 = 54.8; positionChoice.enable(true); updateDelLambda(); updateNumGuides(); updateSourceAp(); } else { instrumentChosen = 2; DDet = 0.5; aPixel = 0.5; phi0 = 1.82e13; lambdaT = 6.05; l2r_lower = 100.0; l2r_upper = 1531.0; lambda_lower = 4.0; guide_width = 5.0; l_gap = 188.0; b = 0.04472; c2 = 0.04504; S12 = 54.8; positionChoice.enable(true); updateDelLambda(); updateNumGuides(); updateSourceAp(); } if (sampleDet <= l2r_lower) { sampleDet = l2r_lower; sampleDetField.setText(String.valueOf(sampleDet)); } if (sampleDet >= l2r_upper) { sampleDet = l2r_upper - 1.0; sampleDetField.setText(String.valueOf(sampleDet)); } validate(); } public void updateSourceAp() { switch(instrumentChosen) { case 0: numGuidesChoice.select(0); instPanel.remove(sourceApChoice); sourceApChoice.invalidate(); sourceApChoice = new Choice(); sourceApChoice.addItem("2.7"); sourceApChoice.setFont(font); instPanel.add(sourceApChoice,7); sourceApChoice.validate(); break; case 1: guides = Integer.parseInt(numGuidesChoice.getSelectedItem()); switch(guides) { case 0 : instPanel.remove(sourceApChoice); sourceApChoice.invalidate(); sourceApChoice = new Choice(); sourceApChoice.addItem("1.43"); sourceApChoice.addItem("2.54"); sourceApChoice.addItem("3.81"); sourceApChoice.setFont(font); instPanel.add(sourceApChoice,7); sourceApChoice.validate(); break; case 7 : instPanel.remove(sourceApChoice); sourceApChoice.invalidate(); sourceApChoice = new Choice(); sourceApChoice.addItem("2.5"); sourceApChoice.addItem("5.0"); sourceApChoice.setFont(font); instPanel.add(sourceApChoice,7); sourceApChoice.validate(); break; default : instPanel.remove(sourceApChoice); sourceApChoice.invalidate(); sourceApChoice = new Choice(); sourceApChoice.addItem("5.0"); sourceApChoice.setFont(font); instPanel.add(sourceApChoice,7); sourceApChoice.validate(); break; } break; case 2: guides = Integer.parseInt(numGuidesChoice.getSelectedItem()); switch(guides) { case 0 : instPanel.remove(sourceApChoice); sourceApChoice.invalidate(); sourceApChoice = new Choice(); sourceApChoice.addItem("1.43"); sourceApChoice.addItem("2.22"); sourceApChoice.addItem("3.81"); sourceApChoice.setFont(font); instPanel.add(sourceApChoice,7); sourceApChoice.validate(); break; default : instPanel.remove(sourceApChoice); sourceApChoice.invalidate(); sourceApChoice = new Choice(); sourceApChoice.addItem("5.08"); sourceApChoice.setFont(font); instPanel.add(sourceApChoice,7); sourceApChoice.validate(); break; } break; } this.validate(); } public void updateDelLambda() { switch(instrumentChosen) { case 0: instPanel.remove(delLambdaChoice); delLambdaChoice.invalidate(); delLambdaChoice = new Choice(); delLambdaChoice.addItem("0.25"); delLambdaChoice.setFont(font); instPanel.add(delLambdaChoice,3); delLambdaChoice.validate(); break; case 1: instPanel.remove(delLambdaChoice); delLambdaChoice.invalidate(); delLambdaChoice = new Choice(); delLambdaChoice.addItem("0.11"); delLambdaChoice.addItem("0.15"); delLambdaChoice.addItem("0.34"); delLambdaChoice.setFont(font); instPanel.add(delLambdaChoice,3); delLambdaChoice.validate(); break; case 2: instPanel.remove(delLambdaChoice); delLambdaChoice.invalidate(); delLambdaChoice = new Choice(); delLambdaChoice.addItem("0.09"); delLambdaChoice.addItem("0.11"); delLambdaChoice.addItem("0.22"); delLambdaChoice.setFont(font); instPanel.add(delLambdaChoice,3); delLambdaChoice.validate(); break; } validate(); } public void updateNumGuides() { switch(instrumentChosen) { case 0: instPanel.remove(numGuidesChoice); numGuidesChoice.invalidate(); numGuidesChoice = new Choice(); numGuidesChoice.addItem("0"); numGuidesChoice.setFont(font); instPanel.add(numGuidesChoice,5); numGuidesChoice.validate(); break; case 1: instPanel.remove(numGuidesChoice); numGuidesChoice.invalidate(); numGuidesChoice = new Choice(); numGuidesChoice.addItem("0"); numGuidesChoice.addItem("1"); numGuidesChoice.addItem("2"); numGuidesChoice.addItem("3"); numGuidesChoice.addItem("4"); numGuidesChoice.addItem("5"); numGuidesChoice.addItem("7"); numGuidesChoice.addItem("8"); numGuidesChoice.setFont(font); instPanel.add(numGuidesChoice,5); numGuidesChoice.validate(); break; case 2: instPanel.remove(numGuidesChoice); numGuidesChoice.invalidate(); numGuidesChoice = new Choice(); numGuidesChoice.addItem("0"); numGuidesChoice.addItem("1"); numGuidesChoice.addItem("2"); numGuidesChoice.addItem("3"); numGuidesChoice.addItem("4"); numGuidesChoice.addItem("5"); numGuidesChoice.addItem("6"); numGuidesChoice.addItem("7"); numGuidesChoice.addItem("8"); numGuidesChoice.setFont(font); instPanel.add(numGuidesChoice,5); numGuidesChoice.validate(); break; } validate(); } public boolean action(Event e, Object a) { if (e.target instanceof Choice) { if(e.target.equals(numGuidesChoice)) { updateSourceAp(); } } if (e.target instanceof Checkbox) { updateInstrument(); } writeOutput(); return true; } }