MIASDBViewer.java

package ac.essex.ooechs.imaging.commons.apps; 
 
import ac.essex.ooechs.imaging.commons.util.panels.ImagePanel; 
import ac.essex.ooechs.imaging.commons.PixelLoader; 
 
import javax.swing.*; 
import java.io.BufferedReader; 
import java.io.FileReader; 
import java.io.IOException; 
import java.io.File; 
import java.awt.event.ActionListener; 
import java.awt.event.ActionEvent; 
import java.awt.*; 
import java.awt.image.BufferedImage; 
import java.util.Vector; 
import java.util.StringTokenizer; 
 
/** 
 * <p/> 
 * This program is free software; you can redistribute it and/or 
 * modify it under the terms of the GNU General Public License 
 * as published by the Free Software Foundation; either version 2 
 * of the License, or (at your option) any later version, 
 * provided that any use properly credits the author. 
 * This program is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 * GNU General Public License for more details at http://www.gnu.org 
 * </p> 
 * 
 * @author Olly Oechsle, University of Essex, Date: 29-Jan-2007 
 * @version 1.0 
 */ 
public class MIASDBViewer extends JFrame { 
 
    public static final String APP_NAME =  "MIAS Viewer"; 
 
    final File directory = new File("/home/ooechs/Desktop/mias/"); 
 
    private ImagePanel imagePanel; 
    private JLabel abnormality; 
    private JLabel backgroundTissueType; 
    private JLabel severity; 
 
    Vector<MIASImage> images; 
    int cursor = 0; 
 
    public static void main(String[] args) { 
        new MIASDBViewer(); 
    } 
 
    public MIASDBViewer() { 
 
        super(APP_NAME); 
 
        JMenu file = new JMenu("File"); 
 
        JMenuItem open = new JMenuItem("Open"); 
 
        open.addActionListener(new ActionListener() { 
            public void actionPerformed(ActionEvent e) { 
                read(new File(directory, "Info.txt")); 
            } 
        }); 
 
        JMenuItem exit = new JMenuItem("Exit"); 
 
        exit.addActionListener(new ActionListener() { 
            public void actionPerformed(ActionEvent e) { 
                System.exit(0); 
            } 
        }); 
 
        file.add(open); 
        file.add(exit); 
 
        JMenuBar bar = new JMenuBar(); 
        bar.add(file); 
        setJMenuBar(bar); 
 
        JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT)); 
 
        JButton btnNext = new JButton("Next"); 
        JButton btnPrev = new JButton("Prev"); 
 
        btnNext.addActionListener(new ActionListener() { 
            public void actionPerformed(ActionEvent e) { 
                next(); 
            } 
        }); 
 
        btnPrev.addActionListener(new ActionListener() { 
            public void actionPerformed(ActionEvent e) { 
                prev(); 
            } 
        }); 
 
        panel.add(btnPrev); 
        panel.add(btnNext); 
 
 
        JPanel status = new JPanel(new GridLayout(1, 3)); 
        abnormality = new JLabel(""); 
        severity = new JLabel(""); 
        backgroundTissueType = new JLabel(""); 
 
        status.add(backgroundTissueType); 
        status.add(abnormality); 
        status.add(severity); 
 
        Container c = getContentPane(); 
        imagePanel = new ImagePanel(); 
        c.add(panel, BorderLayout.NORTH); 
        c.add(imagePanel, BorderLayout.CENTER); 
        c.add(status, BorderLayout.SOUTH); 
 
        setSize(1024, 1024); 
        setVisible(true); 
 
    } 
 
    public void next() { 
    if (images == null) { 
        alert("Load images first"); 
        return; 
    } 
        if (cursor < images.size()) { 
            MIASImage image = images.elementAt(cursor); 
            cursor++; 
            displayImage(image); 
        } else { 
            alert("No more images"); 
        } 
    } 
 
    public void prev() { 
    if (images == null) { 
        alert("Load images first"); 
        return; 
    } 
        if (cursor > 0) { 
            MIASImage image = images.elementAt(cursor - 1); 
            cursor--; 
            displayImage(image); 
        } else { 
            alert("Can't go back"); 
        } 
    } 
 
    public void displayImage(MIASImage image) { 
        try { 
            PixelLoader loader = new PixelLoader(new File(directory, image.getFilename() + ".pgm.bmp")); 
            BufferedImage img = loader.getBufferedImage(); 
            if (image.getX() != -1) { 
                Graphics g = img.getGraphics(); 
                if (image.getSeverity() == MIASImage.BENIGN) { 
                    g.setColor(Color.WHITE); 
                } else { 
                    g.setColor(Color.RED); 
                } 
 
                int halfRadius = image.getRadius() / 2; 
                int x = image.getX() - halfRadius; 
                int y = img.getHeight() - image.getY() - halfRadius; 
                g.drawOval(x, y, image.getRadius(), image.getRadius()); 
 
            } 
            imagePanel.setImage(img); 
            abnormality.setText("Abnormality: " + image.abnormalityToString()); 
            severity.setText("Severity: " + image.severityToString()); 
            backgroundTissueType.setText("Background: " + image.backgroundTypeToString()); 
            setTitle(APP_NAME + " - " + image.getFilename()); 
        } catch (Exception e) { 
            alert("Can't load next image: " + e); 
        } 
    } 
 
    public void read(File f) { 
 
        cursor = 0; 
        images = new Vector<MIASImage>(100); 
 
        try { 
            BufferedReader in = new BufferedReader(new FileReader(f)); 
 
            if (!in.ready()) throw new IOException(); 
 
            String line; 
 
            while ((line = in.readLine()) != null) { 
 
                if (line.startsWith("mdb")) { 
 
                    int x = -1; 
                    int y = -1; 
                    int radius = 0; 
 
                    StringTokenizer tokenizer = new StringTokenizer(line); 
                    String filename = tokenizer.nextToken(); 
                    String backgroundTissue = tokenizer.nextToken(); 
                    String abnormality = tokenizer.nextToken(); 
 
                    String severity = ""; 
 
                    if (tokenizer.hasMoreTokens()) { 
                        severity = tokenizer.nextToken(); 
 
                        try { 
                            if (tokenizer.hasMoreTokens()) { 
                                x = Integer.parseInt(tokenizer.nextToken()); 
                                y = Integer.parseInt(tokenizer.nextToken()); 
                                radius = Integer.parseInt(tokenizer.nextToken()); 
                            } 
                        } catch (NumberFormatException nfe) { 
                            // do nothing. 
                        } 
 
                    } 
                    images.add(new MIASImage(filename, backgroundTissue, abnormality, severity, x, y, radius)); 
                } 
 
 
 
            } 
 
            System.out.println("Loaded: " + images.size() + " images."); 
            next(); 
 
        } catch (IOException e) { 
 
            alert("Error Reading file: " + e); 
 
        } 
    } 
 
    public void alert(String message) { 
        JOptionPane.showMessageDialog(this, message); 
    } 
 
    class MIASImage { 
 
/* 
1st column: MIAS database reference number. 
 
2nd column: Character of background tissue: 
                F - Fatty 
                G - Fatty-glandular 
                D - Dense-glandular 
 
3rd column: Class of abnormality present: 
                CALC - Calcification 
                CIRC - Well-defined/circumscribed masses 
                SPIC - Spiculated masses 
                MISC - Other, ill-defined masses 
                ARCH - Architectural distortion 
                ASYM - Asymmetry 
                NORMAL - Normal 
 
4th column: Severity of abnormality; 
                B - Benign 
                M - Malignant 
                */ 
 
        public static final int FATTY = 0; 
        public static final int FATTY_GLANDULAR = 1; 
        public static final int DENSE_GLANDULAR = 2; 
 
        public static final int CALCIFICATION = 0; 
        public static final int WELL_DEFINED_OR_CIRCUMSCRIBED_MASSES = 1; 
        public static final int SPICULATED_MASSES = 2; 
        public static final int OTHER_ILL_DEFINED_MASSES = 3; 
        public static final int ARCHITECTURAL_DISTORTION = 4; 
        public static final int ASYMMETRY = 5; 
        public static final int NORMAL = 6; 
 
        public static final int NOT_APPLICABLE = 0; 
        public static final int BENIGN = 1; 
        public static final int MALIGNANT = 2; 
 
        protected String filename; 
        protected int backgroundTissueType; 
        protected int abnormality; 
        protected int severity; 
 
        protected int x, y, radius; 
 
        public MIASImage(String filename, String backgroundTissueType, String abnormality, String severity, int x, int y, int radius) { 
            this.filename = filename; 
            if (backgroundTissueType.equals("F")) this.backgroundTissueType = FATTY; 
            if (backgroundTissueType.equals("G")) this.backgroundTissueType = FATTY_GLANDULAR; 
            if (backgroundTissueType.equals("D")) this.backgroundTissueType = DENSE_GLANDULAR; 
 
            /* 
                       CALC - Calcification 
            CIRC - Well-defined/circumscribed masses 
            SPIC - Spiculated masses 
            MISC - Other, ill-defined masses 
            ARCH - Architectural distortion 
            ASYM - Asymmetry 
            NORMAL - Normal 
            */ 
 
            if (abnormality.equals("CALC")) this.abnormality = CALCIFICATION; 
            if (abnormality.equals("CIRC")) this.abnormality = WELL_DEFINED_OR_CIRCUMSCRIBED_MASSES; 
            if (abnormality.equals("MISC")) this.abnormality = OTHER_ILL_DEFINED_MASSES; 
            if (abnormality.equals("ARCH")) this.abnormality = ARCHITECTURAL_DISTORTION; 
            if (abnormality.equals("ASYN")) this.abnormality = ASYMMETRY; 
            if (abnormality.equals("NORM")) this.abnormality = NORMAL; 
 
            this.severity = NOT_APPLICABLE; 
            if (severity.equals("B")) this.severity = BENIGN; 
            if (severity.equals("M")) this.severity = MALIGNANT; 
 
            this.x = x; 
            this.y = y; 
            this.radius = radius; 
        } 
 
        public String getFilename() { 
            return filename; 
        } 
 
        public int getBackgroundTissueType() { 
            return backgroundTissueType; 
        } 
 
        public int getAbnormality() { 
            return abnormality; 
        } 
 
        public int getSeverity() { 
            return severity; 
        } 
 
        public int getX() { 
            return x; 
        } 
 
        public int getY() { 
            return y; 
        } 
 
        public int getRadius() { 
            return radius; 
        } 
 
        public String backgroundTypeToString() { 
            String[] types = new String[]{"Fatty", "Fatty Glandular", "Dense Glandular"}; 
            return types[backgroundTissueType]; 
        } 
 
        public String abnormalityToString() { 
            String[] abnormalities = new String[]{"Calcification", "Well defined / Circumscribed masses", "Spiculated Masses", "Other ill defined masses", "Architectural distortion", "Asymmetry", "Normal"}; 
            return abnormalities[abnormality]; 
        } 
 
        public String severityToString() { 
            String[] severities = new String[]{"Not Applicable", "Benign", "Malignant"}; 
            return severities[severity]; 
        } 
 
    } 
}