From ceeec30d76f8049058e862f8943a2a42bfd3dfec Mon Sep 17 00:00:00 2001 From: tparker Date: Sat, 27 Feb 2016 21:37:39 -0900 Subject: [PATCH 01/67] Added coda marker and began Hyop71 adapter --- .../usgs/volcanoes/swarm/picker/Event.java | 16 +- .../volcanoes/swarm/picker/EventChannel.java | 16 +- .../volcanoes/swarm/picker/EventLocator.java | 5 + .../volcanoes/swarm/picker/PhasePopup.java | 12 +- .../volcanoes/swarm/picker/PickListPanel.java | 21 +- .../swarm/picker/PickerWavePanel.java | 47 ++- .../swarm/picker/hypo71/Hypo71Adapter.java | 315 ++++++++++++++++++ 7 files changed, 421 insertions(+), 11 deletions(-) create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/picker/EventLocator.java create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Adapter.java diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/Event.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/Event.java index 8655619d..58c4de2a 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/Event.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/Event.java @@ -38,7 +38,7 @@ public void clearPhase(String channel, Phase.PhaseType type) { if (eChan.isEmpty()) { channels.remove(channel); } - notifyObservers(); + notifyObservers(); } } @@ -69,8 +69,20 @@ public void remove(String channel) { channels.remove(channel); notifyObservers(); } - + public boolean isEmpty() { return channels.isEmpty(); } + + public void setCoda(String channel, long time) { + EventChannel eChan = channels.get(channel); + if (eChan != null) { + eChan.setCoda(time); + } + } + + public long coda(String channel) { + EventChannel eChan = channels.get(channel); + return eChan.getCodaTime(); + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/EventChannel.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/EventChannel.java index 2d1d8b6e..f898f171 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/EventChannel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/EventChannel.java @@ -7,7 +7,8 @@ public class EventChannel { private final static Logger LOGGER = LoggerFactory.getLogger(EventChannel.class); private Phase pPhase; private Phase sPhase; - + private long codaTime; + private int maxAmplitude; private long duration; @@ -23,11 +24,12 @@ public void setPhase(Phase phase) { throw new RuntimeException("Unknown phase type."); } } - + public void clearPhase(Phase.PhaseType type) { switch (type) { case P: pPhase = null; + codaTime = 0; break; case S: sPhase = null; @@ -36,7 +38,7 @@ public void clearPhase(Phase.PhaseType type) { throw new RuntimeException("Unknown phase type."); } } - + public Phase getPhase(Phase.PhaseType type) { switch (type) { case P: @@ -51,4 +53,12 @@ public Phase getPhase(Phase.PhaseType type) { public boolean isEmpty() { return pPhase == null && sPhase == null; } + + public void setCoda(long time) { + codaTime = time; + } + + public long getCodaTime() { + return codaTime; + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/EventLocator.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/EventLocator.java new file mode 100644 index 00000000..4811bcda --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/EventLocator.java @@ -0,0 +1,5 @@ +package gov.usgs.volcanoes.swarm.picker; + +public interface EventLocator { + +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/PhasePopup.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/PhasePopup.java index 7ebfef31..3bd03e73 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/PhasePopup.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/PhasePopup.java @@ -146,7 +146,17 @@ public void actionPerformed(ActionEvent e) { } }); s.add(clearS); - + + JMenuItem coda = new JMenuItem("Coda"); + coda.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + event.setCoda(channel, time); + parent.validate(); + parent.repaint(); + } + }); + add(coda); + JMenuItem clearAll = new JMenuItem("Clear"); clearAll.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickListPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickListPanel.java index bdf40936..57bfb2fa 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickListPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickListPanel.java @@ -109,13 +109,18 @@ private void writeList(JPanel pickList) { phase = eventChannel.getPhase(Phase.PhaseType.P); if (phase != null) { writePhase(pickList, chan, phase, c); + long coda = eventChannel.getCodaTime(); + if (coda > 0) { + writeCoda(pickList, chan, coda, c); + + } } phase = eventChannel.getPhase(Phase.PhaseType.S); if (phase != null) { writePhase(pickList, chan, phase, c); } - } + } c.weighty = 1; c.gridy++; @@ -124,6 +129,20 @@ private void writeList(JPanel pickList) { pickList.add(filler, c); } + private void writeCoda(JPanel pickList, String channel, long coda, GridBagConstraints c) { + boolean isSelected = selected.contains(channel); + c.gridy++; + + String time = Time.toDateString(coda); + pickList.add(getLabel(time, isSelected), c); + + String phaseT = "C"; + pickList.add(getLabel(phaseT, isSelected), c); + + pickList.add(getLabel(channel, isSelected), c); + + } + public void writePhase(final JPanel pickList, final String channel, final Phase phase, final GridBagConstraints c) { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java index e4941c63..3e3ac9d6 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java @@ -22,7 +22,7 @@ public class PickerWavePanel extends AbstractWavePanel implements EventObserver private static final Font ANNOTATION_FONT = new Font("Monospaced", Font.BOLD, 12); private static final Color P_BACKGROUND = new Color(128, 255, 128, 192); private static final Color S_BACKGROUND = new Color(128, 128, 255, 192); - + private static final Color CODA_BACKGROUND = new Color(128, 128, 128, 192); private Event event; private Component parent; @@ -54,12 +54,51 @@ protected void annotateImage(Graphics2D g2) { for (Phase.PhaseType type : Phase.PhaseType.values()) { Phase phase = event.getPhase(channel, type); if (phase != null) { - markPhase(g2, phase); + Color background; + if (phase.phaseType == Phase.PhaseType.P) { + markPhase(g2, P_BACKGROUND, phase.time, phase.tag()); + long time = event.coda(channel); + if (time > 0) { + markPhase(g2, CODA_BACKGROUND, event.coda(channel), "C"); + } + } else { + markPhase(g2, S_BACKGROUND, phase.time, phase.tag()); + } } } // repaint(); } + private void markPhase(Graphics2D g2, Color backgroundColor, long time, String tag) { + double j2k = J2kSec.fromEpoch(time); + double[] t = getTranslation(); + if (t == null) + return; + + double x = 2 + (j2k - t[1]) / t[0]; + g2.setColor(DARK_GREEN); + g2.draw(new Line2D.Double(x, yOffset, x, getHeight() - bottomHeight - 1)); + + Font oldFont = g2.getFont(); + g2.setFont(ANNOTATION_FONT); + + FontMetrics fm = g2.getFontMetrics(); + int width = fm.stringWidth(tag); + int height = fm.getAscent(); + + int offset = 2; + int lw = width + 2 * offset; + + g2.setColor(backgroundColor); + + g2.fillRect((int) x, 3, lw, height + 2 * offset); + g2.setColor(Color.black); + g2.drawRect((int) x, 3, lw, height + 2 * offset); + + g2.drawString(tag, (int) x + offset, 3 + (fm.getAscent() + offset)); + g2.setFont(oldFont); + } + private void markPhase(Graphics2D g2, Phase phase) { double j2k = J2kSec.fromEpoch(phase.time); double[] t = getTranslation(); @@ -81,10 +120,10 @@ private void markPhase(Graphics2D g2, Phase phase) { int offset = 2; int lw = width + 2 * offset; - Color background; + Color background = null; if (phase.phaseType == Phase.PhaseType.P) { background = P_BACKGROUND; - } else { + } else if (phase.phaseType == Phase.PhaseType.S) { background = S_BACKGROUND; } g2.setColor(background); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Adapter.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Adapter.java new file mode 100644 index 00000000..7d3ed7db --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Adapter.java @@ -0,0 +1,315 @@ +package gov.usgs.volcanoes.swarm.picker.hypo71; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.text.ParseException; +import java.util.Calendar; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +import javax.swing.JOptionPane; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.Marker; + +import gov.usgs.volcanoes.core.Hypo71.ControlCard; +import gov.usgs.volcanoes.core.Hypo71.CrustalModel; +import gov.usgs.volcanoes.core.Hypo71.Hypo71; +import gov.usgs.volcanoes.core.Hypo71.Hypo71.Results; +import gov.usgs.volcanoes.core.Hypo71.HypoArchiveOutput; +import gov.usgs.volcanoes.core.Hypo71.Hypocenter; +import gov.usgs.volcanoes.core.Hypo71.PhaseRecord; +import gov.usgs.volcanoes.core.Hypo71.Station; +import gov.usgs.volcanoes.swarm.Metadata; +import gov.usgs.volcanoes.swarm.Swarm; +import gov.usgs.volcanoes.swarm.SwarmConfig; +import gov.usgs.volcanoes.swarm.picker.Event; +import gov.usgs.volcanoes.swarm.picker.EventLocator; + +public class Hypo71Adapter implements EventLocator { + + private static final Logger LOGGER = LoggerFactory.getLogger(Hypo71Adapter.class); + private ControlCard controlCard; + private Queue phaseRecordsList; + private Queue stationsList; + private Queue crustalModelList; + + public Hypo71Adapter() { + + + // defaults taken from hypo-test-case-1.properties + controlCard = + new ControlCard(0, 5.0, 50.0, 100.0, 1.78, 2, 1, 18, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0); + + crustalModelList = new LinkedList(); + crustalModelList.add(new CrustalModel(3.3, 0.0)); + crustalModelList.add(new CrustalModel(5.0, 1.0)); + crustalModelList.add(new CrustalModel(5.7, 4.0)); + crustalModelList.add(new CrustalModel(6.7, 15.0)); + crustalModelList.add(new CrustalModel(8.0, 25.0)); + + } + + private void runHypo(Event event) throws IOException { + + Hypo71 hypoCalculator = new Hypo71(); + + HypoArchiveOutput hy = new HypoArchiveOutput(); + hy.setControlCard(controlCard); + for (PhaseRecord o : phaseRecordsList) { + hy.getPhaseRecords().add(o); + } + + for (Station o : stationsList) { + hy.getStations().add(o); + } + + for (CrustalModel o : crustalModelList) { + hy.getCrustalModel().add(o); + } + + try { + hypoCalculator.calculateHypo71("", null, stationsList, crustalModelList, controlCard, + phaseRecordsList, null); + } catch (ParseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + Results result = hypoCalculator.getResults(); + + } + + public void locate(Event event) { + String error = null; + try { + generateHypoInputs(event); + } catch (Exception ex) { + ex.printStackTrace(); + error = "Cannot run hypo please ensure input file has correct data"; + } + + if (error == null) { + try { + Results hypoResult = null; + hypoResult = runHypo(); + + HypoResults hr = new HypoResults(); + hr.setAdjustmentsOutput(hypoResult.getAdjustmentIterations()); + hr.setDeletedStationsList(hypoResult.getDeletedStationsList()); + hr.setHypocenterOuput(hypoResult.getHypocenterOutput()); + hr.setMissingStationsList(hypoResult.getMissingStationsList()); + hr.setPrintOutput(hypoResult.getPrintOutput()); + hr.setPunchOutput(hypoResult.getPunchOutput()); + hr.setStationsResultList(hypoResult.getStationsResultList()); + hr.setStats(hypoResult.getStats()); + hr.setSummaryList(hypoResult.getSummaryList()); + + if (hr.getHypocenterOuput() != null && hr.getHypocenterOuput().size() > 0) { + + List centers = hr.getHypocenterOuput(); + if (centers.size() > 0) { + Swarm.getSelectedAttempt().setLatitude((double) centers.get(0).getLAT1()); + Swarm.getSelectedAttempt().setLongitude((double) centers.get(0).getLON1()); + Swarm.getSelectedAttempt().setDepth(centers.get(0).getZ()); + + } + } + + if (Swarm.getSelectedAttempt() != null) { + Swarm.getSelectedAttempt().setHypoResultsAsBytes(hr); + if (archiveCheck.isSelected()) { + Swarm.getSelectedAttempt().setHypoInputArchiveFilePath(hypoTotalInputPath.getText()); + } + Swarm.getSelectedAttempt().persist(); + } + + if (Swarm.getApplication().getHypoOuputMapFrame() == null) { + Swarm.getApplication().setHypoOuputMapFrame(new HypoOuputMapFrame()); + } + + Swarm.getApplication().getHypoOuputMapFrame().setHy(hy); + Swarm.getApplication().getHypoOuputMapFrame().setHypoOutput(hypoTotalInputPath.getText()); + Swarm.getApplication().getHypoOuputMapFrame().setResultText(hypoResult.getOutput()); + Swarm.getApplication().getHypoOuputMapFrame().setVisible(true); + + } catch (Exception e1) { + e1.printStackTrace(); + JOptionPane.showMessageDialog(null, + "Cannot run hypo, please verify hypo has all neccessary inputs: " + e1.getMessage(), + "Error", JOptionPane.ERROR_MESSAGE); + } + + } else { + JOptionPane.showMessageDialog(null, error, "Error", JOptionPane.ERROR_MESSAGE); + } + + } + + /** + * Generates hypo inputs either from an archived file or from objects in memory + */ + private void generateHypoInputs(Event event) { + + for (String channel : event.getChannels().keySet()) { + String station = channel.split(" ")[0]; + if (stationsList.contains(channel)) { + continue; + } else { + Metadata metadata = SwarmConfig.getInstance().getMetadata(channel); + if (metadata != null) { + stationsList.add(createStation(metadata)); + } else { + LOGGER.error("Skipping {}, no metadata found.", channel); + } + } + + phaseRecordsList.clear(); + + + for (String st : stations) { + List pmarkers = Marker.listByStationAndTypeAndAttempt( + Swarm.getSelectedAttempt().getId(), st, Marker.P_MARKER_LABEL); + + List smarkers = Marker.listByStationAndTypeAndAttempt( + Swarm.getSelectedAttempt().getId(), st, Marker.S_MARKER_LABEL); + + List codaMarkers = Marker.listByStationAndTypeAndAttempt( + Swarm.getSelectedAttempt().getId(), st, Marker.CODA_MARKER_LABEL); + + if (pmarkers.size() == 0 && smarkers.size() == 0) { + System.out.println("WARNING: Marker (p or s) not found for station " + st + " using file " + + hypoInputPath.getText() + ". Skipping this station."); + continue; + } + + if (codaMarkers.size() > 0 && pmarkers.size() == 0) { + throw new Exception( + "Must have a p marker with coda marker. No p marker found for coda marker for station: " + + st + " using file " + hypoInputPath.getText()); + } + + String prmk = null; + float pkDate = 0f; + int pHour = 0; + int pMin = 0; + float pSec = 0f; + + String smrk = null; + float sSec = 0f; + + float timeDiffFromCodaToPInSec = 0; + + if (pmarkers.size() > 0) { + Marker pMarker = pmarkers.get(0); + prmk = pMarker.getIp_ep() + + (pMarker.getUpDownUnknown().equals("Up") ? "U" + : (pMarker.getUpDownUnknown().equals("Down") ? "D" : "")) + + (pMarker.getWeight() == null ? "0" : pMarker.getWeight().toString()); + Calendar c = Calendar.getInstance(); + c.setTimeInMillis(pMarker.getMarkerTime().getTime()); + int pmonth = c.get(Calendar.MONTH); + int pyear = c.get(Calendar.YEAR); + int pday = c.get(Calendar.DAY_OF_MONTH); + pHour = c.get(Calendar.HOUR_OF_DAY); + pMin = c.get(Calendar.MINUTE); + pSec = c.get(Calendar.SECOND) + c.get(Calendar.MILLISECOND) / 1000f; + + pkDate = Float.parseFloat(Integer.toString(pyear - 1900) + + (pmonth < 10 ? "0" + Integer.toString(pmonth) : Integer.toString(pmonth)) + + (pday < 10 ? "0" + Integer.toString(pday) : Integer.toString(pday))); + + if (codaMarkers.size() > 0) { + Marker codaMarker = codaMarkers.get(0); + long codaMarkerTime = codaMarker.getMarkerTime().getTime(); + long pMarkerTime = pMarker.getMarkerTime().getTime(); + long timeDiffFromCodaToP = Math.abs(codaMarkerTime - pMarkerTime); + timeDiffFromCodaToPInSec = timeDiffFromCodaToP / 1000; + } + } + + if (smarkers.size() > 0) { + Marker sMarker = smarkers.get(0); + Calendar c = Calendar.getInstance(); + c.setTimeInMillis(sMarker.getMarkerTime().getTime()); + + smrk = sMarker.getIs_es() + sMarker.getUpDownUnknown() + + (sMarker.getWeight() == null ? "0" : sMarker.getWeight().toString()); + + sSec = c.get(Calendar.SECOND) + c.get(Calendar.MILLISECOND) / 1000f; + } + + phaseRecordsList + .add( + new PhaseRecord(st, prmk, // PRMK + (prmk != null && prmk.length() > 3) ? Float.parseFloat(prmk.substring(3, 4)) + : 0, + (int) pkDate, pMin, pSec, sSec, smrk, // SMRK + 0.0f, // WS + 0.0f, // AMX TODO: calc this + 0.0f, // PRX + 0.0f, // CALC + 0.0f, // CALX + "", // RMK + 0.0f, // DT + timeDiffFromCodaToPInSec, // FMP + "", // "1.22", + 'D', smrk != null ? "1" : "", "", // "SR01IPD0 691005120651.22", + ' ', "" // "IPD0" + )); + } + } + PhaseRecord lastRecordIndicator = new PhaseRecord(); + lastRecordIndicator.setMSTA(""); + phaseRecordsList.add(lastRecordIndicator); + } + + private Station createStation(Metadata metadata) { + Station station = new Station(); + + String stationName = metadata.getChannel().split(" |$")[0]; + if (stationName.length() > 4) { + stationName = stationName.substring(0, 4); + } + station.setNSTA(stationName); + + double lat = metadata.getLatitude(); + char ins = (lat < 0) ? 'S' : 'N'; + lat = Math.abs(lat); + int latDegree = (int) Math.abs(lat); + double latMin = (lat - latDegree) * 60; + + station.setLAT1(latDegree); + station.setLAT2(latMin); + station.setINS(ins); + + double lon = metadata.getLongitude(); + char iew = (lon < 0) ? 'W' : 'E'; + lon = Math.abs(lon); + int lonDegree = (int) lon; + double lonMin = (lon - lonDegree) * 60; + + station.setLON1(lonDegree); + station.setLON2(lonMin); + station.setIEW(iew); + + // TODO: add elevation to winston + station.setIELV(0); + + // TODO: station delay needed? + station.setDly(0); + + // TODO: station correction for FMEG needed? + station.setFMGC(0); + + // TODO: station correction for XMEG needed? + station.setXMGC(0); + + // TODO: System number? + station.setKLAS(8); + + return station; + } + +} From 85c2b07a161b3542b37655645456d2038547ef8a Mon Sep 17 00:00:00 2001 From: tparker Date: Mon, 29 Feb 2016 08:35:30 -0900 Subject: [PATCH 02/67] hypo in progress... --- .../java/gov/usgs/volcanoes/swarm/Icons.java | 1 + .../volcanoes/swarm/picker/EventLocator.java | 4 +- .../volcanoes/swarm/picker/PickerFrame.java | 18 +- .../swarm/picker/hypo71/Hypo71Adapter.java | 223 ++++++------------ .../swarm/picker/hypo71/HypoResults.java | 86 +++++++ 5 files changed, 167 insertions(+), 165 deletions(-) create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/HypoResults.java diff --git a/src/main/java/gov/usgs/volcanoes/swarm/Icons.java b/src/main/java/gov/usgs/volcanoes/swarm/Icons.java index 796d25bc..b29ba831 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/Icons.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/Icons.java @@ -87,6 +87,7 @@ public class Icons { public static final ImageIcon rsam_values = getIcon("images/rsam_values.png"); public static final ImageIcon rsam_counts = getIcon("images/rsam_counts.png"); public static final ImageIcon particle_motion = getIcon("images/bee.png"); + public static final ImageIcon locate = getIcon("images/bee.png"); private static ImageIcon getIcon(String key) { return new ImageIcon(ClassLoader.getSystemResource(key)); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/EventLocator.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/EventLocator.java index 4811bcda..f2e94d85 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/EventLocator.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/EventLocator.java @@ -1,5 +1,7 @@ package gov.usgs.volcanoes.swarm.picker; -public interface EventLocator { +import java.io.IOException; +public interface EventLocator { + public void locate(Event event) throws IOException; } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java index 1de7a623..cd0b24c4 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java @@ -34,10 +34,8 @@ import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.ButtonGroup; -import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFileChooser; -import javax.swing.JInternalFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; @@ -77,8 +75,7 @@ import gov.usgs.volcanoes.swarm.chooser.DataChooser; import gov.usgs.volcanoes.swarm.data.CachedDataSource; import gov.usgs.volcanoes.swarm.data.SeismicDataSource; -import gov.usgs.volcanoes.swarm.internalFrame.InternalFrameListener; -import gov.usgs.volcanoes.swarm.internalFrame.SwarmInternalFrames; +import gov.usgs.volcanoes.swarm.picker.hypo71.Hypo71Adapter; import gov.usgs.volcanoes.swarm.time.TimeListener; import gov.usgs.volcanoes.swarm.time.WaveViewTime; import gov.usgs.volcanoes.swarm.wave.AbstractWavePanel; @@ -111,7 +108,7 @@ public class PickerFrame extends SwarmFrame implements EventObserver { private JButton saveButton; private JButton captureButton; private JButton histButton; - private JButton particleMotionButton; + private JButton locateButton; private final DateFormat saveAllDateFormat; @@ -413,10 +410,15 @@ public void actionPerformed(final ActionEvent e) { UiUtils.mapKeyStrokeToButton(this, "DELETE", "remove", removeButton); toolbar.add(removeButton); - particleMotionButton = SwarmUtil.createToolBarButton(Icons.particle_motion, "Particle Motion", + locateButton = SwarmUtil.createToolBarButton(Icons.locate, "Locate", new ActionListener() { public void actionPerformed(final ActionEvent e) { - particleMotionPlot(); + EventLocator locator = new Hypo71Adapter(); + try { + locator.locate(event); + } catch (IOException e1) { + e1.printStackTrace(); + }; } private void particleMotionPlot() { @@ -424,7 +426,7 @@ private void particleMotionPlot() { } }); - toolbar.add(particleMotionButton); + toolbar.add(locateButton); toolbar.add(Box.createHorizontalGlue()); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Adapter.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Adapter.java index 7d3ed7db..cda77b00 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Adapter.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Adapter.java @@ -1,18 +1,17 @@ package gov.usgs.volcanoes.swarm.picker.hypo71; -import java.io.FileNotFoundException; import java.io.IOException; import java.text.ParseException; -import java.util.Calendar; +import java.text.SimpleDateFormat; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Queue; import javax.swing.JOptionPane; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.slf4j.Marker; import gov.usgs.volcanoes.core.Hypo71.ControlCard; import gov.usgs.volcanoes.core.Hypo71.CrustalModel; @@ -26,7 +25,9 @@ import gov.usgs.volcanoes.swarm.Swarm; import gov.usgs.volcanoes.swarm.SwarmConfig; import gov.usgs.volcanoes.swarm.picker.Event; +import gov.usgs.volcanoes.swarm.picker.EventChannel; import gov.usgs.volcanoes.swarm.picker.EventLocator; +import gov.usgs.volcanoes.swarm.picker.Phase; public class Hypo71Adapter implements EventLocator { @@ -35,6 +36,7 @@ public class Hypo71Adapter implements EventLocator { private Queue phaseRecordsList; private Queue stationsList; private Queue crustalModelList; + private SimpleDateFormat jtimeFormat; public Hypo71Adapter() { @@ -50,9 +52,28 @@ public Hypo71Adapter() { crustalModelList.add(new CrustalModel(6.7, 15.0)); crustalModelList.add(new CrustalModel(8.0, 25.0)); + jtimeFormat = new SimpleDateFormat("yyMMddHH"); + + stationsList = new LinkedList(); + phaseRecordsList = new LinkedList(); } - private void runHypo(Event event) throws IOException { + public void locate(Event event) throws IOException { + String error = null; + try { + generateHypoInputs(event); + } catch (Exception ex) { + ex.printStackTrace(); + error = "Cannot run hypo please ensure input file has correct data"; + } + + if (error == null) { + Results hypoResult = runHypo(event); + LOGGER.debug(hypoResult.getPrintOutput()); + } + } + + private Results runHypo(Event event) throws IOException { Hypo71 hypoCalculator = new Hypo71(); @@ -78,74 +99,10 @@ private void runHypo(Event event) throws IOException { e.printStackTrace(); } Results result = hypoCalculator.getResults(); + return result; } - public void locate(Event event) { - String error = null; - try { - generateHypoInputs(event); - } catch (Exception ex) { - ex.printStackTrace(); - error = "Cannot run hypo please ensure input file has correct data"; - } - - if (error == null) { - try { - Results hypoResult = null; - hypoResult = runHypo(); - - HypoResults hr = new HypoResults(); - hr.setAdjustmentsOutput(hypoResult.getAdjustmentIterations()); - hr.setDeletedStationsList(hypoResult.getDeletedStationsList()); - hr.setHypocenterOuput(hypoResult.getHypocenterOutput()); - hr.setMissingStationsList(hypoResult.getMissingStationsList()); - hr.setPrintOutput(hypoResult.getPrintOutput()); - hr.setPunchOutput(hypoResult.getPunchOutput()); - hr.setStationsResultList(hypoResult.getStationsResultList()); - hr.setStats(hypoResult.getStats()); - hr.setSummaryList(hypoResult.getSummaryList()); - - if (hr.getHypocenterOuput() != null && hr.getHypocenterOuput().size() > 0) { - - List centers = hr.getHypocenterOuput(); - if (centers.size() > 0) { - Swarm.getSelectedAttempt().setLatitude((double) centers.get(0).getLAT1()); - Swarm.getSelectedAttempt().setLongitude((double) centers.get(0).getLON1()); - Swarm.getSelectedAttempt().setDepth(centers.get(0).getZ()); - - } - } - - if (Swarm.getSelectedAttempt() != null) { - Swarm.getSelectedAttempt().setHypoResultsAsBytes(hr); - if (archiveCheck.isSelected()) { - Swarm.getSelectedAttempt().setHypoInputArchiveFilePath(hypoTotalInputPath.getText()); - } - Swarm.getSelectedAttempt().persist(); - } - - if (Swarm.getApplication().getHypoOuputMapFrame() == null) { - Swarm.getApplication().setHypoOuputMapFrame(new HypoOuputMapFrame()); - } - - Swarm.getApplication().getHypoOuputMapFrame().setHy(hy); - Swarm.getApplication().getHypoOuputMapFrame().setHypoOutput(hypoTotalInputPath.getText()); - Swarm.getApplication().getHypoOuputMapFrame().setResultText(hypoResult.getOutput()); - Swarm.getApplication().getHypoOuputMapFrame().setVisible(true); - - } catch (Exception e1) { - e1.printStackTrace(); - JOptionPane.showMessageDialog(null, - "Cannot run hypo, please verify hypo has all neccessary inputs: " + e1.getMessage(), - "Error", JOptionPane.ERROR_MESSAGE); - } - - } else { - JOptionPane.showMessageDialog(null, error, "Error", JOptionPane.ERROR_MESSAGE); - } - - } /** * Generates hypo inputs either from an archived file or from objects in memory @@ -164,102 +121,56 @@ private void generateHypoInputs(Event event) { LOGGER.error("Skipping {}, no metadata found.", channel); } } + } - phaseRecordsList.clear(); - - - for (String st : stations) { - List pmarkers = Marker.listByStationAndTypeAndAttempt( - Swarm.getSelectedAttempt().getId(), st, Marker.P_MARKER_LABEL); - - List smarkers = Marker.listByStationAndTypeAndAttempt( - Swarm.getSelectedAttempt().getId(), st, Marker.S_MARKER_LABEL); - - List codaMarkers = Marker.listByStationAndTypeAndAttempt( - Swarm.getSelectedAttempt().getId(), st, Marker.CODA_MARKER_LABEL); + phaseRecordsList.clear(); + Map eChans = event.getChannels(); + for (String chan : eChans.keySet()) { + EventChannel eChan = eChans.get(chan); + PhaseRecord phaseRecord = new PhaseRecord(); + phaseRecord.setMSTA(chan.split(" ")[0]); + + Phase pPhase = eChan.getPhase(Phase.PhaseType.P); + float pSec = 0; + if (pPhase != null) { + String prmk = pPhase.onset + "P" + pPhase.firstMotion + pPhase.weight; + phaseRecord.setPRMK(prmk); + long time = pPhase.time; + phaseRecord.setJTIME(Integer.parseInt(jtimeFormat.format(time))); + int min = (int) ((time / 1000) / 60) % 60; + phaseRecord.setJMIN(min); + + pSec = ((time / 1000) % 60) + ((time % 1000) / 1000f); + phaseRecord.setP(pSec); + } - if (pmarkers.size() == 0 && smarkers.size() == 0) { - System.out.println("WARNING: Marker (p or s) not found for station " + st + " using file " - + hypoInputPath.getText() + ". Skipping this station."); - continue; - } + Phase sPhase = eChan.getPhase(Phase.PhaseType.S); + if (sPhase != null) { + String srmk = sPhase.onset + "S" + sPhase.firstMotion + sPhase.weight; + phaseRecord.setSRMK(srmk); + long time = sPhase.time; - if (codaMarkers.size() > 0 && pmarkers.size() == 0) { - throw new Exception( - "Must have a p marker with coda marker. No p marker found for coda marker for station: " - + st + " using file " + hypoInputPath.getText()); + float sSec = ((time / 1000) % 60) + ((time % 1000) / 1000f); + if (sSec < pSec) { + sSec += 60; } + phaseRecord.setS(sSec); - String prmk = null; - float pkDate = 0f; - int pHour = 0; - int pMin = 0; - float pSec = 0f; - - String smrk = null; - float sSec = 0f; - - float timeDiffFromCodaToPInSec = 0; - - if (pmarkers.size() > 0) { - Marker pMarker = pmarkers.get(0); - prmk = pMarker.getIp_ep() - + (pMarker.getUpDownUnknown().equals("Up") ? "U" - : (pMarker.getUpDownUnknown().equals("Down") ? "D" : "")) - + (pMarker.getWeight() == null ? "0" : pMarker.getWeight().toString()); - Calendar c = Calendar.getInstance(); - c.setTimeInMillis(pMarker.getMarkerTime().getTime()); - int pmonth = c.get(Calendar.MONTH); - int pyear = c.get(Calendar.YEAR); - int pday = c.get(Calendar.DAY_OF_MONTH); - pHour = c.get(Calendar.HOUR_OF_DAY); - pMin = c.get(Calendar.MINUTE); - pSec = c.get(Calendar.SECOND) + c.get(Calendar.MILLISECOND) / 1000f; - - pkDate = Float.parseFloat(Integer.toString(pyear - 1900) - + (pmonth < 10 ? "0" + Integer.toString(pmonth) : Integer.toString(pmonth)) - + (pday < 10 ? "0" + Integer.toString(pday) : Integer.toString(pday))); - - if (codaMarkers.size() > 0) { - Marker codaMarker = codaMarkers.get(0); - long codaMarkerTime = codaMarker.getMarkerTime().getTime(); - long pMarkerTime = pMarker.getMarkerTime().getTime(); - long timeDiffFromCodaToP = Math.abs(codaMarkerTime - pMarkerTime); - timeDiffFromCodaToPInSec = timeDiffFromCodaToP / 1000; - } + long cTime = eChan.getCodaTime(); + if (cTime > 0) { + phaseRecord.setFMP(cTime = pPhase.time); } + phaseRecord.setAS("1"); + } else { + phaseRecord.setAS(""); + } - if (smarkers.size() > 0) { - Marker sMarker = smarkers.get(0); - Calendar c = Calendar.getInstance(); - c.setTimeInMillis(sMarker.getMarkerTime().getTime()); - - smrk = sMarker.getIs_es() + sMarker.getUpDownUnknown() - + (sMarker.getWeight() == null ? "0" : sMarker.getWeight().toString()); - - sSec = c.get(Calendar.SECOND) + c.get(Calendar.MILLISECOND) / 1000f; - } + phaseRecord.setSYM('D'); + phaseRecord.setRMK(""); + phaseRecordsList.add(phaseRecord); - phaseRecordsList - .add( - new PhaseRecord(st, prmk, // PRMK - (prmk != null && prmk.length() > 3) ? Float.parseFloat(prmk.substring(3, 4)) - : 0, - (int) pkDate, pMin, pSec, sSec, smrk, // SMRK - 0.0f, // WS - 0.0f, // AMX TODO: calc this - 0.0f, // PRX - 0.0f, // CALC - 0.0f, // CALX - "", // RMK - 0.0f, // DT - timeDiffFromCodaToPInSec, // FMP - "", // "1.22", - 'D', smrk != null ? "1" : "", "", // "SR01IPD0 691005120651.22", - ' ', "" // "IPD0" - )); - } } + PhaseRecord lastRecordIndicator = new PhaseRecord(); lastRecordIndicator.setMSTA(""); phaseRecordsList.add(lastRecordIndicator); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/HypoResults.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/HypoResults.java new file mode 100644 index 00000000..4db97e6c --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/HypoResults.java @@ -0,0 +1,86 @@ +package gov.usgs.volcanoes.swarm.picker.hypo71; + + +import java.io.Serializable; +import java.util.LinkedList; +import java.util.List; + +import gov.usgs.volcanoes.core.Hypo71.AdjustmentIteration; +import gov.usgs.volcanoes.core.Hypo71.Hypocenter; +import gov.usgs.volcanoes.core.Hypo71.Station; +import gov.usgs.volcanoes.core.Hypo71.Stats; + +/** + * This class represents the results of an hypo calculation + * + * @author Chirag Patel + */ +@SuppressWarnings("serial") +public class HypoResults implements Serializable{ + private List adjustmentsOutput = new LinkedList(); + private List hypocenterOuput = new LinkedList(); + private List missingStationsList = new LinkedList(); + private List stationsResultList = new LinkedList(); + private List summaryList = new LinkedList(); + private List deletedStationsList = new LinkedList(); + private Stats stats; + private String printOutput = new String(); + private String punchOutput = new String(); + public List getAdjustmentsOutput() { + return adjustmentsOutput; + } + public void setAdjustmentsOutput(List adjustmentsOutput) { + this.adjustmentsOutput = adjustmentsOutput; + } + public List getHypocenterOuput() { + return hypocenterOuput; + } + public void setHypocenterOuput(List hypocenterOuput) { + this.hypocenterOuput = hypocenterOuput; + } + public List getMissingStationsList() { + return missingStationsList; + } + public void setMissingStationsList(List missingStationsList) { + this.missingStationsList = missingStationsList; + } + public List getStationsResultList() { + return stationsResultList; + } + public void setStationsResultList(List stationsResultList) { + this.stationsResultList = stationsResultList; + } + public List getSummaryList() { + return summaryList; + } + public void setSummaryList(List summaryList) { + this.summaryList = summaryList; + } + public List getDeletedStationsList() { + return deletedStationsList; + } + public void setDeletedStationsList(List deletedStationsList) { + this.deletedStationsList = deletedStationsList; + } + public Stats getStats() { + return stats; + } + public void setStats(Stats stats) { + this.stats = stats; + } + public String getPrintOutput() { + return printOutput; + } + public void setPrintOutput(String printOutput) { + this.printOutput = printOutput; + } + public String getPunchOutput() { + return punchOutput; + } + public void setPunchOutput(String punchOutput) { + this.punchOutput = punchOutput; + } + + + +} From a04505f7e874c090a990e4c4377124089f26040f Mon Sep 17 00:00:00 2001 From: tparker Date: Sat, 5 Mar 2016 14:16:18 -0900 Subject: [PATCH 03/67] Run Hypo71 and plot locations on map --- .../swarm/hypocenters/Hypocenter.java | 11 +++++ .../hypocenters/HypocenterListListener.java | 5 ++ .../swarm/hypocenters/HypocenterPlotter.java | 47 +++++++++++++++++++ .../swarm/hypocenters/Hypocenters.java | 37 +++++++++++++++ .../usgs/volcanoes/swarm/map/MapFrame.java | 5 ++ .../usgs/volcanoes/swarm/map/MapLayer.java | 12 +++++ .../usgs/volcanoes/swarm/map/MapPanel.java | 21 +++++++-- .../volcanoes/swarm/picker/PickerFrame.java | 4 +- ...{Hypo71Adapter.java => Hypo71Locator.java} | 36 +++++++------- src/main/resources/log4jDebug.properties | 17 +++++++ 10 files changed, 169 insertions(+), 26 deletions(-) create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/hypocenters/Hypocenter.java create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/hypocenters/HypocenterListListener.java create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/hypocenters/HypocenterPlotter.java create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/hypocenters/Hypocenters.java create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/map/MapLayer.java rename src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/{Hypo71Adapter.java => Hypo71Locator.java} (88%) create mode 100644 src/main/resources/log4jDebug.properties diff --git a/src/main/java/gov/usgs/volcanoes/swarm/hypocenters/Hypocenter.java b/src/main/java/gov/usgs/volcanoes/swarm/hypocenters/Hypocenter.java new file mode 100644 index 00000000..03e241e8 --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/hypocenters/Hypocenter.java @@ -0,0 +1,11 @@ +package gov.usgs.volcanoes.swarm.hypocenters; + +public class Hypocenter { + public final double lat; + public final double lon; + + public Hypocenter(double lat, double lon) { + this.lat = lat; + this.lon = lon; + } +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/hypocenters/HypocenterListListener.java b/src/main/java/gov/usgs/volcanoes/swarm/hypocenters/HypocenterListListener.java new file mode 100644 index 00000000..aa0e890e --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/hypocenters/HypocenterListListener.java @@ -0,0 +1,5 @@ +package gov.usgs.volcanoes.swarm.hypocenters; + +public interface HypocenterListListener { + +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/hypocenters/HypocenterPlotter.java b/src/main/java/gov/usgs/volcanoes/swarm/hypocenters/HypocenterPlotter.java new file mode 100644 index 00000000..6eac4a5b --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/hypocenters/HypocenterPlotter.java @@ -0,0 +1,47 @@ +package gov.usgs.volcanoes.swarm.hypocenters; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.geom.Point2D; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import gov.usgs.proj.GeoRange; +import gov.usgs.proj.Projection; +import gov.usgs.volcanoes.swarm.map.MapFrame; +import gov.usgs.volcanoes.swarm.map.MapLayer; + +public final class HypocenterPlotter implements MapLayer { + + Logger LOGGER = LoggerFactory.getLogger(HypocenterPlotter.class); + private final List hypocenters; + + public HypocenterPlotter(List hypocenters) { + this.hypocenters = hypocenters; + // Hypocenters.addListener(this); + MapFrame.getInstance().addLayer(this); + } + + public void draw(Graphics2D g2, GeoRange range, Projection projection, int widthPx, int heightPx, + int insetPx) { + + for (Hypocenter hypocenter : hypocenters) { + LOGGER.debug("Hypo at {}, {}", hypocenter.lon, hypocenter.lat); + final Point2D.Double xy = + projection.forward(new Point2D.Double(-hypocenter.lon, hypocenter.lat)); + final double[] ext = range.getProjectedExtents(projection); + final double dx = (ext[1] - ext[0]); + final double dy = (ext[3] - ext[2]); + final Point2D.Double res = new Point2D.Double(); + res.x = (((xy.x - ext[0]) / dx) * widthPx + insetPx); + res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); + + g2.translate(res.x, res.y); + g2.setColor(Color.RED); + g2.drawOval(0, 0, 10, 10); + g2.translate(-res.x, -res.y); + } + } +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/hypocenters/Hypocenters.java b/src/main/java/gov/usgs/volcanoes/swarm/hypocenters/Hypocenters.java new file mode 100644 index 00000000..c1ad38ef --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/hypocenters/Hypocenters.java @@ -0,0 +1,37 @@ +package gov.usgs.volcanoes.swarm.hypocenters; + +import java.util.ArrayList; +import java.util.List; + +public class Hypocenters { + + private final static List hypocenters; + private final static List listeners; + private final static HypocenterPlotter plotter; + + static { + hypocenters = new ArrayList(); + listeners = new ArrayList(); + plotter = new HypocenterPlotter(hypocenters); + } + + /** uninstantiable */ + private Hypocenters() {} + + public static void addListener(HypocenterListListener listener) { + listeners.add(listener); + } + + public static void add (Hypocenter hypocenter) { + hypocenters.add(hypocenter); + } + + public static Hypocenters getInstance() { + return HypocentersHolder.hypocenters; + } + + private static class HypocentersHolder { + public static Hypocenters hypocenters = new Hypocenters(); + } + +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapFrame.java index fe6dd421..7320da41 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapFrame.java @@ -3,6 +3,7 @@ import java.awt.BorderLayout; import java.awt.Graphics; import java.awt.Insets; +import java.awt.Panel; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; @@ -551,6 +552,10 @@ public void setKioskMode(final boolean b) { } } + public void addLayer(MapLayer layer) { + mapPanel.addLayer(layer); + } + public void run() { while (true) { try { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapLayer.java new file mode 100644 index 00000000..9174eb40 --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapLayer.java @@ -0,0 +1,12 @@ +package gov.usgs.volcanoes.swarm.map; + +import java.awt.Graphics2D; + +import gov.usgs.proj.GeoRange; +import gov.usgs.proj.Projection; + +public interface MapLayer { + + public void draw(Graphics2D g2, GeoRange range, Projection projection, int widthPx, int heightPx, int insetPx); + +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java index 3da848f3..7225b378 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java @@ -1,8 +1,5 @@ package gov.usgs.volcanoes.swarm.map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Color; @@ -50,6 +47,9 @@ import javax.swing.JPanel; import javax.swing.SwingUtilities; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import gov.usgs.plot.Plot; import gov.usgs.plot.map.GeoImageSet; import gov.usgs.plot.map.GeoLabelSet; @@ -179,6 +179,7 @@ else if (s.equals("S")) private LabelSetting labelSetting = LabelSetting.SOME; private List clickableLabels; + private List layers; public MapPanel() { swarmConfig = SwarmConfig.getInstance(); @@ -189,12 +190,18 @@ public MapPanel() { layouts = Collections.synchronizedMap(new HashMap()); visiblePanels = Collections.synchronizedList(new ArrayList()); selectedPanels = new HashSet(); + layers = new ArrayList(); final Cursor crosshair = new Cursor(Cursor.CROSSHAIR_CURSOR); this.setCursor(crosshair); createUI(); } + public void addLayer(MapLayer layer) { + LOGGER.debug("Layer added"); + layers.add(layer); + } + public void saveLayout(final ConfigFile cf, final String prefix) { cf.put(prefix + ".longitude", Double.toString(center.x)); cf.put(prefix + ".latitude", Double.toString(center.y)); @@ -1017,9 +1024,15 @@ public void paintComponent(final Graphics g) { } } } + + g2.translate(-dx, -dy); + for (MapLayer layer : layers) { + layer.draw(g2, range, projection, renderer.getGraphWidth(), renderer.getGraphHeight(), INSET); + } + g2.translate(dx, dy); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldaa); g2.setTransform(at); - } } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java index cd0b24c4..ee220ba5 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java @@ -75,7 +75,7 @@ import gov.usgs.volcanoes.swarm.chooser.DataChooser; import gov.usgs.volcanoes.swarm.data.CachedDataSource; import gov.usgs.volcanoes.swarm.data.SeismicDataSource; -import gov.usgs.volcanoes.swarm.picker.hypo71.Hypo71Adapter; +import gov.usgs.volcanoes.swarm.picker.hypo71.Hypo71Locator; import gov.usgs.volcanoes.swarm.time.TimeListener; import gov.usgs.volcanoes.swarm.time.WaveViewTime; import gov.usgs.volcanoes.swarm.wave.AbstractWavePanel; @@ -413,7 +413,7 @@ public void actionPerformed(final ActionEvent e) { locateButton = SwarmUtil.createToolBarButton(Icons.locate, "Locate", new ActionListener() { public void actionPerformed(final ActionEvent e) { - EventLocator locator = new Hypo71Adapter(); + EventLocator locator = new Hypo71Locator(); try { locator.locate(event); } catch (IOException e1) { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Adapter.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Locator.java similarity index 88% rename from src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Adapter.java rename to src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Locator.java index cda77b00..f52a7132 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Adapter.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Locator.java @@ -4,12 +4,9 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.LinkedList; -import java.util.List; import java.util.Map; import java.util.Queue; -import javax.swing.JOptionPane; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -22,24 +19,23 @@ import gov.usgs.volcanoes.core.Hypo71.PhaseRecord; import gov.usgs.volcanoes.core.Hypo71.Station; import gov.usgs.volcanoes.swarm.Metadata; -import gov.usgs.volcanoes.swarm.Swarm; import gov.usgs.volcanoes.swarm.SwarmConfig; +import gov.usgs.volcanoes.swarm.hypocenters.Hypocenters; import gov.usgs.volcanoes.swarm.picker.Event; import gov.usgs.volcanoes.swarm.picker.EventChannel; import gov.usgs.volcanoes.swarm.picker.EventLocator; import gov.usgs.volcanoes.swarm.picker.Phase; -public class Hypo71Adapter implements EventLocator { +public class Hypo71Locator implements EventLocator { - private static final Logger LOGGER = LoggerFactory.getLogger(Hypo71Adapter.class); + private static final Logger LOGGER = LoggerFactory.getLogger(Hypo71Locator.class); private ControlCard controlCard; private Queue phaseRecordsList; private Queue stationsList; private Queue crustalModelList; private SimpleDateFormat jtimeFormat; - public Hypo71Adapter() { - + public Hypo71Locator() { // defaults taken from hypo-test-case-1.properties controlCard = @@ -53,23 +49,21 @@ public Hypo71Adapter() { crustalModelList.add(new CrustalModel(8.0, 25.0)); jtimeFormat = new SimpleDateFormat("yyMMddHH"); - + stationsList = new LinkedList(); phaseRecordsList = new LinkedList(); } public void locate(Event event) throws IOException { - String error = null; - try { - generateHypoInputs(event); - } catch (Exception ex) { - ex.printStackTrace(); - error = "Cannot run hypo please ensure input file has correct data"; - } - - if (error == null) { - Results hypoResult = runHypo(event); - LOGGER.debug(hypoResult.getPrintOutput()); + generateHypoInputs(event); + Results hypoResult = runHypo(event); + LOGGER.debug(hypoResult.getPrintOutput()); + for (Hypocenter hypo : hypoResult.getHypocenterOutput()) { + double lon = hypo.getLON1() + (hypo.getLON2() / 60); + double lat = hypo.getLAT1() + (hypo.getLAT2() / 60); + LOGGER.debug("Adding hypo: {}, {} ({} +{}, {} + {})", lon, lat, hypo.getLON1(), + hypo.getLON2(), hypo.getLAT1(), hypo.getLAT2()); + Hypocenters.add(new gov.usgs.volcanoes.swarm.hypocenters.Hypocenter(lat, lon)); } } @@ -150,6 +144,8 @@ private void generateHypoInputs(Event event) { phaseRecord.setSRMK(srmk); long time = sPhase.time; + phaseRecord.setJTIME(Integer.parseInt(jtimeFormat.format(time))); + float sSec = ((time / 1000) % 60) + ((time % 1000) / 1000f); if (sSec < pSec) { sSec += 60; diff --git a/src/main/resources/log4jDebug.properties b/src/main/resources/log4jDebug.properties new file mode 100644 index 00000000..a31c6da1 --- /dev/null +++ b/src/main/resources/log4jDebug.properties @@ -0,0 +1,17 @@ +log4j.rootLogger=ALL, stdout, R + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.Threshold=DEBUG + +# Pattern to output the caller's file name and line number. +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd hh:mm:ss} %5p - %m%n + +log4j.appender.R=org.apache.log4j.RollingFileAppender +log4j.appender.R.File=pensive.log +log4j.appender.R.MaxFileSize=100KB +# Keep one backup file +log4j.appender.R.MaxBackupIndex=9 + +log4j.appender.R.layout=org.apache.log4j.PatternLayout +log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd hh:mm:ss} %5p - %m (%F:%L)%n \ No newline at end of file From bc34562be1b0dbd70807cb90ea9b1dfe7913994c Mon Sep 17 00:00:00 2001 From: tparker Date: Mon, 7 Mar 2016 06:56:02 -0900 Subject: [PATCH 04/67] NEIC hypocenter plotter in progress.. --- pom.xml | 30 +++++++-- .../hypocenters/HypocenterListListener.java | 5 -- .../swarm/map/hypocenters/Hypocenter.java | 63 +++++++++++++++++ .../map/hypocenters/HypocenterPlotter.java | 67 +++++++++++++++++++ .../swarm/map/hypocenters/Hypocenters.java | 40 +++++++++++ .../{hypocenters => picker}/Hypocenter.java | 2 +- .../HypocenterPlotter.java | 2 +- .../{hypocenters => picker}/Hypocenters.java | 8 +-- .../swarm/picker/HypocentersListener.java | 5 ++ .../swarm/picker/hypo71/Hypo71Locator.java | 20 +++--- .../swarm/picker/hypo71/HypoResults.java | 8 +-- 11 files changed, 218 insertions(+), 32 deletions(-) delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/hypocenters/HypocenterListListener.java create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterPlotter.java create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenters.java rename src/main/java/gov/usgs/volcanoes/swarm/{hypocenters => picker}/Hypocenter.java (79%) rename src/main/java/gov/usgs/volcanoes/swarm/{hypocenters => picker}/HypocenterPlotter.java (97%) rename src/main/java/gov/usgs/volcanoes/swarm/{hypocenters => picker}/Hypocenters.java (74%) create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/picker/HypocentersListener.java diff --git a/pom.xml b/pom.xml index f2ea8c7f..ef083235 100644 --- a/pom.xml +++ b/pom.xml @@ -403,10 +403,16 @@ volcanoes - true http://volcanoes.usgs.gov/software/maven2/ + @@ -490,16 +496,26 @@ winston 1.3.0-SNAPSHOT + + io.netty + netty-all + 4.0.31.Final + + + com.mastfrog + netty-http-client + 1.6.4 + opensymphony oscache 2.4.1 - - - javax.jms - jms - - + + + javax.jms + jms + + diff --git a/src/main/java/gov/usgs/volcanoes/swarm/hypocenters/HypocenterListListener.java b/src/main/java/gov/usgs/volcanoes/swarm/hypocenters/HypocenterListListener.java deleted file mode 100644 index aa0e890e..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/hypocenters/HypocenterListListener.java +++ /dev/null @@ -1,5 +0,0 @@ -package gov.usgs.volcanoes.swarm.hypocenters; - -public interface HypocenterListListener { - -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java new file mode 100644 index 00000000..856ac0ae --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java @@ -0,0 +1,63 @@ +package gov.usgs.volcanoes.swarm.map.hypocenters; + +public class Hypocenter { + + /* + * { + * "type":"FeatureCollection", + * "metadata": + * { + * "generated":1457314920000, + * "url":"http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_day.geojson", + * "title":"USGS Magnitude 2.5+ Earthquakes, Past Day", + * "status":200, + * "api":"1.5.0", + * "count":28 + * }, + * "features":[ + * { + * "type":"Feature", + * "properties":{ + * "mag":4, + * "place":"28km NW of Fairview, Oklahoma", + * "time":1457311416660, + * "updated":1457314429000, + * "tz":-360, + * "url":"http://earthquake.usgs.gov/earthquakes/eventpage/us10004vsc", + * "detail":"http://earthquake.usgs.gov/earthquakes/feed/v1.0/detail/us10004vsc.geojson", + * "felt":10, + * "cdi":4.7, + * "mmi":4.65, + * "alert":"green", + * "status":"reviewed", + * "tsunami":0, + * "sig":251, + * "net":"us", + * "code":"10004vsc", + * "ids":",us10004vsc,", + * "sources":",us,", + * "types":",dyfi,general-link,geoserve,losspager,nearby-cities,origin,phase-data,shakemap,tectonic-summary,", + * "nst":null, + * "dmin":0.034, + * "rms":0.64, + * "gap":43, + * "magType":"mb_lg", + * "type":"earthquake", + * "title":"M 4.0 - 28km NW of Fairview, Oklahoma" + * }, + * "geometry":{ + * "type":"Point", + * "coordinates":[-98.7015,36.4561,3.16] + * }, + * "id":"us10004vsc" + * }, + * */ + */ + public final double lat; + public final double lon; + + public Hypocenter(double lat, double lon) { + this.lat = lat; + this.lon = lon; + } +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterPlotter.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterPlotter.java new file mode 100644 index 00000000..57ccd1c5 --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterPlotter.java @@ -0,0 +1,67 @@ +package gov.usgs.volcanoes.swarm.map.hypocenters; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.geom.Point2D; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.mastfrog.netty.http.client.HttpClient; +import com.mastfrog.netty.http.client.ResponseFuture; +import com.mastfrog.netty.http.client.ResponseHandler; + +import gov.usgs.proj.GeoRange; +import gov.usgs.proj.Projection; +import gov.usgs.volcanoes.swarm.map.MapFrame; +import gov.usgs.volcanoes.swarm.map.MapLayer; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpResponseStatus; + +public final class HypocenterPlotter implements MapLayer { + + Logger LOGGER = LoggerFactory.getLogger(HypocenterPlotter.class); + private final List hypocenters; + + public HypocenterPlotter(List hypocenters) { + this.hypocenters = hypocenters; + // Hypocenters.addListener(this); + MapFrame.getInstance().addLayer(this); + } + + + private void startPolling() { + + HttpClient client = HttpClient.builder().followRedirects().build(); + ResponseFuture f = client.get() + .setURL( "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_day.geojson" ) + .execute ( new ResponseHandler ( String.class ) { + + protected void receive ( HttpResponseStatus status, HttpHeaders headers, String response ) { + System.out.println ( "Here's the response: '" + response + "'" ); + } + }); + } + + public void draw(Graphics2D g2, GeoRange range, Projection projection, int widthPx, int heightPx, + int insetPx) { + + for (Hypocenter hypocenter : hypocenters) { + LOGGER.debug("Hypo at {}, {}", hypocenter.lon, hypocenter.lat); + final Point2D.Double xy = + projection.forward(new Point2D.Double(-hypocenter.lon, hypocenter.lat)); + final double[] ext = range.getProjectedExtents(projection); + final double dx = (ext[1] - ext[0]); + final double dy = (ext[3] - ext[2]); + final Point2D.Double res = new Point2D.Double(); + res.x = (((xy.x - ext[0]) / dx) * widthPx + insetPx); + res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); + + g2.translate(res.x, res.y); + g2.setColor(Color.RED); + g2.drawOval(0, 0, 10, 10); + g2.translate(-res.x, -res.y); + } + } +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenters.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenters.java new file mode 100644 index 00000000..c45be58c --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenters.java @@ -0,0 +1,40 @@ +package gov.usgs.volcanoes.swarm.map.hypocenters; + +import java.util.ArrayList; +import java.util.List; + +import gov.usgs.volcanoes.swarm.picker.HypocentersListener; + + +public class Hypocenters { + + private final static List hypocenters; + private final static List listeners; + private final static HypocenterPlotter plotter; + + static { + hypocenters = new ArrayList(); + listeners = new ArrayList(); + plotter = new HypocenterPlotter(hypocenters); + } + + /** uninstantiable */ + private Hypocenters() {} + + public static void addListener(HypocentersListener listener) { + listeners.add(listener); + } + + public static void add (Hypocenter hypocenter) { + hypocenters.add(hypocenter); + } + + public static Hypocenters getInstance() { + return HypocentersHolder.hypocenters; + } + + private static class HypocentersHolder { + public static Hypocenters hypocenters = new Hypocenters(); + } + +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/hypocenters/Hypocenter.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/Hypocenter.java similarity index 79% rename from src/main/java/gov/usgs/volcanoes/swarm/hypocenters/Hypocenter.java rename to src/main/java/gov/usgs/volcanoes/swarm/picker/Hypocenter.java index 03e241e8..8fd4fec0 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/hypocenters/Hypocenter.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/Hypocenter.java @@ -1,4 +1,4 @@ -package gov.usgs.volcanoes.swarm.hypocenters; +package gov.usgs.volcanoes.swarm.picker; public class Hypocenter { public final double lat; diff --git a/src/main/java/gov/usgs/volcanoes/swarm/hypocenters/HypocenterPlotter.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/HypocenterPlotter.java similarity index 97% rename from src/main/java/gov/usgs/volcanoes/swarm/hypocenters/HypocenterPlotter.java rename to src/main/java/gov/usgs/volcanoes/swarm/picker/HypocenterPlotter.java index 6eac4a5b..07c0d16f 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/hypocenters/HypocenterPlotter.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/HypocenterPlotter.java @@ -1,4 +1,4 @@ -package gov.usgs.volcanoes.swarm.hypocenters; +package gov.usgs.volcanoes.swarm.picker; import java.awt.Color; import java.awt.Graphics2D; diff --git a/src/main/java/gov/usgs/volcanoes/swarm/hypocenters/Hypocenters.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/Hypocenters.java similarity index 74% rename from src/main/java/gov/usgs/volcanoes/swarm/hypocenters/Hypocenters.java rename to src/main/java/gov/usgs/volcanoes/swarm/picker/Hypocenters.java index c1ad38ef..cb76a12d 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/hypocenters/Hypocenters.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/Hypocenters.java @@ -1,4 +1,4 @@ -package gov.usgs.volcanoes.swarm.hypocenters; +package gov.usgs.volcanoes.swarm.picker; import java.util.ArrayList; import java.util.List; @@ -6,19 +6,19 @@ public class Hypocenters { private final static List hypocenters; - private final static List listeners; + private final static List listeners; private final static HypocenterPlotter plotter; static { hypocenters = new ArrayList(); - listeners = new ArrayList(); + listeners = new ArrayList(); plotter = new HypocenterPlotter(hypocenters); } /** uninstantiable */ private Hypocenters() {} - public static void addListener(HypocenterListListener listener) { + public static void addListener(HypocentersListener listener) { listeners.add(listener); } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/HypocentersListener.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/HypocentersListener.java new file mode 100644 index 00000000..6a399a1c --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/HypocentersListener.java @@ -0,0 +1,5 @@ +package gov.usgs.volcanoes.swarm.picker; + +public interface HypocentersListener { + +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Locator.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Locator.java index f52a7132..1eff0c8f 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Locator.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Locator.java @@ -10,20 +10,20 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import gov.usgs.volcanoes.core.Hypo71.ControlCard; -import gov.usgs.volcanoes.core.Hypo71.CrustalModel; -import gov.usgs.volcanoes.core.Hypo71.Hypo71; -import gov.usgs.volcanoes.core.Hypo71.Hypo71.Results; -import gov.usgs.volcanoes.core.Hypo71.HypoArchiveOutput; -import gov.usgs.volcanoes.core.Hypo71.Hypocenter; -import gov.usgs.volcanoes.core.Hypo71.PhaseRecord; -import gov.usgs.volcanoes.core.Hypo71.Station; +import gov.usgs.volcanoes.core.hypo71.ControlCard; +import gov.usgs.volcanoes.core.hypo71.CrustalModel; +import gov.usgs.volcanoes.core.hypo71.Hypo71; +import gov.usgs.volcanoes.core.hypo71.HypoArchiveOutput; +import gov.usgs.volcanoes.core.hypo71.Hypocenter; +import gov.usgs.volcanoes.core.hypo71.PhaseRecord; +import gov.usgs.volcanoes.core.hypo71.Station; +import gov.usgs.volcanoes.core.hypo71.Hypo71.Results; import gov.usgs.volcanoes.swarm.Metadata; import gov.usgs.volcanoes.swarm.SwarmConfig; -import gov.usgs.volcanoes.swarm.hypocenters.Hypocenters; import gov.usgs.volcanoes.swarm.picker.Event; import gov.usgs.volcanoes.swarm.picker.EventChannel; import gov.usgs.volcanoes.swarm.picker.EventLocator; +import gov.usgs.volcanoes.swarm.picker.Hypocenters; import gov.usgs.volcanoes.swarm.picker.Phase; public class Hypo71Locator implements EventLocator { @@ -63,7 +63,7 @@ public void locate(Event event) throws IOException { double lat = hypo.getLAT1() + (hypo.getLAT2() / 60); LOGGER.debug("Adding hypo: {}, {} ({} +{}, {} + {})", lon, lat, hypo.getLON1(), hypo.getLON2(), hypo.getLAT1(), hypo.getLAT2()); - Hypocenters.add(new gov.usgs.volcanoes.swarm.hypocenters.Hypocenter(lat, lon)); + Hypocenters.add(new gov.usgs.volcanoes.swarm.picker.Hypocenter(lat, lon)); } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/HypoResults.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/HypoResults.java index 4db97e6c..ddc048b7 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/HypoResults.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/HypoResults.java @@ -5,10 +5,10 @@ import java.util.LinkedList; import java.util.List; -import gov.usgs.volcanoes.core.Hypo71.AdjustmentIteration; -import gov.usgs.volcanoes.core.Hypo71.Hypocenter; -import gov.usgs.volcanoes.core.Hypo71.Station; -import gov.usgs.volcanoes.core.Hypo71.Stats; +import gov.usgs.volcanoes.core.hypo71.AdjustmentIteration; +import gov.usgs.volcanoes.core.hypo71.Hypocenter; +import gov.usgs.volcanoes.core.hypo71.Station; +import gov.usgs.volcanoes.core.hypo71.Stats; /** * This class represents the results of an hypo calculation From 4e4a0ec27f199b6321b55fe2b1ee4e691a7bf159 Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Mon, 7 Mar 2016 16:30:24 -0900 Subject: [PATCH 05/67] New hypocenters working... --- .../java/gov/usgs/volcanoes/swarm/Swarm.java | 11 +- .../volcanoes/swarm/map/FdsnLabelSource.java | 1 + .../usgs/volcanoes/swarm/map/Hypocenter.java | 80 -------- .../usgs/volcanoes/swarm/map/MapFrame.java | 4 +- .../usgs/volcanoes/swarm/map/MapLayer.java | 5 +- .../usgs/volcanoes/swarm/map/MapPanel.java | 54 +++--- .../swarm/map/hypocenters/Hypocenter.java | 136 ++++++++------ .../map/hypocenters/HypocenterPlotter.java | 175 ++++++++++++++---- .../swarm/map/hypocenters/Hypocenters.java | 40 ---- .../nz/org/geonet/data/RSSHypocenters.java | 2 +- 10 files changed, 263 insertions(+), 245 deletions(-) delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/map/Hypocenter.java delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenters.java diff --git a/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java b/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java index c3a18bdf..b7e18b00 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java @@ -1,5 +1,10 @@ package gov.usgs.volcanoes.swarm; +import com.jgoodies.looks.plastic.Plastic3DLookAndFeel; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.awt.Dimension; import java.awt.Frame; import java.awt.KeyboardFocusManager; @@ -24,11 +29,6 @@ import javax.swing.SwingUtilities; import javax.swing.UIManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.jgoodies.looks.plastic.Plastic3DLookAndFeel; - import gov.usgs.plot.data.Wave; import gov.usgs.volcanoes.core.configfile.ConfigFile; import gov.usgs.volcanoes.core.time.CurrentTime; @@ -105,6 +105,7 @@ public Swarm(final String[] args) { checkJavaVersion(); setupGlobalKeys(); createUI(); + new gov.usgs.volcanoes.swarm.map.hypocenters.HypocenterPlotter(); } private void checkJavaVersion() { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/FdsnLabelSource.java b/src/main/java/gov/usgs/volcanoes/swarm/map/FdsnLabelSource.java index ad57839d..6774fc90 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/FdsnLabelSource.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/FdsnLabelSource.java @@ -27,6 +27,7 @@ import gov.usgs.proj.GeoRange; import gov.usgs.volcanoes.core.time.J2kSec; import gov.usgs.volcanoes.core.time.Time; +import gov.usgs.volcanoes.swarm.map.hypocenters.Hypocenter; /* * A class to retrieve events from IRIS for plotting on the map. diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/Hypocenter.java b/src/main/java/gov/usgs/volcanoes/swarm/map/Hypocenter.java deleted file mode 100644 index b70d686d..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/Hypocenter.java +++ /dev/null @@ -1,80 +0,0 @@ -package gov.usgs.volcanoes.swarm.map; - -import gov.usgs.math.Geometry; -import gov.usgs.plot.render.DataPointRenderer; -import gov.usgs.util.Pair; -import gov.usgs.volcanoes.swarm.Metadata; -import gov.usgs.volcanoes.swarm.SwarmConfig; -import gov.usgs.volcanoes.swarm.wave.MultiMonitor; -import gov.usgs.volcanoes.swarm.wave.SwarmMultiMonitors; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Rectangle; -import java.awt.event.MouseEvent; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * - * @author Dan Cervelli - */ -public class Hypocenter extends ClickableGeoLabel -{ - public double time; - public double depth; - public double magnitude; - - private static SwarmConfig swarmConfig; - - public Hypocenter() - { - swarmConfig = SwarmConfig.getInstance(); - - DataPointRenderer r = new DataPointRenderer(); - r.antiAlias = true; - r.stroke = new BasicStroke(1.2f); - r.filled = true; - r.paint = Color.RED; - r.color = Color.yellow; - r.shape = Geometry.STAR_10; - marker = r; - } - - @Override - public Rectangle getClickBox() - { - return new Rectangle(-7, -7, 17, 17); - } - - @Override - public void mouseClicked(MouseEvent e) - { - Map metadata = swarmConfig.getMetadata(); - List> nrst = Metadata.findNearest(swarmConfig.getMetadata(), location, true); - Set cleared = new HashSet(); - if (nrst != null) - { - for (int i = 0, total = 0; i < nrst.size() && total < 10; i++) - { - String ch = nrst.get(i).item2; - if (ch.matches(".* ..Z .*")) - { - Metadata md = metadata.get(ch); - MultiMonitor mm = SwarmMultiMonitors.getMonitor(md.source); - if (!cleared.contains(mm)) - { - mm.removeAllWaves(); - cleared.add(mm); - } - mm.addChannel(ch); - mm.setVisible(true); - mm.setPauseStartTime(time - 4); - total++; - } - } - } - } -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapFrame.java index 7320da41..be5d0580 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapFrame.java @@ -552,8 +552,10 @@ public void setKioskMode(final boolean b) { } } - public void addLayer(MapLayer layer) { + public MapPanel addLayer(MapLayer layer) { mapPanel.addLayer(layer); + + return mapPanel; } public void run() { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapLayer.java index 9174eb40..915d4aab 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapLayer.java @@ -1,12 +1,15 @@ package gov.usgs.volcanoes.swarm.map; import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.event.MouseEvent; import gov.usgs.proj.GeoRange; import gov.usgs.proj.Projection; public interface MapLayer { - public void draw(Graphics2D g2, GeoRange range, Projection projection, int widthPx, int heightPx, int insetPx); + public void draw(Graphics2D g2); + public boolean mouseClicked(MouseEvent e); } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java index 7225b378..1e30adeb 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java @@ -1,5 +1,8 @@ package gov.usgs.volcanoes.swarm.map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Color; @@ -33,6 +36,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -47,9 +51,6 @@ import javax.swing.JPanel; import javax.swing.SwingUtilities; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import gov.usgs.plot.Plot; import gov.usgs.plot.map.GeoImageSet; import gov.usgs.plot.map.GeoLabelSet; @@ -178,7 +179,6 @@ else if (s.equals("S")) private LabelSetting labelSetting = LabelSetting.SOME; - private List clickableLabels; private List layers; public MapPanel() { @@ -343,7 +343,6 @@ public void loadLabels() { try { final Class cl = Class.forName(swarmConfig.labelSource); final LabelSource src = (LabelSource) cl.newInstance(); - clickableLabels = src.getLabels(); repaint(); } catch (final Exception e) { LOGGER.warn("Can't load labelSource {}", swarmConfig.labelSource); @@ -1014,20 +1013,10 @@ public void paintComponent(final Graphics g) { g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); final AffineTransform at = g2.getTransform(); g2.setFont(Font.decode("dialog-plain-12")); - if (clickableLabels != null) { - for (final ClickableGeoLabel label : clickableLabels) { - final Point2D.Double xy = getXY(label.location.x, label.location.y); - if (xy != null) { - g2.translate(xy.x - dx, xy.y - dy); - label.draw(g2); - g2.translate(-xy.x + dx, -xy.y + dy); - } - } - } g2.translate(-dx, -dy); for (MapLayer layer : layers) { - layer.draw(g2, range, projection, renderer.getGraphWidth(), renderer.getGraphHeight(), INSET); + layer.draw(g2); } g2.translate(dx, dy); @@ -1041,6 +1030,22 @@ public GeoRange getRange() { return range; } + public Projection getProjection() { + return projection; + } + + public int getGraphWidth() { + return renderer.getGraphWidth(); + } + + public int getGraphHeight() { + return renderer.getGraphHeight(); + } + + public int getInset() { + return INSET; + } + public class MapMouseAdapter extends MouseAdapter { @Override public void mouseExited(final MouseEvent e) { @@ -1049,19 +1054,16 @@ public void mouseExited(final MouseEvent e) { @Override public void mouseClicked(final MouseEvent e) { - if (clickableLabels != null) { - for (final ClickableGeoLabel label : clickableLabels) { - final Rectangle r = label.getClickBox(); - final Point2D.Double xy = getXY(label.location.x, label.location.y); - if (xy != null) { - r.translate((int) xy.x, (int) xy.y); - if (r.contains(e.getPoint())) - label.mouseClicked(e); - } + if (layers != null) { + boolean handled = false; + Iterator it = layers.iterator(); + while (it.hasNext() && handled == false) { + MapLayer layer = it.next(); + handled = layer.mouseClicked(e); } } } - + @Override public void mousePressed(final MouseEvent e) { requestFocusInWindow(); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java index 856ac0ae..e8195992 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java @@ -1,63 +1,81 @@ package gov.usgs.volcanoes.swarm.map.hypocenters; -public class Hypocenter { - - /* - * { - * "type":"FeatureCollection", - * "metadata": - * { - * "generated":1457314920000, - * "url":"http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_day.geojson", - * "title":"USGS Magnitude 2.5+ Earthquakes, Past Day", - * "status":200, - * "api":"1.5.0", - * "count":28 - * }, - * "features":[ - * { - * "type":"Feature", - * "properties":{ - * "mag":4, - * "place":"28km NW of Fairview, Oklahoma", - * "time":1457311416660, - * "updated":1457314429000, - * "tz":-360, - * "url":"http://earthquake.usgs.gov/earthquakes/eventpage/us10004vsc", - * "detail":"http://earthquake.usgs.gov/earthquakes/feed/v1.0/detail/us10004vsc.geojson", - * "felt":10, - * "cdi":4.7, - * "mmi":4.65, - * "alert":"green", - * "status":"reviewed", - * "tsunami":0, - * "sig":251, - * "net":"us", - * "code":"10004vsc", - * "ids":",us10004vsc,", - * "sources":",us,", - * "types":",dyfi,general-link,geoserve,losspager,nearby-cities,origin,phase-data,shakemap,tectonic-summary,", - * "nst":null, - * "dmin":0.034, - * "rms":0.64, - * "gap":43, - * "magType":"mb_lg", - * "type":"earthquake", - * "title":"M 4.0 - 28km NW of Fairview, Oklahoma" - * }, - * "geometry":{ - * "type":"Point", - * "coordinates":[-98.7015,36.4561,3.16] - * }, - * "id":"us10004vsc" - * }, - * */ - */ - public final double lat; - public final double lon; +import gov.usgs.math.Geometry; +import gov.usgs.plot.render.DataPointRenderer; +import gov.usgs.util.Pair; +import gov.usgs.volcanoes.swarm.Metadata; +import gov.usgs.volcanoes.swarm.SwarmConfig; +import gov.usgs.volcanoes.swarm.map.ClickableGeoLabel; +import gov.usgs.volcanoes.swarm.wave.MultiMonitor; +import gov.usgs.volcanoes.swarm.wave.SwarmMultiMonitors; - public Hypocenter(double lat, double lon) { - this.lat = lat; - this.lon = lon; - } +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Rectangle; +import java.awt.event.MouseEvent; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * + * @author Dan Cervelli + */ +public class Hypocenter extends ClickableGeoLabel +{ + public double time; + public double depth; + public double magnitude; + + private static SwarmConfig swarmConfig; + + public Hypocenter() + { + swarmConfig = SwarmConfig.getInstance(); + + DataPointRenderer r = new DataPointRenderer(); + r.antiAlias = true; + r.stroke = new BasicStroke(1.2f); + r.filled = true; + r.paint = Color.RED; + r.color = Color.yellow; + r.shape = Geometry.STAR_10; + marker = r; + } + + @Override + public Rectangle getClickBox() + { + return new Rectangle(-7, -7, 17, 17); + } + + @Override + public void mouseClicked(MouseEvent e) + { + Map metadata = swarmConfig.getMetadata(); + List> nrst = Metadata.findNearest(swarmConfig.getMetadata(), location, true); + Set cleared = new HashSet(); + if (nrst != null) + { + for (int i = 0, total = 0; i < nrst.size() && total < 10; i++) + { + String ch = nrst.get(i).item2; + if (ch.matches(".* ..Z .*")) + { + Metadata md = metadata.get(ch); + MultiMonitor mm = SwarmMultiMonitors.getMonitor(md.source); + if (!cleared.contains(mm)) + { + mm.removeAllWaves(); + cleared.add(mm); + } + mm.addChannel(ch); + mm.setVisible(true); + mm.setPauseStartTime(time - 4); + total++; + } + } + } + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterPlotter.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterPlotter.java index 57ccd1c5..9e8a3f28 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterPlotter.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterPlotter.java @@ -1,56 +1,131 @@ package gov.usgs.volcanoes.swarm.map.hypocenters; -import java.awt.Color; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.event.MouseEvent; import java.awt.geom.Point2D; +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.mastfrog.netty.http.client.HttpClient; -import com.mastfrog.netty.http.client.ResponseFuture; -import com.mastfrog.netty.http.client.ResponseHandler; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; import gov.usgs.proj.GeoRange; import gov.usgs.proj.Projection; +import gov.usgs.volcanoes.core.time.J2kSec; +import gov.usgs.volcanoes.swarm.map.ClickableGeoLabel; import gov.usgs.volcanoes.swarm.map.MapFrame; import gov.usgs.volcanoes.swarm.map.MapLayer; -import io.netty.handler.codec.http.HttpHeaders; -import io.netty.handler.codec.http.HttpResponseStatus; +import gov.usgs.volcanoes.swarm.map.MapPanel; public final class HypocenterPlotter implements MapLayer { - Logger LOGGER = LoggerFactory.getLogger(HypocenterPlotter.class); - private final List hypocenters; + private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSX"; + + private static final Logger LOGGER = LoggerFactory.getLogger(HypocenterPlotter.class); + private static final int REFRESH_INTERVAL = 5 * 60 * 1000; + private List hypocenters; + private final String URL = + "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_day.quakeml"; - public HypocenterPlotter(List hypocenters) { - this.hypocenters = hypocenters; - // Hypocenters.addListener(this); - MapFrame.getInstance().addLayer(this); - } + private MapPanel panel; + private SimpleDateFormat dateFormat; + public HypocenterPlotter() { + dateFormat = new SimpleDateFormat(DATE_FORMAT); + panel = MapFrame.getInstance().addLayer(this); + startPolling(); + } private void startPolling() { - - HttpClient client = HttpClient.builder().followRedirects().build(); - ResponseFuture f = client.get() - .setURL( "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_day.geojson" ) - .execute ( new ResponseHandler ( String.class ) { - - protected void receive ( HttpResponseStatus status, HttpHeaders headers, String response ) { - System.out.println ( "Here's the response: '" + response + "'" ); + new Thread() { + public void run() { + try { + hypocenters = pollHypocenters(); + MapFrame.getInstance().repaint(); + try { + Thread.sleep(REFRESH_INTERVAL); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); } - }); + } catch (ParserConfigurationException e) { + LOGGER.debug("ParserConfigurationException while retrieving hypocenters ({})", e); + } catch (SAXException e) { + LOGGER.debug("SAXException while retrieving hypocenters ({})", e); + } catch (IOException e) { + LOGGER.debug("IOException while retrieving hypocenters ({})", e); + } catch (DOMException e) { + LOGGER.debug("DOMException while retrieving hypocenters ({})", e); + } catch (ParseException e) { + LOGGER.debug("ParseException while retrieving hypocenters ({})", e); + } + } + }.start(); + } + + private List pollHypocenters() + throws ParserConfigurationException, SAXException, IOException, DOMException, ParseException { + List hypocenters = new ArrayList(); + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + Document doc = dBuilder.parse(URL); + doc.getDocumentElement().normalize(); + + NodeList events = doc.getElementsByTagName("event"); + LOGGER.debug("Got {} events.", events.getLength()); + + for (int idx = 0; idx < events.getLength(); idx++) { + + Element event = (Element) events.item(idx); + Element origin = (Element) event.getElementsByTagName("origin").item(0); + double lon = Double.parseDouble(((Element) origin.getElementsByTagName("longitude").item(0)) + .getElementsByTagName("value").item(0).getTextContent()); + double lat = Double.parseDouble(((Element) origin.getElementsByTagName("latitude").item(0)) + .getElementsByTagName("value").item(0).getTextContent()); + + Date date = dateFormat.parse(((Element) origin.getElementsByTagName("time").item(0)) + .getElementsByTagName("value").item(0).getTextContent()); + + double mag = Double.parseDouble(((Element) event.getElementsByTagName("mag").item(0)) + .getElementsByTagName("value").item(0).getTextContent()); + + Hypocenter h = new Hypocenter(); + h.location = new Point2D.Double(lon, lat); + h.text = "M" + mag; + h.depth = 0; + h.time = J2kSec.fromDate(date); + hypocenters.add(h); } + return hypocenters; + } + + public void draw(Graphics2D g2) { - public void draw(Graphics2D g2, GeoRange range, Projection projection, int widthPx, int heightPx, - int insetPx) { + if (hypocenters == null) + return; - for (Hypocenter hypocenter : hypocenters) { - LOGGER.debug("Hypo at {}, {}", hypocenter.lon, hypocenter.lat); + GeoRange range = panel.getRange(); + Projection projection = panel.getProjection(); + int widthPx = panel.getGraphWidth(); + int heightPx = panel.getGraphHeight(); + int insetPx = panel.getInset(); + + for (final ClickableGeoLabel label : hypocenters) { final Point2D.Double xy = - projection.forward(new Point2D.Double(-hypocenter.lon, hypocenter.lat)); + projection.forward(new Point2D.Double(label.location.x, label.location.y)); final double[] ext = range.getProjectedExtents(projection); final double dx = (ext[1] - ext[0]); final double dy = (ext[3] - ext[2]); @@ -59,9 +134,45 @@ public void draw(Graphics2D g2, GeoRange range, Projection projection, int width res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); g2.translate(res.x, res.y); - g2.setColor(Color.RED); - g2.drawOval(0, 0, 10, 10); + label.draw(g2); g2.translate(-res.x, -res.y); + } } + + public boolean mouseClicked(final MouseEvent e) { + + if (hypocenters == null) { + return false; + } + + boolean handled = false; + + GeoRange range = panel.getRange(); + Projection projection = panel.getProjection(); + int widthPx = panel.getGraphWidth(); + int heightPx = panel.getGraphHeight(); + int insetPx = panel.getInset(); + + for (ClickableGeoLabel label : hypocenters) { + final Rectangle r = label.getClickBox(); + + + final Point2D.Double xy = + projection.forward(new Point2D.Double(label.location.x, label.location.y)); + final double[] ext = range.getProjectedExtents(projection); + final double dx = (ext[1] - ext[0]); + final double dy = (ext[3] - ext[2]); + final Point2D.Double res = new Point2D.Double(); + res.x = (((xy.x - ext[0]) / dx) * widthPx + insetPx); + res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); + + r.translate((int) res.x, (int) res.y); + if (r.contains(e.getPoint())) { + label.mouseClicked(e); + } + } + + return handled; + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenters.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenters.java deleted file mode 100644 index c45be58c..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenters.java +++ /dev/null @@ -1,40 +0,0 @@ -package gov.usgs.volcanoes.swarm.map.hypocenters; - -import java.util.ArrayList; -import java.util.List; - -import gov.usgs.volcanoes.swarm.picker.HypocentersListener; - - -public class Hypocenters { - - private final static List hypocenters; - private final static List listeners; - private final static HypocenterPlotter plotter; - - static { - hypocenters = new ArrayList(); - listeners = new ArrayList(); - plotter = new HypocenterPlotter(hypocenters); - } - - /** uninstantiable */ - private Hypocenters() {} - - public static void addListener(HypocentersListener listener) { - listeners.add(listener); - } - - public static void add (Hypocenter hypocenter) { - hypocenters.add(hypocenter); - } - - public static Hypocenters getInstance() { - return HypocentersHolder.hypocenters; - } - - private static class HypocentersHolder { - public static Hypocenters hypocenters = new Hypocenters(); - } - -} diff --git a/src/main/java/nz/org/geonet/data/RSSHypocenters.java b/src/main/java/nz/org/geonet/data/RSSHypocenters.java index 086d305c..ad9402c9 100644 --- a/src/main/java/nz/org/geonet/data/RSSHypocenters.java +++ b/src/main/java/nz/org/geonet/data/RSSHypocenters.java @@ -7,8 +7,8 @@ import gov.usgs.volcanoes.core.time.J2kSec; import gov.usgs.volcanoes.core.time.Time; import gov.usgs.volcanoes.swarm.map.ClickableGeoLabel; -import gov.usgs.volcanoes.swarm.map.Hypocenter; import gov.usgs.volcanoes.swarm.map.LabelSource; +import gov.usgs.volcanoes.swarm.map.hypocenters.Hypocenter; import java.awt.geom.Point2D; import java.util.ArrayList; From 060b4752c5b2cb544cf66c4a0e8c2c17097458d6 Mon Sep 17 00:00:00 2001 From: tparker Date: Tue, 8 Mar 2016 13:00:56 -0900 Subject: [PATCH 06/67] Updated hypocenter plotter --- .../usgs/volcanoes/swarm/ConfigListener.java | 5 + .../java/gov/usgs/volcanoes/swarm/Swarm.java | 1 - .../gov/usgs/volcanoes/swarm/SwarmConfig.java | 53 ++- .../volcanoes/swarm/map/FdsnLabelSource.java | 116 ----- .../usgs/volcanoes/swarm/map/MapFrame.java | 15 +- .../usgs/volcanoes/swarm/map/MapLayer.java | 2 + .../usgs/volcanoes/swarm/map/MapPanel.java | 16 - .../swarm/map/MapSettingsDialog.java | 416 +++++++++--------- .../swarm/map/hypocenters/Hypocenter.java | 182 +++++--- ...enterPlotter.java => HypocenterLayer.java} | 107 +++-- .../map/hypocenters/HypocenterSource.java | 50 +++ ...enterPlotter.java => HypocenterLayer.java} | 41 +- .../volcanoes/swarm/picker/Hypocenters.java | 4 +- .../nz/org/geonet/data/RSSHypocenters.java | 106 ----- 14 files changed, 537 insertions(+), 577 deletions(-) create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/ConfigListener.java delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/map/FdsnLabelSource.java rename src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/{HypocenterPlotter.java => HypocenterLayer.java} (70%) create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterSource.java rename src/main/java/gov/usgs/volcanoes/swarm/picker/{HypocenterPlotter.java => HypocenterLayer.java} (52%) delete mode 100644 src/main/java/nz/org/geonet/data/RSSHypocenters.java diff --git a/src/main/java/gov/usgs/volcanoes/swarm/ConfigListener.java b/src/main/java/gov/usgs/volcanoes/swarm/ConfigListener.java new file mode 100644 index 00000000..deceaaf1 --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/ConfigListener.java @@ -0,0 +1,5 @@ +package gov.usgs.volcanoes.swarm; + +public interface ConfigListener { + public void settingsChanged(); +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java b/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java index b7e18b00..38e360d8 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java @@ -105,7 +105,6 @@ public Swarm(final String[] args) { checkJavaVersion(); setupGlobalKeys(); createUI(); - new gov.usgs.volcanoes.swarm.map.hypocenters.HypocenterPlotter(); } private void checkJavaVersion() { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/SwarmConfig.java b/src/main/java/gov/usgs/volcanoes/swarm/SwarmConfig.java index ee376339..4cc0ecfa 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/SwarmConfig.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/SwarmConfig.java @@ -1,8 +1,5 @@ package gov.usgs.volcanoes.swarm; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.awt.Color; import java.io.File; import java.util.ArrayList; @@ -16,21 +13,30 @@ import java.util.TimeZone; import java.util.TreeMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import gov.usgs.plot.map.WMSGeoImageSet; import gov.usgs.volcanoes.core.configfile.ConfigFile; import gov.usgs.volcanoes.core.util.StringUtils; import gov.usgs.volcanoes.swarm.data.DataSourceType; import gov.usgs.volcanoes.swarm.data.SeismicDataSource; +import gov.usgs.volcanoes.swarm.map.hypocenters.HypocenterLayer; +import gov.usgs.volcanoes.swarm.map.hypocenters.HypocenterSource; /** - * Swarm configuration class. - * + * Swarm configuration class. + * + * TODO: This is getting our of hand. Extract configs for individual components. e.g. map + * * @author Dan Cervelli */ public class SwarmConfig { private static final Logger LOGGER = LoggerFactory.getLogger(SwarmConfig.class); + private final List listeners; + private static String[] DEFAULT_SERVERS = new String[] {"AVO Winston;wws:pubavo1.wr.usgs.gov:16022:10000:1" // "IRIS DMC - New @@ -86,6 +92,7 @@ public class SwarmConfig { public int mapWidth; public int mapHeight; public boolean mapMaximized; + private HypocenterSource hypocenterSource; public double mapScale; public double mapLongitude; @@ -111,15 +118,34 @@ public class SwarmConfig { public String wmsLayer; public String wmsStyles; - public String labelSource; public String fdsnDataselectURL; public String fdsnStationURL; - private SwarmConfig() {} + private SwarmConfig() { + listeners = new ArrayList(); + } + public void addListener(ConfigListener configListener) { + listeners.add(configListener); + } + + private void notifyListeners() { + for (ConfigListener listener : listeners) { + listener.settingsChanged(); + } + } public static SwarmConfig getInstance() { return SwarmConfigHolder.swarmConfig; } + + public void setHypocenterSource(HypocenterSource hypocenterSource) { + this.hypocenterSource = hypocenterSource; + notifyListeners(); + } + + public HypocenterSource getHypocenterSource() { + return hypocenterSource; + } public void createConfig(final String[] args) { LOGGER.info("current directory: " + System.getProperty("user.dir")); @@ -261,11 +287,10 @@ public void assignMetadataSource(final Collection channels, } /** - * Sets Swarm configuration variables based on the contents of a ConfigFile; - * sets default values if missing. + * Sets Swarm configuration variables based on the contents of a ConfigFile; sets default values + * if missing. * - * @param config - * the configuration information + * @param config the configuration information */ public void parseConfig(final ConfigFile config) { configFilename = config.getString("configFile"); @@ -341,8 +366,8 @@ public void parseConfig(final ConfigFile config) { StringUtils.stringToString(config.getString("wmsLayer"), WMSGeoImageSet.DEFAULT_LAYER); wmsStyles = StringUtils.stringToString(config.getString("wmsStyles"), WMSGeoImageSet.DEFAULT_STYLE); - - labelSource = StringUtils.stringToString(config.getString("labelSource"), ""); + + hypocenterSource = HypocenterSource.valueOf(StringUtils.stringToString(config.getString("hypocenterSource"), "NONE")); fdsnDataselectURL = StringUtils.stringToString(config.getString("fdsnDataselectURL"), "http://service.iris.edu/fdsnws/dataselect/1/query"); @@ -497,7 +522,7 @@ public ConfigFile toConfigFile() { config.put("wmsLayer", wmsLayer); config.put("wmsStyles", wmsStyles); - config.put("labelSource", labelSource); + config.put("hypocenterSource", hypocenterSource.name()); config.put("fdsnDataselectURL", fdsnDataselectURL); config.put("fdsnStationURL", fdsnStationURL); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/FdsnLabelSource.java b/src/main/java/gov/usgs/volcanoes/swarm/map/FdsnLabelSource.java deleted file mode 100644 index 6774fc90..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/FdsnLabelSource.java +++ /dev/null @@ -1,116 +0,0 @@ -package gov.usgs.volcanoes.swarm.map; - -import java.awt.geom.Point2D; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.TimeZone; - -import javax.xml.stream.XMLStreamException; - -import edu.sc.seis.seisFile.SeisFileException; -import edu.sc.seis.seisFile.fdsnws.FDSNEventQuerier; -import edu.sc.seis.seisFile.fdsnws.FDSNEventQueryParams; -import edu.sc.seis.seisFile.fdsnws.FDSNWSException; -import edu.sc.seis.seisFile.fdsnws.quakeml.Event; -import edu.sc.seis.seisFile.fdsnws.quakeml.EventIterator; -import edu.sc.seis.seisFile.fdsnws.quakeml.Magnitude; -import edu.sc.seis.seisFile.fdsnws.quakeml.Origin; -import edu.sc.seis.seisFile.fdsnws.quakeml.QuakeMLTagNames; -import edu.sc.seis.seisFile.fdsnws.quakeml.Quakeml; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import gov.usgs.proj.GeoRange; -import gov.usgs.volcanoes.core.time.J2kSec; -import gov.usgs.volcanoes.core.time.Time; -import gov.usgs.volcanoes.swarm.map.hypocenters.Hypocenter; - -/* - * A class to retrieve events from IRIS for plotting on the map. - * - * @author: Tom Parker - */ -public class FdsnLabelSource implements LabelSource { - - private static final Logger LOGGER = LoggerFactory.getLogger(FdsnLabelSource.class); - - - public List getLabels() { - - FDSNEventQueryParams queryParams = new FDSNEventQueryParams(); - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); - sdf.setTimeZone(TimeZone.getTimeZone("GMT")); - - MapFrame mapFrame = MapFrame.getInstance(); - if (mapFrame == null) - return null; - GeoRange range = mapFrame.getRange(); - - float minLat = (float) range.getSouth(); - float maxLat = (float) range.getNorth(); - float minLon = (float) range.getWest(); - float maxLon = (float) range.getEast(); - - Date endTime = new Date(System.currentTimeMillis()); - Date startTime = new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000L); - - queryParams.area(minLat, maxLat, minLon, maxLon).setStartTime(startTime).setEndTime(endTime) - .setMaxDepth(100).setMinMagnitude(1).setOrderBy(FDSNEventQueryParams.ORDER_TIME_ASC); - - FDSNEventQuerier querier = new FDSNEventQuerier(queryParams); - // System.err.println("::" + querier.getConnectionUri()); - Quakeml quakeml = null; - try { - quakeml = querier.getQuakeML(); - } catch (FDSNWSException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - return null; - } - if (!quakeml.checkSchemaVersion()) { - System.out.println(""); - System.out.println( - "WARNING: XmlSchema of this document does not match this code, results may be incorrect."); - System.out.println("XmlSchema (code): " + QuakeMLTagNames.CODE_MAIN_SCHEMA_VERSION); - System.out.println("XmlSchema (doc): " + quakeml.getSchemaVersion()); - } - - List hypos = new ArrayList(); - EventIterator eIt = quakeml.getEventParameters().getEvents(); - try { - while (eIt.hasNext()) { - Event e = eIt.next(); - Origin o = e.getOriginList().get(0); - Magnitude m = e.getMagnitudeList().get(0); - System.out.println(o.getLatitude() + "/" + o.getLongitude() + " " + m.getMag().getValue() - + " " + m.getType() + " " + o.getTime().getValue()); - Hypocenter h = new Hypocenter(); - double lat = o.getLatitude().getValue(); - double lon = o.getLongitude().getValue(); - h.location = new Point2D.Double(lon, lat); - h.text = "M" + m.getMag().getValue(); - h.depth = o.getDepth().getValue(); - try { - h.time = J2kSec.parse(Time.FDSN_TIME_FORMAT, o.getTime().getValue()); - } catch (ParseException e1) { - LOGGER.info("Can't parse label date: {}", o.getTime().getValue()); - continue; - } - hypos.add(h); - - } - } catch (XMLStreamException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (SeisFileException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - return hypos; - } -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapFrame.java index be5d0580..96ead0d8 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapFrame.java @@ -102,18 +102,29 @@ public class MapFrame extends SwarmFrame implements Runnable, Kioskable, SwarmOp private Border border; + private MapSettingsDialog mapSettingsDialog; + private MapFrame() { super("Map", true, true, true, false); this.setFocusable(true); UiTime.touchTime(); + mapSettingsDialog = new MapSettingsDialog(this); + createUI(); + addLayers(); updateThread = new Thread(this, "Map Update"); updateThread.start(); SwarmOptions.addOptionsListener(this); } + private void addLayers() { + MapLayer mapLayer = new gov.usgs.volcanoes.swarm.map.hypocenters.HypocenterLayer(); + mapLayer.setMapPanel(mapPanel); + addLayer(mapLayer); + } + public static MapFrame getInstance() { return MapFrameHolder.mapFrame; } @@ -209,8 +220,8 @@ private void createToolbar() { optionsButton = SwarmUtil.createToolBarButton(Icons.settings, "Map options", new ActionListener() { public void actionPerformed(final ActionEvent e) { - final MapSettingsDialog msd = MapSettingsDialog.getInstance(MapFrame.this); - msd.setVisible(true); + mapSettingsDialog.setToCurrent(); + mapSettingsDialog.setVisible(true); } }); toolbar.add(optionsButton); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapLayer.java index 915d4aab..f50496d8 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapLayer.java @@ -11,5 +11,7 @@ public interface MapLayer { public void draw(Graphics2D g2); public boolean mouseClicked(MouseEvent e); + public void setMapPanel(MapPanel mapPanel); + public void stop(); } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java index 1e30adeb..c8de2ede 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java @@ -332,22 +332,6 @@ public void keyTyped(final KeyEvent e) {} pane.add(mapImagePanel, new Integer(10)); add(pane, BorderLayout.CENTER); - loadLabels(); - - } - - public void loadLabels() { - if (swarmConfig.labelSource.isEmpty()) - return; - - try { - final Class cl = Class.forName(swarmConfig.labelSource); - final LabelSource src = (LabelSource) cl.newInstance(); - repaint(); - } catch (final Exception e) { - LOGGER.warn("Can't load labelSource {}", swarmConfig.labelSource); - e.printStackTrace(); - } } public void wavesToClipboard() { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapSettingsDialog.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapSettingsDialog.java index 50f258ef..63d9b41d 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapSettingsDialog.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapSettingsDialog.java @@ -8,235 +8,231 @@ import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JColorChooser; +import javax.swing.JComboBox; import javax.swing.JDialog; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JTextField; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.FormLayout; -import gov.usgs.volcanoes.swarm.SwarmConfig; import gov.usgs.volcanoes.swarm.SwarmDialog; import gov.usgs.volcanoes.swarm.map.MapPanel.LabelSetting; +import gov.usgs.volcanoes.swarm.map.hypocenters.HypocenterSource; /** * * @author Dan Cervelli */ public class MapSettingsDialog extends SwarmDialog { - public static final long serialVersionUID = -1; - - private MapFrame map; - - private JPanel dialogPanel; - - private JTextField scale; - private JTextField longitude; - private JTextField latitude; - - private JTextField lineWidth; - private JTextField refreshInterval; - private ButtonGroup labelGroup; - private JRadioButton someLabels; - private JRadioButton allLabels; - private JRadioButton noLabels; - private JButton mapLine; - private JColorChooser lineChooser; - - private JTextField labelSource; - - private static MapSettingsDialog dialog; - - private MapSettingsDialog() { - super(applicationFrame, "Map Settings", true); - createUI(); - setSizeAndLocation(); - } - - private void createFields() { - latitude = new JTextField(); - longitude = new JTextField(); - scale = new JTextField(); - lineWidth = new JTextField(); - refreshInterval = new JTextField(); - labelGroup = new ButtonGroup(); - someLabels = new JRadioButton("Some"); - allLabels = new JRadioButton("All"); - noLabels = new JRadioButton("None"); - labelGroup.add(someLabels); - labelGroup.add(allLabels); - labelGroup.add(noLabels); - labelSource = new JTextField(); - mapLine = new JButton(); - - lineChooser = new JColorChooser(); - lineChooser.setPreviewPanel(new MapLinePreview()); - - final ActionListener okActionListener = new ActionListener() { - public void actionPerformed(ActionEvent actionEvent) { -// swarmConfig.mapLineColor = lineChooser.getC - } - }; - - mapLine.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - JDialog dialog = JColorChooser.createDialog(applicationFrame, "Map Line Settings", true, lineChooser, - okActionListener, null); - dialog.setVisible(true); - } - }); - - } - - protected void createUI() { - super.createUI(); - createFields(); - - FormLayout layout = new FormLayout("right:max(30dlu;pref), 3dlu, 50dlu, 3dlu, 30dlu", ""); - - DefaultFormBuilder builder = new DefaultFormBuilder(layout); - builder.setDefaultDialogBorder(); - - builder.appendSeparator("Location"); - builder.append("Longitude:"); - builder.append(longitude); - builder.append("degrees"); - builder.nextLine(); - builder.append("Latitude:"); - builder.append(latitude); - builder.append("degrees"); - builder.nextLine(); - builder.append("Scale:"); - builder.append(scale); - builder.append("m/pixel"); - builder.nextLine(); - - builder.appendSeparator("Options"); - builder.append("Line:"); - builder.append(mapLine); - builder.nextLine(); - builder.append("Refresh Interval:"); - builder.append(refreshInterval); - builder.append(" seconds"); - builder.nextLine(); - builder.append("Channel Labels:"); - builder.append(noLabels); - builder.nextLine(); - builder.append(" "); - builder.append(someLabels); - builder.nextLine(); - builder.append(" "); - builder.append(allLabels); - builder.nextLine(); - builder.append("Click Labels:"); - builder.append(labelSource, 3); - - dialogPanel = builder.getPanel(); - mainPanel.add(dialogPanel, BorderLayout.CENTER); - } - - public static MapSettingsDialog getInstance(MapFrame mf) { - if (dialog == null) - dialog = new MapSettingsDialog(); - - dialog.setMapFrame(mf); - dialog.setToCurrent(); - return dialog; - } - - public void setVisible(boolean b) { - if (b) - this.getRootPane().setDefaultButton(okButton); - super.setVisible(b); + public static final long serialVersionUID = -1; + + private static final Logger LOGGER = LoggerFactory.getLogger(MapSettingsDialog.class); + + private JPanel dialogPanel; + + private JTextField scale; + private JTextField longitude; + private JTextField latitude; + + private JTextField lineWidth; + private JTextField refreshInterval; + private ButtonGroup labelGroup; + private JRadioButton someLabels; + private JRadioButton allLabels; + private JRadioButton noLabels; + private JButton mapLine; + private JColorChooser lineChooser; + private JComboBox hypocenterSource; + + private MapFrame mapFrame; + + public MapSettingsDialog(MapFrame mapFrame) { + super(applicationFrame, "Map Settings", true); + this.mapFrame = mapFrame; + createUI(); + setToCurrent(); + setSizeAndLocation(); + } + + private void createFields() { + latitude = new JTextField(); + longitude = new JTextField(); + scale = new JTextField(); + lineWidth = new JTextField(); + refreshInterval = new JTextField(); + labelGroup = new ButtonGroup(); + someLabels = new JRadioButton("Some"); + allLabels = new JRadioButton("All"); + noLabels = new JRadioButton("None"); + labelGroup.add(someLabels); + labelGroup.add(allLabels); + labelGroup.add(noLabels); + mapLine = new JButton(); + hypocenterSource = new JComboBox(HypocenterSource.values()); + + lineChooser = new JColorChooser(); + lineChooser.setPreviewPanel(new MapLinePreview()); + + final ActionListener okActionListener = new ActionListener() { + public void actionPerformed(ActionEvent actionEvent) { + // swarmConfig.mapLineColor = lineChooser.getC + } + }; + + mapLine.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JDialog dialog = JColorChooser.createDialog(applicationFrame, "Map Line Settings", true, + lineChooser, okActionListener, null); + dialog.setVisible(true); + } + }); + + } + + protected void createUI() { + super.createUI(); + createFields(); + + FormLayout layout = new FormLayout("right:max(30dlu;pref), 3dlu, 50dlu, 3dlu, 30dlu", ""); + + DefaultFormBuilder builder = new DefaultFormBuilder(layout); + builder.setDefaultDialogBorder(); + + builder.appendSeparator("Location"); + builder.append("Longitude:"); + builder.append(longitude); + builder.append("degrees"); + builder.nextLine(); + builder.append("Latitude:"); + builder.append(latitude); + builder.append("degrees"); + builder.nextLine(); + builder.append("Scale:"); + builder.append(scale); + builder.append("m/pixel"); + builder.nextLine(); + + builder.appendSeparator("Options"); + builder.append("Line:"); + builder.append(mapLine); + builder.nextLine(); + builder.append("Refresh Interval:"); + builder.append(refreshInterval); + builder.append(" seconds"); + builder.nextLine(); + builder.append("Channel Labels:"); + builder.append(noLabels); + builder.nextLine(); + builder.append(" "); + builder.append(someLabels); + builder.nextLine(); + builder.append(" "); + builder.append(allLabels); + + builder.nextLine(); + builder.append("Hypocenter Source:"); + builder.append(hypocenterSource, 3); + + dialogPanel = builder.getPanel(); + mainPanel.add(dialogPanel, BorderLayout.CENTER); + + } + + public void setVisible(boolean b) { + if (b) + this.getRootPane().setDefaultButton(okButton); + super.setVisible(b); + } + + public void setToCurrent() { + MapPanel panel = mapFrame.getMapPanel(); + if (panel == null) + return; + + longitude.setText(String.format("%.4f", panel.getCenter().x)); + latitude.setText(String.format("%.4f", panel.getCenter().y)); + scale.setText(String.format("%.1f", panel.getScale())); + lineWidth.setText(Integer.toString(swarmConfig.mapLineWidth)); + refreshInterval.setText(String.format("%.2f", mapFrame.getRefreshInterval() / 1000.0)); + LabelSetting ls = panel.getLabelSetting(); + switch (ls) { + case ALL: + allLabels.setSelected(true); + break; + case SOME: + someLabels.setSelected(true); + break; + case NONE: + noLabels.setSelected(true); + break; } - - public void setMapFrame(MapFrame mf) { - map = mf; - setToCurrent(); - } - - public void setToCurrent() { - MapPanel panel = map.getMapPanel(); - longitude.setText(String.format("%.4f", panel.getCenter().x)); - latitude.setText(String.format("%.4f", panel.getCenter().y)); - scale.setText(String.format("%.1f", panel.getScale())); - lineWidth.setText(Integer.toString(swarmConfig.mapLineWidth)); - refreshInterval.setText(String.format("%.2f", map.getRefreshInterval() / 1000.0)); - LabelSetting ls = panel.getLabelSetting(); - switch (ls) { - case ALL: - allLabels.setSelected(true); - break; - case SOME: - someLabels.setSelected(true); - break; - case NONE: - noLabels.setSelected(true); - break; - } - labelSource.setText(swarmConfig.labelSource); + hypocenterSource.setSelectedItem(swarmConfig.getHypocenterSource()); + } + + protected void wasOK() { + try { + MapPanel panel = mapFrame.getMapPanel(); + LabelSetting ls = LabelSetting.ALL; + if (someLabels.isSelected()) + ls = LabelSetting.SOME; + else if (noLabels.isSelected()) + ls = LabelSetting.NONE; + panel.setLabelSetting(ls); + Point2D.Double center = new Point2D.Double(); + center.x = Double.parseDouble(longitude.getText()); + center.y = Double.parseDouble(latitude.getText()); + double sc = Double.parseDouble(scale.getText()); + panel.setCenterAndScale(center, sc); + swarmConfig.mapLineWidth = Integer.parseInt(lineWidth.getText()); + mapFrame.setRefreshInterval(Math.round(Double.parseDouble(refreshInterval.getText()) * 1000)); + + swarmConfig.setHypocenterSource((HypocenterSource) hypocenterSource.getSelectedItem()); + } catch (Exception e) { + LOGGER.debug("Exception caught while accepting map options."); + e.printStackTrace(); } - - protected void wasOK() { - try { - swarmConfig.labelSource = labelSource.getText(); - MapPanel panel = map.getMapPanel(); - LabelSetting ls = LabelSetting.ALL; - if (someLabels.isSelected()) - ls = LabelSetting.SOME; - else if (noLabels.isSelected()) - ls = LabelSetting.NONE; - panel.setLabelSetting(ls); - Point2D.Double center = new Point2D.Double(); - center.x = Double.parseDouble(longitude.getText()); - center.y = Double.parseDouble(latitude.getText()); - double sc = Double.parseDouble(scale.getText()); - panel.setCenterAndScale(center, sc); - swarmConfig.mapLineWidth = Integer.parseInt(lineWidth.getText()); - map.setRefreshInterval(Math.round(Double.parseDouble(refreshInterval.getText()) * 1000)); - panel.loadLabels(); - } catch (Exception e) { - e.printStackTrace(); - // don't do anything here since all validation should occur in - // allowOK() -- this is just worst case. - } - } - - protected boolean allowOK() { - String message = null; - try { - message = "Invalid refresh interval; legal values are between 0 and 3600, 0 to refresh continuously."; - double ri = Double.parseDouble(refreshInterval.getText()); - if (ri < 0 || ri > 3600) - throw new NumberFormatException(); - - message = "Invalid longitude; legal values are between -180 and 180."; - double lon = Double.parseDouble(longitude.getText()); - if (lon < -180 || lon > 180) - throw new NumberFormatException(); - - message = "Invalid latitude; legal values are between -90 and 90."; - double lat = Double.parseDouble(latitude.getText()); - if (lat < -90 || lat > 90) - throw new NumberFormatException(); - - message = "Invalid scale; legal values are greater than 0."; - double sc = Double.parseDouble(scale.getText()); - if (sc <= 0) - throw new NumberFormatException(); - - message = "Invalid line width; legal values are integers greater than 0."; - int i = Integer.parseInt(lineWidth.getText()); - if (i <= 0) - throw new NumberFormatException(); - - return true; - } catch (Exception e) { - JOptionPane.showMessageDialog(this, message, "Options Error", JOptionPane.ERROR_MESSAGE); - } - return false; + } + + protected boolean allowOK() { + String message = null; + try { + message = + "Invalid refresh interval; legal values are between 0 and 3600, 0 to refresh continuously."; + double ri = Double.parseDouble(refreshInterval.getText()); + if (ri < 0 || ri > 3600) + throw new NumberFormatException(); + + message = "Invalid longitude; legal values are between -180 and 180."; + double lon = Double.parseDouble(longitude.getText()); + if (lon < -180 || lon > 180) + throw new NumberFormatException(); + + message = "Invalid latitude; legal values are between -90 and 90."; + double lat = Double.parseDouble(latitude.getText()); + if (lat < -90 || lat > 90) + throw new NumberFormatException(); + + message = "Invalid scale; legal values are greater than 0."; + double sc = Double.parseDouble(scale.getText()); + if (sc <= 0) + throw new NumberFormatException(); + + message = "Invalid line width; legal values are integers greater than 0."; + int i = Integer.parseInt(lineWidth.getText()); + if (i <= 0) + throw new NumberFormatException(); + + return true; + } catch (Exception e) { + JOptionPane.showMessageDialog(this, message, "Options Error", JOptionPane.ERROR_MESSAGE); } + return false; + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java index e8195992..db517761 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java @@ -1,81 +1,135 @@ package gov.usgs.volcanoes.swarm.map.hypocenters; -import gov.usgs.math.Geometry; -import gov.usgs.plot.render.DataPointRenderer; -import gov.usgs.util.Pair; -import gov.usgs.volcanoes.swarm.Metadata; -import gov.usgs.volcanoes.swarm.SwarmConfig; -import gov.usgs.volcanoes.swarm.map.ClickableGeoLabel; -import gov.usgs.volcanoes.swarm.wave.MultiMonitor; -import gov.usgs.volcanoes.swarm.wave.SwarmMultiMonitors; - import java.awt.BasicStroke; import java.awt.Color; +import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.event.MouseEvent; +import java.awt.geom.Ellipse2D; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import gov.usgs.plot.render.DataPointRenderer; +import gov.usgs.util.Pair; +import gov.usgs.volcanoes.core.time.J2kSec; +import gov.usgs.volcanoes.swarm.Metadata; +import gov.usgs.volcanoes.swarm.SwarmConfig; +import gov.usgs.volcanoes.swarm.map.ClickableGeoLabel; +import gov.usgs.volcanoes.swarm.picker.Phase; +import gov.usgs.volcanoes.swarm.picker.Phase.Builder; +import gov.usgs.volcanoes.swarm.picker.Phase.FirstMotion; +import gov.usgs.volcanoes.swarm.picker.Phase.Onset; +import gov.usgs.volcanoes.swarm.picker.Phase.PhaseType; +import gov.usgs.volcanoes.swarm.wave.MultiMonitor; +import gov.usgs.volcanoes.swarm.wave.SwarmMultiMonitors; + /** * * @author Dan Cervelli + * @author Tom Parker */ -public class Hypocenter extends ClickableGeoLabel -{ - public double time; - public double depth; - public double magnitude; - - private static SwarmConfig swarmConfig; - - public Hypocenter() - { - swarmConfig = SwarmConfig.getInstance(); - - DataPointRenderer r = new DataPointRenderer(); - r.antiAlias = true; - r.stroke = new BasicStroke(1.2f); - r.filled = true; - r.paint = Color.RED; - r.color = Color.yellow; - r.shape = Geometry.STAR_10; - marker = r; - } - - @Override - public Rectangle getClickBox() - { - return new Rectangle(-7, -7, 17, 17); - } +public class Hypocenter extends ClickableGeoLabel { + private static final int ONE_HOUR = 60 * 60; + private static final int ONE_DAY = ONE_HOUR * 24; + private static final int ONE_WEEK = ONE_DAY * 7; + + private static final SwarmConfig swarmConfig = SwarmConfig.getInstance(); + + private final double time; + private final double depth; + private final double magnitude; + private final DataPointRenderer renderer; + + private Hypocenter(Builder builder) { + time = builder.time; + depth = builder.depth; + magnitude = builder.magnitude; + + renderer = new DataPointRenderer(); + renderer.antiAlias = true; + renderer.stroke = new BasicStroke(1.2f); + renderer.filled = true; + renderer.color = Color.LIGHT_GRAY; + // r.shape = Geometry.STAR_10; + renderer.shape = new Ellipse2D.Float(0f, 0f, 7f, 7f); + marker = renderer; + } + + @Override + public Rectangle getClickBox() { + return new Rectangle(-7, -7, 17, 17); + } + + public void setColor(Color color) { + renderer.paint = color; + } + + @Override + public void mouseClicked(MouseEvent e) { + Map metadata = swarmConfig.getMetadata(); + List> nrst = + Metadata.findNearest(swarmConfig.getMetadata(), location, true); + Set cleared = new HashSet(); + if (nrst != null) { + for (int i = 0, total = 0; i < nrst.size() && total < 10; i++) { + String ch = nrst.get(i).item2; + if (ch.matches(".* ..Z .*")) { + Metadata md = metadata.get(ch); + MultiMonitor mm = SwarmMultiMonitors.getMonitor(md.source); + if (!cleared.contains(mm)) { + mm.removeAllWaves(); + cleared.add(mm); + } + mm.addChannel(ch); + mm.setVisible(true); + mm.setPauseStartTime(time - 4); + total++; + } + } + } + } + + public void draw(Graphics2D g2) { + double age = J2kSec.now() - time; + + if (age < ONE_HOUR) { + renderer.paint = Color.RED; + } else if (age < ONE_DAY) { + renderer.paint = Color.ORANGE; + } else if (age < ONE_WEEK) { + renderer.paint = Color.YELLOW; + } else { + renderer.paint = Color.WHITE; + } + super.draw(g2); + } + + public static class Builder { + private double time; + private double depth; + private double magnitude; + + public Builder() {} + + public Builder magnitude(double magnitude) { + this.magnitude = magnitude; + return this; + } + + public Builder depth(double depth) { + this.depth = depth; + return this; + } + + public Builder time(double time) { + this.time = time; + return this; + } - @Override - public void mouseClicked(MouseEvent e) - { - Map metadata = swarmConfig.getMetadata(); - List> nrst = Metadata.findNearest(swarmConfig.getMetadata(), location, true); - Set cleared = new HashSet(); - if (nrst != null) - { - for (int i = 0, total = 0; i < nrst.size() && total < 10; i++) - { - String ch = nrst.get(i).item2; - if (ch.matches(".* ..Z .*")) - { - Metadata md = metadata.get(ch); - MultiMonitor mm = SwarmMultiMonitors.getMonitor(md.source); - if (!cleared.contains(mm)) - { - mm.removeAllWaves(); - cleared.add(mm); - } - mm.addChannel(ch); - mm.setVisible(true); - mm.setPauseStartTime(time - 4); - total++; - } - } - } - } + public Hypocenter build() { + return new Hypocenter(this); + } + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterPlotter.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java similarity index 70% rename from src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterPlotter.java rename to src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java index 9e8a3f28..e9d9a352 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterPlotter.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java @@ -1,13 +1,6 @@ package gov.usgs.volcanoes.swarm.map.hypocenters; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.DOMException; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - +import java.awt.Color; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.event.MouseEvent; @@ -23,65 +16,97 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + import gov.usgs.proj.GeoRange; import gov.usgs.proj.Projection; import gov.usgs.volcanoes.core.time.J2kSec; +import gov.usgs.volcanoes.swarm.ConfigListener; +import gov.usgs.volcanoes.swarm.SwarmConfig; import gov.usgs.volcanoes.swarm.map.ClickableGeoLabel; import gov.usgs.volcanoes.swarm.map.MapFrame; import gov.usgs.volcanoes.swarm.map.MapLayer; import gov.usgs.volcanoes.swarm.map.MapPanel; -public final class HypocenterPlotter implements MapLayer { +public final class HypocenterLayer implements MapLayer, ConfigListener { private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSX"; - - private static final Logger LOGGER = LoggerFactory.getLogger(HypocenterPlotter.class); + + private static final Logger LOGGER = LoggerFactory.getLogger(HypocenterLayer.class); private static final int REFRESH_INTERVAL = 5 * 60 * 1000; private List hypocenters; - private final String URL = - "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_day.quakeml"; + private boolean run = true; private MapPanel panel; private SimpleDateFormat dateFormat; - public HypocenterPlotter() { + private Thread refreshThread; + private final SwarmConfig swarmConfig; + + public HypocenterLayer() { dateFormat = new SimpleDateFormat(DATE_FORMAT); - panel = MapFrame.getInstance().addLayer(this); + swarmConfig = SwarmConfig.getInstance(); + swarmConfig.addListener(this); startPolling(); } + public void setMapPanel(MapPanel mapPanel) { + panel = mapPanel; + } + private void startPolling() { - new Thread() { + + Runnable r = new Runnable() { public void run() { - try { - hypocenters = pollHypocenters(); + while (run) { + try { + hypocenters = pollHypocenters(); + } catch (ParserConfigurationException e) { + LOGGER.debug("ParserConfigurationException while retrieving hypocenters ({})", e); + } catch (SAXException e) { + hypocenters = null; + LOGGER.debug("SAXException while retrieving hypocenters. Typically this means there were no hypocenters to display."); + } catch (IOException e) { + LOGGER.debug("IOException while retrieving hypocenters ({})", e); + } catch (DOMException e) { + LOGGER.debug("DOMException while retrieving hypocenters ({})", e); + } catch (ParseException e) { + LOGGER.debug("ParseException while retrieving hypocenters ({})", e); + } + MapFrame.getInstance().repaint(); + try { Thread.sleep(REFRESH_INTERVAL); } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + LOGGER.debug("hypocenter update interupted."); } - } catch (ParserConfigurationException e) { - LOGGER.debug("ParserConfigurationException while retrieving hypocenters ({})", e); - } catch (SAXException e) { - LOGGER.debug("SAXException while retrieving hypocenters ({})", e); - } catch (IOException e) { - LOGGER.debug("IOException while retrieving hypocenters ({})", e); - } catch (DOMException e) { - LOGGER.debug("DOMException while retrieving hypocenters ({})", e); - } catch (ParseException e) { - LOGGER.debug("ParseException while retrieving hypocenters ({})", e); + } } - }.start(); + }; + refreshThread = new Thread(r); + refreshThread.start(); } private List pollHypocenters() throws ParserConfigurationException, SAXException, IOException, DOMException, ParseException { + LOGGER.debug("Polling hypocenters"); + HypocenterSource hypocenterSource = swarmConfig.getHypocenterSource(); + if (hypocenterSource == HypocenterSource.NONE) { + return null; + } + List hypocenters = new ArrayList(); DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); - Document doc = dBuilder.parse(URL); + Document doc = dBuilder.parse(hypocenterSource.getUrl()); doc.getDocumentElement().normalize(); NodeList events = doc.getElementsByTagName("event"); @@ -98,22 +123,19 @@ private List pollHypocenters() Date date = dateFormat.parse(((Element) origin.getElementsByTagName("time").item(0)) .getElementsByTagName("value").item(0).getTextContent()); - + double mag = Double.parseDouble(((Element) event.getElementsByTagName("mag").item(0)) .getElementsByTagName("value").item(0).getTextContent()); - Hypocenter h = new Hypocenter(); + Hypocenter h = new Hypocenter.Builder().time(J2kSec.fromDate(date)).build(); h.location = new Point2D.Double(lon, lat); h.text = "M" + mag; - h.depth = 0; - h.time = J2kSec.fromDate(date); hypocenters.add(h); } return hypocenters; } public void draw(Graphics2D g2) { - if (hypocenters == null) return; @@ -123,7 +145,7 @@ public void draw(Graphics2D g2) { int heightPx = panel.getGraphHeight(); int insetPx = panel.getInset(); - for (final ClickableGeoLabel label : hypocenters) { + for (final Hypocenter label : hypocenters) { final Point2D.Double xy = projection.forward(new Point2D.Double(label.location.x, label.location.y)); final double[] ext = range.getProjectedExtents(projection); @@ -136,7 +158,6 @@ public void draw(Graphics2D g2) { g2.translate(res.x, res.y); label.draw(g2); g2.translate(-res.x, -res.y); - } } @@ -175,4 +196,14 @@ public boolean mouseClicked(final MouseEvent e) { return handled; } + + public void settingsChanged() { + LOGGER.debug("hypocenter plotter sees changed settings."); + refreshThread.interrupt(); + } + + public void stop() { + run = false; + refreshThread.interrupt(); + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterSource.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterSource.java new file mode 100644 index 00000000..bb7ed5aa --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterSource.java @@ -0,0 +1,50 @@ +package gov.usgs.volcanoes.swarm.map.hypocenters; + +public enum HypocenterSource { + NONE("None", null), + HR_SIG("1 Hour - Significant", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/significant_hour.quakeml"), + HR_45("1 Hour - M4.5+", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/4.5_hour.quakeml"), + HR_25("1 Hour - M2.5+", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_hour.quakeml"), + HR_1("1 Hour - M1.0+", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/1.0_hour.quakeml") , + HR_ALL("1 Hour - All", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.quakeml"), + DAY_SIG("1 Day - Significant", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/significant_day.quakeml"), + DAY_45("1 Day - M4.5+", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/4.5_day.quakeml"), + DAY_25("1 Day - M2.5+", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_day.quakeml"), + DAY_1("1 Day - M1.0+", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/1.0_day.quakeml"), + DAY_ALL("1 Day - All", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.quakeml"), + WEEK_SIG("1 Week - Significant", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/significant_week.quakeml"), + WEEK_45("1 Week - M4.5+", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/4.5_week.quakeml"), + WEEK_25("1 Week - M2.5+", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_week.quakeml"), + WEEK_1("1 Week - M1.0+", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/1.0_week.quakeml"), + WEEK_ALL("1 Week - All", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/All_week.quakeml"), + MONTH_SIG("1 Month - Significant", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/significant_month.quakeml"), + MONTH_45("1 Month - M4.5+", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/4.5_month.quakeml"), + MONTH_25("1 Month - M2.5+", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_month.quakeml"), + MONTH_1("1 Month - M1.0+", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/1.0_month.quakeml"), + MONTH_ALL("1 Month - All", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/All_month.quakeml"); + + private String label; + private String url; + + private HypocenterSource(String label, String url) { + this.label = label; + this.url = url; + } + + public String toString() { + return label; + } + + public String getUrl() { + return url; + } + + public static HypocenterSource fromUrl(String hypocenterUrl) { + for (HypocenterSource source : HypocenterSource.values()) { + if (source.url == hypocenterUrl) { + return source; + } + } + throw new RuntimeException("Cannot find hypo source for " + hypocenterUrl); + } +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/HypocenterPlotter.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/HypocenterLayer.java similarity index 52% rename from src/main/java/gov/usgs/volcanoes/swarm/picker/HypocenterPlotter.java rename to src/main/java/gov/usgs/volcanoes/swarm/picker/HypocenterLayer.java index 07c0d16f..27aa916e 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/HypocenterPlotter.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/HypocenterLayer.java @@ -2,6 +2,7 @@ import java.awt.Color; import java.awt.Graphics2D; +import java.awt.event.MouseEvent; import java.awt.geom.Point2D; import java.util.List; @@ -12,20 +13,29 @@ import gov.usgs.proj.Projection; import gov.usgs.volcanoes.swarm.map.MapFrame; import gov.usgs.volcanoes.swarm.map.MapLayer; +import gov.usgs.volcanoes.swarm.map.MapPanel; -public final class HypocenterPlotter implements MapLayer { +public final class HypocenterLayer implements MapLayer { - Logger LOGGER = LoggerFactory.getLogger(HypocenterPlotter.class); + Logger LOGGER = LoggerFactory.getLogger(HypocenterLayer.class); private final List hypocenters; + private MapPanel mapPanel; - public HypocenterPlotter(List hypocenters) { + public HypocenterLayer(List hypocenters) { this.hypocenters = hypocenters; - // Hypocenters.addListener(this); - MapFrame.getInstance().addLayer(this); + mapPanel = MapFrame.getInstance().addLayer(this); } - public void draw(Graphics2D g2, GeoRange range, Projection projection, int widthPx, int heightPx, - int insetPx) { + public void draw(Graphics2D g2) { + + if (hypocenters == null) + return; + + GeoRange range = mapPanel.getRange(); + Projection projection = mapPanel.getProjection(); + int widthPx = mapPanel.getGraphWidth(); + int heightPx = mapPanel.getGraphHeight(); + int insetPx = mapPanel.getInset(); for (Hypocenter hypocenter : hypocenters) { LOGGER.debug("Hypo at {}, {}", hypocenter.lon, hypocenter.lat); @@ -39,9 +49,24 @@ public void draw(Graphics2D g2, GeoRange range, Projection projection, int width res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); g2.translate(res.x, res.y); - g2.setColor(Color.RED); + g2.setColor(Color.YELLOW); + g2.fillOval(0, 0, 10, 10); + g2.setColor(Color.lightGray); g2.drawOval(0, 0, 10, 10); g2.translate(-res.x, -res.y); } } + + public boolean mouseClicked(MouseEvent e) { + System.out.println("Mouse clicked. Now what?"); + return false; + } + + public void setMapPanel(MapPanel mapPanel) { + this.mapPanel = mapPanel; + } + + public void stop() { + // nothing to do here + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/Hypocenters.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/Hypocenters.java index cb76a12d..437bc64b 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/Hypocenters.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/Hypocenters.java @@ -7,12 +7,12 @@ public class Hypocenters { private final static List hypocenters; private final static List listeners; - private final static HypocenterPlotter plotter; + private final static HypocenterLayer plotter; static { hypocenters = new ArrayList(); listeners = new ArrayList(); - plotter = new HypocenterPlotter(hypocenters); + plotter = new HypocenterLayer(hypocenters); } /** uninstantiable */ diff --git a/src/main/java/nz/org/geonet/data/RSSHypocenters.java b/src/main/java/nz/org/geonet/data/RSSHypocenters.java deleted file mode 100644 index ad9402c9..00000000 --- a/src/main/java/nz/org/geonet/data/RSSHypocenters.java +++ /dev/null @@ -1,106 +0,0 @@ -package nz.org.geonet.data; - -import gov.usgs.util.ResourceReader; -import gov.usgs.util.xml.SimpleXMLParser; -import gov.usgs.util.xml.XMLDocHandler; -import gov.usgs.util.xml.XMLToMap; -import gov.usgs.volcanoes.core.time.J2kSec; -import gov.usgs.volcanoes.core.time.Time; -import gov.usgs.volcanoes.swarm.map.ClickableGeoLabel; -import gov.usgs.volcanoes.swarm.map.LabelSource; -import gov.usgs.volcanoes.swarm.map.hypocenters.Hypocenter; - -import java.awt.geom.Point2D; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * A class for getting hypocenter information from the GeoNet RSS feed. - * - * $Log: not supported by cvs2svn $ - * @author Dan Cervelli - * @version $Id: RSSHypocenters.java,v 1.1 2007-05-21 02:59:38 dcervelli Exp $ - */ -public class RSSHypocenters implements LabelSource -{ - public static final String RSS_URL = "http://www.geonet.org.nz/feeds/earthquake/geonet-recent-quakes-1.0.xml"; - public static final String QUAKE_URL = "http://www.geonet.org.nz/services/quake/"; - - private static class GetQuakeIDs implements XMLDocHandler - { - public List ids = new ArrayList(); - private boolean idTag; - - public void endDocument() throws Exception - { - } - - public void endElement(String tag) throws Exception - { - } - - public void startDocument() throws Exception - { - } - - public void startElement(String tag, Map h) throws Exception - { - if ("quake:id".equals(tag)) - idTag = true; - } - - public void text(String str) throws Exception - { - if (idTag) - { - ids.add(str); - idTag = false; - } - } - } - - public List getLabels() - { - ResourceReader rr = ResourceReader.getResourceReader(RSS_URL); - List hypos = new ArrayList(); - try - { - GetQuakeIDs q = new GetQuakeIDs(); - SimpleXMLParser.parse(q, rr.getReader()); - for (String id : q.ids) - { - System.out.println(id); - XMLToMap qm = new XMLToMap(); - ResourceReader qr = ResourceReader.getResourceReader(QUAKE_URL + "/" + id); - SimpleXMLParser.parse(qm, qr.getReader()); - Hypocenter h = new Hypocenter(); - double lat = Double.parseDouble(qm.text.get("report/lat")); - double lon = Double.parseDouble(qm.text.get("report/lon")); - h.location = new Point2D.Double(lon, lat); - h.text = "M" + qm.text.get("report/mag"); - h.depth = Double.parseDouble(qm.text.get("report/depth")); - String year = qm.text.get("report/uttime/year"); - String mo = qm.text.get("report/uttime/month"); - String day = qm.text.get("report/uttime/day"); - String hour = qm.text.get("report/uttime/hour"); - String minute = qm.text.get("report/uttime/minute"); - String second = qm.text.get("report/uttime/second"); - String ms = qm.text.get("report/uttime/msec"); - String ds = String.format("%s-%s-%s %s:%s:%s.%s", year, mo, day, hour, minute, second, ms); - h.time = J2kSec.parse(Time.STANDARD_TIME_FORMAT_MS, ds); - hypos.add(h); - } - } - catch (Exception e) - { - e.printStackTrace(); - } - return hypos; - } - - public static void main(String[] args) - { - new RSSHypocenters().getLabels(); - } -} From 990ee9be9fa11c686ff0808f5768d1a7cdc07e30 Mon Sep 17 00:00:00 2001 From: tparker Date: Tue, 8 Mar 2016 21:48:25 -0900 Subject: [PATCH 07/67] Keyboard phase shortcut and plot hypocenters by descending age --- .../swarm/map/hypocenters/Hypocenter.java | 4 +- .../map/hypocenters/HypocenterLayer.java | 11 ++-- .../map/hypocenters/HypocenterSource.java | 2 +- .../volcanoes/swarm/picker/PickerFrame.java | 51 +++++++++++++------ .../swarm/picker/PickerWavePanel.java | 28 ++++++++-- .../swarm/wave/AbstractWavePanel.java | 17 ++++--- .../swarm/wave/WaveViewPanelAdapter.java | 9 +--- 7 files changed, 79 insertions(+), 43 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java index db517761..88706571 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java @@ -84,7 +84,8 @@ public void mouseClicked(MouseEvent e) { } mm.addChannel(ch); mm.setVisible(true); - mm.setPauseStartTime(time - 4); + mm.setPauseStartTime(time - 1); + mm.setSpan(30); total++; } } @@ -132,4 +133,5 @@ public Hypocenter build() { return new Hypocenter(this); } } + } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java index e9d9a352..8edc8127 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java @@ -1,6 +1,5 @@ package gov.usgs.volcanoes.swarm.map.hypocenters; -import java.awt.Color; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.event.MouseEvent; @@ -102,8 +101,7 @@ private List pollHypocenters() if (hypocenterSource == HypocenterSource.NONE) { return null; } - - List hypocenters = new ArrayList(); + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); Document doc = dBuilder.parse(hypocenterSource.getUrl()); @@ -111,8 +109,11 @@ private List pollHypocenters() NodeList events = doc.getElementsByTagName("event"); LOGGER.debug("Got {} events.", events.getLength()); + int eventCount = events.getLength(); + List hypocenters = new ArrayList(eventCount); - for (int idx = 0; idx < events.getLength(); idx++) { + // add elements in reverse order to encourage plotting recent events on top + for (int idx = eventCount - 1; idx > 0; idx--) { Element event = (Element) events.item(idx); Element origin = (Element) event.getElementsByTagName("origin").item(0); @@ -134,7 +135,7 @@ private List pollHypocenters() } return hypocenters; } - + public void draw(Graphics2D g2) { if (hypocenters == null) return; diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterSource.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterSource.java index bb7ed5aa..0be9e5fd 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterSource.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterSource.java @@ -47,4 +47,4 @@ public static HypocenterSource fromUrl(String hypocenterUrl) { } throw new RuntimeException("Cannot find hypo source for " + hypocenterUrl); } -} +} \ No newline at end of file diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java index ee220ba5..8ef8d64d 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java @@ -4,6 +4,8 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; +import java.awt.MouseInfo; +import java.awt.Point; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; @@ -44,6 +46,7 @@ import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JToolBar; +import javax.swing.KeyStroke; import javax.swing.ScrollPaneConstants; import javax.swing.SwingUtilities; import javax.swing.TransferHandler; @@ -150,8 +153,27 @@ public PickerFrame() { histories = new HashMap>(); createUI(); LOGGER.debug("Finished creating picker frame."); + + // getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("typed q"), + // "pPick"); + getInputMap().put(KeyStroke.getKeyStroke("typed q"), "pPick"); + getActionMap().put("pPick", new AbstractAction() { + private static final long serialVersionUID = -1; + + public void actionPerformed(final ActionEvent e) { + findWavePanel(); + } + }); + } + private void findWavePanel() { + Point p = MouseInfo.getPointerInfo().getLocation(); + SwingUtilities.convertPointFromScreen(p, waveBox); + int idx = p.y / calculateWaveHeight(); + PickerWavePanel panel = waves.get(idx); + panel.instantPick(Phase.PhaseType.P); + } private void createUI() { this.setFrameIcon(Icons.ruler); @@ -410,22 +432,21 @@ public void actionPerformed(final ActionEvent e) { UiUtils.mapKeyStrokeToButton(this, "DELETE", "remove", removeButton); toolbar.add(removeButton); - locateButton = SwarmUtil.createToolBarButton(Icons.locate, "Locate", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - EventLocator locator = new Hypo71Locator(); - try { - locator.locate(event); - } catch (IOException e1) { - e1.printStackTrace(); - }; - } + locateButton = SwarmUtil.createToolBarButton(Icons.locate, "Locate", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + EventLocator locator = new Hypo71Locator(); + try { + locator.locate(event); + } catch (IOException e1) { + e1.printStackTrace(); + }; + } - private void particleMotionPlot() { - // TODO Auto-generated method stub + private void particleMotionPlot() { + // TODO Auto-generated method stub - } - }); + } + }); toolbar.add(locateButton); toolbar.add(Box.createHorizontalGlue()); @@ -656,7 +677,7 @@ private void doButtonEnables() { histButton.setEnabled(allowMulti); removeButton.setEnabled(allowMulti); gotoButton.setEnabled(allowMulti); - } + } public synchronized PickerWavePanel getSingleSelected() { if (selectedSet.size() != 1) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java index 3e3ac9d6..1b1cc088 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java @@ -5,13 +5,23 @@ import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; +import java.awt.MouseInfo; +import java.awt.Point; +import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; import java.awt.geom.Line2D; +import javax.swing.AbstractAction; +import javax.swing.JComponent; +import javax.swing.KeyStroke; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import gov.usgs.volcanoes.core.time.J2kSec; +import gov.usgs.volcanoes.core.ui.GlobalKeyManager; +import gov.usgs.volcanoes.core.ui.UiUtils; +import gov.usgs.volcanoes.swarm.picker.Phase.PhaseType; import gov.usgs.volcanoes.swarm.time.WaveViewTime; import gov.usgs.volcanoes.swarm.wave.AbstractWavePanel; @@ -42,9 +52,15 @@ protected void processRightMousePress(MouseEvent e) { phasePopup.show(e.getComponent(), e.getX(), e.getY()); pauseCursorMark = true; WaveViewTime.fireTimeChanged(cursorTime); - } + public void instantPick(PhaseType p) { + Phase phase = new Phase.Builder().onset(Phase.Onset.i).phaseType(Phase.PhaseType.P) + .firstMotion(Phase.FirstMotion.UP).time(J2kSec.asEpoch(time)).weight(1).build(); + + event.setPhase(channel, phase); + WaveViewTime.fireTimeChanged(time); + } public void setEvent(Event event) { this.event = event; } @@ -61,7 +77,7 @@ protected void annotateImage(Graphics2D g2) { if (time > 0) { markPhase(g2, CODA_BACKGROUND, event.coda(channel), "C"); } - } else { + } else { markPhase(g2, S_BACKGROUND, phase.time, phase.tag()); } } @@ -88,7 +104,7 @@ private void markPhase(Graphics2D g2, Color backgroundColor, long time, String t int offset = 2; int lw = width + 2 * offset; - + g2.setColor(backgroundColor); g2.fillRect((int) x, 3, lw, height + 2 * offset); @@ -98,7 +114,7 @@ private void markPhase(Graphics2D g2, Color backgroundColor, long time, String t g2.drawString(tag, (int) x + offset, 3 + (fm.getAscent() + offset)); g2.setFont(oldFont); } - + private void markPhase(Graphics2D g2, Phase phase) { double j2k = J2kSec.fromEpoch(phase.time); double[] t = getTranslation(); @@ -119,7 +135,7 @@ private void markPhase(Graphics2D g2, Phase phase) { int offset = 2; int lw = width + 2 * offset; - + Color background = null; if (phase.phaseType == Phase.PhaseType.P) { background = P_BACKGROUND; @@ -148,4 +164,6 @@ public void updateEvent() { public void setParent(Component parent) { this.parent = parent; } + + } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java b/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java index 0e34f386..5af72629 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java @@ -120,6 +120,7 @@ public abstract class AbstractWavePanel extends JComponent { protected static final Color DARK_GREEN = new Color(0, 168, 0); protected boolean pauseCursorMark; + protected double time; public AbstractWavePanel(WaveViewSettings s) { swarmConfig = SwarmConfig.getInstance(); @@ -482,11 +483,11 @@ public boolean processMousePosition(int x, int y) { Dimension size = getSize(); double[] t = getTranslation(); - double j2k = Double.NaN; + time = Double.NaN; if (wave != null && t != null && y > yOffset && y < (size.height - bottomHeight) && x > xOffset && x < size.width - rightWidth) { - j2k = x * t[0] + t[1]; + time = x * t[0] + t[1]; double yi = y * -t[2] + t[3]; int[] dataRange = wave.getDataRange(); @@ -497,12 +498,12 @@ public boolean processMousePosition(int x, int y) { dataRange[1]); if (timeSeries) { - String utc = J2kSec.format(Time.STANDARD_TIME_FORMAT_MS, j2k); + String utc = J2kSec.format(Time.STANDARD_TIME_FORMAT_MS, time); TimeZone tz = swarmConfig.getTimeZone(channel); - double tzo = tz.getOffset(J2kSec.asEpoch(j2k)); + double tzo = tz.getOffset(J2kSec.asEpoch(time)); if (tzo != 0) { - String tza = tz.getDisplayName(tz.inDaylightTime(J2kSec.asDate(j2k)), TimeZone.SHORT); - status = J2kSec.format(Time.STANDARD_TIME_FORMAT_MS, j2k + tzo) + " (" + tza + "), " + utc + String tza = tz.getDisplayName(tz.inDaylightTime(J2kSec.asDate(time)), TimeZone.SHORT); + status = J2kSec.format(Time.STANDARD_TIME_FORMAT_MS, time + tzo) + " (" + tza + "), " + utc + " (UTC)"; } else status = utc; @@ -532,7 +533,7 @@ public boolean processMousePosition(int x, int y) { } else { - double xi = j2k; + double xi = time; if (settings.viewType == ViewType.SPECTRA && settings.logFreq) xi = Math.pow(10.0, xi); if (settings.viewType == ViewType.SPECTRA && settings.logPower) @@ -544,7 +545,7 @@ public boolean processMousePosition(int x, int y) { } if (!pauseCursorMark) - WaveViewTime.fireTimeChanged(j2k); + WaveViewTime.fireTimeChanged(time); if (status == null) status = " "; diff --git a/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewPanelAdapter.java b/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewPanelAdapter.java index 83f73630..57799109 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewPanelAdapter.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewPanelAdapter.java @@ -4,16 +4,9 @@ /** * - * $Log: not supported by cvs2svn $ - * Revision 1.1 2006/08/01 23:45:23 cervelli - * Moved package. - * - * Revision 1.1 2006/06/05 18:06:49 dcervelli - * Major 1.3 changes. - * * @author Dan Cervelli */ -public class WaveViewPanelAdapter implements WaveViewPanelListener +public abstract class WaveViewPanelAdapter implements WaveViewPanelListener { public void waveZoomed(AbstractWavePanel src, double st, double et, double nst, double net) {} From cb2f9e612466b603ba7f3e94731c5718412bcb3c Mon Sep 17 00:00:00 2001 From: tparker Date: Sun, 13 Mar 2016 01:44:46 -0900 Subject: [PATCH 08/67] Add hover panel to map events --- .../java/gov/usgs/volcanoes/swarm/Swarm.java | 22 +- .../usgs/volcanoes/swarm/event/Arrival.java | 24 ++ .../gov/usgs/volcanoes/swarm/event/Event.java | 87 +++++++ .../usgs/volcanoes/swarm/event/Magnitude.java | 28 +++ .../usgs/volcanoes/swarm/event/Origin.java | 80 +++++++ .../gov/usgs/volcanoes/swarm/event/Pick.java | 16 ++ .../swarm/map/ClickableGeoLabel.java | 2 +- .../usgs/volcanoes/swarm/map/MapLayer.java | 1 + .../usgs/volcanoes/swarm/map/MapPanel.java | 11 + .../swarm/map/hypocenters/Hypocenter.java | 75 +++--- .../map/hypocenters/HypocenterLayer.java | 222 ++++++++++++++---- .../swarm/picker/HypocenterLayer.java | 5 + .../volcanoes/swarm/picker/PickerFrame.java | 6 + 13 files changed, 485 insertions(+), 94 deletions(-) create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/Event.java create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/Magnitude.java create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java diff --git a/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java b/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java index 38e360d8..120bd926 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java @@ -1,10 +1,5 @@ package gov.usgs.volcanoes.swarm; -import com.jgoodies.looks.plastic.Plastic3DLookAndFeel; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.awt.Dimension; import java.awt.Frame; import java.awt.KeyboardFocusManager; @@ -29,6 +24,12 @@ import javax.swing.SwingUtilities; import javax.swing.UIManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; + +import com.jgoodies.looks.plastic.Plastic3DLookAndFeel; + import gov.usgs.plot.data.Wave; import gov.usgs.volcanoes.core.configfile.ConfigFile; import gov.usgs.volcanoes.core.time.CurrentTime; @@ -38,6 +39,7 @@ import gov.usgs.volcanoes.swarm.chooser.DataChooser; import gov.usgs.volcanoes.swarm.data.CachedDataSource; import gov.usgs.volcanoes.swarm.data.SeismicDataSource; +import gov.usgs.volcanoes.swarm.event.Event; import gov.usgs.volcanoes.swarm.heli.HelicorderViewerFrame; import gov.usgs.volcanoes.swarm.internalFrame.InternalFrameListener; import gov.usgs.volcanoes.swarm.internalFrame.SwarmInternalFrames; @@ -586,6 +588,15 @@ public static PickerFrame openPicker(final WaveViewPanel insetWavePanel) { pickerFrame.setBaseWave(p); return pickerFrame; } + + public static PickerFrame openPicker(Event event) { + PickerFrame pickerFrame = new PickerFrame(event); + pickerFrame.setVisible(true); + pickerFrame.requestFocus(); + SwarmInternalFrames.add(pickerFrame); + return pickerFrame; + } + public void saveLayout(String name) { final boolean fixedName = (name != null); @@ -956,4 +967,5 @@ public static void main(final String[] args) { swarm.parseKiosk(); } + } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java new file mode 100644 index 00000000..ba1ed052 --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java @@ -0,0 +1,24 @@ +package gov.usgs.volcanoes.swarm.event; + +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; + +public class Arrival { + Logger LOGGER = LoggerFactory.getLogger(Arrival.class); + +public final String publicId; +private Pick pick; +private String phase; + +public Arrival(Element arrivalElement, Map picks) { + this.publicId = arrivalElement.getAttribute("publicID"); + LOGGER.debug("new arrival {}", publicId); + + this.phase = arrivalElement.getAttribute("phase"); + this.pick = picks.get(arrivalElement.getAttribute("pickID")); +} + +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java new file mode 100644 index 00000000..ecfa14f2 --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java @@ -0,0 +1,87 @@ +package gov.usgs.volcanoes.swarm.event; + +import java.util.HashMap; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +public class Event { + private static final Logger LOGGER = LoggerFactory.getLogger(Event.class); + + public final String publicId; + private final Map origins; + private final Map magnitudes; + private final Map picks; + private Origin preferredOrigin; + private Magnitude preferredMagnitude; + private String description; + + + + public Event(Element event) { + this.publicId = event.getAttribute("publicID"); + LOGGER.debug("New event ({}}", publicId); + + origins = new HashMap(); + magnitudes = new HashMap(); + picks = new HashMap(); + + parseEvent(event); + } + + private void parseEvent(Element event) { + + // order matters. + parsePicks(event.getElementsByTagName("pick")); + + parseOrigins(event.getElementsByTagName("origin")); + preferredOrigin = origins.get(event.getAttribute("preferredOriginID")); + if (preferredOrigin == null && origins.size() > 0) { + preferredOrigin = (Origin) origins.values().toArray()[0]; + } + + parseMagnitudes(event.getElementsByTagName("magnitude")); + preferredMagnitude = magnitudes.get(event.getAttribute("preferredMagnitudeID")); + if (preferredMagnitude == null && magnitudes.size() > 0) { + preferredMagnitude = (Magnitude) magnitudes.values().toArray()[0]; + } + } + + private void parsePicks(NodeList pickElements) { + int pickCount = pickElements.getLength(); + for (int idx = 0; idx < pickCount; idx++) { + Pick pick = new Pick((Element) pickElements.item(idx)); + picks.put(pick.publicId, pick); + } + } + + + private void parseOrigins(NodeList originElements) { + int originCount = originElements.getLength(); + for (int idx = 0; idx < originCount; idx++) { + Origin origin = new Origin((Element) originElements.item(idx), picks); + origins.put(origin.publicId, origin); + } + } + + public Origin getPreferredOrigin() { + + return preferredOrigin; + } + + private void parseMagnitudes(NodeList magnitudeElements) { + int originCount = magnitudeElements.getLength(); + for (int idx = 0; idx < originCount; idx++) { + Magnitude magnitude = new Magnitude((Element) magnitudeElements.item(idx)); + magnitudes.put(magnitude.publicId, magnitude); + } + } + + public Magnitude getPerferredMagnitude() { + return preferredMagnitude; + } + +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Magnitude.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Magnitude.java new file mode 100644 index 00000000..d330f38f --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Magnitude.java @@ -0,0 +1,28 @@ +package gov.usgs.volcanoes.swarm.event; + +import java.util.Map; + +import org.w3c.dom.Element; + +public class Magnitude { + + public final String publicId; + + private double mag; + private String type; + + public Magnitude(Element magnitudeElement) { + publicId = magnitudeElement.getAttribute("publicId"); +// mag = Double.parseDouble(magnitudeElement.getElementsByTagName("mag").item(0).getTextContent()); + type = magnitudeElement.getElementsByTagName("type").item(0).getTextContent(); + + Element magElement = (Element) magnitudeElement.getElementsByTagName("mag").item(0); + mag = Double.parseDouble(magElement.getElementsByTagName("value").item(0).getTextContent()); + + } + + public double getMag() { + return mag; + } + +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java new file mode 100644 index 00000000..6964f61e --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java @@ -0,0 +1,80 @@ +package gov.usgs.volcanoes.swarm.event; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Map; +import java.util.TimeZone; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.DOMException; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +public class Origin { + private static final Logger LOGGER = LoggerFactory.getLogger(Origin.class); + private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSX"; + + public final String publicId; + private double latitude; + private double longitude; + private double depth; + private long time; + + private Map arrivals; + + public Origin(Element originElement, Map picks) { + this.publicId = originElement.getAttribute("publicId"); + LOGGER.debug("new origin {}", publicId); + + this.longitude = Double + .parseDouble(originElement.getElementsByTagName("longitude").item(0).getTextContent()); + this.latitude = + Double.parseDouble(originElement.getElementsByTagName("latitude").item(0).getTextContent()); + + Element depthElement = (Element) originElement.getElementsByTagName("depth").item(0); + depth = Double.parseDouble(depthElement.getElementsByTagName("value").item(0).getTextContent()); + + DateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT); + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + + Element timeElement = (Element) originElement.getElementsByTagName("time").item(0); + try { + time = dateFormat.parse(timeElement.getElementsByTagName("value").item(0).getTextContent()).getTime(); + } catch (DOMException e) { + LOGGER.debug("DOMException parsing origin"); + } catch (ParseException e) { + LOGGER.debug("{ParseException parsing origin"); + } + + + + parseArrivals(originElement.getElementsByTagName("arrival"), picks); + } + + private void parseArrivals(NodeList arrivalElements, Map picks) { + int arrivalCount = arrivalElements.getLength(); + for (int idx = 0; idx < arrivalCount; idx++) { + Arrival arrival = new Arrival((Element) arrivalElements.item(idx), picks); + arrivals.put(arrival.publicId, arrival); + } + } + + public double getLongitude() { + return longitude; + } + + public double getLatitude() { + return latitude; + } + + public double getDepth() { + return depth; + } + + public long getTime() { + return time; + } +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java new file mode 100644 index 00000000..d154b807 --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java @@ -0,0 +1,16 @@ +package gov.usgs.volcanoes.swarm.event; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; + +public class Pick { + Logger LOGGER = LoggerFactory.getLogger(Pick.class); + + public final String publicId; + + public Pick(Element pickElement) { + publicId = pickElement.getAttribute("publicID"); + LOGGER.debug("new PIck {}", publicId); + } +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/ClickableGeoLabel.java b/src/main/java/gov/usgs/volcanoes/swarm/map/ClickableGeoLabel.java index 0c89a0d6..23404587 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/ClickableGeoLabel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/ClickableGeoLabel.java @@ -15,7 +15,7 @@ */ abstract public class ClickableGeoLabel extends GeoLabel { - abstract public void mouseClicked(MouseEvent e); + abstract public boolean mouseClicked(MouseEvent e); abstract public Rectangle getClickBox(); public ClickableGeoLabel() diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapLayer.java index f50496d8..962eac79 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapLayer.java @@ -13,5 +13,6 @@ public interface MapLayer { public boolean mouseClicked(MouseEvent e); public void setMapPanel(MapPanel mapPanel); public void stop(); + public boolean mouseMoved(MouseEvent e); } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java index c8de2ede..98180f2d 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java @@ -1106,6 +1106,17 @@ public void mouseMoved(final MouseEvent e) { final Point2D.Double latLon = getLonLat(e.getX(), e.getY()); if (latLon != null) MapFrame.getInstance().setStatusText(Util.lonLatToString(latLon)); + + if (layers != null) { + boolean handled = false; + Iterator it = layers.iterator(); + while (it.hasNext() && handled == false) { + MapLayer layer = it.next(); + handled = layer.mouseMoved(e); + } + resetImage(); + } + } public void mouseDragged(final MouseEvent e) { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java index 88706571..6f8930ba 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java @@ -6,24 +6,16 @@ import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.awt.geom.Ellipse2D; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Element; import gov.usgs.plot.render.DataPointRenderer; -import gov.usgs.util.Pair; import gov.usgs.volcanoes.core.time.J2kSec; -import gov.usgs.volcanoes.swarm.Metadata; +import gov.usgs.volcanoes.swarm.Swarm; import gov.usgs.volcanoes.swarm.SwarmConfig; import gov.usgs.volcanoes.swarm.map.ClickableGeoLabel; -import gov.usgs.volcanoes.swarm.picker.Phase; -import gov.usgs.volcanoes.swarm.picker.Phase.Builder; -import gov.usgs.volcanoes.swarm.picker.Phase.FirstMotion; -import gov.usgs.volcanoes.swarm.picker.Phase.Onset; -import gov.usgs.volcanoes.swarm.picker.Phase.PhaseType; -import gov.usgs.volcanoes.swarm.wave.MultiMonitor; -import gov.usgs.volcanoes.swarm.wave.SwarmMultiMonitors; /** * @@ -37,15 +29,18 @@ public class Hypocenter extends ClickableGeoLabel { private static final SwarmConfig swarmConfig = SwarmConfig.getInstance(); + private static final Logger LOGGER = LoggerFactory.getLogger(Hypocenter.class); private final double time; private final double depth; private final double magnitude; private final DataPointRenderer renderer; + private final Element event; private Hypocenter(Builder builder) { time = builder.time; depth = builder.depth; magnitude = builder.magnitude; + event = builder.event; renderer = new DataPointRenderer(); renderer.antiAlias = true; @@ -67,29 +62,32 @@ public void setColor(Color color) { } @Override - public void mouseClicked(MouseEvent e) { - Map metadata = swarmConfig.getMetadata(); - List> nrst = - Metadata.findNearest(swarmConfig.getMetadata(), location, true); - Set cleared = new HashSet(); - if (nrst != null) { - for (int i = 0, total = 0; i < nrst.size() && total < 10; i++) { - String ch = nrst.get(i).item2; - if (ch.matches(".* ..Z .*")) { - Metadata md = metadata.get(ch); - MultiMonitor mm = SwarmMultiMonitors.getMonitor(md.source); - if (!cleared.contains(mm)) { - mm.removeAllWaves(); - cleared.add(mm); - } - mm.addChannel(ch); - mm.setVisible(true); - mm.setPauseStartTime(time - 1); - mm.setSpan(30); - total++; - } - } - } + public boolean mouseClicked(MouseEvent e) { + LOGGER.debug("event clicked" ); +// Swarm.openPicker(event); + return true; +// Map metadata = swarmConfig.getMetadata(); +// List> nrst = +// Metadata.findNearest(swarmConfig.getMetadata(), location, true); +// Set cleared = new HashSet(); +// if (nrst != null) { +// for (int i = 0, total = 0; i < nrst.size() && total < 10; i++) { +// String ch = nrst.get(i).item2; +// if (ch.matches(".* ..Z .*")) { +// Metadata md = metadata.get(ch); +// MultiMonitor mm = SwarmMultiMonitors.getMonitor(md.source); +// if (!cleared.contains(mm)) { +// mm.removeAllWaves(); +// cleared.add(mm); +// } +// mm.addChannel(ch); +// mm.setVisible(true); +// mm.setPauseStartTime(time - 1); +// mm.setSpan(30); +// total++; +// } +// } +// } } public void draw(Graphics2D g2) { @@ -111,6 +109,7 @@ public static class Builder { private double time; private double depth; private double magnitude; + private Element event; public Builder() {} @@ -129,6 +128,10 @@ public Builder time(double time) { return this; } + public Builder event(Element event) { + this.event = event; + return this; + } public Hypocenter build() { return new Hypocenter(this); } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java index 8edc8127..dd675c0d 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java @@ -1,15 +1,24 @@ package gov.usgs.volcanoes.swarm.map.hypocenters; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.FontMetrics; import java.awt.Graphics2D; +import java.awt.Point; import java.awt.Rectangle; import java.awt.event.MouseEvent; +import java.awt.geom.Ellipse2D; import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; +import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -23,23 +32,32 @@ import org.w3c.dom.NodeList; import org.xml.sax.SAXException; +import gov.usgs.plot.render.DataPointRenderer; import gov.usgs.proj.GeoRange; import gov.usgs.proj.Projection; import gov.usgs.volcanoes.core.time.J2kSec; +import gov.usgs.volcanoes.core.time.Time; import gov.usgs.volcanoes.swarm.ConfigListener; +import gov.usgs.volcanoes.swarm.Swarm; import gov.usgs.volcanoes.swarm.SwarmConfig; -import gov.usgs.volcanoes.swarm.map.ClickableGeoLabel; +import gov.usgs.volcanoes.swarm.event.Event; +import gov.usgs.volcanoes.swarm.event.Origin; import gov.usgs.volcanoes.swarm.map.MapFrame; import gov.usgs.volcanoes.swarm.map.MapLayer; import gov.usgs.volcanoes.swarm.map.MapPanel; public final class HypocenterLayer implements MapLayer, ConfigListener { - - private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSX"; - private static final Logger LOGGER = LoggerFactory.getLogger(HypocenterLayer.class); private static final int REFRESH_INTERVAL = 5 * 60 * 1000; - private List hypocenters; + private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSX"; + private static final int ONE_HOUR = 60 * 60 * 1000; + private static final int ONE_DAY = ONE_HOUR * 24; + private static final int ONE_WEEK = ONE_DAY * 7; + + private static final int POPUP_PADDING = 2; + + // private List hypocenters; + private final Map events; private boolean run = true; private MapPanel panel; @@ -47,11 +65,24 @@ public final class HypocenterLayer implements MapLayer, ConfigListener { private Thread refreshThread; private final SwarmConfig swarmConfig; + private final DataPointRenderer renderer; + private Event hoverEvent; + private Point hoverLocation; public HypocenterLayer() { + events = new HashMap(); dateFormat = new SimpleDateFormat(DATE_FORMAT); swarmConfig = SwarmConfig.getInstance(); swarmConfig.addListener(this); + + renderer = new DataPointRenderer(); + renderer.antiAlias = true; + renderer.stroke = new BasicStroke(1.2f); + renderer.filled = true; + renderer.color = Color.LIGHT_GRAY; + // r.shape = Geometry.STAR_10; + renderer.shape = new Ellipse2D.Float(0f, 0f, 7f, 7f); + startPolling(); } @@ -65,12 +96,13 @@ private void startPolling() { public void run() { while (run) { try { - hypocenters = pollHypocenters(); + pollHypocenters(); } catch (ParserConfigurationException e) { LOGGER.debug("ParserConfigurationException while retrieving hypocenters ({})", e); } catch (SAXException e) { - hypocenters = null; - LOGGER.debug("SAXException while retrieving hypocenters. Typically this means there were no hypocenters to display."); + events.clear(); + LOGGER.debug( + "SAXException while retrieving hypocenters. Typically this means there were no hypocenters to display."); } catch (IOException e) { LOGGER.debug("IOException while retrieving hypocenters ({})", e); } catch (DOMException e) { @@ -78,9 +110,9 @@ public void run() { } catch (ParseException e) { LOGGER.debug("ParseException while retrieving hypocenters ({})", e); } - + MapFrame.getInstance().repaint(); - + try { Thread.sleep(REFRESH_INTERVAL); } catch (InterruptedException e) { @@ -94,50 +126,31 @@ public void run() { refreshThread.start(); } - private List pollHypocenters() + private void pollHypocenters() throws ParserConfigurationException, SAXException, IOException, DOMException, ParseException { LOGGER.debug("Polling hypocenters"); + events.clear(); HypocenterSource hypocenterSource = swarmConfig.getHypocenterSource(); if (hypocenterSource == HypocenterSource.NONE) { - return null; + return; } - + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); Document doc = dBuilder.parse(hypocenterSource.getUrl()); doc.getDocumentElement().normalize(); - NodeList events = doc.getElementsByTagName("event"); - LOGGER.debug("Got {} events.", events.getLength()); - int eventCount = events.getLength(); - List hypocenters = new ArrayList(eventCount); - - // add elements in reverse order to encourage plotting recent events on top - for (int idx = eventCount - 1; idx > 0; idx--) { - - Element event = (Element) events.item(idx); - Element origin = (Element) event.getElementsByTagName("origin").item(0); - double lon = Double.parseDouble(((Element) origin.getElementsByTagName("longitude").item(0)) - .getElementsByTagName("value").item(0).getTextContent()); - double lat = Double.parseDouble(((Element) origin.getElementsByTagName("latitude").item(0)) - .getElementsByTagName("value").item(0).getTextContent()); - - Date date = dateFormat.parse(((Element) origin.getElementsByTagName("time").item(0)) - .getElementsByTagName("value").item(0).getTextContent()); - - double mag = Double.parseDouble(((Element) event.getElementsByTagName("mag").item(0)) - .getElementsByTagName("value").item(0).getTextContent()); - - Hypocenter h = new Hypocenter.Builder().time(J2kSec.fromDate(date)).build(); - h.location = new Point2D.Double(lon, lat); - h.text = "M" + mag; - hypocenters.add(h); + NodeList eventElements = doc.getElementsByTagName("event"); + LOGGER.debug("Got {} events.", eventElements.getLength()); + int eventCount = eventElements.getLength(); + for (int idx = 0; idx < eventCount; idx++) { + Event event = new Event((Element) eventElements.item(idx)); + events.put(event.publicId, event); } - return hypocenters; } - + public void draw(Graphics2D g2) { - if (hypocenters == null) + if (events.size() < 1) return; GeoRange range = panel.getRange(); @@ -146,9 +159,12 @@ public void draw(Graphics2D g2) { int heightPx = panel.getGraphHeight(); int insetPx = panel.getInset(); - for (final Hypocenter label : hypocenters) { + for (final Event event : events.values()) { + Origin origin = event.getPreferredOrigin(); + + LOGGER.debug("Plotting event at {}, {}", origin.getLongitude(), origin.getLatitude()); final Point2D.Double xy = - projection.forward(new Point2D.Double(label.location.x, label.location.y)); + projection.forward(new Point2D.Double(origin.getLongitude(), origin.getLatitude())); final double[] ext = range.getProjectedExtents(projection); final double dx = (ext[1] - ext[0]); final double dy = (ext[3] - ext[2]); @@ -157,31 +173,87 @@ public void draw(Graphics2D g2) { res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); g2.translate(res.x, res.y); - label.draw(g2); + long age = J2kSec.asEpoch(J2kSec.now()); + if (event == hoverEvent) { + renderer.paint = Color.GREEN; + } else if (age < ONE_HOUR) { + renderer.paint = Color.RED; + } else if (age < ONE_DAY) { + renderer.paint = Color.ORANGE; + } else if (age < ONE_WEEK) { + renderer.paint = Color.YELLOW; + } else { + renderer.paint = Color.WHITE; + } + renderer.renderAtOrigin(g2); + + if (event == hoverEvent) { + drawPopup(g2); + } g2.translate(-res.x, -res.y); } } + private void drawPopup(Graphics2D g2) { + Origin origin = hoverEvent.getPreferredOrigin(); + + g2.setStroke(new BasicStroke(1.2f)); + g2.setColor(new Color(0, 0, 0, 64)); + + List text = new ArrayList(3); + String depth = String.format("Depth: %.2f km", (origin.getDepth() / 1000)); + text.add(depth); + + String mag = String.format("Mag: %.2f", (hoverEvent.getPerferredMagnitude().getMag())); + text.add(mag); + + String date = Time.format(Time.STANDARD_TIME_FORMAT, new Date(origin.getTime())); + text.add(date); + + FontMetrics fm = g2.getFontMetrics(); + int height = 2 * POPUP_PADDING; + int width = 0; + for (String string : text) { + Rectangle2D bounds = fm.getStringBounds(string, g2); + height += (int) (Math.ceil(bounds.getHeight()) + 2); + width = Math.max(width, (int) (Math.ceil(bounds.getWidth()) + 2 * POPUP_PADDING)); + } + + g2.setStroke(new BasicStroke(1.2f)); + g2.setColor(new Color(0, 0, 0, 128)); + g2.drawRect(0, -(height - POPUP_PADDING), width, height); + g2.fillRect(0, -(height - POPUP_PADDING), width, height); + + g2.setColor(Color.WHITE); + int baseY = POPUP_PADDING; + for (String string : text) { + g2.drawString(string, POPUP_PADDING, -baseY); + Rectangle2D bounds = fm.getStringBounds(string, g2); + baseY += (int) (Math.ceil(bounds.getHeight()) + 2); + } + } + public boolean mouseClicked(final MouseEvent e) { - if (hypocenters == null) { + if (events.size() < 1l) { return false; } - boolean handled = false; - GeoRange range = panel.getRange(); Projection projection = panel.getProjection(); int widthPx = panel.getGraphWidth(); int heightPx = panel.getGraphHeight(); int insetPx = panel.getInset(); - for (ClickableGeoLabel label : hypocenters) { - final Rectangle r = label.getClickBox(); - + Iterator it = events.values().iterator(); + boolean handled = false; + while (it.hasNext() && handled == false) { + Event event = it.next(); + Origin origin = event.getPreferredOrigin(); + final Rectangle r = new Rectangle(-7, -7, 17, 17); final Point2D.Double xy = - projection.forward(new Point2D.Double(label.location.x, label.location.y)); + projection.forward(new Point2D.Double(origin.getLongitude(), origin.getLatitude())); final double[] ext = range.getProjectedExtents(projection); final double dx = (ext[1] - ext[0]); final double dy = (ext[3] - ext[2]); @@ -190,8 +262,11 @@ public boolean mouseClicked(final MouseEvent e) { res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); r.translate((int) res.x, (int) res.y); + if (r.contains(e.getPoint())) { - label.mouseClicked(e); + LOGGER.debug("event clicked"); + Swarm.openPicker(event); + return true; } } @@ -207,4 +282,47 @@ public void stop() { run = false; refreshThread.interrupt(); } + + public boolean mouseMoved(MouseEvent e) { + if (events.size() < 1) { + return false; + } + + GeoRange range = panel.getRange(); + Projection projection = panel.getProjection(); + int widthPx = panel.getGraphWidth(); + int heightPx = panel.getGraphHeight(); + int insetPx = panel.getInset(); + + Iterator it = events.values().iterator(); + boolean handled = false; + while (it.hasNext() && handled == false) { + Event event = it.next(); + Origin origin = event.getPreferredOrigin(); + final Rectangle r = new Rectangle(-7, -7, 17, 17); + + final Point2D.Double xy = + projection.forward(new Point2D.Double(origin.getLongitude(), origin.getLatitude())); + final double[] ext = range.getProjectedExtents(projection); + final double dx = (ext[1] - ext[0]); + final double dy = (ext[3] - ext[2]); + final Point2D.Double res = new Point2D.Double(); + res.x = (((xy.x - ext[0]) / dx) * widthPx + insetPx); + res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); + + r.translate((int) res.x, (int) res.y); + if (r.contains(e.getPoint())) { + LOGGER.debug("set hover event {}", event.publicId); + hoverEvent = event; + handled = true; + } else if (event == hoverEvent) { + LOGGER.debug("unset hover event {}", event.publicId); + + hoverEvent = null; + hoverLocation = e.getPoint(); + } + } + + return handled; + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/HypocenterLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/HypocenterLayer.java index 27aa916e..26a52922 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/HypocenterLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/HypocenterLayer.java @@ -69,4 +69,9 @@ public void setMapPanel(MapPanel mapPanel) { public void stop() { // nothing to do here } + + public boolean mouseMoved(MouseEvent e) { + // TODO Auto-generated method stub + return false; + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java index 8ef8d64d..5a9a2e59 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java @@ -153,6 +153,7 @@ public PickerFrame() { histories = new HashMap>(); createUI(); LOGGER.debug("Finished creating picker frame."); + this.setVisible(true); // getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("typed q"), // "pPick"); @@ -167,6 +168,11 @@ public void actionPerformed(final ActionEvent e) { } + public PickerFrame(gov.usgs.volcanoes.swarm.event.Event event) { + this(); +// this.event = event; + } + private void findWavePanel() { Point p = MouseInfo.getPointerInfo().getLocation(); SwingUtilities.convertPointFromScreen(p, waveBox); From f39cb1d04b21804c1eb28d2fa98d4d2ebf81e713 Mon Sep 17 00:00:00 2001 From: tparker Date: Mon, 14 Mar 2016 08:49:18 -0800 Subject: [PATCH 09/67] quakeml redesign in progress... --- .../usgs/volcanoes/swarm/event/Arrival.java | 12 +- .../gov/usgs/volcanoes/swarm/event/Event.java | 47 ++++- .../volcanoes/swarm/event/EventObserver.java | 5 + .../usgs/volcanoes/swarm/event/Origin.java | 57 ++++-- .../gov/usgs/volcanoes/swarm/event/Pick.java | 75 +++++++- .../swarm/map/hypocenters/Hypocenter.java | 140 -------------- .../map/hypocenters/HypocenterLayer.java | 31 +++- .../volcanoes/swarm/picker/EventLocator.java | 2 +- .../picker/{Event.java => EventOld.java} | 6 +- .../volcanoes/swarm/picker/PhasePopup.java | 4 +- .../volcanoes/swarm/picker/PickListPanel.java | 171 ++++++++++++++---- .../volcanoes/swarm/picker/PickerFrame.java | 56 ++++-- .../swarm/picker/PickerWavePanel.java | 4 +- .../swarm/picker/hypo71/Hypo71Locator.java | 8 +- 14 files changed, 379 insertions(+), 239 deletions(-) create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/EventObserver.java delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java rename src/main/java/gov/usgs/volcanoes/swarm/picker/{Event.java => EventOld.java} (97%) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java index ba1ed052..de8c0d76 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java @@ -17,8 +17,16 @@ public Arrival(Element arrivalElement, Map picks) { this.publicId = arrivalElement.getAttribute("publicID"); LOGGER.debug("new arrival {}", publicId); - this.phase = arrivalElement.getAttribute("phase"); - this.pick = picks.get(arrivalElement.getAttribute("pickID")); +// this.phase = arrivalElement.getAttribute("phase"); + this.pick = picks.get(arrivalElement.getElementsByTagName("pickID").item(0).getTextContent()); + this.phase = arrivalElement.getElementsByTagName("phase").item(0).getTextContent(); } +public Pick getPick() { + return pick; +} + +public String getPhase() { + return phase; +} } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java index ecfa14f2..dd1934b7 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java @@ -1,13 +1,19 @@ package gov.usgs.volcanoes.swarm.event; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; import org.w3c.dom.NodeList; +import gov.usgs.volcanoes.swarm.picker.EventObserver; + public class Event { private static final Logger LOGGER = LoggerFactory.getLogger(Event.class); @@ -15,39 +21,53 @@ public class Event { private final Map origins; private final Map magnitudes; private final Map picks; + private final List observers; + private Origin preferredOrigin; private Magnitude preferredMagnitude; private String description; + private String eventSource; + private String evid; - - - public Event(Element event) { - this.publicId = event.getAttribute("publicID"); + public Event(String publicId) { + this.publicId = publicId; LOGGER.debug("New event ({}}", publicId); origins = new HashMap(); magnitudes = new HashMap(); picks = new HashMap(); + observers = new ArrayList(); + } + + public Event(Element event) { + this(event.getAttribute("publicID")); parseEvent(event); } + public void addObserver(EventObserver observer) { + observers.add(observer); + } + private void parseEvent(Element event) { // order matters. parsePicks(event.getElementsByTagName("pick")); - + parseOrigins(event.getElementsByTagName("origin")); preferredOrigin = origins.get(event.getAttribute("preferredOriginID")); if (preferredOrigin == null && origins.size() > 0) { preferredOrigin = (Origin) origins.values().toArray()[0]; } - + parseMagnitudes(event.getElementsByTagName("magnitude")); preferredMagnitude = magnitudes.get(event.getAttribute("preferredMagnitudeID")); if (preferredMagnitude == null && magnitudes.size() > 0) { preferredMagnitude = (Magnitude) magnitudes.values().toArray()[0]; - } + } + + eventSource = event.getAttribute("catalog:eventsource"); + evid = event.getAttribute("catalog:eventid"); } private void parsePicks(NodeList pickElements) { @@ -58,7 +78,7 @@ private void parsePicks(NodeList pickElements) { } } - + private void parseOrigins(NodeList originElements) { int originCount = originElements.getLength(); for (int idx = 0; idx < originCount; idx++) { @@ -84,4 +104,15 @@ public Magnitude getPerferredMagnitude() { return preferredMagnitude; } + public String getEventSource() { + return eventSource; + } + + public String getEvid() { + return evid; + } + public String getDataid() { + return null; + } + } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/EventObserver.java b/src/main/java/gov/usgs/volcanoes/swarm/event/EventObserver.java new file mode 100644 index 00000000..16464325 --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/EventObserver.java @@ -0,0 +1,5 @@ +package gov.usgs.volcanoes.swarm.event; + +public interface EventObserver { + public void updateEvent(); +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java index 6964f61e..9aa5cc84 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java @@ -3,7 +3,11 @@ import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.Date; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.TimeZone; @@ -13,9 +17,15 @@ import org.w3c.dom.Element; import org.w3c.dom.NodeList; + public class Origin { private static final Logger LOGGER = LoggerFactory.getLogger(Origin.class); - private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSX"; + private static final List DATE_FORMATS = new ArrayList(); + + static { + DATE_FORMATS.add("yyyy-MM-dd'T'HH:mm:ss.SSSX"); + DATE_FORMATS.add("yyyy-MM-dd'T'HH:mm:ss.SS"); + } public final String publicId; private double latitude; @@ -27,30 +37,39 @@ public class Origin { public Origin(Element originElement, Map picks) { this.publicId = originElement.getAttribute("publicId"); + arrivals = new HashMap(); + LOGGER.debug("new origin {}", publicId); - this.longitude = Double - .parseDouble(originElement.getElementsByTagName("longitude").item(0).getTextContent()); - this.latitude = - Double.parseDouble(originElement.getElementsByTagName("latitude").item(0).getTextContent()); + Element lonElement = (Element) originElement.getElementsByTagName("longitude").item(0); + longitude = Double.parseDouble(lonElement.getElementsByTagName("value").item(0).getTextContent()); + + Element latElement = (Element) originElement.getElementsByTagName("latitude").item(0); + latitude = Double.parseDouble(latElement.getElementsByTagName("value").item(0).getTextContent()); Element depthElement = (Element) originElement.getElementsByTagName("depth").item(0); depth = Double.parseDouble(depthElement.getElementsByTagName("value").item(0).getTextContent()); - DateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT); - dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - + Element timeElement = (Element) originElement.getElementsByTagName("time").item(0); - try { - time = dateFormat.parse(timeElement.getElementsByTagName("value").item(0).getTextContent()).getTime(); - } catch (DOMException e) { - LOGGER.debug("DOMException parsing origin"); - } catch (ParseException e) { - LOGGER.debug("{ParseException parsing origin"); + time = 0; + Iterator it = DATE_FORMATS.iterator(); + while (it.hasNext() && time < 1) { + String format = it.next(); + DateFormat dateFormat = new SimpleDateFormat(format); + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + try { + time = dateFormat.parse(timeElement.getElementsByTagName("value").item(0).getTextContent()) + .getTime(); + } catch (DOMException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (ParseException e) { + System.out.println(timeElement.getElementsByTagName("value").item(0).getTextContent() + + " didn't match " + format); + } } - - parseArrivals(originElement.getElementsByTagName("arrival"), picks); } @@ -77,4 +96,8 @@ public double getDepth() { public long getTime() { return time; } + + public Collection getArrivals() { + return arrivals.values(); + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java index d154b807..8c60cd7f 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java @@ -1,16 +1,87 @@ package gov.usgs.volcanoes.swarm.event; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.TimeZone; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.w3c.dom.DOMException; import org.w3c.dom.Element; public class Pick { Logger LOGGER = LoggerFactory.getLogger(Pick.class); - - public final String publicId; + private static final List DATE_FORMATS = new ArrayList(); + + static { + DATE_FORMATS.add("yyyy-MM-dd'T'HH:mm:ss.SSSX"); + DATE_FORMATS.add("yyyy-MM-dd'T'HH:mm:ss.SS"); + } + public final String publicId; + private long time; + private String channel; + public Pick(Element pickElement) { publicId = pickElement.getAttribute("publicID"); LOGGER.debug("new PIck {}", publicId); + +// DateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT); +// dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + + Element timeElement = (Element) pickElement.getElementsByTagName("time").item(0); + time = 0; + Iterator it = DATE_FORMATS.iterator(); + while (it.hasNext() && time < 1) { + String format = it.next(); + DateFormat dateFormat = new SimpleDateFormat(format); + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); + try { + time = dateFormat.parse(timeElement.getElementsByTagName("value").item(0).getTextContent()) + .getTime(); + } catch (DOMException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (ParseException e) { + System.out.println(timeElement.getElementsByTagName("value").item(0).getTextContent() + + " didn't match " + format); + } + } + + + + + + + +// try { +// time = dateFormat.parse(timeElement.getElementsByTagName("value").item(0).getTextContent()) +// .getTime(); +// } catch (DOMException e) { +// LOGGER.debug("DOMException parsing origin"); +// } catch (ParseException e) { +// LOGGER.debug("{ParseException parsing origin"); +// } + + + Element waveformId = (Element) pickElement.getElementsByTagName("waveformID").item(0); + String station = waveformId.getAttribute("stationCode"); + String chan = waveformId.getAttribute("channelCode"); + String net = waveformId.getAttribute("networkCode"); + String loc = waveformId.getAttribute("locationCode"); + + channel = station + "$" + chan + "$" + net + "$" + loc; + } + + public long getTime() { + return time; + } + + public String getChannel() { + return channel; } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java deleted file mode 100644 index 6f8930ba..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/Hypocenter.java +++ /dev/null @@ -1,140 +0,0 @@ -package gov.usgs.volcanoes.swarm.map.hypocenters; - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.event.MouseEvent; -import java.awt.geom.Ellipse2D; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Element; - -import gov.usgs.plot.render.DataPointRenderer; -import gov.usgs.volcanoes.core.time.J2kSec; -import gov.usgs.volcanoes.swarm.Swarm; -import gov.usgs.volcanoes.swarm.SwarmConfig; -import gov.usgs.volcanoes.swarm.map.ClickableGeoLabel; - -/** - * - * @author Dan Cervelli - * @author Tom Parker - */ -public class Hypocenter extends ClickableGeoLabel { - private static final int ONE_HOUR = 60 * 60; - private static final int ONE_DAY = ONE_HOUR * 24; - private static final int ONE_WEEK = ONE_DAY * 7; - - private static final SwarmConfig swarmConfig = SwarmConfig.getInstance(); - - private static final Logger LOGGER = LoggerFactory.getLogger(Hypocenter.class); - private final double time; - private final double depth; - private final double magnitude; - private final DataPointRenderer renderer; - private final Element event; - - private Hypocenter(Builder builder) { - time = builder.time; - depth = builder.depth; - magnitude = builder.magnitude; - event = builder.event; - - renderer = new DataPointRenderer(); - renderer.antiAlias = true; - renderer.stroke = new BasicStroke(1.2f); - renderer.filled = true; - renderer.color = Color.LIGHT_GRAY; - // r.shape = Geometry.STAR_10; - renderer.shape = new Ellipse2D.Float(0f, 0f, 7f, 7f); - marker = renderer; - } - - @Override - public Rectangle getClickBox() { - return new Rectangle(-7, -7, 17, 17); - } - - public void setColor(Color color) { - renderer.paint = color; - } - - @Override - public boolean mouseClicked(MouseEvent e) { - LOGGER.debug("event clicked" ); -// Swarm.openPicker(event); - return true; -// Map metadata = swarmConfig.getMetadata(); -// List> nrst = -// Metadata.findNearest(swarmConfig.getMetadata(), location, true); -// Set cleared = new HashSet(); -// if (nrst != null) { -// for (int i = 0, total = 0; i < nrst.size() && total < 10; i++) { -// String ch = nrst.get(i).item2; -// if (ch.matches(".* ..Z .*")) { -// Metadata md = metadata.get(ch); -// MultiMonitor mm = SwarmMultiMonitors.getMonitor(md.source); -// if (!cleared.contains(mm)) { -// mm.removeAllWaves(); -// cleared.add(mm); -// } -// mm.addChannel(ch); -// mm.setVisible(true); -// mm.setPauseStartTime(time - 1); -// mm.setSpan(30); -// total++; -// } -// } -// } - } - - public void draw(Graphics2D g2) { - double age = J2kSec.now() - time; - - if (age < ONE_HOUR) { - renderer.paint = Color.RED; - } else if (age < ONE_DAY) { - renderer.paint = Color.ORANGE; - } else if (age < ONE_WEEK) { - renderer.paint = Color.YELLOW; - } else { - renderer.paint = Color.WHITE; - } - super.draw(g2); - } - - public static class Builder { - private double time; - private double depth; - private double magnitude; - private Element event; - - public Builder() {} - - public Builder magnitude(double magnitude) { - this.magnitude = magnitude; - return this; - } - - public Builder depth(double depth) { - this.depth = depth; - return this; - } - - public Builder time(double time) { - this.time = time; - return this; - } - - public Builder event(Element event) { - this.event = event; - return this; - } - public Hypocenter build() { - return new Hypocenter(this); - } - } - -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java index dd675c0d..db4baef1 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java @@ -15,10 +15,10 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; -import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -70,7 +70,8 @@ public final class HypocenterLayer implements MapLayer, ConfigListener { private Point hoverLocation; public HypocenterLayer() { - events = new HashMap(); +// events = new HashMap(); + events = new ConcurrentHashMap(); dateFormat = new SimpleDateFormat(DATE_FORMAT); swarmConfig = SwarmConfig.getInstance(); swarmConfig.addListener(this); @@ -206,7 +207,7 @@ private void drawPopup(Graphics2D g2) { String mag = String.format("Mag: %.2f", (hoverEvent.getPerferredMagnitude().getMag())); text.add(mag); - + String date = Time.format(Time.STANDARD_TIME_FORMAT, new Date(origin.getTime())); text.add(date); @@ -235,6 +236,7 @@ private void drawPopup(Graphics2D g2) { public boolean mouseClicked(final MouseEvent e) { + hoverEvent = null; if (events.size() < 1l) { return false; } @@ -265,7 +267,15 @@ public boolean mouseClicked(final MouseEvent e) { if (r.contains(e.getPoint())) { LOGGER.debug("event clicked"); - Swarm.openPicker(event); + try { + Swarm.openPicker(getDetailedEvent(event.getEventSource() + event.getEvid())); + } catch (ParserConfigurationException e1) { + e1.printStackTrace(); + } catch (SAXException e1) { + LOGGER.debug("SAXExcepton"); + } catch (IOException e1) { + e1.printStackTrace(); + } return true; } } @@ -273,6 +283,19 @@ public boolean mouseClicked(final MouseEvent e) { return handled; } + private Event getDetailedEvent(String evid) throws ParserConfigurationException, SAXException, IOException { + String url = "http://earthquake.usgs.gov/fdsnws/event/1/query?eventid=" + evid; + + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + Document doc = dBuilder.parse(url); + doc.getDocumentElement().normalize(); + + NodeList eventElements = doc.getElementsByTagName("event"); + LOGGER.debug("Got {} events.", eventElements.getLength()); + return new Event((Element) eventElements.item(0)); + } + public void settingsChanged() { LOGGER.debug("hypocenter plotter sees changed settings."); refreshThread.interrupt(); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/EventLocator.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/EventLocator.java index f2e94d85..39f982e5 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/EventLocator.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/EventLocator.java @@ -3,5 +3,5 @@ import java.io.IOException; public interface EventLocator { - public void locate(Event event) throws IOException; + public void locate(EventOld event) throws IOException; } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/Event.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/EventOld.java similarity index 97% rename from src/main/java/gov/usgs/volcanoes/swarm/picker/Event.java rename to src/main/java/gov/usgs/volcanoes/swarm/picker/EventOld.java index 58c4de2a..1bfd630a 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/Event.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/EventOld.java @@ -8,12 +8,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class Event { - private static final Logger LOGGER = LoggerFactory.getLogger(Event.class); +public class EventOld { + private static final Logger LOGGER = LoggerFactory.getLogger(EventOld.class); private final Map channels; private final List observers; - public Event() { + public EventOld() { channels = new LinkedHashMap(); observers = new ArrayList(); } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/PhasePopup.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/PhasePopup.java index 3bd03e73..3f02ef95 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/PhasePopup.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/PhasePopup.java @@ -15,10 +15,10 @@ public class PhasePopup extends JPopupMenu { private JMenu s; private final String channel; private final long time; - private final Event event; + private final EventOld event; private Component parent; - public PhasePopup(final Event event, final String channel, final long time) { + public PhasePopup(final EventOld event, final String channel, final long time) { this.channel = channel; this.time = time; this.event = event; diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickListPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickListPanel.java index 57bfb2fa..2d3a2bd9 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickListPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickListPanel.java @@ -3,17 +3,17 @@ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; -import java.awt.Dimension; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.font.TextAttribute; +import java.text.SimpleDateFormat; import java.util.Collections; import java.util.HashSet; -import java.util.Map; import java.util.Set; +import java.util.TimeZone; import javax.swing.BorderFactory; import javax.swing.JComboBox; @@ -26,23 +26,26 @@ import org.slf4j.LoggerFactory; import gov.usgs.volcanoes.core.time.Time; +import gov.usgs.volcanoes.swarm.event.Arrival; +import gov.usgs.volcanoes.swarm.event.Event; +import gov.usgs.volcanoes.swarm.event.Origin; +import gov.usgs.volcanoes.swarm.event.Pick; public class PickListPanel extends JPanel implements EventObserver { private static final Logger LOGGER = LoggerFactory.getLogger(PickListPanel.class); private static final Color BACKGROUND_COLOR = new Color(255, 255, 255); private static final Color SELECTED_BACKGROUND_COLOR = new Color(255, 248, 220); - // private static final Color SELECTED_BACKGROUND_COLOR = new Color(0, 0, 220); private static final Font TABLE_FONT = new Font(Font.MONOSPACED, Font.PLAIN, 12); private final Event event; private JPanel pickList; - private Set selected; + private Set selected; private Component parent; public PickListPanel(Event event) { super(); this.event = event; LOGGER.debug("GOT EVENT: {}", event); - selected = new HashSet(); + selected = new HashSet(); setLayout(new BorderLayout()); LOGGER.debug("Event: " + event); @@ -74,7 +77,7 @@ private void writeList(JPanel pickList) { label.setBorder(border); pickList.add(label, c); - label = new JLabel("Type", SwingConstants.CENTER); + label = new JLabel("Phase", SwingConstants.CENTER); label.setBorder(border); pickList.add(label, c); @@ -94,33 +97,40 @@ private void writeList(JPanel pickList) { label.setBorder(border); pickList.add(label, c); - LOGGER.debug("event: {}", event); - Map channels = event.getChannels(); - String[] keys = channels.keySet().toArray(new String[0]); - int idx = keys.length; - while (idx-- > 0) { - c.gridy++; - String chan = keys[idx]; - - EventChannel eventChannel = channels.get(chan); - - Phase phase; - - phase = eventChannel.getPhase(Phase.PhaseType.P); - if (phase != null) { - writePhase(pickList, chan, phase, c); - long coda = eventChannel.getCodaTime(); - if (coda > 0) { - writeCoda(pickList, chan, coda, c); - - } - } - - phase = eventChannel.getPhase(Phase.PhaseType.S); - if (phase != null) { - writePhase(pickList, chan, phase, c); + LOGGER.debug("event: {} : {}", event, event.getPreferredOrigin()); + Origin origin = event.getPreferredOrigin(); + if (origin != null) { + for (Arrival arrival : origin.getArrivals()) { + c.gridy++; + writeArrival(pickList, arrival, c); } - } + } + // Map channels = event.getChannels(); + // String[] keys = channels.keySet().toArray(new String[0]); + // int idx = keys.length; + // while (idx-- > 0) { + // c.gridy++; + // String chan = keys[idx]; + // + // EventChannel eventChannel = channels.get(chan); + // + // Phase phase; + // + // phase = eventChannel.getPhase(Phase.PhaseType.P); + // if (phase != null) { + // writePhase(pickList, chan, phase, c); + // long coda = eventChannel.getCodaTime(); + // if (coda > 0) { + // writeCoda(pickList, chan, coda, c); + // + // } + // } + // + // phase = eventChannel.getPhase(Phase.PhaseType.S); + // if (phase != null) { + // writePhase(pickList, chan, phase, c); + // } + // } c.weighty = 1; c.gridy++; @@ -143,6 +153,91 @@ private void writeCoda(JPanel pickList, String channel, long coda, GridBagConstr } + + + public void writeArrival(final JPanel pickList, final Arrival arrival, + final GridBagConstraints c) { + c.gridy++; + + boolean isSelected = selected.contains(arrival); + Pick pick = arrival.getPick(); + + SimpleDateFormat dateF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + dateF.setTimeZone(TimeZone.getTimeZone("UTC")); + + String time = dateF.format(pick.getTime()); + pickList.add(getLabel(time, isSelected), c); + pickList.add(getLabel(arrival.getPhase(), isSelected), c); + pickList.add(getLabel(pick.getChannel().replace('$', ' '), isSelected), c); + + c.fill = GridBagConstraints.NONE; + final JComboBox weight = new JComboBox(new Integer[] {0, 1, 2, 3, 4}); + weight.setFont(TABLE_FONT); + // weight.setSelectedIndex(phase.weight); + weight.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + // Phase newPhase = new Phase.Builder(phase).weight(weight.getSelectedIndex()).build(); + // event.setPhase(channel, newPhase); + parent.validate(); + parent.repaint(); + } + }); + pickList.add(weight, c); + c.fill = GridBagConstraints.HORIZONTAL; + + c.fill = GridBagConstraints.NONE; + Phase.Onset[] onsets = Phase.Onset.values(); + final JComboBox onset = new JComboBox(onsets); + onset.setFont(TABLE_FONT); + int i = 0; + // while (i < onsets.length && onsets[i] != phase.onset) { + // i++; + // } + onset.setSelectedIndex(i); + onset.addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + // Phase newPhase = + // new Phase.Builder(phase).onset((Phase.Onset) onset.getSelectedItem()).build(); + // event.setPhase(channel, newPhase); + parent.validate(); + parent.repaint(); + } + }); + pickList.add(onset, c); + c.fill = GridBagConstraints.HORIZONTAL; + + // if (phase.phaseType == Phase.PhaseType.P) { + // c.fill = GridBagConstraints.NONE; + // Phase.FirstMotion[] firstMotions = Phase.FirstMotion.values(); + // final JComboBox firstMotion = + // new JComboBox(firstMotions); + // firstMotion.setFont(TABLE_FONT); + // int idx = 0; + // while (idx < firstMotions.length && firstMotions[idx] != phase.firstMotion) { + // idx++; + // } + // firstMotion.setSelectedIndex(idx); + // firstMotion.addActionListener(new ActionListener() { + // + // public void actionPerformed(ActionEvent e) { + // Phase newPhase = new Phase.Builder(phase) + // .firstMotion((Phase.FirstMotion) firstMotion.getSelectedItem()).build(); + // event.setPhase(channel, newPhase); + // parent.validate(); + // parent.repaint(); + // } + // }); + // pickList.add(firstMotion, c); + // c.fill = GridBagConstraints.HORIZONTAL; + // } else { + // pickList.add(new JLabel(""), c); + // } + // } + } + + public void writePhase(final JPanel pickList, final String channel, final Phase phase, final GridBagConstraints c) { @@ -166,7 +261,7 @@ public void writePhase(final JPanel pickList, final String channel, final Phase public void actionPerformed(ActionEvent e) { Phase newPhase = new Phase.Builder(phase).weight(weight.getSelectedIndex()).build(); - event.setPhase(channel, newPhase); + // event.setPhase(channel, newPhase); parent.validate(); parent.repaint(); } @@ -188,7 +283,7 @@ public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) { Phase newPhase = new Phase.Builder(phase).onset((Phase.Onset) onset.getSelectedItem()).build(); - event.setPhase(channel, newPhase); + // event.setPhase(channel, newPhase); parent.validate(); parent.repaint(); } @@ -212,7 +307,7 @@ public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) { Phase newPhase = new Phase.Builder(phase) .firstMotion((Phase.FirstMotion) firstMotion.getSelectedItem()).build(); - event.setPhase(channel, newPhase); + // event.setPhase(channel, newPhase); parent.validate(); parent.repaint(); } @@ -246,20 +341,20 @@ public void deselect(String channel) { public void deselectAll() { LOGGER.debug("deselecting all"); - selected = new HashSet(); + selected = new HashSet(); } public void select(String channel) { LOGGER.debug("selecting {}", channel); - selected.add(channel); + // selected.add(channel); } public void remove(String channel) { LOGGER.debug("removing {}", channel); selected.remove(channel); - event.remove(channel); + // event.remove(channel); } private JLabel getLabel(String string, boolean selected) { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java index 5a9a2e59..722914cd 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java @@ -78,6 +78,7 @@ import gov.usgs.volcanoes.swarm.chooser.DataChooser; import gov.usgs.volcanoes.swarm.data.CachedDataSource; import gov.usgs.volcanoes.swarm.data.SeismicDataSource; +import gov.usgs.volcanoes.swarm.event.Event; import gov.usgs.volcanoes.swarm.picker.hypo71.Hypo71Locator; import gov.usgs.volcanoes.swarm.time.TimeListener; import gov.usgs.volcanoes.swarm.time.WaveViewTime; @@ -141,7 +142,7 @@ public class PickerFrame extends SwarmFrame implements EventObserver { public PickerFrame() { super("Picker", true, true, true, false); - event = new Event(); + event = new Event("testIId"); event.addObserver(this); this.setFocusable(true); @@ -168,9 +169,32 @@ public void actionPerformed(final ActionEvent e) { } - public PickerFrame(gov.usgs.volcanoes.swarm.event.Event event) { - this(); -// this.event = event; + public PickerFrame(Event event) { + super("Picker", true, true, true, false); + this.event = event; + event.addObserver(this); + + this.setFocusable(true); + this.setVisible(true); + selectedSet = new HashSet(); + saveAllDateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); + saveAllDateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); + waves = new ArrayList(); + histories = new HashMap>(); + createUI(); + LOGGER.debug("Finished creating picker frame."); + this.setVisible(true); + + // getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("typed q"), + // "pPick"); + getInputMap().put(KeyStroke.getKeyStroke("typed q"), "pPick"); + getActionMap().put("pPick", new AbstractAction() { + private static final long serialVersionUID = -1; + + public void actionPerformed(final ActionEvent e) { + findWavePanel(); + } + }); } private void findWavePanel() { @@ -441,11 +465,11 @@ public void actionPerformed(final ActionEvent e) { locateButton = SwarmUtil.createToolBarButton(Icons.locate, "Locate", new ActionListener() { public void actionPerformed(final ActionEvent e) { EventLocator locator = new Hypo71Locator(); - try { - locator.locate(event); - } catch (IOException e1) { - e1.printStackTrace(); - }; +// try { +// locator.locate(event); +// } catch (IOException e1) { +// e1.printStackTrace(); +// }; } private void particleMotionPlot() { @@ -534,7 +558,7 @@ public void mousePressed(final AbstractWavePanel src, final MouseEvent e, } } lastClickedIndex = thisIndex; - event.notifyObservers(); +// event.notifyObservers(); mainPanel.validate(); mainPanel.repaint(); } @@ -808,7 +832,7 @@ public synchronized void addWave(final PickerWavePanel p) { p.setStatusLabel(statusLabel); p.setAllowDragging(true); p.setDisplayTitle(true); - p.setEvent(event); +// p.setEvent(event); p.setParent(mainPanel); final int w = scrollPane.getViewport().getSize().width; p.setSize(w, calculateWaveHeight()); @@ -850,7 +874,7 @@ private synchronized void select(final PickerWavePanel p) { } private synchronized void remove(final AbstractWavePanel p) { - event.remove(p.getChannel()); +// event.remove(p.getChannel()); int i = 0; for (i = 0; i < waveBox.getComponentCount(); i++) { if (p == waveBox.getComponent(i)) @@ -869,7 +893,7 @@ private synchronized void remove(final AbstractWavePanel p) { pickList.remove(p.getChannel()); lastClickedIndex = Math.min(lastClickedIndex, waveBox.getComponentCount() - 1); waveToolbar.removeSettings(p.getSettings()); - event.notifyObservers(); +// event.notifyObservers(); validate(); repaint(); } @@ -889,7 +913,7 @@ public synchronized void remove() { LOGGER.debug("removing panel {}", p); waveBox.remove(p); waves.remove(p); - event.remove(p.getChannel()); +// event.remove(p.getChannel()); // pickList.remove(p); validate(); repaint(); @@ -1121,7 +1145,7 @@ public void setVisible(final boolean isVisible) { public void updateEvent() { - LOGGER.debug("event is empty? {}", event.getChannels().isEmpty()); - saveButton.setEnabled(!event.getChannels().isEmpty()); +// LOGGER.debug("event is empty? {}", event.getChannels().isEmpty()); +// saveButton.setEnabled(!event.getChannels().isEmpty()); } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java index 1b1cc088..7002d402 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java @@ -33,7 +33,7 @@ public class PickerWavePanel extends AbstractWavePanel implements EventObserver private static final Color P_BACKGROUND = new Color(128, 255, 128, 192); private static final Color S_BACKGROUND = new Color(128, 128, 255, 192); private static final Color CODA_BACKGROUND = new Color(128, 128, 128, 192); - private Event event; + private EventOld event; private Component parent; public PickerWavePanel(AbstractWavePanel insetWavePanel) { @@ -61,7 +61,7 @@ public void instantPick(PhaseType p) { event.setPhase(channel, phase); WaveViewTime.fireTimeChanged(time); } - public void setEvent(Event event) { + public void setEvent(EventOld event) { this.event = event; } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Locator.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Locator.java index 1eff0c8f..d11d50e2 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Locator.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Locator.java @@ -20,7 +20,7 @@ import gov.usgs.volcanoes.core.hypo71.Hypo71.Results; import gov.usgs.volcanoes.swarm.Metadata; import gov.usgs.volcanoes.swarm.SwarmConfig; -import gov.usgs.volcanoes.swarm.picker.Event; +import gov.usgs.volcanoes.swarm.picker.EventOld; import gov.usgs.volcanoes.swarm.picker.EventChannel; import gov.usgs.volcanoes.swarm.picker.EventLocator; import gov.usgs.volcanoes.swarm.picker.Hypocenters; @@ -54,7 +54,7 @@ public Hypo71Locator() { phaseRecordsList = new LinkedList(); } - public void locate(Event event) throws IOException { + public void locate(EventOld event) throws IOException { generateHypoInputs(event); Results hypoResult = runHypo(event); LOGGER.debug(hypoResult.getPrintOutput()); @@ -67,7 +67,7 @@ public void locate(Event event) throws IOException { } } - private Results runHypo(Event event) throws IOException { + private Results runHypo(EventOld event) throws IOException { Hypo71 hypoCalculator = new Hypo71(); @@ -101,7 +101,7 @@ private Results runHypo(Event event) throws IOException { /** * Generates hypo inputs either from an archived file or from objects in memory */ - private void generateHypoInputs(Event event) { + private void generateHypoInputs(EventOld event) { for (String channel : event.getChannels().keySet()) { String station = channel.split(" ")[0]; From 06130611fc4c26ac1feeb2aaa03d8b3ffae77f99 Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Tue, 15 Mar 2016 17:19:53 -0800 Subject: [PATCH 10/67] Event window in progress... --- pom.xml | 14 +- .../java/gov/usgs/volcanoes/swarm/Swarm.java | 20 +- .../data/fdsnWs/AbstractDataRecordClient.java | 12 +- .../swarm/data/fdsnWs/WebServicesClient.java | 47 +++ .../gov/usgs/volcanoes/swarm/event/Event.java | 64 +++- .../volcanoes/swarm/event/EventFrame.java | 322 ++++++++++++++++++ .../volcanoes/swarm/event/EventObserver.java | 2 +- .../usgs/volcanoes/swarm/event/Magnitude.java | 4 + .../map/hypocenters/HypocenterLayer.java | 73 ++-- .../volcanoes/swarm/picker/EventObserver.java | 5 - .../usgs/volcanoes/swarm/picker/EventOld.java | 8 +- .../volcanoes/swarm/picker/PickListPanel.java | 17 +- .../volcanoes/swarm/picker/PickerFrame.java | 9 +- .../swarm/picker/PickerWavePanel.java | 18 +- 14 files changed, 516 insertions(+), 99 deletions(-) create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/picker/EventObserver.java diff --git a/pom.xml b/pom.xml index ef083235..64d8ad2b 100644 --- a/pom.xml +++ b/pom.xml @@ -406,13 +406,6 @@ http://volcanoes.usgs.gov/software/maven2/ - @@ -489,7 +482,7 @@ gov.usgs.volcanoes volcano-core - [1.3.2,) + [1.3.3,) gov.usgs.volcanoes @@ -501,11 +494,6 @@ netty-all 4.0.31.Final - - com.mastfrog - netty-http-client - 1.6.4 - opensymphony oscache diff --git a/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java b/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java index 120bd926..b889fbe1 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java @@ -1,5 +1,10 @@ package gov.usgs.volcanoes.swarm; +import com.jgoodies.looks.plastic.Plastic3DLookAndFeel; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.awt.Dimension; import java.awt.Frame; import java.awt.KeyboardFocusManager; @@ -24,12 +29,6 @@ import javax.swing.SwingUtilities; import javax.swing.UIManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Element; - -import com.jgoodies.looks.plastic.Plastic3DLookAndFeel; - import gov.usgs.plot.data.Wave; import gov.usgs.volcanoes.core.configfile.ConfigFile; import gov.usgs.volcanoes.core.time.CurrentTime; @@ -40,6 +39,7 @@ import gov.usgs.volcanoes.swarm.data.CachedDataSource; import gov.usgs.volcanoes.swarm.data.SeismicDataSource; import gov.usgs.volcanoes.swarm.event.Event; +import gov.usgs.volcanoes.swarm.event.EventFrame; import gov.usgs.volcanoes.swarm.heli.HelicorderViewerFrame; import gov.usgs.volcanoes.swarm.internalFrame.InternalFrameListener; import gov.usgs.volcanoes.swarm.internalFrame.SwarmInternalFrames; @@ -967,5 +967,13 @@ public static void main(final String[] args) { swarm.parseKiosk(); } + public static EventFrame openEvent(Event event) { + EventFrame eventFrame = new EventFrame(event); + eventFrame.setVisible(true); + eventFrame.requestFocus(); + SwarmInternalFrames.add(eventFrame); + return eventFrame; + } + } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/AbstractDataRecordClient.java b/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/AbstractDataRecordClient.java index f94e6459..f92ec0ec 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/AbstractDataRecordClient.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/AbstractDataRecordClient.java @@ -43,7 +43,7 @@ public AbstractDataRecordClient(SeismicDataSource source) { * @throws UnsupportedCompressionType * @throws CodecException */ - public List addWaves(final List waves, final DataRecord dr) + public static List addWaves(final List waves, final DataRecord dr) throws UnsupportedCompressionType, CodecException { for (Blockette blockette : dr.getBlockettes(1000)) { if (blockette instanceof Blockette1000) { @@ -67,7 +67,7 @@ public void assignChannels(List channels) { * * @return the list of waves. */ - public List createWaves() { + public static List createWaves() { return new ArrayList(); } @@ -84,7 +84,7 @@ public List createWaves() { * @param t the time. * @return the date. */ - protected Date getDate(double t) { + protected static Date getDate(double t) { return J2kSec.asDate(t); } @@ -94,7 +94,7 @@ protected Date getDate(double t) { * @param date the date. * @return the text. */ - protected String getDateText(Date date) { + protected static String getDateText(Date date) { return WebServiceUtils.getDateText(date); } @@ -104,7 +104,7 @@ protected String getDateText(Date date) { * @param date the date. * @return the text. */ - protected String getDateText(double t) { + protected static String getDateText(double t) { return getDateText(getDate(t)); } @@ -133,7 +133,7 @@ public SeismicDataSource getSource() { * @param waves the list of Wave s * @return the new joined wave */ - public Wave join(List waves) { + public static Wave join(List waves) { // TODO ensure index is good and no gaps? return Wave.join(waves); } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesClient.java b/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesClient.java index fdeae728..52232ffb 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesClient.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesClient.java @@ -223,4 +223,51 @@ public boolean processRecord(DataRecord dr) { } return wave; } + + /** + * Retrieve a single waveform without providing full SDS functions. + * + * TODO: integrate with getRawData(). should all SDSs have a static wave retrieval method? + * + * @param channelInfo the channel information. + * @param t1 the start time. + * @param t2 the end time. + * @return the raw data. + */ + public static Wave getWave(final String wsDataSelectUrl, final ChannelInfo channelInfo, final double t1, final double t2) { + final Date begin = getDate(t1); + final Date end = getDate(t2); + final List waves = createWaves(); + final DataSelectReader reader = new DataSelectReader(wsDataSelectUrl) { + /** + * Process a data record. + * + * @param dr the data record. + * @return true if data record should be added to the list, false + * otherwise. + */ + public boolean processRecord(DataRecord dr) { + try { + addWaves(waves, dr); + } catch (Exception ex) { + LOGGER.warn("could not get web service raw data ({}): {}", channelInfo, ex.getMessage()); + } + return true; + } + }; + try { + final String query = reader.createQuery(channelInfo.getNetwork(), channelInfo.getStation(), + channelInfo.getLocation(), channelInfo.getChannel(), begin, end); + reader.read(query, (List) null); + } catch (Exception ex) { + LOGGER.warn("could not get web service raw data ({}): {}", channelInfo, ex.getMessage()); + } + Wave wave = join(waves); + if (wave != null && WebServiceUtils.isDebug()) { + LOGGER.debug("web service raw data ({}, {})", getDateText(wave.getStartTime()), + getDateText(wave.getEndTime()) + ")"); + } + return wave; + } + } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java index dd1934b7..ed89e07e 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java @@ -1,18 +1,24 @@ package gov.usgs.volcanoes.swarm.event; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import gov.usgs.volcanoes.core.util.StringUtils; -import gov.usgs.volcanoes.swarm.picker.EventObserver; public class Event { private static final Logger LOGGER = LoggerFactory.getLogger(Event.class); @@ -42,14 +48,14 @@ public Event(String publicId) { public Event(Element event) { this(event.getAttribute("publicID")); - parseEvent(event); + updateEvent(event); } public void addObserver(EventObserver observer) { observers.add(observer); } - private void parseEvent(Element event) { + public void updateEvent(Element event) { // order matters. parsePicks(event.getElementsByTagName("pick")); @@ -66,11 +72,22 @@ private void parseEvent(Element event) { preferredMagnitude = (Magnitude) magnitudes.values().toArray()[0]; } - eventSource = event.getAttribute("catalog:eventsource"); - evid = event.getAttribute("catalog:eventid"); + eventSource = StringUtils.stringToString(event.getAttribute("catalog:eventsource"), eventSource); + evid = StringUtils.stringToString(event.getAttribute("catalog:eventid"), evid); + + Element descriptionElement = (Element) event.getElementsByTagName("description").item(0); + description = StringUtils.stringToString(descriptionElement.getElementsByTagName("text").item(0).getTextContent(), description); + + notifyObservers(); } + private void notifyObservers() { + for (EventObserver observer : observers) { + observer.eventUpdated(); + } + } private void parsePicks(NodeList pickElements) { + picks.clear(); int pickCount = pickElements.getLength(); for (int idx = 0; idx < pickCount; idx++) { Pick pick = new Pick((Element) pickElements.item(idx)); @@ -80,6 +97,7 @@ private void parsePicks(NodeList pickElements) { private void parseOrigins(NodeList originElements) { + origins.clear(); int originCount = originElements.getLength(); for (int idx = 0; idx < originCount; idx++) { Origin origin = new Origin((Element) originElements.item(idx), picks); @@ -93,8 +111,9 @@ public Origin getPreferredOrigin() { } private void parseMagnitudes(NodeList magnitudeElements) { - int originCount = magnitudeElements.getLength(); - for (int idx = 0; idx < originCount; idx++) { + magnitudes.clear(); + int magnitudeCount = magnitudeElements.getLength(); + for (int idx = 0; idx < magnitudeCount; idx++) { Magnitude magnitude = new Magnitude((Element) magnitudeElements.item(idx)); magnitudes.put(magnitude.publicId, magnitude); } @@ -115,4 +134,21 @@ public String getDataid() { return null; } -} + public String getDescription() { + return description; + } + +private Event getDetailedEvent(String evid) + throws ParserConfigurationException, SAXException, IOException { + String url = "http://earthquake.usgs.gov/fdsnws/event/1/query?eventid=" + evid; + + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + Document doc = dBuilder.parse(url); + doc.getDocumentElement().normalize(); + + NodeList eventElements = doc.getElementsByTagName("event"); + LOGGER.debug("Got {} events.", eventElements.getLength()); + return new Event((Element) eventElements.item(0)); + } +} \ No newline at end of file diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java new file mode 100644 index 00000000..aa0417f7 --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java @@ -0,0 +1,322 @@ +package gov.usgs.volcanoes.swarm.event; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.io.IOException; +import java.text.SimpleDateFormat; + +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.ScrollPaneConstants; +import javax.swing.SwingConstants; +import javax.swing.WindowConstants; +import javax.swing.event.InternalFrameAdapter; +import javax.swing.event.InternalFrameEvent; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import gov.usgs.volcanoes.swarm.Icons; +import gov.usgs.volcanoes.swarm.SwarmFrame; +import gov.usgs.volcanoes.swarm.data.SeismicDataSource; +import gov.usgs.volcanoes.swarm.data.fdsnWs.WebServicesClient; +import gov.usgs.volcanoes.swarm.data.fdsnWs.WebServicesSource; +import gov.usgs.volcanoes.swarm.internalFrame.SwarmInternalFrames; +import gov.usgs.volcanoes.swarm.wave.WaveViewPanel; + +/** + * The picker internal frame. Adapted from the WaveClipboardFrame. + * + * @author Tom Parker + */ +public class EventFrame extends SwarmFrame implements EventObserver { + private static final Logger LOGGER = LoggerFactory.getLogger(EventFrame.class); + private static final Color BACKGROUND_COLOR = new Color(255, 255, 255); + private static final Font KEY_FONT = Font.decode("dialog-BOLD-12"); + private static final Font VALUE_FONT = Font.decode("dialog-12"); + + public static final long serialVersionUID = -1; + + private JSplitPane mainPanel; + private Event event; + private SeismicDataSource seismicDataSource; + + public EventFrame(Event event) { + super("Event - " + event.getEvid(), true, true, true, false); + this.event = event; + + event.addObserver(this); + this.setFocusable(true); + createUI(); + createListeners(); + this.setVisible(true); + fetchDetailedEvent(event); + } + + private void fetchDetailedEvent(Event event) { + final String neicEvid = event.getEventSource() + event.getEvid(); + final Event workingEvent = event; + + new Thread() { + public void run() { + String url = "http://earthquake.usgs.gov/fdsnws/event/1/query?eventid=" + neicEvid; + + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = null; + Document doc = null; + try { + + dBuilder = dbFactory.newDocumentBuilder(); + doc = dBuilder.parse(url); + doc.getDocumentElement().normalize(); + NodeList eventElements = doc.getElementsByTagName("event"); + LOGGER.debug("Got {} events.", eventElements.getLength()); + workingEvent.updateEvent((Element) eventElements.item(0)); + + WebServicesClient.getWave(wsDataSelectUrl, channelInfo, t1, t2); + + } catch (SAXException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } catch (IOException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } catch (ParserConfigurationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + }.start(); + } + + private void createUI() { + this.setFrameIcon(Icons.ruler); + this.setSize(swarmConfig.clipboardWidth, swarmConfig.clipboardHeight); + this.setLocation(swarmConfig.clipboardX, swarmConfig.clipboardY); + this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + LOGGER.debug("event frame: {} @ {}", this.getSize(), this.getLocation()); + + // JPanel pickPanel = new JPanel(); + // pickPanel.setLayout(new BoxLayout(pickPanel, BoxLayout.PAGE_AXIS)); + + mainPanel = + new JSplitPane(JSplitPane.VERTICAL_SPLIT, createParameterPanel(), createPickPanel()); + mainPanel.setOneTouchExpandable(true); + + + // scrollPane = new JScrollPane(createParameterPanel()); + // parameterPanel.add(scrollPane, BorderLayout.NORTH); + + // Box pickBox = new Box(BoxLayout.Y_AXIS); + // scrollPane = new JScrollPane(pickBox); + // scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + // scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + // scrollPane.getVerticalScrollBar().setUnitIncrement(40); + // pickPanel.add(scrollPane, BorderLayout.NORTH); + + // mainPanel.setResizeWeight(.25); + this.setContentPane(mainPanel); + } + + + private Component createParameterPanel() { + Origin origin = event.getPreferredOrigin(); + Magnitude magnitude = event.getPerferredMagnitude(); + + JPanel parameterPanel = new JPanel(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.NORTHWEST; + c.gridy = 0; + c.gridx = GridBagConstraints.RELATIVE; + c.ipadx = 3; + c.ipady = 2; + + JLabel label; + + label = new JLabel("Description: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + label = new JLabel(event.getDescription(), SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + + c.gridy++; + + label = new JLabel("Origin date: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + if (origin != null) { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + String date = dateFormat.format(event.getPreferredOrigin().getTime()); + label = new JLabel(date, SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + } + c.gridy++; + + label = new JLabel("Magnitude: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + if (magnitude != null) { + String mag = String.format("%s (%s)", magnitude.getMag(), magnitude.getType()); + label = new JLabel(mag, SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + } + c.gridy++; + + label = new JLabel("Location: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + if (origin != null) { + String loc = origin.getLatitude() + ", " + origin.getLongitude(); + loc += " at " + (origin.getDepth() / 1000) + " km depth"; + label = new JLabel(loc, SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + } + c.gridy++; + + c.weighty = 1; + c.weightx = 1; + c.gridy++; + c.gridx = 10; + JPanel filler = new JPanel(); + parameterPanel.add(filler, c); + + return parameterPanel; + } + + private Component createPickPanel() { + Box pickBox = new Box(BoxLayout.Y_AXIS); + + Origin origin = event.getPreferredOrigin(); + Magnitude magnitude = event.getPerferredMagnitude(); + + long firstPick = Long.MAX_VALUE; + long lastPick = Long.MIN_VALUE; + for (Arrival arrival : origin.getArrivals()) { + WaveViewPanel wavePanel = new WaveViewPanel(); + + Pick pick = arrival.getPick(); + firstPick = Math.min(pick.getTime(), firstPick); + lastPick = Math.max(pick.getTime(), lastPick); + String channel = pick.getChannel(); + wavePanel.setChannel(channel); + + pickBox.add(wavePanel); + } + + JScrollPane scrollPane = new JScrollPane(pickBox); + scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + scrollPane.getVerticalScrollBar().setUnitIncrement(40); + + return scrollPane; + } + + // public synchronized void addWave(final String chan) { + // SeismicDataSource sds = p2.getDataSource(); + // double st = p2.getStartTime(); + // double et = p2.getEndTime(); + // Wave wave = sds.getWave(chan, st, et); + // if (wave != null && wave.isData()) { + // p2.setWave(wave, st, et); + // p2.getWaveViewSettings().autoScaleAmpMemory = false; + // addWave(p2); + // } + // } + // + // public synchronized void addWave(final PickerWavePanel p) { + // p.addListener(selectListener); + // p.setOffsets(54, 8, 21, 19); + // p.setAllowClose(true); + // p.setStatusLabel(statusLabel); + // p.setAllowDragging(true); + // p.setDisplayTitle(true); + //// p.setEvent(event); + // p.setParent(mainPanel); + // final int w = scrollPane.getViewport().getSize().width; + // p.setSize(w, calculateWaveHeight()); + // p.setBottomBorderColor(Color.GRAY); + // p.createImage(); + // waveBox.add(p); + // waves.add(p); + // LOGGER.debug("{} panels; {} waves", waveBox.getComponentCount(), waves.size()); + // } + + @Override + public void paint(final Graphics g) { + super.paint(g); + // if (waves.size() == 0) { + // final Dimension dim = this.getSize(); + // g.setColor(Color.black); + // g.drawString("Picker empty.", dim.width / 2 - 40, dim.height / 2); + // } + } + + @Override + public void setVisible(final boolean isVisible) { + LOGGER.debug("Visible = {}", isVisible); + super.setVisible(isVisible); + if (isVisible) + toFront(); + } + + + public void eventUpdated() { + mainPanel.setTopComponent(createParameterPanel()); + mainPanel.setBottomComponent(createPickPanel()); + } + + private void createListeners() { + this.addInternalFrameListener(new InternalFrameAdapter() { + @Override + public void internalFrameActivated(final InternalFrameEvent e) {} + + @Override + public void internalFrameDeiconified(final InternalFrameEvent e) {} + + @Override + public void internalFrameClosing(final InternalFrameEvent e) { + dispose(); + SwarmInternalFrames.remove(EventFrame.this); + } + + @Override + public void internalFrameClosed(final InternalFrameEvent e) {} + }); + + this.addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(final ComponentEvent e) {} + }); + + + } + +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/EventObserver.java b/src/main/java/gov/usgs/volcanoes/swarm/event/EventObserver.java index 16464325..c7d52064 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/EventObserver.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/EventObserver.java @@ -1,5 +1,5 @@ package gov.usgs.volcanoes.swarm.event; public interface EventObserver { - public void updateEvent(); + public void eventUpdated(); } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Magnitude.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Magnitude.java index d330f38f..23cb31cf 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Magnitude.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Magnitude.java @@ -24,5 +24,9 @@ public Magnitude(Element magnitudeElement) { public double getMag() { return mag; } + + public String getType() { + return type; + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java index db4baef1..d633fa9e 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java @@ -1,5 +1,13 @@ package gov.usgs.volcanoes.swarm.map.hypocenters; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + import java.awt.BasicStroke; import java.awt.Color; import java.awt.FontMetrics; @@ -24,14 +32,6 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.DOMException; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - import gov.usgs.plot.render.DataPointRenderer; import gov.usgs.proj.GeoRange; import gov.usgs.proj.Projection; @@ -41,6 +41,7 @@ import gov.usgs.volcanoes.swarm.Swarm; import gov.usgs.volcanoes.swarm.SwarmConfig; import gov.usgs.volcanoes.swarm.event.Event; +import gov.usgs.volcanoes.swarm.event.Magnitude; import gov.usgs.volcanoes.swarm.event.Origin; import gov.usgs.volcanoes.swarm.map.MapFrame; import gov.usgs.volcanoes.swarm.map.MapLayer; @@ -70,8 +71,8 @@ public final class HypocenterLayer implements MapLayer, ConfigListener { private Point hoverLocation; public HypocenterLayer() { -// events = new HashMap(); - events = new ConcurrentHashMap(); + // events = new HashMap(); + events = new ConcurrentHashMap(); dateFormat = new SimpleDateFormat(DATE_FORMAT); swarmConfig = SwarmConfig.getInstance(); swarmConfig.addListener(this); @@ -189,27 +190,52 @@ public void draw(Graphics2D g2) { renderer.renderAtOrigin(g2); if (event == hoverEvent) { - drawPopup(g2); } g2.translate(-res.x, -res.y); } + + drawPopup(g2); } private void drawPopup(Graphics2D g2) { + if (hoverEvent == null) { + return; + } Origin origin = hoverEvent.getPreferredOrigin(); + GeoRange range = panel.getRange(); + Projection projection = panel.getProjection(); + int widthPx = panel.getGraphWidth(); + int heightPx = panel.getGraphHeight(); + int insetPx = panel.getInset(); + + final Point2D.Double xy = + projection.forward(new Point2D.Double(origin.getLongitude(), origin.getLatitude())); + final double[] ext = range.getProjectedExtents(projection); + final double dx = (ext[1] - ext[0]); + final double dy = (ext[3] - ext[2]); + final Point2D.Double res = new Point2D.Double(); + res.x = (((xy.x - ext[0]) / dx) * widthPx + insetPx); + res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); + + g2.translate(res.x, res.y); g2.setStroke(new BasicStroke(1.2f)); g2.setColor(new Color(0, 0, 0, 64)); List text = new ArrayList(3); - String depth = String.format("Depth: %.2f km", (origin.getDepth() / 1000)); - text.add(depth); + // String depth = String.format("Depth: %.2f km", (origin.getDepth() / 1000)); + // text.add(depth); - String mag = String.format("Mag: %.2f", (hoverEvent.getPerferredMagnitude().getMag())); + Magnitude magElement = hoverEvent.getPerferredMagnitude(); + String mag = String.format("%.2f %s at %.2f km depth", magElement.getMag(), + magElement.getType(), (origin.getDepth() / 1000)); text.add(mag); String date = Time.format(Time.STANDARD_TIME_FORMAT, new Date(origin.getTime())); - text.add(date); + text.add(date + " UTC"); + + String description = hoverEvent.getDescription(); + text.add(description); FontMetrics fm = g2.getFontMetrics(); int height = 2 * POPUP_PADDING; @@ -232,6 +258,8 @@ private void drawPopup(Graphics2D g2) { Rectangle2D bounds = fm.getStringBounds(string, g2); baseY += (int) (Math.ceil(bounds.getHeight()) + 2); } + g2.translate(-res.x, -res.y); + } public boolean mouseClicked(final MouseEvent e) { @@ -267,15 +295,7 @@ public boolean mouseClicked(final MouseEvent e) { if (r.contains(e.getPoint())) { LOGGER.debug("event clicked"); - try { - Swarm.openPicker(getDetailedEvent(event.getEventSource() + event.getEvid())); - } catch (ParserConfigurationException e1) { - e1.printStackTrace(); - } catch (SAXException e1) { - LOGGER.debug("SAXExcepton"); - } catch (IOException e1) { - e1.printStackTrace(); - } + Swarm.openEvent(event); return true; } } @@ -283,7 +303,8 @@ public boolean mouseClicked(final MouseEvent e) { return handled; } - private Event getDetailedEvent(String evid) throws ParserConfigurationException, SAXException, IOException { + private Event getDetailedEvent(String evid) + throws ParserConfigurationException, SAXException, IOException { String url = "http://earthquake.usgs.gov/fdsnws/event/1/query?eventid=" + evid; DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); @@ -322,7 +343,7 @@ public boolean mouseMoved(MouseEvent e) { while (it.hasNext() && handled == false) { Event event = it.next(); Origin origin = event.getPreferredOrigin(); - final Rectangle r = new Rectangle(-7, -7, 17, 17); + final Rectangle r = new Rectangle(0, 0, 10, 10); final Point2D.Double xy = projection.forward(new Point2D.Double(origin.getLongitude(), origin.getLatitude())); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/EventObserver.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/EventObserver.java deleted file mode 100644 index 900ecbc4..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/EventObserver.java +++ /dev/null @@ -1,5 +0,0 @@ -package gov.usgs.volcanoes.swarm.picker; - -public interface EventObserver { - public void updateEvent(); -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/EventOld.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/EventOld.java index 1bfd630a..9c4783b0 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/EventOld.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/EventOld.java @@ -1,12 +1,14 @@ package gov.usgs.volcanoes.swarm.picker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import gov.usgs.volcanoes.swarm.event.EventObserver; public class EventOld { private static final Logger LOGGER = LoggerFactory.getLogger(EventOld.class); @@ -61,7 +63,7 @@ public void addObserver(EventObserver observer) { public void notifyObservers() { for (EventObserver observer : observers) { - observer.updateEvent(); + observer.eventUpdated(); } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickListPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickListPanel.java index 2d3a2bd9..27d17b18 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickListPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickListPanel.java @@ -1,5 +1,8 @@ package gov.usgs.volcanoes.swarm.picker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; @@ -22,12 +25,10 @@ import javax.swing.SwingConstants; import javax.swing.border.Border; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import gov.usgs.volcanoes.core.time.Time; import gov.usgs.volcanoes.swarm.event.Arrival; import gov.usgs.volcanoes.swarm.event.Event; +import gov.usgs.volcanoes.swarm.event.EventObserver; import gov.usgs.volcanoes.swarm.event.Origin; import gov.usgs.volcanoes.swarm.event.Pick; @@ -96,7 +97,6 @@ private void writeList(JPanel pickList) { label = new JLabel("First Motion", SwingConstants.CENTER); label.setBorder(border); pickList.add(label, c); - LOGGER.debug("event: {} : {}", event, event.getPreferredOrigin()); Origin origin = event.getPreferredOrigin(); if (origin != null) { @@ -158,7 +158,6 @@ private void writeCoda(JPanel pickList, String channel, long coda, GridBagConstr public void writeArrival(final JPanel pickList, final Arrival arrival, final GridBagConstraints c) { c.gridy++; - boolean isSelected = selected.contains(arrival); Pick pick = arrival.getPick(); @@ -185,7 +184,6 @@ public void actionPerformed(ActionEvent e) { }); pickList.add(weight, c); c.fill = GridBagConstraints.HORIZONTAL; - c.fill = GridBagConstraints.NONE; Phase.Onset[] onsets = Phase.Onset.values(); final JComboBox onset = new JComboBox(onsets); @@ -319,7 +317,7 @@ public void actionPerformed(ActionEvent e) { } } - public void updateEvent() { + public void eventUpdated() { if (event == null) { return; } @@ -382,7 +380,10 @@ public void setParent(Component parent) { } public void repaint() { - updateEvent(); + eventUpdated(); super.repaint(); + + + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java index 722914cd..50dbdfcb 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java @@ -1,5 +1,8 @@ package gov.usgs.volcanoes.swarm.picker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; @@ -54,9 +57,6 @@ import javax.swing.event.InternalFrameAdapter; import javax.swing.event.InternalFrameEvent; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import gov.usgs.plot.data.Wave; import gov.usgs.plot.data.file.FileType; import gov.usgs.plot.data.file.SeismicDataFile; @@ -79,6 +79,7 @@ import gov.usgs.volcanoes.swarm.data.CachedDataSource; import gov.usgs.volcanoes.swarm.data.SeismicDataSource; import gov.usgs.volcanoes.swarm.event.Event; +import gov.usgs.volcanoes.swarm.event.EventObserver; import gov.usgs.volcanoes.swarm.picker.hypo71.Hypo71Locator; import gov.usgs.volcanoes.swarm.time.TimeListener; import gov.usgs.volcanoes.swarm.time.WaveViewTime; @@ -1144,7 +1145,7 @@ public void setVisible(final boolean isVisible) { } - public void updateEvent() { + public void eventUpdated() { // LOGGER.debug("event is empty? {}", event.getChannels().isEmpty()); // saveButton.setEnabled(!event.getChannels().isEmpty()); } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java index 7002d402..751aa216 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java @@ -1,26 +1,18 @@ package gov.usgs.volcanoes.swarm.picker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.awt.Color; import java.awt.Component; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; -import java.awt.MouseInfo; -import java.awt.Point; -import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; import java.awt.geom.Line2D; -import javax.swing.AbstractAction; -import javax.swing.JComponent; -import javax.swing.KeyStroke; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import gov.usgs.volcanoes.core.time.J2kSec; -import gov.usgs.volcanoes.core.ui.GlobalKeyManager; -import gov.usgs.volcanoes.core.ui.UiUtils; +import gov.usgs.volcanoes.swarm.event.EventObserver; import gov.usgs.volcanoes.swarm.picker.Phase.PhaseType; import gov.usgs.volcanoes.swarm.time.WaveViewTime; import gov.usgs.volcanoes.swarm.wave.AbstractWavePanel; @@ -157,7 +149,7 @@ protected void processRightMouseRelease(MouseEvent e) { pauseCursorMark = false; } - public void updateEvent() { + public void eventUpdated() { repaint(); } From 96e071200adc758a243b558f870c835ee9f1fb00 Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Wed, 16 Mar 2016 14:47:16 -0800 Subject: [PATCH 11/67] Continue work on Event window. Waves not plotting. Concurrency issue? --- .../java/gov/usgs/volcanoes/swarm/Swarm.java | 11 +- .../swarm/data/fdsnWs/WebServicesClient.java | 49 +++-- .../gov/usgs/volcanoes/swarm/event/Event.java | 4 +- .../volcanoes/swarm/event/EventFrame.java | 202 ++++++++---------- .../swarm/wave/AbstractWavePanel.java | 9 + 5 files changed, 138 insertions(+), 137 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java b/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java index b889fbe1..f1f625fe 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java @@ -437,7 +437,7 @@ public void setFullScreenMode(final boolean full) { for (final JInternalFrame frame : SwarmInternalFrames.getFrames()) { // Why did this check isVisible()? -// if (frame.isVisible() && frame instanceof Kioskable) { + // if (frame.isVisible() && frame instanceof Kioskable) { if (frame instanceof Kioskable) { final Kioskable f = (Kioskable) frame; f.setKioskMode(full); @@ -588,8 +588,8 @@ public static PickerFrame openPicker(final WaveViewPanel insetWavePanel) { pickerFrame.setBaseWave(p); return pickerFrame; } - - public static PickerFrame openPicker(Event event) { + + public static PickerFrame openPicker(Event event) { PickerFrame pickerFrame = new PickerFrame(event); pickerFrame.setVisible(true); pickerFrame.requestFocus(); @@ -967,11 +967,12 @@ public static void main(final String[] args) { swarm.parseKiosk(); } - public static EventFrame openEvent(Event event) { - EventFrame eventFrame = new EventFrame(event); + public static EventFrame openEvent(final Event event) { + final EventFrame eventFrame = new EventFrame(event); eventFrame.setVisible(true); eventFrame.requestFocus(); SwarmInternalFrames.add(eventFrame); + return eventFrame; } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesClient.java b/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesClient.java index 52232ffb..7bf92dc6 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesClient.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesClient.java @@ -5,11 +5,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; import java.util.Date; import java.util.List; import gov.usgs.plot.data.Wave; import gov.usgs.volcanoes.swarm.ChannelInfo; +import gov.usgs.volcanoes.swarm.SwarmConfig; import gov.usgs.volcanoes.swarm.data.DataSelectReader; import gov.usgs.volcanoes.swarm.data.SeismicDataSource; @@ -223,7 +225,7 @@ public boolean processRecord(DataRecord dr) { } return wave; } - + /** * Retrieve a single waveform without providing full SDS functions. * @@ -234,33 +236,34 @@ public boolean processRecord(DataRecord dr) { * @param t2 the end time. * @return the raw data. */ - public static Wave getWave(final String wsDataSelectUrl, final ChannelInfo channelInfo, final double t1, final double t2) { + public static Wave getWave(final String code, final double t1, final double t2) { final Date begin = getDate(t1); final Date end = getDate(t2); - final List waves = createWaves(); - final DataSelectReader reader = new DataSelectReader(wsDataSelectUrl) { - /** - * Process a data record. - * - * @param dr the data record. - * @return true if data record should be added to the list, false - * otherwise. - */ - public boolean processRecord(DataRecord dr) { - try { - addWaves(waves, dr); - } catch (Exception ex) { - LOGGER.warn("could not get web service raw data ({}): {}", channelInfo, ex.getMessage()); - } - return true; - } - }; + final List waves = new ArrayList(); + final DataSelectReader reader = + new DataSelectReader(SwarmConfig.getInstance().fdsnDataselectURL) { + /** + * Process a data record. + * + * @param dr the data record. + * @return true if data record should be added to the list, false + * otherwise. + */ + public boolean processRecord(DataRecord dr) { + try { + addWaves(waves, dr); + } catch (Exception ex) { + LOGGER.warn("could not get web service raw data ({}): {}", code, ex.getMessage()); + } + return true; + } + }; try { - final String query = reader.createQuery(channelInfo.getNetwork(), channelInfo.getStation(), - channelInfo.getLocation(), channelInfo.getChannel(), begin, end); + String[] comps = code.split("\\$"); + final String query = reader.createQuery(comps[2], comps[0], (comps.length > 3 ? comps[3] : "--"), comps[1], begin, end); reader.read(query, (List) null); } catch (Exception ex) { - LOGGER.warn("could not get web service raw data ({}): {}", channelInfo, ex.getMessage()); + LOGGER.warn("could not get web service raw data ({}): {}", code, ex.getMessage()); } Wave wave = join(waves); if (wave != null && WebServiceUtils.isDebug()) { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java index ed89e07e..aac135a6 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java @@ -76,7 +76,9 @@ public void updateEvent(Element event) { evid = StringUtils.stringToString(event.getAttribute("catalog:eventid"), evid); Element descriptionElement = (Element) event.getElementsByTagName("description").item(0); - description = StringUtils.stringToString(descriptionElement.getElementsByTagName("text").item(0).getTextContent(), description); + if (descriptionElement != null) { + description = StringUtils.stringToString(descriptionElement.getElementsByTagName("text").item(0).getTextContent(), description); + } notifyObservers(); } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java index aa0417f7..b4c56005 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java @@ -33,11 +33,14 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import gov.usgs.plot.data.Wave; +import gov.usgs.volcanoes.core.time.J2kSec; import gov.usgs.volcanoes.swarm.Icons; import gov.usgs.volcanoes.swarm.SwarmFrame; +import gov.usgs.volcanoes.swarm.SwingWorker; +import gov.usgs.volcanoes.swarm.data.CachedDataSource; import gov.usgs.volcanoes.swarm.data.SeismicDataSource; import gov.usgs.volcanoes.swarm.data.fdsnWs.WebServicesClient; -import gov.usgs.volcanoes.swarm.data.fdsnWs.WebServicesSource; import gov.usgs.volcanoes.swarm.internalFrame.SwarmInternalFrames; import gov.usgs.volcanoes.swarm.wave.WaveViewPanel; @@ -57,84 +60,48 @@ public class EventFrame extends SwarmFrame implements EventObserver { private JSplitPane mainPanel; private Event event; private SeismicDataSource seismicDataSource; + private final JPanel pickBox; public EventFrame(Event event) { super("Event - " + event.getEvid(), true, true, true, false); this.event = event; - event.addObserver(this); this.setFocusable(true); - createUI(); createListeners(); - this.setVisible(true); - fetchDetailedEvent(event); - } - private void fetchDetailedEvent(Event event) { - final String neicEvid = event.getEventSource() + event.getEvid(); - final Event workingEvent = event; - - new Thread() { - public void run() { - String url = "http://earthquake.usgs.gov/fdsnws/event/1/query?eventid=" + neicEvid; - - DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder dBuilder = null; - Document doc = null; - try { - - dBuilder = dbFactory.newDocumentBuilder(); - doc = dBuilder.parse(url); - doc.getDocumentElement().normalize(); - NodeList eventElements = doc.getElementsByTagName("event"); - LOGGER.debug("Got {} events.", eventElements.getLength()); - workingEvent.updateEvent((Element) eventElements.item(0)); - - WebServicesClient.getWave(wsDataSelectUrl, channelInfo, t1, t2); - - } catch (SAXException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } catch (IOException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } catch (ParserConfigurationException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - }.start(); - } + pickBox = new JPanel(); + pickBox.setLayout(new BoxLayout(pickBox, BoxLayout.PAGE_AXIS)); - private void createUI() { - this.setFrameIcon(Icons.ruler); - this.setSize(swarmConfig.clipboardWidth, swarmConfig.clipboardHeight); - this.setLocation(swarmConfig.clipboardX, swarmConfig.clipboardY); - this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + setFrameIcon(Icons.ruler); + setSize(swarmConfig.clipboardWidth, swarmConfig.clipboardHeight); + setLocation(swarmConfig.clipboardX, swarmConfig.clipboardY); + setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); LOGGER.debug("event frame: {} @ {}", this.getSize(), this.getLocation()); - // JPanel pickPanel = new JPanel(); - // pickPanel.setLayout(new BoxLayout(pickPanel, BoxLayout.PAGE_AXIS)); - mainPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT, createParameterPanel(), createPickPanel()); mainPanel.setOneTouchExpandable(true); + setContentPane(mainPanel); + this.setVisible(true); - // scrollPane = new JScrollPane(createParameterPanel()); - // parameterPanel.add(scrollPane, BorderLayout.NORTH); + // fetchDetailedEvent(); - // Box pickBox = new Box(BoxLayout.Y_AXIS); - // scrollPane = new JScrollPane(pickBox); - // scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - // scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); - // scrollPane.getVerticalScrollBar().setUnitIncrement(40); - // pickPanel.add(scrollPane, BorderLayout.NORTH); + new SwingWorker() { + @Override + public Object construct() { + fetchDetailedEvent(); + populatePicks(); + return null; + } - // mainPanel.setResizeWeight(.25); - this.setContentPane(mainPanel); - } + @Override + public void finished() { + repaint(); + } + }.start(); + } private Component createParameterPanel() { Origin origin = event.getPreferredOrigin(); @@ -212,63 +179,86 @@ private Component createParameterPanel() { } private Component createPickPanel() { - Box pickBox = new Box(BoxLayout.Y_AXIS); - Origin origin = event.getPreferredOrigin(); - Magnitude magnitude = event.getPerferredMagnitude(); + JScrollPane scrollPane = new JScrollPane(pickBox); + scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + scrollPane.getVerticalScrollBar().setUnitIncrement(40); + + return scrollPane; + } + + public void fetchDetailedEvent() { + final String neicEvid = event.getEventSource() + event.getEvid(); + final Event workingEvent = event; + String url = "http://earthquake.usgs.gov/fdsnws/event/1/query?eventid=" + neicEvid; + + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = null; + Document doc = null; + + try { + dBuilder = dbFactory.newDocumentBuilder(); + doc = dBuilder.parse(url); + doc.getDocumentElement().normalize(); + NodeList eventElements = doc.getElementsByTagName("event"); + workingEvent.updateEvent((Element) eventElements.item(0)); + } catch (SAXException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } catch (IOException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } catch (ParserConfigurationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + private void populatePicks() { + Origin origin = event.getPreferredOrigin(); + long firstPick = Long.MAX_VALUE; long lastPick = Long.MIN_VALUE; for (Arrival arrival : origin.getArrivals()) { - WaveViewPanel wavePanel = new WaveViewPanel(); - Pick pick = arrival.getPick(); firstPick = Math.min(pick.getTime(), firstPick); lastPick = Math.max(pick.getTime(), lastPick); - String channel = pick.getChannel(); - wavePanel.setChannel(channel); - - pickBox.add(wavePanel); } - JScrollPane scrollPane = new JScrollPane(pickBox); - scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); - scrollPane.getVerticalScrollBar().setUnitIncrement(40); + double waveStart = J2kSec.fromEpoch(firstPick) - 1; + double waveEnd = J2kSec.fromEpoch(lastPick) + 1; + LOGGER.debug("wave span {} - {}", waveStart, waveEnd); - return scrollPane; - } + for (Arrival arrival : origin.getArrivals()) { + Pick pick = arrival.getPick(); + + WaveViewPanel wavePanel = new WaveViewPanel(); + wavePanel.setChannel(pick.getChannel()); + Wave wave = WebServicesClient.getWave(pick.getChannel(), waveStart, waveEnd); + if (wave == null) { + continue; + } + LOGGER.debug("Got {} samples", wave.numSamples()); + wavePanel.setWave(wave, waveStart, waveEnd); + wavePanel.setSize(600, 200); + wavePanel.getWaveViewSettings().autoScaleAmpMemory = false; + + pickBox.add(Box.createVerticalGlue()); - // public synchronized void addWave(final String chan) { - // SeismicDataSource sds = p2.getDataSource(); - // double st = p2.getStartTime(); - // double et = p2.getEndTime(); - // Wave wave = sds.getWave(chan, st, et); - // if (wave != null && wave.isData()) { - // p2.setWave(wave, st, et); - // p2.getWaveViewSettings().autoScaleAmpMemory = false; - // addWave(p2); - // } - // } - // - // public synchronized void addWave(final PickerWavePanel p) { - // p.addListener(selectListener); - // p.setOffsets(54, 8, 21, 19); - // p.setAllowClose(true); - // p.setStatusLabel(statusLabel); - // p.setAllowDragging(true); - // p.setDisplayTitle(true); - //// p.setEvent(event); - // p.setParent(mainPanel); - // final int w = scrollPane.getViewport().getSize().width; - // p.setSize(w, calculateWaveHeight()); - // p.setBottomBorderColor(Color.GRAY); - // p.createImage(); - // waveBox.add(p); - // waves.add(p); - // LOGGER.debug("{} panels; {} waves", waveBox.getComponentCount(), waves.size()); - // } + pickBox.add(wavePanel); + pickBox.add(Box.createVerticalGlue()); + pickBox.add(new JLabel(pick.getChannel())); + + wavePanel.repaint(); + pickBox.repaint(); + mainPanel.repaint(); + EventFrame.this.repaint(); + LOGGER.debug("pickBox {}", pickBox.countComponents()); + } + } + @Override public void paint(final Graphics g) { super.paint(g); @@ -287,7 +277,6 @@ public void setVisible(final boolean isVisible) { toFront(); } - public void eventUpdated() { mainPanel.setTopComponent(createParameterPanel()); mainPanel.setBottomComponent(createPickPanel()); @@ -315,8 +304,5 @@ public void internalFrameClosed(final InternalFrameEvent e) {} @Override public void componentResized(final ComponentEvent e) {} }); - - } - } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java b/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java index 5af72629..503b18a2 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java @@ -622,11 +622,15 @@ public void createImage() { final Runnable r = new Runnable() { public void run() { if (getWidth() > 0 && getHeight() > 0) { + LOGGER.debug("PAINTING"); BufferedImage bi = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_4BYTE_ABGR); Graphics2D ig = (Graphics2D) bi.getGraphics(); constructPlot(ig); setImage(bi); + + } else { + LOGGER.debug("SKIPPING SIZE"); } } }; @@ -702,6 +706,8 @@ private void filter(Wave w) { * @param g the graphics context */ public void paint(Graphics g) { + LOGGER.debug("START PAINTING WAVE"); + Graphics2D g2 = (Graphics2D) g; Dimension dim = this.getSize(); if (wave == null) { @@ -718,6 +724,7 @@ public void paint(Graphics g) { g2.drawString(error, dim.width / 2 - w / 2, dim.height / 2); } } else { + LOGGER.debug("PAINTING WAVE"); BufferedImage bi = getImage(); if (bi != null) g2.drawImage(bi, 0, 0, null); @@ -746,6 +753,8 @@ public void paint(Graphics g) { g2.setColor(borderColor); g2.drawRect(0, 0, dim.width - 1, dim.height - 2); } + + LOGGER.debug("finished painting wave"); } public void setUseFilterLabel(boolean b) { From 235854592fb8fed57c2f42a9cb786e43e70f64dc Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Thu, 17 Mar 2016 16:02:53 -0800 Subject: [PATCH 12/67] Event window in progress... --- .../volcanoes/swarm/event/EventFrame.java | 70 +++++---- .../usgs/volcanoes/swarm/event/Origin.java | 23 +-- .../gov/usgs/volcanoes/swarm/event/Pick.java | 67 ++------- .../usgs/volcanoes/swarm/event/PickPanel.java | 135 ++++++++++++++++++ .../volcanoes/swarm/event/PickWavePanel.java | 124 ++++++++++++++++ .../volcanoes/swarm/event/QuakeMlUtils.java | 28 ++++ .../usgs/volcanoes/swarm/map/MapPanel.java | 6 - .../swarm/wave/AbstractWavePanel.java | 15 +- .../volcanoes/swarm/wave/MultiMonitor.java | 2 + src/main/resources/log4j.properties | 2 +- src/main/resources/log4jDebug.properties | 4 +- 11 files changed, 339 insertions(+), 137 deletions(-) create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/QuakeMlUtils.java diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java index b4c56005..52c16e44 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java @@ -15,8 +15,11 @@ import java.awt.GridBagLayout; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; +import java.awt.image.BufferedImage; import java.io.IOException; import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; import javax.swing.Box; import javax.swing.BoxLayout; @@ -38,7 +41,6 @@ import gov.usgs.volcanoes.swarm.Icons; import gov.usgs.volcanoes.swarm.SwarmFrame; import gov.usgs.volcanoes.swarm.SwingWorker; -import gov.usgs.volcanoes.swarm.data.CachedDataSource; import gov.usgs.volcanoes.swarm.data.SeismicDataSource; import gov.usgs.volcanoes.swarm.data.fdsnWs.WebServicesClient; import gov.usgs.volcanoes.swarm.internalFrame.SwarmInternalFrames; @@ -58,9 +60,10 @@ public class EventFrame extends SwarmFrame implements EventObserver { public static final long serialVersionUID = -1; private JSplitPane mainPanel; + private JScrollPane pickScrollPane; private Event event; private SeismicDataSource seismicDataSource; - private final JPanel pickBox; + private final PickPanel pickBox; public EventFrame(Event event) { super("Event - " + event.getEvid(), true, true, true, false); @@ -69,7 +72,7 @@ public EventFrame(Event event) { this.setFocusable(true); createListeners(); - pickBox = new JPanel(); + pickBox = new PickPanel(); pickBox.setLayout(new BoxLayout(pickBox, BoxLayout.PAGE_AXIS)); setFrameIcon(Icons.ruler); @@ -78,15 +81,14 @@ public EventFrame(Event event) { setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); LOGGER.debug("event frame: {} @ {}", this.getSize(), this.getLocation()); - mainPanel = - new JSplitPane(JSplitPane.VERTICAL_SPLIT, createParameterPanel(), createPickPanel()); + + pickScrollPane = createPickPanel(); + mainPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT, createParameterPanel(), pickScrollPane); mainPanel.setOneTouchExpandable(true); setContentPane(mainPanel); this.setVisible(true); - // fetchDetailedEvent(); - new SwingWorker() { @Override public Object construct() { @@ -100,7 +102,6 @@ public void finished() { repaint(); } }.start(); - } private Component createParameterPanel() { @@ -178,12 +179,18 @@ private Component createParameterPanel() { return parameterPanel; } - private Component createPickPanel() { + private JScrollPane createPickPanel() { - JScrollPane scrollPane = new JScrollPane(pickBox); + final JScrollPane scrollPane = new JScrollPane(pickBox); scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); scrollPane.getVerticalScrollBar().setUnitIncrement(40); + scrollPane.addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(final ComponentEvent e) { + scrollPane.getViewport().setSize(scrollPane.getWidth(), scrollPane.getViewport().getHeight()); + } + }); return scrollPane; } @@ -196,7 +203,7 @@ public void fetchDetailedEvent() { DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = null; Document doc = null; - + try { dBuilder = dbFactory.newDocumentBuilder(); doc = dBuilder.parse(url); @@ -217,7 +224,7 @@ public void fetchDetailedEvent() { private void populatePicks() { Origin origin = event.getPreferredOrigin(); - + long firstPick = Long.MAX_VALUE; long lastPick = Long.MIN_VALUE; for (Arrival arrival : origin.getArrivals()) { @@ -230,35 +237,16 @@ private void populatePicks() { double waveEnd = J2kSec.fromEpoch(lastPick) + 1; LOGGER.debug("wave span {} - {}", waveStart, waveEnd); - for (Arrival arrival : origin.getArrivals()) { - Pick pick = arrival.getPick(); - - WaveViewPanel wavePanel = new WaveViewPanel(); - wavePanel.setChannel(pick.getChannel()); - Wave wave = WebServicesClient.getWave(pick.getChannel(), waveStart, waveEnd); - if (wave == null) { - continue; - } - LOGGER.debug("Got {} samples", wave.numSamples()); - wavePanel.setWave(wave, waveStart, waveEnd); - wavePanel.setSize(600, 200); - wavePanel.getWaveViewSettings().autoScaleAmpMemory = false; - - pickBox.add(Box.createVerticalGlue()); - - pickBox.add(wavePanel); - pickBox.add(Box.createVerticalGlue()); - pickBox.add(new JLabel(pick.getChannel())); - - wavePanel.repaint(); - pickBox.repaint(); - mainPanel.repaint(); - EventFrame.this.repaint(); + pickBox.setStart(waveStart); + pickBox.setEnd(waveEnd); + for (Arrival arrival : origin.getArrivals()) { + pickBox.addPick(arrival); + mainPanel.validate(); LOGGER.debug("pickBox {}", pickBox.countComponents()); - } + } } - + @Override public void paint(final Graphics g) { super.paint(g); @@ -305,4 +293,10 @@ public void internalFrameClosed(final InternalFrameEvent e) {} public void componentResized(final ComponentEvent e) {} }); } + + // private synchronized void createImage() { + // if (getWidth() > 0 && getHeight() > 0) + // image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_4BYTE_ABGR); + // } + } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java index 9aa5cc84..e21b8fc5 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java @@ -20,12 +20,6 @@ public class Origin { private static final Logger LOGGER = LoggerFactory.getLogger(Origin.class); - private static final List DATE_FORMATS = new ArrayList(); - - static { - DATE_FORMATS.add("yyyy-MM-dd'T'HH:mm:ss.SSSX"); - DATE_FORMATS.add("yyyy-MM-dd'T'HH:mm:ss.SS"); - } public final String publicId; private double latitude; @@ -53,22 +47,7 @@ public Origin(Element originElement, Map picks) { Element timeElement = (Element) originElement.getElementsByTagName("time").item(0); time = 0; - Iterator it = DATE_FORMATS.iterator(); - while (it.hasNext() && time < 1) { - String format = it.next(); - DateFormat dateFormat = new SimpleDateFormat(format); - dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - try { - time = dateFormat.parse(timeElement.getElementsByTagName("value").item(0).getTextContent()) - .getTime(); - } catch (DOMException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (ParseException e) { - System.out.println(timeElement.getElementsByTagName("value").item(0).getTextContent() - + " didn't match " + format); - } - } + time = QuakeMlUtils.parseTime(timeElement.getElementsByTagName("value").item(0).getTextContent()); parseArrivals(originElement.getElementsByTagName("arrival"), picks); } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java index 8c60cd7f..93b45d04 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java @@ -1,86 +1,37 @@ package gov.usgs.volcanoes.swarm.event; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.TimeZone; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.w3c.dom.DOMException; import org.w3c.dom.Element; public class Pick { Logger LOGGER = LoggerFactory.getLogger(Pick.class); - private static final List DATE_FORMATS = new ArrayList(); - - static { - DATE_FORMATS.add("yyyy-MM-dd'T'HH:mm:ss.SSSX"); - DATE_FORMATS.add("yyyy-MM-dd'T'HH:mm:ss.SS"); - } public final String publicId; private long time; private String channel; - + public Pick(Element pickElement) { publicId = pickElement.getAttribute("publicID"); LOGGER.debug("new PIck {}", publicId); - -// DateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT); -// dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); Element timeElement = (Element) pickElement.getElementsByTagName("time").item(0); - time = 0; - Iterator it = DATE_FORMATS.iterator(); - while (it.hasNext() && time < 1) { - String format = it.next(); - DateFormat dateFormat = new SimpleDateFormat(format); - dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - try { - time = dateFormat.parse(timeElement.getElementsByTagName("value").item(0).getTextContent()) - .getTime(); - } catch (DOMException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (ParseException e) { - System.out.println(timeElement.getElementsByTagName("value").item(0).getTextContent() - + " didn't match " + format); - } - } + time = + QuakeMlUtils.parseTime(timeElement.getElementsByTagName("value").item(0).getTextContent()); - - - - - - -// try { -// time = dateFormat.parse(timeElement.getElementsByTagName("value").item(0).getTextContent()) -// .getTime(); -// } catch (DOMException e) { -// LOGGER.debug("DOMException parsing origin"); -// } catch (ParseException e) { -// LOGGER.debug("{ParseException parsing origin"); -// } - - Element waveformId = (Element) pickElement.getElementsByTagName("waveformID").item(0); String station = waveformId.getAttribute("stationCode"); - String chan = waveformId.getAttribute("channelCode"); - String net = waveformId.getAttribute("networkCode"); - String loc = waveformId.getAttribute("locationCode"); - + String chan = waveformId.getAttribute("channelCode"); + String net = waveformId.getAttribute("networkCode"); + String loc = waveformId.getAttribute("locationCode"); + channel = station + "$" + chan + "$" + net + "$" + loc; } - + public long getTime() { return time; } - + public String getChannel() { return channel; } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java new file mode 100644 index 00000000..e83eff58 --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java @@ -0,0 +1,135 @@ +package gov.usgs.volcanoes.swarm.event; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.image.BufferedImage; +import java.util.HashMap; +import java.util.Map; + +import javax.swing.BoxLayout; +import javax.swing.JPanel; +import javax.swing.Scrollable; + +import gov.usgs.plot.data.Wave; +import gov.usgs.volcanoes.swarm.data.fdsnWs.WebServicesClient; + +public class PickPanel extends JPanel implements Scrollable { + private static final long serialVersionUID = 1L; + private static final Logger LOGGER = LoggerFactory.getLogger(PickPanel.class); + + private BufferedImage image; + private final Map panels; + private double startJ2k; + private double endJ2k; + + public PickPanel() { + panels = new HashMap(); + setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); + addComponentListener(new ComponentAdapter() { + @Override + public void componentMoved(final ComponentEvent e) { + resizeWaves(); + } + + @Override + public void componentResized(final ComponentEvent e) { + createImage(); + resizeWaves(); + } + }); + } + + public void setStart(Double startJ2k) { + this.startJ2k = startJ2k; + } + + public void setEnd(Double startJ2k) { + this.endJ2k = startJ2k; + } + + private synchronized void createImage() { + if (getWidth() > 0 && getHeight() > 0) + image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_4BYTE_ABGR); + } + + @Override + public void paint(final Graphics g) { + if (getWidth() <= 0 || getHeight() <= 0) + return; + + if (image == null || panels.size() == 0) { + super.paint(g); + final Dimension dim = this.getSize(); + g.setColor(Color.black); + g.drawString("Monitor empty.", dim.width / 2 - 40, dim.height / 2); + } else { + super.paint(image.getGraphics()); + g.drawImage(image, 0, 0, null); + g.setColor(Color.WHITE); + } + } + + public void addPick(Arrival arrival) { + Pick pick = arrival.getPick(); + PickWavePanel wavePanel = panels.get(pick.getChannel()); + if (wavePanel == null) { + wavePanel = new PickWavePanel(); + wavePanel.setChannel(pick.getChannel()); + Wave wave = WebServicesClient.getWave(pick.getChannel(), startJ2k, endJ2k); + panels.put(pick.getChannel(), wavePanel); + wavePanel.setWave(wave, startJ2k, endJ2k); + add(wavePanel); + wavePanel.setSize(getWidth(), 200); + wavePanel.setDisplayTitle(true); + wavePanel.setOffsets(60, 0, 0, 0); + wavePanel.createImage(); + } + + wavePanel.addArrival(arrival); +// +// if (wave == null) { +// return; +// } + +// LOGGER.debug("Got {} samples", wave.numSamples()); + } + + private synchronized void resizeWaves() { + for (int idx = 0; idx < panels.size(); idx++) { + PickWavePanel panel = panels.get(idx); + Dimension d = panel.getSize(); + + panel.setSize(getWidth(), d.height); + panel.createImage(); + panel.repaint(); + } + } + + public Dimension getPreferredScrollableViewportSize() { + return null; + } + + public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { + return 0; + } + + public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { + return 0; + } + + public boolean getScrollableTracksViewportWidth() { + return true; + } + + public boolean getScrollableTracksViewportHeight() { + // TODO Auto-generated method stub + return false; + } +} \ No newline at end of file diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java new file mode 100644 index 00000000..131d5454 --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java @@ -0,0 +1,124 @@ +package gov.usgs.volcanoes.swarm.event; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.event.MouseEvent; +import java.awt.geom.Line2D; +import java.util.ArrayList; +import java.util.List; + +import gov.usgs.volcanoes.core.time.J2kSec; +import gov.usgs.volcanoes.swarm.picker.Phase; +import gov.usgs.volcanoes.swarm.time.WaveViewTime; +import gov.usgs.volcanoes.swarm.wave.AbstractWavePanel; + +public class PickWavePanel extends AbstractWavePanel implements EventObserver { + + private static final Logger LOGGER = LoggerFactory.getLogger(PickWavePanel.class); + + private static final Font ANNOTATION_FONT = new Font("Monospaced", Font.BOLD, 12); + private static final Color P_BACKGROUND = new Color(128, 255, 128, 192); + private static final Color S_BACKGROUND = new Color(128, 128, 255, 192); + private static final Color CODA_BACKGROUND = new Color(128, 128, 128, 192); + private final List arrivals; + + public PickWavePanel() { + super(); + arrivals = new ArrayList(); + } + + public void addArrival(Arrival arrival) { + arrivals.add(arrival); + } + + @Override + protected void annotateImage(Graphics2D g2) { + for (Arrival arrival : arrivals) { + Pick pick = arrival.getPick(); + + String tag = arrival.getPhase(); + double j2k = J2kSec.fromEpoch(pick.getTime()); + double[] t = getTranslation(); + if (t == null) + continue; + + double x = 2 + (j2k - t[1]) / t[0]; + g2.setColor(DARK_GREEN); + g2.draw(new Line2D.Double(x, yOffset, x, getHeight() - bottomHeight - 1)); + g2.setFont(ANNOTATION_FONT); + + FontMetrics fm = g2.getFontMetrics(); + int width = fm.stringWidth(tag); + int height = fm.getAscent(); + + int offset = 2; + int lw = width + 2 * offset; + + g2.setColor(backgroundColor); + + g2.fillRect((int) x, 3, lw, height + 2 * offset); + g2.setColor(Color.black); + g2.drawRect((int) x, 3, lw, height + 2 * offset); + + g2.drawString(tag, (int) x + offset, 3 + (fm.getAscent() + offset)); + } + } + + private void markPhase(Graphics2D g2, Phase phase) { + double j2k = J2kSec.fromEpoch(phase.time); + double[] t = getTranslation(); + if (t == null) + return; + + double x = 2 + (j2k - t[1]) / t[0]; + g2.setColor(DARK_GREEN); + g2.draw(new Line2D.Double(x, yOffset, x, getHeight() - bottomHeight - 1)); + + String tag = phase.tag(); + Font oldFont = g2.getFont(); + g2.setFont(ANNOTATION_FONT); + + FontMetrics fm = g2.getFontMetrics(); + int width = fm.stringWidth(tag); + int height = fm.getAscent(); + + int offset = 2; + int lw = width + 2 * offset; + + Color background = null; + if (phase.phaseType == Phase.PhaseType.P) { + background = P_BACKGROUND; + } else if (phase.phaseType == Phase.PhaseType.S) { + background = S_BACKGROUND; + } + g2.setColor(background); + + g2.fillRect((int) x, 3, lw, height + 2 * offset); + g2.setColor(Color.black); + g2.drawRect((int) x, 3, lw, height + 2 * offset); + + g2.drawString(tag, (int) x + offset, 3 + (fm.getAscent() + offset)); + g2.setFont(oldFont); + } + + @Override + protected void processRightMouseRelease(MouseEvent e) { + pauseCursorMark = false; + } + + public void eventUpdated() { + repaint(); + } + + @Override + protected void processRightMousePress(MouseEvent e) { + // TODO Auto-generated method stub + + } +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/QuakeMlUtils.java b/src/main/java/gov/usgs/volcanoes/swarm/event/QuakeMlUtils.java new file mode 100644 index 00000000..7b809f3f --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/QuakeMlUtils.java @@ -0,0 +1,28 @@ +package gov.usgs.volcanoes.swarm.event; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.ParseException; +import java.text.SimpleDateFormat; + +public class QuakeMlUtils { + private static final Logger LOGGER = LoggerFactory.getLogger(QuakeMlUtils.class); + private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSX"; + + public static long parseTime(String timeString) { + String inString = timeString; + timeString = timeString.replaceFirst("\\.(\\d)Z?", ".$100Z"); + timeString = timeString.replaceFirst("\\.(\\d{2})Z?$", ".$10Z"); + + long time = Long.MIN_VALUE; + SimpleDateFormat dateF = new SimpleDateFormat(DATE_FORMAT); + try { + time = dateF.parse(timeString).getTime(); + } catch (ParseException e) { + LOGGER.error("Cannot parse time String {}", inString); + throw new RuntimeException("Cannot parse time string " + inString); + } + return time; + } +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java index 98180f2d..c50e8e5e 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java @@ -631,7 +631,6 @@ private void checkLayouts() { private BufferedImage updateMapRenderer() { BufferedImage mi = null; - final CodeTimer ct = new CodeTimer("whole map"); try { swarmConfig.mapScale = scale; swarmConfig.mapLongitude = center.x; @@ -646,9 +645,7 @@ private BufferedImage updateMapRenderer() { LOGGER.debug("map scale: " + scale); LOGGER.debug("center: " + center.x + " " + center.y); final MapRenderer mr = new MapRenderer(range, projection); - ct.mark("pre bg"); image = images.getMapBackground(projection, range, width, scale); - ct.mark("bg"); mr.setLocation(INSET, INSET, width); mr.setMapImage(image); mr.setGeoLabelSet(labels); @@ -677,12 +674,9 @@ private BufferedImage updateMapRenderer() { final Plot plot = new Plot(); plot.setSize(mapImagePanel.getWidth(), mapImagePanel.getHeight()); plot.addRenderer(renderer); - ct.mark("pre plot"); mi = plot.getAsBufferedImage(false); - ct.mark("plot"); dragDX = Integer.MAX_VALUE; dragDY = Integer.MAX_VALUE; - ct.stopAndReport(); } catch (final Exception e) { LOGGER.error("Exception during map creation. {}", e); } finally { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java b/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java index 503b18a2..3f22b004 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java @@ -86,7 +86,7 @@ public abstract class AbstractWavePanel extends JComponent { */ protected SeismicDataSource source; /** - * A flag to indicate wheter the plot should display a title. Currently used when the plot is on + * A flag to indicate whether the plot should display a title. Currently used when the plot is on * the clipboard or monitor. */ protected boolean displayTitle; @@ -622,15 +622,11 @@ public void createImage() { final Runnable r = new Runnable() { public void run() { if (getWidth() > 0 && getHeight() > 0) { - LOGGER.debug("PAINTING"); BufferedImage bi = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_4BYTE_ABGR); Graphics2D ig = (Graphics2D) bi.getGraphics(); constructPlot(ig); setImage(bi); - - } else { - LOGGER.debug("SKIPPING SIZE"); } } }; @@ -647,8 +643,10 @@ public void finished() { } }; worker.start(); - } else + } else { + r.run(); + } } /** @@ -706,8 +704,6 @@ private void filter(Wave w) { * @param g the graphics context */ public void paint(Graphics g) { - LOGGER.debug("START PAINTING WAVE"); - Graphics2D g2 = (Graphics2D) g; Dimension dim = this.getSize(); if (wave == null) { @@ -724,7 +720,6 @@ public void paint(Graphics g) { g2.drawString(error, dim.width / 2 - w / 2, dim.height / 2); } } else { - LOGGER.debug("PAINTING WAVE"); BufferedImage bi = getImage(); if (bi != null) g2.drawImage(bi, 0, 0, null); @@ -753,8 +748,6 @@ public void paint(Graphics g) { g2.setColor(borderColor); g2.drawRect(0, 0, dim.width - 1, dim.height - 2); } - - LOGGER.debug("finished painting wave"); } public void setUseFilterLabel(boolean b) { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/wave/MultiMonitor.java b/src/main/java/gov/usgs/volcanoes/swarm/wave/MultiMonitor.java index a51b2198..4ee1a309 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/wave/MultiMonitor.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/wave/MultiMonitor.java @@ -156,6 +156,8 @@ public void processLayout(final ConfigFile cf) { final String w = "wave-" + i; final String channel = cf.getString(w + ".channel"); final ConfigFile scf = cf.getSubConfig(w); + + //TODO: why is wvp discarded? final WaveViewPanel wvp = addChannel(channel); wvp.getSettings().set(scf); } diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties index 84a7fbad..9bcabac9 100644 --- a/src/main/resources/log4j.properties +++ b/src/main/resources/log4j.properties @@ -2,7 +2,7 @@ log4j.rootLogger=debug, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.Threshold=debug +log4j.appender.stdout.Threshold=info # Pattern to output the caller's file name and line number. log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd hh:mm:ss} %5p - %m%n diff --git a/src/main/resources/log4jDebug.properties b/src/main/resources/log4jDebug.properties index a31c6da1..5cce82c3 100644 --- a/src/main/resources/log4jDebug.properties +++ b/src/main/resources/log4jDebug.properties @@ -14,4 +14,6 @@ log4j.appender.R.MaxFileSize=100KB log4j.appender.R.MaxBackupIndex=9 log4j.appender.R.layout=org.apache.log4j.PatternLayout -log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd hh:mm:ss} %5p - %m (%F:%L)%n \ No newline at end of file +log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd hh:mm:ss} %5p - %m (%F:%L)%n + +log4j.logger.gov.usgs.volcanoes.swarm.map=info \ No newline at end of file From 386e4d47d82c0e477d7a971839282fd5ff70d53d Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Fri, 18 Mar 2016 13:47:24 -0800 Subject: [PATCH 13/67] Event window in progress... --- .../usgs/volcanoes/swarm/event/Arrival.java | 76 +++++++++++----- .../gov/usgs/volcanoes/swarm/event/Pick.java | 74 +++++++++++++++ .../usgs/volcanoes/swarm/event/PickPanel.java | 74 +++++++++++---- .../volcanoes/swarm/event/PickWavePanel.java | 89 ++++++++++--------- .../volcanoes/swarm/event/QuakeMlUtils.java | 3 +- .../usgs/volcanoes/swarm/map/MapPanel.java | 12 ++- .../swarm/wave/AbstractWavePanel.java | 41 +++++---- 7 files changed, 263 insertions(+), 106 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java index de8c0d76..b8e3d6c3 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java @@ -1,32 +1,64 @@ package gov.usgs.volcanoes.swarm.event; -import java.util.Map; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Element; +import java.util.Map; + +import gov.usgs.volcanoes.swarm.event.Pick.Onset; +import gov.usgs.volcanoes.swarm.event.Pick.Polarity; + public class Arrival { Logger LOGGER = LoggerFactory.getLogger(Arrival.class); - -public final String publicId; -private Pick pick; -private String phase; - -public Arrival(Element arrivalElement, Map picks) { - this.publicId = arrivalElement.getAttribute("publicID"); - LOGGER.debug("new arrival {}", publicId); - -// this.phase = arrivalElement.getAttribute("phase"); - this.pick = picks.get(arrivalElement.getElementsByTagName("pickID").item(0).getTextContent()); - this.phase = arrivalElement.getElementsByTagName("phase").item(0).getTextContent(); -} - -public Pick getPick() { - return pick; -} -public String getPhase() { - return phase; -} + public final String publicId; + private Pick pick; + private String phase; + private double timeResidual; + + public Arrival(Element arrivalElement, Map picks) { + this.publicId = arrivalElement.getAttribute("publicID"); + LOGGER.debug("new arrival {}", publicId); + + // this.phase = arrivalElement.getAttribute("phase"); + pick = picks.get(arrivalElement.getElementsByTagName("pickID").item(0).getTextContent()); + phase = arrivalElement.getElementsByTagName("phase").item(0).getTextContent(); + timeResidual = Double + .parseDouble(arrivalElement.getElementsByTagName("timeResidual").item(0).getTextContent()); + } + + public Pick getPick() { + return pick; + } + + public String getPhase() { + return phase; + } + + public double getTimeResidual() { + return timeResidual; + } + + public String getTag() { + StringBuilder sb = new StringBuilder(); + + Onset onset = pick.getOnset(); + if (onset == Pick.Onset.EMERGENT) { + sb.append("e"); + } else if (onset == Pick.Onset.IMPULSIVE) { + sb.append("i"); + } + + sb.append(phase.charAt(0)); + + Polarity polarity = pick.getPolarity(); + if (polarity == Pick.Polarity.NEGATIVE) { + sb.append("-"); + } else if (polarity == Pick.Polarity.POSITIVE) { + sb.append("+"); + } + + return sb.toString(); + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java index 93b45d04..c6dfebd6 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java @@ -2,7 +2,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.w3c.dom.DOMException; import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import java.text.ParseException; public class Pick { Logger LOGGER = LoggerFactory.getLogger(Pick.class); @@ -10,6 +14,42 @@ public class Pick { public final String publicId; private long time; private String channel; + private Onset onset; + private Polarity polarity; + + + public static enum Onset { + EMERGENT, IMPULSIVE, QUESTIONABLE; + + public static Onset parse(String string) throws ParseException { + if ("emergent".equals(string)) { + return EMERGENT; + } else if ("impulsive".equals(string)) { + return IMPULSIVE; + } else if ("questionable".equals(string)) { + return QUESTIONABLE; + } else { + throw new ParseException("Cannot parse " + string, 12); + } + + } + } + + public static enum Polarity { + POSITIVE, NEGATIVE, UNDECIDABLE; + + public static Polarity parse(String string) throws ParseException { + if ("positive".equals(string)) { + return POSITIVE; + } else if ("negative".equals(string)) { + return NEGATIVE; + } else if ("undecidable".equals(string)) { + return UNDECIDABLE; + } else { + throw new ParseException("Cannot parse " + string, 12); + } + } + } public Pick(Element pickElement) { publicId = pickElement.getAttribute("publicID"); @@ -19,6 +59,32 @@ public Pick(Element pickElement) { time = QuakeMlUtils.parseTime(timeElement.getElementsByTagName("value").item(0).getTextContent()); + NodeList onsetList = pickElement.getElementsByTagName("onset"); + if (onsetList != null && onsetList.getLength() > 0) { + try { + onset = Onset.parse(onsetList.item(0).getTextContent()); + } catch (DOMException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (ParseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + NodeList polarityList = pickElement.getElementsByTagName("polarity"); + if (polarityList != null && polarityList.getLength() > 0) { + try { + polarity = + Polarity.parse(pickElement.getElementsByTagName("polarity").item(0).getTextContent()); + } catch (DOMException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (ParseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } Element waveformId = (Element) pickElement.getElementsByTagName("waveformID").item(0); String station = waveformId.getAttribute("stationCode"); String chan = waveformId.getAttribute("channelCode"); @@ -35,4 +101,12 @@ public long getTime() { public String getChannel() { return channel; } + + public Onset getOnset() { + return onset; + } + + public Polarity getPolarity() { + return polarity; + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java index e83eff58..f8ddae9f 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java @@ -13,24 +13,34 @@ import java.util.HashMap; import java.util.Map; +import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JPanel; import javax.swing.Scrollable; import gov.usgs.plot.data.Wave; -import gov.usgs.volcanoes.swarm.data.fdsnWs.WebServicesClient; +import gov.usgs.volcanoes.swarm.data.SeismicDataSource; +import gov.usgs.volcanoes.swarm.data.fdsnWs.WebServicesSource; +import gov.usgs.volcanoes.swarm.wave.WaveViewPanelListener; public class PickPanel extends JPanel implements Scrollable { private static final long serialVersionUID = 1L; private static final Logger LOGGER = LoggerFactory.getLogger(PickPanel.class); + private static final String IRIS_DATASELECT_URL = "http://service.iris.edu/fdsnws/dataselect/1/query"; + private static final String IRIS_STATION_URL = "http://service.iris.edu/fdsnws/station/1/query"; + private BufferedImage image; private final Map panels; private double startJ2k; private double endJ2k; + private WaveViewPanelListener selectListener; + private final Map seismicSources; public PickPanel() { panels = new HashMap(); + seismicSources = new HashMap(); + setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); addComponentListener(new ComponentAdapter() { @Override @@ -46,6 +56,7 @@ public void componentResized(final ComponentEvent e) { }); } + public void setStart(Double startJ2k) { this.startJ2k = startJ2k; } @@ -78,32 +89,57 @@ public void paint(final Graphics g) { public void addPick(Arrival arrival) { Pick pick = arrival.getPick(); - PickWavePanel wavePanel = panels.get(pick.getChannel()); + String channel = pick.getChannel(); + PickWavePanel wavePanel = panels.get(channel); if (wavePanel == null) { wavePanel = new PickWavePanel(); - wavePanel.setChannel(pick.getChannel()); - Wave wave = WebServicesClient.getWave(pick.getChannel(), startJ2k, endJ2k); - panels.put(pick.getChannel(), wavePanel); - wavePanel.setWave(wave, startJ2k, endJ2k); - add(wavePanel); - wavePanel.setSize(getWidth(), 200); - wavePanel.setDisplayTitle(true); - wavePanel.setOffsets(60, 0, 0, 0); - wavePanel.createImage(); + wavePanel.setChannel(channel); + + SeismicDataSource source = seismicSources.get(channel); + if (source == null) { + source = new WebServicesSource(); + source.parse(buildParams(channel)); + } + wavePanel.setDataSource(source); + Wave wave = source.getWave(channel, startJ2k, endJ2k); + if (wave != null) { + panels.put(pick.getChannel(), wavePanel); + wavePanel.setWave(wave, startJ2k, endJ2k); + add(wavePanel); + add(Box.createRigidArea(new Dimension(0, 10))); + wavePanel.setSize(getWidth(), 200); + wavePanel.setDisplayTitle(true); + wavePanel.setOffsets(60, 0, 5, 15); + wavePanel.createImage(); + wavePanel.addListener(selectListener); + } } wavePanel.addArrival(arrival); -// -// if (wave == null) { -// return; -// } - -// LOGGER.debug("Got {} samples", wave.numSamples()); } + private String buildParams(String channel) { + String[] comps = channel.split("\\$"); + LOGGER.debug("SPLIT {}", channel); + StringBuilder sb = new StringBuilder(); + sb.append(comps[2]).append("|"); + sb.append(comps[0]).append("|"); + + if (comps.length > 3) { + sb.append(comps[3]).append("|"); + } else { + sb.append("--|"); + } + sb.append(comps[1]).append("|"); + sb.append(3600).append("|"); + sb.append(1000).append("|"); + sb.append(IRIS_DATASELECT_URL).append("|"); + sb.append(IRIS_STATION_URL); + + return sb.toString(); + } private synchronized void resizeWaves() { - for (int idx = 0; idx < panels.size(); idx++) { - PickWavePanel panel = panels.get(idx); + for (PickWavePanel panel : panels.values().toArray(new PickWavePanel[0])) { Dimension d = panel.getSize(); panel.setSize(getWidth(), d.height); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java index 131d5454..8ce0a092 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java @@ -4,19 +4,21 @@ import org.slf4j.LoggerFactory; import java.awt.Color; -import java.awt.Component; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.event.MouseEvent; import java.awt.geom.Line2D; +import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.List; +import java.util.Stack; import gov.usgs.volcanoes.core.time.J2kSec; -import gov.usgs.volcanoes.swarm.picker.Phase; +import gov.usgs.volcanoes.swarm.time.TimeListener; import gov.usgs.volcanoes.swarm.time.WaveViewTime; import gov.usgs.volcanoes.swarm.wave.AbstractWavePanel; +import gov.usgs.volcanoes.swarm.wave.WaveViewPanelAdapter; public class PickWavePanel extends AbstractWavePanel implements EventObserver { @@ -25,32 +27,64 @@ public class PickWavePanel extends AbstractWavePanel implements EventObserver { private static final Font ANNOTATION_FONT = new Font("Monospaced", Font.BOLD, 12); private static final Color P_BACKGROUND = new Color(128, 255, 128, 192); private static final Color S_BACKGROUND = new Color(128, 128, 255, 192); - private static final Color CODA_BACKGROUND = new Color(128, 128, 128, 192); + private static final Color RESIDUAL_COLOR = new Color(128, 128, 128, 32); private final List arrivals; + private final Stack zoomHistory; public PickWavePanel() { super(); + allowDragging = true; arrivals = new ArrayList(); + zoomHistory = new Stack(); + createListeners(); } public void addArrival(Arrival arrival) { arrivals.add(arrival); } + + private void createListeners() { + WaveViewTime.addTimeListener(new TimeListener() { + public void timeChanged(final double j2k) { + setCursorMark(j2k); + } + }); + + this.addListener(new WaveViewPanelAdapter() { + @Override + public void waveZoomed(final AbstractWavePanel src, final double st, final double et, + final double nst, final double net) { + final double[] t = new double[] {st, et}; + zoomHistory.push(t); + zoom(nst, net); + } + }); + } + @Override protected void annotateImage(Graphics2D g2) { for (Arrival arrival : arrivals) { Pick pick = arrival.getPick(); - String tag = arrival.getPhase(); + String tag = arrival.getTag(); double j2k = J2kSec.fromEpoch(pick.getTime()); double[] t = getTranslation(); if (t == null) continue; - + double x = 2 + (j2k - t[1]) / t[0]; g2.setColor(DARK_GREEN); g2.draw(new Line2D.Double(x, yOffset, x, getHeight() - bottomHeight - 1)); + + double residual = arrival.getTimeResidual(); + if (residual != 0) { + double residualMark = 2 + (j2k + residual - t[1]) / t[0]; + g2.setColor(RESIDUAL_COLOR); + g2.fill(new Rectangle2D.Double(Math.min(x, residualMark), yOffset, + Math.abs(x - residualMark), getHeight() - bottomHeight - 1)); + } + g2.setFont(ANNOTATION_FONT); FontMetrics fm = g2.getFontMetrics(); @@ -60,7 +94,11 @@ protected void annotateImage(Graphics2D g2) { int offset = 2; int lw = width + 2 * offset; - g2.setColor(backgroundColor); + if (tag.indexOf('P') != -1) { + g2.setColor(P_BACKGROUND); + } else if (tag.indexOf('S') != -1) { + g2.setColor(S_BACKGROUND); + } g2.fillRect((int) x, 3, lw, height + 2 * offset); g2.setColor(Color.black); @@ -70,43 +108,6 @@ protected void annotateImage(Graphics2D g2) { } } - private void markPhase(Graphics2D g2, Phase phase) { - double j2k = J2kSec.fromEpoch(phase.time); - double[] t = getTranslation(); - if (t == null) - return; - - double x = 2 + (j2k - t[1]) / t[0]; - g2.setColor(DARK_GREEN); - g2.draw(new Line2D.Double(x, yOffset, x, getHeight() - bottomHeight - 1)); - - String tag = phase.tag(); - Font oldFont = g2.getFont(); - g2.setFont(ANNOTATION_FONT); - - FontMetrics fm = g2.getFontMetrics(); - int width = fm.stringWidth(tag); - int height = fm.getAscent(); - - int offset = 2; - int lw = width + 2 * offset; - - Color background = null; - if (phase.phaseType == Phase.PhaseType.P) { - background = P_BACKGROUND; - } else if (phase.phaseType == Phase.PhaseType.S) { - background = S_BACKGROUND; - } - g2.setColor(background); - - g2.fillRect((int) x, 3, lw, height + 2 * offset); - g2.setColor(Color.black); - g2.drawRect((int) x, 3, lw, height + 2 * offset); - - g2.drawString(tag, (int) x + offset, 3 + (fm.getAscent() + offset)); - g2.setFont(oldFont); - } - @Override protected void processRightMouseRelease(MouseEvent e) { pauseCursorMark = false; @@ -119,6 +120,6 @@ public void eventUpdated() { @Override protected void processRightMousePress(MouseEvent e) { // TODO Auto-generated method stub - + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/QuakeMlUtils.java b/src/main/java/gov/usgs/volcanoes/swarm/event/QuakeMlUtils.java index 7b809f3f..23986fe3 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/QuakeMlUtils.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/QuakeMlUtils.java @@ -14,7 +14,8 @@ public static long parseTime(String timeString) { String inString = timeString; timeString = timeString.replaceFirst("\\.(\\d)Z?", ".$100Z"); timeString = timeString.replaceFirst("\\.(\\d{2})Z?$", ".$10Z"); - + timeString = timeString.replaceFirst(":(\\d{2})Z?$", ":$1.000Z"); + long time = Long.MIN_VALUE; SimpleDateFormat dateF = new SimpleDateFormat(DATE_FORMAT); try { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java index c50e8e5e..95d28bd4 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java @@ -1013,11 +1013,19 @@ public Projection getProjection() { } public int getGraphWidth() { - return renderer.getGraphWidth(); + int width = 0; + if (renderer != null) { + width = renderer.getGraphWidth(); + } + return width; } public int getGraphHeight() { - return renderer.getGraphHeight(); + int height = 0; + if (renderer != null) { + height = renderer.getGraphHeight(); + } + return height; } public int getInset() { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java b/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java index 3f22b004..384fa47c 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java @@ -122,13 +122,22 @@ public abstract class AbstractWavePanel extends JComponent { protected boolean pauseCursorMark; protected double time; - public AbstractWavePanel(WaveViewSettings s) { + + public AbstractWavePanel() { + super(); swarmConfig = SwarmConfig.getInstance(); - settings = s; - s.view = this; pauseCursorMark = false; backgroundColor = new Color(0xf7, 0xf7, 0xf7); + settings = new WaveViewSettings(); + setupMouseHandler(); + + } + + public AbstractWavePanel(WaveViewSettings s) { + this(); + settings = s; + s.view = this; } /** @@ -138,8 +147,8 @@ public AbstractWavePanel(WaveViewSettings s) { * @param p the source WaveViewPanel */ public AbstractWavePanel(AbstractWavePanel p) { + this(); - swarmConfig = SwarmConfig.getInstance(); channel = p.channel; source = p.source; startTime = p.startTime; @@ -147,21 +156,22 @@ public AbstractWavePanel(AbstractWavePanel p) { bias = p.bias; maxSpectraPower = p.maxSpectraPower; maxSpectrogramPower = p.maxSpectrogramPower; - translation = new double[8]; - if (p.translation != null) - System.arraycopy(p.translation, 0, translation, 0, 8); timeSeries = p.timeSeries; allowDragging = p.allowDragging; - settings = new WaveViewSettings(p.settings); - settings.view = this; wave = p.wave; displayTitle = p.displayTitle; backgroundColor = p.backgroundColor; mark1 = p.mark1; mark2 = p.mark2; - setupMouseHandler(); - processSettings(); + translation = new double[8]; + if (p.translation != null) + System.arraycopy(p.translation, 0, translation, 0, 8); + + settings = new WaveViewSettings(p.settings); + settings.view = this; + + processSettings(); } public void setOffsets(int xo, int yo, int rw, int bh) { @@ -503,8 +513,8 @@ public boolean processMousePosition(int x, int y) { double tzo = tz.getOffset(J2kSec.asEpoch(time)); if (tzo != 0) { String tza = tz.getDisplayName(tz.inDaylightTime(J2kSec.asDate(time)), TimeZone.SHORT); - status = J2kSec.format(Time.STANDARD_TIME_FORMAT_MS, time + tzo) + " (" + tza + "), " + utc - + " (UTC)"; + status = J2kSec.format(Time.STANDARD_TIME_FORMAT_MS, time + tzo) + " (" + tza + "), " + + utc + " (UTC)"; } else status = utc; @@ -998,11 +1008,6 @@ private void paintDragBox(Graphics2D g2) { g2.setPaint(pnt); } - - public AbstractWavePanel() { - super(); - } - public void setCursorMark(double j2k) { cursorMark = j2k; repaint(); From b92f154606dad3bafa71626fc3539bb1c41015ff Mon Sep 17 00:00:00 2001 From: tparker Date: Mon, 21 Mar 2016 06:50:40 -0800 Subject: [PATCH 14/67] Event panel in progress... --- .../java/gov/usgs/volcanoes/swarm/Swarm.java | 11 +- .../usgs/volcanoes/swarm/event/Arrival.java | 15 +- .../gov/usgs/volcanoes/swarm/event/Event.java | 33 +- .../volcanoes/swarm/event/EventFrame.java | 630 ++++++++- .../volcanoes/swarm/event/EventFrame3.java | 805 +++++++++++ .../usgs/volcanoes/swarm/event/Magnitude.java | 11 +- .../usgs/volcanoes/swarm/event/Networks.java | 121 ++ .../usgs/volcanoes/swarm/event/Origin.java | 105 +- .../usgs/volcanoes/swarm/event/PickPanel.java | 24 +- .../volcanoes/swarm/event/PickWavePanel.java | 17 +- .../swarm/map/MapSettingsDialog.java | 2 +- .../map/hypocenters/HypocenterLayer.java | 19 +- .../swarm/picker/PickerWavePanel.java | 90 +- .../swarm/wave/AbstractWavePanel.java | 13 +- src/main/resources/networks.csv | 1212 +++++++++++++++++ 15 files changed, 2964 insertions(+), 144 deletions(-) create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame3.java create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/Networks.java create mode 100644 src/main/resources/networks.csv diff --git a/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java b/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java index f1f625fe..7a511c8b 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java @@ -1,10 +1,5 @@ package gov.usgs.volcanoes.swarm; -import com.jgoodies.looks.plastic.Plastic3DLookAndFeel; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.awt.Dimension; import java.awt.Frame; import java.awt.KeyboardFocusManager; @@ -29,6 +24,11 @@ import javax.swing.SwingUtilities; import javax.swing.UIManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.jgoodies.looks.plastic.Plastic3DLookAndFeel; + import gov.usgs.plot.data.Wave; import gov.usgs.volcanoes.core.configfile.ConfigFile; import gov.usgs.volcanoes.core.time.CurrentTime; @@ -40,6 +40,7 @@ import gov.usgs.volcanoes.swarm.data.SeismicDataSource; import gov.usgs.volcanoes.swarm.event.Event; import gov.usgs.volcanoes.swarm.event.EventFrame; +import gov.usgs.volcanoes.swarm.event.EventFrame3; import gov.usgs.volcanoes.swarm.heli.HelicorderViewerFrame; import gov.usgs.volcanoes.swarm.internalFrame.InternalFrameListener; import gov.usgs.volcanoes.swarm.internalFrame.SwarmInternalFrames; diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java index b8e3d6c3..1b81bf09 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java @@ -4,6 +4,7 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Element; +import java.util.Comparator; import java.util.Map; import gov.usgs.volcanoes.swarm.event.Pick.Onset; @@ -16,6 +17,7 @@ public class Arrival { private Pick pick; private String phase; private double timeResidual; + private double distance; public Arrival(Element arrivalElement, Map picks) { this.publicId = arrivalElement.getAttribute("publicID"); @@ -26,7 +28,9 @@ public Arrival(Element arrivalElement, Map picks) { phase = arrivalElement.getElementsByTagName("phase").item(0).getTextContent(); timeResidual = Double .parseDouble(arrivalElement.getElementsByTagName("timeResidual").item(0).getTextContent()); - } + distance = Double + .parseDouble(arrivalElement.getElementsByTagName("distance").item(0).getTextContent()); + } public Pick getPick() { return pick; @@ -61,4 +65,13 @@ public String getTag() { return sb.toString(); } + + public static Comparator distanceComparator() { + return new Comparator() { + public int compare(final Arrival e1, final Arrival e2) { + return Double.compare(e1.distance, e2.distance); + } + }; + } + } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java index aac135a6..531efcff 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java @@ -18,6 +18,7 @@ import javax.xml.parsers.ParserConfigurationException; import gov.usgs.volcanoes.core.util.StringUtils; +import gov.usgs.volcanoes.swarm.SwarmConfig; public class Event { @@ -28,7 +29,7 @@ public class Event { private final Map magnitudes; private final Map picks; private final List observers; - + private Origin preferredOrigin; private Magnitude preferredMagnitude; private String description; @@ -72,12 +73,14 @@ public void updateEvent(Element event) { preferredMagnitude = (Magnitude) magnitudes.values().toArray()[0]; } - eventSource = StringUtils.stringToString(event.getAttribute("catalog:eventsource"), eventSource); + eventSource = + StringUtils.stringToString(event.getAttribute("catalog:eventsource"), eventSource); evid = StringUtils.stringToString(event.getAttribute("catalog:eventid"), evid); - + Element descriptionElement = (Element) event.getElementsByTagName("description").item(0); if (descriptionElement != null) { - description = StringUtils.stringToString(descriptionElement.getElementsByTagName("text").item(0).getTextContent(), description); + description = StringUtils.stringToString( + descriptionElement.getElementsByTagName("text").item(0).getTextContent(), description); } notifyObservers(); @@ -88,6 +91,7 @@ private void notifyObservers() { observer.eventUpdated(); } } + private void parsePicks(NodeList pickElements) { picks.clear(); int pickCount = pickElements.getLength(); @@ -128,10 +132,11 @@ public Magnitude getPerferredMagnitude() { public String getEventSource() { return eventSource; } - + public String getEvid() { return evid; } + public String getDataid() { return null; } @@ -140,17 +145,7 @@ public String getDescription() { return description; } -private Event getDetailedEvent(String evid) - throws ParserConfigurationException, SAXException, IOException { - String url = "http://earthquake.usgs.gov/fdsnws/event/1/query?eventid=" + evid; - - DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); - Document doc = dBuilder.parse(url); - doc.getDocumentElement().normalize(); - - NodeList eventElements = doc.getElementsByTagName("event"); - LOGGER.debug("Got {} events.", eventElements.getLength()); - return new Event((Element) eventElements.item(0)); - } -} \ No newline at end of file + public void setDescription(String description) { + this.description = description; + } +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java index 52c16e44..399e3e2f 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java @@ -1,32 +1,38 @@ package gov.usgs.volcanoes.swarm.event; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - +import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; +import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; -import java.awt.image.BufferedImage; import java.io.IOException; +import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.List; - +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.Stack; +import java.util.TimeZone; +import java.util.TreeSet; + +import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; +import javax.swing.JButton; import javax.swing.JLabel; +import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; +import javax.swing.JToolBar; import javax.swing.ScrollPaneConstants; import javax.swing.SwingConstants; import javax.swing.WindowConstants; @@ -36,15 +42,28 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + import gov.usgs.plot.data.Wave; import gov.usgs.volcanoes.core.time.J2kSec; +import gov.usgs.volcanoes.core.util.UiUtils; import gov.usgs.volcanoes.swarm.Icons; import gov.usgs.volcanoes.swarm.SwarmFrame; +import gov.usgs.volcanoes.swarm.SwarmUtil; import gov.usgs.volcanoes.swarm.SwingWorker; +import gov.usgs.volcanoes.swarm.Throbber; +import gov.usgs.volcanoes.swarm.data.CachedDataSource; import gov.usgs.volcanoes.swarm.data.SeismicDataSource; -import gov.usgs.volcanoes.swarm.data.fdsnWs.WebServicesClient; import gov.usgs.volcanoes.swarm.internalFrame.SwarmInternalFrames; -import gov.usgs.volcanoes.swarm.wave.WaveViewPanel; +import gov.usgs.volcanoes.swarm.picker.PickerWavePanel; +import gov.usgs.volcanoes.swarm.wave.AbstractWavePanel; +import gov.usgs.volcanoes.swarm.wave.WaveViewPanelListener; +import gov.usgs.volcanoes.swarm.wave.WaveViewSettingsToolbar; /** * The picker internal frame. Adapted from the WaveClipboardFrame. @@ -60,19 +79,50 @@ public class EventFrame extends SwarmFrame implements EventObserver { public static final long serialVersionUID = -1; private JSplitPane mainPanel; - private JScrollPane pickScrollPane; + private JPanel pickPanel; private Event event; private SeismicDataSource seismicDataSource; private final PickPanel pickBox; + private JToolBar toolbar; + private final JLabel statusLabel; + private JButton sizeButton; + private JButton saveButton; + private JButton captureButton; + private JButton histButton; + private JButton locateButton; + + private final DateFormat saveAllDateFormat; + + private WaveViewPanelListener selectListener; + private WaveViewSettingsToolbar waveToolbar; + + private JButton upButton; + private JButton downButton; + private JButton removeButton; + private JButton compXButton; + private JButton expXButton; + private JButton forwardButton; + private JButton backButton; + private JButton gotoButton; + private Throbber throbber; + private final Map> histories; + private final Set selectedSet; + private boolean closing = false; public EventFrame(Event event) { super("Event - " + event.getEvid(), true, true, true, false); this.event = event; + statusLabel = new JLabel(" "); + saveAllDateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); + saveAllDateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); + histories = new HashMap>(); + selectedSet = new HashSet(); + event.addObserver(this); this.setFocusable(true); createListeners(); - pickBox = new PickPanel(); + pickBox = new PickPanel(statusLabel); pickBox.setLayout(new BoxLayout(pickBox, BoxLayout.PAGE_AXIS)); setFrameIcon(Icons.ruler); @@ -82,8 +132,8 @@ public EventFrame(Event event) { LOGGER.debug("event frame: {} @ {}", this.getSize(), this.getLocation()); - pickScrollPane = createPickPanel(); - mainPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT, createParameterPanel(), pickScrollPane); + pickPanel = createPickPanel(); + mainPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT, createParameterPanel(), pickPanel); mainPanel.setOneTouchExpandable(true); setContentPane(mainPanel); @@ -121,11 +171,30 @@ private Component createParameterPanel() { JLabel label; + label = new JLabel("Event source: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + String source = Networks.getInstance().getName(event.getEventSource().toUpperCase()); + if (source == null) { + source = event.getEventSource(); + } + label = new JLabel(Networks.getInstance().getName(event.getEventSource().toUpperCase()), + SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + + c.gridy++; + label = new JLabel("Description: ", SwingConstants.LEFT); label.setFont(KEY_FONT); parameterPanel.add(label, c); - label = new JLabel(event.getDescription(), SwingConstants.LEFT); + // wrap description to support multi-line descriptions + String description = event.getDescription(); + description = description.replace("\n", "
"); + description = "" + description + ""; + label = new JLabel(description, SwingConstants.LEFT); label.setFont(VALUE_FONT); parameterPanel.add(label, c); @@ -144,31 +213,118 @@ private Component createParameterPanel() { } c.gridy++; - label = new JLabel("Magnitude: ", SwingConstants.LEFT); + + label = new JLabel("Hypocenter: ", SwingConstants.LEFT); label.setFont(KEY_FONT); parameterPanel.add(label, c); - if (magnitude != null) { - String mag = String.format("%s (%s)", magnitude.getMag(), magnitude.getType()); - label = new JLabel(mag, SwingConstants.LEFT); + if (origin != null) { + String loc = origin.getLatitude() + ", " + origin.getLongitude(); + loc += " at " + (origin.getDepth() / 1000) + " km depth"; + label = new JLabel(loc, SwingConstants.LEFT); label.setFont(VALUE_FONT); parameterPanel.add(label, c); } c.gridy++; - label = new JLabel("Location: ", SwingConstants.LEFT); + label = new JLabel("Error (RMS): ", SwingConstants.LEFT); label.setFont(KEY_FONT); parameterPanel.add(label, c); - if (origin != null) { - String loc = origin.getLatitude() + ", " + origin.getLongitude(); - loc += " at " + (origin.getDepth() / 1000) + " km depth"; - label = new JLabel(loc, SwingConstants.LEFT); + double error = origin.getStandardError(); + if (!Double.isNaN(error)) { + label = new JLabel("" + error, SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + } + c.gridy++; + + label = new JLabel("Azimuthal gap: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + double gap = origin.getAzimuthalGap(); + if (!Double.isNaN(gap)) { + label = new JLabel("" + gap + "\u00B0", SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + } + c.gridy++; + + label = new JLabel("Nearest station: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + double distance = origin.getMinimumDistance(); + if (!Double.isNaN(distance)) { + label = new JLabel("" + distance + "\u00B0", SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + } + c.gridy++; + + label = new JLabel("Phase count: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + int phaseCount = origin.getPhaseCount(); + if (phaseCount > 0) { + label = new JLabel("" + phaseCount, SwingConstants.LEFT); label.setFont(VALUE_FONT); parameterPanel.add(label, c); } c.gridy++; + label = new JLabel("Magnitude: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + if (magnitude != null) { + String mag = String.format("%s %s", magnitude.getMag(), magnitude.getType()); + String uncertaintly = magnitude.getUncertainty(); + if (uncertaintly != null) { + mag += " (" + uncertaintly + ")"; + } + label = new JLabel(mag, SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + } + c.gridy++; + + label = new JLabel("Evalutation: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + String evaluationTag = ""; + + Origin.EvaluationMode evaluationMode = origin.getEvaluationMode(); + if (evaluationMode != null) { + evaluationTag += evaluationMode.toString().toLowerCase(); + } + + Origin.EvaluationStatus evaluationStatus = origin.getEvaluationStatus(); + if (evaluationStatus != null) { + if (evaluationTag.length() > 0) { + evaluationTag += " / "; + } + evaluationTag += evaluationStatus.toString().toLowerCase(); + } + + label = new JLabel(evaluationTag, SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + + c.gridy++; + + label = new JLabel("Event id: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + label = new JLabel(event.getEvid(), SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + c.gridy++; + c.weighty = 1; c.weightx = 1; c.gridy++; @@ -176,28 +332,416 @@ private Component createParameterPanel() { JPanel filler = new JPanel(); parameterPanel.add(filler, c); - return parameterPanel; + final JScrollPane scrollPane = new JScrollPane(parameterPanel); + scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); + scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + scrollPane.getVerticalScrollBar().setUnitIncrement(40); + + return scrollPane; } - private JScrollPane createPickPanel() { + private JPanel createPickPanel() { + toolbar = SwarmUtil.createToolBar(); + createMainButtons(); + createWaveButtons(); final JScrollPane scrollPane = new JScrollPane(pickBox); scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); scrollPane.getVerticalScrollBar().setUnitIncrement(40); - scrollPane.addComponentListener(new ComponentAdapter() { + + JPanel pickPanel = new JPanel(); + pickPanel.setLayout(new BoxLayout(pickPanel, BoxLayout.PAGE_AXIS)); + LOGGER.info("Adding toolbar"); + pickPanel.add(toolbar); + pickPanel.add(scrollPane); + + JPanel statusPanel = new JPanel(); + statusPanel.setLayout(new BorderLayout()); + statusLabel.setBorder(BorderFactory.createEtchedBorder()); + statusPanel.add(statusLabel); + statusPanel + .setMaximumSize(new Dimension(Integer.MAX_VALUE, statusPanel.getPreferredSize().height)); + pickPanel.add(statusPanel); + + return pickPanel; + } + + private void createMainButtons() { + saveButton = + SwarmUtil.createToolBarButton(Icons.save, "Save selected wave", new SaveActionListener()); + saveButton.setEnabled(false); + toolbar.add(saveButton); + + toolbar.addSeparator(); + + sizeButton = + SwarmUtil.createToolBarButton(Icons.resize, "Set wave height", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + doSizePopup(); + } + }); + toolbar.add(sizeButton); + + toolbar.addSeparator(); + captureButton = SwarmUtil.createToolBarButton(Icons.camera, "Save pick image (P)", + new CaptureActionListener()); + UiUtils.mapKeyStrokeToButton(this, "P", "capture", captureButton); + toolbar.add(captureButton); + } + + + private void createWaveButtons() { + toolbar.addSeparator(); + + backButton = SwarmUtil.createToolBarButton(Icons.left, "Scroll back time 20% (Left arrow)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + shiftTime(-0.20); + } + }); + UiUtils.mapKeyStrokeToButton(this, "LEFT", "backward1", backButton); + toolbar.add(backButton); + + forwardButton = SwarmUtil.createToolBarButton(Icons.right, + "Scroll forward time 20% (Right arrow)", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + shiftTime(0.20); + } + }); + toolbar.add(forwardButton); + UiUtils.mapKeyStrokeToButton(this, "RIGHT", "forward1", forwardButton); + + gotoButton = + SwarmUtil.createToolBarButton(Icons.gototime, "Go to time (Ctrl-G)", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + final String t = JOptionPane.showInputDialog(applicationFrame, + "Input time in 'YYYYMMDDhhmm[ss]' format:", "Go to Time", + JOptionPane.PLAIN_MESSAGE); + if (t != null) + gotoTime(t); + } + }); + toolbar.add(gotoButton); + UiUtils.mapKeyStrokeToButton(this, "ctrl G", "goto", gotoButton); + + compXButton = SwarmUtil.createToolBarButton(Icons.xminus, + "Shrink sample time 20% (Alt-left arrow, +)", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + scaleTime(0.20); + } + }); + toolbar.add(compXButton); + UiUtils.mapKeyStrokeToButton(this, "alt LEFT", "compx", compXButton); + UiUtils.mapKeyStrokeToButton(this, "EQUALS", "compx2", compXButton); + UiUtils.mapKeyStrokeToButton(this, "shift EQUALS", "compx2", compXButton); + + expXButton = SwarmUtil.createToolBarButton(Icons.xplus, + "Expand sample time 20% (Alt-right arrow, -)", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + scaleTime(-0.20); + } + }); + toolbar.add(expXButton); + UiUtils.mapKeyStrokeToButton(this, "alt RIGHT", "expx", expXButton); + UiUtils.mapKeyStrokeToButton(this, "MINUS", "expx", expXButton); + + histButton = SwarmUtil.createToolBarButton(Icons.timeback, "Last time settings (Backspace)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + back(); + } + }); + UiUtils.mapKeyStrokeToButton(this, "BACK_SPACE", "back", histButton); + toolbar.add(histButton); + toolbar.addSeparator(); + + waveToolbar = new WaveViewSettingsToolbar(null, toolbar, this); + + toolbar.addSeparator(); + + toolbar.add(Box.createHorizontalGlue()); + + throbber = new Throbber(); + toolbar.add(throbber); + + // UiUtils.mapKeyStrokeToAction(this, "control A", "selectAll", new AbstractAction() { + // private static final long serialVersionUID = 1L; + // + // public void actionPerformed(final ActionEvent e) { + // for (final PickerWavePanel wave : waves) + // select(wave); + // } + // }); + } + + private void addHistory(final AbstractWavePanel wvp, final double[] t) { + Stack history = histories.get(wvp); + if (history == null) { + history = new Stack(); + histories.put(wvp, history); + } + history.push(t); + } + + public void gotoTime(final AbstractWavePanel wvp, String t) { + double j2k = Double.NaN; + try { + if (t.length() == 12) + t = t + "30"; + + j2k = J2kSec.parse("yyyyMMddHHmmss", t); + } catch (final Exception e) { + JOptionPane.showMessageDialog(applicationFrame, "Illegal time value.", "Error", + JOptionPane.ERROR_MESSAGE); + } + + if (!Double.isNaN(j2k)) { + double dt = 60; + if (wvp.getWave() != null) { + final double st = wvp.getStartTime(); + final double et = wvp.getEndTime(); + final double[] ts = new double[] {st, et}; + addHistory(wvp, ts); + dt = (et - st); + } + + final double tzo = + swarmConfig.getTimeZone(wvp.getChannel()).getOffset(System.currentTimeMillis()) / 1000; + + final double nst = j2k - tzo - dt / 2; + final double net = nst + dt; + + fetchNewWave(wvp, nst, net); + } + } + + // TODO: This isn't right, this should be a method of waveviewpanel + private void fetchNewWave(final AbstractWavePanel wvp, final double nst, final double net) { + final SwingWorker worker = new SwingWorker() { @Override - public void componentResized(final ComponentEvent e) { - scrollPane.getViewport().setSize(scrollPane.getWidth(), scrollPane.getViewport().getHeight()); + public Object construct() { + throbber.increment(); + final SeismicDataSource sds = wvp.getDataSource(); + // Hacky fix for bug #84 + Wave sw = null; + if (sds instanceof CachedDataSource) + sw = ((CachedDataSource) sds).getBestWave(wvp.getChannel(), nst, net); + else + sw = sds.getWave(wvp.getChannel(), nst, net); + wvp.setWave(sw, nst, net); + wvp.repaint(); + return null; } - }); - return scrollPane; + @Override + public void finished() { + throbber.decrement(); + repaint(); + } + }; + worker.start(); + } + + + public void gotoTime(final String t) { + for (final AbstractWavePanel p : selectedSet) + gotoTime(p, t); + } + + public void scaleTime(final AbstractWavePanel wvp, final double pct) { + final double st = wvp.getStartTime(); + final double et = wvp.getEndTime(); + final double[] t = new double[] {st, et}; + addHistory(wvp, t); + final double dt = (et - st) * (1 - pct); + final double mt = (et - st) / 2 + st; + final double nst = mt - dt / 2; + final double net = mt + dt / 2; + fetchNewWave(wvp, nst, net); + } + + public void scaleTime(final double pct) { + for (final AbstractWavePanel p : selectedSet) + scaleTime(p, pct); + } + + public void back(final AbstractWavePanel wvp) { + final Stack history = histories.get(wvp); + if (history == null || history.empty()) + return; + + final double[] t = history.pop(); + fetchNewWave(wvp, t[0], t[1]); + } + + public void back() { + for (final AbstractWavePanel p : selectedSet) + back(p); + } + + private void shiftTime(final AbstractWavePanel wvp, final double pct) { + final double st = wvp.getStartTime(); + final double et = wvp.getEndTime(); + final double[] t = new double[] {st, et}; + addHistory(wvp, t); + final double dt = (et - st) * pct; + final double nst = st + dt; + final double net = et + dt; + fetchNewWave(wvp, nst, net); + } + + public void shiftTime(final double pct) { + for (final AbstractWavePanel p : selectedSet) + shiftTime(p, pct); + } + + // TODO: don't write image on event thread + // TODO: unify with MapFrame.CaptureActionListener + class CaptureActionListener implements ActionListener { + public void actionPerformed(final ActionEvent e) { + // if (waves == null || waves.size() == 0) + // return; + // + // final JFileChooser chooser = FileChooser.getFileChooser(); + // final File lastPath = new File(swarmConfig.lastPath); + // chooser.setCurrentDirectory(lastPath); + // chooser.setSelectedFile(new File("clipboard.png")); + // chooser.setDialogTitle("Save Clipboard Screen Capture"); + // final int result = chooser.showSaveDialog(applicationFrame); + // File f = null; + // if (result == JFileChooser.APPROVE_OPTION) { + // f = chooser.getSelectedFile(); + // + // if (f.exists()) { + // final int choice = JOptionPane.showConfirmDialog(applicationFrame, + // "File exists, overwrite?", "Confirm", JOptionPane.YES_NO_OPTION); + // if (choice != JOptionPane.YES_OPTION) + // return; + // } + // swarmConfig.lastPath = f.getParent(); + // } + // if (f == null) + // return; + // + // int height = 0; + // final int width = waves.get(0).getWidth(); + // for (final AbstractWavePanel panel : waves) + // height += panel.getHeight(); + // + // final BufferedImage image = new BufferedImage(width, height, + // BufferedImage.TYPE_4BYTE_ABGR); + // final Graphics g = image.getGraphics(); + // for (final AbstractWavePanel panel : waves) { + // panel.paint(g); + // g.translate(0, panel.getHeight()); + // } + // try { + // final PngEncoderB png = new PngEncoderB(image, false, PngEncoder.FILTER_NONE, 7); + // final FileOutputStream out = new FileOutputStream(f); + // final byte[] bytes = png.pngEncode(); + // out.write(bytes); + // out.close(); + // } catch (final Exception ex) { + // ex.printStackTrace(); + // } + } + } + + + private class SaveActionListener implements ActionListener { + public void actionPerformed(final ActionEvent e) { + // final AbstractWavePanel selected = getSingleSelected(); + // if (selected == null) + // return; + // + // final JFileChooser chooser = FileChooser.getFileChooser(); + // chooser.resetChoosableFileFilters(); + // chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + // chooser.setMultiSelectionEnabled(false); + // chooser.setDialogTitle("Save Wave"); + // + // for (final FileType ft : FileType.values()) { + // if (ft == FileType.UNKNOWN) + // continue; + // + // final ExtensionFileFilter f = new ExtensionFileFilter(ft.extension, ft.description); + // chooser.addChoosableFileFilter(f); + // } + // + // chooser.setFileFilter(chooser.getAcceptAllFileFilter()); + // + // final File lastPath = new File(swarmConfig.lastPath); + // chooser.setCurrentDirectory(lastPath); + // final String fileName = selected.getChannel().replace(' ', '_') + ".sac"; + // chooser.setSelectedFile(new File(fileName)); + // final int result = chooser.showSaveDialog(applicationFrame); + // if (result == JFileChooser.APPROVE_OPTION) { + // final File f = chooser.getSelectedFile(); + // boolean confirm = true; + // if (f.exists()) { + // if (f.isDirectory()) { + // JOptionPane.showMessageDialog(applicationFrame, + // "You can not select an existing directory.", "Error", JOptionPane.ERROR_MESSAGE); + // return; + // } + // confirm = false; + // final int choice = JOptionPane.showConfirmDialog(applicationFrame, + // "File exists, overwrite?", "Confirm", JOptionPane.YES_NO_OPTION); + // if (choice == JOptionPane.YES_OPTION) + // confirm = true; + // } + // + // if (confirm) { + // try { + // swarmConfig.lastPath = f.getParent(); + // final String fn = f.getPath(); + // final SeismicDataFile file = SeismicDataFile.getFile(fn); + // final Wave wave = selected.getWave(); + // file.putWave(selected.getChannel(), wave); + // file.write(); + // } catch (final FileNotFoundException ex) { + // JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Directory does not exist.", + // "Error", JOptionPane.ERROR_MESSAGE); + // } catch (final IOException ex) { + // JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Error writing file.", + // "Error", JOptionPane.ERROR_MESSAGE); + // } + // } + // } + } + } + + private void doSizePopup() { + // if (popup == null) { + // final String[] labels = new String[] {"Auto", null, "Tiny", "Small", "Medium", "Large"}; + // final int[] sizes = new int[] {-1, -1, 50, 100, 160, 230}; + // popup = new JPopupMenu(); + // final ButtonGroup group = new ButtonGroup(); + // for (int i = 0; i < labels.length; i++) { + // if (labels[i] != null) { + // final int size = sizes[i]; + // final JRadioButtonMenuItem mi = new JRadioButtonMenuItem(labels[i]); + // mi.addActionListener(new ActionListener() { + // public void actionPerformed(final ActionEvent e) { + // setWaveHeight(size); + // } + // }); + // if (waveHeight == size) + // mi.setSelected(true); + // group.add(mi); + // popup.add(mi); + // } else + // popup.addSeparator(); + // } + // } + // popup.show(sizeButton.getParent(), sizeButton.getX(), sizeButton.getY()); } public void fetchDetailedEvent() { final String neicEvid = event.getEventSource() + event.getEvid(); final Event workingEvent = event; + String url = "http://earthquake.usgs.gov/fdsnws/event/1/query?eventid=" + neicEvid; DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); @@ -208,8 +752,14 @@ public void fetchDetailedEvent() { dBuilder = dbFactory.newDocumentBuilder(); doc = dBuilder.parse(url); doc.getDocumentElement().normalize(); + NodeList eventElements = doc.getElementsByTagName("event"); - workingEvent.updateEvent((Element) eventElements.item(0)); + Element eventElement = (Element) eventElements.item(0); + NodeList descriptionNodes = eventElement.getElementsByTagName("description"); + for (int idx = 0; idx < descriptionNodes.getLength(); idx++) { + eventElement.removeChild(descriptionNodes.item(idx)); + } + workingEvent.updateEvent(eventElement); } catch (SAXException e1) { // TODO Auto-generated catch block e1.printStackTrace(); @@ -240,11 +790,18 @@ private void populatePicks() { pickBox.setStart(waveStart); pickBox.setEnd(waveEnd); - for (Arrival arrival : origin.getArrivals()) { + throbber.increment(); + TreeSet arrivals = new TreeSet(Arrival.distanceComparator()); + arrivals.addAll(origin.getArrivals()); + for (Arrival arrival : arrivals) { + if (closing) { + break; + } pickBox.addPick(arrival); mainPanel.validate(); LOGGER.debug("pickBox {}", pickBox.countComponents()); } + throbber.decrement(); } @Override @@ -280,6 +837,7 @@ public void internalFrameDeiconified(final InternalFrameEvent e) {} @Override public void internalFrameClosing(final InternalFrameEvent e) { + closing = true; dispose(); SwarmInternalFrames.remove(EventFrame.this); } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame3.java b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame3.java new file mode 100644 index 00000000..d0db5afb --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame3.java @@ -0,0 +1,805 @@ +package gov.usgs.volcanoes.swarm.event; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.io.IOException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.Stack; +import java.util.TimeZone; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JToolBar; +import javax.swing.ScrollPaneConstants; +import javax.swing.SwingConstants; +import javax.swing.WindowConstants; +import javax.swing.event.InternalFrameAdapter; +import javax.swing.event.InternalFrameEvent; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.log4j.Layout; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import gov.usgs.plot.data.Wave; +import gov.usgs.volcanoes.core.time.J2kSec; +import gov.usgs.volcanoes.core.util.UiUtils; +import gov.usgs.volcanoes.swarm.Icons; +import gov.usgs.volcanoes.swarm.SwarmFrame; +import gov.usgs.volcanoes.swarm.SwarmUtil; +import gov.usgs.volcanoes.swarm.SwingWorker; +import gov.usgs.volcanoes.swarm.Throbber; +import gov.usgs.volcanoes.swarm.data.CachedDataSource; +import gov.usgs.volcanoes.swarm.data.SeismicDataSource; +import gov.usgs.volcanoes.swarm.internalFrame.SwarmInternalFrames; +import gov.usgs.volcanoes.swarm.picker.PickerWavePanel; +import gov.usgs.volcanoes.swarm.wave.AbstractWavePanel; +import gov.usgs.volcanoes.swarm.wave.WaveViewPanelListener; +import gov.usgs.volcanoes.swarm.wave.WaveViewSettingsToolbar; + +/** + * The picker internal frame. Adapted from the WaveClipboardFrame. + * + * @author Tom Parker + */ +public class EventFrame3 extends SwarmFrame implements EventObserver { + private static final Logger LOGGER = LoggerFactory.getLogger(EventFrame3.class); + private static final Color BACKGROUND_COLOR = new Color(255, 255, 255); + private static final Font KEY_FONT = Font.decode("dialog-BOLD-12"); + private static final Font VALUE_FONT = Font.decode("dialog-12"); + + public static final long serialVersionUID = -1; + + private JSplitPane mainPanel; + private Component pickPanel; + private Event event; + private SeismicDataSource seismicDataSource; + private final PickPanel pickBox; + private JToolBar toolbar; + private final JLabel statusLabel; + private JButton sizeButton; + private JButton saveButton; + private JButton captureButton; + private JButton histButton; + private JButton locateButton; + + private final DateFormat saveAllDateFormat; + + private WaveViewPanelListener selectListener; + private WaveViewSettingsToolbar waveToolbar; + + private JButton upButton; + private JButton downButton; + private JButton removeButton; + private JButton compXButton; + private JButton expXButton; + private JButton forwardButton; + private JButton backButton; + private JButton gotoButton; + private Throbber throbber; + private final Map> histories; + private final Set selectedSet; + private boolean closing = false; + + public EventFrame3(Event event) { + super("Event - " + event.getEvid(), true, true, true, false); + this.event = event; + statusLabel = new JLabel(" "); + saveAllDateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); + saveAllDateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); + histories = new HashMap>(); + selectedSet = new HashSet(); + + event.addObserver(this); + this.setFocusable(true); + createListeners(); + + pickBox = new PickPanel(statusLabel); + pickBox.setLayout(new BoxLayout(pickBox, BoxLayout.PAGE_AXIS)); + + setFrameIcon(Icons.ruler); + setSize(swarmConfig.clipboardWidth, swarmConfig.clipboardHeight); + setLocation(swarmConfig.clipboardX, swarmConfig.clipboardY); + setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + LOGGER.debug("event frame: {} @ {}", this.getSize(), this.getLocation()); + + + pickPanel = createPickPanel(); + mainPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT, createParameterPanel(), pickPanel); + mainPanel.setOneTouchExpandable(true); + + setContentPane(mainPanel); + this.setVisible(true); + + new SwingWorker() { + @Override + public Object construct() { + fetchDetailedEvent(); + populatePicks(); + return null; + } + + @Override + public void finished() { + repaint(); + } + }.start(); + } + + private Component createParameterPanel() { + Origin origin = event.getPreferredOrigin(); + Magnitude magnitude = event.getPerferredMagnitude(); + + JPanel parameterPanel = new JPanel(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.NORTHWEST; + c.gridy = 0; + c.gridx = GridBagConstraints.RELATIVE; + c.ipadx = 3; + c.ipady = 2; + + JLabel label; + + label = new JLabel("Event source: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + label = new JLabel(event.getEventSource(), SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + + c.gridy++; + + label = new JLabel("Description: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + // wrap description to support multi-line descriptions + String description = event.getDescription(); + description = description.replace("\n", "
"); + description = "" + description + ""; + label = new JLabel(description, SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + + c.gridy++; + + label = new JLabel("Origin date: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + if (origin != null) { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + String date = dateFormat.format(event.getPreferredOrigin().getTime()); + label = new JLabel(date, SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + } + c.gridy++; + + + label = new JLabel("Hypocenter: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + if (origin != null) { + String loc = origin.getLatitude() + ", " + origin.getLongitude(); + loc += " at " + (origin.getDepth() / 1000) + " km depth"; + label = new JLabel(loc, SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + } + c.gridy++; + + label = new JLabel("Magnitude: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + if (magnitude != null) { + String mag = String.format("%s %s", magnitude.getMag(), magnitude.getType()); + String uncertaintly = magnitude.getUncertainty(); + if (uncertaintly != null) { + mag += " (" + uncertaintly + ")"; + } + label = new JLabel(mag, SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + } + c.gridy++; + + label = new JLabel("Event id: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + label = new JLabel(event.getEvid(), SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + c.gridy++; + + c.weighty = 1; + c.weightx = 1; + c.gridy++; + c.gridx = 10; + JPanel filler = new JPanel(); + parameterPanel.add(filler, c); + + final JScrollPane scrollPane = new JScrollPane(parameterPanel); + scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); + scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + scrollPane.getVerticalScrollBar().setUnitIncrement(40); + + return scrollPane; + } + + private Component createPickPanel() { + +// toolbar = SwarmUtil.createToolBar(); +// createMainButtons(); +// createWaveButtons(); + + GridBagLayout layout = new GridBagLayout(); + GridBagConstraints c = new GridBagConstraints(); + + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.NORTHWEST; + c.gridy = 0; + c.gridx = GridBagConstraints.RELATIVE; + c.ipadx = 3; + c.ipady = 2; + + JPanel tablePanel = new JPanel(layout); + + tablePanel.add(new JLabel("AAAAAAAAAAAAAAAAAA", SwingConstants.LEFT), c); + tablePanel.add(new JLabel("Event id", SwingConstants.LEFT), c); + tablePanel.add(new JLabel("XXX", SwingConstants.LEFT), c); + + final JScrollPane scrollPane = new JScrollPane(tablePanel); + scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + scrollPane.getVerticalScrollBar().setUnitIncrement(40); + + JPanel headerPanel = new JPanel(layout); + scrollPane.setColumnHeaderView(headerPanel); + c.gridy = 0; + headerPanel.add(new JLabel("Event id", SwingConstants.LEFT), c); + headerPanel.add(new JLabel("XXX", SwingConstants.LEFT), c); + headerPanel.add(new JLabel("AAAAAAAAAAAAAAAAAA", SwingConstants.LEFT), c); + +// JPanel pickPanel = new JPanel(); +// pickPanel.setLayout(new BoxLayout(pickPanel, BoxLayout.PAGE_AXIS)); +// LOGGER.info("Adding toolbar"); +// pickPanel.add(toolbar); +// pickPanel.add(scrollPane); +// +// JPanel statusPanel = new JPanel(); +// statusPanel.setLayout(new BorderLayout()); +// statusLabel.setBorder(BorderFactory.createEtchedBorder()); +// statusPanel.add(statusLabel); +// statusPanel +// .setMaximumSize(new Dimension(Integer.MAX_VALUE, statusPanel.getPreferredSize().height)); +// pickPanel.add(statusPanel); + + return scrollPane; + } + + private void createMainButtons() { + saveButton = + SwarmUtil.createToolBarButton(Icons.save, "Save selected wave", new SaveActionListener()); + saveButton.setEnabled(false); + toolbar.add(saveButton); + + toolbar.addSeparator(); + + sizeButton = + SwarmUtil.createToolBarButton(Icons.resize, "Set wave height", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + doSizePopup(); + } + }); + toolbar.add(sizeButton); + + toolbar.addSeparator(); + captureButton = SwarmUtil.createToolBarButton(Icons.camera, "Save pick image (P)", + new CaptureActionListener()); + UiUtils.mapKeyStrokeToButton(this, "P", "capture", captureButton); + toolbar.add(captureButton); + } + + + private void createWaveButtons() { + toolbar.addSeparator(); + + backButton = SwarmUtil.createToolBarButton(Icons.left, "Scroll back time 20% (Left arrow)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + shiftTime(-0.20); + } + }); + UiUtils.mapKeyStrokeToButton(this, "LEFT", "backward1", backButton); + toolbar.add(backButton); + + forwardButton = SwarmUtil.createToolBarButton(Icons.right, + "Scroll forward time 20% (Right arrow)", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + shiftTime(0.20); + } + }); + toolbar.add(forwardButton); + UiUtils.mapKeyStrokeToButton(this, "RIGHT", "forward1", forwardButton); + + gotoButton = + SwarmUtil.createToolBarButton(Icons.gototime, "Go to time (Ctrl-G)", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + final String t = JOptionPane.showInputDialog(applicationFrame, + "Input time in 'YYYYMMDDhhmm[ss]' format:", "Go to Time", + JOptionPane.PLAIN_MESSAGE); + if (t != null) + gotoTime(t); + } + }); + toolbar.add(gotoButton); + UiUtils.mapKeyStrokeToButton(this, "ctrl G", "goto", gotoButton); + + compXButton = SwarmUtil.createToolBarButton(Icons.xminus, + "Shrink sample time 20% (Alt-left arrow, +)", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + scaleTime(0.20); + } + }); + toolbar.add(compXButton); + UiUtils.mapKeyStrokeToButton(this, "alt LEFT", "compx", compXButton); + UiUtils.mapKeyStrokeToButton(this, "EQUALS", "compx2", compXButton); + UiUtils.mapKeyStrokeToButton(this, "shift EQUALS", "compx2", compXButton); + + expXButton = SwarmUtil.createToolBarButton(Icons.xplus, + "Expand sample time 20% (Alt-right arrow, -)", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + scaleTime(-0.20); + } + }); + toolbar.add(expXButton); + UiUtils.mapKeyStrokeToButton(this, "alt RIGHT", "expx", expXButton); + UiUtils.mapKeyStrokeToButton(this, "MINUS", "expx", expXButton); + + histButton = SwarmUtil.createToolBarButton(Icons.timeback, "Last time settings (Backspace)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + back(); + } + }); + UiUtils.mapKeyStrokeToButton(this, "BACK_SPACE", "back", histButton); + toolbar.add(histButton); + toolbar.addSeparator(); + + waveToolbar = new WaveViewSettingsToolbar(null, toolbar, this); + + toolbar.addSeparator(); + + toolbar.add(Box.createHorizontalGlue()); + + throbber = new Throbber(); + toolbar.add(throbber); + + // UiUtils.mapKeyStrokeToAction(this, "control A", "selectAll", new AbstractAction() { + // private static final long serialVersionUID = 1L; + // + // public void actionPerformed(final ActionEvent e) { + // for (final PickerWavePanel wave : waves) + // select(wave); + // } + // }); + } + + private void addHistory(final AbstractWavePanel wvp, final double[] t) { + Stack history = histories.get(wvp); + if (history == null) { + history = new Stack(); + histories.put(wvp, history); + } + history.push(t); + } + + public void gotoTime(final AbstractWavePanel wvp, String t) { + double j2k = Double.NaN; + try { + if (t.length() == 12) + t = t + "30"; + + j2k = J2kSec.parse("yyyyMMddHHmmss", t); + } catch (final Exception e) { + JOptionPane.showMessageDialog(applicationFrame, "Illegal time value.", "Error", + JOptionPane.ERROR_MESSAGE); + } + + if (!Double.isNaN(j2k)) { + double dt = 60; + if (wvp.getWave() != null) { + final double st = wvp.getStartTime(); + final double et = wvp.getEndTime(); + final double[] ts = new double[] {st, et}; + addHistory(wvp, ts); + dt = (et - st); + } + + final double tzo = + swarmConfig.getTimeZone(wvp.getChannel()).getOffset(System.currentTimeMillis()) / 1000; + + final double nst = j2k - tzo - dt / 2; + final double net = nst + dt; + + fetchNewWave(wvp, nst, net); + } + } + + // TODO: This isn't right, this should be a method of waveviewpanel + private void fetchNewWave(final AbstractWavePanel wvp, final double nst, final double net) { + final SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + throbber.increment(); + final SeismicDataSource sds = wvp.getDataSource(); + // Hacky fix for bug #84 + Wave sw = null; + if (sds instanceof CachedDataSource) + sw = ((CachedDataSource) sds).getBestWave(wvp.getChannel(), nst, net); + else + sw = sds.getWave(wvp.getChannel(), nst, net); + wvp.setWave(sw, nst, net); + wvp.repaint(); + return null; + } + + @Override + public void finished() { + throbber.decrement(); + repaint(); + } + }; + worker.start(); + } + + + public void gotoTime(final String t) { + for (final AbstractWavePanel p : selectedSet) + gotoTime(p, t); + } + + public void scaleTime(final AbstractWavePanel wvp, final double pct) { + final double st = wvp.getStartTime(); + final double et = wvp.getEndTime(); + final double[] t = new double[] {st, et}; + addHistory(wvp, t); + final double dt = (et - st) * (1 - pct); + final double mt = (et - st) / 2 + st; + final double nst = mt - dt / 2; + final double net = mt + dt / 2; + fetchNewWave(wvp, nst, net); + } + + public void scaleTime(final double pct) { + for (final AbstractWavePanel p : selectedSet) + scaleTime(p, pct); + } + + public void back(final AbstractWavePanel wvp) { + final Stack history = histories.get(wvp); + if (history == null || history.empty()) + return; + + final double[] t = history.pop(); + fetchNewWave(wvp, t[0], t[1]); + } + + public void back() { + for (final AbstractWavePanel p : selectedSet) + back(p); + } + + private void shiftTime(final AbstractWavePanel wvp, final double pct) { + final double st = wvp.getStartTime(); + final double et = wvp.getEndTime(); + final double[] t = new double[] {st, et}; + addHistory(wvp, t); + final double dt = (et - st) * pct; + final double nst = st + dt; + final double net = et + dt; + fetchNewWave(wvp, nst, net); + } + + public void shiftTime(final double pct) { + for (final AbstractWavePanel p : selectedSet) + shiftTime(p, pct); + } + + // TODO: don't write image on event thread + // TODO: unify with MapFrame.CaptureActionListener + class CaptureActionListener implements ActionListener { + public void actionPerformed(final ActionEvent e) { + // if (waves == null || waves.size() == 0) + // return; + // + // final JFileChooser chooser = FileChooser.getFileChooser(); + // final File lastPath = new File(swarmConfig.lastPath); + // chooser.setCurrentDirectory(lastPath); + // chooser.setSelectedFile(new File("clipboard.png")); + // chooser.setDialogTitle("Save Clipboard Screen Capture"); + // final int result = chooser.showSaveDialog(applicationFrame); + // File f = null; + // if (result == JFileChooser.APPROVE_OPTION) { + // f = chooser.getSelectedFile(); + // + // if (f.exists()) { + // final int choice = JOptionPane.showConfirmDialog(applicationFrame, + // "File exists, overwrite?", "Confirm", JOptionPane.YES_NO_OPTION); + // if (choice != JOptionPane.YES_OPTION) + // return; + // } + // swarmConfig.lastPath = f.getParent(); + // } + // if (f == null) + // return; + // + // int height = 0; + // final int width = waves.get(0).getWidth(); + // for (final AbstractWavePanel panel : waves) + // height += panel.getHeight(); + // + // final BufferedImage image = new BufferedImage(width, height, + // BufferedImage.TYPE_4BYTE_ABGR); + // final Graphics g = image.getGraphics(); + // for (final AbstractWavePanel panel : waves) { + // panel.paint(g); + // g.translate(0, panel.getHeight()); + // } + // try { + // final PngEncoderB png = new PngEncoderB(image, false, PngEncoder.FILTER_NONE, 7); + // final FileOutputStream out = new FileOutputStream(f); + // final byte[] bytes = png.pngEncode(); + // out.write(bytes); + // out.close(); + // } catch (final Exception ex) { + // ex.printStackTrace(); + // } + } + } + + + private class SaveActionListener implements ActionListener { + public void actionPerformed(final ActionEvent e) { + // final AbstractWavePanel selected = getSingleSelected(); + // if (selected == null) + // return; + // + // final JFileChooser chooser = FileChooser.getFileChooser(); + // chooser.resetChoosableFileFilters(); + // chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + // chooser.setMultiSelectionEnabled(false); + // chooser.setDialogTitle("Save Wave"); + // + // for (final FileType ft : FileType.values()) { + // if (ft == FileType.UNKNOWN) + // continue; + // + // final ExtensionFileFilter f = new ExtensionFileFilter(ft.extension, ft.description); + // chooser.addChoosableFileFilter(f); + // } + // + // chooser.setFileFilter(chooser.getAcceptAllFileFilter()); + // + // final File lastPath = new File(swarmConfig.lastPath); + // chooser.setCurrentDirectory(lastPath); + // final String fileName = selected.getChannel().replace(' ', '_') + ".sac"; + // chooser.setSelectedFile(new File(fileName)); + // final int result = chooser.showSaveDialog(applicationFrame); + // if (result == JFileChooser.APPROVE_OPTION) { + // final File f = chooser.getSelectedFile(); + // boolean confirm = true; + // if (f.exists()) { + // if (f.isDirectory()) { + // JOptionPane.showMessageDialog(applicationFrame, + // "You can not select an existing directory.", "Error", JOptionPane.ERROR_MESSAGE); + // return; + // } + // confirm = false; + // final int choice = JOptionPane.showConfirmDialog(applicationFrame, + // "File exists, overwrite?", "Confirm", JOptionPane.YES_NO_OPTION); + // if (choice == JOptionPane.YES_OPTION) + // confirm = true; + // } + // + // if (confirm) { + // try { + // swarmConfig.lastPath = f.getParent(); + // final String fn = f.getPath(); + // final SeismicDataFile file = SeismicDataFile.getFile(fn); + // final Wave wave = selected.getWave(); + // file.putWave(selected.getChannel(), wave); + // file.write(); + // } catch (final FileNotFoundException ex) { + // JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Directory does not exist.", + // "Error", JOptionPane.ERROR_MESSAGE); + // } catch (final IOException ex) { + // JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Error writing file.", + // "Error", JOptionPane.ERROR_MESSAGE); + // } + // } + // } + } + } + + private void doSizePopup() { + // if (popup == null) { + // final String[] labels = new String[] {"Auto", null, "Tiny", "Small", "Medium", "Large"}; + // final int[] sizes = new int[] {-1, -1, 50, 100, 160, 230}; + // popup = new JPopupMenu(); + // final ButtonGroup group = new ButtonGroup(); + // for (int i = 0; i < labels.length; i++) { + // if (labels[i] != null) { + // final int size = sizes[i]; + // final JRadioButtonMenuItem mi = new JRadioButtonMenuItem(labels[i]); + // mi.addActionListener(new ActionListener() { + // public void actionPerformed(final ActionEvent e) { + // setWaveHeight(size); + // } + // }); + // if (waveHeight == size) + // mi.setSelected(true); + // group.add(mi); + // popup.add(mi); + // } else + // popup.addSeparator(); + // } + // } + // popup.show(sizeButton.getParent(), sizeButton.getX(), sizeButton.getY()); + } + + public void fetchDetailedEvent() { + final String neicEvid = event.getEventSource() + event.getEvid(); + final Event workingEvent = event; + + String url = "http://earthquake.usgs.gov/fdsnws/event/1/query?eventid=" + neicEvid; + + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = null; + Document doc = null; + + try { + dBuilder = dbFactory.newDocumentBuilder(); + doc = dBuilder.parse(url); + doc.getDocumentElement().normalize(); + + NodeList eventElements = doc.getElementsByTagName("event"); + Element eventElement = (Element) eventElements.item(0); + NodeList descriptionNodes = eventElement.getElementsByTagName("description"); + for (int idx = 0; idx < descriptionNodes.getLength(); idx++) { + eventElement.removeChild(descriptionNodes.item(idx)); + } + workingEvent.updateEvent(eventElement); + } catch (SAXException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } catch (IOException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } catch (ParserConfigurationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + private void populatePicks() { + Origin origin = event.getPreferredOrigin(); + + long firstPick = Long.MAX_VALUE; + long lastPick = Long.MIN_VALUE; + for (Arrival arrival : origin.getArrivals()) { + Pick pick = arrival.getPick(); + firstPick = Math.min(pick.getTime(), firstPick); + lastPick = Math.max(pick.getTime(), lastPick); + } + + double waveStart = J2kSec.fromEpoch(firstPick) - 1; + double waveEnd = J2kSec.fromEpoch(lastPick) + 1; + LOGGER.debug("wave span {} - {}", waveStart, waveEnd); + + pickBox.setStart(waveStart); + pickBox.setEnd(waveEnd); + + throbber.increment(); + for (Arrival arrival : origin.getArrivals()) { + if (closing) { + break; + } + pickBox.addPick(arrival); + mainPanel.validate(); + LOGGER.debug("pickBox {}", pickBox.countComponents()); + } + throbber.decrement(); + } + + @Override + public void paint(final Graphics g) { + super.paint(g); + // if (waves.size() == 0) { + // final Dimension dim = this.getSize(); + // g.setColor(Color.black); + // g.drawString("Picker empty.", dim.width / 2 - 40, dim.height / 2); + // } + } + + @Override + public void setVisible(final boolean isVisible) { + LOGGER.debug("Visible = {}", isVisible); + super.setVisible(isVisible); + if (isVisible) + toFront(); + } + + public void eventUpdated() { + mainPanel.setTopComponent(createParameterPanel()); + mainPanel.setBottomComponent(createPickPanel()); + } + + private void createListeners() { + this.addInternalFrameListener(new InternalFrameAdapter() { + @Override + public void internalFrameActivated(final InternalFrameEvent e) {} + + @Override + public void internalFrameDeiconified(final InternalFrameEvent e) {} + + @Override + public void internalFrameClosing(final InternalFrameEvent e) { + closing = true; + dispose(); + SwarmInternalFrames.remove(EventFrame3.this); + } + + @Override + public void internalFrameClosed(final InternalFrameEvent e) {} + }); + + this.addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(final ComponentEvent e) {} + }); + } + + // private synchronized void createImage() { + // if (getWidth() > 0 && getHeight() > 0) + // image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_4BYTE_ABGR); + // } + +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Magnitude.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Magnitude.java index 23cb31cf..5cf30cb1 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Magnitude.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Magnitude.java @@ -1,8 +1,7 @@ package gov.usgs.volcanoes.swarm.event; -import java.util.Map; - import org.w3c.dom.Element; +import org.w3c.dom.NodeList; public class Magnitude { @@ -10,6 +9,7 @@ public class Magnitude { private double mag; private String type; + private String uncertainty; public Magnitude(Element magnitudeElement) { publicId = magnitudeElement.getAttribute("publicId"); @@ -18,6 +18,10 @@ public Magnitude(Element magnitudeElement) { Element magElement = (Element) magnitudeElement.getElementsByTagName("mag").item(0); mag = Double.parseDouble(magElement.getElementsByTagName("value").item(0).getTextContent()); + + Element uncertaintyElement = (Element) magElement.getElementsByTagName("uncertainty").item(0); + if (uncertaintyElement != null) + uncertainty = "\u00B1" + uncertaintyElement.getTextContent(); } @@ -29,4 +33,7 @@ public String getType() { return type; } + public String getUncertainty() { + return uncertainty; + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Networks.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Networks.java new file mode 100644 index 00000000..7a8aea3a --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Networks.java @@ -0,0 +1,121 @@ +package gov.usgs.volcanoes.swarm.event; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Vector; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Networks { + private final static Logger LOGGER = LoggerFactory.getLogger(Networks.class); + + private final static String NETWORKS_FILE = "networks.csv"; + private final Map networks; + + public String getName(String code) { + return networks.get(code); + } + + private Networks() { + networks = new HashMap(); + FileReader reader = null; + try { + reader = new FileReader(new File(ClassLoader.getSystemResource(NETWORKS_FILE).getFile())); + + try { + List fields = Networks.parseLine(reader); + while (fields != null) { + networks.put(fields.get(0), fields.get(2)); + fields = Networks.parseLine(reader); + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } catch (IOException e) { + LOGGER.info("Unable to read networks", e); + // } catch (URISyntaxException e) { + // // TODO Auto-generated catch block + // LOGGER.debug("DASDSA ", e); + // e.printStackTrace(); + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException ignored) { + } + } + } + + } + + public static Networks getInstance() { + return NetworksHolder.networks; + } + + private static class NetworksHolder { + public static Networks networks = new Networks(); + } + + /** + * Adapted from https://agiletribe.wordpress.com/2012/11/23/the-only-class-you-need-for-csv-files/ + * + * @param r + * @return + * @throws Exception + */ + public static List parseLine(Reader r) throws Exception { + int ch = r.read(); + while (ch == '\r') { + // ignore linefeed chars wherever, particularly just before end of file + ch = r.read(); + } + if (ch < 0) { + return null; + } + Vector store = new Vector(); + StringBuffer curVal = new StringBuffer(); + boolean inquotes = false; + boolean started = false; + while (ch >= 0) { + if (inquotes) { + started = true; + if (ch == '\"') { + inquotes = false; + } else { + curVal.append((char) ch); + } + } else { + if (ch == '\"') { + inquotes = true; + if (started) { + // if this is the second quote in a value, add a quote + // this is for the double quote in the middle of a value + curVal.append('\"'); + } + } else if (ch == ',') { + store.add(curVal.toString()); + curVal = new StringBuffer(); + started = false; + } else if (ch == '\r') { + // ignore LF characters + } else if (ch == '\n') { + // end of a line, break out + break; + } else { + curVal.append((char) ch); + } + } + ch = r.read(); + } + store.add(curVal.toString()); + return store; + } +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java index e21b8fc5..eb8a0a63 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java @@ -1,19 +1,12 @@ package gov.usgs.volcanoes.swarm.event; -import java.text.DateFormat; import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.Iterator; -import java.util.List; import java.util.Map; -import java.util.TimeZone; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.w3c.dom.DOMException; import org.w3c.dom.Element; import org.w3c.dom.NodeList; @@ -21,34 +14,92 @@ public class Origin { private static final Logger LOGGER = LoggerFactory.getLogger(Origin.class); + public static enum EvaluationMode { + AUTOMATIC, MANUAL; + } + + public static enum EvaluationStatus { + PRELIMINARY, CONFIRMED, REVIEWED, FINAL, REJECTED + } + public final String publicId; private double latitude; private double longitude; private double depth; private long time; - + private EvaluationMode evaluationMode; + private EvaluationStatus evaluationStatus; + private double standardError; + private double azimuthalGap; private Map arrivals; + private int phaseCount; + private double minimumDistance; public Origin(Element originElement, Map picks) { this.publicId = originElement.getAttribute("publicId"); arrivals = new HashMap(); - - LOGGER.debug("new origin {}", publicId); + LOGGER.debug("new origin {}", publicId); + Element lonElement = (Element) originElement.getElementsByTagName("longitude").item(0); - longitude = Double.parseDouble(lonElement.getElementsByTagName("value").item(0).getTextContent()); + longitude = + Double.parseDouble(lonElement.getElementsByTagName("value").item(0).getTextContent()); Element latElement = (Element) originElement.getElementsByTagName("latitude").item(0); - latitude = Double.parseDouble(latElement.getElementsByTagName("value").item(0).getTextContent()); + latitude = + Double.parseDouble(latElement.getElementsByTagName("value").item(0).getTextContent()); Element depthElement = (Element) originElement.getElementsByTagName("depth").item(0); depth = Double.parseDouble(depthElement.getElementsByTagName("value").item(0).getTextContent()); - Element timeElement = (Element) originElement.getElementsByTagName("time").item(0); time = 0; - time = QuakeMlUtils.parseTime(timeElement.getElementsByTagName("value").item(0).getTextContent()); - + time = + QuakeMlUtils.parseTime(timeElement.getElementsByTagName("value").item(0).getTextContent()); + + Element evaluationElement = (Element) originElement.getElementsByTagName("evaluationStatus").item(0); + if (evaluationElement != null) { + evaluationStatus = EvaluationStatus.valueOf(evaluationElement.getTextContent().toUpperCase()); + } + + evaluationElement = (Element) originElement.getElementsByTagName("evaluationMode").item(0); + if (evaluationElement != null) { + evaluationMode = EvaluationMode.valueOf(evaluationElement.getTextContent().toUpperCase()); + } + + Element qualityElement = (Element) originElement.getElementsByTagName("quality").item(0); + if (qualityElement != null) { + Element errorElement = (Element) qualityElement.getElementsByTagName("standardError").item(0); + if (errorElement != null) { + standardError = Double.parseDouble(errorElement.getTextContent()); + } else { + standardError = Double.NaN; + } + + Element gapElement = (Element) qualityElement.getElementsByTagName("azimuthalGap").item(0); + if (gapElement != null) { + LOGGER.debug("GAP: {}", gapElement.getTextContent()); + azimuthalGap = Double.parseDouble(gapElement.getTextContent()); + } else { + azimuthalGap = Double.NaN; + } + + Element phaseCountElement = (Element) qualityElement.getElementsByTagName("usedPhaseCount").item(0); + if (gapElement != null) { + phaseCount = Integer.parseInt(phaseCountElement.getTextContent()); + } else { + phaseCount = -1; + } + + Element distanceElement = (Element) qualityElement.getElementsByTagName("minimumDistance").item(0); + if (distanceElement != null) { + minimumDistance = Double.parseDouble(distanceElement.getTextContent()); + } else { + minimumDistance = Double.NaN; + } + + } + parseArrivals(originElement.getElementsByTagName("arrival"), picks); } @@ -79,4 +130,28 @@ public long getTime() { public Collection getArrivals() { return arrivals.values(); } + + public EvaluationStatus getEvaluationStatus() { + return evaluationStatus; + } + + public EvaluationMode getEvaluationMode() { + return evaluationMode; + } + + public double getStandardError() { + return standardError; + } + + public double getAzimuthalGap() { + return azimuthalGap; + } + + public int getPhaseCount() { + return phaseCount; + } + + public double getMinimumDistance() { + return minimumDistance; + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java index f8ddae9f..80f3ca72 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java @@ -1,8 +1,5 @@ package gov.usgs.volcanoes.swarm.event; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; @@ -13,11 +10,15 @@ import java.util.HashMap; import java.util.Map; -import javax.swing.Box; import javax.swing.BoxLayout; +import javax.swing.JLabel; import javax.swing.JPanel; +import javax.swing.JViewport; import javax.swing.Scrollable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import gov.usgs.plot.data.Wave; import gov.usgs.volcanoes.swarm.data.SeismicDataSource; import gov.usgs.volcanoes.swarm.data.fdsnWs.WebServicesSource; @@ -34,10 +35,12 @@ public class PickPanel extends JPanel implements Scrollable { private final Map panels; private double startJ2k; private double endJ2k; + private final JLabel statusLabel; private WaveViewPanelListener selectListener; private final Map seismicSources; - public PickPanel() { + public PickPanel(JLabel statusLabel) { + this.statusLabel = statusLabel; panels = new HashMap(); seismicSources = new HashMap(); @@ -93,8 +96,9 @@ public void addPick(Arrival arrival) { PickWavePanel wavePanel = panels.get(channel); if (wavePanel == null) { wavePanel = new PickWavePanel(); + wavePanel.setStatusLabel(statusLabel); wavePanel.setChannel(channel); - + wavePanel.setViewport(((JViewport)getParent())); SeismicDataSource source = seismicSources.get(channel); if (source == null) { source = new WebServicesSource(); @@ -106,10 +110,12 @@ public void addPick(Arrival arrival) { panels.put(pick.getChannel(), wavePanel); wavePanel.setWave(wave, startJ2k, endJ2k); add(wavePanel); - add(Box.createRigidArea(new Dimension(0, 10))); - wavePanel.setSize(getWidth(), 200); +// add(Box.createRigidArea(new Dimension(0, 10))); +// p.setSize(w, calculateWaveHeight()); + wavePanel.setBottomBorderColor(Color.GRAY); + wavePanel.setSize(getWidth(), 100); wavePanel.setDisplayTitle(true); - wavePanel.setOffsets(60, 0, 5, 15); + wavePanel.setOffsets(54, 8, 21, 19); wavePanel.createImage(); wavePanel.addListener(selectListener); } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java index 8ce0a092..a27c3ba2 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java @@ -1,12 +1,11 @@ package gov.usgs.volcanoes.swarm.event; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; +import java.awt.Graphics; import java.awt.Graphics2D; +import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.awt.geom.Line2D; import java.awt.geom.Rectangle2D; @@ -14,6 +13,12 @@ import java.util.List; import java.util.Stack; +import javax.swing.JScrollPane; +import javax.swing.JViewport; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import gov.usgs.volcanoes.core.time.J2kSec; import gov.usgs.volcanoes.swarm.time.TimeListener; import gov.usgs.volcanoes.swarm.time.WaveViewTime; @@ -30,6 +35,7 @@ public class PickWavePanel extends AbstractWavePanel implements EventObserver { private static final Color RESIDUAL_COLOR = new Color(128, 128, 128, 32); private final List arrivals; private final Stack zoomHistory; +private JViewport viewport; public PickWavePanel() { super(); @@ -122,4 +128,9 @@ protected void processRightMousePress(MouseEvent e) { // TODO Auto-generated method stub } + + public void setViewport(JViewport viewport) { + this.viewport = viewport; + } + } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapSettingsDialog.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapSettingsDialog.java index 63d9b41d..5a0d9085 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapSettingsDialog.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapSettingsDialog.java @@ -136,7 +136,7 @@ protected void createUI() { builder.append(allLabels); builder.nextLine(); - builder.append("Hypocenter Source:"); + builder.append("NEIC Event Summary"); builder.append(hypocenterSource, 3); dialogPanel = builder.getPanel(); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java index d633fa9e..51176aa8 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java @@ -303,19 +303,6 @@ public boolean mouseClicked(final MouseEvent e) { return handled; } - private Event getDetailedEvent(String evid) - throws ParserConfigurationException, SAXException, IOException { - String url = "http://earthquake.usgs.gov/fdsnws/event/1/query?eventid=" + evid; - - DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); - Document doc = dBuilder.parse(url); - doc.getDocumentElement().normalize(); - - NodeList eventElements = doc.getElementsByTagName("event"); - LOGGER.debug("Got {} events.", eventElements.getLength()); - return new Event((Element) eventElements.item(0)); - } public void settingsChanged() { LOGGER.debug("hypocenter plotter sees changed settings."); @@ -334,6 +321,9 @@ public boolean mouseMoved(MouseEvent e) { GeoRange range = panel.getRange(); Projection projection = panel.getProjection(); + if (projection == null) { + return false; + } int widthPx = panel.getGraphWidth(); int heightPx = panel.getGraphHeight(); int insetPx = panel.getInset(); @@ -343,6 +333,9 @@ public boolean mouseMoved(MouseEvent e) { while (it.hasNext() && handled == false) { Event event = it.next(); Origin origin = event.getPreferredOrigin(); + if (origin == null) { + continue; + } final Rectangle r = new Rectangle(0, 0, 10, 10); final Point2D.Double xy = diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java index 751aa216..3e9ffad9 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java @@ -7,10 +7,14 @@ import java.awt.Component; import java.awt.Font; import java.awt.FontMetrics; +import java.awt.Graphics; import java.awt.Graphics2D; +import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.awt.geom.Line2D; +import javax.swing.JScrollPane; + import gov.usgs.volcanoes.core.time.J2kSec; import gov.usgs.volcanoes.swarm.event.EventObserver; import gov.usgs.volcanoes.swarm.picker.Phase.PhaseType; @@ -106,43 +110,59 @@ private void markPhase(Graphics2D g2, Color backgroundColor, long time, String t g2.drawString(tag, (int) x + offset, 3 + (fm.getAscent() + offset)); g2.setFont(oldFont); } - - private void markPhase(Graphics2D g2, Phase phase) { - double j2k = J2kSec.fromEpoch(phase.time); - double[] t = getTranslation(); - if (t == null) + + /** + * Paints the component on the specified graphics context. + * + * @param g the graphics context + */ + public void paint(Graphics g) { + + Rectangle rect = ((JScrollPane)getParent()).getVisibleRect(); + if (!rect.intersects(getBounds())) { return; - - double x = 2 + (j2k - t[1]) / t[0]; - g2.setColor(DARK_GREEN); - g2.draw(new Line2D.Double(x, yOffset, x, getHeight() - bottomHeight - 1)); - - String tag = phase.tag(); - Font oldFont = g2.getFont(); - g2.setFont(ANNOTATION_FONT); - - FontMetrics fm = g2.getFontMetrics(); - int width = fm.stringWidth(tag); - int height = fm.getAscent(); - - int offset = 2; - int lw = width + 2 * offset; - - Color background = null; - if (phase.phaseType == Phase.PhaseType.P) { - background = P_BACKGROUND; - } else if (phase.phaseType == Phase.PhaseType.S) { - background = S_BACKGROUND; } - g2.setColor(background); - - g2.fillRect((int) x, 3, lw, height + 2 * offset); - g2.setColor(Color.black); - g2.drawRect((int) x, 3, lw, height + 2 * offset); - - g2.drawString(tag, (int) x + offset, 3 + (fm.getAscent() + offset)); - g2.setFont(oldFont); - } + + super.paint(g); + } + + +// private void markPhase(Graphics2D g2, Phase phase) { +// double j2k = J2kSec.fromEpoch(phase.time); +// double[] t = getTranslation(); +// if (t == null) +// return; +// +// double x = 2 + (j2k - t[1]) / t[0]; +// g2.setColor(DARK_GREEN); +// g2.draw(new Line2D.Double(x, yOffset, x, getHeight() - bottomHeight - 1)); +// +// String tag = phase.tag(); +// Font oldFont = g2.getFont(); +// g2.setFont(ANNOTATION_FONT); +// +// FontMetrics fm = g2.getFontMetrics(); +// int width = fm.stringWidth(tag); +// int height = fm.getAscent(); +// +// int offset = 2; +// int lw = width + 2 * offset; +// +// Color background = null; +// if (phase.phaseType == Phase.PhaseType.P) { +// background = P_BACKGROUND; +// } else if (phase.phaseType == Phase.PhaseType.S) { +// background = S_BACKGROUND; +// } +// g2.setColor(background); +// +// g2.fillRect((int) x, 3, lw, height + 2 * offset); +// g2.setColor(Color.black); +// g2.drawRect((int) x, 3, lw, height + 2 * offset); +// +// g2.drawString(tag, (int) x + offset, 3 + (fm.getAscent() + offset)); +// g2.setFont(oldFont); +// } @Override protected void processRightMouseRelease(MouseEvent e) { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java b/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java index 384fa47c..ae3ce11b 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java @@ -2,9 +2,6 @@ -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; @@ -12,6 +9,7 @@ import java.awt.Graphics2D; import java.awt.Image; import java.awt.Paint; +import java.awt.Rectangle; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; @@ -22,9 +20,13 @@ import javax.swing.JComponent; import javax.swing.JLabel; +import javax.swing.JScrollPane; import javax.swing.SwingUtilities; import javax.swing.event.EventListenerList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import gov.usgs.math.Filter; import gov.usgs.plot.Plot; import gov.usgs.plot.PlotException; @@ -167,7 +169,7 @@ public AbstractWavePanel(AbstractWavePanel p) { translation = new double[8]; if (p.translation != null) System.arraycopy(p.translation, 0, translation, 0, 8); - + settings = new WaveViewSettings(p.settings); settings.view = this; @@ -569,7 +571,7 @@ public boolean processMousePosition(int x, int y) { else status = pre; } - + if (status != null && statusLabel != null) { final String st = status; SwingUtilities.invokeLater(new Runnable() { @@ -714,6 +716,7 @@ private void filter(Wave w) { * @param g the graphics context */ public void paint(Graphics g) { + Graphics2D g2 = (Graphics2D) g; Dimension dim = this.getSize(); if (wave == null) { diff --git a/src/main/resources/networks.csv b/src/main/resources/networks.csv new file mode 100644 index 00000000..637995fd --- /dev/null +++ b/src/main/resources/networks.csv @@ -0,0 +1,1212 @@ +# Network Code,Network Name,Network Operator,Network Country (ISO & Name),Network Website,Deployment Country (if different),Digital Object Identifier (DOI) +1A,NCISP6,"Institute of Geology and Geophysics, CAS",CN (China),http://english.igg.cas.cn,China,doi:10.7914/SN/1A_2007 +1A,Arlita,Institut des Sciences de la Terre,FR (France),,France, +1A,Waste Isolation Pilot Plant Noise Analysis,"New Mexico Tech (NMT Mining & Technology NM,USA)",US (United States),,United States,doi:10.7914/SN/1A_2013 +1A,"Mining-induced seismicity network at mine Prosper-Haniel, Bottrop",Ruhr Universitaet Bochum (RUB Germany),DE (Germany),,Germany,doi:10.7914/SN/1A_2014 +1B,UGANDA,University of Frankfurt,DE (Germany),,Germany, +1B,Gulf of Alaska Active Source Experiment,Woods Hole Oceanographic Institution (WHOI),US (United States),,United States, +1B,Assured Arctic Awareness,University of Washington,US (United States),,United States,doi:10.7914/SN/1B_2013 +1B,Sweetwater Array,IRIS HQ (DC),US (United States),,United States, +1C,Urban Seismology 2,Karlsruhe Institute of Technology (KIT GIP Germany),DE (Germany),,Germany, +1C,"Seismic Characterization of Menengai Crater, Kenya",University of Texas at El Paso (UTEP),US (United States),,United States,doi:10.7914/SN/1C_2011 +1C,Antithesis 2,Geoazur,FR (France),,France, +1D,Elevation change anomalies in West Antarctica and dynamics of subglacial water beneath ice streams and their tributaries,UC Santa Cruz,US (United States),,United States,doi:10.7914/SN/1D_2010 +1D,MSH Node Array,University of New Mexico (UNM),US (United States),,United States,doi:10.7914/SN/1D_2014 +1D,UKANET: UK Antarctic Network,University of Leeds (UK),GB (United Kingdom),,United Kingdom,doi:10.7914/SN/1D_2016 +1E,ELLITE,University of Aberdeen (UK),GB (United Kingdom),,United Kingdom, +1E,Crustal Magma Plumbing of the Santorini Volcanic System - OBS Component,University of Oregon,US (United States),,United States,doi:10.7914/SN/1E_2015 +1F,"Workshops on Volcanoes 2016, Santiaguito, Guatemala","University of Alaska, Fairbanks (UAF, AK USA)",US (United States),,United States,doi:10.7914/SN/1F_2015 +1G,ScanArray core,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +2A,"Gravity Lineations, Intraplate Melting, Petrologic and Seismic Expedition",Brown University,US (United States),,United States, +2A,"COGEAR Temporary Deployments, Valais, Switzerland",Swiss Seismological Service,CH (Switzerland),,Switzerland, +2B,"PUDEL Network, Argentina, 2007-2009","GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +2B,OBSIP: Bering Sea Active Source Experiment,Woods Hole Oceanographic Institution (WHOI),US (United States),,United States, +2B,East_Staithes,Durham University,GB (United Kingdom),,United Kingdom, +2C,Geophysical Study of Ice Stream Stick-slip dynamics,Central Washington University,US (United States),,United States,doi:10.7914/SN/2C_2010 +2C,CoLiBrEA,University Montpellier II (UM2 UMSF France),FR (France),,Tanzania,doi:10.7914/SN/2C_2014 +2D,Albacore,UC San Diego,US (United States),,United States, +2D,N2,University of Bergen (UiB Norway) Inst of Geophysics,NO (Norway),,Norway, +2E,"Seismic Coherence and Site Effect Studies at Precarious Rock Locations in Riverside, California","USGS Caltech, Pasadena",US (United States),,United States,doi:10.7914/SN/2E_2010 +2E,Norway Microbarom Study 2014,"Los Alamos National Laboratory (LANL, NM)",US (United States),,United States,doi:10.7914/SN/2E_2014 +2F,OMBRA seismic network,Istituto Nazionale di Geofisica e Vulcanologia (INGV),IT (Italy),http://ombra.bo.ingv.it,Italy, +2F,LONGMEN,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany,10.14470/7S7567431325 +2F,PFO Accelerometer Test,IGPP University of California Systemwide Institute of Geophysics and Planetary Physics,US (United States),,United States, +2G,Testing of the effectiveness of incorporating seismic data in seismic hazard assessment within a traditional field course,Indiana University Bloomington (IU Bloomington),US (United States),,United States,doi:10.7914/SN/2G_2010 +3A,ARC-Vanuatu,"Observatoire de Grenoble, Grenoble",FR (France),,France, +3A,Maule Aftershock Deployment (UK),University of Liverpool,GB (United Kingdom),,United Kingdom, +3A,The celerity of microbaroms,"Los Alamos National Laboratory (LANL, NM)",US (United States),,United States,doi:10.7914/SN/3A_2013 +3B,Desert Peak EGS,"Lawrence Berkeley Laboratory (LBNL, CA USA)",US (United States),,United States, +3B,"Integrated Geosciences in the Merida Andes, Venezuela","Fundación Venezolana de Investigaciones Sismológicas (FUNVISIS), Caracas",VE (Venezuela),,Venezuela, +3C,Collaborative Proposal: Glacier seismicity and its relationship to basal motion,Central Washington University,US (United States),,United States,doi:10.7914/SN/3C_2010 +3C,Arizona Rapid Array Array Mobilization Program,Arizona Geological Survey,US (United States),,United States,doi:10.7914/SN/3C_2014 +3D,Morocco-Muenster,Munster University (WWU-Germany) Westfalische Wilhelms-Universitat Munster,DE (Germany),,Germany, +3D,HART Pisagua Earthquake,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +3E,Exploring Seismic Velocity of Sediments in the Mississippi Embayment,"University of Memphis, CERI",US (United States),,United States,doi:10.7914/SN/3E_2010 +3E,Crustal Magma Plumbing of the Santorini Volcanic System - Land Component,University of Oregon,US (United States),,United States,doi:10.7914/SN/3E_2015 +3F,USGS flume seismic monitoring,USGS Vancouver WA,US (United States),,United States,doi:10.7914/SN/3F_2010 +3F,HUMMING WOMBAT,Weston Geophysical Corp,US (United States),,United States,doi:10.7914/SN/3F_2013 +3G,TÜBITAK Marmara Research Center Earth Sciences Institution Network,TÜBITAK Marmara Research Center,TR (Turkey),,Turkey,doi:10.7914/SN/3G_2007 +4A,Investigating mechanisms of subglacial hydrology and basal shear stress beneath Whillans Ice Stream using passive seismology,UC Santa Cruz,US (United States),,United States,doi:10.7914/SN/4A_2008 +4A,"Darfield RAMP Aftershock Deployment, NZ","University of Wisconsin, Madison",US (United States),,United States,doi:10.7914/SN/4A_2010 +4A,Pollino Seismic Experiment,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +4B,TASK FORCE KIRGISTAN,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +4B,Raft River EGS,"Lawrence Berkeley Laboratory (LBNL, CA USA)",US (United States),,United States, +4C,Semipalatinsk Test Site Network,Inst. of Geophysical Research National Nuclear Center of Republic of Kazakhstan,KZ (Kazakhstan),,Kazakhstan, +4C,NERA-JRA1-A,"Observatoire de Grenoble, Grenoble",FR (France),,France, +4C,GeoGirls outreach experiment at Mount St. Helens,USGS Vancouver WA,US (United States),,United States, +4D,Seismological Experiments on Swiss Glaciers,Swiss Seismological Service,CH (Switzerland),,Switzerland, +4D,Parkfield Experiment to Record Microseismicity and Tremor,Karlsruhe Institute of Technology (KIT GIP Germany),DE (Germany),,Germany, +4D,Seismological Experiments on Swiss Glaciers,Swiss Seismological Service,CH (Switzerland),,Switzerland, +4E,MARS/Testing of cabled broadband OBS using MARS test facility,UC San Diego,US (United States),,United States, +4E,Field Research Station broadband seismometer network,University of Bristol (UK),GB (United Kingdom),,United Kingdom,doi:10.7914/SN/4E_2015 +4F,Askja 2007,University of Cambridge (UK) Earth Sciences,GB (United Kingdom),,United Kingdom, +4F,North Texas Earthquake Study,Southern Methodist University (SMU TX),US (United States),,United States,doi:10.7914/SN/4F_2015 +5A,Samoa Lithosphere Integrated Seismic-Petrologic Expedition,Woods Hole Oceanographic Institution (WHOI),US (United States),,United States,doi:10.7914/SN/5A_2005 +5A,Crustal-Scale Geometry of Active Continental Normal Faults,Oregon State University (OSU USA),US (United States),,United States,doi:10.7914/SN/5A_2010 +5A,Eastern North American Margin Explosives Test,University of Texas at El Paso (UTEP),US (United States),,United States,doi:10.7914/SN/5A_2013 +5A,Subduction Reversal and the Ontong Java Plateau,University of Southampton (UK),GB (United Kingdom),,United Kingdom, +5B,TaskForce L Aquila 2009,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +5B,Brady Hot Spring EGS,"Lawrence Berkeley Laboratory (LBNL, CA USA)",US (United States),,United States, +5C,"Dynamics of Lake-Calving Glaciers: Yakutat Glacier, Alaska","University of Alaska, Fairbanks (UAF, AK USA)",US (United States),,United States,doi:10.7914/SN/5C_2009 +5C,TIPTIMON TAJIKISTAN,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +5D,LuxBB,Karlsruhe Institute of Technology (KIT GIP Germany),DE (Germany),,Germany, +5E,MINAS,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany,doi:10.14470/ab466166 +5F,"Magnetotelluric and seismic investigation of arc melt generation, delivery, and storage beneath Okmok Volcano","University of Wisconsin, Madison",US (United States),,United States,doi:10.7914/SN/5F_2015 +6A,Rohrbach/Vogtland seismic array 2008,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +6A,Walvis Ridge Passive Source Seismic Experiment,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +6A,Seismic Array iNegrated Detection for a Window of Indian Continental Head,"Institute of Geology and Geophysics, CAS",CN (China),,China,doi:10.7914/SN/6A_2013 +6B,North China seismic Array,Institute of Geophysics China Earthquake Administration (IGPCEA),CN (China),http://www.chinarraydmc.org/,China,doi:10.7914/SN/6B_2006 +6B,New York Canyon EGS,"Lawrence Berkeley Laboratory (LBNL, CA USA)",US (United States),,United States, +6C,Ferghana,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +6C,Seismic Cluster Investigation in the Southern Rio Grande Rift,University of Texas at El Paso (UTEP),US (United States),,United States,doi:10.7914/SN/6C_2011 +6C,TIPTIMON AFGHANISTAN,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +6D,Telica Seismic and Deformation Network,Carnegie Institute of Washington / Science (DTM CIW),US (United States),,United States, +6E,Nisyros network,Ruhr Universitaet Bochum (RUB Germany),DE (Germany),,Germany, +6E,Wabash Valley Seismic Zone,Southern Illinois University Carbondale (SIUC),US (United States),,United States,doi:10.7914/SN/6E_2013 +6F,"WIsconsin, new Zealand, And Rpi Deployment, Deep Fault Drilling Project","University of Wisconsin, Madison",US (United States),,United States,doi:10.7914/SN/6F_2012 +7A,BTL,"Australian National University (ANU, Australia)",AU (Australia),,Australia, +7A,Lake Toba,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +7A,Cascadia- Keck,Woods Hole Oceanographic Institution (WHOI),US (United States),,United States, +7A,Mid-Atlantic Geophysical Integrative Collaboration,Yale University,US (United States),,United States,doi:10.7914/SN/7A_2013 +7B,SKIPPY,"Australian National University (ANU, Australia)",AU (Australia),,Australia, +7B,TIPAGE,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +7B,Dixie Valley EGS,"Lawrence Berkeley Laboratory (LBNL, CA USA)",US (United States),,United States, +7C,YE,"Australian National University (ANU, Australia)",AU (Australia),,Australia, +7C,DORA,Institut des Sciences de la Terre,FR (France),,France, +7C,The Mackenzie Mountains Transect: Active Deformation from Margin to Craton,Colorado State University (CSU),US (United States),,United States,doi:10.7914/SN/7C_2015 +7D,KIMBA97,"Australian National University (ANU, Australia)",AU (Australia),,Australia, +7D,Yakima Landslide RAMP,"University of Memphis, CERI",US (United States),,United States,doi:10.7914/SN/7D_2009 +7D,Cascadia Initiative Community Experiment - OBS Component,IRIS HQ (DC),US (United States),,United States,doi:10.7914/SN/7D_2011 +7E,KIMBA98,"Australian National University (ANU, Australia)",AU (Australia),,Australia, +7E,PASSEQ,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany,10.14470/2R383989 +7E,Glacioseismic Monitoring of Rumblings in Jakobshavn Glacier,University of North Carolina at Chapel Hill (UNC),US (United States),,United States,doi:10.7914/SN/7E_2010 +7E,Reykjanet,"Institute of Geophysics, Academy of Sciences of the Czech Republic",CZ (Czech Republic),http://www.ig.cas.cz/en/reykjanet,Czech Republic,doi:10.7914/SN/7E_2013 +7F,QUOLL,"Australian National University (ANU, Australia)",AU (Australia),,Australia, +7F,Central Arkansas Induced Eathquakes 2010-2011,"University of Memphis, CERI",US (United States),,United States, +7F,Casey - Davis region,University of Tasmania,AU (Australia),,Australia, +7G,WA-CRATON,Auburn University,US (United States),,United States, +7G,"Youngstown, Ohio, induced earthquakes","Lamont Doherty Earth Observatory (LDEO), Columbia University",US (United States),,United States, +7H,TIGGER,"Australian National University (ANU, Australia)",AU (Australia),,Australia, +7H,"W-Alps landslide experiments Char d Osset, Chamousset, Pont Bourquin",Institut des Sciences de la Terre,FR (France),,France, +7I,TASMAL,"Australian National University (ANU, Australia)",AU (Australia),,Australia, +7I,Test data of Insight Seismomoter,Institut de Physique du Globe de Paris,FR (France),,France, +7J,CAPRAL,"Australian National University (ANU, Australia)",AU (Australia),,Australia, +7J,"Correlating seismic and visual (TLS) signals at Breidamerkurjokull, Iceland",University of South Florida (USF),US (United States),,United States,doi:10.7914/SN/7J_2011 +7K,SOC,"Australian National University (ANU, Australia)",AU (Australia),,Australia, +7M,LF98,"Australian National University (ANU, Australia)",AU (Australia),,Australia, +7N,MB99,"Australian National University (ANU, Australia)",AU (Australia),,Australia, +7O,AFOO,"Australian National University (ANU, Australia)",AU (Australia),,Australia, +7P,TIGGER-SP,"Australian National University (ANU, Australia)",AU (Australia),,Australia, +7Q,SEAL,"Australian National University (ANU, Australia)",AU (Australia),,Australia, +7R,EVA,"Australian National University (ANU, Australia)",AU (Australia),,Australia, +7S,SETA,"Australian National University (ANU, Australia)",AU (Australia),,Australia, +7T,SEAL2,"Australian National University (ANU, Australia)",AU (Australia),,Australia, +7U,SEAL3,"Australian National University (ANU, Australia)",AU (Australia),,Australia, +8A,IPY: Stability of Larsen C Ice Shelf in a Warming Climate,IRIS PASSCAL Instrument Center @ New Mexico Tech,US (United States),,United States,doi:10.7914/SN/8A_2008 +8A,West Iberia Lithosphere and Astenosphere Structure,Instituto Dom Luiz (FCUL formerly CGUL-LX Portugal),PT (Portugal),,Portugal, +8A,AfricaArray - Namibia,Penn State University,US (United States),,United States, +8B,NCISP7,"Institute of Geology and Geophysics, CAS",CN (China),http://english.igg.cas.cn,China,doi:10.7914/SN/8B_2008 +8B,Newberry EGS,"Lawrence Berkeley Laboratory (LBNL, CA USA)",US (United States),,United States, +8C,Lucky Strike OBS Network,,,,, +8D,Swiss Seismological Service Aftershock Deployments,Swiss Seismological Service,CH (Switzerland),,Switzerland, +8E,Mammoth Mountain Broadband Experiment,USGS Menlo Park,US (United States),,United States, +8F,Hikurangi Ocean Bottom Investigation of Tremor and Slow Slip,University of Texas at Austin,US (United States),,United States,doi:10.7914/SN/8F_2015 +9A,COBO,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +9A,Loihi Seismicity,Woods Hole Oceanographic Institution (WHOI),US (United States),,United States, +9A,East Texas Earthquake Monitoring,Weston Geophysical Corp,US (United States),,United States,doi:10.7914/SN/9A_2013 +9A,Makushin Volcano Plumbing,"University of Wisconsin, Madison",US (United States),,United States,doi:10.7914/SN/9A_2015 +9B,Volcano Seismology and Digital Signal Processing Short Course (GEOP539),"New Mexico Tech (NMT Mining & Technology NM,USA)",US (United States),,United States,doi:10.7914/SN/9B_2008 +9B,"Volcano Geophysical Field Methods Course at Kilauea Volcano, Hawaii","New Mexico Tech (NMT Mining & Technology NM,USA)",US (United States),,United States,doi:10.7914/SN/9B_2010 +9B,Tomographic Imaging of Silali and Paka Volcanoes,University of Texas at El Paso (UTEP),US (United States),,United States, +9B,"Cape Verde, Fogo Temporary Seismic Network ","Instituto Português do Mar e da Atmosfera, I.P.",PT (Portugal),,Portugal, +9C,High Resolution Seismological Profiling across Sierra Nevad,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +9C,Aleutian Array of Arrays,UC Riverside,US (United States),,United States,doi:10.7914/SN/9C_2014 +9D,Ice-ocean interaction at Nuuk tidewater glaciers,"University of Alaska, Fairbanks (UAF, AK USA)",US (United States),,United States,doi:10.7914/SN/9D_2010 +9D,Seismic Array of the Sevilleta,,,,,doi:10.7914/SN/9D_2015 +9E,"Short term noise tests / structural / foundation monitoring at SED, ETHZ",Swiss Seismological Service,CH (Switzerland),,Switzerland, +9F,Southern Alps microearthquake Borehole Array- part 2,Victoria University of Wellington (VUW New Zealand),NZ (New Zealand),,New Zealand,doi:10.7914/SN/9F_2008 +A,Generic Asian Strong Motion Network,INGV Instituto Nazionale di Geofisica e Vulcanologia (Italy),IT (Italy),,Asia, +A1,Southern African Co-located Academic Network,Pangaea Geophyics and Geodesy Working Group,ZA (South Africa),,South Africa, +AA,Anchorage Strong Motion Network,"University of Alaska, Fairbanks (UAF, AK USA)",US (United States),,United States, +AB,National Seismic Network of Azerbaijan,Republic Center of Seismic Survey/Acad. of Sciences of Azerbaijan,AZ (Azerbaijan),,Azerbaijan, +AC,Albanian Seismological Network,"Institute of Geosciences, Polytechnic Univ. of Tirana",AL (Albania),,Albania, +AD,ACROSS Strong Motion Network,Central Asian Institute for Applied Geosciences,KG (Kyrgyzstan),,Kyrgyzstan, +AE,Arizona Broadband Seismic Network,Arizona Geological Survey,US (United States),,United States,doi:10.7914/SN/AE +AF,Africa Array,Penn State University,US (United States),http://www.africaarray.psu.edu/,United States, +AG,Arkansas Seismic Network,Arkansas Geological Survey (AGS),US (United States),,United States, +AH,Arkhangelsk Seismic Network,Institute of Environmental Problems of the North UB RAS,RU (Russian Federation),,Russian Federation, +AI,Antarctic Seismographic Argentinean Italian Network,Istituto Nazionale di Oceanografia e di Geofisica Sperimentale,IT (Italy),http://www.crs.inogs.it/asain/,Antarctica,doi:10.7914/SN/AI +AK,Alaska Regional Network,"Alaska Earthquake Center, Univ. of Alaska Fairbanks",US (United States),http://earthquake.alaska.edu,United States,doi:10.7914/SN/AK +AL,Alaskan Long Period Array,"University of Alaska, Fairbanks (UAF, AK USA)",US (United States),,United States, +AM,Public Seismic Network,Other, (),http://psn.quake.net/,, +AN,Altay-Sayan Regional Seismic Network,Geophysical Survey Siberian Branch Russian Academy of Sciences (GS SB RAS),RU (Russian Federation),,Russian Federation, +AO,Arkansas Seismic Observatory,University of Arkansas at Little Rock (UALR),US (United States),,United States, +AQ,Central Queensland Seismic Network,Central Queensland Seismology Research Group,AU (Australia),,Australia,doi:10.7914/SN/AQ +AR,Northern Arizona Network,Northern Arizona University (NAU AEIC Arizona),US (United States),,United States, +AS,Modified High Gain Long Period Observatory,Albuquerque Seismological Laboratory (ASL)/USGS,US (United States),,Global,doi:10.7914/SN/AS +AT,National Tsunami Warning Center Alaska Seismic Network,NOAA National Oceanic and Atmospheric Administration (USA),US (United States),http://ntwc.arh.noaa.gov/,Alaska,doi:10.7914/SN/AT +AU,Australian National Seismograph Network,Geoscience Australia,AU (Australia),,Australia, +AV,Alaska Volcano Observatory,USGS Alaska Fairbanks,US (United States),http://www.avo.alaska.edu/,United States, +AW,AWI Network Antarctica,Alfred Wegener Institute for Polar and Marine Research,DE (Germany),,Antarctica, +AX,Meteo Aruba,Departamento Meterologico Aruba,AW (Aruba),http://www.meteo.aw/,Aruba, +AY,Haitian Seismic Network,Bureau of Mines and Energy (Haiti),HT (Haiti),,Haiti, +AZ,ANZA Regional Network,UC San Diego,US (United States),http://eqinfo.ucsd.edu/,United States, +BA,UniBAS,Universita della Basilicata,IT (Italy),,Italy, +BB,Brunei Darussalam National Seismic Network,National Seismic Center of Brunei,BN (Brunei),,Brunei, +BC,Red Sismica del Noroeste de Mexico,"Centro de Investigación Científica y de Educación Superior de Ensenada (CICESE), Ensenada",MX (Mexico),,Mexico, +BD,Bakun Dam Micro-Seismic Monitoring Network,Kinemetrics,US (United States),,United States, +BE,Belgian Seismic Network,Royal Observatory of Belgium,BE (Belgium),http://www.seismology.be,Belgium,doi:10.7914/SN/BE +BF,Black Forest Observatory,Universities of Karlsruhe and Stuttgart,DE (Germany),,Germany, +BG,Berkeley Geysers Network,UC Berkeley,US (United States),,United States, +BH,Bay Area Urban Hazards,USGS Golden Colorado,US (United States),,United States, +BI,University of Dhaka Seismographic Network,University of Dhaka,BD (Bangladesh),,Bangladesh, +BK,Berkeley Digital Seismograph Network,UC Berkeley,US (United States),http://seismo.berkeley.edu/bdsn/,United States,doi:10.7932/BDSN +BL,Brazilian Lithospheric Seismic Project,"Universidade de Sao Paulo, USP",BR (Brazil),,Brazil, +BN,"UK-Net, Blacknest Array",Blacknest (AWE UK),GB (United Kingdom),,United Kingdom, +BO,Bosai-Ken Network,National Research Institute for Earth Science and Disaster Prevention (NEID JAPAN),JP (Japan),http://www.bosai.go.jp/,Japan, +BP,Berkeley Parkfield High Resolution Seismic Network,UC Berkeley,US (United States),http://seismo.berkeley.edu/bdsn/hrsn_overview.html,United States,doi:10.7932/HRSN +BR,University of Brasilia Seismic Network,University of Brasilia,BR (Brazil),,Brazil, +BS,National Seismic Network of Bulgaria,Bulgarian Academy of Sciences Geophysical Institute (GPhl Bulgaria),BG (Bulgaria),,Bulgaria, +BT,Red Sismológica de la Sabana de Bogotá,Universidad Nacional de Colombia (UN-Colombia),CO (Colombia),,Colombia, +BU,Boise State University Seismic Network,Boise State University,US (United States),,United States, +BW,BayernNetz,"Department of Earth and Environmental Sciences, Geophysical Observatory, University of Munchen",DE (Germany),,Germany, +BX,Botswana Seismological Network,Department of Geological Survey of Botswana,BW (Botswana),,Botswana, +BY,Baikal Digital Seismograph Network,Baikal Regional Seismological Center,RU (Russian Federation),,Russian Federation, +C,Chilean National Seismic Network,"Universidad de Chile, Dept de Geofisica (DGF UChile Chile)",CL (Chile),,Chile, +C1,Red Sismologica Nacional,"Universidad de Chile, Dept de Geofisica (DGF UChile Chile)",CL (Chile),http://www.sismologia.cl/,Chile, +CA,Catalan Seismic Network,Institut Cartogràfic i Geològic de Catalunya-Institut d'Estudis Catalans,ES (Spain),http://www.icgc.cat/xarxasismica,Spain,doi:10.7914/SN/CA +CB,"Data Management Centre of China National Seismic Network at Institute of Geophysics, CEA",Institute of Geophysics China Earthquake Administration (IGPCEA),CN (China),http://www.seisdmc.ac.cn,China,doi:10.7914/SN/CB +CC,Cascade Chain Volcano Monitoring,Cascades Volcano Observatory/USGS,US (United States),,United States, +CD,China Digital Seismograph Network,"China Seismological Bureau, Institute of Geophysics, Beijing",CN (China),,China,doi:10.7914/SN/CD +CE,California Strong Motion Instrumentation Program,California Division of Mines and Geology (CDMG),US (United States),,United States, +CF,Red Acelerografica Nacional de la Comision Federal de Electricidad (CFE),Comision Federal de Electricidad (CFE),MX (Mexico),,Mexico, +CG,Coso Microearthquake Network,Geothermal Program Office/US Navy,US (United States),,United States, +CH,Switzerland Seismological Network,Swiss Seismological Service,CH (Switzerland),,Switzerland, +CI,Southern California Seismic Network,California Institute of Technology (Caltech),US (United States),http://www.scsn.org/,United States,doi:10.7914/SN/CI +CJ,Community Seismic Network,California Institute of Technology (Caltech),US (United States),http://csn.caltech.edu/,United States, +CK,CAREMON Central Asian Cross-border network,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Central Asia, +CL,Corinth Riff Laboratory,"Sismos a l'Ecole, Geosciences Azur",FR (France),,France, +CM,Red Sismologica Nacional de Colombia,INGEOMINAS - Servicio Geologico Colombiano (SGC Colombia),CO (Colombia),,Colombia, +CN,Canadian National Seismic Network,Geological Survey of Canada,CA (Canada),http://www.earthquakescanada.nrcan.gc.ca/stndon/CNSN-RNSC/,Canada, +CO,South Carolina Seismic Network,University of South Carolina,US (United States),http://www.seis.sc.edu/projects/SCSN/,United States,doi:10.7914/SN/CO +CP,CIVISA Seismo-Volcanic Monitoring Network-Azores Islands,University of Azores,PT (Portugal),,Portugal, +CQ,Cyprus Broadband Seismological Network,Geological Survey Department Cyprus,CY (Cyprus),,Cyprus, +CR,Croatian Seismograph Network,University of Zagreb,HR (Croatia),,Croatia, +CS,Caucusus Array,"Lamont Doherty Earth Observatory (LDEO), Columbia University",US (United States),,Russian Federation, +CT,California Transect Network,UC Santa Cruz,US (United States),,United States, +CU,Caribbean Network,USGS National Earthquake Information Center (NEIC),US (United States),,Caribbean region, +CV,"Vigil Network, Cape Verde Islands","Instituto Superior Tecnico (IST Universidade Tecnica de Lisboa, Portugal)",PT (Portugal),,Portugal, +CW,Servicio Sismologico Nacional de Cuba (SSNC),National Centre for Seismological Research (CENAIS Cuba),CU (Cuba),,Cuba, +CX,Plate Boundary Observatory Network Northern Chile,GFZ / IGPP / CSN / UdC / UCNA,M7 (Multiple Countries),http://www.ipoc-network.org/index.php/data/cx-net.html,Multiple Countries,10.14470/PK615318 +CY,Cayman Islands,Cayman Islands Government,KY (Cayman Islands),,Cayman Islands, +CZ,Czech Regional Seismic Network,"Institute of Geophysics, Academy of Sciences of the Czech Republic",CZ (Czech Republic),http://www.ig.cas.cz/en/structure/observatories/czech-regional-seismological-network,Czech Republic,doi:10.7914/SN/CZ +D0,Kamchatka Network of Seismic Stations,Geophysical Survey Kamchatkan EMSD (KEMSD GS RAS - Russia),RU (Russian Federation),,Russian Federation, +DE,Nanometrics Research Network,Nanometrics Seismological Instruments,CA (Canada),,Global, +DH,DOHAD,Research Association on Planateral Acitivities of Nature (DOHAD),TR (Turkey),,Turkey, +DK,Danish Seismological Network,National Survey and Cadastre,DK (Denmark),,Denmark, +DM,Public Seismic Network - Dominica,,,http://dpsninc.org/,Dominica, +DN,Dubai Seismological Network,Dubai Municipality,AE (United Arab Emirates),http://www.seismo.geodesy.ae/,United Arab Emirates, +DO,Dense Oceanfloor Network System for Earthquakes & Tsunamis,Japan Marine Science and Technology Center (JAMSTEC),JP (Japan),http://www.jamstec.go.jp/donet,Japan, +DR,Dominican Republic Seismic Network,Universidad Autonoma de Santo Domingo (ISU/UASD Dominican Republic),DO (Dominican Republic),,Dominican Republic, +DW,Digital World-Wide Standardized Seismograph Network,Albuquerque Seismological Laboratory (ASL)/USGS,US (United States),,Global,doi:10.7914/SN/DW +DZ,REALSAS,"CRAAG (Research Center of Astronomy, Astrophysics & Geophysics) Algeria",DZ (Algeria),,Algeria, +E,Rete ENEA,Agenzia Nazionale per le Nuove Technolgie (ENEA),IT (Italy),,Italy, +EA,IRIS Education and Research Network,IRIS HQ (DC),US (United States),,United States, +EB,Ebre Observatory Regional Seismic Network,"Observatori de l'Ebre, Tarragona",ES (Spain),,Spain, +EC,Ecuador Seismic Network,Instituto Geofisico Escuela Politecnica Nacional (IG-EPN Ecuador),EC (Ecuador),,Ecuador, +ED,French Educational Seismological Network,"Sismos a l'Ecole, Geosciences Azur",FR (France),,France, +EE,Estonian Seismic Network,Geological Survey of Estonia (GSE),EE (Estonia),,Estonia, +EG,EUROSEISTEST Strong Motion Network,Aristotle University of Thessaloniki,GR (Greece),http://euroseisdb.civil.auth.gr/,Greece, +EH,Ethiopian Seismic Network,Addis Ababa University,ET (Ethiopia),,Ethiopia,doi:10.7914/SN/EH +EI,Irish National Seismic Network (INSN),Dublin Institute for Advanced Studies,IE (Ireland),,Ireland, +EM,Electromagnetic Studies of the Continents,Oregon State University (OSU USA),US (United States),http://NGF@oregonstate.edu,United States,doi:10.7914/SN/EM +EN,CalEnergy Subnetwork,"USGS Caltech, Pasadena",US (United States),,United States, +EP,UTEP Seismic Network,University of Texas at El Paso (UTEP),US (United States),,United States, +EQ,Nevada Educational Seismic Network,University of Nevada (UNR Reno),US (United States),,United States, +ER,Mount Erebus Volcano Observatory Seismic Network,"New Mexico Tech (NMT Mining & Technology NM,USA)",US (United States),http://erebus.nmt.edu/,Antartica, +ES,Spanish Digital Seismic Network,Subdireccion General De Geodesia Y Geofisica,ES (Spain),,Spain, +ET,CERI Southern Appalachian Seismic Network,"University of Memphis, CERI",US (United States),http://www.ceri.memphis.edu/,United States, +EU,Generic European Strong Motion Network,INGV Instituto Nazionale di Geofisica e Vulcanologia (Italy),IT (Italy),,Europe, +EV,Collalto Seismic Network - Rete Sismica di Collalto,Istituto Nazionale di Oceanografia e di Geofisica Sperimentale,IT (Italy),http://rete-collalto.crs.inogs.it/,Italy,doi:10.7914/SN/EV +EX,EXTREMA Network,Istituto Nazionale di Geofisica e Vulcanologia (INGV),IT (Italy),,Italy, +FA,UCLA Seismic Network,UC Los Angeles,US (United States),,United States, +FB,Seismic Network of Federation of Bosnia and Herzegovina,Federal Hydrometeorological Institute (Bosnia),BA (Bosnia and Herzegovina),,Bosnia and Herzegovina, +FC,Generic African Strong Motion Network,INGV Instituto Nazionale di Geofisica e Vulcanologia (Italy),IT (Italy),,Africa, +FG,Fallon Microearthquake Network,Geothermal Program Office/US Navy,US (United States),,United States, +FN,Northern Finland Seismological Network,Sodankyla Geophysical Observatory / University of Oulu (Finland),FI (Finland),,Finland, +FR,RESIF and other Broad-band and accelerometric permanent networks in metropolitan France,Ecole et Observatoire des Sciences de la Terre (EOST),FR (France),https://portal.resif.fr/?FR-French-broadband-and,France,10.15778/RESIF.FR +FV,Friuli and Veneto Short Period Network,OGS (Istituto Nazionale di Oceanografia e di Geofisica Sperimentale),IT (Italy),http://oasis.crs.inogs.it/,Italy,doi:10.7914/SN/FV +G,GEOSCOPE,Institut de Physique du Globe de Paris,FR (France),,Global, +GA,GARNET Seismic Network,Geological Survey of Japan (GSJ AIST),JP (Japan),,Japan, +GB,Great Britain Seismograph Network,British Geological Survey,GB (United Kingdom),,United Kingdom, +GC,UCLA Geonet Network,UC Los Angeles,US (United States),http://lecs.cs.ucla.edu/wiki/index.php/GeoNet,United States, +GD,Global Positioning System (GPS) Displacement Measurements, None, ( ),,Global , +GE,GEOFON,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),http://geofon.gfz-potsdam.de/,Global,doi:10.14470/TR560404 +GF,GONAF,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),http://www.gonaf.de/,Turkey, +GG,Greenland Ice Sheet Monitoring Network,IRIS HQ (DC),US (United States),http://glisn.info/,Greenland, +GH,Ghana Digital Seismic Network,Ghana Geological Survey,GH (Ghana),,Ghana, +GI,Red Sismologica Nacional- Guatemala,"Instituto Nacional de Sismologia, Vulcanologia,Meteorologia e Hidrologia (INSIVUMEH)",GT (Guatemala),,Guatemala, +GL,Guadeloupe Seismic and Volcano Observatory Network,Institut de Physique du Globe de Paris,FR (France),http://www.ipgp.fr/ovsg,"Guadeloupe, Lesser Antilles, Caribbean", +GN,Garni Dense Array,USGS Menlo Park,US (United States),http://nsmp.wr.usgs.gov/geos/GARNI/garni.html,Armenia, +GO,National Seismic Network of Georgia,Ilia State University- Seismic Monitoring Centre of Georgia (Georgia),GE (Georgia),,Georgia, +GP,GPS Data Products for Solid Earth Science,California Institute of Technology (Caltech),US (United States),,United States, +GR,German Regional Seismic Network,Seismogisches Zentralobseratorium GRF,DE (Germany),,Germany, +GS,US Geological Survey Networks,USGS Golden Colorado,US (United States),,Global, +GT,Global Telemetered Seismograph Network (USAF/USGS),Albuquerque Seismological Laboratory (ASL)/USGS,US (United States),,"South America, Africa and Antarctica ",doi:10.7914/SN/GT +GU,Regional Seismic Network of North Western Italy,University of Genova,IT (Italy),http://www.distav.unige.it/rsni,Italy,doi:10.7914/SN/GU +GY,"Geyokcha Array, Turkmenistan",UC San Diego,US (United States),,Turkmenistan, +GZ,ANKARA-NET,"Gazi University, Earthquake Engineering Implementation and Research Center",TR (Turkey),,Turkey, +H2,Hawaii 2 Observatory,University of Hawaii (UH),US (United States),http://www.soest.hawaii.edu/H2O/,United States, +HA,Hellenic Seismological Network,University of Athens,GR (Greece),,Greece, +HC,Seismological Network of Crete,Technological Educational Institute of Crete,GR (Greece),,Greece, +HE,Finnish National Seismic Network,University of Helsinki,FI (Finland),,Finland, +HF,Swedish Seismic Array Network,Swedish Defence Research Agency (FOI),SE (Sweden),http://snsn.geofys.uu.se/,Sweden, +HG,High-Gain Long-Period Network,Albuquerque Seismological Laboratory (ASL)/USGS,US (United States),,Global ,doi:10.7914/SN/HG +HI,ITSAK Strong Motion Network,Institute of Engineering Seismology and Earthquake Engineering (ITSAK),GR (Greece),,Greece, +HK,Hong Kong Seismograph Network,Hong Kong Observatory,CN (China),http://www.hko.gov.hk/gts/equake/sp_seismo_network_intro_e.htm,China, +HL,National Observatory of Athens Seismic Network,"National Observatory of Athens, Institute of Geodynamics, Athens",GR (Greece),http://bbnet.gein.noa.gr,Greece,doi:10.7914/SN/HL +HM,GeoRisk Seismic Network, GeoRisk Earthquake Engineering,HU (Hungary),http://www.foldrenges.hu,Hungary,doi:10.7914/SN/HM +HP,"University of Patras, Seismological Laboratory",University of Patras,GR (Greece),http://seismo.geology.upatras.gr/,Greece, +HS,Hessischer Erdbebendienst (HED),"Hessisches Landesamt für Umwelt und Geologie, Wiesbaden",DE (Germany),,Germany, +HT,Aristotle University of Thessaloniki Seismological Network,Aristotle University of Thessaloniki,GR (Greece),http://geophysics.geo.auth.gr/the_seisnet/WEBSITE_2005/station_index_en.html,Greece,doi:10.7914/SN/HT +HU,Hungarian National Seismological Network,Geodetic and Geophysical Research Institute,HU (Hungary),http://www.seismology.hu/index.php/en/observatory/stations/51-the-hungarian-national-seismological-network,Hungary,10.14470/UH028726 +HV,Hawaiian Volcano Observatory Network,USGS Hawaiian Volcano Observatory (HVO),US (United States),http://hvo.wr.usgs.gov,United States,doi:10.7914/SN/HV +HW,Hanford Washington Seismic Network,Pacific Northwest National Laboratory (PNL),US (United States),,United States, +I1,Iranian Strong Motion Network,Ministry of Road and Urban Development (BHRC),IR (Iran),,Iran, +I2,Iranian National Broadband Seismic Network,Internationa Institute of Earthquake Engineering and Seismology,JP (Japan),,Japan, +IA,InaTEWS Indonesia Tsunami Early Warning System,"Meteorological, Climatological and Geophysical Agency (BMKG Indonesia)",ID (Indonesia),,Indonesia, +IB,IberArray,"Institute Earth Sciences ""Jaume Almera"" CSIC (ICTJA Spain)",ES (Spain),http://iberarray.ictja.csic.es/,Spain, +IC,New China Digital Seismograph Network,Albuquerque Seismological Laboratory (ASL)/USGS,US (United States),,China,doi:10.7914/SN/IC +ID,Project IDA VLP Seismometer Network (UCSD/SIO/IGPP),Scripps Institution of Oceanography,US (United States),http://ida.ucsd.edu/,Global,doi:10.7914/SN/ID +IE,Idaho National Engineering Laboratory,University of Utah,US (United States),,United States, +IG,Southern Spain Broadband Seismic Network,"Instituto Andaluz de Geofisica, Granada University",ES (Spain),,Spain, +IH,Red Sismica Dominicana del INDRHI,Instituto Nacional de Recursos Hidraulicos,DO (Dominican Republic),,Dominican Republic, +II,IRIS/IDA Seismic Network,Scripps Institution of Oceanography,US (United States),http://ida.ucsd.edu/,Global,doi:10.7914/SN/II +IK,IISERK Seismic Network,Indian Institute of Science Education and Research Kolkata (IISER),IN (India),http://www.iiserkol.ac.in/,India, +IL,Iranian Long Period Array,"Institute of Geophysics (University of Tehran, Iranian Seis Center-Iran)",IR (Iran),,Iran, +IM,International Miscellaneous Stations, None, ( ),,Global, +IN,National Seismic Network of India,India Meteorological Department,IN (India),,India, +IO,International OGS Network,Istituto Nazionale di Oceanografia e di Geofisica Sperimentale,IT (Italy),http://www.inogs.it/asain/evn,Global,doi:10.7914/SN/IO +IP,Instituto Superior Tecnico Broadband Seismic Network,"Instituto Superior Tecnico (IST Universidade Tecnica de Lisboa, Portugal)",PT (Portugal),,Portugal, +IQ,Inquique Local Network,University of Kiel,DE (Germany),http://www.ipoc-network.org/index.php/observatory/seismology/iquique-local-network.html,Chile, +IR,International Registry,"International Seismological Centre (ISC, UK)",GB (United Kingdom),,United Kingdom, +IS,Israel National Seismic Network,Geophysical Institute of Israel (GII Israel),IL (Israel),,Israel, +IT,Italian Strong Motion Network,Presidency of Counsil of Ministers - Civil Protection Department ,IT (Italy),http://ran.protezionecivile.it/IT/index.php,Italy,doi:10.7914/SN/IT +IU,Global Seismograph Network (GSN - IRIS/USGS),Albuquerque Seismological Laboratory (ASL)/USGS,US (United States),http://earthquake.usgs.gov/monitoring/gsn/,Global,doi:10.7914/SN/IU +IV,Italian National Seismic Network,Istituto Nazionale di Geofisica e Vulcanologia (INGV),IT (Italy),http://terremoti.ingv.it/,Italy, +IW,Intermountain West Seismic Network,USGS National Earthquake Information Center (NEIC),US (United States),http://earthquake.usgs.gov/monitoring/anss/regions/imw/,United States, +IX,ISNet - Irpinia Seismic Network,INGV Instituto Nazionale di Geofisica e Vulcanologia (Italy),IT (Italy),http://isnet.fisica.unina.it/,Italy, +IZ,Italian Experimental Seismic Network,Other, (),http://www.iesn.org/,, +JA,Red Sísmica y Acelerométrica de Jalisco,Universidad De Guadalajara (UDG Mexico),MX (Mexico),,Mexico, +JI,Jorhat India Seismic Network,"North East Institute of Science and Technology, Jorhat (NEIST India)",IN (India),,India, +JM,Jamaica Seismograph Network,University of the West Indies - Mona (Jamaica),JM (Jamaica),http://www.mona.uwi.edu/earthquake/jamseisnet.htm,Jamaica, +JP,Japan Meteorological Agency Seismic Network,JMA Japan Meteorological Agency,JP (Japan),http://www.jma.go.jp/en/quake/,Japan, +JS,Jordan Seismic Network,Jordan Seismo Obs & Geo Studies / Natural Resources Authority (NRA Jordan),JO (Jordan),,Jordan, +KA,Karthala Volcano Monitoring Network,Institut de Physique du Globe de Paris,FR (France),,Comoros, +KB,Karlsruhe BroadBand Array,Karlsruhe Institute of Technology (KIT GIP Germany),DE (Germany),http://www.gpi.kit.edu/english/KABBA.php,Global, +KC,Central Asian Seismic Network of CAIAG,Central Asian Institute for Applied Geosciences,KG (Kyrgyzstan),http://www.caiag.kg,Central Asia,doi:10.7914/SN/KC +KG,Korean Seismic Network (KIGAM),"Korean Institute of Geology, Mining and Materials (KIGAM)","KR (Korea, South)",,"Korea, South", +KI,Kandilli Observatory Strong Motion Network,"Bogazici University (Istanbul, Turkey)",TR (Turkey),,Turkey, +KK,Ọbáfémi Awólówò University Digital Seismograph Network,"Geology Department, Ọbáfémi Awólówò University, Ilé-Ifè, Osun State, Nigeria",NG (Nigeria),,Nigeria, +KM,Kansas Seismic Monitoring Network,Kansas Geological Survey,US (United States),,United States, +KN,Kyrgyz Seismic Telemetry Network,"Kyrgyz Institute of Seismology, IVTAN/KIS ",KG (Kyrgyzstan),,Kyrgyzstan, +KO,Bogazici University Kandilli Observatory And Earthquake Research Institute,"Kandilli Observatory and Earthquake Research Institute, Bosphorus Univ.",TR (Turkey),http://bdtim.koeri.boun.edu.tr/,Turkey,doi:10.7914/SN/KO +KP,Korea Polar Seismic Network,Korea Polar Research Institute (KOPRI),"KR (Korea, South)",,Greenland,doi:10.7914/SN/KP +KR,Kyrgyz Digital Network,"Institute of Seismology, National Academy of Sciences of Kyrgyz Republic (KIS)",KG (Kyrgyzstan),http://www.seismo.kg,Kyrgyzstan,doi:10.7914/SN/KR +KS,Korea National Seismography Network (KNSN-KMA),"Korea Meteorological Administration, Seoul","KR (Korea, South)",,"Korea, South", +KU,King Saud University Network,King Saud University,SA (Saudi Arabia),,Saudi Arabia, +KW,Kuwait National Seismic Network,Kuwait Institute for Scienctific Research (KISR),KW (Kuwait),,Kuwait, +KY,Kentucky Seismic and Strong Motion Network,Kentucky Geological Survey/Univ. of Kentucky,US (United States),http://www.uky.edu/KGS/geologichazards/equake3.htm,United States,doi:10.7914/SN/KY +KZ,Kazakhstan Network,KNDC/Institute of Geophysical Research (Kazakhstan),KZ (Kazakhstan),,Kazakhstan,doi:10.7914/SN/KZ +LA,Los Angeles Basin Seismic Network,USC - University of Southern California,US (United States),,United States, +LB,Leo Brady Network,Sandia National Laboratories,US (United States),,United States, +LC,LSC (Laboratorio Subterraneo Canfranc) ,"Institut de Ciencies de la Terra ""Jaume Almera"" (CSIC ICTJA Spain)",ES (Spain),,Spain, +LD,Lamont-Doherty Cooperative Seismographic Network,"Lamont Doherty Earth Observatory (LDEO), Columbia University",US (United States),http://www.ldeo.columbia.edu/LCSN/,United States, +LE,Landeserdbebendienst Baden-Wuerttemberg,"Landesamt fuer Geologie, Rohstoffe und Bergbau",DE (Germany),http://www.lgrb.uni-freiburg.de/lgrb/Fachbereiche/erdbebendienst,Germany, +LI,Laser Interferometer Gravitational-Wave Experiment,California Institute of Technology (Caltech),US (United States),http://www.ligo.caltech.edu/,United States,doi:10.7914/SN/LI +LL,LLNL NTS Network,Lawrence Livermore National Laboratory (LLNL),US (United States),,United States, +LN,Los Alamos Seismic Network (LASN),"Los Alamos National Laboratory (LANL, NM)",US (United States),http://www.ees.lanl.gov/ees11/geophysics/lasn/lasn.shtml,United States, +LO,Observatorio Sismologico Loyola,Instituto Politecnico Loyola,DO (Dominican Republic),,Dominican Republic, +LS,Large Aperture Seismic Array (LASA), None, ( ),, , +LT,Timor Leste Seismic Network,Other, (),http://ipg.tl,Timor-Leste,doi:10.7914/SN/LT +LV,seismic data in North West of UK,Liverpool University,GB (United Kingdom),,United Kingdom,doi:10.7914/SN/LV +LX,University of Lisbon Seismic Network,Universidade de Lisboa (Lisbon Portugal),PT (Portugal),,Portugal, +LZ,Zambia Seismic Network,Geological Survey Department of Zambia,ZM (Zambia),http://www.mewd.gov.zm,Zambia,doi:10.7914/SN/LZ +M,Generic American Strong Motion Network,Istituto Nazionale di Geofisica e Vulcanologia (INGV),IT (Italy),,Italy, +MA,Macedonian Seismological Network,Macedonia Seismological Observatory (Macedonia),MK (Macedonia),,Macedonia, +MB,Montana Regional Seismic Network,"Montana Bureau of Mines and Geology/Montana Tech (MBMG, MT USA)",US (United States),http://mbmgquake.mtech.edu,United States,doi:10.7914/SN/MB +MC,Montserrat CALIPSO Borehole Network,University of Texas-Arlington,US (United States),http://www.uta.edu/faculty/mattioli/research/CALIPSO/Intro.html,Montserrat, +MD,Moldova Digital Seismic Network,Geological and Seismological Institute of Moldova,MD (Moldova),,Moldova, +ME,Montenegrian Seismic Network,Montenegro Seismological Observatory,ME (Montenegro),,Montenegro, +MF,Laboratorio de Ingeniería Sísmica,Universidad de Costa Rica,CR (Costa Rica),http://www.lis.ucr.ac.cr,Costa Rica,doi:10.7914/SN/MF +MG,Seismic Network of the NorthEastern Mexico,"Universidad Nacional Autónoma de México (UNAM), Mexico City, D.F.",MX (Mexico),,Mexico, +MI,USGS Northern Mariana Islands Network,USGS Alaska Anchorage,US (United States),http://volcanoes.usgs.gov/nmi/,Northern Mariana Islands,doi:10.7914/SN/MI +ML,Malta Seismic Network,University of Malta (Malta),MT (Malta),,Malta, +MM,Myanmar National Seismic Network,Department of Meteorology and Hydrology - National Earthquake Data Center,MM (Myanmar),http://www.dmh.gov.mm/,Myanmar,doi:10.7914/SN/MM +MN,MEDNET Project,Istituto Nazionale di Geofisica e Vulcanologia (INGV),IT (Italy),http://mednet.rm.ingv.it/,Mediterrean Sea region, +MO,Morocco Seismic Network,"Institut National de Géophysique (CNRST), Rabat",MA (Morocco),,Morocco, +MQ,Martinique Seismic and Volcano Observatory Network ,Institut de Physique du Globe de Paris,FR (France),http://www.ipgp.fr/fr/ovsm,Martinique, +MR,Mauritius Seismic Network,Mauritius Meteorological Services,MU (Mauritius),,Mauritius, +MS,Singapore Seismological Network,Meteorological Service of Singapore,SG (Singapore),,Singapore, +MT,Observatory for Multidisciplinary monitoring of Instability of Versant,"Observatoire de Grenoble, Grenoble",FR (France),,France, +MU,Miami University Seismic Network,"Miami University (Ohio, USA)",US (United States),,United States, +MV,Montserrat Volcano Observatory,University of the West Indies (Seismic Research Centre Trinidad),TT (Trinidad and Tobago),,Trinidad and Tobago, +MW,Malawi National Seismic Network,Geological Survey Department of Malawi,MW (Malawi),,Eastern Region,doi:10.7914/SN/MW +MX,Mexican National Seismic Network,"Universidad Nacional Autónoma de México (UNAM), Mexico City, D.F.",MX (Mexico),,Mexico, +MY,Malaysian National Seismic Network,"Malaysian Meteorological Service (Ministry of Science, Tech and Innovation, MOSTI-MMD-MET)",MY (Malaysia),,Malaysia, +N4,Central and Eastern US Network,UC San Diego,US (United States),http://ceusn.ucsd.edu/,United States,doi:10.7914/SN/N4 +NA,Netherlands Antilles Seismic Network,"ORFEUS (KNMI) Data Center, Royal Netherlands Meteorological Institute",NL (Netherlands),,Netherlands, +NB,Northeastern Brazil UFRN,Universidade Federal do Rio Grande do Norte (UFRN Brazil),BR (Brazil),http://www.sistemas.ufrn.br/,Brazil, +NC,USGS Northern California Regional Network,USGS Menlo Park,US (United States),http://www.ncedc.org/ncsn/,United States, +ND,New CaleDonia Broadband Seismic Network,"Centre IRD de Noumea, Nouvelle-Caledonie",NC (New Caledonia),http://www.seisme.nc,New Caledonia,doi:10.7914/SN/ND +NE,New England Seismic Network,Boston College,US (United States),http://aki.bc.edu/nesn.htm,North East United States,doi:10.7914/SN/NE +NF,North Fork Valley Seismic Network,"National Institute for Occupational and Health (NIOSH WA,USA)",US (United States),,United States, +NG,Reserved for Papua New Guinea Seismic Network,,,,, +NH,Geological Survey of North Rhine - Westphalia,Geological Survey of North Rhine - Westphalia,DE (Germany),http://www.gd.nrw.de/gg_le.htm,Germany, +NI,North-East Italy Broadband Network,OGS (Istituto Nazionale di Oceanografia e di Geofisica Sperimentale) and University of Trieste,IT (Italy),,Italy,doi:10.7914/SN/NI +NJ,Nigerian National Network of Seismographi Stations (NNNSS),Centre for Geodesy and Geodynamics,NG (Nigeria),,Nigeria,doi:10.7914/SN/NJ +NL,Netherlands Seismic Network,"ORFEUS (KNMI) Data Center, Royal Netherlands Meteorological Institute",NL (Netherlands),http://www.knmi.nl/research/seismology/nat_seism_network.html,Netherlands, +NM,Cooperative New Madrid Seismic Network,Saint Louis University,US (United States),http://www.eas.slu.edu/eqc/eqcnetwork.html,United States, +NN,Nevada Seismic Network,University of Nevada (UNR Reno),US (United States),http://www.seismo.unr.edu,United States,doi:10.7914/SN/NN +NO,Norwegian Seismic Array Network,Norwegian Seismic Array (NORSAR),NO (Norway),,Norway, +NP,United States National Strong-Motion Network,USGS National Strong Motion Program -Fresno,US (United States),,United States, +NQ,NetQuakes,USGS Menlo Park,US (United States),http://earthquake.usgs.gov/monitoring/netquakes/,United States, +NR,NARS Array,Utrecht University (UU Netherlands),NL (Netherlands),http://www.data.scec.org/NARS-Baja/,Mexico, +NS,Norwegian National Seismic Network,University of Bergen (UiB Norway) Inst of Geophysics,NO (Norway),http://www.geo.uib.no/seismo/nnsn/,Norway, +NT,USGS Geomagnetism Program,USGS Golden Colorado,US (United States),http://geomag.usgs.gov/,United States, +NU,Nicaraguan Seismic Network,INETER (Instituto Nicarag¿ense de Estudios Territoriales),NI (Nicaragua),,Nicaragua, +NV,Neptune Canada,Geological Survey of Canada,CA (Canada),http://www.neptunecanada.com/,Canada, +NW,Northwestern University Seismic Network,Northwestern University,US (United States),http://www.earth.northwestern.edu/,United States, +NX,Nanometrics Research Network,Nanometrics Seismological Instruments,CA (Canada),,Canada,doi:10.7914/SN/NX +NY,Yukon-Northwest Seismic Network (YNSN),University of Ottawa (uOttawa Canada),CA (Canada),,Canada, +NZ,New Zealand National Seismograph Network,Institute of Geological & Nuclear Sciences Ltd (GNS New Zealand),NZ (New Zealand),http://info.geonet.org.nz/display/equip/New+Zealand+National+Seismograph+Network,New Zealand, +OB,"Osservatorio Sismico ""A. Bina""","Osservatorio Sismico ""A. Bina"", Perugia",IT (Italy),,Italy, +OE,Austrian Seismic Network,ZAMG - Central Institute for Meteorology and Geodynamics,AT (Austria),,Austria, +OG,Sismalp,"Observatoire de Grenoble, Grenoble",FR (France),,France, +OH,Ohio Seismic Network,Ohio Geological Survey,US (United States),,United States, +OK,Oklahoma Seismic Network,University of Oklahoma (OU Oklahoma USA),US (United States),http://www.okgeosurvey1.gov/pages/seismic-stations.php,United States, +OL,Cornegliano Laudense Seismic Network,Istituto Nazionale di Oceanografia e di Geofisica Sperimentale,IT (Italy),,Italy,doi:10.7914/SN/OL +OM,Earthquake Monitoring Program of Oman,Sultan Qaboos University,OM (Oman),http://www.squ.edu.om/emc,Oman, +ON,Rede Sismográfica do Sul e do Sudeste,"Observatório Nacional, Rio de Janeiro, RJ",BR (Brazil),http://www.rsis1.on.br/,Brazil,doi:10.7914/SN/ON +OO,Ocean Observatories Initiative,Rutgers University,US (United States),http://www.oceanobservatories.org/,Juan de Fuca Plate,doi:10.7914/SN/OO +OS,"Seismological Observatory, Brasilia Brazil",University of Brasilia,BR (Brazil),http://www.obsis.unb.br/,Brazil, +OT,OTRIONS,"University of Bari ""Aldo Moro""",IT (Italy),http://www.otrions.uniba.it,Italy,doi:10.7914/SN/OT +OV,Observatorio Vulcanológico y Sismológico de Costa Rica,Universidad Nacional Costa Rica (UNA Heredia OVISCORI Costa Rica) ,CR (Costa Rica),http://www.ovsicori.una.ac.cr/,Costa Rica, +OX,North-East Italy Seismic Network,OGS (Istituto Nazionale di Oceanografia e di Geofisica Sperimentale),IT (Italy),http://rts.crs.inogs.it/,Italy,doi:10.7914/SN/OX +OZ,SRC eqServer,Seismology Research Centre,AU (Australia),,Australia, +PA,ChiriNet,Observatorio Sismico del Occidente de Panamá (OSOP),PA (Panama),,Panama, +PB,Plate Boundary Observatory Borehole Seismic Network,UNAVCO,US (United States),,United States, +PC,Panama Canal Network,Autoridad del Canal de Panama (Panama Canal Authority),PA (Panama),,Panama, +PD,Polish Seismic Monitoring Network,Polish Academy of Sciences (PAN) Polskiej Akademii Nauk,PL (Poland),http://www.igf.edu.pl/en/monitoring_geofizyczny/monitoring_sejsmiczny_polski,Poland, +PE,Penn State Network,Penn State University,US (United States),http://eqseis.geosc.psu.edu/,United States, +PF,Piton de la Fournaise Volcano Observatory Network (Reunion Island),Institut de Physique du Globe de Paris,FR (France),http://www.ipgp.fr/ovpf,Réunion, +PG,"Central Coast Seismic Network, PG&E",Pacific Gas and Electric (PG&E),US (United States),http://ncedc.org/pge/,United States, +PH,Puna Geothermal Network,Duke University,US (United States),,United States, +PI,PASSCAL Pier Test Data,IRIS/PASSCAL, (),,, +PK,Micro Seismic Monitoring System of Northern Areas of Pakistan,Water and Power Development Authority (WAPDA),PK (Pakistan),,Pakistan, +PL,Polish Seismological Network,Polish Academy of Sciences (PAN) Polskiej Akademii Nauk,PL (Poland),http://www.igf.edu.pl/pl/zaklady_naukowe/sejsmologii_i_fizyki_wnetrza_ziemi/stacje_i_obserwatoria_sejsmologiczne,Poland, +PM,Portuguese National Seismic Network,"Instituto Português do Mar e da Atmosfera, I.P.",PT (Portugal),http://www.meteo.pt/en/sismologia/redes/,Portugal, +PN,PEPP-Indiana,Indiana University Bloomington (IU Bloomington),US (United States),http://www.indiana.edu/~pepp/,United States, +PO,Portable Observatories for Lithospheric Analysis and Research Investigating Seismicity,Geological Survey of Canada,CA (Canada),http://www.polarisnet.ca/network/polaris-network-locations.html,Canada, +PP,Princeton Earth Physics Program,Princeton University,US (United States),,United States, +PR,Puerto Rico Seismic Network (PRSN) & Puerto Rico Strong Motion Program (PRSMP),University of Puerto Rico/Mayaguez Campus (UPRM),PR (Puerto Rico),http://redsismica.uprm.edu/,Puerto Rico, +PS,Pacific21 ,"University of Tokyo, Earthquake Research Institute (Todai, ERI, Japan)",JP (Japan),,Japan, +PT,Pacific Tsunami Warning Seismic System,Pacific Tsunami Warning Center,US (United States),,United States, +PU,INGEMMET,"Instituto Geologico Minero Y Metalurgico, Lima",PE (Peru),,Peru, +PV,Philippine Seismic Network,Philippine Institution of Volcanology and Seismology,PH (Philippines),,Philippines, +PW,Pacific Northwest Geodetic Array,Central Washington University,US (United States),http://www.panga.cwu.edu/,United States,doi:10.7914/SN/PW +PX,Parkfield Experiment Array,Duke University,US (United States),,United States, +PY,Pinyon Flats Observatory (PFO) Array,UC San Diego,US (United States),,United States, +PZ,Prince Islands Real-time Earthquake monitoring System (PIRES),"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Turkey, +QA,Qatar Seismic Network,Qatar Civil Aviation Authority,QA (Qatar),http://www.caa.gov.qa/en/meteorology,Qatar, +QC,Quake Catcher Network,Stanford University,US (United States),http://qcn.stanford.edu/,United States, +RA,Réseau Accélérométrique Permanent (French Accelerometrique Network),Universite Joseph Fourier - Grenoble (LGIT-UJF-France),FR (France),http://www-rap.obs.ujf-grenoble.fr/,France, +RB,Red Sísmica de Banda Ancha (RESBAN),"Centro de Investigación Científica y de Educación Superior de Ensenada (CICESE), Ensenada",MX (Mexico),http://sismologia.cicese.mx/Redes/Resban.html,Mexico, +RC,BYU-Idaho Network,Brigham Young Univ-Idaho (BYU Idaho),US (United States),,United States,doi:10.7914/SN/RC +RD,CEA/DASE Seismic Network,Departement d'Analyse et Surveillance de l'Environnement du CEA,PF (French Polynesia),http://www-dase.cea.fr/public/dossiers_thematiques/alerte_aux_forts_seismes/description_en.html,French Polynesia, +RE,US Bureau of Reclamation Seismic Networks,U.S. State Department,US (United States),,United States, +RF,Friuli Venezia Giulia Accelerometric Network,University of Trieste,IT (Italy),http://rtweb.units.it/,Italy,doi:10.7914/SN/RF +RG,Upper-Rhine Graben Geothermal Network,ES-Géothermie,FR (France),,France,doi:10.7914/SN/RG +RI,National Seismic Network of Argentina,Instituto Nacional de Prevención Sísmica (INPRES),AR (Argentina),,Argentina, +RJ,Rede Sísmica e Geomagnética do Rio de Janeiro,"Observatório Nacional, Rio de Janeiro, RJ",BR (Brazil),,Brazil, +RM,Regional Integrated Multi-Hazard Early Warning System,Regional Integrated Multi-Hazard Early Warning System (RIMES Thailand),TH (Thailand),http://www.rimes.int/,Asia,doi:10.7914/SN/RM +RN,RuhrNet,Ruhr Universitaet Bochum (RUB Germany),DE (Germany),http://www.gmg.ruhr-uni-bochum.de/geophysik/seismology/research/,Germany, +RO,Romanian Seismic Network,National Institute for Earth Physics (NIEP Romania),RO (Romania),http://www.infp.ro/retea-seismica-nationala/,Romania,doi:10.7914/SN/RO +RP,Universidad de Panama Seismic Network,"Instituto de Geociencias, Universidad de Panamá",PA (Panama),,Panama, +RS,Regional Seismic Test Network,USGS National Earthquake Information Center (NEIC),US (United States),,North America,doi:10.7914/SN/RS +RT,Kamchatka Tsunami Warning Sesimic Network,Geophysical Survey Kamchatkan EMSD (KEMSD GS RAS - Russia),RU (Russian Federation),,Russian Federation, +RV,Regional Alberta Seismic Observatory for Earthquake Studies Network,Alberta Geological Survey (AGS Canada),CA (Canada),http://ags.gov.ab.ca/geohazards/earthquakes_project.html,"Alberta, Canada",doi:10.7914/SN/RV +RY,Yakutain Branch of Russian Seismic Network,"Yakutian Branch, Geological Survey, Siberian Branch, Russian Academy of Sciences",RU (Russian Federation),,Russian Federation, +S,Seismographs in Schools Network,Swiss Seismological Service,CH (Switzerland),http://www.iris.edu/hq/ssn/schools,Global, +SA,Saudi Arabia Broadband Seismic Network,"Institute for Astronomical and Geophysical Research, Saudi Arabia (KACST)",SA (Saudi Arabia),,Saudi Arabia, +SB,UC Santa Barbara Engineering Seismology Network,UC Santa Barbara,US (United States),http://www.nees.ucsb.edu/,United States, +SC,New Mexico Tech Seismic Network,"New Mexico Tech (NMT Mining & Technology NM,USA)",US (United States),http://www.ees.nmt.edu/outside/Geop/NMTSO.html,United States, +SE,Southeastern Appalachian Cooperative Seismic Network, None, ( ),, , +SF,San Andreas Fault Observatory at Depth,Stanford University,US (United States),http://www.earthscope.org/observatories/safod,United States, +SG,Global Geodynamics Project,Multiple Operators,BE (Belgium),http://www.eas.slu.edu/GGP/ggphome.html,Global,doi:10.7914/SN/SG +SH,Shumagin-East Aleutian Network,"Lamont Doherty Earth Observatory (LDEO), Columbia University",US (United States),,"Alaska, United States",doi:10.7914/SN/SH +SI,Province Südtirol,ZAMG - Central Institute for Meteorology and Geodynamics,AT (Austria),,Austria, +SJ,Serbian Seismological Network,Seismological Survey of Serbia,RS (Serbia),,Serbia, +SK,Slovak National Seismic Network,"Geophysical Institute, Slovak Academy of Sciences",SK (Slovakia),http://www.seismology.sk/National_Network/national_network_A.html,Slovakia, +SL,Slovenia Seismic Network,Geological Survey of Slovenia (GEoZS Slovenia),SI (Slovenia),http://www.geo-zs.si/podrocje.aspx?id=0,Slovenia, +SM,Icelandic Strong Motion Network,University of Iceland,IS (Iceland),http://www.isesd.hi.is/,Iceland, +SN,Southern Great Basin Network,University of Nevada (UNR Reno),US (United States),http://www.seismo.unr.edu,United States,doi:10.7914/SN/SN +SP,South Carolina Earth Physics Project,University of South Carolina,US (United States),http://www.seis.sc.edu/scepp/,United States,doi:10.7914/SN/SP +SR,Seismic Research Observatory,Albuquerque Seismological Laboratory (ASL)/USGS,US (United States),,Global,doi:10.7914/SN/SR +SS,SINGLE STATION, None, ( ),, , +ST,Trentino Seismic Network,Geological Survey-Provincia Autonoma di Trento,IT (Italy),http://www.protezionecivile.tn.it,Italy,doi:10.7914/SN/ST +SU,Sandia Seismo-Acoustic Network,Sandia National Laboratories,US (United States),,United States, +SV,"Servicio Nacional de Estudios Territoriales (SNET), El Salvador",Servicio Nacional de Estudios Territoriales (SNET El Salvador),SV (El Salvador),http://www.snet.gob.sv/ver/sismologia/,El Salvador, +SX,SXNET Saxon Seismic Network,University of Leipzig,DE (Germany),,Germany, +SY,Synthetic Seismograms,IRIS DMC (Seattle),US (United States),,United States, +TA,USArray Transportable Array,IRIS Transportable Array,US (United States),http://www.earthscope.org/observatories/usarray,United States,doi:10.7914/SN/TA +TC,Red Sismológica Nacional de Costa Rica,Universidad de Costa Rica,CR (Costa Rica),http://www.rsn.ucr.ac.cr/,Costa Rica,doi:10.15517/TC +TD,TransAlta Monitoring Network,TransAlta Corporation,CA (Canada),http://www.transalta.com/,Canada, +TE,EGAT Dams Seismic Monitoring System,Electricity Generating Authority of Thailand,TH (Thailand),,Thailand,doi:10.7914/SN/TE +TG,Royal Irrigation Department,Royal Irrigation Department,TH (Thailand),,Thailand,doi:10.7914/SN/TG +TH,Thüringer Seismisches Netz (TSN),"Institut fuer Geowissenschaften, Friedrich-Schiller-Universitaet Jena",DE (Germany),http://www.geophysik.uni-jena.de/Einrichtungen+_+Labore/Thüringer+Seismisches+Netz_TSN.html,Germany, +TI,Centro Sismologico de America Central,Universidad de Costa Rica,CR (Costa Rica),,Costa Rica, +TJ,Tajikistan National Seismic Network,PMP International (Tajikistan),TJ (Tajikistan),,Tajikistan,doi:10.7914/SN/TJ +TK,National Strong-Motion Network of Turkey (TR-NSMN),"Prime Ministry Disaster & Emergency Managment Presidency Earthquake Department (AFAD), Ankara",TR (Turkey),,Turkey, +TL,Armutlu Local Seismic Network,Kocaeli University,TR (Turkey),http://www.kocaeli.edu.tr/yubam/,Turkey, +TM,Thai Seismic Monitoring Network,Thailand Seismological Bureau,TH (Thailand),,Thailand, +TN,Eastern Tennessee Seismic Network,Joint Institute for Energy and the Evnironment,US (United States),,United States, +TO,"Tectonic Observatory -MASE, VEOX , PeruSE, CCSE",California Institute of Technology (Caltech),US (United States),http://web.gps.caltech.edu/~clay/MexWeb/MexSubduction.html,Mexico, +TR,Eastern Caribbean Seismograph Network,University of the West Indies (Seismic Research Centre Trinidad),TT (Trinidad and Tobago),,Eastern Caribbean, +TS,TERRAscope (Southern California Seismic Network),California Institute of Technology (Caltech),US (United States),,United States, +TT,Seismic Network of Tunisia,"Institut National de la Météorologie, Tunis",TN (Tunisia),,Tunisia, +TU,National Seismic Network of Turkey (DDA),Disaster and Emergency Management Presidency (AFAD Turkey),TR (Turkey),,Turkey, +TV,INGV experiments network,INGV Instituto Nazionale di Geofisica e Vulcanologia (Italy),IT (Italy),,Italy, +TW,Broadband Array in Taiwan for Seismology,"Academia Sinica, Institute of Earth Sciences",TW (Taiwan),http://bats.earth.sinica.edu.tw/,Taiwan,doi:10.7914/SN/TW +TX,Texas Seismological Network,"Bureau of Economic Geology, The University of Texas at Austin",US (United States),,"United States, Texas",doi:10.7914/SN/TX +UA,Caribbean Andesite Lava Island Precision Seismo-geodetic Observatory,University of Arkansas - Fayetteville,US (United States),,Montserrat, +UC,Colima Seismic Network,Universidad de Colima (Mexico),MX (Mexico),http://www.ucol.mx/volcan/monitoreo.php,Mexico, +UE,Seismological Network of United Arab Emirates,National Center of Meteorology and Seismology,AE (United Arab Emirates),,United Arab Emirates, +UG,Unocal Geothermal Northern California Network,Unocal Corporation,US (United States),http://www.ncedc.org/geysers/,United States, +UH,UH Infrasound Network,University of Hawaii (UH),US (United States),http://www.isla.hawaii.edu/,United States, +UI,North Idaho Seismic Network,University of Idaho,US (United States),,United States, +UK,UK Schools Seismic Network,University of Leicester (SEIS UK),GB (United Kingdom),http://www.le.ac.uk/seis-uk/school_resources.html,United Kingdom, +UL,USGS Low Frequency Geophysical Data Network,USGS Menlo Park,US (United States),http://quake.geo.berkeley.edu/ul/ul.overview.html,United States, +UO,University of Oregon Regional Network,University of Oregon,US (United States),,United States, +UP,University of Uppsala Network,University of Uppsala,SE (Sweden),,Sweden, +UR,UKArray,British Geological Survey,GB (United Kingdom),,United Kingdom,doi:10.7914/SN/UR +US,United States National Seismic Network,USGS National Earthquake Information Center (NEIC),US (United States),,United States,doi:10.7914/SN/US +UU,University of Utah Regional Seismic Network,University of Utah,US (United States),http://www.seis.utah.edu/,United States,doi:10.7914/SN/UU +UW,Pacific Northwest Regional Seismic Network,University of Washington,US (United States),http://www.pnsn.org/,United States, +UY,Observatorio Geofisico de Uruguay,Universidad de la Republica,UY (Uruguay),http://geotectonica.fcien.edu.uy/oga,Uruguay, +UZ,Uzbekistan Digital Seismic Network,"Uzbekistan Institute of Seismology, Tashkent",UZ (Uzbekistan),,Uzbekistan, +VC,Red Nacional de Vigilancia Volcánica Chile (VC),Servicio Nacional de Geología y Minería,CL (Chile),http://www.sernageomin.cl/,Chile, +VE,Red Sismologica Nacional con Apertura Continental,"Fundación Venezolana de Investigaciones Sismológicas (FUNVISIS), Caracas",VE (Venezuela),,Venezuela, +VG,Seismic Network of the Indonesian Center for Volcanology and Geological Hazard Mitigation,Pusat Vulkanologi dan Mitigasi Bencana Geologi,ID (Indonesia),,Indonesia,doi:10.7914/SN/VG +VI,Icelandic National Digital Seismograph Network,Icelandic Meteorological Office,IS (Iceland),http://en.vedur.is/earthquakes-and-volcanism/earthquakes/,Iceland, +VU,Vanuatu Seismic Network,Vanuatu Geoscience Observatory,VU (Vanuatu),,Vanuatu, +WA,West Central Argentina Network,"Universidad Nacional de San Juan (UNSJ, Argentina)",AR (Argentina),,Argentina, +WB,West Bohemia Local Seismic Network,"Institute of Geophysics, Academy of Sciences of the Czech Republic",CZ (Czech Republic),http://www.ig.cas.cz/struktura/oddeleni/seismika/zapadoceska-zemetreseni,Czech Republic,doi:10.7914/SN/WB +WC,Curacao Seismic Network,Meteorologische Dienst Curacao,CW (Curaçao),,Curacao, +WI,West Indies French Seismic Network,Institut de Physique du Globe de Paris,FR (France),,West Indies, +WK,Wake Island Hydrophone Array,University of Hawaii (UH),US (United States),,United States, +WM,Western Mediterranean Seismic Network,Real Instituto y Observatorio de la Armada (Spain),ES (Spain),,Spain, +WR,California Division of Water Resources,California Division of Water Resources,US (United States),,United States, +WS,Seismic Network of Repuplika Srpska,Republicki Hidrometeorološki Zavod,RS (Serbia),,Serbia, +WU,The Southern Ontario Seismic Network,University of Western Ontario (UWO Canada),CA (Canada),http://www.gp.uwo.ca/docs/stationmap.html,Canada, +WY,Yellowstone Wyoming Seismic Network,University of Utah,US (United States),,United States,doi:10.7914/SN/WY +X1,"Development and Testing of a Deep-Water, Acoustically-Linked, Moored- Buoy Seafloor Observatory",Woods Hole Oceanographic Institution (WHOI),US (United States),,United States, +X1,Aysen Chile Aftershock Deployment,University of Liverpool,GB (United Kingdom),,United Kingdom, +X1,Carbon Sequestration Technical Assessemnt-Pennsylvania,Penn State University,US (United States),,United States, +X1,Byrd Lake Reflection Seismics - Cresis,Penn State University,US (United States),,United States,doi:10.7914/SN/X1_2011 +X1,Réunion Hotspot and Upper Mantle Project,University of Frankfurt,DE (Germany),,Germany, +X2,NCISP4,"Institute of Geology and Geophysics, CAS",CN (China),http://english.igg.cas.cn,China,doi:10.7914/SN/X2_2005 +X2,Martinique 2007 Aftershock Experiment,"Observatoire de Grenoble, Grenoble",FR (France),,France, +X2,Wellington Geophysical Transect (aka SAHKE),Victoria University of Wellington (VUW New Zealand),NZ (New Zealand),,New Zealand,doi:10.7914/SN/X2_2009 +X2,Haida Gwaii OBS Experiment,Natural Resources Canada (NRCAN Canada),CA (Canada),,Canada, +X2,Sunset Seismic Experiment,Carnegie Institute of Washington / Science (DTM CIW),US (United States),,United States, +X3,"Understanding the current thinning and accelerration of the Jakobshavns Isbrae, Greenland","University of Alaska, Fairbanks (UAF, AK USA)",US (United States),,United States,doi:10.7914/SN/X3_2007 +X3,MARINER: Seismic Investigation of the Rainbow Hydrothermal Field,University of Hawaii (UH),US (United States),,United States,doi:10.7914/SN/X3_2013 +X4,Deep Structure of the Northeastern Tibet Collision Zone: INDEPTH IV,Missouri University of Science & Technology(Former UM-Rolla)(Missouri S&T USA),US (United States),,United States,doi:10.7914/SN/X4_2007 +X4,Gulf of Mexico Basin Opening,Texas Tech University,US (United States),,United States, +X5,Hudson Bay Lithospheric Experiment,University of Bristol (UK),GB (United Kingdom),,United Kingdom, +X5,IGC Geothermal Test Site,Ruhr Universitaet Bochum (RUB Germany),DE (Germany),,Germany, +X6,SLIP - Seismic Lithospheric Imaging of the Puna Plateau,University of Missouri (MU) (Mizzou),US (United States),,United States,doi:10.7914/SN/X6_2007 +X6,MonaSeis,Institute for Geosciences - Goethe University,DE (Germany),,Germany, +X6,Evolution and hydration of the Juan de Fuca crust and uppermost mantle,Woods Hole Oceanographic Institution (WHOI),US (United States),,United States,doi:10.7914/SN/X6_2012 +X6,Collaborative Research: Unlocking the Seismic Signature of Rivers,UC Santa Cruz,US (United States),,United States,doi:10.7914/SN/X6_2013 +X6,"Homestake Gold Mine Three-dimensional, Broadband Array",Indiana University Bloomington (IU Bloomington),US (United States),,United States,doi:10.7914/SN/X6_2014 +X7,Seismic Monitoring of Active Rock Fall Source Areas in the Yosemite National Park,UC Berkeley,US (United States),,United States,doi:10.7914/SN/X7_2007 +X7,Pyrope,Institut des Sciences de la Terre,FR (France),,France, +X8,Studies of Earthquakes & Rapid Motions of Ice,"Lamont Doherty Earth Observatory (LDEO), Columbia University",US (United States),,United States, +X8,Deep Structure of Three Continental Sutures in Eastern North America,Rutgers University,US (United States),,United States,doi:10.7914/SN/X8_2012 +X9,"Monitoring an active rift system at the front of the Amery Ice Shelf, East Antarctica",University of Chicago,US (United States),,United States,doi:10.7914/SN/X9_2004 +X9,Dallas Earthquake Swarm,Southern Methodist University (SMU TX),US (United States),,United States,doi:10.7914/SN/X9_2008 +X9,Plate Boundary Evolution and Physics at an Oceanic Transform Fault System,Oregon State University (OSU USA),US (United States),,United States, +XA,Apollo Lunar Seismic,NASA Goddard Space Flight Center (GSFC),US (United States),,United States, +XA,"PANDA -- San Juan, Argentina Experiment","University of Memphis, CERI",US (United States),,United States, +XA,Pinyon Flat High Frequency Array,IRIS/PASSCAL, (),,, +XA,Pinyon Flat Broadband Triggered Array,IRIS/PASSCAL, (),,, +XA,Joshua Tree Aftershocks,IRIS/PASSCAL, (),,, +XA,Non Proliferation Experiment (Chemical Kiloton at NTS),IRIS/PASSCAL, (),,, +XA,Northridge Aftershocks,IRIS/PASSCAL, (),,, +XA,Missouri to Massachusetts Transect,IRIS/PASSCAL, (),,, +XA,"Anatomy of an Archean Craton, South Africa",IRIS/PASSCAL, (),,, +XA,LIGO Noise Study,IRIS/PASSCAL, (),,,doi:10.7914/SN/XA_2000 +XA,Bhutan Pilot Experiment,IRIS/PASSCAL, (),,,doi:10.7914/SN/XA_2002 +XA,Collaborative Research: Mechanics of Dry-Land Calving of Ice Glaciers,IRIS/PASSCAL, (),,,doi:10.7914/SN/XA_2004 +XA,Monitgoring seismicity associated with a possible asperity on the Cascadia megathrust,Oregon State University (OSU USA),US (United States),,United States,doi:10.7914/SN/XA_2008 +XA,Using Fault-Zone Trapped Waves to Document Subsuface Rock Damage Caused by the M6.3 Earthquake in Ne,USC - University of Southern California,US (United States),,United States,doi:10.7914/SN/XA_2011 +XA,GANSSER: Swiss BB seismic experiment in Bhutan,Swiss Seismological Service,CH (Switzerland),,Switzerland, +XB,Viking Mission,Institut de Physique du Globe de Paris,FR (France),,France, +XB,UC Mammoth/Long Valley network, None, ( ),, , +XB,Landers Aftershocks,IRIS/PASSCAL, (),,, +XB,Southwest Pacific Seismic Experiment,IRIS/PASSCAL, (),,, +XB,Abitibi Experiment,IRIS/PASSCAL, (),,, +XB,Seismic Experiment in Patagonia and Antarctica,IRIS/PASSCAL, (),,, +XB,Array studies of anisotropy and converted phases in the Marlborough Fault Zone of New Zealand,IRIS/PASSCAL, (),,,doi:10.7914/SN/XB_2000 +XB,Magdalena Ridge Observatory site noise study,IRIS/PASSCAL, (),,,doi:10.7914/SN/XB_2003 +XB,Broadband Seismic Investigation of the Cameroon Volcanic Line,IRIS/PASSCAL, (),,,doi:10.7914/SN/XB_2005 +XB,Costa Rica Active Source OBS Experiment,Woods Hole Oceanographic Institution (WHOI),US (United States),,United States, +XB,Program to Investigate Convective Alboran Sea System Overturn,University of Oregon,US (United States),,United States,doi:10.7914/SN/XB_2009 +XB,Sweetwater Array,IRIS PASSCAL Instrument Center @ New Mexico Tech,US (United States),,United States,doi:10.7914/SN/XB_2014 +XB,INSIGHT,Institut de Physique du Globe de Paris,FR (France),,France, +XC,RESERVED,IRIS/PASSCAL, (),,, +XC,Tibetan Plateau Broadband Experiment,IRIS/PASSCAL, (),,, +XC,PANDA -- Hawaii Experiment,"University of Memphis, CERI",US (United States),,United States, +XC,Puget Sound BB Array,IRIS/PASSCAL, (),,, +XC,Southern Alps Passive Seismic Experiment,IRIS/PASSCAL, (),,, +XC,Namibia,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +XC,Geodynamics of the Yellowstone Hotspot from Seismic and GPS imaging,IRIS/PASSCAL, (),,,doi:10.7914/SN/XC_2000 +XC,Geodynamics of Indentor Corners,IRIS/PASSCAL, (),,,doi:10.7914/SN/XC_2002 +XC,Geodynamics of the Tibetan Plateau and the Origin of Great Earthquakes in Western China,Albuquerque Seismological Laboratory (ASL)/USGS,US (United States),,United States, +XC,Collaborative Research: Understanding the causes of continental intraplate tectonomagmatism: A case study in the Pacific Northwest,Arizona State University,US (United States),,United States,doi:10.7914/SN/XC_2006 +XC,Pacaya Tremor,"Michigan Technological University (MTU, Michigan USA)",US (United States),,United States,doi:10.7914/SN/XC_2011 +XC,Observing Pine Island Glacier (PIG) ice shelf deformation and fracture using a GPS and Seismic Network,New York University (NYU USA),US (United States),,United States,doi:10.7914/SN/XC_2012 +XC,"Pantanal, Chaco and Paraná (PCPB) structural studies network","IAG-USP (Institute of Astronomy, Geophysics & Atmospheric Science -Univ. of Sao Paulo)",BR (Brazil),http://www.moho.iag.usp.br/,Brazil, +XD,"Tararua BB Array, New Zealand", None, ( ),, , +XD,Tanzania BB Experiment,IRIS/PASSCAL, (),,, +XD,Iceland Hotspot,IRIS/PASSCAL, (),,, +XD,"Woodlark - D_Entrecasteaux Rift, PNG",IRIS/PASSCAL, (),,, +XD,"Broadband Seismic Studies of Dome Growth at Merapi Volcano, Indonesia",IRIS/PASSCAL, (),,,doi:10.7914/SN/XD_2001 +XD,Broadband Seismic Experiment in Various Regions in China,IRIS/PASSCAL, (),,,doi:10.7914/SN/XD_2002 +XD,Development of A Power and Communication for Remote Autonomous GPS and Seismic Stations in Antarctica,IRIS/PASSCAL, (),,,doi:10.7914/SN/XD_2007 +XD,Passive seismic study of a magma-dominated rift: the Salton Trough,Stanford University,US (United States),,United States,doi:10.7914/SN/XD_2011 +XD,Collaborative Research: Illuminating the architecture of the greater Mount St. Helens magmatic systems from slab to surface,University of Washington,US (United States),,United States,doi:10.7914/SN/XD_2014 +XE,PANDA -- New Madrid Experiment,"University of Memphis, CERI",US (United States),,United States, +XE,BBand Andean Joint Exp. / Seismic Exploration of Deep Andes,IRIS/PASSCAL, (),,, +XE,Askja/Bardardalur Iceland ,IRIS/PASSCAL, (),,, +XE,Eifel Plume,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +XE,Broadband Experiment Across Alaskan Range,IRIS/PASSCAL, (),,, +XE,Torfajokull 2002,Nordic Volcanological Institute (NORDVULK Iceland),IS (Iceland),,Iceland, +XE,Geodynamics of Indentor Corners,IRIS/PASSCAL, (),,,doi:10.7914/SN/XE_2003 +XE,Sierra Nevada EarthScope Project,EarthScope Transportable Array, (),,,doi:10.7914/SN/XE_2005 +XE,TICO-CAVA,Woods Hole Oceanographic Institution (WHOI),US (United States),,United States, +XE,Sierra Negra Array Galapagos,University of Rochester,US (United States),,United States,doi:10.7914/SN/XE_2009 +XE,"Seismic Activity of Low Angle Normal Faults in Death Valley, Caifornia.",University of Washington,US (United States),,United States,doi:10.7914/SN/XE_2012 +XE,Study of the Socorro Magma Body,University of Nevada (UNR Reno),US (United States),,United States,doi:10.7914/SN/XE_2015 +XF,Anza Borehole Experiment,IRIS/PASSCAL, (),,, +XF,"Penninsular Ranges, California",IRIS/PASSCAL, (),,, +XF,Antarctic Microearthquake Project,IRIS/PASSCAL, (),,, +XF,GEDEPTH-II,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +XF,Laramie Telemetered Broad-band Array,IRIS/PASSCAL, (),,, +XF,Collaborative Research: Lithospheric Scale Dynamics of Active Mountain Building along the Himalayan-Tibetan Collision Zone,IRIS/PASSCAL, (),,,doi:10.7914/SN/XF_2002 +XF,Mapping the Rivera Subduction Zone,IRIS/PASSCAL, (),,,doi:10.7914/SN/XF_2006 +XF,Red Seismological Experiment,"Universidad de Chile, Dept de Geofisica (DGF UChile Chile)",CL (Chile),,Chile, +XF,"Collaborative Research: Relating glacier-generated seismicity to ice motion, basal processes and iceberg calving.","University of Alaska, Fairbanks (UAF, AK USA)",US (United States),,United States,doi:10.7914/SN/XF_2009 +XF,Mantle serpentinization and water cycling through the Mariana Trench and Forearc,Washington University in St. Louis (WUSTL),US (United States),,United States,doi:10.7914/SN/XF_2012 +XF,Understanding Precambrian to Present Assembly of Greenland,Columbia University,US (United States),,United States,doi:10.7914/SN/XF_2014 +XG,Rocky Mountain Front,IRIS/PASSCAL, (),,, +XG,Anisotropy AI,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +XG,Nanga Parbat Pakistan ,IRIS/PASSCAL, (),,, +XG,Amazon,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +XG,Eastern Turkey Seismic Experiment,IRIS/PASSCAL, (),,, +XG,A Comparative Study of Natural and Man-Induced Seismicity in the Yanquing-Huailai Basin and the Haicheng Area,IRIS/PASSCAL, (),,,doi:10.7914/SN/XG_2002 +XG,Cascadia Array of Arrays,University of Washington,US (United States),,United States,doi:10.7914/SN/XG_2009 +XG,Underground Array,University of Minnesota-Twin Cities,US (United States),,United States, +XG,Barcelonnette 2014 aftershock sequence,"Sismos a l'Ecole, Geosciences Azur",FR (France),,France, +XG,Colorado River Runoff Pilot Project,"New Mexico Tech (NMT Mining & Technology NM,USA)",US (United States),,United States,doi:10.7914/SN/XG_2015 +XH,Colorado Plateau-Great Basin Network ,IRIS/PASSCAL, (),,, +XH,Bolivian Experiment,IRIS/PASSCAL, (),,, +XH,TransAlp-1,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +XH,ISSA2000,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +XH,START,IRIS/PASSCAL, (),,, +XH,Integrated Seismological Studies of Crust and Upper Mantle Structure in Western Anatolia,IRIS/PASSCAL, (),,,doi:10.7914/SN/XH_2002 +XH,Seismic Array Studies of Cascadia Deep Tremor,IRIS/PASSCAL, (),,,doi:10.7914/SN/XH_2004 +XH,Cascade Tiltmeter Array,Central Washington University,US (United States),,United States, +XH,Hawaiian South Flank Slow EQ Project,"University of Wisconsin, Madison",US (United States),,United States,doi:10.7914/SN/XH_2007 +XH,Lithospheric Structure above the variably dipping Nazca Slab,Purdue University,US (United States),,United States,doi:10.7914/SN/XH_2008 +XH,Seismic Survey of Greeland Icesheet Margins,"ETHZ (Swiss Federal Institute of Technology, Zurich Switzerland)",CH (Switzerland),,Switzerland, +XH,Small aperture array for observing a slow slip event on Kilauea volcano.,"University of Wisconsin, Madison",US (United States),,United States,doi:10.7914/SN/XH_2012 +XH,Collaborative Research: Mantle Structure and Dynamics of the Ross Sea from a Passive Seismic Deployment on the Ross Ice Shelf,Scripps Institution of Oceanography,US (United States),,United States,doi:10.7914/SN/XH_2014 +XI,GEDEPTH 1,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +XI,Saudi Arabia Broadband Array,IRIS/PASSCAL, (),,, +XI,NE China Seismic Experiment,IRIS/PASSCAL, (),,, +XI,Kenya Broadband Seismic Experiment,IRIS/PASSCAL, (),,,doi:10.7914/SN/XI_2000 +XI,TAG Hydrothermal Mound Passive Seismic Experiment,Woods Hole Oceanographic Institution (WHOI),US (United States),,United States, +XI,3D Tomographic Imaging of the Chicxulub Crater,Imperial College London (Imperial UK),GB (United Kingdom),,United Kingdom, +XI,"Characterization of High Frequency Noise Generated at the South Pole Station, Antarctica",IRIS HQ (DC),US (United States),,United States,doi:10.7914/SN/XI_2006 +XI,Collision of the Burma Arc accretionary prism and foldbelt with the Ganges-Brahmaputra Delta in Bangladesh,"Lamont Doherty Earth Observatory (LDEO), Columbia University",US (United States),,United States,doi:10.7914/SN/XI_2007 +XI,Superior Province Rifting Earthscope Experiment,Northwestern University,US (United States),,United States,doi:10.7914/SN/XI_2011 +XI,Long Beach Broadband or LA Syncline Seismic Interferometry Experiment,NodalSeismic,US (United States),,United States,doi:10.7914/SN/XI_2014 +XI,Enid OK Network,Cornell University,US (United States),,United States, +XJ,RESERVED,IRIS/PASSCAL, (),,, +XJ,Adirondack Broadband Array,IRIS/PASSCAL, (),,, +XJ,Sierran Paradox ,IRIS/PASSCAL, (),,, +XJ,Side Edge of Kamchatka Subduction Zone,IRIS/PASSCAL, (),,, +XJ,Shear-wave Splitting in the Snake River Plain,IRIS/PASSCAL, (),,,doi:10.7914/SN/XJ_2000 +XJ,Ethiopian Afar Geophysical Lithospheric Experiment,"Royal Holloway, University of London",GB (United Kingdom),,United Kingdom, +XJ,Seismic Experiment in the Aisen Region of Chile,University of Cambridge (UK) Earth Sciences,GB (United Kingdom),,United Kingdom, +XJ,Tomo TEIDEVS,University of Liverpool,GB (United Kingdom),,United Kingdom, +XJ,"Wells, Nevada Aftershock Recording",University of Nevada (UNR Reno),US (United States),,United States,doi:10.7914/SN/XJ_2008 +XJ,L Aquila Aftershock Experiment,"Observatoire de Grenoble, Grenoble",FR (France),,France, +XJ,High-resolution imaging of magma transport at the summit of Kilauea Volcano,USGS Hawaiian Volcano Observatory (HVO),US (United States),,United States,doi:10.7914/SN/XJ_2010 +XJ,Gulf of Mexico Hydrates Research Consortium,Woods Hole Oceanographic Institution (WHOI),US (United States),,United States, +XJ,Fuego Volcano VLP and tilt experiment,"Michigan Technological University (MTU, Michigan USA)",US (United States),,United States,doi:10.7914/SN/XJ_2012 +XJ,Magadi-Natron Magmatic Rifting Studies,University of Rochester,US (United States),,United States,doi:10.7914/SN/XJ_2013 +XJ,Impact of subglacial discharge on turbulent plume dynamics and ocean-glacier heat and mass transfer,University of Alaska Southeast (UAS),US (United States),,United States,doi:10.7914/SN/XJ_2016 +XK,RESERVED,IRIS/PASSCAL, (),,, +XK,"ICEMELT, Anarctica",IRIS/PASSCAL, (),,, +XK,"Chicxulub Impact Crater, Yucatan",IRIS/PASSCAL, (),,, +XK,Western Superior Teleseismic Experiment,IRIS/PASSCAL, (),,, +XK,Merapi and Semeru Volcano Project,IRIS/PASSCAL, (),,, +XK,CDROM (Colorado),IRIS/PASSCAL, (),,, +XK,Reflections Under the Scottish Highlands: A Broadband Investigation of Upper Mantle Reflectors in Scotland,IRIS/PASSCAL, (),,,doi:10.7914/SN/XK_2001 +XK,RISTRA 1.5 -- Colorado Plateau Extension,IRIS/PASSCAL, (),,,doi:10.7914/SN/XK_2004 +XK,POLENET/LAPNET,University of Oslo (Norway),NO (Norway),,Norway, +XK,Big Horn Project Regional Array Deployment,"Los Alamos National Laboratory (LANL, NM)",US (United States),,United States, +XK,"Passive seismic for geothermal exploration, Fairmont, Montana","Montana Bureau of Mines and Geology/Montana Tech (MBMG, MT USA)",US (United States),,United States,doi:10.7914/SN/XK_2011 +XK,"Passive seismic study of early rifting in Botswana, Zambia, and Malawi",Missouri University of Science & Technology(Former UM-Rolla)(Missouri S&T USA),US (United States),,United States,doi:10.7914/SN/XK_2012 +XK,Seismic Array of the Sevilleta,University of New Mexico (UNM),US (United States),,United States, +XL,Southern Seirra - Death Valley,IRIS/PASSCAL, (),,, +XL,North Korea Seismic Deployment,IRIS/PASSCAL, (),,, +XL,Deep Probe (Archean-Proterozoic),IRIS/PASSCAL, (),,, +XL,Santa Clara Valley,IRIS/PASSCAL, (),,, +XL,Oakland San Francisco Urban Seismic Array,IRIS/PASSCAL, (),,, +XL,COnsortium for Arizona Reconnaissance Seismic Experiment, None, ( ),, , +XL,Collaborative Research: Dynamic controls on tidewater glacier retreat,University of Colorado Boulder (CU),US (United States),,United States,doi:10.7914/SN/XL_2008 +XL,"Hangay Dome, Mongolia",Lehigh University,US (United States),,United States,doi:10.7914/SN/XL_2012 +XM,S. Island (N. Zealand) Pilot BB Network,IRIS/PASSCAL, (),,, +XM,Wabash Seismic Experiment,IRIS/PASSCAL, (),,, +XM,TOMOG 3D,IRIS/PASSCAL, (),,, +XM,Ocean Seismic Network Exp.,IRIS/PASSCAL, (),,,doi:10.7914/SN/XM_1998 +XM,Rio Grande Seismic Transect,IRIS/PASSCAL, (),http://www.iris.washington.edu/gmap/XM?timewindow=1999-2001,,doi:10.7914/SN/XM_1999 +XM,Ethiopia-Afar Geoscientific Lithospheric Experiment 6TD Passive Array,University of Leicester (SEIS UK),GB (United Kingdom),,United Kingdom, +XM,Vestmanna04 (SeiFaBa Project),University of Cambridge (UK) Earth Sciences,GB (United Kingdom),,United Kingdom, +XM,ALPASS,IRIS/PASSCAL, (),,, +XM,Western Tibet passive array deployment,IRIS/PASSCAL, (),,, +XM,Broadband recording at the site of great earthquake rupture in the Alaska Megathrust,University of Oklahoma (OU Oklahoma USA),US (United States),,United States,doi:10.7914/SN/XM_2011 +XM,ARGOS - Alutu and Regional Geophysical Observation Study SEIS-UK,University of Bristol (UK),GB (United Kingdom),,United Kingdom, +XM,Poroelastic Tomography at Brady Geothermal Field,"University of Wisconsin, Madison",US (United States),,United States,doi:10.7914/SN/XM_2016 +XN,TOR-0,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +XN,Biak Aftershock Survey,IRIS/PASSCAL, (),,, +XN,LARSE II - Passive Phase,IRIS/PASSCAL, (),,, +XN,Parkfield Passive Seismic Array,"University of Wisconsin, Madison",US (United States),,United States,doi:10.7914/SN/XN_2000 +XN,Collaborative Research: Canadian Northwest Seismic Experiment,IRIS/PASSCAL, (),,,doi:10.7914/SN/XN_2003 +XN,TaskForce_Java,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +XN,Bolivar: Western Venezuela,Rice University,US (United States),,United States,doi:10.7914/SN/XN_2008 +XN,Monitgoring seismicity associated with a possible asperity on the Cascadia megathrust,Oregon State University (OSU USA),US (United States),,United States,doi:10.7914/SN/XN_2010 +XN,joint summer field camp BSU/CSM/Imperial College of London,Boise State University,US (United States),,United States,doi:10.7914/SN/XN_2011 +XN,Dynamic Response of the Ross Ice Shelf to to Wave Induced Vibrations,Scripps Institution of Oceanography,US (United States),,United States,doi:10.7914/SN/XN_2014 +XN,Gorkha Earthquake 2015,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +XO,CINCA95,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +XO,ANCORP96-AN,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +XO,NOMAD,Brown University,US (United States),,United States,doi:10.7914/SN/XO_1997 +XO,Santa Clara Valley 2000,USGS Menlo Park,US (United States),,United States,doi:10.7914/SN/XO_2000 +XO,US-Japan Collaborative Research: Multi-scale seismic imaging of the Mariana Subduction Factory,IRIS/PASSCAL, (),,,doi:10.7914/SN/XO_2003 +XO,Eastern Black Sea Seismic Experiment,University of Southampton (UK),GB (United Kingdom),,United Kingdom, +XO,NOISY,Stanford University,US (United States),,United States, +XO,INDEPTH IV ,University of Cambridge (UK) Earth Sciences,GB (United Kingdom),,United Kingdom, +XO,"Deep Fault Drilling Project, Alpine Fault, New Zealand: Whataroa-Wanganui Passive Seismology Experiment 2010",Victoria University of Wellington (VUW New Zealand),NZ (New Zealand),,New Zealand,doi:10.7914/SN/XO_2010 +XO,Structure and Dynamics of the North American Craton,Indiana University Bloomington (IU Bloomington),US (United States),,United States,doi:10.7914/SN/XO_2011 +XP,"Taupo Volcanic Zone, New Zealand. Panda project",IRIS/PASSCAL, (),,, +XP,TaskForce Adana 1998,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +XP,A Broadband Seismic Investigation of Deep Continental Structure Across the East-West Antarctic Boundary,IRIS/PASSCAL, (),,,doi:10.7914/SN/XP_2000 +XP,Discrete vs. Continuous Continental Deformation and the Role of the Lower Crust in the Tien Shan,IRIS/PASSCAL, (),,,doi:10.7914/SN/XP_2005 +XP,Colorado Rockies Experiment and Seismic Transect,"New Mexico Tech (NMT Mining & Technology NM,USA)",US (United States),,United States,doi:10.7914/SN/XP_2008 +XP,Investigating the relationship between pluton growth and volcanism at two active intrusions in the central Andes,"University of Alaska, Fairbanks (UAF, AK USA)",US (United States),,United States,doi:10.7914/SN/XP_2010 +XP,VocArray,"Observatoire de Grenoble, Grenoble",FR (France),,France, +XP,Seismic Experiment for Imaging Structure beneath Connecticut,Yale University,US (United States),,United States, +XQ,Green River Experiment,IRIS/PASSCAL, (),,, +XQ,Hikurangi Subduction System (New Zealand) Seismic Transects,IRIS/PASSCAL, (),,,doi:10.7914/SN/XQ_2001 +XQ,Oregon Array for Teleseismic Study,"University of Wisconsin, Madison",US (United States),,United States, +XQ,Collaborative Research: Understanding Fault Zone Compliance by Seismic Probing of InSAR Anomalies,IRIS/PASSCAL, (),,,doi:10.7914/SN/XQ_2006 +XQ,Seismic and Geodetic Investigations of Mendocino Triple Junction Dynamics,University of Oregon,US (United States),,United States,doi:10.7914/SN/XQ_2007 +XQ,Pismo BeachNet,Cuesta Community college,US (United States),,United States, +XQ,NEESR-CR: Topographic Effects in Strong Ground Motion - From Physical and Numerical Modeling to Design,University of Arkansas - Fayetteville,US (United States),,United States,doi:10.7914/SN/XQ_2011 +XQ,Pre-Hydrofracking Regional Assessment of Central Carolina Seismicity,University of North Carolina at Chapel Hill (UNC),US (United States),,United States, +XQ,"Rapid response to the Mw 7.9 earthquake of April 25, 2015 in Nepal",Oregon State University (OSU USA),US (United States),,United States, +XR,INDEPTH II,IRIS/PASSCAL, (),,, +XR,INDEPTH III,IRIS/PASSCAL, (),,, +XR,The Florida to Edmonton Broadband Experiment,IRIS/PASSCAL, (),,,doi:10.7914/SN/XR_2001 +XR,Mammoth 2003,IRIS/PASSCAL, (),,, +XR,CSEDI: Observational and Theoretical Constraints on the Structure and Rotation of the Inner Core,IRIS/PASSCAL, (),,,doi:10.7914/SN/XR_2004 +XR,Seismic Investigation of Edge Driven Convection Associated with the Rio Grande Rift.,University of Texas at Austin,US (United States),,United States,doi:10.7914/SN/XR_2008 +XR,Deployment of a simultaneous broadband gradiometers to quantify the effects of aperture and near-surface geology on gradient-der,East Carolina University (ECU),US (United States),,United States,doi:10.7914/SN/XR_2012 +XR,"Bowdoin glacier, NE Greenland","ETHZ (Swiss Federal Institute of Technology, Zurich Switzerland)",CH (Switzerland),http://www.vaw.ethz.ch/people/gz/funk/projects/data/gz_bowdoin,Switzerland, +XR,Seismicity near the Nemaha fault in northern Oklahoma,Cornell University,US (United States),,United States,doi:10.7914/SN/XR_2016 +XS,"Erebus, Antarctica",IRIS/PASSCAL, (),,, +XS,"Sangay Volcano, Ecuador",IRIS/PASSCAL, (),,, +XS,Montana BB Array,IRIS/PASSCAL, (),,, +XS,Embayment Seismic Excitation Experiment,"University of Memphis, CERI",US (United States),,United States,doi:10.7914/SN/XS_2002 +XS,Source Phenomenology Experiments in Arizona,IRIS/PASSCAL, (),,,doi:10.7914/SN/XS_2003 +XS,Tungurahua 2004,IRIS/PASSCAL, (),,, +XS,San Jose Microtremor 2005,IRIS/PASSCAL, (),,, +XS,Multi-disciplinary Experiments for Dynamic Understanding of Subduction under the Aegean Sea,"Massachusetts Institute of Technology (MIT, USA)",US (United States),,United States,doi:10.7914/SN/XS_2006 +XS,Maule Earthquake (Chile) Aftershock Experiment,"Observatoire de Grenoble, Grenoble",FR (France),,France, +XS,Geysers Broadband Network,ARRAY Information Technology (MD),US (United States),,United States, +XS,Passive Imaging of the Lithosphere-Asthenosphere Boundary,University of Southampton (UK),GB (United Kingdom),,United Kingdom, +XT,Micronesia Seismic Network,IRIS/PASSCAL, (),,, +XT,Colorado BB Array - Lodore,IRIS/PASSCAL, (),,, +XT,SIGAR (Kenya),IRIS/PASSCAL, (),,, +XT,Tonga-Fiji Dual Array Experiment,IRIS/PASSCAL, (),,,doi:10.7914/SN/XT_2001 +XT,Crust-Mantle Interactions during Continental Growth and High-Pressure Rock Exhumation at an Oblique Arc-Continent Collision Zone: SE Caribbean Margin,IRIS/PASSCAL, (),,,doi:10.7914/SN/XT_2003 +XT,Oregon Array for Teleseismic Study II,UC Berkeley,US (United States),,United States, +XT,Fuego Volcano 2009,"Michigan Technological University (MTU, Michigan USA)",US (United States),,United States,doi:10.7914/SN/XT_2009 +XT,"Retrieval of reflections from seismic background-noise measurements for geophysical imaging of Fault Systems in Reno, NV",University of Nevada (UNR Reno),US (United States),,United States,doi:10.7914/SN/XT_2010 +XT,Western Idaho Shear Zone - Passive,University of Florida,US (United States),,United States,doi:10.7914/SN/XT_2011 +XT,EASI - Eastern Alpine Seismic Investigation,Swiss Seismological Service,CH (Switzerland),,Switzerland, +XU,New Zealand Seismic Experiment,IRIS/PASSCAL, (),,, +XU,Trans-Antarctic ,Institute of Geological and Nuclear Science (GNS - New Zealand),NZ (New Zealand),,New Zealand, +XU,Monitoring MEQ activity during pulsed injection at geothermal reservoirs,"Lawrence Berkeley Laboratory (LBNL, CA USA)",US (United States),,United States, +XU,TaskForce Alsdorf 2002,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +XU,"2003 Fort Payne, AL, Aftershock Network","University of Memphis, CERI",US (United States),,United States, +XU,Deception Island Passive/Active Source,University of Washington,US (United States),,United States, +XU,"Collaborative Research: Earthscope integrated investigations of Cascadia subduction zone tremor, structure and process",University of Washington,US (United States),,United States,doi:10.7914/SN/XU_2006 +XU,Jakarta Experiment,"Australian National University (ANU, Australia)",AU (Australia),,Australia, +XU,Greeley Colorado RAMP Deployment 2014,University of Colorado Boulder (CU),US (United States),,United States,doi:10.7914/SN/XU_2014 +XU,USGS NEHRP Proposal 2016-0180 - Greeley,University of Colorado,US (United States),,United States,doi:10.7914/SN/XU_2016 +XV,Panama Canal Experiment,IRIS/PASSCAL, (),,, +XV,Kilauea East Rift,IRIS/PASSCAL, (),,, +XV,Tacoma Array,USGS Menlo Park,US (United States),,United States, +XV,Collaborative research of the Earth's largest icebergs,IRIS/PASSCAL, (),,,doi:10.7914/SN/XV_2003 +XV,Glacier Seismicity and High Resolution Motion Records: Relation to Glacier Erosion,"University of Alaska, Fairbanks (UAF, AK USA)",US (United States),,United States,doi:10.7914/SN/XV_2007 +XV,Collaborative Research: Geometry and kinematics of basement-involved foreland arches:Insights into continental processes from Earthscope.,Colorado College,US (United States),,United States,doi:10.7914/SN/XV_2009 +XV,"INVESTIGATION OF SOURCES OF INTRAPLATE VOLCANISM USING PASSCAL BROADBAND INSTRUMENTS IN MADAGASCAR, THE COMORES, AND MOZAMBIQUE",Washington University in St. Louis (WUSTL),US (United States),,United States,doi:10.7914/SN/XV_2011 +XV,Fault Locations and Alaska Tectonics from Seismicity,"University of Alaska, Fairbanks (UAF, AK USA)",US (United States),,United States,doi:10.7914/SN/XV_2014 +XW,Tien Shan Continental Dynamics,IRIS/PASSCAL, (),,, +XW,"Siple Coast Antarctica, Microearthquake Project",IRIS/PASSCAL, (),,, +XW,Seismic Imaging of the Mantle Beneath the Anatolian-Aegan Domain,"Observatoire de Grenoble, Grenoble",FR (France),,France, +XW,Young Conjugate Margins Lab in the Gulf of Aden,University of Southampton (UK),GB (United Kingdom),,United Kingdom,doi:10.7914/SN/XW_2009 +XW,CRESIS Greenland 2012,Penn State University,US (United States),,United States,doi:10.7914/SN/XW_2012 +XW,ESG Bayou Corne,ESG Solutions (Canada),CA (Canada),,Canada, +XW,Chile as a laboratory for understanding the impact of geology on slip prior to and during megathrust,,,,, +XY,Northern Baja Transect,IRIS/PASSCAL, (),,, +XY,"Nicoya, Costa Rica",IRIS/PASSCAL, (),,, +XY,Mongolia-Baikal Lithospheric Transect,"Sismos a l'Ecole, Geosciences Azur",FR (France),,France, +XY,"Seismic Imaging of Fractures at Krafla, Iceland",IRIS/PASSCAL, (),,,doi:10.7914/SN/XY_2004 +XY,Magma Accretion and the Formation of Batholiths,IRIS/PASSCAL, (),,,doi:10.7914/SN/XY_2005 +XY,Seismic Imagining of the Mantle Beneath the Anatolian-Aegan Domain,"Observatoire de Grenoble, Grenoble",FR (France),,France, +XY,RAMP response for 2010 earthquake,University of Florida,US (United States),,United States,doi:10.7914/SN/XY_2010 +XY,"Experiment to Determine Hypocenters and Focal Mechanisms of Earthquakes Occurring in Association with Imaged Faults Near Summeville, South Carolina",Virginia Polytechnic Institute and State University (VPI&SU or Virginia Tech),US (United States),,United States,doi:10.7914/SN/XY_2011 +XY,PASEIS,Penn State University,US (United States),,United States, +XZ,Cascadia/SEED reformat,Arizona State University,US (United States),,United States, +XZ,"Erebus II, Anarctica",IRIS/PASSCAL, (),,, +XZ,Spokane WA Earthquake Swarm,IRIS/PASSCAL, (),,,doi:10.7914/SN/XZ_2001 +XZ,DHOFAR Seismic Experiment,Institut de Physique du Globe de Paris,FR (France),,France, +XZ,Collaborative Research: St. Elias Erosion/Tectonics Project,"University of Alaska, Fairbanks (UAF, AK USA)",US (United States),,United States,doi:10.7914/SN/XZ_2005 +XZ,Gulf of Mexico USGS Hydrates,USGS Woods Hole,US (United States),,United States, +XZ,Idaho Teton Dam,Southern Methodist University (SMU TX),US (United States),,United States,doi:10.7914/SN/XZ_2014 +XZ,Measuring ambient noise of ocean breakers,East Carolina University (ECU),US (United States),,United States,doi:10.7914/SN/XZ_2015 +XZ,Volatile recycling at the Lesser Antilles Arc: Processes and consequences,Imperial College London (Imperial UK),GB (United Kingdom),,United Kingdom, +Y1,SCANLIPS2,University of Leicester (SEIS UK),GB (United Kingdom),,United Kingdom, +Y1,Libris,Institut des Sciences de la Terre,FR (France),,France, +Y1,Rock Arches Resonance,University of Utah,US (United States),,United States, +Y2,Collaborative Research: Imaging the Upper Mantle Beneath the Western Tibetan Plateau,Rutgers University,US (United States),,United States,doi:10.7914/SN/Y2_2007 +Y2,Green County Observation,University of Pittsburgh (Pitt PA),US (United States),,United States, +Y2,Balcombe,University of Bristol (UK),GB (United Kingdom),,United Kingdom,doi:10.7914/SN/Y2_2013 +Y2,Safe-CO2,Universite Joseph Fourier - Grenoble (LGIT-UJF-France),FR (France),,France, +Y3,"Studies of crust and upper mantle structure, mantle flow and geodynamics of the Chile Ridge subduction zone",University of Florida,US (United States),,United States,doi:10.7914/SN/Y3_2007 +Y3,"Wells, Nevada Aftershock Recording","New Mexico Tech (NMT Mining & Technology NM,USA)",US (United States),,United States,doi:10.7914/SN/Y3_2008 +Y3,"Collaborative Research: Constraining Mantle Rheology, Mantle Flow, and Crust/Mantle coupling Beneath New Zealand",University of Colorado Boulder (CU),US (United States),,United States,doi:10.7914/SN/Y3_2009 +Y3,Vaughn-Lewis Icefall Seismicity Project,Stanford University,US (United States),,United States,doi:10.7914/SN/Y3_2012 +Y3,SEIS-UK instrument type noise study,Leicester University ,GB (United Kingdom),,United Kingdom,doi:10.7914/SN/Y3_2013 +Y4,Alpes04,"Observatoire de Grenoble, Grenoble",FR (France),,France, +Y4,Mt. Erebus Volcano Observatory,"New Mexico Tech (NMT Mining & Technology NM,USA)",US (United States),,United States,doi:10.7914/SN/Y4_2008 +Y4,Eastern Mediterranean Seismic,"Weston Geophysical Engineers, Inc",US (United States),,United States,doi:10.7914/SN/Y4_2010 +Y4,Brazilian Temporary Seismographic Experiments,"Universidade de Sao Paulo, USP",BR (Brazil),,Brazil, +Y4,"Extended Pollino Seismic Experiment, 2014-2015","GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +Y5,Canadian Rockies and Alberta Network,University of Alberta (UAlberta Canada),CA (Canada),,Canada, +Y6,Behavior of supraglacial lakes and their role in outlet glacier dynamics and mass balance of the Greenland Ice Sheet,Woods Hole Oceanographic Institution (WHOI),US (United States),,United States,doi:10.7914/SN/Y6_2006 +Y6,QM-III-UK,Imperial College London (Imperial UK),GB (United Kingdom),,United Kingdom, +Y7,Seismic Experiment Active Caribbean Andesitic Lava Island Perscison Seismio-Geodetic Observatory,Penn State University,US (United States),,United States,doi:10.7914/SN/Y7_2007 +Y7,Geothermal Exploration Arkansas Valley,Colorado School of Mines (CSM),US (United States),,United States,doi:10.7914/SN/Y7_2009 +Y7,Deep OCean Test ARray experiment,Universitat Potsdam,DE (Germany),,Germany, +Y7,MOCHA MT Observations of Cascadia Using a Huge Array,Oregon State University (OSU USA),US (United States),,United States, +Y8,BBMOMAR,Institut de Physique du Globe de Paris,FR (France),,France, +Y8,Detection and location of non-volcanic tremor in the New Madrid Seismic Zone,"University of Memphis, CERI",US (United States),,United States,doi:10.7914/SN/Y8_2009 +Y8,"Passive-Source Guided Wave Study along the San Andreas Fault in San Gorgonio Pass, California",UC Riverside,US (United States),,United States,doi:10.7914/SN/Y8_2013 +Y9,Tocopilla,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +Y9,Guerrero Gap Experiment (Mexico),"Observatoire de Grenoble, Grenoble",FR (France),,France, +YA,Coso Passive Short Period Arrays,IRIS/PASSCAL, (),,, +YA,Bhuj Aftershock Study,IRIS/PASSCAL, (),,, +YA,"Collaborative research in Eastern Tibet: Evolution and dynamics of the crust and mantle, and surface topography.",IRIS/PASSCAL, (),,,doi:10.7914/SN/YA_2003 +YA,Torfajokull 2005,Nordic Volcanological Institute (NORDVULK Iceland),IS (Iceland),,Iceland, +YA,Transylvanian Basin Attenuation and Anisotropy Deployment,University of Florida,US (United States),,United States, +YA,HLP-3,Stanford University,US (United States),,United States, +YA,Undervolc,"Observatoire de Grenoble, Grenoble",FR (France),,France, +YA,Dynamics of the Lake Kivu System,University of Rochester,US (United States),,United States,doi:10.7914/SN/YA_2012 +YA,Fuego Volcano VLP and tilt experiment Continued,"Michigan State University (MSU, Michigan USA)",US (United States),,United States, +YB,Black Thunder Mine,IRIS/PASSCAL, (),,, +YB,South Africa Seismic Experiment - Kimberley Telemetered Array,IRIS/PASSCAL, (),,, +YB,Central Zagros 2001 transect,Universite Joseph Fourier - Grenoble (LGIT-UJF-France),FR (France),,France, +YB,"Puerto Plata, Dominican Republic Aftershock Study - RAMP",IRIS/PASSCAL, (),,,doi:10.7914/SN/YB_2003 +YB,Cavola Broadband Array on a Landslide,INGV Instituto Nazionale di Geofisica e Vulcanologia (Italy),IT (Italy),,Italy, +YB,Mount Saint Helens Dense Array,USGS Menlo Park,US (United States),,United States,doi:10.7914/SN/YB_2005 +YB,Haiti Earthquake Aftershock Experiment,"Observatoire de Grenoble, Grenoble",FR (France),,France, +YB,Faroe Islands Passive Seismic Experiment,University of Leeds,GB (United Kingdom),,United Kingdom, +YB,Continental Dynamics/Central Anatolian Tectonics: Surface to mantle dynamics during collision to escape,University of Missouri (MU) (Mizzou),US (United States),,United States,doi:10.7914/SN/YB_2013 +YB,Evolution of Slow-Spreading Oceanic Crust: South Atlantic,Texas A&M University,US (United States),,United States,doi:10.7914/SN/YB_2016 +YC,"Osa Penninsula, Costa Rica",IRIS/PASSCAL, (),,, +YC,Slab Geometry in the Southern Andes,IRIS/PASSCAL, (),,,doi:10.7914/SN/YC_2000 +YC,Eastern Oregon Mantle Experiment,IRIS/PASSCAL, (),,,doi:10.7914/SN/YC_2003 +YC,RABID,British Antarctic Survey (BAS UK),GB (United Kingdom),,United Kingdom, +YC,Partnership in Research and Education in Volcanology,"University of Alaska, Fairbanks (UAF, AK USA)",US (United States),,United States,doi:10.7914/SN/YC_2006 +YC,RAMP Virginia,IRIS PASSCAL Instrument Center @ New Mexico Tech,US (United States),,United States,doi:10.7914/SN/YC_2011 +YC,Texas Brine Corporation Louisiana Seismic Network,Nanometrics Seismological Instruments,CA (Canada),,Canada, +YD,"Koacelli, Turkey",IRIS/PASSCAL, (),,, +YD,Calabria-Appennine-Tyrrhenian/Subduction-Collision-Accretion Network,IRIS/PASSCAL, (),,,doi:10.7914/SN/YD_2003 +YD,"Toward Understanding Eruption Seismicity: Multidiscplinary Experiment at Santiaguito and Fuego Volcanos, Guatemala",University of New Hampshire (UNH),US (United States),,United States,doi:10.7914/SN/YD_2007 +YD,Recording Mogul Events throughout the Reno Basin,University of Nevada (UNR Reno),US (United States),,United States,doi:10.7914/SN/YD_2008 +YD,South Carpathian Project,University of Leeds,GB (United Kingdom),,United Kingdom, +YD,Whillians Ice Stream Subglacial Access Research Drilling,UC Santa Cruz,US (United States),,United States,doi:10.7914/SN/YD_2012 +YE,Seattle Site Response, None, ( ),, , +YE,Upper Geyser Basin Seismicity,IRIS/PASSCAL, (),,, +YE,"Water storage and routing within glaciers via planar voids, a new model of glacier hydrology",Boise State University,US (United States),,United States,doi:10.7914/SN/YE_2007 +YE,"Title: NEESR-SG: High Fidelity site characterization by experimentation, field observation, and inversion-based modeling",UC Santa Barbara,US (United States),,United States,doi:10.7914/SN/YE_2008 +YE,SeaJade I,Geological Survey of Canada,CA (Canada),,Canada, +YE,Testing TA & FA vaults and directly buried sensor (3T),IRIS PASSCAL Instrument Center @ New Mexico Tech,US (United States),,United States,doi:10.7914/SN/YE_2011 +YF,Midsea - Mantle Investigation of the Deep Suture between Eurasia and Africa,Eidgendssisch Technische Hochschule (ETH Zurich) - Swiss Seismological Service,CH (Switzerland),,Switzerland, +YF,Yellowstone RAMP,IRIS/PASSCAL, (),,,doi:10.7914/SN/YF_2003 +YF,Northern IL. aftershock survey,"University of Memphis, CERI",US (United States),,United States, +YF,A new survey studies the Northeastern Caribbean plate: GEOPRICO-DO Project,Woods Hole Oceanographic Institution (WHOI),US (United States),,United States, +YF,SCANLIPS,University of Leicester (SEIS UK),GB (United Kingdom),,United Kingdom, +YF,Recognition of the lithosphere-asthenosphere system in the transition between Proterozoic and Phanerozoic Europe - Passive Seismic Experiment in TESZ 2006-2007,"Institute of Geophysics, Polish Academy of Sciences (IGF PAN Poland)",PL (Poland),,Poland,doi:10.7914/SN/YF_2007 +YF,Seismic Signature of Landslides,USGS Menlo Park,US (United States),,United States, +YF,Carboneras Fault Experiment,University of Liverpool,GB (United Kingdom),,United Kingdom, +YF,Observation of a glacier calving event using a network of GPS and Seismic sensors,New York University (NYU USA),US (United States),,United States,doi:10.7914/SN/YF_2012 +YG,South Bay Seismic Array,IRIS/PASSCAL, (),,, +YG,Carpathian Basins Project Regional Array,University of Leeds (UK),GB (United Kingdom),,United Kingdom, +YG,Imaging the Upper Crust at Newberry Volcano Using Large Offset Reflections,University of Oregon,US (United States),,United States, +YG,Gauging Rutford Ice Stream Transients,British Antarctic Survey (BAS UK),GB (United Kingdom),,United Kingdom, +YG,San Andreas Virtual Earthquake Experiment Los Angeles,Stanford University,US (United States),,United States, +YG,Collaborative Research: Imaging the Cascadia subduction zone - a ship-to-shore opportunity,Oregon State University (OSU USA),US (United States),,United States,doi:10.7914/SN/YG_2012 +YG,Deployment for the Southern Cook Strait Earthquake Sequence,Victoria University of Wellington (VUW New Zealand),NZ (New Zealand),,New Zealand,doi:10.7914/SN/YG_2013 +YG,Fate and consequences of Yakutat terrane subduction beneath eastern Alaska and the Wrangell Volcanic Field,"University of Alaska, Fairbanks (UAF, AK USA)",US (United States),,United States, +YH,Imaging Galapagos Upwelling & Neotectonics,University of Oregon,US (United States),,United States, +YH,Seismic tomography and location calibration around the SAFOD site,"University of Wisconsin, Madison",US (United States),,United States,doi:10.7914/SN/YH_2004 +YH,LaBarge Experiment,University of Arizona,US (United States),,United States,doi:10.7914/SN/YH_2008 +YH,Africa Array SE Tanzania Basin Experiment,Penn State University,US (United States),,United States, +YH,Dense Array for North Anatolia,University of Leeds (UK),GB (United Kingdom),,United Kingdom,doi:10.7914/SN/YH_2012 +YH,Hikurangi Ocean Bottom Investigation of Tremor and Slow Slip,University of Texas at Austin,US (United States),,United States,doi:10.7914/SN/YH_2014 +YI,Antarctic Network of Broadband Seismometers,IRIS/PASSCAL, (),,, +YI,"Retreating-Trench, Extension, and Accretion LTectonics: A Multidisciplinary Study of the Northern Apennines",IRIS/PASSCAL, (),,,doi:10.7914/SN/YI_2003 +YI,GEOPRICO2,Woods Hole Oceanographic Institution (WHOI),US (United States),,United States, +YI,SIMBAAD-Etransect (Seismic Imaging of the Mantle Beneath the Anatolian-Aegan Domain),"Observatoire de Grenoble, Grenoble",FR (France),,France, +YI,2009 Malawi Earthquake RAMP Response,Columbia University,US (United States),,United States,doi:10.7914/SN/YI_2010 +YI,DAFNE,Sodankyla Geophysical Observatory / University of Oulu (Finland),FI (Finland),,Finland, +YI,St Guérin dam experiment,Universite Joseph Fourier - Grenoble (LGIT-UJF-France),FR (France),,France, +YJ,Turkey RAMP Deployment,IRIS/PASSCAL, (),,, +YJ,Ethiopia-Afar Geoscientific Lithospheric Experiment,IRIS/PASSCAL, (),,, +YJ,"Studies of crust and upper mantle structure, mantle flow and geodynamics of the Chile Ridge subduction zone",IRIS/PASSCAL, (),,,doi:10.7914/SN/YJ_2004 +YJ,"Record ground motion, strain changes, fault slip, temperature changes, and othere parameter close to the seismic source for earthquakess in the magnitude range expending to 3",USGS Menlo Park,US (United States),,United States,doi:10.7914/SN/YJ_2007 +YJ,Bench Glacier Monitoring,Boise State University,US (United States),,United States, +YJ,Infrasound From Earthquakes: Signal Characteristics and Depth Discrimination,University of Utah,US (United States),,United States,doi:10.7914/SN/YJ_2010 +YJ,SLIDEQUAKES,Institut de Physique du Globe de Paris,FR (France),,France, +YK,Coordinated Seismic Experiment in the Azores,Eidgendssisch Technische Hochschule (ETH Zurich) - Swiss Seismological Service,CH (Switzerland),,Switzerland, +YK,Investigation of Crustal Structure and Site Response in the San Francisco North Bay,USGS Menlo Park,US (United States),,United States,doi:10.7914/SN/YK_2003 +YL,"Himalayan Seismotectonics, Nepal and Tibet",IRIS/PASSCAL, (),,,doi:10.7914/SN/YL_2001 +YL,San Simeon Aftershocks,USGS Menlo Park,US (United States),,United States, +YL,"Continental lithospheric deformation along a major strike-slip fault zone: the central North Anatolian Fault Zone, Turkey",University of Arizona,US (United States),,United States,doi:10.7914/SN/YL_2005 +YL,Lau Basin OBS Experiment,Woods Hole Oceanographic Institution (WHOI),US (United States),,United States, +YL,Santiaguito 2012,University of North Carolina at Chapel Hill (UNC),US (United States),,United States,doi:10.7914/SN/YL_2012 +YL,"Seismo_acoustic experiment and initial monitoring effort at Pagan Volcano, Commonwealth of the Northern Mariana Islands",USGS Alaska Anchorage,US (United States),,United States,doi:10.7914/SN/YL_2013 +YL,Parnaiba Basin WARR profile,University of Aberdeen (UK),GB (United Kingdom),,Northeast Brazil,doi:10.7914/SN/YL_2015 +YM,Central North Island Passive Seismic Exp, None, ( ),, , +YM,Denali RAMP,IRIS/PASSCAL, (),,,doi:10.7914/SN/YM_2002 +YM,Columbia Glacier Seismic Experiment,IRIS/PASSCAL, (),,,doi:10.7914/SN/YM_2004 +YM,Taiwan Supplement #2 to TAIGER project,IRIS/PASSCAL, (),,,doi:10.7914/SN/YM_2006 +YM,"An Integrated Analysis of Low-Frequency Seismicity at Villarrica Volcano, Chile","Michigan Technological University (MTU, Michigan USA)",US (United States),,United States,doi:10.7914/SN/YM_2010 +YM,Physical controls on ocean-terminating glacier variability in central west greenland,"University of Alaska, Fairbanks (UAF, AK USA)",US (United States),,United States,doi:10.7914/SN/YM_2013 +YN,Seismic Experiment in Patagonia and Antarctica,Washington University in St. Louis (WUSTL),US (United States),,United States, +YN,Socorro Magma Body,IRIS/PASSCAL, (),,,doi:10.7914/SN/YN_2005 +YN,Reverberation method development,USGS Golden Colorado,US (United States),,United States,doi:10.7914/SN/YN_2008 +YN,Juan de Fuca Passive Source Tomography Experiment,Woods Hole Oceanographic Institution (WHOI),US (United States),,United States, +YN,Collaborative Research: Structural Architecture and Evolutionary Plate-Boundary Processes along the San Jacinto Fault Zone,UC San Diego,US (United States),,United States,doi:10.7914/SN/YN_2010 +YO,Taranaki,University of Cambridge (UK) Earth Sciences,GB (United Kingdom),,United Kingdom, +YO,Imaging the mantle in the Central American Subduction Factory,IRIS/PASSCAL, (),,,doi:10.7914/SN/YO_2003 +YO,Mogul west Reno ,University of Nevada (UNR Reno),US (United States),,United States,doi:10.7914/SN/YO_2008 +YO,"Volacano Geophysics Field Course and Digital Signal Processing at Tungurahua, Ecuador",Boise State University,US (United States),,United States,doi:10.7914/SN/YO_2009 +YO,Tidewater glacier and ice marginal dynamic behavior,USACE - Cold Regions Research and Engineering Laboratory (CRREL),US (United States),,United States,doi:10.7914/SN/YO_2010 +YO,Sakurajima Infrasound Network,"University of Alaska, Fairbanks (UAF, AK USA)",US (United States),,United States, +YO,Eastern North American Margin Community Seismic Experiment,University of Texas at Austin,US (United States),,United States,doi:10.7914/SN/YO_2014 +YP,Southern Apennines Tomography Experiment,Istituto Nazionale di Geofisica e Vulcanologia (INGV),IT (Italy),,Italy, +YP,NISD,Multimax Inc (MD USA),US (United States),,United States, +YP,NTS October 2008,"Los Alamos National Laboratory (LANL, NM)",US (United States),,United States, +YP,"Collaborative Research: Northeast China Extended Seismic Array: Deep subduction, mantle dynamics and lithospheric evolution beneath Northeast China",Rice University,US (United States),,United States,doi:10.7914/SN/YP_2009 +YP,CIFALPS,Institut des Sciences de la Terre,FR (France),,France, +YP,Argostoli earthquake aftershock experiment,Institut des Sciences de la Terre,FR (France),,France, +YQ,Himalaya Tectonic,IRIS/PASSCAL, (),,, +YQ,Katla 2003,Nordic Volcanological Institute (NORDVULK Iceland),IS (Iceland),,Iceland, +YQ,Deep crustal structure of the northernmost Basin and Range and its relation to extensional faulting,IRIS/PASSCAL, (),,,doi:10.7914/SN/YQ_2004 +YQ,Nicoya Peninsula Seismic Network,UC Santa Cruz,US (United States),,United States, +YQ,Lincoln Noise Study,University of Leicester (SEIS UK),GB (United Kingdom),,United Kingdom,doi:10.7914/SN/YQ_2009 +YQ,Development of a low cost method to estimate the seismic signature of a geothermal field from ambient seismic noise analysis,University of Nevada (UNR Reno),US (United States),,United States,doi:10.7914/SN/YQ_2012 +YQ,Study of Extension and maGmatism in Malawi aNd Tanzania,"Lamont Doherty Earth Observatory (LDEO), Columbia University",US (United States),,United States,doi:10.7914/SN/YQ_2013 +YR,"Horn of Africa (Ethiopa, Yemen) broad-band experiment",IPGS (Institut de Physique du Globe de Strasbourg) ,FR (France),,France, +YR,Petrophysical and Seismic Properties of Faroes Basalts,University of Cambridge (UK) Earth Sciences,GB (United Kingdom),,United Kingdom, +YR,Northern Lake Tahoe Magma Injection Seismic Monitoring Network,University of Nevada (UNR Reno),US (United States),,United States, +YR,Dhofar Seismic Experiment II,Institut de Physique du Globe de Paris,FR (France),,France, +YR,ALFA08,Institute of Geological and Nuclear Science (GNS - New Zealand),NZ (New Zealand),,New Zealand,doi:10.7914/SN/YR_2008 +YR,Eritrea Seismic Project,Imperial College London (Imperial UK),GB (United Kingdom),,United Kingdom, +YR,DOMERAPI,Institut des Sciences de la Terre,FR (France),,France, +YS,Observational Constraints on Persistent Water Level Changes Generated by Seismic Waves,IRIS/PASSCAL, (),,,doi:10.7914/SN/YS_2001 +YS,Plume Lithosphere Undersea Melt Experiment ,Woods Hole Oceanographic Institution (WHOI),US (United States),,United States, +YS,Andravida (Greece) Aftershock Experiment,"Observatoire de Grenoble, Grenoble",FR (France),,France, +YS,The life cycle of Andean volcanoes:Combining space-based and field studies,Cornell University,US (United States),,United States,doi:10.7914/SN/YS_2009 +YS,Transitions in the Banda Arc-Australia continental collision,USC - University of Southern California,US (United States),,United States,doi:10.7914/SN/YS_2014 +YT,West Kunlun 2001 transect,Universite Joseph Fourier - Grenoble (LGIT-UJF-France),FR (France),,France, +YT,MOBAL 03,"Sismos a l'Ecole, Geosciences Azur",FR (France),,France, +YT,Parkfield Trapped Waves,IRIS/PASSCAL, (),,,doi:10.7914/SN/YT_2004 +YT,Herdubreid 2006,University of Cambridge (UK) Earth Sciences,GB (United Kingdom),,United Kingdom, +YT,IPY POLENET-Antarctica: Investigating links between geodynamics and ice sheets,Washington University in St. Louis (WUSTL),US (United States),,United States,doi:10.7914/SN/YT_2007 +YU,Several Greek networks,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +YU,Erta Ale,IRIS/PASSCAL, (),,, +YU,Mount Saint Helens Broadband,"University of Memphis, CERI",US (United States),,United States, +YU,Northern California Delta,USGS Menlo Park,US (United States),,United States,doi:10.7914/SN/YU_2006 +YV,North East Atlantic Tomography,University of Leicester (SEIS UK),GB (United Kingdom),,United Kingdom, +YV,Parkfield aftershocks,USGS Menlo Park,US (United States),,United States,doi:10.7914/SN/YV_2004 +YV,Seismic and geodetic imaging of subducting terranes under North America,IRIS/PASSCAL, (),,,doi:10.7914/SN/YV_2006 +YV,Bering Glacier Surge Seismic Experiment,"Michigan Technological University (MTU, Michigan USA)",US (United States),,United States,doi:10.7914/SN/YV_2010 +YV,RUM-RHUM,"Observatoire de Grenoble, Grenoble",FR (France),,France, +YW,North China Experiment 2000-2001,"Institute of Geology and Geophysics, CAS",CN (China),,China, +YW,Cape Verde Mantle Structure,University of Bristol (UK),GB (United Kingdom),,United Kingdom, +YW,Stalking Cascadia episodic tremor and slip with enhanced GPS and seismic arrays,University of Washington,US (United States),,United States,doi:10.7914/SN/YW_2005 +YW,TONGA06,Washington University in St. Louis (WUSTL),US (United States),,United States, +YW,Resolving structural control of episodic tremor and slip along the length of Cascadia,UC Berkeley,US (United States),,United States,doi:10.7914/SN/YW_2007 +YW,Nabro Urgency Array,Imperial College London (Imperial UK),GB (United Kingdom),,United Kingdom, +YW,"MIDGE: Minimally Invasive Direct Glacial Exploration of Biogeochemistry, Hydrology and Glaciology of Blood Falls, McMurdo Dry Va","University of Alaska, Fairbanks (UAF, AK USA)",US (United States),,United States,doi:10.7914/SN/YW_2013 +YX,3FCorinth Tomography,"Sismos a l'Ecole, Geosciences Azur",FR (France),,France, +YX,Tides ,IRIS/PASSCAL, (),,, +YX,Samoa Lithosphere Integrated Seismic Experiment,Woods Hole Oceanographic Institution (WHOI),US (United States),,United States, +YX,Seismology Rapid Response Test During the SoSAF Shakeout,UC Riverside,US (United States),,United States,doi:10.7914/SN/YX_2008 +YX,SSocorro Swarm 2009 RAMP,"New Mexico Tech (NMT Mining & Technology NM,USA)",US (United States),,United States,doi:10.7914/SN/YX_2009 +YX,Collaborative Research: 4D multi-disciplinary investigation of highly variable crustal response to continental extension in the north-central Basin and Range,Stanford University,US (United States),,United States,doi:10.7914/SN/YX_2010 +YX,Lhasa Block Top to Bottom--Lithospheric Evolution of Asia’s Leading Edge,Lehigh University,US (United States),,United States, +YY,NCISP1,"Institute of Geology and Geophysics, CAS",CN (China),http://english.igg.cas.cn,China,doi:10.7914/SN/YY_2000 +YY,Mariana Subdction Factory Experiment,Washington University in St. Louis (WUSTL),US (United States),,United States, +YY,Norway 05,Aarhus University,DK (Denmark),,Denmark, +YY,Southern Nevada Earthquake,"University of Nevada, Las Vegas",US (United States),,United States,doi:10.7914/SN/YY_2008 +YY,KRAFLA-09,University of Cambridge (UK) Earth Sciences,GB (United Kingdom),,United Kingdom, +YY,Mendenhall Glacier Outburst Flood Seismicity and Next-Generation Instrument Testing,UC Santa Cruz,US (United States),,United States,doi:10.7914/SN/YY_2012 +YY,Exploring extensional tectonics beyond the Ethiopian Rift,Cornell University,US (United States),,United States,doi:10.7914/SN/YY_2013 +YZ,"Bardwell, KY Aftershock Deployment","University of Memphis, CERI",US (United States),,United States, +YZ,Tabriz Experiment,"Observatoire de Grenoble, Grenoble",FR (France),,France, +YZ,Boina Broadband Network,"Royal Holloway, University of London",GB (United Kingdom),,United Kingdom, +YZ,Nicoya Seismogenic Zone,UC Santa Cruz,US (United States),,United States,doi:10.7914/SN/YZ_2009 +Z1,Northeast Tibet Plateu Seismic Experiment: Pilot,University of Rhode Island (URI),US (United States),,United States,doi:10.7914/SN/Z1_2006 +Z1,Mantle flow and magma supply to the Eastern Lau Spreading Center,Washington University in St. Louis (WUSTL),US (United States),,United States,doi:10.7914/SN/Z1_2009 +Z1,MT Imaging of the Cascades Volcanic Arc GeoPRISMS/ES MT Experiment,Oregon State University (OSU USA),US (United States),,United States, +Z2,HAMNET,"BGR Federal Institute for Geosciences and Natural Resources (BGR, Germany)",DE (Germany),,Germany, +Z2,NOISY,Stanford University,US (United States),,United States, +Z2,Luther OK,Cornell University,US (United States),,United States, +Z2,Galapagos2014,Geoazur,FR (France),,Ecuador,doi:10.7914/SN/Z2_2014 +Z3,EGELADOS network,Ruhr Universitaet Bochum (RUB Germany),DE (Germany),,Germany, +Z3,Mt.Carmel 2008 AFtershock Network,"University of Memphis, CERI",US (United States),,United States, +Z3,Detecting Structural changes During an ETS Event: Proof of Concept,Rice University,US (United States),,United States,doi:10.7914/SN/Z3_2009 +Z3,Jemez Pueblo geothermal project,TBA Inc,US (United States),,United States,doi:10.7914/SN/Z3_2010 +Z3,AlpArray,Eidgendssisch Technische Hochschule (ETH Zurich) - Swiss Seismological Service,CH (Switzerland),http://www.seismo.ethz.ch/alparray/,Switzerland, +Z4,DESIRE,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +Z4,Appalachian Seismic Transect,University of North Carolina at Chapel Hill (UNC),US (United States),,United States, +Z4,Chilean 2010 post-seismic response,Oregon State University (OSU USA),US (United States),,United States, +Z4,Seismic data of Santiguito volcano,University of Liverpool,GB (United Kingdom),,United Kingdom,doi:10.7914/SN/Z4_2014 +Z5,Tahiti Plume,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +Z5,Rwenzori Seismic Network,J.W. Goethe-University,DE (Germany),,Germany, +Z5,"Seismicity, Structure and Dynamics of the Gorda Deformation Zone",Oregon State University (OSU USA),US (United States),,United States,doi:10.7914/SN/Z5_2013 +Z6,Meramex,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +Z6,Mantle Investigations of Norwegian Uplift Structures,Karlsruhe Institute of Technology (KIT GIP Germany),DE (Germany),,Germany, +Z6,Forsyth Deployment near the South Shatsky Fracture Zone,UC San Diego,US (United States),,United States, +Z6,Collision of the Burma Arc accretionary prism and foldbelt with the Ganges-Brahmaputra Delta in Bangladesh,"Lamont Doherty Earth Observatory (LDEO), Columbia University",US (United States),,United States,doi:10.7914/SN/Z6_2011 +Z7,MROI vibrations,"New Mexico Tech (NMT Mining & Technology NM,USA)",US (United States),,United States,doi:10.7914/SN/Z7_2008 +Z7,Norhern Volcanic Zone,Geological Survey of Estonia (GSE),EE (Estonia),,Estonia, +Z8,NCISP5,"Institute of Geology and Geophysics, CAS",CN (China),http://english.igg.cas.cn,China,doi:10.7914/SN/Z8_2006 +Z8,"Deep Geothermal ""Hotter and Deeper"" seismic array",Institute of Geological & Nuclear Sciences Ltd (GNS New Zealand),NZ (New Zealand),,New Zealand, +Z8,Dense Virtual Seismic Array at Pacaya,"Michigan Technological University (MTU, Michigan USA)",US (United States),,United States,doi:10.7914/SN/Z8_2013 +Z9,Laramide Landslides,USGS University of Washington,US (United States),,United States, +Z9,Southeastern Suture of the Appalachian Margin Experiment,Brown University,US (United States),,United States,doi:10.7914/SN/Z9_2010 +ZA,Erzican,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZA,Killari,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZA,PISCO94 PS,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZA,Chicxulub CP,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZA,TOR-TE,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZA,REFUCA,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZA,The Colima Deep Seismic Experiment: Imaging the Magmatic Root of Colima Volcano,"University of Alaska, Fairbanks (UAF, AK USA)",US (United States),,United States,doi:10.7914/SN/ZA_2006 +ZA,Russell Glacier Catchment 2009-12,Swansea University,GB (United Kingdom),,United Kingdom, +ZA,NoMelt,Woods Hole Oceanographic Institution (WHOI),US (United States),,United States, +ZA,"Wellington, Kansas CO2 Sequestration Monitoring",Kansas Geological Survey,US (United States),,United States,doi:10.7914/SN/ZA_2014 +ZB,Alaska TE,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZB,PUNA97,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZB,Svekalapko,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZB,Simeulue,University of Cambridge (UK) Earth Sciences,GB (United Kingdom),,United Kingdom, +ZB,Sumatra Segmentation and Aftershocks Deployment,University of Cambridge (UK) Earth Sciences,GB (United Kingdom),,United Kingdom, +ZB,HARP,Scripps Institution of Oceanography,US (United States),,United States, +ZC,Antofagasta,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZC,TOR-TO,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZC,GLATIS,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZC,Vogtland,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZC,TEDESE,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZC,Mt. St.Helens Temporary Array 2005,University of Washington,US (United States),,United States, +ZC,Anatahan and submarine Mariana volcanos,Washington University in St. Louis (WUSTL),US (United States),,United States,doi:10.7914/SN/ZC_2006 +ZC,Seismic Detection of Avalanches,Boise State University,US (United States),,United States,doi:10.7914/SN/ZC_2010 +ZC,Greater Antilles Seismic Program,Baylor University,US (United States),,United States,doi:10.7914/SN/ZC_2013 +ZD,Crete-TE,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZD,SEISM Seychelles,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZD,Tides E 2005,IRIS/PASSCAL, (),,, +ZD,Seismcity of Quebrada-Discovery-gofur- Transforms ( QDG),Woods Hole Oceanographic Institution (WHOI),US (United States),,United States, +ZD,PerU Lithosphere and Slab Experiment,University of North Carolina at Chapel Hill (UNC),US (United States),,United States,doi:10.7914/SN/ZD_2010 +ZD,"4D Integrated Study Using Geology, Geophysics, Reservoir Modeling & Rock Mechanics to Develop Assessment Models for Potential In",University of Oklahoma (OU Oklahoma USA),US (United States),,United States,doi:10.7914/SN/ZD_2014 +ZE,ANCORP-TE,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZE,Calixto,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZE,Sultandagi,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZE,Bingoel,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZE,SIKKIM,University of Cambridge (UK) Earth Sciences,GB (United Kingdom),,United Kingdom, +ZE,AFAR,University of Rochester,US (United States),,United States,doi:10.7914/SN/ZE_2007 +ZE,Maule Aftershock Survey-GFZ,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZE,"SELASOMA Project, Madagascar 2012-2014","GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany,10.14470/MR7567431421 +ZE,Southern Alaska Lithosphere and Mantle Observation Network,"University of Alaska, Fairbanks (UAF, AK USA)",US (United States),,United States,doi:10.7914/SN/ZE_2015 +ZF,Yakutia,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZF,Hawaii Plume,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZF,Aachen,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZF,BAM Earthquake Aftershock Experiment,"Observatoire de Grenoble, Grenoble",FR (France),,France, +ZF,Tidal modulation of ice stream flow,IRIS/PASSCAL, (),,,doi:10.7914/SN/ZF_2005 +ZF,Afar Consortium Network,University of Bristol (UK),GB (United Kingdom),,United Kingdom, +ZF,Collaborative Research: East Antarctic Outlet Glacier Dynamics,Central Washington University,US (United States),,United States,doi:10.7914/SN/ZF_2012 +ZG,Cariaco,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZG,Adana,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZG,Popcatepetl,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZG,TaskForce Bingoel 2003,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZG,Tidal modulation of ice stream flow,IRIS/PASSCAL, (),,,doi:10.7914/SN/ZG_2004 +ZG,Origin of the Columbia River Basalts and Uplift of the Wallowa Mountains,University of Oregon,US (United States),,United States,doi:10.7914/SN/ZG_2006 +ZG,Central Andean Uplift and the Geodynamics of the High Topography,University of Arizona,US (United States),,United States,doi:10.7914/SN/ZG_2010 +ZG,Bringing New Tools and Techniques to Bear on Earthquake Hazard Analysis and Mitigation,IRIS HQ (DC),US (United States),,United States,doi:10.7914/SN/ZG_2013 +ZG,Sage Brush Flats Nodal Experiment,UC San Diego,US (United States),,United States, +ZG,27F2 SOW 019 (is the official name of the well),"USGS OGW BG, Storrs, CT",US (United States),http://va.water.usgs.gov/earthquakes/,United States, +ZH,Duezce,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZH,NW Zagros Transet,"Observatoire de Grenoble, Grenoble",FR (France),,France, +ZH,Tidal modulation of ice stream flow,IRIS/PASSCAL, (),,,doi:10.7914/SN/ZH_2004 +ZH,British Isles Seismic Experiment,University of Cambridge (UK) Earth Sciences,GB (United Kingdom),,United Kingdom, +ZH,Collaborative Research: Geometry and kinematics of basement-involved foreland arches:Insights into continental processes from Earthscope.,University of Colorado,US (United States),,United States,doi:10.7914/SN/ZH_2010 +ZH,Monitgoring seismicity associated with a possible asperity on the Cascadia megathrust,Oregon State University (OSU USA),US (United States),,United States,doi:10.7914/SN/ZH_2011 +ZH,Imaging the Floridan Aquifer System Using Seismic Noise,University of Florida,US (United States),,United States,doi:10.7914/SN/ZH_2013 +ZI,Izmit,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZI,Polynesian Lithosphere and Upper Mantle Experiment (PLUME),University Montpellier II (UM2 UMSF France),FR (France),http://www.gm.univ-montp2.fr/PERSO/barruol/polynesia/,France,doi:10.7914/SN/ZI_2001 +ZI,British Isles Seismic Experiment,University of Cambridge (UK) Earth Sciences,GB (United Kingdom),,United Kingdom, +ZI,Collaborative Research: Geometry and kinematics of basement-involved foreland arches: Insights into continental processes from Earthscope,University of Colorado,US (United States),,United States,doi:10.7914/SN/ZI_2010 +ZI,CoMITAC Morocco-Bristol Network,University of Bristol (UK),GB (United Kingdom),,United Kingdom, +ZI,"A community seismic experiment targeting the pre-syn, post-rift evolution of the Mid-Atlantic US",Southern Methodist University (SMU TX),US (United States),,United States, +ZJ,Alborz Transect,"Observatoire de Grenoble, Grenoble",FR (France),,France, +ZJ,Herdubreid 2005,Geological Survey of Estonia (GSE),EE (Estonia),,Estonia, +ZJ,Central China Broadband Experiment,Multimax Inc (MD USA),US (United States),,United States, +ZJ,Preparation for WISSARD in Alaska,UC Santa Cruz,US (United States),,United States,doi:10.7914/SN/ZJ_2011 +ZJ,Transantarctic Mountains Northern Network,The University of Alabama,US (United States),,United States,doi:10.7914/SN/ZJ_2012 +ZK,TOLSTOY,"Lamont Doherty Earth Observatory (LDEO), Columbia University",US (United States),,United States, +ZK,UWTremTexBS,University of Washington,US (United States),,United States,doi:10.7914/SN/ZK_2008 +ZK,"Four-Dimensional Anatomy of Continental Rifts Transitioning into Sea Floor spreading: Insights from Afar, Ethiopia for oil and gas exploration of global rift systems and passive continental margins",Missouri University of Science & Technology(Former UM-Rolla)(Missouri S&T USA),US (United States),,United States,doi:10.7914/SN/ZK_2009 +ZK,Guerrero Coast Experiment,Monitron,MX (Mexico),,Mexico, +ZK,Vatnajokull Icequake and Tremor Array: Lite,University of Cambridge (UK) Earth Sciences,GB (United Kingdom),,United Kingdom, +ZL,David Glacier 2003-2004,Institute of Geological and Nuclear Science (GNS - New Zealand),NZ (New Zealand),,New Zealand, +ZL,Sea of Cortez Ocean Bottom Array,Scripps Institution of Oceanography,US (United States),,United States, +ZL,Lithospheric Structure and Deformation of the Flat Slab Region of Argentina,University of Arizona,US (United States),,United States,doi:10.7914/SN/ZL_2007 +ZL,Shatsky Rise Active Source Experiment OBSIP,Woods Hole Oceanographic Institution (WHOI),US (United States),,United States, +ZL,Northern Embayment Lithospheric Experiment,"University of Memphis, CERI",US (United States),,United States,doi:10.7914/SN/ZL_2011 +ZM,Uraban Seismology,Karlsruhe Institute of Technology (KIT GIP Germany),DE (Germany),,Germany, +ZM,"Seismicity of the Atlantis Massif, Mid Atlantic Ridge",Woods Hole Oceanographic Institution (WHOI),US (United States),,United States, +ZM,"A Broadband Seismic Experiment to Image the Lithosphere beneath the Gamburtsev Mountains, East Antarctica",Saint Louis University,US (United States),,United States,doi:10.7914/SN/ZM_2007 +ZM,UKFLUV14,Durham University,GB (United Kingdom),,United Kingdom,doi:10.7914/SN/ZM_2014 +ZN,Enola Arkansas Aftershock Study,"University of Memphis, CERI",US (United States),,United States, +ZN,SISMOVALP,Politecnico Milano,IT (Italy),,Italy, +ZN,Lithospheric structure of West Greenland,University of Leicester (SEIS UK),GB (United Kingdom),,United Kingdom, +ZN,Meteo Aruba/Rice Univ,Other, (),,, +ZN,How is Rifting Exhuming the Youngest HP/UHP Rocks on Earth?,"Lamont Doherty Earth Observatory (LDEO), Columbia University",US (United States),,United States,doi:10.7914/SN/ZN_2010 +ZN,"Investigation of subglacial hydrologic seismic signals, Breidamerkurjokull Glacier, Iceland- a WISSARD test case",UC Santa Cruz,US (United States),,United States,doi:10.7914/SN/ZN_2013 +ZN,"Site response in the Washington, DC, area",USGS National Center/Reston (United States Geological Survey),US (United States),,United States,doi:10.7914/SN/ZN_2014 +ZO,Transalp II,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZO,Seismic Monitoring of Greenland's Melting Ice Sheet,University of North Carolina at Chapel Hill (UNC),US (United States),,United States,doi:10.7914/SN/ZO_2006 +ZO,Seismo-Acoustic data collection near Salt Lake,Southern Methodist University (SMU TX),US (United States),,United States,doi:10.7914/SN/ZO_2007 +ZO,ARC-Vanuatu Seismic Experiment (Volcanoes),"Observatoire de Grenoble, Grenoble",FR (France),,France, +ZO,"Volcanic stress field analysis using non-local seismic sources at Hekla Volcano, Iceland",University of South Florida (USF),US (United States),,United States,doi:10.7914/SN/ZO_2010 +ZO,Erebus Small Array,"New Mexico Tech (NMT Mining & Technology NM,USA)",US (United States),,United States,doi:10.7914/SN/ZO_2011 +ZO,Vaigat,Durham University,GB (United Kingdom),,United Kingdom, +ZO,Bhutanepal seismic array,Institut des Sciences de la Terre,FR (France),,France, +ZP,ISSA,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZP,"3D Site Amplification at Sion, Valais, Switzerland",Swiss Seismological Service,CH (Switzerland),,Switzerland, +ZP,AfricaArray, None, ( ),, ,doi:10.7914/SN/ZP_2007 +ZP,Africa Array- Uganda/Tanzania,Penn State University,US (United States),,United States, +ZP,Ross Ice Shelf Project,University of Otago (New Zealand),NZ (New Zealand),,New Zealand,doi:10.7914/SN/ZP_2015 +ZQ,NCISP2,"Institute of Geology and Geophysics, CAS",CN (China),http://english.igg.cas.cn,China,doi:10.7914/SN/ZQ_2001 +ZQ,Cerro Blanco,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZQ,Africa Array- S.Africa mine network,Penn State University,US (United States),,United States, +ZQ,Oklahoma RAMP,University of Oklahoma (OU Oklahoma USA),US (United States),,United States,doi:10.7914/SN/ZQ_2011 +ZQ,Imaging the Matador arch using receiver funcitons from Texan dataloggers and short period geop0hones.,Texas Tech University,US (United States),,United States,doi:10.7914/SN/ZQ_2013 +ZQ,Taku Glacier GEOICE Development Initiative,Central Washington University,US (United States),,United States,doi:10.7914/SN/ZQ_2015 +ZR,DESERT,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZR,Reconnaissance survey of Bering Glacier Basal seismicity and calving,"Michigan Technological University (MTU, Michigan USA)",US (United States),,United States,doi:10.7914/SN/ZR_2007 +ZR,Bering Glacier Field Camp 2008,"Michigan Technological University (MTU, Michigan USA)",US (United States),,United States,doi:10.7914/SN/ZR_2008 +ZR,AFAR0911,University of Southampton (UK),GB (United Kingdom),,United Kingdom,doi:10.7914/SN/ZR_2009 +ZR,El Tatio Geyser Study,Stanford University,US (United States),,United States,doi:10.7914/SN/ZR_2012 +ZR,SCANLIPS3D,University of Leicester (SEIS UK),GB (United Kingdom),,United Kingdom, +ZR,Laguna del Maule seismic imaging,"University of Wisconsin, Madison",US (United States),,United States, +ZS,CENMOVE,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZS,TaskForce Yogyakarta 2006,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZS,Seismological Network in Northern Tanzania,UBO-IUEM-CNRS Domaines Oceaniques ,FR (France),,France, +ZS,CReSIS,Penn State University,US (United States),,United States,doi:10.7914/SN/ZS_2009 +ZS,"Stick Slip Motion of Engabreen Glacier, Norway",Penn State University,US (United States),,United States, +ZS,Seismicity of East Coast Submarine Landslides,Woods Hole Oceanographic Institution (WHOI),US (United States),,United States, +ZS,Measuring the frequency of ocean breaker induced surface waves for determining swell direction: feasibility study,East Carolina University (ECU),US (United States),,United States,doi:10.7914/SN/ZS_2014 +ZT,Gulf of Guinea Islands,University of Texas at Austin,US (United States),,United States, +ZT,Study of the Dynamic of Utiku Landslide (NZ),"Observatoire de Grenoble, Grenoble",FR (France),,France, +ZT,"WIsconsin, new Zealand, And Rensselaer Deployment","University of Wisconsin, Madison",US (United States),,United States,doi:10.7914/SN/ZT_2012 +ZU,TaskForce Waldkirch 2004,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZU,PASSEQ,University of Leicester (SEIS UK),GB (United Kingdom),,United Kingdom, +ZU,North Tanzania,University of Rochester,US (United States),,United States, +ZU,Marine Observations of Anisotropy,Woods Hole Oceanographic Institution (WHOI),US (United States),,United States, +ZU,Repeating glacier quakes (clones) on Mount Rainier,University of Washington,US (United States),,United States,doi:10.7914/SN/ZU_2011 +ZU,Grand Canyon Controlled Flood,California Institute of Technology (Caltech),US (United States),,United States,doi:10.7914/SN/ZU_2012 +ZU,Trans-Haiti,University of Southampton (UK),GB (United Kingdom),,United Kingdom, +ZU,OROGEN-X,Research Institute in Astrophysics and Planetology (IRAP France),FR (France),,France, +ZV,BOHEMA,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZV,Monitoring of Augustine Volcano Eruption using Ocean Bottom Seismometers,Woods Hole Oceanographic Institution (WHOI),US (United States),,United States, +ZV,Mid-Ocean Volcanoes and Earthquakes (during Arctic Gakkel Vents Expedition),Alfred Wegener Institute for Polar and Marine Research,DE (Germany),,Germany,doi:10.7914/SN/ZV_2007 +ZV,Northeast Tibet Plateau Seismic Experiment,University of Rhode Island (URI),US (United States),,United States,doi:10.7914/SN/ZV_2008 +ZV,Malargue seismic array,Delft University of Technology (TU Netherlands),NL (Netherlands),,Netherlands,doi:10.7914/SN/ZV_2012 +ZV,Southern Lake Tanganyika experiment,University of Southampton (UK),GB (United Kingdom),,United Kingdom, +ZW,TIPTEQ North,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZW,Erebus Tomography and Source Studies,"New Mexico Tech (NMT Mining & Technology NM,USA)",US (United States),,United States,doi:10.7914/SN/ZW_2007 +ZW,JULS,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZW,Locating North Texas Earthquakes,Southern Methodist University (SMU TX),US (United States),,United States,doi:10.7914/SN/ZW_2013 +ZX,NCISP3,"Institute of Geology and Geophysics, CAS",CN (China),http://english.igg.cas.cn,China,doi:10.7914/SN/ZX_2003 +ZX,Costa Rica Poco Sol,Rutgers University,US (United States),,United States, +ZX,Boulby Cliffs,Durham University,GB (United Kingdom),,United Kingdom, +ZX,Gisborne-Mahia Seismic Tremor Array,GNS Science,NZ (New Zealand),,New Zealand, +ZY,Portable Southern California Seismic Networks,California Institute of Technology (Caltech),US (United States),,United States, +ZZ,CYCLADES,"GEOFON Program (GFZ-Potsdam, Germany)",DE (Germany),,Germany, +ZZ,Lithospheric Structure of the Puna Plateau,Missouri University of Science & Technology(Former UM-Rolla)(Missouri S&T USA),US (United States),,United States, +ZZ,Seismology Classroom at University of Chicago,University of Chicago,US (United States),,United States,doi:10.7914/SN/ZZ_2010 +ZZ,"Multi-array observations of tectonic tremor in the Anza gap, San Jacinto fault, CA - Phase 1",California Institute of Technology (Caltech),US (United States),,United States,doi:10.7914/SN/ZZ_2011 +ZZ,Collaborative Research: Imaging the Cascadia subduction zone - a ship-to-shore opportunity,"Lamont Doherty Earth Observatory (LDEO), Columbia University",US (United States),,United States,doi:10.7914/SN/ZZ_2012 +ZZ,Virginia seismic experiment,USGS National Center/Reston (United States Geological Survey),US (United States),,United States,doi:10.7914/SN/ZZ_2013 From c4fe8bd468f0fbc15e6ff00e8c7b095fd0c9eaa4 Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Mon, 21 Mar 2016 16:19:01 -0800 Subject: [PATCH 15/67] Event dialog in progress. Concurrency trouble while selecting waves. --- .../java/gov/usgs/volcanoes/swarm/Swarm.java | 11 +- .../volcanoes/swarm/event/EventFrame.java | 425 ++------- .../volcanoes/swarm/event/EventFrame3.java | 805 ------------------ .../volcanoes/swarm/event/ParameterPanel.java | 211 +++++ .../usgs/volcanoes/swarm/event/PickPanel.java | 247 +++++- .../map/hypocenters/HypocenterLayer.java | 11 +- 6 files changed, 499 insertions(+), 1211 deletions(-) delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame3.java create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/ParameterPanel.java diff --git a/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java b/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java index 7a511c8b..f1f625fe 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java @@ -1,5 +1,10 @@ package gov.usgs.volcanoes.swarm; +import com.jgoodies.looks.plastic.Plastic3DLookAndFeel; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.awt.Dimension; import java.awt.Frame; import java.awt.KeyboardFocusManager; @@ -24,11 +29,6 @@ import javax.swing.SwingUtilities; import javax.swing.UIManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.jgoodies.looks.plastic.Plastic3DLookAndFeel; - import gov.usgs.plot.data.Wave; import gov.usgs.volcanoes.core.configfile.ConfigFile; import gov.usgs.volcanoes.core.time.CurrentTime; @@ -40,7 +40,6 @@ import gov.usgs.volcanoes.swarm.data.SeismicDataSource; import gov.usgs.volcanoes.swarm.event.Event; import gov.usgs.volcanoes.swarm.event.EventFrame; -import gov.usgs.volcanoes.swarm.event.EventFrame3; import gov.usgs.volcanoes.swarm.heli.HelicorderViewerFrame; import gov.usgs.volcanoes.swarm.internalFrame.InternalFrameListener; import gov.usgs.volcanoes.swarm.internalFrame.SwarmInternalFrames; diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java index 399e3e2f..d8b136cc 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java @@ -1,40 +1,42 @@ package gov.usgs.volcanoes.swarm.event; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.io.IOException; -import java.text.DateFormat; -import java.text.SimpleDateFormat; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.Stack; -import java.util.TimeZone; import java.util.TreeSet; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; +import javax.swing.ButtonGroup; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JRadioButtonMenuItem; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JToolBar; import javax.swing.ScrollPaneConstants; -import javax.swing.SwingConstants; import javax.swing.WindowConstants; import javax.swing.event.InternalFrameAdapter; import javax.swing.event.InternalFrameEvent; @@ -42,13 +44,6 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - import gov.usgs.plot.data.Wave; import gov.usgs.volcanoes.core.time.J2kSec; import gov.usgs.volcanoes.core.util.UiUtils; @@ -62,7 +57,6 @@ import gov.usgs.volcanoes.swarm.internalFrame.SwarmInternalFrames; import gov.usgs.volcanoes.swarm.picker.PickerWavePanel; import gov.usgs.volcanoes.swarm.wave.AbstractWavePanel; -import gov.usgs.volcanoes.swarm.wave.WaveViewPanelListener; import gov.usgs.volcanoes.swarm.wave.WaveViewSettingsToolbar; /** @@ -72,49 +66,45 @@ */ public class EventFrame extends SwarmFrame implements EventObserver { private static final Logger LOGGER = LoggerFactory.getLogger(EventFrame.class); - private static final Color BACKGROUND_COLOR = new Color(255, 255, 255); private static final Font KEY_FONT = Font.decode("dialog-BOLD-12"); private static final Font VALUE_FONT = Font.decode("dialog-12"); public static final long serialVersionUID = -1; + private final PickPanel pickBox; + private final JLabel statusLabel; + private final Map> histories; + private final Set selectedSet; + private JSplitPane mainPanel; - private JPanel pickPanel; private Event event; - private SeismicDataSource seismicDataSource; - private final PickPanel pickBox; private JToolBar toolbar; - private final JLabel statusLabel; private JButton sizeButton; private JButton saveButton; private JButton captureButton; private JButton histButton; - private JButton locateButton; - private final DateFormat saveAllDateFormat; - - private WaveViewPanelListener selectListener; private WaveViewSettingsToolbar waveToolbar; - private JButton upButton; - private JButton downButton; - private JButton removeButton; private JButton compXButton; private JButton expXButton; private JButton forwardButton; private JButton backButton; private JButton gotoButton; private Throbber throbber; - private final Map> histories; - private final Set selectedSet; + private JPopupMenu popup; + private int waveHeight; + private boolean closing = false; public EventFrame(Event event) { super("Event - " + event.getEvid(), true, true, true, false); this.event = event; + statusLabel = new JLabel(" "); - saveAllDateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); - saveAllDateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); + pickBox = new PickPanel(statusLabel); + pickBox.setLayout(new BoxLayout(pickBox, BoxLayout.PAGE_AXIS)); + histories = new HashMap>(); selectedSet = new HashSet(); @@ -122,18 +112,14 @@ public EventFrame(Event event) { this.setFocusable(true); createListeners(); - pickBox = new PickPanel(statusLabel); - pickBox.setLayout(new BoxLayout(pickBox, BoxLayout.PAGE_AXIS)); - setFrameIcon(Icons.ruler); setSize(swarmConfig.clipboardWidth, swarmConfig.clipboardHeight); setLocation(swarmConfig.clipboardX, swarmConfig.clipboardY); setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); LOGGER.debug("event frame: {} @ {}", this.getSize(), this.getLocation()); - - pickPanel = createPickPanel(); - mainPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT, createParameterPanel(), pickPanel); + mainPanel = + new JSplitPane(JSplitPane.VERTICAL_SPLIT, ParameterPanel.create(event), createPickPanel()); mainPanel.setOneTouchExpandable(true); setContentPane(mainPanel); @@ -154,191 +140,6 @@ public void finished() { }.start(); } - private Component createParameterPanel() { - Origin origin = event.getPreferredOrigin(); - Magnitude magnitude = event.getPerferredMagnitude(); - - JPanel parameterPanel = new JPanel(new GridBagLayout()); - GridBagConstraints c = new GridBagConstraints(); - - - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.NORTHWEST; - c.gridy = 0; - c.gridx = GridBagConstraints.RELATIVE; - c.ipadx = 3; - c.ipady = 2; - - JLabel label; - - label = new JLabel("Event source: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); - - String source = Networks.getInstance().getName(event.getEventSource().toUpperCase()); - if (source == null) { - source = event.getEventSource(); - } - label = new JLabel(Networks.getInstance().getName(event.getEventSource().toUpperCase()), - SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); - - c.gridy++; - - label = new JLabel("Description: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); - - // wrap description to support multi-line descriptions - String description = event.getDescription(); - description = description.replace("\n", "
"); - description = "" + description + ""; - label = new JLabel(description, SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); - - c.gridy++; - - label = new JLabel("Origin date: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); - - if (origin != null) { - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); - String date = dateFormat.format(event.getPreferredOrigin().getTime()); - label = new JLabel(date, SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); - } - c.gridy++; - - - label = new JLabel("Hypocenter: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); - - if (origin != null) { - String loc = origin.getLatitude() + ", " + origin.getLongitude(); - loc += " at " + (origin.getDepth() / 1000) + " km depth"; - label = new JLabel(loc, SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); - } - c.gridy++; - - label = new JLabel("Error (RMS): ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); - - double error = origin.getStandardError(); - if (!Double.isNaN(error)) { - label = new JLabel("" + error, SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); - } - c.gridy++; - - label = new JLabel("Azimuthal gap: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); - - double gap = origin.getAzimuthalGap(); - if (!Double.isNaN(gap)) { - label = new JLabel("" + gap + "\u00B0", SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); - } - c.gridy++; - - label = new JLabel("Nearest station: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); - - double distance = origin.getMinimumDistance(); - if (!Double.isNaN(distance)) { - label = new JLabel("" + distance + "\u00B0", SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); - } - c.gridy++; - - label = new JLabel("Phase count: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); - - int phaseCount = origin.getPhaseCount(); - if (phaseCount > 0) { - label = new JLabel("" + phaseCount, SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); - } - c.gridy++; - - label = new JLabel("Magnitude: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); - - if (magnitude != null) { - String mag = String.format("%s %s", magnitude.getMag(), magnitude.getType()); - String uncertaintly = magnitude.getUncertainty(); - if (uncertaintly != null) { - mag += " (" + uncertaintly + ")"; - } - label = new JLabel(mag, SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); - } - c.gridy++; - - label = new JLabel("Evalutation: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); - - String evaluationTag = ""; - - Origin.EvaluationMode evaluationMode = origin.getEvaluationMode(); - if (evaluationMode != null) { - evaluationTag += evaluationMode.toString().toLowerCase(); - } - - Origin.EvaluationStatus evaluationStatus = origin.getEvaluationStatus(); - if (evaluationStatus != null) { - if (evaluationTag.length() > 0) { - evaluationTag += " / "; - } - evaluationTag += evaluationStatus.toString().toLowerCase(); - } - - label = new JLabel(evaluationTag, SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); - - c.gridy++; - - label = new JLabel("Event id: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); - - label = new JLabel(event.getEvid(), SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); - c.gridy++; - - c.weighty = 1; - c.weightx = 1; - c.gridy++; - c.gridx = 10; - JPanel filler = new JPanel(); - parameterPanel.add(filler, c); - - final JScrollPane scrollPane = new JScrollPane(parameterPanel); - scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); - scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); - scrollPane.getVerticalScrollBar().setUnitIncrement(40); - - return scrollPane; - } private JPanel createPickPanel() { @@ -368,13 +169,6 @@ private JPanel createPickPanel() { } private void createMainButtons() { - saveButton = - SwarmUtil.createToolBarButton(Icons.save, "Save selected wave", new SaveActionListener()); - saveButton.setEnabled(false); - toolbar.add(saveButton); - - toolbar.addSeparator(); - sizeButton = SwarmUtil.createToolBarButton(Icons.resize, "Set wave height", new ActionListener() { public void actionPerformed(final ActionEvent e) { @@ -596,146 +390,36 @@ public void shiftTime(final double pct) { shiftTime(p, pct); } - // TODO: don't write image on event thread - // TODO: unify with MapFrame.CaptureActionListener class CaptureActionListener implements ActionListener { public void actionPerformed(final ActionEvent e) { - // if (waves == null || waves.size() == 0) - // return; - // - // final JFileChooser chooser = FileChooser.getFileChooser(); - // final File lastPath = new File(swarmConfig.lastPath); - // chooser.setCurrentDirectory(lastPath); - // chooser.setSelectedFile(new File("clipboard.png")); - // chooser.setDialogTitle("Save Clipboard Screen Capture"); - // final int result = chooser.showSaveDialog(applicationFrame); - // File f = null; - // if (result == JFileChooser.APPROVE_OPTION) { - // f = chooser.getSelectedFile(); - // - // if (f.exists()) { - // final int choice = JOptionPane.showConfirmDialog(applicationFrame, - // "File exists, overwrite?", "Confirm", JOptionPane.YES_NO_OPTION); - // if (choice != JOptionPane.YES_OPTION) - // return; - // } - // swarmConfig.lastPath = f.getParent(); - // } - // if (f == null) - // return; - // - // int height = 0; - // final int width = waves.get(0).getWidth(); - // for (final AbstractWavePanel panel : waves) - // height += panel.getHeight(); - // - // final BufferedImage image = new BufferedImage(width, height, - // BufferedImage.TYPE_4BYTE_ABGR); - // final Graphics g = image.getGraphics(); - // for (final AbstractWavePanel panel : waves) { - // panel.paint(g); - // g.translate(0, panel.getHeight()); - // } - // try { - // final PngEncoderB png = new PngEncoderB(image, false, PngEncoder.FILTER_NONE, 7); - // final FileOutputStream out = new FileOutputStream(f); - // final byte[] bytes = png.pngEncode(); - // out.write(bytes); - // out.close(); - // } catch (final Exception ex) { - // ex.printStackTrace(); - // } - } - } - - - private class SaveActionListener implements ActionListener { - public void actionPerformed(final ActionEvent e) { - // final AbstractWavePanel selected = getSingleSelected(); - // if (selected == null) - // return; - // - // final JFileChooser chooser = FileChooser.getFileChooser(); - // chooser.resetChoosableFileFilters(); - // chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); - // chooser.setMultiSelectionEnabled(false); - // chooser.setDialogTitle("Save Wave"); - // - // for (final FileType ft : FileType.values()) { - // if (ft == FileType.UNKNOWN) - // continue; - // - // final ExtensionFileFilter f = new ExtensionFileFilter(ft.extension, ft.description); - // chooser.addChoosableFileFilter(f); - // } - // - // chooser.setFileFilter(chooser.getAcceptAllFileFilter()); - // - // final File lastPath = new File(swarmConfig.lastPath); - // chooser.setCurrentDirectory(lastPath); - // final String fileName = selected.getChannel().replace(' ', '_') + ".sac"; - // chooser.setSelectedFile(new File(fileName)); - // final int result = chooser.showSaveDialog(applicationFrame); - // if (result == JFileChooser.APPROVE_OPTION) { - // final File f = chooser.getSelectedFile(); - // boolean confirm = true; - // if (f.exists()) { - // if (f.isDirectory()) { - // JOptionPane.showMessageDialog(applicationFrame, - // "You can not select an existing directory.", "Error", JOptionPane.ERROR_MESSAGE); - // return; - // } - // confirm = false; - // final int choice = JOptionPane.showConfirmDialog(applicationFrame, - // "File exists, overwrite?", "Confirm", JOptionPane.YES_NO_OPTION); - // if (choice == JOptionPane.YES_OPTION) - // confirm = true; - // } - // - // if (confirm) { - // try { - // swarmConfig.lastPath = f.getParent(); - // final String fn = f.getPath(); - // final SeismicDataFile file = SeismicDataFile.getFile(fn); - // final Wave wave = selected.getWave(); - // file.putWave(selected.getChannel(), wave); - // file.write(); - // } catch (final FileNotFoundException ex) { - // JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Directory does not exist.", - // "Error", JOptionPane.ERROR_MESSAGE); - // } catch (final IOException ex) { - // JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Error writing file.", - // "Error", JOptionPane.ERROR_MESSAGE); - // } - // } - // } + pickBox.writeImage(); } } private void doSizePopup() { - // if (popup == null) { - // final String[] labels = new String[] {"Auto", null, "Tiny", "Small", "Medium", "Large"}; - // final int[] sizes = new int[] {-1, -1, 50, 100, 160, 230}; - // popup = new JPopupMenu(); - // final ButtonGroup group = new ButtonGroup(); - // for (int i = 0; i < labels.length; i++) { - // if (labels[i] != null) { - // final int size = sizes[i]; - // final JRadioButtonMenuItem mi = new JRadioButtonMenuItem(labels[i]); - // mi.addActionListener(new ActionListener() { - // public void actionPerformed(final ActionEvent e) { - // setWaveHeight(size); - // } - // }); - // if (waveHeight == size) - // mi.setSelected(true); - // group.add(mi); - // popup.add(mi); - // } else - // popup.addSeparator(); - // } - // } - // popup.show(sizeButton.getParent(), sizeButton.getX(), sizeButton.getY()); + if (popup == null) { + final String[] labels = new String[] {"Auto", null, "Tiny", "Small", "Medium", "Large"}; + final int[] sizes = new int[] {-1, -1, 50, 100, 160, 230}; + popup = new JPopupMenu(); + final ButtonGroup group = new ButtonGroup(); + for (int i = 0; i < labels.length; i++) { + if (labels[i] != null) { + final int size = sizes[i]; + final JRadioButtonMenuItem mi = new JRadioButtonMenuItem(labels[i]); + mi.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + pickBox.setWaveHeight(size); + } + }); + if (waveHeight == size) + mi.setSelected(true); + group.add(mi); + popup.add(mi); + } else + popup.addSeparator(); + } + } + popup.show(sizeButton.getParent(), sizeButton.getX(), sizeButton.getY()); } public void fetchDetailedEvent() { @@ -807,11 +491,6 @@ private void populatePicks() { @Override public void paint(final Graphics g) { super.paint(g); - // if (waves.size() == 0) { - // final Dimension dim = this.getSize(); - // g.setColor(Color.black); - // g.drawString("Picker empty.", dim.width / 2 - 40, dim.height / 2); - // } } @Override @@ -823,7 +502,7 @@ public void setVisible(final boolean isVisible) { } public void eventUpdated() { - mainPanel.setTopComponent(createParameterPanel()); + mainPanel.setTopComponent(ParameterPanel.create(event)); mainPanel.setBottomComponent(createPickPanel()); } @@ -851,10 +530,4 @@ public void internalFrameClosed(final InternalFrameEvent e) {} public void componentResized(final ComponentEvent e) {} }); } - - // private synchronized void createImage() { - // if (getWidth() > 0 && getHeight() > 0) - // image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_4BYTE_ABGR); - // } - } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame3.java b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame3.java deleted file mode 100644 index d0db5afb..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame3.java +++ /dev/null @@ -1,805 +0,0 @@ -package gov.usgs.volcanoes.swarm.event; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.io.IOException; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.Stack; -import java.util.TimeZone; - -import javax.swing.BorderFactory; -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JSplitPane; -import javax.swing.JToolBar; -import javax.swing.ScrollPaneConstants; -import javax.swing.SwingConstants; -import javax.swing.WindowConstants; -import javax.swing.event.InternalFrameAdapter; -import javax.swing.event.InternalFrameEvent; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - -import org.apache.log4j.Layout; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - -import gov.usgs.plot.data.Wave; -import gov.usgs.volcanoes.core.time.J2kSec; -import gov.usgs.volcanoes.core.util.UiUtils; -import gov.usgs.volcanoes.swarm.Icons; -import gov.usgs.volcanoes.swarm.SwarmFrame; -import gov.usgs.volcanoes.swarm.SwarmUtil; -import gov.usgs.volcanoes.swarm.SwingWorker; -import gov.usgs.volcanoes.swarm.Throbber; -import gov.usgs.volcanoes.swarm.data.CachedDataSource; -import gov.usgs.volcanoes.swarm.data.SeismicDataSource; -import gov.usgs.volcanoes.swarm.internalFrame.SwarmInternalFrames; -import gov.usgs.volcanoes.swarm.picker.PickerWavePanel; -import gov.usgs.volcanoes.swarm.wave.AbstractWavePanel; -import gov.usgs.volcanoes.swarm.wave.WaveViewPanelListener; -import gov.usgs.volcanoes.swarm.wave.WaveViewSettingsToolbar; - -/** - * The picker internal frame. Adapted from the WaveClipboardFrame. - * - * @author Tom Parker - */ -public class EventFrame3 extends SwarmFrame implements EventObserver { - private static final Logger LOGGER = LoggerFactory.getLogger(EventFrame3.class); - private static final Color BACKGROUND_COLOR = new Color(255, 255, 255); - private static final Font KEY_FONT = Font.decode("dialog-BOLD-12"); - private static final Font VALUE_FONT = Font.decode("dialog-12"); - - public static final long serialVersionUID = -1; - - private JSplitPane mainPanel; - private Component pickPanel; - private Event event; - private SeismicDataSource seismicDataSource; - private final PickPanel pickBox; - private JToolBar toolbar; - private final JLabel statusLabel; - private JButton sizeButton; - private JButton saveButton; - private JButton captureButton; - private JButton histButton; - private JButton locateButton; - - private final DateFormat saveAllDateFormat; - - private WaveViewPanelListener selectListener; - private WaveViewSettingsToolbar waveToolbar; - - private JButton upButton; - private JButton downButton; - private JButton removeButton; - private JButton compXButton; - private JButton expXButton; - private JButton forwardButton; - private JButton backButton; - private JButton gotoButton; - private Throbber throbber; - private final Map> histories; - private final Set selectedSet; - private boolean closing = false; - - public EventFrame3(Event event) { - super("Event - " + event.getEvid(), true, true, true, false); - this.event = event; - statusLabel = new JLabel(" "); - saveAllDateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); - saveAllDateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); - histories = new HashMap>(); - selectedSet = new HashSet(); - - event.addObserver(this); - this.setFocusable(true); - createListeners(); - - pickBox = new PickPanel(statusLabel); - pickBox.setLayout(new BoxLayout(pickBox, BoxLayout.PAGE_AXIS)); - - setFrameIcon(Icons.ruler); - setSize(swarmConfig.clipboardWidth, swarmConfig.clipboardHeight); - setLocation(swarmConfig.clipboardX, swarmConfig.clipboardY); - setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - LOGGER.debug("event frame: {} @ {}", this.getSize(), this.getLocation()); - - - pickPanel = createPickPanel(); - mainPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT, createParameterPanel(), pickPanel); - mainPanel.setOneTouchExpandable(true); - - setContentPane(mainPanel); - this.setVisible(true); - - new SwingWorker() { - @Override - public Object construct() { - fetchDetailedEvent(); - populatePicks(); - return null; - } - - @Override - public void finished() { - repaint(); - } - }.start(); - } - - private Component createParameterPanel() { - Origin origin = event.getPreferredOrigin(); - Magnitude magnitude = event.getPerferredMagnitude(); - - JPanel parameterPanel = new JPanel(new GridBagLayout()); - GridBagConstraints c = new GridBagConstraints(); - - - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.NORTHWEST; - c.gridy = 0; - c.gridx = GridBagConstraints.RELATIVE; - c.ipadx = 3; - c.ipady = 2; - - JLabel label; - - label = new JLabel("Event source: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); - - label = new JLabel(event.getEventSource(), SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); - - c.gridy++; - - label = new JLabel("Description: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); - - // wrap description to support multi-line descriptions - String description = event.getDescription(); - description = description.replace("\n", "
"); - description = "" + description + ""; - label = new JLabel(description, SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); - - c.gridy++; - - label = new JLabel("Origin date: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); - - if (origin != null) { - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); - String date = dateFormat.format(event.getPreferredOrigin().getTime()); - label = new JLabel(date, SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); - } - c.gridy++; - - - label = new JLabel("Hypocenter: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); - - if (origin != null) { - String loc = origin.getLatitude() + ", " + origin.getLongitude(); - loc += " at " + (origin.getDepth() / 1000) + " km depth"; - label = new JLabel(loc, SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); - } - c.gridy++; - - label = new JLabel("Magnitude: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); - - if (magnitude != null) { - String mag = String.format("%s %s", magnitude.getMag(), magnitude.getType()); - String uncertaintly = magnitude.getUncertainty(); - if (uncertaintly != null) { - mag += " (" + uncertaintly + ")"; - } - label = new JLabel(mag, SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); - } - c.gridy++; - - label = new JLabel("Event id: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); - - label = new JLabel(event.getEvid(), SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); - c.gridy++; - - c.weighty = 1; - c.weightx = 1; - c.gridy++; - c.gridx = 10; - JPanel filler = new JPanel(); - parameterPanel.add(filler, c); - - final JScrollPane scrollPane = new JScrollPane(parameterPanel); - scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); - scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); - scrollPane.getVerticalScrollBar().setUnitIncrement(40); - - return scrollPane; - } - - private Component createPickPanel() { - -// toolbar = SwarmUtil.createToolBar(); -// createMainButtons(); -// createWaveButtons(); - - GridBagLayout layout = new GridBagLayout(); - GridBagConstraints c = new GridBagConstraints(); - - - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.NORTHWEST; - c.gridy = 0; - c.gridx = GridBagConstraints.RELATIVE; - c.ipadx = 3; - c.ipady = 2; - - JPanel tablePanel = new JPanel(layout); - - tablePanel.add(new JLabel("AAAAAAAAAAAAAAAAAA", SwingConstants.LEFT), c); - tablePanel.add(new JLabel("Event id", SwingConstants.LEFT), c); - tablePanel.add(new JLabel("XXX", SwingConstants.LEFT), c); - - final JScrollPane scrollPane = new JScrollPane(tablePanel); - scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); - scrollPane.getVerticalScrollBar().setUnitIncrement(40); - - JPanel headerPanel = new JPanel(layout); - scrollPane.setColumnHeaderView(headerPanel); - c.gridy = 0; - headerPanel.add(new JLabel("Event id", SwingConstants.LEFT), c); - headerPanel.add(new JLabel("XXX", SwingConstants.LEFT), c); - headerPanel.add(new JLabel("AAAAAAAAAAAAAAAAAA", SwingConstants.LEFT), c); - -// JPanel pickPanel = new JPanel(); -// pickPanel.setLayout(new BoxLayout(pickPanel, BoxLayout.PAGE_AXIS)); -// LOGGER.info("Adding toolbar"); -// pickPanel.add(toolbar); -// pickPanel.add(scrollPane); -// -// JPanel statusPanel = new JPanel(); -// statusPanel.setLayout(new BorderLayout()); -// statusLabel.setBorder(BorderFactory.createEtchedBorder()); -// statusPanel.add(statusLabel); -// statusPanel -// .setMaximumSize(new Dimension(Integer.MAX_VALUE, statusPanel.getPreferredSize().height)); -// pickPanel.add(statusPanel); - - return scrollPane; - } - - private void createMainButtons() { - saveButton = - SwarmUtil.createToolBarButton(Icons.save, "Save selected wave", new SaveActionListener()); - saveButton.setEnabled(false); - toolbar.add(saveButton); - - toolbar.addSeparator(); - - sizeButton = - SwarmUtil.createToolBarButton(Icons.resize, "Set wave height", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - doSizePopup(); - } - }); - toolbar.add(sizeButton); - - toolbar.addSeparator(); - captureButton = SwarmUtil.createToolBarButton(Icons.camera, "Save pick image (P)", - new CaptureActionListener()); - UiUtils.mapKeyStrokeToButton(this, "P", "capture", captureButton); - toolbar.add(captureButton); - } - - - private void createWaveButtons() { - toolbar.addSeparator(); - - backButton = SwarmUtil.createToolBarButton(Icons.left, "Scroll back time 20% (Left arrow)", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - shiftTime(-0.20); - } - }); - UiUtils.mapKeyStrokeToButton(this, "LEFT", "backward1", backButton); - toolbar.add(backButton); - - forwardButton = SwarmUtil.createToolBarButton(Icons.right, - "Scroll forward time 20% (Right arrow)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - shiftTime(0.20); - } - }); - toolbar.add(forwardButton); - UiUtils.mapKeyStrokeToButton(this, "RIGHT", "forward1", forwardButton); - - gotoButton = - SwarmUtil.createToolBarButton(Icons.gototime, "Go to time (Ctrl-G)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - final String t = JOptionPane.showInputDialog(applicationFrame, - "Input time in 'YYYYMMDDhhmm[ss]' format:", "Go to Time", - JOptionPane.PLAIN_MESSAGE); - if (t != null) - gotoTime(t); - } - }); - toolbar.add(gotoButton); - UiUtils.mapKeyStrokeToButton(this, "ctrl G", "goto", gotoButton); - - compXButton = SwarmUtil.createToolBarButton(Icons.xminus, - "Shrink sample time 20% (Alt-left arrow, +)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - scaleTime(0.20); - } - }); - toolbar.add(compXButton); - UiUtils.mapKeyStrokeToButton(this, "alt LEFT", "compx", compXButton); - UiUtils.mapKeyStrokeToButton(this, "EQUALS", "compx2", compXButton); - UiUtils.mapKeyStrokeToButton(this, "shift EQUALS", "compx2", compXButton); - - expXButton = SwarmUtil.createToolBarButton(Icons.xplus, - "Expand sample time 20% (Alt-right arrow, -)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - scaleTime(-0.20); - } - }); - toolbar.add(expXButton); - UiUtils.mapKeyStrokeToButton(this, "alt RIGHT", "expx", expXButton); - UiUtils.mapKeyStrokeToButton(this, "MINUS", "expx", expXButton); - - histButton = SwarmUtil.createToolBarButton(Icons.timeback, "Last time settings (Backspace)", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - back(); - } - }); - UiUtils.mapKeyStrokeToButton(this, "BACK_SPACE", "back", histButton); - toolbar.add(histButton); - toolbar.addSeparator(); - - waveToolbar = new WaveViewSettingsToolbar(null, toolbar, this); - - toolbar.addSeparator(); - - toolbar.add(Box.createHorizontalGlue()); - - throbber = new Throbber(); - toolbar.add(throbber); - - // UiUtils.mapKeyStrokeToAction(this, "control A", "selectAll", new AbstractAction() { - // private static final long serialVersionUID = 1L; - // - // public void actionPerformed(final ActionEvent e) { - // for (final PickerWavePanel wave : waves) - // select(wave); - // } - // }); - } - - private void addHistory(final AbstractWavePanel wvp, final double[] t) { - Stack history = histories.get(wvp); - if (history == null) { - history = new Stack(); - histories.put(wvp, history); - } - history.push(t); - } - - public void gotoTime(final AbstractWavePanel wvp, String t) { - double j2k = Double.NaN; - try { - if (t.length() == 12) - t = t + "30"; - - j2k = J2kSec.parse("yyyyMMddHHmmss", t); - } catch (final Exception e) { - JOptionPane.showMessageDialog(applicationFrame, "Illegal time value.", "Error", - JOptionPane.ERROR_MESSAGE); - } - - if (!Double.isNaN(j2k)) { - double dt = 60; - if (wvp.getWave() != null) { - final double st = wvp.getStartTime(); - final double et = wvp.getEndTime(); - final double[] ts = new double[] {st, et}; - addHistory(wvp, ts); - dt = (et - st); - } - - final double tzo = - swarmConfig.getTimeZone(wvp.getChannel()).getOffset(System.currentTimeMillis()) / 1000; - - final double nst = j2k - tzo - dt / 2; - final double net = nst + dt; - - fetchNewWave(wvp, nst, net); - } - } - - // TODO: This isn't right, this should be a method of waveviewpanel - private void fetchNewWave(final AbstractWavePanel wvp, final double nst, final double net) { - final SwingWorker worker = new SwingWorker() { - @Override - public Object construct() { - throbber.increment(); - final SeismicDataSource sds = wvp.getDataSource(); - // Hacky fix for bug #84 - Wave sw = null; - if (sds instanceof CachedDataSource) - sw = ((CachedDataSource) sds).getBestWave(wvp.getChannel(), nst, net); - else - sw = sds.getWave(wvp.getChannel(), nst, net); - wvp.setWave(sw, nst, net); - wvp.repaint(); - return null; - } - - @Override - public void finished() { - throbber.decrement(); - repaint(); - } - }; - worker.start(); - } - - - public void gotoTime(final String t) { - for (final AbstractWavePanel p : selectedSet) - gotoTime(p, t); - } - - public void scaleTime(final AbstractWavePanel wvp, final double pct) { - final double st = wvp.getStartTime(); - final double et = wvp.getEndTime(); - final double[] t = new double[] {st, et}; - addHistory(wvp, t); - final double dt = (et - st) * (1 - pct); - final double mt = (et - st) / 2 + st; - final double nst = mt - dt / 2; - final double net = mt + dt / 2; - fetchNewWave(wvp, nst, net); - } - - public void scaleTime(final double pct) { - for (final AbstractWavePanel p : selectedSet) - scaleTime(p, pct); - } - - public void back(final AbstractWavePanel wvp) { - final Stack history = histories.get(wvp); - if (history == null || history.empty()) - return; - - final double[] t = history.pop(); - fetchNewWave(wvp, t[0], t[1]); - } - - public void back() { - for (final AbstractWavePanel p : selectedSet) - back(p); - } - - private void shiftTime(final AbstractWavePanel wvp, final double pct) { - final double st = wvp.getStartTime(); - final double et = wvp.getEndTime(); - final double[] t = new double[] {st, et}; - addHistory(wvp, t); - final double dt = (et - st) * pct; - final double nst = st + dt; - final double net = et + dt; - fetchNewWave(wvp, nst, net); - } - - public void shiftTime(final double pct) { - for (final AbstractWavePanel p : selectedSet) - shiftTime(p, pct); - } - - // TODO: don't write image on event thread - // TODO: unify with MapFrame.CaptureActionListener - class CaptureActionListener implements ActionListener { - public void actionPerformed(final ActionEvent e) { - // if (waves == null || waves.size() == 0) - // return; - // - // final JFileChooser chooser = FileChooser.getFileChooser(); - // final File lastPath = new File(swarmConfig.lastPath); - // chooser.setCurrentDirectory(lastPath); - // chooser.setSelectedFile(new File("clipboard.png")); - // chooser.setDialogTitle("Save Clipboard Screen Capture"); - // final int result = chooser.showSaveDialog(applicationFrame); - // File f = null; - // if (result == JFileChooser.APPROVE_OPTION) { - // f = chooser.getSelectedFile(); - // - // if (f.exists()) { - // final int choice = JOptionPane.showConfirmDialog(applicationFrame, - // "File exists, overwrite?", "Confirm", JOptionPane.YES_NO_OPTION); - // if (choice != JOptionPane.YES_OPTION) - // return; - // } - // swarmConfig.lastPath = f.getParent(); - // } - // if (f == null) - // return; - // - // int height = 0; - // final int width = waves.get(0).getWidth(); - // for (final AbstractWavePanel panel : waves) - // height += panel.getHeight(); - // - // final BufferedImage image = new BufferedImage(width, height, - // BufferedImage.TYPE_4BYTE_ABGR); - // final Graphics g = image.getGraphics(); - // for (final AbstractWavePanel panel : waves) { - // panel.paint(g); - // g.translate(0, panel.getHeight()); - // } - // try { - // final PngEncoderB png = new PngEncoderB(image, false, PngEncoder.FILTER_NONE, 7); - // final FileOutputStream out = new FileOutputStream(f); - // final byte[] bytes = png.pngEncode(); - // out.write(bytes); - // out.close(); - // } catch (final Exception ex) { - // ex.printStackTrace(); - // } - } - } - - - private class SaveActionListener implements ActionListener { - public void actionPerformed(final ActionEvent e) { - // final AbstractWavePanel selected = getSingleSelected(); - // if (selected == null) - // return; - // - // final JFileChooser chooser = FileChooser.getFileChooser(); - // chooser.resetChoosableFileFilters(); - // chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); - // chooser.setMultiSelectionEnabled(false); - // chooser.setDialogTitle("Save Wave"); - // - // for (final FileType ft : FileType.values()) { - // if (ft == FileType.UNKNOWN) - // continue; - // - // final ExtensionFileFilter f = new ExtensionFileFilter(ft.extension, ft.description); - // chooser.addChoosableFileFilter(f); - // } - // - // chooser.setFileFilter(chooser.getAcceptAllFileFilter()); - // - // final File lastPath = new File(swarmConfig.lastPath); - // chooser.setCurrentDirectory(lastPath); - // final String fileName = selected.getChannel().replace(' ', '_') + ".sac"; - // chooser.setSelectedFile(new File(fileName)); - // final int result = chooser.showSaveDialog(applicationFrame); - // if (result == JFileChooser.APPROVE_OPTION) { - // final File f = chooser.getSelectedFile(); - // boolean confirm = true; - // if (f.exists()) { - // if (f.isDirectory()) { - // JOptionPane.showMessageDialog(applicationFrame, - // "You can not select an existing directory.", "Error", JOptionPane.ERROR_MESSAGE); - // return; - // } - // confirm = false; - // final int choice = JOptionPane.showConfirmDialog(applicationFrame, - // "File exists, overwrite?", "Confirm", JOptionPane.YES_NO_OPTION); - // if (choice == JOptionPane.YES_OPTION) - // confirm = true; - // } - // - // if (confirm) { - // try { - // swarmConfig.lastPath = f.getParent(); - // final String fn = f.getPath(); - // final SeismicDataFile file = SeismicDataFile.getFile(fn); - // final Wave wave = selected.getWave(); - // file.putWave(selected.getChannel(), wave); - // file.write(); - // } catch (final FileNotFoundException ex) { - // JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Directory does not exist.", - // "Error", JOptionPane.ERROR_MESSAGE); - // } catch (final IOException ex) { - // JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Error writing file.", - // "Error", JOptionPane.ERROR_MESSAGE); - // } - // } - // } - } - } - - private void doSizePopup() { - // if (popup == null) { - // final String[] labels = new String[] {"Auto", null, "Tiny", "Small", "Medium", "Large"}; - // final int[] sizes = new int[] {-1, -1, 50, 100, 160, 230}; - // popup = new JPopupMenu(); - // final ButtonGroup group = new ButtonGroup(); - // for (int i = 0; i < labels.length; i++) { - // if (labels[i] != null) { - // final int size = sizes[i]; - // final JRadioButtonMenuItem mi = new JRadioButtonMenuItem(labels[i]); - // mi.addActionListener(new ActionListener() { - // public void actionPerformed(final ActionEvent e) { - // setWaveHeight(size); - // } - // }); - // if (waveHeight == size) - // mi.setSelected(true); - // group.add(mi); - // popup.add(mi); - // } else - // popup.addSeparator(); - // } - // } - // popup.show(sizeButton.getParent(), sizeButton.getX(), sizeButton.getY()); - } - - public void fetchDetailedEvent() { - final String neicEvid = event.getEventSource() + event.getEvid(); - final Event workingEvent = event; - - String url = "http://earthquake.usgs.gov/fdsnws/event/1/query?eventid=" + neicEvid; - - DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder dBuilder = null; - Document doc = null; - - try { - dBuilder = dbFactory.newDocumentBuilder(); - doc = dBuilder.parse(url); - doc.getDocumentElement().normalize(); - - NodeList eventElements = doc.getElementsByTagName("event"); - Element eventElement = (Element) eventElements.item(0); - NodeList descriptionNodes = eventElement.getElementsByTagName("description"); - for (int idx = 0; idx < descriptionNodes.getLength(); idx++) { - eventElement.removeChild(descriptionNodes.item(idx)); - } - workingEvent.updateEvent(eventElement); - } catch (SAXException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } catch (IOException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } catch (ParserConfigurationException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - private void populatePicks() { - Origin origin = event.getPreferredOrigin(); - - long firstPick = Long.MAX_VALUE; - long lastPick = Long.MIN_VALUE; - for (Arrival arrival : origin.getArrivals()) { - Pick pick = arrival.getPick(); - firstPick = Math.min(pick.getTime(), firstPick); - lastPick = Math.max(pick.getTime(), lastPick); - } - - double waveStart = J2kSec.fromEpoch(firstPick) - 1; - double waveEnd = J2kSec.fromEpoch(lastPick) + 1; - LOGGER.debug("wave span {} - {}", waveStart, waveEnd); - - pickBox.setStart(waveStart); - pickBox.setEnd(waveEnd); - - throbber.increment(); - for (Arrival arrival : origin.getArrivals()) { - if (closing) { - break; - } - pickBox.addPick(arrival); - mainPanel.validate(); - LOGGER.debug("pickBox {}", pickBox.countComponents()); - } - throbber.decrement(); - } - - @Override - public void paint(final Graphics g) { - super.paint(g); - // if (waves.size() == 0) { - // final Dimension dim = this.getSize(); - // g.setColor(Color.black); - // g.drawString("Picker empty.", dim.width / 2 - 40, dim.height / 2); - // } - } - - @Override - public void setVisible(final boolean isVisible) { - LOGGER.debug("Visible = {}", isVisible); - super.setVisible(isVisible); - if (isVisible) - toFront(); - } - - public void eventUpdated() { - mainPanel.setTopComponent(createParameterPanel()); - mainPanel.setBottomComponent(createPickPanel()); - } - - private void createListeners() { - this.addInternalFrameListener(new InternalFrameAdapter() { - @Override - public void internalFrameActivated(final InternalFrameEvent e) {} - - @Override - public void internalFrameDeiconified(final InternalFrameEvent e) {} - - @Override - public void internalFrameClosing(final InternalFrameEvent e) { - closing = true; - dispose(); - SwarmInternalFrames.remove(EventFrame3.this); - } - - @Override - public void internalFrameClosed(final InternalFrameEvent e) {} - }); - - this.addComponentListener(new ComponentAdapter() { - @Override - public void componentResized(final ComponentEvent e) {} - }); - } - - // private synchronized void createImage() { - // if (getWidth() > 0 && getHeight() > 0) - // image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_4BYTE_ABGR); - // } - -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/ParameterPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/event/ParameterPanel.java new file mode 100644 index 00000000..8bd8b8b3 --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/ParameterPanel.java @@ -0,0 +1,211 @@ +package gov.usgs.volcanoes.swarm.event; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.awt.Component; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.text.SimpleDateFormat; + +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.ScrollPaneConstants; +import javax.swing.SwingConstants; + +public class ParameterPanel { + private static final Logger LOGGER = LoggerFactory.getLogger(ParameterPanel.class); + private static final Font KEY_FONT = Font.decode("dialog-BOLD-12"); + private static final Font VALUE_FONT = Font.decode("dialog-12"); + + private ParameterPanel() {} + + public static Component create(Event event) { + Origin origin = event.getPreferredOrigin(); + Magnitude magnitude = event.getPerferredMagnitude(); + + JPanel parameterPanel = new JPanel(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.NORTHWEST; + c.gridy = 0; + c.gridx = GridBagConstraints.RELATIVE; + c.ipadx = 3; + c.ipady = 2; + + JLabel label; + + label = new JLabel("Event source: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + String source = Networks.getInstance().getName(event.getEventSource().toUpperCase()); + if (source == null) { + source = event.getEventSource(); + } + label = new JLabel(Networks.getInstance().getName(event.getEventSource().toUpperCase()), + SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + + c.gridy++; + + label = new JLabel("Description: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + // wrap description to support multi-line descriptions + String description = event.getDescription(); + description = description.replace("\n", "
"); + description = "" + description + ""; + label = new JLabel(description, SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + + c.gridy++; + + label = new JLabel("Origin date: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + if (origin != null) { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + String date = dateFormat.format(event.getPreferredOrigin().getTime()); + label = new JLabel(date, SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + } + c.gridy++; + + + label = new JLabel("Hypocenter: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + if (origin != null) { + String loc = origin.getLatitude() + ", " + origin.getLongitude(); + loc += " at " + (origin.getDepth() / 1000) + " km depth"; + label = new JLabel(loc, SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + } + c.gridy++; + + label = new JLabel("Error (RMS): ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + double error = origin.getStandardError(); + if (!Double.isNaN(error)) { + label = new JLabel("" + error, SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + } + c.gridy++; + + label = new JLabel("Azimuthal gap: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + double gap = origin.getAzimuthalGap(); + if (!Double.isNaN(gap)) { + label = new JLabel("" + gap + "\u00B0", SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + } + c.gridy++; + + label = new JLabel("Nearest station: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + double distance = origin.getMinimumDistance(); + if (!Double.isNaN(distance)) { + label = new JLabel("" + distance + "\u00B0", SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + } + c.gridy++; + + label = new JLabel("Phase count: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + int phaseCount = origin.getPhaseCount(); + if (phaseCount > 0) { + label = new JLabel("" + phaseCount, SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + } + c.gridy++; + + label = new JLabel("Magnitude: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + if (magnitude != null) { + String mag = String.format("%s %s", magnitude.getMag(), magnitude.getType()); + String uncertaintly = magnitude.getUncertainty(); + if (uncertaintly != null) { + mag += " (" + uncertaintly + ")"; + } + label = new JLabel(mag, SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + } + c.gridy++; + + label = new JLabel("Evalutation: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + String evaluationTag = ""; + + Origin.EvaluationMode evaluationMode = origin.getEvaluationMode(); + if (evaluationMode != null) { + evaluationTag += evaluationMode.toString().toLowerCase(); + } + + Origin.EvaluationStatus evaluationStatus = origin.getEvaluationStatus(); + if (evaluationStatus != null) { + if (evaluationTag.length() > 0) { + evaluationTag += " / "; + } + evaluationTag += evaluationStatus.toString().toLowerCase(); + } + + label = new JLabel(evaluationTag, SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + + c.gridy++; + + label = new JLabel("Event id: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + label = new JLabel(event.getEvid(), SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + c.gridy++; + + c.weighty = 1; + c.weightx = 1; + c.gridy++; + c.gridx = 10; + JPanel filler = new JPanel(); + parameterPanel.add(filler, c); + + final JScrollPane scrollPane = new JScrollPane(parameterPanel); + scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); + scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + scrollPane.getVerticalScrollBar().setUnitIncrement(40); + + return scrollPane; + } + +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java index 80f3ca72..2e311bbe 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java @@ -1,49 +1,87 @@ package gov.usgs.volcanoes.swarm.event; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; +import java.awt.MouseInfo; +import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; +import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileOutputStream; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; +import java.util.Stack; +import java.util.concurrent.ConcurrentSkipListSet; import javax.swing.BoxLayout; +import javax.swing.JFileChooser; +import javax.swing.JFrame; import javax.swing.JLabel; +import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JViewport; import javax.swing.Scrollable; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import javax.swing.SwingUtilities; import gov.usgs.plot.data.Wave; +import gov.usgs.volcanoes.core.contrib.PngEncoder; +import gov.usgs.volcanoes.core.contrib.PngEncoderB; +import gov.usgs.volcanoes.swarm.FileChooser; +import gov.usgs.volcanoes.swarm.Swarm; +import gov.usgs.volcanoes.swarm.SwarmConfig; +import gov.usgs.volcanoes.swarm.chooser.DataChooser; import gov.usgs.volcanoes.swarm.data.SeismicDataSource; import gov.usgs.volcanoes.swarm.data.fdsnWs.WebServicesSource; +import gov.usgs.volcanoes.swarm.picker.Phase; +import gov.usgs.volcanoes.swarm.picker.PickerWavePanel; +import gov.usgs.volcanoes.swarm.wave.AbstractWavePanel; +import gov.usgs.volcanoes.swarm.wave.WaveViewPanelAdapter; import gov.usgs.volcanoes.swarm.wave.WaveViewPanelListener; public class PickPanel extends JPanel implements Scrollable { private static final long serialVersionUID = 1L; private static final Logger LOGGER = LoggerFactory.getLogger(PickPanel.class); + private static final int DEFAULT_WAVE_PANEL_HEIGHT = 150; + private static final Color SELECT_COLOR = new Color(200, 220, 241); + private static final Color BACKGROUND_COLOR = new Color(0xf7, 0xf7, 0xf7); - private static final String IRIS_DATASELECT_URL = "http://service.iris.edu/fdsnws/dataselect/1/query"; + private static final String IRIS_DATASELECT_URL = + "http://service.iris.edu/fdsnws/dataselect/1/query"; private static final String IRIS_STATION_URL = "http://service.iris.edu/fdsnws/station/1/query"; - - private BufferedImage image; + + protected static final JFrame applicationFrame = Swarm.getApplicationFrame(); + + private final Map> histories; + private final Set selectedSet; private final Map panels; + + private BufferedImage image; private double startJ2k; private double endJ2k; private final JLabel statusLabel; private WaveViewPanelListener selectListener; private final Map seismicSources; + private int wavePanelHeight; + private int lastClickedIndex; public PickPanel(JLabel statusLabel) { this.statusLabel = statusLabel; panels = new HashMap(); seismicSources = new HashMap(); - + histories = new HashMap>(); +// selectedSet = new HashSet(); + selectedSet = new ConcurrentSkipListSet(); + wavePanelHeight = DEFAULT_WAVE_PANEL_HEIGHT; + setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); addComponentListener(new ComponentAdapter() { @Override @@ -57,8 +95,76 @@ public void componentResized(final ComponentEvent e) { resizeWaves(); } }); + + selectListener = new WaveViewPanelAdapter() { + public void mousePressed(final AbstractWavePanel src, final MouseEvent e, + final boolean dragging) { + PickWavePanel panel = (PickWavePanel) src; + LOGGER.debug("wave selected."); + requestFocusInWindow(); + final int thisIndex = getWaveIndex(src); + if (!e.isControlDown() && !e.isShiftDown() && !e.isAltDown()) { + deselectAll(); + select(panel); + } else if (e.isControlDown()) { + if (selectedSet.contains(src)) + deselect(src); + else + select(panel); + } else if (e.isShiftDown()) { + if (lastClickedIndex == -1) { + select(panel); + } else { + deselectAll(); + final int min = Math.min(lastClickedIndex, thisIndex); + final int max = Math.max(lastClickedIndex, thisIndex); + PickWavePanel[] wavePanels = panels.values().toArray(new PickWavePanel[0]); + for (int i = min; i <= max; i++) { + select(wavePanels[i]); + } + } + } + lastClickedIndex = thisIndex; + // event.notifyObservers(); + validate(); + repaint(); + } + + @Override + public void waveZoomed(final AbstractWavePanel src, final double st, final double et, + final double nst, final double net) { + final double[] t = new double[] {st, et}; + addHistory(src, t); + for (final AbstractWavePanel wvp : selectedSet) { + if (wvp != src) { + addHistory(wvp, t); + wvp.zoom(nst, net); + } + } + } + + @Override + public void waveClosed(final AbstractWavePanel src) { + LOGGER.debug("Removing wave: {}", src.getChannel()); + remove(src); + } + }; + } + + protected int getWaveIndex(AbstractWavePanel src) { + + int panelIndex = -1; + AbstractWavePanel[] wavePanels = panels.values().toArray(new AbstractWavePanel[0]); + int idx = 0; + while (panelIndex < 0 && idx < wavePanels.length) { + if (src == wavePanels[idx]) { + panelIndex = idx; + } + } + + return panelIndex; } - + public void setStart(Double startJ2k) { this.startJ2k = startJ2k; @@ -98,7 +204,7 @@ public void addPick(Arrival arrival) { wavePanel = new PickWavePanel(); wavePanel.setStatusLabel(statusLabel); wavePanel.setChannel(channel); - wavePanel.setViewport(((JViewport)getParent())); + wavePanel.setViewport(((JViewport) getParent())); SeismicDataSource source = seismicSources.get(channel); if (source == null) { source = new WebServicesSource(); @@ -107,32 +213,32 @@ public void addPick(Arrival arrival) { wavePanel.setDataSource(source); Wave wave = source.getWave(channel, startJ2k, endJ2k); if (wave != null) { - panels.put(pick.getChannel(), wavePanel); + panels.put(pick.getChannel(), wavePanel); wavePanel.setWave(wave, startJ2k, endJ2k); add(wavePanel); -// add(Box.createRigidArea(new Dimension(0, 10))); -// p.setSize(w, calculateWaveHeight()); + // add(Box.createRigidArea(new Dimension(0, 10))); + // p.setSize(w, calculateWaveHeight()); wavePanel.setBottomBorderColor(Color.GRAY); - wavePanel.setSize(getWidth(), 100); + wavePanel.setSize(getWidth(), wavePanelHeight); wavePanel.setDisplayTitle(true); wavePanel.setOffsets(54, 8, 21, 19); wavePanel.createImage(); wavePanel.addListener(selectListener); } } - + wavePanel.addArrival(arrival); } - + private String buildParams(String channel) { String[] comps = channel.split("\\$"); LOGGER.debug("SPLIT {}", channel); StringBuilder sb = new StringBuilder(); sb.append(comps[2]).append("|"); sb.append(comps[0]).append("|"); - + if (comps.length > 3) { - sb.append(comps[3]).append("|"); + sb.append(comps[3]).append("|"); } else { sb.append("--|"); } @@ -144,11 +250,12 @@ private String buildParams(String channel) { return sb.toString(); } - private synchronized void resizeWaves() { + + private void resizeWaves() { for (PickWavePanel panel : panels.values().toArray(new PickWavePanel[0])) { Dimension d = panel.getSize(); - - panel.setSize(getWidth(), d.height); + + panel.setSize(getWidth(), wavePanelHeight); panel.createImage(); panel.repaint(); } @@ -174,4 +281,102 @@ public boolean getScrollableTracksViewportHeight() { // TODO Auto-generated method stub return false; } -} \ No newline at end of file + + public void setWaveHeight(int height) { + wavePanelHeight = height; + resizeWaves(); + } + + + public void writeImage() { + SwarmConfig swarmConfig = SwarmConfig.getInstance(); + if (panels.size() == 0) + return; + + final JFileChooser chooser = FileChooser.getFileChooser(); + final File lastPath = new File(swarmConfig.lastPath); + chooser.setCurrentDirectory(lastPath); + chooser.setSelectedFile(new File("clipboard.png")); + chooser.setDialogTitle("Save Clipboard Screen Capture"); + final int result = chooser.showSaveDialog(applicationFrame); + File f = null; + if (result == JFileChooser.APPROVE_OPTION) { + f = chooser.getSelectedFile(); + + if (f.exists()) { + final int choice = JOptionPane.showConfirmDialog(applicationFrame, + "File exists, overwrite?", "Confirm", JOptionPane.YES_NO_OPTION); + if (choice != JOptionPane.YES_OPTION) + return; + } + swarmConfig.lastPath = f.getParent(); + } + if (f == null) + return; + + int height = 0; + + AbstractWavePanel[] panelArray = panels.values().toArray(new AbstractWavePanel[0]); + final int width = panelArray[0].getWidth(); + for (final AbstractWavePanel panel : panelArray) { + height += panel.getHeight(); + } + + final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); + final Graphics g = image.getGraphics(); + for (final AbstractWavePanel panel : panelArray) { + panel.paint(g); + g.translate(0, panel.getHeight()); + } + try { + final PngEncoderB png = new PngEncoderB(image, false, PngEncoder.FILTER_NONE, 7); + final FileOutputStream out = new FileOutputStream(f); + final byte[] bytes = png.pngEncode(); + out.write(bytes); + out.close(); + } catch (final Exception ex) { + ex.printStackTrace(); + } + } + + + private void deselect(final AbstractWavePanel p) { + selectedSet.remove(p); + p.setBackgroundColor(BACKGROUND_COLOR); + p.createImage(); + } + + private void deselectAll() { + final AbstractWavePanel[] panels = selectedSet.toArray(new AbstractWavePanel[0]); + for (final AbstractWavePanel p : panels) { + deselect(p); + } + } + + private void select(final PickWavePanel p) { + if (p == null || selectedSet.contains(p)) + return; + + selectedSet.add(p); + p.setBackgroundColor(SELECT_COLOR); + DataChooser.getInstance().setNearest(p.getChannel()); + p.createImage(); + } + + private void findWavePanel() { + Point p = MouseInfo.getPointerInfo().getLocation(); + SwingUtilities.convertPointFromScreen(p, this); + int idx = p.y / wavePanelHeight; + PickWavePanel panel = panels.get(idx); + } + + private void addHistory(final AbstractWavePanel wvp, final double[] t) { + Stack history = histories.get(wvp); + if (history == null) { + history = new Stack(); + histories.put(wvp, history); + } + history.push(t); + } + +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java index 51176aa8..dba875fa 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java @@ -165,8 +165,13 @@ public void draw(Graphics2D g2) { Origin origin = event.getPreferredOrigin(); LOGGER.debug("Plotting event at {}, {}", origin.getLongitude(), origin.getLatitude()); - final Point2D.Double xy = - projection.forward(new Point2D.Double(origin.getLongitude(), origin.getLatitude())); + Point2D.Double originLoc = new Point2D.Double(origin.getLongitude(), origin.getLatitude()); + if (!range.contains(originLoc)) { + continue; + } + + final Point2D.Double xy = projection.forward(originLoc); + final double[] ext = range.getProjectedExtents(projection); final double dx = (ext[1] - ext[0]); final double dy = (ext[3] - ext[2]); @@ -175,7 +180,7 @@ public void draw(Graphics2D g2) { res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); g2.translate(res.x, res.y); - long age = J2kSec.asEpoch(J2kSec.now()); + long age = J2kSec.asEpoch(J2kSec.now()) - origin.getTime(); if (event == hoverEvent) { renderer.paint = Color.GREEN; } else if (age < ONE_HOUR) { From 35abca6e82a64ea48a322426c5633248d7a42ffa Mon Sep 17 00:00:00 2001 From: tparker Date: Tue, 22 Mar 2016 06:56:22 -0800 Subject: [PATCH 16/67] ToolBar rework in progress... --- .../volcanoes/swarm/event/EventFrame.java | 296 +---------------- .../swarm/event/PickBoxListener.java | 5 + .../usgs/volcanoes/swarm/event/PickPanel.java | 121 ++++++- .../volcanoes/swarm/event/PickToolBar.java | 306 ++++++++++++++++++ .../swarm/event/PickToolBarListener.java | 9 + .../volcanoes/swarm/event/PickWavePanel.java | 6 +- .../swarm/wave/WaveToolBarListener.java | 5 + .../volcanoes/swarm/wave/WaveViewToolBar.java | 223 +++++++++++++ .../swarm/wave/WaveViewToolBarListener.java | 5 + 9 files changed, 680 insertions(+), 296 deletions(-) create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/PickBoxListener.java create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBar.java create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBarListener.java create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/wave/WaveToolBarListener.java create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewToolBar.java create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewToolBarListener.java diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java index d8b136cc..e2e620b8 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java @@ -1,12 +1,5 @@ package gov.usgs.volcanoes.swarm.event; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Font; @@ -44,6 +37,13 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + import gov.usgs.plot.data.Wave; import gov.usgs.volcanoes.core.time.J2kSec; import gov.usgs.volcanoes.core.util.UiUtils; @@ -78,22 +78,7 @@ public class EventFrame extends SwarmFrame implements EventObserver { private JSplitPane mainPanel; private Event event; - private JToolBar toolbar; - private JButton sizeButton; - private JButton saveButton; - private JButton captureButton; - private JButton histButton; - - private WaveViewSettingsToolbar waveToolbar; - - private JButton compXButton; - private JButton expXButton; - private JButton forwardButton; - private JButton backButton; - private JButton gotoButton; - private Throbber throbber; - private JPopupMenu popup; - private int waveHeight; + private PickToolBar toolbar; private boolean closing = false; @@ -143,9 +128,7 @@ public void finished() { private JPanel createPickPanel() { - toolbar = SwarmUtil.createToolBar(); - createMainButtons(); - createWaveButtons(); + toolbar = new PickToolBar(); final JScrollPane scrollPane = new JScrollPane(pickBox); scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); @@ -168,259 +151,6 @@ private JPanel createPickPanel() { return pickPanel; } - private void createMainButtons() { - sizeButton = - SwarmUtil.createToolBarButton(Icons.resize, "Set wave height", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - doSizePopup(); - } - }); - toolbar.add(sizeButton); - - toolbar.addSeparator(); - captureButton = SwarmUtil.createToolBarButton(Icons.camera, "Save pick image (P)", - new CaptureActionListener()); - UiUtils.mapKeyStrokeToButton(this, "P", "capture", captureButton); - toolbar.add(captureButton); - } - - - private void createWaveButtons() { - toolbar.addSeparator(); - - backButton = SwarmUtil.createToolBarButton(Icons.left, "Scroll back time 20% (Left arrow)", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - shiftTime(-0.20); - } - }); - UiUtils.mapKeyStrokeToButton(this, "LEFT", "backward1", backButton); - toolbar.add(backButton); - - forwardButton = SwarmUtil.createToolBarButton(Icons.right, - "Scroll forward time 20% (Right arrow)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - shiftTime(0.20); - } - }); - toolbar.add(forwardButton); - UiUtils.mapKeyStrokeToButton(this, "RIGHT", "forward1", forwardButton); - - gotoButton = - SwarmUtil.createToolBarButton(Icons.gototime, "Go to time (Ctrl-G)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - final String t = JOptionPane.showInputDialog(applicationFrame, - "Input time in 'YYYYMMDDhhmm[ss]' format:", "Go to Time", - JOptionPane.PLAIN_MESSAGE); - if (t != null) - gotoTime(t); - } - }); - toolbar.add(gotoButton); - UiUtils.mapKeyStrokeToButton(this, "ctrl G", "goto", gotoButton); - - compXButton = SwarmUtil.createToolBarButton(Icons.xminus, - "Shrink sample time 20% (Alt-left arrow, +)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - scaleTime(0.20); - } - }); - toolbar.add(compXButton); - UiUtils.mapKeyStrokeToButton(this, "alt LEFT", "compx", compXButton); - UiUtils.mapKeyStrokeToButton(this, "EQUALS", "compx2", compXButton); - UiUtils.mapKeyStrokeToButton(this, "shift EQUALS", "compx2", compXButton); - - expXButton = SwarmUtil.createToolBarButton(Icons.xplus, - "Expand sample time 20% (Alt-right arrow, -)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - scaleTime(-0.20); - } - }); - toolbar.add(expXButton); - UiUtils.mapKeyStrokeToButton(this, "alt RIGHT", "expx", expXButton); - UiUtils.mapKeyStrokeToButton(this, "MINUS", "expx", expXButton); - - histButton = SwarmUtil.createToolBarButton(Icons.timeback, "Last time settings (Backspace)", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - back(); - } - }); - UiUtils.mapKeyStrokeToButton(this, "BACK_SPACE", "back", histButton); - toolbar.add(histButton); - toolbar.addSeparator(); - - waveToolbar = new WaveViewSettingsToolbar(null, toolbar, this); - - toolbar.addSeparator(); - - toolbar.add(Box.createHorizontalGlue()); - - throbber = new Throbber(); - toolbar.add(throbber); - - // UiUtils.mapKeyStrokeToAction(this, "control A", "selectAll", new AbstractAction() { - // private static final long serialVersionUID = 1L; - // - // public void actionPerformed(final ActionEvent e) { - // for (final PickerWavePanel wave : waves) - // select(wave); - // } - // }); - } - - private void addHistory(final AbstractWavePanel wvp, final double[] t) { - Stack history = histories.get(wvp); - if (history == null) { - history = new Stack(); - histories.put(wvp, history); - } - history.push(t); - } - - public void gotoTime(final AbstractWavePanel wvp, String t) { - double j2k = Double.NaN; - try { - if (t.length() == 12) - t = t + "30"; - - j2k = J2kSec.parse("yyyyMMddHHmmss", t); - } catch (final Exception e) { - JOptionPane.showMessageDialog(applicationFrame, "Illegal time value.", "Error", - JOptionPane.ERROR_MESSAGE); - } - - if (!Double.isNaN(j2k)) { - double dt = 60; - if (wvp.getWave() != null) { - final double st = wvp.getStartTime(); - final double et = wvp.getEndTime(); - final double[] ts = new double[] {st, et}; - addHistory(wvp, ts); - dt = (et - st); - } - - final double tzo = - swarmConfig.getTimeZone(wvp.getChannel()).getOffset(System.currentTimeMillis()) / 1000; - - final double nst = j2k - tzo - dt / 2; - final double net = nst + dt; - - fetchNewWave(wvp, nst, net); - } - } - - // TODO: This isn't right, this should be a method of waveviewpanel - private void fetchNewWave(final AbstractWavePanel wvp, final double nst, final double net) { - final SwingWorker worker = new SwingWorker() { - @Override - public Object construct() { - throbber.increment(); - final SeismicDataSource sds = wvp.getDataSource(); - // Hacky fix for bug #84 - Wave sw = null; - if (sds instanceof CachedDataSource) - sw = ((CachedDataSource) sds).getBestWave(wvp.getChannel(), nst, net); - else - sw = sds.getWave(wvp.getChannel(), nst, net); - wvp.setWave(sw, nst, net); - wvp.repaint(); - return null; - } - - @Override - public void finished() { - throbber.decrement(); - repaint(); - } - }; - worker.start(); - } - - - public void gotoTime(final String t) { - for (final AbstractWavePanel p : selectedSet) - gotoTime(p, t); - } - - public void scaleTime(final AbstractWavePanel wvp, final double pct) { - final double st = wvp.getStartTime(); - final double et = wvp.getEndTime(); - final double[] t = new double[] {st, et}; - addHistory(wvp, t); - final double dt = (et - st) * (1 - pct); - final double mt = (et - st) / 2 + st; - final double nst = mt - dt / 2; - final double net = mt + dt / 2; - fetchNewWave(wvp, nst, net); - } - - public void scaleTime(final double pct) { - for (final AbstractWavePanel p : selectedSet) - scaleTime(p, pct); - } - - public void back(final AbstractWavePanel wvp) { - final Stack history = histories.get(wvp); - if (history == null || history.empty()) - return; - - final double[] t = history.pop(); - fetchNewWave(wvp, t[0], t[1]); - } - - public void back() { - for (final AbstractWavePanel p : selectedSet) - back(p); - } - - private void shiftTime(final AbstractWavePanel wvp, final double pct) { - final double st = wvp.getStartTime(); - final double et = wvp.getEndTime(); - final double[] t = new double[] {st, et}; - addHistory(wvp, t); - final double dt = (et - st) * pct; - final double nst = st + dt; - final double net = et + dt; - fetchNewWave(wvp, nst, net); - } - - public void shiftTime(final double pct) { - for (final AbstractWavePanel p : selectedSet) - shiftTime(p, pct); - } - - class CaptureActionListener implements ActionListener { - public void actionPerformed(final ActionEvent e) { - pickBox.writeImage(); - } - } - - private void doSizePopup() { - if (popup == null) { - final String[] labels = new String[] {"Auto", null, "Tiny", "Small", "Medium", "Large"}; - final int[] sizes = new int[] {-1, -1, 50, 100, 160, 230}; - popup = new JPopupMenu(); - final ButtonGroup group = new ButtonGroup(); - for (int i = 0; i < labels.length; i++) { - if (labels[i] != null) { - final int size = sizes[i]; - final JRadioButtonMenuItem mi = new JRadioButtonMenuItem(labels[i]); - mi.addActionListener(new ActionListener() { - public void actionPerformed(final ActionEvent e) { - pickBox.setWaveHeight(size); - } - }); - if (waveHeight == size) - mi.setSelected(true); - group.add(mi); - popup.add(mi); - } else - popup.addSeparator(); - } - } - popup.show(sizeButton.getParent(), sizeButton.getX(), sizeButton.getY()); - } public void fetchDetailedEvent() { final String neicEvid = event.getEventSource() + event.getEvid(); @@ -474,7 +204,7 @@ private void populatePicks() { pickBox.setStart(waveStart); pickBox.setEnd(waveEnd); - throbber.increment(); + toolbar.incrementThrobber(); TreeSet arrivals = new TreeSet(Arrival.distanceComparator()); arrivals.addAll(origin.getArrivals()); for (Arrival arrival : arrivals) { @@ -485,7 +215,7 @@ private void populatePicks() { mainPanel.validate(); LOGGER.debug("pickBox {}", pickBox.countComponents()); } - throbber.decrement(); + toolbar.decrementThrobber(); } @Override @@ -530,4 +260,6 @@ public void internalFrameClosed(final InternalFrameEvent e) {} public void componentResized(final ComponentEvent e) {} }); } -} + + + } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickBoxListener.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickBoxListener.java new file mode 100644 index 00000000..b7349089 --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickBoxListener.java @@ -0,0 +1,5 @@ +package gov.usgs.volcanoes.swarm.event; + +public interface PickBoxListener { + public void selectCountChanged(int count); +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java index 2e311bbe..19f156a8 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java @@ -1,8 +1,5 @@ package gov.usgs.volcanoes.swarm.event; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; @@ -32,22 +29,25 @@ import javax.swing.Scrollable; import javax.swing.SwingUtilities; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import gov.usgs.plot.data.Wave; import gov.usgs.volcanoes.core.contrib.PngEncoder; import gov.usgs.volcanoes.core.contrib.PngEncoderB; import gov.usgs.volcanoes.swarm.FileChooser; import gov.usgs.volcanoes.swarm.Swarm; import gov.usgs.volcanoes.swarm.SwarmConfig; +import gov.usgs.volcanoes.swarm.SwingWorker; import gov.usgs.volcanoes.swarm.chooser.DataChooser; +import gov.usgs.volcanoes.swarm.data.CachedDataSource; import gov.usgs.volcanoes.swarm.data.SeismicDataSource; import gov.usgs.volcanoes.swarm.data.fdsnWs.WebServicesSource; -import gov.usgs.volcanoes.swarm.picker.Phase; -import gov.usgs.volcanoes.swarm.picker.PickerWavePanel; import gov.usgs.volcanoes.swarm.wave.AbstractWavePanel; import gov.usgs.volcanoes.swarm.wave.WaveViewPanelAdapter; import gov.usgs.volcanoes.swarm.wave.WaveViewPanelListener; -public class PickPanel extends JPanel implements Scrollable { +public class PickPanel extends JPanel implements Scrollable, PickToolBarListener { private static final long serialVersionUID = 1L; private static final Logger LOGGER = LoggerFactory.getLogger(PickPanel.class); private static final int DEFAULT_WAVE_PANEL_HEIGHT = 150; @@ -72,13 +72,15 @@ public class PickPanel extends JPanel implements Scrollable { private final Map seismicSources; private int wavePanelHeight; private int lastClickedIndex; + private final Set listeners; public PickPanel(JLabel statusLabel) { this.statusLabel = statusLabel; panels = new HashMap(); seismicSources = new HashMap(); histories = new HashMap>(); -// selectedSet = new HashSet(); + listeners = new HashSet(); + // selectedSet = new HashSet(); selectedSet = new ConcurrentSkipListSet(); wavePanelHeight = DEFAULT_WAVE_PANEL_HEIGHT; @@ -100,9 +102,9 @@ public void componentResized(final ComponentEvent e) { public void mousePressed(final AbstractWavePanel src, final MouseEvent e, final boolean dragging) { PickWavePanel panel = (PickWavePanel) src; - LOGGER.debug("wave selected."); requestFocusInWindow(); final int thisIndex = getWaveIndex(src); + if (!e.isControlDown() && !e.isShiftDown() && !e.isAltDown()) { deselectAll(); select(panel); @@ -151,14 +153,22 @@ public void waveClosed(final AbstractWavePanel src) { }; } + public void addListener(PickBoxListener listener) { + listeners.add(listener); + } + protected int getWaveIndex(AbstractWavePanel src) { - int panelIndex = -1; AbstractWavePanel[] wavePanels = panels.values().toArray(new AbstractWavePanel[0]); + int idx = 0; + int panelIndex = -1; while (panelIndex < 0 && idx < wavePanels.length) { + if (src == wavePanels[idx]) { panelIndex = idx; + } else { + idx++; } } @@ -251,7 +261,7 @@ private String buildParams(String channel) { return sb.toString(); } - private void resizeWaves() { + private void resizeWaves() { for (PickWavePanel panel : panels.values().toArray(new PickWavePanel[0])) { Dimension d = panel.getSize(); @@ -340,20 +350,24 @@ public void writeImage() { } - private void deselect(final AbstractWavePanel p) { + private void deselect(final AbstractWavePanel p) { + LOGGER.debug("start deselect"); selectedSet.remove(p); p.setBackgroundColor(BACKGROUND_COLOR); p.createImage(); + LOGGER.debug("complete deselect"); } - private void deselectAll() { + private void deselectAll() { final AbstractWavePanel[] panels = selectedSet.toArray(new AbstractWavePanel[0]); for (final AbstractWavePanel p : panels) { deselect(p); } + notifyListeners(); } - private void select(final PickWavePanel p) { + private void select(final PickWavePanel p) { + LOGGER.debug("start select"); if (p == null || selectedSet.contains(p)) return; @@ -361,8 +375,14 @@ private void select(final PickWavePanel p) { p.setBackgroundColor(SELECT_COLOR); DataChooser.getInstance().setNearest(p.getChannel()); p.createImage(); + notifyListeners(); } + private void notifyListeners() { + for (PickBoxListener listener : listeners) { + listener.selectCountChanged(selectedSet.size()); + } + } private void findWavePanel() { Point p = MouseInfo.getPointerInfo().getLocation(); SwingUtilities.convertPointFromScreen(p, this); @@ -379,4 +399,79 @@ private void addHistory(final AbstractWavePanel wvp, final double[] t) { history.push(t); } + public void scaleTime(final AbstractWavePanel wvp, final double pct) { + final double st = wvp.getStartTime(); + final double et = wvp.getEndTime(); + final double[] t = new double[] {st, et}; + addHistory(wvp, t); + final double dt = (et - st) * (1 - pct); + final double mt = (et - st) / 2 + st; + final double nst = mt - dt / 2; + final double net = mt + dt / 2; + fetchNewWave(wvp, nst, net); + } + public void scaleTime(final double pct) { + for (final AbstractWavePanel p : selectedSet) + scaleTime(p, pct); + } + + public void back(final AbstractWavePanel wvp) { + final Stack history = histories.get(wvp); + if (history == null || history.empty()) + return; + + final double[] t = history.pop(); +// fetchNewWave(wvp, t[0], t[1]); + } + + public void back() { + for (final AbstractWavePanel p : selectedSet) + back(p); + } + + private void shiftTime(final AbstractWavePanel wvp, final double pct) { + LOGGER.debug("shifting time {}", pct); + final double st = wvp.getStartTime(); + final double et = wvp.getEndTime(); + final double[] t = new double[] {st, et}; + addHistory(wvp, t); + final double dt = (et - st) * pct; + final double nst = st + dt; + final double net = et + dt; + fetchNewWave(wvp, nst, net); + } + + public void shiftTime(final double pct) { + for (final AbstractWavePanel p : selectedSet) + shiftTime(p, pct); + } + + // TODO: This isn't right, this should be a method of waveviewpanel + private void fetchNewWave(final AbstractWavePanel wvp, final double nst, final double net) { + final SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { +// throbber.increment(); + final SeismicDataSource sds = wvp.getDataSource(); + // Hacky fix for bug #84 + Wave sw = null; + if (sds instanceof CachedDataSource) + sw = ((CachedDataSource) sds).getBestWave(wvp.getChannel(), nst, net); + else + sw = sds.getWave(wvp.getChannel(), nst, net); + wvp.setWave(sw, nst, net); + wvp.repaint(); + return null; + } + + @Override + public void finished() { +// throbber.decrement(); + repaint(); + } + }; + worker.start(); + } + + } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBar.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBar.java new file mode 100644 index 00000000..48da8dc3 --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBar.java @@ -0,0 +1,306 @@ +package gov.usgs.volcanoes.swarm.event; + +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.HashSet; +import java.util.Set; +import java.util.Stack; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JOptionPane; +import javax.swing.JPopupMenu; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.JToolBar; + +import gov.usgs.plot.data.Wave; +import gov.usgs.volcanoes.core.time.J2kSec; +import gov.usgs.volcanoes.core.util.UiUtils; +import gov.usgs.volcanoes.swarm.Icons; +import gov.usgs.volcanoes.swarm.Swarm; +import gov.usgs.volcanoes.swarm.SwarmConfig; +import gov.usgs.volcanoes.swarm.SwarmUtil; +import gov.usgs.volcanoes.swarm.SwingWorker; +import gov.usgs.volcanoes.swarm.Throbber; +import gov.usgs.volcanoes.swarm.data.CachedDataSource; +import gov.usgs.volcanoes.swarm.data.SeismicDataSource; +import gov.usgs.volcanoes.swarm.wave.AbstractWavePanel; +import gov.usgs.volcanoes.swarm.wave.WaveViewSettingsToolbar; + +public class PickToolBar extends JToolBar implements PickBoxListener { + + private final static SwarmConfig swarmConfig = SwarmConfig.getInstance(); + private final static Component applicationFrame = Swarm.getApplicationFrame(); + + private JButton sizeButton; + private JButton saveButton; + private JButton captureButton; + private JButton histButton; + + private WaveViewSettingsToolbar waveToolbar; + + private JButton compXButton; + private JButton expXButton; + private JButton forwardButton; + private JButton backButton; + private JButton gotoButton; + private Throbber throbber; + private JPopupMenu popup; + private int waveHeight; + + private PickPanel pickBox; + private PickToolBarListener listener; + + public PickToolBar() { + setFloatable(false); + setRollover(true); + setBorder(BorderFactory.createEmptyBorder(1, 0, 0, 0)); + } + + public void setPickBox(PickPanel pickBox) { + this.pickBox = pickBox; + } + + public void selectCountChanged(int count) { + boolean enable = count > 0; + histButton.setEnabled(enable); + compXButton.setEnabled(enable); + expXButton.setEnabled(enable); + forwardButton.setEnabled(enable); + backButton.setEnabled(enable); + gotoButton.setEnabled(enable); + } + + private void createMainButtons() { + sizeButton = + SwarmUtil.createToolBarButton(Icons.resize, "Set wave height", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + doSizePopup(); + } + }); + add(sizeButton); + + addSeparator(); + captureButton = SwarmUtil.createToolBarButton(Icons.camera, "Save pick image (P)", + new CaptureActionListener()); + UiUtils.mapKeyStrokeToButton(this, "P", "capture", captureButton); + add(captureButton); + } + + + private void createWaveButtons() { + addSeparator(); + + backButton = SwarmUtil.createToolBarButton(Icons.left, "Scroll back time 20% (Left arrow)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + shiftTime(-0.20); + } + }); + UiUtils.mapKeyStrokeToButton(this, "LEFT", "backward1", backButton); + add(backButton); + backButton.setEnabled(false); + + forwardButton = SwarmUtil.createToolBarButton(Icons.right, + "Scroll forward time 20% (Right arrow)", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + shiftTime(0.20); + } + }); + add(forwardButton); + UiUtils.mapKeyStrokeToButton(this, "RIGHT", "forward1", forwardButton); + forwardButton.setEnabled(false); + // gotoButton = + // SwarmUtil.createToolBarButton(Icons.gototime, "Go to time (Ctrl-G)", new ActionListener() { + // public void actionPerformed(final ActionEvent e) { + // final String t = JOptionPane.showInputDialog(applicationFrame, + // "Input time in 'YYYYMMDDhhmm[ss]' format:", "Go to Time", + // JOptionPane.PLAIN_MESSAGE); + // if (t != null) + // gotoTime(t); + // } + // }); + // toolbar.add(gotoButton); + // UiUtils.mapKeyStrokeToButton(this, "ctrl G", "goto", gotoButton); + + compXButton = SwarmUtil.createToolBarButton(Icons.xminus, + "Shrink sample time 20% (Alt-left arrow, +)", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + scaleTime(0.20); + } + }); + add(compXButton); + UiUtils.mapKeyStrokeToButton(this, "alt LEFT", "compx", compXButton); + UiUtils.mapKeyStrokeToButton(this, "EQUALS", "compx2", compXButton); + UiUtils.mapKeyStrokeToButton(this, "shift EQUALS", "compx2", compXButton); + compXButton.setEnabled(false); + + expXButton = SwarmUtil.createToolBarButton(Icons.xplus, + "Expand sample time 20% (Alt-right arrow, -)", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + scaleTime(-0.20); + } + }); + add(expXButton); + UiUtils.mapKeyStrokeToButton(this, "alt RIGHT", "expx", expXButton); + UiUtils.mapKeyStrokeToButton(this, "MINUS", "expx", expXButton); + expXButton.setEnabled(false); + + histButton = SwarmUtil.createToolBarButton(Icons.timeback, "Last time settings (Backspace)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + back(); + } + }); + UiUtils.mapKeyStrokeToButton(this, "BACK_SPACE", "back", histButton); + add(histButton); + addSeparator(); + histButton.setEnabled(false); + waveToolbar = new WaveViewSettingsToolbar(null, this, listener); + + addSeparator(); + + add(Box.createHorizontalGlue()); + + throbber = new Throbber(); + add(throbber); + + // UiUtils.mapKeyStrokeToAction(this, "control A", "selectAll", new AbstractAction() { + // private static final long serialVersionUID = 1L; + // + // public void actionPerformed(final ActionEvent e) { + // for (final PickerWavePanel wave : waves) + // select(wave); + // } + // }); + } + +// private void addHistory(final AbstractWavePanel wvp, final double[] t) { +// Stack history = histories.get(wvp); +// if (history == null) { +// history = new Stack(); +// histories.put(wvp, history); +// } +// history.push(t); +// } + +// public void gotoTime(final AbstractWavePanel wvp, String t) { +// double j2k = Double.NaN; +// try { +// if (t.length() == 12) +// t = t + "30"; +// +// j2k = J2kSec.parse("yyyyMMddHHmmss", t); +// } catch (final Exception e) { +// JOptionPane.showMessageDialog(applicationFrame, "Illegal time value.", "Error", +// JOptionPane.ERROR_MESSAGE); +// } +// +// if (!Double.isNaN(j2k)) { +// double dt = 60; +// if (wvp.getWave() != null) { +// final double st = wvp.getStartTime(); +// final double et = wvp.getEndTime(); +// final double[] ts = new double[] {st, et}; +// addHistory(wvp, ts); +// dt = (et - st); +// } +// +// final double tzo = +// swarmConfig.getTimeZone(wvp.getChannel()).getOffset(System.currentTimeMillis()) / 1000; +// +// final double nst = j2k - tzo - dt / 2; +// final double net = nst + dt; +// +// fetchNewWave(wvp, nst, net); +// } +// } + + // TODO: This isn't right, this should be a method of waveviewpanel + private void fetchNewWave(final AbstractWavePanel wvp, final double nst, final double net) { + final SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + throbber.increment(); + final SeismicDataSource sds = wvp.getDataSource(); + // Hacky fix for bug #84 + Wave sw = null; + if (sds instanceof CachedDataSource) + sw = ((CachedDataSource) sds).getBestWave(wvp.getChannel(), nst, net); + else + sw = sds.getWave(wvp.getChannel(), nst, net); + wvp.setWave(sw, nst, net); + wvp.repaint(); + return null; + } + + @Override + public void finished() { + throbber.decrement(); + repaint(); + } + }; + worker.start(); + } + + + public void gotoTime(final String t) { + listener.gotoTime(t); + } + + public void scaleTime(final double pct) { + pickBox.scaleTime(pct); + } + + public void back() { + pickBox.back(); + } + + public void shiftTime(final double pct) { + pickBox.shiftTime(pct); + } + + class CaptureActionListener implements ActionListener { + public void actionPerformed(final ActionEvent e) { + pickBox.writeImage(); + } + } + + private void doSizePopup() { + if (popup == null) { + final String[] labels = new String[] {"Auto", null, "Tiny", "Small", "Medium", "Large"}; + final int[] sizes = new int[] {-1, -1, 50, 100, 160, 230}; + popup = new JPopupMenu(); + final ButtonGroup group = new ButtonGroup(); + for (int i = 0; i < labels.length; i++) { + if (labels[i] != null) { + final int size = sizes[i]; + final JRadioButtonMenuItem mi = new JRadioButtonMenuItem(labels[i]); + mi.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + pickBox.setWaveHeight(size); + } + }); + if (waveHeight == size) + mi.setSelected(true); + group.add(mi); + popup.add(mi); + } else + popup.addSeparator(); + } + } + popup.show(sizeButton.getParent(), sizeButton.getX(), sizeButton.getY()); + } + + public void incrementThrobber() { + throbber.increment();; + } + + public void decrementThrobber() { + throbber.decrement();; + } + +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBarListener.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBarListener.java new file mode 100644 index 00000000..ef57f043 --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBarListener.java @@ -0,0 +1,9 @@ +package gov.usgs.volcanoes.swarm.event; + +import gov.usgs.volcanoes.swarm.wave.WaveViewToolBarListener; + +public interface PickToolBarListener extends WaveViewToolBarListener { + public void setWaveHeight(int height); + + public void gotoTime(String t); +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java index a27c3ba2..3c7de5b7 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java @@ -25,7 +25,7 @@ import gov.usgs.volcanoes.swarm.wave.AbstractWavePanel; import gov.usgs.volcanoes.swarm.wave.WaveViewPanelAdapter; -public class PickWavePanel extends AbstractWavePanel implements EventObserver { +public class PickWavePanel extends AbstractWavePanel implements EventObserver, Comparable { private static final Logger LOGGER = LoggerFactory.getLogger(PickWavePanel.class); @@ -131,6 +131,10 @@ protected void processRightMousePress(MouseEvent e) { public void setViewport(JViewport viewport) { this.viewport = viewport; + } + + public int compareTo(PickWavePanel o) { + return Arrival.distanceComparator().compare(arrivals.get(0),o.arrivals.get(0)); } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveToolBarListener.java b/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveToolBarListener.java new file mode 100644 index 00000000..d0a1bd3e --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveToolBarListener.java @@ -0,0 +1,5 @@ +package gov.usgs.volcanoes.swarm.wave; + +public interface WaveToolBarListener { + +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewToolBar.java b/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewToolBar.java new file mode 100644 index 00000000..def4e6fb --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewToolBar.java @@ -0,0 +1,223 @@ +package gov.usgs.volcanoes.swarm.wave; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.AbstractAction; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JToggleButton; +import javax.swing.JToolBar; +import javax.swing.KeyStroke; + +import gov.usgs.volcanoes.core.ui.UiUtils; +import gov.usgs.volcanoes.swarm.Icons; +import gov.usgs.volcanoes.swarm.SwarmUtil; +import gov.usgs.volcanoes.swarm.wave.WaveViewSettings.ViewType; + +public class WaveViewToolBar { + private JButton waveSet; + private JToggleButton waveToggle; + private JToggleButton spectraToggle; + private JToggleButton spectrogramToggle; + private ButtonGroup waveTypes; + private WaveViewToolBarListener listener; + + public WaveViewToolBar(WaveViewSettings s, JToolBar dest, WaveViewToolBarListener listener) + { + this.listener = listener; + createUI(dest); + setSettings(s); + } + + public void createUI(JToolBar dest) + { + waveSet = SwarmUtil.createToolBarButton( + Icons.wavesettings, + "Wave view settings (?)", + new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + if (settingsSet.size()==0) + return; + WaveViewSettings s = settingsSet.iterator().next(); + WaveViewSettingsDialog wvsd = WaveViewSettingsDialog.getInstance(s, settingsSet.size()); + wvsd.setVisible(true); + for (WaveViewSettings settings : settingsSet) + { + settings.copy(s); + settings.notifyView(); + } + } + }); + UiUtils.mapKeyStrokeToButton(keyComp, "shift SLASH", "settings", waveSet); + dest.add(waveSet); + + waveToggle = SwarmUtil.createToolBarToggleButton( + Icons.wave, + "Wave view (W or ,)", + new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + for (WaveViewSettings settings : settingsSet) + settings.setType(ViewType.WAVE); + } + }); + UiUtils.mapKeyStrokeToButton(keyComp, "COMMA", "wave1", waveToggle); + UiUtils.mapKeyStrokeToButton(keyComp, "W", "wave2", waveToggle); + dest.add(waveToggle); + + spectraToggle = SwarmUtil.createToolBarToggleButton( + Icons.spectra, + "Spectra view (S or .)", + new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + for (WaveViewSettings settings : settingsSet) + settings.setType(ViewType.SPECTRA); + } + }); + UiUtils.mapKeyStrokeToButton(keyComp, "PERIOD", "spectra1", spectraToggle); + UiUtils.mapKeyStrokeToButton(keyComp, "S", "spectra2", spectraToggle); + dest.add(spectraToggle); + + spectrogramToggle = SwarmUtil.createToolBarToggleButton( + Icons.spectrogram, + "Spectrogram view (G or /)", + new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + for (WaveViewSettings settings : settingsSet) + settings.setType(ViewType.SPECTROGRAM); + } + }); + UiUtils.mapKeyStrokeToButton(keyComp, "SLASH", "spectrogram1", spectrogramToggle); + UiUtils.mapKeyStrokeToButton(keyComp, "G", "spectrogram2", spectrogramToggle); + dest.add(spectrogramToggle); + + keyComp.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("L"), "cycleLogSettings"); + keyComp.getActionMap().put("cycleLogSettings", new AbstractAction() + { + public static final long serialVersionUID = -1; + public void actionPerformed(ActionEvent e) + { + for (WaveViewSettings settings : settingsSet) { + if (settings.viewType == ViewType.SPECTRA) + settings.cycleLogSettings(); + if (settings.viewType == ViewType.SPECTROGRAM) + settings.toggleLogPower(); + } + } + }); + + keyComp.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("F"), "toggleFilter"); + keyComp.getActionMap().put("toggleFilter", new AbstractAction() + { + public static final long serialVersionUID = -1; + public void actionPerformed(ActionEvent e) + { + for (WaveViewSettings settings : settingsSet) + settings.toggleFilter(); + } + }); + + keyComp.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("R"), "resetAutoScale"); + keyComp.getActionMap().put("resetAutoScale", new AbstractAction() + { + public static final long serialVersionUID = -1; + public void actionPerformed(ActionEvent e) + { + for (WaveViewSettings settings : settingsSet) + settings.resetAutoScaleMemory(); + } + }); + + keyComp.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("OPEN_BRACKET"), "yScaleIn"); + keyComp.getActionMap().put("yScaleIn", new AbstractAction() + { + public static final long serialVersionUID = -1; + public void actionPerformed(ActionEvent e) + { + for (WaveViewSettings settings : settingsSet) { + settings.adjustScale(1.0 / 1.25); + } + } + }); + + keyComp.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("CLOSE_BRACKET"), "yScaleOut"); + keyComp.getActionMap().put("yScaleOut", new AbstractAction() + { + public static final long serialVersionUID = -1; + public void actionPerformed(ActionEvent e) + { + for (WaveViewSettings settings : settingsSet) + settings.adjustScale(1.25); + } + }); + + waveTypes = new ButtonGroup(); + waveTypes.add(waveToggle); + waveTypes.add(spectraToggle); + waveTypes.add(spectrogramToggle); + } + + public void clearSettingsSet() + { + settingsSet.clear(); + } + + public void addSettings(WaveViewSettings s) + { + if (s != null) + { + settingsSet.add(s); + s.toolbar = this; + settingsChanged(); + } + } + + public void removeSettings(WaveViewSettings s) + { + settingsSet.remove(s); + if (s != null) + { + s.toolbar = null; + settingsChanged(); + } + } + + public void setSettings(WaveViewSettings s) + { + clearSettingsSet(); + addSettings(s); + } + + public void settingsChanged() + { + boolean w = false; + boolean s = false; + boolean sg = false; + for (WaveViewSettings set : settingsSet) + { + if (set.viewType == ViewType.WAVE) + w = true; + if (set.viewType == ViewType.SPECTRA) + s = true; + if (set.viewType == ViewType.SPECTROGRAM) + sg = true; + } + + // fix for Java 1.5, clearSelection was added in 1.6 + try { + waveTypes.setSelected( waveTypes.getSelection(), false ); + } catch (Throwable e) {} + waveToggle.setSelected(w && !s && !sg); + spectraToggle.setSelected(!w && s && !sg); + spectrogramToggle.setSelected(!w && !s && sg); + } +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewToolBarListener.java b/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewToolBarListener.java new file mode 100644 index 00000000..be310c41 --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewToolBarListener.java @@ -0,0 +1,5 @@ +package gov.usgs.volcanoes.swarm.wave; + +public interface WaveViewToolBarListener { + +} From e0ef114a752139474058d8003daa29b24cd2d872 Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Tue, 22 Mar 2016 12:48:08 -0800 Subject: [PATCH 17/67] Event frame checkpoint. Things are looking better. --- .../gov/usgs/volcanoes/swarm/event/Event.java | 33 +- .../volcanoes/swarm/event/EventFrame.java | 89 ++---- .../volcanoes/swarm/event/ParameterPanel.java | 11 + .../event/{PickPanel.java => PickBox.java} | 162 +++++++--- .../volcanoes/swarm/event/PickToolBar.java | 284 ++++++------------ .../swarm/event/PickToolBarListener.java | 11 +- .../volcanoes/swarm/event/PickWavePanel.java | 16 +- .../swarm/wave/AbstractWavePanel.java | 4 +- .../volcanoes/swarm/wave/WaveViewToolBar.java | 260 ++++------------ .../swarm/wave/WaveViewToolBarListener.java | 8 +- 10 files changed, 361 insertions(+), 517 deletions(-) rename src/main/java/gov/usgs/volcanoes/swarm/event/{PickPanel.java => PickBox.java} (79%) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java index 531efcff..38f9f499 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java @@ -2,23 +2,16 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.w3c.dom.Node; import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; -import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - import gov.usgs.volcanoes.core.util.StringUtils; -import gov.usgs.volcanoes.swarm.SwarmConfig; public class Event { @@ -29,12 +22,13 @@ public class Event { private final Map magnitudes; private final Map picks; private final List observers; - + private Origin preferredOrigin; private Magnitude preferredMagnitude; private String description; private String eventSource; private String evid; + private String type; public Event(String publicId) { this.publicId = publicId; @@ -83,6 +77,23 @@ public void updateEvent(Element event) { descriptionElement.getElementsByTagName("text").item(0).getTextContent(), description); } + // Element typeElement = (Element) event.getElementsByTagName("type").item(0); + NodeList childList = event.getChildNodes(); + String newType = null; + int idx = 0; + while (type == null && idx < childList.getLength()) { + Node node = childList.item(idx); + if (node.getNodeType() == Node.ELEMENT_NODE) { + Element element = (Element) node; + if (element.getTagName() == "type") { + type = element.getTextContent(); + } + idx++; + } + } + + type = StringUtils.stringToString(newType, type); + notifyObservers(); } @@ -145,6 +156,10 @@ public String getDescription() { return description; } + public String getType() { + return type; + } + public void setDescription(String description) { this.description = description; } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java index e2e620b8..3c4f35cf 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java @@ -1,34 +1,23 @@ package gov.usgs.volcanoes.swarm.event; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + import java.awt.BorderLayout; import java.awt.Dimension; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; import java.io.IOException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.Stack; import java.util.TreeSet; import javax.swing.BorderFactory; -import javax.swing.Box; import javax.swing.BoxLayout; -import javax.swing.ButtonGroup; -import javax.swing.JButton; import javax.swing.JLabel; -import javax.swing.JOptionPane; import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JRadioButtonMenuItem; import javax.swing.JScrollPane; import javax.swing.JSplitPane; -import javax.swing.JToolBar; import javax.swing.ScrollPaneConstants; import javax.swing.WindowConstants; import javax.swing.event.InternalFrameAdapter; @@ -37,27 +26,11 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - -import gov.usgs.plot.data.Wave; import gov.usgs.volcanoes.core.time.J2kSec; -import gov.usgs.volcanoes.core.util.UiUtils; import gov.usgs.volcanoes.swarm.Icons; import gov.usgs.volcanoes.swarm.SwarmFrame; -import gov.usgs.volcanoes.swarm.SwarmUtil; import gov.usgs.volcanoes.swarm.SwingWorker; -import gov.usgs.volcanoes.swarm.Throbber; -import gov.usgs.volcanoes.swarm.data.CachedDataSource; -import gov.usgs.volcanoes.swarm.data.SeismicDataSource; import gov.usgs.volcanoes.swarm.internalFrame.SwarmInternalFrames; -import gov.usgs.volcanoes.swarm.picker.PickerWavePanel; -import gov.usgs.volcanoes.swarm.wave.AbstractWavePanel; -import gov.usgs.volcanoes.swarm.wave.WaveViewSettingsToolbar; /** * The picker internal frame. Adapted from the WaveClipboardFrame. @@ -66,20 +39,14 @@ */ public class EventFrame extends SwarmFrame implements EventObserver { private static final Logger LOGGER = LoggerFactory.getLogger(EventFrame.class); - private static final Font KEY_FONT = Font.decode("dialog-BOLD-12"); - private static final Font VALUE_FONT = Font.decode("dialog-12"); - public static final long serialVersionUID = -1; - private final PickPanel pickBox; + private final PickBox pickBox; private final JLabel statusLabel; - private final Map> histories; - private final Set selectedSet; + private final Event event; private JSplitPane mainPanel; - private Event event; private PickToolBar toolbar; - private boolean closing = false; public EventFrame(Event event) { @@ -87,12 +54,9 @@ public EventFrame(Event event) { this.event = event; statusLabel = new JLabel(" "); - pickBox = new PickPanel(statusLabel); + pickBox = new PickBox(statusLabel); pickBox.setLayout(new BoxLayout(pickBox, BoxLayout.PAGE_AXIS)); - histories = new HashMap>(); - selectedSet = new HashSet(); - event.addObserver(this); this.setFocusable(true); createListeners(); @@ -101,7 +65,6 @@ public EventFrame(Event event) { setSize(swarmConfig.clipboardWidth, swarmConfig.clipboardHeight); setLocation(swarmConfig.clipboardX, swarmConfig.clipboardY); setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - LOGGER.debug("event frame: {} @ {}", this.getSize(), this.getLocation()); mainPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT, ParameterPanel.create(event), createPickPanel()); @@ -109,7 +72,7 @@ public EventFrame(Event event) { setContentPane(mainPanel); this.setVisible(true); - + new SwingWorker() { @Override public Object construct() { @@ -128,16 +91,17 @@ public void finished() { private JPanel createPickPanel() { - toolbar = new PickToolBar(); + JPanel pickPanel = new JPanel(); + pickPanel.setLayout(new BoxLayout(pickPanel, BoxLayout.PAGE_AXIS)); + + toolbar = new PickToolBar(pickBox); + pickPanel.add(toolbar); + pickBox.addListener(toolbar); + final JScrollPane scrollPane = new JScrollPane(pickBox); scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); scrollPane.getVerticalScrollBar().setUnitIncrement(40); - - JPanel pickPanel = new JPanel(); - pickPanel.setLayout(new BoxLayout(pickPanel, BoxLayout.PAGE_AXIS)); - LOGGER.info("Adding toolbar"); - pickPanel.add(toolbar); pickPanel.add(scrollPane); JPanel statusPanel = new JPanel(); @@ -199,7 +163,6 @@ private void populatePicks() { double waveStart = J2kSec.fromEpoch(firstPick) - 1; double waveEnd = J2kSec.fromEpoch(lastPick) + 1; - LOGGER.debug("wave span {} - {}", waveStart, waveEnd); pickBox.setStart(waveStart); pickBox.setEnd(waveEnd); @@ -213,19 +176,12 @@ private void populatePicks() { } pickBox.addPick(arrival); mainPanel.validate(); - LOGGER.debug("pickBox {}", pickBox.countComponents()); } toolbar.decrementThrobber(); } - @Override - public void paint(final Graphics g) { - super.paint(g); - } - @Override public void setVisible(final boolean isVisible) { - LOGGER.debug("Visible = {}", isVisible); super.setVisible(isVisible); if (isVisible) toFront(); @@ -254,12 +210,5 @@ public void internalFrameClosing(final InternalFrameEvent e) { @Override public void internalFrameClosed(final InternalFrameEvent e) {} }); - - this.addComponentListener(new ComponentAdapter() { - @Override - public void componentResized(final ComponentEvent e) {} - }); } - - - } +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/ParameterPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/event/ParameterPanel.java index 8bd8b8b3..c8c3b5ce 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/ParameterPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/ParameterPanel.java @@ -81,6 +81,17 @@ public static Component create(Event event) { } c.gridy++; + label = new JLabel("Type: ", SwingConstants.LEFT); + label.setFont(KEY_FONT); + parameterPanel.add(label, c); + + if (origin != null) { + label = new JLabel(event.getType(), SwingConstants.LEFT); + label.setFont(VALUE_FONT); + parameterPanel.add(label, c); + } + c.gridy++; + label = new JLabel("Hypocenter: ", SwingConstants.LEFT); label.setFont(KEY_FONT); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickBox.java similarity index 79% rename from src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java rename to src/main/java/gov/usgs/volcanoes/swarm/event/PickBox.java index 19f156a8..0a0f394b 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickBox.java @@ -1,10 +1,11 @@ package gov.usgs.volcanoes.swarm.event; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; -import java.awt.MouseInfo; -import java.awt.Point; import java.awt.Rectangle; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; @@ -14,11 +15,14 @@ import java.io.FileOutputStream; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.Stack; import java.util.concurrent.ConcurrentSkipListSet; +import java.util.concurrent.CopyOnWriteArrayList; +import javax.swing.AbstractButton; import javax.swing.BoxLayout; import javax.swing.JFileChooser; import javax.swing.JFrame; @@ -27,29 +31,27 @@ import javax.swing.JPanel; import javax.swing.JViewport; import javax.swing.Scrollable; -import javax.swing.SwingUtilities; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import gov.usgs.plot.data.Wave; import gov.usgs.volcanoes.core.contrib.PngEncoder; import gov.usgs.volcanoes.core.contrib.PngEncoderB; +import gov.usgs.volcanoes.core.time.J2kSec; +import gov.usgs.volcanoes.core.util.UiUtils; import gov.usgs.volcanoes.swarm.FileChooser; import gov.usgs.volcanoes.swarm.Swarm; import gov.usgs.volcanoes.swarm.SwarmConfig; import gov.usgs.volcanoes.swarm.SwingWorker; -import gov.usgs.volcanoes.swarm.chooser.DataChooser; import gov.usgs.volcanoes.swarm.data.CachedDataSource; import gov.usgs.volcanoes.swarm.data.SeismicDataSource; import gov.usgs.volcanoes.swarm.data.fdsnWs.WebServicesSource; import gov.usgs.volcanoes.swarm.wave.AbstractWavePanel; import gov.usgs.volcanoes.swarm.wave.WaveViewPanelAdapter; import gov.usgs.volcanoes.swarm.wave.WaveViewPanelListener; +import gov.usgs.volcanoes.swarm.wave.WaveViewSettings.ViewType; -public class PickPanel extends JPanel implements Scrollable, PickToolBarListener { +public class PickBox extends JPanel implements Scrollable, PickToolBarListener { private static final long serialVersionUID = 1L; - private static final Logger LOGGER = LoggerFactory.getLogger(PickPanel.class); + private static final Logger LOGGER = LoggerFactory.getLogger(PickBox.class); private static final int DEFAULT_WAVE_PANEL_HEIGHT = 150; private static final Color SELECT_COLOR = new Color(200, 220, 241); private static final Color BACKGROUND_COLOR = new Color(0xf7, 0xf7, 0xf7); @@ -59,10 +61,12 @@ public class PickPanel extends JPanel implements Scrollable, PickToolBarListener private static final String IRIS_STATION_URL = "http://service.iris.edu/fdsnws/station/1/query"; protected static final JFrame applicationFrame = Swarm.getApplicationFrame(); + private static final SwarmConfig swarmConfig = SwarmConfig.getInstance(); private final Map> histories; private final Set selectedSet; - private final Map panels; + // private final Map panels; + private final List panels; private BufferedImage image; private double startJ2k; @@ -74,9 +78,10 @@ public class PickPanel extends JPanel implements Scrollable, PickToolBarListener private int lastClickedIndex; private final Set listeners; - public PickPanel(JLabel statusLabel) { + public PickBox(JLabel statusLabel) { this.statusLabel = statusLabel; - panels = new HashMap(); + panels = new CopyOnWriteArrayList(); + seismicSources = new HashMap(); histories = new HashMap>(); listeners = new HashSet(); @@ -108,6 +113,7 @@ public void mousePressed(final AbstractWavePanel src, final MouseEvent e, if (!e.isControlDown() && !e.isShiftDown() && !e.isAltDown()) { deselectAll(); select(panel); + lastClickedIndex = findPanelIndex(panel); } else if (e.isControlDown()) { if (selectedSet.contains(src)) deselect(src); @@ -120,9 +126,8 @@ public void mousePressed(final AbstractWavePanel src, final MouseEvent e, deselectAll(); final int min = Math.min(lastClickedIndex, thisIndex); final int max = Math.max(lastClickedIndex, thisIndex); - PickWavePanel[] wavePanels = panels.values().toArray(new PickWavePanel[0]); for (int i = min; i <= max; i++) { - select(wavePanels[i]); + select(panels.get(i)); } } } @@ -141,6 +146,7 @@ public void waveZoomed(final AbstractWavePanel src, final double st, final doubl if (wvp != src) { addHistory(wvp, t); wvp.zoom(nst, net); + wvp.createImage(); } } } @@ -156,23 +162,21 @@ public void waveClosed(final AbstractWavePanel src) { public void addListener(PickBoxListener listener) { listeners.add(listener); } - - protected int getWaveIndex(AbstractWavePanel src) { - AbstractWavePanel[] wavePanels = panels.values().toArray(new AbstractWavePanel[0]); + protected int getWaveIndex(AbstractWavePanel src) { - int idx = 0; - int panelIndex = -1; - while (panelIndex < 0 && idx < wavePanels.length) { + int panelIdx = -1; + int searchIdx = 0; + while (panelIdx < 0 && searchIdx < panels.size()) { - if (src == wavePanels[idx]) { - panelIndex = idx; + if (src == panels.get(searchIdx)) { + panelIdx = searchIdx; } else { - idx++; + searchIdx++; } } - return panelIndex; + return panelIdx; } @@ -191,8 +195,8 @@ private synchronized void createImage() { @Override public void paint(final Graphics g) { - if (getWidth() <= 0 || getHeight() <= 0) - return; +// if (getWidth() <= 0 || getHeight() <= 0) +// return; if (image == null || panels.size() == 0) { super.paint(g); @@ -209,8 +213,9 @@ public void paint(final Graphics g) { public void addPick(Arrival arrival) { Pick pick = arrival.getPick(); String channel = pick.getChannel(); - PickWavePanel wavePanel = panels.get(channel); - if (wavePanel == null) { + int index = panels.lastIndexOf(channel); + PickWavePanel wavePanel; + if (index < 0) { wavePanel = new PickWavePanel(); wavePanel.setStatusLabel(statusLabel); wavePanel.setChannel(channel); @@ -223,7 +228,7 @@ public void addPick(Arrival arrival) { wavePanel.setDataSource(source); Wave wave = source.getWave(channel, startJ2k, endJ2k); if (wave != null) { - panels.put(pick.getChannel(), wavePanel); + panels.add(wavePanel); wavePanel.setWave(wave, startJ2k, endJ2k); add(wavePanel); // add(Box.createRigidArea(new Dimension(0, 10))); @@ -235,6 +240,8 @@ public void addPick(Arrival arrival) { wavePanel.createImage(); wavePanel.addListener(selectListener); } + } else { + wavePanel = panels.get(index); } wavePanel.addArrival(arrival); @@ -262,12 +269,9 @@ private String buildParams(String channel) { } private void resizeWaves() { - for (PickWavePanel panel : panels.values().toArray(new PickWavePanel[0])) { - Dimension d = panel.getSize(); - + for (PickWavePanel panel : panels) { panel.setSize(getWidth(), wavePanelHeight); panel.createImage(); - panel.repaint(); } } @@ -326,15 +330,14 @@ public void writeImage() { int height = 0; - AbstractWavePanel[] panelArray = panels.values().toArray(new AbstractWavePanel[0]); - final int width = panelArray[0].getWidth(); - for (final AbstractWavePanel panel : panelArray) { + final int width = panels.get(0).getWidth(); + for (final AbstractWavePanel panel : panels) { height += panel.getHeight(); } final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); final Graphics g = image.getGraphics(); - for (final AbstractWavePanel panel : panelArray) { + for (final AbstractWavePanel panel : panels) { panel.paint(g); g.translate(0, panel.getHeight()); } @@ -351,11 +354,10 @@ public void writeImage() { private void deselect(final AbstractWavePanel p) { - LOGGER.debug("start deselect"); selectedSet.remove(p); p.setBackgroundColor(BACKGROUND_COLOR); p.createImage(); - LOGGER.debug("complete deselect"); + notifyListeners(); } private void deselectAll() { @@ -367,13 +369,11 @@ private void deselectAll() { } private void select(final PickWavePanel p) { - LOGGER.debug("start select"); if (p == null || selectedSet.contains(p)) return; selectedSet.add(p); p.setBackgroundColor(SELECT_COLOR); - DataChooser.getInstance().setNearest(p.getChannel()); p.createImage(); notifyListeners(); } @@ -383,11 +383,19 @@ private void notifyListeners() { listener.selectCountChanged(selectedSet.size()); } } - private void findWavePanel() { - Point p = MouseInfo.getPointerInfo().getLocation(); - SwingUtilities.convertPointFromScreen(p, this); - int idx = p.y / wavePanelHeight; - PickWavePanel panel = panels.get(idx); + + private int findPanelIndex(PickWavePanel panel) { + int panelIdx = -1; + int searchIdx = 0; + while (panelIdx < 0 && searchIdx < panels.size()) { + if (panels.get(searchIdx) == panel) { + panelIdx = searchIdx; + } else { + searchIdx++; + } + } + LOGGER.debug("FOUND PANEL {}", panelIdx); + return panelIdx; } private void addHistory(final AbstractWavePanel wvp, final double[] t) { @@ -410,6 +418,7 @@ public void scaleTime(final AbstractWavePanel wvp, final double pct) { final double net = mt + dt / 2; fetchNewWave(wvp, nst, net); } + public void scaleTime(final double pct) { for (final AbstractWavePanel p : selectedSet) scaleTime(p, pct); @@ -421,7 +430,7 @@ public void back(final AbstractWavePanel wvp) { return; final double[] t = history.pop(); -// fetchNewWave(wvp, t[0], t[1]); + fetchNewWave(wvp, t[0], t[1]); } public void back() { @@ -445,13 +454,13 @@ public void shiftTime(final double pct) { for (final AbstractWavePanel p : selectedSet) shiftTime(p, pct); } - + // TODO: This isn't right, this should be a method of waveviewpanel private void fetchNewWave(final AbstractWavePanel wvp, final double nst, final double net) { final SwingWorker worker = new SwingWorker() { @Override public Object construct() { -// throbber.increment(); + // throbber.increment(); final SeismicDataSource sds = wvp.getDataSource(); // Hacky fix for bug #84 Wave sw = null; @@ -466,12 +475,65 @@ public Object construct() { @Override public void finished() { -// throbber.decrement(); + // throbber.decrement(); repaint(); } }; worker.start(); } + public void displaySettingsDialog() { + // TODO Auto-generated method stub + + } + public void mapKeyStroke(String keyStroke, String name, AbstractButton button) { + UiUtils.mapKeyStrokeToButton(this, keyStroke, name, button); + } + + public void setType(ViewType viewType) { + for (AbstractWavePanel panel : selectedSet) { + panel.getSettings().setType(viewType); + panel.createImage(); + } + } + + + public void gotoTime(final AbstractWavePanel wvp, String t) { + double j2k = Double.NaN; + try { + if (t.length() == 12) + t = t + "30"; + + j2k = J2kSec.parse("yyyyMMddHHmmss", t); + } catch (final Exception e) { + JOptionPane.showMessageDialog(applicationFrame, "Illegal time value.", "Error", + JOptionPane.ERROR_MESSAGE); + } + + if (!Double.isNaN(j2k)) { + double dt = 60; + if (wvp.getWave() != null) { + final double st = wvp.getStartTime(); + final double et = wvp.getEndTime(); + final double[] ts = new double[] {st, et}; + addHistory(wvp, ts); + dt = (et - st); + } + + final double tzo = + swarmConfig.getTimeZone(wvp.getChannel()).getOffset(System.currentTimeMillis()) / 1000; + + final double nst = j2k - tzo - dt / 2; + final double net = nst + dt; + + fetchNewWave(wvp, nst, net); + } + wvp.createImage(); + } + + public void gotoTime(final String t) { + for (final AbstractWavePanel p : selectedSet) + gotoTime(p, t); + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBar.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBar.java index 48da8dc3..bc5d18a3 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBar.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBar.java @@ -1,271 +1,188 @@ package gov.usgs.volcanoes.swarm.event; -import java.awt.Component; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.HashSet; -import java.util.Set; -import java.util.Stack; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.ButtonGroup; import javax.swing.JButton; -import javax.swing.JOptionPane; import javax.swing.JPopupMenu; import javax.swing.JRadioButtonMenuItem; import javax.swing.JToolBar; -import gov.usgs.plot.data.Wave; -import gov.usgs.volcanoes.core.time.J2kSec; import gov.usgs.volcanoes.core.util.UiUtils; import gov.usgs.volcanoes.swarm.Icons; -import gov.usgs.volcanoes.swarm.Swarm; -import gov.usgs.volcanoes.swarm.SwarmConfig; import gov.usgs.volcanoes.swarm.SwarmUtil; -import gov.usgs.volcanoes.swarm.SwingWorker; import gov.usgs.volcanoes.swarm.Throbber; -import gov.usgs.volcanoes.swarm.data.CachedDataSource; -import gov.usgs.volcanoes.swarm.data.SeismicDataSource; -import gov.usgs.volcanoes.swarm.wave.AbstractWavePanel; -import gov.usgs.volcanoes.swarm.wave.WaveViewSettingsToolbar; +import gov.usgs.volcanoes.swarm.wave.WaveViewToolBar; public class PickToolBar extends JToolBar implements PickBoxListener { - - private final static SwarmConfig swarmConfig = SwarmConfig.getInstance(); - private final static Component applicationFrame = Swarm.getApplicationFrame(); - - private JButton sizeButton; - private JButton saveButton; - private JButton captureButton; - private JButton histButton; - - private WaveViewSettingsToolbar waveToolbar; - - private JButton compXButton; - private JButton expXButton; - private JButton forwardButton; - private JButton backButton; - private JButton gotoButton; - private Throbber throbber; + private static final long serialVersionUID = 1L; + private final static Logger LOGGER = LoggerFactory.getLogger(PickToolBar.class); + + private final JButton sizeButton; + private final JButton captureButton; + private final JButton histButton; + + private final JButton compXButton; + private final JButton expXButton; + private final JButton forwardButton; + private final JButton backButton; + private final Throbber throbber; + private final WaveViewToolBar waveViewToolBar; private JPopupMenu popup; private int waveHeight; - private PickPanel pickBox; - private PickToolBarListener listener; + private final PickToolBarListener listener; - public PickToolBar() { + public PickToolBar(PickToolBarListener listener) { + this.listener = listener; setFloatable(false); setRollover(true); setBorder(BorderFactory.createEmptyBorder(1, 0, 0, 0)); + + sizeButton = createSizeButton(); + captureButton = createCaptureButton(); + backButton = createBackButton(); + compXButton = createCompXButton(); + expXButton = createExpXButton(); + forwardButton = createForwardButton(); + histButton = createHistButton(); + placeButtons(); + + waveViewToolBar = new WaveViewToolBar(null, this, listener); + selectCountChanged(0); + add(Box.createHorizontalGlue()); + throbber = new Throbber(); + add(throbber); } - public void setPickBox(PickPanel pickBox) { - this.pickBox = pickBox; + public void placeButtons() { + add(sizeButton); + addSeparator(); + add(captureButton); + addSeparator(); + add(backButton); + add(forwardButton); + add(compXButton); + add(expXButton); + add(histButton); + addSeparator(); } public void selectCountChanged(int count) { + LOGGER.debug("New select count {}", count); boolean enable = count > 0; histButton.setEnabled(enable); compXButton.setEnabled(enable); expXButton.setEnabled(enable); forwardButton.setEnabled(enable); backButton.setEnabled(enable); - gotoButton.setEnabled(enable); + waveViewToolBar.setEnabled(enable); } - private void createMainButtons() { - sizeButton = + private JButton createSizeButton() { + JButton sizeButton = SwarmUtil.createToolBarButton(Icons.resize, "Set wave height", new ActionListener() { public void actionPerformed(final ActionEvent e) { doSizePopup(); } }); - add(sizeButton); - addSeparator(); - captureButton = SwarmUtil.createToolBarButton(Icons.camera, "Save pick image (P)", - new CaptureActionListener()); - UiUtils.mapKeyStrokeToButton(this, "P", "capture", captureButton); - add(captureButton); + return sizeButton; } - private void createWaveButtons() { - addSeparator(); + private JButton createCaptureButton() { + JButton captureButton = SwarmUtil.createToolBarButton(Icons.camera, "Save pick image (P)", + new CaptureActionListener()); + listener.mapKeyStroke("P", "capture", captureButton); + + return captureButton; + } - backButton = SwarmUtil.createToolBarButton(Icons.left, "Scroll back time 20% (Left arrow)", - new ActionListener() { + private JButton createBackButton() { + JButton backButton = SwarmUtil.createToolBarButton(Icons.left, + "Scroll back time 20% (Left arrow)", new ActionListener() { public void actionPerformed(final ActionEvent e) { shiftTime(-0.20); } }); - UiUtils.mapKeyStrokeToButton(this, "LEFT", "backward1", backButton); - add(backButton); - backButton.setEnabled(false); + listener.mapKeyStroke("LEFT", "backward1", backButton); - forwardButton = SwarmUtil.createToolBarButton(Icons.right, + return backButton; + } + + private JButton createForwardButton() { + JButton forwardButton = SwarmUtil.createToolBarButton(Icons.right, "Scroll forward time 20% (Right arrow)", new ActionListener() { public void actionPerformed(final ActionEvent e) { shiftTime(0.20); } }); - add(forwardButton); - UiUtils.mapKeyStrokeToButton(this, "RIGHT", "forward1", forwardButton); - forwardButton.setEnabled(false); - // gotoButton = - // SwarmUtil.createToolBarButton(Icons.gototime, "Go to time (Ctrl-G)", new ActionListener() { - // public void actionPerformed(final ActionEvent e) { - // final String t = JOptionPane.showInputDialog(applicationFrame, - // "Input time in 'YYYYMMDDhhmm[ss]' format:", "Go to Time", - // JOptionPane.PLAIN_MESSAGE); - // if (t != null) - // gotoTime(t); - // } - // }); - // toolbar.add(gotoButton); - // UiUtils.mapKeyStrokeToButton(this, "ctrl G", "goto", gotoButton); - - compXButton = SwarmUtil.createToolBarButton(Icons.xminus, + listener.mapKeyStroke("RIGHT", "forward1", forwardButton); + + return forwardButton; + } + + private JButton createCompXButton() { + JButton compXButton = SwarmUtil.createToolBarButton(Icons.xminus, "Shrink sample time 20% (Alt-left arrow, +)", new ActionListener() { public void actionPerformed(final ActionEvent e) { scaleTime(0.20); } }); - add(compXButton); - UiUtils.mapKeyStrokeToButton(this, "alt LEFT", "compx", compXButton); - UiUtils.mapKeyStrokeToButton(this, "EQUALS", "compx2", compXButton); - UiUtils.mapKeyStrokeToButton(this, "shift EQUALS", "compx2", compXButton); - compXButton.setEnabled(false); + listener.mapKeyStroke("alt LEFT", "compx", compXButton); + listener.mapKeyStroke("EQUALS", "compx2", compXButton); + listener.mapKeyStroke("shift EQUALS", "compx2", compXButton); - expXButton = SwarmUtil.createToolBarButton(Icons.xplus, + return compXButton; + } + + private JButton createExpXButton() { + JButton expXButton = SwarmUtil.createToolBarButton(Icons.xplus, "Expand sample time 20% (Alt-right arrow, -)", new ActionListener() { public void actionPerformed(final ActionEvent e) { scaleTime(-0.20); } }); - add(expXButton); - UiUtils.mapKeyStrokeToButton(this, "alt RIGHT", "expx", expXButton); - UiUtils.mapKeyStrokeToButton(this, "MINUS", "expx", expXButton); - expXButton.setEnabled(false); + listener.mapKeyStroke("alt RIGHT", "expx", expXButton); + listener.mapKeyStroke("MINUS", "expx", expXButton); - histButton = SwarmUtil.createToolBarButton(Icons.timeback, "Last time settings (Backspace)", - new ActionListener() { + return expXButton; + } + + private JButton createHistButton() { + JButton histButton = SwarmUtil.createToolBarButton(Icons.timeback, + "Last time settings (Backspace)", new ActionListener() { public void actionPerformed(final ActionEvent e) { back(); } }); - UiUtils.mapKeyStrokeToButton(this, "BACK_SPACE", "back", histButton); - add(histButton); - addSeparator(); - histButton.setEnabled(false); - waveToolbar = new WaveViewSettingsToolbar(null, this, listener); + listener.mapKeyStroke("BACK_SPACE", "back", histButton); - addSeparator(); - - add(Box.createHorizontalGlue()); - - throbber = new Throbber(); - add(throbber); - - // UiUtils.mapKeyStrokeToAction(this, "control A", "selectAll", new AbstractAction() { - // private static final long serialVersionUID = 1L; - // - // public void actionPerformed(final ActionEvent e) { - // for (final PickerWavePanel wave : waves) - // select(wave); - // } - // }); - } - -// private void addHistory(final AbstractWavePanel wvp, final double[] t) { -// Stack history = histories.get(wvp); -// if (history == null) { -// history = new Stack(); -// histories.put(wvp, history); -// } -// history.push(t); -// } - -// public void gotoTime(final AbstractWavePanel wvp, String t) { -// double j2k = Double.NaN; -// try { -// if (t.length() == 12) -// t = t + "30"; -// -// j2k = J2kSec.parse("yyyyMMddHHmmss", t); -// } catch (final Exception e) { -// JOptionPane.showMessageDialog(applicationFrame, "Illegal time value.", "Error", -// JOptionPane.ERROR_MESSAGE); -// } -// -// if (!Double.isNaN(j2k)) { -// double dt = 60; -// if (wvp.getWave() != null) { -// final double st = wvp.getStartTime(); -// final double et = wvp.getEndTime(); -// final double[] ts = new double[] {st, et}; -// addHistory(wvp, ts); -// dt = (et - st); -// } -// -// final double tzo = -// swarmConfig.getTimeZone(wvp.getChannel()).getOffset(System.currentTimeMillis()) / 1000; -// -// final double nst = j2k - tzo - dt / 2; -// final double net = nst + dt; -// -// fetchNewWave(wvp, nst, net); -// } -// } - - // TODO: This isn't right, this should be a method of waveviewpanel - private void fetchNewWave(final AbstractWavePanel wvp, final double nst, final double net) { - final SwingWorker worker = new SwingWorker() { - @Override - public Object construct() { - throbber.increment(); - final SeismicDataSource sds = wvp.getDataSource(); - // Hacky fix for bug #84 - Wave sw = null; - if (sds instanceof CachedDataSource) - sw = ((CachedDataSource) sds).getBestWave(wvp.getChannel(), nst, net); - else - sw = sds.getWave(wvp.getChannel(), nst, net); - wvp.setWave(sw, nst, net); - wvp.repaint(); - return null; - } - - @Override - public void finished() { - throbber.decrement(); - repaint(); - } - }; - worker.start(); - } - - - public void gotoTime(final String t) { - listener.gotoTime(t); + return histButton; } public void scaleTime(final double pct) { - pickBox.scaleTime(pct); + listener.scaleTime(pct); } public void back() { - pickBox.back(); + listener.back(); } public void shiftTime(final double pct) { - pickBox.shiftTime(pct); + listener.shiftTime(pct); } class CaptureActionListener implements ActionListener { public void actionPerformed(final ActionEvent e) { - pickBox.writeImage(); + listener.writeImage(); } } @@ -281,7 +198,7 @@ private void doSizePopup() { final JRadioButtonMenuItem mi = new JRadioButtonMenuItem(labels[i]); mi.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { - pickBox.setWaveHeight(size); + listener.setWaveHeight(size); } }); if (waveHeight == size) @@ -296,11 +213,10 @@ public void actionPerformed(final ActionEvent e) { } public void incrementThrobber() { - throbber.increment();; + throbber.increment(); } public void decrementThrobber() { - throbber.decrement();; + throbber.decrement(); } - -} +} \ No newline at end of file diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBarListener.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBarListener.java index ef57f043..1c9d75af 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBarListener.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBarListener.java @@ -1,9 +1,18 @@ package gov.usgs.volcanoes.swarm.event; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + import gov.usgs.volcanoes.swarm.wave.WaveViewToolBarListener; public interface PickToolBarListener extends WaveViewToolBarListener { public void setWaveHeight(int height); - public void gotoTime(String t); + public void scaleTime(final double pct); + + public void back(); + + public void shiftTime(final double pct); + + public void writeImage(); } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java index 3c7de5b7..fdf04aa0 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java @@ -10,6 +10,7 @@ import java.awt.geom.Line2D; import java.awt.geom.Rectangle2D; import java.util.ArrayList; +import java.util.Comparator; import java.util.List; import java.util.Stack; @@ -70,6 +71,10 @@ public void waveZoomed(final AbstractWavePanel src, final double st, final doubl @Override protected void annotateImage(Graphics2D g2) { + if (getVisibleRect().isEmpty()) { + return; + } + for (Arrival arrival : arrivals) { Pick pick = arrival.getPick(); @@ -125,8 +130,7 @@ public void eventUpdated() { @Override protected void processRightMousePress(MouseEvent e) { - // TODO Auto-generated method stub - + settings.cycleType(); } public void setViewport(JViewport viewport) { @@ -137,4 +141,12 @@ public int compareTo(PickWavePanel o) { return Arrival.distanceComparator().compare(arrivals.get(0),o.arrivals.get(0)); } + public static Comparator distanceComparator() { + return new Comparator() { + public int compare(final PickWavePanel e1, final PickWavePanel e2) { + return Arrival.distanceComparator().compare(e1.arrivals.get(0),e2.arrivals.get(0)); + } + }; + } + } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java b/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java index ae3ce11b..ec8062f6 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java @@ -716,7 +716,9 @@ private void filter(Wave w) { * @param g the graphics context */ public void paint(Graphics g) { - +if (getVisibleRect().isEmpty()) { + return; +} Graphics2D g2 = (Graphics2D) g; Dimension dim = this.getSize(); if (wave == null) { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewToolBar.java b/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewToolBar.java index def4e6fb..2c942340 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewToolBar.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewToolBar.java @@ -17,207 +17,69 @@ import gov.usgs.volcanoes.swarm.wave.WaveViewSettings.ViewType; public class WaveViewToolBar { - private JButton waveSet; - private JToggleButton waveToggle; - private JToggleButton spectraToggle; - private JToggleButton spectrogramToggle; - private ButtonGroup waveTypes; - private WaveViewToolBarListener listener; - - public WaveViewToolBar(WaveViewSettings s, JToolBar dest, WaveViewToolBarListener listener) - { - this.listener = listener; - createUI(dest); - setSettings(s); - } - - public void createUI(JToolBar dest) - { - waveSet = SwarmUtil.createToolBarButton( - Icons.wavesettings, - "Wave view settings (?)", - new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - if (settingsSet.size()==0) - return; - WaveViewSettings s = settingsSet.iterator().next(); - WaveViewSettingsDialog wvsd = WaveViewSettingsDialog.getInstance(s, settingsSet.size()); - wvsd.setVisible(true); - for (WaveViewSettings settings : settingsSet) - { - settings.copy(s); - settings.notifyView(); - } - } - }); - UiUtils.mapKeyStrokeToButton(keyComp, "shift SLASH", "settings", waveSet); - dest.add(waveSet); - - waveToggle = SwarmUtil.createToolBarToggleButton( - Icons.wave, - "Wave view (W or ,)", - new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - for (WaveViewSettings settings : settingsSet) - settings.setType(ViewType.WAVE); - } - }); - UiUtils.mapKeyStrokeToButton(keyComp, "COMMA", "wave1", waveToggle); - UiUtils.mapKeyStrokeToButton(keyComp, "W", "wave2", waveToggle); - dest.add(waveToggle); - - spectraToggle = SwarmUtil.createToolBarToggleButton( - Icons.spectra, - "Spectra view (S or .)", - new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - for (WaveViewSettings settings : settingsSet) - settings.setType(ViewType.SPECTRA); - } - }); - UiUtils.mapKeyStrokeToButton(keyComp, "PERIOD", "spectra1", spectraToggle); - UiUtils.mapKeyStrokeToButton(keyComp, "S", "spectra2", spectraToggle); - dest.add(spectraToggle); - - spectrogramToggle = SwarmUtil.createToolBarToggleButton( - Icons.spectrogram, - "Spectrogram view (G or /)", - new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - for (WaveViewSettings settings : settingsSet) - settings.setType(ViewType.SPECTROGRAM); - } - }); - UiUtils.mapKeyStrokeToButton(keyComp, "SLASH", "spectrogram1", spectrogramToggle); - UiUtils.mapKeyStrokeToButton(keyComp, "G", "spectrogram2", spectrogramToggle); - dest.add(spectrogramToggle); - - keyComp.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("L"), "cycleLogSettings"); - keyComp.getActionMap().put("cycleLogSettings", new AbstractAction() - { - public static final long serialVersionUID = -1; - public void actionPerformed(ActionEvent e) - { - for (WaveViewSettings settings : settingsSet) { - if (settings.viewType == ViewType.SPECTRA) - settings.cycleLogSettings(); - if (settings.viewType == ViewType.SPECTROGRAM) - settings.toggleLogPower(); - } - } - }); - - keyComp.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("F"), "toggleFilter"); - keyComp.getActionMap().put("toggleFilter", new AbstractAction() - { - public static final long serialVersionUID = -1; - public void actionPerformed(ActionEvent e) - { - for (WaveViewSettings settings : settingsSet) - settings.toggleFilter(); - } - }); - - keyComp.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("R"), "resetAutoScale"); - keyComp.getActionMap().put("resetAutoScale", new AbstractAction() - { - public static final long serialVersionUID = -1; - public void actionPerformed(ActionEvent e) - { - for (WaveViewSettings settings : settingsSet) - settings.resetAutoScaleMemory(); - } - }); - - keyComp.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("OPEN_BRACKET"), "yScaleIn"); - keyComp.getActionMap().put("yScaleIn", new AbstractAction() - { - public static final long serialVersionUID = -1; - public void actionPerformed(ActionEvent e) - { - for (WaveViewSettings settings : settingsSet) { - settings.adjustScale(1.0 / 1.25); - } - } - }); - - keyComp.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke("CLOSE_BRACKET"), "yScaleOut"); - keyComp.getActionMap().put("yScaleOut", new AbstractAction() - { - public static final long serialVersionUID = -1; - public void actionPerformed(ActionEvent e) - { - for (WaveViewSettings settings : settingsSet) - settings.adjustScale(1.25); - } - }); - - waveTypes = new ButtonGroup(); - waveTypes.add(waveToggle); - waveTypes.add(spectraToggle); - waveTypes.add(spectrogramToggle); - } - - public void clearSettingsSet() - { - settingsSet.clear(); - } - - public void addSettings(WaveViewSettings s) - { - if (s != null) - { - settingsSet.add(s); - s.toolbar = this; - settingsChanged(); + private JButton waveSet; + private JToggleButton waveToggle; + private JToggleButton spectraToggle; + private JToggleButton spectrogramToggle; + private ButtonGroup waveTypes; + private WaveViewToolBarListener listener; + + public WaveViewToolBar(WaveViewSettings s, JToolBar dest, WaveViewToolBarListener listener) { + this.listener = listener; + createUI(dest); + } + + public void createUI(JToolBar dest) { + waveSet = SwarmUtil.createToolBarButton(Icons.wavesettings, "Wave view settings (?)", + new ActionListener() { + public void actionPerformed(ActionEvent e) { + listener.displaySettingsDialog(); + } + }); + listener.mapKeyStroke("shift SLASH", "settings", waveSet); + dest.add(waveSet); + + waveToggle = + SwarmUtil.createToolBarToggleButton(Icons.wave, "Wave view (W or ,)", new ActionListener() { + public void actionPerformed(ActionEvent e) { + listener.setType(ViewType.WAVE); } - } - - public void removeSettings(WaveViewSettings s) - { - settingsSet.remove(s); - if (s != null) - { - s.toolbar = null; - settingsChanged(); + }); + listener.mapKeyStroke("COMMA", "wave1", waveToggle); + listener.mapKeyStroke("W", "wave2", waveToggle); + dest.add(waveToggle); + + spectraToggle = SwarmUtil.createToolBarToggleButton(Icons.spectra, "Spectra view (S or .)", + new ActionListener() { + public void actionPerformed(ActionEvent e) { + listener.setType(ViewType.SPECTRA); } - } - - public void setSettings(WaveViewSettings s) - { - clearSettingsSet(); - addSettings(s); - } - - public void settingsChanged() - { - boolean w = false; - boolean s = false; - boolean sg = false; - for (WaveViewSettings set : settingsSet) - { - if (set.viewType == ViewType.WAVE) - w = true; - if (set.viewType == ViewType.SPECTRA) - s = true; - if (set.viewType == ViewType.SPECTROGRAM) - sg = true; + }); + listener.mapKeyStroke("PERIOD", "spectra1", spectraToggle); + listener.mapKeyStroke("S", "spectra2", spectraToggle); + dest.add(spectraToggle); + + spectrogramToggle = SwarmUtil.createToolBarToggleButton(Icons.spectrogram, + "Spectrogram view (G or /)", new ActionListener() { + public void actionPerformed(ActionEvent e) { + listener.setType(ViewType.SPECTROGRAM); } + }); + listener.mapKeyStroke("SLASH", "spectrogram1", spectrogramToggle); + listener.mapKeyStroke("G", "spectrogram2", spectrogramToggle); + dest.add(spectrogramToggle); + + waveTypes = new ButtonGroup(); + waveTypes.add(waveToggle); + waveTypes.add(spectraToggle); + waveTypes.add(spectrogramToggle); + } + + public void setEnabled(boolean enable) { + waveSet.setEnabled(enable); + waveToggle.setEnabled(enable); + spectraToggle.setEnabled(enable); + spectrogramToggle.setEnabled(enable); - // fix for Java 1.5, clearSelection was added in 1.6 - try { - waveTypes.setSelected( waveTypes.getSelection(), false ); - } catch (Throwable e) {} - waveToggle.setSelected(w && !s && !sg); - spectraToggle.setSelected(!w && s && !sg); - spectrogramToggle.setSelected(!w && !s && sg); - } + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewToolBarListener.java b/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewToolBarListener.java index be310c41..5575e0d3 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewToolBarListener.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewToolBarListener.java @@ -1,5 +1,11 @@ package gov.usgs.volcanoes.swarm.wave; -public interface WaveViewToolBarListener { +import javax.swing.AbstractButton; + +import gov.usgs.volcanoes.swarm.wave.WaveViewSettings.ViewType; +public interface WaveViewToolBarListener { + public void displaySettingsDialog(); + public void mapKeyStroke(String keyStroke,String name, AbstractButton button); + public void setType(ViewType viewType); } From 700ba64cfdd194f6c8b3835b736b011f91296acd Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Tue, 22 Mar 2016 13:28:56 -0800 Subject: [PATCH 18/67] Initial 2.6 snapshot. --- pom.xml | 2 +- .../usgs/volcanoes/swarm/event/PickBox.java | 41 +++++++++++-------- .../swarm/heli/HelicorderViewerFrame.java | 2 +- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/pom.xml b/pom.xml index 64d8ad2b..c121a761 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ gov.usgs.volcanoes swarm - 2.5.5-epic + 2.6.0-SNAPSHOT jar Swarm diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickBox.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickBox.java index 0a0f394b..532efc63 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickBox.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickBox.java @@ -47,6 +47,8 @@ import gov.usgs.volcanoes.swarm.wave.AbstractWavePanel; import gov.usgs.volcanoes.swarm.wave.WaveViewPanelAdapter; import gov.usgs.volcanoes.swarm.wave.WaveViewPanelListener; +import gov.usgs.volcanoes.swarm.wave.WaveViewSettings; +import gov.usgs.volcanoes.swarm.wave.WaveViewSettingsDialog; import gov.usgs.volcanoes.swarm.wave.WaveViewSettings.ViewType; public class PickBox extends JPanel implements Scrollable, PickToolBarListener { @@ -77,19 +79,21 @@ public class PickBox extends JPanel implements Scrollable, PickToolBarListener { private int wavePanelHeight; private int lastClickedIndex; private final Set listeners; + private JLabel emptyArrivalLabel; public PickBox(JLabel statusLabel) { this.statusLabel = statusLabel; panels = new CopyOnWriteArrayList(); - + seismicSources = new HashMap(); histories = new HashMap>(); listeners = new HashSet(); // selectedSet = new HashSet(); selectedSet = new ConcurrentSkipListSet(); wavePanelHeight = DEFAULT_WAVE_PANEL_HEIGHT; - setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); + emptyArrivalLabel = new JLabel("No arrivals available."); + add(emptyArrivalLabel); addComponentListener(new ComponentAdapter() { @Override public void componentMoved(final ComponentEvent e) { @@ -195,22 +199,16 @@ private synchronized void createImage() { @Override public void paint(final Graphics g) { -// if (getWidth() <= 0 || getHeight() <= 0) -// return; - - if (image == null || panels.size() == 0) { - super.paint(g); - final Dimension dim = this.getSize(); - g.setColor(Color.black); - g.drawString("Monitor empty.", dim.width / 2 - 40, dim.height / 2); - } else { - super.paint(image.getGraphics()); - g.drawImage(image, 0, 0, null); - g.setColor(Color.WHITE); + if (image == null) { + createImage(); } + super.paint(image.getGraphics()); + g.drawImage(image, 0, 0, null); + g.setColor(Color.WHITE); } public void addPick(Arrival arrival) { + this.remove(emptyArrivalLabel); Pick pick = arrival.getPick(); String channel = pick.getChannel(); int index = panels.lastIndexOf(channel); @@ -430,7 +428,7 @@ public void back(final AbstractWavePanel wvp) { return; final double[] t = history.pop(); - fetchNewWave(wvp, t[0], t[1]); + fetchNewWave(wvp, t[0], t[1]); } public void back() { @@ -469,7 +467,6 @@ public Object construct() { else sw = sds.getWave(wvp.getChannel(), nst, net); wvp.setWave(sw, nst, net); - wvp.repaint(); return null; } @@ -483,8 +480,16 @@ public void finished() { } public void displaySettingsDialog() { - // TODO Auto-generated method stub - + if (panels.size() == 0) + return; + + WaveViewSettings s = panels.get(0).getSettings(); + WaveViewSettingsDialog wvsd = WaveViewSettingsDialog.getInstance(s, selectedSet.size()); + wvsd.setVisible(true); + for (PickWavePanel panel : selectedSet) { + WaveViewSettings settings= panel.getSettings(); + settings.copy(s); + } } public void mapKeyStroke(String keyStroke, String name, AbstractButton button) { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewerFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewerFrame.java index 4b7bd2b4..c7d96af6 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewerFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewerFrame.java @@ -367,7 +367,7 @@ public void actionPerformed(final ActionEvent e) { picker.setEnabled(false); UiUtils.mapKeyStrokeToButton(this, "control P", "picker1", picker); UiUtils.mapKeyStrokeToButton(this, "P", "picker2", picker); - toolBar.add(picker); +// toolBar.add(picker); removeWave = SwarmUtil.createToolBarButton(Icons.delete, "Remove inset wave (Delete or Escape)", new ActionListener() { From 0d009a1e784c6bd2106eb65659afc328a84c59eb Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Wed, 23 Mar 2016 16:22:15 -0800 Subject: [PATCH 19/67] Tidy event features a bit. --- .../usgs/volcanoes/swarm/event/Arrival.java | 12 ++ .../gov/usgs/volcanoes/swarm/event/Event.java | 14 +- .../volcanoes/swarm/event/EventFrame.java | 142 +++++++++------- .../volcanoes/swarm/event/EventObserver.java | 12 ++ .../usgs/volcanoes/swarm/event/Magnitude.java | 14 +- .../usgs/volcanoes/swarm/event/Networks.java | 29 ++-- .../usgs/volcanoes/swarm/event/Origin.java | 19 ++- .../volcanoes/swarm/event/ParameterPanel.java | 159 +++++++----------- .../gov/usgs/volcanoes/swarm/event/Pick.java | 12 ++ .../usgs/volcanoes/swarm/event/PickBox.java | 70 ++++---- .../swarm/event/PickBoxListener.java | 12 ++ .../volcanoes/swarm/event/PickToolBar.java | 12 ++ .../swarm/event/PickToolBarListener.java | 14 +- .../volcanoes/swarm/event/PickWavePanel.java | 43 ++--- .../volcanoes/swarm/event/QuakeMlUtils.java | 11 ++ 15 files changed, 349 insertions(+), 226 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java index 1b81bf09..8ff9370d 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java @@ -1,3 +1,9 @@ +/** + * I waive copyright and related rights in the this work worldwide + * through the CC0 1.0 Universal public domain dedication. + * https://creativecommons.org/publicdomain/zero/1.0/legalcode + */ + package gov.usgs.volcanoes.swarm.event; import org.slf4j.Logger; @@ -10,6 +16,12 @@ import gov.usgs.volcanoes.swarm.event.Pick.Onset; import gov.usgs.volcanoes.swarm.event.Pick.Polarity; +/** + * Holder for QuakeML arrival. + * + * @author Tom Parker + * + */ public class Arrival { Logger LOGGER = LoggerFactory.getLogger(Arrival.class); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java index 38f9f499..58a644d9 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java @@ -1,3 +1,9 @@ +/** + * I waive copyright and related rights in the this work worldwide + * through the CC0 1.0 Universal public domain dedication. + * https://creativecommons.org/publicdomain/zero/1.0/legalcode + */ + package gov.usgs.volcanoes.swarm.event; import org.slf4j.Logger; @@ -13,11 +19,17 @@ import gov.usgs.volcanoes.core.util.StringUtils; - +/** + * Holder for QuakeML Event. + * + * @author Tom Parker + * + */ public class Event { private static final Logger LOGGER = LoggerFactory.getLogger(Event.class); public final String publicId; + private final Map origins; private final Map magnitudes; private final Map picks; diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java index 3c4f35cf..8f90dc10 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java @@ -1,3 +1,9 @@ +/** + * I waive copyright and related rights in the this work worldwide + * through the CC0 1.0 Universal public domain dedication. + * https://creativecommons.org/publicdomain/zero/1.0/legalcode + */ + package gov.usgs.volcanoes.swarm.event; import org.slf4j.Logger; @@ -26,6 +32,7 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import gov.usgs.volcanoes.core.CodeTimer; import gov.usgs.volcanoes.core.time.J2kSec; import gov.usgs.volcanoes.swarm.Icons; import gov.usgs.volcanoes.swarm.SwarmFrame; @@ -39,62 +46,58 @@ */ public class EventFrame extends SwarmFrame implements EventObserver { private static final Logger LOGGER = LoggerFactory.getLogger(EventFrame.class); + private static final String EVENT_URL = "http://earthquake.usgs.gov/fdsnws/event/1/query?eventid="; + + /** default */ public static final long serialVersionUID = -1; + private final PickBox pickBox; private final JLabel statusLabel; private final Event event; - - private JSplitPane mainPanel; - private PickToolBar toolbar; + private final JSplitPane mainPanel; + private final PickToolBar toolbar; + private boolean closing = false; + /** + * Constructor. + * + * @param event Event to display + */ public EventFrame(Event event) { super("Event - " + event.getEvid(), true, true, true, false); this.event = event; + event.addObserver(this); statusLabel = new JLabel(" "); pickBox = new PickBox(statusLabel); pickBox.setLayout(new BoxLayout(pickBox, BoxLayout.PAGE_AXIS)); + + toolbar = new PickToolBar(pickBox); - event.addObserver(this); - this.setFocusable(true); - createListeners(); + mainPanel = + new JSplitPane(JSplitPane.VERTICAL_SPLIT, ParameterPanel.create(event), createPickPanel()); + mainPanel.setOneTouchExpandable(true); + setContentPane(mainPanel); setFrameIcon(Icons.ruler); setSize(swarmConfig.clipboardWidth, swarmConfig.clipboardHeight); setLocation(swarmConfig.clipboardX, swarmConfig.clipboardY); setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - mainPanel = - new JSplitPane(JSplitPane.VERTICAL_SPLIT, ParameterPanel.create(event), createPickPanel()); - mainPanel.setOneTouchExpandable(true); + createListeners(); - setContentPane(mainPanel); this.setVisible(true); - - new SwingWorker() { - @Override - public Object construct() { - fetchDetailedEvent(); - populatePicks(); - return null; - } + this.setFocusable(true); - @Override - public void finished() { - repaint(); - } - }.start(); + updateEvent(); } - private JPanel createPickPanel() { - JPanel pickPanel = new JPanel(); pickPanel.setLayout(new BoxLayout(pickPanel, BoxLayout.PAGE_AXIS)); - toolbar = new PickToolBar(pickBox); pickPanel.add(toolbar); pickBox.addListener(toolbar); @@ -115,13 +118,52 @@ private JPanel createPickPanel() { return pickPanel; } + private void createListeners() { + this.addInternalFrameListener(new InternalFrameAdapter() { + @Override + public void internalFrameActivated(final InternalFrameEvent e) {} - public void fetchDetailedEvent() { - final String neicEvid = event.getEventSource() + event.getEvid(); - final Event workingEvent = event; + @Override + public void internalFrameDeiconified(final InternalFrameEvent e) {} + + @Override + public void internalFrameClosing(final InternalFrameEvent e) { + closing = true; + dispose(); + SwarmInternalFrames.remove(EventFrame.this); + } + + @Override + public void internalFrameClosed(final InternalFrameEvent e) {} + }); + } + + private void updateEvent() { + new SwingWorker() { + @Override + public Object construct() { + toolbar.incrementThrobber(); + CodeTimer timer = new CodeTimer("Detailed event"); + fetchDetailedEvent(); + timer.stopAndReport(); + populatePicks(); + return null; + } + + @Override + public void finished() { + toolbar.decrementThrobber(); + repaint(); + } + }.start(); + } - String url = "http://earthquake.usgs.gov/fdsnws/event/1/query?eventid=" + neicEvid; + + public void fetchDetailedEvent() { + String neicEvid = event.getEventSource() + event.getEvid(); + Event workingEvent = event; + String url = EVENT_URL + neicEvid; DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = null; Document doc = null; @@ -133,24 +175,26 @@ public void fetchDetailedEvent() { NodeList eventElements = doc.getElementsByTagName("event"); Element eventElement = (Element) eventElements.item(0); + + // NEIC has better descriptions NodeList descriptionNodes = eventElement.getElementsByTagName("description"); for (int idx = 0; idx < descriptionNodes.getLength(); idx++) { eventElement.removeChild(descriptionNodes.item(idx)); } + workingEvent.updateEvent(eventElement); - } catch (SAXException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } catch (IOException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); + } catch (SAXException e) { + LOGGER.warn("Unable to redtieve detailed event description. ({})", e.getLocalizedMessage()); + } catch (IOException e) { + LOGGER.warn("Unable to redtieve detailed event description. ({})", e.getLocalizedMessage()); } catch (ParserConfigurationException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + LOGGER.warn("Unable to redtieve detailed event description. ({})", e.getLocalizedMessage()); } } private void populatePicks() { + toolbar.incrementThrobber(); + Origin origin = event.getPreferredOrigin(); long firstPick = Long.MAX_VALUE; @@ -167,7 +211,6 @@ private void populatePicks() { pickBox.setStart(waveStart); pickBox.setEnd(waveEnd); - toolbar.incrementThrobber(); TreeSet arrivals = new TreeSet(Arrival.distanceComparator()); arrivals.addAll(origin.getArrivals()); for (Arrival arrival : arrivals) { @@ -177,6 +220,7 @@ private void populatePicks() { pickBox.addPick(arrival); mainPanel.validate(); } + toolbar.decrementThrobber(); } @@ -191,24 +235,4 @@ public void eventUpdated() { mainPanel.setTopComponent(ParameterPanel.create(event)); mainPanel.setBottomComponent(createPickPanel()); } - - private void createListeners() { - this.addInternalFrameListener(new InternalFrameAdapter() { - @Override - public void internalFrameActivated(final InternalFrameEvent e) {} - - @Override - public void internalFrameDeiconified(final InternalFrameEvent e) {} - - @Override - public void internalFrameClosing(final InternalFrameEvent e) { - closing = true; - dispose(); - SwarmInternalFrames.remove(EventFrame.this); - } - - @Override - public void internalFrameClosed(final InternalFrameEvent e) {} - }); - } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/EventObserver.java b/src/main/java/gov/usgs/volcanoes/swarm/event/EventObserver.java index c7d52064..28348ddd 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/EventObserver.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/EventObserver.java @@ -1,5 +1,17 @@ +/** + * I waive copyright and related rights in the this work worldwide + * through the CC0 1.0 Universal public domain dedication. + * https://creativecommons.org/publicdomain/zero/1.0/legalcode + */ + package gov.usgs.volcanoes.swarm.event; +/** + * Observer interface for Event objects. + * + * @author Tom Parker + * + */ public interface EventObserver { public void eventUpdated(); } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Magnitude.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Magnitude.java index 5cf30cb1..01972ff7 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Magnitude.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Magnitude.java @@ -1,8 +1,19 @@ +/** + * I waive copyright and related rights in the this work worldwide + * through the CC0 1.0 Universal public domain dedication. + * https://creativecommons.org/publicdomain/zero/1.0/legalcode + */ + package gov.usgs.volcanoes.swarm.event; import org.w3c.dom.Element; -import org.w3c.dom.NodeList; +/** + * Holder for QuakeML magnitude. + * + * @author Tom Parker + * + */ public class Magnitude { public final String publicId; @@ -13,7 +24,6 @@ public class Magnitude { public Magnitude(Element magnitudeElement) { publicId = magnitudeElement.getAttribute("publicId"); -// mag = Double.parseDouble(magnitudeElement.getElementsByTagName("mag").item(0).getTextContent()); type = magnitudeElement.getElementsByTagName("type").item(0).getTextContent(); Element magElement = (Element) magnitudeElement.getElementsByTagName("mag").item(0); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Networks.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Networks.java index 7a8aea3a..eca8c49a 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Networks.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Networks.java @@ -1,18 +1,29 @@ +/** + * I waive copyright and related rights in the this work worldwide + * through the CC0 1.0 Universal public domain dedication. + * https://creativecommons.org/publicdomain/zero/1.0/legalcode + */ + package gov.usgs.volcanoes.swarm.event; -import java.io.BufferedReader; -import java.io.File; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.FileReader; import java.io.IOException; +import java.io.InputStreamReader; import java.io.Reader; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Vector; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - +/** + * Translate FDSN network codes into organizational names. + * + * @author Tom Parker + * + */ public class Networks { private final static Logger LOGGER = LoggerFactory.getLogger(Networks.class); @@ -25,9 +36,9 @@ public String getName(String code) { private Networks() { networks = new HashMap(); - FileReader reader = null; + Reader reader = null; try { - reader = new FileReader(new File(ClassLoader.getSystemResource(NETWORKS_FILE).getFile())); + reader = new InputStreamReader(ClassLoader.getSystemResource(NETWORKS_FILE).openStream()); try { List fields = Networks.parseLine(reader); @@ -41,10 +52,6 @@ private Networks() { } } catch (IOException e) { LOGGER.info("Unable to read networks", e); - // } catch (URISyntaxException e) { - // // TODO Auto-generated catch block - // LOGGER.debug("DASDSA ", e); - // e.printStackTrace(); } finally { if (reader != null) { try { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java index eb8a0a63..90c3d77d 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java @@ -1,16 +1,27 @@ +/** + * I waive copyright and related rights in the this work worldwide + * through the CC0 1.0 Universal public domain dedication. + * https://creativecommons.org/publicdomain/zero/1.0/legalcode + */ + package gov.usgs.volcanoes.swarm.event; -import java.text.ParseException; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Element; import org.w3c.dom.NodeList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +/** + * Holder for QuakeML origin. + * + * @author Tom Parker + * + */ public class Origin { private static final Logger LOGGER = LoggerFactory.getLogger(Origin.class); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/ParameterPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/event/ParameterPanel.java index c8c3b5ce..67aac58c 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/ParameterPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/ParameterPanel.java @@ -1,3 +1,9 @@ +/** + * I waive copyright and related rights in the this work worldwide + * through the CC0 1.0 Universal public domain dedication. + * https://creativecommons.org/publicdomain/zero/1.0/legalcode + */ + package gov.usgs.volcanoes.swarm.event; import org.slf4j.Logger; @@ -21,13 +27,17 @@ public class ParameterPanel { private static final Font VALUE_FONT = Font.decode("dialog-12"); private ParameterPanel() {} - + public static Component create(Event event) { Origin origin = event.getPreferredOrigin(); Magnitude magnitude = event.getPerferredMagnitude(); JPanel parameterPanel = new JPanel(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); + if (origin == null) { + LOGGER.error("Cannot find perferred origin."); + return parameterPanel; + } c.fill = GridBagConstraints.NONE; @@ -37,126 +47,79 @@ public static Component create(Event event) { c.ipadx = 3; c.ipady = 2; - JLabel label; - - label = new JLabel("Event source: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); + addKey("Event source: ", parameterPanel, c); String source = Networks.getInstance().getName(event.getEventSource().toUpperCase()); if (source == null) { source = event.getEventSource(); } - label = new JLabel(Networks.getInstance().getName(event.getEventSource().toUpperCase()), - SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); + addValue(source, parameterPanel, c); c.gridy++; - - label = new JLabel("Description: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); + addKey("Description: ", parameterPanel, c); // wrap description to support multi-line descriptions String description = event.getDescription(); description = description.replace("\n", "
"); description = "" + description + ""; - label = new JLabel(description, SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); + addValue(description, parameterPanel, c); c.gridy++; + addKey("Origin date: ", parameterPanel, c); - label = new JLabel("Origin date: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + String date = dateFormat.format(event.getPreferredOrigin().getTime()); + addValue(date, parameterPanel, c); - if (origin != null) { - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); - String date = dateFormat.format(event.getPreferredOrigin().getTime()); - label = new JLabel(date, SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); - } c.gridy++; - - label = new JLabel("Type: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); + addKey("Type: ", parameterPanel, c); if (origin != null) { - label = new JLabel(event.getType(), SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); + addValue(event.getType(), parameterPanel, c); } - c.gridy++; + c.gridy++; + addKey("Hypocenter: ", parameterPanel, c); - label = new JLabel("Hypocenter: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); + String loc = origin.getLatitude() + ", " + origin.getLongitude(); + loc += " at " + (origin.getDepth() / 1000) + " km depth"; + addValue(loc, parameterPanel, c); - if (origin != null) { - String loc = origin.getLatitude() + ", " + origin.getLongitude(); - loc += " at " + (origin.getDepth() / 1000) + " km depth"; - label = new JLabel(loc, SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); - } c.gridy++; - - label = new JLabel("Error (RMS): ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); + addKey("Error (RMS): ", parameterPanel, c); double error = origin.getStandardError(); if (!Double.isNaN(error)) { - label = new JLabel("" + error, SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); + addValue(Double.toString(error), parameterPanel, c); } - c.gridy++; - label = new JLabel("Azimuthal gap: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); + c.gridy++; + addKey("Azimuthal gap: ", parameterPanel, c); double gap = origin.getAzimuthalGap(); if (!Double.isNaN(gap)) { - label = new JLabel("" + gap + "\u00B0", SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); + addValue(gap + "\u00B0", parameterPanel, c); } - c.gridy++; - label = new JLabel("Nearest station: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); + c.gridy++; + addKey("Nearest station: ", parameterPanel, c); double distance = origin.getMinimumDistance(); if (!Double.isNaN(distance)) { - label = new JLabel("" + distance + "\u00B0", SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); + String tag = distance + "\u00B0" + " \u2248" + String.format("%.2f", Math.toRadians(distance * 6371)) + " km"; + addValue(tag, parameterPanel, c); } - c.gridy++; - label = new JLabel("Phase count: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); + c.gridy++; + addKey("Phase count: ", parameterPanel, c); int phaseCount = origin.getPhaseCount(); if (phaseCount > 0) { - label = new JLabel("" + phaseCount, SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); + addValue(Integer.toString(phaseCount), parameterPanel, c); } - c.gridy++; - label = new JLabel("Magnitude: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); + c.gridy++; + addKey("Magnitude: ", parameterPanel, c); if (magnitude != null) { String mag = String.format("%s %s", magnitude.getMag(), magnitude.getType()); @@ -164,18 +127,13 @@ public static Component create(Event event) { if (uncertaintly != null) { mag += " (" + uncertaintly + ")"; } - label = new JLabel(mag, SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); + addValue(mag, parameterPanel, c); } - c.gridy++; - label = new JLabel("Evalutation: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); + c.gridy++; + addKey("Evalutation: ", parameterPanel, c); String evaluationTag = ""; - Origin.EvaluationMode evaluationMode = origin.getEvaluationMode(); if (evaluationMode != null) { evaluationTag += evaluationMode.toString().toLowerCase(); @@ -188,21 +146,12 @@ public static Component create(Event event) { } evaluationTag += evaluationStatus.toString().toLowerCase(); } + addValue(evaluationTag, parameterPanel, c); - label = new JLabel(evaluationTag, SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); c.gridy++; - - label = new JLabel("Event id: ", SwingConstants.LEFT); - label.setFont(KEY_FONT); - parameterPanel.add(label, c); - - label = new JLabel(event.getEvid(), SwingConstants.LEFT); - label.setFont(VALUE_FONT); - parameterPanel.add(label, c); - c.gridy++; + addKey("Event id: ", parameterPanel, c); + addValue(event.getEvid(), parameterPanel, c); c.weighty = 1; c.weightx = 1; @@ -219,4 +168,20 @@ public static Component create(Event event) { return scrollPane; } + private static void addKey(String labelS, JPanel parameterPanel, GridBagConstraints c) { + addLabel(labelS, KEY_FONT, parameterPanel, c); + } + + private static void addValue(String labelS, JPanel parameterPanel, GridBagConstraints c) { + addLabel(labelS, VALUE_FONT, parameterPanel, c); + } + + private static void addLabel(String labelS, Font font, JPanel parameterPanel, + GridBagConstraints c) { + JLabel label = new JLabel(labelS, SwingConstants.LEFT); + label.setFont(font); + parameterPanel.add(label, c); + + } + } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java index c6dfebd6..60103a09 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java @@ -1,3 +1,9 @@ +/** + * I waive copyright and related rights in the this work worldwide + * through the CC0 1.0 Universal public domain dedication. + * https://creativecommons.org/publicdomain/zero/1.0/legalcode + */ + package gov.usgs.volcanoes.swarm.event; import org.slf4j.Logger; @@ -8,6 +14,12 @@ import java.text.ParseException; +/** + * Holder for QuakeML pick. + * + * @author Tom Parker + * + */ public class Pick { Logger LOGGER = LoggerFactory.getLogger(Pick.class); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickBox.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickBox.java index 532efc63..c4103b3f 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickBox.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickBox.java @@ -1,3 +1,9 @@ +/** + * I waive copyright and related rights in the this work worldwide + * through the CC0 1.0 Universal public domain dedication. + * https://creativecommons.org/publicdomain/zero/1.0/legalcode + */ + package gov.usgs.volcanoes.swarm.event; import org.slf4j.Logger; @@ -29,10 +35,10 @@ import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; -import javax.swing.JViewport; import javax.swing.Scrollable; import gov.usgs.plot.data.Wave; +import gov.usgs.volcanoes.core.CodeTimer; import gov.usgs.volcanoes.core.contrib.PngEncoder; import gov.usgs.volcanoes.core.contrib.PngEncoderB; import gov.usgs.volcanoes.core.time.J2kSec; @@ -48,26 +54,28 @@ import gov.usgs.volcanoes.swarm.wave.WaveViewPanelAdapter; import gov.usgs.volcanoes.swarm.wave.WaveViewPanelListener; import gov.usgs.volcanoes.swarm.wave.WaveViewSettings; -import gov.usgs.volcanoes.swarm.wave.WaveViewSettingsDialog; import gov.usgs.volcanoes.swarm.wave.WaveViewSettings.ViewType; +import gov.usgs.volcanoes.swarm.wave.WaveViewSettingsDialog; +/** + * A panel to display picks for a single event. + * + * @author Tom Parker + * + */ public class PickBox extends JPanel implements Scrollable, PickToolBarListener { private static final long serialVersionUID = 1L; private static final Logger LOGGER = LoggerFactory.getLogger(PickBox.class); private static final int DEFAULT_WAVE_PANEL_HEIGHT = 150; private static final Color SELECT_COLOR = new Color(200, 220, 241); private static final Color BACKGROUND_COLOR = new Color(0xf7, 0xf7, 0xf7); - - private static final String IRIS_DATASELECT_URL = - "http://service.iris.edu/fdsnws/dataselect/1/query"; - private static final String IRIS_STATION_URL = "http://service.iris.edu/fdsnws/station/1/query"; - - protected static final JFrame applicationFrame = Swarm.getApplicationFrame(); - private static final SwarmConfig swarmConfig = SwarmConfig.getInstance(); + private static final String DATASELECT_URL = "http://service.iris.edu/fdsnws/dataselect/1/query"; + private static final String STATION_URL = "http://service.iris.edu/fdsnws/station/1/query"; + private static final JFrame APPLICATION_FRAME = Swarm.getApplicationFrame(); + private static final SwarmConfig SWARM_CONFIG = SwarmConfig.getInstance(); private final Map> histories; private final Set selectedSet; - // private final Map panels; private final List panels; private BufferedImage image; @@ -88,7 +96,6 @@ public PickBox(JLabel statusLabel) { seismicSources = new HashMap(); histories = new HashMap>(); listeners = new HashSet(); - // selectedSet = new HashSet(); selectedSet = new ConcurrentSkipListSet(); wavePanelHeight = DEFAULT_WAVE_PANEL_HEIGHT; setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); @@ -208,16 +215,16 @@ public void paint(final Graphics g) { } public void addPick(Arrival arrival) { + CodeTimer timer = new CodeTimer("arrival"); this.remove(emptyArrivalLabel); Pick pick = arrival.getPick(); String channel = pick.getChannel(); - int index = panels.lastIndexOf(channel); - PickWavePanel wavePanel; - if (index < 0) { + + PickWavePanel wavePanel = findPanel(channel); + if (wavePanel == null) { wavePanel = new PickWavePanel(); wavePanel.setStatusLabel(statusLabel); wavePanel.setChannel(channel); - wavePanel.setViewport(((JViewport) getParent())); SeismicDataSource source = seismicSources.get(channel); if (source == null) { source = new WebServicesSource(); @@ -229,8 +236,6 @@ public void addPick(Arrival arrival) { panels.add(wavePanel); wavePanel.setWave(wave, startJ2k, endJ2k); add(wavePanel); - // add(Box.createRigidArea(new Dimension(0, 10))); - // p.setSize(w, calculateWaveHeight()); wavePanel.setBottomBorderColor(Color.GRAY); wavePanel.setSize(getWidth(), wavePanelHeight); wavePanel.setDisplayTitle(true); @@ -238,11 +243,10 @@ public void addPick(Arrival arrival) { wavePanel.createImage(); wavePanel.addListener(selectListener); } - } else { - wavePanel = panels.get(index); } wavePanel.addArrival(arrival); + timer.stopAndReport(); } private String buildParams(String channel) { @@ -260,8 +264,8 @@ private String buildParams(String channel) { sb.append(comps[1]).append("|"); sb.append(3600).append("|"); sb.append(1000).append("|"); - sb.append(IRIS_DATASELECT_URL).append("|"); - sb.append(IRIS_STATION_URL); + sb.append(DATASELECT_URL).append("|"); + sb.append(STATION_URL); return sb.toString(); } @@ -310,13 +314,13 @@ public void writeImage() { chooser.setCurrentDirectory(lastPath); chooser.setSelectedFile(new File("clipboard.png")); chooser.setDialogTitle("Save Clipboard Screen Capture"); - final int result = chooser.showSaveDialog(applicationFrame); + final int result = chooser.showSaveDialog(APPLICATION_FRAME); File f = null; if (result == JFileChooser.APPROVE_OPTION) { f = chooser.getSelectedFile(); if (f.exists()) { - final int choice = JOptionPane.showConfirmDialog(applicationFrame, + final int choice = JOptionPane.showConfirmDialog(APPLICATION_FRAME, "File exists, overwrite?", "Confirm", JOptionPane.YES_NO_OPTION); if (choice != JOptionPane.YES_OPTION) return; @@ -382,6 +386,15 @@ private void notifyListeners() { } } + private PickWavePanel findPanel(String channel) { + for (PickWavePanel panel : panels) { + if (panel.getChannel().equals(channel)) { + return panel; + } + } + return null; + } + private int findPanelIndex(PickWavePanel panel) { int panelIdx = -1; int searchIdx = 0; @@ -392,7 +405,6 @@ private int findPanelIndex(PickWavePanel panel) { searchIdx++; } } - LOGGER.debug("FOUND PANEL {}", panelIdx); return panelIdx; } @@ -458,7 +470,6 @@ private void fetchNewWave(final AbstractWavePanel wvp, final double nst, final d final SwingWorker worker = new SwingWorker() { @Override public Object construct() { - // throbber.increment(); final SeismicDataSource sds = wvp.getDataSource(); // Hacky fix for bug #84 Wave sw = null; @@ -472,7 +483,6 @@ public Object construct() { @Override public void finished() { - // throbber.decrement(); repaint(); } }; @@ -482,12 +492,12 @@ public void finished() { public void displaySettingsDialog() { if (panels.size() == 0) return; - + WaveViewSettings s = panels.get(0).getSettings(); WaveViewSettingsDialog wvsd = WaveViewSettingsDialog.getInstance(s, selectedSet.size()); wvsd.setVisible(true); for (PickWavePanel panel : selectedSet) { - WaveViewSettings settings= panel.getSettings(); + WaveViewSettings settings = panel.getSettings(); settings.copy(s); } } @@ -512,7 +522,7 @@ public void gotoTime(final AbstractWavePanel wvp, String t) { j2k = J2kSec.parse("yyyyMMddHHmmss", t); } catch (final Exception e) { - JOptionPane.showMessageDialog(applicationFrame, "Illegal time value.", "Error", + JOptionPane.showMessageDialog(APPLICATION_FRAME, "Illegal time value.", "Error", JOptionPane.ERROR_MESSAGE); } @@ -527,7 +537,7 @@ public void gotoTime(final AbstractWavePanel wvp, String t) { } final double tzo = - swarmConfig.getTimeZone(wvp.getChannel()).getOffset(System.currentTimeMillis()) / 1000; + SWARM_CONFIG.getTimeZone(wvp.getChannel()).getOffset(System.currentTimeMillis()) / 1000; final double nst = j2k - tzo - dt / 2; final double net = nst + dt; diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickBoxListener.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickBoxListener.java index b7349089..198a0072 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickBoxListener.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickBoxListener.java @@ -1,5 +1,17 @@ +/** + * I waive copyright and related rights in the this work worldwide + * through the CC0 1.0 Universal public domain dedication. + * https://creativecommons.org/publicdomain/zero/1.0/legalcode + */ + package gov.usgs.volcanoes.swarm.event; +/** + * Listener interface for pickBox objects. + * + * @author Tom Parker + * + */ public interface PickBoxListener { public void selectCountChanged(int count); } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBar.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBar.java index bc5d18a3..5e1ef3b9 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBar.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBar.java @@ -1,3 +1,9 @@ +/** + * I waive copyright and related rights in the this work worldwide + * through the CC0 1.0 Universal public domain dedication. + * https://creativecommons.org/publicdomain/zero/1.0/legalcode + */ + package gov.usgs.volcanoes.swarm.event; import org.slf4j.Logger; @@ -20,6 +26,12 @@ import gov.usgs.volcanoes.swarm.Throbber; import gov.usgs.volcanoes.swarm.wave.WaveViewToolBar; +/** + * Toolbar used in event frame. + * + * @author Tom Parker + * + */ public class PickToolBar extends JToolBar implements PickBoxListener { private static final long serialVersionUID = 1L; private final static Logger LOGGER = LoggerFactory.getLogger(PickToolBar.class); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBarListener.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBarListener.java index 1c9d75af..c1f9a71d 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBarListener.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBarListener.java @@ -1,10 +1,18 @@ +/** + * I waive copyright and related rights in the this work worldwide + * through the CC0 1.0 Universal public domain dedication. + * https://creativecommons.org/publicdomain/zero/1.0/legalcode + */ package gov.usgs.volcanoes.swarm.event; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - import gov.usgs.volcanoes.swarm.wave.WaveViewToolBarListener; +/** + * Listener interface for PickToolBar objects. + * + * @author Tom Parker + * + */ public interface PickToolBarListener extends WaveViewToolBarListener { public void setWaveHeight(int height); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java index fdf04aa0..5f45f2c7 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java @@ -1,11 +1,17 @@ +/** + * I waive copyright and related rights in the this work worldwide + * through the CC0 1.0 Universal public domain dedication. + * https://creativecommons.org/publicdomain/zero/1.0/legalcode + */ package gov.usgs.volcanoes.swarm.event; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; -import java.awt.Graphics; import java.awt.Graphics2D; -import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.awt.geom.Line2D; import java.awt.geom.Rectangle2D; @@ -14,29 +20,32 @@ import java.util.List; import java.util.Stack; -import javax.swing.JScrollPane; import javax.swing.JViewport; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import gov.usgs.volcanoes.core.time.J2kSec; import gov.usgs.volcanoes.swarm.time.TimeListener; import gov.usgs.volcanoes.swarm.time.WaveViewTime; import gov.usgs.volcanoes.swarm.wave.AbstractWavePanel; import gov.usgs.volcanoes.swarm.wave.WaveViewPanelAdapter; -public class PickWavePanel extends AbstractWavePanel implements EventObserver, Comparable { +/** + * A wave panel which adds pick annotations. + * + * @author Tom Parker + * + */ +public class PickWavePanel extends AbstractWavePanel + implements EventObserver, Comparable { + private static final long serialVersionUID = 1L; private static final Logger LOGGER = LoggerFactory.getLogger(PickWavePanel.class); - private static final Font ANNOTATION_FONT = new Font("Monospaced", Font.BOLD, 12); private static final Color P_BACKGROUND = new Color(128, 255, 128, 192); private static final Color S_BACKGROUND = new Color(128, 128, 255, 192); private static final Color RESIDUAL_COLOR = new Color(128, 128, 128, 32); + private final List arrivals; private final Stack zoomHistory; -private JViewport viewport; public PickWavePanel() { super(); @@ -74,7 +83,7 @@ protected void annotateImage(Graphics2D g2) { if (getVisibleRect().isEmpty()) { return; } - + for (Arrival arrival : arrivals) { Pick pick = arrival.getPick(); @@ -95,7 +104,7 @@ protected void annotateImage(Graphics2D g2) { g2.fill(new Rectangle2D.Double(Math.min(x, residualMark), yOffset, Math.abs(x - residualMark), getHeight() - bottomHeight - 1)); } - + g2.setFont(ANNOTATION_FONT); FontMetrics fm = g2.getFontMetrics(); @@ -132,19 +141,15 @@ public void eventUpdated() { protected void processRightMousePress(MouseEvent e) { settings.cycleType(); } - - public void setViewport(JViewport viewport) { - this.viewport = viewport; - } public int compareTo(PickWavePanel o) { - return Arrival.distanceComparator().compare(arrivals.get(0),o.arrivals.get(0)); - } - + return Arrival.distanceComparator().compare(arrivals.get(0), o.arrivals.get(0)); + } + public static Comparator distanceComparator() { return new Comparator() { public int compare(final PickWavePanel e1, final PickWavePanel e2) { - return Arrival.distanceComparator().compare(e1.arrivals.get(0),e2.arrivals.get(0)); + return Arrival.distanceComparator().compare(e1.arrivals.get(0), e2.arrivals.get(0)); } }; } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/QuakeMlUtils.java b/src/main/java/gov/usgs/volcanoes/swarm/event/QuakeMlUtils.java index 23986fe3..c89be2dd 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/QuakeMlUtils.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/QuakeMlUtils.java @@ -1,3 +1,8 @@ +/** + * I waive copyright and related rights in the this work worldwide + * through the CC0 1.0 Universal public domain dedication. + * https://creativecommons.org/publicdomain/zero/1.0/legalcode + */ package gov.usgs.volcanoes.swarm.event; import org.slf4j.Logger; @@ -6,6 +11,12 @@ import java.text.ParseException; import java.text.SimpleDateFormat; +/** + * A utility class for working with QuakeML files + * + * @author Tom Parker + * + */ public class QuakeMlUtils { private static final Logger LOGGER = LoggerFactory.getLogger(QuakeMlUtils.class); private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSX"; From c212bd51fe951afb3d2d9c703da3a41fb9102513 Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Thu, 24 Mar 2016 08:30:29 -0800 Subject: [PATCH 20/67] Prep for merge --- dependency-reduced-pom.xml | 30 ++++++++++++++++--- .../usgs/volcanoes/swarm/event/Networks.java | 1 - .../volcanoes/swarm/event/PickToolBar.java | 1 - .../volcanoes/swarm/event/PickWavePanel.java | 6 ---- 4 files changed, 26 insertions(+), 12 deletions(-) diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml index 1fa6b1da..09da54df 100644 --- a/dependency-reduced-pom.xml +++ b/dependency-reduced-pom.xml @@ -4,7 +4,7 @@ gov.usgs.volcanoes swarm Swarm - 2.5.3 + 2.6.0-SNAPSHOT Swarm is a Java application designed to display and analyze seismic waveforms in real-time. Swarm can connect to and read from a variety of different static and dynamics data sources, including Earthworm waveservers, IRIS DMCs, SEED and SAC files, and simple ASCII. Swarm has both time- and frequency-domain analysis tools, along with a simple but powerful mapping platfrom. A full-screen kiosk mode can act as a low-cost, low-maintenance replacement for paper drum recorders. Swarm was written by and for scientists and provides fine control over many different program settings and variables. http://volcanoes.usgs.gov/software/swarm @@ -160,6 +160,12 @@ ** + + opensymphony:oscache + + ** + + @@ -292,9 +298,7 @@ - - true - + volcanoes http://volcanoes.usgs.gov/software/maven2/ @@ -306,6 +310,24 @@ 1.0.10 compile
+ + io.netty + netty-all + 4.0.31.Final + compile + + + opensymphony + oscache + 2.4.1 + compile + + + jms + javax.jms + + +
diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Networks.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Networks.java index eca8c49a..a32d6405 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Networks.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/Networks.java @@ -9,7 +9,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBar.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBar.java index 5e1ef3b9..5024685b 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBar.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBar.java @@ -20,7 +20,6 @@ import javax.swing.JRadioButtonMenuItem; import javax.swing.JToolBar; -import gov.usgs.volcanoes.core.util.UiUtils; import gov.usgs.volcanoes.swarm.Icons; import gov.usgs.volcanoes.swarm.SwarmUtil; import gov.usgs.volcanoes.swarm.Throbber; diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java index 5f45f2c7..1ca8ee66 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java @@ -5,9 +5,6 @@ */ package gov.usgs.volcanoes.swarm.event; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; @@ -20,8 +17,6 @@ import java.util.List; import java.util.Stack; -import javax.swing.JViewport; - import gov.usgs.volcanoes.core.time.J2kSec; import gov.usgs.volcanoes.swarm.time.TimeListener; import gov.usgs.volcanoes.swarm.time.WaveViewTime; @@ -38,7 +33,6 @@ public class PickWavePanel extends AbstractWavePanel implements EventObserver, Comparable { private static final long serialVersionUID = 1L; - private static final Logger LOGGER = LoggerFactory.getLogger(PickWavePanel.class); private static final Font ANNOTATION_FONT = new Font("Monospaced", Font.BOLD, 12); private static final Color P_BACKGROUND = new Color(128, 255, 128, 192); private static final Color S_BACKGROUND = new Color(128, 128, 255, 192); From 069fe1966a600cc5722c81fb137493914196b128 Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Thu, 24 Mar 2016 08:45:25 -0800 Subject: [PATCH 21/67] Remove experimental features. --- .../java/gov/usgs/volcanoes/swarm/Swarm.java | 38 +- .../swarm/heli/HelicorderViewPanel.java | 19 +- .../volcanoes/swarm/picker/EventChannel.java | 64 - .../volcanoes/swarm/picker/EventLocator.java | 7 - .../usgs/volcanoes/swarm/picker/EventOld.java | 90 -- .../volcanoes/swarm/picker/Hypocenter.java | 11 - .../swarm/picker/HypocenterLayer.java | 77 -- .../volcanoes/swarm/picker/Hypocenters.java | 37 - .../swarm/picker/HypocentersListener.java | 5 - .../usgs/volcanoes/swarm/picker/Phase.java | 87 -- .../volcanoes/swarm/picker/PhasePopup.java | 177 --- .../volcanoes/swarm/picker/PickListPanel.java | 389 ------ .../volcanoes/swarm/picker/PickerFrame.java | 1152 ----------------- .../swarm/picker/PickerWavePanel.java | 181 --- .../swarm/picker/hypo71/Hypo71Locator.java | 222 ---- .../swarm/picker/hypo71/HypoResults.java | 86 -- .../swarm/wave/AbstractWavePanel.java | 2 +- 17 files changed, 28 insertions(+), 2616 deletions(-) delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/picker/EventChannel.java delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/picker/EventLocator.java delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/picker/EventOld.java delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/picker/Hypocenter.java delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/picker/HypocenterLayer.java delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/picker/Hypocenters.java delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/picker/HypocentersListener.java delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/picker/Phase.java delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/picker/PhasePopup.java delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/picker/PickListPanel.java delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Locator.java delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/HypoResults.java diff --git a/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java b/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java index f1f625fe..51a3832d 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java @@ -44,8 +44,6 @@ import gov.usgs.volcanoes.swarm.internalFrame.InternalFrameListener; import gov.usgs.volcanoes.swarm.internalFrame.SwarmInternalFrames; import gov.usgs.volcanoes.swarm.map.MapFrame; -import gov.usgs.volcanoes.swarm.picker.PickerFrame; -import gov.usgs.volcanoes.swarm.picker.PickerWavePanel; import gov.usgs.volcanoes.swarm.rsam.RsamViewerFrame; import gov.usgs.volcanoes.swarm.wave.MultiMonitor; import gov.usgs.volcanoes.swarm.wave.WaveClipboardFrame; @@ -578,24 +576,24 @@ public static RsamViewerFrame openRsam(final SeismicDataSource source, final Str return frame; } - public static PickerFrame openPicker(final WaveViewPanel insetWavePanel) { - PickerWavePanel p = new PickerWavePanel(insetWavePanel); - p.setDataSource(insetWavePanel.getDataSource().getCopy()); - PickerFrame pickerFrame = new PickerFrame(); - pickerFrame.setVisible(true); - pickerFrame.requestFocus(); - SwarmInternalFrames.add(pickerFrame); - pickerFrame.setBaseWave(p); - return pickerFrame; - } - - public static PickerFrame openPicker(Event event) { - PickerFrame pickerFrame = new PickerFrame(event); - pickerFrame.setVisible(true); - pickerFrame.requestFocus(); - SwarmInternalFrames.add(pickerFrame); - return pickerFrame; - } +// public static PickerFrame openPicker(final WaveViewPanel insetWavePanel) { +// PickerWavePanel p = new PickerWavePanel(insetWavePanel); +// p.setDataSource(insetWavePanel.getDataSource().getCopy()); +// PickerFrame pickerFrame = new PickerFrame(); +// pickerFrame.setVisible(true); +// pickerFrame.requestFocus(); +// SwarmInternalFrames.add(pickerFrame); +// pickerFrame.setBaseWave(p); +// return pickerFrame; +// } + +// public static PickerFrame openPicker(Event event) { +// PickerFrame pickerFrame = new PickerFrame(event); +// pickerFrame.setVisible(true); +// pickerFrame.requestFocus(); +// SwarmInternalFrames.add(pickerFrame); +// return pickerFrame; +// } public void saveLayout(String name) { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewPanel.java index 8979ba58..b78ba5d7 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewPanel.java @@ -1,5 +1,8 @@ package gov.usgs.volcanoes.swarm.heli; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; @@ -28,9 +31,6 @@ import javax.swing.SwingUtilities; import javax.swing.event.EventListenerList; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import gov.usgs.plot.Plot; import gov.usgs.plot.PlotException; import gov.usgs.plot.data.HelicorderData; @@ -49,7 +49,6 @@ import gov.usgs.volcanoes.swarm.SwingWorker; import gov.usgs.volcanoes.swarm.options.SwarmOptions; import gov.usgs.volcanoes.swarm.options.SwarmOptionsListener; -import gov.usgs.volcanoes.swarm.picker.PickerFrame; import gov.usgs.volcanoes.swarm.time.UiTime; import gov.usgs.volcanoes.swarm.wave.AbstractWavePanel; import gov.usgs.volcanoes.swarm.wave.WaveClipboardFrame; @@ -865,11 +864,11 @@ public void optionsChanged() { clearMarks(); } - public void insetToPicker() { - if (insetWavePanel != null) { - LOGGER.debug("Sending wave to picker"); - Swarm.openPicker(insetWavePanel); - } - } +// public void insetToPicker() { +// if (insetWavePanel != null) { +// LOGGER.debug("Sending wave to picker"); +// Swarm.openPicker(insetWavePanel); +// } +// } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/EventChannel.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/EventChannel.java deleted file mode 100644 index f898f171..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/EventChannel.java +++ /dev/null @@ -1,64 +0,0 @@ -package gov.usgs.volcanoes.swarm.picker; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class EventChannel { - private final static Logger LOGGER = LoggerFactory.getLogger(EventChannel.class); - private Phase pPhase; - private Phase sPhase; - private long codaTime; - - private int maxAmplitude; - private long duration; - - public void setPhase(Phase phase) { - switch (phase.phaseType) { - case P: - pPhase = phase; - break; - case S: - sPhase = phase; - break; - default: - throw new RuntimeException("Unknown phase type."); - } - } - - public void clearPhase(Phase.PhaseType type) { - switch (type) { - case P: - pPhase = null; - codaTime = 0; - break; - case S: - sPhase = null; - break; - default: - throw new RuntimeException("Unknown phase type."); - } - } - - public Phase getPhase(Phase.PhaseType type) { - switch (type) { - case P: - return pPhase; - case S: - return sPhase; - default: - throw new RuntimeException("Unknown phase type."); - } - } - - public boolean isEmpty() { - return pPhase == null && sPhase == null; - } - - public void setCoda(long time) { - codaTime = time; - } - - public long getCodaTime() { - return codaTime; - } -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/EventLocator.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/EventLocator.java deleted file mode 100644 index 39f982e5..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/EventLocator.java +++ /dev/null @@ -1,7 +0,0 @@ -package gov.usgs.volcanoes.swarm.picker; - -import java.io.IOException; - -public interface EventLocator { - public void locate(EventOld event) throws IOException; -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/EventOld.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/EventOld.java deleted file mode 100644 index 9c4783b0..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/EventOld.java +++ /dev/null @@ -1,90 +0,0 @@ -package gov.usgs.volcanoes.swarm.picker; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import gov.usgs.volcanoes.swarm.event.EventObserver; - -public class EventOld { - private static final Logger LOGGER = LoggerFactory.getLogger(EventOld.class); - private final Map channels; - private final List observers; - - public EventOld() { - channels = new LinkedHashMap(); - observers = new ArrayList(); - } - - public void setPhase(String channel, Phase phase) { - EventChannel eChan = channels.get(channel); - if (eChan == null) { - eChan = new EventChannel(); - channels.put(channel, eChan); - } - eChan.setPhase(phase); - if (eChan.isEmpty()) { - channels.remove(channel); - } - notifyObservers(); - } - - public void clearPhase(String channel, Phase.PhaseType type) { - EventChannel eChan = channels.get(channel); - if (eChan != null) { - eChan.clearPhase(type); - if (eChan.isEmpty()) { - channels.remove(channel); - } - notifyObservers(); - } - } - - public Phase getPhase(String channel, Phase.PhaseType type) { - EventChannel eChan = channels.get(channel); - if (eChan != null) { - return eChan.getPhase(type); - } else { - return null; - } - } - - public Map getChannels() { - return channels; - } - - public void addObserver(EventObserver observer) { - observers.add(observer); - } - - public void notifyObservers() { - for (EventObserver observer : observers) { - observer.eventUpdated(); - } - } - - public void remove(String channel) { - channels.remove(channel); - notifyObservers(); - } - - public boolean isEmpty() { - return channels.isEmpty(); - } - - public void setCoda(String channel, long time) { - EventChannel eChan = channels.get(channel); - if (eChan != null) { - eChan.setCoda(time); - } - } - - public long coda(String channel) { - EventChannel eChan = channels.get(channel); - return eChan.getCodaTime(); - } -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/Hypocenter.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/Hypocenter.java deleted file mode 100644 index 8fd4fec0..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/Hypocenter.java +++ /dev/null @@ -1,11 +0,0 @@ -package gov.usgs.volcanoes.swarm.picker; - -public class Hypocenter { - public final double lat; - public final double lon; - - public Hypocenter(double lat, double lon) { - this.lat = lat; - this.lon = lon; - } -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/HypocenterLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/HypocenterLayer.java deleted file mode 100644 index 26a52922..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/HypocenterLayer.java +++ /dev/null @@ -1,77 +0,0 @@ -package gov.usgs.volcanoes.swarm.picker; - -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.event.MouseEvent; -import java.awt.geom.Point2D; -import java.util.List; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import gov.usgs.proj.GeoRange; -import gov.usgs.proj.Projection; -import gov.usgs.volcanoes.swarm.map.MapFrame; -import gov.usgs.volcanoes.swarm.map.MapLayer; -import gov.usgs.volcanoes.swarm.map.MapPanel; - -public final class HypocenterLayer implements MapLayer { - - Logger LOGGER = LoggerFactory.getLogger(HypocenterLayer.class); - private final List hypocenters; - private MapPanel mapPanel; - - public HypocenterLayer(List hypocenters) { - this.hypocenters = hypocenters; - mapPanel = MapFrame.getInstance().addLayer(this); - } - - public void draw(Graphics2D g2) { - - if (hypocenters == null) - return; - - GeoRange range = mapPanel.getRange(); - Projection projection = mapPanel.getProjection(); - int widthPx = mapPanel.getGraphWidth(); - int heightPx = mapPanel.getGraphHeight(); - int insetPx = mapPanel.getInset(); - - for (Hypocenter hypocenter : hypocenters) { - LOGGER.debug("Hypo at {}, {}", hypocenter.lon, hypocenter.lat); - final Point2D.Double xy = - projection.forward(new Point2D.Double(-hypocenter.lon, hypocenter.lat)); - final double[] ext = range.getProjectedExtents(projection); - final double dx = (ext[1] - ext[0]); - final double dy = (ext[3] - ext[2]); - final Point2D.Double res = new Point2D.Double(); - res.x = (((xy.x - ext[0]) / dx) * widthPx + insetPx); - res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); - - g2.translate(res.x, res.y); - g2.setColor(Color.YELLOW); - g2.fillOval(0, 0, 10, 10); - g2.setColor(Color.lightGray); - g2.drawOval(0, 0, 10, 10); - g2.translate(-res.x, -res.y); - } - } - - public boolean mouseClicked(MouseEvent e) { - System.out.println("Mouse clicked. Now what?"); - return false; - } - - public void setMapPanel(MapPanel mapPanel) { - this.mapPanel = mapPanel; - } - - public void stop() { - // nothing to do here - } - - public boolean mouseMoved(MouseEvent e) { - // TODO Auto-generated method stub - return false; - } -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/Hypocenters.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/Hypocenters.java deleted file mode 100644 index 437bc64b..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/Hypocenters.java +++ /dev/null @@ -1,37 +0,0 @@ -package gov.usgs.volcanoes.swarm.picker; - -import java.util.ArrayList; -import java.util.List; - -public class Hypocenters { - - private final static List hypocenters; - private final static List listeners; - private final static HypocenterLayer plotter; - - static { - hypocenters = new ArrayList(); - listeners = new ArrayList(); - plotter = new HypocenterLayer(hypocenters); - } - - /** uninstantiable */ - private Hypocenters() {} - - public static void addListener(HypocentersListener listener) { - listeners.add(listener); - } - - public static void add (Hypocenter hypocenter) { - hypocenters.add(hypocenter); - } - - public static Hypocenters getInstance() { - return HypocentersHolder.hypocenters; - } - - private static class HypocentersHolder { - public static Hypocenters hypocenters = new Hypocenters(); - } - -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/HypocentersListener.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/HypocentersListener.java deleted file mode 100644 index 6a399a1c..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/HypocentersListener.java +++ /dev/null @@ -1,5 +0,0 @@ -package gov.usgs.volcanoes.swarm.picker; - -public interface HypocentersListener { - -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/Phase.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/Phase.java deleted file mode 100644 index b13815c2..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/Phase.java +++ /dev/null @@ -1,87 +0,0 @@ -package gov.usgs.volcanoes.swarm.picker; - -import gov.usgs.volcanoes.swarm.picker.Phase.Builder; -import gov.usgs.volcanoes.swarm.picker.Phase.FirstMotion; - -public class Phase { - public static enum Onset { - i, e - } - - public static enum PhaseType { - P, S - } - - public static enum FirstMotion { - UP, DOWN, COMPRESSION, DIALATION, POOR_UP, POOR_DOWN, POOR_COMPRESSION, POOR_DIALATION, NOISY, NOT_READABLE; - } - - public final Onset onset; - public final PhaseType phaseType; - public final FirstMotion firstMotion; - public final int weight; - public final long time; - - public static class Builder { - private String channel; - private Onset onset; - private PhaseType phaseType; - private FirstMotion firstMotion; - private int weight; - private long time; - - public Builder() {} - public Builder(Phase phase) { - onset = phase.onset; - phaseType = phase.phaseType; - firstMotion = phase.firstMotion; - weight = phase.weight; - time = phase.time; - } - - public Builder onset(Onset onset) { - this.onset = onset; - return this; - } - - public Builder phaseType(PhaseType phaseType) { - this.phaseType = phaseType; - return this; - } - - public Builder firstMotion(FirstMotion firstMotion) { - this.firstMotion = firstMotion; - return this; - } - - public Builder weight(int weight) { - this.weight = weight; - return this; - } - - public Builder time(long time) { - this.time = time; - return this; - } - - public Phase build() { - return new Phase(this); - } - - } - - private Phase(Builder builder) { - onset = builder.onset; - phaseType = builder.phaseType; - firstMotion = builder.firstMotion; - weight = builder.weight; - time = builder.time; - } - - public String tag() { - StringBuffer sb = new StringBuffer(); - sb.append(onset).append(phaseType).append(weight); - - return sb.toString(); - } -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/PhasePopup.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/PhasePopup.java deleted file mode 100644 index 3f02ef95..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/PhasePopup.java +++ /dev/null @@ -1,177 +0,0 @@ -package gov.usgs.volcanoes.swarm.picker; - -import java.awt.Component; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.SwingUtilities; - -public class PhasePopup extends JPopupMenu { - private JMenu p; - private JMenu s; - private final String channel; - private final long time; - private final EventOld event; - private Component parent; - - public PhasePopup(final EventOld event, final String channel, final long time) { - this.channel = channel; - this.time = time; - this.event = event; - - // final Component parentFrame = SwingUtilities.getAncestorNamed("mainPanel", this.getParent()); - p = new JMenu("P"); - add(p); - - - JMenuItem ip0 = new JMenuItem("iP0"); - ip0.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Phase phase = new Phase.Builder().onset(Phase.Onset.i).phaseType(Phase.PhaseType.P) - .firstMotion(Phase.FirstMotion.UP).time(time).weight(0).build(); - event.setPhase(channel, phase); - parent.validate(); - parent.repaint(); - } - }); - p.add(ip0); - - JMenuItem ip1 = new JMenuItem("iP1"); - ip1.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Phase phase = new Phase.Builder().onset(Phase.Onset.i).phaseType(Phase.PhaseType.P) - .firstMotion(Phase.FirstMotion.UP).time(time).weight(1).build(); - event.setPhase(channel, phase); - parent.validate(); - parent.repaint(); - } - }); - p.add(ip1); - - JMenuItem ep2 = new JMenuItem("eP2"); - ep2.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Phase phase = new Phase.Builder().onset(Phase.Onset.e).phaseType(Phase.PhaseType.P) - .firstMotion(Phase.FirstMotion.UP).time(time).weight(2).build(); - event.setPhase(channel, phase); - parent.validate(); - parent.repaint(); - } - }); - p.add(ep2); - - JMenuItem ep3 = new JMenuItem("eP3"); - ep3.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Phase phase = new Phase.Builder().onset(Phase.Onset.e).phaseType(Phase.PhaseType.P) - .firstMotion(Phase.FirstMotion.UP).time(time).weight(3).build(); - event.setPhase(channel, phase); - parent.validate(); - parent.repaint(); - } - }); - p.add(ep3); - - JMenuItem clearP = new JMenuItem("Clear P"); - clearP.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - event.clearPhase(channel, Phase.PhaseType.P); - parent.validate(); - parent.repaint(); - } - }); - p.add(clearP); - - s = new JMenu("S"); - add(s); - - JMenuItem is0 = new JMenuItem("iS0"); - is0.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Phase phase = new Phase.Builder().onset(Phase.Onset.i).phaseType(Phase.PhaseType.S) - .firstMotion(Phase.FirstMotion.UP).time(time).weight(0).build(); - event.setPhase(channel, phase); - parent.validate(); - parent.repaint(); - } - }); - s.add(is0); - - JMenuItem is1 = new JMenuItem("iS1"); - is1.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Phase phase = new Phase.Builder().onset(Phase.Onset.i).phaseType(Phase.PhaseType.S) - .firstMotion(Phase.FirstMotion.UP).time(time).weight(1).build(); - event.setPhase(channel, phase); - parent.validate(); - parent.repaint(); - } - }); - s.add(is1); - - JMenuItem es2 = new JMenuItem("eS2"); - es2.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Phase phase = new Phase.Builder().onset(Phase.Onset.e).phaseType(Phase.PhaseType.S) - .firstMotion(Phase.FirstMotion.UP).time(time).weight(2).build(); - event.setPhase(channel, phase); - parent.validate(); - parent.repaint(); - } - }); - s.add(es2); - - JMenuItem es3 = new JMenuItem("eS3"); - es3.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Phase phase = new Phase.Builder().onset(Phase.Onset.e).phaseType(Phase.PhaseType.S) - .firstMotion(Phase.FirstMotion.UP).time(time).weight(3).build(); - event.setPhase(channel, phase); - parent.validate(); - parent.repaint(); - } - }); - s.add(es3); - - JMenuItem clearS = new JMenuItem("Clear S"); - clearS.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - event.clearPhase(channel, Phase.PhaseType.S); - parent.validate(); - parent.repaint(); - } - }); - s.add(clearS); - - JMenuItem coda = new JMenuItem("Coda"); - coda.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - event.setCoda(channel, time); - parent.validate(); - parent.repaint(); - } - }); - add(coda); - - JMenuItem clearAll = new JMenuItem("Clear"); - clearAll.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - event.clearPhase(channel, Phase.PhaseType.P); - event.clearPhase(channel, Phase.PhaseType.S); - parent.validate(); - parent.repaint(); - } - }); - add(clearAll); - - - } - - public void setParent(Component parent) { - this.parent = parent; - } -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickListPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickListPanel.java deleted file mode 100644 index 27d17b18..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickListPanel.java +++ /dev/null @@ -1,389 +0,0 @@ -package gov.usgs.volcanoes.swarm.picker; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.font.TextAttribute; -import java.text.SimpleDateFormat; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.util.TimeZone; - -import javax.swing.BorderFactory; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.SwingConstants; -import javax.swing.border.Border; - -import gov.usgs.volcanoes.core.time.Time; -import gov.usgs.volcanoes.swarm.event.Arrival; -import gov.usgs.volcanoes.swarm.event.Event; -import gov.usgs.volcanoes.swarm.event.EventObserver; -import gov.usgs.volcanoes.swarm.event.Origin; -import gov.usgs.volcanoes.swarm.event.Pick; - -public class PickListPanel extends JPanel implements EventObserver { - private static final Logger LOGGER = LoggerFactory.getLogger(PickListPanel.class); - private static final Color BACKGROUND_COLOR = new Color(255, 255, 255); - private static final Color SELECTED_BACKGROUND_COLOR = new Color(255, 248, 220); - private static final Font TABLE_FONT = new Font(Font.MONOSPACED, Font.PLAIN, 12); - private final Event event; - private JPanel pickList; - private Set selected; - private Component parent; - - public PickListPanel(Event event) { - super(); - this.event = event; - LOGGER.debug("GOT EVENT: {}", event); - selected = new HashSet(); - - setLayout(new BorderLayout()); - LOGGER.debug("Event: " + event); - event.addObserver(this); - pickList = new JPanel(); - pickList.setLayout(new GridBagLayout()); - - writeList(pickList); - add(pickList, BorderLayout.PAGE_START); - } - - private void writeList(JPanel pickList) { - // pickList.setBorder(BorderFactory.createLineBorder(Color.black)); - pickList.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 3)); - pickList.setBackground(BACKGROUND_COLOR); - JLabel label; - GridBagConstraints c = new GridBagConstraints(); - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = .5; - c.anchor = GridBagConstraints.CENTER; - c.gridy = 0; - c.gridx = GridBagConstraints.RELATIVE; - c.ipadx = 3; - c.ipady = 2; - - Border border = BorderFactory.createMatteBorder(0, 0, 1, 0, Color.BLACK); - - label = new JLabel("Time", SwingConstants.CENTER); - label.setBorder(border); - pickList.add(label, c); - - label = new JLabel("Phase", SwingConstants.CENTER); - label.setBorder(border); - pickList.add(label, c); - - label = new JLabel("Channel", SwingConstants.CENTER); - label.setBorder(border); - pickList.add(label, c); - - label = new JLabel("Weight", SwingConstants.CENTER); - label.setBorder(border); - pickList.add(label, c); - - label = new JLabel("Onset", SwingConstants.CENTER); - label.setBorder(border); - pickList.add(label, c); - - label = new JLabel("First Motion", SwingConstants.CENTER); - label.setBorder(border); - pickList.add(label, c); - LOGGER.debug("event: {} : {}", event, event.getPreferredOrigin()); - Origin origin = event.getPreferredOrigin(); - if (origin != null) { - for (Arrival arrival : origin.getArrivals()) { - c.gridy++; - writeArrival(pickList, arrival, c); - } - } - // Map channels = event.getChannels(); - // String[] keys = channels.keySet().toArray(new String[0]); - // int idx = keys.length; - // while (idx-- > 0) { - // c.gridy++; - // String chan = keys[idx]; - // - // EventChannel eventChannel = channels.get(chan); - // - // Phase phase; - // - // phase = eventChannel.getPhase(Phase.PhaseType.P); - // if (phase != null) { - // writePhase(pickList, chan, phase, c); - // long coda = eventChannel.getCodaTime(); - // if (coda > 0) { - // writeCoda(pickList, chan, coda, c); - // - // } - // } - // - // phase = eventChannel.getPhase(Phase.PhaseType.S); - // if (phase != null) { - // writePhase(pickList, chan, phase, c); - // } - // } - - c.weighty = 1; - c.gridy++; - JPanel filler = new JPanel(); - filler.setBackground(BACKGROUND_COLOR); - pickList.add(filler, c); - } - - private void writeCoda(JPanel pickList, String channel, long coda, GridBagConstraints c) { - boolean isSelected = selected.contains(channel); - c.gridy++; - - String time = Time.toDateString(coda); - pickList.add(getLabel(time, isSelected), c); - - String phaseT = "C"; - pickList.add(getLabel(phaseT, isSelected), c); - - pickList.add(getLabel(channel, isSelected), c); - - } - - - - public void writeArrival(final JPanel pickList, final Arrival arrival, - final GridBagConstraints c) { - c.gridy++; - boolean isSelected = selected.contains(arrival); - Pick pick = arrival.getPick(); - - SimpleDateFormat dateF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); - dateF.setTimeZone(TimeZone.getTimeZone("UTC")); - - String time = dateF.format(pick.getTime()); - pickList.add(getLabel(time, isSelected), c); - pickList.add(getLabel(arrival.getPhase(), isSelected), c); - pickList.add(getLabel(pick.getChannel().replace('$', ' '), isSelected), c); - - c.fill = GridBagConstraints.NONE; - final JComboBox weight = new JComboBox(new Integer[] {0, 1, 2, 3, 4}); - weight.setFont(TABLE_FONT); - // weight.setSelectedIndex(phase.weight); - weight.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - // Phase newPhase = new Phase.Builder(phase).weight(weight.getSelectedIndex()).build(); - // event.setPhase(channel, newPhase); - parent.validate(); - parent.repaint(); - } - }); - pickList.add(weight, c); - c.fill = GridBagConstraints.HORIZONTAL; - c.fill = GridBagConstraints.NONE; - Phase.Onset[] onsets = Phase.Onset.values(); - final JComboBox onset = new JComboBox(onsets); - onset.setFont(TABLE_FONT); - int i = 0; - // while (i < onsets.length && onsets[i] != phase.onset) { - // i++; - // } - onset.setSelectedIndex(i); - onset.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - // Phase newPhase = - // new Phase.Builder(phase).onset((Phase.Onset) onset.getSelectedItem()).build(); - // event.setPhase(channel, newPhase); - parent.validate(); - parent.repaint(); - } - }); - pickList.add(onset, c); - c.fill = GridBagConstraints.HORIZONTAL; - - // if (phase.phaseType == Phase.PhaseType.P) { - // c.fill = GridBagConstraints.NONE; - // Phase.FirstMotion[] firstMotions = Phase.FirstMotion.values(); - // final JComboBox firstMotion = - // new JComboBox(firstMotions); - // firstMotion.setFont(TABLE_FONT); - // int idx = 0; - // while (idx < firstMotions.length && firstMotions[idx] != phase.firstMotion) { - // idx++; - // } - // firstMotion.setSelectedIndex(idx); - // firstMotion.addActionListener(new ActionListener() { - // - // public void actionPerformed(ActionEvent e) { - // Phase newPhase = new Phase.Builder(phase) - // .firstMotion((Phase.FirstMotion) firstMotion.getSelectedItem()).build(); - // event.setPhase(channel, newPhase); - // parent.validate(); - // parent.repaint(); - // } - // }); - // pickList.add(firstMotion, c); - // c.fill = GridBagConstraints.HORIZONTAL; - // } else { - // pickList.add(new JLabel(""), c); - // } - // } - } - - - public void writePhase(final JPanel pickList, final String channel, final Phase phase, - final GridBagConstraints c) { - - boolean isSelected = selected.contains(channel); - - c.gridy++; - - String time = Time.toDateString(phase.time); - pickList.add(getLabel(time, isSelected), c); - - String phaseT = phase.phaseType.toString(); - pickList.add(getLabel(phaseT, isSelected), c); - - pickList.add(getLabel(channel, isSelected), c); - - c.fill = GridBagConstraints.NONE; - final JComboBox weight = new JComboBox(new Integer[] {0, 1, 2, 3, 4}); - weight.setFont(TABLE_FONT); - weight.setSelectedIndex(phase.weight); - weight.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - Phase newPhase = new Phase.Builder(phase).weight(weight.getSelectedIndex()).build(); - // event.setPhase(channel, newPhase); - parent.validate(); - parent.repaint(); - } - }); - pickList.add(weight, c); - c.fill = GridBagConstraints.HORIZONTAL; - - c.fill = GridBagConstraints.NONE; - Phase.Onset[] onsets = Phase.Onset.values(); - final JComboBox onset = new JComboBox(onsets); - onset.setFont(TABLE_FONT); - int i = 0; - while (i < onsets.length && onsets[i] != phase.onset) { - i++; - } - onset.setSelectedIndex(i); - onset.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - Phase newPhase = - new Phase.Builder(phase).onset((Phase.Onset) onset.getSelectedItem()).build(); - // event.setPhase(channel, newPhase); - parent.validate(); - parent.repaint(); - } - }); - pickList.add(onset, c); - c.fill = GridBagConstraints.HORIZONTAL; - - if (phase.phaseType == Phase.PhaseType.P) { - c.fill = GridBagConstraints.NONE; - Phase.FirstMotion[] firstMotions = Phase.FirstMotion.values(); - final JComboBox firstMotion = - new JComboBox(firstMotions); - firstMotion.setFont(TABLE_FONT); - int idx = 0; - while (idx < firstMotions.length && firstMotions[idx] != phase.firstMotion) { - idx++; - } - firstMotion.setSelectedIndex(idx); - firstMotion.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - Phase newPhase = new Phase.Builder(phase) - .firstMotion((Phase.FirstMotion) firstMotion.getSelectedItem()).build(); - // event.setPhase(channel, newPhase); - parent.validate(); - parent.repaint(); - } - }); - pickList.add(firstMotion, c); - c.fill = GridBagConstraints.HORIZONTAL; - } else { - pickList.add(new JLabel(""), c); - } - } - - public void eventUpdated() { - if (event == null) { - return; - } - - LOGGER.debug("Updating pick list"); - JPanel newList = new JPanel(); - newList.setLayout(new GridBagLayout()); - writeList(newList); - remove(pickList); - pickList = newList; - add(pickList, BorderLayout.CENTER); - // parent.repaint(); - } - - public void deselect(String channel) { - LOGGER.debug("deselecting {}", channel); - selected.remove(channel); - } - - public void deselectAll() { - LOGGER.debug("deselecting all"); - selected = new HashSet(); - - } - - public void select(String channel) { - LOGGER.debug("selecting {}", channel); - // selected.add(channel); - } - - public void remove(String channel) { - LOGGER.debug("removing {}", channel); - - selected.remove(channel); - // event.remove(channel); - } - - private JLabel getLabel(String string, boolean selected) { - JLabel label = new JLabel(string, SwingConstants.CENTER); - label.setFont(TABLE_FONT); - label.setOpaque(true); - if (selected) { - // label.setBackground(SELECTED_BACKGROUND_COLOR); - label.setBackground(BACKGROUND_COLOR); - Font font = label.getFont(); - font = font - .deriveFont(Collections.singletonMap(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD)); - // TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE)); - - label.setFont(font); - } else { - label.setBackground(BACKGROUND_COLOR); - } - - return label; - } - - public void setParent(Component parent) { - this.parent = parent; - } - - public void repaint() { - eventUpdated(); - super.repaint(); - - - - } -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java deleted file mode 100644 index 50dbdfcb..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerFrame.java +++ /dev/null @@ -1,1152 +0,0 @@ -package gov.usgs.volcanoes.swarm.picker; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.MouseInfo; -import java.awt.Point; -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.Transferable; -import java.awt.datatransfer.UnsupportedFlavorException; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.MouseEvent; -import java.awt.image.BufferedImage; -import java.beans.PropertyVetoException; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Stack; -import java.util.TimeZone; - -import javax.swing.AbstractAction; -import javax.swing.BorderFactory; -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.ButtonGroup; -import javax.swing.JButton; -import javax.swing.JFileChooser; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JRadioButtonMenuItem; -import javax.swing.JScrollPane; -import javax.swing.JSplitPane; -import javax.swing.JToolBar; -import javax.swing.KeyStroke; -import javax.swing.ScrollPaneConstants; -import javax.swing.SwingUtilities; -import javax.swing.TransferHandler; -import javax.swing.WindowConstants; -import javax.swing.event.InternalFrameAdapter; -import javax.swing.event.InternalFrameEvent; - -import gov.usgs.plot.data.Wave; -import gov.usgs.plot.data.file.FileType; -import gov.usgs.plot.data.file.SeismicDataFile; -import gov.usgs.util.Pair; -import gov.usgs.volcanoes.core.contrib.PngEncoder; -import gov.usgs.volcanoes.core.contrib.PngEncoderB; -import gov.usgs.volcanoes.core.time.J2kSec; -import gov.usgs.volcanoes.core.ui.ExtensionFileFilter; -import gov.usgs.volcanoes.core.util.UiUtils; -import gov.usgs.volcanoes.swarm.FileChooser; -import gov.usgs.volcanoes.swarm.Icons; -import gov.usgs.volcanoes.swarm.Metadata; -import gov.usgs.volcanoes.swarm.Swarm; -import gov.usgs.volcanoes.swarm.SwarmConfig; -import gov.usgs.volcanoes.swarm.SwarmFrame; -import gov.usgs.volcanoes.swarm.SwarmUtil; -import gov.usgs.volcanoes.swarm.SwingWorker; -import gov.usgs.volcanoes.swarm.Throbber; -import gov.usgs.volcanoes.swarm.chooser.DataChooser; -import gov.usgs.volcanoes.swarm.data.CachedDataSource; -import gov.usgs.volcanoes.swarm.data.SeismicDataSource; -import gov.usgs.volcanoes.swarm.event.Event; -import gov.usgs.volcanoes.swarm.event.EventObserver; -import gov.usgs.volcanoes.swarm.picker.hypo71.Hypo71Locator; -import gov.usgs.volcanoes.swarm.time.TimeListener; -import gov.usgs.volcanoes.swarm.time.WaveViewTime; -import gov.usgs.volcanoes.swarm.wave.AbstractWavePanel; -import gov.usgs.volcanoes.swarm.wave.WaveViewPanelAdapter; -import gov.usgs.volcanoes.swarm.wave.WaveViewPanelListener; -import gov.usgs.volcanoes.swarm.wave.WaveViewSettingsToolbar; - -/** - * The picker internal frame. Adapted from the WaveClipboardFrame. - * - * @author Tom Parker - */ -public class PickerFrame extends SwarmFrame implements EventObserver { - private static final Logger LOGGER = LoggerFactory.getLogger(PickerFrame.class); - - public static final long serialVersionUID = -1; - private static final Color SELECT_COLOR = new Color(200, 220, 241); - private static final Color BACKGROUND_COLOR = new Color(0xf7, 0xf7, 0xf7); - - private JScrollPane scrollPane; - private Box waveBox; - private PickListPanel pickList; - private JSplitPane mainPanel; - private PickerWavePanel baseWave; - private final List waves; - private final Set selectedSet; - private JToolBar toolbar; - private JLabel statusLabel; - private JButton sizeButton; - private JButton saveButton; - private JButton captureButton; - private JButton histButton; - private JButton locateButton; - - private final DateFormat saveAllDateFormat; - - private WaveViewPanelListener selectListener; - private WaveViewSettingsToolbar waveToolbar; - - private JButton upButton; - private JButton downButton; - private JButton removeButton; - private JButton compXButton; - private JButton expXButton; - private JButton forwardButton; - private JButton backButton; - private JButton gotoButton; - - private JPopupMenu popup; - - private final Map> histories; - - private Throbber throbber; - - private int waveHeight = -1; - - private int lastClickedIndex = -1; - - private Event event; - - public PickerFrame() { - super("Picker", true, true, true, false); - event = new Event("testIId"); - event.addObserver(this); - - this.setFocusable(true); - this.setVisible(true); - selectedSet = new HashSet(); - saveAllDateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); - saveAllDateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); - waves = new ArrayList(); - histories = new HashMap>(); - createUI(); - LOGGER.debug("Finished creating picker frame."); - this.setVisible(true); - - // getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("typed q"), - // "pPick"); - getInputMap().put(KeyStroke.getKeyStroke("typed q"), "pPick"); - getActionMap().put("pPick", new AbstractAction() { - private static final long serialVersionUID = -1; - - public void actionPerformed(final ActionEvent e) { - findWavePanel(); - } - }); - - } - - public PickerFrame(Event event) { - super("Picker", true, true, true, false); - this.event = event; - event.addObserver(this); - - this.setFocusable(true); - this.setVisible(true); - selectedSet = new HashSet(); - saveAllDateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); - saveAllDateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); - waves = new ArrayList(); - histories = new HashMap>(); - createUI(); - LOGGER.debug("Finished creating picker frame."); - this.setVisible(true); - - // getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("typed q"), - // "pPick"); - getInputMap().put(KeyStroke.getKeyStroke("typed q"), "pPick"); - getActionMap().put("pPick", new AbstractAction() { - private static final long serialVersionUID = -1; - - public void actionPerformed(final ActionEvent e) { - findWavePanel(); - } - }); - } - - private void findWavePanel() { - Point p = MouseInfo.getPointerInfo().getLocation(); - SwingUtilities.convertPointFromScreen(p, waveBox); - int idx = p.y / calculateWaveHeight(); - PickerWavePanel panel = waves.get(idx); - panel.instantPick(Phase.PhaseType.P); - } - - private void createUI() { - this.setFrameIcon(Icons.ruler); - this.setSize(swarmConfig.clipboardWidth, swarmConfig.clipboardHeight); - this.setLocation(swarmConfig.clipboardX, swarmConfig.clipboardY); - this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - LOGGER.debug("picker frame: {} @ {}", this.getSize(), this.getLocation()); - - toolbar = SwarmUtil.createToolBar(); - - JPanel wavePanel = new JPanel(); - wavePanel.setLayout(new BoxLayout(wavePanel, BoxLayout.PAGE_AXIS)); - - JPanel tablePanel = new JPanel(); - tablePanel.setLayout(new BoxLayout(tablePanel, BoxLayout.PAGE_AXIS)); - - mainPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT, wavePanel, tablePanel); - mainPanel.setOneTouchExpandable(true); - - createMainButtons(); - createWaveButtons(); - wavePanel.add(toolbar); - - waveBox = new Box(BoxLayout.Y_AXIS); - waveBox.setTransferHandler(new TransferHandler("") { - public boolean canImport(TransferSupport supp) { - return supp.isDataFlavorSupported(DataFlavor.stringFlavor); - } - - public boolean importData(TransferSupport supp) { - if (!canImport(supp)) { - return false; - } - - Transferable t = supp.getTransferable(); - String data = null; - try { - data = (String) t.getTransferData(DataFlavor.stringFlavor); - } catch (UnsupportedFlavorException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - // Fetch the drop location - DropLocation loc = supp.getDropLocation(); - - // Insert the data at this location - LOGGER.debug("DROP {} @ {}", data, loc); - String[] chans = data.split("\n"); - for (String chan : chans) { - addWave(chan); - } - return true; - } - - }); - scrollPane = new JScrollPane(waveBox); - scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); - scrollPane.getVerticalScrollBar().setUnitIncrement(40); - wavePanel.add(scrollPane); - - JPanel statusPanel = new JPanel(); - statusPanel.setLayout(new BorderLayout()); - statusLabel = new JLabel(" "); - statusLabel.setBorder(BorderFactory.createEtchedBorder()); - statusPanel.add(statusLabel); - statusPanel - .setMaximumSize(new Dimension(Integer.MAX_VALUE, statusPanel.getPreferredSize().height)); - wavePanel.add(statusPanel); - - pickList = new PickListPanel(event); - pickList.setParent(mainPanel); - - scrollPane = new JScrollPane(pickList); - scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); - scrollPane.getVerticalScrollBar().setUnitIncrement(40); - tablePanel.add(scrollPane); - - mainPanel.setResizeWeight(.75); - this.setContentPane(mainPanel); - - createListeners(); - doButtonEnables(); - } - - private void createMainButtons() { - saveButton = - SwarmUtil.createToolBarButton(Icons.save, "Save selected wave", new SaveActionListener()); - saveButton.setEnabled(false); - toolbar.add(saveButton); - - toolbar.addSeparator(); - - sizeButton = - SwarmUtil.createToolBarButton(Icons.resize, "Set wave height", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - doSizePopup(); - } - }); - toolbar.add(sizeButton); - - toolbar.addSeparator(); - captureButton = SwarmUtil.createToolBarButton(Icons.camera, "Save pick image (P)", - new CaptureActionListener()); - UiUtils.mapKeyStrokeToButton(this, "P", "capture", captureButton); - toolbar.add(captureButton); - } - - // TODO: don't write image on event thread - // TODO: unify with MapFrame.CaptureActionListener - class CaptureActionListener implements ActionListener { - public void actionPerformed(final ActionEvent e) { - if (waves == null || waves.size() == 0) - return; - - final JFileChooser chooser = FileChooser.getFileChooser(); - final File lastPath = new File(swarmConfig.lastPath); - chooser.setCurrentDirectory(lastPath); - chooser.setSelectedFile(new File("clipboard.png")); - chooser.setDialogTitle("Save Clipboard Screen Capture"); - final int result = chooser.showSaveDialog(applicationFrame); - File f = null; - if (result == JFileChooser.APPROVE_OPTION) { - f = chooser.getSelectedFile(); - - if (f.exists()) { - final int choice = JOptionPane.showConfirmDialog(applicationFrame, - "File exists, overwrite?", "Confirm", JOptionPane.YES_NO_OPTION); - if (choice != JOptionPane.YES_OPTION) - return; - } - swarmConfig.lastPath = f.getParent(); - } - if (f == null) - return; - - int height = 0; - final int width = waves.get(0).getWidth(); - for (final AbstractWavePanel panel : waves) - height += panel.getHeight(); - - final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); - final Graphics g = image.getGraphics(); - for (final AbstractWavePanel panel : waves) { - panel.paint(g); - g.translate(0, panel.getHeight()); - } - try { - final PngEncoderB png = new PngEncoderB(image, false, PngEncoder.FILTER_NONE, 7); - final FileOutputStream out = new FileOutputStream(f); - final byte[] bytes = png.pngEncode(); - out.write(bytes); - out.close(); - } catch (final Exception ex) { - ex.printStackTrace(); - } - } - } - - private void createWaveButtons() { - toolbar.addSeparator(); - - backButton = SwarmUtil.createToolBarButton(Icons.left, "Scroll back time 20% (Left arrow)", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - shiftTime(-0.20); - } - }); - UiUtils.mapKeyStrokeToButton(this, "LEFT", "backward1", backButton); - toolbar.add(backButton); - - forwardButton = SwarmUtil.createToolBarButton(Icons.right, - "Scroll forward time 20% (Right arrow)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - shiftTime(0.20); - } - }); - toolbar.add(forwardButton); - UiUtils.mapKeyStrokeToButton(this, "RIGHT", "forward1", forwardButton); - - gotoButton = - SwarmUtil.createToolBarButton(Icons.gototime, "Go to time (Ctrl-G)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - final String t = JOptionPane.showInputDialog(applicationFrame, - "Input time in 'YYYYMMDDhhmm[ss]' format:", "Go to Time", - JOptionPane.PLAIN_MESSAGE); - if (t != null) - gotoTime(t); - } - }); - toolbar.add(gotoButton); - UiUtils.mapKeyStrokeToButton(this, "ctrl G", "goto", gotoButton); - - compXButton = SwarmUtil.createToolBarButton(Icons.xminus, - "Shrink sample time 20% (Alt-left arrow, +)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - scaleTime(0.20); - } - }); - toolbar.add(compXButton); - UiUtils.mapKeyStrokeToButton(this, "alt LEFT", "compx", compXButton); - UiUtils.mapKeyStrokeToButton(this, "EQUALS", "compx2", compXButton); - UiUtils.mapKeyStrokeToButton(this, "shift EQUALS", "compx2", compXButton); - - expXButton = SwarmUtil.createToolBarButton(Icons.xplus, - "Expand sample time 20% (Alt-right arrow, -)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - scaleTime(-0.20); - } - }); - toolbar.add(expXButton); - UiUtils.mapKeyStrokeToButton(this, "alt RIGHT", "expx", expXButton); - UiUtils.mapKeyStrokeToButton(this, "MINUS", "expx", expXButton); - - histButton = SwarmUtil.createToolBarButton(Icons.timeback, "Last time settings (Backspace)", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - back(); - } - }); - UiUtils.mapKeyStrokeToButton(this, "BACK_SPACE", "back", histButton); - toolbar.add(histButton); - toolbar.addSeparator(); - - waveToolbar = new WaveViewSettingsToolbar(null, toolbar, this); - - toolbar.addSeparator(); - - upButton = SwarmUtil.createToolBarButton(Icons.up, "Move wave up in clipboard (Up arrow)", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - moveUp(); - } - }); - UiUtils.mapKeyStrokeToButton(this, "UP", "up", upButton); - toolbar.add(upButton); - - downButton = SwarmUtil.createToolBarButton(Icons.down, - "Move wave down in clipboard (Down arrow)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - moveDown(); - } - }); - UiUtils.mapKeyStrokeToButton(this, "DOWN", "down", downButton); - toolbar.add(downButton); - - removeButton = SwarmUtil.createToolBarButton(Icons.delete, - "Remove wave from clipboard (Delete)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - remove(); - } - }); - UiUtils.mapKeyStrokeToButton(this, "DELETE", "remove", removeButton); - toolbar.add(removeButton); - - locateButton = SwarmUtil.createToolBarButton(Icons.locate, "Locate", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - EventLocator locator = new Hypo71Locator(); -// try { -// locator.locate(event); -// } catch (IOException e1) { -// e1.printStackTrace(); -// }; - } - - private void particleMotionPlot() { - // TODO Auto-generated method stub - - } - }); - toolbar.add(locateButton); - - toolbar.add(Box.createHorizontalGlue()); - - throbber = new Throbber(); - toolbar.add(throbber); - - UiUtils.mapKeyStrokeToAction(this, "control A", "selectAll", new AbstractAction() { - private static final long serialVersionUID = 1L; - - public void actionPerformed(final ActionEvent e) { - for (final PickerWavePanel wave : waves) - select(wave); - } - }); - } - - private void createListeners() { - this.addInternalFrameListener(new InternalFrameAdapter() { - @Override - public void internalFrameActivated(final InternalFrameEvent e) {} - - @Override - public void internalFrameDeiconified(final InternalFrameEvent e) { - resizeWaves(); - } - - @Override - public void internalFrameClosing(final InternalFrameEvent e) { - setVisible(false); - } - - @Override - public void internalFrameClosed(final InternalFrameEvent e) {} - }); - - this.addComponentListener(new ComponentAdapter() { - @Override - public void componentResized(final ComponentEvent e) { - resizeWaves(); - } - }); - - WaveViewTime.addTimeListener(new TimeListener() { - public void timeChanged(final double j2k) { - for (final AbstractWavePanel panel : waves) { - if (panel != null) - panel.setCursorMark(j2k); - } - } - }); - - selectListener = new WaveViewPanelAdapter() { - public void mousePressed(final AbstractWavePanel src, final MouseEvent e, - final boolean dragging) { - PickerWavePanel panel = (PickerWavePanel) src; - LOGGER.debug("wave selected."); - requestFocusInWindow(); - final int thisIndex = getWaveIndex(src); - if (!e.isControlDown() && !e.isShiftDown() && !e.isAltDown()) { - deselectAll(); - select(panel); - } else if (e.isControlDown()) { - if (selectedSet.contains(src)) - deselect(src); - else - select(panel); - } else if (e.isShiftDown()) { - if (lastClickedIndex == -1) - select(panel); - else { - deselectAll(); - final int min = Math.min(lastClickedIndex, thisIndex); - final int max = Math.max(lastClickedIndex, thisIndex); - for (int i = min; i <= max; i++) { - final PickerWavePanel ps = (PickerWavePanel) waveBox.getComponent(i); - select(ps); - } - } - } - lastClickedIndex = thisIndex; -// event.notifyObservers(); - mainPanel.validate(); - mainPanel.repaint(); - } - - @Override - public void waveZoomed(final AbstractWavePanel src, final double st, final double et, - final double nst, final double net) { - final double[] t = new double[] {st, et}; - addHistory(src, t); - for (final AbstractWavePanel wvp : selectedSet) { - if (wvp != src) { - addHistory(wvp, t); - wvp.zoom(nst, net); - } - } - } - - @Override - public void waveClosed(final AbstractWavePanel src) { - LOGGER.debug("Removing wave: {}", src.getChannel()); - remove(src); - } - }; - } - - private int calculateWaveHeight() { - if (waveHeight > 0) - return waveHeight; - - final int w = scrollPane.getViewport().getSize().width; - int h = (int) Math.round(w * 60.0 / 300.0); - h = Math.min(200, h); - h = Math.max(h, 80); - return h; - } - - private void setWaveHeight(final int s) { - waveHeight = s; - resizeWaves(); - } - - private void doSizePopup() { - if (popup == null) { - final String[] labels = new String[] {"Auto", null, "Tiny", "Small", "Medium", "Large"}; - final int[] sizes = new int[] {-1, -1, 50, 100, 160, 230}; - popup = new JPopupMenu(); - final ButtonGroup group = new ButtonGroup(); - for (int i = 0; i < labels.length; i++) { - if (labels[i] != null) { - final int size = sizes[i]; - final JRadioButtonMenuItem mi = new JRadioButtonMenuItem(labels[i]); - mi.addActionListener(new ActionListener() { - public void actionPerformed(final ActionEvent e) { - setWaveHeight(size); - } - }); - if (waveHeight == size) - mi.setSelected(true); - group.add(mi); - popup.add(mi); - } else - popup.addSeparator(); - } - } - popup.show(sizeButton.getParent(), sizeButton.getX(), sizeButton.getY()); - } - - private class SaveActionListener implements ActionListener { - public void actionPerformed(final ActionEvent e) { - final AbstractWavePanel selected = getSingleSelected(); - if (selected == null) - return; - - final JFileChooser chooser = FileChooser.getFileChooser(); - chooser.resetChoosableFileFilters(); - chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); - chooser.setMultiSelectionEnabled(false); - chooser.setDialogTitle("Save Wave"); - - for (final FileType ft : FileType.values()) { - if (ft == FileType.UNKNOWN) - continue; - - final ExtensionFileFilter f = new ExtensionFileFilter(ft.extension, ft.description); - chooser.addChoosableFileFilter(f); - } - - chooser.setFileFilter(chooser.getAcceptAllFileFilter()); - - final File lastPath = new File(swarmConfig.lastPath); - chooser.setCurrentDirectory(lastPath); - final String fileName = selected.getChannel().replace(' ', '_') + ".sac"; - chooser.setSelectedFile(new File(fileName)); - final int result = chooser.showSaveDialog(applicationFrame); - if (result == JFileChooser.APPROVE_OPTION) { - final File f = chooser.getSelectedFile(); - boolean confirm = true; - if (f.exists()) { - if (f.isDirectory()) { - JOptionPane.showMessageDialog(applicationFrame, - "You can not select an existing directory.", "Error", JOptionPane.ERROR_MESSAGE); - return; - } - confirm = false; - final int choice = JOptionPane.showConfirmDialog(applicationFrame, - "File exists, overwrite?", "Confirm", JOptionPane.YES_NO_OPTION); - if (choice == JOptionPane.YES_OPTION) - confirm = true; - } - - if (confirm) { - try { - swarmConfig.lastPath = f.getParent(); - final String fn = f.getPath(); - final SeismicDataFile file = SeismicDataFile.getFile(fn); - final Wave wave = selected.getWave(); - file.putWave(selected.getChannel(), wave); - file.write(); - } catch (final FileNotFoundException ex) { - JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Directory does not exist.", - "Error", JOptionPane.ERROR_MESSAGE); - } catch (final IOException ex) { - JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Error writing file.", - "Error", JOptionPane.ERROR_MESSAGE); - } - } - } - } - } - - - - private void doButtonEnables() { - final boolean enable = (waves == null || waves.size() == 0); - - final boolean allowSingle = (selectedSet.size() == 1); - upButton.setEnabled(allowSingle); - downButton.setEnabled(allowSingle); - - final boolean allowMulti = (selectedSet.size() > 0); - backButton.setEnabled(allowMulti); - expXButton.setEnabled(allowMulti); - compXButton.setEnabled(allowMulti); - backButton.setEnabled(allowMulti); - forwardButton.setEnabled(allowMulti); - histButton.setEnabled(allowMulti); - removeButton.setEnabled(allowMulti); - gotoButton.setEnabled(allowMulti); - } - - public synchronized PickerWavePanel getSingleSelected() { - if (selectedSet.size() != 1) - return null; - - PickerWavePanel p = null; - for (final PickerWavePanel panel : selectedSet) - p = panel; - - return p; - } - - public synchronized void syncChannels() { - final AbstractWavePanel p = getSingleSelected(); - if (p == null) - return; - - final double st = p.getStartTime(); - final double et = p.getEndTime(); - - // TODO: thread bug here. must synch iterator below - final SwingWorker worker = new SwingWorker() { - @Override - public Object construct() { - List copy = null; - synchronized (PickerFrame.this) { - copy = new ArrayList(waves); - } - for (final AbstractWavePanel wvp : copy) { - if (wvp != p) { - if (wvp.getDataSource() != null) { - addHistory(wvp, new double[] {wvp.getStartTime(), wvp.getEndTime()}); - final Wave sw = wvp.getDataSource().getWave(wvp.getChannel(), st, et); - wvp.setWave(sw, st, et); - } - } - } - return null; - } - - @Override - public void finished() { - repaint(); - } - }; - worker.start(); - } - - public void setStatusText(final String s) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - statusLabel.setText(s); - } - }); - } - - public synchronized void setBaseWave(final PickerWavePanel p) { - baseWave = p; - addWave(p); - doButtonEnables(); - waveBox.validate(); - - String channel = p.getChannel(); - - final List> nrst = - Metadata.findNearest(SwarmConfig.getInstance().getMetadata(), channel); - - final SwingWorker worker = new SwingWorker() { - @Override - public Object construct() { - for (Pair item : nrst) { - if (item.item1 > 20000) { - break; - } else if (item.item2.matches(".*(B|E|H)H(Z|E|N).*")) { - PickerWavePanel p2 = new PickerWavePanel(p); - p2.setChannel(item.item2); - SeismicDataSource sds = p2.getDataSource(); - double st = p2.getStartTime(); - double et = p2.getEndTime(); - Wave wave = sds.getWave(item.item2, st, et); - if (wave != null && wave.isData()) { - p2.setWave(wave, st, et); - p2.getWaveViewSettings().autoScaleAmpMemory = false; - addWave(p2); - System.out.println(String.format("%s (%.1f km)", item.item2, item.item1 / 1000)); - } else { - LOGGER.debug("Skipping {}, no data.", item.item2); - } - } - } - return null; - } - - @Override - public void finished() { - waveBox.validate(); - validate(); - repaint(); - } - }; - worker.start(); - } - - public synchronized void addWave(final String chan) { - PickerWavePanel p2 = new PickerWavePanel(baseWave); - p2.setChannel(chan); - SeismicDataSource sds = p2.getDataSource(); - double st = p2.getStartTime(); - double et = p2.getEndTime(); - Wave wave = sds.getWave(chan, st, et); - if (wave != null && wave.isData()) { - p2.setWave(wave, st, et); - p2.getWaveViewSettings().autoScaleAmpMemory = false; - addWave(p2); - } - } - - public synchronized void addWave(final PickerWavePanel p) { - p.addListener(selectListener); - p.setOffsets(54, 8, 21, 19); - p.setAllowClose(true); - p.setStatusLabel(statusLabel); - p.setAllowDragging(true); - p.setDisplayTitle(true); -// p.setEvent(event); - p.setParent(mainPanel); - final int w = scrollPane.getViewport().getSize().width; - p.setSize(w, calculateWaveHeight()); - p.setBottomBorderColor(Color.GRAY); - p.createImage(); - waveBox.add(p); - waves.add(p); - LOGGER.debug("{} panels; {} waves", waveBox.getComponentCount(), waves.size()); - } - - private synchronized void deselect(final AbstractWavePanel p) { - selectedSet.remove(p); - pickList.deselect(p.getChannel()); - waveToolbar.removeSettings(p.getSettings()); - p.setBackgroundColor(BACKGROUND_COLOR); - p.createImage(); - doButtonEnables(); - } - - private synchronized void deselectAll() { - final AbstractWavePanel[] panels = selectedSet.toArray(new AbstractWavePanel[0]); - pickList.deselectAll(); - for (final AbstractWavePanel p : panels) { - deselect(p); - } - } - - private synchronized void select(final PickerWavePanel p) { - if (p == null || selectedSet.contains(p)) - return; - - pickList.select(p.getChannel()); - selectedSet.add(p); - doButtonEnables(); - p.setBackgroundColor(SELECT_COLOR); - DataChooser.getInstance().setNearest(p.getChannel()); - p.createImage(); - waveToolbar.addSettings(p.getSettings()); - } - - private synchronized void remove(final AbstractWavePanel p) { -// event.remove(p.getChannel()); - int i = 0; - for (i = 0; i < waveBox.getComponentCount(); i++) { - if (p == waveBox.getComponent(i)) - break; - } - - p.removeListener(selectListener); - p.getDataSource().close(); - setStatusText(" "); - waveBox.remove(i); - waves.remove(p); - histories.remove(p); - doButtonEnables(); - waveBox.validate(); - selectedSet.remove(p); - pickList.remove(p.getChannel()); - lastClickedIndex = Math.min(lastClickedIndex, waveBox.getComponentCount() - 1); - waveToolbar.removeSettings(p.getSettings()); -// event.notifyObservers(); - validate(); - repaint(); - } - - protected int getWaveIndex(final AbstractWavePanel p) { - int i = 0; - for (i = 0; i < waveBox.getComponentCount(); i++) { - if (p == waveBox.getComponent(i)) - break; - } - return i; - } - - public synchronized void remove() { - final PickerWavePanel[] panels = selectedSet.toArray(new PickerWavePanel[0]); - for (final PickerWavePanel p : panels) { - LOGGER.debug("removing panel {}", p); - waveBox.remove(p); - waves.remove(p); -// event.remove(p.getChannel()); - // pickList.remove(p); - validate(); - repaint(); - } - } - - public synchronized void moveDown() { - final PickerWavePanel p = getSingleSelected(); - if (p == null) - return; - - final int i = waves.indexOf(p); - if (i == waves.size() - 1) - return; - - waves.remove(i); - waves.add(i + 1, p); - waveBox.remove(p); - waveBox.add(p, i + 1); - waveBox.validate(); - repaint(); - } - - public synchronized void moveUp() { - final PickerWavePanel p = getSingleSelected(); - if (p == null) - return; - - final int i = waves.indexOf(p); - if (i == 0) - return; - - waves.remove(i); - waves.add(i - 1, p); - waveBox.remove(p); - waveBox.add(p, i - 1); - waveBox.validate(); - repaint(); - } - - public void resizeWaves() { - final SwingWorker worker = new SwingWorker() { - @Override - public Object construct() { - final int w = scrollPane.getViewport().getSize().width; - for (final AbstractWavePanel wave : waves) { - wave.setSize(w, calculateWaveHeight()); - wave.createImage(); - } - return null; - } - - @Override - public void finished() { - waveBox.validate(); - validate(); - repaint(); - } - }; - worker.start(); - } - - public void removeWaves() { - while (waves.size() > 0) - remove(waves.get(0)); - - waveBox.validate(); - scrollPane.validate(); - doButtonEnables(); - repaint(); - } - - private void addHistory(final AbstractWavePanel wvp, final double[] t) { - Stack history = histories.get(wvp); - if (history == null) { - history = new Stack(); - histories.put(wvp, history); - } - history.push(t); - } - - public void gotoTime(final AbstractWavePanel wvp, String t) { - double j2k = Double.NaN; - try { - if (t.length() == 12) - t = t + "30"; - - j2k = J2kSec.parse("yyyyMMddHHmmss", t); - } catch (final Exception e) { - JOptionPane.showMessageDialog(applicationFrame, "Illegal time value.", "Error", - JOptionPane.ERROR_MESSAGE); - } - - if (!Double.isNaN(j2k)) { - double dt = 60; - if (wvp.getWave() != null) { - final double st = wvp.getStartTime(); - final double et = wvp.getEndTime(); - final double[] ts = new double[] {st, et}; - addHistory(wvp, ts); - dt = (et - st); - } - - final double tzo = - swarmConfig.getTimeZone(wvp.getChannel()).getOffset(System.currentTimeMillis()) / 1000; - - final double nst = j2k - tzo - dt / 2; - final double net = nst + dt; - - fetchNewWave(wvp, nst, net); - } - } - - public void gotoTime(final String t) { - for (final AbstractWavePanel p : selectedSet) - gotoTime(p, t); - } - - public void scaleTime(final AbstractWavePanel wvp, final double pct) { - final double st = wvp.getStartTime(); - final double et = wvp.getEndTime(); - final double[] t = new double[] {st, et}; - addHistory(wvp, t); - final double dt = (et - st) * (1 - pct); - final double mt = (et - st) / 2 + st; - final double nst = mt - dt / 2; - final double net = mt + dt / 2; - fetchNewWave(wvp, nst, net); - } - - public void scaleTime(final double pct) { - for (final AbstractWavePanel p : selectedSet) - scaleTime(p, pct); - } - - public void back(final AbstractWavePanel wvp) { - final Stack history = histories.get(wvp); - if (history == null || history.empty()) - return; - - final double[] t = history.pop(); - fetchNewWave(wvp, t[0], t[1]); - } - - public void back() { - for (final AbstractWavePanel p : selectedSet) - back(p); - } - - private void shiftTime(final AbstractWavePanel wvp, final double pct) { - final double st = wvp.getStartTime(); - final double et = wvp.getEndTime(); - final double[] t = new double[] {st, et}; - addHistory(wvp, t); - final double dt = (et - st) * pct; - final double nst = st + dt; - final double net = et + dt; - fetchNewWave(wvp, nst, net); - } - - public void shiftTime(final double pct) { - for (final AbstractWavePanel p : selectedSet) - shiftTime(p, pct); - } - - public void repositionWaves(final double st, final double et) { - for (final AbstractWavePanel wave : waves) { - fetchNewWave(wave, st, et); - } - } - - public Throbber getThrobber() { - return throbber; - } - - // TODO: This isn't right, this should be a method of waveviewpanel - private void fetchNewWave(final AbstractWavePanel wvp, final double nst, final double net) { - final SwingWorker worker = new SwingWorker() { - @Override - public Object construct() { - throbber.increment(); - final SeismicDataSource sds = wvp.getDataSource(); - // Hacky fix for bug #84 - Wave sw = null; - if (sds instanceof CachedDataSource) - sw = ((CachedDataSource) sds).getBestWave(wvp.getChannel(), nst, net); - else - sw = sds.getWave(wvp.getChannel(), nst, net); - wvp.setWave(sw, nst, net); - wvp.repaint(); - return null; - } - - @Override - public void finished() { - throbber.decrement(); - repaint(); - } - }; - worker.start(); - } - - @Override - public void setMaximum(final boolean max) throws PropertyVetoException { - if (max) { - swarmConfig.clipboardX = getX(); - swarmConfig.clipboardY = getY(); - } - super.setMaximum(max); - } - - @Override - public void paint(final Graphics g) { - super.paint(g); - if (waves.size() == 0) { - final Dimension dim = this.getSize(); - g.setColor(Color.black); - g.drawString("Picker empty.", dim.width / 2 - 40, dim.height / 2); - } - } - - @Override - public void setVisible(final boolean isVisible) { - LOGGER.debug("Visible = {}", isVisible); - super.setVisible(isVisible); - if (isVisible) - toFront(); - } - - - public void eventUpdated() { -// LOGGER.debug("event is empty? {}", event.getChannels().isEmpty()); -// saveButton.setEnabled(!event.getChannels().isEmpty()); - } -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java deleted file mode 100644 index 3e9ffad9..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/PickerWavePanel.java +++ /dev/null @@ -1,181 +0,0 @@ -package gov.usgs.volcanoes.swarm.picker; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.event.MouseEvent; -import java.awt.geom.Line2D; - -import javax.swing.JScrollPane; - -import gov.usgs.volcanoes.core.time.J2kSec; -import gov.usgs.volcanoes.swarm.event.EventObserver; -import gov.usgs.volcanoes.swarm.picker.Phase.PhaseType; -import gov.usgs.volcanoes.swarm.time.WaveViewTime; -import gov.usgs.volcanoes.swarm.wave.AbstractWavePanel; - -public class PickerWavePanel extends AbstractWavePanel implements EventObserver { - - private static final Logger LOGGER = LoggerFactory.getLogger(PickerWavePanel.class); - - private static final Font ANNOTATION_FONT = new Font("Monospaced", Font.BOLD, 12); - private static final Color P_BACKGROUND = new Color(128, 255, 128, 192); - private static final Color S_BACKGROUND = new Color(128, 128, 255, 192); - private static final Color CODA_BACKGROUND = new Color(128, 128, 128, 192); - private EventOld event; - private Component parent; - - public PickerWavePanel(AbstractWavePanel insetWavePanel) { - super(insetWavePanel); - } - - @Override - protected void processRightMousePress(MouseEvent e) { - double[] t = getTranslation(); - int x = e.getX(); - double cursorTime = x * t[0] + t[1]; - LOGGER.debug("New phase: {} @ {}", channel, J2kSec.toDateString(cursorTime)); - - PhasePopup phasePopup = new PhasePopup(event, channel, J2kSec.asEpoch(cursorTime)); - phasePopup.setParent(parent); - phasePopup.show(e.getComponent(), e.getX(), e.getY()); - pauseCursorMark = true; - WaveViewTime.fireTimeChanged(cursorTime); - } - - public void instantPick(PhaseType p) { - Phase phase = new Phase.Builder().onset(Phase.Onset.i).phaseType(Phase.PhaseType.P) - .firstMotion(Phase.FirstMotion.UP).time(J2kSec.asEpoch(time)).weight(1).build(); - - event.setPhase(channel, phase); - WaveViewTime.fireTimeChanged(time); - } - public void setEvent(EventOld event) { - this.event = event; - } - - @Override - protected void annotateImage(Graphics2D g2) { - for (Phase.PhaseType type : Phase.PhaseType.values()) { - Phase phase = event.getPhase(channel, type); - if (phase != null) { - Color background; - if (phase.phaseType == Phase.PhaseType.P) { - markPhase(g2, P_BACKGROUND, phase.time, phase.tag()); - long time = event.coda(channel); - if (time > 0) { - markPhase(g2, CODA_BACKGROUND, event.coda(channel), "C"); - } - } else { - markPhase(g2, S_BACKGROUND, phase.time, phase.tag()); - } - } - } - // repaint(); - } - - private void markPhase(Graphics2D g2, Color backgroundColor, long time, String tag) { - double j2k = J2kSec.fromEpoch(time); - double[] t = getTranslation(); - if (t == null) - return; - - double x = 2 + (j2k - t[1]) / t[0]; - g2.setColor(DARK_GREEN); - g2.draw(new Line2D.Double(x, yOffset, x, getHeight() - bottomHeight - 1)); - - Font oldFont = g2.getFont(); - g2.setFont(ANNOTATION_FONT); - - FontMetrics fm = g2.getFontMetrics(); - int width = fm.stringWidth(tag); - int height = fm.getAscent(); - - int offset = 2; - int lw = width + 2 * offset; - - g2.setColor(backgroundColor); - - g2.fillRect((int) x, 3, lw, height + 2 * offset); - g2.setColor(Color.black); - g2.drawRect((int) x, 3, lw, height + 2 * offset); - - g2.drawString(tag, (int) x + offset, 3 + (fm.getAscent() + offset)); - g2.setFont(oldFont); - } - - /** - * Paints the component on the specified graphics context. - * - * @param g the graphics context - */ - public void paint(Graphics g) { - - Rectangle rect = ((JScrollPane)getParent()).getVisibleRect(); - if (!rect.intersects(getBounds())) { - return; - } - - super.paint(g); - } - - -// private void markPhase(Graphics2D g2, Phase phase) { -// double j2k = J2kSec.fromEpoch(phase.time); -// double[] t = getTranslation(); -// if (t == null) -// return; -// -// double x = 2 + (j2k - t[1]) / t[0]; -// g2.setColor(DARK_GREEN); -// g2.draw(new Line2D.Double(x, yOffset, x, getHeight() - bottomHeight - 1)); -// -// String tag = phase.tag(); -// Font oldFont = g2.getFont(); -// g2.setFont(ANNOTATION_FONT); -// -// FontMetrics fm = g2.getFontMetrics(); -// int width = fm.stringWidth(tag); -// int height = fm.getAscent(); -// -// int offset = 2; -// int lw = width + 2 * offset; -// -// Color background = null; -// if (phase.phaseType == Phase.PhaseType.P) { -// background = P_BACKGROUND; -// } else if (phase.phaseType == Phase.PhaseType.S) { -// background = S_BACKGROUND; -// } -// g2.setColor(background); -// -// g2.fillRect((int) x, 3, lw, height + 2 * offset); -// g2.setColor(Color.black); -// g2.drawRect((int) x, 3, lw, height + 2 * offset); -// -// g2.drawString(tag, (int) x + offset, 3 + (fm.getAscent() + offset)); -// g2.setFont(oldFont); -// } - - @Override - protected void processRightMouseRelease(MouseEvent e) { - pauseCursorMark = false; - } - - public void eventUpdated() { - repaint(); - } - - public void setParent(Component parent) { - this.parent = parent; - } - - -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Locator.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Locator.java deleted file mode 100644 index d11d50e2..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/Hypo71Locator.java +++ /dev/null @@ -1,222 +0,0 @@ -package gov.usgs.volcanoes.swarm.picker.hypo71; - -import java.io.IOException; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.LinkedList; -import java.util.Map; -import java.util.Queue; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import gov.usgs.volcanoes.core.hypo71.ControlCard; -import gov.usgs.volcanoes.core.hypo71.CrustalModel; -import gov.usgs.volcanoes.core.hypo71.Hypo71; -import gov.usgs.volcanoes.core.hypo71.HypoArchiveOutput; -import gov.usgs.volcanoes.core.hypo71.Hypocenter; -import gov.usgs.volcanoes.core.hypo71.PhaseRecord; -import gov.usgs.volcanoes.core.hypo71.Station; -import gov.usgs.volcanoes.core.hypo71.Hypo71.Results; -import gov.usgs.volcanoes.swarm.Metadata; -import gov.usgs.volcanoes.swarm.SwarmConfig; -import gov.usgs.volcanoes.swarm.picker.EventOld; -import gov.usgs.volcanoes.swarm.picker.EventChannel; -import gov.usgs.volcanoes.swarm.picker.EventLocator; -import gov.usgs.volcanoes.swarm.picker.Hypocenters; -import gov.usgs.volcanoes.swarm.picker.Phase; - -public class Hypo71Locator implements EventLocator { - - private static final Logger LOGGER = LoggerFactory.getLogger(Hypo71Locator.class); - private ControlCard controlCard; - private Queue phaseRecordsList; - private Queue stationsList; - private Queue crustalModelList; - private SimpleDateFormat jtimeFormat; - - public Hypo71Locator() { - - // defaults taken from hypo-test-case-1.properties - controlCard = - new ControlCard(0, 5.0, 50.0, 100.0, 1.78, 2, 1, 18, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0); - - crustalModelList = new LinkedList(); - crustalModelList.add(new CrustalModel(3.3, 0.0)); - crustalModelList.add(new CrustalModel(5.0, 1.0)); - crustalModelList.add(new CrustalModel(5.7, 4.0)); - crustalModelList.add(new CrustalModel(6.7, 15.0)); - crustalModelList.add(new CrustalModel(8.0, 25.0)); - - jtimeFormat = new SimpleDateFormat("yyMMddHH"); - - stationsList = new LinkedList(); - phaseRecordsList = new LinkedList(); - } - - public void locate(EventOld event) throws IOException { - generateHypoInputs(event); - Results hypoResult = runHypo(event); - LOGGER.debug(hypoResult.getPrintOutput()); - for (Hypocenter hypo : hypoResult.getHypocenterOutput()) { - double lon = hypo.getLON1() + (hypo.getLON2() / 60); - double lat = hypo.getLAT1() + (hypo.getLAT2() / 60); - LOGGER.debug("Adding hypo: {}, {} ({} +{}, {} + {})", lon, lat, hypo.getLON1(), - hypo.getLON2(), hypo.getLAT1(), hypo.getLAT2()); - Hypocenters.add(new gov.usgs.volcanoes.swarm.picker.Hypocenter(lat, lon)); - } - } - - private Results runHypo(EventOld event) throws IOException { - - Hypo71 hypoCalculator = new Hypo71(); - - HypoArchiveOutput hy = new HypoArchiveOutput(); - hy.setControlCard(controlCard); - for (PhaseRecord o : phaseRecordsList) { - hy.getPhaseRecords().add(o); - } - - for (Station o : stationsList) { - hy.getStations().add(o); - } - - for (CrustalModel o : crustalModelList) { - hy.getCrustalModel().add(o); - } - - try { - hypoCalculator.calculateHypo71("", null, stationsList, crustalModelList, controlCard, - phaseRecordsList, null); - } catch (ParseException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - Results result = hypoCalculator.getResults(); - return result; - - } - - - /** - * Generates hypo inputs either from an archived file or from objects in memory - */ - private void generateHypoInputs(EventOld event) { - - for (String channel : event.getChannels().keySet()) { - String station = channel.split(" ")[0]; - if (stationsList.contains(channel)) { - continue; - } else { - Metadata metadata = SwarmConfig.getInstance().getMetadata(channel); - if (metadata != null) { - stationsList.add(createStation(metadata)); - } else { - LOGGER.error("Skipping {}, no metadata found.", channel); - } - } - } - - phaseRecordsList.clear(); - Map eChans = event.getChannels(); - for (String chan : eChans.keySet()) { - EventChannel eChan = eChans.get(chan); - PhaseRecord phaseRecord = new PhaseRecord(); - phaseRecord.setMSTA(chan.split(" ")[0]); - - Phase pPhase = eChan.getPhase(Phase.PhaseType.P); - float pSec = 0; - if (pPhase != null) { - String prmk = pPhase.onset + "P" + pPhase.firstMotion + pPhase.weight; - phaseRecord.setPRMK(prmk); - long time = pPhase.time; - phaseRecord.setJTIME(Integer.parseInt(jtimeFormat.format(time))); - int min = (int) ((time / 1000) / 60) % 60; - phaseRecord.setJMIN(min); - - pSec = ((time / 1000) % 60) + ((time % 1000) / 1000f); - phaseRecord.setP(pSec); - } - - Phase sPhase = eChan.getPhase(Phase.PhaseType.S); - if (sPhase != null) { - String srmk = sPhase.onset + "S" + sPhase.firstMotion + sPhase.weight; - phaseRecord.setSRMK(srmk); - long time = sPhase.time; - - phaseRecord.setJTIME(Integer.parseInt(jtimeFormat.format(time))); - - float sSec = ((time / 1000) % 60) + ((time % 1000) / 1000f); - if (sSec < pSec) { - sSec += 60; - } - phaseRecord.setS(sSec); - - long cTime = eChan.getCodaTime(); - if (cTime > 0) { - phaseRecord.setFMP(cTime = pPhase.time); - } - phaseRecord.setAS("1"); - } else { - phaseRecord.setAS(""); - } - - phaseRecord.setSYM('D'); - phaseRecord.setRMK(""); - phaseRecordsList.add(phaseRecord); - - } - - PhaseRecord lastRecordIndicator = new PhaseRecord(); - lastRecordIndicator.setMSTA(""); - phaseRecordsList.add(lastRecordIndicator); - } - - private Station createStation(Metadata metadata) { - Station station = new Station(); - - String stationName = metadata.getChannel().split(" |$")[0]; - if (stationName.length() > 4) { - stationName = stationName.substring(0, 4); - } - station.setNSTA(stationName); - - double lat = metadata.getLatitude(); - char ins = (lat < 0) ? 'S' : 'N'; - lat = Math.abs(lat); - int latDegree = (int) Math.abs(lat); - double latMin = (lat - latDegree) * 60; - - station.setLAT1(latDegree); - station.setLAT2(latMin); - station.setINS(ins); - - double lon = metadata.getLongitude(); - char iew = (lon < 0) ? 'W' : 'E'; - lon = Math.abs(lon); - int lonDegree = (int) lon; - double lonMin = (lon - lonDegree) * 60; - - station.setLON1(lonDegree); - station.setLON2(lonMin); - station.setIEW(iew); - - // TODO: add elevation to winston - station.setIELV(0); - - // TODO: station delay needed? - station.setDly(0); - - // TODO: station correction for FMEG needed? - station.setFMGC(0); - - // TODO: station correction for XMEG needed? - station.setXMGC(0); - - // TODO: System number? - station.setKLAS(8); - - return station; - } - -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/HypoResults.java b/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/HypoResults.java deleted file mode 100644 index ddc048b7..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/picker/hypo71/HypoResults.java +++ /dev/null @@ -1,86 +0,0 @@ -package gov.usgs.volcanoes.swarm.picker.hypo71; - - -import java.io.Serializable; -import java.util.LinkedList; -import java.util.List; - -import gov.usgs.volcanoes.core.hypo71.AdjustmentIteration; -import gov.usgs.volcanoes.core.hypo71.Hypocenter; -import gov.usgs.volcanoes.core.hypo71.Station; -import gov.usgs.volcanoes.core.hypo71.Stats; - -/** - * This class represents the results of an hypo calculation - * - * @author Chirag Patel - */ -@SuppressWarnings("serial") -public class HypoResults implements Serializable{ - private List adjustmentsOutput = new LinkedList(); - private List hypocenterOuput = new LinkedList(); - private List missingStationsList = new LinkedList(); - private List stationsResultList = new LinkedList(); - private List summaryList = new LinkedList(); - private List deletedStationsList = new LinkedList(); - private Stats stats; - private String printOutput = new String(); - private String punchOutput = new String(); - public List getAdjustmentsOutput() { - return adjustmentsOutput; - } - public void setAdjustmentsOutput(List adjustmentsOutput) { - this.adjustmentsOutput = adjustmentsOutput; - } - public List getHypocenterOuput() { - return hypocenterOuput; - } - public void setHypocenterOuput(List hypocenterOuput) { - this.hypocenterOuput = hypocenterOuput; - } - public List getMissingStationsList() { - return missingStationsList; - } - public void setMissingStationsList(List missingStationsList) { - this.missingStationsList = missingStationsList; - } - public List getStationsResultList() { - return stationsResultList; - } - public void setStationsResultList(List stationsResultList) { - this.stationsResultList = stationsResultList; - } - public List getSummaryList() { - return summaryList; - } - public void setSummaryList(List summaryList) { - this.summaryList = summaryList; - } - public List getDeletedStationsList() { - return deletedStationsList; - } - public void setDeletedStationsList(List deletedStationsList) { - this.deletedStationsList = deletedStationsList; - } - public Stats getStats() { - return stats; - } - public void setStats(Stats stats) { - this.stats = stats; - } - public String getPrintOutput() { - return printOutput; - } - public void setPrintOutput(String printOutput) { - this.printOutput = printOutput; - } - public String getPunchOutput() { - return punchOutput; - } - public void setPunchOutput(String punchOutput) { - this.punchOutput = punchOutput; - } - - - -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java b/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java index 63f445d6..b983cd69 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/wave/AbstractWavePanel.java @@ -512,7 +512,7 @@ public boolean processMousePosition(int x, int y) { if (timeSeries) { String utc = J2kSec.format(Time.STANDARD_TIME_FORMAT_MS, time); TimeZone tz = swarmConfig.getTimeZone(channel); - double tzo = tz.getOffset(J2kSec.asEpoch(j2k)) / 1000; + double tzo = tz.getOffset(J2kSec.asEpoch(time)) / 1000; if (tzo != 0) { String tza = tz.getDisplayName(tz.inDaylightTime(J2kSec.asDate(time)), TimeZone.SHORT); status = J2kSec.format(Time.STANDARD_TIME_FORMAT_MS, time + tzo) + " (" + tza + "), " From 39a39170fedc5fb6e811821e233e0c6e5e020dd9 Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Thu, 24 Mar 2016 09:22:56 -0800 Subject: [PATCH 22/67] Correct string compare. --- .../usgs/volcanoes/swarm/map/hypocenters/HypocenterSource.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterSource.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterSource.java index 0be9e5fd..b3d68623 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterSource.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterSource.java @@ -41,7 +41,7 @@ public String getUrl() { public static HypocenterSource fromUrl(String hypocenterUrl) { for (HypocenterSource source : HypocenterSource.values()) { - if (source.url == hypocenterUrl) { + if (source.url.equals(hypocenterUrl)) { return source; } } From 75987ef2d8409dab2ecab19abc6d28a1f3e35c28 Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Thu, 24 Mar 2016 15:47:01 -0800 Subject: [PATCH 23/67] Add sort by selected station in progress... --- .../swarm/data/seedLink/SeedLinkClient.java | 2 +- .../gov/usgs/volcanoes/swarm/event/PickBox.java | 5 +++++ .../usgs/volcanoes/swarm/event/PickToolBar.java | 17 +++++++++++++++++ .../swarm/event/PickToolBarListener.java | 2 ++ .../volcanoes/swarm/event/PickWavePanel.java | 8 ++++++++ .../gov/usgs/volcanoes/swarm/map/MapPanel.java | 4 +++- .../swarm/map/hypocenters/HypocenterLayer.java | 16 ++++++++++++---- .../swarm/map/hypocenters/HypocenterSource.java | 4 ++-- src/main/resources/log4jDebug.properties | 2 +- 9 files changed, 51 insertions(+), 9 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/data/seedLink/SeedLinkClient.java b/src/main/java/gov/usgs/volcanoes/swarm/data/seedLink/SeedLinkClient.java index 6d69e5c8..c891b269 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/data/seedLink/SeedLinkClient.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/data/seedLink/SeedLinkClient.java @@ -561,7 +561,7 @@ protected void runAndWait() { try { - threadSyncObj.wait(); + threadSyncObj.wait(); } catch (InterruptedException ex) { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickBox.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickBox.java index c4103b3f..4dae46e7 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickBox.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickBox.java @@ -551,4 +551,9 @@ public void gotoTime(final String t) { for (final AbstractWavePanel p : selectedSet) gotoTime(p, t); } + + public void sortChannelsByNearest() { + // TODO Auto-generated method stub + + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBar.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBar.java index 5024685b..f25d0e0d 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBar.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBar.java @@ -36,6 +36,7 @@ public class PickToolBar extends JToolBar implements PickBoxListener { private final static Logger LOGGER = LoggerFactory.getLogger(PickToolBar.class); private final JButton sizeButton; + private final JButton sortButton; private final JButton captureButton; private final JButton histButton; @@ -57,6 +58,7 @@ public PickToolBar(PickToolBarListener listener) { setBorder(BorderFactory.createEmptyBorder(1, 0, 0, 0)); sizeButton = createSizeButton(); + sortButton = createSortButton(); captureButton = createCaptureButton(); backButton = createBackButton(); compXButton = createCompXButton(); @@ -74,6 +76,7 @@ public PickToolBar(PickToolBarListener listener) { public void placeButtons() { add(sizeButton); + add(sortButton); addSeparator(); add(captureButton); addSeparator(); @@ -94,6 +97,8 @@ public void selectCountChanged(int count) { forwardButton.setEnabled(enable); backButton.setEnabled(enable); waveViewToolBar.setEnabled(enable); + + sortButton.setEnabled(count == 1); } private JButton createSizeButton() { @@ -115,6 +120,18 @@ private JButton createCaptureButton() { return captureButton; } + + + private JButton createSortButton() { + JButton sortButton = SwarmUtil.createToolBarButton(Icons.geosort, + "Sort waves by nearest to selected wave", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + listener.sortChannelsByNearest(); + } + }); + + return sortButton; + } private JButton createBackButton() { JButton backButton = SwarmUtil.createToolBarButton(Icons.left, diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBarListener.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBarListener.java index c1f9a71d..4f358748 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBarListener.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickToolBarListener.java @@ -23,4 +23,6 @@ public interface PickToolBarListener extends WaveViewToolBarListener { public void shiftTime(final double pct); public void writeImage(); + + public void sortChannelsByNearest(); } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java index 1ca8ee66..1928e479 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java @@ -148,4 +148,12 @@ public int compare(final PickWavePanel e1, final PickWavePanel e2) { }; } + public static Comparator stationDistanceComparator(final PickWavePanel panel) { + return new Comparator() { + public int compare(final PickWavePanel e1, final PickWavePanel e2) { + return Arrival.distanceComparator().compare(e1.arrivals.get(0), e2.arrivals.get(0)); + } + }; + } + } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java index 95d28bd4..8d4eaa66 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java @@ -1116,7 +1116,9 @@ public void mouseMoved(final MouseEvent e) { MapLayer layer = it.next(); handled = layer.mouseMoved(e); } - resetImage(); + if (handled == true) { + repaint(); + } } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java index dba875fa..abba3689 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java @@ -35,6 +35,7 @@ import gov.usgs.plot.render.DataPointRenderer; import gov.usgs.proj.GeoRange; import gov.usgs.proj.Projection; +import gov.usgs.volcanoes.core.CodeTimer; import gov.usgs.volcanoes.core.time.J2kSec; import gov.usgs.volcanoes.core.time.Time; import gov.usgs.volcanoes.swarm.ConfigListener; @@ -79,9 +80,9 @@ public HypocenterLayer() { renderer = new DataPointRenderer(); renderer.antiAlias = true; - renderer.stroke = new BasicStroke(1.2f); + renderer.stroke = new BasicStroke(2f); renderer.filled = true; - renderer.color = Color.LIGHT_GRAY; + renderer.color = Color.BLACK; // r.shape = Geometry.STAR_10; renderer.shape = new Ellipse2D.Float(0f, 0f, 7f, 7f); @@ -164,7 +165,6 @@ public void draw(Graphics2D g2) { for (final Event event : events.values()) { Origin origin = event.getPreferredOrigin(); - LOGGER.debug("Plotting event at {}, {}", origin.getLongitude(), origin.getLatitude()); Point2D.Double originLoc = new Point2D.Double(origin.getLongitude(), origin.getLatitude()); if (!range.contains(originLoc)) { continue; @@ -329,6 +329,7 @@ public boolean mouseMoved(MouseEvent e) { if (projection == null) { return false; } + int widthPx = panel.getGraphWidth(); int heightPx = panel.getGraphHeight(); int insetPx = panel.getInset(); @@ -341,8 +342,15 @@ public boolean mouseMoved(MouseEvent e) { if (origin == null) { continue; } + + Point2D.Double originLoc = new Point2D.Double(origin.getLongitude(), origin.getLatitude()); + if (!range.contains(originLoc)) { + continue; + } + final Rectangle r = new Rectangle(0, 0, 10, 10); + final Point2D.Double xy = projection.forward(new Point2D.Double(origin.getLongitude(), origin.getLatitude())); final double[] ext = range.getProjectedExtents(projection); @@ -362,9 +370,9 @@ public boolean mouseMoved(MouseEvent e) { hoverEvent = null; hoverLocation = e.getPoint(); + handled = true; } } - return handled; } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterSource.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterSource.java index b3d68623..2a293218 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterSource.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterSource.java @@ -16,12 +16,12 @@ public enum HypocenterSource { WEEK_45("1 Week - M4.5+", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/4.5_week.quakeml"), WEEK_25("1 Week - M2.5+", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_week.quakeml"), WEEK_1("1 Week - M1.0+", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/1.0_week.quakeml"), - WEEK_ALL("1 Week - All", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/All_week.quakeml"), + WEEK_ALL("1 Week - All", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.quakeml"), MONTH_SIG("1 Month - Significant", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/significant_month.quakeml"), MONTH_45("1 Month - M4.5+", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/4.5_month.quakeml"), MONTH_25("1 Month - M2.5+", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_month.quakeml"), MONTH_1("1 Month - M1.0+", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/1.0_month.quakeml"), - MONTH_ALL("1 Month - All", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/All_month.quakeml"); + MONTH_ALL("1 Month - All", "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.quakeml"); private String label; private String url; diff --git a/src/main/resources/log4jDebug.properties b/src/main/resources/log4jDebug.properties index 5cce82c3..219f95e5 100644 --- a/src/main/resources/log4jDebug.properties +++ b/src/main/resources/log4jDebug.properties @@ -16,4 +16,4 @@ log4j.appender.R.MaxBackupIndex=9 log4j.appender.R.layout=org.apache.log4j.PatternLayout log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd hh:mm:ss} %5p - %m (%F:%L)%n -log4j.logger.gov.usgs.volcanoes.swarm.map=info \ No newline at end of file +#log4j.logger.gov.usgs.volcanoes.swarm.map=info \ No newline at end of file From e924ea55e0f5d33b3afff5140a0ca69854cda84f Mon Sep 17 00:00:00 2001 From: tparker Date: Thu, 12 May 2016 06:29:20 -0800 Subject: [PATCH 24/67] Begin adding mational map layers to options dialog --- pom.xml | 2 +- .../usgs/volcanoes/swarm/OptionsDialog.java | 386 +++++++++--------- .../volcanoes/swarm/event/EventFrame.java | 9 +- .../volcanoes/swarm/map/NationalMapLayer.java | 32 ++ .../map/hypocenters/HypocenterLayer.java | 62 +-- 5 files changed, 278 insertions(+), 213 deletions(-) create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/map/NationalMapLayer.java diff --git a/pom.xml b/pom.xml index 5870f2d3..627ad76b 100644 --- a/pom.xml +++ b/pom.xml @@ -478,7 +478,7 @@ gov.usgs.volcanoes usgs - 1.2 + 1.3.1 gov.usgs.volcanoes diff --git a/src/main/java/gov/usgs/volcanoes/swarm/OptionsDialog.java b/src/main/java/gov/usgs/volcanoes/swarm/OptionsDialog.java index be636781..6754952b 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/OptionsDialog.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/OptionsDialog.java @@ -1,6 +1,8 @@ package gov.usgs.volcanoes.swarm; import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.Arrays; @@ -19,6 +21,7 @@ import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.FormLayout; +import gov.usgs.volcanoes.swarm.map.NationalMapLayer; import gov.usgs.volcanoes.swarm.options.SwarmOptions; /** @@ -27,188 +30,203 @@ * @version $Id: OptionsDialog.java,v 1.7 2007-05-21 02:38:41 dcervelli Exp $ */ public class OptionsDialog extends SwarmDialog { - private static final long serialVersionUID = 1L; - private static final JFrame applicationFrame = Swarm.getApplicationFrame(); - - private JPanel dialogPanel; - - private JCheckBox durationEnabled; - private JTextField durationA; - private JTextField durationB; - private JCheckBox useLargeCursor; - - private JCheckBox tzInstrument; - private JRadioButton tzLocal; - private JRadioButton tzSpecific; - private JComboBox timeZones; - - private JRadioButton useMapPacks; - private JRadioButton useWMS; - private JTextField wmsServer; - private JTextField wmsLayer; - private JTextField wmsStyles; - private JLabel wmsServerLabel; - private JLabel wmsLayerLabel; - private JLabel wmsStylesLabel; - - public OptionsDialog() { - super(applicationFrame, "Options", true); - createUI(); - setCurrentValues(); - setSizeAndLocation(); - } - - private void createFields() { - durationEnabled = new JCheckBox("Enabled"); - durationA = new JTextField(); - durationB = new JTextField(); - useLargeCursor = new JCheckBox("Large Helicorder Cursor"); - tzInstrument = new JCheckBox("Use instrument time zone if available"); - tzLocal = new JRadioButton("Use local machine time zone:"); - tzSpecific = new JRadioButton("Use specific time zone:"); - ButtonGroup tzGroup = new ButtonGroup(); - tzGroup.add(tzLocal); - tzGroup.add(tzSpecific); - String[] tzs = TimeZone.getAvailableIDs(); - Arrays.sort(tzs); - timeZones = new JComboBox(tzs); - - useMapPacks = new JRadioButton("Use local MapPacks"); - useWMS = new JRadioButton("Use WMS"); - ButtonGroup mapGroup = new ButtonGroup(); - mapGroup.add(useMapPacks); - mapGroup.add(useWMS); - wmsLayer = new JTextField(); - wmsServer = new JTextField(); - wmsStyles = new JTextField(); - } - - protected void createUI() { - super.createUI(); - createFields(); - - FormLayout layout = new FormLayout( - "right:max(30dlu;pref), 3dlu, 40dlu, 3dlu, right:max(40dlu;pref), 3dlu, 40dlu", ""); - - DefaultFormBuilder builder = new DefaultFormBuilder(layout); - builder.setDefaultDialogBorder(); - - builder.appendSeparator("Time Zone"); - - builder.append(tzInstrument, 7); - builder.nextLine(); - TimeZone local = TimeZone.getDefault(); - - builder.append(tzLocal, 7); - builder.append(" "); - builder.append(new JLabel(local.getID()), 5); - builder.nextLine(); - - builder.append(tzSpecific, 7); - builder.nextLine(); - - builder.append(" "); - builder.append(timeZones, 5); - builder.nextLine(); - - builder.appendSeparator("Duration Magnitude"); - builder.append(durationEnabled, 7); - builder.nextLine(); - builder.append("Md=", durationA); - builder.append("* Log(t) +", durationB); - - builder.appendSeparator("Maps"); - builder.append(useMapPacks, 7); - builder.nextLine(); - builder.append(useWMS, 7); - builder.nextLine(); - wmsServerLabel = new JLabel("Server:"); - wmsServerLabel.setLabelFor(wmsServer); - builder.append(wmsServerLabel); - builder.append(wmsServer, 5); - builder.nextLine(); - wmsLayerLabel = new JLabel("Layer:"); - wmsLayerLabel.setLabelFor(wmsLayer); - builder.append(wmsLayerLabel); - builder.append(wmsLayer, 5); - builder.nextLine(); - wmsStylesLabel = new JLabel("Styles:"); - wmsStylesLabel.setLabelFor(wmsStyles); - builder.append(wmsStylesLabel); - builder.append(wmsStyles, 5); - builder.nextLine(); - - useMapPacks.addItemListener(new ItemListener() { - public void itemStateChanged(ItemEvent e) { - doEnables(); - } - }); - - builder.appendSeparator("Other"); - builder.append(useLargeCursor, 7); - builder.nextLine(); - - dialogPanel = builder.getPanel(); - mainPanel.add(dialogPanel, BorderLayout.CENTER); - } - - public void doEnables() { - boolean state = useMapPacks.isSelected(); - wmsServer.setEnabled(!state); - wmsLayer.setEnabled(!state); - wmsStyles.setEnabled(!state); - wmsServerLabel.setEnabled(!state); - wmsLayerLabel.setEnabled(!state); - wmsStylesLabel.setEnabled(!state); - } - - public void setCurrentValues() { - useLargeCursor.setSelected(swarmConfig.useLargeCursor); - durationA.setText(Double.toString(swarmConfig.durationA)); - durationB.setText(Double.toString(swarmConfig.durationB)); - durationEnabled.setSelected(swarmConfig.durationEnabled); - tzInstrument.setSelected(swarmConfig.useInstrumentTimeZone); - if (swarmConfig.useLocalTimeZone) - tzLocal.setSelected(true); - else - tzSpecific.setSelected(true); - timeZones.setSelectedItem(swarmConfig.specificTimeZone.getID()); - - useMapPacks.setSelected(!swarmConfig.useWMS); - useWMS.setSelected(swarmConfig.useWMS); - wmsServer.setText(swarmConfig.wmsServer); - wmsLayer.setText(swarmConfig.wmsLayer); - wmsStyles.setText(swarmConfig.wmsStyles); - doEnables(); - } - - public boolean allowOK() { - String message = null; - try { - message = "The duration magnitude constants must be numbers."; - Double.parseDouble(durationA.getText().trim()); - Double.parseDouble(durationB.getText().trim()); - - return true; - } catch (Exception e) { - JOptionPane.showMessageDialog(this, message, "Options Error", JOptionPane.ERROR_MESSAGE); - } - return false; - } - - public void wasOK() { - swarmConfig.useLargeCursor = useLargeCursor.isSelected(); - swarmConfig.durationEnabled = durationEnabled.isSelected(); - swarmConfig.durationA = Double.parseDouble(durationA.getText().trim()); - swarmConfig.durationB = Double.parseDouble(durationB.getText().trim()); - swarmConfig.useInstrumentTimeZone = tzInstrument.isSelected(); - swarmConfig.useLocalTimeZone = tzLocal.isSelected(); - swarmConfig.specificTimeZone = TimeZone.getTimeZone((String) timeZones.getSelectedItem()); - swarmConfig.useWMS = useWMS.isSelected(); - swarmConfig.wmsServer = wmsServer.getText(); - swarmConfig.wmsLayer = wmsLayer.getText(); - swarmConfig.wmsStyles = wmsStyles.getText(); - - SwarmOptions.optionsChanged(); - } + private static final long serialVersionUID = 1L; + private static final JFrame applicationFrame = Swarm.getApplicationFrame(); + + private JPanel dialogPanel; + + private JCheckBox durationEnabled; + private JTextField durationA; + private JTextField durationB; + private JCheckBox useLargeCursor; + + private JCheckBox tzInstrument; + private JRadioButton tzLocal; + private JRadioButton tzSpecific; + private JComboBox timeZones; + private JComboBox natMapList; + private JRadioButton useMapPacks; + private JRadioButton useWMS; + private JTextField wmsServer; + private JTextField wmsLayer; + private JTextField wmsStyles; + private JLabel wmsServerLabel; + private JLabel wmsLayerLabel; + private JLabel wmsStylesLabel; + + public OptionsDialog() { + super(applicationFrame, "Options", true); + createUI(); + setCurrentValues(); + setSizeAndLocation(); + } + + private void createFields() { + durationEnabled = new JCheckBox("Enabled"); + durationA = new JTextField(); + durationB = new JTextField(); + useLargeCursor = new JCheckBox("Large Helicorder Cursor"); + tzInstrument = new JCheckBox("Use instrument time zone if available"); + tzLocal = new JRadioButton("Use local machine time zone:"); + tzSpecific = new JRadioButton("Use specific time zone:"); + ButtonGroup tzGroup = new ButtonGroup(); + tzGroup.add(tzLocal); + tzGroup.add(tzSpecific); + String[] tzs = TimeZone.getAvailableIDs(); + Arrays.sort(tzs); + timeZones = new JComboBox(tzs); + + useMapPacks = new JRadioButton("Use local MapPacks"); + useWMS = new JRadioButton("Use WMS"); + ButtonGroup mapGroup = new ButtonGroup(); + mapGroup.add(useMapPacks); + mapGroup.add(useWMS); + + + natMapList = new JComboBox(NationalMapLayer.values()); + wmsLayer = new JTextField(); + wmsServer = new JTextField(); + wmsStyles = new JTextField(); + } + + protected void createUI() { + super.createUI(); + createFields(); + + FormLayout layout = new FormLayout( + "right:max(30dlu;pref), 3dlu, 40dlu, 3dlu, right:max(40dlu;pref), 3dlu, 40dlu", ""); + + DefaultFormBuilder builder = new DefaultFormBuilder(layout); + builder.setDefaultDialogBorder(); + + builder.appendSeparator("Time Zone"); + + builder.append(tzInstrument, 7); + builder.nextLine(); + TimeZone local = TimeZone.getDefault(); + + builder.append(tzLocal, 7); + builder.append(" "); + builder.append(new JLabel(local.getID()), 5); + builder.nextLine(); + + builder.append(tzSpecific, 7); + builder.nextLine(); + + builder.append(" "); + builder.append(timeZones, 5); + builder.nextLine(); + + builder.appendSeparator("Duration Magnitude"); + builder.append(durationEnabled, 7); + builder.nextLine(); + builder.append("Md=", durationA); + builder.append("* Log(t) +", durationB); + + builder.appendSeparator("Maps"); + builder.append(useMapPacks, 7); + builder.nextLine(); + builder.append(useWMS, 7); + builder.nextLine(); + builder.append("USGS National Map:"); + builder.append(natMapList, 5); + builder.nextLine(); + wmsServerLabel = new JLabel("Server:"); + wmsServerLabel.setLabelFor(wmsServer); + builder.append(wmsServerLabel); + builder.append(wmsServer, 5); + builder.nextLine(); + wmsLayerLabel = new JLabel("Layer:"); + wmsLayerLabel.setLabelFor(wmsLayer); + builder.append(wmsLayerLabel); + builder.append(wmsLayer, 5); + builder.nextLine(); + wmsStylesLabel = new JLabel("Styles:"); + wmsStylesLabel.setLabelFor(wmsStyles); + builder.append(wmsStylesLabel); + builder.append(wmsStyles, 5); + builder.nextLine(); + + useMapPacks.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + doEnables(); + } + }); + + natMapList.addActionListener (new ActionListener () { + public void actionPerformed(ActionEvent e) { + NationalMapLayer layer = (NationalMapLayer) ((JComboBox) e.getSource()).getSelectedItem(); + wmsServer.setText(layer.server); + wmsLayer.setText(layer.layer); + wmsStyles.setText(layer.sytels); + } + }); + builder.appendSeparator("Other"); + builder.append(useLargeCursor, 7); + builder.nextLine(); + + dialogPanel = builder.getPanel(); + mainPanel.add(dialogPanel, BorderLayout.CENTER); + } + + public void doEnables() { + boolean state = useMapPacks.isSelected(); + wmsServer.setEnabled(!state); + wmsLayer.setEnabled(!state); + wmsStyles.setEnabled(!state); + wmsServerLabel.setEnabled(!state); + wmsLayerLabel.setEnabled(!state); + wmsStylesLabel.setEnabled(!state); + natMapList.setEnabled(!state); + } + + public void setCurrentValues() { + useLargeCursor.setSelected(swarmConfig.useLargeCursor); + durationA.setText(Double.toString(swarmConfig.durationA)); + durationB.setText(Double.toString(swarmConfig.durationB)); + durationEnabled.setSelected(swarmConfig.durationEnabled); + tzInstrument.setSelected(swarmConfig.useInstrumentTimeZone); + if (swarmConfig.useLocalTimeZone) + tzLocal.setSelected(true); + else + tzSpecific.setSelected(true); + timeZones.setSelectedItem(swarmConfig.specificTimeZone.getID()); + + useMapPacks.setSelected(!swarmConfig.useWMS); + useWMS.setSelected(swarmConfig.useWMS); + wmsServer.setText(swarmConfig.wmsServer); + wmsLayer.setText(swarmConfig.wmsLayer); + wmsStyles.setText(swarmConfig.wmsStyles); + doEnables(); + } + + public boolean allowOK() { + String message = null; + try { + message = "The duration magnitude constants must be numbers."; + Double.parseDouble(durationA.getText().trim()); + Double.parseDouble(durationB.getText().trim()); + + return true; + } catch (Exception e) { + JOptionPane.showMessageDialog(this, message, "Options Error", JOptionPane.ERROR_MESSAGE); + } + return false; + } + + public void wasOK() { + swarmConfig.useLargeCursor = useLargeCursor.isSelected(); + swarmConfig.durationEnabled = durationEnabled.isSelected(); + swarmConfig.durationA = Double.parseDouble(durationA.getText().trim()); + swarmConfig.durationB = Double.parseDouble(durationB.getText().trim()); + swarmConfig.useInstrumentTimeZone = tzInstrument.isSelected(); + swarmConfig.useLocalTimeZone = tzLocal.isSelected(); + swarmConfig.specificTimeZone = TimeZone.getTimeZone((String) timeZones.getSelectedItem()); + swarmConfig.useWMS = useWMS.isSelected(); + swarmConfig.wmsServer = wmsServer.getText(); + swarmConfig.wmsLayer = wmsLayer.getText(); + swarmConfig.wmsStyles = wmsStyles.getText(); + + SwarmOptions.optionsChanged(); + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java index 8f90dc10..5c68de9d 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java @@ -24,6 +24,7 @@ import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; +import javax.swing.JViewport; import javax.swing.ScrollPaneConstants; import javax.swing.WindowConstants; import javax.swing.event.InternalFrameAdapter; @@ -79,6 +80,7 @@ public EventFrame(Event event) { mainPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT, ParameterPanel.create(event), createPickPanel()); mainPanel.setOneTouchExpandable(true); + mainPanel.setDividerLocation(0.25); setContentPane(mainPanel); setFrameIcon(Icons.ruler); @@ -90,7 +92,6 @@ public EventFrame(Event event) { this.setVisible(true); this.setFocusable(true); - updateEvent(); } @@ -105,6 +106,10 @@ private JPanel createPickPanel() { scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); scrollPane.getVerticalScrollBar().setUnitIncrement(40); + + JViewport viewPort = scrollPane.getViewport(); + viewPort.setScrollMode(JViewport.BLIT_SCROLL_MODE); + pickPanel.add(scrollPane); JPanel statusPanel = new JPanel(); @@ -232,7 +237,9 @@ public void setVisible(final boolean isVisible) { } public void eventUpdated() { + int loc = mainPanel.getDividerLocation(); mainPanel.setTopComponent(ParameterPanel.create(event)); mainPanel.setBottomComponent(createPickPanel()); + mainPanel.setDividerLocation(loc); } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/NationalMapLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/NationalMapLayer.java new file mode 100644 index 00000000..723c6125 --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/NationalMapLayer.java @@ -0,0 +1,32 @@ +package gov.usgs.volcanoes.swarm.map; + +/** + * + * http://basemap.nationalmap.gov/arc + * + * @author Tom Parker + * + */ +public enum NationalMapLayer { + + TOPO("Topo", "http://basemap.nationalmap.gov/arcgis/services/USGSTopo/MapServer/WMSServer?"), + SHADED_RELIEF("Shaded Relief", "http://basemap.nationalmap.gov/arcgis/services/USGSShadedReliefOnly/MapServer/WMSServer?"), + IMAGERY_ONLY( "Imagery Only", "http://basemap.nationalmap.gov/arcgis/services/USGSImageryOnly/MapServer/WMSServer?"), + IMAGERY_TOPO("Imagery Topo", "http://basemap.nationalmap.gov/arcgis/services/USGSTopo/USGSImageryTopo/WMSServer?"), + ; + + public final String server; + public final String layer = "0"; + public final String sytels = ""; + + private final String title; + + private NationalMapLayer(String title, String server) { + this.title = title; + this.server = server; + } + + public String toString() { + return title; + } +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java index abba3689..9a2ea5bc 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java @@ -209,6 +209,17 @@ private void drawPopup(Graphics2D g2) { Origin origin = hoverEvent.getPreferredOrigin(); GeoRange range = panel.getRange(); Projection projection = panel.getProjection(); + List text = generatePopupText(origin); + + FontMetrics fm = g2.getFontMetrics(); + int popupHeight = 2 * POPUP_PADDING; + int popupWidth = 0; + for (String string : text) { + Rectangle2D bounds = fm.getStringBounds(string, g2); + popupHeight += (int) (Math.ceil(bounds.getHeight()) + 2); + popupWidth = Math.max(popupWidth, (int) (Math.ceil(bounds.getWidth()) + 2 * POPUP_PADDING)); + } + int widthPx = panel.getGraphWidth(); int heightPx = panel.getGraphHeight(); int insetPx = panel.getInset(); @@ -219,18 +230,37 @@ private void drawPopup(Graphics2D g2) { final double dx = (ext[1] - ext[0]); final double dy = (ext[3] - ext[2]); final Point2D.Double res = new Point2D.Double(); + res.x = (((xy.x - ext[0]) / dx) * widthPx + insetPx); + int maxX = widthPx - popupWidth + POPUP_PADDING; + res.x = Math.min(res.x, maxX); + res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); + if (res.y < ( insetPx + popupHeight)) { + res.y += popupHeight; + } g2.translate(res.x, res.y); g2.setStroke(new BasicStroke(1.2f)); - g2.setColor(new Color(0, 0, 0, 64)); + g2.setColor(new Color(0, 0, 0, 128)); + g2.drawRect(0, -(popupHeight - POPUP_PADDING), popupWidth, popupHeight); + g2.fillRect(0, -(popupHeight - POPUP_PADDING), popupWidth, popupHeight); - List text = new ArrayList(3); - // String depth = String.format("Depth: %.2f km", (origin.getDepth() / 1000)); - // text.add(depth); + g2.setColor(Color.WHITE); + int baseY = POPUP_PADDING; + for (String string : text) { + g2.drawString(string, POPUP_PADDING, -baseY); + Rectangle2D bounds = fm.getStringBounds(string, g2); + baseY += (int) (Math.ceil(bounds.getHeight()) + 2); + } + g2.translate(-res.x, -res.y); + + } + private List generatePopupText(Origin origin) { + List text = new ArrayList(3); + Magnitude magElement = hoverEvent.getPerferredMagnitude(); String mag = String.format("%.2f %s at %.2f km depth", magElement.getMag(), magElement.getType(), (origin.getDepth() / 1000)); @@ -242,29 +272,7 @@ private void drawPopup(Graphics2D g2) { String description = hoverEvent.getDescription(); text.add(description); - FontMetrics fm = g2.getFontMetrics(); - int height = 2 * POPUP_PADDING; - int width = 0; - for (String string : text) { - Rectangle2D bounds = fm.getStringBounds(string, g2); - height += (int) (Math.ceil(bounds.getHeight()) + 2); - width = Math.max(width, (int) (Math.ceil(bounds.getWidth()) + 2 * POPUP_PADDING)); - } - - g2.setStroke(new BasicStroke(1.2f)); - g2.setColor(new Color(0, 0, 0, 128)); - g2.drawRect(0, -(height - POPUP_PADDING), width, height); - g2.fillRect(0, -(height - POPUP_PADDING), width, height); - - g2.setColor(Color.WHITE); - int baseY = POPUP_PADDING; - for (String string : text) { - g2.drawString(string, POPUP_PADDING, -baseY); - Rectangle2D bounds = fm.getStringBounds(string, g2); - baseY += (int) (Math.ceil(bounds.getHeight()) + 2); - } - g2.translate(-res.x, -res.y); - + return text; } public boolean mouseClicked(final MouseEvent e) { From c1cb9cd24965fc3bdb05d8a434f0db2048f73eac Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Tue, 17 May 2016 11:57:20 -0800 Subject: [PATCH 25/67] Remove debugging output. --- src/main/java/gov/usgs/volcanoes/swarm/map/MapLinePreview.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapLinePreview.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapLinePreview.java index 7d95a655..c97c8686 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapLinePreview.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapLinePreview.java @@ -88,7 +88,6 @@ public void changedUpdate(DocumentEvent e) { } private void updateLineWidth(String w) { - System.out.println("-- " + w); try { lineWidth = Integer.parseInt(w); widthBox.setBackground(Color.white); From 3ecf515848899fc797fc7a2c2dfc20b1ff347123 Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Tue, 17 May 2016 11:58:42 -0800 Subject: [PATCH 26/67] Refactor SwarmDialog to SwarmModalDialog. Create non-modal super class if it's ever needed. --- .../java/gov/usgs/volcanoes/swarm/FileTypeDialog.java | 4 ++-- src/main/java/gov/usgs/volcanoes/swarm/OptionsDialog.java | 4 ++-- src/main/java/gov/usgs/volcanoes/swarm/SwarmMenu.java | 4 ++-- .../swarm/{SwarmDialog.java => SwarmModalDialog.java} | 6 +++--- .../volcanoes/swarm/chooser/EditDataSourceDialog.java | 6 +++--- .../swarm/heli/HelicorderViewerSettingsDialog.java | 6 +++--- .../java/gov/usgs/volcanoes/swarm/map/MapLineDialog.java | 8 ++++---- .../gov/usgs/volcanoes/swarm/map/MapSettingsDialog.java | 8 ++++---- .../usgs/volcanoes/swarm/rsam/RsamViewSettingsDialog.java | 6 +++--- .../volcanoes/swarm/wave/MultiMonitorSettingsDialog.java | 6 +++--- .../usgs/volcanoes/swarm/wave/WaveViewSettingsDialog.java | 6 +++--- 11 files changed, 32 insertions(+), 32 deletions(-) rename src/main/java/gov/usgs/volcanoes/swarm/{SwarmDialog.java => SwarmModalDialog.java} (95%) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/FileTypeDialog.java b/src/main/java/gov/usgs/volcanoes/swarm/FileTypeDialog.java index 62e28209..c244b4b2 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/FileTypeDialog.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/FileTypeDialog.java @@ -20,7 +20,7 @@ /* * @author Tom Parker */ -public class FileTypeDialog extends SwarmDialog { +public class FileTypeDialog extends SwarmModalDialog { private static final long serialVersionUID = 1L; private static final JFrame applicationFrame = Swarm.getApplicationFrame(); private JLabel filename; @@ -30,7 +30,7 @@ public class FileTypeDialog extends SwarmDialog { private boolean opened = false; public FileTypeDialog() { - super(applicationFrame, "Select File Type", true); + super(applicationFrame, "Select File Type"); setSizeAndLocation(); } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/OptionsDialog.java b/src/main/java/gov/usgs/volcanoes/swarm/OptionsDialog.java index 6754952b..a09e975c 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/OptionsDialog.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/OptionsDialog.java @@ -29,7 +29,7 @@ * @author Dan Cervelli * @version $Id: OptionsDialog.java,v 1.7 2007-05-21 02:38:41 dcervelli Exp $ */ -public class OptionsDialog extends SwarmDialog { +public class OptionsDialog extends SwarmModalDialog { private static final long serialVersionUID = 1L; private static final JFrame applicationFrame = Swarm.getApplicationFrame(); @@ -55,7 +55,7 @@ public class OptionsDialog extends SwarmDialog { private JLabel wmsStylesLabel; public OptionsDialog() { - super(applicationFrame, "Options", true); + super(applicationFrame, "Options"); createUI(); setCurrentValues(); setSizeAndLocation(); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/SwarmMenu.java b/src/main/java/gov/usgs/volcanoes/swarm/SwarmMenu.java index 48b7f92e..74bcfd64 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/SwarmMenu.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/SwarmMenu.java @@ -398,13 +398,13 @@ public void actionPerformed(ActionEvent e) { } } - private class RemoveLayoutDialog extends SwarmDialog { + private class RemoveLayoutDialog extends SwarmModalDialog { private static final long serialVersionUID = 1L; private JList layoutList; private DefaultListModel model; protected RemoveLayoutDialog() { - super(Swarm.getApplicationFrame(), "Remove Layouts", true); + super(Swarm.getApplicationFrame(), "Remove Layouts"); setSizeAndLocation(); } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/SwarmDialog.java b/src/main/java/gov/usgs/volcanoes/swarm/SwarmModalDialog.java similarity index 95% rename from src/main/java/gov/usgs/volcanoes/swarm/SwarmDialog.java rename to src/main/java/gov/usgs/volcanoes/swarm/SwarmModalDialog.java index e7bfb860..63eb387b 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/SwarmDialog.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/SwarmModalDialog.java @@ -24,7 +24,7 @@ /** * @author Dan Cervelli */ -public class SwarmDialog extends JDialog { +public class SwarmModalDialog extends JDialog { private static final long serialVersionUID = -1; protected JButton okButton; @@ -40,8 +40,8 @@ public class SwarmDialog extends JDialog { protected static SwarmConfig swarmConfig; protected static final JFrame applicationFrame = Swarm.getApplicationFrame(); - protected SwarmDialog(JFrame parent, String title, boolean modal) { - super(parent, title, modal); + protected SwarmModalDialog(JFrame parent, String title) { + super(parent, title, true); swarmConfig = SwarmConfig.getInstance(); setResizable(false); this.parent = parent; diff --git a/src/main/java/gov/usgs/volcanoes/swarm/chooser/EditDataSourceDialog.java b/src/main/java/gov/usgs/volcanoes/swarm/chooser/EditDataSourceDialog.java index 98fb9ccf..7d76908f 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/chooser/EditDataSourceDialog.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/chooser/EditDataSourceDialog.java @@ -17,13 +17,13 @@ import gov.usgs.volcanoes.swarm.Swarm; import gov.usgs.volcanoes.swarm.SwarmConfig; -import gov.usgs.volcanoes.swarm.SwarmDialog; +import gov.usgs.volcanoes.swarm.SwarmModalDialog; /** * * @author Dan Cervelli */ -public class EditDataSourceDialog extends SwarmDialog { +public class EditDataSourceDialog extends SwarmModalDialog { private static final long serialVersionUID = 1L; private static final JFrame applicationFrame = Swarm.getApplicationFrame(); @@ -39,7 +39,7 @@ public class EditDataSourceDialog extends SwarmDialog { private String result; public EditDataSourceDialog(String s) { - super(applicationFrame, "", true); + super(applicationFrame, ""); createPanels(); source = s; if (source == null) { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewerSettingsDialog.java b/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewerSettingsDialog.java index e9c3c8ad..ef3231b5 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewerSettingsDialog.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewerSettingsDialog.java @@ -29,7 +29,7 @@ import gov.usgs.volcanoes.core.time.J2kSec; import gov.usgs.volcanoes.swarm.Icons; import gov.usgs.volcanoes.swarm.Swarm; -import gov.usgs.volcanoes.swarm.SwarmDialog; +import gov.usgs.volcanoes.swarm.SwarmModalDialog; import gov.usgs.volcanoes.swarm.SwingWorker; import gov.usgs.volcanoes.swarm.wave.WaveViewSettings; import gov.usgs.volcanoes.swarm.wave.WaveViewSettingsDialog; @@ -38,7 +38,7 @@ * * @author Dan Cervelli */ -public class HelicorderViewerSettingsDialog extends SwarmDialog { +public class HelicorderViewerSettingsDialog extends SwarmModalDialog { public static final long serialVersionUID = -1; private HelicorderViewerSettings settings; @@ -68,7 +68,7 @@ public class HelicorderViewerSettingsDialog extends SwarmDialog { private HelicorderViewerSettingsDialog() { // super(Swarm.getApplication(), "Helicorder View Settings", true, // WIDTH, HEIGHT); - super(Swarm.getApplicationFrame(), "Helicorder View Settings", true); + super(Swarm.getApplicationFrame(), "Helicorder View Settings"); utcDateFormat = new SimpleDateFormat("yyyyMMddHHmm"); utcDateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapLineDialog.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapLineDialog.java index 5e0815f1..53a7b3d1 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapLineDialog.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapLineDialog.java @@ -2,12 +2,12 @@ import javax.swing.JFrame; -import gov.usgs.volcanoes.swarm.SwarmDialog; +import gov.usgs.volcanoes.swarm.SwarmModalDialog; -public class MapLineDialog extends SwarmDialog { +public class MapLineDialog extends SwarmModalDialog { - protected MapLineDialog(JFrame parent, String title, boolean modal) { - super(parent, title, modal); + protected MapLineDialog(JFrame parent, String title) { + super(parent, title); } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapSettingsDialog.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapSettingsDialog.java index 5a0d9085..f67778ac 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapSettingsDialog.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapSettingsDialog.java @@ -21,7 +21,8 @@ import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.FormLayout; -import gov.usgs.volcanoes.swarm.SwarmDialog; +import gov.usgs.volcanoes.swarm.Icons; +import gov.usgs.volcanoes.swarm.SwarmModalDialog; import gov.usgs.volcanoes.swarm.map.MapPanel.LabelSetting; import gov.usgs.volcanoes.swarm.map.hypocenters.HypocenterSource; @@ -29,7 +30,7 @@ * * @author Dan Cervelli */ -public class MapSettingsDialog extends SwarmDialog { +public class MapSettingsDialog extends SwarmModalDialog { public static final long serialVersionUID = -1; private static final Logger LOGGER = LoggerFactory.getLogger(MapSettingsDialog.class); @@ -53,7 +54,7 @@ public class MapSettingsDialog extends SwarmDialog { private MapFrame mapFrame; public MapSettingsDialog(MapFrame mapFrame) { - super(applicationFrame, "Map Settings", true); + super(applicationFrame, "Map Settings"); this.mapFrame = mapFrame; createUI(); setToCurrent(); @@ -75,7 +76,6 @@ private void createFields() { labelGroup.add(noLabels); mapLine = new JButton(); hypocenterSource = new JComboBox(HypocenterSource.values()); - lineChooser = new JColorChooser(); lineChooser.setPreviewPanel(new MapLinePreview()); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/rsam/RsamViewSettingsDialog.java b/src/main/java/gov/usgs/volcanoes/swarm/rsam/RsamViewSettingsDialog.java index cd9b8099..fd38fed1 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/rsam/RsamViewSettingsDialog.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/rsam/RsamViewSettingsDialog.java @@ -2,7 +2,7 @@ import gov.usgs.math.BinSize; import gov.usgs.volcanoes.swarm.Icons; -import gov.usgs.volcanoes.swarm.SwarmDialog; +import gov.usgs.volcanoes.swarm.SwarmModalDialog; import gov.usgs.volcanoes.swarm.rsam.RsamViewSettings.ViewType; import java.awt.BorderLayout; @@ -29,7 +29,7 @@ * * @author Tom Parker */ -public class RsamViewSettingsDialog extends SwarmDialog { +public class RsamViewSettingsDialog extends SwarmModalDialog { private static final long serialVersionUID = 1L; private JPanel dialogPanel; @@ -60,7 +60,7 @@ public class RsamViewSettingsDialog extends SwarmDialog { private JTextField scaleMin; private RsamViewSettingsDialog() { - super(applicationFrame, "RSAM Settings", true); + super(applicationFrame, "RSAM Settings"); this.setIconImage(Icons.rsam_values.getImage()); createUI(); setSizeAndLocation(); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/wave/MultiMonitorSettingsDialog.java b/src/main/java/gov/usgs/volcanoes/swarm/wave/MultiMonitorSettingsDialog.java index d47cb67c..7c64465f 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/wave/MultiMonitorSettingsDialog.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/wave/MultiMonitorSettingsDialog.java @@ -10,7 +10,7 @@ import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.FormLayout; -import gov.usgs.volcanoes.swarm.SwarmDialog; +import gov.usgs.volcanoes.swarm.SwarmModalDialog; /** * A dialog for Monitor Mode Settings. @@ -18,7 +18,7 @@ * * @author Dan Cervelli */ -public class MultiMonitorSettingsDialog extends SwarmDialog { +public class MultiMonitorSettingsDialog extends SwarmModalDialog { public static final long serialVersionUID = -1; private MultiMonitor monitor; @@ -32,7 +32,7 @@ public class MultiMonitorSettingsDialog extends SwarmDialog { private static MultiMonitorSettingsDialog dialog; private MultiMonitorSettingsDialog() { - super(applicationFrame, "Monitor Settings", true); + super(applicationFrame, "Monitor Settings"); createUI(); // setToCurrent(); // setCurrentValues(); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewSettingsDialog.java b/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewSettingsDialog.java index 54c3cc4f..e40df672 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewSettingsDialog.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveViewSettingsDialog.java @@ -1,7 +1,7 @@ package gov.usgs.volcanoes.swarm.wave; import gov.usgs.volcanoes.core.math.Butterworth.FilterType; -import gov.usgs.volcanoes.swarm.SwarmDialog; +import gov.usgs.volcanoes.swarm.SwarmModalDialog; import gov.usgs.volcanoes.swarm.wave.WaveViewSettings.ViewType; import java.awt.BorderLayout; @@ -24,7 +24,7 @@ * * @author Dan Cervelli */ -public class WaveViewSettingsDialog extends SwarmDialog { +public class WaveViewSettingsDialog extends SwarmModalDialog { private static final long serialVersionUID = 1L; private JPanel dialogPanel; @@ -72,7 +72,7 @@ public class WaveViewSettingsDialog extends SwarmDialog { private int settingsCount; private WaveViewSettingsDialog() { - super(applicationFrame, "Wave Settings", true); + super(applicationFrame, "Wave Settings"); createUI(); setSizeAndLocation(); } From 2f8e013a658bbe8651a00425f26df9779a072131 Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Wed, 18 May 2016 11:51:23 -0800 Subject: [PATCH 27/67] Add optional help button to SwarmModalDialogs --- pom.xml | 5 ++ .../gov/usgs/volcanoes/swarm/HelpDialog.java | 40 +++++++++++++++ .../volcanoes/swarm/SwarmModalDialog.java | 43 +++++++++++++--- .../swarm/data/fdsnWs/WebServicesClient.java | 1 - .../swarm/data/fdsnWs/WebServicesSource.java | 51 ++++++++++--------- .../swarm/map/MapSettingsDialog.java | 2 +- src/main/resources/help/mapSettings.md | 18 +++++++ 7 files changed, 127 insertions(+), 33 deletions(-) create mode 100644 src/main/java/gov/usgs/volcanoes/swarm/HelpDialog.java create mode 100644 src/main/resources/help/mapSettings.md diff --git a/pom.xml b/pom.xml index 627ad76b..cf55295f 100644 --- a/pom.xml +++ b/pom.xml @@ -506,5 +506,10 @@ + + org.pegdown + pegdown + 1.6.0 + diff --git a/src/main/java/gov/usgs/volcanoes/swarm/HelpDialog.java b/src/main/java/gov/usgs/volcanoes/swarm/HelpDialog.java new file mode 100644 index 00000000..5bfecabd --- /dev/null +++ b/src/main/java/gov/usgs/volcanoes/swarm/HelpDialog.java @@ -0,0 +1,40 @@ +package gov.usgs.volcanoes.swarm; + +import org.pegdown.PegDownProcessor; + +import java.awt.Component; +import java.util.Scanner; + +import javax.swing.BoxLayout; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextPane; + +public final class HelpDialog { + + private static final PegDownProcessor pegdownProcessor = new PegDownProcessor(); + + public static void displayHelp(Component parent, String helpFile) { + final JPanel helpPanel = new JPanel(); + helpPanel.setLayout(new BoxLayout(helpPanel, BoxLayout.PAGE_AXIS)); + JTextPane htmlPane = new JTextPane(); + + Scanner scanner = new Scanner(HelpDialog.class.getResourceAsStream("/help/" + helpFile), "UTF-8"); + String text = scanner.useDelimiter("\\A").next(); + scanner.close(); + + htmlPane.setContentType("text/html"); + htmlPane.setText(pegdownProcessor.markdownToHtml(text)); + JScrollPane paneScrollPane = new JScrollPane(htmlPane); + + helpPanel.add(paneScrollPane); + + + JOptionPane.showMessageDialog(parent, + helpPanel, + "A plain message", + JOptionPane.PLAIN_MESSAGE); + + } +} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/SwarmModalDialog.java b/src/main/java/gov/usgs/volcanoes/swarm/SwarmModalDialog.java index 63eb387b..6cad8952 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/SwarmModalDialog.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/SwarmModalDialog.java @@ -1,6 +1,8 @@ package gov.usgs.volcanoes.swarm; +import com.jgoodies.forms.builder.ButtonBarBuilder; + import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Point; @@ -10,17 +12,22 @@ import java.awt.event.WindowEvent; import javax.swing.BorderFactory; +import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; +import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JRootPane; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextPane; import javax.swing.SwingUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.StyledDocument; import gov.usgs.volcanoes.core.util.UiUtils; -import com.jgoodies.forms.builder.ButtonBarBuilder; - /** * @author Dan Cervelli */ @@ -29,6 +36,8 @@ public class SwarmModalDialog extends JDialog { protected JButton okButton; protected JButton cancelButton; + protected JButton helpButton; + protected JPanel buttonPanel; protected JPanel mainPanel; @@ -39,14 +48,20 @@ public class SwarmModalDialog extends JDialog { protected static SwarmConfig swarmConfig; protected static final JFrame applicationFrame = Swarm.getApplicationFrame(); + protected String helpFile; - protected SwarmModalDialog(JFrame parent, String title) { + protected SwarmModalDialog(JFrame parent, String title, String helpFile) { super(parent, title, true); + this.helpFile = helpFile; swarmConfig = SwarmConfig.getInstance(); setResizable(false); this.parent = parent; createUI(); } + + protected SwarmModalDialog(JFrame parent, String title) { + this(parent, title, null); + } protected void setSizeAndLocation() { Dimension d = mainPanel.getPreferredSize(); @@ -70,6 +85,7 @@ public void actionPerformed(ActionEvent e) { } } }); + cancelButton = new JButton("Cancel"); cancelButton.setMnemonic('C'); cancelButton.addActionListener(new ActionListener() { @@ -95,17 +111,30 @@ public void windowClosing(WindowEvent e) { } }); - // buttonPanel = ButtonBarFactory.buildOKCancelBar(okButton, - // cancelButton); ButtonBarBuilder builder = new ButtonBarBuilder(); builder.addGlue(); - builder.addButton(okButton, cancelButton); + + if (helpFile != null) { + helpButton = new JButton("Help"); + helpButton.setMnemonic('H'); + + helpButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + HelpDialog.displayHelp(parent, helpFile); + } + }); + builder.addButton(okButton, cancelButton, helpButton); + } else { + builder.addButton(okButton, cancelButton); + } buttonPanel = builder.getPanel(); buttonPanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 10)); mainPanel.add(buttonPanel, BorderLayout.SOUTH); this.setContentPane(mainPanel); } - + + + protected boolean allowOK() { return true; } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesClient.java b/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesClient.java index 7bf92dc6..59b8a568 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesClient.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesClient.java @@ -12,7 +12,6 @@ import gov.usgs.plot.data.Wave; import gov.usgs.volcanoes.swarm.ChannelInfo; import gov.usgs.volcanoes.swarm.SwarmConfig; -import gov.usgs.volcanoes.swarm.data.DataSelectReader; import gov.usgs.volcanoes.swarm.data.SeismicDataSource; public class WebServicesClient extends AbstractDataRecordClient { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesSource.java b/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesSource.java index 6083a660..eae0a0f3 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesSource.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesSource.java @@ -32,28 +32,30 @@ public class WebServicesSource extends SeismicDataSource { public static final String PARAM_FMT_TEXT = "%s|%s|%s|%s|%d|%d|%s|%s"; /** instance counter */ private static int counter = 0; - /** The channel. */ - private String chan; - /** Web Services Client. */ - private WebServicesClient client; /** instance count */ private final int count = ++counter; + /** Web Services Client. */ + private WebServicesClient client; + /** The colon separated parameters. */ + private String params; /** The gulp delay. */ private int gulpDelay; /** The gulp size. */ private int gulpSize; - /** The location. */ - private String loc; - /** The network. */ - private String net; - /** The colon separated parameters. */ - private String params; - /** The station. */ - private String sta; - /** Web Services dataselect URL. */ - private String wsDataSelectUrl; - /** Web Services station URL. */ - private String wsStationUrl; + // /** The channel. */ + // private String chan; + // /** The location. */ + // private String loc; + // /** The network. */ + // private String net; + // /** The station. */ + // private String sta; + // /** Web Services dataselect URL. */ + // private String wsDataSelectUrl; + // /** Web Services station URL. */ + // private String wsStationUrl; + + private String configString; static { typeString = DataSourceType.getShortName(WebServicesSource.class); @@ -65,14 +67,16 @@ public void parse(String params) { this.params = params; String[] ss = params.split(PARAM_SPLIT_TEXT); int ssIndex = 0; - net = ss[ssIndex++]; - sta = ss[ssIndex++]; - loc = ss[ssIndex++]; - chan = ss[ssIndex++]; + String net = ss[ssIndex++]; + String sta = ss[ssIndex++]; + String loc = ss[ssIndex++]; + String chan = ss[ssIndex++]; gulpSize = Integer.parseInt(ss[ssIndex++]); gulpDelay = Integer.parseInt(ss[ssIndex++]); - wsDataSelectUrl = ss[ssIndex++]; - wsStationUrl = ss[ssIndex++]; + String wsDataSelectUrl = ss[ssIndex++]; + String wsStationUrl = ss[ssIndex++]; + configString = String.format("%s;%s:" + PARAM_FMT_TEXT, name, typeString, net, sta, loc, chan, + gulpSize, gulpDelay, wsDataSelectUrl, wsStationUrl); client = new WebServicesClient(this, net, sta, loc, chan, wsDataSelectUrl, wsStationUrl); LOGGER.debug("web service started {}", count); } @@ -209,7 +213,6 @@ public synchronized void notifyDataNotNeeded(String station, double t1, double t * @return the configuration string. */ public String toConfigString() { - return String.format("%s;%s:" + PARAM_FMT_TEXT, name, typeString, net, sta, loc, chan, gulpSize, - gulpDelay, wsDataSelectUrl, wsStationUrl); + return configString; } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapSettingsDialog.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapSettingsDialog.java index f67778ac..0a517d51 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapSettingsDialog.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapSettingsDialog.java @@ -54,7 +54,7 @@ public class MapSettingsDialog extends SwarmModalDialog { private MapFrame mapFrame; public MapSettingsDialog(MapFrame mapFrame) { - super(applicationFrame, "Map Settings"); + super(applicationFrame, "Map Settings", "mapSettings.md"); this.mapFrame = mapFrame; createUI(); setToCurrent(); diff --git a/src/main/resources/help/mapSettings.md b/src/main/resources/help/mapSettings.md new file mode 100644 index 00000000..354952d7 --- /dev/null +++ b/src/main/resources/help/mapSettings.md @@ -0,0 +1,18 @@ +# Map Settings # + +## Location ## + +Specifies the center of the map and the scale in pixels per meter. + + +## Options ## + +### Line ### +Specifies the color and width of the line connecting an inset map pannel with its marker. + +### Refresh Interval ### + +### Channel Labels ### + +### NEIC Event Summary ### +Swarm can plot real-time events using data from the [NEIC real-time feed](http://earthquake.usgs.gov/earthquakes/feed/). Events are updated every five minutes. \ No newline at end of file From 420f2d1f63ab4bf22be9f522cdd54e6732b66ea1 Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Thu, 19 May 2016 08:51:43 -0800 Subject: [PATCH 28/67] Revert kiosk key to F11 --- src/main/java/gov/usgs/volcanoes/swarm/Swarm.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java b/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java index 51a3832d..b955da3e 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java @@ -167,8 +167,8 @@ public void actionPerformed(final ActionEvent e) { } }); - m.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F12, 0), "fullScreenToggle"); - m.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F12, InputEvent.CTRL_DOWN_MASK), + m.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F11, 0), "fullScreenToggle"); + m.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F11, InputEvent.CTRL_DOWN_MASK), "fullScreenToggle"); m.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SLASH, InputEvent.CTRL_DOWN_MASK), "fullScreenToggle"); From 2b8a08ad79c7e11a9461931f469c82f79b439b02 Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Thu, 19 May 2016 10:20:09 -0800 Subject: [PATCH 29/67] Minor web services tweaks to support event viewer. --- .../volcanoes/swarm/data/{ => fdsnWs}/DataSelectReader.java | 3 +-- IRIS_networks.txt => src/main/resources/IRIS_networks.txt | 0 2 files changed, 1 insertion(+), 2 deletions(-) rename src/main/java/gov/usgs/volcanoes/swarm/data/{ => fdsnWs}/DataSelectReader.java (98%) rename IRIS_networks.txt => src/main/resources/IRIS_networks.txt (100%) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/data/DataSelectReader.java b/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/DataSelectReader.java similarity index 98% rename from src/main/java/gov/usgs/volcanoes/swarm/data/DataSelectReader.java rename to src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/DataSelectReader.java index a84e7196..4dc32006 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/data/DataSelectReader.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/DataSelectReader.java @@ -1,4 +1,4 @@ -package gov.usgs.volcanoes.swarm.data; +package gov.usgs.volcanoes.swarm.data.fdsnWs; import edu.sc.seis.seisFile.SeisFileException; import edu.sc.seis.seisFile.StringMSeedQueryReader; @@ -23,7 +23,6 @@ import gov.usgs.volcanoes.swarm.Swarm; import gov.usgs.volcanoes.swarm.Version; -import gov.usgs.volcanoes.swarm.data.fdsnWs.WebServiceUtils; /** * The data select reader reads data from the web services. This class a based diff --git a/IRIS_networks.txt b/src/main/resources/IRIS_networks.txt similarity index 100% rename from IRIS_networks.txt rename to src/main/resources/IRIS_networks.txt From 0e67a295c02dae7cd01920b4429e62a97cbb6251 Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Thu, 19 May 2016 10:20:45 -0800 Subject: [PATCH 30/67] Add map settings help dialog. --- src/main/java/gov/usgs/volcanoes/swarm/HelpDialog.java | 7 ++++--- src/main/resources/help/mapSettings.md | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/HelpDialog.java b/src/main/java/gov/usgs/volcanoes/swarm/HelpDialog.java index 5bfecabd..82d701d4 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/HelpDialog.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/HelpDialog.java @@ -3,6 +3,7 @@ import org.pegdown.PegDownProcessor; import java.awt.Component; +import java.awt.Dimension; import java.util.Scanner; import javax.swing.BoxLayout; @@ -26,11 +27,11 @@ public static void displayHelp(Component parent, String helpFile) { htmlPane.setContentType("text/html"); htmlPane.setText(pegdownProcessor.markdownToHtml(text)); - JScrollPane paneScrollPane = new JScrollPane(htmlPane); + htmlPane.setPreferredSize(new Dimension(500, 600)); + JScrollPane paneScrollPane = new JScrollPane(htmlPane); helpPanel.add(paneScrollPane); - - + JOptionPane.showMessageDialog(parent, helpPanel, "A plain message", diff --git a/src/main/resources/help/mapSettings.md b/src/main/resources/help/mapSettings.md index 354952d7..af60b9d7 100644 --- a/src/main/resources/help/mapSettings.md +++ b/src/main/resources/help/mapSettings.md @@ -15,4 +15,6 @@ Specifies the color and width of the line connecting an inset map pannel with it ### Channel Labels ### ### NEIC Event Summary ### -Swarm can plot real-time events using data from the [NEIC real-time feed](http://earthquake.usgs.gov/earthquakes/feed/). Events are updated every five minutes. \ No newline at end of file +Swarm can plot real-time events using data from the [NEIC real-time feed](http://earthquake.usgs.gov/earthquakes/feed/). Events are updated every five minutes. + +Event markers are colored according to the event age. Events shown in red have occurred within the past hour; events shown in orange have occurred within the past day; events shown in yellow have occurred within the past week. \ No newline at end of file From b95e4a61ea98a2dab94b88fd705887104dc15c92 Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Thu, 19 May 2016 10:22:15 -0800 Subject: [PATCH 31/67] Remove derived pom from source control. --- dependency-reduced-pom.xml | 405 ------------------------------------- 1 file changed, 405 deletions(-) delete mode 100644 dependency-reduced-pom.xml diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml deleted file mode 100644 index 09da54df..00000000 --- a/dependency-reduced-pom.xml +++ /dev/null @@ -1,405 +0,0 @@ - - - 4.0.0 - gov.usgs.volcanoes - swarm - Swarm - 2.6.0-SNAPSHOT - Swarm is a Java application designed to display and analyze seismic waveforms in real-time. Swarm can connect to and read from a variety of different static and dynamics data sources, including Earthworm waveservers, IRIS DMCs, SEED and SAC files, and simple ASCII. Swarm has both time- and frequency-domain analysis tools, along with a simple but powerful mapping platfrom. A full-screen kiosk mode can act as a low-cost, low-maintenance replacement for paper drum recorders. Swarm was written by and for scientists and provides fine control over many different program settings and variables. - http://volcanoes.usgs.gov/software/swarm - - GitHub - https://github.com/usgs/swarm/issues - - - Travis - https://travis-ci.org/usgs/swarm/ - - - - tparker - Tom Parker - tparker@usgs.gov - U.S. Geological Survey, Alaska Volcano Observatory - - true - - - - cervelli - Peter Cervelli - pcervelli@usgs.gov - U.S. Geological Survey, Volcano Science Center - - true - - - - lantolik - Loren Antolik - lantolik@usgs.gov - U.S. Geological Survey, Hawaiian Volcano Observatory - - true - - - - dcervelli - Dan Cervelli - - false - - - - - - Kevin Frechette (ISTI) - - - Anthony Lomax - - - Dave Ketchum - - - Chirag Patel - - - Ivan Henson - - - - - CC0 1.0 Universal - http://creativecommons.org/publicdomain/zero/1.0 /> - repo - - - - scm:git:git@github.com:usgs/swarm.git - scm:git:git@github.com:usgs/swarm.git - git@github.com:usgs/swarm.git - - - - - org.apache.maven.wagon - wagon-ssh-external - 1.0-beta-6 - - - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - com.google.code.maven-replacer-plugin - maven-replacer-plugin - 1.4.0 - - replace - - - - - - source: - - - - - - - - - - maven-shade-plugin - 2.4.1 - - - package - - shade - - - true - - - org.apache:log4j - - org/apache/log4j/** - - - - org.freemarker:freemarker - - freemarker/** - - - - com.jgoodies:jgoodies-common - - ** - - - - com.jgoodies:jgoodies-forms - - ** - - - - com.jgoodies:jgoodies-looks - - ** - - - - opensymphony:oscache - - ** - - - - - - gov.usgs.volcanoes:usgs - gov.usgs.volcanoes:volcano-core - gov.usgs.volcanoes:winston - gov.usgs.volcanoes:swarm - org.freemarker:freemarker - com.jgoodies:* - com.martiansoftware:jsap - net.sourceforge.jtransforms:jtransforms - org.slf4j:* - org.apache:log4j - net.alomax:* - edu.sc.seis:* - colt:colt - edu.iris:JavaSeedLite - - - - - - - - maven-jar-plugin - 2.6 - - - - true - gov.usgs.volcanoes.swarm.Swarm - - - - - - com.google.code.maven-replacer-plugin - maven-replacer-plugin - 1.4.0 - - - process-sources - - replace - - - - - ${version.template.file} - ${version.file} - - - @buildnumber@ - ${svn.revision} - - - @buildtime@ - ${maven.build.timestamp} - - - @pomversion@ - ${project.version} - - - - - - org.codehaus.mojo - cobertura-maven-plugin - 2.7 - - xml - 256m - true - - - - org.eluder.coveralls - coveralls-maven-plugin - 3.2.0 - - ${env.coveralls_repo_token} - - - - maven-site-plugin - 3.4 - - - org.apache.maven.wagon - wagon-scm - 2.9 - - - org.apache.maven.scm - maven-scm-manager-plexus - 1.9.4 - - - org.apache.maven.scm - maven-scm-provider-gitexe - 1.9.4 - - - org.apache.maven.scm - maven-scm-api - 1.9.4 - - - - - maven-assembly-plugin - 2.6 - - - make-assembly - package - - single - - - - - - src/assembly/swarmBin.xml - - - - - - - - - volcanoes - http://volcanoes.usgs.gov/software/maven2/ - - - - - edu.iris - seedCodec - 1.0.10 - compile - - - io.netty - netty-all - 4.0.31.Final - compile - - - opensymphony - oscache - 2.4.1 - compile - - - jms - javax.jms - - - - - - - - maven-pmd-plugin - 3.5 - - - /rulesets/java/braces.xml - /rulesets/java/naming.xml - .ruleset - - - - - org.codehaus.mojo - findbugs-maven-plugin - 3.0.0 - - Max - Low - true - - - - maven-jxr-plugin - 2.5 - - - maven-javadoc-plugin - 2.10.3 - - false - - - - org.codehaus.mojo - cobertura-maven-plugin - 2.7 - - - html - xml - - - - - org.codehaus.mojo - javancss-maven-plugin - 2.1 - - utf-8 - false - - - - - - - volcanoes.web - Volcanoes website - scpexe://vulcan4.wr.usgs.gov/webdata/volcanoes.usgs.gov/htdocs/software/maven2 - - - github.pages - scm:git:https://git@github.com/usgs/swarm.git - - - - src/main/resources/Version.java.template - src/main/java/gov/usgs/volcanoes/swarm/Version.java - UTF-8 - - - From 622af4a8071219a7a0dc4435a021a4b3adeb6ba9 Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Thu, 19 May 2016 14:59:50 -0800 Subject: [PATCH 32/67] change event marker color and docs --- .../swarm/map/hypocenters/HypocenterLayer.java | 11 +++++++++-- src/main/resources/help/mapSettings.md | 7 +------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java index 9a2ea5bc..95c6b058 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java @@ -84,7 +84,7 @@ public HypocenterLayer() { renderer.filled = true; renderer.color = Color.BLACK; // r.shape = Geometry.STAR_10; - renderer.shape = new Ellipse2D.Float(0f, 0f, 7f, 7f); + renderer.shape = new Ellipse2D.Float(0f, 0f, 5f, 5f); startPolling(); } @@ -180,13 +180,20 @@ public void draw(Graphics2D g2) { res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); g2.translate(res.x, res.y); + + double mag = event.getPerferredMagnitude().getMag(); + float diameter = (float) (2.5 + mag * 9/2.5); + diameter = Math.min(diameter, 10); + diameter = Math.max(diameter, 1); + long age = J2kSec.asEpoch(J2kSec.now()) - origin.getTime(); + renderer.shape = new Ellipse2D.Float(0f, 0f, diameter, diameter); if (event == hoverEvent) { renderer.paint = Color.GREEN; } else if (age < ONE_HOUR) { renderer.paint = Color.RED; } else if (age < ONE_DAY) { - renderer.paint = Color.ORANGE; + renderer.paint = Color.CYAN; } else if (age < ONE_WEEK) { renderer.paint = Color.YELLOW; } else { diff --git a/src/main/resources/help/mapSettings.md b/src/main/resources/help/mapSettings.md index af60b9d7..136b2f30 100644 --- a/src/main/resources/help/mapSettings.md +++ b/src/main/resources/help/mapSettings.md @@ -1,20 +1,15 @@ # Map Settings # ## Location ## - Specifies the center of the map and the scale in pixels per meter. ## Options ## - ### Line ### Specifies the color and width of the line connecting an inset map pannel with its marker. -### Refresh Interval ### - -### Channel Labels ### ### NEIC Event Summary ### Swarm can plot real-time events using data from the [NEIC real-time feed](http://earthquake.usgs.gov/earthquakes/feed/). Events are updated every five minutes. -Event markers are colored according to the event age. Events shown in red have occurred within the past hour; events shown in orange have occurred within the past day; events shown in yellow have occurred within the past week. \ No newline at end of file +Event markers are colored according to the event age. Events shown in red have occurred within the past hour; events shown in blue have occurred within the past day; events shown in yellow have occurred within the past week. \ No newline at end of file From 9736f4f71927fc554335eb67208344e67fe5931d Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Wed, 5 Oct 2016 09:18:51 -0800 Subject: [PATCH 33/67] system migration --- pom.xml | 65 +++++++ .../java/gov/usgs/volcanoes/swarm/Swarm.java | 2 +- .../usgs/volcanoes/swarm/event/Arrival.java | 89 --------- .../gov/usgs/volcanoes/swarm/event/Event.java | 178 ------------------ .../volcanoes/swarm/event/EventFrame.java | 5 + .../volcanoes/swarm/event/EventObserver.java | 17 -- .../usgs/volcanoes/swarm/event/Magnitude.java | 49 ----- .../usgs/volcanoes/swarm/event/Origin.java | 168 ----------------- .../volcanoes/swarm/event/ParameterPanel.java | 6 +- .../gov/usgs/volcanoes/swarm/event/Pick.java | 124 ------------ .../usgs/volcanoes/swarm/event/PickBox.java | 2 + .../volcanoes/swarm/event/PickWavePanel.java | 3 + .../usgs/volcanoes/swarm/map/MapFrame.java | 20 +- .../map/hypocenters/HypocenterLayer.java | 131 ++++--------- 14 files changed, 137 insertions(+), 722 deletions(-) delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/Event.java delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/EventObserver.java delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/Magnitude.java delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java delete mode 100644 src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java diff --git a/pom.xml b/pom.xml index cf55295f..6079012c 100644 --- a/pom.xml +++ b/pom.xml @@ -177,6 +177,37 @@ + + org.apache.maven.plugins maven-shade-plugin @@ -226,6 +257,18 @@ ** + + com.sun.xml.bind:jaxb-impl + + ** + + + + com.sun.xml.bind:jaxb-api + + ** + + @@ -244,6 +287,9 @@ colt:colt edu.iris:JavaSeedLite opensymphony:oscache + gov.usgs.earthquake:messageUtils + com.sun.xml.bind:jaxb-impl + com.sun.xml.bind:jaxb-api @@ -511,5 +557,24 @@ pegdown 1.6.0 + + + gov.usgs.earthquake + messageUtils + 1.0 + + + + com.sun.xml.bind + jaxb-impl + 2.1.2 + + + + javax.xml.bind + jaxb-api + 2.1 + + diff --git a/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java b/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java index b955da3e..d4a0d47a 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java @@ -31,6 +31,7 @@ import gov.usgs.plot.data.Wave; import gov.usgs.volcanoes.core.configfile.ConfigFile; +import gov.usgs.volcanoes.core.quakeml.Event; import gov.usgs.volcanoes.core.time.CurrentTime; import gov.usgs.volcanoes.core.time.J2kSec; import gov.usgs.volcanoes.core.ui.GlobalKeyManager; @@ -38,7 +39,6 @@ import gov.usgs.volcanoes.swarm.chooser.DataChooser; import gov.usgs.volcanoes.swarm.data.CachedDataSource; import gov.usgs.volcanoes.swarm.data.SeismicDataSource; -import gov.usgs.volcanoes.swarm.event.Event; import gov.usgs.volcanoes.swarm.event.EventFrame; import gov.usgs.volcanoes.swarm.heli.HelicorderViewerFrame; import gov.usgs.volcanoes.swarm.internalFrame.InternalFrameListener; diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java deleted file mode 100644 index 8ff9370d..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Arrival.java +++ /dev/null @@ -1,89 +0,0 @@ -/** - * I waive copyright and related rights in the this work worldwide - * through the CC0 1.0 Universal public domain dedication. - * https://creativecommons.org/publicdomain/zero/1.0/legalcode - */ - -package gov.usgs.volcanoes.swarm.event; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Element; - -import java.util.Comparator; -import java.util.Map; - -import gov.usgs.volcanoes.swarm.event.Pick.Onset; -import gov.usgs.volcanoes.swarm.event.Pick.Polarity; - -/** - * Holder for QuakeML arrival. - * - * @author Tom Parker - * - */ -public class Arrival { - Logger LOGGER = LoggerFactory.getLogger(Arrival.class); - - public final String publicId; - private Pick pick; - private String phase; - private double timeResidual; - private double distance; - - public Arrival(Element arrivalElement, Map picks) { - this.publicId = arrivalElement.getAttribute("publicID"); - LOGGER.debug("new arrival {}", publicId); - - // this.phase = arrivalElement.getAttribute("phase"); - pick = picks.get(arrivalElement.getElementsByTagName("pickID").item(0).getTextContent()); - phase = arrivalElement.getElementsByTagName("phase").item(0).getTextContent(); - timeResidual = Double - .parseDouble(arrivalElement.getElementsByTagName("timeResidual").item(0).getTextContent()); - distance = Double - .parseDouble(arrivalElement.getElementsByTagName("distance").item(0).getTextContent()); - } - - public Pick getPick() { - return pick; - } - - public String getPhase() { - return phase; - } - - public double getTimeResidual() { - return timeResidual; - } - - public String getTag() { - StringBuilder sb = new StringBuilder(); - - Onset onset = pick.getOnset(); - if (onset == Pick.Onset.EMERGENT) { - sb.append("e"); - } else if (onset == Pick.Onset.IMPULSIVE) { - sb.append("i"); - } - - sb.append(phase.charAt(0)); - - Polarity polarity = pick.getPolarity(); - if (polarity == Pick.Polarity.NEGATIVE) { - sb.append("-"); - } else if (polarity == Pick.Polarity.POSITIVE) { - sb.append("+"); - } - - return sb.toString(); - } - - public static Comparator distanceComparator() { - return new Comparator() { - public int compare(final Arrival e1, final Arrival e2) { - return Double.compare(e1.distance, e2.distance); - } - }; - } - -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java deleted file mode 100644 index 58a644d9..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Event.java +++ /dev/null @@ -1,178 +0,0 @@ -/** - * I waive copyright and related rights in the this work worldwide - * through the CC0 1.0 Universal public domain dedication. - * https://creativecommons.org/publicdomain/zero/1.0/legalcode - */ - -package gov.usgs.volcanoes.swarm.event; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import gov.usgs.volcanoes.core.util.StringUtils; - -/** - * Holder for QuakeML Event. - * - * @author Tom Parker - * - */ -public class Event { - private static final Logger LOGGER = LoggerFactory.getLogger(Event.class); - - public final String publicId; - - private final Map origins; - private final Map magnitudes; - private final Map picks; - private final List observers; - - private Origin preferredOrigin; - private Magnitude preferredMagnitude; - private String description; - private String eventSource; - private String evid; - private String type; - - public Event(String publicId) { - this.publicId = publicId; - LOGGER.debug("New event ({}}", publicId); - - origins = new HashMap(); - magnitudes = new HashMap(); - picks = new HashMap(); - observers = new ArrayList(); - } - - public Event(Element event) { - this(event.getAttribute("publicID")); - - updateEvent(event); - } - - public void addObserver(EventObserver observer) { - observers.add(observer); - } - - public void updateEvent(Element event) { - - // order matters. - parsePicks(event.getElementsByTagName("pick")); - - parseOrigins(event.getElementsByTagName("origin")); - preferredOrigin = origins.get(event.getAttribute("preferredOriginID")); - if (preferredOrigin == null && origins.size() > 0) { - preferredOrigin = (Origin) origins.values().toArray()[0]; - } - - parseMagnitudes(event.getElementsByTagName("magnitude")); - preferredMagnitude = magnitudes.get(event.getAttribute("preferredMagnitudeID")); - if (preferredMagnitude == null && magnitudes.size() > 0) { - preferredMagnitude = (Magnitude) magnitudes.values().toArray()[0]; - } - - eventSource = - StringUtils.stringToString(event.getAttribute("catalog:eventsource"), eventSource); - evid = StringUtils.stringToString(event.getAttribute("catalog:eventid"), evid); - - Element descriptionElement = (Element) event.getElementsByTagName("description").item(0); - if (descriptionElement != null) { - description = StringUtils.stringToString( - descriptionElement.getElementsByTagName("text").item(0).getTextContent(), description); - } - - // Element typeElement = (Element) event.getElementsByTagName("type").item(0); - NodeList childList = event.getChildNodes(); - String newType = null; - int idx = 0; - while (type == null && idx < childList.getLength()) { - Node node = childList.item(idx); - if (node.getNodeType() == Node.ELEMENT_NODE) { - Element element = (Element) node; - if (element.getTagName() == "type") { - type = element.getTextContent(); - } - idx++; - } - } - - type = StringUtils.stringToString(newType, type); - - notifyObservers(); - } - - private void notifyObservers() { - for (EventObserver observer : observers) { - observer.eventUpdated(); - } - } - - private void parsePicks(NodeList pickElements) { - picks.clear(); - int pickCount = pickElements.getLength(); - for (int idx = 0; idx < pickCount; idx++) { - Pick pick = new Pick((Element) pickElements.item(idx)); - picks.put(pick.publicId, pick); - } - } - - - private void parseOrigins(NodeList originElements) { - origins.clear(); - int originCount = originElements.getLength(); - for (int idx = 0; idx < originCount; idx++) { - Origin origin = new Origin((Element) originElements.item(idx), picks); - origins.put(origin.publicId, origin); - } - } - - public Origin getPreferredOrigin() { - - return preferredOrigin; - } - - private void parseMagnitudes(NodeList magnitudeElements) { - magnitudes.clear(); - int magnitudeCount = magnitudeElements.getLength(); - for (int idx = 0; idx < magnitudeCount; idx++) { - Magnitude magnitude = new Magnitude((Element) magnitudeElements.item(idx)); - magnitudes.put(magnitude.publicId, magnitude); - } - } - - public Magnitude getPerferredMagnitude() { - return preferredMagnitude; - } - - public String getEventSource() { - return eventSource; - } - - public String getEvid() { - return evid; - } - - public String getDataid() { - return null; - } - - public String getDescription() { - return description; - } - - public String getType() { - return type; - } - - public void setDescription(String description) { - this.description = description; - } -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java index 5c68de9d..c2b7adae 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java @@ -34,6 +34,11 @@ import javax.xml.parsers.ParserConfigurationException; import gov.usgs.volcanoes.core.CodeTimer; +import gov.usgs.volcanoes.core.quakeml.Arrival; +import gov.usgs.volcanoes.core.quakeml.Event; +import gov.usgs.volcanoes.core.quakeml.EventObserver; +import gov.usgs.volcanoes.core.quakeml.Origin; +import gov.usgs.volcanoes.core.quakeml.Pick; import gov.usgs.volcanoes.core.time.J2kSec; import gov.usgs.volcanoes.swarm.Icons; import gov.usgs.volcanoes.swarm.SwarmFrame; diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/EventObserver.java b/src/main/java/gov/usgs/volcanoes/swarm/event/EventObserver.java deleted file mode 100644 index 28348ddd..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/EventObserver.java +++ /dev/null @@ -1,17 +0,0 @@ -/** - * I waive copyright and related rights in the this work worldwide - * through the CC0 1.0 Universal public domain dedication. - * https://creativecommons.org/publicdomain/zero/1.0/legalcode - */ - -package gov.usgs.volcanoes.swarm.event; - -/** - * Observer interface for Event objects. - * - * @author Tom Parker - * - */ -public interface EventObserver { - public void eventUpdated(); -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Magnitude.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Magnitude.java deleted file mode 100644 index 01972ff7..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Magnitude.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * I waive copyright and related rights in the this work worldwide - * through the CC0 1.0 Universal public domain dedication. - * https://creativecommons.org/publicdomain/zero/1.0/legalcode - */ - -package gov.usgs.volcanoes.swarm.event; - -import org.w3c.dom.Element; - -/** - * Holder for QuakeML magnitude. - * - * @author Tom Parker - * - */ -public class Magnitude { - - public final String publicId; - - private double mag; - private String type; - private String uncertainty; - - public Magnitude(Element magnitudeElement) { - publicId = magnitudeElement.getAttribute("publicId"); - type = magnitudeElement.getElementsByTagName("type").item(0).getTextContent(); - - Element magElement = (Element) magnitudeElement.getElementsByTagName("mag").item(0); - mag = Double.parseDouble(magElement.getElementsByTagName("value").item(0).getTextContent()); - - Element uncertaintyElement = (Element) magElement.getElementsByTagName("uncertainty").item(0); - if (uncertaintyElement != null) - uncertainty = "\u00B1" + uncertaintyElement.getTextContent(); - - } - - public double getMag() { - return mag; - } - - public String getType() { - return type; - } - - public String getUncertainty() { - return uncertainty; - } -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java deleted file mode 100644 index 90c3d77d..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Origin.java +++ /dev/null @@ -1,168 +0,0 @@ -/** - * I waive copyright and related rights in the this work worldwide - * through the CC0 1.0 Universal public domain dedication. - * https://creativecommons.org/publicdomain/zero/1.0/legalcode - */ - -package gov.usgs.volcanoes.swarm.event; - - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -/** - * Holder for QuakeML origin. - * - * @author Tom Parker - * - */ -public class Origin { - private static final Logger LOGGER = LoggerFactory.getLogger(Origin.class); - - public static enum EvaluationMode { - AUTOMATIC, MANUAL; - } - - public static enum EvaluationStatus { - PRELIMINARY, CONFIRMED, REVIEWED, FINAL, REJECTED - } - - public final String publicId; - private double latitude; - private double longitude; - private double depth; - private long time; - private EvaluationMode evaluationMode; - private EvaluationStatus evaluationStatus; - private double standardError; - private double azimuthalGap; - private Map arrivals; - private int phaseCount; - private double minimumDistance; - - public Origin(Element originElement, Map picks) { - this.publicId = originElement.getAttribute("publicId"); - arrivals = new HashMap(); - - LOGGER.debug("new origin {}", publicId); - - Element lonElement = (Element) originElement.getElementsByTagName("longitude").item(0); - longitude = - Double.parseDouble(lonElement.getElementsByTagName("value").item(0).getTextContent()); - - Element latElement = (Element) originElement.getElementsByTagName("latitude").item(0); - latitude = - Double.parseDouble(latElement.getElementsByTagName("value").item(0).getTextContent()); - - Element depthElement = (Element) originElement.getElementsByTagName("depth").item(0); - depth = Double.parseDouble(depthElement.getElementsByTagName("value").item(0).getTextContent()); - - Element timeElement = (Element) originElement.getElementsByTagName("time").item(0); - time = 0; - time = - QuakeMlUtils.parseTime(timeElement.getElementsByTagName("value").item(0).getTextContent()); - - Element evaluationElement = (Element) originElement.getElementsByTagName("evaluationStatus").item(0); - if (evaluationElement != null) { - evaluationStatus = EvaluationStatus.valueOf(evaluationElement.getTextContent().toUpperCase()); - } - - evaluationElement = (Element) originElement.getElementsByTagName("evaluationMode").item(0); - if (evaluationElement != null) { - evaluationMode = EvaluationMode.valueOf(evaluationElement.getTextContent().toUpperCase()); - } - - Element qualityElement = (Element) originElement.getElementsByTagName("quality").item(0); - if (qualityElement != null) { - Element errorElement = (Element) qualityElement.getElementsByTagName("standardError").item(0); - if (errorElement != null) { - standardError = Double.parseDouble(errorElement.getTextContent()); - } else { - standardError = Double.NaN; - } - - Element gapElement = (Element) qualityElement.getElementsByTagName("azimuthalGap").item(0); - if (gapElement != null) { - LOGGER.debug("GAP: {}", gapElement.getTextContent()); - azimuthalGap = Double.parseDouble(gapElement.getTextContent()); - } else { - azimuthalGap = Double.NaN; - } - - Element phaseCountElement = (Element) qualityElement.getElementsByTagName("usedPhaseCount").item(0); - if (gapElement != null) { - phaseCount = Integer.parseInt(phaseCountElement.getTextContent()); - } else { - phaseCount = -1; - } - - Element distanceElement = (Element) qualityElement.getElementsByTagName("minimumDistance").item(0); - if (distanceElement != null) { - minimumDistance = Double.parseDouble(distanceElement.getTextContent()); - } else { - minimumDistance = Double.NaN; - } - - } - - parseArrivals(originElement.getElementsByTagName("arrival"), picks); - } - - private void parseArrivals(NodeList arrivalElements, Map picks) { - int arrivalCount = arrivalElements.getLength(); - for (int idx = 0; idx < arrivalCount; idx++) { - Arrival arrival = new Arrival((Element) arrivalElements.item(idx), picks); - arrivals.put(arrival.publicId, arrival); - } - } - - public double getLongitude() { - return longitude; - } - - public double getLatitude() { - return latitude; - } - - public double getDepth() { - return depth; - } - - public long getTime() { - return time; - } - - public Collection getArrivals() { - return arrivals.values(); - } - - public EvaluationStatus getEvaluationStatus() { - return evaluationStatus; - } - - public EvaluationMode getEvaluationMode() { - return evaluationMode; - } - - public double getStandardError() { - return standardError; - } - - public double getAzimuthalGap() { - return azimuthalGap; - } - - public int getPhaseCount() { - return phaseCount; - } - - public double getMinimumDistance() { - return minimumDistance; - } -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/ParameterPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/event/ParameterPanel.java index 67aac58c..3595ca4c 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/ParameterPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/ParameterPanel.java @@ -21,6 +21,10 @@ import javax.swing.ScrollPaneConstants; import javax.swing.SwingConstants; +import gov.usgs.volcanoes.core.quakeml.Event; +import gov.usgs.volcanoes.core.quakeml.Magnitude; +import gov.usgs.volcanoes.core.quakeml.Origin; + public class ParameterPanel { private static final Logger LOGGER = LoggerFactory.getLogger(ParameterPanel.class); private static final Font KEY_FONT = Font.decode("dialog-BOLD-12"); @@ -75,7 +79,7 @@ public static Component create(Event event) { addKey("Type: ", parameterPanel, c); if (origin != null) { - addValue(event.getType(), parameterPanel, c); + addValue(event.getTypeDescription(), parameterPanel, c); } c.gridy++; diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java b/src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java deleted file mode 100644 index 60103a09..00000000 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/Pick.java +++ /dev/null @@ -1,124 +0,0 @@ -/** - * I waive copyright and related rights in the this work worldwide - * through the CC0 1.0 Universal public domain dedication. - * https://creativecommons.org/publicdomain/zero/1.0/legalcode - */ - -package gov.usgs.volcanoes.swarm.event; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.w3c.dom.DOMException; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - -import java.text.ParseException; - -/** - * Holder for QuakeML pick. - * - * @author Tom Parker - * - */ -public class Pick { - Logger LOGGER = LoggerFactory.getLogger(Pick.class); - - public final String publicId; - private long time; - private String channel; - private Onset onset; - private Polarity polarity; - - - public static enum Onset { - EMERGENT, IMPULSIVE, QUESTIONABLE; - - public static Onset parse(String string) throws ParseException { - if ("emergent".equals(string)) { - return EMERGENT; - } else if ("impulsive".equals(string)) { - return IMPULSIVE; - } else if ("questionable".equals(string)) { - return QUESTIONABLE; - } else { - throw new ParseException("Cannot parse " + string, 12); - } - - } - } - - public static enum Polarity { - POSITIVE, NEGATIVE, UNDECIDABLE; - - public static Polarity parse(String string) throws ParseException { - if ("positive".equals(string)) { - return POSITIVE; - } else if ("negative".equals(string)) { - return NEGATIVE; - } else if ("undecidable".equals(string)) { - return UNDECIDABLE; - } else { - throw new ParseException("Cannot parse " + string, 12); - } - } - } - - public Pick(Element pickElement) { - publicId = pickElement.getAttribute("publicID"); - LOGGER.debug("new PIck {}", publicId); - - Element timeElement = (Element) pickElement.getElementsByTagName("time").item(0); - time = - QuakeMlUtils.parseTime(timeElement.getElementsByTagName("value").item(0).getTextContent()); - - NodeList onsetList = pickElement.getElementsByTagName("onset"); - if (onsetList != null && onsetList.getLength() > 0) { - try { - onset = Onset.parse(onsetList.item(0).getTextContent()); - } catch (DOMException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (ParseException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - NodeList polarityList = pickElement.getElementsByTagName("polarity"); - if (polarityList != null && polarityList.getLength() > 0) { - try { - polarity = - Polarity.parse(pickElement.getElementsByTagName("polarity").item(0).getTextContent()); - } catch (DOMException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (ParseException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - Element waveformId = (Element) pickElement.getElementsByTagName("waveformID").item(0); - String station = waveformId.getAttribute("stationCode"); - String chan = waveformId.getAttribute("channelCode"); - String net = waveformId.getAttribute("networkCode"); - String loc = waveformId.getAttribute("locationCode"); - - channel = station + "$" + chan + "$" + net + "$" + loc; - } - - public long getTime() { - return time; - } - - public String getChannel() { - return channel; - } - - public Onset getOnset() { - return onset; - } - - public Polarity getPolarity() { - return polarity; - } -} diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickBox.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickBox.java index 4dae46e7..bf209e5b 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickBox.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickBox.java @@ -41,6 +41,8 @@ import gov.usgs.volcanoes.core.CodeTimer; import gov.usgs.volcanoes.core.contrib.PngEncoder; import gov.usgs.volcanoes.core.contrib.PngEncoderB; +import gov.usgs.volcanoes.core.quakeml.Arrival; +import gov.usgs.volcanoes.core.quakeml.Pick; import gov.usgs.volcanoes.core.time.J2kSec; import gov.usgs.volcanoes.core.util.UiUtils; import gov.usgs.volcanoes.swarm.FileChooser; diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java b/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java index 1928e479..0e28410d 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/PickWavePanel.java @@ -17,6 +17,9 @@ import java.util.List; import java.util.Stack; +import gov.usgs.volcanoes.core.quakeml.Arrival; +import gov.usgs.volcanoes.core.quakeml.EventObserver; +import gov.usgs.volcanoes.core.quakeml.Pick; import gov.usgs.volcanoes.core.time.J2kSec; import gov.usgs.volcanoes.swarm.time.TimeListener; import gov.usgs.volcanoes.swarm.time.WaveViewTime; diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapFrame.java index 96ead0d8..06c6b3d3 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapFrame.java @@ -1,9 +1,11 @@ package gov.usgs.volcanoes.swarm.map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.awt.BorderLayout; import java.awt.Graphics; import java.awt.Insets; -import java.awt.Panel; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; @@ -13,6 +15,7 @@ import java.beans.PropertyVetoException; import java.io.File; import java.io.FileOutputStream; +import java.net.MalformedURLException; import java.text.ParseException; import javax.swing.BorderFactory; @@ -36,7 +39,6 @@ import gov.usgs.volcanoes.core.configfile.ConfigFile; import gov.usgs.volcanoes.core.contrib.PngEncoder; import gov.usgs.volcanoes.core.contrib.PngEncoderB; -import gov.usgs.volcanoes.core.time.CurrentTime; import gov.usgs.volcanoes.core.time.J2kSec; import gov.usgs.volcanoes.core.util.UiUtils; import gov.usgs.volcanoes.swarm.FileChooser; @@ -48,6 +50,7 @@ import gov.usgs.volcanoes.swarm.heli.HelicorderViewPanelListener; import gov.usgs.volcanoes.swarm.map.MapPanel.DragMode; import gov.usgs.volcanoes.swarm.map.MapPanel.LabelSetting; +import gov.usgs.volcanoes.swarm.map.hypocenters.HypocenterLayer; import gov.usgs.volcanoes.swarm.options.SwarmOptions; import gov.usgs.volcanoes.swarm.options.SwarmOptionsListener; import gov.usgs.volcanoes.swarm.time.UiTime; @@ -61,7 +64,9 @@ */ public class MapFrame extends SwarmFrame implements Runnable, Kioskable, SwarmOptionsListener { private static final long serialVersionUID = 1L; + private static final Logger LOGGER = LoggerFactory.getLogger(MapFrame.class); + private JToolBar toolbar; private JPanel mainPanel; private JButton optionsButton; @@ -120,9 +125,14 @@ private MapFrame() { } private void addLayers() { - MapLayer mapLayer = new gov.usgs.volcanoes.swarm.map.hypocenters.HypocenterLayer(); - mapLayer.setMapPanel(mapPanel); - addLayer(mapLayer); + MapLayer mapLayer; + try { + mapLayer = new HypocenterLayer(); + mapLayer.setMapPanel(mapPanel); + addLayer(mapLayer); + } catch (MalformedURLException ex) { + LOGGER.error("Unable to load layer. {}", ex); + } } public static MapFrame getInstance() { diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java index 95c6b058..1c46964a 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java @@ -2,11 +2,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.w3c.dom.DOMException; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; import java.awt.BasicStroke; import java.awt.Color; @@ -18,8 +13,8 @@ import java.awt.geom.Ellipse2D; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; -import java.io.IOException; -import java.text.ParseException; +import java.net.MalformedURLException; +import java.net.URL; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; @@ -28,27 +23,24 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - import gov.usgs.plot.render.DataPointRenderer; import gov.usgs.proj.GeoRange; import gov.usgs.proj.Projection; -import gov.usgs.volcanoes.core.CodeTimer; +import gov.usgs.volcanoes.core.quakeml.Event; +import gov.usgs.volcanoes.core.quakeml.Magnitude; +import gov.usgs.volcanoes.core.quakeml.Origin; +import gov.usgs.volcanoes.core.quakeml.QuakemlObserver; +import gov.usgs.volcanoes.core.quakeml.QuakemlSource; import gov.usgs.volcanoes.core.time.J2kSec; import gov.usgs.volcanoes.core.time.Time; import gov.usgs.volcanoes.swarm.ConfigListener; import gov.usgs.volcanoes.swarm.Swarm; import gov.usgs.volcanoes.swarm.SwarmConfig; -import gov.usgs.volcanoes.swarm.event.Event; -import gov.usgs.volcanoes.swarm.event.Magnitude; -import gov.usgs.volcanoes.swarm.event.Origin; import gov.usgs.volcanoes.swarm.map.MapFrame; import gov.usgs.volcanoes.swarm.map.MapLayer; import gov.usgs.volcanoes.swarm.map.MapPanel; -public final class HypocenterLayer implements MapLayer, ConfigListener { +public final class HypocenterLayer implements MapLayer, ConfigListener, QuakemlObserver { private static final Logger LOGGER = LoggerFactory.getLogger(HypocenterLayer.class); private static final int REFRESH_INTERVAL = 5 * 60 * 1000; private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSX"; @@ -65,14 +57,13 @@ public final class HypocenterLayer implements MapLayer, ConfigListener { private MapPanel panel; private SimpleDateFormat dateFormat; - private Thread refreshThread; private final SwarmConfig swarmConfig; private final DataPointRenderer renderer; + private QuakemlSource quakemlSource; private Event hoverEvent; private Point hoverLocation; - public HypocenterLayer() { - // events = new HashMap(); + public HypocenterLayer() throws MalformedURLException { events = new ConcurrentHashMap(); dateFormat = new SimpleDateFormat(DATE_FORMAT); swarmConfig = SwarmConfig.getInstance(); @@ -85,74 +76,19 @@ public HypocenterLayer() { renderer.color = Color.BLACK; // r.shape = Geometry.STAR_10; renderer.shape = new Ellipse2D.Float(0f, 0f, 5f, 5f); + HypocenterSource hypocenterSource = swarmConfig.getHypocenterSource(); - startPolling(); + quakemlSource = new QuakemlSource(new URL(hypocenterSource.getUrl()), (long) REFRESH_INTERVAL); + quakemlSource.addObserver(this); + update(quakemlSource); } public void setMapPanel(MapPanel mapPanel) { panel = mapPanel; } - private void startPolling() { - - Runnable r = new Runnable() { - public void run() { - while (run) { - try { - pollHypocenters(); - } catch (ParserConfigurationException e) { - LOGGER.debug("ParserConfigurationException while retrieving hypocenters ({})", e); - } catch (SAXException e) { - events.clear(); - LOGGER.debug( - "SAXException while retrieving hypocenters. Typically this means there were no hypocenters to display."); - } catch (IOException e) { - LOGGER.debug("IOException while retrieving hypocenters ({})", e); - } catch (DOMException e) { - LOGGER.debug("DOMException while retrieving hypocenters ({})", e); - } catch (ParseException e) { - LOGGER.debug("ParseException while retrieving hypocenters ({})", e); - } - - MapFrame.getInstance().repaint(); - - try { - Thread.sleep(REFRESH_INTERVAL); - } catch (InterruptedException e) { - LOGGER.debug("hypocenter update interupted."); - } - - } - } - }; - refreshThread = new Thread(r); - refreshThread.start(); - } - - private void pollHypocenters() - throws ParserConfigurationException, SAXException, IOException, DOMException, ParseException { - LOGGER.debug("Polling hypocenters"); - events.clear(); - HypocenterSource hypocenterSource = swarmConfig.getHypocenterSource(); - if (hypocenterSource == HypocenterSource.NONE) { - return; - } - - DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); - Document doc = dBuilder.parse(hypocenterSource.getUrl()); - doc.getDocumentElement().normalize(); - - NodeList eventElements = doc.getElementsByTagName("event"); - LOGGER.debug("Got {} events.", eventElements.getLength()); - int eventCount = eventElements.getLength(); - for (int idx = 0; idx < eventCount; idx++) { - Event event = new Event((Element) eventElements.item(idx)); - events.put(event.publicId, event); - } - } - public void draw(Graphics2D g2) { + if (events.size() < 1) return; @@ -182,7 +118,7 @@ public void draw(Graphics2D g2) { g2.translate(res.x, res.y); double mag = event.getPerferredMagnitude().getMag(); - float diameter = (float) (2.5 + mag * 9/2.5); + float diameter = (float) (2.5 + mag * 9 / 2.5); diameter = Math.min(diameter, 10); diameter = Math.max(diameter, 1); @@ -217,7 +153,7 @@ private void drawPopup(Graphics2D g2) { GeoRange range = panel.getRange(); Projection projection = panel.getProjection(); List text = generatePopupText(origin); - + FontMetrics fm = g2.getFontMetrics(); int popupHeight = 2 * POPUP_PADDING; int popupWidth = 0; @@ -237,13 +173,13 @@ private void drawPopup(Graphics2D g2) { final double dx = (ext[1] - ext[0]); final double dy = (ext[3] - ext[2]); final Point2D.Double res = new Point2D.Double(); - + res.x = (((xy.x - ext[0]) / dx) * widthPx + insetPx); int maxX = widthPx - popupWidth + POPUP_PADDING; res.x = Math.min(res.x, maxX); - + res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); - if (res.y < ( insetPx + popupHeight)) { + if (res.y < (insetPx + popupHeight)) { res.y += popupHeight; } @@ -267,7 +203,7 @@ private void drawPopup(Graphics2D g2) { private List generatePopupText(Origin origin) { List text = new ArrayList(3); - + Magnitude magElement = hoverEvent.getPerferredMagnitude(); String mag = String.format("%.2f %s at %.2f km depth", magElement.getMag(), magElement.getType(), (origin.getDepth() / 1000)); @@ -326,12 +262,19 @@ public boolean mouseClicked(final MouseEvent e) { public void settingsChanged() { LOGGER.debug("hypocenter plotter sees changed settings."); - refreshThread.interrupt(); + HypocenterSource hypocenterSource = swarmConfig.getHypocenterSource(); + try { + quakemlSource.stop(); + quakemlSource = new QuakemlSource(new URL(hypocenterSource.getUrl()), (long) REFRESH_INTERVAL); + quakemlSource.addObserver(this); + update(quakemlSource); + } catch (MalformedURLException ex) { + LOGGER.error("Unable to load hypocenter URL.", ex); + } } public void stop() { run = false; - refreshThread.interrupt(); } public boolean mouseMoved(MouseEvent e) { @@ -344,7 +287,7 @@ public boolean mouseMoved(MouseEvent e) { if (projection == null) { return false; } - + int widthPx = panel.getGraphWidth(); int heightPx = panel.getGraphHeight(); int insetPx = panel.getInset(); @@ -362,10 +305,10 @@ public boolean mouseMoved(MouseEvent e) { if (!range.contains(originLoc)) { continue; } - + final Rectangle r = new Rectangle(0, 0, 10, 10); - + final Point2D.Double xy = projection.forward(new Point2D.Double(origin.getLongitude(), origin.getLatitude())); final double[] ext = range.getProjectedExtents(projection); @@ -390,4 +333,12 @@ public boolean mouseMoved(MouseEvent e) { } return handled; } + + public void update(QuakemlSource source) { + events.clear(); + events.putAll(source.getEventSet()); + if (MapFrame.getInstance() != null) { + MapFrame.getInstance().repaint(); + } + } } From 716cc8f440485d21f98deb231407b81575312827 Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Wed, 5 Oct 2016 09:19:24 -0800 Subject: [PATCH 34/67] add straglers --- RsamDefaults.config | 30 ++++++++++++++++++++++++++++++ release.properties | 17 +++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 RsamDefaults.config create mode 100644 release.properties diff --git a/RsamDefaults.config b/RsamDefaults.config new file mode 100644 index 00000000..af0afee7 --- /dev/null +++ b/RsamDefaults.config @@ -0,0 +1,30 @@ +default.autoScale=true + +default.binSize=Hour + +default.countsPeriod=10 + +default.detrend=false + +default.eventMaxLength=300.0 + +default.eventRatio=1.3 + +default.eventThreshold=50.0 + +default.runningMean=false + +default.runningMeanPeriod=300.0 + +default.runningMedian=false + +default.runningMedianPeriod=300.0 + +default.scaleMax=100.0 + +default.scaleMin=0.0 + +default.valuesPeriod=600 + +default.viewType=VALUES + diff --git a/release.properties b/release.properties new file mode 100644 index 00000000..a47bae19 --- /dev/null +++ b/release.properties @@ -0,0 +1,17 @@ +#release configuration +#Tue Oct 13 16:26:44 AKDT 2015 +project.scm.gov.usgs.volcanoes\:swarm.tag=swarm-2.5 +scm.tagNameFormat=@{project.artifactId}-@{project.version} +project.scm.gov.usgs.volcanoes\:swarm.url=git@github.com\:usgs/swarm.git +scm.tag=swarm-2.5 +project.rel.gov.usgs.volcanoes\:swarm=2.5 +pushChanges=true +scm.url=scm\:git\:git@github.com\:usgs/swarm.git +preparationGoals=clean verify +project.scm.gov.usgs.volcanoes\:swarm.connection=scm\:git\:git@github.com\:usgs/swarm.git +remoteTagging=true +scm.commentPrefix=[maven-release-plugin] +project.dev.gov.usgs.volcanoes\:swarm=2.5.1-SNAPSHOT +project.scm.gov.usgs.volcanoes\:swarm.developerConnection=scm\:git\:git@github.com\:usgs/swarm.git +exec.snapshotReleasePluginAllowed=false +completedPhase=run-preparation-goals From b382c9f6cfb9ff9103afc00626617efafa1d633a Mon Sep 17 00:00:00 2001 From: tparker Date: Wed, 7 Dec 2016 14:55:00 -0900 Subject: [PATCH 35/67] Continue event viewer --- pom.xml | 2 +- .../usgs/volcanoes/swarm/map/MapPanel.java | 1 + .../map/hypocenters/HypocenterLayer.java | 602 +++++++++--------- 3 files changed, 304 insertions(+), 301 deletions(-) diff --git a/pom.xml b/pom.xml index 6079012c..778e8761 100644 --- a/pom.xml +++ b/pom.xml @@ -524,7 +524,7 @@ gov.usgs.volcanoes usgs - 1.3.1 + 1.3.2 gov.usgs.volcanoes diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java index 8d4eaa66..4be7c912 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java @@ -939,6 +939,7 @@ private void paintGreatCircleRoute(final Graphics2D g2) { @Override public void paintComponent(final Graphics g) { + if (renderer == null || mapImage == null) { final Dimension d = getSize(); g.drawString("Loading map...", d.width / 2 - 50, d.height / 2); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java index 1c46964a..4f147cdf 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java @@ -41,304 +41,306 @@ import gov.usgs.volcanoes.swarm.map.MapPanel; public final class HypocenterLayer implements MapLayer, ConfigListener, QuakemlObserver { - private static final Logger LOGGER = LoggerFactory.getLogger(HypocenterLayer.class); - private static final int REFRESH_INTERVAL = 5 * 60 * 1000; - private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSX"; - private static final int ONE_HOUR = 60 * 60 * 1000; - private static final int ONE_DAY = ONE_HOUR * 24; - private static final int ONE_WEEK = ONE_DAY * 7; - - private static final int POPUP_PADDING = 2; - - // private List hypocenters; - private final Map events; - private boolean run = true; - - private MapPanel panel; - private SimpleDateFormat dateFormat; - - private final SwarmConfig swarmConfig; - private final DataPointRenderer renderer; - private QuakemlSource quakemlSource; - private Event hoverEvent; - private Point hoverLocation; - - public HypocenterLayer() throws MalformedURLException { - events = new ConcurrentHashMap(); - dateFormat = new SimpleDateFormat(DATE_FORMAT); - swarmConfig = SwarmConfig.getInstance(); - swarmConfig.addListener(this); - - renderer = new DataPointRenderer(); - renderer.antiAlias = true; - renderer.stroke = new BasicStroke(2f); - renderer.filled = true; - renderer.color = Color.BLACK; - // r.shape = Geometry.STAR_10; - renderer.shape = new Ellipse2D.Float(0f, 0f, 5f, 5f); - HypocenterSource hypocenterSource = swarmConfig.getHypocenterSource(); - - quakemlSource = new QuakemlSource(new URL(hypocenterSource.getUrl()), (long) REFRESH_INTERVAL); - quakemlSource.addObserver(this); - update(quakemlSource); - } - - public void setMapPanel(MapPanel mapPanel) { - panel = mapPanel; - } - - public void draw(Graphics2D g2) { - - if (events.size() < 1) - return; - - GeoRange range = panel.getRange(); - Projection projection = panel.getProjection(); - int widthPx = panel.getGraphWidth(); - int heightPx = panel.getGraphHeight(); - int insetPx = panel.getInset(); - - for (final Event event : events.values()) { - Origin origin = event.getPreferredOrigin(); - - Point2D.Double originLoc = new Point2D.Double(origin.getLongitude(), origin.getLatitude()); - if (!range.contains(originLoc)) { - continue; - } - - final Point2D.Double xy = projection.forward(originLoc); - - final double[] ext = range.getProjectedExtents(projection); - final double dx = (ext[1] - ext[0]); - final double dy = (ext[3] - ext[2]); - final Point2D.Double res = new Point2D.Double(); - res.x = (((xy.x - ext[0]) / dx) * widthPx + insetPx); - res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); - - g2.translate(res.x, res.y); - - double mag = event.getPerferredMagnitude().getMag(); - float diameter = (float) (2.5 + mag * 9 / 2.5); - diameter = Math.min(diameter, 10); - diameter = Math.max(diameter, 1); - - long age = J2kSec.asEpoch(J2kSec.now()) - origin.getTime(); - renderer.shape = new Ellipse2D.Float(0f, 0f, diameter, diameter); - if (event == hoverEvent) { - renderer.paint = Color.GREEN; - } else if (age < ONE_HOUR) { - renderer.paint = Color.RED; - } else if (age < ONE_DAY) { - renderer.paint = Color.CYAN; - } else if (age < ONE_WEEK) { - renderer.paint = Color.YELLOW; - } else { - renderer.paint = Color.WHITE; - } - renderer.renderAtOrigin(g2); - - if (event == hoverEvent) { - } - g2.translate(-res.x, -res.y); - } - - drawPopup(g2); - } - - private void drawPopup(Graphics2D g2) { - if (hoverEvent == null) { - return; - } - Origin origin = hoverEvent.getPreferredOrigin(); - GeoRange range = panel.getRange(); - Projection projection = panel.getProjection(); - List text = generatePopupText(origin); - - FontMetrics fm = g2.getFontMetrics(); - int popupHeight = 2 * POPUP_PADDING; - int popupWidth = 0; - for (String string : text) { - Rectangle2D bounds = fm.getStringBounds(string, g2); - popupHeight += (int) (Math.ceil(bounds.getHeight()) + 2); - popupWidth = Math.max(popupWidth, (int) (Math.ceil(bounds.getWidth()) + 2 * POPUP_PADDING)); - } - - int widthPx = panel.getGraphWidth(); - int heightPx = panel.getGraphHeight(); - int insetPx = panel.getInset(); - - final Point2D.Double xy = - projection.forward(new Point2D.Double(origin.getLongitude(), origin.getLatitude())); - final double[] ext = range.getProjectedExtents(projection); - final double dx = (ext[1] - ext[0]); - final double dy = (ext[3] - ext[2]); - final Point2D.Double res = new Point2D.Double(); - - res.x = (((xy.x - ext[0]) / dx) * widthPx + insetPx); - int maxX = widthPx - popupWidth + POPUP_PADDING; - res.x = Math.min(res.x, maxX); - - res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); - if (res.y < (insetPx + popupHeight)) { - res.y += popupHeight; - } - - g2.translate(res.x, res.y); - - g2.setStroke(new BasicStroke(1.2f)); - g2.setColor(new Color(0, 0, 0, 128)); - g2.drawRect(0, -(popupHeight - POPUP_PADDING), popupWidth, popupHeight); - g2.fillRect(0, -(popupHeight - POPUP_PADDING), popupWidth, popupHeight); - - g2.setColor(Color.WHITE); - int baseY = POPUP_PADDING; - for (String string : text) { - g2.drawString(string, POPUP_PADDING, -baseY); - Rectangle2D bounds = fm.getStringBounds(string, g2); - baseY += (int) (Math.ceil(bounds.getHeight()) + 2); - } - g2.translate(-res.x, -res.y); - - } - - private List generatePopupText(Origin origin) { - List text = new ArrayList(3); - - Magnitude magElement = hoverEvent.getPerferredMagnitude(); - String mag = String.format("%.2f %s at %.2f km depth", magElement.getMag(), - magElement.getType(), (origin.getDepth() / 1000)); - text.add(mag); - - String date = Time.format(Time.STANDARD_TIME_FORMAT, new Date(origin.getTime())); - text.add(date + " UTC"); - - String description = hoverEvent.getDescription(); - text.add(description); - - return text; - } - - public boolean mouseClicked(final MouseEvent e) { - - hoverEvent = null; - if (events.size() < 1l) { - return false; - } - - GeoRange range = panel.getRange(); - Projection projection = panel.getProjection(); - int widthPx = panel.getGraphWidth(); - int heightPx = panel.getGraphHeight(); - int insetPx = panel.getInset(); - - Iterator it = events.values().iterator(); - boolean handled = false; - while (it.hasNext() && handled == false) { - Event event = it.next(); - Origin origin = event.getPreferredOrigin(); - final Rectangle r = new Rectangle(-7, -7, 17, 17); - - final Point2D.Double xy = - projection.forward(new Point2D.Double(origin.getLongitude(), origin.getLatitude())); - final double[] ext = range.getProjectedExtents(projection); - final double dx = (ext[1] - ext[0]); - final double dy = (ext[3] - ext[2]); - final Point2D.Double res = new Point2D.Double(); - res.x = (((xy.x - ext[0]) / dx) * widthPx + insetPx); - res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); - - r.translate((int) res.x, (int) res.y); - - if (r.contains(e.getPoint())) { - LOGGER.debug("event clicked"); - Swarm.openEvent(event); - return true; - } - } - - return handled; - } - - - public void settingsChanged() { - LOGGER.debug("hypocenter plotter sees changed settings."); - HypocenterSource hypocenterSource = swarmConfig.getHypocenterSource(); - try { - quakemlSource.stop(); - quakemlSource = new QuakemlSource(new URL(hypocenterSource.getUrl()), (long) REFRESH_INTERVAL); - quakemlSource.addObserver(this); - update(quakemlSource); - } catch (MalformedURLException ex) { - LOGGER.error("Unable to load hypocenter URL.", ex); - } - } - - public void stop() { - run = false; - } - - public boolean mouseMoved(MouseEvent e) { - if (events.size() < 1) { - return false; - } - - GeoRange range = panel.getRange(); - Projection projection = panel.getProjection(); - if (projection == null) { - return false; - } - - int widthPx = panel.getGraphWidth(); - int heightPx = panel.getGraphHeight(); - int insetPx = panel.getInset(); - - Iterator it = events.values().iterator(); - boolean handled = false; - while (it.hasNext() && handled == false) { - Event event = it.next(); - Origin origin = event.getPreferredOrigin(); - if (origin == null) { - continue; - } - - Point2D.Double originLoc = new Point2D.Double(origin.getLongitude(), origin.getLatitude()); - if (!range.contains(originLoc)) { - continue; - } - - final Rectangle r = new Rectangle(0, 0, 10, 10); - - - final Point2D.Double xy = - projection.forward(new Point2D.Double(origin.getLongitude(), origin.getLatitude())); - final double[] ext = range.getProjectedExtents(projection); - final double dx = (ext[1] - ext[0]); - final double dy = (ext[3] - ext[2]); - final Point2D.Double res = new Point2D.Double(); - res.x = (((xy.x - ext[0]) / dx) * widthPx + insetPx); - res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); - - r.translate((int) res.x, (int) res.y); - if (r.contains(e.getPoint())) { - LOGGER.debug("set hover event {}", event.publicId); - hoverEvent = event; - handled = true; - } else if (event == hoverEvent) { - LOGGER.debug("unset hover event {}", event.publicId); - - hoverEvent = null; - hoverLocation = e.getPoint(); - handled = true; - } - } - return handled; - } - - public void update(QuakemlSource source) { - events.clear(); - events.putAll(source.getEventSet()); - if (MapFrame.getInstance() != null) { - MapFrame.getInstance().repaint(); - } - } + private static final Logger LOGGER = LoggerFactory.getLogger(HypocenterLayer.class); + private static final int REFRESH_INTERVAL = 5 * 60 * 1000; + private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSX"; + private static final int ONE_HOUR = 60 * 60 * 1000; + private static final int ONE_DAY = ONE_HOUR * 24; + private static final int ONE_WEEK = ONE_DAY * 7; + + private static final int POPUP_PADDING = 2; + + // private List hypocenters; + private final Map events; + private boolean run = true; + + private MapPanel panel; + private SimpleDateFormat dateFormat; + + private final SwarmConfig swarmConfig; + private final DataPointRenderer renderer; + private QuakemlSource quakemlSource; + private Event hoverEvent; + private Point hoverLocation; + + public HypocenterLayer() throws MalformedURLException { + events = new ConcurrentHashMap(); + dateFormat = new SimpleDateFormat(DATE_FORMAT); + swarmConfig = SwarmConfig.getInstance(); + swarmConfig.addListener(this); + + renderer = new DataPointRenderer(); + renderer.antiAlias = true; + renderer.stroke = new BasicStroke(2f); + renderer.filled = true; + renderer.color = Color.BLACK; + // r.shape = Geometry.STAR_10; + renderer.shape = new Ellipse2D.Float(0f, 0f, 5f, 5f); + HypocenterSource hypocenterSource = swarmConfig.getHypocenterSource(); + + URL quakemlUrl = new URL(hypocenterSource.getUrl()); + if (quakemlUrl != null) { + quakemlSource = new QuakemlSource(quakemlUrl, (long) REFRESH_INTERVAL); + quakemlSource.addObserver(this); + update(quakemlSource); + } + } + + public void setMapPanel(MapPanel mapPanel) { + panel = mapPanel; + } + + public void draw(Graphics2D g2) { + if (events.size() < 1) + return; + + GeoRange range = panel.getRange(); + Projection projection = panel.getProjection(); + int widthPx = panel.getGraphWidth(); + int heightPx = panel.getGraphHeight(); + int insetPx = panel.getInset(); + + for (final Event event : events.values()) { + Origin origin = event.getPreferredOrigin(); + + Point2D.Double originLoc = new Point2D.Double(origin.getLongitude(), origin.getLatitude()); + if (!range.contains(originLoc)) { + continue; + } + + final Point2D.Double xy = projection.forward(originLoc); + + final double[] ext = range.getProjectedExtents(projection); + final double dx = (ext[1] - ext[0]); + final double dy = (ext[3] - ext[2]); + final Point2D.Double res = new Point2D.Double(); + res.x = (((xy.x - ext[0]) / dx) * widthPx + insetPx); + res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); + + g2.translate(res.x, res.y); + + double mag = event.getPerferredMagnitude().getMag(); + float diameter = (float) (2.5 + mag * 9 / 2.5); + diameter = Math.min(diameter, 10); + diameter = Math.max(diameter, 1); + + long age = J2kSec.asEpoch(J2kSec.now()) - origin.getTime(); + renderer.shape = new Ellipse2D.Float(0f, 0f, diameter, diameter); + if (event == hoverEvent) { + renderer.paint = Color.GREEN; + } else if (age < ONE_HOUR) { + renderer.paint = Color.RED; + } else if (age < ONE_DAY) { + renderer.paint = Color.CYAN; + } else if (age < ONE_WEEK) { + renderer.paint = Color.YELLOW; + } else { + renderer.paint = Color.WHITE; + } + renderer.renderAtOrigin(g2); + + if (event == hoverEvent) { + } + g2.translate(-res.x, -res.y); + } + + drawPopup(g2); + } + + private void drawPopup(Graphics2D g2) { + if (hoverEvent == null) { + return; + } + Origin origin = hoverEvent.getPreferredOrigin(); + GeoRange range = panel.getRange(); + Projection projection = panel.getProjection(); + List text = generatePopupText(origin); + + FontMetrics fm = g2.getFontMetrics(); + int popupHeight = 2 * POPUP_PADDING; + int popupWidth = 0; + for (String string : text) { + Rectangle2D bounds = fm.getStringBounds(string, g2); + popupHeight += (int) (Math.ceil(bounds.getHeight()) + 2); + popupWidth = Math.max(popupWidth, (int) (Math.ceil(bounds.getWidth()) + 2 * POPUP_PADDING)); + } + + int widthPx = panel.getGraphWidth(); + int heightPx = panel.getGraphHeight(); + int insetPx = panel.getInset(); + + final Point2D.Double xy = projection.forward(new Point2D.Double(origin.getLongitude(), origin.getLatitude())); + final double[] ext = range.getProjectedExtents(projection); + final double dx = (ext[1] - ext[0]); + final double dy = (ext[3] - ext[2]); + final Point2D.Double res = new Point2D.Double(); + + res.x = (((xy.x - ext[0]) / dx) * widthPx + insetPx); + int maxX = widthPx - popupWidth + POPUP_PADDING; + res.x = Math.min(res.x, maxX); + + res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); + if (res.y < (insetPx + popupHeight)) { + res.y += popupHeight; + } + + g2.translate(res.x, res.y); + + g2.setStroke(new BasicStroke(1.2f)); + g2.setColor(new Color(0, 0, 0, 128)); + g2.drawRect(0, -(popupHeight - POPUP_PADDING), popupWidth, popupHeight); + g2.fillRect(0, -(popupHeight - POPUP_PADDING), popupWidth, popupHeight); + + g2.setColor(Color.WHITE); + int baseY = POPUP_PADDING; + for (String string : text) { + g2.drawString(string, POPUP_PADDING, -baseY); + Rectangle2D bounds = fm.getStringBounds(string, g2); + baseY += (int) (Math.ceil(bounds.getHeight()) + 2); + } + g2.translate(-res.x, -res.y); + + } + + private List generatePopupText(Origin origin) { + List text = new ArrayList(3); + + Magnitude magElement = hoverEvent.getPerferredMagnitude(); + String mag = String.format("%.2f %s at %.2f km depth", magElement.getMag(), magElement.getType(), + (origin.getDepth() / 1000)); + text.add(mag); + + String date = Time.format(Time.STANDARD_TIME_FORMAT, new Date(origin.getTime())); + text.add(date + " UTC"); + + String description = hoverEvent.getDescription(); + text.add(description); + + return text; + } + + public boolean mouseClicked(final MouseEvent e) { + + hoverEvent = null; + if (events.size() < 1l) { + return false; + } + + GeoRange range = panel.getRange(); + Projection projection = panel.getProjection(); + int widthPx = panel.getGraphWidth(); + int heightPx = panel.getGraphHeight(); + int insetPx = panel.getInset(); + + Iterator it = events.values().iterator(); + boolean handled = false; + while (it.hasNext() && handled == false) { + Event event = it.next(); + Origin origin = event.getPreferredOrigin(); + final Rectangle r = new Rectangle(-7, -7, 17, 17); + + final Point2D.Double xy = projection + .forward(new Point2D.Double(origin.getLongitude(), origin.getLatitude())); + final double[] ext = range.getProjectedExtents(projection); + final double dx = (ext[1] - ext[0]); + final double dy = (ext[3] - ext[2]); + final Point2D.Double res = new Point2D.Double(); + res.x = (((xy.x - ext[0]) / dx) * widthPx + insetPx); + res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); + + r.translate((int) res.x, (int) res.y); + + if (r.contains(e.getPoint())) { + LOGGER.debug("event clicked"); + Swarm.openEvent(event); + return true; + } + } + + return handled; + } + + public void settingsChanged() { + LOGGER.debug("hypocenter plotter sees changed settings."); + HypocenterSource hypocenterSource = swarmConfig.getHypocenterSource(); + if (quakemlSource == null) { + return; + } + try { + quakemlSource.stop(); + quakemlSource = new QuakemlSource(new URL(hypocenterSource.getUrl()), (long) REFRESH_INTERVAL); + quakemlSource.addObserver(this); + update(quakemlSource); + } catch (MalformedURLException ex) { + LOGGER.error("Unable to load hypocenter URL.", ex); + } + } + + public void stop() { + run = false; + } + + public boolean mouseMoved(MouseEvent e) { + if (events.size() < 1) { + return false; + } + + GeoRange range = panel.getRange(); + Projection projection = panel.getProjection(); + if (projection == null) { + return false; + } + + int widthPx = panel.getGraphWidth(); + int heightPx = panel.getGraphHeight(); + int insetPx = panel.getInset(); + + Iterator it = events.values().iterator(); + boolean handled = false; + while (it.hasNext() && handled == false) { + Event event = it.next(); + Origin origin = event.getPreferredOrigin(); + if (origin == null) { + continue; + } + + Point2D.Double originLoc = new Point2D.Double(origin.getLongitude(), origin.getLatitude()); + if (!range.contains(originLoc)) { + continue; + } + + final Rectangle r = new Rectangle(0, 0, 10, 10); + + final Point2D.Double xy = projection + .forward(new Point2D.Double(origin.getLongitude(), origin.getLatitude())); + final double[] ext = range.getProjectedExtents(projection); + final double dx = (ext[1] - ext[0]); + final double dy = (ext[3] - ext[2]); + final Point2D.Double res = new Point2D.Double(); + res.x = (((xy.x - ext[0]) / dx) * widthPx + insetPx); + res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); + + r.translate((int) res.x, (int) res.y); + if (r.contains(e.getPoint())) { + LOGGER.debug("set hover event {}", event.publicId); + hoverEvent = event; + handled = true; + } else if (event == hoverEvent) { + LOGGER.debug("unset hover event {}", event.publicId); + + hoverEvent = null; + hoverLocation = e.getPoint(); + handled = true; + } + } + return handled; + } + + public void update(QuakemlSource source) { + events.clear(); + events.putAll(source.getEventSet()); + if (MapFrame.getInstance() != null) { + MapFrame.getInstance().repaint(); + } + } } From 6366adbebf8cdce15624074413effd598c999040 Mon Sep 17 00:00:00 2001 From: tparker Date: Wed, 7 Dec 2016 15:11:00 -0900 Subject: [PATCH 36/67] Add timezone to event panel --- .../java/gov/usgs/volcanoes/swarm/event/ParameterPanel.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/ParameterPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/event/ParameterPanel.java index 3595ca4c..8f5269d1 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/ParameterPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/ParameterPanel.java @@ -14,6 +14,7 @@ import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.text.SimpleDateFormat; +import java.util.TimeZone; import javax.swing.JLabel; import javax.swing.JPanel; @@ -71,7 +72,8 @@ public static Component create(Event event) { c.gridy++; addKey("Origin date: ", parameterPanel, c); - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z"); + dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); String date = dateFormat.format(event.getPreferredOrigin().getTime()); addValue(date, parameterPanel, c); From e962192303c9750e66381a51d23654c5224c5670 Mon Sep 17 00:00:00 2001 From: tparker Date: Thu, 8 Dec 2016 10:13:26 -0900 Subject: [PATCH 37/67] Shrink hypocenter outline to 1px --- .../usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java index 4f147cdf..882d7ac3 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java @@ -71,7 +71,7 @@ public HypocenterLayer() throws MalformedURLException { renderer = new DataPointRenderer(); renderer.antiAlias = true; - renderer.stroke = new BasicStroke(2f); + renderer.stroke = new BasicStroke(1f); renderer.filled = true; renderer.color = Color.BLACK; // r.shape = Geometry.STAR_10; From 30de488ee0393a9aac52575bc79674645e90e193 Mon Sep 17 00:00:00 2001 From: tparker Date: Thu, 8 Dec 2016 16:24:50 -0900 Subject: [PATCH 38/67] Add transparency to markers and use presets for scaled size --- .../map/hypocenters/HypocenterLayer.java | 44 ++++++++++++++----- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java index 882d7ac3..334ac02f 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java @@ -120,27 +120,51 @@ public void draw(Graphics2D g2) { g2.translate(res.x, res.y); double mag = event.getPerferredMagnitude().getMag(); - float diameter = (float) (2.5 + mag * 9 / 2.5); - diameter = Math.min(diameter, 10); - diameter = Math.max(diameter, 1); + float diameter; + // float diameter = (float) (2.5 + mag * 9 / 2.5); + // diameter = Math.min(diameter, 10); + // diameter = Math.max(diameter, 1); + + if (mag > 7) { + diameter = 25; + } else if (mag > 6) { + diameter = 21; + } else if (mag > 5) { + diameter = 17; + } else if (mag > 4) { + diameter = 13; + } else if (mag > 3) { + diameter = 11; + } else if (mag > 2) { + diameter = 9; + } else if (mag > 1) { + diameter = 7; + } else { + diameter = 5; + } long age = J2kSec.asEpoch(J2kSec.now()) - origin.getTime(); renderer.shape = new Ellipse2D.Float(0f, 0f, diameter, diameter); + Color markerColor; if (event == hoverEvent) { - renderer.paint = Color.GREEN; + markerColor = Color.GREEN; } else if (age < ONE_HOUR) { - renderer.paint = Color.RED; + markerColor = Color.RED; } else if (age < ONE_DAY) { - renderer.paint = Color.CYAN; + // renderer.paint = Color.CYAN; + markerColor = Color.ORANGE; } else if (age < ONE_WEEK) { - renderer.paint = Color.YELLOW; + markerColor = Color.YELLOW; } else { - renderer.paint = Color.WHITE; + markerColor = Color.WHITE; } + + int alpha = 0x80FFFFFF; + renderer.paint = new Color(alpha & markerColor.getRGB(), true); renderer.renderAtOrigin(g2); - if (event == hoverEvent) { - } +// if (event == hoverEvent) { +// } g2.translate(-res.x, -res.y); } From 50ee418a2a677a557f29b221aeb906e36d8bfed0 Mon Sep 17 00:00:00 2001 From: tparker Date: Fri, 27 Jan 2017 15:30:52 -0900 Subject: [PATCH 39/67] Update map in dedicated thread. --- .../volcanoes/swarm/event/EventFrame.java | 2 +- .../usgs/volcanoes/swarm/map/MapFrame.java | 1070 ++++++++--------- .../usgs/volcanoes/swarm/map/MapLayer.java | 2 +- .../usgs/volcanoes/swarm/map/MapPanel.java | 13 + .../map/hypocenters/HypocenterLayer.java | 129 +- 5 files changed, 591 insertions(+), 625 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java index c2b7adae..5b7dae59 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/event/EventFrame.java @@ -72,7 +72,7 @@ public class EventFrame extends SwarmFrame implements EventObserver { * @param event Event to display */ public EventFrame(Event event) { - super("Event - " + event.getEvid(), true, true, true, false); + super("Event - " + event.getEventSource() + event.getEvid(), true, true, true, false); this.event = event; event.addObserver(this); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapFrame.java index 06c6b3d3..bcf46181 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapFrame.java @@ -63,543 +63,535 @@ * @author Dan Cervelli */ public class MapFrame extends SwarmFrame implements Runnable, Kioskable, SwarmOptionsListener { - private static final long serialVersionUID = 1L; - private static final Logger LOGGER = LoggerFactory.getLogger(MapFrame.class); - - - private JToolBar toolbar; - private JPanel mainPanel; - private JButton optionsButton; - private JButton labelButton; - private JLabel statusLabel; - private JToggleButton linkButton; - private JToggleButton realtimeButton; - private JButton compXButton; - private JButton expXButton; - private JButton forwardTimeButton; - private JButton backTimeButton; - private JButton gotoButton; - private JButton timeHistoryButton; - private JButton captureButton; - private JButton clipboardButton; - - private JToggleButton dragButton; - private JToggleButton dragZoomButton; - private JToggleButton rulerButton; - - private WaveViewSettingsToolbar waveToolbar; - private WaveViewPanel selected; - - private final Thread updateThread; - - private MapPanel mapPanel; - - private Throbber throbber; - - private int spanIndex = 3; - private boolean realtime = true; - - private long refreshInterval = 1000; - - private HelicorderViewPanelListener linkListener; - - private boolean heliLinked = true; - - private Border border; - - private MapSettingsDialog mapSettingsDialog; - - private MapFrame() { - super("Map", true, true, true, false); - this.setFocusable(true); - UiTime.touchTime(); - - mapSettingsDialog = new MapSettingsDialog(this); - - createUI(); - addLayers(); - - updateThread = new Thread(this, "Map Update"); - updateThread.start(); - SwarmOptions.addOptionsListener(this); - } - - private void addLayers() { - MapLayer mapLayer; - try { - mapLayer = new HypocenterLayer(); - mapLayer.setMapPanel(mapPanel); - addLayer(mapLayer); - } catch (MalformedURLException ex) { - LOGGER.error("Unable to load layer. {}", ex); - } - } - - public static MapFrame getInstance() { - return MapFrameHolder.mapFrame; - } - - @Override - public void saveLayout(final ConfigFile cf, final String prefix) { - super.saveLayout(cf, prefix); - mapPanel.saveLayout(cf, prefix + ".panel"); - } - - public void processLayout(final ConfigFile cf) { - processStandardLayout(cf); - mapPanel.processLayout(cf.getSubConfig("panel")); - final LabelSetting ls = mapPanel.getLabelSetting(); - labelButton.setIcon(ls.getIcon()); - } - - private void createUI() { - setFrameIcon(Icons.earth); - setSize(swarmConfig.mapWidth, swarmConfig.mapHeight); - setLocation(swarmConfig.mapX, swarmConfig.mapY); - setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - - mainPanel = new JPanel(new BorderLayout()); - - createToolbar(); - - mainPanel.add(toolbar, BorderLayout.NORTH); - - mapPanel = new MapPanel(); - - border = BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(0, 2, 0, 3), - LineBorder.createGrayLineBorder()); - mapPanel.setBorder(border); - mainPanel.add(mapPanel, BorderLayout.CENTER); - statusLabel = new JLabel(" "); - statusLabel.setBorder(BorderFactory.createEmptyBorder(1, 5, 1, 1)); - mainPanel.add(statusLabel, BorderLayout.SOUTH); - setContentPane(mainPanel); - - this.addComponentListener(new ComponentAdapter() { - @Override - public void componentShown(final ComponentEvent e) { - if (!mapPanel.imageValid()) - mapPanel.resetImage(); - } - }); - - this.addInternalFrameListener(new InternalFrameAdapter() { - @Override - public void internalFrameClosing(final InternalFrameEvent e) { - setVisible(false); - } - }); - - linkListener = new HelicorderViewPanelListener() { - public void insetCreated(final double st, final double et) { - if (heliLinked) { - if (!realtime) - mapPanel.timePush(); - - setRealtime(false); - mapPanel.setTimes(st, et, true); - } - } - }; - - setVisible(true); - } - - @Override - public void setVisible(final boolean isVisible) { - super.setVisible(isVisible); - if (isVisible) - toFront(); - } - - @Override - public void setMaximum(final boolean max) throws PropertyVetoException { - if (max) { - swarmConfig.mapX = getX(); - swarmConfig.mapY = getY(); - } - super.setMaximum(max); - } - - public GeoRange getRange() { - return mapPanel.getRange(); - } - - private void createToolbar() { - toolbar = SwarmUtil.createToolBar(); - optionsButton = - SwarmUtil.createToolBarButton(Icons.settings, "Map options", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - mapSettingsDialog.setToCurrent(); - mapSettingsDialog.setVisible(true); - } - }); - toolbar.add(optionsButton); - - labelButton = SwarmUtil.createToolBarButton(Icons.label_some, "Change label settings", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - final LabelSetting ls = mapPanel.getLabelSetting().next(); - labelButton.setIcon(ls.getIcon()); - mapPanel.setLabelSetting(ls); - } - }); - toolbar.add(labelButton); - - toolbar.addSeparator(); - - realtimeButton = - SwarmUtil.createToolBarToggleButton(Icons.clock, "Realtime mode (N)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - setRealtime(realtimeButton.isSelected()); - } - }); - UiUtils.mapKeyStrokeToButton(this, "N", "realtime", realtimeButton); - realtimeButton.setSelected(realtime); - toolbar.add(realtimeButton); - - linkButton = SwarmUtil.createToolBarToggleButton(Icons.helilink, - "Synchronize times with helicorder wave (H)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - heliLinked = linkButton.isSelected(); - } - }); - UiUtils.mapKeyStrokeToButton(this, "H", "helilink", linkButton); - linkButton.setSelected(heliLinked); - toolbar.add(linkButton); - - toolbar.addSeparator(); - - final JButton earthButton = SwarmUtil.createToolBarButton(Icons.earth, - "Zoom out to full scale (Home)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - final Point2D.Double c = new Point2D.Double(mapPanel.getCenter().x, 0); - mapPanel.setCenterAndScale(c, 100000); - } - }); - UiUtils.mapKeyStrokeToButton(this, "HOME", "home", earthButton); - toolbar.add(earthButton); - - dragButton = - SwarmUtil.createToolBarToggleButton(Icons.drag, "Drag map (D)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - mapPanel.setDragMode(DragMode.DRAG_MAP); - } - }); - UiUtils.mapKeyStrokeToButton(this, "D", "drag", dragButton); - dragButton.setSelected(true); - toolbar.add(dragButton); - - dragZoomButton = SwarmUtil.createToolBarToggleButton(Icons.dragbox, "Zoom into box (B)", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - mapPanel.setDragMode(DragMode.BOX); - } - }); - UiUtils.mapKeyStrokeToButton(this, "B", "box", dragZoomButton); - dragZoomButton.setSelected(false); - toolbar.add(dragZoomButton); - - rulerButton = SwarmUtil.createToolBarToggleButton(Icons.ruler, "Measure distances (M)", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - mapPanel.setDragMode(DragMode.RULER); - } - }); - UiUtils.mapKeyStrokeToButton(this, "M", "measure", rulerButton); - toolbar.add(rulerButton); - toolbar.addSeparator(); - - final ButtonGroup group = new ButtonGroup(); - group.add(dragButton); - group.add(dragZoomButton); - group.add(rulerButton); - - final JButton zoomIn = - SwarmUtil.createToolBarButton(Icons.zoomplus, "Zoom in (+)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - mapPanel.zoom(0.5); - } - }); - UiUtils.mapKeyStrokeToButton(this, "EQUALS", "zoomin1", zoomIn); - UiUtils.mapKeyStrokeToButton(this, "shift EQUALS", "zoomin2", zoomIn); - toolbar.add(zoomIn); - - final JButton zoomOut = - SwarmUtil.createToolBarButton(Icons.zoomminus, "Zoom out (-)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - mapPanel.zoom(2); - } - }); - UiUtils.mapKeyStrokeToButton(this, "MINUS", "zoomout1", zoomOut); - toolbar.add(zoomOut); - - final JButton backButton = SwarmUtil.createToolBarButton(Icons.geoback, - "Last map view (Ctrl-backspace)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - mapPanel.mapPop(); - } - }); - UiUtils.mapKeyStrokeToButton(this, "ctrl BACK_SPACE", "mapback1", backButton); - toolbar.add(backButton); - - toolbar.addSeparator(); - - backTimeButton = SwarmUtil.createToolBarButton(Icons.left, "Scroll back time 20% (Left arrow)", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - setRealtime(false); - mapPanel.shiftTime(-0.20); - } - }); - UiUtils.mapKeyStrokeToButton(this, "LEFT", "backward1", backTimeButton); - toolbar.add(backTimeButton); - - forwardTimeButton = SwarmUtil.createToolBarButton(Icons.right, - "Scroll forward time 20% (Right arrow)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - setRealtime(false); - mapPanel.shiftTime(0.20); - } - }); - toolbar.add(forwardTimeButton); - UiUtils.mapKeyStrokeToButton(this, "RIGHT", "forward1", forwardTimeButton); - - gotoButton = - SwarmUtil.createToolBarButton(Icons.gototime, "Go to time (Ctrl-G)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - String t = JOptionPane.showInputDialog(applicationFrame, - "Input time in 'YYYYMMDDhhmm[ss]' format:", "Go to Time", - JOptionPane.PLAIN_MESSAGE); - if (t != null) { - if (t.length() == 12) - t = t + "30"; - - double j2k; - - try { - j2k = J2kSec.parse("yyyyMMddHHmmss", t); - setRealtime(false); - mapPanel.gotoTime(j2k); - } catch (final ParseException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - } - } - }); - toolbar.add(gotoButton); - UiUtils.mapKeyStrokeToButton(this, "ctrl G", "goto", gotoButton); - - compXButton = SwarmUtil.createToolBarButton(Icons.xminus, "Shrink time axis (Alt-left arrow", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - if (realtime) { - if (spanIndex != 0) - spanIndex--; - } else { - mapPanel.scaleTime(0.20); - } - } - }); - toolbar.add(compXButton); - UiUtils.mapKeyStrokeToButton(this, "alt LEFT", "compx", compXButton); - - expXButton = SwarmUtil.createToolBarButton(Icons.xplus, "Expand time axis (Alt-right arrow)", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - if (realtime) { - if (spanIndex < MultiMonitor.SPANS.length - 1) - spanIndex++; - } else { - mapPanel.scaleTime(-0.20); - } - } - }); - toolbar.add(expXButton); - UiUtils.mapKeyStrokeToButton(this, "alt RIGHT", "expx", expXButton); - - timeHistoryButton = SwarmUtil.createToolBarButton(Icons.timeback, - "Last time settings (Backspace)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - if (mapPanel.timePop()) - setRealtime(false); - } - }); - UiUtils.mapKeyStrokeToButton(this, "BACK_SPACE", "back", timeHistoryButton); - toolbar.add(timeHistoryButton); - toolbar.addSeparator(); - - waveToolbar = new WaveViewSettingsToolbar(null, toolbar, this); - - clipboardButton = SwarmUtil.createToolBarButton(Icons.clipboard, - "Copy inset to clipboard (C or Ctrl-C)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - mapPanel.wavesToClipboard(); - } - }); - UiUtils.mapKeyStrokeToButton(this, "control C", "clipboard1", clipboardButton); - UiUtils.mapKeyStrokeToButton(this, "C", "clipboard2", clipboardButton); - toolbar.add(clipboardButton); - - toolbar.addSeparator(); - - captureButton = SwarmUtil.createToolBarButton(Icons.camera, "Save map image (P)", - new CaptureActionListener()); - UiUtils.mapKeyStrokeToButton(this, "P", "capture", captureButton); - toolbar.add(captureButton); - - toolbar.addSeparator(); - - toolbar.add(Box.createHorizontalGlue()); - throbber = new Throbber(); - toolbar.add(throbber); - } - - class CaptureActionListener implements ActionListener { - public void actionPerformed(final ActionEvent e) { - final JFileChooser chooser = FileChooser.getFileChooser(); - final File lastPath = new File(swarmConfig.lastPath); - chooser.setCurrentDirectory(lastPath); - chooser.setSelectedFile(new File("map.png")); - chooser.setDialogTitle("Save Map Screen Capture"); - final int result = chooser.showSaveDialog(applicationFrame); - File f = null; - if (result == JFileChooser.APPROVE_OPTION) { - f = chooser.getSelectedFile(); - - if (f.exists()) { - final int choice = JOptionPane.showConfirmDialog(applicationFrame, - "File exists, overwrite?", "Confirm", JOptionPane.YES_NO_OPTION); - if (choice != JOptionPane.YES_OPTION) - return; - } - swarmConfig.lastPath = f.getParent(); - } - if (f == null) - return; - - final Insets i = mapPanel.getInsets(); - final BufferedImage image = new BufferedImage(mapPanel.getWidth() - i.left - i.right, - mapPanel.getHeight() - i.top - i.bottom, BufferedImage.TYPE_4BYTE_ABGR); - final Graphics g = image.getGraphics(); - g.translate(-i.left, -i.top); - mapPanel.paint(g); - try { - final PngEncoderB png = new PngEncoderB(image, false, PngEncoder.FILTER_NONE, 7); - final FileOutputStream out = new FileOutputStream(f); - final byte[] bytes = png.pngEncode(); - out.write(bytes); - out.close(); - } catch (final Exception ex) { - ex.printStackTrace(); - } - } - } - - public void setRealtime(final boolean b) { - realtime = b; - realtimeButton.setSelected(realtime); - } - - public Throbber getThrobber() { - return throbber; - } - - public void setRefreshInterval(final long r) { - refreshInterval = r; - } - - public long getRefreshInterval() { - return refreshInterval; - } - - public MapPanel getMapPanel() { - return mapPanel; - } - - public void setSelectedWave(final WaveViewPanel wvp) { - selected = wvp; - waveToolbar.setSettings(selected.getSettings()); - } - - public void setView(final GeoRange gr) { - final double lr1 = gr.getLonRange(); - final double lr2 = GeoRange.getLonRange(gr.getEast(), gr.getWest()); - if (lr2 < lr1) - gr.flipEastWest(); - - mapPanel.setCenterAndScale(gr); - } - - public void setStatusText(final String t) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - String missing = ""; - if (mapPanel.getMissing() == 1) - missing = "(" + mapPanel.getMissing() + " channel hidden) "; - else if (mapPanel.getMissing() > 1) - missing = "(" + mapPanel.getMissing() + " channels hidden) "; - statusLabel.setText(missing + t); - statusLabel.repaint(); - } - }); - } - - public void reloadImages() { - mapPanel.loadMaps(true); - } - - public void reset(final boolean doMap) { - mapPanel.resetImage(doMap); - } - - public void mapSettingsChanged() { - mapPanel.loadMaps(true); - } - - public HelicorderViewPanelListener getLinkListener() { - return linkListener; - } - - public void setKioskMode(final boolean b) { - setDefaultKioskMode(b); - if (fullScreen) { - mainPanel.remove(toolbar); - mapPanel.setBorder(null); - } else { - mainPanel.add(toolbar, BorderLayout.NORTH); - mapPanel.setBorder(border); - } - } - - public MapPanel addLayer(MapLayer layer) { - mapPanel.addLayer(layer); - - return mapPanel; - } - - public void run() { - while (true) { - try { - if (this.isVisible() && realtime) { - final double end = J2kSec.now(); - final double start = end - MultiMonitor.SPANS[spanIndex]; - mapPanel.setTimes(start, end, false); - } - - Thread.sleep(refreshInterval); - } catch (final Throwable e) { - e.printStackTrace(); - } - } - } - - public void optionsChanged() { - reloadImages(); - } - - private static class MapFrameHolder { - public static MapFrame mapFrame = new MapFrame(); - } + private static final long serialVersionUID = 1L; + private static final Logger LOGGER = LoggerFactory.getLogger(MapFrame.class); + + private JToolBar toolbar; + private JPanel mainPanel; + private JButton optionsButton; + private JButton labelButton; + private JLabel statusLabel; + private JToggleButton linkButton; + private JToggleButton realtimeButton; + private JButton compXButton; + private JButton expXButton; + private JButton forwardTimeButton; + private JButton backTimeButton; + private JButton gotoButton; + private JButton timeHistoryButton; + private JButton captureButton; + private JButton clipboardButton; + + private JToggleButton dragButton; + private JToggleButton dragZoomButton; + private JToggleButton rulerButton; + + private WaveViewSettingsToolbar waveToolbar; + private WaveViewPanel selected; + + private final Thread updateThread; + + private MapPanel mapPanel; + + private Throbber throbber; + + private int spanIndex = 3; + private boolean realtime = true; + + private long refreshInterval = 1000; + + private HelicorderViewPanelListener linkListener; + + private boolean heliLinked = true; + + private Border border; + + private MapSettingsDialog mapSettingsDialog; + + private MapFrame() { + super("Map", true, true, true, false); + this.setFocusable(true); + UiTime.touchTime(); + + mapSettingsDialog = new MapSettingsDialog(this); + + createUI(); + addLayers(); + + updateThread = new Thread(this, "Map Update"); + updateThread.start(); + SwarmOptions.addOptionsListener(this); + } + + private void addLayers() { + MapLayer mapLayer; + try { + mapLayer = new HypocenterLayer(); + mapLayer.setMapPanel(mapPanel); + addLayer(mapLayer); + } catch (MalformedURLException ex) { + LOGGER.error("Unable to load layer. {}", ex); + } + } + + public static MapFrame getInstance() { + return MapFrameHolder.mapFrame; + } + + @Override + public void saveLayout(final ConfigFile cf, final String prefix) { + super.saveLayout(cf, prefix); + mapPanel.saveLayout(cf, prefix + ".panel"); + } + + public void processLayout(final ConfigFile cf) { + processStandardLayout(cf); + mapPanel.processLayout(cf.getSubConfig("panel")); + final LabelSetting ls = mapPanel.getLabelSetting(); + labelButton.setIcon(ls.getIcon()); + } + + private void createUI() { + setFrameIcon(Icons.earth); + setSize(swarmConfig.mapWidth, swarmConfig.mapHeight); + setLocation(swarmConfig.mapX, swarmConfig.mapY); + setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + + mainPanel = new JPanel(new BorderLayout()); + + createToolbar(); + + mainPanel.add(toolbar, BorderLayout.NORTH); + + mapPanel = new MapPanel(); + + border = BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(0, 2, 0, 3), + LineBorder.createGrayLineBorder()); + mapPanel.setBorder(border); + mainPanel.add(mapPanel, BorderLayout.CENTER); + statusLabel = new JLabel(" "); + statusLabel.setBorder(BorderFactory.createEmptyBorder(1, 5, 1, 1)); + mainPanel.add(statusLabel, BorderLayout.SOUTH); + setContentPane(mainPanel); + + this.addComponentListener(new ComponentAdapter() { + @Override + public void componentShown(final ComponentEvent e) { + if (!mapPanel.imageValid()) + mapPanel.resetImage(); + } + }); + + this.addInternalFrameListener(new InternalFrameAdapter() { + @Override + public void internalFrameClosing(final InternalFrameEvent e) { + setVisible(false); + } + }); + + linkListener = new HelicorderViewPanelListener() { + public void insetCreated(final double st, final double et) { + if (heliLinked) { + if (!realtime) + mapPanel.timePush(); + + setRealtime(false); + mapPanel.setTimes(st, et, true); + } + } + }; + + setVisible(true); + } + + @Override + public void setVisible(final boolean isVisible) { + LOGGER.debug("Frame closing"); + super.setVisible(isVisible); + if (mapPanel != null) { + mapPanel.setVisible(isVisible); + } + if (isVisible) + toFront(); + } + + @Override + public void setMaximum(final boolean max) throws PropertyVetoException { + if (max) { + swarmConfig.mapX = getX(); + swarmConfig.mapY = getY(); + } + super.setMaximum(max); + } + + public GeoRange getRange() { + return mapPanel.getRange(); + } + + private void createToolbar() { + toolbar = SwarmUtil.createToolBar(); + optionsButton = SwarmUtil.createToolBarButton(Icons.settings, "Map options", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + mapSettingsDialog.setToCurrent(); + mapSettingsDialog.setVisible(true); + } + }); + toolbar.add(optionsButton); + + labelButton = SwarmUtil.createToolBarButton(Icons.label_some, "Change label settings", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + final LabelSetting ls = mapPanel.getLabelSetting().next(); + labelButton.setIcon(ls.getIcon()); + mapPanel.setLabelSetting(ls); + } + }); + toolbar.add(labelButton); + + toolbar.addSeparator(); + + realtimeButton = SwarmUtil.createToolBarToggleButton(Icons.clock, "Realtime mode (N)", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setRealtime(realtimeButton.isSelected()); + } + }); + UiUtils.mapKeyStrokeToButton(this, "N", "realtime", realtimeButton); + realtimeButton.setSelected(realtime); + toolbar.add(realtimeButton); + + linkButton = SwarmUtil.createToolBarToggleButton(Icons.helilink, "Synchronize times with helicorder wave (H)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + heliLinked = linkButton.isSelected(); + } + }); + UiUtils.mapKeyStrokeToButton(this, "H", "helilink", linkButton); + linkButton.setSelected(heliLinked); + toolbar.add(linkButton); + + toolbar.addSeparator(); + + final JButton earthButton = SwarmUtil.createToolBarButton(Icons.earth, "Zoom out to full scale (Home)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + final Point2D.Double c = new Point2D.Double(mapPanel.getCenter().x, 0); + mapPanel.setCenterAndScale(c, 100000); + } + }); + UiUtils.mapKeyStrokeToButton(this, "HOME", "home", earthButton); + toolbar.add(earthButton); + + dragButton = SwarmUtil.createToolBarToggleButton(Icons.drag, "Drag map (D)", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + mapPanel.setDragMode(DragMode.DRAG_MAP); + } + }); + UiUtils.mapKeyStrokeToButton(this, "D", "drag", dragButton); + dragButton.setSelected(true); + toolbar.add(dragButton); + + dragZoomButton = SwarmUtil.createToolBarToggleButton(Icons.dragbox, "Zoom into box (B)", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + mapPanel.setDragMode(DragMode.BOX); + } + }); + UiUtils.mapKeyStrokeToButton(this, "B", "box", dragZoomButton); + dragZoomButton.setSelected(false); + toolbar.add(dragZoomButton); + + rulerButton = SwarmUtil.createToolBarToggleButton(Icons.ruler, "Measure distances (M)", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + mapPanel.setDragMode(DragMode.RULER); + } + }); + UiUtils.mapKeyStrokeToButton(this, "M", "measure", rulerButton); + toolbar.add(rulerButton); + toolbar.addSeparator(); + + final ButtonGroup group = new ButtonGroup(); + group.add(dragButton); + group.add(dragZoomButton); + group.add(rulerButton); + + final JButton zoomIn = SwarmUtil.createToolBarButton(Icons.zoomplus, "Zoom in (+)", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + mapPanel.zoom(0.5); + } + }); + UiUtils.mapKeyStrokeToButton(this, "EQUALS", "zoomin1", zoomIn); + UiUtils.mapKeyStrokeToButton(this, "shift EQUALS", "zoomin2", zoomIn); + toolbar.add(zoomIn); + + final JButton zoomOut = SwarmUtil.createToolBarButton(Icons.zoomminus, "Zoom out (-)", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + mapPanel.zoom(2); + } + }); + UiUtils.mapKeyStrokeToButton(this, "MINUS", "zoomout1", zoomOut); + toolbar.add(zoomOut); + + final JButton backButton = SwarmUtil.createToolBarButton(Icons.geoback, "Last map view (Ctrl-backspace)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + mapPanel.mapPop(); + } + }); + UiUtils.mapKeyStrokeToButton(this, "ctrl BACK_SPACE", "mapback1", backButton); + toolbar.add(backButton); + + toolbar.addSeparator(); + + backTimeButton = SwarmUtil.createToolBarButton(Icons.left, "Scroll back time 20% (Left arrow)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setRealtime(false); + mapPanel.shiftTime(-0.20); + } + }); + UiUtils.mapKeyStrokeToButton(this, "LEFT", "backward1", backTimeButton); + toolbar.add(backTimeButton); + + forwardTimeButton = SwarmUtil.createToolBarButton(Icons.right, "Scroll forward time 20% (Right arrow)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setRealtime(false); + mapPanel.shiftTime(0.20); + } + }); + toolbar.add(forwardTimeButton); + UiUtils.mapKeyStrokeToButton(this, "RIGHT", "forward1", forwardTimeButton); + + gotoButton = SwarmUtil.createToolBarButton(Icons.gototime, "Go to time (Ctrl-G)", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + String t = JOptionPane.showInputDialog(applicationFrame, "Input time in 'YYYYMMDDhhmm[ss]' format:", + "Go to Time", JOptionPane.PLAIN_MESSAGE); + if (t != null) { + if (t.length() == 12) + t = t + "30"; + + double j2k; + + try { + j2k = J2kSec.parse("yyyyMMddHHmmss", t); + setRealtime(false); + mapPanel.gotoTime(j2k); + } catch (final ParseException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } + } + }); + toolbar.add(gotoButton); + UiUtils.mapKeyStrokeToButton(this, "ctrl G", "goto", gotoButton); + + compXButton = SwarmUtil.createToolBarButton(Icons.xminus, "Shrink time axis (Alt-left arrow", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + if (realtime) { + if (spanIndex != 0) + spanIndex--; + } else { + mapPanel.scaleTime(0.20); + } + } + }); + toolbar.add(compXButton); + UiUtils.mapKeyStrokeToButton(this, "alt LEFT", "compx", compXButton); + + expXButton = SwarmUtil.createToolBarButton(Icons.xplus, "Expand time axis (Alt-right arrow)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + if (realtime) { + if (spanIndex < MultiMonitor.SPANS.length - 1) + spanIndex++; + } else { + mapPanel.scaleTime(-0.20); + } + } + }); + toolbar.add(expXButton); + UiUtils.mapKeyStrokeToButton(this, "alt RIGHT", "expx", expXButton); + + timeHistoryButton = SwarmUtil.createToolBarButton(Icons.timeback, "Last time settings (Backspace)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + if (mapPanel.timePop()) + setRealtime(false); + } + }); + UiUtils.mapKeyStrokeToButton(this, "BACK_SPACE", "back", timeHistoryButton); + toolbar.add(timeHistoryButton); + toolbar.addSeparator(); + + waveToolbar = new WaveViewSettingsToolbar(null, toolbar, this); + + clipboardButton = SwarmUtil.createToolBarButton(Icons.clipboard, "Copy inset to clipboard (C or Ctrl-C)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + mapPanel.wavesToClipboard(); + } + }); + UiUtils.mapKeyStrokeToButton(this, "control C", "clipboard1", clipboardButton); + UiUtils.mapKeyStrokeToButton(this, "C", "clipboard2", clipboardButton); + toolbar.add(clipboardButton); + + toolbar.addSeparator(); + + captureButton = SwarmUtil.createToolBarButton(Icons.camera, "Save map image (P)", new CaptureActionListener()); + UiUtils.mapKeyStrokeToButton(this, "P", "capture", captureButton); + toolbar.add(captureButton); + + toolbar.addSeparator(); + + toolbar.add(Box.createHorizontalGlue()); + throbber = new Throbber(); + toolbar.add(throbber); + } + + class CaptureActionListener implements ActionListener { + public void actionPerformed(final ActionEvent e) { + final JFileChooser chooser = FileChooser.getFileChooser(); + final File lastPath = new File(swarmConfig.lastPath); + chooser.setCurrentDirectory(lastPath); + chooser.setSelectedFile(new File("map.png")); + chooser.setDialogTitle("Save Map Screen Capture"); + final int result = chooser.showSaveDialog(applicationFrame); + File f = null; + if (result == JFileChooser.APPROVE_OPTION) { + f = chooser.getSelectedFile(); + + if (f.exists()) { + final int choice = JOptionPane.showConfirmDialog(applicationFrame, "File exists, overwrite?", + "Confirm", JOptionPane.YES_NO_OPTION); + if (choice != JOptionPane.YES_OPTION) + return; + } + swarmConfig.lastPath = f.getParent(); + } + if (f == null) + return; + + final Insets i = mapPanel.getInsets(); + final BufferedImage image = new BufferedImage(mapPanel.getWidth() - i.left - i.right, + mapPanel.getHeight() - i.top - i.bottom, BufferedImage.TYPE_4BYTE_ABGR); + final Graphics g = image.getGraphics(); + g.translate(-i.left, -i.top); + mapPanel.paint(g); + try { + final PngEncoderB png = new PngEncoderB(image, false, PngEncoder.FILTER_NONE, 7); + final FileOutputStream out = new FileOutputStream(f); + final byte[] bytes = png.pngEncode(); + out.write(bytes); + out.close(); + } catch (final Exception ex) { + ex.printStackTrace(); + } + } + } + + public void setRealtime(final boolean b) { + realtime = b; + realtimeButton.setSelected(realtime); + } + + public Throbber getThrobber() { + return throbber; + } + + public void setRefreshInterval(final long r) { + refreshInterval = r; + } + + public long getRefreshInterval() { + return refreshInterval; + } + + public MapPanel getMapPanel() { + return mapPanel; + } + + public void setSelectedWave(final WaveViewPanel wvp) { + selected = wvp; + waveToolbar.setSettings(selected.getSettings()); + } + + public void setView(final GeoRange gr) { + final double lr1 = gr.getLonRange(); + final double lr2 = GeoRange.getLonRange(gr.getEast(), gr.getWest()); + if (lr2 < lr1) + gr.flipEastWest(); + + mapPanel.setCenterAndScale(gr); + } + + public void setStatusText(final String t) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + String missing = ""; + if (mapPanel.getMissing() == 1) + missing = "(" + mapPanel.getMissing() + " channel hidden) "; + else if (mapPanel.getMissing() > 1) + missing = "(" + mapPanel.getMissing() + " channels hidden) "; + statusLabel.setText(missing + t); + statusLabel.repaint(); + } + }); + } + + public void reloadImages() { + mapPanel.loadMaps(true); + } + + public void reset(final boolean doMap) { + mapPanel.resetImage(doMap); + } + + public void mapSettingsChanged() { + mapPanel.loadMaps(true); + } + + public HelicorderViewPanelListener getLinkListener() { + return linkListener; + } + + public void setKioskMode(final boolean b) { + setDefaultKioskMode(b); + if (fullScreen) { + mainPanel.remove(toolbar); + mapPanel.setBorder(null); + } else { + mainPanel.add(toolbar, BorderLayout.NORTH); + mapPanel.setBorder(border); + } + } + + public MapPanel addLayer(MapLayer layer) { + mapPanel.addLayer(layer); + + return mapPanel; + } + + public void run() { + while (true) { + try { + if (this.isVisible() && realtime) { + final double end = J2kSec.now(); + final double start = end - MultiMonitor.SPANS[spanIndex]; + mapPanel.setTimes(start, end, false); + } + + Thread.sleep(refreshInterval); + } catch (final Throwable e) { + e.printStackTrace(); + } + } + } + + public void optionsChanged() { + reloadImages(); + } + + private static class MapFrameHolder { + public static MapFrame mapFrame = new MapFrame(); + } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapLayer.java index 962eac79..8bd5bdcf 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapLayer.java @@ -12,7 +12,7 @@ public interface MapLayer { public void draw(Graphics2D g2); public boolean mouseClicked(MouseEvent e); public void setMapPanel(MapPanel mapPanel); - public void stop(); + public void setVisible(boolean isVisible); public boolean mouseMoved(MouseEvent e); } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java index 4be7c912..570e9a3e 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/MapPanel.java @@ -6,6 +6,7 @@ import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Color; +import java.awt.Container; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Font; @@ -195,6 +196,8 @@ public MapPanel() { final Cursor crosshair = new Cursor(Cursor.CROSSHAIR_CURSOR); this.setCursor(crosshair); createUI(); + + } public void addLayer(MapLayer layer) { @@ -685,6 +688,14 @@ private BufferedImage updateMapRenderer() { return mi; } + @Override + public void setVisible(boolean isVisible) { + for (MapLayer layer : layers) { + layer.setVisible(isVisible); + } + } + + private Pair, List> updateMiniPanels() { final List compsToAdd = new ArrayList(); final List linesToAdd = new ArrayList(); @@ -817,6 +828,7 @@ public Object construct() { return new Boolean(true); } + @Override public void finished() { @@ -1123,6 +1135,7 @@ public void mouseMoved(final MouseEvent e) { } } + public void mouseDragged(final MouseEvent e) { mouseNow = e.getPoint(); diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java index 334ac02f..f007a186 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java @@ -1,13 +1,9 @@ package gov.usgs.volcanoes.swarm.map.hypocenters; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.awt.BasicStroke; import java.awt.Color; import java.awt.FontMetrics; import java.awt.Graphics2D; -import java.awt.Point; import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.awt.geom.Ellipse2D; @@ -15,7 +11,6 @@ import java.awt.geom.Rectangle2D; import java.net.MalformedURLException; import java.net.URL; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; @@ -23,6 +18,9 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import gov.usgs.plot.render.DataPointRenderer; import gov.usgs.proj.GeoRange; import gov.usgs.proj.Projection; @@ -43,29 +41,31 @@ public final class HypocenterLayer implements MapLayer, ConfigListener, QuakemlObserver { private static final Logger LOGGER = LoggerFactory.getLogger(HypocenterLayer.class); private static final int REFRESH_INTERVAL = 5 * 60 * 1000; - private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSX"; private static final int ONE_HOUR = 60 * 60 * 1000; private static final int ONE_DAY = ONE_HOUR * 24; private static final int ONE_WEEK = ONE_DAY * 7; private static final int POPUP_PADDING = 2; - // private List hypocenters; + private static final int[] markerSize = { 5, 7, 9, 11, 13, 17,21, 25}; + + private static final Color ORANGE = new Color(225, 175, 0, 200); + private static final Color RED = new Color(200, 0, 0, 200); + private static final Color YELLOW = new Color(225, 225, 0, 200); + private static final Color WHITE = new Color(200, 200, 200, 200); + private static final Color GREEN = new Color(0, 200, 0, 200); + private final Map events; - private boolean run = true; private MapPanel panel; - private SimpleDateFormat dateFormat; private final SwarmConfig swarmConfig; private final DataPointRenderer renderer; private QuakemlSource quakemlSource; private Event hoverEvent; - private Point hoverLocation; public HypocenterLayer() throws MalformedURLException { events = new ConcurrentHashMap(); - dateFormat = new SimpleDateFormat(DATE_FORMAT); swarmConfig = SwarmConfig.getInstance(); swarmConfig.addListener(this); @@ -74,8 +74,7 @@ public HypocenterLayer() throws MalformedURLException { renderer.stroke = new BasicStroke(1f); renderer.filled = true; renderer.color = Color.BLACK; - // r.shape = Geometry.STAR_10; - renderer.shape = new Ellipse2D.Float(0f, 0f, 5f, 5f); + HypocenterSource hypocenterSource = swarmConfig.getHypocenterSource(); URL quakemlUrl = new URL(hypocenterSource.getUrl()); @@ -121,56 +120,41 @@ public void draw(Graphics2D g2) { double mag = event.getPerferredMagnitude().getMag(); float diameter; - // float diameter = (float) (2.5 + mag * 9 / 2.5); - // diameter = Math.min(diameter, 10); - // diameter = Math.max(diameter, 1); - - if (mag > 7) { - diameter = 25; - } else if (mag > 6) { - diameter = 21; - } else if (mag > 5) { - diameter = 17; - } else if (mag > 4) { - diameter = 13; - } else if (mag > 3) { - diameter = 11; - } else if (mag > 2) { - diameter = 9; - } else if (mag > 1) { - diameter = 7; - } else { - diameter = 5; - } + diameter = getMarkerSize(mag); + long age = J2kSec.asEpoch(J2kSec.now()) - origin.getTime(); renderer.shape = new Ellipse2D.Float(0f, 0f, diameter, diameter); Color markerColor; if (event == hoverEvent) { - markerColor = Color.GREEN; + markerColor = GREEN; } else if (age < ONE_HOUR) { - markerColor = Color.RED; + markerColor = RED; } else if (age < ONE_DAY) { - // renderer.paint = Color.CYAN; - markerColor = Color.ORANGE; + markerColor = ORANGE; } else if (age < ONE_WEEK) { - markerColor = Color.YELLOW; + markerColor = YELLOW; } else { - markerColor = Color.WHITE; + markerColor = WHITE; } - int alpha = 0x80FFFFFF; - renderer.paint = new Color(alpha & markerColor.getRGB(), true); +// int alpha = 0x80FFFFFF; +// renderer.paint = new Color(alpha & markerColor.getRGB(), true); + renderer.paint = markerColor; renderer.renderAtOrigin(g2); -// if (event == hoverEvent) { -// } g2.translate(-res.x, -res.y); } drawPopup(g2); } + private int getMarkerSize(double mag) { + int markerMag = Integer.max((int)mag, 0); + markerMag = Integer.min(markerMag, markerSize.length); + return markerSize[markerMag]; + } + private void drawPopup(Graphics2D g2) { if (hoverEvent == null) { return; @@ -243,47 +227,21 @@ private List generatePopupText(Origin origin) { return text; } + public boolean mouseClicked(final MouseEvent e) { - - hoverEvent = null; - if (events.size() < 1l) { - return false; - } - - GeoRange range = panel.getRange(); - Projection projection = panel.getProjection(); - int widthPx = panel.getGraphWidth(); - int heightPx = panel.getGraphHeight(); - int insetPx = panel.getInset(); - - Iterator it = events.values().iterator(); boolean handled = false; - while (it.hasNext() && handled == false) { - Event event = it.next(); - Origin origin = event.getPreferredOrigin(); - final Rectangle r = new Rectangle(-7, -7, 17, 17); - final Point2D.Double xy = projection - .forward(new Point2D.Double(origin.getLongitude(), origin.getLatitude())); - final double[] ext = range.getProjectedExtents(projection); - final double dx = (ext[1] - ext[0]); - final double dy = (ext[3] - ext[2]); - final Point2D.Double res = new Point2D.Double(); - res.x = (((xy.x - ext[0]) / dx) * widthPx + insetPx); - res.y = ((1 - (xy.y - ext[2]) / dy) * heightPx + insetPx); - - r.translate((int) res.x, (int) res.y); - - if (r.contains(e.getPoint())) { - LOGGER.debug("event clicked"); - Swarm.openEvent(event); - return true; - } + if (hoverEvent != null) { + LOGGER.debug("Opening event {}", hoverEvent.getEvid()); + Swarm.openEvent(hoverEvent); + handled = true; + hoverEvent = null; } - + return handled; } + public void settingsChanged() { LOGGER.debug("hypocenter plotter sees changed settings."); HypocenterSource hypocenterSource = swarmConfig.getHypocenterSource(); @@ -293,6 +251,7 @@ public void settingsChanged() { try { quakemlSource.stop(); quakemlSource = new QuakemlSource(new URL(hypocenterSource.getUrl()), (long) REFRESH_INTERVAL); + quakemlSource.start(); quakemlSource.addObserver(this); update(quakemlSource); } catch (MalformedURLException ex) { @@ -300,10 +259,6 @@ public void settingsChanged() { } } - public void stop() { - run = false; - } - public boolean mouseMoved(MouseEvent e) { if (events.size() < 1) { return false; @@ -323,6 +278,7 @@ public boolean mouseMoved(MouseEvent e) { boolean handled = false; while (it.hasNext() && handled == false) { Event event = it.next(); + Origin origin = event.getPreferredOrigin(); if (origin == null) { continue; @@ -333,7 +289,8 @@ public boolean mouseMoved(MouseEvent e) { continue; } - final Rectangle r = new Rectangle(0, 0, 10, 10); + int markerDiameter = getMarkerSize(event.getPerferredMagnitude().getMag()); + final Rectangle r = new Rectangle(0, 0, markerDiameter, markerDiameter); final Point2D.Double xy = projection .forward(new Point2D.Double(origin.getLongitude(), origin.getLatitude())); @@ -353,7 +310,6 @@ public boolean mouseMoved(MouseEvent e) { LOGGER.debug("unset hover event {}", event.publicId); hoverEvent = null; - hoverLocation = e.getPoint(); handled = true; } } @@ -367,4 +323,9 @@ public void update(QuakemlSource source) { MapFrame.getInstance().repaint(); } } + + public void setVisible(boolean isVisible) { + LOGGER.debug("Setting hypocenter update to {}", isVisible); + quakemlSource.doUpdate(isVisible); + } } From f668de269d26caef5b282193389892ba0a51b944 Mon Sep 17 00:00:00 2001 From: tparker Date: Fri, 27 Jan 2017 15:31:45 -0900 Subject: [PATCH 40/67] Update seisFile dependancy. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 778e8761..c54c4db6 100644 --- a/pom.xml +++ b/pom.xml @@ -494,7 +494,7 @@ edu.sc.seis seisFile - 1.6.3 + 1.7.2 net.alomax From 170059f84c948829b6efb5eb28c511036d945f75 Mon Sep 17 00:00:00 2001 From: tparker Date: Fri, 27 Jan 2017 16:06:50 -0900 Subject: [PATCH 41/67] Handle data source NONE --- .../swarm/map/hypocenters/HypocenterLayer.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java index f007a186..651cab2c 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java @@ -77,11 +77,13 @@ public HypocenterLayer() throws MalformedURLException { HypocenterSource hypocenterSource = swarmConfig.getHypocenterSource(); - URL quakemlUrl = new URL(hypocenterSource.getUrl()); - if (quakemlUrl != null) { - quakemlSource = new QuakemlSource(quakemlUrl, (long) REFRESH_INTERVAL); - quakemlSource.addObserver(this); - update(quakemlSource); + if (hypocenterSource != HypocenterSource.NONE) { + URL quakemlUrl = new URL(hypocenterSource.getUrl()); + if (quakemlUrl != null) { + quakemlSource = new QuakemlSource(quakemlUrl, (long) REFRESH_INTERVAL); + quakemlSource.addObserver(this); + update(quakemlSource); + } } } From a3792e713be4b5b3fa9f924eff3bc99dc2965392 Mon Sep 17 00:00:00 2001 From: tparker Date: Mon, 30 Jan 2017 08:27:43 -0900 Subject: [PATCH 42/67] Correct handing on null and NONE sources --- .../map/hypocenters/HypocenterLayer.java | 43 +++++++++++-------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java index 651cab2c..76edcca8 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java @@ -47,8 +47,8 @@ public final class HypocenterLayer implements MapLayer, ConfigListener, QuakemlO private static final int POPUP_PADDING = 2; - private static final int[] markerSize = { 5, 7, 9, 11, 13, 17,21, 25}; - + private static final int[] markerSize = { 5, 7, 9, 11, 13, 17, 21, 25 }; + private static final Color ORANGE = new Color(225, 175, 0, 200); private static final Color RED = new Color(200, 0, 0, 200); private static final Color YELLOW = new Color(225, 225, 0, 200); @@ -74,7 +74,7 @@ public HypocenterLayer() throws MalformedURLException { renderer.stroke = new BasicStroke(1f); renderer.filled = true; renderer.color = Color.BLACK; - + HypocenterSource hypocenterSource = swarmConfig.getHypocenterSource(); if (hypocenterSource != HypocenterSource.NONE) { @@ -83,7 +83,7 @@ public HypocenterLayer() throws MalformedURLException { quakemlSource = new QuakemlSource(quakemlUrl, (long) REFRESH_INTERVAL); quakemlSource.addObserver(this); update(quakemlSource); - } + } } } @@ -124,7 +124,7 @@ public void draw(Graphics2D g2) { float diameter; diameter = getMarkerSize(mag); - + long age = J2kSec.asEpoch(J2kSec.now()) - origin.getTime(); renderer.shape = new Ellipse2D.Float(0f, 0f, diameter, diameter); Color markerColor; @@ -140,8 +140,8 @@ public void draw(Graphics2D g2) { markerColor = WHITE; } -// int alpha = 0x80FFFFFF; -// renderer.paint = new Color(alpha & markerColor.getRGB(), true); + // int alpha = 0x80FFFFFF; + // renderer.paint = new Color(alpha & markerColor.getRGB(), true); renderer.paint = markerColor; renderer.renderAtOrigin(g2); @@ -152,8 +152,8 @@ public void draw(Graphics2D g2) { } private int getMarkerSize(double mag) { - int markerMag = Integer.max((int)mag, 0); - markerMag = Integer.min(markerMag, markerSize.length); + int markerMag = Integer.max((int) mag, 0); + markerMag = Integer.min(markerMag, markerSize.length); return markerSize[markerMag]; } @@ -229,7 +229,6 @@ private List generatePopupText(Origin origin) { return text; } - public boolean mouseClicked(final MouseEvent e) { boolean handled = false; @@ -239,19 +238,27 @@ public boolean mouseClicked(final MouseEvent e) { handled = true; hoverEvent = null; } - + return handled; } - public void settingsChanged() { LOGGER.debug("hypocenter plotter sees changed settings."); - HypocenterSource hypocenterSource = swarmConfig.getHypocenterSource(); - if (quakemlSource == null) { + if (quakemlSource != null) { + quakemlSource.stop(); + } + + HypocenterSource hypocenterSource = swarmConfig.getHypocenterSource(); + if (hypocenterSource == HypocenterSource.NONE) { + events.clear(); + if (MapFrame.getInstance() != null) { + MapFrame.getInstance().repaint(); + } return; } + try { - quakemlSource.stop(); + LOGGER.debug("New hypocenter source: {}", hypocenterSource); quakemlSource = new QuakemlSource(new URL(hypocenterSource.getUrl()), (long) REFRESH_INTERVAL); quakemlSource.start(); quakemlSource.addObserver(this); @@ -280,7 +287,7 @@ public boolean mouseMoved(MouseEvent e) { boolean handled = false; while (it.hasNext() && handled == false) { Event event = it.next(); - + Origin origin = event.getPreferredOrigin(); if (origin == null) { continue; @@ -328,6 +335,8 @@ public void update(QuakemlSource source) { public void setVisible(boolean isVisible) { LOGGER.debug("Setting hypocenter update to {}", isVisible); - quakemlSource.doUpdate(isVisible); + if (quakemlSource != null) { + quakemlSource.doUpdate(isVisible); + } } } From 9bb19b1afc2f1175d8e2d0e7c6bccf1f7fb98c35 Mon Sep 17 00:00:00 2001 From: tparker Date: Mon, 30 Jan 2017 15:54:52 -0900 Subject: [PATCH 43/67] Bump USGS.jar version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c54c4db6..8e3fe2be 100644 --- a/pom.xml +++ b/pom.xml @@ -524,7 +524,7 @@ gov.usgs.volcanoes usgs - 1.3.2 + 1.3.3 gov.usgs.volcanoes From a5f234bdcd4a43c686fc293874db4176d736b547 Mon Sep 17 00:00:00 2001 From: tparker Date: Mon, 30 Jan 2017 16:01:08 -0900 Subject: [PATCH 44/67] Data source name may not contain a semicolon. Fixes #30 --- .../swarm/chooser/EditDataSourceDialog.java | 238 +++++++++--------- 1 file changed, 120 insertions(+), 118 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/chooser/EditDataSourceDialog.java b/src/main/java/gov/usgs/volcanoes/swarm/chooser/EditDataSourceDialog.java index 7d76908f..471dbedd 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/chooser/EditDataSourceDialog.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/chooser/EditDataSourceDialog.java @@ -24,122 +24,124 @@ * @author Dan Cervelli */ public class EditDataSourceDialog extends SwarmModalDialog { - private static final long serialVersionUID = 1L; - private static final JFrame applicationFrame = Swarm.getApplicationFrame(); - - private String source; - private boolean edit; - - private JTextField name; - - private JTabbedPane tabPane; - - private List panels; - - private String result; - - public EditDataSourceDialog(String s) { - super(applicationFrame, ""); - createPanels(); - source = s; - if (source == null) { - this.setTitle("New Data Source"); - edit = false; - } else { - this.setTitle("Edit Data Source"); - edit = true; - } - createDataSourceUI(); - setSizeAndLocation(); - } - - private void createPanels() { - panels = new ArrayList(); - panels.add(new WWSPanel()); - panels.add(new WaveServerPanel()); - // panels.add(new DHIPanel()); - panels.add(new WebServicesPanel()); - panels.add(new SeedLinkPanel()); - } - - protected void createDataSourceUI() { - JPanel dsPanel = new JPanel(new BorderLayout()); - - String src = null; - if (source != null) - src = source.substring(source.indexOf(';') + 1, source.indexOf(':')); - - tabPane = new JTabbedPane(); - for (DataSourcePanel dsp : panels) { - dsp.setSource(source); - JPanel p = dsp.getPanel(); - tabPane.add(dsp.getName(), p); - if (src != null && src.equals(dsp.getCode())) - tabPane.setSelectedComponent(p); - } - - dsPanel.add(tabPane, BorderLayout.CENTER); - - Box namePanel = new Box(BoxLayout.X_AXIS); - namePanel.add(new JLabel("Data Source Name:")); - namePanel.add(Box.createHorizontalStrut(10)); - String n = ""; - if (source != null) - n = source.substring(0, source.indexOf(';')); - name = new JTextField(30); - namePanel.add(name); - name.setText(n); - dsPanel.add(namePanel, BorderLayout.NORTH); - dsPanel.setBorder(new EmptyBorder(new Insets(10, 10, 10, 10))); - mainPanel.add(dsPanel, BorderLayout.CENTER); - } - - public void resetSource(String src) { - if (src != null) { - source = src; - String s = source.substring(source.indexOf(';') + 1, source.indexOf(':')); - for (DataSourcePanel dsp : panels) { - dsp.resetSource(source); - JPanel p = dsp.getPanel(); - if (s.equals(dsp.getCode())) - tabPane.setSelectedComponent(p); - } - name.setText(source.substring(0, source.indexOf(';'))); - } - } - - protected boolean allowOK() { - String n = name.getText(); - String message = null; - if (n == null || n.length() <= 0) - message = "You must specify a name for this data source."; - else if (!edit && SwarmConfig.getInstance().sourceExists(n)) - message = "A data source by that name already exists."; - - if (message != null) { - JOptionPane.showMessageDialog(applicationFrame, message, "Error", JOptionPane.ERROR_MESSAGE); - return false; - } - - DataSourcePanel p = panels.get(tabPane.getSelectedIndex()); - return p.allowOK(edit); - } - - public void setVisible(boolean b) { - if (b) { - if (source == null) - name.setText(""); - result = null; - } - super.setVisible(b); - } - - protected void wasOK() { - DataSourcePanel p = panels.get(tabPane.getSelectedIndex()); - result = name.getText() + ";" + p.wasOK(); - } - - public String getResult() { - return result; - } + private static final long serialVersionUID = 1L; + private static final JFrame applicationFrame = Swarm.getApplicationFrame(); + + private String source; + private boolean edit; + + private JTextField name; + + private JTabbedPane tabPane; + + private List panels; + + private String result; + + public EditDataSourceDialog(String s) { + super(applicationFrame, ""); + createPanels(); + source = s; + if (source == null) { + this.setTitle("New Data Source"); + edit = false; + } else { + this.setTitle("Edit Data Source"); + edit = true; + } + createDataSourceUI(); + setSizeAndLocation(); + } + + private void createPanels() { + panels = new ArrayList(); + panels.add(new WWSPanel()); + panels.add(new WaveServerPanel()); + // panels.add(new DHIPanel()); + panels.add(new WebServicesPanel()); + panels.add(new SeedLinkPanel()); + } + + protected void createDataSourceUI() { + JPanel dsPanel = new JPanel(new BorderLayout()); + + String src = null; + if (source != null) + src = source.substring(source.indexOf(';') + 1, source.indexOf(':')); + + tabPane = new JTabbedPane(); + for (DataSourcePanel dsp : panels) { + dsp.setSource(source); + JPanel p = dsp.getPanel(); + tabPane.add(dsp.getName(), p); + if (src != null && src.equals(dsp.getCode())) + tabPane.setSelectedComponent(p); + } + + dsPanel.add(tabPane, BorderLayout.CENTER); + + Box namePanel = new Box(BoxLayout.X_AXIS); + namePanel.add(new JLabel("Data Source Name:")); + namePanel.add(Box.createHorizontalStrut(10)); + String n = ""; + if (source != null) + n = source.substring(0, source.indexOf(';')); + name = new JTextField(30); + namePanel.add(name); + name.setText(n); + dsPanel.add(namePanel, BorderLayout.NORTH); + dsPanel.setBorder(new EmptyBorder(new Insets(10, 10, 10, 10))); + mainPanel.add(dsPanel, BorderLayout.CENTER); + } + + public void resetSource(String src) { + if (src != null) { + source = src; + String s = source.substring(source.indexOf(';') + 1, source.indexOf(':')); + for (DataSourcePanel dsp : panels) { + dsp.resetSource(source); + JPanel p = dsp.getPanel(); + if (s.equals(dsp.getCode())) + tabPane.setSelectedComponent(p); + } + name.setText(source.substring(0, source.indexOf(';'))); + } + } + + protected boolean allowOK() { + String n = name.getText(); + String message = null; + if (n == null || n.length() <= 0) + message = "You must specify a name for this data source."; + else if (!edit && SwarmConfig.getInstance().sourceExists(n)) + message = "A data source by that name already exists."; + else if (n.contains(";")) + message = "Data source name cannot contain ';'"; + + if (message != null) { + JOptionPane.showMessageDialog(applicationFrame, message, "Error", JOptionPane.ERROR_MESSAGE); + return false; + } + + DataSourcePanel p = panels.get(tabPane.getSelectedIndex()); + return p.allowOK(edit); + } + + public void setVisible(boolean b) { + if (b) { + if (source == null) + name.setText(""); + result = null; + } + super.setVisible(b); + } + + protected void wasOK() { + DataSourcePanel p = panels.get(tabPane.getSelectedIndex()); + result = name.getText() + ";" + p.wasOK(); + } + + public String getResult() { + return result; + } } From 6e9fd38b15dd2f0a6d563dd389f6bd9c817e2116 Mon Sep 17 00:00:00 2001 From: tparker Date: Mon, 30 Jan 2017 16:09:31 -0900 Subject: [PATCH 45/67] Trim provided layout name. --- src/main/java/gov/usgs/volcanoes/swarm/Swarm.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java b/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java index d4a0d47a..706f3e22 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/Swarm.java @@ -604,8 +604,9 @@ public void saveLayout(String name) { if (name == null) { name = (String) JOptionPane.showInputDialog(this, "Enter a name for this layout:", "Save Layout", JOptionPane.INFORMATION_MESSAGE, null, null, lastLayout); + name = name.trim(); } - if (name != null) { + if (name != null && "".equals(name)) { if (Swarm.config.layouts.containsKey(name)) { boolean overwrite = false; if (!fixedName) { From 7b3d6860be6c27867dd0ff8e04f16571a149d4cb Mon Sep 17 00:00:00 2001 From: tparker Date: Mon, 30 Jan 2017 16:22:37 -0900 Subject: [PATCH 46/67] Quote command line args. Fixes #42 --- swarm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swarm.sh b/swarm.sh index e0a18c55..cbf5ed32 100644 --- a/swarm.sh +++ b/swarm.sh @@ -1 +1 @@ -java -Duser.country=US -Duser.language=us -jar lib/swarm.jar $* +java -Duser.country=US -Duser.language=us -jar lib/swarm.jar "$@" From 002e78a584dd0933705840acbea9d5cf5c757cc8 Mon Sep 17 00:00:00 2001 From: tparker Date: Mon, 30 Jan 2017 16:54:23 -0900 Subject: [PATCH 47/67] Close whaves correctly. Fixes #43 and #46 --- .../swarm/wave/WaveClipboardFrame.java | 2244 ++++++++--------- 1 file changed, 1118 insertions(+), 1126 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveClipboardFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveClipboardFrame.java index 692c441b..d8aae924 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveClipboardFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveClipboardFrame.java @@ -79,1130 +79,1122 @@ * @author Dan Cervelli */ public class WaveClipboardFrame extends SwarmFrame { - public static final long serialVersionUID = -1; - private static final Color SELECT_COLOR = new Color(200, 220, 241); - private static final Color BACKGROUND_COLOR = new Color(0xf7, 0xf7, 0xf7); - - private JScrollPane scrollPane; - private Box waveBox; - private final List waves; - private final Set selectedSet; - private JToolBar toolbar; - private JPanel mainPanel; - private JLabel statusLabel; - private JToggleButton linkButton; - private JButton sizeButton; - private JButton syncButton; - private JButton sortButton; - private JButton removeAllButton; - private JButton saveButton; - private JButton saveAllButton; - private JButton openButton; - private JButton captureButton; - private JButton histButton; - private final DateFormat saveAllDateFormat; - - private WaveViewPanelListener selectListener; - private WaveViewSettingsToolbar waveToolbar; - - private JButton upButton; - private JButton downButton; - private JButton removeButton; - private JButton compXButton; - private JButton expXButton; - private JButton copyButton; - private JButton forwardButton; - private JButton backButton; - private JButton gotoButton; - - private JPopupMenu popup; - - private final Map> histories; - - private final HelicorderViewPanelListener linkListener; - - private boolean heliLinked = true; - - private Throbber throbber; - - private int waveHeight = -1; - - private int lastClickedIndex = -1; - - private WaveClipboardFrame() { - super("Wave Clipboard", true, true, true, false); - this.setFocusable(true); - selectedSet = new HashSet(); - saveAllDateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); - saveAllDateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); - waves = new ArrayList(); - histories = new HashMap>(); - createUI(); - linkListener = new HelicorderViewPanelListener() { - public void insetCreated(final double st, final double et) { - if (heliLinked) - repositionWaves(st, et); - } - }; - } - - public static WaveClipboardFrame getInstance() { - return WaveClipboardFrameHolder.waveClipiboardFrame; - } - - public HelicorderViewPanelListener getLinkListener() { - return linkListener; - } - - private void createUI() { - this.setFrameIcon(Icons.clipboard); - this.setSize(swarmConfig.clipboardWidth, swarmConfig.clipboardHeight); - this.setLocation(swarmConfig.clipboardX, swarmConfig.clipboardY); - this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - - toolbar = SwarmUtil.createToolBar(); - mainPanel = new JPanel(new BorderLayout()); - - createMainButtons(); - createWaveButtons(); - - mainPanel.add(toolbar, BorderLayout.NORTH); - - waveBox = new Box(BoxLayout.Y_AXIS); - scrollPane = new JScrollPane(waveBox); - scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); - scrollPane.getVerticalScrollBar().setUnitIncrement(40); - mainPanel.add(scrollPane, BorderLayout.CENTER); - - statusLabel = new JLabel(" "); - statusLabel.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 1)); - mainPanel.add(statusLabel, BorderLayout.SOUTH); - - mainPanel.setBorder(BorderFactory.createEmptyBorder(0, 2, 1, 2)); - this.setContentPane(mainPanel); - - createListeners(); - doButtonEnables(); - } - - private void createMainButtons() { - openButton = - SwarmUtil.createToolBarButton(Icons.open, "Open a saved wave", new OpenActionListener()); - toolbar.add(openButton); - - saveButton = - SwarmUtil.createToolBarButton(Icons.save, "Save selected wave", new SaveActionListener()); - saveButton.setEnabled(false); - toolbar.add(saveButton); - - saveAllButton = - SwarmUtil.createToolBarButton(Icons.saveall, "Save all waves", new SaveAllActionListener()); - saveAllButton.setEnabled(false); - toolbar.add(saveAllButton); - - toolbar.addSeparator(); - - linkButton = SwarmUtil.createToolBarToggleButton(Icons.helilink, - "Synchronize times with helicorder wave", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - heliLinked = linkButton.isSelected(); - } - }); - linkButton.setSelected(heliLinked); - toolbar.add(linkButton); - - syncButton = SwarmUtil.createToolBarButton(Icons.clock, "Synchronize times with selected wave", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - syncChannels(); - } - }); - syncButton.setEnabled(false); - toolbar.add(syncButton); - - sortButton = SwarmUtil.createToolBarButton(Icons.geosort, - "Sort waves by nearest to selected wave", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - sortChannelsByNearest(); - } - }); - sortButton.setEnabled(false); - toolbar.add(sortButton); - - toolbar.addSeparator(); - - sizeButton = SwarmUtil.createToolBarButton(Icons.resize, "Set clipboard wave size", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - doSizePopup(sizeButton.getX(), sizeButton.getY() + 2 * sizeButton.getHeight()); - } - }); - toolbar.add(sizeButton); - - removeAllButton = SwarmUtil.createToolBarButton(Icons.deleteall, - "Remove all waves from clipboard", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - removeWaves(); - } - }); - removeAllButton.setEnabled(false); - toolbar.add(removeAllButton); - - toolbar.addSeparator(); - captureButton = SwarmUtil.createToolBarButton(Icons.camera, "Save clipboard image (P)", - new CaptureActionListener()); - UiUtils.mapKeyStrokeToButton(this, "P", "capture", captureButton); - toolbar.add(captureButton); - } - - // TODO: don't write image on event thread - // TODO: unify with MapFrame.CaptureActionListener - class CaptureActionListener implements ActionListener { - public void actionPerformed(final ActionEvent e) { - if (waves == null || waves.size() == 0) - return; - - final JFileChooser chooser = FileChooser.getFileChooser(); - final File lastPath = new File(swarmConfig.lastPath); - chooser.setCurrentDirectory(lastPath); - chooser.setSelectedFile(new File("clipboard.png")); - chooser.setDialogTitle("Save Clipboard Screen Capture"); - final int result = chooser.showSaveDialog(applicationFrame); - File f = null; - if (result == JFileChooser.APPROVE_OPTION) { - f = chooser.getSelectedFile(); - - if (f.exists()) { - final int choice = JOptionPane.showConfirmDialog(applicationFrame, - "File exists, overwrite?", "Confirm", JOptionPane.YES_NO_OPTION); - if (choice != JOptionPane.YES_OPTION) - return; - } - swarmConfig.lastPath = f.getParent(); - } - if (f == null) - return; - - int height = 0; - final int width = waves.get(0).getWidth(); - for (final AbstractWavePanel panel : waves) - height += panel.getHeight(); - - final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); - final Graphics g = image.getGraphics(); - for (final AbstractWavePanel panel : waves) { - panel.paint(g); - g.translate(0, panel.getHeight()); - } - try { - final PngEncoderB png = new PngEncoderB(image, false, PngEncoder.FILTER_NONE, 7); - final FileOutputStream out = new FileOutputStream(f); - final byte[] bytes = png.pngEncode(); - out.write(bytes); - out.close(); - } catch (final Exception ex) { - ex.printStackTrace(); - } - } - } - - private void createWaveButtons() { - toolbar.addSeparator(); - - backButton = SwarmUtil.createToolBarButton(Icons.left, "Scroll back time 20% (Left arrow)", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - shiftTime(-0.20); - } - }); - UiUtils.mapKeyStrokeToButton(this, "LEFT", "backward1", backButton); - toolbar.add(backButton); - - forwardButton = SwarmUtil.createToolBarButton(Icons.right, - "Scroll forward time 20% (Right arrow)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - shiftTime(0.20); - } - }); - toolbar.add(forwardButton); - UiUtils.mapKeyStrokeToButton(this, "RIGHT", "forward1", forwardButton); - - gotoButton = - SwarmUtil.createToolBarButton(Icons.gototime, "Go to time (Ctrl-G)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - final String t = JOptionPane.showInputDialog(applicationFrame, - "Input time in 'YYYYMMDDhhmm[ss]' format:", "Go to Time", - JOptionPane.PLAIN_MESSAGE); - if (t != null) - gotoTime(t); - } - }); - toolbar.add(gotoButton); - UiUtils.mapKeyStrokeToButton(this, "ctrl G", "goto", gotoButton); - - compXButton = SwarmUtil.createToolBarButton(Icons.xminus, - "Shrink sample time 20% (Alt-left arrow, +)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - scaleTime(0.20); - } - }); - toolbar.add(compXButton); - UiUtils.mapKeyStrokeToButton(this, "alt LEFT", "compx", compXButton); - UiUtils.mapKeyStrokeToButton(this, "EQUALS", "compx2", compXButton); - UiUtils.mapKeyStrokeToButton(this, "shift EQUALS", "compx2", compXButton); - - expXButton = SwarmUtil.createToolBarButton(Icons.xplus, - "Expand sample time 20% (Alt-right arrow, -)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - scaleTime(-0.20); - } - }); - toolbar.add(expXButton); - UiUtils.mapKeyStrokeToButton(this, "alt RIGHT", "expx", expXButton); - UiUtils.mapKeyStrokeToButton(this, "MINUS", "expx", expXButton); - - histButton = SwarmUtil.createToolBarButton(Icons.timeback, "Last time settings (Backspace)", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - back(); - } - }); - UiUtils.mapKeyStrokeToButton(this, "BACK_SPACE", "back", histButton); - toolbar.add(histButton); - toolbar.addSeparator(); - - waveToolbar = new WaveViewSettingsToolbar(null, toolbar, this); - - copyButton = SwarmUtil.createToolBarButton(Icons.clipboard, - "Place another copy of wave on clipboard (C or Ctrl-C)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - // TODO: implement - // if (selected != null) - // { - // WaveViewPanel wvp = new WaveViewPanel(selected); - // wvp.setBackgroundColor(BACKGROUND_COLOR); - // addWave(wvp); - // } - } - }); - UiUtils.mapKeyStrokeToButton(this, "C", "clipboard1", copyButton); - UiUtils.mapKeyStrokeToButton(this, "control C", "clipboard2", copyButton); - toolbar.add(copyButton); - - toolbar.addSeparator(); - - upButton = SwarmUtil.createToolBarButton(Icons.up, "Move wave up in clipboard (Up arrow)", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - moveUp(); - } - }); - UiUtils.mapKeyStrokeToButton(this, "UP", "up", upButton); - toolbar.add(upButton); - - downButton = SwarmUtil.createToolBarButton(Icons.down, - "Move wave down in clipboard (Down arrow)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - moveDown(); - } - }); - UiUtils.mapKeyStrokeToButton(this, "DOWN", "down", downButton); - toolbar.add(downButton); - - removeButton = SwarmUtil.createToolBarButton(Icons.delete, - "Remove wave from clipboard (Delete)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - remove(); - } - }); - UiUtils.mapKeyStrokeToButton(this, "DELETE", "remove", removeButton); - toolbar.add(removeButton); - - toolbar.add(Box.createHorizontalGlue()); - - throbber = new Throbber(); - toolbar.add(throbber); - - UiUtils.mapKeyStrokeToAction(this, "control A", "selectAll", new AbstractAction() { - private static final long serialVersionUID = 1L; - - public void actionPerformed(final ActionEvent e) { - for (final AbstractWavePanel wave : waves) - select(wave); - } - }); - } - - private void createListeners() { - this.addInternalFrameListener(new InternalFrameAdapter() { - @Override - public void internalFrameActivated(final InternalFrameEvent e) {} - - @Override - public void internalFrameDeiconified(final InternalFrameEvent e) { - resizeWaves(); - } - - @Override - public void internalFrameClosing(final InternalFrameEvent e) { - setVisible(false); - } - - @Override - public void internalFrameClosed(final InternalFrameEvent e) {} - }); - - this.addComponentListener(new ComponentAdapter() { - @Override - public void componentResized(final ComponentEvent e) { - resizeWaves(); - } - }); - - WaveViewTime.addTimeListener(new TimeListener() { - public void timeChanged(final double j2k) { - for (final AbstractWavePanel panel : waves) { - if (panel != null) - panel.setCursorMark(j2k); - } - } - }); - - selectListener = new WaveViewPanelAdapter() { - @Override - public void mousePressed(final AbstractWavePanel src, final MouseEvent e, - final boolean dragging) { - requestFocusInWindow(); - final int thisIndex = getWaveIndex(src); - if (!e.isControlDown() && !e.isShiftDown() && !e.isAltDown()) { - deselectAll(); - select(src); - } else if (e.isControlDown()) { - if (selectedSet.contains(src)) - deselect(src); - else - select(src); - } else if (e.isShiftDown()) { - if (lastClickedIndex == -1) - select(src); - else { - deselectAll(); - final int min = Math.min(lastClickedIndex, thisIndex); - final int max = Math.max(lastClickedIndex, thisIndex); - for (int i = min; i <= max; i++) { - final WaveViewPanel ps = (WaveViewPanel) waveBox.getComponent(i); - select(ps); - } - } - } - lastClickedIndex = thisIndex; - } - - @Override - public void waveZoomed(final AbstractWavePanel src, final double st, final double et, - final double nst, final double net) { - final double[] t = new double[] {st, et}; - addHistory(src, t); - for (final AbstractWavePanel wvp : selectedSet) { - if (wvp != src) { - addHistory(wvp, t); - wvp.zoom(nst, net); - } - } - } - - @Override - public void waveClosed(final AbstractWavePanel src) { - remove(src); - } - }; - } - - private int calculateWaveHeight() { - if (waveHeight > 0) - return waveHeight; - - final int w = scrollPane.getViewport().getSize().width; - int h = (int) Math.round(w * 60.0 / 300.0); - h = Math.min(200, h); - h = Math.max(h, 80); - return h; - } - - private void setWaveHeight(final int s) { - waveHeight = s; - resizeWaves(); - } - - private void doSizePopup(final int x, final int y) { - if (popup == null) { - final String[] labels = new String[] {"Auto", null, "Tiny", "Small", "Medium", "Large"}; - final int[] sizes = new int[] {-1, -1, 50, 100, 160, 230}; - popup = new JPopupMenu(); - final ButtonGroup group = new ButtonGroup(); - for (int i = 0; i < labels.length; i++) { - if (labels[i] != null) { - final int size = sizes[i]; - final JRadioButtonMenuItem mi = new JRadioButtonMenuItem(labels[i]); - mi.addActionListener(new ActionListener() { - public void actionPerformed(final ActionEvent e) { - setWaveHeight(size); - } - }); - if (waveHeight == size) - mi.setSelected(true); - group.add(mi); - popup.add(mi); - } else - popup.addSeparator(); - } - } - popup.show(this, x, y); - } - - private class OpenActionListener implements ActionListener { - public void actionPerformed(final ActionEvent e) { - final JFileChooser chooser = FileChooser.getFileChooser(); - chooser.resetChoosableFileFilters(); - for (final FileType ft : FileType.getKnownTypes()) { - final ExtensionFileFilter f = new ExtensionFileFilter(ft.extension, ft.description); - chooser.addChoosableFileFilter(f); - } - chooser.setDialogTitle("Open Wave"); - chooser.setFileFilter(chooser.getAcceptAllFileFilter()); - final File lastPath = new File(swarmConfig.lastPath); - chooser.setCurrentDirectory(lastPath); - chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); - chooser.setMultiSelectionEnabled(true); - final int result = chooser.showOpenDialog(applicationFrame); - if (result == JFileChooser.APPROVE_OPTION) { - final File[] fs = chooser.getSelectedFiles(); - - for (int i = 0; i < fs.length; i++) { - if (fs[i].isDirectory()) { - final File[] dfs = fs[i].listFiles(); - if (dfs == null) - continue; - for (int j = 0; j < dfs.length; j++) - openFile(dfs[j]); - swarmConfig.lastPath = fs[i].getParent(); - } else { - openFile(fs[i]); - swarmConfig.lastPath = fs[i].getParent(); - } - } - } - } - } - - private class SaveActionListener implements ActionListener { - public void actionPerformed(final ActionEvent e) { - final AbstractWavePanel selected = getSingleSelected(); - if (selected == null) - return; - - final JFileChooser chooser = FileChooser.getFileChooser(); - chooser.resetChoosableFileFilters(); - chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); - chooser.setMultiSelectionEnabled(false); - chooser.setDialogTitle("Save Wave"); - - for (final FileType ft : FileType.values()) { - if (ft == FileType.UNKNOWN) - continue; - - final ExtensionFileFilter f = new ExtensionFileFilter(ft.extension, ft.description); - chooser.addChoosableFileFilter(f); - } - - chooser.setFileFilter(chooser.getAcceptAllFileFilter()); - - final File lastPath = new File(swarmConfig.lastPath); - chooser.setCurrentDirectory(lastPath); - final String fileName = selected.getChannel().replace(' ', '_') + ".sac"; - chooser.setSelectedFile(new File(fileName)); - final int result = chooser.showSaveDialog(applicationFrame); - if (result == JFileChooser.APPROVE_OPTION) { - final File f = chooser.getSelectedFile(); - boolean confirm = true; - if (f.exists()) { - if (f.isDirectory()) { - JOptionPane.showMessageDialog(applicationFrame, - "You can not select an existing directory.", "Error", JOptionPane.ERROR_MESSAGE); - return; - } - confirm = false; - final int choice = JOptionPane.showConfirmDialog(applicationFrame, - "File exists, overwrite?", "Confirm", JOptionPane.YES_NO_OPTION); - if (choice == JOptionPane.YES_OPTION) - confirm = true; - } - - if (confirm) { - try { - swarmConfig.lastPath = f.getParent(); - final String fn = f.getPath(); - final SeismicDataFile file = SeismicDataFile.getFile(fn); - // String channel = selected.getChannel().replace(' ', '_'); - final Wave wave = selected.getWave(); - // file.putWave(channel, wave); - file.putWave(selected.getChannel(), wave); - file.write(); - } catch (final FileNotFoundException ex) { - JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Directory does not exist.", - "Error", JOptionPane.ERROR_MESSAGE); - } catch (final IOException ex) { - JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Error writing file.", - "Error", JOptionPane.ERROR_MESSAGE); - } - } - } - } - } - - private class SaveAllActionListener implements ActionListener { - public void actionPerformed(final ActionEvent e) { - if (waves.size() <= 0) - return; - - final FileTypeDialog dialog = new FileTypeDialog(); - FileType fileType = FileType.UNKNOWN; - if (!dialog.isOpen() || (dialog.isOpen() && !dialog.isAssumeSame())) { - dialog.setVisible(true); - - if (dialog.isCancelled()) - fileType = FileType.UNKNOWN; - else - fileType = dialog.getFileType(); - - } - - final JFileChooser chooser = FileChooser.getFileChooser(); - chooser.resetChoosableFileFilters(); - chooser.setMultiSelectionEnabled(false); - chooser.setDialogTitle("Save All Files"); - final File lastPath = new File(swarmConfig.lastPath); - chooser.setCurrentDirectory(lastPath); - - if (!fileType.isCollective) - chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - else - chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); - - final int result = chooser.showSaveDialog(applicationFrame); - if (result == JFileChooser.CANCEL_OPTION) - return; - - final File f = chooser.getSelectedFile(); - - if (f == null) { - JOptionPane.showMessageDialog(applicationFrame, "Save location not understood.", "Error", - JOptionPane.ERROR_MESSAGE); - return; - } - - if (result == JFileChooser.APPROVE_OPTION) { - try { - if (f.exists() && !f.isDirectory()) - return; - if (!f.exists()) - f.mkdir(); - for (final AbstractWavePanel wvp : waves) { - Wave sw = wvp.getWave(); - - if (sw != null) { - sw = sw.subset(wvp.getStartTime(), wvp.getEndTime()); - final String date = saveAllDateFormat.format(J2kSec.asDate(sw.getStartTime())); - final File dir = new File(f.getPath() + File.separatorChar + date); - if (!dir.exists()) - dir.mkdir(); - - swarmConfig.lastPath = f.getParent(); - final String fn = - dir + File.separator + wvp.getChannel().replace(' ', '_') + fileType.extension; - final SeismicDataFile file = SeismicDataFile.getFile(fn); - file.putWave(wvp.getChannel(), sw); - file.write(); - } - } - swarmConfig.lastPath = f.getPath(); - } catch (final FileNotFoundException ex) { - JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Directory does not exist.", - "Error", JOptionPane.ERROR_MESSAGE); - } catch (final IOException ex) { - JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Error writing file.", "Error", - JOptionPane.ERROR_MESSAGE); - } - } - } - } - - public void openFile(final File f) { - SeismicDataFile file = SeismicDataFile.getFile(f); - if (file == null) { - final FileTypeDialog dialog = new FileTypeDialog(); - FileType fileType = FileType.UNKNOWN; - if (!dialog.isOpen() || (dialog.isOpen() && !dialog.isAssumeSame())) { - dialog.setVisible(true); - - if (dialog.isCancelled()) - fileType = FileType.UNKNOWN; - else - fileType = dialog.getFileType(); - - } - file = SeismicDataFile.getFile(f, fileType); - } - - if (file == null) { - JOptionPane.showMessageDialog(applicationFrame, - "There was an error opening the file, '" + f.getName() + "'.", "Error", - JOptionPane.ERROR_MESSAGE); - return; - } - - try { - file.read(); - } catch (final IOException e) { - JOptionPane.showMessageDialog(applicationFrame, - "There was an error opening the file, '" + f.getName() + "'.\n" + e.getMessage(), "Error", - JOptionPane.ERROR_MESSAGE); - } - - for (final String channel : file.getChannels()) { - final WaveViewPanel wvp = new WaveViewPanel(); - wvp.setChannel(channel); - final CachedDataSource cache = CachedDataSource.getInstance(); - - final Wave wave = file.getWave(channel); - cache.putWave(channel, wave); - wvp.setDataSource(cache); - wvp.setWave(wave, wave.getStartTime(), wave.getEndTime()); - WaveClipboardFrame.this.addWave(new WaveViewPanel(wvp)); - } - } - - private void doButtonEnables() { - final boolean enable = (waves == null || waves.size() == 0); - saveButton.setEnabled(!enable); - sortButton.setEnabled(!enable); - saveAllButton.setEnabled(!enable); - syncButton.setEnabled(!enable); - removeAllButton.setEnabled(!enable); - saveAllButton.setEnabled(!enable); - - final boolean allowSingle = (selectedSet.size() == 1); - upButton.setEnabled(allowSingle); - downButton.setEnabled(allowSingle); - sortButton.setEnabled(allowSingle); - syncButton.setEnabled(allowSingle); - saveButton.setEnabled(allowSingle); - - final boolean allowMulti = (selectedSet.size() > 0); - backButton.setEnabled(allowMulti); - expXButton.setEnabled(allowMulti); - compXButton.setEnabled(allowMulti); - backButton.setEnabled(allowMulti); - forwardButton.setEnabled(allowMulti); - histButton.setEnabled(allowMulti); - removeButton.setEnabled(allowMulti); - gotoButton.setEnabled(allowMulti); - } - - public synchronized void sortChannelsByNearest() { - final AbstractWavePanel p = getSingleSelected(); - if (p == null) - return; - - final ArrayList sorted = new ArrayList(waves.size()); - for (final AbstractWavePanel wave : waves) - sorted.add(wave); - - final Metadata smd = swarmConfig.getMetadata(p.getChannel()); - if (smd == null || Double.isNaN(smd.getLongitude()) || Double.isNaN(smd.getLatitude())) - return; - - Collections.sort(sorted, new Comparator() { - public int compare(final AbstractWavePanel wvp1, final AbstractWavePanel wvp2) { - Metadata md = swarmConfig.getMetadata(wvp1.getChannel()); - final double d1 = smd.distanceTo(md); - md = swarmConfig.getMetadata(wvp2.getChannel()); - final double d2 = smd.distanceTo(md); - return Double.compare(d1, d2); - } - }); - - removeWaves(); - for (final AbstractWavePanel wave : sorted) - addWave(wave); - select(p); - } - - public synchronized AbstractWavePanel getSingleSelected() { - if (selectedSet.size() != 1) - return null; - - AbstractWavePanel p = null; - for (final AbstractWavePanel panel : selectedSet) - p = panel; - - return p; - } - - public synchronized void syncChannels() { - final AbstractWavePanel p = getSingleSelected(); - if (p == null) - return; - - final double st = p.getStartTime(); - final double et = p.getEndTime(); - - // TODO: thread bug here. must synch iterator below - final SwingWorker worker = new SwingWorker() { - @Override - public Object construct() { - List copy = null; - synchronized (WaveClipboardFrame.this) { - copy = new ArrayList(waves); - } - for (final AbstractWavePanel wvp : copy) { - if (wvp != p) { - if (wvp.getDataSource() != null) { - addHistory(wvp, new double[] {wvp.getStartTime(), wvp.getEndTime()}); - final Wave sw = wvp.getDataSource().getWave(wvp.getChannel(), st, et); - wvp.setWave(sw, st, et); - } - } - } - return null; - } - - @Override - public void finished() { - repaint(); - } - }; - worker.start(); - } - - public void setStatusText(final String s) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - statusLabel.setText(s); - } - }); - } - - public WaveViewPanel getSelected() { - return null; - // return selected; - } - - public synchronized void addWave(final AbstractWavePanel p) { - p.addListener(selectListener); - p.setOffsets(54, 8, 21, 19); - p.setAllowClose(true); - p.setStatusLabel(statusLabel); - p.setAllowDragging(true); - p.setDisplayTitle(true); - final int w = scrollPane.getViewport().getSize().width; - p.setSize(w, calculateWaveHeight()); - p.setBottomBorderColor(Color.GRAY); - p.createImage(); - waveBox.add(p); - waves.add(p); - doButtonEnables(); - waveBox.validate(); - } - - private synchronized void deselect(final AbstractWavePanel p) { - selectedSet.remove(p); - waveToolbar.removeSettings(p.getSettings()); - p.setBackgroundColor(BACKGROUND_COLOR); - p.createImage(); - doButtonEnables(); - } - - private synchronized void deselectAll() { - final WaveViewPanel[] panels = selectedSet.toArray(new WaveViewPanel[0]); - for (final WaveViewPanel p : panels) - deselect(p); - } - - private synchronized void select(final AbstractWavePanel p) { - if (p == null || selectedSet.contains(p)) - return; - - selectedSet.add(p); - doButtonEnables(); - p.setBackgroundColor(SELECT_COLOR); - DataChooser.getInstance().setNearest(p.getChannel()); - p.createImage(); - waveToolbar.addSettings(p.getSettings()); - } - - private synchronized void remove(final WaveViewPanel p) { - int i = 0; - for (i = 0; i < waveBox.getComponentCount(); i++) { - if (p == waveBox.getComponent(i)) - break; - } - - p.removeListener(selectListener); - p.getDataSource().close(); - setStatusText(" "); - waveBox.remove(i); - waves.remove(p); - histories.remove(p); - doButtonEnables(); - waveBox.validate(); - selectedSet.remove(p); - lastClickedIndex = Math.min(lastClickedIndex, waveBox.getComponentCount() - 1); - waveToolbar.removeSettings(p.getSettings()); - repaint(); - } - - protected int getWaveIndex(final AbstractWavePanel p) { - int i = 0; - for (i = 0; i < waveBox.getComponentCount(); i++) { - if (p == waveBox.getComponent(i)) - break; - } - return i; - } - - public synchronized void remove() { - final WaveViewPanel[] panels = selectedSet.toArray(new WaveViewPanel[0]); - for (final WaveViewPanel p : panels) - remove(p); - } - - public synchronized void moveDown() { - final AbstractWavePanel p = getSingleSelected(); - if (p == null) - return; - - final int i = waves.indexOf(p); - if (i == waves.size() - 1) - return; - - waves.remove(i); - waves.add(i + 1, p); - waveBox.remove(p); - waveBox.add(p, i + 1); - waveBox.validate(); - repaint(); - } - - public synchronized void moveUp() { - final AbstractWavePanel p = getSingleSelected(); - if (p == null) - return; - - final int i = waves.indexOf(p); - if (i == 0) - return; - - waves.remove(i); - waves.add(i - 1, p); - waveBox.remove(p); - waveBox.add(p, i - 1); - waveBox.validate(); - repaint(); - } - - public void resizeWaves() { - final SwingWorker worker = new SwingWorker() { - @Override - public Object construct() { - final int w = scrollPane.getViewport().getSize().width; - for (final AbstractWavePanel wave : waves) { - wave.setSize(w, calculateWaveHeight()); - wave.createImage(); - } - return null; - } - - @Override - public void finished() { - waveBox.validate(); - validate(); - repaint(); - } - }; - worker.start(); - } - - public void removeWaves() { - while (waves.size() > 0) { - remove(waves.get(0)); - waves.remove(0); - } - - waveBox.validate(); - scrollPane.validate(); - doButtonEnables(); - repaint(); - } - - private void addHistory(final AbstractWavePanel wvp, final double[] t) { - Stack history = histories.get(wvp); - if (history == null) { - history = new Stack(); - histories.put(wvp, history); - } - history.push(t); - } - - public void gotoTime(final AbstractWavePanel wvp, String t) { - double j2k = Double.NaN; - try { - if (t.length() == 12) - t = t + "30"; - - j2k = J2kSec.parse("yyyyMMddHHmmss", t); - } catch (final Exception e) { - JOptionPane.showMessageDialog(applicationFrame, "Illegal time value.", "Error", - JOptionPane.ERROR_MESSAGE); - } - - if (!Double.isNaN(j2k)) { - double dt = 60; - if (wvp.getWave() != null) { - final double st = wvp.getStartTime(); - final double et = wvp.getEndTime(); - final double[] ts = new double[] {st, et}; - addHistory(wvp, ts); - dt = (et - st); - } - - final double tzo = - swarmConfig.getTimeZone(wvp.getChannel()).getOffset(System.currentTimeMillis()) / 1000; - - final double nst = j2k - tzo - dt / 2; - final double net = nst + dt; - - fetchNewWave(wvp, nst, net); - } - } - - public void gotoTime(final String t) { - for (final AbstractWavePanel p : selectedSet) - gotoTime(p, t); - } - - public void scaleTime(final AbstractWavePanel wvp, final double pct) { - final double st = wvp.getStartTime(); - final double et = wvp.getEndTime(); - final double[] t = new double[] {st, et}; - addHistory(wvp, t); - final double dt = (et - st) * (1 - pct); - final double mt = (et - st) / 2 + st; - final double nst = mt - dt / 2; - final double net = mt + dt / 2; - fetchNewWave(wvp, nst, net); - } - - public void scaleTime(final double pct) { - for (final AbstractWavePanel p : selectedSet) - scaleTime(p, pct); - } - - public void back(final AbstractWavePanel wvp) { - final Stack history = histories.get(wvp); - if (history == null || history.empty()) - return; - - final double[] t = history.pop(); - fetchNewWave(wvp, t[0], t[1]); - } - - public void back() { - for (final AbstractWavePanel p : selectedSet) - back(p); - } - - private void shiftTime(final AbstractWavePanel wvp, final double pct) { - final double st = wvp.getStartTime(); - final double et = wvp.getEndTime(); - final double[] t = new double[] {st, et}; - addHistory(wvp, t); - final double dt = (et - st) * pct; - final double nst = st + dt; - final double net = et + dt; - fetchNewWave(wvp, nst, net); - } - - public void shiftTime(final double pct) { - for (final AbstractWavePanel p : selectedSet) - shiftTime(p, pct); - } - - public void repositionWaves(final double st, final double et) { - for (final AbstractWavePanel wave : waves) { - fetchNewWave(wave, st, et); - } - } - - public Throbber getThrobber() { - return throbber; - } - - // TODO: This isn't right, this should be a method of waveviewpanel - private void fetchNewWave(final AbstractWavePanel wvp, final double nst, final double net) { - final SwingWorker worker = new SwingWorker() { - @Override - public Object construct() { - throbber.increment(); - final SeismicDataSource sds = wvp.getDataSource(); - // Hacky fix for bug #84 - Wave sw = null; - if (sds instanceof CachedDataSource) - sw = ((CachedDataSource) sds).getBestWave(wvp.getChannel(), nst, net); - else - sw = sds.getWave(wvp.getChannel(), nst, net); - wvp.setWave(sw, nst, net); - wvp.repaint(); - return null; - } - - @Override - public void finished() { - throbber.decrement(); - repaint(); - } - }; - worker.start(); - } - - @Override - public void setMaximum(final boolean max) throws PropertyVetoException { - if (max) { - swarmConfig.clipboardX = getX(); - swarmConfig.clipboardY = getY(); - } - super.setMaximum(max); - } - - @Override - public void paint(final Graphics g) { - super.paint(g); - if (waves.size() == 0) { - final Dimension dim = this.getSize(); - g.setColor(Color.black); - g.drawString("Clipboard empty.", dim.width / 2 - 40, dim.height / 2); - } - } - - @Override - public void setVisible(final boolean isVisible) { - super.setVisible(isVisible); - if (isVisible) - toFront(); - } - - private static class WaveClipboardFrameHolder { - public static WaveClipboardFrame waveClipiboardFrame = new WaveClipboardFrame(); - } + public static final long serialVersionUID = -1; + private static final Color SELECT_COLOR = new Color(200, 220, 241); + private static final Color BACKGROUND_COLOR = new Color(0xf7, 0xf7, 0xf7); + + private JScrollPane scrollPane; + private Box waveBox; + private final List waves; + private final Set selectedSet; + private JToolBar toolbar; + private JPanel mainPanel; + private JLabel statusLabel; + private JToggleButton linkButton; + private JButton sizeButton; + private JButton syncButton; + private JButton sortButton; + private JButton removeAllButton; + private JButton saveButton; + private JButton saveAllButton; + private JButton openButton; + private JButton captureButton; + private JButton histButton; + private final DateFormat saveAllDateFormat; + + private WaveViewPanelListener selectListener; + private WaveViewSettingsToolbar waveToolbar; + + private JButton upButton; + private JButton downButton; + private JButton removeButton; + private JButton compXButton; + private JButton expXButton; + private JButton copyButton; + private JButton forwardButton; + private JButton backButton; + private JButton gotoButton; + + private JPopupMenu popup; + + private final Map> histories; + + private final HelicorderViewPanelListener linkListener; + + private boolean heliLinked = true; + + private Throbber throbber; + + private int waveHeight = -1; + + private int lastClickedIndex = -1; + + private WaveClipboardFrame() { + super("Wave Clipboard", true, true, true, false); + this.setFocusable(true); + selectedSet = new HashSet(); + saveAllDateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); + saveAllDateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); + waves = new ArrayList(); + histories = new HashMap>(); + createUI(); + linkListener = new HelicorderViewPanelListener() { + public void insetCreated(final double st, final double et) { + if (heliLinked) + repositionWaves(st, et); + } + }; + } + + public static WaveClipboardFrame getInstance() { + return WaveClipboardFrameHolder.waveClipiboardFrame; + } + + public HelicorderViewPanelListener getLinkListener() { + return linkListener; + } + + private void createUI() { + this.setFrameIcon(Icons.clipboard); + this.setSize(swarmConfig.clipboardWidth, swarmConfig.clipboardHeight); + this.setLocation(swarmConfig.clipboardX, swarmConfig.clipboardY); + this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + + toolbar = SwarmUtil.createToolBar(); + mainPanel = new JPanel(new BorderLayout()); + + createMainButtons(); + createWaveButtons(); + + mainPanel.add(toolbar, BorderLayout.NORTH); + + waveBox = new Box(BoxLayout.Y_AXIS); + scrollPane = new JScrollPane(waveBox); + scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + scrollPane.getVerticalScrollBar().setUnitIncrement(40); + mainPanel.add(scrollPane, BorderLayout.CENTER); + + statusLabel = new JLabel(" "); + statusLabel.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 1)); + mainPanel.add(statusLabel, BorderLayout.SOUTH); + + mainPanel.setBorder(BorderFactory.createEmptyBorder(0, 2, 1, 2)); + this.setContentPane(mainPanel); + + createListeners(); + doButtonEnables(); + } + + private void createMainButtons() { + openButton = SwarmUtil.createToolBarButton(Icons.open, "Open a saved wave", new OpenActionListener()); + toolbar.add(openButton); + + saveButton = SwarmUtil.createToolBarButton(Icons.save, "Save selected wave", new SaveActionListener()); + saveButton.setEnabled(false); + toolbar.add(saveButton); + + saveAllButton = SwarmUtil.createToolBarButton(Icons.saveall, "Save all waves", new SaveAllActionListener()); + saveAllButton.setEnabled(false); + toolbar.add(saveAllButton); + + toolbar.addSeparator(); + + linkButton = SwarmUtil.createToolBarToggleButton(Icons.helilink, "Synchronize times with helicorder wave", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + heliLinked = linkButton.isSelected(); + } + }); + linkButton.setSelected(heliLinked); + toolbar.add(linkButton); + + syncButton = SwarmUtil.createToolBarButton(Icons.clock, "Synchronize times with selected wave", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + syncChannels(); + } + }); + syncButton.setEnabled(false); + toolbar.add(syncButton); + + sortButton = SwarmUtil.createToolBarButton(Icons.geosort, "Sort waves by nearest to selected wave", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + sortChannelsByNearest(); + } + }); + sortButton.setEnabled(false); + toolbar.add(sortButton); + + toolbar.addSeparator(); + + sizeButton = SwarmUtil.createToolBarButton(Icons.resize, "Set clipboard wave size", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + doSizePopup(sizeButton.getX(), sizeButton.getY() + 2 * sizeButton.getHeight()); + } + }); + toolbar.add(sizeButton); + + removeAllButton = SwarmUtil.createToolBarButton(Icons.deleteall, "Remove all waves from clipboard", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + removeWaves(); + } + }); + removeAllButton.setEnabled(false); + toolbar.add(removeAllButton); + + toolbar.addSeparator(); + captureButton = SwarmUtil.createToolBarButton(Icons.camera, "Save clipboard image (P)", + new CaptureActionListener()); + UiUtils.mapKeyStrokeToButton(this, "P", "capture", captureButton); + toolbar.add(captureButton); + } + + // TODO: don't write image on event thread + // TODO: unify with MapFrame.CaptureActionListener + class CaptureActionListener implements ActionListener { + public void actionPerformed(final ActionEvent e) { + if (waves == null || waves.size() == 0) + return; + + final JFileChooser chooser = FileChooser.getFileChooser(); + final File lastPath = new File(swarmConfig.lastPath); + chooser.setCurrentDirectory(lastPath); + chooser.setSelectedFile(new File("clipboard.png")); + chooser.setDialogTitle("Save Clipboard Screen Capture"); + final int result = chooser.showSaveDialog(applicationFrame); + File f = null; + if (result == JFileChooser.APPROVE_OPTION) { + f = chooser.getSelectedFile(); + + if (f.exists()) { + final int choice = JOptionPane.showConfirmDialog(applicationFrame, "File exists, overwrite?", + "Confirm", JOptionPane.YES_NO_OPTION); + if (choice != JOptionPane.YES_OPTION) + return; + } + swarmConfig.lastPath = f.getParent(); + } + if (f == null) + return; + + int height = 0; + final int width = waves.get(0).getWidth(); + for (final AbstractWavePanel panel : waves) + height += panel.getHeight(); + + final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); + final Graphics g = image.getGraphics(); + for (final AbstractWavePanel panel : waves) { + panel.paint(g); + g.translate(0, panel.getHeight()); + } + try { + final PngEncoderB png = new PngEncoderB(image, false, PngEncoder.FILTER_NONE, 7); + final FileOutputStream out = new FileOutputStream(f); + final byte[] bytes = png.pngEncode(); + out.write(bytes); + out.close(); + } catch (final Exception ex) { + ex.printStackTrace(); + } + } + } + + private void createWaveButtons() { + toolbar.addSeparator(); + + backButton = SwarmUtil.createToolBarButton(Icons.left, "Scroll back time 20% (Left arrow)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + shiftTime(-0.20); + } + }); + UiUtils.mapKeyStrokeToButton(this, "LEFT", "backward1", backButton); + toolbar.add(backButton); + + forwardButton = SwarmUtil.createToolBarButton(Icons.right, "Scroll forward time 20% (Right arrow)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + shiftTime(0.20); + } + }); + toolbar.add(forwardButton); + UiUtils.mapKeyStrokeToButton(this, "RIGHT", "forward1", forwardButton); + + gotoButton = SwarmUtil.createToolBarButton(Icons.gototime, "Go to time (Ctrl-G)", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + final String t = JOptionPane.showInputDialog(applicationFrame, + "Input time in 'YYYYMMDDhhmm[ss]' format:", "Go to Time", JOptionPane.PLAIN_MESSAGE); + if (t != null) + gotoTime(t); + } + }); + toolbar.add(gotoButton); + UiUtils.mapKeyStrokeToButton(this, "ctrl G", "goto", gotoButton); + + compXButton = SwarmUtil.createToolBarButton(Icons.xminus, "Shrink sample time 20% (Alt-left arrow, +)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + scaleTime(0.20); + } + }); + toolbar.add(compXButton); + UiUtils.mapKeyStrokeToButton(this, "alt LEFT", "compx", compXButton); + UiUtils.mapKeyStrokeToButton(this, "EQUALS", "compx2", compXButton); + UiUtils.mapKeyStrokeToButton(this, "shift EQUALS", "compx2", compXButton); + + expXButton = SwarmUtil.createToolBarButton(Icons.xplus, "Expand sample time 20% (Alt-right arrow, -)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + scaleTime(-0.20); + } + }); + toolbar.add(expXButton); + UiUtils.mapKeyStrokeToButton(this, "alt RIGHT", "expx", expXButton); + UiUtils.mapKeyStrokeToButton(this, "MINUS", "expx", expXButton); + + histButton = SwarmUtil.createToolBarButton(Icons.timeback, "Last time settings (Backspace)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + back(); + } + }); + UiUtils.mapKeyStrokeToButton(this, "BACK_SPACE", "back", histButton); + toolbar.add(histButton); + toolbar.addSeparator(); + + waveToolbar = new WaveViewSettingsToolbar(null, toolbar, this); + + copyButton = SwarmUtil.createToolBarButton(Icons.clipboard, + "Place another copy of wave on clipboard (C or Ctrl-C)", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + // TODO: implement + // if (selected != null) + // { + // WaveViewPanel wvp = new WaveViewPanel(selected); + // wvp.setBackgroundColor(BACKGROUND_COLOR); + // addWave(wvp); + // } + } + }); + UiUtils.mapKeyStrokeToButton(this, "C", "clipboard1", copyButton); + UiUtils.mapKeyStrokeToButton(this, "control C", "clipboard2", copyButton); + toolbar.add(copyButton); + + toolbar.addSeparator(); + + upButton = SwarmUtil.createToolBarButton(Icons.up, "Move wave up in clipboard (Up arrow)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + moveUp(); + } + }); + UiUtils.mapKeyStrokeToButton(this, "UP", "up", upButton); + toolbar.add(upButton); + + downButton = SwarmUtil.createToolBarButton(Icons.down, "Move wave down in clipboard (Down arrow)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + moveDown(); + } + }); + UiUtils.mapKeyStrokeToButton(this, "DOWN", "down", downButton); + toolbar.add(downButton); + + removeButton = SwarmUtil.createToolBarButton(Icons.delete, "Remove wave from clipboard (Delete)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + remove(); + } + }); + UiUtils.mapKeyStrokeToButton(this, "DELETE", "remove", removeButton); + toolbar.add(removeButton); + + toolbar.add(Box.createHorizontalGlue()); + + throbber = new Throbber(); + toolbar.add(throbber); + + UiUtils.mapKeyStrokeToAction(this, "control A", "selectAll", new AbstractAction() { + private static final long serialVersionUID = 1L; + + public void actionPerformed(final ActionEvent e) { + for (final AbstractWavePanel wave : waves) + select(wave); + } + }); + } + + private void createListeners() { + this.addInternalFrameListener(new InternalFrameAdapter() { + @Override + public void internalFrameActivated(final InternalFrameEvent e) { + } + + @Override + public void internalFrameDeiconified(final InternalFrameEvent e) { + resizeWaves(); + } + + @Override + public void internalFrameClosing(final InternalFrameEvent e) { + setVisible(false); + } + + @Override + public void internalFrameClosed(final InternalFrameEvent e) { + } + }); + + this.addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(final ComponentEvent e) { + resizeWaves(); + } + }); + + WaveViewTime.addTimeListener(new TimeListener() { + public void timeChanged(final double j2k) { + for (final AbstractWavePanel panel : waves) { + if (panel != null) + panel.setCursorMark(j2k); + } + } + }); + + selectListener = new WaveViewPanelAdapter() { + @Override + public void mousePressed(final AbstractWavePanel src, final MouseEvent e, final boolean dragging) { + requestFocusInWindow(); + final int thisIndex = getWaveIndex(src); + if (!e.isControlDown() && !e.isShiftDown() && !e.isAltDown()) { + deselectAll(); + select(src); + } else if (e.isControlDown()) { + if (selectedSet.contains(src)) + deselect(src); + else + select(src); + } else if (e.isShiftDown()) { + if (lastClickedIndex == -1) + select(src); + else { + deselectAll(); + final int min = Math.min(lastClickedIndex, thisIndex); + final int max = Math.max(lastClickedIndex, thisIndex); + for (int i = min; i <= max; i++) { + final WaveViewPanel ps = (WaveViewPanel) waveBox.getComponent(i); + select(ps); + } + } + } + lastClickedIndex = thisIndex; + } + + @Override + public void waveZoomed(final AbstractWavePanel src, final double st, final double et, final double nst, + final double net) { + final double[] t = new double[] { st, et }; + addHistory(src, t); + for (final AbstractWavePanel wvp : selectedSet) { + if (wvp != src) { + addHistory(wvp, t); + wvp.zoom(nst, net); + } + } + } + + @Override + public void waveClosed(final AbstractWavePanel src) { + remove(src); + } + }; + } + + private int calculateWaveHeight() { + if (waveHeight > 0) + return waveHeight; + + final int w = scrollPane.getViewport().getSize().width; + int h = (int) Math.round(w * 60.0 / 300.0); + h = Math.min(200, h); + h = Math.max(h, 80); + return h; + } + + private void setWaveHeight(final int s) { + waveHeight = s; + resizeWaves(); + } + + private void doSizePopup(final int x, final int y) { + if (popup == null) { + final String[] labels = new String[] { "Auto", null, "Tiny", "Small", "Medium", "Large" }; + final int[] sizes = new int[] { -1, -1, 50, 100, 160, 230 }; + popup = new JPopupMenu(); + final ButtonGroup group = new ButtonGroup(); + for (int i = 0; i < labels.length; i++) { + if (labels[i] != null) { + final int size = sizes[i]; + final JRadioButtonMenuItem mi = new JRadioButtonMenuItem(labels[i]); + mi.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setWaveHeight(size); + } + }); + if (waveHeight == size) + mi.setSelected(true); + group.add(mi); + popup.add(mi); + } else + popup.addSeparator(); + } + } + popup.show(this, x, y); + } + + private class OpenActionListener implements ActionListener { + public void actionPerformed(final ActionEvent e) { + final JFileChooser chooser = FileChooser.getFileChooser(); + chooser.resetChoosableFileFilters(); + for (final FileType ft : FileType.getKnownTypes()) { + final ExtensionFileFilter f = new ExtensionFileFilter(ft.extension, ft.description); + chooser.addChoosableFileFilter(f); + } + chooser.setDialogTitle("Open Wave"); + chooser.setFileFilter(chooser.getAcceptAllFileFilter()); + final File lastPath = new File(swarmConfig.lastPath); + chooser.setCurrentDirectory(lastPath); + chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + chooser.setMultiSelectionEnabled(true); + final int result = chooser.showOpenDialog(applicationFrame); + if (result == JFileChooser.APPROVE_OPTION) { + final File[] fs = chooser.getSelectedFiles(); + + for (int i = 0; i < fs.length; i++) { + if (fs[i].isDirectory()) { + final File[] dfs = fs[i].listFiles(); + if (dfs == null) + continue; + for (int j = 0; j < dfs.length; j++) + openFile(dfs[j]); + swarmConfig.lastPath = fs[i].getParent(); + } else { + openFile(fs[i]); + swarmConfig.lastPath = fs[i].getParent(); + } + } + } + } + } + + private class SaveActionListener implements ActionListener { + public void actionPerformed(final ActionEvent e) { + final AbstractWavePanel selected = getSingleSelected(); + if (selected == null) + return; + + final JFileChooser chooser = FileChooser.getFileChooser(); + chooser.resetChoosableFileFilters(); + chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + chooser.setMultiSelectionEnabled(false); + chooser.setDialogTitle("Save Wave"); + + for (final FileType ft : FileType.values()) { + if (ft == FileType.UNKNOWN) + continue; + + final ExtensionFileFilter f = new ExtensionFileFilter(ft.extension, ft.description); + chooser.addChoosableFileFilter(f); + } + + chooser.setFileFilter(chooser.getAcceptAllFileFilter()); + + final File lastPath = new File(swarmConfig.lastPath); + chooser.setCurrentDirectory(lastPath); + final String fileName = selected.getChannel().replace(' ', '_') + ".sac"; + chooser.setSelectedFile(new File(fileName)); + final int result = chooser.showSaveDialog(applicationFrame); + if (result == JFileChooser.APPROVE_OPTION) { + final File f = chooser.getSelectedFile(); + boolean confirm = true; + if (f.exists()) { + if (f.isDirectory()) { + JOptionPane.showMessageDialog(applicationFrame, "You can not select an existing directory.", + "Error", JOptionPane.ERROR_MESSAGE); + return; + } + confirm = false; + final int choice = JOptionPane.showConfirmDialog(applicationFrame, "File exists, overwrite?", + "Confirm", JOptionPane.YES_NO_OPTION); + if (choice == JOptionPane.YES_OPTION) + confirm = true; + } + + if (confirm) { + try { + swarmConfig.lastPath = f.getParent(); + final String fn = f.getPath(); + final SeismicDataFile file = SeismicDataFile.getFile(fn); + // String channel = selected.getChannel().replace(' ', + // '_'); + final Wave wave = selected.getWave(); + // file.putWave(channel, wave); + file.putWave(selected.getChannel(), wave); + file.write(); + } catch (final FileNotFoundException ex) { + JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Directory does not exist.", "Error", + JOptionPane.ERROR_MESSAGE); + } catch (final IOException ex) { + JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Error writing file.", "Error", + JOptionPane.ERROR_MESSAGE); + } + } + } + } + } + + private class SaveAllActionListener implements ActionListener { + public void actionPerformed(final ActionEvent e) { + if (waves.size() <= 0) + return; + + final FileTypeDialog dialog = new FileTypeDialog(); + FileType fileType = FileType.UNKNOWN; + if (!dialog.isOpen() || (dialog.isOpen() && !dialog.isAssumeSame())) { + dialog.setVisible(true); + + if (dialog.isCancelled()) + fileType = FileType.UNKNOWN; + else + fileType = dialog.getFileType(); + + } + + final JFileChooser chooser = FileChooser.getFileChooser(); + chooser.resetChoosableFileFilters(); + chooser.setMultiSelectionEnabled(false); + chooser.setDialogTitle("Save All Files"); + final File lastPath = new File(swarmConfig.lastPath); + chooser.setCurrentDirectory(lastPath); + + if (!fileType.isCollective) + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + else + chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + + final int result = chooser.showSaveDialog(applicationFrame); + if (result == JFileChooser.CANCEL_OPTION) + return; + + final File f = chooser.getSelectedFile(); + + if (f == null) { + JOptionPane.showMessageDialog(applicationFrame, "Save location not understood.", "Error", + JOptionPane.ERROR_MESSAGE); + return; + } + + if (result == JFileChooser.APPROVE_OPTION) { + try { + if (f.exists() && !f.isDirectory()) + return; + if (!f.exists()) + f.mkdir(); + for (final AbstractWavePanel wvp : waves) { + Wave sw = wvp.getWave(); + + if (sw != null) { + sw = sw.subset(wvp.getStartTime(), wvp.getEndTime()); + final String date = saveAllDateFormat.format(J2kSec.asDate(sw.getStartTime())); + final File dir = new File(f.getPath() + File.separatorChar + date); + if (!dir.exists()) + dir.mkdir(); + + swarmConfig.lastPath = f.getParent(); + final String fn = dir + File.separator + wvp.getChannel().replace(' ', '_') + + fileType.extension; + final SeismicDataFile file = SeismicDataFile.getFile(fn); + file.putWave(wvp.getChannel(), sw); + file.write(); + } + } + swarmConfig.lastPath = f.getPath(); + } catch (final FileNotFoundException ex) { + JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Directory does not exist.", "Error", + JOptionPane.ERROR_MESSAGE); + } catch (final IOException ex) { + JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Error writing file.", "Error", + JOptionPane.ERROR_MESSAGE); + } + } + } + } + + public void openFile(final File f) { + SeismicDataFile file = SeismicDataFile.getFile(f); + if (file == null) { + final FileTypeDialog dialog = new FileTypeDialog(); + FileType fileType = FileType.UNKNOWN; + if (!dialog.isOpen() || (dialog.isOpen() && !dialog.isAssumeSame())) { + dialog.setVisible(true); + + if (dialog.isCancelled()) + fileType = FileType.UNKNOWN; + else + fileType = dialog.getFileType(); + + } + file = SeismicDataFile.getFile(f, fileType); + } + + if (file == null) { + JOptionPane.showMessageDialog(applicationFrame, + "There was an error opening the file, '" + f.getName() + "'.", "Error", JOptionPane.ERROR_MESSAGE); + return; + } + + try { + file.read(); + } catch (final IOException e) { + JOptionPane.showMessageDialog(applicationFrame, + "There was an error opening the file, '" + f.getName() + "'.\n" + e.getMessage(), "Error", + JOptionPane.ERROR_MESSAGE); + } + + for (final String channel : file.getChannels()) { + final WaveViewPanel wvp = new WaveViewPanel(); + wvp.setChannel(channel); + final CachedDataSource cache = CachedDataSource.getInstance(); + + final Wave wave = file.getWave(channel); + cache.putWave(channel, wave); + wvp.setDataSource(cache); + wvp.setWave(wave, wave.getStartTime(), wave.getEndTime()); + WaveClipboardFrame.this.addWave(new WaveViewPanel(wvp)); + } + } + + private void doButtonEnables() { + final boolean enable = (waves == null || waves.size() == 0); + saveButton.setEnabled(!enable); + sortButton.setEnabled(!enable); + saveAllButton.setEnabled(!enable); + syncButton.setEnabled(!enable); + removeAllButton.setEnabled(!enable); + saveAllButton.setEnabled(!enable); + + final boolean allowSingle = (selectedSet.size() == 1); + upButton.setEnabled(allowSingle); + downButton.setEnabled(allowSingle); + sortButton.setEnabled(allowSingle); + syncButton.setEnabled(allowSingle); + saveButton.setEnabled(allowSingle); + + final boolean allowMulti = (selectedSet.size() > 0); + backButton.setEnabled(allowMulti); + expXButton.setEnabled(allowMulti); + compXButton.setEnabled(allowMulti); + backButton.setEnabled(allowMulti); + forwardButton.setEnabled(allowMulti); + histButton.setEnabled(allowMulti); + removeButton.setEnabled(allowMulti); + gotoButton.setEnabled(allowMulti); + } + + public synchronized void sortChannelsByNearest() { + final AbstractWavePanel p = getSingleSelected(); + if (p == null) + return; + + final ArrayList sorted = new ArrayList(waves.size()); + for (final AbstractWavePanel wave : waves) + sorted.add(wave); + + final Metadata smd = swarmConfig.getMetadata(p.getChannel()); + if (smd == null || Double.isNaN(smd.getLongitude()) || Double.isNaN(smd.getLatitude())) + return; + + Collections.sort(sorted, new Comparator() { + public int compare(final AbstractWavePanel wvp1, final AbstractWavePanel wvp2) { + Metadata md = swarmConfig.getMetadata(wvp1.getChannel()); + final double d1 = smd.distanceTo(md); + md = swarmConfig.getMetadata(wvp2.getChannel()); + final double d2 = smd.distanceTo(md); + return Double.compare(d1, d2); + } + }); + + removeWaves(); + for (final AbstractWavePanel wave : sorted) + addWave(wave); + select(p); + } + + public synchronized AbstractWavePanel getSingleSelected() { + if (selectedSet.size() != 1) + return null; + + AbstractWavePanel p = null; + for (final AbstractWavePanel panel : selectedSet) + p = panel; + + return p; + } + + public synchronized void syncChannels() { + final AbstractWavePanel p = getSingleSelected(); + if (p == null) + return; + + final double st = p.getStartTime(); + final double et = p.getEndTime(); + + // TODO: thread bug here. must synch iterator below + final SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + List copy = null; + synchronized (WaveClipboardFrame.this) { + copy = new ArrayList(waves); + } + for (final AbstractWavePanel wvp : copy) { + if (wvp != p) { + if (wvp.getDataSource() != null) { + addHistory(wvp, new double[] { wvp.getStartTime(), wvp.getEndTime() }); + final Wave sw = wvp.getDataSource().getWave(wvp.getChannel(), st, et); + wvp.setWave(sw, st, et); + } + } + } + return null; + } + + @Override + public void finished() { + repaint(); + } + }; + worker.start(); + } + + public void setStatusText(final String s) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + statusLabel.setText(s); + } + }); + } + + public WaveViewPanel getSelected() { + return null; + // return selected; + } + + public synchronized void addWave(final AbstractWavePanel p) { + p.addListener(selectListener); + p.setOffsets(54, 8, 21, 19); + p.setAllowClose(true); + p.setStatusLabel(statusLabel); + p.setAllowDragging(true); + p.setDisplayTitle(true); + final int w = scrollPane.getViewport().getSize().width; + p.setSize(w, calculateWaveHeight()); + p.setBottomBorderColor(Color.GRAY); + p.createImage(); + waveBox.add(p); + waves.add(p); + doButtonEnables(); + waveBox.validate(); + } + + private synchronized void deselect(final AbstractWavePanel p) { + selectedSet.remove(p); + waveToolbar.removeSettings(p.getSettings()); + p.setBackgroundColor(BACKGROUND_COLOR); + p.createImage(); + doButtonEnables(); + } + + private synchronized void deselectAll() { + final WaveViewPanel[] panels = selectedSet.toArray(new WaveViewPanel[0]); + for (final WaveViewPanel p : panels) + deselect(p); + } + + private synchronized void select(final AbstractWavePanel p) { + if (p == null || selectedSet.contains(p)) + return; + + selectedSet.add(p); + doButtonEnables(); + p.setBackgroundColor(SELECT_COLOR); + DataChooser.getInstance().setNearest(p.getChannel()); + p.createImage(); + waveToolbar.addSettings(p.getSettings()); + } + + private synchronized void remove(final AbstractWavePanel p) { + int i = 0; + for (i = 0; i < waveBox.getComponentCount(); i++) { + if (p == waveBox.getComponent(i)) + break; + } + + p.removeListener(selectListener); + p.getDataSource().close(); + setStatusText(" "); + waveBox.remove(i); + waves.remove(p); + histories.remove(p); + doButtonEnables(); + waveBox.validate(); + selectedSet.remove(p); + lastClickedIndex = Math.min(lastClickedIndex, waveBox.getComponentCount() - 1); + waveToolbar.removeSettings(p.getSettings()); + repaint(); + } + + protected int getWaveIndex(final AbstractWavePanel p) { + int i = 0; + for (i = 0; i < waveBox.getComponentCount(); i++) { + if (p == waveBox.getComponent(i)) + break; + } + return i; + } + + public synchronized void remove() { + final WaveViewPanel[] panels = selectedSet.toArray(new WaveViewPanel[0]); + for (final WaveViewPanel p : panels) + remove(p); + } + + public synchronized void moveDown() { + final AbstractWavePanel p = getSingleSelected(); + if (p == null) + return; + + final int i = waves.indexOf(p); + if (i == waves.size() - 1) + return; + + waves.remove(i); + waves.add(i + 1, p); + waveBox.remove(p); + waveBox.add(p, i + 1); + waveBox.validate(); + repaint(); + } + + public synchronized void moveUp() { + final AbstractWavePanel p = getSingleSelected(); + if (p == null) + return; + + final int i = waves.indexOf(p); + if (i == 0) + return; + + waves.remove(i); + waves.add(i - 1, p); + waveBox.remove(p); + waveBox.add(p, i - 1); + waveBox.validate(); + repaint(); + } + + public void resizeWaves() { + final SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + final int w = scrollPane.getViewport().getSize().width; + for (final AbstractWavePanel wave : waves) { + wave.setSize(w, calculateWaveHeight()); + wave.createImage(); + } + return null; + } + + @Override + public void finished() { + waveBox.validate(); + validate(); + repaint(); + } + }; + worker.start(); + } + + public void removeWaves() { + while (waves.size() > 0) { + remove(waves.get(0)); + } + + waveBox.validate(); + scrollPane.validate(); + doButtonEnables(); + repaint(); + } + + private void addHistory(final AbstractWavePanel wvp, final double[] t) { + Stack history = histories.get(wvp); + if (history == null) { + history = new Stack(); + histories.put(wvp, history); + } + history.push(t); + } + + public void gotoTime(final AbstractWavePanel wvp, String t) { + double j2k = Double.NaN; + try { + if (t.length() == 12) + t = t + "30"; + + j2k = J2kSec.parse("yyyyMMddHHmmss", t); + } catch (final Exception e) { + JOptionPane.showMessageDialog(applicationFrame, "Illegal time value.", "Error", JOptionPane.ERROR_MESSAGE); + } + + if (!Double.isNaN(j2k)) { + double dt = 60; + if (wvp.getWave() != null) { + final double st = wvp.getStartTime(); + final double et = wvp.getEndTime(); + final double[] ts = new double[] { st, et }; + addHistory(wvp, ts); + dt = (et - st); + } + + final double tzo = swarmConfig.getTimeZone(wvp.getChannel()).getOffset(System.currentTimeMillis()) / 1000; + + final double nst = j2k - tzo - dt / 2; + final double net = nst + dt; + + fetchNewWave(wvp, nst, net); + } + } + + public void gotoTime(final String t) { + for (final AbstractWavePanel p : selectedSet) + gotoTime(p, t); + } + + public void scaleTime(final AbstractWavePanel wvp, final double pct) { + final double st = wvp.getStartTime(); + final double et = wvp.getEndTime(); + final double[] t = new double[] { st, et }; + addHistory(wvp, t); + final double dt = (et - st) * (1 - pct); + final double mt = (et - st) / 2 + st; + final double nst = mt - dt / 2; + final double net = mt + dt / 2; + fetchNewWave(wvp, nst, net); + } + + public void scaleTime(final double pct) { + for (final AbstractWavePanel p : selectedSet) + scaleTime(p, pct); + } + + public void back(final AbstractWavePanel wvp) { + final Stack history = histories.get(wvp); + if (history == null || history.empty()) + return; + + final double[] t = history.pop(); + fetchNewWave(wvp, t[0], t[1]); + } + + public void back() { + for (final AbstractWavePanel p : selectedSet) + back(p); + } + + private void shiftTime(final AbstractWavePanel wvp, final double pct) { + final double st = wvp.getStartTime(); + final double et = wvp.getEndTime(); + final double[] t = new double[] { st, et }; + addHistory(wvp, t); + final double dt = (et - st) * pct; + final double nst = st + dt; + final double net = et + dt; + fetchNewWave(wvp, nst, net); + } + + public void shiftTime(final double pct) { + for (final AbstractWavePanel p : selectedSet) + shiftTime(p, pct); + } + + public void repositionWaves(final double st, final double et) { + for (final AbstractWavePanel wave : waves) { + fetchNewWave(wave, st, et); + } + } + + public Throbber getThrobber() { + return throbber; + } + + // TODO: This isn't right, this should be a method of waveviewpanel + private void fetchNewWave(final AbstractWavePanel wvp, final double nst, final double net) { + final SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + throbber.increment(); + final SeismicDataSource sds = wvp.getDataSource(); + // Hacky fix for bug #84 + Wave sw = null; + if (sds instanceof CachedDataSource) + sw = ((CachedDataSource) sds).getBestWave(wvp.getChannel(), nst, net); + else + sw = sds.getWave(wvp.getChannel(), nst, net); + wvp.setWave(sw, nst, net); + wvp.repaint(); + return null; + } + + @Override + public void finished() { + throbber.decrement(); + repaint(); + } + }; + worker.start(); + } + + @Override + public void setMaximum(final boolean max) throws PropertyVetoException { + if (max) { + swarmConfig.clipboardX = getX(); + swarmConfig.clipboardY = getY(); + } + super.setMaximum(max); + } + + @Override + public void paint(final Graphics g) { + super.paint(g); + if (waves.size() == 0) { + final Dimension dim = this.getSize(); + g.setColor(Color.black); + g.drawString("Clipboard empty.", dim.width / 2 - 40, dim.height / 2); + } + } + + @Override + public void setVisible(final boolean isVisible) { + super.setVisible(isVisible); + if (isVisible) + toFront(); + } + + private static class WaveClipboardFrameHolder { + public static WaveClipboardFrame waveClipiboardFrame = new WaveClipboardFrame(); + } } From 99e9740ba82b0442df336a878ce5814f2510a40f Mon Sep 17 00:00:00 2001 From: tparker Date: Tue, 31 Jan 2017 09:05:58 -0900 Subject: [PATCH 48/67] Update import --- .../gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesClient.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesClient.java b/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesClient.java index 59b8a568..7bf92dc6 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesClient.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesClient.java @@ -12,6 +12,7 @@ import gov.usgs.plot.data.Wave; import gov.usgs.volcanoes.swarm.ChannelInfo; import gov.usgs.volcanoes.swarm.SwarmConfig; +import gov.usgs.volcanoes.swarm.data.DataSelectReader; import gov.usgs.volcanoes.swarm.data.SeismicDataSource; public class WebServicesClient extends AbstractDataRecordClient { From 97a9254f2a68af01634f3925689d616314848cfa Mon Sep 17 00:00:00 2001 From: tparker Date: Tue, 31 Jan 2017 09:09:02 -0900 Subject: [PATCH 49/67] Correct wave panel class for remove --- .../java/gov/usgs/volcanoes/swarm/wave/WaveClipboardFrame.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveClipboardFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveClipboardFrame.java index 692c441b..8456ad21 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveClipboardFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveClipboardFrame.java @@ -942,7 +942,7 @@ private synchronized void select(final AbstractWavePanel p) { waveToolbar.addSettings(p.getSettings()); } - private synchronized void remove(final WaveViewPanel p) { + private synchronized void remove(final AbstractWavePanel p) { int i = 0; for (i = 0; i < waveBox.getComponentCount(); i++) { if (p == waveBox.getComponent(i)) @@ -1037,7 +1037,6 @@ public void finished() { public void removeWaves() { while (waves.size() > 0) { remove(waves.get(0)); - waves.remove(0); } waveBox.validate(); From d358e2d6163994589411750339fe5053662521ef Mon Sep 17 00:00:00 2001 From: Tom Parker Date: Tue, 31 Jan 2017 09:52:16 -0900 Subject: [PATCH 50/67] quote command line args --- swarm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swarm.sh b/swarm.sh index e0a18c55..cbf5ed32 100644 --- a/swarm.sh +++ b/swarm.sh @@ -1 +1 @@ -java -Duser.country=US -Duser.language=us -jar lib/swarm.jar $* +java -Duser.country=US -Duser.language=us -jar lib/swarm.jar "$@" From cf70b86bbb9bd3bbf3480be738104dfb072a25cb Mon Sep 17 00:00:00 2001 From: tparker Date: Tue, 31 Jan 2017 09:54:12 -0900 Subject: [PATCH 51/67] Update deps --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index cf55295f..6b48a36f 100644 --- a/pom.xml +++ b/pom.xml @@ -478,12 +478,12 @@ gov.usgs.volcanoes usgs - 1.3.1 + 1.3.3 gov.usgs.volcanoes volcano-core - [1.3.3,) + [1.3.7,) gov.usgs.volcanoes From ca09a8f861dbabe16fdff542305c66b7c6203573 Mon Sep 17 00:00:00 2001 From: tparker Date: Tue, 31 Jan 2017 10:04:34 -0900 Subject: [PATCH 52/67] Cleanup --- .../swarm/wave/WaveClipboardFrame.java | 2243 ++++++++--------- 1 file changed, 1118 insertions(+), 1125 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveClipboardFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveClipboardFrame.java index 8456ad21..d8aae924 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveClipboardFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveClipboardFrame.java @@ -79,1129 +79,1122 @@ * @author Dan Cervelli */ public class WaveClipboardFrame extends SwarmFrame { - public static final long serialVersionUID = -1; - private static final Color SELECT_COLOR = new Color(200, 220, 241); - private static final Color BACKGROUND_COLOR = new Color(0xf7, 0xf7, 0xf7); - - private JScrollPane scrollPane; - private Box waveBox; - private final List waves; - private final Set selectedSet; - private JToolBar toolbar; - private JPanel mainPanel; - private JLabel statusLabel; - private JToggleButton linkButton; - private JButton sizeButton; - private JButton syncButton; - private JButton sortButton; - private JButton removeAllButton; - private JButton saveButton; - private JButton saveAllButton; - private JButton openButton; - private JButton captureButton; - private JButton histButton; - private final DateFormat saveAllDateFormat; - - private WaveViewPanelListener selectListener; - private WaveViewSettingsToolbar waveToolbar; - - private JButton upButton; - private JButton downButton; - private JButton removeButton; - private JButton compXButton; - private JButton expXButton; - private JButton copyButton; - private JButton forwardButton; - private JButton backButton; - private JButton gotoButton; - - private JPopupMenu popup; - - private final Map> histories; - - private final HelicorderViewPanelListener linkListener; - - private boolean heliLinked = true; - - private Throbber throbber; - - private int waveHeight = -1; - - private int lastClickedIndex = -1; - - private WaveClipboardFrame() { - super("Wave Clipboard", true, true, true, false); - this.setFocusable(true); - selectedSet = new HashSet(); - saveAllDateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); - saveAllDateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); - waves = new ArrayList(); - histories = new HashMap>(); - createUI(); - linkListener = new HelicorderViewPanelListener() { - public void insetCreated(final double st, final double et) { - if (heliLinked) - repositionWaves(st, et); - } - }; - } - - public static WaveClipboardFrame getInstance() { - return WaveClipboardFrameHolder.waveClipiboardFrame; - } - - public HelicorderViewPanelListener getLinkListener() { - return linkListener; - } - - private void createUI() { - this.setFrameIcon(Icons.clipboard); - this.setSize(swarmConfig.clipboardWidth, swarmConfig.clipboardHeight); - this.setLocation(swarmConfig.clipboardX, swarmConfig.clipboardY); - this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - - toolbar = SwarmUtil.createToolBar(); - mainPanel = new JPanel(new BorderLayout()); - - createMainButtons(); - createWaveButtons(); - - mainPanel.add(toolbar, BorderLayout.NORTH); - - waveBox = new Box(BoxLayout.Y_AXIS); - scrollPane = new JScrollPane(waveBox); - scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); - scrollPane.getVerticalScrollBar().setUnitIncrement(40); - mainPanel.add(scrollPane, BorderLayout.CENTER); - - statusLabel = new JLabel(" "); - statusLabel.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 1)); - mainPanel.add(statusLabel, BorderLayout.SOUTH); - - mainPanel.setBorder(BorderFactory.createEmptyBorder(0, 2, 1, 2)); - this.setContentPane(mainPanel); - - createListeners(); - doButtonEnables(); - } - - private void createMainButtons() { - openButton = - SwarmUtil.createToolBarButton(Icons.open, "Open a saved wave", new OpenActionListener()); - toolbar.add(openButton); - - saveButton = - SwarmUtil.createToolBarButton(Icons.save, "Save selected wave", new SaveActionListener()); - saveButton.setEnabled(false); - toolbar.add(saveButton); - - saveAllButton = - SwarmUtil.createToolBarButton(Icons.saveall, "Save all waves", new SaveAllActionListener()); - saveAllButton.setEnabled(false); - toolbar.add(saveAllButton); - - toolbar.addSeparator(); - - linkButton = SwarmUtil.createToolBarToggleButton(Icons.helilink, - "Synchronize times with helicorder wave", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - heliLinked = linkButton.isSelected(); - } - }); - linkButton.setSelected(heliLinked); - toolbar.add(linkButton); - - syncButton = SwarmUtil.createToolBarButton(Icons.clock, "Synchronize times with selected wave", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - syncChannels(); - } - }); - syncButton.setEnabled(false); - toolbar.add(syncButton); - - sortButton = SwarmUtil.createToolBarButton(Icons.geosort, - "Sort waves by nearest to selected wave", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - sortChannelsByNearest(); - } - }); - sortButton.setEnabled(false); - toolbar.add(sortButton); - - toolbar.addSeparator(); - - sizeButton = SwarmUtil.createToolBarButton(Icons.resize, "Set clipboard wave size", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - doSizePopup(sizeButton.getX(), sizeButton.getY() + 2 * sizeButton.getHeight()); - } - }); - toolbar.add(sizeButton); - - removeAllButton = SwarmUtil.createToolBarButton(Icons.deleteall, - "Remove all waves from clipboard", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - removeWaves(); - } - }); - removeAllButton.setEnabled(false); - toolbar.add(removeAllButton); - - toolbar.addSeparator(); - captureButton = SwarmUtil.createToolBarButton(Icons.camera, "Save clipboard image (P)", - new CaptureActionListener()); - UiUtils.mapKeyStrokeToButton(this, "P", "capture", captureButton); - toolbar.add(captureButton); - } - - // TODO: don't write image on event thread - // TODO: unify with MapFrame.CaptureActionListener - class CaptureActionListener implements ActionListener { - public void actionPerformed(final ActionEvent e) { - if (waves == null || waves.size() == 0) - return; - - final JFileChooser chooser = FileChooser.getFileChooser(); - final File lastPath = new File(swarmConfig.lastPath); - chooser.setCurrentDirectory(lastPath); - chooser.setSelectedFile(new File("clipboard.png")); - chooser.setDialogTitle("Save Clipboard Screen Capture"); - final int result = chooser.showSaveDialog(applicationFrame); - File f = null; - if (result == JFileChooser.APPROVE_OPTION) { - f = chooser.getSelectedFile(); - - if (f.exists()) { - final int choice = JOptionPane.showConfirmDialog(applicationFrame, - "File exists, overwrite?", "Confirm", JOptionPane.YES_NO_OPTION); - if (choice != JOptionPane.YES_OPTION) - return; - } - swarmConfig.lastPath = f.getParent(); - } - if (f == null) - return; - - int height = 0; - final int width = waves.get(0).getWidth(); - for (final AbstractWavePanel panel : waves) - height += panel.getHeight(); - - final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); - final Graphics g = image.getGraphics(); - for (final AbstractWavePanel panel : waves) { - panel.paint(g); - g.translate(0, panel.getHeight()); - } - try { - final PngEncoderB png = new PngEncoderB(image, false, PngEncoder.FILTER_NONE, 7); - final FileOutputStream out = new FileOutputStream(f); - final byte[] bytes = png.pngEncode(); - out.write(bytes); - out.close(); - } catch (final Exception ex) { - ex.printStackTrace(); - } - } - } - - private void createWaveButtons() { - toolbar.addSeparator(); - - backButton = SwarmUtil.createToolBarButton(Icons.left, "Scroll back time 20% (Left arrow)", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - shiftTime(-0.20); - } - }); - UiUtils.mapKeyStrokeToButton(this, "LEFT", "backward1", backButton); - toolbar.add(backButton); - - forwardButton = SwarmUtil.createToolBarButton(Icons.right, - "Scroll forward time 20% (Right arrow)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - shiftTime(0.20); - } - }); - toolbar.add(forwardButton); - UiUtils.mapKeyStrokeToButton(this, "RIGHT", "forward1", forwardButton); - - gotoButton = - SwarmUtil.createToolBarButton(Icons.gototime, "Go to time (Ctrl-G)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - final String t = JOptionPane.showInputDialog(applicationFrame, - "Input time in 'YYYYMMDDhhmm[ss]' format:", "Go to Time", - JOptionPane.PLAIN_MESSAGE); - if (t != null) - gotoTime(t); - } - }); - toolbar.add(gotoButton); - UiUtils.mapKeyStrokeToButton(this, "ctrl G", "goto", gotoButton); - - compXButton = SwarmUtil.createToolBarButton(Icons.xminus, - "Shrink sample time 20% (Alt-left arrow, +)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - scaleTime(0.20); - } - }); - toolbar.add(compXButton); - UiUtils.mapKeyStrokeToButton(this, "alt LEFT", "compx", compXButton); - UiUtils.mapKeyStrokeToButton(this, "EQUALS", "compx2", compXButton); - UiUtils.mapKeyStrokeToButton(this, "shift EQUALS", "compx2", compXButton); - - expXButton = SwarmUtil.createToolBarButton(Icons.xplus, - "Expand sample time 20% (Alt-right arrow, -)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - scaleTime(-0.20); - } - }); - toolbar.add(expXButton); - UiUtils.mapKeyStrokeToButton(this, "alt RIGHT", "expx", expXButton); - UiUtils.mapKeyStrokeToButton(this, "MINUS", "expx", expXButton); - - histButton = SwarmUtil.createToolBarButton(Icons.timeback, "Last time settings (Backspace)", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - back(); - } - }); - UiUtils.mapKeyStrokeToButton(this, "BACK_SPACE", "back", histButton); - toolbar.add(histButton); - toolbar.addSeparator(); - - waveToolbar = new WaveViewSettingsToolbar(null, toolbar, this); - - copyButton = SwarmUtil.createToolBarButton(Icons.clipboard, - "Place another copy of wave on clipboard (C or Ctrl-C)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - // TODO: implement - // if (selected != null) - // { - // WaveViewPanel wvp = new WaveViewPanel(selected); - // wvp.setBackgroundColor(BACKGROUND_COLOR); - // addWave(wvp); - // } - } - }); - UiUtils.mapKeyStrokeToButton(this, "C", "clipboard1", copyButton); - UiUtils.mapKeyStrokeToButton(this, "control C", "clipboard2", copyButton); - toolbar.add(copyButton); - - toolbar.addSeparator(); - - upButton = SwarmUtil.createToolBarButton(Icons.up, "Move wave up in clipboard (Up arrow)", - new ActionListener() { - public void actionPerformed(final ActionEvent e) { - moveUp(); - } - }); - UiUtils.mapKeyStrokeToButton(this, "UP", "up", upButton); - toolbar.add(upButton); - - downButton = SwarmUtil.createToolBarButton(Icons.down, - "Move wave down in clipboard (Down arrow)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - moveDown(); - } - }); - UiUtils.mapKeyStrokeToButton(this, "DOWN", "down", downButton); - toolbar.add(downButton); - - removeButton = SwarmUtil.createToolBarButton(Icons.delete, - "Remove wave from clipboard (Delete)", new ActionListener() { - public void actionPerformed(final ActionEvent e) { - remove(); - } - }); - UiUtils.mapKeyStrokeToButton(this, "DELETE", "remove", removeButton); - toolbar.add(removeButton); - - toolbar.add(Box.createHorizontalGlue()); - - throbber = new Throbber(); - toolbar.add(throbber); - - UiUtils.mapKeyStrokeToAction(this, "control A", "selectAll", new AbstractAction() { - private static final long serialVersionUID = 1L; - - public void actionPerformed(final ActionEvent e) { - for (final AbstractWavePanel wave : waves) - select(wave); - } - }); - } - - private void createListeners() { - this.addInternalFrameListener(new InternalFrameAdapter() { - @Override - public void internalFrameActivated(final InternalFrameEvent e) {} - - @Override - public void internalFrameDeiconified(final InternalFrameEvent e) { - resizeWaves(); - } - - @Override - public void internalFrameClosing(final InternalFrameEvent e) { - setVisible(false); - } - - @Override - public void internalFrameClosed(final InternalFrameEvent e) {} - }); - - this.addComponentListener(new ComponentAdapter() { - @Override - public void componentResized(final ComponentEvent e) { - resizeWaves(); - } - }); - - WaveViewTime.addTimeListener(new TimeListener() { - public void timeChanged(final double j2k) { - for (final AbstractWavePanel panel : waves) { - if (panel != null) - panel.setCursorMark(j2k); - } - } - }); - - selectListener = new WaveViewPanelAdapter() { - @Override - public void mousePressed(final AbstractWavePanel src, final MouseEvent e, - final boolean dragging) { - requestFocusInWindow(); - final int thisIndex = getWaveIndex(src); - if (!e.isControlDown() && !e.isShiftDown() && !e.isAltDown()) { - deselectAll(); - select(src); - } else if (e.isControlDown()) { - if (selectedSet.contains(src)) - deselect(src); - else - select(src); - } else if (e.isShiftDown()) { - if (lastClickedIndex == -1) - select(src); - else { - deselectAll(); - final int min = Math.min(lastClickedIndex, thisIndex); - final int max = Math.max(lastClickedIndex, thisIndex); - for (int i = min; i <= max; i++) { - final WaveViewPanel ps = (WaveViewPanel) waveBox.getComponent(i); - select(ps); - } - } - } - lastClickedIndex = thisIndex; - } - - @Override - public void waveZoomed(final AbstractWavePanel src, final double st, final double et, - final double nst, final double net) { - final double[] t = new double[] {st, et}; - addHistory(src, t); - for (final AbstractWavePanel wvp : selectedSet) { - if (wvp != src) { - addHistory(wvp, t); - wvp.zoom(nst, net); - } - } - } - - @Override - public void waveClosed(final AbstractWavePanel src) { - remove(src); - } - }; - } - - private int calculateWaveHeight() { - if (waveHeight > 0) - return waveHeight; - - final int w = scrollPane.getViewport().getSize().width; - int h = (int) Math.round(w * 60.0 / 300.0); - h = Math.min(200, h); - h = Math.max(h, 80); - return h; - } - - private void setWaveHeight(final int s) { - waveHeight = s; - resizeWaves(); - } - - private void doSizePopup(final int x, final int y) { - if (popup == null) { - final String[] labels = new String[] {"Auto", null, "Tiny", "Small", "Medium", "Large"}; - final int[] sizes = new int[] {-1, -1, 50, 100, 160, 230}; - popup = new JPopupMenu(); - final ButtonGroup group = new ButtonGroup(); - for (int i = 0; i < labels.length; i++) { - if (labels[i] != null) { - final int size = sizes[i]; - final JRadioButtonMenuItem mi = new JRadioButtonMenuItem(labels[i]); - mi.addActionListener(new ActionListener() { - public void actionPerformed(final ActionEvent e) { - setWaveHeight(size); - } - }); - if (waveHeight == size) - mi.setSelected(true); - group.add(mi); - popup.add(mi); - } else - popup.addSeparator(); - } - } - popup.show(this, x, y); - } - - private class OpenActionListener implements ActionListener { - public void actionPerformed(final ActionEvent e) { - final JFileChooser chooser = FileChooser.getFileChooser(); - chooser.resetChoosableFileFilters(); - for (final FileType ft : FileType.getKnownTypes()) { - final ExtensionFileFilter f = new ExtensionFileFilter(ft.extension, ft.description); - chooser.addChoosableFileFilter(f); - } - chooser.setDialogTitle("Open Wave"); - chooser.setFileFilter(chooser.getAcceptAllFileFilter()); - final File lastPath = new File(swarmConfig.lastPath); - chooser.setCurrentDirectory(lastPath); - chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); - chooser.setMultiSelectionEnabled(true); - final int result = chooser.showOpenDialog(applicationFrame); - if (result == JFileChooser.APPROVE_OPTION) { - final File[] fs = chooser.getSelectedFiles(); - - for (int i = 0; i < fs.length; i++) { - if (fs[i].isDirectory()) { - final File[] dfs = fs[i].listFiles(); - if (dfs == null) - continue; - for (int j = 0; j < dfs.length; j++) - openFile(dfs[j]); - swarmConfig.lastPath = fs[i].getParent(); - } else { - openFile(fs[i]); - swarmConfig.lastPath = fs[i].getParent(); - } - } - } - } - } - - private class SaveActionListener implements ActionListener { - public void actionPerformed(final ActionEvent e) { - final AbstractWavePanel selected = getSingleSelected(); - if (selected == null) - return; - - final JFileChooser chooser = FileChooser.getFileChooser(); - chooser.resetChoosableFileFilters(); - chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); - chooser.setMultiSelectionEnabled(false); - chooser.setDialogTitle("Save Wave"); - - for (final FileType ft : FileType.values()) { - if (ft == FileType.UNKNOWN) - continue; - - final ExtensionFileFilter f = new ExtensionFileFilter(ft.extension, ft.description); - chooser.addChoosableFileFilter(f); - } - - chooser.setFileFilter(chooser.getAcceptAllFileFilter()); - - final File lastPath = new File(swarmConfig.lastPath); - chooser.setCurrentDirectory(lastPath); - final String fileName = selected.getChannel().replace(' ', '_') + ".sac"; - chooser.setSelectedFile(new File(fileName)); - final int result = chooser.showSaveDialog(applicationFrame); - if (result == JFileChooser.APPROVE_OPTION) { - final File f = chooser.getSelectedFile(); - boolean confirm = true; - if (f.exists()) { - if (f.isDirectory()) { - JOptionPane.showMessageDialog(applicationFrame, - "You can not select an existing directory.", "Error", JOptionPane.ERROR_MESSAGE); - return; - } - confirm = false; - final int choice = JOptionPane.showConfirmDialog(applicationFrame, - "File exists, overwrite?", "Confirm", JOptionPane.YES_NO_OPTION); - if (choice == JOptionPane.YES_OPTION) - confirm = true; - } - - if (confirm) { - try { - swarmConfig.lastPath = f.getParent(); - final String fn = f.getPath(); - final SeismicDataFile file = SeismicDataFile.getFile(fn); - // String channel = selected.getChannel().replace(' ', '_'); - final Wave wave = selected.getWave(); - // file.putWave(channel, wave); - file.putWave(selected.getChannel(), wave); - file.write(); - } catch (final FileNotFoundException ex) { - JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Directory does not exist.", - "Error", JOptionPane.ERROR_MESSAGE); - } catch (final IOException ex) { - JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Error writing file.", - "Error", JOptionPane.ERROR_MESSAGE); - } - } - } - } - } - - private class SaveAllActionListener implements ActionListener { - public void actionPerformed(final ActionEvent e) { - if (waves.size() <= 0) - return; - - final FileTypeDialog dialog = new FileTypeDialog(); - FileType fileType = FileType.UNKNOWN; - if (!dialog.isOpen() || (dialog.isOpen() && !dialog.isAssumeSame())) { - dialog.setVisible(true); - - if (dialog.isCancelled()) - fileType = FileType.UNKNOWN; - else - fileType = dialog.getFileType(); - - } - - final JFileChooser chooser = FileChooser.getFileChooser(); - chooser.resetChoosableFileFilters(); - chooser.setMultiSelectionEnabled(false); - chooser.setDialogTitle("Save All Files"); - final File lastPath = new File(swarmConfig.lastPath); - chooser.setCurrentDirectory(lastPath); - - if (!fileType.isCollective) - chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - else - chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); - - final int result = chooser.showSaveDialog(applicationFrame); - if (result == JFileChooser.CANCEL_OPTION) - return; - - final File f = chooser.getSelectedFile(); - - if (f == null) { - JOptionPane.showMessageDialog(applicationFrame, "Save location not understood.", "Error", - JOptionPane.ERROR_MESSAGE); - return; - } - - if (result == JFileChooser.APPROVE_OPTION) { - try { - if (f.exists() && !f.isDirectory()) - return; - if (!f.exists()) - f.mkdir(); - for (final AbstractWavePanel wvp : waves) { - Wave sw = wvp.getWave(); - - if (sw != null) { - sw = sw.subset(wvp.getStartTime(), wvp.getEndTime()); - final String date = saveAllDateFormat.format(J2kSec.asDate(sw.getStartTime())); - final File dir = new File(f.getPath() + File.separatorChar + date); - if (!dir.exists()) - dir.mkdir(); - - swarmConfig.lastPath = f.getParent(); - final String fn = - dir + File.separator + wvp.getChannel().replace(' ', '_') + fileType.extension; - final SeismicDataFile file = SeismicDataFile.getFile(fn); - file.putWave(wvp.getChannel(), sw); - file.write(); - } - } - swarmConfig.lastPath = f.getPath(); - } catch (final FileNotFoundException ex) { - JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Directory does not exist.", - "Error", JOptionPane.ERROR_MESSAGE); - } catch (final IOException ex) { - JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Error writing file.", "Error", - JOptionPane.ERROR_MESSAGE); - } - } - } - } - - public void openFile(final File f) { - SeismicDataFile file = SeismicDataFile.getFile(f); - if (file == null) { - final FileTypeDialog dialog = new FileTypeDialog(); - FileType fileType = FileType.UNKNOWN; - if (!dialog.isOpen() || (dialog.isOpen() && !dialog.isAssumeSame())) { - dialog.setVisible(true); - - if (dialog.isCancelled()) - fileType = FileType.UNKNOWN; - else - fileType = dialog.getFileType(); - - } - file = SeismicDataFile.getFile(f, fileType); - } - - if (file == null) { - JOptionPane.showMessageDialog(applicationFrame, - "There was an error opening the file, '" + f.getName() + "'.", "Error", - JOptionPane.ERROR_MESSAGE); - return; - } - - try { - file.read(); - } catch (final IOException e) { - JOptionPane.showMessageDialog(applicationFrame, - "There was an error opening the file, '" + f.getName() + "'.\n" + e.getMessage(), "Error", - JOptionPane.ERROR_MESSAGE); - } - - for (final String channel : file.getChannels()) { - final WaveViewPanel wvp = new WaveViewPanel(); - wvp.setChannel(channel); - final CachedDataSource cache = CachedDataSource.getInstance(); - - final Wave wave = file.getWave(channel); - cache.putWave(channel, wave); - wvp.setDataSource(cache); - wvp.setWave(wave, wave.getStartTime(), wave.getEndTime()); - WaveClipboardFrame.this.addWave(new WaveViewPanel(wvp)); - } - } - - private void doButtonEnables() { - final boolean enable = (waves == null || waves.size() == 0); - saveButton.setEnabled(!enable); - sortButton.setEnabled(!enable); - saveAllButton.setEnabled(!enable); - syncButton.setEnabled(!enable); - removeAllButton.setEnabled(!enable); - saveAllButton.setEnabled(!enable); - - final boolean allowSingle = (selectedSet.size() == 1); - upButton.setEnabled(allowSingle); - downButton.setEnabled(allowSingle); - sortButton.setEnabled(allowSingle); - syncButton.setEnabled(allowSingle); - saveButton.setEnabled(allowSingle); - - final boolean allowMulti = (selectedSet.size() > 0); - backButton.setEnabled(allowMulti); - expXButton.setEnabled(allowMulti); - compXButton.setEnabled(allowMulti); - backButton.setEnabled(allowMulti); - forwardButton.setEnabled(allowMulti); - histButton.setEnabled(allowMulti); - removeButton.setEnabled(allowMulti); - gotoButton.setEnabled(allowMulti); - } - - public synchronized void sortChannelsByNearest() { - final AbstractWavePanel p = getSingleSelected(); - if (p == null) - return; - - final ArrayList sorted = new ArrayList(waves.size()); - for (final AbstractWavePanel wave : waves) - sorted.add(wave); - - final Metadata smd = swarmConfig.getMetadata(p.getChannel()); - if (smd == null || Double.isNaN(smd.getLongitude()) || Double.isNaN(smd.getLatitude())) - return; - - Collections.sort(sorted, new Comparator() { - public int compare(final AbstractWavePanel wvp1, final AbstractWavePanel wvp2) { - Metadata md = swarmConfig.getMetadata(wvp1.getChannel()); - final double d1 = smd.distanceTo(md); - md = swarmConfig.getMetadata(wvp2.getChannel()); - final double d2 = smd.distanceTo(md); - return Double.compare(d1, d2); - } - }); - - removeWaves(); - for (final AbstractWavePanel wave : sorted) - addWave(wave); - select(p); - } - - public synchronized AbstractWavePanel getSingleSelected() { - if (selectedSet.size() != 1) - return null; - - AbstractWavePanel p = null; - for (final AbstractWavePanel panel : selectedSet) - p = panel; - - return p; - } - - public synchronized void syncChannels() { - final AbstractWavePanel p = getSingleSelected(); - if (p == null) - return; - - final double st = p.getStartTime(); - final double et = p.getEndTime(); - - // TODO: thread bug here. must synch iterator below - final SwingWorker worker = new SwingWorker() { - @Override - public Object construct() { - List copy = null; - synchronized (WaveClipboardFrame.this) { - copy = new ArrayList(waves); - } - for (final AbstractWavePanel wvp : copy) { - if (wvp != p) { - if (wvp.getDataSource() != null) { - addHistory(wvp, new double[] {wvp.getStartTime(), wvp.getEndTime()}); - final Wave sw = wvp.getDataSource().getWave(wvp.getChannel(), st, et); - wvp.setWave(sw, st, et); - } - } - } - return null; - } - - @Override - public void finished() { - repaint(); - } - }; - worker.start(); - } - - public void setStatusText(final String s) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - statusLabel.setText(s); - } - }); - } - - public WaveViewPanel getSelected() { - return null; - // return selected; - } - - public synchronized void addWave(final AbstractWavePanel p) { - p.addListener(selectListener); - p.setOffsets(54, 8, 21, 19); - p.setAllowClose(true); - p.setStatusLabel(statusLabel); - p.setAllowDragging(true); - p.setDisplayTitle(true); - final int w = scrollPane.getViewport().getSize().width; - p.setSize(w, calculateWaveHeight()); - p.setBottomBorderColor(Color.GRAY); - p.createImage(); - waveBox.add(p); - waves.add(p); - doButtonEnables(); - waveBox.validate(); - } - - private synchronized void deselect(final AbstractWavePanel p) { - selectedSet.remove(p); - waveToolbar.removeSettings(p.getSettings()); - p.setBackgroundColor(BACKGROUND_COLOR); - p.createImage(); - doButtonEnables(); - } - - private synchronized void deselectAll() { - final WaveViewPanel[] panels = selectedSet.toArray(new WaveViewPanel[0]); - for (final WaveViewPanel p : panels) - deselect(p); - } - - private synchronized void select(final AbstractWavePanel p) { - if (p == null || selectedSet.contains(p)) - return; - - selectedSet.add(p); - doButtonEnables(); - p.setBackgroundColor(SELECT_COLOR); - DataChooser.getInstance().setNearest(p.getChannel()); - p.createImage(); - waveToolbar.addSettings(p.getSettings()); - } - - private synchronized void remove(final AbstractWavePanel p) { - int i = 0; - for (i = 0; i < waveBox.getComponentCount(); i++) { - if (p == waveBox.getComponent(i)) - break; - } - - p.removeListener(selectListener); - p.getDataSource().close(); - setStatusText(" "); - waveBox.remove(i); - waves.remove(p); - histories.remove(p); - doButtonEnables(); - waveBox.validate(); - selectedSet.remove(p); - lastClickedIndex = Math.min(lastClickedIndex, waveBox.getComponentCount() - 1); - waveToolbar.removeSettings(p.getSettings()); - repaint(); - } - - protected int getWaveIndex(final AbstractWavePanel p) { - int i = 0; - for (i = 0; i < waveBox.getComponentCount(); i++) { - if (p == waveBox.getComponent(i)) - break; - } - return i; - } - - public synchronized void remove() { - final WaveViewPanel[] panels = selectedSet.toArray(new WaveViewPanel[0]); - for (final WaveViewPanel p : panels) - remove(p); - } - - public synchronized void moveDown() { - final AbstractWavePanel p = getSingleSelected(); - if (p == null) - return; - - final int i = waves.indexOf(p); - if (i == waves.size() - 1) - return; - - waves.remove(i); - waves.add(i + 1, p); - waveBox.remove(p); - waveBox.add(p, i + 1); - waveBox.validate(); - repaint(); - } - - public synchronized void moveUp() { - final AbstractWavePanel p = getSingleSelected(); - if (p == null) - return; - - final int i = waves.indexOf(p); - if (i == 0) - return; - - waves.remove(i); - waves.add(i - 1, p); - waveBox.remove(p); - waveBox.add(p, i - 1); - waveBox.validate(); - repaint(); - } - - public void resizeWaves() { - final SwingWorker worker = new SwingWorker() { - @Override - public Object construct() { - final int w = scrollPane.getViewport().getSize().width; - for (final AbstractWavePanel wave : waves) { - wave.setSize(w, calculateWaveHeight()); - wave.createImage(); - } - return null; - } - - @Override - public void finished() { - waveBox.validate(); - validate(); - repaint(); - } - }; - worker.start(); - } - - public void removeWaves() { - while (waves.size() > 0) { - remove(waves.get(0)); - } - - waveBox.validate(); - scrollPane.validate(); - doButtonEnables(); - repaint(); - } - - private void addHistory(final AbstractWavePanel wvp, final double[] t) { - Stack history = histories.get(wvp); - if (history == null) { - history = new Stack(); - histories.put(wvp, history); - } - history.push(t); - } - - public void gotoTime(final AbstractWavePanel wvp, String t) { - double j2k = Double.NaN; - try { - if (t.length() == 12) - t = t + "30"; - - j2k = J2kSec.parse("yyyyMMddHHmmss", t); - } catch (final Exception e) { - JOptionPane.showMessageDialog(applicationFrame, "Illegal time value.", "Error", - JOptionPane.ERROR_MESSAGE); - } - - if (!Double.isNaN(j2k)) { - double dt = 60; - if (wvp.getWave() != null) { - final double st = wvp.getStartTime(); - final double et = wvp.getEndTime(); - final double[] ts = new double[] {st, et}; - addHistory(wvp, ts); - dt = (et - st); - } - - final double tzo = - swarmConfig.getTimeZone(wvp.getChannel()).getOffset(System.currentTimeMillis()) / 1000; - - final double nst = j2k - tzo - dt / 2; - final double net = nst + dt; - - fetchNewWave(wvp, nst, net); - } - } - - public void gotoTime(final String t) { - for (final AbstractWavePanel p : selectedSet) - gotoTime(p, t); - } - - public void scaleTime(final AbstractWavePanel wvp, final double pct) { - final double st = wvp.getStartTime(); - final double et = wvp.getEndTime(); - final double[] t = new double[] {st, et}; - addHistory(wvp, t); - final double dt = (et - st) * (1 - pct); - final double mt = (et - st) / 2 + st; - final double nst = mt - dt / 2; - final double net = mt + dt / 2; - fetchNewWave(wvp, nst, net); - } - - public void scaleTime(final double pct) { - for (final AbstractWavePanel p : selectedSet) - scaleTime(p, pct); - } - - public void back(final AbstractWavePanel wvp) { - final Stack history = histories.get(wvp); - if (history == null || history.empty()) - return; - - final double[] t = history.pop(); - fetchNewWave(wvp, t[0], t[1]); - } - - public void back() { - for (final AbstractWavePanel p : selectedSet) - back(p); - } - - private void shiftTime(final AbstractWavePanel wvp, final double pct) { - final double st = wvp.getStartTime(); - final double et = wvp.getEndTime(); - final double[] t = new double[] {st, et}; - addHistory(wvp, t); - final double dt = (et - st) * pct; - final double nst = st + dt; - final double net = et + dt; - fetchNewWave(wvp, nst, net); - } - - public void shiftTime(final double pct) { - for (final AbstractWavePanel p : selectedSet) - shiftTime(p, pct); - } - - public void repositionWaves(final double st, final double et) { - for (final AbstractWavePanel wave : waves) { - fetchNewWave(wave, st, et); - } - } - - public Throbber getThrobber() { - return throbber; - } - - // TODO: This isn't right, this should be a method of waveviewpanel - private void fetchNewWave(final AbstractWavePanel wvp, final double nst, final double net) { - final SwingWorker worker = new SwingWorker() { - @Override - public Object construct() { - throbber.increment(); - final SeismicDataSource sds = wvp.getDataSource(); - // Hacky fix for bug #84 - Wave sw = null; - if (sds instanceof CachedDataSource) - sw = ((CachedDataSource) sds).getBestWave(wvp.getChannel(), nst, net); - else - sw = sds.getWave(wvp.getChannel(), nst, net); - wvp.setWave(sw, nst, net); - wvp.repaint(); - return null; - } - - @Override - public void finished() { - throbber.decrement(); - repaint(); - } - }; - worker.start(); - } - - @Override - public void setMaximum(final boolean max) throws PropertyVetoException { - if (max) { - swarmConfig.clipboardX = getX(); - swarmConfig.clipboardY = getY(); - } - super.setMaximum(max); - } - - @Override - public void paint(final Graphics g) { - super.paint(g); - if (waves.size() == 0) { - final Dimension dim = this.getSize(); - g.setColor(Color.black); - g.drawString("Clipboard empty.", dim.width / 2 - 40, dim.height / 2); - } - } - - @Override - public void setVisible(final boolean isVisible) { - super.setVisible(isVisible); - if (isVisible) - toFront(); - } - - private static class WaveClipboardFrameHolder { - public static WaveClipboardFrame waveClipiboardFrame = new WaveClipboardFrame(); - } + public static final long serialVersionUID = -1; + private static final Color SELECT_COLOR = new Color(200, 220, 241); + private static final Color BACKGROUND_COLOR = new Color(0xf7, 0xf7, 0xf7); + + private JScrollPane scrollPane; + private Box waveBox; + private final List waves; + private final Set selectedSet; + private JToolBar toolbar; + private JPanel mainPanel; + private JLabel statusLabel; + private JToggleButton linkButton; + private JButton sizeButton; + private JButton syncButton; + private JButton sortButton; + private JButton removeAllButton; + private JButton saveButton; + private JButton saveAllButton; + private JButton openButton; + private JButton captureButton; + private JButton histButton; + private final DateFormat saveAllDateFormat; + + private WaveViewPanelListener selectListener; + private WaveViewSettingsToolbar waveToolbar; + + private JButton upButton; + private JButton downButton; + private JButton removeButton; + private JButton compXButton; + private JButton expXButton; + private JButton copyButton; + private JButton forwardButton; + private JButton backButton; + private JButton gotoButton; + + private JPopupMenu popup; + + private final Map> histories; + + private final HelicorderViewPanelListener linkListener; + + private boolean heliLinked = true; + + private Throbber throbber; + + private int waveHeight = -1; + + private int lastClickedIndex = -1; + + private WaveClipboardFrame() { + super("Wave Clipboard", true, true, true, false); + this.setFocusable(true); + selectedSet = new HashSet(); + saveAllDateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); + saveAllDateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); + waves = new ArrayList(); + histories = new HashMap>(); + createUI(); + linkListener = new HelicorderViewPanelListener() { + public void insetCreated(final double st, final double et) { + if (heliLinked) + repositionWaves(st, et); + } + }; + } + + public static WaveClipboardFrame getInstance() { + return WaveClipboardFrameHolder.waveClipiboardFrame; + } + + public HelicorderViewPanelListener getLinkListener() { + return linkListener; + } + + private void createUI() { + this.setFrameIcon(Icons.clipboard); + this.setSize(swarmConfig.clipboardWidth, swarmConfig.clipboardHeight); + this.setLocation(swarmConfig.clipboardX, swarmConfig.clipboardY); + this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + + toolbar = SwarmUtil.createToolBar(); + mainPanel = new JPanel(new BorderLayout()); + + createMainButtons(); + createWaveButtons(); + + mainPanel.add(toolbar, BorderLayout.NORTH); + + waveBox = new Box(BoxLayout.Y_AXIS); + scrollPane = new JScrollPane(waveBox); + scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + scrollPane.getVerticalScrollBar().setUnitIncrement(40); + mainPanel.add(scrollPane, BorderLayout.CENTER); + + statusLabel = new JLabel(" "); + statusLabel.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 1)); + mainPanel.add(statusLabel, BorderLayout.SOUTH); + + mainPanel.setBorder(BorderFactory.createEmptyBorder(0, 2, 1, 2)); + this.setContentPane(mainPanel); + + createListeners(); + doButtonEnables(); + } + + private void createMainButtons() { + openButton = SwarmUtil.createToolBarButton(Icons.open, "Open a saved wave", new OpenActionListener()); + toolbar.add(openButton); + + saveButton = SwarmUtil.createToolBarButton(Icons.save, "Save selected wave", new SaveActionListener()); + saveButton.setEnabled(false); + toolbar.add(saveButton); + + saveAllButton = SwarmUtil.createToolBarButton(Icons.saveall, "Save all waves", new SaveAllActionListener()); + saveAllButton.setEnabled(false); + toolbar.add(saveAllButton); + + toolbar.addSeparator(); + + linkButton = SwarmUtil.createToolBarToggleButton(Icons.helilink, "Synchronize times with helicorder wave", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + heliLinked = linkButton.isSelected(); + } + }); + linkButton.setSelected(heliLinked); + toolbar.add(linkButton); + + syncButton = SwarmUtil.createToolBarButton(Icons.clock, "Synchronize times with selected wave", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + syncChannels(); + } + }); + syncButton.setEnabled(false); + toolbar.add(syncButton); + + sortButton = SwarmUtil.createToolBarButton(Icons.geosort, "Sort waves by nearest to selected wave", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + sortChannelsByNearest(); + } + }); + sortButton.setEnabled(false); + toolbar.add(sortButton); + + toolbar.addSeparator(); + + sizeButton = SwarmUtil.createToolBarButton(Icons.resize, "Set clipboard wave size", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + doSizePopup(sizeButton.getX(), sizeButton.getY() + 2 * sizeButton.getHeight()); + } + }); + toolbar.add(sizeButton); + + removeAllButton = SwarmUtil.createToolBarButton(Icons.deleteall, "Remove all waves from clipboard", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + removeWaves(); + } + }); + removeAllButton.setEnabled(false); + toolbar.add(removeAllButton); + + toolbar.addSeparator(); + captureButton = SwarmUtil.createToolBarButton(Icons.camera, "Save clipboard image (P)", + new CaptureActionListener()); + UiUtils.mapKeyStrokeToButton(this, "P", "capture", captureButton); + toolbar.add(captureButton); + } + + // TODO: don't write image on event thread + // TODO: unify with MapFrame.CaptureActionListener + class CaptureActionListener implements ActionListener { + public void actionPerformed(final ActionEvent e) { + if (waves == null || waves.size() == 0) + return; + + final JFileChooser chooser = FileChooser.getFileChooser(); + final File lastPath = new File(swarmConfig.lastPath); + chooser.setCurrentDirectory(lastPath); + chooser.setSelectedFile(new File("clipboard.png")); + chooser.setDialogTitle("Save Clipboard Screen Capture"); + final int result = chooser.showSaveDialog(applicationFrame); + File f = null; + if (result == JFileChooser.APPROVE_OPTION) { + f = chooser.getSelectedFile(); + + if (f.exists()) { + final int choice = JOptionPane.showConfirmDialog(applicationFrame, "File exists, overwrite?", + "Confirm", JOptionPane.YES_NO_OPTION); + if (choice != JOptionPane.YES_OPTION) + return; + } + swarmConfig.lastPath = f.getParent(); + } + if (f == null) + return; + + int height = 0; + final int width = waves.get(0).getWidth(); + for (final AbstractWavePanel panel : waves) + height += panel.getHeight(); + + final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); + final Graphics g = image.getGraphics(); + for (final AbstractWavePanel panel : waves) { + panel.paint(g); + g.translate(0, panel.getHeight()); + } + try { + final PngEncoderB png = new PngEncoderB(image, false, PngEncoder.FILTER_NONE, 7); + final FileOutputStream out = new FileOutputStream(f); + final byte[] bytes = png.pngEncode(); + out.write(bytes); + out.close(); + } catch (final Exception ex) { + ex.printStackTrace(); + } + } + } + + private void createWaveButtons() { + toolbar.addSeparator(); + + backButton = SwarmUtil.createToolBarButton(Icons.left, "Scroll back time 20% (Left arrow)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + shiftTime(-0.20); + } + }); + UiUtils.mapKeyStrokeToButton(this, "LEFT", "backward1", backButton); + toolbar.add(backButton); + + forwardButton = SwarmUtil.createToolBarButton(Icons.right, "Scroll forward time 20% (Right arrow)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + shiftTime(0.20); + } + }); + toolbar.add(forwardButton); + UiUtils.mapKeyStrokeToButton(this, "RIGHT", "forward1", forwardButton); + + gotoButton = SwarmUtil.createToolBarButton(Icons.gototime, "Go to time (Ctrl-G)", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + final String t = JOptionPane.showInputDialog(applicationFrame, + "Input time in 'YYYYMMDDhhmm[ss]' format:", "Go to Time", JOptionPane.PLAIN_MESSAGE); + if (t != null) + gotoTime(t); + } + }); + toolbar.add(gotoButton); + UiUtils.mapKeyStrokeToButton(this, "ctrl G", "goto", gotoButton); + + compXButton = SwarmUtil.createToolBarButton(Icons.xminus, "Shrink sample time 20% (Alt-left arrow, +)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + scaleTime(0.20); + } + }); + toolbar.add(compXButton); + UiUtils.mapKeyStrokeToButton(this, "alt LEFT", "compx", compXButton); + UiUtils.mapKeyStrokeToButton(this, "EQUALS", "compx2", compXButton); + UiUtils.mapKeyStrokeToButton(this, "shift EQUALS", "compx2", compXButton); + + expXButton = SwarmUtil.createToolBarButton(Icons.xplus, "Expand sample time 20% (Alt-right arrow, -)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + scaleTime(-0.20); + } + }); + toolbar.add(expXButton); + UiUtils.mapKeyStrokeToButton(this, "alt RIGHT", "expx", expXButton); + UiUtils.mapKeyStrokeToButton(this, "MINUS", "expx", expXButton); + + histButton = SwarmUtil.createToolBarButton(Icons.timeback, "Last time settings (Backspace)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + back(); + } + }); + UiUtils.mapKeyStrokeToButton(this, "BACK_SPACE", "back", histButton); + toolbar.add(histButton); + toolbar.addSeparator(); + + waveToolbar = new WaveViewSettingsToolbar(null, toolbar, this); + + copyButton = SwarmUtil.createToolBarButton(Icons.clipboard, + "Place another copy of wave on clipboard (C or Ctrl-C)", new ActionListener() { + public void actionPerformed(final ActionEvent e) { + // TODO: implement + // if (selected != null) + // { + // WaveViewPanel wvp = new WaveViewPanel(selected); + // wvp.setBackgroundColor(BACKGROUND_COLOR); + // addWave(wvp); + // } + } + }); + UiUtils.mapKeyStrokeToButton(this, "C", "clipboard1", copyButton); + UiUtils.mapKeyStrokeToButton(this, "control C", "clipboard2", copyButton); + toolbar.add(copyButton); + + toolbar.addSeparator(); + + upButton = SwarmUtil.createToolBarButton(Icons.up, "Move wave up in clipboard (Up arrow)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + moveUp(); + } + }); + UiUtils.mapKeyStrokeToButton(this, "UP", "up", upButton); + toolbar.add(upButton); + + downButton = SwarmUtil.createToolBarButton(Icons.down, "Move wave down in clipboard (Down arrow)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + moveDown(); + } + }); + UiUtils.mapKeyStrokeToButton(this, "DOWN", "down", downButton); + toolbar.add(downButton); + + removeButton = SwarmUtil.createToolBarButton(Icons.delete, "Remove wave from clipboard (Delete)", + new ActionListener() { + public void actionPerformed(final ActionEvent e) { + remove(); + } + }); + UiUtils.mapKeyStrokeToButton(this, "DELETE", "remove", removeButton); + toolbar.add(removeButton); + + toolbar.add(Box.createHorizontalGlue()); + + throbber = new Throbber(); + toolbar.add(throbber); + + UiUtils.mapKeyStrokeToAction(this, "control A", "selectAll", new AbstractAction() { + private static final long serialVersionUID = 1L; + + public void actionPerformed(final ActionEvent e) { + for (final AbstractWavePanel wave : waves) + select(wave); + } + }); + } + + private void createListeners() { + this.addInternalFrameListener(new InternalFrameAdapter() { + @Override + public void internalFrameActivated(final InternalFrameEvent e) { + } + + @Override + public void internalFrameDeiconified(final InternalFrameEvent e) { + resizeWaves(); + } + + @Override + public void internalFrameClosing(final InternalFrameEvent e) { + setVisible(false); + } + + @Override + public void internalFrameClosed(final InternalFrameEvent e) { + } + }); + + this.addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(final ComponentEvent e) { + resizeWaves(); + } + }); + + WaveViewTime.addTimeListener(new TimeListener() { + public void timeChanged(final double j2k) { + for (final AbstractWavePanel panel : waves) { + if (panel != null) + panel.setCursorMark(j2k); + } + } + }); + + selectListener = new WaveViewPanelAdapter() { + @Override + public void mousePressed(final AbstractWavePanel src, final MouseEvent e, final boolean dragging) { + requestFocusInWindow(); + final int thisIndex = getWaveIndex(src); + if (!e.isControlDown() && !e.isShiftDown() && !e.isAltDown()) { + deselectAll(); + select(src); + } else if (e.isControlDown()) { + if (selectedSet.contains(src)) + deselect(src); + else + select(src); + } else if (e.isShiftDown()) { + if (lastClickedIndex == -1) + select(src); + else { + deselectAll(); + final int min = Math.min(lastClickedIndex, thisIndex); + final int max = Math.max(lastClickedIndex, thisIndex); + for (int i = min; i <= max; i++) { + final WaveViewPanel ps = (WaveViewPanel) waveBox.getComponent(i); + select(ps); + } + } + } + lastClickedIndex = thisIndex; + } + + @Override + public void waveZoomed(final AbstractWavePanel src, final double st, final double et, final double nst, + final double net) { + final double[] t = new double[] { st, et }; + addHistory(src, t); + for (final AbstractWavePanel wvp : selectedSet) { + if (wvp != src) { + addHistory(wvp, t); + wvp.zoom(nst, net); + } + } + } + + @Override + public void waveClosed(final AbstractWavePanel src) { + remove(src); + } + }; + } + + private int calculateWaveHeight() { + if (waveHeight > 0) + return waveHeight; + + final int w = scrollPane.getViewport().getSize().width; + int h = (int) Math.round(w * 60.0 / 300.0); + h = Math.min(200, h); + h = Math.max(h, 80); + return h; + } + + private void setWaveHeight(final int s) { + waveHeight = s; + resizeWaves(); + } + + private void doSizePopup(final int x, final int y) { + if (popup == null) { + final String[] labels = new String[] { "Auto", null, "Tiny", "Small", "Medium", "Large" }; + final int[] sizes = new int[] { -1, -1, 50, 100, 160, 230 }; + popup = new JPopupMenu(); + final ButtonGroup group = new ButtonGroup(); + for (int i = 0; i < labels.length; i++) { + if (labels[i] != null) { + final int size = sizes[i]; + final JRadioButtonMenuItem mi = new JRadioButtonMenuItem(labels[i]); + mi.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + setWaveHeight(size); + } + }); + if (waveHeight == size) + mi.setSelected(true); + group.add(mi); + popup.add(mi); + } else + popup.addSeparator(); + } + } + popup.show(this, x, y); + } + + private class OpenActionListener implements ActionListener { + public void actionPerformed(final ActionEvent e) { + final JFileChooser chooser = FileChooser.getFileChooser(); + chooser.resetChoosableFileFilters(); + for (final FileType ft : FileType.getKnownTypes()) { + final ExtensionFileFilter f = new ExtensionFileFilter(ft.extension, ft.description); + chooser.addChoosableFileFilter(f); + } + chooser.setDialogTitle("Open Wave"); + chooser.setFileFilter(chooser.getAcceptAllFileFilter()); + final File lastPath = new File(swarmConfig.lastPath); + chooser.setCurrentDirectory(lastPath); + chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + chooser.setMultiSelectionEnabled(true); + final int result = chooser.showOpenDialog(applicationFrame); + if (result == JFileChooser.APPROVE_OPTION) { + final File[] fs = chooser.getSelectedFiles(); + + for (int i = 0; i < fs.length; i++) { + if (fs[i].isDirectory()) { + final File[] dfs = fs[i].listFiles(); + if (dfs == null) + continue; + for (int j = 0; j < dfs.length; j++) + openFile(dfs[j]); + swarmConfig.lastPath = fs[i].getParent(); + } else { + openFile(fs[i]); + swarmConfig.lastPath = fs[i].getParent(); + } + } + } + } + } + + private class SaveActionListener implements ActionListener { + public void actionPerformed(final ActionEvent e) { + final AbstractWavePanel selected = getSingleSelected(); + if (selected == null) + return; + + final JFileChooser chooser = FileChooser.getFileChooser(); + chooser.resetChoosableFileFilters(); + chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + chooser.setMultiSelectionEnabled(false); + chooser.setDialogTitle("Save Wave"); + + for (final FileType ft : FileType.values()) { + if (ft == FileType.UNKNOWN) + continue; + + final ExtensionFileFilter f = new ExtensionFileFilter(ft.extension, ft.description); + chooser.addChoosableFileFilter(f); + } + + chooser.setFileFilter(chooser.getAcceptAllFileFilter()); + + final File lastPath = new File(swarmConfig.lastPath); + chooser.setCurrentDirectory(lastPath); + final String fileName = selected.getChannel().replace(' ', '_') + ".sac"; + chooser.setSelectedFile(new File(fileName)); + final int result = chooser.showSaveDialog(applicationFrame); + if (result == JFileChooser.APPROVE_OPTION) { + final File f = chooser.getSelectedFile(); + boolean confirm = true; + if (f.exists()) { + if (f.isDirectory()) { + JOptionPane.showMessageDialog(applicationFrame, "You can not select an existing directory.", + "Error", JOptionPane.ERROR_MESSAGE); + return; + } + confirm = false; + final int choice = JOptionPane.showConfirmDialog(applicationFrame, "File exists, overwrite?", + "Confirm", JOptionPane.YES_NO_OPTION); + if (choice == JOptionPane.YES_OPTION) + confirm = true; + } + + if (confirm) { + try { + swarmConfig.lastPath = f.getParent(); + final String fn = f.getPath(); + final SeismicDataFile file = SeismicDataFile.getFile(fn); + // String channel = selected.getChannel().replace(' ', + // '_'); + final Wave wave = selected.getWave(); + // file.putWave(channel, wave); + file.putWave(selected.getChannel(), wave); + file.write(); + } catch (final FileNotFoundException ex) { + JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Directory does not exist.", "Error", + JOptionPane.ERROR_MESSAGE); + } catch (final IOException ex) { + JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Error writing file.", "Error", + JOptionPane.ERROR_MESSAGE); + } + } + } + } + } + + private class SaveAllActionListener implements ActionListener { + public void actionPerformed(final ActionEvent e) { + if (waves.size() <= 0) + return; + + final FileTypeDialog dialog = new FileTypeDialog(); + FileType fileType = FileType.UNKNOWN; + if (!dialog.isOpen() || (dialog.isOpen() && !dialog.isAssumeSame())) { + dialog.setVisible(true); + + if (dialog.isCancelled()) + fileType = FileType.UNKNOWN; + else + fileType = dialog.getFileType(); + + } + + final JFileChooser chooser = FileChooser.getFileChooser(); + chooser.resetChoosableFileFilters(); + chooser.setMultiSelectionEnabled(false); + chooser.setDialogTitle("Save All Files"); + final File lastPath = new File(swarmConfig.lastPath); + chooser.setCurrentDirectory(lastPath); + + if (!fileType.isCollective) + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + else + chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + + final int result = chooser.showSaveDialog(applicationFrame); + if (result == JFileChooser.CANCEL_OPTION) + return; + + final File f = chooser.getSelectedFile(); + + if (f == null) { + JOptionPane.showMessageDialog(applicationFrame, "Save location not understood.", "Error", + JOptionPane.ERROR_MESSAGE); + return; + } + + if (result == JFileChooser.APPROVE_OPTION) { + try { + if (f.exists() && !f.isDirectory()) + return; + if (!f.exists()) + f.mkdir(); + for (final AbstractWavePanel wvp : waves) { + Wave sw = wvp.getWave(); + + if (sw != null) { + sw = sw.subset(wvp.getStartTime(), wvp.getEndTime()); + final String date = saveAllDateFormat.format(J2kSec.asDate(sw.getStartTime())); + final File dir = new File(f.getPath() + File.separatorChar + date); + if (!dir.exists()) + dir.mkdir(); + + swarmConfig.lastPath = f.getParent(); + final String fn = dir + File.separator + wvp.getChannel().replace(' ', '_') + + fileType.extension; + final SeismicDataFile file = SeismicDataFile.getFile(fn); + file.putWave(wvp.getChannel(), sw); + file.write(); + } + } + swarmConfig.lastPath = f.getPath(); + } catch (final FileNotFoundException ex) { + JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Directory does not exist.", "Error", + JOptionPane.ERROR_MESSAGE); + } catch (final IOException ex) { + JOptionPane.showMessageDialog(Swarm.getApplicationFrame(), "Error writing file.", "Error", + JOptionPane.ERROR_MESSAGE); + } + } + } + } + + public void openFile(final File f) { + SeismicDataFile file = SeismicDataFile.getFile(f); + if (file == null) { + final FileTypeDialog dialog = new FileTypeDialog(); + FileType fileType = FileType.UNKNOWN; + if (!dialog.isOpen() || (dialog.isOpen() && !dialog.isAssumeSame())) { + dialog.setVisible(true); + + if (dialog.isCancelled()) + fileType = FileType.UNKNOWN; + else + fileType = dialog.getFileType(); + + } + file = SeismicDataFile.getFile(f, fileType); + } + + if (file == null) { + JOptionPane.showMessageDialog(applicationFrame, + "There was an error opening the file, '" + f.getName() + "'.", "Error", JOptionPane.ERROR_MESSAGE); + return; + } + + try { + file.read(); + } catch (final IOException e) { + JOptionPane.showMessageDialog(applicationFrame, + "There was an error opening the file, '" + f.getName() + "'.\n" + e.getMessage(), "Error", + JOptionPane.ERROR_MESSAGE); + } + + for (final String channel : file.getChannels()) { + final WaveViewPanel wvp = new WaveViewPanel(); + wvp.setChannel(channel); + final CachedDataSource cache = CachedDataSource.getInstance(); + + final Wave wave = file.getWave(channel); + cache.putWave(channel, wave); + wvp.setDataSource(cache); + wvp.setWave(wave, wave.getStartTime(), wave.getEndTime()); + WaveClipboardFrame.this.addWave(new WaveViewPanel(wvp)); + } + } + + private void doButtonEnables() { + final boolean enable = (waves == null || waves.size() == 0); + saveButton.setEnabled(!enable); + sortButton.setEnabled(!enable); + saveAllButton.setEnabled(!enable); + syncButton.setEnabled(!enable); + removeAllButton.setEnabled(!enable); + saveAllButton.setEnabled(!enable); + + final boolean allowSingle = (selectedSet.size() == 1); + upButton.setEnabled(allowSingle); + downButton.setEnabled(allowSingle); + sortButton.setEnabled(allowSingle); + syncButton.setEnabled(allowSingle); + saveButton.setEnabled(allowSingle); + + final boolean allowMulti = (selectedSet.size() > 0); + backButton.setEnabled(allowMulti); + expXButton.setEnabled(allowMulti); + compXButton.setEnabled(allowMulti); + backButton.setEnabled(allowMulti); + forwardButton.setEnabled(allowMulti); + histButton.setEnabled(allowMulti); + removeButton.setEnabled(allowMulti); + gotoButton.setEnabled(allowMulti); + } + + public synchronized void sortChannelsByNearest() { + final AbstractWavePanel p = getSingleSelected(); + if (p == null) + return; + + final ArrayList sorted = new ArrayList(waves.size()); + for (final AbstractWavePanel wave : waves) + sorted.add(wave); + + final Metadata smd = swarmConfig.getMetadata(p.getChannel()); + if (smd == null || Double.isNaN(smd.getLongitude()) || Double.isNaN(smd.getLatitude())) + return; + + Collections.sort(sorted, new Comparator() { + public int compare(final AbstractWavePanel wvp1, final AbstractWavePanel wvp2) { + Metadata md = swarmConfig.getMetadata(wvp1.getChannel()); + final double d1 = smd.distanceTo(md); + md = swarmConfig.getMetadata(wvp2.getChannel()); + final double d2 = smd.distanceTo(md); + return Double.compare(d1, d2); + } + }); + + removeWaves(); + for (final AbstractWavePanel wave : sorted) + addWave(wave); + select(p); + } + + public synchronized AbstractWavePanel getSingleSelected() { + if (selectedSet.size() != 1) + return null; + + AbstractWavePanel p = null; + for (final AbstractWavePanel panel : selectedSet) + p = panel; + + return p; + } + + public synchronized void syncChannels() { + final AbstractWavePanel p = getSingleSelected(); + if (p == null) + return; + + final double st = p.getStartTime(); + final double et = p.getEndTime(); + + // TODO: thread bug here. must synch iterator below + final SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + List copy = null; + synchronized (WaveClipboardFrame.this) { + copy = new ArrayList(waves); + } + for (final AbstractWavePanel wvp : copy) { + if (wvp != p) { + if (wvp.getDataSource() != null) { + addHistory(wvp, new double[] { wvp.getStartTime(), wvp.getEndTime() }); + final Wave sw = wvp.getDataSource().getWave(wvp.getChannel(), st, et); + wvp.setWave(sw, st, et); + } + } + } + return null; + } + + @Override + public void finished() { + repaint(); + } + }; + worker.start(); + } + + public void setStatusText(final String s) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + statusLabel.setText(s); + } + }); + } + + public WaveViewPanel getSelected() { + return null; + // return selected; + } + + public synchronized void addWave(final AbstractWavePanel p) { + p.addListener(selectListener); + p.setOffsets(54, 8, 21, 19); + p.setAllowClose(true); + p.setStatusLabel(statusLabel); + p.setAllowDragging(true); + p.setDisplayTitle(true); + final int w = scrollPane.getViewport().getSize().width; + p.setSize(w, calculateWaveHeight()); + p.setBottomBorderColor(Color.GRAY); + p.createImage(); + waveBox.add(p); + waves.add(p); + doButtonEnables(); + waveBox.validate(); + } + + private synchronized void deselect(final AbstractWavePanel p) { + selectedSet.remove(p); + waveToolbar.removeSettings(p.getSettings()); + p.setBackgroundColor(BACKGROUND_COLOR); + p.createImage(); + doButtonEnables(); + } + + private synchronized void deselectAll() { + final WaveViewPanel[] panels = selectedSet.toArray(new WaveViewPanel[0]); + for (final WaveViewPanel p : panels) + deselect(p); + } + + private synchronized void select(final AbstractWavePanel p) { + if (p == null || selectedSet.contains(p)) + return; + + selectedSet.add(p); + doButtonEnables(); + p.setBackgroundColor(SELECT_COLOR); + DataChooser.getInstance().setNearest(p.getChannel()); + p.createImage(); + waveToolbar.addSettings(p.getSettings()); + } + + private synchronized void remove(final AbstractWavePanel p) { + int i = 0; + for (i = 0; i < waveBox.getComponentCount(); i++) { + if (p == waveBox.getComponent(i)) + break; + } + + p.removeListener(selectListener); + p.getDataSource().close(); + setStatusText(" "); + waveBox.remove(i); + waves.remove(p); + histories.remove(p); + doButtonEnables(); + waveBox.validate(); + selectedSet.remove(p); + lastClickedIndex = Math.min(lastClickedIndex, waveBox.getComponentCount() - 1); + waveToolbar.removeSettings(p.getSettings()); + repaint(); + } + + protected int getWaveIndex(final AbstractWavePanel p) { + int i = 0; + for (i = 0; i < waveBox.getComponentCount(); i++) { + if (p == waveBox.getComponent(i)) + break; + } + return i; + } + + public synchronized void remove() { + final WaveViewPanel[] panels = selectedSet.toArray(new WaveViewPanel[0]); + for (final WaveViewPanel p : panels) + remove(p); + } + + public synchronized void moveDown() { + final AbstractWavePanel p = getSingleSelected(); + if (p == null) + return; + + final int i = waves.indexOf(p); + if (i == waves.size() - 1) + return; + + waves.remove(i); + waves.add(i + 1, p); + waveBox.remove(p); + waveBox.add(p, i + 1); + waveBox.validate(); + repaint(); + } + + public synchronized void moveUp() { + final AbstractWavePanel p = getSingleSelected(); + if (p == null) + return; + + final int i = waves.indexOf(p); + if (i == 0) + return; + + waves.remove(i); + waves.add(i - 1, p); + waveBox.remove(p); + waveBox.add(p, i - 1); + waveBox.validate(); + repaint(); + } + + public void resizeWaves() { + final SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + final int w = scrollPane.getViewport().getSize().width; + for (final AbstractWavePanel wave : waves) { + wave.setSize(w, calculateWaveHeight()); + wave.createImage(); + } + return null; + } + + @Override + public void finished() { + waveBox.validate(); + validate(); + repaint(); + } + }; + worker.start(); + } + + public void removeWaves() { + while (waves.size() > 0) { + remove(waves.get(0)); + } + + waveBox.validate(); + scrollPane.validate(); + doButtonEnables(); + repaint(); + } + + private void addHistory(final AbstractWavePanel wvp, final double[] t) { + Stack history = histories.get(wvp); + if (history == null) { + history = new Stack(); + histories.put(wvp, history); + } + history.push(t); + } + + public void gotoTime(final AbstractWavePanel wvp, String t) { + double j2k = Double.NaN; + try { + if (t.length() == 12) + t = t + "30"; + + j2k = J2kSec.parse("yyyyMMddHHmmss", t); + } catch (final Exception e) { + JOptionPane.showMessageDialog(applicationFrame, "Illegal time value.", "Error", JOptionPane.ERROR_MESSAGE); + } + + if (!Double.isNaN(j2k)) { + double dt = 60; + if (wvp.getWave() != null) { + final double st = wvp.getStartTime(); + final double et = wvp.getEndTime(); + final double[] ts = new double[] { st, et }; + addHistory(wvp, ts); + dt = (et - st); + } + + final double tzo = swarmConfig.getTimeZone(wvp.getChannel()).getOffset(System.currentTimeMillis()) / 1000; + + final double nst = j2k - tzo - dt / 2; + final double net = nst + dt; + + fetchNewWave(wvp, nst, net); + } + } + + public void gotoTime(final String t) { + for (final AbstractWavePanel p : selectedSet) + gotoTime(p, t); + } + + public void scaleTime(final AbstractWavePanel wvp, final double pct) { + final double st = wvp.getStartTime(); + final double et = wvp.getEndTime(); + final double[] t = new double[] { st, et }; + addHistory(wvp, t); + final double dt = (et - st) * (1 - pct); + final double mt = (et - st) / 2 + st; + final double nst = mt - dt / 2; + final double net = mt + dt / 2; + fetchNewWave(wvp, nst, net); + } + + public void scaleTime(final double pct) { + for (final AbstractWavePanel p : selectedSet) + scaleTime(p, pct); + } + + public void back(final AbstractWavePanel wvp) { + final Stack history = histories.get(wvp); + if (history == null || history.empty()) + return; + + final double[] t = history.pop(); + fetchNewWave(wvp, t[0], t[1]); + } + + public void back() { + for (final AbstractWavePanel p : selectedSet) + back(p); + } + + private void shiftTime(final AbstractWavePanel wvp, final double pct) { + final double st = wvp.getStartTime(); + final double et = wvp.getEndTime(); + final double[] t = new double[] { st, et }; + addHistory(wvp, t); + final double dt = (et - st) * pct; + final double nst = st + dt; + final double net = et + dt; + fetchNewWave(wvp, nst, net); + } + + public void shiftTime(final double pct) { + for (final AbstractWavePanel p : selectedSet) + shiftTime(p, pct); + } + + public void repositionWaves(final double st, final double et) { + for (final AbstractWavePanel wave : waves) { + fetchNewWave(wave, st, et); + } + } + + public Throbber getThrobber() { + return throbber; + } + + // TODO: This isn't right, this should be a method of waveviewpanel + private void fetchNewWave(final AbstractWavePanel wvp, final double nst, final double net) { + final SwingWorker worker = new SwingWorker() { + @Override + public Object construct() { + throbber.increment(); + final SeismicDataSource sds = wvp.getDataSource(); + // Hacky fix for bug #84 + Wave sw = null; + if (sds instanceof CachedDataSource) + sw = ((CachedDataSource) sds).getBestWave(wvp.getChannel(), nst, net); + else + sw = sds.getWave(wvp.getChannel(), nst, net); + wvp.setWave(sw, nst, net); + wvp.repaint(); + return null; + } + + @Override + public void finished() { + throbber.decrement(); + repaint(); + } + }; + worker.start(); + } + + @Override + public void setMaximum(final boolean max) throws PropertyVetoException { + if (max) { + swarmConfig.clipboardX = getX(); + swarmConfig.clipboardY = getY(); + } + super.setMaximum(max); + } + + @Override + public void paint(final Graphics g) { + super.paint(g); + if (waves.size() == 0) { + final Dimension dim = this.getSize(); + g.setColor(Color.black); + g.drawString("Clipboard empty.", dim.width / 2 - 40, dim.height / 2); + } + } + + @Override + public void setVisible(final boolean isVisible) { + super.setVisible(isVisible); + if (isVisible) + toFront(); + } + + private static class WaveClipboardFrameHolder { + public static WaveClipboardFrame waveClipiboardFrame = new WaveClipboardFrame(); + } } From 835aed430dd35969adb785b0ea07761c2a4f4460 Mon Sep 17 00:00:00 2001 From: tparker Date: Tue, 31 Jan 2017 10:47:18 -0900 Subject: [PATCH 53/67] Don't log hypocenter poll if source is NONE --- .../usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java index 9a2ea5bc..eaad2a61 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java @@ -131,13 +131,13 @@ public void run() { private void pollHypocenters() throws ParserConfigurationException, SAXException, IOException, DOMException, ParseException { - LOGGER.debug("Polling hypocenters"); events.clear(); HypocenterSource hypocenterSource = swarmConfig.getHypocenterSource(); if (hypocenterSource == HypocenterSource.NONE) { return; } + LOGGER.debug("Polling hypocenters"); DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); Document doc = dBuilder.parse(hypocenterSource.getUrl()); From 8f9f4e433d7092a8a16019a51264360d775cab38 Mon Sep 17 00:00:00 2001 From: tparker Date: Tue, 31 Jan 2017 14:32:57 -0900 Subject: [PATCH 54/67] Add support for moving multiple waves in the clipboard. --- .../swarm/wave/WaveClipboardFrame.java | 48 ++++++++++++------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveClipboardFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveClipboardFrame.java index d8aae924..5c25e2f6 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveClipboardFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/wave/WaveClipboardFrame.java @@ -27,6 +27,7 @@ import java.util.Set; import java.util.Stack; import java.util.TimeZone; +import java.util.TreeSet; import javax.swing.AbstractAction; import javax.swing.BorderFactory; @@ -386,10 +387,10 @@ public void actionPerformed(final ActionEvent e) { toolbar.addSeparator(); - upButton = SwarmUtil.createToolBarButton(Icons.up, "Move wave up in clipboard (Up arrow)", + upButton = SwarmUtil.createToolBarButton(Icons.up, "Move wave(s) up in clipboard (Up arrow)", new ActionListener() { public void actionPerformed(final ActionEvent e) { - moveUp(); + moveWaves(-1); } }); UiUtils.mapKeyStrokeToButton(this, "UP", "up", upButton); @@ -398,7 +399,7 @@ public void actionPerformed(final ActionEvent e) { downButton = SwarmUtil.createToolBarButton(Icons.down, "Move wave down in clipboard (Down arrow)", new ActionListener() { public void actionPerformed(final ActionEvent e) { - moveDown(); + moveWaves(1); } }); UiUtils.mapKeyStrokeToButton(this, "DOWN", "down", downButton); @@ -788,13 +789,13 @@ private void doButtonEnables() { saveAllButton.setEnabled(!enable); final boolean allowSingle = (selectedSet.size() == 1); - upButton.setEnabled(allowSingle); - downButton.setEnabled(allowSingle); sortButton.setEnabled(allowSingle); syncButton.setEnabled(allowSingle); saveButton.setEnabled(allowSingle); final boolean allowMulti = (selectedSet.size() > 0); + upButton.setEnabled(allowMulti); + downButton.setEnabled(allowMulti); backButton.setEnabled(allowMulti); expXButton.setEnabled(allowMulti); compXButton.setEnabled(allowMulti); @@ -990,19 +991,34 @@ public synchronized void moveDown() { repaint(); } - public synchronized void moveUp() { - final AbstractWavePanel p = getSingleSelected(); - if (p == null) - return; + public synchronized void moveWaves(int i) { + final WaveViewPanel[] panels = selectedSet.toArray(new WaveViewPanel[0]); - final int i = waves.indexOf(p); - if (i == 0) - return; + List panelIdx = new ArrayList(); + for (int idx = 0; idx < panels.length; idx++) { + panelIdx.add(waves.indexOf(panels[idx])); + } + + Collections.sort(panelIdx); + if (i > 0) { + Collections.reverse(panelIdx); + if (panelIdx.get(0) + i > waves.size() - 1) { + return; + } + } else { + if (panelIdx.get(0) + i < 0) { + return; + } + } + + for (int idx : panelIdx) { + AbstractWavePanel p = waves.get(idx); + waves.remove(idx); + waves.add(idx + i, p); + waveBox.remove(p); + waveBox.add(p, idx + i); + } - waves.remove(i); - waves.add(i - 1, p); - waveBox.remove(p); - waveBox.add(p, i - 1); waveBox.validate(); repaint(); } From 17d41d852242014145038701f4e29456ae304099 Mon Sep 17 00:00:00 2001 From: tparker Date: Wed, 1 Feb 2017 11:42:10 -0900 Subject: [PATCH 55/67] Slow but works. --- .../swarm/heli/HelicorderViewPanel.java | 1641 +++++++++-------- .../swarm/heli/HelicorderViewerFrame.java | 7 +- 2 files changed, 837 insertions(+), 811 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewPanel.java index b78ba5d7..62b19d71 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewPanel.java @@ -61,814 +61,837 @@ * @author Dan Cervelli */ public class HelicorderViewPanel extends JComponent implements SwarmOptionsListener { - private static final Logger LOGGER = LoggerFactory.getLogger(HelicorderViewPanel.class); - - private static final Color BACKGROUND_COLOR = new Color(0xf7, 0xf7, 0xf7); - public static final long serialVersionUID = -1; - - public static final int X_OFFSET = 70; - public static final int Y_OFFSET = 10; - public static final int RIGHT_WIDTH = 70; - public static final int BOTTOM_HEIGHT = 35; - private int insetHeight = 200; - - private Plot plot; - private HelicorderRenderer heliRenderer; - private HelicorderViewerSettings settings; - private HelicorderData heliData; - private double startTime; - private double endTime; - private double mean; - private double bias; - private HelicorderViewerFrame parent; - private double[] translation; - - private WaveViewPanel insetWavePanel; - - private BufferedImage bufferImage, displayImage; - private DateFormat dateFormat; - - private boolean working; - private boolean resized; - - private int insetY; - - private boolean fullScreen; - - private boolean minimal; - - private double startMark = Double.NaN; - private double endMark = Double.NaN; - private double lastMark = Double.NaN; - - private EventListenerList listeners = new EventListenerList(); - private static SwarmConfig swarmConfig; - - public HelicorderViewPanel(HelicorderViewerFrame hvf) { - swarmConfig = SwarmConfig.getInstance(); - - // setBackground(new Color(255, 255, 255, 128)); - parent = hvf; - dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); - dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); - plot = new Plot(); - plot.setBackgroundColor(BACKGROUND_COLOR); - // plot.setBackgroundColor(null); - settings = hvf.getHelicorderViewerSettings(); - heliRenderer = new HelicorderRenderer(); - if (swarmConfig.heliColors != null) - heliRenderer.setDefaultColors(swarmConfig.heliColors);// DCK: add - // configured - // colors - heliRenderer.setExtents(0, 1, Double.MAX_VALUE, -Double.MAX_VALUE); - plot.addRenderer(heliRenderer); - - this.setRequestFocusEnabled(true); - this.addMouseListener(new HelicorderMouseListener()); - this.addMouseMotionListener(new HelicorderMouseMotionListener()); - this.addMouseWheelListener(new HelicorderMouseWheelListener()); - - cursorChanged(); - - SwarmOptions.addOptionsListener(this); - } - - public void addListener(HelicorderViewPanelListener listener) { - listeners.add(HelicorderViewPanelListener.class, listener); - } - - public void removeListener(HelicorderViewPanelListener listener) { - listeners.remove(HelicorderViewPanelListener.class, listener); - } - - public void fireInsetCreated(double st, double et) { - Object[] ls = listeners.getListenerList(); - for (int i = ls.length - 2; i >= 0; i -= 2) - if (ls[i] == HelicorderViewPanelListener.class) - ((HelicorderViewPanelListener) ls[i + 1]).insetCreated(st, et); - } - - public void cursorChanged() { - Cursor crosshair = new Cursor(Cursor.CROSSHAIR_CURSOR); - if (swarmConfig.useLargeCursor) { - Image cursorImg = Icons.crosshair.getImage(); - crosshair = Toolkit.getDefaultToolkit().createCustomCursor(cursorImg, new Point(16, 16), - "Large crosshair"); - } - - this.setCursor(crosshair); - } - - public void settingsChanged() { - if (insetWavePanel != null) { - double zoomOffset = parent.getHelicorderViewerSettings().waveZoomOffset; - double j2k = insetWavePanel.getStartTime() - + (insetWavePanel.getEndTime() - insetWavePanel.getStartTime()) / 2; - loadInsetWave(j2k - zoomOffset, j2k + zoomOffset); - } - - repaint(); - } - - public void setStartMark(double t) { - startMark = t; - } - - public void setEndMark(double t) { - endMark = t; - } - - public void clearMarks() { - startMark = endMark = Double.NaN; - } - - public void setCursorMark(double t) { - if (insetWavePanel != null) - insetWavePanel.setCursorMark(t); - } - - public void markTime(double t) { - if (Double.isNaN(startMark) && Double.isNaN(endMark)) { - startMark = t; - } else if (!Double.isNaN(startMark) && Double.isNaN(endMark)) { - endMark = t; - if (endMark < startMark) { - double tm = startMark; - startMark = endMark; - endMark = tm; - } - } else { - startMark = Math.min(lastMark, t); - endMark = Math.max(lastMark, t); - } - lastMark = t; - if (insetWavePanel != null) { - insetWavePanel.setMarks(startMark, endMark); - } - repaint(); - } - - class HelicorderMouseMotionListener implements MouseMotionListener { - public void mouseDragged(MouseEvent e) { - UiTime.touchTime(); - HelicorderViewPanel.this.requestFocus(); - int mx = e.getX(); - int my = e.getY(); - - if (mx < heliRenderer.getGraphX() || my < heliRenderer.getGraphY() - || mx > heliRenderer.getGraphX() + heliRenderer.getGraphWidth() - 1 - || my > heliRenderer.getGraphY() + heliRenderer.getGraphHeight() - 1) { - /* - * // removed because it wasn't helpful! if (insetWavePanel != - * null) { removeWaveInset(); repaint(); } return; - */ - } else { - double j2k = getMouseJ2K(mx, my); - processMousePosition(mx, my); - - if (SwingUtilities.isLeftMouseButton(e)) - createWaveInset(j2k, mx, my); - } - } - - public void mouseMoved(MouseEvent e) { - UiTime.touchTime(); - processMousePosition(e.getX(), e.getY()); - } - } - - class HelicorderMouseWheelListener implements MouseWheelListener { - int totalScroll = 0; - Delay delay; - - public void mouseWheelMoved(MouseWheelEvent e) { - UiTime.touchTime(); - totalScroll += e.getWheelRotation(); - if (delay == null) - delay = new Delay(250); - else - delay.restart(); - } - - public void delayOver() { - removeWaveInset(); - SwingUtilities.invokeLater(new Runnable() { - public void run() { - parent.scroll(totalScroll); - delay = null; - totalScroll = 0; - } - }); - } - - class Delay extends Thread { - long delayLeft; - - public Delay(long ms) { - delayLeft = ms; - start(); - } - - public void restart() { - interrupt(); - } - - public void run() { - boolean done = false; - while (!done) { - try { - Thread.sleep(delayLeft); - done = true; - } catch (Exception e) { - } - } - delayOver(); - } - } - } - - class HelicorderMouseListener implements MouseListener { - public void mouseClicked(MouseEvent e) { - UiTime.touchTime(); - HelicorderViewPanel.this.requestFocus(); - } - - public void mouseEntered(MouseEvent e) {} - - public void mouseExited(MouseEvent e) {} - - public void mousePressed(MouseEvent e) { - UiTime.touchTime(); - if (e.getButton() == MouseEvent.BUTTON1) { - int mx = e.getX(); - int my = e.getY(); - if (mx < heliRenderer.getGraphX() || my < heliRenderer.getGraphY() - || mx > heliRenderer.getGraphX() + heliRenderer.getGraphWidth() - 1 - || my > heliRenderer.getGraphY() + heliRenderer.getGraphHeight() - 1) - return; - - double j2k = getMouseJ2K(mx, my); - if (j2k != -1E300) { - if (insetWavePanel != null) - insetWavePanel.setWave(null, 0, 1); - createWaveInset(j2k, mx, my); - } - } - /* - * else if (e.getButton() == MouseEvent.BUTTON3) { if - * (insetWavePanel != null) { removeWaveInset(); repaint(); } } - */ - } - - public void mouseReleased(MouseEvent e) {} - } - - public boolean hasInset() { - return insetWavePanel != null; - } - - public HelicorderData getData() { - return heliData; - } - - public double getStartTime() { - return startTime; - } - - public double getEndTime() { - return endTime; - } - - public void insetToClipboard() { - if (insetWavePanel != null) { - WaveViewPanel p = new WaveViewPanel(insetWavePanel); - p.setDataSource(insetWavePanel.getDataSource().getCopy()); - WaveClipboardFrame cb = WaveClipboardFrame.getInstance(); - cb.setVisible(true); - cb.addWave(p); - requestFocus(); - } - } - - private void processMousePosition(int x, int y) { - if (heliData == null) - return; - - String status = null; - - boolean wp = false; - if (insetWavePanel != null) { - Point loc = insetWavePanel.getLocation(); - wp = insetWavePanel.processMousePosition(x - loc.x, y - loc.y); - } - - if (!wp) { - if (status == null) { - if (!(x < heliRenderer.getGraphX() || y < heliRenderer.getGraphY() - || x > heliRenderer.getGraphX() + heliRenderer.getGraphWidth() - 1 - || y > heliRenderer.getGraphY() + heliRenderer.getGraphHeight() - 1)) { - double j2k = getMouseJ2K(x, y); - status = dateFormat.format(J2kSec.asDate(j2k)); - TimeZone tz = swarmConfig.getTimeZone(settings.channel); - double tzo = tz.getOffset(J2kSec.asEpoch(j2k)); - if (tzo != 0) { - String tza = tz.getDisplayName(tz.inDaylightTime(J2kSec.asDate(j2k)), TimeZone.SHORT); - status = dateFormat.format(J2kSec.asDate(j2k + tzo / 1000)) + " (" + tza + "), " + status - + " (UTC)"; - } - } - } - - if (status == null) - status = " "; - - if (!Double.isNaN(startMark) && !Double.isNaN(endMark)) { - double dur = Math.abs(startMark - endMark); - String pre = - String.format("Duration: %.2fs (Md: %.2f)", dur, swarmConfig.getDurationMagnitude(dur)); - if (status.length() > 2) - status = pre + ", " + status; - else - status = pre; - } - - if (status != null) - parent.setStatus(status); - } - } - - public double getMouseJ2K(int mx, int my) { - double j2k = 0; - if (translation != null) { - j2k = translation[4]; - j2k += (mx - translation[0]) * translation[7]; - j2k += getHelicorderRow(my) * translation[6]; - } - return j2k; - } - - public int getHelicorderRow(int my) { - return (int) Math.floor((my - translation[3]) / translation[2]); - } - - public void removeWaveInset() { - if (insetWavePanel != null) { - parent.setInsetButtonsEnabled(false); - this.remove(insetWavePanel); - insetWavePanel = null; - repaint(); - } - } - - public void moveInset(int offset) { - if (insetWavePanel != null) { - double st = insetWavePanel.getStartTime(); - double et = insetWavePanel.getEndTime(); - double dt = et - st; - double nst = st + dt * offset; - double net = et + dt * offset; - - int row = heliRenderer.getRow(st + dt * offset + (dt / 2)); - if (row < 0 || row >= heliRenderer.getNumRows()) - return; - - loadInsetWave(nst, net); - int height = insetHeight; - - if (row * translation[2] + translation[3] > height + translation[3]) { - int y = (int) Math.ceil((row - 1) * translation[2] + translation[3]); - insetWavePanel.setLocation(0, y - height); - } else { - int y = (int) Math.ceil((row + 2) * translation[2] + translation[3]); - insetWavePanel.setLocation(0, y); - } - } - } - - public void createWaveInset(final double j2k, final int mx, final int my) { - if (working) - return; - - insetY = my; - - if (insetWavePanel == null) { - insetWavePanel = new WaveViewPanel(parent.getWaveViewSettings()); - insetWavePanel.addListener(new WaveViewPanelAdapter() { - public void waveClosed(AbstractWavePanel src) { - removeWaveInset(); - } - - public void waveTimePressed(AbstractWavePanel src, MouseEvent e, double j2k) { - if (swarmConfig.durationEnabled && SwingUtilities.isLeftMouseButton(e)) - markTime(j2k); - insetWavePanel.processMousePosition(e.getX(), e.getY()); - } - }); - } - - // insetWavePanel.setHelicorderPanel(this); - insetWavePanel.setMarks(startMark, endMark); - insetWavePanel.setChannel(settings.channel); - insetWavePanel.setDataSource(parent.getDataSource()); - insetWavePanel.setStatusLabel(parent.getStatusLabel()); - - Dimension d = getSize(); - insetHeight = getHeight() / 4; - int height = insetHeight; - int row = heliRenderer.getRow(j2k); - - insetWavePanel.setSize(d.width + 2, height); - if (insetY - heliRenderer.getRowHeight() > height + translation[3]) { - int y = (int) Math.ceil((row - 1) * translation[2] + translation[3]); - insetWavePanel.setLocation(-1, y - height); - } else { - int y = (int) Math.ceil((row + 2) * translation[2] + translation[3]); - insetWavePanel.setLocation(-1, y); - } - - insetWavePanel.setAllowClose(true); - insetWavePanel.setWorking(true); - - double zoomOffset = parent.getHelicorderViewerSettings().waveZoomOffset; - loadInsetWave(j2k - zoomOffset, j2k + zoomOffset); - parent.setInsetButtonsEnabled(true); - this.add(insetWavePanel); - repaint(); - } - - private void loadInsetWave(final double st, final double et) { - fireInsetCreated(st, et); - final SwingWorker worker = new SwingWorker() { - private Wave sw; - - public Object construct() { - parent.getThrobber().increment(); - working = true; - sw = parent.getWave(st, et); - return null; - } - - public void finished() { - parent.getThrobber().decrement(); - working = false; - if (insetWavePanel != null) { - insetWavePanel.setWave(sw, st, et); - insetWavePanel.setWorking(false); - } - repaint(); - } - }; - worker.start(); - } - - public void setHelicorder(HelicorderData d, double time1, double time2) { - heliData = d; - if (heliData != null) { - startTime = time1; - endTime = time2; - heliRenderer.setData(heliData); - heliRenderer.setTimeChunk(settings.timeChunk); - heliRenderer.setTimeZone(swarmConfig.getTimeZone(settings.channel)); - heliRenderer.setForceCenter(settings.forceCenter); - heliRenderer.setClipBars(settings.clipBars); - heliRenderer.setShowClip(settings.showClip); - heliRenderer.setAlertClip(settings.alertClip); - heliRenderer.setClipWav("clip.wav"); - heliRenderer.setClipAlertTimeout(settings.alertClipTimeout); - mean = heliData.getMeanMax(); - bias = heliData.getBias(); - if (bias != mean) - mean = Math.abs(bias - mean); - heliRenderer.setClipValue(settings.clipValue); - - } - } - - public void invalidateImage() { - final SwingWorker worker = new SwingWorker() { - public Object construct() { - createImage(); - return null; - } - - public void finished() { - displayImage = bufferImage; - repaint(); - } - }; - worker.start(); - } - - public void setResized(boolean b) { - resized = b; - } - - private void createImage() { - if (heliData == null) - return; - - Dimension d = this.getSize(); - if (d.width <= 0 || d.height <= 0) - return; - - bufferImage = new BufferedImage(d.width, d.height, BufferedImage.TYPE_4BYTE_ABGR); - - Graphics2D ig = (Graphics2D) bufferImage.getGraphics(); - plot.setSize(d); - - double offset = 0; - double multiplier = 1; - Metadata md = swarmConfig.getMetadata(settings.channel); - if (md != null) { - offset = md.getOffset(); - multiplier = md.getMultiplier(); - } - - if (minimal) - heliRenderer.setLocation(X_OFFSET / 2, Y_OFFSET, d.width - X_OFFSET - 5, - d.height - Y_OFFSET - BOTTOM_HEIGHT / 2); - else - heliRenderer.setLocation(X_OFFSET, Y_OFFSET, d.width - X_OFFSET - RIGHT_WIDTH, - d.height - Y_OFFSET - BOTTOM_HEIGHT); - - if (settings.autoScale) { - settings.barRange = (int) (mean * settings.barMult); - settings.clipValue = (int) (mean * settings.clipBars); - heliRenderer.setHelicorderExtents(startTime, endTime, -1 * Math.abs(settings.barRange), - Math.abs(settings.barRange)); - - } else { - heliRenderer.setHelicorderExtents(startTime, endTime, - -1 * Math.abs((settings.barRange - offset) / multiplier), - Math.abs((settings.barRange - offset) / multiplier)); - } - - heliRenderer.setTimeZone(swarmConfig.getTimeZone(settings.channel)); - heliRenderer.setClipValue(settings.clipValue); - if (minimal) { - // System.out.println("minimal"); - // heliRenderer.createMinimumAxis(); - heliRenderer.setFrameDecorator(new SmallDecorator()); - } else - heliRenderer.createDefaultAxis(); - - if (md == null || md.getAlias() == null) - heliRenderer.setChannel(settings.channel); - else - heliRenderer.setChannel(md.getAlias()); - - translation = heliRenderer.getTranslationInfo(false); - heliRenderer.setLargeChannelDisplay(fullScreen); - - try { - plot.render(ig); - } catch (PlotException e) { - e.printStackTrace(); - } - } - - class SmallDecorator extends FrameDecorator { - public void decorate(FrameRenderer fr) { - HelicorderRenderer hr = (HelicorderRenderer) fr; - AxisRenderer axis = new AxisRenderer(fr); - axis.createDefault(); - fr.setAxis(axis); - - int minutes = (int) Math.round(settings.timeChunk / 60.0); - int majorTicks = minutes; - if (minutes > 30 && minutes < 180) - majorTicks = minutes / 5; - else if (minutes >= 180 && minutes < 360) - majorTicks = minutes / 10; - else if (minutes >= 360) - majorTicks = minutes / 20; - double[] mjt = SmartTick.intervalTick(0, settings.timeChunk, majorTicks); - - axis.createBottomTicks(null, mjt); - axis.createTopTicks(null, mjt); - axis.createVerticalGridLines(mjt); - - int bc = (settings.timeChunk / 5) + 2; - String[] btl = new String[bc]; - double[] btlv = new double[bc]; - btl[0] = "+"; - btlv[0] = 30; - for (int i = 0, j = 1; i < mjt.length; i++) { - long m = Math.round(mjt[i] / 60.0); - if (m % 5 == 0) { - btl[j] = Long.toString(m); - btlv[j++] = mjt[i]; - } - } - axis.createBottomTickLabels(btlv, btl); - - int numRows = hr.getNumRows(); - double[] labelPosLR = new double[numRows]; - String[] leftLabelText = new String[numRows]; - String[] rightLabelText = new String[numRows]; - TimeZone timeZone = swarmConfig.getTimeZone(settings.channel); - - DateFormat localTimeFormat = new SimpleDateFormat("HH:mm"); - localTimeFormat.setTimeZone(timeZone); - - DateFormat localDayFormat = new SimpleDateFormat("MM-dd"); - localDayFormat.setTimeZone(timeZone); - - double pixelsPast = 0; - double pixelsPerRow = fr.getGraphHeight() / numRows; - String lastLocalDay = ""; - for (int i = numRows - 1; i >= 0; i--) { - pixelsPast += pixelsPerRow; - labelPosLR[i] = i + 0.5; - - String localTime = localTimeFormat - .format(J2kSec.asDate(hr.getHelicorderMaxX() - (i + 1) * settings.timeChunk)); - leftLabelText[i] = null; - if (pixelsPast > 20) { - leftLabelText[i] = localTime; - pixelsPast = 0; - } - - Date dtz = J2kSec.asDate(hr.getHelicorderMaxX() - (i + 1) * settings.timeChunk); - String localDay = - localDayFormat.format(new Date(dtz.getTime() + settings.timeChunk * 1000)); - if (!localDay.equals(lastLocalDay)) { - rightLabelText[i] = localDay; - lastLocalDay = localDay; - } - } - - axis.createLeftTickLabels(labelPosLR, leftLabelText); - axis.createRightTickLabels(labelPosLR, rightLabelText); - - boolean dst = timeZone.inDaylightTime(J2kSec.asDate(hr.getViewEndTime())); - String timeZoneName = timeZone.getDisplayName(dst, TimeZone.SHORT); - TextRenderer tr = - new TextRenderer(3, fr.getGraphY() + fr.getGraphHeight() + 14, timeZoneName); - tr.font = Font.decode("dialog-PLAIN-9"); - tr.antiAlias = false; - axis.addPostRenderer(tr); - - double[] hg = new double[numRows - 1]; - for (int i = 0; i < numRows - 1; i++) - hg[i] = i + 1.0; - - axis.createHorizontalGridLines(hg); - - axis.setBackgroundColor(Color.white); - } - } - - public void setFullScreen(boolean b) { - fullScreen = b; - } - - public void setMinimal(boolean b) { - minimal = b; - } - - private void drawMark(Graphics2D g2, double t, Color color) { - if (Double.isNaN(t)) - return; - - int x = (int) (heliRenderer.helicorderGetXPixel(t)); - int row = heliRenderer.getRow(t); - int y = (int) Math.ceil(row * translation[2] + translation[3]); - g2.setColor(color); - g2.draw(new Line2D.Double(x, y, x, y + translation[2])); - - GeneralPath gp = new GeneralPath(); - gp.moveTo(x, y); - gp.lineTo((float) x - 4, (float) y - 6); - gp.lineTo((float) x + 4, (float) y - 6); - gp.closePath(); - g2.setColor(Color.GREEN); - g2.fill(gp); - g2.setColor(DARK_GREEN); - g2.draw(gp); - - gp.reset(); - gp.moveTo(x, (float) (y + translation[2])); - gp.lineTo((float) x - 4, (float) (y + 6 + translation[2])); - gp.lineTo((float) x + 4, (float) (y + 6 + translation[2])); - gp.closePath(); - gp.closePath(); - g2.setColor(Color.GREEN); - g2.fill(gp); - g2.setColor(DARK_GREEN); - g2.draw(gp); - } - - private static final Color DARK_GREEN = new Color(0, 168, 0); - - public void paint(Graphics g) { - Graphics2D g2 = (Graphics2D) g; - Dimension d = this.getSize(); - if (heliData == null) { - // if (parent.isWorking()) - // g2.drawString("Attempting to retrieve data...", d.width / 2 - 75, - // d.height / 2); - // else - if (!parent.isWorking()) { - // g2.drawString("The server returned no helicorder data.", - // d.width / 2 - 150, d.height / 2); - parent.setStatus("The server returned no helicorder data."); - // double start = settings.getBottomTime() - settings.span * 60; - // double end = settings.getBottomTime(); - // g2.drawString(String.format("Time range: %s to %s", - // Time.format(Time.STANDARD_TIME_FORMAT, start), - // Time.format(Time.STANDARD_TIME_FORMAT, end)), - // d.width / 2 - 100, d.height / 2 + 16); - } - } else if (displayImage != null) - g2.drawImage(displayImage, 0, 0, null); - - drawMark(g2, startMark, DARK_GREEN); - drawMark(g2, endMark, DARK_GREEN); - - if (insetWavePanel != null) { - // find out where time highlight will be, possibly reposition the - // insetWavePanel - double t1 = insetWavePanel.getStartTime(); - double t2 = insetWavePanel.getEndTime(); - double t = (t2 - t1) / 2 + t1; - int row = heliRenderer.getRow(t); - if (resized) { - insetWavePanel.setSize(d.width, insetHeight); - insetWavePanel.createImage(); - if (row * translation[2] > insetHeight + translation[3]) { - int y = (int) Math.ceil((row - 1) * translation[2] + translation[3]); - insetWavePanel.setLocation(0, y - insetHeight); - } else { - int y = (int) Math.ceil((row + 2) * translation[2] + translation[3]); - insetWavePanel.setLocation(0, y); - } - } - - // now it's safe to draw the waveInsetPanel - Point p = insetWavePanel.getLocation(); - g2.translate(p.x, p.y); - insetWavePanel.paint(g2); - Dimension wvd = insetWavePanel.getSize(); - g.setColor(Color.gray); - g.drawRect(0, 0, wvd.width - 1, wvd.height); - g2.translate(-p.x, -p.y); - - // fixes bug where highlight was being drawn before wave loaded - if (row < 0) - return; - - // finally, draw the highlight. support for spanning one row - // above and one row below the center point. - // TODO: support multi-row span - Paint pnt = g2.getPaint(); - g2.setPaint(new Color(255, 255, 0, 128)); - Rectangle2D.Double rect = new Rectangle2D.Double(); - int zoomOffset = parent.getHelicorderViewerSettings().waveZoomOffset; - double xo = 1.0 / translation[7] * zoomOffset; - int bx = (int) (heliRenderer.helicorderGetXPixel(t) - xo); - int width = (int) (xo * 2); - int right = heliRenderer.getGraphX() + heliRenderer.getGraphWidth(); - if (bx < heliRenderer.getGraphX()) { - int width2 = heliRenderer.getGraphX() - bx; - rect.setRect(right - width2, (int) Math.ceil((row - 1) * translation[2] + translation[3]), - width2, (int) Math.ceil(translation[2])); - if (row - 1 >= 0) - g2.fill(rect); - bx = heliRenderer.getGraphX(); - width = width - width2; - } - if (bx + width > right) { - int width2 = bx + width - right; - rect.setRect(heliRenderer.getGraphX() + 1, - (int) Math.ceil((row + 1) * translation[2] + translation[3]), width2, - (int) Math.ceil(translation[2])); - if (row + 1 < heliRenderer.getNumRows()) - g2.fill(rect); - width = width - width2; - } - rect.setRect(bx, (int) Math.ceil(row * translation[2] + translation[3]), width, - (int) Math.floor(translation[2])); - - g2.fill(rect); - g2.setPaint(pnt); - } - - resized = false; - } - - public void optionsChanged() { - cursorChanged(); - invalidateImage(); - if (!SwarmConfig.getInstance().durationEnabled) - clearMarks(); - } - -// public void insetToPicker() { -// if (insetWavePanel != null) { -// LOGGER.debug("Sending wave to picker"); -// Swarm.openPicker(insetWavePanel); -// } -// } + private static final Logger LOGGER = LoggerFactory.getLogger(HelicorderViewPanel.class); + + private static final Color BACKGROUND_COLOR = new Color(0xf7, 0xf7, 0xf7); + public static final long serialVersionUID = -1; + + public static final int X_OFFSET = 70; + public static final int Y_OFFSET = 10; + public static final int RIGHT_WIDTH = 70; + public static final int BOTTOM_HEIGHT = 35; + private int insetHeight = 200; + + // TODO: extract translation into an object + private static final int GRAPH_LEFT = 0; + private static final int GRAPH_RIGHT = 1; + private static final int ROW_HEIGHT = 2; + private static final int GRAPH_Y = 3; + private static final int MIN_TIME_LOCAL = 4; + private static final int MAX_TIME_LOCAL = 5; + private static final int TIME_CHUNK = 6; + private static final int PIXEL_TIME_SPAN = 7; + + private Plot plot; + private HelicorderRenderer heliRenderer; + private HelicorderViewerSettings settings; + private HelicorderData heliData; + private double startTime; + private double endTime; + private double mean; + private double bias; + private HelicorderViewerFrame parent; + + private double[] translation; + + private WaveViewPanel insetWavePanel; + + private BufferedImage bufferImage, displayImage; + private DateFormat dateFormat; + + private boolean working; + private boolean resized; + + private int insetY; + + private boolean fullScreen; + + private boolean minimal; + + private double startMark = Double.NaN; + private double endMark = Double.NaN; + private double lastMark = Double.NaN; + + private EventListenerList listeners = new EventListenerList(); + private static SwarmConfig swarmConfig; + + public HelicorderViewPanel(HelicorderViewerFrame hvf) { + swarmConfig = SwarmConfig.getInstance(); + + // setBackground(new Color(255, 255, 255, 128)); + parent = hvf; + dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); + dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); + plot = new Plot(); + plot.setBackgroundColor(BACKGROUND_COLOR); + // plot.setBackgroundColor(null); + settings = hvf.getHelicorderViewerSettings(); + heliRenderer = new HelicorderRenderer(); + if (swarmConfig.heliColors != null) + heliRenderer.setDefaultColors(swarmConfig.heliColors);// DCK: add + // configured + // colors + heliRenderer.setExtents(0, 1, Double.MAX_VALUE, -Double.MAX_VALUE); + plot.addRenderer(heliRenderer); + + this.setRequestFocusEnabled(true); + this.addMouseListener(new HelicorderMouseListener()); + this.addMouseMotionListener(new HelicorderMouseMotionListener()); + this.addMouseWheelListener(new HelicorderMouseWheelListener()); + + cursorChanged(); + + SwarmOptions.addOptionsListener(this); + } + + public void addListener(HelicorderViewPanelListener listener) { + listeners.add(HelicorderViewPanelListener.class, listener); + } + + public void removeListener(HelicorderViewPanelListener listener) { + listeners.remove(HelicorderViewPanelListener.class, listener); + } + + public void fireInsetCreated(double st, double et) { + Object[] ls = listeners.getListenerList(); + for (int i = ls.length - 2; i >= 0; i -= 2) + if (ls[i] == HelicorderViewPanelListener.class) + ((HelicorderViewPanelListener) ls[i + 1]).insetCreated(st, et); + } + + public void cursorChanged() { + Cursor crosshair = new Cursor(Cursor.CROSSHAIR_CURSOR); + if (swarmConfig.useLargeCursor) { + Image cursorImg = Icons.crosshair.getImage(); + crosshair = Toolkit.getDefaultToolkit().createCustomCursor(cursorImg, new Point(16, 16), "Large crosshair"); + } + + this.setCursor(crosshair); + } + + public void settingsChanged() { + if (insetWavePanel != null) { + double zoomOffset = parent.getHelicorderViewerSettings().waveZoomOffset; + double j2k = insetWavePanel.getStartTime() + + (insetWavePanel.getEndTime() - insetWavePanel.getStartTime()) / 2; + loadInsetWave(j2k - zoomOffset, j2k + zoomOffset); + System.err.println("MOVING INSET"); + moveInset(0); + } + + repaint(); + } + + public void setStartMark(double t) { + startMark = t; + } + + public void setEndMark(double t) { + endMark = t; + } + + public void clearMarks() { + startMark = endMark = Double.NaN; + } + + public void setCursorMark(double t) { + if (insetWavePanel != null) + insetWavePanel.setCursorMark(t); + } + + public void markTime(double t) { + if (Double.isNaN(startMark) && Double.isNaN(endMark)) { + startMark = t; + } else if (!Double.isNaN(startMark) && Double.isNaN(endMark)) { + endMark = t; + if (endMark < startMark) { + double tm = startMark; + startMark = endMark; + endMark = tm; + } + } else { + startMark = Math.min(lastMark, t); + endMark = Math.max(lastMark, t); + } + lastMark = t; + if (insetWavePanel != null) { + insetWavePanel.setMarks(startMark, endMark); + } + repaint(); + } + + class HelicorderMouseMotionListener implements MouseMotionListener { + public void mouseDragged(MouseEvent e) { + UiTime.touchTime(); + HelicorderViewPanel.this.requestFocus(); + int mx = e.getX(); + int my = e.getY(); + + if (mx < heliRenderer.getGraphX() || my < heliRenderer.getGraphY() + || mx > heliRenderer.getGraphX() + heliRenderer.getGraphWidth() - 1 + || my > heliRenderer.getGraphY() + heliRenderer.getGraphHeight() - 1) { + /* + * // removed because it wasn't helpful! if (insetWavePanel != + * null) { removeWaveInset(); repaint(); } return; + */ + } else { + double j2k = getMouseJ2K(mx, my); + processMousePosition(mx, my); + + if (SwingUtilities.isLeftMouseButton(e)) + createWaveInset(j2k, mx, my); + } + } + + public void mouseMoved(MouseEvent e) { + UiTime.touchTime(); + processMousePosition(e.getX(), e.getY()); + } + } + + class HelicorderMouseWheelListener implements MouseWheelListener { + int totalScroll = 0; + Delay delay; + + public void mouseWheelMoved(MouseWheelEvent e) { + UiTime.touchTime(); + totalScroll += e.getWheelRotation(); + if (delay == null) + delay = new Delay(250); + else + delay.restart(); + } + + public void delayOver() { + removeWaveInset(); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + parent.scroll(totalScroll); + delay = null; + totalScroll = 0; + } + }); + } + + class Delay extends Thread { + long delayLeft; + + public Delay(long ms) { + delayLeft = ms; + start(); + } + + public void restart() { + interrupt(); + } + + public void run() { + boolean done = false; + while (!done) { + try { + Thread.sleep(delayLeft); + done = true; + } catch (Exception e) { + } + } + delayOver(); + } + } + } + + class HelicorderMouseListener implements MouseListener { + public void mouseClicked(MouseEvent e) { + UiTime.touchTime(); + HelicorderViewPanel.this.requestFocus(); + } + + public void mouseEntered(MouseEvent e) { + } + + public void mouseExited(MouseEvent e) { + } + + public void mousePressed(MouseEvent e) { + UiTime.touchTime(); + if (e.getButton() == MouseEvent.BUTTON1) { + int mx = e.getX(); + int my = e.getY(); + if (mx < heliRenderer.getGraphX() || my < heliRenderer.getGraphY() + || mx > heliRenderer.getGraphX() + heliRenderer.getGraphWidth() - 1 + || my > heliRenderer.getGraphY() + heliRenderer.getGraphHeight() - 1) + return; + + double j2k = getMouseJ2K(mx, my); + if (j2k != -1E300) { + if (insetWavePanel != null) + insetWavePanel.setWave(null, 0, 1); + createWaveInset(j2k, mx, my); + } + } + /* + * else if (e.getButton() == MouseEvent.BUTTON3) { if + * (insetWavePanel != null) { removeWaveInset(); repaint(); } } + */ + } + + public void mouseReleased(MouseEvent e) { + } + } + + public boolean hasInset() { + return insetWavePanel != null; + } + + public HelicorderData getData() { + return heliData; + } + + public double getStartTime() { + return startTime; + } + + public double getEndTime() { + return endTime; + } + + public void insetToClipboard() { + if (insetWavePanel != null) { + WaveViewPanel p = new WaveViewPanel(insetWavePanel); + p.setDataSource(insetWavePanel.getDataSource().getCopy()); + WaveClipboardFrame cb = WaveClipboardFrame.getInstance(); + cb.setVisible(true); + cb.addWave(p); + requestFocus(); + } + } + + private void processMousePosition(int x, int y) { + if (heliData == null) + return; + + String status = null; + + boolean wp = false; + if (insetWavePanel != null) { + Point loc = insetWavePanel.getLocation(); + wp = insetWavePanel.processMousePosition(x - loc.x, y - loc.y); + } + + if (!wp) { + if (status == null) { + if (!(x < heliRenderer.getGraphX() || y < heliRenderer.getGraphY() + || x > heliRenderer.getGraphX() + heliRenderer.getGraphWidth() - 1 + || y > heliRenderer.getGraphY() + heliRenderer.getGraphHeight() - 1)) { + double j2k = getMouseJ2K(x, y); + status = dateFormat.format(J2kSec.asDate(j2k)); + TimeZone tz = swarmConfig.getTimeZone(settings.channel); + double tzo = tz.getOffset(J2kSec.asEpoch(j2k)); + if (tzo != 0) { + String tza = tz.getDisplayName(tz.inDaylightTime(J2kSec.asDate(j2k)), TimeZone.SHORT); + status = dateFormat.format(J2kSec.asDate(j2k + tzo / 1000)) + " (" + tza + "), " + status + + " (UTC)"; + } + } + } + + if (status == null) + status = " "; + + if (!Double.isNaN(startMark) && !Double.isNaN(endMark)) { + double dur = Math.abs(startMark - endMark); + String pre = String.format("Duration: %.2fs (Md: %.2f)", dur, swarmConfig.getDurationMagnitude(dur)); + if (status.length() > 2) + status = pre + ", " + status; + else + status = pre; + } + + if (status != null) + parent.setStatus(status); + } + } + + public double getMouseJ2K(int mx, int my) { + double j2k = 0; + if (translation != null) { + j2k = translation[4]; + j2k += (mx - translation[0]) * translation[7]; + j2k += getHelicorderRow(my) * translation[6]; + } + return j2k; + } + + public int getHelicorderRow(int my) { + return (int) Math.floor((my - translation[3]) / translation[2]); + } + + public void removeWaveInset() { + if (insetWavePanel != null) { + parent.setInsetButtonsEnabled(false); + this.remove(insetWavePanel); + insetWavePanel = null; + repaint(); + } + } + + public void moveInset(int offset) { + if (insetWavePanel != null) { + double st = insetWavePanel.getStartTime(); + double et = insetWavePanel.getEndTime(); + double dt = et - st; + double nst = st + dt * offset; + double net = et + dt * offset; + + int row = heliRenderer.getRow(st + dt * offset + (dt / 2)); + if (row < 0 || row >= heliRenderer.getNumRows()) + return; + + loadInsetWave(nst, net); + int height = insetHeight; + + int rowSpan = (int) Math.ceil(dt / heliRenderer.getTimeChunk()); + if (row * translation[ROW_HEIGHT] + translation[GRAPH_Y] > height + translation[GRAPH_Y]) { + int y = (int) Math.ceil((row - rowSpan) * translation[ROW_HEIGHT] + translation[GRAPH_Y]); + insetWavePanel.setLocation(0, y - height); + } else { + int y = (int) Math.ceil((row + 1 + rowSpan) * translation[ROW_HEIGHT] + translation[GRAPH_Y]); + insetWavePanel.setLocation(0, y); + } + } + } + + public void createWaveInset(final double j2k, final int mx, final int my) { + if (working) + return; + + insetY = my; + + if (insetWavePanel == null) { + insetWavePanel = new WaveViewPanel(parent.getWaveViewSettings()); + insetWavePanel.addListener(new WaveViewPanelAdapter() { + public void waveClosed(AbstractWavePanel src) { + removeWaveInset(); + } + + public void waveTimePressed(AbstractWavePanel src, MouseEvent e, double j2k) { + if (swarmConfig.durationEnabled && SwingUtilities.isLeftMouseButton(e)) + markTime(j2k); + insetWavePanel.processMousePosition(e.getX(), e.getY()); + } + }); + } + + // insetWavePanel.setHelicorderPanel(this); + insetWavePanel.setMarks(startMark, endMark); + insetWavePanel.setChannel(settings.channel); + insetWavePanel.setDataSource(parent.getDataSource()); + insetWavePanel.setStatusLabel(parent.getStatusLabel()); + + Dimension d = getSize(); + insetHeight = getHeight() / 4; + int height = insetHeight; + int row = heliRenderer.getRow(j2k); + + insetWavePanel.setSize(d.width + 2, height); + double zoomOffset = parent.getHelicorderViewerSettings().waveZoomOffset; + int rowSpan = (int) Math.ceil( 2 * zoomOffset / heliRenderer.getTimeChunk()); + if (insetY - heliRenderer.getRowHeight() > height + translation[GRAPH_Y]) { + int y = (int) Math.ceil((row - rowSpan) * translation[ROW_HEIGHT] + translation[GRAPH_Y]); + insetWavePanel.setLocation(-1, y - height); + } else { + int y = (int) Math.ceil((row + 1 + rowSpan) * translation[ROW_HEIGHT] + translation[GRAPH_Y]); + insetWavePanel.setLocation(-1, y); + } + + insetWavePanel.setAllowClose(true); + insetWavePanel.setWorking(true); + + loadInsetWave(j2k - zoomOffset, j2k + zoomOffset); + parent.setInsetButtonsEnabled(true); + this.add(insetWavePanel); + repaint(); + } + + private void loadInsetWave(final double st, final double et) { + fireInsetCreated(st, et); + final SwingWorker worker = new SwingWorker() { + private Wave sw; + + public Object construct() { + parent.getThrobber().increment(); + working = true; + sw = parent.getWave(st, et); + return null; + } + + public void finished() { + parent.getThrobber().decrement(); + working = false; + if (insetWavePanel != null) { + insetWavePanel.setWave(sw, st, et); + insetWavePanel.setWorking(false); + } + repaint(); + } + }; + worker.start(); + } + + public void setHelicorder(HelicorderData d, double time1, double time2) { + heliData = d; + if (heliData != null) { + startTime = time1; + endTime = time2; + heliRenderer.setData(heliData); + heliRenderer.setTimeChunk(settings.timeChunk); + heliRenderer.setTimeZone(swarmConfig.getTimeZone(settings.channel)); + heliRenderer.setForceCenter(settings.forceCenter); + heliRenderer.setClipBars(settings.clipBars); + heliRenderer.setShowClip(settings.showClip); + heliRenderer.setAlertClip(settings.alertClip); + heliRenderer.setClipWav("clip.wav"); + heliRenderer.setClipAlertTimeout(settings.alertClipTimeout); + mean = heliData.getMeanMax(); + bias = heliData.getBias(); + if (bias != mean) + mean = Math.abs(bias - mean); + heliRenderer.setClipValue(settings.clipValue); + + } + } + + public void invalidateImage() { + final SwingWorker worker = new SwingWorker() { + public Object construct() { + createImage(); + return null; + } + + public void finished() { + displayImage = bufferImage; + repaint(); + } + }; + worker.start(); + } + + public void setResized(boolean b) { + resized = b; + } + + private void createImage() { + if (heliData == null) + return; + + Dimension d = this.getSize(); + if (d.width <= 0 || d.height <= 0) + return; + + bufferImage = new BufferedImage(d.width, d.height, BufferedImage.TYPE_4BYTE_ABGR); + + Graphics2D ig = (Graphics2D) bufferImage.getGraphics(); + plot.setSize(d); + + double offset = 0; + double multiplier = 1; + Metadata md = swarmConfig.getMetadata(settings.channel); + if (md != null) { + offset = md.getOffset(); + multiplier = md.getMultiplier(); + } + + if (minimal) + heliRenderer.setLocation(X_OFFSET / 2, Y_OFFSET, d.width - X_OFFSET - 5, + d.height - Y_OFFSET - BOTTOM_HEIGHT / 2); + else + heliRenderer.setLocation(X_OFFSET, Y_OFFSET, d.width - X_OFFSET - RIGHT_WIDTH, + d.height - Y_OFFSET - BOTTOM_HEIGHT); + + if (settings.autoScale) { + settings.barRange = (int) (mean * settings.barMult); + settings.clipValue = (int) (mean * settings.clipBars); + heliRenderer.setHelicorderExtents(startTime, endTime, -1 * Math.abs(settings.barRange), + Math.abs(settings.barRange)); + + } else { + heliRenderer.setHelicorderExtents(startTime, endTime, + -1 * Math.abs((settings.barRange - offset) / multiplier), + Math.abs((settings.barRange - offset) / multiplier)); + } + + heliRenderer.setTimeZone(swarmConfig.getTimeZone(settings.channel)); + heliRenderer.setClipValue(settings.clipValue); + if (minimal) { + // System.out.println("minimal"); + // heliRenderer.createMinimumAxis(); + heliRenderer.setFrameDecorator(new SmallDecorator()); + } else + heliRenderer.createDefaultAxis(); + + if (md == null || md.getAlias() == null) + heliRenderer.setChannel(settings.channel); + else + heliRenderer.setChannel(md.getAlias()); + + translation = heliRenderer.getTranslationInfo(false); + heliRenderer.setLargeChannelDisplay(fullScreen); + + try { + plot.render(ig); + } catch (PlotException e) { + e.printStackTrace(); + } + } + + class SmallDecorator extends FrameDecorator { + public void decorate(FrameRenderer fr) { + HelicorderRenderer hr = (HelicorderRenderer) fr; + AxisRenderer axis = new AxisRenderer(fr); + axis.createDefault(); + fr.setAxis(axis); + + int minutes = (int) Math.round(settings.timeChunk / 60.0); + int majorTicks = minutes; + if (minutes > 30 && minutes < 180) + majorTicks = minutes / 5; + else if (minutes >= 180 && minutes < 360) + majorTicks = minutes / 10; + else if (minutes >= 360) + majorTicks = minutes / 20; + double[] mjt = SmartTick.intervalTick(0, settings.timeChunk, majorTicks); + + axis.createBottomTicks(null, mjt); + axis.createTopTicks(null, mjt); + axis.createVerticalGridLines(mjt); + + int bc = (settings.timeChunk / 5) + 2; + String[] btl = new String[bc]; + double[] btlv = new double[bc]; + btl[0] = "+"; + btlv[0] = 30; + for (int i = 0, j = 1; i < mjt.length; i++) { + long m = Math.round(mjt[i] / 60.0); + if (m % 5 == 0) { + btl[j] = Long.toString(m); + btlv[j++] = mjt[i]; + } + } + axis.createBottomTickLabels(btlv, btl); + + int numRows = hr.getNumRows(); + double[] labelPosLR = new double[numRows]; + String[] leftLabelText = new String[numRows]; + String[] rightLabelText = new String[numRows]; + TimeZone timeZone = swarmConfig.getTimeZone(settings.channel); + + DateFormat localTimeFormat = new SimpleDateFormat("HH:mm"); + localTimeFormat.setTimeZone(timeZone); + + DateFormat localDayFormat = new SimpleDateFormat("MM-dd"); + localDayFormat.setTimeZone(timeZone); + + double pixelsPast = 0; + double pixelsPerRow = fr.getGraphHeight() / numRows; + String lastLocalDay = ""; + for (int i = numRows - 1; i >= 0; i--) { + pixelsPast += pixelsPerRow; + labelPosLR[i] = i + 0.5; + + String localTime = localTimeFormat + .format(J2kSec.asDate(hr.getHelicorderMaxX() - (i + 1) * settings.timeChunk)); + leftLabelText[i] = null; + if (pixelsPast > 20) { + leftLabelText[i] = localTime; + pixelsPast = 0; + } + + Date dtz = J2kSec.asDate(hr.getHelicorderMaxX() - (i + 1) * settings.timeChunk); + String localDay = localDayFormat.format(new Date(dtz.getTime() + settings.timeChunk * 1000)); + if (!localDay.equals(lastLocalDay)) { + rightLabelText[i] = localDay; + lastLocalDay = localDay; + } + } + + axis.createLeftTickLabels(labelPosLR, leftLabelText); + axis.createRightTickLabels(labelPosLR, rightLabelText); + + boolean dst = timeZone.inDaylightTime(J2kSec.asDate(hr.getViewEndTime())); + String timeZoneName = timeZone.getDisplayName(dst, TimeZone.SHORT); + TextRenderer tr = new TextRenderer(3, fr.getGraphY() + fr.getGraphHeight() + 14, timeZoneName); + tr.font = Font.decode("dialog-PLAIN-9"); + tr.antiAlias = false; + axis.addPostRenderer(tr); + + double[] hg = new double[numRows - 1]; + for (int i = 0; i < numRows - 1; i++) + hg[i] = i + 1.0; + + axis.createHorizontalGridLines(hg); + + axis.setBackgroundColor(Color.white); + } + } + + public void setFullScreen(boolean b) { + fullScreen = b; + } + + public void setMinimal(boolean b) { + minimal = b; + } + + private void drawMark(Graphics2D g2, double t, Color color) { + if (Double.isNaN(t)) + return; + + int x = (int) (heliRenderer.helicorderGetXPixel(t)); + int row = heliRenderer.getRow(t); + int y = (int) Math.ceil(row * translation[2] + translation[3]); + g2.setColor(color); + g2.draw(new Line2D.Double(x, y, x, y + translation[2])); + + GeneralPath gp = new GeneralPath(); + gp.moveTo(x, y); + gp.lineTo((float) x - 4, (float) y - 6); + gp.lineTo((float) x + 4, (float) y - 6); + gp.closePath(); + g2.setColor(Color.GREEN); + g2.fill(gp); + g2.setColor(DARK_GREEN); + g2.draw(gp); + + gp.reset(); + gp.moveTo(x, (float) (y + translation[2])); + gp.lineTo((float) x - 4, (float) (y + 6 + translation[2])); + gp.lineTo((float) x + 4, (float) (y + 6 + translation[2])); + gp.closePath(); + gp.closePath(); + g2.setColor(Color.GREEN); + g2.fill(gp); + g2.setColor(DARK_GREEN); + g2.draw(gp); + } + + private static final Color DARK_GREEN = new Color(0, 168, 0); + + public void paint(Graphics g) { + Graphics2D g2 = (Graphics2D) g; + Dimension d = this.getSize(); + if (heliData == null) { + // if (parent.isWorking()) + // g2.drawString("Attempting to retrieve data...", d.width / 2 - 75, + // d.height / 2); + // else + if (!parent.isWorking()) { + // g2.drawString("The server returned no helicorder data.", + // d.width / 2 - 150, d.height / 2); + parent.setStatus("The server returned no helicorder data."); + // double start = settings.getBottomTime() - settings.span * 60; + // double end = settings.getBottomTime(); + // g2.drawString(String.format("Time range: %s to %s", + // Time.format(Time.STANDARD_TIME_FORMAT, start), + // Time.format(Time.STANDARD_TIME_FORMAT, end)), + // d.width / 2 - 100, d.height / 2 + 16); + } + } else if (displayImage != null) + g2.drawImage(displayImage, 0, 0, null); + + drawMark(g2, startMark, DARK_GREEN); + drawMark(g2, endMark, DARK_GREEN); + + if (insetWavePanel != null) { + // find out where time highlight will be, possibly reposition the + // insetWavePanel + double t1 = insetWavePanel.getStartTime(); + double t2 = insetWavePanel.getEndTime(); + double spanCenter = (t2 - t1) / 2 + t1; + int row = heliRenderer.getRow(spanCenter); + if (resized) { + insetWavePanel.setSize(d.width, insetHeight); + insetWavePanel.createImage(); + if (row * translation[2] > insetHeight + translation[3]) { + int y = (int) Math.ceil((row - 1) * translation[2] + translation[3]); + insetWavePanel.setLocation(0, y - insetHeight); + } else { + int y = (int) Math.ceil((row + 2) * translation[2] + translation[3]); + insetWavePanel.setLocation(0, y); + } + } + + // now it's safe to draw the waveInsetPanel + Point p = insetWavePanel.getLocation(); + g2.translate(p.x, p.y); + insetWavePanel.paint(g2); + Dimension wvd = insetWavePanel.getSize(); + g.setColor(Color.gray); + g.drawRect(0, 0, wvd.width - 1, wvd.height); + g2.translate(-p.x, -p.y); + + // fixes bug where highlight was being drawn before wave loaded + if (row < 0) + return; + + // finally, draw the highlight. + Paint pnt = g2.getPaint(); + g2.setPaint(new Color(255, 255, 0, 128)); + Rectangle2D.Double rect = new Rectangle2D.Double(); + + int zoomTimeSpan = parent.getHelicorderViewerSettings().waveZoomOffset * 2; + double zoomPixelSpan = 1.0 / translation[PIXEL_TIME_SPAN] * zoomTimeSpan; + + // hightlight left + int highlightStart = (int) heliRenderer.helicorderGetXPixel(spanCenter); + int highlightSpan = (int) (zoomPixelSpan / 2); + int row_offset = 0; + while (highlightSpan > 0) { + int width = Math.min(highlightSpan, (int) (highlightStart - translation[GRAPH_LEFT])); + + rect.setRect(highlightStart - width, + (int) Math.ceil((row - row_offset++) * translation[ROW_HEIGHT] + translation[GRAPH_Y]), width, + (int) Math.ceil(translation[ROW_HEIGHT])); + g2.fill(rect); + + highlightSpan -= width; + highlightStart = (int) translation[GRAPH_RIGHT]; + + } + + // hightlight right + highlightStart = (int) heliRenderer.helicorderGetXPixel(spanCenter); + highlightSpan = (int) (zoomPixelSpan / 2); + row_offset = 0; + while (highlightSpan > 0) { + int width = Math.min(highlightSpan, (int) (translation[GRAPH_RIGHT] - highlightStart)); + + rect.setRect(highlightStart, + (int) Math.ceil((row + row_offset++) * translation[ROW_HEIGHT] + translation[GRAPH_Y]), width, + (int) Math.ceil(translation[ROW_HEIGHT])); + g2.fill(rect); + + highlightSpan -= width; + highlightStart = (int) translation[GRAPH_LEFT]; + + } + + g2.setPaint(pnt); + } + + resized = false; + } + + public void optionsChanged() { + cursorChanged(); + invalidateImage(); + if (!SwarmConfig.getInstance().durationEnabled) + clearMarks(); + } + + // public void insetToPicker() { + // if (insetWavePanel != null) { + // LOGGER.debug("Sending wave to picker"); + // Swarm.openPicker(insetWavePanel); + // } + // } } diff --git a/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewerFrame.java b/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewerFrame.java index ee6c2018..01bb4303 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewerFrame.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewerFrame.java @@ -75,9 +75,12 @@ public class HelicorderViewerFrame extends SwarmFrame implements Kioskable { public static final long serialVersionUID = -1; + private static final int MINUTE = 60; + private static final int HOUR = MINUTE * 60; + // minutes * 60 = seconds public static final int[] chunkValues = - new int[] {10 * 60, 15 * 60, 20 * 60, 30 * 60, 60 * 60, 120 * 60, 180 * 60, 360 * 60}; + new int[] {10 * MINUTE, 15 * MINUTE, 20 * MINUTE, 30 * MINUTE, 1 * HOUR, 2 * HOUR, 180 * MINUTE, 6 * HOUR}; // hours * 60 = minutes public static final int[] spanValues = @@ -85,7 +88,7 @@ public class HelicorderViewerFrame extends SwarmFrame implements Kioskable { 144 * 60, 168 * 60, 192 * 60, 216 * 60, 240 * 60, 264 * 60, 288 * 60, 312 * 60, 336 * 60}; // seconds - public static final int[] zoomValues = new int[] {1, 2, 5, 10, 20, 30, 60, 120, 300, 600}; + public static final int[] zoomValues = new int[] {1, 2, 5, 10, 20, 30, MINUTE, 2 * MINUTE, 5 * MINUTE, 10 * MINUTE, 20 * MINUTE, 40 * MINUTE, 1 * HOUR, 90 * MINUTE}; private final RefreshThread refreshThread; private final SeismicDataSource dataSource; From d324d0b47201cf8d7006342a192c818622d3b975 Mon Sep 17 00:00:00 2001 From: tparker Date: Thu, 2 Feb 2017 10:15:30 -0900 Subject: [PATCH 56/67] Correct highlighting when center point is off helicorder. --- .../swarm/heli/HelicorderViewPanel.java | 149 +++++++++--------- 1 file changed, 77 insertions(+), 72 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewPanel.java b/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewPanel.java index 62b19d71..685c0c9d 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewPanel.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/heli/HelicorderViewPanel.java @@ -1,8 +1,5 @@ package gov.usgs.volcanoes.swarm.heli; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; @@ -31,6 +28,9 @@ import javax.swing.SwingUtilities; import javax.swing.event.EventListenerList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import gov.usgs.plot.Plot; import gov.usgs.plot.PlotException; import gov.usgs.plot.data.HelicorderData; @@ -44,7 +44,6 @@ import gov.usgs.volcanoes.core.time.J2kSec; import gov.usgs.volcanoes.swarm.Icons; import gov.usgs.volcanoes.swarm.Metadata; -import gov.usgs.volcanoes.swarm.Swarm; import gov.usgs.volcanoes.swarm.SwarmConfig; import gov.usgs.volcanoes.swarm.SwingWorker; import gov.usgs.volcanoes.swarm.options.SwarmOptions; @@ -175,8 +174,6 @@ public void settingsChanged() { double j2k = insetWavePanel.getStartTime() + (insetWavePanel.getEndTime() - insetWavePanel.getStartTime()) / 2; loadInsetWave(j2k - zoomOffset, j2k + zoomOffset); - System.err.println("MOVING INSET"); - moveInset(0); } repaint(); @@ -434,30 +431,30 @@ public void removeWaveInset() { } } + /** + * Move selected wave window. + * + * @param offset + * window lengths to move + */ public void moveInset(int offset) { - if (insetWavePanel != null) { - double st = insetWavePanel.getStartTime(); - double et = insetWavePanel.getEndTime(); - double dt = et - st; - double nst = st + dt * offset; - double net = et + dt * offset; - - int row = heliRenderer.getRow(st + dt * offset + (dt / 2)); - if (row < 0 || row >= heliRenderer.getNumRows()) - return; - - loadInsetWave(nst, net); - int height = insetHeight; - - int rowSpan = (int) Math.ceil(dt / heliRenderer.getTimeChunk()); - if (row * translation[ROW_HEIGHT] + translation[GRAPH_Y] > height + translation[GRAPH_Y]) { - int y = (int) Math.ceil((row - rowSpan) * translation[ROW_HEIGHT] + translation[GRAPH_Y]); - insetWavePanel.setLocation(0, y - height); - } else { - int y = (int) Math.ceil((row + 1 + rowSpan) * translation[ROW_HEIGHT] + translation[GRAPH_Y]); - insetWavePanel.setLocation(0, y); - } + if (insetWavePanel == null) { + return; + } + + double st = insetWavePanel.getStartTime(); + double et = insetWavePanel.getEndTime(); + double dt = et - st; + double newStartTime = st + dt * offset; + double newEndTime = et + dt * offset; + + int firstRow = heliRenderer.getRow(newStartTime); + int lastRow = heliRenderer.getRow(newEndTime); + if (lastRow < 0 || firstRow > heliRenderer.getNumRows() - 1) { + return; } + + loadInsetWave(newStartTime, newEndTime); } public void createWaveInset(final double j2k, final int mx, final int my) { @@ -494,7 +491,7 @@ public void waveTimePressed(AbstractWavePanel src, MouseEvent e, double j2k) { insetWavePanel.setSize(d.width + 2, height); double zoomOffset = parent.getHelicorderViewerSettings().waveZoomOffset; - int rowSpan = (int) Math.ceil( 2 * zoomOffset / heliRenderer.getTimeChunk()); + int rowSpan = (int) Math.ceil(2 * zoomOffset / heliRenderer.getTimeChunk()); if (insetY - heliRenderer.getRowHeight() > height + translation[GRAPH_Y]) { int y = (int) Math.ceil((row - rowSpan) * translation[ROW_HEIGHT] + translation[GRAPH_Y]); insetWavePanel.setLocation(-1, y - height); @@ -575,7 +572,7 @@ public void finished() { worker.start(); } - public void setResized(boolean b) { + protected void setResized(boolean b) { resized = b; } @@ -779,20 +776,8 @@ public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; Dimension d = this.getSize(); if (heliData == null) { - // if (parent.isWorking()) - // g2.drawString("Attempting to retrieve data...", d.width / 2 - 75, - // d.height / 2); - // else if (!parent.isWorking()) { - // g2.drawString("The server returned no helicorder data.", - // d.width / 2 - 150, d.height / 2); parent.setStatus("The server returned no helicorder data."); - // double start = settings.getBottomTime() - settings.span * 60; - // double end = settings.getBottomTime(); - // g2.drawString(String.format("Time range: %s to %s", - // Time.format(Time.STANDARD_TIME_FORMAT, start), - // Time.format(Time.STANDARD_TIME_FORMAT, end)), - // d.width / 2 - 100, d.height / 2 + 16); } } else if (displayImage != null) g2.drawImage(displayImage, 0, 0, null); @@ -805,18 +790,28 @@ public void paint(Graphics g) { // insetWavePanel double t1 = insetWavePanel.getStartTime(); double t2 = insetWavePanel.getEndTime(); + double dt = t2 - t1; double spanCenter = (t2 - t1) / 2 + t1; int row = heliRenderer.getRow(spanCenter); + + int rowSpan = (int) Math.ceil(dt / heliRenderer.getMaxX()) + 1; + double rowHeight = translation[ROW_HEIGHT]; + double graphY = translation[GRAPH_Y]; + if (resized) { insetWavePanel.setSize(d.width, insetHeight); insetWavePanel.createImage(); - if (row * translation[2] > insetHeight + translation[3]) { - int y = (int) Math.ceil((row - 1) * translation[2] + translation[3]); - insetWavePanel.setLocation(0, y - insetHeight); - } else { - int y = (int) Math.ceil((row + 2) * translation[2] + translation[3]); - insetWavePanel.setLocation(0, y); - } + } + + int panelY; + if ((row - rowSpan) * rowHeight > insetHeight + graphY) { + panelY = (int) Math.ceil((row - rowSpan) * rowHeight + graphY - insetHeight); + } else { + panelY = (int) Math.ceil((row + rowSpan) * rowHeight + graphY); + } + + if (panelY != insetWavePanel.getLocation().y) { + insetWavePanel.setLocation(0, panelY); } // now it's safe to draw the waveInsetPanel @@ -828,11 +823,17 @@ public void paint(Graphics g) { g.drawRect(0, 0, wvd.width - 1, wvd.height); g2.translate(-p.x, -p.y); + /* + * Not sure what below is meant to address. I removed the check + * because negative row offsets were necessary to handle multi-row + * highlights. If there's a problem with wave loading, find a more + * direct fix. --tjp + */ // fixes bug where highlight was being drawn before wave loaded - if (row < 0) - return; + // if (row < 0) + // return; - // finally, draw the highlight. + // finally, draw the highlight. Paint pnt = g2.getPaint(); g2.setPaint(new Color(255, 255, 0, 128)); Rectangle2D.Double rect = new Rectangle2D.Double(); @@ -840,40 +841,44 @@ public void paint(Graphics g) { int zoomTimeSpan = parent.getHelicorderViewerSettings().waveZoomOffset * 2; double zoomPixelSpan = 1.0 / translation[PIXEL_TIME_SPAN] * zoomTimeSpan; - // hightlight left + // highlight left int highlightStart = (int) heliRenderer.helicorderGetXPixel(spanCenter); int highlightSpan = (int) (zoomPixelSpan / 2); - int row_offset = 0; - while (highlightSpan > 0) { + int rowOffset = 0; + while (highlightSpan > 0 && row - rowOffset >= 0) { int width = Math.min(highlightSpan, (int) (highlightStart - translation[GRAPH_LEFT])); - rect.setRect(highlightStart - width, - (int) Math.ceil((row - row_offset++) * translation[ROW_HEIGHT] + translation[GRAPH_Y]), width, - (int) Math.ceil(translation[ROW_HEIGHT])); + if (row - rowOffset < heliRenderer.getNumRows()) { + rect.setRect(highlightStart - width, + (int) Math.ceil((row - rowOffset) * translation[ROW_HEIGHT] + translation[GRAPH_Y]), width, + (int) Math.ceil(translation[ROW_HEIGHT])); g2.fill(rect); - - highlightSpan -= width; - highlightStart = (int) translation[GRAPH_RIGHT]; + } + highlightSpan -= width; + highlightStart = (int) translation[GRAPH_RIGHT]; + rowOffset++; } - - // hightlight right + + // highlight right highlightStart = (int) heliRenderer.helicorderGetXPixel(spanCenter); highlightSpan = (int) (zoomPixelSpan / 2); - row_offset = 0; - while (highlightSpan > 0) { + rowOffset = 0; + while (highlightSpan > 0 && row + rowOffset < heliRenderer.getNumRows()) { int width = Math.min(highlightSpan, (int) (translation[GRAPH_RIGHT] - highlightStart)); - rect.setRect(highlightStart, - (int) Math.ceil((row + row_offset++) * translation[ROW_HEIGHT] + translation[GRAPH_Y]), width, - (int) Math.ceil(translation[ROW_HEIGHT])); + if (row + rowOffset >= 0) { + rect.setRect(highlightStart, + (int) Math.ceil((row + rowOffset) * translation[ROW_HEIGHT] + translation[GRAPH_Y]), width, + (int) Math.ceil(translation[ROW_HEIGHT])); g2.fill(rect); - - highlightSpan -= width; - highlightStart = (int) translation[GRAPH_LEFT]; + } + highlightSpan -= width; + highlightStart = (int) translation[GRAPH_LEFT]; + rowOffset++; } - + g2.setPaint(pnt); } From c41c7fe27b5202f54eae2fa874e6a32c067c2216 Mon Sep 17 00:00:00 2001 From: tparker Date: Thu, 2 Feb 2017 10:29:57 -0900 Subject: [PATCH 57/67] Update dataselect path --- .../volcanoes/swarm/data/fdsnWs/WebServicesClient.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesClient.java b/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesClient.java index 7bf92dc6..a0cdf8f5 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesClient.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/data/fdsnWs/WebServicesClient.java @@ -1,18 +1,16 @@ package gov.usgs.volcanoes.swarm.data.fdsnWs; -import edu.sc.seis.seisFile.mseed.DataRecord; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.ArrayList; import java.util.Date; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import edu.sc.seis.seisFile.mseed.DataRecord; import gov.usgs.plot.data.Wave; import gov.usgs.volcanoes.swarm.ChannelInfo; import gov.usgs.volcanoes.swarm.SwarmConfig; -import gov.usgs.volcanoes.swarm.data.DataSelectReader; import gov.usgs.volcanoes.swarm.data.SeismicDataSource; public class WebServicesClient extends AbstractDataRecordClient { From f5f9132d7c3a7cb94c26c09cbebb1bc4d2c60896 Mon Sep 17 00:00:00 2001 From: tparker Date: Thu, 2 Feb 2017 10:32:08 -0900 Subject: [PATCH 58/67] Update dep versions --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index c856a564..7ac9d241 100644 --- a/pom.xml +++ b/pom.xml @@ -494,7 +494,7 @@ edu.sc.seis seisFile - 1.7.2 + 1.7.3 net.alomax @@ -524,7 +524,7 @@ gov.usgs.volcanoes usgs - 1.3.3 + 1.3.4 gov.usgs.volcanoes From 876095f60a46b8089ca325abe049f36af06b38ab Mon Sep 17 00:00:00 2001 From: tparker Date: Thu, 2 Feb 2017 13:57:33 -0900 Subject: [PATCH 59/67] Rejigger about dialog. Needs more work. --- .../gov/usgs/volcanoes/swarm/AboutDialog.java | 289 +++++++++--------- 1 file changed, 151 insertions(+), 138 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/AboutDialog.java b/src/main/java/gov/usgs/volcanoes/swarm/AboutDialog.java index 4180809d..e2b2a4bb 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/AboutDialog.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/AboutDialog.java @@ -35,54 +35,51 @@ * * @author Dan Cervelli */ -public class AboutDialog extends JDialog implements Runnable -{ +public class AboutDialog extends JDialog implements Runnable { private static final long serialVersionUID = -1; private static final JFrame applicationFrame = Swarm.getApplicationFrame(); + + private static final int PANE_WIDTH = 344; + private static final int PANEL_PADDING = 9; + private final static int TITLE_LOC_Y = 5; - private final static int TITLE_HEIGHT = 190; - private final static int MAIN_PAD_HEIGHT = 9; - private final static int MAIN_LOC_Y = TITLE_LOC_Y + TITLE_HEIGHT + MAIN_PAD_HEIGHT; - private final static int MAIN_HEIGHT = 100; + private final static int TITLE_HEIGHT = 80; + + private final static int ATTRIBUTION_LOC_Y = TITLE_LOC_Y + TITLE_HEIGHT + PANEL_PADDING; + private final static int ATTRIBUTION_HEIGHT = 175; + + private final static int MEMORY_LOC_Y = ATTRIBUTION_LOC_Y + ATTRIBUTION_HEIGHT + PANEL_PADDING; + private final static int MEMORY_HEIGHT = 100; + private final static int BUTTON_PAD_HEIGHT = 11; - private final static int BUTTON_LOC_Y = MAIN_LOC_Y + MAIN_HEIGHT + BUTTON_PAD_HEIGHT; + private final static int BUTTON_LOC_Y = MEMORY_LOC_Y + MEMORY_HEIGHT + BUTTON_PAD_HEIGHT; private final static int BUTTON_HEIGHT = 30; - private final static int BG_WIDTH = 237; + private final static int BG_WIDTH = 357; private final static int BG_HEIGHT = BUTTON_LOC_Y + BUTTON_HEIGHT + 10; - private static final int WIDTH = BG_WIDTH + 3; - private static final int HEIGHT = BG_HEIGHT + 26; - private final JPanel mainPanel; + private static final int WIDTH = BG_WIDTH; + private static final int HEIGHT = BG_HEIGHT + 20; + private final MemoryPanel memoryPanel; - private final JLabel freeMemory; - private final JLabel totalMemory; - private final JLabel usedMemory; - private final JLabel maxMemory; - private final JLabel cacheMemory; - private final JButton gcButton; - private final ImageIcon background; - private final JButton okButton; - + private Thread updateThread; - + private boolean kill = false; - + /** * Construct an about dialog. */ - public AboutDialog() - { + public AboutDialog() { super(applicationFrame, "About", true); this.setSize(WIDTH, HEIGHT); Dimension parentSize = applicationFrame.getSize(); Point parentLoc = applicationFrame.getLocation(); this.setLocation(parentLoc.x + (parentSize.width / 2 - WIDTH / 2), parentLoc.y + (parentSize.height / 2 - HEIGHT / 2)); - + this.setResizable(false); - - background = Icons.honeycomb; - if (background.getIconWidth() != BG_WIDTH || background.getIconHeight() != BG_HEIGHT) - { + + ImageIcon background = Icons.honeycomb; + if (background.getIconWidth() != BG_WIDTH || background.getIconHeight() != BG_HEIGHT) { // resize the background image Image image = background.getImage(); image = image.getScaledInstance(BG_WIDTH, BG_HEIGHT, Image.SCALE_FAST); @@ -91,113 +88,107 @@ public AboutDialog() JPanel bp = new JPanel(new BorderLayout()); bp.add(new JLabel(background), BorderLayout.CENTER); bp.setSize(BG_WIDTH, BG_HEIGHT); - bp.setLocation(0,0); + bp.setLocation(0, 0); + this.getLayeredPane().add(bp); this.getLayeredPane().setLayer(bp, JLayeredPane.DEFAULT_LAYER.intValue()); - - mainPanel = new JPanel(new BorderLayout()); - mainPanel.setBorder(LineBorder.createBlackLineBorder()); - memoryPanel = new MemoryPanel(new GridLayout(5, 2)); - memoryPanel.setBorder(new EmptyBorder(3, 6, 3, 6)); - memoryPanel.add(new JLabel("Free memory: ")); - freeMemory = new JLabel(); - memoryPanel.add(freeMemory); - memoryPanel.add(new JLabel("Total memory: ")); - totalMemory = new JLabel(); - memoryPanel.add(totalMemory); - memoryPanel.add(new JLabel("Used memory: ")); - usedMemory = new JLabel(); - memoryPanel.add(usedMemory); - memoryPanel.add(new JLabel("Max memory: ")); - maxMemory = new JLabel(); - memoryPanel.add(maxMemory); - memoryPanel.add(new JLabel("Cache size: ")); - cacheMemory = new JLabel(); - memoryPanel.add(cacheMemory); - - mainPanel.add(memoryPanel, BorderLayout.CENTER); - mainPanel.setSize(224, MAIN_HEIGHT); - mainPanel.setLocation(5, MAIN_LOC_Y); - memoryPanel.setBackground(new Color(255, 255, 0)); - mainPanel.setBackground(new Color(0, 0, 0, 0)); - this.getLayeredPane().add(mainPanel); - this.getLayeredPane().setLayer(mainPanel, JLayeredPane.PALETTE_LAYER.intValue()); - - JTextPane title = new JTextPane(); - title.setFont(freeMemory.getFont()); // use label font for title - title.setEditable(false); //make title not modifiable - title.setBackground(new Color(255, 255, 0, 210)); - title.setSize(224, TITLE_HEIGHT); - title.setLocation(5, TITLE_LOC_Y); - title.setBorder(LineBorder.createBlackLineBorder()); - title.setContentType("text/html"); - title.setText("
" - + "SWARM:
" - + "Seismic Wave Analysis/
" - + "Real-time Monitoring/
" - + "Version: " + Version.POM_VERSION + "
" - + "
" - + "Funded by:
" - + "USGS http://www.usgs.gov
" - + "IRIS http://www.iris.edu
" - + "ISTI http://www.isti.com
" - + "
" - + "Library versions:
" - + BuildVersion.getName() + " " + BuildVersion.getVersion() + "
" - + SLClient.PROGRAM_NAME + "
" - + "
"); + + JTextPane title = getTitlePane(); this.getLayeredPane().add(title); this.getLayeredPane().setLayer(title, JLayeredPane.PALETTE_LAYER.intValue()); + + JTextPane attribution = getAttributionPane(); + this.getLayeredPane().add(attribution); + this.getLayeredPane().setLayer(attribution, JLayeredPane.PALETTE_LAYER.intValue()); + - okButton = new JButton("OK"); + memoryPanel = new MemoryPanel(new GridLayout(5, 2)); + + JPanel memoryContainer = new JPanel(new BorderLayout()); + memoryContainer.setBorder(LineBorder.createBlackLineBorder()); + memoryContainer.add(memoryPanel, BorderLayout.CENTER); + memoryContainer.setSize(PANE_WIDTH, MEMORY_HEIGHT); + memoryContainer.setLocation(5, MEMORY_LOC_Y); + memoryContainer.setBackground(new Color(0, 0, 0, 0)); + + this.getLayeredPane().add(memoryContainer); + this.getLayeredPane().setLayer(memoryContainer, JLayeredPane.PALETTE_LAYER.intValue()); + + JButton okButton = new JButton("OK"); okButton.setSize(60, BUTTON_HEIGHT); okButton.setLocation(170, BUTTON_LOC_Y); - okButton.addActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - dispose(); - kill = true; - } - }); - - gcButton = new JButton("Run GC"); + okButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + dispose(); + kill = true; + } + }); + + JButton gcButton = new JButton("Run GC"); gcButton.setSize(90, BUTTON_HEIGHT); gcButton.setLocation(70, BUTTON_LOC_Y); - gcButton.addActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - System.gc(); - // update(); - // no need to update since it will be done by thread - } - }); - + gcButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + System.gc(); + // update(); + // no need to update since it will be done by thread + } + }); + this.getLayeredPane().add(okButton); - this.getLayeredPane().add(gcButton); - + this.getLayeredPane().add(gcButton); + this.getLayeredPane().setLayer(okButton, JLayeredPane.PALETTE_LAYER.intValue()); this.getLayeredPane().setLayer(gcButton, JLayeredPane.PALETTE_LAYER.intValue()); } - - public void setVisible(boolean v) - { + + private JTextPane getTitlePane() { + JTextPane pane = new JTextPane(); + pane.setBorder(new EmptyBorder(3, 6, 3, 6)); + + pane.setEditable(false); // make title not modifiable + pane.setBackground(new Color(255, 255, 0, 210)); + pane.setSize(PANE_WIDTH, TITLE_HEIGHT); + pane.setLocation(5, TITLE_LOC_Y); + pane.setBorder(LineBorder.createBlackLineBorder()); + pane.setContentType("text/html"); + pane.setText("
" + "SWARM:
" + + "Seismic Wave Analysis/
" + + "Real-time Monitoring/
https://volcanoes.usgs.gov/software/swarm/
" + "Version: " + Version.POM_VERSION + + "
" + + ""); + return pane; + } + + private JTextPane getAttributionPane() { + JTextPane pane = new JTextPane(); + pane.setBorder(new EmptyBorder(3, 6, 3, 6)); + pane.setEditable(false); // make title not modifiable + pane.setBackground(new Color(255, 255, 0, 210)); + pane.setSize(PANE_WIDTH, ATTRIBUTION_HEIGHT); + pane.setLocation(5, ATTRIBUTION_LOC_Y); + pane.setBorder(LineBorder.createBlackLineBorder()); + pane.setContentType("text/html"); + pane.setText("" + "
Developed by:
U.S. Geological Survey" + + "

With contributions from:" + "
Instrumental Software Technologies, Inc. (ISTI)" + + "
The Incorporated Research Institutions for Seismology (IRIS)" + + "

Primary developers:
Dan Cervelli
Tom Parker" + "

"); + return pane; + } + + public void setVisible(boolean v) { updateThread = new Thread(this, "About"); updateThread.start(); super.setVisible(v); } - - public void run() - { - while (!kill) - { - try - { + + public void run() { + while (!kill) { + try { update(); Thread.sleep(500); + } catch (Exception e) { } - catch (Exception e) {} } kill = false; } @@ -205,53 +196,76 @@ public void run() /** * The memory panel overrides the paint method to update the values. */ - private class MemoryPanel extends JPanel - { + private class MemoryPanel extends JPanel { /** serial version UID */ private static final long serialVersionUID = 1L; /** re-use the number format safely on the Event Dispatch Thread. */ private final NumberFormat nf = new DecimalFormat("#.##"); - - public MemoryPanel(LayoutManager layout) - { + + private final JLabel freeMemory; + private final JLabel totalMemory; + private final JLabel usedMemory; + private final JLabel maxMemory; + private final JLabel cacheMemory; + + public MemoryPanel(LayoutManager layout) { super(layout); + setBorder(new EmptyBorder(3, 6, 3, 6)); + add(new JLabel("Free memory: ")); + freeMemory = new JLabel(); + add(freeMemory); + add(new JLabel("Total memory: ")); + totalMemory = new JLabel(); + add(totalMemory); + add(new JLabel("Used memory: ")); + usedMemory = new JLabel(); + add(usedMemory); + add(new JLabel("Max memory: ")); + maxMemory = new JLabel(); + add(maxMemory); + add(new JLabel("Cache size: ")); + cacheMemory = new JLabel(); + add(cacheMemory); + setSize(PANE_WIDTH, MEMORY_HEIGHT); + setLocation(5, MEMORY_LOC_Y); + setBackground(new Color(255, 255, 0)); } /** * Invoked by Swing to draw components. This method should not be called * directly, use the repaint method. * - * @param g the graphics. + * @param g + * the graphics. */ - public void paint(Graphics g) - { + public void paint(Graphics g) { update(); super.paint(g); } - - /** + + /** * Formats a long as a number of bytes. - * @param bytes the number of bytes + * + * @param bytes + * the number of bytes * @return a formatted string */ - private String toByteString(long bytes) - { + private String toByteString(long bytes) { return nf.format(bytes / 1000000.0) + " MB"; } - + /** - * Updates the memory information displayed in the dialog. - * This should only be called on the Event Dispatch Thread. + * Updates the memory information displayed in the dialog. This should + * only be called on the Event Dispatch Thread. */ - private void update() - { + private void update() { Runtime r = Runtime.getRuntime(); freeMemory.setText(toByteString(r.freeMemory())); totalMemory.setText(toByteString(r.totalMemory())); usedMemory.setText(toByteString(r.totalMemory() - r.freeMemory())); maxMemory.setText(toByteString(r.maxMemory())); - + CachedDataSource cache = CachedDataSource.getInstance(); cacheMemory.setText(toByteString(cache.getSize())); } @@ -260,9 +274,8 @@ private void update() /** * Updates the memory information displayed in the dialog. */ - public void update() - { - //this will cause paint to be called on the Event Dispatch Thread + public void update() { + // this will cause paint to be called on the Event Dispatch Thread memoryPanel.repaint(); } } \ No newline at end of file From 7575ef22f8b229a804cfd1cb2ab1c2da75fbbfea Mon Sep 17 00:00:00 2001 From: tparker Date: Thu, 2 Feb 2017 13:59:15 -0900 Subject: [PATCH 60/67] small text format --- src/main/java/gov/usgs/volcanoes/swarm/AboutDialog.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/AboutDialog.java b/src/main/java/gov/usgs/volcanoes/swarm/AboutDialog.java index e2b2a4bb..96cba3b0 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/AboutDialog.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/AboutDialog.java @@ -153,8 +153,8 @@ private JTextPane getTitlePane() { pane.setBorder(LineBorder.createBlackLineBorder()); pane.setContentType("text/html"); pane.setText("
" + "SWARM:
" - + "Seismic Wave Analysis/
" - + "Real-time Monitoring/
https://volcanoes.usgs.gov/software/swarm/
" + "Version: " + Version.POM_VERSION + + "Seismic Wave Analysis / " + + "Real-time Monitoring
https://volcanoes.usgs.gov/software/swarm/
" + "Version: " + Version.POM_VERSION + "
" + ""); return pane; From aca2a0f50bb61b0933e5c7f23e0d12a204bd25ac Mon Sep 17 00:00:00 2001 From: tparker Date: Thu, 2 Feb 2017 14:27:56 -0900 Subject: [PATCH 61/67] Tweak git ignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 982446bd..6d40ef6b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ /target/ /classes/ src/main/java/gov/usgs/volcanoes/swarm/Version.java +/.DS_Store +/dependency-reduced-pom.xml +/Swarm.config +/Swarm.config.bak From 68162205d056d2973dacc1b793acddda2f3bb0fc Mon Sep 17 00:00:00 2001 From: tparker Date: Thu, 2 Feb 2017 14:58:28 -0900 Subject: [PATCH 62/67] Roll back java 8-specific method call --- .../usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java index 76edcca8..29cd5d09 100644 --- a/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java +++ b/src/main/java/gov/usgs/volcanoes/swarm/map/hypocenters/HypocenterLayer.java @@ -152,8 +152,8 @@ public void draw(Graphics2D g2) { } private int getMarkerSize(double mag) { - int markerMag = Integer.max((int) mag, 0); - markerMag = Integer.min(markerMag, markerSize.length); + int markerMag = Math.max((int) mag, 0); + markerMag = Math.min(markerMag, markerSize.length); return markerSize[markerMag]; } From 46385f87e4d71faf3d0add7fe340c6e5bd5b1c39 Mon Sep 17 00:00:00 2001 From: tparker Date: Fri, 3 Feb 2017 11:58:18 -0900 Subject: [PATCH 63/67] Update changes file for 2.6.0 --- CHANGES.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 52863203..373efeb2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,11 @@ +## Version 2.6.0 + * Add option to plot hypocenters from NEIC summary files on map + * Add event inspector dialog + * Expand maximum time span of inset wave window + * Quote command line args before passing them to java + * Fix wave close buttons + * Fix kisok enter/exit keys + ## Version 2.5.2 * Remove obsoleted DefaultMetadata Class. From c3ab38aae89bf73649a0c20504a8cc54611afea2 Mon Sep 17 00:00:00 2001 From: tparker Date: Fri, 3 Feb 2017 12:01:22 -0900 Subject: [PATCH 64/67] Do not write debug logs to a file. --- src/main/resources/log4jDebug.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/log4jDebug.properties b/src/main/resources/log4jDebug.properties index 219f95e5..ff2cf672 100644 --- a/src/main/resources/log4jDebug.properties +++ b/src/main/resources/log4jDebug.properties @@ -1,4 +1,4 @@ -log4j.rootLogger=ALL, stdout, R +log4j.rootLogger=ALL, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout @@ -8,7 +8,7 @@ log4j.appender.stdout.Threshold=DEBUG log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd hh:mm:ss} %5p - %m%n log4j.appender.R=org.apache.log4j.RollingFileAppender -log4j.appender.R.File=pensive.log +log4j.appender.R.File=swarm.log log4j.appender.R.MaxFileSize=100KB # Keep one backup file log4j.appender.R.MaxBackupIndex=9 From 7cbacc0862941ecd783c924897b2401bbf63903a Mon Sep 17 00:00:00 2001 From: tparker Date: Fri, 3 Feb 2017 15:00:09 -0900 Subject: [PATCH 65/67] Update volcanoes links to https --- pom.xml | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 7ac9d241..ae5c62a0 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ jar Swarm - http://volcanoes.usgs.gov/software/swarm + https://volcanoes.usgs.gov/software/swarm Swarm is a Java application designed to display and analyze seismic waveforms in real-time. Swarm can connect to and read from a variety of different static and dynamics data sources, including Earthworm waveservers, IRIS DMCs, SEED and SAC files, and simple ASCII. Swarm has both time- and frequency-domain analysis tools, along with a simple but powerful mapping platfrom. A full-screen kiosk mode can act as a low-cost, low-maintenance replacement for paper drum recorders. Swarm was written by and for scientists and provides fine control over many different program settings and variables. UTF-8 @@ -434,6 +434,42 @@
+ + sh.tak.appbundler + appbundle-maven-plugin + 1.2.0 + + gov.usgs.volcanoes.swarm.Swarm + /Users/tparker/jre/jre1.8.0_121.jre + true + + + ${project.basedir} + + README.md + LICENSE.md + CHANGES.md + IRIS_networks.txt + NTP.config + WaveDefaults.config + clip.wav + swarm.sh + swarm_console.bat + layouts + mapdata + + + + + + + package + + bundle + + + +
@@ -451,7 +487,7 @@ volcanoes - http://volcanoes.usgs.gov/software/maven2/ + https://volcanoes.usgs.gov/software/maven2/ From b77eb91cf3f860c499bcd79f3c2abc7af6a012db Mon Sep 17 00:00:00 2001 From: tparker Date: Fri, 3 Feb 2017 21:08:36 -0900 Subject: [PATCH 66/67] Allow more log4j versions --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ae5c62a0..56ca8c62 100644 --- a/pom.xml +++ b/pom.xml @@ -555,7 +555,7 @@ org.apache log4j - 1.2.13 + [1.2.13,) gov.usgs.volcanoes From 1b9d1ee255175b06d4978df4da152d691e28882c Mon Sep 17 00:00:00 2001 From: tparker Date: Fri, 3 Feb 2017 21:33:16 -0900 Subject: [PATCH 67/67] Update log4j group id. --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 56ca8c62..b70cdcd0 100644 --- a/pom.xml +++ b/pom.xml @@ -222,7 +222,7 @@ true - org.apache:log4j + log4j:log4j org/apache/log4j/** @@ -281,7 +281,7 @@ com.martiansoftware:jsap net.sourceforge.jtransforms:jtransforms org.slf4j:* - org.apache:log4j + log4j:log4j net.alomax:* edu.sc.seis:* colt:colt @@ -553,9 +553,9 @@ 1.7.1 - org.apache + log4j log4j - [1.2.13,) + 1.2.13 gov.usgs.volcanoes