/* * Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at your option) * any later version. * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see http://www.gnu.org/licenses/ */ package org.esa.beam.smos.visat; import org.esa.beam.dataio.smos.L1cScienceSmosFile; import org.esa.beam.dataio.smos.L1cSmosFile; import org.esa.beam.dataio.smos.SmosConstants; import org.esa.beam.dataio.smos.dddb.BandDescriptor; import org.esa.beam.dataio.smos.dddb.Dddb; import org.esa.beam.dataio.smos.dddb.Family; import org.esa.beam.dataio.smos.dddb.FlagDescriptor; import org.esa.beam.framework.ui.product.ProductSceneView; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.axis.SymbolAxis; import org.jfree.chart.labels.XYZToolTipGenerator; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.LookupPaintScale; import org.jfree.chart.renderer.xy.XYBlockRenderer; import org.jfree.data.xy.DefaultXYZDataset; import org.jfree.data.xy.XYDataset; import org.jfree.data.xy.XYZDataset; import org.jfree.ui.RectangleInsets; import javax.swing.JComponent; import java.awt.Color; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class GridPointBtDataFlagmatrixToolView extends GridPointBtDataToolView { public static final String ID = GridPointBtDataFlagmatrixToolView.class.getName(); private static final String SERIES_KEY = "Flags"; private static final String DEFAULT_FLAG_DESCRIPTOR_IDENTIFIER = "DBL_SM_XXXX_MIR_XXXF1C_0400_flags"; private JFreeChart chart; private DefaultXYZDataset dataset; private XYPlot plot; private ChartPanel chartPanel; private String[] flagNames; @Override protected JComponent createGridPointComponent() { dataset = new DefaultXYZDataset(); final NumberAxis xAxis = new NumberAxis("Record #"); xAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); xAxis.setAutoRangeIncludesZero(false); xAxis.setLowerMargin(0.0); xAxis.setUpperMargin(0.0); flagNames = createFlagNames(Dddb.getInstance().getFlagDescriptors(DEFAULT_FLAG_DESCRIPTOR_IDENTIFIER)); final NumberAxis yAxis = createRangeAxis(flagNames); final LookupPaintScale paintScale = new LookupPaintScale(0.0, 4.0, Color.WHITE); paintScale.add(0.0, Color.BLACK); paintScale.add(1.0, Color.RED); paintScale.add(2.0, Color.GREEN); paintScale.add(3.0, Color.BLUE); paintScale.add(4.0, Color.YELLOW); final XYBlockRenderer renderer = new XYBlockRenderer(); renderer.setPaintScale(paintScale); renderer.setBaseToolTipGenerator(new FlagToolTipGenerator(flagNames)); plot = new XYPlot(dataset, xAxis, yAxis, renderer); plot.setBackgroundPaint(Color.LIGHT_GRAY); plot.setDomainGridlinePaint(Color.WHITE); plot.setRangeGridlinePaint(Color.WHITE); plot.setForegroundAlpha(0.5f); plot.setAxisOffset(new RectangleInsets(5, 5, 5, 5)); plot.setNoDataMessage("No data"); chart = new JFreeChart(null, plot); chart.removeLegend(); chartPanel = new ChartPanel(chart); return chartPanel; } @Override protected void updateClientComponent(ProductSceneView smosView) { boolean enabled = smosView != null; L1cSmosFile smosFile = null; if (enabled) { smosFile = getL1cSmosFile(); if (canNotDisplayFile(smosFile)) { enabled = false; } } chartPanel.setEnabled(enabled); if (enabled) { final Family<BandDescriptor> bandDescriptors = Dddb.getInstance().getBandDescriptors( smosFile.getDataFormat().getName()); final BandDescriptor flagsBandDescriptor = bandDescriptors.getMember(SmosConstants.BT_FLAGS_NAME); final Family<FlagDescriptor> flagDescriptors = flagsBandDescriptor.getFlagDescriptors(); flagNames = createFlagNames(flagDescriptors); final NumberAxis rangeAxis = createRangeAxis(flagNames); plot.setRangeAxis(rangeAxis); } } static boolean canNotDisplayFile(L1cSmosFile smosFile) { return smosFile == null || ! (smosFile instanceof L1cScienceSmosFile); } @Override protected void updateGridPointBtDataComponent(GridPointBtDataset ds) { dataset.removeSeries(SERIES_KEY); int iq = ds.getColumnIndex(SmosConstants.BT_FLAGS_NAME); if (iq != -1) { final Number[][] dsData = ds.getData(); final int m = dsData.length; final int n = flagNames.length; double[][] data = new double[3][n * m]; for (int x = 0; x < m; x++) { final int flags = dsData[x][iq].intValue(); for (int y = 0; y < n; y++) { final int index = y * m + x; data[0][index] = (1 + x); data[1][index] = y; data[2][index] = ((flags & (1 << y)) != 0) ? (1 + y % 3) : 0.0; } } dataset.addSeries(SERIES_KEY, data); } else { plot.setNoDataMessage("Not a SMOS D1C/F1C pixel."); } chart.fireChartChanged(); } @Override protected void updateGridPointBtDataComponent(IOException e) { dataset.removeSeries(SERIES_KEY); plot.setNoDataMessage("I/O error"); } @Override protected void clearGridPointBtDataComponent() { dataset.removeSeries(SERIES_KEY); plot.setNoDataMessage("No data"); } private String[] createFlagNames(Family<FlagDescriptor> flagDescriptors) { final List<FlagDescriptor> flagDescriptorsList = flagDescriptors.asList(); final List<String> flagNames = new ArrayList<>(flagDescriptorsList.size()); for (final FlagDescriptor d : flagDescriptorsList) { flagNames.add(d.getFlagName()); } return flagNames.toArray(new String[flagNames.size()]); } private NumberAxis createRangeAxis(String[] flagNames) { final NumberAxis axis = new SymbolAxis(null, flagNames); axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits()); axis.setAutoRangeIncludesZero(false); axis.setLowerMargin(0.0); axis.setUpperMargin(0.0); axis.setInverted(true); return axis; } private class FlagToolTipGenerator implements XYZToolTipGenerator { private String[] flagNames; private FlagToolTipGenerator(String[] flagNames) { this.flagNames = flagNames; } @Override public String generateToolTip(XYDataset xyDataset, int series, int item) { return generateToolTip((XYZDataset) xyDataset, series, item); } @Override public String generateToolTip(XYZDataset xyzDataset, int series, int item) { int recordIndex = dataset.getX(series, item).intValue(); int flagIndex = dataset.getY(series, item).intValue(); boolean flagSet = dataset.getZ(series, item).intValue() != 0; String flagName = "?"; if (flagIndex >= 0 && flagIndex < flagNames.length) { flagName = flagNames[flagIndex]; } return flagName + "(" + recordIndex + "): " + (flagSet ? "ON" : "OFF"); } } }