diff --git a/README.md b/README.md index 8b8773d5..5ced1505 100644 --- a/README.md +++ b/README.md @@ -42,18 +42,18 @@ We don't presently deploy versioned artifacts into a public repository like the #### **As a single runnable JAR** ```shell -java -jar coda-calibration/calibration-standalone/target/calibration-standalone-1.0.8-runnable.jar +java -jar coda-calibration/calibration-standalone/target/calibration-standalone-1.0.9-runnable.jar ``` #### **GUI alone** ```shell -java -jar coda-calibration/calibration-gui/target/calibration-gui-1.0.8-runnable.jar +java -jar coda-calibration/calibration-gui/target/calibration-gui-1.0.9-runnable.jar ``` #### **Calibration REST service alone** ```shell -java -jar coda-calibration/calibration-service/application/target/application-1.0.8-runnable.jar +java -jar coda-calibration/calibration-service/application/target/application-1.0.9-runnable.jar ``` #### A note about HTTPS diff --git a/calibration-gui/pom.xml b/calibration-gui/pom.xml index 931a1847..374102ca 100644 --- a/calibration-gui/pom.xml +++ b/calibration-gui/pom.xml @@ -1,23 +1,23 @@ - + 4.0.0 gov.llnl.gnem.apps.coda.calibration coda-calibration - 1.0.8.1 + 1.0.9 calibration-gui jar calibration-gui - http://www.llnl.gov + https://www.llnl.gov Lawrence Livermore National Laboratory (LLNL) - http://www.llnl.gov + https://www.llnl.gov @@ -37,7 +37,7 @@ spring-milestones - http://repo.spring.io/milestone + https://repo.spring.io/milestone @@ -62,10 +62,6 @@ org.eclipse.persistence javax.persistence - - io.springlets - springlets-context - org.aspectj aspectjweaver diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/CodaGuiController.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/CodaGuiController.java index 689ac5ec..1151ed41 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/CodaGuiController.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/CodaGuiController.java @@ -456,6 +456,7 @@ private void listener(CalibrationStatusEvent event) { if (!monitors.containsKey(event.getId()) && event.getStatus() == Status.STARTING) { CalibrationProgressListener eventMonitor = new CalibrationProgressListener(bus, event); ProgressMonitor monitor = new ProgressMonitor("Calibration Progress " + event.getId(), eventMonitor); + monitor.addCancelCallback(() -> calibrationClient.cancelCalibration(event.getId()).subscribe()); monitors.put(event.getId(), monitor); loadingGui.addProgressMonitor(monitor); loadingGui.show(); @@ -465,6 +466,7 @@ private void listener(CalibrationStatusEvent event) { final ProgressMonitor monitor = monitors.remove(event.getId()); if (monitor != null) { monitor.setProgressStage("Finished"); + monitor.clearCancelCallbacks(); service.schedule(() -> loadingGui.removeProgressMonitor(monitor), 15, TimeUnit.MINUTES); } } else { diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/AbstractMeasurementController.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/AbstractMeasurementController.java new file mode 100644 index 00000000..2f10a390 --- /dev/null +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/AbstractMeasurementController.java @@ -0,0 +1,1050 @@ +/* +* Copyright (c) 2020, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* CODE-743439. +* All rights reserved. +* +* Licensed under the Apache License, Version 2.0 (the “Licensee”); you may not use this file except in compliance with the License. You may obtain a copy of the License at: +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and limitations under the license. +* +* This work was performed under the auspices of the U.S. Department of Energy +* by Lawrence Livermore National Laboratory under Contract DE-AC52-07NA27344. +*/ +package gov.llnl.gnem.apps.coda.calibration.gui.controllers; + +import java.awt.Color; +import java.awt.event.MouseEvent; +import java.awt.geom.Point2D; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.InvocationTargetException; +import java.text.NumberFormat; +import java.time.Duration; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.Collections; +import java.util.DoubleSummaryStatistics; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.Observable; +import java.util.Observer; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +import javax.swing.SwingUtilities; + +import org.apache.batik.svggen.SVGGraphics2DIOException; +import org.apache.commons.math3.stat.descriptive.SummaryStatistics; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.Subscribe; + +import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ParameterClient; +import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.EventClient; +import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.SpectraClient; +import gov.llnl.gnem.apps.coda.calibration.gui.plotting.MapPlottingUtilities; +import gov.llnl.gnem.apps.coda.calibration.gui.plotting.SpectralPlot; +import gov.llnl.gnem.apps.coda.calibration.gui.util.Axis; +import gov.llnl.gnem.apps.coda.calibration.model.domain.MeasuredMwDetails; +import gov.llnl.gnem.apps.coda.calibration.model.domain.Spectra; +import gov.llnl.gnem.apps.coda.calibration.model.domain.SpectraMeasurement; +import gov.llnl.gnem.apps.coda.common.gui.data.client.api.WaveformClient; +import gov.llnl.gnem.apps.coda.common.gui.events.WaveformSelectionEvent; +import gov.llnl.gnem.apps.coda.common.gui.plotting.LabeledPlotPoint; +import gov.llnl.gnem.apps.coda.common.gui.plotting.PlotPoint; +import gov.llnl.gnem.apps.coda.common.gui.plotting.SymbolStyleMapFactory; +import gov.llnl.gnem.apps.coda.common.gui.util.CellBindingUtils; +import gov.llnl.gnem.apps.coda.common.gui.util.MaybeNumericStringComparator; +import gov.llnl.gnem.apps.coda.common.gui.util.NumberFormatFactory; +import gov.llnl.gnem.apps.coda.common.gui.util.SnapshotUtils; +import gov.llnl.gnem.apps.coda.common.mapping.api.GeoMap; +import gov.llnl.gnem.apps.coda.common.model.domain.Event; +import gov.llnl.gnem.apps.coda.common.model.domain.Pair; +import gov.llnl.gnem.apps.coda.common.model.domain.Waveform; +import gov.llnl.gnem.apps.coda.common.model.messaging.WaveformChangeEvent; +import javafx.application.Platform; +import javafx.beans.binding.Bindings; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.embed.swing.SwingFXUtils; +import javafx.embed.swing.SwingNode; +import javafx.event.EventHandler; +import javafx.fxml.FXML; +import javafx.geometry.Insets; +import javafx.scene.control.Button; +import javafx.scene.control.ComboBox; +import javafx.scene.control.ContextMenu; +import javafx.scene.control.Label; +import javafx.scene.control.MenuItem; +import javafx.scene.control.Tab; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableColumn.CellDataFeatures; +import javafx.scene.control.TableView; +import javafx.scene.control.TextField; +import javafx.scene.image.ImageView; +import javafx.scene.input.MouseButton; +import javafx.scene.layout.StackPane; +import llnl.gnem.core.gui.plotting.HorizPinEdge; +import llnl.gnem.core.gui.plotting.PaintMode; +import llnl.gnem.core.gui.plotting.PenStyle; +import llnl.gnem.core.gui.plotting.PlotObjectClicked; +import llnl.gnem.core.gui.plotting.SymbolLegend; +import llnl.gnem.core.gui.plotting.SymbolLegend.SymbolTextPair; +import llnl.gnem.core.gui.plotting.VertPinEdge; +import llnl.gnem.core.gui.plotting.color.ColorMap; +import llnl.gnem.core.gui.plotting.color.ViridisColorMap; +import llnl.gnem.core.gui.plotting.jmultiaxisplot.JMultiAxisPlot; +import llnl.gnem.core.gui.plotting.jmultiaxisplot.JSubplot; +import llnl.gnem.core.gui.plotting.plotobject.Circle; +import llnl.gnem.core.gui.plotting.plotobject.Line; +import llnl.gnem.core.gui.plotting.plotobject.PlotObject; +import llnl.gnem.core.gui.plotting.plotobject.Square; +import llnl.gnem.core.gui.plotting.plotobject.Symbol; +import llnl.gnem.core.gui.plotting.plotobject.SymbolDef; +import llnl.gnem.core.gui.plotting.plotobject.SymbolFactory; +import llnl.gnem.core.gui.plotting.plotobject.SymbolStyle; + +public abstract class AbstractMeasurementController implements MapListeningController, RefreshableController, ScreenshotEnabledController { + + private final Logger log = LoggerFactory.getLogger(this.getClass()); + private static final int MAX_LEGEND_COLORS = 8; + private static final Boolean SHOW_LEGEND = Boolean.TRUE; + private static final Boolean HIDE_LEGEND = Boolean.FALSE; + + @FXML + protected Tab resultsTab; + + @FXML + protected SwingNode mwPlotSwingNode; + private JMultiAxisPlot mwPlot; + private JSubplot mwPlotFigure; + private Line mwZeroLine; + + @FXML + protected SwingNode stressPlotSwingNode; + private JMultiAxisPlot stressPlot; + private JSubplot stressPlotFigure; + private Line stressZeroLine; + + @FXML + protected SwingNode sdPlotSwingNode; + private JMultiAxisPlot sdPlot; + private JSubplot sdPlotFigure; + + protected StackPane spectraPlotPanel; + + @FXML + protected ComboBox evidCombo; + + @FXML + protected TableView eventTable; + + @FXML + protected TableView iconTable; + + @FXML + protected TableColumn evidCol; + + @FXML + protected TableColumn mwCol; + + @FXML + protected TableColumn stressCol; + + @FXML + protected TableColumn measuredMwCol; + + @FXML + protected TableColumn measuredStressCol; + + @FXML + protected TableColumn valMwCol; + + @FXML + protected TableColumn valStressCol; + + @FXML + protected TableColumn mistfitCol; + + @FXML + protected TableColumn measuredCornerFreqCol; + + @FXML + protected TableColumn measuredMwUq1LowCol; + + @FXML + protected TableColumn measuredMwUq1HighCol; + + @FXML + protected TableColumn measuredMwUq2LowCol; + + @FXML + protected TableColumn measuredMwUq2HighCol; + + @FXML + protected TableColumn iterationsCol; + + @FXML + protected TableColumn dataCountCol; + + @FXML + protected TableColumn iconCol; + + @FXML + protected TableColumn stationCol; + + @FXML + protected TextField eventTime; + + @FXML + protected TextField eventLoc; + + protected List spectralMeasurements = new ArrayList<>(); + private ObservableList evids = FXCollections.observableArrayList(); + + protected SpectraClient spectraClient; + private ParameterClient paramClient; + protected EventClient referenceEventClient; + protected WaveformClient waveformClient; + + protected ObservableList mwParameters = FXCollections.observableArrayList(); + + private ObservableList stationSymbols = FXCollections.observableArrayList(); + private BiConsumer eventSelectionCallback; + private BiConsumer stationSelectionCallback; + + private Map> plotPointMap = new HashMap<>(); + private final List selectedPoints = new ArrayList<>(); + + private SymbolStyleMapFactory symbolStyleMapFactory; + private Map symbolStyleMap; + + private GeoMap mapImpl; + + private MapPlottingUtilities iconFactory; + + private MenuItem exclude; + private MenuItem include; + protected ContextMenu menu; + + private final NumberFormat dfmt4 = NumberFormatFactory.fourDecimalOneLeadingZero(); + + private ColorMap colorMap = new ViridisColorMap(); + private final AtomicReference minFreq = new AtomicReference<>(1.0); + private final AtomicReference maxFreq = new AtomicReference<>(-0.0); + + private final AtomicReference minY = new AtomicReference<>(1.0); + private final AtomicReference maxY = new AtomicReference<>(-0.0); + + @FXML + protected Button xAxisShrink; + private boolean shouldXAxisShrink = false; + + @FXML + protected Button yAxisShrink; + private boolean shouldYAxisShrink = false; + + private boolean isVisible = false; + + protected List spectraControllers = new ArrayList<>(1); + private EventBus bus; + + protected EventHandler menuHideHandler = (evt) -> { + if (MouseButton.SECONDARY != evt.getButton()) { + menu.hide(); + } + }; + + //TODO: Break this up into components so this isn't so incredibly huge. + public AbstractMeasurementController(SpectraClient spectraClient, ParameterClient paramClient, EventClient referenceEventClient, WaveformClient waveformClient, SymbolStyleMapFactory styleFactory, + GeoMap map, MapPlottingUtilities iconFactory, EventBus bus) { + this.spectraClient = spectraClient; + this.paramClient = paramClient; + this.referenceEventClient = referenceEventClient; + this.waveformClient = waveformClient; + this.symbolStyleMapFactory = styleFactory; + this.mapImpl = map; + this.bus = bus; + this.iconFactory = iconFactory; + + eventSelectionCallback = (selected, eventId) -> { + selectDataByCriteria(selected, eventId); + }; + + stationSelectionCallback = (selected, stationId) -> { + selectDataByCriteria(selected, stationId); + }; + + this.bus.register(this); + } + + protected abstract String getDisplayName(); + + protected abstract List getFitSpectra(); + + protected abstract void setActive(List waveforms, List plotObjects, boolean active, BiConsumer, Boolean> activationFunc); + + protected abstract List getSpectraData(); + + protected abstract void runGuiUpdate(Runnable runnable) throws InvocationTargetException, InterruptedException; + + protected abstract List getEvents(); + + public void initialize() { + evidCombo.setItems(evids); + + configureAxisShrink(xAxisShrink, () -> { + shouldXAxisShrink = !shouldXAxisShrink; + return shouldXAxisShrink; + }, Axis.X); + + configureAxisShrink(yAxisShrink, () -> { + shouldYAxisShrink = !shouldYAxisShrink; + return shouldYAxisShrink; + }, Axis.Y); + + SwingUtilities.invokeLater(() -> { + mwPlot = new JMultiAxisPlot(); + mwPlotFigure = mwPlot.addSubplot(); + + mwPlot.getTitle().setText("Mw comparison"); + mwPlot.getXaxis().setLabelText("Measured"); + mwPlot.setYaxisVisibility(true); + mwPlotSwingNode.setContent(mwPlot); + + mwPlotFigure.getYaxis().setLabelOffset(2.5d * mwPlot.getXaxis().getLabelOffset()); + mwPlotFigure.setAxisLimits(0.0, 10.0, 0.0, 10.0); + mwPlotFigure.getYaxis().setLabelText("Reference (red), Validation (black)"); + + stressPlot = new JMultiAxisPlot(); + stressPlotFigure = stressPlot.addSubplot(); + + stressPlot.getTitle().setText("Stress comparison"); + stressPlot.getXaxis().setLabelText("Measured"); + stressPlot.setYaxisVisibility(true); + stressPlotSwingNode.setContent(stressPlot); + + stressPlotFigure.getYaxis().setLabelOffset(2.5d * stressPlot.getXaxis().getLabelOffset()); + stressPlotFigure.setAxisLimits(0.0, 10.0, 0.0, 10.0); + stressPlotFigure.getYaxis().setLabelText("Reference (red), Validation (black)"); + + sdPlot = new JMultiAxisPlot(); + sdPlotFigure = sdPlot.addSubplot(); + + sdPlot.getTitle().setText("Site correction overview"); + sdPlot.getXaxis().setLabelText("Frequency"); + sdPlot.setYaxisVisibility(true); + sdPlotSwingNode.setContent(sdPlot); + + sdPlotFigure.getYaxis().setLabelOffset(2.5d * sdPlot.getXaxis().getLabelOffset()); + sdPlotFigure.setAxisLimits(0.0, 10.0, 0.0, 2.0); + sdPlotFigure.getYaxis().setLabelText("Standard Deviation"); + + int points = 50; + double dx = 20.0 / (points - 1); + float[] xy = new float[points]; + for (int i = 0; i < points; i++) { + xy[i] = (float) (-5.0 + (dx * i)); + } + mwZeroLine = new Line(xy, xy, Color.LIGHT_GRAY, PaintMode.COPY, PenStyle.DASH, 2); + stressZeroLine = new Line(xy, xy, Color.LIGHT_GRAY, PaintMode.COPY, PenStyle.DASH, 2); + mwPlotFigure.AddPlotObject(mwZeroLine); + stressPlotFigure.AddPlotObject(stressZeroLine); + }); + + evidCombo.valueProperty().addListener((observable, oldValue, newValue) -> { + if (newValue != null && !newValue.equals(oldValue)) { + refreshView(); + } + }); + + CellBindingUtils.attachTextCellFactoriesString(evidCol, MeasuredMwDetails::getEventId); + evidCol.comparatorProperty().set(new MaybeNumericStringComparator()); + + CellBindingUtils.attachTextCellFactories(mwCol, MeasuredMwDetails::getRefMw, dfmt4); + CellBindingUtils.attachTextCellFactories(stressCol, MeasuredMwDetails::getRefApparentStressInMpa, dfmt4); + + CellBindingUtils.attachTextCellFactories(valMwCol, MeasuredMwDetails::getValMw, dfmt4); + CellBindingUtils.attachTextCellFactories(valStressCol, MeasuredMwDetails::getValApparentStressInMpa, dfmt4); + + CellBindingUtils.attachTextCellFactories(measuredMwCol, MeasuredMwDetails::getMw, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredStressCol, MeasuredMwDetails::getApparentStressInMpa, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredCornerFreqCol, MeasuredMwDetails::getCornerFreq, dfmt4); + + CellBindingUtils.attachTextCellFactories(mistfitCol, MeasuredMwDetails::getMisfit, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredMwUq1LowCol, MeasuredMwDetails::getMw1Min, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredMwUq1HighCol, MeasuredMwDetails::getMw1Max, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredMwUq2LowCol, MeasuredMwDetails::getMw2Min, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredMwUq2HighCol, MeasuredMwDetails::getMw2Max, dfmt4); + + iterationsCol.setCellValueFactory(x -> Bindings.createIntegerBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(MeasuredMwDetails::getIterations).orElseGet(() -> 0)) + .asObject()); + + dataCountCol.setCellValueFactory(x -> Bindings.createIntegerBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(MeasuredMwDetails::getDataCount).orElseGet(() -> 0)) + .asObject()); + + iconCol.setCellValueFactory(x -> Bindings.createObjectBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(pp -> { + ImageView imView = new ImageView(SwingFXUtils.toFXImage(SymbolFactory.createSymbol(pp.getStyle(), 0, 0, 2, pp.getColor(), pp.getColor(), pp.getColor(), "", true, false, 10.0) + .getBufferedImage(256), + null)); + imView.setFitHeight(12); + imView.setFitWidth(12); + return imView; + }).orElseGet(() -> new ImageView()))); + + stationCol.setCellValueFactory(x -> Bindings.createStringBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(LabeledPlotPoint::getLabel).orElseGet(String::new))); + + eventTable.setItems(mwParameters); + iconTable.setItems(stationSymbols); + + iconCol.prefWidthProperty().bind(iconTable.widthProperty().multiply(0.3)); + stationCol.prefWidthProperty().bind(iconTable.widthProperty().multiply(0.7)); + + menu = new ContextMenu(); + include = new MenuItem("Include Selected"); + menu.getItems().add(include); + exclude = new MenuItem("Exclude Selected"); + menu.getItems().add(exclude); + } + + protected Object getPoint2D(Symbol sym) { + return new Point2D.Double(sym.getXcenter(), sym.getYcenter()); + } + + private void showWaveformPopup(Waveform waveform) { + bus.post(new WaveformSelectionEvent(waveform.getId())); + } + + private void plotSpectra() { + clearSpectraPlots(); + spectraControllers.forEach(spc -> spc.getSymbolMap().clear()); + plotPointMap.clear(); + List filteredMeasurements; + + spectraControllers.forEach(spc -> { + SpectralPlot plot = spc.getSpectralPlot(); + plot.setAutoCalculateXaxisRange(shouldXAxisShrink); + if (!shouldXAxisShrink) { + plot.setAllXlimits(minFreq.get(), maxFreq.get()); + } + }); + + final List fittingSpectra; + if (evidCombo != null && evidCombo.getSelectionModel().getSelectedIndex() > 0) { + filteredMeasurements = filterToEvent(evidCombo.getSelectionModel().getSelectedItem(), spectralMeasurements); + fittingSpectra = getFitSpectra(); + Spectra referenceSpectra = spectraClient.getReferenceSpectra(evidCombo.getSelectionModel().getSelectedItem()).block(Duration.ofSeconds(2)); + fittingSpectra.add(referenceSpectra); + Spectra validationSpectra = spectraClient.getValidationSpectra(evidCombo.getSelectionModel().getSelectedItem()).block(Duration.ofSeconds(2)); + fittingSpectra.add(validationSpectra); + if (filteredMeasurements != null && filteredMeasurements.size() > 0 && filteredMeasurements.get(0).getWaveform() != null) { + Event event = filteredMeasurements.get(0).getWaveform().getEvent(); + eventTime.setText("Date: " + DateTimeFormatter.ISO_INSTANT.format(event.getOriginTime().toInstant())); + eventLoc.setText("Lat: " + dfmt4.format(event.getLatitude()) + " Lon: " + dfmt4.format(event.getLongitude())); + eventTime.setVisible(true); + eventLoc.setVisible(true); + } + } else { + eventTime.setVisible(false); + eventLoc.setVisible(false); + filteredMeasurements = spectralMeasurements; + fittingSpectra = null; + } + + spectraControllers.forEach(spc -> { + if (fittingSpectra != null) { + spc.getSpectralPlot().plotXYdata(toPlotPoints(filteredMeasurements, spc.getDataFunc()), SHOW_LEGEND, fittingSpectra); + } else { + spc.getSpectralPlot().plotXYdata(toPlotPoints(filteredMeasurements, spc.getDataFunc()), HIDE_LEGEND); + } + spc.getSymbolMap().putAll(mapSpectraToPoint(filteredMeasurements, spc.getDataFunc())); + }); + mapMeasurements(filteredMeasurements); + + minY.set(100.0); + maxY.set(0.0); + DoubleSummaryStatistics stats = filteredMeasurements.stream() + .filter(Objects::nonNull) + .map(spec -> spec.getPathAndSiteCorrected()) + .filter(v -> v != 0.0) + .collect(Collectors.summarizingDouble(Double::doubleValue)); + maxY.set(stats.getMax() + .1); + minY.set(stats.getMin() - .1); + + spectraControllers.forEach(spc -> spc.setYAxisResize(shouldYAxisShrink, minY.get(), maxY.get())); + } + + private void mapMeasurements(List measurements) { + if (measurements != null) { + mapImpl.addIcons(iconFactory.genIconsFromWaveforms(eventSelectionCallback, + stationSelectionCallback, + measurements.stream().map(m -> m.getWaveform()).filter(Objects::nonNull).collect(Collectors.toList()))); + } + } + + protected void clearSpectraPlots() { + spectraControllers.forEach(spc -> spc.getSpectralPlot().clearPlot()); + } + + private List filterToEvent(String selectedItem, List spectralMeasurements) { + return spectralMeasurements.stream().filter(spec -> selectedItem.equalsIgnoreCase(spec.getWaveform().getEvent().getEventId())).collect(Collectors.toList()); + } + + private Map mapSpectraToPoint(List spectralMeasurements, Function func) { + return spectralMeasurements.stream() + .filter(spectra -> !func.apply(spectra).equals(0.0)) + .collect(Collectors.toMap(spectra -> new Point2D.Double(Math.log10(centerFreq(spectra.getWaveform().getLowFrequency(), spectra.getWaveform().getHighFrequency())), + func.apply(spectra)), + Function.identity(), + (a, b) -> b, + HashMap::new)); + } + + private List toPlotPoints(List spectralMeasurements, Function func) { + List list = spectralMeasurements.stream() + .filter(spectra -> !func.apply(spectra).equals(0.0)) + .filter(spectra -> spectra != null && spectra.getWaveform() != null && spectra.getWaveform().getStream() != null + && spectra.getWaveform().getStream().getStation() != null) + .map(spectra -> { + String key = spectra.getWaveform().getStream().getStation().getStationName(); + PlotPoint pp = getPlotPoint(key, spectra.getWaveform().isActive()); + PlotPoint point = new LabeledPlotPoint(key, + new PlotPoint(Math.log10(centerFreq(spectra.getWaveform().getLowFrequency(), + spectra.getWaveform().getHighFrequency())), + func.apply(spectra), + pp.getStyle(), + pp.getColor())); + if (hasEventAndStation(spectra)) { + plotPointMap.computeIfAbsent(spectra.getWaveform().getEvent().getEventId(), k -> new ArrayList<>()).add(point); + plotPointMap.computeIfAbsent(spectra.getWaveform().getStream().getStation().getStationName(), k -> new ArrayList<>()).add(point); + } + return point; + }) + .collect(Collectors.toList()); + return list; + } + + private PlotPoint getPlotPoint(String key, boolean active) { + PlotPoint pp = new PlotPoint(symbolStyleMap.get(key)); + if (!active) { + pp.setColor(Color.GRAY); + } + return pp; + } + + private boolean hasEventAndStation(SpectraMeasurement spectra) { + return spectra != null && spectra.getWaveform() != null && spectra.getWaveform().getEvent() != null && spectra.getWaveform().getEvent().getEventId() != null + && spectra.getWaveform().getStream() != null && spectra.getWaveform().getStream().getStation() != null && spectra.getWaveform().getStream().getStation().getStationName() != null; + } + + private double centerFreq(Double lowFrequency, Double highFrequency) { + return lowFrequency + (highFrequency - lowFrequency) / 2.; + } + + protected void reloadData() { + try { + runGuiUpdate(() -> clearSpectraPlots()); + maxFreq.set(-0.0); + minFreq.set(1.0); + + DoubleSummaryStatistics stats = paramClient.getSharedFrequencyBandParameters() + .filter(Objects::nonNull) + .collectList() + .block(Duration.of(10l, ChronoUnit.SECONDS)) + .stream() + .map(sfb -> Math.log10(centerFreq(sfb.getLowFrequency(), sfb.getHighFrequency()))) + .collect(Collectors.summarizingDouble(Double::doubleValue)); + maxFreq.set(stats.getMax()); + minFreq.set(stats.getMin()); + + preloadData(); + spectralMeasurements.clear(); + spectralMeasurements.addAll(getSpectraData()); + + runGuiUpdate(() -> { + mwParameters.clear(); + mwPlotFigure.Clear(); + stressPlotFigure.Clear(); + sdPlotFigure.Clear(); + mwPlotFigure.AddPlotObject(mwZeroLine); + stressPlotFigure.AddPlotObject(stressZeroLine); + List evs = getEvents(); + + double minMw = 10.0; + double maxMw = 0.0; + double minStress = 1.0; + double maxStress = 0.0; + for (MeasuredMwDetails ev : evs) { + mwParameters.add(ev); + + if (ev.getMw() != null && ev.getMw() != 0.0) { + Double mw = ev.getMw(); + if (mw < minMw) { + minMw = mw; + } + if (mw > maxMw) { + maxMw = mw; + } + + Double valMw = ev.getValMw(); + if (valMw != null && valMw != 0.0) { + if (valMw < minMw) { + minMw = valMw; + } + if (valMw > maxMw) { + maxMw = valMw; + } + + Square valSym = new Square(mw, valMw, 2.2, Color.BLACK, Color.BLACK, Color.BLACK, ev.getEventId(), true, false, 6.0); + mwPlotFigure.AddPlotObject(valSym); + } + + if (ev.getRefMw() != null && ev.getRefMw() != 0.0) { + Double ref = ev.getRefMw(); + if (ref < minMw) { + minMw = ref; + } + if (ref > maxMw) { + maxMw = ref; + } + + Circle mwSym = new Circle(mw, ref, 2.0, Color.RED, Color.RED, Color.RED, ev.getEventId(), true, false, 6.0); + mwPlotFigure.AddPlotObject(mwSym); + } + + Double stress = ev.getApparentStressInMpa(); + Double refStress = ev.getRefApparentStressInMpa(); + + if (stress != null) { + if (stress < minStress) { + minStress = stress; + } + if (stress > maxStress) { + maxStress = stress; + } + + if (refStress == null) { + refStress = 0.0; + } + + Double valStress = ev.getValApparentStressInMpa(); + if (valStress != null && valStress != 0.0) { + if (valStress < minStress) { + minStress = valStress; + } + if (valStress > maxStress) { + maxStress = valStress; + } + + Square valSym = new Square(stress, valStress, 2.2, Color.BLACK, Color.BLACK, Color.BLACK, ev.getEventId(), true, false, 6.0); + stressPlotFigure.AddPlotObject(valSym); + } + + if (refStress != null && refStress != 0.0) { + if (refStress < minStress) { + minStress = refStress; + } + if (refStress > maxStress) { + maxStress = refStress; + } + + Circle stressSym = new Circle(stress, refStress, 2.0, Color.RED, Color.RED, Color.RED, ev.getEventId(), true, false, 6.0); + stressPlotFigure.AddPlotObject(stressSym); + } + } + } + } + + maxMw = maxMw + .1; + minMw = minMw > maxMw ? minMw = maxMw - .1 : minMw - .1; + + mwPlotFigure.setAxisLimits(minMw, maxMw, minMw, maxMw); + + maxStress = maxStress + .1; + minStress = minStress > maxStress ? minStress = maxStress - .1 : minStress - .1; + + stressPlotFigure.setAxisLimits(minStress, maxStress, minStress, maxStress); + }); + + symbolStyleMap = symbolStyleMapFactory.build(spectralMeasurements, new Function() { + @Override + public String apply(SpectraMeasurement t) { + return t.getWaveform().getStream().getStation().getStationName(); + } + }); + + runGuiUpdate(() -> { + stationSymbols.clear(); + stationSymbols.addAll(symbolStyleMap.entrySet().stream().map(e -> new LabeledPlotPoint(e.getKey(), e.getValue())).collect(Collectors.toList())); + + Platform.runLater(() -> { + evids.clear(); + evids.add("All"); + evids.addAll(spectralMeasurements.stream() + .map(spec -> spec.getWaveform().getEvent().getEventId()) + .distinct() + .sorted(new MaybeNumericStringComparator()) + .collect(Collectors.toList())); + eventTable.sort(); + }); + + Map> evidStats = new HashMap<>(); + + double minSite = 1E2; + double maxSite = -1E2; + double minFreq = 1E2; + double maxFreq = -1E2; + int minStations = 2; + int maxStations = 3; + + for (SpectraMeasurement meas : spectralMeasurements) { + String evid = meas.getWaveform().getEvent().getEventId(); + Double freq = centerFreq(meas.getWaveform()); + evidStats.computeIfAbsent(evid, key -> new HashMap<>()).computeIfAbsent(freq, (key) -> new SummaryStatistics()).addValue(meas.getPathAndSiteCorrected()); + } + + for (Map freqStats : evidStats.values()) { + for (Entry entry : freqStats.entrySet()) { + double site = entry.getValue().getStandardDeviation(); + if (entry.getValue() != null && entry.getValue().getN() > 1) { + if (maxStations < entry.getValue().getN()) { + maxStations = (int) entry.getValue().getN(); + } + if (site < minSite) { + minSite = site; + } + if (site > maxSite) { + maxSite = site; + } + if (entry.getKey() < minFreq) { + minFreq = entry.getKey(); + } + if (entry.getKey() > maxFreq) { + maxFreq = entry.getKey(); + } + } + } + } + + colorMap.setRange(minStations, maxStations); + + for (Map freqStats : evidStats.values()) { + for (Entry entry : freqStats.entrySet()) { + double site = entry.getValue().getStandardDeviation(); + if (entry.getValue() != null && entry.getValue().getN() > 1) { + Color color = colorMap.getColor(entry.getValue().getN()); + Circle sdSym = new Circle(entry.getKey(), site, 2.0, color, color, color, "", true, false, 6.0); + sdPlotFigure.AddPlotObject(sdSym); + } + } + } + + maxSite = maxSite + .1; + minSite = minSite > maxSite ? minSite = maxSite - .1 : minSite - .1; + + maxFreq = maxFreq + 5.0; + minFreq = minFreq > maxFreq ? minFreq = maxFreq - .1 : minFreq - 1.0; + + sdPlotFigure.setAxisLimits(minFreq, maxFreq, minSite, maxSite); + sdPlotFigure.AddPlotObject(createColorLegend(minStations, maxStations)); + }); + + runGuiUpdate(() -> { + mwPlot.repaint(); + stressPlot.repaint(); + sdPlot.repaint(); + }); + } catch (InvocationTargetException ex) { + //nop + } catch (InterruptedException ex) { + log.warn("Swing interrupt during re-plotting of controller", ex); + Thread.currentThread().interrupt(); + } + } + + protected void preloadData() { + // Placeholder to allow children to overload any pre-fetching needed before data calls + } + + private PlotObject createColorLegend(int minVal, int maxVal) { + int range = maxVal - minVal; + int legendEntries = range; + if (legendEntries > MAX_LEGEND_COLORS) { + legendEntries = MAX_LEGEND_COLORS; + } + List legendSymbols = new ArrayList<>(range); + + Color color = colorMap.getColor(minVal); + legendSymbols.add(new SymbolTextPair(Integer.toString(minVal), new SymbolDef(SymbolStyle.CIRCLE, 1.0, color, color))); + if (legendEntries > 2) { + int i = minVal + 1; + while (i < legendEntries + minVal) { + color = colorMap.getColor(i); + legendSymbols.add(new SymbolTextPair(Integer.toString(i), new SymbolDef(SymbolStyle.CIRCLE, 1.0, color, color))); + i = i + (range / (legendEntries - 1)); + } + } + color = colorMap.getColor(maxVal); + legendSymbols.add(new SymbolTextPair(maxVal + "+", new SymbolDef(SymbolStyle.CIRCLE, 1.0, color, color))); + return new SymbolLegend(legendSymbols, sdPlot.getTitle().getFontName(), 8.0, HorizPinEdge.RIGHT, VertPinEdge.TOP, 1, 1); + } + + private Double centerFreq(Waveform waveform) { + return ((waveform.getHighFrequency() - waveform.getLowFrequency()) / 2.0) + waveform.getLowFrequency(); + } + + @Override + public void refreshView() { + if (isVisible) { + mapImpl.clearIcons(); + plotSpectra(); + Platform.runLater(() -> { + spectraControllers.forEach(spc -> spc.getSpectralPlot().repaint()); + }); + } + } + + @Override + public Runnable getRefreshFunction() { + return () -> reloadData(); + } + + @Override + public Consumer getScreenshotFunction() { + return (folder) -> { + String timestamp = SnapshotUtils.getTimestampWithLeadingSeparator(); + try { + if (resultsTab.isSelected() && evidCombo.getValue() != null) { + SnapshotUtils.writePng(folder, new Pair<>(getDisplayName(), resultsTab.getContent()), timestamp); + spectraControllers.forEach(spc -> { + SpectralPlot plot = spc.getSpectralPlot(); + try { + plot.exportSVG(folder + File.separator + getDisplayName() + "_" + plot.getTitle() + "_" + evidCombo.getValue() + timestamp + ".svg"); + } catch (UnsupportedEncodingException | FileNotFoundException | SVGGraphics2DIOException e) { + log.error("Error attempting to write plots for controller : {}", e.getLocalizedMessage(), e); + } + }); + } else { + mwPlot.exportSVG(folder + File.separator + getDisplayName() + "_Mw" + timestamp + ".svg"); + stressPlot.exportSVG(folder + File.separator + getDisplayName() + "Site_Stress" + timestamp + ".svg"); + sdPlot.exportSVG(folder + File.separator + getDisplayName() + "_Station_Event_SD" + timestamp + ".svg"); + } + } catch (UnsupportedEncodingException | FileNotFoundException | SVGGraphics2DIOException e) { + log.error("Error attempting to write plots for controller : {}", e.getLocalizedMessage(), e); + } + }; + } + + private void selectDataByCriteria(Boolean selected, String key) { + List points = plotPointMap.get(key); + if (selected) { + selectPoints(points); + } else { + deselectPoints(points); + } + } + + private void selectPoints(List points) { + if (points != null && !points.isEmpty()) { + if (!selectedPoints.isEmpty()) { + deselectPoints(selectedPoints); + } + selectedPoints.addAll(points); + SwingUtilities.invokeLater(() -> { + points.forEach(point -> { + selectPoint(point); + }); + }); + } + } + + private void deselectPoints(List selected) { + if (selected != null && !selected.isEmpty()) { + List points = new ArrayList<>(selected.size()); + points.addAll(selected); + selectedPoints.clear(); + SwingUtilities.invokeLater(() -> { + points.forEach(point -> { + deselectPoint(point); + }); + }); + } + } + + private void selectPoint(PlotPoint point) { + runIfSymbolExists(point, (plot, xy) -> plot.selectPoint(xy)); + } + + private void deselectPoint(PlotPoint point) { + runIfSymbolExists(point, (plot, xy) -> plot.deselectPoint(xy)); + } + + private void runIfSymbolExists(PlotPoint point, BiConsumer xyPointFunction) { + Point2D.Double xyPoint = new Point2D.Double(point.getX(), point.getY()); + spectraControllers.forEach(spc -> { + Map symbolMap = spc.getSymbolMap(); + SpectralPlot plot = spc.getSpectralPlot(); + boolean existsInPlot = symbolMap.containsKey(xyPoint); + if (existsInPlot) { + xyPointFunction.accept(plot, xyPoint); + } + }); + } + + protected void setSymbolsActive(List objs, Boolean active) { + SwingUtilities.invokeLater(() -> { + objs.forEach(sym -> { + if (active) { + sym.setFillColor(sym.getEdgeColor()); + sym.setEdgeColor(Color.BLACK); + } else { + sym.setEdgeColor(sym.getFillColor()); + sym.setFillColor(Color.GRAY); + } + }); + Platform.runLater(() -> { + spectraControllers.forEach(spc -> spc.getSpectralPlot().repaint()); + }); + }); + } + + private void showContextMenu(List waveforms, List plotObjects, MouseEvent t, BiConsumer, Boolean> activationFunc) { + Platform.runLater(() -> { + include.setOnAction(evt -> setActive(waveforms, plotObjects, true, activationFunc)); + exclude.setOnAction(evt -> setActive(waveforms, plotObjects, false, activationFunc)); + menu.show(spectraPlotPanel, t.getXOnScreen(), t.getYOnScreen()); + }); + } + + @Subscribe + private void listener(WaveformChangeEvent wce) { + List nonNull = wce.getIds().stream().filter(Objects::nonNull).collect(Collectors.toList()); + synchronized (spectralMeasurements) { + Map activeMeasurements = spectralMeasurements.stream().collect(Collectors.toMap(x -> x.getWaveform().getId(), Function.identity())); + if (wce.isAddOrUpdate()) { + waveformClient.getWaveformMetadataFromIds(nonNull).collect(Collectors.toList()).block(Duration.ofSeconds(10l)).forEach(md -> { + SpectraMeasurement measurement = activeMeasurements.get(md.getId()); + if (measurement != null) { + measurement.getWaveform().setActive(md.isActive()); + } + }); + } else if (wce.isDelete()) { + nonNull.forEach(id -> { + SpectraMeasurement measurement = activeMeasurements.remove(id); + if (measurement != null) { + spectralMeasurements.remove(measurement); + } + }); + } + } + refreshView(); + } + + protected void handlePlotObjectClicked(Object obj, Function measurementFunc) { + if (obj instanceof PlotObjectClicked && ((PlotObjectClicked) obj).getMouseEvent().getID() == MouseEvent.MOUSE_RELEASED) { + PlotObjectClicked poc = (PlotObjectClicked) obj; + PlotObject po = poc.getPlotObject(); + if (po instanceof Symbol) { + SpectraMeasurement spectra = measurementFunc.apply((Symbol) po); + if (spectra != null && spectra.getWaveform() != null) { + if (SwingUtilities.isLeftMouseButton(poc.getMouseEvent())) { + selectPoints(plotPointMap.get(((Symbol) po).getText())); + if (spectra != null) { + showWaveformPopup(spectra.getWaveform()); + } + Platform.runLater(() -> menu.hide()); + } else if (SwingUtilities.isRightMouseButton(poc.getMouseEvent())) { + showContextMenu(Collections.singletonList(spectra.getWaveform()), Collections.singletonList((Symbol) po), poc.getMouseEvent(), (objs, active) -> { + setSymbolsActive(objs, active); + }); + } + } + } + } + } + + @Override + public void setVisible(boolean visible) { + isVisible = visible; + } + + private void configureAxisShrink(Button axisShrinkButton, Supplier toggleAxisShrink, Axis axis) { + Label axisShrinkOn = new Label("><"); + axisShrinkOn.setStyle("-fx-font-weight:bold; -fx-font-size: 12px;"); + axisShrinkOn.setPadding(Insets.EMPTY); + Label axisShrinkOff = new Label("<>"); + axisShrinkOff.setStyle("-fx-font-weight:bold; -fx-font-size: 12px;"); + axisShrinkOff.setPadding(Insets.EMPTY); + + if (Axis.Y == axis) { + axisShrinkOn.setRotate(90.0); + axisShrinkOff.setRotate(90.0); + } + + axisShrinkButton.setGraphic(axisShrinkOn); + axisShrinkButton.prefHeightProperty().bind(evidCombo.heightProperty()); + axisShrinkButton.setPadding(new Insets(axisShrinkButton.getPadding().getTop(), 0, axisShrinkButton.getPadding().getBottom(), 0)); + + axisShrinkButton.setOnAction(e -> { + if (toggleAxisShrink.get()) { + axisShrinkButton.setGraphic(axisShrinkOff); + } else { + axisShrinkButton.setGraphic(axisShrinkOn); + } + refreshView(); + }); + } + + protected Observer getPlotpointObserver(Supplier> symbolMapSupplier) { + return new Observer() { + @Override + public void update(Observable observable, Object obj) { + handlePlotObjectClicked(obj, sym -> symbolMapSupplier.get().get(getPoint2D(sym))); + } + }; + } + + @FXML + private void clearRefEvents() { + removeRefEvents(mwParameters); + } + + @FXML + private void removeRefEvents() { + List evs = new ArrayList<>(eventTable.getSelectionModel().getSelectedIndices().size()); + eventTable.getSelectionModel().getSelectedIndices().forEach(i -> evs.add(mwParameters.get(i))); + removeRefEvents(evs); + } + + @FXML + private void toggleValidationEvent() { + List evs = new ArrayList<>(eventTable.getSelectionModel().getSelectedIndices().size()); + eventTable.getSelectionModel().getSelectedIndices().forEach(i -> evs.add(mwParameters.get(i))); + if (evs != null && !evs.isEmpty()) { + referenceEventClient.toggleValidationEventsByEventId(evs.stream().map(mwd -> mwd.getEventId()).distinct().collect(Collectors.toList())) + .doOnComplete(() -> Platform.runLater(() -> reloadData())) + .subscribe(); + } + } + + private void removeRefEvents(List evs) { + if (evs != null && !evs.isEmpty()) { + referenceEventClient.removeReferenceEventsByEventId(evs.stream().map(mwd -> mwd.getEventId()).distinct().collect(Collectors.toList())) + .doOnSuccess((v) -> Platform.runLater(() -> reloadData())) + .subscribe(); + } + } +} diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/CodaParamLoadingController.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/CodaParamLoadingController.java index ae814b06..a3d3c093 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/CodaParamLoadingController.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/CodaParamLoadingController.java @@ -33,13 +33,14 @@ import gov.llnl.gnem.apps.coda.calibration.gui.converters.api.FileToParameterConverter; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ParameterClient; -import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ReferenceEventClient; +import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.EventClient; import gov.llnl.gnem.apps.coda.calibration.gui.events.ParametersLoadedEvent; import gov.llnl.gnem.apps.coda.calibration.model.domain.MdacParametersFI; import gov.llnl.gnem.apps.coda.calibration.model.domain.MdacParametersPS; import gov.llnl.gnem.apps.coda.calibration.model.domain.ReferenceMwParameters; import gov.llnl.gnem.apps.coda.calibration.model.domain.ShapeFitterConstraints; import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteCorrections; +import gov.llnl.gnem.apps.coda.calibration.model.domain.ValidationMwParameters; import gov.llnl.gnem.apps.coda.calibration.model.domain.VelocityConfiguration; import gov.llnl.gnem.apps.coda.common.model.domain.SharedFrequencyBandParameters; import reactor.core.publisher.Mono; @@ -51,7 +52,7 @@ public class CodaParamLoadingController { private ParameterClient paramsClient; - private ReferenceEventClient refMwClient; + private EventClient eventClient; private int maxBatching = 100; @@ -60,17 +61,17 @@ public class CodaParamLoadingController { private EventBus bus; @Autowired - public CodaParamLoadingController(List> fileConverters, ParameterClient paramsClient, ReferenceEventClient refMwClient, EventBus bus) { + public CodaParamLoadingController(List> fileConverters, ParameterClient paramsClient, EventClient eventClient, EventBus bus) { super(); this.fileConverters = fileConverters; this.paramsClient = paramsClient; - this.refMwClient = refMwClient; + this.eventClient = eventClient; this.bus = bus; if (paramsClient == null) { throw new IllegalStateException("Unable to find implementation of Coda Param loding client"); } - if (refMwClient == null) { + if (eventClient == null) { throw new IllegalStateException("Unable to find implementation of Reference Event loding client"); } } @@ -87,100 +88,104 @@ public void loadFiles(List files) { protected void convertFiles(List validFiles) { fileConverters.stream() - .forEach( - fileConverter -> fileConverter.convertFiles(validFiles) - .subscribe( - result -> { - // TODO: Feedback to the user about failure causes! - if (result.isSuccess()) { - Optional res = result.getResultPayload(); - if (res.isPresent()) { - if (res.get() instanceof SharedFrequencyBandParameters) { - SharedFrequencyBandParameters sfb = (SharedFrequencyBandParameters) res.get(); - try { - Mono request = paramsClient.setSharedFrequencyBandParameter(sfb); - if (request != null) { - request.retry(3).subscribe(); - } else { - log.error( - "Returned a null request from the parameter client while posting SharedFrequencyBandParameters {}", - sfb); - } - } catch (JsonProcessingException ex) { - log.trace(ex.getMessage(), ex); - } - } else if (res.get() instanceof SiteCorrections) { - try { - Mono request = paramsClient.setSiteSpecificFrequencyBandParameter( - new ArrayList<>(((SiteCorrections) res.get()).getSiteCorrections())); - if (request != null) { - request.retry(3).subscribe(); - } else { - log.error( - "Returned a null request from the parameter client while posting SiteFrequencyBandParameters {}", - (res.get())); - } - } catch (JsonProcessingException ex) { - log.trace(ex.getMessage(), ex); - } - } else if (res.get() instanceof MdacParametersPS) { - MdacParametersPS entry = (MdacParametersPS) res.get(); - try { - Mono request = paramsClient.setPsParameter(entry); - if (request != null) { - request.retry(3).subscribe(); - } else { - log.error("Returned a null request from the parameter client while posting MdacParametersPS {}", entry); - } - } catch (JsonProcessingException ex) { - log.trace(ex.getMessage(), ex); - } - } else if (res.get() instanceof MdacParametersFI) { - MdacParametersFI entry = (MdacParametersFI) res.get(); - try { - Mono request = paramsClient.setFiParameter(entry); - if (request != null) { - request.retry(3).subscribe(); - } else { - log.error("Returned a null request from the parameter client while posting MdacParametersFI {}", entry); - } - } catch (JsonProcessingException ex) { - log.trace(ex.getMessage(), ex); - } - } else if (res.get() instanceof ReferenceMwParameters) { - ReferenceMwParameters entry = (ReferenceMwParameters) res.get(); - try { - Mono request = refMwClient.postReferenceEvents(Collections.singletonList(entry)); - if (request != null) { - request.retry(3).subscribe(); - } else { - log.error( - "Returned a null request from the parameter client while posting ReferenceMwParameters {}", - entry); - } - } catch (JsonProcessingException ex) { - log.trace(ex.getMessage(), ex); - } - } else if (res.get() instanceof VelocityConfiguration) { - VelocityConfiguration entry = (VelocityConfiguration) res.get(); - Mono request = paramsClient.updateVelocityConfiguration(entry); - if (request != null) { - request.retry(3).subscribe(); - } else { - log.error("Returned a null request from the parameter client while posting VelocityConfiguration {}", entry); - } - } else if (res.get() instanceof ShapeFitterConstraints) { - ShapeFitterConstraints entry = (ShapeFitterConstraints) res.get(); - Mono request = paramsClient.updateShapeFitterConstraints(entry); - if (request != null) { - request.retry(3).subscribe(); - } else { - log.error("Returned a null request from the parameter client while posting ShapeFitterConstraints {}", entry); - } - } - } - } - })); + .forEach(fileConverter -> fileConverter.convertFiles(validFiles) + .subscribe(result -> { + // TODO: Feedback to the user about failure causes! + if (result.isSuccess()) { + Optional res = result.getResultPayload(); + if (res.isPresent()) { + if (res.get() instanceof SharedFrequencyBandParameters) { + SharedFrequencyBandParameters sfb = (SharedFrequencyBandParameters) res.get(); + try { + Mono request = paramsClient.setSharedFrequencyBandParameter(sfb); + if (request != null) { + request.retry(3).subscribe(); + } else { + log.error("Returned a null request from the parameter client while posting SharedFrequencyBandParameters {}", sfb); + } + } catch (JsonProcessingException ex) { + log.trace(ex.getMessage(), ex); + } + } else if (res.get() instanceof SiteCorrections) { + try { + Mono request = paramsClient.setSiteSpecificFrequencyBandParameter(new ArrayList<>(((SiteCorrections) res.get()).getSiteCorrections())); + if (request != null) { + request.retry(3).subscribe(); + } else { + log.error("Returned a null request from the parameter client while posting SiteFrequencyBandParameters {}", + (res.get())); + } + } catch (JsonProcessingException ex) { + log.trace(ex.getMessage(), ex); + } + } else if (res.get() instanceof MdacParametersPS) { + MdacParametersPS entry = (MdacParametersPS) res.get(); + try { + Mono request = paramsClient.setPsParameter(entry); + if (request != null) { + request.retry(3).subscribe(); + } else { + log.error("Returned a null request from the parameter client while posting MdacParametersPS {}", entry); + } + } catch (JsonProcessingException ex) { + log.trace(ex.getMessage(), ex); + } + } else if (res.get() instanceof MdacParametersFI) { + MdacParametersFI entry = (MdacParametersFI) res.get(); + try { + Mono request = paramsClient.setFiParameter(entry); + if (request != null) { + request.retry(3).subscribe(); + } else { + log.error("Returned a null request from the parameter client while posting MdacParametersFI {}", entry); + } + } catch (JsonProcessingException ex) { + log.trace(ex.getMessage(), ex); + } + } else if (res.get() instanceof ValidationMwParameters) { + ValidationMwParameters entry = (ValidationMwParameters) res.get(); + try { + Mono request = eventClient.postValidationEvents(Collections.singletonList(entry)); + if (request != null) { + request.retry(3).subscribe(); + } else { + log.error("Returned a null request from the parameter client while posting ReferenceMwParameters {}", entry); + } + } catch (JsonProcessingException ex) { + log.trace(ex.getMessage(), ex); + } + } else if (res.get() instanceof ReferenceMwParameters) { + ReferenceMwParameters entry = (ReferenceMwParameters) res.get(); + try { + Mono request = eventClient.postReferenceEvents(Collections.singletonList(entry)); + if (request != null) { + request.retry(3).subscribe(); + } else { + log.error("Returned a null request from the parameter client while posting ReferenceMwParameters {}", entry); + } + } catch (JsonProcessingException ex) { + log.trace(ex.getMessage(), ex); + } + } else if (res.get() instanceof VelocityConfiguration) { + VelocityConfiguration entry = (VelocityConfiguration) res.get(); + Mono request = paramsClient.updateVelocityConfiguration(entry); + if (request != null) { + request.retry(3).subscribe(); + } else { + log.error("Returned a null request from the parameter client while posting VelocityConfiguration {}", entry); + } + } else if (res.get() instanceof ShapeFitterConstraints) { + ShapeFitterConstraints entry = (ShapeFitterConstraints) res.get(); + Mono request = paramsClient.updateShapeFitterConstraints(entry); + if (request != null) { + request.retry(3).subscribe(); + } else { + log.error("Returned a null request from the parameter client while posting ShapeFitterConstraints {}", entry); + } + } + } + } + })); } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/DataController.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/DataController.java index 1fea323d..21cfd01b 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/DataController.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/DataController.java @@ -101,6 +101,9 @@ public class DataController implements MapListeningController, RefreshableContro @FXML private TableColumn highFreqCol; + + @FXML + private TableColumn depthCol; private ObservableList listData = FXCollections.synchronizedObservableList(FXCollections.observableArrayList()); @@ -213,6 +216,15 @@ public void initialize() { CellBindingUtils.attachTextCellFactories(lowFreqCol, Waveform::getLowFrequency, dfmt2); CellBindingUtils.attachTextCellFactories(highFreqCol, Waveform::getHighFrequency, dfmt2); + + depthCol.setCellValueFactory( + x -> Bindings.createStringBinding( + () -> + dfmt2.format( + Optional.ofNullable(x).map(CellDataFeatures::getValue) + .map(Waveform::getEvent) + .map(ev->Double.toString(ev.getDepth())).orElseGet(String::new)))); + depthCol.comparatorProperty().set(new MaybeNumericStringComparator()); usedCol.setCellValueFactory(x -> Bindings.createObjectBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(waveform -> { CheckBox box = new CheckBox(); diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/MeasuredMwsController.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/MeasuredMwsController.java index 5acc1f6c..ceb4dd9e 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/MeasuredMwsController.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/MeasuredMwsController.java @@ -14,42 +14,26 @@ */ package gov.llnl.gnem.apps.coda.calibration.gui.controllers; -import java.awt.Color; -import java.awt.event.MouseEvent; -import java.awt.geom.Point2D; import java.io.File; -import java.io.FileNotFoundException; -import java.io.UnsupportedEncodingException; +import java.lang.reflect.InvocationTargetException; import java.nio.file.Paths; -import java.text.NumberFormat; import java.time.Duration; -import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; -import java.util.DoubleSummaryStatistics; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Observable; -import java.util.Observer; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Function; import java.util.stream.Collectors; import javax.swing.SwingUtilities; -import org.apache.batik.svggen.SVGGraphics2DIOException; import org.apache.commons.io.FilenameUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -57,10 +41,10 @@ import org.springframework.stereotype.Component; import com.google.common.eventbus.EventBus; -import com.google.common.eventbus.Subscribe; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.CalibrationClient; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ParameterClient; +import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.EventClient; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.SpectraClient; import gov.llnl.gnem.apps.coda.calibration.gui.data.exporters.ParamExporter; import gov.llnl.gnem.apps.coda.calibration.gui.plotting.MapPlottingUtilities; @@ -72,180 +56,34 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.SpectraMeasurement; import gov.llnl.gnem.apps.coda.common.gui.controllers.ProgressGui; import gov.llnl.gnem.apps.coda.common.gui.data.client.api.WaveformClient; -import gov.llnl.gnem.apps.coda.common.gui.events.WaveformSelectionEvent; -import gov.llnl.gnem.apps.coda.common.gui.plotting.LabeledPlotPoint; -import gov.llnl.gnem.apps.coda.common.gui.plotting.PlotPoint; import gov.llnl.gnem.apps.coda.common.gui.plotting.SymbolStyleMapFactory; -import gov.llnl.gnem.apps.coda.common.gui.util.CellBindingUtils; -import gov.llnl.gnem.apps.coda.common.gui.util.MaybeNumericStringComparator; -import gov.llnl.gnem.apps.coda.common.gui.util.NumberFormatFactory; import gov.llnl.gnem.apps.coda.common.gui.util.ProgressListener; import gov.llnl.gnem.apps.coda.common.gui.util.ProgressMonitor; -import gov.llnl.gnem.apps.coda.common.gui.util.SnapshotUtils; import gov.llnl.gnem.apps.coda.common.mapping.api.GeoMap; -import gov.llnl.gnem.apps.coda.common.model.domain.Event; -import gov.llnl.gnem.apps.coda.common.model.domain.Pair; import gov.llnl.gnem.apps.coda.common.model.domain.Waveform; -import gov.llnl.gnem.apps.coda.common.model.messaging.WaveformChangeEvent; import javafx.application.Platform; -import javafx.beans.binding.Bindings; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.embed.swing.SwingFXUtils; import javafx.embed.swing.SwingNode; -import javafx.event.EventHandler; import javafx.fxml.FXML; -import javafx.geometry.Insets; -import javafx.scene.control.Button; -import javafx.scene.control.ComboBox; -import javafx.scene.control.ContextMenu; -import javafx.scene.control.Label; -import javafx.scene.control.MenuItem; -import javafx.scene.control.Tab; -import javafx.scene.control.TableColumn; -import javafx.scene.control.TableColumn.CellDataFeatures; -import javafx.scene.control.TableView; -import javafx.scene.control.TextField; -import javafx.scene.image.ImageView; -import javafx.scene.input.MouseButton; import javafx.scene.layout.StackPane; import javafx.stage.Modality; -import llnl.gnem.core.gui.plotting.PlotObjectClicked; -import llnl.gnem.core.gui.plotting.plotobject.PlotObject; import llnl.gnem.core.gui.plotting.plotobject.Symbol; -import llnl.gnem.core.gui.plotting.plotobject.SymbolFactory; +import reactor.core.scheduler.Schedulers; -//TODO: This is effectively a subset of SiteController. Revisit and see if we can factor out common functions into a third shared class at some point. @Component -public class MeasuredMwsController implements MapListeningController, RefreshableController, ScreenshotEnabledController { +public class MeasuredMwsController extends AbstractMeasurementController { private static final Logger log = LoggerFactory.getLogger(MeasuredMwsController.class); private static final String X_AXIS_LABEL = "center freq"; - @FXML - private Tab plotsTab; - - @FXML - private StackPane measuredMws; - - @FXML - private SwingNode fitPlotSwingNode; - private SpectralPlot fitPlot; - - @FXML - private ComboBox evidCombo; - - @FXML - private TableView eventTable; - - @FXML - private TableView iconTable; - - @FXML - private TableColumn evidCol; - - @FXML - private TableColumn measuredMwCol; - - // @FXML - // private TableColumn measuredMwSdCol; - - @FXML - private TableColumn measuredStressCol; - - @FXML - private TableColumn measuredCornerFreqCol; - - @FXML - private TableColumn mistfitCol; - - // @FXML - // private TableColumn measuredCornerFreqSdCol; - - @FXML - private TableColumn measuredMwUq1LowCol; - - @FXML - private TableColumn measuredMwUq1HighCol; - - @FXML - private TableColumn measuredMwUq2LowCol; - - @FXML - private TableColumn measuredMwUq2HighCol; - - @FXML - private TableColumn iterationsCol; - - @FXML - private TableColumn dataCountCol; - - @FXML - private TableColumn iconCol; - - @FXML - private TableColumn stationCol; - - @FXML - private TextField eventTime; - - @FXML - private TextField eventLoc; + private static final String displayName = "Measured_Mws"; - private SpectraClient spectraClient; - private ParameterClient paramClient; private CalibrationClient calibrationClient; private ParamExporter paramExporter; - private WaveformClient waveformClient; - private GeoMap mapImpl; - private EventBus bus; - private MapPlottingUtilities iconFactory; - private List spectralMeasurements = new ArrayList<>(); private Map> fitSpectra = new HashMap<>(); - private ObservableList evids = FXCollections.observableArrayList(); - private ObservableList mwParameters = FXCollections.observableArrayList(); - private ObservableList stationSymbols = FXCollections.observableArrayList(); - - private final BiConsumer eventSelectionCallback; - private final BiConsumer stationSelectionCallback; - - protected Map fitSymbolMap = new ConcurrentHashMap<>(); - - private Map> plotPointMap = new HashMap<>(); - private final List selectedPoints = new ArrayList<>(); - - private SymbolStyleMapFactory symbolStyleMapFactory; - - private Map symbolStyleMap; - - private MenuItem exclude; - private MenuItem include; - private ContextMenu menu; - - private final NumberFormat dfmt4 = NumberFormatFactory.fourDecimalOneLeadingZero(); - private ProgressGui progressGui; - private final AtomicReference minFreq = new AtomicReference<>(1.0); - private final AtomicReference maxFreq = new AtomicReference<>(-0.0); - - private final AtomicReference minY = new AtomicReference<>(1.0); - private final AtomicReference maxY = new AtomicReference<>(-0.0); - - @FXML - private Button xAxisShrink; - private boolean shouldXAxisShrink = false; - private Label xAxisShrinkOn; - private Label xAxisShrinkOff; - - @FXML - private Button yAxisShrink; - private boolean shouldYAxisShrink = false; - private Label yAxisShrinkOn; - private Label yAxisShrinkOff; - private ThreadPoolExecutor exec = new ThreadPoolExecutor(1, 1, 0, TimeUnit.SECONDS, new SynchronousQueue<>(), r -> { Thread thread = new Thread(r); thread.setName("MeasureMwController"); @@ -253,34 +91,30 @@ public class MeasuredMwsController implements MapListeningController, Refreshabl return thread; }, new ThreadPoolExecutor.DiscardPolicy()); - private boolean isVisible = false; + @FXML + private StackPane measuredMws; + + @FXML + private SwingNode spectraPlotSwingNode; + + private List mwDetails = new ArrayList<>(); + + private MeasuredMwReportByEvent mfs = new MeasuredMwReportByEvent(); @Autowired private MeasuredMwsController(SpectraClient spectraClient, ParameterClient paramClient, WaveformClient waveformClient, SymbolStyleMapFactory styleFactory, GeoMap map, - MapPlottingUtilities iconFactory, EventBus bus, ParamExporter paramExporter, CalibrationClient calibrationClient) { - this.spectraClient = spectraClient; - this.paramClient = paramClient; - this.waveformClient = waveformClient; - this.symbolStyleMapFactory = styleFactory; - this.mapImpl = map; - this.bus = bus; - this.iconFactory = iconFactory; + MapPlottingUtilities iconFactory, EventBus bus, ParamExporter paramExporter, CalibrationClient calibrationClient, EventClient referenceEventClient) { + super(spectraClient, paramClient, referenceEventClient, waveformClient, styleFactory, map, iconFactory, bus); this.calibrationClient = calibrationClient; this.paramExporter = paramExporter; - - eventSelectionCallback = (selected, eventId) -> { - selectDataByCriteria(selected, eventId); - }; - - stationSelectionCallback = (selected, stationId) -> { - selectDataByCriteria(selected, stationId); - }; - - this.bus.register(this); } + @Override @FXML public void initialize() { + spectraPlotPanel = measuredMws; + super.initialize(); + ProgressMonitor pm = new ProgressMonitor("Measuring Mws", new ProgressListener() { @Override public double getProgress() { @@ -293,333 +127,97 @@ public double getProgress() { progressGui.initModality(Modality.NONE); progressGui.setAlwaysOnTop(true); - evidCombo.setItems(evids); - - xAxisShrinkOn = new Label("><"); - xAxisShrinkOn.setStyle("-fx-font-weight:bold; -fx-font-size: 12px;"); - xAxisShrinkOn.setPadding(Insets.EMPTY); - xAxisShrinkOff = new Label("<>"); - xAxisShrinkOff.setStyle("-fx-font-weight:bold; -fx-font-size: 12px;"); - xAxisShrinkOff.setPadding(Insets.EMPTY); - xAxisShrink.setGraphic(xAxisShrinkOn); - double topPad = xAxisShrink.getPadding().getTop(); - double bottomPad = xAxisShrink.getPadding().getBottom(); - xAxisShrink.setPadding(new Insets(topPad, 0, bottomPad, 0)); - xAxisShrink.prefHeightProperty().bind(evidCombo.heightProperty()); - xAxisShrink.setOnAction(e -> { - shouldXAxisShrink = !shouldXAxisShrink; - if (shouldXAxisShrink) { - xAxisShrink.setGraphic(xAxisShrinkOff); - } else { - xAxisShrink.setGraphic(xAxisShrinkOn); - } - refreshView(); - }); - - yAxisShrinkOn = new Label("><"); - yAxisShrinkOn.setRotate(90.0); - yAxisShrinkOn.setStyle("-fx-font-weight:bold; -fx-font-size: 12px;"); - yAxisShrinkOn.setPadding(Insets.EMPTY); - yAxisShrinkOff = new Label("<>"); - yAxisShrinkOff.setRotate(90.0); - yAxisShrinkOff.setStyle("-fx-font-weight:bold; -fx-font-size: 12px;"); - yAxisShrinkOff.setPadding(Insets.EMPTY); - yAxisShrink.setGraphic(yAxisShrinkOn); - yAxisShrink.setPadding(new Insets(yAxisShrink.getPadding().getTop(), 0, yAxisShrink.getPadding().getBottom(), 0)); - yAxisShrink.prefHeightProperty().bind(evidCombo.heightProperty()); - yAxisShrink.setOnAction(e -> { - shouldYAxisShrink = !shouldYAxisShrink; - if (shouldYAxisShrink) { - yAxisShrink.setGraphic(yAxisShrinkOff); - } else { - yAxisShrink.setGraphic(yAxisShrinkOn); - } - refreshView(); - }); - SwingUtilities.invokeLater(() -> { - fitPlot = new SpectralPlot(); - fitPlot.addPlotObjectObserver(new Observer() { - @Override - public void update(Observable observable, Object obj) { - handlePlotObjectClicked(obj, sym -> fitSymbolMap.get(getPoint2D(sym))); - } - }); - fitPlotSwingNode.setContent(fitPlot); - - fitPlot.setLabels("Moment Rate Spectra", X_AXIS_LABEL, "log10(dyne-cm)"); - fitPlot.setYaxisVisibility(true); + final SpectraPlotController spectra = new SpectraPlotController(SpectraMeasurement::getPathAndSiteCorrected); + SpectralPlot plot = spectra.getSpectralPlot(); + plot.addPlotObjectObserver(getPlotpointObserver(() -> spectra.getSymbolMap())); + plot.setLabels("Moment Rate Spectra", X_AXIS_LABEL, "log10(dyne-cm)"); + plot.setYaxisVisibility(true); + spectra.setYAxisResizable(true); + spectraPlotSwingNode.setContent(plot); + + spectraPlotSwingNode.addEventHandler(javafx.scene.input.MouseEvent.MOUSE_CLICKED, menuHideHandler); + spectraControllers.add(spectra); }); - - evidCombo.valueProperty().addListener((observable, oldValue, newValue) -> { - if (newValue != null && !newValue.equals(oldValue)) { - refreshView(); - } - }); - - CellBindingUtils.attachTextCellFactoriesString(evidCol, MeasuredMwDetails::getEventId); - evidCol.comparatorProperty().set(new MaybeNumericStringComparator()); - - CellBindingUtils.attachTextCellFactories(measuredMwCol, MeasuredMwDetails::getMw, dfmt4); - // CellBindingUtils.attachTextCellFactories(measuredMwSdCol, MeasuredMwDetails::getMwSd, dfmt4); - CellBindingUtils.attachTextCellFactories(measuredStressCol, MeasuredMwDetails::getApparentStressInMpa, dfmt4); - CellBindingUtils.attachTextCellFactories(measuredCornerFreqCol, MeasuredMwDetails::getCornerFreq, dfmt4); - CellBindingUtils.attachTextCellFactories(mistfitCol, MeasuredMwDetails::getMisfit, dfmt4); - // CellBindingUtils.attachTextCellFactories(measuredCornerFreqSdCol, MeasuredMwDetails::getCornerFreqSd, dfmt4); - CellBindingUtils.attachTextCellFactories(measuredMwUq1LowCol, MeasuredMwDetails::getMw1Min, dfmt4); - CellBindingUtils.attachTextCellFactories(measuredMwUq1HighCol, MeasuredMwDetails::getMw1Max, dfmt4); - CellBindingUtils.attachTextCellFactories(measuredMwUq2LowCol, MeasuredMwDetails::getMw2Min, dfmt4); - CellBindingUtils.attachTextCellFactories(measuredMwUq2HighCol, MeasuredMwDetails::getMw2Max, dfmt4); - - iterationsCol.setCellValueFactory( - x -> Bindings.createIntegerBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(MeasuredMwDetails::getIterations).orElseGet(() -> 0)).asObject()); - - dataCountCol.setCellValueFactory( - x -> Bindings.createIntegerBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(MeasuredMwDetails::getDataCount).orElseGet(() -> 0)).asObject()); - - iconCol.setCellValueFactory(x -> Bindings.createObjectBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(pp -> { - ImageView imView = new ImageView(SwingFXUtils.toFXImage( - SymbolFactory.createSymbol(pp.getStyle(), 0, 0, 2, pp.getColor(), pp.getColor(), pp.getColor(), "", true, false, 10.0).getBufferedImage(256), - null)); - imView.setFitHeight(12); - imView.setFitWidth(12); - return imView; - }).orElseGet(() -> new ImageView()))); - - stationCol.setCellValueFactory(x -> Bindings.createStringBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(LabeledPlotPoint::getLabel).orElseGet(String::new))); - - eventTable.setItems(mwParameters); - iconTable.setItems(stationSymbols); - - iconCol.prefWidthProperty().bind(iconTable.widthProperty().multiply(0.3)); - stationCol.prefWidthProperty().bind(iconTable.widthProperty().multiply(0.7)); - - menu = new ContextMenu(); - include = new MenuItem("Include Selected"); - menu.getItems().add(include); - exclude = new MenuItem("Exclude Selected"); - menu.getItems().add(exclude); - - EventHandler menuHideHandler = (evt) -> { - if (MouseButton.SECONDARY != evt.getButton()) { - menu.hide(); - } - }; - fitPlotSwingNode.addEventHandler(javafx.scene.input.MouseEvent.MOUSE_CLICKED, menuHideHandler); - - bus.register(this); - } - - protected Object getPoint2D(Symbol sym) { - return new Point2D.Double(sym.getXcenter(), sym.getYcenter()); } - private void showWaveformPopup(Waveform waveform) { - bus.post(new WaveformSelectionEvent(waveform.getId())); - } - - private void plotSpectra() { - clearSpectraPlots(); - fitSymbolMap.clear(); - plotPointMap.clear(); - List filteredMeasurements; - - fitPlot.setAutoCalculateXaxisRange(shouldXAxisShrink); - if (!shouldXAxisShrink) { - fitPlot.setAllXlimits(minFreq.get(), maxFreq.get()); - } - - if (evidCombo != null && evidCombo.getSelectionModel().getSelectedIndex() > 0) { - filteredMeasurements = filterToEvent(evidCombo.getSelectionModel().getSelectedItem(), spectralMeasurements); - Spectra referenceSpectra = spectraClient.getReferenceSpectra(evidCombo.getSelectionModel().getSelectedItem()).block(Duration.ofSeconds(2)); - List fittingSpectra = new ArrayList<>(fitSpectra.get(evidCombo.getSelectionModel().getSelectedItem())); - fittingSpectra.add(referenceSpectra); - fitPlot.plotXYdata(toPlotPoints(filteredMeasurements, SpectraMeasurement::getPathAndSiteCorrected), Boolean.TRUE, fittingSpectra); - if (filteredMeasurements != null && filteredMeasurements.size() > 0 && filteredMeasurements.get(0).getWaveform() != null) { - Event event = filteredMeasurements.get(0).getWaveform().getEvent(); - eventTime.setText("Date: " + DateTimeFormatter.ISO_INSTANT.format(event.getOriginTime().toInstant())); - eventLoc.setText("Lat: " + dfmt4.format(event.getLatitude()) + " Lon: " + dfmt4.format(event.getLongitude())); - eventTime.setVisible(true); - eventLoc.setVisible(true); - } - } else { - eventTime.setVisible(false); - eventLoc.setVisible(false); - filteredMeasurements = spectralMeasurements; - fitPlot.plotXYdata(toPlotPoints(filteredMeasurements, SpectraMeasurement::getPathAndSiteCorrected), Boolean.FALSE); - } - fitSymbolMap.putAll(mapSpectraToPoint(filteredMeasurements, SpectraMeasurement::getPathAndSiteCorrected)); - mapMeasurements(filteredMeasurements); - - minY.set(100.0); - maxY.set(0.0); - DoubleSummaryStatistics stats = filteredMeasurements.stream() - .filter(Objects::nonNull) - .map(spec -> spec.getPathAndSiteCorrected()) - .filter(v -> v != 0.0) - .collect(Collectors.summarizingDouble(Double::doubleValue)); - maxY.set(stats.getMax() + .1); - minY.set(stats.getMin() - .1); - - fitPlot.setAutoCalculateYaxisRange(shouldYAxisShrink); - if (shouldYAxisShrink) { - fitPlot.setAllYlimits(minY.get(), maxY.get()); - } else { - fitPlot.setAllYlimits(); - } - } - - private void mapMeasurements(List measurements) { - if (measurements != null) { - mapImpl.addIcons( - iconFactory.genIconsFromWaveforms( - eventSelectionCallback, - stationSelectionCallback, - measurements.stream().map(m -> m.getWaveform()).filter(Objects::nonNull).collect(Collectors.toList()))); - } - } - - private void clearSpectraPlots() { - fitPlot.clearPlot(); - } - - private List filterToEvent(String selectedItem, List spectralMeasurements) { - return spectralMeasurements.stream().filter(spec -> selectedItem.equalsIgnoreCase(spec.getWaveform().getEvent().getEventId())).collect(Collectors.toList()); + @Override + protected String getDisplayName() { + return displayName; } - private Map mapSpectraToPoint(List spectralMeasurements, Function func) { - return spectralMeasurements.stream() - .filter(spectra -> !func.apply(spectra).equals(0.0)) - .collect( - Collectors.toMap( - spectra -> new Point2D.Double(Math.log10(centerFreq(spectra.getWaveform().getLowFrequency(), spectra.getWaveform().getHighFrequency())), - func.apply(spectra)), - Function.identity(), - (a, b) -> b, - HashMap::new)); + @Override + protected List getFitSpectra() { + List spectra = new ArrayList<>(fitSpectra.get(evidCombo.getSelectionModel().getSelectedItem())); + return spectra; } - private List toPlotPoints(List spectralMeasurements, Function func) { - List list = spectralMeasurements.stream() - .filter(spectra -> !func.apply(spectra).equals(0.0)) - .filter( - spectra -> spectra != null - && spectra.getWaveform() != null - && spectra.getWaveform().getStream() != null - && spectra.getWaveform().getStream().getStation() != null) - .map(spectra -> { - String key = spectra.getWaveform().getStream().getStation().getStationName(); - PlotPoint pp = getPlotPoint(key, spectra.getWaveform().isActive()); - PlotPoint point = new LabeledPlotPoint(key, - new PlotPoint(Math.log10( - centerFreq(spectra.getWaveform().getLowFrequency(), spectra.getWaveform().getHighFrequency())), - func.apply(spectra), - pp.getStyle(), - pp.getColor())); - if (hasEventAndStation(spectra)) { - plotPointMap.computeIfAbsent(spectra.getWaveform().getEvent().getEventId(), k -> new ArrayList<>()).add(point); - plotPointMap.computeIfAbsent(spectra.getWaveform().getStream().getStation().getStationName(), k -> new ArrayList<>()).add(point); - } - return point; - }) - .collect(Collectors.toList()); - return list; + @Override + protected void setActive(List waveforms, List plotObjects, boolean active, BiConsumer, Boolean> activationFunc) { + waveformClient.setWaveformsActiveByIds(waveforms.stream().peek(w -> w.setActive(active)).map(w -> w.getId()).collect(Collectors.toList()), active) + .subscribe(s -> activationFunc.accept(plotObjects, active)); } - private PlotPoint getPlotPoint(String key, boolean active) { - PlotPoint pp = new PlotPoint(symbolStyleMap.get(key)); - if (!active) { - pp.setColor(Color.GRAY); + @Override + protected void preloadData() { + spectralMeasurements.clear(); + fitSpectra.clear(); + mwDetails.clear(); + mfs = calibrationClient.makeMwMeasurements(Boolean.TRUE) + .doOnError(err -> log.trace(err.getMessage(), err)) + .doFinally((s) -> Platform.runLater(() -> progressGui.hide())) + .block(Duration.of(1000l, ChronoUnit.SECONDS)); + fitSpectra.putAll(mfs.getFitSpectra()); + + List refEvs = referenceEventClient.getMeasuredEventDetails() + .filter(ev -> ev.getEventId() != null) + .collect(Collectors.toList()) + .subscribeOn(Schedulers.elastic()) + .block(Duration.ofSeconds(10l)); + Collection measMws = mfs.getMeasuredMwDetails().values(); + + //Not terribly efficient but this list should never be huge so eh... + for (MeasuredMwDetails ref : refEvs) { + for (MeasuredMwDetails meas : measMws) { + if (meas.getEventId().equals(ref.getEventId())) { + meas.setRefMw(ref.getRefMw()); + meas.setRefApparentStressInMpa(ref.getRefApparentStressInMpa()); + meas.setValMw(ref.getValMw()); + meas.setValApparentStressInMpa(ref.getValApparentStressInMpa()); + break; + } + } } - return pp; - } - - private boolean hasEventAndStation(SpectraMeasurement spectra) { - return spectra != null - && spectra.getWaveform() != null - && spectra.getWaveform().getEvent() != null - && spectra.getWaveform().getEvent().getEventId() != null - && spectra.getWaveform().getStream() != null - && spectra.getWaveform().getStream().getStation() != null - && spectra.getWaveform().getStream().getStation().getStationName() != null; - } - private double centerFreq(Double lowFrequency, Double highFrequency) { - return lowFrequency + (highFrequency - lowFrequency) / 2.; + mwDetails.addAll(measMws); } - private void reloadData() { + @Override + protected void reloadData() { try { progressGui.show(); progressGui.toFront(); - - Platform.runLater(() -> { - evids.clear(); - evids.add("All"); - }); - - exec.submit(() -> { - maxFreq.set(-0.0); - minFreq.set(1.0); - - DoubleSummaryStatistics stats = paramClient.getSharedFrequencyBandParameters() - .filter(Objects::nonNull) - .collectList() - .block(Duration.of(10l, ChronoUnit.SECONDS)) - .stream() - .map(sfb -> Math.log10(centerFreq(sfb.getLowFrequency(), sfb.getHighFrequency()))) - .collect(Collectors.summarizingDouble(Double::doubleValue)); - maxFreq.set(stats.getMax()); - minFreq.set(stats.getMin()); - - MeasuredMwReportByEvent mfs = calibrationClient.makeMwMeasurements(Boolean.TRUE) - .doOnError(err -> log.trace(err.getMessage(), err)) - .doFinally((s) -> Platform.runLater(() -> progressGui.hide())) - .block(Duration.of(1000l, ChronoUnit.SECONDS)); - - fitSpectra.putAll(mfs.getFitSpectra()); - spectralMeasurements.addAll( - mfs.getSpectraMeasurements() - .values() - .stream() - .flatMap(x -> x.stream()) - .filter(Objects::nonNull) - .filter(spectra -> spectra.getWaveform() != null && spectra.getWaveform().getEvent() != null && spectra.getWaveform().getStream() != null) - .map(md -> new SpectraMeasurement(md)) - .collect(Collectors.toList())); - - symbolStyleMap = symbolStyleMapFactory.build(spectralMeasurements, new Function() { - @Override - public String apply(SpectraMeasurement t) { - return t.getWaveform().getStream().getStation().getStationName(); - } - }); - - List symbols = symbolStyleMap.entrySet().stream().map(e -> new LabeledPlotPoint(e.getKey(), e.getValue())).collect(Collectors.toList()); - List uniqueEvids = mfs.getSpectraMeasurements().keySet().stream().distinct().sorted(new MaybeNumericStringComparator()).collect(Collectors.toList()); - Collection mwDetails = mfs.getMeasuredMwDetails().values(); - - Platform.runLater(() -> { - mwParameters.clear(); - stationSymbols.clear(); - stationSymbols.addAll(symbols); - evids.addAll(uniqueEvids); - mwParameters.addAll(mwDetails); - eventTable.sort(); - }); - }); - - clearSpectraPlots(); - spectralMeasurements.clear(); - fitSpectra.clear(); + exec.submit(() -> super.reloadData()); } catch (RejectedExecutionException e) { progressGui.hide(); } } + @Override + protected List getSpectraData() { + return mfs.getSpectraMeasurements() + .values() + .stream() + .flatMap(x -> x.stream()) + .filter(Objects::nonNull) + .filter(spectra -> spectra.getWaveform() != null && spectra.getWaveform().getEvent() != null && spectra.getWaveform().getStream() != null) + .map(md -> new SpectraMeasurement(md)) + .collect(Collectors.toList()); + } + public void exportMws() { Platform.runLater(() -> { - File file = FileDialogs.openFileSaveDialog("Measured_Mws", ".json", measuredMws.getScene().getWindow()); + File file = FileDialogs.openFileSaveDialog(getDisplayName(), ".json", spectraPlotPanel.getScene().getWindow()); if (file != null && FileDialogs.ensureFileIsWritable(file)) { String filePath = file.getAbsolutePath(); paramExporter.writeMeasuredMws(Paths.get(FilenameUtils.getFullPath(filePath)), FilenameUtils.getName(filePath), mwParameters); @@ -628,168 +226,12 @@ public void exportMws() { } @Override - public void refreshView() { - if (isVisible) { - mapImpl.clearIcons(); - plotSpectra(); - Platform.runLater(() -> { - fitPlot.repaint(); - }); - } - } - - @Override - public Runnable getRefreshFunction() { - return () -> reloadData(); - } - - @Override - public Consumer getScreenshotFunction() { - return (folder) -> { - String timestamp = SnapshotUtils.getTimestampWithLeadingSeparator(); - SnapshotUtils.writePng(folder, new Pair<>("Measured_Mws", plotsTab.getContent()), timestamp); - try { - if (evidCombo.getValue() != null) { - fitPlot.exportSVG(folder + File.separator + "Measured_Mws_" + evidCombo.getValue() + timestamp + ".svg"); - } - } catch (UnsupportedEncodingException | FileNotFoundException | SVGGraphics2DIOException e) { - log.error("Error attempting to write plots for path controller : {}", e.getLocalizedMessage(), e); - } - }; - } - - private void selectDataByCriteria(Boolean selected, String key) { - List points = plotPointMap.get(key); - if (selected) { - selectPoints(points); - } else { - deselectPoints(points); - } - } - - private void selectPoints(List points) { - if (points != null && !points.isEmpty()) { - if (!selectedPoints.isEmpty()) { - deselectPoints(selectedPoints); - } - selectedPoints.addAll(points); - SwingUtilities.invokeLater(() -> { - points.forEach(point -> { - selectPoint(point); - }); - }); - } - } - - private void deselectPoints(List selected) { - if (selected != null && !selected.isEmpty()) { - List points = new ArrayList<>(selected.size()); - points.addAll(selected); - selectedPoints.clear(); - SwingUtilities.invokeLater(() -> { - points.forEach(point -> { - deselectPoint(point); - }); - }); - } - } - - private void selectPoint(PlotPoint point) { - Point2D.Double xyPoint = new Point2D.Double(point.getX(), point.getY()); - boolean existsInPlot = fitSymbolMap.containsKey(xyPoint); - if (existsInPlot) { - fitPlot.selectPoint(xyPoint); - } - } - - private void deselectPoint(PlotPoint point) { - Point2D.Double xyPoint = new Point2D.Double(point.getX(), point.getY()); - boolean existsInPlot = fitSymbolMap.containsKey(xyPoint); - if (existsInPlot) { - fitPlot.deselectPoint(xyPoint); - } - } - - protected void setSymbolsActive(List objs, Boolean active) { - SwingUtilities.invokeLater(() -> { - objs.forEach(sym -> { - if (active) { - sym.setFillColor(sym.getEdgeColor()); - sym.setEdgeColor(Color.BLACK); - } else { - sym.setEdgeColor(sym.getFillColor()); - sym.setFillColor(Color.GRAY); - } - }); - Platform.runLater(() -> { - fitPlot.repaint(); - }); - }); - } - - private void showContextMenu(List waveforms, List plotObjects, MouseEvent t, BiConsumer, Boolean> activationFunc) { - Platform.runLater(() -> { - include.setOnAction(evt -> setActive(waveforms, plotObjects, true, activationFunc)); - exclude.setOnAction(evt -> setActive(waveforms, plotObjects, false, activationFunc)); - menu.show(fitPlotSwingNode, t.getXOnScreen(), t.getYOnScreen()); - }); - } - - private void setActive(List waveforms, List plotObjects, boolean active, BiConsumer, Boolean> activationFunc) { - waveformClient.setWaveformsActiveByIds(waveforms.stream().peek(w -> w.setActive(active)).map(w -> w.getId()).collect(Collectors.toList()), active) - .subscribe(s -> activationFunc.accept(plotObjects, active)); - } - - @Subscribe - private void listener(WaveformChangeEvent wce) { - List nonNull = wce.getIds().stream().filter(Objects::nonNull).collect(Collectors.toList()); - synchronized (spectralMeasurements) { - Map activeMeasurements = spectralMeasurements.stream().collect(Collectors.toMap(x -> x.getWaveform().getId(), Function.identity())); - if (wce.isAddOrUpdate()) { - waveformClient.getWaveformMetadataFromIds(nonNull).collect(Collectors.toList()).block(Duration.ofSeconds(10l)).forEach(md -> { - SpectraMeasurement measurement = activeMeasurements.get(md.getId()); - if (measurement != null) { - measurement.getWaveform().setActive(md.isActive()); - } - }); - } else if (wce.isDelete()) { - nonNull.forEach(id -> { - SpectraMeasurement measurement = activeMeasurements.remove(id); - if (measurement != null) { - spectralMeasurements.remove(measurement); - } - }); - } - } - refreshView(); - } - - private void handlePlotObjectClicked(Object obj, Function measurementFunc) { - if (obj instanceof PlotObjectClicked && ((PlotObjectClicked) obj).getMouseEvent().getID() == MouseEvent.MOUSE_RELEASED) { - PlotObjectClicked poc = (PlotObjectClicked) obj; - PlotObject po = poc.getPlotObject(); - if (po instanceof Symbol) { - SpectraMeasurement spectra = measurementFunc.apply((Symbol) po); - String symbolId = ((Symbol) po).getText(); - if (spectra != null && spectra.getWaveform() != null) { - if (SwingUtilities.isLeftMouseButton(poc.getMouseEvent()) && symbolId != null) { - selectPoints(plotPointMap.get(symbolId)); - if (spectra != null) { - showWaveformPopup(spectra.getWaveform()); - } - Platform.runLater(() -> menu.hide()); - } else if (SwingUtilities.isRightMouseButton(poc.getMouseEvent())) { - showContextMenu(Collections.singletonList(spectra.getWaveform()), Collections.singletonList((Symbol) po), poc.getMouseEvent(), (objs, active) -> { - setSymbolsActive(objs, active); - }); - } - } - } - } + protected void runGuiUpdate(Runnable runnable) throws InvocationTargetException, InterruptedException { + Platform.runLater(runnable); } @Override - public void setVisible(boolean visible) { - isVisible = visible; + protected List getEvents() { + return mwDetails; } } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/PathController.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/PathController.java index 297ef9cb..19dd84c6 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/PathController.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/PathController.java @@ -301,7 +301,7 @@ public void update(Observable observable, Object obj) { } } }); - sdPlot.getXaxis().setLabelText("Distance (km)"); + sdPlot.getXaxis().setLabelText("Inter-Station Distance (km)"); sdPlot.setYaxisVisibility(true); sdPlot.setShowPickTooltips(true); diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/ReferenceEventLoadingController.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/ReferenceEventLoadingController.java index 6f6d74f9..99a7a862 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/ReferenceEventLoadingController.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/ReferenceEventLoadingController.java @@ -30,7 +30,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import gov.llnl.gnem.apps.coda.calibration.gui.converters.api.FileToReferenceEventConverter; -import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ReferenceEventClient; +import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.EventClient; import gov.llnl.gnem.apps.coda.common.model.messaging.Result; //TODO: This class needs a GUI to display a list of files it's attempting to load and process + pass/fail indicators @@ -39,14 +39,14 @@ public class ReferenceEventLoadingController { private static final Logger log = LoggerFactory.getLogger(ReferenceEventLoadingController.class); - private ReferenceEventClient client; + private EventClient client; private int maxBatching = 1000; private List fileConverters; @Autowired - public ReferenceEventLoadingController(List fileConverters, ReferenceEventClient client) throws IOException { + public ReferenceEventLoadingController(List fileConverters, EventClient client) throws IOException { super(); this.fileConverters = fileConverters; this.client = client; diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/SiteController.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/SiteController.java index ce9caa09..b60d597b 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/SiteController.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/SiteController.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2019, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* Copyright (c) 2020, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory * CODE-743439. * All rights reserved. * This file is part of CCT. For details, see https://github.com/LLNL/coda-calibration-tool. @@ -14,49 +14,25 @@ */ package gov.llnl.gnem.apps.coda.calibration.gui.controllers; -import java.awt.Color; -import java.awt.event.MouseEvent; -import java.awt.geom.Point2D; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.UnsupportedEncodingException; import java.lang.reflect.InvocationTargetException; -import java.text.NumberFormat; import java.time.Duration; -import java.time.format.DateTimeFormatter; -import java.time.temporal.ChronoUnit; import java.util.ArrayList; -import java.util.Collections; -import java.util.DoubleSummaryStatistics; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; import java.util.Objects; -import java.util.Observable; -import java.util.Observer; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Function; import java.util.stream.Collectors; import javax.swing.SwingUtilities; -import org.apache.batik.svggen.SVGGraphics2DIOException; -import org.apache.commons.math3.stat.descriptive.SummaryStatistics; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.google.common.eventbus.EventBus; -import com.google.common.eventbus.Subscribe; +import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.EventClient; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ParameterClient; -import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ReferenceEventClient; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.SpectraClient; import gov.llnl.gnem.apps.coda.calibration.gui.plotting.MapPlottingUtilities; import gov.llnl.gnem.apps.coda.calibration.gui.plotting.SpectralPlot; @@ -64,1030 +40,122 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.Spectra; import gov.llnl.gnem.apps.coda.calibration.model.domain.SpectraMeasurement; import gov.llnl.gnem.apps.coda.common.gui.data.client.api.WaveformClient; -import gov.llnl.gnem.apps.coda.common.gui.events.WaveformSelectionEvent; -import gov.llnl.gnem.apps.coda.common.gui.plotting.LabeledPlotPoint; -import gov.llnl.gnem.apps.coda.common.gui.plotting.PlotPoint; import gov.llnl.gnem.apps.coda.common.gui.plotting.SymbolStyleMapFactory; -import gov.llnl.gnem.apps.coda.common.gui.util.CellBindingUtils; -import gov.llnl.gnem.apps.coda.common.gui.util.MaybeNumericStringComparator; -import gov.llnl.gnem.apps.coda.common.gui.util.NumberFormatFactory; -import gov.llnl.gnem.apps.coda.common.gui.util.SnapshotUtils; import gov.llnl.gnem.apps.coda.common.mapping.api.GeoMap; -import gov.llnl.gnem.apps.coda.common.model.domain.Event; -import gov.llnl.gnem.apps.coda.common.model.domain.Pair; import gov.llnl.gnem.apps.coda.common.model.domain.Waveform; -import gov.llnl.gnem.apps.coda.common.model.messaging.WaveformChangeEvent; -import javafx.application.Platform; -import javafx.beans.binding.Bindings; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.embed.swing.SwingFXUtils; import javafx.embed.swing.SwingNode; -import javafx.event.EventHandler; import javafx.fxml.FXML; -import javafx.geometry.Insets; -import javafx.scene.control.Button; -import javafx.scene.control.ComboBox; -import javafx.scene.control.ContextMenu; -import javafx.scene.control.Label; -import javafx.scene.control.MenuItem; -import javafx.scene.control.Tab; -import javafx.scene.control.TableColumn; -import javafx.scene.control.TableColumn.CellDataFeatures; -import javafx.scene.control.TableView; -import javafx.scene.control.TextField; -import javafx.scene.image.ImageView; -import javafx.scene.input.MouseButton; -import llnl.gnem.core.gui.plotting.HorizPinEdge; -import llnl.gnem.core.gui.plotting.PaintMode; -import llnl.gnem.core.gui.plotting.PenStyle; -import llnl.gnem.core.gui.plotting.PlotObjectClicked; -import llnl.gnem.core.gui.plotting.SymbolLegend; -import llnl.gnem.core.gui.plotting.SymbolLegend.SymbolTextPair; -import llnl.gnem.core.gui.plotting.VertPinEdge; -import llnl.gnem.core.gui.plotting.color.ColorMap; -import llnl.gnem.core.gui.plotting.color.ViridisColorMap; -import llnl.gnem.core.gui.plotting.jmultiaxisplot.JMultiAxisPlot; -import llnl.gnem.core.gui.plotting.jmultiaxisplot.JSubplot; -import llnl.gnem.core.gui.plotting.plotobject.Circle; -import llnl.gnem.core.gui.plotting.plotobject.Line; -import llnl.gnem.core.gui.plotting.plotobject.PlotObject; +import javafx.scene.layout.StackPane; import llnl.gnem.core.gui.plotting.plotobject.Symbol; -import llnl.gnem.core.gui.plotting.plotobject.SymbolDef; -import llnl.gnem.core.gui.plotting.plotobject.SymbolFactory; -import llnl.gnem.core.gui.plotting.plotobject.SymbolStyle; import reactor.core.scheduler.Schedulers; @Component -public class SiteController implements MapListeningController, RefreshableController, ScreenshotEnabledController { +public class SiteController extends AbstractMeasurementController { private static final Logger log = LoggerFactory.getLogger(SiteController.class); private static final String X_AXIS_LABEL = "center freq"; - private static final int MAX_LEGEND_COLORS = 8; - - @FXML - private Tab resultsTab; - - @FXML - private SwingNode mwPlotSwingNode; - private JMultiAxisPlot mwPlot; - private JSubplot mwPlotFigure; - private Line mwZeroLine; - - @FXML - private SwingNode stressPlotSwingNode; - private JMultiAxisPlot stressPlot; - private JSubplot stressPlotFigure; - private Line stressZeroLine; - + private static final String displayName = "Site"; + @FXML - private SwingNode sdPlotSwingNode; - private JMultiAxisPlot sdPlot; - private JSubplot sdPlotFigure; + private StackPane site; @FXML private SwingNode rawPlotSwingNode; - private SpectralPlot rawPlot; @FXML private SwingNode pathPlotSwingNode; - private SpectralPlot pathPlot; @FXML private SwingNode sitePlotSwingNode; - private SpectralPlot sitePlot; - - @FXML - private ComboBox evidCombo; - - @FXML - private TableView eventTable; - - @FXML - private TableView iconTable; - - @FXML - private TableColumn evidCol; - - @FXML - private TableColumn mwCol; - - @FXML - private TableColumn stressCol; - - @FXML - private TableColumn measuredMwCol; - - @FXML - private TableColumn mistfitCol; - - // @FXML - // private TableColumn measuredMwSdCol; - - @FXML - private TableColumn measuredStressCol; - - @FXML - private TableColumn measuredCornerFreqCol; - - // @FXML - // private TableColumn measuredCornerFreqSdCol; - - @FXML - private TableColumn measuredMwUq1LowCol; - - @FXML - private TableColumn measuredMwUq1HighCol; - - @FXML - private TableColumn measuredMwUq2LowCol; - - @FXML - private TableColumn measuredMwUq2HighCol; - - @FXML - private TableColumn iterationsCol; - - @FXML - private TableColumn dataCountCol; - - @FXML - private TableColumn iconCol; - - @FXML - private TableColumn stationCol; - - @FXML - private TextField eventTime; - - @FXML - private TextField eventLoc; - - private SpectraClient spectraClient; - private ParameterClient paramClient; - private List spectralMeasurements = new ArrayList<>(); - private ObservableList evids = FXCollections.observableArrayList(); - - private ReferenceEventClient referenceEventClient; - private ObservableList mwParameters = FXCollections.observableArrayList(); - - private WaveformClient waveformClient; - - private ObservableList stationSymbols = FXCollections.observableArrayList(); - private final BiConsumer eventSelectionCallback; - private final BiConsumer stationSelectionCallback; - - private EventBus bus; - - protected Map rawSymbolMap = new ConcurrentHashMap<>(); - protected Map pathSymbolMap = new ConcurrentHashMap<>(); - protected Map siteSymbolMap = new ConcurrentHashMap<>(); - - private Map> plotPointMap = new HashMap<>(); - private final List selectedPoints = new ArrayList<>(); - - private SymbolStyleMapFactory symbolStyleMapFactory; - - private Map symbolStyleMap; - - private GeoMap mapImpl; - - private MapPlottingUtilities iconFactory; - - private MenuItem exclude; - private MenuItem include; - private ContextMenu menu; - - private final NumberFormat dfmt4 = NumberFormatFactory.fourDecimalOneLeadingZero(); - - private ColorMap colorMap = new ViridisColorMap(); - private final AtomicReference minFreq = new AtomicReference<>(1.0); - private final AtomicReference maxFreq = new AtomicReference<>(-0.0); - - private final AtomicReference minY = new AtomicReference<>(1.0); - private final AtomicReference maxY = new AtomicReference<>(-0.0); - - @FXML - private Button xAxisShrink; - private boolean shouldXAxisShrink = false; - private Label xAxisShrinkOn; - private Label xAxisShrinkOff; - - @FXML - private Button yAxisShrink; - private boolean shouldYAxisShrink = false; - private Label yAxisShrinkOn; - private Label yAxisShrinkOff; - - private boolean isVisible = false; @Autowired - private SiteController(SpectraClient spectraClient, ParameterClient paramClient, ReferenceEventClient referenceEventClient, WaveformClient waveformClient, SymbolStyleMapFactory styleFactory, + private SiteController(SpectraClient spectraClient, ParameterClient paramClient, EventClient referenceEventClient, WaveformClient waveformClient, SymbolStyleMapFactory styleFactory, GeoMap map, MapPlottingUtilities iconFactory, EventBus bus) { - this.spectraClient = spectraClient; - this.paramClient = paramClient; - this.referenceEventClient = referenceEventClient; - this.waveformClient = waveformClient; - this.symbolStyleMapFactory = styleFactory; - this.mapImpl = map; - this.bus = bus; - this.iconFactory = iconFactory; - - eventSelectionCallback = (selected, eventId) -> { - selectDataByCriteria(selected, eventId); - }; - - stationSelectionCallback = (selected, stationId) -> { - selectDataByCriteria(selected, stationId); - }; - - this.bus.register(this); + super(spectraClient, paramClient, referenceEventClient, waveformClient, styleFactory, map, iconFactory, bus); } + @Override @FXML public void initialize() { - evidCombo.setItems(evids); - - xAxisShrinkOn = new Label("><"); - xAxisShrinkOn.setStyle("-fx-font-weight:bold; -fx-font-size: 12px;"); - xAxisShrinkOn.setPadding(Insets.EMPTY); - xAxisShrinkOff = new Label("<>"); - xAxisShrinkOff.setStyle("-fx-font-weight:bold; -fx-font-size: 12px;"); - xAxisShrinkOff.setPadding(Insets.EMPTY); - xAxisShrink.setGraphic(xAxisShrinkOn); - double topPad = xAxisShrink.getPadding().getTop(); - double bottomPad = xAxisShrink.getPadding().getBottom(); - xAxisShrink.setPadding(new Insets(topPad, 0, bottomPad, 0)); - xAxisShrink.prefHeightProperty().bind(evidCombo.heightProperty()); - xAxisShrink.setOnAction(e -> { - shouldXAxisShrink = !shouldXAxisShrink; - if (shouldXAxisShrink) { - xAxisShrink.setGraphic(xAxisShrinkOff); - } else { - xAxisShrink.setGraphic(xAxisShrinkOn); - } - refreshView(); - }); - - yAxisShrinkOn = new Label("><"); - yAxisShrinkOn.setRotate(90.0); - yAxisShrinkOn.setStyle("-fx-font-weight:bold; -fx-font-size: 12px;"); - yAxisShrinkOn.setPadding(Insets.EMPTY); - yAxisShrinkOff = new Label("<>"); - yAxisShrinkOff.setRotate(90.0); - yAxisShrinkOff.setStyle("-fx-font-weight:bold; -fx-font-size: 12px;"); - yAxisShrinkOff.setPadding(Insets.EMPTY); - yAxisShrink.setGraphic(yAxisShrinkOn); - yAxisShrink.setPadding(new Insets(yAxisShrink.getPadding().getTop(), 0, yAxisShrink.getPadding().getBottom(), 0)); - yAxisShrink.prefHeightProperty().bind(evidCombo.heightProperty()); - - yAxisShrink.setOnAction(e -> { - shouldYAxisShrink = !shouldYAxisShrink; - if (shouldYAxisShrink) { - yAxisShrink.setGraphic(yAxisShrinkOff); - } else { - yAxisShrink.setGraphic(yAxisShrinkOn); - } - refreshView(); - }); + spectraPlotPanel = site; + super.initialize(); SwingUtilities.invokeLater(() -> { - - rawPlot = new SpectralPlot(); - rawPlot.addPlotObjectObserver(new Observer() { - @Override - public void update(Observable observable, Object obj) { - handlePlotObjectClicked(obj, sym -> rawSymbolMap.get(getPoint2D(sym))); - } - }); - rawPlotSwingNode.setContent(rawPlot); - - pathPlot = new SpectralPlot(); - pathPlot.addPlotObjectObserver(new Observer() { - @Override - public void update(Observable observable, Object obj) { - handlePlotObjectClicked(obj, sym -> pathSymbolMap.get(getPoint2D(sym))); - } - }); - - pathPlotSwingNode.setContent(pathPlot); - - sitePlot = new SpectralPlot(); - sitePlot.addPlotObjectObserver(new Observer() { - @Override - public void update(Observable observable, Object obj) { - handlePlotObjectClicked(obj, sym -> siteSymbolMap.get(getPoint2D(sym))); - } - }); - sitePlotSwingNode.setContent(sitePlot); - - rawPlot.setLabels("Raw Plot", X_AXIS_LABEL, "log10(non-dim)"); - rawPlot.setYaxisVisibility(true); - rawPlot.setAllXlimits(0.0, 0.0); - rawPlot.setDefaultYMin(-2.0); - rawPlot.setDefaultYMax(7.0); - - pathPlot.setLabels("Path Corrected", X_AXIS_LABEL, "log10(non-dim)"); - pathPlot.setYaxisVisibility(true); - pathPlot.setAllXlimits(0.0, 0.0); - pathPlot.setDefaultYMin(-2.0); - pathPlot.setDefaultYMax(7.0); - - sitePlot.setLabels("Moment Rate Spectra", X_AXIS_LABEL, "log10(dyne-cm)"); - sitePlot.setYaxisVisibility(true); - - mwPlot = new JMultiAxisPlot(); - mwPlotFigure = mwPlot.addSubplot(); - - mwPlot.getTitle().setText("Mw comparison"); - mwPlot.getXaxis().setLabelText("Measured"); - mwPlot.setYaxisVisibility(true); - mwPlotSwingNode.setContent(mwPlot); - - mwPlotFigure.getYaxis().setLabelOffset(2.5d * mwPlot.getXaxis().getLabelOffset()); - mwPlotFigure.setAxisLimits(0.0, 10.0, 0.0, 10.0); - mwPlotFigure.getYaxis().setLabelText("Reference"); - - stressPlot = new JMultiAxisPlot(); - stressPlotFigure = stressPlot.addSubplot(); - - stressPlot.getTitle().setText("Stress comparison"); - stressPlot.getXaxis().setLabelText("Measured"); - stressPlot.setYaxisVisibility(true); - stressPlotSwingNode.setContent(stressPlot); - - stressPlotFigure.getYaxis().setLabelOffset(2.5d * stressPlot.getXaxis().getLabelOffset()); - stressPlotFigure.setAxisLimits(0.0, 10.0, 0.0, 10.0); - stressPlotFigure.getYaxis().setLabelText("Reference"); - - sdPlot = new JMultiAxisPlot(); - sdPlotFigure = sdPlot.addSubplot(); - - sdPlot.getTitle().setText("Site correction overview"); - sdPlot.getXaxis().setLabelText("Frequency"); - sdPlot.setYaxisVisibility(true); - sdPlotSwingNode.setContent(sdPlot); - - sdPlotFigure.getYaxis().setLabelOffset(2.5d * sdPlot.getXaxis().getLabelOffset()); - sdPlotFigure.setAxisLimits(0.0, 10.0, 0.0, 2.0); - sdPlotFigure.getYaxis().setLabelText("Standard Deviation"); - - int points = 50; - double dx = 20.0 / (points - 1); - float[] xy = new float[points]; - for (int i = 0; i < points; i++) { - xy[i] = (float) (-5.0 + (dx * i)); - } - mwZeroLine = new Line(xy, xy, Color.LIGHT_GRAY, PaintMode.COPY, PenStyle.DASH, 2); - stressZeroLine = new Line(xy, xy, Color.LIGHT_GRAY, PaintMode.COPY, PenStyle.DASH, 2); - mwPlotFigure.AddPlotObject(mwZeroLine); - stressPlotFigure.AddPlotObject(stressZeroLine); - }); - - evidCombo.valueProperty().addListener((observable, oldValue, newValue) -> { - if (newValue != null && !newValue.equals(oldValue)) { - refreshView(); - } + final SpectraPlotController raw = new SpectraPlotController(SpectraMeasurement::getRawAtMeasurementTime); + SpectralPlot plot = raw.getSpectralPlot(); + plot.addPlotObjectObserver(getPlotpointObserver(() -> raw.getSymbolMap())); + plot.setLabels("Raw Plot", X_AXIS_LABEL, "log10(non-dim)"); + plot.setYaxisVisibility(true); + plot.setAllXlimits(0.0, 0.0); + plot.setDefaultYMin(-2.0); + plot.setDefaultYMax(7.0); + rawPlotSwingNode.setContent(plot); + + final SpectraPlotController path = new SpectraPlotController(SpectraMeasurement::getPathCorrected); + plot = path.getSpectralPlot(); + plot.addPlotObjectObserver(getPlotpointObserver(() -> path.getSymbolMap())); + plot.setLabels("Path Corrected", X_AXIS_LABEL, "log10(non-dim)"); + plot.setYaxisVisibility(true); + plot.setAllXlimits(0.0, 0.0); + plot.setDefaultYMin(-2.0); + plot.setDefaultYMax(7.0); + pathPlotSwingNode.setContent(plot); + + final SpectraPlotController site = new SpectraPlotController(SpectraMeasurement::getPathAndSiteCorrected); + plot = site.getSpectralPlot(); + plot.addPlotObjectObserver(getPlotpointObserver(() -> site.getSymbolMap())); + plot.setLabels("Moment Rate Spectra", X_AXIS_LABEL, "log10(dyne-cm)"); + plot.setYaxisVisibility(true); + site.setYAxisResizable(true); + sitePlotSwingNode.setContent(plot); + + rawPlotSwingNode.addEventHandler(javafx.scene.input.MouseEvent.MOUSE_CLICKED, menuHideHandler); + pathPlotSwingNode.addEventHandler(javafx.scene.input.MouseEvent.MOUSE_CLICKED, menuHideHandler); + sitePlotSwingNode.addEventHandler(javafx.scene.input.MouseEvent.MOUSE_CLICKED, menuHideHandler); + + spectraControllers.add(raw); + spectraControllers.add(path); + spectraControllers.add(site); }); - - CellBindingUtils.attachTextCellFactoriesString(evidCol, MeasuredMwDetails::getEventId); - evidCol.comparatorProperty().set(new MaybeNumericStringComparator()); - - CellBindingUtils.attachTextCellFactories(mwCol, MeasuredMwDetails::getRefMw, dfmt4); - CellBindingUtils.attachTextCellFactories(stressCol, MeasuredMwDetails::getRefApparentStressInMpa, dfmt4); - CellBindingUtils.attachTextCellFactories(measuredMwCol, MeasuredMwDetails::getMw, dfmt4); - CellBindingUtils.attachTextCellFactories(mistfitCol, MeasuredMwDetails::getMisfit, dfmt4); - // CellBindingUtils.attachTextCellFactories(measuredMwSdCol, MeasuredMwDetails::getMwSd, dfmt4); - CellBindingUtils.attachTextCellFactories(measuredStressCol, MeasuredMwDetails::getApparentStressInMpa, dfmt4); - CellBindingUtils.attachTextCellFactories(measuredCornerFreqCol, MeasuredMwDetails::getCornerFreq, dfmt4); - // CellBindingUtils.attachTextCellFactories(measuredCornerFreqSdCol, MeasuredMwDetails::getCornerFreqSd, dfmt4); - CellBindingUtils.attachTextCellFactories(measuredMwUq1LowCol, MeasuredMwDetails::getMw1Min, dfmt4); - CellBindingUtils.attachTextCellFactories(measuredMwUq1HighCol, MeasuredMwDetails::getMw1Max, dfmt4); - CellBindingUtils.attachTextCellFactories(measuredMwUq2LowCol, MeasuredMwDetails::getMw2Min, dfmt4); - CellBindingUtils.attachTextCellFactories(measuredMwUq2HighCol, MeasuredMwDetails::getMw2Max, dfmt4); - - iterationsCol.setCellValueFactory( - x -> Bindings.createIntegerBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(MeasuredMwDetails::getIterations).orElseGet(() -> 0)).asObject()); - - dataCountCol.setCellValueFactory( - x -> Bindings.createIntegerBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(MeasuredMwDetails::getDataCount).orElseGet(() -> 0)).asObject()); - - iconCol.setCellValueFactory(x -> Bindings.createObjectBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(pp -> { - ImageView imView = new ImageView(SwingFXUtils.toFXImage( - SymbolFactory.createSymbol(pp.getStyle(), 0, 0, 2, pp.getColor(), pp.getColor(), pp.getColor(), "", true, false, 10.0).getBufferedImage(256), - null)); - imView.setFitHeight(12); - imView.setFitWidth(12); - return imView; - }).orElseGet(() -> new ImageView()))); - - stationCol.setCellValueFactory(x -> Bindings.createStringBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(LabeledPlotPoint::getLabel).orElseGet(String::new))); - - eventTable.setItems(mwParameters); - iconTable.setItems(stationSymbols); - - iconCol.prefWidthProperty().bind(iconTable.widthProperty().multiply(0.3)); - stationCol.prefWidthProperty().bind(iconTable.widthProperty().multiply(0.7)); - - menu = new ContextMenu(); - include = new MenuItem("Include Selected"); - menu.getItems().add(include); - exclude = new MenuItem("Exclude Selected"); - menu.getItems().add(exclude); - - EventHandler menuHideHandler = (evt) -> { - if (MouseButton.SECONDARY != evt.getButton()) { - menu.hide(); - } - }; - rawPlotSwingNode.addEventHandler(javafx.scene.input.MouseEvent.MOUSE_CLICKED, menuHideHandler); - pathPlotSwingNode.addEventHandler(javafx.scene.input.MouseEvent.MOUSE_CLICKED, menuHideHandler); - sitePlotSwingNode.addEventHandler(javafx.scene.input.MouseEvent.MOUSE_CLICKED, menuHideHandler); - } - - protected Object getPoint2D(Symbol sym) { - return new Point2D.Double(sym.getXcenter(), sym.getYcenter()); - } - - private void showWaveformPopup(Waveform waveform) { - bus.post(new WaveformSelectionEvent(waveform.getId())); - } - - private void plotSpectra() { - clearSpectraPlots(); - rawSymbolMap.clear(); - pathSymbolMap.clear(); - siteSymbolMap.clear(); - plotPointMap.clear(); - List filteredMeasurements; - - rawPlot.setAutoCalculateXaxisRange(shouldXAxisShrink); - pathPlot.setAutoCalculateXaxisRange(shouldXAxisShrink); - sitePlot.setAutoCalculateXaxisRange(shouldXAxisShrink); - if (!shouldXAxisShrink) { - rawPlot.setAllXlimits(minFreq.get(), maxFreq.get()); - pathPlot.setAllXlimits(minFreq.get(), maxFreq.get()); - sitePlot.setAllXlimits(minFreq.get(), maxFreq.get()); - } - - if (evidCombo != null && evidCombo.getSelectionModel().getSelectedIndex() > 0) { - filteredMeasurements = filterToEvent(evidCombo.getSelectionModel().getSelectedItem(), spectralMeasurements); - Spectra referenceSpectra = spectraClient.getReferenceSpectra(evidCombo.getSelectionModel().getSelectedItem()).block(Duration.ofSeconds(2)); - List fittingSpectra = new ArrayList<>(spectraClient.getFitSpectra(evidCombo.getSelectionModel().getSelectedItem()).block(Duration.ofSeconds(2))); - fittingSpectra.add(referenceSpectra); - rawPlot.plotXYdata(toPlotPoints(filteredMeasurements, SpectraMeasurement::getRawAtMeasurementTime), Boolean.TRUE); - pathPlot.plotXYdata(toPlotPoints(filteredMeasurements, SpectraMeasurement::getPathCorrected), Boolean.TRUE); - sitePlot.plotXYdata(toPlotPoints(filteredMeasurements, SpectraMeasurement::getPathAndSiteCorrected), Boolean.TRUE, fittingSpectra); - if (filteredMeasurements != null && filteredMeasurements.size() > 0 && filteredMeasurements.get(0).getWaveform() != null) { - Event event = filteredMeasurements.get(0).getWaveform().getEvent(); - eventTime.setText("Date: " + DateTimeFormatter.ISO_INSTANT.format(event.getOriginTime().toInstant())); - eventLoc.setText("Lat: " + dfmt4.format(event.getLatitude()) + " Lon: " + dfmt4.format(event.getLongitude())); - eventTime.setVisible(true); - eventLoc.setVisible(true); - } - } else { - eventTime.setVisible(false); - eventLoc.setVisible(false); - filteredMeasurements = spectralMeasurements; - rawPlot.plotXYdata(toPlotPoints(filteredMeasurements, SpectraMeasurement::getRawAtMeasurementTime), Boolean.FALSE); - pathPlot.plotXYdata(toPlotPoints(filteredMeasurements, SpectraMeasurement::getPathCorrected), Boolean.FALSE); - sitePlot.plotXYdata(toPlotPoints(filteredMeasurements, SpectraMeasurement::getPathAndSiteCorrected), Boolean.FALSE); - } - rawSymbolMap.putAll(mapSpectraToPoint(filteredMeasurements, SpectraMeasurement::getRawAtMeasurementTime)); - pathSymbolMap.putAll(mapSpectraToPoint(filteredMeasurements, SpectraMeasurement::getPathCorrected)); - siteSymbolMap.putAll(mapSpectraToPoint(filteredMeasurements, SpectraMeasurement::getPathAndSiteCorrected)); - mapMeasurements(filteredMeasurements); - - minY.set(100.0); - maxY.set(0.0); - DoubleSummaryStatistics stats = filteredMeasurements.stream() - .filter(Objects::nonNull) - .map(spec -> spec.getPathAndSiteCorrected()) - .filter(v -> v != 0.0) - .collect(Collectors.summarizingDouble(Double::doubleValue)); - maxY.set(stats.getMax() + .1); - minY.set(stats.getMin() - .1); - - sitePlot.setAutoCalculateYaxisRange(shouldYAxisShrink); - if (shouldYAxisShrink) { - sitePlot.setAllYlimits(minY.get(), maxY.get()); - } else { - sitePlot.setAllYlimits(); - } - } - - private void mapMeasurements(List measurements) { - if (measurements != null) { - mapImpl.addIcons( - iconFactory.genIconsFromWaveforms( - eventSelectionCallback, - stationSelectionCallback, - measurements.stream().map(m -> m.getWaveform()).filter(Objects::nonNull).collect(Collectors.toList()))); - } - } - - private void clearSpectraPlots() { - rawPlot.clearPlot(); - pathPlot.clearPlot(); - sitePlot.clearPlot(); - } - - private List filterToEvent(String selectedItem, List spectralMeasurements) { - return spectralMeasurements.stream().filter(spec -> selectedItem.equalsIgnoreCase(spec.getWaveform().getEvent().getEventId())).collect(Collectors.toList()); - } - - private Map mapSpectraToPoint(List spectralMeasurements, Function func) { - return spectralMeasurements.stream() - .filter(spectra -> !func.apply(spectra).equals(0.0)) - .collect( - Collectors.toMap( - spectra -> new Point2D.Double(Math.log10(centerFreq(spectra.getWaveform().getLowFrequency(), spectra.getWaveform().getHighFrequency())), - func.apply(spectra)), - Function.identity(), - (a, b) -> b, - HashMap::new)); - } - - private List toPlotPoints(List spectralMeasurements, Function func) { - List list = spectralMeasurements.stream() - .filter(spectra -> !func.apply(spectra).equals(0.0)) - .filter( - spectra -> spectra != null - && spectra.getWaveform() != null - && spectra.getWaveform().getStream() != null - && spectra.getWaveform().getStream().getStation() != null) - .map(spectra -> { - String key = spectra.getWaveform().getStream().getStation().getStationName(); - PlotPoint pp = getPlotPoint(key, spectra.getWaveform().isActive()); - PlotPoint point = new LabeledPlotPoint(key, - new PlotPoint(Math.log10( - centerFreq(spectra.getWaveform().getLowFrequency(), spectra.getWaveform().getHighFrequency())), - func.apply(spectra), - pp.getStyle(), - pp.getColor())); - if (hasEventAndStation(spectra)) { - plotPointMap.computeIfAbsent(spectra.getWaveform().getEvent().getEventId(), k -> new ArrayList<>()).add(point); - plotPointMap.computeIfAbsent(spectra.getWaveform().getStream().getStation().getStationName(), k -> new ArrayList<>()).add(point); - } - return point; - }) - .collect(Collectors.toList()); - return list; - } - - private PlotPoint getPlotPoint(String key, boolean active) { - PlotPoint pp = new PlotPoint(symbolStyleMap.get(key)); - if (!active) { - pp.setColor(Color.GRAY); - } - return pp; - } - - private boolean hasEventAndStation(SpectraMeasurement spectra) { - return spectra != null - && spectra.getWaveform() != null - && spectra.getWaveform().getEvent() != null - && spectra.getWaveform().getEvent().getEventId() != null - && spectra.getWaveform().getStream() != null - && spectra.getWaveform().getStream().getStation() != null - && spectra.getWaveform().getStream().getStation().getStationName() != null; - } - - private double centerFreq(Double lowFrequency, Double highFrequency) { - return lowFrequency + (highFrequency - lowFrequency) / 2.; - } - - private void reloadData() { - clearSpectraPlots(); - - mwParameters.clear(); - try { - SwingUtilities.invokeAndWait(() -> { - mwPlotFigure.Clear(); - stressPlotFigure.Clear(); - sdPlotFigure.Clear(); - mwPlotFigure.AddPlotObject(mwZeroLine); - stressPlotFigure.AddPlotObject(stressZeroLine); - List evs = referenceEventClient.getMeasuredEventDetails() - .filter(ev -> ev.getEventId() != null) - .collect(Collectors.toList()) - .subscribeOn(Schedulers.elastic()) - .block(Duration.ofSeconds(10l)); - - maxFreq.set(-0.0); - minFreq.set(1.0); - - DoubleSummaryStatistics stats = paramClient.getSharedFrequencyBandParameters() - .filter(Objects::nonNull) - .collectList() - .block(Duration.of(10l, ChronoUnit.SECONDS)) - .stream() - .map(sfb -> Math.log10(centerFreq(sfb.getLowFrequency(), sfb.getHighFrequency()))) - .collect(Collectors.summarizingDouble(Double::doubleValue)); - maxFreq.set(stats.getMax()); - minFreq.set(stats.getMin()); - - double minMw = 10.0; - double maxMw = 0.0; - double minStress = 1.0; - double maxStress = 0.0; - for (MeasuredMwDetails ev : evs) { - mwParameters.add(ev); - if (ev.getMw() != null && ev.getMw() != 0.0 && ev.getRefMw() != null && ev.getRefMw() != 0.0) { - Double mw = ev.getMw(); - Double ref = ev.getRefMw(); - if (mw < minMw) { - minMw = mw; - } - if (mw > maxMw) { - maxMw = mw; - } - if (ref < minMw) { - minMw = ref; - } - if (ref > maxMw) { - maxMw = ref; - } - - Double stress = ev.getApparentStressInMpa(); - Double refStress = ev.getRefApparentStressInMpa(); - - if (stress != null) { - if (stress < minStress) { - minStress = stress; - } - if (stress > maxStress) { - maxStress = stress; - } - - if (refStress == null) { - refStress = 0.0; - } - - if (refStress < minStress) { - minStress = refStress; - } - if (refStress > maxStress) { - maxStress = refStress; - } - - Circle stressSym = new Circle(stress, refStress, 2.0, Color.RED, Color.RED, Color.RED, ev.getEventId(), true, false, 6.0); - stressPlotFigure.AddPlotObject(stressSym); - } - - Circle mwSym = new Circle(mw, ref, 2.0, Color.RED, Color.RED, Color.RED, ev.getEventId(), true, false, 6.0); - mwPlotFigure.AddPlotObject(mwSym); - } - } - - maxMw = maxMw + .1; - minMw = minMw > maxMw ? minMw = maxMw - .1 : minMw - .1; - - mwPlotFigure.setAxisLimits(minMw, maxMw, minMw, maxMw); - - maxStress = maxStress + .1; - minStress = minStress > maxStress ? minStress = maxStress - .1 : minStress - .1; - - stressPlotFigure.setAxisLimits(minStress, maxStress, minStress, maxStress); - }); - - spectralMeasurements.clear(); - stationSymbols.clear(); - - evids.clear(); - evids.add("All"); - - spectralMeasurements.addAll( - spectraClient.getMeasuredSpectraMetadata() - .filter(Objects::nonNull) - .filter(spectra -> spectra.getWaveform() != null && spectra.getWaveform().getEvent() != null && spectra.getWaveform().getStream() != null) - .toStream() - .collect(Collectors.toList())); - - symbolStyleMap = symbolStyleMapFactory.build(spectralMeasurements, new Function() { - @Override - public String apply(SpectraMeasurement t) { - return t.getWaveform().getStream().getStation().getStationName(); - } - }); - stationSymbols.addAll(symbolStyleMap.entrySet().stream().map(e -> new LabeledPlotPoint(e.getKey(), e.getValue())).collect(Collectors.toList())); - - evids.addAll(spectralMeasurements.stream().map(spec -> spec.getWaveform().getEvent().getEventId()).distinct().sorted(new MaybeNumericStringComparator()).collect(Collectors.toList())); - eventTable.sort(); - - SwingUtilities.invokeAndWait(() -> { - Map> evidStats = new HashMap<>(); - - double minSite = 1E2; - double maxSite = -1E2; - double minFreq = 1E2; - double maxFreq = -1E2; - int minStations = 2; - int maxStations = 3; - - for (SpectraMeasurement meas : spectralMeasurements) { - String evid = meas.getWaveform().getEvent().getEventId(); - Double freq = centerFreq(meas.getWaveform()); - evidStats.computeIfAbsent(evid, key -> new HashMap<>()).computeIfAbsent(freq, (key) -> new SummaryStatistics()).addValue(meas.getPathAndSiteCorrected()); - } - - for (Map freqStats : evidStats.values()) { - for (Entry entry : freqStats.entrySet()) { - double site = entry.getValue().getStandardDeviation(); - if (entry.getValue() != null && entry.getValue().getN() > 1) { - if (maxStations < entry.getValue().getN()) { - maxStations = (int) entry.getValue().getN(); - } - if (site < minSite) { - minSite = site; - } - if (site > maxSite) { - maxSite = site; - } - if (entry.getKey() < minFreq) { - minFreq = entry.getKey(); - } - if (entry.getKey() > maxFreq) { - maxFreq = entry.getKey(); - } - } - } - } - - colorMap.setRange(minStations, maxStations); - - for (Map freqStats : evidStats.values()) { - for (Entry entry : freqStats.entrySet()) { - double site = entry.getValue().getStandardDeviation(); - if (entry.getValue() != null && entry.getValue().getN() > 1) { - Color color = colorMap.getColor(entry.getValue().getN()); - Circle sdSym = new Circle(entry.getKey(), site, 2.0, color, color, color, "", true, false, 6.0); - sdPlotFigure.AddPlotObject(sdSym); - } - } - } - - maxSite = maxSite + .1; - minSite = minSite > maxSite ? minSite = maxSite - .1 : minSite - .1; - - maxFreq = maxFreq + 5.0; - minFreq = minFreq > maxFreq ? minFreq = maxFreq - .1 : minFreq - 1.0; - - sdPlotFigure.setAxisLimits(minFreq, maxFreq, minSite, maxSite); - sdPlotFigure.AddPlotObject(createColorLegend(minStations, maxStations)); - }); - - mwPlot.repaint(); - stressPlot.repaint(); - sdPlot.repaint(); - } catch (InvocationTargetException ex) { - //nop - } catch (InterruptedException ex) { - log.warn("Swing interrupt during re-plotting of site controller", ex); - Thread.currentThread().interrupt(); - } - } - - private PlotObject createColorLegend(int minVal, int maxVal) { - int range = maxVal - minVal; - int legendEntries = range; - if (legendEntries > MAX_LEGEND_COLORS) { - legendEntries = MAX_LEGEND_COLORS; - } - List legendSymbols = new ArrayList<>(range); - - Color color = colorMap.getColor(minVal); - legendSymbols.add(new SymbolTextPair(Integer.toString(minVal), new SymbolDef(SymbolStyle.CIRCLE, 1.0, color, color))); - if (legendEntries > 2) { - int i = minVal + 1; - while (i < legendEntries + minVal) { - color = colorMap.getColor(i); - legendSymbols.add(new SymbolTextPair(Integer.toString(i), new SymbolDef(SymbolStyle.CIRCLE, 1.0, color, color))); - i = i + (range / (legendEntries - 1)); - } - } - color = colorMap.getColor(maxVal); - legendSymbols.add(new SymbolTextPair(maxVal + "+", new SymbolDef(SymbolStyle.CIRCLE, 1.0, color, color))); - return new SymbolLegend(legendSymbols, sdPlot.getTitle().getFontName(), 8.0, HorizPinEdge.RIGHT, VertPinEdge.TOP, 1, 1); - } - - private Double centerFreq(Waveform waveform) { - return ((waveform.getHighFrequency() - waveform.getLowFrequency()) / 2.0) + waveform.getLowFrequency(); } @Override - public void refreshView() { - if (isVisible) { - mapImpl.clearIcons(); - plotSpectra(); - Platform.runLater(() -> { - rawPlot.repaint(); - pathPlot.repaint(); - sitePlot.repaint(); - }); - } + protected String getDisplayName() { + return displayName; } @Override - public Runnable getRefreshFunction() { - return () -> reloadData(); + protected List getFitSpectra() { + return new ArrayList<>(spectraClient.getFitSpectra(evidCombo.getSelectionModel().getSelectedItem()).block(Duration.ofSeconds(2))); } @Override - public Consumer getScreenshotFunction() { - return (folder) -> { - String timestamp = SnapshotUtils.getTimestampWithLeadingSeparator(); - try { - if (resultsTab.isSelected() && evidCombo.getValue() != null) { - SnapshotUtils.writePng(folder, new Pair<>("Site", resultsTab.getContent()), timestamp); - rawPlot.exportSVG(folder + File.separator + "Site_Raw_" + evidCombo.getValue() + timestamp + ".svg"); - pathPlot.exportSVG(folder + File.separator + "Site_Path_" + evidCombo.getValue() + timestamp + ".svg"); - sitePlot.exportSVG(folder + File.separator + "Site_Full_" + evidCombo.getValue() + timestamp + ".svg"); - } else { - mwPlot.exportSVG(folder + File.separator + "Site_Mw" + timestamp + ".svg"); - stressPlot.exportSVG(folder + File.separator + "Site_Stress" + timestamp + ".svg"); - sdPlot.exportSVG(folder + File.separator + "Site_Station_Event_SD" + timestamp + ".svg"); - } - } catch (UnsupportedEncodingException | FileNotFoundException | SVGGraphics2DIOException e) { - log.error("Error attempting to write plots for path controller : {}", e.getLocalizedMessage(), e); - } - }; - } - - private void selectDataByCriteria(Boolean selected, String key) { - List points = plotPointMap.get(key); - if (selected) { - selectPoints(points); - } else { - deselectPoints(points); - } - } - - private void selectPoints(List points) { - if (points != null && !points.isEmpty()) { - if (!selectedPoints.isEmpty()) { - deselectPoints(selectedPoints); - } - selectedPoints.addAll(points); - SwingUtilities.invokeLater(() -> { - points.forEach(point -> { - selectPoint(point); - }); - }); - } - } - - private void deselectPoints(List selected) { - if (selected != null && !selected.isEmpty()) { - List points = new ArrayList<>(selected.size()); - points.addAll(selected); - selectedPoints.clear(); - SwingUtilities.invokeLater(() -> { - points.forEach(point -> { - deselectPoint(point); - }); - }); - } - } - - private void selectPoint(PlotPoint point) { - Point2D.Double xyPoint = new Point2D.Double(point.getX(), point.getY()); - boolean existsInPlot = rawSymbolMap.containsKey(xyPoint); - if (existsInPlot) { - rawPlot.selectPoint(xyPoint); - } - - existsInPlot = pathSymbolMap.containsKey(xyPoint); - if (existsInPlot) { - pathPlot.selectPoint(xyPoint); - } - - existsInPlot = siteSymbolMap.containsKey(xyPoint); - if (existsInPlot) { - sitePlot.selectPoint(xyPoint); - } - } - - private void deselectPoint(PlotPoint point) { - Point2D.Double xyPoint = new Point2D.Double(point.getX(), point.getY()); - boolean existsInPlot = rawSymbolMap.containsKey(xyPoint); - if (existsInPlot) { - rawPlot.deselectPoint(xyPoint); - } - - existsInPlot = pathSymbolMap.containsKey(xyPoint); - if (existsInPlot) { - pathPlot.deselectPoint(xyPoint); - } - - existsInPlot = siteSymbolMap.containsKey(xyPoint); - if (existsInPlot) { - sitePlot.deselectPoint(xyPoint); - } - } - - protected void setSymbolsActive(List objs, Boolean active) { - SwingUtilities.invokeLater(() -> { - objs.forEach(sym -> { - if (active) { - sym.setFillColor(sym.getEdgeColor()); - sym.setEdgeColor(Color.BLACK); - } else { - sym.setEdgeColor(sym.getFillColor()); - sym.setFillColor(Color.GRAY); - } - }); - Platform.runLater(() -> { - rawPlot.repaint(); - pathPlot.repaint(); - sitePlot.repaint(); - }); - }); - } - - private void showContextMenu(List waveforms, List plotObjects, MouseEvent t, BiConsumer, Boolean> activationFunc) { - Platform.runLater(() -> { - include.setOnAction(evt -> setActive(waveforms, plotObjects, true, activationFunc)); - exclude.setOnAction(evt -> setActive(waveforms, plotObjects, false, activationFunc)); - menu.show(sitePlotSwingNode, t.getXOnScreen(), t.getYOnScreen()); - }); - } - - private void setActive(List waveforms, List plotObjects, boolean active, BiConsumer, Boolean> activationFunc) { + protected void setActive(List waveforms, List plotObjects, boolean active, BiConsumer, Boolean> activationFunc) { waveformClient.setWaveformsActiveByIds(waveforms.stream().map(w -> w.getId()).collect(Collectors.toList()), active).subscribe(s -> activationFunc.accept(plotObjects, active)); } - @Subscribe - private void listener(WaveformChangeEvent wce) { - List nonNull = wce.getIds().stream().filter(Objects::nonNull).collect(Collectors.toList()); - synchronized (spectralMeasurements) { - Map activeMeasurements = spectralMeasurements.stream().collect(Collectors.toMap(x -> x.getWaveform().getId(), Function.identity())); - if (wce.isAddOrUpdate()) { - waveformClient.getWaveformMetadataFromIds(nonNull).collect(Collectors.toList()).block(Duration.ofSeconds(10l)).forEach(md -> { - SpectraMeasurement measurement = activeMeasurements.get(md.getId()); - if (measurement != null) { - measurement.getWaveform().setActive(md.isActive()); - } - }); - } else if (wce.isDelete()) { - nonNull.forEach(id -> { - SpectraMeasurement measurement = activeMeasurements.remove(id); - if (measurement != null) { - spectralMeasurements.remove(measurement); - } - }); - } - } - refreshView(); - } - - private void handlePlotObjectClicked(Object obj, Function measurementFunc) { - if (obj instanceof PlotObjectClicked && ((PlotObjectClicked) obj).getMouseEvent().getID() == MouseEvent.MOUSE_RELEASED) { - PlotObjectClicked poc = (PlotObjectClicked) obj; - PlotObject po = poc.getPlotObject(); - if (po instanceof Symbol) { - SpectraMeasurement spectra = measurementFunc.apply((Symbol) po); - if (spectra != null && spectra.getWaveform() != null) { - if (SwingUtilities.isLeftMouseButton(poc.getMouseEvent())) { - selectPoints(plotPointMap.get(((Symbol) po).getText())); - if (spectra != null) { - showWaveformPopup(spectra.getWaveform()); - } - Platform.runLater(() -> menu.hide()); - } else if (SwingUtilities.isRightMouseButton(poc.getMouseEvent())) { - showContextMenu(Collections.singletonList(spectra.getWaveform()), Collections.singletonList((Symbol) po), poc.getMouseEvent(), (objs, active) -> { - setSymbolsActive(objs, active); - }); - } - } - } - } - } - @Override - public void setVisible(boolean visible) { - isVisible = visible; - } - - @FXML - private void clearRefEvents() { - removeRefEvents(mwParameters); - } - - @FXML - private void removeRefEvents() { - List evs = new ArrayList<>(eventTable.getSelectionModel().getSelectedIndices().size()); - eventTable.getSelectionModel().getSelectedIndices().forEach(i -> evs.add(mwParameters.get(i))); - removeRefEvents(evs); + protected List getSpectraData() { + return spectraClient.getMeasuredSpectraMetadata() + .filter(Objects::nonNull) + .filter(spectra -> spectra.getWaveform() != null && spectra.getWaveform().getEvent() != null && spectra.getWaveform().getStream() != null) + .toStream() + .collect(Collectors.toList()); + } + + @Override + protected void runGuiUpdate(Runnable runnable) throws InvocationTargetException, InterruptedException { + SwingUtilities.invokeAndWait(runnable); } - private void removeRefEvents(List evs) { - if (evs != null && !evs.isEmpty()) { - referenceEventClient.removeReferenceEventsByEventId(evs.stream().map(mwd -> mwd.getEventId()).distinct().collect(Collectors.toList())) - .doOnSuccess((v) -> Platform.runLater(() -> reloadData())) - .subscribe(); - } + @Override + protected List getEvents() { + return referenceEventClient.getMeasuredEventDetails() + .filter(ev -> ev.getEventId() != null) + .collect(Collectors.toList()) + .subscribeOn(Schedulers.elastic()) + .block(Duration.ofSeconds(10l)); } } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/SpectraPlotController.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/SpectraPlotController.java new file mode 100644 index 00000000..da63f08a --- /dev/null +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/SpectraPlotController.java @@ -0,0 +1,64 @@ +/* +* Copyright (c) 2020, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* CODE-743439. +* All rights reserved. +* +* Licensed under the Apache License, Version 2.0 (the “Licensee”); you may not use this file except in compliance with the License. You may obtain a copy of the License at: +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and limitations under the license. +* +* This work was performed under the auspices of the U.S. Department of Energy +* by Lawrence Livermore National Laboratory under Contract DE-AC52-07NA27344. +*/ +package gov.llnl.gnem.apps.coda.calibration.gui.controllers; + +import java.awt.geom.Point2D; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import gov.llnl.gnem.apps.coda.calibration.gui.plotting.SpectralPlot; +import gov.llnl.gnem.apps.coda.calibration.model.domain.SpectraMeasurement; + +public class SpectraPlotController { + private final Logger log = LoggerFactory.getLogger(this.getClass()); + private SpectralPlot spectraPlot = new SpectralPlot();; + private Map spectraSymbolMap = new ConcurrentHashMap<>(); + private boolean isYaxisResizble = false; + private Function dataFunction; + + public SpectraPlotController(Function dataFunction) { + this.dataFunction = dataFunction; + } + + public SpectralPlot getSpectralPlot() { + return spectraPlot; + } + + public Map getSymbolMap() { + return spectraSymbolMap; + } + + public void setYAxisResize(boolean shouldYAxisShrink, double minY, double maxY) { + if (isYaxisResizble) { + spectraPlot.setAutoCalculateYaxisRange(shouldYAxisShrink); + if (shouldYAxisShrink) { + spectraPlot.setAllYlimits(minY, maxY); + } else { + spectraPlot.setAllYlimits(); + } + } + } + + public void setYAxisResizable(boolean isYaxisResizble) { + this.isYaxisResizble = isYaxisResizble; + } + + public Function getDataFunc() { + return dataFunction; + } +} diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/CodaJsonParamLoader.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/CodaJsonParamLoader.java index 53b0643c..6647521f 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/CodaJsonParamLoader.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/CodaJsonParamLoader.java @@ -25,6 +25,7 @@ import static gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.CalibrationJsonConstants.SITE_CORRECTION_FIELD; import static gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.CalibrationJsonConstants.TYPE_FIELD; import static gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.CalibrationJsonConstants.TYPE_VALUE; +import static gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.CalibrationJsonConstants.VALIDATION_EVENTS_FIELD; import static gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.CalibrationJsonConstants.VELOCITY_CONFIGURATION; import java.io.File; @@ -55,6 +56,7 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.ShapeFitterConstraints; import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteCorrections; import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteFrequencyBandParameters; +import gov.llnl.gnem.apps.coda.calibration.model.domain.ValidationMwParameters; import gov.llnl.gnem.apps.coda.calibration.model.domain.VelocityConfiguration; import gov.llnl.gnem.apps.coda.calibration.model.domain.mixins.SharedFrequencyBandParametersFileMixin; import gov.llnl.gnem.apps.coda.calibration.model.domain.mixins.SiteFrequencyBandParametersFileMixin; @@ -93,21 +95,23 @@ public Flux> convertFiles(List files) { public List> convertJsonParamFile(File file) { if (file == null) { - return Collections.singletonList( - exceptionalResult(new LightweightIllegalStateException(String.format("Error parsing (%s): file does not exist or is unreadable. %s", "NULL", "File reference is null")))); + return Collections.singletonList(exceptionalResult(new LightweightIllegalStateException(String.format("Error parsing (%s): file does not exist or is unreadable. %s", + "NULL", + "File reference is null")))); } List> results = new ArrayList<>(); try { JsonNode node = mapper.readTree(file); - + //TODO: Collapse these into generic method with self-validation type at some point. if (node.has(SCHEMA_FIELD) && node.get(SCHEMA_FIELD).asText().equalsIgnoreCase(SCHEMA_VALUE) && node.has(TYPE_FIELD) && node.get(TYPE_FIELD).asText().equalsIgnoreCase(TYPE_VALUE)) { results.addAll(convertJsonFields(node, BAND_FIELD, x -> sharedFrequenyBandFromJsonNode(x))); results.addAll(convertJsonFields(node, SITE_CORRECTION_FIELD, x -> siteFrequenyBandsFromJsonNode(x))); results.addAll(convertJsonFields(node, MDAC_PS_FIELD, x -> mdacPsFromJsonNode(x))); results.addAll(convertJsonFields(node, MDAC_FI_FIELD, x -> mdacFiFromJsonNode(x))); results.addAll(convertJsonFields(node, REFERENCE_EVENTS_FIELD, x -> refEventsFromJsonNode(x))); + results.addAll(convertJsonFields(node, VALIDATION_EVENTS_FIELD, x -> valEventsFromJsonNode(x))); results.addAll(convertJsonFields(node, VELOCITY_CONFIGURATION, x -> velocityConfigurationFromJsonNode(x))); results.addAll(convertJsonFields(node, SHAPE_CONSTRAINTS, x -> shapeConstraintsFromJsonNode(x))); } else if (node.has(ENVELOPE_JOB_NODE)) { @@ -168,6 +172,17 @@ protected Result refEventsFromJsonNode(JsonNode node) { } } + protected Result valEventsFromJsonNode(JsonNode node) { + ObjectReader reader = mapper.readerFor(ValidationMwParameters.class); + try { + //TODO: Validate all fields + ValidationMwParameters val = reader.readValue(node); + return new Result<>(true, val); + } catch (IOException e) { + return exceptionalResult(e); + } + } + protected Result mdacPsFromJsonNode(JsonNode node) { ObjectReader reader = mapper.readerFor(MdacParametersPS.class); try { diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/CalibrationWebClient.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/CalibrationWebClient.java index d2c2c2a3..2c978947 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/CalibrationWebClient.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/CalibrationWebClient.java @@ -45,6 +45,19 @@ public Mono runCalibration(Boolean autoPickingEnabled) { return client.get().uri("/calibration/start/" + autoPickingEnabled).accept(MediaType.APPLICATION_JSON).exchange().flatMap(resp -> resp.bodyToMono(String.class)); } + @Override + public Mono cancelCalibration(Long id) { + return client.post() + .uri("/calibration/cancel/") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .bodyValue(id) + .exchange() + .doOnError(e -> log.error(e.getMessage(), e)) + .doOnSuccess(cr -> log.error(cr.toString())) + .flatMap(resp -> resp.bodyToMono(String.class).map(Boolean::valueOf)); + } + @Override public Mono makeMwMeasurements(Boolean autoPickingEnabled) { return makeMwMeasurements(autoPickingEnabled, null); diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/ReferenceEventWebClient.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/EventWebClient.java similarity index 66% rename from calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/ReferenceEventWebClient.java rename to calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/EventWebClient.java index 9b106787..fd4aa413 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/ReferenceEventWebClient.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/EventWebClient.java @@ -23,21 +23,22 @@ import com.fasterxml.jackson.core.JsonProcessingException; -import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ReferenceEventClient; +import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.EventClient; import gov.llnl.gnem.apps.coda.calibration.model.domain.MeasuredMwDetails; import gov.llnl.gnem.apps.coda.calibration.model.domain.MeasuredMwParameters; import gov.llnl.gnem.apps.coda.calibration.model.domain.ReferenceMwParameters; +import gov.llnl.gnem.apps.coda.calibration.model.domain.ValidationMwParameters; import gov.llnl.gnem.apps.coda.common.model.domain.Event; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @Component -public class ReferenceEventWebClient implements ReferenceEventClient { +public class EventWebClient implements EventClient { private WebClient client; @Autowired - public ReferenceEventWebClient(WebClient client) { + public EventWebClient(WebClient client) { this.client = client; } @@ -98,4 +99,48 @@ public Mono removeReferenceEventsByEventId(List evids) { .flatMap(resp -> Mono.empty()); } + @Override + public Flux getValidationEvents() { + return client.get() + .uri("/validation-events") + .accept(MediaType.APPLICATION_JSON) + .exchange() + .flatMapMany(response -> response.bodyToFlux(ValidationMwParameters.class)) + .onErrorReturn(new ValidationMwParameters()); + } + + @Override + public Mono postValidationEvents(List events) throws JsonProcessingException { + return client.post() + .uri("/validation-events/batch") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .bodyValue(events) + .exchange() + .flatMap(resp -> resp.bodyToMono(String.class)); + } + + @Override + public Mono removeValidationEventsByEventId(List evids) { + return client.post() + .uri("/validation-events/delete/batch-by-evids") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .bodyValue(evids) + .exchange() + .flatMap(resp -> Mono.empty()); + } + + @Override + public Flux toggleValidationEventsByEventId(List evids) { + return client.post() + .uri("/calibration/toggle-validation/batch-by-evids") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .bodyValue(evids) + .exchange() + .flux() + .flatMap(resp -> resp.bodyToFlux(String.class)); + } + } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/SpectraWebClient.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/SpectraWebClient.java index a1129624..fa7a36b6 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/SpectraWebClient.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/SpectraWebClient.java @@ -70,6 +70,18 @@ public Mono getReferenceSpectra(String eventId) { .flatMap(response -> response.bodyToMono(Spectra.class)) .onErrorReturn(new Spectra()); } + + @Override + public Mono getValidationSpectra(String eventId) { + return client.post() + .uri("/spectra-measurements/validation-spectra") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .bodyValue(eventId) + .exchange() + .flatMap(response -> response.bodyToMono(Spectra.class)) + .onErrorReturn(new Spectra()); + } @Override public Mono> getFitSpectra(String eventId) { diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/CalibrationClient.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/CalibrationClient.java index 26dd49bb..ec08ac0d 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/CalibrationClient.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/CalibrationClient.java @@ -22,6 +22,8 @@ public interface CalibrationClient { public Mono runCalibration(Boolean autoPickingEnabled); + + public Mono cancelCalibration(Long id); public Mono makeMwMeasurements(Boolean autoPickingEnabled); diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/CalibrationJsonConstants.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/CalibrationJsonConstants.java index ac372a33..bf868e19 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/CalibrationJsonConstants.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/CalibrationJsonConstants.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2019, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* Copyright (c) 2020, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory * CODE-743439. * All rights reserved. * This file is part of CCT. For details, see https://github.com/LLNL/coda-calibration-tool. @@ -24,6 +24,7 @@ public class CalibrationJsonConstants { public static final String MDAC_PS_FIELD = "mdac-ps"; public static final String MDAC_FI_FIELD = "mdac-fi"; public static final String REFERENCE_EVENTS_FIELD = "reference-events"; + public static final String VALIDATION_EVENTS_FIELD = "validation-events"; public static final String MEASURED_EVENTS_FIELD = "measured-events"; public static final String VELOCITY_CONFIGURATION = "velocity-configuration"; public static final String SHAPE_CONSTRAINTS = "shape-constraints"; diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/ReferenceEventClient.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/EventClient.java similarity index 77% rename from calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/ReferenceEventClient.java rename to calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/EventClient.java index 34800d5d..4f6d8d0e 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/ReferenceEventClient.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/EventClient.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2018, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* Copyright (c) 2020, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory * CODE-743439. * All rights reserved. * This file is part of CCT. For details, see https://github.com/LLNL/coda-calibration-tool. @@ -21,21 +21,30 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.MeasuredMwDetails; import gov.llnl.gnem.apps.coda.calibration.model.domain.MeasuredMwParameters; import gov.llnl.gnem.apps.coda.calibration.model.domain.ReferenceMwParameters; +import gov.llnl.gnem.apps.coda.calibration.model.domain.ValidationMwParameters; import gov.llnl.gnem.apps.coda.common.model.domain.Event; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -public interface ReferenceEventClient { - - public Flux getReferenceEvents(); +public interface EventClient { public Flux getMeasuredEvents(); - - public Mono postReferenceEvents(List refEvents) throws JsonProcessingException; + + public Flux getMeasuredEventDetails(); + + public Flux getReferenceEvents(); + + public Flux getValidationEvents(); public Mono getEvent(String eventId); - public Flux getMeasuredEventDetails(); + public Mono postReferenceEvents(List refEvents) throws JsonProcessingException; + + public Mono postValidationEvents(List valEvents) throws JsonProcessingException; public Mono removeReferenceEventsByEventId(List evids); + + public Mono removeValidationEventsByEventId(List evids); + + public Flux toggleValidationEventsByEventId(List evids); } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/SpectraClient.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/SpectraClient.java index 4df136a6..32cfbc05 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/SpectraClient.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/SpectraClient.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2018, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* Copyright (c) 2020, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory * CODE-743439. * All rights reserved. * This file is part of CCT. For details, see https://github.com/LLNL/coda-calibration-tool. @@ -29,5 +29,8 @@ public interface SpectraClient { public Mono getReferenceSpectra(String eventId); + public Mono getValidationSpectra(String eventId); + public Mono> getFitSpectra(String eventId); + } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/JsonTempFileWriter.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/JsonTempFileWriter.java index 69704037..5582a48b 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/JsonTempFileWriter.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/JsonTempFileWriter.java @@ -34,19 +34,20 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeType; -import com.fasterxml.jackson.databind.node.MissingNode; import com.fasterxml.jackson.databind.node.ObjectNode; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.CalibrationJsonConstants; import gov.llnl.gnem.apps.coda.calibration.gui.data.exporters.api.MeasuredMwTempFileWriter; import gov.llnl.gnem.apps.coda.calibration.gui.data.exporters.api.ParamTempFileWriter; import gov.llnl.gnem.apps.coda.calibration.gui.data.exporters.api.ReferenceMwTempFileWriter; +import gov.llnl.gnem.apps.coda.calibration.gui.data.exporters.api.ValidationMwTempFileWriter; import gov.llnl.gnem.apps.coda.calibration.model.domain.MdacParametersFI; import gov.llnl.gnem.apps.coda.calibration.model.domain.MdacParametersPS; import gov.llnl.gnem.apps.coda.calibration.model.domain.MeasuredMwDetails; import gov.llnl.gnem.apps.coda.calibration.model.domain.ReferenceMwParameters; import gov.llnl.gnem.apps.coda.calibration.model.domain.ShapeFitterConstraints; import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteFrequencyBandParameters; +import gov.llnl.gnem.apps.coda.calibration.model.domain.ValidationMwParameters; import gov.llnl.gnem.apps.coda.calibration.model.domain.VelocityConfiguration; import gov.llnl.gnem.apps.coda.calibration.model.domain.mixins.MdacFiFileMixin; import gov.llnl.gnem.apps.coda.calibration.model.domain.mixins.MdacPsFileMixin; @@ -54,12 +55,13 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.mixins.ShapeFitterConstraintsFileMixin; import gov.llnl.gnem.apps.coda.calibration.model.domain.mixins.SharedFrequencyBandParametersFileMixin; import gov.llnl.gnem.apps.coda.calibration.model.domain.mixins.SiteFrequencyBandParametersFileMixin; +import gov.llnl.gnem.apps.coda.calibration.model.domain.mixins.ValidationMwParametersFileMixin; import gov.llnl.gnem.apps.coda.common.model.domain.FrequencyBand; import gov.llnl.gnem.apps.coda.common.model.domain.SharedFrequencyBandParameters; import gov.llnl.gnem.apps.coda.common.model.domain.Station; @Component -public class JsonTempFileWriter implements ParamTempFileWriter, MeasuredMwTempFileWriter, ReferenceMwTempFileWriter { +public class JsonTempFileWriter implements ParamTempFileWriter, MeasuredMwTempFileWriter, ReferenceMwTempFileWriter, ValidationMwTempFileWriter { private static final Logger log = LoggerFactory.getLogger(JsonTempFileWriter.class); @@ -79,6 +81,7 @@ public JsonTempFileWriter() { mapper.addMixIn(ShapeFitterConstraints.class, ShapeFitterConstraintsFileMixin.class); mapper.addMixIn(MdacParametersFI.class, MdacFiFileMixin.class); mapper.addMixIn(MdacParametersPS.class, MdacPsFileMixin.class); + mapper.addMixIn(ValidationMwParameters.class, ValidationMwParametersFileMixin.class); } @Override @@ -103,6 +106,21 @@ public void writeReferenceMwParams(Path folder, List mws) } } + @Override + public void writeValidationMws(Path folder, List validationMws) { + writeValidationMws(folder, CALIBRATION_JSON_NAME, validationMws); + } + + @Override + public void writeValidationMws(Path folder, String filename, List validationMws) { + try { + JsonNode document = createOrGetDocument(folder, filename); + writeValidationEvents(createOrGetFile(folder, filename), document, validationMws); + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } + @Override public void writeMeasuredMws(Path folder, List measuredMwsDetails) { writeMeasuredMws(folder, MW_JSON_NAME, measuredMwsDetails); @@ -125,12 +143,12 @@ private void writeParams(File file, JsonNode document, Map>> siteBands = siteParameters.entrySet() .stream() - .collect( - Collectors.groupingBy( - e -> e.getKey().getNetworkName(), - Collectors.toMap( - e -> e.getKey().getStationName(), - e -> e.getValue().values().stream().collect(Collectors.toList())))); + .collect(Collectors.groupingBy(e -> e.getKey().getNetworkName(), + Collectors.toMap(e -> e.getKey().getStationName(), + e -> e.getValue() + .values() + .stream() + .collect(Collectors.toList())))); writeArrayNodeToFile(file, document, siteBands.entrySet(), CalibrationJsonConstants.SITE_CORRECTION_FIELD); } @@ -152,6 +170,10 @@ private void writeReferenceEvents(File file, JsonNode document, List validationMws) throws IOException { + writeArrayNodeToFile(file, document, validationMws, CalibrationJsonConstants.VALIDATION_EVENTS_FIELD); + } + private void writeMeasuredEvents(File file, JsonNode document, List measuredMwsDetails) throws IOException { writeArrayNodeToFile(file, document, measuredMwsDetails, CalibrationJsonConstants.MEASURED_EVENTS_FIELD); } @@ -208,7 +230,7 @@ private JsonNode createOrGetDocument(Path folder, String filename) throws JsonPr } else { rootNode = mapper.createObjectNode(); } - + if (rootNode == null || rootNode.getNodeType().equals(JsonNodeType.MISSING)) { rootNode = mapper.createObjectNode(); } @@ -217,7 +239,7 @@ private JsonNode createOrGetDocument(Path folder, String filename) throws JsonPr private File createOrGetFile(Path folder, String filename) throws IOException { Files.deleteIfExists(folder.resolve(filename)); - File file = Files.createFile(folder.resolve(filename)).toFile(); + File file = Files.createFile(folder.resolve(filename)).toFile(); return file; } } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/ParamExporter.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/ParamExporter.java index 0032b724..8d557060 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/ParamExporter.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/ParamExporter.java @@ -39,17 +39,19 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.EventClient; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ParameterClient; -import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ReferenceEventClient; import gov.llnl.gnem.apps.coda.calibration.gui.data.exporters.api.MeasuredMwTempFileWriter; import gov.llnl.gnem.apps.coda.calibration.gui.data.exporters.api.ParamTempFileWriter; import gov.llnl.gnem.apps.coda.calibration.gui.data.exporters.api.ReferenceMwTempFileWriter; +import gov.llnl.gnem.apps.coda.calibration.gui.data.exporters.api.ValidationMwTempFileWriter; import gov.llnl.gnem.apps.coda.calibration.model.domain.MdacParametersFI; import gov.llnl.gnem.apps.coda.calibration.model.domain.MdacParametersPS; import gov.llnl.gnem.apps.coda.calibration.model.domain.MeasuredMwDetails; import gov.llnl.gnem.apps.coda.calibration.model.domain.ReferenceMwParameters; import gov.llnl.gnem.apps.coda.calibration.model.domain.ShapeFitterConstraints; import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteFrequencyBandParameters; +import gov.llnl.gnem.apps.coda.calibration.model.domain.ValidationMwParameters; import gov.llnl.gnem.apps.coda.calibration.model.domain.VelocityConfiguration; import gov.llnl.gnem.apps.coda.common.model.domain.FrequencyBand; import gov.llnl.gnem.apps.coda.common.model.domain.SharedFrequencyBandParameters; @@ -63,19 +65,21 @@ public class ParamExporter { private ParameterClient paramClient; private List paramWriters; - private ReferenceEventClient eventClient; + private EventClient eventClient; private List mwWriters; private List referenceMwWriters; + private List validationMwWriters; @Autowired - public ParamExporter(ParameterClient paramClient, ReferenceEventClient eventClient, List paramWriters, List mwWriters, - List referenceMwWriters) { + public ParamExporter(ParameterClient paramClient, EventClient eventClient, List paramWriters, List mwWriters, + List referenceMwWriters, List validationMwWriters) { this.paramClient = paramClient; this.paramWriters = paramWriters; this.eventClient = eventClient; this.mwWriters = mwWriters; this.referenceMwWriters = referenceMwWriters; + this.validationMwWriters = validationMwWriters; } public File createExportArchive() throws IOException { @@ -132,6 +136,14 @@ public File createExportArchive() throws IOException { writer.writeReferenceMwParams(tmpFolder, referenceMws); } } + + if (validationMwWriters != null) { + List validationMws = new ArrayList<>(); + validationMws.addAll(eventClient.getValidationEvents().filter(Objects::nonNull).toStream().collect(Collectors.toList())); + for (ValidationMwTempFileWriter writer : validationMwWriters) { + writer.writeValidationMws(tmpFolder, validationMws); + } + } } File zipDir = File.createTempFile("zip-dir", "tmp"); diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/api/ValidationMwTempFileWriter.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/api/ValidationMwTempFileWriter.java new file mode 100644 index 00000000..d0836dc4 --- /dev/null +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/api/ValidationMwTempFileWriter.java @@ -0,0 +1,26 @@ +/* +* Copyright (c) 2020, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* CODE-743439. +* All rights reserved. +* This file is part of CCT. For details, see https://github.com/LLNL/coda-calibration-tool. +* +* Licensed under the Apache License, Version 2.0 (the “Licensee”); you may not use this file except in compliance with the License. You may obtain a copy of the License at: +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and limitations under the license. +* +* This work was performed under the auspices of the U.S. Department of Energy +* by Lawrence Livermore National Laboratory under Contract DE-AC52-07NA27344. +*/ +package gov.llnl.gnem.apps.coda.calibration.gui.data.exporters.api; + +import java.nio.file.Path; +import java.util.List; + +import gov.llnl.gnem.apps.coda.calibration.model.domain.ValidationMwParameters; + +public interface ValidationMwTempFileWriter { + public void writeValidationMws(Path folder, List validationMws); + + public void writeValidationMws(Path folder, String filename, List validationMws); +} diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting/CodaWaveformPlot.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting/CodaWaveformPlot.java index ab8bb26a..b5a991ef 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting/CodaWaveformPlot.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting/CodaWaveformPlot.java @@ -277,21 +277,25 @@ private void plotSynthetic(Waveform waveform, SyntheticCoda synth, final TimeT b if (startTime.lt(endTime)) { interpolatedSeries.cut(startTime, endTime); synthSeriesBeforeEndMarker.cut(startTime, endTime); - - TimeSeries diffSeis = interpolatedSeries.subtract(synthSeriesBeforeEndMarker); - int synthStartTimeShift = (int) (startTime.subtractD(beginTime) + 0.5); - double median = diffSeis.getMedian(); - - subplot.DeletePlotObject(legendRef); - subplot.AddPlotObject(createLegend(labelText + "Shift: " + dfmt4.format(median))); - subplot.AddPlotObject(createLine(synthStartTimeShift, median, synthSeriesBeforeEndMarker, Color.GREEN), PLOT_ORDERING.MODEL_FIT.getZOrder()); - - if (endTime.lt(synthSeriesRemaining.getEndtime())) { - synthSeriesRemaining.cutBefore(endTime); - int remainingStartTimeShift = (int) (endTime.subtractD(beginTime) + 0.5); - subplot.AddPlotObject(createLine(remainingStartTimeShift, median, synthSeriesRemaining, Color.GREEN, DEFAULT_LINE_WIDTH, PenStyle.DASH), PLOT_ORDERING.MODEL_FIT.getZOrder()); + if (synthSeriesBeforeEndMarker.getLength() > 1) { + TimeSeries diffSeis = interpolatedSeries.subtract(synthSeriesBeforeEndMarker); + int synthStartTimeShift = (int) (startTime.subtractD(beginTime) + 0.5); + double median = diffSeis.getMedian(); + + subplot.DeletePlotObject(legendRef); + subplot.AddPlotObject(createLegend(labelText + "Shift: " + dfmt4.format(median))); + subplot.AddPlotObject(createLine(synthStartTimeShift, median, synthSeriesBeforeEndMarker, Color.GREEN), PLOT_ORDERING.MODEL_FIT.getZOrder()); + + if (endTime.lt(synthSeriesRemaining.getEndtime())) { + synthSeriesRemaining.cutBefore(endTime); + int remainingStartTimeShift = (int) (endTime.subtractD(beginTime) + 0.5); + if (synthSeriesRemaining.getLength() > 1) { + subplot.AddPlotObject(createLine(remainingStartTimeShift, median, synthSeriesRemaining, Color.GREEN, DEFAULT_LINE_WIDTH, PenStyle.DASH), + PLOT_ORDERING.MODEL_FIT.getZOrder()); + } + } + repaint(); } - repaint(); } } } @@ -363,12 +367,11 @@ protected void handlePickMovedState(Object obj) { pick.setPickTimeSecFromOrigin((float) (vpl.getXval() - new TimeT(pick.getWaveform().getEvent().getOriginTime()).subtractD(new TimeT(pick.getWaveform().getBeginTime())))); if (pick.getPickName() != null && PICK_TYPES.F.getPhase().equalsIgnoreCase(pick.getPickName().trim())) { pick.getWaveform() - .setAssociatedPicks( - pick.getWaveform() - .getAssociatedPicks() - .stream() - .filter(p -> p.getPickName() != null && !PICK_TYPES.AP.getPhase().equalsIgnoreCase(p.getPickName().trim())) - .collect(Collectors.toList())); + .setAssociatedPicks(pick.getWaveform() + .getAssociatedPicks() + .stream() + .filter(p -> p.getPickName() != null && !PICK_TYPES.AP.getPhase().equalsIgnoreCase(p.getPickName().trim())) + .collect(Collectors.toList())); } waveformClient.postWaveform(pick.getWaveform()).subscribe(this::setWaveform); } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting/CodaWaveformPlotManager.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting/CodaWaveformPlotManager.java index 848b7c93..77f8be02 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting/CodaWaveformPlotManager.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting/CodaWaveformPlotManager.java @@ -91,7 +91,7 @@ public class CodaWaveformPlotManager extends JPanel { @Override public void actionPerformed(ActionEvent e) { - if (currentPage < totalPages) { + if ((currentPage + 1) < totalPages) { currentPage++; loadWaveformsForPage(currentPage); } @@ -240,7 +240,12 @@ public void setOrderedWaveformIDs(List waveformIDs) { allWaveformIDs.add(waveformIDs.get(i)); } if (waveformIDs.size() > pageSize) { - totalPages = (int) ((waveformIDs.size() - 1) / pageSize); + double page = waveformIDs.size() / (double) pageSize; + if (page % 1.0 > 0.001) { + totalPages = (int) (page + 1.0); + } else { + totalPages = (int) (page); + } } else { totalPages = 1; } @@ -270,7 +275,7 @@ private void loadWaveformsForPage(int pageNumber) { results.add(createPlot(waveformClient.getWaveformFromId(allWaveformIDs.get(0)).publishOn(Schedulers.elastic()).block(Duration.ofSeconds(10)))); } } else { - pagingLabel.setText(pageNumber + 1 + "/" + (totalPages + 1)); + pagingLabel.setText(pageNumber + 1 + "/" + totalPages); List pageIds = new ArrayList<>(pageSize.intValue()); long skipVal = pageNumber * pageSize; if (skipVal != 0 && allWaveformIDs.size() > pageSize && allWaveformIDs.size() - skipVal < pageSize) { diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting/SpectralPlot.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting/SpectralPlot.java index a2e7cf50..0be3b579 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting/SpectralPlot.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting/SpectralPlot.java @@ -208,6 +208,9 @@ private void plotSpectraObject(JSubplot jsubplot, Spectra spectra, Legend legend case REF: line = new Line(x, y, Color.BLACK, PaintMode.COPY, PenStyle.DASH, 2); break; + case VAL: + line = new Line(x, y, Color.BLUE, PaintMode.COPY, PenStyle.DASHDOT, 2); + break; case UQ1: line = new Line(x, y, Color.LIGHT_GRAY, PaintMode.COPY, PenStyle.DASH, 2); break; diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/util/Axis.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/util/Axis.java new file mode 100644 index 00000000..930cbdec --- /dev/null +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/util/Axis.java @@ -0,0 +1,18 @@ +/* +* Copyright (c) 2020, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* CODE-743439. +* All rights reserved. +* +* Licensed under the Apache License, Version 2.0 (the “Licensee”); you may not use this file except in compliance with the License. You may obtain a copy of the License at: +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and limitations under the license. +* +* This work was performed under the auspices of the U.S. Department of Energy +* by Lawrence Livermore National Laboratory under Contract DE-AC52-07NA27344. +*/ +package gov.llnl.gnem.apps.coda.calibration.gui.util; + +public enum Axis { + X, Y; +} diff --git a/calibration-gui/src/main/resources/fxml/Data.fxml b/calibration-gui/src/main/resources/fxml/Data.fxml index be063020..980e75db 100644 --- a/calibration-gui/src/main/resources/fxml/Data.fxml +++ b/calibration-gui/src/main/resources/fxml/Data.fxml @@ -25,6 +25,7 @@ + diff --git a/calibration-gui/src/main/resources/fxml/MeasuredMws.fxml b/calibration-gui/src/main/resources/fxml/MeasuredMws.fxml index e513f701..eba18b79 100644 --- a/calibration-gui/src/main/resources/fxml/MeasuredMws.fxml +++ b/calibration-gui/src/main/resources/fxml/MeasuredMws.fxml @@ -4,7 +4,9 @@ + + @@ -18,13 +20,14 @@ - + - + @@ -41,31 +44,30 @@ - + - - + - - - - - - + + + + + + @@ -88,7 +90,7 @@ - + @@ -97,36 +99,87 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/calibration-gui/src/main/resources/fxml/Site.fxml b/calibration-gui/src/main/resources/fxml/Site.fxml index f963a3af..b787f03e 100644 --- a/calibration-gui/src/main/resources/fxml/Site.fxml +++ b/calibration-gui/src/main/resources/fxml/Site.fxml @@ -20,7 +20,8 @@ - + @@ -43,30 +44,30 @@ - + - + - - - - - - + + + + + + @@ -160,35 +161,36 @@ - - + - + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + + diff --git a/calibration-gui/src/test/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/CodaJsonParamLoaderTest.java b/calibration-gui/src/test/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/CodaJsonParamLoaderTest.java index f6d7398c..eed5b4c0 100644 --- a/calibration-gui/src/test/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/CodaJsonParamLoaderTest.java +++ b/calibration-gui/src/test/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/CodaJsonParamLoaderTest.java @@ -32,6 +32,7 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.ReferenceMwParameters; import gov.llnl.gnem.apps.coda.calibration.model.domain.ShapeFitterConstraints; import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteCorrections; +import gov.llnl.gnem.apps.coda.calibration.model.domain.ValidationMwParameters; import gov.llnl.gnem.apps.coda.common.model.domain.SharedFrequencyBandParameters; import gov.llnl.gnem.apps.coda.common.model.messaging.Result; import reactor.core.publisher.Flux; @@ -116,6 +117,16 @@ public final void testRefMw(String filePath) throws Exception { Long.valueOf(2l), results.filter(r -> r.isSuccess() && r.getResultPayload().orElse(null) instanceof ReferenceMwParameters).count().block()); } + + @ParameterizedTest + @MethodSource("filePaths") + public final void testValidationMw(String filePath) throws Exception { + Flux> results = convertFile(filePath); + Assert.assertEquals( + "Expected to have 2 valid validation event definitions", + Long.valueOf(2l), + results.filter(r -> r.isSuccess() && r.getResultPayload().orElse(null) instanceof ValidationMwParameters).count().block()); + } @ParameterizedTest @MethodSource("filePaths") diff --git a/calibration-gui/src/test/resources/calibration-params-test.json b/calibration-gui/src/test/resources/calibration-params-test.json index cf2bce7a..86caf0b6 100644 --- a/calibration-gui/src/test/resources/calibration-params-test.json +++ b/calibration-gui/src/test/resources/calibration-params-test.json @@ -1,545 +1,546 @@ { - "schemaVersion": 1, - "type": "llnl/coda-calibration-tool", - "bands": [ - { - "lowFreqHz": 0.02, - "highFreqHz": 0.03, - "minWindowLengthSec": 100, - "maxWindowLengthSec": 1000, - "snrThresholdAboveNoiseLog10": 0.5, - "measurementTimeSec": 100.0, - "velocity0": 1, - "velocity1": 2, - "velocity2": 3, - "beta0": 4, - "beta1": 5, - "beta2": 6, - "gamma0": 7, - "gamma1": 8, - "gamma2": 9, - "p1": 10, - "p2": 11, - "xc": 12, - "xt": 13, - "q": 14 - }, - { - "lowFreqHz": 0.03, - "highFreqHz": 0.05, - "minWindowLengthSec": 100, - "maxWindowLengthSec": 800, - "snrThresholdAboveNoiseLog10": 0.5 - }, - { - "lowFreqHz": 0.05, - "highFreqHz": 0.1, - "minWindowLengthSec": 75, - "maxWindowLengthSec": 600, - "snrThresholdAboveNoiseLog10": 0.5 - }, - { - "lowFreqHz": 0.1, - "highFreqHz": 0.2, - "minWindowLengthSec": 75, - "maxWindowLengthSec": 550, - "snrThresholdAboveNoiseLog10": 0.5 - }, - { - "lowFreqHz": 0.2, - "highFreqHz": 0.3, - "minWindowLengthSec": 50, - "maxWindowLengthSec": 550, - "snrThresholdAboveNoiseLog10": 0.5 - }, - { - "lowFreqHz": 0.3, - "highFreqHz": 0.5, - "minWindowLengthSec": 50, - "maxWindowLengthSec": 500, - "snrThresholdAboveNoiseLog10": 0.5 - }, - { - "lowFreqHz": 0.5, - "highFreqHz": 0.7, - "minWindowLengthSec": 50, - "maxWindowLengthSec": 500, - "snrThresholdAboveNoiseLog10": 0.5 - }, - { - "lowFreqHz": 0.7, - "highFreqHz": 1.0, - "minWindowLengthSec": 40, - "maxWindowLengthSec": 450, - "snrThresholdAboveNoiseLog10": 0.5 - }, - { - "lowFreqHz": 1.0, - "highFreqHz": 1.5, - "minWindowLengthSec": 40, - "maxWindowLengthSec": 450, - "snrThresholdAboveNoiseLog10": 0.5 - }, - { - "lowFreqHz": 1.5, - "highFreqHz": 2.0, - "minWindowLengthSec": 40, - "maxWindowLengthSec": 400, - "snrThresholdAboveNoiseLog10": 0.5 - }, - { - "lowFreqHz": 2.0, - "highFreqHz": 3.0, - "minWindowLengthSec": 40, - "maxWindowLengthSec": 400, - "snrThresholdAboveNoiseLog10": 0.5 - }, - { - "lowFreqHz": 3.0, - "highFreqHz": 4.0, - "minWindowLengthSec": 40, - "maxWindowLengthSec": 400, - "snrThresholdAboveNoiseLog10": 0.5 - }, - { - "lowFreqHz": 4.0, - "highFreqHz": 6.0, - "minWindowLengthSec": 40, - "maxWindowLengthSec": 400, - "snrThresholdAboveNoiseLog10": 0.5 - }, - { - "lowFreqHz": 6.0, - "highFreqHz": 8.0, - "minWindowLengthSec": 40, - "maxWindowLengthSec": 350, - "snrThresholdAboveNoiseLog10": 0.5 - } - ], - "mdac-fi": { - "alphaR": 5000, - "alphas": 6000, - "betas": 3500, - "betaR": 2900, - "sigma": 0.3, - "delSigma": 98.0, - "psi": 0.25, - "delPsi": 99.0, - "zeta": 1.0, - "m0ref": 10000000000000000, - "radPatP": 0.44, - "radPatS": 0.6, - "rhor": 2500, - "rhos": 2700 - }, - "mdac-ps": [ - { - "phase": "Pn", - "q0": 210, - "delQ0": 100, - "gamma0": 0.65, - "delGamma0": 101, - "u0": 7900, - "eta": 1.1, - "delEta": 102, - "distCrit": 0.001, - "snr": 2 - }, - { - "phase": "Pg", - "q0": 190, - "delQ0": 0, - "gamma0": 0.45, - "delGamma0": 0, - "u0": 6000, - "eta": 0.5, - "delEta": 0, - "distCrit": 100, - "snr": 2 - }, - { - "phase": "Sn", - "q0": 590, - "delQ0": 0, - "gamma0": 0.55, - "delGamma0": 0, - "u0": 4500, - "eta": 1.1, - "delEta": 0, - "distCrit": 0.001, - "snr": 2 - }, - { - "phase": "Lg", - "q0": 200, - "delQ0": 0, - "gamma0": 0.54, - "delGamma0": 0, - "u0": 3500, - "eta": 0.5, - "delEta": 0, - "distCrit": 100, - "snr": 2 - } - ], - "reference-events": [ - { - "eventId": "0331199924", - "refMw": 3.0 - }, - { - "eventId": "0401199924", - "refMw": 5.0, - "apparentStressInMpa": 0.7 - } - ], - "shape-constraints" : { - "maxVP1" : 1600.0, - "minVP1" : 150.0, - "v0reg" : 1100.0, - "maxVP2" : 15000.0, - "minVP2" : 11.0, - "maxVP3" : 15000.0, - "minVP3" : 11.0, - "maxBP1" : 11000.0, - "minBP1" : -1500.0, - "b0reg" : 110000.0, - "maxBP2" : 120.0, - "minBP2" : 10.1, - "maxBP3" : 11500.0, - "minBP3" : 11.0E-4, - "maxGP1" : 1100.0, - "minGP1" : 10.0, - "g0reg" : 1100.0, - "maxGP2" : 1101.0, - "minGP2" : 10.0, - "g1reg" : -11.0, - "maxGP3" : 1101.0, - "minGP3" : 11.0, - "yvvMin" : 10.5, - "yvvMax" : 16.01, - "vDistMax" : 11600.0, - "vDistMin" : 10.0, - "ybbMin" : -10.12, - "ybbMax" : 15.0E-4, - "bDistMax" : 11550.0, - "bDistMin" : 10.0, - "yggMin" : 10.01, - "yggMax" : 1100.0, - "gDistMin" : 1600.0, - "gDistMax" : 10.0, - "minIntercept" : 10.001, - "maxIntercept" : 120.0, - "minBeta" : -14.0, - "maxBeta" : -11.0E-4, - "minGamma" : 10.001, - "maxGamma" : 14.0, - "iterations" : 110 - }, - "site-corrections": [ - { - "BK": { - "SAO": [ - { - "siteTerm": 19.160301172988373, - "lowFreqHz": 0.2, - "highFreqHz": 0.3 - }, - { - "siteTerm": 19.160301172988373, - "lowFreqHz": 0.2, - "highFreqHz": 0.3 - }, - { - "siteTerm": 19.078495953084072, - "lowFreqHz": 0.3, - "highFreqHz": 0.5 - }, - { - "siteTerm": 19.00135341977889, - "lowFreqHz": 0.5, - "highFreqHz": 0.7 - }, - { - "siteTerm": 19.03492718945587, - "lowFreqHz": 0.7, - "highFreqHz": 1.0 - }, - { - "siteTerm": 18.94226636451329, - "lowFreqHz": 1.0, - "highFreqHz": 1.5 - }, - { - "siteTerm": 18.92723226138862, - "lowFreqHz": 1.5, - "highFreqHz": 2.0 - }, - { - "siteTerm": 19.184367156400697, - "lowFreqHz": 2.0, - "highFreqHz": 3.0 - }, - { - "siteTerm": 19.14718589386693, - "lowFreqHz": 3.0, - "highFreqHz": 4.0 - }, - { - "siteTerm": 19.211116316565025, - "lowFreqHz": 4.0, - "highFreqHz": 6.0 - }, - { - "siteTerm": 19.57881986308872, - "lowFreqHz": 6.0, - "highFreqHz": 8.0 - }, - { - "siteTerm": 20.164195454405423, - "lowFreqHz": 8.0, - "highFreqHz": 10.0 - }, - { - "siteTerm": 20.325371990356185, - "lowFreqHz": 10.0, - "highFreqHz": 15.0 - }, - { - "siteTerm": 21.24328806924078, - "lowFreqHz": 15.0, - "highFreqHz": 20.0 - }, - { - "siteTerm": 21.48709133874192, - "lowFreqHz": 20.0, - "highFreqHz": 25.0 - } - ], - "CVS": [ - { - "siteTerm": 18.99512062088609, - "lowFreqHz": 0.2, - "highFreqHz": 0.3 - }, - { - "siteTerm": 18.712207283591184, - "lowFreqHz": 0.3, - "highFreqHz": 0.5 - }, - { - "siteTerm": 18.688751493057524, - "lowFreqHz": 0.5, - "highFreqHz": 0.7 - }, - { - "siteTerm": 18.84134477372329, - "lowFreqHz": 0.7, - "highFreqHz": 1.0 - }, - { - "siteTerm": 18.891154656359777, - "lowFreqHz": 1.0, - "highFreqHz": 1.5 - }, - { - "siteTerm": 18.82400240637313, - "lowFreqHz": 1.5, - "highFreqHz": 2.0 - }, - { - "siteTerm": 18.949633953462328, - "lowFreqHz": 2.0, - "highFreqHz": 3.0 - }, - { - "siteTerm": 18.961351413110204, - "lowFreqHz": 3.0, - "highFreqHz": 4.0 - }, - { - "siteTerm": 19.06547621563001, - "lowFreqHz": 4.0, - "highFreqHz": 6.0 - }, - { - "siteTerm": 19.591903909961985, - "lowFreqHz": 6.0, - "highFreqHz": 8.0 - }, - { - "siteTerm": 20.181175758798673, - "lowFreqHz": 8.0, - "highFreqHz": 10.0 - }, - { - "siteTerm": 20.371678739288434, - "lowFreqHz": 10.0, - "highFreqHz": 15.0 - }, - { - "siteTerm": 21.34581922180849, - "lowFreqHz": 15.0, - "highFreqHz": 20.0 - }, - { - "siteTerm": 21.607084224674125, - "lowFreqHz": 20.0, - "highFreqHz": 25.0 - } - ], - "WENL": [ - { - "siteTerm": 18.736694993008697, - "lowFreqHz": 0.2, - "highFreqHz": 0.3 - }, - { - "siteTerm": 18.6085082031463, - "lowFreqHz": 0.3, - "highFreqHz": 0.5 - }, - { - "siteTerm": 18.580578107370048, - "lowFreqHz": 0.5, - "highFreqHz": 0.7 - }, - { - "siteTerm": 18.661130492426334, - "lowFreqHz": 0.7, - "highFreqHz": 1.0 - }, - { - "siteTerm": 18.587026724834214, - "lowFreqHz": 1.0, - "highFreqHz": 1.5 - }, - { - "siteTerm": 18.495225296106195, - "lowFreqHz": 1.5, - "highFreqHz": 2.0 - }, - { - "siteTerm": 18.802400569430816, - "lowFreqHz": 2.0, - "highFreqHz": 3.0 - }, - { - "siteTerm": 19.062474655337304, - "lowFreqHz": 3.0, - "highFreqHz": 4.0 - }, - { - "siteTerm": 19.293388411261628, - "lowFreqHz": 4.0, - "highFreqHz": 6.0 - }, - { - "siteTerm": 19.927795134546052, - "lowFreqHz": 6.0, - "highFreqHz": 8.0 - }, - { - "siteTerm": 20.71777025105482, - "lowFreqHz": 8.0, - "highFreqHz": 10.0 - }, - { - "siteTerm": 20.95605674566051, - "lowFreqHz": 10.0, - "highFreqHz": 15.0 - }, - { - "siteTerm": 21.977061937887687, - "lowFreqHz": 15.0, - "highFreqHz": 20.0 - }, - { - "siteTerm": 22.434419365054662, - "lowFreqHz": 20.0, - "highFreqHz": 25.0 - } - ] - }, - "UNK": { - "SAO": [ - { - "siteTerm": 19.160301172988373, - "lowFreqHz": 0.2, - "highFreqHz": 0.3 - }, - { - "siteTerm": 19.160301172988373, - "lowFreqHz": 0.2, - "highFreqHz": 0.3 - }, - { - "siteTerm": 19.078495953084072, - "lowFreqHz": 0.3, - "highFreqHz": 0.5 - }, - { - "siteTerm": 19.00135341977889, - "lowFreqHz": 0.5, - "highFreqHz": 0.7 - }, - { - "siteTerm": 19.03492718945587, - "lowFreqHz": 0.7, - "highFreqHz": 1.0 - }, - { - "siteTerm": 18.94226636451329, - "lowFreqHz": 1.0, - "highFreqHz": 1.5 - }, - { - "siteTerm": 18.92723226138862, - "lowFreqHz": 1.5, - "highFreqHz": 2.0 - }, - { - "siteTerm": 19.184367156400697, - "lowFreqHz": 2.0, - "highFreqHz": 3.0 - }, - { - "siteTerm": 19.14718589386693, - "lowFreqHz": 3.0, - "highFreqHz": 4.0 - }, - { - "siteTerm": 19.211116316565025, - "lowFreqHz": 4.0, - "highFreqHz": 6.0 - }, - { - "siteTerm": 19.57881986308872, - "lowFreqHz": 6.0, - "highFreqHz": 8.0 - }, - { - "siteTerm": 20.164195454405423, - "lowFreqHz": 8.0, - "highFreqHz": 10.0 - }, - { - "siteTerm": 20.325371990356185, - "lowFreqHz": 10.0, - "highFreqHz": 15.0 - }, - { - "siteTerm": 21.24328806924078, - "lowFreqHz": 15.0, - "highFreqHz": 20.0 - }, - { - "siteTerm": 21.48709133874192, - "lowFreqHz": 20.0, - "highFreqHz": 25.0 - } - ] - } - } - ] + "schemaVersion": 1, + "type": "llnl/coda-calibration-tool", + "bands": [{ + "lowFreqHz": 0.02, + "highFreqHz": 0.03, + "minWindowLengthSec": 100, + "maxWindowLengthSec": 1000, + "snrThresholdAboveNoiseLog10": 0.5, + "measurementTimeSec": 100.0, + "velocity0": 1, + "velocity1": 2, + "velocity2": 3, + "beta0": 4, + "beta1": 5, + "beta2": 6, + "gamma0": 7, + "gamma1": 8, + "gamma2": 9, + "p1": 10, + "p2": 11, + "xc": 12, + "xt": 13, + "q": 14 + }, + { + "lowFreqHz": 0.03, + "highFreqHz": 0.05, + "minWindowLengthSec": 100, + "maxWindowLengthSec": 800, + "snrThresholdAboveNoiseLog10": 0.5 + }, + { + "lowFreqHz": 0.05, + "highFreqHz": 0.1, + "minWindowLengthSec": 75, + "maxWindowLengthSec": 600, + "snrThresholdAboveNoiseLog10": 0.5 + }, + { + "lowFreqHz": 0.1, + "highFreqHz": 0.2, + "minWindowLengthSec": 75, + "maxWindowLengthSec": 550, + "snrThresholdAboveNoiseLog10": 0.5 + }, + { + "lowFreqHz": 0.2, + "highFreqHz": 0.3, + "minWindowLengthSec": 50, + "maxWindowLengthSec": 550, + "snrThresholdAboveNoiseLog10": 0.5 + }, + { + "lowFreqHz": 0.3, + "highFreqHz": 0.5, + "minWindowLengthSec": 50, + "maxWindowLengthSec": 500, + "snrThresholdAboveNoiseLog10": 0.5 + }, + { + "lowFreqHz": 0.5, + "highFreqHz": 0.7, + "minWindowLengthSec": 50, + "maxWindowLengthSec": 500, + "snrThresholdAboveNoiseLog10": 0.5 + }, + { + "lowFreqHz": 0.7, + "highFreqHz": 1.0, + "minWindowLengthSec": 40, + "maxWindowLengthSec": 450, + "snrThresholdAboveNoiseLog10": 0.5 + }, + { + "lowFreqHz": 1.0, + "highFreqHz": 1.5, + "minWindowLengthSec": 40, + "maxWindowLengthSec": 450, + "snrThresholdAboveNoiseLog10": 0.5 + }, + { + "lowFreqHz": 1.5, + "highFreqHz": 2.0, + "minWindowLengthSec": 40, + "maxWindowLengthSec": 400, + "snrThresholdAboveNoiseLog10": 0.5 + }, + { + "lowFreqHz": 2.0, + "highFreqHz": 3.0, + "minWindowLengthSec": 40, + "maxWindowLengthSec": 400, + "snrThresholdAboveNoiseLog10": 0.5 + }, + { + "lowFreqHz": 3.0, + "highFreqHz": 4.0, + "minWindowLengthSec": 40, + "maxWindowLengthSec": 400, + "snrThresholdAboveNoiseLog10": 0.5 + }, + { + "lowFreqHz": 4.0, + "highFreqHz": 6.0, + "minWindowLengthSec": 40, + "maxWindowLengthSec": 400, + "snrThresholdAboveNoiseLog10": 0.5 + }, + { + "lowFreqHz": 6.0, + "highFreqHz": 8.0, + "minWindowLengthSec": 40, + "maxWindowLengthSec": 350, + "snrThresholdAboveNoiseLog10": 0.5 + } + ], + "mdac-fi": { + "alphaR": 5000, + "alphas": 6000, + "betas": 3500, + "betaR": 2900, + "sigma": 0.3, + "delSigma": 98.0, + "psi": 0.25, + "delPsi": 99.0, + "zeta": 1.0, + "m0ref": 10000000000000000, + "radPatP": 0.44, + "radPatS": 0.6, + "rhor": 2500, + "rhos": 2700 + }, + "mdac-ps": [{ + "phase": "Pn", + "q0": 210, + "delQ0": 100, + "gamma0": 0.65, + "delGamma0": 101, + "u0": 7900, + "eta": 1.1, + "delEta": 102, + "distCrit": 0.001, + "snr": 2 + }, + { + "phase": "Pg", + "q0": 190, + "delQ0": 0, + "gamma0": 0.45, + "delGamma0": 0, + "u0": 6000, + "eta": 0.5, + "delEta": 0, + "distCrit": 100, + "snr": 2 + }, + { + "phase": "Sn", + "q0": 590, + "delQ0": 0, + "gamma0": 0.55, + "delGamma0": 0, + "u0": 4500, + "eta": 1.1, + "delEta": 0, + "distCrit": 0.001, + "snr": 2 + }, + { + "phase": "Lg", + "q0": 200, + "delQ0": 0, + "gamma0": 0.54, + "delGamma0": 0, + "u0": 3500, + "eta": 0.5, + "delEta": 0, + "distCrit": 100, + "snr": 2 + } + ], + "reference-events": [{ + "eventId": "0331199924", + "refMw": 3.0 + }, + { + "eventId": "0401199924", + "refMw": 5.0, + "apparentStressInMpa": 0.7 + } + ], + "validation-events": [{ + "eventId": "0331199924", + "mw": 3.2 + }, + { + "eventId": "0401199924", + "mw": 5.2, + "apparentStressInMpa": 0.7 + } + ], + "shape-constraints": { + "maxVP1": 1600.0, + "minVP1": 150.0, + "v0reg": 1100.0, + "maxVP2": 15000.0, + "minVP2": 11.0, + "maxVP3": 15000.0, + "minVP3": 11.0, + "maxBP1": 11000.0, + "minBP1": -1500.0, + "b0reg": 110000.0, + "maxBP2": 120.0, + "minBP2": 10.1, + "maxBP3": 11500.0, + "minBP3": 11.0E-4, + "maxGP1": 1100.0, + "minGP1": 10.0, + "g0reg": 1100.0, + "maxGP2": 1101.0, + "minGP2": 10.0, + "g1reg": -11.0, + "maxGP3": 1101.0, + "minGP3": 11.0, + "yvvMin": 10.5, + "yvvMax": 16.01, + "vDistMax": 11600.0, + "vDistMin": 10.0, + "ybbMin": -10.12, + "ybbMax": 15.0E-4, + "bDistMax": 11550.0, + "bDistMin": 10.0, + "yggMin": 10.01, + "yggMax": 1100.0, + "gDistMin": 1600.0, + "gDistMax": 10.0, + "minIntercept": 10.001, + "maxIntercept": 120.0, + "minBeta": -14.0, + "maxBeta": -11.0E-4, + "minGamma": 10.001, + "maxGamma": 14.0, + "iterations": 110 + }, + "site-corrections": [{ + "BK": { + "SAO": [{ + "siteTerm": 19.160301172988373, + "lowFreqHz": 0.2, + "highFreqHz": 0.3 + }, + { + "siteTerm": 19.160301172988373, + "lowFreqHz": 0.2, + "highFreqHz": 0.3 + }, + { + "siteTerm": 19.078495953084072, + "lowFreqHz": 0.3, + "highFreqHz": 0.5 + }, + { + "siteTerm": 19.00135341977889, + "lowFreqHz": 0.5, + "highFreqHz": 0.7 + }, + { + "siteTerm": 19.03492718945587, + "lowFreqHz": 0.7, + "highFreqHz": 1.0 + }, + { + "siteTerm": 18.94226636451329, + "lowFreqHz": 1.0, + "highFreqHz": 1.5 + }, + { + "siteTerm": 18.92723226138862, + "lowFreqHz": 1.5, + "highFreqHz": 2.0 + }, + { + "siteTerm": 19.184367156400697, + "lowFreqHz": 2.0, + "highFreqHz": 3.0 + }, + { + "siteTerm": 19.14718589386693, + "lowFreqHz": 3.0, + "highFreqHz": 4.0 + }, + { + "siteTerm": 19.211116316565025, + "lowFreqHz": 4.0, + "highFreqHz": 6.0 + }, + { + "siteTerm": 19.57881986308872, + "lowFreqHz": 6.0, + "highFreqHz": 8.0 + }, + { + "siteTerm": 20.164195454405423, + "lowFreqHz": 8.0, + "highFreqHz": 10.0 + }, + { + "siteTerm": 20.325371990356185, + "lowFreqHz": 10.0, + "highFreqHz": 15.0 + }, + { + "siteTerm": 21.24328806924078, + "lowFreqHz": 15.0, + "highFreqHz": 20.0 + }, + { + "siteTerm": 21.48709133874192, + "lowFreqHz": 20.0, + "highFreqHz": 25.0 + } + ], + "CVS": [{ + "siteTerm": 18.99512062088609, + "lowFreqHz": 0.2, + "highFreqHz": 0.3 + }, + { + "siteTerm": 18.712207283591184, + "lowFreqHz": 0.3, + "highFreqHz": 0.5 + }, + { + "siteTerm": 18.688751493057524, + "lowFreqHz": 0.5, + "highFreqHz": 0.7 + }, + { + "siteTerm": 18.84134477372329, + "lowFreqHz": 0.7, + "highFreqHz": 1.0 + }, + { + "siteTerm": 18.891154656359777, + "lowFreqHz": 1.0, + "highFreqHz": 1.5 + }, + { + "siteTerm": 18.82400240637313, + "lowFreqHz": 1.5, + "highFreqHz": 2.0 + }, + { + "siteTerm": 18.949633953462328, + "lowFreqHz": 2.0, + "highFreqHz": 3.0 + }, + { + "siteTerm": 18.961351413110204, + "lowFreqHz": 3.0, + "highFreqHz": 4.0 + }, + { + "siteTerm": 19.06547621563001, + "lowFreqHz": 4.0, + "highFreqHz": 6.0 + }, + { + "siteTerm": 19.591903909961985, + "lowFreqHz": 6.0, + "highFreqHz": 8.0 + }, + { + "siteTerm": 20.181175758798673, + "lowFreqHz": 8.0, + "highFreqHz": 10.0 + }, + { + "siteTerm": 20.371678739288434, + "lowFreqHz": 10.0, + "highFreqHz": 15.0 + }, + { + "siteTerm": 21.34581922180849, + "lowFreqHz": 15.0, + "highFreqHz": 20.0 + }, + { + "siteTerm": 21.607084224674125, + "lowFreqHz": 20.0, + "highFreqHz": 25.0 + } + ], + "WENL": [{ + "siteTerm": 18.736694993008697, + "lowFreqHz": 0.2, + "highFreqHz": 0.3 + }, + { + "siteTerm": 18.6085082031463, + "lowFreqHz": 0.3, + "highFreqHz": 0.5 + }, + { + "siteTerm": 18.580578107370048, + "lowFreqHz": 0.5, + "highFreqHz": 0.7 + }, + { + "siteTerm": 18.661130492426334, + "lowFreqHz": 0.7, + "highFreqHz": 1.0 + }, + { + "siteTerm": 18.587026724834214, + "lowFreqHz": 1.0, + "highFreqHz": 1.5 + }, + { + "siteTerm": 18.495225296106195, + "lowFreqHz": 1.5, + "highFreqHz": 2.0 + }, + { + "siteTerm": 18.802400569430816, + "lowFreqHz": 2.0, + "highFreqHz": 3.0 + }, + { + "siteTerm": 19.062474655337304, + "lowFreqHz": 3.0, + "highFreqHz": 4.0 + }, + { + "siteTerm": 19.293388411261628, + "lowFreqHz": 4.0, + "highFreqHz": 6.0 + }, + { + "siteTerm": 19.927795134546052, + "lowFreqHz": 6.0, + "highFreqHz": 8.0 + }, + { + "siteTerm": 20.71777025105482, + "lowFreqHz": 8.0, + "highFreqHz": 10.0 + }, + { + "siteTerm": 20.95605674566051, + "lowFreqHz": 10.0, + "highFreqHz": 15.0 + }, + { + "siteTerm": 21.977061937887687, + "lowFreqHz": 15.0, + "highFreqHz": 20.0 + }, + { + "siteTerm": 22.434419365054662, + "lowFreqHz": 20.0, + "highFreqHz": 25.0 + } + ] + }, + "UNK": { + "SAO": [{ + "siteTerm": 19.160301172988373, + "lowFreqHz": 0.2, + "highFreqHz": 0.3 + }, + { + "siteTerm": 19.160301172988373, + "lowFreqHz": 0.2, + "highFreqHz": 0.3 + }, + { + "siteTerm": 19.078495953084072, + "lowFreqHz": 0.3, + "highFreqHz": 0.5 + }, + { + "siteTerm": 19.00135341977889, + "lowFreqHz": 0.5, + "highFreqHz": 0.7 + }, + { + "siteTerm": 19.03492718945587, + "lowFreqHz": 0.7, + "highFreqHz": 1.0 + }, + { + "siteTerm": 18.94226636451329, + "lowFreqHz": 1.0, + "highFreqHz": 1.5 + }, + { + "siteTerm": 18.92723226138862, + "lowFreqHz": 1.5, + "highFreqHz": 2.0 + }, + { + "siteTerm": 19.184367156400697, + "lowFreqHz": 2.0, + "highFreqHz": 3.0 + }, + { + "siteTerm": 19.14718589386693, + "lowFreqHz": 3.0, + "highFreqHz": 4.0 + }, + { + "siteTerm": 19.211116316565025, + "lowFreqHz": 4.0, + "highFreqHz": 6.0 + }, + { + "siteTerm": 19.57881986308872, + "lowFreqHz": 6.0, + "highFreqHz": 8.0 + }, + { + "siteTerm": 20.164195454405423, + "lowFreqHz": 8.0, + "highFreqHz": 10.0 + }, + { + "siteTerm": 20.325371990356185, + "lowFreqHz": 10.0, + "highFreqHz": 15.0 + }, + { + "siteTerm": 21.24328806924078, + "lowFreqHz": 15.0, + "highFreqHz": 20.0 + }, + { + "siteTerm": 21.48709133874192, + "lowFreqHz": 20.0, + "highFreqHz": 25.0 + } + ] + } + }] } \ No newline at end of file diff --git a/calibration-service/calibration-application/pom.xml b/calibration-service/calibration-application/pom.xml index 379e7de2..15316612 100644 --- a/calibration-service/calibration-application/pom.xml +++ b/calibration-service/calibration-application/pom.xml @@ -1,11 +1,11 @@ - + gov.llnl.gnem.apps.coda.calibration calibration-service - 1.0.8.1 + 1.0.9 4.0.0 @@ -77,14 +77,6 @@ org.springframework spring-webmvc - - io.springlets - springlets-data-jpa - - - io.springlets - springlets-data-commons - org.springframework.boot spring-boot-starter-actuator diff --git a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/CalibrationJsonController.java b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/CalibrationJsonController.java index 65783e0a..7d1c5eef 100644 --- a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/CalibrationJsonController.java +++ b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/CalibrationJsonController.java @@ -14,11 +14,19 @@ */ package gov.llnl.gnem.apps.coda.calibration.application.web; +import java.util.List; + +import javax.validation.Valid; + import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -47,6 +55,15 @@ public ResponseEntity runCalibration(@PathVariable(name = "autoPickingEnabled } } + @PostMapping(value = "/cancel", name = "cancelCalibration") + public ResponseEntity cancelCalibration(@Valid @RequestBody Long id, BindingResult result) { + if (getService().cancelCalibration(id)) { + return ResponseEntity.ok().build(); + } else { + return ResponseEntity.badRequest().build(); + } + } + @GetMapping(value = "/clear-data", name = "clearData") public ResponseEntity clearData() { if (getService().clearData()) { @@ -55,7 +72,15 @@ public ResponseEntity clearData() { return ResponseEntity.badRequest().build(); } } - + + //TODO: A little gross API wise to cram this here but will do for now. Revisit in V2 + @PostMapping(value = "/toggle-validation/batch-by-evids", name = "toggleValidationByEvids") + public ResponseEntity deleteBatchByEvids(@Valid @RequestBody List eventIds, BindingResult result) { + if (result.hasErrors()) { + return ResponseEntity.status(HttpStatus.CONFLICT).body(result); + } + return ResponseEntity.ok(service.toggleAllByEventIds(eventIds)); + } public CalibrationService getService() { return service; diff --git a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/SpectraMeasurementJsonController.java b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/SpectraMeasurementJsonController.java index 94a81a3e..ffd1748a 100644 --- a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/SpectraMeasurementJsonController.java +++ b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/SpectraMeasurementJsonController.java @@ -62,6 +62,14 @@ public ResponseEntity computeSpectraForEventId(@RequestBody String eventId, B Spectra theoreticalSpectra = service.computeReferenceSpectraForEventId(eventId, sharedParamsService.getFrequencyBands(), PICK_TYPES.LG); return ResponseEntity.ok(theoreticalSpectra); } + + @PostMapping(value = "/validation-spectra", name = "computeValidationSpectraForEventId") + public ResponseEntity computeValidationSpectraForEventId(@RequestBody String eventId, BindingResult result) { + //FIXME: Accept a phase to use! + Spectra theoreticalSpectra = service.computeValidationSpectraForEventId(eventId, sharedParamsService.getFrequencyBands(), PICK_TYPES.LG); + return ResponseEntity.ok(theoreticalSpectra); + } + @PostMapping(value = "/fit-spectra", name = "getFitSpectraForEventId") public ResponseEntity getFitSpectraForEventId(@RequestBody String eventId, BindingResult result) { diff --git a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/ValidationEventsJsonController.java b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/ValidationEventsJsonController.java new file mode 100644 index 00000000..ee9a45f6 --- /dev/null +++ b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/ValidationEventsJsonController.java @@ -0,0 +1,78 @@ +/* +* Copyright (c) 2020, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* CODE-743439. +* All rights reserved. +* This file is part of CCT. For details, see https://github.com/LLNL/coda-calibration-tool. +* +* Licensed under the Apache License, Version 2.0 (the “Licensee”); you may not use this file except in compliance with the License. You may obtain a copy of the License at: +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and limitations under the license. +* +* This work was performed under the auspices of the U.S. Department of Energy +* by Lawrence Livermore National Laboratory under Contract DE-AC52-07NA27344. +*/ +package gov.llnl.gnem.apps.coda.calibration.application.web; + +import java.util.Collection; +import java.util.List; + +import javax.validation.Valid; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import gov.llnl.gnem.apps.coda.calibration.model.domain.ValidationMwParameters; +import gov.llnl.gnem.apps.coda.calibration.service.api.ValidationMwParametersService; + +@RestController +@RequestMapping(value = "/api/v1/validation-events", name = "ValidationEventsJsonController", produces = MediaType.APPLICATION_JSON_VALUE) +public class ValidationEventsJsonController { + + private ValidationMwParametersService service; + + @Autowired + public ValidationEventsJsonController(ValidationMwParametersService service) { + this.service = service; + } + + @GetMapping(name = "getValidationEvents") + public List getValidationEvents() { + return service.findAll(); + } + + @PostMapping(value = "/batch", name = "createBatch") + public ResponseEntity createBatch(@Valid @RequestBody Collection referenceEvents, BindingResult result) { + if (result.hasErrors()) { + return ResponseEntity.status(HttpStatus.CONFLICT).body(result); + } + service.save(referenceEvents); + return ResponseEntity.ok().build(); + } + + @PostMapping(value = "/delete/batch-by-evids", name = "deleteBatchByEvids") + public ResponseEntity deleteBatchByEvids(@Valid @RequestBody Collection eventIds, BindingResult result) { + if (result.hasErrors()) { + return ResponseEntity.status(HttpStatus.CONFLICT).body(result); + } + service.deleteAllByEventIds(eventIds); + return ResponseEntity.ok().build(); + } + + public ValidationMwParametersService getService() { + return service; + } + + public void setService(ValidationMwParametersService service) { + this.service = service; + } + +} diff --git a/calibration-service/calibration-integration/pom.xml b/calibration-service/calibration-integration/pom.xml index 9d2215da..001db916 100644 --- a/calibration-service/calibration-integration/pom.xml +++ b/calibration-service/calibration-integration/pom.xml @@ -1,10 +1,10 @@ - + gov.llnl.gnem.apps.coda.calibration calibration-service - 1.0.8.1 + 1.0.9 4.0.0 diff --git a/calibration-service/calibration-model/pom.xml b/calibration-service/calibration-model/pom.xml index 427fb1c8..cc931d11 100644 --- a/calibration-service/calibration-model/pom.xml +++ b/calibration-service/calibration-model/pom.xml @@ -1,11 +1,11 @@ - + gov.llnl.gnem.apps.coda.calibration calibration-service - 1.0.8.1 + 1.0.9 4.0.0 @@ -14,14 +14,6 @@ calibration-model - - io.springlets - springlets-context - - - org.springframework - spring-context - org.springframework.data spring-data-jpa diff --git a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/MeasuredMwDetails.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/MeasuredMwDetails.java index dd9985c6..ccc246a6 100644 --- a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/MeasuredMwDetails.java +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/MeasuredMwDetails.java @@ -38,6 +38,8 @@ public class MeasuredMwDetails { private Double mw2Min; private Double refMw; + + private Double valMw; private Double apparentStressInMpa; @@ -50,6 +52,8 @@ public class MeasuredMwDetails { private Double apparentStress2Min; private Double refApparentStressInMpa; + + private Double valApparentStressInMpa; private Double cornerFreq; @@ -61,17 +65,18 @@ public class MeasuredMwDetails { private Double longitude; + private Double depth; + private String datetime; private Integer iterations; private Double misfit; - public MeasuredMwDetails(MeasuredMwParameters meas, ReferenceMwParameters ref, Event event) { + public MeasuredMwDetails(MeasuredMwParameters meas, ReferenceMwParameters ref, ValidationMwParameters val, Event event) { if (meas != null) { this.eventId = meas.getEventId(); this.mw = meas.getMw(); - // this.mwSd = meas.getMwSd(); this.mw1Max = meas.getMw1Max(); this.mw1Min = meas.getMw1Min(); this.mw2Max = meas.getMw2Max(); @@ -82,7 +87,6 @@ public MeasuredMwDetails(MeasuredMwParameters meas, ReferenceMwParameters ref, E this.apparentStress2Max = meas.getApparentStress2Max(); this.apparentStress2Min = meas.getApparentStress2Min(); this.cornerFreq = meas.getCornerFrequency(); - // this.cornerFreqSd = meas.getCornerFrequencySd(); this.dataCount = meas.getDataCount(); this.iterations = meas.getIterations(); this.misfit = meas.getMisfit(); @@ -91,6 +95,7 @@ public MeasuredMwDetails(MeasuredMwParameters meas, ReferenceMwParameters ref, E this.eventId = event.getEventId(); this.latitude = event.getLatitude(); this.longitude = event.getLongitude(); + this.depth = event.getDepth(); if (event.getOriginTime() != null) { this.datetime = DateTimeFormatter.ISO_INSTANT.format(event.getOriginTime().toInstant()); } @@ -102,6 +107,14 @@ public MeasuredMwDetails(MeasuredMwParameters meas, ReferenceMwParameters ref, E this.refApparentStressInMpa = ref.getRefApparentStressInMpa(); this.refMw = ref.getRefMw(); } + + if (val != null) { + if (eventId == null) { + this.eventId = val.getEventId(); + } + this.valApparentStressInMpa = val.getApparentStressInMpa(); + this.valMw = val.getMw(); + } } public MeasuredMwDetails() { @@ -143,6 +156,15 @@ public MeasuredMwDetails setRefMw(Double refMw) { this.refMw = refMw; return this; } + + public Double getValMw() { + return valMw; + } + + public MeasuredMwDetails setValMw(Double mw) { + this.valMw = mw; + return this; + } public Double getApparentStressInMpa() { return apparentStressInMpa; @@ -152,6 +174,15 @@ public MeasuredMwDetails setApparentStressInMpa(Double apparentStressInMpa) { this.apparentStressInMpa = apparentStressInMpa; return this; } + + public Double getValApparentStressInMpa() { + return valApparentStressInMpa; + } + + public MeasuredMwDetails setValApparentStressInMpa(Double stressMpa) { + this.valApparentStressInMpa = stressMpa; + return this; + } public Double getRefApparentStressInMpa() { return refApparentStressInMpa; @@ -189,6 +220,15 @@ public MeasuredMwDetails setLongitude(double longitude) { return this; } + public Double getDepth() { + return depth; + } + + public MeasuredMwDetails setDepth(double depth) { + this.depth = depth; + return this; + } + public String getDatetime() { return datetime; } @@ -325,6 +365,8 @@ public String toString() { .append(mw2Min) .append(", refMw=") .append(refMw) + .append(", valMw=") + .append(valMw) .append(", apparentStressInMpa=") .append(apparentStressInMpa) .append(", apparentStress1Max=") @@ -337,6 +379,8 @@ public String toString() { .append(apparentStress2Min) .append(", refApparentStressInMpa=") .append(refApparentStressInMpa) + .append(", valApparentStressInMpa=") + .append(valApparentStressInMpa) .append(", cornerFreq=") .append(cornerFreq) .append(", cornerFreqSd=") @@ -347,6 +391,8 @@ public String toString() { .append(latitude) .append(", longitude=") .append(longitude) + .append(", depth=") + .append(depth) .append(", datetime=") .append(datetime) .append(", iterations=") @@ -359,29 +405,31 @@ public String toString() { @Override public int hashCode() { - return Objects.hash( - apparentStress1Max, - apparentStress1Min, - apparentStress2Max, - apparentStress2Min, - apparentStressInMpa, - cornerFreq, - cornerFreqSd, - dataCount, - datetime, - eventId, - iterations, - latitude, - longitude, - misfit, - mw, - mw1Max, - mw1Min, - mw2Max, - mw2Min, - mwSd, - refApparentStressInMpa, - refMw); + return Objects.hash(apparentStress1Max, + apparentStress1Min, + apparentStress2Max, + apparentStress2Min, + apparentStressInMpa, + cornerFreq, + cornerFreqSd, + dataCount, + datetime, + depth, + eventId, + iterations, + latitude, + longitude, + misfit, + mw, + mw1Max, + mw1Min, + mw2Max, + mw2Min, + mwSd, + refApparentStressInMpa, + refMw, + valApparentStressInMpa, + valMw); } @Override @@ -393,28 +441,14 @@ public boolean equals(Object obj) { return false; } MeasuredMwDetails other = (MeasuredMwDetails) obj; - return Objects.equals(apparentStress1Max, other.apparentStress1Max) - && Objects.equals(apparentStress1Min, other.apparentStress1Min) - && Objects.equals(apparentStress2Max, other.apparentStress2Max) - && Objects.equals(apparentStress2Min, other.apparentStress2Min) - && Objects.equals(apparentStressInMpa, other.apparentStressInMpa) - && Objects.equals(cornerFreq, other.cornerFreq) - && Objects.equals(cornerFreqSd, other.cornerFreqSd) - && Objects.equals(dataCount, other.dataCount) - && Objects.equals(datetime, other.datetime) - && Objects.equals(eventId, other.eventId) - && Objects.equals(iterations, other.iterations) - && Objects.equals(latitude, other.latitude) - && Objects.equals(longitude, other.longitude) - && Objects.equals(misfit, other.misfit) - && Objects.equals(mw, other.mw) - && Objects.equals(mw1Max, other.mw1Max) - && Objects.equals(mw1Min, other.mw1Min) - && Objects.equals(mw2Max, other.mw2Max) - && Objects.equals(mw2Min, other.mw2Min) - && Objects.equals(mwSd, other.mwSd) - && Objects.equals(refApparentStressInMpa, other.refApparentStressInMpa) - && Objects.equals(refMw, other.refMw); + return Objects.equals(apparentStress1Max, other.apparentStress1Max) && Objects.equals(apparentStress1Min, other.apparentStress1Min) + && Objects.equals(apparentStress2Max, other.apparentStress2Max) && Objects.equals(apparentStress2Min, other.apparentStress2Min) + && Objects.equals(apparentStressInMpa, other.apparentStressInMpa) && Objects.equals(cornerFreq, other.cornerFreq) && Objects.equals(cornerFreqSd, other.cornerFreqSd) + && Objects.equals(dataCount, other.dataCount) && Objects.equals(datetime, other.datetime) && Objects.equals(depth, other.depth) && Objects.equals(eventId, other.eventId) + && Objects.equals(iterations, other.iterations) && Objects.equals(latitude, other.latitude) && Objects.equals(longitude, other.longitude) && Objects.equals(misfit, other.misfit) + && Objects.equals(mw, other.mw) && Objects.equals(mw1Max, other.mw1Max) && Objects.equals(mw1Min, other.mw1Min) && Objects.equals(mw2Max, other.mw2Max) + && Objects.equals(mw2Min, other.mw2Min) && Objects.equals(mwSd, other.mwSd) && Objects.equals(refApparentStressInMpa, other.refApparentStressInMpa) + && Objects.equals(refMw, other.refMw) && Objects.equals(valApparentStressInMpa, other.valApparentStressInMpa) && Objects.equals(valMw, other.valMw); } @JsonIgnore diff --git a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/ValidationMwParameters.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/ValidationMwParameters.java new file mode 100644 index 00000000..6f1ed79f --- /dev/null +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/ValidationMwParameters.java @@ -0,0 +1,149 @@ +/* +* Copyright (c) 2020, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* CODE-743439. +* All rights reserved. +* This file is part of CCT. For details, see https://github.com/LLNL/coda-calibration-tool. +* +* Licensed under the Apache License, Version 2.0 (the “Licensee”); you may not use this file except in compliance with the License. You may obtain a copy of the License at: +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and limitations under the license. +* +* This work was performed under the auspices of the U.S. Department of Energy +* by Lawrence Livermore National Laboratory under Contract DE-AC52-07NA27344. +*/ +package gov.llnl.gnem.apps.coda.calibration.model.domain; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Index; +import javax.persistence.Table; +import javax.persistence.Version; + +import org.springframework.format.annotation.NumberFormat; + +@Entity +@Table(name = "Validation_Mws", indexes = { @Index(columnList = "eventId", name = "val_mw_event_id_index") }) +public class ValidationMwParameters implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "ID") + private Long id; + + @Version + private Integer version = 0; + + @Column(name = "eventId") + private String eventId; + + @NumberFormat + private double mw; + + @NumberFormat + @Column(nullable = true) + private Double apparentStressInMpa; + + public Long getId() { + return id; + } + + public ValidationMwParameters setId(Long id) { + this.id = id; + return this; + } + + public Integer getVersion() { + return version; + } + + public String getEventId() { + return eventId; + } + + public ValidationMwParameters setEventId(String eventId) { + this.eventId = eventId; + return this; + } + + public double getMw() { + return mw; + } + + public ValidationMwParameters setMw(double mw) { + this.mw = mw; + return this; + } + + public Double getApparentStressInMpa() { + return apparentStressInMpa; + } + + public ValidationMwParameters setApparentStressInMpa(Double apparentStressInMpa) { + this.apparentStressInMpa = apparentStressInMpa; + return this; + } + + @Override + public String toString() { + return "ValidationMwParams [id=" + id + ", version=" + version + ", eventId=" + eventId + ", Mw=" + mw + ", ApparentStressInMpa=" + apparentStressInMpa + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((eventId == null) ? 0 : eventId.hashCode()); + long temp; + temp = Double.doubleToLongBits(mw); + result = prime * result + (int) (temp ^ (temp >>> 32)); + result = prime * result + ((apparentStressInMpa == null) ? 0 : apparentStressInMpa.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + ValidationMwParameters other = (ValidationMwParameters) obj; + if (eventId == null) { + if (other.eventId != null) { + return false; + } + } else if (!eventId.equals(other.eventId)) { + return false; + } + if (Double.doubleToLongBits(mw) != Double.doubleToLongBits(other.getMw())) { + return false; + } + if (apparentStressInMpa == null) { + if (other.apparentStressInMpa != null) { + return false; + } + } else if (!apparentStressInMpa.equals(other.apparentStressInMpa)) { + return false; + } + return true; + } + + public ValidationMwParameters merge(ValidationMwParameters overlay) { + this.mw = overlay.getMw(); + this.apparentStressInMpa = overlay.getApparentStressInMpa(); + return this; + } + +} \ No newline at end of file diff --git a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/mixins/ReferenceMwParametersFileMixin.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/mixins/ReferenceMwParametersFileMixin.java index be8debe8..151a1922 100644 --- a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/mixins/ReferenceMwParametersFileMixin.java +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/mixins/ReferenceMwParametersFileMixin.java @@ -15,9 +15,6 @@ package gov.llnl.gnem.apps.coda.calibration.model.domain.mixins; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -import gov.llnl.gnem.apps.coda.common.model.domain.FrequencyBand; @JsonIgnoreProperties(value = { "id", "version" }) public class ReferenceMwParametersFileMixin { diff --git a/common-service/common-application/src/main/java/gov/llnl/gnem/apps/coda/common/application/config/WebMvcConfiguration.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/mixins/ValidationMwParametersFileMixin.java similarity index 57% rename from common-service/common-application/src/main/java/gov/llnl/gnem/apps/coda/common/application/config/WebMvcConfiguration.java rename to calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/mixins/ValidationMwParametersFileMixin.java index 3a147337..c094c0ad 100644 --- a/common-service/common-application/src/main/java/gov/llnl/gnem/apps/coda/common/application/config/WebMvcConfiguration.java +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/mixins/ValidationMwParametersFileMixin.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2018, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* Copyright (c) 2019, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory * CODE-743439. * All rights reserved. * This file is part of CCT. For details, see https://github.com/LLNL/coda-calibration-tool. @@ -12,20 +12,10 @@ * This work was performed under the auspices of the U.S. Department of Energy * by Lawrence Livermore National Laboratory under Contract DE-AC52-07NA27344. */ -package gov.llnl.gnem.apps.coda.common.application.config; +package gov.llnl.gnem.apps.coda.calibration.model.domain.mixins; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -@Configuration -public class WebMvcConfiguration implements WebMvcConfigurer { - - @Primary - @Bean - public LocalValidatorFactoryBean validator() { - return new LocalValidatorFactoryBean(); - } +@JsonIgnoreProperties(value = { "id", "version" }) +public class ValidationMwParametersFileMixin { } diff --git a/calibration-service/calibration-repository/pom.xml b/calibration-service/calibration-repository/pom.xml index 8d82e625..6b424794 100644 --- a/calibration-service/calibration-repository/pom.xml +++ b/calibration-service/calibration-repository/pom.xml @@ -1,11 +1,11 @@ - + gov.llnl.gnem.apps.coda.calibration calibration-service - 1.0.8.1 + 1.0.9 4.0.0 @@ -23,14 +23,6 @@ h2 test - - io.springlets - springlets-data-commons - - - io.springlets - springlets-data-jpa - gov.llnl.gnem.apps.coda.calibration calibration-model diff --git a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/CalibrationShapeFitterConstraintsRepository.java b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/CalibrationShapeFitterConstraintsRepository.java index be88c978..7e3ba17f 100644 --- a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/CalibrationShapeFitterConstraintsRepository.java +++ b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/CalibrationShapeFitterConstraintsRepository.java @@ -17,7 +17,7 @@ import org.springframework.transaction.annotation.Transactional; import gov.llnl.gnem.apps.coda.calibration.model.domain.ShapeFitterConstraints; -import io.springlets.data.jpa.repository.DetachableJpaRepository; +import gov.llnl.gnem.apps.coda.common.repository.DetachableJpaRepository; @Transactional public interface CalibrationShapeFitterConstraintsRepository extends DetachableJpaRepository { diff --git a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/MdacParametersFiRepository.java b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/MdacParametersFiRepository.java index 30a8fa53..9a410753 100644 --- a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/MdacParametersFiRepository.java +++ b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/MdacParametersFiRepository.java @@ -17,7 +17,7 @@ import org.springframework.transaction.annotation.Transactional; import gov.llnl.gnem.apps.coda.calibration.model.domain.MdacParametersFI; -import io.springlets.data.jpa.repository.DetachableJpaRepository; +import gov.llnl.gnem.apps.coda.common.repository.DetachableJpaRepository; @Transactional public interface MdacParametersFiRepository extends DetachableJpaRepository { diff --git a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/MdacParametersPsRepository.java b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/MdacParametersPsRepository.java index ccb817c5..a19a542e 100644 --- a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/MdacParametersPsRepository.java +++ b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/MdacParametersPsRepository.java @@ -17,7 +17,7 @@ import org.springframework.transaction.annotation.Transactional; import gov.llnl.gnem.apps.coda.calibration.model.domain.MdacParametersPS; -import io.springlets.data.jpa.repository.DetachableJpaRepository; +import gov.llnl.gnem.apps.coda.common.repository.DetachableJpaRepository; @Transactional public interface MdacParametersPsRepository extends DetachableJpaRepository { diff --git a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/MeasuredMwsRepository.java b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/MeasuredMwsRepository.java index dd65f5ae..40f51793 100644 --- a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/MeasuredMwsRepository.java +++ b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/MeasuredMwsRepository.java @@ -21,7 +21,7 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.MeasuredMwDetails; import gov.llnl.gnem.apps.coda.calibration.model.domain.MeasuredMwParameters; -import io.springlets.data.jpa.repository.DetachableJpaRepository; +import gov.llnl.gnem.apps.coda.common.repository.DetachableJpaRepository; @Transactional public interface MeasuredMwsRepository extends DetachableJpaRepository { diff --git a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/PathCalibrationMeasurementRepository.java b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/PathCalibrationMeasurementRepository.java index b15e9169..3c3a1a7a 100644 --- a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/PathCalibrationMeasurementRepository.java +++ b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/PathCalibrationMeasurementRepository.java @@ -17,7 +17,7 @@ import org.springframework.transaction.annotation.Transactional; import gov.llnl.gnem.apps.coda.calibration.model.domain.PathCalibrationMeasurement; -import io.springlets.data.jpa.repository.DetachableJpaRepository; +import gov.llnl.gnem.apps.coda.common.repository.DetachableJpaRepository; @Transactional public interface PathCalibrationMeasurementRepository extends DetachableJpaRepository { diff --git a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/PeakVelocityMeasurementRepository.java b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/PeakVelocityMeasurementRepository.java index 52c27901..c2c5f6fa 100644 --- a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/PeakVelocityMeasurementRepository.java +++ b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/PeakVelocityMeasurementRepository.java @@ -22,7 +22,7 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.PeakVelocityMeasurement; import gov.llnl.gnem.apps.coda.calibration.model.domain.PeakVelocityMeasurementMetadata; -import io.springlets.data.jpa.repository.DetachableJpaRepository; +import gov.llnl.gnem.apps.coda.common.repository.DetachableJpaRepository; @Transactional public interface PeakVelocityMeasurementRepository extends DetachableJpaRepository { diff --git a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/ReferenceMwParametersRepository.java b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/ReferenceMwParametersRepository.java index ae1e79e2..666e4ab8 100644 --- a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/ReferenceMwParametersRepository.java +++ b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/ReferenceMwParametersRepository.java @@ -22,7 +22,7 @@ import org.springframework.transaction.annotation.Transactional; import gov.llnl.gnem.apps.coda.calibration.model.domain.ReferenceMwParameters; -import io.springlets.data.jpa.repository.DetachableJpaRepository; +import gov.llnl.gnem.apps.coda.common.repository.DetachableJpaRepository; @Transactional public interface ReferenceMwParametersRepository extends DetachableJpaRepository { diff --git a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/ShapeMeasurementRepository.java b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/ShapeMeasurementRepository.java index 293e4de1..a7d83d95 100644 --- a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/ShapeMeasurementRepository.java +++ b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/ShapeMeasurementRepository.java @@ -21,7 +21,7 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.ShapeMeasurement; import gov.llnl.gnem.apps.coda.calibration.model.domain.ShapeMeasurementMetadata; -import io.springlets.data.jpa.repository.DetachableJpaRepository; +import gov.llnl.gnem.apps.coda.common.repository.DetachableJpaRepository; @Transactional public interface ShapeMeasurementRepository extends DetachableJpaRepository { diff --git a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/SharedFrequencyBandParametersRepository.java b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/SharedFrequencyBandParametersRepository.java index 58f1a154..3b9305fb 100644 --- a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/SharedFrequencyBandParametersRepository.java +++ b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/SharedFrequencyBandParametersRepository.java @@ -22,7 +22,7 @@ import gov.llnl.gnem.apps.coda.common.model.domain.FrequencyBand; import gov.llnl.gnem.apps.coda.common.model.domain.SharedFrequencyBandParameters; -import io.springlets.data.jpa.repository.DetachableJpaRepository; +import gov.llnl.gnem.apps.coda.common.repository.DetachableJpaRepository; @Transactional public interface SharedFrequencyBandParametersRepository extends DetachableJpaRepository { diff --git a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/SiteFrequencyBandParametersRepository.java b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/SiteFrequencyBandParametersRepository.java index c51edd99..124f8cb7 100644 --- a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/SiteFrequencyBandParametersRepository.java +++ b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/SiteFrequencyBandParametersRepository.java @@ -21,7 +21,7 @@ import org.springframework.transaction.annotation.Transactional; import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteFrequencyBandParameters; -import io.springlets.data.jpa.repository.DetachableJpaRepository; +import gov.llnl.gnem.apps.coda.common.repository.DetachableJpaRepository; @Transactional public interface SiteFrequencyBandParametersRepository extends DetachableJpaRepository { diff --git a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/SpectraMeasurementRepository.java b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/SpectraMeasurementRepository.java index e4e9224a..d47e9e38 100644 --- a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/SpectraMeasurementRepository.java +++ b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/SpectraMeasurementRepository.java @@ -21,7 +21,7 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.SpectraMeasurement; import gov.llnl.gnem.apps.coda.calibration.model.domain.SpectraMeasurementMetadata; -import io.springlets.data.jpa.repository.DetachableJpaRepository; +import gov.llnl.gnem.apps.coda.common.repository.DetachableJpaRepository; @Transactional public interface SpectraMeasurementRepository extends DetachableJpaRepository { diff --git a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/SyntheticRepository.java b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/SyntheticRepository.java index e474ebda..713dd622 100644 --- a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/SyntheticRepository.java +++ b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/SyntheticRepository.java @@ -22,7 +22,7 @@ import org.springframework.transaction.annotation.Transactional; import gov.llnl.gnem.apps.coda.common.model.domain.SyntheticCoda; -import io.springlets.data.jpa.repository.DetachableJpaRepository; +import gov.llnl.gnem.apps.coda.common.repository.DetachableJpaRepository; @Transactional public interface SyntheticRepository extends DetachableJpaRepository { diff --git a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/ValidationMwParametersRepository.java b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/ValidationMwParametersRepository.java new file mode 100644 index 00000000..a40f03b0 --- /dev/null +++ b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/ValidationMwParametersRepository.java @@ -0,0 +1,34 @@ +/* +* Copyright (c) 2020, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* CODE-743439. +* All rights reserved. +* This file is part of CCT. For details, see https://github.com/LLNL/coda-calibration-tool. +* +* Licensed under the Apache License, Version 2.0 (the “Licensee”); you may not use this file except in compliance with the License. You may obtain a copy of the License at: +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and limitations under the license. +* +* This work was performed under the auspices of the U.S. Department of Energy +* by Lawrence Livermore National Laboratory under Contract DE-AC52-07NA27344. +*/ +package gov.llnl.gnem.apps.coda.calibration.repository; + +import java.util.Collection; +import java.util.List; + +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.transaction.annotation.Transactional; + +import gov.llnl.gnem.apps.coda.calibration.model.domain.ValidationMwParameters; +import gov.llnl.gnem.apps.coda.common.repository.DetachableJpaRepository; + +@Transactional +public interface ValidationMwParametersRepository extends DetachableJpaRepository { + + @Query("select v from ValidationMwParameters v where v.eventId in :eventIds") + public List findAllByEventIds(@Param("eventIds") Collection eventIds); + + public ValidationMwParameters findOneByEventId(String eventId); +} diff --git a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/VelocityConfigurationRepository.java b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/VelocityConfigurationRepository.java index 7e80ed18..e7133a2a 100644 --- a/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/VelocityConfigurationRepository.java +++ b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/VelocityConfigurationRepository.java @@ -17,7 +17,7 @@ import org.springframework.transaction.annotation.Transactional; import gov.llnl.gnem.apps.coda.calibration.model.domain.VelocityConfiguration; -import io.springlets.data.jpa.repository.DetachableJpaRepository; +import gov.llnl.gnem.apps.coda.common.repository.DetachableJpaRepository; @Transactional public interface VelocityConfigurationRepository extends DetachableJpaRepository { diff --git a/calibration-service/calibration-service-api/pom.xml b/calibration-service/calibration-service-api/pom.xml index 419b5fb2..e8ea6d36 100644 --- a/calibration-service/calibration-service-api/pom.xml +++ b/calibration-service/calibration-service-api/pom.xml @@ -1,10 +1,10 @@ - + gov.llnl.gnem.apps.coda.calibration calibration-service - 1.0.8.1 + 1.0.9 4.0.0 @@ -17,10 +17,6 @@ gov.llnl.gnem.apps.coda.calibration calibration-model - - io.springlets - springlets-data-commons - gov.llnl.gnem.apps.coda.common common-service-api diff --git a/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/CalibrationService.java b/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/CalibrationService.java index 8bfdd687..dfac5804 100644 --- a/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/CalibrationService.java +++ b/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/CalibrationService.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2018, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* Copyright (c) 2020, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory * CODE-743439. * All rights reserved. * This file is part of CCT. For details, see https://github.com/LLNL/coda-calibration-tool. @@ -25,6 +25,8 @@ public interface CalibrationService { public boolean startCalibration(Boolean autoPickingEnabled); + + public boolean cancelCalibration(Long id); public boolean clearData(); @@ -33,4 +35,6 @@ public interface CalibrationService { public Future> makeMwMeasurements(Boolean autoPickingEnabled, Boolean persistResults, Set eventIds); public Future> makeMwMeasurements(Boolean autoPickingEnabled, Boolean persistResults, List stacks); + + public List toggleAllByEventIds(List eventIds); } diff --git a/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/PathCalibrationService.java b/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/PathCalibrationService.java index f96eca02..31a19eba 100644 --- a/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/PathCalibrationService.java +++ b/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/PathCalibrationService.java @@ -25,5 +25,5 @@ public interface PathCalibrationService { Map measurePathCorrections(Map> dataByFreqBand, - Map frequencyBandParameters, VelocityConfiguration velConf); + Map frequencyBandParameters, VelocityConfiguration velConf) throws InterruptedException; } diff --git a/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/ReferenceMwParametersService.java b/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/ReferenceMwParametersService.java index 7423be39..8847852a 100644 --- a/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/ReferenceMwParametersService.java +++ b/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/ReferenceMwParametersService.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2018, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* Copyright (c) 2020, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory * CODE-743439. * All rights reserved. * This file is part of CCT. For details, see https://github.com/LLNL/coda-calibration-tool. @@ -25,4 +25,6 @@ public interface ReferenceMwParametersService extends BaseService findAllByEventIds(Collection eventIds); public void deleteAllByEventIds(Collection eventIds); + + public ReferenceMwParameters findByEventId(String evid); } diff --git a/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/ShapeCalibrationService.java b/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/ShapeCalibrationService.java index 90ae365a..4d78b48e 100644 --- a/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/ShapeCalibrationService.java +++ b/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/ShapeCalibrationService.java @@ -25,5 +25,5 @@ public interface ShapeCalibrationService { public Map measureShapes(Collection velocityMeasurements, - Map frequencyBandParameters, ShapeFitterConstraints constraints, boolean autoPickingEnabled); + Map frequencyBandParameters, ShapeFitterConstraints constraints, boolean autoPickingEnabled) throws InterruptedException; } diff --git a/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/SpectraMeasurementService.java b/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/SpectraMeasurementService.java index bf3a3d70..0ed498b5 100644 --- a/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/SpectraMeasurementService.java +++ b/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/SpectraMeasurementService.java @@ -52,5 +52,7 @@ public List measureSpectra(List generatedSynt public Spectra computeReferenceSpectraForEventId(String eventId, List frequencyBands, PICK_TYPES selectedPhase); + public Spectra computeValidationSpectraForEventId(String eventId, List frequencyBands, PICK_TYPES selectedPhase); + public List getFitSpectraForEventId(String eventId, List frequencyBands, PICK_TYPES selectedPhase); } diff --git a/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/ValidationMwParametersService.java b/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/ValidationMwParametersService.java new file mode 100644 index 00000000..4d7051ab --- /dev/null +++ b/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/ValidationMwParametersService.java @@ -0,0 +1,31 @@ +/* +* Copyright (c) 2020, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* CODE-743439. +* All rights reserved. +* This file is part of CCT. For details, see https://github.com/LLNL/coda-calibration-tool. +* +* Licensed under the Apache License, Version 2.0 (the “Licensee”); you may not use this file except in compliance with the License. You may obtain a copy of the License at: +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and limitations under the license. +* +* This work was performed under the auspices of the U.S. Department of Energy +* by Lawrence Livermore National Laboratory under Contract DE-AC52-07NA27344. +*/ +package gov.llnl.gnem.apps.coda.calibration.service.api; + +import java.util.Collection; +import java.util.List; + +import gov.llnl.gnem.apps.coda.calibration.model.domain.ValidationMwParameters; +import gov.llnl.gnem.apps.coda.common.service.api.BaseService; + + +public interface ValidationMwParametersService extends BaseService { + + public List findAllByEventIds(Collection eventIds); + + public void deleteAllByEventIds(Collection eventIds); + + public ValidationMwParameters findByEventId(String evid); +} diff --git a/calibration-service/calibration-service-impl/pom.xml b/calibration-service/calibration-service-impl/pom.xml index 394651fd..1bf4766a 100644 --- a/calibration-service/calibration-service-impl/pom.xml +++ b/calibration-service/calibration-service-impl/pom.xml @@ -1,11 +1,11 @@ - + gov.llnl.gnem.apps.coda.calibration calibration-service - 1.0.8.1 + 1.0.9 4.0.0 diff --git a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/CalibrationServiceImpl.java b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/CalibrationServiceImpl.java index d73dfea2..5498ca6e 100644 --- a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/CalibrationServiceImpl.java +++ b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/CalibrationServiceImpl.java @@ -28,6 +28,7 @@ import java.util.Set; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.RejectedExecutionException; @@ -60,6 +61,7 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.SpectraMeasurement; import gov.llnl.gnem.apps.coda.calibration.model.domain.SpectraMeasurementMetadata; import gov.llnl.gnem.apps.coda.calibration.model.domain.SpectraMeasurementMetadataImpl; +import gov.llnl.gnem.apps.coda.calibration.model.domain.ValidationMwParameters; import gov.llnl.gnem.apps.coda.calibration.model.domain.VelocityConfiguration; import gov.llnl.gnem.apps.coda.calibration.model.messaging.CalibrationStatusEvent; import gov.llnl.gnem.apps.coda.calibration.model.messaging.MeasurementStatusEvent; @@ -79,6 +81,7 @@ import gov.llnl.gnem.apps.coda.calibration.service.api.SpectraMeasurementService; import gov.llnl.gnem.apps.coda.calibration.service.api.SyntheticCodaGenerationService; import gov.llnl.gnem.apps.coda.calibration.service.api.SyntheticService; +import gov.llnl.gnem.apps.coda.calibration.service.api.ValidationMwParametersService; import gov.llnl.gnem.apps.coda.calibration.service.impl.processing.SpectraCalculator; import gov.llnl.gnem.apps.coda.common.model.domain.Event; import gov.llnl.gnem.apps.coda.common.model.domain.FrequencyBand; @@ -97,6 +100,7 @@ @Service @Transactional +//FIXME: Kind of becoming a god-class, maybe see if we can break this up. public class CalibrationServiceImpl implements CalibrationService { private static final Logger log = LoggerFactory.getLogger(CalibrationServiceImpl.class); @@ -113,6 +117,7 @@ public class CalibrationServiceImpl implements CalibrationService { private MdacParametersFiService mdacFiService; private MdacParametersPsService mdacPsService; private ReferenceMwParametersService referenceMwService; + private ValidationMwParametersService validationMwService; private SiteCalibrationService siteCalibrationService; private SyntheticService syntheticService; private NotificationService notificationService; @@ -130,12 +135,14 @@ public class CalibrationServiceImpl implements CalibrationService { }); private final ExecutorService measureService; + private Map> runningJobs = new ConcurrentHashMap<>(2); + @Autowired public CalibrationServiceImpl(WaveformService waveformService, PeakVelocityMeasurementService peakVelocityMeasurementsService, SharedFrequencyBandParametersService sharedParametersService, ShapeCalibrationService shapeCalibrationService, SpectraMeasurementService spectraMeasurementService, SyntheticCodaGenerationService syntheticGenerationService, PathCalibrationService pathCalibrationService, MdacParametersFiService mdacFiService, MdacParametersPsService mdacPsService, ReferenceMwParametersService referenceMwService, - SiteCalibrationService siteCalibrationService, SyntheticService syntheticService, NotificationService notificationService, DatabaseCleaningService cleaningService, - ConfigurationService configService, SiteFrequencyBandParametersService siteParamsService, SpectraCalculator spectraCalc, AutopickingService picker, + ValidationMwParametersService validationMwService, SiteCalibrationService siteCalibrationService, SyntheticService syntheticService, NotificationService notificationService, + DatabaseCleaningService cleaningService, ConfigurationService configService, SiteFrequencyBandParametersService siteParamsService, SpectraCalculator spectraCalc, AutopickingService picker, @Qualifier("MeasurementExecutorService") ExecutorService measureService) { this.waveformService = waveformService; this.peakVelocityMeasurementsService = peakVelocityMeasurementsService; @@ -147,6 +154,7 @@ public CalibrationServiceImpl(WaveformService waveformService, PeakVelocityMeasu this.mdacFiService = mdacFiService; this.mdacPsService = mdacPsService; this.referenceMwService = referenceMwService; + this.validationMwService = validationMwService; this.siteCalibrationService = siteCalibrationService; this.syntheticService = syntheticService; this.notificationService = notificationService; @@ -182,13 +190,12 @@ public Future> makeMwMeasurements(Boolean autoPi if (stacks != null && !stacks.isEmpty()) { measuredMws = makeMwMeasurements(id, autoPickingEnabled, persistResults, stacks); } else { - notificationService.post( - new MeasurementStatusEvent(id, - MeasurementStatusEvent.Status.ERROR, - new Result(false, - new LightweightIllegalStateException("No matching waveforms found for event ids: " + eventIds != null - ? eventIds.toString() - : "{null}")))); + notificationService.post(new MeasurementStatusEvent(id, + MeasurementStatusEvent.Status.ERROR, + new Result(false, + new LightweightIllegalStateException("No matching waveforms found for event ids: " + eventIds != null + ? eventIds.toString() + : "{null}")))); } return measuredMws; @@ -271,13 +278,12 @@ private MeasuredMwReportByEvent makeMwMeasurements(Long id, Boolean autoPickingE List spectra = spectraCalc.measureAmplitudes(synthetics, frequencyBandParameterMap, velocityConfig, stationFrequencyBandMap); - List measuredMwsParams = siteCalibrationService.fitMws( - spectraByFrequencyBand(spectra), - mdacFiService.findFirst(), - collectByFrequencyBand(mdacPsService.findAll()), - collectByEvid(referenceMwService.findAll()), - stationFrequencyBandMap, - PICK_TYPES.LG); + List measuredMwsParams = siteCalibrationService.fitMws(spectraByFrequencyBand(spectra), + mdacFiService.findFirst(), + collectByFrequencyBand(mdacPsService.findAll()), + collectByEvid(referenceMwService.findAll()), + stationFrequencyBandMap, + PICK_TYPES.LG); Map measuredMwsMap = Optional.ofNullable(measuredMwsParams).orElseGet(ArrayList::new).stream().map(mwp -> { Event event = getEventForId(mwp.getEventId(), eventsInStacks); @@ -290,9 +296,8 @@ private MeasuredMwReportByEvent makeMwMeasurements(Long id, Boolean autoPickingE Map> fitSpectra = measuredMwsMap.entrySet() .parallelStream() - .map( - mw -> new AbstractMap.SimpleEntry<>(mw.getKey().getEventId(), - computeFitSpectra(mw.getValue(), frequencyBandParameterMap.keySet(), PICK_TYPES.LG))) + .map(mw -> new AbstractMap.SimpleEntry<>(mw.getKey().getEventId(), + computeFitSpectra(mw.getValue(), frequencyBandParameterMap.keySet(), PICK_TYPES.LG))) .collect(Collectors.toConcurrentMap(kv -> kv.getKey(), kv -> kv.getValue())); if (persistResults) { @@ -304,13 +309,14 @@ private MeasuredMwReportByEvent makeMwMeasurements(Long id, Boolean autoPickingE details.setFitSpectra(fitSpectra); - details.setMeasuredMwDetails( - measuredMwsMap.entrySet().parallelStream().collect(Collectors.toConcurrentMap(kv -> kv.getKey().getEventId(), kv -> new MeasuredMwDetails(kv.getValue(), null, kv.getKey())))); + details.setMeasuredMwDetails(measuredMwsMap.entrySet() + .parallelStream() + .collect(Collectors.toConcurrentMap(kv -> kv.getKey().getEventId(), kv -> new MeasuredMwDetails(kv.getValue(), null, null, kv.getKey())))); - details.setSpectraMeasurements( - spectra.parallelStream() - .map(s -> new AbstractMap.SimpleEntry(s.getWaveform().getEvent().getEventId(), new SpectraMeasurementMetadataImpl(s))) - .collect(Collectors.groupingByConcurrent(kv -> kv.getKey(), Collectors.mapping(kv -> kv.getValue(), Collectors.toList())))); + details.setSpectraMeasurements(spectra.parallelStream() + .map(s -> new AbstractMap.SimpleEntry(s.getWaveform().getEvent().getEventId(), + new SpectraMeasurementMetadataImpl(s))) + .collect(Collectors.groupingByConcurrent(kv -> kv.getKey(), Collectors.mapping(kv -> kv.getValue(), Collectors.toList())))); } else { log.info("Unable to measure Mws, no waveforms were provided."); } @@ -344,7 +350,7 @@ public boolean startCalibration(Boolean autoPickingEnabled) { // FIXME: These *All methods should be *AllByProjectID instead! final Long id = atomicLong.getAndIncrement(); try { - calService.submit(() -> { + runningJobs.put(id, calService.submit(() -> { try { notificationService.post(new CalibrationStatusEvent(id, CalibrationStatusEvent.Status.STARTING)); log.info("Starting calibration at {}", LocalDateTime.now()); @@ -380,6 +386,7 @@ public boolean startCalibration(Boolean autoPickingEnabled) { // Now save the new ones we just calculated peakVelocityMeasurementsService.save(snrFilteredVelocity); + ConcurrencyUtils.checkInterrupt(); notificationService.post(new CalibrationStatusEvent(id, CalibrationStatusEvent.Status.SHAPE_STARTING)); // 2) Compute the shape parameters describing each stack @@ -398,11 +405,11 @@ public boolean startCalibration(Boolean autoPickingEnabled) { // values back stacks = filterToEndPicked(stacks); - List spectra = spectraMeasurementService.measureSpectra( - syntheticGenerationService.generateSynthetics(stacks, frequencyBandParameterMap), - frequencyBandParameterMap, - velocityConfig); + List spectra = spectraMeasurementService.measureSpectra(syntheticGenerationService.generateSynthetics(stacks, frequencyBandParameterMap), + frequencyBandParameterMap, + velocityConfig); + ConcurrencyUtils.checkInterrupt(); notificationService.post(new CalibrationStatusEvent(id, CalibrationStatusEvent.Status.PATH_STARTING)); // 4) For each event in the data set find all stations that @@ -411,11 +418,13 @@ public boolean startCalibration(Boolean autoPickingEnabled) { frequencyBandParameterMap = pathCalibrationService.measurePathCorrections(spectraByFrequencyBand(spectra), frequencyBandParameterMap, velocityConfig); frequencyBandParameterMap = mapParamsToFrequencyBands(sharedParametersService.save(frequencyBandParameterMap.values())); + ConcurrencyUtils.checkInterrupt(); // 5) Measure the amplitudes again but this time we can // compute ESH path corrected values spectra = spectraMeasurementService.measureSpectra(syntheticGenerationService.generateSynthetics(stacks, frequencyBandParameterMap), frequencyBandParameterMap, velocityConfig); + ConcurrencyUtils.checkInterrupt(); notificationService.post(new CalibrationStatusEvent(id, CalibrationStatusEvent.Status.SITE_STARTING)); // 6) Now using those path correction values plus a list of @@ -424,31 +433,33 @@ public boolean startCalibration(Boolean autoPickingEnabled) { // from the expected source spectra for that MW value. This value is // recorded as the site specific offset for measured values at each // frequency band - Map> frequencyBandSiteParameterMap = siteCalibrationService.measureSiteCorrections( - spectraByFrequencyBand(spectra), - mdacFiService.findFirst(), - collectByFrequencyBand(mdacPsService.findAll()), - collectByEvid(referenceMwService.findAll()), - frequencyBandParameterMap, - PICK_TYPES.LG); - + Map> frequencyBandSiteParameterMap = siteCalibrationService.measureSiteCorrections(spectraByFrequencyBand(spectra), + mdacFiService.findFirst(), + collectByFrequencyBand(mdacPsService.findAll()), + collectByEvid(referenceMwService.findAll()), + frequencyBandParameterMap, + PICK_TYPES.LG); + + ConcurrencyUtils.checkInterrupt(); // 7) Measure the amplitudes one last time to fill out the // Path+Site corrected amplitude values - spectra = spectraMeasurementService.measureSpectra( - syntheticService.save(syntheticGenerationService.generateSynthetics(stacks, frequencyBandParameterMap)), - frequencyBandParameterMap, - velocityConfig, - frequencyBandSiteParameterMap); + spectra = spectraMeasurementService.measureSpectra(syntheticService.save(syntheticGenerationService.generateSynthetics(stacks, frequencyBandParameterMap)), + frequencyBandParameterMap, + velocityConfig, + frequencyBandSiteParameterMap); log.info("Calibration complete at {}", LocalDateTime.now()); notificationService.post(new CalibrationStatusEvent(id, CalibrationStatusEvent.Status.COMPLETE)); + } catch (InterruptedException interrupted) { + notificationService.post(new CalibrationStatusEvent(id, CalibrationStatusEvent.Status.COMPLETE, new Result<>(true, interrupted))); } catch (Exception ex) { log.error(ex.getMessage(), ex); notificationService.post(new CalibrationStatusEvent(id, CalibrationStatusEvent.Status.ERROR, new Result<>(false, ex))); throw ex; + } finally { + runningJobs.remove(id); } - return new CompletableFuture<>(); - }); + })); } catch (RejectedExecutionException e) { notificationService.post(new CalibrationStatusEvent(id, CalibrationStatusEvent.Status.ERROR, new Result(false, e))); return false; @@ -456,6 +467,17 @@ public boolean startCalibration(Boolean autoPickingEnabled) { return true; } + @Override + public boolean cancelCalibration(Long id) { + boolean cancelled = false; + Future task = runningJobs.get(id); + if (task != null) { + task.cancel(true); + cancelled = true; + } + return cancelled; + } + private List filterToEndPicked(List stacks) { return stacks.parallelStream().filter(wave -> wave.getAssociatedPicks() != null).map(wave -> { Optional pick = wave.getAssociatedPicks().stream().filter(p -> p.getPickType() != null && PICK_TYPES.F.name().equalsIgnoreCase(p.getPickType().trim())).findFirst(); @@ -519,4 +541,43 @@ public boolean clearData() { return false; } + + @Override + public List toggleAllByEventIds(List eventIds) { + List infoMesssages = new ArrayList<>(0); + for (String evid : eventIds) { + ReferenceMwParameters ref = referenceMwService.findByEventId(evid); + ValidationMwParameters val = validationMwService.findByEventId(evid); + + //Has ref but no validation (move Ref to Val) + if (ref != null && ref.getRefMw() != 0.0 && (val == null || val.getMw() == 0.0)) { + if (val == null) { + val = new ValidationMwParameters(); + } + val.setEventId(ref.getEventId()); + val.setMw(ref.getRefMw()); + val.setApparentStressInMpa(ref.getRefApparentStressInMpa()); + referenceMwService.delete(ref); + validationMwService.save(val); + infoMesssages.add("Evid " + evid + " converted from reference event to validation."); + } + //Has val but no reference (move Val to Ref) + else if (val != null && val.getMw() != 0.0 && (ref == null || ref.getRefMw() == 0.0)) { + if (ref == null) { + ref = new ReferenceMwParameters(); + } + ref.setEventId(val.getEventId()); + ref.setRefMw(val.getMw()); + ref.setRefApparentStressInMpa(val.getApparentStressInMpa()); + validationMwService.delete(val); + referenceMwService.save(ref); + infoMesssages.add("Evid " + evid + " converted from validation event to reference."); + } + //Has both/neither (info message?) + else { + infoMesssages.add("Ignoring request to convert evid " + evid + ", either the event has both or both are blank. Ref " + ref + "; Val " + val); + } + } + return infoMesssages; + } } diff --git a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/ConcurrencyUtils.java b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/ConcurrencyUtils.java new file mode 100644 index 00000000..570641a1 --- /dev/null +++ b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/ConcurrencyUtils.java @@ -0,0 +1,23 @@ +/* +* Copyright (c) 2019, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* CODE-743439. +* All rights reserved. +* +* Licensed under the Apache License, Version 2.0 (the “Licensee”); you may not use this file except in compliance with the License. You may obtain a copy of the License at: +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and limitations under the license. +* +* This work was performed under the auspices of the U.S. Department of Energy +* by Lawrence Livermore National Laboratory under Contract DE-AC52-07NA27344. +*/ +package gov.llnl.gnem.apps.coda.calibration.service.impl; + +public class ConcurrencyUtils { + + public static void checkInterrupt() throws InterruptedException { + if (Thread.currentThread().isInterrupted()) { + throw new InterruptedException(); + } + } +} diff --git a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/Joint1DPathCorrection.java b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/Joint1DPathCorrection.java index 42231627..22e3bf74 100644 --- a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/Joint1DPathCorrection.java +++ b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/Joint1DPathCorrection.java @@ -111,7 +111,7 @@ public Joint1DPathCorrection(SpectraCalculator spectraCalc, PathCalibrationMeasu @Override public Map measurePathCorrections(Map> dataByFreqBand, - Map frequencyBandParameters, VelocityConfiguration velConf) { + Map frequencyBandParameters, VelocityConfiguration velConf) throws InterruptedException { if (velConf != null) { Double phase = velConf.getPhaseVelocityInKms(); @@ -128,9 +128,12 @@ public Map measurePathCorrections( Map pathCorrectedFrequencyBandParameters = new HashMap<>(); Map>> dataMappedToEventAndStation = removeSingleStationOrFewerEntries(mapToEventAndStation(dataByFreqBand)); - - frequencyBandParameters.entrySet().parallelStream().forEach(frequencyBandParams -> { - + + ConcurrencyUtils.checkInterrupt(); + frequencyBandParameters.entrySet().parallelStream().forEach(frequencyBandParams -> { + if (Thread.currentThread().isInterrupted()) { + return; + } SharedFrequencyBandParameters pathCorrectedParams = frequencyBandParams.getValue(); Map eventCountByStation = new HashMap<>(); @@ -150,6 +153,9 @@ public Map measurePathCorrections( for (Entry> eventEntry : freqBandData.entrySet()) { Event event = eventEntry.getKey(); for (Entry stationEntry : eventEntry.getValue().entrySet()) { + if (Thread.currentThread().isInterrupted()) { + return; + } SpectraMeasurement spectra = stationEntry.getValue(); Station station = stationEntry.getKey(); @@ -266,6 +272,7 @@ public Map measurePathCorrections( pathCorrectedFrequencyBandParameters.put(frequencyBand, pathCorrectedParams); } }); + ConcurrencyUtils.checkInterrupt(); pathCalibrationMeasurementService.deleteAll(); pathCalibrationMeasurementService.save(measurements); diff --git a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/MeasuredMwsServiceImpl.java b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/MeasuredMwsServiceImpl.java index 98a770d4..a5d31fa1 100644 --- a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/MeasuredMwsServiceImpl.java +++ b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/MeasuredMwsServiceImpl.java @@ -24,8 +24,10 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.MeasuredMwDetails; import gov.llnl.gnem.apps.coda.calibration.model.domain.MeasuredMwParameters; import gov.llnl.gnem.apps.coda.calibration.model.domain.ReferenceMwParameters; +import gov.llnl.gnem.apps.coda.calibration.model.domain.ValidationMwParameters; import gov.llnl.gnem.apps.coda.calibration.repository.MeasuredMwsRepository; import gov.llnl.gnem.apps.coda.calibration.repository.ReferenceMwParametersRepository; +import gov.llnl.gnem.apps.coda.calibration.repository.ValidationMwParametersRepository; import gov.llnl.gnem.apps.coda.calibration.service.api.MeasuredMwsService; import gov.llnl.gnem.apps.coda.common.service.api.WaveformService; @@ -35,12 +37,15 @@ public class MeasuredMwsServiceImpl implements MeasuredMwsService { private MeasuredMwsRepository measuredMwsRepository; private ReferenceMwParametersRepository referenceMwsRepository; + private ValidationMwParametersRepository validationMwsRepository; private WaveformService eventRepository; @Autowired - public MeasuredMwsServiceImpl(MeasuredMwsRepository measuredMwsRepository, ReferenceMwParametersRepository referenceMwsRepository, WaveformService eventRepository) { + public MeasuredMwsServiceImpl(MeasuredMwsRepository measuredMwsRepository, ReferenceMwParametersRepository referenceMwsRepository, + ValidationMwParametersRepository validationMwParametersRepository, WaveformService eventRepository) { this.measuredMwsRepository = measuredMwsRepository; this.referenceMwsRepository = referenceMwsRepository; + this.validationMwsRepository = validationMwParametersRepository; this.eventRepository = eventRepository; } @@ -102,16 +107,33 @@ public Class getIdType() { public List findAllDetails() { List measured = measuredMwsRepository.findAll(); List reference = referenceMwsRepository.findAll(); + List validation = validationMwsRepository.findAll(); List details = measured.stream().map(meas -> { - ReferenceMwParameters rmw = reference.stream().filter(ref -> ref.getEventId().equals(meas.getEventId())).findAny().orElseGet(() -> null); - return new MeasuredMwDetails(meas, rmw, eventRepository.findEventById(meas.getEventId())); + ReferenceMwParameters refMw = reference.stream().filter(ref -> ref.getEventId().equals(meas.getEventId())).findAny().orElseGet(() -> null); + ValidationMwParameters valMw = validation.stream().filter(val -> val.getEventId().equals(meas.getEventId())).findAny().orElseGet(() -> null); + return new MeasuredMwDetails(meas, refMw, valMw, eventRepository.findEventById(meas.getEventId())); }).collect(Collectors.toList()); + //Ref v Meas details.addAll(reference.stream() .filter(ref -> measured.stream().noneMatch(meas -> ref.getEventId().equals(meas.getEventId()))) - .map(ref -> new MeasuredMwDetails(null, ref, eventRepository.findEventById(ref.getEventId()))) + .map(ref -> new MeasuredMwDetails(null, ref, null, eventRepository.findEventById(ref.getEventId()))) + .map(ref -> { + validation.stream().filter(val -> ref.getEventId().equals(val.getEventId())).findFirst().ifPresent(v -> { + ref.setValMw(v.getMw()); + ref.setValApparentStressInMpa(v.getApparentStressInMpa()); + }); + return ref; + }) .collect(Collectors.toList())); + //Val ^ (Ref v Meas) + details.addAll(validation.stream() + .filter(val -> measured.stream().noneMatch(meas -> val.getEventId().equals(meas.getEventId()))) + .filter(val -> reference.stream().noneMatch(ref -> val.getEventId().equals(ref.getEventId()))) + .map(val -> new MeasuredMwDetails(null, null, val, eventRepository.findEventById(val.getEventId()))) + .collect(Collectors.toList())); + return details; } } diff --git a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/ReferenceMwParametersServiceImpl.java b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/ReferenceMwParametersServiceImpl.java index 9ab95f47..2817eb7a 100644 --- a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/ReferenceMwParametersServiceImpl.java +++ b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/ReferenceMwParametersServiceImpl.java @@ -126,4 +126,9 @@ public Class getIdType() { public List findAllByEventIds(Collection eventIds) { return referenceMwParametersRepository.findAllByEventIds(eventIds); } + + @Override + public ReferenceMwParameters findByEventId(String evid) { + return referenceMwParametersRepository.findOneByEventId(evid); + } } diff --git a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/ShapeCalibrationServiceImpl.java b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/ShapeCalibrationServiceImpl.java index aaa6e6bf..78ccd0ea 100644 --- a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/ShapeCalibrationServiceImpl.java +++ b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/ShapeCalibrationServiceImpl.java @@ -61,7 +61,7 @@ public ShapeCalibrationServiceImpl(ShapeMeasurementService shapeMeasurementServi @Override public Map measureShapes(Collection velocityMeasurements, - Map frequencyBandParameters, ShapeFitterConstraints constraints, boolean autoPickingEnabled) { + Map frequencyBandParameters, ShapeFitterConstraints constraints, boolean autoPickingEnabled) throws InterruptedException { if (frequencyBandParameters.isEmpty()) { // TODO: Propagate warning to the status API log.warn("No frequency band parameters available, unable to compute shape parameters without them!"); @@ -69,6 +69,7 @@ public Map measureShapes(Collectio } final CalibrationCurveFitter fitter = new CalibrationCurveFitter(); + ConcurrencyUtils.checkInterrupt(); Map frequencyBandCurveFits = fitter.fitAllVelocity( velocityMeasurements.stream() .filter(vel -> vel.getWaveform() != null) @@ -76,20 +77,25 @@ public Map measureShapes(Collectio frequencyBandParameters, constraints); + ConcurrencyUtils.checkInterrupt(); // 1) If auto-picking is enabled attempt to pick any envelopes that // don't already have F-picks in this set if (autoPickingEnabled) { velocityMeasurements = picker.autoPickVelocityMeasuredWaveforms(velocityMeasurements, frequencyBandParameters); velocityMeasurements = velocityMeasurements.parallelStream().map(v -> v.setWaveform(waveService.save(v.getWaveform()))).collect(Collectors.toList()); } + ConcurrencyUtils.checkInterrupt(); // 2) Filter to only measurements with an end pick Collection> filteredVelocityMeasurements = filterMeasurementsToEndPickedOnly(velocityMeasurements); + ConcurrencyUtils.checkInterrupt(); // 3) For every Waveform remaining, measure picks based on start // (computed from velocity) and end (from 'End'/'F' picks) List betaAndGammaMeasurements = shapeCalc.fitShapelineToMeasuredEnvelopes(filteredVelocityMeasurements, frequencyBandCurveFits, constraints); + ConcurrencyUtils.checkInterrupt(); + // Shape measurements are intermediary results so rather than trying to // merge them we want to just drop them wholesale if they exist and // replace them with the new data set. @@ -103,8 +109,9 @@ public Map measureShapes(Collectio Collectors.groupingBy( meas -> new FrequencyBand(meas.getWaveform().getLowFrequency(), meas.getWaveform().getHighFrequency()))); - + ConcurrencyUtils.checkInterrupt(); frequencyBandCurveFits = fitter.fitAllBeta(frequencyBandShapeMeasurementMap, frequencyBandCurveFits, constraints); + ConcurrencyUtils.checkInterrupt(); frequencyBandCurveFits = fitter.fitAllGamma(frequencyBandShapeMeasurementMap, frequencyBandCurveFits, constraints); return frequencyBandCurveFits; } diff --git a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/SpectraMeasurementServiceImpl.java b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/SpectraMeasurementServiceImpl.java index 9d1c5715..5bc8ae2b 100644 --- a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/SpectraMeasurementServiceImpl.java +++ b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/SpectraMeasurementServiceImpl.java @@ -28,10 +28,12 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.Spectra; import gov.llnl.gnem.apps.coda.calibration.model.domain.SpectraMeasurement; import gov.llnl.gnem.apps.coda.calibration.model.domain.SpectraMeasurementMetadata; +import gov.llnl.gnem.apps.coda.calibration.model.domain.ValidationMwParameters; import gov.llnl.gnem.apps.coda.calibration.model.domain.VelocityConfiguration; import gov.llnl.gnem.apps.coda.calibration.repository.MeasuredMwsRepository; import gov.llnl.gnem.apps.coda.calibration.repository.ReferenceMwParametersRepository; import gov.llnl.gnem.apps.coda.calibration.repository.SpectraMeasurementRepository; +import gov.llnl.gnem.apps.coda.calibration.repository.ValidationMwParametersRepository; import gov.llnl.gnem.apps.coda.calibration.service.api.SpectraMeasurementService; import gov.llnl.gnem.apps.coda.calibration.service.impl.processing.SpectraCalculator; import gov.llnl.gnem.apps.coda.common.model.domain.FrequencyBand; @@ -50,16 +52,19 @@ public class SpectraMeasurementServiceImpl implements SpectraMeasurementService private SpectraMeasurementRepository spectraRepo; private ReferenceMwParametersRepository referenceEventRepo; + + private ValidationMwParametersRepository validationEventRepo; private MeasuredMwsRepository measuredEventRepo; @Autowired public SpectraMeasurementServiceImpl(SpectraMeasurementRepository spectraRepo, SpectraCalculator spectraCalc, MeasuredMwsRepository measuredEventRepo, - ReferenceMwParametersRepository referenceEventRepo) { + ReferenceMwParametersRepository referenceEventRepo, ValidationMwParametersRepository validationEventRepo) { this.spectraRepo = spectraRepo; this.spectraCalc = spectraCalc; this.measuredEventRepo = measuredEventRepo; this.referenceEventRepo = referenceEventRepo; + this.validationEventRepo = validationEventRepo; } @Override @@ -128,6 +133,16 @@ public Spectra computeReferenceSpectraForEventId(String eventId, List frequencyBands, PICK_TYPES selectedPhase) { + Spectra valSpectra = new Spectra(); + ValidationMwParameters valEvent = validationEventRepo.findOneByEventId(eventId); + if (valEvent != null) { + valSpectra = spectraCalc.computeSpecificSpectra(valEvent.getMw(), valEvent.getApparentStressInMpa(), frequencyBands, selectedPhase, SPECTRA_TYPES.VAL); + } + return valSpectra; + } @Override public List getFitSpectraForEventId(String eventId, List frequencyBands, PICK_TYPES selectedPhase) { diff --git a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/ValidationMwParametersServiceImpl.java b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/ValidationMwParametersServiceImpl.java new file mode 100644 index 00000000..265c140e --- /dev/null +++ b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/ValidationMwParametersServiceImpl.java @@ -0,0 +1,134 @@ +/* +* Copyright (c) 2018, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* CODE-743439. +* All rights reserved. +* This file is part of CCT. For details, see https://github.com/LLNL/coda-calibration-tool. +* +* Licensed under the Apache License, Version 2.0 (the “Licensee”); you may not use this file except in compliance with the License. You may obtain a copy of the License at: +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and limitations under the license. +* +* This work was performed under the auspices of the U.S. Department of Energy +* by Lawrence Livermore National Laboratory under Contract DE-AC52-07NA27344. +*/ +package gov.llnl.gnem.apps.coda.calibration.service.impl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import gov.llnl.gnem.apps.coda.calibration.model.domain.ValidationMwParameters; +import gov.llnl.gnem.apps.coda.calibration.repository.ValidationMwParametersRepository; +import gov.llnl.gnem.apps.coda.calibration.service.api.ValidationMwParametersService; + +@Service +@Transactional +public class ValidationMwParametersServiceImpl implements ValidationMwParametersService { + + private ValidationMwParametersRepository validationMwParametersRepository; + + @Autowired + public ValidationMwParametersServiceImpl(ValidationMwParametersRepository validationMwParametersRepository) { + this.validationMwParametersRepository = validationMwParametersRepository; + } + + public ValidationMwParametersRepository getValidationMwParametersRepository() { + return validationMwParametersRepository; + } + + public void setValidationMwParametersRepository(ValidationMwParametersRepository validationMwParametersRepository) { + this.validationMwParametersRepository = validationMwParametersRepository; + } + + @Override + @Transactional + public void delete(ValidationMwParameters validationMwParameters) { + validationMwParametersRepository.delete(validationMwParameters); + } + + @Override + @Transactional + public List save(Iterable entities) { + List results = new ArrayList<>(); + for (ValidationMwParameters ref : entities) { + results.add(save(ref)); + } + return results; + } + + @Override + @Transactional + public void delete(Iterable ids) { + List toDelete = validationMwParametersRepository.findAllById(ids); + validationMwParametersRepository.deleteInBatch(toDelete); + validationMwParametersRepository.flush(); + } + + @Override + @Transactional + public void deleteAllByEventIds(Collection eventIds) { + List toDelete = validationMwParametersRepository.findAllByEventIds(eventIds); + validationMwParametersRepository.deleteInBatch(toDelete); + validationMwParametersRepository.flush(); + } + + @Override + @Transactional + public ValidationMwParameters save(ValidationMwParameters entity) { + ValidationMwParameters persistentRef = validationMwParametersRepository.findOneByEventId(entity.getEventId()); + if (persistentRef == null) { + persistentRef = entity; + } else { + persistentRef.merge(entity); + } + return validationMwParametersRepository.save(persistentRef); + } + + @Override + public ValidationMwParameters findOne(Long id) { + return validationMwParametersRepository.findOneDetached(id); + } + + @Override + public ValidationMwParameters findOneForUpdate(Long id) { + return validationMwParametersRepository.findOneDetached(id); + } + + @Override + public List findAll(Iterable ids) { + return validationMwParametersRepository.findAllById(ids); + } + + @Override + public List findAll() { + return validationMwParametersRepository.findAll(); + } + + @Override + public long count() { + return validationMwParametersRepository.count(); + } + + public Class getEntityType() { + return ValidationMwParameters.class; + } + + public Class getIdType() { + return Long.class; + } + + @Override + public List findAllByEventIds(Collection eventIds) { + return validationMwParametersRepository.findAllByEventIds(eventIds); + } + + @Override + public ValidationMwParameters findByEventId(String evid) { + return validationMwParametersRepository.findOneByEventId(evid); + } +} diff --git a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/MaxVelocityCalculator.java b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/MaxVelocityCalculator.java index c4fe5a6e..1a8dd354 100644 --- a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/MaxVelocityCalculator.java +++ b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/MaxVelocityCalculator.java @@ -71,6 +71,9 @@ public Stream computeMaximumVelocity(List wav private Stream computeMaximumVelocity(List waveforms, double gv1GtDistanceThreshold, double gv2GtDistanceThreshold, double gv1LtDistanceThreshold, double gv2LtDistanceThreshold, double thresholdInKm) { return waveforms.stream().parallel().map(rawWaveform -> { + if (Thread.currentThread().isInterrupted()) { + return null; + } TimeSeries waveform = converter.convert(rawWaveform); double distance = EModel.getDistanceWGS84( rawWaveform.getEvent().getLatitude(), @@ -123,6 +126,6 @@ private Stream computeMaximumVelocity(List wa log.info("Unable to compute maximum velocity, this stack will be skipped. {} {}.", ill.getMessage(), rawWaveform); return new PeakVelocityMeasurement(); } - }).filter(measurement -> measurement.getWaveform() != null); + }).filter(measurement -> measurement != null && measurement.getWaveform() != null); } } diff --git a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/ShapeCalculator.java b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/ShapeCalculator.java index 86884aac..b6cc470f 100644 --- a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/ShapeCalculator.java +++ b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/ShapeCalculator.java @@ -80,7 +80,6 @@ public List fitShapelineToMeasuredEnvelopes(Collection fitShapelineToMeasuredEnvelopes(Collection fitShapelineToMeasuredEnvelopes(Collection 0 && synthSeis.getLengthInSeconds() < frequencyBandParameter.getMinLength()) { - log.trace( - "Encountered a too small window length while processing {} with length {} and minimum window of {}; processing will skip this file", - velocityMeasurement, - synthSeis.getLengthInSeconds(), - frequencyBandParameter.getMinLength()); + log.trace("Encountered a too small window length while processing {} with length {} and minimum window of {}; processing will skip this file", + velocityMeasurement, + synthSeis.getLengthInSeconds(), + frequencyBandParameter.getMinLength()); return null; } else if (frequencyBandParameter.getMaxLength() > 0 && synthSeis.getLengthInSeconds() > frequencyBandParameter.getMaxLength()) { - log.trace( - "Encountered a too large window length while processing {} with length {} and maxium window of {}; processing will continue on a truncated envelope", - velocityMeasurement, - synthSeis.getLengthInSeconds(), - frequencyBandParameter.getMaxLength()); + log.trace("Encountered a too large window length while processing {} with length {} and maxium window of {}; processing will continue on a truncated envelope", + velocityMeasurement, + synthSeis.getLengthInSeconds(), + frequencyBandParameter.getMaxLength()); synthSeis.cutAfter(travelTime.add(frequencyBandParameter.getMaxLength())); } diff --git a/calibration-service/pom.xml b/calibration-service/pom.xml index 17205e0a..2e05cae8 100644 --- a/calibration-service/pom.xml +++ b/calibration-service/pom.xml @@ -1,11 +1,11 @@ - + gov.llnl.gnem.apps.coda.calibration coda-calibration - 1.0.8.1 + 1.0.9 4.0.0 diff --git a/calibration-standalone/pom.xml b/calibration-standalone/pom.xml index 052f0244..8068f722 100644 --- a/calibration-standalone/pom.xml +++ b/calibration-standalone/pom.xml @@ -1,12 +1,12 @@ - + gov.llnl.gnem.apps.coda.calibration coda-calibration - 1.0.8.1 + 1.0.9 4.0.0 @@ -199,14 +199,6 @@ org.springframework spring-webmvc - - io.springlets - springlets-data-jpa - - - io.springlets - springlets-data-commons - org.springframework.boot spring-boot-starter-web diff --git a/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/CalibrationLocalClient.java b/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/CalibrationLocalClient.java index 7a0efeba..a14798e8 100644 --- a/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/CalibrationLocalClient.java +++ b/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/CalibrationLocalClient.java @@ -47,6 +47,11 @@ public CalibrationLocalClient(CalibrationService service) { public Mono runCalibration(Boolean autoPickingEnabled) { return Mono.just(Boolean.toString(service.startCalibration(autoPickingEnabled))); } + + @Override + public Mono cancelCalibration(Long id) { + return Mono.just(service.cancelCalibration(id)); + } @Override public Mono makeMwMeasurements(Boolean autoPickingEnabled) { diff --git a/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/ReferenceEventLocalClient.java b/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/EventLocalClient.java similarity index 69% rename from calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/ReferenceEventLocalClient.java rename to calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/EventLocalClient.java index 9c59fd2e..b55cd3fb 100644 --- a/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/ReferenceEventLocalClient.java +++ b/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/EventLocalClient.java @@ -23,12 +23,15 @@ import com.fasterxml.jackson.core.JsonProcessingException; -import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ReferenceEventClient; +import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.EventClient; import gov.llnl.gnem.apps.coda.calibration.model.domain.MeasuredMwDetails; import gov.llnl.gnem.apps.coda.calibration.model.domain.MeasuredMwParameters; import gov.llnl.gnem.apps.coda.calibration.model.domain.ReferenceMwParameters; +import gov.llnl.gnem.apps.coda.calibration.model.domain.ValidationMwParameters; +import gov.llnl.gnem.apps.coda.calibration.service.api.CalibrationService; import gov.llnl.gnem.apps.coda.calibration.service.api.MeasuredMwsService; import gov.llnl.gnem.apps.coda.calibration.service.api.ReferenceMwParametersService; +import gov.llnl.gnem.apps.coda.calibration.service.api.ValidationMwParametersService; import gov.llnl.gnem.apps.coda.common.model.domain.Event; import gov.llnl.gnem.apps.coda.common.service.api.WaveformService; import reactor.core.publisher.Flux; @@ -36,16 +39,21 @@ @Component @Primary -public class ReferenceEventLocalClient implements ReferenceEventClient { +public class EventLocalClient implements EventClient { private ReferenceMwParametersService refEventService; + private ValidationMwParametersService valEventService; private MeasuredMwsService measureService; private WaveformService waveformService; + private CalibrationService calService; @Autowired - public ReferenceEventLocalClient(ReferenceMwParametersService refEventService, MeasuredMwsService measureService, WaveformService waveformService) { + public EventLocalClient(ReferenceMwParametersService refEventService, ValidationMwParametersService valEventService, MeasuredMwsService measureService, CalibrationService calService, + WaveformService waveformService) { this.refEventService = refEventService; + this.valEventService = valEventService; this.measureService = measureService; + this.calService = calService; this.waveformService = waveformService; } @@ -59,6 +67,33 @@ public Mono postReferenceEvents(List refEvents) t return Mono.just(refEventService.save(refEvents).toString()); } + @Override + public Mono removeReferenceEventsByEventId(List evids) { + refEventService.deleteAllByEventIds(evids); + return Mono.empty(); + } + + @Override + public Flux getValidationEvents() { + return Flux.fromIterable(valEventService.findAll()).filter(Objects::nonNull).onErrorReturn(new ValidationMwParameters()); + } + + @Override + public Mono postValidationEvents(List valEvents) throws JsonProcessingException { + return Mono.just(valEventService.save(valEvents).toString()); + } + + @Override + public Mono removeValidationEventsByEventId(List evids) { + valEventService.deleteAllByEventIds(evids); + return Mono.empty(); + } + + @Override + public Flux toggleValidationEventsByEventId(List evids) { + return Flux.fromIterable(calService.toggleAllByEventIds(evids)); + } + @Override public Flux getMeasuredEvents() { return Flux.fromIterable(measureService.findAll()).filter(Objects::nonNull).onErrorReturn(new MeasuredMwParameters()); @@ -77,11 +112,4 @@ public Mono getEvent(String eventId) { public Flux getMeasuredEventDetails() { return Flux.fromIterable(measureService.findAllDetails()).filter(Objects::nonNull).onErrorReturn(new MeasuredMwDetails()); } - - @Override - public Mono removeReferenceEventsByEventId(List evids) { - refEventService.deleteAllByEventIds(evids); - return Mono.empty(); - } - } diff --git a/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/SpectraLocalClient.java b/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/SpectraLocalClient.java index 166230b8..c63af385 100644 --- a/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/SpectraLocalClient.java +++ b/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/SpectraLocalClient.java @@ -60,6 +60,13 @@ public Mono getReferenceSpectra(String eventId) { return Mono.just(Optional.ofNullable(service.computeReferenceSpectraForEventId(eventId, sharedParamsService.getFrequencyBands(), PICK_TYPES.LG)).orElseGet(() -> new Spectra())) .onErrorReturn(new Spectra()); } + + @Override + public Mono getValidationSpectra(String eventId) { + //FIXME: Use the calibrations phase for this! + return Mono.just(Optional.ofNullable(service.computeValidationSpectraForEventId(eventId, sharedParamsService.getFrequencyBands(), PICK_TYPES.LG)).orElseGet(() -> new Spectra())) + .onErrorReturn(new Spectra()); + } @Override public Mono> getFitSpectra(String eventId) { diff --git a/common-gui/pom.xml b/common-gui/pom.xml index a69ae567..af8bbc27 100644 --- a/common-gui/pom.xml +++ b/common-gui/pom.xml @@ -1,24 +1,24 @@ - + 4.0.0 gov.llnl.gnem.apps.coda.calibration coda-calibration - 1.0.8.1 + 1.0.9 gov.llnl.gnem.apps.coda.common common-gui jar common-gui - http://www.llnl.gov + https://www.llnl.gov Lawrence Livermore National Laboratory (LLNL) - http://www.llnl.gov + https://www.llnl.gov diff --git a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/controllers/ProgressGui.java b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/controllers/ProgressGui.java index 850c794d..74ae3717 100644 --- a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/controllers/ProgressGui.java +++ b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/controllers/ProgressGui.java @@ -27,6 +27,7 @@ import javafx.scene.Node; import javafx.scene.Parent; import javafx.scene.Scene; +import javafx.scene.control.Button; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; @@ -45,6 +46,9 @@ public class ProgressGui { @FXML private TableView progressTable; + @FXML + private TableColumn cancelColumn; + @FXML private TableColumn progressColumn; @@ -92,6 +96,9 @@ protected void updateItem(Node item, boolean empty) { }; } }); + + cancelColumn.setCellValueFactory(value -> Bindings.createObjectBinding(() -> value.getValue().getCancelButton())); + progressTable.setItems(monitors); progressTable.getSelectionModel().selectedItemProperty().addListener((obs, prevSelection, newSelection) -> { if (newSelection != null) { diff --git a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/converters/sac/SacExporter.java b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/converters/sac/SacExporter.java index 9a293a83..c2f00e05 100644 --- a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/converters/sac/SacExporter.java +++ b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/converters/sac/SacExporter.java @@ -48,62 +48,16 @@ public Result writeWaveformToDirectory(File exportDirectory, Waveform w) String filename = getFileName(w); if (filename != null && !filename.trim().isEmpty()) { try (DataOutputStream os = new DataOutputStream(new BufferedOutputStream(Files.newOutputStream(exportDirectory.toPath().resolve(filename))))) { - try (SACHeader header = new SACHeader()) { - header.setTime(new TimeT(w.getEvent().getOriginTime())); - header.setBeginTime(new TimeT(w.getBeginTime())); - header.setOriginTime(new TimeT(w.getEvent().getOriginTime())); - - header.nevid = Integer.parseInt(w.getEvent().getEventId()); - if (w.getAssociatedPicks() != null) { - for (int i = 0; i < w.getAssociatedPicks().size() && i <= 10; i++) { - try { - WaveformPick pick = w.getAssociatedPicks().get(i); - if (pick.getPickType().equalsIgnoreCase(PICK_TYPES.F.getPhase())) { - header.f = pick.getPickTimeSecFromOrigin(); - } else if (pick.getPickType().equalsIgnoreCase(PICK_TYPES.A.getPhase())) { - header.a = pick.getPickTimeSecFromOrigin(); - } else if (pick.getPickType().equalsIgnoreCase(PICK_TYPES.B.getPhase())) { - header.b = pick.getPickTimeSecFromOrigin(); - } else if (pick.getPickType().equalsIgnoreCase(PICK_TYPES.O.getPhase())) { - header.o = pick.getPickTimeSecFromOrigin(); - } else { - header.setTimePick(i, pick.getPickTimeSecFromOrigin(), pick.getPickName()); - } - } catch (RuntimeException e) { - log.error(e.getMessage(), e); - } - } - } - - header.delta = (float) (1.0 / w.getSampleRate()); - header.kstnm = w.getStream().getStation().getStationName(); - header.kcmpnm = w.getStream().getChannelName(); - header.stla = (float) w.getStream().getStation().getLatitude(); - header.stlo = (float) w.getStream().getStation().getLongitude(); - header.knetwk = w.getStream().getStation().getNetworkName(); - header.kevnm = w.getEvent().getEventId(); - header.evla = (float) w.getEvent().getLatitude(); - header.evlo = (float) w.getEvent().getLongitude(); - String depType = w.getSegmentType(); - if (depType != null && !depType.trim().isEmpty()) { - if (depType.toLowerCase(Locale.ENGLISH).startsWith("dis")) { - header.idep = 6; - } else if (depType.toLowerCase(Locale.ENGLISH).startsWith("vel")) { - header.idep = 7; - } else if (depType.toLowerCase(Locale.ENGLISH).startsWith("acc")) { - header.idep = 8; - } - } - float[] sequence = new Sequence(w.getSegment()).getArray(); - header.npts = sequence.length; - header.write(os); - for (int i = 0; i < sequence.length; i++) { - os.writeFloat(sequence[i]); - } - os.flush(); - - return new Result<>(true, filename); + SACHeader header = sacHeaderFromWaveform(w); + float[] sequence = new Sequence(w.getSegment()).getArray(); + header.npts = sequence.length; + header.write(os); + for (int i = 0; i < sequence.length; i++) { + os.writeFloat(sequence[i]); } + os.flush(); + + return new Result<>(true, filename); } catch (IOException e) { log.error(e.getMessage(), e); return new Result<>(false, e.toString()).setErrors(Collections.singletonList(e)); @@ -115,6 +69,58 @@ public Result writeWaveformToDirectory(File exportDirectory, Waveform w) return new Result<>(false, message); } + public SACHeader sacHeaderFromWaveform(Waveform w) throws IOException { + try (SACHeader header = new SACHeader()) { + header.setTime(new TimeT(w.getEvent().getOriginTime())); + header.setBeginTime(new TimeT(w.getBeginTime())); + header.setOriginTime(new TimeT(w.getEvent().getOriginTime())); + + header.nevid = Integer.parseInt(w.getEvent().getEventId()); + if (w.getAssociatedPicks() != null) { + for (int i = 0; i < w.getAssociatedPicks().size() && i <= 10; i++) { + try { + WaveformPick pick = w.getAssociatedPicks().get(i); + if (pick.getPickType().equalsIgnoreCase(PICK_TYPES.F.getPhase())) { + header.f = pick.getPickTimeSecFromOrigin(); + } else if (pick.getPickType().equalsIgnoreCase(PICK_TYPES.A.getPhase())) { + header.a = pick.getPickTimeSecFromOrigin(); + } else if (pick.getPickType().equalsIgnoreCase(PICK_TYPES.B.getPhase())) { + header.b = pick.getPickTimeSecFromOrigin(); + } else if (pick.getPickType().equalsIgnoreCase(PICK_TYPES.O.getPhase())) { + header.o = pick.getPickTimeSecFromOrigin(); + } else { + header.setTimePick(i, pick.getPickTimeSecFromOrigin(), pick.getPickName()); + } + } catch (RuntimeException e) { + log.error(e.getMessage(), e); + } + } + } + + header.delta = (float) (1.0 / w.getSampleRate()); + header.kstnm = w.getStream().getStation().getStationName(); + header.kcmpnm = w.getStream().getChannelName(); + header.stla = (float) w.getStream().getStation().getLatitude(); + header.stlo = (float) w.getStream().getStation().getLongitude(); + header.knetwk = w.getStream().getStation().getNetworkName(); + header.kevnm = w.getEvent().getEventId(); + header.evla = (float) w.getEvent().getLatitude(); + header.evlo = (float) w.getEvent().getLongitude(); + header.evdp = (float) w.getEvent().getDepth(); + String depType = w.getSegmentType(); + if (depType != null && !depType.trim().isEmpty()) { + if (depType.toLowerCase(Locale.ENGLISH).startsWith("dis")) { + header.idep = 6; + } else if (depType.toLowerCase(Locale.ENGLISH).startsWith("vel")) { + header.idep = 7; + } else if (depType.toLowerCase(Locale.ENGLISH).startsWith("acc")) { + header.idep = 8; + } + } + return header; + } + } + private boolean waveformFullySpecified(Waveform w) { return w != null && w.getLowFrequency() != null diff --git a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/converters/sac/SacLoader.java b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/converters/sac/SacLoader.java index a0f47840..2ff52fb7 100644 --- a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/converters/sac/SacLoader.java +++ b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/converters/sac/SacLoader.java @@ -178,7 +178,15 @@ public Result convertSacFileToWaveform(File file) { return exceptionalResult(headerResult.getErrors()); } double stationLongitude = header.stlo; - + + double eventDepth; + if (SACHeader.isDefault(header.evdp)) { + eventDepth = 0; + } + else { + eventDepth = header.evdp; + } + String dataType = StringUtils.trimToEmpty((String) header.getVariableMap().get("depvariabletype")).toLowerCase(Locale.ENGLISH); if (dataType.startsWith("acc")) { dataType = ACCELERATION; @@ -239,6 +247,7 @@ public Result convertSacFileToWaveform(File file) { new Event().setEventId(evid) .setLatitude(eventLatitude) .setLongitude(eventLongitude) + .setDepth(eventDepth) .setOriginTime(Date.from(Instant.ofEpochMilli(originTime.getMilliseconds())))) .setSegment(segment) .setSegmentType(dataType) diff --git a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/data/client/CodaWebClientBuilder.java b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/data/client/CodaWebClientBuilder.java index 575439cc..a172d8e1 100644 --- a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/data/client/CodaWebClientBuilder.java +++ b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/data/client/CodaWebClientBuilder.java @@ -186,7 +186,6 @@ public void close() { if (strategies != null) { builder.exchangeStrategies(strategies); } - // builder.exchangeStrategies(configurer -> configurer.codecs(codecs -> codecs.defaultCodecs().maxInMemorySize(-1))); return builder.build(); } diff --git a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/util/ProgressMonitor.java b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/util/ProgressMonitor.java index 9908bea0..93e3fe2d 100644 --- a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/util/ProgressMonitor.java +++ b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/util/ProgressMonitor.java @@ -15,20 +15,31 @@ package gov.llnl.gnem.apps.coda.common.gui.util; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.Observable; import java.util.Observer; import gov.llnl.gnem.apps.coda.common.model.messaging.Progress; import javafx.application.Platform; +import javafx.beans.binding.Bindings; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; +import javafx.geometry.Insets; +import javafx.geometry.Pos; import javafx.scene.Parent; +import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.ProgressBar; import javafx.scene.layout.VBox; import javafx.scene.text.Font; +import javafx.scene.text.TextAlignment; public class ProgressMonitor extends VBox implements Observer { + private Button cancelButton = new Button(); @FXML private ProgressBar progressBar; @@ -38,6 +49,7 @@ public class ProgressMonitor extends VBox implements Observer { private String displayableName; private String progressStage; + private final ObservableList cancelFunctions = FXCollections.observableArrayList(); public ProgressMonitor(String displayableName, ProgressListener progressListener) { this.displayableName = displayableName; @@ -58,6 +70,19 @@ public ProgressMonitor(String displayableName, ProgressListener progressListener progressBar.setProgress(ProgressBar.INDETERMINATE_PROGRESS); } label.setText(""); + + cancelButton.setAlignment(Pos.CENTER); + cancelButton.setPadding(new Insets(0, 0, 0, 0)); + cancelButton.setPrefSize(25.0, 25.0); + cancelButton.setText("X"); + cancelButton.setTextAlignment(TextAlignment.CENTER); + cancelButton.setOnAction((ActionEvent event) -> { + List funcs = new ArrayList<>(cancelFunctions.size()); + funcs.addAll(cancelFunctions); + funcs.forEach(Runnable::run); + }); + cancelButton.visibleProperty().bind(Bindings.size(cancelFunctions).greaterThan(0)); + } catch (IOException e) { throw new IllegalStateException(e); } @@ -100,4 +125,16 @@ public ProgressMonitor setProgressStage(String progressStage) { public ProgressBar getProgressBar() { return progressBar; } + + public void addCancelCallback(Runnable cancelFunction) { + cancelFunctions.add(cancelFunction); + } + + public void clearCancelCallbacks() { + cancelFunctions.clear(); + } + + public Button getCancelButton() { + return cancelButton; + } } diff --git a/common-gui/src/main/resources/fxml/ProgressDisplay.fxml b/common-gui/src/main/resources/fxml/ProgressDisplay.fxml index b81ec37a..7700da15 100644 --- a/common-gui/src/main/resources/fxml/ProgressDisplay.fxml +++ b/common-gui/src/main/resources/fxml/ProgressDisplay.fxml @@ -26,8 +26,8 @@ minWidth="200.0" prefWidth="-1.0" text="Task" /> - + diff --git a/common-gui/src/main/resources/fxml/ProgressMonitor.fxml b/common-gui/src/main/resources/fxml/ProgressMonitor.fxml index 99d3f8ee..7c486582 100644 --- a/common-gui/src/main/resources/fxml/ProgressMonitor.fxml +++ b/common-gui/src/main/resources/fxml/ProgressMonitor.fxml @@ -1,14 +1,13 @@ + - + diff --git a/common-gui/src/test/java/gov/llnl/gnem/apps/coda/common/gui/converters/sac/SacExporterTest.java b/common-gui/src/test/java/gov/llnl/gnem/apps/coda/common/gui/converters/sac/SacExporterTest.java index a6b41992..4809c73d 100644 --- a/common-gui/src/test/java/gov/llnl/gnem/apps/coda/common/gui/converters/sac/SacExporterTest.java +++ b/common-gui/src/test/java/gov/llnl/gnem/apps/coda/common/gui/converters/sac/SacExporterTest.java @@ -20,17 +20,22 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.sql.Date; +import java.time.Duration; import java.time.Instant; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Locale; import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.IntStream; import org.junit.Assert; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.aggregator.ArgumentsAccessor; import org.junit.jupiter.params.provider.MethodSource; @@ -40,6 +45,7 @@ import gov.llnl.gnem.apps.coda.common.model.domain.Stream; import gov.llnl.gnem.apps.coda.common.model.domain.Waveform; import gov.llnl.gnem.apps.coda.common.model.messaging.Result; +import llnl.gnem.core.io.SAC.SACHeader; public class SacExporterTest { @@ -55,23 +61,24 @@ private static Collection testParamSet() throws Exception { params.add(new Object[] { new Waveform().setStream(new Stream()), "", waveformNotValidAssertions() }); params.add(new Object[] { new Waveform().setStream(new Stream()).setEvent(new Event()), "", waveformNotValidAssertions() }); params.add(new Object[] { new Waveform().setStream(new Stream().setStation(new Station())).setEvent(new Event()), "", waveformNotValidAssertions() }); - params.add( - new Object[] { new Waveform().setLowFrequency(.0).setHighFrequency(.0).setSegmentType("vel").setStream(new Stream().setStation(new Station())).setEvent(new Event()), "", - waveformNotValidAssertions() }); - - params.add( - new Object[] { new Waveform().setLowFrequency(.0) - .setHighFrequency(.0) - .setSegmentType("vel") - .setSampleRate(.0) - .setBeginTime(Date.from(Instant.now())) - .setEndTime(Date.from(Instant.now())) - .setStream(new Stream().setChannelName(Stream.TYPE_STACK).setStation(new Station().setStationName("RNG"))) - .setEvent(new Event().setEventId("12345").setOriginTime(Date.from(Instant.now()))), - "RNG_STACK_12345_0.0_0.0_VEL_.ENV", waveformValidAssertions() }); + params.add(new Object[] { new Waveform().setLowFrequency(.0).setHighFrequency(.0).setSegmentType("vel").setStream(new Stream().setStation(new Station())).setEvent(new Event()), "", + waveformNotValidAssertions() }); + + params.add(new Object[] { createValidWaveform(), "RNG_STACK_12345_0.0_0.0_VEL_.ENV", waveformValidAssertions() }); return params; } + public static Waveform createValidWaveform() { + return new Waveform().setLowFrequency(.0) + .setHighFrequency(.0) + .setSegmentType("vel") + .setSampleRate(.0) + .setBeginTime(Date.from(Instant.now())) + .setEndTime(Date.from(Instant.now())) + .setStream(new Stream().setChannelName(Stream.TYPE_STACK).setStation(new Station().setStationName("RNG"))) + .setEvent(new Event().setEventId("12345").setDepth(100.0).setOriginTime(Date.from(Instant.now()))); + } + @BeforeAll public static void setUpBeforeClass() throws Exception { testDir = Files.createDirectory(Paths.get(".sac_exporter_test_" + Instant.now().toEpochMilli())).toFile(); @@ -107,6 +114,14 @@ public void testGetFileName(Waveform input, String expectedFilename) throws Exce Assert.assertEquals(expectedFilename, actual); } + @Test + public void testEventDepthPopulated() throws Exception { + //GMPAPPS-1947 Envelope tool was dropping event depth info during import/export. + Waveform waveform = createValidWaveform(); + SACHeader header = exporter.sacHeaderFromWaveform(waveform); + Assert.assertTrue("Expect that the waveform should have a populated event depth if the original file had it.", header.evdp != 0 && !SACHeader.isDefault(header.evdp)); + } + private static Consumer> waveformNotValidAssertions() throws Exception { return res -> { Assert.assertFalse("Result on an invalid waveform should be false", res.isSuccess()); diff --git a/common-gui/src/test/java/gov/llnl/gnem/apps/coda/common/gui/converters/sac/SacLoaderTest.java b/common-gui/src/test/java/gov/llnl/gnem/apps/coda/common/gui/converters/sac/SacLoaderTest.java index 736ba729..9470c52b 100644 --- a/common-gui/src/test/java/gov/llnl/gnem/apps/coda/common/gui/converters/sac/SacLoaderTest.java +++ b/common-gui/src/test/java/gov/llnl/gnem/apps/coda/common/gui/converters/sac/SacLoaderTest.java @@ -61,9 +61,17 @@ public void teardown() { @MethodSource("singleFile") public void testConvertFile(File inputFile) throws Exception { Result res = loader.convertFile(inputFile).doOnError(error -> Assert.fail(error.getMessage())).block(Duration.ofSeconds(10l)); - Assert.assertTrue("Expect that waveform result should all complete successfully", res.isSuccess()); - Assert.assertTrue("Expect that waveform result should have no error or warning messages", res.getErrors().isEmpty()); - Assert.assertTrue("Expect that waveform result should have a Waveform payload", res.getResultPayload().isPresent()); + Assert.assertTrue("Expect that waveform results should all complete successfully", res.isSuccess()); + Assert.assertTrue("Expect that waveform results should have no error or warning messages", res.getErrors().isEmpty()); + Assert.assertTrue("Expect that waveform results should have a Waveform payload", res.getResultPayload().isPresent()); + } + + public static Collection singleFile() throws IOException { + try (Stream stream = Files.walk(Paths.get("src/test/resources/sac/"))) { + return stream.filter(path -> path.getFileName().toString().toLowerCase(Locale.ENGLISH).endsWith(".sac")).map(path -> { + return Arguments.of(path.toFile()); + }).collect(Collectors.toList()); + } } @Test @@ -79,16 +87,25 @@ public void testConvertFiles() throws Exception { List> results = loader.convertFiles(multipleFiles.get(0)).doOnError(error -> Assert.fail(error.getMessage())).collectList().block(Duration.ofSeconds(10l)); for (Result res : results) { Assert.assertTrue("Expect that waveform results should all complete successfully", res.isSuccess()); - Assert.assertTrue("Expect that waveform result should have no error or warning messages", res.getErrors().isEmpty()); - Assert.assertTrue("Expect that waveform result should have a Waveform payload", res.getResultPayload().isPresent()); + Assert.assertTrue("Expect that waveform results should have no error or warning messages", res.getErrors().isEmpty()); + Assert.assertTrue("Expect that waveform results should have a Waveform payload", res.getResultPayload().isPresent()); } } - public static Collection singleFile() throws IOException { - try (Stream stream = Files.walk(Paths.get("src/test/resources/sac/"))) { - return stream.filter(path -> path.getFileName().toString().toLowerCase(Locale.ENGLISH).endsWith(".sac")).map(path -> { - return Arguments.of(path.toFile()); - }).collect(Collectors.toList()); + @Test + public void testEventDepthPopulated() throws Exception { + //GMPAPPS-1947 Envelope tool was dropping event depth info. + List> multipleFiles = IntStream.range(0, 3).mapToObj(i -> { + try (Stream stream = Files.walk(Paths.get("src/test/resources/sac/"))) { + return stream.filter(path -> path.getFileName().toString().toLowerCase(Locale.ENGLISH).endsWith(".sac")).map(path -> path.toFile()).collect(Collectors.toList()); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + }).filter(o -> o != null).collect(Collectors.toList()); + List> results = loader.convertFiles(multipleFiles.get(0)).doOnError(error -> Assert.fail(error.getMessage())).collectList().block(Duration.ofSeconds(10l)); + for (Result res : results) { + Assert.assertTrue("Expect that the waveform should have a populated event depth if the original file had it.", res.getResultPayload().get().getEvent().getDepth() != 0); } } } diff --git a/common-service/common-application/pom.xml b/common-service/common-application/pom.xml index ee22a23a..ec7dbdbe 100644 --- a/common-service/common-application/pom.xml +++ b/common-service/common-application/pom.xml @@ -1,11 +1,11 @@ - + gov.llnl.gnem.apps.coda.common common-service - 1.0.8.1 + 1.0.9 4.0.0 @@ -86,14 +86,6 @@ org.springframework spring-webmvc - - io.springlets - springlets-data-jpa - - - io.springlets - springlets-data-commons - org.springframework.boot spring-boot-starter-actuator diff --git a/common-service/common-model/pom.xml b/common-service/common-model/pom.xml index e221f3d0..6497be2f 100644 --- a/common-service/common-model/pom.xml +++ b/common-service/common-model/pom.xml @@ -1,11 +1,11 @@ - + gov.llnl.gnem.apps.coda.common common-service - 1.0.8.1 + 1.0.9 4.0.0 @@ -22,10 +22,6 @@ org.eclipse.collections eclipse-collections - - io.springlets - springlets-context - org.springframework spring-context diff --git a/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/Event.java b/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/Event.java index ccaaa46b..a21d86a7 100644 --- a/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/Event.java +++ b/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/Event.java @@ -56,6 +56,10 @@ public class Event implements Serializable { @NumberFormat private double longitude; + @Column(name = "eventDepth") + @NumberFormat + private double depth; + public String getEventId() { return this.eventId; } @@ -95,6 +99,15 @@ public Event setLongitude(double longitude) { return this; } + public double getDepth() { + return this.depth; + } + + public Event setDepth(double depth) { + this.depth = depth; + return this; + } + @Override public int hashCode() { final int prime = 31; @@ -127,7 +140,18 @@ public boolean equals(Object obj) { @Override public String toString() { - return "Event [eventId=" + eventId + ", originTime=" + originTime + ", latitude=" + latitude + ", longitude=" + longitude + "]"; + StringBuilder builder = new StringBuilder(); + builder.append("Event [eventId=") + .append(eventId) + .append(", originTime=") + .append(originTime) + .append(", latitude=") + .append(latitude) + .append(", longitude=") + .append(longitude) + .append(", depth=") + .append(depth) + .append("]"); + return builder.toString(); } - } diff --git a/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/util/SPECTRA_TYPES.java b/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/util/SPECTRA_TYPES.java index 218e7293..93b612f8 100644 --- a/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/util/SPECTRA_TYPES.java +++ b/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/util/SPECTRA_TYPES.java @@ -15,5 +15,5 @@ package gov.llnl.gnem.apps.coda.common.model.util; public enum SPECTRA_TYPES { - REF, FIT, UQ1, UQ2, UNK + REF, FIT, UQ1, UQ2, VAL, UNK } diff --git a/common-service/common-repository/pom.xml b/common-service/common-repository/pom.xml index 9ce79aac..330ea915 100644 --- a/common-service/common-repository/pom.xml +++ b/common-service/common-repository/pom.xml @@ -1,10 +1,10 @@ - + gov.llnl.gnem.apps.coda.common common-service - 1.0.8.1 + 1.0.9 4.0.0 @@ -18,14 +18,6 @@ h2 test - - io.springlets - springlets-data-commons - - - io.springlets - springlets-data-jpa - gov.llnl.gnem.apps.coda.common common-model diff --git a/common-service/common-repository/src/main/java/gov/llnl/gnem/apps/coda/common/repository/DetachableJpaRepoImpl.java b/common-service/common-repository/src/main/java/gov/llnl/gnem/apps/coda/common/repository/DetachableJpaRepoImpl.java index 84912d06..0d54ab28 100644 --- a/common-service/common-repository/src/main/java/gov/llnl/gnem/apps/coda/common/repository/DetachableJpaRepoImpl.java +++ b/common-service/common-repository/src/main/java/gov/llnl/gnem/apps/coda/common/repository/DetachableJpaRepoImpl.java @@ -19,19 +19,9 @@ import javax.persistence.EntityManager; import org.springframework.data.jpa.repository.support.JpaEntityInformation; +import org.springframework.data.jpa.repository.support.SimpleJpaRepository; -import io.springlets.data.jpa.repository.support.DetachableJpaRepositoryImpl; - -/** - *

- * This is a quick hack to the existing DetachableJpaRepositoryImpl to correctly - * implement the findOneDetached with the new findById API changes in Spring - * JPA. It should be removed ASAP when the API has settled. - *

- * - * @see DetachableJpaRepositoryImpl - */ -public class DetachableJpaRepoImpl extends DetachableJpaRepositoryImpl { +public class DetachableJpaRepoImpl extends SimpleJpaRepository implements DetachableJpaRepository { private EntityManager entityManager; public DetachableJpaRepoImpl(JpaEntityInformation entityInformation, EntityManager entityManager) { diff --git a/common-service/common-repository/src/main/java/gov/llnl/gnem/apps/coda/common/repository/DetachableJpaRepository.java b/common-service/common-repository/src/main/java/gov/llnl/gnem/apps/coda/common/repository/DetachableJpaRepository.java new file mode 100644 index 00000000..b78d1203 --- /dev/null +++ b/common-service/common-repository/src/main/java/gov/llnl/gnem/apps/coda/common/repository/DetachableJpaRepository.java @@ -0,0 +1,33 @@ +/* +* Copyright (c) 2019, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* CODE-743439. +* All rights reserved. +* +* Licensed under the Apache License, Version 2.0 (the “Licensee”); you may not use this file except in compliance with the License. You may obtain a copy of the License at: +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and limitations under the license. +* +* This work was performed under the auspices of the U.S. Department of Energy +* by Lawrence Livermore National Laboratory under Contract DE-AC52-07NA27344. +*/ +package gov.llnl.gnem.apps.coda.common.repository; + + +import java.io.Serializable; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.repository.NoRepositoryBean; +@NoRepositoryBean +public interface DetachableJpaRepository extends JpaRepository { + + /** + * Retrieves an entity by its id and detaches it from the EntityManager. + * + * @param id must not be {@literal null}. + * @return the entity with the given id or {@literal null} if none found + * @throws IllegalArgumentException if {@code id} is {@literal null} + */ + T findOneDetached(ID id); + +} \ No newline at end of file diff --git a/common-service/common-repository/src/main/java/gov/llnl/gnem/apps/coda/common/repository/WaveformPickRepository.java b/common-service/common-repository/src/main/java/gov/llnl/gnem/apps/coda/common/repository/WaveformPickRepository.java index 622c1124..a33a96b4 100644 --- a/common-service/common-repository/src/main/java/gov/llnl/gnem/apps/coda/common/repository/WaveformPickRepository.java +++ b/common-service/common-repository/src/main/java/gov/llnl/gnem/apps/coda/common/repository/WaveformPickRepository.java @@ -18,7 +18,7 @@ import gov.llnl.gnem.apps.coda.common.model.domain.Waveform; import gov.llnl.gnem.apps.coda.common.model.domain.WaveformPick; -import io.springlets.data.jpa.repository.DetachableJpaRepository; +import gov.llnl.gnem.apps.coda.common.repository.DetachableJpaRepository; @Transactional public interface WaveformPickRepository extends DetachableJpaRepository { diff --git a/common-service/common-repository/src/main/java/gov/llnl/gnem/apps/coda/common/repository/WaveformRepository.java b/common-service/common-repository/src/main/java/gov/llnl/gnem/apps/coda/common/repository/WaveformRepository.java index 38aab568..0f5eae6a 100644 --- a/common-service/common-repository/src/main/java/gov/llnl/gnem/apps/coda/common/repository/WaveformRepository.java +++ b/common-service/common-repository/src/main/java/gov/llnl/gnem/apps/coda/common/repository/WaveformRepository.java @@ -28,7 +28,7 @@ import gov.llnl.gnem.apps.coda.common.model.domain.Stream; import gov.llnl.gnem.apps.coda.common.model.domain.Waveform; import gov.llnl.gnem.apps.coda.common.model.domain.WaveformPick; -import io.springlets.data.jpa.repository.DetachableJpaRepository; +import gov.llnl.gnem.apps.coda.common.repository.DetachableJpaRepository; @Transactional public interface WaveformRepository extends DetachableJpaRepository { diff --git a/common-service/common-service-api/pom.xml b/common-service/common-service-api/pom.xml index 72089254..96dc89ba 100644 --- a/common-service/common-service-api/pom.xml +++ b/common-service/common-service-api/pom.xml @@ -1,10 +1,10 @@ - + gov.llnl.gnem.apps.coda.common common-service - 1.0.8.1 + 1.0.9 4.0.0 @@ -17,10 +17,6 @@ gov.llnl.gnem.apps.coda.common common-model
- - io.springlets - springlets-data-commons -
diff --git a/common-service/common-service-impl/pom.xml b/common-service/common-service-impl/pom.xml index ab19f2d3..f401e5ac 100644 --- a/common-service/common-service-impl/pom.xml +++ b/common-service/common-service-impl/pom.xml @@ -1,11 +1,11 @@ - + gov.llnl.gnem.apps.coda.common common-service - 1.0.8.1 + 1.0.9 4.0.0 diff --git a/common-service/pom.xml b/common-service/pom.xml index 1355880b..b6e677fc 100644 --- a/common-service/pom.xml +++ b/common-service/pom.xml @@ -1,11 +1,11 @@ - + gov.llnl.gnem.apps.coda.calibration coda-calibration - 1.0.8.1 + 1.0.9 gov.llnl.gnem.apps.coda.common diff --git a/envelope-gui/pom.xml b/envelope-gui/pom.xml index f9a8f056..093fda9b 100644 --- a/envelope-gui/pom.xml +++ b/envelope-gui/pom.xml @@ -1,24 +1,24 @@ - + 4.0.0 gov.llnl.gnem.apps.coda.calibration coda-calibration - 1.0.8.1 + 1.0.9 envelope-gui gov.llnl.gnem.apps.coda.envelope jar envelope-gui - http://www.llnl.gov + https://www.llnl.gov Lawrence Livermore National Laboratory (LLNL) - http://www.llnl.gov + https://www.llnl.gov @@ -38,7 +38,7 @@ spring-milestones - http://repo.spring.io/milestone + https://repo.spring.io/milestone diff --git a/envelope-service/envelope-application/pom.xml b/envelope-service/envelope-application/pom.xml index 11a1086d..f93a4aff 100644 --- a/envelope-service/envelope-application/pom.xml +++ b/envelope-service/envelope-application/pom.xml @@ -1,11 +1,11 @@ - + gov.llnl.gnem.apps.coda.envelope envelope-service - 1.0.8.1 + 1.0.9 4.0.0 @@ -82,14 +82,6 @@ org.springframework spring-webmvc
- - io.springlets - springlets-data-jpa - - - io.springlets - springlets-data-commons - org.springframework.boot spring-boot-starter-web diff --git a/envelope-service/envelope-model/pom.xml b/envelope-service/envelope-model/pom.xml index 0f234bba..d4904595 100644 --- a/envelope-service/envelope-model/pom.xml +++ b/envelope-service/envelope-model/pom.xml @@ -1,10 +1,10 @@ - + gov.llnl.gnem.apps.coda.envelope envelope-service - 1.0.8.1 + 1.0.9 4.0.0 @@ -13,10 +13,6 @@ envelope-model - - io.springlets - springlets-context - org.springframework spring-context diff --git a/envelope-service/envelope-repository/pom.xml b/envelope-service/envelope-repository/pom.xml index 9422f684..4aad408d 100644 --- a/envelope-service/envelope-repository/pom.xml +++ b/envelope-service/envelope-repository/pom.xml @@ -1,10 +1,10 @@ - + gov.llnl.gnem.apps.coda.envelope envelope-service - 1.0.8.1 + 1.0.9 4.0.0 @@ -22,14 +22,6 @@ h2 test - - io.springlets - springlets-data-commons - - - io.springlets - springlets-data-jpa - gov.llnl.gnem.apps.coda.common common-repository diff --git a/envelope-service/envelope-service-api/pom.xml b/envelope-service/envelope-service-api/pom.xml index 9e430d28..15cacf0a 100644 --- a/envelope-service/envelope-service-api/pom.xml +++ b/envelope-service/envelope-service-api/pom.xml @@ -1,11 +1,11 @@ - + gov.llnl.gnem.apps.coda.envelope envelope-service - 1.0.8.1 + 1.0.9 4.0.0 @@ -18,10 +18,6 @@ gov.llnl.gnem.apps.coda.envelope envelope-model - - io.springlets - springlets-data-commons - gov.llnl.gnem.apps.coda.common common-model diff --git a/envelope-service/envelope-service-impl/pom.xml b/envelope-service/envelope-service-impl/pom.xml index 550aab49..cbc31199 100644 --- a/envelope-service/envelope-service-impl/pom.xml +++ b/envelope-service/envelope-service-impl/pom.xml @@ -1,12 +1,12 @@ - + gov.llnl.gnem.apps.coda.envelope envelope-service - 1.0.8.1 + 1.0.9 4.0.0 diff --git a/envelope-service/pom.xml b/envelope-service/pom.xml index 66035bbb..00e61912 100644 --- a/envelope-service/pom.xml +++ b/envelope-service/pom.xml @@ -1,11 +1,11 @@ - + gov.llnl.gnem.apps.coda.calibration coda-calibration - 1.0.8.1 + 1.0.9 gov.llnl.gnem.apps.coda.envelope diff --git a/envelope-standalone/pom.xml b/envelope-standalone/pom.xml index fea19da2..ee8a5ae7 100644 --- a/envelope-standalone/pom.xml +++ b/envelope-standalone/pom.xml @@ -1,12 +1,12 @@ - + gov.llnl.gnem.apps.coda.calibration coda-calibration - 1.0.8.1 + 1.0.9 4.0.0 diff --git a/externals/pom.xml b/externals/pom.xml index 3c853fe0..5b885ade 100644 --- a/externals/pom.xml +++ b/externals/pom.xml @@ -1,29 +1,29 @@ - + 4.0.0 gov.llnl.gnem.apps.coda.calibration coda-calibration - 1.0.8.1 + 1.0.9 externals jar externals - http://www.llnl.gov + https://www.llnl.gov Lawrence Livermore National Laboratory (LLNL) - http://www.llnl.gov + https://www.llnl.gov - + com.google.guava guava diff --git a/externals/src/main/java/llnl/gnem/core/io/SAC/SACFileReader.java b/externals/src/main/java/llnl/gnem/core/io/SAC/SACFileReader.java index 122270a8..863e6ba8 100755 --- a/externals/src/main/java/llnl/gnem/core/io/SAC/SACFileReader.java +++ b/externals/src/main/java/llnl/gnem/core/io/SAC/SACFileReader.java @@ -38,33 +38,6 @@ public SACFileReader(File file) throws IOException { path = file.getAbsolutePath(); } - //constructor - public SACFileReader(ObjectInput stream) { - try { - header = new SACHeader(stream); - - totalNumSamples = header.npts; - nextSample = 0; - numSamplesRemaining = totalNumSamples; - station = (header.kstnm).trim(); - channel = (header.kcmpnm).trim(); - samplingRate = 1.0 / (header.delta); - timeT = new TimeT(header.nzyear, header.nzjday, header.nzhour, header.nzmin, header.nzsec, header.nzmsec); - foff = 4 * WORDS_IN_HEADER; - timeT = timeT.add(header.b); - startTime = timeT.getEpochTime(); - - if (header.checkByteSwap()) { - format = CSS_F4; - } else { - format = CSS_T4; - } - - } catch (IOException e) { - throw new IllegalStateException(e.getMessage()); - } - } - public SACFileReader(InputStream stream) { try { header = new SACHeader(stream); diff --git a/externals/src/main/java/llnl/gnem/core/util/Passband.java b/externals/src/main/java/llnl/gnem/core/util/Passband.java index 7a919272..91f2cdfd 100755 --- a/externals/src/main/java/llnl/gnem/core/util/Passband.java +++ b/externals/src/main/java/llnl/gnem/core/util/Passband.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2018, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* Copyright (c) 2020, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory * CODE-743439. * All rights reserved. * This file is part of CCT. For details, see https://github.com/LLNL/coda-calibration-tool. @@ -14,13 +14,10 @@ */ package llnl.gnem.core.util; -/** - * A type-safe enum that describes the passband for a filter. - * - * @author Doug Dodge - */ -public class Passband { - private final String name; +public enum Passband { + BAND_PASS("BP"), BAND_REJECT("BR"), LOW_PASS("LP"), HIGH_PASS("HP"); + + private String name; private Passband(String name) { this.name = name; @@ -28,7 +25,7 @@ private Passband(String name) { /** * A string representation of the passband for a filter suitable for use - * with the dbh.ButterworthFilter.. + * with the ButterworthFilter.. * * @return A String with the one of the values "LP", or "HP", "BP", "BR" */ @@ -36,16 +33,6 @@ public String toString() { return name; } - /** - * Get all the passband codes known to this class - * - * @return A String array containing all the passband codes - */ - public static String[] getPassBandCodes() { - String[] codes = { "BP", "BR", "LP", "HP" }; - return codes; - } - /** * Returns a Passband object given a 2-character String descriptor. Only * recognized codes are "BP", "LP", "HP", "BR". Any other String will result @@ -55,7 +42,7 @@ public static String[] getPassBandCodes() { * The code of the desired passband object. * @return The specified Passband object. */ - public static Passband getPassbandFromString(final String code) { + public static Passband getPassband(final String code) { if (code.equals("BP")) return Passband.BAND_PASS; else if (code.equals("LP")) @@ -67,30 +54,4 @@ else if (code.equals("BR")) else return null; } - - public static Passband[] getAvailablePassBands() { - Passband[] result = new Passband[4]; - result[0] = BAND_PASS; - result[1] = BAND_REJECT; - result[2] = LOW_PASS; - result[3] = HIGH_PASS; - return result; - } - - /** - * Specifies a band-pass filter - */ - public final static Passband BAND_PASS = new Passband("BP"); - /** - * Specifies a band-reject filter - */ - public final static Passband BAND_REJECT = new Passband("BR"); - /** - * Specifies a low-pass filter - */ - public final static Passband LOW_PASS = new Passband("LP"); - /** - * Specifies a high-pass filter - */ - public final static Passband HIGH_PASS = new Passband("HP"); } diff --git a/mapping/pom.xml b/mapping/pom.xml index f2f8f908..36f09f82 100644 --- a/mapping/pom.xml +++ b/mapping/pom.xml @@ -1,24 +1,24 @@ - + 4.0.0 gov.llnl.gnem.apps.coda.calibration coda-calibration - 1.0.8.1 + 1.0.9 gov.llnl.gnem.apps.coda.common mapping jar mapping - http://www.llnl.gov + https://www.llnl.gov Lawrence Livermore National Laboratory (LLNL) - http://www.llnl.gov + https://www.llnl.gov diff --git a/mapping/src/main/resources/leaflet/images/cancel.png b/mapping/src/main/resources/leaflet/images/cancel.png new file mode 100755 index 00000000..a4e7c492 Binary files /dev/null and b/mapping/src/main/resources/leaflet/images/cancel.png differ diff --git a/mapping/src/main/resources/leaflet/images/cancel.svg b/mapping/src/main/resources/leaflet/images/cancel.svg new file mode 100755 index 00000000..081c4fdf --- /dev/null +++ b/mapping/src/main/resources/leaflet/images/cancel.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/mapping/src/main/resources/leaflet/images/cancel_@2X.png b/mapping/src/main/resources/leaflet/images/cancel_@2X.png new file mode 100755 index 00000000..dcc72f0c Binary files /dev/null and b/mapping/src/main/resources/leaflet/images/cancel_@2X.png differ diff --git a/mapping/src/main/resources/leaflet/images/check.png b/mapping/src/main/resources/leaflet/images/check.png new file mode 100755 index 00000000..55f274b1 Binary files /dev/null and b/mapping/src/main/resources/leaflet/images/check.png differ diff --git a/mapping/src/main/resources/leaflet/images/check.svg b/mapping/src/main/resources/leaflet/images/check.svg new file mode 100755 index 00000000..e0efc03f --- /dev/null +++ b/mapping/src/main/resources/leaflet/images/check.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/mapping/src/main/resources/leaflet/images/check_@2X.png b/mapping/src/main/resources/leaflet/images/check_@2X.png new file mode 100755 index 00000000..df8032e4 Binary files /dev/null and b/mapping/src/main/resources/leaflet/images/check_@2X.png differ diff --git a/mapping/src/main/resources/leaflet/images/focus.png b/mapping/src/main/resources/leaflet/images/focus.png new file mode 100755 index 00000000..5a87d243 Binary files /dev/null and b/mapping/src/main/resources/leaflet/images/focus.png differ diff --git a/mapping/src/main/resources/leaflet/images/focus.svg b/mapping/src/main/resources/leaflet/images/focus.svg new file mode 100755 index 00000000..1761ea65 --- /dev/null +++ b/mapping/src/main/resources/leaflet/images/focus.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/mapping/src/main/resources/leaflet/images/focus_@2X.png b/mapping/src/main/resources/leaflet/images/focus_@2X.png new file mode 100755 index 00000000..1eb7dd4c Binary files /dev/null and b/mapping/src/main/resources/leaflet/images/focus_@2X.png differ diff --git a/mapping/src/main/resources/leaflet/images/leaflet-measure.png b/mapping/src/main/resources/leaflet/images/leaflet-measure.png new file mode 100644 index 00000000..73258b1c Binary files /dev/null and b/mapping/src/main/resources/leaflet/images/leaflet-measure.png differ diff --git a/mapping/src/main/resources/leaflet/images/rulers.png b/mapping/src/main/resources/leaflet/images/rulers.png new file mode 100755 index 00000000..5d6339d9 Binary files /dev/null and b/mapping/src/main/resources/leaflet/images/rulers.png differ diff --git a/mapping/src/main/resources/leaflet/images/rulers.svg b/mapping/src/main/resources/leaflet/images/rulers.svg new file mode 100755 index 00000000..a08da9f9 --- /dev/null +++ b/mapping/src/main/resources/leaflet/images/rulers.svg @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/mapping/src/main/resources/leaflet/images/rulers_@2X.png b/mapping/src/main/resources/leaflet/images/rulers_@2X.png new file mode 100644 index 00000000..7247a0c9 Binary files /dev/null and b/mapping/src/main/resources/leaflet/images/rulers_@2X.png differ diff --git a/mapping/src/main/resources/leaflet/images/start.png b/mapping/src/main/resources/leaflet/images/start.png new file mode 100755 index 00000000..b8ca942b Binary files /dev/null and b/mapping/src/main/resources/leaflet/images/start.png differ diff --git a/mapping/src/main/resources/leaflet/images/start.svg b/mapping/src/main/resources/leaflet/images/start.svg new file mode 100755 index 00000000..36a391c4 --- /dev/null +++ b/mapping/src/main/resources/leaflet/images/start.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/mapping/src/main/resources/leaflet/images/start_@2X.png b/mapping/src/main/resources/leaflet/images/start_@2X.png new file mode 100755 index 00000000..01da494c Binary files /dev/null and b/mapping/src/main/resources/leaflet/images/start_@2X.png differ diff --git a/mapping/src/main/resources/leaflet/images/trash.png b/mapping/src/main/resources/leaflet/images/trash.png new file mode 100755 index 00000000..7ff478a4 Binary files /dev/null and b/mapping/src/main/resources/leaflet/images/trash.png differ diff --git a/mapping/src/main/resources/leaflet/images/trash.svg b/mapping/src/main/resources/leaflet/images/trash.svg new file mode 100644 index 00000000..a8596156 --- /dev/null +++ b/mapping/src/main/resources/leaflet/images/trash.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/mapping/src/main/resources/leaflet/images/trash_@2X.png b/mapping/src/main/resources/leaflet/images/trash_@2X.png new file mode 100755 index 00000000..fea11a8c Binary files /dev/null and b/mapping/src/main/resources/leaflet/images/trash_@2X.png differ diff --git a/mapping/src/main/resources/leaflet/leaflet-measure-license.txt b/mapping/src/main/resources/leaflet/leaflet-measure-license.txt new file mode 100644 index 00000000..8b187580 --- /dev/null +++ b/mapping/src/main/resources/leaflet/leaflet-measure-license.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 LJA Engineering, Inc - GIS + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/mapping/src/main/resources/leaflet/leaflet-measure.css b/mapping/src/main/resources/leaflet/leaflet-measure.css new file mode 100644 index 00000000..8f29307f --- /dev/null +++ b/mapping/src/main/resources/leaflet/leaflet-measure.css @@ -0,0 +1 @@ +.leaflet-control-measure h3,.leaflet-measure-resultpopup h3{margin:0 0 12px;padding-bottom:10px;border-bottom:1px solid #ddd}.leaflet-control-measure p,.leaflet-measure-resultpopup p{margin:10px 0 0;line-height:1.5em}.leaflet-control-measure p:first-child,.leaflet-measure-resultpopup p:first-child{margin-top:0}.leaflet-control-measure .tasks,.leaflet-measure-resultpopup .tasks{margin:12px 0 0;padding:10px 0 0;border-top:1px solid #ddd;text-align:right;list-style:none;list-style-image:none}.leaflet-control-measure .tasks li,.leaflet-measure-resultpopup .tasks li{display:inline;margin:0 10px 0 0}.leaflet-control-measure .tasks li:last-child,.leaflet-measure-resultpopup .tasks li:last-child{margin-right:0}.leaflet-control-measure .coorddivider,.leaflet-measure-resultpopup .coorddivider{color:#999}.leaflet-control-measure{max-width:280px;background:#fff}.leaflet-control-measure .leaflet-control-measure-toggle,.leaflet-control-measure .leaflet-control-measure-toggle:hover{background-size:14px 14px;background-image:url(images/rulers.png);border:0;border-radius:4px;text-indent:100%;white-space:nowrap;overflow:hidden}.leaflet-touch .leaflet-control-measure .leaflet-control-measure-toggle,.leaflet-touch .leaflet-control-measure .leaflet-control-measure-toggle:hover{border-radius:2px}.leaflet-retina .leaflet-control-measure .leaflet-control-measure-toggle,.leaflet-retina .leaflet-control-measure .leaflet-control-measure-toggle:hover{background-image:url(images/rulers_@2X.png)}.leaflet-touch .leaflet-control-measure .leaflet-control-measure-toggle,.leaflet-touch .leaflet-control-measure .leaflet-control-measure-toggle:hover{background-size:16px 16px}.leaflet-control-measure .startprompt h3{margin-bottom:10px}.leaflet-control-measure .startprompt .tasks{margin-top:0;padding-top:0;border-top:0;text-align:left}.leaflet-control-measure .leaflet-control-measure-interaction{padding:10px 12px}.leaflet-control-measure .results .group{margin-top:10px;padding-top:10px;border-top:1px dotted #eaeaea}.leaflet-control-measure .results .group:first-child{margin-top:0;padding-top:0;border-top:0}.leaflet-control-measure .results .heading{margin-right:5px;color:#999}.leaflet-control-measure a.start{display:inline;width:auto;height:auto;padding-left:20px;margin-right:4px;line-height:1em;border:0;text-align:left;background-image:url("images/start.png");background-repeat:no-repeat;background-position:0 50%;background-size:12px 12px;color:#5e66cc;text-decoration:none}.leaflet-control-measure a.start,.leaflet-control-measure a.start:hover{background-color:transparent}.leaflet-retina .leaflet-control-measure a.start{background-image:url("images/start_@2X.png")}.leaflet-control-measure a.start:hover{opacity:.5;text-decoration:none}.leaflet-control-measure a.cancel{display:inline;width:auto;height:auto;padding-left:20px;margin-right:4px;line-height:1em;border:0;text-align:left;background-image:url("images/cancel.png");background-repeat:no-repeat;background-position:0 50%;background-size:12px 12px;color:#5e66cc;text-decoration:none}.leaflet-control-measure a.cancel,.leaflet-control-measure a.cancel:hover{background-color:transparent}.leaflet-retina .leaflet-control-measure a.cancel{background-image:url("images/cancel_@2X.png")}.leaflet-control-measure a.cancel:hover{opacity:.5;text-decoration:none}.leaflet-control-measure a.finish{display:inline;width:auto;height:auto;padding-left:20px;margin-right:4px;line-height:1em;border:0;text-align:left;background-image:url("images/check.png");background-repeat:no-repeat;background-position:0 50%;background-size:12px 12px;color:#5e66cc;text-decoration:none}.leaflet-control-measure a.finish,.leaflet-control-measure a.finish:hover{background-color:transparent}.leaflet-retina .leaflet-control-measure a.finish{background-image:url("images/check_@2X.png")}.leaflet-control-measure a.finish:hover{opacity:.5;text-decoration:none}.leaflet-measure-resultpopup a.zoomto{display:inline;width:auto;height:auto;padding-left:20px;margin-right:4px;line-height:1em;border:0;text-align:left;background-image:url("images/focus.png");background-repeat:no-repeat;background-position:0 50%;background-size:12px 12px;color:#5e66cc;text-decoration:none}.leaflet-measure-resultpopup a.zoomto,.leaflet-measure-resultpopup a.zoomto:hover{background-color:transparent}.leaflet-retina .leaflet-measure-resultpopup a.zoomto{background-image:url("images/focus_@2X.png")}.leaflet-measure-resultpopup a.zoomto:hover{opacity:.5;text-decoration:none}.leaflet-measure-resultpopup a.deletemarkup{display:inline;width:auto;height:auto;padding-left:20px;margin-right:4px;line-height:1em;border:0;text-align:left;background-image:url("images/trash.png");background-repeat:no-repeat;background-position:0 50%;background-size:12px 12px;color:#5e66cc;text-decoration:none}.leaflet-measure-resultpopup a.deletemarkup,.leaflet-measure-resultpopup a.deletemarkup:hover{background-color:transparent}.leaflet-retina .leaflet-measure-resultpopup a.deletemarkup{background-image:url("images/trash_@2X.png")}.leaflet-measure-resultpopup a.deletemarkup:hover{opacity:.5;text-decoration:none} \ No newline at end of file diff --git a/mapping/src/main/resources/leaflet/leaflet-measure.js b/mapping/src/main/resources/leaflet/leaflet-measure.js new file mode 100644 index 00000000..d88e170d --- /dev/null +++ b/mapping/src/main/resources/leaflet/leaflet-measure.js @@ -0,0 +1 @@ +!function(e){function t(n){if(r[n])return r[n].exports;var o=r[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var r={};t.m=e,t.c=r,t.d=function(e,r,n){t.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:n})},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="/dist/",t(t.s=28)}([function(e,t,r){function n(e){return null==e?void 0===e?u:a:l&&l in Object(e)?i(e):s(e)}var o=r(4),i=r(38),s=r(39),a="[object Null]",u="[object Undefined]",l=o?o.toStringTag:void 0;e.exports=n},function(e,t){function r(e){return null!=e&&"object"==typeof e}e.exports=r},function(e,t){function r(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}e.exports=r},function(e,t,r){"use strict";function n(e,t,r){if(r=r||{},!h(r))throw new Error("options is invalid");var n=r.bbox,o=r.id;if(void 0===e)throw new Error("geometry is required");if(t&&t.constructor!==Object)throw new Error("properties must be an Object");n&&d(n),o&&m(o);var i={type:"Feature"};return o&&(i.id=o),n&&(i.bbox=n),i.properties=t||{},i.geometry=e,i}function o(e,t,r){if(!e)throw new Error("coordinates is required");if(!Array.isArray(e))throw new Error("coordinates must be an Array");if(e.length<2)throw new Error("coordinates must be at least 2 numbers long");if(!p(e[0])||!p(e[1]))throw new Error("coordinates must contain numbers");return n({type:"Point",coordinates:e},t,r)}function i(e,t,r){if(!e)throw new Error("coordinates is required");for(var o=0;o-1&&e%1==0&&e<=n}var n=9007199254740991;e.exports=r},function(e,t){function r(e,t){var r=typeof e;return!!(t=null==t?n:t)&&("number"==r||"symbol"!=r&&o.test(e))&&e>-1&&e%1==0&&e/g;e.exports=r},function(e,t,r){function n(e){return null==e?"":o(e)}var o=r(75);e.exports=n},function(e,t,r){"use strict";function n(e,t,r){if(null!==e)for(var o,i,s,a,u,l,c,f,p=0,h=0,d=e.type,m="FeatureCollection"===d,y="Feature"===d,v=m?e.features.length:1,g=0;g2&&e.push(e[0]);var n=(0,l.default)(e);1===e.length?(t=L.circleMarker(e[0],this._symbols.getSymbol("resultPoint")),r=b({model:n})):2===e.length?(t=L.polyline(e,this._symbols.getSymbol("resultLine")),r=_({model:L.extend({},n,this._getMeasurementDisplayStrings(n))})):(t=L.polygon(e,this._symbols.getSymbol("resultArea")),r=j({model:L.extend({},n,this._getMeasurementDisplayStrings(n))}));var o=L.DomUtil.create("div","");o.innerHTML=r;var i=(0,c.selectOne)(".js-zoomto",o);i&&(L.DomEvent.on(i,"click",L.DomEvent.stop),L.DomEvent.on(i,"click",function(){t.getBounds?this._map.fitBounds(t.getBounds(),{padding:[20,20],maxZoom:17}):t.getLatLng&&this._map.panTo(t.getLatLng())},this));var s=(0,c.selectOne)(".js-deletemarkup",o);s&&(L.DomEvent.on(s,"click",L.DomEvent.stop),L.DomEvent.on(s,"click",function(){this._layer.removeLayer(t)},this)),t.addTo(this._layer),t.bindPopup(o,this.options.popupOptions),t.getBounds?t.openPopup(t.getBounds().getCenter()):t.getLatLng&&t.openPopup(t.getLatLng())}},_handleMeasureClick:function(e){var t=this._map.mouseEventToLatLng(e.originalEvent),r=this._latlngs[this._latlngs.length-1],n=this._symbols.getSymbol("measureVertex");r&&t.equals(r)||(this._latlngs.push(t),this._addMeasureArea(this._latlngs),this._addMeasureBoundary(this._latlngs),this._measureVertexes.eachLayer(function(e){e.setStyle(n),e._path.setAttribute("class",n.className)}),this._addNewVertex(t),this._measureBoundary&&this._measureBoundary.bringToFront(),this._measureVertexes.bringToFront()),this._updateResults(),this._updateMeasureStartedWithPoints()},_handleMapMouseOut:function(){this._measureDrag&&(this._layer.removeLayer(this._measureDrag),this._measureDrag=null)},_addNewVertex:function(e){L.circleMarker(e,this._symbols.getSymbol("measureVertexActive")).addTo(this._measureVertexes)},_addMeasureArea:function(e){if(e.length<3)return void(this._measureArea&&(this._layer.removeLayer(this._measureArea),this._measureArea=null));this._measureArea?this._measureArea.setLatLngs(e):this._measureArea=L.polygon(e,this._symbols.getSymbol("measureArea")).addTo(this._layer)},_addMeasureBoundary:function(e){if(e.length<2)return void(this._measureBoundary&&(this._layer.removeLayer(this._measureBoundary),this._measureBoundary=null));this._measureBoundary?this._measureBoundary.setLatLngs(e):this._measureBoundary=L.polyline(e,this._symbols.getSymbol("measureBoundary")).addTo(this._layer)}}),L.Map.mergeOptions({measureControl:!1}),L.Map.addInitHook(function(){this.options.measureControl&&(this.measureControl=(new L.Control.Measure).addTo(this))}),L.control.measure=function(e){return new L.Control.Measure(e)}},function(e,t){},function(e,t,r){function n(e,t,r){var n=h.imports._.templateSettings||h;r&&c(e,t,r)&&(t=void 0),e=d(e),t=o({},t,n,a);var j,x,M=o({},t.imports,n.imports,a),w=f(M),L=s(M,w),O=0,P=t.interpolate||b,k="__p += '",C=RegExp((t.escape||b).source+"|"+P.source+"|"+(P===p?g:b).source+"|"+(t.evaluate||b).source+"|$","g"),E="sourceURL"in t?"//# sourceURL="+t.sourceURL+"\n":"";e.replace(C,function(t,r,n,o,i,s){return n||(n=o),k+=e.slice(O,s).replace(_,u),r&&(j=!0,k+="' +\n__e("+r+") +\n'"),i&&(x=!0,k+="';\n"+i+";\n__p += '"),n&&(k+="' +\n((__t = ("+n+")) == null ? '' : __t) +\n'"),O=s+t.length,t}),k+="';\n";var S=t.variable;S||(k="with (obj) {\n"+k+"\n}\n"),k=(x?k.replace(m,""):k).replace(y,"$1").replace(v,"$1;"),k="function("+(S||"obj")+") {\n"+(S?"":"obj || (obj = {});\n")+"var __t, __p = ''"+(j?", __e = _.escape":"")+(x?", __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\n":";\n")+k+"return __p\n}";var A=i(function(){return Function(w,E+"return "+k).apply(void 0,L)});if(A.source=k,l(A))throw A;return A}var o=r(32),i=r(62),s=r(65),a=r(66),u=r(67),l=r(22),c=r(15),f=r(68),p=r(25),h=r(71),d=r(26),m=/\b__p \+= '';/g,y=/\b(__p \+=) '' \+/g,v=/(__e\(.*?\)|\b__t\)) \+\n'';/g,g=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,b=/($^)/,_=/['\n\r\u2028\u2029\\]/g;e.exports=n},function(e,t,r){var n=r(33),o=r(44),i=r(50),s=o(function(e,t,r,o){n(t,i(t),e,o)});e.exports=s},function(e,t,r){function n(e,t,r,n){var s=!r;r||(r={});for(var a=-1,u=t.length;++a1?r[o-1]:void 0,a=o>2?r[2]:void 0;for(s=e.length>3&&"function"==typeof s?(o--,s):void 0,a&&i(r[0],r[1],a)&&(s=o<3?void 0:s,o=1),t=Object(t);++n0){if(++t>=n)return arguments[0]}else t=0;return e.apply(void 0,arguments)}}var n=800,o=16,i=Date.now;e.exports=r},function(e,t,r){function n(e){return s(e)?o(e,!0):i(e)}var o=r(18),i=r(60),s=r(7);e.exports=n},function(e,t){function r(e,t){for(var r=-1,n=Array(e);++r"']/g,a=RegExp(s.source);e.exports=n},function(e,t,r){var n=r(74),o={"&":"&","<":"<",">":">",'"':""","'":"'"},i=n(o);e.exports=i},function(e,t){function r(e){return function(t){return null==e?void 0:e[t]}}e.exports=r},function(e,t,r){function n(e){if("string"==typeof e)return e;if(s(e))return i(e,n)+"";if(a(e))return c?c.call(e):"";var t=e+"";return"0"==t&&1/e==-u?"-0":t}var o=r(4),i=r(24),s=r(19),a=r(76),u=1/0,l=o?o.prototype:void 0,c=l?l.toString:void 0;e.exports=n},function(e,t,r){function n(e){return"symbol"==typeof e||i(e)&&o(e)==s}var o=r(0),i=r(1),s="[object Symbol]";e.exports=n},function(e,t){var r=/<%-([\s\S]+?)%>/g;e.exports=r},function(e,t){var r=/<%([\s\S]+?)%>/g;e.exports=r},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default={acres:{factor:24711e-8,display:"acres",decimals:2},feet:{factor:3.2808,display:"feet",decimals:0},kilometers:{factor:.001,display:"kilometers",decimals:2},hectares:{factor:1e-4,display:"hectares",decimals:2},meters:{factor:1,display:"meters",decimals:0},miles:{factor:3.2808/5280,display:"miles",decimals:2},sqfeet:{factor:10.7639,display:"sqfeet",decimals:0},sqmeters:{factor:1,display:"sqmeters",decimals:0},sqmiles:{factor:3.86102e-7,display:"sqmiles",decimals:2}}},function(e,t,r){"use strict";function n(e){return e&&e.__esModule?e:{default:e}}function o(e){return e<10?"0"+e.toString():e.toString()}function i(e,t,r){var n=Math.abs(e),i=Math.floor(n),s=Math.floor(60*(n-i)),a=Math.round(3600*(n-i-s/60)*100)/100,u=n===e?t:r;return o(i)+"° "+o(s)+"' "+o(a)+'" '+u}function s(e){var t=e[e.length-1],r=e.map(function(e){return[e.lat,e.lng]}),n=L.polyline(r),o=L.polygon(r),s=1e3*(0,u.default)(n.toGeoJSON(),{units:"kilometers"}),a=(0,c.default)(o.toGeoJSON());return{lastCoord:{dd:{x:t.lng,y:t.lat},dms:{x:i(t.lng,"E","W"),y:i(t.lat,"N","S")}},length:s,area:a}}Object.defineProperty(t,"__esModule",{value:!0}),t.default=s;var a=r(81),u=n(a),l=r(84),c=n(l)},function(e,t,r){"use strict";function n(e,t){if(t=t||{},!Object(s.d)(t))throw new Error("options is invalid");if(!e)throw new Error("geojson is required");return Object(i.b)(e,function(e,r){var n=r.geometry.coordinates;return e+Object(o.a)(n[0],n[1],t)},0)}Object.defineProperty(t,"__esModule",{value:!0});var o=r(82),i=r(27),s=r(3);t.default=n},function(e,t,r){"use strict";function n(e,t,r){if(r=r||{},!Object(i.d)(r))throw new Error("options is invalid");var n=r.units,s=Object(o.a)(e),a=Object(o.a)(t),u=Object(i.a)(a[1]-s[1]),l=Object(i.a)(a[0]-s[0]),c=Object(i.a)(s[1]),f=Object(i.a)(a[1]),p=Math.pow(Math.sin(u/2),2)+Math.pow(Math.sin(l/2),2)*Math.cos(c)*Math.cos(f);return Object(i.g)(2*Math.atan2(Math.sqrt(p),Math.sqrt(1-p)),n)}var o=r(83),i=r(3);t.a=n},function(e,t,r){"use strict";function n(e){if(!e)throw new Error("coord is required");if("Feature"===e.type&&null!==e.geometry&&"Point"===e.geometry.type)return e.geometry.coordinates;if("Point"===e.type)return e.coordinates;if(Array.isArray(e)&&e.length>=2&&void 0===e[0].length&&void 0===e[1].length)return e;throw new Error("coord must be GeoJSON Point or an Array of numbers")}r.d(t,"a",function(){return n});r(3)},function(e,t,r){"use strict";function n(e){return Object(u.a)(e,function(e,t){return e+o(t)},0)}function o(e){var t,r=0;switch(e.type){case"Polygon":return i(e.coordinates);case"MultiPolygon":for(t=0;t0){t+=Math.abs(s(e[0]));for(var r=1;r2){for(u=0;u1&&void 0!==arguments[1]?arguments[1]:2,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:".",n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:",",o=e<0?"-":"",i=Math.abs(+e||0),s=parseInt(i.toFixed(t),10)+"",a=s.length>3?s.length%3:0;return[o,a?s.substr(0,a)+n:"",s.substr(a).replace(/(\d{3})(?=\d)/g,"$1"+n),t?""+r+Math.abs(i-s).toFixed(t).slice(2):""].join("")}Object.defineProperty(t,"__esModule",{value:!0}),t.numberFormat=n},function(e,t,r){"use strict";function n(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var o=r(89);Object.defineProperty(t,"controlTemplate",{enumerable:!0,get:function(){return n(o).default}});var i=r(90);Object.defineProperty(t,"resultsTemplate",{enumerable:!0,get:function(){return n(i).default}});var s=r(91);Object.defineProperty(t,"pointPopupTemplate",{enumerable:!0,get:function(){return n(s).default}});var a=r(92);Object.defineProperty(t,"linePopupTemplate",{enumerable:!0,get:function(){return n(a).default}});var u=r(93);Object.defineProperty(t,"areaPopupTemplate",{enumerable:!0,get:function(){return n(u).default}})},function(e,t,r){e.exports='Measure

Measure distances and areas

Measure distances and areas

Start creating a measurement by adding points to the map

'},function(e,t,r){e.exports='

Last point

{{ model.lastCoord.dms.y }} / {{ model.lastCoord.dms.x }}

{{ numberFormat(model.lastCoord.dd.y, 6) }} / {{ numberFormat(model.lastCoord.dd.x, 6) }}

<% if (model.pointCount > 1) { %>

Path distance {{ model.lengthDisplay }}

<% } %> <% if (model.pointCount > 2) { %>

Area {{ model.areaDisplay }}

<% } %> '},function(e,t,r){e.exports='

Point location

{{ model.lastCoord.dms.y }} / {{ model.lastCoord.dms.x }}

{{ numberFormat(model.lastCoord.dd.y, 6) }} / {{ numberFormat(model.lastCoord.dd.x, 6) }}

'},function(e,t,r){e.exports='

Linear measurement

{{ model.lengthDisplay }}

'},function(e,t,r){e.exports='

Area measurement

{{ model.areaDisplay }}

{{ model.lengthDisplay }} Perimeter

'}]); \ No newline at end of file diff --git a/mapping/src/main/resources/leaflet/leaflet.html b/mapping/src/main/resources/leaflet/leaflet.html index 643d5f23..492c654a 100644 --- a/mapping/src/main/resources/leaflet/leaflet.html +++ b/mapping/src/main/resources/leaflet/leaflet.html @@ -3,9 +3,11 @@ + - + + @@ -34,7 +36,20 @@ var map = L.map('map', { attributionControl: false - }).setView([0, 0], 2); + }).setView([0, 0], 2); + + //Path measurement library controls + var measureControl = L.control.measure({ + position: 'topleft', primaryLengthUnit: 'kilometers', + primaryAreaUnit: 'sqmeters', secondaryAreaUnit: 'sqmiles', + captureZIndex: 2000000, + activeColor: '#086972', + completedColor: '#342b38' + }); + measureControl.addTo(map); + + //Add the scale bar to the bottom right + L.control.scale({position: 'bottomright'}).addTo(map); var countriesLayer = L.geoJson(countryData, { style: { diff --git a/pom.xml b/pom.xml index a25da873..e4cc1907 100644 --- a/pom.xml +++ b/pom.xml @@ -1,12 +1,12 @@ - + 4.0.0 gov.llnl.gnem.apps.coda.calibration coda-calibration - 1.0.8.1 + 1.0.9 coda-calibration pom @@ -61,7 +61,7 @@ spring-milestones - http://repo.spring.io/milestone + https://repo.spring.io/milestone @@ -73,34 +73,33 @@ 1.8 1.8 3.8.1 - 3.1.1 + 3.2.0 3.0.0-M4 - 3.2.1 + 3.2.2 3.2.0 - 15-ea+1 + 15-ea+2 2.4.0-b180830.0359 - 1.2.0.RELEASE - 2.2.4.RELEASE - Dysprosium-SR4 + 2.3.0.M3 + Dysprosium-SR6 2.2.1 1.12 1.3.04 1.50 - 10.1.0 + 10.2.0 - 1.15 - 1.19 + 1.16 + 1.20 3.6.1 28.2-jre - 2.3.1 + 2.3.4 - 5.2.3.RELEASE - 5.6.0 - 3.2.4 + 5.2.5.RELEASE + 5.6.1 + 3.3.3 1.3.2 @@ -295,22 +294,7 @@ ${spring.boot.version} pom import -
- - io.springlets - springlets-data-jpa - ${springlets.version} - - - io.springlets - springlets-data-commons - ${springlets.version} - - - io.springlets - springlets-context - ${springlets.version} - +
org.springframework.boot spring-boot-loader @@ -444,7 +428,6 @@ javax.annotation-api ${javax.annotation.version} -
diff --git a/schema/calibration-input-params.json.example b/schema/calibration-input-params.json.example index 72271c7e..ef3cb014 100644 --- a/schema/calibration-input-params.json.example +++ b/schema/calibration-input-params.json.example @@ -1,97 +1,102 @@ { "schemaVersion": 1, "type": "llnl/coda-calibration-tool", - "bands":[ - {"lowFreqHz":0.02 ,"highFreqHz":0.03,"minWindowLengthSec":100,"maxWindowLengthSec":1000,"snrThresholdAboveNoiseLog10":0.5,"measurementTimeSec":100.0,"velocity0":0,"velocity1":0,"velocity2":0,"beta0":0,"beta1":0,"beta2":0,"gamma0":0,"gamma1":0,"gamma2":0,"p1":0,"p2":0,"xc":0,"xt":0,"q":0}, - {"lowFreqHz":0.03 ,"highFreqHz":0.05,"minWindowLengthSec":100,"maxWindowLengthSec":800, "snrThresholdAboveNoiseLog10":0.5}, - {"lowFreqHz":0.05 ,"highFreqHz":0.1, "minWindowLengthSec":75, "maxWindowLengthSec":600, "snrThresholdAboveNoiseLog10":0.5}, - {"lowFreqHz":0.1, "highFreqHz":0.2, "minWindowLengthSec":75, "maxWindowLengthSec":550, "snrThresholdAboveNoiseLog10":0.5}, - {"lowFreqHz":0.2, "highFreqHz":0.3, "minWindowLengthSec":50, "maxWindowLengthSec":550, "snrThresholdAboveNoiseLog10":0.5}, - {"lowFreqHz":0.3, "highFreqHz":0.5, "minWindowLengthSec":50, "maxWindowLengthSec":500, "snrThresholdAboveNoiseLog10":0.5}, - {"lowFreqHz":0.5, "highFreqHz":0.7, "minWindowLengthSec":50, "maxWindowLengthSec":500, "snrThresholdAboveNoiseLog10":0.5}, - {"lowFreqHz":0.7, "highFreqHz":1.0, "minWindowLengthSec":40, "maxWindowLengthSec":450, "snrThresholdAboveNoiseLog10":0.5}, - {"lowFreqHz":1.0, "highFreqHz":1.5, "minWindowLengthSec":40, "maxWindowLengthSec":450, "snrThresholdAboveNoiseLog10":0.5}, - {"lowFreqHz":1.5, "highFreqHz":2.0, "minWindowLengthSec":40, "maxWindowLengthSec":400, "snrThresholdAboveNoiseLog10":0.5}, - {"lowFreqHz":2.0, "highFreqHz":3.0, "minWindowLengthSec":40, "maxWindowLengthSec":400, "snrThresholdAboveNoiseLog10":0.5}, - {"lowFreqHz":3.0, "highFreqHz":4.0, "minWindowLengthSec":40, "maxWindowLengthSec":400, "snrThresholdAboveNoiseLog10":0.5}, - {"lowFreqHz":4.0, "highFreqHz":6.0, "minWindowLengthSec":40, "maxWindowLengthSec":400, "snrThresholdAboveNoiseLog10":0.5}, - {"lowFreqHz":6.0, "highFreqHz":8.0, "minWindowLengthSec":40, "maxWindowLengthSec":350, "snrThresholdAboveNoiseLog10":0.5} + "bands": [ + { "lowFreqHz": 0.02, "highFreqHz": 0.03, "minWindowLengthSec": 100, "maxWindowLengthSec": 1000, "snrThresholdAboveNoiseLog10": 0.5, "measurementTimeSec": 100.0, "velocity0": 0, "velocity1": 0, "velocity2": 0, "beta0": 0, "beta1": 0, "beta2": 0, "gamma0": 0, "gamma1": 0, "gamma2": 0, "p1": 0, "p2": 0, "xc": 0, "xt": 0, "q": 0 }, + { "lowFreqHz": 0.03, "highFreqHz": 0.05, "minWindowLengthSec": 100, "maxWindowLengthSec": 800, "snrThresholdAboveNoiseLog10": 0.5 }, + { "lowFreqHz": 0.05, "highFreqHz": 0.1, "minWindowLengthSec": 75, "maxWindowLengthSec": 600, "snrThresholdAboveNoiseLog10": 0.5 }, + { "lowFreqHz": 0.1, "highFreqHz": 0.2, "minWindowLengthSec": 75, "maxWindowLengthSec": 550, "snrThresholdAboveNoiseLog10": 0.5 }, + { "lowFreqHz": 0.2, "highFreqHz": 0.3, "minWindowLengthSec": 50, "maxWindowLengthSec": 550, "snrThresholdAboveNoiseLog10": 0.5 }, + { "lowFreqHz": 0.3, "highFreqHz": 0.5, "minWindowLengthSec": 50, "maxWindowLengthSec": 500, "snrThresholdAboveNoiseLog10": 0.5 }, + { "lowFreqHz": 0.5, "highFreqHz": 0.7, "minWindowLengthSec": 50, "maxWindowLengthSec": 500, "snrThresholdAboveNoiseLog10": 0.5 }, + { "lowFreqHz": 0.7, "highFreqHz": 1.0, "minWindowLengthSec": 40, "maxWindowLengthSec": 450, "snrThresholdAboveNoiseLog10": 0.5 }, + { "lowFreqHz": 1.0, "highFreqHz": 1.5, "minWindowLengthSec": 40, "maxWindowLengthSec": 450, "snrThresholdAboveNoiseLog10": 0.5 }, + { "lowFreqHz": 1.5, "highFreqHz": 2.0, "minWindowLengthSec": 40, "maxWindowLengthSec": 400, "snrThresholdAboveNoiseLog10": 0.5 }, + { "lowFreqHz": 2.0, "highFreqHz": 3.0, "minWindowLengthSec": 40, "maxWindowLengthSec": 400, "snrThresholdAboveNoiseLog10": 0.5 }, + { "lowFreqHz": 3.0, "highFreqHz": 4.0, "minWindowLengthSec": 40, "maxWindowLengthSec": 400, "snrThresholdAboveNoiseLog10": 0.5 }, + { "lowFreqHz": 4.0, "highFreqHz": 6.0, "minWindowLengthSec": 40, "maxWindowLengthSec": 400, "snrThresholdAboveNoiseLog10": 0.5 }, + { "lowFreqHz": 6.0, "highFreqHz": 8.0, "minWindowLengthSec": 40, "maxWindowLengthSec": 350, "snrThresholdAboveNoiseLog10": 0.5 } ], "mdac-fi": { - "alphaR": 5000, - "alphas": 6000, - "betas": 3500, - "betaR": 2900, - "sigma": 0.3, - "delSigma": 0.0, - "psi": 0.25, - "delPsi": 0.0, - "zeta": 1.0, - "m0ref": 10000000000000000, - "radPatP": 0.44, - "radPatS": 0.6, - "rhor": 2500, - "rhos": 2700 + "alphaR": 5000, + "alphas": 6000, + "betas": 3500, + "betaR": 2900, + "sigma": 0.3, + "delSigma": 0.0, + "psi": 0.25, + "delPsi": 0.0, + "zeta": 1.0, + "m0ref": 10000000000000000, + "radPatP": 0.44, + "radPatS": 0.6, + "rhor": 2500, + "rhos": 2700 }, "mdac-ps": [ - {"phase":"Pn","q0":210,"delQ0":0,"gamma0":0.65,"delGamma0":0,"u0":7900,"eta":1.1,"delEta":0,"distCrit":0.001,"snr":2}, - {"phase":"Pg","q0":190,"delQ0":0,"gamma0":0.45,"delGamma0":0,"u0":6000,"eta":0.5,"delEta":0,"distCrit":100, "snr":2}, - {"phase":"Sn","q0":590,"delQ0":0,"gamma0":0.55,"delGamma0":0,"u0":4500,"eta":1.1,"delEta":0,"distCrit":0.001,"snr":2}, - {"phase":"Lg","q0":200,"delQ0":0,"gamma0":0.54,"delGamma0":0,"u0":3500,"eta":0.5,"delEta":0,"distCrit":100, "snr":2} + { "phase": "Pn", "q0": 210, "delQ0": 0, "gamma0": 0.65, "delGamma0": 0, "u0": 7900, "eta": 1.1, "delEta": 0, "distCrit": 0.001, "snr": 2 }, + { "phase": "Pg", "q0": 190, "delQ0": 0, "gamma0": 0.45, "delGamma0": 0, "u0": 6000, "eta": 0.5, "delEta": 0, "distCrit": 100, "snr": 2 }, + { "phase": "Sn", "q0": 590, "delQ0": 0, "gamma0": 0.55, "delGamma0": 0, "u0": 4500, "eta": 1.1, "delEta": 0, "distCrit": 0.001, "snr": 2 }, + { "phase": "Lg", "q0": 200, "delQ0": 0, "gamma0": 0.54, "delGamma0": 0, "u0": 3500, "eta": 0.5, "delEta": 0, "distCrit": 100, "snr": 2 } ], "reference-events": [ - { "eventId" : "0331199924", "refMw" : 3.0 }, - { "eventId" : "0401199924", "refMw" : 5.0, "refApparentStressInMpa": 0.7 } + { "eventId": "0331199924", "refMw": 3.0 }, + { "eventId": "0401199924", "refMw": 5.0, "refApparentStressInMpa": 0.7 } ], - "velocity-configuration": { - "phaseVelocityInKms" : 3.5, - "groupVelocity1InKmsGtDistance" : 4.7, - "groupVelocity2InKmsGtDistance" : 2.3, - "groupVelocity1InKmsLtDistance" : 3.9, - "groupVelocity2InKmsLtDistance" : 1.9, - "distanceThresholdInKm" : 300.0, + "validation-events": [{ + "eventId": "0331199924", + "mw": 3.1, + "apparentStressInMpa": 0.5 + }], + "velocity-configuration": { + "phaseVelocityInKms": 3.5, + "groupVelocity1InKmsGtDistance": 4.7, + "groupVelocity2InKmsGtDistance": 2.3, + "groupVelocity1InKmsLtDistance": 3.9, + "groupVelocity2InKmsLtDistance": 1.9, + "distanceThresholdInKm": 300.0 }, - "shape-constraints" : { - "maxVP1" : 600.0, - "minVP1" : 50.0, - "v0reg" : 100.0, - "maxVP2" : 5000.0, - "minVP2" : 1.0, - "maxVP3" : 5000.0, - "minVP3" : 1.0, - "maxBP1" : 1000.0, - "minBP1" : -500.0, - "b0reg" : 10000.0, - "maxBP2" : 20.0, - "minBP2" : 0.1, - "maxBP3" : 1500.0, - "minBP3" : 1.0E-4, - "maxGP1" : 100.0, - "minGP1" : 0.0, - "g0reg" : 100.0, - "maxGP2" : 101.0, - "minGP2" : 0.0, - "g1reg" : -1.0, - "maxGP3" : 101.0, - "minGP3" : 1.0, - "yvvMin" : 0.5, - "yvvMax" : 6.01, - "vDistMax" : 1600.0, - "vDistMin" : 0.0, - "ybbMin" : -0.12, - "ybbMax" : 5.0E-4, - "bDistMax" : 1550.0, - "bDistMin" : 0.0, - "yggMin" : 0.01, - "yggMax" : 100.0, - "gDistMin" : 600.0, - "gDistMax" : 0.0, - "minIntercept" : 0.001, - "maxIntercept" : 20.0, - "minBeta" : -4.0, - "maxBeta" : -1.0E-4, - "minGamma" : 0.001, - "maxGamma" : 4.0, - "iterations" : 10 - } + "shape-constraints": { + "maxVP1": 600.0, + "minVP1": 50.0, + "v0reg": 100.0, + "maxVP2": 5000.0, + "minVP2": 1.0, + "maxVP3": 5000.0, + "minVP3": 1.0, + "maxBP1": 1000.0, + "minBP1": -500.0, + "b0reg": 10000.0, + "maxBP2": 20.0, + "minBP2": 0.1, + "maxBP3": 1500.0, + "minBP3": 1.0E-4, + "maxGP1": 100.0, + "minGP1": 0.0, + "g0reg": 100.0, + "maxGP2": 101.0, + "minGP2": 0.0, + "g1reg": -1.0, + "maxGP3": 101.0, + "minGP3": 1.0, + "yvvMin": 0.5, + "yvvMax": 6.01, + "vDistMax": 1600.0, + "vDistMin": 0.0, + "ybbMin": -0.12, + "ybbMax": 5.0E-4, + "bDistMax": 1550.0, + "bDistMin": 0.0, + "yggMin": 0.01, + "yggMax": 100.0, + "gDistMin": 600.0, + "gDistMax": 0.0, + "minIntercept": 0.001, + "maxIntercept": 20.0, + "minBeta": -4.0, + "maxBeta": -1.0E-4, + "minGamma": 0.001, + "maxGamma": 4.0, + "iterations": 10 + } } \ No newline at end of file diff --git a/schema/calibration-input-params.jsonschema b/schema/calibration-input-params.jsonschema index 5513ef1d..957483e3 100644 --- a/schema/calibration-input-params.jsonschema +++ b/schema/calibration-input-params.jsonschema @@ -589,6 +589,50 @@ } } }, + "validation-events": { + "$id": "#/properties/validation-events", + "type": "array", + "title": "Array of known validation events; not used in calibration but displayed in the GUI for verification.", + "items": { + "$id": "#/properties/validation-events/entry", + "type": "object", + "title": "A specific validation event entry.", + "required": [ + "eventId", + "mw" + ], + "properties": { + "eventId": { + "$id": "#/properties/validation-events/entry/properties/eventId", + "type": "string", + "title": "Specific event id, needs to match an event id in the calibration to display on plots.", + "default": false, + "examples": [ + "0101190012" + ] + }, + "mw": { + "$id": "#/properties/validation-events/entry/properties/mw", + "type": "number", + "title": "The Mw value for the validation event.", + "default": 0, + "examples": [ + 5.0 + ] + }, + "apparentStressInMpa": { + "$id": "#/properties/validation-events/entry/properties/apparentStressInMpa", + "type": "number", + "title": "An optional measure of the apparent stress term for this specific validation event.", + "default": false, + "examples": [ + 0.0, + 0.5 + ] + } + } + } + }, "velocity-configuration": { "$id": "#/properties/velocity-configuration", "type": "object",