/**
  * Create summary table with horizontal columns.
  *
  * @param writer The Excel writer.
  * @param rowIndex The selected row.
  */
 private void printSummaryHeader(ExcelWriter writer, int rowIndex) {
   writer.writeElement(rowIndex, 0, "channel");
   writer.writeElement(rowIndex, 1, "zsection");
   writer.writeElement(rowIndex, 2, "time");
   for (int y = 0; y < channelSummaryTable.getRowCount(); y++)
     writer.writeElement(rowIndex, 3 + y, channelSummaryTable.getValueAt(y, 0));
 }
 /** Invokes when ROI are removed. */
 void onFigureRemoved() {
   channelSelection.setEnabled(false);
   showIntensityTable.setEnabled(false);
   saveButton.setEnabled(false);
   channelSelection.setVisible(false);
   channelSummaryTable.setVisible(false);
 }
  /**
   * Populate the summary table with the list of values for the ROI at coord.
   *
   * @param coord see above.
   */
  private void populateChannelSummaryTable(Coord3D coord) {
    List<String> statNames = new ArrayList<String>();
    List<String> channelNames = new ArrayList<String>();
    ROIFigure fig = shape.getFigure();
    int count = 0;
    statNames.add("Min");
    statNames.add("Max");
    statNames.add("Sum");
    statNames.add("Mean");
    statNames.add("Std Dev.");
    statNames.add("NumPixels");
    if (areaFigure(fig)) addAreaStats(statNames);
    else if (lineFigure(fig)) addLineStats(statNames);
    else if (pointFigure(fig)) addPointStats(statNames);
    Iterator<Integer> channelIterator = channelName.keySet().iterator();
    while (channelIterator.hasNext()) channelNames.add(channelName.get(channelIterator.next()));
    Double data[][] = new Double[channelName.size()][statNames.size()];

    channelIterator = channelName.keySet().iterator();
    int channel;
    count = 0;
    while (channelIterator.hasNext()) {
      channel = channelIterator.next();
      populateSummaryColumn(fig, data, channel, count);
      count++;
    }

    channelSummaryModel = new ChannelSummaryModel(statNames, channelNames, data);
    channelSummaryTable.setModel(channelSummaryModel);
  }
 /**
  * Adds the any remaining fields (min, max, mean, stdDev) to the file being saved.
  *
  * @param writer The Excel writer.
  * @param rowIndex The selected row.
  * @param channel The channel to output.
  * @param z z-section to output.
  * @param t timepoint to output.
  */
 private void outputSummaryRow(ExcelWriter writer, int rowIndex, Integer channel, int z, int t) {
   writer.writeElement(rowIndex, 0, channelName.get(channel));
   writer.writeElement(rowIndex, 1, z + "");
   writer.writeElement(rowIndex, 2, t + "");
   int col;
   String v;
   for (int y = 0; y < channelSummaryTable.getRowCount(); y++) {
     col = getColumn(channelName.get(channel));
     if (col == -1) continue;
     v = (String) channelSummaryTable.getValueAt(y, col);
     if (v.contains(".") && v.contains(",")) {
       v = v.replace(".", "");
       v = v.replace(",", ".");
     }
     writer.writeElement(rowIndex, 3 + y, new Double(v));
   }
 }
  /**
   * Get the analysis results from the model and convert to the necessary array. data types using
   * the ROIStats wrapper then create the appropriate table data and summary statistics.
   */
  void displayAnalysisResults() {
    if (state == State.ANALYSING) return;
    this.ROIStats = model.getAnalysisResults();
    if (ROIStats == null || ROIStats.size() == 0) return;
    state = State.ANALYSING;
    channelSelection.setVisible(true);
    clearMaps();
    shapeStatsList = new TreeMap<Coord3D, Map<StatsType, Map>>(new Coord3D());
    pixelStats = new TreeMap<Coord3D, Map<Integer, Map<Point, Double>>>(new Coord3D());
    shapeMap = new TreeMap<Coord3D, ROIShape>(new Coord3D());
    minStats = new TreeMap<Coord3D, Map<Integer, Double>>(new Coord3D());
    maxStats = new TreeMap<Coord3D, Map<Integer, Double>>(new Coord3D());
    meanStats = new TreeMap<Coord3D, Map<Integer, Double>>(new Coord3D());
    sumStats = new TreeMap<Coord3D, Map<Integer, Double>>(new Coord3D());
    stdDevStats = new TreeMap<Coord3D, Map<Integer, Double>>(new Coord3D());

    Entry entry;
    Iterator j = ROIStats.entrySet().iterator();
    channelName = new TreeMap<Integer, String>();
    nameMap = new LinkedHashMap<String, Integer>();

    int minZ = Integer.MAX_VALUE, maxZ = Integer.MIN_VALUE;
    int minT = Integer.MAX_VALUE, maxT = Integer.MIN_VALUE;
    clearAllValues();
    Coord3D c3D;
    Map<StatsType, Map> shapeStats;
    ChannelData channelData;
    int channel;
    Iterator<ChannelData> i;
    List<ChannelData> metadata = model.getMetadata();
    while (j.hasNext()) {
      entry = (Entry) j.next();
      shape = (ROIShape) entry.getKey();
      c3D = shape.getCoord3D();
      minT = Math.min(minT, c3D.getTimePoint());
      maxT = Math.max(maxT, c3D.getTimePoint());
      minZ = Math.min(minZ, c3D.getZSection());
      maxZ = Math.max(maxZ, c3D.getZSection());

      shapeMap.put(c3D, shape);
      if (shape.getFigure() instanceof MeasureTextFigure) {
        state = State.READY;
        return;
      }

      shapeStats = AnalysisStatsWrapper.convertStats((Map) entry.getValue());
      shapeStatsList.put(c3D, shapeStats);

      minStats.put(c3D, shapeStats.get(StatsType.MIN));
      maxStats.put(c3D, shapeStats.get(StatsType.MAX));
      meanStats.put(c3D, shapeStats.get(StatsType.MEAN));
      sumStats.put(c3D, shapeStats.get(StatsType.SUM));
      stdDevStats.put(c3D, shapeStats.get(StatsType.STDDEV));
      pixelStats.put(c3D, shapeStats.get(StatsType.PIXEL_PLANEPOINT2D));

      /* really inefficient but hey.... quick hack just now till refactor */
      channelName.clear();
      nameMap.clear();
      channelColour.clear();

      i = metadata.iterator();
      List<String> names = new ArrayList<String>();
      String name;
      while (i.hasNext()) {
        channelData = i.next();
        channel = channelData.getIndex();
        if (model.isChannelActive(channel)) {
          name = channelData.getChannelLabeling();
          if (names.contains(name)) name += " " + channel;
          channelName.put(channel, name);
          nameMap.put(channelName.get(channel), channel);
          channelColour.put(channel, (Color) model.getActiveChannels().get(channel));
        }
      }
    }
    if (channelName.size() != channelColour.size() || nameMap.size() == 0) {
      createComboBox();
      List<String> names = channelSummaryModel.getRowNames();
      List<String> channelNames = new ArrayList<String>();
      Double data[][] = new Double[channelName.size()][names.size()];
      channelSummaryModel = new ChannelSummaryModel(names, channelNames, data);
      channelSummaryTable.setModel(channelSummaryModel);
      saveButton.setEnabled(false);
      showIntensityTable.setEnabled(false);
      if (intensityDialog != null) intensityDialog.setVisible(false);
      state = State.READY;
      return;
    }
    saveButton.setEnabled(true);
    showIntensityTable.setEnabled(true);
    maxZ = maxZ + 1;
    minZ = minZ + 1;
    maxT = maxT + 1;
    minT = minT + 1;

    createComboBox();
    Object[] nameColour = (Object[]) channelSelection.getSelectedItem();
    String string = (String) nameColour[1];
    selectedChannel = nameMap.get(string);
    zSlider.setMaximum(maxZ);
    zSlider.setMinimum(minZ);
    tSlider.setMaximum(maxT);
    tSlider.setMinimum(minT);
    zSlider.setVisible((maxZ != minZ));
    tSlider.setVisible((maxT != minT));
    tSlider.setValue(model.getCurrentView().getTimePoint() + 1);
    zSlider.setValue(model.getCurrentView().getZSection() + 1);
    coord = new Coord3D(zSlider.getValue() - 1, tSlider.getValue() - 1);
    shape = shapeMap.get(coord);
    populateData(coord, selectedChannel);
    saveButton.setEnabled(tableModel.getRowCount() > 0);
    state = State.READY;
  }
 /**
  * Populates the table and fields with the data.
  *
  * @param coord the coordinate of the shape being analysed.
  * @param channel the channel to be analysed.
  */
 private void populateData(Coord3D coord, int channel) {
   channelSummaryTable.setVisible(true);
   interpretResults(coord, channel);
   populateChannelSummaryTable(coord);
 }