/* * Copyright (C) 2015 by Array Systems Computing Inc. http://www.array.ca * * 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.s1tbx.ocean.toolviews.polarview; import org.esa.s1tbx.ocean.toolviews.polarview.polarplot.Axis; import org.esa.s1tbx.ocean.toolviews.polarview.polarplot.ColourScale; import org.esa.s1tbx.ocean.toolviews.polarview.polarplot.PolarCanvas; import org.esa.s1tbx.ocean.toolviews.polarview.polarplot.PolarData; import org.esa.snap.core.datamodel.MetadataElement; import org.esa.snap.core.datamodel.Product; import org.esa.snap.engine_utilities.datamodel.AbstractMetadata; import org.esa.snap.rcp.SnapApp; import org.esa.snap.rcp.util.Dialogs; import javax.swing.*; import javax.swing.border.BevelBorder; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.io.File; /** * Polar plot panel */ public final class PolarView extends JPanel implements ActionListener, PopupMenuListener, MouseListener, MouseMotionListener { private Product product; private int currentRecord = 0; private static final String[] unitTypes = new String[]{"Real", "Imaginary", "Amplitude", "Intensity"}; private ControlPanel controlPanel; private PolarPanel polarPanel; private Component emptyPanel; private SpectraData.SpectraUnit spectraUnit; private SpectraData.WaveProductType waveProductType; private SpectraData spectraData; public static final Color colourTable[] = (new Color[]{ new Color(255, 255, 255), new Color(0, 0, 255), new Color(0, 255, 255), new Color(0, 255, 0), new Color(255, 255, 0), new Color(255, 0, 0) }); private static final double rings[] = {50.0, 100.0, 200.0}; private static final String ringTextStrings[] = {"200 m", "100 m", "50 m"}; private final static String LAST_WAVE_EXPORT_DIR_KEY = "snap.lastWaveExportDir"; public PolarView() { addMouseListener(this); addMouseMotionListener(this); this.setLayout(new BorderLayout()); waveProductType = null; spectraData = null; emptyPanel = createEmptyPanel(); this.add(emptyPanel, BorderLayout.NORTH); polarPanel = new PolarPanel(); this.add(polarPanel, BorderLayout.CENTER); controlPanel = new ControlPanel(this); this.add(controlPanel, BorderLayout.SOUTH); enablePlot(false); } private Component createEmptyPanel() { return new JLabel("<html>This tool window is used to analyse<br>" + "<b>Level-2 Ocean Swell</b> data in a polar plot.<br>" + "Please open and select a Sentinel-1 L2 OCN WV<br>" + "or an ASAR L2 WV product.", SwingConstants.CENTER); } private void enablePlot(final boolean flag) { emptyPanel.setVisible(!flag); polarPanel.setVisible(flag); controlPanel.setVisible(flag); } public void setProduct(final Product prod) { if (product == prod) { return; } this.product = prod; if (product == null) { enablePlot(false); return; } switch (product.getProductType()) { case "ASA_WVW_2P": if (spectraUnit == null) { spectraUnit = SpectraData.SpectraUnit.AMPLITUDE; } spectraData = new SpectraDataAsar(product, SpectraData.WaveProductType.WAVE_SPECTRA); break; case "ASA_WVS_1P": if (spectraUnit == null) { spectraUnit = SpectraData.SpectraUnit.INTENSITY; } spectraData = new SpectraDataAsar(product, SpectraData.WaveProductType.CROSS_SPECTRA); break; case "OCN": final MetadataElement absRoot = AbstractMetadata.getAbstractedMetadata(product); final String mode = absRoot.getAttributeString(AbstractMetadata.ACQUISITION_MODE); if (mode.equals("WV")) { if (spectraUnit == null) { spectraUnit = SpectraData.SpectraUnit.AMPLITUDE; } if (waveProductType == null) { waveProductType = SpectraData.WaveProductType.WAVE_SPECTRA; } spectraData = new SpectraDataSentinel1(product); spectraData.setWaveProductType(waveProductType); } else { enablePlot(false); return; } break; default: enablePlot(false); return; } if (waveProductType != null) { currentRecord = 0; // reset to 0 createPlot(currentRecord); } enablePlot(waveProductType != null); } public void removeProduct(final Product product) { if (this.product == product) { this.product = null; enablePlot(false); } } private void createPlot(final int rec) { try { final String[] readouts = spectraData.getSpectraMetadata(rec); polarPanel.setMetadata(readouts); final PolarCanvas polarCanvas = polarPanel.getPolarCanvas(); polarCanvas.setAxisNames("Azimuth", "Range"); if (!(spectraData instanceof SpectraDataAsar && spectraData.getWaveProductType() == SpectraData.WaveProductType.CROSS_SPECTRA)) { polarCanvas.setWindDirection(spectraData.getWindDirection()); polarCanvas.showWindDirection(true); polarCanvas.setAxisNames("North", "East"); } final PolarData data = spectraData.getPolarData(currentRecord, spectraUnit); final double colourRange[] = {(double) data.getMinValue(), (double) data.getMaxValue()}; final double radialRange[] = {spectraData.getMinRadius(), spectraData.getMaxRadius()}; final Axis colourAxis = polarCanvas.getColourAxis(); final Axis radialAxis = polarCanvas.getRadialAxis(); colourAxis.setDataRange(colourRange); colourAxis.setUnit(unitTypes[spectraUnit.ordinal()]); radialAxis.setAutoRange(false); radialAxis.setDataRange(radialRange); radialAxis.setRange(radialRange[0], radialRange[1], 4); radialAxis.setTitle("Wavelength (m)"); polarCanvas.setRings(rings, ringTextStrings); data.setColorScale(ColourScale.newCustomScale(colourRange)); polarCanvas.setData(data); repaint(); controlPanel.updateControls(); } catch (Exception e) { SnapApp.getDefault().handleError("Unable to read OSW data from product ", e); } } public JPopupMenu createPopupMenu(final MouseEvent event) { final JPopupMenu popup = new JPopupMenu(); final JMenuItem itemNext = createMenuItem("Next"); popup.add(itemNext); itemNext.setEnabled(currentRecord < spectraData.getNumRecords()); final JMenuItem itemPrev = createMenuItem("Previous"); popup.add(itemPrev); itemPrev.setEnabled(currentRecord > 0); final JMenuItem itemColourScale = createMenuItem("Colour Scale"); popup.add(itemColourScale); if (spectraData instanceof SpectraDataSentinel1) { final JMenu dataMenu = new JMenu("Data"); popup.add(dataMenu); createCheckedMenuItem("Wave Spectra", dataMenu, spectraData.getWaveProductType() == SpectraData.WaveProductType.WAVE_SPECTRA); createCheckedMenuItem("Cross Spectra", dataMenu, spectraData.getWaveProductType() == SpectraData.WaveProductType.CROSS_SPECTRA); } final JMenu unitMenu = new JMenu("Unit"); popup.add(unitMenu); if (spectraData.getWaveProductType() == SpectraData.WaveProductType.WAVE_SPECTRA) { createCheckedMenuItem(unitTypes[SpectraData.SpectraUnit.AMPLITUDE.ordinal()], unitMenu, spectraUnit == SpectraData.SpectraUnit.AMPLITUDE); createCheckedMenuItem(unitTypes[SpectraData.SpectraUnit.INTENSITY.ordinal()], unitMenu, spectraUnit == SpectraData.SpectraUnit.INTENSITY); } else { createCheckedMenuItem(unitTypes[SpectraData.SpectraUnit.REAL.ordinal()], unitMenu, spectraUnit == SpectraData.SpectraUnit.REAL); createCheckedMenuItem(unitTypes[SpectraData.SpectraUnit.IMAGINARY.ordinal()], unitMenu, spectraUnit == SpectraData.SpectraUnit.IMAGINARY); createCheckedMenuItem(unitTypes[SpectraData.SpectraUnit.AMPLITUDE.ordinal()], unitMenu, spectraUnit == SpectraData.SpectraUnit.AMPLITUDE); createCheckedMenuItem(unitTypes[SpectraData.SpectraUnit.INTENSITY.ordinal()], unitMenu, spectraUnit == SpectraData.SpectraUnit.INTENSITY); } final JMenuItem itemExportReadout = createMenuItem("Export Readouts"); popup.add(itemExportReadout); popup.setLabel("Justification"); popup.setBorder(new BevelBorder(BevelBorder.RAISED)); popup.addPopupMenuListener(this); popup.show(this, event.getX(), event.getY()); return popup; } private JMenuItem createMenuItem(final String name) { final JMenuItem item = new JMenuItem(name); item.setHorizontalTextPosition(JMenuItem.RIGHT); item.addActionListener(this); return item; } public JCheckBoxMenuItem createCheckedMenuItem(final String name, final JMenu parent, boolean state) { final JCheckBoxMenuItem item = new JCheckBoxMenuItem(name); item.setHorizontalTextPosition(JMenuItem.RIGHT); item.addActionListener(this); item.setState(state); parent.add(item); return item; } /** * Handles menu item pressed events * * @param event the action event */ public void actionPerformed(final ActionEvent event) { if (event.getActionCommand().equals("Next")) { showNextPlot(); } else if (event.getActionCommand().equals("Previous")) { showPreviousPlot(); } else if (event.getActionCommand().equals("Colour Scale")) { callColourScaleDlg(); } else if (event.getActionCommand().equals("Export Readouts")) { exportReadouts(); } else if (event.getActionCommand().equals("Real")) { spectraUnit = SpectraData.SpectraUnit.REAL; createPlot(currentRecord); } else if (event.getActionCommand().equals("Imaginary")) { spectraUnit = SpectraData.SpectraUnit.IMAGINARY; createPlot(currentRecord); } else if (event.getActionCommand().equals("Amplitude")) { spectraUnit = SpectraData.SpectraUnit.AMPLITUDE; createPlot(currentRecord); } else if (event.getActionCommand().equals("Intensity")) { spectraUnit = SpectraData.SpectraUnit.INTENSITY; createPlot(currentRecord); } else if (event.getActionCommand().equals("Wave Spectra")) { waveProductType = SpectraData.WaveProductType.WAVE_SPECTRA; spectraData.setWaveProductType(waveProductType); if (spectraUnit != SpectraData.SpectraUnit.AMPLITUDE && spectraUnit != SpectraData.SpectraUnit.INTENSITY) { spectraUnit = SpectraData.SpectraUnit.AMPLITUDE; } createPlot(currentRecord); } else if (event.getActionCommand().equals("Cross Spectra")) { waveProductType = SpectraData.WaveProductType.CROSS_SPECTRA; spectraData.setWaveProductType(waveProductType); createPlot(currentRecord); } } int getCurrentRecord() { return currentRecord; } int getNumRecords() { return spectraData != null ? spectraData.getNumRecords() : 0; } void showNextPlot() { createPlot(++currentRecord); } void showPreviousPlot() { createPlot(--currentRecord); } void showPlot(int record) { currentRecord = record; createPlot(currentRecord); } void zoomOut() { createPlot(currentRecord); } void zoomIn() { createPlot(currentRecord); } private void callColourScaleDlg() { final PolarCanvas polarCanvas = polarPanel.getPolarCanvas(); final ColourScaleDialog dlg = new ColourScaleDialog(polarCanvas.getColourAxis()); dlg.show(); } private void exportReadouts() { final File file = Dialogs.requestFileForSave("Export Wave Mode Readout", false, null, ".txt", product.getName() + "_rec" + currentRecord, null, LAST_WAVE_EXPORT_DIR_KEY); try { if (file != null) { polarPanel.exportReadout(file); } } catch (Exception e) { SnapApp.getDefault().handleError("Unable to export file " + file.toString() + ": " + e.getMessage(), e); } } private void checkPopup(final MouseEvent e) { if (e.isPopupTrigger()) { createPopupMenu(e); } } public void popupMenuWillBecomeVisible(final PopupMenuEvent e) { } public void popupMenuWillBecomeInvisible(final PopupMenuEvent e) { } public void popupMenuCanceled(final PopupMenuEvent e) { } /** * Handle mouse pressed event * * @param e the mouse event */ public void mousePressed(final MouseEvent e) { checkPopup(e); } /** * Handle mouse clicked event * * @param e the mouse event */ public void mouseClicked(final MouseEvent e) { checkPopup(e); final Object src = e.getSource(); final PolarCanvas polarCanvas = polarPanel.getPolarCanvas(); if (src == polarCanvas) { final Axis axis = polarCanvas.selectAxis(e.getPoint()); if (axis != null && axis == polarCanvas.getColourAxis()) { callColourScaleDlg(); } } } public void mouseEntered(final MouseEvent e) { } public void mouseExited(final MouseEvent e) { } public void mouseReleased(final MouseEvent e) { checkPopup(e); } public void mouseDragged(final MouseEvent e) { } /** * Handle mouse moved event * * @param e the mouse event */ public void mouseMoved(final MouseEvent e) { updateReadout(e); } private void updateReadout(final MouseEvent evt) { final double rTh[] = polarPanel.getPolarCanvas().getRTheta(evt.getPoint()); if (rTh != null) { final String[] readouts = spectraData.updateReadouts(rTh, currentRecord); polarPanel.setReadout(readouts); } else { polarPanel.setReadout(null); } repaint(); } }