Example: Heart Data

A multivariate data set is charted. This example shows how multiple variables can be encoded into a single chart. The data set is from: Afifi, A.A. and S.P. Azen (1979), Statistical Analysis: A Computer Oriented Approach , Second Edition, Academic Press, New York.

Each observation in the data set is represented by a marker. The encoding of the variables into the chart is described in the following table:

Representation Variable
x -coordinate Age (years)
y -coordinate Height (cm)
z -coordinate Initial Body Surface Area (m^2)
Marker Type Survival?
Marker Size Initial Mean Circulation Time (sec)
Color Initial Cardiac Index (liters/min-m^2)
Min Pulse Size Initial Hemoglobin (gm/100 ml)
Max Pulse Size Final Hemoglobin (gm/100 ml)
Rotation Direction Sex (Gender)
import com.imsl.chart.Colormap;
import com.imsl.chart3d.*;
import com.imsl.io.*;
import com.imsl.stat.Summary;
import java.awt.Color;
import java.io.*;
import java.sql.ResultSetMetaData;
import java.sql.*;
import java.util.StringTokenizer;
import javax.swing.JPanel;
import javax.swing.JLabel;

public class DataEx3 extends javax.swing.JFrame {
    static private final int nVariables = 34;
    static private final int nObs = 113;
    
    static private final Colormap colormap = Colormap.BLUE_GREEN_RED_YELLOW;
    
    static private final int ivarX = 1;                 // Age (years)
    static private final int ivarY = 2;                 // Height (cm)
    static private final int ivarZ = 11;                // Initial Body Surface Area (m^2)
    static private final int ivarMarkerType = 4;        // Survival?
    static private final int ivarMarkerSize = 14;       // Initial Mean Circulation Time (sec)
    static private final int ivarMarkerColor = 12;      // Initial Cardiac Index (liters/min-m^2)
    static private final int ivarMarkerPulseMin = 18;   // Initial Hemoglobin (gm/100 ml)
    static private final int ivarMarkerPulseMax = 32;   // Final Hemoglobin (gm/100 ml)
    static private final int ivarRotationAxis = 3;      // Sex (Gender)
    
    private ResultSetMetaData   meta;
    private JPanel              jPanelLegend;
    

    public DataEx3() throws IOException, SQLException {
        InputStream is = DataEx3.class.getResourceAsStream("AfifiAzen.csv");
        AfifiAzenReader reader = new AfifiAzenReader(is);
        double data[][] = reader.readData();
        is.close();
        
        Chart3D chart = new Chart3D();
        AxisXYZ axis = new AxisXYZ(chart);
        axis.setAxisTitlePosition(axis.AXIS_TITLE_PARALLEL);
        
        meta = reader.getMetaData();
        axis.getAxisX().getAxisTitle().setTitle(meta.getColumnName(ivarX+1));
        axis.getAxisY().getAxisTitle().setTitle(meta.getColumnName(ivarY+1));
        axis.getAxisZ().getAxisTitle().setTitle(meta.getColumnName(ivarZ+1));
        
        int markerTypes[] = {Data.MARKER_TYPE_CUBE, Data.MARKER_TYPE_TETRAHEDRON};
        
        double minMarkerSize = 0.0;
        double maxMarkerSize = 0.0;
        if (ivarMarkerSize >= 0) {
            Summary summary = getSummary(data, ivarMarkerSize);
            minMarkerSize = summary.getMinimum();
            maxMarkerSize = summary.getMaximum();
        }
        
        double minColor = 0.0;
        double maxColor = 0.0;
        if (ivarMarkerColor >= 0) {
            Summary summary = getSummary(data, ivarMarkerColor);
            minColor = summary.getMinimum();
            maxColor = summary.getMaximum();
        }
        
        double maxPulse = 0.0;
        if (ivarMarkerColor >= 0) {
            maxPulse = getSummary(data, ivarMarkerPulseMax).getMaximum();
        }
        
        axis.setDataType(Data.DATA_TYPE_MARKER);
        for (int i = 0;  i < data.length;  i++) {
            double xp[] = {data[i][ivarX]};
            double yp[] = {data[i][ivarY]};
            double zp[] = {data[i][ivarZ]};
            Data data3D = new Data(axis, xp, yp, zp);
            double size = (data[i][ivarMarkerSize]-minMarkerSize) / (maxMarkerSize-minMarkerSize);
            data3D.setMarkerSize(1.0 + size);
            double t = (data[i][ivarMarkerColor]-minColor) / (maxColor-minColor);
            data3D.setMarkerColor(colormap.color(t));
            
            data3D.setMarkerPulsingMinimumScale(data[i][ivarMarkerPulseMin]/maxPulse);
            data3D.setMarkerPulsingMaximumScale(data[i][ivarMarkerPulseMax]/maxPulse);
            data3D.setMarkerPulsingCycle(1.0);
            
            double zaxis = (data[i][ivarRotationAxis] == 1 ? 1.0 : -1.0);
            data3D.setMarkerRotatingAxis(0.0, 0.0, zaxis);
            data3D.setMarkerRotatingCycle(8.0);
            
            data3D.setMarkerType(data[i][ivarMarkerType] == 1.0 ? markerTypes[0] : markerTypes[1]);
        }
        
        Canvas3DChart canvas = new Canvas3DChart(chart);
        canvas.setSize(375, 375);
        getContentPane().add(canvas, java.awt.BorderLayout.CENTER);
        
        
        jPanelLegend = new JPanel(new java.awt.GridBagLayout());
        setupLegend();
        getContentPane().add(jPanelLegend, java.awt.BorderLayout.WEST);
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        pack();
        
        ColormapLegend colormapLegend = new ColormapLegend(chart, colormap, minColor, maxColor);
        colormapLegend.setPosition(10, 10);
        colormapLegend.setTitle(meta.getColumnName(ivarMarkerColor+1));
        
        canvas.render();
    }
    
    
    private class AfifiAzenReader extends FlatFile {     
        AfifiAzenReader(InputStream is) throws IOException {
            super(new BufferedReader(new InputStreamReader(is)));
            String line = readLine();
            line = readLine();
            line = readLine();
            StringTokenizer st = new StringTokenizer(line, ",");
            for (int j = 0;  st.hasMoreTokens();  j++) {
                setColumnName(j+1, st.nextToken().trim());
                setColumnClass(j, Double.class);
            }
        }
        
        double[][] readData() throws IOException, java.sql.SQLException {
            double data[][] = new double[nObs][nVariables];
            for (int i = 0;  i < nObs;  i++) {
                if (!next()) throw new IOException("Error in file");
                for (int j = 0;  j < nVariables;  j++) {
                    data[i][j] = getDouble(j+1);
                }
            }
            return data;
        }
    }
    

    static Summary getSummary(double data[][], int ivar) {
        Summary summary = new Summary();
        for (int i = 0;  i < nObs;  i++) {
            summary.update(data[i][ivar]);
        }
        return summary;
    }
    
    private void setupLegend() throws SQLException {
        addLegendTitle("Marker Color:");
        addLegendValue(ivarMarkerColor, 1.0);
        
        addLegendTitle("Marker Size:");
        addLegendValue(ivarMarkerSize, 1.0);
 
        addLegendTitle("Marker Pulse (min/max):");
        addLegendValue(ivarMarkerPulseMin, 0.0);
        addLegendValue(ivarMarkerPulseMax, 1.0);

        addLegendTitle("Rotation Axis:");
        addLegendValue(ivarRotationAxis, 1.0);

        addLegendTitle("Marker Type:");
        addLegendValue(ivarMarkerType, 1.0);
    }
    
    private void addLegendTitle(String title) {
        JLabel jLabel = new JLabel(title);
        java.awt.GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        jPanelLegend.add(jLabel, gridBagConstraints);
    }
    
    private void addLegendValue(int ivar, double weight) throws SQLException {
        JLabel jLabel = new JLabel(meta.getColumnName(ivar+1));
        java.awt.GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weighty = weight;
        jPanelLegend.add(jLabel, gridBagConstraints);
        jLabel.setForeground(Color.BLUE);
    }

    public static void main(String args[]) throws IOException, java.sql.SQLException {
        new DataEx3().setVisible(true);
    }
}

Output

Link to Java source.