import java.awt.Choice; import java.awt.Color; import java.awt.Container; import java.awt.Font; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.util.Vector; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.KeyStroke; import org.shodor.data.BarLocationData; import org.shodor.gui11.Colors; import org.shodor.gui11.FlexGridLayout; import org.shodor.gui11.GraphWindowFrame; import org.shodor.gui11.GraphListener; import org.shodor.gui11.HStackLayout; import org.shodor.gui11.NumInput; import org.shodor.gui11.ShodorGraphPaper; import org.shodor.gui11.SliderBar; import org.shodor.gui11.SliderListener; import org.shodor.gui11.StackLayout; import org.shodor.gui11.TextCanvas; import org.shodor.math11.Point2D; import org.shodor.math11.SingleStat; import org.shodor.util11.StrLib; /** * Application reads a data file containing participant IDs, condition IDs, and * property data and shows time series mean plot for each experimental * condition. User may select a time and a histogram or dot plot distribution is * shown at that time instance for each of the displayed experimental * conditions. */ public class TimeSeries extends JFrame implements ActionListener, ItemListener, SliderListener, GraphListener { public static final boolean DEBUG = false; /** * How thick to draw the outlines of the bars on the histogram. */ private static final int OUTLINE_THICKNESS = 3; /** * Vertical position of histogram axis */ private static final int HISTOGRAM_AXIS_Y = 2; private double binSize; private final int SIGFIG = 3; private int maxTimeSteps = 0; // Used for storage to save re-calculating /** When plotting just means, these should represent the graph paper limits. */ private double graphYMax = 0.0; private double graphYMin = 0.0; // Slider bar variables private SliderBar sbX; private SliderBar sbY; private static final int XSLIDER = 0; private static final int YSLIDER = 1; private static final Color slideColor = Colors.orange; // AWT components File myfile; // Data file to be read Choice cProperties; // Drop down to select which property to display JCheckBox[] cbShowConditions; // User selectable array of checkboxes to // show experimental conditions // Swing components JScrollPane scrollPane; JFileChooser fc; Container contentPane; JPanel meanPanel; JMenu fileMenu, editMenu; JButton bSetWindow; // JRadioButton radioButtonMean; // JRadioButton radioButtonHistogram; TextCanvas lN, lMean; TextCanvas lMinFreq, lMaxFreq, lbinsize; NumInput tfMaxFreq, tfMinFreq, tfBinSize; JMenuItem openMenuItem, closeMenuItem, saveMenuItem, saveAsMenuItem, quitMenuItem; JButton bSetHistogramLimits; Choice cDataSet; // Shodor library components ShodorGraphPaper graph; ShodorGraphPaper histogramGraph; ShodorGraphPaper boxPlotGraph; GraphWindowFrame setFrame; // Application components public static final Color[] COLORS = { Colors.red, Colors.blue, Colors.forrestGreen, Colors.purple, Colors.crimson }; private static final int MEAN_GRAPH_WIDTH = 400; private static final int MEAN_GRAPH_HEIGHT = 400; private static final int RESIDUAL_GRAPH_WIDTH = MEAN_GRAPH_WIDTH / 2; private static final int RESIDUAL_GRAPH_HEIGHT = MEAN_GRAPH_HEIGHT / 2; private static final Color BOXPLOT_MEDIAN_LINE_COLOR = Colors.orange; int[] offsetArray = new int[3]; Vector experimentalConditions; // Where to store the data. public static final double DEFAULT_GLOBAL_MIN = -10.0; public static final double DEFAULT_GLOBAL_MAX = 10.0; private static final int SIGS = 3; // Decimal places private double globalMin = DEFAULT_GLOBAL_MIN; private double globalMax = DEFAULT_GLOBAL_MAX; private NumInput niMinFreq; private NumInput niMaxFreq; private NumInput niBinSize; private boolean histogramWindowFrozen = false; public TimeSeries() { super("Time Series"); setBackground(Color.white); getContentPane().setBackground(Color.white); setSize(1000, 800); JPopupMenu.setDefaultLightWeightPopupEnabled(false); // maybe have two plots, both with the real graph in the background, one // with histogram & // one with bar graph on top histogramGraph = new ShodorGraphPaper(-10, -10, 10, 10); histogramGraph.setSize(RESIDUAL_GRAPH_WIDTH, RESIDUAL_GRAPH_HEIGHT); boxPlotGraph = new ShodorGraphPaper(-10, -10, 10, 10); boxPlotGraph.setSize(RESIDUAL_GRAPH_WIDTH, RESIDUAL_GRAPH_HEIGHT); experimentalConditions = new Vector(); JFrame.setDefaultLookAndFeelDecorated(true); System.setProperty("apple.laf.useScreenMenuBar", "true"); fc = new JFileChooser(); ExampleFileFilter filter = new ExampleFileFilter(); filter.addExtension(FileIO.FILE_EXTENSION); filter.setDescription("Experiment Files"); fc.setFileFilter(filter); getContentPane().setLayout(new HStackLayout(HStackLayout.NORTH)); contentPane = getContentPane(); contentPane.setLayout(new StackLayout(StackLayout.NORTHWEST)); meanPanel = new JPanel(new StackLayout(StackLayout.NORTHWEST)); meanPanel.setBackground(Color.white); cProperties = new Choice(); cProperties .addItem("Please open a data file. Select Open from the File menu below."); cProperties.addItemListener(this); meanPanel.add(StackLayout.LEFT, createMenuBar()); meanPanel.add(StackLayout.NORTH, cProperties); graph = new ShodorGraphPaper(-10, -10, 10, 10); graph.setSize(MEAN_GRAPH_WIDTH, MEAN_GRAPH_HEIGHT); meanPanel.add(StackLayout.CENTER, graph); contentPane.add(StackLayout.NORTH, meanPanel); } // This creates a Menu Bar public JMenuBar createMenuBar() { JMenuBar menuBar; // Create the menu bar. menuBar = new JMenuBar(); menuBar.setOpaque(true); // Build the first menu and add it to the menubar fileMenu = new JMenu("File"); menuBar.add(fileMenu); // Creates and adds JMenuItems to the menu bar openMenuItem = new JMenuItem("Open"); openMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.ALT_MASK)); openMenuItem.addActionListener(this); fileMenu.add(openMenuItem); closeMenuItem = new JMenuItem("Close"); closeMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, ActionEvent.ALT_MASK)); closeMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { experimentalConditions.removeAllElements(); graph.removeAll(); graph.repaint(); } }); fileMenu.add(closeMenuItem); fileMenu.addSeparator(); quitMenuItem = new JMenuItem("Quit"); quitMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.ALT_MASK)); quitMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { System.exit(0); } }); fileMenu.add(quitMenuItem); menuBar.setBorder(new javax.swing.border.BevelBorder( javax.swing.border.BevelBorder.RAISED)); return menuBar; } public void itemStateChanged(ItemEvent evt) { boolean showConditionChecked = false; for (int i = 0; i < cbShowConditions.length; i++) { if (evt.getSource() == cbShowConditions[i]) { showConditionChecked = true; } } if (evt.getSource() == cProperties || showConditionChecked) { if (cProperties.getSelectedIndex() == 0) return; // The user selected the Select a property option. graph.removeAll(); try { double[] verticalScale = computeMeanGraphVerticalScale(); graphYMax = verticalScale[1]; graphYMin = verticalScale[0]; } catch (NullPointerException npe) { // Likely all experimental // condition checkboxes were // unchecked. graphYMax = DEFAULT_GLOBAL_MAX; graphYMax = DEFAULT_GLOBAL_MIN; } try { for (int i = 0; i < experimentalConditions.size(); i++) { ExperimentalCondition ec = ((ExperimentalCondition) experimentalConditions .elementAt(i)); if (cbShowConditions[i].isSelected() && (int) Math.round(sbX.getValue()) < ec .getNumberOfTimeSteps()) { double[] dataX = new double[ec.getNumberOfTimeSteps()]; double[] dataY = new double[ec.getNumberOfTimeSteps()]; // this is the for loop that's taking forever when // conditions unchecked for (int j = 0; j < dataX.length; j++) { dataX[j] = (double) j; dataY[j] = ec.getMean(j, cProperties .getSelectedIndex() - 1); } graph.addDataSet(dataX, dataY, COLORS[i % COLORS.length], -1, false, true, 1); } } } catch (TrialException te) { oops(te.getMessage()); return; } if (graphYMax > graphYMin) { graph.setWindow(0, graphYMin, getMaxTimeSteps() + 1, graphYMax, (double) (getMaxTimeSteps() + 1) / 10.0, ((double) graphYMin - (double) graphYMax) / 10.0); /* * histogramGraph.setWindow(0, graphYMin, getMaxTimeSteps() + 1, * graphYMax, (double) (getMaxTimeSteps() + 1) / 10.0, ((double) * graphYMin - (double) graphYMax) / 10.0); * boxPlotGraph.setWindow(0, graphYMin, getMaxTimeSteps() + 1, * graphYMax, (double) (getMaxTimeSteps() + 1) / 10.0, ((double) * graphYMin - (double) graphYMax) / 10.0); */ sbX.setRange(0, getMaxTimeSteps() + 1); sbX.setValue((getMaxTimeSteps() + 1) / 2); sbY.setRange(((graphYMax - graphYMin) * .01), (graphYMax - graphYMin) * .75); sbY.setValue((graphYMax - graphYMin) * .50); graph.setAxisSpacing((double) (maxTimeSteps + 1) / 10.0, (graphYMax - graphYMin) / 10.0); histogramGraph.setAxisSpacing( (double) (maxTimeSteps + 1) / 10.0, (graphYMax - graphYMin) / 10.0); boxPlotGraph.setAxisSpacing((double) (maxTimeSteps + 1) / 10.0, (graphYMax - graphYMin) / 10.0); niMinFreq.setText("0"); // min freq niMaxFreq.setText(StrLib.round3(getMaxFreq(), 2)); // max freq niBinSize.setText(StrLib.round3(sbY.getValue(), 3));// bin size setGlobalMinMaxProperties(); drawHistogram(); drawBoxPlot(); } } } /** * Called from GraphWindowFrame. Implements GraphListener. Processes user * request to change graph limits and scale. */ public boolean setWindow(double[] newData) { if (newData.length != GraphWindowFrame.DEFAULT_VALUES.length) { System.out .println("DEVELOPMENT ERROR.. graphit.setWindow() must accept a double array of " + GraphWindowFrame.DEFAULT_VALUES.length + " elements. See graphit.setWindow() JavaDoc."); // Print stack trace to show source of error. try { Integer.parseInt("s"); } catch (NumberFormatException nfe) { nfe.printStackTrace(); } return false; } double minx = newData[0]; double miny = newData[3]; double maxx = newData[1]; double maxy = newData[4]; if ((maxx - minx) < 0.001) { maxx += 0.1; minx -= 0.1; } if ((maxy - miny) < 0.001) { maxy += 0.1; miny -= 0.1; } sbX.setRange(minx, maxx); sbX.setValue((maxx + maxy) / 2); sbY.setRange((maxy - miny) * .01, (maxy - miny)); sbY.setValue((maxy - miny) * .5); graph.setWindow(minx, miny, maxx, maxy, newData[2], newData[5]); graph.updateAll(); graph.repaint(); return true; } public void actionPerformed(ActionEvent ae) { if (ae.getSource() == openMenuItem) { int returnValue = fc.showOpenDialog(TimeSeries.this); if (returnValue == JFileChooser.APPROVE_OPTION) { myfile = fc.getSelectedFile(); experimentalConditions = FileIO .loadExperimentalConditionFile(myfile); cProperties.removeAll(); String[] propertyDescriptions = new String[0]; if (experimentalConditions.size() > 0) { propertyDescriptions = ((ExperimentalCondition) experimentalConditions .elementAt(0)).getPropertyDescriptions(); } cProperties.addItem("Select a property"); for (int i = 0; i < propertyDescriptions.length; i++) { cProperties.addItem(propertyDescriptions[i]); } meanPanel.setVisible(false); meanPanel.removeAll(); contentPane.remove(meanPanel); contentPane.setBackground(Color.white); // meanPanel = new JPanel(new HStackLayout(HStackLayout.NORTH)); meanPanel = null; JPanel mainPanel = new JPanel(new StackLayout( StackLayout.CENTER)); mainPanel.setBackground(Color.white); mainPanel.add(StackLayout.CENTER, cProperties); sbX = new SliderBar(this, slideColor, -10.0, 10.0, 1.0, 0.0, XSLIDER); sbX.setSize(400, 25); sbX.setPadding(0); sbX.preciseMouseX(true); sbX.setSliderColor(slideColor); sbY = new SliderBar(this, slideColor, 0.0, 10.0, 1.0, 1.0, YSLIDER); sbY.setSize(RESIDUAL_GRAPH_WIDTH, 20); sbY.setPadding(0); sbY.preciseMouseX(true); sbY.setSliderColor(slideColor); JPanel graphPanel = new JPanel(new StackLayout( StackLayout.NORTH)); graphPanel.setBackground(Color.white); graphPanel.add(StackLayout.CENTER, graph); graphPanel.add(StackLayout.CENTER, sbX); mainPanel.add(StackLayout.NORTH, graphPanel); JPanel pShowConditions = new JPanel(new StackLayout( StackLayout.NORTH)); pShowConditions.setBackground(Color.white); cbShowConditions = new JCheckBox[experimentalConditions.size()]; for (int i = 0; i < cbShowConditions.length; i++) { pShowConditions.add(StackLayout.LEFT, cbShowConditions[i] = new JCheckBox( "Show Experimental Condition " + (i + 1), true)); cbShowConditions[i].addItemListener(this); cbShowConditions[i].setBackground(Color.white); } JPanel pLimits = new JPanel(new FlexGridLayout(3, 2)); pLimits.setBackground(Color.white); pLimits.add(FlexGridLayout.EAST, new TextCanvas( "Min Frequency:", 100, TextCanvas.LHEIGHT, TextCanvas.RIGHT)); pLimits.add(FlexGridLayout.WEST, niMinFreq = new NumInput("10", 5)); pLimits.add(HStackLayout.EAST, new TextCanvas("Max Frequency:", 100, TextCanvas.LHEIGHT, TextCanvas.RIGHT)); pLimits.add(HStackLayout.WEST, niMaxFreq = new NumInput("10", 5)); pLimits.add(HStackLayout.NORTH, new TextCanvas("Bin Size:", 100, TextCanvas.LHEIGHT, TextCanvas.RIGHT)); pLimits.add(HStackLayout.SOUTH, niBinSize = new NumInput(StrLib.round((sbY.getValue()), SIGFIG), 5, NumInput.POSDOUBLE)); bSetWindow = new JButton("Set Mean Graph Window"); bSetWindow.addActionListener(this); bSetHistogramLimits = new JButton("Update Histogram"); bSetHistogramLimits.addActionListener(this); // radioButtonMean = new JRadioButton("Scale by Mean", false); // radioButtonHistogram = new JRadioButton("Scale by Histogram", // true); // radioButtonMean.addActionListener(this); // radioButtonHistogram.addActionListener(this); JPanel pSetWindowButtons = new JPanel(new HStackLayout( HStackLayout.CENTER)); pSetWindowButtons.add(HStackLayout.WEST, bSetWindow); pSetWindowButtons.add(HStackLayout.CENTER, new TextCanvas("", 200, TextCanvas.LHEIGHT, TextCanvas.LEFT)); pSetWindowButtons.add(HStackLayout.WEST, bSetHistogramLimits); JPanel pControl = new JPanel( new HStackLayout(StackLayout.NORTH)); pControl.setBackground(Color.white); pControl.add(HStackLayout.CENTER, pShowConditions); pControl.add(HStackLayout.CENTER, pLimits); // pControl.add(HStackLayout.CENTER, bSetWindow); // pControl.add(StackLayout.CENTER, radioButtonMean); // pControl.add(StackLayout.CENTER, radioButtonHistogram); JPanel residualPlots = new JPanel(new StackLayout( StackLayout.NORTH)); residualPlots.setBackground(Color.white); residualPlots.add(StackLayout.CENTER, new JLabel( "Time Step Distribution", JLabel.CENTER)); residualPlots.add(StackLayout.CENTER, histogramGraph); residualPlots.add(StackLayout.CENTER, new JLabel("Bin Size", JLabel.CENTER)); residualPlots.add(StackLayout.FILL, sbY); residualPlots.add(StackLayout.CENTER, new JLabel( "Time Step Box Plot", JLabel.CENTER)); residualPlots.add(StackLayout.CENTER, boxPlotGraph); JPanel pTop = new JPanel(new HStackLayout(HStackLayout.NORTH)); pTop.setBackground(Color.white); pTop.add(HStackLayout.CENTER, mainPanel); pTop.add(HStackLayout.CENTER, residualPlots); JPanel myPanel = new JPanel(new StackLayout(StackLayout.NORTH)); myPanel.setBackground(Color.white); myPanel.add(StackLayout.CENTER, pTop); myPanel.add(StackLayout.CENTER, pSetWindowButtons); myPanel.add(StackLayout.CENTER, pControl); myPanel.setOpaque(true); // content panes must be opaque contentPane = myPanel; setContentPane(myPanel); validate(); } else { System.out.println("Open command cancelled by user."); } } // If the Set Limits button is selected, the limits of the graph are set // to the text box values if (ae.getSource() == bSetWindow) { if (setFrame != null) { setFrame.setVisible(false); setFrame.dispose(); setFrame = null; } setFrame = new GraphWindowFrame(this, getFrameLabels(), graph .getWindowWithScale(), GraphWindowFrame.DEFAULT_TEXTCANVAS_WIDTH); setFrame.setDefaults(GraphWindowFrame.DEFAULT_VALUES); setFrame.setVisible(true); } // If the update button is selected, binsize, max/min frequency SHOULD // reset if (ae.getSource() == bSetHistogramLimits) { int fMin = -1; int fMax = -1; double localBinSize = -1; try { fMin = niMinFreq.getInt(); fMax = niMaxFreq.getInt(); localBinSize = niBinSize.getDouble(); } catch (NumberFormatException nfe) { oops("I cannot understand your bin size, max frequency, or min frequency. Please try again."); return; } if (fMin < 0 || fMax < 0 || localBinSize <= 0.0) { oops("Frequencies must be zero or positive. Bin sizes must be positive. Please try again."); return; } if (fMin > fMax) { oops("Your minimum frequency must be less than your maximum frequency."); } histogramWindowFrozen = true; double[] oldWindow = histogramGraph.getWindow(); histogramGraph.setWindow(oldWindow[0], fMin, oldWindow[1], fMax, (oldWindow[1] - oldWindow[0]) / 10.0, (fMax - fMin) / 10.0); if (Math.abs(localBinSize - sbY.getValue()) > 1E-2) { // User changed bin size. Need to redraw histogram without // changing window. sbY.setValue(localBinSize); drawHistogram(); } else { histogramGraph.updateAll(); histogramGraph.repaint(); } } /** * if (radioButtonHistogram.isSelected()) { double[] tempProperty = * computeVerticalScale(false); graphYMin = tempProperty[0]; graphYMax = * tempProperty[1]; * * double[] graphWindow = graph.getWindow(); * * graphWindow[0] = 0; graphWindow[1] = graph.getX(); graphWindow[2] = * tempProperty[0]; graphWindow[3] = tempProperty[1]; * * graph .setWindow( 0, tempProperty[0], getMaxTimeSteps() + 1, * tempProperty[1], (double) (getMaxTimeSteps() + 1) / 10.0, ((double) * tempProperty[0] - (double) tempProperty[1]) / 10.0); } * * if (radioButtonMean.isSelected()) { double[] tempProperty = * computeVerticalScale(true); graphYMin = tempProperty[0]; graphYMax = * tempProperty[1]; * * double[] graphWindow = graph.getWindow(); * * graphWindow[0] = 0; graphWindow[1] = graph.getX(); graphWindow[2] = * tempProperty[0]; graphWindow[3] = tempProperty[1]; * * graph .setWindow( 0, tempProperty[0], getMaxTimeSteps() + 1, * tempProperty[1], (double) (getMaxTimeSteps() + 1) / 10.0, ((double) * tempProperty[0] - (double) tempProperty[1]) / 10.0); } * * drawHistogram(); graph.updateAll(); graph.repaint(); } if * (ae.getSource() == sbY) { * * adjustFrequencies(); * * graph.updateAll(); graph.repaint(); } */ /** * if (ae.getSource() == radioButtonHistogram) { * * radioButtonMean.setSelected(false); * * double[] tempProperty = computeVerticalScale(false); graphYMin = * tempProperty[0]; graphYMax = tempProperty[1]; * * double[] graphWindow = graph.getWindow(); * * graphWindow[0] = 0; graphWindow[1] = graph.getX(); graphWindow[2] = * tempProperty[0]; graphWindow[3] = tempProperty[1]; * * graph .setWindow( 0, tempProperty[0], getMaxTimeSteps() + 1, * tempProperty[1], (double) (getMaxTimeSteps() + 1) / 10.0, ((double) * tempProperty[0] - (double) tempProperty[1]) / 10.0); * * graph.updateAll(); graph.repaint(); } * * if (ae.getSource() == radioButtonMean) { * * radioButtonHistogram.setSelected(false); double[] tempProperty = * computeVerticalScale(!COMPUTE_MEAN_SCALE); graphYMin = * tempProperty[0]; graphYMax = tempProperty[1]; * * double[] graphWindow = graph.getWindow(); * * graphWindow[0] = 0; graphWindow[1] = graph.getX(); graphWindow[2] = * tempProperty[0]; graphWindow[3] = tempProperty[1]; * * graph .setWindow( 0, tempProperty[0], getMaxTimeSteps() + 1, * tempProperty[1], (double) (getMaxTimeSteps() + 1) / 10.0, ((double) * tempProperty[0] - (double) tempProperty[1]) / 10.0); * * graph.updateAll(); graph.repaint(); } * * if (!(radioButtonHistogram.isSelected()) && * !(radioButtonMean.isSelected())) { radioButtonMean.setSelected(true); * * double[] tempProperties = computeVerticalScale(COMPUTE_MEAN_SCALE); * graphYMin = tempProperties[0]; graphYMax = tempProperties[1]; * * double[] graphWindow = graph.getWindow(); * * graphWindow[0] = 0; graphWindow[1] = graph.getX(); graphWindow[2] = * tempProperties[0]; graphWindow[3] = tempProperties[1]; * * graph.setWindow(graphWindow[0], graphWindow[2], graphWindow[1], * graphWindow[3]); * * graph.updateAll(); graph.repaint(); } */ } public void oops(String t, String s) { JOptionPane.showMessageDialog(getFrame(), s, t, JOptionPane.ERROR_MESSAGE); } /** * Find the hosting frame, for the file-chooser dialog. */ protected JFrame getFrame() { for (Container p = getParent(); p != null; p = p.getParent()) { if (p instanceof JFrame) { return (JFrame) p; } } return null; } public void oops(String s) { JOptionPane.showMessageDialog(getFrame(), s, "Error", JOptionPane.ERROR_MESSAGE); } /** * Returns the maximum number of time steps for all experimental conditions. * Used for scaling the graph. */ public int getMaxTimeSteps() { if (experimentalConditions.size() == 0) return 0; int max = 0; for (int i = 0; i < experimentalConditions.size(); i++) { max = Math.max(max, ((ExperimentalCondition) experimentalConditions .elementAt(i)).getNumberOfTimeSteps()); } return (maxTimeSteps = max); } /** * This method is used to determine the value to be placed in the Max Freq * box next to the graph. * * @return maxHits integer representing the max number of hits for the * experimental condition */ public int getMaxFreq() { int maxHits = 0; for (int i = 0; i < experimentalConditions.size(); i++) { ExperimentalCondition ec = ((ExperimentalCondition) experimentalConditions .elementAt(i)); if ((int) Math.round(sbX.getValue()) < ec.getNumberOfTimeSteps() && cbShowConditions[i].isSelected()) { TimeStep timeStep = ec.getTimeStepByTime((int) sbX.getValue()); maxHits = Math.max(maxHits, timeStep.getMaxHits((int) Math .round(sbX.getValue()), sbY.getValue(), cProperties .getSelectedIndex() - 1)); } for (int j = 0; j <= maxHits; j++) { maxHits = (int) Math.round((double) i * (double) graph.getSize().width / (double) maxHits); } } return maxHits; } public static void main(String[] args) { JFrame myframe = new TimeSeries(); myframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); myframe.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); myframe.setVisible(true); } /** * The sliders are not really "linked" and you should always be able to move * them. */ public SliderBar[] getLinkedSliders() { return null; } /** * Returns whether or not the slider bar with the passed id is changed */ public void stepChanged(int sliderID) { return; } /** * Returns whether or not the slider bar, with the passed ID and logical * distance is moved */ public void sliderMoved(int sliderID, double logicalDistance) { if (sliderID == XSLIDER || sliderID == YSLIDER) { histogramWindowFrozen = false; addLines(XSLIDER, true); drawHistogram(); drawBoxPlot(); if (sliderID == YSLIDER) { niBinSize.setText(StrLib.round3(sbY.getValue(), SIGS)); } } } /** * Adds the line coming up with the X sliderbar that displays the time step. * It removes and updates the lines as the slider bar on the x axis moves. * Also, if the user does not select a property, the method returns without * drawing a line. * * @param sliderID * integer representing the location of the slider on the x-axis * @param redraw * boolean stating true if the line should drawn */ public void addLines(int sliderID, boolean redraw) { if (cProperties.getSelectedIndex() == 0) { return; } graph.removeAllBars(); graph.removeAllGraphLabels(); histogramGraph.removeAllBars(); histogramGraph.removeAllGraphLabels(); boxPlotGraph.removeAllBars(); boxPlotGraph.removeAllGraphLabels(); int closestIndex = sbX.getID(); if (sliderID == XSLIDER) { closestIndex = (int) Math.round(sbX.getValue()); } else if (closestIndex < 0 || closestIndex >= graph.getWidth()) return; Point intersect = graph.translate_point(sbX.getValue(), graph .getHeight()); graph.addLine(intersect.x, 0, intersect.x, graph.getHeight(), slideColor); graph.updateAll(); graph.repaint(); histogramGraph.updateAll(); histogramGraph.repaint(); boxPlotGraph.updateAll(); boxPlotGraph.repaint(); } /** * This method is for the 3 plot to graph the box plot * */ public void drawBoxPlot() { if (cProperties.getSelectedIndex() == 0 || sbY.getValue() <= 0) { return; } // Are all checkboxes unchecked? boolean allUnchecked = true; for (int i = 0; i < cbShowConditions.length; i++) { if (cbShowConditions[i].isSelected()) { allUnchecked = false; } } if (allUnchecked) { return; } boxPlotGraph.removeAllBars(); boxPlotGraph.removeAllGraphLabels(); boxPlotGraph .addLine(0, 2, boxPlotGraph.getSize().width, 2, Color.black); // Point2D[] boxPlotPoints = { mean, min, max, median, quartiles[0], // quartiles[1] }; double boxplotymin = boxPlotGraph.getWindow()[2]; double boxplotymax = boxPlotGraph.getWindow()[3]; double boxplotyrange = boxplotymax - boxplotymin; double spacebetweenplots = (boxplotyrange / 8.0); double boxplotystart = boxplotymax - spacebetweenplots; // Where to // start drawing // the box // plots. double boxplotyheight = boxplotyrange / 6.0; // Height of each // boxplot double boxplotspacing = spacebetweenplots + boxplotyheight; boolean useMedian = false; for (int i = 0; i < experimentalConditions.size(); i++) { ExperimentalCondition ec = ((ExperimentalCondition) experimentalConditions .elementAt(i)); if ((int) Math.round(sbX.getValue()) < ec.getNumberOfTimeSteps() && cbShowConditions[i].isSelected()) { TimeStep timeStep = ec.getTimeStepByTime((int) sbX.getValue()); Vector trials = timeStep.getTrials(); SingleStat stats = new SingleStat(); for (int j = 0; j < trials.size(); j++) { double property = ((Trial) trials.elementAt(j)) .getProperty(cProperties.getSelectedIndex() - 1); if (Trial.isNumber(property)) { stats.addItem(property); } } // Draw the box boxPlotGraph.addBar(stats.getQ1(useMedian), boxplotystart - (i * boxplotspacing), stats.getIRQ(useMedian), boxplotyheight, false, false, COLORS[i % COLORS.length], "", 0, 0, true); // Draw the median line. boxPlotGraph.addLine(stats.getMedian(), boxplotystart - (i * boxplotspacing), stats.getMedian(), boxplotystart - (i * boxplotspacing) - boxplotyheight, BOXPLOT_MEDIAN_LINE_COLOR, true); // Draw horizontal lines to wiskers boxPlotGraph.addLine(stats.getMin(), boxplotystart - (i * boxplotspacing) - (boxplotyheight / 2.0), stats .getQ1(useMedian), boxplotystart - (i * boxplotspacing) - (boxplotyheight / 2.0), COLORS[i % COLORS.length], true); boxPlotGraph.addLine(stats.getQ3(useMedian), boxplotystart - (i * boxplotspacing) - (boxplotyheight / 2.0), stats .getMax(), boxplotystart - (i * boxplotspacing) - (boxplotyheight / 2.0), COLORS[i % COLORS.length], true); // Draw the vertical lines at the whiskers boxPlotGraph.addLine(stats.getMin(), boxplotystart - (i * boxplotspacing), stats.getMin(), boxplotystart - (i * boxplotspacing) - boxplotyheight, COLORS[i % COLORS.length], true); boxPlotGraph.addLine(stats.getMax(), boxplotystart - (i * boxplotspacing), stats.getMax(), boxplotystart - (i * boxplotspacing) - boxplotyheight, COLORS[i % COLORS.length], true); } } double boxplotxmin = globalMin; double boxplotxmax = globalMax; if (boxplotxmax > boxplotxmin) { boxPlotGraph.setWindow(boxplotxmin, boxplotymin, boxplotxmax, boxplotymax, (boxplotxmax - boxplotxmin) / 10.0, (boxplotymax - boxplotymin) / 10.0); } else { System.out.println("drawBoxPlot Error: boxplotxmin = " + boxplotxmin + ", boxplotxmax = " + boxplotxmax); } boxPlotGraph.updateAll(); boxPlotGraph.repaint(); } private void setGlobalMinMaxProperties() { if (cProperties.getSelectedIndex() == 0 || sbY.getValue() <= 0) { return; } // Are all checkboxes unchecked? boolean allUnchecked = true; for (int i = 0; i < cbShowConditions.length; i++) { if (cbShowConditions[i].isSelected()) { allUnchecked = false; } } if (allUnchecked) { return; } if (sbX.getMax() <= sbX.getMin()) { System.out.println("Error: sbX.getMin() = " + sbX.getMin() + ", sbX.getMax() = " + sbX.getMax()); return; } globalMin = 1E20; globalMax = -1E20; for (int i = 0; i < experimentalConditions.size(); i++) { ExperimentalCondition ec = ((ExperimentalCondition) experimentalConditions .elementAt(i)); double sliderX = sbX.getMin(); double sliderIncrement = (sbX.getMax() - sbX.getMin()) / 100.0; while (sliderX < sbX.getMax()) { if ((int) Math.round(sliderX) < ec.getNumberOfTimeSteps() && cbShowConditions[i].isSelected()) { TimeStep timeStep = ec.getTimeStepByTime((int) sliderX); if (timeStep != null && timeStep.getTrials() != null) { Vector trials = timeStep.getTrials(); for (int j = 0; j < trials.size(); j++) { Trial trial = (Trial) trials.elementAt(j); double property = trial.getProperty(cProperties .getSelectedIndex() - 1); if (Trial.isNumber(property)) { globalMin = Math.min(globalMin, property); globalMax = Math.max(globalMax, property); } } } } sliderX += sliderIncrement; } } } /** * If the user has not selected a property to display or the value of the y * slider bar is less than or equal to 0, this method returns. Otherwise, * this method adds an additional horizontal axis at the top of the graph, * goes through each of the experimental conditions pulling out the * corresponding trial values and places them in their corresponding bins. * It draws the histogram, removing all the bars and updating the histogram * each time either of the slider bars move. * */ public void drawHistogram() { if (cProperties.getSelectedIndex() == 0 || sbY.getValue() <= 0) { return; } // Are all checkboxes unchecked? boolean allUnchecked = true; for (int i = 0; i < cbShowConditions.length; i++) { if (cbShowConditions[i].isSelected()) { allUnchecked = false; } } if (allUnchecked) { return; } if (globalMin >= globalMax) { System.out.println("ERROR: drawHistogram() globalMin = " + globalMin + ", globalMax = " + globalMax); return; } histogramGraph.removeAllBars(); histogramGraph.removeAllGraphLabels(); histogramGraph.addLine(0, 2, histogramGraph.getSize().width, 2, Color.black); // This keeps the yslider on the graph with the histogram so the user // knows // the time step the histogram is drawing for. addLines(XSLIDER, true); int maxHits = 0; setGlobalMinMaxProperties(); for (int i = 0; i < experimentalConditions.size(); i++) { ExperimentalCondition ec = ((ExperimentalCondition) experimentalConditions .elementAt(i)); if ((int) Math.round(sbX.getValue()) < ec.getNumberOfTimeSteps() && cbShowConditions[i].isSelected()) { TimeStep timeStep = ec.getTimeStepByTime((int) sbX.getValue()); Vector trials = timeStep.getTrials(); // XXX Should this be binSize or sbY.getValue() double localbinsize = sbY.getValue(); int[] bins = new int[(int) Math.ceil((globalMax - globalMin) / localbinsize)]; // XXX DO NOT USE i in populating bins for (int j = 0; j < trials.size(); j++) { double property = ((Trial) trials.elementAt(j)) .getProperty(cProperties.getSelectedIndex() - 1); if (Trial.isNumber(property)) { int binIndex = 0; while (property > (binIndex + 1) * localbinsize) { binIndex++; } if (binIndex < bins.length) { bins[binIndex]++; } else { System.out.println("Error putting in bins."); System.out.println("bins.length = " + bins.length); System.out.println("binIndex = " + binIndex); System.out .println("localbinsize = " + localbinsize); System.out.println("property = " + property); System.out.println("globalMin = " + globalMin); System.out.println("globalMax = " + globalMax); } } } for (int j = 0; j < bins.length; j++) { if (bins[j] > 0) { maxHits = Math.max(maxHits, bins[j]); double offset = (globalMax - globalMin) / 50.0; BarLocationData bld = new BarLocationData(globalMin + (j * localbinsize) + (i * offset), (double) bins[j], localbinsize, (double) bins[j], false, true, COLORS[i % COLORS.length], "", 0, 0, true); bld.setOutlineThickness(OUTLINE_THICKNESS); histogramGraph.addBar(bld); } } } } if (!histogramWindowFrozen) { histogramGraph.setWindow(globalMin, 0, globalMax, maxHits + 1, (globalMax - globalMin) / 10.0, maxHits / 10.0); niMinFreq.setText("0"); niMaxFreq.setText("" + maxHits); histogramGraph.updateAll(); histogramGraph.repaint(); } } private String[] getFrameLabels() { String[] retValue = new String[6]; retValue[0] = "min time"; retValue[1] = "max time"; retValue[2] = "time scale"; retValue[3] = "min mean"; retValue[4] = "max mean"; retValue[5] = "max scale"; return retValue; } /** * There are problems with the vertical scale. If the scale is to the * min/max mean, not all bars draw. If scale is drawn to histogram, all bars * draw but mean plots are flattened. This allows for easy toggling between * scales to Dwight can compare. Possibly we need two graphs with two * scales. * * @return Vertical scale for graph. */ private double[] computeMeanGraphVerticalScale() { double returnMin = 1E20; double returnMax = -1E20; try { for (int i = 0; i < experimentalConditions.size(); i++) { ExperimentalCondition ec = ((ExperimentalCondition) experimentalConditions .elementAt(i)); if (cbShowConditions[i].isSelected() && (int) Math.round(sbX.getValue()) < ec .getNumberOfTimeSteps()) { for (int j = 0; j < ec.getNumberOfTimeSteps(); j++) { returnMax = Math.max(returnMax, ec.getMean(j, cProperties.getSelectedIndex() - 1)); returnMin = Math.min(returnMin, ec.getMean(j, cProperties.getSelectedIndex() - 1)); } } } } catch (TrialException te) { oops(te.getMessage()); return null; } if (returnMin >= returnMax) { System.out.println("ERROR: min Vertical Scale, " + returnMin + ", max Vertical Scale, " + returnMax); return null; } double[] returnValue = new double[2]; returnValue[0] = returnMin; returnValue[1] = returnMax; return returnValue; } public void windowChanged(double newminx, double newminy, double newmaxx, double newmaxy) { // TODO Auto-generated method stub } }