From 89b9f486609865f039b54f7f67730a85a96fe26e Mon Sep 17 00:00:00 2001 From: Justin Barno Date: Tue, 7 May 2019 09:08:05 -0700 Subject: [PATCH] CCT 1.0.4-M3 Release notes: Improvements and changes: * Overall optimization for the GUI and calibration modules. ** Calibrations should take ~50% less memory on average and run %10-20 faster. ** The GUI panels should also load and refresh considerably faster as well. * Group velocities used for selection criteria during calibration are now configurable. See the schema folder for examples of the new JSON block and the Parameters tab for the new table display. * Data can now be filtered from use in calibration ** Data selection options: *** From the data tab check the 'used' checkbox or multi-select and right click for a context menu to include/exclude more records at once *** From shape, path, and site plots you can right click a plotted point and exclude the data that was used to generate that plot point (use with care as you can exclude more data than you expect this way, especially in path!) *** From the map you can right click a station or event and include/exclude all records that match either that station or event * Map will now auto (re)center to the data loaded if you tap the 'Map' button while the map is already open (this will also bring the map back to the front if its behind other windows). * Measured and reference event information in the Site correction tab have been consolidated into a single Mw results table. * The combined Mw table also includes the number of measurements used to make the measurement for the measured mw fields. * The Mw results tab now also includes three plots for: ** Reference vs. Measured Mw ** Reference vs. Measured Stress ** Standard deviation of final calibrated measurement by event and frequency. *** Sd plot is color coded by # of station records in the measurement * The measured-mw json output for calibration will now include the reference event if there was one for that evid. * We now remove auto-pick indicator AP picks on waveforms if a human moves the F marker. By moving the F marker this tells the auto-picker that the waveform has been human reviewed and it should not move the F marker during future calibrations. * The waveform plot now also plots the synthetic out past the F marker as a dashed line. This is intended to help a human decide if the pick could be moved further out without affecting the fit too much. * The calibration status update bar has been improved with some additional states showing how far along the calibration is. * If a reference stress value is provided the Site calibration will weight that spectra evenly across all frequencies for that event (default is lower frequencies have higher weight). Bugfixes: * Fixed a bug where many overlapping points intersecting with the model line in the Shape tab could make some points stop responding to clicks for plotting purposes. * The waveform plot should now immediately update and repaint the synthetic when you move the F marker (if it had one). * Waveform plot won't try to plot a synthetic if the start happens before the expected GV onset for the phase. This criteria was already being used to exclude the synthetic during calibration anyway so no sense in plotting it! * Workaround implemented for reported hang on Mac 10.13+ caused by a deadlock in the native Apple AWT implementation. The application should no longer occasionally hang on startup. Known bugs: * Data selection color changes to indicate used/not-used can be inconsistent until you refresh after excluding/including data on the plots and map. The de/selection does work, however. --- README.md | 4 +- calibration-gui/pom.xml | 4 + .../coda/calibration/gui/AppProperties.java | 13 +- .../calibration/gui/CodaGuiController.java | 63 ++- .../coda/calibration/gui/GuiApplication.java | 2 +- .../apps/coda/calibration/gui/MapConfig.java | 37 ++ .../CodaParamLoadingController.java | 130 +++-- .../gui/controllers/DataController.java | 207 ++++++- .../EnvelopeLoadingController.java | 6 +- .../gui/controllers/PathController.java | 111 +++- .../gui/controllers/ShapeController.java | 157 +++++- .../gui/controllers/SiteController.java | 532 ++++++++++++++---- .../parameters/ParametersController.java | 12 +- .../parameters/SharedBandController.java | 2 +- .../parameters/SiteBandController.java | 29 +- .../VelocityConfigurationController.java | 105 ++++ .../converters/param/CodaJsonParamLoader.java | 16 +- .../param/ReferenceEventLoader.java | 16 +- .../gui/data/client/ParameterWebClient.java | 19 +- .../data/client/PeakVelocityWebClient.java | 6 +- .../data/client/ReferenceEventWebClient.java | 11 + .../client/ShapeMeasurementWebClient.java | 20 + .../gui/data/client/SpectraWebClient.java | 13 +- .../client/api/CalibrationJsonConstants.java | 1 + .../gui/data/client/api/ParameterClient.java | 5 + .../data/client/api/ReferenceEventClient.java | 3 + .../client/api/ShapeMeasurementClient.java | 4 + .../gui/data/client/api/SpectraClient.java | 2 + .../data/exporters/JsonTempFileWriter.java | 64 ++- .../gui/data/exporters/ParamExporter.java | 41 +- .../exporters/SwftStyleParamFileWriter.java | 10 +- .../VelocityConfigurationFileMixin.java | 21 + .../api/MeasuredMwTempFileWriter.java | 2 +- .../exporters/api/ParamTempFileWriter.java | 4 +- .../api/ReferenceMwTempFileWriter.java | 24 + .../gui/events/MapIconActivationCallback.java | 47 ++ .../gui/plotting/CodaWaveformPlot.java | 88 +-- .../gui/plotting/CodaWaveformPlotManager.java | 83 +-- .../gui/plotting/SpectralPlot.java | 6 +- .../calibration/gui/plotting/WaveformGui.java | 10 + .../gui/util/CalibrationProgressListener.java | 6 +- .../gui/util/TimeLatchedGetSet.java | 74 ++- .../src/main/resources/application.properties | 1 + .../src/main/resources/fxml/CodaGui.fxml | 3 +- .../src/main/resources/fxml/Data.fxml | 47 +- .../src/main/resources/fxml/FitPlot.css | 2 +- .../src/main/resources/fxml/Parameters.fxml | 7 +- .../src/main/resources/fxml/Shape.fxml | 2 +- .../src/main/resources/fxml/Site.fxml | 264 +++++---- .../src/main/resources/fxml/Velocity.fxml | 47 ++ .../resources/calibration-params-test.json | 2 +- .../calibration-application/pom.xml | 36 +- ...alibrationNotificationStompController.java | 38 +- .../web/ConfigurationItemJsonController.java | 57 ++ .../MdacParametersFiItemJsonController.java | 3 +- .../MdacParametersPsItemJsonController.java | 3 +- .../web/MeasuredMwsJsonController.java | 8 +- .../web/PeakVelocityJsonController.java | 6 +- .../web/ShapeMeasurementJsonController.java | 11 + ...uencyBandParametersItemJsonController.java | 3 +- ...uencyBandParametersItemJsonController.java | 3 +- .../web/SpectraMeasurementJsonController.java | 8 +- .../SyntheticCollectionJsonController.java | 5 +- ...itional-spring-configuration-metadata.json | 120 ++++ .../main/resources/application-dev.properties | 8 +- .../resources/application-file.properties | 7 +- .../src/main/resources/application.properties | 6 +- .../src/main/resources/data.sql | 2 + .../model/domain/InjectedVelocityConfig.java | 51 ++ .../model/domain/MdacParametersFI.java | 51 +- .../model/domain/MdacParametersPS.java | 9 +- .../model/domain/MeasuredMwDetails.java | 163 ++++-- .../model/domain/MeasuredMwParameters.java | 94 +++- .../domain/PathCalibrationMeasurement.java | 10 +- .../model/domain/PeakVelocityMeasurement.java | 12 +- .../PeakVelocityMeasurementMetadata.java | 2 +- .../model/domain/ReferenceMwParameters.java | 35 +- .../model/domain/ShapeMeasurement.java | 30 +- .../domain/ShapeMeasurementMetadata.java | 48 ++ .../domain/SiteFrequencyBandParameters.java | 9 +- .../calibration/model/domain/Spectra.java | 14 +- .../model/domain/SpectraMeasurement.java | 25 +- .../domain/SpectraMeasurementMetadata.java | 40 ++ .../model/domain/VelocityConfiguration.java | 242 ++++++++ .../ReferenceMwParametersFileMixin.java | 24 + .../BandParametersDataChangeEvent.java | 2 +- .../messaging/CalibrationStatusEvent.java | 2 +- .../model/messaging/GvDataChangeEvent.java | 77 +++ .../model/messaging/MdacDataChangeEvent.java | 2 +- .../repository/MeasuredMwsRepository.java | 4 + .../ShapeMeasurementRepository.java | 10 + .../SpectraMeasurementRepository.java | 10 + .../VelocityConfigurationRepository.java | 25 + .../service/api/ConfigurationService.java | 23 + .../service/api/MeasuredMwsService.java | 4 + .../service/api/PathCalibrationService.java | 3 +- .../api/PeakVelocityMeasurementService.java | 5 +- .../service/api/ShapeMeasurementService.java | 8 + .../api/SpectraMeasurementService.java | 12 +- .../calibration-service-impl/pom.xml | 4 + .../service/impl/CalibrationServiceImpl.java | 34 +- .../impl/ConfigurationServiceImpl.java | 66 +++ .../service/impl/Joint1DPathCorrection.java | 71 ++- .../impl/MdacParametersFiServiceImpl.java | 2 +- .../service/impl/MeasuredMwsServiceImpl.java | 60 +- .../PeakVelocityMeasurementServiceImpl.java | 7 +- .../impl/ShapeCalibrationServiceImpl.java | 5 +- .../impl/ShapeMeasurementServiceImpl.java | 11 + .../impl/SiteCalibrationServiceImpl.java | 9 +- .../impl/SpectraMeasurementServiceImpl.java | 38 +- .../SyntheticCodaGenerationServiceImpl.java | 4 +- .../processing/CalibrationCurveFitter.java | 88 ++- .../impl/processing/CodaSNREndTimePicker.java | 37 +- .../processing/MaxVelocityCalculator.java | 54 +- .../impl/processing/MdacCalculator.java | 5 - .../processing/MdacCalculatorService.java | 14 +- .../impl/processing/SpectraCalculator.java | 86 +-- calibration-standalone/pom.xml | 4 - .../standalone/CodaCalibrationStandalone.java | 2 +- .../data/client/ParameterLocalClient.java | 20 +- .../client/ReferenceEventLocalClient.java | 6 + .../client/ShapeMeasurementLocalClient.java | 12 +- .../data/client/SpectraLocalClient.java | 11 +- .../data/client/WaveformLocalClient.java | 33 +- .../resources/application-file.properties | 7 +- .../src/main/resources/application.properties | 5 +- .../coda/calibration/AssessAutopicker.java | 2 +- common-gui/pom.xml | 24 +- .../apps/coda/common/gui/WebclientConfig.java | 88 +++ .../common/gui/controllers/ProgressGui.java | 2 +- .../gui/converters/sac/SacExporter.java | 5 +- .../common/gui/converters/sac/SacLoader.java | 23 +- .../gui/data/client/CodaWebClientBuilder.java | 104 +--- .../gui/data/client/WaveformWebClient.java | 67 ++- .../gui/data/client/api/WaveformClient.java | 12 +- .../gui/events/WaveformSelectionEvent.java | 7 +- .../coda/common/gui/plotting/PlotPoint.java | 14 + .../gui/plotting/SymbolStyleMapFactory.java | 6 +- .../common/gui/util/CombinedTrustManager.java | 3 +- .../coda/common/gui/util/CommonGuiUtils.java | 9 +- .../util/MaybeNumericStringComparator.java | 27 +- .../coda/common/gui/util/ProgressMonitor.java | 17 +- .../apps/coda/common/gui/util/SslUtils.java | 31 +- common-service/common-application/pom.xml | 34 +- .../config/JettyConfiguration.java | 44 ++ .../web/WaveformPicksItemJsonController.java | 3 +- .../WaveformsCollectionJsonController.java | 53 +- .../web/WaveformsItemJsonController.java | 9 +- common-service/common-model/pom.xml | 8 + .../apps/coda/common/model/domain/Pair.java | 2 +- .../domain/SharedFrequencyBandParameters.java | 10 +- .../apps/coda/common/model/domain/Stream.java | 24 - .../common/model/domain/SyntheticCoda.java | 42 +- .../coda/common/model/domain/Waveform.java | 86 +-- .../common/model/domain/WaveformMetadata.java | 2 +- .../common/model/domain/WaveformPick.java | 45 +- .../model/messaging/WaveformChangeEvent.java | 92 +++ .../common/repository/WaveformRepository.java | 32 +- .../common/service/api/WaveformService.java | 16 +- common-service/common-service-impl/pom.xml | 15 + .../service/impl/WaveformPickServiceImpl.java | 2 +- .../service/impl/WaveformServiceImpl.java | 105 +++- .../common/service/util/WaveformUtils.java | 54 +- .../service/CommonServiceTestContext.java | 31 + .../service/WaveformServiceImplTest.java | 103 ++++ .../src/test/resources/logback-test.xml | 12 + .../apps/coda/envelope/gui/AppProperties.java | 4 +- .../coda/envelope/gui/GuiApplication.java | 2 +- .../WaveformLoadingController.java | 8 +- .../gui/data/client/EnvelopeWebClient.java | 2 +- .../src/main/resources/application.properties | 1 + envelope-service/envelope-application/pom.xml | 26 +- .../main/resources/application-dev.properties | 5 +- .../resources/application-file.properties | 6 +- .../src/main/resources/application.properties | 2 + .../envelope/model/domain/EnvelopeJob.java | 2 +- .../standalone/EnvelopeStandalone.java | 2 +- .../data/client/EnvelopeLocalClient.java | 8 +- .../resources/application-file.properties | 6 +- .../src/main/resources/application.properties | 3 + .../gnem/core/gui/plotting/DrawingUnits.java | 10 +- .../core/gui/plotting/JPlotContainer.java | 9 +- .../core/gui/plotting/PickCreationInfo.java | 5 +- .../gnem/core/gui/plotting/SymbolLegend.java | 8 +- .../core/gui/plotting/color/ColorMap.java | 27 + .../LinearInterpolatedGradientColorMap.java | 81 +++ .../gui/plotting/color/ViridisColorMap.java | 77 +++ .../jmultiaxisplot/JPlotMouseListener.java | 2 +- .../jmultiaxisplot/SubplotZoomData.java | 2 +- .../gui/plotting/plotobject/AbstractLine.java | 12 +- .../core/gui/plotting/plotobject/Line.java | 4 +- .../plotting/plotobject/PositionMarker.java | 2 +- .../llnl/gnem/core/io/FileDataSource.java | 11 +- .../llnl/gnem/core/io/SAC/SACFileReader.java | 23 +- .../java/llnl/gnem/core/io/SAC/SACHeader.java | 4 +- .../java/llnl/gnem/core/polygon/Vertex.java | 2 +- .../gnem/core/util/FileUtil/FileManager.java | 25 +- .../gnem/core/util/FileUtil/ListOfFiles.java | 26 +- .../util/MathFunctions/FitnessCriteria.java | 16 +- .../core/util/MathFunctions/MathFunction.java | 4 +- mapping/pom.xml | 25 +- .../apps/coda/common/mapping/LeafletIcon.java | 2 +- .../apps/coda/common/mapping/LeafletLine.java | 2 +- .../apps/coda/common/mapping/LeafletMap.java | 106 ++-- .../common/mapping/LeafletMapController.java | 14 +- .../mapping/MAP_CALLBACK_EVENT_TYPE.java | 28 + .../coda/common/mapping/MapCallbackEvent.java | 41 ++ .../common/mapping/WMSLayerDescriptor.java | 2 +- .../apps/coda/common/mapping/api/GeoMap.java | 7 + .../src/main/resources/leaflet/leaflet.html | 5 + pom.xml | 115 +++- schema/calibration-input-params.json.example | 12 +- schema/calibration-input-params.jsonschema | 71 ++- schema/measured-mws-output.json.example | 5 +- schema/measured-mws-output.jsonschema | 54 +- 215 files changed, 5047 insertions(+), 1584 deletions(-) create mode 100644 calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/MapConfig.java create mode 100644 calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/parameters/VelocityConfigurationController.java create mode 100644 calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/VelocityConfigurationFileMixin.java create mode 100644 calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/api/ReferenceMwTempFileWriter.java create mode 100644 calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/events/MapIconActivationCallback.java create mode 100644 calibration-gui/src/main/resources/fxml/Velocity.fxml create mode 100644 calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/ConfigurationItemJsonController.java create mode 100644 calibration-service/calibration-application/src/main/resources/META-INF/additional-spring-configuration-metadata.json create mode 100644 calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/InjectedVelocityConfig.java create mode 100644 calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/ShapeMeasurementMetadata.java create mode 100644 calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/SpectraMeasurementMetadata.java create mode 100644 calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/VelocityConfiguration.java create mode 100644 calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/mixins/ReferenceMwParametersFileMixin.java create mode 100644 calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/messaging/GvDataChangeEvent.java create mode 100644 calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/VelocityConfigurationRepository.java create mode 100644 calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/ConfigurationService.java create mode 100644 calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/ConfigurationServiceImpl.java create mode 100644 common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/WebclientConfig.java create mode 100644 common-service/common-application/src/main/java/gov/llnl/gnem/apps/coda/common/application/config/JettyConfiguration.java create mode 100644 common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/messaging/WaveformChangeEvent.java create mode 100644 common-service/common-service-impl/src/test/java/gov/llnl/gnem/apps/coda/common/service/CommonServiceTestContext.java create mode 100644 common-service/common-service-impl/src/test/java/gov/llnl/gnem/apps/coda/common/service/WaveformServiceImplTest.java create mode 100644 common-service/common-service-impl/src/test/resources/logback-test.xml create mode 100644 externals/src/main/java/llnl/gnem/core/gui/plotting/color/ColorMap.java create mode 100644 externals/src/main/java/llnl/gnem/core/gui/plotting/color/LinearInterpolatedGradientColorMap.java create mode 100644 externals/src/main/java/llnl/gnem/core/gui/plotting/color/ViridisColorMap.java create mode 100644 mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/MAP_CALLBACK_EVENT_TYPE.java create mode 100644 mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/MapCallbackEvent.java diff --git a/README.md b/README.md index 9d1b3b73..8020df36 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ![Livermore logo](llnl-logo.gif) The `Coda Calibration Tool` (CCT) is a Java based application for calibrating 1D shear wave coda measurement models to observed data using a much smaller set of reference MWs calculated from other means (waveform modeling, etc.). -
These calibrated measurement models can then be used in other tools to generate coda MW measurements, source spectra, estimated stress drop, and other useful measurements against the rest of the events and any new data collected in the calibrated region. +
These calibrated measurement models can then be used in other tools to generate coda MW measurements, source spectra, estimated stress, and other useful measurements against the rest of the events and any new data collected in the calibrated region. > ***note***
> The `Coda Calibration Tool` currently only does calibration; it requires data to be pre-processed for loading using other tools. @@ -97,7 +97,7 @@ As of 1.0, CCT is capable of loading four basic file types A simple space delimited text file of format: ```text - EVID MW [STRESS_DROP_IN_MPA|0.0] + EVID MW [APPARENT_STRESS_IN_MPA|0.0] (e.g. 999999 5.1 0.0) ``` > ***note***
diff --git a/calibration-gui/pom.xml b/calibration-gui/pom.xml index 25179af8..dcab9ce0 100644 --- a/calibration-gui/pom.xml +++ b/calibration-gui/pom.xml @@ -177,6 +177,10 @@ mockito-junit-jupiter test + + io.netty + netty-tcnative-boringssl-static + diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/AppProperties.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/AppProperties.java index c70ff08d..2bed41c6 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/AppProperties.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/AppProperties.java @@ -18,22 +18,16 @@ import java.util.List; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.stereotype.Component; -import gov.llnl.gnem.apps.coda.common.mapping.MapProperties; import gov.llnl.gnem.apps.coda.common.mapping.WMSLayerDescriptor; -@Component -@Configuration @ConfigurationProperties("app") public class AppProperties { private String baseTitle = "Coda Calibration"; private Integer height = 800; private Integer width = 600; - private Boolean debugEnabled = false; + private Boolean debugEnabled = Boolean.FALSE; private List wmsLayers = new ArrayList<>(); public Boolean getDebugEnabled() { @@ -75,9 +69,4 @@ public List getWmsLayers() { public void setWmsLayers(List wmsLayers) { this.wmsLayers = wmsLayers; } - - @Bean - public MapProperties getMapProperties() { - return new MapProperties().setLayers(wmsLayers); - } } 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 ce9212f4..d73a31ef 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 @@ -22,7 +22,6 @@ import java.util.HashMap; import java.util.Map; import java.util.Optional; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -49,14 +48,16 @@ import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.CalibrationClient; import gov.llnl.gnem.apps.coda.calibration.gui.data.exporters.ParamExporter; import gov.llnl.gnem.apps.coda.calibration.gui.events.CalibrationStageShownEvent; +import gov.llnl.gnem.apps.coda.calibration.gui.events.MapIconActivationCallback; +import gov.llnl.gnem.apps.coda.calibration.gui.plotting.WaveformGui; import gov.llnl.gnem.apps.coda.calibration.gui.util.CalibrationProgressListener; import gov.llnl.gnem.apps.coda.calibration.model.messaging.CalibrationStatusEvent; import gov.llnl.gnem.apps.coda.calibration.model.messaging.CalibrationStatusEvent.Status; import gov.llnl.gnem.apps.coda.common.gui.controllers.ProgressGui; -import gov.llnl.gnem.apps.coda.common.gui.events.EnvelopeLoadCompleteEvent; +import gov.llnl.gnem.apps.coda.common.gui.data.client.api.WaveformClient; import gov.llnl.gnem.apps.coda.common.gui.events.ShowFailureReportEvent; import gov.llnl.gnem.apps.coda.common.gui.util.ProgressMonitor; -import gov.llnl.gnem.apps.coda.common.mapping.LeafletMapController; +import gov.llnl.gnem.apps.coda.common.mapping.api.GeoMap; import javafx.application.Platform; import javafx.event.ActionEvent; import javafx.fxml.FXML; @@ -79,11 +80,12 @@ public class CodaGuiController { @FXML private Node rootElement; + private WaveformGui waveformGui; private DataController data; private ParametersController param; private ShapeController shape; private PathController path; - private SiteController site; + private SiteController site; @FXML private Tab dataTab; @@ -117,7 +119,9 @@ public class CodaGuiController { private Label showMapIcon; - private LeafletMapController mapController; + private GeoMap mapController; + + private WaveformClient waveformClient; private EnvelopeLoadingController envelopeLoadingController; @@ -153,16 +157,18 @@ public class CodaGuiController { }); @Autowired - public CodaGuiController(LeafletMapController mapController, EnvelopeLoadingController waveformLoadingController, CodaParamLoadingController codaParamLoadingController, - ReferenceEventLoadingController refEventLoadingController, CalibrationClient calibrationClient, ParamExporter paramExporter, DataController data, ParametersController param, - ShapeController shape, PathController path, SiteController site, EventBus bus) throws IOException { + public CodaGuiController(GeoMap mapController, WaveformClient waveformClient, EnvelopeLoadingController waveformLoadingController, CodaParamLoadingController codaParamLoadingController, + ReferenceEventLoadingController refEventLoadingController, CalibrationClient calibrationClient, ParamExporter paramExporter, WaveformGui waveformGui, DataController data, + ParametersController param, ShapeController shape, PathController path, SiteController site, EventBus bus) throws IOException { super(); this.mapController = mapController; + this.waveformClient = waveformClient; this.envelopeLoadingController = waveformLoadingController; this.codaParamLoadingController = codaParamLoadingController; this.refEventLoadingController = refEventLoadingController; this.calibrationClient = calibrationClient; this.paramExporter = paramExporter; + this.waveformGui = waveformGui; this.data = data; this.param = param; this.shape = shape; @@ -213,6 +219,11 @@ private void showMapWindow() { }); } + @FXML + private void openWaveformDisplay() { + waveformGui.toFront(); + } + @FXML private void openFailureReportDisplay() { bus.post(new ShowFailureReportEvent()); @@ -295,21 +306,24 @@ private void openMdacFiWindow() { @FXML private void runCalibration() { - calibrationClient.runCalibration(Boolean.FALSE).subscribe(value -> log.trace(value.toString()), err -> log.trace(err.getMessage(), err)); + calibrationClient.runCalibration(Boolean.FALSE).subscribe(value -> log.trace(value), err -> log.trace(err.getMessage(), err)); } @FXML private void clearData() { - calibrationClient.clearData().subscribe(value -> log.trace(value.toString()), err -> log.trace(err.getMessage(), err)); + calibrationClient.clearData().subscribe(value -> log.trace(value), err -> log.trace(err.getMessage(), err), () -> dataRefresh.run()); } @FXML private void runAutoPickingCalibration() { - calibrationClient.runCalibration(Boolean.TRUE).subscribe(value -> log.trace(value.toString()), err -> log.trace(err.getMessage(), err)); + calibrationClient.runCalibration(Boolean.TRUE).subscribe(value -> log.trace(value), err -> log.trace(err.getMessage(), err)); } @FXML public void initialize() { + + mapController.registerEventCallback(new MapIconActivationCallback(waveformClient)); + activeMapIcon = makeMapLabel(); showMapIcon = makeMapLabel(); @@ -396,14 +410,29 @@ private void listener(CalibrationStatusEvent event) { if (event.getStatus() == Status.COMPLETE || event.getStatus() == Status.ERROR) { final ProgressMonitor monitor = monitors.remove(event.getId()); + monitor.setProgressStage("Finished"); service.schedule(() -> loadingGui.removeProgressMonitor(monitor), 15, TimeUnit.MINUTES); - } - } + } else { + ProgressMonitor monitor = monitors.get(event.getId()); + if (monitor != null) { + switch (event.getStatus()) { + case PEAK_STARTING: + monitor.setProgressStage("Peak starting"); + break; + case SHAPE_STARTING: + monitor.setProgressStage("Shape starting"); + break; + case PATH_STARTING: + monitor.setProgressStage("Path starting"); + break; + case SITE_STARTING: + monitor.setProgressStage("Site starting"); + break; + default: + break; - @Subscribe - private void listener(EnvelopeLoadCompleteEvent evt) { - if (dataTab.isSelected()) { - CompletableFuture.runAsync(dataRefresh); + } + } } } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/GuiApplication.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/GuiApplication.java index 148a51ea..26372a6a 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/GuiApplication.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/GuiApplication.java @@ -167,7 +167,7 @@ public void stop() throws Exception { springContext.stop(); springContext.close(); }).get(1, TimeUnit.SECONDS); - } catch (TimeoutException | ExecutionException | CancellationException | InterruptedException e) { + } catch (TimeoutException | ExecutionException | CancellationException e) { } Platform.exit(); System.exit(0); diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/MapConfig.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/MapConfig.java new file mode 100644 index 00000000..e61c63ff --- /dev/null +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/MapConfig.java @@ -0,0 +1,37 @@ +/* +* 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.gui; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; + +import gov.llnl.gnem.apps.coda.common.mapping.MapProperties; + +@Configuration +@Component +public class MapConfig { + + private AppProperties props; + + public MapConfig(AppProperties props) { + super(); + this.props = props; + } + + @Bean + public MapProperties getMapProperties() { + return new MapProperties().setLayers(props.getWmsLayers()); + } +} 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 47791487..9fb1c855 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 @@ -25,7 +25,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import com.fasterxml.jackson.core.JsonProcessingException; @@ -38,12 +37,11 @@ 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.VelocityConfiguration; import gov.llnl.gnem.apps.coda.common.model.domain.SharedFrequencyBandParameters; import reactor.core.publisher.Mono; -//TODO: This class needs a GUI to display a list of files it's attempting to load and process + pass/fail indicators @Component -@ConfigurationProperties("coda.param.client") public class CodaParamLoadingController { private static final Logger log = LoggerFactory.getLogger(CodaParamLoadingController.class); @@ -85,67 +83,77 @@ 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 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 MdacParametersFI {}", entry); - } - } catch (JsonProcessingException ex) { - log.trace(ex.getMessage(), ex); - } - } - } - } - })); + 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 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); + } + } + } + } + })); } private boolean validPath(Path p) { - Optional> match = Optional.ofNullable(fileConverters).orElse(Collections.emptyList()).stream().filter(fc -> fc.getMatchingPattern().matches(p)).findAny(); + Optional> match = Optional.ofNullable(fileConverters).orElseGet(() -> Collections.emptyList()).stream().filter(fc -> fc.getMatchingPattern().matches(p)).findAny(); return match.isPresent(); } 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 3a102562..3659254b 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 @@ -16,20 +16,27 @@ import java.text.NumberFormat; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.stream.Collectors; +import javax.annotation.PreDestroy; + 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.plotting.MapPlottingUtilities; import gov.llnl.gnem.apps.coda.common.gui.data.client.api.WaveformClient; @@ -44,18 +51,24 @@ import gov.llnl.gnem.apps.coda.common.model.domain.Station; 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.WaveformChangeEvent; +import javafx.application.Platform; import javafx.beans.binding.Bindings; import javafx.collections.FXCollections; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; import javafx.event.ActionEvent; +import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.scene.control.CheckBox; +import javafx.scene.control.ContextMenu; import javafx.scene.control.MenuItem; import javafx.scene.control.SelectionMode; import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn.CellDataFeatures; import javafx.scene.control.TableView; +import javafx.scene.input.MouseButton; +import javafx.scene.input.MouseEvent; @Component public class DataController implements MapListeningController, RefreshableController { @@ -71,6 +84,9 @@ public class DataController implements MapListeningController, RefreshableContro @FXML private CheckBox selectAllCheckbox; + @FXML + private TableColumn usedCol; + @FXML private TableColumn stationCol; @@ -101,6 +117,15 @@ public class DataController implements MapListeningController, RefreshableContro private final BiConsumer eventSelectionCallback; private final BiConsumer stationSelectionCallback; + private ScheduledExecutorService scheduled = Executors.newSingleThreadScheduledExecutor(r -> { + Thread thread = new Thread(r); + thread.setDaemon(true); + return thread; + }); + + private List dataUpdateList = Collections.synchronizedList(new ArrayList<>()); + private List dataDeleteList = Collections.synchronizedList(new ArrayList<>()); + private List updatedData = Collections.synchronizedList(new ArrayList<>()); @Autowired public DataController(WaveformClient client, GeoMap mapImpl, MapPlottingUtilities iconFactory, EventBus bus) { @@ -111,6 +136,7 @@ public DataController(WaveformClient client, GeoMap mapImpl, MapPlottingUtilitie this.bus = bus; bus.register(this); tableChangeListener = buildTableListener(); + scheduled.scheduleWithFixedDelay(() -> updateData(), 1000l, 1000l, TimeUnit.MILLISECONDS); eventSelectionCallback = (selected, eventId) -> { selectDataByCriteria(bus, selected, (w) -> w.getEvent() != null && w.getEvent().getEventId().equalsIgnoreCase(eventId)); @@ -126,13 +152,17 @@ private void selectDataByCriteria(EventBus bus, Boolean selected, Function selectionIndices = new ArrayList<>(); tableView.getSelectionModel().clearSelection(); if (selected) { - for (int i = 0; i < listData.size(); i++) { - Waveform w = listData.get(i); - if (matchCriteria.apply(w)) { - selection.add(w); - tableView.getSelectionModel().select(i); + tableView.getSelectionModel().getSelectedItems().removeListener(tableChangeListener); + synchronized (listData) { + for (int i = 0; i < listData.size(); i++) { + Waveform w = listData.get(i); + if (matchCriteria.apply(w)) { + selection.add(w); + tableView.getSelectionModel().select(i); + } } } + tableView.getSelectionModel().getSelectedItems().addListener(tableChangeListener); if (!selection.isEmpty()) { selection.sort(eventStaFreqComparator); Long[] ids = selection.stream().sequential().map(w -> w.getId()).collect(Collectors.toList()).toArray(new Long[0]); @@ -154,11 +184,15 @@ private ListChangeListener buildTableListener() { List selection = new ArrayList<>(); selection.addAll(tableView.getSelectionModel().getSelectedItems()); selection.sort(eventStaFreqComparator); - Long[] ids = selection.stream().sequential().map(w -> w.getId()).collect(Collectors.toList()).toArray(new Long[0]); + Long[] ids = getIds(selection).toArray(new Long[0]); bus.post(new WaveformSelectionEvent(ids)); }; } + private List getIds(List selection) { + return selection.stream().sequential().map(w -> w.getId()).collect(Collectors.toList()); + } + @FXML private void reloadTable(ActionEvent e) { CompletableFuture.runAsync(getRefreshFunction()); @@ -167,7 +201,6 @@ private void reloadTable(ActionEvent e) { @FXML public void initialize() { tableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); - eventCol.setCellValueFactory( x -> Bindings.createStringBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(Waveform::getEvent).map(Event::getEventId).orElseGet(String::new))); eventCol.comparatorProperty().set(new MaybeNumericStringComparator()); @@ -175,6 +208,23 @@ public void initialize() { CellBindingUtils.attachTextCellFactories(lowFreqCol, Waveform::getLowFrequency, dfmt2); CellBindingUtils.attachTextCellFactories(highFreqCol, Waveform::getHighFrequency, dfmt2); + usedCol.setCellValueFactory(x -> Bindings.createObjectBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(waveform -> { + CheckBox box = new CheckBox(); + box.setSelected(waveform.isActive()); + if (!waveform.isActive()) { + box.setStyle("-fx-background-color: red"); + } else { + box.setStyle(""); + } + box.selectedProperty().addListener((obs, o, n) -> { + if (n != null && o != n) { + client.setWaveformsActiveByIds(Collections.singletonList(waveform.getId()), n).subscribe(); + } + }); + return box; + }).orElseGet(CheckBox::new))); + usedCol.comparatorProperty().set((c1, c2) -> Boolean.compare(c1.isSelected(), c2.isSelected())); + stationCol.setCellValueFactory( x -> Bindings.createStringBinding( () -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(Waveform::getStream).map(Stream::getStation).map(Station::getStationName).orElseGet(String::new))); @@ -186,18 +236,49 @@ public void initialize() { tableView.getSelectionModel().clearSelection(); } }); + + ContextMenu menu = new ContextMenu(); + MenuItem include = new MenuItem("Include Selected"); + include.setOnAction(evt -> includeWaveforms()); + menu.getItems().add(include); + MenuItem exclude = new MenuItem("Exclude Selected"); + exclude.setOnAction(evt -> excludeWaveforms()); + menu.getItems().add(exclude); + + tableView.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler() { + @Override + public void handle(MouseEvent t) { + if (MouseButton.SECONDARY == t.getButton()) { + menu.show(tableView, t.getScreenX(), t.getScreenY()); + } else { + menu.hide(); + } + } + }); + tableView.setItems(listData); } @Override public void refreshView() { - if (listData.isEmpty()) { - CompletableFuture.runAsync(getRefreshFunction()); - } else { - CompletableFuture.runAsync(() -> { - mapImpl.clearIcons(); - listData.forEach(waveform -> mapImpl.addIcons(genIconsFromData(waveform))); + CompletableFuture.runAsync(() -> { + synchronized (listData) { + if (!listData.isEmpty()) { + refreshMap(); + } + } + Platform.runLater(() -> { + if (tableView != null) { + tableView.refresh(); + } }); + }); + } + + private void refreshMap() { + mapImpl.clearIcons(); + synchronized (listData) { + listData.forEach(waveform -> mapImpl.addIcons(genIconsFromData(waveform))); } } @@ -207,16 +288,95 @@ public Runnable getRefreshFunction() { } private void requestData() { - listData.clear(); + synchronized (listData) { + listData.clear(); + } mapImpl.clearIcons(); client.getUniqueEventStationMetadataForStacks().filter(Objects::nonNull).doOnComplete(() -> { tableView.sort(); refreshView(); }).subscribe(waveform -> { - listData.add(waveform); + synchronized (listData) { + listData.add(waveform); + } }, err -> log.error(err.getMessage(), err)); } + private void requestUpdates() { + List updates = new ArrayList(); + List deletes = new ArrayList(); + synchronized (dataUpdateList) { + updates.addAll(dataUpdateList); + dataUpdateList.clear(); + deletes.addAll(dataDeleteList); + dataDeleteList.clear(); + } + + if (!deletes.isEmpty()) { + synchronized (listData) { + deletes.forEach(id -> { + synchronized (listData) { + int idx = -1; + for (int i = 0; i < listData.size(); i++) { + if (listData.get(i).getId().equals(id)) { + idx = i; + break; + } + } + if (idx >= 0) { + listData.remove(idx); + } + } + }); + } + } + + client.getWaveformMetadataFromIds(updates).filter(Objects::nonNull).subscribe(waveform -> updatedData.add(waveform), err -> log.error(err.getMessage(), err)); + } + + private void updateData() { + List updates = new ArrayList<>(); + synchronized (updatedData) { + updates.addAll(updatedData); + updatedData.clear(); + } + if (!updates.isEmpty()) { + synchronized (listData) { + tableView.getSelectionModel().getSelectedItems().removeListener(tableChangeListener); + updates.forEach(waveform -> { + int idx = -1; + for (int i = 0; i < listData.size(); i++) { + if (listData.get(i).getId().equals(waveform.getId())) { + idx = i; + break; + } + } + if (idx >= 0) { + listData.set(idx, waveform); + } else { + listData.add(waveform); + } + }); + tableView.getSelectionModel().getSelectedItems().addListener(tableChangeListener); + } + if (tableView.isVisible()) { + refreshMap(); + } + } + } + + private void excludeWaveforms() { + client.setWaveformsActiveByIds(getSelectedWaveforms(), false).subscribe(); + } + + private void includeWaveforms() { + client.setWaveformsActiveByIds(getSelectedWaveforms(), true).subscribe(); + } + + private List getSelectedWaveforms() { + return getIds(tableView.getSelectionModel().getSelectedItems()); + } + protected List genIconsFromData(Waveform waveform) { List icons = new ArrayList<>(); if (waveform != null && waveform.getStream() != null && waveform.getEvent() != null) { @@ -226,4 +386,21 @@ protected List genIconsFromData(Waveform waveform) { return icons; } + @Subscribe + private void listener(WaveformChangeEvent wce) { + List nonNull = wce.getIds().stream().filter(Objects::nonNull).collect(Collectors.toList()); + synchronized (dataUpdateList) { + if (wce.isAddOrUpdate()) { + dataUpdateList.addAll(nonNull); + } else if (wce.isDelete()) { + dataDeleteList.addAll(nonNull); + } + } + requestUpdates(); + } + + @PreDestroy + private void cleanup() { + scheduled.shutdownNow(); + } } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/EnvelopeLoadingController.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/EnvelopeLoadingController.java index 56f2401f..b3aeca28 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/EnvelopeLoadingController.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/EnvelopeLoadingController.java @@ -20,7 +20,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import com.google.common.eventbus.EventBus; @@ -29,21 +28,19 @@ import gov.llnl.gnem.apps.coda.common.gui.converters.api.FileToEnvelopeConverter; import gov.llnl.gnem.apps.coda.common.gui.converters.sac.SacExporter; import gov.llnl.gnem.apps.coda.common.gui.data.client.api.WaveformClient; -import gov.llnl.gnem.apps.coda.common.gui.events.EnvelopeLoadCompleteEvent; import gov.llnl.gnem.apps.coda.common.gui.util.ProgressEventProgressListener; import gov.llnl.gnem.apps.coda.common.gui.util.ProgressMonitor; import gov.llnl.gnem.apps.coda.common.model.messaging.Progress; import gov.llnl.gnem.apps.coda.common.model.messaging.ProgressEvent; @Component -@ConfigurationProperties("waveform.client") public class EnvelopeLoadingController extends AbstractSeismogramSaveLoadController { private static final Logger log = LoggerFactory.getLogger(EnvelopeLoadingController.class); @Autowired public EnvelopeLoadingController(List fileConverters, WaveformClient client, EventBus bus, SacExporter sacExporter) { - super(fileConverters, bus, log, sacExporter, () -> client.getAllStacks(), (id, waveforms) -> client.postWaveforms(id, waveforms)); + super(fileConverters, bus, log, sacExporter, () -> client.getAllActiveStacks(), (id, waveforms) -> client.postWaveforms(id, waveforms)); } @Override @@ -52,7 +49,6 @@ public void loadFiles(List inputFiles) { ProgressEvent progressEvent = new ProgressEvent(idCounter.getAndIncrement(), progress); ProgressMonitor progressMonitor = new ProgressMonitor("Data Processing", new ProgressEventProgressListener(bus, progressEvent)); super.loadFiles(inputFiles, () -> { - bus.post(new EnvelopeLoadCompleteEvent()); progress.setTotal(1l); progress.setCurrent(1l); bus.post(progressEvent); 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 43086ef6..509bc0d5 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 @@ -31,6 +31,7 @@ import java.util.Objects; import java.util.Observable; import java.util.Observer; +import java.util.Optional; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; @@ -48,6 +49,7 @@ 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.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.util.EventStaFreqStringComparator; import gov.llnl.gnem.apps.coda.common.gui.util.NumberFormatFactory; @@ -62,10 +64,15 @@ import javafx.collections.FXCollections; import javafx.collections.ObservableSet; import javafx.embed.swing.SwingNode; +import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.scene.control.ComboBox; +import javafx.scene.control.ContextMenu; import javafx.scene.control.ListCell; +import javafx.scene.control.MenuItem; import javafx.scene.control.Tooltip; +import javafx.scene.input.MouseButton; +import javafx.scene.layout.Pane; import llnl.gnem.core.gui.plotting.JBasicPlot; import llnl.gnem.core.gui.plotting.MouseOverPlotObject; import llnl.gnem.core.gui.plotting.PaintMode; @@ -107,7 +114,11 @@ public class PathController implements MapListeningController, RefreshableContro @FXML SwingNode sdPlotSwingNode; + @FXML + Pane path; + private SpectraClient spectraMeasurementClient; + private WaveformClient waveformClient; private GeoMap mapImpl; @@ -127,11 +138,15 @@ public class PathController implements MapListeningController, RefreshableContro private final BiConsumer eventSelectionCallback; private final BiConsumer stationSelectionCallback; private final List selectedSymbols = new ArrayList<>(); + private MenuItem exclude; + private MenuItem include; + private ContextMenu menu; @Autowired - public PathController(SpectraClient spectraMeasurementClient, EventBus bus, GeoMap mapImpl, MapPlottingUtilities mappingUtilities) { + public PathController(SpectraClient spectraMeasurementClient, WaveformClient waveformClient, EventBus bus, GeoMap mapImpl, MapPlottingUtilities mappingUtilities) { super(); this.spectraMeasurementClient = spectraMeasurementClient; + this.waveformClient = waveformClient; this.mapImpl = mapImpl; this.mappingUtilities = mappingUtilities; this.bus = bus; @@ -214,7 +229,7 @@ public void update(Observable observable, Object obj) { if (obj instanceof MouseOverPlotObject) { MouseOverPlotObject pos = (MouseOverPlotObject) obj; PlotObject po = pos.getPlotObject(); - if (po != null && po instanceof Symbol) { + if (po instanceof Symbol) { Platform.runLater(() -> { stationPlotTooltip.setText(((Symbol) po).getText()); Point p = MouseInfo.getPointerInfo().getLocation(); @@ -228,14 +243,9 @@ public void update(Observable observable, Object obj) { if (obj instanceof PlotObjectClicked && ((PlotObjectClicked) obj).getMouseEvent().getID() == MouseEvent.MOUSE_RELEASED) { PlotObjectClicked poc = (PlotObjectClicked) obj; PlotObject po = poc.getPlotObject(); - if (po != null && po instanceof Symbol) { - TreeSet sortedSet = new TreeSet(evStaComparator); - sortedSet.addAll(stationSymbolMap.get(new Point2D.Double(((Symbol) po).getXcenter(), ((Symbol) po).getYcenter()))); - List ids = sortedSet.stream().sequential().map(w -> w.getId()).collect(Collectors.toList()); - if (ids != null) { - selectSymbolsForWaveforms(sortedSet); - selectWaveforms(ids.toArray(new Long[0])); - } + if (po instanceof Symbol) { + List waveforms = stationSymbolMap.get(new Point2D.Double(((Symbol) po).getXcenter(), ((Symbol) po).getYcenter())); + handlePlotObjectClicked(poc, waveforms); } } } @@ -253,7 +263,7 @@ public void update(Observable observable, Object obj) { if (obj instanceof MouseOverPlotObject) { MouseOverPlotObject pos = (MouseOverPlotObject) obj; PlotObject po = pos.getPlotObject(); - if (po != null && po instanceof Symbol) { + if (po instanceof Symbol) { Platform.runLater(() -> { sdPlotTooltip.setText(((Symbol) po).getText()); Point p = MouseInfo.getPointerInfo().getLocation(); @@ -267,14 +277,9 @@ public void update(Observable observable, Object obj) { if (obj instanceof PlotObjectClicked && ((PlotObjectClicked) obj).getMouseEvent().getID() == MouseEvent.MOUSE_RELEASED) { PlotObjectClicked poc = (PlotObjectClicked) obj; PlotObject po = poc.getPlotObject(); - if (po != null && po instanceof Symbol) { - TreeSet sortedSet = new TreeSet(evStaComparator); - sortedSet.addAll(sdSymbolMap.get(new Point2D.Double(((Symbol) po).getXcenter(), ((Symbol) po).getYcenter()))); - List ids = sortedSet.stream().sequential().map(w -> w.getId()).collect(Collectors.toList()); - if (ids != null) { - selectSymbolsForWaveforms(sortedSet); - selectWaveforms(ids.toArray(new Long[0])); - } + if (po instanceof Symbol) { + List waveforms = sdSymbolMap.get(new Point2D.Double(((Symbol) po).getXcenter(), ((Symbol) po).getYcenter())); + handlePlotObjectClicked(poc, waveforms); } } } @@ -301,9 +306,51 @@ public void update(Observable observable, Object obj) { station1ComboBox.valueProperty().addListener(e -> refreshView()); station2ComboBox.valueProperty().addListener(e -> refreshView()); + + 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(); + } + }; + path.addEventHandler(javafx.scene.input.MouseEvent.MOUSE_CLICKED, menuHideHandler); + sdPlotSwingNode.addEventHandler(javafx.scene.input.MouseEvent.MOUSE_CLICKED, menuHideHandler); + stationPlotSwingNode.addEventHandler(javafx.scene.input.MouseEvent.MOUSE_CLICKED, menuHideHandler); + } + + private void setSymbolsActive(List ws, Boolean active) { + SwingUtilities.invokeLater(() -> { + ws.stream().flatMap(w -> Optional.ofNullable(stationWaveformMap.get(w.getEvent().getEventId())).orElseGet(() -> new ArrayList<>()).stream()).forEach(sym -> { + if (active) { + sym.setFillColor(sym.getEdgeColor()); + } else { + sym.setFillColor(Color.GRAY); + } + }); + Platform.runLater(() -> { + stationPlot.repaint(); + }); + }); + } + + private void showContextMenu(List waveforms, MouseEvent t, BiConsumer, Boolean> activationFunc) { + Platform.runLater(() -> { + include.setOnAction(evt -> setActive(waveforms, true, activationFunc)); + exclude.setOnAction(evt -> setActive(waveforms, false, activationFunc)); + menu.show(path, t.getXOnScreen(), t.getYOnScreen()); + }); + } + + private void setActive(List waveforms, boolean active, BiConsumer, Boolean> activationFunc) { + waveformClient.setWaveformsActiveByIds(waveforms.stream().map(w -> w.getId()).collect(Collectors.toList()), active).subscribe(s -> activationFunc.accept(waveforms, active)); } - protected void selectSymbolsForWaveforms(Collection sortedSet) { + private void selectSymbolsForWaveforms(Collection sortedSet) { if (!selectedSymbols.isEmpty()) { deselectSymbols(selectedSymbols); selectedSymbols.clear(); @@ -349,7 +396,7 @@ private void reloadData() { frequencyBandComboBox.getItems().clear(); measurementsFreqBandMap.putAll( - spectraMeasurementClient.getMeasuredSpectra() + spectraMeasurementClient.getMeasuredSpectraMetadata() .filter(Objects::nonNull) .filter(spectra -> spectra.getWaveform() != null) .toStream() @@ -501,7 +548,6 @@ private void plotSd() { } for (Entry, Double> distanceStaPair : distanceStaPairs.entrySet()) { - Pair staPair = distanceStaPair.getKey(); if (Double.isNaN(beforeStatsStaPairs.get(staPair).getStandardDeviation()) || beforeStatsStaPairs.get(staPair).getStandardDeviation() == 0.0) { continue; @@ -621,7 +667,7 @@ private void plotBeforeAfter() { TriangleUp plotObj = new TriangleUp(firstMeasurement.getRawAtMeasurementTime(), secondMeasurement.getRawAtMeasurementTime(), 5.0, - Color.RED, + firstMeasurement.getWaveform().isActive() ? Color.RED : Color.GRAY, Color.RED, Color.RED, firstStation.getStationName(), @@ -633,7 +679,7 @@ private void plotBeforeAfter() { TriangleDn plotObj2 = new TriangleDn(firstMeasurement.getPathCorrected(), secondMeasurement.getPathCorrected(), 5.0, - Color.BLUE, + firstMeasurement.getWaveform().isActive() ? Color.BLUE : Color.GRAY, Color.BLUE, Color.BLUE, secondStation.getStationName(), @@ -744,4 +790,21 @@ private void plotBeforeAfter() { }); } } + + private void handlePlotObjectClicked(PlotObjectClicked poc, List waveforms) { + if (waveforms != null) { + if (SwingUtilities.isLeftMouseButton(poc.getMouseEvent())) { + TreeSet sortedSet = new TreeSet(evStaComparator); + sortedSet.addAll(waveforms); + List ids = sortedSet.stream().sequential().map(w -> w.getId()).collect(Collectors.toList()); + selectSymbolsForWaveforms(sortedSet); + selectWaveforms(ids.toArray(new Long[0])); + Platform.runLater(() -> menu.hide()); + } else if (SwingUtilities.isRightMouseButton(poc.getMouseEvent())) { + showContextMenu(waveforms, poc.getMouseEvent(), (ws, active) -> { + setSymbolsActive(ws, active); + }); + } + } + } } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/ShapeController.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/ShapeController.java index 0c285ac0..f115a3b5 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/ShapeController.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/ShapeController.java @@ -17,6 +17,7 @@ import java.text.NumberFormat; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -40,15 +41,18 @@ import gov.llnl.gnem.apps.coda.calibration.gui.plotting.MapPlottingUtilities; import gov.llnl.gnem.apps.coda.calibration.model.domain.PeakVelocityMeasurement; import gov.llnl.gnem.apps.coda.calibration.model.domain.ShapeMeasurement; +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.util.EventStaFreqStringComparator; import gov.llnl.gnem.apps.coda.common.gui.util.NumberFormatFactory; import gov.llnl.gnem.apps.coda.common.mapping.api.GeoMap; import gov.llnl.gnem.apps.coda.common.mapping.api.Icon; import gov.llnl.gnem.apps.coda.common.model.domain.FrequencyBand; +import gov.llnl.gnem.apps.coda.common.model.domain.Pair; import gov.llnl.gnem.apps.coda.common.model.domain.SharedFrequencyBandParameters; import gov.llnl.gnem.apps.coda.common.model.domain.Station; import gov.llnl.gnem.apps.coda.common.model.domain.Waveform; +import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.Event; @@ -59,9 +63,14 @@ import javafx.scene.chart.XYChart.Data; import javafx.scene.chart.XYChart.Series; import javafx.scene.control.ComboBox; +import javafx.scene.control.ContextMenu; import javafx.scene.control.ListCell; +import javafx.scene.control.MenuItem; +import javafx.scene.input.MouseButton; import javafx.scene.input.MouseEvent; +import javafx.scene.input.ScrollEvent; import javafx.scene.layout.StackPane; +import javafx.scene.transform.Affine; @Component public class ShapeController implements MapListeningController, RefreshableController { @@ -79,10 +88,13 @@ private enum SHAPE_DATA_TYPE { private static final int XAXIS_MIN = 0; private static final int XAXIS_MAX = 5000; private static final double LINE_SEGMENTS = 250.0; + private static final double SCALE_IN = 1.5; + private static final double SCALE_OUT = 0.5; private Map> velocityDistancePairsFreqMap = new HashMap<>(); private Map> shapeDistancePairsFreqMap = new HashMap<>(); private Map modelCurveMap = new TreeMap<>(); + private Map, List>> waveformIdMapping = new HashMap<>(); private EventStaFreqStringComparator eventStaFreqComparator = new EventStaFreqStringComparator(); @FXML @@ -106,6 +118,7 @@ private enum SHAPE_DATA_TYPE { private ParameterClient paramClient; private PeakVelocityClient velocityClient; private ShapeMeasurementClient shapeClient; + private WaveformClient waveformClient; private NumberFormat dfmt = NumberFormatFactory.twoDecimalOneLeadingZero(); private ObservableList> modelData = FXCollections.observableArrayList(); @@ -126,12 +139,17 @@ private enum SHAPE_DATA_TYPE { private final BiConsumer eventSelectionCallback; private final BiConsumer stationSelectionCallback; private FrequencyBand selectedBand; + private MenuItem exclude; + private MenuItem include; + private ContextMenu menu; @Autowired - private ShapeController(ParameterClient paramClient, PeakVelocityClient velocityClient, ShapeMeasurementClient shapeClient, GeoMap map, MapPlottingUtilities iconFactory, EventBus bus) { + private ShapeController(ParameterClient paramClient, PeakVelocityClient velocityClient, ShapeMeasurementClient shapeClient, WaveformClient waveformClient, GeoMap map, + MapPlottingUtilities iconFactory, EventBus bus) { this.paramClient = paramClient; this.velocityClient = velocityClient; this.shapeClient = shapeClient; + this.waveformClient = waveformClient; this.bus = bus; this.mapImpl = map; this.iconFactory = iconFactory; @@ -182,7 +200,6 @@ private void selectDataByCriteria(EventBus bus, Boolean selected, String key) { @FXML public void initialize() { - mainFitPlot.setAnimated(false); yAxis.setAutoRanging(false); @@ -220,8 +237,40 @@ public void initialize() { mainFitPlot.setData(series); mainFitPlot.setLegendVisible(false); modelCurveSeries.getNode().setMouseTransparent(true); + modelCurveSeries.getNode().toFront(); + selectedSeries.getNode().setMouseTransparent(true); highlightedSeries.getNode().setMouseTransparent(true); + + mainFitPlot.addEventHandler(MouseEvent.MOUSE_CLICKED, (evt) -> { + if (MouseButton.SECONDARY != evt.getButton()) { + menu.hide(); + } + }); + + final Affine scaleTrans = new Affine(); + mainFitPlot.getTransforms().add(scaleTrans); + + mainFitPlot.setOnScroll(new EventHandler() { + @Override + public void handle(ScrollEvent event) { + if (event.getDeltaY() < 0) { + if (mainFitPlot.getScaleX() * SCALE_OUT < 1.0) { + scaleTrans.setToIdentity(); + } else { + scaleTrans.appendScale(SCALE_OUT, SCALE_OUT, event.getX(), event.getY()); + } + } else { + scaleTrans.appendScale(SCALE_IN, SCALE_IN, event.getX(), event.getY()); + } + } + }); + + menu = new ContextMenu(); + include = new MenuItem("Include Selected"); + menu.getItems().add(include); + exclude = new MenuItem("Exclude Selected"); + menu.getItems().add(exclude); } private ListCell getFBCell() { @@ -289,7 +338,13 @@ private void plotGamma(final FrequencyBand selectedFrequency) { Function> valueSupplier = createValueSupplier(shapeDistancePairsFreqMap); Function mapFunc = ShapeMeasurement::getWaveform; mapValues(selectedFrequency, valueSupplier, mapFunc); - plot(selectedFrequency, valueSupplier, val -> new Data<>(val.getDistance(), val.getMeasuredGamma()), val -> showWaveformPopup(val.getWaveform()), curvePointProducer, mapFunc); + plot( + selectedFrequency, + valueSupplier, + val -> new Data<>(val.getDistance(), val.getMeasuredGamma()), + (data, val) -> clickEventHandler(data, val.getWaveform()), + curvePointProducer, + mapFunc); } } @@ -302,7 +357,7 @@ private void plotBeta(final FrequencyBand selectedFrequency) { Function> valueSupplier = createValueSupplier(shapeDistancePairsFreqMap); Function mapFunc = ShapeMeasurement::getWaveform; mapValues(selectedFrequency, valueSupplier, mapFunc); - plot(selectedFrequency, valueSupplier, val -> new Data<>(val.getDistance(), val.getMeasuredBeta()), val -> showWaveformPopup(val.getWaveform()), curvePointProducer, mapFunc); + plot(selectedFrequency, valueSupplier, val -> new Data<>(val.getDistance(), val.getMeasuredBeta()), (data, val) -> clickEventHandler(data, val.getWaveform()), curvePointProducer, mapFunc); } } @@ -315,7 +370,47 @@ private void plotVelocity(final FrequencyBand selectedFrequency) { Function> valueSupplier = createValueSupplier(velocityDistancePairsFreqMap); Function mapFunc = PeakVelocityMeasurement::getWaveform; mapValues(selectedFrequency, valueSupplier, mapFunc); - plot(selectedFrequency, valueSupplier, val -> new Data<>(val.getDistance(), val.getVelocity()), val -> showWaveformPopup(val.getWaveform()), curvePointProducer, mapFunc); + plot(selectedFrequency, valueSupplier, val -> new Data<>(val.getDistance(), val.getVelocity()), (data, val) -> clickEventHandler(data, val.getWaveform()), curvePointProducer, mapFunc); + } + } + + private EventHandler clickEventHandler(Data data, Waveform waveform) { + return event -> { + if (event instanceof MouseEvent) { + MouseEvent evt = (MouseEvent) event; + if (MouseButton.PRIMARY == evt.getButton()) { + showWaveformPopup(waveform); + } else if (MouseButton.SECONDARY == evt.getButton()) { + showContextMenu(data, waveform, evt); + } + } + }; + } + + private void showContextMenu(Data data, Waveform waveform, MouseEvent t) { + include.setOnAction(evt -> includeWaveforms(data, waveform)); + exclude.setOnAction(evt -> excludeWaveforms(data, waveform)); + menu.show(mainFitPlot, t.getScreenX(), t.getScreenY()); + } + + private void excludeWaveforms(Data data, Waveform waveform) { + setActive(data, waveform, false); + } + + private void includeWaveforms(Data data, Waveform waveform) { + setActive(data, waveform, true); + } + + private void setActive(Data data, Waveform waveform, boolean active) { + if (waveformClient != null && waveform != null && waveform.getId() != null) { + waveformClient.setWaveformsActiveByIds(Collections.singletonList(waveform.getId()), active).subscribe(s -> { + Pair, List> pair = waveformIdMapping.get(waveform.getId()); + if (pair != null) { + pair.getLeft().forEach(v -> v.getWaveform().setActive(active)); + pair.getRight().forEach(v -> v.getWaveform().setActive(active)); + Platform.runLater(() -> refreshView()); + } + }); } } @@ -326,7 +421,7 @@ private void mapValues(final FrequencyBand selectedFrequency, Function Function> createValueSupplier(Map> valueMap) { Function> valueSupplier; if (valueMap != null) { - valueSupplier = freq -> Optional.ofNullable(valueMap.get(freq)).orElse(new ArrayList<>(0)); + valueSupplier = freq -> Optional.ofNullable(valueMap.get(freq)).orElseGet(() -> new ArrayList<>(0)); } else { valueSupplier = freq -> new ArrayList<>(0); } @@ -343,7 +438,7 @@ private Function> createCurvePointProducer(final Fr } private void plot(final FrequencyBand selectedFrequency, Function> valueSupplier, Function> dataPointSupplier, - Function> mouseClickedCallback, Function> curveProducer, Function mapFunc) { + BiFunction, T, EventHandler> mouseClickedCallback, Function> curveProducer, Function mapFunc) { if (selectedFrequency != null) { pointMap.clear(); modelData.clear(); @@ -360,21 +455,30 @@ private void plot(final FrequencyBand selectedFrequency, Function data = dataPointSupplier.apply(val); pointData.add(data); if (data.getXValue().doubleValue() > maxX.get()) { - maxX.set(data.getXValue().intValue()); + maxX.set(Integer.valueOf((int) (data.getXValue().doubleValue() * 1.1))); } if (data.getXValue().doubleValue() < minX.get()) { minX.set(data.getXValue().intValue()); } - if (data.getXValue().doubleValue() > maxY.get()) { + if (data.getYValue().doubleValue() > maxY.get()) { maxY.set(data.getYValue().doubleValue()); } if (data.getYValue().doubleValue() < minY.get()) { minY.set(data.getYValue().doubleValue()); } - data.getNode().addEventHandler(MouseEvent.MOUSE_CLICKED, mouseClickedCallback.apply(val)); - data.getNode().toBack(); + data.getNode().addEventHandler(MouseEvent.MOUSE_CLICKED, mouseClickedCallback.apply(data, val)); + data.extraValueProperty().addListener((obs, o, n) -> { + if (n instanceof Boolean && data != null && data.getNode() != null) { + if ((Boolean) n) { + data.getNode().setStyle(""); + } else { + data.getNode().setStyle("-fx-background-color: white, gray;"); + } + } + }); + data.setExtraValue(mapFunc.apply(val).isActive()); Waveform w = mapFunc.apply(val); boolean eventExists = w != null && w.getEvent() != null && w.getEvent().getEventId() != null; boolean stationExists = w != null && w.getStream() != null && w.getStream().getStation() != null && w.getStream().getStation().getStationName() != null; @@ -407,8 +511,10 @@ private void plot(final FrequencyBand selectedFrequency, Function data = curveProducer.apply(i); modelData.add(data); data.getNode().setMouseTransparent(true); + data.getNode().toFront(); } } + modelCurveSeries.getNode().toFront(); } } @@ -426,38 +532,39 @@ private Collection mapMeasurements(List waveforms) { }).collect(Collectors.toList()); } - private EventHandler showWaveformPopup(Waveform waveform) { - return event -> { - highlightedData.clear(); - List> selection = pointMap.get(waveform.getEvent().getEventId() + waveform.getStream().getStation().getStationName()); - if (selection != null && selection.size() == 1) { - highlightedData.add(new Data(selection.get(0).getXValue(), selection.get(0).getYValue())); - highlightedData.forEach(x -> x.getNode().setMouseTransparent(true)); - } - bus.post(new WaveformSelectionEvent(waveform.getId())); - }; + private void showWaveformPopup(Waveform waveform) { + highlightedData.clear(); + List> selection = pointMap.get(waveform.getEvent().getEventId() + waveform.getStream().getStation().getStationName()); + if (selection != null && selection.size() == 1) { + highlightedData.add(new Data(selection.get(0).getXValue(), selection.get(0).getYValue())); + highlightedData.forEach(x -> x.getNode().setMouseTransparent(true)); + } + bus.post(new WaveformSelectionEvent(waveform.getId())); } private void reloadData() { velocityDistancePairsFreqMap.clear(); shapeDistancePairsFreqMap.clear(); + waveformIdMapping.clear(); modelCurveMap.clear(); frequencyBandCombo.getItems().clear(); paramClient.getSharedFrequencyBandParameters().subscribe(sfb -> modelCurveMap.put(new FrequencyBand(sfb.getLowFrequency(), sfb.getHighFrequency()), sfb)); velocityDistancePairsFreqMap.putAll( - velocityClient.getMeasuredPeakVelocities() + velocityClient.getMeasuredPeakVelocitiesMetadata() .toStream() .filter(Objects::nonNull) .filter(pvm -> pvm.getWaveform() != null) + .peek(pvm -> waveformIdMapping.computeIfAbsent(pvm.getWaveform().getId(), k -> getMapping(k)).getLeft().add(pvm)) .collect(Collectors.groupingBy(pvm -> new FrequencyBand(pvm.getWaveform().getLowFrequency(), pvm.getWaveform().getHighFrequency())))); shapeDistancePairsFreqMap.putAll( - shapeClient.getMeasuredShapes() + shapeClient.getMeasuredShapesMetadata() .toStream() .filter(Objects::nonNull) .filter(shape -> shape.getWaveform() != null) + .peek(shape -> waveformIdMapping.computeIfAbsent(shape.getWaveform().getId(), k -> getMapping(k)).getRight().add(shape)) .collect(Collectors.groupingBy(shape -> new FrequencyBand(shape.getWaveform().getLowFrequency(), shape.getWaveform().getHighFrequency())))); frequencyBandCombo.getItems().addAll(modelCurveMap.keySet()); @@ -466,6 +573,10 @@ private void reloadData() { refreshView(); } + private Pair, List> getMapping(Long key) { + return new Pair, List>(new ArrayList(), new ArrayList()); + } + @Override public void refreshView() { mapImpl.clearIcons(); 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 e6c1ab1f..05096655 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) 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. @@ -14,14 +14,19 @@ */ 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.lang.reflect.InvocationTargetException; +import java.text.NumberFormat; import java.time.Duration; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; 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; @@ -33,6 +38,9 @@ import javax.swing.SwingUtilities; +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; @@ -42,15 +50,17 @@ 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.model.domain.MeasuredMwParameters; -import gov.llnl.gnem.apps.coda.calibration.model.domain.ReferenceMwParameters; +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.mapping.api.GeoMap; import gov.llnl.gnem.apps.coda.common.mapping.api.Icon; import gov.llnl.gnem.apps.coda.common.model.domain.Station; @@ -61,22 +71,62 @@ import javafx.collections.ObservableList; import javafx.embed.swing.SwingFXUtils; import javafx.embed.swing.SwingNode; +import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.scene.control.ComboBox; +import javafx.scene.control.ContextMenu; +import javafx.scene.control.MenuItem; import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn.CellDataFeatures; import javafx.scene.control.TableView; 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 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 { + 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 SwingNode mwPlotSwingNode; + private JMultiAxisPlot mwPlot; + private JSubplot mwPlotFigure; + private Line mwZeroLine; + + @FXML + private SwingNode stressPlotSwingNode; + private JMultiAxisPlot stressPlot; + private JSubplot stressPlotFigure; + private Line stressZeroLine; + + @FXML + private SwingNode sdPlotSwingNode; + private JMultiAxisPlot sdPlot; + private JSubplot sdPlotFigure; + @FXML private SwingNode rawPlotSwingNode; private SpectralPlot rawPlot; @@ -93,31 +143,28 @@ public class SiteController implements MapListeningController, RefreshableContro private ComboBox evidCombo; @FXML - private TableView refEventTable; - - @FXML - private TableView measuredEventTable; + private TableView eventTable; @FXML private TableView iconTable; @FXML - private TableColumn evidCol; + private TableColumn evidCol; @FXML - private TableColumn mwCol; + private TableColumn mwCol; @FXML - private TableColumn stressDropCol; + private TableColumn stressCol; @FXML - private TableColumn measuredEvidCol; + private TableColumn measuredMwCol; @FXML - private TableColumn measuredMwCol; + private TableColumn measuredStressCol; @FXML - private TableColumn measuredStressDropCol; + private TableColumn dataCountCol; @FXML private TableColumn iconCol; @@ -130,8 +177,9 @@ public class SiteController implements MapListeningController, RefreshableContro private ObservableList evids = FXCollections.observableArrayList(); private ReferenceEventClient referenceEventClient; - private ObservableList referenceMwParameters = FXCollections.observableArrayList(); - private ObservableList measuredMwParameters = FXCollections.observableArrayList(); + private ObservableList mwParameters = FXCollections.observableArrayList(); + + private WaveformClient waveformClient; private ObservableList stationSymbols = FXCollections.observableArrayList(); private final BiConsumer eventSelectionCallback; @@ -154,21 +202,31 @@ public class SiteController implements MapListeningController, RefreshableContro private MapPlottingUtilities iconFactory; + private MenuItem exclude; + private MenuItem include; + private ContextMenu menu; + + private final NumberFormat dfmt4 = NumberFormatFactory.fourDecimalOneLeadingZero(); + + private ColorMap colorMap = new ViridisColorMap(); + @Autowired - private SiteController(SpectraClient spectraClient, ReferenceEventClient referenceEventClient, SymbolStyleMapFactory styleFactory, GeoMap map, MapPlottingUtilities iconFactory, EventBus bus) { + private SiteController(SpectraClient spectraClient, ReferenceEventClient referenceEventClient, WaveformClient waveformClient, SymbolStyleMapFactory styleFactory, GeoMap map, + MapPlottingUtilities iconFactory, EventBus bus) { this.spectraClient = spectraClient; this.referenceEventClient = referenceEventClient; + this.waveformClient = waveformClient; this.symbolStyleMapFactory = styleFactory; this.mapImpl = map; this.bus = bus; this.iconFactory = iconFactory; eventSelectionCallback = (selected, eventId) -> { - selectDataByCriteria(bus, selected, eventId); + selectDataByCriteria(selected, eventId); }; stationSelectionCallback = (selected, stationId) -> { - selectDataByCriteria(bus, selected, stationId); + selectDataByCriteria(selected, stationId); }; } @@ -177,42 +235,21 @@ public void initialize() { evidCombo.setItems(evids); SwingUtilities.invokeLater(() -> { + rawPlot = new SpectralPlot(); rawPlot.addPlotObjectObserver(new Observer() { - @Override public void update(Observable observable, Object obj) { - if (obj instanceof PlotObjectClicked && ((PlotObjectClicked) obj).getMouseEvent().getID() == MouseEvent.MOUSE_RELEASED) { - PlotObjectClicked poc = (PlotObjectClicked) obj; - PlotObject po = poc.getPlotObject(); - if (po != null && po instanceof Symbol) { - selectPoints(plotPointMap.get(((Symbol) po).getText())); - SpectraMeasurement spectra = rawSymbolMap.get(new Point2D.Double(((Symbol) po).getXcenter(), ((Symbol) po).getYcenter())); - if (spectra != null) { - showWaveformPopup(spectra.getWaveform()); - } - } - } + 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) { - if (obj instanceof PlotObjectClicked && ((PlotObjectClicked) obj).getMouseEvent().getID() == MouseEvent.MOUSE_RELEASED) { - PlotObjectClicked poc = (PlotObjectClicked) obj; - PlotObject po = poc.getPlotObject(); - if (po != null && po instanceof Symbol) { - selectPoints(plotPointMap.get(((Symbol) po).getText())); - SpectraMeasurement spectra = pathSymbolMap.get(new Point2D.Double(((Symbol) po).getXcenter(), ((Symbol) po).getYcenter())); - if (spectra != null) { - showWaveformPopup(spectra.getWaveform()); - } - } - } + handlePlotObjectClicked(obj, sym -> pathSymbolMap.get(getPoint2D(sym))); } }); @@ -220,20 +257,9 @@ public void update(Observable observable, Object obj) { sitePlot = new SpectralPlot(); sitePlot.addPlotObjectObserver(new Observer() { - @Override public void update(Observable observable, Object obj) { - if (obj instanceof PlotObjectClicked && ((PlotObjectClicked) obj).getMouseEvent().getID() == MouseEvent.MOUSE_RELEASED) { - PlotObjectClicked poc = (PlotObjectClicked) obj; - PlotObject po = poc.getPlotObject(); - if (po != null && po instanceof Symbol) { - selectPoints(plotPointMap.get(((Symbol) po).getText())); - SpectraMeasurement spectra = siteSymbolMap.get(new Point2D.Double(((Symbol) po).getXcenter(), ((Symbol) po).getYcenter())); - if (spectra != null) { - showWaveformPopup(spectra.getWaveform()); - } - } - } + handlePlotObjectClicked(obj, sym -> siteSymbolMap.get(getPoint2D(sym))); } }); sitePlotSwingNode.setContent(sitePlot); @@ -252,6 +278,53 @@ public void update(Observable observable, Object obj) { sitePlot.setLabels("Site Corrected", X_AXIS_LABEL, "log10(amplitude)"); 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(2d * 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(2d * 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(2d * 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) -> { @@ -260,23 +333,16 @@ public void update(Observable observable, Object obj) { } }); - evidCol.setCellValueFactory(x -> Bindings.createStringBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(ReferenceMwParameters::getEventId).orElseGet(String::new))); + CellBindingUtils.attachTextCellFactoriesString(evidCol, MeasuredMwDetails::getEventId); evidCol.comparatorProperty().set(new MaybeNumericStringComparator()); - mwCol.setCellValueFactory(x -> Bindings.createDoubleBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(ReferenceMwParameters::getRefMw).orElseGet(() -> 0.0)).asObject()); - - stressDropCol.setCellValueFactory( - x -> Bindings.createDoubleBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(ReferenceMwParameters::getStressDropInMpa).orElseGet(() -> 0.0)).asObject()); + CellBindingUtils.attachTextCellFactories(mwCol, MeasuredMwDetails::getRefMw, dfmt4); + CellBindingUtils.attachTextCellFactories(stressCol, MeasuredMwDetails::getRefApparentStressInMpa, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredMwCol, MeasuredMwDetails::getMw, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredStressCol, MeasuredMwDetails::getApparentStressInMpa, dfmt4); - measuredEvidCol.setCellValueFactory( - x -> Bindings.createStringBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(MeasuredMwParameters::getEventId).orElseGet(String::new))); - measuredEvidCol.comparatorProperty().set(new MaybeNumericStringComparator()); - - measuredMwCol.setCellValueFactory( - x -> Bindings.createDoubleBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(MeasuredMwParameters::getMw).orElseGet(() -> 0.0)).asObject()); - - measuredStressDropCol.setCellValueFactory( - x -> Bindings.createDoubleBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(MeasuredMwParameters::getStressDropInMpa).orElseGet(() -> 0.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( @@ -289,12 +355,30 @@ public void update(Observable observable, Object obj) { stationCol.setCellValueFactory(x -> Bindings.createStringBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(LabeledPlotPoint::getLabel).orElseGet(String::new))); - refEventTable.setItems(referenceMwParameters); - measuredEventTable.setItems(measuredMwParameters); + 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) { @@ -365,23 +449,40 @@ private Map mapSpectraToPoint(List toPlotPoints(List spectralMeasurements, Function func) { - List list = spectralMeasurements.stream().filter(spectra -> !func.apply(spectra).equals(0.0)).map(spectra -> { - String key = spectra.getWaveform().getStream().getStation().getStationName(); - PlotPoint pp = symbolStyleMap.get(key); - 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()); + 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 @@ -399,33 +500,198 @@ private double centerFreq(Double lowFrequency, Double highFrequency) { private void reloadData() { clearSpectraPlots(); - referenceMwParameters.clear(); - measuredMwParameters.clear(); - referenceEventClient.getReferenceEvents().filter(ref -> ref.getId() != null).subscribe(ref -> referenceMwParameters.add(ref)); - referenceEventClient.getMeasuredEvents().filter(meas -> meas.getId() != null).subscribe(meas -> measuredMwParameters.add(meas)); + 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)); + + 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 < minStress) { + minStress = stress; + } + if (stress > maxStress) { + maxStress = stress; + } + if (refStress < minStress) { + minStress = refStress; + } + if (refStress > maxStress) { + maxStress = refStress; + } + + Circle mwSym = new Circle(mw, ref, 2.0, Color.RED, Color.RED, Color.RED, ev.getEventId(), true, false, 6.0); + mwPlotFigure.AddPlotObject(mwSym); - spectralMeasurements.clear(); - stationSymbols.clear(); + 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); + }); + + 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; - evids.clear(); - evids.add("All"); + sdPlotFigure.setAxisLimits(minFreq, maxFreq, minSite, maxSite); + sdPlotFigure.AddPlotObject(createColorLegend(minStations, maxStations)); + }); - spectralMeasurements.addAll( - spectraClient.getMeasuredSpectra() - .filter(Objects::nonNull) - .filter(spectra -> spectra.getWaveform() != null && spectra.getWaveform().getEvent() != null && spectra.getWaveform().getStream() != null) - .toStream() - .collect(Collectors.toList())); + 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(); + } + } - symbolStyleMap = symbolStyleMapFactory.build(spectralMeasurements, new Function() { - @Override - public String apply(SpectraMeasurement t) { - return t.getWaveform().getStream().getStation().getStationName(); + 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)); } - }); - stationSymbols.addAll(symbolStyleMap.entrySet().stream().map(e -> new LabeledPlotPoint(e.getKey(), e.getValue())).collect(Collectors.toList())); + } + 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); + } - evids.addAll(spectralMeasurements.stream().map(spec -> spec.getWaveform().getEvent().getEventId()).distinct().sorted(new MaybeNumericStringComparator()).collect(Collectors.toList())); + private Double centerFreq(Waveform waveform) { + return ((waveform.getHighFrequency() - waveform.getLowFrequency()) / 2.0) + waveform.getLowFrequency(); } @Override @@ -444,7 +710,7 @@ public Runnable getRefreshFunction() { return () -> reloadData(); } - private void selectDataByCriteria(EventBus bus, Boolean selected, String key) { + private void selectDataByCriteria(Boolean selected, String key) { List points = plotPointMap.get(key); if (selected) { selectPoints(points); @@ -515,4 +781,58 @@ private void deselectPoint(PlotPoint point) { 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) { + waveformClient.setWaveformsActiveByIds(waveforms.stream().map(w -> w.getId()).collect(Collectors.toList()), active).subscribe(s -> activationFunc.accept(plotObjects, active)); + } + + 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); + }); + } + } + } + } + } } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/parameters/ParametersController.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/parameters/ParametersController.java index a22d2a67..cadc4901 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/parameters/ParametersController.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/parameters/ParametersController.java @@ -22,6 +22,7 @@ import gov.llnl.gnem.apps.coda.calibration.gui.controllers.RefreshableController; import gov.llnl.gnem.apps.coda.calibration.gui.events.ParametersLoadedEvent; +import gov.llnl.gnem.apps.coda.calibration.model.messaging.GvDataChangeEvent; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.layout.StackPane; @@ -40,15 +41,23 @@ public class ParametersController implements RefreshableController { @FXML private SiteBandController siteBandController; + + @FXML + private VelocityConfigurationController velocityConfigController; private EventBus bus; @Autowired public ParametersController(EventBus bus) { this.bus = bus; - bus.register(this); + this.bus.register(this); } + @Subscribe + private void listener(GvDataChangeEvent event) { + velocityConfigController.requestData(); + } + @Subscribe private void listener(ParametersLoadedEvent event) { reloadData(); @@ -63,6 +72,7 @@ private void reloadData() { sharedBandController.requestData(); modelController.requestData(); siteBandController.requestData(); + velocityConfigController.requestData(); } @Override diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/parameters/SharedBandController.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/parameters/SharedBandController.java index 8c2ac03f..ed4d9bb8 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/parameters/SharedBandController.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/parameters/SharedBandController.java @@ -186,7 +186,7 @@ private void clearTable() { @FXML private void removeBands() { - List sfb = new ArrayList<>(); + List sfb = new ArrayList<>(codaSharedTableView.getSelectionModel().getSelectedIndices().size()); codaSharedTableView.getSelectionModel().getSelectedIndices().forEach(i -> sfb.add(sharedFbData.get(i))); if (!sfb.isEmpty()) { sfb.forEach(x -> client.removeSharedFrequencyBandParameter(x).subscribe()); diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/parameters/SiteBandController.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/parameters/SiteBandController.java index e04d02c0..eb39fbdb 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/parameters/SiteBandController.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/parameters/SiteBandController.java @@ -25,7 +25,7 @@ import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ParameterClient; import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteFrequencyBandParameters; -import gov.llnl.gnem.apps.coda.common.gui.util.MaybeNumericStringComparator; +import gov.llnl.gnem.apps.coda.common.gui.util.CellBindingUtils; import gov.llnl.gnem.apps.coda.common.gui.util.NumberFormatFactory; import gov.llnl.gnem.apps.coda.common.model.domain.Station; import javafx.beans.binding.Bindings; @@ -86,30 +86,9 @@ public void initialize() { .filter(Objects::nonNull) .orElseGet(String::new))); - siteLowFreqCol.setCellValueFactory( - x -> Bindings.createStringBinding( - () -> Optional.ofNullable(x) - .map(CellDataFeatures::getValue) - .map(SiteFrequencyBandParameters::getLowFrequency) - .filter(Objects::nonNull) - .map(dfmt2::format) - .orElseGet(String::new))); - siteLowFreqCol.comparatorProperty().set(new MaybeNumericStringComparator()); - - siteHighFreqCol.setCellValueFactory( - x -> Bindings.createStringBinding( - () -> Optional.ofNullable(x) - .map(CellDataFeatures::getValue) - .map(SiteFrequencyBandParameters::getHighFrequency) - .filter(Objects::nonNull) - .map(dfmt2::format) - .orElseGet(String::new))); - siteHighFreqCol.comparatorProperty().set(new MaybeNumericStringComparator()); - - siteCorrectionCol.setCellValueFactory( - x -> Bindings.createStringBinding( - () -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(SiteFrequencyBandParameters::getSiteTerm).filter(Objects::nonNull).map(dfmt2::format).orElseGet(String::new))); - + CellBindingUtils.attachTextCellFactories(siteLowFreqCol, SiteFrequencyBandParameters::getLowFrequency, dfmt2); + CellBindingUtils.attachTextCellFactories(siteHighFreqCol, SiteFrequencyBandParameters::getHighFrequency, dfmt2); + CellBindingUtils.attachTextCellFactories(siteCorrectionCol, SiteFrequencyBandParameters::getSiteTerm, dfmt2); codaSiteTableView.setItems(siteFbData); } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/parameters/VelocityConfigurationController.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/parameters/VelocityConfigurationController.java new file mode 100644 index 00000000..40879bb0 --- /dev/null +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/parameters/VelocityConfigurationController.java @@ -0,0 +1,105 @@ +/* +* 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. +* +* 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.parameters; + +import java.text.NumberFormat; +import java.util.Objects; +import java.util.Optional; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ParameterClient; +import gov.llnl.gnem.apps.coda.calibration.model.domain.VelocityConfiguration; +import gov.llnl.gnem.apps.coda.common.gui.util.CellBindingUtils; +import gov.llnl.gnem.apps.coda.common.gui.util.NumberFormatFactory; +import javafx.application.Platform; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; + +@Component +public class VelocityConfigurationController { + + private static final Logger log = LoggerFactory.getLogger(VelocityConfigurationController.class); + + private final NumberFormat dfmt2 = NumberFormatFactory.twoDecimalOneLeadingZero(); + + @FXML + private TableView velocityConfTableView; + + @FXML + TableColumn distanceThresholdCol; + + @FXML + TableColumn gt1Col; + + @FXML + TableColumn gt2Col; + + @FXML + TableColumn lt1Col; + + @FXML + TableColumn lt2Col; + + @FXML + TableColumn phaseSpeedCol; + + private ObservableList velData = FXCollections.observableArrayList(); + + private ParameterClient client; + + @Autowired + public VelocityConfigurationController(ParameterClient client) { + this.client = client; + } + + @FXML + private void reloadData(ActionEvent e) { + requestData(); + } + + @FXML + public void initialize() { + CellBindingUtils.attachTextCellFactories(distanceThresholdCol, VelocityConfiguration::getDistanceThresholdInKm, dfmt2); + CellBindingUtils.attachTextCellFactories(gt1Col, VelocityConfiguration::getGroupVelocity1InKmsGtDistance, dfmt2); + CellBindingUtils.attachTextCellFactories(gt2Col, VelocityConfiguration::getGroupVelocity2InKmsGtDistance, dfmt2); + CellBindingUtils.attachTextCellFactories(lt1Col, VelocityConfiguration::getGroupVelocity1InKmsLtDistance, dfmt2); + CellBindingUtils.attachTextCellFactories(lt2Col, VelocityConfiguration::getGroupVelocity2InKmsLtDistance, dfmt2); + CellBindingUtils.attachTextCellFactories(phaseSpeedCol, VelocityConfiguration::getPhaseSpeedInKms, dfmt2); + velocityConfTableView.setItems(velData); + requestData(); + } + + + protected void requestData() { + velData.clear(); + client.getVelocityConfiguration() + .filter(Objects::nonNull) + .filter(value -> null != value.getId()) + .doOnTerminate(() -> velocityConfTableView.sort()) + .subscribe(value -> velData.add(value), err -> log.trace(err.getMessage(), err)); + + Platform.runLater(() -> { + Optional.ofNullable(velocityConfTableView).ifPresent(v -> v.refresh()); + }); + } +} 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 29b85f50..a998f116 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 @@ -22,6 +22,7 @@ import static gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.CalibrationJsonConstants.SCHEMA_VALUE; 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.VELOCITY_CONFIGURATION; import java.io.File; import java.io.IOException; @@ -43,6 +44,7 @@ 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.VelocityConfiguration; import gov.llnl.gnem.apps.coda.calibration.model.domain.mixins.SharedFrequencyBandParametersFileMixin; import gov.llnl.gnem.apps.coda.common.model.domain.SharedFrequencyBandParameters; import gov.llnl.gnem.apps.coda.common.model.messaging.Result; @@ -91,6 +93,7 @@ public List> convertJsonParamFile(File file) { 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, VELOCITY_CONFIGURATION, x -> velocityConfigurationFromJsonNode(x))); } } catch (IOException e) { return Collections.singletonList(exceptionalResult(new LightweightIllegalStateException(String.format("Error parsing (%s): %s", file.getName(), e.getMessage()), e))); @@ -114,6 +117,17 @@ protected List> convertJsonFields(JsonNode node, String field, Fu return results; } + protected Result velocityConfigurationFromJsonNode(JsonNode node) { + ObjectReader reader = mapper.readerFor(VelocityConfiguration.class); + try { + //TODO: Validate all fields + VelocityConfiguration val = reader.readValue(node); + return new Result(true, val); + } catch (IOException e) { + return exceptionalResult(e); + } + } + protected Result refEventsFromJsonNode(JsonNode node) { ObjectReader reader = mapper.readerFor(ReferenceMwParameters.class); try { @@ -150,7 +164,7 @@ protected Result mdacFiFromJsonNode(JsonNode node) { protected Result sharedFrequenyBandFromJsonNode(JsonNode band) { SharedFrequencyBandParameters sfb = new SharedFrequencyBandParameters(); if (band.get("lowFreqHz").isNull() || band.get("highFreqHz").isNull()) { - return exceptionalResult(new LightweightIllegalStateException("Unable to parse frequency band " + sfb.toString() + "; received a empty frequency band.")); + return exceptionalResult(new LightweightIllegalStateException("Unable to parse frequency band " + sfb + "; received a empty frequency band.")); } else { try { ObjectReader reader = mapper.readerFor(SharedFrequencyBandParameters.class); diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/ReferenceEventLoader.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/ReferenceEventLoader.java index ac796362..3a3a9cbf 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/ReferenceEventLoader.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/ReferenceEventLoader.java @@ -53,14 +53,14 @@ public Flux> convertFiles(List files) { public List> convertFileToReferenceMwParameters(File file) { - ArrayList> results = new ArrayList<>(); + List> results = new ArrayList<>(); if (file == null || !file.exists() || file.isDirectory()) { return exceptionalResult(new LightweightIllegalStateException(String.format("Error parsing (%s): file does not exist or is unreadable.", "NULL"))); } if (!file.getName().toUpperCase(Locale.ENGLISH).endsWith(".TXT") && !file.getName().toUpperCase(Locale.ENGLISH).endsWith(".DAT")) { - return exceptionalResult(new LightweightIllegalStateException(String.format("Error parsing (%s): file is not of a recognized format. The accepted file formats are .txt and .dat.", - file.getName()))); + return exceptionalResult( + new LightweightIllegalStateException(String.format("Error parsing (%s): file is not of a recognized format. The accepted file formats are .txt and .dat.", file.getName()))); } Pattern pattern = Pattern.compile("\\s+"); @@ -78,9 +78,9 @@ private Result extractReferenceEvent(String[] tokens) { ReferenceMwParameters refEvent = new ReferenceMwParameters(); try { if (tokens.length >= 2) { - refEvent.setEventId(tokens[0]).setRefMw(Double.valueOf(tokens[1])); + refEvent.setEventId(tokens[0]).setRefMw(Double.parseDouble(tokens[1])); if (tokens.length == 3 && tokens[2].matches("^[-+]?\\d+(\\.\\d+)?$")) { - refEvent.setStressDropInMpa(Double.valueOf(tokens[2])); + refEvent.setRefApparentStressInMpa(Double.valueOf(tokens[2])); } result.setSuccess(true).setResultPayload(Optional.of(refEvent)); } else { @@ -93,10 +93,8 @@ private Result extractReferenceEvent(String[] tokens) { } private List> exceptionalResult(Exception error) { - ArrayList> results = new ArrayList<>(); - List exceptions = new ArrayList<>(); - exceptions.add(error); - results.add(new Result(false, exceptions, null)); + List> results = new ArrayList<>(); + results.add(new Result(false, Collections.singletonList(error), null)); return results; } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/ParameterWebClient.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/ParameterWebClient.java index 90b3f5ad..44febe9e 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/ParameterWebClient.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/ParameterWebClient.java @@ -14,8 +14,6 @@ */ package gov.llnl.gnem.apps.coda.calibration.gui.data.client; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; @@ -27,6 +25,7 @@ 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.SiteFrequencyBandParameters; +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; import reactor.core.publisher.Flux; @@ -36,7 +35,6 @@ public class ParameterWebClient implements ParameterClient { private WebClient client; - private static final Logger log = LoggerFactory.getLogger(ParameterWebClient.class); @Autowired public ParameterWebClient(WebClient client) { @@ -161,4 +159,19 @@ public Mono getSharedFrequencyBandParametersForFr .flatMap(response -> response.bodyToMono(SharedFrequencyBandParameters.class)); } + @Override + public Mono getVelocityConfiguration() { + return client.get() + .uri("/config/velocity/") + .accept(MediaType.APPLICATION_JSON) + .exchange() + .flatMap(response -> response.bodyToMono(VelocityConfiguration.class)) + .onErrorReturn(new VelocityConfiguration()); + } + + @Override + public Mono updateVelocityConfiguration(VelocityConfiguration velConf) { + return client.post().uri("/config/velocity/update").accept(MediaType.APPLICATION_JSON).syncBody(velConf).exchange().flatMap(response -> response.bodyToMono(String.class)).onErrorReturn(""); + } + } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/PeakVelocityWebClient.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/PeakVelocityWebClient.java index ea2b0e37..4cd57aec 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/PeakVelocityWebClient.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/PeakVelocityWebClient.java @@ -41,7 +41,7 @@ public PeakVelocityWebClient(WebClient client) { @Override public Flux getMeasuredPeakVelocities() { return client.get() - .uri("/peak-velocity-measurements") + .uri("/peak-velocity-measurements/all") .accept(MediaType.APPLICATION_JSON) .exchange() .flatMapMany(response -> response.bodyToFlux(PeakVelocityMeasurement.class)) @@ -51,7 +51,7 @@ public Flux getMeasuredPeakVelocities() { @Override public Flux getMeasuredPeakVelocitiesMetadata() { return client.get() - .uri("/peak-velocity-measurements/metadata") + .uri("/peak-velocity-measurements/metadata/all") .accept(MediaType.APPLICATION_JSON) .exchange() .flatMapMany(response -> response.bodyToFlux(PeakVelocityMeasurement.class)) @@ -61,7 +61,7 @@ public Flux getMeasuredPeakVelocitiesMetadata() { @Override public Mono getNoiseForWaveform(Long id) { return client.get() - .uri("/peak-velocity-measurements/metadata-by-id/" + id) + .uri("/peak-velocity-measurements/metadata/by-id/" + id) .accept(MediaType.APPLICATION_JSON) .exchange() .flatMap(response -> response.bodyToMono(PeakVelocityMeasurement.class)) 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/ReferenceEventWebClient.java index 1c5d5db6..67012e8f 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/ReferenceEventWebClient.java @@ -24,6 +24,7 @@ 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.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.common.model.domain.Event; @@ -76,4 +77,14 @@ public Mono getEvent(String eventId) { return client.get().uri("/events/" + eventId).accept(MediaType.APPLICATION_JSON).exchange().flatMap(response -> response.bodyToMono(Event.class)).onErrorReturn(new Event()); } + @Override + public Flux getMeasuredEventDetails() { + return client.get() + .uri("/measured-mws/details") + .accept(MediaType.APPLICATION_JSON) + .exchange() + .flatMapMany(response -> response.bodyToFlux(MeasuredMwDetails.class)) + .onErrorReturn(new MeasuredMwDetails()); + } + } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/ShapeMeasurementWebClient.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/ShapeMeasurementWebClient.java index f14a9c6a..bdcc75be 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/ShapeMeasurementWebClient.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/ShapeMeasurementWebClient.java @@ -53,4 +53,24 @@ public Mono getMeasuredShape(Long id) { .flatMap(response -> response.bodyToMono(ShapeMeasurement.class)) .onErrorReturn(new ShapeMeasurement()); } + + @Override + public Flux getMeasuredShapesMetadata() { + return client.get() + .uri("/shape-measurements/metadata/all/") + .accept(MediaType.APPLICATION_JSON) + .exchange() + .flatMapMany(response -> response.bodyToFlux(ShapeMeasurement.class)) + .onErrorReturn(new ShapeMeasurement()); + } + + @Override + public Mono getMeasuredShapeMetadata(Long id) { + return client.get() + .uri("/shape-measurements/metadata/byWaveformId/" + id) + .accept(MediaType.APPLICATION_JSON) + .exchange() + .flatMap(response -> response.bodyToMono(ShapeMeasurement.class)) + .onErrorReturn(new ShapeMeasurement()); + } } 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 86b6ec47..7c0ba84e 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 @@ -38,13 +38,24 @@ public SpectraWebClient(WebClient client) { @Override public Flux getMeasuredSpectra() { return client.get() - .uri("/spectra-measurements") + .uri("/spectra-measurements/all") .accept(MediaType.APPLICATION_JSON) .exchange() .flatMapMany(response -> response.bodyToFlux(SpectraMeasurement.class)) .onErrorReturn(new SpectraMeasurement()); } + + @Override + public Flux getMeasuredSpectraMetadata() { + return client.get() + .uri("/spectra-measurements/metadata/all") + .accept(MediaType.APPLICATION_JSON) + .exchange() + .flatMapMany(response -> response.bodyToFlux(SpectraMeasurement.class)) + .onErrorReturn(new SpectraMeasurement()); + } + @Override public Mono getReferenceSpectra(String eventId) { return client.post() 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 efd762fe..16aa5017 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 @@ -24,4 +24,5 @@ public class CalibrationJsonConstants { public static final String MDAC_FI_FIELD = "mdac-fi"; public static final String REFERENCE_EVENTS_FIELD = "reference-events"; public static final String MEASURED_EVENTS_FIELD = "measured-events"; + public static final String VELOCITY_CONFIGURATION = "velocity-configuration"; } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/ParameterClient.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/ParameterClient.java index 71cfa2cb..d0f77820 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/ParameterClient.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/ParameterClient.java @@ -19,6 +19,7 @@ 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.SiteFrequencyBandParameters; +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; import reactor.core.publisher.Flux; @@ -50,4 +51,8 @@ public interface ParameterClient { public Mono removeFiParameter(MdacParametersFI parameters); + public Mono getVelocityConfiguration(); + + public Mono updateVelocityConfiguration(VelocityConfiguration velConf); + } 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/ReferenceEventClient.java index 35a57674..00063be0 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/ReferenceEventClient.java @@ -18,6 +18,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; +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.common.model.domain.Event; @@ -33,4 +34,6 @@ public interface ReferenceEventClient { public Mono postReferenceEvents(List refEvents) throws JsonProcessingException; public Mono getEvent(String eventId); + + public Flux getMeasuredEventDetails(); } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/ShapeMeasurementClient.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/ShapeMeasurementClient.java index 06de71b0..a5f6a1e8 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/ShapeMeasurementClient.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/ShapeMeasurementClient.java @@ -23,4 +23,8 @@ public interface ShapeMeasurementClient { public Flux getMeasuredShapes(); public Mono getMeasuredShape(Long id); + + public Flux getMeasuredShapesMetadata(); + + public Mono getMeasuredShapeMetadata(Long id); } 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 3dbb7484..f1a0999d 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 @@ -22,6 +22,8 @@ public interface SpectraClient { public Flux getMeasuredSpectra(); + + public Flux getMeasuredSpectraMetadata(); public Mono getReferenceSpectra(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 185b0fc3..91d9cd3c 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 @@ -19,8 +19,10 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,15 +38,19 @@ 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.model.domain.MeasuredMwDetails; +import gov.llnl.gnem.apps.coda.calibration.model.domain.ReferenceMwParameters; import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteFrequencyBandParameters; +import gov.llnl.gnem.apps.coda.calibration.model.domain.VelocityConfiguration; +import gov.llnl.gnem.apps.coda.calibration.model.domain.mixins.ReferenceMwParametersFileMixin; import gov.llnl.gnem.apps.coda.calibration.model.domain.mixins.SharedFrequencyBandParametersFileMixin; 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 { +public class JsonTempFileWriter implements ParamTempFileWriter, MeasuredMwTempFileWriter, ReferenceMwTempFileWriter { private static final Logger log = LoggerFactory.getLogger(JsonTempFileWriter.class); @@ -58,20 +64,34 @@ public JsonTempFileWriter() { mapper.setSerializationInclusion(Include.NON_NULL); mapper.setSerializationInclusion(Include.NON_EMPTY); mapper.addMixIn(SharedFrequencyBandParameters.class, SharedFrequencyBandParametersFileMixin.class); + mapper.addMixIn(ReferenceMwParameters.class, ReferenceMwParametersFileMixin.class); + mapper.addMixIn(VelocityConfiguration.class, VelocityConfigurationFileMixin.class); } @Override - public void writeParams(Path folder, Map sharedParametersByFreqBand, Map> siteParameters) { + public void writeParams(Path folder, Map sharedParametersByFreqBand, Map> siteParameters, + VelocityConfiguration velocityConfig) { try { JsonNode document = createOrGetDocument(folder, CALIBRATION_JSON_NAME); - writeParams(createOrGetFile(folder, CALIBRATION_JSON_NAME), document, sharedParametersByFreqBand, siteParameters); + writeParams(createOrGetFile(folder, CALIBRATION_JSON_NAME), document, sharedParametersByFreqBand, siteParameters, velocityConfig); } catch (IOException e) { log.error(e.getMessage(), e); } } @Override - public void writeParams(Path folder, List measuredMwsDetails) { + public void writeReferenceMwParams(Path folder, List mws) { + try { + JsonNode document = createOrGetDocument(folder, CALIBRATION_JSON_NAME); + List refMws = mws.stream().filter(mw -> mw.getRefMw() != 0.0).collect(Collectors.toList()); + writeReferenceEvents(createOrGetFile(folder, CALIBRATION_JSON_NAME), document, refMws); + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } + + @Override + public void writeMeasuredMws(Path folder, List measuredMwsDetails) { try { JsonNode document = createOrGetDocument(folder, MW_JSON_NAME); writeMeasuredEvents(createOrGetFile(folder, MW_JSON_NAME), document, measuredMwsDetails); @@ -81,33 +101,30 @@ public void writeParams(Path folder, List measuredMwsDetails) } private void writeParams(File file, JsonNode document, Map sharedParametersByFreqBand, - Map> siteParameters) throws IOException { - ArrayNode arrayNode = mapper.createArrayNode(); - for (SharedFrequencyBandParameters sfb : sharedParametersByFreqBand.values()) { - //TODO: Validation logic - //if sfb is valid - arrayNode.add(mapper.valueToTree(sfb)); - //else log error - } - writeFieldNodeToFile(file, document, CalibrationJsonConstants.SCHEMA_FIELD, mapper.valueToTree(CalibrationJsonConstants.SCHEMA_VALUE)); - writeFieldNodeToFile(file, document, CalibrationJsonConstants.TYPE_FIELD, mapper.valueToTree(CalibrationJsonConstants.TYPE_VALUE)); - if (arrayNode.size() > 0) { - writeFieldNodeToFile(file, document, CalibrationJsonConstants.BAND_FIELD, arrayNode); + Map> siteParameters, VelocityConfiguration velocityConfig) throws IOException { + writeArrayNodeToFile(file, document, sharedParametersByFreqBand.values(), CalibrationJsonConstants.BAND_FIELD); + if (velocityConfig != null) { + writeFieldNodeToFile(file, document, CalibrationJsonConstants.VELOCITY_CONFIGURATION, mapper.valueToTree(velocityConfig)); } } + private void writeReferenceEvents(File file, JsonNode document, List referenceMwsDetails) throws IOException { + writeArrayNodeToFile(file, document, referenceMwsDetails, CalibrationJsonConstants.REFERENCE_EVENTS_FIELD); + } + private void writeMeasuredEvents(File file, JsonNode document, List measuredMwsDetails) throws IOException { + writeArrayNodeToFile(file, document, measuredMwsDetails, CalibrationJsonConstants.MEASURED_EVENTS_FIELD); + } + + private void writeArrayNodeToFile(File file, JsonNode document, Collection values, String field) throws IllegalArgumentException, IOException { ArrayNode arrayNode = mapper.createArrayNode(); - for (MeasuredMwDetails mw : measuredMwsDetails) { - //TODO: Validation logic - //if mw is valid - arrayNode.add(mapper.valueToTree(mw)); - //else log error + for (T value : values) { + arrayNode.add(mapper.valueToTree(value)); } writeFieldNodeToFile(file, document, CalibrationJsonConstants.SCHEMA_FIELD, mapper.valueToTree(CalibrationJsonConstants.SCHEMA_VALUE)); writeFieldNodeToFile(file, document, CalibrationJsonConstants.TYPE_FIELD, mapper.valueToTree(CalibrationJsonConstants.TYPE_VALUE)); if (arrayNode.size() > 0) { - writeFieldNodeToFile(file, document, CalibrationJsonConstants.MEASURED_EVENTS_FIELD, arrayNode); + writeFieldNodeToFile(file, document, field, arrayNode); } } @@ -122,7 +139,7 @@ private void writeFieldNodeToFile(File file, JsonNode document, String field, Js } private JsonNode addOrReplaceNode(JsonNode document, String field, JsonNode node) { - if (document != null && document instanceof ObjectNode) { + if (document instanceof ObjectNode) { if (node != null) { document = deleteNodesIfExists(document, field); ((ObjectNode) document).set(field, node); @@ -155,6 +172,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.deleteOnExit(); 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 a9cbc687..3661f890 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 @@ -15,11 +15,10 @@ package gov.llnl.gnem.apps.coda.calibration.gui.data.exporters; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.time.Duration; import java.util.ArrayList; import java.util.Comparator; import java.util.List; @@ -44,12 +43,15 @@ 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.model.domain.MeasuredMwDetails; +import gov.llnl.gnem.apps.coda.calibration.model.domain.ReferenceMwParameters; import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteFrequencyBandParameters; -import gov.llnl.gnem.apps.coda.common.model.domain.Event; +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; import gov.llnl.gnem.apps.coda.common.model.domain.Station; +import reactor.core.scheduler.Schedulers; @Component public class ParamExporter { @@ -60,14 +62,17 @@ public class ParamExporter { private ReferenceEventClient eventClient; private List mwWriters; + private List referenceMwWriters; @Autowired - public ParamExporter(ParameterClient paramClient, ReferenceEventClient eventClient, List paramWriters, List mwWriters) { + public ParamExporter(ParameterClient paramClient, ReferenceEventClient eventClient, List paramWriters, List mwWriters, + List referenceMwWriters) { this.paramClient = paramClient; this.paramWriters = paramWriters; this.eventClient = eventClient; this.mwWriters = mwWriters; + this.referenceMwWriters = referenceMwWriters; } public File createExportArchive() throws IOException { @@ -98,24 +103,28 @@ public File createExportArchive() throws IOException { (a, b) -> b, TreeMap::new))); + VelocityConfiguration velocity = paramClient.getVelocityConfiguration().subscribeOn(Schedulers.elastic()).block(Duration.ofSeconds(5l)); + for (ParamTempFileWriter writer : paramWriters) { - writer.writeParams(tmpFolder, sharedParametersByFreqBand, siteParameters); + writer.writeParams(tmpFolder, sharedParametersByFreqBand, siteParameters, velocity); } } if (mwWriters != null) { - List measuredMwsDetails = new ArrayList<>(); //Get corresponding Event details - eventClient.getMeasuredEvents().filter(Objects::nonNull).filter(mw -> mw.getEventId() != null && !mw.getEventId().trim().isEmpty()).subscribe(mw -> { - Event event = eventClient.getEvent(mw.getEventId()).block(); - MeasuredMwDetails details = new MeasuredMwDetails(mw, event); - if (details.isValid()) { - measuredMwsDetails.add(details); - } - }); + measuredMwsDetails.addAll(eventClient.getMeasuredEventDetails().filter(Objects::nonNull).filter(MeasuredMwDetails::isValid).toStream().collect(Collectors.toList())); + for (MeasuredMwTempFileWriter writer : mwWriters) { - writer.writeParams(tmpFolder, measuredMwsDetails); + writer.writeMeasuredMws(tmpFolder, measuredMwsDetails); + } + + if (referenceMwWriters != null) { + List referenceMws = new ArrayList<>(); + referenceMws.addAll(eventClient.getReferenceEvents().filter(Objects::nonNull).toStream().collect(Collectors.toList())); + for (ReferenceMwTempFileWriter writer : referenceMwWriters) { + writer.writeReferenceMwParams(tmpFolder, referenceMws); + } } } @@ -124,10 +133,10 @@ public File createExportArchive() throws IOException { try (Stream fileStream = Files.walk(tmpFolder, 5)) { List files = fileStream.map(p -> p.toFile()).filter(f -> f.isFile()).collect(Collectors.toList()); - try (ArchiveOutputStream os = new ArchiveStreamFactory().createArchiveOutputStream("zip", new FileOutputStream(zipDir))) { + try (ArchiveOutputStream os = new ArchiveStreamFactory().createArchiveOutputStream("zip", Files.newOutputStream(zipDir.toPath()))) { for (File file : files) { os.putArchiveEntry(new ZipArchiveEntry(file, file.getName())); - IOUtils.copy(new FileInputStream(file), os); + IOUtils.copy(Files.newInputStream(file.toPath()), os); os.closeArchiveEntry(); } os.flush(); diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/SwftStyleParamFileWriter.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/SwftStyleParamFileWriter.java index c5e33339..706aecea 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/SwftStyleParamFileWriter.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/SwftStyleParamFileWriter.java @@ -30,6 +30,7 @@ import gov.llnl.gnem.apps.coda.calibration.gui.data.exporters.api.ParamTempFileWriter; import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteFrequencyBandParameters; +import gov.llnl.gnem.apps.coda.calibration.model.domain.VelocityConfiguration; import gov.llnl.gnem.apps.coda.common.gui.util.NumberFormatFactory; import gov.llnl.gnem.apps.coda.common.model.domain.FrequencyBand; import gov.llnl.gnem.apps.coda.common.model.domain.SharedFrequencyBandParameters; @@ -38,6 +39,8 @@ @Component public class SwftStyleParamFileWriter implements ParamTempFileWriter { + private static final char NEWLINE = '\n'; + private NumberFormat dfmt6 = NumberFormatFactory.sixDecimalOneLeadingZero(); private static final double DEFAULT_SITE_TERM = 0.0; @@ -76,9 +79,9 @@ private void writeParams(File paramFile, Map sharedParametersByFreqBand, Map> siteParameters) { + public void writeParams(Path folder, Map sharedParametersByFreqBand, Map> siteParameters, + VelocityConfiguration velocityConfig) { File sharedParamFile = new File(folder.toFile(), "Shared.param"); sharedParamFile.deleteOnExit(); try { diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/VelocityConfigurationFileMixin.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/VelocityConfigurationFileMixin.java new file mode 100644 index 00000000..cd2282dd --- /dev/null +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/VelocityConfigurationFileMixin.java @@ -0,0 +1,21 @@ +/* +* 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. +* +* 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; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(value = { "id", "version" }) +public class VelocityConfigurationFileMixin { +} diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/api/MeasuredMwTempFileWriter.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/api/MeasuredMwTempFileWriter.java index 5dcf981e..e4c6750a 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/api/MeasuredMwTempFileWriter.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/api/MeasuredMwTempFileWriter.java @@ -20,5 +20,5 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.MeasuredMwDetails; public interface MeasuredMwTempFileWriter { - void writeParams(Path folder, List measuredMwsDetails); + void writeMeasuredMws(Path folder, List measuredMwsDetails); } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/api/ParamTempFileWriter.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/api/ParamTempFileWriter.java index c6dba06d..dc3bd335 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/api/ParamTempFileWriter.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/api/ParamTempFileWriter.java @@ -18,10 +18,12 @@ import java.util.Map; import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteFrequencyBandParameters; +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; import gov.llnl.gnem.apps.coda.common.model.domain.Station; public interface ParamTempFileWriter { - void writeParams(Path folder, Map sharedParametersByFreqBand, Map> siteParameters); + void writeParams(Path folder, Map sharedParametersByFreqBand, Map> siteParameters, + VelocityConfiguration velocity); } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/api/ReferenceMwTempFileWriter.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/api/ReferenceMwTempFileWriter.java new file mode 100644 index 00000000..f565d366 --- /dev/null +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/api/ReferenceMwTempFileWriter.java @@ -0,0 +1,24 @@ +/* +* 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.gui.data.exporters.api; + +import java.nio.file.Path; +import java.util.List; + +import gov.llnl.gnem.apps.coda.calibration.model.domain.ReferenceMwParameters; + +public interface ReferenceMwTempFileWriter { + void writeReferenceMwParams(Path folder, List measuredMwsDetails); +} diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/events/MapIconActivationCallback.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/events/MapIconActivationCallback.java new file mode 100644 index 00000000..0cba7d12 --- /dev/null +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/events/MapIconActivationCallback.java @@ -0,0 +1,47 @@ +/* +* 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.gui.events; + +import java.util.function.Consumer; + +import gov.llnl.gnem.apps.coda.common.gui.data.client.api.WaveformClient; +import gov.llnl.gnem.apps.coda.common.mapping.MAP_CALLBACK_EVENT_TYPE; +import gov.llnl.gnem.apps.coda.common.mapping.MapCallbackEvent; +import gov.llnl.gnem.apps.coda.common.mapping.api.Icon; + +public class MapIconActivationCallback implements Consumer { + private WaveformClient client; + + public MapIconActivationCallback(WaveformClient client) { + this.client = client; + } + + @Override + public void accept(MapCallbackEvent evtVal) { + if (evtVal != null && MAP_CALLBACK_EVENT_TYPE.ACTIVATION.equals(evtVal.getType())) { + Icon icon = evtVal.getIcon(); + switch (icon.getType()) { + case CIRCLE: + client.setWaveformsActiveByEventId(icon.getId(), evtVal.getFlag()).subscribe(); + break; + case TRIANGLE_UP: + client.setWaveformsActiveByStationName(icon.getId(), evtVal.getFlag()).subscribe(); + break; + case DEFAULT: + default: + break; + } + } + } +} 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 d819391b..4b496a91 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 @@ -102,12 +102,6 @@ public CodaWaveformPlot(WaveformClient waveformClient, ShapeMeasurementClient sh private static final long serialVersionUID = 1L; - private static final int FULL_LENGTH = 1000; - - private static final Color LIGHT_RED = new Color(250, 100, 100); - - private static final Color PINK_HALF_TRANS = new Color(238, 200, 200, 128); - public void setWaveform(Waveform waveform) { setWaveform(waveform, null); } @@ -155,7 +149,13 @@ public void setWaveform(Waveform waveform, SyntheticCoda synth) { // a pick is before/after the bounds of the // waveform so we need to check that for (WaveformPick pick : picks) { - double pickTime = new TimeT(waveform.getEvent().getOriginTime()).getEpochTime() + pick.getPickTimeSecFromOrigin(); + double pickTime; + //"'Bad' pick, plot it at begin time + if (pick.getPickTimeSecFromOrigin() < 0) { + pickTime = new TimeT(waveform.getBeginTime()).getEpochTime(); + } else { + pickTime = new TimeT(waveform.getEvent().getOriginTime()).getEpochTime() + pick.getPickTimeSecFromOrigin(); + } if (pickTime >= new TimeT(waveform.getBeginTime()).getEpochTime() && pickTime <= new TimeT(waveform.getEndTime()).getEpochTime()) { Collection pickLines = this.addPick(pick.getPickName(), pickTime); for (VPickLine pickLine : pickLines) { @@ -201,9 +201,6 @@ public void setWaveform(Waveform waveform, SyntheticCoda synth) { velocityClient.getNoiseForWaveform(waveform.getId()).subscribe(measurement -> { if (measurement != null && measurement.getNoiseEndSecondsFromOrigin() != 0.0) { int lineLength = (int) (waveform.getSegment().length / waveform.getSampleRate()) + 10; - // int timeStart = (int) (new TimeT(measurement.getNoiseStartSecondsFromOrigin()).subtractD(beginTime) - 0.5); - // int timeEnd = (int) (new TimeT(measurement.getNoiseEndSecondsFromOrigin()).subtractD(beginTime) - 0.5); - // subplot.AddPlotObject(createRectangle(timeStart, timeEnd, -FULL_LENGTH, FULL_LENGTH, PINK_HALF_TRANS), PLOT_ORDERING.NOISE_BOX.getZOrder()); subplot.AddPlotObject(createFixedLine(measurement.getNoiseLevel(), lineLength, Color.BLACK, PenStyle.DASH), PLOT_ORDERING.NOISE_LINE.getZOrder()); subplot.AddPlotObject(createFixedLine(measurement.getNoiseLevel() + params.getMinSnr(), lineLength, Color.BLACK, PenStyle.SOLID), PLOT_ORDERING.NOISE_LINE.getZOrder()); repaint(); @@ -213,7 +210,7 @@ public void setWaveform(Waveform waveform, SyntheticCoda synth) { if (synth != null) { plotSynthetic(waveform, synth, beginTime, waveformSegment, subplot, event, distance, labelText, legendRef, params); this.synthetic = synth; - } else if (this.synthetic != null && synthetic.getSourceWaveform() != null && synthetic.getSourceWaveform().getId() == waveform.getId()) { + } else if (this.synthetic != null && synthetic.getSourceWaveform() != null && synthetic.getSourceWaveform().getId().equals(waveform.getId())) { plotSynthetic(waveform, synthetic, beginTime, waveformSegment, subplot, event, distance, labelText, legendRef, params); } } catch (IllegalArgumentException e) { @@ -230,7 +227,8 @@ private void plotSynthetic(Waveform waveform, SyntheticCoda synth, final TimeT b PlotObject legendRef, SharedFrequencyBandParameters params) { TimeSeries interpolatedSeries = new TimeSeries(waveformSegment, waveform.getSampleRate(), beginTime); float[] synthSegment = doublesToFloats(synth.getSegment()); - TimeSeries synthSeries = new TimeSeries(synthSegment, synth.getSampleRate(), new TimeT(synth.getBeginTime())); + TimeSeries synthSeriesBeforeEndMarker = new TimeSeries(synthSegment, synth.getSampleRate(), new TimeT(synth.getBeginTime())); + TimeSeries synthSeriesRemaining = new TimeSeries(synthSegment, synth.getSampleRate(), new TimeT(synth.getBeginTime())); WaveformPick endPick = null; for (WaveformPick p : waveform.getAssociatedPicks()) { if (p.getPickType() != null && PICK_TYPES.F.name().equalsIgnoreCase(p.getPickType().trim())) { @@ -239,19 +237,25 @@ private void plotSynthetic(Waveform waveform, SyntheticCoda synth, final TimeT b } } TimeT endTime; + TimeT originTime; + if (event != null) { + originTime = new TimeT(event.getOriginTime()); + } else { + originTime = new TimeT(synth.getBeginTime()); + } + if (endPick != null && event != null) { - endTime = new TimeT(event.getOriginTime()).add(endPick.getPickTimeSecFromOrigin()); + endTime = new TimeT(originTime).add(endPick.getPickTimeSecFromOrigin()); } else { endTime = new TimeT(synth.getEndTime()); } - interpolatedSeries.interpolate(synthSeries.getSamprate()); + interpolatedSeries.interpolate(synthSeriesBeforeEndMarker.getSamprate()); double vr = params.getVelocity0() - params.getVelocity1() / (params.getVelocity2() + distance); if (vr == 0.0) { vr = 1.0; } - TimeT originTime = new TimeT(event.getOriginTime()); TimeT startTime; TimeT trimTime = originTime.add(distance / vr); if (trimTime.lt(endTime)) { @@ -266,15 +270,18 @@ private void plotSynthetic(Waveform waveform, SyntheticCoda synth, final TimeT b if (startTime.lt(endTime)) { interpolatedSeries.cut(startTime, endTime); - synthSeries.cut(startTime, endTime); + synthSeriesBeforeEndMarker.cut(startTime, endTime); + synthSeriesRemaining.cutBefore(endTime); - TimeSeries diffSeis = interpolatedSeries.subtract(synthSeries); - int timeShift = (int) (startTime.subtractD(beginTime) + 0.5); + TimeSeries diffSeis = interpolatedSeries.subtract(synthSeriesBeforeEndMarker); + int synthStartTimeShift = (int) (startTime.subtractD(beginTime) + 0.5); + int remainingStartTimeShift = (int) (endTime.subtractD(beginTime) + 0.5); double median = diffSeis.getMedian(); subplot.DeletePlotObject(legendRef); subplot.AddPlotObject(createLegend(labelText + "Shift: " + dfmt4.format(median))); - subplot.AddPlotObject(createLine(timeShift, median, synthSeries, Color.GREEN), PLOT_ORDERING.MODEL_FIT.getZOrder()); + subplot.AddPlotObject(createLine(synthStartTimeShift, median, synthSeriesBeforeEndMarker, Color.GREEN), PLOT_ORDERING.MODEL_FIT.getZOrder()); + subplot.AddPlotObject(createLine(remainingStartTimeShift, median, synthSeriesRemaining, Color.GREEN, 3, PenStyle.DASH), PLOT_ORDERING.MODEL_FIT.getZOrder()); repaint(); } } @@ -284,6 +291,18 @@ private PinnedText createLegend(String text) { return new PinnedText(5d, 5d, text, HorizPinEdge.RIGHT, VertPinEdge.TOP, getTitle().getFontName(), getTitle().getFontSize(), Color.black, HorizAlignment.RIGHT, VertAlignment.TOP); } + private PlotObject createLine(int timeShift, double valueShift, TimeSeries timeSeries, Color lineColor) { + return createLine(timeShift, valueShift, timeSeries, lineColor, 3, PenStyle.SOLID); + } + + private PlotObject createLine(int timeShift, double valueShift, TimeSeries timeSeries, Color lineColor, int width, PenStyle style) { + Line line = new Line(timeShift, timeSeries.getDelta(), SeriesMath.add(timeSeries.getData(), valueShift), 1); + line.setPenStyle(style); + line.setColor(lineColor); + line.setWidth(width); + return line; + } + //Only used for Waveforms @Override public AbstractLine addLine(TimeSeries seismogram, Color lineColor) { @@ -293,6 +312,16 @@ public AbstractLine addLine(TimeSeries seismogram, Color lineColor) { return line; } + private PlotObject createFixedLine(double value, int length, Color lineColor, PenStyle penStyle) { + float[] data = new float[length]; + Arrays.fill(data, (float) value); + Line line = new Line(0, 1.0, data, 1); + line.setColor(lineColor); + line.setPenStyle(penStyle); + line.setWidth(3); + return line; + } + //Only used for Picks @Override protected void addPlotObject(JSubplot subplot, PlotObject object) { @@ -305,23 +334,6 @@ private PlotObject createRectangle(int timeStart, int timeEnd, int heightMin, in return rect; } - private PlotObject createLine(int timeShift, double valueShift, TimeSeries timeSeries, Color lineColor) { - Line line = new Line(timeShift, timeSeries.getDelta(), SeriesMath.add(timeSeries.getData(), valueShift), 1); - line.setColor(lineColor); - line.setWidth(3); - return line; - } - - private PlotObject createFixedLine(double value, int length, Color lineColor, PenStyle penStyle) { - float[] data = new float[length]; - Arrays.fill(data, (float) value); - Line line = new Line(0, 1.0, data, 1); - line.setColor(lineColor); - line.setPenStyle(penStyle); - line.setWidth(3); - return line; - } - /* * (non-Javadoc) * @@ -357,10 +369,10 @@ protected void handlePickMovedState(Object obj) { } } - public static float[] doublesToFloats(Double[] x) { + public static float[] doublesToFloats(double[] x) { float[] xfloats = new float[x.length]; for (int i = 0; i < x.length; i++) { - xfloats[i] = x[i].floatValue(); + xfloats[i] = (float) x[i]; } return xfloats; } 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 d5312e10..c2c15a3a 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 @@ -16,12 +16,9 @@ import java.awt.BorderLayout; import java.awt.Font; -import java.awt.FontFormatException; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; -import java.io.IOException; -import java.io.InputStream; import java.time.Duration; import java.util.ArrayList; import java.util.Collection; @@ -56,6 +53,7 @@ import gov.llnl.gnem.apps.coda.common.model.domain.SyntheticCoda; import gov.llnl.gnem.apps.coda.common.model.domain.Waveform; import javafx.scene.input.KeyCode; +import reactor.core.scheduler.Schedulers; //TODO: Split this out into a few separate functional areas when time permits (i.e. CodaWaveformPlotGUI, CodaWaveformPlotManager, etc). // As it currently is this class is pretty entangled. @@ -122,38 +120,33 @@ public CodaWaveformPlotManager(WaveformClient waveformClient, ShapeMeasurementCl toolbar = new JToolBar(); toolbar.setFloatable(false); - try (InputStream is = CodaWaveformPlotManager.class.getResourceAsStream("/fxml/MaterialIcons-Regular.ttf")) { - Font font = Font.createFont(Font.TRUETYPE_FONT, is); - Font sizedFont = font.deriveFont(24f); - - JButton forwardButton = new JButton("\uE315"); - pagingLabel = new JLabel("0/0"); - JButton backButton = new JButton("\uE314"); - forwardButton.setFont(sizedFont); - backButton.setFont(sizedFont); - - forwardButton.setBorderPainted(false); - forwardButton.setFocusPainted(false); - forwardButton.setContentAreaFilled(false); - - backButton.setBorderPainted(false); - backButton.setFocusPainted(false); - backButton.setContentAreaFilled(false); - - forwardButton.addActionListener(action -> { - forwardAction.actionPerformed(action); - }); - - backButton.addActionListener(action -> { - backwardAction.actionPerformed(action); - }); - - toolbar.add(backButton); - toolbar.add(pagingLabel); - toolbar.add(forwardButton); - } catch (FontFormatException | IOException e) { - log.error(e.getMessage(), e); - } + pagingLabel = new JLabel("0/0"); + JButton forwardButton = new JButton(">"); + JButton backButton = new JButton("<"); + + forwardButton.setBorderPainted(false); + forwardButton.setFocusPainted(false); + forwardButton.setContentAreaFilled(false); + + backButton.setBorderPainted(false); + backButton.setFocusPainted(false); + backButton.setContentAreaFilled(false); + + forwardButton.addActionListener(action -> { + forwardAction.actionPerformed(action); + }); + + backButton.addActionListener(action -> { + backwardAction.actionPerformed(action); + }); + + toolbar.add(backButton); + toolbar.add(pagingLabel); + toolbar.add(forwardButton); + + Font sizedFont = forwardButton.getFont().deriveFont(24f); + forwardButton.setFont(sizedFont); + backButton.setFont(sizedFont); }); } @@ -256,11 +249,11 @@ private void loadWaveformsForPage(int pageNumber) { clear(); List> results = new ArrayList<>(); if (allWaveformIDs.size() == 1) { - SyntheticCoda synth = waveformClient.getSyntheticFromWaveformId(allWaveformIDs.get(0)).block(Duration.ofSeconds(10)); + SyntheticCoda synth = waveformClient.getSyntheticFromWaveformId(allWaveformIDs.get(0)).publishOn(Schedulers.elastic()).block(Duration.ofSeconds(10)); if (synth != null && synth.getId() != null) { results.add(createPlot(synth)); } else { - results.add(createPlot(waveformClient.getWaveformFromId(allWaveformIDs.get(0)).block(Duration.ofSeconds(10)))); + results.add(createPlot(waveformClient.getWaveformFromId(allWaveformIDs.get(0)).publishOn(Schedulers.elastic()).block(Duration.ofSeconds(10)))); } } else { pagingLabel.setText(pageNumber + 1 + "/" + (totalPages + 1)); @@ -270,13 +263,21 @@ private void loadWaveformsForPage(int pageNumber) { skipVal = allWaveformIDs.size() - pageSize; } allWaveformIDs.stream().sequential().skip(skipVal).limit(pageSize).forEach(pageIds::add); - List synthetics = waveformClient.getSyntheticsFromWaveformIds(pageIds).filter(synth -> synth != null && synth.getId() != null).collectList().block(Duration.ofSeconds(10)); + List synthetics = waveformClient.getSyntheticsFromWaveformIds(pageIds) + .filter(synth -> synth != null && synth.getId() != null) + .collectList() + .publishOn(Schedulers.elastic()) + .block(Duration.ofSeconds(10)); if (synthetics != null && !synthetics.isEmpty()) { pageIds.removeAll(synthetics.stream().map(synth -> synth.getSourceWaveform().getId()).collect(Collectors.toList())); results.addAll(createSyntheticPlots(synthetics)); } - List waveforms = waveformClient.getWaveformsFromIds(pageIds).filter(waveform -> waveform != null && waveform.getId() != null).collectList().block(Duration.ofSeconds(10)); + List waveforms = waveformClient.getWaveformsFromIds(pageIds) + .filter(waveform -> waveform != null && waveform.getId() != null) + .collectList() + .publishOn(Schedulers.elastic()) + .block(Duration.ofSeconds(10)); if (waveforms != null && !waveforms.isEmpty()) { results.addAll(createWaveformPlots(waveforms)); } @@ -303,9 +304,9 @@ private void setPlots(List> plotPairs) { } public void triggerKeyEvent(javafx.scene.input.KeyEvent event) { - if (event.getCode().equals(KeyCode.LEFT)) { + if (event.getCode() == KeyCode.LEFT) { SwingUtilities.invokeLater(() -> backwardAction.actionPerformed(new ActionEvent(event.getSource(), KeyEvent.KEY_RELEASED, "BackwardAction"))); - } else if (event.getCode().equals(KeyCode.RIGHT)) { + } else if (event.getCode() == KeyCode.RIGHT) { SwingUtilities.invokeLater(() -> forwardAction.actionPerformed(new ActionEvent(event.getSource(), KeyEvent.KEY_RELEASED, "ForwardAction"))); } } 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 44227321..addfa97d 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 @@ -215,9 +215,9 @@ private void plotSpectraObject(JSubplot jsubplot, Spectra spectra, Legend legend } jsubplot.AddPlotObject(line); DecimalFormat df = new DecimalFormat("#.0#"); - if (spectra.getStressDrop() > 0.0) { + if (spectra.getApparentStress() > 0.0) { DecimalFormat df2 = new DecimalFormat("#0.0#"); - legend.addLabeledLine(spectra.getType().name() + ' ' + df.format(spectra.getMw()) + " @ " + df2.format(spectra.getStressDrop()) + "MPa", line); + legend.addLabeledLine(spectra.getType().name() + ' ' + df.format(spectra.getMw()) + " @ " + df2.format(spectra.getApparentStress()) + "MPa", line); } else { legend.addLabeledLine(spectra.getType().name() + ' ' + df.format(spectra.getMw()), line); } @@ -263,7 +263,7 @@ private List createAveragePlot(List allOrderedPoints) { private List sortPointsByX(List inPlots) { List plots = new ArrayList<>(inPlots); int smallestIndex = getSmallestX(plots); - List orderedList = new ArrayList<>(); + List orderedList = new ArrayList<>(plots.size()); orderedList.add(plots.remove(smallestIndex)); while (!plots.isEmpty()) { // Find the index of the closest point (using another method) diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting/WaveformGui.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting/WaveformGui.java index d0f953d4..998252b6 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting/WaveformGui.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting/WaveformGui.java @@ -134,10 +134,20 @@ public void hide() { public void show() { Platform.runLater(() -> { + boolean showing = stage.isShowing(); stage.show(); if (waveformPlotManager != null) { waveformPlotManager.setVisible(true); } + if (!showing) { + stage.toFront(); + } + }); + } + + public void toFront() { + show(); + Platform.runLater(() -> { stage.toFront(); }); } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/util/CalibrationProgressListener.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/util/CalibrationProgressListener.java index 573e6a14..5626919d 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/util/CalibrationProgressListener.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/util/CalibrationProgressListener.java @@ -25,7 +25,7 @@ public class CalibrationProgressListener extends ProgressListener { private CalibrationStatusEvent cachedEvent; - private Progress progress = new Progress(1l, -1l); + private Progress progress = new Progress((long) CalibrationStatusEvent.Status.COMPLETE.ordinal(), 0l); public CalibrationProgressListener(EventBus bus, CalibrationStatusEvent event) { bus.register(this); @@ -37,9 +37,9 @@ private void listener(CalibrationStatusEvent event) { if (cachedEvent != null && cachedEvent.getId().equals(event.getId())) { cachedEvent = event; if (cachedEvent.getStatus() == Status.COMPLETE || cachedEvent.getStatus() == Status.ERROR) { - progress.setCurrent(1l); + progress.setCurrent((long) CalibrationStatusEvent.Status.COMPLETE.ordinal()); } else { - progress.setCurrent(-1l); + progress.setCurrent((long) cachedEvent.getStatus().ordinal()); } this.setChanged(); this.notifyObservers(progress); diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/util/TimeLatchedGetSet.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/util/TimeLatchedGetSet.java index 9ccd669f..cc6210e3 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/util/TimeLatchedGetSet.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/util/TimeLatchedGetSet.java @@ -17,12 +17,9 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class TimeLatchedGetSet { - private final Logger log = LoggerFactory.getLogger(this.getClass()); + private static final int THRESHOLD = 1; private final ScheduledThreadPoolExecutor scheduledGet = new ScheduledThreadPoolExecutor(1); private final ScheduledThreadPoolExecutor scheduledSet = new ScheduledThreadPoolExecutor(1); @@ -49,27 +46,70 @@ public TimeLatchedGetSet(Runnable getter, Runnable setter, long setDelay, long g scheduledSet.setRemoveOnCancelPolicy(true); } + public TimeLatchedGetSet() { + this(null, null, 1000l, 1000l, 1000l); + } + public void set() { if (setter != null) { - scheduledSet.getQueue().clear(); - scheduledSet.schedule(() -> { - setter.run(); - if (getter != null) { - scheduledGet.schedule(() -> { - getter.run(); - }, failsafeDelay, TimeUnit.MILLISECONDS); - } - }, setDelay, TimeUnit.MILLISECONDS); + if (scheduledSet.getQueue().size() < THRESHOLD) { + scheduledSet.schedule(() -> { + setter.run(); + }, setDelay, TimeUnit.MILLISECONDS); + } } } public void get() { if (getter != null) { - scheduledGet.getQueue().clear(); - scheduledGet.schedule(() -> { - getter.run(); - }, getDelay, TimeUnit.MILLISECONDS); + if (scheduledGet.getQueue().size() < THRESHOLD) { + scheduledGet.schedule(() -> { + getter.run(); + }, getDelay, TimeUnit.MILLISECONDS); + } } } + public TimeLatchedGetSet setGetter(Runnable getter) { + this.getter = getter; + return this; + } + + public TimeLatchedGetSet setSetter(Runnable setter) { + this.setter = setter; + return this; + } + + public long getSetDelay() { + return setDelay; + } + + public TimeLatchedGetSet setSetDelay(long setDelay) { + this.setDelay = setDelay; + return this; + } + + public long getGetDelay() { + return getDelay; + } + + public TimeLatchedGetSet setGetDelay(long getDelay) { + this.getDelay = getDelay; + return this; + } + + public long getFailsafeDelay() { + return failsafeDelay; + } + + public TimeLatchedGetSet setFailsafeDelay(long failsafeDelay) { + this.failsafeDelay = failsafeDelay; + return this; + } + + public void clear() { + scheduledSet.getQueue().clear(); + scheduledGet.getQueue().clear(); + } + } diff --git a/calibration-gui/src/main/resources/application.properties b/calibration-gui/src/main/resources/application.properties index 84012dfc..436c4ce8 100644 --- a/calibration-gui/src/main/resources/application.properties +++ b/calibration-gui/src/main/resources/application.properties @@ -1,3 +1,4 @@ +spring.output.ansi.enabled=ALWAYS logging.level.org.springframework.web.socket.*=off logging.level.org.springframework.web.reactive.function.client.*=off webclient.basePath=localhost:53921 diff --git a/calibration-gui/src/main/resources/fxml/CodaGui.fxml b/calibration-gui/src/main/resources/fxml/CodaGui.fxml index d11106f7..c5523ea7 100644 --- a/calibration-gui/src/main/resources/fxml/CodaGui.fxml +++ b/calibration-gui/src/main/resources/fxml/CodaGui.fxml @@ -55,7 +55,8 @@ - + + diff --git a/calibration-gui/src/main/resources/fxml/Data.fxml b/calibration-gui/src/main/resources/fxml/Data.fxml index 6aa8bad8..e9f56320 100644 --- a/calibration-gui/src/main/resources/fxml/Data.fxml +++ b/calibration-gui/src/main/resources/fxml/Data.fxml @@ -6,30 +6,33 @@ - + - -
- - - + +
+ + + + + + + + - - - - - - - - + + - - - - - - -
-
+ + + + + +
+
+
+
+
diff --git a/calibration-gui/src/main/resources/fxml/FitPlot.css b/calibration-gui/src/main/resources/fxml/FitPlot.css index dcef147e..82311302 100644 --- a/calibration-gui/src/main/resources/fxml/FitPlot.css +++ b/calibration-gui/src/main/resources/fxml/FitPlot.css @@ -1,5 +1,5 @@ .default-color0.chart-series-line { -fx-stroke: transparent; } -.default-color1.chart-series-line { -fx-stroke: blue; -fx-stroke-width:5px; } +.default-color1.chart-series-line { -fx-stroke: blue; -fx-stroke-width: 3px; -fx-stroke-dash-array: 6 6;} .default-color2.chart-series-line { -fx-stroke: transparent; } .default-color3.chart-series-line { -fx-stroke: transparent; } diff --git a/calibration-gui/src/main/resources/fxml/Parameters.fxml b/calibration-gui/src/main/resources/fxml/Parameters.fxml index 1d4e3eee..7efff873 100644 --- a/calibration-gui/src/main/resources/fxml/Parameters.fxml +++ b/calibration-gui/src/main/resources/fxml/Parameters.fxml @@ -5,7 +5,7 @@ - + @@ -26,6 +26,11 @@ + + + + + diff --git a/calibration-gui/src/main/resources/fxml/Shape.fxml b/calibration-gui/src/main/resources/fxml/Shape.fxml index fde5a641..b1ba5e12 100644 --- a/calibration-gui/src/main/resources/fxml/Shape.fxml +++ b/calibration-gui/src/main/resources/fxml/Shape.fxml @@ -13,7 +13,7 @@ - + diff --git a/calibration-gui/src/main/resources/fxml/Site.fxml b/calibration-gui/src/main/resources/fxml/Site.fxml index 614fd0e1..6f4b548c 100644 --- a/calibration-gui/src/main/resources/fxml/Site.fxml +++ b/calibration-gui/src/main/resources/fxml/Site.fxml @@ -15,114 +15,162 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/calibration-gui/src/main/resources/fxml/Velocity.fxml b/calibration-gui/src/main/resources/fxml/Velocity.fxml new file mode 100644 index 00000000..cc1c9a0a --- /dev/null +++ b/calibration-gui/src/main/resources/fxml/Velocity.fxml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/calibration-gui/src/test/resources/calibration-params-test.json b/calibration-gui/src/test/resources/calibration-params-test.json index 7be4ed10..ea066b76 100644 --- a/calibration-gui/src/test/resources/calibration-params-test.json +++ b/calibration-gui/src/test/resources/calibration-params-test.json @@ -41,6 +41,6 @@ ], "reference-events": [ { "eventId" : "0331199924", "refMw" : 3.0 }, - { "eventId" : "0401199924", "refMw" : 5.0, "stressDropInMpa": 0.7 } + { "eventId" : "0401199924", "refMw" : 5.0, "apparentStressInMpa": 0.7 } ] } \ No newline at end of file diff --git a/calibration-service/calibration-application/pom.xml b/calibration-service/calibration-application/pom.xml index 60833fa4..c6632556 100644 --- a/calibration-service/calibration-application/pom.xml +++ b/calibration-service/calibration-application/pom.xml @@ -1,12 +1,13 @@ - gov.llnl.gnem.apps.coda.calibration calibration-service 1.0.4-SNAPSHOT - + 4.0.0 calibration-application jar @@ -21,11 +22,6 @@ org.springframework.boot spring-boot-starter - - org.springframework.boot - spring-boot-starter-test - test - org.springframework.boot spring-boot-devtools @@ -90,12 +86,32 @@ springlets-data-commons - io.springlets - springlets-web + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + + org.springframework.boot - spring-boot-starter-web + spring-boot-starter-jetty + + + org.eclipse.jetty + jetty-server + + + + + org.eclipse.jetty + jetty-alpn-conscrypt-server + + + org.eclipse.jetty.http2 + http2-server gov.llnl.gnem.apps.coda.common diff --git a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/CalibrationNotificationStompController.java b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/CalibrationNotificationStompController.java index 7ce8a90b..4c613e6b 100644 --- a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/CalibrationNotificationStompController.java +++ b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/CalibrationNotificationStompController.java @@ -22,6 +22,7 @@ import gov.llnl.gnem.apps.coda.calibration.model.messaging.CalibrationStatusEvent; import gov.llnl.gnem.apps.coda.calibration.model.messaging.MdacDataChangeEvent; import gov.llnl.gnem.apps.coda.common.application.web.TypingMessageTemplate; +import gov.llnl.gnem.apps.coda.common.model.messaging.WaveformChangeEvent; import gov.llnl.gnem.apps.coda.common.service.api.Listener; import gov.llnl.gnem.apps.coda.common.service.api.NotificationService; @@ -32,39 +33,22 @@ public class CalibrationNotificationStompController { public CalibrationNotificationStompController(SimpMessagingTemplate template, NotificationService notificationService) { final TypingMessageTemplate typingTemplate = new TypingMessageTemplate(template); - notificationService.register(new Listener() { - @Override - public void apply(CalibrationStatusEvent event) { - typingTemplate.convertAndSend("/topic/calibration-events", event); - } - - @Override - public Class getType() { - return CalibrationStatusEvent.class; - } - }); - - notificationService.register(new Listener() { - @Override - public void apply(MdacDataChangeEvent event) { - typingTemplate.convertAndSend("/topic/calibration-events", event); - } - - @Override - public Class getType() { - return MdacDataChangeEvent.class; - } - }); + registerCalEvent(notificationService, typingTemplate, CalibrationStatusEvent.class); + registerCalEvent(notificationService, typingTemplate, MdacDataChangeEvent.class); + registerCalEvent(notificationService, typingTemplate, BandParametersDataChangeEvent.class); + registerCalEvent(notificationService, typingTemplate, WaveformChangeEvent.class); + } - notificationService.register(new Listener() { + private void registerCalEvent(final NotificationService notificationService, final TypingMessageTemplate typingTemplate, Class clazz) { + notificationService.register(new Listener() { @Override - public void apply(BandParametersDataChangeEvent event) { + public void apply(T event) { typingTemplate.convertAndSend("/topic/calibration-events", event); } @Override - public Class getType() { - return BandParametersDataChangeEvent.class; + public Class getType() { + return clazz; } }); } diff --git a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/ConfigurationItemJsonController.java b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/ConfigurationItemJsonController.java new file mode 100644 index 00000000..39a428f1 --- /dev/null +++ b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/ConfigurationItemJsonController.java @@ -0,0 +1,57 @@ +/* +* 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. +* +* 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 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.VelocityConfiguration; +import gov.llnl.gnem.apps.coda.calibration.service.api.ConfigurationService; + +@RestController +@RequestMapping(value = "/api/v1/config/", name = "ConfigurationItemJsonController", produces = MediaType.APPLICATION_JSON_VALUE) +public class ConfigurationItemJsonController { + + private ConfigurationService configService; + + @Autowired + public ConfigurationItemJsonController(ConfigurationService configService) { + this.configService = configService; + } + + @GetMapping(value = "/velocity", name = "getVelocityConfiguration") + public VelocityConfiguration getVelocityConfiguration() { + return configService.getVelocityConfiguration(); + } + + @PostMapping(value = "/velocity/update", name = "updateVelocity") + public ResponseEntity update(@Valid @RequestBody VelocityConfiguration entry, BindingResult result) { + if (result.hasErrors()) { + return ResponseEntity.status(HttpStatus.CONFLICT).body(result); + } + configService.update(entry); + return ResponseEntity.ok().build(); + } +} diff --git a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/MdacParametersFiItemJsonController.java b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/MdacParametersFiItemJsonController.java index 1191fe90..73a75e87 100644 --- a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/MdacParametersFiItemJsonController.java +++ b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/MdacParametersFiItemJsonController.java @@ -34,7 +34,6 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.MdacParametersFI; import gov.llnl.gnem.apps.coda.calibration.service.api.MdacParametersFiService; -import io.springlets.web.NotFoundException; @RestController @RequestMapping(value = "/api/v1/params/fi/{fiParameters}", name = "MdacParametersFiItemJsonController", produces = MediaType.APPLICATION_JSON_VALUE) @@ -59,7 +58,7 @@ public MdacParametersFiItemJsonController(MdacParametersFiService fiParametersSe public MdacParametersFI getMdacParameters(@PathVariable("fiParameters") Long id) { MdacParametersFI fiParameters = fiParametersService.findOne(id); if (fiParameters == null) { - throw new NotFoundException(String.format("MdacParameters with identifier '%s' not found", id)); + throw new IllegalStateException(String.format("MdacParameters with identifier '%s' not found", id)); } return fiParameters; } diff --git a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/MdacParametersPsItemJsonController.java b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/MdacParametersPsItemJsonController.java index 1c5329fc..6f7a7054 100644 --- a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/MdacParametersPsItemJsonController.java +++ b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/MdacParametersPsItemJsonController.java @@ -34,7 +34,6 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.MdacParametersPS; import gov.llnl.gnem.apps.coda.calibration.service.api.MdacParametersPsService; -import io.springlets.web.NotFoundException; @RestController @RequestMapping(value = "/api/v1/params/ps/{psParameters}", name = "MdacParametersPsItemJsonController", produces = MediaType.APPLICATION_JSON_VALUE) @@ -59,7 +58,7 @@ public MdacParametersPsItemJsonController(MdacParametersPsService psParametersSe public MdacParametersPS getMdacParameters(@PathVariable("psParameters") Long id) { MdacParametersPS psParameters = psParametersService.findOne(id); if (psParameters == null) { - throw new NotFoundException(String.format("MdacParameters with identifier '%s' not found", id)); + throw new IllegalStateException(String.format("MdacParameters with identifier '%s' not found", id)); } return psParameters; } diff --git a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/MeasuredMwsJsonController.java b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/MeasuredMwsJsonController.java index 568e73a1..37544b95 100644 --- a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/MeasuredMwsJsonController.java +++ b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/MeasuredMwsJsonController.java @@ -22,6 +22,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +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.service.api.MeasuredMwsService; @@ -36,9 +37,14 @@ public MeasuredMwsJsonController(MeasuredMwsService service) { this.service = service; } - @GetMapping(name = "getReferenceEvents") + @GetMapping(name = "getReferenceEvents", value = "/") public List getReferenceEvents() { return service.findAll(); + } + + @GetMapping(name = "getEventDetails", value = "/details") + public List getEventDetails() { + return service.findAllDetails(); } public MeasuredMwsService getService() { diff --git a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/PeakVelocityJsonController.java b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/PeakVelocityJsonController.java index 4a88230a..15742971 100644 --- a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/PeakVelocityJsonController.java +++ b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/PeakVelocityJsonController.java @@ -38,17 +38,17 @@ public PeakVelocityJsonController(PeakVelocityMeasurementService service) { this.service = service; } - @GetMapping(name = "getMeasurements") + @GetMapping(name = "getMeasurements", path = "/all") public List getMeasurements() { return service.findAll(); } - @GetMapping(name = "getMeasurementsMetadataOnly", path = "/metadata") + @GetMapping(name = "getMeasurementsMetadataOnly", path = "/metadata/all") public List getMeasurementsMetadataOnly() { return service.findAllMetadataOnly(); } - @GetMapping(name = "getMeasurementsMetadataOnly", path = "/metadata-by-id/{id}") + @GetMapping(name = "getMeasurementsMetadataOnly", path = "/metadata/by-id/{id}") public PeakVelocityMeasurementMetadata getByWaveformIdMetadataOnly(@PathVariable(name = "id", required = true) Long id) { return service.findByWaveformIdMetadataOnly(id); } diff --git a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/ShapeMeasurementJsonController.java b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/ShapeMeasurementJsonController.java index cef5a8d3..662b6db0 100644 --- a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/ShapeMeasurementJsonController.java +++ b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/ShapeMeasurementJsonController.java @@ -15,6 +15,7 @@ package gov.llnl.gnem.apps.coda.calibration.application.web; import java.util.List; +import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; @@ -42,11 +43,21 @@ public List getMeasurements() { return service.findAll(); } + @GetMapping(path = "/metadata/all/", name = "getMeasurementsMetadata") + public List getMeasurementsMetadata() { + return service.findAllMetadataOnly().stream().map(md -> new ShapeMeasurement(md)).collect(Collectors.toList()); + } + @GetMapping("/byWaveformId/{id}") public ShapeMeasurement getMeasurementByWaveformId(@PathVariable Long id) { return service.findOneByWaveformId(id); } + @GetMapping("/metadata/byWaveformId/{id}") + public ShapeMeasurement getMeasurementMetadataByWaveformId(@PathVariable Long id) { + return new ShapeMeasurement(service.findOneMetadataByWaveformId(id)); + } + public ShapeMeasurementService getService() { return service; } diff --git a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/SharedFrequencyBandParametersItemJsonController.java b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/SharedFrequencyBandParametersItemJsonController.java index 4c7dc63d..b3126b81 100644 --- a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/SharedFrequencyBandParametersItemJsonController.java +++ b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/SharedFrequencyBandParametersItemJsonController.java @@ -27,7 +27,6 @@ import gov.llnl.gnem.apps.coda.calibration.service.api.SharedFrequencyBandParametersService; import gov.llnl.gnem.apps.coda.common.model.domain.SharedFrequencyBandParameters; -import io.springlets.web.NotFoundException; @RestController @RequestMapping(value = "/api/v1/params/shared-fb-parameters/{sharedFrequencyBandParameters}", name = "SharedFrequencyBandParametersItemJsonController", produces = MediaType.APPLICATION_JSON_VALUE) @@ -52,7 +51,7 @@ public SharedFrequencyBandParametersItemJsonController(SharedFrequencyBandParame public SharedFrequencyBandParameters getSharedFrequencyBandParameters(@PathVariable("sharedFrequencyBandParameters") Long id) { SharedFrequencyBandParameters sharedFrequencyBandParameters = sharedFrequencyBandParametersService.findOne(id); if (sharedFrequencyBandParameters == null) { - throw new NotFoundException(String.format("SharedFrequencyBandParameters with identifier '%s' not found", id)); + throw new IllegalStateException(String.format("SharedFrequencyBandParameters with identifier '%s' not found", id)); } return sharedFrequencyBandParameters; } diff --git a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/SiteFrequencyBandParametersItemJsonController.java b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/SiteFrequencyBandParametersItemJsonController.java index 266b3f90..971fe56f 100644 --- a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/SiteFrequencyBandParametersItemJsonController.java +++ b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/SiteFrequencyBandParametersItemJsonController.java @@ -34,7 +34,6 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteFrequencyBandParameters; import gov.llnl.gnem.apps.coda.calibration.service.api.SiteFrequencyBandParametersService; -import io.springlets.web.NotFoundException; @RestController @RequestMapping(value = "/api/v1/params/site-fb-parameters/{siteFrequencyBandParameters}", name = "SiteFrequencyBandParametersItemJsonController", produces = MediaType.APPLICATION_JSON_VALUE) @@ -49,7 +48,7 @@ public SiteFrequencyBandParametersItemJsonController(SiteFrequencyBandParameters public SiteFrequencyBandParameters getSiteFrequencyBandParameters(@PathVariable("siteFrequencyBandParameters") Long id) { SiteFrequencyBandParameters siteFrequencyBandParameters = siteFrequencyBandParametersService.findOne(id); if (siteFrequencyBandParameters == null) { - throw new NotFoundException(String.format("SiteFrequencyBandParameters with identifier '%s' not found", id)); + throw new IllegalStateException(String.format("SiteFrequencyBandParameters with identifier '%s' not found", id)); } return siteFrequencyBandParameters; } 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 9aa37723..1b3aa9b5 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 @@ -15,6 +15,7 @@ package gov.llnl.gnem.apps.coda.calibration.application.web; import java.util.List; +import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; @@ -45,11 +46,16 @@ public SpectraMeasurementJsonController(SpectraMeasurementService service, Share this.sharedParamsService = sharedParamsService; } - @GetMapping(name = "getMeasurements") + @GetMapping(name = "getMeasurements", path = "/all") public List getMeasurements() { return service.findAll(); } + @GetMapping(name = "getMeasurementsMetadata", path = "/metadata/all") + public List getMeasurementsMetadata() { + return service.findAllMetadataOnly().stream().map(md -> new SpectraMeasurement(md)).collect(Collectors.toList()); + } + @PostMapping(value = "/reference-spectra", name = "computeSpectraForEventId") public ResponseEntity computeSpectraForEventId(@RequestBody String eventId, BindingResult result) { //FIXME: Accept a phase to use! diff --git a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/SyntheticCollectionJsonController.java b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/SyntheticCollectionJsonController.java index d72b6f40..12437538 100644 --- a/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/SyntheticCollectionJsonController.java +++ b/calibration-service/calibration-application/src/main/java/gov/llnl/gnem/apps/coda/calibration/application/web/SyntheticCollectionJsonController.java @@ -38,7 +38,6 @@ import gov.llnl.gnem.apps.coda.calibration.service.api.SyntheticService; import gov.llnl.gnem.apps.coda.common.model.domain.SyntheticCoda; -import io.springlets.web.NotFoundException; @RestController @RequestMapping(value = "/api/v1/synthetics", name = "SyntheticCollectionJsonController", produces = MediaType.APPLICATION_JSON_VALUE) @@ -71,7 +70,7 @@ public ResponseEntity getBatch(@PathVariable("ids") Collection ids) { if (!data.isEmpty()) { return ResponseEntity.ok().body(data); } else { - throw new NotFoundException(String.format("SyntheticCoda with identifiers '%s' not found", ids)); + throw new IllegalStateException(String.format("SyntheticCoda with identifiers '%s' not found", ids)); } } @@ -81,7 +80,7 @@ public ResponseEntity getSyntheticCoda(@PathVariable("id") Long id) { if (synthetic == null) { synthetic = syntheticService.findOneByWaveformId(id); if (synthetic == null) { - throw new NotFoundException(String.format("SyntheticCoda with identifier '%s' not found", id)); + throw new IllegalStateException(String.format("SyntheticCoda with identifier '%s' not found", id)); } } return ResponseEntity.ok().body(synthetic); diff --git a/calibration-service/calibration-application/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/calibration-service/calibration-application/src/main/resources/META-INF/additional-spring-configuration-metadata.json new file mode 100644 index 00000000..1f32f096 --- /dev/null +++ b/calibration-service/calibration-application/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -0,0 +1,120 @@ +{ + "groups": [ + { + "name": "path" + }, + { + "name": "phase" + }, + { + "name": "velocity.calc" + } + ], + "properties": [ + { + "name": "path.use-aggressive-opt", + "type": "java.lang.Boolean", + "description": "If the path correction inversion should be more aggressive and start one chain for every vertex of the model space permutation simplex + some additional samples across the space. This is considerably slower but is more robust to noisier data sets. If disabled the path correction still uses a small number of starting chains empirically observed to be sufficient for every data set we've ever seen that a 1D correction was possible or appropriate for. Generally the recommendation is to run at least once with the fully aggressive inversion every time you start a new data set to watch for instability in the inversion (note: set logging.level.gov.llnl.gnem.apps.coda.calibration.service.impl.Joint1DPathCorrection=debug to see each chain's residuals) and then run the less aggressive version if you can for speed. Defaults to enabled (true)." + }, + { + "name": "path.phase-speed-kms", + "type": "java.lang.Double", + "description": "Phase speed (Km/S) to use for the path calibration." + }, + { + "name": "phase.phase-speed-kms", + "type": "java.lang.Double", + "description": "Phase speed (Km/S) to use for the spectra calibration. Note: path calibration will use this value if it is available but path.phaseSpeedKmS isn't." + }, + { + "name": "velocity.calc.group-velocity1-gt-distance", + "type": "java.lang.Double", + "description": "Starting velocity (in Km/S) for windowing distances before the distance threshold." + }, + { + "name": "velocity.calc.group-velocity2-gt-distance", + "type": "java.lang.Double", + "description": "Ending velocity (in Km/S) for windowing distances before the distance threshold." + }, + { + "name": "velocity.calc.group-velocity1-lt-distance", + "type": "java.lang.Double", + "description": "Starting velocity (in Km/S) for windowing distances after the distance threshold." + }, + { + "name": "velocity.calc.group-velocity2-lt-distance", + "type": "java.lang.Double", + "description": "Ending velocity (in Km/S) for windowing distances after the distance threshold." + }, + { + "name": "velocity.calc.distance-threshold-km", + "type": "java.lang.Double", + "description": "Distance threshold to use (in Km) to use for selected which group velocity to use" + } + ], + "hints": [ + { + "name": "phase.phase-speed-kms", + "values": [ + { + "value": "3.5", + "description": "Default phase speed in Km/S for spectra calculation" + } + ] + }, + { + "name": "path.phase-speed-kms", + "values": [ + { + "value": "3.5", + "description": "Default phase speed in Km/S for path correction" + } + ] + }, + { + "name": "velocity.calc.group-velocity1-gt-distance", + "values": [ + { + "value": "4.7", + "description": "Default starting velocity (in Km/S) for windowing distances past the distance threshold." + } + ] + }, + { + "name": "velocity.calc.group-velocity2-gt-distance", + "values": [ + { + "value": "2.3", + "description": "Default ending velocity (in Km/S) for windowing distances past the distance threshold." + } + ] + }, + { + "name": "velocity.calc.group-velocity1-lt-distance", + "values": [ + { + "value": "3.9", + "description": "Default starting velocity (in Km/S) for windowing distances before the distance threshold." + } + ] + }, + { + "name": "velocity.calc.group-velocity2-lt-distance", + "values": [ + { + "value": "1.9", + "description": "Default ending velocity (in Km/S) for windowing distances before the distance threshold." + } + ] + }, + { + "name": "velocity.calc.distance-threshold-km", + "values": [ + { + "value": "300.0", + "description": "Default distance threshold to use (in Km)" + } + ] + } + ] +} \ No newline at end of file diff --git a/calibration-service/calibration-application/src/main/resources/application-dev.properties b/calibration-service/calibration-application/src/main/resources/application-dev.properties index c77e23d5..71f23df4 100644 --- a/calibration-service/calibration-application/src/main/resources/application-dev.properties +++ b/calibration-service/calibration-application/src/main/resources/application-dev.properties @@ -1,15 +1,18 @@ +spring.output.ansi.enabled=ALWAYS +spring.jpa.open-in-view=false logging.level.org.hibernate.SQL=warn logging.level.root=INFO logging.level.gov.llnl.gnem.apps.coda.*=INFO #logging.level.org.hibernate.stat=debug spring.datasource.driver-class-name=org.h2.Driver -spring.datasource.url=jdbc\:h2\:file\:./codaH2.db;DB_CLOSE_DELAY\=-1;DB_CLOSE_ON_EXIT=FALSE;COMPRESS=TRUE +spring.datasource.url=jdbc:h2:file:./codaH2.db;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;COMPRESS=TRUE #spring.jackson.serialization.indent-output=true #spring.jpa.properties.hibernate.format_sql=true #spring.jpa.properties.hibernate.generate_statistics=true #spring.jpa.show-sql=true spring.messages.cache-duration=0 server.port=53921 +server.address=127.0.0.1 spring.jpa.hibernate.ddl-auto=update server.ssl.key-alias=selfsigned server.ssl.key-password=changeit @@ -18,4 +21,5 @@ server.ssl.key-store-provider=SUN server.ssl.key-store-type=JKS spring.datasource.continueOnError=true spring.jdbc.template.fetch-size=1000 -spring.jpa.properties.hibernate.jdbc.time_zone = UTC \ No newline at end of file +spring.jpa.properties.hibernate.jdbc.time_zone = UTC +server.http2.enabled=true \ No newline at end of file diff --git a/calibration-service/calibration-application/src/main/resources/application-file.properties b/calibration-service/calibration-application/src/main/resources/application-file.properties index d51bf326..e9260945 100644 --- a/calibration-service/calibration-application/src/main/resources/application-file.properties +++ b/calibration-service/calibration-application/src/main/resources/application-file.properties @@ -1,9 +1,11 @@ +spring.output.ansi.enabled=ALWAYS +spring.jpa.open-in-view=false logging.level.root=ERROR logging.level.gov.llnl.gnem.apps.coda.*=INFO spring.datasource.driver-class-name=org.h2.Driver -spring.datasource.url=jdbc\:h2\:./codaH2.db;DB_CLOSE_DELAY\=-1;COMPRESS=TRUE;DB_CLOSE_ON_EXIT=FALSE;AUTO_SERVER=TRUE;AUTO_SERVER_PORT=9999 -spring.jpa.hibernate.naming.strategy=org.hibernate.cfg.ImprovedNamingStrategy +spring.datasource.url=jdbc:h2:./codaH2.db;DB_CLOSE_DELAY=-1;COMPRESS=TRUE;DB_CLOSE_ON_EXIT=FALSE;AUTO_SERVER=TRUE;AUTO_SERVER_PORT=9999 server.port=53921 +server.address=127.0.0.1 spring.jpa.hibernate.ddl-auto=update server.ssl.key-alias=selfsigned server.ssl.key-password=changeit @@ -17,3 +19,4 @@ spring.jpa.properties.hibernate.jdbc.time_zone = UTC server.compression.enabled=true server.compression.mime-types=text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json server.compression.min-response-size=1024 +server.http2.enabled=true \ No newline at end of file diff --git a/calibration-service/calibration-application/src/main/resources/application.properties b/calibration-service/calibration-application/src/main/resources/application.properties index b75997ae..8a1bfb40 100644 --- a/calibration-service/calibration-application/src/main/resources/application.properties +++ b/calibration-service/calibration-application/src/main/resources/application.properties @@ -1,8 +1,11 @@ +spring.output.ansi.enabled=ALWAYS +spring.jpa.open-in-view=false logging.level.root=ERROR logging.level.gov.llnl.gnem.apps.coda.*=INFO spring.datasource.driver-class-name=org.h2.Driver -spring.datasource.url=jdbc\:h2\:mem\:./coda;DB_CLOSE_DELAY\=-1;COMPRESS=TRUE +spring.datasource.url=jdbc:h2:memLZF:./coda;DB_CLOSE_DELAY=-1;COMPRESS=TRUE server.port=53921 +server.address=127.0.0.1 spring.jpa.hibernate.ddl-auto=create server.ssl.key-alias=selfsigned server.ssl.key-password=changeit @@ -15,3 +18,4 @@ spring.jpa.properties.hibernate.jdbc.time_zone = UTC server.compression.enabled=true server.compression.mime-types=text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json server.compression.min-response-size=1024 +server.http2.enabled=true \ No newline at end of file diff --git a/calibration-service/calibration-application/src/main/resources/data.sql b/calibration-service/calibration-application/src/main/resources/data.sql index c9cfad7c..6dcfb431 100644 --- a/calibration-service/calibration-application/src/main/resources/data.sql +++ b/calibration-service/calibration-application/src/main/resources/data.sql @@ -5,6 +5,8 @@ INSERT INTO "MDACPS" (ID, DEL_ETA, DEL_GAMMA0, DELQ0, DIST_CRIT, ETA, GAMMA0, PH INSERT INTO "MDACFI" (ID, ALPHAR, ALPHAS, BETAS, BETAR, DEL_PSI, DEL_SIGMA, M0REF, PSI, RAD_PATP, RAD_PATS, RHOR, RHOS, SIGMA, VERSION, ZETA) VALUES ('-1', '5000', '6000', '3500', '2900', '0', '0', '10000000000000000', '0.25', '0.44', '0.6', '2500', '2700', '0.3', '0', '1') +INSERT INTO "VELOCITY_CONFIGURATION" (ID,DISTANCE_THRESHOLD_IN_KM,GROUP_VELOCITY1IN_KMS_GT_DISTANCE,GROUP_VELOCITY1IN_KMS_LT_DISTANCE,GROUP_VELOCITY2IN_KMS_GT_DISTANCE,GROUP_VELOCITY2IN_KMS_LT_DISTANCE,PHASE_SPEED_IN_KMS,VERSION) VALUES (-1,300.0,4.7,3.9,2.3,1.9,3.5,0) + INSERT INTO "SHARED_FB_PARAMS" (ID, BETA0, BETA1, BETA2, GAMMA0, GAMMA1, GAMMA2, LOW_FREQUENCY, HIGH_FREQUENCY,MIN_SNR, Q, S1, S2, VELOCITY0, VELOCITY1, VELOCITY2, VERSION, XC, XT, MIN_LENGTH, MAX_LENGTH, MEASURE_TIME) VALUES ('-1', '0', '0', '0', '0', '0', '0', '0.0200', '0.0300', '0.5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '100', '1000','100') INSERT INTO "SHARED_FB_PARAMS" (ID, BETA0, BETA1, BETA2, GAMMA0, GAMMA1, GAMMA2, LOW_FREQUENCY, HIGH_FREQUENCY,MIN_SNR, Q, S1, S2, VELOCITY0, VELOCITY1, VELOCITY2, VERSION, XC, XT, MIN_LENGTH, MAX_LENGTH, MEASURE_TIME) VALUES ('-2', '0', '0', '0', '0', '0', '0', '0.0300', '0.0500', '0.5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '100', '800', '100') INSERT INTO "SHARED_FB_PARAMS" (ID, BETA0, BETA1, BETA2, GAMMA0, GAMMA1, GAMMA2, LOW_FREQUENCY, HIGH_FREQUENCY,MIN_SNR, Q, S1, S2, VELOCITY0, VELOCITY1, VELOCITY2, VERSION, XC, XT, MIN_LENGTH, MAX_LENGTH, MEASURE_TIME) VALUES ('-3', '0', '0', '0', '0', '0', '0', '0.0500', '0.1000', '0.5', '0', '0', '0', '0', '0', '0', '0', '0', '0', '75', '600', '100') diff --git a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/InjectedVelocityConfig.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/InjectedVelocityConfig.java new file mode 100644 index 00000000..d827ce07 --- /dev/null +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/InjectedVelocityConfig.java @@ -0,0 +1,51 @@ +/* +* 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.model.domain; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; + +@Component +@Configuration +public class InjectedVelocityConfig { + @Value("#{'${path.phase-speed-kms:${phase.phase-speed-kms:${phase-speed-kms:3.5}}}'}") + private Double phaseSpeedInKms; + + @Value("#{'${velocity.calc.group-velocity1-gt-distance:${group-velocity1-gt-distance:4.7}}'}") + private Double groupVelocity1InKmsGtDistance; + + @Value("#{'${velocity.calc.group-velocity2-gt-distance:${group-velocity2-gt-distance:2.3}}'}") + private Double groupVelocity2InKmsGtDistance; + + @Value("#{'${velocity.calc.group-velocity1-lt-distance:${group-velocity1-lt-distance:3.9}}'}") + private Double groupVelocity1InKmsLtDistance; + + @Value("#{'${velocity.calc.group-velocity2-lt-distance:${group-velocity2-lt-distance:1.9}}'}") + private Double groupVelocity2InKmsLtDistance; + + @Value("#{'${velocity.calc.distance-threshold-km:${distance-threshold-km:300.0}}'}") + private Double distanceThresholdInKm; + + @Bean + public VelocityConfiguration toVelocityConfiguration() { + return new VelocityConfiguration().setDistanceThresholdInKm(distanceThresholdInKm) + .setGroupVelocity1InKmsGtDistance(groupVelocity1InKmsGtDistance) + .setGroupVelocity1InKmsLtDistance(groupVelocity1InKmsLtDistance) + .setGroupVelocity2InKmsGtDistance(groupVelocity2InKmsGtDistance) + .setGroupVelocity2InKmsLtDistance(groupVelocity2InKmsLtDistance) + .setPhaseSpeedInKms(phaseSpeedInKms); + } +} diff --git a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/MdacParametersFI.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/MdacParametersFI.java index a25c8a07..4c6665f5 100644 --- a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/MdacParametersFI.java +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/MdacParametersFI.java @@ -39,8 +39,7 @@ public class MdacParametersFI { private Long id; @Version - @Column(name = "version") - private Long version; + private Integer version = 0; @NumberFormat private double sigma; @@ -90,8 +89,8 @@ public MdacParametersFI() { public MdacParametersFI(MdacParametersFI mdacFI) { super(); - this.id = new Long(mdacFI.getId()); - this.version = new Long(mdacFI.getVersion()); + this.id = mdacFI.getId(); + this.version = mdacFI.getVersion(); this.sigma = mdacFI.getSigma(); this.delSigma = mdacFI.getDelSigma(); this.psi = mdacFI.getPsi(); @@ -108,6 +107,24 @@ public MdacParametersFI(MdacParametersFI mdacFI) { this.rhor = mdacFI.getRhor(); } + public MdacParametersFI merge(MdacParametersFI overlay) { + this.sigma = overlay.sigma; + this.delSigma = overlay.delSigma; + this.psi = overlay.psi; + this.delPsi = overlay.delPsi; + this.zeta = overlay.zeta; + this.m0ref = overlay.m0ref; + this.alphas = overlay.alphas; + this.betas = overlay.betas; + this.rhos = overlay.rhos; + this.radPatP = overlay.radPatP; + this.radPatS = overlay.radPatS; + this.alphaR = overlay.alphaR; + this.betaR = overlay.betaR; + this.rhor = overlay.rhor; + return this; + } + @Override public boolean equals(Object obj) { if (this == obj) { @@ -133,14 +150,10 @@ public void setId(Long id) { this.id = id; } - public Long getVersion() { + public Integer getVersion() { return this.version; } - public void setVersion(Long version) { - this.version = version; - } - public double getSigma() { return this.sigma; } @@ -289,24 +302,4 @@ public String toString() { + rhor + "]"; } - - public MdacParametersFI mergeNonNullOrEmptyFields(MdacParametersFI overlay) { - - this.sigma = overlay.sigma; - this.delSigma = overlay.delSigma; - this.psi = overlay.psi; - this.delPsi = overlay.delPsi; - this.zeta = overlay.zeta; - this.m0ref = overlay.m0ref; - this.alphas = overlay.alphas; - this.betas = overlay.betas; - this.rhos = overlay.rhos; - this.radPatP = overlay.radPatP; - this.radPatS = overlay.radPatS; - this.alphaR = overlay.alphaR; - this.betaR = overlay.betaR; - this.rhor = overlay.rhor; - - return this; - } } diff --git a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/MdacParametersPS.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/MdacParametersPS.java index 11b86328..ec9d3561 100644 --- a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/MdacParametersPS.java +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/MdacParametersPS.java @@ -37,8 +37,7 @@ public class MdacParametersPS { private Long id; @Version - @Column(name = "version") - private Long version; + private Integer version = 0; @Column(unique = true) private String phase; @@ -78,14 +77,10 @@ public void setId(Long id) { this.id = id; } - public Long getVersion() { + public Integer getVersion() { return this.version; } - public void setVersion(Long version) { - this.version = version; - } - public String getPhase() { return this.phase; } 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 7088f3f6..3c2a9f42 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 @@ -26,7 +26,13 @@ public class MeasuredMwDetails { private Double mw; - private Double stressDropInMpa; + private Double refMw; + + private Double apparentStressInMpa; + + private Double refApparentStressInMpa; + + private Integer dataCount; private Double latitude; @@ -34,19 +40,31 @@ public class MeasuredMwDetails { private String datetime; - private final DateTimeFormatter dateFormatter = DateTimeFormatter.ISO_INSTANT; - - public MeasuredMwDetails(MeasuredMwParameters meas, Event event) { - if (meas != null && event != null) { - setEventId(meas.getEventId()); - setMw(meas.getMw()); - setStressDropInMpa(meas.getStressDropInMpa()); - setLatitude(event.getLatitude()); - setLongitude(event.getLongitude()); + public MeasuredMwDetails(MeasuredMwParameters meas, ReferenceMwParameters ref, Event event) { + if (meas != null) { + this.mw = meas.getMw(); + this.apparentStressInMpa = meas.getApparentStressInMpa(); + this.dataCount = meas.getDataCount(); + } + if (event != null) { + this.eventId = event.getEventId(); + this.latitude = event.getLatitude(); + this.longitude = event.getLongitude(); if (event.getOriginTime() != null) { - setDatetime(dateFormatter.format(event.getOriginTime().toInstant())); + this.datetime = DateTimeFormatter.ISO_INSTANT.format(event.getOriginTime().toInstant()); } } + if (ref != null) { + if (eventId == null) { + this.eventId = ref.getEventId(); + } + this.refApparentStressInMpa = ref.getRefApparentStressInMpa(); + this.refMw = ref.getRefMw(); + } + } + + public MeasuredMwDetails() { + //nop } public String getEventId() { @@ -67,12 +85,39 @@ public MeasuredMwDetails setMw(double mw) { return this; } - public Double getStressDropInMpa() { - return stressDropInMpa; + public Double getRefMw() { + return refMw; + } + + public MeasuredMwDetails setRefMw(Double refMw) { + this.refMw = refMw; + return this; + } + + public Double getApparentStressInMpa() { + return apparentStressInMpa; + } + + public MeasuredMwDetails setApparentStressInMpa(Double apparentStressInMpa) { + this.apparentStressInMpa = apparentStressInMpa; + return this; + } + + public Double getRefApparentStressInMpa() { + return refApparentStressInMpa; } - public MeasuredMwDetails setStressDropInMpa(Double stressDropInMpa) { - this.stressDropInMpa = stressDropInMpa; + public MeasuredMwDetails setRefApparentStressInMpa(Double refApparentStressInMpa) { + this.refApparentStressInMpa = refApparentStressInMpa; + return this; + } + + public Integer getDataCount() { + return dataCount; + } + + public MeasuredMwDetails setDataCount(Integer dataCount) { + this.dataCount = dataCount; return this; } @@ -107,16 +152,14 @@ public MeasuredMwDetails setDatetime(String datetime) { public int hashCode() { final int prime = 31; int result = 1; + result = prime * result + ((apparentStressInMpa == null) ? 0 : apparentStressInMpa.hashCode()); result = prime * result + ((datetime == null) ? 0 : datetime.hashCode()); result = prime * result + ((eventId == null) ? 0 : eventId.hashCode()); - long temp; - temp = Double.doubleToLongBits(latitude); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(longitude); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(mw); - result = prime * result + (int) (temp ^ (temp >>> 32)); - result = prime * result + ((stressDropInMpa == null) ? 0 : stressDropInMpa.hashCode()); + result = prime * result + ((latitude == null) ? 0 : latitude.hashCode()); + result = prime * result + ((longitude == null) ? 0 : longitude.hashCode()); + result = prime * result + ((mw == null) ? 0 : mw.hashCode()); + result = prime * result + ((refApparentStressInMpa == null) ? 0 : refApparentStressInMpa.hashCode()); + result = prime * result + ((refMw == null) ? 0 : refMw.hashCode()); return result; } @@ -132,6 +175,13 @@ public boolean equals(Object obj) { return false; } MeasuredMwDetails other = (MeasuredMwDetails) obj; + if (apparentStressInMpa == null) { + if (other.apparentStressInMpa != null) { + return false; + } + } else if (!apparentStressInMpa.equals(other.apparentStressInMpa)) { + return false; + } if (datetime == null) { if (other.datetime != null) { return false; @@ -146,20 +196,39 @@ public boolean equals(Object obj) { } else if (!eventId.equals(other.eventId)) { return false; } - if (Double.doubleToLongBits(latitude) != Double.doubleToLongBits(other.latitude)) { + if (latitude == null) { + if (other.latitude != null) { + return false; + } + } else if (!latitude.equals(other.latitude)) { return false; } - if (Double.doubleToLongBits(longitude) != Double.doubleToLongBits(other.longitude)) { + if (longitude == null) { + if (other.longitude != null) { + return false; + } + } else if (!longitude.equals(other.longitude)) { return false; } - if (Double.doubleToLongBits(mw) != Double.doubleToLongBits(other.mw)) { + if (mw == null) { + if (other.mw != null) { + return false; + } + } else if (!mw.equals(other.mw)) { + return false; + } + if (refApparentStressInMpa == null) { + if (other.refApparentStressInMpa != null) { + return false; + } + } else if (!refApparentStressInMpa.equals(other.refApparentStressInMpa)) { return false; } - if (stressDropInMpa == null) { - if (other.stressDropInMpa != null) { + if (refMw == null) { + if (other.refMw != null) { return false; } - } else if (!stressDropInMpa.equals(other.stressDropInMpa)) { + } else if (!refMw.equals(other.refMw)) { return false; } return true; @@ -167,25 +236,27 @@ public boolean equals(Object obj) { @Override public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("\"") - .append(eventId) - .append("\", \"") - .append(mw) - .append("\", \"") - .append(stressDropInMpa) - .append("\", \"") - .append(latitude) - .append("\", \"") - .append(longitude) - .append("\", \"") - .append(datetime) - .append("\""); - return builder.toString(); + return "MeasuredMwDetails [eventId=" + + eventId + + ", mw=" + + mw + + ", refMw=" + + refMw + + ", apparentStressInMpa=" + + apparentStressInMpa + + ", refApparentStressInMpa=" + + refApparentStressInMpa + + ", latitude=" + + latitude + + ", longitude=" + + longitude + + ", datetime=" + + datetime + + "]"; } @JsonIgnore public boolean isValid() { - return eventId != null && mw != null && stressDropInMpa != null && latitude != null && longitude != null && datetime != null; + return eventId != null; } -} \ No newline at end of file +} diff --git a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/MeasuredMwParameters.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/MeasuredMwParameters.java index b93313da..6147c446 100644 --- a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/MeasuredMwParameters.java +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/MeasuredMwParameters.java @@ -39,8 +39,7 @@ public class MeasuredMwParameters implements Serializable { private Long id; @Version - @Column(name = "version") - private Long version; + private Integer version = 0; @Column(name = "eventId") private String eventId; @@ -50,7 +49,9 @@ public class MeasuredMwParameters implements Serializable { @NumberFormat @Column(nullable = true) - private Double stressDropInMpa; + private Double apparentStressInMpa; + + private int dataCount; public Long getId() { return id; @@ -61,15 +62,10 @@ public MeasuredMwParameters setId(Long id) { return this; } - public Long getVersion() { + public Integer getVersion() { return version; } - public MeasuredMwParameters setVersion(Long version) { - this.version = version; - return this; - } - public String getEventId() { return eventId; } @@ -88,32 +84,44 @@ public MeasuredMwParameters setMw(double mw) { return this; } - public Double getStressDropInMpa() { - return stressDropInMpa; + public Double getApparentStressInMpa() { + return apparentStressInMpa; } - public MeasuredMwParameters setStressDropInMpa(Double stressDropInMpa) { - this.stressDropInMpa = stressDropInMpa; + public MeasuredMwParameters setApparentStressInMpa(Double apparentStressInMpa) { + this.apparentStressInMpa = apparentStressInMpa; return this; } - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return "MeasuredMwParameters [id=" + id + ", version=" + version + ", eventId=" + eventId + ", mw=" + mw + ", stressDropInMpa=" + stressDropInMpa + "]"; + public Integer getDataCount() { + return dataCount; + } + + public MeasuredMwParameters setDataCount(Integer dataCount) { + this.dataCount = dataCount; + return this; + } + + public MeasuredMwParameters merge(MeasuredMwParameters overlay) { + this.mw = overlay.getMw(); + this.apparentStressInMpa = overlay.getApparentStressInMpa(); + this.dataCount = overlay.getDataCount(); + return this; } @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((eventId == null) ? 0 : eventId.hashCode()); + result = prime * result + ((apparentStressInMpa == null) ? 0 : apparentStressInMpa.hashCode()); long temp; + temp = Double.doubleToLongBits(dataCount); + result = prime * result + (int) (temp ^ (temp >>> 32)); + result = prime * result + ((eventId == null) ? 0 : eventId.hashCode()); + result = prime * result + ((id == null) ? 0 : id.hashCode()); temp = Double.doubleToLongBits(mw); result = prime * result + (int) (temp ^ (temp >>> 32)); - result = prime * result + ((stressDropInMpa == null) ? 0 : stressDropInMpa.hashCode()); + result = prime * result + ((version == null) ? 0 : version.hashCode()); return result; } @@ -129,6 +137,16 @@ public boolean equals(Object obj) { return false; } MeasuredMwParameters other = (MeasuredMwParameters) obj; + if (apparentStressInMpa == null) { + if (other.apparentStressInMpa != null) { + return false; + } + } else if (!apparentStressInMpa.equals(other.apparentStressInMpa)) { + return false; + } + if (Double.doubleToLongBits(dataCount) != Double.doubleToLongBits(other.dataCount)) { + return false; + } if (eventId == null) { if (other.eventId != null) { return false; @@ -136,23 +154,43 @@ public boolean equals(Object obj) { } else if (!eventId.equals(other.eventId)) { return false; } + if (id == null) { + if (other.id != null) { + return false; + } + } else if (!id.equals(other.id)) { + return false; + } if (Double.doubleToLongBits(mw) != Double.doubleToLongBits(other.mw)) { return false; } - if (stressDropInMpa == null) { - if (other.stressDropInMpa != null) { + if (version == null) { + if (other.version != null) { return false; } - } else if (!stressDropInMpa.equals(other.stressDropInMpa)) { + } else if (!version.equals(other.version)) { return false; } return true; } - public MeasuredMwParameters merge(MeasuredMwParameters overlay) { - this.mw = overlay.getMw(); - this.stressDropInMpa = overlay.getStressDropInMpa(); - return this; + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("MeasuredMwParameters [id=") + .append(id) + .append(", version=") + .append(version) + .append(", eventId=") + .append(eventId) + .append(", mw=") + .append(mw) + .append(", apparentStressInMpa=") + .append(apparentStressInMpa) + .append(", dataCount=") + .append(dataCount) + .append("]"); + return builder.toString(); } } \ No newline at end of file diff --git a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/PathCalibrationMeasurement.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/PathCalibrationMeasurement.java index e3271a6e..b8542a42 100644 --- a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/PathCalibrationMeasurement.java +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/PathCalibrationMeasurement.java @@ -41,8 +41,7 @@ public class PathCalibrationMeasurement implements Serializable { private Long id; @Version - @Column(name = "version") - private Long version; + private Integer version = 0; @NumberFormat private Double initialResidual; @@ -62,15 +61,10 @@ public PathCalibrationMeasurement setId(Long id) { return this; } - public Long getVersion() { + public Integer getVersion() { return version; } - public PathCalibrationMeasurement setVersion(Long version) { - this.version = version; - return this; - } - public Double getInitialResidual() { return initialResidual; } diff --git a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/PeakVelocityMeasurement.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/PeakVelocityMeasurement.java index 71661ca2..c43439be 100644 --- a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/PeakVelocityMeasurement.java +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/PeakVelocityMeasurement.java @@ -41,8 +41,7 @@ public class PeakVelocityMeasurement implements Serializable { private Long id; @Version - @Column(name = "version") - private Long version; + private Integer version = 0; @OneToOne(optional = false) @JoinColumn(unique = true) @@ -91,15 +90,10 @@ public PeakVelocityMeasurement(PeakVelocityMeasurementMetadata metadata) { this.waveform = new Waveform(metadata.getWaveform()); } - public Long getVersion() { + public Integer getVersion() { return version; } - public PeakVelocityMeasurement setVersion(Long version) { - this.version = version; - return this; - } - public Waveform getWaveform() { return waveform; } @@ -311,7 +305,7 @@ public String toString() { .append(noiseEndSecondsFromOrigin) .append("\", \"") .append(noiseLevel) - .append("\""); + .append('\"'); return builder.toString(); } diff --git a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/PeakVelocityMeasurementMetadata.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/PeakVelocityMeasurementMetadata.java index f3a19439..ef8abe9e 100644 --- a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/PeakVelocityMeasurementMetadata.java +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/PeakVelocityMeasurementMetadata.java @@ -20,7 +20,7 @@ public interface PeakVelocityMeasurementMetadata { public Long getId(); - public Long getVersion(); + public Integer getVersion(); public WaveformMetadata getWaveform(); diff --git a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/ReferenceMwParameters.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/ReferenceMwParameters.java index f0e3cbef..54babcf3 100644 --- a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/ReferenceMwParameters.java +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/ReferenceMwParameters.java @@ -27,6 +27,8 @@ import org.springframework.format.annotation.NumberFormat; +import com.fasterxml.jackson.annotation.JsonAlias; + @Entity @Table(name = "Reference_Mws", indexes = { @Index(columnList = "eventId", name = "ref_mw_event_id_index") }) public class ReferenceMwParameters implements Serializable { @@ -39,8 +41,7 @@ public class ReferenceMwParameters implements Serializable { private Long id; @Version - @Column(name = "version") - private Long version; + private Integer version = 0; @Column(name = "eventId") private String eventId; @@ -50,7 +51,8 @@ public class ReferenceMwParameters implements Serializable { @NumberFormat @Column(nullable = true) - private Double stressDropInMpa; + @JsonAlias({ "stressDropInMpa" }) + private Double refApparentStressInMpa; public Long getId() { return id; @@ -61,15 +63,10 @@ public ReferenceMwParameters setId(Long id) { return this; } - public Long getVersion() { + public Integer getVersion() { return version; } - public ReferenceMwParameters setVersion(Long version) { - this.version = version; - return this; - } - public String getEventId() { return eventId; } @@ -88,18 +85,18 @@ public ReferenceMwParameters setRefMw(double refMw) { return this; } - public Double getStressDropInMpa() { - return stressDropInMpa; + public Double getRefApparentStressInMpa() { + return refApparentStressInMpa; } - public ReferenceMwParameters setStressDropInMpa(Double stressDropInMpa) { - this.stressDropInMpa = stressDropInMpa; + public ReferenceMwParameters setRefApparentStressInMpa(Double apparentStressInMpa) { + this.refApparentStressInMpa = apparentStressInMpa; return this; } @Override public String toString() { - return "ReferenceMwParams [id=" + id + ", version=" + version + ", eventId=" + eventId + ", refMw=" + refMw + ", stressDropInMpa=" + stressDropInMpa + "]"; + return "ReferenceMwParams [id=" + id + ", version=" + version + ", eventId=" + eventId + ", refMw=" + refMw + ", apparentStressInMpa=" + refApparentStressInMpa + "]"; } @Override @@ -110,7 +107,7 @@ public int hashCode() { long temp; temp = Double.doubleToLongBits(refMw); result = prime * result + (int) (temp ^ (temp >>> 32)); - result = prime * result + ((stressDropInMpa == null) ? 0 : stressDropInMpa.hashCode()); + result = prime * result + ((refApparentStressInMpa == null) ? 0 : refApparentStressInMpa.hashCode()); return result; } @@ -136,11 +133,11 @@ public boolean equals(Object obj) { if (Double.doubleToLongBits(refMw) != Double.doubleToLongBits(other.refMw)) { return false; } - if (stressDropInMpa == null) { - if (other.stressDropInMpa != null) { + if (refApparentStressInMpa == null) { + if (other.refApparentStressInMpa != null) { return false; } - } else if (!stressDropInMpa.equals(other.stressDropInMpa)) { + } else if (!refApparentStressInMpa.equals(other.refApparentStressInMpa)) { return false; } return true; @@ -148,7 +145,7 @@ public boolean equals(Object obj) { public ReferenceMwParameters merge(ReferenceMwParameters overlay) { this.refMw = overlay.getRefMw(); - this.stressDropInMpa = overlay.getStressDropInMpa(); + this.refApparentStressInMpa = overlay.getRefApparentStressInMpa(); return this; } diff --git a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/ShapeMeasurement.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/ShapeMeasurement.java index 8251a1fc..04ff22cd 100644 --- a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/ShapeMeasurement.java +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/ShapeMeasurement.java @@ -46,8 +46,7 @@ public class ShapeMeasurement implements Serializable { private Long id; @Version - @Column(name = "version") - private Long version; + private Integer version = 0; @OneToOne(optional = false) @JoinColumn(unique = true) @@ -85,6 +84,26 @@ public class ShapeMeasurement implements Serializable { @NumberFormat private double timeDifference; + public ShapeMeasurement() { + //nop + } + + public ShapeMeasurement(ShapeMeasurementMetadata md) { + this.id = md.getId(); + this.version = md.getVersion(); + this.waveform = new Waveform(md.getWaveform()); + this.v0 = md.getV0(); + this.v1 = md.getV1(); + this.v2 = md.getV2(); + this.measuredBeta = md.getMeasuredBeta(); + this.measuredGamma = md.getMeasuredGamma(); + this.measuredIntercept = md.getMeasuredIntercept(); + this.measuredError = md.getMeasuredError(); + this.measuredTime = md.getMeasuredTime(); + this.distance = md.getDistance(); + this.timeDifference = md.getTimeDifference(); + } + public Long getId() { return id; } @@ -94,15 +113,10 @@ public ShapeMeasurement setId(Long id) { return this; } - public Long getVersion() { + public Integer getVersion() { return version; } - public ShapeMeasurement setVersion(Long version) { - this.version = version; - return this; - } - public Waveform getWaveform() { return waveform; } diff --git a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/ShapeMeasurementMetadata.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/ShapeMeasurementMetadata.java new file mode 100644 index 00000000..5378b6d2 --- /dev/null +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/ShapeMeasurementMetadata.java @@ -0,0 +1,48 @@ +/* +* 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. +* +* 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.util.Date; + +import gov.llnl.gnem.apps.coda.common.model.domain.WaveformMetadata; + +public interface ShapeMeasurementMetadata { + + public Long getId(); + + public Integer getVersion(); + + public WaveformMetadata getWaveform(); + + public double getV0(); + + public double getV1(); + + public double getV2(); + + public double getMeasuredBeta(); + + public double getMeasuredGamma(); + + public double getMeasuredIntercept(); + + public double getMeasuredError(); + + public Date getMeasuredTime(); + + public double getTimeDifference(); + + public double getDistance(); +} diff --git a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/SiteFrequencyBandParameters.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/SiteFrequencyBandParameters.java index 78da8250..6c56dd64 100644 --- a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/SiteFrequencyBandParameters.java +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/SiteFrequencyBandParameters.java @@ -37,8 +37,7 @@ public class SiteFrequencyBandParameters { private Long id; @Version - @Column(name = "version") - private Long version; + private Integer version = 0; @NumberFormat private double lowFrequency; @@ -60,14 +59,10 @@ public void setId(Long id) { this.id = id; } - public Long getVersion() { + public Integer getVersion() { return this.version; } - public void setVersion(Long version) { - this.version = version; - } - public double getLowFrequency() { return this.lowFrequency; } diff --git a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/Spectra.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/Spectra.java index 5911a27f..af5a4a9b 100644 --- a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/Spectra.java +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/Spectra.java @@ -22,7 +22,7 @@ public class Spectra { private List xyVals; - private double stressDrop = -1; + private double apparentStress = -1; private double mw = -1; private SPECTRA_TYPES type; @@ -31,16 +31,16 @@ public class Spectra { * List of java.awt.geom.Point2D.Double entries representing X, Y * points * @param mw - * @param stressDrop + * @param stress */ - public Spectra(SPECTRA_TYPES type, List xyVals, Double mw, Double stressDrop) { + public Spectra(SPECTRA_TYPES type, List xyVals, Double mw, Double stress) { this.type = type; this.xyVals = xyVals; if (mw != null) { this.mw = mw; } - if (stressDrop != null) { - this.stressDrop = stressDrop; + if (stress != null) { + this.apparentStress = stress; } } @@ -53,8 +53,8 @@ public List getSpectraXY() { return xyVals; } - public double getStressDrop() { - return stressDrop; + public double getApparentStress() { + return apparentStress; } public double getMw() { diff --git a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/SpectraMeasurement.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/SpectraMeasurement.java index 175a393a..b60d6283 100644 --- a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/SpectraMeasurement.java +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/SpectraMeasurement.java @@ -42,8 +42,7 @@ public class SpectraMeasurement implements Serializable { private Long id; @Version - @Column(name = "version") - private Long version; + private Integer version = 0; @OneToOne(optional = false) @JoinColumn(unique = true) @@ -70,13 +69,25 @@ public class SpectraMeasurement implements Serializable { @NumberFormat private double rmsFit; - public Long getVersion() { - return version; + public SpectraMeasurement() { + //nop } - public SpectraMeasurement setVersion(Long version) { - this.version = version; - return this; + public SpectraMeasurement(SpectraMeasurementMetadata md) { + this.id = md.getId(); + this.version = md.getVersion(); + this.waveform = new Waveform(md.getWaveform()); + this.rawAtStart = md.getRawAtStart(); + this.rawAtMeasurementTime = md.getRawAtMeasurementTime(); + this.pathCorrected = md.getPathCorrected(); + this.pathAndSiteCorrected = md.getPathAndSiteCorrected(); + this.startCutSec = md.getStartCutSec(); + this.endCutSec = md.getEndCutSec(); + this.rmsFit = md.getRmsFit(); + } + + public Integer getVersion() { + return version; } public Waveform getWaveform() { diff --git a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/SpectraMeasurementMetadata.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/SpectraMeasurementMetadata.java new file mode 100644 index 00000000..59a39253 --- /dev/null +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/SpectraMeasurementMetadata.java @@ -0,0 +1,40 @@ +/* +* 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. +* +* 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 gov.llnl.gnem.apps.coda.common.model.domain.WaveformMetadata; + +public interface SpectraMeasurementMetadata { + + public Long getId(); + + public Integer getVersion(); + + public double getEndCutSec(); + + public double getPathAndSiteCorrected(); + + public double getPathCorrected(); + + public double getRawAtMeasurementTime(); + + public double getRawAtStart(); + + public double getRmsFit(); + + public double getStartCutSec(); + + public WaveformMetadata getWaveform(); +} diff --git a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/VelocityConfiguration.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/VelocityConfiguration.java new file mode 100644 index 00000000..d83d649f --- /dev/null +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/VelocityConfiguration.java @@ -0,0 +1,242 @@ +/* +* 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. +* +* 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.Table; +import javax.persistence.Version; + +import org.springframework.format.annotation.NumberFormat; + +import gov.llnl.gnem.apps.coda.common.model.util.Durable; + +@Durable +@Entity +@Table(name = "Velocity_Configuration") +public class VelocityConfiguration implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "ID") + private Long id; + + @Version + private Integer version = 0; + + @NumberFormat + private Double phaseSpeedInKms; + + @NumberFormat + private Double groupVelocity1InKmsGtDistance; + + @NumberFormat + private Double groupVelocity2InKmsGtDistance; + + @NumberFormat + private Double groupVelocity1InKmsLtDistance; + + @NumberFormat + private Double groupVelocity2InKmsLtDistance; + + @NumberFormat + private Double distanceThresholdInKm; + + public Long getId() { + return id; + } + + public Integer getVersion() { + return version; + } + + public Double getPhaseSpeedInKms() { + return phaseSpeedInKms; + } + + public VelocityConfiguration setPhaseSpeedInKms(Double phaseSpeedInKms) { + this.phaseSpeedInKms = phaseSpeedInKms; + return this; + } + + public Double getGroupVelocity1InKmsGtDistance() { + return groupVelocity1InKmsGtDistance; + } + + public VelocityConfiguration setGroupVelocity1InKmsGtDistance(Double groupVelocity1InKmsGtDistance) { + this.groupVelocity1InKmsGtDistance = groupVelocity1InKmsGtDistance; + return this; + } + + public Double getGroupVelocity2InKmsGtDistance() { + return groupVelocity2InKmsGtDistance; + } + + public VelocityConfiguration setGroupVelocity2InKmsGtDistance(Double groupVelocity2InKmsGtDistance) { + this.groupVelocity2InKmsGtDistance = groupVelocity2InKmsGtDistance; + return this; + } + + public Double getGroupVelocity1InKmsLtDistance() { + return groupVelocity1InKmsLtDistance; + } + + public VelocityConfiguration setGroupVelocity1InKmsLtDistance(Double groupVelocity1InKmsLtDistance) { + this.groupVelocity1InKmsLtDistance = groupVelocity1InKmsLtDistance; + return this; + } + + public Double getGroupVelocity2InKmsLtDistance() { + return groupVelocity2InKmsLtDistance; + } + + public VelocityConfiguration setGroupVelocity2InKmsLtDistance(Double groupVelocity2InKmsLtDistance) { + this.groupVelocity2InKmsLtDistance = groupVelocity2InKmsLtDistance; + return this; + } + + public Double getDistanceThresholdInKm() { + return distanceThresholdInKm; + } + + public VelocityConfiguration setDistanceThresholdInKm(Double distanceThresholdInKm) { + this.distanceThresholdInKm = distanceThresholdInKm; + return this; + } + + public VelocityConfiguration merge(VelocityConfiguration overlay) { + if (overlay.phaseSpeedInKms != null && overlay.phaseSpeedInKms != 0.0) { + this.phaseSpeedInKms = overlay.phaseSpeedInKms; + } + if (overlay.groupVelocity1InKmsGtDistance != null && overlay.groupVelocity1InKmsGtDistance != 0.0) { + this.groupVelocity1InKmsGtDistance = overlay.groupVelocity1InKmsGtDistance; + } + if (overlay.groupVelocity2InKmsGtDistance != null && overlay.groupVelocity2InKmsGtDistance != 0.0) { + this.groupVelocity2InKmsGtDistance = overlay.groupVelocity2InKmsGtDistance; + } + if (overlay.groupVelocity1InKmsLtDistance != null && overlay.groupVelocity1InKmsLtDistance != 0.0) { + this.groupVelocity1InKmsLtDistance = overlay.groupVelocity1InKmsLtDistance; + } + if (overlay.groupVelocity2InKmsLtDistance != null && overlay.groupVelocity2InKmsLtDistance != 0.0) { + this.groupVelocity2InKmsLtDistance = overlay.groupVelocity2InKmsLtDistance; + } + if (overlay.distanceThresholdInKm != null && overlay.distanceThresholdInKm != 0.0) { + this.distanceThresholdInKm = overlay.distanceThresholdInKm; + } + return this; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((distanceThresholdInKm == null) ? 0 : distanceThresholdInKm.hashCode()); + result = prime * result + ((groupVelocity1InKmsGtDistance == null) ? 0 : groupVelocity1InKmsGtDistance.hashCode()); + result = prime * result + ((groupVelocity1InKmsLtDistance == null) ? 0 : groupVelocity1InKmsLtDistance.hashCode()); + result = prime * result + ((groupVelocity2InKmsGtDistance == null) ? 0 : groupVelocity2InKmsGtDistance.hashCode()); + result = prime * result + ((groupVelocity2InKmsLtDistance == null) ? 0 : groupVelocity2InKmsLtDistance.hashCode()); + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((phaseSpeedInKms == null) ? 0 : phaseSpeedInKms.hashCode()); + result = prime * result + ((version == null) ? 0 : version.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; + } + VelocityConfiguration other = (VelocityConfiguration) obj; + if (distanceThresholdInKm == null) { + if (other.distanceThresholdInKm != null) { + return false; + } + } else if (!distanceThresholdInKm.equals(other.distanceThresholdInKm)) { + return false; + } + if (groupVelocity1InKmsGtDistance == null) { + if (other.groupVelocity1InKmsGtDistance != null) { + return false; + } + } else if (!groupVelocity1InKmsGtDistance.equals(other.groupVelocity1InKmsGtDistance)) { + return false; + } + if (groupVelocity1InKmsLtDistance == null) { + if (other.groupVelocity1InKmsLtDistance != null) { + return false; + } + } else if (!groupVelocity1InKmsLtDistance.equals(other.groupVelocity1InKmsLtDistance)) { + return false; + } + if (groupVelocity2InKmsGtDistance == null) { + if (other.groupVelocity2InKmsGtDistance != null) { + return false; + } + } else if (!groupVelocity2InKmsGtDistance.equals(other.groupVelocity2InKmsGtDistance)) { + return false; + } + if (groupVelocity2InKmsLtDistance == null) { + if (other.groupVelocity2InKmsLtDistance != null) { + return false; + } + } else if (!groupVelocity2InKmsLtDistance.equals(other.groupVelocity2InKmsLtDistance)) { + return false; + } + if (phaseSpeedInKms == null) { + if (other.phaseSpeedInKms != null) { + return false; + } + } else if (!phaseSpeedInKms.equals(other.phaseSpeedInKms)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("VelocityConfiguration [id=") + .append(id) + .append(", version=") + .append(version) + .append(", phaseSpeedInKms=") + .append(phaseSpeedInKms) + .append(", groupVelocity1InKmsGtDistance=") + .append(groupVelocity1InKmsGtDistance) + .append(", groupVelocity2InKmsGtDistance=") + .append(groupVelocity2InKmsGtDistance) + .append(", groupVelocity1InKmsLtDistance=") + .append(groupVelocity1InKmsLtDistance) + .append(", groupVelocity2InKmsLtDistance=") + .append(groupVelocity2InKmsLtDistance) + .append(", distanceThresholdInKm=") + .append(distanceThresholdInKm) + .append("]"); + return builder.toString(); + } +} 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 new file mode 100644 index 00000000..be8debe8 --- /dev/null +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/mixins/ReferenceMwParametersFileMixin.java @@ -0,0 +1,24 @@ +/* +* 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. +* +* 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.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/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/messaging/BandParametersDataChangeEvent.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/messaging/BandParametersDataChangeEvent.java index 34c5aead..f39e40cd 100644 --- a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/messaging/BandParametersDataChangeEvent.java +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/messaging/BandParametersDataChangeEvent.java @@ -40,7 +40,7 @@ public void setId(Long id) { @Override public String toString() { StringBuilder builder = new StringBuilder(); - builder.append("\"").append(id).append("\""); + builder.append("\"").append(id).append('\"'); return builder.toString(); } diff --git a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/messaging/CalibrationStatusEvent.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/messaging/CalibrationStatusEvent.java index 81664471..d9f63ffc 100644 --- a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/messaging/CalibrationStatusEvent.java +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/messaging/CalibrationStatusEvent.java @@ -22,7 +22,7 @@ public class CalibrationStatusEvent { public enum Status { - STARTING, COMPLETE, ERROR + STARTING, PEAK_STARTING, SHAPE_STARTING, PATH_STARTING, SITE_STARTING, COMPLETE, ERROR }; private Long id; diff --git a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/messaging/GvDataChangeEvent.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/messaging/GvDataChangeEvent.java new file mode 100644 index 00000000..85a8a757 --- /dev/null +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/messaging/GvDataChangeEvent.java @@ -0,0 +1,77 @@ +/* +* 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. +* +* 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.messaging; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class GvDataChangeEvent { + + private Long id; + + public GvDataChangeEvent() { + id = 0l; + } + + @JsonCreator + public GvDataChangeEvent(@JsonProperty("id") Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("\"").append(id).append('\"'); + return builder.toString(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.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; + } + GvDataChangeEvent other = (GvDataChangeEvent) obj; + if (id == null) { + if (other.id != null) { + return false; + } + } else if (!id.equals(other.id)) { + return false; + } + return true; + } +} diff --git a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/messaging/MdacDataChangeEvent.java b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/messaging/MdacDataChangeEvent.java index adfa9a7d..0572ecf8 100644 --- a/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/messaging/MdacDataChangeEvent.java +++ b/calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/messaging/MdacDataChangeEvent.java @@ -41,7 +41,7 @@ public void setId(Long id) { @Override public String toString() { StringBuilder builder = new StringBuilder(); - builder.append("\"").append(id).append("\""); + builder.append("\"").append(id).append('\"'); return builder.toString(); } 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 90cce61a..dd65f5ae 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 @@ -14,8 +14,12 @@ */ package gov.llnl.gnem.apps.coda.calibration.repository; +import java.util.List; + +import org.springframework.data.jpa.repository.Query; import org.springframework.transaction.annotation.Transactional; +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; 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 fda8bdf2..293e4de1 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 @@ -14,13 +14,23 @@ */ package gov.llnl.gnem.apps.coda.calibration.repository; +import java.util.List; + +import org.springframework.data.jpa.repository.Query; import org.springframework.transaction.annotation.Transactional; 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; @Transactional public interface ShapeMeasurementRepository extends DetachableJpaRepository { public ShapeMeasurement findOneByWaveformId(Long waveformId); + + @Query("select v from ShapeMeasurement v") + public List findAllMetadataOnly(); + + @Query("select v from ShapeMeasurement v where v.waveform.id = :waveformId ") + public ShapeMeasurementMetadata findOneMetadataByWaveformId(Long waveformId); } 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 8090b041..e4e9224a 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 @@ -14,11 +14,21 @@ */ package gov.llnl.gnem.apps.coda.calibration.repository; +import java.util.List; + +import org.springframework.data.jpa.repository.Query; import org.springframework.transaction.annotation.Transactional; 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; @Transactional public interface SpectraMeasurementRepository extends DetachableJpaRepository { + + @Query("select v from SpectraMeasurement v") + public List findAllMetadataOnly(); + + @Query("select v from SpectraMeasurement v where v.id in :ids ") + public List findAllMetadataById(Iterable ids); } 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 new file mode 100644 index 00000000..7e80ed18 --- /dev/null +++ b/calibration-service/calibration-repository/src/main/java/gov/llnl/gnem/apps/coda/calibration/repository/VelocityConfigurationRepository.java @@ -0,0 +1,25 @@ +/* +* 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. +* +* 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 org.springframework.transaction.annotation.Transactional; + +import gov.llnl.gnem.apps.coda.calibration.model.domain.VelocityConfiguration; +import io.springlets.data.jpa.repository.DetachableJpaRepository; + +@Transactional +public interface VelocityConfigurationRepository extends DetachableJpaRepository { + public VelocityConfiguration findFirstByOrderById(); +} diff --git a/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/ConfigurationService.java b/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/ConfigurationService.java new file mode 100644 index 00000000..09eb5514 --- /dev/null +++ b/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/ConfigurationService.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. +* 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 gov.llnl.gnem.apps.coda.calibration.model.domain.VelocityConfiguration; + +public interface ConfigurationService { + public VelocityConfiguration getVelocityConfiguration(); + + public VelocityConfiguration update(VelocityConfiguration entry); +} diff --git a/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/MeasuredMwsService.java b/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/MeasuredMwsService.java index 2017ae0e..dc909881 100644 --- a/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/MeasuredMwsService.java +++ b/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/MeasuredMwsService.java @@ -14,8 +14,12 @@ */ package gov.llnl.gnem.apps.coda.calibration.service.api; +import java.util.List; + +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.common.service.api.BaseService; public interface MeasuredMwsService extends BaseService { + public List findAllDetails(); } 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 4bac3aa0..f96eca02 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 @@ -18,11 +18,12 @@ import java.util.Map; import gov.llnl.gnem.apps.coda.calibration.model.domain.SpectraMeasurement; +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; public interface PathCalibrationService { Map measurePathCorrections(Map> dataByFreqBand, - Map frequencyBandParameters); + Map frequencyBandParameters, VelocityConfiguration velConf); } diff --git a/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/PeakVelocityMeasurementService.java b/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/PeakVelocityMeasurementService.java index 22858464..dfd6fdf1 100644 --- a/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/PeakVelocityMeasurementService.java +++ b/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/PeakVelocityMeasurementService.java @@ -14,17 +14,18 @@ */ package gov.llnl.gnem.apps.coda.calibration.service.api; -import java.util.Collection; import java.util.List; +import java.util.stream.Stream; import gov.llnl.gnem.apps.coda.calibration.model.domain.PeakVelocityMeasurement; import gov.llnl.gnem.apps.coda.calibration.model.domain.PeakVelocityMeasurementMetadata; +import gov.llnl.gnem.apps.coda.calibration.model.domain.VelocityConfiguration; import gov.llnl.gnem.apps.coda.common.model.domain.Waveform; import gov.llnl.gnem.apps.coda.common.service.api.BaseService; public interface PeakVelocityMeasurementService extends BaseService { - public Collection measureVelocities(List allStacks); + public Stream measureVelocities(List allStacks, VelocityConfiguration velocityConfig); public List findAllMetadataOnly(); diff --git a/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/ShapeMeasurementService.java b/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/ShapeMeasurementService.java index c20f5438..e51cb12e 100644 --- a/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/ShapeMeasurementService.java +++ b/calibration-service/calibration-service-api/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/api/ShapeMeasurementService.java @@ -14,9 +14,17 @@ */ package gov.llnl.gnem.apps.coda.calibration.service.api; +import java.util.List; + import gov.llnl.gnem.apps.coda.calibration.model.domain.ShapeMeasurement; +import gov.llnl.gnem.apps.coda.calibration.model.domain.ShapeMeasurementMetadata; import gov.llnl.gnem.apps.coda.common.service.api.BaseService; public interface ShapeMeasurementService extends BaseService { + public ShapeMeasurement findOneByWaveformId(Long waveformId); + + public List findAllMetadataOnly(); + + public ShapeMeasurementMetadata findOneMetadataByWaveformId(Long waveformId); } 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 829fe07b..9608608e 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 @@ -20,6 +20,8 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteFrequencyBandParameters; 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.VelocityConfiguration; 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; @@ -28,10 +30,11 @@ public interface SpectraMeasurementService { - public List measureSpectra(List generatedSynthetics, Map frequencyBandParameterMap, Boolean autoPickingEnabled); + public List measureSpectra(List generatedSynthetics, Map frequencyBandParameterMap, Boolean autoPickingEnabled, + VelocityConfiguration velocityConfig); public List measureSpectra(List generatedSynthetics, Map frequencyBandParameterMap, Boolean autoPickingEnabled, - Map> frequencyBandSiteParameterMap); + VelocityConfiguration velocityConfig, Map> frequencyBandSiteParameterMap); public SpectraMeasurement findOne(Long id); @@ -41,10 +44,13 @@ public List measureSpectra(List generatedSynt public List findAll(); + public List findAllMetadataOnly(); + + public List findAllMetadataOnly(Iterable ids); + public long count(); public Spectra computeSpectraForEventId(String eventId, List frequencyBands, PICK_TYPES selectedPhase); public Spectra getFitSpectraForEventId(String eventId, List frequencyBands, PICK_TYPES selectedPhase); - } diff --git a/calibration-service/calibration-service-impl/pom.xml b/calibration-service/calibration-service-impl/pom.xml index f091e045..24ae9c97 100644 --- a/calibration-service/calibration-service-impl/pom.xml +++ b/calibration-service/calibration-service-impl/pom.xml @@ -87,6 +87,10 @@ gov.llnl.gnem.apps.coda.common common-service-impl + + javax.annotation + javax.annotation-api + 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 085a3edd..b6295b38 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 @@ -31,6 +31,7 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.annotation.PreDestroy; @@ -45,8 +46,10 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.ReferenceMwParameters; import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteFrequencyBandParameters; import gov.llnl.gnem.apps.coda.calibration.model.domain.SpectraMeasurement; +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.service.api.CalibrationService; +import gov.llnl.gnem.apps.coda.calibration.service.api.ConfigurationService; import gov.llnl.gnem.apps.coda.calibration.service.api.DatabaseCleaningService; import gov.llnl.gnem.apps.coda.calibration.service.api.MdacParametersFiService; import gov.llnl.gnem.apps.coda.calibration.service.api.MdacParametersPsService; @@ -89,6 +92,7 @@ public class CalibrationServiceImpl implements CalibrationService { private SyntheticService syntheticService; private NotificationService notificationService; private DatabaseCleaningService cleaningService; + private ConfigurationService configService; private static final AtomicLong atomicLong = new AtomicLong(0l); @@ -102,7 +106,8 @@ public class CalibrationServiceImpl implements CalibrationService { 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) { + SiteCalibrationService siteCalibrationService, SyntheticService syntheticService, NotificationService notificationService, DatabaseCleaningService cleaningService, + ConfigurationService configService) { this.waveformService = waveformService; this.peakVelocityMeasurementsService = peakVelocityMeasurementsService; this.sharedParametersService = sharedParametersService; @@ -117,6 +122,7 @@ public CalibrationServiceImpl(WaveformService waveformService, PeakVelocityMeasu this.syntheticService = syntheticService; this.notificationService = notificationService; this.cleaningService = cleaningService; + this.configService = configService; } @Override @@ -134,14 +140,17 @@ public boolean start(Boolean autoPickingEnabled) { Map frequencyBandParameterMap = mapParamsToFrequencyBands(sharedParametersService.findAll()); final Map snrFilterMap = new HashMap<>(frequencyBandParameterMap); + notificationService.post(new CalibrationStatusEvent(id, CalibrationStatusEvent.Status.PEAK_STARTING)); List stacks = waveformService.getAllActiveStacks(); // In general each step produces output that the next step // consumes + VelocityConfiguration velocityConfig = configService.getVelocityConfiguration(); + // 1) Compute the peak velocity, amplitude, and SNR values // for the given coda stacks using theoretical group velocities // to cut the windows for noise and SN/LG arrival - Collection velocityMeasurements = peakVelocityMeasurementsService.measureVelocities(stacks); + Stream velocityMeasurements = peakVelocityMeasurementsService.measureVelocities(stacks, velocityConfig); // First step is to clean up all the intermediary results if // they exist. This is as wildly not-thread-safe as you might @@ -151,7 +160,7 @@ public boolean start(Boolean autoPickingEnabled) { // We want to filter out the ones that don't pass the user's // SNR threshold - List snrFilteredVelocity = velocityMeasurements.stream().filter(vel -> { + List snrFilteredVelocity = velocityMeasurements.parallel().filter(vel -> { boolean valid = false; if (vel.getWaveform() != null) { FrequencyBand fb = new FrequencyBand(vel.getWaveform().getLowFrequency(), vel.getWaveform().getHighFrequency()); @@ -164,6 +173,8 @@ public boolean start(Boolean autoPickingEnabled) { // Now save the new ones we just calculated peakVelocityMeasurementsService.save(snrFilteredVelocity); + notificationService.post(new CalibrationStatusEvent(id, CalibrationStatusEvent.Status.SHAPE_STARTING)); + // 2) Compute the shape parameters describing each stack // (Velocity V0-2, Beta B0-2, Gamma G0-2) and then fit // models to each of those parameters for each frequency band that can be used @@ -193,18 +204,27 @@ public boolean start(Boolean autoPickingEnabled) { List spectra = spectraMeasurementService.measureSpectra( syntheticGenerationService.generateSynthetics(stacks, frequencyBandParameterMap), frequencyBandParameterMap, - autoPickingEnabled); + autoPickingEnabled, + velocityConfig); + + notificationService.post(new CalibrationStatusEvent(id, CalibrationStatusEvent.Status.PATH_STARTING)); // 4) For each event in the data set find all stations that // recorded the event, then compute what the estimated path // effect correction needs to be for each frequency band - frequencyBandParameterMap = pathCalibrationService.measurePathCorrections(spectraByFrequencyBand(spectra), frequencyBandParameterMap); + frequencyBandParameterMap = pathCalibrationService.measurePathCorrections(spectraByFrequencyBand(spectra), frequencyBandParameterMap, velocityConfig); frequencyBandParameterMap = mapParamsToFrequencyBands(sharedParametersService.save(frequencyBandParameterMap.values())); // 5) Measure the amplitudes again but this time we can // compute ESH path corrected values - spectra = spectraMeasurementService.measureSpectra(syntheticGenerationService.generateSynthetics(stacks, frequencyBandParameterMap), frequencyBandParameterMap, autoPickingEnabled); + spectra = spectraMeasurementService.measureSpectra( + syntheticGenerationService.generateSynthetics(stacks, frequencyBandParameterMap), + frequencyBandParameterMap, + autoPickingEnabled, + velocityConfig); + + notificationService.post(new CalibrationStatusEvent(id, CalibrationStatusEvent.Status.SITE_STARTING)); // 6) Now using those path correction values plus a list of // trusted Mw/spectra measurements for some subset of events @@ -219,12 +239,14 @@ public boolean start(Boolean autoPickingEnabled) { collectByEvid(referenceMwService.findAll()), frequencyBandParameterMap, PICK_TYPES.LG); + // 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, autoPickingEnabled, + velocityConfig, frequencyBandSiteParameterMap); log.info("Calibration complete at {}", LocalDateTime.now()); diff --git a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/ConfigurationServiceImpl.java b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/ConfigurationServiceImpl.java new file mode 100644 index 00000000..c8dc7991 --- /dev/null +++ b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/ConfigurationServiceImpl.java @@ -0,0 +1,66 @@ +/* +* 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; + +import javax.persistence.EntityManager; + +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.VelocityConfiguration; +import gov.llnl.gnem.apps.coda.calibration.model.messaging.GvDataChangeEvent; +import gov.llnl.gnem.apps.coda.calibration.repository.VelocityConfigurationRepository; +import gov.llnl.gnem.apps.coda.calibration.service.api.ConfigurationService; +import gov.llnl.gnem.apps.coda.common.service.api.NotificationService; + +@Service +@Transactional +public class ConfigurationServiceImpl implements ConfigurationService { + + private EntityManager em; + private VelocityConfigurationRepository repository; + private NotificationService notificationService; + + @Autowired + public ConfigurationServiceImpl(EntityManager em, VelocityConfigurationRepository repository, NotificationService notificationService) { + this.em = em; + this.repository = repository; + this.notificationService = notificationService; + } + + @Override + public VelocityConfiguration update(VelocityConfiguration entry) { + VelocityConfiguration mergedEntry; + if (entry.getId() != null) { + mergedEntry = repository.findById(entry.getId()).get(); + } else { + mergedEntry = repository.findFirstByOrderById(); + } + if (mergedEntry != null) { + mergedEntry = mergedEntry.merge(entry); + } else { + mergedEntry = entry; + } + notificationService.post(new GvDataChangeEvent()); + return repository.saveAndFlush(mergedEntry); + } + + @Override + public VelocityConfiguration getVelocityConfiguration() { + VelocityConfiguration res = repository.findFirstByOrderById(); + em.detach(res); + return res; + } +} 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 873f27ad..87b4fa97 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 @@ -41,11 +41,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import gov.llnl.gnem.apps.coda.calibration.model.domain.PathCalibrationMeasurement; import gov.llnl.gnem.apps.coda.calibration.model.domain.SpectraMeasurement; +import gov.llnl.gnem.apps.coda.calibration.model.domain.VelocityConfiguration; import gov.llnl.gnem.apps.coda.calibration.service.api.PathCalibrationMeasurementService; import gov.llnl.gnem.apps.coda.calibration.service.api.PathCalibrationService; import gov.llnl.gnem.apps.coda.calibration.service.impl.processing.SpectraCalculator; @@ -92,11 +94,15 @@ public class Joint1DPathCorrection implements PathCalibrationService { private double q = Math.log10(500.0); private double xtrans = Math.log10(Math.log10(2.0)); private double xcross = Math.log10(500.0); - private double vphase = 3.5; - private final double efact = Math.log10(Math.E); + @Value("#{'${path.phase-speed-kms:${phase.phase-speed-kms:${phase-speed-kms:3.5}}}'}") + private double vphase; + + private static final double efact = Math.log10(Math.E); private PathCalibrationMeasurementService pathCalibrationMeasurementService; private List paramPoints; + @Value(value = "${path.use-aggressive-opt:true}") + private boolean agressiveOptimization; @Autowired public Joint1DPathCorrection(SpectraCalculator spectraCalc, PathCalibrationMeasurementService pathCalibrationMeasurementService) { @@ -106,14 +112,21 @@ public Joint1DPathCorrection(SpectraCalculator spectraCalc, PathCalibrationMeasu @Override public Map measurePathCorrections(Map> dataByFreqBand, - Map frequencyBandParameters) { + Map frequencyBandParameters, VelocityConfiguration velConf) { + if (velConf != null) { + Double phase = velConf.getPhaseSpeedInKms(); + if (phase != null && phase != 0.0) { + vphase = phase; + } + } + List measurements = new ArrayList<>(); Map pathCorrectedFrequencyBandParameters = new HashMap<>(); Map>> dataMappedToEventAndStation = removeSingleStationOrFewerEntries(mapToEventAndStation(dataByFreqBand)); - for (Entry frequencyBandParams : frequencyBandParameters.entrySet()) { + frequencyBandParameters.entrySet().parallelStream().forEach(frequencyBandParams -> { SharedFrequencyBandParameters pathCorrectedParams = frequencyBandParams.getValue(); @@ -156,6 +169,7 @@ public Map measurePathCorrections( dataCount++; } } + dataCount = dataCount > 0 ? dataCount : 1; totalDataCount = dataCount; // Common terms + one site term for each station @@ -201,7 +215,7 @@ public Map measurePathCorrections( Double initialResidual = Math.pow(costFunction(freqBandData, dataMap, distanceMap, stationIdxMap, frequencyBand, optimizationParams) / totalDataCount, 2.0); log.info("Band {} initial cost: {}", frequencyBand.getLowFrequency(), initialResidual); - List paramPoints = makeParamPoints(NUM_TERMS, optimizationLowBounds, optimizationHighBounds); + List paramPoints = makeParamPoints(NUM_TERMS, agressiveOptimization, optimizationLowBounds, optimizationHighBounds); PointValuePair optimizedResult = IntStream.range(0, paramPoints.size()).parallel().mapToObj(i -> { ConvergenceChecker convergenceChecker = new SimpleValueChecker(TOLERANCE, TOLERANCE); CMAESOptimizer optimizer = new CMAESOptimizer(1000000, TOLERANCE, true, 0, 10, new MersenneTwister(), true, convergenceChecker); @@ -209,17 +223,16 @@ public Map measurePathCorrections( MultivariateFunction prediction = new ESHPathMultivariate(freqBandData, dataMap, distanceMap, stationIdxMap, frequencyBand); PointValuePair opt = null; try { - opt = optimizer.optimize( - new MaxEval(1000000), - new ObjectiveFunction(prediction), - GoalType.MINIMIZE, - new SimpleBounds(optimizationLowBounds, optimizationHighBounds), - new InitialGuess(paramPoints.get(i)), - new CMAESOptimizer.PopulationSize(POP_SIZE), - new CMAESOptimizer.Sigma(sigmaArray)); + opt = optimizer.optimize(new MaxEval(1000000), + new ObjectiveFunction(prediction), + GoalType.MINIMIZE, + new SimpleBounds(optimizationLowBounds, optimizationHighBounds), + new InitialGuess(paramPoints.get(i)), + new CMAESOptimizer.PopulationSize(POP_SIZE), + new CMAESOptimizer.Sigma(sigmaArray)); } catch (TooManyEvaluationsException e) { } - log.info("frequency: {}, iteration: {}, residual: {}", frequencyBand.getLowFrequency(), i, opt.getValue()); + log.debug("frequency: {}, iteration: {}, residual: {}", frequencyBand.getLowFrequency(), i, opt.getValue()); return opt; }).filter(Objects::nonNull).reduce((a, b) -> Double.compare(a.getValue(), b.getValue()) <= 0 ? a : b).orElse(null); @@ -248,7 +261,7 @@ public Map measurePathCorrections( pathCorrectedParams.setXt(Math.pow(10.0, Math.pow(10.0, optimizationParams[XTRANS_IDX]))); pathCorrectedFrequencyBandParameters.put(frequencyBand, pathCorrectedParams); } - } + }); pathCalibrationMeasurementService.deleteAll(); pathCalibrationMeasurementService.save(measurements); @@ -370,13 +383,18 @@ public double costFunction(Map> evidStaD * I'm making the pretty big assumption these are ordered such * that bound0 is the min and boundN is the max. * @return + * @throws IllegalStateException + * if optimizationBounds.length < 2 */ - private List makeParamPoints(int numberOfTerms, double[]... optimizationBounds) { + private List makeParamPoints(int numberOfTerms, boolean agressiveOptimization, double[]... optimizationBounds) { if (paramPoints != null && !paramPoints.isEmpty() && paramPoints.get(0).length == numberOfTerms) { return paramPoints; } + if (optimizationBounds.length < 2) { + throw new IllegalStateException("Optmization bounds needs at least two entries for the low and high boundary conditions. Got: " + optimizationBounds.length); + } - int terms = numberOfTerms * numberOfTerms + 1; + int terms = (int) (Math.pow(numberOfTerms, optimizationBounds.length)) + 1; List params = new ArrayList<>(terms); int[] selectionIndex = new int[numberOfTerms]; double[] param = optimizationBounds[0].clone(); @@ -388,14 +406,21 @@ private List makeParamPoints(int numberOfTerms, double[]... optimizati params.add(param.clone()); param = optimizationBounds[0].clone(); - for (int i = 1; i < terms; i++) { - for (int j = 0; j < selectionIndex.length; j++) { - param[j] = optimizationBounds[selectionIndex[j]][j]; + if (agressiveOptimization) { + for (int i = 1; i < terms; i++) { + for (int j = 0; j < selectionIndex.length; j++) { + param[j] = optimizationBounds[selectionIndex[j]][j]; + } + params.add(param.clone()); + param = optimizationBounds[0].clone(); + selectionIndex = nextIndex(selectionIndex, optimizationBounds.length); } - params.add(param.clone()); - param = optimizationBounds[0].clone(); - selectionIndex = nextIndex(selectionIndex, optimizationBounds.length); + } else { + params.add(param); + param = optimizationBounds[optimizationBounds.length - 1].clone(); + params.add(param); } + paramPoints = params; return paramPoints; } diff --git a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/MdacParametersFiServiceImpl.java b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/MdacParametersFiServiceImpl.java index ec9bd485..603cfc54 100644 --- a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/MdacParametersFiServiceImpl.java +++ b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/MdacParametersFiServiceImpl.java @@ -129,7 +129,7 @@ public MdacParametersFI update(MdacParametersFI entry) { mergedEntry = mdacParametersRepository.findFirstByOrderById(); } if (mergedEntry != null) { - mergedEntry = mergedEntry.mergeNonNullOrEmptyFields(entry); + mergedEntry = mergedEntry.merge(entry); } else { mergedEntry = entry; } 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 dc6bbf08..98a770d4 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 @@ -15,73 +15,74 @@ package gov.llnl.gnem.apps.coda.calibration.service.impl; import java.util.List; +import java.util.stream.Collectors; 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.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.repository.MeasuredMwsRepository; +import gov.llnl.gnem.apps.coda.calibration.repository.ReferenceMwParametersRepository; import gov.llnl.gnem.apps.coda.calibration.service.api.MeasuredMwsService; +import gov.llnl.gnem.apps.coda.common.service.api.WaveformService; @Service @Transactional public class MeasuredMwsServiceImpl implements MeasuredMwsService { private MeasuredMwsRepository measuredMwsRepository; - - public MeasuredMwsRepository getMeasuredMwsRepository() { - return measuredMwsRepository; - } - - public void setMeasuredMwsRepository(MeasuredMwsRepository measuredMwsRepository) { - this.measuredMwsRepository = measuredMwsRepository; - } + private ReferenceMwParametersRepository referenceMwsRepository; + private WaveformService eventRepository; @Autowired - public MeasuredMwsServiceImpl(MeasuredMwsRepository measuredMwsRepository) { - setMeasuredMwsRepository(measuredMwsRepository); + public MeasuredMwsServiceImpl(MeasuredMwsRepository measuredMwsRepository, ReferenceMwParametersRepository referenceMwsRepository, WaveformService eventRepository) { + this.measuredMwsRepository = measuredMwsRepository; + this.referenceMwsRepository = referenceMwsRepository; + this.eventRepository = eventRepository; } @Transactional public void delete(MeasuredMwParameters MeasuredMwParameters) { - getMeasuredMwsRepository().delete(MeasuredMwParameters); + measuredMwsRepository.delete(MeasuredMwParameters); } @Transactional public List save(Iterable entities) { - return getMeasuredMwsRepository().saveAll(entities); + return measuredMwsRepository.saveAll(entities); } @Transactional public void delete(Iterable ids) { - List toDelete = getMeasuredMwsRepository().findAllById(ids); - getMeasuredMwsRepository().deleteInBatch(toDelete); + List toDelete = measuredMwsRepository.findAllById(ids); + measuredMwsRepository.deleteInBatch(toDelete); } @Transactional public MeasuredMwParameters save(MeasuredMwParameters entity) { - return getMeasuredMwsRepository().save(entity); + return measuredMwsRepository.save(entity); } public MeasuredMwParameters findOne(Long id) { - return getMeasuredMwsRepository().findOneDetached(id); + return measuredMwsRepository.findOneDetached(id); } public MeasuredMwParameters findOneForUpdate(Long id) { - return getMeasuredMwsRepository().findOneDetached(id); + return measuredMwsRepository.findOneDetached(id); } public List findAll(Iterable ids) { - return getMeasuredMwsRepository().findAllById(ids); + return measuredMwsRepository.findAllById(ids); } public List findAll() { - return getMeasuredMwsRepository().findAll(); + return measuredMwsRepository.findAll(); } public long count() { - return getMeasuredMwsRepository().count(); + return measuredMwsRepository.count(); } public Class getEntityType() { @@ -90,10 +91,27 @@ public Class getEntityType() { @Override public void deleteAll() { - getMeasuredMwsRepository().deleteAllInBatch(); + measuredMwsRepository.deleteAllInBatch(); } public Class getIdType() { return Long.class; } + + @Override + public List findAllDetails() { + List measured = measuredMwsRepository.findAll(); + List reference = referenceMwsRepository.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())); + }).collect(Collectors.toList()); + + 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()))) + .collect(Collectors.toList())); + + return details; + } } diff --git a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/PeakVelocityMeasurementServiceImpl.java b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/PeakVelocityMeasurementServiceImpl.java index 36e7b38b..72b0e25f 100644 --- a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/PeakVelocityMeasurementServiceImpl.java +++ b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/PeakVelocityMeasurementServiceImpl.java @@ -14,8 +14,8 @@ */ package gov.llnl.gnem.apps.coda.calibration.service.impl; -import java.util.Collection; import java.util.List; +import java.util.stream.Stream; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -23,6 +23,7 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.PeakVelocityMeasurement; import gov.llnl.gnem.apps.coda.calibration.model.domain.PeakVelocityMeasurementMetadata; +import gov.llnl.gnem.apps.coda.calibration.model.domain.VelocityConfiguration; import gov.llnl.gnem.apps.coda.calibration.repository.PeakVelocityMeasurementRepository; import gov.llnl.gnem.apps.coda.calibration.service.api.PeakVelocityMeasurementService; import gov.llnl.gnem.apps.coda.calibration.service.impl.processing.MaxVelocityCalculator; @@ -106,8 +107,8 @@ public List findAll(Iterable ids) { } @Override - public Collection measureVelocities(List allStacks) { - return velocityCalc.computeMaximumVelocity(allStacks); + public Stream measureVelocities(List allStacks, VelocityConfiguration velocityConfiguration) { + return velocityCalc.computeMaximumVelocity(allStacks, velocityConfiguration); } @Override 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 aed68753..070696ff 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 @@ -91,7 +91,7 @@ public Map measureShapes(Collectio // don't already have F-picks in this set if (autoPickingEnabled) { velocityMeasurements = autoPickWaveforms(velocityMeasurements, frequencyBandParameters); - velocityMeasurements.forEach(v -> pickService.save(waveService.save(v.getWaveform()).getAssociatedPicks())); + velocityMeasurements = velocityMeasurements.parallelStream().map(v -> v.setWaveform(waveService.save(v.getWaveform()))).collect(Collectors.toList()); } // 2) Filter to only measurements with an end pick @@ -108,7 +108,7 @@ public Map measureShapes(Collectio shapeMeasurementService.deleteAll(); Map> frequencyBandShapeMeasurementMap = shapeMeasurementService.save(betaAndGammaMeasurements) - .stream() + .parallelStream() .filter(meas -> meas.getWaveform() != null) .collect( Collectors.groupingBy( @@ -211,7 +211,6 @@ private Collection autoPickWaveforms(final Collection

> filterMeasurementsToEndPickedOnly(Collection velocityMeasurements) { return velocityMeasurements.parallelStream().filter(vel -> vel.getWaveform() != null).filter(vel -> vel.getWaveform().getAssociatedPicks() != null).map(vel -> { - Optional pick = vel.getWaveform().getAssociatedPicks().stream().filter(p -> PICK_TYPES.F.name().equalsIgnoreCase(p.getPickType())).findFirst(); if (pick.isPresent()) { return new AbstractMap.SimpleEntry<>(vel, pick.get()); diff --git a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/ShapeMeasurementServiceImpl.java b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/ShapeMeasurementServiceImpl.java index 906852e3..e9d5b3e0 100644 --- a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/ShapeMeasurementServiceImpl.java +++ b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/ShapeMeasurementServiceImpl.java @@ -21,6 +21,7 @@ import org.springframework.stereotype.Service; import gov.llnl.gnem.apps.coda.calibration.model.domain.ShapeMeasurement; +import gov.llnl.gnem.apps.coda.calibration.model.domain.ShapeMeasurementMetadata; import gov.llnl.gnem.apps.coda.calibration.repository.ShapeMeasurementRepository; import gov.llnl.gnem.apps.coda.calibration.service.api.ShapeMeasurementService; @@ -88,4 +89,14 @@ public void deleteAll() { public ShapeMeasurement findOneByWaveformId(Long waveformId) { return Optional.ofNullable(shapeMeasurementRepository.findOneByWaveformId(waveformId)).orElseGet(ShapeMeasurement::new); } + + @Override + public List findAllMetadataOnly() { + return shapeMeasurementRepository.findAllMetadataOnly(); + } + + @Override + public ShapeMeasurementMetadata findOneMetadataByWaveformId(Long waveformId) { + return shapeMeasurementRepository.findOneMetadataByWaveformId(waveformId); + } } diff --git a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/SiteCalibrationServiceImpl.java b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/SiteCalibrationServiceImpl.java index 959901b0..cfa4cc78 100644 --- a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/SiteCalibrationServiceImpl.java +++ b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/SiteCalibrationServiceImpl.java @@ -87,7 +87,7 @@ public Map> measureSite //Result Map> siteCorrections = new HashMap<>(); - //0) Determine if we have a RefMW in the dataset with a GT stress drop + //0) Determine if we have a RefMW in the dataset with a GT stress //0-1A) If yes then omit everything above the corner frequency for MDAC model only events //0-1B) Add it to the GT spectra event map //0-1C) Weight the Mw fit for that event 1.0 at all bands @@ -107,11 +107,8 @@ public Map> measureSite if (refMw != null) { double mw = refMw.getRefMw(); MdacParametersFI mdacFiEntry = new MdacParametersFI(mdacFI); - if (refMw.getStressDropInMpa() != null && refMw.getStressDropInMpa() != 0.0) { - // If we know a MPA stress drop for this reference - // event we want to use stress instead of apparent - // stress so we set Psi == 0.0 to use Sigma as stress drop - mdacFiEntry.setSigma(refMw.getStressDropInMpa()); + if (refMw.getRefApparentStressInMpa() != null && refMw.getRefApparentStressInMpa() != 0.0) { + mdacFiEntry.setSigma(refMw.getRefApparentStressInMpa()); mdacFiEntry.setPsi(0.0); weightFunctionMapByEvent.put(evid, this::noWeights); } 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 b3c75b00..29b553bc 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 @@ -26,6 +26,8 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteFrequencyBandParameters; 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.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; @@ -46,11 +48,12 @@ public class SpectraMeasurementServiceImpl implements SpectraMeasurementService private SpectraMeasurementRepository spectraRepo; private ReferenceMwParametersRepository referenceEventRepo; - + private MeasuredMwsRepository measuredEventRepo; @Autowired - public SpectraMeasurementServiceImpl(SpectraMeasurementRepository spectraRepo, SpectraCalculator spectraCalc,MeasuredMwsRepository measuredEventRepo, ReferenceMwParametersRepository referenceEventRepo) { + public SpectraMeasurementServiceImpl(SpectraMeasurementRepository spectraRepo, SpectraCalculator spectraCalc, MeasuredMwsRepository measuredEventRepo, + ReferenceMwParametersRepository referenceEventRepo) { this.spectraRepo = spectraRepo; this.spectraCalc = spectraCalc; this.measuredEventRepo = measuredEventRepo; @@ -72,19 +75,30 @@ public List findAll(Iterable ids) { return spectraRepo.findAllById(ids); } + @Override + public List findAllMetadataOnly(Iterable ids) { + return spectraRepo.findAllMetadataById(ids); + } + @Override public List findAll() { return spectraRepo.findAll(); } + @Override + public List findAllMetadataOnly() { + return spectraRepo.findAllMetadataOnly(); + } + @Override public long count() { return spectraRepo.count(); } @Override - public List measureSpectra(List generatedSynthetics, Map frequencyBandParameterMap, Boolean autoPickingEnabled) { - List measurements = spectraCalc.measureAmplitudes(generatedSynthetics, frequencyBandParameterMap, autoPickingEnabled); + public List measureSpectra(List generatedSynthetics, Map frequencyBandParameterMap, Boolean autoPickingEnabled, + VelocityConfiguration velocityConfig) { + List measurements = spectraCalc.measureAmplitudes(generatedSynthetics, frequencyBandParameterMap, autoPickingEnabled, velocityConfig); if (!measurements.isEmpty()) { spectraRepo.deleteAllInBatch(); measurements = spectraRepo.saveAll(measurements); @@ -94,8 +108,8 @@ public List measureSpectra(List generatedSynt @Override public List measureSpectra(List generatedSynthetics, Map frequencyBandParameterMap, Boolean autoPickingEnabled, - Map> frequencyBandSiteParameterMap) { - List measurements = spectraCalc.measureAmplitudes(generatedSynthetics, frequencyBandParameterMap, autoPickingEnabled, frequencyBandSiteParameterMap); + VelocityConfiguration velocityConfig, Map> frequencyBandSiteParameterMap) { + List measurements = spectraCalc.measureAmplitudes(generatedSynthetics, frequencyBandParameterMap, autoPickingEnabled, velocityConfig, frequencyBandSiteParameterMap); if (!measurements.isEmpty()) { spectraRepo.deleteAllInBatch(); measurements = spectraRepo.saveAll(measurements); @@ -115,11 +129,11 @@ public Spectra computeSpectraForEventId(String eventId, List freq @Override public Spectra getFitSpectraForEventId(String eventId, List frequencyBands, PICK_TYPES selectedPhase) { - Spectra fitSpectra = new Spectra(); - MeasuredMwParameters event = measuredEventRepo.findOneByEventId(eventId); - if (event != null) { - fitSpectra = spectraCalc.computeFitSpectra(event, frequencyBands, selectedPhase); - } - return fitSpectra; + Spectra fitSpectra = new Spectra(); + MeasuredMwParameters event = measuredEventRepo.findOneByEventId(eventId); + if (event != null) { + fitSpectra = spectraCalc.computeFitSpectra(event, frequencyBands, selectedPhase); } + return fitSpectra; + } } diff --git a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/SyntheticCodaGenerationServiceImpl.java b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/SyntheticCodaGenerationServiceImpl.java index 245019a5..5d431cac 100644 --- a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/SyntheticCodaGenerationServiceImpl.java +++ b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/SyntheticCodaGenerationServiceImpl.java @@ -98,7 +98,7 @@ private SyntheticCoda createSyntheticFromWaveform(Waveform sourceWaveform, Share int npts = seis.getNsamp(); //TODO: Set synthetic end time to max length of measurement (+1?) for FB if it's set and > 0.0 - Double[] Ac = new Double[npts]; + double[] Ac = new double[npts]; for (int ii = 0; ii < Ac.length; ii++) { // t is relative to the phase start time - note t=0 is a @@ -116,7 +116,7 @@ private SyntheticCoda createSyntheticFromWaveform(Waveform sourceWaveform, Share synth.setMeasuredV(vr); synth.setMeasuredB(br); synth.setMeasuredG(gr); - + return synth; } catch (IllegalArgumentException e) { log.warn("Error attempting to cut seismogram for Synthetic generation {}; {}", sourceWaveform, e.getMessage()); diff --git a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/CalibrationCurveFitter.java b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/CalibrationCurveFitter.java index 55c0e2c8..26fd0082 100755 --- a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/CalibrationCurveFitter.java +++ b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/CalibrationCurveFitter.java @@ -138,17 +138,7 @@ public EnvelopeFit fitCodaCMAES(final float[] segment) { if (Double.isNaN(startIntercept)) { startIntercept = ThreadLocalRandom.current().nextDouble(minInt, maxInt); startBeta = minBeta; - } - - if (startIntercept > maxInt) { - startIntercept = maxInt; - } else if (startIntercept < minInt) { - startIntercept = minInt; - } - - if (startBeta > maxBeta) { - startBeta = maxBeta; - } else if (startBeta < minBeta) { + } else if (startBeta > maxBeta || startBeta < minBeta) { startBeta = minBeta; } @@ -158,7 +148,7 @@ public EnvelopeFit fitCodaCMAES(final float[] segment) { new CMAESOptimizer.Sigma(new double[] { 0.5, 0.05, 0.05 }), convergenceChecker, 50, - new SimpleBounds(new double[] { minInt, minGamma, minBeta }, new double[] { maxInt, maxGamma, maxBeta })); + new SimpleBounds(new double[] { -Double.MAX_VALUE, minGamma, minBeta }, new double[] { Double.MAX_VALUE, maxGamma, maxBeta })); double[] curve = bestResult.getKey(); fit.setIntercept(curve[0]); @@ -426,9 +416,9 @@ public double[] gridSearchCodaV(final List> velocityDistan sum = lossFunction(sum, velocity, predictedVel); } return new Double[] { v0, v1, v2, sum }; - }).min((o1, o2) -> o1[3] > o2[3] ? 1 : -1).orElse(baseResult); - }).min((o1, o2) -> o1[3] > o2[3] ? 1 : -1).orElse(baseResult); - }).min((o1, o2) -> o1[3] > o2[3] ? 1 : -1).orElse(baseResult)); + }).min((o1, o2) -> o1[3] > o2[3] ? 1 : -1).orElseGet(() -> baseResult); + }).min((o1, o2) -> o1[3] > o2[3] ? 1 : -1).orElseGet(() -> baseResult); + }).min((o1, o2) -> o1[3] > o2[3] ? 1 : -1).orElseGet(() -> baseResult)); } public double[] gridSearchCodaB(List> betaDistancePairs) { @@ -459,9 +449,9 @@ public double[] gridSearchCodaB(final List> betaDistancePa sum = lossFunction(sum, beta, bb); } return new Double[] { b0, b1, b2, sum }; - }).min((o1, o2) -> o1[3] > o2[3] ? 1 : -1).orElse(baseResult); - }).min((o1, o2) -> o1[3] > o2[3] ? 1 : -1).orElse(baseResult); - }).min((o1, o2) -> o1[3] > o2[3] ? 1 : -1).orElse(baseResult)); + }).min((o1, o2) -> o1[3] > o2[3] ? 1 : -1).orElseGet(() -> baseResult); + }).min((o1, o2) -> o1[3] > o2[3] ? 1 : -1).orElseGet(() -> baseResult); + }).min((o1, o2) -> o1[3] > o2[3] ? 1 : -1).orElseGet(() -> baseResult)); } public double[] gridSearchCodaG(List> gammaDistancePairs) { @@ -497,9 +487,9 @@ public double[] gridSearchCodaG(final List> gammaDistanceP } return new Double[] { g0, g1, g2, sum }; - }).min((o1, o2) -> o1[3] > o2[3] ? 1 : -1).orElse(baseResult); - }).min((o1, o2) -> o1[3] > o2[3] ? 1 : -1).orElse(baseResult); - }).min((o1, o2) -> o1[3] > o2[3] ? 1 : -1).orElse(baseResult)); + }).min((o1, o2) -> o1[3] > o2[3] ? 1 : -1).orElseGet(() -> baseResult); + }).min((o1, o2) -> o1[3] > o2[3] ? 1 : -1).orElseGet(() -> baseResult); + }).min((o1, o2) -> o1[3] > o2[3] ? 1 : -1).orElseGet(() -> baseResult)); } /** @@ -517,17 +507,15 @@ public double[] gridSearchCodaG(final List> gammaDistanceP */ public Map fitAllVelocity(Map> velocityDistancePairsFreqMap, Map freqBandMap) { - for (Entry> velDistPairs : velocityDistancePairsFreqMap.entrySet()) { - if (freqBandMap.get(velDistPairs.getKey()) != null) { - double[] curve = gridSearch( - velDistPairs.getValue().stream().map(v -> new AbstractMap.SimpleEntry(v.getVelocity(), v.getDistance())).collect(Collectors.toList()), - new ApacheGridSearchV(), - new BasicGridSearchV()); - - freqBandMap.put(velDistPairs.getKey(), freqBandMap.get(velDistPairs.getKey()).setVelocity0(curve[0]).setVelocity1(curve[1]).setVelocity2(curve[2])); - } - } + velocityDistancePairsFreqMap.entrySet().parallelStream().filter(velDistPairs -> freqBandMap.get(velDistPairs.getKey()) != null).forEach(velDistPairs -> { + double[] curve = gridSearch( + velDistPairs.getValue().stream().map(v -> new AbstractMap.SimpleEntry(v.getVelocity(), v.getDistance())).collect(Collectors.toList()), + new ApacheGridSearchV(), + new BasicGridSearchV()); + + freqBandMap.put(velDistPairs.getKey(), freqBandMap.get(velDistPairs.getKey()).setVelocity0(curve[0]).setVelocity1(curve[1]).setVelocity2(curve[2])); + }); return freqBandMap; } @@ -547,18 +535,16 @@ public Map fitAllVelocity(Map fitAllBeta(Map> betaDistancePairsFreqMap, Map freqBandMap) { - for (Entry> betaDistPairs : betaDistancePairsFreqMap.entrySet()) { - if (freqBandMap.get(betaDistPairs.getKey()) != null) { - double[] curve = gridSearch( - betaDistPairs.getValue().stream().map(v -> new AbstractMap.SimpleEntry(v.getMeasuredBeta(), v.getDistance())).collect(Collectors.toList()), - new ApacheGridSearchB(), - new BasicGridSearchB()); - // Artificially lower the intercept value, b0 to 95% - // to account for possible noise contamination causing - // too shallow decay - freqBandMap.put(betaDistPairs.getKey(), freqBandMap.get(betaDistPairs.getKey()).setBeta0(curve[0] * 1.05).setBeta1(curve[1]).setBeta2(curve[2])); - } - } + betaDistancePairsFreqMap.entrySet().parallelStream().filter(betaDistPairs -> freqBandMap.get(betaDistPairs.getKey()) != null).forEach(betaDistPairs -> { + double[] curve = gridSearch( + betaDistPairs.getValue().stream().map(v -> new AbstractMap.SimpleEntry(v.getMeasuredBeta(), v.getDistance())).collect(Collectors.toList()), + new ApacheGridSearchB(), + new BasicGridSearchB()); + // Artificially lower the intercept value, b0 to 95% + // to account for possible noise contamination causing + // too shallow decay + freqBandMap.put(betaDistPairs.getKey(), freqBandMap.get(betaDistPairs.getKey()).setBeta0(curve[0] * 1.05).setBeta1(curve[1]).setBeta2(curve[2])); + }); return freqBandMap; } @@ -579,15 +565,13 @@ public Map fitAllBeta(Map fitAllGamma(Map> gammaDistancePairsFreqMap, Map freqBandMap) { - for (Entry> gammaDistPairs : gammaDistancePairsFreqMap.entrySet()) { - if (freqBandMap.get(gammaDistPairs.getKey()) != null) { - double[] curve = gridSearch( - gammaDistPairs.getValue().stream().map(v -> new AbstractMap.SimpleEntry(v.getMeasuredGamma(), v.getDistance())).collect(Collectors.toList()), - new ApacheGridSearchG(), - new BasicGridSearchG()); - freqBandMap.put(gammaDistPairs.getKey(), freqBandMap.get(gammaDistPairs.getKey()).setGamma0(curve[0]).setGamma1(curve[1]).setGamma2(curve[2])); - } - } + gammaDistancePairsFreqMap.entrySet().parallelStream().filter(gammaDistPairs -> freqBandMap.get(gammaDistPairs.getKey()) != null).forEach(gammaDistPairs -> { + double[] curve = gridSearch( + gammaDistPairs.getValue().stream().map(v -> new AbstractMap.SimpleEntry(v.getMeasuredGamma(), v.getDistance())).collect(Collectors.toList()), + new ApacheGridSearchG(), + new BasicGridSearchG()); + freqBandMap.put(gammaDistPairs.getKey(), freqBandMap.get(gammaDistPairs.getKey()).setGamma0(curve[0]).setGamma1(curve[1]).setGamma2(curve[2])); + }); return freqBandMap; } diff --git a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/CodaSNREndTimePicker.java b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/CodaSNREndTimePicker.java index d6925592..45158be2 100644 --- a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/CodaSNREndTimePicker.java +++ b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/CodaSNREndTimePicker.java @@ -15,6 +15,7 @@ package gov.llnl.gnem.apps.coda.calibration.service.impl.processing; import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; +import org.apache.commons.math3.stat.regression.SimpleRegression; import org.springframework.stereotype.Component; import gov.llnl.gnem.apps.coda.calibration.service.api.EndTimePicker; @@ -27,7 +28,7 @@ public class CodaSNREndTimePicker implements EndTimePicker { @Override public double getEndTime(float[] waveform, double sampleRate, double startTimeEpochSeconds, int startOffset, double minLengthSec, double maxLengthSec, double minimumSnr, double noise) { - Double snrPick = getSnrEndPick(waveform, sampleRate, startOffset, minLengthSec, maxLengthSec, minimumSnr, noise, 20); + Double snrPick = getSnrEndPick(waveform, sampleRate, startOffset, minLengthSec, maxLengthSec, minimumSnr, noise, 40); Double overallPick; if (!Double.isNaN(snrPick)) { @@ -42,40 +43,60 @@ public double getEndTime(float[] waveform, double sampleRate, double startTimeEp private Double getSnrEndPick(final float[] waveform, final double sampleRate, int startOffset, final double minLengthSec, final double maxLengthSec, final double minimumSnr, final double noise, final int windowSize) { int obsWindow = (int) (windowSize * sampleRate); + int spikeSamples = (int) ((windowSize/4) * sampleRate); DescriptiveStatistics obs = new DescriptiveStatistics(obsWindow); - DescriptiveStatistics spike = new DescriptiveStatistics((int) (5 * sampleRate)); + DescriptiveStatistics spike = new DescriptiveStatistics(spikeSamples); + SimpleRegression spikeReg = new SimpleRegression(); double snrTimePick = BAD_PICK; int minSamples = (int) (minLengthSec * sampleRate); int maxSamples = (int) (maxLengthSec * sampleRate); + if (startOffset < 0) { + startOffset = 0; + } if (waveform.length > startOffset && waveform.length - startOffset > minSamples) { int stopIdx = waveform.length > maxSamples ? maxSamples : waveform.length; - if (waveform[startOffset] - minimumSnr >= noise) { + double noiseThreshold = noise + minimumSnr; + if (waveform[startOffset] >= noiseThreshold) { for (int i = startOffset; i < stopIdx; i++) { obs.addValue(waveform[i]); spike.addValue(waveform[i]); if (obs.getN() >= windowSize) { - if (obs.getMean() <= minimumSnr + noise) { + if (obs.getMean() <= noiseThreshold) { for (int j = i - obsWindow; j < i; j++) { - if (j > 0 && waveform[j] <= minimumSnr + noise) { + if (j > 0 && waveform[j] <= noiseThreshold) { snrTimePick = j / sampleRate; break; } } break; - - //TODO: 1.1 is a WAG on a data set, should try to find a better formulation that takes into account things like sample rate, window, and overall SNR - } else if (spike.getMean() > (obs.getMean() * 1.1d)) { + } else if (waveform[i] <= noiseThreshold) { + snrTimePick = i / sampleRate; break; } else { snrTimePick = (i - spike.getN()) / sampleRate; } } + if (spike.getN() >= spikeSamples) { + double[] spikeVals = spike.getValues(); + spikeReg.clear(); + for (int k = 0; k < spikeVals.length; k++) { + spikeReg.addData(k, spikeVals[k]); + } + + double spikeSlope = spikeReg.getSlope(); + if (!Double.isNaN(spikeSlope)) { + if (spikeSlope > 0.1 || (obs.getN() < windowSize && spikeSlope > 0.05)) { + break; + } + } + } } } } return snrTimePick; } + } 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 16a9175e..d9e8051b 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 @@ -14,9 +14,8 @@ */ package gov.llnl.gnem.apps.coda.calibration.service.impl.processing; -import java.util.Collection; import java.util.List; -import java.util.stream.Collectors; +import java.util.stream.Stream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,6 +23,7 @@ import org.springframework.stereotype.Component; import gov.llnl.gnem.apps.coda.calibration.model.domain.PeakVelocityMeasurement; +import gov.llnl.gnem.apps.coda.calibration.model.domain.VelocityConfiguration; import gov.llnl.gnem.apps.coda.common.model.domain.Waveform; import gov.llnl.gnem.apps.coda.common.service.util.WaveformToTimeSeriesConverter; import gov.llnl.gnem.apps.coda.common.service.util.WaveformUtils; @@ -36,19 +36,40 @@ public class MaxVelocityCalculator { private static final Logger log = LoggerFactory.getLogger(MaxVelocityCalculator.class); private WaveformToTimeSeriesConverter converter; - - // TODO: Make these configurable - final static double groupVelocity1Greater300 = 4.7; - final static double groupVelocity2Greater300 = 2.3; - final static double groupVelocity1Less300 = 3.9; - final static double groupVelocity2Less300 = 1.9; + private VelocityConfiguration velConf; @Autowired - public MaxVelocityCalculator(WaveformToTimeSeriesConverter converter) { + public MaxVelocityCalculator(VelocityConfiguration velConf, WaveformToTimeSeriesConverter converter) { this.converter = converter; + this.velConf = velConf; + } + + public Stream computeMaximumVelocity(List waveforms) { + return computeMaximumVelocity( + waveforms, + velConf.getGroupVelocity1InKmsGtDistance(), + velConf.getGroupVelocity2InKmsGtDistance(), + velConf.getGroupVelocity1InKmsLtDistance(), + velConf.getGroupVelocity2InKmsLtDistance(), + velConf.getDistanceThresholdInKm()); } - public Collection computeMaximumVelocity(List waveforms) { + public Stream computeMaximumVelocity(List waveforms, VelocityConfiguration velocityConfiguration) { + if (velocityConfiguration != null) { + return computeMaximumVelocity( + waveforms, + velocityConfiguration.getGroupVelocity1InKmsGtDistance(), + velocityConfiguration.getGroupVelocity2InKmsGtDistance(), + velocityConfiguration.getGroupVelocity1InKmsLtDistance(), + velocityConfiguration.getGroupVelocity2InKmsLtDistance(), + velocityConfiguration.getDistanceThresholdInKm()); + } else { + return computeMaximumVelocity(waveforms); + } + } + + private Stream computeMaximumVelocity(List waveforms, double gv1GtDistanceThreshold, double gv2GtDistanceThreshold, double gv1LtDistanceThreshold, + double gv2LtDistanceThreshold, double thresholdInKm) { return waveforms.stream().parallel().map(rawWaveform -> { TimeSeries waveform = converter.convert(rawWaveform); double distance = EModel.getDistanceWGS84( @@ -60,17 +81,16 @@ public Collection computeMaximumVelocity(List TimeT starttime; TimeT endtime; - if (distance >= 300) { - starttime = origintime.add(distance / groupVelocity1Greater300); - endtime = origintime.add(distance / groupVelocity2Greater300); + if (distance >= thresholdInKm) { + starttime = origintime.add(distance / gv1GtDistanceThreshold); + endtime = origintime.add(distance / gv2GtDistanceThreshold); } else { - starttime = origintime.add(distance / groupVelocity1Less300); - endtime = origintime.add(distance / groupVelocity2Less300); + starttime = origintime.add(distance / gv1LtDistanceThreshold); + endtime = origintime.add(distance / gv2LtDistanceThreshold); } // The envelope is in log10. try { - // cut the coda window portion of the seismograms waveform.cut(starttime, endtime); @@ -108,6 +128,6 @@ public Collection computeMaximumVelocity(List log.info("Unable to compute maximum velocity, this stack will be skipped. {} {}.", ill.getMessage(), rawWaveform); return new PeakVelocityMeasurement(); } - }).filter(measurement -> measurement.getWaveform() != null).collect(Collectors.toList()); + }).filter(measurement -> measurement.getWaveform() != null); } } diff --git a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/MdacCalculator.java b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/MdacCalculator.java index 48cb86cd..26275ec7 100644 --- a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/MdacCalculator.java +++ b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/MdacCalculator.java @@ -48,8 +48,6 @@ public class MdacCalculator { double[][] wcvels; // phase specific variables - double logGr; - double logQfi; double F; double logS0; double wc; @@ -203,9 +201,6 @@ private double calculateMomentRateSpectra(double frequency, double wcorner, doub * wc - the corner frequency wcp or wcs (see getCornerFrequencies). */ public void initializePhaseSpecificVariables(double distance, MdacParametersPS mdacPs, MdacParametersFI mdacFi, double M0) { - logGr = getLogGeometricalSpreading(distance, mdacPs.getDistCrit(), mdacPs.getEta()); - logQfi = getLogQfi(distance, mdacPs.getQ0(), mdacPs.getU0()); - String phase = mdacPs.getPhase(); if (PICK_TYPES.PN.getPhase().equals(phase) || PICK_TYPES.PG.getPhase().equals(phase)) { diff --git a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/MdacCalculatorService.java b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/MdacCalculatorService.java index c0a7a532..5ec59d98 100644 --- a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/MdacCalculatorService.java +++ b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/MdacCalculatorService.java @@ -67,12 +67,12 @@ public double[] calculateMdacSourceSpectra(MdacParametersPS psEntry, MdacParamet * @param phase * The phase to use for the MDAC calculation. Should be one of * the phases in {@link PICK_TYPES}. - * @param stressDrop - * Stress drop in MPA to use. May be null to use the MDAC - * parameters instead. Otherwise Psi=0 and Sigma=stressDrop + * @param stress + * Apparent stress in MPA to use. May be null to use the MDAC + * parameters instead. Otherwise Psi=0 and Sigma=stress * @return logAmp In Dyne-CM */ - public double calculateMdacAmplitudeForMw(MdacParametersPS psEntry, MdacParametersFI fiEntry, double Mw, double frequency, PICK_TYPES phase, Double stressDrop) { + public double calculateMdacAmplitudeForMw(MdacParametersPS psEntry, MdacParametersFI fiEntry, double Mw, double frequency, PICK_TYPES phase, Double stress) { // M0 in N-m units double M0 = MdacCalculator.DYNE_CM_TO_NEWTON_M * Math.pow(10, 1.5 * (Mw + 10.73)); @@ -91,8 +91,8 @@ public double calculateMdacAmplitudeForMw(MdacParametersPS psEntry, MdacParamete mdc.initializePhaseSpecificVariables(distance, psEntry, fiEntry, M0); //FIXME: Use the calibrations phase for this! - if (stressDrop != null) { - mdacM0 = mdc.calculateMomentRateSpectra(frequency, M0, stressDrop, 0.0, phase); + if (stress != null) { + mdacM0 = mdc.calculateMomentRateSpectra(frequency, M0, stress, 0.0, phase); } else { mdacM0 = mdc.calculateMomentRateSpectra(frequency, M0, fiEntry.getSigma(), fiEntry.getPsi(), phase); } @@ -129,7 +129,7 @@ public double getM0(double Mw) { return MdacCalculator.mwToM0(Mw); } - public double getMwInDyne(double testMw) { + public double getMwInDyne(double testMw) { return MdacCalculator.mwInDyne(testMw); } } diff --git a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/SpectraCalculator.java b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/SpectraCalculator.java index 8014338c..5fb867b5 100644 --- a/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/SpectraCalculator.java +++ b/calibration-service/calibration-service-impl/src/main/java/gov/llnl/gnem/apps/coda/calibration/service/impl/processing/SpectraCalculator.java @@ -50,6 +50,7 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteFrequencyBandParameters; 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.VelocityConfiguration; import gov.llnl.gnem.apps.coda.calibration.service.api.MdacParametersFiService; import gov.llnl.gnem.apps.coda.calibration.service.api.MdacParametersPsService; import gov.llnl.gnem.apps.coda.common.model.domain.Event; @@ -69,8 +70,7 @@ @Component public class SpectraCalculator { - - private static final double LG_PHASE_SPEED_KM_S = 3.5; + private double PHASE_SPEED_KM_S; private static final Logger log = LoggerFactory.getLogger(SpectraCalculator.class); @@ -80,31 +80,38 @@ public class SpectraCalculator { private MdacParametersFiService mdacFiService; private MdacParametersPsService mdacPsService; + private static final int LOG10_M0 = 0; + private static final int MW_FIT = 1; + private static final int DATA_COUNT = 2; + private static final int RMS_FIT = 3; + private static final int STRESS = 4; + @Autowired public SpectraCalculator(WaveformToTimeSeriesConverter converter, SyntheticCodaModel syntheticCodaModel, MdacCalculatorService mdacService, MdacParametersFiService mdacFiService, - MdacParametersPsService mdacPsService) { + MdacParametersPsService mdacPsService, VelocityConfiguration velConf) { this.converter = converter; this.syntheticCodaModel = syntheticCodaModel; this.mdacService = mdacService; this.mdacFiService = mdacFiService; this.mdacPsService = mdacPsService; + this.PHASE_SPEED_KM_S = velConf.getPhaseSpeedInKms(); } - public List measureAmplitudes(List generatedSynthetics, Map frequencyBandParameterMap, - Boolean autoPickingEnabled) { - return measureAmplitudes(generatedSynthetics, frequencyBandParameterMap, autoPickingEnabled, null); + public List measureAmplitudes(List generatedSynthetics, Map frequencyBandParameterMap, Boolean autoPickingEnabled, + VelocityConfiguration velocityConfig) { + return measureAmplitudes(generatedSynthetics, frequencyBandParameterMap, autoPickingEnabled, velocityConfig, null); } public List measureAmplitudes(List generatedSynthetics, Map frequencyBandParameterMap, Boolean autoPickingEnabled, - Map> frequencyBandSiteParameterMap) { + VelocityConfiguration velocityConfig, Map> frequencyBandSiteParameterMap) { return generatedSynthetics.parallelStream() - .map(synth -> measureAmplitudeForSynthetic(synth, frequencyBandParameterMap, frequencyBandSiteParameterMap, autoPickingEnabled)) + .map(synth -> measureAmplitudeForSynthetic(synth, frequencyBandParameterMap, frequencyBandSiteParameterMap, autoPickingEnabled, velocityConfig)) .filter(Objects::nonNull) .collect(Collectors.toList()); } private SpectraMeasurement measureAmplitudeForSynthetic(SyntheticCoda synth, Map frequencyBandParameterMap, - Map> frequencyBandSiteParameterMap, Boolean autoPickingEnabled) { + Map> frequencyBandSiteParameterMap, Boolean autoPickingEnabled, VelocityConfiguration velocityConfig) { FrequencyBand frequencyBand = new FrequencyBand(synth.getSourceWaveform().getLowFrequency(), synth.getSourceWaveform().getHighFrequency()); SharedFrequencyBandParameters params = frequencyBandParameterMap.get(frequencyBand); @@ -151,7 +158,8 @@ private SpectraMeasurement measureAmplitudeForSynthetic(SyntheticCoda synth, Map params.getXc(), params.getXt(), params.getQ(), - distance); + distance, + velocityConfig); double minlength = params.getMinLength(); double maxlength = params.getMaxLength(); @@ -320,7 +328,7 @@ private boolean cutSeismograms(TimeSeries a, TimeSeries b, TimeT startTime, Time * the attenuation term * @return -log10(esh) + distance*pi*f0*log10(e) / (vphase* q) */ - public double log10ESHcorrection(double lowfreq, double highfreq, double alpha1, double alpha2, double xc, double xt, double q, double distance) { + public double log10ESHcorrection(double lowfreq, double highfreq, double alpha1, double alpha2, double xc, double xt, double q, double distance, VelocityConfiguration velocityConfig) { double log10esh = log10ESHcorrection(alpha1, alpha2, xc, xt, distance); if ((log10esh == 0.) || (q == 0.)) { @@ -329,8 +337,12 @@ public double log10ESHcorrection(double lowfreq, double highfreq, double alpha1, double f0 = Math.sqrt(lowfreq * highfreq); double efact = Math.log10(Math.E); - // TODO: make this generic w.r.t. phase - double vphase = LG_PHASE_SPEED_KM_S; + double vphase; + if (velocityConfig != null && velocityConfig.getPhaseSpeedInKms() != null && velocityConfig.getPhaseSpeedInKms() != 0.0) { + vphase = velocityConfig.getPhaseSpeedInKms(); + } else { + vphase = PHASE_SPEED_KM_S; + } double distQ = distance * Math.PI * f0 * efact / (q * vphase); // We want to return a positive number for path correction return -1 * log10esh + distQ; @@ -375,13 +387,12 @@ public Spectra computeReferenceSpectra(ReferenceMwParameters refEvent, List 0.0) { - // If we know a MPA stress drop for this reference event we want - // to use stress instead of apparent stress - // so we set Psi == 0.0 to use Sigma as stress drop - mdacFiEntry.setSigma(refEvent.getStressDropInMpa()); + if (refEvent.getRefApparentStressInMpa() != null && refEvent.getRefApparentStressInMpa() > 0.0) { + // If we know an apparent stress in MPA for this reference event we want + // to use that stress so we set Psi == 0.0 to use Sigma + mdacFiEntry.setSigma(refEvent.getRefApparentStressInMpa()); mdacFiEntry.setPsi(0.0); - amplitude = mdacService.calculateMdacAmplitudeForMw(psRows, mdacFiEntry, refEvent.getRefMw(), centerFreq, selectedPhase, refEvent.getStressDropInMpa()); + amplitude = mdacService.calculateMdacAmplitudeForMw(psRows, mdacFiEntry, refEvent.getRefMw(), centerFreq, selectedPhase, refEvent.getRefApparentStressInMpa()); } else { amplitude = mdacService.calculateMdacAmplitudeForMw(psRows, mdacFiEntry, refEvent.getRefMw(), centerFreq, selectedPhase); } @@ -394,7 +405,7 @@ public Spectra computeReferenceSpectra(ReferenceMwParameters refEvent, List Double.compare(p1.getX(), p2.getX())); - return new Spectra(SPECTRA_TYPES.REF, xyPoints, refEvent.getRefMw(), refEvent.getStressDropInMpa()); + return new Spectra(SPECTRA_TYPES.REF, xyPoints, refEvent.getRefMw(), refEvent.getRefApparentStressInMpa()); } public Spectra computeFitSpectra(MeasuredMwParameters event, List bands, PICK_TYPES selectedPhase) { @@ -406,13 +417,10 @@ public Spectra computeFitSpectra(MeasuredMwParameters event, List for (FrequencyBand band : bands) { double centerFreq = band.getLowFrequency() + (band.getHighFrequency() - band.getLowFrequency()) / 2.; double amplitude; - if (event.getStressDropInMpa() != null && event.getStressDropInMpa() > 0.0) { - // If we know a MPA stress drop for this reference event we want - // to use stress instead of apparent stress - // so we set Psi == 0.0 to use Sigma as stress drop - mdacFiEntry.setSigma(event.getStressDropInMpa()); + if (event.getApparentStressInMpa() != null && event.getApparentStressInMpa() > 0.0) { + mdacFiEntry.setSigma(event.getApparentStressInMpa()); mdacFiEntry.setPsi(0.0); - amplitude = mdacService.calculateMdacAmplitudeForMw(psRows, mdacFiEntry, event.getMw(), centerFreq, selectedPhase, event.getStressDropInMpa()); + amplitude = mdacService.calculateMdacAmplitudeForMw(psRows, mdacFiEntry, event.getMw(), centerFreq, selectedPhase, event.getApparentStressInMpa()); } else { amplitude = mdacService.calculateMdacAmplitudeForMw(psRows, mdacFiEntry, event.getMw(), centerFreq, selectedPhase); } @@ -425,7 +433,7 @@ public Spectra computeFitSpectra(MeasuredMwParameters event, List Collections.sort(xyPoints, (p1, p2) -> Double.compare(p1.getX(), p2.getX())); - return new Spectra(SPECTRA_TYPES.FIT, xyPoints, event.getMw(), event.getStressDropInMpa()); + return new Spectra(SPECTRA_TYPES.FIT, xyPoints, event.getMw(), event.getApparentStressInMpa()); } /** @@ -438,7 +446,7 @@ public List measureMws(final Map measuredMws = new ArrayList<>(); + List measuredMws = new ArrayList<>(evidMap.entrySet().size()); for (Entry> entry : evidMap.entrySet()) { Map measurements = entry.getValue(); @@ -447,13 +455,13 @@ public List measureMws(final Map measurements, final double maxMW = 8.0; final double minMPA = 0.00001; final double maxMPA = 10.00; - int dataCount = 0; + long dataCount = 0l; for (Entry meas : measurements.entrySet()) { double logAmplitude = meas.getValue().getMean(); @@ -482,7 +490,7 @@ public double[] fitMw(final Map measurements, double highFreq = meas.getKey().getHighFrequency(); double centerFreq = (highFreq + lowFreq) / 2.0; frequencyBands.put(centerFreq, logAmplitude); - dataCount++; + dataCount = dataCount + meas.getValue().getN(); } } @@ -532,14 +540,14 @@ public double value(double[] point) { // converted back into dyne-cm to match Kevin's format double testMw = optimizerResult.getPoint()[0]; // log10M0 - result[0] = Math.log10(mdacService.getMwInDyne(testMw)); - result[1] = testMw; // best Mw fit + result[LOG10_M0] = Math.log10(mdacService.getMwInDyne(testMw)); + result[MW_FIT] = testMw; // best Mw fit // this is the number of elements that have a signal measurement - result[2] = dataCount; + result[DATA_COUNT] = dataCount; // this is the rmsfit measurement - result[3] = optimizerResult.getValue(); - // this is the stress drop - result[4] = optimizerResult.getPoint()[1]; + result[RMS_FIT] = optimizerResult.getValue(); + // this is the stress + result[STRESS] = optimizerResult.getPoint()[1]; return result; } @@ -561,4 +569,4 @@ protected static double WCVRMSD(Map weightMap, HashMapio.springlets springlets-data-commons - - io.springlets - springlets-web - org.springframework.boot spring-boot-starter-web diff --git a/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/CodaCalibrationStandalone.java b/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/CodaCalibrationStandalone.java index 2992ab3c..04201a4d 100644 --- a/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/CodaCalibrationStandalone.java +++ b/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/CodaCalibrationStandalone.java @@ -110,7 +110,7 @@ public void stop() throws Exception { springContext.stop(); springContext.close(); }).get(1, TimeUnit.SECONDS); - } catch (TimeoutException | ExecutionException | CancellationException | InterruptedException e) { + } catch (TimeoutException | ExecutionException | CancellationException e) { } Platform.exit(); System.exit(0); diff --git a/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/ParameterLocalClient.java b/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/ParameterLocalClient.java index b2eb2e0e..bc14e992 100644 --- a/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/ParameterLocalClient.java +++ b/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/ParameterLocalClient.java @@ -26,6 +26,8 @@ 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.SiteFrequencyBandParameters; +import gov.llnl.gnem.apps.coda.calibration.model.domain.VelocityConfiguration; +import gov.llnl.gnem.apps.coda.calibration.service.api.ConfigurationService; import gov.llnl.gnem.apps.coda.calibration.service.api.MdacParametersFiService; import gov.llnl.gnem.apps.coda.calibration.service.api.MdacParametersPsService; import gov.llnl.gnem.apps.coda.calibration.service.api.SharedFrequencyBandParametersService; @@ -43,19 +45,21 @@ public class ParameterLocalClient implements ParameterClient { private SiteFrequencyBandParametersService siteParamsService; private MdacParametersFiService mdacFiService; private MdacParametersPsService mdacPsService; + private ConfigurationService configService; @Autowired public ParameterLocalClient(SharedFrequencyBandParametersService sharedParamsService, SiteFrequencyBandParametersService siteParamsService, MdacParametersFiService mdacFiService, - MdacParametersPsService mdacPsService) { + MdacParametersPsService mdacPsService, ConfigurationService configService) { this.sharedParamsService = sharedParamsService; this.siteParamsService = siteParamsService; this.mdacFiService = mdacFiService; this.mdacPsService = mdacPsService; + this.configService = configService; } @Override public Mono setSharedFrequencyBandParameter(SharedFrequencyBandParameters parameters) throws JsonProcessingException { - return Mono.just(Optional.ofNullable(sharedParamsService.update(parameters)).orElse(new SharedFrequencyBandParameters()).toString()); + return Mono.just(Optional.ofNullable(sharedParamsService.update(parameters)).orElseGet(() -> new SharedFrequencyBandParameters()).toString()); } @Override @@ -113,7 +117,17 @@ public Flux getFiParameters() { @Override public Mono getSharedFrequencyBandParametersForFrequency(FrequencyBand frequencyBand) { - return Mono.just(Optional.ofNullable(sharedParamsService.findByFrequencyBand(frequencyBand)).orElse(new SharedFrequencyBandParameters())); + return Mono.just(Optional.ofNullable(sharedParamsService.findByFrequencyBand(frequencyBand)).orElseGet(() -> new SharedFrequencyBandParameters())); + } + + @Override + public Mono getVelocityConfiguration() { + return Mono.just(Optional.ofNullable(configService.getVelocityConfiguration()).orElseGet(() -> new VelocityConfiguration())); + } + + @Override + public Mono updateVelocityConfiguration(VelocityConfiguration velConf) { + return Mono.just(Optional.ofNullable(configService.update(velConf)).map(v -> v.toString()).orElseGet(() -> "")); } } 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/ReferenceEventLocalClient.java index 571e2f40..a608d8c2 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/ReferenceEventLocalClient.java @@ -24,6 +24,7 @@ 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.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.service.api.MeasuredMwsService; @@ -72,4 +73,9 @@ public Mono getEvent(String eventId) { return Mono.just(event); } + @Override + public Flux getMeasuredEventDetails() { + return Flux.fromIterable(measureService.findAllDetails()).filter(Objects::nonNull).onErrorReturn(new MeasuredMwDetails()); + } + } diff --git a/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/ShapeMeasurementLocalClient.java b/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/ShapeMeasurementLocalClient.java index 89d7baa8..28f2c8b4 100644 --- a/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/ShapeMeasurementLocalClient.java +++ b/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/ShapeMeasurementLocalClient.java @@ -42,8 +42,18 @@ public Flux getMeasuredShapes() { return Flux.fromIterable(service.findAll()).onErrorReturn(new ShapeMeasurement()); } + @Override + public Flux getMeasuredShapesMetadata() { + return Flux.fromIterable(service.findAllMetadataOnly()).map(md -> new ShapeMeasurement(md)).onErrorReturn(new ShapeMeasurement()); + } + @Override public Mono getMeasuredShape(Long waveformId) { - return Mono.just(Optional.ofNullable(service.findOneByWaveformId(waveformId)).orElse(new ShapeMeasurement())).onErrorReturn(new ShapeMeasurement()); + return Mono.just(Optional.ofNullable(service.findOneByWaveformId(waveformId)).orElseGet(() -> new ShapeMeasurement())).onErrorReturn(new ShapeMeasurement()); + } + + @Override + public Mono getMeasuredShapeMetadata(Long waveformId) { + return Mono.just(service.findOneMetadataByWaveformId(waveformId)).map(md -> new ShapeMeasurement(md)).onErrorReturn(new ShapeMeasurement()); } } 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 35b197d0..7f8f3e15 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 @@ -47,13 +47,20 @@ public Flux getMeasuredSpectra() { return Flux.fromIterable(service.findAll()).onErrorReturn(new SpectraMeasurement()); } + @Override + public Flux getMeasuredSpectraMetadata() { + return Flux.fromIterable(service.findAllMetadataOnly()).map(md -> new SpectraMeasurement(md)).onErrorReturn(new SpectraMeasurement()); + } + @Override public Mono getReferenceSpectra(String eventId) { - return Mono.just(Optional.ofNullable(service.computeSpectraForEventId(eventId, sharedParamsService.getFrequencyBands(), PICK_TYPES.LG)).orElse(new Spectra())).onErrorReturn(new Spectra()); + return Mono.just(Optional.ofNullable(service.computeSpectraForEventId(eventId, sharedParamsService.getFrequencyBands(), PICK_TYPES.LG)).orElseGet(() -> new Spectra())) + .onErrorReturn(new Spectra()); } @Override public Mono getFitSpectra(String eventId) { - return Mono.just(Optional.ofNullable(service.getFitSpectraForEventId(eventId, sharedParamsService.getFrequencyBands(), PICK_TYPES.LG)).orElse(new Spectra())).onErrorReturn(new Spectra()); + return Mono.just(Optional.ofNullable(service.getFitSpectraForEventId(eventId, sharedParamsService.getFrequencyBands(), PICK_TYPES.LG)).orElseGet(() -> new Spectra())) + .onErrorReturn(new Spectra()); } } diff --git a/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/WaveformLocalClient.java b/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/WaveformLocalClient.java index 32768ff2..9adb9834 100644 --- a/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/WaveformLocalClient.java +++ b/calibration-standalone/src/main/java/gov/llnl/gnem/apps/coda/calibration/standalone/data/client/WaveformLocalClient.java @@ -47,17 +47,17 @@ public WaveformLocalClient(WaveformService service, SyntheticService synthServic @Override public Mono getWaveformFromId(Long id) { - return Mono.just(Optional.ofNullable(service.findOne(id)).orElse(new Waveform())); + return Mono.just(Optional.ofNullable(service.findOne(id)).orElseGet(() -> new Waveform())); } @Override public Mono getSyntheticFromWaveformId(Long id) { - return Mono.just(Optional.ofNullable(synthService.findOneByWaveformId(id)).orElse(new SyntheticCoda())).onErrorReturn(new SyntheticCoda()); + return Mono.just(Optional.ofNullable(synthService.findOneByWaveformId(id)).orElseGet(() -> new SyntheticCoda())).onErrorReturn(new SyntheticCoda()); } @Override public Mono postWaveform(Waveform segment) throws JsonProcessingException { - return Mono.just(Optional.ofNullable(service.update(segment)).orElse(new Waveform())); + return Mono.just(Optional.ofNullable(service.update(segment)).orElseGet(() -> new Waveform())); } @Override @@ -67,7 +67,12 @@ public Flux postWaveforms(Long sessionId, List segments) { @Override public Flux getAllStacks() { - return Flux.fromIterable(service.findAll()).onErrorReturn(new Waveform()); + return Flux.fromIterable(service.getAllStacks()).onErrorReturn(new Waveform()); + } + + @Override + public Flux getAllActiveStacks() { + return Flux.fromIterable(service.getAllActiveStacks()).onErrorReturn(new Waveform()); } @Override @@ -80,9 +85,29 @@ public Flux getWaveformsFromIds(Collection ids) { return Flux.fromIterable(service.findAll(ids)).onErrorReturn(new Waveform()); } + @Override + public Flux getWaveformMetadataFromIds(List ids) { + return Flux.fromIterable(service.findAllMetadata(ids)).onErrorReturn(new Waveform()); + } + @Override public Flux getSyntheticsFromWaveformIds(Collection ids) { return Flux.fromIterable(synthService.findAllByWaveformId(ids)).onErrorReturn(new SyntheticCoda()); } + @Override + public Flux setWaveformsActiveByIds(List selectedWaveforms, boolean active) { + return Flux.just(service.setActiveFlagForIds(selectedWaveforms, active).toString()); + } + + @Override + public Flux setWaveformsActiveByEventId(String id, boolean active) { + return Flux.just(service.setActiveFlagByEventId(id, active).toString()); + } + + @Override + public Flux setWaveformsActiveByStationName(String id, boolean active) { + return Flux.just(service.setActiveFlagByStationName(id, active).toString()); + } + } diff --git a/calibration-standalone/src/main/resources/application-file.properties b/calibration-standalone/src/main/resources/application-file.properties index ec5cb463..e1ec1361 100644 --- a/calibration-standalone/src/main/resources/application-file.properties +++ b/calibration-standalone/src/main/resources/application-file.properties @@ -1,9 +1,11 @@ +spring.output.ansi.enabled=ALWAYS +spring.jpa.open-in-view=false logging.level.root=ERROR logging.level.gov.llnl.gnem.apps.coda.*=INFO spring.datasource.driver-class-name=org.h2.Driver -spring.datasource.url=jdbc\:h2\:./codaH2.db;DB_CLOSE_DELAY\=-1;COMPRESS=TRUE;DB_CLOSE_ON_EXIT=FALSE;AUTO_SERVER=TRUE;AUTO_SERVER_PORT=9999 -spring.jpa.hibernate.naming.strategy=org.hibernate.cfg.ImprovedNamingStrategy +spring.datasource.url=jdbc:h2:./codaH2.db;DB_CLOSE_DELAY=-1;COMPRESS=TRUE;DB_CLOSE_ON_EXIT=FALSE;AUTO_SERVER=TRUE;AUTO_SERVER_PORT=9999 server.port=53921 +server.address=127.0.0.1 spring.jpa.hibernate.ddl-auto=create spring.datasource.continueOnError=true spring.datasource.hikari.connection-timeout=0 @@ -12,3 +14,4 @@ spring.jpa.properties.hibernate.jdbc.time_zone = UTC server.compression.enabled=true server.compression.mime-types=text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json server.compression.min-response-size=1024 +server.http2.enabled=true \ No newline at end of file diff --git a/calibration-standalone/src/main/resources/application.properties b/calibration-standalone/src/main/resources/application.properties index 7543b226..91c53ee0 100644 --- a/calibration-standalone/src/main/resources/application.properties +++ b/calibration-standalone/src/main/resources/application.properties @@ -1,3 +1,4 @@ +spring.output.ansi.enabled=ALWAYS webclient.basePath=localhost:53921 webclient.subscriptions=/topic/status-events,/topic/calibration-events app.height=1200 @@ -9,6 +10,7 @@ logging.level.org.springframework.web.socket.*=off logging.level.org.springframework.web.reactive.function.client.*=off spring.datasource.driver-class-name=org.h2.Driver server.port=53921 +server.address=127.0.0.1 spring.jpa.hibernate.ddl-auto=create server.ssl.key-alias=selfsigned server.ssl.key-password=changeit @@ -20,4 +22,5 @@ spring.jdbc.template.fetch-size=1000 spring.jpa.properties.hibernate.jdbc.time_zone = UTC server.compression.enabled=true server.compression.mime-types=text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json -server.compression.min-response-size=1024 \ No newline at end of file +server.compression.min-response-size=1024 +server.http2.enabled=true \ No newline at end of file diff --git a/calibration-standalone/src/test/java/gov/llnl/gnem/apps/coda/calibration/AssessAutopicker.java b/calibration-standalone/src/test/java/gov/llnl/gnem/apps/coda/calibration/AssessAutopicker.java index 9d5d8627..645c0ea1 100644 --- a/calibration-standalone/src/test/java/gov/llnl/gnem/apps/coda/calibration/AssessAutopicker.java +++ b/calibration-standalone/src/test/java/gov/llnl/gnem/apps/coda/calibration/AssessAutopicker.java @@ -98,7 +98,7 @@ public static void main(String[] args) { .filter(pick -> PICK_TYPES.F.getPhase().equalsIgnoreCase(pick.getPickType())) .findAny() .map(pick -> (double) pick.getPickTimeSecFromOrigin()) - .orElse(new Double(-100)); + .orElseGet(() -> Double.valueOf(-100)); if (autoPickedTime > 0) { stats.addValue(humanPickedTime - autoPickedTime); diff --git a/common-gui/pom.xml b/common-gui/pom.xml index fe9e22e0..183603b7 100644 --- a/common-gui/pom.xml +++ b/common-gui/pom.xml @@ -34,17 +34,39 @@ org.openjfx javafx-fxml + + org.openjfx + javafx-swing + org.openjfx javafx-web + win org.openjfx - javafx-swing + javafx-web + mac + + + org.openjfx + javafx-web + linux + + + org.openjfx + javafx-graphics + win + + + org.openjfx + javafx-graphics + mac org.openjfx javafx-graphics + linux org.openjfx diff --git a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/WebclientConfig.java b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/WebclientConfig.java new file mode 100644 index 00000000..0ff0edb6 --- /dev/null +++ b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/WebclientConfig.java @@ -0,0 +1,88 @@ +/* +* 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.gui; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Component +@ConfigurationProperties(prefix = "webclient") +public class WebclientConfig { + private String basePath = "localhost:2222"; + private String httpPrefix = "https://"; + private String websocketPrefix = "https://"; + private String apiPath = "/api/v1/"; + private String socketPath = "/websocket-guide/"; + private List subscriptions = new ArrayList<>(); + + public String getBasePath() { + return basePath; + } + + public WebclientConfig setBasePath(String basePath) { + this.basePath = basePath; + return this; + } + + public String getHttpPrefix() { + return httpPrefix; + } + + public WebclientConfig setHttpPrefix(String httpPrefix) { + this.httpPrefix = httpPrefix; + return this; + } + + public String getWebsocketPrefix() { + return websocketPrefix; + } + + public WebclientConfig setWebsocketPrefix(String websocketPrefix) { + this.websocketPrefix = websocketPrefix; + return this; + } + + public String getApiPath() { + return apiPath; + } + + public WebclientConfig setApiPath(String apiPath) { + this.apiPath = apiPath; + return this; + } + + public String getSocketPath() { + return socketPath; + } + + public WebclientConfig setSocketPath(String socketPath) { + this.socketPath = socketPath; + return this; + } + + public String getHTTPPath() { + return httpPrefix + basePath + apiPath; + } + + public List getSubscriptions() { + return subscriptions; + } + + public void setSubscriptions(List subscriptions) { + this.subscriptions = subscriptions; + } +} 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 496b3267..92b03d28 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 @@ -85,7 +85,7 @@ protected void updateItem(Node item, boolean empty) { super.setGraphic(null); } else if (item instanceof Node) { super.setText(null); - super.setGraphic((Node) item); + super.setGraphic(item); } } }; 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 08674127..d0efda1d 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 @@ -23,7 +23,6 @@ import java.util.Collections; import java.util.Locale; -import org.apache.commons.lang3.ArrayUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @@ -56,7 +55,7 @@ public Result writeWaveformToDirectory(File exportDirectory, Waveform w) header.setBeginTime(new TimeT(w.getBeginTime())); header.setOriginTime(new TimeT(w.getEvent().getOriginTime())); - header.nevid = Integer.valueOf(w.getEvent().getEventId()); + header.nevid = Integer.parseInt(w.getEvent().getEventId()); if (w.getAssociatedPicks() != null) { for (int i = 0; i < w.getAssociatedPicks().size() && i <= 10; i++) { try { @@ -97,7 +96,7 @@ public Result writeWaveformToDirectory(File exportDirectory, Waveform w) header.idep = 8; } } - float[] sequence = new Sequence(ArrayUtils.toPrimitive(w.getSegment())).getArray(); + float[] sequence = new Sequence(w.getSegment()).getArray(); header.npts = sequence.length; header.write(os); for (int i = 0; i < sequence.length; i++) { 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 3585b1e3..7e794b59 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 @@ -15,7 +15,7 @@ package gov.llnl.gnem.apps.coda.common.gui.converters.sac; import java.io.File; -import java.io.FileNotFoundException; +import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.PathMatcher; @@ -107,7 +107,10 @@ public Result convertSacFileToWaveform(File file) { } String stationName = headerResult.getResultPayload().orElse(UNKNOWN_VAL); - TimeT originTime = header.getOriginTime() != null ? header.getOriginTime() : header.getReferenceTime(); + TimeT originTime = header.getOriginTime(); + if (originTime == null) { + originTime = header.getReferenceTime(); + } if (originTime == null) { return exceptionalResult(new LightweightIllegalStateException("Both reference time and origin time may not be null!")); } @@ -203,7 +206,7 @@ public Result convertSacFileToWaveform(File file) { double sampleRate = header.delta > 0 ? 1.0 / header.delta : 1.0; Sequence sequence = reader.readSequence(header.npts); float[] rawVals = sequence.getArray(); - Double[] segment = new Double[rawVals.length]; + double[] segment = new double[rawVals.length]; try { IntStream.range(0, rawVals.length).forEach(index -> { segment[index] = Double.valueOf(rawVals[index]); @@ -238,7 +241,7 @@ public Result convertSacFileToWaveform(File file) { .setSegmentUnits(dataUnits) .setSampleRate(sampleRate) .setAssociatedPicks(getPicksFromHeader(header))); - } catch (FileNotFoundException | NegativeArraySizeException | IllegalStateException e) { + } catch (NegativeArraySizeException | IllegalStateException | IOException e) { return exceptionalResult(new LightweightIllegalStateException(String.format("Error parsing (%s): file does not exist or is unreadable. %s", fileName, e.getMessage()), e)); } finally { if (reader != null) { @@ -353,10 +356,14 @@ public String getOrCreateEvid(Waveform waveform) { public String getOrCreateEvid(SACHeader header) { int evid = 0; Double time = 0d; - if (header.getOriginTime() != null) { - time = header.getOriginTime().getEpochTime(); - } else if (header.getReferenceTime() != null) { - time = header.getReferenceTime().getEpochTime(); + TimeT relTime = header.getOriginTime(); + if (relTime != null) { + time = relTime.getEpochTime(); + } else { + relTime = header.getReferenceTime(); + if (relTime != null) { + time = relTime.getEpochTime(); + } } evid = createJDateMinuteResolutionFromEpoch(time); return Integer.toString(evid); 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 243abf69..ddccd45c 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 @@ -19,7 +19,6 @@ import java.security.GeneralSecurityException; import java.time.temporal.ChronoUnit; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.concurrent.ExecutionException; @@ -38,7 +37,6 @@ import org.glassfish.tyrus.client.SslEngineConfigurator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; @@ -58,15 +56,11 @@ import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; +import gov.llnl.gnem.apps.coda.common.gui.WebclientConfig; import gov.llnl.gnem.apps.coda.common.gui.events.SocketDisconnectEvent; import gov.llnl.gnem.apps.coda.common.gui.util.SslUtils; -import io.netty.handler.ssl.ApplicationProtocolConfig; -import io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBehavior; -import io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior; -import io.netty.handler.ssl.ApplicationProtocolNames; -import io.netty.handler.ssl.ClientAuth; -import io.netty.handler.ssl.IdentityCipherSuiteFilter; -import io.netty.handler.ssl.JdkSslContext; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslContextBuilder; import net.jodah.failsafe.Failsafe; import net.jodah.failsafe.FailsafeExecutor; import net.jodah.failsafe.RetryPolicy; @@ -74,20 +68,12 @@ @Service @Scope(scopeName = "singleton") -@ConfigurationProperties(prefix = "webclient") @Configuration public class CodaWebClientBuilder { + private WebclientConfig config; private static final Logger log = LoggerFactory.getLogger(CodaWebClientBuilder.class); - private String basePath = "localhost:2222"; - private String httpPrefix = "https://"; - private String websocketPrefix = "https://"; - private String apiPath = "/api/v1/"; - private String socketPath = "/websocket-guide/"; private String websocketBase; - - private List subscriptions = new ArrayList<>(); - private String trustStoreName = "coda-truststore.jks"; private final HostnameVerifier defaultHostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier(); @@ -95,7 +81,7 @@ public class CodaWebClientBuilder { if (hostname == null) { return false; } - boolean local = basePath.toLowerCase(Locale.ENGLISH).startsWith(hostname.toLowerCase(Locale.ENGLISH)); + boolean local = config.getBasePath().toLowerCase(Locale.ENGLISH).startsWith(hostname.toLowerCase(Locale.ENGLISH)); if (!local) { return defaultHostnameVerifier.verify(hostname, session); } @@ -114,42 +100,34 @@ public class CodaWebClientBuilder { private SslEngineConfigurator sslEngineConfigurator; private ReactorClientHttpConnector connector; - public CodaWebClientBuilder(EventBus bus, StompSessionHandlerAdapter frameHandler) { + public CodaWebClientBuilder(EventBus bus, WebclientConfig config, StompSessionHandlerAdapter frameHandler) { + this.config = config; bus.register(this); this.frameHandler = frameHandler; - if (subscriptions.isEmpty()) { - subscriptions.add("/topic/status-events"); + if (config.getSubscriptions().isEmpty()) { + config.getSubscriptions().add("/topic/status-events"); } HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - SSLContext sc; try (InputStream keyStore = classLoader.getResourceAsStream(trustStoreName)) { - sc = SslUtils.initMergedSSLTrustStore(keyStore); + SSLContext sc = SslUtils.initMergedSSLTrustStore(keyStore); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); - System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true"); + sslEngineConfigurator = new SslEngineConfigurator(sc); + sslEngineConfigurator.setHostnameVerifier(hostnameVerifier); + } catch (IOException | GeneralSecurityException e) { + throw new IllegalStateException("Unable to load trust store.", e); + } + try (InputStream keyStore = classLoader.getResourceAsStream(trustStoreName)) { + SslContext sslContext = SslUtils.initMergedSSLTrustStore(() -> SslContextBuilder.forClient(), keyStore); + connector = new ReactorClientHttpConnector(HttpClient.create().secure(t -> t.sslContext(sslContext))); } catch (IOException | GeneralSecurityException e) { throw new IllegalStateException("Unable to load trust store.", e); } - - JdkSslContext sslContext = new JdkSslContext(sc, - true, - Arrays.asList(sc.getSupportedSSLParameters().getCipherSuites()), - IdentityCipherSuiteFilter.INSTANCE, - new ApplicationProtocolConfig(ApplicationProtocolConfig.Protocol.ALPN, - SelectorFailureBehavior.CHOOSE_MY_LAST_PROTOCOL, - SelectedListenerFailureBehavior.ACCEPT, - ApplicationProtocolNames.HTTP_1_1), - ClientAuth.OPTIONAL, - new String[] { "TLSv1.2" }, - false); - connector = new ReactorClientHttpConnector(HttpClient.create().secure(t -> t.sslContext(sslContext))); - sslEngineConfigurator = new SslEngineConfigurator(sc); - sslEngineConfigurator.setHostnameVerifier(hostnameVerifier); } @PostConstruct private void initialize() throws InterruptedException, ExecutionException { - websocketBase = websocketPrefix + basePath + socketPath; + websocketBase = config.getWebsocketPrefix() + config.getBasePath() + config.getSocketPath(); ClientManager client = ClientManager.createClient(); client.getProperties().put(ClientProperties.SSL_ENGINE_CONFIGURATOR, sslEngineConfigurator); StandardWebSocketClient standardClient = new StandardWebSocketClient(client); @@ -185,7 +163,7 @@ private void connectSocket() { log.trace("Attempting to connect to stomp: {}", evt); }).runAsync(r -> { stompSession = stompClient.connect(websocketBase, frameHandler).get(1, TimeUnit.SECONDS); - subscriptions.forEach(topic -> stompSession.subscribe(topic.replaceAll("\"", ""), frameHandler)); + config.getSubscriptions().forEach(topic -> stompSession.subscribe(topic.replaceAll("\"", ""), frameHandler)); }); } @@ -197,47 +175,7 @@ public void close() { retryExecutor.shutdownNow(); } - public String getHttpPrefix() { - return httpPrefix; - } - - public void setHttpPrefix(String httpPrefix) { - this.httpPrefix = httpPrefix; - } - - public String getWebsocketPrefix() { - return websocketPrefix; - } - - public void setWebsocketPrefix(String websocketPrefix) { - this.websocketPrefix = websocketPrefix; - } - - public String getHTTPPath() { - return httpPrefix + basePath + apiPath; - } - - public String getWebSocketPath() { - return websocketPrefix + basePath + socketPath; - } - - public String getBasePath() { - return basePath; - } - - public void setBasePath(String baseURL) { - this.basePath = baseURL; - } - public @Bean @Scope("prototype") WebClient getWebClient() { - return WebClient.builder().clientConnector(connector).baseUrl(getHTTPPath()).build(); - } - - public List getSubscriptions() { - return subscriptions; - } - - public void setSubscriptions(List subscriptions) { - this.subscriptions = subscriptions; + return WebClient.builder().clientConnector(connector).baseUrl(config.getHTTPPath()).build(); } } \ No newline at end of file diff --git a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/data/client/WaveformWebClient.java b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/data/client/WaveformWebClient.java index 10e70007..8ee156e9 100644 --- a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/data/client/WaveformWebClient.java +++ b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/data/client/WaveformWebClient.java @@ -18,6 +18,8 @@ import java.util.List; import java.util.Objects; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; @@ -34,6 +36,8 @@ @Component public class WaveformWebClient implements WaveformClient { + private static final Logger log = LoggerFactory.getLogger(WaveformWebClient.class); + private WebClient client; @Autowired @@ -75,7 +79,24 @@ public Flux postWaveforms(Long sessionId, List segments) { @Override public Flux getAllStacks() { - return client.get().uri("/waveforms/query/stacks").accept(MediaType.APPLICATION_JSON).exchange().flatMapMany(response -> response.bodyToFlux(Waveform.class)).onErrorReturn(new Waveform()); + return client.get() + .uri("/waveforms/query/stacks") + .accept(MediaType.APPLICATION_JSON) + .exchange() + .flatMapMany(response -> response.bodyToFlux(Waveform.class)) + .doOnError(e -> log.error(e.getMessage(), e)) + .onErrorReturn(new Waveform()); + } + + @Override + public Flux getAllActiveStacks() { + return client.get() + .uri("/waveforms/query/active-stacks") + .accept(MediaType.APPLICATION_JSON) + .exchange() + .flatMapMany(response -> response.bodyToFlux(Waveform.class)) + .doOnError(e -> log.error(e.getMessage(), e)) + .onErrorReturn(new Waveform()); } @Override @@ -100,6 +121,17 @@ public Flux getWaveformsFromIds(Collection ids) { .onErrorReturn(new Waveform()); } + @Override + public Flux getWaveformMetadataFromIds(List ids) { + return client.get() + .uri("/waveforms/metadata/batch/{ids}", ids.toString().replaceAll("\\[|\\]", "")) + .accept(MediaType.APPLICATION_JSON) + .exchange() + .flatMapMany(response -> response.bodyToFlux(Waveform.class)) + .filter(Objects::nonNull) + .onErrorReturn(new Waveform()); + } + @Override public Flux getSyntheticsFromWaveformIds(Collection ids) { return client.get() @@ -110,4 +142,37 @@ public Flux getSyntheticsFromWaveformIds(Collection ids) { .filter(Objects::nonNull) .onErrorReturn(new SyntheticCoda()); } + + @Override + public Flux setWaveformsActiveByIds(List selectedWaveforms, boolean active) { + return client.post() + .uri("/waveforms/set-active/batch/" + active) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .syncBody(selectedWaveforms) + .exchange() + .flatMapMany(resp -> Flux.just(resp.toString())); + } + + @Override + public Flux setWaveformsActiveByEventId(String id, boolean active) { + return client.post() + .uri("/waveforms/set-active/by-event-id/" + active) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .syncBody(id) + .exchange() + .flatMapMany(resp -> Flux.just(resp.toString())); + } + + @Override + public Flux setWaveformsActiveByStationName(String id, boolean active) { + return client.post() + .uri("/waveforms/set-active/by-station-name/" + active) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .syncBody(id) + .exchange() + .flatMapMany(resp -> Flux.just(resp.toString())); + } } diff --git a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/data/client/api/WaveformClient.java b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/data/client/api/WaveformClient.java index 3ec27595..13d7bd8f 100644 --- a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/data/client/api/WaveformClient.java +++ b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/data/client/api/WaveformClient.java @@ -29,16 +29,26 @@ public interface WaveformClient { public Mono getWaveformFromId(Long id); public Mono getSyntheticFromWaveformId(Long id); - + public Flux getWaveformsFromIds(Collection ids); + public Flux getWaveformMetadataFromIds(List ids); + public Flux getSyntheticsFromWaveformIds(Collection ids); public Mono postWaveform(Waveform segment) throws JsonProcessingException; public Flux getAllStacks(); + public Flux getAllActiveStacks(); + public Flux postWaveforms(Long sessionId, List segments); public Flux getUniqueEventStationMetadataForStacks(); + + public Flux setWaveformsActiveByIds(List selectedWaveforms, boolean active); + + public Flux setWaveformsActiveByEventId(String id, boolean active); + + public Flux setWaveformsActiveByStationName(String id, boolean active); } diff --git a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/events/WaveformSelectionEvent.java b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/events/WaveformSelectionEvent.java index 11426526..744602ce 100644 --- a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/events/WaveformSelectionEvent.java +++ b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/events/WaveformSelectionEvent.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. @@ -18,9 +18,10 @@ import java.util.List; public class WaveformSelectionEvent { - private List waveformIDs = new ArrayList<>(); + private List waveformIDs; - public WaveformSelectionEvent(Long... ids) { + public WaveformSelectionEvent(Long... ids) { + waveformIDs = new ArrayList<>(ids.length); for (Long id : ids) { waveformIDs.add(id); } diff --git a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/plotting/PlotPoint.java b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/plotting/PlotPoint.java index 0c3841a2..da21fc5d 100644 --- a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/plotting/PlotPoint.java +++ b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/plotting/PlotPoint.java @@ -33,6 +33,20 @@ public PlotPoint(Double x, Double y, SymbolStyle style, Color color) { this.color = color; } + public PlotPoint(PlotPoint pp) { + super(); + if (pp != null) { + this.x = pp.getX(); + this.y = pp.getY(); + this.style = pp.getStyle(); + this.color = pp.getColor(); + } + } + + public PlotPoint() { + super(); + } + public Double getX() { return x; } diff --git a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/plotting/SymbolStyleMapFactory.java b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/plotting/SymbolStyleMapFactory.java index 4d01ac0d..3c9ef4a2 100644 --- a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/plotting/SymbolStyleMapFactory.java +++ b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/plotting/SymbolStyleMapFactory.java @@ -42,7 +42,7 @@ public class SymbolStyleMapFactory { * @return A java.awt.Color object containing the color. * @author HughesR */ - private Color getSpacedOutColour(int index, int count) { + private static Color getSpacedOutColour(int index, int count) { final float saturation = 0.95f; // Saturation final float brightness = 0.8f; // Brightness float hue = (float) index / (float) count; @@ -89,7 +89,9 @@ public Map build(List values, Function keyProvider AtomicInteger i = new AtomicInteger(0); long keyCount = values.stream().map(v -> keyProvider.apply(v)).distinct().count(); //Is the JIT going to do what I expect here? Let's find out... - values.stream().sequential().forEach(v -> styles.putIfAbsent(keyProvider.apply(v), new PlotPoint(null, null, nextSymbol(), getSpacedOutColour(i.getAndIncrement(), (int) keyCount)))); + values.stream() + .sequential() + .forEach(v -> styles.putIfAbsent(keyProvider.apply(v), new PlotPoint(null, null, nextSymbol(), SymbolStyleMapFactory.getSpacedOutColour(i.getAndIncrement(), (int) keyCount)))); return styles; } } diff --git a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/util/CombinedTrustManager.java b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/util/CombinedTrustManager.java index be0d00ae..7874c410 100644 --- a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/util/CombinedTrustManager.java +++ b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/util/CombinedTrustManager.java @@ -24,12 +24,13 @@ import javax.net.ssl.X509TrustManager; public class CombinedTrustManager implements X509TrustManager { - private List managers = new ArrayList<>(); + private List managers; public CombinedTrustManager(X509TrustManager... trustManagers) { if (trustManagers == null) { throw new IllegalStateException("A minimum of one X509TrustManager is required to use a CombinedTrustManager."); } + managers = new ArrayList<>(trustManagers.length); for (X509TrustManager manager : trustManagers) { this.managers.add(manager); } diff --git a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/util/CommonGuiUtils.java b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/util/CommonGuiUtils.java index 3a16e7d7..9d408ec3 100644 --- a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/util/CommonGuiUtils.java +++ b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/util/CommonGuiUtils.java @@ -38,10 +38,11 @@ public static void setIcon(Class clazz, String iconPath) { Method getTaskbar = taskbar.getMethod("getTaskbar"); try { Object taskbarInstance = getTaskbar.invoke(taskbar); - Method setIconImage = taskbar.cast(taskbarInstance).getClass().getMethod("setIconImage", java.awt.Image.class); - setIconImage.invoke(taskbarInstance, image); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - log.error(e.getMessage(), e); + if (taskbarInstance != null) { + Method setIconImage = taskbar.cast(taskbarInstance).getClass().getMethod("setIconImage", java.awt.Image.class); + setIconImage.invoke(taskbarInstance, image); + } + } catch (UnsupportedOperationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { } } catch (ClassNotFoundException | NoSuchMethodException e) { try { diff --git a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/util/MaybeNumericStringComparator.java b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/util/MaybeNumericStringComparator.java index a98b6a2e..00a69459 100644 --- a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/util/MaybeNumericStringComparator.java +++ b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/util/MaybeNumericStringComparator.java @@ -29,23 +29,28 @@ public int compare(String s1, String s2) { } else if (s2 == null) { return 1; } - if (StringUtils.isNumeric(s1) && StringUtils.isNumeric(s2)) { - int val = -1; + String ns1 = s1.trim().isEmpty() ? "0.0" : s1.trim(); + String ns2 = s2.trim().isEmpty() ? "0.0" : s2.trim(); + int val = -1; + if (StringUtils.isNumeric(ns1) && StringUtils.isNumeric(ns2)) { try { - val = Long.valueOf(s1).compareTo(Long.valueOf(s2)); + val = Long.valueOf(ns1).compareTo(Long.valueOf(ns2)); } catch (NumberFormatException e) { } - return val; - } else if (StringUtils.containsOnly(s1, "0123456789.") && StringUtils.containsOnly(s2, "0123456789.")) { - int val = -1; - try { - val = Double.valueOf(s1).compareTo(Double.valueOf(s2)); - } catch (NumberFormatException e) { + } else if (StringUtils.containsOnly(ns1, "0123456789.")) { + if (StringUtils.containsOnly(ns2, "0123456789.")) { + try { + val = Double.valueOf(ns1).compareTo(Double.valueOf(ns2)); + } catch (NumberFormatException e) { + } + } else { + val = ns1.compareTo(ns2); } - return val; } else { - return s1.compareTo(s2); + val = ns1.compareTo(ns2); } + + return val; } } 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 7a24b693..9908bea0 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 @@ -37,9 +37,11 @@ public class ProgressMonitor extends VBox implements Observer { private Label label; private String displayableName; + private String progressStage; public ProgressMonitor(String displayableName, ProgressListener progressListener) { this.displayableName = displayableName; + this.progressStage = ""; progressListener.addObserver(this); Platform.runLater(() -> { @@ -68,7 +70,7 @@ public void update(Observable o, Object event) { Progress progress = (Progress) event; Platform.runLater(() -> { if (progress.getTotal() >= 0.0) { - label.setText(progress.getCurrent() + "/" + progress.getTotal()); + label.setText(progress.getCurrent() + "/" + progress.getTotal() + getProgressStage()); progressBar.setProgress(progress.getProgress()); } else { progressBar.setProgress(ProgressBar.INDETERMINATE_PROGRESS); @@ -78,10 +80,23 @@ public void update(Observable o, Object event) { } } + private String getProgressStage() { + if (progressStage.isEmpty()) { + return progressStage; + } else { + return " | " + progressStage; + } + } + public String getDisplayableName() { return displayableName; } + public ProgressMonitor setProgressStage(String progressStage) { + this.progressStage = progressStage; + return this; + } + public ProgressBar getProgressBar() { return progressBar; } diff --git a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/util/SslUtils.java b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/util/SslUtils.java index 8795b5cf..d0e80315 100644 --- a/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/util/SslUtils.java +++ b/common-gui/src/main/java/gov/llnl/gnem/apps/coda/common/gui/util/SslUtils.java @@ -18,6 +18,7 @@ import java.io.InputStream; import java.security.GeneralSecurityException; import java.security.KeyStore; +import java.util.function.Supplier; import java.util.stream.Stream; import javax.net.ssl.KeyManager; @@ -31,15 +32,20 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import io.netty.handler.ssl.ApplicationProtocolConfig; +import io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBehavior; +import io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior; +import io.netty.handler.ssl.ApplicationProtocolNames; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslContextBuilder; + public class SslUtils { private final Logger log = LoggerFactory.getLogger(this.getClass()); public static SSLContext initMergedSSLTrustStore(InputStream keyStoreInput) throws GeneralSecurityException, IOException { - KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(keyStoreInput, null); - String defaultAlgorithm = KeyManagerFactory.getDefaultAlgorithm(); KeyManager[] keyManagers = { getSystemKeyManager(defaultAlgorithm, null) }; @@ -51,6 +57,27 @@ public static SSLContext initMergedSSLTrustStore(InputStream keyStoreInput) thro return context; } + public static SslContext initMergedSSLTrustStore(Supplier base, InputStream keyStoreInput) throws GeneralSecurityException, IOException { + SslContextBuilder baseSSL = base.get(); + KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + keyStore.load(keyStoreInput, null); + String defaultAlgorithm = KeyManagerFactory.getDefaultAlgorithm(); + + KeyManagerFactory keyManFactory = KeyManagerFactory.getInstance(defaultAlgorithm); + keyManFactory.init(keyStore, null); + + return baseSSL.applicationProtocolConfig( + new ApplicationProtocolConfig(ApplicationProtocolConfig.Protocol.ALPN, + SelectorFailureBehavior.CHOOSE_MY_LAST_PROTOCOL, + SelectedListenerFailureBehavior.ACCEPT, + // **Go back to H2 when Netty 4.1.X fixes their connection pooling problem with h2 + // ApplicationProtocolNames.HTTP_2, + ApplicationProtocolNames.HTTP_1_1)) + .keyManager(keyManFactory) + .trustManager(new CombinedTrustManager(getSystemTrustManager(defaultAlgorithm, keyStore), getSystemTrustManager(defaultAlgorithm, null)).getAcceptedIssuers()) + .build(); + } + public static X509KeyManager getSystemKeyManager(String algorithm, KeyStore keystore) throws GeneralSecurityException { KeyManagerFactory factory = KeyManagerFactory.getInstance(algorithm); factory.init(keystore, null); diff --git a/common-service/common-application/pom.xml b/common-service/common-application/pom.xml index dac6cea3..a4cae5c2 100644 --- a/common-service/common-application/pom.xml +++ b/common-service/common-application/pom.xml @@ -95,18 +95,46 @@ springlets-data-commons - io.springlets - springlets-web + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + + org.springframework.boot - spring-boot-starter-web + spring-boot-starter-jetty + + + org.eclipse.jetty + jetty-server + + + + + org.eclipse.jetty + jetty-alpn-conscrypt-server + + + org.eclipse.jetty.http2 + http2-server org.junit.jupiter junit-jupiter test + + io.netty + netty-tcnative-boringssl-static + + + org.springframework.boot + spring-boot-configuration-processor + diff --git a/common-service/common-application/src/main/java/gov/llnl/gnem/apps/coda/common/application/config/JettyConfiguration.java b/common-service/common-application/src/main/java/gov/llnl/gnem/apps/coda/common/application/config/JettyConfiguration.java new file mode 100644 index 00000000..9785f596 --- /dev/null +++ b/common-service/common-application/src/main/java/gov/llnl/gnem/apps/coda/common/application/config/JettyConfiguration.java @@ -0,0 +1,44 @@ +/* +* 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.application.config; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory; +import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class JettyConfiguration { + + private static final Logger log = LoggerFactory.getLogger(JettyConfiguration.class); + + @Bean + public ConfigurableServletWebServerFactory undertowServletFactory(@Value("${server.address:127.0.0.1}") String address, @Value("${server.port:8080}") int port) { + JettyServletWebServerFactory factory = new JettyServletWebServerFactory(); + factory.setPort(port); + try { + factory.setAddress(InetAddress.getByName(address)); + } catch (UnknownHostException e) { + log.error(e.getMessage(), e); + factory.setAddress(InetAddress.getLoopbackAddress()); + } + return factory; + } +} diff --git a/common-service/common-application/src/main/java/gov/llnl/gnem/apps/coda/common/application/web/WaveformPicksItemJsonController.java b/common-service/common-application/src/main/java/gov/llnl/gnem/apps/coda/common/application/web/WaveformPicksItemJsonController.java index 2d2f4c90..c12b0f31 100644 --- a/common-service/common-application/src/main/java/gov/llnl/gnem/apps/coda/common/application/web/WaveformPicksItemJsonController.java +++ b/common-service/common-application/src/main/java/gov/llnl/gnem/apps/coda/common/application/web/WaveformPicksItemJsonController.java @@ -34,7 +34,6 @@ import gov.llnl.gnem.apps.coda.common.model.domain.WaveformPick; import gov.llnl.gnem.apps.coda.common.service.api.WaveformPickService; -import io.springlets.web.NotFoundException; @RestController @RequestMapping(value = "/api/v1/waveform-picks/{waveformPick}", name = "WaveformPicksItemJsonController", produces = MediaType.APPLICATION_JSON_VALUE) @@ -59,7 +58,7 @@ public WaveformPicksItemJsonController(WaveformPickService waveformPickService) public WaveformPick getWaveformPick(@PathVariable("waveformPick") Long id) { WaveformPick waveformPick = waveformPickService.findOne(id); if (waveformPick == null) { - throw new NotFoundException(String.format("WaveformPick with identifier '%s' not found", id)); + throw new IllegalStateException(String.format("WaveformPick with identifier '%s' not found", id)); } return waveformPick; } diff --git a/common-service/common-application/src/main/java/gov/llnl/gnem/apps/coda/common/application/web/WaveformsCollectionJsonController.java b/common-service/common-application/src/main/java/gov/llnl/gnem/apps/coda/common/application/web/WaveformsCollectionJsonController.java index d8ca9adc..b7125e82 100644 --- a/common-service/common-application/src/main/java/gov/llnl/gnem/apps/coda/common/application/web/WaveformsCollectionJsonController.java +++ b/common-service/common-application/src/main/java/gov/llnl/gnem/apps/coda/common/application/web/WaveformsCollectionJsonController.java @@ -57,13 +57,18 @@ public WaveformsCollectionJsonController(WaveformService waveformService) { */ @PostMapping(value = "/query/all", name = "getByExampleAllMatching") public ResponseEntity getByExampleAllMatching(@RequestBody Waveform waveform, BindingResult result) { - List waveforms = getWaveformService().getByExampleAllMatching(waveform); + List waveforms = getWaveformService().getByExampleAllDistinctMatching(waveform); return ResponseEntity.ok(waveforms); } @GetMapping(value = "/query/stacks", name = "getAllStacks") public ResponseEntity getAllStacks() { + List waveforms = getWaveformService().getAllStacks(); + return ResponseEntity.ok(waveforms); + } + @GetMapping(value = "/query/active-stacks", name = "getAllActiveStacks") + public ResponseEntity getAllActiveStacks() { List waveforms = getWaveformService().getAllActiveStacks(); return ResponseEntity.ok(waveforms); } @@ -73,6 +78,48 @@ public ResponseEntity getUniqueEventStationStacks() { return ResponseEntity.ok(getWaveformService().getUniqueEventStationStacks()); } + @PostMapping(value = "/set-active/batch/{active}", name = "setActiveFlagsById") + public ResponseEntity setActiveFlagsById(@PathVariable Boolean active, @Valid @RequestBody List waveformIds, BindingResult result) { + if (result.hasErrors()) { + return ResponseEntity.status(HttpStatus.CONFLICT).body(result); + } + getWaveformService().setActiveFlagForIds(waveformIds, active); + return ResponseEntity.ok().build(); + } + + @PostMapping(value = "/set-active/by-event-id/{active}", name = "setActiveFlagByEventId") + public ResponseEntity setActiveFlagByEventId(@PathVariable Boolean active, @Valid @RequestBody String eventId, BindingResult result) { + if (result.hasErrors()) { + return ResponseEntity.status(HttpStatus.CONFLICT).body(result); + } + getWaveformService().setActiveFlagByEventId(eventId, active); + return ResponseEntity.ok().build(); + } + + @PostMapping(value = "/set-active/by-station-name/{active}", name = "setActiveFlagByStationName") + public ResponseEntity setActiveFlagByStationName(@PathVariable Boolean active, @Valid @RequestBody String stationName, BindingResult result) { + if (result.hasErrors()) { + return ResponseEntity.status(HttpStatus.CONFLICT).body(result); + } + getWaveformService().setActiveFlagByStationName(stationName, active); + return ResponseEntity.ok().build(); + } + + /** + * + * @param ids + * @return ResponseEntity + */ + @GetMapping(value = "/metadata/batch/{ids}", name = "getBatchMetadata") + public ResponseEntity getBatchMetadata(@PathVariable("ids") List ids) { + List data = getWaveformService().findAllMetadata(ids); + if (data != null && !data.isEmpty()) { + return ResponseEntity.ok().body(data); + } else { + return ResponseEntity.noContent().build(); + } + } + /** * * @param ids @@ -95,7 +142,7 @@ public ResponseEntity getBatch(@PathVariable("ids") Collection ids) { * @return ResponseEntity */ @PostMapping(value = "/batch/{sessionId}", name = "createBatch") - public ResponseEntity createBatch(@PathVariable Long sessionId, @Valid @RequestBody Collection waveforms, BindingResult result) { + public ResponseEntity createBatch(@PathVariable Long sessionId, @Valid @RequestBody List waveforms, BindingResult result) { if (result.hasErrors()) { return ResponseEntity.status(HttpStatus.CONFLICT).body(result); } @@ -110,7 +157,7 @@ public ResponseEntity createBatch(@PathVariable Long sessionId, @Valid @Reque * @return ResponseEntity */ @PutMapping(value = "/batch/{sessionId}", name = "updateBatch") - public ResponseEntity updateBatch(@PathVariable Long sessionId, @Valid @RequestBody Collection waveforms, BindingResult result) { + public ResponseEntity updateBatch(@PathVariable Long sessionId, @Valid @RequestBody List waveforms, BindingResult result) { if (result.hasErrors()) { return ResponseEntity.status(HttpStatus.CONFLICT).body(result); } diff --git a/common-service/common-application/src/main/java/gov/llnl/gnem/apps/coda/common/application/web/WaveformsItemJsonController.java b/common-service/common-application/src/main/java/gov/llnl/gnem/apps/coda/common/application/web/WaveformsItemJsonController.java index 12bb6bac..9d25dd64 100644 --- a/common-service/common-application/src/main/java/gov/llnl/gnem/apps/coda/common/application/web/WaveformsItemJsonController.java +++ b/common-service/common-application/src/main/java/gov/llnl/gnem/apps/coda/common/application/web/WaveformsItemJsonController.java @@ -32,7 +32,6 @@ import gov.llnl.gnem.apps.coda.common.model.domain.Waveform; import gov.llnl.gnem.apps.coda.common.service.api.WaveformService; -import io.springlets.web.NotFoundException; @RestController @RequestMapping(value = "/api/v1/single-waveform", name = "WaveformsItemJsonController", produces = MediaType.APPLICATION_JSON_VALUE) @@ -56,11 +55,11 @@ public WaveformsItemJsonController(WaveformService waveformService) { public Waveform getWaveform(@PathVariable("id") Long id) { Waveform waveform = waveformService.findOne(id); if (waveform == null) { - throw new NotFoundException(String.format("Waveform with identifier '%s' not found", id)); + throw new IllegalStateException(String.format("Waveform with identifier '%s' not found", id)); } return waveform; } - + /** * * @param storedWaveform @@ -70,12 +69,10 @@ public Waveform getWaveform(@PathVariable("id") Long id) { */ @PostMapping(name = "update") public ResponseEntity update(@Valid @RequestBody Waveform waveform, BindingResult result) { - if (result.hasErrors()) { return ResponseEntity.status(HttpStatus.CONFLICT).body(result); } - - Waveform wave = getWaveformService().save(waveform); + Waveform wave = getWaveformService().update(waveform); return ResponseEntity.ok(wave); } diff --git a/common-service/common-model/pom.xml b/common-service/common-model/pom.xml index 537d4078..2716ffa2 100644 --- a/common-service/common-model/pom.xml +++ b/common-service/common-model/pom.xml @@ -14,6 +14,14 @@ common-model + + org.eclipse.collections + eclipse-collections-api + + + org.eclipse.collections + eclipse-collections + io.springlets springlets-context diff --git a/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/Pair.java b/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/Pair.java index 0a554b7c..28febecc 100644 --- a/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/Pair.java +++ b/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/Pair.java @@ -74,7 +74,7 @@ public boolean equals(Object obj) { @Override public String toString() { StringBuilder builder = new StringBuilder(); - builder.append("\"").append(left).append("\", \"").append(right).append("\""); + builder.append("\"").append(left).append("\", \"").append(right).append('\"'); return builder.toString(); } diff --git a/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/SharedFrequencyBandParameters.java b/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/SharedFrequencyBandParameters.java index 3180e4fb..1115558c 100644 --- a/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/SharedFrequencyBandParameters.java +++ b/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/SharedFrequencyBandParameters.java @@ -38,8 +38,7 @@ public class SharedFrequencyBandParameters { private Long id; @Version - @Column(name = "version") - private Long version; + private Integer version = 0; @Embedded private FrequencyBand frequencyBand = new FrequencyBand(); @@ -108,15 +107,10 @@ public SharedFrequencyBandParameters setId(Long id) { return this; } - public Long getVersion() { + public Integer getVersion() { return this.version; } - public SharedFrequencyBandParameters setVersion(Long version) { - this.version = version; - return this; - } - public double getLowFrequency() { return this.frequencyBand.getLowFrequency(); } diff --git a/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/Stream.java b/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/Stream.java index 23376663..24586140 100644 --- a/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/Stream.java +++ b/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/Stream.java @@ -95,10 +95,7 @@ public Stream setInstrument(String instrument) { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((bandName == null) ? 0 : bandName.hashCode()); result = prime * result + ((channelName == null) ? 0 : channelName.hashCode()); - result = prime * result + ((instrument == null) ? 0 : instrument.hashCode()); - result = prime * result + ((orientation == null) ? 0 : orientation.hashCode()); result = prime * result + ((station == null) ? 0 : station.hashCode()); return result; } @@ -115,13 +112,6 @@ public boolean equals(Object obj) { return false; } Stream other = (Stream) obj; - if (bandName == null) { - if (other.bandName != null) { - return false; - } - } else if (!bandName.equals(other.bandName)) { - return false; - } if (channelName == null) { if (other.channelName != null) { return false; @@ -129,20 +119,6 @@ public boolean equals(Object obj) { } else if (!channelName.equals(other.channelName)) { return false; } - if (instrument == null) { - if (other.instrument != null) { - return false; - } - } else if (!instrument.equals(other.instrument)) { - return false; - } - if (orientation == null) { - if (other.orientation != null) { - return false; - } - } else if (!orientation.equals(other.orientation)) { - return false; - } if (station == null) { if (other.station != null) { return false; diff --git a/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/SyntheticCoda.java b/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/SyntheticCoda.java index f1778959..f3a03746 100644 --- a/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/SyntheticCoda.java +++ b/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/SyntheticCoda.java @@ -15,7 +15,6 @@ package gov.llnl.gnem.apps.coda.common.model.domain; import java.io.Serializable; -import java.util.Arrays; import java.util.Date; import javax.persistence.Basic; @@ -35,6 +34,7 @@ import javax.persistence.Version; import javax.validation.constraints.NotNull; +import org.eclipse.collections.impl.list.mutable.primitive.DoubleArrayList; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.NumberFormat; @@ -50,10 +50,9 @@ public class SyntheticCoda implements Serializable { private Long id; @Version - @Column(name = "version") - private Long version; + private Integer version = 0; - @ManyToOne(optional = false, cascade = { CascadeType.MERGE }) + @ManyToOne(optional = false) private Waveform sourceWaveform; @Column(name = "sampleRate") @@ -64,7 +63,7 @@ public class SyntheticCoda implements Serializable { @NotNull @Lob @Basic(fetch = FetchType.LAZY) - private Double[] segment; + private DoubleArrayList segment = new DoubleArrayList(0); @Column(name = "beginTime") @Temporal(TemporalType.TIMESTAMP) @@ -76,7 +75,7 @@ public class SyntheticCoda implements Serializable { @DateTimeFormat(style = "M-") private Date endTime; - @ManyToOne(optional = false) + @ManyToOne(optional = false, cascade = { CascadeType.MERGE }) private SharedFrequencyBandParameters sourceModel; private Double measuredV; @@ -93,15 +92,10 @@ public SyntheticCoda setId(Long id) { return this; } - public Long getVersion() { + public Integer getVersion() { return version; } - public SyntheticCoda setVersion(Long version) { - this.version = version; - return this; - } - public Waveform getSourceWaveform() { return sourceWaveform; } @@ -119,17 +113,17 @@ public Double getSampleRate() { return sampleRate; } - public SyntheticCoda setSampleRate(Double sampleRate) { + public SyntheticCoda setSampleRate(double sampleRate) { this.sampleRate = sampleRate; return this; } - public Double[] getSegment() { - return segment; + public double[] getSegment() { + return segment.toArray(); } - public SyntheticCoda setSegment(Double[] segment) { - this.segment = segment; + public SyntheticCoda setSegment(double[] segment) { + this.segment = new DoubleArrayList(segment); return this; } @@ -198,7 +192,7 @@ public int hashCode() { result = prime * result + ((measuredG == null) ? 0 : measuredG.hashCode()); result = prime * result + ((measuredV == null) ? 0 : measuredV.hashCode()); result = prime * result + ((sampleRate == null) ? 0 : sampleRate.hashCode()); - result = prime * result + Arrays.hashCode(segment); + result = prime * result + ((segment == null) ? 0 : segment.hashCode()); result = prime * result + ((sourceModel == null) ? 0 : sourceModel.hashCode()); result = prime * result + ((sourceWaveform == null) ? 0 : sourceWaveform.hashCode()); result = prime * result + ((version == null) ? 0 : version.hashCode()); @@ -266,7 +260,11 @@ public boolean equals(Object obj) { } else if (!sampleRate.equals(other.sampleRate)) { return false; } - if (!Arrays.equals(segment, other.segment)) { + if (segment == null) { + if (other.segment != null) { + return false; + } + } else if (!segment.equals(other.segment)) { return false; } if (sourceModel == null) { @@ -303,8 +301,6 @@ public String toString() { + sourceWaveform + ", sampleRate=" + sampleRate - + ", segment=" - + Arrays.toString(segment) + ", beginTime=" + beginTime + ", endTime=" @@ -337,10 +333,6 @@ public SyntheticCoda mergeNonNullOrEmptyFields(SyntheticCoda overlay) { this.setSampleRate(overlay.getSampleRate()); } - if (overlay.getVersion() != null) { - this.setVersion(overlay.getVersion()); - } - if (overlay.getSourceWaveform() != null) { this.setSourceWaveform(overlay.getSourceWaveform()); } diff --git a/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/Waveform.java b/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/Waveform.java index aa236fd5..e84eeb56 100644 --- a/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/Waveform.java +++ b/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/Waveform.java @@ -15,9 +15,9 @@ package gov.llnl.gnem.apps.coda.common.model.domain; import java.util.ArrayList; -import java.util.Arrays; import java.util.Date; import java.util.List; +import java.util.stream.Collectors; import javax.persistence.Basic; import javax.persistence.CascadeType; @@ -37,6 +37,7 @@ import javax.persistence.Version; import javax.validation.constraints.NotNull; +import org.eclipse.collections.impl.list.mutable.primitive.DoubleArrayList; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.NumberFormat; import org.springframework.util.StringUtils; @@ -57,8 +58,7 @@ public class Waveform { private Long id; @Version - @Column(name = "version") - private Long version; + private Integer version = 0; @Embedded private Event event; @@ -98,7 +98,7 @@ public class Waveform { @NotNull @Lob @Basic - private Double[] segment = new Double[0]; + private DoubleArrayList segment = new DoubleArrayList(0); @OneToMany(cascade = { CascadeType.ALL }, orphanRemoval = true, mappedBy = "waveform", targetEntity = WaveformPick.class, fetch = FetchType.EAGER) @JsonManagedReference(value = "waveform-picks") @@ -113,7 +113,7 @@ public Waveform() { public Waveform(WaveformMetadata waveform) { this.setId(waveform.getId()); - this.setVersion(waveform.getVersion()); + this.version = waveform.getVersion(); this.setEvent(waveform.getEvent()); this.setStream(waveform.getStream()); this.setBeginTime(waveform.getBeginTime()); @@ -127,7 +127,7 @@ public Waveform(WaveformMetadata waveform) { this.setActive(waveform.getActive()); } - public Waveform(Long id, Long version, Event event, Stream stream, Date beginTime, Date endTime, String segmentType, String segmentUnits, Double lowFrequency, Double highFrequency, + public Waveform(Long id, Integer version, Event event, Stream stream, Date beginTime, Date endTime, String segmentType, String segmentUnits, Double lowFrequency, Double highFrequency, Double sampleRate, Boolean active) { super(); this.id = id; @@ -153,15 +153,10 @@ public Waveform setId(Long id) { return this; } - public Long getVersion() { + public Integer getVersion() { return this.version; } - public Waveform setVersion(Long version) { - this.version = version; - return this; - } - public Event getEvent() { return event; } @@ -225,12 +220,12 @@ public Waveform setHighFrequency(Double highFrequency) { return this; } - public Double[] getSegment() { - return segment; + public double[] getSegment() { + return segment.toArray(); } - public Waveform setSegment(Double[] segment) { - this.segment = segment; + public Waveform setSegment(double[] segment) { + this.segment = new DoubleArrayList(segment); return this; } @@ -258,10 +253,19 @@ public List getAssociatedPicks() { public Waveform setAssociatedPicks(List associatedPicks) { if (associatedPicks != null) { - this.associatedPicks.clear(); - ; - this.associatedPicks.addAll(associatedPicks); - this.associatedPicks.forEach(pick -> pick.setWaveform(this)); + associatedPicks.forEach(pick -> { + int idx = this.associatedPicks.indexOf(pick); + if (idx >= 0) { + this.associatedPicks.get(idx).mergeNonNullOrEmptyFields(pick); + } else { + this.associatedPicks.add(pick); + } + pick.setWaveform(this); + }); + + //Remove picks not on the waveform anymore + List shouldRemove = this.associatedPicks.stream().filter(pick -> associatedPicks.indexOf(pick) < 0).collect(Collectors.toList()); + this.associatedPicks.removeAll(shouldRemove); } else { this.associatedPicks.clear(); } @@ -272,6 +276,10 @@ public Boolean isActive() { return active; } + public Boolean getActive() { + return active; + } + public Waveform setActive(Boolean active) { this.active = active; return this; @@ -282,22 +290,28 @@ public static Waveform mergeNonNullOrEmptyFields(Waveform waveformOverlay, Wavef } public Waveform mergeNonNullOrEmptyFields(Waveform waveformOverlay) { + if (waveformOverlay.getEvent() != null) { + this.setEvent(waveformOverlay.getEvent()); + } if (waveformOverlay.getStream() != null) { this.setStream(waveformOverlay.getStream()); } - if (waveformOverlay.getEvent() != null) { - this.setEvent(waveformOverlay.getEvent()); + if (waveformOverlay.getLowFrequency() != null) { + this.setLowFrequency(waveformOverlay.getLowFrequency()); + } + if (waveformOverlay.getHighFrequency() != null) { + this.setHighFrequency(waveformOverlay.getHighFrequency()); } + if (waveformOverlay.getSegment() != null) { + this.setSegment(waveformOverlay.getSegment()); + } if (!StringUtils.isEmpty(waveformOverlay.getSegmentType())) { this.setSegmentType(waveformOverlay.getSegmentType()); } if (!StringUtils.isEmpty(waveformOverlay.getSegmentUnits())) { this.setSegmentUnits(waveformOverlay.getSegmentUnits()); } - if (waveformOverlay.getSegment() != null) { - this.setSegment(waveformOverlay.getSegment()); - } if (waveformOverlay.getSampleRate() != null) { this.setSampleRate(waveformOverlay.getSampleRate()); } @@ -307,7 +321,7 @@ public Waveform mergeNonNullOrEmptyFields(Waveform waveformOverlay) { if (waveformOverlay.getEndTime() != null) { this.setEndTime(waveformOverlay.getEndTime()); } - if (waveformOverlay.getAssociatedPicks() != null) { + if (waveformOverlay.getAssociatedPicks() != null && !waveformOverlay.getAssociatedPicks().isEmpty()) { this.setAssociatedPicks(waveformOverlay.getAssociatedPicks()); } if (waveformOverlay.isActive() != null) { @@ -320,14 +334,13 @@ public Waveform mergeNonNullOrEmptyFields(Waveform waveformOverlay) { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((active == null) ? 0 : active.hashCode()); result = prime * result + ((beginTime == null) ? 0 : beginTime.hashCode()); result = prime * result + ((endTime == null) ? 0 : endTime.hashCode()); result = prime * result + ((event == null) ? 0 : event.hashCode()); result = prime * result + ((highFrequency == null) ? 0 : highFrequency.hashCode()); result = prime * result + ((lowFrequency == null) ? 0 : lowFrequency.hashCode()); result = prime * result + ((sampleRate == null) ? 0 : sampleRate.hashCode()); - result = prime * result + Arrays.hashCode(segment); + result = prime * result + ((segment == null) ? 0 : segment.hashCode()); result = prime * result + ((segmentType == null) ? 0 : segmentType.hashCode()); result = prime * result + ((segmentUnits == null) ? 0 : segmentUnits.hashCode()); result = prime * result + ((stream == null) ? 0 : stream.hashCode()); @@ -346,13 +359,6 @@ public boolean equals(Object obj) { return false; } Waveform other = (Waveform) obj; - if (active == null) { - if (other.active != null) { - return false; - } - } else if (!active.equals(other.active)) { - return false; - } if (beginTime == null) { if (other.beginTime != null) { return false; @@ -395,7 +401,11 @@ public boolean equals(Object obj) { } else if (!sampleRate.equals(other.sampleRate)) { return false; } - if (!Arrays.equals(segment, other.segment)) { + if (segment == null) { + if (other.segment != null) { + return false; + } + } else if (!segment.equals(other.segment)) { return false; } if (segmentType == null) { @@ -447,11 +457,9 @@ public String toString() { .append(highFrequency) .append(", sampleRate=") .append(sampleRate) - .append(", segment=") - .append(segment) .append(", active=") .append(active) - .append("]"); + .append(']'); return builder.toString(); } } diff --git a/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/WaveformMetadata.java b/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/WaveformMetadata.java index ad1c707c..95c1bfeb 100644 --- a/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/WaveformMetadata.java +++ b/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/WaveformMetadata.java @@ -41,7 +41,7 @@ public interface WaveformMetadata { public Stream getStream(); - public Long getVersion(); + public Integer getVersion(); public Boolean getActive(); diff --git a/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/WaveformPick.java b/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/WaveformPick.java index 9f6b3812..45524b10 100644 --- a/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/WaveformPick.java +++ b/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/domain/WaveformPick.java @@ -41,8 +41,7 @@ public class WaveformPick implements Serializable { private Long id; @Version - @Column(name = "version") - private Long version; + private Integer version = 0; @JsonBackReference(value = "waveform-picks") @ManyToOne(optional = false, cascade = { CascadeType.PERSIST }) @@ -66,15 +65,10 @@ public WaveformPick setId(Long id) { return this; } - public Long getVersion() { + public Integer getVersion() { return this.version; } - public WaveformPick setVersion(Long version) { - this.version = version; - return this; - } - public Waveform getWaveform() { return waveform; } @@ -142,20 +136,6 @@ public boolean equals(Object obj) { return false; } WaveformPick other = (WaveformPick) obj; - if (pickName == null) { - if (other.pickName != null) { - return false; - } - } else if (!pickName.equals(other.pickName)) { - return false; - } - if (pickTimeSecFromOrigin == null) { - if (other.pickTimeSecFromOrigin != null) { - return false; - } - } else if (!pickTimeSecFromOrigin.equals(other.pickTimeSecFromOrigin)) { - return false; - } if (pickType == null) { if (other.pickType != null) { return false; @@ -163,13 +143,20 @@ public boolean equals(Object obj) { } else if (!pickType.equals(other.pickType)) { return false; } - if (waveform == null) { - if (other.waveform != null) { - return false; - } - } else if (!waveform.equals(other.waveform)) { - return false; - } return true; } + + public WaveformPick mergeNonNullOrEmptyFields(WaveformPick pickOverlay) { + if (pickOverlay.getPickName() != null) { + this.setPickName(pickOverlay.getPickName()); + } + if (pickOverlay.getPickTimeSecFromOrigin() != null) { + this.setPickTimeSecFromOrigin(pickOverlay.getPickTimeSecFromOrigin()); + } + + if (pickOverlay.getPickType() != null) { + this.setPickType(pickOverlay.getPickType()); + } + return this; + } } diff --git a/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/messaging/WaveformChangeEvent.java b/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/messaging/WaveformChangeEvent.java new file mode 100644 index 00000000..409663c0 --- /dev/null +++ b/common-service/common-model/src/main/java/gov/llnl/gnem/apps/coda/common/model/messaging/WaveformChangeEvent.java @@ -0,0 +1,92 @@ +/* +* 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.common.model.messaging; + +import java.util.ArrayList; +import java.util.List; + +public class WaveformChangeEvent { + + private List ids; + private boolean isAddOrUpdate = false; + private boolean isDelete = false; + + public List getIds() { + return ids; + } + + public WaveformChangeEvent() { + ids = new ArrayList(); + } + + public WaveformChangeEvent(List ids) { + this.ids = ids; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("WaveformChangeEvent [ids=").append(ids).append(']'); + return builder.toString(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((ids == null) ? 0 : ids.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; + } + WaveformChangeEvent other = (WaveformChangeEvent) obj; + if (ids == null) { + if (other.ids != null) { + return false; + } + } else if (!ids.equals(other.ids)) { + return false; + } + return true; + } + + public boolean isAddOrUpdate() { + return isAddOrUpdate; + } + + public boolean isDelete() { + return isDelete; + } + + public WaveformChangeEvent setAddOrUpdate(boolean isAddOrUpdate) { + this.isAddOrUpdate = isAddOrUpdate; + return this; + } + + public WaveformChangeEvent setDelete(boolean isDelete) { + this.isDelete = isDelete; + return this; + } +} 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 6eff464c..7845dfa0 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 @@ -16,8 +16,10 @@ import java.util.Date; import java.util.List; +import java.util.Set; import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.transaction.annotation.Transactional; @@ -31,16 +33,40 @@ @Transactional public interface WaveformRepository extends DetachableJpaRepository { - @Query("select w from Waveform w where w.beginTime = :beginTime and w.endTime = :endTime and w.event = :event and w.stream = :stream and w.segmentType = :segmentType and w.segmentUnits = :segmentUnits and w.lowFrequency = :lowFrequency and w.highFrequency = :highFrequency") + @Query("select w from Waveform w where w.event.eventId = :eventId and w.stream.station.networkName = :networkName and w.stream.station.stationName = :stationName and w.lowFrequency = :lowFrequency and w.highFrequency = :highFrequency order by w.id desc") + public Waveform findByUniqueFields(@Param("eventId") String eventId, @Param("networkName") String networkName, @Param("stationName") String stationName, @Param("lowFrequency") Double lowFrequency, + @Param("highFrequency") Double highFrequency); + + @Query("select w from Waveform w where w.beginTime = :beginTime and w.endTime = :endTime and w.event = :event and w.stream = :stream and w.segmentType = :segmentType and w.segmentUnits = :segmentUnits and w.lowFrequency = :lowFrequency and w.highFrequency = :highFrequency order by w.id desc") public Waveform findOneByAllFields(@Param("beginTime") Date beginTime, @Param("endTime") Date endTime, @Param("event") Event event, @Param("stream") Stream stream, @Param("segmentType") String segmentType, @Param("segmentUnits") String segmentUnits, @Param("lowFrequency") Double lowFrequency, @Param("highFrequency") Double highFrequency); - @Query("select new Waveform(w.id, w.version, w.event, w.stream, w.beginTime, w.endTime, w.segmentType, w.segmentUnits, w.lowFrequency, w.highFrequency, w.sampleRate, w.active) from Waveform w") - public List getWaveformMetadata(); + @Query("select new Waveform(w.id, w.version, w.event, w.stream, w.beginTime, w.endTime, w.segmentType, w.segmentUnits, w.lowFrequency, w.highFrequency, w.sampleRate, w.active) from Waveform w order by w.id desc") + public Set getWaveformMetadata(); + + @Query("select new Waveform(w.id, w.version, w.event, w.stream, w.beginTime, w.endTime, w.segmentType, w.segmentUnits, w.lowFrequency, w.highFrequency, w.sampleRate, w.active) from Waveform w where w.id in :ids order by w.id desc") + public List findAllMetadataByIds(@Param("ids") List ids); + + @Query("select new Waveform(w.id, w.version, w.event, w.stream, w.beginTime, w.endTime, w.segmentType, w.segmentUnits, w.lowFrequency, w.highFrequency, w.sampleRate, w.active) from Waveform w where w.id = :id order by w.id desc") + public Waveform findWaveformMetadataById(@Param("id") Long id); @Query("select p from WaveformPick p where p.waveform.id = :id") public List findPicksByWaveformId(@Param("id") Long id); @Query("select w.event from Waveform w where w.event.eventId = :eventId order by w.id desc") public List findEventById(@Param("eventId") String eventId, Pageable pageable); + + @Modifying(clearAutomatically = true, flushAutomatically = true) + @Query("update Waveform w SET w.active = :active where w.event.eventId = :eventId") + public int setActiveByEventId(@Param("eventId") String eventId, @Param("active") boolean active); + + @Modifying(clearAutomatically = true, flushAutomatically = true) + @Query("update Waveform w SET w.active = :active where w.stream.station.stationName = :stationName") + public int setActiveByStationName(@Param("stationName") String stationName, @Param("active") boolean active); + + @Query("select w.id from Waveform w where w.event.eventId = :eventId") + public List findAllIdsByEventId(@Param("eventId") String eventId); + + @Query("select w.id from Waveform w where w.stream.station.stationName = :stationName") + public List findAllIdsByStationName(@Param("stationName") String stationName); } diff --git a/common-service/common-service-api/src/main/java/gov/llnl/gnem/apps/coda/common/service/api/WaveformService.java b/common-service/common-service-api/src/main/java/gov/llnl/gnem/apps/coda/common/service/api/WaveformService.java index 95da2ac4..592dab2e 100644 --- a/common-service/common-service-api/src/main/java/gov/llnl/gnem/apps/coda/common/service/api/WaveformService.java +++ b/common-service/common-service-api/src/main/java/gov/llnl/gnem/apps/coda/common/service/api/WaveformService.java @@ -14,7 +14,6 @@ */ package gov.llnl.gnem.apps.coda.common.service.api; -import java.util.Collection; import java.util.List; import gov.llnl.gnem.apps.coda.common.model.domain.Event; @@ -22,15 +21,26 @@ public interface WaveformService extends BaseService { - public List getByExampleAllMatching(Waveform waveform); + public List getByExampleAllDistinctMatching(Waveform waveform); + + public List getAllStacks(); public List getAllActiveStacks(); - public List update(Long sessionId, Collection values); + public List update(Long sessionId, List values); public Waveform update(Waveform waveformPayload); public List getUniqueEventStationStacks(); public Event findEventById(String eventId); + + public List findAllMetadata(List ids); + + public List setActiveFlagForIds(List selectedWaveforms, boolean active); + + public List setActiveFlagByEventId(String eventId, boolean active); + + public List setActiveFlagByStationName(String stationName, boolean active); + } diff --git a/common-service/common-service-impl/pom.xml b/common-service/common-service-impl/pom.xml index 5c4d8bad..fce7ce87 100644 --- a/common-service/common-service-impl/pom.xml +++ b/common-service/common-service-impl/pom.xml @@ -71,6 +71,21 @@ junit-jupiter test + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-data-jpa + test + + + com.h2database + h2 + test + diff --git a/common-service/common-service-impl/src/main/java/gov/llnl/gnem/apps/coda/common/service/impl/WaveformPickServiceImpl.java b/common-service/common-service-impl/src/main/java/gov/llnl/gnem/apps/coda/common/service/impl/WaveformPickServiceImpl.java index eb2bb9ad..020f49d3 100644 --- a/common-service/common-service-impl/src/main/java/gov/llnl/gnem/apps/coda/common/service/impl/WaveformPickServiceImpl.java +++ b/common-service/common-service-impl/src/main/java/gov/llnl/gnem/apps/coda/common/service/impl/WaveformPickServiceImpl.java @@ -103,7 +103,7 @@ public void delete(Iterable ids) { @Transactional @Override public WaveformPick save(WaveformPick entity) { - return waveformPickRepository.save(entity); + return waveformPickRepository.saveAndFlush(entity); } /** diff --git a/common-service/common-service-impl/src/main/java/gov/llnl/gnem/apps/coda/common/service/impl/WaveformServiceImpl.java b/common-service/common-service-impl/src/main/java/gov/llnl/gnem/apps/coda/common/service/impl/WaveformServiceImpl.java index 4cd6146e..507d509b 100644 --- a/common-service/common-service-impl/src/main/java/gov/llnl/gnem/apps/coda/common/service/impl/WaveformServiceImpl.java +++ b/common-service/common-service-impl/src/main/java/gov/llnl/gnem/apps/coda/common/service/impl/WaveformServiceImpl.java @@ -15,9 +15,10 @@ package gov.llnl.gnem.apps.coda.common.service.impl; import java.util.ArrayList; -import java.util.Collection; +import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.Optional; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; @@ -35,6 +36,7 @@ import gov.llnl.gnem.apps.coda.common.model.domain.Waveform; import gov.llnl.gnem.apps.coda.common.model.messaging.PassFailEvent; import gov.llnl.gnem.apps.coda.common.model.messaging.Result; +import gov.llnl.gnem.apps.coda.common.model.messaging.WaveformChangeEvent; import gov.llnl.gnem.apps.coda.common.repository.WaveformRepository; import gov.llnl.gnem.apps.coda.common.service.api.NotificationService; import gov.llnl.gnem.apps.coda.common.service.api.WaveformService; @@ -44,6 +46,7 @@ public class WaveformServiceImpl implements WaveformService { private WaveformRepository waveformRepository; private NotificationService notificationService; + private ExampleMatcher ignoreStandardFieldsMatcher = ExampleMatcher.matching().withIgnoreNullValues().withIgnoreCase().withIgnorePaths("id", "version", "associatedPicks", "segment"); @Autowired public WaveformServiceImpl(WaveformRepository waveformRepository, NotificationService notificationService) { @@ -63,6 +66,7 @@ public void setWaveformRepository(WaveformRepository waveformRepository) { @Override public void delete(Waveform waveform) { getWaveformRepository().delete(waveform); + notificationService.post(new WaveformChangeEvent(getIds(waveform)).setDelete(true)); } @Transactional @@ -80,12 +84,19 @@ public List save(Iterable entities) { public void delete(Iterable ids) { List toDelete = getWaveformRepository().findAllById(ids); getWaveformRepository().deleteInBatch(toDelete); + notificationService.post(new WaveformChangeEvent(getIds(toDelete)).setDelete(true)); } @Transactional @Override public Waveform save(Waveform entity) { - return update(entity); + Waveform wave; + if (entity.getId() != null) { + wave = waveformRepository.save(entity); + } else { + wave = update(entity); + } + return wave; } @Override @@ -103,6 +114,11 @@ public List findAll(Iterable ids) { return getWaveformRepository().findAllById(ids); } + @Override + public List findAllMetadata(List ids) { + return getWaveformRepository().findAllMetadataByIds(ids); + } + @Override public List findAll() { return getWaveformRepository().findAll(); @@ -124,49 +140,73 @@ public Class getIdType() { @Transactional @Override public Waveform update(Waveform entry) { - Waveform mergedEntry = attachIfAvailableInRepository(entry); - return waveformRepository.saveAndFlush(mergedEntry); + Waveform mergedEntry = waveformRepository.saveAndFlush(attachIfAvailableInRepository(entry)); + notificationService.post(new WaveformChangeEvent(getIds(mergedEntry)).setAddOrUpdate(true)); + return mergedEntry; } @Transactional @Override - public List update(Long sessionId, Collection values) { + public List update(Long sessionId, List values) { List vals = new ArrayList<>(values.size()); for (Waveform entry : values) { Waveform mergedEntry = attachIfAvailableInRepository(entry); vals.add(mergedEntry); } - CompletableFuture.runAsync(() -> waveformRepository.saveAll(vals)).thenRun(() -> { + CompletableFuture.runAsync(() -> { + List saved = waveformRepository.saveAll(vals); + waveformRepository.flush(); if (sessionId != null) { notificationService.post(new PassFailEvent(sessionId, UUID.randomUUID().toString(), new Result(true, Boolean.TRUE))); + notificationService.post(new WaveformChangeEvent(getIds(saved)).setAddOrUpdate(true)); } }); return vals; } + private List getIds(Waveform waveform) { + return getIds(Collections.singletonList(waveform)); + } + + private List getIds(List vals) { + return vals.stream().map(Waveform::getId).collect(Collectors.toList()); + } + private Waveform attachIfAvailableInRepository(Waveform entry) { Waveform mergedEntry = null; - if (entry.getId() != null) { - mergedEntry = waveformRepository.findById(entry.getId()).get(); - } - if (mergedEntry != null) { - mergedEntry = mergedEntry.mergeNonNullOrEmptyFields(entry); - } else { - mergedEntry = entry; + if (entry != null) { + if (entry.getId() != null) { + mergedEntry = waveformRepository.findById(entry.getId()).get(); + } else if (entry.getEvent() != null && entry.getStream() != null && entry.getStream().getStation() != null && entry.getLowFrequency() != null && entry.getHighFrequency() != null) { + mergedEntry = waveformRepository.findByUniqueFields( + entry.getEvent().getEventId(), + entry.getStream().getStation().getNetworkName(), + entry.getStream().getStation().getStationName(), + entry.getLowFrequency(), + entry.getHighFrequency()); + } + if (mergedEntry != null) { + mergedEntry = mergedEntry.mergeNonNullOrEmptyFields(entry); + } else { + mergedEntry = entry; + } } return mergedEntry; } @Override public List getAllActiveStacks() { - ExampleMatcher matcher = ExampleMatcher.matchingAll().withIgnoreNullValues().withIgnoreCase().withIgnorePaths("id", "version", "associatedPicks", "segment"); - return waveformRepository.findAll(Example.of(new Waveform().setStream(new Stream().setChannelName(Stream.TYPE_STACK)).setActive(Boolean.TRUE), matcher)); + return getByExampleAllDistinctMatching(new Waveform().setActive(Boolean.TRUE).setStream(new Stream().setChannelName(Stream.TYPE_STACK))); } @Override - public List getByExampleAllMatching(Waveform waveform) { - ExampleMatcher matcher = ExampleMatcher.matching().withIgnoreNullValues().withIgnoreCase().withIgnorePaths("id", "version", "associatedPicks", "segment"); - return waveformRepository.findAll(Example.of(waveform, matcher)); + public List getAllStacks() { + return getByExampleAllDistinctMatching(new Waveform().setStream(new Stream().setChannelName(Stream.TYPE_STACK))); + } + + @Override + public List getByExampleAllDistinctMatching(Waveform waveform) { + return Optional.ofNullable(waveformRepository.findAll(Example.of(waveform, ignoreStandardFieldsMatcher))).orElseGet(ArrayList::new).stream().distinct().collect(Collectors.toList()); } @Transactional(propagation = Propagation.NOT_SUPPORTED) @@ -184,4 +224,33 @@ public Event findEventById(String eventId) { return new Event(); } } + + @Override + public List setActiveFlagForIds(List selectedWaveforms, boolean active) { + List waveforms = waveformRepository.findAllById(selectedWaveforms); + waveforms.forEach(w -> w.setActive(active)); + waveformRepository.saveAll(waveforms); + notificationService.post(new WaveformChangeEvent(selectedWaveforms).setAddOrUpdate(true)); + return selectedWaveforms; + } + + @Override + public List setActiveFlagByEventId(String eventId, boolean active) { + List ids = new ArrayList<>(); + if (waveformRepository.setActiveByEventId(eventId, active) > 0) { + ids.addAll(waveformRepository.findAllIdsByEventId(eventId)); + notificationService.post(new WaveformChangeEvent(ids).setAddOrUpdate(true)); + } + return ids; + } + + @Override + public List setActiveFlagByStationName(String stationName, boolean active) { + List ids = new ArrayList<>(); + if (waveformRepository.setActiveByStationName(stationName, active) > 0) { + ids.addAll(waveformRepository.findAllIdsByStationName(stationName)); + notificationService.post(new WaveformChangeEvent(ids).setAddOrUpdate(true)); + } + return ids; + } } diff --git a/common-service/common-service-impl/src/main/java/gov/llnl/gnem/apps/coda/common/service/util/WaveformUtils.java b/common-service/common-service-impl/src/main/java/gov/llnl/gnem/apps/coda/common/service/util/WaveformUtils.java index 9f0462ec..94801313 100644 --- a/common-service/common-service-impl/src/main/java/gov/llnl/gnem/apps/coda/common/service/util/WaveformUtils.java +++ b/common-service/common-service-impl/src/main/java/gov/llnl/gnem/apps/coda/common/service/util/WaveformUtils.java @@ -26,49 +26,7 @@ import llnl.gnem.core.waveform.seismogram.TimeSeries; public class WaveformUtils { - - // TODO: Make these configurable - // In KM/s - private static double groupVelocityDenominator = 10.0; - // In Seconds - private static long noiseWindowOffset = 20l; - - /** - * @param distance - * in kilometers between event and station recording it. This is - * used to compute the predicted start and end arrival time - * windows based on the group velocity. - * @param origintime - * event origin time - * @param segment - * the segment of the waveform to use for computing the noise - * window - * @return {@link TimeSeries} containing the calculated noise window offset - * from the origin time - * @throws IllegalArgumentException - * if the predicted time windows do not align with the actual - * envelope (predicted start > end of the recorded waveform, - * etc.) - */ - //FIXME: This mean value calculation is fundamentally not generalizable across frequency bands and regions and needs to be updated. - public static TimeSeries getNoiseWindow(double distance, TimeT origintime, TimeSeries segment) { - - TimeSeries result1 = new TimeSeries(segment); - result1.cut(origintime.subtract(noiseWindowOffset), origintime); - double mean1 = result1.getMean(); - - TimeSeries result2 = new TimeSeries(segment); - double groupVelocity = distance / groupVelocityDenominator; - TimeT noiseStart = origintime.subtract(noiseWindowOffset); - TimeT noiseEnd = origintime.add(groupVelocity); - - result2.cut(noiseStart, noiseEnd); - double mean2 = result2.getMean(); - - return mean1 > mean2 ? result2 : result1; - } - - public static double getNoiseFloor(Double[] waveform) { + public static double getNoiseFloor(double[] waveform) { DescriptiveStatistics stats = new DescriptiveStatistics(); double[] values = new double[waveform.length]; for (int i = 0; i < waveform.length; i++) { @@ -121,15 +79,15 @@ public static double[] getMaxTime(TimeSeries waveform, TimeT originTime) { } - public static float[] doublesToFloats(Double[] x) { + public static float[] doublesToFloats(double[] x) { float[] xfloats = new float[x.length]; - IntStream.range(0, x.length).parallel().forEach(i -> xfloats[i] = x[i].floatValue()); + IntStream.range(0, x.length).parallel().forEach(i -> xfloats[i] = (float) x[i]); return xfloats; } - public static Double[] floatsToDoubles(float[] x) { - Double[] xdoubles = new Double[x.length]; - IntStream.range(0, x.length).parallel().forEach(i -> xdoubles[i] = new Double(x[i])); + public static double[] floatsToDoubles(float[] x) { + double[] xdoubles = new double[x.length]; + IntStream.range(0, x.length).parallel().forEach(i -> xdoubles[i] = x[i]); return xdoubles; } diff --git a/common-service/common-service-impl/src/test/java/gov/llnl/gnem/apps/coda/common/service/CommonServiceTestContext.java b/common-service/common-service-impl/src/test/java/gov/llnl/gnem/apps/coda/common/service/CommonServiceTestContext.java new file mode 100644 index 00000000..06919365 --- /dev/null +++ b/common-service/common-service-impl/src/test/java/gov/llnl/gnem/apps/coda/common/service/CommonServiceTestContext.java @@ -0,0 +1,31 @@ +/* +* 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.service; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +import gov.llnl.gnem.apps.coda.common.repository.DetachableJpaRepoImpl; + +@SpringBootApplication +@ComponentScan("gov.llnl.gnem.apps.coda.common.application") +@ComponentScan("gov.llnl.gnem.apps.coda.common.service") +@ComponentScan("gov.llnl.gnem.apps.coda.common.repository") +@ComponentScan("gov.llnl.gnem.apps.coda.common.model") +@EntityScan(basePackages = { "gov.llnl.gnem.apps.coda.common" }) +@EnableJpaRepositories(basePackages = { "gov.llnl.gnem.apps.coda.common" }, repositoryBaseClass = DetachableJpaRepoImpl.class) +public class CommonServiceTestContext { +} diff --git a/common-service/common-service-impl/src/test/java/gov/llnl/gnem/apps/coda/common/service/WaveformServiceImplTest.java b/common-service/common-service-impl/src/test/java/gov/llnl/gnem/apps/coda/common/service/WaveformServiceImplTest.java new file mode 100644 index 00000000..fe8b1409 --- /dev/null +++ b/common-service/common-service-impl/src/test/java/gov/llnl/gnem/apps/coda/common/service/WaveformServiceImplTest.java @@ -0,0 +1,103 @@ +package gov.llnl.gnem.apps.coda.common.service; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.time.Instant; +import java.util.Date; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.ContextConfiguration; + +import gov.llnl.gnem.apps.coda.common.model.domain.Event; +import gov.llnl.gnem.apps.coda.common.model.domain.Station; +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 gov.llnl.gnem.apps.coda.common.model.test.annotations.IntTest; +import gov.llnl.gnem.apps.coda.common.repository.WaveformRepository; +import gov.llnl.gnem.apps.coda.common.service.api.NotificationService; +import gov.llnl.gnem.apps.coda.common.service.impl.WaveformServiceImpl; + +@IntTest +@DataJpaTest(showSql = false) +@ContextConfiguration(classes = CommonServiceTestContext.class) +public class WaveformServiceImplTest { + + @Autowired + private WaveformRepository waveformRepository; + + @Autowired + private WaveformServiceImpl waveformService; + + @Autowired + @Mock + private NotificationService notificationService; + + private static final Date zeroDate = Date.from(Instant.EPOCH); + + @Test + public void testSaveDuplicateWaveform() throws Exception { + Waveform initialWaveform = genWaveform(); + waveformService.save(new Waveform().mergeNonNullOrEmptyFields(initialWaveform)); + waveformService.save(new Waveform().mergeNonNullOrEmptyFields(initialWaveform)); + assertThat(waveformService.findAll()).size().isEqualTo(1).describedAs("Should have saved only one waveform entry"); + } + + @Test + public void testSaveWaveformWithChangedPicks() throws Exception { + Waveform initialWaveform = genWaveform(); + Waveform firstWaveform = waveformService.save(new Waveform().mergeNonNullOrEmptyFields(initialWaveform)); + Waveform secondWaveform = waveformService.findOneForUpdate(firstWaveform.getId()); + + secondWaveform.setAssociatedPicks( + secondWaveform.getAssociatedPicks().stream().map(p -> new WaveformPick().mergeNonNullOrEmptyFields(p).setPickTimeSecFromOrigin(-100f)).collect(Collectors.toList())); + secondWaveform = waveformService.save(secondWaveform); + + assertThat(secondWaveform.getAssociatedPicks()).size().isEqualTo(1).describedAs("Should still only have one pick on the waveform itself"); + assertThat(secondWaveform.getAssociatedPicks()).anyMatch(pick -> pick.getPickTimeSecFromOrigin() == -100f).describedAs("Pick should be a -100 offset now"); + } + + @Test + public void testFindByUniqueFields() throws Exception { + Waveform initialWaveform = genWaveform(); + Waveform firstWaveform = waveformService.save(new Waveform().mergeNonNullOrEmptyFields(initialWaveform)); + assertNotNull( + waveformRepository.findByUniqueFields( + firstWaveform.getEvent().getEventId(), + firstWaveform.getStream().getStation().getNetworkName(), + firstWaveform.getStream().getStation().getStationName(), + firstWaveform.getLowFrequency(), + firstWaveform.getHighFrequency()), + "Should be able to find the station by the unique compound key Evid-Net-Sta-Freq"); + } + + @Test + public void testSaveSameStationBandDifferentEvent() throws Exception { + Waveform initialWaveform = genWaveform(); + waveformService.save(new Waveform().mergeNonNullOrEmptyFields(initialWaveform)); + waveformService.save(new Waveform().mergeNonNullOrEmptyFields(initialWaveform).setEvent(initialWaveform.getEvent().setEventId("111"))); + assertThat(waveformService.findAll()).size().isEqualTo(2).describedAs("Should have saved two waveform entries"); + } + + private Waveform genWaveform() { + Waveform w = new Waveform(null, + null, + new Event().setEventId("123").setLatitude(0).setLongitude(0).setOriginTime(zeroDate), + new Stream().setStation(new Station().setLatitude(0).setLongitude(0).setNetworkName("XX").setStationName("STA1")), + zeroDate, + zeroDate, + "vel", + "nm/s", + 1.0, + 1.5, + 4d, + Boolean.TRUE); + w.getAssociatedPicks().add(new WaveformPick().setPickName("f").setPickTimeSecFromOrigin(0f).setPickType("f").setWaveform(w)); + return w; + } +} \ No newline at end of file diff --git a/common-service/common-service-impl/src/test/resources/logback-test.xml b/common-service/common-service-impl/src/test/resources/logback-test.xml new file mode 100644 index 00000000..b22a5cc1 --- /dev/null +++ b/common-service/common-service-impl/src/test/resources/logback-test.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/envelope-gui/src/main/java/gov/llnl/gnem/apps/coda/envelope/gui/AppProperties.java b/envelope-gui/src/main/java/gov/llnl/gnem/apps/coda/envelope/gui/AppProperties.java index 33078c54..c642dd6b 100644 --- a/envelope-gui/src/main/java/gov/llnl/gnem/apps/coda/envelope/gui/AppProperties.java +++ b/envelope-gui/src/main/java/gov/llnl/gnem/apps/coda/envelope/gui/AppProperties.java @@ -15,16 +15,14 @@ package gov.llnl.gnem.apps.coda.envelope.gui; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; -@Component @ConfigurationProperties("envelope-app") public class AppProperties { private String baseTitle = "Envelope Creator"; private Integer height = 900; private Integer width = 800; - private Boolean debugEnabled = false; + private Boolean debugEnabled = Boolean.FALSE; public Boolean getDebugEnabled() { return debugEnabled; diff --git a/envelope-gui/src/main/java/gov/llnl/gnem/apps/coda/envelope/gui/GuiApplication.java b/envelope-gui/src/main/java/gov/llnl/gnem/apps/coda/envelope/gui/GuiApplication.java index 70a8df36..bf647b0b 100644 --- a/envelope-gui/src/main/java/gov/llnl/gnem/apps/coda/envelope/gui/GuiApplication.java +++ b/envelope-gui/src/main/java/gov/llnl/gnem/apps/coda/envelope/gui/GuiApplication.java @@ -157,7 +157,7 @@ public void stop() throws Exception { springContext.stop(); springContext.close(); }).get(1, TimeUnit.SECONDS); - } catch (TimeoutException | ExecutionException | CancellationException | InterruptedException e) { + } catch (TimeoutException | ExecutionException | CancellationException e) { } Platform.exit(); System.exit(0); diff --git a/envelope-gui/src/main/java/gov/llnl/gnem/apps/coda/envelope/gui/controllers/WaveformLoadingController.java b/envelope-gui/src/main/java/gov/llnl/gnem/apps/coda/envelope/gui/controllers/WaveformLoadingController.java index 76796916..d1ad6975 100644 --- a/envelope-gui/src/main/java/gov/llnl/gnem/apps/coda/envelope/gui/controllers/WaveformLoadingController.java +++ b/envelope-gui/src/main/java/gov/llnl/gnem/apps/coda/envelope/gui/controllers/WaveformLoadingController.java @@ -30,7 +30,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import com.google.common.eventbus.EventBus; @@ -49,7 +48,6 @@ import llnl.gnem.core.waveform.seismogram.TimeSeries; @Component -@ConfigurationProperties("envelope-app.waveform.client") public class WaveformLoadingController extends AbstractSeismogramSaveLoadController { private static final Logger log = LoggerFactory.getLogger(WaveformLoadingController.class); @@ -158,7 +156,7 @@ public void stackEnvelopes(TreeMap> evidStaFreqMap) { if (rawWaveform != null && rawWaveform.getSegment() != null && rawWaveform.getSegment().length > 0) { float[] fData = new float[rawWaveform.getSegment().length]; for (int j = 0; j < fData.length; ++j) { - fData[j] = rawWaveform.getSegment()[j].floatValue(); + fData[j] = (float) rawWaveform.getSegment()[j]; } TimeSeries seis = new TimeSeries(fData, rawWaveform.getSampleRate(), new TimeT(rawWaveform.getBeginTime())); if (stackedSeries == null) { @@ -223,9 +221,9 @@ public void stackEnvelopes(TreeMap> evidStaFreqMap) { if (nseismograms > 1) { stackedSeries.MultiplyScalar(1 / ((double) nseismograms)); float[] stackedData = stackedSeries.getData(); - Double[] data = new Double[stackedData.length]; + double[] data = new double[stackedData.length]; for (int i = 0; i < data.length; ++i) { - data[i] = new Double(stackedData[i]); + data[i] = stackedData[i]; } stackedWaveform.setSegment(data); stackedWaveform.getStream().setChannelName("STACK"); diff --git a/envelope-gui/src/main/java/gov/llnl/gnem/apps/coda/envelope/gui/data/client/EnvelopeWebClient.java b/envelope-gui/src/main/java/gov/llnl/gnem/apps/coda/envelope/gui/data/client/EnvelopeWebClient.java index 94640092..403a92c5 100644 --- a/envelope-gui/src/main/java/gov/llnl/gnem/apps/coda/envelope/gui/data/client/EnvelopeWebClient.java +++ b/envelope-gui/src/main/java/gov/llnl/gnem/apps/coda/envelope/gui/data/client/EnvelopeWebClient.java @@ -71,7 +71,7 @@ public Flux postEnvelopes(Long sessionId, List segments, Env Mono>> respMono = resp.bodyToMono(POST_ENV_RETURN_TYPE); return respMono.doOnError(e -> log.error(resp.toString())).doOnError(e -> log.error(e.getMessage(), e)).flatMapMany(results -> { if (results.isSuccess()) { - return Flux.fromStream(results.getResultPayload().orElse(new ArrayList()).stream()); + return Flux.fromStream(results.getResultPayload().orElseGet(() -> new ArrayList()).stream()); } else { return Flux.empty(); } diff --git a/envelope-gui/src/main/resources/application.properties b/envelope-gui/src/main/resources/application.properties index b1a785d1..7e8a4241 100644 --- a/envelope-gui/src/main/resources/application.properties +++ b/envelope-gui/src/main/resources/application.properties @@ -1,3 +1,4 @@ +spring.output.ansi.enabled=ALWAYS logging.level.org.springframework.web.socket.*=off logging.level.org.springframework.web.reactive.function.client.*=off logging.level.org.springframework.web.socket.sockjs.client.SockJsClient=off diff --git a/envelope-service/envelope-application/pom.xml b/envelope-service/envelope-application/pom.xml index 6d1f1e20..17426746 100644 --- a/envelope-service/envelope-application/pom.xml +++ b/envelope-service/envelope-application/pom.xml @@ -91,12 +91,32 @@ springlets-data-commons - io.springlets - springlets-web + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + + org.springframework.boot - spring-boot-starter-web + spring-boot-starter-jetty + + + org.eclipse.jetty + jetty-server + + + + + org.eclipse.jetty + jetty-alpn-conscrypt-server + + + org.eclipse.jetty.http2 + http2-server gov.llnl.gnem.apps.coda.common diff --git a/envelope-service/envelope-application/src/main/resources/application-dev.properties b/envelope-service/envelope-application/src/main/resources/application-dev.properties index eba2cb11..f4d6c748 100644 --- a/envelope-service/envelope-application/src/main/resources/application-dev.properties +++ b/envelope-service/envelope-application/src/main/resources/application-dev.properties @@ -1,8 +1,10 @@ +spring.output.ansi.enabled=ALWAYS +spring.jpa.open-in-view=false logging.level.org.hibernate.SQL=warn logging.level.root=INFO logging.level.gov.llnl.gnem.apps.coda.*=INFO spring.datasource.driver-class-name=org.h2.Driver -spring.datasource.url=jdbc\:h2\:file\:./codaH2.db;DB_CLOSE_DELAY\=-1;DB_CLOSE_ON_EXIT=FALSE;COMPRESS=TRUE +spring.datasource.url=jdbc:h2:file:./codaH2.db;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;COMPRESS=TRUE spring.messages.cache-duration=0 server.port=53922 spring.jpa.hibernate.ddl-auto=update @@ -17,3 +19,4 @@ spring.jpa.properties.hibernate.jdbc.time_zone = UTC server.compression.enabled=true server.compression.mime-types=text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json server.compression.min-response-size=1024 +server.http2.enabled=true \ No newline at end of file diff --git a/envelope-service/envelope-application/src/main/resources/application-file.properties b/envelope-service/envelope-application/src/main/resources/application-file.properties index b7d10dae..ee19ce05 100644 --- a/envelope-service/envelope-application/src/main/resources/application-file.properties +++ b/envelope-service/envelope-application/src/main/resources/application-file.properties @@ -1,8 +1,9 @@ +spring.output.ansi.enabled=ALWAYS +spring.jpa.open-in-view=false logging.level.root=ERROR logging.level.gov.llnl.gnem.apps.coda.*=INFO spring.datasource.driver-class-name=org.h2.Driver -spring.datasource.url=jdbc\:h2\:./codaH2.db;DB_CLOSE_DELAY\=-1;COMPRESS=TRUE;DB_CLOSE_ON_EXIT=FALSE;AUTO_SERVER=TRUE;AUTO_SERVER_PORT=9999 -spring.jpa.hibernate.naming.strategy=org.hibernate.cfg.ImprovedNamingStrategy +spring.datasource.url=jdbc:h2:./codaH2.db;DB_CLOSE_DELAY=-1;COMPRESS=TRUE;DB_CLOSE_ON_EXIT=FALSE;AUTO_SERVER=TRUE;AUTO_SERVER_PORT=9999 server.port=53922 spring.jpa.hibernate.ddl-auto=update server.ssl.key-alias=selfsigned @@ -17,3 +18,4 @@ spring.jpa.properties.hibernate.jdbc.time_zone = UTC server.compression.enabled=true server.compression.mime-types=text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json server.compression.min-response-size=1024 +server.http2.enabled=true \ No newline at end of file diff --git a/envelope-service/envelope-application/src/main/resources/application.properties b/envelope-service/envelope-application/src/main/resources/application.properties index 264b8296..f29f755e 100644 --- a/envelope-service/envelope-application/src/main/resources/application.properties +++ b/envelope-service/envelope-application/src/main/resources/application.properties @@ -1,3 +1,4 @@ +spring.output.ansi.enabled=ALWAYS logging.level.root=ERROR logging.level.gov.llnl.gnem.apps.coda.*=INFO spring.datasource.driver-class-name=org.h2.Driver @@ -14,3 +15,4 @@ spring.jpa.properties.hibernate.jdbc.time_zone = UTC server.compression.enabled=true server.compression.mime-types=text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json server.compression.min-response-size=1024 +server.http2.enabled=true \ No newline at end of file diff --git a/envelope-service/envelope-model/src/main/java/gov/llnl/gnem/apps/coda/envelope/model/domain/EnvelopeJob.java b/envelope-service/envelope-model/src/main/java/gov/llnl/gnem/apps/coda/envelope/model/domain/EnvelopeJob.java index 5ea1fd3b..2d208609 100644 --- a/envelope-service/envelope-model/src/main/java/gov/llnl/gnem/apps/coda/envelope/model/domain/EnvelopeJob.java +++ b/envelope-service/envelope-model/src/main/java/gov/llnl/gnem/apps/coda/envelope/model/domain/EnvelopeJob.java @@ -85,7 +85,7 @@ public boolean equals(Object obj) { @Override public String toString() { StringBuilder builder = new StringBuilder(); - builder.append("\"").append(jobConfig).append("\", \"").append(data).append("\""); + builder.append("\"").append(jobConfig).append("\", \"").append(data).append('\"'); return builder.toString(); } diff --git a/envelope-standalone/src/main/java/gov/llnl/gnem/apps/coda/envelope/standalone/EnvelopeStandalone.java b/envelope-standalone/src/main/java/gov/llnl/gnem/apps/coda/envelope/standalone/EnvelopeStandalone.java index fff873d2..a074becc 100644 --- a/envelope-standalone/src/main/java/gov/llnl/gnem/apps/coda/envelope/standalone/EnvelopeStandalone.java +++ b/envelope-standalone/src/main/java/gov/llnl/gnem/apps/coda/envelope/standalone/EnvelopeStandalone.java @@ -106,7 +106,7 @@ public void stop() throws Exception { springContext.stop(); springContext.close(); }).get(1, TimeUnit.SECONDS); - } catch (TimeoutException | ExecutionException | CancellationException | InterruptedException e) { + } catch (TimeoutException | ExecutionException | CancellationException e) { } Platform.exit(); System.exit(0); diff --git a/envelope-standalone/src/main/java/gov/llnl/gnem/apps/coda/envelope/standalone/data/client/EnvelopeLocalClient.java b/envelope-standalone/src/main/java/gov/llnl/gnem/apps/coda/envelope/standalone/data/client/EnvelopeLocalClient.java index bbb6433b..a42fb584 100644 --- a/envelope-standalone/src/main/java/gov/llnl/gnem/apps/coda/envelope/standalone/data/client/EnvelopeLocalClient.java +++ b/envelope-standalone/src/main/java/gov/llnl/gnem/apps/coda/envelope/standalone/data/client/EnvelopeLocalClient.java @@ -38,7 +38,7 @@ public class EnvelopeLocalClient implements EnvelopeClient { private EnvelopeCreationService service; private WaveformService waveformService; - + private static final Logger log = LoggerFactory.getLogger(EnvelopeLocalClient.class); @Autowired @@ -49,12 +49,12 @@ public EnvelopeLocalClient(EnvelopeCreationService service, WaveformService wave @Override public Mono getEnvelopeFromId(Long id) { - return Mono.just(Optional.ofNullable(waveformService.findOne(id)).orElse(new Waveform())); + return Mono.just(Optional.ofNullable(waveformService.findOne(id)).orElseGet(() -> new Waveform())); } @Override public Flux getEnvelopesMatchingAllFields(Waveform segment) { - return Flux.fromIterable(waveformService.getByExampleAllMatching(segment)).onErrorReturn(new Waveform()); + return Flux.fromIterable(waveformService.getByExampleAllDistinctMatching(segment)).onErrorReturn(new Waveform()); } @Override @@ -69,7 +69,7 @@ public Flux postEnvelopes(Long sessionId, List segments) { @Override public Flux postEnvelopes(Long sessionId, List segments, EnvelopeJobConfiguration conf) { - return Flux.fromIterable(service.createEnvelopes(sessionId, segments, conf).getResultPayload().orElse(new ArrayList())); + return Flux.fromIterable(service.createEnvelopes(sessionId, segments, conf).getResultPayload().orElseGet(() -> new ArrayList())); } } diff --git a/envelope-standalone/src/main/resources/application-file.properties b/envelope-standalone/src/main/resources/application-file.properties index f9141dfc..2f3a80af 100644 --- a/envelope-standalone/src/main/resources/application-file.properties +++ b/envelope-standalone/src/main/resources/application-file.properties @@ -1,8 +1,9 @@ +spring.output.ansi.enabled=ALWAYS +spring.jpa.open-in-view=false logging.level.root=ERROR logging.level.gov.llnl.gnem.apps.coda.*=INFO spring.datasource.driver-class-name=org.h2.Driver -spring.datasource.url=jdbc\:h2\:./codaH2.db;DB_CLOSE_DELAY\=-1;COMPRESS=TRUE;DB_CLOSE_ON_EXIT=FALSE;AUTO_SERVER=TRUE;AUTO_SERVER_PORT=9999 -spring.jpa.hibernate.naming.strategy=org.hibernate.cfg.ImprovedNamingStrategy +spring.datasource.url=jdbc:h2:./codaH2.db;DB_CLOSE_DELAY=-1;COMPRESS=TRUE;DB_CLOSE_ON_EXIT=FALSE;AUTO_SERVER=TRUE;AUTO_SERVER_PORT=9999 server.port=53922 spring.jpa.hibernate.ddl-auto=create server.ssl.key-alias=selfsigned @@ -17,3 +18,4 @@ spring.jpa.properties.hibernate.jdbc.time_zone = UTC server.compression.enabled=true server.compression.mime-types=text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json server.compression.min-response-size=1024 +server.http2.enabled=true \ No newline at end of file diff --git a/envelope-standalone/src/main/resources/application.properties b/envelope-standalone/src/main/resources/application.properties index 1ed19ca2..0c470c26 100644 --- a/envelope-standalone/src/main/resources/application.properties +++ b/envelope-standalone/src/main/resources/application.properties @@ -1,3 +1,5 @@ +spring.output.ansi.enabled=ALWAYS +spring.jpa.open-in-view=false logging.level.org.springframework.web.socket.*=off logging.level.org.springframework.web.reactive.function.client.*=off logging.level.org.springframework.web.socket.sockjs.client.SockJsClient=off @@ -22,3 +24,4 @@ spring.jpa.properties.hibernate.jdbc.time_zone = UTC server.compression.enabled=true server.compression.mime-types=text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json server.compression.min-response-size=1024 +server.http2.enabled=true \ No newline at end of file diff --git a/externals/src/main/java/llnl/gnem/core/gui/plotting/DrawingUnits.java b/externals/src/main/java/llnl/gnem/core/gui/plotting/DrawingUnits.java index f82ea889..b13194c6 100755 --- a/externals/src/main/java/llnl/gnem/core/gui/plotting/DrawingUnits.java +++ b/externals/src/main/java/llnl/gnem/core/gui/plotting/DrawingUnits.java @@ -27,6 +27,11 @@ */ public class DrawingUnits { + private static final double PixelsPerHorizUnit = 72.0 / 25.4; + // Units are assumed to be millimeters + private static final double PixelsPerVertUnit = 72.0 / 25.4; + // Units are assumed to be millimeters + /** * Gets the horizontal pixel equivalent of a value in millimeters for this * graphics context @@ -84,9 +89,4 @@ public double getVertPixelsToUnits(int u) { public double getPixelsPerUnit() { return (PixelsPerHorizUnit + PixelsPerVertUnit) / 2; } - - private final double PixelsPerHorizUnit = 72.0 / 25.4; - // Units are assumed to be millimeters - private final double PixelsPerVertUnit = 72.0 / 25.4; - // Units are assumed to be millimeters } diff --git a/externals/src/main/java/llnl/gnem/core/gui/plotting/JPlotContainer.java b/externals/src/main/java/llnl/gnem/core/gui/plotting/JPlotContainer.java index 38f9f88e..bc95c70f 100755 --- a/externals/src/main/java/llnl/gnem/core/gui/plotting/JPlotContainer.java +++ b/externals/src/main/java/llnl/gnem/core/gui/plotting/JPlotContainer.java @@ -21,12 +21,11 @@ import java.awt.print.PrinterJob; import java.io.File; import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.io.Writer; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Collection; @@ -361,9 +360,8 @@ public void exportSVG(File file) throws UnsupportedEncodingException, FileNotFou // Finally, stream out SVG to the standard output using // UTF-8 encoding. - boolean useCSS = true; // we want to use CSS style attributes - OutputStream stream = new FileOutputStream(file); - try (Writer out = new OutputStreamWriter(stream, "UTF-8")) { + boolean useCSS = true; // we want to use CSS style attributes + try (Writer out = new OutputStreamWriter(Files.newOutputStream(file.toPath()), "UTF-8")) { svgGenerator.stream(out, useCSS); } catch (IOException e) { log.error("Unable to write file {}", file.getAbsolutePath(), e); @@ -452,6 +450,7 @@ public static BufferedImage createBufferedImage(int dpi, final JPlotContainer gu gui.setPolyLineUsage(true); gui.setForceFullRender(false); cm.setDoubleBufferingEnabled(true); + g.dispose(); return bi; } diff --git a/externals/src/main/java/llnl/gnem/core/gui/plotting/PickCreationInfo.java b/externals/src/main/java/llnl/gnem/core/gui/plotting/PickCreationInfo.java index 7d26b944..e5162950 100755 --- a/externals/src/main/java/llnl/gnem/core/gui/plotting/PickCreationInfo.java +++ b/externals/src/main/java/llnl/gnem/core/gui/plotting/PickCreationInfo.java @@ -26,14 +26,15 @@ */ public class PickCreationInfo { public PlotObject getSelectedObject() { - if (clickedObject != null && clickedObject instanceof Line) { + if (clickedObject instanceof Line) { return clickedObject; } else { if (owningPlot != null && owningPlot.getLineCount() == 1) { Line[] lines = owningPlot.getLines(); return lines[0]; - } else + } else { return null; + } } } diff --git a/externals/src/main/java/llnl/gnem/core/gui/plotting/SymbolLegend.java b/externals/src/main/java/llnl/gnem/core/gui/plotting/SymbolLegend.java index 8d3a1dc7..c0591865 100755 --- a/externals/src/main/java/llnl/gnem/core/gui/plotting/SymbolLegend.java +++ b/externals/src/main/java/llnl/gnem/core/gui/plotting/SymbolLegend.java @@ -21,7 +21,7 @@ import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; -import java.util.ArrayList; +import java.util.List; import llnl.gnem.core.gui.plotting.plotobject.PlotObject; import llnl.gnem.core.gui.plotting.plotobject.Symbol; @@ -33,7 +33,7 @@ */ public class SymbolLegend extends PlotObject { - private ArrayList legendEntries; + private List legendEntries; private String fontName; private double fontSize; private HorizPinEdge horAlign; @@ -41,7 +41,7 @@ public class SymbolLegend extends PlotObject { private double xOffset; private double yOffset; - public SymbolLegend(ArrayList entries, String fontName, double fontSize, HorizPinEdge hAlign, VertPinEdge vAlign, double xOff, double yOff) { + public SymbolLegend(List entries, String fontName, double fontSize, HorizPinEdge hAlign, VertPinEdge vAlign, double xOff, double yOff) { this.legendEntries = entries; this.fontName = fontName; this.fontSize = fontSize; @@ -106,7 +106,7 @@ private int getLegendWidth(JBasicPlot owner, FontMetrics fm) { int advance = fm.stringWidth(a_Text.getText()); maxlen = Math.max(maxlen, advance); } - double minLineLen = 15.0; + double minLineLen = 8.0; // millimeters return maxlen + owner.getUnitsMgr().getHorizUnitsToPixels(minLineLen) + 5; } diff --git a/externals/src/main/java/llnl/gnem/core/gui/plotting/color/ColorMap.java b/externals/src/main/java/llnl/gnem/core/gui/plotting/color/ColorMap.java new file mode 100644 index 00000000..07b25cb9 --- /dev/null +++ b/externals/src/main/java/llnl/gnem/core/gui/plotting/color/ColorMap.java @@ -0,0 +1,27 @@ +/* +* 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 llnl.gnem.core.gui.plotting.color; + +import java.awt.Color; + +public interface ColorMap { + + public Color getColor(final double value); + + public void setRange(double min, double max); + + public double getMin(); + + public double getMax(); +} \ No newline at end of file diff --git a/externals/src/main/java/llnl/gnem/core/gui/plotting/color/LinearInterpolatedGradientColorMap.java b/externals/src/main/java/llnl/gnem/core/gui/plotting/color/LinearInterpolatedGradientColorMap.java new file mode 100644 index 00000000..40867158 --- /dev/null +++ b/externals/src/main/java/llnl/gnem/core/gui/plotting/color/LinearInterpolatedGradientColorMap.java @@ -0,0 +1,81 @@ +/* +* 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 llnl.gnem.core.gui.plotting.color; + +import java.awt.Color; + +import llnl.gnem.core.util.PairT; + +public abstract class LinearInterpolatedGradientColorMap implements ColorMap { + private static final int red = 0; + private static final int green = 1; + private static final int blue = 2; + protected float[][] rgb; + private double min; + private double max; + + @Override + public void setRange(double min, double max) { + if (max < min) { + max = 2. * min; + } + + this.min = min; + this.max = max; + } + + @Override + public Color getColor(final double value) { + PairT index = getIndex(value); + int idx = index.getFirst(); + float pct2 = index.getSecond(); + float pct1; + Color color1; + Color color2 = new Color(rgb[idx][red], rgb[idx][green], rgb[idx][blue]); + float epsilon = (float) 1E-12; + if (idx != 0 && 1f - pct2 > epsilon) { + color1 = new Color(rgb[idx - 1][red], rgb[idx - 1][green], rgb[idx - 1][blue]); + pct1 = 1.0f - pct2; + color2 = combineColors(color1, pct1, color2, pct2); + } else if (idx != rgb.length - 1 && 1f - pct2 > epsilon) { + color1 = new Color(rgb[idx + 1][red], rgb[idx + 1][green], rgb[idx + 1][blue]); + pct1 = 1.0f - pct2; + color2 = combineColors(color1, pct1, color2, pct2); + } + return color2; + } + + private Color combineColors(Color color1, float pct1, Color color2, float pct2) { + return new Color((color1.getRed() / 255f) * pct1 + (color2.getRed() / 255f) * pct2, + (color1.getGreen() / 255f) * pct1 + (color2.getGreen() / 255f) * pct2, + (color1.getBlue() / 255f) * pct1 + (color2.getBlue() / 255f) * pct2); + } + + @Override + public double getMin() { + return min; + } + + @Override + public double getMax() { + return max; + } + + private PairT getIndex(double value) { + value = Math.max(Math.min(max, value), min); + double frac = (value - min) * (rgb.length - 1) / (max - min); + int index = rgb.length - 1 - (int) (frac); + return new PairT(index, 1.0f - (float) frac % 1); + } +} diff --git a/externals/src/main/java/llnl/gnem/core/gui/plotting/color/ViridisColorMap.java b/externals/src/main/java/llnl/gnem/core/gui/plotting/color/ViridisColorMap.java new file mode 100644 index 00000000..c17456dd --- /dev/null +++ b/externals/src/main/java/llnl/gnem/core/gui/plotting/color/ViridisColorMap.java @@ -0,0 +1,77 @@ +/* +* 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 llnl.gnem.core.gui.plotting.color; + +public class ViridisColorMap extends LinearInterpolatedGradientColorMap { + + /*** + * Implements a variant of the Viridis color scale created by Stéfan van der + * Walt and Nathaniel Smith for the Python matplotlib library. + */ + public ViridisColorMap() { + rgb = new float[][] { { 0.267004f, 0.004874f, 0.329415f }, { 0.268510f, 0.009605f, 0.335427f }, { 0.269944f, 0.014625f, 0.341379f }, { 0.271305f, 0.019942f, 0.347269f }, + { 0.272594f, 0.025563f, 0.353093f }, { 0.273809f, 0.031497f, 0.358853f }, { 0.274952f, 0.037752f, 0.364543f }, { 0.276022f, 0.044167f, 0.370164f }, { 0.277018f, 0.050344f, 0.375715f }, + { 0.277941f, 0.056324f, 0.381191f }, { 0.278791f, 0.062145f, 0.386592f }, { 0.279566f, 0.067836f, 0.391917f }, { 0.280267f, 0.073417f, 0.397163f }, { 0.280894f, 0.078907f, 0.402329f }, + { 0.281446f, 0.084320f, 0.407414f }, { 0.281924f, 0.089666f, 0.412415f }, { 0.282327f, 0.094955f, 0.417331f }, { 0.282656f, 0.100196f, 0.422160f }, { 0.282910f, 0.105393f, 0.426902f }, + { 0.283091f, 0.110553f, 0.431554f }, { 0.283197f, 0.115680f, 0.436115f }, { 0.283229f, 0.120777f, 0.440584f }, { 0.283187f, 0.125848f, 0.444960f }, { 0.283072f, 0.130895f, 0.449241f }, + { 0.282884f, 0.135920f, 0.453427f }, { 0.282623f, 0.140926f, 0.457517f }, { 0.282290f, 0.145912f, 0.461510f }, { 0.281887f, 0.150881f, 0.465405f }, { 0.281412f, 0.155834f, 0.469201f }, + { 0.280868f, 0.160771f, 0.472899f }, { 0.280255f, 0.165693f, 0.476498f }, { 0.279574f, 0.170599f, 0.479997f }, { 0.278826f, 0.175490f, 0.483397f }, { 0.278012f, 0.180367f, 0.486697f }, + { 0.277134f, 0.185228f, 0.489898f }, { 0.276194f, 0.190074f, 0.493001f }, { 0.275191f, 0.194905f, 0.496005f }, { 0.274128f, 0.199721f, 0.498911f }, { 0.273006f, 0.204520f, 0.501721f }, + { 0.271828f, 0.209303f, 0.504434f }, { 0.270595f, 0.214069f, 0.507052f }, { 0.269308f, 0.218818f, 0.509577f }, { 0.267968f, 0.223549f, 0.512008f }, { 0.266580f, 0.228262f, 0.514349f }, + { 0.265145f, 0.232956f, 0.516599f }, { 0.263663f, 0.237631f, 0.518762f }, { 0.262138f, 0.242286f, 0.520837f }, { 0.260571f, 0.246922f, 0.522828f }, { 0.258965f, 0.251537f, 0.524736f }, + { 0.257322f, 0.256130f, 0.526563f }, { 0.255645f, 0.260703f, 0.528312f }, { 0.253935f, 0.265254f, 0.529983f }, { 0.252194f, 0.269783f, 0.531579f }, { 0.250425f, 0.274290f, 0.533103f }, + { 0.248629f, 0.278775f, 0.534556f }, { 0.246811f, 0.283237f, 0.535941f }, { 0.244972f, 0.287675f, 0.537260f }, { 0.243113f, 0.292092f, 0.538516f }, { 0.241237f, 0.296485f, 0.539709f }, + { 0.239346f, 0.300855f, 0.540844f }, { 0.237441f, 0.305202f, 0.541921f }, { 0.235526f, 0.309527f, 0.542944f }, { 0.233603f, 0.313828f, 0.543914f }, { 0.231674f, 0.318106f, 0.544834f }, + { 0.229739f, 0.322361f, 0.545706f }, { 0.227802f, 0.326594f, 0.546532f }, { 0.225863f, 0.330805f, 0.547314f }, { 0.223925f, 0.334994f, 0.548053f }, { 0.221989f, 0.339161f, 0.548752f }, + { 0.220057f, 0.343307f, 0.549413f }, { 0.218130f, 0.347432f, 0.550038f }, { 0.216210f, 0.351535f, 0.550627f }, { 0.214298f, 0.355619f, 0.551184f }, { 0.212395f, 0.359683f, 0.551710f }, + { 0.210503f, 0.363727f, 0.552206f }, { 0.208623f, 0.367752f, 0.552675f }, { 0.206756f, 0.371758f, 0.553117f }, { 0.204903f, 0.375746f, 0.553533f }, { 0.203063f, 0.379716f, 0.553925f }, + { 0.201239f, 0.383670f, 0.554294f }, { 0.199430f, 0.387607f, 0.554642f }, { 0.197636f, 0.391528f, 0.554969f }, { 0.195860f, 0.395433f, 0.555276f }, { 0.194100f, 0.399323f, 0.555565f }, + { 0.192357f, 0.403199f, 0.555836f }, { 0.190631f, 0.407061f, 0.556089f }, { 0.188923f, 0.410910f, 0.556326f }, { 0.187231f, 0.414746f, 0.556547f }, { 0.185556f, 0.418570f, 0.556753f }, + { 0.183898f, 0.422383f, 0.556944f }, { 0.182256f, 0.426184f, 0.557120f }, { 0.180629f, 0.429975f, 0.557282f }, { 0.179019f, 0.433756f, 0.557430f }, { 0.177423f, 0.437527f, 0.557565f }, + { 0.175841f, 0.441290f, 0.557685f }, { 0.174274f, 0.445044f, 0.557792f }, { 0.172719f, 0.448791f, 0.557885f }, { 0.171176f, 0.452530f, 0.557965f }, { 0.169646f, 0.456262f, 0.558030f }, + { 0.168126f, 0.459988f, 0.558082f }, { 0.166617f, 0.463708f, 0.558119f }, { 0.165117f, 0.467423f, 0.558141f }, { 0.163625f, 0.471133f, 0.558148f }, { 0.162142f, 0.474838f, 0.558140f }, + { 0.160665f, 0.478540f, 0.558115f }, { 0.159194f, 0.482237f, 0.558073f }, { 0.157729f, 0.485932f, 0.558013f }, { 0.156270f, 0.489624f, 0.557936f }, { 0.154815f, 0.493313f, 0.557840f }, + { 0.153364f, 0.497000f, 0.557724f }, { 0.151918f, 0.500685f, 0.557587f }, { 0.150476f, 0.504369f, 0.557430f }, { 0.149039f, 0.508051f, 0.557250f }, { 0.147607f, 0.511733f, 0.557049f }, + { 0.146180f, 0.515413f, 0.556823f }, { 0.144759f, 0.519093f, 0.556572f }, { 0.143343f, 0.522773f, 0.556295f }, { 0.141935f, 0.526453f, 0.555991f }, { 0.140536f, 0.530132f, 0.555659f }, + { 0.139147f, 0.533812f, 0.555298f }, { 0.137770f, 0.537492f, 0.554906f }, { 0.136408f, 0.541173f, 0.554483f }, { 0.135066f, 0.544853f, 0.554029f }, { 0.133743f, 0.548535f, 0.553541f }, + { 0.132444f, 0.552216f, 0.553018f }, { 0.131172f, 0.555899f, 0.552459f }, { 0.129933f, 0.559582f, 0.551864f }, { 0.128729f, 0.563265f, 0.551229f }, { 0.127568f, 0.566949f, 0.550556f }, + { 0.126453f, 0.570633f, 0.549841f }, { 0.125394f, 0.574318f, 0.549086f }, { 0.124395f, 0.578002f, 0.548287f }, { 0.123463f, 0.581687f, 0.547445f }, { 0.122606f, 0.585371f, 0.546557f }, + { 0.121831f, 0.589055f, 0.545623f }, { 0.121148f, 0.592739f, 0.544641f }, { 0.120565f, 0.596422f, 0.543611f }, { 0.120092f, 0.600104f, 0.542530f }, { 0.119738f, 0.603785f, 0.541400f }, + { 0.119512f, 0.607464f, 0.540218f }, { 0.119423f, 0.611141f, 0.538982f }, { 0.119483f, 0.614817f, 0.537692f }, { 0.119699f, 0.618490f, 0.536347f }, { 0.120081f, 0.622161f, 0.534946f }, + { 0.120638f, 0.625828f, 0.533488f }, { 0.121380f, 0.629492f, 0.531973f }, { 0.122312f, 0.633153f, 0.530398f }, { 0.123444f, 0.636809f, 0.528763f }, { 0.124780f, 0.640461f, 0.527068f }, + { 0.126326f, 0.644107f, 0.525311f }, { 0.128087f, 0.647749f, 0.523491f }, { 0.130067f, 0.651384f, 0.521608f }, { 0.132268f, 0.655014f, 0.519661f }, { 0.134692f, 0.658636f, 0.517649f }, + { 0.137339f, 0.662252f, 0.515571f }, { 0.140210f, 0.665859f, 0.513427f }, { 0.143303f, 0.669459f, 0.511215f }, { 0.146616f, 0.673050f, 0.508936f }, { 0.150148f, 0.676631f, 0.506589f }, + { 0.153894f, 0.680203f, 0.504172f }, { 0.157851f, 0.683765f, 0.501686f }, { 0.162016f, 0.687316f, 0.499129f }, { 0.166383f, 0.690856f, 0.496502f }, { 0.170948f, 0.694384f, 0.493803f }, + { 0.175707f, 0.697900f, 0.491033f }, { 0.180653f, 0.701402f, 0.488189f }, { 0.185783f, 0.704891f, 0.485273f }, { 0.191090f, 0.708366f, 0.482284f }, { 0.196571f, 0.711827f, 0.479221f }, + { 0.202219f, 0.715272f, 0.476084f }, { 0.208030f, 0.718701f, 0.472873f }, { 0.214000f, 0.722114f, 0.469588f }, { 0.220124f, 0.725509f, 0.466226f }, { 0.226397f, 0.728888f, 0.462789f }, + { 0.232815f, 0.732247f, 0.459277f }, { 0.239374f, 0.735588f, 0.455688f }, { 0.246070f, 0.738910f, 0.452024f }, { 0.252899f, 0.742211f, 0.448284f }, { 0.259857f, 0.745492f, 0.444467f }, + { 0.266941f, 0.748751f, 0.440573f }, { 0.274149f, 0.751988f, 0.436601f }, { 0.281477f, 0.755203f, 0.432552f }, { 0.288921f, 0.758394f, 0.428426f }, { 0.296479f, 0.761561f, 0.424223f }, + { 0.304148f, 0.764704f, 0.419943f }, { 0.311925f, 0.767822f, 0.415586f }, { 0.319809f, 0.770914f, 0.411152f }, { 0.327796f, 0.773980f, 0.406640f }, { 0.335885f, 0.777018f, 0.402049f }, + { 0.344074f, 0.780029f, 0.397381f }, { 0.352360f, 0.783011f, 0.392636f }, { 0.360741f, 0.785964f, 0.387814f }, { 0.369214f, 0.788888f, 0.382914f }, { 0.377779f, 0.791781f, 0.377939f }, + { 0.386433f, 0.794644f, 0.372886f }, { 0.395174f, 0.797475f, 0.367757f }, { 0.404001f, 0.800275f, 0.362552f }, { 0.412913f, 0.803041f, 0.357269f }, { 0.421908f, 0.805774f, 0.351910f }, + { 0.430983f, 0.808473f, 0.346476f }, { 0.440137f, 0.811138f, 0.340967f }, { 0.449368f, 0.813768f, 0.335384f }, { 0.458674f, 0.816363f, 0.329727f }, { 0.468053f, 0.818921f, 0.323998f }, + { 0.477504f, 0.821444f, 0.318195f }, { 0.487026f, 0.823929f, 0.312321f }, { 0.496615f, 0.826376f, 0.306377f }, { 0.506271f, 0.828786f, 0.300362f }, { 0.515992f, 0.831158f, 0.294279f }, + { 0.525776f, 0.833491f, 0.288127f }, { 0.535621f, 0.835785f, 0.281908f }, { 0.545524f, 0.838039f, 0.275626f }, { 0.555484f, 0.840254f, 0.269281f }, { 0.565498f, 0.842430f, 0.262877f }, + { 0.575563f, 0.844566f, 0.256415f }, { 0.585678f, 0.846661f, 0.249897f }, { 0.595839f, 0.848717f, 0.243329f }, { 0.606045f, 0.850733f, 0.236712f }, { 0.616293f, 0.852709f, 0.230052f }, + { 0.626579f, 0.854645f, 0.223353f }, { 0.636902f, 0.856542f, 0.216620f }, { 0.647257f, 0.858400f, 0.209861f }, { 0.657642f, 0.860219f, 0.203082f }, { 0.668054f, 0.861999f, 0.196293f }, + { 0.678489f, 0.863742f, 0.189503f }, { 0.688944f, 0.865448f, 0.182725f }, { 0.699415f, 0.867117f, 0.175971f }, { 0.709898f, 0.868751f, 0.169257f }, { 0.720391f, 0.870350f, 0.162603f }, + { 0.730889f, 0.871916f, 0.156029f }, { 0.741388f, 0.873449f, 0.149561f }, { 0.751884f, 0.874951f, 0.143228f }, { 0.762373f, 0.876424f, 0.137064f }, { 0.772852f, 0.877868f, 0.131109f }, + { 0.783315f, 0.879285f, 0.125405f }, { 0.793760f, 0.880678f, 0.120005f }, { 0.804182f, 0.882046f, 0.114965f }, { 0.814576f, 0.883393f, 0.110347f }, { 0.824940f, 0.884720f, 0.106217f }, + { 0.835270f, 0.886029f, 0.102646f }, { 0.845561f, 0.887322f, 0.099702f }, { 0.855810f, 0.888601f, 0.097452f }, { 0.866013f, 0.889868f, 0.095953f }, { 0.876168f, 0.891125f, 0.095250f }, + { 0.886271f, 0.892374f, 0.095374f }, { 0.896320f, 0.893616f, 0.096335f }, { 0.906311f, 0.894855f, 0.098125f }, { 0.916242f, 0.896091f, 0.100717f }, { 0.926106f, 0.897330f, 0.104071f }, + { 0.935904f, 0.898570f, 0.108131f }, { 0.945636f, 0.899815f, 0.112838f }, { 0.955300f, 0.901065f, 0.118128f }, { 0.964894f, 0.902323f, 0.123941f }, { 0.974417f, 0.903590f, 0.130215f }, + { 0.983868f, 0.904867f, 0.136897f }, { 0.993248f, 0.906157f, 0.143936f } }; + } + +} diff --git a/externals/src/main/java/llnl/gnem/core/gui/plotting/jmultiaxisplot/JPlotMouseListener.java b/externals/src/main/java/llnl/gnem/core/gui/plotting/jmultiaxisplot/JPlotMouseListener.java index cef48a4d..a317fd8b 100755 --- a/externals/src/main/java/llnl/gnem/core/gui/plotting/jmultiaxisplot/JPlotMouseListener.java +++ b/externals/src/main/java/llnl/gnem/core/gui/plotting/jmultiaxisplot/JPlotMouseListener.java @@ -303,7 +303,7 @@ public void mousePressed(MouseEvent me) { } } - if (po != null && po instanceof MarginButton) { + if (po instanceof MarginButton) { marginButton = (MarginButton) po; marginButton.setToDepressedState(myGraphics); } diff --git a/externals/src/main/java/llnl/gnem/core/gui/plotting/jmultiaxisplot/SubplotZoomData.java b/externals/src/main/java/llnl/gnem/core/gui/plotting/jmultiaxisplot/SubplotZoomData.java index dae5503e..4e74eb21 100755 --- a/externals/src/main/java/llnl/gnem/core/gui/plotting/jmultiaxisplot/SubplotZoomData.java +++ b/externals/src/main/java/llnl/gnem/core/gui/plotting/jmultiaxisplot/SubplotZoomData.java @@ -117,7 +117,7 @@ public JSubplot getSubplot() { @Override public String toString() { - StringBuilder sb = new StringBuilder("SubplotZoomData{" + "subplot(" + Integer.toHexString(System.identityHashCode(p)) + "), state=:"); + StringBuilder sb = new StringBuilder("SubplotZoomData{ subplot(").append(Integer.toHexString(System.identityHashCode(p))).append("), state=:"); for (SubplotDisplayInfo sdi : stack) { sb.append("\n\t\t"); sb.append(sdi); diff --git a/externals/src/main/java/llnl/gnem/core/gui/plotting/plotobject/AbstractLine.java b/externals/src/main/java/llnl/gnem/core/gui/plotting/plotobject/AbstractLine.java index 1d82e01e..a7656054 100755 --- a/externals/src/main/java/llnl/gnem/core/gui/plotting/plotobject/AbstractLine.java +++ b/externals/src/main/java/llnl/gnem/core/gui/plotting/plotobject/AbstractLine.java @@ -403,8 +403,13 @@ public static double getDataMax(float[] V) { */ @Override public String toString() { - StringBuilder s = new StringBuilder("Line with attributes: Color = " + color); - s.append(", PaintMode = ").append(Mode).append(", PenStyle = ").append(penStyle).append(", Width = ").append(_Width); + StringBuilder s = new StringBuilder("Line with attributes: Color = ").append(color) + .append(", PaintMode = ") + .append(Mode) + .append(", PenStyle = ") + .append(penStyle) + .append(", Width = ") + .append(_Width); return s.toString(); } @@ -604,8 +609,9 @@ private void RenderSymbols(Graphics2D g2d) { return; } - if (!plotLineSymbols) + if (!plotLineSymbols) { return; + } if (limitPlottedSymbols && Npts > maxSymbolsToPlot) { return; diff --git a/externals/src/main/java/llnl/gnem/core/gui/plotting/plotobject/Line.java b/externals/src/main/java/llnl/gnem/core/gui/plotting/plotobject/Line.java index 66913492..49fdd9c7 100755 --- a/externals/src/main/java/llnl/gnem/core/gui/plotting/plotobject/Line.java +++ b/externals/src/main/java/llnl/gnem/core/gui/plotting/plotobject/Line.java @@ -330,7 +330,7 @@ private int[] getTimeIndex(double requestedTime) { @Override protected int getMinIndex() { - if (owner != null && owner instanceof JSubplot) { + if (owner instanceof JSubplot) { JSubplot plot = (JSubplot) owner; double xmin = plot.getXaxis().getMin(); double ymin = plot.getYaxis().getMin(); @@ -361,7 +361,7 @@ protected int getMinIndex() { @Override protected int getMaxIndex() { - if (owner != null && owner instanceof JSubplot) { + if (owner instanceof JSubplot) { JSubplot plot = (JSubplot) owner; double xmax = plot.getXaxis().getMax(); double ymin = plot.getYaxis().getMin(); diff --git a/externals/src/main/java/llnl/gnem/core/gui/plotting/plotobject/PositionMarker.java b/externals/src/main/java/llnl/gnem/core/gui/plotting/plotobject/PositionMarker.java index 05d7dfa1..c10e58a1 100755 --- a/externals/src/main/java/llnl/gnem/core/gui/plotting/plotobject/PositionMarker.java +++ b/externals/src/main/java/llnl/gnem/core/gui/plotting/plotobject/PositionMarker.java @@ -232,7 +232,7 @@ public String toString() { s.append(f.format(xCenter)); s.append(", "); s.append(f.format(yCenter)); - s.append(")"); + s.append(')'); return s.toString(); } diff --git a/externals/src/main/java/llnl/gnem/core/io/FileDataSource.java b/externals/src/main/java/llnl/gnem/core/io/FileDataSource.java index 834f1f45..a64dbfee 100755 --- a/externals/src/main/java/llnl/gnem/core/io/FileDataSource.java +++ b/externals/src/main/java/llnl/gnem/core/io/FileDataSource.java @@ -12,10 +12,11 @@ import java.io.ByteArrayInputStream; import java.io.DataInputStream; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; +import java.nio.file.Files; +import java.nio.file.Paths; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -55,7 +56,7 @@ public void initiate() { super.initiate(); close(); try { - initiate(new FileInputStream(path)); + initiate(Files.newInputStream(Paths.get(path))); fis.skip(foff); // skip bytes, as necessary } catch (IOException ioe) { log.warn("io.FileDataSource.initiate(): {} ", ioe.getMessage(), ioe); @@ -170,7 +171,7 @@ public void getData(float[] dataArray, int offset, int numRequested) { case CSS_S4: for (int i = 0; i < numSamplesToRead; i++) { - dataArray[i + offset] = (float) dis.readInt(); + dataArray[i + offset] = dis.readInt(); } numSamplesRemaining -= numSamplesToRead; nextSample += numSamplesToRead; @@ -191,9 +192,9 @@ public void getData(float[] dataArray, int offset, int numRequested) { for (int i = 0; i < numSamplesToRead; i++) { if ((0x80 & buffer[ib]) == 0x80) { - dataArray[i + offset] = (float) (((0xff) << 24) + ((buffer[ib++] & 0xff) << 16) + ((buffer[ib++] & 0xff) << 8) + ((buffer[ib++] & 0xff))); + dataArray[i + offset] = ((0xff) << 24) + ((buffer[ib++] & 0xff) << 16) + ((buffer[ib++] & 0xff) << 8) + ((buffer[ib++] & 0xff)); } else { - dataArray[i + offset] = (float) (((0x00) << 24) + ((buffer[ib++] & 0xff) << 16) + ((buffer[ib++] & 0xff) << 8) + ((buffer[ib++] & 0xff))); + dataArray[i + offset] = ((0x00) << 24) + ((buffer[ib++] & 0xff) << 16) + ((buffer[ib++] & 0xff) << 8) + ((buffer[ib++] & 0xff)); } } 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 cddd058a..122270a8 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 @@ -9,11 +9,10 @@ import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInput; +import java.nio.file.Files; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,12 +29,12 @@ public class SACFileReader extends FileDataSource { public SACHeader header; public TimeT timeT; - public SACFileReader(String filename) throws FileNotFoundException { + public SACFileReader(String filename) throws IOException { this(new File(filename)); } - public SACFileReader(File file) throws FileNotFoundException { - this(new FileInputStream(file)); + public SACFileReader(File file) throws IOException { + this(Files.newInputStream(file.toPath())); path = file.getAbsolutePath(); } @@ -49,10 +48,10 @@ public SACFileReader(ObjectInput stream) { numSamplesRemaining = totalNumSamples; station = (header.kstnm).trim(); channel = (header.kcmpnm).trim(); - samplingRate = 1.0 / ((double) header.delta); + 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((double) header.b); + timeT = timeT.add(header.b); startTime = timeT.getEpochTime(); if (header.checkByteSwap()) { @@ -75,10 +74,10 @@ public SACFileReader(InputStream stream) { numSamplesRemaining = totalNumSamples; station = (header.kstnm).trim(); channel = (header.kcmpnm).trim(); - samplingRate = 1.0 / ((double) header.delta); + 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((double) header.b); + timeT = timeT.add(header.b); startTime = timeT.getEpochTime(); if (header.checkByteSwap()) { @@ -149,7 +148,7 @@ public float[] getData(ObjectInput in, SACHeader header) { case CSS_S4: for (int i = 0; i < numSamplesToRead; i++) { - dataArray[i + offset] = (float) dis.readInt(); + dataArray[i + offset] = dis.readInt(); } numSamplesRemaining -= numSamplesToRead; nextSample += numSamplesToRead; @@ -170,9 +169,9 @@ public float[] getData(ObjectInput in, SACHeader header) { for (int i = 0; i < numSamplesToRead; i++) { if ((0x80 & buffer[ib]) == 0x80) { - dataArray[i + offset] = (float) (((0xff) << 24) + ((buffer[ib++] & 0xff) << 16) + ((buffer[ib++] & 0xff) << 8) + ((buffer[ib++] & 0xff))); + dataArray[i + offset] = ((0xff) << 24) + ((buffer[ib++] & 0xff) << 16) + ((buffer[ib++] & 0xff) << 8) + ((buffer[ib++] & 0xff)); } else { - dataArray[i + offset] = (float) (((0x00) << 24) + ((buffer[ib++] & 0xff) << 16) + ((buffer[ib++] & 0xff) << 8) + ((buffer[ib++] & 0xff))); + dataArray[i + offset] = ((0x00) << 24) + ((buffer[ib++] & 0xff) << 16) + ((buffer[ib++] & 0xff) << 8) + ((buffer[ib++] & 0xff)); } } diff --git a/externals/src/main/java/llnl/gnem/core/io/SAC/SACHeader.java b/externals/src/main/java/llnl/gnem/core/io/SAC/SACHeader.java index f3d38f3e..ea0efe08 100755 --- a/externals/src/main/java/llnl/gnem/core/io/SAC/SACHeader.java +++ b/externals/src/main/java/llnl/gnem/core/io/SAC/SACHeader.java @@ -10,11 +10,11 @@ import java.io.DataInputStream; import java.io.DataOutput; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInput; import java.io.RandomAccessFile; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Iterator; import java.util.StringTokenizer; @@ -278,7 +278,7 @@ public SACHeader(String filename) throws IOException { } public SACHeader(File file) throws IOException { - this(new FileInputStream(file)); + this(Files.newInputStream(file.toPath())); } public SACHeader(ObjectInput objectInput) throws IOException { diff --git a/externals/src/main/java/llnl/gnem/core/polygon/Vertex.java b/externals/src/main/java/llnl/gnem/core/polygon/Vertex.java index 0a20b811..7306d5e4 100755 --- a/externals/src/main/java/llnl/gnem/core/polygon/Vertex.java +++ b/externals/src/main/java/llnl/gnem/core/polygon/Vertex.java @@ -110,7 +110,7 @@ public boolean equals(Object o) { * @return The hash code */ public int hashCode() { - return new Double(lat).hashCode() ^ new Double(lon).hashCode(); + return Double.valueOf(lat).hashCode() ^ Double.valueOf(lon).hashCode(); } /** diff --git a/externals/src/main/java/llnl/gnem/core/util/FileUtil/FileManager.java b/externals/src/main/java/llnl/gnem/core/util/FileUtil/FileManager.java index 27a1934f..92c798b2 100755 --- a/externals/src/main/java/llnl/gnem/core/util/FileUtil/FileManager.java +++ b/externals/src/main/java/llnl/gnem/core/util/FileUtil/FileManager.java @@ -17,23 +17,18 @@ import java.awt.Component; import java.io.BufferedReader; import java.io.BufferedWriter; -import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.DataOutputStream; -import java.io.EOFException; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.FilenameFilter; import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintWriter; +import java.io.OutputStream; import java.io.RandomAccessFile; import java.io.SequenceInputStream; -import java.io.StringReader; -import java.nio.channels.FileChannel; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.Locale; import java.util.StringTokenizer; @@ -75,16 +70,7 @@ public static void copy(File srcFile, File destFile) throws IOException { throw new FileSystemException(msg); } try { - try (FileInputStream fis = new FileInputStream(srcFile)) { - try (FileChannel srcChannel = fis.getChannel()) { - try (FileOutputStream fos = new FileOutputStream(destFile)) { - try (FileChannel destChannel = fos.getChannel()) { - long size = srcChannel.size(); - destChannel.transferFrom(srcChannel, 0, size); - } - } - } - } + Files.copy(srcFile.toPath(), destFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } catch (IOException e) { String msg = String.format("Copy failed: ", e.toString()); throw new FileSystemException(msg); @@ -110,8 +96,7 @@ public static void copy(File srcFile, File destFile) throws IOException { */ public static void concatenate(Vector filelist, File outfile) throws IOException { ListOfFiles mylist = new ListOfFiles(filelist); - try (SequenceInputStream s = new SequenceInputStream(mylist); FileOutputStream out = new FileOutputStream(outfile);) { - + try (SequenceInputStream s = new SequenceInputStream(mylist); OutputStream out = Files.newOutputStream(outfile.toPath());) { int c; while ((c = s.read()) != -1) { out.write(c); diff --git a/externals/src/main/java/llnl/gnem/core/util/FileUtil/ListOfFiles.java b/externals/src/main/java/llnl/gnem/core/util/FileUtil/ListOfFiles.java index 1b9350fb..2f9f03cd 100755 --- a/externals/src/main/java/llnl/gnem/core/util/FileUtil/ListOfFiles.java +++ b/externals/src/main/java/llnl/gnem/core/util/FileUtil/ListOfFiles.java @@ -15,8 +15,10 @@ package llnl.gnem.core.util.FileUtil; import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.Enumeration; import java.util.NoSuchElementException; import java.util.Vector; @@ -24,7 +26,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class ListOfFiles implements Enumeration { +public class ListOfFiles implements Enumeration { private static final Logger log = LoggerFactory.getLogger(ListOfFiles.class); private String[] listOfFiles; private int current = 0; @@ -57,24 +59,24 @@ public ListOfFiles(Vector list) { @Override public boolean hasMoreElements() { - if (current < listOfFiles.length) + if (current < listOfFiles.length) { return true; - else + } else { return false; + } } @Override - public FileInputStream nextElement() { - FileInputStream in = null; - - if (!hasMoreElements()) + public InputStream nextElement() { + InputStream in = null; + if (!hasMoreElements()) { throw new NoSuchElementException("No more files."); - else { + } else { String nextElement = listOfFiles[current]; current++; try { - in = new FileInputStream(nextElement); - } catch (FileNotFoundException e) { + in = Files.newInputStream(Paths.get(nextElement)); + } catch (IOException e) { log.warn("ListOfFiles: Can't open {}", nextElement, e); } } diff --git a/externals/src/main/java/llnl/gnem/core/util/MathFunctions/FitnessCriteria.java b/externals/src/main/java/llnl/gnem/core/util/MathFunctions/FitnessCriteria.java index 0ab5e8d5..e5c3eb7a 100755 --- a/externals/src/main/java/llnl/gnem/core/util/MathFunctions/FitnessCriteria.java +++ b/externals/src/main/java/llnl/gnem/core/util/MathFunctions/FitnessCriteria.java @@ -37,8 +37,7 @@ public class FitnessCriteria { * @return */ public static float[] Differential(float[] data, float[] reference) { - //if (data.length != reference.length) TODO encountering an error where one trace is a single element longer than the other - // return Float.MAX_VALUE; + int minnpts = (data.length < reference.length) ? data.length : reference.length; // find the number of points in the shorter trace float[] Difference = new float[minnpts];// the sum of the squares of the differences (data - reference) @@ -62,8 +61,6 @@ public static float[] Differential(float[] data, float[] reference) { * @return the sum of the squares of the differences */ public static Double SumSquareDifference(double[] data, double[] reference) { - //if (data.length != reference.length) TODO encountering an error where one trace is a single element longer than the other - // return Float.MAX_VALUE; int minnpts = (data.length < reference.length) ? data.length : reference.length; // find the number of points in the shorter trace Double SumSquareDifference = 0.;// the sum of the squares of the differences (data - reference) @@ -87,8 +84,6 @@ public static Double SumSquareDifference(double[] data, double[] reference) { * @return the sum of the squares of the differences */ public static Double SumSquareDifference(float[] data, float[] reference) { - //if (data.length != reference.length) TODO encountering an error where one trace is a single element longer than the other - // return Float.MAX_VALUE; int minnpts = (data.length < reference.length) ? data.length : reference.length; // find the number of points in the shorter trace Double SumSquareDifference = 0.;// the sum of the squares of the differences (data - reference) @@ -145,8 +140,6 @@ public static Double SumSquares(float[] data) { * @return the RMSD of the two series */ public static Double RMSD(float[] data, float[] reference) { - //if (data.length != reference.length) TODO encountering an error where one trace is a single element longer than the other - // return Float.MAX_VALUE; int minnpts = (data.length < reference.length) ? data.length : reference.length; // find the number of points in the shorter trace Double SumSquareDifference = SumSquareDifference(data, reference); @@ -195,9 +188,6 @@ public static Double NRMSD(float[] data, float[] reference) { * @return a single float measure of the RMS fit */ public static Double CVRMSD(float[] data, float[] reference) { - //if (data.length != reference.length) TODO encountering an error where one trace is a single element longer than the other due to measurement limits - // return Float.MAX_VALUE; - int minnpts = (data.length < reference.length) ? data.length : reference.length; // find the number of points in the shorter trace if (minnpts <= 0) { @@ -227,8 +217,6 @@ public static Double CVRMSD(float[] data, float[] reference) { * @return a single double valued measure of the RMS fit */ public static Double CVRMSD(double[] data, double[] reference) { - //if (data.length != reference.length) TODO encountering an error where one trace is a single element longer than the other - // return Double.MAX_VALUE; int minnpts = (data.length < reference.length) ? data.length : reference.length; // find the number of points in the shorter trace if (minnpts <= 0) { @@ -294,8 +282,6 @@ public static Double CVRMSD(HashMap dataHashMap) { * @return a single float measure of the MD fit */ public static Float MeanDifference(float[] data, float[] reference) { - //if (data.length != reference.length) TODO encountering an error where one trace is a single element longer than the other - // return Double.MAX_VALUE; int minnpts = (data.length < reference.length) ? data.length : reference.length; // find the number of points in the shorter trace if (minnpts <= 0) { diff --git a/externals/src/main/java/llnl/gnem/core/util/MathFunctions/MathFunction.java b/externals/src/main/java/llnl/gnem/core/util/MathFunctions/MathFunction.java index 9b35783c..db8b7c4c 100755 --- a/externals/src/main/java/llnl/gnem/core/util/MathFunctions/MathFunction.java +++ b/externals/src/main/java/llnl/gnem/core/util/MathFunctions/MathFunction.java @@ -63,7 +63,7 @@ public static long closestPowerOf2(long num) { return 0; } else { String bits = Long.toBinaryString(num); - int exp = bits.length() - bits.indexOf("1"); + int exp = bits.length() - bits.indexOf('1'); long larger = (long) Math.pow(2, exp); // next power of 2 greater than num long lower = (long) Math.pow(2, exp - 1); // previous power of 2 less than num @@ -85,7 +85,7 @@ public static long nextPowerOf2(long num) { return 0; } else { String bits = Long.toBinaryString(num); - int exp = bits.length() - bits.indexOf("1"); + int exp = bits.length() - bits.indexOf('1'); return (long) Math.pow(2, exp); // next power of 2 greater than num } } diff --git a/mapping/pom.xml b/mapping/pom.xml index d7e44303..07ef9efe 100644 --- a/mapping/pom.xml +++ b/mapping/pom.xml @@ -21,7 +21,6 @@ http://www.llnl.gov - org.springframework @@ -35,17 +34,39 @@ org.openjfx javafx-fxml + + org.openjfx + javafx-swing + org.openjfx javafx-web + win org.openjfx - javafx-swing + javafx-web + mac + + + org.openjfx + javafx-web + linux + + + org.openjfx + javafx-graphics + win + + + org.openjfx + javafx-graphics + mac org.openjfx javafx-graphics + linux org.openjfx diff --git a/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/LeafletIcon.java b/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/LeafletIcon.java index 80f062a0..6e9049d9 100644 --- a/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/LeafletIcon.java +++ b/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/LeafletIcon.java @@ -73,7 +73,7 @@ public Location setLocation(Location location) { @Override public String toString() { StringBuilder builder = new StringBuilder(); - builder.append("\"").append(id).append("\", \"").append(location).append("\", \"").append(friendlyName).append("\", \"").append(iconType).append("\""); + builder.append("\"").append(id).append("\", \"").append(location).append("\", \"").append(friendlyName).append("\", \"").append(iconType).append('\"'); return builder.toString(); } diff --git a/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/LeafletLine.java b/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/LeafletLine.java index d2f70a59..dfb6a4fd 100644 --- a/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/LeafletLine.java +++ b/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/LeafletLine.java @@ -120,7 +120,7 @@ public boolean equals(Object obj) { @Override public String toString() { StringBuilder builder = new StringBuilder(); - builder.append("\"").append(id).append("\", \"").append(startLocation).append("\", \"").append(endLocation).append("\""); + builder.append("\"").append(id).append("\", \"").append(startLocation).append("\", \"").append(endLocation).append('\"'); return builder.toString(); } } diff --git a/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/LeafletMap.java b/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/LeafletMap.java index a2c77501..476a35a9 100644 --- a/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/LeafletMap.java +++ b/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/LeafletMap.java @@ -24,8 +24,8 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.BiConsumer; +import java.util.function.Consumer; -import gov.llnl.gnem.apps.coda.common.mapping.api.GeoMap; import gov.llnl.gnem.apps.coda.common.mapping.api.GeoShape; import gov.llnl.gnem.apps.coda.common.mapping.api.Icon; import gov.llnl.gnem.apps.coda.common.mapping.api.Icon.IconStyles; @@ -34,11 +34,16 @@ import javafx.collections.FXCollections; import javafx.collections.ObservableSet; import javafx.concurrent.Worker; +import javafx.scene.control.ContextMenu; +import javafx.scene.control.MenuItem; +import javafx.scene.input.MouseButton; +import javafx.scene.input.MouseEvent; import javafx.scene.layout.Pane; +import javafx.scene.web.WebEngine; import javafx.scene.web.WebView; import netscape.javascript.JSObject; -public class LeafletMap implements GeoMap { +public class LeafletMap { private WebView webView; private ObservableSet icons = FXCollections.observableSet(new HashSet<>()); @@ -48,6 +53,11 @@ public class LeafletMap implements GeoMap { private AtomicBoolean mapReady = new AtomicBoolean(false); private Map> callbackMap = new HashMap<>(); private IconCallbackHandler iconCallbackHandler; + private List> eventCallbacks = new ArrayList<>(); + private ContextMenu contextMenu; + private MenuItem reload = new MenuItem("Reload"); + private MenuItem include = new MenuItem("Include"); + private MenuItem exclude = new MenuItem("Exclude"); public class IconCallbackHandler { private BiConsumer iconCallbackHandler; @@ -72,6 +82,31 @@ public LeafletMap() { Platform.runLater(() -> { webView = new WebView(); webView.getEngine().setJavaScriptEnabled(true); + webView.setContextMenuEnabled(false); + contextMenu = new ContextMenu(); + reload.setOnAction(e -> webView.getEngine().reload()); + + webView.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> { + if (MouseButton.SECONDARY == event.getButton()) { + WebEngine engine = webView.getEngine(); + contextMenu.getItems().clear(); + Object activeIconId = engine.executeScript("getActiveIcon();"); + if (activeIconId instanceof String) { + icons.stream().filter(icon -> icon.getId().equalsIgnoreCase((String) activeIconId)).findFirst().ifPresent(icon -> { + include.setOnAction(e -> invokeActivationCallbacks(icon, true)); + exclude.setOnAction(e -> invokeActivationCallbacks(icon, false)); + contextMenu.getItems().addAll(include, exclude); + contextMenu.show(webView, event.getScreenX(), event.getScreenY()); + }); + } else { + contextMenu.getItems().addAll(reload); + contextMenu.show(webView, event.getScreenX(), event.getScreenY()); + } + + } else { + contextMenu.hide(); + } + }); webView.getEngine().getLoadWorker().stateProperty().addListener((obs, o, n) -> { if (n == Worker.State.SUCCEEDED) { mapReady.set(true); @@ -89,7 +124,20 @@ public LeafletMap() { }); } - @Override + private void invokeActivationCallbacks(Icon icon, boolean active) { + List> callbacks = new ArrayList<>(eventCallbacks); + MapCallbackEvent event = new MapCallbackEvent(icon, MAP_CALLBACK_EVENT_TYPE.ACTIVATION, active); + callbacks.forEach(cb -> cb.accept(event)); + } + + public void registerEventCallback(Consumer callback) { + eventCallbacks.add(callback); + } + + public void removeEventCallback(Consumer callback) { + eventCallbacks.remove(callback); + } + public long getIconCount() { return icons.size(); } @@ -106,7 +154,6 @@ public void attach(Pane parent) { } } - @Override public void clearIcons() { icons.clear(); callbackMap.clear(); @@ -119,7 +166,6 @@ private void clearIconLayer() { } } - @Override public void addLayer(WMSLayerDescriptor layer) { if (layer != null) { layers.add(layer); @@ -140,7 +186,7 @@ public void addLayerToMap(WMSLayerDescriptor layer) { for (int i = 0; i < layer.getLayers().size(); i++) { sb.append(layer.getLayers().get(i)); if (i != layer.getLayers().size() - 1) { - sb.append(":"); + sb.append(':'); } } sb.append("'}),\""); @@ -150,7 +196,6 @@ public void addLayerToMap(WMSLayerDescriptor layer) { }); } - @Override public boolean addIcon(Icon icon) { if (mapReady.get()) { addIconsToMap(Collections.singleton(icon)); @@ -158,7 +203,6 @@ public boolean addIcon(Icon icon) { return icons.add(icon); } - @Override public boolean removeIcon(Icon icon) { if (mapReady.get()) { removeIconsFromMap(Collections.singleton(icon)); @@ -167,7 +211,6 @@ public boolean removeIcon(Icon icon) { return icons.remove(icon); } - @Override public void addIcons(Collection icons) { this.icons.addAll(icons); if (mapReady.get()) { @@ -175,7 +218,6 @@ public void addIcons(Collection icons) { } } - @Override public void removeIcons(Collection icons) { this.icons.removeAll(icons); icons.forEach(icon -> callbackMap.remove(icon.getId())); @@ -204,7 +246,6 @@ private void removeIconsFromMap(Collection icons) { })); } - @Override public void addShape(GeoShape shape) { if (mapReady.get()) { addShapesToMap(Collections.singleton(shape)); @@ -212,7 +253,6 @@ public void addShape(GeoShape shape) { shapes.add(shape); } - @Override public void removeShape(GeoShape shape) { if (mapReady.get()) { removeShapesFromMap(Collections.singleton(shape)); @@ -231,7 +271,6 @@ private void addShapesToMap(Collection shapes) { }); } - @Override public void fitViewToActiveShapes() { Platform.runLater(() -> webView.getEngine().executeScript("fitViewToActiveShapes();")); } @@ -252,20 +291,20 @@ private String createJsShapeRepresentation(GeoShape shape) { sb.append(line.getId()); sb.append("\")) {"); sb.append("marker = L.polyline(["); - sb.append("["); + sb.append('['); sb.append(line.getStartLocation().getLatitude()); - sb.append(","); + sb.append(','); sb.append(line.getStartLocation().getLongitude()); - sb.append("]"); - sb.append(","); - sb.append("["); + sb.append(']'); + sb.append(','); + sb.append('['); sb.append(line.getEndLocation().getLatitude()); - sb.append(","); + sb.append(','); sb.append(line.getEndLocation().getLongitude()); - sb.append("]"); - sb.append("]"); + sb.append(']'); + sb.append(']'); sb.append(", {color: 'black', interactive: false, weight: 1, pane: 'background-pane', bubblingMouseEvents: false, smoothFactor: 1}"); - sb.append(")"); + sb.append(')'); sb.append(".addTo(lineGroup);"); sb.append("marker._uid = \""); sb.append(shape.getId()); @@ -286,7 +325,7 @@ private String createJsIconRepresentation(Icon icon) { case TRIANGLE_UP: sb.append("marker = L.marker(["); sb.append(icon.getLocation().getLatitude()); - sb.append(","); + sb.append(','); sb.append(icon.getLocation().getLongitude()); sb.append("], {icon: L.icon({"); sb.append("iconUrl: "); @@ -302,11 +341,11 @@ private String createJsIconRepresentation(Icon icon) { case DEFAULT: sb.append("marker = L.circleMarker(["); sb.append(icon.getLocation().getLatitude()); - sb.append(","); + sb.append(','); sb.append(icon.getLocation().getLongitude()); - sb.append("]"); + sb.append(']'); sb.append(getCircleStyle(icon.getStyle())); - sb.append(")"); + sb.append(')'); break; default: return ""; @@ -324,13 +363,17 @@ private String createJsIconRepresentation(Icon icon) { private String addCallbacks(String id, String name) { return ".on('click', function() { iconCallbackHandler.accept(true, \"" + id - + "\"); })" - + ".bindPopup('" + + "\"); }).bindPopup('" + name - + "')" - + ".on('popupclose', function() { iconCallbackHandler.accept(false, \"" + + "').on('popupclose', function() { iconCallbackHandler.accept(false, \"" + + id + + "\"); }).on('mouseover', function() { if (\"" + id - + "\"); })"; + + "\" !== mouseoverIconId) { mouseoverIconId = \"" + + id + + "\"; }}).on('mouseout', function() { if (\"" + + id + + "\" === mouseoverIconId) { mouseoverIconId = null; }})"; } private String getTriangleStyleZIndex(IconStyles style) { @@ -383,5 +426,4 @@ private String getCircleStyle(IconStyles style) { } return jsonStyle; } - } diff --git a/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/LeafletMapController.java b/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/LeafletMapController.java index fab483d3..1efd5bcf 100644 --- a/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/LeafletMapController.java +++ b/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/LeafletMapController.java @@ -16,6 +16,7 @@ import java.io.IOException; import java.util.Collection; +import java.util.function.Consumer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -75,6 +76,7 @@ public void hide() { }); } + @Override public void show() { Platform.runLater(() -> { stage.show(); @@ -132,6 +134,16 @@ public void fitViewToActiveShapes() { mapImpl.fitViewToActiveShapes(); } + @Override + public void registerEventCallback(Consumer callback) { + mapImpl.registerEventCallback(callback); + } + + @Override + public void removeEventCallback(Consumer callback) { + mapImpl.removeEventCallback(callback); + } + @Override public int hashCode() { final int prime = 31; @@ -173,7 +185,7 @@ public boolean equals(Object obj) { @Override public String toString() { StringBuilder builder = new StringBuilder(); - builder.append("\"").append(view).append("\", \"").append(mapImpl).append("\""); + builder.append("\"").append(view).append("\", \"").append(mapImpl).append('\"'); return builder.toString(); } diff --git a/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/MAP_CALLBACK_EVENT_TYPE.java b/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/MAP_CALLBACK_EVENT_TYPE.java new file mode 100644 index 00000000..6cce09b8 --- /dev/null +++ b/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/MAP_CALLBACK_EVENT_TYPE.java @@ -0,0 +1,28 @@ +/* +* 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.mapping; + +public enum MAP_CALLBACK_EVENT_TYPE { + + SELECTION("selection"), ACTIVATION("activation"); + private String type; + + private MAP_CALLBACK_EVENT_TYPE(String type) { + this.type = type; + } + + public String getType() { + return type; + } +} diff --git a/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/MapCallbackEvent.java b/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/MapCallbackEvent.java new file mode 100644 index 00000000..bbbe825c --- /dev/null +++ b/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/MapCallbackEvent.java @@ -0,0 +1,41 @@ +/* +* 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.mapping; + +import gov.llnl.gnem.apps.coda.common.mapping.api.Icon; + +public class MapCallbackEvent { + private final MAP_CALLBACK_EVENT_TYPE type; + private final boolean flag; + private final Icon icon; + + public MapCallbackEvent(Icon icon, MAP_CALLBACK_EVENT_TYPE type, boolean flag) { + super(); + this.icon = icon; + this.type = type; + this.flag = flag; + } + + public Icon getIcon() { + return icon; + } + + public boolean getFlag() { + return flag; + } + + public MAP_CALLBACK_EVENT_TYPE getType() { + return type; + } +} diff --git a/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/WMSLayerDescriptor.java b/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/WMSLayerDescriptor.java index 1f497964..ed8043ff 100644 --- a/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/WMSLayerDescriptor.java +++ b/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/WMSLayerDescriptor.java @@ -108,7 +108,7 @@ public boolean equals(Object obj) { @Override public String toString() { StringBuilder builder = new StringBuilder(); - builder.append("\"").append(url).append("\", \"").append(name).append("\", \"").append(layers).append("\""); + builder.append("\"").append(url).append("\", \"").append(name).append("\", \"").append(layers).append('\"'); return builder.toString(); } diff --git a/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/api/GeoMap.java b/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/api/GeoMap.java index 2d34574a..38ff6109 100644 --- a/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/api/GeoMap.java +++ b/mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/api/GeoMap.java @@ -15,7 +15,9 @@ package gov.llnl.gnem.apps.coda.common.mapping.api; import java.util.Collection; +import java.util.function.Consumer; +import gov.llnl.gnem.apps.coda.common.mapping.MapCallbackEvent; import gov.llnl.gnem.apps.coda.common.mapping.WMSLayerDescriptor; public interface GeoMap { @@ -40,4 +42,9 @@ public interface GeoMap { public void fitViewToActiveShapes(); + public void registerEventCallback(Consumer callback); + + public void removeEventCallback(Consumer callback); + + public void show(); } diff --git a/mapping/src/main/resources/leaflet/leaflet.html b/mapping/src/main/resources/leaflet/leaflet.html index df7429ec..58ac2d02 100644 --- a/mapping/src/main/resources/leaflet/leaflet.html +++ b/mapping/src/main/resources/leaflet/leaflet.html @@ -12,6 +12,7 @@
diff --git a/pom.xml b/pom.xml index c2f7669d..39d26026 100644 --- a/pom.xml +++ b/pom.xml @@ -73,38 +73,58 @@ 1.8 1.8 3.8.0 - 3.0.1 + 3.1.0 3.0.0-M3 3.0.0 3.1.1 - 12-ea+14 + 13-ea+5 2.4.0-b180830.0359 1.2.0.RELEASE - 2.1.3.RELEASE - Californium-RELEASE + 2.2.0.M2 + Californium-SR6 2.2.1 1.11 1.3.04 - 2.0.2 1.49 + 2.0.25.Final + 9.4.16.v20190411 + 10.0.0.M2 + 1.15 1.18 3.6.1 - 27.0.1-jre + 27.1-jre 2.0.1 - 5.1.5.RELEASE - 5.4.0 - 2.24.5 + 5.2.0.M1 + 5.5.0-M1 + 2.27.0 + 1.3.2 + + org.eclipse.collections + eclipse-collections-api + ${eclipse.collections.version} + + + + org.eclipse.collections + eclipse-collections + ${eclipse.collections.version} + + + io.netty + netty-tcnative-boringssl-static + ${netty.boringssl.version} + org.openjfx javafx-base @@ -115,27 +135,52 @@ javafx-fxml ${jfx.version} + + org.openjfx + javafx-swing + ${jfx.version} + org.openjfx javafx-web ${jfx.version} + win org.openjfx - javafx-swing + javafx-web + ${jfx.version} + mac + + + org.openjfx + javafx-web + ${jfx.version} + linux + + + org.openjfx + javafx-graphics + ${jfx.version} + win + + + org.openjfx + javafx-graphics ${jfx.version} + mac org.openjfx javafx-graphics ${jfx.version} + linux org.openjfx javafx-controls ${jfx.version} - javax.xml.bind jaxb-api @@ -275,14 +320,36 @@ ${springlets.version} - io.springlets - springlets-web - ${springlets.version} + org.springframework.boot + spring-boot-starter-web + ${spring.boot.version} + + + org.springframework.boot + spring-boot-starter-tomcat + + - io.springlets - springlets-boot-starter-web - ${springlets.version} + org.springframework.boot + spring-boot-starter-jetty + ${spring.boot.version} + + + org.eclipse.jetty + jetty-server + + + + + org.eclipse.jetty + jetty-alpn-conscrypt-server + ${jetty.version} + + + org.eclipse.jetty.http2 + http2-server + ${jetty.version} @@ -314,7 +381,12 @@ xml-apis xml-apis - ${xml.apis.version} + + + 1.4.01 xml-apis @@ -392,6 +464,12 @@ mockito-junit-jupiter ${mockito.version} + + javax.annotation + javax.annotation-api + ${javax.annotation.version} + + @@ -407,6 +485,7 @@ ${java.version} ${project.build.sourceEncoding} false + -Xlint:deprecation diff --git a/schema/calibration-input-params.json.example b/schema/calibration-input-params.json.example index 113d6a2c..74310716 100644 --- a/schema/calibration-input-params.json.example +++ b/schema/calibration-input-params.json.example @@ -41,6 +41,14 @@ ], "reference-events": [ { "eventId" : "0331199924", "refMw" : 3.0 }, - { "eventId" : "0401199924", "refMw" : 5.0, "stressDropInMpa": 0.7 } - ] + { "eventId" : "0401199924", "refMw" : 5.0, "refApparentStressInMpa": 0.7 } + ], + "velocity-configuration": { + "phaseSpeedInKms" : 3.5, + "groupVelocity1InKmsGtDistance" : 4.7, + "groupVelocity2InKmsGtDistance" : 2.3, + "groupVelocity1InKmsLtDistance" : 3.9, + "groupVelocity2InKmsLtDistance" : 1.9, + "distanceThresholdInKm" : 300.0, + } } \ No newline at end of file diff --git a/schema/calibration-input-params.jsonschema b/schema/calibration-input-params.jsonschema index c9e7412b..320329ec 100644 --- a/schema/calibration-input-params.jsonschema +++ b/schema/calibration-input-params.jsonschema @@ -514,10 +514,10 @@ 5.0 ] }, - "stressDropInMpa": { - "$id": "#/properties/reference-events/entry/properties/stressDropInMpa", + "refApparentStressInMpa": { + "$id": "#/properties/reference-events/entry/properties/refApparentStressInMpa", "type": "number", - "title": "An optional measure of the stress drop term for this specific event. If present it will be used in lieu of the MDAC2 Sigma-Psi terms loaded for calibrating tie points for this event.", + "title": "An optional measure of the apparent stress term for this specific event. If present it will be used in lieu of the MDAC2 Sigma-Psi terms loaded for calibrating tie points for this event.", "default": false, "examples": [ 0.0, 0.5 @@ -525,6 +525,67 @@ } } } - } + }, + "velocity-configuration": { + "$id": "#/properties/velocity-configuration", + "type": "object", + "title": "Configuration properties related to group velocities that should be used by the calibration code.", + "properties": { + "phaseSpeedInKms": { + "$id": "#/properties/velocity-configuration/properties/phaseSpeedInKms", + "type": "number", + "title": "Phase speed (Km/S) to use for the spectra calibration. Note: path calibration will use this value if it is available but path.phaseSpeedKmS isn't.", + "default": 0, + "examples": [ + 3.5 + ] + }, + "groupVelocity1InKmsGtDistance": { + "$id": "#/properties/velocity-configuration/properties/groupVelocity1InKmsGtDistance", + "type": "number", + "title": "Starting velocity (in Km/S) for windowing distances after the distance threshold.", + "default": 0, + "examples": [ + 4.7 + ] + }, + "groupVelocity2InKmsGtDistance": { + "$id": "#/properties/velocity-configuration/properties/groupVelocity2InKmsGtDistance", + "type": "number", + "title": "Ending velocity (in Km/S) for windowing distances after the distance threshold.", + "default": 0, + "examples": [ + 2.3 + ] + }, + "groupVelocity1InKmsLtDistance": { + "$id": "#/properties/velocity-configuration/properties/groupVelocity1InKmsLtDistance", + "type": "number", + "title": "Starting velocity (in Km/S) for windowing distances before the distance threshold.", + "default": 0, + "examples": [ + 3.9 + ] + }, + "groupVelocity2InKmsLtDistance": { + "$id": "#/properties/velocity-configuration/properties/groupVelocity2InKmsLtDistance", + "type": "number", + "title": "Ending velocity (in Km/S) for windowing distances before the distance threshold.", + "default": 0, + "examples": [ + 1.9 + ] + }, + "distanceThresholdInKm": { + "$id": "#/properties/velocity-configuration/properties/distanceThresholdInKm", + "type": "number", + "title": "Distance threshold to use (in Km) to use for selected which group velocity to use.", + "default": 0, + "examples": [ + 300.0 + ] + } + } + } } -} \ No newline at end of file +} \ No newline at end of file diff --git a/schema/measured-mws-output.json.example b/schema/measured-mws-output.json.example index 84a8e8c9..f1e06d4a 100644 --- a/schema/measured-mws-output.json.example +++ b/schema/measured-mws-output.json.example @@ -8,7 +8,10 @@ "latitude": 0.0, "longitude": 0.0, "mw": 3.3, - "stressDropInMpa": 0.7 + "apparentStressInMpa": 0.7, + "refMw" : 3.3, + "refApparentStressInMpa" : 0.7, + "dataCount": 123 } ] } \ No newline at end of file diff --git a/schema/measured-mws-output.jsonschema b/schema/measured-mws-output.jsonschema index dee7d8ff..3ebef50e 100644 --- a/schema/measured-mws-output.jsonschema +++ b/schema/measured-mws-output.jsonschema @@ -33,13 +33,22 @@ "type": "object", "title": "A specific measured event entry.", "required": [ - "eventId", - "mw", - "stressDropInMpa", - "datetime", - "latitude", - "longitude" + "eventId" ], + "anyOf": [ + { + "required": + [ + "mw" + ] + }, + { + "required": + [ + "refMw" + ] + } + ] "properties": { "eventId": { "$id": "#/properties/measured-events/entry/properties/eventId", @@ -59,15 +68,42 @@ 5.0 ] }, - "stressDropInMpa": { - "$id": "#/properties/reference-events/entry/properties/stressDropInMpa", + "apparentStressInMpa": { + "$id": "#/properties/reference-events/entry/properties/apparentStressInMpa", "type": "number", - "title": "An estimate measure of the stress drop term for this specific event.", + "title": "An estimate measure of the apparent stress term for this specific event.", "default": false, "examples": [ 0.3 ] }, + "refMw": { + "$id": "#/properties/reference-events/entry/properties/refMw", + "type": "number", + "title": "The Mw value used as a reference for this event.", + "default": 0, + "examples": [ + 5.0 + ] + }, + "refApparentStressInMpa": { + "$id": "#/properties/reference-events/entry/properties/refApparentStressInMpa", + "type": "number", + "title": "A reference estimate of the apparent stress term for this specific event.", + "default": false, + "examples": [ + 0.3 + ] + }, + "dataCount": { + "$id": "#/properties/reference-events/entry/properties/dataCount", + "type": "number", + "title": "The number of data points used in the inversion to compute the Mw fit value. If every station contributed an entry for every frequency band this is equivalent to nSta*nBands.", + "default": 0, + "examples": [ + 100 + ] + }, "datetime": { "$id": "#/properties/reference-events/entry/properties/datetime", "type": "string",