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.*;
import java.util.StringTokenizer;
import javax.swing.*;

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;

    // Age (years)
    static private final int ivarX = 1;

    // Height (cm)
    static private final int ivarY = 2;

    // Initial Body Surface Area (m^2)
    static private final int ivarZ = 11;

    // Survival?
    static private final int ivarMarkerType = 4;

    // Initial Mean Circulation Time (sec)
    static private final int ivarMarkerSize = 14;

    // Initial Cardiac Index (liters/min-m^2)
    static private final int ivarMarkerColor = 12;

    // Initial Hemoglobin (gm/100 ml)
    static private final int ivarMarkerPulseMin = 18;

    // Final Hemoglobin (gm/100 ml)
    static private final int ivarMarkerPulseMax = 32;

    // Sex (Gender)
    static private final int ivarRotationAxis = 3;

    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(AxisXYZ.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.