From 44c36ec16ee1ebcf102ae296b22038d6369cf3d6 Mon Sep 17 00:00:00 2001 From: Justin Barno Date: Thu, 2 Jun 2022 14:10:54 -0700 Subject: [PATCH] CCT 1.0.17 Release Notes * Added a network average spectrum to the relative site and absolute site term plots * Updates to all naming conventions for generating envelopes based on user feedback * Updates to the naming conventions around loading and saving data based on user feedback. * Add filter capabilities for including and excluding waveforms from the waveform plot displays based on specific criteria, such as event or station information * Updates to the Data filter functionality to include new features and a redesigned layout that is more compact. * Event depth headers on the SAC files are not (correctly) using Meters and will update the internal data representation accordingly. * Corrected display bug in the relative site plot when site correction terms were missing for the primary station. * New functions to export spectra value JSON directly from the spectra plots. * New feature to allow exporting raw data JSON files from all plots in the GUI. * Energy magnitude now being calculated in addition to Mw based on [Mayeda and Walter 1996] paper * Updates to uncertainty quantification to include confidence intervals for apparent stress, corner frequency, total energy, observed apparent stress, and energy magnitude values in addition to Mw. --- README.md | 6 +- calibration-gui/pom.xml | 2 +- .../AbstractMeasurementController.java | 247 +- .../gui/controllers/DataController.java | 15 +- .../gui/controllers/DataFilterController.java | 52 +- .../controllers/FilterDialogController.java | 434 ++-- .../controllers/MeasuredMwsController.java | 3 +- .../gui/controllers/PathController.java | 2 +- .../gui/controllers/PredicateBuilder.java | 24 +- .../gui/controllers/ShapeController.java | 14 +- .../gui/controllers/SiteController.java | 196 +- .../client/api/CalibrationJsonConstants.java | 6 +- .../data/exporters/JsonTempFileWriter.java | 34 +- .../gui/data/exporters/ParamExporter.java | 29 +- .../exporters/api/SpectraTempFileWriter.java | 26 + .../gui/plotting/CodaWaveformPlotManager.java | 194 +- .../calibration/gui/plotting}/LeafletMap.java | 159 +- .../gui/plotting}/LeafletMapController.java | 34 +- .../gui/plotting}/LeafletShapeFactory.java | 4 +- .../gui/converters/sac/SacExporter.java | 8 +- .../common/gui/converters/sac/SacLoader.java | 23 +- .../gui/data/client/WaveformWebClient.java | 34 +- .../gui/data/client/api/WaveformClient.java | 6 +- .../common/gui/util/NumberFormatFactory.java | 30 +- .../coda/common/gui/util/SnapshotUtils.java | 2 +- .../coda/envelope/util/LogBandGenerator.java | 95 +- .../src/main/resources/click_to_pick_icon.svg | 121 + .../src/main/resources/fxml/EnvelopeGui.fxml | 4 +- .../src/main/resources/fxml/FilterGui.fxml | 46 +- .../src/main/resources/fxml/MeasuredMws.fxml | 168 +- .../src/main/resources/fxml/Site.fxml | 84 +- .../gui/plotting}/LeafletMapTest.java | 11 +- .../plotting}/LeafletShapeFactoryTest.java | 3 +- .../calibration-application/pom.xml | 2 +- .../web/MeasurementJsonController.java | 8 +- .../WaveformsCollectionJsonController.java | 16 +- .../coda/common/util/NumberFormatFactory.java | 16 +- calibration-service/calibration-model/pom.xml | 2 +- .../model/domain/EventSpectraReport.java | 89 + .../model/domain/MeasuredMwDetails.java | 665 ++++-- .../model/domain/MeasuredMwParameters.java | 440 +++- .../model/domain/MwOptimizerMeasurement.java | 73 + .../domain/SiteFrequencyBandParameters.java | 47 +- .../calibration/model/domain/Spectra.java | 2 +- .../apps/coda/common/model/domain/Pair.java | 44 +- .../calibration-repository/pom.xml | 2 +- .../common/repository/WaveformRepository.java | 12 + .../calibration-service-api/pom.xml | 2 +- .../common/service/api/WaveformService.java | 4 + .../calibration-service-impl/pom.xml | 2 +- .../impl/SpectraMeasurementServiceImpl.java | 248 +- .../impl/processing/MdacCalculator.java | 4 - .../processing/MdacCalculatorService.java | 4 - .../impl/processing/SpectraCalculator.java | 214 +- .../service/impl/WaveformServiceImpl.java | 14 + .../processing/SpectraCalculatorTest.java | 23 +- calibration-service/pom.xml | 2 +- calibration-standalone/pom.xml | 2 +- .../data/client/WaveformLocalClient.java | 14 +- externals/pom.xml | 2 +- .../core/gui/plotting/plotly/PlotlyPlot.java | 34 + externals/src/main/resources/plotly.html | 56 +- mapping/pom.xml | 56 +- .../apps/coda/common/mapping/LeafletIcon.java | 87 +- .../common/mapping/StaticHtmlLeafletMap.java | 233 ++ .../apps/coda/common/mapping/api/GeoBox.java | 35 +- .../apps/coda/common/mapping/api/Icon.java | 16 +- .../mapping/utils/LeafletToJavascript.java | 176 ++ .../main/resources/leaflet/leaflet-src.esm.js | 1849 +++++++-------- .../resources/leaflet/leaflet-src.esm.js.map | 2 +- .../src/main/resources/leaflet/leaflet-src.js | 1992 +++++++++-------- .../main/resources/leaflet/leaflet-src.js.map | 2 +- .../main/resources/leaflet/leaflet-src.map | 1 - .../resources/leaflet/leaflet-static.shim | 987 ++++++++ .../src/main/resources/leaflet/leaflet.css | 89 +- mapping/src/main/resources/leaflet/leaflet.js | 6 +- .../src/main/resources/leaflet/leaflet.js.map | 2 +- pom.xml | 4 +- 78 files changed, 6466 insertions(+), 3230 deletions(-) create mode 100644 calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/api/SpectraTempFileWriter.java rename {mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping => calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting}/LeafletMap.java (70%) rename {mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping => calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting}/LeafletMapController.java (93%) rename {mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping => calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting}/LeafletShapeFactory.java (93%) create mode 100644 calibration-gui/src/main/resources/click_to_pick_icon.svg rename {mapping/src/test/java/gov/llnl/gnem/apps/coda/common/mapping => calibration-gui/src/test/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting}/LeafletMapTest.java (94%) rename {mapping/src/test/java/gov/llnl/gnem/apps/coda/common/mapping => calibration-gui/src/test/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting}/LeafletShapeFactoryTest.java (97%) create mode 100644 calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/EventSpectraReport.java create mode 100644 calibration-service/calibration-model/src/main/java/gov/llnl/gnem/apps/coda/calibration/model/domain/MwOptimizerMeasurement.java create mode 100644 mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/StaticHtmlLeafletMap.java create mode 100644 mapping/src/main/java/gov/llnl/gnem/apps/coda/common/mapping/utils/LeafletToJavascript.java delete mode 100644 mapping/src/main/resources/leaflet/leaflet-src.map create mode 100644 mapping/src/main/resources/leaflet/leaflet-static.shim diff --git a/README.md b/README.md index 5241d6ca..686ce596 100644 --- a/README.md +++ b/README.md @@ -42,18 +42,18 @@ We don't presently deploy versioned artifacts into a public repository like the #### **As a single runnable JAR** ```shell -java -jar coda-calibration/calibration-standalone/target/calibration-standalone-1.0.15-runnable.jar +java -jar coda-calibration/calibration-standalone/target/calibration-standalone-1.0.17-runnable.jar ``` #### **GUI alone** ```shell -java -jar coda-calibration/calibration-gui/target/calibration-gui-1.0.15-runnable.jar +java -jar coda-calibration/calibration-gui/target/calibration-gui-1.0.17-runnable.jar ``` #### **Calibration REST service alone** ```shell -java -jar coda-calibration/calibration-service/application/target/application-1.0.15-runnable.jar +java -jar coda-calibration/calibration-service/application/target/application-1.0.17-runnable.jar ``` #### A note about HTTPS diff --git a/calibration-gui/pom.xml b/calibration-gui/pom.xml index d52d506f..bd5c15b7 100644 --- a/calibration-gui/pom.xml +++ b/calibration-gui/pom.xml @@ -5,7 +5,7 @@ gov.llnl.gnem.apps.coda.calibration coda-calibration - 1.0.16 + 1.0.17 calibration-gui diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/AbstractMeasurementController.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/AbstractMeasurementController.java index ddf3ad63..5f7b03bd 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/AbstractMeasurementController.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/AbstractMeasurementController.java @@ -35,6 +35,7 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.TreeMap; import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiConsumer; import java.util.function.BooleanSupplier; @@ -43,6 +44,7 @@ import java.util.function.Supplier; import java.util.stream.Collectors; +import org.apache.commons.io.FilenameUtils; import org.apache.commons.math3.stat.descriptive.SummaryStatistics; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -53,9 +55,12 @@ import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.EventClient; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ParameterClient; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.SpectraClient; +import gov.llnl.gnem.apps.coda.calibration.gui.data.exporters.ParamExporter; import gov.llnl.gnem.apps.coda.calibration.gui.plotting.MapPlottingUtilities; import gov.llnl.gnem.apps.coda.calibration.gui.plotting.SpectralPlot; +import gov.llnl.gnem.apps.coda.calibration.gui.util.FileDialogs; import gov.llnl.gnem.apps.coda.calibration.gui.util.TextWrappingTableCell; +import gov.llnl.gnem.apps.coda.calibration.model.domain.EventSpectraReport; 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; @@ -85,6 +90,7 @@ import javafx.geometry.Point2D; import javafx.scene.control.Button; import javafx.scene.control.ComboBox; +import javafx.scene.control.ContentDisplay; import javafx.scene.control.ContextMenu; import javafx.scene.control.Label; import javafx.scene.control.MenuItem; @@ -166,21 +172,60 @@ public abstract class AbstractMeasurementController implements MapListeningContr @FXML protected TableColumn totalEnergyCol; + @FXML + protected TableColumn totalEnergyUq1LowCol; + + @FXML + protected TableColumn totalEnergyUq1HighCol; + + @FXML + protected TableColumn totalEnergyUq2LowCol; + + @FXML + protected TableColumn totalEnergyUq2HighCol; + @FXML protected TableColumn totalEnergyMDACCol; + @FXML + protected TableColumn totalEnergyMDACUq1LowCol; + + @FXML + protected TableColumn totalEnergyMDACUq1HighCol; + + @FXML + protected TableColumn totalEnergyMDACUq2LowCol; + + @FXML + protected TableColumn totalEnergyMDACUq2HighCol; + @FXML protected TableColumn energyRatioCol; @FXML protected TableColumn energyStressCol; + @FXML + protected TableColumn energyStressUq1LowCol; + + @FXML + protected TableColumn energyStressUq1HighCol; + + @FXML + protected TableColumn energyStressUq2LowCol; + + @FXML + protected TableColumn energyStressUq2HighCol; + @FXML protected TableColumn stressCol; @FXML protected TableColumn measuredMwCol; + @FXML + protected TableColumn measuredMeCol; + @FXML protected TableColumn measuredStressCol; @@ -208,6 +253,42 @@ public abstract class AbstractMeasurementController implements MapListeningContr @FXML protected TableColumn measuredMwUq2HighCol; + @FXML + protected TableColumn measuredMeUq1LowCol; + + @FXML + protected TableColumn measuredMeUq1HighCol; + + @FXML + protected TableColumn measuredMeUq2LowCol; + + @FXML + protected TableColumn measuredMeUq2HighCol; + + @FXML + protected TableColumn measuredStressUq1LowCol; + + @FXML + protected TableColumn measuredStressUq1HighCol; + + @FXML + protected TableColumn measuredStressUq2LowCol; + + @FXML + protected TableColumn measuredStressUq2HighCol; + + @FXML + protected TableColumn measuredCornerFreqUq1LowCol; + + @FXML + protected TableColumn measuredCornerFreqUq1HighCol; + + @FXML + protected TableColumn measuredCornerFreqUq2LowCol; + + @FXML + protected TableColumn measuredCornerFreqUq2HighCol; + @FXML protected TableColumn iterationsCol; @@ -254,7 +335,7 @@ public abstract class AbstractMeasurementController implements MapListeningContr private final Map> plotPointMap = new HashMap<>(); private final SymbolStyleMapFactory symbolStyleMapFactory; - private Map symbolStyleMap; + private Map symbolStyleMap = new HashMap<>(); private final GeoMap mapImpl; @@ -281,6 +362,9 @@ public abstract class AbstractMeasurementController implements MapListeningContr protected Button yAxisShrink; private boolean shouldYAxisShrink = false; + @FXML + protected Button exportSpectraBtn; + private boolean isVisible = false; protected List spectraControllers = new ArrayList<>(1); @@ -288,15 +372,18 @@ public abstract class AbstractMeasurementController implements MapListeningContr protected final PlotFactory plotFactory; private final EventBus bus; + private ParamExporter paramExporter; + // TODO: Break this up into components so this isn't so incredibly huge. protected AbstractMeasurementController(final SpectraClient spectraClient, final ParameterClient paramClient, final EventClient referenceEventClient, final WaveformClient waveformClient, - final SymbolStyleMapFactory styleFactory, final GeoMap map, final MapPlottingUtilities iconFactory, final PlotFactory plotFactory, final EventBus bus) { + final SymbolStyleMapFactory styleFactory, final GeoMap map, final MapPlottingUtilities iconFactory, final ParamExporter paramExporter, final PlotFactory plotFactory, final EventBus bus) { this.spectraClient = spectraClient; this.paramClient = paramClient; this.referenceEventClient = referenceEventClient; this.waveformClient = waveformClient; this.symbolStyleMapFactory = styleFactory; this.mapImpl = map; + this.paramExporter = paramExporter; this.plotFactory = plotFactory; this.bus = bus; this.iconFactory = iconFactory; @@ -334,6 +421,13 @@ public void initialize() { return shouldYAxisShrink; }, Axis.Type.Y); + final Label label = new Label("\uE2C4"); + label.getStyleClass().add("material-icons-medium"); + label.setMaxHeight(16); + label.setMinWidth(16); + exportSpectraBtn.setGraphic(label); + exportSpectraBtn.setContentDisplay(ContentDisplay.CENTER); + mwPlot = plotFactory.basicPlot(); mwPlot.getTitle().setText("Mw"); mwPlot.getTitle().setFontSize(16); @@ -366,7 +460,7 @@ public void initialize() { energyVsMomentPlot = plotFactory.basicPlot(); energyVsMomentPlot.getTitle().setText("Energy vs Moment"); energyVsMomentPlot.getTitle().setFontSize(16); - energyVsMomentPlot.addAxes(plotFactory.axis(Axis.Type.X, "Total Observed Energy (J)"), plotFactory.axis(Axis.Type.Y, "log10 Mo (N-m)")); + energyVsMomentPlot.addAxes(plotFactory.axis(Axis.Type.X, "Total Observed Energy (log J)"), plotFactory.axis(Axis.Type.Y, "log10 Mo (N-m)")); Axis rightAxis = new BasicAxis(Axis.Type.Y_RIGHT, "Mw"); rightAxis.setTickFormat(TickFormat.LOG10_DYNE_CM_TO_MW); energyVsMomentPlot.addAxes(rightAxis); @@ -409,25 +503,53 @@ public void initialize() { CellBindingUtils.attachTextCellFactories(mwCol, MeasuredMwDetails::getRefMw, dfmt4); CellBindingUtils.attachTextCellFactories(stressCol, MeasuredMwDetails::getRefApparentStressInMpa, dfmt4); - CellBindingUtils.attachTextCellFactories(valMwCol, MeasuredMwDetails::getValMw, dfmt4); CellBindingUtils.attachTextCellFactories(valStressCol, MeasuredMwDetails::getValApparentStressInMpa, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredMwCol, MeasuredMwDetails::getMw, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredMwUq1LowCol, MeasuredMwDetails::getMw1Min, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredMwUq1HighCol, MeasuredMwDetails::getMw1Max, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredMwUq2LowCol, MeasuredMwDetails::getMw2Min, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredMwUq2HighCol, MeasuredMwDetails::getMw2Max, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredMeCol, MeasuredMwDetails::getMe, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredMeUq1LowCol, MeasuredMwDetails::getMw1Min, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredMeUq1HighCol, MeasuredMwDetails::getMw1Max, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredMeUq2LowCol, MeasuredMwDetails::getMw2Min, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredMeUq2HighCol, MeasuredMwDetails::getMw2Max, dfmt4); CellBindingUtils.attachTextCellFactories(obsEnergyCol, MeasuredMwDetails::getObsEnergy, dfmt4); CellBindingUtils.attachTextCellFactories(totalEnergyCol, MeasuredMwDetails::getTotalEnergy, dfmt4); + CellBindingUtils.attachTextCellFactories(totalEnergyUq1LowCol, MeasuredMwDetails::getLogTotalEnergy1Min, dfmt4); + CellBindingUtils.attachTextCellFactories(totalEnergyUq1HighCol, MeasuredMwDetails::getLogTotalEnergy1Max, dfmt4); + CellBindingUtils.attachTextCellFactories(totalEnergyUq2LowCol, MeasuredMwDetails::getLogTotalEnergy2Min, dfmt4); + CellBindingUtils.attachTextCellFactories(totalEnergyUq2HighCol, MeasuredMwDetails::getLogTotalEnergy2Max, dfmt4); + CellBindingUtils.attachTextCellFactories(totalEnergyMDACCol, MeasuredMwDetails::getTotalEnergyMDAC, dfmt4); + CellBindingUtils.attachTextCellFactories(totalEnergyMDACUq1LowCol, MeasuredMwDetails::getLogTotalEnergyMDAC1Min, dfmt4); + CellBindingUtils.attachTextCellFactories(totalEnergyMDACUq1HighCol, MeasuredMwDetails::getLogTotalEnergyMDAC1Max, dfmt4); + CellBindingUtils.attachTextCellFactories(totalEnergyMDACUq2LowCol, MeasuredMwDetails::getLogTotalEnergyMDAC2Min, dfmt4); + CellBindingUtils.attachTextCellFactories(totalEnergyMDACUq2HighCol, MeasuredMwDetails::getLogTotalEnergyMDAC2Max, dfmt4); + CellBindingUtils.attachTextCellFactories(energyRatioCol, MeasuredMwDetails::getEnergyRatio, dfmt4); CellBindingUtils.attachTextCellFactories(energyStressCol, MeasuredMwDetails::getEnergyStress, dfmt4); + CellBindingUtils.attachTextCellFactories(energyStressUq1LowCol, MeasuredMwDetails::getObsAppStress1Min, dfmt4); + CellBindingUtils.attachTextCellFactories(energyStressUq1HighCol, MeasuredMwDetails::getObsAppStress1Max, dfmt4); + CellBindingUtils.attachTextCellFactories(energyStressUq2LowCol, MeasuredMwDetails::getObsAppStress2Min, dfmt4); + CellBindingUtils.attachTextCellFactories(energyStressUq2HighCol, MeasuredMwDetails::getObsAppStress2Max, dfmt4); CellBindingUtils.attachTextCellFactories(measuredStressCol, MeasuredMwDetails::getApparentStressInMpa, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredStressUq1LowCol, MeasuredMwDetails::getApparentStress1Min, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredStressUq1HighCol, MeasuredMwDetails::getApparentStress1Max, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredStressUq2LowCol, MeasuredMwDetails::getApparentStress2Min, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredStressUq2HighCol, MeasuredMwDetails::getApparentStress2Max, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredCornerFreqCol, MeasuredMwDetails::getCornerFreq, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredCornerFreqUq1LowCol, MeasuredMwDetails::getCornerFreq1Min, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredCornerFreqUq1HighCol, MeasuredMwDetails::getCornerFreq1Max, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredCornerFreqUq2LowCol, MeasuredMwDetails::getCornerFreq2Min, dfmt4); + CellBindingUtils.attachTextCellFactories(measuredCornerFreqUq2HighCol, MeasuredMwDetails::getCornerFreq2Max, dfmt4); CellBindingUtils.attachTextCellFactories(mistfitCol, MeasuredMwDetails::getMisfit, dfmt4); - CellBindingUtils.attachTextCellFactories(measuredMwUq1LowCol, MeasuredMwDetails::getMw1Min, dfmt4); - CellBindingUtils.attachTextCellFactories(measuredMwUq1HighCol, MeasuredMwDetails::getMw1Max, dfmt4); - CellBindingUtils.attachTextCellFactories(measuredMwUq2LowCol, MeasuredMwDetails::getMw2Min, dfmt4); - CellBindingUtils.attachTextCellFactories(measuredMwUq2HighCol, MeasuredMwDetails::getMw2Max, dfmt4); CellBindingUtils.attachTextCellFactories(bandCoverageCol, MeasuredMwDetails::getBandCoverage, dfmt4); CellBindingUtils.attachTextCellFactoriesString(likelyPoorlyConstrainedCol, mw -> mw.isLikelyPoorlyConstrained().toString()); @@ -453,14 +575,14 @@ public void initialize() { @Override protected void updateItem(Pair entry, boolean b) { super.updateItem(entry, b); - if (entry != null && entry.getLeft() != null && entry.getLeft().contains("(Model Fit)")) { + if (entry != null && entry.getX() != null && entry.getX().contains("(Model Fit)")) { setStyle("-fx-font-weight:bold;"); } } }); - CellBindingUtils.attachTextCellFactoriesString(summaryNameCol, Pair::getLeft); - CellBindingUtils.attachTextCellFactoriesString(summaryValueCol, Pair::getRight); + CellBindingUtils.attachTextCellFactoriesString(summaryNameCol, Pair::getX); + CellBindingUtils.attachTextCellFactoriesString(summaryValueCol, Pair::getY); summaryNameCol.setCellFactory(param -> new TextWrappingTableCell()); } @@ -523,15 +645,53 @@ private void plotSpectra() { } final Spectra fitSpectra = fittingSpectra.get(0); - summaryValues.add(new Pair<>("Mw (Model Fit)", dfmt2.format(fitSpectra.getMw()))); + summaryValues.add( + new Pair<>("Mw (Model Fit)", + dfmt2.format( + fitSpectra.getMw()) + " [" + dfmt2.format(mwDetails.getMw2Min() - fitSpectra.getMw()) + ", " + dfmt2.format(mwDetails.getMw2Max() - fitSpectra.getMw()) + "]")); if (fitSpectra.getApparentStress() > 0.0) { - summaryValues.add(new Pair<>("Apparent Stress (Model Fit)", dfmt2.format(fitSpectra.getApparentStress()) + " MPa")); + summaryValues.add( + new Pair<>("Apparent Stress (Model Fit)", + dfmt2.format(fitSpectra.getApparentStress()) + + " MPa [" + + dfmt2.format(mwDetails.getApparentStress2Min() - fitSpectra.getApparentStress()) + + ", " + + dfmt2.format(mwDetails.getApparentStress2Max() - fitSpectra.getApparentStress()) + + "]")); } - summaryValues.add(new Pair<>("Energy (Model Fit)", dfmt2.format(fitSpectra.getlogTotalEnergyMDAC()) + " J")); + summaryValues.add( + new Pair<>("Energy (Model Fit)", + dfmt2.format(fitSpectra.getLogTotalEnergyMDAC()) + + " [" + + dfmt2.format(mwDetails.getLogTotalEnergyMDAC2Min() - fitSpectra.getLogTotalEnergyMDAC()) + + ", " + + dfmt2.format(mwDetails.getLogTotalEnergyMDAC2Max() - fitSpectra.getLogTotalEnergyMDAC()) + + "] log J")); + + summaryValues.add( + new Pair<>("Total Energy", + dfmt2.format(fitSpectra.getLogTotalEnergy()) + + " [" + + dfmt2.format(mwDetails.getLogTotalEnergy2Min() - fitSpectra.getLogTotalEnergy()) + + ", " + + dfmt2.format(mwDetails.getLogTotalEnergy2Max() - fitSpectra.getLogTotalEnergy()) + + "] log J")); + + summaryValues.add( + new Pair<>("Me (Total Energy)", + dfmt2.format( + mwDetails.getMe()) + " [" + dfmt2.format(mwDetails.getMe2Min() - mwDetails.getMe()) + ", " + dfmt2.format(mwDetails.getMe2Max() - mwDetails.getMe()) + "]")); + + summaryValues.add( + new Pair<>("Observed Apparent Stress", + dfmt2.format(fitSpectra.getObsAppStress()) + + " MPa [" + + dfmt2.format(mwDetails.getObsAppStress2Min() - fitSpectra.getObsAppStress()) + + ", " + + dfmt2.format(mwDetails.getObsAppStress2Max() - fitSpectra.getObsAppStress()) + + "]")); - summaryValues.add(new Pair<>("Observed Total Energy", dfmt2.format(fitSpectra.getLogTotalEnergy()) + " J")); - summaryValues.add(new Pair<>("Observed Apparent Stress", dfmt2.format(fitSpectra.getObsAppStress()) + " MPa")); summaryValues.add(new Pair<>("Observed / Total Energy", dfmt2.format(100.0 * (Math.pow(10, fitSpectra.getObsEnergy()) / Math.pow(10, fitSpectra.getLogTotalEnergy()))) + " %")); summaryValues.add( new Pair<>("Extrapolated / Total Energy", dfmt2.format(100.0 - (100.0 * (Math.pow(10, fitSpectra.getObsEnergy()) / Math.pow(10, fitSpectra.getLogTotalEnergy())))) + " %")); @@ -871,7 +1031,9 @@ protected void reloadData() { energyVsMomentPlot.replot(); }); - symbolStyleMap = symbolStyleMapFactory.build(spectralMeasurements, specMeas -> specMeas.getWaveform().getStream().getStation().getStationName()); + //Wastes a little compute but KISS + Map styleMap = symbolStyleMapFactory.build(spectralMeasurements, specMeas -> specMeas.getWaveform().getStream().getStation().getStationName()); + styleMap.entrySet().forEach(e -> symbolStyleMap.putIfAbsent(e.getKey(), e.getValue())); runGuiUpdate(() -> { stationSymbols.clear(); @@ -993,6 +1155,57 @@ public Runnable getRefreshFunction() { return this::reloadData; } + public void exportSpectra() { + Platform.runLater(() -> { + if (evidCombo.getValue() != null) { + final File file = FileDialogs.openFileSaveDialog(evidCombo.getValue(), "-Spectra.json", spectraPlotPanel.getScene().getWindow()); + if (file != null && FileDialogs.ensureFileIsWritable(file)) { + final String filePath = file.getAbsolutePath(); + List formattedExportValues = getFormattedValues(evidCombo.getValue(), spectralMeasurements); + paramExporter.writeSpectra(Paths.get(FilenameUtils.getFullPath(filePath)), FilenameUtils.getName(filePath), formattedExportValues); + } + } + }); + } + + private List getFormattedValues(String eventId, List measurements) { + Map valuesMap = new HashMap<>(); + if (eventId != null && measurements != null) { + List filteredMeasurements = measurements; + if (!eventId.equalsIgnoreCase("All")) { + filteredMeasurements = filterToEvent(eventId, measurements); + } + Map> averageValues = new HashMap<>(); + for (SpectraMeasurement meas : filteredMeasurements) { + String key = meas.getWaveform().getEvent().getEventId() + + "-" + + meas.getWaveform().getStream().getStation().getNetworkName() + + "-" + + meas.getWaveform().getStream().getStation().getStationName(); + valuesMap.computeIfAbsent( + key, + k -> new EventSpectraReport(meas.getWaveform().getEvent().getEventId(), + meas.getWaveform().getStream().getStation().getNetworkName(), + meas.getWaveform().getStream().getStation().getStationName(), + new ArrayList<>())); + + Double freq = centerFreq(meas.getWaveform()); + valuesMap.get(key).add(new Pair<>(freq, meas.getPathAndSiteCorrected())); + averageValues.computeIfAbsent(meas.getWaveform().getEvent().getEventId(), k -> new TreeMap<>()).merge(freq, meas.getPathAndSiteCorrected(), (l, r) -> (l + r) / 2.0); + } + + for (Entry> average : averageValues.entrySet()) { + valuesMap.put( + "Average-" + average.getKey(), + new EventSpectraReport(average.getKey(), + null, + "Average", + average.getValue().entrySet().stream().map(e -> new Pair<>(e.getKey(), e.getValue())).collect(Collectors.toList()))); + } + } + return new ArrayList<>(valuesMap.values()); + } + @Override public Consumer getScreenshotFunction() { return folder -> { 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 1491d690..56b4b206 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 @@ -66,6 +66,7 @@ import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn.CellDataFeatures; import javafx.scene.control.TableView; +import javafx.scene.control.ToggleGroup; import javafx.scene.input.MouseButton; import javafx.scene.input.MouseEvent; @@ -282,13 +283,13 @@ public void initialize() { //The filter controller will manage the list so don't add the listData directly //to the table, otherwise the event handlers will trip over themselves DataFilterController filterController = new DataFilterController<>(tableView, listData); - - filterController.addFilterToColumn(eventCol, (data, item) -> data.getEvent().getEventId().equals(item)); - filterController.addFilterToColumn(depthCol, (data, item) -> dfmt2.format(data.getEvent().getDepth()).equals(item)); - filterController.addFilterToColumn(lowFreqCol, (data, item) -> data.getLowFrequency().toString().equals(item)); - filterController.addFilterToColumn(highFreqCol, (data, item) -> data.getHighFrequency().toString().equals(item)); - filterController.addFilterToColumn(stationCol, (data, item) -> data.getStream().getStation().getStationName().equals(item)); - filterController.addFilterToColumn(networkCol, (data, item) -> data.getStream().getStation().getNetworkName().equals(item)); + ToggleGroup freqFieldsToggle = new ToggleGroup(); //The toggle group will prevent freqFields from both being active during the 'And' filter. + filterController.addFilterToColumn(false, null, eventCol, (data, value) -> data.getEvent().getEventId().equals(value)); + filterController.addFilterToColumn(false, null, depthCol, (data, value) -> dfmt2.format(data.getEvent().getDepth()).equals(value)); + filterController.addFilterToColumn(true, freqFieldsToggle, lowFreqCol, (data, value) -> data.getLowFrequency().toString().equals(value)); + filterController.addFilterToColumn(true, freqFieldsToggle, highFreqCol, (data, value) -> data.getHighFrequency().toString().equals(value)); + filterController.addFilterToColumn(false, null, stationCol, (data, value) -> data.getStream().getStation().getStationName().equals(value)); + filterController.addFilterToColumn(false, null, networkCol, (data, value) -> data.getStream().getStation().getNetworkName().equals(value)); } @Override diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/DataFilterController.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/DataFilterController.java index 6102c21e..47a1afa9 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/DataFilterController.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/DataFilterController.java @@ -19,6 +19,7 @@ import java.util.List; import java.util.function.Predicate; +import javafx.beans.value.ChangeListener; import javafx.collections.FXCollections; import javafx.collections.ListChangeListener; import javafx.collections.ListChangeListener.Change; @@ -30,6 +31,7 @@ import javafx.scene.control.Label; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; +import javafx.scene.control.ToggleGroup; class DataFilterController { // The list of unfiltered table items @@ -39,12 +41,14 @@ class DataFilterController { // The filter buttons attached to columns private List