import javax.swing.*; import javax.swing.filechooser.*; import java.awt.event.*; import java.awt.*; import java.util.Map; import java.io.*; import javax.imageio.*; public class AsedraGui implements ActionListener, ItemListener { // Instance variables provide access to widgets or widget contents. JFrame frame; SpectrumGraph graph; JPanel southPanel, westPanel, eastPanel; JButton runAsedra; FileButton sampleButton, backgroundButton, energyCallibrationButton, fwhmCallibrationButton; ButtonGroup containerButtons; JRadioButton noContainerButton, ironContainerButton; int containerType = 0; JCheckBox denoiseCheck, tailingCheck; boolean denoiseSelected = true, tailingSelected = false; JTextField alphaField, tailingHeightField, tailingFwhmField; // Just creating an instance of AsedraGui. See the AsedraGui constructor for more details. public static void main (String[] args) { AsedraGui thisgui = new AsedraGui(); } // Create widgets and place them at appropriate positions in the window. public AsedraGui() { frame = new JFrame("ASEDRA - Advanced Synthetically Enhanced Detector Resolution Algorithm"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); graph = new SpectrumGraph(); frame.getContentPane().add(BorderLayout.CENTER,graph); southPanel = new JPanel(); southPanel.setLayout(new BorderLayout()); frame.getContentPane().add(BorderLayout.SOUTH,southPanel); runAsedra = new JButton("Run ASEDRA"); southPanel.add(BorderLayout.SOUTH,runAsedra); runAsedra.addActionListener(graph); westPanel = new JPanel(); southPanel.add(BorderLayout.WEST,westPanel); westPanel.setLayout(new BoxLayout(westPanel,BoxLayout.Y_AXIS)); eastPanel = new JPanel(); southPanel.add(BorderLayout.EAST,eastPanel); eastPanel.setLayout(new BoxLayout(eastPanel,BoxLayout.Y_AXIS)); sampleButton = new FileButton("Sample"); westPanel.add(sampleButton); backgroundButton = new FileButton("Background"); westPanel.add(backgroundButton); energyCallibrationButton = new FileButton("Energy Callibration"); westPanel.add(energyCallibrationButton); fwhmCallibrationButton = new FileButton("FWHM Callibration"); westPanel.add(fwhmCallibrationButton); containerButtons = new ButtonGroup(); noContainerButton = new JRadioButton("No Container"); noContainerButton.setSelected(true); noContainerButton.addActionListener(this); containerButtons.add(noContainerButton); westPanel.add(noContainerButton); ironContainerButton = new JRadioButton("Iron Container"); ironContainerButton.addActionListener(this); containerButtons.add(ironContainerButton); westPanel.add(ironContainerButton); denoiseCheck = new JCheckBox("Use ACHIP Denoising"); denoiseCheck.setSelected(true); denoiseCheck.addItemListener(this); eastPanel.add(denoiseCheck); JLabel alphaLabel = new JLabel("Alpha:"); alphaField = new JTextField("0.005"); alphaLabel.setLabelFor(alphaField); eastPanel.add(alphaLabel); eastPanel.add(alphaField); tailingCheck = new JCheckBox("Tailing Correction Needed"); tailingCheck.addItemListener(this); eastPanel.add(tailingCheck); JLabel tailingHeightLabel = new JLabel("Tailing Height Ratio:"); tailingHeightField = new JTextField("0.0"); tailingHeightLabel.setLabelFor(tailingHeightField); eastPanel.add(tailingHeightLabel); eastPanel.add(tailingHeightField); JLabel tailingFwhmLabel = new JLabel("Tailing FWHM:"); tailingFwhmField = new JTextField("10"); tailingFwhmLabel.setLabelFor(tailingFwhmField); eastPanel.add(tailingFwhmLabel); eastPanel.add(tailingFwhmField); frame.setSize(660,700); frame.setVisible(true); } // Record changes to container material radio buttons. public void actionPerformed(ActionEvent event) { Object source = event.getSource(); if(source == noContainerButton) { containerType = 0; } if(source == ironContainerButton) { containerType = 1; } } // Respond to selection/deselection of check boxes. public void itemStateChanged(ItemEvent e) { Object source = e.getItemSelectable(); boolean result = true; if(e.getStateChange() == ItemEvent.DESELECTED) { result = false; } if(source == denoiseCheck) { denoiseSelected = result; } else { tailingSelected = result; } } // First argument is program. Other arguments are command-line arguments. // Calls the program and waits for it to finish. No interaction. public static void callProgram(String... commandAndArguments) { try { ProcessBuilder launcher = new ProcessBuilder(); launcher.command(commandAndArguments); launcher.redirectErrorStream(true); Process p = launcher.start(); System.out.println("called process, starting to wait"); BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())); String line; while((line = br.readLine()) != null) { System.out.println(line); } p.waitFor(); System.out.println("finished waiting"); } catch(Exception e) { System.out.print("exception in callProgram: "); System.out.println(e); } } // Displays graphic output of ASEDRA code, using gnuplot for rendering. class SpectrumGraph extends JPanel implements ActionListener { public void paintComponent(Graphics g) { Image image; callProgram("bin\\pgnuplot","gnuplot-overlay.txt"); try { image = ImageIO.read(new File("sharpoverlay.png")); g.drawImage(image,3,4,this); } catch (Exception ex) { System.out.println("error reading graph"); } } // "Run ASEDRA" button was pushed. Time to create a process file, // run ASEDRA, and redisplay the graph. public void actionPerformed(ActionEvent event) { try { // Create "process.txt" input file for ASEDRA. BufferedWriter out = new BufferedWriter(new FileWriter(new File("process.txt"))); out.write("Sample File"); out.newLine(); out.write("\""+sampleButton.filePath()+"\""); out.newLine(); out.write("Background File"); out.newLine(); out.write("\""+backgroundButton.filePath()+"\""); out.newLine(); out.write("Background Significance Factor (1 for correct background subtraction)"); out.newLine(); out.write("1"); out.newLine(); out.write("Max Energy FWHM callibration table: file in \"position(keV) width(keV)\" format"); out.newLine(); out.write("\""+fwhmCallibrationButton.filePath()+"\""); out.newLine(); out.write("Low energy tailing: height ratio, FWHM(keV)"); out.newLine(); out.write( ! tailingSelected ? "0 1" : tailingHeightField.getText() + " " + tailingFwhmField.getText() ); out.newLine(); out.write("Energy Callibration Table"); out.newLine(); out.write("\""+energyCallibrationButton.filePath()+"\""); out.newLine(); out.write("Chi-squared threshold (negative value turns on adaptive chi filter)"); out.newLine(); out.write( denoiseSelected ? "-1" : "0" ); out.newLine(); out.write("Alpha for adaptive chi (max smoothing is 0.005, min smoothing is 0.1, recommended 0.05)"); out.newLine(); out.write( denoiseSelected ? alphaField.getText() : "0.05" ); out.newLine(); out.write("Shielding Material (0=air,1=iron)"); out.newLine(); out.write(""+containerType); out.newLine(); out.write("Rejection Threshold (minimum peak height)"); out.newLine(); out.write("10"); out.newLine(); out.write("Relative channel threshold (peak must represent a significant percent of the total spectrum in a channel)"); out.newLine(); out.write("5"); out.newLine(); out.write("Scattered counts scale factor to account for unknown geometry"); out.newLine(); out.write("1"); out.newLine(); out.close(); // Call the ASEDRA program (findpeak). callProgram("bin\\findpeak",""); } catch(IOException ex) { System.out.println("difficulty creating process.txt or calling ASEDRA"); } // New results from ASEDRA, so need to make sure they are displayed. this.repaint(); } } // Button used for selecting a file class FileButton extends JButton implements ActionListener { String id, fileString; public FileButton(String init_id) { id = init_id; this.setText(id); this.addActionListener(this); } public void actionPerformed(ActionEvent event) { JFileChooser fc = new JFileChooser(); fc.setCurrentDirectory(new File(".")); if(fc.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) { fileString = fc.getSelectedFile().getPath(); this.setText(id+": "+fc.getSelectedFile().getName()); } } public String filePath() { return fileString; } } }