package edu.stanford.rsl.conrad.calibration; import ij.IJ; import ij.ImageJ; import ij.ImagePlus; import ij.gui.EllipseRoi; import ij.gui.Overlay; import ij.gui.Roi; import ij.gui.ShapeRoi; import ij.gui.StackWindow; import ij.gui.TextRoi; import java.awt.Color; import java.awt.Component; import java.awt.Cursor; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.text.NumberFormat; import java.util.ArrayList; import javax.swing.AbstractAction; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JSpinner; import javax.swing.JTextField; import javax.swing.JTextPane; import javax.swing.RootPaneContainer; import javax.swing.SpinnerModel; import javax.swing.SpinnerNumberModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.text.DefaultEditorKit; import edu.stanford.rsl.apps.gui.ConfigurePipelineFrame; import edu.stanford.rsl.apps.gui.blobdetection.AutomaticMarkerDetectionWorker; import edu.stanford.rsl.apps.gui.blobdetection.MarkerDetection; import edu.stanford.rsl.apps.gui.blobdetection.MarkerDetectionWorker; import edu.stanford.rsl.conrad.filtering.FastRadialSymmetryTool; import edu.stanford.rsl.conrad.filtering.ImageFilteringTool; import edu.stanford.rsl.conrad.filtering.NumericalDerivativeComputationTool; import edu.stanford.rsl.conrad.geometry.Projection; import edu.stanford.rsl.conrad.geometry.shapes.simple.PointND; import edu.stanford.rsl.conrad.numerics.SimpleMatrix; import edu.stanford.rsl.conrad.phantom.MathematicalPhantom; import edu.stanford.rsl.conrad.utils.CONRAD; import edu.stanford.rsl.conrad.utils.Configuration; import edu.stanford.rsl.conrad.utils.FileUtil; import edu.stanford.rsl.conrad.utils.StringFileFilter; import edu.stanford.rsl.conrad.utils.XmlUtils; import edu.stanford.rsl.jpop.utils.UserUtil; public class GeometricCalibrationGUI extends JFrame { protected static String location; ArrayList<JButton> buttonList; ConfigurePipelineFrame pipelineFrame; ImagePlus currentImage; String currentConfigFile; NumericalDerivativeComputationTool derivativeTool; ArrayList<Double> errors; // attributes for line detection/definition Roi leftBorder; Roi rightBorder; Roi leftLineRoi; Roi rightLineRoi; boolean identify2D; Component visualizationComponent; int sliceNumber; public int getSliceNumber() { return sliceNumber; } public void setSliceNumber(int sliceNumber) { this.sliceNumber = sliceNumber; } JLabel currentStatus; GeometricCalibration tool; Factorization toolF; protected void initTool() { this.tool = new GeometricCalibration(); } protected void label(Overlay overlay) { NumberFormat nf = NumberFormat.getInstance(); nf.setMaximumFractionDigits(2); nf.setMinimumFractionDigits(2); for (int n = 0; n < tool.cBeads.size(); n++) { CalibrationBead first = tool.cBeads.get(n); TextRoi text = new TextRoi(first.getU(), first.getV() - 20, "Bead " /* * + tool.ids[n] + " (" + nf.format(first.getX()) + ", " + * nf.format(first.getY()) + ", " + nf.format(first.getZ()) + " | " * + nf.format(first.getU()) + ", " + nf.format(first.getV()) + ")" */); overlay.add(text); } } protected void overlayHoughLines() { // Roi[] lines = tool.detectHoughLines(currentImage, derivativeTool, // rightBorder, leftBorder); int sx1 = 300; int sy1 = 0; int ex1 = 0; int ey1 = 960; int sx2 = 980; int sy2 = 0; int ex2 = 0; int ey2 = 960; try { sx1 = UserUtil.queryInt("xStart", sx1); sy1 = UserUtil.queryInt("yStart", sy1); ex1 = UserUtil.queryInt("xEnd", ex1); ey1 = UserUtil.queryInt("xEnd", ey1); sx2 = UserUtil.queryInt("xStart", sx2); sy2 = UserUtil.queryInt("yStart", sy2); ex2 = UserUtil.queryInt("xEnd", ex2); ey2 = UserUtil.queryInt("yEnd", ey2); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } leftLineRoi = new Roi(sx1, sy1, ex1, ey1); rightLineRoi = new Roi(sx2, sy2, ex2, ey2); // leftLineRoi = lines[0]; // rightLineRoi = lines[1]; overlayLines(); this.revalidate(); this.repaint(); } public GeometricCalibrationGUI() { derivativeTool = new NumericalDerivativeComputationTool(); derivativeTool.setConfigured(true); initGUI(); initTool(); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); } protected void setSlice(int n) { currentImage.setSlice(n + 1); // IJ.run("Enhance Contrast", "0.35"); } protected void overlayMultipleRois(Roi... rois) { ShapeRoi accumulationRoi = new ShapeRoi(rois[0]); for (int i = 1; i < rois.length; i++) { ShapeRoi additionalRoi = new ShapeRoi(rois[i]); accumulationRoi = accumulationRoi.or(additionalRoi); } currentImage.setRoi(accumulationRoi); } protected void overlayBorders() { overlayMultipleRois(leftBorder, rightBorder); } protected void overlayLines() { if (leftLineRoi != null && rightLineRoi != null) { overlayMultipleRois(leftLineRoi, rightLineRoi); } else { overlayHoughLines(); System.out .println("No vertical lines detectable: manual definition."); } } protected void overlayBeads(ArrayList<PointND> listOfBeads1, double radius1) { Overlay overlay = new Overlay(); Roi[] beadRois1 = new Roi[listOfBeads1.size()]; for (int i = 0; i < listOfBeads1.size(); i++) { double x = listOfBeads1.get(i).get(0); double y = listOfBeads1.get(i).get(1); beadRois1[i] = new EllipseRoi(x - radius1, y - radius1, x + radius1, y + radius1, 1.0); overlay.add(new EllipseRoi(x - radius1, y - radius1, x + radius1, y + radius1, 1.0)); } // overlayMultipleRois(beadRois1); // label(overlay); currentImage.setOverlay(overlay); // this happens in the GUI // currentImage.setOverlay(overlay); } protected void overlayBeadsF(ArrayList<PointND> listOfBeads1, double radius1) { Overlay overlay = new Overlay(); Roi[] beadRois1 = new Roi[listOfBeads1.size()]; for (int i = 0; i < listOfBeads1.size(); i++) { if (listOfBeads1.get(i) != null) { double x = listOfBeads1.get(i).get(0); double y = listOfBeads1.get(i).get(1); beadRois1[i] = new EllipseRoi(x - radius1, y - radius1, x + radius1, y + radius1, 1.0); overlay.add(new EllipseRoi(x - radius1, y - radius1, x + radius1, y + radius1, 1.0)); } } // overlayMultipleRois(beadRois1); currentImage.setOverlay(overlay); // this happens in the GUI // currentImage.setOverlay(overlay); } protected void overlayBeadsCB(ArrayList<CalibrationBead> listOfBeads1, double radius1) { Overlay overlay = new Overlay(); overlay.setLabelColor(Color.RED); overlay.setFillColor(Color.RED); Roi[] beadRois1 = new Roi[listOfBeads1.size()]; for (int i = 0; i < listOfBeads1.size(); i++) { double x = listOfBeads1.get(i).getU(); double y = listOfBeads1.get(i).getV(); beadRois1[i] = new EllipseRoi(x - radius1, y - radius1, x + radius1, y + radius1, 1.0); overlay.add(new EllipseRoi(x - radius1, y - radius1, x + radius1, y + radius1, 1.0)); } // overlayMultipleRois(beadRois1); label(overlay); currentImage.setOverlay(overlay); // this happens in the GUI // currentImage.setOverlay(overlay); } public static String queryFunction(String message, String messageTitle, String[] functions) throws Exception { return (String) UserUtil.chooseObject(message, messageTitle, functions, functions[0]); } protected void loadImageData(String filename) { System.out.println("Loading Image Data: " + filename); IJ.open(filename); currentImage = IJ.getImage(); sliceNumber = 0; leftBorder = new Roi((int) (0.05 * currentImage.getWidth()), 0, (int) (0.30 * currentImage.getWidth()), currentImage.getHeight()); leftBorder.setName("leftBorder"); rightBorder = new Roi((int) (0.65 * currentImage.getWidth()), 0, (int) (0.30 * currentImage.getWidth()), currentImage.getHeight()); rightBorder.setName("rightBorder"); // overlayBorders(); updateVisualizationComponent(getCanvas(currentImage)); setSlice(sliceNumber); tool.setSlice(sliceNumber); tool.errors = new ArrayList<Double>(); try { if (queryFunction("Function", "Function", new String[] { "Naive", "Factorization" }).equals("Naive")) { addCalibrationButtons(); } else { addFactorizationButtons(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } /* * Configuration .getGlobalConfiguration() .getGeometry() * .setProjectionMatrices( new Projection[currentImage.getStackSize()]); * Configuration.getGlobalConfiguration().getGeometry() * .setPrimaryAngleArray(new double[currentImage.getStackSize()]); * Configuration .getGlobalConfiguration() .getGeometry() * .setSecondaryAngleArray(new double[currentImage.getStackSize()]); * Configuration.getGlobalConfiguration().getGeometry() * .setNumProjectionMatrices(currentImage.getStackSize()); */ } Component getCanvas(ImagePlus imp) { StackWindow window = new StackWindow(imp); window.setVisible(false); return window.getComponents()[0]; } public interface Cursors { Cursor WAIT_CURSOR = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); Cursor DEFAULT_CURSOR = Cursor .getPredefinedCursor(Cursor.DEFAULT_CURSOR); } public static void startWaitCursor(JComponent component) { RootPaneContainer root = (RootPaneContainer) component .getTopLevelAncestor(); root.getGlassPane().setCursor( Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); root.getGlassPane().setVisible(true); } public static void stopWaitCursor(JComponent component) { RootPaneContainer root = (RootPaneContainer) component .getTopLevelAncestor(); root.getGlassPane().setCursor( Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); root.getGlassPane().setVisible(false); } private void updateVisualizationComponent(Component cmp) { if (visualizationComponent != null) getContentPane().remove(visualizationComponent); visualizationComponent = cmp; getContentPane().add( visualizationComponent, new GridBagConstraints(1, 1, 1, 3, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0)); } private void loadConfiguration() throws Exception { String filename = FileUtil.myFileChoose(".xml", false); if (filename != null) { tool.config = Configuration.loadConfiguration(filename); } } private void loadImageData() throws Exception { String filename = FileUtil.myFileChoose(".zip", false); if (filename != null) { loadImageData(filename); Configuration.getGlobalConfiguration().setRecentFileOne(filename); } } final static String[] tools = { "Naive", "Factorization" }; public static String queryTool(String message, String messageTitle) throws Exception { return (String) UserUtil.chooseObject(message, messageTitle, tools, tools[0]); } public void initPane() { getContentPane().removeAll(); GridBagLayout thisLayout = new GridBagLayout(); thisLayout.rowWeights = new double[] { 0.1, 0.1, 0.8 }; thisLayout.rowHeights = new int[] { 50, 140, 618 }; thisLayout.columnWeights = new double[] { 0.1, 0.9 }; thisLayout.columnWidths = new int[] { 200, 800 }; getContentPane().setLayout(thisLayout); JLabel jLabel1 = new JLabel(); getContentPane().add( jLabel1, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); jLabel1.setText("Visualization"); jLabel1 = new JLabel(); getContentPane().add( jLabel1, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); jLabel1.setText("Tools"); int insetY = 20; int insetX = 10; JButton pipeline = new JButton(); pipeline.setText("configure Pipeline"); pipeline.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { pipelineFrame = new ConfigurePipelineFrame(); pipelineFrame.setVisible(true); pipelineFrame.setSaveToDisk(false); } }); getContentPane().add( pipeline, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX, 0, insetX), 0, 0)); insetY += 40; JButton selectConfig = new JButton(); selectConfig.setText("select Configuration"); selectConfig.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { try { loadConfiguration(); tool.reConfigure(); doLayout(); revalidate(); repaint(); } catch (Exception e1) { System.out.println("Action not completed: " + e1.toString()); } } }); getContentPane().add( selectConfig, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX, 0, insetX), 0, 0)); insetY += 40; JButton selectData = new JButton(); selectData.setText("select File"); selectData.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { try { loadImageData(); doLayout(); revalidate(); repaint(); } catch (Exception e1) { System.out.println("Action not completed: " + e1.toString()); } } }); getContentPane().add( selectData, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX, 0, insetX), 0, 0)); // insetY += 20; // if (Configuration.getGlobalConfiguration().getRecentFileOne() != // null) { // loadImageData(Configuration.getGlobalConfiguration() // .getRecentFileOne()); // } this.revalidate(); this.repaint(); } private String saveAs() { try { String filename = FileUtil.myFileChoose(".xml", true); if (!filename.endsWith(".xml")) filename += ".xml"; save(filename); return filename; } catch (Exception e1) { e1.printStackTrace(); } return null; } private void save(String filename) { Configuration.saveConfiguration(Configuration.getGlobalConfiguration(), filename); Configuration.loadConfiguration(filename); } /** * Create an Edit menu to support cut/copy/paste. */ @SuppressWarnings("serial") public JMenuBar createMenuBar() { JMenuItem menuItem = null; JMenuBar menuBar = new JMenuBar(); JMenu mainMenu = new JMenu("Configuration"); mainMenu.setMnemonic(KeyEvent.VK_C); menuItem = new JMenuItem(new AbstractAction() { public void actionPerformed(ActionEvent e) { try { if (pipelineFrame != null) pipelineFrame.exit(); Configuration configuration = new Configuration(); configuration .setFilterPipeline(new ImageFilteringTool[] { new FastRadialSymmetryTool() }); configuration.setCurrentPath(location); Configuration.setGlobalConfiguration(tool.config); Thread thread = new Thread(new Runnable() { @Override public void run() { initPane(); } }); thread.start(); } catch (Exception e1) { System.out.println(e1.getLocalizedMessage()); } } }); menuItem.setText("New"); menuItem.setMnemonic(KeyEvent.VK_N); mainMenu.add(menuItem); menuItem = new JMenuItem(new AbstractAction() { public void actionPerformed(ActionEvent e) { try { JFileChooser FC = new JFileChooser(); File dir = new File(location); FC.setCurrentDirectory(dir); FC.setVisible(true); FC.setFileFilter(new StringFileFilter(".xml")); FC.showOpenDialog(null); String filename = FC.getSelectedFile().getAbsolutePath(); Configuration.setGlobalConfiguration(Configuration .loadConfiguration(filename)); currentConfigFile = filename; if (pipelineFrame != null) pipelineFrame.exit(); initPane(); } catch (Exception e1) { e1.printStackTrace(); } } }); menuItem.setText("Load"); menuItem.setMnemonic(KeyEvent.VK_L); mainMenu.add(menuItem); menuItem = new JMenuItem(new AbstractAction() { public void actionPerformed(ActionEvent e) { if (currentConfigFile == null) currentConfigFile = saveAs(); else save(currentConfigFile); } }); menuItem.setText("Save"); menuItem.setMnemonic(KeyEvent.VK_S); mainMenu.add(menuItem); menuItem = new JMenuItem(new AbstractAction() { public void actionPerformed(ActionEvent e) { currentConfigFile = saveAs(); } }); menuItem.setText("Save As"); menuItem.setMnemonic(KeyEvent.VK_A); mainMenu.add(menuItem); menuBar.add(mainMenu); mainMenu = new JMenu("Edit"); mainMenu.setMnemonic(KeyEvent.VK_E); menuItem = new JMenuItem(new DefaultEditorKit.CutAction()); menuItem.setText("Cut"); menuItem.setMnemonic(KeyEvent.VK_T); mainMenu.add(menuItem); menuItem = new JMenuItem(new DefaultEditorKit.CopyAction()); menuItem.setText("Copy"); menuItem.setMnemonic(KeyEvent.VK_C); mainMenu.add(menuItem); menuItem = new JMenuItem(new DefaultEditorKit.PasteAction()); menuItem.setText("Paste"); menuItem.setMnemonic(KeyEvent.VK_P); mainMenu.add(menuItem); menuBar.add(mainMenu); mainMenu = new JMenu("Help"); mainMenu.setMnemonic(KeyEvent.VK_H); menuItem = new JMenuItem(new AbstractAction() { public void actionPerformed(ActionEvent e) { JOptionPane .showMessageDialog( null, "Geometric Calibration GUI\n\nCreated by Andreas Maier\nandreas.maier@fau.de", "About", JOptionPane.PLAIN_MESSAGE); } }); menuItem.setText("About"); menuItem.setMnemonic(KeyEvent.VK_A); mainMenu.add(menuItem); menuBar.add(mainMenu); return menuBar; } JTextField beadRadius = new JTextField(); JTextField smallBeadPercentile = new JTextField(); JTextField threshold = new JTextField(); JTextField thresh2Percentile = new JTextField(); public void initGUI() { this.setBackground(Color.WHITE); this.setTitle("Geometric Calibration GUI"); this.setSize(1400, 980); this.setJMenuBar(createMenuBar()); this.getContentPane().setBackground(Color.WHITE); } boolean intensity = false; protected void addCalibrationButtons() { int insetY = 0; int insetX = 10; buttonList = new ArrayList<JButton>(); final String[] phantoms = { "Random Distribution Phantom", "Randomized Helix Phantom", "Mathematical Phantom" }; final JComboBox<String> phantomBox = new JComboBox<String>(phantoms); phantomBox.addActionListener(new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { tool.setPhantom(phantoms[phantomBox.getSelectedIndex()]); if (tool.phantom instanceof MathematicalPhantom) { } System.out.println(tool.phantomName + " chosen..."); } }); getContentPane().add( phantomBox, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX, 0, insetX), 0, 0)); insetY += 40; JButton export = new JButton(); buttonList.add(export); export.setText("export to .scad"); export.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { tool.phantom.writeToOpenSCAD(); } }); getContentPane().add( export, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX, 0, insetX), 0, 0)); insetY += 40; JButton newButton = new JButton(); buttonList.add(newButton); newButton.setText("next Projection"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { sliceNumber++; if (sliceNumber >= currentImage.getStackSize()) sliceNumber = currentImage.getStackSize() - 1; setSlice(sliceNumber); tool.setSlice(sliceNumber); revalidate(); repaint(); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX, 0, insetX), 0, 0)); insetY += 40; newButton = new JButton(); buttonList.add(newButton); newButton.setText("previous Projection"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { sliceNumber--; if (sliceNumber < 0) sliceNumber = 0; setSlice(sliceNumber); tool.setSlice(sliceNumber); revalidate(); repaint(); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX, 0, insetX), 0, 0)); insetY += 40; int offsetLeft = 40; int offsetMid = 180; int offsetRight = 80; newButton = new JButton(); buttonList.add(newButton); newButton.setText("detect Boundary"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { Roi[] lines = tool.detectHoughLines(currentImage, derivativeTool, rightBorder, leftBorder); leftLineRoi = lines[0]; rightLineRoi = lines[1]; overlayLines(); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft, 0, insetX + offsetRight), 0, 0)); newButton = new JButton(); buttonList.add(newButton); newButton.setText("l"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { if (leftBorder.getName() .equals(currentImage.getRoi().getName())) { leftBorder = currentImage.getRoi(); } currentImage.setRoi(leftBorder); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft + 200, 0, insetX + offsetRight / 2), 0, 0)); newButton = new JButton(); buttonList.add(newButton); newButton.setText("r"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { if (rightBorder.getName().equals( currentImage.getRoi().getName())) { rightBorder = currentImage.getRoi(); } currentImage.setRoi(rightBorder); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft + 200 + 40, 0, insetX), 0, 0)); insetY += 40; newButton = new JButton(); buttonList.add(newButton); newButton.setText("estimate rotation"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { tool.idealBeads(); tool.detectBeads(currentImage, leftLineRoi, rightLineRoi); tool.estimateRotation(); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft, 0, insetX + offsetRight), 0, 0)); insetY += 40; newButton = new JButton(); buttonList.add(newButton); newButton.setText("ideal Beads 2D"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { tool.idealBeads(); overlayBeads(tool.beads2DIdeal, tool.beadRadius); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft, 0, insetX + offsetRight), 0, 0)); insetY += 40; newButton = new JButton(); buttonList.add(newButton); newButton.setText("detect/identify Beads 2D"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { tool.setDetection(Integer.parseInt(beadRadius.getText()), Double.parseDouble(threshold.getText())); tool.detectBeads(currentImage, leftLineRoi, rightLineRoi); tool.idealBeads(); tool.computeBeadIDsForward(); identify2D = true; // overlayBeads(tool.beads2DIdeal, tool.beadRadius); System.out.println("correspondences detected..."); overlayBeadsCB(tool.cBeads, tool.beadRadius); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft, 0, insetX + offsetRight), 0, 0)); newButton = new JButton(); buttonList.add(newButton); newButton.setText("l"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { if (leftLineRoi.getName().equals( currentImage.getRoi().getName())) { leftLineRoi = currentImage.getRoi(); } currentImage.setRoi(leftLineRoi); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft + 200, 0, insetX + offsetRight / 2), 0, 0)); newButton = new JButton(); buttonList.add(newButton); newButton.setText("r"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { if (rightLineRoi.getName().equals( currentImage.getRoi().getName())) { rightLineRoi = currentImage.getRoi(); } currentImage.setRoi(rightLineRoi); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft + 200 + 40, 0, insetX), 0, 0)); insetY += 40; newButton = new JButton(); buttonList.add(newButton); newButton.setText("find Points"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { tool.setDetection(Integer.parseInt(beadRadius.getText()), Double.parseDouble(threshold.getText())); tool.detectBeads(currentImage, leftLineRoi, rightLineRoi); tool.findPointsNaive(currentImage, leftLineRoi, rightLineRoi); overlayBeadsCB(tool.cBeads, tool.beadRadius); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft, 0, insetX + offsetRight), 0, 0)); insetY += 40; JLabel beadLabel1 = new JLabel("Bead Radius"); // JLabel beadLabel2 = new JLabel("Small Bead Percentile"); JLabel threshLabel1 = new JLabel("Threshold Percentile"); // JLabel threshLabel2 = new JLabel("High Threshold Percentile"); beadRadius.setText("" + tool.beadRadius); // smallBeadPercentile.setText("" + tool.smallBeadPercentileD); threshold.setText("" + tool.threshold); // thresh2Percentile.setText("" + tool.thresh2PercentileD); getContentPane().add( beadLabel1, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft, 0, insetX + offsetRight), 0, 0)); getContentPane().add( beadRadius, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft + 200, 0, insetX + offsetRight / 2), 0, 0)); insetY += 40; getContentPane().add( threshLabel1, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft, 0, insetX + offsetRight), 0, 0)); getContentPane().add( threshold, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft + 200, 0, insetX + offsetRight / 2), 0, 0)); insetY += 40; newButton = new JButton(); buttonList.add(newButton); newButton.setText("compute Matrix"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { NumberFormat nf = NumberFormat.getInstance(); nf.setMaximumFractionDigits(2); nf.setMinimumFractionDigits(2); Overlay overlay = new Overlay(); double error = tool.calibrate(sliceNumber, overlay); // double error = tool.testP(sliceNumber, overlay); currentImage.setOverlay(overlay); System.out.println("Projection: " + sliceNumber + " error: " + nf.format(error) + " [px/bead]."); currentStatus.setText("Projection: " + sliceNumber + " error: " + nf.format(error) + " [px/bead]."); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft, 0, insetX + offsetRight), 0, 0)); insetY += 40; offsetLeft = 0; newButton = new JButton(); buttonList.add(newButton); newButton.setText("continue"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { Thread thread = new Thread(new Runnable() { public void run() { NumberFormat nf = NumberFormat.getInstance(); nf.setMaximumFractionDigits(2); nf.setMinimumFractionDigits(2); ArrayList<CalibrationBead> reference = tool.cBeads; startWaitCursor(getRootPane()); double error = 0; while (/* * (error < 1) && */sliceNumber != currentImage.getStackSize() - 1) { sliceNumber++; if (sliceNumber >= currentImage.getStackSize()) sliceNumber = currentImage.getStackSize() - 1; setSlice(sliceNumber); tool.setSlice(sliceNumber); tool.detectBeads(currentImage, leftLineRoi, rightLineRoi); tool.findPointsNaive(currentImage, leftBorder, leftBorder); /* * tool.detectBeads(currentImage, leftLineRoi, * rightLineRoi); tool.idealBeads(); if (identify2D) * { tool.computeBeadIDsForward(); } else { * tool.computeBeadIDsBack(); } */ Overlay overlay = new Overlay(); error = tool.calibrate(sliceNumber, overlay); if (error > 0.15) { tool.detectBeads(currentImage, leftLineRoi, rightLineRoi); tool.computeBeadIDsForward(); Overlay newOverlay = new Overlay(); double newError = tool.calibrate(sliceNumber, newOverlay); if (newError < error) { error = newError; overlay = newOverlay; } } currentImage.setOverlay(overlay); System.out.println("Projection: " + sliceNumber + " error: " + nf.format(error) + " [px/bead]."); currentStatus.setText("Projection: " + sliceNumber + " error: " + nf.format(error) + " [px/bead]."); Thread.yield(); try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } stopWaitCursor(getRootPane()); }; }); thread.start(); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft, 0, insetX + offsetRight), 0, 0)); insetY += 40; newButton = new JButton(); buttonList.add(newButton); newButton.setText("save Results"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { try { System.out.println(tool.errors); String name = tool.phantom.getName().concat( "Calibration.txt"); BufferedWriter out = new BufferedWriter( new FileWriter(name)); out.write("Projection Matrices\n"); for (SimpleMatrix p : tool.projectionMatrices) { out.write("Slice " + tool.projectionMatrices.indexOf(p) + ": " + p + ", Backprojection Error: " + tool.errors.get(tool.projectionMatrices .indexOf(p)) + "\n"); } out.close(); } catch (Exception ex) { } } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft, 0, insetX + offsetRight), 0, 0)); insetY += 40; if (currentStatus != null) { getContentPane().remove(currentStatus); } currentStatus = new JLabel("Loaded."); getContentPane().add( currentStatus, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft, 0, insetX + offsetRight), 0, 0)); } public void addFactorizationButtons() { int insetY = 0; int insetX = 10; buttonList = new ArrayList<JButton>(); final String[] phantoms = { "Random Distribution Phantom", "Randomized Helix Phantom", "Mathematical Phantom" }; final JComboBox<String> phantomBox = new JComboBox<String>(phantoms); phantomBox.addActionListener(new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { tool.setPhantom(phantoms[phantomBox.getSelectedIndex()]); if (tool.phantom instanceof MathematicalPhantom) { } System.out.println(tool.phantomName + " chosen..."); } }); getContentPane().add( phantomBox, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX, 0, insetX), 0, 0)); insetY += 40; JButton export = new JButton(); buttonList.add(export); export.setText("export to .scad"); export.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { tool.phantom.writeToOpenSCAD(); } }); getContentPane().add( export, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX, 0, insetX), 0, 0)); insetY += 40; JButton newButton = new JButton(); buttonList.add(newButton); newButton.setText("Intesity/Integral"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { if (intensity) { IJ.run(currentImage, "Log", ""); IJ.run(currentImage, "Multiply...", "value=-1.0"); intensity = false; } else { IJ.run(currentImage, "Multiply...", "value=-1.0"); IJ.run(currentImage, "Exp", ""); intensity = true; } revalidate(); repaint(); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX, 0, insetX), 0, 0)); insetY += 40; insetY += 40; newButton = new JButton(); buttonList.add(newButton); newButton.setText("next Projection"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { sliceNumber++; if (sliceNumber >= currentImage.getStackSize()) sliceNumber = currentImage.getStackSize() - 1; setSlice(sliceNumber); tool.setSlice(sliceNumber); revalidate(); repaint(); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX, 0, insetX), 0, 0)); insetY += 40; newButton = new JButton(); buttonList.add(newButton); newButton.setText("previous Projection"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { sliceNumber--; if (sliceNumber < 0) sliceNumber = 0; setSlice(sliceNumber); revalidate(); repaint(); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX, 0, insetX), 0, 0)); insetY += 40; int offsetLeft = 40; int offsetMid = 180; int offsetRight = 80; newButton = new JButton(); buttonList.add(newButton); newButton.setText("detect Boundary"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { Roi[] lines = tool.detectHoughLines(currentImage, derivativeTool, rightBorder, leftBorder); leftLineRoi = lines[0]; rightLineRoi = lines[1]; overlayLines(); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft, 0, insetX + offsetRight), 0, 0)); newButton = new JButton(); buttonList.add(newButton); newButton.setText("l"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { if (leftBorder.getName() .equals(currentImage.getRoi().getName())) { leftBorder = currentImage.getRoi(); } currentImage.setRoi(leftBorder); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft + 200, 0, insetX + offsetRight / 2), 0, 0)); newButton = new JButton(); buttonList.add(newButton); newButton.setText("r"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { if (rightBorder.getName().equals( currentImage.getRoi().getName())) { rightBorder = currentImage.getRoi(); } currentImage.setRoi(rightBorder); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft + 200 + 40, 0, insetX), 0, 0)); insetY += 40; newButton = new JButton(); buttonList.add(newButton); newButton.setText("find initial points"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { tool.setDetection(Integer.parseInt(beadRadius.getText()), Double.parseDouble(threshold.getText())); tool.getInitialPoints(false, currentImage, leftLineRoi, rightLineRoi); overlayBeadsF(tool.referencePoints, tool.beadRadius); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft, 0, insetX + offsetRight), 0, 0)); newButton = new JButton(); buttonList.add(newButton); newButton.setText("l"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { if (leftLineRoi.getName().equals( currentImage.getRoi().getName())) { leftLineRoi = currentImage.getRoi(); } currentImage.setRoi(leftLineRoi); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft + 200, 0, insetX + offsetRight / 2), 0, 0)); newButton = new JButton(); buttonList.add(newButton); newButton.setText("r"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { if (rightLineRoi.getName().equals( currentImage.getRoi().getName())) { rightLineRoi = currentImage.getRoi(); } currentImage.setRoi(rightLineRoi); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft + 200 + 40, 0, insetX), 0, 0)); insetY += 40; JLabel beadLabel1 = new JLabel("Bead Radius"); // JLabel beadLabel2 = new JLabel("Small Bead Percentile"); JLabel threshLabel1 = new JLabel("Threshold Percentile"); // JLabel threshLabel2 = new JLabel("High Threshold Percentile"); beadRadius.setText("" + tool.beadRadius); // smallBeadPercentile.setText("" + tool.smallBeadPercentileD); threshold.setText("" + tool.threshold); // thresh2Percentile.setText("" + tool.thresh2PercentileD); getContentPane().add( beadLabel1, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft, 0, insetX + offsetRight), 0, 0)); getContentPane().add( beadRadius, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft + 200, 0, insetX + offsetRight / 2), 0, 0)); insetY += 40; getContentPane().add( threshLabel1, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft, 0, insetX + offsetRight), 0, 0)); getContentPane().add( threshold, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft + 200, 0, insetX + offsetRight / 2), 0, 0)); insetY += 40; newButton = new JButton(); buttonList.add(newButton); newButton.setText("find all points"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { Thread thread = new Thread(new Runnable() { public void run() { startWaitCursor(getRootPane()); while (sliceNumber != currentImage.getStackSize() - 1) { sliceNumber++; if (sliceNumber >= currentImage.getStackSize()) sliceNumber = currentImage.getStackSize() - 1; setSlice(sliceNumber); tool.setSlice(sliceNumber); tool.findPoints(currentImage, leftLineRoi, rightLineRoi); overlayBeadsF(tool.imagePoints.get(sliceNumber), tool.beadRadius); currentStatus.setText("Projection: " + sliceNumber + "Beads estimated: " + (tool.phantom.getNumberOfBeads() - tool.imagePoints .get(sliceNumber).size())); Thread.yield(); try { Thread.sleep(50); } catch (InterruptedException ex) { // TODO Auto-generated catch block ex.printStackTrace(); } } // tool.removePoints(); stopWaitCursor(getRootPane()); } }); thread.start(); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft, 0, insetX + offsetRight), 0, 0)); insetY += 40; newButton = new JButton(); buttonList.add(newButton); newButton.setText("compute Matrices"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { tool.factorize(); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft, 0, insetX + offsetRight), 0, 0)); insetY += 40; offsetLeft = 0; newButton = new JButton(); buttonList.add(newButton); newButton.setText("calibrate"); newButton.addActionListener(new AbstractAction() { public void actionPerformed(ActionEvent e) { Thread thread = new Thread(new Runnable() { public void run() { NumberFormat nf = NumberFormat.getInstance(); nf.setMaximumFractionDigits(2); nf.setMinimumFractionDigits(2); startWaitCursor(getRootPane()); double error = 0; sliceNumber = 0; while (sliceNumber != currentImage.getStackSize() - 1) { if (sliceNumber >= currentImage.getStackSize()) sliceNumber = currentImage.getStackSize() - 1; setSlice(sliceNumber); tool.setSlice(sliceNumber); Overlay overlay = new Overlay(); tool.detectBeads(currentImage, leftBorder, leftBorder); error = tool.calibrateF(sliceNumber, overlay); if (error > 1) System.out.println("Error in slice" + sliceNumber + ": " + error); currentImage.setOverlay(overlay); currentStatus.setText("Projection: " + sliceNumber + " error: " + nf.format(error) + " [px/bead]."); sliceNumber++; Thread.yield(); try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } stopWaitCursor(getRootPane()); }; }); thread.start(); } }); getContentPane().add( newButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft, 0, insetX + offsetRight), 0, 0)); insetY += 40; if (currentStatus != null) { getContentPane().remove(currentStatus); } currentStatus = new JLabel("Loaded."); getContentPane().add( currentStatus, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(insetY, insetX + offsetLeft, 0, insetX + offsetRight), 0, 0)); } public static void main(String[] args) { if (args.length > 0) location = args[0]; // CONRAD.setup(); new ImageJ().setVisible(true); GeometricCalibrationGUI gui = new GeometricCalibrationGUI(); gui.setVisible(true); } }