/** * Called when one of the sliding window size or step values has changed. This attempts to be * 'smart' and instead of recalculating everything from scratch, */ private void newWindowSizeAction() { if (sgSeriesMap == null) return; XYSeries data; int windowSize = (Integer) windowSizeSpinner.getValue(); int windowStep = (Integer) windowStepSpinner.getValue(); int tot = 0; for (AbstractSeries series : chart.getAllSeries()) { if (series instanceof BaseCounterSeries) { BaseCounterSeries bcSer = (BaseCounterSeries) series; BaseCounter bc = bcSer.getCalculator(); int partitionIndex = bcSer.getPartitionIndex(); // System.out.println("Replacing series for calc with name : " + bcSer.getName() + " and // partition : " + bcSer.getPartitionIndex()); if (partitionIndex > -1) { bcSer.replaceSeries(bc.getWindowPointSeries(windowSize, windowStep, partitionIndex)); } else bcSer.replaceSeries(bc.getWindowPointSeries(windowSize, windowStep)); } else { // System.err.println("Hmm, one of the series (" + series.getName() + ") is not a // basecounter, cannot recalculate it for the new window size.");/ } } chart.repaint(); }
/** * Adjusts the x min and max bounds of the chart to match the selection region. Has no effect if * there is no selected region */ protected void zoomToSelection() { if (chart.isRangeSelected()) { double[] range = chart.getRangeSelection(); if (range[0] < range[1]) { chart.setXMin(range[0]); chart.setXMax(range[1]); chart.clearRangeSelection(); repaint(); } } }
/** * You guessed it..remove from the chart all series that are a) baseCounters, and b), have the * baseCounter name of calcName. This happens when the user toggles off the check box associated * with the named calculator. * * @param calcName */ public void removeSeriesByCalculatorName(String calcName) { List<AbstractSeries> activeSeries = chart.getAllSeries(); for (AbstractSeries series : activeSeries) { if (series instanceof BaseCounterSeries) { String name = ((BaseCounterSeries) series).getCalculator().getName(); if (name.equals(calcName)) { chart.removeSeries(series); } } } }
/** * Remove all series associated with the class specified * * @param toRemove */ public void removeSeriesByClass(Class toRemove) { List<AbstractSeries> activeSeries = chart.getAllSeries(); for (AbstractSeries series : activeSeries) { if (series instanceof BaseCounterSeries) { BaseCounter bc = ((BaseCounterSeries) series).getCalculator(); if (bc.getClass() == toRemove) { chart.removeSeries(series); } } } }
/** * Selects the columns in the associated sequence group that correspond to the selected range in * the current chart. */ protected void selectSitesFromAxesRange() { if (chart.isRangeSelected()) { double[] range = chart.getRangeSelection(); int rangeStart = (int) Math.round(range[0]); int rangeEnd = (int) Math.round(range[1]); try { SGContentPanelDisplay sgDisplay = (SGContentPanelDisplay) source; sgDisplay.selectColumns(rangeStart, rangeEnd); } catch (ClassCastException ex) { // apparently source wasn't an sgDisplay, not sure what should happen here } } }
/** * Uses the calculator with name calcName to construct & display a series for the sg. This should * be the only way new series' are added to the chart, since we need to keep track of all the * current series in the sgSeriesMap * * @param calcName * @param sg */ protected void addSeriesForSG(String calcName, SequenceGroup sg) { BaseCounter calc = null; try { calc = sgReg.getBaseCounterInstance(calcName, sg); } catch (IllegalArgumentException ex) { System.err.println("Could not find base counter of type : " + calcName); return; } List<AbstractSeries> seriesList = sgSeriesMap.get(sg); if (seriesList == null) { System.out.println( "Uh-oh, this sequence group doesn't have an associated list in the sgSeriesMap..."); } // Make a new series from the calculator int windowsize = ((Integer) windowSizeSpinner.getValue()).intValue(); int windowStep = ((Integer) windowStepSpinner.getValue()).intValue(); if (usePartitionsBox.isSelected()) { for (int i = 0; i < sg.getPartitionCount(); i++) { BaseCounterSeries ser = calc.getWindowSeries(windowsize, windowStep, i); ser.setPartitionIndex(i); seriesList.add(ser); ser.setName(calc.getName() + " - " + sg.getPartitionKeyForIndex(i)); if (ser != null && ser.size() > 0) { chart.addDataSeries(ser); chart.repaint(); } } } else { BaseCounterSeries ser = calc.getWindowSeries(windowsize, windowStep); seriesList.add(ser); if (sgSeriesMap.size() > 1) { String name = sg.getName(); if (name == null) { ser.setName(calc.getName()); } else { ser.setName(calc.getName() + " - " + sg.getName()); } } if (ser != null && ser.size() > 0) { chart.addDataSeries(ser); chart.repaint(); } } }
public void popupSaveDataAction() { JFileChooser saveChart = new JFileChooser(); int val = saveChart.showSaveDialog(parent); if (val == JFileChooser.APPROVE_OPTION) { File file = saveChart.getSelectedFile(); try { BufferedWriter writer = new BufferedWriter(new FileWriter(file)); writer.write("#Chart data for file : " + currentName + "\n"); Date now = new Date(); SimpleDateFormat dateFormatter = new SimpleDateFormat("K:mm a, EEE, MMM d, yyyy"); writer.write("#Created " + dateFormatter.format(now) + "\n"); writer.write( "#Sliding window data, window size : " + windowSizeSpinner.getValue() + " window step : " + windowStepSpinner.getValue() + "\n"); AbstractSeries data = chart.getSeries(0); if (data instanceof XYSeries) { XYSeries xyData = (XYSeries) data; for (int i = 0; i < data.size(); i++) writer.write(xyData.get(i).getX() + ",\t" + xyData.get(i).getY() + "\n"); } else { ErrorWindow.showErrorWindow( new IllegalArgumentException( "Cannot write non-xy series data (feature not implemented, yet)")); } writer.write("\n"); writer.close(); logger.info("Wrote data to file : " + file.getAbsolutePath()); } catch (IOException ioe) { logger.warning("Error writing chart data to file : " + ioe.toString()); } } }
/** * Clears the all current series from the figure, then re-adds everything based on the current sg * list and current calculators list. */ private void repaintAllSeries() { chart.removeAllSeriesSilently(); // System.out.println("Repainting all series!"); for (String calcName : currentCalculators) { for (SequenceGroup sg : sgSeriesMap.keySet()) { addSeriesForSG(calcName, sg); } } }
public void saveChartImage() { BufferedImage chartImage = chart.getImage(); JFileChooser saveChart = new JFileChooser(); int val = saveChart.showSaveDialog(parent); if (val == JFileChooser.APPROVE_OPTION) { File file = saveChart.getSelectedFile(); try { ImageIO.write(chartImage, "png", file); } catch (IOException ioe) { logger.warning("Error saving chart image to file : " + ioe.toString()); } } }
/** * This method updates the current list of calculators (currentCalculators) in toggle fashion, * meaning that if calcName is in the list, it is removed. If not, it is added. Further, when the * calculator is removed, all series in the chart associated with the calculator are also removed. * When a calculator is added, series are added for all active sequenceGroups, and all associated * partitions if usePartitions is true. * * @param calcName */ public void toggleCalculator(String calcName) { if (currentCalculators.contains(calcName)) { currentCalculators.remove(calcName); removeSeriesByCalculatorName(calcName); } else { currentCalculators.add(calcName); // For all active sequence groups, add the new data series for (SequenceGroup sg : sgSeriesMap.keySet()) { addSeriesForSG(calcName, sg); } } chart.inferBoundsFromCurrentSeries(); repaint(); }
public void analyze(String name, Object data) { if (data.getClass() != SequenceGroup.class) { ErrorWindow.showErrorWindow( new IllegalArgumentException( "Got a incompatible data type for SequenceLineChart: " + data.getClass())); return; } SequenceGroup currentSG = (SequenceGroup) data; originalSG = currentSG; originalSG.addPartitionListener(this); originalSG.addSGChangeListener(this); sgSeriesMap.put((SequenceGroup) data, new ArrayList<AbstractSeries>()); currentName = name; if (topLabel != null) topLabel.setText(currentName); else topLabel = new JLabel(currentName); topLabel.setFont(defaultFont); int maxLength = currentSG.getMaxSeqLength(); // Guess some decent initial values for size of window and step int windowSize = Math.min(100, maxLength); int windowStep = maxLength > 50 ? 10 : 1; if (maxLength > 9999) { windowSize = 1000; windowStep = 100; } SpinnerModel sizeModel = new SpinnerNumberModel(windowSize, 1, maxLength, 1); SpinnerModel stepModel = new SpinnerNumberModel(windowStep, 1, maxLength / 2, 1); windowSizeSpinner.setModel(sizeModel); windowStepSpinner.setModel(stepModel); if (currentSG.getPartitionCount() < 2) { usePartitionsBox.setSelected(false); usePartitionsBox.setEnabled(false); } else { usePartitionsBox.setEnabled(true); usePartitionsBox.setSelected(true); } toggleCalculator(SGStatisticsRegistry.NUC_DIVERSITY); chart.repaint(); }
private void initializeComponents() { int leftPanelWidth = 250; JPanel parentPanel = new JPanel(); parent = new JScrollPane(parentPanel); chartSize = new Dimension(500, 300); parentPanel.setLayout(new BoxLayout(parentPanel, BoxLayout.X_AXIS)); JPanel leftPanel = new JPanel(); leftPanel.setMaximumSize(new Dimension(leftPanelWidth, Integer.MAX_VALUE)); parent.setBorder(BorderFactory.createEmptyBorder()); parent.setViewportBorder(BorderFactory.createEmptyBorder()); jSeparator1 = new javax.swing.JSeparator(); chartTypeLabel = new javax.swing.JLabel(); windowSizeSpinner = new javax.swing.JSpinner(); windowStepSpinner = new javax.swing.JSpinner(); jLabel1 = new javax.swing.JLabel(); jLabel2 = new javax.swing.JLabel(); leftPanel.setPreferredSize(new java.awt.Dimension(leftPanelWidth, 300)); leftPanel.setBackground(Color.WHITE); leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.PAGE_AXIS)); topLabel = new JLabel(); topLabel.setText(currentName); topLabel.setHorizontalTextPosition(SwingConstants.CENTER); leftPanel.add(topLabel); JPanel topPanel = new JPanel(); topPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 1, 0)); topPanel.setBackground(Color.white); topPanel.setMaximumSize(new Dimension(leftPanelWidth, 16)); topPanel.setAlignmentX(Component.LEFT_ALIGNMENT); leftPanel.add(topPanel); JPanel buttonPanel = new JPanel(); buttonPanel.setOpaque(false); buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); buttonPanel.setAlignmentX(LEFT_ALIGNMENT); buttonPanel.setMaximumSize(new Dimension(leftPanelWidth, 40)); buttonPanel.setPreferredSize(new Dimension(leftPanelWidth, 36)); saveButton = new JButton(getIcon("icons/save.png")); saveButton.setFont(defaultFont); saveButton.setToolTipText("Save chart image"); saveButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent arg0) { saveChartImage(); } }); saveButton.setAlignmentX(LEFT_ALIGNMENT); JButton restoreButton = new JButton(getIcon("icons/expand.png")); restoreButton.setToolTipText("Restore default axes boundaries"); restoreButton.setFont(defaultFont); restoreButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent arg0) { restoreDefaultBounds(); } }); restoreButton.setAlignmentX(LEFT_ALIGNMENT); JButton zoomButton = new JButton(getIcon("icons/zoom.png")); zoomButton.setToolTipText("Zoom to selection region"); zoomButton.setFont(defaultFont); zoomButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent arg0) { zoomToSelection(); } }); zoomButton.setAlignmentX(LEFT_ALIGNMENT); JButton selectRangeButton = new JButton(getIcon("icons/selectColumns.png")); selectRangeButton.setFont(defaultFont); selectRangeButton.setToolTipText("Select range in sequence group"); selectRangeButton.setAlignmentX(LEFT_ALIGNMENT); selectRangeButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent arg0) { selectSitesFromAxesRange(); } }); JButton clearButton = new JButton("Clear"); clearButton.setFont(defaultFont); // selectRangeButton.setPreferredSize(new Dimension(80, 24)); clearButton.setAlignmentX(LEFT_ALIGNMENT); clearButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent arg0) { chart.clearRangeSelection(); chart.repaint(); } }); buttonPanel.add(saveButton); buttonPanel.add(restoreButton); buttonPanel.add(zoomButton); buttonPanel.add(selectRangeButton); leftPanel.add(buttonPanel); usePartitionsBox = new JCheckBox("Use partition data"); usePartitionsBox.setFont(defaultFont); usePartitionsBox.setSelected(true); usePartitionsBox.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { repaintAllSeries(); } }); leftPanel.add(usePartitionsBox); SpinnerModel sizeModel = new SpinnerNumberModel(100, 1, 1000, 10); SpinnerModel stepModel = new SpinnerNumberModel(100, 1, 1000, 5); windowSizeSpinner = new JSpinner(sizeModel); windowStepSpinner = new JSpinner(stepModel); windowStepSpinner.setMaximumSize(new Dimension(80, 25)); windowSizeSpinner.setMaximumSize(new Dimension(80, 25)); windowSizeLabel = new JLabel(); windowSizeLabel.setFont(defaultFont); windowSizeLabel.setText("Window size"); windowStepLabel = new JLabel(); windowStepLabel.setFont(defaultFont); windowStepLabel.setText("Window step"); JPanel spinnerLabels = new JPanel(); spinnerLabels.setAlignmentX(LEFT_ALIGNMENT); spinnerLabels.setOpaque(false); spinnerLabels.setLayout(new BoxLayout(spinnerLabels, BoxLayout.X_AXIS)); spinnerLabels.add(windowSizeLabel); spinnerLabels.add(Box.createHorizontalStrut(16)); spinnerLabels.add(windowStepLabel); spinnerLabels.add(Box.createHorizontalGlue()); JPanel spinnerPanel = new JPanel(); spinnerPanel.setAlignmentX(LEFT_ALIGNMENT); spinnerPanel.setOpaque(false); spinnerPanel.setLayout(new BoxLayout(spinnerPanel, BoxLayout.X_AXIS)); spinnerPanel.add(windowSizeSpinner); spinnerPanel.add(Box.createHorizontalStrut(25)); spinnerPanel.add(windowStepSpinner); spinnerPanel.add(Box.createHorizontalGlue()); leftPanel.add(spinnerLabels); leftPanel.add(spinnerPanel); windowSizeSpinner.setFont(defaultFont); windowSizeSpinner.addChangeListener( new javax.swing.event.ChangeListener() { public void stateChanged(javax.swing.event.ChangeEvent evt) { newWindowSizeAction(); } }); windowStepSpinner.setFont(defaultFont); windowStepSpinner.addChangeListener( new javax.swing.event.ChangeListener() { public void stateChanged(javax.swing.event.ChangeEvent evt) { newWindowSizeAction(); } }); leftPanel.add(Box.createRigidArea(new Dimension(0, 10))); JScrollPane pane = createStatisticListPanel(); pane.setPreferredSize(new Dimension(leftPanelWidth, 200)); pane.setMaximumSize(new Dimension(leftPanelWidth, 400)); pane.setBackground(Color.white); pane.setAlignmentX(Component.LEFT_ALIGNMENT); leftPanel.add(pane); leftPanel.add(Box.createVerticalGlue()); JPanel bottomPanel = new JPanel(); bottomPanel.setBackground(Color.white); chart = new XYSeriesFigure(); chart.setMinimumSize(chartSize); chart.setPreferredSize(chartSize); chart.addMouseListener(new PopupListener()); parentPanel.add(leftPanel); parentPanel.add(chart); chartPopup = new JPopupMenu(); JMenuItem popupExport = new JMenuItem("Save as image"); popupExport.addActionListener( new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { saveChartImage(); } }); chartPopup.add(popupExport); JMenuItem popupSaveData = new JMenuItem("Save data as .csv"); popupSaveData.addActionListener( new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { popupSaveDataAction(); } }); chartPopup.add(popupSaveData); chartPopup.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY)); setLayout(new BorderLayout()); add(parent, BorderLayout.CENTER); chart.addSeriesListener(this); }
/** Re-infer the axes bounds from the current series & repaint */ protected void restoreDefaultBounds() { chart.inferBoundsFromCurrentSeries(); repaint(); }