Example usage for javax.swing JTable getFontMetrics

List of usage examples for javax.swing JTable getFontMetrics

Introduction

In this page you can find the example usage for javax.swing JTable getFontMetrics.

Prototype

public FontMetrics getFontMetrics(Font font) 

Source Link

Document

Gets the FontMetrics for the specified Font.

Usage

From source file:org.esa.beam.visat.toolviews.stat.StatisticsPanel.java

private JPanel createStatPanel(Stx stx, final Mask regionalMask, final Mask qualityMask, int stxIdx,
        RasterDataNode raster) {/*from w  w  w .  j  av a  2  s.co m*/

    final Histogram histogram = stx.getHistogram();
    final int row = stxIdx + 1; // account for header

    boolean includeFileMetaData = statisticsCriteriaPanel.isIncludeFileMetaData();
    boolean includeMaskMetaData = statisticsCriteriaPanel.isIncludeMaskMetaData();
    boolean includeBandMetaData = statisticsCriteriaPanel.isIncludeBandMetaData();
    boolean includeBinningInfo = statisticsCriteriaPanel.isIncludeBinningInfo();
    ;
    boolean includeTimeMetaData = statisticsCriteriaPanel.isIncludeTimeMetaData();
    boolean isIncludeTimeSeriesMetaData = statisticsCriteriaPanel.isIncludeTimeSeriesMetaData();
    boolean includeProjectionParameters = statisticsCriteriaPanel.isIncludeProjectionParameters();
    boolean includeColumnBreaks = statisticsCriteriaPanel.isIncludeColBreaks();

    // Initialize all spreadsheet table indices to -1 (default don't use value)
    if (stxIdx == 0 || metaDataFieldsHashMap == null || primaryStatisticsFieldsHashMap == null) {
        initHashMaps();
    }

    XIntervalSeries histogramSeries = new XIntervalSeries("Histogram");
    double histDomainBounds[] = { histogram.getLowValue(0), histogram.getHighValue(0) };
    double histRangeBounds[] = { Double.NaN, Double.NaN };

    if (!fixedHistDomainAllPlots || (fixedHistDomainAllPlots && !fixedHistDomainAllPlotsInitialized)) {
        if (!statisticsCriteriaPanel.isLogMode()) {
            if (statisticsCriteriaPanel.plotsThreshDomainSpan()) {

                if (statisticsCriteriaPanel.plotsThreshDomainLow() >= 0.1) {
                    histDomainBounds[0] = histogram
                            .getPTileThreshold((statisticsCriteriaPanel.plotsThreshDomainLow()) / 100)[0];
                }

                if (statisticsCriteriaPanel.plotsThreshDomainHigh() <= 99.9) {
                    histDomainBounds[1] = histogram
                            .getPTileThreshold(statisticsCriteriaPanel.plotsThreshDomainHigh() / 100)[0];
                }

            } else if (statisticsCriteriaPanel.plotsDomainSpan()) {
                if (!Double.isNaN(statisticsCriteriaPanel.plotsDomainLow())) {
                    histDomainBounds[0] = statisticsCriteriaPanel.plotsDomainLow();
                }
                if (!Double.isNaN(statisticsCriteriaPanel.plotsDomainHigh())) {
                    histDomainBounds[1] = statisticsCriteriaPanel.plotsDomainHigh();
                }
            }

        } else {
            histDomainBounds[0] = histogram.getBinLowValue(0, 0);
            histDomainBounds[1] = histogram.getHighValue(0);
        }

        //            if (!LogMode && plotsThreshDomainSpan && plotsThreshDomainLow >= 0.1 && plotsThreshDomainHigh <= 99.9) {
        //                histDomainBounds[0] = histogram.getPTileThreshold((plotsThreshDomainLow) / 100)[0];
        //                histDomainBounds[1] = histogram.getPTileThreshold(plotsThreshDomainHigh / 100)[0];
        //
        //            } else {
        //                histDomainBounds[0] = histogram.getBinLowValue(0, 0);
        //                histDomainBounds[1] = histogram.getHighValue(0);
        //            }

        if (fixedHistDomainAllPlots && !fixedHistDomainAllPlotsInitialized) {
            histDomainBoundsAllPlots[0] = histDomainBounds[0];
            histDomainBoundsAllPlots[1] = histDomainBounds[1];
            fixedHistDomainAllPlotsInitialized = true;
        }
    } else {
        histDomainBounds[0] = histDomainBoundsAllPlots[0];
        histDomainBounds[1] = histDomainBoundsAllPlots[1];
    }

    int[] bins = histogram.getBins(0);
    for (int j = 0; j < bins.length; j++) {

        histogramSeries.add(histogram.getBinLowValue(0, j), histogram.getBinLowValue(0, j),
                j < bins.length - 1 ? histogram.getBinLowValue(0, j + 1) : histogram.getHighValue(0), bins[j]);
    }

    String logTitle = (statisticsCriteriaPanel.isLogMode()) ? "Log10 of " : "";

    ChartPanel histogramPanel = createChartPanel(histogramSeries,
            logTitle + raster.getName() + " (" + raster.getUnit() + ")", "Frequency in #Pixels",
            new Color(0, 0, 127), histDomainBounds, histRangeBounds);

    //  histogramPanel.setPreferredSize(new Dimension(300, 200));

    if (statisticsCriteriaPanel.exactPlotSize()) {
        histogramPanel.setMinimumSize(new Dimension(statisticsCriteriaPanel.plotSizeWidth(),
                statisticsCriteriaPanel.plotSizeHeight()));
        histogramPanel.setPreferredSize(new Dimension(statisticsCriteriaPanel.plotSizeWidth(),
                statisticsCriteriaPanel.plotSizeHeight()));
        histogramPanel.setMaximumSize(new Dimension(statisticsCriteriaPanel.plotSizeWidth(),
                statisticsCriteriaPanel.plotSizeHeight()));
    } else {
        histogramPanel.setMinimumSize(new Dimension(plotMinWidth, plotMinHeight));
        histogramPanel.setPreferredSize(new Dimension(plotMinWidth, plotMinHeight));
    }

    XIntervalSeries percentileSeries = new XIntervalSeries("Percentile");

    //        if (1 == 2 && LogMode) {
    //            percentileSeries.add(0,
    //                    0,
    //                    1,
    //                    Math.pow(10, histogram.getLowValue(0)));
    //            for (int j = 1; j < 99; j++) {
    //                percentileSeries.add(j,
    //                        j,
    //                        j + 1,
    //                        Math.pow(10, histogram.getPTileThreshold(j / 100.0)[0]));
    //            }
    //            percentileSeries.add(99,
    //                    99,
    //                    100,
    //                    Math.pow(10, histogram.getHighValue(0)));
    //
    //        } else {
    //            percentileSeries.add(0,
    //                    0,
    //                    0.25,
    //                    histogram.getLowValue(0));
    //
    //            for (double j = 0.25; j < 99.75; j += .25) {
    //                percentileSeries.add(j,
    //                        j,
    //                        j + 1,
    //                        histogram.getPTileThreshold(j / 100.0)[0]);
    //            }
    //            percentileSeries.add(99.75,
    //                    99.75,
    //                    100,
    //                    histogram.getHighValue(0));
    //        }

    //
    //        double fraction = 0;
    //        for (int j = 0; j < bins.length; j++) {
    //
    //             fraction = (1.0) * j / bins.length;
    //
    //            if (fraction > 0 && fraction < 1) {
    //                percentileSeries.add(histogram.getBinLowValue(0, j),
    //                        histogram.getBinLowValue(0, j),
    //                        j < bins.length - 1 ? histogram.getBinLowValue(0, j + 1) : histogram.getHighValue(0),
    //                        histogram.getPTileThreshold(fraction)[0]);
    //            }
    //
    //
    //        }
    //
    //        double test = fraction;

    double[] percentileDomainBounds = { Double.NaN, Double.NaN };
    double[] percentileRangeBounds = { Double.NaN, Double.NaN };
    ChartPanel percentilePanel = null;

    if (invertPercentile) {

        double increment = .01;
        for (double j = 0; j < 100; j += increment) {
            double fraction = j / 100.0;
            double nextFraction = (j + increment) / 100.0;

            if (fraction > 0.0 && fraction < 1.0 && nextFraction > 0.0 && nextFraction < 1.0) {
                double thresh = histogram.getPTileThreshold(fraction)[0];
                double nextThresh = histogram.getPTileThreshold(nextFraction)[0];

                percentileSeries.add(thresh, thresh, nextThresh, j);
            }
        }

        if (!statisticsCriteriaPanel.isLogMode()) {
            percentileDomainBounds[0] = histDomainBounds[0];
            percentileDomainBounds[1] = histDomainBounds[1];
        }
        percentileRangeBounds[0] = 0;
        percentileRangeBounds[1] = 100;

        percentilePanel = createScatterChartPanel(percentileSeries,
                logTitle + raster.getName() + " (" + raster.getUnit() + ")", "Percent Threshold",
                new Color(0, 0, 0), percentileDomainBounds, percentileRangeBounds);

    } else {
        percentileSeries.add(0, 0, 0.25, histogram.getLowValue(0));

        for (double j = 0.25; j < 99.75; j += .25) {
            percentileSeries.add(j, j, j + 1, histogram.getPTileThreshold(j / 100.0)[0]);
        }
        percentileSeries.add(99.75, 99.75, 100, histogram.getHighValue(0));

        percentileDomainBounds[0] = 0;
        percentileDomainBounds[1] = 100;
        percentileRangeBounds[0] = histDomainBounds[0];
        percentileRangeBounds[1] = histDomainBounds[1];

        percentilePanel = createScatterChartPanel(percentileSeries, "Percent_Threshold",
                logTitle + raster.getName() + " (" + raster.getUnit() + ")", new Color(0, 0, 0),
                percentileDomainBounds, percentileRangeBounds);

    }

    //   percentilePanel.setPreferredSize(new Dimension(300, 200));
    if (statisticsCriteriaPanel.exactPlotSize()) {
        percentilePanel.setMinimumSize(new Dimension(statisticsCriteriaPanel.plotSizeWidth(),
                statisticsCriteriaPanel.plotSizeHeight()));
        percentilePanel.setPreferredSize(new Dimension(statisticsCriteriaPanel.plotSizeWidth(),
                statisticsCriteriaPanel.plotSizeHeight()));
        percentilePanel.setMaximumSize(new Dimension(statisticsCriteriaPanel.plotSizeWidth(),
                statisticsCriteriaPanel.plotSizeHeight()));
    } else {
        percentilePanel.setMinimumSize(new Dimension(plotMinWidth, plotMinHeight));
        percentilePanel.setPreferredSize(new Dimension(plotMinWidth, plotMinHeight));
    }

    int size = raster.getRasterHeight() * raster.getRasterWidth();

    int validPixelCount = histogram.getTotals()[0];

    int dataRows = 0;

    //                new Object[]{"RasterSize(Pixels)", size},
    //                new Object[]{"SampleSize(Pixels)", histogram.getTotals()[0]},

    Object[][] totalPixels = null;

    if (statisticsCriteriaPanel.includeTotalPixels()) {
        int totalPixelCount = stx.getRawTotal();
        double percentFilled = (totalPixelCount > 0) ? (1.0 * validPixelCount / totalPixelCount) : 0;

        totalPixels = new Object[][] { new Object[] { "Regional_Pixels", stx.getRawTotal() },
                new Object[] { "Valid_Pixels", validPixelCount },
                new Object[] { "Fraction_Valid", percentFilled } };

    } else {
        totalPixels = new Object[][] { new Object[] { "Valid_Pixels", validPixelCount } };
    }
    dataRows += totalPixels.length;

    Object[][] firstData = new Object[][] { new Object[] { "Mean", stx.getMean() } };
    dataRows += firstData.length;

    Object[][] minMaxData = null;
    if (statisticsCriteriaPanel.includeMinMax()) {
        minMaxData = new Object[][] { new Object[] { "Minimum", stx.getMinimum() },
                new Object[] { "Maximum", stx.getMaximum() } };
        dataRows += minMaxData.length;
    }

    Object[] medianObject = null;

    if (statisticsCriteriaPanel.includeMedian()) {
        medianObject = new Object[] { "Median", stx.getMedianRaster() };

        dataRows++;
    }

    Object[][] secondData = new Object[][] { new Object[] { "Standard_Deviation", stx.getStandardDeviation() },
            new Object[] { "Variance", getVariance(stx) },
            new Object[] { "Coefficient_of_Variation", getCoefficientOfVariation(stx) } };
    dataRows += secondData.length;

    Object[][] binningInfo = null;
    if (statisticsCriteriaPanel.isIncludeBinningInfo()) {
        binningInfo = new Object[][] { new Object[] { "Total_Bins", histogram.getNumBins()[0] },
                new Object[] { "Bin_Width", getBinSize(histogram) },
                new Object[] { "Bin_Min", histogram.getLowValue(0) },
                new Object[] { "Bin_Max", histogram.getHighValue(0) } };

        dataRows += binningInfo.length;
    }

    Object[][] histogramStats = null;
    if (statisticsCriteriaPanel.includeHistogramStats()) {
        if (statisticsCriteriaPanel.isLogMode()) {
            histogramStats = new Object[][] {
                    new Object[] { "Mean(LogBinned)", Math.pow(10, histogram.getMean()[0]) },
                    new Object[] { "Median(LogBinned)", Math.pow(10, stx.getMedian()) },
                    new Object[] { "StandardDeviation(LogBinned)",
                            Math.pow(10, histogram.getStandardDeviation()[0]) } };
        } else {
            histogramStats = new Object[][] { new Object[] { "Mean(Binned)", histogram.getMean()[0] },
                    new Object[] { "Median(Binned)", stx.getMedian() },
                    new Object[] { "StandardDeviation(Binned)", histogram.getStandardDeviation()[0] } };
        }
        dataRows += histogramStats.length;
    }

    Object[][] percentData = new Object[statisticsCriteriaPanel.getPercentThresholdsList().size()][];
    for (int i = 0; i < statisticsCriteriaPanel.getPercentThresholdsList().size(); i++) {
        int value = statisticsCriteriaPanel.getPercentThresholdsList().get(i);
        double percent = value / 100.0;
        String percentString = Integer.toString(value);

        Object[] pTileThreshold;
        if (statisticsCriteriaPanel.isLogMode()) {
            pTileThreshold = new Object[] { percentString + "%Threshold(Log)",
                    Math.pow(10, histogram.getPTileThreshold(percent)[0]) };
        } else {
            pTileThreshold = new Object[] { percentString + "%Threshold",
                    histogram.getPTileThreshold(percent)[0] };
        }
        percentData[i] = pTileThreshold;
    }
    dataRows += percentData.length;

    Object[][] tableData = new Object[dataRows][];
    int tableDataIdx = 0;

    if (totalPixels != null) {
        for (int i = 0; i < totalPixels.length; i++) {
            tableData[tableDataIdx] = totalPixels[i];
            tableDataIdx++;
        }
    }

    if (firstData != null) {
        for (int i = 0; i < firstData.length; i++) {
            tableData[tableDataIdx] = firstData[i];
            tableDataIdx++;
        }
    }

    if (medianObject != null) {
        tableData[tableDataIdx] = medianObject;
        tableDataIdx++;
    }

    if (minMaxData != null) {
        for (int i = 0; i < minMaxData.length; i++) {
            tableData[tableDataIdx] = minMaxData[i];
            tableDataIdx++;
        }
    }

    if (secondData != null) {
        for (int i = 0; i < secondData.length; i++) {
            tableData[tableDataIdx] = secondData[i];
            tableDataIdx++;
        }
    }

    if (binningInfo != null) {
        for (int i = 0; i < binningInfo.length; i++) {
            tableData[tableDataIdx] = binningInfo[i];
            tableDataIdx++;
        }
    }

    if (histogramStats != null) {
        for (int i = 0; i < histogramStats.length; i++) {
            tableData[tableDataIdx] = histogramStats[i];
            tableDataIdx++;
        }
    }

    if (percentData != null) {
        for (int i = 0; i < percentData.length; i++) {
            tableData[tableDataIdx] = percentData[i];
            tableDataIdx++;
        }
    }

    numStxFields = tableData.length;

    int fieldIdx = 0;

    // Initialize indices
    if (stxIdx == 0) {

        primaryStatisticsFieldsHashMap.put(PrimaryStatisticsFields.FileRefNum, fieldIdx);
        fieldIdx++;
        primaryStatisticsFieldsHashMap.put(PrimaryStatisticsFields.BandName, fieldIdx);
        fieldIdx++;
        primaryStatisticsFieldsHashMap.put(PrimaryStatisticsFields.MaskName, fieldIdx);
        fieldIdx++;
        primaryStatisticsFieldsHashMap.put(PrimaryStatisticsFields.QualityMaskName, fieldIdx);
        fieldIdx++;

        stxFieldsStartIdx = fieldIdx;
        fieldIdx += numStxFields;
        stxFieldsEndIdx = fieldIdx - 1;
        if (includeBandMetaData) {
            if (includeColumnBreaks) {
                metaDataFieldsHashMap.put(MetaDataFields.BandMetaDataBreak, fieldIdx);
                fieldIdx++;
            }
            metaDataFieldsHashMap.put(MetaDataFields.BandName, fieldIdx);
            fieldIdx++;
            metaDataFieldsHashMap.put(MetaDataFields.BandUnit, fieldIdx);
            fieldIdx++;
            metaDataFieldsHashMap.put(MetaDataFields.BandValidExpression, fieldIdx);
            fieldIdx++;
            metaDataFieldsHashMap.put(MetaDataFields.BandDescription, fieldIdx);
            fieldIdx++;

        }

        if (includeMaskMetaData) {
            if (includeColumnBreaks) {
                metaDataFieldsHashMap.put(MetaDataFields.RegionalMaskMetaDataBreak, fieldIdx);
                fieldIdx++;
            }
            metaDataFieldsHashMap.put(MetaDataFields.RegionalMaskName, fieldIdx);
            fieldIdx++;
            metaDataFieldsHashMap.put(MetaDataFields.RegionalMaskDescription, fieldIdx);
            fieldIdx++;
            metaDataFieldsHashMap.put(MetaDataFields.RegionalMaskExpression, fieldIdx);
            fieldIdx++;

            if (includeColumnBreaks) {
                metaDataFieldsHashMap.put(MetaDataFields.QualityMaskMetaDataBreak, fieldIdx);
                fieldIdx++;
            }
            metaDataFieldsHashMap.put(MetaDataFields.QualityMaskName, fieldIdx);
            fieldIdx++;
            metaDataFieldsHashMap.put(MetaDataFields.QualityMaskDescription, fieldIdx);
            fieldIdx++;
            metaDataFieldsHashMap.put(MetaDataFields.QualityMaskExpression, fieldIdx);
            fieldIdx++;
        }

        if (includeTimeMetaData || isIncludeTimeSeriesMetaData) {
            if (includeColumnBreaks) {
                metaDataFieldsHashMap.put(MetaDataFields.TimeMetaDataBreak, fieldIdx);
                fieldIdx++;
            }

            if (includeTimeMetaData) {
                metaDataFieldsHashMap.put(MetaDataFields.StartDate, fieldIdx);
                fieldIdx++;
                metaDataFieldsHashMap.put(MetaDataFields.StartTime, fieldIdx);
                fieldIdx++;
                metaDataFieldsHashMap.put(MetaDataFields.EndDate, fieldIdx);
                fieldIdx++;
                metaDataFieldsHashMap.put(MetaDataFields.EndTime, fieldIdx);
                fieldIdx++;
            }

            if (isIncludeTimeSeriesMetaData) {
                metaDataFieldsHashMap.put(MetaDataFields.TimeSeriesDate, fieldIdx);
                fieldIdx++;
                metaDataFieldsHashMap.put(MetaDataFields.TimeSeriesTime, fieldIdx);
                fieldIdx++;
            }
        }

        if (includeFileMetaData) {
            if (includeColumnBreaks) {
                metaDataFieldsHashMap.put(MetaDataFields.FileMetaDataBreak, fieldIdx);
                fieldIdx++;
            }
            metaDataFieldsHashMap.put(MetaDataFields.FileName, fieldIdx);
            fieldIdx++;
            metaDataFieldsHashMap.put(MetaDataFields.FileType, fieldIdx);
            fieldIdx++;
            metaDataFieldsHashMap.put(MetaDataFields.FileFormat, fieldIdx);
            fieldIdx++;
            metaDataFieldsHashMap.put(MetaDataFields.FileWidth, fieldIdx);
            fieldIdx++;
            metaDataFieldsHashMap.put(MetaDataFields.FileHeight, fieldIdx);
            fieldIdx++;
            metaDataFieldsHashMap.put(MetaDataFields.Sensor, fieldIdx);
            fieldIdx++;
            metaDataFieldsHashMap.put(MetaDataFields.Platform, fieldIdx);
            fieldIdx++;
            metaDataFieldsHashMap.put(MetaDataFields.Resolution, fieldIdx);
            fieldIdx++;
            metaDataFieldsHashMap.put(MetaDataFields.DayNight, fieldIdx);
            fieldIdx++;
            metaDataFieldsHashMap.put(MetaDataFields.Orbit, fieldIdx);
            fieldIdx++;
            metaDataFieldsHashMap.put(MetaDataFields.ProcessingVersion, fieldIdx);
            fieldIdx++;
            metaDataFieldsHashMap.put(MetaDataFields.Projection, fieldIdx);
            fieldIdx++;

        }

        if (includeProjectionParameters) {
            metaDataFieldsHashMap.put(MetaDataFields.ProjectionParameters, fieldIdx);
            fieldIdx++;
        }

    }

    if (statsSpreadsheet == null) {
        statsSpreadsheet = new Object[numStxRegions + 2][fieldIdx];
        // add 1 row to account for the header and 1 more empty row because JTable for some reason displays
        // only half of the last row when row count is large
    }

    String startDateString = "";
    String startTimeString = "";
    String endDateString = "";
    String endTimeString = "";

    if (includeTimeMetaData) {
        ProductData.UTC startDateTimeCorrected;
        ProductData.UTC endDateTimeCorrected;

        // correct time (invert start and end time if end time later than start time
        if (getProduct().getStartTime() != null && getProduct().getEndTime() != null) {
            if (getProduct().getStartTime().getMJD() <= getProduct().getEndTime().getMJD()) {

                startDateTimeCorrected = getProduct().getStartTime();
                endDateTimeCorrected = getProduct().getEndTime();
            } else {

                startDateTimeCorrected = getProduct().getEndTime();
                endDateTimeCorrected = getProduct().getStartTime();
            }

            if (startDateTimeCorrected != null) {
                String[] startDateTimeStringArray = startDateTimeCorrected.toString().split(" ");
                if (startDateTimeStringArray.length >= 2) {
                    startDateString = startDateTimeStringArray[0].trim();
                    startTimeString = startDateTimeStringArray[1].trim();
                }
            }

            if (endDateTimeCorrected != null) {
                String[] endDateTimeStringArray = endDateTimeCorrected.toString().split(" ");
                if (endDateTimeStringArray.length >= 2) {
                    endDateString = endDateTimeStringArray[0].trim();
                    endTimeString = endDateTimeStringArray[1].trim();
                }
            }
        }
    }

    String timeSeriesDate = "";
    String timeSeriesTime = "";
    if (isIncludeTimeSeriesMetaData) {
        String bandName = raster.getName();

        String productDateTime = convertBandNameToProductTime(bandName);

        if (productDateTime != null) {
            String[] endDateTimeStringArray = productDateTime.split(" ");
            if (endDateTimeStringArray.length >= 2) {
                timeSeriesDate = endDateTimeStringArray[0].trim();
                timeSeriesTime = endDateTimeStringArray[1].trim();
            }
        }
    }

    String maskName = "";
    String maskDescription = "";
    String maskExpression = "";
    if (regionalMask != null) {
        maskName = regionalMask.getName();
        maskDescription = regionalMask.getDescription();
        maskExpression = regionalMask.getImageConfig().getValue("expression");
    }

    String qualityMaskName = "";
    String qualityMaskDescription = "";
    String qualityMaskExpression = "";
    if (qualityMask != null) {
        qualityMaskName = qualityMask.getName();
        qualityMaskDescription = qualityMask.getDescription();
        qualityMaskExpression = qualityMask.getImageConfig().getValue("expression");
    }

    addFieldToSpreadsheet(row, PrimaryStatisticsFields.FileRefNum, getProduct().getRefNo());
    addFieldToSpreadsheet(row, PrimaryStatisticsFields.BandName, raster.getName());
    addFieldToSpreadsheet(row, PrimaryStatisticsFields.MaskName, maskName);
    addFieldToSpreadsheet(row, PrimaryStatisticsFields.QualityMaskName, qualityMaskName);

    addFieldToSpreadsheet(row, MetaDataFields.TimeMetaDataBreak, COLUMN_BREAK);
    addFieldToSpreadsheet(row, MetaDataFields.StartDate, startDateString);
    addFieldToSpreadsheet(row, MetaDataFields.StartTime, startTimeString);
    addFieldToSpreadsheet(row, MetaDataFields.EndDate, endDateString);
    addFieldToSpreadsheet(row, MetaDataFields.EndTime, endTimeString);

    addFieldToSpreadsheet(row, MetaDataFields.TimeSeriesDate, timeSeriesDate);
    addFieldToSpreadsheet(row, MetaDataFields.TimeSeriesTime, timeSeriesTime);

    addFieldToSpreadsheet(row, MetaDataFields.FileMetaDataBreak, COLUMN_BREAK);
    addFieldToSpreadsheet(row, MetaDataFields.FileName, getProduct().getName());
    addFieldToSpreadsheet(row, MetaDataFields.FileType, getProduct().getProductType());
    addFieldToSpreadsheet(row, MetaDataFields.FileWidth, getProduct().getSceneRasterWidth());
    addFieldToSpreadsheet(row, MetaDataFields.FileFormat, getProductFormatName(getProduct()));
    addFieldToSpreadsheet(row, MetaDataFields.FileHeight, getProduct().getSceneRasterHeight());
    addFieldToSpreadsheet(row, MetaDataFields.Sensor,
            ProductUtils.getMetaData(getProduct(), ProductUtils.METADATA_POSSIBLE_SENSOR_KEYS));
    addFieldToSpreadsheet(row, MetaDataFields.Platform,
            ProductUtils.getMetaData(getProduct(), ProductUtils.METADATA_POSSIBLE_PLATFORM_KEYS));
    addFieldToSpreadsheet(row, MetaDataFields.Resolution,
            ProductUtils.getMetaData(getProduct(), ProductUtils.METADATA_POSSIBLE_RESOLUTION_KEYS));
    addFieldToSpreadsheet(row, MetaDataFields.DayNight,
            ProductUtils.getMetaData(getProduct(), ProductUtils.METADATA_POSSIBLE_DAY_NIGHT_KEYS));
    addFieldToSpreadsheet(row, MetaDataFields.Orbit, ProductUtils.getMetaDataOrbit(getProduct()));
    addFieldToSpreadsheet(row, MetaDataFields.ProcessingVersion,
            ProductUtils.getMetaData(getProduct(), ProductUtils.METADATA_POSSIBLE_PROCESSING_VERSION_KEYS));

    // Determine projection
    String projection = "";
    String projectionParameters = "";
    GeoCoding geo = getProduct().getGeoCoding();
    // determine if using class CrsGeoCoding otherwise display class
    if (geo != null) {
        if (geo instanceof CrsGeoCoding) {
            projection = geo.getMapCRS().getName().toString() + "(obtained from CrsGeoCoding)";
            projectionParameters = geo.getMapCRS().toString().replaceAll("\n", " ").replaceAll(" ", "");
        } else if (geo.toString() != null) {
            String projectionFromMetaData = ProductUtils.getMetaData(getProduct(),
                    ProductUtils.METADATA_POSSIBLE_PROJECTION_KEYS);

            if (projectionFromMetaData != null && projectionFromMetaData.length() > 0) {
                projection = projectionFromMetaData + "(obtained from MetaData)";
            } else {
                projection = "unknown (" + geo.getClass().toString() + ")";
            }
        }
    }
    addFieldToSpreadsheet(row, MetaDataFields.Projection, projection);
    addFieldToSpreadsheet(row, MetaDataFields.ProjectionParameters, projectionParameters);

    addFieldToSpreadsheet(row, MetaDataFields.BandMetaDataBreak, COLUMN_BREAK);
    addFieldToSpreadsheet(row, MetaDataFields.BandName, raster.getName());
    addFieldToSpreadsheet(row, MetaDataFields.BandUnit, raster.getUnit());
    addFieldToSpreadsheet(row, MetaDataFields.BandValidExpression, raster.getValidPixelExpression());
    addFieldToSpreadsheet(row, MetaDataFields.BandDescription, raster.getDescription());

    addFieldToSpreadsheet(row, MetaDataFields.RegionalMaskMetaDataBreak, COLUMN_BREAK);
    addFieldToSpreadsheet(row, MetaDataFields.RegionalMaskName, maskName);
    addFieldToSpreadsheet(row, MetaDataFields.RegionalMaskDescription, maskDescription);
    addFieldToSpreadsheet(row, MetaDataFields.RegionalMaskExpression, maskExpression);

    addFieldToSpreadsheet(row, MetaDataFields.QualityMaskMetaDataBreak, COLUMN_BREAK);
    addFieldToSpreadsheet(row, MetaDataFields.QualityMaskName, qualityMaskName);
    addFieldToSpreadsheet(row, MetaDataFields.QualityMaskDescription, qualityMaskDescription);
    addFieldToSpreadsheet(row, MetaDataFields.QualityMaskExpression, qualityMaskExpression);

    // Add Header first time through
    if (row <= 1) {

        int k = stxFieldsStartIdx;
        for (int i = 0; i < tableData.length; i++) {
            Object value = tableData[i][0];

            if (k < statsSpreadsheet[0].length && k <= stxFieldsEndIdx) {
                statsSpreadsheet[0][k] = value;
                k++;
            }
        }

    }

    // account for header as added row
    if (row < statsSpreadsheet.length) {

        int k = stxFieldsStartIdx;
        for (int i = 0; i < tableData.length; i++) {
            Object value = tableData[i][1];

            if (k < statsSpreadsheet[row].length && k <= stxFieldsEndIdx) {
                statsSpreadsheet[row][k] = value;
                k++;
            }
        }

    }

    int numPlots = 0;
    if (statisticsCriteriaPanel.showPercentPlots()) {
        numPlots++;
    }

    if (statisticsCriteriaPanel.showHistogramPlots()) {
        numPlots++;
    }

    JPanel plotContainerPanel = null;

    if (numPlots > 0) {
        plotContainerPanel = new JPanel(new GridLayout(1, numPlots));

        if (statisticsCriteriaPanel.showHistogramPlots()) {
            plotContainerPanel.add(histogramPanel);
        }

        if (statisticsCriteriaPanel.showPercentPlots()) {
            plotContainerPanel.add(percentilePanel);
        }
    }

    TableModel tableModel = new DefaultTableModel(tableData, new String[] { "Name", "Value" }) {
        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return columnIndex == 0 ? String.class : Number.class;
        }

        @Override
        public boolean isCellEditable(int row, int column) {
            return false;
        }
    };

    final JTable table = new JTable(tableModel);
    table.setDefaultRenderer(Number.class, new DefaultTableCellRenderer() {
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                boolean hasFocus, int row, int column) {
            final Component label = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row,
                    column);
            if (value instanceof Float || value instanceof Double) {
                setHorizontalTextPosition(RIGHT);
                setText(getFormattedValue((Number) value));
            }
            return label;
        }

        private String getFormattedValue(Number value) {
            if (value.doubleValue() < 0.001 && value.doubleValue() > -0.001 && value.doubleValue() != 0.0) {
                return new DecimalFormat("0.####E0").format(value.doubleValue());
            }
            String format = "%." + Integer.toString(statisticsCriteriaPanel.decimalPlaces()) + "f";

            return String.format(format, value.doubleValue());
        }
    });
    table.addMouseListener(popupHandler);

    // TEST CODE generically preferred size of each column based on longest expected entry
    // fails a bit because decimal formatting is not captured
    // stub of code commented out in case we want to make it work
    // meanwhile longest entry is being used SEE below

    //        int column0Length = 0;
    //        int column1Length = 0;
    //        FontMetrics fm = table.getFontMetrics(table.getFont());
    //        for (int rowIndex = 0; rowIndex < table.getRowCount(); rowIndex++) {
    //            String test = table.getValueAt(rowIndex,0).toString();
    //            int currColumn0Length = fm.stringWidth(table.getValueAt(rowIndex,0).toString());
    //            if (currColumn0Length > column0Length) {
    //                column0Length = currColumn0Length;
    //            }
    //
    //            String test2 = table.getValueAt(rowIndex,1).toString();
    //            int currColumn1Length = fm.stringWidth(table.getValueAt(rowIndex,1).toString());
    //            if (currColumn1Length > column1Length) {
    //                column1Length = currColumn1Length;
    //            }
    //        }

    // Set preferred size of each column based on longest expected entry
    FontMetrics fm = table.getFontMetrics(table.getFont());
    TableColumn column = null;
    int col1PreferredWidth = -1;
    if (statisticsCriteriaPanel.isLogMode()) {
        col1PreferredWidth = fm.stringWidth("StandardDeviation(LogBinned):") + 10;
    } else {
        col1PreferredWidth = fm.stringWidth("StandardDeviation(Binned):") + 10;
    }

    // int col1PreferredWidth = fm.stringWidth("wwwwwwwwwwwwwwwwwwwwwwwwww");
    int col2PreferredWidth = fm.stringWidth("1234567890") + 10;
    int tablePreferredWidth = col1PreferredWidth + col2PreferredWidth;
    for (int i = 0; i < 2; i++) {
        column = table.getColumnModel().getColumn(i);
        if (i == 0) {
            column.setPreferredWidth(col1PreferredWidth);
            column.setMaxWidth(col1PreferredWidth);
        } else {
            column.setPreferredWidth(col2PreferredWidth);
        }
    }

    JPanel textContainerPanel = new JPanel(new BorderLayout(2, 2));
    //   textContainerPanel.setBackground(Color.WHITE);
    textContainerPanel.add(table, BorderLayout.CENTER);
    textContainerPanel.addMouseListener(popupHandler);

    JPanel statsPane = GridBagUtils.createPanel();
    GridBagConstraints gbc = GridBagUtils.createConstraints("");
    gbc.gridy = 0;
    gbc.fill = GridBagConstraints.BOTH;
    gbc.anchor = GridBagConstraints.NORTHWEST;
    gbc.weightx = 1;
    gbc.weighty = 1;

    Dimension dim = table.getPreferredSize();
    table.setPreferredSize(new Dimension(tablePreferredWidth, dim.height));
    statsPane.add(table, gbc);
    statsPane.setPreferredSize(new Dimension(tablePreferredWidth, dim.height));

    JPanel plotsPane = null;

    if (plotContainerPanel != null) {
        plotsPane = GridBagUtils.createPanel();
        plotsPane.setBackground(Color.WHITE);
        //    plotsPane.setBorder(UIUtils.createGroupBorder(" ")); /*I18N*/
        GridBagConstraints gbcPlots = GridBagUtils.createConstraints("");
        gbcPlots.gridy = 0;
        if (statisticsCriteriaPanel.exactPlotSize()) {
            gbcPlots.fill = GridBagConstraints.NONE;
        } else {
            gbcPlots.fill = GridBagConstraints.BOTH;
        }

        gbcPlots.anchor = GridBagConstraints.NORTHWEST;
        gbcPlots.weightx = 0.5;
        gbcPlots.weighty = 1;
        plotsPane.add(plotContainerPanel, gbcPlots);
    }

    JPanel mainPane = GridBagUtils.createPanel();
    mainPane.setBorder(UIUtils.createGroupBorder(getSubPanelTitle(regionalMask, qualityMask, raster))); /*I18N*/
    GridBagConstraints gbcMain = GridBagUtils.createConstraints("");
    gbcMain.gridx = 0;
    gbcMain.gridy = 0;
    gbcMain.anchor = GridBagConstraints.NORTHWEST;
    if (plotsPane != null) {
        gbcMain.fill = GridBagConstraints.VERTICAL;
        gbcMain.weightx = 0;
    } else {
        gbcMain.fill = GridBagConstraints.BOTH;
        gbcMain.weightx = 1;
    }

    if (statisticsCriteriaPanel.showStatsList()) {
        gbcMain.weighty = 1;
        mainPane.add(statsPane, gbcMain);
        gbcMain.gridx++;
    }

    gbcMain.weightx = 1;
    gbcMain.weighty = 1;
    gbcMain.fill = GridBagConstraints.BOTH;

    if (plotsPane != null) {
        mainPane.add(plotsPane, gbcMain);
    }

    return mainPane;
}