ThebaGUI.java

Go to the documentation of this file.
00001 package theba.core.gui;
00002 
00003 import java.awt.BorderLayout;
00004 import java.awt.Color;
00005 import java.awt.Component;
00006 import java.awt.Cursor;
00007 import java.awt.Dimension;
00008 import java.awt.FlowLayout;
00009 import java.awt.Frame;
00010 import java.awt.Point;
00011 import java.awt.event.ActionEvent;
00012 import java.awt.event.ActionListener;
00013 import java.awt.event.MouseAdapter;
00014 import java.awt.event.MouseEvent;
00015 import java.io.DataOutputStream;
00016 import java.io.File;
00017 import java.io.FileNotFoundException;
00018 import java.io.FileOutputStream;
00019 import java.io.IOException;
00020 import java.io.PrintStream;
00021 import java.io.RandomAccessFile;
00022 import java.lang.reflect.InvocationTargetException;
00023 import java.util.ArrayList;
00024 import java.util.LinkedList;
00025 
00026 import javax.swing.ButtonGroup;
00027 import javax.swing.JButton;
00028 import javax.swing.JCheckBoxMenuItem;
00029 import javax.swing.JComponent;
00030 import javax.swing.JFileChooser;
00031 import javax.swing.JFrame;
00032 import javax.swing.JLabel;
00033 import javax.swing.JMenu;
00034 import javax.swing.JMenuBar;
00035 import javax.swing.JMenuItem;
00036 import javax.swing.JOptionPane;
00037 import javax.swing.JPanel;
00038 import javax.swing.JProgressBar;
00039 import javax.swing.JScrollPane;
00040 import javax.swing.JSlider;
00041 import javax.swing.JTabbedPane;
00042 import javax.swing.JTextArea;
00043 import javax.swing.JTextField;
00044 import javax.swing.JToggleButton;
00045 import javax.swing.JToolBar;
00046 import javax.swing.KeyStroke;
00047 import javax.swing.SwingUtilities;
00048 import javax.swing.UIManager;
00049 import javax.swing.border.EmptyBorder;
00050 import javax.swing.event.ChangeEvent;
00051 import javax.swing.event.ChangeListener;
00052 
00053 import theba.core.BoxBounds;
00054 import theba.core.ImageFunctions;
00055 import theba.core.Plugin;
00056 import theba.core.PluginLoader;
00057 import theba.core.Region;
00058 import theba.core.RegionDescriptor;
00059 import theba.core.RegionMask;
00060 import theba.core.RegionMask2D;
00061 import theba.core.Stack;
00062 import theba.core.Tracker;
00063 import theba.core.io.DataConversion;
00064 import theba.core.io.HeapReader;
00065 import theba.core.io.SliceReader;
00066 import theba.core.io.VolumeReader;
00067 import theba.core.math.Point3D;
00068 
00069 
00070 
00079 public class ThebaGUI implements ActionListener {
00080         public ArrayList lumencenters;
00081 
00082         public final int MAX_FIBERS = 2048;
00083 
00084         public int width, height, depth;
00085 
00086         private short selectedRegion;
00087 
00088         public final short INVALID = 7;
00089 
00090         private JButton stopButton;
00091 
00092         private JMenu analyzeMenu;
00093 
00094         private JTextArea area;
00095 
00096         private ButtonGroup buttonGroup;
00097 
00098         private JFileChooser chooser;
00099 
00100         private VolumeReader datawriter;
00101 
00102         private JToggleButton deleteButton;
00103 
00104         private JSlider depthSlider;
00105 
00106         private JMenu fileMenu;
00107 
00108         private JMenu filterMenu;
00109 
00110         private JMenuItem flipItem;
00111 
00112         private JCheckBoxMenuItem hideWhite;
00113 
00114         private JTextField idSelector;
00115 
00116         private int inputType;
00117 
00118         private ImagePane iw;
00119 
00120         private String labeltext;
00121 
00122         private JFrame mainWindow;
00123 
00124         private JToggleButton measureButton;
00125 
00126         private JToggleButton measureButton3d;
00127 
00128         private JMenuBar menuBar;
00129 
00130         private boolean menuEnabled;
00131 
00132         private String pixeltext;
00133 
00134         private ThebaPrefs preferences;
00135 
00136         private JProgressBar progressbar;
00137 
00138         private int regionCount;
00139 
00140         private LinkedList<Region> regList;
00141 
00142         private JScrollPane resultScrollPane;
00143 
00144         private JFrame resultWindow;
00145 
00146         private JScrollPane scrollpane;
00147 
00148         private JToggleButton seedButton3d;
00149 
00150         private JLabel stackLabel;
00151 
00152         private JPanel statusbar;
00153 
00154         private JTabbedPane tabPane;
00155 
00156         private JToolBar toolbar;
00157 
00158         private Tracker tracker;
00159 
00160         private JMenu trackMenu;
00161 
00162         private theba.core.Stack volume;
00163 
00164         private boolean isStopped;
00165 
00166         private JLabel statusLabel;
00167 
00168         private String fileName;
00169 
00170         private final String THEBA_VERSION_STRING = "Theba 1.0.5";
00171 
00172         public final int BYTE_TYPE = 0;
00173 
00174         public final int SHORT_TYPE = 1;
00175 
00176         private final short ID_OFFSET = 256;
00177 
00178         static int count = 0;
00179 
00180         static short[] empty;
00181 
00182         static ThebaGUI instance = null;
00183 
00184         static short[] tmp;
00185 
00186         private PluginLoader loader;
00187 
00188         private ThebaGUI() {
00189                 try {
00190                         // Set System L&F
00191                         UIManager.setLookAndFeel(
00192                                         UIManager.getSystemLookAndFeelClassName());
00193                 } 
00194                 catch (Exception e) {
00195                         // pass, not critical to set the look
00196                 }
00197                 
00198                 mainWindow = new JFrame(THEBA_VERSION_STRING);
00199                 mainWindow.setLayout(new BorderLayout());
00200                 mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
00201                 mainWindow.setSize(800, 500);
00202 
00203                 setLoader(new PluginLoader(this, "theba.jar"));
00204 
00205                 createMenu();
00206                 createImageWindow();
00207                 createStatusBar();
00208                 createToolbar();
00209                 mainWindow.setLocationRelativeTo(null);
00210 
00211                 mainWindow.setVisible(true);
00212 
00213                 showOpenDialog();
00214         }
00215 
00220         public void actionPerformed(final ActionEvent e) {
00221                 disableMenus();
00222                 (new Thread() {
00223                         public void run() {
00224                                 if (e.getActionCommand().equals("Quit")) {
00225                                         System.exit(0);
00226                                 } else if (e.getActionCommand().equals("Stop")) {
00227                                         tracker.stop();
00228                                 } else if (e.getActionCommand().equals("<html>Flip 90&deg;</html>")) {
00229                                         flipVolume();
00230                                 } else if (e.getActionCommand().equals("Installed Plugins")) {
00231                                         StringBuffer buf = new StringBuffer();
00232                                         buf.append("Installed descriptors :\n");
00233                                         ArrayList descriptors = getPluginLoader().getRegionDescriptors();
00234                                         for (int i = 0; i < descriptors.size(); i++) {
00235                                                 RegionDescriptor desc = (RegionDescriptor) descriptors.get(i);
00236                                                 buf.append("  " + desc.getName() + "\n");
00237                                         }
00238                                         buf.append("Installed trackers :\n");
00239                                         ArrayList trackers = getPluginLoader().getTrackers();
00240                                         for (int i = 0; i < trackers.size(); i++) {
00241                                                 String fullname = trackers.get(i).getClass().getName();
00242                                                 String[] fields = fullname.split("\\.");
00243                                                 buf.append(" " + fields[fields.length-1] + "\n");
00244                                         }
00245                                         buf.append("Installed plugins :\n");
00246                                         ArrayList plugins = getPluginLoader().getPlugins();
00247                                         for (int i = 0; i < plugins.size(); i++) {
00248                                                 Plugin desc = (Plugin) plugins.get(i);
00249                                                 buf.append("  " + desc.getName() + "\n");
00250                                         }
00251                                         JOptionPane.showMessageDialog(null, buf);
00252                                 } else if (e.getActionCommand().equals("About")) {
00253                                         StringBuffer buf = new StringBuffer();
00254                                         buf.append("Theba -- the image segmentation and measurement framework\n" +"<html><a href=http://theba.sourceforge.net>http://theba.sourceforge.net</a></html>\n\n");
00255                                         buf.append("Created by Per Christian Henden and Jens Bache-Wiig\n\n");
00256                                         buf.append("Uses code from the following other projects:\n");
00257                                         buf.append("JAMA - http://math.nist.gov/javanumerics/jama/ (Public domain license)\n");
00258                                         buf.append("ImageJ - http://rsb.info.nih.gov/ij/ (Public domain license)\n");
00259                                         JOptionPane.showMessageDialog(null, buf);
00260 
00261                                 } else if (e.getActionCommand().equals("Save...")) {
00262                                         chooser = new JFileChooser();
00263 
00264                                         chooser.showSaveDialog(null);
00265                                         File outFile = chooser.getSelectedFile();
00266                                         System.out.println("You selected " + outFile);
00267                                         if (outFile != null) {
00268                                                 try {
00269                                                         FileOutputStream fs = new FileOutputStream(outFile);
00270                                                         DataOutputStream fo = new DataOutputStream(fs);
00271                                                         int i;
00272                                                         byte[] tmp;
00273                                                         for (i = 0; i < depth; i++) {
00274                                                                 short[] data = getSlice(i);
00275                                                                 tmp = DataConversion.shortToBytes(data);
00276                                                                 fo.write(tmp);
00277                                                                 setProgress(i);
00278                                                         }
00279                                                         if (i < depth) {
00280                                                                 JOptionPane.showMessageDialog(null, "There isn't that many slices. You get " + (i + 1));
00281                                                                 depth = i;
00282                                                         }
00283                                                         fs.close();
00284                                                 } catch (IOException e2) {
00285                                                         JOptionPane.showMessageDialog(mainWindow, e2.getMessage());
00286                                                         enableMenus();
00287                                                 }
00288                                                 updateImage();
00289                                                 depthSlider.setMaximum(depth - 1);
00290                                                 setProgress(depth);
00291                                                 mainWindow.repaint();
00292                                         }
00293                                 }
00294                                 enableMenus();
00295                         }
00296                 }).start();
00297         }
00298 
00305         public void fiberChordMeasurements() {
00306                 final Stack stack = getStack();
00307                 double length = 0;
00308                 double count = 0;
00309                 double total = 0;
00310                 double nlength = 0;
00311                 double ncount = 0;
00312                 double ntotal = 0;
00313 
00314                 for (int x = 0; x < stack.getWidth(); x++) {
00315                         setProgressbar(x, stack.getWidth());
00316 
00317                         if (isStopped())
00318                                 return;
00319 
00320                         for (int y = 0; y < stack.getHeight(); y++) {
00321                                 for (int z = 0; z < stack.getDepth(); z++) {
00322                                         short voxel = stack.getVoxel(x, y, z);
00323                                         if (voxel == 0 && z < stack.getDepth())
00324                                                 length++;
00325                                         else if (length > 0) {
00326                                                 count++;
00327                                                 total += length;
00328                                                 length = 0;
00329                                         }
00330                                         if (voxel != 0 && z < stack.getDepth())
00331                                                 nlength++;
00332                                         else if (nlength > 0) {
00333                                                 ncount++;
00334                                                 ntotal += nlength;
00335                                                 nlength = 0;
00336                                         }
00337                                 }
00338                         }
00339                 }
00340 
00341                 double zaverageLength = total / (double) count;
00342                 double zaverageLength_inverse = ntotal / (double) ncount;
00343 
00344                 length = 0;
00345                 total = 0;
00346                 count = 0;
00347                 nlength = 0;
00348                 ntotal = 0;
00349                 ncount = 0;
00350 
00351                 for (int x = 0; x < stack.getWidth(); x++) {
00352                         setProgressbar(x, stack.getWidth());
00353                         if (isStopped())
00354                                 return;
00355                         for (int z = 0; z < stack.getDepth(); z++) {
00356                                 for (int y = 0; y < stack.getHeight(); y++) {
00357                                         short voxel = stack.getVoxel(x, y, z);
00358 
00359                                         if (voxel == 0 && y < stack.getHeight())
00360                                                 length++;
00361                                         else if (length > 0) {
00362                                                 count++;
00363                                                 total += length;
00364                                                 length = 0;
00365                                         }
00366                                         if (voxel != 0 && y < stack.getHeight())
00367                                                 nlength++;
00368                                         else if (nlength > 0) {
00369                                                 ncount++;
00370                                                 ntotal += nlength;
00371                                                 nlength = 0;
00372                                         }
00373                                 }
00374                         }
00375                 }
00376 
00377                 double yaverage = total / count;
00378                 double yaverage_inverse = ntotal / ncount;
00379 
00380                 length = 0;
00381                 total = 0;
00382                 count = 0;
00383                 nlength = 0;
00384                 ntotal = 0;
00385                 ncount = 0;
00386 
00387                 for (int y = 0; y < stack.getHeight(); y++) {
00388                         setProgressbar(y, stack.getHeight());
00389                         if (isStopped())
00390                                 return;
00391                         for (int z = 0; z < stack.getDepth(); z++) {
00392                                 for (int x = 0; x < stack.getWidth(); x++) {
00393                                         short voxel = stack.getVoxel(x, y, z);
00394                                         if (voxel == 0 && x < stack.getWidth())
00395                                                 length++;
00396                                         else if (length > 0) {
00397                                                 count++;
00398                                                 total += length;
00399                                                 length = 0;
00400                                         }
00401                                         if (voxel != 0 && x < stack.getWidth())
00402                                                 nlength++;
00403                                         else if (nlength > 0) {
00404                                                 ncount++;
00405                                                 ntotal += nlength;
00406                                                 nlength = 0;
00407                                         }
00408                                 }
00409                         }
00410                 }
00411 
00412                 double xaverage = total / count;
00413                 double xaverage_inverse = ntotal / ncount;
00414 
00415                 showResults(" Average length zero values x = " + xaverage + " y = " + yaverage + " z = " + zaverageLength);
00416                 showResults(" Average length non_zero values x = " + xaverage_inverse + " y = " + yaverage_inverse + " z = " + zaverageLength_inverse);
00417         }
00418 
00428         public void addChannel(SliceReader reader, String name) {
00429                 boolean found = false;
00430                 for (int i = 0; i < tabPane.getComponentCount(); i++)
00431                         if (tabPane.getComponent(i).getName().equals(name))
00432                                 found = true;
00433                 if (!found) {
00434                         ImagePane newPane = new ImagePane(this, reader);
00435                         JScrollPane sp = new JScrollPane(newPane);
00436                         sp.setName(name);
00437                         tabPane.add(sp);
00438                 }
00439         }
00440 
00450         public void addMenuItem(String title, final Runnable action) {
00451                 JMenuItem menuItem = new JMenuItem(title);
00452                 ActionListener threadListener = new ActionListener() {
00453                         public void actionPerformed(final ActionEvent arg0) {
00454                                 Thread r = new Thread() {
00455                                         public void run() {
00456                                                 disableMenus();
00457                                                 action.run();
00458                                                 enableMenus();
00459                                         }
00460                                 };
00461                                 r.start();
00462                         };
00463                 };
00464                 menuItem.addActionListener(threadListener);
00465                 trackMenu.add(menuItem);
00466         }
00467 
00468         public void addMenuSeparator() {
00469                 trackMenu.addSeparator();
00470         }
00471 
00477         public void addToolbarButton(JComponent customButton) {
00478                 if (customButton instanceof JToggleButton) {
00479                         buttonGroup.add((JToggleButton) customButton);
00480                 }
00481                 toolbar.add(new JLabel("Tracker tools :"));
00482                 toolbar.add(customButton);
00483         }
00484 
00490         public void clearChannels() {
00491                 tabPane.setSelectedIndex(0);
00492         }
00493 
00497         private void createImageWindow() {
00498                 iw = new ImagePane(this);
00499                 scrollpane = new JScrollPane(iw);
00500                 depthSlider = new JSlider();
00501                 depthSlider.addChangeListener(new ChangeListener() {
00502                         public void stateChanged(ChangeEvent e) {
00503                                 JScrollPane spane = (JScrollPane) tabPane.getSelectedComponent();
00504                                 ImagePane ipane = (ImagePane) spane.getViewport().getComponent(0); // fetch image pane from scrollpane
00505                                 ipane.updateData(currentSlice());
00506                                 labeltext = "Stack " + currentSlice() + "/" + (depth - 1);
00507                                 stackLabel.setText(labeltext + pixeltext);
00508                                 mainWindow.repaint();
00509                         }
00510                 });
00511                 depthSlider.setOrientation(JSlider.VERTICAL);
00512                 scrollpane.setName("Main view");
00513                 scrollpane.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
00514                 tabPane = new JTabbedPane();
00515                 tabPane.add(scrollpane);
00516                 tabPane.addChangeListener(new ChangeListener() {
00517                         public void stateChanged(ChangeEvent e) {
00518                                 if (tabPane.getSelectedIndex() == 0) {
00519                                         iw.setData(getSlice(currentSlice()), width, height);
00520                                 } else {
00521                                         JScrollPane spane = (JScrollPane) tabPane.getSelectedComponent();
00522                                         ImagePane ipane = (ImagePane) spane.getViewport().getComponent(0); // fetch image pane from scrollpane
00523                                         ipane.showSlice(currentSlice());
00524                                 }
00525                         };
00526                 });
00527                 mainWindow.add(tabPane, BorderLayout.CENTER);
00528                 mainWindow.add(depthSlider, BorderLayout.EAST);
00529                 iw.addMouseListener(new MouseClickListener());
00530         }
00531 
00535         private void createMenu() {
00536                 menuBar = new JMenuBar();
00537                 fileMenu = new JMenu("File");
00538                 fileMenu.setMnemonic('f');
00539                 JMenuItem fileOpenItem = new JMenuItem("Open...");
00540                 fileOpenItem.setAccelerator(KeyStroke.getKeyStroke('o'));
00541                 fileOpenItem.addActionListener(new ActionListener() {
00542                         public void actionPerformed(ActionEvent e) {
00543                                 (new Thread() {
00544                                         public void run() {
00545                                                 showOpenDialog();
00546                                         }
00547                                 }).start();
00548                         }
00549                 });
00550                 fileMenu.add(fileOpenItem);
00551                 JMenuItem saveItem = new JMenuItem("Save...");
00552                 saveItem.setAccelerator(KeyStroke.getKeyStroke('s'));
00553                 fileMenu.add(saveItem);
00554                 saveItem.addActionListener(this);
00555                 JMenuItem quitItem = new JMenuItem("Quit");
00556                 quitItem.setMnemonic('q');
00557                 fileMenu.add(quitItem);
00558                 quitItem.addActionListener(this);
00559                 filterMenu = new JMenu("Filters");
00560                 filterMenu.setMnemonic('i');
00561                 flipItem = new JMenuItem("<html>Flip 90&deg;</html>");
00562                 trackMenu = new JMenu("Track");
00563                 trackMenu.setMnemonic('t');
00564                 JMenu helpMenu = new JMenu("Help");
00565                 JMenu filterHelpMenu = new JMenu("Filter");
00566                 helpMenu.add(filterHelpMenu);
00567                 ArrayList<Plugin> plugins = getPluginLoader().getPlugins();
00568 
00569                 if (plugins != null){
00570                         for (final Plugin p : plugins) {
00571                                 p.setup(this);
00572 
00573                                 final JMenuItem item = new JMenuItem(p.getName());
00574 
00575                                 item.addActionListener(new ActionListener() {
00576                                         public void actionPerformed(ActionEvent e) {
00577                                                 disableMenus();
00578                                                 (new Thread() {
00579                                                         public void run() {
00580                                                                 p.process(volume);
00581                                                                 updateImage();
00582                                                                 enableMenus();
00583                                                         }
00584                                                 }).start();
00585                                         };
00586                                 });
00587 
00588                                 final JMenuItem helpitem = new JMenuItem(p.getName());
00589                                 helpitem.addActionListener(new ActionListener() {
00590                                         public void actionPerformed(ActionEvent e) {
00591                                                 if (p.getAbout() == null)
00592                                                         JOptionPane.showMessageDialog(mainWindow, "No description available");
00593                                                 else
00594                                                         JOptionPane.showMessageDialog(mainWindow, p.getAbout());
00595                                         };
00596                                 });
00597                                 filterHelpMenu.add(helpitem);
00598 
00599                                 // Group catecories in sub-menus :
00600                                 if (p.getCategory() != null) {
00601 
00602                                         // search for existing category, if not found create a new
00603 
00604                                         JMenu category = null;
00605                                         Component[] components = filterMenu.getMenuComponents();
00606                                         for (int j = 0; j < components.length; j++) {
00607                                                 Component s = components[j];
00608                                                 if (s.getName() != null) {
00609                                                         if (s.getName().equals(p.getCategory())) {
00610                                                                 category = (JMenu) s;
00611                                                         }
00612                                                 }
00613                                         }
00614                                         if (category == null) {
00615                                                 category = new JMenu(p.getCategory());
00616                                                 category.setName(p.getCategory());
00617                                                 filterMenu.add(category);
00618                                         }
00619                                         category.add(item);
00620                                 } else {
00621                                         filterMenu.add(item);
00622                                 }
00623 
00624                         }
00625                 }
00626 
00627                 JMenu regionHelpMenu = new JMenu("Region descriptors");
00628                 ArrayList<RegionDescriptor> descriptors = getPluginLoader().getRegionDescriptors();
00629                 if (descriptors != null){
00630                         for (final RegionDescriptor p : descriptors) {
00631                                 final JMenuItem helpitem = new JMenuItem(p.getName());
00632                                 helpitem.addActionListener(new ActionListener() {
00633                                         public void actionPerformed(ActionEvent e) {
00634                                                 if (p.getAbout() == null)
00635                                                         JOptionPane.showMessageDialog(mainWindow, "No description available");
00636                                                 else
00637                                                         JOptionPane.showMessageDialog(mainWindow, p.getAbout());
00638                                         };
00639                                 });
00640                                 regionHelpMenu.add(helpitem);
00641                         }
00642                         helpMenu.add(regionHelpMenu);
00643                 }
00644 
00645                 filterMenu.addSeparator();
00646                 JMenuItem removeMarkedVoxels = new JMenuItem("Remove marked");
00647                 removeMarkedVoxels.addActionListener(new ActionListener() {
00648                         public void actionPerformed(ActionEvent e) {
00649                                 final Stack activeVolume = getCurrentView().getVolume();
00650                                 disableMenus();
00651                                 Thread r = new Thread() {
00652                                         public void run() {
00653                                                 byte ff = (byte) 0xff;
00654                                                 int count = 0;
00655                                                 for (int z = 0; z < activeVolume.getDepth(); z++) {
00656                                                         if (isStopped)
00657                                                                 return;
00658                                                         setProgress(z);
00659                                                         short[] slice = activeVolume.getSlice(z);
00660                                                         for (int i = 0; i < slice.length; i++) {
00661                                                                 if (slice[i] != 0 && slice[i] != ff) {
00662                                                                         count++;
00663                                                                         slice[i] = 0;
00664                                                                 }
00665                                                         }
00666                                                 }
00667                                                 activeVolume.flush();
00668                                                 StringBuffer output = new StringBuffer();
00669                                                 output.append("Removed " + count + " voxels \n");
00670                                                 showResults(output, "Voxelcount");
00671                                                 enableMenus();
00672                                                 updateImage();
00673                                         }
00674                                 };
00675                                 r.start();
00676                         }
00677                 });
00678 
00679                 JMenuItem removeSmallRegions = new JMenuItem("Remove small labeled regions");
00680                 removeSmallRegions.addActionListener(new ActionListener() {
00681                         public void actionPerformed(ActionEvent e) {
00682                                 Thread r = new Thread() {
00683                                         public void run() {
00684 
00685                                                 String input = JOptionPane.showInputDialog(null, "Enter minmum regsize.", 100);
00686                                                 if (input == null) return;
00687 
00688                                                 int tval = Integer.parseInt(input);
00689 
00690                                                 setLabel("Creating histogram...");
00691                                                 long[] histo = new long[MAX_FIBERS + 256];
00692                                                 for (int z = 0; z < volume.getDepth(); z++) {
00693                                                         setProgress(z);
00694                                                         short[] slice = volume.getSlice(z);
00695                                                         for (int i = 0; i < slice.length; i++) {
00696                                                                 histo[slice[i]]++;
00697                                                         }
00698                                                 }
00699                                                 setLabel("Removing regions");
00700 
00701                                                 for (int z = 0; z < volume.getDepth(); z++) {
00702                                                         setProgress(z);
00703                                                         short[] slice = volume.getSlice(z);
00704                                                         for (int i = 0; i < slice.length; i++) {
00705                                                                 if (histo[slice[i]] < tval) slice[i] = 0;
00706                                                         }
00707                                                 }
00708                                                 enableMenus();
00709                                                 updateImage();
00710                                         }
00711 
00712                                 };
00713                                 disableMenus();
00714                                 r.start();
00715                         }
00716                 });
00717 
00718                 JMenuItem removeUnmarkedVoxels = new JMenuItem("Remove unlabeled");
00719                 removeUnmarkedVoxels.addActionListener(new ActionListener() {
00720                         public void actionPerformed(ActionEvent e) {
00721                                 final Stack activeVolume = getCurrentView().getVolume();
00722                                 disableMenus();
00723                                 Thread r = new Thread() {
00724                                         public void run() {
00725                                                 int count = 0;
00726                                                 for (int z = 0; z < activeVolume.getDepth(); z++) {
00727                                                         if (isStopped)
00728                                                                 return;
00729                                                         setProgress(z);
00730                                                         short[] slice = activeVolume.getSlice(z);
00731                                                         for (int i = 0; i < slice.length; i++) {
00732                                                                 if (slice[i] == 255) {
00733                                                                         count++;
00734                                                                         slice[i] = 0;
00735                                                                 }
00736                                                         }
00737                                                 }
00738                                                 activeVolume.flush();
00739                                                 StringBuffer output = new StringBuffer();
00740                                                 output.append("Removed " + count + " voxels \n");
00741                                                 showResults(output, "Voxelcount");
00742                                                 enableMenus();
00743                                                 updateImage();
00744                                         }
00745                                 };
00746                                 r.start();
00747                         }
00748                 });
00749 
00750                 JMenuItem resetMarkedVoxels = new JMenuItem("Remove colors");
00751                 resetMarkedVoxels.addActionListener(new ActionListener() {
00752                         public void actionPerformed(ActionEvent e) {
00753                                 final Stack activeVolume = getCurrentView().getVolume();
00754                                 disableMenus();
00755                                 Thread r = new Thread() {
00756                                         public void run() {
00757                                                 byte ff = (byte) 0xff;
00758                                                 int count = 0;
00759                                                 for (int z = 0; z < activeVolume.getDepth(); z++) {
00760                                                         setProgress(z);
00761                                                         short[] slice = activeVolume.getSlice(z);
00762                                                         for (int i = 0; i < slice.length; i++) {
00763                                                                 if (slice[i] != 0 && slice[i] != ff) {
00764                                                                         count++;
00765                                                                         slice[i] = 0;
00766                                                                 }
00767                                                         }
00768                                                 }
00769                                                 activeVolume.flush();
00770                                                 StringBuffer output = new StringBuffer();
00771                                                 output.append("Reset " + count + " voxels \n");
00772                                                 showResults(output, "Voxelcount");
00773                                                 enableMenus();
00774                                                 updateImage();
00775                                         }
00776                                 };
00777                                 r.start();
00778                         }
00779                 });
00780 
00781                 JMenuItem resetLabels = new JMenuItem("Reset labels");
00782                 resetMarkedVoxels.addActionListener(new ActionListener() {
00783                         public void actionPerformed(ActionEvent e) {
00784                                 final Stack activeVolume = getCurrentView().getVolume();
00785                                 disableMenus();
00786                                 Thread r = new Thread() {
00787                                         public void run() {
00788                                                 int count = 0;
00789                                                 for (int z = 0; z < activeVolume.getDepth(); z++) {
00790                                                         setProgress(z);
00791                                                         short[] slice = activeVolume.getSlice(z);
00792                                                         for (int i = 0; i < slice.length; i++) {
00793                                                                 if (slice[i] != 0) {
00794                                                                         count++;
00795                                                                         slice[i] = 255;
00796                                                                 }
00797                                                         }
00798                                                 }
00799                                                 activeVolume.flush();
00800                                                 StringBuffer output = new StringBuffer();
00801                                                 output.append("Reset " + count + " voxels \n");
00802                                                 showResults(output, "Voxelcount");
00803                                                 enableMenus();
00804                                                 updateImage();
00805                                         }
00806                                 };
00807                                 r.start();
00808                         }
00809                 });
00810 
00811                 filterMenu.add(removeMarkedVoxels);
00812                 filterMenu.add(removeUnmarkedVoxels);
00813                 filterMenu.add(resetMarkedVoxels);
00814                 filterMenu.add(resetLabels);
00815                 filterMenu.addSeparator();
00816                 filterMenu.add(removeSmallRegions);
00817 
00818                 filterMenu.addSeparator();
00819 
00820                 flipItem.addActionListener(this);
00821                 filterMenu.add(flipItem);
00822                 helpMenu.setMnemonic('h');
00823                 JMenuItem pluginItem = new JMenuItem("Installed Plugins");
00824                 pluginItem.addActionListener(this);
00825                 helpMenu.add(pluginItem);
00826                 JMenuItem aboutItem = new JMenuItem("About");
00827                 aboutItem.addActionListener(this);
00828                 helpMenu.add(aboutItem);
00829 
00830                 JMenu editMenu = new JMenu("Edit");
00831                 editMenu.setMnemonic('e');
00832                 JMenuItem undoItem = new JMenuItem("Undo");
00833                 JMenuItem preferencesItem = new JMenuItem("Preferences...");
00834                 preferencesItem.setMnemonic('p');
00835                 undoItem.setEnabled(false);
00836                 editMenu.add(undoItem);
00837                 editMenu.add(preferencesItem);
00838                 JMenuItem reloadItem = new JMenuItem("Reload stack");
00839                 reloadItem.setMnemonic('r');
00840                 reloadItem.setAccelerator(KeyStroke.getKeyStroke('r'));
00841                 reloadItem.addActionListener(new ActionListener() {
00842                         public void actionPerformed(ActionEvent e) {
00843                                 Thread r = new Thread() {
00844                                         public void run() {
00845                                                 loadStack();
00846                                         }
00847                                 };
00848                                 r.start();
00849                         }
00850                 });
00851                 editMenu.add(reloadItem);
00852                 preferencesItem.addActionListener(new ActionListener() {
00853                         public void actionPerformed(ActionEvent e) {
00854                                 preferences = new ThebaPrefs(mainWindow);
00855                                 preferences.setVisible(true);
00856                         }
00857                 });
00858                 analyzeMenu = new JMenu("Analyze");
00859                 analyzeMenu.setMnemonic('a');
00860 
00861                 JMenuItem fiberMenu = new JMenu("Region measurements");
00862 
00863                 JMenuItem measureAllItem = new JMenuItem("Perform all");
00864 
00865                 if (descriptors != null){
00866                         for (final RegionDescriptor d : descriptors) {
00867                                 if (d.does3D()) {
00868                                         JMenuItem item = new JMenuItem("Measure :" + d.getName());
00869                                         ActionListener listener = new ActionListener() {
00870                                                 public void actionPerformed(ActionEvent e) {
00871                                                         final Stack volume = getCurrentView().getVolume();
00872                                                         disableMenus();
00873                                                         Thread r = new Thread() {
00874                                                                 public void run() {
00875                                                                         setLabel("Counting regions...");
00876                                                                         StringBuffer buf = new StringBuffer("Bounding regions...");
00877                                                                         showResults(buf, "Results");
00878 
00879                                                                         regList = getRegions();
00880 
00881                                                                         progressbar.setMaximum(regList.size());
00882                                                                 
00883                                                                         for (int i = 0; i < regList.size(); i++) {
00884                                                                                 buf = new StringBuffer();
00885                                                                                 Region reg = (Region) regList.get(i);
00886                                                                                 setProgress(i);
00887                                                                                 if (reg == null)
00888                                                                                         continue;
00889                                                                                 regionCount++;
00890                                                                                 buf.append("ID " + reg.getId() + " ");
00891                                                                                 RegionMask mask = new RegionMask(reg.getId(), volume, reg.getBounds());
00892                                                                                 buf.append(d.measure(mask));
00893                                                                                 showResults(buf, "Results");
00894                                                                         }
00895 
00896                                                                         buf.append("\nRegioncount :" + regList.size() + " \n");
00897                                                                         progressbar.setMaximum(depth);
00898                                                                         enableMenus();
00899                                                                 }
00900 
00901                                                         };
00902                                                         r.start();
00903                                                 }
00904                                         };
00905                                         item.addActionListener(listener);
00906                                         fiberMenu.add(item);
00907                                 }
00908 
00909                         }
00910                 }
00911                 fiberMenu.add(measureAllItem);
00912 
00913                 measureAllItem.addActionListener(new RegionAnalysisAction());
00914                 JMenu bulkMenu = new JMenu("Bulk");
00915                 analyzeMenu.add(fiberMenu);
00916                 analyzeMenu.add(bulkMenu);
00917 
00918                 JMenuItem poreItem = new JMenuItem("Pore chords");
00919                 poreItem.addActionListener(new ActionListener() {
00920                         public void actionPerformed(ActionEvent e) {
00921                                 disableMenus();
00922 
00923                                 Thread r = new Thread() {
00924                                         public void run() {
00925                                                 fiberChordMeasurements();
00926                                                 enableMenus();
00927                                         }
00928                                 };
00929 
00930                                 r.start();
00931                         }
00932                 });
00933                 bulkMenu.add(poreItem);
00934 
00935                 JMenuItem calcForeGroundItem = new JMenuItem("Volume");
00936                 calcForeGroundItem.addActionListener(new RegCountAction());
00937                 JMenuItem histogramItem = new JMenuItem("Histogram");
00938                 histogramItem.addActionListener(new HistogramAction());
00939                 bulkMenu.add(calcForeGroundItem);
00940                 bulkMenu.add(histogramItem);
00941                 JMenu viewMenu = new JMenu("View");
00942                 viewMenu.setMnemonic('v');
00943                 hideWhite = new JCheckBoxMenuItem("Hide unlabeled");
00944                 viewMenu.add(hideWhite);
00945                 menuBar.add(fileMenu);
00946                 menuBar.add(editMenu);
00947                 menuBar.add(viewMenu);
00948                 menuBar.add(filterMenu);
00949                 menuBar.add(trackMenu);
00950                 menuBar.add(analyzeMenu);
00951                 menuBar.add(helpMenu);
00952                 mainWindow.setJMenuBar(menuBar);
00953         }
00954 
00958         private void createStatusBar() {
00959                 statusbar = new JPanel();
00960                 mainWindow.add(statusbar, BorderLayout.SOUTH);
00961                 stackLabel = new JLabel("Stack 0/0");
00962                 statusLabel = new JLabel();
00963                 statusbar.add(statusLabel);
00964                 statusbar.add(stackLabel);
00965                 progressbar = new JProgressBar();
00966                 progressbar.setPreferredSize(new Dimension(300, 10));
00967                 progressbar.setForeground(mainWindow.getBackground().darker());
00968                 statusbar.add(progressbar);
00969                 statusbar.setLayout(new FlowLayout(FlowLayout.RIGHT));
00970         }
00971 
00975         private void createToolbar() {
00976                 if (toolbar == null) {
00977                         toolbar = new JToolBar("tools");
00978                         toolbar.setLayout(new FlowLayout(FlowLayout.LEADING));
00979                         measureButton = new JToggleButton("Measure 2D");
00980                         measureButton3d = new JToggleButton("Measure 3D");
00981                         seedButton3d = new JToggleButton("Fill ");
00982                         idSelector = new JTextField("255");
00983                         stopButton = new JButton("Stop");
00984                         stopButton.setForeground(Color.red);
00985                         stopButton.setEnabled(false);
00986                         stopButton.addActionListener(new ActionListener() {
00987                                 public void actionPerformed(ActionEvent e) {
00988                                         tracker.stop();
00989                                         isStopped = true;
00990                                         enableMenus();
00991                                 }
00992                         });
00993                         idSelector.setColumns(4);
00994                         deleteButton = new JToggleButton("Delete");
00995                         buttonGroup = new ButtonGroup();
00996                         buttonGroup.add(seedButton3d);
00997                         buttonGroup.add(deleteButton);
00998                         buttonGroup.add(measureButton);
00999                         buttonGroup.add(measureButton3d);
01000                         hideWhite.addActionListener(new ActionListener() {
01001                                 public void actionPerformed(ActionEvent e) {
01002                                         updateImage();
01003                                 }
01004                         });
01005 
01006                         idSelector.addActionListener(new ActionListener() {
01007                                 public void actionPerformed(ActionEvent e) {
01008                                         try {
01009                                                 selectedRegion = Short.parseShort(idSelector.getText());
01010                                                 System.out.println(selectedRegion);
01011                                         } catch (NumberFormatException e2) {
01012                                                 selectedRegion = 0;
01013                                                 idSelector.setText("0");
01014                                         }
01015                                 }
01016                         });
01017                 } else {
01018                         mainWindow.remove(toolbar);
01019                         toolbar = new JToolBar();
01020                         toolbar.setLayout(new FlowLayout(FlowLayout.LEADING));
01021                         mainWindow.add(toolbar, BorderLayout.NORTH);
01022                 }
01023                 toolbar.add(new JLabel("General tools:"));
01024                 toolbar.add(measureButton);
01025                 toolbar.add(measureButton3d);
01026                 toolbar.addSeparator();
01027                 toolbar.add(seedButton3d);
01028                 toolbar.add(idSelector);
01029                 toolbar.add(deleteButton);
01030                 toolbar.addSeparator();
01031                 statusbar.add(stopButton);
01032                 toolbar.addSeparator();
01033         }
01034 
01040         public synchronized int currentSlice() {
01041                 return depthSlider.getValue();
01042         }
01043 
01049         private void disableMenus() {
01050                 isStopped = false;
01051                 stopButton.setEnabled(true);
01052                 mainWindow.setCursor(new Cursor(Cursor.WAIT_CURSOR));
01053                 menuEnabled = false;
01054                 toolbar.setEnabled(false);
01055                 fileMenu.setEnabled(false);
01056                 filterMenu.setEnabled(false);
01057                 trackMenu.setEnabled(false);
01058                 menuBar.setEnabled(false);
01059                 analyzeMenu.setEnabled(false);
01060                 seedButton3d.setEnabled(false);
01061                 deleteButton.setEnabled(false);
01062         }
01063 
01068         private void enableMenus() {
01069                 stopButton.setEnabled(false);
01070                 mainWindow.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
01071                 menuEnabled = true;
01072                 analyzeMenu.setEnabled(true);
01073                 toolbar.setEnabled(true);
01074                 fileMenu.setEnabled(true);
01075                 filterMenu.setEnabled(true);
01076                 trackMenu.setEnabled(true);
01077                 deleteButton.setEnabled(true);
01078                 seedButton3d.setEnabled(true);
01079                 setProgressComplete();
01080         }
01081 
01088         public void flipVolume() {
01089                 try {
01090                         RandomAccessFile file2 = new RandomAccessFile("temp_vol.raw", "rw");
01091                         volume.flush();
01092                         progressbar.setMaximum(width);
01093                         for (int x = 0; x < width; x++) {
01094                                 if (isStopped) {
01095                                         return;
01096                                 }
01097                                 setProgress(x / 2);
01098                                 short[] nslice = new short[depth * height];
01099                                 for (int z = 0; z < depth; z++) {
01100                                         short[] slice = getSlice(z);
01101                                         for (int y = 0; y < height; y++) {
01102                                                 nslice[z + y * depth] = (short) (slice[x + y * width]);
01103                                         }
01104                                 }
01105                                 file2.write(DataConversion.shortToBytes(nslice));
01106                         }
01107                         file2.close();
01108                 } catch (Exception e) {
01109                         e.printStackTrace();
01110                 }
01111 
01112                 datawriter.destroy(); // frees up allocated resources
01113 
01114                 int tmp = width;
01115                 width = depth;
01116                 depth = tmp;
01117                 disableMenus();
01118                 inputType = SHORT_TYPE;
01119 
01120                 String tmpName = fileName;
01121                 fileName = "temp_vol.raw";
01122                 loadStack();
01123                 fileName = tmpName;
01124                 tracker.reset();
01125                 enableMenus();
01126 
01127         }
01128 
01134         public short[] getCurrentPixels() {
01135                 return getSlice(currentSlice());
01136         }
01137 
01143         public ImagePane getCurrentView() {
01144                 if (tabPane.getSelectedIndex() == 0) {
01145                         return iw;
01146                 }
01147                 JScrollPane spane = (JScrollPane) tabPane.getSelectedComponent();
01148                 ImagePane ipane = (ImagePane) spane.getViewport().getComponent(0); // fetch image pane from scrollpane
01149                 return ipane;
01150         }
01151 
01159         public ThebaPrefs getPreferences() {
01160                 if (preferences == null)
01161                         preferences = new ThebaPrefs(mainWindow);
01162                 return preferences;
01163         }
01164 
01165 
01166 
01175         public short[] getSlice(int z) {
01176                 VolumeReader ip = getCurrentView().getSliceReader();
01177                 if (ip == null)
01178                         return null;
01179                 return ip.getSlice(z);
01180         }
01181 
01186         public Tracker getCurrentTracker() {
01187                 return tracker;
01188         }
01189 
01190 
01194         public Stack getStack() {
01195                 return getCurrentView().getVolume();
01196         }
01197 
01204         public JFrame getWindow() {
01205                 return mainWindow;
01206         }
01207 
01212         public JCheckBoxMenuItem hideWhite() {
01213                 return hideWhite;
01214         }
01215 
01221         public boolean isMinimized() {
01222                 if (mainWindow.getState() != Frame.ICONIFIED)
01223                         return false;
01224                 return true;
01225         }
01226 
01231         private void loadStack() {
01232                 volume = null;
01233                 if (datawriter != null)
01234                         datawriter.destroy();
01235                 initIdList();
01236                 disableMenus();
01237                 SliceReader sr = new SliceReader(fileName, width, height, depth, 0);
01238                 if (getPreferences().getInt("use_cached_access", 0) == 0) {
01239                         datawriter = new HeapReader(width, height, depth);
01240                         volume = new Stack(datawriter);
01241                 } else {
01242                         volume = new Stack(width, height, depth, getPreferences().getString("tempFileName", "temp.raw"));
01243                         datawriter = volume.getWriter();
01244                 }
01245                 iw.setReader(datawriter);
01246                 depthSlider.setMaximum(depth - 1);
01247                 progressbar.setMaximum(depth - 1);
01248                 RandomAccessFile ra = sr.getFile();
01249                 totalCount = 0;
01250 
01251                 for (int i = 0; i < depth; i++) {
01252 
01253                         if (isStopped)
01254                                 return;
01255 
01256                         if (inputType == BYTE_TYPE) {
01257                                 short[] data = new short[width * height];
01258                                 byte[] ba = new byte[data.length];
01259                                 try {
01260                                         ra.readFully(ba);
01261                                 } catch (IOException e) {
01262                                         //ignore
01263                                 }
01264                                 for (int j = 0; j < data.length; j++) {
01265                                         data[j] = (short) (ba[j] & 0xff);
01266                                 }
01267                                 datawriter.putSlice(data, i);
01268                         } else if (inputType == SHORT_TYPE) {
01269                                 short[] slice = sr.getSlice((i));
01270                                 for (int g = 0; g < slice.length; g++) {
01271                                         if (slice[g] != 0 && slice[g] > 255) {
01272                                                 removeFiberId(slice[g]);
01273                                         }
01274                                 }
01275                                 datawriter.putSlice(slice, i);
01276                         }
01277                         setProgress(i);
01278                 }
01279                 setLabel("Found " + totalCount + " regions.");
01280                 sr.close();
01281                 depthSlider.setValue(0);
01282                 updateImage();
01283                 tracker.reset();
01284                 enableMenus();
01285         }
01286 
01295         private void measure(Point pt) {
01296 
01297                 if (pt.x < 0 || pt.x >= width || pt.y < 0 || pt.y >= height)
01298                         return;
01299 
01300                 byte ff = (byte) 0xff;
01301                 short[] data = getCurrentPixels().clone();
01302                 short[] mask = new short[data.length];
01303                 ImageFunctions.floodFill2D(pt.x, pt.y, width, height, data, mask, ff);
01304                 StringBuffer output = new StringBuffer();
01305                 ArrayList descriptors = getPluginLoader().getRegionDescriptors();
01306                 short id = volume.getVoxel(pt.x, pt.y, currentSlice());
01307                 output.append("Region id " + id + "\n");
01308                 for (int i = 0; i < descriptors.size(); i++) {
01309                         RegionMask2D maskreg = new RegionMask2D(mask, width, height);
01310                         RegionDescriptor descriptor = (RegionDescriptor) descriptors.get(i);
01311                         if (maskreg == null){
01312                                 System.err.println("Got null regionmask");
01313                         }
01314                         if (descriptor == null){
01315                                 System.err.println("Got null descriptor");
01316                         }
01317                         if (!descriptor.does3D())
01318                                 output.append(descriptor.getName() + " : " + descriptor.measure(maskreg) + "\n");
01319                 }
01320                 showResults(output, "region");
01321                 for (int i = 0; i < data.length; i++)
01322                         if (mask[i] != 0)
01323                                 data[i] = 256;
01324 
01325                 showImage(data);
01326 
01327                 try {
01328                         Thread.sleep(500);
01329                 } catch (InterruptedException e) {
01330                         // ignore
01331                 }
01332                 updateImage();
01333         }
01334 
01343         private void measure3D(Point3D pt) {
01344                 short id = volume.getVoxel(pt.x, pt.y, pt.z);
01345                 ArrayList descriptors = getPluginLoader().getRegionDescriptors();
01346 
01347                 StringBuffer output = new StringBuffer();
01348                 output.append("Region id " + id + "\n");
01349 
01350                 RegionMask mask = getRegionMask(id);
01351                 for (int i = 0; i < descriptors.size(); i++) {
01352                         RegionDescriptor descriptor = (RegionDescriptor) descriptors.get(i);
01353                         if (descriptor.does3D()) {
01354                                 output.append(descriptor.getName() + " : " + descriptor.measure(mask) + "\n");
01355                         }
01356                         setProgress(progressbar.getValue() + 4); // this is a dirty hack to give the user some feedback
01357                 }
01358                 showResults(output, "region");
01359 
01360         }
01361 
01369         private RegionMask getRegionMask(short id) {
01370                 Region reg = null;
01371                 short[] markImage = getCurrentPixels().clone();
01372 
01373                 for (int z = 0; z < depth; z++) {
01374 
01375                         setProgress(z / 2);
01376 
01377                         short[] slice = getSlice(z);
01378                         for (int x = 0; x < width; x++) {
01379                                 for (int y = 0; y < height; y++) {
01380                                         int i = x + y * width;
01381                                         if (slice[i] == id) {
01382                                                 if (z == currentSlice())
01383                                                         markImage[i] = 256;
01384                                                 if (reg == null) {
01385                                                         BoxBounds bounds = new BoxBounds();
01386                                                         reg = new Region(id, bounds);
01387                                                 }
01388                                                 reg.getBounds().update(x, y, z);
01389                                                 reg.size++;
01390                                         }
01391                                 }
01392                         }
01393 
01394                 }
01395 
01396                 reg.getBounds().printSize();
01397                 RegionMask mask = new RegionMask(reg.getId(), volume, reg.getBounds());
01398                 showImage(markImage);
01399 
01400                 return mask;
01401         }
01402 
01412         public void putSlice(short[] data, int z) {
01413                 datawriter.putSlice(data, z);
01414         }
01415 
01423         public void setPointerLabel(Point p) {
01424                 if (volume == null)
01425                         return;
01426                 pixeltext = " x " + p.x + " y " + p.y;
01427                 short[] curr = getSlice(currentSlice());
01428                 int pixval = 0;
01429                 if (curr != null && p.x >= 0 && p.y >= 0 && p.x < width && p.y < height)
01430                         pixval = getCurrentPixels()[p.x + p.y * width];
01431                 stackLabel.setPreferredSize(new Dimension(190, 15));
01432                 stackLabel.setBorder(new EmptyBorder(3, 3, 3, 3));
01433                 stackLabel.setText(labeltext + pixeltext + " " + pixval + " ");
01434         }
01435 
01440         public void setProgress(final int val) {
01441                 try {
01442                         SwingUtilities.invokeAndWait(new Thread() {
01443                                 public void run() {
01444                                         progressbar.setValue(val);
01445                                         progressbar.repaint();
01446                                 };
01447                         });
01448                 } catch (InterruptedException e) {
01449                         e.printStackTrace();
01450                 } catch (InvocationTargetException e) {
01451                         e.printStackTrace();
01452                 }
01453         }
01454 
01458         public void setProgressComplete() {
01459                 SwingUtilities.invokeLater(new Thread() {
01460                         public void run() {
01461                                 progressbar.setValue(progressbar.getMaximum());
01462                         };
01463                 });
01464         }
01465 
01474         public void showImage(final short[] data) {
01475                 SwingUtilities.invokeLater(new Thread() {
01476                         public void run() {
01477                                 iw.setData(data, width, height);
01478                                 iw.repaint();
01479                         };
01480                 });
01481         }
01482 
01486         private void showOpenDialog() {
01487                 OpenDialog dialog = new OpenDialog(this);
01488                 if (dialog != null){
01489                         dialog.setVisible(true);
01490                         dialog.toFront();
01491                         while (dialog.isVisible())
01492                                 Thread.yield();
01493                         if (dialog.isCanceled())
01494                                 return;
01495                         width = dialog.getVolumeWidth();
01496                         height = dialog.getVolumeHeight();
01497                         depth = dialog.getVolumeDepth();
01498                         mainWindow.setVisible(true);
01499                         inputType = dialog.getDataType();
01500                         tracker = dialog.getSelectedTracker();
01501                         createToolbar();
01502                         trackMenu.removeAll();
01503                         tracker.setup();
01504                         fileName = getPreferences().getString("fileName", "data.raw");
01505                         loadStack();
01506                 }
01507         }
01514         public void showResults(String s) {
01515                 StringBuffer buf = new StringBuffer(s);
01516                 showResults(buf, "Results");
01517         }
01518 
01528         public void showResults(final StringBuffer results, String title) {
01529                 results.append("\n");
01530                 if (resultWindow == null) {
01531                         area = new JTextArea();
01532                         resultScrollPane = new JScrollPane(area);
01533                         resultWindow = new JFrame();
01534                         JButton saveLogButton = new JButton("Save log...");
01535                         saveLogButton.addActionListener(new ActionListener() {
01536                                 public void actionPerformed(ActionEvent e) {
01537                                         if (chooser == null)
01538                                                 chooser = new JFileChooser();
01539                                         int retval = chooser.showSaveDialog(mainWindow);
01540                                         if (retval != JFileChooser.CANCEL_OPTION) {
01541                                                 File f = chooser.getSelectedFile();
01542                                                 try {
01543                                                         PrintStream fo = new PrintStream(f);
01544                                                         fo.print(area.getText());
01545                                                         fo.close();
01546                                                 } catch (FileNotFoundException e1) {
01547                                                         JOptionPane.showMessageDialog(mainWindow, "Error, could not save logfile to " + f);
01548                                                 }
01549                                         }
01550                                 }
01551                         });
01552                         JButton clearLogButton = new JButton("Clear");
01553                         clearLogButton.addActionListener(new ActionListener() {
01554                                 public void actionPerformed(ActionEvent e) {
01555                                         area.setText("");
01556                                 }
01557                         });
01558                         JPanel topPanel = new JPanel(new FlowLayout());
01559                         topPanel.add(saveLogButton);
01560                         topPanel.add(clearLogButton);
01561                         resultWindow.add(topPanel, BorderLayout.SOUTH);
01562                         resultWindow.add(resultScrollPane, BorderLayout.CENTER);
01563                         resultWindow.setLocationRelativeTo(mainWindow);
01564                         resultWindow.setLocation((int) mainWindow.getX(), (int) mainWindow.getY() + mainWindow.getHeight());
01565                         resultWindow.setSize(new Dimension(mainWindow.getWidth(), 300));
01566                 }
01567                 area.insert(results.toString(),0); //prepend the text
01568                 resultScrollPane.setViewportView(area);
01569                 resultWindow.setTitle("Results : " + title);
01570                 if (!resultWindow.isVisible())
01571                         resultWindow.setVisible(true);
01572         }
01573 
01578         public void updateImage() {
01579                 (new Thread() {
01580                         public void run() {
01581                                 getCurrentView().updateData(currentSlice());
01582                         };
01583                 }).start();
01584         }
01585 
01592         public void updateSlice(final int z) {
01593                 Thread r = new Thread() {
01594                         public void run() {
01595                                 if (z < 0 || z > depth)
01596                                         return;
01597                                 depthSlider.setValue(z);
01598                         }
01599                 };
01600                 try {
01601                         SwingUtilities.invokeAndWait(r);
01602                 } catch (InterruptedException e) {
01603                         e.printStackTrace();
01604                 } catch (InvocationTargetException e) {
01605                         e.printStackTrace();
01606                 }
01607                 if (!isMinimized())
01608                         updateImage(); // only perform the update if the window is visible
01609         }
01610 
01616         public static ThebaGUI getInstance() {
01617                 if (instance == null) {
01618                         instance = new ThebaGUI();
01619                 }
01620                 return instance;
01621         }
01622 
01629         public static void main(String[] args) {
01630                 String antialising = "swing.aatext";
01631                 System.setProperty(antialising, "true");
01632                 ThebaGUI.getInstance();
01633         }
01634 
01640         private final class HistogramAction implements ActionListener {
01641                 public void actionPerformed(ActionEvent e) {
01642                         final Stack volume = getCurrentView().getVolume();
01643                         disableMenus();
01644                         Thread r = new Thread() {
01645                                 public void run() {
01646                                         long total = 0;
01647                                         int cnt = 0;
01648                                         for (int i = 0; i < idList.length; i++) {
01649                                                 if (!idList[i])
01650                                                         cnt++;
01651                                         }
01652                                         long[] histo = new long[MAX_FIBERS + 256];
01653 
01654                                         for (int z = 0; z < volume.getDepth(); z++) {
01655                                                 setProgress(z);
01656                                                 short[] slice = volume.getSlice(z);
01657                                                 for (int i = 0; i < slice.length; i++) {
01658                                                         histo[slice[i]]++;
01659                                                         total++;
01660                                                 }
01661                                         }
01662                                         StringBuffer output = new StringBuffer();
01663                                         int diffcnt = 0;
01664                                         for (int i = 0; i < histo.length; i++) {
01665                                                 if (histo[i] > 0)
01666                                                         output.append(i + " : " + histo[i] + "\n");
01667                                                 if (histo[i] != 0)
01668                                                         diffcnt++;
01669                                         }
01670                                         output.append("Total = " + total + "\n");
01671                                         output.append(diffcnt + " unique labels");
01672                                         showResults(output, "Histogram");
01673                                         enableMenus();
01674                                 }
01675                         };
01676                         r.start();
01677                 }
01678         }
01679 
01685         private final class MouseClickListener extends MouseAdapter {
01689                 public void mouseClicked(final MouseEvent e) {
01690                         if (!menuEnabled)
01691                                 return;
01692                         disableMenus();
01693                         iw.setEnabled(false);
01694                         Thread r = (new Thread() {
01695                                 public void run() {
01696                                         if (e.getButton() == MouseEvent.BUTTON3) {
01697                                                 selectedRegion = 0;
01698                                                 idSelector.setText("" + getStack().getVoxel(e.getX(), e.getY(), currentSlice()));
01699                                         } else if (seedButton3d.isSelected()) {
01700                                                 try {
01701                                                         ImageFunctions.floodFill3D26(getStack(), e.getX(), e.getY(), currentSlice(), Short.parseShort(idSelector.getText()));
01702                                                         updateImage();
01703                                                 } catch (NumberFormatException e) {
01704                                                         JOptionPane.showMessageDialog(mainWindow, "The selected value " + idSelector.getText()
01705                                                                         + " is not a valid region ID");
01706                                                 }
01707                                         } else if (deleteButton.isSelected()) {
01708                                                 ImageFunctions.floodFill3D26(volume, e.getX(), e.getY(), currentSlice(), (short) 0);
01709                                                 updateImage();
01710                                         } else if (measureButton.isSelected()) {
01711                                                 measure(e.getPoint());
01712                                         } else if (measureButton3d.isSelected()) {
01713                                                 measure3D(new Point3D(e.getX(), e.getY(), currentSlice()));
01714                                         } else {
01715                                                 tracker.mouseClicked(new Point3D(e.getX(), e.getY(), currentSlice()));
01716                                         }
01717                                         iw.setEnabled(true);
01718                                         enableMenus();
01719                                 }
01720                         });
01721                         r.start();
01722                 }
01723         }
01724 
01730         private final class RegCountAction implements ActionListener {
01731                 public void actionPerformed(ActionEvent e) {
01732                         final Stack volume = getCurrentView().getVolume();
01733                         disableMenus();
01734                         Thread r = new Thread() {
01735                                 public void run() {
01736                                         long nonblackCount = 0;
01737                                         long whiteCount = 0;
01738 
01739                                         long total = 0;
01740 
01741                                         for (int z = 0; z < volume.getDepth(); z++) {
01742                                                 setProgress(z);
01743 
01744                                                 short[] slice = volume.getSlice(z);
01745                                                 for (int i = 0; i < slice.length; i++) {
01746 
01747                                                         if (slice[i] == 255)
01748                                                                 whiteCount++;
01749 
01750                                                         if (slice[i] != 0)
01751                                                                 nonblackCount++;
01752 
01753                                                         total++;
01754                                                 }
01755                                         }
01756                                         StringBuffer output = new StringBuffer();
01757 
01758                                         output.append("White pixelcount = " + whiteCount + " voxels \n");
01759                                         output.append("Percentage of total = "  + (100 * whiteCount / (float) total) + " %\n");
01760                                         output.append("Non-black pixelcount = " + nonblackCount + " voxels \n");
01761                                         output.append("Percentage of total = " + (100 * nonblackCount / (float) total) + " %\n");
01762 
01763                                         output.append("White to non-black percentage ratio = " + (100 * whiteCount / (float) nonblackCount)     + " %");
01764                                         output.append("Percentage of labelled material = "      + (100 * (nonblackCount - whiteCount) / (double) nonblackCount) + " %");
01765 
01766                                         showResults(output, "Voxelcount");
01767 
01768                                         enableMenus();
01769                                 }
01770                         };
01771                         r.start();
01772                 }
01773         }
01774 
01784         private final class RegionAnalysisAction implements ActionListener {
01785                 public void actionPerformed(ActionEvent e) {
01786                         final Stack volume = getCurrentView().getVolume();
01787                         disableMenus();
01788                         Thread r = new Thread() {
01789                                 public void run() {
01790                                         StringBuffer buf = new StringBuffer("Counting regions...");
01791                                         showResults(buf, "Region analysis");
01792                                         Region[] regArray = new Region[4096];
01793                                         regList = new LinkedList<Region>();
01794                                         for (int z = 0; z < volume.getDepth(); z++) {
01795                                                 setProgress(z);
01796                                                 for (int x = 0; x < width; x++) {
01797                                                         for (int y = 0; y < height; y++) {
01798                                                                 short val = volume.getVoxelUnchecked(x, y, z);
01799                                                                 if (val != 255 && val != 0 && val != 7) {
01800                                                                         Region reg = regArray[val];
01801                                                                         if (reg == null) {
01802                                                                                 BoxBounds bounds = new BoxBounds();
01803                                                                                 reg = new Region(val, bounds);
01804                                                                                 regArray[val] = reg;
01805                                                                                 regList.add(reg);
01806                                                                         }
01807                                                                         reg.getBounds().update(x, y, z);
01808                                                                         reg.size++;
01809                                                                 }
01810                                                         }
01811                                                 }
01812                                         }
01813                                         progressbar.setMaximum(regList.size());
01814                                         buf = new StringBuffer("Found "+regList.size() + " regions"); 
01815                                         showResults(buf, "Region analysis");
01816                                         
01817                                         for (int i = 0; i < regList.size(); i++) {
01818                                                 Region reg = (Region) regList.get(i);
01819                                                 setProgress(i);
01820                                                 if (reg == null)
01821                                                         continue;
01822                                                 regionCount++;
01823                                                 
01824                                                 buf = new StringBuffer();
01825                                                 buf.append("\nRegion : " + reg.getId() + " \n");
01826                                                 buf.append("Bounded size : " + reg.getBounds() + " \n");
01827                                                 ArrayList<RegionDescriptor> descriptors = getPluginLoader().getRegionDescriptors();
01828                                                 for (final RegionDescriptor r : descriptors) {
01829                                                         if (r.does3D()) {
01830                                                                 RegionMask mask = new RegionMask(reg.getId(), volume, reg.getBounds());
01831                                                                 buf.append(r.getName() + " -> " + r.measure(mask) + "\n");
01832                                                                 showResults(buf, "Region analysis");
01833                                                         }
01834                                                 }
01835                                         }
01836                                         buf.append("\nRegioncount :" + regList.size() + " \n");
01837                                         progressbar.setMaximum(depth);
01838                                         enableMenus();
01839                                 }
01840                         };
01841                         r.start();
01842                 }
01843         }
01844 
01853         public boolean isStopped() {
01854                 return isStopped;
01855         }
01856 
01862         public void setIsStopped(boolean isStopped) {
01863                 this.isStopped = isStopped;
01864         }
01865 
01874         public void setProgressbar(int i, int max) {
01875                 progressbar.setMaximum(max);
01876                 progressbar.setValue(i);
01877         }
01878 
01879         private boolean[] idList;
01880 
01881         private int totalCount; // the fiber region count upon loading
01882 
01891         public void releaseFiberId(short val) {
01892                 idList[val] = true;
01893         }
01894 
01900         private void removeFiberId(short val) {
01901                 if (val - ID_OFFSET > idList.length) {
01902                         System.err.print("Attempted to remove id > MAX_REG_COUNT " + val);
01903                         return;
01904                 }
01905                 if (idList[val - ID_OFFSET] == true) {
01906                         idList[val - ID_OFFSET] = false;
01907                         totalCount++;
01908                 }
01909         }
01910 
01914         private void initIdList() {
01915                 idList = new boolean[MAX_FIBERS];
01916                 for (int i = 0; i < MAX_FIBERS; i++) {
01917                         idList[i] = true;
01918                 }
01919         }
01920 
01927         private LinkedList<Region> getRegions() {
01928                 LinkedList<Region> regList = new LinkedList<Region>();
01929                 Region[] regArray = new Region[4096];
01930                 for (int z = 0; z < volume.getDepth(); z++) {
01931                         setProgress(z);
01932                         for (int x = 0; x < width; x++) {
01933                                 for (int y = 0; y < height; y++) {
01934                                         short val = volume.getVoxelUnchecked(x, y, z);
01935                                         if (val != 255 && val != 0 && val != 7) {
01936                                                 Region reg = regArray[val];
01937                                                 if (reg == null) {
01938                                                         BoxBounds bounds = new BoxBounds();
01939                                                         reg = new Region(val, bounds);
01940                                                         regArray[val] = reg;
01941                                                         regList.add(reg);
01942                                                 }
01943                                                 reg.getBounds().update(x, y, z);
01944                                                 reg.size++;
01945                                         }
01946                                 }
01947                         }
01948                 }
01949                 return regList;
01950         }
01951 
01958         public short getNewFiberId() {
01959                 for (short i = 0; i < idList.length; i++) {
01960                         if (idList[i]) {
01961                                 idList[i] = false;
01962                                 return (short) (i + ID_OFFSET);
01963                         }
01964                 }
01965                 System.err.print("OUT OF ID's!");
01966                 return -1;
01967         }
01968 
01975         public void setLabel(String string) {
01976                 statusLabel.setText(string);
01977         }
01978 
01979         public void setLoader(PluginLoader loader) {
01980                 this.loader = loader;
01981         }
01982 
01983         public PluginLoader getPluginLoader() {
01984                 return loader;
01985         }
01986 }

Generated on Fri Nov 13 08:57:07 2009 for Theba by  doxygen 1.6.1